diff --git a/.gitattributes b/.gitattributes index c9e0d8c607a..9461903e124 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ *.fits -text +astropy/io/fits/tiled_compression/tests/data/*fits binary diff --git a/.github/workflows/ci_workflows.yml b/.github/workflows/ci_workflows.yml index 1c6ef24c2a7..985bcf74f69 100644 --- a/.github/workflows/ci_workflows.yml +++ b/.github/workflows/ci_workflows.yml @@ -45,7 +45,7 @@ jobs: } tests: - needs: [initial_checks] + # needs: [initial_checks] uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1 with: submodules: false @@ -65,7 +65,12 @@ jobs: # leave open any files. This has a performance impact on running the # tests, hence why it is not enabled by default. - name: Python 3.9 with all optional dependencies - linux: py39-test-alldeps + linux: py39-test-alldeps-fitsio + libraries: + apt: + - language-pack-fr + - tzdata + - libcfitsio-dev toxargs: -v --develop posargs: --open-files --run-slow @@ -82,7 +87,7 @@ jobs: posargs: --durations=50 --run-slow allowed_failures: - needs: [initial_checks] + # needs: [initial_checks] uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1 with: submodules: false @@ -101,7 +106,7 @@ jobs: parallel_and_32bit: name: 32-bit and parallel runs-on: ubuntu-latest - needs: [initial_checks] + # needs: [initial_checks] container: image: quay.io/pypa/manylinux2014_i686:2022-04-03-da6ecb3 steps: diff --git a/astropy/io/fits/hdu/compressed.py b/astropy/io/fits/hdu/compressed.py index 2e10cfa5ae5..debc15fd271 100644 --- a/astropy/io/fits/hdu/compressed.py +++ b/astropy/io/fits/hdu/compressed.py @@ -17,6 +17,7 @@ from astropy.io.fits.column import TDEF_RE, ColDefs, Column from astropy.io.fits.fitsrec import FITS_rec from astropy.io.fits.header import Header +from astropy.io.fits.tiled_compression import compress_hdu, decompress_hdu from astropy.io.fits.util import ( _get_array_mmap, _is_int, @@ -30,13 +31,7 @@ from .image import ImageHDU from .table import BinTableHDU -try: - from astropy.io.fits import compression - - COMPRESSION_SUPPORTED = COMPRESSION_ENABLED = True -except ImportError: - COMPRESSION_SUPPORTED = COMPRESSION_ENABLED = False - +COMPRESSION_ENABLED = True # Quantization dithering method constants; these are right out of fitsio.h NO_DITHER = -1 @@ -642,14 +637,6 @@ def __init__( same image will always use the same seed. """ - if not COMPRESSION_SUPPORTED: - # TODO: Raise a more specific Exception type - raise Exception( - "The astropy.io.fits.compression module is not " - "available. Creation of compressed image HDUs is " - "disabled." - ) - compression_type = CMTYPE_ALIASES.get(compression_type, compression_type) if data is DELAYED: @@ -764,16 +751,8 @@ def match_header(cls, header): if "ZIMAGE" not in header or not header["ZIMAGE"]: return False - if COMPRESSION_SUPPORTED and COMPRESSION_ENABLED: + if COMPRESSION_ENABLED: return True - elif not COMPRESSION_SUPPORTED: - warnings.warn( - "Failure matching header to a compressed image " - "HDU: The compression module is not available.\n" - "The HDU will be treated as a Binary Table HDU.", - AstropyUserWarning, - ) - return False else: # Compression is supported but disabled; just pass silently (#92) return False @@ -1068,10 +1047,26 @@ def _update_header_data( # Set default tile dimensions for HCOMPRESS_1 if compression_type == "HCOMPRESS_1": - if self._image_header["NAXIS1"] < 4 or self._image_header["NAXIS2"] < 4: + + # HCOMPRESS_1 allows >2D tiles provided only two dimensions have + # non-1 values. We store the indices of those dimensions to use + # below. + keep_dims = [] + for i in range(len(tile_size)): + if tile_size[i] > 1: + keep_dims.append(i) + + if ( + self._image_header[f"NAXIS{keep_dims[0] + 1}"] < 4 + or self._image_header[f"NAXIS{keep_dims[1] + 1}"] < 4 + ): raise ValueError("Hcompress minimum image dimension is 4 pixels") elif tile_size: - if tile_size[0] < 4 or tile_size[1] < 4: + if len(keep_dims) != 2: + raise ValueError( + "Hcompress tile size should contain exactly two non-1 values" + ) + if tile_size[keep_dims[0]] < 4 or tile_size[keep_dims[1]] < 4: # user specified tile size is too small raise ValueError("Hcompress minimum tile dimension is 4 pixels") major_dims = len([ts for ts in tile_size if ts > 1]) @@ -1082,6 +1077,10 @@ def _update_header_data( "to 1." ) + # TODO: is '0' a magic value that means all pixels along a certain + # dimension? If so we should perhaps check not the first two but + # the two dimensions that are not 1. + if tile_size and (tile_size[0] == 0 and tile_size[1] == 0): # compress the whole image as a single tile tile_size[0] = self._image_header["NAXIS1"] @@ -1125,24 +1124,33 @@ def _update_header_data( # check if requested tile size causes the last tile to have # less than 4 pixels - remain = self._image_header["NAXIS1"] % tile_size[0] # 1st dimen + remain = ( + self._image_header[f"NAXIS{keep_dims[0] + 1}"] % tile_size[keep_dims[0]] + ) # 1st dimen if remain > 0 and remain < 4: - tile_size[0] += 1 # try increasing tile size by 1 - - remain = self._image_header["NAXIS1"] % tile_size[0] + tile_size[keep_dims[0]] += 1 # try increasing tile size by 1 + remain = ( + self._image_header[f"NAXIS{keep_dims[0] + 1}"] + % tile_size[keep_dims[0]] + ) if remain > 0 and remain < 4: raise ValueError( "Last tile along 1st dimension has less than 4 pixels" ) - remain = self._image_header["NAXIS2"] % tile_size[1] # 2nd dimen + remain = ( + self._image_header[f"NAXIS{keep_dims[1] + 1}"] % tile_size[keep_dims[1]] + ) # 2nd dimen if remain > 0 and remain < 4: - tile_size[1] += 1 # try increasing tile size by 1 + tile_size[keep_dims[1]] += 1 # try increasing tile size by 1 - remain = self._image_header["NAXIS2"] % tile_size[1] + remain = ( + self._image_header[f"NAXIS{keep_dims[1] + 1}"] + % tile_size[keep_dims[1]] + ) if remain > 0 and remain < 4: raise ValueError( @@ -1495,7 +1503,7 @@ def _update_header_data( @lazyproperty def data(self): # The data attribute is the image data (not the table data). - data = compression.decompress_hdu(self) + data = decompress_hdu(self) if data is None: return data @@ -1505,6 +1513,11 @@ def data(self): new_dtype = self._dtype_for_bitpix() data = np.array(data, dtype=new_dtype) + # TODO: ZBLANK should not be dealt with here as it should apply + # to data before being unquantized, which has already happened in + # decompress_hdu, so we should remove references to ZBLANK here. + # However, it might be that we still need to handle BLANK. + zblank = None if "ZBLANK" in self.compressed_data.columns.names: @@ -1802,17 +1815,6 @@ def _update_compressed_data(self): self.data - _pseudo_zero(self.data.dtype), dtype=f"=i{self.data.dtype.itemsize}", ) - should_swap = False - else: - should_swap = not self.data.dtype.isnative - - if should_swap: - if self.data.flags.writeable: - self.data.byteswap(True) - else: - # For read-only arrays, there is no way around making - # a byteswapped copy of the data. - self.data = self.data.byteswap(False) try: nrows = self._header["NAXIS2"] @@ -1836,11 +1838,8 @@ def _update_compressed_data(self): # self.compressed_data, and writes directly to it # compress_hdu returns the size of the heap for the written # compressed image table - heapsize, self.compressed_data = compression.compress_hdu(self) + heapsize, self.compressed_data = compress_hdu(self) finally: - # if data was byteswapped return it to its original order - if should_swap: - self.data.byteswap(True) self.data = old_data # CFITSIO will write the compressed data in big-endian order diff --git a/astropy/io/fits/setup_package.py b/astropy/io/fits/setup_package.py deleted file mode 100644 index 494fdd1f4c2..00000000000 --- a/astropy/io/fits/setup_package.py +++ /dev/null @@ -1,82 +0,0 @@ -# Licensed under a 3-clause BSD style license - see PYFITS.rst - -import os -import sys -from collections import defaultdict -from glob import glob - -import numpy -from setuptools import Extension - -from extension_helpers import get_compiler, pkg_config - - -def _get_compression_extension(): - debug = "--debug" in sys.argv - - cfg = defaultdict(list) - cfg["include_dirs"].append(numpy.get_include()) - cfg["sources"].append( - os.path.join(os.path.dirname(__file__), "src", "compressionmodule.c") - ) - - if int(os.environ.get("ASTROPY_USE_SYSTEM_CFITSIO", 0)) or int( - os.environ.get("ASTROPY_USE_SYSTEM_ALL", 0) - ): - for k, v in pkg_config(["cfitsio"], ["cfitsio"]).items(): - cfg[k].extend(v) - else: - if get_compiler() == "msvc": - # These come from the CFITSIO vcc makefile, except the last - # which ensures on windows we do not include unistd.h (in regular - # compilation of cfitsio, an empty file would be generated) - cfg["extra_compile_args"].extend( - [ - "/D", - "WIN32", - "/D", - "_WINDOWS", - "/D", - "_MBCS", - "/D", - "_USRDLL", - "/D", - "_CRT_SECURE_NO_DEPRECATE", - "/D", - "YY_NO_UNISTD_H", - ] - ) - else: - cfg["extra_compile_args"].extend(["-Wno-declaration-after-statement"]) - - cfg["define_macros"].append(("HAVE_UNISTD_H", None)) - - if not debug: - # these switches are to silence warnings from compiling CFITSIO - # For full silencing, some are added that only are used in - # later versions of gcc (versions approximate; see #6474) - cfg["extra_compile_args"].extend( - [ - "-Wno-strict-prototypes", - "-Wno-unused", - "-Wno-uninitialized", - "-Wno-unused-result", # gcc >~4.8 - "-Wno-misleading-indentation", # gcc >~7.2 - "-Wno-format-overflow", # gcc >~7.2 - ] - ) - - cfitsio_lib_path = os.path.join("cextern", "cfitsio", "lib") - cfitsio_zlib_path = os.path.join("cextern", "cfitsio", "zlib") - cfitsio_files = glob(os.path.join(cfitsio_lib_path, "*.c")) - cfitsio_zlib_files = glob(os.path.join(cfitsio_zlib_path, "*.c")) - cfg["include_dirs"].append(cfitsio_lib_path) - cfg["include_dirs"].append(cfitsio_zlib_path) - cfg["sources"].extend(cfitsio_files) - cfg["sources"].extend(cfitsio_zlib_files) - - return Extension("astropy.io.fits.compression", **cfg) - - -def get_extensions(): - return [_get_compression_extension()] diff --git a/astropy/io/fits/src/compressionmodule.c b/astropy/io/fits/src/compressionmodule.c deleted file mode 100644 index b8bfc399722..00000000000 --- a/astropy/io/fits/src/compressionmodule.c +++ /dev/null @@ -1,1308 +0,0 @@ -/* "compression module */ - -/*****************************************************************************/ -/* */ -/* The compression software is a python module implemented in C that, when */ -/* accessed through the astropy module, supports the storage of compressed */ -/* images in FITS binary tables. An n-dimensional image is divided 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. */ -/* 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. */ -/* */ -/* This module contains three functions that are callable from python. The */ -/* first is compress_hdu. This function takes an */ -/* astropy.io.fits.CompImageHDU object containing the uncompressed image */ -/* data and returns the compressed data for all tiles into the */ -/* .compressed_data attribute of that HDU. */ -/* */ -/* The second function is decompress_hdu. It takes an */ -/* astropy.io.fits.CompImageHDU object that already has compressed data in */ -/* its .compressed_data attribute. It returns the decompressed image data */ -/* into the HDU's .data attribute. */ -/* */ -/* Copyright (C) 2013 Association of Universities for Research in Astronomy */ -/* (AURA) */ -/* */ -/* Redistribution and use in source and binary forms, with or without */ -/* modification, are permitted provided that the following conditions are */ -/* met: */ -/* */ -/* 1. Redistributions of source code must retain the above copyright */ -/* notice, this list of conditions and the following disclaimer. */ -/* */ -/* 2. Redistributions in binary form must reproduce the above */ -/* copyright notice, this list of conditions and the following */ -/* disclaimer in the documentation and/or other materials provided */ -/* with the distribution. */ -/* */ -/* 3. The name of AURA and its representatives may not be used to */ -/* endorse or promote products derived from this software without */ -/* specific prior written permission. */ -/* */ -/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED */ -/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ -/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ -/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, */ -/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ -/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS */ -/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND */ -/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR */ -/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE */ -/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH */ -/* DAMAGE. */ -/* */ -/* Some of the source code used by this module was copied and modified from */ -/* the FITSIO software that was written by William Pence at the High Energy */ -/* Astrophysic Science Archive Research Center (HEASARC) at the NASA Goddard */ -/* Space Flight Center. That software contained the following copyright and */ -/* warranty notices: */ -/* */ -/* 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 the Python C API */ - -#include -#include -#include -#include - -#include -#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -#include -#include -#include "compressionmodule.h" - - -/* These defaults mirror the defaults in astropy.io.fits.hdu.compressed */ -#define DEFAULT_COMPRESSION_TYPE "RICE_1" -#define DEFAULT_QUANTIZE_LEVEL 16.0 -#define DEFAULT_HCOMP_SCALE 0 -#define DEFAULT_HCOMP_SMOOTH 0 -#define DEFAULT_BLOCK_SIZE 32 -#define DEFAULT_BYTE_PIX 4 - -/* Flags to pass to get_header_* functions to control error messages. */ -typedef enum { - HDR_NOFLAG = 0, - HDR_FAIL_KEY_MISSING = 1 << 0, - HDR_FAIL_VAL_NEGATIVE = 1 << 1, -} HeaderGetFlags; - - -/* Report any error based on the status returned from cfitsio. */ -void process_status_err(int status) -{ - PyObject* except_type; - char err_msg[81]; - char def_err_msg[81]; - - err_msg[0] = '\0'; - def_err_msg[0] = '\0'; - - switch (status) { - case MEMORY_ALLOCATION: - except_type = PyExc_MemoryError; - break; - case OVERFLOW_ERR: - except_type = PyExc_OverflowError; - break; - case BAD_COL_NUM: - strcpy(def_err_msg, "bad column number"); - except_type = PyExc_ValueError; - break; - case BAD_PIX_NUM: - strcpy(def_err_msg, "bad pixel number"); - except_type = PyExc_ValueError; - break; - case NEG_AXIS: - strcpy(def_err_msg, "negative axis number"); - except_type = PyExc_ValueError; - break; - case BAD_DATATYPE: - strcpy(def_err_msg, "bad data type"); - except_type = PyExc_TypeError; - break; - case NO_COMPRESSED_TILE: - strcpy(def_err_msg, "no compressed or uncompressed data for tile."); - except_type = PyExc_ValueError; - break; - default: - except_type = PyExc_RuntimeError; - break; - } - - if (fits_read_errmsg(err_msg)) { - PyErr_SetString(except_type, err_msg); - } else if (*def_err_msg) { - PyErr_SetString(except_type, def_err_msg); - } else { - PyErr_Format(except_type, "unknown error %i.", status); - } -} - - -void bitpix_to_datatypes(int bitpix, int* datatype, int* npdatatype) { - /* Given a FITS BITPIX value, returns the appropriate CFITSIO type code and - Numpy type code for that BITPIX into datatype and npdatatype - respectively. - */ - switch (bitpix) { - case BYTE_IMG: - *datatype = TBYTE; - *npdatatype = NPY_UINT8; - break; - case SHORT_IMG: - *datatype = TSHORT; - *npdatatype = NPY_INT16; - break; - case LONG_IMG: - *datatype = TINT; - *npdatatype = NPY_INT32; - break; - case LONGLONG_IMG: - *datatype = TLONGLONG; - *npdatatype = NPY_LONGLONG; - break; - case FLOAT_IMG: - *datatype = TFLOAT; - *npdatatype = NPY_FLOAT; - break; - case DOUBLE_IMG: - *datatype = TDOUBLE; - *npdatatype = NPY_DOUBLE; - break; - default: - PyErr_Format(PyExc_ValueError, "Invalid value for BITPIX: %d", - bitpix); - break; - } - - return; -} - - - -int compress_type_from_string(char* zcmptype) { - if (0 == strcmp(zcmptype, "RICE_1")) { - return RICE_1; - } else if (0 == strcmp(zcmptype, "GZIP_1")) { - return GZIP_1; - } else if (0 == strcmp(zcmptype, "GZIP_2")) { - return GZIP_2; - } else if (0 == strcmp(zcmptype, "PLIO_1")) { - return PLIO_1; - } else if (0 == strcmp(zcmptype, "HCOMPRESS_1")) { - return HCOMPRESS_1; - } - /* CFITSIO adds a compression type alias for RICE_1 compression - as a flag for using subtractive_dither_2 */ - else if (0 == strcmp(zcmptype, "RICE_ONE")) { - return RICE_1; - } - else { - PyErr_Format(PyExc_ValueError, "Unrecognized compression type: %s", - zcmptype); - return -1; - } -} - - -PyObject * -get_header_value(PyObject* header, const char* key, HeaderGetFlags flags) { - PyObject* hdrkey; - PyObject* hdrval; - hdrkey = PyUnicode_FromString(key); - if (hdrkey == NULL) { - return NULL; - } - hdrval = PyObject_GetItem(header, hdrkey); - Py_DECREF(hdrkey); - if ((flags & HDR_FAIL_KEY_MISSING) == 0) { - /* Normally we have a default so we want to ignore the exception in - any case. But if the flag was given this step must be skipped. */ - PyErr_Clear(); - } - return hdrval; -} - - -// TODO: It might be possible to simplify these further by making the -// conversion function (eg. PyString_AsString) an argument to a macro or -// something, but I'm not sure yet how easy it is to generalize the error -// handling -/* The get_header_* functions resemble "Header.get" where "def" is the default - value, "keyword" is a string representing the header-key and the result is - stored in "val". - The function returns 0 on success, 1 if the header didn't have the keyword - and the default was applied and -1 (with an exception set) if an Exception - happened (like a MemoryError or Overflow). -*/ -#define GET_HEADER_SUCCESS 0 -#define GET_HEADER_DEFAULT_USED 1 -#define GET_HEADER_FAILED -1 -int get_header_string(PyObject* header, const char* keyword, char* val, - const char* def, HeaderGetFlags flags) { - /* nonnegative doesn't make sense for strings*/ - assert(!(flags & HDR_FAIL_VAL_NEGATIVE)); - PyObject* keyval = get_header_value(header, keyword, flags); - - if (keyval == NULL) { - strncpy(val, def, 72); - return PyErr_Occurred() ? GET_HEADER_FAILED : GET_HEADER_DEFAULT_USED; - } - PyObject* tmp = PyUnicode_AsLatin1String(keyval); - // FITS header values should always be ASCII, but Latin1 is on the - // safe side - Py_DECREF(keyval); - if (tmp == NULL) { - /* could always fail to allocate the memory or such like. */ - return GET_HEADER_FAILED; - } - strncpy(val, PyBytes_AsString(tmp), 72); - Py_DECREF(tmp); - return GET_HEADER_SUCCESS; -} - - -int get_header_long(PyObject* header, const char* keyword, long* val, long def, - HeaderGetFlags flags) { - PyObject* keyval = get_header_value(header, keyword, flags); - - if (keyval == NULL) { - *val = def; - return PyErr_Occurred() ? GET_HEADER_FAILED : GET_HEADER_DEFAULT_USED; - } - long tmp = PyLong_AsLong(keyval); - Py_DECREF(keyval); - if (PyErr_Occurred()) { - return GET_HEADER_FAILED; - } - if ((flags & HDR_FAIL_VAL_NEGATIVE) && (tmp < 0)) { - PyErr_Format(PyExc_ValueError, "%s should not be negative.", keyword); - return GET_HEADER_FAILED; - } - *val = tmp; - return GET_HEADER_SUCCESS; -} - - -int get_header_int(PyObject* header, const char* keyword, int* val, int def, - HeaderGetFlags flags) { - long tmp; - int ret = get_header_long(header, keyword, &tmp, def, flags); - if (ret == GET_HEADER_SUCCESS) { - if (tmp >= INT_MIN && tmp <= INT_MAX) { - *val = (int) tmp; - } else { - PyErr_Format(PyExc_OverflowError, "Cannot convert %ld to C 'int'", tmp); - ret = GET_HEADER_FAILED; - } - } - return ret; -} - - -int get_header_double(PyObject* header, const char* keyword, double* val, - double def, HeaderGetFlags flags) { - /* nonnegative isn't currently used for doubles/floats. But if needed one - could simply remove the assert again and implement the negative check. */ - assert(!(flags & HDR_FAIL_VAL_NEGATIVE)); - PyObject* keyval = get_header_value(header, keyword, flags); - - if (keyval == NULL) { - *val = def; - return PyErr_Occurred() ? GET_HEADER_FAILED : GET_HEADER_DEFAULT_USED; - } - double tmp = PyFloat_AsDouble(keyval); - Py_DECREF(keyval); - if (PyErr_Occurred()) { - return GET_HEADER_FAILED; - } - *val = tmp; - return GET_HEADER_SUCCESS; -} - - -int get_header_float(PyObject* header, const char* keyword, float* val, - float def, HeaderGetFlags flags) { - double tmp; - int ret = get_header_double(header, keyword, &tmp, def, flags); - if (ret == GET_HEADER_SUCCESS) { - if (tmp == 0.0 || (fabs(tmp) >= FLT_MIN && fabs(tmp) <= FLT_MAX)) { - *val = (float) tmp; - } else { - PyErr_SetString(PyExc_OverflowError, - "Cannot convert 'double' to 'float'"); - ret = GET_HEADER_FAILED; - } - } - return ret; -} - - -int get_header_longlong(PyObject* header, const char* keyword, long long* val, - long long def, HeaderGetFlags flags) { - PyObject* keyval = get_header_value(header, keyword, flags); - - if (keyval == NULL) { - *val = def; - return PyErr_Occurred() ? GET_HEADER_FAILED : GET_HEADER_DEFAULT_USED; - } - long long tmp = PyLong_AsLongLong(keyval); - Py_DECREF(keyval); - if (PyErr_Occurred()) { - return GET_HEADER_FAILED; - } - if ((flags & HDR_FAIL_VAL_NEGATIVE) && (tmp < 0)) { - PyErr_Format(PyExc_ValueError, "%s should not be negative.", keyword); - return GET_HEADER_FAILED; - } - *val = tmp; - return GET_HEADER_SUCCESS; -} - - -void tcolumns_from_header(fitsfile* fileptr, PyObject* header, - tcolumn** columns) { - // Creates the array of tcolumn structures from the table column keywords - // read from the astropy.io.fits.Header object; caller is responsible for - // freeing the memory allocated for this array - - tcolumn* column; - char tkw[9]; - - int tfields; - char ttype[72]; - char tform[72]; - int dtcode; - long trepeat; - long twidth; - long long totalwidth; - int status = 0; - int idx; - - if (get_header_int(header, "TFIELDS", &tfields, 0, HDR_FAIL_VAL_NEGATIVE) == GET_HEADER_FAILED) { - return; - } - /* To avoid issues in the loop we need to limit the number of TFIELDs to - 999. Otherwise we would exceed the maximum length of the keyword name of - 8. This could lead to multiple accesses of the same header keyword with - snprintf because we limit it to 8 characters + null-termination. */ - if (tfields > 999) { - PyErr_SetString(PyExc_ValueError, "The TFIELDS value exceeds 999."); - return; - } - - // This used to use PyMem_New, but don't do that; CFITSIO will later - // free() this object when the file is closed, so just use malloc here - // *columns = column = PyMem_New(tcolumn, (size_t) tfields); - *columns = column = calloc((size_t) tfields, sizeof(tcolumn)); - if (column == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Couldn't allocate memory for columns."); - return; - } - - - for (idx = 1; idx <= tfields; idx++, column++) { - /* set some invalid defaults */ - column->ttype[0] = '\0'; - column->tbcol = 0; - column->tdatatype = -9999; /* this default used by cfitsio */ - column->trepeat = 1; - column->strnull[0] = '\0'; - column->tform[0] = '\0'; - column->twidth = 0; - - snprintf(tkw, 9, "TTYPE%u", idx); - if (get_header_string(header, tkw, ttype, "", HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - strncpy(column->ttype, ttype, 69); - column->ttype[69] = '\0'; - - snprintf(tkw, 9, "TFORM%u", idx); - if (get_header_string(header, tkw, tform, "", HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - strncpy(column->tform, tform, 9); - column->tform[9] = '\0'; - fits_binary_tform(tform, &dtcode, &trepeat, &twidth, &status); - if (status != 0) { - process_status_err(status); - return; - } - - column->tdatatype = dtcode; - column->trepeat = trepeat; - column->twidth = twidth; - - snprintf(tkw, 9, "TSCAL%u", idx); - if (get_header_double(header, tkw, &(column->tscale), 1.0, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - - snprintf(tkw, 9, "TZERO%u", idx); - if (get_header_double(header, tkw, &(column->tzero), 0.0, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - - snprintf(tkw, 9, "TNULL%u", idx); - if (get_header_longlong(header, tkw, &(column->tnull), NULL_UNDEFINED, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - } - - fileptr->Fptr->tableptr = *columns; - fileptr->Fptr->tfield = tfields; - - // This routine from CFITSIO calculates the byte offset of each column - // and stores it in the column->tbcol field - ffgtbc(fileptr, &totalwidth, &status); - if (status != 0) { - process_status_err(status); - } - - return; -} - - - -void configure_compression(fitsfile* fileptr, PyObject* header) { - /* Configure the compression-related elements in the fitsfile struct - using values in the FITS header. */ - - FITSfile* Fptr; - - int tfields; - tcolumn* columns; - - char keyword[9]; - char zname[72]; - int znaxis; - char tmp[72]; - float version; - - int idx; - - Fptr = fileptr->Fptr; - tfields = Fptr->tfield; - columns = Fptr->tableptr; - - int tmp_retval; - - // Get the ZBITPIX header value; if this is missing we're in trouble - if (get_header_int(header, "ZBITPIX", &(Fptr->zbitpix), 0, HDR_FAIL_KEY_MISSING) != GET_HEADER_SUCCESS) { - return; - } - - // By default assume there is no ZBLANK column and check for ZBLANK or - // BLANK in the header - Fptr->cn_zblank = Fptr->cn_zzero = Fptr->cn_zscale = -1; - Fptr->cn_uncompressed = 0; - Fptr->cn_gzip_data = 0; - - // Check for a ZBLANK, ZZERO, ZSCALE, and - // UNCOMPRESSED_DATA/GZIP_COMPRESSED_DATA columns in the compressed data - // table - for (idx = 0; idx < tfields; idx++) { - if (0 == strncmp(columns[idx].ttype, "UNCOMPRESSED_DATA", 18)) { - Fptr->cn_uncompressed = idx + 1; - } else if (0 == strncmp(columns[idx].ttype, - "GZIP_COMPRESSED_DATA", 21)) { - Fptr->cn_gzip_data = idx + 1; - } else if (0 == strncmp(columns[idx].ttype, "ZSCALE", 7)) { - Fptr->cn_zscale = idx + 1; - } else if (0 == strncmp(columns[idx].ttype, "ZZERO", 6)) { - Fptr->cn_zzero = idx + 1; - } else if (0 == strncmp(columns[idx].ttype, "ZBLANK", 7)) { - Fptr->cn_zblank = idx + 1; - } - } - - Fptr->zblank = 0; - if (Fptr->cn_zblank < 1) { - // No ZBLANK column--check the ZBLANK and BLANK heard keywords - switch (get_header_int(header, "ZBLANK", &(Fptr->zblank), 0, HDR_NOFLAG)) { - case GET_HEADER_FAILED: - return; - case GET_HEADER_DEFAULT_USED: - // ZBLANK keyword not found - if (get_header_int(header, "BLANK", &(Fptr->zblank), 0, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - break; - default: - break; - } - } - - Fptr->zscale = 1.0; - if (Fptr->cn_zscale < 1) { - switch (get_header_double(header, "ZSCALE", &(Fptr->zscale), 1.0, HDR_NOFLAG)) { - case GET_HEADER_FAILED: - return; - case GET_HEADER_DEFAULT_USED: - Fptr->cn_zscale = 0; - break; - default: - break; - } - } - Fptr->cn_bscale = Fptr->zscale; - - Fptr->zzero = 0.0; - if (Fptr->cn_zzero < 1) { - switch (get_header_double(header, "ZZERO", &(Fptr->zzero), 0.0, HDR_NOFLAG)) { - case GET_HEADER_FAILED: - return; - case GET_HEADER_DEFAULT_USED: - Fptr->cn_zzero = 0; - break; - default: - break; - } - } - Fptr->cn_bzero = Fptr->zzero; - - if (get_header_string(header, "ZCMPTYPE", tmp, DEFAULT_COMPRESSION_TYPE, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - strncpy(Fptr->zcmptype, tmp, 11); - Fptr->zcmptype[strlen(tmp)] = '\0'; - - Fptr->compress_type = compress_type_from_string(Fptr->zcmptype); - if (PyErr_Occurred()) { - return; - } - - if (get_header_int(header, "ZNAXIS", &znaxis, 0, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - Fptr->zndim = znaxis; - - if (znaxis > MAX_COMPRESS_DIM) { - // The CFITSIO compression code currently only supports up to 6 - // dimensions by default. - znaxis = MAX_COMPRESS_DIM; - } - - Fptr->tilerow = NULL; - Fptr->maxtilelen = 1; - for (idx = 1; idx <= znaxis; idx++) { - snprintf(keyword, 9, "ZNAXIS%u", idx); - if (get_header_long(header, keyword, Fptr->znaxis + idx - 1, 0, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - snprintf(keyword, 9, "ZTILE%u", idx); - if (get_header_long(header, keyword, Fptr->tilesize + idx - 1, 0, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - Fptr->maxtilelen *= Fptr->tilesize[idx - 1]; - } - - // Set some more default compression options - Fptr->rice_blocksize = DEFAULT_BLOCK_SIZE; - Fptr->rice_bytepix = DEFAULT_BYTE_PIX; - Fptr->quantize_level = DEFAULT_QUANTIZE_LEVEL; - Fptr->hcomp_smooth = DEFAULT_HCOMP_SMOOTH; - Fptr->hcomp_scale = DEFAULT_HCOMP_SCALE; - - // Now process the ZVALn keywords - idx = 1; - while (1) { - snprintf(keyword, 9, "ZNAME%u", idx); - // Assumes there are no gaps in the ZNAMEn keywords; this same - // assumption was made in the Python code. This could be done slightly - // more flexibly by using a wildcard slice of the header - tmp_retval = get_header_string(header, keyword, zname, "", HDR_NOFLAG); - if (tmp_retval == GET_HEADER_FAILED) { - return; - } else if (tmp_retval == 1) { - break; - } - - snprintf(keyword, 9, "ZVAL%u", idx); - if (Fptr->compress_type == RICE_1) { - if (0 == strcmp(zname, "BLOCKSIZE")) { - if (get_header_int(header, keyword, &(Fptr->rice_blocksize), - DEFAULT_BLOCK_SIZE, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - } else if (0 == strcmp(zname, "BYTEPIX")) { - if (get_header_int(header, keyword, &(Fptr->rice_bytepix), - DEFAULT_BYTE_PIX, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - } - } else if (Fptr->compress_type == HCOMPRESS_1) { - if (0 == strcmp(zname, "SMOOTH")) { - if (get_header_int(header, keyword, &(Fptr->hcomp_smooth), - DEFAULT_HCOMP_SMOOTH, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - } else if (0 == strcmp(zname, "SCALE")) { - if (get_header_float(header, keyword, &(Fptr->hcomp_scale), - DEFAULT_HCOMP_SCALE, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - } - } - if (Fptr->zbitpix < 0 && 0 == strcmp(zname, "NOISEBIT")) { - if (get_header_float(header, keyword, &(Fptr->quantize_level), - DEFAULT_QUANTIZE_LEVEL, HDR_NOFLAG) == GET_HEADER_FAILED) { - return; - } - if (Fptr->quantize_level == 0.0) { - /* NOISEBIT == 0 is equivalent to no quantize */ - Fptr->quantize_level = NO_QUANTIZE; - } - } - - idx++; - } - - /* The ZQUANTIZ keyword determines the quantization algorithm; NO_QUANTIZE - implies lossless compression */ - tmp_retval = get_header_string(header, "ZQUANTIZ", tmp, "", HDR_NOFLAG); - if (tmp_retval == GET_HEADER_FAILED) { - return; - } else if (tmp_retval == GET_HEADER_SUCCESS) { - /* Ugh; the fact that cfitsio defines its version as a float makes - preprocessor comparison impossible */ - fits_get_version(&version); - if (0 == strcmp(tmp, "NONE")) { - Fptr->quantize_level = NO_QUANTIZE; - } else if (0 == strcmp(tmp, "SUBTRACTIVE_DITHER_1")) { - // Added in CFITSIO 3.35, this also changed the name of the - // quantize_dither struct member to quantize_method - Fptr->quantize_method = SUBTRACTIVE_DITHER_1; - } else if (0 == strcmp(tmp, "SUBTRACTIVE_DITHER_2")) { - Fptr->quantize_method = SUBTRACTIVE_DITHER_2; - } else { - Fptr->quantize_method = NO_DITHER; - } - } else { - Fptr->quantize_method = NO_DITHER; - } - - if (Fptr->quantize_method != NO_DITHER) { - switch (get_header_int(header, "ZDITHER0", &(Fptr->dither_seed), 0, HDR_NOFLAG)) { - case GET_HEADER_FAILED: - return; - case GET_HEADER_DEFAULT_USED: // ZDITHER0 keyword not found - Fptr->dither_seed = 0; - Fptr->request_dither_seed = 0; - break; - default: - break; - } - } - - Fptr->compressimg = 1; - Fptr->maxelem = imcomp_calc_max_elem(Fptr->compress_type, - Fptr->maxtilelen, - Fptr->zbitpix, - Fptr->rice_blocksize); - Fptr->cn_compressed = 1; - return; -} - - -void init_output_buffer(PyObject* hdu, void** buf, size_t* bufsize) { - // Determines a good size for the output data buffer and allocates - // memory for it, returning the address and size of the allocated - // memory into **buf and *bufsize respectively. - - PyObject* header = NULL; - char keyword[9]; - char tmp[72]; - int znaxis; - int compress_type; - int zbitpix; - int rice_blocksize = 0; - long long rowlen; - long long nrows; - long maxelem; - long tilelen; - unsigned long maxtilelen = 1; - int idx; - - header = PyObject_GetAttrString(hdu, "_header"); - if (header == NULL) { - return; - } - - if (get_header_int(header, "ZNAXIS", &znaxis, 0, - HDR_FAIL_KEY_MISSING | HDR_FAIL_VAL_NEGATIVE) != GET_HEADER_SUCCESS) { - goto fail; - } - - if (znaxis > 999) { - PyErr_SetString(PyExc_ValueError, "ZNAXIS is greater than 999."); - goto fail; - } - - for (idx = 1; idx <= znaxis; idx++) { - snprintf(keyword, 9, "ZTILE%u", idx); - if (get_header_long(header, keyword, &tilelen, 1, HDR_NOFLAG) == GET_HEADER_FAILED) { - goto fail; - } - maxtilelen *= tilelen; - } - - if (get_header_string(header, "ZCMPTYPE", tmp, DEFAULT_COMPRESSION_TYPE, HDR_NOFLAG) == GET_HEADER_FAILED) { - goto fail; - } - compress_type = compress_type_from_string(tmp); - if (PyErr_Occurred()) { - goto fail; - } - if (compress_type == RICE_1) { - if (get_header_int(header, "ZVAL1", &rice_blocksize, 0, HDR_NOFLAG) == GET_HEADER_FAILED) { - goto fail; - } - } - - /* Because we calculate the size of the buffer based on these values they - must not be negative. Otherwise it would wrap around during the casting - to size_t and give huge values. */ - if (get_header_longlong(header, "NAXIS1", &rowlen, 0, HDR_FAIL_VAL_NEGATIVE) == GET_HEADER_FAILED) { - goto fail; - } - if (get_header_longlong(header, "NAXIS2", &nrows, 0, HDR_FAIL_VAL_NEGATIVE) == GET_HEADER_FAILED) { - goto fail; - } - - // Get the ZBITPIX header value; if this is missing we're in trouble - if (get_header_int(header, "ZBITPIX", &zbitpix, 0, HDR_FAIL_KEY_MISSING) != GET_HEADER_SUCCESS) { - goto fail; - } - - maxelem = imcomp_calc_max_elem(compress_type, maxtilelen, zbitpix, - rice_blocksize); - - *bufsize = ((size_t) (rowlen * nrows) + (nrows * maxelem)); - - if (*bufsize < IOBUFLEN) { - // We must have a full FITS block at a minimum - *bufsize = IOBUFLEN; - } else if (*bufsize % IOBUFLEN != 0) { - // Still make sure to pad out to a multiple of 2880 byte blocks - // otherwise CFITSIO can get read errors when it tries to read - // a partial block that goes past the end of the file - *bufsize += ((size_t) (IOBUFLEN - (*bufsize % IOBUFLEN))); - } - - *buf = calloc(*bufsize, sizeof(char)); - if (*buf == NULL) { - // Checking if calloc failed. - PyErr_SetString(PyExc_MemoryError, - "Failed to allocate memory for output data buffer."); - goto fail; - } - -fail: - Py_DECREF(header); - return; -} - - -void get_hdu_data_base(PyObject* hdu, void** buf, size_t* bufsize) { - // Given a pointer to an HDU object, returns a pointer to the deepest base - // array of that HDU's data array into **buf, and the size of that array - // into *bufsize. - - PyArrayObject* data = NULL; - PyArrayObject* base; - PyArrayObject* tmp; - - data = (PyArrayObject*) PyObject_GetAttrString(hdu, "compressed_data"); - if (data == NULL) { - goto fail; - } - - // Walk the array data bases until we find the lowest ndarray base; for - // CompImageHDUs there should always be at least one contiguous byte array - // allocated for the table and its heap - if (!PyObject_TypeCheck(data, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, - "CompImageHDU.compressed_data must be a numpy.ndarray"); - goto fail; - } - - tmp = base = data; - while (PyObject_TypeCheck((PyObject*) tmp, &PyArray_Type)) { - base = tmp; - *bufsize = (size_t) PyArray_NBYTES(base); - tmp = (PyArrayObject*) PyArray_BASE(base); - if (tmp == NULL) { - break; - } - } - - *buf = PyArray_DATA(base); -fail: - Py_XDECREF(data); - return; -} - - -void open_from_hdu(fitsfile** fileptr, void** buf, size_t* bufsize, - PyObject* hdu, tcolumn** columns, int mode) { - - PyObject* header = NULL; - FITSfile* Fptr; - - int status = 0; - long long rowlen; - long long nrows; - long long heapsize; - long long theap; - - header = PyObject_GetAttrString(hdu, "_header"); - if (header == NULL) { - goto fail; - } - - if (get_header_longlong(header, "NAXIS1", &rowlen, 0, HDR_NOFLAG) == GET_HEADER_FAILED) { - goto fail; - } - if (get_header_longlong(header, "NAXIS2", &nrows, 0, HDR_NOFLAG) == GET_HEADER_FAILED) { - goto fail; - } - - // The PCOUNT keyword contains the number of bytes in the table heap - if (get_header_longlong(header, "PCOUNT", &heapsize, 0, HDR_FAIL_VAL_NEGATIVE) == GET_HEADER_FAILED) { - goto fail; - } - - // The THEAP keyword gives the offset of the heap from the beginning of - // the HDU data portion; normally this offset is 0 but it can be set - // to something else with THEAP - if (get_header_longlong(header, "THEAP", &theap, 0, HDR_NOFLAG) == GET_HEADER_FAILED) { - goto fail; - } - - fits_create_memfile(fileptr, buf, bufsize, 0, realloc, &status); - if (status != 0) { - process_status_err(status); - goto fail; - } - - Fptr = (*fileptr)->Fptr; - - // Now we have some fun munging some of the elements in the fitsfile struct - Fptr->writemode = mode; - Fptr->open_count = 1; - Fptr->hdutype = BINARY_TBL; /* This is a binary table HDU */ - Fptr->lasthdu = 1; - Fptr->headstart[0] = 0; - Fptr->headend = 0; - Fptr->datastart = 0; /* There is no header, data starts at 0 */ - Fptr->origrows = Fptr->numrows = nrows; - Fptr->rowlength = rowlen; - if (theap != 0) { - Fptr->heapstart = theap; - } else { - Fptr->heapstart = rowlen * nrows; - } - - Fptr->heapsize = heapsize; - - // Configure the array of table column structs from the Astropy header - // instead of allowing CFITSIO to try to read from the header - tcolumns_from_header(*fileptr, header, columns); - if (PyErr_Occurred()) { - goto fail; - } - - // If any errors occur in this function they'll bubble up from here to - // compression_decompress_hdu - configure_compression(*fileptr, header); - -fail: - Py_XDECREF(header); - return; -} - - -/* define a PyCapsule_Destructor, using the correct deallocator for buff */ -void free_wrap(void *capsule){ - void * obj = PyCapsule_GetPointer(capsule, PyCapsule_GetName(capsule)); - free(obj); -}; - - -PyObject* compression_compress_hdu(PyObject* self, PyObject* args) -{ - PyObject* hdu; - PyObject* retval = NULL; - tcolumn* columns = NULL; - - void* outbuf = NULL; - size_t outbufsize; - - PyObject* tmp_indata; - PyArrayObject* indata = NULL; - PyArrayObject* tmp; - npy_intp znaxis; - int datatype; - int npdatatype; - unsigned long long heapsize; - - fitsfile* fileptr = NULL; - FITSfile* Fptr = NULL; - int status = 0; - - if (!PyArg_ParseTuple(args, "O:compression.compress_hdu", &hdu)) { - return NULL; - } - - // For HDU compression never use CFITSIO to write directly to the file; - // although there's nothing wrong with CFITSIO, right now that would cause - // too much confusion to Astropy's internal book keeping. - // We just need to get the compressed bytes and Astropy will handle the - // writing of them. - init_output_buffer(hdu, &outbuf, &outbufsize); - if (outbuf == NULL) { - return NULL; - } - - open_from_hdu(&fileptr, &outbuf, &outbufsize, hdu, &columns, READWRITE); - if (PyErr_Occurred()) { - goto fail; - } - - Fptr = fileptr->Fptr; - - bitpix_to_datatypes(Fptr->zbitpix, &datatype, &npdatatype); - if (PyErr_Occurred()) { - goto fail; - } - - /* The data attribute could be something different from an array, i.e. None */ - tmp_indata = PyObject_GetAttrString(hdu, "data"); - if (tmp_indata == NULL) { - goto fail; - } - - if (!PyObject_TypeCheck(tmp_indata, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, - "CompImageHDU.data must be a numpy.ndarray"); - Py_DECREF(tmp_indata); - goto fail; - } - - indata = (PyArrayObject*) tmp_indata; - - fits_write_img(fileptr, datatype, 1, PyArray_SIZE(indata), - PyArray_DATA(indata), &status); - if (status != 0) { - process_status_err(status); - goto fail; - } - - fits_flush_buffer(fileptr, 1, &status); - if (status != 0) { - process_status_err(status); - goto fail; - } - - // Previously this used outbufsize as the size to use for the new Numpy - // byte array. However outbufsize is usually larger than necessary to - // store all the compressed data exactly; instead use the exact size - // of the compressed data from the heapsize plus the size of the table - // itself - heapsize = (unsigned long long) Fptr->heapsize; - znaxis = (npy_intp) (Fptr->heapstart + heapsize); - - if (znaxis < outbufsize) { - void* tmp_outbuf = NULL; - // Go ahead and truncate to the size in znaxis to free the - // redundant allocation - if (znaxis == 0) { - /* This really shouldn't happen, but if it did, we would have a - problem because realloc would deallocate outbuf AND return NULL. - */ - PyErr_SetString(PyExc_ValueError, - "Calculated array size is zero. This shouldn't happen!"); - goto fail; - } - tmp_outbuf = realloc(outbuf, (size_t) znaxis); - if (tmp_outbuf == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Couldn't resize the output-buffer."); - goto fail; - } - outbuf = tmp_outbuf; - } - - tmp = (PyArrayObject*) PyArray_SimpleNewFromData(1, &znaxis, NPY_UBYTE, - outbuf); - if (tmp == NULL) { - /* Really not sure if it's always safe to free outbuf when - PyArray_SimpleNewFromData failed (which is unlikely but could happen) - but it seems like if it fails then the outbuf NEEDS to be freed... */ - goto fail; - } - - // Take responsibility for outbuf by wrapping it in a capsule and - // setting tmp.base to the capsule - // See explanations on memory policy in the numpy docs for more details: - // https://github.com/numpy/numpy/blob/main/doc/source/reference/c-api/data_memory.rst - PyObject *capsule = PyCapsule_New(outbuf, "wrapped_data", - (PyCapsule_Destructor)&free_wrap); - if (PyArray_SetBaseObject(tmp, capsule) == -1) { - Py_DECREF(tmp); - goto cleanup; - } - - // Leaves refcount of tmp untouched, so its refcount should remain as 1 - retval = Py_BuildValue("KN", heapsize, tmp); - if (retval == NULL) { - Py_DECREF(tmp); - goto cleanup; - } - - goto cleanup; - -fail: - if (outbuf != NULL) { - // At this point outbuf should never not be NULL, but in principle - // buggy code somewhere in CFITSIO or Numpy could set it to NULL - free(outbuf); - } -cleanup: - if (columns != NULL) { - free(columns); - /* See https://github.com/astropy/astropy/pull/4489 - We can only set the tableptr to NULL if Fptr is actually not NULL. - */ - if (fileptr != NULL && fileptr->Fptr != NULL) { - fileptr->Fptr->tableptr = NULL; - } - } - - if (fileptr != NULL) { - status = 1; // Disable header-related errors - fits_close_file(fileptr, &status); - if (status != 1) { - process_status_err(status); - retval = NULL; - } - } - - Py_XDECREF(indata); - - // Clear any messages remaining in CFITSIO's error stack - fits_clear_errmsg(); - - return retval; -} - - -PyObject* compression_decompress_hdu(PyObject* self, PyObject* args) -{ - - PyObject* hdu; - tcolumn* columns = NULL; - - void* inbuf; - size_t inbufsize; - - PyArrayObject* outdata = NULL; - int datatype; - int npdatatype; - npy_intp zndim; - npy_intp* znaxis = NULL; - long arrsize; - - fitsfile* fileptr = NULL; - int anynul = 0; - int status = 0; - int idx; - - int free_columns_manually = 1; - - if (!PyArg_ParseTuple(args, "O:compression.decompress_hdu", &hdu)) { - return NULL; - } - - // Grab a pointer to the input data from the HDU's compressed_data - // attribute - get_hdu_data_base(hdu, &inbuf, &inbufsize); - if (PyErr_Occurred()) { - return NULL; - } else if (inbufsize == 0) { - // The compressed data buffer is empty (probably zero rows, for an - // empty "compressed" image. Just return None in this case. - Py_RETURN_NONE; - } - - open_from_hdu(&fileptr, &inbuf, &inbufsize, hdu, &columns, READONLY); - if (PyErr_Occurred()) { - goto fail; - } - - bitpix_to_datatypes(fileptr->Fptr->zbitpix, &datatype, &npdatatype); - if (PyErr_Occurred()) { - goto fail; - } - - zndim = (npy_intp)fileptr->Fptr->zndim; - znaxis = PyMem_Malloc(sizeof(npy_intp) * zndim); - if (znaxis == NULL) { - goto fail; - } - - arrsize = 1; - for (idx = 0; idx < zndim; idx++) { - znaxis[zndim - idx - 1] = fileptr->Fptr->znaxis[idx]; - arrsize *= fileptr->Fptr->znaxis[idx]; - } - - /* Create and allocate a new array for the decompressed data */ - outdata = (PyArrayObject*) PyArray_SimpleNew(zndim, znaxis, npdatatype); - if (outdata == NULL) { - goto fail; - } - - fits_read_img(fileptr, datatype, 1, arrsize, NULL, PyArray_DATA(outdata), - &anynul, &status); - /* At this point we need to let CFITSIO clean up the tableptr and the - compressed tile cache. */ - free_columns_manually = 0; - if (status != 0) { - process_status_err(status); - Py_DECREF(outdata); - outdata = NULL; - } - -fail: - // CFITSIO will free this object in the ffchdu function by way of - // fits_close_file; we need to let CFITSIO handle this so that it also - // cleans up the compressed tile cache - but that's only necessary in case - // we called "fits_read_img"... - if (free_columns_manually && columns != NULL) { - free(columns); - if (fileptr != NULL && fileptr->Fptr != NULL) { - fileptr->Fptr->tableptr = NULL; - } - } - - if (fileptr != NULL) { - status = 1;// Disable header-related errors - fits_close_file(fileptr, &status); - if (status != 1) { - process_status_err(status); - outdata = NULL; - } - } - - if (znaxis != NULL) { - PyMem_Free(znaxis); - } - - // Clear any messages remaining in CFITSIO's error stack - fits_clear_errmsg(); - - return (PyObject*) outdata; -} - - -/* CFITSIO version float as returned by fits_get_version() */ -static double cfitsio_version; - - -int compression_module_init(PyObject* module) { - /* Python version-independent initialization routine for the - compression module. Returns 0 on success and -1 (with exception set) - on failure. */ - PyObject* tmp; - float version_tmp; - int ret; - - fits_get_version(&version_tmp); - cfitsio_version = (double) version_tmp; - /* The conversion to double can lead to some rounding errors; round to the - nearest 3 decimal places, which should be accurate for any past or - current CFITSIO version. This is why relying on floats for version - comparison isn't generally a bright idea... */ - cfitsio_version = floor((1000 * version_tmp + 0.5)) / 1000; - - tmp = PyFloat_FromDouble(cfitsio_version); - if (tmp == NULL) { - return -1; - } - ret = PyObject_SetAttrString(module, "CFITSIO_VERSION", tmp); - Py_DECREF(tmp); - return ret; -} - - -/* Method table mapping names to wrappers */ -static PyMethodDef compression_methods[] = -{ - {"compress_hdu", compression_compress_hdu, METH_VARARGS}, - {"decompress_hdu", compression_decompress_hdu, METH_VARARGS}, - {NULL, NULL} -}; - -static struct PyModuleDef compressionmodule = { - PyModuleDef_HEAD_INIT, - "compression", - "astropy.compression module", - -1, /* No global state */ - compression_methods -}; - -PyObject * -PyInit_compression(void) -{ - PyObject* module = PyModule_Create(&compressionmodule); - if (module == NULL) { - return NULL; - } - if (compression_module_init(module)) { - Py_DECREF(module); - return NULL; - } - - /* Needed to use Numpy routines */ - /* Note -- import_array() is a macro that behaves differently in Python2.x - * vs. Python 3. See the discussion at: - * https://groups.google.com/d/topic/astropy-dev/6_AesAsCauM/discussion - */ - import_array(); - return module; -} diff --git a/astropy/io/fits/src/compressionmodule.h b/astropy/io/fits/src/compressionmodule.h deleted file mode 100644 index 7c13387a5ba..00000000000 --- a/astropy/io/fits/src/compressionmodule.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _COMPRESSIONMODULE_H -#define _COMPRESSIONMODULE_H - - -/* CFITSIO version-specific feature support */ -#ifndef CFITSIO_MAJOR - // Define a minimized version - #define CFITSIO_MAJOR 0 - #ifdef _MSC_VER - #pragma warning ( "CFITSIO_MAJOR not defined; your CFITSIO version may be too old; compile at your own risk" ) - #else - #warning "CFITSIO_MAJOR not defined; your CFITSIO version may be too old; compile at your own risk" - #endif -#endif - -#ifndef CFITSIO_MINOR - #define CFITSIO_MINOR 0 -#endif - - -#if CFITSIO_MAJOR == 3 && CFITSIO_MINOR < 35 - #ifdef _MSC_VER - #pragma warning ( "your CFITSIO version is too old; use 3.35 or later" ) - #else - #warning "your CFITSIO version is too old; use 3.35 or later" - #endif -#endif - - -/* These defaults mirror the defaults in io.fits.hdu.compressed */ -#define DEFAULT_COMPRESSION_TYPE "RICE_1" -#define DEFAULT_QUANTIZE_LEVEL 16.0 -#define DEFAULT_HCOMP_SCALE 0 -#define DEFAULT_HCOMP_SMOOTH 0 -#define DEFAULT_BLOCK_SIZE 32 -#define DEFAULT_BYTE_PIX 4 - -/* This constant is defined by cfitsio in imcompress.c */ -#define NO_QUANTIZE 9999 - -#endif diff --git a/astropy/io/fits/tests/test_compression_failures.py b/astropy/io/fits/tests/test_compression_failures.py index 3117c5fdb1c..98bddfcd791 100644 --- a/astropy/io/fits/tests/test_compression_failures.py +++ b/astropy/io/fits/tests/test_compression_failures.py @@ -4,7 +4,7 @@ import pytest from astropy.io import fits -from astropy.io.fits.compression import compress_hdu +from astropy.io.fits.tiled_compression import compress_hdu from .conftest import FitsTestCase diff --git a/astropy/io/fits/tiled_compression/__init__.py b/astropy/io/fits/tiled_compression/__init__.py new file mode 100644 index 00000000000..daf1a3d597f --- /dev/null +++ b/astropy/io/fits/tiled_compression/__init__.py @@ -0,0 +1 @@ +from .tiled_compression import * diff --git a/astropy/io/fits/tiled_compression/_codecs.py b/astropy/io/fits/tiled_compression/_codecs.py new file mode 100644 index 00000000000..5f994a0dec3 --- /dev/null +++ b/astropy/io/fits/tiled_compression/_codecs.py @@ -0,0 +1,364 @@ +""" +This file contains the FITS compression algorithms in numcodecs style Codecs. + +This module is currently private as these classes have not been tested +externally to Astropy and their behaviour may have to change. +""" +from gzip import compress as gzip_compress +from gzip import decompress as gzip_decompress + +import numpy as np + +from astropy.io.fits.tiled_compression._compression import ( + compress_hcompress_1_c, + compress_plio_1_c, + compress_rice_1_c, + decompress_hcompress_1_c, + decompress_plio_1_c, + decompress_rice_1_c, +) + +try: + from numcodecs.abc import Codec +except ImportError: + + class Codec: + codec_id = None + + +__all__ = [ + "Gzip1", + "Gzip2", + "Rice1", + "PLIO1", + "HCompress1", +] + + +class Gzip1(Codec): + """ + The FITS GZIP 1 compression and decompression algorithm. + + The Gzip algorithm is used in the free GNU software compression utility of + the same name. It was created by J. L. Gailly and M. Adler, based on the + DEFLATE algorithm (Deutsch 1996), which is a combination of LZ77 (Ziv & + Lempel 1977) and Huffman coding. + """ + + codec_id = "FITS_GZIP1" + + def decode(self, buf): + """ + Decompress buffer using the GZIP_1 algorithm. + + Parameters + ---------- + buf + The buffer to decompress. + + Returns + ------- + buf + The decompressed buffer. + """ + cbytes = np.frombuffer(buf, dtype=np.uint8).tobytes() + dbytes = gzip_decompress(cbytes) + return np.frombuffer(dbytes, dtype=np.uint8).data + + def encode(self, buf): + """ + Compress the data in the buffer using the GZIP_1 algorithm. + + Parameters + ---------- + buf + The buffer to compress. + + Returns + ------- + buf + A buffer with compressed data. + """ + dbytes = np.asarray(buf).tobytes() + return gzip_compress(dbytes) + + +class Gzip2(Codec): + """ + The FTIS GZIP2 compression and decompression algorithm. + + The gzip2 algorithm is a variation on 'GZIP 1'. In this case the buffer in + the array of data values are shuffled so that they are arranged in order of + decreasing significance before being compressed. + + For example, a five-element contiguous array of two-byte (16-bit) integer + values, with an original big-endian byte order of: + + .. math:: + A1 A2 B1 B2 C1 C2 D1 D2 E1 E2 + + will have the following byte order after shuffling: + + .. math:: + A1 B1 C1 D1 E1 A2 B2 C2 D2 E2, + + where A1, B1, C1, D1, and E1 are the most-significant buffer from + each of the integer values. + + Byte shuffling shall only be performed for integer or floating-point + numeric data types; logical, bit, and character types must not be shuffled. + + Parameters + ---------- + itemsize + The number of buffer per value (e.g. 2 for a 16-bit integer) + + """ + + codec_id = "FITS_GZIP2" + + def __init__(self, itemsize: int): + super().__init__() + self.itemsize = itemsize + + def decode(self, buf): + """ + Decompress buffer using the GZIP_2 algorithm. + + Parameters + ---------- + buf + The buffer to decompress. + + Returns + ------- + buf + The decompressed buffer. + """ + cbytes = np.frombuffer(buf, dtype=np.uint8).tobytes() + # Start off by unshuffling buffer + unshuffled_buffer = gzip_decompress(cbytes) + array = np.frombuffer(unshuffled_buffer, dtype=np.uint8) + return array.reshape((self.itemsize, -1)).T.ravel().data + + def encode(self, buf): + """ + Compress the data in the buffer using the GZIP_2 algorithm. + + Parameters + ---------- + buf + The buffer to decompress. + + Returns + ------- + buf + The decompressed buffer. + """ + # Start off by shuffling buffer + array = np.asarray(buf).ravel() + itemsize = array.dtype.itemsize + array = array.view(np.uint8) + shuffled_buffer = array.reshape((-1, itemsize)).T.ravel().tobytes() + return gzip_compress(shuffled_buffer) + + +class Rice1(Codec): + """ + The FTIS RICE1 compression and decompression algorithm. + + The Rice algorithm [1]_ is simple and very fast It requires only enough + memory to hold a single block of 16 or 32 pixels at a time. It codes the + pixels in small blocks and so is able to adapt very quickly to changes in + the input image statistics (e.g., Rice has no problem handling cosmic rays, + bright stars, saturated pixels, etc.). + + Parameters + ---------- + blocksize + The blocksize to use, each tile is coded into blocks a number of pixels + wide. The default value in FITS headers is 32 pixels per block. + + bytepix + The number of 8-bit buffer in each original integer pixel value. + + References + ---------- + .. [1] Rice, R. F., Yeh, P.-S., and Miller, W. H. 1993, in Proc. of the 9th + AIAA Computing in Aerospace Conf., AIAA-93-4541-CP, American Institute of + Aeronautics and Astronautics [https://doi.org/10.2514/6.1993-4541] + """ + + codec_id = "FITS_RICE1" + + def __init__(self, blocksize: int, bytepix: int, tilesize: int): + self.blocksize = blocksize + self.bytepix = bytepix + self.tilesize = tilesize + + def decode(self, buf): + """ + Decompress buffer using the RICE_1 algorithm. + + Parameters + ---------- + buf + The buffer to decompress. + + Returns + ------- + buf + The decompressed buffer. + """ + cbytes = np.frombuffer(buf, dtype=np.uint8).tobytes() + dbytes = decompress_rice_1_c( + cbytes, self.blocksize, self.bytepix, self.tilesize + ) + return np.frombuffer(dbytes, dtype=f"i{self.bytepix}").data + + def encode(self, buf): + """ + Compress the data in the buffer using the RICE_1 algorithm. + + Parameters + ---------- + buf + The buffer to decompress. + + Returns + ------- + buf + A buffer with decompressed data. + """ + dbytes = np.asarray(buf).astype(f"i{self.bytepix}").tobytes() + return compress_rice_1_c(dbytes, self.blocksize, self.bytepix) + + +class PLIO1(Codec): + """ + The FTIS PLIO1 compression and decompression algorithm. + + The IRAF PLIO (pixel list) algorithm was developed to store integer-valued + image masks in a compressed form. Such masks often have large regions of + constant value hence are highly compressible. The compression algorithm + used is based on run-length encoding, with the ability to dynamically + follow level changes in the image, allowing a 16-bit encoding to be used + regardless of the image depth. + """ + + codec_id = "FITS_PLIO1" + + def __init__(self, tilesize: int): + self.tilesize = tilesize + + def decode(self, buf): + """ + Decompress buffer using the PLIO_1 algorithm. + + Parameters + ---------- + buf + The buffer to decompress. + + Returns + ------- + buf + The decompressed buffer. + """ + cbytes = np.frombuffer(buf, dtype=np.uint8).tobytes() + dbytes = decompress_plio_1_c(cbytes, self.tilesize) + return np.frombuffer(dbytes, dtype="i4").data + + def encode(self, buf): + """ + Compress the data in the buffer using the PLIO_1 algorithm. + """ + dbytes = np.asarray(buf).astype("i4").tobytes() + return compress_plio_1_c(dbytes, self.tilesize) + + +class HCompress1(Codec): + """ + The FTIS PLIO1 compression and decompression algorithm. + + Hcompress is an the image compression package written by Richard L. White + for use at the Space Telescope Science Institute. Hcompress was used to + compress the STScI Digitized Sky Survey and has also been used to compress + the preview images in the Hubble Data Archive. + + The technique gives very good compression for astronomical images and is + relatively fast. The calculations are carried out using integer arithmetic + and are entirely reversible. Consequently, the program can be used for + either lossy or lossless compression, with no special approach needed for + the lossless case. + + Parameters + ---------- + scale + The integer scale parameter determines the amount of compression. Scale + = 0 or 1 leads to lossless compression, i.e. the decompressed image has + exactly the same pixel values as the original image. If the scale + factor is greater than 1 then the compression is lossy: the + decompressed image will not be exactly the same as the original + + smooth + At high compressions factors the decompressed image begins to appear + blocky because of the way information is discarded. This blockiness + ness is greatly reduced, producing more pleasing images, if the image + is smoothed slightly during decompression. + + References + ---------- + .. [1] White, R. L. 1992, in Proceedings of the NASA Space and Earth Science + Data Compression Workshop, ed. J. C. Tilton, Snowbird, UT; + https://archive.org/details/nasa_techdoc_19930016742 + """ + + codec_id = "FITS_HCOMPRESS1" + + def __init__(self, scale: int, smooth: bool, bytepix: int, nx: int, ny: int): + self.scale = scale + self.smooth = smooth + self.bytepix = bytepix + # NOTE: we should probably make this less confusing, but nx is shape[0] and ny is shape[1] + self.nx = nx + self.ny = ny + + def decode(self, buf): + """ + Decompress buffer using the HCOMPRESS_1 algorithm. + + Parameters + ---------- + buf + The buffer to decompress. + + Returns + ------- + buf + A buffer with decompressed data. + """ + cbytes = np.frombuffer(buf, dtype=np.uint8).tobytes() + dbytes = decompress_hcompress_1_c( + cbytes, self.nx, self.ny, self.scale, self.smooth, self.bytepix + ) + return np.frombuffer(dbytes, dtype=f"i{self.bytepix}").data + + def encode(self, buf): + """ + Compress the data in the buffer using the HCOMPRESS_1 algorithm. + + Parameters + ---------- + buf + The buffer to decompress. + + Returns + ------- + buf + A buffer with decompressed data. + """ + dbytes = np.asarray(buf).astype(f"i{self.bytepix}").tobytes() + return compress_hcompress_1_c( + dbytes, self.nx, self.ny, self.scale, self.bytepix + ) diff --git a/astropy/io/fits/tiled_compression/_quantization.py b/astropy/io/fits/tiled_compression/_quantization.py new file mode 100644 index 00000000000..a6f7386a1c2 --- /dev/null +++ b/astropy/io/fits/tiled_compression/_quantization.py @@ -0,0 +1,134 @@ +""" +This file contains the code for Quantizing / Dequantizing floats. +""" +import numpy as np + +from astropy.io.fits.hdu.base import BITPIX2DTYPE +from astropy.io.fits.tiled_compression._compression import ( + quantize_double_c, + quantize_float_c, + unquantize_double_c, + unquantize_float_c, +) + +__all__ = ["Quantize"] + + +DITHER_METHODS = {"NO_DITHER": -1, "SUBTRACTIVE_DITHER_1": 1, "SUBTRACTIVE_DITHER_2": 2} + + +class QuantizationFailedException(Exception): + pass + + +class Quantize: + """ + Quantization of floating-point data following the FITS standard. + """ + + def __init__(self, row: int, dither_method: int, quantize_level: int, bitpix: int): + super().__init__() + self.row = row + # TODO: pass dither method as a string instead of int? + self.quantize_level = quantize_level + self.dither_method = dither_method + self.bitpix = bitpix + + # NOTE: below we use decode_quantized and encode_quantized instead of + # decode and encode as we need to break with the numcodec API and take/return + # scale and zero in addition to quantized value. We should figure out how + # to properly use the numcodec API for this use case. + + def decode_quantized(self, buf, scale, zero): + """ + Unquantize data + + Parameters + ---------- + buf + The buffer to unquantize. + + Returns + ------- + buf + The unquantized buffer. + """ + qbytes = np.asarray(buf) + qbytes = qbytes.astype(qbytes.dtype.newbyteorder("=")) + # TODO: figure out if we need to support null checking + if self.dither_method == -1: + # For NO_DITHER we should just use the scale and zero directly + return qbytes * scale + zero + if self.bitpix == -32: + ubytes = unquantize_float_c( + qbytes.tobytes(), + self.row, + qbytes.size, + scale, + zero, + self.dither_method, + 0, + 0, + 0.0, + qbytes.dtype.itemsize, + ) + elif self.bitpix == -64: + ubytes = unquantize_double_c( + qbytes.tobytes(), + self.row, + qbytes.size, + scale, + zero, + self.dither_method, + 0, + 0, + 0.0, + qbytes.dtype.itemsize, + ) + else: + raise TypeError("bitpix should be one of -32 or -64") + return np.frombuffer(ubytes, dtype=BITPIX2DTYPE[self.bitpix]).data + + def encode_quantized(self, buf): + """ + Quantize data. + + Parameters + ---------- + buf + The buffer to quantize. + + Returns + ------- + buf + A buffer with quantized data. + """ + uarray = np.asarray(buf) + uarray = uarray.astype(uarray.dtype.newbyteorder("=")) + # TODO: figure out if we need to support null checking + if uarray.dtype.itemsize == 4: + qbytes, status, scale, zero = quantize_float_c( + uarray.tobytes(), + self.row, + uarray.size, + 1, + 0, + 0, + self.quantize_level, + self.dither_method, + )[:4] + elif uarray.dtype.itemsize == 8: + qbytes, status, scale, zero = quantize_double_c( + uarray.tobytes(), + self.row, + uarray.size, + 1, + 0, + 0, + self.quantize_level, + self.dither_method, + )[:4] + if status == 0: + raise QuantizationFailedException() + else: + return np.frombuffer(qbytes, dtype=np.int32).data, scale, zero diff --git a/astropy/io/fits/tiled_compression/setup_package.py b/astropy/io/fits/tiled_compression/setup_package.py new file mode 100644 index 00000000000..c5b1f953a03 --- /dev/null +++ b/astropy/io/fits/tiled_compression/setup_package.py @@ -0,0 +1,25 @@ +# Licensed under a 3-clause BSD style license + +import os + +from setuptools import Extension + +SRC_DIR = os.path.join(os.path.dirname(__file__), "src") + + +def get_extensions(): + return [ + Extension( + "astropy.io.fits.tiled_compression._compression", + sources=[ + os.path.join(SRC_DIR, "compression.c"), + os.path.join("cextern", "cfitsio", "lib", "pliocomp.c"), + os.path.join("cextern", "cfitsio", "lib", "ricecomp.c"), + os.path.join("cextern", "cfitsio", "lib", "fits_hcompress.c"), + os.path.join("cextern", "cfitsio", "lib", "fits_hdecompress.c"), + os.path.join("cextern", "cfitsio", "lib", "quantize.c"), + os.path.join("cextern", "cfitsio", "lib", "imcompress.c"), + ], + include_dirs=[SRC_DIR], + ) + ] diff --git a/astropy/io/fits/tiled_compression/src/compression.c b/astropy/io/fits/tiled_compression/src/compression.c new file mode 100644 index 00000000000..9f01af8a34a --- /dev/null +++ b/astropy/io/fits/tiled_compression/src/compression.c @@ -0,0 +1,571 @@ +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#define PY_SSIZE_T_CLEAN + +#include +#include +#include +#include +#include +#include +#include + +// Some of the cfitsio compression files use ffpmsg +// so we provide a dummy function to replace this. +void ffpmsg(const char *err_message) { + PyErr_SetString(PyExc_ValueError, err_message); +} + +// Compatibility code because we pick up fitsio2.h from cextern. Can +// remove once we remove cextern +#ifdef _REENTRANT +pthread_mutex_t Fitsio_Lock; +int Fitsio_Pthread_Status = 0; +#endif + +/* Define docstrings */ +static char module_docstring[] = "Core compression/decompression functions"; +static char compress_plio_1_c_docstring[] = "Compress data using PLIO_1"; +static char decompress_plio_1_c_docstring[] = "Decompress data using PLIO_1"; +static char compress_rice_1_c_docstring[] = "Compress data using RICE_1"; +static char decompress_rice_1_c_docstring[] = "Decompress data using RICE_1"; +static char compress_hcompress_1_c_docstring[] = + "Compress data using HCOMPRESS_1"; +static char decompress_hcompress_1_c_docstring[] = + "Decompress data using HCOMPRESS_1"; +static char quantize_float_c_docstring[] = "Quantize float data"; +static char quantize_double_c_docstring[] = "Quantize float data"; +static char unquantize_float_c_docstring[] = "Unquantize data to float"; +static char unquantize_double_c_docstring[] = "Unquantize data to double"; + +/* Declare the C functions here. */ +static PyObject *compress_plio_1_c(PyObject *self, PyObject *args); +static PyObject *decompress_plio_1_c(PyObject *self, PyObject *args); +static PyObject *compress_rice_1_c(PyObject *self, PyObject *args); +static PyObject *decompress_rice_1_c(PyObject *self, PyObject *args); +static PyObject *compress_hcompress_1_c(PyObject *self, PyObject *args); +static PyObject *decompress_hcompress_1_c(PyObject *self, PyObject *args); +static PyObject *quantize_float_c(PyObject *self, PyObject *args); +static PyObject *quantize_double_c(PyObject *self, PyObject *args); +static PyObject *unquantize_float_c(PyObject *self, PyObject *args); +static PyObject *unquantize_double_c(PyObject *self, PyObject *args); + +/* Define the methods that will be available on the module. */ +static PyMethodDef module_methods[] = { + {"compress_plio_1_c", compress_plio_1_c, METH_VARARGS, compress_plio_1_c_docstring}, + {"decompress_plio_1_c", decompress_plio_1_c, METH_VARARGS, decompress_plio_1_c_docstring}, + {"compress_rice_1_c", compress_rice_1_c, METH_VARARGS, compress_rice_1_c_docstring}, + {"decompress_rice_1_c", decompress_rice_1_c, METH_VARARGS, decompress_rice_1_c_docstring}, + {"compress_hcompress_1_c", compress_hcompress_1_c, METH_VARARGS, compress_hcompress_1_c_docstring}, + {"decompress_hcompress_1_c", decompress_hcompress_1_c, METH_VARARGS, decompress_hcompress_1_c_docstring}, + {"quantize_float_c", quantize_float_c, METH_VARARGS, quantize_float_c_docstring}, + {"quantize_double_c", quantize_double_c, METH_VARARGS, quantize_double_c_docstring}, + {"unquantize_float_c", unquantize_float_c, METH_VARARGS, unquantize_float_c_docstring}, + {"unquantize_double_c", unquantize_double_c, METH_VARARGS, unquantize_double_c_docstring}, + {NULL, NULL, 0, NULL} +}; + +/* This is the function that is called on import. */ + +#define MOD_ERROR_VAL NULL +#define MOD_SUCCESS_VAL(val) val +#define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) +#define MOD_DEF(ob, name, doc, methods) \ + static struct PyModuleDef moduledef = { \ + PyModuleDef_HEAD_INIT, name, doc, -1, methods, \ + }; \ + ob = PyModule_Create(&moduledef); + +MOD_INIT(_compression) { + PyObject *m; + MOD_DEF(m, "_compression", module_docstring, module_methods); + if (m == NULL) + return MOD_ERROR_VAL; + return MOD_SUCCESS_VAL(m); +} + +/* PLIO/IRAF compression */ + +static PyObject *compress_plio_1_c(PyObject *self, PyObject *args) { + + const char *str; + char *buf; + Py_ssize_t count; + PyObject *result; + + int maxelem; + int tilesize; + short *compressed_values; + int compressed_length; + int *decompressed_values; + + if (!PyArg_ParseTuple(args, "y#i", &str, &count, &tilesize)) { + return NULL; + } + + // For PLIO imcomp_calc_max_elem in cfitsio does this to calculate max memory: + maxelem = tilesize * sizeof(int); + // However, when compressing small numbers of random integers you can end up + // using more memory for the compressed bytes. In the worst case senario we + // tested, compressing a single 4 byte integer will compress to 16 bytes. We + // add 32 bytes here to give a small margin of error. + compressed_values = (short *)malloc(maxelem + 32); + + decompressed_values = (int *)str; + + // Zero the compressed values array + for (int i = 0; i < maxelem / 2; i++) { + compressed_values[i] = 0; + } + + compressed_length = pl_p2li(decompressed_values, 1, compressed_values, tilesize); + + if (PyErr_Occurred() != NULL) { + // If an error condition inside the cfitsio function, the call inside + // cfitsio should have called the ffpmsg function which sets the Python + // exception, so we just return here to raise an error. + return (PyObject *)NULL; + } + + buf = (char *)compressed_values; + + result = Py_BuildValue("y#", buf, compressed_length * 2); + free(buf); + return result; +} + +static PyObject *decompress_plio_1_c(PyObject *self, PyObject *args) { + + const char *str; + char *buf; + Py_ssize_t count; + PyObject *result; + + int tilesize; + + short *compressed_values; + int *decompressed_values; + + if (!PyArg_ParseTuple(args, "y#i", &str, &count, &tilesize)) { + return NULL; + } + + compressed_values = (short *)str; + + decompressed_values = (int *)malloc(sizeof(int) * tilesize); + + pl_l2pi(compressed_values, 1, decompressed_values, tilesize); + + if (PyErr_Occurred() != NULL) { + // If an error condition inside the cfitsio function, the call inside + // cfitsio should have called the ffpmsg function which sets the Python + // exception, so we just return here to raise an error. + return (PyObject *)NULL; + } + + buf = (char *)decompressed_values; + + result = Py_BuildValue("y#", buf, tilesize * 4); + free(buf); + return result; +} + +/* RICE compression */ + +static PyObject *compress_rice_1_c(PyObject *self, PyObject *args) { + + const char *str; + Py_ssize_t count; + PyObject *result; + + int blocksize, bytepix; + + int maxelem; + unsigned char *compressed_values; + int compressed_length; + signed char *decompressed_values_byte; + short *decompressed_values_short; + int *decompressed_values_int; + + if (!PyArg_ParseTuple(args, "y#ii", &str, &count, &blocksize, &bytepix)) { + return NULL; + } + + // maxelem adapted from cfitsio's imcomp_calc_max_elem function + maxelem = count + count / bytepix / blocksize + 2 + 4; + + compressed_values = (unsigned char *)malloc(maxelem); + + if (bytepix == 1) { + decompressed_values_byte = (signed char *)str; + compressed_length = fits_rcomp_byte(decompressed_values_byte, (int)count, compressed_values, count * 16, blocksize); + } else if (bytepix == 2) { + decompressed_values_short = (short *)str; + compressed_length = fits_rcomp_short(decompressed_values_short, (int)count / 2, compressed_values, count * 16, blocksize); + } else { + decompressed_values_int = (int *)str; + compressed_length = fits_rcomp(decompressed_values_int, (int)count / 4, compressed_values, count * 16, blocksize); + } + + if (PyErr_Occurred() != NULL) { + // If an error condition inside the cfitsio function, the call inside + // cfitsio should have called the ffpmsg function which sets the Python + // exception, so we just return here to raise an error. + return (PyObject *)NULL; + } + + result = Py_BuildValue("y#", compressed_values, compressed_length); + free(compressed_values); + return result; +} + +static PyObject *decompress_rice_1_c(PyObject *self, PyObject *args) { + + const char *str; + char *dbytes; + Py_ssize_t count; + PyObject *result; + + int blocksize, bytepix, tilesize; + + unsigned char *compressed_values; + unsigned char *decompressed_values_byte; + unsigned short *decompressed_values_short; + unsigned int *decompressed_values_int; + + if (!PyArg_ParseTuple(args, "y#iii", &str, &count, &blocksize, &bytepix, &tilesize)) { + return NULL; + } + + compressed_values = (unsigned char *)str; + + if (bytepix == 1) { + decompressed_values_byte = (unsigned char *)malloc(tilesize); + fits_rdecomp_byte(compressed_values, (int)count, decompressed_values_byte, tilesize, blocksize); + dbytes = (char *)decompressed_values_byte; + } else if (bytepix == 2) { + decompressed_values_short = (unsigned short *)malloc(tilesize * 2); + fits_rdecomp_short(compressed_values, (int)count, decompressed_values_short, tilesize, blocksize); + dbytes = (char *)decompressed_values_short; + } else { + decompressed_values_int = (unsigned int *)malloc(tilesize * 4); + fits_rdecomp(compressed_values, (int)count, decompressed_values_int, tilesize, blocksize); + dbytes = (char *)decompressed_values_int; + } + + if (PyErr_Occurred() != NULL) { + // If an error condition inside the cfitsio function, the call inside + // cfitsio should have called the ffpmsg function which sets the Python + // exception, so we just return here to raise an error. + return (PyObject *)NULL; + } + + result = Py_BuildValue("y#", dbytes, tilesize * bytepix); + free(dbytes); + return result; +} + +/* HCompress compression */ + +static PyObject *compress_hcompress_1_c(PyObject *self, PyObject *args) { + + const char *str; + Py_ssize_t count; + PyObject *result; + + int bytepix, nx, ny, scale; + int status=0; // Important to initialize this to zero otherwise will fail silently + + int maxelem; + char *compressed_values; + int *decompressed_values_int; + long long *decompressed_values_longlong; + + if (!PyArg_ParseTuple(args, "y#iiii", &str, &count, &nx, &ny, &scale, &bytepix)) { + return NULL; + } + + if (bytepix != 4 && bytepix != 8) { + PyErr_SetString(PyExc_ValueError, + "HCompress can only work with 4 or 8 byte integers."); + return (PyObject *)NULL; + + } + + if ((nx < 4) || (ny < 4)) { + PyErr_SetString(PyExc_ValueError, + "HCOMPRESS requires tiles of at least 4x4 pixels."); + return (PyObject *)NULL; + } + + if (count != nx * ny * bytepix) { + PyErr_SetString(PyExc_ValueError, + "The tile dimensions and dtype do not match the number of bytes provided."); + return (PyObject *)NULL; + } + + // maxelem adapted from cfitsio's imcomp_calc_max_elem function + maxelem = count / 4 * 2.2 + 26; + + // Apparently with the above calculation we can still end up allocating too + // small of a buffer, this could never happen by more than 32 bytes + // riiiiiight. + // TODO: Do a small buffer calculation to tune this number like we did for PLIO + long buffer_size = maxelem + 32; + compressed_values = (char *)malloc(buffer_size); + + if (bytepix == 4) { + decompressed_values_int = (int *)str; + fits_hcompress(decompressed_values_int, ny, nx, scale, compressed_values, &buffer_size, &status); + } else { + decompressed_values_longlong = (long long *)str; + fits_hcompress64(decompressed_values_longlong, ny, nx, scale, compressed_values, &buffer_size, &status); + } + + if (PyErr_Occurred() != NULL) { + // If an error condition inside the cfitsio function, the call inside + // cfitsio should have called the ffpmsg function which sets the Python + // exception, so we just return here to raise an error. + return (PyObject *)NULL; + } + + result = Py_BuildValue("y#", compressed_values, maxelem); + free(compressed_values); + return result; +} + +static PyObject *decompress_hcompress_1_c(PyObject *self, PyObject *args) { + + const unsigned char *str; + char *dbytes; + Py_ssize_t count; + PyObject *result; + + int bytepix, nx, ny, scale, smooth; + int status=0; // Important to initialize this to zero otherwise will fail silently + + unsigned char *compressed_values; + int *decompressed_values_int; + long long *decompressed_values_longlong; + + if (!PyArg_ParseTuple(args, "y#iiiii", &str, &count, &nx, &ny, &scale, &smooth, &bytepix)) { + return NULL; + } + + compressed_values = (unsigned char *)str; + + if (bytepix != 4 && bytepix != 8) { + PyErr_SetString(PyExc_ValueError, + "HCompress can only work with 4 or 8 byte integers."); + return (PyObject *)NULL; + + } + + dbytes = malloc(nx * ny * bytepix); + + if (bytepix == 4) { + decompressed_values_int = (int *)dbytes; + fits_hdecompress(compressed_values, smooth, decompressed_values_int, &ny, &nx, &scale, &status); + } else { + decompressed_values_longlong = (long long *)dbytes; + fits_hdecompress64(compressed_values, smooth, decompressed_values_longlong, &ny, &nx, &scale, &status); + } + + if (PyErr_Occurred() != NULL) { + // If an error condition inside the cfitsio function, the call inside + // cfitsio should have called the ffpmsg function which sets the Python + // exception, so we just return here to raise an error. + return (PyObject *)NULL; + } + + result = Py_BuildValue("y#", dbytes, nx * ny * bytepix); + free(dbytes); + return result; +} + +static PyObject *quantize_float_c(PyObject *self, PyObject *args) { + + const char *input_bytes; + Py_ssize_t nbytes; + PyObject *result; + + float *input_data; + + long row, nx, ny; + int nullcheck; + float in_null_value; + float qlevel; + int dither_method; + + int *quantized_data; + char *quantized_bytes; + double bscale, bzero; + int iminval, imaxval; + + int status; + + if (!PyArg_ParseTuple(args, "y#lllidfi", &input_bytes, &nbytes, &row, &nx, + &ny, &nullcheck, &in_null_value, &qlevel, + &dither_method)) { + return NULL; + } + + input_data = (float *)input_bytes; + quantized_data = (int *)malloc(nx * ny * sizeof(int)); + + status = fits_quantize_float(row, input_data, nx, ny, nullcheck, in_null_value, qlevel, + dither_method, quantized_data, &bscale, &bzero, &iminval, + &imaxval); + + quantized_bytes = (char *)quantized_data; + + result = Py_BuildValue("y#iddii", quantized_bytes, nx * ny * sizeof(int), status, + bscale, bzero, iminval, imaxval); + free(quantized_bytes); + return result; +} + +static PyObject *quantize_double_c(PyObject *self, PyObject *args) { + + const char *input_bytes; + Py_ssize_t nbytes; + PyObject *result; + + double *input_data; + + long row, nx, ny; + int nullcheck; + double in_null_value; + float qlevel; + int dither_method; + + int *quantized_data; + char *quantized_bytes; + double bscale, bzero; + int iminval, imaxval; + + int status; + + if (!PyArg_ParseTuple(args, "y#lllidfi", &input_bytes, &nbytes, &row, &nx, + &ny, &nullcheck, &in_null_value, &qlevel, + &dither_method)) { + return NULL; + } + + input_data = (double *)input_bytes; + quantized_data = (int *)malloc(nx * ny * sizeof(int)); + + status = fits_quantize_double(row, input_data, nx, ny, nullcheck, in_null_value, + qlevel, dither_method, quantized_data, &bscale, &bzero, + &iminval, &imaxval); + + quantized_bytes = (char *)quantized_data; + + result = Py_BuildValue("y#iddii", quantized_bytes, nx * ny * sizeof(int), status, + bscale, bzero, iminval, imaxval); + free(quantized_bytes); + return result; +} + +static PyObject *unquantize_float_c(PyObject *self, PyObject *args) { + + const char *input_bytes; + Py_ssize_t nbytes; + PyObject *result; + + long row, npix; + int nullcheck; + int tnull; + float nullval; + int dither_method; + + double bscale, bzero; + int bytepix; // int size + int status = 0; + + int *anynull; + float *output_data; + char *output_bytes; + + if (!PyArg_ParseTuple(args, "y#llddiiifi", &input_bytes, &nbytes, &row, &npix, + &bscale, &bzero, &dither_method, &nullcheck, &tnull, + &nullval, &bytepix)) { + return NULL; + } + +// TODO: add support, if needed, for nullcheck=1 + +anynull = (int *)malloc(npix * sizeof(int)); +output_data = (float *)malloc(npix * sizeof(float)); + +if (bytepix == 1) { + unquantize_i1r4(row, (unsigned char *)input_bytes, npix, bscale, bzero, + dither_method, nullcheck, (unsigned char)tnull, nullval, + NULL, anynull, output_data, &status); +} else if (bytepix == 2) { + unquantize_i2r4(row, (short *)input_bytes, npix, bscale, bzero, + dither_method, nullcheck, (short)tnull, nullval, NULL, + anynull, output_data, &status); +} else if (bytepix == 4) { + unquantize_i4r4(row, (int *)input_bytes, npix, bscale, bzero, dither_method, + nullcheck, (int)tnull, nullval, NULL, anynull, output_data, + &status); +} + +output_bytes = (char *)output_data; + + result = Py_BuildValue("y#", output_bytes, npix * sizeof(float)); + free(output_bytes); + return result; +} + +static PyObject *unquantize_double_c(PyObject *self, PyObject *args) { + + const char *input_bytes; + Py_ssize_t nbytes; + PyObject *result; + + long row, npix; + int nullcheck; + int tnull; + double nullval; + int dither_method; + + double bscale, bzero; + int bytepix; // int size + int status = 0; + + int *anynull; + double *output_data; + char *output_bytes; + + if (!PyArg_ParseTuple(args, "y#llddiiidi", &input_bytes, &nbytes, &row, &npix, + &bscale, &bzero, &dither_method, &nullcheck, &tnull, + &nullval, &bytepix)) { + return NULL; + } + +// TODO: add support, if needed, for nullcheck=1 + +anynull = (int *)malloc(npix * sizeof(int)); +output_data = (double *)malloc(npix * sizeof(double)); + +if (bytepix == 1) { + unquantize_i1r8(row, (unsigned char *)input_bytes, npix, bscale, bzero, + dither_method, nullcheck, (unsigned char)tnull, nullval, + NULL, anynull, output_data, &status); +} else if (bytepix == 2) { + unquantize_i2r8(row, (short *)input_bytes, npix, bscale, bzero, + dither_method, nullcheck, (short)tnull, nullval, NULL, + anynull, output_data, &status); +} else if (bytepix == 4) { + unquantize_i4r8(row, (int *)input_bytes, npix, bscale, bzero, dither_method, + nullcheck, (int)tnull, nullval, NULL, anynull, output_data, + &status); +} + +output_bytes = (char *)output_data; + + result = Py_BuildValue("y#", output_bytes, npix * sizeof(double)); + free(output_bytes); + return result; +} diff --git a/astropy/io/fits/tiled_compression/src/fits_hcompress.h b/astropy/io/fits/tiled_compression/src/fits_hcompress.h new file mode 100644 index 00000000000..1d5b2095189 --- /dev/null +++ b/astropy/io/fits/tiled_compression/src/fits_hcompress.h @@ -0,0 +1,6 @@ +typedef long long LONGLONG; + +int fits_hcompress(int *a, int ny, int nx, int scale, char *output, + long *nbytes, int *status); +int fits_hcompress64(LONGLONG *a, int ny, int nx, int scale, char *output, + long *nbytes, int *status); diff --git a/astropy/io/fits/tiled_compression/src/fits_hdecompress.h b/astropy/io/fits/tiled_compression/src/fits_hdecompress.h new file mode 100644 index 00000000000..002d51fecbd --- /dev/null +++ b/astropy/io/fits/tiled_compression/src/fits_hdecompress.h @@ -0,0 +1,6 @@ +typedef long long LONGLONG; + +int fits_hdecompress(unsigned char *input, int smooth, int *a, int *ny, int *nx, + int *scale, int *status); +int fits_hdecompress64(unsigned char *input, int smooth, LONGLONG *a, int *ny, int *nx, + int *scale, int *status); diff --git a/astropy/io/fits/tiled_compression/src/fitsio2.h b/astropy/io/fits/tiled_compression/src/fitsio2.h new file mode 100644 index 00000000000..35bfb4a61ae --- /dev/null +++ b/astropy/io/fits/tiled_compression/src/fitsio2.h @@ -0,0 +1,57 @@ +#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 + +# 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 */ + +void ffpmsg(const char *err_message); + +#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 + +#define N_RANDOM 10000 /* DO NOT CHANGE THIS; used when quantizing real numbers */ + +#define MEMORY_ALLOCATION 113 /* Could not allocate memory */ + +#define NO_DITHER -1 +#define SUBTRACTIVE_DITHER_1 1 +#define SUBTRACTIVE_DITHER_2 2 + +int fits_init_randoms(void); diff --git a/astropy/io/fits/tiled_compression/src/imcompress.h b/astropy/io/fits/tiled_compression/src/imcompress.h new file mode 100644 index 00000000000..6a3e09a38a6 --- /dev/null +++ b/astropy/io/fits/tiled_compression/src/imcompress.h @@ -0,0 +1,90 @@ +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 */ +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 */ +int unquantize_i4r4(long row, + 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 */ + 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 */ + int 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 */ +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 */ +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 */ +int unquantize_i4r8(long row, + 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 */ + 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 */ + int 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 */ diff --git a/astropy/io/fits/tiled_compression/src/pliocomp.h b/astropy/io/fits/tiled_compression/src/pliocomp.h new file mode 100644 index 00000000000..a648da7ee70 --- /dev/null +++ b/astropy/io/fits/tiled_compression/src/pliocomp.h @@ -0,0 +1,2 @@ +int pl_p2li (int *pxsrc, int xs, short *lldst, int npix); +int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix); diff --git a/astropy/io/fits/tiled_compression/src/quantize.h b/astropy/io/fits/tiled_compression/src/quantize.h new file mode 100644 index 00000000000..3c35047ba8b --- /dev/null +++ b/astropy/io/fits/tiled_compression/src/quantize.h @@ -0,0 +1,7 @@ +int fits_quantize_float (long row, float fdata[], long nxpix, long nypix, int nullcheck, + float in_null_value, float qlevel, int dither_method, int idata[], double *bscale, + double *bzero, int *iminval, int *imaxval); + +int fits_quantize_double (long row, double fdata[], long nxpix, long nypix, int nullcheck, + double in_null_value, float qlevel, int dither_method, int idata[], double *bscale, + double *bzero, int *iminval, int *imaxval); diff --git a/astropy/io/fits/tiled_compression/src/ricecomp.h b/astropy/io/fits/tiled_compression/src/ricecomp.h new file mode 100644 index 00000000000..5669e2b965c --- /dev/null +++ b/astropy/io/fits/tiled_compression/src/ricecomp.h @@ -0,0 +1,6 @@ +int fits_rcomp_byte(signed char 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(int a[], int nx, unsigned char *c, int clen, int nblock); +int fits_rdecomp_byte(unsigned char *c, int clen, unsigned char array[], int nx, int nblock); +int fits_rdecomp_short(unsigned char *c, int clen, unsigned short array[], int nx, int nblock); +int fits_rdecomp(unsigned char *c, int clen, unsigned int array[], int nx, int nblock); diff --git a/astropy/io/fits/tiled_compression/tests/__init__.py b/astropy/io/fits/tiled_compression/tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/astropy/io/fits/tiled_compression/tests/conftest.py b/astropy/io/fits/tiled_compression/tests/conftest.py new file mode 100644 index 00000000000..dff152018be --- /dev/null +++ b/astropy/io/fits/tiled_compression/tests/conftest.py @@ -0,0 +1,97 @@ +import itertools + +import numpy as np +import pytest + +COMPRESSION_TYPES = [ + "GZIP_1", + "GZIP_2", + "RICE_1", + "HCOMPRESS_1", + "PLIO_1", +] + + +def fitsio_param_to_astropy_param(param): + # Convert fitsio kwargs to astropy kwargs + _map = {"qlevel": "quantize_level", "qmethod": "quantize_method"} + param = {_map[k]: v for k, v in param.items()} + + # Map quantize_level + if param.get("quantize_level", "missing") is None: + param["quantize_level"] = 0.0 + + return param + + +def _expand(*params): + """ + Expands a list of N iterables of parameters into a flat list with all + combinations of all parameters. + """ + expanded = [] + for ele in params: + expanded += list(itertools.product(*ele)) + return expanded + + +ALL_INTEGER_DTYPES = [ + "".join(ele) + for ele in _expand([("<", ">"), ("i",), ("2", "4")], [("<", ">"), ("u",), ("1",)]) +] +ALL_FLOAT_DTYPES = ["".join(ele) for ele in _expand([("<", ">"), ("f",), ("4", "8")])] + + +@pytest.fixture( + scope="session", + ids=lambda x: " ".join(map(str, x)), + # The params here are compression type, parameters for the compression / + # quantise and dtype + params=_expand( + # Test all compression types with default compression parameters for + # all integers + [ + COMPRESSION_TYPES, + ({},), + ALL_INTEGER_DTYPES, + ], + # GZIP supports lossless non-quantized floating point data + [ + ("GZIP_1", "GZIP_2"), + ({"qlevel": None},), + ALL_FLOAT_DTYPES, + ], + # All compression types can also take quantized floating point input + [ + COMPRESSION_TYPES, + ( + {"qlevel": 5, "qmethod": -1}, + {"qlevel": 10, "qmethod": 1}, + {"qlevel": 20, "qmethod": 2}, + ), + ALL_FLOAT_DTYPES, + ], + ), +) +def comp_param_dtype(request): + return request.param + + +@pytest.fixture(scope="session") +def compression_type(comp_param_dtype): + return comp_param_dtype[0] + + +@pytest.fixture(scope="session") +def compression_param(comp_param_dtype): + return comp_param_dtype[1] + + +@pytest.fixture(scope="session") +def dtype(comp_param_dtype): + return comp_param_dtype[2] + + +@pytest.fixture(scope="session") +def numpy_rng(): + return np.random.default_rng() diff --git a/astropy/io/fits/tiled_compression/tests/data/compressed_with_nan.fits b/astropy/io/fits/tiled_compression/tests/data/compressed_with_nan.fits new file mode 100644 index 00000000000..5a1f6a4ba4c --- /dev/null +++ b/astropy/io/fits/tiled_compression/tests/data/compressed_with_nan.fits @@ -0,0 +1,2 @@ +SIMPLE = 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 is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H CHECKSUM= '2cH54Z932bG32Z93' / HDU checksum updated 2022-12-13T14:49:19 DATASUM = ' 0' / data unit checksum updated 2022-12-13T14:49:19 END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 24 / width of table in bytes NAXIS2 = 4 / number of rows in table PCOUNT = 106 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 3 / number of fields in each row TTYPE1 = 'COMPRESSED_DATA' / label for field 1 TFORM1 = '1PB(28) ' / data format of field: variable length array TTYPE2 = 'ZSCALE ' / label for field 2 TFORM2 = '1D ' / data format of field: 8-byte DOUBLE TTYPE3 = 'ZZERO ' / label for field 3 TFORM3 = '1D ' / data format of field: 8-byte DOUBLE ZIMAGE = T / extension contains compressed image ZTILE1 = 6 / size of tiles to be compressed ZTILE2 = 6 / size of tiles to be compressed ZCMPTYPE= 'RICE_1 ' / compression algorithm ZBLANK = -2147483647 / null value in the compressed integer array ZNAME1 = 'BLOCKSIZE' / compression block size ZVAL1 = 32 / pixels per block ZNAME2 = 'BYTEPIX ' / bytes per pixel (1, 2, 4, or 8) ZVAL2 = 4 / bytes per pixel (1, 2, 4, or 8) EXTNAME = 'COMPRESSED_IMAGE' ZSIMPLE = T / conforms to FITS standard ZBITPIX = -64 / array data type ZNAXIS = 2 / number of array dimensions ZNAXIS1 = 12 ZNAXIS2 = 12 ZEXTEND = T ZQUANTIZ= 'SUBTRACTIVE_DITHER_1' / Pixel Quantization Algorithm HISTORY Image was compressed by CFITSIO using scaled integer quantization: HISTORY q = 4.000000 / quantized level scaling parameter HISTORY 'SUBTRACTIVE_DITHER_1' / Pixel Quantization Algorithm ZDITHER0= 2961 / dithering offset when quantizing floats CHECKSUM= 'Qa6JTX4HQa4HQU4H' / HDU checksum updated 2022-12-13T14:49:19 DATASUM = '2516956193' / data unit checksum updated 2022-12-13T14:49:19 END ?àÆîð DAÐÆí£?àÆîð D@ZŠ>6?àÆîð D@QôC¼î3P?àÆîð D@S†’ +#oq€ $fV`À GV ®ÌÁUÕ˜+3«p‘DÈ€dDD"" #“"0DHl‰€FLˆDDÀ""&6`6ˆ̈€FDÈ&D@#d2"`ˆˆ \ No newline at end of file diff --git a/astropy/io/fits/tiled_compression/tests/data/m13.fits b/astropy/io/fits/tiled_compression/tests/data/m13.fits new file mode 100644 index 00000000000..1f2f82a4f18 Binary files /dev/null and b/astropy/io/fits/tiled_compression/tests/data/m13.fits differ diff --git a/astropy/io/fits/tiled_compression/tests/data/m13_gzip.fits b/astropy/io/fits/tiled_compression/tests/data/m13_gzip.fits new file mode 100644 index 00000000000..cf7acea4eac --- /dev/null +++ b/astropy/io/fits/tiled_compression/tests/data/m13_gzip.fits @@ -0,0 +1,366 @@ +SIMPLE = 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 is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H CHECKSUM= '0aE73a960aC60a96' / HDU checksum updated 2006-11-15T17:28:30 DATASUM = ' 0' / data unit checksum updated 2006-11-15T17:28:30 END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 8 / width of table in bytes NAXIS2 = 300 / number of rows in table PCOUNT = 111820 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 1 / number of fields in each row TTYPE1 = 'COMPRESSED_DATA' / label for field 1 TFORM1 = '1PB(506)' / data format of field: variable length array ZIMAGE = T / extension contains compressed image ZTILE1 = 300 / size of tiles to be compressed ZTILE2 = 1 / size of tiles to be compressed ZCMPTYPE= 'GZIP_1 ' / compression algorithm EXTNAME = 'COMPRESSED_IMAGE' ZSIMPLE = T / file does conform to FITS standard ZBITPIX = 16 / number of bits per data pixel ZNAXIS = 2 / number of data axes ZNAXIS1 = 300 / length of data axis 1 ZNAXIS2 = 300 / length of data axis 2 ZEXTEND = 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 COMMENT COMMENT This file was produced by the SkyView survey analysis system from COMMENT available astronomical surveys. The data are formatted COMMENT as a simple two-dimensional FITS image with the same units as COMMENT the orginal survey. CTYPE1 = 'RA---TAN' / X-axis type CTYPE2 = 'DEC--TAN' / Y-axis type CRVAL1 = 250.4226 / Reference pixel value CRVAL2 = 36.4602 / Reference pixel value CRPIX1 = 150.500 / Reference pixel CRPIX2 = 150.500 / Reference pixel CDELT1 = -0.00027770002 / Degrees/pixel CDELT2 = 0.00027770002 / Degrees/pixel CROTA1 = 0.00000 / Rotation in degrees. EQUINOX = 2000.00 /Equinox of coordinates ZHECKSUM= '2f4R3c4O2c4O2c4O' / HDU checksum updated 2006-11-15T17:18:55 ZDATASUM= '1803906202' / data unit checksum updated 2006-11-15T17:18:55 CHECKSUM= 'CeA6FZ03Cd73CZ73' / HDU checksum updated 2006-11-15T17:28:30 DATASUM = '3567348586' / data unit checksum updated 2006-11-15T17:28:30 END "/"6QO‡SÖP)SyKÌ7 +- N { ˜´ÊÛô& )2&[/°Ëá*ý*',Q}"› ½-!Ü;# 9$D6%}8&³-'ë)*-+? ,]$-}.¡/¼0Õ1ô3 4*5J?6gQ7¦p8÷e:gi;Ìg=5H>œ8?äA"B5BCWYD™iEòG[zHÚiJThK½nM%rN“fPaQkjRÌ{T6‚U±‡W3…XºrZ?_[±m]o^}}_ìˆai~bñ‹doŠeú”g„„iljœnl†mvžnüÏpšÁri¶t*ªuà˜wІy"”z¨}|<˜}¹•Q‘€æ‚w„›…¡¬‡<­ˆè®Š•­ŒC¬ðœž‘9Ÿ’×£”v±–¸—ÊÆ™‚á›HÔ)âžýÌ ßÄ¢«®¤o·¦ã§Ôß©·é«–Ø­ʯW±±!Ö²Òç´¨ضà¸gÚºGÙ¼!×½úî¿ÑúÁ¿òùçÅ«æÇ’êÉxØËbØÍ:åÏåÐ÷áÒÜÝÔ½àÖšרzÒÚQâÜ#ßÞÉßäÄá­§ãq·å½æÏÃ茸êOÓìåíÚæï¿ðñ¥ôó•ôõ‰ê÷}ñùgçûXÏý?ÙÿÝçæÄǪÍqÇ>Ê +Ê ÏÊ ™µcÔÈ츴³l¸¶×´®A¯ï˜ ž˜"6¢#ÎÀ%pÌ'0Ê(ü¹*Ư,˜..„/ƈ1J‘2Ò¨4cÂ6 Ù7ÍÇ9¦¾;m´=+‡>ßl@flAÒoC>qD­zF‰G˜‡I!zJ¨kL"{MfOqPntQßnSSoTÁˆV0’W¸›YJ‹Zå€\p’]ðŒ_‚xa{b†tdbeuXf×Dh/@is0j³GkãRm*Qn|]oÍbq*\rŒ^sècuF`v©Kx @yT>z”;{Ò/} (~<'d€‹£ ‚±ƒ¾ù„̅ņƇˈˉъà$‹÷).ŽD,r4ž@‘Ò9“9”K3•„ –·—×(˜õ,š6›I"œ¡ž½ ŸÚî æû¡Ô¢Ï£ß ¤ô ¦ §  ¨© ª7«U¬cù­e®^ü¯_°["±c'²… ³¬‹…”;n1†‡3pŽH´\ +²ï.«M +"%ˆ‚"}DA“ ä¹GRå7Œ•Ñ Å§õc^þwly” ™Âs^÷䆨¾g¬°_Ap?.A &úu:žø'°SЀJýB\§¾2’'7ù¼ÿ3Xƒw°/&¿ßïÀØ€•îwºWQŒSÂi¸×1œò9ƒ)À ¼bo<ìžáÜ+4uí†â¹Eï57æ%˯Ïgqjû—˦rîÚxå2Îéßñ>®àž`žÎÍk]>´žò’Õ[Vгå³÷Æñç+öónbž2Ù=©ûÎàõ°a¶¾ o0B{ý/paCÝÌ+qÆukù×}žïà.m¨M­—}¿YïÑ.Å÷ÿ݇è~û8ŒsÉ;)¬›ý¿ˆâŠq~·¿?°½i°‹…”±NA†Ð’ðLT< êÁrw cb°1†( /@G …=¾O`eÅ¿òO²o¤ør·»3;3ÿ̈dr¦Gîˆîëú6!“¿~ž½½¯gðìûd +ð>EjxÖÛ ‰÷ö¶à ÉxKúLèœúRb¼¼‚˜3~ ¾ÁÔ°·SÚ’'k­ÃÖ­è¹úZ]<}S=CBU¼@ +êÙ75ÛøvÖ6ãYI¡ÀØ€{P$þª‡ÆÏ¥ºÎKó¡yÆ;îÙóȘwþ—oÚ«“‡×§‚5ƹzGÌÁ^¤±¹náùƒÙ¼Âþx§NñçÁë×ÀÄŠµNYo™hèéfçF¹!]bÏ/õCQ½ã·ñ rþw¯÷Q4/›çïúî|Lϰ‹…”A.Q†Ë„cØ:‡p K‘ û½îi†LÌYÌŠ°´ ±`cao!n`é áü-%•ßôX|é®zýªþªzýÌ,™YvIAJâþmâv)Gã©ý7ƒ}p¾Ì^Ìz`ï[ð=‚c0'༂wð θ?uÄWýIèƒ!¸A¾eä]Ÿ`ö:ü÷` PƒŠ{jjw’hp[×Õ®H¦Îâ3h×öÀ!{P‡oË£aúô•aÔ«õk2¿mk¾dÿŸÀ5çÐØßÚ3sD¢Æ?Î=ËÌk=2d<í“ÖßÕß.fÛÄúÀœƒ7œƒo³ÅU³¥;<‘«·ÿ×ÇœK%èù‹z]gMÆÌèoÔãë9Ð>ûÿ<¯^ŸGÔ¢ùÚswj¿ÿ‡])g¤÷ŠÞ]÷ÅÜ{㞊~°‹”=NÃ@…‡Ÿ’ +Z åTˆÐq vbÇ#ˆ" A + +(hÜ.@…¸ Ÿ¥7ÒjdÅ'g&Þ™·oÇkf¹™õà@ôD&<¿'<νP'Ö‹ñ_xÝ>Œá>ÍæŽÌæWx~ùg¨ánà‹üìÂñ›þÏ;êGýN.J˜ÀõÖè½ °C¼MþN` ´¦v'<.’uƒ–÷Ó|£s_¸7øa3¸„)ŒBïRÞÔò± +}Jå +k×ýIûžÃ<•êÇ};•tœ +×ÙV?KÖÅ3©ä÷LL´‡è“ãú¾¢¿]´Ím®sn´ŸÁ5¼3x¿°j¶¸Îs“ø•<3bò)ÕçÄùKõºÎBýÆ:Û©~;öá³×ô<Ô{ÿó®ï´¯Zµðùñ~M¯föîáNgR%5»î®ûâ×{ãþ‰µ°‹”½JÄ@Ç÷lm| ñ©|c’Í}ä¼Csj#‡"ˆ‚ØY[ê#øbkcå/ðXÆËiñ#Ù™ÝùÏÌNBÈCl‹Lì8¼?wؾÌáýFk+¡]þÂ<Âg½ Xãý æ0† \Á7>Îöf°Éú ˆÒñùÎn˜½=Wà ¼s ^ Õû€3éGQºº|ü"ÙÛ‡‘ÎTk_ØžJXÜ4ÇJ½¹„k8…=&ñõ®õŸÃ¾tÒLÏ߃¯!õ[_fÊaª8¾þ¨|éßÃÞëû­6o·u¥^ME-]>£ÿ¬KDzy«îc¸ƒ/æºVÖy>Ã*¶›¤'qAüesgw3Too¸áUzÉWI¼¨Þ´³¹«=]whßç_}³š«^??鉉rÊÃïAJ×ÿÂëçi¬RZ*°‹ÔKJÄ@àšûx/â<€1Éd&ãû‚ Š]ˆ¢‚èF\xÁ…K·Š'âÚ¿™¿°ø‰ÅÇLº“êªêN̬4³¨ E¡ó¥ðû +¡ó.UHçó\ ˰ Gp gpÍß çÃ<™õf`ÿ?àV Ïu4Ÿ$ãÎÇósX…Cx€·é:vÊñ:Ü_I]ßczÜœÿ&ãŒ8Õäq=Nź·™WîÍ>¬Áñ[8€;¸‡örrˆt’Ì¥Ž¹&ä­u&Ž·Ì-çñ¯p [¡>_'ÖûX‰! ¬»ÏñœýçZãk½~OÍz×Ùû8Gx‡g¸bm¾]ùÿvîú|6ïå|â<ÏÁ<ôp}K¼¯ñ|?Æì¹ö&Öäïç_}Ë16lúnMXwöË÷¿¥Æ¾Ï©~ ¢Ÿ¾º~c}Fp|°‹}“MNÃ@ …MÁ!8 IšLÚŠZñWX‚8g`Á{®ƒx¦ÏŠe&]|J2ñß³="RȆ1Ñ÷ +L¥ôv…³©IE›ÒÅ)é›ÈÄÙ”ôñ”Χ¡OÎÀ܃;° 0G ¥ýœ‚Gð +>À3¸à?«5æ¯0틯9¯X‹ÖtÂü¾W>FÔX…¸-k^ñÙñ¬¥¶9ÏRÈayýTã5X‚C×?õb/¾Á {ØetæúS;ýC:†´šÆûô>ÁÈÎÏwpÃZ¦ÒïIúîϛ̹ß+ߟ¸W‘8ÿ”Áôû¸‰õÚ|ÝÇKpKM‹-s‹äêIœ£Îô ýÚí‚=¼«ísl«ÏîEì}˜ßî·kŒcÙìÖ’³œIΉíªÝ5«ÿóÈå‹÷Çïßý/ÒÇH°‹u”MJÄ@…{<§gPc:=™‰ÿˆ¢A\ºu-ˆ Áx—.<†¯÷˜G‘^|Tª«^UW%¥t6ì“ú|Òƒ.mýD#)ôé,N}^‚#²²Xs8½10n=w ÎÁ%¸ ÍóJc¦í\ƒžùMybþÜ äPóÒrG¿rÎÕ9Xj]'wgf/3y¤Ýû4™®LûxŸàÜZO¼N½{rÚÎA«Ž¹õ]5Vm÷àü€_ðF-UãÚXñŒP¿‡@±¾Hsìßw$޿⩟kËÛšùŒÔ=™­5G‘9=…±îÀwJ ÌþÎ.@ÜÅ#l_i³>ÿBÚ4±7zß#1¿öÛÏi&'«ó +<ƒÞë5ù¾ùÿ¢µž/î×÷ïÿiæ°‹“ËMADÛÁÙ Ýõì¬`þX²á‚o\‘àJœ Á‡A ÔHåfVâð¤ÙžžþT÷šYeÇÔ` :@C{Ís—`Á˜ˆoÅs²-y?“û†9-óLI$“‘þ­¼Ï4ŒS >ŽGû.½+õ£5Öãk |7ÝæÔÇçÑï¬a'úeÒœžÀ X3žêœŸ=Øqþ`åyf{®)rö7à¼Ø‚pKîíwŸVàÂþîƒ×½o~}󩬼ú¶£îwà,hó3õ}¶Rgþöºøz<~gÔâÃl0Ÿ`Na{ç\u.ºÿ©îsÑO}ò–þûÄÑ;wêPÏœàüÅ™ÎÙ‡ÿßü¡‡Ÿûo(ïp°‹“»nÂ@E—ÔÔù~,²Û˜G@Q ˆG(ÓD¢JOOÏq7¹#M†1¡8Z{ç¹swC1ü’‘tA´ç$}ÀÀX‚‘ò͸V`žS(J’jô铨i¯ˆŽ‰ìÍ#*? Ú^ÝÈ—tþÂÔÕ}•Š[yÒ9Çœ›œYòÈL†\K§Žüç¦nåP›\úœMó°ûvþZo_´•xÑø¼“9Xø{ðAß~¸¾¶ŽÕ­I«ŸŸú}3ðF}zަ^ÿî…×OtüìýØ‚S­ÐÆ÷lÂß÷¸ 5·ï@îafý'¢m6ÿÑOàý·Và{߬Ûuòß[¿i>?ö mD> +°‹…Ô=NÃ@àá.܃A6‰M~ˆ¨…’! + +*ꈆ«å-~#=ž¼¢ødÙ;;;;^;"æ1¸„)¯õ¾£3¸ :¾‚Wø‚<ÁFrT眷¤\#óçóžù®©çøŒrNÞkš³Ç«Â57ÔKÍ}xÉÇ[õNHãp{¸…-Ÿ™7o(7Y×ûâ²íÛBhžÚŸ«ø{Z}ñ<úÞUÇœ¹ÿGx†wøäuÏžt"ûãÆú2Æûãñy¿†] çc%ûñøÿÎ÷Éã<_«Oµ÷ðoðÀÚZïxɺ³~ý¶µýN«±sªç7÷PÏÄüDœœÁ7|Ài ÿ‚㦠¾~æ÷:¼žßñ#c›‡“°‹}Ò]JAàñjÞÀ‹¨Éκ»Æ@‚?"j@|ôpÞAR“TASôúð‘,ÛÓÓS;¥”¡u°ào#UXµ÷+x…oø‚'˜Bæ’º ö—kW¤Y–Ô%Ï­~MZSÉë£Êú-­9CV¯søñ,‹dï¯T_™ë¼Á3là*dûÄœâ9ë̾sæ¾KåÞ¢ýZ6÷œsÙÿËE}to4ooTÓz> ìà>˜É\‡^cÈÇ©o–I–×;å0ÌÔeçÎîçäuÞÏs™ÜÐj²ïܳf +gÈÏÉï©ß_¡õ¼…ø+åä Nñÿ>9c }œï¯þ>‡Ïsx¿êu2°‹”Í +Â0„÷‰ýkLm+õ_¼‰^¼z|>“…em(xø(I6“Íì¦"D$‚ IãX‚-h¹^€±‰Y€؃9× £3Πë…#òÜ)Ç#bãÓZvà ®à6Ü™[èÐ×ý X5ï¦ç‡ŸŸ:ü}ý½ý¼Í¡¤·Gz¸0šC¢:vOÅoùGvŒN$ªYÏäïÜÁE¾ýå×SëOÒ«¹¿2z^?2®e-V¬áŽçÔ&~ÖQÛ.r>äú­0úµñ4×?^'w®úåtúÞã€äúÅ£o(õmêx‚›|ÿšcß{èóËûö‰{¹“ ô°‹•ÓMnÂ0à9qšUÀ]U°èX·¨z $6ܤÏí{b:‚.>EN&cû%6³'3«ì÷š´°„78À0†Ò.õ tPs<"õeäžWì¥y +Rý˜sÎaŸp„/x…k¯]Ÿ(½ßÃŒõ7_E-5|¦û±Wéòðâ>EõZÇ”¹Î8.ùÞ#©Oi×/ÿ]G̹§6ì/×ðg8Á;løÌï#æÓ0Ó´·Ž÷ô=´n}Îâÿ'Í£ºÚÍuM.‡˜¿—Ö7ð;ôa?±6öÉÍ«œ‹ ·žš™-hÊývÿCßCçÐç*±>wèÞó«ÜR^+x-<Ûå_ºç<ÜÊ+æöS÷ KÍk°‹Ó9nAÐò8+0ݳ c±Ø’"‘CBäÀ™%¸ƒ@†}<¿¤ækÚ&xz©^ª 3[§€SXþàVÐp\yüˆÆBû +äíj +œ;ä7$ã/°…“ÙÃß3ì` -L` xb_Íó?Rþ²ç>¾F›w!Ãï£÷õ¸’*ò8¯y çëh¼*Däý§äïêëµ|ï#|Ã>áÕnk Ê˜Pöϭ3ü¾¿ÖG•¬“öë½5ÿ¾oºN#çºþžÁ³uµRõì¯yÖ÷ÔÿÁ=ùOsx}ƒ7ØÃ;l¬«ÝôœÑúë*2‡^ã}çÔ¸¿Îíÿšò1}WÝw$rùÐóåâ~Û?ñÌõ°‹}Ô;NAÐæœ»­×Þ±ù + °Csû@†Dà +$Ôà*i(v¾eÚ'ÝýÏqʾžíç±}C÷«ºx~þ.Jy Õ_ù¥=Ó{}ØÛ‡|Á‚}müwþ{Õy-w½£!Z/_g×øÊêäç­L©¥ÿŸ÷ÿê(H@°‹…ÔMNAà➀KxNCÀžéa@4*‰Q6lX`ÜjB‚a-×î8¾vªHó,pñ…a¨ôÔ#"=iô!Àžà¾à  €+ z뫞ËË拾GpS¸Aö̤T)¿Gx‡-¬`ýüiµá×{ØÀž?†*=»pê)H™ ÎïìT‚žÁqÖ@çÛwî!÷Ù›ƒ=+Ï›ã*êƒÅVÚ«gx…öûb–3×c¢Î.’ª•Åp~ÜÃùÞ3‹¯µŽ¡æžjXÂ+Ì¥Ù±:åx¬ü|žWI¼\½}JõßÊïþ¶.` ;èàÞ§4;åïžðœ-ëó©y{ÿ;/O®ÛÛçÔë®úo.^Þçxïƒp”Ïk°‹…ÔMNAà’;xWž€ÃüáOü‘°† ·Â¥·pëÆ ø:¼2åK ,¾3=]Õ¯{0³‰íM¡‚na X Ìà‚c*~¦4Idãâµ2÷5<à <@jƺ û)ãV°`¿ÅÎìä >áʘo®ázj9OQSìÅuòL-÷3CùT|ÞëVtÍPsÎöÁk¹¬¿çõüwˬîà‰¹Î™…÷kèú›06ê$O£ýiNûw1‡Y¨×sW¶?/å ¼Âl¹¶ÞòýçBë{þÞg-´×˜IÇ|[~¿‡wœÓsø2âsŒkðhÿω¾7ÚƒÏ?´ßÙ{§â9Ð÷#æPòÓ±}Éú>$ûÿøó ÷צ°‹”MnÂ@ … ê¸ +nÁaH˜LDK‹6‰â,Xp°^ oijj ,>ebÇ¿cGD +¹¥ ˜ƒ5X‚O©SÆ âslä£ ª÷ñ +Ú§˜ßà‡ñÒ{`ŒŠç’çLÉ„$»“Hg(ÒíÎðù–ß$Ÿ-Q»Öø¦žŠº/æ5¥}ù¾”ûþXy ½æ¡½ ìmåüz9¿¯â{…“kÜHÖšîÁ»¨>Èíý{jÓ#ïWk·õ>Ëßú °óL¬ÈXéîfdv`6r—ÖÕ£1m ¾Ÿ¹þçôꯑÿùÑ~¦üàs +Yçúx?Ëuæâq´ê_{ê÷ÏîšÅî½Îi4yê}Ùy/ä~¯sõçö>÷Ÿxʾv®°‹”MNA…Ë —ó02N÷Ðóh&²0aÍšñn<ƒWð_%Å£#,¾ÌtÕtýטYc—ÌA^À¼ƒ5eÏÔŸiAæ³¥.ê׫¿'>( 'YÄûî·–à`ö0à!û8Û†`çLû‰ï™>G°o¬ÇDyü^ówT^xU±£y¦Š=ï^ÿj¯µz¾^Ç1zÞKÆåz·g}¼ž AíÚ.<»þ¿øsÅN$æŸD7±g¯ÌÁsÚÚßÁžµÒ¾Õð>Fûg¹îŸï›Þwyœ³8Þ¯8o]ïuÜ›ÚëÞßú_Tùfqä9°‹…”M‚0„{b(@ð'Æ ÷žÀ›x ·Âi2/¾Œ_å½étZBX„oJÐ#ÉÏ(¤&‚†Ô®¦à÷rB[™“‚ýµ"I$R¯ZóÑ‚¸ƒ'x¸q #؃-Xƒ©VåæÌz°£nÎ`é¼xo~Ìðz‘s Ô멟8Í÷Öe©z-ûFzѺR°q¿?VŸ&°ï ×9Îi4.—=søn¨/Ó_RËr´ÜÕ·?S´Ÿ»®oͽîéËöÛz}½ï×\tå­žm\Ï«®/{Égâ®àLï6þOª£X½þgª£þÔ§æókŸŒÄœó™8…Ͻ‘þôÛ1›ðòÅm8S°‹…“ÁJÄ@Dç‹ÕLœL6F×]\Ae=xñ<ù~™5K5”e‚‡¡»§ººg’RºHÉ ‚+Ò¾{ÐYÍ%ó[p-u=óyAÛ9:ž-ÔVB«“ºèÓò˜À=xoà ÜxÏà@¯#)¢Õ‹V䛿 6â+KÍD‰Í²·ðßâ7à–ù‘õ…D¿º0‹?€wðÁùv¦¿FÍÐ(B¥Ç˜» +3g8p§{Îõî?ô7Üû–»‰½Ç;‰ú¸‡²Â( rÎç‹~êm–»ŠzŸß÷¢ïBçɆ{ޏ¿WŸOßî$ûóóÚg‰ÎðÿÌu\ͧׯùh»}Ÿà|#÷?¦ßÿq6ýæïì§ø»—e°‹…”KNÃ@D›cpIˆ±ã±@æ#>(kv!Ë%7áÔ*¥)ÅbñäÑLª{zçñ—i í7¤î-Á5¸7`¸01ŸGñrÞ%iS åÔy!=‘Ï.Áš¬ÀÞÀ;¿µŽôiÝ?HOÏØWÌ£xw`^Ù“~=ײˆï÷´W­…q>À'ø[ðÂüª[qJê÷²MZ¼®Ö|†OŒ¬µêy$ûíú»”«O¾ê—×é>~¿²Ëu–ä£:;ËWçó<ó^ž¨·Ê“5äûv]>çYGÕ©yÒ¹×é~:ÏóžñwéoÌíΈëð¸sÌÅ?VWíÇCìçò;âä`»ØÏÈš6Çþ#®»‰Ãü­âð~~Ïk°‹”MNA…˽Wð$ÞIQzf@6ˆ?‰ 7,HàÁ… âÒKðÚ¼‹JO`ñe¦§º~^Õt›Ùµ2 7ø}F àdÀm``Çóh­¸#¾+†r–s°"%wC[aL2)¶xïà…ë ÉôS©Gƒâ&GÃ-¹¯`Ö¬¯s~±.ѹz´WzJÜ%ø?à|7ú©W>Nëü}/ÕÏTa|T›´e>'Ô9'Sî“®Ø#?ù·ÑÇLJù6NWœ·ìªsÁÙïØÃ-x¤­­äñuøùǺjöäz­ÿIö¨3þ_qßùós¬ùkß9·¾ø5]™=þ4;;—àëoðl‡çì”ûE÷ÊÔþÏÏŸ}š öS°‹…”9jAEÛÐUmf׌¼ B‰@ @Êœl9têHÇÐ|ÿÆ¿ðwÑ£ ÍTW×ò§ºCWá?Óf¤ h¸F{FÌ/'™cæ0»ù—D}bްà lÁ ÷ŠD}+ú<‚;Ѓ–ÔÜ·¼©zÊ„%½ÏI̱°KÐI/FÍs cv¬©-5ïx_à^»•:4Î\ô0¼.ÞžêWëê¾­Ó -sÉã5ÈÏøµßzñ¨–­Ðó?Ü“¨Ý&üÎÊ'xkp+ñÛæFç´pyµö2Ñ¿ŸoóÓšgè^¨_j>ý9oÚºþú}ÿÔoAmO!\L°~ƒwêß…¿÷aì}ɨS| _ÁµtGº;Ú Åà™Ûã5!„‡Ð÷xÇÓ€RâS²XASÇ×°qËTŠÞà®pXCbÎPÝ‚ñZT"ʼ~=‘9 Y~¢:~fKØÃ0“½D©gëh˜ÓQͺ–—c+8À‘ò÷9ã¶[c+5´wzVCã~¿yÞgx¡éo݇7#ý,Þ¶žÈsÒž(í¥õ0çoà>á^Ù¯/ø…츷Fj뻑dÚ7WßÓJίrû6þÜ“›Çß Ncï§ÎÅÇîŸ?ú?Hìg¾›ßpf¯¯Bÿ?â?þÎÕ|6OnpÐS°‹u”ÁNÂ`„—GðEJ[(ˆ &¨'!<Þ}ãÅ3óÃN2™´‡/íÿwÿ™Ýí¶QEÄ Ü safTÉ|$Î׌_•Áså¾Ë¤ÉørÝ€øÿÉ7Øç™:ãš¼¯E·¶çÔm®5§:sè$—VX‡de{`múÔå:ø,Å·h=gðšµöÛŽà>¬È_Ÿ3ŸÒëmú¯s]Ø%[˳Ï}Æ{?ý½ûR—ï‹:¬›ûžßÂ|µÏô§‹á9b®êÁ¾ûüóŒÂü»ë¯ã5°ŸîS4§úî;•8~GåÝ—9}/q›Öèÿ‘1¨éu_ý.¦»¶7°‹…”=NÃP„®Ã18} Á‰íØI”!h8D:.@IGAË…£i4r øŠ}ïíì¼}?UÕTÕ +ÜKð@Väž(^šÏXë×$uSoòÓžxο€7ð>Á ™³±¼ŽZ®;Ñénˆb÷¤õ½åHgÃ[Ò™ÖmЄ–Æp ;0‚=Í‹üH¿ ´¦ oêÏ_^ÕÿÁöÖÓϑ쬆æô¸5êež»bÝ ×É:¹çuÔž|>ƒ÷ª‹ëªË+ð nß`ü¼‚GjÖ3ùÐ9ä¸ãuÇ™óð{•÷HùÙk½?ÝSÏqä!ßݹþ&šoyNOdÏ󒟬qî½/ˆþŠ|þ^üÿøEÍïë·î*¹êT°‹…”ÍNÃ0„¸õM¡&V +\ù¹ ÎH<W^Š ‘–Q"ŸïƳ㵈h#¢€K²Mâ-ß›”$ÏY%”Ë1éi¼4*XƒŽõ}Þöà ¼€{p•ünÀØÚüBÍ1~›òÒò_è¥ç³Nä+ñ~Ò¤5I£1ãcGðʵí¹Þ.Q“F3SOã–ój÷I'ûÉþEg ìÙŽ üN:=÷áš9iË—ûVÜçoɆcÕϾ¼î x8ZD£g'ßgðxú€ñâçȿѷö²Äßó'_î³×8ž1½|.ü|Ïáuu_<îûê÷å¿:¹^e_ŸÁ'øˆÃ=Ú¥¾ª/~ß½^ÎM­G^çþþÿ˜Cš¿ýÿľ°‹u”MNÄ0 …X‡á ìÙrJ§mÒ锸Y²á !ÁØ!ŽÅ‚ñ O&]|ÊÄvü\;3KfÖƒ3Ò‚Î~쉿;ñ; Ñs…•Pì§\Ýæùâ¾íÁþêŠq=}#˜À¬¥Þ p.ãçãïÁ×¹¢¯õ­Ìü™u©/Ñž+ýêÉ 1ž£ :+ÚÏÁ#x/¬s–܉qƒèD½Ø§Iú´aOFÉ㤀ÇÍd˜Â÷¯™ËxÿVíCM/žw=Ÿë˜¸ú¹w ÞÌvNÌvÑ·½#³ƒw³ýCì¿`?†ÿ \É,ýné½ó»§èÜéI¹cwœY¶åû½„ëzÞ¥zâ\ÛÀRþÞþ¿ŸÌ^=ƒOðÁ¾Üò»ôÍÅ÷õÔWöþ µ5•ë[s¥ïJµ¾Vö.øJaXc´Ç¹$Åu?wòJîT£ãÛ¬×gQ ßï…{ˆµZÇý¸ßF1§äŠÜjnkr’é8¯ïÛŸÏ£’-Î"ækE'œ#öЇ¼ÖÎäØÚfÀö3°ûìp>³7Ú÷é$çÒóœÒ®Ëç:ÄxÏ:ý«µzn1îQÜŸ©½ÊwØz ~¿2ð—îT)‹5µfÅùà“|'r‰ñ­äï6‡Evo.…ãæ²ØŸ¾¾ۭİ‹•”=NQ „­@ŽÀéh8JÈnö7¢Ð ¤ AÒ€èhRFœ‚ÓÐP¤ÌWìyÈÌ·°ü^ÅýuŸ%kÒýËíMôÍõP­ãûœæ¸ïàIê×ïË÷3~‡îåñ ¹&®›ü‘Ü¿ç×ÿÑ ì,ì{°‹“MNÃ0…ÎÀŠ §á*]BHhb'„ + +UaSq$6,Ør.€8Ïè=1‰Å§ØcÏóüÅÌZ3kÀ9iHK:¢½Î;ÇÒ­/I¸ Ò)wzp îÀ +dÚÛŠ^âŸÀ•#Ñ^»ÛóÉÝ[’¾²/z;ðBžç@ÿD½ìüe—Î_±«ѯè߃[¾ïÏGÆžCÍÕƒÁåQ}F’œ¶Ï[þ¥'ÏàËìàßOð +ÀìâÿÄØo\/³³½ XÓ´ýXT_ÿrÈÌqp=ÍÔ{oˆõ|˜.À1Ö§°¿ƒ­ý·§·ýù~œ ÙÕ‡sYs­âœÇ9ˆó?Ó_½Ö=Ÿgô«Íu|Gû8cÞ²3íþõÄÿ8ÆÓü“3íÒ‰ïÅ{?çßßÇ%¿°‹u”±NA DÍoð‘\’Û½KH DC…èi(‘øZ +>‚Y4#™Ñ¥x:­=g{mßED3pNf¤# ¢³üsÒ|«¤[’…!½â4M¶àìÁš¶åD¼>ù²­‚ ãlyî-O¦ÕZR¬Qü|¾Oà<³Î!éKЧzjŠãù…êëÂøÕìí<ÒW¬çšÞ]O°1FËQ¨k÷»·à|EœœâùÞÁ=Ø êuß6ù†dÛ3Þ8P3Z y>êMqJò©¯¹î+ð^Á'jÆ#¾Áxä,kÂóû<…ôù<òNöjG{«É÷Ü÷ ‹ÿ»©™ùn+Ÿ¿ç{ä{ë}œÚ!Ý=kæû~ýà¸ÿŒÓy>×ýù5›)ý°‹…”MnÂ0„sbT’’ˆPº(ªTµªZXuÛ;ô œ›0ó¤aÄÏâ±3žyÏØÉ²lšy2b>7銸O¢ X‚g°à\iº’ó‰ ßtôè9Öõ¡+ õI¿s£¢ï'ø#_`Ã:k©©âx!¸ßÌðµ×ò•†„×­~¢ŽŽ´Ü—¼‘ô¼æ»š$Í+ø{ðÁçpð˵+0p/æ4ô‹Ü%36d$ÿkíE‰~|\çýöÌ|ï`¾Á–ù-3}¼ŽÈ›Ëž‡FëéØGOï8·z7r«Uïjôœúy_'ô®»æ§uD¯þ~ú¿ï>V +ɸ÷} Ök&ä"ç¬/b°‹…ÔQkÂ0àübY5í¬µX†TÁmììÙ±÷ý¬ñއ¶{øšÜôÞ›& !dáæÁøøºâÒü¨Ã°C0¦¢ÅDŽŒÏå½×± TPòYצ¸hô=©U°ž'ØÁ ¬ø<•Z ‰_R‘¯m˯t.ïé'Õ1¥Öð¿p3,a&õ>Ã|Ã|Âð'®¹ö?‡-¼roÌS1g®y‡£ì]ØRzQÞo[ÿº.õ[±†š}¥:=ŸïסùJÑö]Æ2—άޗhõê=è»GÑòø·ŽáþükœŸ{½g~wt>ûG×ÁãF–§ïÿ¢±¾f@wyþ:ó°‹•”;nADÇgà4œ +Øg?`ƒ±! –G$ˆSX²GÄ\…„ZQ-µJ³’ ž4ÓS=ýÙž !ŒÃ‘0&DõfÏ{ȈéúöÑs»»;{t”bÎ6I9mE}äº5÷–GI:û ÌÁ x-ï)\Qð¹ZŒ'° œ5\Û¾%f÷u{Röèò^¸„ð0¬ÀŽ5Yì5؃_ðGŸ X‚7ðJý‚Úwð>À–vëSçw'pßà“š–¹Y­Ú¯JÐï4%µó«¸¯ºÖiK§·þú¹É¥‡©¼ô»Û¼è¼Ù¬Õ.¾ŸM}gúŽÌ¿”8E"¾Í ÷¿»Ô{KéûðùkžÙ?tÚwóKþ®èùX°‹ÔAJÃ@à<€—éi<„M:ImšV¥­hw"‚"¸wëÂ¥'ð‚ñþ?<~&X\|LÞÌ{y3IJiš~™©©Èïg¨Iñc÷®²Ú ±ñy« +×A+ÚÂ5\qL9çܵŒÓ{z|95w êìY®‡ú.¨±m!«–á]–°‡”Ž&p§¸ÿ‚G¸ ¹‡šžà ÞánXÊu¨®ÜÁ3<À-û§~k"×1œàú^™cÉþ)oì§úÍ)öpÍ9Ú¯6ÄyO§Þèù¢ð,îc\/Öåû^:¯ñ¼Å<ñlúwæß“rª¾lçïÿßïÎë×ú¥ÿê‘ú€8ï»æÿ??ƒôz~°‹“]jA„Çá]r ¨ÙÙ]”à B"xƒÜ wÈòêQ$5¤ +šf}øf¦«»¦·7„0ÿ<Ý #ŠÏA °äZ˜¸œh¯<3ro]剹+CáÎJ’9¬>úìÀ+Ø‚wðN`žM^«+L~_¯päŽÊôHõ;žÅ»,HM/&®¥Î×µ~j‡Îã;¿CMü°ÿå›[Æ4¬c?Á¹ïx'¢f à ì@Oß‘ õ?àŠzc¬ðEfeÅ\=W½ßöcaü©‡ò¡øÊ!ýŠ¨Ï¾/¹³ó¤8ÝË“ßûïíç< Ãóéç{îú¯¬Þ×ËÆ’šGéRþo¡7• ]Ê_*ŸÞí}©?dù&åž°‹ÓMnÂ0`_¸…-ˆþÐUp6lzˆ.P/Ò+°âE}Ož‚ÚÅ'Û3ã±MJ©›~=ü¡GZŸÃð +3(¡O9)Ny:ôߺõBî¨ ¯§yÅ7ßC˜Ã +Þáö°…öÓûñߪïqRð\†TQò ¨âÆ0¥ ãJÊònŒ7ýîàÎðGx¶¼ªûΧñKæ™óžuçk~ס¯)cð'ø„ cU³fo¯ZÎaÎMg¨q­/Œâk*Óõûй”a.ÞŸÖi^{òß~ßþÎõý}úûèš,ÔWßmñª—…˜È÷çã·öïÿ÷÷æóžÏëúzõíuuŽwt߸ü– %°‹m”KK1„ó‡}¬Îdçá2ˆˆº¸zqÔ“"þMk° +Š2‡ïNº:•éžRÊiù㌜pÙ` pGp&Æ>ò\×ÑþEu3Þ“.è­ö†± +fp öà‰ìwïXOºª+½('ëo©;“Á4åCçt·[pÃ÷UÞD²Þ`ÔˆO¦¹~£oðIÏ»ð+5~^Àx¯à<€Gð~À×WÔ’Ï…gÌ=Ðל¹^ÈÄû¶·3ÿÒOÿþ.ò?Z¾Þ;û¥ï“Ö¾êyýjßYßQ}¬uöAmà9ò—g³ßs.rDúMß9Wžëq“Zþßßg· ­ûŠžï«sÒÓÿéd埵 T°‹…”ÝNÂ@…÷…Q[iÙ¶TDMÀ/Œ7BL4ñ|.y'Nã9ar xñ%0;gþv¶)¥«ôÇ5¹1 +p{†X€ðÖ ¥} !•éJ¢ÿ•ù”ÆØ¹ë§FÔÔÈÞ{ðÀ]¨· 4Ô”!®ò¿k‰ú®‰òÏ,n1ÕGEŸ%xo`ÅùJ×åS½­©ŽL›r±Ïôý3ýžÁø?à lxÏ[ð ö`>9ËÆèÙÏ’1û0Ó¸#êOsëèÛMâzÿs’©›weø=ù>éÜó)öA÷X¤ãžÅ}‹§ûšš~¬çûèïÆßƒ÷ûß»ŠÚh=Ôé´~¯!¾‹KõjgæôU<}Ÿ&¥hœ°‹u”ÍNÃ0„ýÆ×MS(­J¥"$ QÑ[_§àÀ;1®f¤éÊ9|J¼ÙŸñî*)¥»tË=ѹ#½1€X-xP@&… ÆHjÌC£Žçézæò+ß`±Q»Ž <ò.¾»®Xci9FÓê}˜»§“™c>À8²¾â¤­ú=xµÞO¦!S›3#m>‡Bû¼Opß|V]ïà ~ÀøÆ(÷ªQ/Ööþ8…>ÞõwMÏ–ßcÏ÷Q3Õ÷xÖ,×¼WÜûèŸÓíδöÝëD=ÝL>Ýßýb\ì1Þ{Ø|·sÃîçÌ~h–Ëp—Êõ¿ôé9FÖ°‹u”½nÂ@„í3š€ ‰¢´”)"ÁðpŒÃŒ´ŒŽâ+Öû7··¾”R•îÌÈ ‘-ÿ0°_g÷8ù¶à |ƒ#xg¿ù'pà‡º«»0Ô[³i +dƬÉÀo¨áH ò­éC]ß/õ\éÐÙuÿQC.Øš£ï•ï£îT~·µg+êñ½÷ø&=îLiŸc×S=©§³Ç8Ï«ì{Ì÷þþ?>{J¶öä\Z;ËÄÿ»t*Žå°‹“MR1…ã†ó* !™düŠ…{–pÍI8€'ñ¥|]>»’*_Ít:yý“ta~¹#ÞöëFG–¤æ³#Á¬A+° ¶ÏlÓ÷ñkùíA´WB$>_­§øèI’ýÞwÁ ؃-x}cå|”¸VŸÙ=ÏLÄz“$nñïÀ'øáf†ï¼3ö û3í,ÿ5Œ^úc5=ƒ8±®׬®‰ö‘<0WÕL®÷Yúfþ$=‰.Qò-úoà œÁxåkÑkélxGGÖ5IýK×·,wÕz7­{ôsáßuçtý¹ê}©í­åá礿5oåÿ¶‚Íâµõ{]Oç¶ ï$9Ýsþwé‰3°‹}”MRÂ@…‡«xB0!$ˆFÝX.ØYvÀ8gàÀ•/Å{UmW&‹¯’ééŸ×=™„Ãñko)Y’Œ¤ÎÏÇûhÀб‰A~IÄ>¥/cÞl@ r"}Ò+ýV×°_P_ÅwÅË^“gð öà Žà›¶¬éïëÇtغµ—´ÛÚoà~C˜=àù`ËyV¬ÝÑÖ™Y¯ŒþÚéS\ žÀ éÙkË}Å6ŽXÞœ}øýÂÍÃÏYz_9ã+¸ øàùʧ4ùÆò ¾ïà˜Վ}*~lîSç%ô}z»üc߯÷ª§s÷zbq±:Þó·ëùI¤õ)½ö?05{oÓ‘üòÿwÏÿµF÷°‹Ó;NÃPÐaT¬Šg;þÅq @A@(Š(h ¦¤ `t@IÍ"h¹QîÃÈ‘(Žì7ï?›ÙȶÆtLŠ«½éË`Ÿ9cc ãi`~¢œc4?¹1~\FéŸ4~sŽLù^0ž»óúvá”ÐÃ9œ@ÍXÉ÷:öÝÀ³ÙÞ>Á! ö +·°àø:(Ý~™{WEÚWyR~Oá>áÞáæìŸrÌV|.oÂ9<ÝOzλ„+æ¤wwjH9™ÚCkÍ©µ¿yðõ4 ¹j¹ï¼Á¼ðN~¿ž¾¯Ömù½Öð\ë®]Þ”÷ø½|­«^“këܾ^‡j|dæøs(·ýþ[qÞ®ÿ$Ö¹öUlÇxüU«yPó|gpaÛšéîQ…üÅ|ì2ò~–VcC°‹…”MJA…K½Œ§ò &Ó“ÌŸ“DMˆ$ñoáBwºEÜ ^À.½Š¯õ=lŠA=ýªººªº{ÌlÛ~è“‘®y´°ö8© @hYÇúŒD{É1§Öëð $û‡œÈ_ñEÁüä7 C¢yÆ` .8Ž©‹†Úܘ­mš­¯Ì6>Á¾Ï mÁöHŸèÛ:ª$§àö¯\ÞEÒ'Õ{|®Á=¸ 0¢-ŽSæŽiŸðŒ´OáP}Bu¢>;áwšMê#2!-mû\;¥Þ¸”Œ£º»ú}nÁë%q*Ó߃–9œ‚ð>À3¸‡ì›ï»ú ÜtÒ{œ’Þ+“ÞC\×w‡ÎØ÷u—ÔöûÞºðïBùänÙ5÷uù<õ.ƒ‹§\gìã+x/œë¼£}Îïò}üÈëß|ðzý…°‹u”=NÃ@…'‰{Pp7DbÇ?¬Û$ @ ü‚†’QRP"JnAÅx–ßH“Q\|òîÌîì›™]‹ÈP:FdèP{Æ`æ` +rÚRP‚жhÍþ$ pmÁyDü9}èúvoƳSãOHJ-Þ¯öÜùsº/àѨ·Íý\ƒo‘Á—Èæ‡ÈÖ%ØÆøQdc¾°5hwÊqA݉£µ84¿±¬æ¨ãÌxNihû°Wàœ˜Þø¼•ÜäsÎ<–¬Eiö«^=¯â¸6z*Æ8ã·v¹e\×°¶…É¡àºÀ8m ÔYNGuNÌ^[׌¶†ÚÏÁxŸ}“Wpãâ©.k­4®Þ£¬Õ;c‚¬Þ[Åßk«ÙÖAïŽjñ:”˜¬{ö|û3ÓÏ„6]÷ o(°®Ïào¶Á;ØÅüå^i¥8²=ïÍÜÉ|bf}[ƒ(À¡Cç)AÍ»9ï´—|ï¿tï<€r FNCñ¥› +’tpžÀ=˜Òž-A¿KùUÔM>g`ìÎj~ÏÀ1ud‚Žç×àËlåÃlú›{f¿xGÜÕmœ}ƒSÐR+qDjR1/¡¶Ô9}åí)Š«ŒY»ìÁ»ÙÚ.æ Ï|?Ãþ ®Ø×söºrùJGÿÊ«}?ñ% ¬°‹}”=NA …Mr .“KP!®€H–l2›Ý%äB‚„Hj +ˆ"*::ºÔÜCð¬[ÆÑÚÐ:ÐsÏrV‘¿Ûø©zÒºòï·’ulÑ÷ñÇ”xVïV§~G߉½çij)ïu<;‚øRßð0‘§ÿϰ<¬=ó 6®¯È°‹”½NÃ@„ï‘CLb›sã@„@‚†Š&B‚ Q@Ïð¼sÊŒ4Z]AñI÷3³»w¾uJi‘Ž4deãÂ)Y‘5)kKpRAqZÐ\ƒ'ð ÞÁ˜¨ikYÉç=¸Ïà |€{ÆZ›^x--5¥¦3ÖÕ™®©äm,o[pöà<‚7ð +à†šŽôæÍÌëäÀ†dóöŸÖ=OñÌàŠ\€1ä‘OßQßgæ™v<ßÈõX_±jU÷hóšÇÏ ïd¾-½CÐn¸7Å,Žü®Û“²ÖÚK'ïÌûšé›m<ð¬Åû åžòë^:îKÿŸ~rÔþ.U®xbü%žú]}óÄ8þNüéÍÜð~Áw:öÁŽõúY:{g)ú1.ûƒþDóhjZCswj¨n)}©±¦9¿mú¬3Ñ;ûÎÒÛy97ûÎ×q“ýÎ aXÿ÷ëO¬=‡:ßqîx®t3ûÛhÇsm=ßY‡n—­ýª ô©9‡çŠÿ˜¬}ODúxô@kß«´Â¦°‹}ÔÍnÂ0`?q…Ä$¦ü¨•¸Tê‘C/•¸õzì¥ïÔµ:# #Äá$Yï®;)¥eú÷hàÏçà×3˜ËXÕ„:XAbZh€õ™§Eüva +r-eœc½Æêx~¿^Èøµhƒ>&¥ªó*2¦3Ùò‰ï-Ò5nžÂžq¯Ø¸b÷z©[ã·°†:§×ð.áNxæy?!G±ÉËõ`üŽb/ýl1§=~GYþnàXî/b?µö[ø +?á¾ÃgxÁ<2´F÷4×s%ñºßt¿çtò\ù9bœ÷¡ýd‰ós¤÷³à{òkÆÕõ­ç­¾ûw8ÝxƒŒ«ýúw…fÆ¿#p÷´ ó°‹•ÔMJÃPà+¸á"ÜbMLš<›¶¡**ˆˆ8‡‚ÐI·Q§Î9p žçÀÍ%|„÷{ïûÉ3³ÚÌΡ *ÖOœSRùìŸJ*c—ÐÃ$Öu,+©©…ÇõçûT¤u©­ šº1•k÷s6Œ“¿eŽ^â7Á4ðqê‘~*+Þ®ö,aE æÓ†xÊ߯%¹üçœGß[xƒo³½}|?á…1|>3ê[ç§ùU¯óê(ÇÈç 7pOð pÅþKêCyåæÓzýÙ¨>ž¯rîg_XãÁ!Ê?ðÊ9´ºñ>î¢x5÷Aû¤ù”c²á?7ö¿#1ý=ÐüɆwË‹yk\Ü;ÝõÍg÷kØÂ¼Ãcú1úrþ½ù9¦ŠïËàÝùr+QÙ°‹•”=NÃ@…'§@¢¤ä œ…€;Nbâ8€’! ¢¡¡¤à\‰–‹ðVzOp¤ô‰ß—:ÿÐé­G[*°EöÀøïàŽ¶‰Ë%‚­»`Ÿ:c§×åÏöl0çx—Ô›¬‡Ð¯”Ôˆ)OZ²‡g™‚MÖP1Oît¥%»êñýPžÚéH_q]{¢9nÀ—Y² +îÁ +ÖŸà”13ÖÝòW窩wÌÞžCΫ¥_½ªh ¾sp ^Á#óìÐßR3¬XkÃxõIó©èÛ& sænÏÔæ÷/Ôˆ{—,ƒk€Z’ØÞßõ½Ï®yuͧdþЯwÆÒæ÷6~?ZKKg(Ø—Pÿ3xÔÎ\¼ò+ÆßSõ­ï|9ûæòƒ¾,Eüÿ¶¿ûQuÄéÝé½ëÛ¯×È ‡û@/À,°‹}”MNÃ@ …ÝÀŽ%‡à‰i“4I›¦¿Ð¢ò#@¡.`à +$œ6HHHl8—àY}fŠX|Jfb{ülOD¤%"M°C"²Kl¿îÐuÄ|z;ÃüÃxÛÄÎÒ)(ÀxàÜ~o¨_Ú t6õ„yy=}õ¼pæ`À8)cüE"‹še´Ë +’:mºß=0ûà˜Œ™L©wD]-—OLbù˜._“ѧ‚yéy§¬Áßg`ÎÁ‹HmÀ¾¶õ38qz¦ÔrÈuŸÆÒ˜gÔ]Q[X³Š¾Gà<‘9ó’û6á³ãz‘²f¹ÓÖ'=®sG›þ]ƺ_иÖðþ .+œ›Ãp?þ‡T~çY²ß3Ö*“Ÿ¹ ïO8û6‡ªcÌ:=Êâþ\°ž‰ó·ž—´·þZýšÎÖßW›yµÓYxGmVÁ +Þߨ_ó÷u±{g÷Ýþáz‹Ôeù³äÿ ’ëcH°‹uÔ¹NÃ@àåax?‚ØN|Ç .!„8$A"¨!=-/AÉÑðô2Z™âS²ÞñÎìî$ι‘s.…) eZ2dSäÅ…f®‹®¥ëG$5Ô0…gx€X…ÌË'ú”RÜ‘;44^ž'PÂ&œÃB®—PjÆ1¿KL¬Ðˆk40±9cZØfÎxcn©cöáv[ñÝÏ ãš}sº¿„ó%k©ùY™zÄc™_c^9çwø‚¸=Xg½2þvnaŸ¿p[¬qN¹ Ö>6g#qŒk;ö“³æ1ïZòÞÁ'üÀ+ïFjðŽƶÜcÞAï¡¢štlçt^îAúïfp̺lÿù}ø_?úý£ûµÏsæmxöwèÿ>üõ3î¡äÙH­×pÉ3¬Ü¼gµç‡¼Ó)ïpÆ{)ܼ§´Ÿ4¯}WÎû á‰ëLLÝ–ÿÿá{ýoéyûM|ðX’r•°‹…”=NÃ@…‡š[PÓpNCIb;vœØ1ÄA!„…ÿ4HÐÑP!Jh©qN@Ã[å4Å¡ødïîü¼Ù]ŠH¤ 1‰H›ìÚÆ.qv:Ž˜v‘#ä/À\9ƒÒÅI)‰ÿÉÝ%a>—eÝ§àšœ€÷¢kbX?l*pDcÆ; ÞÒıö5s½‚_‘M|¿Á-˜ pλâžô¨9g¼Ô õ…µ>5 žŠz +¢º/Á¸oвöÀÆ_`ÁºF´}Ôþ¦\gõžÁÇ5µ”üŸ¬©§à¾×Œò~BÇ6ØÅÿ󛚇Œ7pèzé°~êk×Õ·¦Öç‚ÆU}ÜÔ‡¶_2ÖjëÕyk¯½¢wÐÞ‹¦ø¹©+ôî¹,{kNý}§;ãÜŒçôγ\p/šî¿½WzoB¾)óÆ×âß?n9ômi¹ºccýå^ư‹}Ô;NÃ@àÉ-8ôôˆã@b;vŒID /Axˆ‚†Š‰‚ PpJJî¥ÿW†UDñI^{g³³6³‰™  „2jÓ©Ý¡”ÔN׃= +ÏtŸF»œq Ô|V|Bâ4§—SE%õáf0f*öÍÜz *ŠñGŒ1~?êçÕŒ™Ã§Yk Öñü÷p +ç4qã‰ÏGáò¬}jü!…ø?àû°æ xxƒ/¬eð½µ…ö7ܱ¿öy ·ð7pÆü]Á<Ãß7ѾŽÓwûÐyh}šgÎõlÀ6ž9çýW“ö6æYN™¿cæ +óºÜè›ê'>7å[u¤ºP=ªžõ>hü¸&»‘x|Õ·Ÿ'wçr:➯yª›Ê–÷&szÌS8§wxelc˺÷wÚßuü¹Åóøvbÿ«ÚA{…øÛn°WV,º°‹“ÍJÃP…GÁOã›iÓ¦I“4i­V+•ZTE]ºp#º7¾OáVpëz\¯ +.>ÂÜù½gÌìÆÌ.Á %-²NtNH‡èì>胆ßä  øù‡¤ôñÿm’üâçy†Äóö« 9ñ{#°M¿*è¿ÕÜ üý^ÍGdH[?¼_1Ÿß›ƒða¶´Šï¸¶Å;܃ °ôÍTñKž…×±¶È&ýjâ¶1˜€cæzOàµ,ƒ5°‚ó 8bŒ†¸ï8çìÃcMi?3ÖQý«NÅ‘.ªÍgÜwðÉZæì¥Pßnße]Wœß)kh˜GóQ~é%ÿéHz¥gÙc +w¬ÉX_q|é[y2újž¾ƒëæܲgÍI1Ò€{Ÿq^'¶ÐLß~î[bßw=ÞÍMû±¶šví‘b¨¸_·µþÁ†ó”VØj°‹uÔÍ.Aàkï9<“§côt÷L·݆±‘aa„ 6Vbaã!$ÀÖ©Ì9qÕÄâˤª«êÞºU5fömf_pëPB]èÀ"-Ñr¢K=¨ ¥(ØïÇ¥óÒ~IãiœúÕΡ†5毸E¿GÌ7êșóѼX—cÕn®äníÌRœ`Žà^à>Ìfæ`fѾæ¸àöÕrË#p¿ lÁçű«ü®üb{ĵ¶á nàÎá^áNaÓ­¯c8dþ»Ì­áïÈ{åòTü@}òµï»=5\;æu \WcKWÛÀ¸ûpÅ=Ürî û[ŽUÌÀZ¨F麅ËÉÓ}*yÖþ>å 4OßÔÖ÷ô^þ×Öž+Ö(žÃ¼Ã'¼Á1÷TÚï½÷ï'suk¨²¿ïÅççß§ö©ø:{Õfh“{µg“;XÚôW|Õ¿fŸÿŸé$Ô¿ýâÌÞQ°‹…Ô;NÃ@à ‡¡át a;6~àMá©Ѐ äÑÐq(8gà_ñ˜ Å'e׳;;ëqD«"ƒù€#¨a$°A)m:•ÐÁ˜(“š8Ý'!?ïù<©Û/ç™G0áJ£Åóæäcr³gfâ ŠwR1WíÖ—f½î¯±=ÞË ÜÀ+îMdiæøßÃ\2~¸nÛäo9îYwÜó¦\ø|‹ZÎõ¼+=Üï}ç43ù:òyv9§Ï‚‰o˜¯5ëu¬çiHǵ‰±f[·îkë¬÷ ážàîáöMÞ†{s^=CE×™œVÍ8ßZ_Å9ßg:Öuÿ‡¤ëíýLXÛ ¼Ã'¼ÁëÒóùïTû²’ÅÞ/äo?k þ;‹ýxÁ\§òÛ±‡náN~z7¸{Ð=b c¾·À9û?“8:¿}§Ä纰‹mÔÝ.CAð)¯àƽwòÚêùèiOÛ=Uñ"D$¸Ã¥K/áAÜùOü'¦£¿ôììžÙ=»i­‰´VDäv¡t`ÃéÒ&umçP€´Ý ãT›b»´oý>w5U.w”³È Ær·.›?¾çù¾Œâ˜’¹4Ϙ{{ +פÏWð…ý?YúYnð»Žö*â7°;¤Ï#·¿¶^M`F‰ùAÍxÔДï[¾†ó©æÜ k»¬Ž‘oó[ÌêèÓ}u0aŽ$óuN)¹µ$Öz—pK÷ðwpÀñ–ßê´XEVWÅ~Û˳M‰ï•ŽÖ{Ì—×sPžz úýyÊ÷uÙyÒùáá`_þÎø¼‹ò[SÆ”ü6gð̽ÇõÁ3¼ÊïÙ…uÙ½*Ý7¨äÿ]ÿs÷ý"=Bì°‹m”»NA Eø*þ‘<6Én’Ý%!<’€ ^¢@¢ §E” Q#* +¾ƒ;p¯b¬G³öŒíëy¬™}šÙ+¸cÐÐ[Ž6é¸y‘ì ô@—d\ß +4I´Ûf@룎T«%PGÈAÀœ½n^ù”ßÇ Ê­uê7_AZ?;Üßð>À#¸of ä[»3[ßĸ»ÿ%˜:¶©_}Ö¤âܘ”¬)Ê1µóU¤füÄ‘òŽHÍ>ö¨§¹«€×7 +kKæžM5}Sj‘/Õ]}ÚcŽ:Ï#pN¹¯÷àÌž¨Ÿô]Øò\ g'Í»¬¥ñ˜Ì¨Iq© ð¾Á38§?Í÷‰îŒî™Þ‹æ{öÿýô©Gº½Î¡;£9u-¨+gînÀ×Í\]åÓ¹èî*FñÖK½=Ùß]Nwø½¦ñ<€3[þKTÏ¿«žÓßzü_(î×þ®ù›}°‹m”MNÃ0…qN‡aÁq  IÚ¤)nZÓ¦AË@Hˆ N€Ø°BbËUX²ãY}£Œ¬.>){Þüxby‘5h@œ‚ôÈ IÌ^bìñ~ H‰ÕQÝ$Š“FÄçÕž˜!ߌÀ˜ iÏM> +´à<ñ{åØ3热 ö\€¨iÏIA’±«ˆš¾ïàWdgìáû<€7ðÛ +ü€#¬¿Àë9‹p¼+&ijž}jƒõsÜŸPÃq¯fîC®õ̘õ¦`)›YY³'޾•ñS_Eõ­®§ÿÜä¡„8ç&~Ãõ%{²¤Ÿ7Zžµ·'SRp=ẢMÙGD›³Þ’9ºÿ.8÷àœsŸÔô™˜øÂäÇFã<xå\Kæê,už¶Ö)Ycl¾AÌØ9ç³gf«9÷°91÷ÒYnDl_©ÉÉòÜÝ€o‘Ö*ì›ÔߺyþBÒ#î90h\W–g~@ Íqïìðåïùµ„ÌÍYcÅš´ÿI]wk <‹¬¬Ã>Â÷#õy6êS´­¯oêÒ;ôßÄÞûæÝwl’æÿÀ3ZÞ/3ZoȰ‹mÔ=NÃ@†á…jz +n€8 ×€Ç$ÁIpb“ BTP€Ä_@ ‰‚‚PpnÀ·Ò;bbQMÃüÞmŸÑ׌µÓ_÷ħÞÁf‹¢=¹¸¦ëu?PµÆ4ÌŸ;Sý6ü÷ñçÞ³ó¿ê÷ q¹’_m‚w¸°‹u”;NÃ@†'ŠÐsîâÄØ&Ç‚  @ˆ +„¢¢ D¢§â +\€Á?ây²„âÓÚ³³3ÿÌ>Dd ¿ô@l‘±ÿ¾ÃÛ»Äü#ÒˆÂ<u¤$!cP€!ˆ—Ä9wnÁx'`B¦Œ£~;Äâ8?¢}›è\Æ5˜ýΩi2×9Ç(é“3¶RsnÎÑrÉØÕZ9ßcÆÖÚîÁ•Ó±nÀøßàœR›Òš9 —ÃSPoÅu3Ò°ÆKp9^P‡Å²×¾ž\û µ<ƒO‘Î:XÅ÷ í¥‹ãuÖ¤`ÌpŸRÚ¬¿Vo)íþO\Mõ@ÏÍ{vÀÚsÆ Ñ¼1›í™å­‚õvÞRiÏUâô‡Ù¬—¶ÞοùÅò÷Nø){Ù°¶=i÷[ëÆ]él€‘•MŒï` ökÖI{Mÿ À4„ú§Í¿ ±,êþï½YFô·‡Ån°‹uÔÍJÃ@ðé{yó…jÓ&Mbú‘¤­R«ˆèEQüO>€AÁƒу7/âUðú_ú‡æð£l:;3›Ýˆôd¥mØ¢é¸kØçmÒøˆºNäø:ûH)¦ üí¯ÉóùNàNa†4fŽmÈ©OÌ_™ÿ3Æ#˜QÉ\%k†¹pHsW2gņFAZc`òÖÌ¡¹á Îሽ†˜}¸…Gxƒg¸‚†úcó¼¦)Õî?]ï.á~àîùŽŒ±ë³ë™:û¾†ø…o¸ã:5‡ö«½LHß{ÁýI(g݉éyƱö”»½Ô¾Âyy€x‚Øc­Â 9¹ÌÈï_ÓØÏ×s—8='1µìÜØÄè±÷ÁçÐ÷ã÷=œ‘pž¾DZ›€ØÖÆï²:Çþ¾¤ }j¶fʹ™ü}/ôÞÇò¿ïußû}°¢%óQš°‹…Ô;NÃ@Ðal€P±VB…ägb{œØŽÂ'|Bt4QÑ Aà +XKÉå^å1ŠDqdÍïÍ{öŒsm·tø;¯eúHíi^;2ëãýZ&~zðÙ1í$ê·B_ +#h¨€| pÌ5aî5\†à!•|æ\—s1LàæpGgPCż´¿7ñ<óÉkÄþšyÍànùœ3îŒû…þgxãóžceT¯g슔óļ/å©Üœ¸‚wç66a¶Ðþ'ŽsžêѾª§¦1]À#¼Â ßUùª¿4ùN©bL}?‡”ýÚG5ª.}·Ô(ø¿PÏ6ìÁÚ¿ðÅÑ· ç¥훺¿çÉÊÜêìø(g«O]#>÷Š©ó/Zß-«gbèÜæÌ«a½Ÿð nyÎ +æ;0uÆ{+×uíÄ­îIh‡û¯ûnëlsÌÒÖxøìkýÍõ¡ê°‹m”]N1…ËN\‚[pCfgg˜?Ô`PžÔÄøóâ&ÜŒì€xΉ7_ÚÛöÞsÛÞÖ9wâv„ãÖŽÌø‘­ós]ãÆLüôA +r¶Þî±U?ðcg £ŸgFl-CÎg´Çàšø~ +CC +úfÔ’ž×(ÁÜ€gð +î¯ òðñ'¤1ù*NC¿Kæt–`Z°`ì5xoà<ÒG¹J/gÞ5sœ3ÞšÜÒ¯¦~ÅWÜÏøv®³pWØ?àq–\§³+ µ9¿sâ÷=£î‚Ú÷?b¿âÚ ®Ñ.Íý¥Dw šŒÉÄ܃ÎÄ÷W`ƒý¼€-ø{û¢^˳šr½îÝêªÞR÷W"ç=¨žTËi€õIˆjZ5¯yÕ¿8%‰!|g±YkµôÆ +žQËó-«Ý3±¬¶lé+ïÌøý÷þõtIÄ×^üÿqèvÿDô ÃÏqâ°‹…”ÍNÂ@…§àK¸÷Í(¥ +…ò#jŒŠ ݸ3Ñ…®Œk·ú">€1žI¾ ×ãâKésϽwfŠs®éœ«‰:ÄЄú?ÔL¾Ík˜µ†‰âŠuD&¦b_ÌEN¼-Z†àã'¢'ºhýs +1)ë}Cf4(ˆ ÐäÄ +ò½÷.´!E?âZÜŠbš.#1c¶‰é;Eë×K±Äïp)îÄ£x ÖÚ1=÷ñí™þüžž’û&>‹ôp¯ä/È÷½­Ä½xæù"­ÄÑ–ØÐû»¸aÆ qÆ<uæÌ0bÿ‡x[JgÎeÀû”¹WÔ™á—C}â¾æº±ée ¥ÙŸ.>4戾„ö2ÚT쉺Gâ˜}-©•˜s çè¸õ= ÷1ô–s ¤ÆÃz…;¾Áê]«¾'n}'mž§1k»h÷ó[ +>a¯«~«––©ß6^¶^lüc÷»/ÿŸ° ýGÝŽå¦üô–°‹}Ô;NÃ@àã€DÁh8-uHœØŽ‡í@$ x +DAGEE  ƒ‹ Z:þEÿˆa…(>9ÞÏÌz7‘HDhP“ZÔðè|H.¦næ"ùÉY§ÀŒkÞ¦—×Í¥0„8ƒ(9þQ׉¡]ƵyÝ„æË ¹Q0fÈkÁ¸¥Ì™QjÖ±®Övó¨`ÊþǬéæ“ÏÅm±nazî°nÎùŠ9¶©äý9ÜÃ<À5kV̳n—´¿}¸ƒ‘¹šÈü,ã÷Æ^àöà^1¾«øý 3x†7^oá&\««?âšvYkÌ~ôý ÌÚ-}÷}Êxïöî®à’½ùÏe\¯[»;+ì«âüˆ=N8–óäÌ÷ˆ5.Á:¬àþn̦Œ+¹7 Ÿ×^õÌé:±§{¢ç@÷¹gòh®„ÏëÌ?kZ#1ÚŒ ÍsN@úŸ‰L~l(¿Ïvë¡Y£ŠM=ÿ;áÓïBì7ÂÖѸ úÎûH¸Ûd°‹m“=NÃ@…(¸7àôˆÃðc'Îí$vþ@H €D¢ §@ (¹§ æ­x#=¬Ÿ¼ëyóvv×Ìr3;"âó]²OÂZRûË­3®Ú C’%9˜hÍXòG`®Á%˜€ 4$.ôâ4©3`nŸ>»;ÖqÜa^‹4‰Ï݃øzðV²ÖDôr‰mÑ[Áõ Ç©èx?»¤GÝàu(ßSp žÁ{t(uKæú9ä¬u>ÍV¶ÍVwÌÖ^ÁÆøÿîÀxGÌþ¯ƒMŒCÏ¿Á=k…³9³Êž½¯ÁË1˜rî>t?¾—±ø.dïõ/ÀYðß±nIBÍÆSwÀø™R;£Ÿ!c_ÀøìÓŒñs2fSñ×£VËþß?s?ÏBúÐ&9ÉH»B¸gáž×‰Þ9÷ŸI=Ówåo/–u‰e]ß`@ßVMP Ý_F¿õö*TõÝ£¯«Ïeþ]#xH~4ØR°‹m”KNA†ËÇÂ+x2×ÞÀ3<AT|$ÆWİrï ¼ˆ;®ü[¿ŠÅ—žîêªþ«ª{̬cf‰8€ø|ö!ØE]4EU”DM‹Kh±¯Èè$¹óüƒ­‚ßP\ˆ‘è²æç#Ö‚-ƒ”8 q„Î ­!×袷ÏXï •ܼ±Ýs¾ÏâQ "½åH[8ó^ÌÅ‹£-…Œ¹S#‡ ¹®?øÞˆ<.y;m|oĻيz¸új¶¾%¶õ½£µ ÙfhûÖüMëŸfk›úþÐÚùèÍ`Éymðšö¨yZìó\NÅY§ƒ“±æÜÙߘ’÷0Ê1|?ˆ'qEøÌaBì”Ú6Ñ1¢S|=Ç í¿ 1{Ô~Bü#úVµÅû’‘ǘØSbûŒ{ï¾ñ<¼‡xÌ”ZzÍSû¿ga_ü®ü½&Qß“Döøâ·U´Å{ïwºõ·Âþo/G>¾kt{¬s™~÷ýý?üË>P…°‹uÔ»N1Ðz:>ƒ†ï æ¨ Éæ©Í;„d!„ˆwÅK*¨h(¨¨-5%©èÜ‘î–%Š£¬½öÌØkÇ̺fV„<ÈŸs°Fëäý Ô¡ )Ô ‡pM“à½Æ”‚øŠç¹ËP!Û‰ô ÅÅ F1+|'Þ®FwƒºÔ§”óJ¤yª«ÔYãxŸwÏðopÃþz×ë?…ø/¸‡!÷ÈÇ6¸Fñþ6ÇŒ!cÐ& 8fH[¤ç}x0›Y4›]0›[U´¿Ñÿ—p‡öGgUtætŽãvƒõ†ß¶Ç~§»¡{ªûìý:×ß÷„â¶î§Î|Ê|º?MæVÞ…ÿyƉﮄõ%ÿÔå5TJª¬H°‹m“Û.aǧ}Ïàĸò:J»¥k·G¶U[%뇄„{D%âV¸÷".Ä•ÿÄbºéÅ/ûÍ|süvFDb)ƒ%R&Ê d‘”¨_5‚$`œ“Ðu¢vUßâé9à²BÛÐÅnƒ&åÀŰ:ÍϨ²>Åj˜4Iä|½¿ÅôrÈžRp¾E +Ó` +çg°Í«´ëƒkð›y0‡ó;ߨEÛ&û\#ªï€Ș+q÷Æ:é1Úï#¢96Á8oÈ? îÀ#˜nÀ%ø‚þEüÛ"ü +û…÷Ö‘2W¹;¬·•ë¡Í»e_Bÿ|OæßgÍûº·ÈxÞ Â:ºÎO{}ŸàÜÒ>rs`õ&|£!ß+c¿‡à”œþk|ä•ú.ãØœ[|{­ó +Ü€ ù› Õëìéù¹­ÉÿN…9¹Î:SWß1Ø¥^gMçÓöÃï³ß¯I÷¶G• r ãû±û¯1ïm§KÄö;ŸÇ~Ϫ¹:Æúø&#ݰ‹}Ô»NÃ0à“7Vx +&Š´%MÚZš6¡-”".ˆK$&„„ÄEÌ€XY+# ;¿Õÿˆ#1|ªãÛÇ'vE$‘ +”¨ «†{a…B*q\X‡¶)ƒêä¯ã+Sdbj›~?Ï +Çi|ÂÜbOB5ObÆXÚoÇ×¹ß-x€o‘`fÑ~…SBÛÔå +¾³ Kh¿Á6ÈÕ«à¸!Çt ÇzöùÜötɽۄ¸€;¸#ÎáæÀ ÜÃ;|À-r û„üæ9èfÐwÉ÷…‘SÆü›¤ye&¯Û™¡qM³ÿŒ±9k0âºî-çoŸ}=>ë;[¯3xFþ2!ãÖ[3ù¶˜‡ÖgvaöÉ}ÓÌ5 hÂ5c»Üƒ›75ZÌÍÕõœß¦0qz¦ý3fÏeÊøŒ5qßêÆ29ScÖ£Á9üû£÷ËÞ½Ó¡Lß?¥ñz¿ü;Ñ ˜ãCOéŸþèù´Uùýß™ÊóÀL.°‹uÔËJÃ@àqçøž¦×4^’j›ÆD õB¬.A\"]("ˆ¸ò\èVܺré?ôÿá8ââ£É9g.Í©s®åœkMhC—ü8‚eŠÌ¸ab{´J tLpP“:Ô2ü8æíšmç×Í` V˜›ºÚO8¯ZÝ€æê±n +[pOð¯ð38‡ lR wð pÅüŒr3®æ3Ÿ7€‚ã‘©'9 s×ð̽œ2_q;pÀ¸C؃ +JØ… xoz`|νȈü÷ síkÀÅ…ù}ʘoÏQqÍšwRp^µ‡œ+yž Ïá?·i +÷ðE3ÖÒ~¥oî±dîØ¨hnçw²°‹øþ7¼Ç‚üyÔ)kk¯×T$&.5söÙ:÷\òN¦t—pìæ¿»ßý»Ù ¨¿Ô7ê3õqØ¢øv üP_GÆ?ó>>v¿ûMýs¬uþìóÛçа‹uÔKJAÆñö|Â+¨™hBÌs¢31Æh$>AAD\èB7ºÑ+O7®¼„_ë¿HSàâG¦{ºjª&ÝB¨„?Kˆ×UYA&ËÉýEØ8CÕÅÙØîWœÌ±ùô¹™Ë¿Š†ôeC:RK']ir¯–ä5¶¾êr›:ÏYC3Ñ&!;r,Wr+Ïò*÷2a­=k¹‘1õ·±.#ÖDâz¬ñ¬k­ÿMØõ˜:^äIÎeÈú>k¶É5Jâmþˆ^îÈ3!¾‹œ^JÔ“;V_Iî’±éÓ[ë‚ÞJêˆïôTö‰·ç˜‚úÏäQÞåÚw‰‹=|ȧ<È!}“zò$_œßJêµþäŒÿÛWsó2•oYÐÜ'ä´¾,6}G¶/üÚÞ(ˆi¡f{"¾‹K¹àÿÙƒí“<Ìöfu¤{<åϹ?sþ\üw.ýùõcûN,3_£7ÛMêôuøïÅoüÐ:Câ°‹}Ô9NC1ÆqÈè9'áƒ$$,ÊFHòBö- ±  ¨B¢ ¡âTôto”¿%Ë$?%¶ŸgÆ~ösÎeÝÀ|ÀÚ¹@&Ë =·€<|Ûg#ùH°ÿ ñýllƒø-ö±Œ}þUÐ`Þ›b§eJÿä™sТv‹Qbv–ÿ;ë‹ïFÎý½£îeü||ßýw#Ç|[£­[¹tƒóUt£¿7áw&ÿ N@¬°‹mÔI/CQàÓ¦±åøƒ†;µªèÜ*m EÌ’"!„°!ba!6vb+,%l½_î{’ωœsÏüécÆMlÌá–’„ä)Rž† ˆ˜÷ÉÏg·í'ßY¨Ažá ΡκH â©qmì:žˆk˜TrŽiÈC *ЀÀ1ìÁc+²­¤sÐf*k)P‘J$e3,“1V`cv8Ç|À;\²M›é-rC‰y™Ö˜6i6T™¬«ªâŸ‡µ†:ëuÜö»Â¹f•ÕXŸwöQÆj1ö3¸‡~oqý-®«߯$pÉÒBÙ>ë»ì+wåNáˆc7Õ|uWUE‘y)ß„WŒgLê'6ÐèÛ—Áü?1ˆ6»Ü9« Ƈ°Íý–øË<߂ڧ2ç¬pÿ1&îem’7øþ‚a”Ÿp/§L|ï3”e™;+wXÞ£¾×ö „¬³}%ÿßûsß}/îûqß—nçsîÏå>Mü~{\shþþFHÿ/Ò¿Ef©°‹mÔ¿NTAÇñ³l „`|©è(è‰@|:k#v¹,fAþ¬+ »,Aù«!˜B 44+ _@KH,´“ïäþN2¹Ù⓽3wfÎ9sgÖÌF-5’‘í–"ŒË˜xÿ+Ì¢¬vA²ë4?ÑÜBFQ|^x~‰%ãÖ,—ã÷ +Ëz—D<¿ I¢XcѺžœO¢9“‘r Óªu‹x‡=|Æ>¶QG3˜C ©inP‘ùȬæ,`ﱉøMýOÀsîÒw¨uíJh¿Ñ:3Z3ÄÝÂNµŸaý&Ö•÷ÞbE5TTÇŠêl*΂ú=ç׊WÓû†ÆzÍžWSc¼nŸSWøG]ƒB?í_øŠìâŒþ.s[¿wx¤½oª†CÕùIýþ]ʵªêÑ·š‹„ö²âýMµõšu<6ë~nöà™Yg·Yþ)±x } ã/ñ78Ç7M—ð-ü¾ø¨*·/¬×C,Æ·¯:ò'ô}çÝOÕ7eé¹/YzfKêóuÃs8»ÙóøÝ(Ih·º~¼í÷%{Š-ÆÄ÷*ʶôœ]ã?þhO*ÿ?¼øÿbâS殟°‹…ÔK/œQÇñ¿©Öâ5tá=XXK¼‰ˆKw¦3ŒaF£JÜ-,h*,¤•¸'ÝhHl-$6"} ýžú89!ŸÌã<çù_Î…™õ˜Yw Kºßï‰ôJ?†‘Ç4²óñ;">®çý$á¼AŒc ·xÀOÖœ¾È€ô©NŸïµ~Ã~ÒÇ”aEF}ÏbÛØÁLhNVµºy_õ.¯ž¦PÄ$rš›Õ·3XÆ:Vðˬ¢‡f)jIµòÜÆøJÁ”dZqrú-c׸åê.©¶å[žé]Aµ$ú-ªîIÅuÏóªsSß/aQãóªßÇœ úN´&.ï9ý|Ä ½ñ}Š:Sü=Ä»'œà¿ñÈxˆ[áöé¯rLI¢~ç_ÔK^¹Ëª§¬^>k¿2ꫨžœ{ò\™Uþ1«aÿkÙÿªvês{R§9‰âíágÏ{fûø®õ-(ÏHËŸ#·NÇÄk1û€*Ö©º™œäiP®Vwþü¹vgÕÝ·1Õ<¡göýyïn:ß·ø~¾÷>¾¿qŽõêöü‡=Ÿ½K­×¨¾é´—ÿ‘ÿ1ÿlÚ£ °‹…”Ë.CQ†×ik&F‰Ëóx§.U½P½ÐjÑK¢¥i HDâ–‘˜!fˆ‘x ÿÒ';;ƒ/眵÷^ÿ¿ÖÞûˆHLDà“iâ;¸ñ€ÌEéæI€,XË`ÞÊ=é0EzåŸ!¶Þ,ˆƒ"8' R3~”E-ßé–®™%&oŒÄI‚úÖ]-° `¤­yyP5°É~éÚ(ƒXaÿ²ŒµÁ18dÞSo\‰„0/„>{êùš½ÉRGýlPO}øT_—à |‚G°Çùº~‹ßªw:Ì‘§?“§då-°¦3ð@.¸¶É}ªÓ›ÊVÝ Æ±ÞDMý"aœÈøÂ;zÆØ(}¿‚'pÞãùÝíÍo¾U‹{â’ç4髯¹iîUŠïiƫݚ¼xA¯"w"}Cð6Ø6ýT¬ÕXÓ>Ÿ-ö Èý]"F+Á³ :Ø[o :·ÐçйAìc/웞?s®õüë}KZu'qsGÌù,ÜûæÞóÿÆ{ýŒ®¹‡Izßa/2ô­kôàþlüv°‹mÓÍ.CAðÓJ»ð–6;/`ã!<…ªª¶´Tõ¶¥”ÖW$*¾_+K6‚ÄΖxÿ“üOœ4wñË™;sfæÌŒˆÌŠHÆ:$ÉꣴmòP‚"ËEÖµœucFÈêOM8º¶”kÏ2v*09×_ÿORž´œ!‹gü~S!Òdñ3œÏÇ×=Wa`‘_[_¦Ù/€%hAƒû(qlq¶kœ#x€¸‡ú‰ ÂÜ@ÚNܼ¯ Û° œoÚpt 룖ÙGã]p¾Æ-‘í·Nº§=x†_øaù˜s·HçÙ‚M®¥É¶8ç¾0WŸH¬[$޼Å㨋D‡ðo}ÞážàŒ9:…C®½ÊµÖÜ×ÊËoÍå£Íµ”yVFÏLßÈû¯Á-ÖÑ È]ä †ÑöÉ\ûÌMƒgigkw¢ÀØ*ðŸöÝg.›è5|A õ~îYãèÝÓ»hw;çÖ¬q¦äÿ¾Û=»ãÊÞ{Ø;gï5íæH:ÖÏÞ­¶N•e“pó&BêÉ?ÿ'̰‹}ÓÍ.QðƒòÖ<†ïà1Œê´”jkZ5­ß4B­‰vb!ÁÖʆW ñ¿ñ?ÉÉdtñËÌÜ{Ï9÷Þ¹WDæD$ 1iÒïñ׿C(Â4LñéäL¬3Fú­ù4¾@y˜d.ŸÏœgûm{ÙÌKóèX·Þ Ùõf:ð)ËZ§È: hÂkëüg`–ã\û<Ô`–«í‹Tcß\Ã;|œœëHW +ð*÷°ÎúNÛpp°iâ/áZœ»Ö9nŸcw¡Î¼Ù±!×߆Gø¢'8‚5X¥ˆ¹[†«q XË H÷ˆHjT¤÷E¤oOtõô£ï/ßp·œ›9ö¸>7¯ +T9ß%îe{Þà¼uŸÜ·ˆíeþ+å¾KòwOÆDÜ7·Ög¸‚ÖÒÿYfL…1UæqgAÏD‰óÕ³ ýUî™û×X÷ ãý‡ç¡ÉÜö~ä™·hÚõœÛ{üßùÖûžtÏ“âô¾fcuT§qö>)㙺^Âwú X·W°‹uÔÉJAà +.GßB¼ùl&™¤uLÌ6Ñ$C4‹DÁ݃E!("Š ˆËÁƒâYŸÄ¿É_Ð6ãá»§ªº«íŽˆE$G–(d)À·°"ã:ËÌ5Ì·2´@šë޳ÎúZ/¢’WW÷ºè1^~ZPãÞ +2^÷g9‡öF®SæZ=ªs¿!i\•ý¬A dã+ܧýÖlÃ>\Á;|Á'<¼Ñ3Ü´Ùs‹uváà‚ã-؃Ú>scöÒà¸Ëo]Ö\å~µ‡˜qmönë_ ¼Â5×Ò:Ö&ãÎ`çüÛöù-’ÂÙM̉L¡÷éy‘É{Œg1z©ÄÜÁÒ1 á”çó,#îWïAŸ½x6M§—&óêT¦é¸BÚ¿Öìp*éÿSé]öëÖXÇžÝ:sõNõx>ð#ã;0äZ‘ü}sªèÌù÷ÙÞa{ßÝ÷¢óî;÷åòLÂØÖÈ8üwx1Zÿ¿ïú»8ãô/Y,Ű‹uÔË.AàêÈ,l$<›— ›¾M›Ö3Í Æe\"q‰B"ˆ 6ÖbeÇ^¬<€ÿðŸ¤Tf_fªúÔ©SÕUmŒIŒ1Sæï7‡&eB@=ŒIaª1ß$ù4N:Ön1W f)gÞÄÊ-b +)rÆ/À"4X[F©56fî^ùuݺí›qžÖÙ¢‚ùRÒ¸:ãdo—`…š¬qJèÂ1\À9]üã Â`^o}ßp‡°Û´{pOp G° ë°KÒî°–6÷Í®SŸµø¬dÛ±ÊÚ¥Ž3Ö-ëØáJj;…gxG¸a_XÓ¥1Ø‹ +ÖUùÄäöÞ`ˆëÜgž.ë—5]qü k‘½œg½z:¬Eæ_³ö]÷^5øNENn»°ÞWɹêV\áäÕ³\§ÂŠ‘:–Y£ŒÍsX÷0Œàÿ;û$OqUóÿüö;ËBw=—£ç;è#´ÆÆ—XíÈÊã[Ü{ã;4¿>w¿z×ôŽÿ~7~´‹i°‹uÔKNÂPàÓj¹·âVTZWA +еj|EF&‰qèœ7àÔÄø_ùO<¹)ƒ/mïóœöÜŠHADbH`Ná6¡k´2CÄqUÒ9«3øë¨HeªÓºGÇùmºN‰ó[Ì¡aÖ,›9ºG“¹WL_Ŭ™íÞ5Ò8[”˜>ËűmèÀ6u¨ 8‡Wx§¸†{ø ÎDBÄ0·€ëÏ.–¸ƒ1<Ó±í &p »Ðçu28äuĘzäî÷8.•i} 97¥‘‘rO­!çÀÛçá ~LŽ“iÞuø)2ø–!Þ]°„¾7æ”™½3î5æû¹a£OšKÆ<:üyæ{YZ+ ¿u—Ú¯}nœ«½-êqŒÒZiz÷Z+.¶ä½Ë¢í–cÝ9sõ[‘ÿº.y´VcÒº®3ÖÛ\_!G䉹nÞY´çDÏwlÖvçÞÿoøÿû™x«Ü÷/®_Ϧ%¹°‹mÔË2Aà“ðÁÎÒByoƒd"7¹MRAÄ¥*nE¹,U”‡°µ°µP…¥…… ÿá?U'Íâ«™>Ýçt÷ÌôˆHJD"¨@Žá–!ó4°xšã +d9s¥Éò-ž¡-ųdíCƒbjòù_Á‹Hb&pÿgpö˜Hr\dÏt×>bÏè{eÞ Ü“ælÀ6À>lAZÐaßéom9‡ô`•ãlÌûv ÏØ!œðª}›°Î9½ëtÙ¯5ná >àëÖuÜÁö„õ$‘›ÄûJè3|‚ ΫuÖ¨Ëú»Ü߀{ô:nÏmæ­ÀÅÌkñÞ¾ Uã;k²¯Ê~Swël»¹böÕƒzEGë]Â'ö?Ó¸ç³Ö;yù{^ÂïÜâöÝêw_æ<Óó’’áó£þ;§‘ ŸC;û7ÞD®¶žÿðÿaÿ«ïÛi·Þ×ÿ³¾oí*Ã÷°‹mÓÍ.QðÓØØ{‰x¯¢Ó™~ë¨N)5UJERâc!V6>"V6+€ÿÿIO&³ø%sï¹÷œ{ïÜ+"žˆøP…ô©ä(käR yæóHãÇIsûœS"k;?`‘ë­A…ó‚D*•9¾`Öè„Ücê¦ßåŒ`Ìü²ÉYeÝŠ™§ñ…¤íy +Y¯ÎúÊý&܈d&¹2³hÃ\ =¿"c“ð3hß!ö +çp t1¬@ÖØnÓÃ#¼ÁÓ Ù…ǯàaß÷ðÌZW¬çÆnq~ócZ….lÃ)ë½À-×¾æúľ¦`ß_3`¾sµ˜1—û€ûÒµö̾—yªÅÿÜLü‹ˆñ>ó ùo¢Äÿ\bN_7š\k—g©bÖ˜ÃÞ)ÍÝàYº}¿Ã\sMîžåeôô^ë“ѽӻ›vÿõy†{oúÎ|Ò7ï'âöíë»Ì§Ä5w6AûulZ²Nî^Ó¡}°‹mÔÏ/Aðá"qô¿ø;üŽ.Žm·Ýní¶»­¶J‹UBS4âW\D"ˆ““Aâ wßI¾/ž‰Ã'»;óæ½ÙÙ™5Æd1  ó@NÉ(¹äÁg›/Kn‰|¶Ùø"ë¼/ªŸyB*1ÞW}Ç$©~Yƒ^%GȾ˜"š#é«R…Êθ +k6¡u²õÖáÖ˜‘1˜i<¿Ã> àmSðmÌè,Là~í7°Ã˜3êC‡kÔ`­%e †ðŸ¼^3ϤЅì1vȹØz¨=Žë¼ÀÂã›r«°Å>wÊy³æ&ëöØvðW|›kÚλtØgsÁ ¯Û̹¢b[\k±È¶¦ó-ìú\³v¬¾g]«™ßý”°­Í<}®í3ÜÃ.ëÚ¡"{DöGW}×”u Ù·²GÎ¥Êx}Þ4÷œÊ OÉ™—g÷ g[æ#ã%Nrgžª§ó¹ÿ?ÿœ/ã9†°‹ÔÍ.Qð;ÁÂÂ+Ø{/etÚaªcZ­*ª” QÂBˆˆØHØñ^ÀÿÄÿÄé$‹_fî{Ϲ=uÎeœsY !eȧÉߌÑ'0ý‰=Ó¤ãÃ?¤ã)ù–‡*,Â$Œ©så}"æŒ8§%*PÞ¬'d_ *R‰9k”˜8%Žm@êl—M>+á¸%ƪrN áÕ9oðþX}xAÿ ŒÁÚÏp«´ ;Ð…mÆl¤4¯Ëøoð=Ø‚uæÜ`<É{B½Ÿ±Þ( áå®ánàîàœñÖ¸¦ xb®SØ5ùd=Ë|v˜SrÁ1÷¢ëéðìô emÆÙãv9¾Íï-3§–R§*ïfŽk¾‚wø€[ž¯Þ»˜%é‹yßÚ®q?zgã€={ò»ü‚#æ,eŠ)¡ +ãÊ\ù=ÛúºŠ8_sÏSìúë gÈ\©O­çt½fRt^à~ëßwýõmÿ?²&‡¥ùlMK{â?¾R¸t€°‹…ÔË.ÃAÇñA"ñöžÆsx´ÕÖ¥Z´Z—ÞPE\q !DXYXXˆ•—°¿Ã÷$ÿü±ødþ3sæÌ¥3 !¤CYÉȈ$03c1©ð;>Í·IÂóxÝòÊX,>>>.“&GE²(EÚ²°ïœŒ3§•ÓÄob^&#ãR‘ÜÖ>… +2Ë|‹|Ok}e©J]¤ÄøILDXüq³¬¿L½);r)²Æ^+Ì»*{r*‡²%-©aI¶åZne_–Éíªœ…åÚ•#rn«EßmsÆz®ä%„Žné“Õßå†5?É›¼Ê#óÛ~Îiÿ’O¹§½ÍújìÏ÷àó’þ䄲Í>üÌëäYÇ +{lDbš”óœ»+Ã‹ÆØ¼wòÀy7è/ÀïHß8O½È^ìž=ëŒúCè¡K÷°«Wõcµ°N›ËïXžßï‹çµÒî²ÝW3Ú¬¿ÄÞlî +9ü øûv6ÖÞgô=Gßk"ÆÇ%‰÷ÿ÷þ¿Þs"6_ôM[}ð?ã¾j‘[´°‹mÔ¹NÃ@àáz*j:^ƒ'à-¨ ‰ã˜$8'˜„rpˆ£H$h§„„„DIÇCÐ Ä¿â_e´¢ø”x<³³»öZD–DdÒàC•8Å óÈBòª>F¶Îæg™—“¿ž>%)áð(áôµ½ËPƒ* T;¯ ”`^à¾àêjî¶>Í1BGž=ס¯sdçÓ  +çr¼´2ßä¬ÐǬS“"æ•)rúlÁ¦ªëÀ ¼Á;×y-jC¶yÝTñ6ãÆÀ1Üpÿ>DFf`0ØÜÃÜÁ+™ÿz‚OäOÃ$ï÷`—snq=œ_ãÃÜÂ<Ã%rÝ5²{fÇjq¬H=³™Ü*÷ÕXeNϡȽ6ãï±W—y%õÌ4/ð·ÂÚ>×|%2†w`bVdsCl +÷NÙ3Ïw¢@æÚ¼3 +ÕœŠŒ™3Èðü–¸»öˆuʳÌyóIÇ÷SЉé3nû¤œz›ï;5–ýÎ,ûýˆËðÜû¿{PEI°‹mÔÍ.QðÓÒ••…¥‡ð"vÞ5m‡NÛI[ý.­ªï„"ˆ¥DˆH¬<VÀÿ$ÿ“^‹_fîÇ9w#"ÉÂ"¤! ³Ž$ÍC +|Î ¡ -h@Ì‘ÅyÌ›‡"`}iæýGnÛb|®2_–}nÑ_[‘Ø8à™cšãv8/pâmå:· +M¨±#½¯p¬Éû"ãæ´¼¡óŒ%æl°–ߦ–³–­¡í:éø2÷¨¶àžà nà6há€méÂ:l3^m’λ€øBí&EâˆîjÿDŸîáƒëžÁ\³}—ðߘ; Üßñ¹öH×ìÃ*ŸCãïá^àk¼rOûÐaݬU—4OÏ©½³µY» +Õ§û]sêmµ¶<%ç}U5û¬ãÇË|'ÇÜó©ÈдHb5›BÍ&Ð7ʺ´dð­ZþßI–ì›)s®öéòyÍ1ÎÝcMþ~×SàUϼ‘¡EÇS΋wϸ­“‰ÄÛüt$ÆØf†¢ÿ¤ μÿ ¿@™°‹uÔÉJAàŠÆCÎO>€ïà iM&Ñ,fsKbÔwÄí"T½yóàAÁ¼ ‚‡<‚øù‹4ƒ>z¦»ºº§§fDdZDâÒk£¦ˆÆ¤`rP„E¨Á2¤!æÄGä¡Ì¹ž³ž?Þîcdý¶ÏÄ?âäqŸºŸ,ÌÃ&¼ˆ&àÎ ˆ¾=î+õG¾Í:ÒÌWàsdxv&9æsYŒåË8±9æZ€Z¢ +Ôa•ý%Æ–©À>[ƒuhÀÃÜÀB“Zp +mØåœ&c´ïˆ×-'Vs=áÌFDpü a,ÔzFÎ=0̵ö}Nàà¾à :pÀõÚ\k 68ïÞ¡Kßð pÉç´ÚsÕ˜CÏDë³He'¦ìSa¾sž]ý6·DöN |G ÆwØV9fïTÇïq6ã8£1‘ÁQ´z¯9_a›qV7¶ŽÖ˜ÖšÖ‹ÖsRzõ—e¿öi­Ïp,ÍyUÖA{Ð9 ¶y>‹ûýû®’ó˜Ûÿ=[l\úÿŠI¶6fsì?ó ûD|ñSd÷Qé×Þ/%£øË°‹mÔK/CAðsIÄFv¶¾‚ø¾+[ªú.Õ–VõåQ¯hh;B<"ÄJˆÇÆV"‰á?ñ?éÉÅ/73sæÌÜsg®ˆ„D$,Ï 1eD`2£*°€i3'$íÜIÆ•˜#nÖôÇÛ5¨áæÅ(â&›…9ÈBžD¼>‡´¿` ÒÜ_Ì'N J1§æM³&*ã£uú/.g,A–¡Ì¶Sî½Î7^¤<,Â*lÁ6lò¹{Ђ}hÀ:¹þC8€¦‰?‚¸€¸¥;¸‡ÔmH¤5骉ôDý"Ý"à "æŠ9Ôd¾7ø†Oxkî¡Å5OÙv{ÙàÞ^‘³FaÐ%ïðÈœ-¾o…´.ֲʶ=§Söy,±Î®.gpÌ}Ô8V`­óæ›Íó¹ºÃ\ò[¸±,óŒý£Væzchÿð}ËŒKó\è:.‡;cî\ê™×3˜`_Ôôg¹ö.׫±/Á˜”©½öÎh~=§zÇìý´sô1Á§Žë?à¿ÿˆí÷k{’‚&o”µHþ˹r°‹…ÔË/QðC"XXØH,Eü$þ$Š>ô]Eõ¡(¥‰Tš"%,+BB,HØÚZbÉßá;qM"¿ÌÌ{¿;sæÞ‘qù6F£d×z/Ó0Ãcœ¢† ²¼I‡ŽŸ… ÇÀGÖ߯Û?™Ÿ„ÄœùBÌ ’w\Ü—…:ÜÁ+‘ö´ÝãÞúœÂ>Ô`öà +ž™¡ÇKgÞC8ç¸:ë Nà ™KÈ.œ£í®™Ù¤:ß5˺ͳ.¶eØf¬nZ‹EÖªÄyk¬E…myfä(Ãïlß°Ì:6ù.E®…ÙÚÓïs 7pÛÌÓõ`{(ÎlË×ñ¶.ò{­ÛšÔó稲n >»>‡í“03Óò³ÿÜýâg?Ûk*Â|ï¾¶kÝ»îÂçaýíú¯~ÿõ·ÿÏW>ÚNU°‹…ÔK/CAð¹•H|;ßÁ‡²Jé‹V[-·«UJh‚xm¼"â V؈­ø!þ‡ÿIO„XüÒ;÷ž™9sf¦Î¹÷­ŸúHÛò-c…¶Å0E`"¿ØQHóYÞ…Ic†È¶“P€*g)’\¢dûEù-Åy3P†X‡%(ñ[ÜŒeÛÒµ&Hëå³¶}˜â0¾‡Žð,5~„+¸5Ža‘kžä®»föD÷¥Ìzè÷:k'¦ŽUÖß7ý}î_ŽJ¬}“ý +Üã åÌ>Ö8~ÕÄÉÕs%ÏiÞM½gzFõLÆçó|ì±æÇO¸ÖÙÕû—p­;kï]Œ9è9Mr.½×ú?¡m¹»ö"üƒÆkû¯¸ÿâõÿç«NŸº^°‹mÔK/CAði#"ai';;k_Á·ÑêûáQ´h{)­Ö+¡„ñHˆH$ÂÎk!숈OâøŸdrbñKîÌœ93÷ÌÜ뜋»?1ˆÂ¨!ý ÈRŠm7F’Òô_¼äÌPÊ“ƒX…:TØsP`LÆË¯su¿y’Ø"ç‰)ög 雀I÷úsl8? ÝO6` V8¦û•øÌsl v`öaZŒ/’Ä—/y·iµ¨q¬Å¾&Û5jržŒ/3wÀµŸ À0t¡ý×ðöˆsáˆsØWçtãyý_Ð}p€Ô(\Åó=ôcî;<œóÚp·ðÀ±S8‚c>_Àë°É=_!g/|cW@MCrÆŸ$yžànXKy÷%Ö¦ÍÜ—pÈZTYÏEÆÔ9GÕ¼óªP™g¦µ x–Ó4Ës’¾Þ‚7¦÷­ì)1Fî’½»zÇtLûõ¦ ‰És½:ë×àön缜ò=ê÷™24>iØïZÈ¿ä‘ÿ_ñã¢F„´móE¹Öï¾ù¡¼?°‹]ÔË.CQà…„„70—ð⌌y‰­j«E«7—R©¢.%QqI‰„¸ML$ÄL„`ä $†þÿŠe¾œ®½×ZgŸÓ½ˆ„ä×`Àà\˜†«gØË {‚dó#0B#Y˜ƒ<a‰ci渺imÌ3F õhÞ8$Ù{ÂÌ'çyÿmZåš–¡k°ó\ã<ç`á +nà ö`Jì¥Ì@µ%*²§öÛâ:*Œ© +»œ/›µ¸ñ7‘š.è‡VÄïp /ˆ{EêúD°†FÔ4öˆÔˆÔ>a®Ú : 5_ðp—pÌû®s]U>§³Cî÷œÓkÜûÛ‡gôï†W8¡fŒß²ÿ)\Æe“Ï\fß{øF~®ŸìW0ïSßeÁ˜…i˜4¦X£ÿa‘ÿQ†{$Å«¿·RÌɲOŽ2&ßî÷(¹8.{ZÇuoF=ºïÝþL›{%åÿžŽ™¾®.,çÄ?wQ“cé¹¶çÓÅzŽõ\ûßu>à$ýïƒíüû€²}°‹uÔ»JA೦H‘Â7°³ô-KÁw°ÔÜÌM£h¼„E#ï + +â¥/………"‚•¥½¥…ÿ°ÿÁã ÅÇîÎÌ93;{vD$.¡‘ŒRR„´'i$HóÚ¸¤É§ý)#Í™…<ŒÃ$”¡«Ð‚*Ûs”§,¹¶ã-§ýEæ)²¿Ä¹¦y-ÒÌAŽáàŒëY¢×6‹°°Í8óN÷° /®bâ¨Ê«¶/3ïíð¹Éõ°Ýå_ƒ:m‹HÐ}Ð>Ë%<âyP$‚w~ˆÄúa÷ÈéBö5À· † ãŸà®à®á”s·¹žuÎß"×¶‡|ÿOø‚W8ç>í¼…‚Dqÿ 'Œwï»Ïñ-¾w›ë@¾ †¡›ë«óûUÍ^èÞÖÈÝÏrÿ+¦¯ÁÜm~ÏÖ‰3!ax_25Sö¸6Wc®ö2òSó*ãÑZökÛökýÛqy/ÖÖΛCãÝü)CÿC—öÚ²Œ±ÿ½žqgIÜŒ÷ÏÿœQ¿Î“o¶`œ°‹}ÔË.CAÇñ©hÄÒ3Ø{ vÞÀÖέÕjéÍ][­kƒÖ%"""Š $±´ ^ÁZâ;ü&Æ ŸœœÿÌÿ?×sŒ1ó¥ÿE {ì{ƒW×åºvWϵÇâ’Ĉ'…1Ìcy¤½y¸~I±ý3Ç4JÊõòRz·}²ŠÛœ&0…IOUÔñ€G\b³˜ÑX“Ê/` û8Æîñ‚g\c,aAul^Ykó”4FAý7°'Û¨aUsÜñâv‹²‰+¼áOZCýëj1¦½ ·ÓÔ ú‡;‰uÑÖæêCýo´.›{ˆìjì]oŸ[š×ªæhÛ/¨Ñ ö=ÄZBmÄ^q«}¹»gçr¤z5­©*nͶíŽZè@7Z•[ÖùçµUQû_Ñþ—t³ÚóÕ=Á©æ^Öùæt_Ræû¾ÙXV2^ÌÅÝݳßÍP@"ÀÝåàÝöÛÝØ®_úYOÊüü~;þoß¡+ˆ%•ã¾k›ýGDý\à?'øŸ‰j~þ/>^ÒV°‹}Ô¹N[AÆñ1(¢B4<OÄ+¤MÍj³Û˜-!¬̾„-„ˆ""Q„„¨©(()èxþ#,DñÓÜ;÷Ì93sïÜBk(i“vñ÷It!,0„/FNÏSèò|QG™¤ø¾”jeЇ^t«t5Ó.ÎÚIë¹Å-à®p%äÝØ¼dU+£˜ESø,ÓXWÎßø¡¸íIdµG±ŒCœâØûƒ¬hŽ·ˆ‚j[åŽ +Êió˜Ä¢‘¸'\âDã•{»8™Ö}àæ¸¢ç×äi"wj¹æ½%êñAª‰yÀ_ßQî ·Ö¢önIëµ5üÃ#ãkP§ß1ޝ¡ôÍŽ8ãÊç÷° EÕ´wu#ÇêS.; 9}7ÖæÃëo*«ëA±ÿ­š.ñ÷Ööi|NâYèqχ¥_âùÐ}îñÜ;_¡töRnN’,ûË×cß:çÝ®žÅÙÿ Eü(ÆûÿÐKÿ3{-1‰°‹mÔ9KAðIcao¡ŸÀÚÖʯ#Ys×DݘÄ#1ÉÆDC<ñ@ð@DA´,¬l m±òÿØÿÀ¸¦ø‘ÉìÌ›7ovG)Õ£<½ÔGA² q…1‡ +,ÃL acž?ž?®ßòõõCŒ1a€9D ÊgQ²™›Í~=OrÍÃ|+hƒ´O!ãks Y+ eØcþÊ'Óáþ‹—g<©K²”!aV¡Jó0Çe¶+Œ›ƒi(@‰f9.Ǹ“ƘÛú¿Ëñ5®½ 'pWðŠZ4CÚ¬Ñ:lrÌ;žµêH@ú~àíFh@ûná’.àÖ`…kÒ–±ß*Ÿ_{qoð]Ôʵ;™ßì³v5îË¥ã-qÝ=¸'x;Øe]³<·4ÏJ“:Îõwy¦yÆ—šÜÇW7uÎ<Ь·ÄVÞ;g;I ÊðÜDJý_£uHÿç§ÈaŸžç¹Ê^F”÷Ž&ùßa>¶!n0soK¾±°Oˆ,ŸÅÔß}è±õ¾óˆ‘‡Œ“û ›ô=$m}o˜÷’þî8Œœ°‹mÔÛ*DQÇñµÉ¸pãxïàÒ•g`ff0Nã4ÎŒ!‡(ãØHI”"Š’p!¥p%I.¹ñ]öoe7ÍÅgöÚ{þë¿Nÿ½1uÆW/!DЈ&4#Ž^Œ`“ØÅ%N°„NÅ7 ¬<¡y¤Qܽ‹·}£ÓŠIT\¿¨æÖ¦±ÛÕnÑ5‰ÜãU€>^5÷·CZS®Ìúëò¸xEüÜcƒ'!Ýè‘>L`ç8ÃF1¤ñ¦°ŒEÍ1£çSê3,¶ÖœV‘Uœý/¥Ü.vP×qÍ9¯yãïþš¼*Ð×cý^)Ï/°é\ñ¬ë5Ngó|Я%´¿ð†\!§zÈj?¶°¢5ω]û¾ÉQƒZ)ïUjŽåþœÿòî)oFû4¥\ØÇ¡æ~ƒWsNûkÏÆÖî€Îª? ¥}ÕÞ¹3sçf×ð„|ê|uÅØw£Cõája"0Þˆb3jÛÚK¿ö,Wëù÷¶Ž»gÛoþë6¡ÜiIi ]“Ònþk<èÛª1š +p±¶]è½sï^–=ûé ¦•””žÝ´þ'üÿaô?4Ún%öëÏÿݰ‹uÔËOSAÇñ)nM„¸`玸1ᯀ…ÿƒ \š(¥öiÖbÁP´¤šøJh +TVcˆƒ‰+7ºv†Ç¿~'7añ ÷Μ9çp¸ƒsîŠûoø†$ÒGwñ-¬â1FÇPÄ ØóUŒDÄÅ¿[­œê¥bâê-®þ²¸‰’úÊ}}~Ç6~â™Ö‹ê9)Lâ½s±SèÇy™ÇmÉ+w.¨ñŽØ^çÚˆ?qݼ³æ¾aŠ{…=özp]¼EE3œÃ”jY/ øŒbÏ¡]3·õG˜E9°„ç¨áî)ö5~sþ úÀz¬ z‹foo•û >àú}"–w 8s‰ßµœp–õ]üÀŠb+ª½¨¾,WC¹[òñhv‡ßP]‹ÙÀ&öÉ}Ôr;:ûUÅÚlþ²ß¡ýOXVïuõ] æuGf4oóPk%ÍÝÜBAlŽ/Ð úm¨~Y3.É´êþ–fYSûúÂ:–ßç)=›ŒdÝÑ÷=¥þígQëiÉŠ¿'þ%äºø»ã÷íÙŸÃбºþž[Þdp>Íãù{}®ˆ¯?pŒËrø?êEæÅ̰‹uÔËJUQÇñÿ±FÄjØÀO ø½@àG=^ÒÂëñŽ÷¼ßSD‰JyAˉ(b ‰¨‰¼ D„¾K 7|Ø{¯õ_ÿußfVbw¢ˆ!ŽJTééTˆ+«GýèF ªÕ®4$*î½ åR&>¯/ƒwx‹Z$1^BqI a hPy½ê𠋘×wRq.æS¥¾Z1ƒC³Hxµ%´k¾µoQŽ&ôâ±<d›=œÅK³¬ç”Ÿ )­Ó*qyhÃ^Qö“Ñø:Ö“;#î¨)~=xAÆ|Ôz4Þ.åÿŽSr&÷ý^Kø;¬XnþQÿYÙ°‹uÔËOSAÇñ)VülÝÊ–?‚=ÿ¬ÀZLy#ZAZ(B •WÀáY£‰(!µ!Ix¬$%°ä{èo’ëMX|r;3§çÌãÎuÎÕ¸¼Zy*u“¨øvš$ˆy">O¸} Î×lD+ZTãY fLí¸bú±„MLá:ÑQ|Å%αˆýÏjÔX»Ï‘ÄVôŸ$ð¤U§[¬ýݹHµsÄ•:WxÈïbúÏ0†AÍg‡¸T‚µEÊéû‰q cHu’Z›Õ¿UüªhÿU\¯¤ÕѼßcoRÿ€-üÆäðYñoµY|Á6V± \fóó<Â;Lã1}ÿðCrzf•Óê.cOì,®q…#|Ãfk57°\è 5/Û“9å´ùŸâFÏeíÃösBFuŽ/uvƒÏh¿:ˤÚ}ŠM¨/­øÍáŸtn–ÏÞ«.ÅNbWûlÏu­Ëj½@:¤Ùåß=—Z4nÚ5—_ìq¸+‘ +íEFñþ.ÄÝÿ÷Ä÷[^ÿŽûñð½ Þë­{\kMiŽ>>ø]',Gm@8¸® ¼h(ç}Üîª/”°‹uÔÉK[QÇñ›ÐtQܸsá_áÒ¿ÁUÿ—jL'T´jL´q¨cœg,‚⬨‚…èÆ…àßÐ]¿§ù]x}ÚŇ¼ûÞ¹çÜ1ιZWT'õÒ q‰½#{§¸ûOœI  )$Ñ(ÁÖnFF°ƒ<–E/2ØÃoç"•¨àùChCKHJïM;ºÐ‡~ô(ç0Æ1¦:_d+ÔøÆe £Õ<Û|5¾ ¬kL¿û‰çW}ŸÀ¤~­NZ5¾ãžØ2T¡TsõóìÕm^_ñM}0‡™@Þ)Ìkl<›XÆ4f±…«Æ.V¿¦>ó³8¯H >j8Ä5žPÀòmá/xÆNTÏòîX¾SœãL}ójTçVµ¯¿ªyúõœ[‡Q­SV{8©wíã€ÖÞÞå—Ö÷\ ÏŠöq]í¬Î@ Ç´â~hÌÛÚÛ¯NW<»ÆÎ?;ë­®xîüy³1-²Æå`½¢5°çϪoyü]ð|;©ï–¯[µü÷ð½ Þ夿aóšÓ\ÚñþŽ&Ü¿w6¡uîíÿH\µS’Ð{þÿñb¡œãþ¼ûô°‹uÔÉ.CqÇñ?k/ 6Þ€—ðO`¡í¥†RcPcƒ´SJ¹f’bˆ6켆…ßá{ãö¦ŸäÞó?ç?œûosqWªöìIkH"’'–åxhƒ™'Q¦&¬ÉH~0nñé–´lÊ©ìIŽØ´É—s R§ç'™>顾7ÂbÆûeX¦$#³¬1$°yóò©µj~Ù³»“G¹— ñe_NØsž=›)È"ó²æ*µ6Ϲ,Èû + Êç¶ñeY§7k²DÜde…ñuÆ×ØË±œÉl‡rìyz[ä\EÎbu·ò†\‘_àŒÄ®©µ½Ê»|È ó^²Ÿ›ÿY½­’&i–ZÖ²õÉÛâ|Ä|ΗãûeèÏ2ý˜¢×ã2Gÿ³äMÒÓ,ñ½\$w†úÞ3¼[Ý<}óÙ“Û]±û×íJïZï|[ÛÏÄo¿*ꫬ–iÔ{Œþ¥\é= æìqw2ØÓ(9ö»ùïw™„å S“¢&ʱ5Û#s˜Âÿ%¹)z’fo‰(WÅò¾Ãþjí°‹mÔÉ/CQÇñ[â?ð/øOü5†RóPJ©C[óCÅLŒ!ìL‘X‘;K6Øá{ô׸^,>y¯·ç{î¹÷=ç\…û«Lì>Œ*Oe ®Bc•^Lu@8Ç ^"R#~¬ŸßbjÑŒAœáùP×gdÐiÜ0^Èõ ;èA;:Љ.‰¡U9ë¤^c ¤1‹IÍÙ¥åsýÄ;^ð Ü6ç +ñJ½Î+A)÷×(RíœkÎ-Õòˆ;͓ѺGuÍݸì¹èõz3Ž”ú=¡ÚOTϺþ÷ŸKy9SÚ‡´j·žN+ÎÎI Å?kö;ª½+÷l¶'¡1ÖË9±ÎP±ö'ª\6WRµ&ôl¯·Ç–ÃÎSLóäÞ¯Üû ¨U-MªÍÆü÷ÎÆÜï»û”‹ÿ- +G\ýHªn/ øïy?ïOÜ7üWš°‹uÔÉOAÇñjá`"à w/\µ¨Ñs•Dï±wuh8ê‘P{Lãz±ÐØÛŒsÁs\9÷à)×c´Ob³8ÂRH¢ÝÀk £_í š»N¹XÜÎpƒO˜A¯â[Ð(-jëB&°ˆ46ðo0¢9mîQLes òQÀý9Þ¢mÊÙÖÚ#’ ­§]9Ù¸ï1™U[J,‡i¬â—r¤\­ÏG¼Sn j³øm|Vü7œ`[X×ûmÕ{'”CZ–U¿)ÕÃêò¿Y{!¡¶—EšgSudžà1~:—÷/ØsÖ”ñîV±vý®µ\óî!¸uÊsNë·½Ó^ †j;„qÕi\û°‹_Œó ¥ú¾öÓ+6ΤâýþΨÕ²+ô­4‰Ý¿rÙo>¡ûf´jo‡Ôÿó–dkã¾j|ûÞº•ËœbIë[ÔXÖ´ÖV_+þ;÷Ïáÿ×øÿ×ÿ5.÷_Ä]î\ðç@DÂÏQõIªÎýêoç!å.wžDþÃw÷¤î&µ°‹uÔÍKTaÇñsµÜ$Am—®ú;Zöo¸šG§F2G3ß_20´,¡‚©|CK¢U‚¶J3¨A¸)¿Çû{ðšµøpïóvνçyî5³köou¨G¤p5!ÌKknV|M j§%ó»ŽF¹‰[hF^qêê±}îvÌ¢=³ò*¼4+Û¢]Kÿ$:ч"FpMhÓØ]ÅÔ¼våÏK÷±FÌj\ÂyÚ èWœ‚b6i­k‘NÅöüÃÊå9»Ñ«û!L(ÇYÅ_ŨÖ{ŽÛzö.é– m‡(á=Öã¸6…Çx$žïæð?Äç.áµÆb /@mm›<#µŽÎq¿Å)%x¾i­S>_¿¨%õùØSõÃ.þû‚j}‘öwÌhÍ2}•øÂ>ÿf¿/s½Bö šÿoñ™±S\÷ñ oô^Eí__¢vÒ£}Ö™™ŒcGœÓ² +ø³ùÞýT-C ¿Þ“~ǬjQ´£óçZ¥Yí|‚·[´ïzž'x…çŸÉ6áœDgT¯Ú_ñ.®Et:®ça}íè»ÊIÈwC$|gáû ß_V}9;þ_ÿ”$Û­ ï\Ðú´üŸ¤þ#Ä;œw oÉã°‹mÔ;OTAÆñY¥A„B(¤ Pz:h()ø| +¬÷†r۰˲Ü\Y`¹¬&š! áj„D† DH „€V +*þÃ>' '¿œsfÞyç=gfŽ1&dò‚Ž0¢x刪݋K³xq¯ÍN\Ô'¢~׊ˆ£ÃÉçå÷êiSÌ{cyPoÌCú q}N›ý„7èÇú”»S×”ú3Áz”7¦8;vÿÈY‹—¨âyYô"©ØN+¿Õ¥œ}>vÞ·Ä8>ã”ÜOñ„û_ø¨šÒNýi±5c9U®Õ÷Ÿ\ÏPÊý>±„5¬â+~`G8Á!vñS±Ó² ø=ò•£ /P¢ZeËø¢g[ËLaEskŽUõOi­¾«ÝÖqEî +s€uõÿÁ%í 8gÝ+¹n &ÿýnòÿVýv¾oz÷]·sÎéÛŽè{zkÒ/iõM¨vÞ#P† æÛŠòûÎÌj2Úï$«9½ß¤Ö²ÛÜî¿^Í—Òs‡Ø½—ÔþÈ8ëïíÕ1Íéõóž:ðhD!m¹ :¿̶êI(»Ä|l›=‡-æî9öÎ}Ä'êôùÙv÷¿Ð¢Ü­æî¹ŽÜ3Ö¶ùÿGAµ…®8´*̰‹mÔÛK”AÇñçõJ½öVï…‚À¿À›¼ð¿Ù¶=dkí®yÚòÔ†‡Ü˜v€h©ÄDEÜ "…„. ‚ºêVßÙ÷74,]|˜}çyžgfÞY3»f±D ‰2”úýø¤\?Î?§Õ&ƒx¡pŒk³È¡7‚xiñõÜDe|7‹Þ™5ÝÇO\åù2ý (aÃD·¤ˆ!™À˜ÆÜÖ»;¸‡ +>✸´Ç ŸMj¾ë HQ +âû‡¥¤Ø.ï –ñ+޵ñ{Ïô®¬ÚîªPnÖksx$î÷<ªøJœt£‹göÅ>`;øŒ}|Ã.>á ãýtóm Kò5ü%^£×Z¯×Í+.Ï&VðJçð8 þsžKUskªí°­¹ûZÇoœ’·Së»SÍ[Z£ÛÏ×xÔU ÚÚÛ±†3q¦ôŽ5ÚÓxNÔ +ö¬é ȹÎtFþ,*ZÇ"*Ž?«qåpß@^߯ˆòùo¨_òê€iÅÕøIÕµ ³XÕ9ôâJ|Fõ3e£v4k_ÊÊã¾ýœø»·wÃõû»—•Æ{ïïw*xÞïŒbô‰çïq&ˆŸ¶ÿÿ/4þ%|þ 4Ãóe°‹uÔÉJ#AÇñêgð(Dæ)ŸÁ“à[¨Mר‰É·ÜqCÅ™ˆ¸Ë(®(‚ƒ;zqE¼‰zô[æ×Ø4xøÐµþÿUÝUmŒ)2)…bËK™Uøú>?¥Ø'è’ §¿T¹B¾ºW9*Ñ€a<ãä>'‡útâ7Zð QÔ Ê#ŒS«1uˆ£I1úÄæÑ¡xamD«âD3¢>wLúbgc7k³xdíYH§|†qô£[±5§IõVÍíA/ºTžÀ6žˆ•4ÊXÁ:NñNûdR~Á¶p‰œc #ÃBê:ò1  ËljÌ’r¬«þ“˜Ñšîð†WåØÔÞÿêýÎáŸÚ·ô¾Wõ<Á=n´ŸkÜêyæù6IO^kJ9vãËÒ·KBõA­wM{°k;bŸÙ –ÃÚœ\ÚöЮïÑ¡÷4­ñ6†{îbõ&uÆ¢ÊçžÛV-µš×& Í+ߤòŒè›bW8Öw¶{^Ä!ö5Çž{í½)÷ؼa•+LêÎÙ»Wò ÿ]vÛÝûjsDÌ×y­WÜÆÙ§÷>ûÿ îÿÀÿ_úü¯|$í¨š°‹uÔY+„QÇñƒ×àFÞ +åJÞŠ1ÃXÇÎXÇ–‘5{ÙE"²'ûš\H¹å·Êß™ùžzzÊŧÎùŸóœÿYcLIȇ-¥ÅQúÚƒ>ú„P"F‰'^&¥äsõ*„i³Ê©7HŸ¬Ê¾¬É–eQbÒ(ÕRIî +Ƭ£­^jéccÍÒ[n•N4Ñ¿†ø°LÉý#h`,Ç~•!aÞƒ²#¿Æ$e%˜Oæ=îé×ãÉß…Úbèe¼Ù’¹c_lýRã§É¦1É’ªržâr Wò˜èßO›RÖåZ}S-¹’©ø—œÊ±‘k›sXâ 6äPnåY^äOr&»|wL~;—{y` 78%Çû¶Éø+ìÙ‚ÌÉ,lû·æš#ßþÚ=kG'ë½`é*ÿÃö=‘7yg-Ã|eœiÖ:Ï™E9ïÊQʾ˜­Û{W…Zbn^î®E8ïirعvK‡ôËycž{1J¿~Ʋ÷µÜ£ar»·áÞcÑ?Ü[u\ܽ×ó97ñ{¿vî]ûÊ!ߘþÿLÀë®L'^°‹uÔÏNSAÇñ¹u­^€¸0–²rá °õ!ÜJhiii–p‹© 4¦‚0€ÐTMLý»1›°aƒÙhXcX¿§÷wÃDÓÅ'{朙¹sgêœs‘Û’”ñ>âü;’ìcâ–;‰iÌbEdV<«ç)±öPÐó¤¤Tcñ2*¨â^â_°‡Eä¼ñÍ òª/¨×|eÕ”´Æ¢Ö° þ9­ßæÛF qWµeÕ–¼õßÃàmìâй`!¨ ˆ½ÂcÙÀ:V5F +jûªb} ljü&Þâ”±ÉKütîÂ/°¶Ä0±Aú>âÞ£ƒ§ª7ÏðIÎÈ¿‚ë¸=»ù¬q^ëÝ^H[±Žú¿Rà*®á"±oèF{ÑkÿÀoü‰ÖÝ›ûÖÒôìjÿw°¯XKíçš‹3›¸…®Þw”ø“xïÑ—ÀY /¸©wÚš¾¯ýÖ±,¶ß÷ñÈË[Q_è}º¾[(vN*îü\ÏŠ–Áyå…š«¡qKê+)¯¬¼¢âKÊ«i>‹O{f$ã±{h÷ο·ñ}‹ïdZRâÇ ZûŒàíïÚ—œW“rÿßã¬~ãþxM–cÿ½ÿ¿¶:…°‹uÔ;O”AÆñó‚•¡4ØÛ™HGcAAE‚_@¾¬€ËevWX‘…•{‚¨ +ˆ& Xy)F + c $ØXcÿÏ›lBñË23gΜ™w3k¶sM’;ˆã[$qÖÛ†ô ‹4:Ñ®þ.ýíñw5–Á}ôªÝäJª/¥\}˜Ä[üÆVSîÅwóîI*hg‚úz¤W2âk á1žaLë„ã}ªý!æ±g]CêÛÂwÚuØÅ>èû‚e¼ÀKÍÁ8&0…Q †Œ(n›øCîwfåœï¥×¨2+ã<¢›Œ}Â{|1¶¡µcë8 ö*jq õ¨ÆTà21ÁlG¹|k`=[Å{¾6õE·5ýÛgÍÿ…ŒñcÇÊõ&¨gQ|oÏ1‹}k{¥=ü'Çö܈Ÿì÷íú¿*~Z÷Åsl3vKú~×™kOuž~®ƒÐ÷ÕwŸSÌ´¾Ÿ{^1Ý‹)ýzÿåÈYñ^§¥ðDFÛ¯yq 9+ÞͬîYF¹üžw«¯Ô”µâp©ñ;ôw¿?—”¸Ý.¥ýñ[õs=áü¨/b/Q%í%Õ› ÖOí®’ÚÒ:«¼öèoýìÿÎ)6È2¥°‹uÓÉJ\AÆñªn7.Vºq—p«ÏàˆALÔØ­m·m´’ˆJB¢†8ãŒ8¢"¢& +uaˆ Ÿ@\%Ùß…âb?î½UuÏ©á”1¦ÞdÕ…¼–p{à4Hø»ñ?âhAZÜ{3š$&qµ·JBíAž ^0¾Yñz0…ï8ÆÞ*^ÜË“¤ß)on©g¸¹´!ƒ.|ŒÚÓÊ×!Ä–16ŠÏiŽ·¼W)ÿÙSÒ~€%,cãZ˨ £½z† hÌpM\Î%²iLôÊyϧí}8ÇO9–m0Þü`\jAn;tã%8»ŠET#‡~áZdžrü¡¿B1³s25Ö9Ã%~ãWØñÍ¢öÃÅZÓºf1­§Ë³";x$>눖€s‹pNÖÕî=ö‹y˜Iìfçm+A=ÙRíÁGí±Ó-î<ç4߬+Îg i¬«Ã÷:‹AO¿×ß©Éhì¸óÏC1ï7Z×€7‡^íñêïâ÷)¥>÷ß'åíP_Pûiåw\½&Õ¾'þŒyýáûçÆµkTçì¹Íå›Zyº71/2$¡¾¤Ö÷Õdë¼KíîÜ^ýgÚ`m°‹ÔÍKTQÇñ玶‘ÿ‡–ù¸¤E»Zˆ+éh“šcêLÖhMš–YJXù†QDÅ 1½ …EJ/Ú&ÐE-\ä&ýžîïÀá‚àâÃ=ç9gžsî¹Ï3k³XkB‹$ã^»œ•´œÛ§®@gðûŒt(îû~ܯëóøx§req¸ƒz”¯#Èw>ÁÇÝÜœô$öétk ¸ˆ^ÉJNýKÒ‡x‚¿fÑI4ã ý÷øE;o–Z4«8Á³‘þqâßð ñÓ2ƒû¸ëÒstc(ây€sIÕðüSÄ·±‚ÏøpýU|ÄæÅˆGŸ°Œ˜%_{p˜v1ÞÁ¶ð z—XÃ?ÆkqœUTOì'Êxw ·-á­â¥xÿöJûÚĺ斵FIë<Û {ªÆ1ÚÄ¢#ñ™Ûw­ñ“˜ÃýÑLgì È],ÆßÓv”ë¹Îù–Åõ×(¨Šú†÷0‚˪7<^ó-K¹³ý‚CÄç5ßïcTýAí§ ZsµçjÔÕm^y‡5îÇ|í÷é·×ÔÎ*ž¼'áÝKãÉû—QŽ‘ø;F•¨RýÜTît°~·„÷/­ö‹ïî¸ÞÃÅÝΙ]K¸G°‹}ÔÍK”QÇñûÌ”m\´—­Ä?£Eî"7ýmÒLÇaÌ—23ß𔢠Å"T°BAM¥¤Mº#²…Pˆ+A‘¾Çùº>P‹s_Ͻç>÷N¡&œWýéqµ)9äÑ€úÿx uš“noœÆÄããºóù>ÏöP@«4Fñ¼¯ r,'Ö÷Mšëc=~ÜkŽØº¥ ÇzI¥”`ûÔ{CÈPÏ’Oæ>õ;´oãfñ“x£ú4Fñ#ÃkÌaSQ¿±õpHü2\¥üŸ°Œ5±úg|Å.vðñ×A>ÉÐl°ço!\(ÇMÊ'´Y¾QìU•-æŽS‚+”á#æñAãWð^ùÌißì)¹„Ûàþ%Uʃ³L®ãÙY†/X+ŸÒw·”³;û ?±…·:¿Ñ9ú™cC:Ç™*Æ8;“ +ÊÇÅo{ö¬¿CßÝï@§âÛZ›Ê×â÷ã™~Y3©ä\áâ]0.ËY$‹Êþ!÷$ôi/¶§.<ÅÝ9»—vg›ð(Åï±ßqÛ_7z4ßæÄo×߃×ýýy{ºžâÚÞ^éœ,·æð÷û[õwèkúÿHòh—‚Úï™?®æ­°‹…ÔËKVAÇñç¼µk㪕ë®Z´ÑÄ•´Hð Lëx×L"¤B¤ÒîFYø¢ð‚Ý(H»b.EÅuH ¿ç78¾`->Ì™Ëyæ™93ÇÌm¯3û(w¶H ÚЊæ8'þNÕƒ0.Õ˜&Iÿ3¾UBAèí]ÒQ¤E:ÔßNÕÛ¢øqì|äú¤—0Œi³$‡ržÿb ÔkÌrGq™ç%¡ý&ðOñ “j‹qÄ÷1Ú‹ëá^ôhíýŠÝ¥~¿«M¶{gãøáÿKÚÅçðÿMƒÛšW:°‹mÔËKVAÇñç¼ÇËJQp] ]»q'X;kå¶öÕ?àÝWßT’¼Aôºð‚]DJ‰$Ȳ‚Ò…$ŠŠB`¤m\´í;½¿¡apñ᜙yæ™Ë™9fÖlf­h“i•fiQ{»´E²Ò…Ž ®S:¢ú¸¿Ï·‡óód£|¾¿/‡q~>N7z1ˆûÃ=ÜEŸÚú½Ò£|îy;¨ï{'0Á8vÍ’« >i |€%Õ×áª(¯â¦ñ³xƒ/…XÛ²êÞa›~hÄ%ʧªŸÄ„LaŸñ +ââ^ªÍ=ñ_±†ï8&o‰Æ(GŠe¸‚ ³ sÏ\ç¾ÉúüÄoÞëÁü“·Z}í6ñ ¯1¯qß«nEk]Vy·'Sc–²)í)㦕fE·ÌŠpƒòMâþà2}~iÝZ>hŸCÚkÑ„jÊ{xÇxˆ'üwþ(Íb°‹uÔËKUQÇñu¼·B!ÂAˆ4‰¦Ú,‚è/¨‰3çMíj¦^óQ™HE>%-{(IH (EQR¡”B‰d&5)šX40ü.ÏoÃá`ƒÏÝû®ý8k?Î1³Z3;‹sâõF´£-h@½J׌KÚë¤6%Äs¨Q™K´Ÿ‘Gâ^oÅ &pWSyÕ'Æ%ó šÔ¿ïÌ¢JäQÅÿèE.à +zTvhüùç‘Oh‘Vñ±—Ñ…N\Lìá5 ã)ÏŒpüµWU^¾¾!ÜP>}¸±ïô/ŒÇÚ*æð“xˆ™xÞeùù‰5¼Ç La\唯¿Æ,àîa:íC)õ”E8ŠcØKì«æuŸñK¹•ãJˆmR–ü2ä“}‰ ꧈=Á._Â[,`ë´íÇi°ßÑ dˆÿ¦<ŒûfG@[{“™7ÛýǬè¸Yá_³=ä˜]¦í }ý®ýÀ¼Ö9?+ª€÷)¦äL"J#'»©=Ð9ŒáíÐ/eÚ;Ÿë‹Ú|O>(6‚ëº]:wÿß­3öó|Œ|Âs°&»«¿1ßIpƑ׫‰-+¯vÝÁ4Wý½ ïAúÞçÕ'Äò‰»ìãêþ#¼Oá»Ð$âãýÞwj­þ-hKÌ›þaÞôór;¨IØþl¤Ýc°‹uÔMKÔQÇñsGň\eE­Üô + µÒwØ&p%63Ú¤¢ib!Y&†FI’Ø%"’=-‚¢Ð…n +Ò*$Qò{ýÿ.]†\|¸ÿ¹wÎùŸ{æÞ1³Œ™]Š4!^ôá® ‡f\F'îà.®k=+!OFr’F£Æt´~QZÐ.ù(Ÿ¿—ø„EŒ¢Kµ4Kø~.š BÍ>nÛÌõ›¥J_ãs÷•Ïïõ†4ö C5µª® M:¤Sñ}ª·Wõ<€{ǼöñO1¬^ê½þ¹_1øAgÀïáÎóùæ0‰‡ªÝïë±zóËø… |Á ×;Ù·}Ð8£\~m!Éïªpù¼ÅxåÊ÷ïÿ «Š9‰Të¹+fEfÅoñ›çúdÎ!æ;Öð+ªyµS`ߎw¸ 8¦N ô×ÑÇyH‘wÓ¬”>¨dl0+¡EgY÷½ù‹¯ê×ó¤nw·ñœG—b~V}Tß½õ†îÈi;x¦µ)¼’'x ¸ðû{7uŽÂ]™NêqÅ [R¾GÿêÛëÁa”©'£:KñÙkøûáïl¸g…ç>¯ï„9Óņ¸løÿ )Šo‘¼òôj¯þì·i-¾ÿû)|_ú?#{ÿ»Õ‘5°‹ÔÍKTQÇñsG£\.ÚøXH¸éh´ Š­ÅœQgœi¨)©i5m*ó"_Ph¡ AVDAA/+qD/~Ÿ¹¿ —Q¡Å‡{ÏsÏësιι.çë–^$1ˆ® …¸Ø·<îà¾ê¤Bíƒz½’˜Æ¹(Á¸QÕËá&Џдâ)Åžâ^a×0 z‰=Æ‹‡ôá’æûË9/‹XD±)ikBYcZ9«qR’V9£>órYÏZÇ X·QÁ¸ž6ÿÇ2©xðm ÃÁ²??¯„-ïñ*f1¡zeµ{€9¼Àwlà,h,{®á‹¼Å +汊ŸŒÑîs•só/µUñZqËe+:ä$΂ùGN;×Іó¼?"Fï8m~c›÷ƒzÿ„o”[ÀYðîá «^‹úäüyp +¬?BÎ=çÃ3Þ¿c]^?íþ`K˜ñóé>ó­GqˆòGÅ'”÷[2ª[ûþ¹©­{\g£¨œßÕ¹²ûÀ>ÕîCAßKê³¢}±õÃ&Þá„öæaèL<ÁsåÙöózè &%-vû$|ÖM¢Np7,/·ûîôì£þ^…YvGìîä4·¸ÚÅêôüg<*Á¢Sjå¯M°‹ÔÍKTQÇñ3£ØB(ZI€îD„AË-Üî‚¶Ñ&tÌg®ã4ùVö2ã ŽNÖ¼ˆ¤…É”6`ŠHQ.ÜH1ÐÆE‹pâ"è{æþ.\îBZ|àÞsÎ}žç<÷žkŒ¹o\ƒƒ‡Ç$0(q¤‘Å,i>& ‰‹#Qåé/¯—o9ä1$1ŒI¬à#Ö±€ÇZ“ÒóÁ| Ÿ!íÇÖ»kLè"ºÐÉ} e<Õ~Ÿ £œ£Ê‘VÃÊ—ÖZÛƒ’QMÏtmçæ±,/µ¿­ƒwx‹%PB‹Z_Áuöâ+¨?ÔÄØÅ,¨9åZT Û£}ù†-¼V;wˆüÁ/Û¼WÜ#7gÝì¨ï›>U·æ pL]WpÜßRh +ømL¸—¸ÞÆ \@3.óü©ÞCMãÝèC:ÐŠë¸ úº‡›¸ææ #L½ k¸ÊØ_´ï'>©×eõ`CµÆžö¼ª^ÚÎI^=®h}U½µïï¹Ìªç6ö+Ýg5—õűy¿Sßaµ6RSã-j¶{lÓû))FQòŠcÏטï;Lú Ã;ÞZïÚžg{R¾q{nþóÄñžqñ߳рÁÿ÷þCÞ""õûbÏro°‹uÔÍOAÇñ ¦ÜH 1ñbB¼xðÀŸÀ¿àÆ“GƒÖn[ZÊ‹å%µ(P[•B±¼%HQ£ÂÁŽœ¼zÕp |ÇýMºÙÄÃ'³óöÌì̳kŒ¹gBw%))¤q_R®}CP¿ïÆe$©øñõÜØ£˜Ä3•®^@NëŒá)&ð0‚¼ââ×KÇÖwãâ9Vñ õ\QÜÅ}¤õ‡5o@e>g[8Æ!ê×Þ\¬2Þa»XÀ”ú\9‡¬a/#^+Þ[c)ì5\äáQŬö1«zUïRQœ7XRüW*7ñˆ— ü‹#¼Wß¶öü{:£ø¢µ¿êì\ÛŽÞí;~ï*n ‹xGËZîÙr.–ýXÎÎv£•9g8Å/íá„öK¸¥qÜ¿ålIõÛ¸‰^ôà +®‡ý-]¸ƒê}á~ÌglDÞ¿&uYÔ½¸óšÑYúó|¡>—ëh¨½hÂ\t÷XÒ™×uŸSê{bš¹\ ÏÕ^fo̹ÐiL;¹‘X6¦{¶'zÿ†öQÖ¼¢rÉå¢Ïõ‚i棓ðm>G][Ns\ɰi~WnŒÿ>²1Ño*ˆÄóíþ?Äøvÿÿo\&¶†ÿ·øñþÿÐ/ÿêç ¡ü°‹mÔË/^AÇñçÐôèΚØÚY4¤ÝèÂÿÁÂÝ[··¨kP*ÔíEiW"¡i•n,Ø”•Ø´bA "i‹&|§ïojrbñÉ9g.ÏÌ™yf̬ÎÒêcjõôõR¼'Є† ]ØÞÕ?—ÆX¼Z©Sÿt ½zºïöÀ‹˜võk +øñ±ñ]»$:ч!¼ÂkÀKéA—ÆoSß6éPß5ü5‹ž¢÷]Œa#x‡=üÄ161§ºaŒcKHaB¦±€X• |źê&4Ö˜â¼ÁTÀÕO*þû€›ó7üaÎ|Wü5·…}üÀ.p\)Æg|Ä'l㿉W€j,‚ÿŠ*QŠî‡ø5Ìc +Oð ¯ðÓRRŸâï™Ã=WÜÇS™4BŽ÷=VðE¶q¢u·£)Ú~aŸ°Šü#v·ÀÞ£ÛhC=±]|Åg“{ßñWãn¢͸Bî°¯zý¦½uhÅ,Žœ«ªåÊZ#ö}ı|õnàR<×Ù|MèÂ\ÑúüÚÞb XÿZõ)ë]ÙÚ—õ~+&^R­CíÇUïYÕwËzGõ=Mh\%®kÔÀ¾˜£æ‚s)Ö—â¯aŸÕÄü7~×6ºŽË<ÿÄåóçÁ÷)È€„sa…sQИ)Šý®}?{.¼Þ{nÓîÿy +ç8íΟiÏþ72šÏÏÿÈ(jÍ៓üXgí§˜x°x°‹mÔÍKTQÇñç:ã*"[ºÑÆU´kØ¢•ø¸Z‹›Çæê¨)æK“âø’È¹SÑ,5¢„V  Eh¡ÿ€;í{¼¿Ë.->ÜóöœsÏsî¹fÖa‘Nt!«ú½„x\F:âqwÕïæ¹~éENëdþ3[;¯±Cx(®ÞƒPóu'ä´VVc\ì†QPL2.¯¶Pï5€A>õõˆëE e|6 jÑŽ&êß±€ÌãVð‡8ÁÞh޽ç${žzñeÕ‹?âÅ=c7Ç<Ç2Þ{~ð®q·pUïõ XÂ[ü¦¯ì§ê +Z(Ÿ¡ —èßÃ&ÖñNeç¾â/ã\ Lœãö»å$¸ŒÛxÀ×ÌR­fé4O¾‡ªfÚCåwz îà&uòÔ1Çvð§Ñšnmû¨½/Š;‡-åþ5žaZ¹-é &UžÓ9Ωã:{—ßGÊñ”r¼Ÿø„YUÌ„æ(GcâR×ͪÙk5ç‘^¥^OûK4âû#gÁntF¶¦õÈÏù=(HŸ¸roB^ +V¹{ÉØø»vãü;á„V¹kN|¿:%nïòÚ’wÚñÿY­íîfü k_¡Uþ9Éÿˆï¼ý¢«=0°‹uÔËKUQÇñuT'û‚fÍ Fý:Ókzí>4Í÷+ ¹jVAQ)e/ÒB¡ +«Šˆ¢H „ú.ïïàဃûž½×^{í}ö¹fvÍÌ’Vh£jb’±¸:‰ÎññZõ_G'îã)î¢)Gó5"ƒfÜ”´¡EýiÅ5HJ"9<ÿ0ž` ý¸¡¹éHŽÆÈ|ïËjÅ7!§šÒzöz0ªý¼Å` oðãx¨}»çø†}üÃWE‡t£W¹óÊñXm^ý]h—NŇs\ø~o«F_÷=>aJõÎã¯Y¢Å…ß¶„i¼ÂKÅï0~ëfÁØ_PÁs%c›øˆ×˜ÔÓòN>ã;V°UüÆ2~â—ê8 Î=(3+"çÉ«f§žÑ–ò\Å5'.ƒ{œÁÈ•øƒÓäXÐz^óœÎyVµLé|ÁšÎ~MµûýÑùÞÁ äuvzÃ:Ï>ñ˜!ŹGø€Eµ÷"ï¦Wïã–ò¼À.us§‚ …} -§ï.b›ç+8Çïjâg”ÿ‡ðnÆå$+ñ±VµÞŸ>F8ÏãÚt¿|½&;úNê%ÉŸŠ ¿Ãð!ü¾ë47§=„{iV_˜?SsØÿx¡¾¯°‹uÔËKUQÇñµAŠ£¤ôH‚ÓtÚá°¼WïU¯æ#E-ób¾ÐJmàc –o‰2 *+‚A¡Qh£ð»½¿M›‹ >ÎÚkï}ÎZû3k4³4ê‹Ü.âiII:R¯Xîb‡øƒÏ˜@‹râõ²hE‡æymÈ)Þ¢œÆh¯I+îsû±€ml` +½Z«Y²ægoÕ¾íÊûæóë c›ØÂž+öñ“Å®>ç+ö±ªuz¤÷‘ǴƽgÊ{¨½»¥O4æ=GÓ:~Ïײ‚EÕdßÔ—OØÑ»ø±7ø‚ßfîæÌ’jP_wŒ*ÆÞcIë-c/‹øõÞ⿘ÇÅþâ?p¤øuPã¤Æìµ/¹bVJÝ/ßäž”äã¼§£þ޹É;P{Ç3»Rí±¦çþ¨gßUÿ½øNnEáÙ]™úàçÌ©_ê}^ý×¹™RG¢>ND}×ý¬ê0«úû¾ FÂý˜jÆþî*ê@ÌÝ"vʵô-)çúµÄ_i¾ï{—Îa¬Í +g4œÓ\t߉{ÊóñæÿgÛ¿Ó +œmžû5/cÿ¾•L´~Fš$|Ÿá¿¾ïÔsܰvœÜ)r?J/~ˆ°‹uÔ?hSQÇñó"1›[W»WœºuºÕÑ­“KGÿÄæŸ©©-…Ä–$QÛ”´ŠD+¡ˆ­E—""8 ±1‚ƒB©âà÷ú~‘úîßs{ν1³´™%q¾Ï99+¾?)¤¿})Ìâ‰YÇ1¾¢…¼æDçgpYrj§$#~Mô “Ëim÷ñ +/pó(à’øýÓâ÷wcS¸"þ<ý/Wqø€wèà&*¨âºT·„¢úÜYV±„Zd¼¤ïšÆ·ä!nimYñ£Ô_ŽÄn`Q±+›úöñ;ê÷q^cïñ ß±GÍbÂdq’þ¯xŠÚ˱ÖÙÖ•›—ÚßíÛUý‡ëƒ8JÿìbŸö¾™Z3;bZ7”ÃkªÃ,klQïbEšÊµ›_W꺕H-Ú××ÊÝ•–røuÎvx¦`§0Fû·jæî‡»îNNK^ü]öoÀËk 9³µýýÏŠûvw»¨:þ óŒcö3¹yiûÿ½ø·éÏ}£þFù÷Ú¯ÞA¿+ÿÚ_á̰‹uÔËKTaÇñç8ˆÕ² ¥v-ƒ £…ÿ@»–¹4sîiÍ4]f0œÆËP£]´ b” +jQ:F’X‹­Š MP7ÒB¿¯çwð0μ·ç}ÎyÞwÌ,if}.K¯üo¼µ@ +<ź™×Îó;&0 9WÄýÎ ')õ%B±R¡5n¯~óóNk‹™G 5Lc +£¸…A\•œöKKF²/È5)(Æ]Lb?ñ /QÁÜÖþ%ývkЏ›Ò\—SUí² ©ÏåüV^à±ötîëÝF0¬|†Åõ¡Ž'ZûshbV±]={‡%¬QŸ.œÁ ݶ…UüÆ&~a9”Ûs=Šïb¾Ç>à£_sï(.€9ßÍó÷;8?°Kû¢Y[·YŒoÛÆyÚ—ÐÁßÙ£æÞ9œÅ)åóEû|Å_úãþ^¶‚y|Æ}'qZïx z׸êøF祮ڌ㡾—놼’õ×TÏŠjW µkŠWW]\î)þÅvinU{6•ÿ>™_Ê:Gá3Ü•L„à>\ך¼Ö JÖÏzQçê_Ÿ¶£·‡ãÊßÅIÛ¿÷%Ø+ÈɵÃ÷:ê?¥?Bëœ`}0´Ý}Oîïã(9°‹…ÔÍOAÇñYˆéAN`¢ÿÜ œ¼r5ñŸàh[l)µ¥_ª måÅ÷b0àKŒ)1JQ ƨ©‰1“Žø~§û›°>™ÙÙgž}fv1gM(‰xÄIHü?ܼ¤ââ2ãâ"F0‘FF­•ÒxÊãòt}çÎ#/\Ð:S˜DÖ3Ž1=5ªxnÞ„b»xW0‹:> .i¢”‹ËyyÙzÌÈUÅ´íuTÿ®jµ¬Ú9¶ÿ÷PÆ´âTpS°¤òϱ‚'º¶÷ß`ǘ`ߌi‹Ñ^C/:¹÷ [x‡·ØÄ{Å|g‘X«x‰uÍ߯Ä:êÛÖ9ôÐ?Ž]4±ßŒ ‚܃Ϩ…Ïœƒ`}èÀÑ0žù‰ïø}üa<ÐxSù|Â_Æ»S'ñ‘úi÷Âwo­ßPmna^ûº¤z?U­Ü»×µvî ©HYûh÷á6î+Ö¢öÍ>sÔ¯jKÚËšöë Ö£¤seÏ’=“öŒŽ›ƒsœÿüæ$kŸý1]ÃÜ‚cÔä„1íÇqšëtX«V òŠñ¸õÜ:6¦ý~£ÿ+áIzüûþ<÷Ÿh}ïÿÌ奰‹…Ô_KTAÇñ9»`…/À_@w]ø*º/½î"w×?kžÕÝÜWmk­ÄJƒ4UWC7e ©¬E¡‚ P½€@„úNþƒàŇ³gæ™çÌ<3³Æ˜^s&‰¹% é¹@4ÎæIaw0†ÑçéGZÏ~µ¥Î‰sstï6W£¸«gNmC¸-!²ÈK¨öÏ Æ…ârßÃ}Œ£„gx9µçµÆ¼Ö9b¤Ýͯ¨\ŽÍ7‰i<Å ¦ðOd¯±ƒ6°¤1%}߯?;¦‚:ø„=ìFÚj;0&hÅcbŒ‰wñ¼ÁûM´ã1ßõÝ-¼Å{¼Ã¶Ô•ëöqˆ¯úÆG|#ÏePƒØu¬ ƒ÷Nú~FæhÇüÂ_úšD~Ûñ͸†2Èt£ W$NüoåÚĺær¬\¬/hÁ+¾ÏœâU\å½rcçiÞà¹öÁîï¢ê_Sÿ­©ª=°qeqõ·û÷Hû° ¹4TÇÏXÃK™×¾?Й™PŽŠê½ª<ö¬t–ÜÙ#Ü9·}#Š-èüeωMK¨˜YQ jãÞÆXwprZ×ÿõp÷6íq÷eXln{{= OÒã÷ûq)söù-“·û°‹uÔËKTaÆñß;£¸heêΕ 7méopQÛþ×êè8ãXãÔ”šSŠ6N9RÑ"ucQ…P"]A¼$ši‹À…¸¨ ðû2ÏÓAμ—ó¼×3f–0³nt‰/wœ ]‚rç)‚ö ¯G’¡üîH}XWHò„~A¹ý¸!בäCý2jƲ‘ö”²ú$#¾ßîb êYP–÷ò¸…1”qwÔßת¾¬>A†Ï~Œ<ĸŒ „iÌcQæUWÄm1ªÌ±Ð;oñËz~Ä7üÁ?üÀ¾™»h»lÿjVu‰ß;Ô‘çiÿ/x‰Wxƒ÷šÇ’2W°Ž-eá/~bµRçšÁ<Ý/òÏð|†&Ú6ñIY~ƶC`[í›Êhó·€³ˆ=¡<‡VœCÖççùïðúj­w—ßuØãý6ÖÊ=³÷n Nëx¸‡G` {ª¬ ñû:«sí}1RžÒ<˜¿«ÇyœÕ^½Pƴμ¤s,èLKRy¾~@w-k•û_¯JN}†å¦U¾ßßß甤%£wü ̯죿»@Ý­)¯ü^½|7ᜌýÿ†Çñuþ{OHôÿ"qÚÿˆÏí?â2F°‹mÔ;HAÇñÙSAìlíé,‚(D;«´)ÒÄÖ>zõ¼Ó¨è9Ÿ'*‘$Ä *¢"ZHðmѼHãl#Š‚~‡ý-Œ‹Å‡»™ÿþ3³3»Æ˜jcL5bÿW?âíXH0>+1§¾m×I­„ëÅÔÎ Ú H¢Åñˆ;yqÅ:Ñ¡x£Þ©•T~\yíèúr´K›Ú6>Œ¯ø‚!¤5ö3f1¥œÁ4æå2ø€~ŒkܪÌáÑ­i­±Oý6¾€5lÉ.ñ +ñx +ö)7&ë8³ÈKú^‘{ƒSüÀ&vUÃÚÇ?œà ¸f\JPŠ|ÍÁkPÇû ž•÷Lã~©þ6þ✘ñk™CüQÎ1ýŬç˜Í¼9Ü‹,æŽÑ_‰'äÜâ7–ñÝ_»—ëǼÚG~Ž7Á¸+Ưðk×gŸÿl`FçaÏk zŽ[Ú¯Ý÷¢Î¤_g<{ÛîuÎÃÖasǨB™ö¶£º“ª•Q´ÎoCw®Cw-¸ã&4K‹r:%¥~{Æ¿çVp¿Š¥´Þ%h¯ëºGvOïÑjüwÄŽwß+—ûžÖ«~‰EÍÃïŒû½‰>GlÝä=q‹óe°‹mÔËK”QÇñóZ‚´r)AŠ ÷&a­ú ülÛ6´qg¼45£Ómfs•ÄjQ)†)Ú•ˆ.%¤´jÓ„6¡.õ{šß¯/³øpæ<çœgÎí=ι^wرzO„Åcˆ‹ÿ}Q,Ö'±H»±¸õ‹Æ­Ícùû1€†0")Å­_I¤ÅÚ!¾}P’¡ú%Œ"‡,®¨Ì*f¬O ·e˜Å#¬©œÂMä1­˜µ?Æ=-`\ý`s(£¨ñ7Tå*ʱ€%yŽ¿Î8‡ Þ8W  §©ïã<ýöð ﱎØÆO|“_Ø¥å .ƒù]Š‘;`ýu'(Ét3nñ +ÏðBõßÕœî6ðÌÑm2î$98Ë£¬©þ¬sGžPo"μÝ?liËš·ÿ¯V­÷õ/øÊïN|fl{µ Zˆ¿ÆCÌh/óÚÇ»XÁ;íÃKÜ×Ùøó»bõ«RÒ™²OA3Ná¸æú°¨³*IEùWñwp Ý»´îcØp˜ï;¦ydÕÇßg»ëýbßÝñ‚ÖVÖúmm9Í!œ#Q#_ÙˆÕﳿë)k|wÜÏÛ¿û]ŒÕôý|#½G¾d #nÌÜw#ßóð{à¿7»ý¿Z¨a°‹ÔÉ.AÇñêñŽnÂÉcxáäh_f,cI±$–Xc™HXÆ>¶˜± 'ÄÉÁøvü*Z…Äá“tÕ¿–wý«1eæwURÊ@©Øv¹£R*Äöÿw¾;Î]×Ï©µR‡DÅo‡q›µÚ ;"Ž:©G#šÐ‚±Š{<ããèF\z1†lbSèð×™ÀŽp‹kìc^c:Ñ!qíÑ«ØF1­µGeLíYI ‰Wc¼bcBmÆd ƒõBѯ>ó†C[Á:ÎðA< ù(gᵃ¸w9ð}½Öâ9ô„\ÚÈF¶1„Ö»Ãv±§÷>•cõoɦÆð½<—GNuáeÒ¡<²ˆ\áï¸Ô;¥ð ¾Wí·ª9ämFô]{ЇIl så3®XtI\ç“vµûu3ªƒ<ªnR:cÿ5½kZy¿h?ÿ¬[Ñl¾j»Ñ|×¢ Äš”Ïœj(©|ýûQë¨1?ï‘{/lýGþoÛö?¼÷U¸ûÿ(÷~ÛyaͳëãŸRêÛ£°‹•ÔI+…QÇñƒäPVvÊ  ,lYÚyvv¸æù^ cÉ=gü?çœçücL±ù]™”"ài/Wø”J‰þ9ß?Î×®©•Rƒ:4ˆ­WyúË5¯\õZ©ò©ö©;¶A4¡ÇÆÄdãΘØxž!Ú1‚v鯿°ˆY„eTÆd +[¸Á®±†~´¡YZ»Sñ0ŽL«l×0¬¸aµÛw/á’µf²æT¼àŒúÒè»À¦ÆÍc‡x¦?ƒ°sb‘ˆ\ä#N}”߉Kç™G½ HF²ÀXs‹9®)²oû<Ð9ì`_õ=áŸÑ˜æ §;ï9×Y›¿‹mý¤öu¢wÙ÷n¨mEc&tÞöûöé,<±ly]:¯µwH«¾W‹¾_»ÆØu¬+ÞQt1IH¡ü½W‘ö}íÇÆ‰½Ûõæû.U®{Ou/Vq¥xšëîµË‹ +ó3\¿Ëwÿ«ÿïêÞÿ„Ëû2O¿Ë?—×…âÏo7Ç寋çú#ÿ“/ ü°‹…ÔÉJ\AÆñêë[賸2¾€àFqá+˜6¶Ý¶¨F£Q´ÁyĹN ‰8 h 8!‚" +ÈÆ… ®ÿEׂÆÅ[·†SuÏ©ncL•Éúè©–*J®u~Ô“+Nx¯h(fLâ’@ øŒf4¢>¤µ¨Ñ3áÅsÄu±“šk÷H¡SÆD +Œ +ÉëÁ#íúÊ[D» b¿ñCVdK˜Á(†°€?¸Ä)Öчoøª½¿ Mñ»ÖÚ ±íRì)Å^Æ6ž8k%61†ôÝc šgÏ5§³?0§ÿøÎrT€÷€ýÖùŒ‘ûç ¨UÐOûE¬ý¯Ø/¼çñ$Wæçr…Ü©}¨=÷q„c`W¹¹ÀvtV›ËLèû3Êí/üT=&1ŒqÛ5ßõ}ÕÁΛÖ<ÎoF05YTü^PsÓ-iåÚå>­ºt¨^-âêÖ­ØvÏ[rR ò¡æ‘Rúþê¼ƒŠ‘’&i0oï·»ÇujÛ9˜ÅžÉÞ¹´Ö…ï´åî{­7ŽW¯¾D¨ßý>ÜïªÚóÉóÞÿˆcçÆBñcÞzû_Þh°‹…ÔËK”QÇñgÆ\æ_‘ÿC‚ÐBZ¸Ü·Q3Ç™QÓÀËàTŒfI…™ /á%Å+R˜`h«6.ÚD.¤6.¢ú>½¿/S‹çåœó<çþšY«EÚªh­êÛ¥Z\¥ö +Õò„q¼.…tâ®d$‹ "!Üǽ˜^t)¾[19I+ß ù»¤[2êß,™%Í’ŸÍ®¬˜Õ6˜ÕlP7CÛ6 ˆMüˆ$ê(¿ã‡xÌã&ðä³=ÅÎâ¹ÚÆPÐ:‡UæccMÄŒ«|ŠILÁç6‡7ûsª¡ü…3¹†U,â^k=—ômóO6£ ×p=’x‡¸‰Þâ®û G`¯ì+ÎñEczyŸôMjN±ã£æ»¥9~ãÙ:–£³ø»O3² uì(Æ×RÖ><Æ}»(iÞg:ÖVÖ^ìj¬²ösLŠ2®s+«,êL +º+ŸÕ()Ïû7ëæ¾&ëáûWÐú=§ße¿o}Ò+~Óÿ³è <´è^ùšÔîtVÒõA¨ï,Ä„9dãïòvL‡„÷”’ÿýGâÿïß)!GÈïßé?¸hô°‹uÔ9LTQÆñóÄž*Z: t$tô6TÔ¢0b˜‘A6Q”ÝÁ!²d LD¡bK¤¡5tD¨- ÿ›ù^¸yÉ¿œ9÷Ý}3k´œWÍ£š¤Y^çÖóh»|y(†Äц$:Ѓ~|À|Ç2æñŸô½_uSèÆGô*oG­x+­’Ð÷wž”Úà§YðÜìIŸÙÓ +웼 Ì•Å(ä†òZ°Ž šü8ß\_6¡6ã˜Áf‘Q\ÔÚ¦1†!qkİÚNbJ1”×ïõµŽ= +ó·]ì(nbE‘y…à|‚¬¹ %ü>EìWPƒg(F*QDÛk­óP‘ööWúvO½RÔ¡å*?Âç¶%«9n`kØÒçÚÛ¿8ÆoµYòönD1­½š‘Œê¸³ø¦3ØÒøYåãÚkߨ×WZçñYqPg4âMFó9Ñžqï‚KÜ¢^ëpw¬ âî|Rü{ëÄ•ûeIµyo¹»ëßsÛ$¿ïë³[RªïÞ§{§îm»÷ë¿Õ¸ò˜=þG¼”ƈèÿJ,7nÜ!Š(°‹…Ô_KTAÇñç^Jx¥7Ñ Å—Ð} —ŠïBËM×UÓTBV¡6µ]ñº‹V‹@ ¢±ÛÁ+Eð*A…Hoúç7t<¸xñavæ<3çÙgfŽ™µY¨]âý¸Ò!ÏKðñ¾ŸWªïu"‰^¼Â0ÒXÆ'ðÅ,  ð˜'Èã¦0IÌcsÃkô£ÝÒѧoHóÆ‘Á)ï{oV–Â*é×0¾¤÷N)+Æ[0‚Fú¿ñ [ÊVù½Q®iqco±¨¼?cEùÏ*÷œl9,¨6Kêçô¿ŠËª¿Yw›ØÅWlGú‡ä] ö/ çà?ÁÞõ('æøýOÿ€±süÂì‡kóí ‰©5 ˜_VAK~ÁCÅúŠòQܾ¯©vÅ0¯ +ÏО»ÆØÛQlVu›VŠš¿¦:gõ,£zåõ|]µLkŸîÝÇŒÖ.jWïï¸!Ï:4¡O»ÐÞŒbÐÂóîÚ Ï¿ãÎ¥;ŸþÌöÚÿ3ëÇÜIÙísíÚ.µ)¹k^RqN§Ý¾ƒCÒ¯ø„…÷ÔÝíŽHœÏ7©ù/õ<þ=ˆgü½ODÖŽrktÿËC°‹]Ô=h“AÇñ{pb#T°¸8vrÒ¥[‡nqv:ÖäI41i›¾ ÆAÅ’*šÚ&©–ÚB[TPDK‡¶ƒ/`é ƒŠ ºKÅïåù=2|xîõ÷Üÿ¹Ç“4‘ó’lãڇĖSÈHJÒ¸€‹jÛâ„’–ГÑ\_F± +(¢Œ9|ÄÏH0`Lì´1ñnžï©ÿ@œ¾e<ÆCÌã>án+–ucƈÖÊ«^”q\FI*ŠýµN Ô_ÊÜÄ}lÓ×…“8H}³¨jÜu\óöS[¾¡M<•œýX{í½Ï>g›YÅjÅëõrI.J­êÒ —‘C+2ê«ß‡Ç{=Ä5i|RhkF×Ð)ü6‹ÊqÒ,uÞ¬ì°ÙÁÓfŽ›•¬ÐÞMÌw<ÇSYÄO¼Á 0Šè ­=«93ªç4÷uÜ”Ûÿ›ÌÅ +ùÇpízŽ)î ^c½èA§âòE¹Ýôc#Ç,æðLÏOòBûW̸<¯ûû1Óx¢þIå{«uÎkÝ?°ÃþjpgPMÛíé>bëjÿKLQ^SÜtß⸈óŠîq†Gp‚òJé{©ýMêŒFµö‰„|%¾°AÞwj «¸£´·á±»øï©ðí?•ï!UIý}¯ð¬Éú@{,ý:+?£ñsË'μGãø_qîè\¼ÖÂþƒmêa}%”ß+ÿ-´I^Bù*Z$#Y m9¹bÿþ›&õ…±­z†qáÛNKóøÿ—.ây½Ïÿïp4¨/“˜Çã}]EÂØºÏã÷‚ßG~ïî¤=™9qư‹]Ô9O”Q‡ñó2#ß@Bƒ¥µ‰ÚÐb´¢²¢Ãufp˜Yd !(ÆD1ƈ,nq‹ +—€ +B¥‰¡À’ç„ÿ 7Sü2ïÝνç.cfWm× 匄òeñï,šÇ5iAºÑ¦ºŒúf£x¡œSŸ¢Æ^—B$/Å}‚el›%gÍR5fû˜)穨üZ¹úz߀=²|V»Çy&ïÔîfð È« +ç1â$ Hknõ ¿e¶JœÄiÖYø™}Å̫챫QîUrœºU“ç8¡u*ï å2®µo1æØ«„9*θ)æN±Þ +òMXSÂNŽÒ|_ í‡Yš3Ms†©‹Ô=P>¾0¢9ßãîê\:u®½RÒ½ õý:³aí÷bŸA#j´§s+˜ÃSÅò87¥[:pÃvï¥+J«íÝË’æ÷~…¨—ÛÃý.ÇïÕ5GÂû ãÃÛ íaLN2‘œúmï݆~ù²y›$S&[&þÏq—ÜÝ®R$°‹]ÔËK”QÇñç}'I\-Û nm.Ü·hé?R63ê˜÷ëH"e]ÐEQŠ)"*ÞÐÊÈ !]t•‹7¢Ñ÷q~^fñaÞsyž÷œ÷#颶çЩ¸´ YšôŽðÏ9„ l˜EfñK³’S³RÖtqÄì¢5Æ?‚1{¤˜a<Æ=Oã'¾ã îk­ZSNkhѾ|¬Kîb¦ *ß$">ª¥o]¹ò2 }’O¬Çû߬GmÏOsFÄ×=Š1<Ǥö°,óXÄ*¶p€}µ_áf5¶­uÎiÌsMaïåþ°§kà½qÈÁUúêÿ¥\»øŠoøÇûŒ‰‹kx~ŠËôÿÀ'¼Å +–àç´ƒ#üʼnæ}Æ;íéµÌhýÓZ³ÇŸ‘û†¾?g1?®ùS—øí¥oÔ\Äúí7Ž g•¢]räKmÒ·¬}xÍ<Ó;×ôæôíûuF~†ƒ’×¹†þ!ñð:=$w5®£ÌÎëö|/aþ¾'Šñø^ õâõÖ¦tá®uª®¼.Æñ01¿[ü¹C<‡×³ß¥lB¸ƒ9Íqw$ÜÃ0Þ(!6Õ w8Ì w8ćv¶H¦Hò?ÇÝtÿÇØ±x°‹mÔÏKÔAÇñç»j` xii¿Îð™Î³WÏÁ mì²Îó¹öð ZÇ‚öß™ÑXÿ½t2Áœþ{qqÓÚ¿œæÈ*ç´¾›auñîžù;åïd\êKŠÿî“GŠKãBî~º{›B‡]Þã|ñMâçkÖüþÞÇU_ƒü÷tKŸ¯¿°‹uÔÍKTQÇñç:µh×&¡…᮵ jÙÿ"¥ŽN3ãø2·±ñ5M°-ÄÄ×Þ¥u ÅL!q#šBŠ© +¡E è÷àïâMtñaî9÷œç<÷9猙•ÚÙÊ Úeˆ"†2’R_¥Þ—‡”ž3?‰Z¤Q)F§Bc«4æ1šñ;f^ –1‰;ô}C;ê·&$¥ßôÊSøÊ%¥5NK‹/Oð¬i»8ÄúР:­W'®/«1õùʵÝÆ'¼S~]ú—ç3¼@F0ƒ%™Ñ¼ilbSÄ+ô+æ=iÎ?êV€‹<ÿÆÖißĸY5Í[5‹[ä®Ñ¿»ŒÛƬâðÎ»ÏØ³|bäåÙÅ&¯—óW¹×>à#rXó¼"ã +í-üÀwÌé»>cTßþ?ñKk_Â-ÜÆ \EDk®)ÇÜqm¼{ ®·wÞöÛY<®…whÏ£S{äkßšt†Üž¹³Ø¨ß U_‡ÎÄ[¼5± Œ©=)nÚÛŸ¬öü¥ÎF‹Þ7hUWÏÕtAuÑYiÒ9 îUù)QõÇ%!ɸÜɘÜÝàÎÔ„rv÷¹Z1Î[/ŠÍO+¶»óeòßÿÑŽöž†°‹eÔÍK”QÇñ{ÑR¢•L«Ñà¦mmruÞšFÔ&ÒÂBJœ!RÓ”2¨TÔDݱEQäÒˆvA!Õ÷8¿‹ãâÃÜç<çžç¾Žs®ÝuUãqI ‰kèFy¤õ.ôùõ¬Ý¡Ö'#öÜ‘N½Ëè›9ô`e¼Á6Ö1ƒ ('¯ülä;iÅn _y9Å-ïºæôŠåUÛúÞÄLáãú"}ÂBÍ‚Þ÷KAõJU¬à5&q·å®žÇ•·‹¿ØÇ'Ìj<¯´.ö<‡¨`Z5Ÿ(ç—sþ¨ç/¡™Øg|¡Ý‚˨â‡sMçÁ›.òüçÈÛÖñ•Xï™KŒxlƒ6{çY#Ï=sóì£o%÷ƒÆ?¯q¾¯×ò'qŠö?|S|K{kßx®9Mj.³Š­*ÿ7««á­ú,â%æPU{øÖ ~bŒ×}'vgpVcy‡±È¾Û¾ ¹úù»çêç­$¿¥Ü—õ{Ø>½Šú‡3ΉÕ+k­lžT¿¨=´1/ig´{RÓ»)»;]îøý²XÊÞ”äÜáÝIGØs^ë`wÀμǧ_Qý’‘oÄ#íé’¬æ;¨5Ëj|–cÿWäàÿã?Ȱ‹]ÔÍOAÇñbL¼ràlâÅ›þ^ø7ðb´ÒÛE+´µ¼5õ#B‹& +DES„àÁ èA! ãE½˜ðúÛ0ÝÃ'Û>ÏÌóÌή1æš©w=&OH +n¡„oõòZc÷þüIÍáò:ÑáåǹñvŤ•wCk÷#rèC—jÊ(.TN‡’ÖÚ¡ã®7Õ[·Ç­3ˆ éÞ­? õ‡tÍ¢Wu8·UO4g—Æ¢ÿ]ü]ñÌâæ0aõæÜÓý#¼Á¾1ö4Nñ{“(i®'Š+yceLa«ä5‚ºìwk/2þøÃ}Îã.ý±ìµ½‚sÄlaUü¨Ùec.£™ßó Î†üûeŸû êá-–ðÛØÁz­>³‚Oú¿ªøꡬ~Ÿá>b Ô_Å‹‹ú~޼ÇP«ùŒ ê: 涇p{CÍöŒæ+êYõè¹åbç!/wt6²ÞYˆÎHÁ‹Ë+wLF·¬òFñR}}ÃkõjÝqåß׳žÓÞíá7~)wBµ»3Ÿ2õïZ›9y·Òæä= Mý»ɨ>×ÿC=—]üULíœÞ: o½¤´I øõ}K\ŒûV\•ãïǨ€ß°‹}Ô»K\AÇñs£…] +k;ë4ú'XÓø7¤®®¬®W]u}k|"Q|á‹‚E‚!¤SÁ‚H  (Úøîo`Ø"ŇYÎ93gî¹kfo,V# ©ÉS+õhD»¤Ð"‡,ú¤Wó>`32¨úÞI›ÆŒæöcëø&[ø„yŒ*¿ø=]| ¿q†süÐsAÑ>³XÀþ˜E ÑKp¦ˆw½BŠxp[ÜàÇø‹<âB{î`¿pÇÚr¼F*peVPiVø‚qÒìY)±bæî©îUlà3¾jÜÄ.~Êž|ÑÜ%Ý‘—ƒŠO«ÞI™S|]yŽT‹»·Îóÿ8ç-8äŒÔ±WT¨Úü{ôºu¿ÃzÖ§XWÀ½ãÉ(Ö#YÉiíû@V=4¦÷éî÷—Ø·¸¯ºÔGá~nÝ8VðWñû0ê±EÍq}~—¾ÿÓ÷»ëûÿ}/)íëjÒÒQIÜ7v¯˜«·Yëü‚ÿžÃÿˆd7­5õyóª‰'´Ù M°‹]ÔÉJ\AÆñê“`pãB|ˆ@6¾‚d‘¥{Áˆ¶v_牴ġÓqÂiѺµ%Æ9*& ˆA·² AÜÔ…ÿCÊ»øqëÖ­áÔ©Óíœ{ãòê¥N¢ý Òˆ$Z%ð¾…h–@ïq±ùMH!ƒ4º½uÂqIID„ý·‡ÅÑ%bí/†¦ˆÀëoñÎÓªùS/1ެLb(ÂÆôã–ðC1‚wx‹={5~_‹£U¼ßbÓZÛòó^ú0€1Ìâ3v±‡œúÓ3 vZqÙ^S˜Á2ð7ì[†xW(¥ÿþà‡Šé 6°-«XÁNñwÂüØ|s® W¨qîQ}Ï5ÿæ”§­gí¬ißÐ1ް©19oÿœÖú¨;š)ÉjÎÎpM ÏxþÇ%í—ÄUëÜcî©°’8÷yJ‰Îk÷òØ=d”ïå¸OwêQ uëÝî{XüÚÉhn¸¦ÕÚ¼rmgýŽsüÖùgUOVßm._ãÚ'¥X²Êï¡ò8®x¬ÎO³ÖéW,V3íú–ŒÓm:Õ¼ÕÒI>—±rÚ¿”ï.íeóüÿF÷ð?"áþ“÷ÆÕyâ÷<®à°‹mÔÍKTQÇñs+$fÙ`+7nÛ‹‹þ‚þ6éèÍ&u˜Êq|ÉÉÔÂp†Æ^TÒÒ ñ…,Aˆ V +Ñ¢…(„¿þž..>œsïy{î9Ϲι´;u[Zp+àÛ[Ú¥MüxkË SÚíVqC(¢'˜Ïëdþ],¶F—æ3y<@AÏÙ oŒ÷ëÜ d¥9••Ó~Ñkç.4¡‘ºÅ±ƒ7Áz#*maÅ2ƹi•eõéO°5ã‰â{÷XÃ&>á+öXû*¨c¿°UÌh¬Åü³˜ÇlေWPGý¾ã'Ï×ù®7ÁÜ‘ÿoÔô¯4wMs½Õû¬ñYß°‚wXÒþÚóœÆX\UÍi}–5ç¬Ê/Ú[buGø‹ÄTOl7œ»t ¬y‘¼ˆö‘¢}Q{gùÔ+E÷˜Ú|[¾øÌ«^йT§Å6g:ßQé°ÞfÝËh–”¾}S{TÑ|–ã]’ ê9Åèϼ¤gk³»’¼7–S“Ú£I}ƒ¿·!ÿ,?ïiý’Æm(ìì,·ïº³{ëÿ™s„wæ2GÞežå”oi~_g§Îø±´è»ðúgz÷ºf;û›Tש9<‡/ÊuDgÖ§sóóñoçqˈ_JWq…÷ꊴæiíÍÎÕcùýñï?-÷,ú~½¾Qy<°ó÷ ¥v=£}Íh-Þ7û>†÷ÏcÔk/|}ýÊ¿M±ã;þ'ð~ñÝKÚÙ¿¢ÚÎÿ;NÿC'Œ¿+¾°‹uÔÉJAàšDâø +Ä£øÞ|¯.1«Ä%Q#Š‘¸â†[p'ÆE +‚ ((ˆ z=ˆý+ù›49|ÌLõtwMwõˆH³ˆ´‚B„vÆ´­…Z­˜^|? +a>û-mÔni³)àR*î²æï„u[4±¾«”°KÄ ý0LIèc\õZÌ{ pJË0Iz¿|NÁ"ü‰8O=Tã^s~…5˜¦%ö=‚l±}Æa„sZtüQ¶O¾¿ çp °Ê<ôzðŒ<4—)ƒ*Ä~ß<¬@–9¡ÍñB TBbïìsðpÅys´MY^3ü^ý¾=ŽoìsÎ +ã;å¸þÂ-Ûá¾ÐV MPÇ\®˜Ç7bžÂºË=ûÀâ à/ô•7æ4õ°ößHºhLk°‡÷ÃÜ?]×'øàºÏBšã¦¸º¦Ÿ¨ +‘²FöÊ7$âE-8 ö[çþ­s/SœWçÓzÕºRDŠu“â955a¿4÷r—k®9wIñܸÏe˜cuqnÔG¾¶4—8Ûô¬›ÿ€égÎkÐjXy–šÏü7òÿŸ•4j"°‹…ÔËK”QÇñg¼”;AÄÿ¦ý®Ý—ŽcÎhš6"™£"j&šW4Ñò–" +A•‘µq#J‹î\Ò÷q~SäâÃûžË{žçÜ^3»kfõH£‘ARõ÷¤>’TÿvdÑ©r2êÓ ‘†Ô'%%M’ºÆ}ñ\ÛðHÚ¤Umiõkúæ-x µðùuK—btJ6šVíO0(½2„)¼Ä‚Ê¡~×,Q…:Ô¢„ºM<Ã0&°‡3ÚªÁ«½×8£@Nq{¤Oñ½} OÅsxƒŸBl{çj[PìßÄaNE·p‡wê•Ô¿Ãf1­oW•ß}näÙ)±¯\÷Zßøs ëx…eÌcFã{ŸñA9{ŸEñq~«œç9¾ª×Ãm5`o·óó±8¦|SëXFù‡ÆÔ¸;šã¶r‹ö±§à ĺ"¡®[ûâû¸‚OøŽ ík¼_¹üœ¬7ûPúÖ¬ìk¼S ïç”WX'ϯ_qý¼ú¹ÍØÕ¹o‰ø¹ŽÏ|¸ï9qŒ(¯»º7A¸>¶ß­ÇÊã‹ÖCkÕªñýñÂ8þî}ª Ï´ýýÿËÿÊN˜°‹}ÔKKBAð£…E_ }‹>CŸ£e›VAë쪙…aj³Ò´‡Zí¤÷ÊÈÚô0"ŠhSËVAô hÓÿà`iñãÞ™{æÌ™¹w®ˆxEÄA!½÷A¯Å±ø!1HÂÛ:¦‡Ì8ù©V>ÇŠ ‰7ýf^}„~€Äa”5…YOÈŠ Ô`ž…¸fôáaæ7×8E)fõG§Æ! 0¬U¯ó° 8ƒu˜…iȲý)âêĹtï>`“¹f ES”â\Ë”§U¸GŽ&hÄý” +°exÃ󌈻ß]‡v'úßáv8FómÃ>œÀ5ÜÀ%×sJfmeŽÕõÂ1ç×¾ æ,²}¯ð̼»GGp Oðȹ˜³R]—KknÚwôƒvs•î©\p¾,÷QßEŽ{—å;P“”ê·nÎIüú~“̳k|g‹ìOðšdnùÆ^·‰ÔDP¿ç ÷­¨7Íõç(Ï<¾k­eHªg!ø‡ùÆû,Ús-25iÝQŽ Xñ&Ÿž‹ç~AmíÐÁï©Äµë9µÿöÜöyv˜Óœ·ç´ÿ=&NÿSÞ_•^¸°‹uÔË.CAð9mB,lÙˆñöÞÁ‚hO[ÚR½©ª†j—XÔ-êZÄFBÂÆB$‚D¼báÿébrÂâ—9óo®gæ(¥Okð€ö­Ð‚ç8…2BÎáïÛá^)WÊ;è‚z¼»an 6`öhŸï/3v\[ÇO}í$ÿva“ý•˜#sx†/x…[¸`¼jôWa?²Û|–Ø ó®áŒó¹„¬¡å\qÜ"÷<Í=Ÿb=ú)Ío¨éïÿC’}È·˜¥œú=giÖss®6W«{Þ­”17¾µ«±F¼[6æ‘e»iö'gQîœq}ô×g¿Ïdécs“9ÉÙ–ûf>#?DrµïkµÁ;æˆsaõ öÄ9I¾¾×~ÇØæ}¶¹†Xêqÿ ùOy¾šJé°‹uÔK/ƒAàù¬lü öþ?EõªJQªuoâ¥h+u‰Š…!‘ˆÄB¬ˆ¥D"6ÞcÞ‰I“.ž43sæÌ™ùfª”r)¥Üà?ôñ×öÛÜ$cA“ë¡^r[ù½Ìë³Úž:ëø©^€ëB.àNÙŽrnÛž0g¬ç]™£8…c´?` Û´ã4NØ?m|tÓ¼÷pWOð¯ðÌúWŒýx5´ð ßð[Æ4]ó#ó5kZÇ]O5<ÄŒf1‡yãS;Æþa-]8ƒ“´â->ãËÿ5ïÖ[w]5çŠïþâ6Í=ã¼5k]´¶¸¾e÷#îó¨ÿׯü_*î_Œ{ŠU÷ö®¹¿U÷¡ásÊ|ãŽû÷Òz«æÔˆyÆœ{Ôÿ»î\-k5ße\ò9dŽt¶’tÖãýJ÷¤è»xöÓy.™«b½Ã¾Ïïcº·ycŠJ±ìmæ8Ç™IÏ_Ëu•ÃþïG®-w{þô )„½»vиÝïÎ?}z]°‹]ÔIJAÆñn¯â9\x¯ÍœhÔ`"¢qlÇÄ#qDÅ AÝ("ºA—®¿"ÿ‚2‹éîª÷^ñ<¯Å«Š &)I#)QÚL¿f„xÓåÙ¶‡8#N®5lÿ'O¸f.ûÝÖŠ£MÆäTîq"Ó’e.qæÒ.|7òR‘7ù•/¹‘Eé%wÒ©•B‡ ˵Ö$‚ô“·[2ÒêÈ›£Ÿ‰™`¬‹ŒeNFÈ5Hû2ó{[Ù–=Ïóõã«ÿ#óR§+Ä9ùr£R”yj•ˆ1ùŸåN6h[ m«R&&`ÝÇ©Q¢}_ŽX“úMñ\‚ͽäüš:ÇÌ©I´ö~ƒ^>åL®åŠÜeÖ, þ\}ë‰kdwYÓ"ýælöë‘|ÆnÖe€=éCq^È·|P{Šõ•-9 –ÿ$ënÚ7åIÞå’þ=^õü™3å=Çsu‡Ø£aÆ”§ÝÄ´;ÌÙtϤ=cöκg¶•º&&´“+íý¿—öÞÆœþ¶ÝÞ¥<ûý"¯rȘ3ô“§ö~×Þó(ãµwÓÎ+RgþoBŽetý°‹]ÔÏ.dAÇñbaaç<€µðÞƒ6újú6!þwg¦i“™¦ 3þgF"‚ĉ„ÙJ,faÇ÷ÄïÄ^|roݪ:uêÞS7„ð!ü/‰^äñ ѧ¾:%¡g)ä$ëïF„É)fVmëïRœ„î»´~26ÏÛž_w,v¤5‡ñU–±€1¤#Òúöl£Òõ.ðB—ðg()ßTLZú1…Ø@L*þµ×tͼåa9®á'¾£ª{˧ˆi­Qоlì.Ö±„mòmÄJõÍ\Р6ÿ³æY¼/˜Á„̪¿¬1KŠû[ÚOYs+ÊÏs¬ÆbÎ*OËq«ØÁolê[”cë8o{üeåmûûË>ZІ&Ú78Õ79Tž‹˜W–ûc[‘A;ígìk\Iù´‡c<àNñxaOתâõ},Æ“òxÁ¹Ö³ï~‚{Üâ+z§“z/¿p‰k­iñìlC…mSŒ'93‡lÁ Ã:ó/1ÏWc<í(¿Øgÿ¡FeÆ.0nóU9ÿlXýåûáî8Wÿ«Œ9 ó° ÷ðI2îá‚õ'h0v…ªÖÚì{çpļà +n¸þ5Ž“<–Hb6±^è„Ôßa—ùIö…1›­~¬ÍÛ‹ûçéBû-ÏåõèƒnÔߘO{óö6”߬—yÎzöYk¯ó¼ro†Lë~ÊLPÜEߊŠs\„¤õÕ¦1bœCÛ¥ó ‹¾!ÍOòN3žÄÑ÷3ß©¾{}Ï>è‡ù+ÊýYæÙȽLYñÎñ»®=îñö°‹…Ó¿/CQðû°û#Ø-l‘X¬b5ø (úãµOiU5´Vý¨6D¡ƒ&"H0 ‰Dl‰ø,¾'ï{⦆OÞ;çÞwî¹/÷c&/!ƒ q’±ÇÔ9WÆg!Åù:GêE­ù.E¬œ'­%×8þ›àÂì_z,Á +,‚/`mkg¡è®î:»îºxâ ë-^x!¢(" +ÞŠ… b'ø +‚¥ß8¿@ÄâÃL’ÿüóO&1Æô˜HH¢)I#Ô˜“@»êû./&嵊MzíD¬ßåúk®NÕ”öÚɸøú0 gAëÎIúòj‡ªß—÷ÆÝ7½ÞwY)xs bËØÃ6q†gœb£V¼}Î(ÖŽ?È5Îq€LcRÏ"汆mÙÀ¢rÙÆ1¦¹¦°„uÕ³ƒK|Ô€õ–” ž÷Ô2v¡|sXP ûxe¼œ  eô=âŽ÷r°'Áêèûıê\T7xÃ;^p¯uÛý:‰ò˜+ìj¯¦½µOªžƒèûßù*yÿVŽ¢Ö;ªXÛ^Åq ¬¯Ù˜Ò*žüË ‘þ[íÇS´Ž ¥Qûw¯ŠšÏþ›#ÕdÛ#èי薼w +:3ö|„âÎKF²1®ß¿´'Ô~¾ÐûÆÕ*>~ŸÜÍÄò¸ü®ßíŒâÝÝtw/~Ÿ]þVi‘6qãmŠOiž>±u$½|9í¯ý—‡? pÛ°‹mÔ»OTAÇñYiìè,)¨¨ üü'vž{Yöd!AÞ( ”m”„„È£MÀBj°2&„Šðöw²'7ŸÜ{î½3sfî™ !Œ…ªô¢[z ‡¼ÞeÑ•’•Dmì¹µ/ˆïÛúïqíMwJ§»·\Šè×}’Ê!q}'޵õú$ýÜÆ(I^íûDZµf¦äò*;ØÀGZ×wx­µœNå1ª]Vm ºÿ?äj¤¤éwµcµlõXpbÜ+¹P«ÃB¨Õ\Þ½+ºñý±½Ù)Yõiµnc]\p±í ;lù}uH»Xœ>7þwÎäBí èл²þÅ îfãpذ‹mÔI/ƒQÆñÛ®,-øÖ>†µm÷Öb¨Åk¨kˆ1fjXH$"H°DBb%‰ˆ…tç°ò¿ésâ¶±øå­{î=w<œsó®d´K +èFºFRÚ$-©Šö¤Æ)÷€rtHJÒ:þ‘ÖØ~ä0‰q jŽ.é–Nék³¸µg$ìgñ>­y ˆù¾²ZÇpÐ' +Æ |ßQL霗±‡[¼àJm£:§ ,•â±z|;Oðý@j'þŒ}åÌcÊû*¸Pû:e[ØÑwC¹È]…F\3/ûÑÄßÍÄŸPP_rÇêÀ=Ä6‘(­Í}iÞ3œãöjÔðûï¸Ç¶µ6ß—ùÜnp‰CÓ±Úü>v±¦qÌé´÷¼~4ÖŸÁ‰öåÏg³:×Uåðû>ŧγ¨¹tW3XQ¿í`ÎUåÓýȘî0§;7á;‰ÄÞÆô»¿óì]öê[ù¾-¹òwëÙû³uø¸ûVŸVßVWa}g´–l°æ>Wþ¦#õµúµµ¼Vÿ­þ?Ù¸d+¥~\‹b~=˺›Ã_ ©|1°‹}ÔÍ.CAðSÞÀÚKH¼ƒ×ZmÝ–V«Ú*Um±ðQ*>ã³BÅ`oecÇÖJbáÒÿIÇMXürçÎ9gfz¦"R‘y˜B4öylkß0)äcýaˆCf!1ö‡ë?6.Ê8)(Ã>\ñ9 Æã8“dÎ4ßmqÎIpŽ;o”´=ÎI¶Ý>ÝSžÏ´3&æ¬EãOP†t|–`NaŠ£X‡w‘žÝ¨‰tµð^‡èÇ÷o¸Ï¥ +{ð ðOpÍ<šo…±á <Ç Æ9àœOäèƒx¬;ÐÃs߆fû=ðŠuÝ Ú_Ћo̧9Žàîàžk¹„ØeÞ-g=M:湬ò{ƒ±´}Î=¶£Ê3+²½uîUÏ¥Ä:Ñ_d¿Æ]vÆZ® +Ǩä(;íiißû}µ=Åß7Ë÷k#-:L±Vl^Ь¾¬þ<Ÿ¨tj×_Ëžï[‚¹¬6µõîº÷ÚîvÄÉim]OŽûÏÈﶘcÒù?ðß{û¤! +þÁ½óAg¼Í‰rMºžüÇÝx°‹uÔË.ÃAÇñ)+ïá¼€­½µZUZmõæV—ЈkEQq-‰`#$؈ÄÂÂCH$ì„ÄwÚßÄä]|2Ó™3çL;35Æä1Y$EDÂÔXT};6 aqñÁñ¨rÚüãC<ï?CžFÆn µ¡ƒþö•?¥ü9Å&‘Á¤j'µ—„úcˈ› ôÓÞwÊk½«÷Œj_©@-»f‹XQ;… )¢‚w¾ç‰1-ŸÆ´×òÌç ðÛ…Èê&æ ×XE [¸Á+ˆ7W8Å1¶WÆîð„{Ô°¡ùœãoøVû€TkCì©‹½õ¢@¿‡±væ.±‡CÕ>RΊj¯«-k¿»:ÇšÖ^ªo÷»†MÕ¬*ç uhÌGã>ÔóÍb^¿Á’ÚÙ¹ÌilYy7´¶¤ùiϤÅOA2:sw¾ösNg›÷æÝ™g5žÓœ[—6wÇÞ1wÿbÿpw2ÑdÞÍ¥T/«¾½‹ö-¹w7àjº~Rût÷Û—5ïØÆÛ÷êÿ_øÿ}Ò/á&ü·öâÝšˆö]ßã/—"Và°‹uÔ»NA೩L| +_ÃW±±µ0Š\V`‘è"¯xÙx‹Z X 5övVö¶ÆDÿ‘ÿ„qÅ—Íž9sæÌîìŠHRºâ4ë˜s¸ãƒòæ! Yò!Ÿ‘p¤È·æä¡e8ñF  +¯0…Ø T ˆË:ï p®‘£€c‹TäÜ%Æ}Zpd97èS£ÀÚ‹ÏkàÈqÍeX…5¨Á +…ŒïÁ3ö8_"CÓ¸þž«‡|ï ayŸpÁ½o@-¸†#Øg½M¨3Çä?Á¼Ã=@ƒLþq÷™Ë\ ÁÖ‡oô†Ã1\Gq㺧p¸eÛì¡Á^wY÷ÚÔa/mÖ8¤ˆk·ºýzcàqk›}6a‡õëÖó­Pñ-æ6ÙSHU²ßGÈ÷eÎ`‰ï//½óÈÿsZ¶rt¼ßyQæœè9Óó§ß¤~+ö·a¤9žàx’±´ôΫÖ×ÚZCó|kYæh<ÃþKÖ3(3¦çÛýŽãý/ÌРÿ†öŸpæ¹ÿ›¿û_ c°‹…ÔË.CAÇñá$l$V¶žÅ‹Ø T[¥”œj¥—¸q‰¸%D"DD°‘ˆ6Ć­•xßI“Ž“6ŸœËüÏæ?gfŒ1S3ØÄ€ü –‰bÈ{m 4¦QÁV1scZzðjLkWÛþ†,cK˜À’2Ž,¦Ô–‘´÷>ãÅ6`ó¥<.GJù“¡þÒêËïÏö•Ã,Š˜Cy±ïʪwÔikíUíèÃ7sÐÎõÄ(W^ó± ½/ªÏ‚Ú·p‡O¼ã+Šsc¨Ê"Ö5·»ØÃ~è›ÿÚÚ†nîÇ”ËÆâ^Ï8PþªrW4†¼à·¸Âuí_›}lŠíó—xÂ>osiì7kÊ_7/y¯~;¿v]m¨>¿î²b휑@óè9«ÿëÖ‚[G9 ·g¼uàâ»VÜKˆÛ3ὓ¸©ï)·Çâ›+¼–]n÷œU=%Õ›Ò·1S߇“Š t?®¶Xƒ±…¹s¡_šnüî|Ÿ'Ρ_Ì9°™°‹uÔË.CAÇññ¬l¬¼•-/@‹ªkµÊ)­û]‰[Üoq A\±@ @""±öýM29ÒÅ'súïÌþsfæc"¦ ¶ˆ:‰Eƒ§^¢E¸ÿý11ÄÑŽ+x3¦¤%<_ãŒç2LáUÄnÑf±†<’hVÎtaÓj»4—“PÛÒª<ÍzîIˆK¡£ªiYtkm¶Þ ¨îœb£ª/¯1cXÀnp…Ö]‰]ü`åÄw”#ÐÜ}ÊkÛ Òj”w{Ê{e «Ord½ºæ±æ3ëØÇs×àߨ&öª~§ø$VJû…s,j]#jm®'¼öÚÀ6Žqg +gáPµ‹kHkÉjýCZS^5åÕϚĸÞ]dôü|AhßÝ9ꔤÇí{ ³‘RlP9mõØsÿž4¢ÉÓè‰árúgÚÖnÏÆŒÞï¤ê²wÅww/Ò’ôjóësw·Åok³w<üˆšÿß›ˆúºµ†Ç9ß¡_" M°‹uÔKKQàO!Z´‹–õ;Úôú+¥–©i¥Xi^F-)³ ‹d*ZA—MEA´kÔ&hÓ²÷sÞC‡3gæ\ß9gD$ ®á6F(ÐFF-! +’ioÊ!‹i†LAÞE|Žˆ¿×gèų3¸Ç}'ôáþ6`f¡Kà°Ÿqö‡À5¯9HÀ„EË“¦N”Wïû$¥HçQ„}øÀ<{pý…cXàÜʰ%˜'}¾Æ¹iÛuXM8…Köqoèw›oåoØenUŽ“g¿Î)Í{ÍhšKm1·‚U_3cN:ßëmCN0v\á!c?2ðá™ü¸ïäå€n”ï8G{™kÛƒxu³Òuµîáœ9èúá‰ëüâ7l°/}/ðÀŒjÌÓázK\GŽß¦ÄŒêâîŸ:ëU¬üŠÌ"à ÖwÓzY~÷8™=äÝY¶u8~šÊ̳É1“ò¿ì3&îþµÏÖ˜¸ûÚ°Ë‘6¢£ÇË3Ãf–â{Sß{&ÌY0ý„-:Î4™z:7û¬›óïýß8³fÓÎûŸiýGþ‡ãv °‹mÔËNSAÇñiÃ7.\»ã|ŸÃZK¥íÁB)-±R‹J@Â% Ü!„! Pƒ7ºq£!7†øNú›trÂ⓹œÿüçræcLÒ“ÀsIx’’òDûÚð +íHãeDòîY›¤5¾ ÆÄã'˜#öŒþMŒbu £„×(¨^FrÈH—b¿âßð y/&§vQ +ÊÛ!¶Þ©˜¼êŽïEÞa׬™2þ”òÒ7÷RC¡Æ `;²¨<{ø‹Z¿íßÂrr>æ +§Xű­\ƒx‹7:—~|ÄŽd ㊵ëªh=e ÕgŸéü'sÄã‚=žà;õßhÑúðŸöÊ[µí~¦0‹¬h/_pFì#´R¿Ñ>êz×ËøÑÈgα«÷9¨õ¬ãû˜ÑÙöIè±kW´W›c #:ÿŠÞIÍ;‹0ÂÅ•uÜýÄÝ“¢âí™}VzweXg¿¡ù osÚû[R{7Ý·Õ®º•öd=JŸ5Í;îßón݇š¿ªù¢ñ/wÎ4¿… ²¶@{+y{qÿû}»ÿ@J}þ$íïÔ8ÿ¹óº_l\z°‹mÔËJBQà­Ñ qÏP³&AÐ[ô ‘™éÑÔŽe¥©!•–$]Aº a4èQÑ Y£"hРI úþ‹6ûœ}]{Ÿµ1&hŒ À,Ò‚°%ä…1ˆ³}Ä#Ø‚¶’Œs`VàÛ߉1þtá¹u{P€,LÃ$É%Ÿ`L–)X†+ø€;(±_ÄÓ/CiΗ`}šk¦Èµ¤9f–àñ î-cÚÖPþà=׬7e˜g¿ +Ÿó[…r¯ûð„±íЉç7¶×gcà.à ^ЯåœÂ:÷)g6Ã*ÏáÞá6×"Ù7Ç¸ŠŒ³Ì˜7à~±Úý=Їç Ï·ÁØoàn3ÎÃÔàŽ9‡ìõº³¯¡ï÷°Ë1užÝ3÷[gœÛ㑺ÆW°¾£×¬uÞºŸ÷¨ß¯Â|ѳÈ{ÆK9iþsMÄ)É|ÈsŽ÷Qe抴m3fÙƒäQŒsN±ä·æ±Cš¯ö}Œ‘®ï²Œ³>j‘{šâY~cÍ·Eÿ¨µ¶Ž×¹56ÁeÌ:Ã6¹ßr×õ?¢õú/s>½sûzÿÃâôÎÊŽ°‹mÔ¹.DQÇñcí4 +o äÞ@¢ô öe˜Ë0û؃Œ b !öJ%!Ô*o ¡ÑøøþãÅ'wî¹ÿíž{ç:çšÜ·4Z¤íh tJ¿ŒHJz¤ƒkßúfX«ɨ\:—W.ÃR§óY G/}¼>ú'9ï’3˜n“M¹–æýcÔU?7Îõ!`-Íú =­/½-&#÷š¹Þ¹ü7ç +Kœ+¨Ñù¡ÖdQ–e[öeMf™oZVeCÖ‰¹•wå±gr$8—S¹‘OÅUJ©~?’ïûM1»Ÿ/'ÏŠÑÁ}Pßf˜e—¸,ñ~ß¶˜Éæ;–'Õ)–*©¦æ1r÷È_Âj0¿?ðL^•_!µR¦ó;ö'Çó:á>÷¨3<«Ö¸G¿žÂPÀïñì÷$ÒÔɰþ8ìîýíHïI2Ûœ¬È.²ôd–413Äû܈šaÿÿòïpÌý}¯;¸ÞEþu©ëktÿª3¤ÈI"ÄljµûŠèqÍjÚ –ÿgÖðûs?ÿQ[o#ÏzÙ÷£þ;Ñh¾²oß0°‹eÔÙ.CQàÍ•gpám<‡G ªƒªjuL«­SÇLÄc‚Db¸1].$$„„x×â_é¿b¥.¾ìvŸ³×Z{:ι€«ë¤€„ž!£Ê05„Ÿ…ÆÝ49ä½($  +ûð70Y>‹)H3o‚ãìAõ²ÎL¼»×ð÷pÏð°ÈñÛð‚<-h¿áæaŒûRa}²Ž§ðƵ•5žä\=þ–œ—ð¨ß}Â+ëÝUØ„#Îã®`Ïäqõ3!FM|Ÿï,±•z–á˜y~àÎ` Ö8·]Xa}U®w +f¿ÊüŸ3òT2{Zf_Ö9çÌùÏÿ?3gæc¢Æ˜ÑDCb—ŒÔ¥#MÉÉï¬âpí.ט'æÅÛ¼¹çÈ›&·•äy6>å½w÷®ž‹ŸBÒ«• &E®’´¥Ëœf¥,ÉK‘±Ü—ˆ±±K²)ׯDDsŽ éùI¶dMNåUÞåQY¿:Р}WÎäY¹"Ò/}z¾!Ÿ]–ž\É%}º^®:Œã@öd…:5Æ¿-/Ê?,š_¤"#2¨öy#ú_È=5míuÖ­A.W³Iþš7¿–gQVe_ÎÉ{B×cÆÖf?”Yÿª´WynoñmºŒ¯È·œá»ÄÎïS Þ²ûÄí¥´'C\v_T¨—C¹PǶeÍÏ=>ONš\vwäNÞäÖ|ï‰<1Ióû ¸1§0‰ s´k`÷Çk–%ÎõóÏ¢;OöŒ»ÿCø¿áÄCqã!õÿúO|K!—­°‹}Ô;NÃ@à…žÑr Î@͸$˜$¶’€“—ŠÂ£AQD< + ƒŠ“ð/ü#F+‡â“ãõîìÌzbcLƳôŒ# 9Xƒ"”!†„dŸ{°J+ä‘Ü/+Y5n×ÜÃ^óŒã©¸y%ç(¨Òæ[ïÃ&4!:TXg‘5V¡M]8„S8æ} öàᎠpoðO|>àž5%æ5aüWc&¦af¸vÀ™\„yü~€˜bÞwpÏðï0‚¾ªÁž[ƒy5¿ªj«;s$[Ï\òülÝç2É9滩¨³’ñªq~‡ïdŸ9–øžmïn+²®ìØ"éƒuóÛç¶_tIÏʼHÍ ù;rÆ}õ\æl0NZk!ϵÏs²ýö·¬9rrô+Pàäß4ý”p,PyÊ|‰'ÿó,¹ß´ïˆ&5Ž[ÿóø +|¥°‹…Ô»JAà_Àǰõ-|5»1›¬5‰¹í&ë&Dð +¢à‹Xˆ¢"VÚ‰…`%V¶þcþã±ø˜Ì™û™ˆHVDf`feX÷ÁcÝfb!´`Ö`æ©äØWeÉc›OY‹Ï6cŽòNÏ‘!oÑ}ø#æ¬ýj™3­²\‚e¨ò¼'p,ßàž`"æ§)$ŒE¬ïÁ\ÁŽ`Ú\³e®i~ס—ð!’Gù·\¯Ïµb®Õƒ.cçMX¶¬~ ë5hpÌ æŸ›„gÀ˜Ì5L íîuy„WÆ^àœãkÌ“ÎÙ¤:Ës¨ûѼČ›<3?§°O°Í³ö(á8=ƒ­ÁxÛ™?eLûÄÜwÊýUxçš÷˜´­Jæ~J2üVŒ‚#¤¢Cãú^Üq:v¥©›ïÒ~úì×d^váÎ`‹û å÷{p¬¹ìµË¼«MÎÛeÌ´-R‰u}Cî{¶ß¼÷G›¡ÿ-ÿµÿøÖv=°‹uÔË.CAÇñÁÖ»xK ;¶Þ‚ÞÛÓ›K«Ú£U´B©DD"ˆKˆ $"<‚D¼‡ßÈw’ÉI»øÄ™çÿŸÿÌœÃ7Æ,ȼÄ$-YII‚˜“‘šœË›\¡%òÒrãˆO"îIR?C ¿Ž›Ÿòb o¾“0Nxk¸|Ûg@ÏAdÝ,ñE,³çmy1fdRäDfeJ¦eL¿ŸI›¹ûr(ix¶¤'ÌÙ#Ö`-»fYŠR"¶FμË3w`kìʦ„Ô°w±ÁØæ­zí>êÌi1ÇÅlÏv_òmÌ茌ëyNñ_¹—K¹–Gîÿƒç#iJUVPe]Ç®×—cï\Öas»œß«|É“Üòü#ŸrA®=‹zv{¯yBj¶¨r&î§É¸Ëô˜[á¼+äuÑælëä†ì±€Æ¾aiÍ&›+JÒ1X¢4çŠúhŸ$ÍSŒý’mâ䲟ŷx.÷ë#νxP€ +ìëˆó,ÒƒùûGDú>p?#EûÞÁ)½¡mÆ`Ï/p5Xá¼*Gyæ[c.0i^³¬G‘×<Çê<ë´Ê÷Ö¦ÜÖ?KãX­–:¾ÎZêÚ‡`÷ïp{°ÉõïÀÁ!l1O%®Áêhë®Â1ÜÂ<@v9ž¥Kx„oøAü^@Üà8òŒz±FGsü ¬‰ŽßöåµÈ½l°­ÊucN¦aúÐvÃñuö·15æT÷³Æ9*œ¿ê‹W`>=æVkåJël¥XK¿TiòX«m…y´~‰6vΓÒ:³9®EßÛ7ÒIBþ¯!Ã=5š9vŸÀ'òŽú®ñ<…ö{æÀÎZÖǾ­hWïõ`ßä,µÿ+LÈ'úÝYë°‹uÔËNSQÆñÅ¥”‘qÌØ¡#æÄÀ 0àx¥´ÚªèÅUÂ%VI¸&Å ŽÀ`œÈÀ‘àÄȈ„ ÿߊ›“0ø%Ýûì½×:k¯3{nw†0‚ILa\ãH&ø=†iT°ŒyE)¼ˆIÉpLJ{¢3gPÓyEä××f´nL±²A>y—¼æ=çt,~: +ÎUÜ ½ãêø€?f­Í}f=fÉ#³ö3枘µðØ>a{øË܈ÝòŒñ5N±Š²Î.ùzÍ'eB¢ß³xE,¨NÑþWªUEósZ;Œ£5%í™Q _j}o±ƒüÂ>ëª:¯¬˜u­M¬i®¬˜Îë×Àöñhb[8õ´cœã7u뢶½ÔøŸYÇ.udü“ù~žÅ;¼Q~«ªOUï^“ºr¼bßöÁw~_âóÛÁž%Ýó–òª5õúùûûzŸ”tŸÞsÞ§Þ“~¯~ßÉÛýÞ-êü†òn*(N.X›“(Ö¨„1Ãÿˆ÷yÖþ÷w!ÈÅM©ߨ ñÚèëý¤ßO©[7Ï.u×UåY +Þ9‹™‘ôcÿ&Ä¿ño‡Ÿn×Üu¤Ò°‹u”;KAÇ'ÆIeoe!؉ß@ìý BÌCs^^.ž‰‰Ñ€¨Á7¾Åˆb¥¥¶‚_ÁÂÖÂÆÿèÉrhñcowggþ3;·"’”_R r`–ã4¿óEà”€² M¦þÀìeHФyVý –èße|sÆhQfˆÑªçç,òV9KŸñ•µH[þÆ-1¿*h‚mð*9‰~ˆôô‹ÄžðÝÆÚ>öžÁ:X:Ãú ˜ØË&˜§ÿ‚USÕ\¶ðH¬Ð'bË*5©ãµh£:‹`¶•eŽ•ãcœk²ËUÚûô§¾×À18[ÔPcL¥N›=pÈq‡¶Z‡6Gw®À9¸¨[B¤k u‰Ç0¦ë ëÚ7/ôÙ¦æKpÄx Æ®SüFFq¹t |ã#“Ø{¤MƒùkÎ÷à„u ˜·é+“¿Ïû)YkžtúÎ`þs¾H +$lëQ·ÖêܱFÕN¿¸D{Û!9 íålÓÛFoÀ>0šÞÍ;êEнÃ" Üu<ÉÚ÷Q[“wíKç?s-j°u„çá÷â¿÷üO?6ßÕ.k°‹mÔÍ.Qð[*ÊÖsØXxïàl|tTG;V[mi«¨ÖW|‹Hˆ„ ‰ÔÒBDll­=€ÿéüOÜL,~étîÜsîœ{æc¦L`†â–9JCrà“ p¬¹jšþ‹Ë|ò°eÈ@f)Aºž$¹äqm®s>4_ó†ãé+±RÌ/qŠP‚83&‚ŸÈ·1=oð€ë/èÃͨrí 8…ø„Wx„ Že™CéÚ+°Ì|yZ„f»k“5*òÙÇ7  ÛЂºõ\‘u)Xqõ¿ŽKîUλp[|w]ÓÉóë|fùk|ÿ2s¯Á1\à kÒf¼:5CÆa‡9eÞj‹÷éE¾h†Qó ÜÇØ;ë!¹¯ànaŸñ+ÔêÁ\Ô+ƒQ\ÿàž±×Pem/áÎYí§ å,>Ç´&r&ìýÕ9žÅîãcTY'ôÍ÷È Åu­ùBúWzÙ¡p¯»\CûÐâ>ùTbý¤¿ÑèQì_l̘AÔ«÷žQ³öF™±<ó÷ÝdBuгA¿='Ä>/kz>è¹4IÝ3ãF¢Q°‹u”Ë.CQ†W<‚‘ÄÌÌÀ3^§Ôé-GO/§7‡¢(­¢¤1(bÀL\ffb$1‘x‰©ë¿Ó•“|Ù—µ×¿Ö^û""Ë2 NVB$ÀȃÈ HGùÅGhü§©íc¸Œá4Hr>Á~’1S#Æ.ó*†üWC„õìØêd¨å©ýúdôÀ§Hd +L¢ÿ®Á.¨0¾¡ +¶Á!hƒ–Zã1ŽUàÚ.8Mú›˜%°E6û%ÚÊ àœñé€3p v@kÊô±~¾ÊÓWT•^‹Z=Æ­ƒuæ_a-`Ÿû²ö@i€ pGL¾5bÖqß'´7ØöÁê|#]óè?€9Ì¿ÒÇø^‚{pK:÷bØä>¾á÷ øDßÀ Æ‹˜až÷a4¯ØÖY3{'=ž•}YuOôöÏ7;ÂÏ%i¢ï]ÀøÏà œò ³ +ûþ’JÃŒÍ]vdø¦Êî²&Ö¬Ïóó™—‰ÑÔ$Cp·Ç§E&fEÆ0÷Û;ëT å‘a ì¹æ™›Éþ='„ý¾GûfÍß`ÿ¥ùû3~«óI¶°‹}Ô9NÃ@àqÎÂ8G  ¦á +ˆ›Ø !Æ`³ˆE,bA@Bé(¸Ôš”ÿG#Ë¡ødÏòÞ<Ç6Æ,š±:-9l{X…ˆWŸýš·\ÂssîŸ'ƒ>ïˆsT{Îûgø6Æ›‚Y˜Aû^á”ñöz\7už;e˜ïáâ-öÏ›·Í×ÉX¿ò²NíwDÚ73õë}뜨­ó 8õé{ÍOœý·çkÈ=N¸NèÄëÜN»áðKã!÷ã^ø^íùµçJç,ã;ûÂþÌS›ì‹÷ 5ôßr¾­UßW“ùU{Áu¢Šš\úG(^Ï`ÿ åÿП_Ä©Á°‹…Ô¹NÃ@ÐùdÈjÇ vŒb!@Á* + DA…@HTÑ@AG‹øîˆûäÇ(Å‘·ywmŒY0¿jÊ"Ùó4¡ > §]½B­B™ˆ!ZÏÑ&yÞ$ikÇ03f¾®û/ÏcMKP@ö~CêC¦æÐ™#Tã‘v>Ù¼œÃ ^඘8u2®ŒRêAÁ,kÀç]êS®Æ3KËX» p7p°Ã±Ma°ksŒÙöŽ˜)c+¸~{ìã naŸy#öu —ð_ôȼ‰êg̼Xvl{÷ð +ïð Wì§`홫\«”ëQBö™Ëaöa +)ç¢ ~•ùDÆ:ºÿ„ó)e”SÆù„´¯!Å×užytÍØä›šËsüÞá…ñÕ}äæ¹4çQ0«ù,Z؃¸€+¸[¸†s8†9㶸÷–dÏkAîÖÄÈü×í°Î¼Á£éÿà^á¾àî¹Vò­CôPþs ã¥öœ±G9÷M2P>{ó^ÄÈý¼žyjÖ×÷nפŒÓ¼™yϺ׊cöÛŠM½¾×;>4sö{Ò¹kç¬1çYȹOYßg¦}è=ÝïocÄ^v©q‹ï©v‹»âkûÑ<²GùŸÿ¢eêX߭Ȥî°‹]ÔIJA†áòžÃs‰Æ˜Ét'1ck¥…à„ u¥".t-îô‚—\ùµ¼µxHzø§ªJB›!„-©I]²‹š‰:Ò—BŽd&9Ïä«Gqi¾êÝ}È^R·Ê‘Iw–r#÷r)ê§ý¶ˆé‘³õšÓïc™Ê¡,˜cÄ9¶Ëý,ê+–Eù}Ýãúèrßyôã^Ž™· ÇjþyïÖ6d]ßßeÅó<êÅu<ãŒõòÜU®sêŽYƒ3¹àó\îäM>䙵?a¿çôçš0OÕLjë3j/P’ïZ®ä”š·ò$/ò*_ò#ŸòHm¯ Y‡˜ç/¨·dmKê¸nIo£Ä0á¼9||^|N¼—S¾{Għg(ÿg"êdäMù\Æ¿Qó3_§¿å6ýæìÍŠ=X±7>»îÙ½ô‰ñ¬Îã3Þ&Îûá÷«ÏyTcH\ú_Ò¤ÏmÔ°ƒ¿û¿ô×üV°‹mÔ9NÃ@àÉy8@¬qlÇŽ—Øda1« „"6AACEDn@MÉèy£¼'ý²(>ÙŽgþefçÜšsn6¡ =¨K;¤ß{TÀ5|À¼C‘Ó‡˜ÏÆÑûÐäé1Ær2î#¼Â FcëSý1ç&¼˜'… Jc ‡pûP™zl)k)yzV|åîSÂy#*L߉¹úy»p pSÓÿܹΠ+ FgÏ¿p5s'”RÉ~jÆ(ÿnéœ9*^}Î3^} oð ?°àœ)ãLëžÝò,LÌzdìµ2uŒ¸æcŽmد¯ã†ñgŒy/ðé–çkÎ1ªW{¨û¢ÅötÅØ—äs#Æ9æí™>÷Á÷üó ç<æÁÖ_à¬3OlòÛº3ÀºWàœ‚!Ï¡¤}ì€#p>À'x‡¬'g/'༃[jåÌò©utkØ|ìeÄÚÎYÛ™üÎÔˆëmÖZt­=j΂gãk|¯àŽ}? æJõýõ›éœ¸ ´¤šS‹Î„=ƒžŒÏMB_M½{ÎÄ{m?:×aÍ¿!Õ]²w30k»Êß™û¯õ³½©ÍÞÝÈô—?«p_Ï5bl “kµŒýƒ~ùSPC°‹}ÔË.AàòžÂãx ZMOééÑ—1CbˆK‰¸,\a1‘±aiá=<ÿ‘ÿÄIgÌâK«ª®s©Ò㜛qÎÍÂ{óžþØÞbÎk>]×oÊöbûѼúh?ãjµuh¾ßß Ó÷ÚŒ°‹m“O/CQů/K´}íûÓzZJiÊ‚ ‚H„‚",ÅÖÒWè7gäLÞdÒÅ/÷Ý÷Î93ïNa1Ô,;–ˆ<7A‹4¸À ˜†0·€õ‚Ä « â^bD }~M:$1ç›ÕDÜ«OýÞ&r¾`Žžy¯ñcîcCJ_B—µíƒ[ðŽÁˆµäÔ%&^Ìøu§àŠëÐÄÎŒ^}Eæl9Öè¡`>©e.Àxgï¥ß› ¤ï®É“ººVwœÓß÷c2¡çoüÓy¬¿à‹ú=°múP2·è/ÁØàR§u(k*ø< vœ€kðžÁ÷ûˆ¹úæ|N4VIrö1gl9û +>Á ¸g?À#óJÝëô[±Wzõ?k?ußvØ;¬ú‚¾¥¾-Öë}ê]ê8¢Pß ½VkgCµ:£ú¾êymÍð¬çt–¼Þ{ññm½~¢q4¾÷çg]½êœüÏû§LÍÔ°‹}ÔINÃ@Ðæ‹cpÀIO1±c†ˆ bF,˜,`Ãö¬¸÷à—òK”‡Å“Ýêªj»çÜ’ûµãv[i]¥VgÌW¾ë„¹–ìÓc]ú¼¯8fÊf¬ßŸMÂïËÍš +wD¾—1cæ~b®W¬ÅÛÇ MNº¦œì:mõÛë÷²û¡Ëø‡¬YÅùKÞ™¯Ý‡vžÜÄ“¶ì{žôœÅNäÄn¬îuÝg)K÷·²k^¤éæ´ÿÿ/јþlèZvÄlÏYD°‹}“±NÃ@ †ÄŒÄs0ñ,ˆçÒ”¤-IHÓ¦í-110 ±òl°0°ñ, ñ[ú-YVÚáÓu>ÿ¶ÏB8 !œm!=’8[è¼_ +. #°_!ì‚pû|‚'Pœþ©#3ô7äÐ…ú¥Œ}"¸3Pšå|jp^Áxaî ý/YeÀUâ·ÔhéŸ ­!'C¢qÔÖs‰[P{îH¤Vɵ"šßkÅzÖà=?!ì`•÷ÿÏà>RóÎöÁöïìÅÜí‰ÑWÍÒä¹b¯iÏÙI-}Eÿ‘¹,©3cÌÊP­Wò˜RgÁ}Ã52ïÈ"c¯™cËû5ïŒiIC4W=÷s`ßK)èß:´—KögÊx]ï®ZbËÜ艭,Û€þÌÝÕ¹Ó9±ÿÄþ);³#÷ïë»ëœÛÿÛs$¯éÿ†Öp.üÐ`°‹u”INÃ@E+\ƒ5÷#“‡Ø&vllÌ$1 !!öHìG`Ç1Øp$~)¿”JCOîTuÿº:"2”¿’ íö{´óÁD$=xà38ûXü€OðJóÜ8`BØí™ÒîQ_Æx‰³ëÙ¨À¬@C[âôô| +Ì÷†œòlá˜3çœ:3®ÕVsFMŸ‡‘ЯZGÀx'` +î Y'1šˆq%‡à l@Øîõ=L@É^ÆÌǦ^Äú^ëÀ‚Ô à~¥ fL}ƵcÞ'g½¸ƒ4¨35µF†Üärƒß;KpĵÖÑ|ÅÜ-øÙ™‹ìöÀÖ÷ˆ}sjüy!/-ÏÏÇW¬[ð{Ô¯¥¶¤úé÷×Ô¬Á¸#§Œ7¤2=zÏKãé:Î{Îû½â¯ÞMà jüú˜~k¯ÉŒ¾…©]ÒÓQë=žÁ'ø¯à5Wô(¹Wï?1èÝMx'ûhy†Kùÿ®¼Vߣ¾û®2“³³¢ï&%ÚOjÈè7â?#:k‘©¾QÇoq<óðÈ»­äoÞ†²=£úÑ5Û!êSÓÿy­†Ã°‹uÔINÃ@ÐÊŽp®ÆˆñÔà˜`‡$HÄ ,`„ƒîÁš“ä7ù%J½xŠé¸kê"Ò‘­@_Ú×7h³CWœmJ ƒ&p s8#®;H)ᾈ4VLQÀ· WðNþyÏìIYCÆç8¨/1ïf¬Çï2vgâå0`/?Ç<Ú§ãºÆ+' 8“+3ûFœgû°cøº§p7ð%Ò[u@ϽU¬=Â!t±.­¿âÚj¾3d¾Âôïë9eÞgø„¸†cTfNû˜1¶Î.§‚ýÁã=À¹©¥fÞ†ÏcöÖ˜~j“gÂ:Jž³òýø;ù†­Á+|/ç&?p —²¼¿Z«ž«Òû ç¦g¬ç5§)óé¹ë½Wö¬í<4‡½Ã±É›ËßKÍß±ü¿ëm¿¥„yK3;=Ç^|íwð÷œsjâj­¯+îÑÿQ°ÿ÷ý6}-c°‹}”Í.Q… ïeé <È0mº§ûÓÝÓHŒ‰6HüDB°‘X ±’HXI<€%O`ã\s**7®Å—S·þîˆH[DæÚò·½Eæ"Äâ,RÐéEÒ£-']ú'DcuHà}p +^À8ȨÉè—š6·ÔÄ×\ÉϲD +úåôõ¿• æSýj¢­³â:Sÿ¨®fÝÐ7ýôï«àÜ€[p.Á#ûã¿GÔÆëÐÚVÀ:ØCöÙÖïíçà|‚wpލk"=jhÓ~hŸë9oà<ƒ°Fg™h슽¨h÷gï±ö3°E]ßà}·Ç9O<ˆL~‰LÍà9‹ïiØïd¼[;ŒWr©!3óµûÞPw®9Ÿ!gæäwïcwÆÞÝkõí˜ss¾;Ö303 +w]ïP¸û%{»ÉyÖ&?/¿;ûìå.ÏÈ‚8¶–Ø9š«þw$þG÷ f + °‹…”¿JAÆ'ú ¾O!Xû +crwI.çÅh¢§Á?Eüƒ¨DQH+ZXˆ`-XYXÙÚù­÷ Ö‹{3»;óÍìî‰HEþ²D¬¯ þ¡L=l܈ûA4A‹4I "®óõT +òUAŽÀÜ}ú/¯Æ´T‰¯W5*QÛi]mŽ-~¯€ÔÔå|Žmêr56ˆÆóí:5¨þЬ‹'¡»Çiéƒkð +žÁØ[`lP§jUÔ·Jºm=®–mp`ÝèpsgàS¤4 fÀì®íš<©×=¿1s\‚7ð^À)虾¦½Õ>¹¼'à)×&ïà +df_ÂïAž£ô-29nE&ŽaÏÂÎÁ!ûØ‘ñ} IäÙ!ër¹nÀkxd®ŒçÒã:½£5³ßž{LÛÞe½ÛŒï¨‹Ý2dí™ß÷¹3^»’¿©=ö¥Á¹>ÏxÈù¢¸ú6õ¡¶ê´½r¹ç‰¾mókÿö²€h°‹…ÔÍJÃ@ðµ'_Á‹G_ÀÓjŒÍÆ4Ý?jµÔ?P<‚ ˆ‚ ¨èÅ“ xñ cã¨òz2–À¬Ãã¦\Oîe\Ï›:ËyjÜÈÌ©šÌ8 X†,2w©¡Í\êÔག‚©15ñò4ÃcyßRÖ£¼¹§û*yÃ=ÜÂs +&ŸY +†\/@‹u¬ðÜÖ#5ta¶8/ðžÔæÜÀìÂ!Œbì†órÒõ²_êVZ_Μöà +à6ÝwÏhßdÜŸÄìS` 'ð†|†açw°jö@ó’±GÌAÔT¹Æù' aüv\¿Ç´gµÍ[ë‰ Ïú/á±ppÏpļ°†»€ ¾wÛÚ Á¼›‚cÚÃ:_û]Þñ><Á+¼°šŒù×sÚ?RW‡{Ñ2{Ûå¾}ôëèåÜæs‘¡ß¦þ#Êÿ»®|{cTþ¶{×_w…Nß°‹m”¹JA†k@S_ħð5L|×=œwö˜]]DDcÁHL} cñoú/·h >ú˜êªú««GDVE¤ê` d ')h‰·Q;µ­soÅì«]ƒ´šÄÅIÀ:(À>¸OàÜ‚° : æyÆSêôŸò\Çhˆ¹v>+Ðç7õÝ0þÃücÚ&DÏ4¹.©áì2Æ3V›ç]m»Ô\pž± ëbÑ…6ºŸh~)cvLn§`FÔî|öxϤ$9Ç-Ú¨ghòîÒn@cêî™:߈Dó{QÛÏ励2sGzOVŸjì2ß¾ÉwƒpÄuEºjýl¾gà ùÌ`üw¬Ñ¹å&Î9ø„í2@M¢¬_ë2 ^­ÆW=ÚOÚûÎþ¼ø<äÁ×J^áã—ø7PÉ´ß´§KÆðN÷dúVcùûÆœžK¯3šóZäžZÝwíoÛ;a¯VÔ—s¿` ¿ás ,bþλÈ[ߎj¯Ø7kùïóËÉ£°‹u”9NCAD€€€Kr.Âlƒý7cÿÅ,± Ä" 6 DH€-$D 9w Æ®’Z#<ýÙzªºgæ;çι:h‚l‚° z +¤IV‰S|í†Yß +P\Ä GàÛ¹èÔæÁ"ÚÕdlìCZFÿ?=y‹LŒðý50`Ž^;1ël~¡ÿˆk;DqmÖÌûÝ{Ü»2:}™ø®!ebî5˜qi°.6y +í•1W_»‚^6Heô5ß')ø2¯!csÆ©Ò(IcÛ'àç9f'íñyç&^ë³ 1ûÝ)ûçô; O?·NJã1%ª»òõ9Ý‚ð ®À9¸§œ×ùípî¼'°O-³|Ô¾ÎK÷Iw߯ñïë\ƒ3ð~Q§€wàF`‹þSS¯uîÁ#8æ˜îXxwræô~À¸aýü¼îwj´S7ÕÚÞß¿ƒÏXKèÑW‡Úz;á¿#|»ê‡óê7,/öh&°‹u”ËJAEK$+Â/2q^é¼fŒ&ADDÄ'‚¸p!n|l\ú "ˆÿàÂÈs/–C\¦«º»êvuטYdfmÐ=°ÎÀ1(AR’Ìùc[Ĉ£CŸ_“MÚ9èƒ +¼š­™­î›µào}aüß s` +‚ËÕqù"3Y¢3á¼è‚ØCêHqù¥wL=SÖfàâmÅî»oàxLFÔ²L¯¯oν=’74/Ó©\Ø¡Vé*87r”ÔTr¾pûÇŒQrm ]"»O¼¿¶'à<“K0k䑞²Q»ÜÝWI”Gšu.Ù:£ê%}²µ¿ ŽpîÁ'øïàÆ}0aÕaFŸj§ûW}†.G°¿ï?u÷¨a˜»à +¼áÝ·¨ã‰¬CÆ3Ô¹Á-u×5­˜_göo*0OÝÓ×ü*®ïíàöê- ¹öÜQcÅx§àz×ÁÆ/\ì·×kü?AýÛvlÙÑ?üÌÏö –w°‹u“½JQ…G‹€¾†•o`gã3øB²ùÛMv³š¢AıQ°QÁN+±²ð|[=79‡ŒK,>Ø;;wæÜsçšYÅÌÊ  èƒ!Øh‚©“¦‹×l\£Âc>¿F´·ºàü˜Íž™•VÌæ¾Ìæ¡¥´ŠØ2þ}RG +bÖˆ\¿@Õõ‘Φ£Îœ*× û·X³áN­cúïè´kpŽèUgÙ W;æwˆ À Ùí)¾ýÕþ6‘îÿô¶¨5è9—Ô{ÁþÒ—“Mê×9t†Ôåeì¸3%…µt).¡Ö¶çiH»õëÑ“ó¥¡ÍþÒ›’ {‡¹[\çÔ¬}Þ/¯Ktxîcða6³ÖÀÖoÔ+ò@õ3“¾ÌþÞ»¿WÍ’÷MuØçÜðNéKÆ=š‰ŒÚnÁ3xt¹ò(v½5¿=zÖ·É»öo&.ò>À7|Y´Ñ[µ{ÆÃ|Ý€wðjã¹Îm2—zsÑÊŽu¢uµ€Þùèÿ/”XJذ‹u”?/aÆg"¾€ï ÷Eô*‰–»[{ûçnw­C8ÿ"…F": +5Qk$J­BáyÝ31^«øå2÷ÎÎ<óì¼+" Y$-€.‰@hXòh=o=«Ëud`œˆ“"Ã#"cs"wàCdôSdhçÏ`t@Ì:-Ó§ééÒú)ŸI<}šÍרæiì ðÞÀ=8»œ£d¿”ĤM .ç\ƒ+p +ãQÄü„Ć”~eÞ¹Õ¯ó:Ø—àþŽã÷œ5ÎSŠþöÁ:cWc™äÆG«Kcí¯±Îï´v½>•©«ÿç¤G;`‹:+ÖÈäïüõ®ÒÛnM®}Æ×­~¹ûà>Mƒy0…ø–Z +¯njèÔ'}/ºGú^5Gk©w±9ï±ç öjƒï"•Ÿ= ™ërnÀµžÒ¿’=ùÿNdR¿óªUçszä{烀»“2د’šûÔÚa ½— ùýmñ㢱ývèýz_Ï¥°‹uÔ».aðÿJ$:oâ…D£ÐyvŒÙÙ™½±ˆË*ˆB%ÑP£Pi–ÐI4ñΗœœÌοÌ|×=ßeÖÌêf¶Aá}SD¬Èë·(¡Åä}´"Z° —ðk65o6½l6ÓƒÞçÌjïh{„]È!•9#WäÉ8¦Ér\êçy[äók¿0® ð€<5X„%@•=Á×áãÏŸ0Ã\à <ÃôØîyRöm–æÊ$§·gÒ¿€>ì3ë\Ár®ÂPÁk*d\s‡2Ç)…÷®ü~FžÃ÷[syÞBäTL¨ïòœ=ȱÃ>ºnê:ÜÃŽä«¢û©9s9ß{øÁ>Íâù ·ÌS”æÊD^âg¢ßŸ_ŸëѼåsÎ¥_¸/æÓ{ß`Ý9¼Â'Ÿ7ܳvÅÙèOmò7ëí¾ÿìË +ÜÁÊoplÿwÞ×âsùwY·ñÿ-¯“—}œæ›ï‡q¿á°‹uÔ9NÃPà œ€Ñp .À(¨(8$ŽÄŽ …% „”ŠŠ¥±tZ.@KMOÏÿ¢Ähŧä-ž™·Ø"Ò‘M§I¤íEC]H¡Ïß„cA›êPr½HcIdfMdv wø¿Š¾yŒ]@Åùæ\<›'f_jt ͯ5oÁ.•ÌcׯGðŽz–á`}op;&Olž×úBÌÎá®á +SÝ—ž«9ÄÎHÇum9k2þ˜nàuâ™ÆÖÑþ`ÞŠgÕ7ëß§Sx„Oø‚W8mîOÉœ™ü­ÉÖ¥c~®§uò XÓ€}ö,ýþd.—Æóm_—ß¿÷ì®àÐí“ϯ÷½à¼’qµ.û^Ô<ŸsÏÄÕxù½/)cÖÔ7c³â™<Éô^NÇÜ/]sÅç SOì$®_óçÆ¼àþÌÁ +,¢ýÀ\©‰mã„÷Ó~Sü·ã¿vdØ:Ûfnëww=&°‹mÔ;NÄ0`ç Tô´t\cK + +λY'8ñ&l ìŠ÷£ DAƒtPP!®@Í8üÿH£!Å'9±=ž±8ç†Î¹McÃÒˆºv +lAÛùìilÈûJhà^àǹd«m÷»Pp¼çš)׈ŒáMüœý"Sí’ +ÎoáÎØŒ!s&poÈk 07YÇó7<Â!k—u¼š/Ï9×Úc­Ç¦.-οPïe\A]~SƼ…{êrûD®Ë°‹Üã9sÑókžÃ>¸÷àœMÚKj¤¢×ˆ^%¶œd!Îl î 1FÔžÒ^Jî¹øœƒWð>Á#8dîå?º+cžñº*öËýÃZ+u$ŽŸÓ·¡ï8WàšßðÞÀí=ã* ë8ïf èÑâ8Àïg¬}€ög(hÿKÉGñbÍšuÖÒ‹šñFœÑ˜yµ¤£­—Øš¿ûײî{µ—n›Ç_ýñ|}~Þƒpžf`Ï~Ÿ×é˜×”=œ±¶&š{|¾ã¹kîA7Üm° &Ò“ ç|À%×*јw'=BÐ;rL½–9Åû5nx+üз#-ï•ß‘Töªÿ@ã}©q‡°‹u”ÍNÃ0„M_H›4M“Z BüJ€€ N\y Þ€+ÏÁẌ‘Ÿâx׳㵓ÂaaŸ½g` +2 ¿ùBñÔ|*Ï™%ä`N*Ð#p +¶`ZÆæÔÔÚ‚±žëT·d~e~ Æ£æ#xåsC–µÖ`ÁZSóך·Kð Àç«ùPíœÈÇ‚4̯“ü8¿äÞZÓS¯\wÎõ1o`ïnÁ¸§ßÈ5Ø1GõjCë¯ÀW{èÏõ'obî›±ÁzÖÑãŠã†x¼ã¸¡±>¨ 5ý Ö³xF'<»>ñcÇÌol~I|ß©?ç¿þ,¨³&=‰/À9çµiè<·ìá ÷¦³õ{ê÷[èÜKÓÔ}ÜXÿå5¾ßwð^Âß]O¿Íô›«_Œô#úÉGÖ¹nü/ø?"³¸4Õ«<ÑKó3×ûWQ¡°‹u”MNÃ@ …Ím8 +Ç’¦É$“Ÿm¢bÁŽW‰7@âH¼HïIƤ‹O­=þ÷LÌlef—䊬H*ЂÖ<ö‘ß5‰²}IjÁ@”OçkR²ž†Ô$Ñ'»³ õ8‚ðÍß#m«@ÌÓ:æ8#è·bŽÚÙ¤€â6Ìד6بÏY¿ežìÎ6¤ ²â«¾;p÷Œsjž¾çÄšvàÝìì|‚pÝãf—·cŽ'ðn™¯}j~OÉíHrMy`¬ëÑæ|x{ê›à7¸|Úûèbdþß‘út¤µÿ÷JñÕÓ–uh¶ëÙS§9ËW÷b✞Ù[g÷®]ø={Ùïªe-£«;Ñ.sF¯à ¼°.ÕäïP|[Å ü›(ô’ã›_Bßõ¡ºÇÛ.Æûž-°_°‹}”ÍN1 „ýÈPº¿ÙÝn)…ñw@âÀñÎÜyN=w3ÂX,‡O›ÄŽÇv’5³™™í‘}2#%hAÇoAû”¿8 q.æ +$êH«¦~IÝ‚ã¼ÞŠ(Ç%Xãåõ\ƒð^Á-}ê ÚÅìÜ8QW{š÷Ê넌ŒëliSþ²©Î2ÌkGÞÛSkúQ'îKÜwÞÀ'Ø‚wpC[rº‡à;ÇÆ<¿`ª9å¾Î7íýÞ™»g?¶Oõeÿ+­Éwð _Ì9pF:wùÿ  ÛgLg³0ñZÏÏ”—«ÏÚ®»À»þ{NvÝùݲGîôy;MÓ°‹u”ÛJÃ@†×;ßÁwôЦicÓ¦1Vm•*hEDôÊQ/E| _Æá˜,ÍÅGw‡9þ™m¡B؇=س$ôB;ÎÛ31€ÌùzúÚ³„´^´åb"NÅ…8æ>âU<‹KQ‹B ùµ³ïÏ÷kć¢3q&nÄZ,DE®äàãs|jú|ïâMÜ‘óˆôHã=#z2Jæ6*ò­Ä‹øŸâ{Œ;ߊ»ÍQ¢ámkbFIm¯É5šÄšKîO̺"ÇØÅZ.ûÖOéòÆ^ú›b·ºÖ·Í<ÃÇ¾ëœ sœ3SÌy"®Ð~ÍŒ§AAè{vœü¬ß9³Æ]û_è<%GÚû–jh÷ØÜÙ¿¶vĶοhýÒ½J÷ÖÓOèÚIÃâ6½OÿF»üºÞp×E×Ý×Ùäת÷êBnw°‹…ÔËJÃ@àé {IÓ41é%¶©­Š‚7ÜxA|E\ŠK}®\ù‚ ÿÿÀßCƒ‹Ð™3gΜfBHB´Nkdã›N–×éx +=J%Vu)u1©ãã2È¡†C89 8v—pǰ#( Ïšº+òöœ¸GÛÌù ¿!t:x¾Â)󿔑­·ß%L`ÎàŠµÅœ»0ƒ±Ôå×›¸Ç–Sɹž5öâžàÞঌ/X“±¾Øy'ÌÓÈùtÿ35×Ìx¦;x‡¸ežRj¶~Bç-ÿˆ†26f¾†ûdÞÎÑ—ž/`Ï)Åžp¼–˜ŠÿÕ#|Á'Ü3ÞbKÖ¶`¯¯ùœó ™Ôbñù>Äúã{ß©ø†Öi¹ô½Ò{ÕvWŒ_›;mwï¿;êçýxÛ·Âç³yOV¬[ZÿÖ'i,°‹}ÔKNAÆñölžÃ+2óPy(ÆhŒo  W.L\¹ó.ti<‚~ÿšŠºø…žžžªê!„v¡…m´œØÇí8m×ßA†ŽÓE}ž3ÇÛElçÒÈB–r •2’¹œÊï'RòÏeq»ÔÒ'N-cb<†°±)ò%[?}á±ý„Õkõ׌;Á‚çXó”vCm½äÌ¡BIì!ó[ÿH.ä^^äI®eŸñ¹cuZü{ä±yÙøŠwö~@ì%yžåSÞåVfäMë.Y·â—øE’c˜ÔÓ°sŒÉ]»yÙ·cÖä\.ÙÇø|Œ1˰¾Ö1®ß›¼Ê9«dœ)&äõgµb#~­V›wÅ÷7ò@Þ«°:Óv.üý°¾…õ{’'í:Y³tïÓ;Ðý#Gä﾿ë6Þßy_—í{æâø|Ö¿öó µÃ·g°‹…”½NÃP … LKBÚ¤IúKÛP +¨º $X`a`câ€ÄÌ̱t,\«ˆá“ro}}Ž}¯+"‰ˆ´Èit¯ öí°Ÿ”$.(AEt¹x##ràÐu ÁÔ.OÁõ ,Á ˜0>ߢe93æÐóЀ+ð¾Ev^Dv_Á;¾?±÷Nßu˜_󯺇ôÒÐsEª3æ:wg·‘3Wéú×gýS° Ÿ#p Và܃ z0¯e>-¿ÝKj³s…óP3︷}’ðFíÆÕ[»üÅ?ù­?CǘµN]=º7gfìÇ xwàœ÷°äï}ù}FÅšÖà™¬©Y†8õ3¡O«Å¿ÕÏ 7rw`uÛ{Õ>]RkÅ;›3^óÄù0ø:m_WõZßl2Ùœì %ξÍtÌg>ú²^¥!OÔ³ýÿ˜D5x"°‹”¹NAD¾‚Ï„Ýõ6öÚË-ˆ„#ABBBÀG@ÊP#UIMsˆàI»==]5=‡™UfV€Å–…#sóÒX0«`ÌÿÇrÎ)óä«8¿ +qit`›Z}PÌýï3ÿkkï´O ó&®NÚ'þužäqdßϋ֛Æwé÷¼°‡ë¬ï?ÇÝ í[ò:%ò[â]“V¼ÏºëÊSOÔƒø6xÏ=®¹ü!õ¥ûåùptÖ°‹…“MJA…+[Á ¸÷2ÞÁ;èd&“I&™š ñEñA\z·‚k÷ºõnÄ׿=¨ƒ.>fº»ºª^U—™ ͬ2°õY`;;¼¿tÖØ»`ÂuÁ³.ïäÜóûm´Ùô¹nÁ=8e¬~ˆ“¹uÎ ˜Û#øßf°^Á'ØÄþ سEí*úN”¤G´_9[Ùøüe_üAÉüj0'à SïŒ:ÓyÃüfdJ] óðyyä_È.ÝRÀ%¸çàˆÌ¿fN‡´¹âj!´ŸQ“t5Œ9$µó´Ý-úÕYÅ÷ <ƒköÿ <0§QЫ¸±Ocúžð_½ó}ò=Uýû×{RMÇNCß!Íà ÖÀ:þßYÓ*øÍmù·ÍEé4ªwÒ£|}žþíʼnó¬Y—¿ïïÉίeŸÛò -ñ£Ö_?wÛÀ°‹}Ô;N1à Qq*.ƒH6ûÞì&ˆW€@/!Z +W £@4P’6-œñ[û†$Å'ye{ìÛ+"•ˆ¤A‡6 Òï.uœ#6±t¼ö‡¾\Ú5 èQD·gtgÄÑq‘“@ ð/ð#“ã¬u¼Œ{Â5<Ã>à¾à^áJæréSÉuR¶5ÏÒŒÏLTl,Ú_Æüöà„FüÞa_e4ÌgvaK~Ï;e¾¥™W˜œ +³firìsüöáŽØ:®êu÷pŽTŒ­¹Üï.ánàŒ96œS›¼‚CxYZ†uXÁ÷›´w`Ìp^2‡Ö¢p´ŽZ ¯ç¢uô÷861s«aýrw¡Nç0ÁþWa íOiïamÆ&òÿ½øµ³VcÎVï§ÆÐ¹zWýÝÔ~½—‹Þ¼åÿ!þßáçÏ{ÓZë?oåv%°‹}”=NÃ@…q‚ˆSp9DìÄqÖÆ6Ä€B QDI4 Q-¢äHœ3ðV¼!“Q’âSÖ;³oþv#"¹ˆôA×°ïØ#ú®#¥Vêt¬=’žA÷U×Ú’:ê—:¢î¸Ÿà¼‚ nˆÏÅ> @ÎÀ-x÷`n¸5ý*ЂKp Æà€¶èÓЧ Aý¶y÷]ß|~9ÏVÔSpÌuäö’¾¹ÔìIËß’uص7æœæ©ÔR4«[{mêoÙ›ð îÀ9ýmœÀz¦à¼‘'0c½oÌï×qF?"[»`ëΤf>A–ï\æÐ^øÚKÓÏÜø«ŽöQ÷uŽªgç^š|†ôQßh»ïÈt°þ’¿ûÖ8ÿ^4µNXÿÄÌUcö̹L–ïjÅ=Lœî¦7Ÿ®Ø_÷ßáýÖ½iÛÓÿ·ò Ñý›­°‹•ÔÛJÃ@à}cmS“l’6m­'<µˆ¤´R +Þ*"x¡‚ˆàûø¯ü?–õâ»èff'»uÎ%ιmÐfDã­H<ߦ8^ûZß4Þ4ouÀîàža ;™8J)‹T0„CØcÌÚèq>Ä=‡{x‚ìs^kú¬+ÄÝúƒÄÔ–qï6œñ\c1n×(!'OÏ¢z**(Œí ë®M­–güóÖQ^åSþ’´&ľ淘Áã\¯¡_p/ð ¯p Çpöü”µØ›Gø‚˜»Õ7·½U_s“w{^õ+w«û’Fqt~«·}î÷&fiêÒ= ¿Ã›ÂÏñ7<£úX1Ÿ½óö{æ³—ìiØ“öªþ.sX[ʸZ¯›Þ¤þšÞªæÿû¦•Wuü¬ÿa² ~°‹”»JA†ç5®ÙÙ[Ö—xAƒŠ +!i´±±;ÁF¬¬,|ÅäÿÉá‹aÎý2»!„Qa˱í|äðú"½—ç}NžÓïJЂpnÀ8£|lâXŸ’:K’UôKÔ òœ€ã^€{ð¾À sw¤ç7äS™c±£ËÁ7øoà ´­éGqSŒÆÔ#2˜YÍÁ”q¢£¦¼§j­]Ejã#¿pÍÚg”5´×,zÎužÀ+Iý_qÞ·`Éû!اFžÎc3ËM{Uÿ¾O» {µu–ÅQ¿’wôÂzÿ–TKÖï° šÑxŸà™{ÑŽ;Öaß½yËy¤9§w¹à½b›³4~ö ©OoŸû&õÈ}«Òë^8þûoøãWÎ&¼°‹…”ANAEÛ³p î$ÎL"†… +ÆX°/ 11ñ®<{~Çÿc¥2/é™î®ú¿ººC§K.új}/CnþÒ¡ÿŠ«ï>)HI†`nÁ šk­~í÷ùŠD0KpÀ¼ƒ/° ®+ ¹øIÛ¬Á¬À è%ŸÁOg-ÐÆøŒ¿kr*Wh4öÝÑË’ù¬vë;2Lj(_eæk‡Í?æÙÌ8Žf¿¨{A߯à¼xd­ÖÔ;çÚT·žÇœÚêóÈ¿t6i˜š˃æ}Ã×iÈy¯Cý§~–®T›ÔOŸà;üõÕÊø±:*Æ”圄ÿ¾|¢4¯ûä{Þ¡üD£ÓßEÿäî²÷¨ûZ: +·Î¿!ú>O.›Ae°‹…”MNÃ0…Í8 +Wá·uì64ýÐ.+•B$X³ìºï¾ÇhŸÅ{b4JÄâS2öøeæÙNá"tsI®ÿ/ÿºƒ®ùžCãÒU|Cú$’¨Á-‚ÊäÚú5æ¿'½Š(V~¤þxspVà ¶h[}Qj\€Oð>À’¥—1µ·!œœ‚3¼À;˜±Ï†¨_ë‡%QsÀ÷Ä5 µÎÙ5ÞߢŸIe^v$ƒöF½%§aµkzùv`6`Mß‹ÿ0¥_Ïà^MÙWnéC{ÛUovžLÛüˆüÌ-ºCÓ§¯CçIçYuØÏ+ø/á÷|y}ù[j¯éAY7gÃÖ–Ýcí“Æíñw×ãï²ïQ÷5±Æ1Ÿ}—çÿ!ŠÏ GBƒü°‹u”;N1D›ƒp εÀ~XÏÎì + „bDJ€Dˆ8Ç æ”¡J*5žàÉãvÛ].ÛÇ1#' æÆiüå‹YBqŸ»+² Zo‘PÞ’xÝSóE®3Ox\:;0’th|G¶D}å ­_¿ÏHÍY“Ü7ðÎvoµëø x_hâ<‚s°!ÛuÚ¿êŽ÷DñÅ;Ó¨qõµ­«¸÷‹áuK£~g9éèH͹Øó!8Â÷7xWô¼g{ žÀ3x#×*¦ÝÏÁÏB¨¦tl ùRèóH cò²EË'iÒ“¾kïxæõ^\SƒŸ«ûê5²çòràšSwdÊ“ü–äaþ/ä7™ãê«Fõì’{»ˆÿolê­ÿòàhÉ/°‹”]JÃP…Çõ¸—SmšŸ›&R‹Š ¢ú"E|7ã†|è‰=c +>|;™¿{&“ˆ8ˆ¹˜¡2–qð‹„ì[ƒÎXY¾U¢!5ñºs(î˜=שnWŸ¸"kК¿ú+¤':W–«¶ü5óæ”SìØ/ðî­îäsIÛ}ÞÀ }ŠåÙ{ŸôîÌg ²¯ÍÞ³fkïuÖ}tÙý\ ¯ë=J¯ŽqÒ`´þÅøŽ89gxþŸ¼û`¹®Á3x¥Nš[±Þ}š…£>¤GŸPÿSîGðÀfFkgN'iåºêÛ÷yø,óñ¹uÿ˜¾Ñbšø»kÇfÝXý‰ü_È;˜wÖw¢å¶à–úù~y\þ7üÚ÷´-ÇV°‹u”]NÃ0„‰ó–&ı›(åïOˆKpîÁ˜ˆi´M>UÞ¬wwÆv#bWd›èÀ5@ÏØÆò7+kíï¹·[pv¬Ù¥¼žq§Ot$¯×â¹îZQÁÜ“g/d$…¹uyž÷H%;¢:ê÷^Á =ªÖS}Žàß÷¬Síû#xÏœiZè;¥ø\ç†óOÔàh¿|r]^·™®j:ÇÏû5‡3{ñ ~#..ñû>ÁÉô7Î~"G®…ûX¬¯ðó, úuèéìñøïñG¤Sù®Sȷ¹å÷hs´Tcˆóû©·$}máL¤Åï´|v?†•þæ}.Ý|·×êä\÷Z´8³ù¿côÞ¨§n”°‹}”_‹Â0Äó‰=«MúÏÞõŠÈq(øìÓà“øo³0?Úl¶;›IÒÂ:„ðÖ`¶F4jŒóÜŠòW…1×ÉßöÆd|êV=f#T@Ç¥¸Ö-é8y­1‚ÜwB<â=Ó o6~ÁŒx$Îg4>@o Xÿ9¿CnöÆÅ¸7ãhì^è¶@u?‘ïô  Ëýw_k0`OgÔh¥Ï$DªWã×óFÁÄø†ßs#û–¦ò5¶×ɼگü#½<’µŽ øWð^¬Ô= éz½ªC~©æÕƒ7ðÎ|Š‘æ@¯RÇýl-f +¿Öß s,Ì'Mé:®çãìßýôuÕÑ[þ™½Á+¿ªEqÙ¯Ÿ¥ûVs¯ÎM~åùoùíwEõ¹§éEjåËù*òéž=ÿØzk÷ÞVöô_üÙ|ûØ8mi°‹…”KjÃ@Dçĉ­ècYrdolY²Ê Âð‘ÜUAQÌàÅ[Lª»gZJ)mRJ[ð&tÁôA“ÖXåø™P3çï‚1‚zÛJíÆü~&¬K¿ç·R«¤çy=èíÔá½äYÞƒ¯àüß°íÄÿ‰˜`Áìªë}Ö׺¬5&è@®ó܃[ð#õ†Â\h)ªË·Ò>”3žƒKp’œ sZ÷§¦ã½ðîϽáÒïó ’S¢ö®î¥÷5gœ¹ïcxµëî5ö~“Ü—Æ+¥ýð9h÷·tÍÚι½½Üãè ô­=û¶|¦Zþ p½ÿøÔôÀȰ‹}”½nÃ0 „õƉíXrš_d,ÚŒdì”%Sž!ÕÊK‡ÊØ´È#iÊ)¥eú¥« o`#èÒßÙÎl²4geÆ€þÖ¹ÞèP¶ÆÔ>rÔ?…=4úÐÞç`}5# ¸‚O°kp_àžàÎ1Ϲ´ÖÁp]ÎM¿KÕß„Þ)ônà|Ä{žÏ¢«ùXýSäÖï>J¼Sµ`/½q6{™Ç\?ã?~¯—v‘+öN÷­D/Yâæç\·ñ¼èã¼'É©;V$Ÿö›Mßmžóý› ïOo­Üœ‰ß¿Ë´Ù×.ð½õe\ËïwÞï²ÿKTçÕûvÃJ°‹…”KÂ0 DscúKÒ–‚`Ãç +‚ÓpNÁ +WÌ k”¨‹'9Žcݤ!„&„Ѓ1‚ V;ÑhÃ/¶í×d¸î@/Ð_‹ë„¶ëqíϰŸ£±Àî+}0^Iõ%—ûbܳ±7ãi¼ñ2ˆOÈíµê|TGü.¬Ÿá_ít\aŸ +ùTÇàr'§sHn?ü z=ÓF?±àW½$»3±àççÈÚÂzkÜ ý3´O°¹f>î«ö$õé¯Ý÷®rÎÏ…ïGc·jé[Ñ·Ì5çÁè½Õ;[CëiÚ¿Ä×ù÷þîóѰ‹“YÂ0 DsbhK’.lb‘øà\‚»p +Áš‘¬QªòñTÅŽ=¶ã†ºB4c zAZЀµ@{7Ã0ãZ؈@u7‚ÖÃ3{*½\Œ«qp½è}ÍÏøŒ¹L ÃÎ{Å·3öÐñ½Oãm|Œ—ñÀÝèðzµ9Þç{èœèc££_ˆŸÓËîƒêÖÎEóhœ0¯ïëIt“³Õú'ô'Ña<óû}Ö³ïo&¼ÿ Úx.¾²WeÇnÆ6?+}'?ï¹ÿн².틳i]?Ÿ(öÚ®Íý;Äé¬5ÏÒ.ÿ£WXõó}u|kVCÿ°‹“IÂ0 E}b(m“BK Ø ±äœ€p,éäZ‰`ñÔÚñ;"R‹H«,• 5X€ +ÌÔ×À8ôk¯¥¼Ã×C™= ÊQ9+;%âÌÛ{ìôÊôÐ3„nÀ½uø¦œ奼•§rA¼ÖÀ8¥{"´ 7{ÞBÆŸgÑÕaóÅŒ½Ï›“Sÿ[e¯Œnž¶Ž¥!¸¼Áèrý[s®.ÆgýiVkÌ«3q¸÷´§žö#Hÿåv¯Ê]¹A^Ét¶w;ßÒ»b¯Þ?Èôn2ÝúµN—ÛµÒÛ©œŸ÷÷q~íò?ù3{›ßøn +¢ƒ°‹•“Í +Â0„óÄjMÚÚÖ*Eô xó<øŽnd–%KñðAB²³?“„ªB5X;¬ Ë•‚qÔ¯œóœ³¶ 5÷yÏÛ³}ž„^Ø “0"O,Ô_ÒÉ÷hL`@mµ"ï7¸Û`{8wá!\QGƒº›fúbIékŸ +ºΟõõ S3Ño€úµz-b‰íšW4~—tí;Œ¿-œkOè ¡'xÓÏ`¯úÊ=Œð.s^ÂGx OÄܰÎ^UNεzÿJ{­ý¶sÐ>ÇP~;ž¦wîýUëÉ¿zöO-À\½Þ_øåý™¼"°‹•”MNÃ0…Ý×m¡v’Ò„þ±‰K¶Ü ê¸W鎱ôžô:Éuñ)vfæy~d§”žÒ˜uÀ£ƒþ+aJ'ƒèœÆx6Ð9úE{ŸOµ£5¶Fͺô÷9«N–ø=PR÷ø¶Xˆú‰-3ui› _&tK÷Ÿ:5·Ô“…Fj¡mÔí0¯hm-ìôѾë¼êæ|Þ®3á\H­ùÕx3NØ×ÿã˸g¬Rß zUc¾ß”ö½?Æ'4?ŒwøòLö‡=Žî•Κuþ×íg´½fdɽzþN-AôÆDùÜœûa†Z?°‹“KN1D›;p­"'`&{>DR6KÎBÄ}†KÐŽª¤¦dG,žfÚýqWÛ6³ÎÌž@vBÇõÐNΈïPñwëÈ™@Â:ã´N/~Úê/ÿû@«N„½ŒAKF_Ð7U88/ÎsÈ)±sÈË~ÔfÿÜFݲÇR©C-}ÔUòW|3rïÍ+…9 ½PWª@ݵ˜ÑþÎ8ýãœâLö•s㺞Ó­GçÍyÅZéÿì|:?ηóå¼mœ÷ɹ˜=<:[gãöÕù@½La_j×÷ Ä÷ç :kqœŸ¾Y½Sz–¼'­·£wжú[ûéÝÓ³kÍ •w‹û? Ű‹}“KnÂ@D›MnÅ8Klüƒ€ R”HQ®’ dË8 +j¤j©(ÙYÀø¯vÆ]OÿYOöUús|ŽÓÝлБdzO†¸æ©¿u¿SžCÞU[Ëw̵þwf×ÞìŸ7~@|eò°‹…“MNÃ@ …çÆ !é$mÚ@E”,X T$Ô3ô,`ÍYú,=«¯VŸ”ÉŒÿží”R‘Î̈Ÿ¯H´Ïzo<¯5z"{1УêÖ¾ö\W:WÈßúª¿`úR¹Xëg®?~=`®—SoÃŽ=önM½u­gdò}¿;úýOž)}ÊÜ›}bž/ŸŸ¯¢ø°‹“AO1…‡Äÿäß‚Ý¥Ý +ŠÐxðDÃ̓ ÿŸoÉ›8™´„×l·Ó™7oZ©Dd@úŽ£’ÿøЂF¤û’ð6àŽ`VŒÕ‘ÿÁÂ\Û/ƒËç°‹…”AJAE+â2—ñÆq&3Ý“IbE¢ Á… 7îWÀ#$ÈAü ÿCQÉàâÑSEwuÕ¯ê1³ÚÌ.¤"òWùKŒhAr,Àø2›œ‚sp{Ag‡÷7níHKš€òËOhýÚ/[÷Έâ(¿ VdN;ó;Ú7à¼s-vO´¯ :*Žüª³£IÒo·®ž†¶òy°f¯Ê÷7Ø‚_ðÊÚb¢.B÷DÔ_ç7»ïcçb<ãÈÖüeç/zÜ‚{®ƒ;'æÔâ s:5;)ìtšxVq㬩Sf^ªipýé)èègÆ÷Û÷MsççÜ¿…±™öo´¶Ã7÷iF4“) ÚÌUµŒÅõ=OÔ©üÀ5}Çò¨y×xŸàãƒ^#°‹uÓ;N1à )8' à<ìÝìnx(!‚(¨"E¢¤Á) @¢§¤¤à”üÖþ#™»ø¤ø1c{vbföß>ÕæUZ;‚-̨‡sx6›lÃì`ü ·Ü›Š@‘á±~?wšßÇAòhœžëãÅ6|G›­ûûóõ¬Ç̳¸ºl.ý>¡NÎ ÌïqzžŽóûÎx‡ <Â=ÜÀÖð?ðÜë¹¢¨½?¯o(Ôß÷yœÖ·Vïí‡R¼ŸuL½Ô§cÓÚ…ýºk¶õj6E-¦ˆŸ|cþ®¹Ïc–œ»‚SÎ{Þž:òsó¾Ì—ò,²ïÝÊ;k}]«Q­çUé?—î8'ýö¥Þ×¾È÷ù9‘õº´±Ïîlì»ÁþöŒkxþ +žà^~M÷åа‹…“;KQ…'ÿ–¿ÇGv7k‰ø*TÄJÁÂ&M E*±MÒˆ…•ÿÃÆ3pã^->–;;¯{f®™íÛoöHÉžñ‡¤5‚cð6f½m|¿À ¸ ý{Š ŠU9^äü:{Ž#0b®§ººÎƒD•¿þ7¬áZLÁ˜µÒé!Û˜´…ºŠ“uB~Ñæ~à ,Á Ü‚p^Á'xÏà,ä.ÝS÷]úª~Ö_~ŠËúþ§w¤þÃ?îdÔ9kÕr>pæØÕ]³­{³>4êïàüû;¸¡V“àï¶+ÚGsÐ=£Ž±7ÏsJ­§ö³ y–¥ýìÒ¨´ó™®7ç}j÷òì³îqî]ýÄYû=ýÝCW{¤nz{¹¯šõ¯Á¬ÁêO °‹…“ANÃ@ E wàT,¹…LÒ!)E,(ˆM Ä +„ʉcq +þ¨ÿ c&°xjÇã|Û?Ž™MlœƒÀ!ËÓYy tà¬À¼‚%@C¢¾(w-5zpBf ó®qÄ祻OÔŸtKgÔÌõ/ÚP3‘)ѽâÊëØs©uîêM)ÔŒºQ_¾ $3æ=i©qD4óx`ŽÙÛ=xÏà†½Æ>bñ¬Üdõ9b\ÏÇù}¼ ºé_j>Õ7=ßÏœO>Ͷ^̶÷Àþï"önÁ•mvZž•ó%½êí÷¾¨N¶Ÿ{«þjÍù;ð]e«ïßÍšç~÷â·Õüƒtµ/cº~®±ÐÌ3zS<»×¶Ù¿…Ó÷ý6ö½³%缃õ¢ô»°‹…“]nÂ0„͸g)ÎIÊo‘P jßxâ2=EoÓ±:#-«X<|JlïŽw'›Â"”yu,I)N륡 èÁlÀÔ ¯/"ãóÎä@=«'ò¥ûBTŸts[0ò¯£Ú©Ýi‰Îµ¯8õ¿Gö²2y¢rÔtÞPg ‰{Ö“šÚûÕóµì¹VLöãijžš¾¿†h߯[¹}›Ÿx_gòK$öÙ9ŸJ¾LùÔüm©ÝsïwðÂlfxÿ7ð>Âÿ ô1Ï‘:¶n[[˘q¢y¯o3𙜎Oï­õÜΞÿ·â¤ýL×ö55š±wp߯·=Œ¾­7†Ç™ÍóxŸ2ŽÅ7°‹“ÍNA„‡qw`p +AcŒ‰ÀwàH8úB^­UÚT؇/³óW]Ý=›R¦?Fä\pŒŒ:¸">È`Lj®KWñ=N{onÁìÁ|€5˜R·"1f͵.ŸÒžx·¦×Èq²ùQç܃ ¸7\+V¯Û9ä_ºs0c>Ùröõ¿²ÿ}LöWgô‘û“óåžÜWË„x<××¶/wà |ƒ/ðîÙ×I&¯k/ÍK©ž¥¸žWÝ>/~oÔ1&q®´o—¶ŸÝý¬À xàZîŠoâP?tŸ×_5åÞ„ïuýsj¸¥¾©èðzLéCc 3¥gnÀ3ÞiÏìoõxkÖ=Ã÷+ÖN[ƒ%uäê§z=÷®ç?ÍMÂ"°‹•“KnA D Cäp îÁ@æLB¾BbØ#Ä5Øpr‰ì³Kª“²ä”f4ÉâIc»ÛŸj™MÍlFæÄí)¹ÈIFfŒ¹ßi"c=õÇ{K°of½˜àûÁ]¨‡û©×<“ZòÎ;ð<žWãÉW‚©:ò·é› ªWAR¸§ÚS›î±ß¨Ï_thêKõñþJ¢vì3g¬"i–=8ƒ+¸€Ø2V…::gÛ^uÓ÷tÛûªY{b¥ýž'·æùb>Ý´§ûÙã}˜QõÒ9Tï¦wò:5YI¯ñ­*™õ¼‚ÇÓóîw;å_“¨““öóœð¯Á»Ùà<™õÇðPƒõ?gþÞÅ/Á@³°‹“1n1E‡{å"œØ5°à (ER$5 GHACÑs™ùþ(£ÑR<íz<ÿù¶Íl`f#R쾉 ‰Çu]œ÷œº0®XoLFBÍø +ìÀœÀ'xMДBÝvM’eÿª¯3!I˜pïG2ýZï–¿CAýq_æô` –AS—ï>¯þÜãCÔåë¼ÎXpŸt5&žÃ"|_Á|ñLߟÞð³t?"]yzޱŸ)÷^Òoï¡ ÿêg쯒X’mÍ'»Ü—zŒ~izKçäõ3qí¥7Ñî9 ¹™zÎ×…ü¨³Íß‚²±ë7è>¾ƒo³Þ8ƒÐGì^‚Î{{þ»‹¿ƒ ̬°‹“]N1 „sãÂ6ûËn[¨Ô‡‚„hOQ‰ÓðÚcà 1š¦ßC6Ž={SJ«”Ò#hÀXžýÞa}Wâ×ÀãÊ·6è‚\ÉÇzå~` ’7#†yJÎqŒ­é¦?g¼YÀˆœ¬×Kþ]0áöµý„ßÝ'ÎÀãäPg<£O½'ÌéõÕ§,gý^«­{Qj>Á þÐóVæ8È{¥g;ÌïÞmƒ×à#8"wŸn÷Ì}e=ïÃu;µ¾I‡¾fÌÖQ]÷æšïuë½öqo]·BÏ©“Þ»6Î`ï[ÄóŸñsÍföœ‚sð–þþ ï¹ìégp ¾ƒkð…7³hüï®þzñ²ÔÍí°‹“ÉÂ0 DóÇ-mÓ¥€!N,ß‹ƒf¤‘•OmÇ“qœBBX +” åŸ0î«dÞÇÕF4§[Ê^’bZÀøôƈo‹œã~!ÿܹZä;€ù¨—þ;Äl ¡>}= ÷û:3ñ¬A ÉØb¬5¡O榎×m@íh2Úê§þ͸'xç}h½G¹ =Oª×Þ8GĤ¹µ±Ã˜5ö}¨ýR‹ž÷áÏíÉù&ôÒ㾕z¹åêKØ'äˆn]},½õ­ûxvjèû¨\Ž´žúgC&ž}嵨ƒWãe¼q—|Ú[óIãb<Œ'âù^|/þêÕ¯«g‡°‹“KÂ0 D}b(MÓôƒ„Xpö¬¹$.š‘¬QJY<)MS{<™šÙÁÌ*p*á¸Ã¿çH ’ô‹õj9—ÂóúMvçæÌNï4ò¢sFj̨¹rvZÔdPÒUBçPß“ û –u=AãfW=Ú·Ä/?çἜ·ó„?Ñ“ç&h¹ÀÖÈðqïÕI ̃ú±•×­}Ö§Þpêhθ•'ÍC#={Å9y^ÿƒèGõ˜ƒ’‡ª5f¯ÁŒ¸§ÎþÏ"½`ÞîX«wÑ‹½®`,xËÿg/«_]r¦m–°‹“;Â0 „ó‹¡m}P lìÌüAt–¬S¢2|jÓÄç‹í:çVι´DC¬ø÷œÒOù¬^ÞÀ× Gá"„{ÖwGèý¼É­ëQ8 wá)Ü„=tá Ög¬ïÒyÖãxýžs'a+\…žs¥Nœ·DÍsÞÛ@ÿ-|„jO{4ÂÓ1‘tˆìScuj}ãy­}Wý„žžÁl|ÅBŸ¹ŽŒž+Å'ÔeDžÉÔÍöS×mAßC7Ç F/`Ïvö‚Ñè©K3¢º=roð(ÎÞE=O¸»ý‡x–fõw/š…¾ˆ°‹…”A +Â0Esb­mÒZµ* +¢K7Šà!<„ÇqéÂ_ùã´‹GIf2ùó3Ô97tÎ ÈлŸÊ$ÞW_ò3C<(Iaê·±1X‚ X€Jåé:¹:'ë‚HN và Þà^àjðõô~¬?‰{"÷[=HßAÅ +åÉ +œÀ éCÑ—êÛêÖ~ˆî‚ž®ÁÜÁÌ•R?0wÂwñ‘;º|“Þ½‹ûlçÃö—zo}_ëO;'{ðW°5zSúRþÙµœ—ý’žÌHHœ—w—¹–üš¾¶ß†ú§Ü+ ÁýÏ‹ö&6{Z»WSK÷¯óú<’Y­XËÆc:coûû‡|Kº·O°‹…”KNA„.ä<„@Ï ðÆq¡K\zWÞ­ð$V“ꤨô ‹/0Wÿ˜GÄ ™ âö1ÝÒ(ç—üýÂH =iÌ¢ý<€[0ˆNý$»—¨k$ÎøŒ˜]_ð®aû/ŒÕNøS{­¾$±Z‹¯ù ¬å‘äÿœ—žäšßÀ;xås-¿©º•Žèý†¶5ûs`N+‰µ4méS[‰¡z×èý¾¢÷ýhŒ±8¾/;ð¾Á{¸á¹î»Ïk¬þ¬ý(óZ1ÆFfé÷Kÿ³fŽ$÷üžä<ƒ-gÒ]œïŠö®¶{þ?Yó·äªïÓîw¬æZžµoÉéò™ÇRô°‹}”MA …C9¯¡iÓ”VÊÒÒÎÊ,]Á¤ÕKI½‹¯fD:/D¤‘/bHôACpžau¸~¤ÕÎO`¢<+cĹN¢¸}®µ§ÊQyˆt®"Ý»òÔ÷—ÒÓø þ|4§¨O»Ç¿>2zÙ(°…v¦ó5¶TvÊJi†Ïcý1ð¹ÙÍ/ÊkA‘OF÷šÙédÔgy^¾¿š7Ñýý¹ª±†Ÿê³\0ãòÿäê×'Ï…u¼¯>ßæÇû™\nßgåêû}×ïên,ЛÍÐÏÌÏý±x¾¼÷žãi~F;Ïÿ¦gñîò.p¿üúÔ}-1l°‹…“ÝmÂ@„‚㟂…"à…DŠÒ(M¤„¼Ò%¤ÆhFYîðÃ'ûÖû;{N)ÍÓ?ÆÂ}nèû“áþ¥³Û•ÏÏî_£Îô_›]ç¬À'8§4;¦Tý€ Þÿ@ûx¶ø)¼Oér¯¬Á¼“7Ön-~œ³cLŸÑ¿6d—FÑ·e®nÂ/âs—¾—â[¢:š_}h®—âGŸW°!Ë QNgյ܂pkùþš`\¼c¥:q¯Ñ?ΛÛÃ{ð ~ɉ¶ý¬¨“çôûŸ›}I\_¿{yáSû,Ýyñ@TSyzæ÷»XÒÐÿ¡[Þ+Kœ›¶°‹…“Ë 1 DM?4D|—]¾â'@ˆp¡ ÄÑ0AÉŒ6ËáÙ3'1³®™õ…“[ç‚T`ì=½@Wˆ}‰‘Ãu]®QCÕºÏú”w.ànÖjƒ'xƒö^à +¯ÏùsŸçUÍs$í)Ø€#8ƒ؃…ÏUsçæ–Cû‹@éw6z)ÏÌ}FÅ}jQ‡wØä[‡æÐüܯ<ÛÖ™x¿öÕédz•¢O +Ÿ}Ò^gôsÿ†¾üœ_œaô!É#½µxØ÷=Úì<3ÿýuVúƹfÝÄ)ÝOëb}ü˜[ÏÚô’ÇÌg·öYjVž;w×?ç1´&V°‹ÓM +Â0àœ¸Ú¦ik +*Š‚ âB<€WpãÂ…WqïÖ™qȈ‹lèdæ%Õ9—9çºJN¬gK ô ¦šŽ)\WOø95—ÿcžÜàU=÷‰³Ž`'¸Â^ð€´”¯øÑŸ×9¯îoå-iÿØÿw¸Á¦¢·ž›÷ÓçfÑõ¥PÑ9Dîp {ØÂDäOÕKðŒ¿ú¦xEÏÏë<ç4ªžë*:Ö~ó|œ•ûêûâï9î=0öOÝ?gl©®O½¬œr-öÃŽp€9íÜ÷7\ˆ,úÌRg(%î’ÿ‹ú}YS‹šTÖ™ek˜%rXg¡s|ú¾Ob°‹“ÍJA„;_Í·‰ÙÝI\MüÔ@ð˜cò +y¾•5P M9#>Ó®êšY3»°ß,ˆžÏÉ¢A#Xò·—ºÎ넞t Úïu÷Õò¯¾Uox¯à |€wžMìQÝVn:_I¤ÌÌà<ƒo³Ù98€'p†³=¸ažIhéÔî%I¾]8ýVúv_àvàŠý>׳ӽ¢^ôÑò;¸“¾‡Té÷üJ>kú^¿pÏÞeÈßukù¸–çâs³ì­y–úDOEó–w<Šî sÔï¸ã¬Ü¸÷,5Ý%Ùß»ê7TÛeöÿïÛö Ê÷³Ÿà…»åÊÿÜ_ÌZßZÿZ¹‹°‹}“kNA„8 'àVÊûà¡Á9ƒ‰^BOàOoÀ]¨Ñê¤)gøñe=ÛêZ3»·ÿ̉¾¿#ó + X´ ÝÈ׉4•>ô¼Ç½¯ZÿÚ·ÖKìuÁXƒÂZ·¦›kГ6äH!Þ2žk¾›¦fã™Ùã/<àæìÙGG‚æ×½ø¹¨¯î*’g?Op?à ìxÞó&+Ïë©?TwÏÑò›šâœ×ï‰×¨SŽ-ÁÀ3Ï ’¯¦O’xιbξ¢çÀzGðš;~×Yy_ªÅ’;XÛµJ{w•´W¯•fÕH½á5¼÷Úµ^Ïþ³w_íÏO¾+Íîý a‡Ñk¿ñ \Û'â°‹…“;Â0D¥¢‚@HÂ/|tÑqJJÀ%¸ 4+ÌÈÅ“âÍzv=k›Yf_$K0"c2<>%¨ÈDòUOשx.hž?$Ï‚þBR}kÿŠê{¼Ù³k2§®Ö*˜»w³V߬}5ëAß]Ä_`¦Ô(¹¯Öÿ|v¿ôÜê§ëÎÀÜÀ<À¬X®Õ7­ëµó ïXžŸ7ÔoöÕô°fïž7%K°aÎ:ÐP}×uô%g¹`Øÿ¦ÖœÁ‰>®ØG!õÔT}w¸žÛïÝsb³HÍDïtlF¹Åßzì¸ÿ5=÷ùTìMߺîÓ·ò™å·ä!*°‹}“1Â@  =áq„KH ‚”ˆ +QÐAü ƒv…YqSعøÖÞ³™öaŠ %¨@)0ŸœÆé@’óZOã\~!¨žŸÍA_¤²oí5X=“»—ù×?kg z§•:)ܱq®f£©ÙxâÜ›ÇÏ?œþoõ1Vª‹óÒ¾už¤†þƒsvŽÎà¬pŸÖk2yõ‰P?ßGÎòE´_Öç›à¼YKu‘Næ¤}'¹WûHð!Ö‰ßx½wN˜ß€}cq_rscL[ã¾´B©©žèävíß®ÿzSœÿ2ø½ÖzúŸîÊ»¯'Õ b°‹…“i +Â@ …SÏäµ´ítZÛºà +‚Wð@Ë^ <2úãcÈLöID¤‘ÔhˆÒ{R²²‰ôMÏⲿ-Ø€z$‰ó0;öÏú tN§%}{÷$²l-ÏQ9('e†œÉo&å¥|DªµòPô®ZéÝ[ÙCÏìrÎ#ª×Û›Ìý²Ü–¸GÔ1yGDþYàó¦\ û~fÜ8¹oQ}¾~ÿ_ޯɥù+Ùsƒ÷¡Ã_^•'ÎÙÕ`;Vš›hîzôavØ¿,³uWÎ'° zž«s=Åå^—rõ;턽Û|Dûû«÷~û/€O½¯°‹…“YÂ0 D}ah›na“ˆEàƒp >¸SjKÖ(§¨‰íØ“©ˆ”"R)ÅJâ×yµ(Þbì^®7U&J¡q$݇åÙ>ßï{³þªþ| Uå§r-¿s°Ô5ºÞkb¨½gðoð°½ÆX¼×ÁÃ}¤æõùöÍïQQoozôD›©ß)þ{ `§úøþ‰º²n<_Iù¹¹Ø¿¼ŸÓ/åöTéîŽôæÖ¿ýc¿|ãç4]#¸€½Œ~4;›Œ¹ƒ+ØÊè£Yâ Ø+öŽQa±Ö¬-×Ëy0彜v©ú¶÷=ÿ±öÝò°‹…ÔË Â0 à° öM[TÄK 8sX˜`þ[˜_±zøQÄŽ­†Šð““Lè÷R¤Ö™¡û R’JŒÝŸK|#ÊDlê¾ÚHåmq¬ÍOï­è|ýÎññŒvp„ Ìa&ß:Sï1+Ø‹%ô&¶¦{Ru¤ê¬HCxŸ×oÝëè¤ÆXÛAò$G§±©·…lÅœÞ_q~¼s<\?ϙׇÚÔ^'âÆæ§‘7ZÃð„;œá7x…0™~…7\¥ƒì·=N½m+oõ²æ8of¼Ü½™ózêõP×ÿ õˆ°‹…Ô; +Â@àÑ«xß‚‚XX ‚•… +6v6À+–^Eý30ù³kŠÜdö1³cD$‘TõH"Õ÷™ +Çæ§$#}Õ´â3Šãs™Ü ÛãX¿Ÿç×÷çññØÀ .°… tý¡*4Þö-ß‹1¹ÔëÂyrE`ÝüÏ}q¾¹æ¸‚=œákÍÁâ”Sáö/s›*« ‹Õ·©Ÿø¹OBwÂùs_Çöó9ûzÄêÉç*k3‡R;]gù–¸…ß,ÀœÁ ¬Ùnã猭­~§¼;ç5ôÈöÅö×~Ûwؼ¬ž§/hTõ35ô¹#®mJ¿}Éu‘ûÅ)8•jàNT®c]ÂöOìD•QµšØ·`›ãì +æ;W9z³š³ª¡ž©1ÏÆ¬èû?ȼ‹§ãÍøçß{ƒ“'R°‹…Ô±NAà_ƒ˜ø&¼…¥/#Üq‰!ØXIBK 6¡ò!´ãl-l¥à?™I&“-¾âvvgwvÜh™Ñq2§+2—ÃÏ·óR룸æ‰òÖzF.ºÁþÑ>šÇÏóûé94ž'ôiBKÚÑ­è^b^žÈWˆÜk¾Ž^ÀŸMó–T‰;z¤9dž¯[¿í94£ÚКždÜï_ +û6Ä<=O)çü¯_ü}øo_GªOþÝk%ï9•¹ÛBî`(ãZ‹]ß—9úÚº¾›Ò8kÐ+¨û¢à¼\\—W@óhÜ0þÉØ;-Ì=Ú>³¢»‹z'ŠÛõ…ìûŒSßïé§þxšµÆ(OôŸñûÛ;<ƒæ°‹”1NBA†"x+oÀ¸¢Oß#š¨$j¡@Á)lL¨I­· ¢£¢óßøO²NÞ²_2»;;óÏÌfô\Š+G/CÊ?·¶|©8)£ëîâF‰üׯý~N¿ùÇù·âŽŒÉ\»Šüí¾Ý‹c•ò­dÇñÍÇò_?ñ†äIšÉ3y'³Hg꾯s¨¯âþŸz}¿ å‘Å-Ô—š·'7ïTÜc}í«gõìMu÷¥¹n~ñ{)åˆ2:³ósJV@ãŒtH“ë ÙÑÞÍ/àôh€“%÷<[“ü¾Áª¦÷¹šsû~¦†éoë“ì©§M.h“HS.›‘ÿ‹þÌð²Ãݰ \ No newline at end of file diff --git a/astropy/io/fits/tiled_compression/tests/data/m13_hcomp.fits b/astropy/io/fits/tiled_compression/tests/data/m13_hcomp.fits new file mode 100644 index 00000000000..fd9184595e0 --- /dev/null +++ b/astropy/io/fits/tiled_compression/tests/data/m13_hcomp.fits @@ -0,0 +1,191 @@ +SIMPLE = 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 is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H CHECKSUM= '0dE53Z940dC40Z94' / HDU checksum updated 2006-11-15T17:28:38 DATASUM = ' 0' / data unit checksum updated 2006-11-15T17:28:38 END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 8 / width of table in bytes NAXIS2 = 1 / number of rows in table PCOUNT = 58149 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 1 / number of fields in each row TTYPE1 = 'COMPRESSED_DATA' / label for field 1 TFORM1 = '1PB(58149)' / data format of field: variable length array ZIMAGE = T / extension contains compressed image ZTILE1 = 300 / size of tiles to be compressed ZTILE2 = 300 / size of tiles to be compressed ZCMPTYPE= 'HCOMPRESS_1' / compression algorithm ZNAME1 = 'SCALE ' / HCOMPRESS scale factor ZVAL1 = 0 / HCOMPRESS scale factor ZNAME2 = 'SMOOTH ' / HCOMPRESS smooth option ZVAL2 = 0 / HCOMPRESS smooth option EXTNAME = 'COMPRESSED_IMAGE' ZSIMPLE = T / file does conform to FITS standard ZBITPIX = 16 / number of bits per data pixel ZNAXIS = 2 / number of data axes ZNAXIS1 = 300 / length of data axis 1 ZNAXIS2 = 300 / length of data axis 2 ZEXTEND = 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 COMMENT COMMENT This file was produced by the SkyView survey analysis system from COMMENT available astronomical surveys. The data are formatted COMMENT as a simple two-dimensional FITS image with the same units as COMMENT the orginal survey. CTYPE1 = 'RA---TAN' / X-axis type CTYPE2 = 'DEC--TAN' / Y-axis type CRVAL1 = 250.4226 / Reference pixel value CRVAL2 = 36.4602 / Reference pixel value CRPIX1 = 150.500 / Reference pixel CRPIX2 = 150.500 / Reference pixel CDELT1 = -0.00027770002 / Degrees/pixel CDELT2 = 0.00027770002 / Degrees/pixel CROTA1 = 0.00000 / Rotation in degrees. EQUINOX = 2000.00 /Equinox of coordinates ZHECKSUM= '2f4R3c4O2c4O2c4O' / HDU checksum updated 2006-11-15T17:18:55 ZDATASUM= '1803906202' / data unit checksum updated 2006-11-15T17:18:55 CHECKSUM= 'cGfHcDZHcDdHcDZH' / HDU checksum updated 2006-11-15T17:28:38 DATASUM = '844555891' / data unit checksum updated 2006-11-15T17:28:38 END ã%Ý™,, öÛtÚ×ÛüòÏ7sóÄlT1\B–Æüi‚ šIؤhVKE¢Á&›P‘6¶‹  Àm¦éIÁ3e°Ñ%·Lž?û¬mÆVbv|å,ÎÖcE¹‰–z1+-/1¬Ë¢M@BÙA$.UZÏ$Ë€Á '„·ÿ; O9£ÓXÈ)Se´Ò$,‚A6~d²šÑ%"¥9I4]"‹p»Jr`4Zàh¾å‘!´Xh­Ô“)€6C{[@ÉK,4H†(ž Áji  0¹¤‹@ÈMÄÀ·eÓ„kÿuŽë2³?ç ÆcZÿ՛̭ÖcI–¸ú—ë3(2¿ò»5‘™¯{Yÿþ5ŸçùœU™˜…,B%娮nRIn\A%*šQOžÐ:Í¥Ä]wÞî°‘(…„ThÈiÕfób¬ôú‰÷Aû3`ßùÜÆÑ 3]J‹´ 3i~ì¦šà ²Z¡Â -´ ‚ÊÕ›öì×Ò0[< qA2ˆv@Mq¤à$wš¬ÉGijއ'E Ði’QgÝ!ÁCÚ6ªF÷?;—Úï &v†7¤Z'#ü(2ÔÂjMI Z¤jS[,™l£cÑ[X5"Ke4Á’†`€Ó ‘’Âl$X éJ7)„8Ò!¤)©!ñ¦Òl¶Cd Q ™h4Ë(: Üüã0ˆ!뀟Ó|I²i6e q÷ WÖ‘‘A¢Z"jÐl=qÎ*Hç¦ÛI”bº¿Ö7u™Y‡ùšÎæwz̬ÌÏó3IÓ|ôj¯2c0æn\¨£ Œ¬Õù_³¹¼ÌÌßùþefEffL÷™CL‚š1oLF—(Þ'0LK?÷yú”køaÑ0C ~žÐòí9·Ïó+üÉ\ZiV`ÿ&RþçÎBƒ­iGç6¥Â)óp%® ¾MfÿÀ}Yš©öa ‘þ`ÿ31~«“?ï3H†Wɔɫ˜Ý4Î;NåÖô¼‘ 2Ñ ²& ê@ÛÑÛý*MìÉ A!´™@‰”ÃÒ&Àö‚,yCm£ÊþyøåG³W¨1ÎTgv áÚïûat^»Hò?Ài´AdÀ "ÛUӸΓ-cž½Ÿu# !ÿcñÜÁZ ½ú\­h ׫3þÂïtsÍ5ÃÍî&ý“žmFÓ^éÈçþD‹ùy€´ä¶æï+2 ÓL²Ý°@.M”eLšhT¢?*Ûb«f”Y]!È!ÔK ðѦ“š,É,”¬ÙtºN‚Lš4i̪a"í©+0ÚHU&!ÜÀ†­‚ïn ¾Ñ*›à@9KCò zÇS˜Ô©à ÌM€ƒ!„êZQE!Eå†eŠ ŠVHl‘ ’ÆÚPx‘MT¶0ÐR¿MqÒl¢E€¸ 2!¨ í==ÙvLêtõX!"È×êeÓM$í‚* $_ ´‹aŠè€Y¶Ù.k‰+ˆ Ó¦:OIJ~âƒj¢ÓE´¶9 ä€\”‹‡£?¶t]°Qäé»1+‰ö’QÉÒN9çîÈToÇHÞŒæý¿ÇuŽî³+0¬÷õ™™ìÿ=þfgù™´—õýû=íÿW™³™'3$¨£¬fj÷ž¿ffffcÌÍæfgùƒ33²'üÌÀ¦‡•1riš=üís¿ù Na·½wß­ßûû aC—ÄÕWeÊÂØ¤ºmŽ8¾sþå/Xbló3½¼Ï#Û–´k2Os%^dõKæòZÌ,çù—ê:;îoÞç=›íkÿ{¹™—ÌʬÌÈÌñÐÿ0™˜· ª÷þ˜›V”†J¤ªº%aÉñƒ¬ˆ«þ»_›®µ#Þê‘¥ž(V=ÁGùYÜiá@ñ·¯1#€AKñ<é7Í Ílð¢_Z¥J LÙ°‘,¾»«šñOE°óÔÕ>{I†žšØÏuˆ]Ã8„ ÷}×ãþæwÒD+2ÿ©Îw»íVlÀœGˆ,Úöš rHL_³€VÚ!É ‹ÝÿËþÀ(:ï¿­´ùtä^ß;ž¯ÿÜÙs±|+“¶·]À{ìØEffîL ‚6hîö³?FŽoüÈhÀk|ÿO°w3<Úïqw{ßõsæˆ,N¿Þw;ÜJ’(W¼ÎæÀ Ó² 3FA†í¢(Y¢2ÛH"h–©8,†) +t•Ùh ›"ƒþ†ÔùQFd†&xœ´´4—ðEZ­À˜üHj•À®¦ ”ÐI¢H›6ªaˆm‚e#`õ(’Á #ýŠº&ÊN‚`[áR”z•¢a¤‘©!§LØ  ¹ëRtßhR°R ­tp*f”dCNª*˜·SØ Žr„è÷\eó¼jÐ\<öÿ×*“dõØüÝáˆHÙ´ÿëËñÝc»¬ÊÌÏÿÌÿ3333?ÌÌÌÌÆÛJÑÿ5ùÿÙžÌßs3g¹›¬ÌÙ˜ÅZÌÝuffffffff<ÌÌÌ̬ÌÌÌÌ7™™™™Cù.›($ANt=?Çù^÷ªÐÓŸÊ}ÿýÙÎw= ½ÌÍ䱟÷Ýýkÿfg¤y„ý™éãÙYŸ×;Û‚@½Ç!¾J¹*T{ü:„ã¿oÜÿ3õÿü¡ëy™ÌÍäwyïj«3Õ™™ÊÌödÖ{·Ýæñœÿ39£ßó¿æg‰ÈÌÞ™y™˜ns3ð+33üÌÃÙͬÌîffkÚh=öo331¤“d[4¢ †%¦Ðlá5D¹‚t(îP-Ö5~ž5i1¸:Fçüì°éþ™ ö»êþkŒÓSØIÔœ×sq0NÎö^‘©îgø¨‰Ž*˜:¨îry¤¿º’/óœìÄÿ þ^—=ã‹M„.‚†ÛGã ìñR"È ZD +fì9ÓP‘Þ¡”¡u¾š²°?DÚ¿\†µ’ìUö{ÄŸçÖûy3ÂçÿóØ^”"æ=ÌÌÌ“Ÿÿ¾äˆ 0+IÍo=&ºó7·LöÝ÷­½ÿ¬ñK³Þï\IÚÿ[ñíáöø*\í¦Ÿkå΂I´ÎšWÆÕ{=þ¿0rwdUqw××[^îg¢ýA>Uæ{“ì•]ŽïÙ®ø^\¸9™îægžÌå‚o}ß¹¿ôóo»^¢ÚÿÌÿðûQ˜å Çg‰Æw38ÿ¿¾æ2 %fùþn;™™þfcÓÐ+»¡ýæeefaË&9u0ûþwÙ™øëKMø”]™‹ÈÎ÷y¨(ÝE¤Â%4((µ6!„'õjSW°Žÿð–‚6z 7m5ü‘ndÉ™µÚCø ÈÅh(.ÿ¸Jÿóßýݤm˜ ¸Ÿî³»ã®eûFlYÒp5Ù\¿ç˶î‘T;¡VW/˜j!ˆI“> ^º$Ïà*C•p¥2îkš}ŽëÝfVf™™™™™™™™™™™»wvþÿ?ÌÌ>ÌÌÌÍ×s2³3+Ù™Ýæew3331æfffeffffeffffeffffcä¥ãåVÙ<·çú~ÐôçùYküîdæ%Ýg³Ë‡w™™q¾÷0zOs331ffdëüÌÍà߳ГÌÌÞ6!geÖk¹™l:Ù\J÷Ë b2·<÷þÖ_ùáóŽVf{üÌ¿÷ü^e¼ÌÎæf=ßù™™¾æfffs?ÌÌÉ;ÌÞo3/¹™™™þfo3Ù†³37±þffffUï33›¬ÌÌÌÌ0;ì̓þfffaÞkÞÎff™˜šM¤i$ˆˆ¡`a¦E²öÒT-þS£R{eAb à/F •B#sszÍÓÏ6Úžò³yè–©3gÞ™.?³Ë­æ›s!ÿ¿^ç¦Iõæû™™ìñý<Îw,ê7þgùÿp@½™Rû*Ïù—™ß{÷¤ýŽ÷:ýu0×wægùüßsdßòr·3²’¨·¡Ã´–dßýŒÛh±½Eè&ÃéîÙf€HRí.ÈÖˆØüªÓ éŽ)ÿ–Qö«N®C“²ä=$“Á`™»aââ?¨ºö½ïÁ³šÛõwûÎ{4Úw|€öoÙèCs™ß÷ý]®ÏqfŒ{7¿ó‘ìÌ” ûOvÙþU_s3ü½{¹ÍŸÍi“Ýç¿þS ³ÜÎ »™™»-;Ìæó×°âo~ð½Æw?ÚsšökÓ©_ù8ÝcAíkßæÿçŸA¹’t¶9šŸýÿtÛ¬öo3~ØÂ.L~ÅW·¾çñâb§¾yŽò¥þ7»ÌöWùÜ<Ξo~AÜÌÞÍfóy™“øÛè¬Ý©}ŸgÿçwÜæoºÞm Á½{Zs¹ŸæVf½¼ÏcÔ*#™™8ægs3;$þff^ÿîo÷™ºÖl2s=ÏóY™ÑÍ4æ•~åû=ìïù˜%Z,Á –æÉLEIPßB!¹tüSþ›MÒŽH&PÚÉI¤ÍƒØ·ê y¨2¸Rý† ÅH‹ºTM0ÊXÝ2Cáã è4q w.çRjL$×jdÉ=ïOC™µn‰qÆAn†zËShJLW šlŸÇMÖH¾6™¿5¯p´\ê™8ÑÒ&‹Iý ^zÐv*ÿuÇ.íܲëS‹ž–(±ÏÕë¿ñs„J7¢ÿãj +dÏa=º¤Øxx +QÀ$†CŠß:ÎÌ(°iVÄkð¦t½4Ú÷UáY²_¹cJÚç`mJâñ9Ë/•°´Æ#aÑzKbi„8 ¸=a¬ëR†´Óì¹~Ñý€Ž)¿À3,Ò½P‘a‘­ob%&›ž´XmP¤Sú †‡dD”P©Gj‚ ŒSë „Å'I´J³ûH‹ÿÄ Êk"âÒ¤”- l‚(øÍŠg]!:dºš^d¶ª•rÛ¥®Û†ÈdO…½3!j9|°€ŽßéàãFNæP$ O†hß?Ày sDû{üÁЫµia©côm¢µ?Ä ðÿùháSRx}ÊAva{t%¢Q°*£æ«þo.5òÎk§+öx§ D¨- ,ïgÄ ; lþu,4uMÀP¥zžÄ;»à®ÑÛˆbS’ü qÄŠ Pÿ@-–”Èž 8M™¥ËeÑÔ“¢Í?ÐŽº.’Þ•‚€þÔ$âÖ¿D::C ’57Í7OZàâ¢lÌÞ³}âù‚`‰gœT ¢Ï•"h–}Ië­^Ì1ûtZòEú±–ƒuýâ:ý’’´Ðý¢B¾&L#ÿm:¾²«›G›¢4Ì_ãþO¢"ãÏÿl¶ÿÄ"R”Lzêw4JQ#ø骎&kô2ö +¬¾4ÓD¤ºÂ7#±M˜oŸ«#þÝž•Zºÿ«‰¨bUÙí8{ôÝùŽÂXö®ÂB÷m‡ÎcZ†i Ü„?‡çQ££ÎGo@êKqÿ·ðøÚm¶ ¿Àºß ´kžoû +pYáéźSÐÒ Ïšÿ¸¨2ANÀ†w¿<þJŠ ’`F†¸ô¿<7Æà¹ÿ%ÔòPL½Ëu®x-ëK×?ähEÛpKU Ãn9/ÍûW>?‰,‘¤™ç'Þê:/þ u_Ý®i ðkHÂ[0u¸‡“Íg§@Š Y '„’}¾IOçnXãj Ál„DLÉR9Ó æ #¦–¸¹Åú0ñL +ã.ÿŽëÝfVgs33333333333ݧwküÿ;™™Y™™™™]ÌÌÌ̬ÌÎï3ffff<ÌÌÌ̬ÌÌÌ̬ÌÌÌ̬ÌÌÌÌ£æ×÷ûη]ú _sO¼ÌÊÏÿÿ=™™ëŸf{8¹Üÿ32ðæg³2Ow™™™¶ó336·þffgïüÞ¹òöffò+7›ÎêßüÌÌ]zëq¾ïûÜÏN{³þO3^Ïg³g]ÈçsÕþfVfffff]ffffaÌÌÌÍæffffw333333332û™™™Ÿæfffa¬ÌÌÏfffffW³337ÜÌÌÌÌ=ŒÞgcüÌÌÌÌ©ÍûÜÿy™™™˜M¤Ò´\¢+ךh’‰V¢æ1QóMÙm¹x¯©OkpUÿÿwüO¸Ôˆ&ÞÇ(ú„oÿ÷›¸œ¯ýo¾¼v£—ßó3?Ìô6ˆ +õÜÞoú¸ƒßó7?æë"˜ž5Ü©Ï,“[¼ß#3=ÜÜ-–yýffzŒÄ3™™™›ÉˆU—Üôwü•eŸóy¼Ìî7f²27­sþe%¼Á™™îæ{'ŠêóüˆÐ;ÌÌÞÿì)©]­Þpí¤x«yŸço=m6ƒÞ‚ÿ¯÷_¼Î-÷عSÙhÐ 0æŽjm ;`„ ½tæÀh5A9f£zkSøNÈT7I1úUÌ’ì5ÇaE)½Ï…^»žÿªÑl4bË·¯Mëþ{ÿ™éÀ2{S™˜óæfwþámqÿsX|Î{;ì÷wþoü¼Ì»[ÿQ]èÏõÅÌÌÌ£Ùöd÷6ÄG"{ +]D/.×ùîæ›ÿ3y™¾ÆžfgËÚ3wÝç³yÛÿ?ÌÌÊRî ÿ›ËÍ—¿ñfz”ï;Ÿï3Úßs33¹ì«¹öøuÞìt©×r¿Îß4óüÿ?ö¿ÊÛ®c>½ÃöÕæW±Õ×ù™ßfxrÌyìæ*î™þ†³YÜÿ?ÌÎÍœÌöw5™þgs7•7›îgüÜäÖ¯7™íÿ™ÌÌÌÌÄ·ÿsf\êk^ÞžÌÌÌÌÌÏñ¤žë';“Úßù™™™¯ó3yœÌ{€µµÛ¸ïw™™ÜÍæ®æ%Áž(ÿÝæfgÿ332hl^wÉžó¹™™ÜÏfgr½ÿâзq_ÿæóýçs=ˆŸ×(SýpþCbKPÁIƒ €c³¡K Ad +IEòZ®&ª]‰Ih×%kCžm=òŸâ@JÅÃІÓCTQãéÛ ~á쎦 +U5‘NÜÛ¹pš0‘”h+Q-·Â9±6 ¤Ê½ÜzÔpÌ+€‚Wä-3£Q‰A?ž  ð§Z Qj(Ëó[mrÒ;ý¿öÚ,”W¹i›ÛÔ¯GšY½¤¯§Ç¯Ð EW èIì +î¿Ißþ!Ø-˜;²ù}|Ô²_$»©y~hroD¶í€{ ø‹ëjkSÞë:Úáãµ£Ý"š*0ªú¸þ5 ý†¡c¶OZëçéLj¤5¶ zõËÙ·P‚‰ð Ig MذÞÓêšž1¾=½UNÿï݈«ßPëï$½öÇ­I¢\Þº3›w¸}òt…ëòôA ÝÃÏ„eÌ.rø=8™`P<®_÷Y»‚PÖÉuD*í ò6ÿ÷;ÒSŽ›ÿ¼ÃïìÂ’â/Ì-;v¹ÑíÝøô¾Ê[‡7Ü— ¸•b +|›Ú0ùé[}`µ\¨b„:_ò´žM€.Méú mp¿ãQõ›©\×O$”GúépÜ»Ýð,Gé½âôuUSç0 í´õ$µ+´æe0QÏf½Zý€‚aå¸.ͽVï^.E­ÝNÖ-Çï¶åÌ›“SœUpF¯&!;gsÂì)öHwfi¡RÒ<‰Ú~ün{ŒæÎ~¿æñR÷jäŽ_ê^§ò¤={ݾÙô þ¦77·ÍsY­ŸÒÿ]Ì(yµ`ë‡FãúíûÜä´š‡nÀÜHNJ\Qcp-Z®&ßM@v7Ó½$AbAb%ºA Dx§È×û»Goÿ>¦½¤¿×YþÒ®TXçT‰)“¨×†ýß åÍ×ÿäè™]Ñ…+UÛ|0vÔ;ýËõZÝo$&ºˆ7ãŸÉ ¡x“ +”>sþ^½í/Ï)!‰zÉÒ9¼UPŠh Ð;†¶õ¯æÁÁ f,Ý“½©Qü‚R™€cp5`¼ÑÞýé×óº{p{|¨BŒ:Ô´-שvz¢‡r×gýú;ËÍo~Þ_äÒnîֻêþE%îßtœ~çxCõÛATÍꘗ NV¹ÇZ3íÍ¢Èh¯#®ëR¿ŒIgñý® åêÿÐrË y¬Vá.¸æ1u®ú«#ߘ 0RÌ=tþJÆõÓèßkßâ© €ÏôªM Ì“>#}@NsñÝc»¬ÊÌÌÌÌÌÌÌÌÌÌÌÌÌÇwwwwgüÌÌÌÊÌÌÌÌÊÌÌÌÌÊÌÌÌÌÊÌÌÌÌÊÌÌÌÌÊÌÌÌÌÊÌÌÌÌÊÌÌÌÌóšŸZ;ÌÌÿÖ#üôîdz3=›ÌÌÌÌËÌÌÏff³Ù™žÎffffdw333Y™™™™·ÜÌÌÌÌÌÌÌÌg7™‘¾æfffeffgsÕ™™™™•å[ÍÔÿ?ï3{ξfoä÷?Íæfgû̯{3üÌÌÌÌ9™™™™™™™™ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÿ333=™™™™™ÜÌÌÌÌÌÌÌÌÏ÷¾æfw3333;¯ó37ìÌÌÌÇm&ÒmZMݦ‘aë •þ¹-K]Ý"c¾$q ÞI_÷)sSÏÕÿæS~Þs.¿¯ñÉn†÷ïÒÊ•*ë¾Ìîg¿ß™ˆ¹öïv9ãäØîó3?Ë߯ŽM_³27˜â{žÑÍæeælÄKì¿{=™³¸z9šï³33.³?³[÷ûîgù¬Þb.»™ÜÉÉîfoú›îó33;“ïýÌÌßs3X¦²s¹ÍÇ„[;îfÿÌÌÍgn»Q™™¼îgRG_æfo3332űY™Üß³xœ¨9ÜÞo3;þe ûÌÌ̹êÏgþÿy¼ÝOi¥²/½ößuºÿ7Îæ{3;³Ó7ÝáÎB1›Þo»Ïó½Îóz$D=ÿ… +ˆÙçróúö»àÐu;rßâžzzðÕ„•Ê3·K9§^ßï0ïúÛ \záåfÿúÏïyžÿή9sƒ5¯Y÷ù™üÇsüÍæfïõ™èöû|­Ïùžö{/¹™™™¼“gÞÿ/=¼õ¬>Ïó7™ìÌÎæó¸¿×ûÞOsyŸä¿ó337ÌÌöó"¿ìœïfû—ßü§y™™™™™Üîf,ß}™™Ÿû¸sÛ÷k333;Ýû›ÎågsüÌÉÿ3=›ÇÌöfw·™™™™¼u9¼ÌÌÌÍç½3}ßñ™Yþffdg¨æWù™™žÌæYöñæfgw›ÌÌÏß'¿æfffffoµ¼öó2ÌÞó3yœ×?ÌÞ‘™™ÿù™™™™ŸæffaÌÏ™™™þDæ{33¹™™—™™‡vs»öo/75œÖgù™™™—žÌî~ó?¬îó3¹½žÞo3ÿó?ÌÏ™š÷?ÌÎäŽ{~ŸûÚÌÿ37™™“@ºŸfg.ÀŒÌÌÍßù™›€hhdÝGžù~ÌÎäÿ¼ÌÌ“Ÿñšæ¦ò#¹Ÿåï333ä¸m´xe‚ÓEH€ƒ­xݦaCT \Š;6ìØ‚ +e¦Z®ÊѲgNëIQÕ"§X çqI$(„Ü2Sƒ[i?Èô¶í¹–TÁ©¼¢8KÛÝÙÇü£vq+™•’nÎõvh‚.tk•7Ùÿ_Žñ¼ªÛ\P/­l‚ôëÃ@ÿ¾Àü­@|g³ µ¢ÓÞv“t^¡Þ°EÍMJUŒ[H»VrùÈk›iL?ûÝqmÍÿ9×Fãª<6"«kø¢m^`tuPÓjWwnùºäNéäI¸Ø)뵌¡³d¨ÏÄl!ÍrûÛ¨ôøé æ­tðKÛØZÿ(N‡ˆ™,’üòDUJ¯‹kµŽOŸÞ•Þ® » +t:kñR–1ªÿ?k‘Û”áGN»ÁU¸zæm¢Ñsk€YÉðÒ]¨Û¦ Øi‡3|®íghÒ[똕¥yÂ+;;ÓÖã…ÿ“>l†FûØÜþ·ÂJ…¦¼hJµµªˆÜçi$NrGkÞÚ™ŒïªYeÏò¼?ÜWvO\ž#œÙß^¹ÿq~½k[ñä ]ûþO«[¿àN[ZÿÚ·qü×€tò×"½ÏF½¸;¬‚d$”1¾é„U׺Ôb%Œ ´7žâLoZ ‰Ð|ß8à„%ЋyÌÆk›™ã4Jïï_”rDÿèQ¶µ¶lÅ/±ª§µ¯¶ïó+ûçîôù½ó?ÿóFä’9}>µˆž‡ê)£¶J½(Sw·þÀçÿîµr]†â´ÚiÊìh×»oÚÿ)»cM”¶ôˆH¯Y\ÀÓOmG=^÷]eÅM6Õplþí¦ö¨b¹DU0eÍ‹ëa¹¤ƒ%×riˆÕrwíè%}’*Dƒ¯Dq$åX|ÝŠõž!^¿@¶ ¿7fš2нËz˜t¸.¤´OéóÍaì["š{zF +}JǘF½e¾øŽ6Ùˆj”¡"xüUúõÏýo¬pisV -ÙmA= îhÄ*’ú•Ø3î3BüÕÔØ"MrW9þjªºùï8üs7Ú7á¸M·n`ÁS°¿ó]“Œrc4ýc\ŠE‡ÄhZ‰,ÈýÚpãýϬg-Vµ/Ѥ­3h»’QHÑ]å{·ê«Pÿ>“Ê;îwþÓÛvjñþ¿@9[UÆ“}ºZ\_ÕÄþ³“ ùÚÈ#wKº9Z¹ü0+ßé«ïjº|´M'p?¬×fÇñ†7úÀA¼„† ôí«Ùç'Z\\¾ÉÓ€nNô<¸‘ìJ×GQÄß/Oýþ­D_9\ÝK¥Pv½,‡ZË‹Ùþ«ú«Õ7ë»}¯ÕÀO9šÝr¡sÊÎÒ:Q®[Ó~>YÿÈOþï¼Îl{‡¹ÜeçL;ÛlrÁõÊ…ru\ã¸ÅKz?Ïùr¼Â…¯^ c¡x÷Ùæ­jÒæÃ\Öã<5l=4ûÍõ&Õ©ˆä±a·ÈõþïÞ<í~}BS¸,1¯ôkÊ ¹‰q›¿ëD×[ˆ”ŸëÜsÊÞý‘« ñ¦¸ƒñAŽ["tè»EÁz”Ï£×iÚ¾yÉp8ÈŸþûÔ==é¸ä.@ óúÑÔ˜C¾G£DÅ}c¡òAüÊŸÊ£·|ÿý€tjõÊ©<îóßëW—¿Ê¹rœ§žu•’¼1;ßMÕc'™—Çúóïoâÿ¼E«¹Ý\UoóúÕë_æöÊ×z´mYOþ¯ãs«¸Ùò8`X†ƒ1U«ªü®¯MWyÊÝbvç“Îu¶³Xj#zµ{ón÷›‹©×uãE/Ùÿ»«VVÿå¹Õ¨¯òóGÛãʇ?Ô/wþëNgsßýÿÿÄß1h™•EûI•~Ò¸× 6øOô\ƒVcËÕ™›FÅo]«ŽG·ê/¿äÕüœü‹ó÷uîw•[o˜^Mî`J¸7yʨG+ß™ØHŸpñŸÿ‰?õfȽzS¯.ïôp×§Ub?uã¼°©ÿ}2@ºŽï°¢Ru»ªï}mp«îâu-Ç»­Õòiâ‰íju—³Ïùh6„j-û;à9Z Ôí^¬¬0Bzý®ö=¸Îç·½4Õ<ÝÙ4ÑÖ´¼øÎËŸýWûHl–XƒLuh Æ÷=Ñk³xû¯Pÿßè9Í6ŠT®ù€Ó¸WüÝU8Ö¡ÖÞ‹Eïº÷š:Ã%W•æJáÖ÷U´ë?×ù®…Ï;í0+ÛÔLÛ-ÜT®]v¡[NæÎé²\v5Éç¸çÕU¥¿Wí~ÀzüÙ²Ÿ9p8ý³üÏFã[¹u¹›^ê\ߣdeËYÁ( +DÊànÅ ¨{&+Oª-{Û5ˆ*±{ÙƒËs!Ùë%Ä€ªnÙOazt"@(e¢¹ë1%vÆ­ä¦ S0hê9 -úé•ôÐa²Øm¹M +¢,ϠͣQ¸ù˜\n™X]vs®8É©õ,‹¬÷vk…5Â×h@¯€Â-û4>b¬þ…âeÄ”¼6¶ãÇ’r!R6(+Š–°­t2_`Û2ºh‰ä²ÌhÖ´ÔŠGÔ‰@¸ÿwËÅì€ßƒ)+^“¾4¶ÌÁº¯#&JK°¾±ZÊK¦^ÆfB`L€•„Y›¦ÒÅ!ÛW¨¼Ðï¢vÇˆÞÆÇ˜Þt®Rz€Ÿ“>ùW*Vþ\¾ï;úéì½ a+‚¦óO3°V ÷î83÷?+Jjp³Èt£Ó(=:îx¦\Å MÞ¨øâè¼O.´uÆkêÃà©ù¸³”¥z>‚vÁØ9ƒ(¨ °ë@#ç†ÎœMJÎ㱇¶bÿòèK5}Wݽ|Î2»‚¡}‹~EäùiÕ¬ºsqiVMSQ%X7ÿÑJvE{'óºølò’§åïïö?þPÐ¥Ë;JQ5JРÒì`…gŸcèås¬òÆGrzº¹­$8}¡Oû·yƒ>*–ŒX„5@Ò.‰Ë22%ÿu”ÐUnI_šLOQ‘¹f ãÁyU4‚E€½ ¢%¼w,€`D3'~@í {šB;‚¯ûµy%Mþt5qØ"Gã,“M)¨bY¿¶Ò:·@†{Á>ÌÆ©Q•ᬨ@O÷¯äI'¡¡_"bfÁáo[¦ë@Ç”á­4A8ˆx€JƒyÂpˆ>íBé„¢5«5Ùì¥{*k´ÌûÒ‡UìO»pË#Ƅı¾p °²t‘&C×ßm|ÞÞÒ}0¤=ž’õ |h˜)p"F‡XCÀ!…+/¢&m÷_8Yr1Pso$¡=ˆtÁˆ1ú`€ÂXl öéYù†nŸM6Ü8¶gøÉ;VC#’"½€¢¨,å¸R)J2ogíÑ@Úÿr<c" \#„€‡u€£˜@W9Lw‚&-jðQc[„ÀaCî`€àÄ€î{`[̈ˆ³\Âð@ +¬Â‰l‚ P † ˜`D,FB +9”‡`Lxú`K`B(X@ €€]†V€•  XF‹DÒT &ÖËBIA +‡€W Úì¡­%þ¾ž‚€,ƒØ€À !"€‚!Å©Ì= ЬpÀ€ r@ €Ó;x …(v)¾»{°@! ‘І˜Á€ ÂF'Hê€À>GæXBHPÀ Yˆ(`#°³I€ÎJ þ{4×Ĩ"ú!:Ž€Ð¾Ø€B"\XÚx„BÏ jpä®l%âè¶!‰rð€ +rÌ@e!BŒ`C˜gLuÇ­i,1‰"‘¨…X¤6 åï7†YóûäfSVqã&ëã‚E`%ðDGdðu¿]WñÄå=éõÖñíô­}Hâ‚@81ô¦–wA— +\½»vÛ~áÿïµ3ÉôWÿ¥i•q„@É%p ʈ¶À À8 Þ!‰LƒÃGè¶ß­~éû³D¼(2„PE 2€üwŠ„³%+š!…gx"AÌeÙ½€B;8†ìü!BuÈäËÈØV©¶£öÏá¨vûñÀi ƒ°%]°SIòÀ )n÷2„kó]RÂí³Ü²o`£…Ô ‹Ï£¸µ±¥àw¢x0‚ºÙ¾™Nïv„ˆѢ•u¹'Û"Ü€ÄĦA«4OŠ ƒJ $%‹â™.{z0oTèLïX÷Í÷–/ŠEÈÌj¬Ñ«–9?ÝáøøLã48T‘Œø ·H³®†ÍS%ãÜ=üËk €’Ál§ÀÄg¼4ù¸œZ…F»~B02±E~ eNϡݡTd6½úß©âq¹€)ùBf¸v7 ^ˆrd/§'OÊ"LBÆxpi:´þj¢5DØf­×#|z4¿õ SJ€¨X“ß0¦¯B— ŽŠ¤¢g:¡eäÂõcè&öz%Ü÷€zò#ú:”’ž\bê­>h©äýôØÀA {¹hMEÃk’o™'6}V™ ¯ ; ÛÐô9YÀÁiüŸ®$rÀw›8·fpÜ ++ðïÐÀ@>¥†p#ã¾(G]chˆ’{=øú>c~é6´ ÷ÛjŠ¾à “Ø5){ie‡ô@ßš‚ú ü—Ô*Ák­Ö/§ÂQ±‰F"à¯Þg˜f…ô3‰Ù†³7Žö3L~4âdxëM€ÍqN­¾®OÏ×dÙ°ZØ ÛyÜ0 +’øéÕà'03|:Ôæ a@,xQ=I†ÏQ(r„ K*¿¶t—Œ}é\kq†nû’¬P†|)Þ-ÀWrGKdÜÎúùüºë]‰ßÚ dêÔ›IEÀ dt¾§JBS%W Ä2ÆÂwû_¾¼[Õ×^vçRصC:ƒHM`ÏJÎ}oT2“Á›SÚ‰1– C%äó9VäsO½§À¤Q¢¼:ŽRùÙe—ÅÎBdf0`’'LÊYÚ à¼“oª(#¸!Ò4ç"F£HRC•É”*óýwšÑ­{L¾’ØmŽàÿqhÑsZ… %bÌPZæðÂ÷£f¼æÐÃ$ œ÷4Í•ÓfP±‡ú½0™p0f(‚;…—©¸DEÕ±§Lÿ~·Âúú¬ôEW•;\„˜»- +éÐɉPÁr¨­=k·ßöC{Ã$,š«˜èd·R4ée6Ð'ö5ÛTcñßÒPb»Î‡,¬Ñ€'T'òÁ×LHÓÎ"/ž‚ `¦ëO'´2{i ECŸÅ‡­ûؼˆB„\ƒÐ"Õ¿Ü‹è "¯eÙ³úP*¿ŠA™–º€‚‰”‹${r}hh{×Xæß&³Œ%9åH BH +ðL!44, œ7¼yǤWâ[þ. óËÚª “¨(p(@shBA#þ4CºÌÌÌÌÌwwj³3&³3&³3&³3$ÄD ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÞfffffffffo3333=™™™™™™™™™™ÜÌÌÌÍ·wwwwwwwwj½ÿ³3ÛÌöffû“Y›ÌÍæfw2s0Vffffó¹ìÌÿÌÞ^ffdffw&³23üÿ3333¸«ÛÎç³7žÿ330<Þf{=¼ÌÌÿ¹•þfo3Ù™™™™¹¯ó3¹Ÿæg{™™“Y™™ÜÞf{3ÙîÍfffffffw¹•™™™™™™ÿÌíffgs7™›ÌÌÉ­æffgùþf™’û™™™›ÌÌÌÌɯóúÌöó3;™É9™y™™þo33ÿMfffÿÌöfó3Ù1LD.?ìV›Ž„«óù‡åõx¿V B÷Vµ×£-ê‰'ƒ‹‹¬ÍÊ<Ü÷Cë$>îMŒÿ^ò{¢6´;å³_™3á¾Èê7JÔ[ò­:*ïc^[¨ §é]Dóßÿ´ôùv`J=6ßëªóåQ¡êתÃõ‰ŽìkŠâx»Öâ4k É:½Îs*Î_]ϳüÄS¹JœxÒî…çéíúÇkÆ=¬õûÿ!˜»ˆÜ`©ãü^[móy¯F½çŽ=³ê­ú{ÞDìûþÛäÖó{ÎÆlÏç[ö¦¹¥§5êѶ¡v}áÞò½’Ö{GQ· Ý+/Ü™¯ÿÿ˜³Ý2»Ë{ÖŒ)sJ|·{}߬{?ôÄGTÄ÷¼þ«ù×oÔü?ï§¹"LLë_ÑÏ÷³/Ó¾l5µÛñÞ˜“%ùþûà'?bb…þ¹VþWÿ¸=Œž‰Îû&EoøQ¨ïv7Qýµ}ºòÐåJ¾ØËžÂcª›r–ýSTµó–Þ¦ÜóñØÙ^î]ö´eÛ»cEG†Ûçÿ¯ý[Í×ë“s±§¡ƒÏüýj$×q{û½VmA<ÝAÝ]-^ýýëx¦Ÿ aêÍÌÖ¿ªãc_Åhs¿ÿ#zÔ»_õÐ×ÿõ>û?|ˆ.?Â6œŒå÷O4»;3Ïn=¯²¿¿èf£Ø¢´´ÿç93|“þÖœð þo9zŸ[ÿ3ë^ߺc\SÑÿÿûúìÿ¯èÅ×¹¼Ðóðu£×œk=qü×6ýµ4{e*»Ïus=‚+ S>—ÏnÆn7ÙíëK—ÞõÝò=þûÝp{/ÚTÔê27ɧèÎþÛ¾½NíóR"bÝî¦Æo×1¸‘:¬3:?Æ.DÏ÷¾^Ì®g?ð_÷`(]»ÔDFçó9gýo—¥#'½½g½@A&@‚Aˆ?÷½£²Ò† D[kÿGÿ¸ƒLbZ6Ûm¦µf8 ¶)ì4áµ 4Ce¤ †B¢&Û^ +öM˜é'ñÝcHæ<Ûàm1™cÿö “l6ÍÛkÖÖjá_0O„h±&)y4­‘øüù0Ê0…i¶œ6• 6Ý´I´e4@O\3. +H8ˆVÕIi+HŽ$.'šmwdS„Z¶n¨“-I»TTíÑÔC6AKù4j_ÿ¸×€ ’tëþëÖefs‰¿ÿšÌÉy›æ“l–[7BݺYÑ£K3Ñ']¿ÏM`QH>*`ˆͳŽý¸l¬ßàƒøÿ~„ÂTkt¢È$†Ú·ZWâ(Ú TÿiÙ ªW€HdTÚ _Pß,ÙvÕIþ2åžêöQ ïѯØPþ-§©†­:—$†¬‘Îþš0•L˲*–îÕ¦’ŸsdÉÀèWÊ!JÉÀMPf LÈ5ú Á¥STBþzœ@jøPâ c]MÊ'‚Kl–ŠpÙ,œ 2wMM/LL’)¢[e»‡)£àKfí8Çu]fVcç.»™êÌÏ<Ì徫a’™põNä[ÿÌï¿Õ{3Ù#ºÌÈÛ9ºÀàèê=H?v†ÀI‹– XN;ô¶¼õIˆUëöCM:öû0 +»ç³3I˜~¿~Œì;[©¨½Lˆ °D¯E›!4Ó·£¹“«IÇèˆÁù(„jgE=¨Døø~äA ºº˜·VÓÏom~œÅóþ´jOnrëÛYÝ$U†š8cþ@zëj€v„;1U.4Â5°ïo.ÔTµz’ ˆv­‘ u¤fx¡E¹hÞ!´t^&AƤ0 îÕM´O4,Á$‡ Û¿-7-‚À "Yô4E‰L¨$¤CüSNeÆ2Ñ ðò.Öí=×¥"/i~?DœD7mera(f¢-†âö­–¿)ºj½50G=ã¹-€–6e킵 šýáÖÛ¾HD’]$oS«Üzz!º¤ÀlŒ m”EQ.‰¦I?˜.À,ƒZjlÙIº •±à ~;¬wu™Y•êíÖfz³3ßæfWù˜­¶^Šºq{ÿœˆÌÏó×y™›ÍVf{0æfFÁçùŸäÃÿ÷¸ê«ÊŠÕÂp°àní5]×ÿ©d1’‘¯`ÇýÞJM;¼Ì¯"‚ÏfVíÓN½Y™“‹¿óüÌÏs}ðˆ—¾ç3ß4ÝœÍòäϪ‹ÐºÄÈÐä4؃OJÅ­ƒAÀü"%Ü&¿ÕÙG2ZÊ‘kq 4ŽÅ£E€òü̳ ‚ ;A§PÙƒHrY¦²mž ßþ<%š¦©KzM☪$q6Ì—t|ˆHÅŽEMq†ëiÕÙÑ,Ó Ý–…Ü‹|4‘©”ˆ&ÒêR)²JaS'ßÌ2-C±é{©d§·«¦•é)¶y–Ýšà膫 £W *’‘)6$ìjׇ@Š×–ô@‘h?礕Ýõ~.E=kHWHH©¶,iöôYâÑì‡gУ§Ex#)®·Wr‰>¢ÈICçySéÙ©©4NüwXîë2³?÷ùu™™ÜÌ÷ù™•™˜®Ý¸9ÿ¿o=|ÎæffÍÿ™™™®æffLfffo¦ó33Ûpgù*ùþ¹ŸÁÙ»‡jƒ@ÂÁýÖYß}nÿüà¬É˜iGwîÿÄœåœéŒö^d«©×¿ÿ33?¼Šß³Ùÿ3=ÿéÅfff{ýÏE¼ÌÌÌÌß$ã3y™›ÿüÉh¼ôfg®¶÷“þãüÝ”ÿ´È©ÞsHºÜulÁçïkÃ= Í»Ùþ] ´gr¿“ ]¦Ô5Rˆ¡lï m‘†¦} 9M¢ìÀ>k•Ó•æÈƒeäßf×èÅórªÀ(hVRê&Íj+dPÿÂ¥åfúøáÿû#ÿ×ù6²³PÚl‡¯g¿öf$ÿÎÎkñ‡‹ü2ÖÜ·ÿzÿòÜÿÞÍF# lÚ¬ŸfoÛæ(n]ù5þ*]ÿÝœÌ÷ýÉ1öÜÌÌß·±´šy†ï=žöw76ަÛF}[öfs¾·qùûY¾N³‘‘úÅ_ÏŸþÉ¡þg}Ú¿öVöyÍú³&µG=±·¯Z…’¿›ÿcÏOÁ–\n¤Wµx²à]É F„(Í“_‘ùEÄíi"7í1ÙpÑÖÐU#öÔVÒ©iY ŠãQ‡?$ï¹>©÷)ãi¯)&Ai¼¿+ªŠ×âÌ P#S$ïñoG;21¤Ú^~K´š-¢¬j±Â‡vl?!}Ú¸€î»rÙP@ d¿/ʤÍ2 ‚kh™tÕØoJ€OpN”òÛL¢ªhô‚GX>òhŸãÔV¸üÙštL˜N#ByÈ&:z&Dˆ†úíJiûkÚ‡šôãÙ»Ïôán{mްÒ~të–ÿH&æì9vvŒÜ*HþÁûd–‹r 1é!{|æ”NÌ©>mû÷mŽ Û‘L*LÔÿ1û0Z¤;FË×?Š$ƒ­òÔËiLç`ÀCi)A³!ò=S¡<â݈ìøOÿŽfÿ°ÝËe_<JÃ|–°$ßlŽ×9¢tLq£û"Fµ-×M„ïü¹`ºX·mŸä +VÈv?úl½¿Q(‹€Öù©™q.¹î»’ÔՀâmï(Øi´J£|j¦ n(@´ú ìq;ÕµTÒ;O»Çµ ü@a'G¤€÷.I¬s´ã?×þ4i[Dc…ƒ€%›´@ žô ¦Ül*”í5ȃcgö´]d€ 6Ø K$„¿¦ÓéâÕÅ2R"¿Ù¢•ä Õ QI®îÚ4ÓO¤ÔóL&Š pE~Èœ¤ëhâÉ ¯j{ßÊPØ ®œ2£a§Û´†Éj 鬇ÝH#õ[´aÉsøî±ÝÖef™—Y™™™™þfeff+»·o+3»ÌWŸæfzó3330æfffe™™™žŒÌÌÌÃìÌÌÌïvs3#yßsÿýŸìïñlåÃôÂÔ4 ¨Ò `01£Ûèÿ/ßç}m{ýæãY‡Ù¿'®n7Ýæf_s5äsºÌÌÿ3Ëúݲffff^G5[ÌÊÌÌÌÌÿBê³3332p]þï333327¸q™™™›ÿ3%®Þgs3ÙÓÇR÷›ÿ#3¸ªŸò«yÙÌæ÷¨¯÷«qœ×?îÖšðÌßN!­Þß½u9hú|yÉ ]¦šm>¹L¹¬mdÝj¥ä<Øgd4Nýû;kwþÍl8joùvhûÎî­¶c&¥ÿu±°—o°k¡æ¨^ùŠÌÁôMb¼ˆ"NÁ•ØwŒ—z›F»þ,îMdƒ%%Õ›©Î×ùïáPîí¥SÕk»}ɯýw‹0úÚ© ‰ÅÜÏó?ÏóÚ œ»ægÿäf{3/v½ë§Ùþuÿü¼™ÿ36w¾ß ´"¨ïW³7™™™¼ÛÈ©Ï,ô<ï²³3˃ÝÚ‹7ÌËÎæw3'}Šó»LÿýrÿÿüÌÍç²…Ü[<¶›mgc3y¼Íæfâ3bÅg‡;Ïo37™ìéɬD`ÿÙY¼Ï÷™ÊàRNØýæ{=™¾TœPõÍsSÏfc™Ë‚ k6µçYîíÿ¾þ/Í.s2{š÷òs$+wvhÁåö MÃvAÀe@«BÒ¸Š~#)ÝIŒ€Eö^ +–ÓY:©â0ÿ™².m;1…þ‘ÿn<ˆýy¨òu?ÍÇ,£$5¸ðx"¤—ú¬ÈŠ­vIÔÇÿ‚é-’OQî¯ØFÝØà!š^²Ÿò õ¾«$%Xf±*¡úYuK®%Cž) >"$°­%&ƒ'J´Bªèv•É$Å;7*I*å³_ê¸=4RziTšˆÐY4À .Qj…ù4¯Áž¯= ?òË0“æíÙ0ª\ñ6Ÿ8IMȸ<l–A$€f-ú Úm½Òçó ß8dh’ˆGízgªíßÔ;%þ×hú/ð“ š?JRæI¯r‹fš—Ád×ãºÇwY•™þfþfffffffff+»»µYÜÌÌÌÌÌÌÏcÌÌÌÌÊÌÌÌÌÊÌÌÌÌóŒÌÌÌÃìÌÌÌÇÜîffaÌÌÏó3+1YÌ—k=1쌎ÿ»ÏïJ?äÿîûyžäp;Ïgù™™™üõßù™™¬Ã™™ÿ?àÌÍæfffg¿g9™™™™™™œÌ¬Þ³33333yn»™™™™™›þóB½Ÿæfffg³Ë^åæffffó7;ÝæffffffqOÿæfffff÷çêÌÌÎæf^M?ÿö«33;›ÌŠu0=šîw3»½™ðÌßOøàGHeä?owž«©¬zzöó®óp·mZµi«QSSë`Ô½Ô»6R[bHwx+"³ðý¸þrõµ–¬ÙÐñ¸¨…Ïy«Á/Ú’«¾ÿ¨õ±Ì¹kÖ¥õèÀ©Ï-wÖ°‚§¹ž×/#2Á÷ûŠÝÍe»YîäffwÙYÿ\îm»ÉYìÞ<_û.³¹Ÿät÷Òo;ßVw½—¼Ïwvû6»&ì]¸Ö)ïúÃßý¿ýx;•9Éq™öÿ™ŸÿšÃ¬îg“ÝàÆë˜.ÿËîg«ýç3?ÞW¼ýÿb닱½ÿ™žyÜÎçr-÷28õÅyþff{7žÏg{ìîY–w“œÿ3=¬Ïfg³3¹þe®£³üÌÌÌÌÿüÌÌÏfï&‡òH¯™þóüÌÿüÏ÷™Ì1 ÿÁY¼Îg·™šÌÊÞvÇl?ÉG¹™Þó=™™™ÿwÿ¹”[·þgù™Ÿæfg³?Ä"øñYìÌÌÌîg³3½öÿÿ=›Bë™™ÌÌÌÌÍ÷3¾Î‰¯;¿^ó3?÷¿÷z¿ß¶0m2ÈÖOãøîw3¹þgûî¶ÔÖe{Ù™èÞë;™¿awù‡YÙ¯gBîfðf&ã¶Ï÷syؾÿÿ–ñQʈYÖ!QÕ .+2åÿ^ŒpÑÈ ½aÉhÆ?TW²n§ô¼bÿÍ@ÜrÀi¦ï\îü½­¶Ó³Èk‡}1û°z ™æ$\ä«kÄÚÊ Þä œš˜¥k.»ÿr;¿à&‘’$ˆõ±jyžu \ ÝxÅQ„¼‘ONñ…®~9pÂHMH¿í¡€Ï6tv*kfs Û™@®ÙÓó k&²iêŸ9{(5R€”d~Bc‰ #(q<n¥ "©(à ° ÓSÔ¶’UÛ  !DnSdd, %AN—€‰¼ly’u»µ¡ÿpwøT¯RÍl”©«_ù‡\“ç·jcP\ÉšiÝÅHuÞ—ü¾5ïR³w3 Ù›š¿ÝÛja.ÿܗ'ž´äGöNÔÕ-–cAj Z’á£×  ¹2Í"_mðÞ7¢õªœßWû¼‡"ÿ_ñ^À4˜P:ŒJÜ1]®(‘5ÿ}ø6[Ú$ÇR@Èÿ“¶â_–Lÿ²]¢z‡…i/atûqIN~ûBˆÝ‘ ë\i`XlñKaþÍ´4%åí‡Þ+]ërœ¹!%_ažêó{å‰Ìþ7ãük#xËS^+ßçP’&4;Bg^þµ‡ý$9 ÈNô)à/ˆßFûß=È׸ÀVJÞÅPâÊiÝ^ãk‹HïœÁÜ/7 Pý¶SZUYSqÞLtN«.˜­Äo“IZ ò+þ¹„WóƒG8T«\ ±Gœ´ŒâÖqWÿú. t­@ߎhDØÙŸúLÇ`©¨rºÔÄgþÁ½ÕÅì¶¼CÏÔ*_ÐýËóŠ$z<ä’N”FˆYgCCŸë¯DÀìúµüŸ:µé¡lïªÒ‡.AØt޲v¹¤)žs¼îòPPC’›ÉòŸoRfo¯– À|5¹”ÿF.ɸS +ç[¦gÐAlDÿ@Âó5:RŸ 7Qâ÷E–”ªŸTc›(òä.]b´µ|‘gØ„»è¨ÿF™ŸmÔVè2é¬ß¢3]ë§n§.[¯ùÞ¿ÇA” aÔÎ1‡h C¦¢ê­ +BlŠçèõ®!&;ä^c­J[™¢Ê/v£K +£\>çƒ6A® Jiþ„¢tçÿÃåØw¢»"cÈHßô›Þÿ4gäšMá*ØUS$Ö´ ¤ù¹3å·8?##…L@În=Ä‚‘£äLXI§Õ|³ÅF}Çþ|»­…C2Ja–”DnˆJ‡=dþªDuÂó;P}I( ùYÂÅ1lĶëýøëdŽ~á= ÓD¸‰HùCä$‰çKs$%Òì·F«:3’ÛMèÙ™h¶H;m¢«þÔêÿµJÐÄN¤ò!€p6“ ¢ŠÂ +¢ À j’y$ "X´„I pŠp(döpÐ +­à@$È@@¶ €€%_ZP€ú… Ÿ8á¡X5˜Ö ˆP@… €Mp$Nø$…c€ æ‚@Q$Šª à&° ¨È%°@=ÀL@"@K€$ ©&H Š€+ÙP( )z€„Ô€_Pð$‰p²Ù€@€€b†ÔHÎBt8à  ðÀH@ €@["Õpž ®¨U@€ð Á!ŠíƒtÒ a!J  B €ÅepÅYEÀ‚°0! @àcWæ +ÀàQ p’Un€ @ATЀ@' +©ÂD€P x•PÈ`@PÖl ¨)‚@P c¸àaU× Pb¨ ˆ PD@Þ ¡L Ð’ÒˆE¨»CPPP€Y”m +°¹€€ÀAw\îQ. +ÀJ'Õí2CD‚ €r%€L"ó` +€2t+ÂÀJ:@A|Cd˜@@€ +P óôã2‰Ëè@›è‘S@Jb00… À$%æƒ!h Já{S ¥õ0¬J2š0‚!äxw0]!Ò{€  H  ¤P€ŒÎ6T‘°ĨDÈ&_åB»`€ +à"@ˆ@Ùp›ÊqS¨×@šVæ:„š"³(±K ^àPìx;¶ànÃÊ'wÔirÄbIšð¤PYF`®ò‘ê nq Y@$ºÔi0íd ªÉäÁấ _K¢¡Ÿ‰Ã]¸l’FÔê¬5 f ’⥒dœ@z¢¸åÀÑB •ÅXds  JÀb  f€ ®@Ïõ?ŸÆ,ßá]p ÕœAÌÂU0\`!Çay(3ŠoÔˆ¦kV€A ×  Êݽ‘i_ÅNÏöóÈÊ:ö‡>¶H%HD@Ð8ì¯ 6'J4UMð´@U¬x1Ò«[-kS P¿ì5AólIcœ(0Û³ßSÍ^ö +ï\ LC„° }˜@=©㉦`†ã?’•‡æúé 2€Œ‚9aÓÍh¡çÄ}þ¢ j~~o7À²J"1"€Z Œe†¬^¤©ÔžÂk_›lø`ˆ© P®„€Ë RÁVV‰F‚£Ü¦G áágiËø ˜e"ë +fJWA|v±úŽõŸÕ´¸ŽùûVÈç€RÁ2P  +"bAê‚Pu/áâdÝr;ma8y4ä;'Êÿ£@@H¨[…†¢< +£\‡=2’ÄŒd' íÕ"Yé¸0óÐ‡ç¬Ø±÷ùú +Sm‡²`|æ  €Z±AÒ.¤óRUóC‘tK”‡r¼ÂE01¿4Ž +V" +M¡¿o¤ðª¬%Z²"€pçø“¦+‹ÙàK¹ÍÕÐû¼ç ³Rnf$²Åkzž4ÛÚ¦þíOÉ^Æûë „ ˆ‡à… bÒ°¿‹Q:q„Gi²å¥“éŒFETÂJFP*PŽ XIêä)mÑeˆ»˜Æ¦¬à„‘W)=0âA  •a/’·ÃhHÜPûÑj^h/›3±àþUÔ½‘BCQ@2„† À_Å)ŒNÖ.‘9V)œ…»ñŽ' @‘T@¢.\Lù'Z9ž±%ŠYðkr¸jzö!@ªw }²DBKœ.̘²˜ 5"˜‹”@D B&Q(J•HB@è³f-j¬ð¨st°äCÓóxƒhˆHÈ!¢8pùSÛ.UBG,ÖÑõÞ×sJ6H´¤@èP`6HGh¢"½|t DZÌŇu¨oÿ¾<ÌpF'Lî’@ à%gë£d å´ÖïõàtÞ€Áh  á…ÓvpžÔ O”œTÂ&hùÿÎ1ób$ˆLh§ ¥Ù@¸@ Ff + ÔÔ¸S ÝE_M]Ràœ¯Ñ’D’Ëð{•EÆé`sÈ–ÓD)jé„`ÅtÒ>î½ÀOH8º‹D +V˜Eiãe=‹)~éæ-V(*~2Q@_ó ˆ« —è³xW¾æ«Öa9ªiåé“…9l`«Õø²‚XH×x°b5ÈC´%pÈ‘)@I +WÀÃ}ðÐ]` … B,+¯äûáPè6Ó½&–B…FpŽD$ `Ï` @Emp~Ó3žA)á0X Ûk PUOªŒVÁvÛÖ —— å!^'ùG +÷ l ‚ H Ê·x™sä“Kd\[/Ã6"h̰TÌdZ!pF U„@Ýè3H!l K,\¶×»UPJ í[°À&‘ªEÙ‘Ô•€†¢@DFúŒ1Â0Õ¸ Ñj'‹AÐ’( *¥VÇAB[¥€¤¼ {E€Ï 0 +ÐAèTˆõ;“}@ +° /® d‡Ofz£‰`ø{…Å-C¶H’P€Q +€€:ªPP4P¦Ú6Íî Ñ"‚Wú©AP¢„–ü" •[Ñ¥p ¢Ä!Û"“D‰…"q,Õ@ e Šs,#`\(½bd$0á* ÈÐ$ô@ ÀÁÔE +¥öI Ò €Ey<¡%T€T…R/fÔ…lVÀ¤zEÖ\C€8 @D‘ €(~I§HPn$yMT&np%P B ÀÖ’¤EÿÃDT^€ÀØÀ P KN… +*„7Òòì4€ŒL8 €€  œ`A J6ò´TL'Òâ @ ] Ð›$²2®È£ P(€šÐû‘!ñ"PsT‘ >Ðì_ò‰@ž“â$ˆjÂp  Ú€¾¢ˆß  +¡è²`ÉãÀP +,Hòw€ãÔD¯¶Œ¶Ä#2pã@¨Ò²Ëà@ZH4å Q žÖ¬NrS @ +¢ œ—!AAª) +ph,m" ®à*¢rš‡A ð…à`4ŸˆÑ(à€ˆ„º +"(€ r`9±›:ê·i;L–Ù¹Š`€x€ Züæ¡V7 «%ñ@ É{BŠÝ†aŒ ˜ +  ˜!K ‹ÐÀã‘,ª·¡Ýûþ‡ñr Sð†[¤”M”Šƒ>ðœ,UÓ$FI@ìà€5à ¦Ð¢P´Ö”&X£gXþñÓE`©Œ€!³¥P)³ LD²€X€¹á•$":F÷pΘR€"É@ "Àcª ªv1þýF4Â"ÍA?Á–õ¦€0@¡@m•Z ˜ØøüD¿ÂG€ú rW}œámLÿ³ ™P }’¯£(AÔ¥ù@—˰–•&çwù·åÅ ˆU˜ Yå c’ì/%…<û±«"M©ý‚^µ)²c!ëôX%0¯( Dˆz¶¸zÔS*¡s[ +Dú©[±&«(›ÉXìÞ:]  å)ˆãP!oà÷ö…Ï£í„ù'(C=ÇÎP6Y¿¿e`ˆP ¤#vT³(vPš~ •ÜŸ5Œ˜¤Dhd7…ðH ¤”_}©ÍÔÏ”Ëdˆ±ÑYß·+ÅÚá¢M„ê´™ÀŇ*ÁnñԀ V•° ˜íIEÏÁëá^%Ÿ­ J*ô˜˜"i4À!@.œ`ScÓ)F!’ð+q!þDˆ&L%  k„’%Óz+Æ­w2)~'.ùü÷¶ÎÉÏS @ê@G`( ‰J "0-|Á„Ä^¾W†w®Ei†i|rQ +n ÚE¥eöèhFc°U~´„¬æã•žb¢ _X|ÐF €Œ¥ë °¤®¶¥l=Á9€DmD<ö6˜ê«ýì¯JCÉ…Ð×àÔ%N#Û£Qé ÒÖ£È3Ç)mF•p²,²Ä@È´) +fkb^¥;6ä\‘7?t bŠê¯Þ!íú4´%P•)Š@ ï„LèÞÉšš”T³¡AKJxéæH+)V'},FL%2U Ñ[”û[ÇÜuf ÆwUL‰OB?4OÒEÔ= ¤®{¢s´ÅÅv•¢r›îºæ>&YN·GY0³¶aAt÷2š>ÕWŒ¥ÛÛZ_*R HÆDP]- +¥œã"MdÄ×Ô-þK-®3ô×Ñü~À¨¤S.ýøA¿X DX¿x!AH°§;þ%³¿jmë^ê1@ßÄ“:Á‚ßûå –ÞY¶ˆ°cwÊ0 +NV²KŠ RÑ”Oýî"²lŠ·…ô¡*àÉÒ¬’L‚7­ë|ž,¤Ú†}§ýëŒÏÏuÎ4p0]Ñ 8A@,Ÿ_ˆ&4N2€1fÖ^Å;Å›–‡ªH±°°Ä@Ü€ ¨ÐK§ AÁ"ïñôy¬‡¥Öý$tTýÕDªá^An@©¤€/#I€uqZ^!,-ïM|™õO¾zk^4èÁ +`K!0Ï1‡¦åxxäñ^t ôËï¸ãrw›ò7ÄÑðˆØ@T'Ÿ­…ý¨nie%ê:νý´e‰p{!ŠrU ,P„w@áªmÃUìÓ À/ªs~ý¿µ{ZCð«ªN-'q.­Ó"GŠ Q) 21 ¤ ·É'xíYbì5•KWiwa–4;å(Ä(¾ú#ÿ ›ðj²ÿH÷yw#EÄj å6ÇgȸœºÁˆÎA¦mà¹1.në§t‹~&ìØÅIg˜›”޽›c|óÆ=ð†!–ö{ìštDÀV˜rñ‰N ]ú¦/dòk.|ðZLR¦@nñAຽûoO<ð/f]&E"°›R‚—E ¦D­Eí² ,ÜgwÏ÷k¹MãìYeRï—îômÝEtCBOʹ±лÃ! ¡€ip¿íȦ¥Ù¼„”"•OBÏ ‡Fö9ÏD%í5Ûž†\’*¦Ä]FÆÙÊ“s`Ý2‡ì‰? røí½íºÛûUºEØK Üo]^7c+ÕÆ¬éØ> *®üò´‡Ê{r®úøš\U;‹"Qsj¹úY´\é³Ê^nr®ùD;1¹­íÓèú¾A´MAGr±&.àk:;…Qð†é¼;˾ÙCÏŠ}Ï—]³uÙvZ>F5*8ˆ x eW¥¯«6 é$¤›¯Œz&Ðfiªj•SDVL‰]¯ojšr*µ°7îƒ÷ËÑRœ*ëXÊ÷úO¾))Îʬ¢1ÑNtzÓ·ÆE¿6©»«¯e€“\:ѤÕ[°H8ttó/7KÏòø€ @÷çvýˆæ ;©w!Ÿë£÷Å6ËN¹´ëwþw`žT•Ðò + ·;§ŽËÀ€½yö{šÞánþÏÖ÷`Oí|MWÌ-\€0êwŸ=®ûÒÔ” Ls„2ÓCÙN×í9ëø‰õ ˆSà ëpùæ+5ھ!áQ¥ÕB‚TjÅy韨£1ê§š³U;Ø^ÚÊèódÙ4_æñY們½uÇœïSPP .1þ:Î⊧cGyÕªc»g½ùOÿÓnã·Ÿt·PåïhÜ*{úÿìJŸÎ…’®œŸßøøù–çFâï'¾äLªO5&Hÿ¤ïýÍïžÿþ–\¸…:²xŒ}ãQßÿ²ed;ªuJ çóÒûöú˜;8¾D5Çë÷6Bèœ}½=Z×òzÚ@.qÐ}$W8N Ùk_ž+tõ_‰ÎBwp˜wmjPÿã"zØqe¦Ù!Kjˆ~S‚9ÖØ®Ê,cYú¬(|k‰ÄÆrÊ÷†»‹éÏD9l®Ñ}7 ·Tþ±¨ÂÈojyóirôÜÔ8ÏÇ7SÑ÷L$ýv{³w2?É× 0Bm E„öÝ–ˆг¾ÓÍ}ÞäRU4~íÛ­¢K.c7=@!rÉ(@|ðwü: \û«ÿ}£¶/Û•™ÛC“Q«ÛcKµ¸(ˆC˜h©p k¦.îæ=èPR{Öö\[Ôð¨˜ù÷O[’ïö¯YCÀAD€Q Érþͽ}ÿhG-Iyc»Rëòïçà¨ñµ®ÿï!0 *—ç~yõî³Xµÿz HmíÖúו ÛÿC¯S^xðDH ÂUݾ·õqôóTâñ‹Ÿ¬½Ê½«ÙÈÏó‹5£uR!v@BpûÚ†XLôqïPlzE™)¶ÒjÙ„q%6(À2ÙyR„§.þ[A Úi¦ €»Ò"î +‘i~;¬iÇ›| ¦3=?ï`¹6Ãlݺ^)¬× ._$þ@†ƒ™Kɯ0Abµæ)ÖÔ¨¶Ëh3†± ÙsnTíT‘e† $T½D'RÒIÁh€Úm`Š0B !DC@‚ЩFÁÂ@BDwRaô „®´¿Ö5u™YœMÿüÖfKÌØ74­†K¦Ë±n]_ýšœÏ :ïì{M ùA¢¡P`L¶¦ÛÆ" ;~Ü4éjõé&†nÂâ˜LÏkhR¨zHmÙpå¤ÙfƒDgR%Ë Zd É ™däÛ#)8¹LâSäÝjÐ.\Iêàt +¢ïüþˆMº–):óÔZ!‡_È©+ÓŒ¹ \Wœ‘*Õ~` DÔžÛ¯ÈJZ+XyuÞ†L‚--¸ÿ†ºWáSCÍ‹vÀ‚±"ZÓ 2æ“~0ˆgû$¤¨ $ˆ»3íòÒ +í1ŽëºÌ¬Êçn¿Ìõfg«39_ï©[b´U¸½Sá/"èKÿ3³þ«3=½ÝfdK9ÚÉpU\M ý6”-€Ä¦š«–H)ßvï%¿Ýf=˜0«÷ì†Ó¤w™Š ÿÏfd®jI${z¾iIÊß.f¦¢ÿ +™} 6 4Ô†á™i¦Ê3NŠ] “jS#üÚêi;ð/ùz„˦¶†Ã4Ñ$U3*nþê|æ{ªý!˜ÍIzß/Øy¶³¦e*ñ Ð×­j@ëÃ!B&ˆ +jrZ·’“-Ò´êj`‚üŠuP OôÄÑÌ–ƒ"•>ÿ2ˆ‰¤U` Ìa‡i `ÄJD´áYº'Va@‹ŽËþH<Љ)ÛI­S ڤʄ6é¶«¡ø‡çvKÿ÷h·£jgõD§t*Ï;'§°ž‰E['½*Ñ«‰h¤ªÉ¶1¨?ŽL@tA°æªµN‚·â…™³½‘‰¸’±!7 ¨6ŒöCþ¸ÛEJÖêüFEIeŒ+@ âT»JÓóiîšI ÞABÛ9Pêÿøî±ÝÖef_?íÖf{¹™êÌ̬ÌËm±Eè«þ·í÷Õ™Ÿà9þfff«ÙžÌ‘ÜÌÌÙæ·’\IÿÿöGº‡úxêS»·aðm†g¶ÚUú5ü†22R'ŸŒÞ²U†šþùÜ©‡È¡QêÌÌÎÿ¯Ó©Ì̈ +ÿ÷³33Ûçƒ/}ËÍëÜØW*7˜, žÿ?î+[¹§SÞ¹l¨\ZKÃ& âÕÉ~!9.Ìÿ32s°fdRçú¼þ+ÀÝÂW ðÁ(a*òë*í¯ÿÖ™3 ˆÝóbØ?û8læ{d¦e=_³þæfcäTfMfff{_¦kfffOE·þfff{#$ :žï¹™¿óØ+=™Ë.w“›òrËþÕ\÷=?–ÄRƒ<ýéx/o†[ØåÐÛ>‰wüÕÚmªGl†¬‡ÙƪO÷±µ©ˆ +”[­¿mi0ªËsÏÐxû-\­æe¯ÝmÏQÝr«Ì"?©>9«¤MwmPËP÷™þMþ³bÐ!½n3=ÿ§8DlšÎNj;ß.`‡wA´óŸ÷(~3Ì$›}Þ`ÌÏòäCôûÖNg7•&7¾Éžï+Ùîÿb“ršîêÞfÿÌîeÿ_¦‚)*ÝÖï=¿òý‘¿0 gšÁ™šÑàž®¼DžžžÏãÕ™øþ*]²ù›uš‘ûÃC·Yª÷”,—IÞlK]ò@ˆìa¢eioòª•ù†14±´-Aÿ`R„€Cœ‰x•M@ò †L'Plÿr•Mƒd2*l’qãÓî¸"¤@l¦Šý´üCU ¡¥sRÐå¹hÜ +Ÿä©U‰§Óq¸åÏåˆ vOKo‰”Hv› Spå³Á 5ý´G“¸@íî‡ vŒšw© B$:¦b -9¨.R£¸ü§Û>m¨iܳû/^i¢Z €'?ŸTiI ˆ¶v[Äôã@mí€ÕÚ,±°ôWòöPwi·ƒÛÔ‘EêhE*¶ü'P SnZ1§:næ×¬½Ò‘2ÔÇNІD´Ú"aTËŠ¶C>nß1T§%ÈRÔƒ :0* {zˆáê…©Ø÷hTà!`mÚ‰Ìa]†Ÿ­ß?,~;¤Ï¤ëm»]Øè"/ØÓ>êï¬N•ƒo°ƒ%2jgŽ•)<·©þ6ª’[þ—Fý5%§Â2CµÇ|±Tb§™£Ì±¥H‰ÕP vVɺÞrÉDT‡Å'\$<P*7FnßHvý¥ÂBþ÷¿î®Íh]iÙˆi¦Ñ:àï?(Y0Jö“;¡ +ü-;¡)ò&Ñ-\ÿQS[„š@K›üP ÊCEÔqô5Ÿ¥gTxÐèõÓK¾+ÓX@ÏÃðl5f'ikMPÀ´üÀ‚-Yü7ø0+¡›…2D¶íV¦‘³Ðï I²/¤[ m¼€eÀ¶Ý“ã²nÝ"Ýî¥coÍ>ÌþŠb“F“»M§âväüšÕ+5?ŽëÝfVgù™u™™™™™™™Y™Ší]ªÊÌî÷Ùö™¼Ïfw332³3331ÿ™™™ž1™™™˜}™™žÌÍœÌÍÎwþÿ³ýÖè/ÿåïBЩ涠¤5’Ï0tU{üýÖóß©wýo&ÿÎû7Ôÿäv"s3ÞÖgþ#9¼Ìÿ3˼ÿšÌÌÌÌËÈå:ÞfffffúÃØ¬ÌÌÌ̘ò–ffffg}³ù‡™þffff`hÞgs33±"¸eï3233+Ôoÿ*×s39¿~O?ˆ=ÞFÆŸ÷¤ZðÌÜ“D1¿n³×SŒëÓãËþL4í4Úl™`Ô½™¥Re¬ª à/¢²è"uïl{Oo¨ß*RØ9l™LcWœù[³Ù2’ÇP?íøûQÈÐoÇæñÕ íá8t‘AÿSéîîñ°už£Xºòk|'tó§Ù&n²³?÷ù]é÷…#}f_¯6»Ÿæú.ÕÈ1/ó33yŸï"3giW³=ë_çùýfm¬Ëq©§¬÷ðsüÁþ“]ÌØ„I€s#Ì÷»™ï{w.·^ÏSŸÿ§¼Þfg³+¾ÏLDgs¬ÖfwÞÉÿzö©y]»Íûÿoç#;5åa'%Ç·Y™ìÌÌÍæ1Ô@+1k#¿ÿ™¯f³þßÿ¿òAt+1ÿ—þíæTfzr·n,ïüÏff›Þlo+d=ßþæffdú +k!kÆÿÞ_«¹ÜM"+÷ܾïg·+x‚ºO$ØÈyK`é­Pu/AÍ£˜X4pŽÕKƒ4ØŠ·‡×Pº*b ×ê¹ Ž&ÓºŸ“6@ÿ + œ‘ž +Äš©²³ÆÜï +=X"¤ÓÄë`öI¸ƒÈJ-rH€¿À©©zO]…v@n…"«j`¨ã¤I3m G•òŸûMòDº¶=T?kÓRH"À-hµ‚NR˜š_¶›¿éÛ¥·Üü•ÿ|•Ë(Ôp5¯"À} Ò¡S\”‹(éfR§â±­#à6Ú|pœ®4£²(œÜ3¥½4MAÁ/µ%˜OþW"íÛ- %¶A…thn³n6…è˧bMd9J­¯ÂK…ºOŸBŽ6£yî®bÃÚñþ zkQãýÝÙéP‚u“i$ÿåëýÕ¼‹(‚Œ³¥WÉ ËüûRà ‘Y¦ÒO{wªç‹þêxÀž$’ܵÈIþê?Üt-Ô¢gɯù\—ÅÞ½q6víVìúy/ƒHó΄~÷Eþ8·<‚ MÙ&iµÔóý½/BÛpÒ÷úÔk‡Äü—hÅI6æ¥ròy¡±oPíóÂ(Aò×ã_òNŸpóº Z­hÜ¢.±ŽþfùÊ´R<­yGõÛ ø_„(G¹¸Ö™Ïc¬ sÑ"´Ÿ#ÜÙ}˜'¼÷ì£Ìfóv‚È—Qz_îŸõœ’Kwi¦Eã׿äóœ9ZüÈNø+®ÁgÐú›®xÛ™ó®*þêLÀZ Ùï•nÕÉì-DÃæÐ90™™=TB<ÐÉ|fŸ,ïφ ßáT +ãwéŸ÷é§ü!×'p ‡~ñ•mâµ øôà/Øâ|ièÏ•pzÍ÷û/HBº!ñ››#X +AïG|s_ëùÊ0£”™N]KÔK-nç\ŒÔÙlÁ "¨pÉIÕ5ÌÄí2@&Ø.IÔ‰m4Ùô¾‚±]vŒz“Ú±ÍwÄS «jÿ}ÆœþGþÀ+nŽÌ·||–Àfa8&©í’LѾÄe‹ZhìTž‘f{3 Ô%s6@©‘Ú®!‘bÏØÕ‡µ #¡M‹"®· ô sdà4C· Åi¾ìòíèâìz ›ª +È2*)ÚM–¸!¦Ñà7kI‘Bµu=d7Q+@‹mV€Mºš€*œn•@J‘ +¼[wɆÕ9©ÊM‘hÍM«R-o +Òö¦þ;¬wu™Y™™Ÿÿ™™™™™™™™™ŽîîÝªÎæff{3333+3333+3333+3333Ï3333+3333ffffÌÌÌÌZ5ž›¬Ï÷ig¯¾Èÿ~ÿæ#'2kÙ›Ïï;sÌÌÏóüÿ31O}ìÌögù•™™ÿu™¼ÌÌÌÏfgþ·ÜÌÿ33?ÌÌÎæVgù™™™™þg¿ªÌÌÌÌÌÌÌþ·¯ûŸæffffó?¼Ïfffffó3ùÎæffffffwÞó33337™3êòîffffgùŸëç·YÜÌÌÌÏUíå÷335™›öŒ5Îë33}Þetw­óg2wÿ³+úçûöò¹ìÞá;´•¦š´\vjy†¥XÝ¿åld»¿WSÿÏð÷0dÞzü÷¾ÚcǼ¡ý ɪÏm×ù=ÐÌÔ,Ṍ›Ú wØ(àZ-5+rz»ß~rdÞˆº©¬#Ó[ÏfMwý÷Y’|•K6½ýF{ñ^žâêΓû`WGý÷®½Š»ëåg2ðâîIñ=®èôfûÝëÕÿùÛÌåörOöíGýN¿Ïóþî³ÝŸûsŸï$G³{ºß_s¹™Éæfky +…âw˜°óÞÌÌî{?Íæfg“¼Â'ü•ØîoüÏó;žÌö·ÿ7N²ó»œÌöffó7›ÌÍdø*5±“œ¼Ìöfffg³3üÌÂ©ÊØ'7YœÌÌÎæfó™•·õ`B¬ÎfwüÌÌÌîw;˜ ö"+øÃ 7™žÌî™™ÜÌüãºz=y‹¯3333ÛÏÿ÷u¸Ìvý­‡9™™þg¿ÌÌïù™‹aõ£-ß,Þffgsg3ÚÍû6ä˜rsñìÏfg}ÌÌÌÌÞd£ú`ß2Ÿù™þffoÙ¼ï¿dãÊ@oÙ¼®çw™¾ïüÌ™÷³³¨ÿ‹‹üÿ=Y™ÜÌÌÏzr43¦»èÌÏfùéYžÎû1;Ž*Ü•;Ï ¨Êß»?ä{þóyÿþõç=ü÷Ó™üs3yÝåmça&æpUeF{;—½gº:ùf²iy éþí<œqª0A!—^¯\L˜ƒu5"½Ÿï'tdÑ)øÉ3r’áühûÒ1<’¢Ndá©·jX&·7aêß%<ñQ$ÑËLÍ²Š›/Ë–•ÍЧîÙ+þ&o€†Ú"§©¡ÿ—m\ çvµWðÐ$»²hè7Ú瓎\ÔmC×òXDGC£î´SÐ&A€j!%ù\0Óý.?«­d5þ­áD!|ß4Þ¤J¾_ÎfÀÝ¥¥vcc]*¦±’8åø·©_Â:¶Ä ïã q¨ ÒAÿ–*ù*âú¼QŽþ„‘üi¥f•ÚuR›º ÌžüÂôî}çÒ{_ëCoßʵ| ÄÅÚ)!ÔîÚGJ­ŠÕ êçðm×ê„Ïÿ* mûOIé„û©\Zc´“€íÊ´xœ*2˜$_¹†è3É{Øxå¯ÿŸæÛºäK<´ÑNä +?­azZãÃäAˆ“~ò¥Ç0pã^ô:/ƒÿ¬¥Ž›Wvì1húzÕKL,’[á0 ½-Z ÿ\­ vå8Ú#«×îܾ­gæ…ß%¦àïÁøjº >çsG¼‡Œ:Oÿß‹Ñÿõ@È}°ˆ1Ûã rt·:%‘×óÖÈ%¤ôÝ÷8«¯´ß„;-¸ìär4D°ÿ•ÛœÏ'Î/yœEÇâ%ì?ól8çü!ËþçÓïçÃkÚÿ?ÊsMWúõ¾xÁüzÓ2e>3+¸AÀï¹½F¢&êÎO÷:ïÆ¢3QÁIòߌèÛ€AŸÿÚå­uÃõ4G/œÕ¾ïÄ¢4õpï½?..ör$ÛÑÍ“o' ~ +*í~?@³¶5¢yØNœFæÇ=üoò4#·ËÏrÞž›n’ÐÞ¿P¦u¡~{}~£­tÂe-ûÄÚ¼ï‘î½|µ·Ÿû?ö¶}U¹ŽA 8ÅÕ~DÆìqýê$Q6kÜZýsh²Î)ß´ÿßzÑ•Z³ÉÛüys_æï‡NwWcÛHô<¸µu­/óþ¨õóŸ»ÿk·%h‹NG„0…žŠh]P…ŠlÆ®ÿýpœ½'E7A+3ªçèÔ–¼ùA¿ûßÖ^„Žv Á¦šmµŠ²²¢£6PÜê`G}ýk©_äh?Go†¹¿?úÏ ÌÝVØ#ʹ+œÑè‹Fý=”´|¦q|\ÿ +L4ÁÜ÷‚gðN Ä‹Úÿ±.¹8;ÓÎæîoFu¯å#îÎiú¼Í='`VÄíÍLt×¹5”0ˆ¾=ŽÊÈ€‰w"ƒd‘¸DÅHÀ‚E¡si =´<Ùü4€†¨àCéçÐÏðôQÁ²á@ø@Ä #lM0*äÞPÜ d!LA©•$,Á,ÉhÁ@_Ðd@z 0µ&` ÄÖ·a#ø,"'p3Œªìï †K"‘&KU=Å¢ÂĽð ¨@ÐÄ̾~dŠ4…øÉàØPl€àC3çÄAHØ4A® P¢@ôáÂV€¸M¡ú˜!„Úˆa ²†€@! ?BN–Ñ]‘ŸõnÑx§ïÕF(&‚ ‚-5 qbA=€•<‚ +9ð@£Y”Ï’Á§ºyÓ\&îÔÂÙÐÚàp bxÒî|Z"\Ù æ`L®ägYö$Ä ‡)ø VéH ò@)â‚k½AË)-슪0<¨ø¾‰º”€0]¹< ’Æj *uLë°Èœ3à„GQ+%uBô…”àS vÙtd€öi¢RÏÃÃr ¡>€!ú( PÕV/JÆ'‚˜ìÌy;Ð[D +‰Ó, ÄÈê.hÞÀ “ìã-båðÎ×6µ 5¨ +6W2~zL¨~…’Æöj œ¹Ù˜ÏxÄ9gª¢ r I yJ+IŠgÚùù8ÊÓ.Ìlr4RŒ ML{x>ª˜Å?Ù* MÍ=›‹²8Ƥ==šVlHÌq9©è È A<ÈvPÎ\kà0‰.Ùw“Ï21ƒAg2ç[ðð4sä´ÖEñ [$»åÛš6HJeV/°bc—³ ´ k@†âf8ÖSÓ(¢ Íf`5EaØÌr¸8ÜHÊ/wÊ‚ VÈ· $Á0 i cDÜÅFLNSB¦[ó\«Ü¤{ôÑ!¸&§-àõÖOÍ0GÔJ°aψ:ûwǶ“‰?׋#ƒïV p€A€€@ÍÒJo~Ìk.*hVgô”‡ßZ?Ãx‰¬wÙ+5’’xØÀ¹˜^Ùl¶Nÿêøn:L‰2:¾þñD¢ 4Rá:,@  Åü¬­žÁ6Ü]; ›±AI  ølÆ<éHÀ@%*’W842~ èGæ€y^ÁŒémŸÚ×ü¶¯¿«#d°†@Dwƈ2Ãèè2ðð7iPù˜ ðÝÒÄUâ ''IP@9A0@$!@Nòe"“ uøŸ¶bæð 9@;YŸ%Rq p_hf Àµ;dê³Ù B´Ôø‘Am9IwÑÞŠ HJ‹(H@‰1 é}CK—X,P8À§Ú:‹-kFxTŒi ÚHèÁ1tC gÙ´ø0P® W>3„‰ž¥|oF°2òäIA* VÔƒ8á\*ÿTEÉpÛG‘.sÕ˜Bs +@v 0ÏK‘IÚ¼lϾŽ?‰£èD Xwï`ƒÇf*¸F0„éùîœO5c%‚Ï b 鬅ô¤djà^¾”«ïî^*æSa0 ¨5ú‡ázÕâXªÂfS+°µË>Æ4†îAÅ"nGU®ksãh„TYd#¬Û)ݲ½Q<·ËXƒvö¤›H@’ ,6ŠT F£óðM©;µ MÑŸ¢ê-¬êT$OWW­¨"pD +L1ôB%uÄ<4M`ÏGÛ3F‘¼lÓh‘£èr4HÔF«‡HÁkÞÙhmPÙq'ë«¿ÚCðH ‚~Å Êà*ÁAd±(/­„à W>Ì9òOG•6ŸòÁØ» Ø. £åyÜ)x#prÈ +SšŽÚHÿÐP”lA¸-x‹mÎK~æd‚9©i×Ò2³…YËX(âøÑ¥g]µå܆(ŠSCüÙÞØ+ý + € Ó·? /ŤwA<Žýí‹—˜˜ŒB¡¡HÂè™û#µ ¡DVlvíBþ\,€ø¦õÂF©ð±ÍEÊ{íqÌÀìÂjzÌZ@^à«ÓÅõ ‰ÂnŸå×ñJ…„ËeLBPIÐ’:#áî# ¯ É÷„PÙ˜÷ïÑVX\É2ñ p²3‚0ô‚À¾ËAÇœ *Ô,ç¸`Y‡¦LËý&#„Ûáä¦ ¼Ç‚­aö0@í€KÀeã€ãèT@6š¥<Ì¡)€”áX´3‰îcKO4+Õ°sä~x„ ¦°tøËp—¸O;á ²#›ÀÀ€€0`à )m¨HÌwxL"™X6¾"„†.o ¦ €4‰ÍÐ#4v;Ø +0q©ÅDÈ0²pæŽ,Ñ<"@ QÉ,—`U W‰ Sìxû»J_VsŒF%È>MKÞ’„ó&P +€  ÈDE“ºà< %hƒ-(ÃÍ®X‰^<ÑA¢1@jB(â,HQçMWH¡Ú„ ¦ðz=LA7pÀw¸˜€€àI›kÁ@Hð0#áz! `Ó™…•…b`mÃ…#Å4äD¨6àlB¬½“ì  ƒ×5Dæ  I(p$ Ö#ƒ u¡"£›·q|†J@ƒÀ,¢A'h@ª€Ô¤˜1 \…3Y‹€Æ À ÖYU ,½0D £A O¶âElPä€ÆÌ€Ñ7ÊÈÆ0”­ÄŠpDyˆ«`à Ätƒ5) Ä€0%EçÃÓ%Ûs™D_ú ,ÊV¡€êHÕ€zq&ü.ø>D%ôü݈np3€ÂrhpÐE< @;@H!* ', ¢, €`L½àf§>“@#¹t‚ÀàÃb8ÿ0ò#!ƒ_;—À3" ÄÀ„¨»ãÀEPì¸hÌÈÆäà•"ÈÀL2¨ þ¤|0È53K©âÚ` ڨƕ€ƒd0­=ÜòóAÉó7ðo3ÒàÊûD«>œ ”ÿ„•ßÀ¼{8 +ñúˆ»îñ"Ñ' "¯èöîˆßreÅ“½£1;?#ÈçÁþ*<;ÎOFFœtÀ+­?¢iÎj}t1ÀÆl¥-د{3ì8W=b“ó5GÆ^`ºŒ}ä3ûêÚšÆ'ȯúá ¤žý Hjm‹t°ÿ¯ÎÚ¦ß (xNððX΀ë#]æÚ@i½ØJ.ð€û”m/Ûò‡>ˆž±ñæ’OSAµÈÄyÞ¬b`±ûÃç=Áê?A—ŽÜÜðX” à@k¹E0¯H<¬¡.4T ¡¡ÓæLïóY@¬HFˆ}0/l¥t-ÎÔh G³u}áñLý§‡kÒÜê ÷OpÄYÒ“áÒZ$"ƒ ›ãx¾ÕŸ_cÌô§¾ç<þË!‰#‚ +hÍuRÇ>ìµKÈb½A6ì>cE®~5é8l³ŒÞ6uÇ;2ßÔñÐ~y-塞Ԉ0Ší€Ð;÷y/ìŸ'¬Ã¼_Å…Ÿ“D’Ã^ƒ“M¥âÒѱ·*ÐØÆÎç™Sà $ +‹.û§O­z]ŠØmÁs()ãÆô QÝ’÷é´ÐTi¤ÝO“Æ-š:\Q;pÂq‹•Æ3!ÿ<Êß/½Þn¹R‡[´pVÿë¶ÆËjÓ±øÕ˜]ü÷^YÊ—¡H+P¹çØ8¬ër‹Ýñ[ëOk~þ­'âþ2Ò‹ %% ¨ÒréŒÒ|õÝS«ú¯ß©úÊ} ÷ù»ñP¤‘q„IȬÀoîQY«+y—|‘PIÓ³ä_:UÿÍù¹¤K„yÈ`§Ë%JÍRÈdfÔìÒ„õp#HS¸ÃKîÞÿ¨[ùkµ§¯ÍNâvGŽ¢T‡æ]SyÂ+3L/QjÅXÄ‹°Go²tÚ8mêQè-`E ›CQ4™0žYô4Œ.‹|¸^¯—ë5èÕ[ïcUåò|¯Q‹HÀ⪇­¡ ß0Ž„·Âﺥf™&Èfî1Pâz=¦=ý¦sxÃ/íçãpè¾Kx=}.ášÓ‰Sî7 ñÜ0ŠøÏß•[h°&î'ïJ„f¸2ã¼&œFó*i°fŒw²!±ÍŠÁØÝ[ì£à…&FñvÞÛhà'VbF´½­ÿ¾tN_„û}U÷4¯ÎYƒOæÓvõ5Ú—h¥Íø»J±Ë@Ú¥W“šð8€†ã“ä™_þ&Ö0ƒÙxòÜç ÑÓËJäçª8KÙóü™ ¯3Ë?ä|‹/Á!ÉÒkšº.ÀÒì~¢¢©«¯%KÄòÁ3xã´dú·ðž¥ ¬ W¤7·ü‘tά±=Ç×£%WضYèøêâ$ùB$[4@›ìÿ_ÛwéÑ©2`*+•_ÖøwÅrèD®B/ž¸'˜?¼°D“Õ“Øá$„JÃb­a¾È-Ü$1=Oû ÿ‹¶V¶¶ R;_ÏÍÖ>~‡ nhàê‰'¿î¸Ó¨_%:hkONºþ”L¾‹ÔÁLµújð±'˼ ”êGQ‹qZæ¬Ë ½¶p +>ì 9ò².Ô_ø Üs·!5~%C7{Ê‚__ Fù³üAPy 3‡ VY)y D†þæÄ+ýn\¶izóH¶…@Ìs¯—°d5äŶó?0#!9¸Zd ”Ì<?ÊîXºÚr¿® +òdD”Ñ“ÿ­æ>ˆ ±~´o<~™?\€Æënà^(¬DªÁï1ÑìVÍ@?À6½ïš¶svGŠ*I¶4üÄVi¤àyÚ\ÇŒ.ƒ½Ó;}(nô­œÝü>×»ç|ÏsUÃKßxc(†ÂˆUéÏzIvòYíK|·„R£OÂBóï4Ìߎ¨Ôçlmö:¡¢—>Ç2ÁuÓòÚïsä5÷½Õ³>Å&ááOÿÉÞêTyÒÆÃŒ!~*…«Ÿ“ËgåŒÚOþ¹þî¶ÉroQ’«õŒõ‰Ày¾ +`³ÿs½QëíKkÕ»Lš×ßùá³.ŠL?Y@Ük¢÷ ‘¼ YE矑ABw³†2Ç‘”ªµn/ýtñƒ_µ4/ÈÃ<½ûÖ{$%ñìjü7C¼%ëAÃ^²³Hä¾ ÀèKРüF=XZgÜ„EŠœÐ"¼óó=ÝÎR>æ½½Þ˜2Ö¦A7¸›¡è70µëÔ*žåÊXè® +•{aYc¥¯´;à.¢î,Fß_ØßŠ-Û‚¾yÒ`•}sË]ósõÿîïdžcùªI.ÝEN•¦¼û´`ˆé¼RË9³»±@ +=&,|—ÑãÅpèµZÕq/üF‹ž Ü¼´­ ÿN±LBÎ9>€œ ¤I!&Ÿ +ïûeE]%9Âlèz,Ù¯Üô(@5NÄ€öj’kegè‡ \óœçßN1dÈ:úÿ¥ô€iö"kDk‡}íqŒyÿ3öm•ªŽ(•üZɺ?¥¾¡þñ9}®:gÂô¿Ôùÿÿ¹©¬ 82†xý“<ý:4‰þ⟵sÂ..ˆ5B2Vì“sĤÀ°®E´ãؼץvÒ G~Ò“µ£¶AÎÓ”˜¿ð–·™@Á^³ð†¢4Ù½¦küø~»ïþ…ç¦k²‹£J¢}Fy¯‘åý5ûüh¿Ó7—/ói_ìì¾êOámt<‘µŸ¸->äåSÌ0j/ØBÀ~åòØà¿›[–‘Cì„Û— «?V™9´kLÏ‚Å-×$wö¿a#÷AVn÷8Ü=äû_ôRèßÂ{ÿú*j÷H“Þ.ƒJ)úDZ}0$hú +×§~UŸÉFÚÛxÛZÚÏwt°û1¹pÌ"ÁË0=lòOûùz _†–E{úÛ"ÔÔ+o†dÞ¸ Â{Ÿ‹sÀMÛÈ ÂûôÍàܼÊ[\Z9§Ðç{¿3Ë{ö+¸þïQW¯)üKfíÆÍ]»Ù©ñ'í¼3Ï,ŒÜïù¸@–eÊîÒ;K|— +ë÷> l_"[äqÓ +#TRú¿´zóìNjIY€³‰»ÕnêÌ›;8s®ªùí.׃|ÚuúÉ7ñóR2ÕO¡ÎÆ7­¿ç]~îøíÓÿ7ëîš\-‘Zy—7Çm-…O÷ÊHt+ 1ÓWi_ëUž»(ºG·íýºXpº”N1×ã´øxóÏJÈý9s(øè|:wqûägýÐñ “-°mMºR ²o¸—J7¤C¿ôµŸPï LöïþÒ;&XŽÁ°¿¿\{ÿ +×–´œ“Īþq¦âzÚ]b½çc¶"²þ·=Ûï{õo쮇C +úÈ<¿óýz ؽ}¹ùLY8[ˆ?ö3ï-0Au/9RÎjø•'ˆ†/˜o lL8|Ïÿ¿ý;ïúüÈ{3|'ã ^„þ€ceÚûXÿÕå3¨®¾_ÏÛ¥ÊÕ^F%ηçÙ?¾ñ4CY¿)þ>ç»iƒ°±&÷ÁÞkÔùóÍ•1DþÈÿWÝ«¶¸@=á¾ÈŸ÷~´õMŸZó¼ô¥Ñ”ýô¹¾'ÿ‹A¢d¾T\ˆmŽ…<øÃbàÏñ˜T÷~ó Äé9Íõ£+ú~‡7~W‡<>¿¯Ÿ®SB¶ãu66œŽæ77üþíÃkŲ+ÅÅVç_uâ{kB×6’nóF%zŸßóÞB ëv»w¬Cÿ½ ÊÜ Ú¢þŽ#}ê !fKm´ÕÙ„q0Ø£[[…•(4åÄ—üÚ ši¦¢ ÞÈ6n$‚b¤ÛoñÝcHÿ%ð4ÆfOù²ä¦v/mf„ÛÁ…‹ E/&—˜ þ+~4ësS†ÚE°ÆWí6É!¾£!«U$EšòPØ€p¡ù„Cj€$éŒJßüI5ˆ•"¨2uQÉ"$£ù6 «l’`€-ƒRKVlI·o©¦šüwXÕÖef>q7ÿóY™/2A¹¥l2]6oñl:¿ú?59ž‚ußüƒ] tƒá B…A‚(mÝM·×"­ûøiÐ^×ò@±›ð\˜ÎëmML^…CmYpÓIÞÈ,ͨLþ‚Ôèµi! Èu7r/¡8öé«ýªCeãüb¾Ã,ùÁ‰[x!„;©Œd5ûºš˜!ÚdÿÉ-B2fg­z« I7gd“FÝÚr„Œ4I„‰Œ&ƒcŒ¿Ø·åÓ sLCZ 9üà;BPä€Gṓç©6"6Á;dùÛ…h餎U.´EWô§s$ò‰ª$—Umª'b4›%»²á~;¬jë2³+ºÿ3Õ™ž¬ÍŠÿ}JÛJn/MÑ7ÞÛ¿ó;ïõY™ì;¬ÎÆÙ;ÁT§Ôƒð©jîÚþå‚¥=ŒµüÚþû™R`‚«Õ솚u'y˜ ¿æffïšìÁ˜Žû¾hZîî{J Šdu°aµ²ÜYÓM³t²ZÝ †€B¼È3ËD„ês³~$PoA¦v«£¡>ÊF­Põк“ªÞo7K$ƒ0Ï3­˜ËÖò쾸ÆÖDZ"Èi’½æùV;$o ~#¤Õzê`3ø“mc1hZwÙ0‹©Ñ€º&Fb"Ü4=SSw™;)Y—DÖå£#Ô@8›&6E0Ý€*¬¶É³wm¥~²äÔÀh‘B›$Ùžé1-šM¹ÚA{i[m¶ÅA¢I£ýwñm4…]p"úBÑýL“!¦—4B~Õ-XWc©Ø­yZ°ô‹7}ÝM¥ J¶¹Ú<%Ü–û_Ã6‹RIÅT-L M²&A—i¦ë€q–ÉÒeí˜4€wÞÕ–æ:D¸÷e¥6¤$À,ò0Êsvݺm=2ÚÒD†Ñ¦ÒJ«NTZmÇïãºÇwY•™ÿn³3Õ™ž¼Ìõff+mŠz*ÿqÍ÷Ü1™—žÿüÌÌÍVffdÆó3{<ÿ;þL8?ÎÀå!þ¯­Û´PÃàÜ34“J³¿Èdˆ†?×»9ÚÉVROüÌÎä>EÛ¬ÌÌÏõúu‡32Nä‹yžÌÌ÷¶$›Þg³ûØ&;™Ë‰s¿æ¢òn—þTžõ¦À…¸g‰éXþö8¹þFÜÀwü…v‰©CôðÐF¤,gì›pC°SÄaÒ þWS¡â?©ïòŸÿ°"Ûü+ÕnA£'½õÈÀ@ØOÿÿž5±X:¨:ÚHz®IŒDkÙ’òs`€Ø_Фo^<Ì®pô@í‘™—ïvšy¶Ï³}ήZþR*±ÿ™œÈÿ—˜+žØ¬É䞬ŽÖL9·ýº÷ù•Ü¥ø·Íoÿ cˆnÑY5ëÿj4Ȇb+ÖFa—Zé‹P‡ ã{¤*ˆÂBÆŸâ‡F™Ù Eº˜¦¢±M‹!sÅYès­R÷ÿR—Ý=of2Dº!$´¬´ºá4Û.ÕVî&?öçe†Ô4”ÙÍ6®#”GcÜ´Ó›"o\*Y&4EhðZB+‘ÙnZ€Ô€vƒÛmZSÉ@Vœãá ä†“؇ù ‡*œ±h¯çÀ†ÉL¸$·™ÈÚi'»uþ¥IM6¦(*Ê} žƒ@--Ck¢pÀ„›w:Ò=a±i'Í]aŠòý(7Z^ͱµ Æ¤žwßÙ¤û¯ä;tÚ×–ÕÃi ׽ߵ›'‡bÌ5üÁ®9'@PRZ–Ñz ÑBÏ 5ÔqÕÂð·isq'“¢íx¢IrŸÚ4ˆ#{ló)LÞÓ%²ÜÇûXK*@AVSrñ‹ Ž]à$’6ƒë`$Ù.4“dW‹  ‚H‰%äÊ2›E¦ÓfÓ~hÙ[´@âl‚6Ún¼¸r¡6C!Ú¶ŽZE¢ +m'MÂÉý†íÌ¢'ñÝc»¬ÊÌÿßåÖfgs3ßæfVfb»wXr;­ÿ¿o<»™™™˜s3335ÜÌÌÉŒÌÌ̃ìÌÌöw²s343·Ïõìþ+*î-xB Ð0€ÁÛÿùÛ·ÿ®/óÓ¸h€DkÝÿ×yùg!ç³üÏ/9óÐwÿù™™—Ø­ÿ¼ÌÌÌï³ôâ³33378.ÿÌÌÌÌÎäÀ¸Îï33û04o3¹™ïàH2÷üÿ‘þoÕ5Oÿ*.ç½æ×æ«f–Œ sý¦¼;“Ã*ˆ{öÞMÐÆ–;þL5i6‡rq¦ˆ¥`‡úÚþp…üìx|; 7=vkÀMAŒ“+÷ÌÆ×üÜM«I©ÌÁB"p¹Áþ5B¾uÀzDÈêîIÕ™nPŠ¿KþÏùÛ¼ÿ›*Ú!ÿéÿ=øÿ3Bà»Iÿ¼üb±} zý4¿Í‡™™™›¬0oÉ÷Ù¬ÿyžÙ{UÏî§ü2o33ÿÿü“™œ®æfz36—ŽÚk0þ³?î{3=šÎaž4}5¼ÌéÏ›Êî3Õ·iï'¹þgù›žåâ"øÿžÏf¿ŒÏëwº•n,ï7œÌÙ‚,5üT¾û?Õnra¬Ÿýþo˜Õ`m8»Œ­À9íÍþE»NÖÄ6¬ÌM,MEŒñ‚ëóÿ„dö-bIAw*ÄŽæ*VGøl*C^häÕJ2­R5ÙÅ$¹G3ž1 µ&s-L©wSBbÑ[P7,ô4@„O_9¥Än; rHNa;ŽHüÅ¥"4à´Û®p6òÜeÀŸ&A-H* 8™†ª}Ôÿ°ìM¤í¨õ÷uù*7QTSpXI*($a»²4‰¦Ip™b~Pݳ¦¬BP¸ÐJ_ *‘e }äâl5VA–Ý»œñå$æ(mþ<<qév­rª^D`^ÆK=í)AšïJð4‹ä½*R2^¡fýdÍ X}àtÇ{_7¸GuvÁÒvòs•æ)æ4xØF°8˜ý¸ë‡àézŽ•ÌCm‚?Þõ + n¨­Ç5ÇelôAë½êëpÙO¬Aü‡BÉZc ‡‘é×ó<ÔèîÌ‹Z¤Ç*GN¢Z¸ŒdxÎi´) 5'–‘õÞß+ÒlWB‚/..Šÿøž\î¸=}ÅN^ÍtA§BfOñ½Äãpô}u–äÐ!ÂC·?‘¨/W4f»mJª%hZp©³Ê_¨’‘o¹å@âò®oú†ÎÑ™"ºž~ލ#KDRvb+i´’h‰xµî^ºýV*hÓo®ÓyÚ&±JÃPêûé­Dû&˜ÒIU6„•jØ‹¾HçíÈIêÑ6¿î+Qh‚kÝ=Vಠö3¨`€ˆ!™•yýAiqÈ7ÌiÛ&ÕE W^ ~«NdHt -]õ!-0“¥`ë‘È ZMÖ]ÝÙÛÜ-¶­1r4-¿ÿ ‹´Ýþ¢Ý ÊVDéJ÷”ü ¢Ô{”ÓI¦Àï„¥gT9¤ml¤¨°:¿Ö;ºÌ¬Ïó2ó333333333ÝÝÝgsy™›9™™¼öVffffVffffVffff>æfffffff<Þffoffffn³ùUß ËYëï¿‹œÖÖbN"j²c~ŒÑïHyÿ½ÿ¿÷ùž°]çûÎÿþéÏiŸý½ï¹™™ìöí]ffÿÌÌÌϾgŽefffffd{÷Y™ìÌÌÌÌÿüÜ×3üÌÌÌÌÌå¿ò½™™™™™›ÊÍÿ›ÌÌÌÌÌÌiï333ÙÜÉÎTÖó3333þgç?öû¼ÌÌÍæMwýïk5™>ÌÉц‘Á™™¼Îa\دÖ÷ìÃu'oOY¿o—ÝÄ5všjÒjÌ!ì×ä;Òº’伃Æßf‡‰¡Ñ¡¤†5Q Gs߀w2ùd¥Äo+Nûíi«!~gnÎå +©Œg“y›ËEÞàŸLO ++ w×½fl'þÿɽ^6Ž¿ÞV sœÈ#³¬ÏVî3×FÔ]¶«ó±_¯ó&³„o|W¸ÁÏ÷Ûh¬ÏÿÌX⿇˜¢ï­`læë7ßóßæ™Þ[º˜cÿüŒë¼îfÏ~(÷06w¦‚uíg¯þ÷=™ÌÒ?çñT?ö;Ìïs7žÌÌŽçùëÕÆ ×}™5ìÏfgÿç¿ÏfÝäè4`ë3ùÜÿ?ÌÏw3$÷‘Gõ ?÷»ßóüÎæz3}ð†ÿ–aÆ«2½ÌÌÌÌÌ÷ûÉ×ûïøíR¯;¾gýÌÌÿ7ÜÌç{ÆŒB  +³·ìßs33¹™Ûÿ;Ì“+›ÿ{¯g³ýû¹¼¬Ì÷ø&½~¿kýFw=™ì­ïc÷^¨ÎëwÿýÌìþó~Ïk m,Ïg«Ù̬Ïó~ÃGu¬Ì÷ùß5ÜÏû¬É{ê|5úÝÿŸ|3"²ʯö`Tä÷y=Ý{ÒíÏóaÖ±U‘Kó“ßèÖJ¶{‹\¾é,ŸÕIÒf ï&»í¨¸š.ë¹½‡qzÝ–ìÁºcøvº6™2^j ܧS±>Ý×ÿŸoÉÖÆFÿb”þ^eCB‘,TÉílØ`»TÈ;‡iä»ìq´-Rkˆƒ óÎF)w!È!ܽ¶`3)][° õ AöËh¾"éž;.qê|Ò¼ÚŠ.¦¤ÀÛ6 SÓ„ÇöÿJ4Ûátmчn¹: +ç)˜{ióD™°ÛìO<½"©Õô”'à÷ 9×a³ÂM ·¤JkðÿÛüÖ“ÎGJ‚[uοpv­Íl@nˆÄ#Êx<émsRÁgÊ‘f˜‡ %T/KÚ­të’ïË‚Œ¥ Åh \ë:z;¿síêvø¨صêpùV]-V·Zq¸€·ú¹ƒÄš ò‰áÖAV?óEr˜ð˜õqK² ¢èŒ¯.ERýú—f‚4Ð:_ÉÊs“ÎYz,[MóNêí> Žø"¶ÈW÷þ9Îv#þ‡Þ9YåßÞõß¿Úïú'n’¶ÌM¦žÓÑ+týÈ•G*ìçýŒžçe­Cmƒ|ÆûP[æbXóÈ’[~¢ˆæË«ÎXå œ¬ÐQTćhr«7t ‰ +º(K¿Ej?zžÈOA3ÉÿL¿À¸Ÿ7Íuëdž™ïxÚ´ÓP ò9Zz]ö_ BáƒGó㻹ýŠ«B¶©z0+o»Öª;Í…~ü½ËZ¢R€YÊ9*¹ÍVº—;ì+µyWMé ÑwZãK²½?Ø­w³ÑXÿ„œ L ó¢[|sãÍèë‹·î´¨¿ÏY?úˆ‚b¨Ðh‡ë×´ã^ÈŽ‘±;Äëó§Ö¹Î!ËoúÙó,ø¡®w”ý™ @½;LÿÇE­û³ Èæžêî(ÔáÒŽ~^ÂeMqø"5³Þò·ýÉ^=Öðy¤ï@Ò)À2(gl¾wÙ® +“‘b+§º¸âÿH RØl~•—Ç{{ýÝ]èî ÎÿÅ‚8ç¬-¢¦®›ÖÉ¢?%2èí4÷C‹ÃÃ\°9¸ëš»ç~)ì‹âêÞ-Pé£ù¡bfÕÀ µ^zº·‚—ùsèüª¤7OšvÄ=`^»¿øÀiZþùÈìq²2Ox.G#bYîkƒmÐêöÚŽ9E£3Ý”ûšDLhHc˜t†ºÒfÁ0¿M¢ùÿ†u€-„À-°”³W$ÈÜ ,é"Ò¸Ž¢Ú;&­((…xCEpæköÄoÍ¥](L¿êj¤'Å0áT^k¡b¡Ê©Úg_ÿ¸@o.Pq +R ½ø÷òw*P €4‡Â*‰ÀIRnã„iZ’aM%`Êä˜rÔ-€TZ™?¥"n-QéA¥y-6ÓmWiZõ£ÝŠ Üƒ X6LFí+Û­˜ D+âi´wÊL½[³ -ö¤Ç.íé½ÄÌ©–¨þ!ÛhkŽ{SÿbÅwƺ¿Þ¸êï•!ëºhŸÿ ÁÅÚ ²@!£*ìŠ0ň  -o¹"!!5I³íÁEÿ(” é>"@8€7ö  !— +ݨ![ê(mñ‚@ª^‹(ž1 ¢Ä€o'x9@Húû`HËlB3'0ä + ,¾ô5 4€JÚE + íjÄà‡ 2ª ™Àér¢¨€âÀÐr Ù +îª' I¨t ;^IøR€îˆX ñ BˆÇ&›³® kqp€F“´Á€‰m›H¦  Îj`3pš²_ —°(­ÐHfÁð Ri€¢ +Y‚¤º½ 9ÂÁÊ«qºß¿è*0  ˆeºIDÙ@H¨3ï ÂÅ]2Dd$À@àY +m +!;MiAe +6uào4V +€@hÈ :U:Ä@ (…ˆ !^RB#¤ow é…(,‘P„ + |!¦: @Ú§cïÔcL),ÔüoZhÀD +Üe B €Ð/ÄKü$x ×%wÙÎÔÏû0É‘P@·¯ +ú2„J_4 |» ` Rgþwqû~\Z…Y€”±NQà°P@9.À‚ùXQqcÏ»²$ÚŸØ%é R› F2÷G‚]*ð@‚H‡«k‡­E2ª5°¤Oª•»a*²‰±S•ŽÍÂ…Ú¾R˜5 öþh\ú>ØO’pâ„3Ü|åxÕšÛþ^eÚB7eK1q²‡eɧàÉ]ÉóXÉŠA$F†@ ˆ_Gt€Ê@[ @÷ÚœØÝLùA¬¶H‹Ýûq’¼]®1@«Iœ Q¸r¬ì;HÅi[ ŽÐ4 \ü¾âC d¢ OA‰‰‚&“A €LéÆ6=1p”b)ß¶F¬· „@‚fâZ–¸I"]7 @r° j×s"—ârïŸÏqЈ+ÁÃúÀŽ,vò€¸”ª#@"×ÌPøLA5ëåqxi‚@´6Q—Ç  FὤZPöQn†„f;WëHJÎn1yYÂz …T…‡ÍjÀú^°ËJJëjVÀƒÜ˜FÔCÏci‰q:Aj­Ô1L˜P€ ~ BTâ=º5‘âÑ}-j<‰-dAɲ×k,D € @ò †f¶%à:S³nAØÕÉð#s¢[&„'ߣ@ BU Q˜¤ÎøDÎ왩©EK:´¥('ã‚aˆ3´a¤ÂS%PÁMAQ%¹O°õ¼}ÇV`Ñ \gzFdñ$ŒyîÁC=$YCÑ2*JàW± +!Ç;L\Wa)Z!×);ï[kìàdL~õY{0;` Os)¡3íUqèÊP-½£pÃY”s6|Ù´²ôP Š[Î2 $ÖLM}@‚Ðä²Úã1=8NüX¿-vJÄs”õŠç‹÷€`b‹ +s¿â[;ö¦Þ·_ûrˆçn§\my|·v màU›h‹0| ƒ¤åaû$°(ô•ÂyX¥g7Á¨À(_Jr @~ *É$È#zÞ·É ãÐ=¦]T•UJ—Í ƒÝÓ€ ÉõøˆÒcDã(–©Ë¡p¢MùE)@Ð+×ü» ÜD Èê(ÚºpÄ.ëëµ3BlÈÚE²(I´Eää +P +Hò4˜§PmªS+m.ð²ÌÁÐü +еCNŒ¦± p|ózn]bháj?Cz/Ý!™£H€ˆTEBp)úØ_ÚžUȺqL^H`KÍ¡¢•ׂ±——%RÅGt¦Ü5^Í;m (·nÚâ£ÕgJÙ÷¶Äðíɱ%* Õ³# +Hú ¸ mr¬Þ!±Å“±K9œ³jR\à+ùkE°"PbŒ@€@[ïµ@;sö)*µÑI€•Jãlç!°¤v|‹ˆ»¬ŒäfÑ0Oq=¥¹E‘ÎI†dðì„Üf»ù7Áßp `Sßbqz'ÙÁôò4âÏŸuÿŠöNLâ¤Å*dÆï;Ì„ »â Y:\_‘èq@E?rªdJÔPÛ! @œo¢È"!'Ãät…0É.Ix,)ë€l‡›] ¼2 +€˜pLЀèn¯W,øÐrÁ­h—’9öo“R]¹èeÉ"ªlEê— D²J~¢FÚÂ)ñ‰wº™sdY²…0¡Ä^´°>zб‡ Àžk¢*˜¯„wúÁ?v’!òr +Y¥Åะ‚%‘¤ÔF11•‹Œì¹î +* 팉ÑzB»q'+`ˆŒIFk¯v›¤º:«2XËu ¨)ˆ€£äcR£€À‘¶LŠÄTPâ´ì¢Ã*„‘2‘¥QL AtEdÈ•ÐHº…‰w Š"˜4Ò5?8¥y³Ž Bš!3àG"uÁ ‰¨Y`c'µU¨…½ˆøX¼/ˆ¨Äy9@TÐqXß/2¨¸LDÛH<˜;€ÈåMYs   ° É–çT"È#õ»û•%©¨ •ÂqœÁÐAÝÈ¢œLšÛ4,¸›0ˆÅm&»P("GÊ&°lT+p¯™€…>Ã$›­I¨‰£C¸`¤éH1¡3×-U‰ +¢ +0€$!ÀŒr¬¢Lhh+pk³öOƒøI3˜Èÿ€:ŸXT‘ƒ p6ð1™H €pR‰1Ž$¢ X‰›Ê‹@ +h | ¨ ¯‚@Cb!@€‚‹LW¨K…œqà 8@‚ #ª€)*€B€€š?!ŒbÄÀDüw[wu™[ÿ32³3+3#üå]ÝÝݱY™™˜ÿÌÌÌÎæfffgù™™±®æfÌȯ¸“±3333333/3333333ffffffffffffffbÿ3333333™™™™™™™3333332ÌÌÌÌÌÌØ­û333339™™™˜/3336!ÆfflÌÁK3aÿ{ BíZ»»»»»»wwwwwv­Û·þfff™þffff{3¹™íç³=™¼¬ÎûÙÿ³;™žÌÎ÷£337Ÿæ{=™Ïgs=™™Y™ÜÌÌÌÌÿ7™™™žÌÿ¹™™™™þo333u½æžîffffgù¼Ïffw3;™ìÌÌÎ{=™ÜÌÌÌÌÌÿ333;‹33+ÝÌÌÿ;ÌÎßù™™›ýö³3333y™™ÿù™™™™žÊ™™™¿FfgùìÌÌÌÌÌÌÌÌÌÎçs33¹þwüÌÌÏó2§/yÌök¹™™™ÜÌÎç}Dffff™™™ìöfgs36s3333Ù™›Íæfffl<ÌÞfæff{y™™†ƒy™™žÌÌÌîw330@1™™™™™ìÌÌÌÌØ]ÌÌÖs3Ÿæffw333=ÜÌÌÌÍŒÌÌÞfffföÎæó=™™™°CÍû7™™žÉ™?æffMçù™™“èÌÌ€ó30™›{ØäÀp…âr1FB»³ïÄG#…ïzç,—À.¸½ýrPñ †/z­QïøûÞâ;öô¿à¾ö¹=þ.‡Gµ¸³¯è’b‡N·ÜÉôñŸ×H?Ëí.V(q=Õnµè2=×:½6¡ÇæÏøkv?0+·o°þ)êˆR_Nî¿<¯/W®¡ ß`uøk·¾uÑ~}á륊óó†˜] нzðnOœ;“é¸×s—UÓ«ßj¹¸y|ŠÉÞmtö&3\' w¿Á×ü‹€–½Çî˜ö¿Î•œÿ˜ÛÜwÒ _,ó½|7dž/Ä)›_ÊtÜy€¡¸ì3Á>®F¹Â¨_OíONóPôW#*M>GR™—/Xüù/¹ÌÿÝyÿy½ Kˆ›|ïðu1‘RøÿèÃQ©äzˆ^¯o\å_œ ó8;5´ú«WÄ/ž×xü¥÷ž¼xkˆÿàõÎryÂk§QíÆ»ßïUw¯Ožm5u\ù±?ò÷ÓÞÅÿÎ÷ ÷F²yn5zÈÕÿáÂÇÁíì=¯ 䉎Ÿ~\1¾’ŽE^ŽíÒ­ByÉÛè9ÿ7ÌõG;Ccý ÷.yãØã9…êô`ÓR˜µY“Ó¤¬;ìÙ¿&AÌÞê{g‰wT¿lÌúWñycúâ²N«§qÿT(ÎG÷¾ÞñB‹%Ê«C×ê¿ÿ4:µ»<Þåÿí#Úp}:Ñ;y¸ ³o‡U<ÿ[öù·åøî¦^-×vq~ôE1Éð‰|ÕÅ¢;Á@ÿ1áÏ÷~íÉÝpóüÿóÄ**ífD,Þâú—Š9½kØ}ÿ=9ÛYÖEOð&9Q¾F½ßûzÿù»ØçPÎÎÙÜŠn=ÿgùîkž¿rv}ß;® ‹åÖõ:ê×fvåÙ¬ÿþ=Ö£kƒÎµ=¥ÍÈæ~önûä¿7ülC`_;¨|år*¯ö\ãå9ÐØ¬Uùç¶Y_§©®=ÍÈZ{ÝÕV{$B]ËìAkþTdwsÝ6EØþóúôg¼ý¯k#»±¸ÛÏüþ‡2°î?öÏ\;Ý肊ŒŸ¿«ÅÍþøÈŸç˜®3?Ÿ.t_=Ø;Ìöv7«kÀãö£ºt=ÿþ†ô?šïAâï+=*sÀsWk:«höü»ÚÉ­,àÖwT߇Oñ½ûúœ9~½…ݹ÷½ßõþùÌãQ÷á~ö?Öh×¶"}ÿBÿcP•gwŒß;Òë\³Òá­E«æ¯O{õÆú«]à½úÔËïý…6:_ŽùqìèV‡ˆ¬B#ýkù¬×c»ZÌ{ÖÍo€äuWw¦¹“¿iGHë;‘w;íþ5àÞð½Ípw¹o¹Ö‰ÌUo±_ðc\š­!{öµþó|ôïQÏûͶgeå.Nõžq#ÊøK¾mΫõßTßž-жTö_ú®5Ò½™àRÕocÙ¿à(Üè‘Ï.ÝsÜ÷ý™ýϨî»ÕÉÿÃejmƒs‘_h^ï ýóûç÷éÛ$Ú•ÈöEDNÅÿÿL\îÈïèžWqæ1u+ƒÜ©ïS¿ê»Y¾a“ÚÓìðã›ÃB¸¢`“¹­o×ø]Õ?ÂÖ‡úöË7Š_{¦¿ ãÿ;îWy¢b†Üt!YÝE‡ù¹&¼vÙ4`ñé5'ÆHh•Ø•Rúmx´ÒöZÐøòá 9Œå˜=ÄéMF±Ðôä¥U&z–¦=ì£ áÙ•0ÈFÅ#¥UÕd…¬†ÃLÇFf†&lâ±¶íì–«ªÚ¬–“ÔœØþ›ªqÅ3ˆ{lçEùõ\«M¤â]Õ¢´k½§!æbLÈl1aæ]jj’Ë1Q®¶:Õµ¬e&´äÄÓ30aÌ8ØßQÈŒ_±Ýhœå{S¶–Õ3ˆÎd2ÛÈßVUð«=ÒªØÚ®b†mèÜ °Û¦&VHåäo x·R¹R»}DÖÏU¬1„ÛåÃPÍÕ f½+„ÙýPªUr×%6iY 9>lŽ:†O®š«5òT Íê*£5¤ªêe¢Ù¢3X›EÐvp¢¼™BpXö›‰m:YhΟ]3™­¦‘²£ÆM2å³tª©V)5,¾ÍÔ>tæŒFÁ´ª9„ ÎNÀ¸×Üc3S]³mà~'9–FÌÈÝ“ë¥ÚöB˜_®ê®š¶tï"ö™Ó*¦ÎÏ%rWlLÛT¦m“™GÆg§Ø œ \fNYÙ$2*KÍ‹ŒÌÚ61ÌÌ?ŸnÐd€ih­Û]L²¨ä5å•#£8°Ã£¡Ñ¥½fŸUMY‘M-W•žZbÛž¡¨–'†S= ZY'¨¢ª ÕÇmB™r–N[zÚÒ‰aJ¡™“i+ctÅV[¯Æ•‚òÈdhD4yÙÙ«6§;BjJ¯r£­é³‚¥U“¥©ƒV&QcwíšwDSØr®Tõ­4X2UºXî3tŒxŽNì–_vŒãl}1DÙ‹2© ŠgÐvT©@Ù–õ&êÔ“‡v3tÐìÐoH_…îÝ—“,T6U§UZ$Œa îc)3¬<ÚÌÆ’`ì£I¶ÍÌŒÃMVÝ4¢´PsDÉœË3´·¢Ø-yuž`ŒlUõØÈZ¦ÄŒÌFÐö°æV[eT¼Ø2¤’Rº¹f,¶°³CS!½†¬Ì}÷ÔUGd,MzS¬RU6«XÙɲYDâ`8ÜÃf?²|Á$ ýº¯#I)n¥‰5%å £°¼Ã6a²Ã8×¾)’JOíˆS@Í:û®kéÌO8_3fÉØsÇÖu€¶’KT [\(¤ºê\¶Y_67Z0ËF9¬9ñ³ïÖѬ°¦ˆ:ª’¡Ñ§£_39€Ñ‹.š¬6ÒréÃTÆFœ'&dA·Œí6cíÞ Ž—P†D“’†Ô™TîÃÓYŒÄq`À¤4Ñ›$C³2SaÁÊCf”lª“L.J ù¹KSÌáɉ’Äsgè<Çq’•{€sº-(”m+±Ë3MªÈðé8L¢3›;5²C-yéƒ¼Ë K¦4®ÒT·Ni,d QG’D„hÔQãkÛg€Í.R©`ç'†¦döHr”dޤGì~ÇoL]Õõá ,Ä÷.6mÆ2¬Ø¶.6†8„xË^`1½‹ÃÓ˦¶µpú£É»|vb0šÄ`‰JPáÌGž9æFãÁuý5¦ê¿Ý<À¥¨RéV†Y©‹(Ä¥™ž4sÌcgǶÆv<ÍŒ<iÀÊ‘–Xà#Œá£,¨ÉbŒNC=ÌI…ÉžÛðtÍÌK¼<õË(¯)•ª6Z)r—¥‰™Ã„Ã(³[ ¾6ÏàŸãÌ©:ÔxkÊÄLcdÙ[“)‘†Ìv8˜c²¯ƒ[ cÇß\œQR«ÆØ³ªM…2ÙLƒæ;$vb<ào²—q¿Þ÷ÿØæäíe2\•£5*×Y&‘v¦/€hx#ó‹2ɦÃ>™­?h7<5*¹[ lð¸1ïh욌ÎP~1vp ¯`¸L®}\©TÐÀwÁÏMPFaøó<'ô³Î?¹ÈU/ï |ÙË•²öÆŒ\  ®ÈÇ;aw6ΞO¼ DƒÿQÆU؉”Cޏ9›t͇Ôü›‚x +`„ §u^•P¤xàùÄci|øòr‹ô{òàøø5+*%+e$‹4Áà%Ã͹râÏ hÎèþ> +|þXJ¶4­’ôE¼©ÆgNÒrn“Îqñ˜wh£ Ó}Œ^¤Ñ©ªt¬Í™ƒM8áŒ7d‰<ãŸÌãÌ€/ „…T±âµ«VqÆpàÒLy1ÆÙ‘7áèá§0"öc4&@*FFzIÛZÈs0qãI†8Ò.®nèÞžöΖ,§ƒô¯2*-o&!ÉŽ>˜“ œÆNÓ‘ÌŒQ£€DH‰ÜúÞ ”ñ.Æc&GM…c‡ÎY3§úgããÞK÷sîHTFKY1\Ì‘3,.fÄógq†Îiï-Ƈÿýû1ð¡æ/õ[bÕ`Ñ—FŒÌ yÀâæã ÜÖ\¼@à@8\‹L¬´Å£)ƒË2:dàcÎF3šÌ3¤Ê¸[>¶þ‹lxßl±™I¶¯Yl­  9˜Øcs\·™§Iþƒ°r¬d R›˜^4!6nI¥ØÀLñh§iâ·oþßíÌ,?¢k9ÍXèn\@Ó3€Ò[žÃf‹8ÊÐÙ×¹ž„A‘n£6RåŠÒ‡c6 ¤9 i6bî6XæY׸þÿ;¶Z©Ž=8–cPÍ1á°Îc<›1 ˜æzÏžCÜcâp8Ðh\ÆfRÌž±”¦xíG2 ¾dÁÁý À="hsv‹xÍ]e-'É—9¸öG1ƒâËÍœaý‰áýâ<œ¶ #ÖêpœŠÈ1âhä=&àÎ0};´qóûØ<á° ¾ø^Ï%±lªJ«T##ògØÈìwiÅä{PüG~ÁÐb©©J¥ªåt±º“œcCaÈìwEÇæ<ØÂ@q8ãÕ3%sK8”j‹›3‘ɰþD~7W)ç·ž=¿~Ú @” m‰’›q:¤œaÌ8²9…Èáþ*á¹}yd¬wivIÆ{¥³\±ÃfC5s9!œ Ø¿‘͆Íÿƒ>ŽGø"UÛWÚ«º)‘ ”‰òÌã9¨}‹ìZ›¶7ÿÀàpñ÷»¥aUèÒÎa4x£8†zpñ—ÜlÇL0G àßüyUÎy"’JXFÊ`ò#0ÅÃ7<ä¥c?“~ç¥ÿdž›xWeë—j7(>̧œiÃ3Æj>rÄÖàÇ3â|2œ „Ý9V¥‹)ÍOlèù5_Œß3ìpÇǘc5ÿš? óÀ'ðR%”²-\„èCñžrœQ™™ xqü\c øÿø>a¥ü3ÙCt"Je"µ»<ìañ8eqÁ›™òx¼\q‹ßá@¯„~LñÜ*‹—Ý2‘:NS3`øÎ˜pÇÐæ¿,9øpïœ;ü9 ¶2ææ3>AÀðÄ>2Ãá|<ç˜Ø~ó?7¸Œ H“ËñÔ›Ei”´N±!éÜ?&I Ö<„ãÖ#þaÙóüüÂ"I 3)Âb£89£Cr±áÍ™6™q±œÞŸàLŸÀcÀõèTéºäK°Â™çhÛ¥KÑå“Ï»>yü?ì=N, +Å`FåŘ<8rðÖ\ÇÓ¬äãŸÏ?ÜñCåCª.þßà@ÿ÷æÚ…¹+ÝX´f¢9#€ù0_0n^9˜èíøü3??ÿâ™@^Ã2­²ªÒùc°86 ec‡Ã¡f×r׸@³¢”ÝZÖZÙ®óbÀÄÍÐó1‡z:XñæÃþ¶÷ÿŽ¿*¦Ñ¥ C•QÕ`r!£N`q¯37œÐh°ÿÿÇ„I¦Ú*œÝ9j8g“.LhK%ƒ<,Î{=ä_€øâÌä²ä*uS“lPO"La1™Xdï²rÈÞ åñŸÿvðêo"ͦY³cPÍI 6y<ñxXãï–9(²]ÃÙ6xgC‰Æx¹”Û„o,‘ÿž†>œ0øÈ.åi­SrÇmü9˜hɱ¦¤ê"Ø[d î[ò;Ï@„ý§¶ÕfE9š«¦Tltbè˜ÈÍò v|a€?Ÿ=ãŸ$2KQ­t1âf4M72qvÇ{™óèÿn^ ŸŽxÞ\¥$âd¸äS¬Ä¡:‡IÔÈe¡‡ð°ýÏÁ÷úʱ§6šçÉŒ:3Iä2o3‚qÓöy=ÆIß:J% ¬‘šRäÚfSLØb•‡5»,ÈøÏ°0àcóºQ6I%.¾µ>s3Nâs›Y‡¹XÇ~~`çüàð¨d“ݦgZŒ”p~1™é‰Í-¤ z‘âåÇx·›¿C™§O+–²I¬9š ;3áìÃÀóÿ/ÃÝ=±¶®rá´ªìlÆ5˜à±¡aù¢X:F¡ï ïüŸ€^üs\§7Ýi–Di‘›`òM'8”äÇÆ±¼‡Ÿ0:ER:k­š³-ÑœÉ)NMÎ&MƘÇyÿÀøÈ9•Q¨Ú8¤gG°Ì9G+6:£Vâ_üq}œ›[dnX˜ÌiƒÐŒå9Wrã LCÿÿñÿÇÀ޳fX0mņ8¢ƒÈ†eÈ\pçΙ¾ã€Álk+tK*p£Í¨:Ñt†Ç.q±ÒºÃ‰Ÿs€ÏôHÒ¹&Ôé’§V‹ñƒÎƒ¬kc±£´Ð¾3@Ç9à“‘´©‘žc8Ç,ËJ™œ¥}¿ãp¡ãnÓ‰Û2TòɘžfIwefÓÞÎs'ÖÿðÛ4«•#µƒUeZÈÙTš.¬²hgFû}à ‘àš%ëŽTÎä©™ÂZGJ‹C1–dØ„ñž~ø\Ã>pÀàÿøøÏ‡PÕCði@Àø øÀ 1œs[RþàGþqøÿð@xFŒîx¼ÿ‡ñxk€0?ð?þ +Îc›†ÁÏày?óüÿÿ€‡ùü_ƒçœ`™{‡‚8y†ü9üÀoïüÈ ûCw~xÓ?à øx€óÏðóËðãÁ7ÂÉÄ€b÷àÿ(aþqìm1#/ÌÃÃà1áÿñ> ð°Œ~Ç*ÙroGÜ!1‹À|RLrhf3Ìòßàÿ¿à¥¡àg3A«å‘ µà<üàqüã̃Ì€Gö‹‘xßö¯ðxAÄÜ|‚æóÅ\d}K’¤’Ïaðàÿ 8v_+F7qÇ›,ðü70@òrølÉÔ‹€À ÿÿbÀ@€¢ìåy²ëÀÿ°8øp6à÷GœqĔΩqT9çƒÿÿ<>ß0ðÌóÿúgž¼2rfxYxñðÿÊñÌrþ€ÿœgqRGx>ÿç€ Ð<ö^\¼’9IÃ;5@À`âƒõpH0ÌF£6x°â?Ãÿ†€ÿ‡Eü‡|ÛEøñÁ÷5‡ˆdøœp0;öðþ÷˜ÿþÍ…1½5˜2sÐÿÏÿ¸ÿÿüÀþåÆ9­ç.PðË?Nøy÷ÿC`˜ðI„c?:%Ï8NqœyÀø‚ÁüûÀR™<=ÆÀÑ$pc†ü~CüŸ€üyžÞaí>ÅÑŸ§üØ1‡ã3t?øë¾ñ‘ØÔÆV̸x£ò.Æz#|ä ð€à1ÿ€…)öe°=ÛƒÿË8‡ÀŽù3’E 03.’<2 ‡Ã—ðøÄ ðpH‡YŠÁŒ Kí4qþßÿÀ8ùüüãÀà?…Ÿ9v8a,øf£äãþýxz?þgÁôÿæ s‰§÷Éó¡ +³ÿóà‡ÿ0aà0æOg+\,çM,c™}˜„€0`€BŽºQË’3œ;áØàx?ø0#ÿ?ÿ?™÷;-Páœh<ÃñHéÄóáÀ~þpÀpàøü|0øï2ì&¥ƒÆy‹¾‡ãø?ÿˆ ðÿ!â)ÍcÆy±,œG=Ç>üðøsC€tú‘’&æM‰¶sNÑùƒ¼·ÿà``ñ8`` 81”?e˜tqÃæÊ:L‹0χü8nþ?`üÈoGë±£‘:¡ÓãLžyà üÁð>?ÿáŽÐ'1ñ%Äxi˜ºç[Ãÿ>ð=ÿÐ_{üþà|dü#šˆó”¢Çrlטÿ´0 à<Ãðp?üx1Š]Á¼ÞžÄ:4î*@Ý?8?ô÷àáÜ8³Ã3a’jU­¬Bðqœx ð1àü0rÃÏœ˜<<ñM<¸Tƒá·‹ À?ø7ÄœóvcN™¶ÈíužSøÿ¼yãïçÀ{þwœaȘnjq†œÃΜ7ðüçùßóŒ`Ÿ€xÁS%;Æ96ØÕlÈ`óa€€?Æ}€ðb?=¾É8O å±Ì³\†'…¥Áþàÿ €çß÷€ð8ã1Àp8Q6fGL¥…¶3ÃÃ>{àâñƒ?àny˜cðÑ[Ü®q”é~@xÿÀ~Ëð¸ÿ€ ÆyÎB×’æbqÌfÔã©À7ÿü/À<> #[FÃ6ù3žO§sP¿ƒÿÏýàùÀþœ7ûÿéÇ…O“Ì^94…Êþd|ûðÀ ÿáÿ˜§ íXàq«8¬€ÀüùàøÀùŸ¸x<â£ í±³Eáó†ð5Ÿ€ÀÏÀ}çÿïà=ާÓ<ÄÓÁðãž9È4CþïþÓÞ÷Áÿï00?lÌæ3¶qì‚ã CÌ×ü3Ïðÿàÿ ñÞ<‰pïÃæd?!ž'\´ü^ÎÌðü7Àž ø àá¦ÇÓ318€îlñ¨Îƒø à#ãø>à 9ÿñÄp<$£ã˜<ÆÜsУÜ7|Ðóæ‚?Í>ĬrOSÏ< œéÒiÓ>ðé<Ÿà?ÂC?ÀþðÈò6±g`™ <öv•¸Êÿþy€yÇ€?üþÿÈÍóùËÇr†’Q⓳³Žþ$9àÿþ8|߃2i2Ûq¸löáãð|ù€qûø>߯üó,i,G‘aA‹±—GÂ>ð|ÿïÎaüÜ:àô‡FÒ’±YO @¿ÿÀü€ð{þ y¾ç +»ž.:s…‹eáÃÃïè(ü¸üÀ%ÇŽ3&è·âLjb8ŸÏÇÿøÿáÓÀ àÿñâOŠ,‘ÅÄ9ó~qž²º­ƒÿÿðƒ‡¼;ÿàø`YŽ(¸ˆäyçËc3r8c½8ÿàaÿïøøðþ€À>dü±Îg%¼gÊÁ2$ºfÿ°x¿çö?(?ûã;†œÊÆv‹ŒŒgÃð`EÕçÿŸŒž>v3îàGÿüøÀ`æÃc›5Œ›ÍsZðŸ¹Çÿ;AÎýþX?ó™®\êy²G¹¬ÉILMù0ͼùïïþ#äûŽpÿÿ¼`B8°@ä¤,ãYãðÈAÀN‡ÿŸ ßÀ‘ÈeC‰Œ¨ñ&•±6Y%›øýÿþÿÿ¹ðÿÁ³ñôï ÁƒtÌcìíÁ6ÂÁ=þó=à?ù ÿüüçbsg÷üüÑäT^aÎ2Ž3a(Ó…OÏøñÿÏ‚ñçŸIà`‚¼Ÿ +E6±˜ûÜSÏaûüñùùþ€'öã!œÛ³ÓÓ†Ä2ir ´ô÷yøüùápŸÍö +Í Òô5GÂÏÄðVU¦ GóƒœÀÜüáÂc„x`µpÃÌ’¹œÁ yY˜f€ƒúÿ›Ïˆ‡À!ùòÙQöw\u3c¦>\Æ$ñ!øD?ßðÿþvsñð€ó4CìTä‹‚™çžæn0ÀàpãÿÿïØ~?;.£:SÃrÉíϤù9þƒÀ@ßß?Çð|ð1T2v=3ƒnÑœM³Äðpÿüðþüÿýè}ãÿÝlj–=¼Ô£>ÉÜqØ'ÿ†?ó§ÿÂà¥Ïþò/†Ç%±o[ºcN? ÿòž/ÿðp`°¡.µx®Î™8œjƒÌŒäÿèûx~àø{Ááÿÿÿveá0íX¾rg±Ï±øÃá€Àp>Ðzçì8¶RqÖ&Ó8ÉПðàû€ðÁÇñ÷€3IÓÆ™´m.µÉb‹ _÷ˆ?øðÆ0?ÿÑáÃÁ,|ØŽÖC0³¦ÏƒÿðÀþý7€ûý€8ümñZtHÃb%£±‹çÿ7Ÿƒþÿ`~0À0ÃÓ-¶XÚ›“—‡U³sæÿóðÿøû›°‡ô3šc Ìd1–GŒÉœ¶–u‡àÙÿüçÿ#ÿqóïx°çiwÄåÓ1,rÌa£ãb?ø`çóü~‡ŸüòHÑI¦qŠUfZ,±bóãïûôÿò7ÎÃÃÿ¯u‘z¬Ås{:0}ñ÷ƒçÿÇgý‡sãÿñøQQJcK)dQ-#+πÞoý'‘ø ëÛ­ÿ5G^7•²uϳ–«þÃûáùãáàžü…’¥·a¬ç%¤ÌîbþõÀÁÏ<ýø@&;4_´s%n†‚ÿÿ„Ã?aË!lµÃñµuÃX ð`þàøÿþ9øcòöã(GZu&¹ÈœÏð}ÏÝü`?þèüp¤73LìR‰å‚NŽZ¦ÿƒ‰ÿð?øø!Ï€'¢”˜¬&MôNayc<ÿÁág>Lþ`Îyó ÏÀþlW™æÛ)yJÆtùpÿãéýÿÿÀÿþþÁ8‹*]ONèÃpŸâïðpÿà|ûmHô­š(´ÔÖ“D>Øþø48|yðøZ¶+'–T§Î7'Çÿwùü Ú øþ1ÿh~žÃQ’ô²Ýœšè<Ïÿü` àpþ÷üø ÿÞm#®o´‡Fd¤Dzç?‡‡P~Ÿ÷†Ϙáÿÿ£I¶8&jÄ–S©&ýÇxðøÆKR†§Ë2‹eØ}‰<øÿè‡á<>'ùø +T6W+*S2¤âɶÏþÿÿÀöÿÈ€_Îà ZRÞ(Ú‡­!¹Œ²¾!àÇÀ ~Nç̸~äg¦¸F2›+æ´I£=€ÿ9Ãðãÿà?ÿÿö?Û$SŽ5FYn­-¹î†|ÿ³âsÆvpCêÆËÔðY§)YÚ3¹±†þÿàüçöÒµÉäìvfZ˜žçþ΀ðèpÃÿxåsÙ3É +u\à \ No newline at end of file diff --git a/astropy/io/fits/tiled_compression/tests/data/m13_plio.fits b/astropy/io/fits/tiled_compression/tests/data/m13_plio.fits new file mode 100644 index 00000000000..c93383bd5c7 --- /dev/null +++ b/astropy/io/fits/tiled_compression/tests/data/m13_plio.fits @@ -0,0 +1,1484 @@ +SIMPLE = 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 is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H CHECKSUM= '1aF71a961aC61a96' / HDU checksum updated 2006-11-15T17:28:20 DATASUM = ' 0' / data unit checksum updated 2006-11-15T17:28:20 END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 8 / width of table in bytes NAXIS2 = 300 / number of rows in table PCOUNT = 165616 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 1 / number of fields in each row TTYPE1 = 'COMPRESSED_DATA' / label for field 1 TFORM1 = '1PI(301)' / data format of field: variable length array ZIMAGE = T / extension contains compressed image ZTILE1 = 300 / size of tiles to be compressed ZTILE2 = 1 / size of tiles to be compressed ZCMPTYPE= 'PLIO_1 ' / compression algorithm EXTNAME = 'COMPRESSED_IMAGE' ZSIMPLE = T / file does conform to FITS standard ZBITPIX = 16 / number of bits per data pixel ZNAXIS = 2 / number of data axes ZNAXIS1 = 300 / length of data axis 1 ZNAXIS2 = 300 / length of data axis 2 ZEXTEND = 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 COMMENT COMMENT This file was produced by the SkyView survey analysis system from COMMENT available astronomical surveys. The data are formatted COMMENT as a simple two-dimensional FITS image with the same units as COMMENT the orginal survey. CTYPE1 = 'RA---TAN' / X-axis type CTYPE2 = 'DEC--TAN' / Y-axis type CRVAL1 = 250.4226 / Reference pixel value CRVAL2 = 36.4602 / Reference pixel value CRPIX1 = 150.500 / Reference pixel CRPIX2 = 150.500 / Reference pixel CDELT1 = -0.00027770002 / Degrees/pixel CDELT2 = 0.00027770002 / Degrees/pixel CROTA1 = 0.00000 / Rotation in degrees. EQUINOX = 2000.00 /Equinox of coordinates ZHECKSUM= '2f4R3c4O2c4O2c4O' / HDU checksum updated 2006-11-15T17:18:55 ZDATASUM= '1803906202' / data unit checksum updated 2006-11-15T17:18:55 CHECKSUM= '9kLgChIZ9hIdAhIZ' / HDU checksum updated 2006-11-15T17:28:20 DATASUM = '3243227777' / data unit checksum updated 2006-11-15T17:28:20 END  + & +4 + L +`t‚Š Œ¢ø¨ú˜øŒö |ó"hö$N÷&:((ô*(ö, -ü +0ÿ2"ý4 68:$<(>. @LB^ DnúF„øHx Jh L‚N˜ PšR²TÚ W +Y [:]L_Vadc„e¨gÈ iöl n6 pLrd tp v‚x”zÄ|ò.bƒ’…¸ ‡ìŠ,ŒJŽr!°(’ò#•B—ˆ™´›èž F¢r%¤¨(¦ò$©B'«Š­Ø° +²:´h"¶œ%¸à »*!½j¿¬Áè$Ä"ÆfȪÊÈ!Í ÏFцÓ®Õâ$ØÚf!Üœ&ÞÞ%á*ãtåžçØê +ì4 îp(ð°,ó"õX%÷œ-ùæ$ü@#þˆ#Î($d!¬+ î  D&„"Ð#Z”Äú%*" t"¸$î%'*%)t(+¾$.!0V2˜4Ô!7&9T ; =à@%B@!DŠFÌHü#K*%MpOºQòTVR(XŽ#ZÞ*]$,_x$aÐ%d+fb(h¸%k"mRo–!qÔtvJ"x‚%zÆ,}*h,¼+„%†j ˆ´$Šô#<!‚(‘Ä!”–V˜ˆš¼œêŸ "¡@£„'¥Â¨ªN¬†®¬°È²ôµ(&·^!¹ª&»ì"¾8À|°ÄÖ!Ç +#ÉL'Ë’Íà!Ð!Ò\ÔžÖÄØèÛÝ4ßdáˆã²!åè$è*%êr%ì¼$ï&ñNóšõØøú8üfþ˜Ðöþ   < p  ¶Ò4ý824 < "J $d &~(–*²,Ðú.Ü0Ð 2î579 ;ò=&ó? +@ðBô DþGIûK" MO0Q<úSB U6 WHYZ[h]t_~ëa„êcZþe.g*i2ük2øm*ùoq su w ýy,ù{&ù}ÿ +úù‚ü„îÿœ + o@ @0@ @0@ @0@0@0@ @` @0@0@````pp`` +``pppp +pp0@` @pp0@ @`````pppp```` +pp +p +0@`p0@ @0@0@0@ @ @0@ @0@0@ @ @ @ @0@p @0@ @0@` @p0@````` `p p0@0@ @ @pp0@ @ @p @0@` @ @p0@ @0@0@ @0@ @0@ @``0@0@````$`M`6ppNp6ppp0@0@0@ @0@```` `)`J`@p pOpFppp0@0@0@ @0@0@ @ @ @0@0@ @0@ @ @ @pp0@ @0@0@ @ÿœ p@ @0@ @0@0@ @ @0@0@0@ @ @ @0@0@ @ @`` +`&`V`XppbpMp0@` @pppp0@ @``` `pp0@` ``7`0pp:p+pp0@ @p0@0@ @ @0@0@ @0@0@ @` @0@0@` @p0@ @0@` @pp0@``` ```pppp0@p` @pp0@0@ @ @0@ @`` @pp0@0@``0@0@0@ @```` +`%`xa`¶pqp”p.p ppp0@0@ @0@```` +`` ppppp0@ @0@ @0@0@ @0@ @ @ @```ppp0@0@ @0@0@ @0@ @ÿœ p@ @0@ @0@0@ @ @0@0@0@ @ @ @0@0@ @ @````J`¶`´p4pÆp‘p60@` ``p pppp0@ @` @```F`¡`|pQp¢pepp0@ @p0@0@ @ @0@0@ @0@0@ @` @0@0@` @pp0@ @ @p` @p0@``` ``$`p"p"pp0@p` @pp0@0@ @ @0@ @`` @pp0@p0@``0@0@0@ @`````G`ða÷aRqqöqpRpppp0@0@ @0@``````ppppp0@ @0@0@0@ @0@ @ @ @``` ppp +0@0@ @0@0@ @0@ @ÿœ`rp0@ @ @0@0@ @ @0@0@ @0@ @ + @````\`â`àpJpþp­p:p ` +`$`2`p&p2pp0@ @0@ @```&`xa `Êpqpšp,p pp`p0@0@0@ @ @0@ @0@ @pp0@`````ppp0@````pp0@``pp0@0@0@``` ``!`p pp p0@ @p0@0@ @ @0@``` @pp0@p0@``0@ @0@0@0@```````Sab5avq5r@qGpZpp0@0@ @` @` @pp0@0@ @`p0@0@0@ @0@0@ @`` @0@````ppppp0@0@ @ @0@ @0@ @ÿœ`rp0@ @ @0@0@ @ @0@0@ @0@ @ + @`` +``D`¢`˜p2pºp}p*p``L`b`pJp\p0p 0@ @0@ @```&`x`õ`ºp}q p–p,p pp`p0@0@0@ @ @0@0@0@ @pp0@```` `pp p0@```ppp0@``pp0@0@ @0@``````ppp0@`` @pp0@0@ @ @0@``` @pp0@p0@``0@ @0@0@0@```````9`Àa‘apãqŒpãpBpp0@0@ @```` @pp0@0@```pp0@0@ @0@0@ @`` @ppp````ppppp0@0@ @ @0@ @0@ @ÿœ `qp0@ @ @0@ @ @0@0@ @0@``0@0@```````;`8ppLp6p`````x`p^pkp8pp0@0@ @0@ @````D`ˆ`fpDp”pXp0@0@0@0@` @```pp0@0@ @0@0@````p ppp`` ``p +pp +0@ @pp0@ @0@``` `pp0@0@``` +```pp0@0@0@ @0@ @`` @pp0@0@0@ @0@ @0@ @ @0@````````R`³`xpap´plp pp0@0@0@` @`` ```p pp p`pp```pp0@p0@ @0@0@ @`` ` pp +p +0@`` @p pp0@ @0@ @ @0@ÿœ +`qp0@ @ @0@ @ @0@0@ @0@``0@0@````` ```pppp```D`X`pFpMp(p +p0@0@ @0@ @``` ``0`&pp4p p +0@ @0@0@` @```pp0@0@0@0@`````p ppp```"`pp#p0@p0@` @0@0@````pp0@ @````$`)`p/p,0@0@0@ @0@ @ @p0@0@0@ @0@ @0@ @ @0@0@`````````-`$pp4p$p pp @0@0@`````#`R`a` pbp^p&p`pp```pp0@p0@ @0@0@ @`` ` pp p +0@`` @ppp0@ @0@ @ @0@ÿœ + o@0@`` @p0@` @p0@0@`` @p0@ @0@`````` `pp +ppppp````$`pp!p0@0@ @ @0@ @``` `ppp0@ @0@ @``` `pp0@``pp0@``` +``pp +p````(`pp+p0@0@ @0@`` @0@ @ @0@``````.`6`p>p8pp0@pp @ @0@ @p0@ @0@0@ @ @ @p`0@``` @```pp +pp0@0@ @`````?`˜`¸`p½p®pAp`0@``pp0@ @0@0@ @ @0@ @`` @ppp` @ppppp0@ @0@ @0@`` @`pp0@ÿœ o@0@`` @pp0@` @p0@0@`` @pp0@ @ @``````pp0@ppp`````pp p0@0@ @ @0@`` @pp0@ @0@ @````ppp```pp0@p````pppp``` ` ppp0@0@ @0@`` @0@ @0@``````&`,`p2p,p0@p0@ @0@ @p0@ @0@0@ @ @ @``ppp0@````0@``pp0@0@0@ @`````M`¨`Ø`pãpÊpGpp0@``pp0@ @0@0@ @ @0@ @`` @p`` ``pp pp pp0@ @0@ @0@`` @`pp0@ÿœ o@`` @pp0@``` +` `p p ppp````pp0@ @`` @0@ @p0@0@p`` @p0@ @0@0@` @0@0@ @ @p0@` @` @pp````pp0@ @0@`` @0@` +``p +pp0@` @0@` @pp @ @0@ @ @``p`` ```pp0@``pp +0@0@0@0@ @0@ @0@0@p @ @0@```ppp0@0@ @ @ @0@0@ @0@ @p````6`v`–`pp’p5p +p0@````ppp0@0@0@ @0@ @`` @` +``J`KppQp=pp0@ @0@0@ @ @0@ÿœ q@0@`` @pp0@````pppppp````p0@ @`` @pp @0@p @p @ @p0@` @0@0@` @0@0@ @ @p0@````pppp````pp0@ @0@p` @ @``pp0@` @0@` @pp @ @0@ @ @``0@``` @` @` +` +ppp p0@0@0@ @0@ @0@0@ @0@`` +`ppp0@0@ @0@ @0@0@ @0@ @p`````2`<` +p;p>p0@0@````ppp0@0@0@ @0@ @ @````5`v`vpp{pfp1p 0@ @0@0@ @ @0@ÿœ t@pp`` @pp0@````pppp +0@p` @p0@` @`` @pp0@ @0@p` @0@ @0@0@`` @ppp0@0@ @ @0@ @ @0@0@ @``` ` +pp +pp0@ @0@pp @ @ @0@0@ @` @0@```ppp0@ @ @` @ @0@```` +` `` ` +p +pp0@p0@ @0@0@ @ @0@0@ @``pp0@0@0@ @ @0@0@0@ @ @0@ @0@ @```` ``ppp0@```ppp0@ @0@0@ @ @ @0@`````6`€`{pp€ppp4p 0@ @0@0@0@ @ @0@ÿœ v@pp`` @pp0@````pppp0@0@ @p` @`` @pp0@ @0@`` @pp0@0@0@`` @ppp0@0@ @ @0@ @ @0@0@ @````ppp +p0@ @ @ @0@0@ @0@0@ @` @0@```ppp0@ @ @`` @0@0@```` +````ppp +0@p0@ @0@0@ @ @0@ @`p0@0@ @ @0@0@0@ @ @0@ @0@ @` @ @p0@0@` @ppp0@ @0@0@ @ @ @0@```` `$`W`SppWpLp#p0@ @0@0@0@ @ @0@ÿœø`s`0@````pppp``` ` +pp +0 @0@0@ @ @``pp0@ @```` ``ppp p0@0@````pp p @`p @ @0@0@0@ @ @``` `pp +p +p0@ @````0@0@0@0@0@ @0@`` @0@0@````pppp +0@ @````pp @0@ @`` @``pp0@ @p0@0@0@ @```pp0@0@0@ @ @0@0@0@0@ @ @ @ @ @pp0@0@p` @0@ @0@0@0@ @ @0@````#`"pp&ppp0@0@ @0@0@ @0@ÿœú`q`0@`` `` ppp pp```pp0@ @0@ @0@``pp0@ @`````(`pp,pp0@0@````ppp @ @pp0@ @0@0@0@ @ @````pppp0@ @` @ @0@0@0@0@ @0@`` @pp @```-`.pp*p(p0@ @0@````pp @ @0@ @0@`pp0@ @p0@0@0@ @`` `pp0@0@0@ @ @0@0@0@0@ @ @`` @pp @pp0@0@` @0@0@0@0@0@ @ @0@```` +` +pp p +p0@0@ @0@0@ @0@ÿœø p@``` ``(`pp*p0@0@0@ @0@ @ @ @0@` @ppp`````` `>`*p#pDp#p +```ppp` @ppp0@``pp0@0@0@0@ @ @ @ @0@0@ @0@ @`` @0@0@0@ @`` @pp @```5`4pp0p.p0@ @ @ppp` @pp @0@ @ @pp @0@ @0@``0@` @pp```pp0@ @ @0@0@ @0@ @ @`````ppp +p0@0@0@````pp0@0@0@```0@0@ @`` @0@0@0@ @ @0@0@ @0@ÿœö p@``` ``0`p"p.p0@0@0@0@ @0@ @ @ @0@` @pp0@```` +``8`&pp`X`p:pMp.p `pp0@0@0@ @ @p @0@0@``0@0@0@ @ @0@0@ @0@0@ @p` @p0@ @0@ @````pppppp``0@``0@ @ @pppp0@ @ @0@0@` @``p````p p0@p0@` @0@0@0@ @ @p0@ @ @`` +`*`j`™`$p‹pŒp8p0@0@ @p @` @pp0@0@ @` @0@0@0@p0@ @0@ @ @0@0@ÿœö o@```` +`` +p pp +p @0@0@0@ @0@ @`` ` +`pp p0@ @``` `p0 +@`"`„`¨`%pjp›p^p0@p0@0@0@ @` @pp0@0@0@`` @0@ @0@0@ @0@0@ @p` @p0@ @0@ @````pppppp``0@``0@ @ @pppp0@ @ @0@0@`` @```````p pp 0@0@``0@0@0@0@ @ @p0@`` @0@`` +`0`z`¹`0p§p¨pBp0@0@ @p @` @pp0@0@ @` @ @0@0@pp0@ @0@ @ @0@0@ÿœ÷ p@``` +` +pp +p0@``0@0@0@ @0@````ppp @pp`` @0@``.``Ä`%p~p³pnpp @ @pp0@0@````pppp0@0@0@ @0@```ppp``0@0@0@ @0@ @0@ @ @0@p` @ @ @````pp0@pp` @ @0@ @``pp0@0@0@` @0@p0@` @`` @` ``p +pppp @` @p0@ @0@ @0@`` @0@p``!`T`„`*prp|p3p +0@ @ @ @pp0@ @ @0@ @`` @`p0@pp0@ @ @0@0@0@ÿœ p@p`` +` +pp +p p0@``0@0@0@ @0@p``` @0@ @pp`` @```k`ˆ`pZpspJpp0@ @pp0@ @``` `pppp0@0@0@ @0@```pppp` @0@0@ @ @0@0@0@ @ @0@``0@ @ @````p p0@p```0@0@0@ @``pp0@0@0@` @ @p0@` @```p```ppppp @` @p0@ @0@ @0@`` @0@p`` `$`4`p*p4pp0@ @ @ @pp0@ @ @0@ @`` @`p0@pp0@ @ @ @0@0@0@ @0@ ÿœô o@`` @pp +p0@`` @pp0@ @0@0@` @`0@ @pp0@ @p``` `)`6` p p-pp`pp0@p0@``````ppp0@ @0@0@ @```ppp0@ @pp0@```ppp0@0@ @ @0@p @0@`` @p0@````p0@pp0@ @` @ppp0@ @ @ @p0@ @p```pp0@0@0@0@ @ @0@ @0@` @0@0@ @ @`` +``p p0@0@ @ @0@0@ @ @0@ @ @0@0@ @``` `pppp0@ @ppp @ ÿœö o@`` @ppp0@````pp0@0@0@0@```0@pp @ @p```` ``pp p` +`pp 0@p0@`` @``pppp`` @0@``pp0@```ppp0@ @pp0@````p pp +0@ @0@p @0@` @p0@``` `p p0@pp0@ @```ppp0@ @0@ @ @p0@ @p````0@pp0@ @0@ @0@ @ @0@` @0@0@ @ @p` @pp0@0@ @ @0@0@ @ @0@ @0@ @` ```p p!pp0@0@ @ppp @ @0@ÿœ n@ @ @0@ @``` `ppp0@p0@ @ @0@` @p0@p @` @0@0@``0@p``` +p +p0@p0@ @0@```p0@` +` pp p p`` @0@p` @pp0@`` +`"`(`p p'p0@``pp0@ @0@``0@0@` @0@``` @pp0@p0@ @```ppp0@ @` @0@0@``0@0@ @p```````pp 0@0@0@`p0@`` @p0@ @`p0@ @ @ @0@ @0@0@0@0@ @0@0@0@0@ @ @0@ + @0@ @````-`?`'ppEp4p pp0@ @0@````pp0@ÿœ + n@ @ @0@ @````ppp0@p0@ @ @0@` @p0@p``` + @p p0@ @ @``` ` +pp0@pp0@ @0@ @0@``0@```ppppp` @ @` @pp0@```(`4`p(p3p0@```p0@ @0@p @0@` @ @p``` @pp0@p0@ @```ppp0@ @` @0@0@``0@ @ @p```````ppp p0@0@0@0@`` @p0@ @`p0@ @ @ @0@0@ @0@0@ @0@0@0@0@ @ @0@ + @0@ @````5`M`/ppVpp!p pp0@```p0@````pp0@p0@ @`` @p0@p```` `$`q`¼`‹pLpÕpŽp/p 0@pp @ @0@ @ @``` @ppp0@ @ @0@0@````pp0@ @0@0@ @ @0@0@ @0@`````pp pp0@ @ @0@0@ +0@ @ @0@ @0@ @ÿœ `qp0@ @ @ @0@0@ @``0@ @0@0@ @````pppp0@ @ @0@``` @pp0@ @``pp @ @0@`` +` @ppp0@ @0@ @0@0@0@ @``p0@``ppp0@``` @ @pp0@```````B`2ppFp+p pp0@```p0@````pp0@pp0@ @`` @p0@p````` ``4`!pp3p&p0@ @p0@ @ @0@````pppp0@ @ @0@0@```p0@ @0@0@ @ @0@0@ @0@`` @`pp0@0@ @0@ @0@ @0@0@ @ @0@ @0@ @ÿœú p@0@ @ @0@ @ @ @0@```pppp0@` @0@0@```ppp0@ @ @ @p` @p`` @ppp +p0@` @0@0@ @`0@0@ @pp0@ @`` @p`` @ppp0@````p``$`$pp.pp``ppp` @`` @ @pppp0@0@ @0@0@`````` +` pp pp pp` @pp0@ @` @0@0@``pppp0@` @p0@0@ @ @p` @0@0@ @p0@ @0@ @`p0@0@0@0@ @0@ @``p0@0@`` @0@p0@ @ @ÿœø p@0@ @0@ @0@ @ @ @0@`` @pp0@` @0@0@```pp0@ @ @ @p` @p`` +``pppp0@` @0@ @0@`0@0@ @p0@ @`` @```%`pppp +0@` ```pp`` ppp`` +`pp +p p``` ``ppppppp0@ @ @0@ @0@``` @```pppp`` @pp0@ @` @0@0@``ppp0@`` @pp0@0@ @`` @0@0@ @p0@ @0@ @0@0@0@0@ @0@ @` @p0@0@`` @pp0@ @ @ÿœ o@0@ @ @0@0@ @ @0@0@ @0@ @ @0@0@`` @pp```pp0@````0@``pp0@ @````pppp0@ @0@``` @pp` @0@` @pp0@0@ @0@```` `$`Q`>p&pNp1p0@` ``!`p pp `pp```` +pp p p`` ` `$` +pp'ppp0@0@0@ @0@`` @ppp` @p` @pppp`` @pp0@ @ @0@ @pp0@ @0@`` @pp0@0@ @ @ @``pp @0@`` @0@0@0@ @0@ @0@ @0@0@`` @p0@0@`` @0@ @pp0@ @ÿœ o@0@ @ @0@ @ @0@0@ @0@ @0@`` @pp```pp0@```` @``pp +0@ @``0@pp0@ @0@```` @p p` @p`` @pp0@0@ @0@p`````4`w`^p8pzpIp0@` ```ppp p0@``` ` +pp pp```4`8` p,p;p&pp @0@0@ @0@`` @ppp` @p` @pppp`` @pp0@ @ @0@ @pp0@0@0@`` @pp0@0@ @ @ @``pp0@0@`` @0@0@0@ @0@ @0@ @0@ @0@0@`` @p0@0@`` @0@ @pp0@ @ÿœ o@ @ @0@````pp0@ @0@0@0@ @ @ @` @0@ @0@0@ @````````p p0@0@ @ @ @0@0@0@`` @ @pp` @p`` @pp0@0@``p0@````.`i`Vp3plpAp0@`` +` `ppp0@````pp0@```1`6`p(p8p$pp```pp0@ @0@` @pp0@`` @pp0@` @0@0@ @ @0@ @0@0@0@0@0@`` @0@0@0@````pp0@0@0@ @ @0@0@0@ @0@0@ +``pp0@ @0@ @0@0@ @ @0@0@ @ÿœ o@ @ @0@``` `p +p0@ @0@0@0@ @ @ @p @ @0@0@ @0@```````pp p0@0@ @ @0@ @ @0@0@`` @0@pp` @``` @pp0@0@``p0@``` ``5`.ppc¶c¸p–sXsq pZp` @pp0@0@` @ppp``0@ @ @0@```ppp0@0@` @`` @pp0@````pp @p```pp0@`` `pp0@pp0@``pp0@ @pp0@``` @```` pp"p0@0@ @p0@0@ @```pp p0@ @`` @0@ @pp0@0@0@ @ @p0@0@`` @pp0@ @ @`````9`Ÿa`Ÿp©qpžp'``pppp0@0@0@ @0@0@ÿœ q@``p0@0@ @``ppp` @p0@```` @ppp p @ @ @ @````ppp0@`` @````p0 +@```ppp``````=`øbÒbÎpprzreqFpJp +0@ @0@p0@p```pp0@ @0@ @````pp0@0@```pp0@ @0@````p0@``pppp````pppp0@0@` @``pppp0@````p````p +p'p0@0@ @pp0@ @0@`````ppp0@ @ @ @ @ @0@ @p` @pp @0@0@0@0@0@`` @p0@ @`` @`````P`àa~`Ïpçq…pÜp;ppp +p0@0@0@0@ @0@0@ÿœ q@``pp0@0@ @``ppp @0@````& @p*p(p p0@ @ @ @`` `$`"p p(pp0@0@`` @``` +`p p +p` @ppp```````taBa*p,qqpšp$p0@0@pp @p```pp0@ @0@````pp0@0@`` +`pp0@````pp0@` @ppp``` +`pppp0@0@``0@``pppp0@```p```` p +pp0@ @ @ @pp0@` @ppp0@ @ @ @ @0@0@`` @pp @0@0@0@0@0@`` @p0@ @`` @`````C`ÈaK`£pËqHp½p7p ppp0@0@0@0@ @0@0@ÿœ o@``pp0@ @ @ @pp0@ @`````&`!pp-p*p p0@ @ @0@ @```,`&pp.pp +0@0@`` @````pp0@ @0@``````` ` `W`Pp +pHpPp,p p @ @ @ @p0@ @0@0@p``` @pp0@0@0@``` +`pppp0@0@````pp0@p` @0@0@```0@pppp @``0@``0@ @0@ @pp`` +`pp pp @` @`ppp0@ @`` @pppp0@0@ @ @ @0@0@ @`` @pp0@0@ @p0@``0@ @ @ @ @```` +`$`a`£`Jplp™p\ppp0@0@0@ @0@0@ÿœ o@ @`0@ @ @ @pp0@````````pppp p0@ @ @0@ @`` ` `p p"pp +0@p` @p```pp0@ @0@p`````````pppp 0@ @ @0@ @ @p0@ @0@0@``` @ppp @0@0@````pppp0@p``0@ @p0@0@```0@`pp0@`` @pp @ @ @ @ @pp`` @p```pp @pppp0@ @`` @pppp0@0@ @ @ @0@0@ @`` @p0@0@ @p0@``0@ @ @ @ @````` ``.`p!p/pp p0@ @0@ @0@0@ÿœ q@ @ @0@0@0@0@`` @ @`` + @p p0@0@ @0@0@0@```` ppp +p0@ @0@0@0@0@ @0@``` @``` @pp +p0@`` @0@ @p`` @pp0@ @0@`````ppp0@ @0@ @` @0@p`` @ppp @````pp0@``0@ @`` @0@p0@```pp0@ @ @p0@``````pppppp0@0@`` @pp0@0@p` @pp0@0@0@ @ @ @0@ @0@ @0@ @0@0@` @ @0@ @p``` @``` `pp p p0@0@ @0@0@ @ÿœ s@0@ @ @0@0@ @0@0@` @`` @0@ @pp @0@0@0@````pppp @ @0@ @0@0@ @0@``` @`` @pp0@`` @0@pp`` @`p0@ @0@``` @ppp0@ @0@ @`` @0@`` +``p pp0@````pp0@`` @0@`` @ @p0@``ppp @p0@ @p0@`````` @p ppp0@0@` @`p0@0@`` @pp @0@0@0@ @ @ @ @0@ @0@` @ @0@ @p```` @pp p @pppp0@0@ @0@0@ @ÿœ `vp0@```pp0@0@ @ @ @p```ppp`ppp0@ @`` @p0@`0@0@ @0@ @p0@0@ @`` @0@ @pp0@ @0@0@`` @0@ @ @0@0@ @`` @ppp0@ @p @ @``p`` ` `@`p,p8pp +0@ @``pp0@`` @0@```````pp +p0@ @0@`ppp0@``pp0@`````%`.`;`(ppDpLp$0@0@0@ @0@`` @0@``pppp0@ @0@` @ @```pp0@ @ @```0@pp`` ````p"p"p0@pppp0@ @p0@ @ @ @0@ÿœ `vp0@```pp0@0@ @ @0@ ``` `pp` `pppp0@`` @p 0 +@`0@0@ @``` `pp +0@0@`` @0@`p0@ @ @0@0@` @0@ @ @0@0@0@`` @ppp0@ @p` @ @``````4`r`6pPphp.p0@ @p @````0@0@````` ` +`ppp0@ @ @`pp0@```ppp0@```` +``:`{`Ppphptp40 +@0@0@ @0@`` @p```pppp0@ @0@`` @ @` +@pp p0@ @ @```0@pp`` ``<`@pp@p@p0@p0@p0@ @p0@ @ @ @0@ÿœ`xp0@ @0@0@0@`` @p0@ @ @0@``` @`` ` p ppp0@````p pp`pp0@ @p``` +`` pp0@0@```0@ @p0@``` @0@``pp0@ @0@ @0@0@``` @p0@0@p```` @`` @``>`ˆ`Bp]pzp;pp``p0@``` +`ppppp0@```` `` ppp 0@```ppp0@p``` @pp0@``````2`w`\ppfpop20 @0@ @0@ @0@`` @p```p p +p0@ @0@``` @````ppp +0@`` @ @0@p0@0@``` ` `L`OppQpOp0@0@0@0@0@ @0@0@ @ @0@ÿœ`zp0@ @0@0@0@```pp0@ @ @0@0@`````` `*`$p p"pp0@````ppp`pp0@ @p````` pp0 @0@```p @ @pp`````` @p +p```pp p0@0@ @0@0@``` @p0@0@p``````` +pppp` `2`v`>pKpjp5p```pp +pp```pp pp0@```` ` @pp0@```pp +p0@```` @pp0@``````C`4pp:pAp0@0@ @ @ @``` `p +p +p0@ @ @````` ``pppp +0@`````pp pp0@0@`````=`;pp=pppp0@ @ @0@``` @pp0@0@ @0@ @0@ @ @0@`` @pp0@```pp0@0@0@ @ @0@ @ @````` +` +@p +``?`¼a``Šq,q>pxp @pp0@ @`` @pp0@` @ @`` @pp0@````p0@ @0@ @pp0@0@``0@``p0@ @pp````` @``ppp0@ @pp0@0@````p` @pp0@` +``p p p p @pp @`` @0@ @` @ @````p`pppp0@0@ @ @ @ @p0@````` ppp```ppp0@0@` @pp0@ @ @0@ÿœ`Ûpp,pp +pp0@ @ @0@```0@pp0@0@ @0@ @0@ @ @ @`` @pp0@``` +`p p0@0@0@ @` @pp0@ @ @`````$`pp,p`/`¨a.`zqqpd0@pp0@ @p` @p0@ @ @0@ @`` @p0@```pp0@ @ @pp @``0@``p0@` @ppp```````` ppp 0@ @pp @0@````p` @pp +0@```5`p$p(pp0@pp @`` @0@0@`` @0@p` @``pp pp @0@ @ @`` @0@pp @````` pp!p ` `` ppp +0@0@```pp0@ @ @0@ÿœ` ppp +pp0@0@``0@0@` @`p0@p0@ @ @0@ @0@ @ @p````` @ppp0@````pp0@0@ @p``` +`pp +p0@````0@```+`:`.ppJp.``P`™`>pˆp„p4p0@```0@``pp0@ @ @``pppp0@```p0@`` @p +ppp` @ @pp```` @p0@``pp````pppp @`````pp p0@0@ @0@p```````p pp`` `2`b`$pApJp-ppp0@ @ @ @0@`` @pp0@` @pp0@```p0@``````p +pp +pp````` ``p pp```pp +p0@ @0@0@0@ @ @0@p`ÿœ!`‚pp0@p0@0@``0@0@````ppp0@ @ @0@ @0@ @p````` @pppp0@````pp0@0@ @``` ``ppp +0@````0@``+`>`*ppLp2p``1`p&p(pp0@`````p`` +``pp0@ @0@``pppp0@```p0@` +` @pppp` @` @pp``` +` +` ppp +0@``pp````ppp0@`` @ppppp0@0@ @0@0@``````ppp```:`j`$pIpRp1ppp0@ @0@ @`` @0@p0@` @pp0@````ppp````-`I`%p/pNp'ppp @````pp +0@`pp0@0@ @0@0@0@ @ @0@p`ÿœ(`yp0@0@ @0@ @p0@0@ @```ppp0@ @p0@`` @0@``pp0@````` +` +`pp p0@`` @p p0@pp @````` +pp0 +@`` @pp0@````(`p p4p"p`` +`ppppp`` `pp0@` ``1`p3p(0@ @pp```pppp`` @pp`` +```ppp p @`` @pp`` +`` `pp0ppp @```` @ppp0@````ppp``pp0@ @` @ppp0@ @ @0@p`` +`$`G`p0p6p"p0@0@ @p0@ @p` @p0@pp0@` @0@``` `pp0@``)`p`­`]pnp¼pfp0@`` @pp0@0@0@ @ @0@0@0@ @` @0@`ÿœ#`wp0@0@ @0@ @p0@0@ @```ppp @ @p0@`` @0@``pp0@`````` +ppp0@`` @pp @p0@``` ` `pp 0@````ppp @``` ``ppp0@``` @````p p p ```,`=` +pCp<0@ @ppp``pppp`` @pp`````ppp p @p` @pp```)`8`.ppLp.pp @````0@pppp`````ppp``pp0@ @` @ppp0@ @0@0@`````` +pppp0@0@ @p0@ @` @pppp0@` @0@``` ` +pp0@` +`5`•`Þ`rpƒpñpŠp(p0@p` @0@0@0@ @ @0@0@0@ @` @0@`ÿœ t@pp @ @0@ @p0@0@ @ @ @0@0@ @`` @0@``pp0@`````pp0@`pp0@0@``pp0@```` @pp`````pp +p0@ @```ppp0@ @````````ppp```*`.`p;p20 @ @pp @ @pp`` @`````pppp0@p0@` @```*`:`3ppQp2p 0@ @ @pppp0@```` @p0@0@ @``` +`pppp0@p0@ @`` @pp0@0@pp @0@0@ @ @pppp @ @0@ @`````p0@` +`'`|`µ`Wphp½pup#p0@p0@ @0@``ppp @ @p0@ @0@`ÿœ t@pp @ @0@ @p0@0@ @ @ @0@0@ @`` @0@``pp0@````` pp0 +@`pp0@0@` `pp0@p @` @pp```` @pp0@ @p0@0@0@ @````````p p +p` +```p +p#p0@ @0@ @ @ @p0@` @```,`pp"pppppp0@`` @p```&`%p p5p"pp @0@ @pppp0@``` @pppp @ @```(`pppp +0@pp @ @0@ @0@ @pp0@0@0@` @`ppp0@ @0@ @``` @ @```B`c`4p;plp?pp0@pp0@ @0@```ppp @ @p0@ @ @0@`ÿœ s@0@ @pp @0@ @ @pp`` @0@p`````pp` @p0@``` @p0@ppp`` ` ppp0@ @`ppp`````` @p +ppp0@```p0@``````` `pppp`` +`` +p +ppp0@p`` @` @0@ppp`````(`\`4p'pFp7ppppp0@`` @ @` ``ppp0@ @p` @pppp0@`` @0@ @pp0@`` `6`o`6p0pXpCp0@pppp @ @`p0@` @pp0@0@0@p` @ @p0@`p0@```` @````!`pp)p0@ @p0@0@ @0@```ppp0@ @p0@ @`ppp @ÿœ s@0@ @0@ @pp @0@ @ @pp`` @0@p``````ppp @p0@``` @``0@`pp`` @pp0@ @ppp0@```````pppp0@` @p0@````````pp``````pppp0@p````` @p ppp``` ```,`j`@p/pVpA0@pp p0@` @ @```ppp0@ @`` @pppp0@`` @0@ @`pp0@```V`µ`ZpRpŒpop$p`pppp @ @`p0@```ppp @0@0@p` @ @p0@ @0@0@``` @`````pp +p0@ @pp @ @0@0@```ppp @p @ @ @pppp @ÿœ`up @ @ @0@0@`` @p0@` @p0@```` +`pp pp0@0@```pp```pp` @p`` @p0@p` @pp0@ @```` +``ppppp````pp p`````` @0@```pp p +p p +pp0@p`````$`*`p7p,pp```` p ``B`0p p>p1p `ppp``pp0@ @ @pp0@`````pp p0@0@````ppp` @ppp```V`²`\pLpŒpop&``ppp p` @0@0@p````pp0@` @ppp0@ @ @0@ @`ppp0@0@`````p0@`` @p0@` @p0@ @ @0@pp0@ @` @pp0@ÿœ`wp0@ @ @0@ @ @pp`` @p0@` @0@p0@``` `` +ppp pp @0@```pp`` `ppp @```ppp0@p` @p0@ @````` `p p pp`````ppp``````0@p````pppp ppp0@p````A`€`º`pÕp”p/p +``2`[`pJp6`` p ppp`pp +p``pp0@ @ @pp0@``` +` ` pp0 +@pp````p p p` @ppp```2`l`8p(pPpEp``ppp p` @p0@0@p````ppp` @ @ppp0@ @ @ @ @ppp0@0@````pp0@` @0@`` @p0@0@ @pp0@ @` @pp0@ @ÿœ%`0 @ @0@0@ @````pp`` @p0@` @0@0@```` `` +ppp pp`0@` @p`` +`pp` @` @ppp0@0@ @0@ @ @`` @ppp0@`````pp0@`` @````p````ppppppp0@p```2`‚aav`q§q(pOp`'`z`Ç`&p·p–p7p ppp0@p0@` `pp0@`` @``ppp0@`` ` @pp ``p0@` +``ppp` @p p +p````%`p ppp +p @pp +p``pppp @0@````p0@ @0@0@pp @ @```ppp0@p0@0@` @0@0@ @ @0@ @ @```pppp0@ @ @p0@ @ @0@0@p```ÿœ(`…p0@ @0@0@ @````pp`` + @pp +p @0@0@`````` `pp +pppp0@`` @pp``pp`` @p``pp +p0@ @0@0@ @``` +``ppp +pp``` ``ppp0@` @p`` @p`` @p 0@pp0@p```6`¤aBa¢` +qñqhp]``K`Æa3`&q-pöpQppppppp0@``pp0@`` @``ppppp``` @pp``p 0 +@` +``p p `` @ppp```` ``pppp` @p +p` +`pppp0@0@``` @pp 0@0@0@ @pp0@ @```pppppp0@0@` @0@0@ @ @0@ @ @```pppp0@ @ @p0@ @ @0@0@````ÿœ$`ƒp0@ @pp0@ @``` `pp` ` @pp0@pp0@0@`` @` @`ppp0@`` @p @`` @0@ @p +p0@ @0@0@```` +``&`p +p0p"p p````.`1ppCp,p +p` @p```p0@ @0@``0@ @p`` `$`t`èaA`qkqpG` `^`ÞaF`qZqpLp0@pppp0@``pp @` @``pp0@p`````p p @p +pp```0@```!pp(p 0 @````` @``` @p```pppp0@` @`` p pp pp0@ @ @0@ @`` @ppppppp @`` @pp0@ @ @0@ @``` @` @pppp0@ @ @ @0@` @pp @ @``ÿœ'`}p +0@ @`p0@ @p`````` +` @pp0@pp0@0@`` @` @``ppp0@`` @p @`` @0@ @pp0@ @ @0@`````-`>`-ppPp2pp`` `)`F`MppgpHpp`` @p`` +`pp0@ @```` @p +p```0`d`…`ppxp!``L`¢`ä`qpºp4p +0@pppp0@` @p @``0@``p0@p`````pp @pp0@p`````"`1pp:p,0 @`````````` @```;`p2p.pp0@0@ @` `` ppppp0@ @ @0@```````p pp ppp0@`` @pp0@ @ @0@ @``` @` @pppp0@ @ @ @ @` @pp0@0@``ÿœ`vp0@` @pp0@ @`````` @p +p0@pp0@ @ @0@` @p0@p @p```pp @ @ @0@0@ @0@`````-`:`,ppFp,pp p``(`@`MppcpB0@`` @pp``pp0@ @p`` ``pppp````#`p'p p ` `,`T`u`pˆpfp0@0@pp0@ @``0@`0@0@p` @````pppp```p0@pp````( 8@pCp0p p @`````` @ @` `*`I`p8p6pp pp0@````p +pp +ppp @0@ @```` ````pppp0@0@0@ @0@0@ @ @ @ @ @` @pp0@ @0@`` @``ppp0@0@ @ÿœ`t0@`` @pp0@ @p``` @ @pp @p0@ @ @0@``p0@` @pp```pp0@0@ @ @0@ @0@ @ @p``` +``"`ppp pp0@``$`-pp7p&0 @`` @pp```p0@ @p````pp"p0@```pppp```$ +@p8p*p0@ @pp0@ @`` @p0@0@p` @p`` +`p pp0@``````p0@` `$ 4@p;p(p +0@p```` @0@` `&`=`pp*p)p0@p0@````ppp0@` @0@````` @`` ppp p0@0@ @0@0@ @ @ @ @p` @pp0@ @0@`` @p``ppp0@0@ @ÿœ r@0@`` @pp0@0@ @ @ @ @0@0@0@ @0@ @0@` @`` `pp0@``pp0@0@ @0@ @`` @ @````` ` ```pppp````pp0@`` @p p````ppp` @p`` ``ppp0@```p0@`` ` ` +ppp0 +@`` @pp0@````p0@p0@```p`` `p p +p0@`````pp!p```.`p+pppppp````p0@p````;`f``pŒ0„@p?p0@``pppppp`` @p0@`````pp0 @`p p0@0@0@p0@p` @0@ @ @0@0@0@ @0@0@`````ppp0@p0@p`ÿœ r@0@` @p0@ @ @ @ @ @0@0@0@ @0@ @0@0@```` ``pp0@``pp0@0@ @ @`` @0@``````` +`` +ppp0@`` `pp0@`` @pp``` `pp`` @p +p```ppp0@```p0@```pppp0@`` @pp0@0@``` @p0@pp`````` `ppp p0@```/`L`GppipBp``,`p!pppp pp` @p0@``` `"`sajbV l@qÜqàpÍp:p +```pp +ppp0@` @p0@```(`D`p-p8p#p pp0@0@p0@` @p0@ @ @0@0@0@ @ @0@0@0@`````ppp0 @p0@ @``ÿœ" r@0@ @0@0@`` @0@```pp0@0@0@```p0@ @0@``` ``,`p)p,p0@0@0@p0@ @`` @` @ @`````` +``p pp +pp`` `pp0@ @ @pp``` `p```"`pp/p"p` @p p +pp`````p0@` `ppppp`` +`pppp0@p @`` @ @pp0@````````ppp +p```K`Š`„p.pÂpnp``"` +pp pp +pp`` @p0@````@`æ#4@e`‚ts¾q©prp` +``p pp pp p +p```pp```6`ªa`:pÊpÐptp$p p0@` @pppp @0@`` @p0@ @ @0@0@0@ @ @0@p`````/`)p p4p'p p0@0@ @``ÿœ% r@0@ @0@0@``0@0@``` `pp0@0@0@```p0@ @0@````$`>`p9p8p0@0@ @0@pp0@ @`` @` @ @````` +``pp +ppp`` @p0@ @0@p````p``?`b`_p +ppfpp @pppp````` +ppp``ppppp`` +`pppp0@``````0@ @pp0@```` `$`:`O`p/pHp4p```O`Ž`’p:pÔpvp```p0@p +p p`` @p0@``` T@a,df3`öuXt²r!p’p`` `pppp +ppp p```````paŽbx`†qòqèpöpHpppp```pppp0@0@`` @p0@ @ @0@0@0@ @ @0@``````3`3p p>p/pp0@0@ @``ÿœ `u0@0@ @0@ @ @``` +`pp +pp0@ @ @0@ @ @0@``` +` `5` p/p.pp @ @pp0@0@0@`` @ @ @ @ @ @```` +```p +pp +p````pp p``pp0@``` `p``]`¤`Âppýp°p/p` @ppp`` `` `pp)p`````pp p``ppppp`` ` +`ppp0@``ppp`````&`f`ª`É`4ppÂpp.```%`X`Zp$pŠpR0@`` @ppp```pp +p0@`` @`B`ìbþd²ats¶q¥ptp```pppppppp @```(`’bc?`¾r—rŠq=p\ppp``` @ppp0@0@ @0@0@ @0@0@ @0@ @ @ @`````!pp+p p p0@ @``ÿœ!`{p0@0@ @0@ @ @``p```pp +pp0@ @ @0@ @ @0@``````ppp +p @ @pp0@0@0@``0@ @ @ @ @ @````` +``pp p +p````pp p` `ppp`` `` pp ``[`¬`Êp +qp¸p/p````pp`` ` ` ` pp-p``` ` +`pppp```p0@` ` @ppp0@``ppp`````^`øafam`qdq^púpRpp +p ``&pp8p"0 +@`0@`` ` +`ppp0@ @`` `"`rabb6`bqÍqÂpÇp

pp +ppppp p``````pp0@``ppp 0@`p```` `` `pppp0@```pppp````pp p````8`R` pFpDp(pppp```ppppp @ @0@0@ @ @p` @p0@ @p` @0@ @pp @0@ @p`ÿœ$`|0@` @pp0@0@```pppp0@0@0@ @0@`````` @pppp0@ @0@``` +`pp0@pp0@ @0@0@ @ @`````` +@p p +0@`````` @p +p``` `````` p +p` @pp pp0@`` ``ppp` @p ppp0@```pppp` @ @`` +```ppp @````pp` `,`›a¬bw`qqq˜q]pºpSp0@```p pp````` `pppp```0@0@0@ @ @````pp0@p @ @0@0@```pp p```` `pp(pp pp0@ @pp0@p` @pp0@0@ @ @0@ @0@p0@ @ @0@0@ @ @0@0@p``p0@ÿœ"`xp`` @p p0@0@````ppp0@0@0@ @0@`````` @pppp0@ @0@ @``` +`pp0@p0@ @pp0@0@ @ @`````` @p p0@`````` @pp``` ``0@`` ``6`R`%p,p`p8pp + @p``` ppp p @pppppp```ppp`` @``` ``pp 0@```` +pp``8`¿aØbopr_q´pËpRpp +`````ppp` @```ppp 0@ @p0@0@ @0@`` @pp0@`` @0@0@0@```pp +p```A`0`p2p@ppp0@p @pp0@`` @pp0@0@ @ @ @0@0@p0@ @ @0@ @ @0@0@```p0@ÿœ`s`` `` ppp0@0@`` @pp0@ @0@ @ @ @ @0@0@ @p0@``` `p0@0@```pp0@`pp0@ @` @ @ @p0@```` @0@```` @pp` `B`¬`Ú`pxqp p-p @pp`` pppp````ppp0@```ppp` @0@```0@pp`````5` p pp`(`œafaÇp*qûqNpmp"p 0@``` `p +p0@0@```pp 0@0@ @p0@` @pp0@`` @p0@0@p @p0@` `,`Z D@pNp[p$pp`0@0@0@0@````ppp0@ @`` @0@0@0@ @pp0@ @ @0@`````p0@ÿœ`s`` ``ppp0@0@ @`` @pp0@ @ @0@ @ @ @0@0@ @0@ @pp0@````p0@0@```ppp```p0@ @` @0@ @p` @0@` @` @0@`` +``8`JppRp0` `baaN`Ùp´q±püp9` @p#p``ppp p```` +pp p pp```ppp`` `pppp @pp`````5` p"p p ``H`²`ãppûpžp7pp0@````p0@ppp``p0@p0@` @pp0@` @pp0@` +@pp0@ @p0@0@` `(`L`<`pFpQp pp`0@0@ @0@0@````ppp0@ @0@0@`` @pp @0@ @pp0@ @ @0@`````p0@ÿœ!`r``` @pp0@0@ @``pp0@ @`` @pp`` @0@pp0@ @````pppp`` @pp0@ @```p0@```ppp` @0@0@`` @ @0@ @p @ @`` `*`T`jp p~pJ``Z`ña6`Åp¤qpèp/` @p"pp``p0@```#`ppppp````pp` +``p +ppp +p0@p0@p````"` +ppp ```2`L`pBp2p ppp0@```` `ppp ppp @ppp0@``` @pp0@```pp0@`` `0@pppp0@ @```&``p&p/p0@`0@````pp0@0@ @pp0@` @0@0@ @ @0@` @0@0@0@0@ @`p0@ @ @0@ÿœ `r``` @p 0@0@ @``pp0@ @`` @pp`` @0@pp0@````pppp`` @pp0@ @` @p0@```ppp`` @0@0@`` @0@0@ @p```0@`` `&`L`^pptpFp`2`}`¦`upXpÝp|p` @pp0@` @```/`pp$ppp``` @p``3`pp&pp +pppppp``` ```pp +pp```` +pppp +pp0@`````pp +pp0@p0@`pp0@`` +` @pp pp```pp0@```` ``p +p!pp +0@ @``` ` +`pp0@ @````pp0@0@pp0@` @0@0@ @0@0@`` @0@0@0@0@ @`p0@ @ @0@ @ÿœ`s`p` @0@0@ @p @ @0@0@ @`` @0@ @0@0@``` +`ppp +0@``pp``` @0@ppp``` @0@`` @ppp````ppp0@`` `pp````*`:ppAp,p``,`6`%ppBp(0@```pp 0@````"`ppppp``` @p``<`pp,p p``pppp` ``ppppppp``` ``pp p`ppp````` +`ppp0@pp0@ @pp```"``pp'p0@ @`pp``````,`n`qp0pŠpLp0 +@ @ @ @`pppp0@````` @pppp0@pp0@ @ @0@ @pp0@ @ @ @0@0@0@ @p0@ +ÿœ`w`pp0@0@ @`` @0@0@0@ @```p0@ @0@0@````ppp +0@``pp``` @pp ppp``` @0@`` @ppp````ppp0@0@`` `pp`````pp0@`` +``pp +p0@`` ``pp0@```` `pp +0@````` ````6`pp,p"p``pppp``$`(pp9ppppp`````pp``pp0 +@ @` @p0@p``pp0@ @ppp` +```ppp 0@ @pp``````.`zaaphqjpÈpHp0@ @ @0@``ppppp``````ppppp0@pp0@ @ @0@ @pp0@ @ @ @0@0@0@ @p0@ @ÿœ`y`ppp0@ @p``````ppp0@ @````pp0@0@0@ @0@` @`` `pp0 @```pp```,`0pp=p,p p0@`` @````pp0@`` @p ppp0@```0@`` @ @pp0@`` @`p0@```#`pp0 @```pp` @ @ @`` +````N``pYplp>p` @p0@``.`3ppIp(p +pppp`` ` `````ppp0@```0@pp`` @pp0@```pp`` ` +`ppp @pp``` +``H`ÇaÄaÈp¶r`l`zpp¥pfpp0@ @ @```pp0@ @ @pp0@` @`` @0@``pppp @p``````` +``p p0 @` +`ppp`` `pp @````H`åbþd¤`Lts\qepd0@````` +pp'p``ppp` +`` @pppppp 0@``pp 0@` @0@```ppp +0@ @0@``` `` p p0 +@`` `.`l`ô`úpZq>p®p=pp` @pppp```pppp`````pp pp```pp0@```0@pp0@`` @ppp```pp0@ @0@ @0@0@ @`` @ÿœ!`s`p0@ @``` @ @`pp p0@ @``` `p +ppp0@ @0@ @ @`0@0@0@```````4`P`RppypNpp0@ @ @` @`p0@ @ @p0@` @```p0@`` @pp0@p`` +``p````pp0@` +`ppp`` ``` @````\aAdf~auüuqïp€p0@````ppppp` `p p p``'`F`JppLp&pppp 0 +@0@``pp0@` @0@ @```ppp +pp0@0@`````pp#p0@```.`X`bp"pvpFpp +p` @ppppp``ppp````` pp p pp`` `pp0@``` @pp0@` @ppp```pp0@ @0@ @0@0@ @`` @ÿœ& s@0@0@ @``` +`p0@0@p0@0@ @`` `p p0@ @ @ @`````ppppp @0@````````&`%p +pacŽe¸`šutFq¨plppp```&`pp'pp``pp0 @``B`ž`¯p4pÏpfpp0 +@ppp +p` @pp @```````` +pp +ppp @ppp```` p pp0@`````p +p"pp 0@` @pppp0@ @ @p`` ``ppppp```pp0@ @`` @pp0@0@ @pp @ @ @0@0@ @ @0@0@`` @ÿœ% s@0@0@ @````p0@0@p0@ @```pp0@ @ @0@``` `ppp0@p0@0@````p`` `` pppp0@ @0@ @` @0@```pp0@pp0@````` `p p 0@``` ``pppp```pp0@```p0@` ``&`ppp``J`n`¬`tpp¤pÁp*`„aâbø`&rr&pÜp8p pp ```"`pp#p p`` ppp ```d`ÞapHq5p¢p @pppp```pp0@p```p` @`ppppp @pp0@`` +`ppp @`````pp +pp0@` @ppp0@ @ @``` ``p pppp```pp0@ @`` @pp0@0@ @pp @ @ @0@0@ @ @0@0@`` @ÿœ t@pp0@`` @p0@0@ @ @ @0@`` @0@``` pp0@pppp0@0@ @ @`` @pp0@```p0@```` @0@` `ppppppp`` +` +```pp p 0@```` @ppp```pp0@``ppp```0`S`p0p4p` `ma(b5aˆp#qärGpÔ``Œ`Ø`pÄp¬pBpp ppp` `` ppp```pp p +p``[`Î`ñp:q0œ@p` +`pppp````p pp +p` @0@ppp @pp` @p0@```p0@```` @ppppp0@` @p0@ @0@`````ppp +0@ @pp0@ @ @0@0@p0@ @ @0@0@0@0@ @ @p``pÿœ t@pp0@`` @p0@ @ @0@ @0@ @`` @0@`` +`0@``pp +pp @0@ @ @ @0@0@```p0@``` +` + @p +p``pppp```````p +pp +p +p0@```` @pp``` `pp0@``pp +p +```<`k` pBpHp ``‡bdcp9stt q”p` `pp0p$ppp ppp`` @0@`` @p p +p``1`z`‰0*@p™pTp``p +pp +```&`*`p$p>pp` @0@pp0@``` @ppp`p0@ @````0@ppp0@p @` @p0@ @0@`````ppp0@ @pp @ @0@ @0@0@ @p0@0@ @ @0@0@0@0@ @ @ @0@`pÿœ r@0@ @``p @0@0@0@``0@0@ @ @ @0@````````p p 0@ @0@`` @0@p```pp```p0@``````pp0@ppp`` ``` +` @pp!ppppp``0@`pp``` + @ppp`` `pp 0 @``4`X`p8p:p``„b2ddc``s°t}q¤pppTp2pp`pp +p +pppp @`````-`p$p$p`` &@`0pp5p"p``ppp```>`H`%pDpjp*p` @0@ @pp @``` @p +p0@p0@``0@ @pppp0@ @ @ @0@0@` @p @0@` @p0@ @p0@ @ @0@``p0@pp @p` @p0@ @` @0@0@ÿœ r@0@ @``` @pp0@0@0@p` @0@ @ @ @` @````p p 0@ @0@`````pppp```pp````0@`````pp ppppp```````pppppppp``0@pp`` ` + +@ppp`` `pp0@` ` `4` +p"pp``TajbÌb(`0rPrñpð`"p pnp>pppppp``pp0@````N`w`pfpLpp0@p @p p +p +p @p`` `"`<`D`pDpjp*0@ @p` +@pp0@```` `ppp +pp0@``0@0@ @pppp0@ @ @ @0@0@` @p` @ @p0@p0@ @ @0@``p0@`0@p` @p0@ @` @0@0@ÿœ p@ @ @0@````````pppp0@0@ @ @ @0@```ppp`` `p0@`p0@``````pp&p0@ @pp``` +``p0@` ```ppp 0@````` +pp``ppp`ppp`` @ppp`` @p0@```0@````` `ppp``'`Ža `ê`pìqpJ`*ppTp2ppppp`` ` +pp pp`` +`%`€`¼`p›p^0@pp"p&pppppp````` ``)`"`p.pBppp0@`` `pp0@``` @ppp +pppp` @0@` @pp0@0@ @p``` @pp0@` @0@``pp0@p0@pp0@ @0@0@ @ @ppp0@`` @pp0@ @```p0@`ÿœ p@ @ @ @``` ````` pppp0@0@ @ @ @0@```ppp```0@``p0@````(`>`:pp\p40@ @p`` ``` +p +ppp``` `ppp` @0@` ``p0 @`p0@`ppp`` @`ppp`` @0@`````` ```` `2pp5p&p```.`N`>`p@pGp +`pp"p0 +@pp pp` +@p pp`` +`#`x`ª` +0‡@pF`` +p0p:p&pp p0@````` ```pppp +pp0@`` +`pp0@```)`pp&p#p +ppp 0@` @0@` @ppp0@0@``` @pp0@` @p p```pp0@ @p0@pp @0@0@ @ @ppp0@`` @pp0@ @p``p @`ÿœ( p@ @``````` `p```p +p pp +pp0@0@`` @ @0@0@`` @0@0@0@````ppp````;`V`Lp&p}pBppppp```0`4`p,p,pp +0@` @`` ``pppp` @``ppp`pp0@```` pp p +p` @p`````` `````<`PppmpHp`` ```pp p `````pppppp ```pp0@```@`_ @pJp`+`p$p.pppp +0@``` ````pp&ppppp @` @`p0@```3`p p(p'pppp +p`` @p p` @pp p0@0@ @0@````ppp`` @p +p +p` @pp0@``pp0@ @p0@0@ @` @pp0@0@`` @pp0@0@ @0@`ÿœ, p@ @````````p` +`%` pp(p!ppp0@0@`` @0@ @0@` @0@0@0@````ppp````3`J`p```K`L`p8pZp*ppp p```(`:`-ppMp&p` @``ppp` +``-`<`C`2`)p*ppJp ``pp p0@```.`„`ªppŒp`p/p"ppp +p``` ` +` @pppp +p`````` p p6pp```0`pp3p`pp +ppp0 @` + @ppp @p0@````ppppp0@```1` +p$p"pppp @pp0@ @0@``` `ppp pp @pp0@ @0@pp @pp0@`````ppp0@0@p0@0@ @0@ @0@ @0@0@ @ÿœ% p@`````0@0@```` +pp p p0@0@`` @0@ @0@``ppp0@``` ``ppp`` +```p ppppp0@`` ``4`5ppFp(0@ppp```>`Âaxa›pNrqZpTp ``*`e`h` pLp‚p:ppp p```F`b`Kpp +` @```ppp```!`,`/``p"pCp"`` +`pp p0@```.`ˆ`¸pp¦plp/pp p +ppp``` @pp p ppp` +````` pp2pp```0`pp=pp` @pp +0 @` @pp +p @p0@`` ` ` `` pp!p 0@``"`5` +p p"pp +p +p @pp0@ @```#`pp pp +p @pp @ @ @pp0@p0@`````p +pp0@ @0@pp0@ @ @0@0@0@ @0@0@ @ÿœ- q@ @ @ @0@0@ @` @ppp0@ @0@ @0@0@ @```ppp0@`````` +ppp ```(`&p +p3p$p +p0@```` ``ppp +``pp0@` `4`¢aDaspLqÑq$pBp`` `M`R`p>pmp0pppp```H`f`OpBppB0 @`````pp pp`````pppp```ppp0@````Z`}pprpL0@`pppp` @``ppppp p`` ``` +`pppp````pp.pp` @ppp ```pppp``ppp```` ``ppppp```#` p ppppp @ppp`` @```@`c`>p!pfpTpp @p0@```0@pp0@0@ @`````ppp +p` @0@ @p0@ @ @ @0@0@0@ @ @0@0@ÿœ$ q@ @ @ @ @0@ @p0@ @0@ @0@0@ @```p0@0@`````` +ppp ``$`D`@pp[p8p0@` @````p`` +`pp0@```Z`¸`·p pÝpœp(pp``!`.` p*p5p`ppp```0`F`)p.pWp*0 @``````pppp`````pp ````pp pp`````"`1`p&p p` `pp p0 @```ppp pp @```ppp` +``pp`p +ppp` @ppp```ppp```ppp`````` ppp +pp``` ` ` `p ppp0@pp````````x`Å`†pKpÆp¤p2p + @p`````ppp0@0@ @`````ppp +p` @0@ @p0@ @`` @pp0@0@ @ @0@0@ÿœ# s@0@`` @p0@p` @ @0@ @0@ @0@ @ @pp0@ @``````ppp``#`F`Ippcp`T`pNpJpppp +p`` ppp0@ +@ppp`` +`ppp`` `p`pppp``ppp```p ppp0@0@````````‚`é`¬phpêp³pp¢p}p(p``ppp``` pppp +0@0@ @```ppp```ppp0@0@ @````ppp0@ @ @0@0@ÿœ( r@``p0@p0@ @`` @``pp0@ @`` @p`ppp0@ @``` `0`ƒ`¢`QphpÇpdp +``pp(p````pppp0@````&`pp)ppp0@````` `` ppppp``` +`$`>`p;p2pp`` @0@0@ @``` ` + @pp0@``` ` @ppppp`` +``` +`` +pp +p pp @` p0 @ @p p +p````,`p``pp=p$p``Q`èa.`Dpâqp‡p ` pp``(pp)ppp pppp0@```p```=`:`p:pCp"0 @```pp``ppp0 +@ @pp0@````` `&`E`,ppHp>p``1`p pp```pppp0@ @0@0@ @`p0@```ppp0@ @0@```` ` ppp +pp @ @0@0@ÿœ$ r@``ppp0@ @`` @``pp0@ @`` @```pp0@ @`````aa`¥pÄq‰p¼p`` ppp`````ppp0@```9`J`(p0pWp*p p0@ @ @`` +`pppp`````,`>`pCp2ppp` @ @ @0@`` +```ppp0@``` ` @ppp pp `` `` `"`0`p#p"p0@``pp `` ` pp +p p```$````+ppGp,p``G`Ôa`PpÞqpƒp`pp``&pp!pppp p0@0@``````B``Š`pŠp¥pFpp` @0@``ppp0@ @pp0@````` +`` pp0@``j`;p pCp``(pp?p)pp0@ @0@0@0@`p0@```ppp0@ @0@`````pp +pp0@ @0@0@ÿœ! r@0@`` @pp0@ @ @ @ @p0@ @p`````pp0@0@p`````pa;a0`“pèq«pÊp p`ppp`````pp +pp`` +``@`X`-p:pgp2p p0@ @ @`` @``````2`7ppBp0pppp````` @p````.`,pp=p"``p``` ` `ppp p0@` ` +``D`NppQp>0@p``pp p ````p ppp``````#pp4p````b`˜`8pepˆpUp`p p` +`ppp +p p p p0@ @````````Ø`Ü`!pÞpÿpbpp` @pp`` ppp p```pp0@``` +`pp```pp``&`Œ`Lp,pZp'`"`1ppTp9pp0@ @pppp @pp @ @0@` @`` @0@pp0@`p0@ @ÿœ+ r@0@`` @pp0@ @ @ @0@`p0@ @p`p````p0@0@p`````L`Ó`à`Sp qpŠppppp0@````ppp`````*`8`p&pEp"p +p @0@0@0@ @ @``````2`7p +pDp,p ppp````` @p```#`6`8ppMp*`````pp```p p0@```)`X`Xp0o@pJ0@` +`p +p p``` `p p$p0 @` ` ` +``ppp`````,`pp,p-pppp` @p`pppp +0@ @``````X`Â`Ô`!pÖpípZp`` +` +pp +p p`pppp```pp0@`` +` +`ppp```pp` `[`7ppAp ``/ppGp-pp0@ @ @pppp @pp0@ @ @0@ @`` @pp0@ @`p0@pp0@ @ÿœ q@0@`` @ @pp0@ @0@0@ @ @ @pp```pp` @``` +``N`d`$pp ppp0@ @``0@p`````pp``L`¡`‚p(p¦p†p&` ` p pp``` 3@`D`#p,pPp$pppppp``` ``` @p pp p` +````p0@pppppppppp0@``4`Z`*p2pTp>p0 @```*`6`p$p9p```p$p&p```` +pppp` @pp` @pp0@`` @pp`` ``p +pp` +` +ppp`` `p p p 0@ @p`pppp0@` @0@``` ``(`p&p!p0@`0@0@ @pp0@0@ÿœ" q@0@ @ @0@ @0@ @p````ppp``p0@```pp0@``````` ``'pp0p"p +p0@`` @0@```p0@ @0@`` ``pp0@0@p`` ``%` +p"p`+`V`bppupZ0@pppp``0@0@```````-`¨a`apmq\q pXp`pp0 @` @`-`.`pp*0@p +ppp0@```` +``%`(` +p&p/p`` +` +``pppp +0@pp````p``*`˜`ô`dp¡pàp…p*0 +@` `"`Q`l`.pTpzp6p`pp0 @````pppp```p0@`ppp0@`` @pp``` `p +p +p``ppp````pp 0@ @0@pp0@ @ @ @0@0@````?`Z` +pWpJp0@0@```p0@ @pp0@ÿœ# q@0@ @ @0@ @0@ @p````ppp``pp````pp0@````````$`1pp:p&p p @` @0@```p0@ @ @````p p 0@ @p```0`O`pJp2`#`f`ˆ`ppzp&p`ppp``p0@0@```` ``9`Ða¸a6p™qœq?plp `pp +0@``&`=`&`pppppppppp +pp```$`G`L`p>pep*`` +` +``pp'p0@ @pp````p` +`B`èaz`ˆq qPp±p2p p` `&`c`€`0php’pBpppp``` `pppppp```ppp`ppp @`` + @p pp``pppp``ppp``` +`ppp0@ @pppp @ @0@ @0@0@```$`W`„`p|pjp)p + @0@` @0@` @p p +0@ÿœ s@0@0@ @ @0@ @0@ @`` @pp0@0@`` @pp0@ @ @``` ``$pp)p0 +@ @ @ @0@` @0@```` @ppp` @`` `&`J`k`phpL``z`ß`Jp·p¼pMp`pp p0@ppp @`````,`œaC`êphq,pëpPp @0 +@p p``D`a`.``pp,```hp2p p|pCpp``p0@``pp&p p```pp`` `p p``F`R`pCp8p+pp +p0@` ``(`"pp&p$p ``2`Øbšcƒ`xrörôq`pTp ``pp pp0@` @0@ppp````ppp0@ @0@0@ @0@ @`````ppppp`` @pp0@` @pp0@ÿœ%`q` @0@ @0@`` @0@ @pp0@ @0@0@0@0@ @0@`` @`p0@0@ @ @ @0@`````ppp0@` @0@pp`` @ @` @ @```<`n`8pCpXp'``Y`$pCpJp!p``` ``ppp +```9`6pp@pAp0@`` +`` 0@p p p``` +`````` +pp p` `:`Œ`„`p–p¤p:` `J`r`pcpTp!pppp````pp`````êa$`p‚p6aTaŒpŽqÿqlp¹pXppp0@`(`H` p+pHp0pp`` +````.`p+p``X`ap +pXpDp)pp 0@````"``pp"p``.`´b&c`fr“r~q'pD0 +@ppppp0@ @0@0@p```pp0@0@ @`0@p```` @ppppp0@ @0@0@``0@0@0@ÿœ"`s` @ @pp`` @ @0@ @pp @ @0@ @0@0@0@````pp0@0@ @ @ @ @````(`pp0p0@` @p0@p0@` @ @`` @0@````<`l`8p=p`p5p``ppp`` ``` `ppp +```;`6pp`ŽbÌbÐpÎsCrXq]pÀpIppp``P`Š`0p]pxpHpp`````F`b`p_pF``T`YppXp@p%pp +p```````ppp```daaŽ`.q[qNpp(0@pp0@p0@ @0@``pppp @ @``0@p```ppppp0@0@ @0@0@``0@0@0@ÿœ`t` @p```ppp @` @pp0@0@ @pp @ @0@` @0@`` +``pppp0@0@` @````<`b`Ip&p{pHp`` `ppppp0@ @ @```ppp``` `"`C`"p#p:p&p +``pp`` ``*`!pp$ppp`` +`$`$`ppp +ppp @``ppp```*`4`p` `2`p1p(0@` ````pp`"`aXaÁ`0q£q–p·p0ppp```6`R`pppp`` `` ` +`pp0@p ```ppp p``:`H`p9p`pp'pp +`` ` ``,`%pp`&`‘aDa¥`0qqŠpÇp8``p p``J`v`pXpXp` `C`2``"`îbRbŽ`°pÉqªrhq¶p¥p,pp``R`{`0pRpppHpp 0@```J`_pp]pLp` @ppp p0@``````& 1@p-p&p +` ``"`*pp5p6p0 +@ @pp0@ @``p0@``pp0@0@ @ @ @ @``` +`pppp0@ @0@0@ @ÿœ% r@ @````pp +0@`` ``pp0@ @0@ @pp0@ @``` ` `pp p```,`pp"pp +pp0@ @0@````S`Ž`mp>p¨pdpp` `pp +pp0@```` @p```0@```p`` @p 0@`pp```U`Š`hp>p£p\ppp +p``` ```0@pp ` ` @ppp ` `6 A@p<0 @ppp``` ```< D@p#``V`¢`Ù`2p¶pÞpœp<`` +pp``>`e`pEpHp`"`?`pp`O`üaca,`“pàrq`p‰p*pp ` `(`:`p$p0p$pp 0@```$`.pp6p"0 @` +``pp +0@``````3`~`‹ppšpjp$p`` +` pppp p0@ @p0@0@ @0@p```pppp0@ @ @```pppp0@ @0@ @0@0@0@0@ @ÿœ% r@ @````pp0@````p p0@ @0@ @pp0@ @``` ``ppp`` ``p ppppp0@ @0@````-`N`=ppXp8pp``pppp0@```` + @p p```` @ppp```ppp`pp```E`v`Zp6ppPpppp```` @`ppp` `!`` +ppp`` %@p"pp0@``````8`D`p ```"`7`.ppRpzp<``p0@`.`I` pp$p +``-`pp&p`<``è`³pxq7pÐpQppp`` ``pp pp +p0@`` `` ppp0@```pp +pp```` `0`¥a–a­pdqêqJpnpp @pp pppp0@0@0@ @p```pppp @0@ @ @0@p```pppp0@ @0@ @0@0@0@0@ @ÿœ( s@0@ @``0@ @```pp0@ @`` @pp @0@``` ` +`pp +pp`` +`pppppp0@ @0@ @`````ppppp +``pppp @````#pp+pp`` ``pppp`` ` +`p +0@``` ``2`)ppHp&p pp` @0@`` `pp```!`$`pp#pp ```ppp`` pp p``` `"`6`.`)`&ppp``p pUp.pppp` +`8`K`$p``p ppppp"``e``Np`p´pnp-pp p @ @`ppp0@``` ``pppp``` +`pp pp`````hascˆc„pðt +rÀpúp>p ppppppppp0@0@ @ @p```0@`ppp0@ @p0@``pp0@ @0@0@ @ @ @0@0@0@0@0@ @ÿœ$ s@ @p`0@ @p @`pp0@`` @pp0@0@``````pp0@ @pp0@ @0@ @`````` @p0@`pppp @`` `$`J`Kppcp4p```$`pp$ppp`` +`p0@``` @`` p +pp +0@`` @p`` @` ``'`$`pp'pp p` ````` +`pp#pp````$`6`G`2pp2p)p` pp-pppp ``$`H`M`p` `4p p\p0p pp"``Y`d`p`p~pBpp +0@0@0@pp0@ @````ppp pp```` +pppp```` `ˆaçd¤džq u s”q€pnp +`p ppppppp0@0@ @ @p```0@`ppp0@ @`p0@``pp0@ @0@0@ @ @ @ @pp0@0@0@0@ @ÿœ! t@``pp0@ @0@ @0@p``` @ppp0@ @```` @pppp @p0@`` @p0@ @``````p0@pp0@`````0`d`jp.pŠpDp +```"` `ppppp``p0@`` @p ppppp @ @ @```` @``.`2`pp.p*pp```(`5`6`pp(p0p9pp @```"`7`*`p$p'ppppp````(`b`^`p``"`d`ìa;`np­pàpap4p`pDppp/p p +``(`p +p(p#` `1``p +p ` `pp7p&ppp`````` @pp +p 0@ @0@` @pp``` @ppp` ` `"` p$p)ppp0@0@0@````pp0@0@````T`Á`º`,p˜pëpvp0@ @` @pp0@0@ @0@ @ @0@ @ÿœ u@p0@0@ @0@ @`````!`ppp0@``0@pp @0@ @``` @```pp0@pp0@`` @p````` ``p +ppp @pp`p```` @pp``````` @pppp p`` @`` ` @pp +p```` +` `Z`š`4pxp`ppp$pp``pp +p``````0@``4`t`®`rpnpÚppp` +`%`L`_`$p(p*pp p3p*pppp`` ``pp p``5`p p`:`Š`npNp°pbpppp` `````ppp p0 @ @p``````pp``pp +pp````ppppppp @p0@`` @ @0@p0@````pa`ÿ`=pÜq9p˜p$p0@`` @pp0@0@0@ @0@ @ @``ÿœ u@p0@0@ @0@ @p```` `pp0@``0@pp @0@ @````pppp0@`` @pp0@`` @``` +`p`` `ppp p```ppp``` @p`` +`pp` @`` +`ppp pp`` @```` ppp` @p` +`F`¾a"`hq +päpIp p.pp``p0@``````pp` `8`z`²`vprpâptpp` ```pp``p`&`c`pJpD0@p pppp``+`p``œa*`àp¢qfp²p&ppp` `````ppp p0@ @p``` +``` p p0 +@ppp +0@` +`` p +pp pppp @0@`` @pp0@p0@````X`¼`Â`3p«pìpppp0@`` @pp0@0@ @0@ @ @``ÿœ%`s`0@p0@0@ @ @0@ @ @ppp` @0@0@` @0@ @`` @pppp0@```pp +p0@`` @0@``` `p +p @ppp```` pp p`` @p 0@```p 0 @p``` @p ppp`` @`````pp```p``ea +a{`|qkqPpup$p)p``````` `````pp` `B`i`\` pZppFpp```pp0@``1`ÈaV`dpðpøphpp$p*p$p`` `#pp`0`Òa‚a pÞq¼pØp-ppp``` ` @ppppp``pp`` +``)`8`pp8p&p +pppp p`` +` pp +ppppp @p @`` @pppp0@ @````+`U`V`pIplp5pppp0@ @ @0@p` @pp0@0@ @0@0@ @`` +ÿœ!`q`0@`0@0@ @ @0@0@ @ @pp`` @0@0@` @0@ @`` @ppp0@```pp +0@`` @0@``` `p0@0@p``` ` pp p``` pp0 +@` ` @p pp`` ` @ppp p`` @`` `` @``&`:` p` +`W`Âa `(qpüp_ppp` @```` ````*`p)p ``Z`k`pJpVpEpp p```p ppp` `Wa`bB` q˜q¬pÔp`Âa]`bpîq +p—p0pp```(`&` p(02@`&`*`p(p9pp p +0@`````pppp0@p0@`` ```p`` pp$p!p`````p*p)p +pp0@ `` ` ppp 0@0@``````p`0@ppp0@0@0@ @pppp0@ @ @0@0@ @ÿœ# r@ @`p0@0@ @ @ @0@0@0@0@ @ @0@0@ @ @`` @`` @pp0@pp`` @0@ @ @````````$` pp&p0@`` `` pp0@`````ppppp0@```````p0@`` @```/`„aap q qp‚p%p p```$`)`(` ```.`p(p1`^`Ó`6p¹pÄp?`B`Xp"pvpLpp`` @pp0@p```R`‰`p[p`pCp0@````` pp```pppppp p p`````ppp 0@0@pp0@p`` ` +````ppp```` @p*p+p +pp0@ @0@p`` ``p +p#p0@0@ @ @0@ @pp0@ @0@0@0@p` @pp0@0@ @ @```p0@0@ @ÿœ% r@ @pp0@0@ @ @ @0@0@0@0@ @ @0@0@ @ @`` @`` @pp0@pp`` @0@ @ @``````2`~`”`+p‚p¢pD0@`` ` `p0@0@ @```` +p ppp 0@``````` pppp```````h`í`Êp%pÔpÎpZppp```(`I`d`V```:`p`pi`b`ÿ`:pßpìpc``.p +p:p,0@```ppp```p```!` +p!ppp 0 @`` +``pp p ` `` ppp`pp p p`` +```ppp0@`p0@pp````````` `0` p,p+pppp0@p0@ @p0@p```!`p +p/p0@0@0@ @ @0@ @pp0@ @0@0@0@p` @pp0@0@ @ @```p0@0@ @ÿœ q@ @ @0@ @ @0@ @0@ @0@ @0@0@`p` @ @`````p0@ppp`` @pp0@ @ @ @``````ta"aX`]q qxpª0"@``` 0@0@`pppp```pppp +ppp````` @p0@```````4`l`Xpp^p_p&ppp ```0`d`”`u`p `@`pˆp•`2`¼`(p¤p´pZp``pp0@```ppp `` +`pp`` ppp +pp0 @` ``pp p +p`` +`pp``ppp p`` +@pp p p0@```ppppp0@```` ``0`d`z`p†p‡p(p p0 @0@p0@0@`````p +p$pp @0@p` @0@ @pp @0@pp0@ @0@0@ @`` @pp0@p`ÿœ q@ @0@ @ @0@ + @0@ @0@0@```` @ @``` `pp0@ppp`` @pp0@ @ @ @`````&`œaŒaÜ`‘qŒrpêp.``' 6@`pppppppp``` ppp ppppp @`` @p`````````"`pppp +ppp ```8`j``mp +p1 @ppp}``V`pNp`p8p```pp`` ` `ppp`` +`pp +`` ppppp0@```pp p +p p` @```pp0@` `` +ppp 0@0@`` +`pp pp0@``````L`ˆ`ž`&pºp½p

`\`F`)ppTpJp)p```ppppp``` ```2```h`pnp•p>pp0@0@`p0@` ``;`:`p*p6ppp pp p`` ` `pp ppp`` ` ppp0@ ` @`` ` `p``6`2`"`ppNpMpp`pp0@pp0@`0@0@p`0@`pp` @ @0@0@0@0@`` @ppppp````ppppp0@ @0@ @ @ @0@``ÿœ( r@0@ @0@0@`` @0@```pp0@ @ @0@` @p```` ``- @`ba`ÊpEpìpåpNpp` +``pp&0 +@ppp`pp` @`` @```?`H`p60Q@p&p``0`D` p*pBp p +ppp @ @p``` @`pp` @p``p0 @ @pp```` @`` +`pp```,`?`$` +pp;p0pp`` @ppppp``` +``L`ˆ`’`p¢pÉpRpp0@``0@`` ``D`q`„`5pJp`pJp@p$ppp ``2`8`p*pAp p pp` @ppp @0@0@``````&`pp``@`,p p8p3p$pp @pp0@0@0@`0@pp0@```0@p0@ @0@0@0@ @ @ppppp````p0@`p0@pp @``0@0@0@``ÿœ# r@0@ @ @0@0@`` @0@```pp0@ @0@`` @p```` `$`7` `.a.b­b*q rPrMp¾pp ```pp$p` ppp ppp` @`` @```)`0 @p&p3pp````ppp pppp @ @`` ```` `p` @pp`p0 @ @0@```ppp`` +` pp```$`-`ppp/p p +````` `pp ppp`` +``@`l`z`pŠp§pFpp0@` @`` `:`X`‰`¤`cppBp†p–pLp:p.p `D`¨`È`pUp&pp0@``0@``8`O`J`U`t`|`p` p®pÖpjpNp>p`Ša^a¶`kq~qÔpÌp(p`` +` pppp` @ppp``````E`Z`pJpYp`` pp pp0@ @pp0@0@ @``ppp @```ppp0@ @ @0@0@ @0@0@0@```pp0@ @0@0@0@ @p0@0@ÿœ, s@0@ @ @0@0@```` @```ppp @0@ @````pp0@p0@``````YaˆcPb|pÞsrÕpôp%pp +``pp``.pp-ppp0@```` @` &@`[`d`!pVpzp00 @ @0@```ppp @```` @p````` @p``` `pppp```p p p p`` @``$`H````”`p¦pÝplp````!`Š`¯`pœp„p:pp +pp````ppp +p p0 +@``pp``<`S`&``8`j`œ`RpŠp´p^pNp:``¢a”aþ`qêr +pìp*p` `` +pp pp` @ppp` @```9`N`p>pCppppp p p0@ @pp @0@``` +` ppp @p0@ppp0@` @ @0@0@0@0@0@0@````p0@ @ @0@0@0@p0@0@ÿœ$ r@0@0@ @```` @pppp0@p0@````` `pppppp````` ``4`Æa£aJpXq€q|pˆpp0@`p`` $@p$pp p0@`` @`` `L`L`$pFpfp*0 @pp0@```ppp```` + @pppp````` @p```!pp$pp ` +``p p`` +` ` @` `F`€`’`Å`â`1qqKpªp9p```ea6ax`qaq&ptpppp +p``````pp&pp`pp p``(`:`p` `E`T`)p>pVp2p6p*p`haaL`nq>qhpžp` +` `pp&p*pp```ppp``pp` +``(`pppp +p @ppp p @``ppp```` ppp` pp p +pppp0@ @`` @ @0@p0@0@````ppp0@0@ @```ppp0@0@0@ÿœ% r@0@0@ @```` @pppp0@p0@``````ppp0@p````````B`ƒ`npp€p|p0p p0@p`` @pp p` @ @ @```&`,`p"p8p0@pp @```pp`````` ppppp````` @pp``pppp `` +pp```2`!pp(p``R`Š`‚``Â`GpÈq+p²pYpp``‰aŽaÔpqÁq^pzppppp +`` ``"`(`pp.pp`pp p +p` `` ` +`$`+`ppppppp`$`d`€`$prpˆ0:@``6`pp:p4pp````pp``pp`` `` ```pp @ppp p @`` +` ppp +``$`#ppp` +`pppp p +p p0@`` @ @ @p0@ @ @`` @pppp0@ @ @```pp p0@0@0@ÿœ+ q@ @0@ @`````ppp0@0@ @0@```` @p0@0@``````````p ppp +pppp0@p```ppp`` @ @``pp````p pp +0@ppp``` @p`````` ppp0@`````+`pp$p+p``pp p``pp``;`h`Ap6pap.``8`Y`B`?```Jp0ppŒpap&p``{a6a[p"qQpÞp`p,p\pJpp` +```!` +ppppppp pp``````p pp ppppp` +``(`pp%p`#`,`*`p2pHp2pp````p0@pp0@```` @` @pp0 @`````pppp``!p p p` &@pppppp0@0@`` @0@ @p0@``````` p pp p0@p @ @ @```pp ppp0@ @ÿœ( q@ @0@ @````pppp0@ @0@0@`````pp0@````p`````ppp0@ppp0@ @``0@p``` @```pp p```ppp @ppp``` @``` +``` +`ppp0@``` ``1` pp,p3p ``p0@``````G`p`Qp6pmp6p` `#````2`p"pLpGpp``O`¦`¡pp•p`´`€p^pèp®p8p`` ```p +p +ppppppppp`` +``p pp`0@```` ` `p``J``Pp2pbp`pHp*pp````p0@pp0@p```0@` @p p 0@``` ```ppp` `pp```` ` ppp)pp +0@0@`` @0@ @0@``` ` +``'`p%p4ppppp @ @ @```pp +ppp0@ @ÿœ% p@ @ @0@ @`` @pp0@` @pp0@`` @ppp0@ @ @ @ @` @` @0@`ppp @0@`` @ @```` ``pp +p @ppp` @p p 0@p````` +` @pp pp p @p````!``pp(0 @ @````` +``2`L`8p p)pp+p`ppp```pppp``*`@`2pp`¤af`àp’qxqpTpp```pp` @0@pppp``` @p +p p @``````p p `:`ÞaW`’påq6p·pNp#0 @```ppp0@p0@`` @ @`p0@``````'`pp*pp @`` ```$` pp,p"p 0@p````ppp @p``````2`B`p=pMp#pp0@ @0@ @```ppp0@0@`ÿœ" p@ @0@0@ @ @`` @p0@` @pp0@``` ` +pp p +p0@ @0@ @` @` @0@`ppp @0@`` @````` @p0@pp`` @p pp pp```` +`&`Q`JppNpDpp +p @p`` +` `` `ppp0@ @```````````pp5p(pp +ppp` @pp``` @p``¼aZ`ÔpŽqXpÿpPpp```pp` + @`ppp ``ppppp0@ @`` ````pp`Pa2b%`®qwqºpõpZp%0 @```ppp0@p0@`` @0@p0@```` +`` +``pp&ppp @`````` pppp0@``` +`ppp0@p``````-`9`p9pDppp0@ @0@ @ @`ppp @0@`ÿœ p@ @p0@ @ @ @0@0@`` @pp0@``` ` +pp +0 +@ @0@ @ @`` @p``pp0@0@0@ @ @````` +`ppp @pp`` +`*`4pp1p$pp`pp```T`³`–pp°p™p8pp`pp`` ```ppp0@````` +```p` +` `0`p'ppppppp``````(` p pp` `f`½`jpFp°pp0p p`` +`pp` +``` +` +ppp `` ppppp`` +` pp +` +```` +pp`Ca4aá`ŽqJq†pçpVpp 0@```ppppp0@``` `` pp ppp0@` `*`B 8@p6p1ppppp 0@p @``` `pp +p p0@````` p pp 0@0@```` ```pp$ppp0@ @ @`p0@p0@ÿœ! p@ @p0@ @ @ @ @0@`` @p0@```pp0@ @0@ @ @`` @p``pp0@0@0@ @ @```` @p0@ @pp`` `&`2pp-p p ``pp p``l`ß`ºppØpÅpHpp``p`` +`ppppp0@`````` +`` +pp +p``` +p ` `pp,p(pp``` +` +``4`.pp1pp ``;`&ppp€pFpp0@0@`` @0@``,`4pp-p$p``` `6`¤`Ó`,p‘p¤plp.pp +```` ` `pp0@`pp p +```ppp0@` +``!ppp0@```ppp +`` ``(`p02@`' @p"p.p pp``pp0@0@pp0@0@```` ` `ppp @```Ya@bebfp rÐr“pÖ0"@``pp p +pp0@ @0@``` + @ppppp p``0@````N`g`pRpQp0p0@` @0@0@```ppp0@ @0@ÿœ%`r`` @ppp @ @p``` +`pp +p0@ @ @ @0@ @ @ @0@0@p``` @`` +``p pp p @0@``` `ppp0@0@```` @0@ @pp0@```p0@````ppp`` `"`]``SpRp¢pV0@ @ppp` @0@``4`>pp5p(p `` ```h`•`8p;pppdp2pp`` @``ppp``ppp```pp0@````pppppp 0@pp`````` p p ``-`pp&p pp p``0@0@p0@0@0@``` @ppp` @p``+`”aa"`qTqGpj0@``ppppp0@ @ @0@`` `` ppppppp`` @`` `*`†`½`p—pŽpOp0@` @0@0@```ppp0@ @0@ÿœ,`q````ppp @0@`` @pp0@ @ @ @ @0@0@ @ @0@ @`````&`pp p0@p``` @````p ppppp0@````` `pp0@`pp0@` @```p``pp`` ``R`t`ApDpƒpDp +``ppp0@```p``"`0`p$pp``pp``;`,`p(p6p&pp +`` +`p` @p 0 @``0@```p0@` +``.`pp$p``p pp p p`` @p pppp``` pppp pp`` @```ppp0@` @pppp```pp +p p``` +pp```0`V`\` +pppjp&p``pppppppp @``pp``` `` ppp +pp0@`` @`` `3`“`Î`p¥p¥pXppp0@ @0@0@`` @pp0@0@0@ÿœ*`q @ @``p0@0@`` @pp0@ @ @ @ @0@0@ @ @0@ @```` `4`p0(@p!p +p``` @```/`pp"pppp0@``````pp 0@pp pp` @``````ppp```*`@`+p$pEp ``L`8p(pXp00@```0@```pp +``` p +p%p ` ``ppppp +`` @`` `ppp`` @```pp```:`R`p7pDp` +`p ppp```*`#p p(pppp`` ``ppp pp`` @```pppp`` ``pp pp`` `ppp0@``pp`` +``` pppp +p``pp0@ppp @```pp``` +`pp ppp0@`` @```#`a`€` +pfphp9ppp0@ @0@0@`` @pp0@0@0@ÿœ, s@ @`` @pppp0@p`` @p0@``0@``pppp0@ @ @ @0@ @ @```+ @pp"ppp``` @``"`5`pp p'ppp0@ @```!` +ppppppp0@```` +` ````p +p p`````pp``F`”`cpRp£pVpp``p0@`` `pp` +``p +p!p`` @ppp pp```` ` `ppp`` @```p````@`a`pBpRp$`pppp p` `#`Z`>p pSp6pp0@` ``p +ppppp0@```&`%pp+p p` ``pp pp```)`pp(ppp``pp`` ``ppppp0@pp @ @pp0@```p0@` @ppp0@p` @p````#`0`p$p'pppp0@ @ @````pppp @0@ÿœ+ u@````pppp0@``` @p0@`` @``pppp0@ @ @ @0@0@ @ @`` @`p pppp`` `pp```)`"`p p+p.p0@ @```` +ppppppp0@``` ``pp ``p +p pp`` +`` +pp ``T` `sp^p¹pZp```pp0@`````` ` ppp``0@ @pppp```` `pp 0 +@ @p`````` `,`E`p.p:p`p pp pp` `/`^`Lp(p_p:pp +0@` ` ` ppp +`ppp +p```2`!pp5p$```ppppp```!`pp$ppp``pp````ppppp0@pp @ @`p0@```p0@0@p`0@p` @pp```` +` pp p +pp`p0@0@ @ @````p +p +p p @0@ÿœ% w@0@``` `ppp +0@`` +``p +p p` @```pp0@````pp0@0@ @0@ @```pppp````p p +p``` `*`p)p2ppp` @``` `pp0@0@ppp``````ppppppp`````p p ` +`<`p`Pp@p…p

pp +`` ` @pp p +p +` + @pp0@0@```1`8`p4pGp 0 @````,`Ša`Îp¦q2p p`4`Z` p4pPp6p ``"`pp)pp p0@```ppp0@ @0@ @ @0@0@0@```p0@ @pppp0@````p0@```ppp0@ @pp0@0@0@0@ @ @```` + @p p 0@``` pÿœ# ‚@ppp` @``0@pp````p0@``pp @`0@ @`0@p0@` @ @0@0@`````ppp0@``ppp0@ @0@``pp0@``````` pp``ppp pp`` +`` @ppp pp p```` @ppppppp`` `````4`9`N`†`Dpep°psp p````&`V`Spp_p>p`L`m` pUpRp.pp` ```pp pp ` +`ppp0@0@```)`8`p0p?p 0 @``` +`(`ˆa`¼p¦q&p˜p`$`<`p p8p&p ``` ppppp0@```ppp0@ @0@ @0@0@0@``p0@ @ @pppp0@````pp0@```ppp0@ @p0@0@0@0@ @ @p``` @pp0@` ``pÿœ! Œ@p p0@````pp0@ @`p0@`` @p0@ @ @0@p @````pp0@ @0@ @` @0@ @` @pp````0@pp` @``` + +@` `"`pp,p0@```-`:`!pp'p +p p"pp +p``` @pppp0@``` @``)`J`Q`x`Ë`vpqp¯p.p`````*`'ppDp,``D```pBp`I`p`»`jppöp¡p*``$`Z`f`pFpEp(p"p``$`4`ppppp ``` +`pppp` `ppp`pp +0@````ppp +p```````.`pp4pp`` +` @ppp +pp @`pp0@`pp0@ @ @pp0@ @`p0@ @```p0@```ppppp0@````p````p0@ @pp0@0@0@0@0@ @ @ @p @ppp`` ``pÿœ!`“pp p +0@`` @pp0@ @ @0@``` `pp +0@0@ @``````pppp`0@``pp0@` @0@0@0@`` @pp````pppp0@`` @ @``` `` +pp0@```H`¸a``ŸpÚq#p\pp8p

`e`4pBpvpWp``Z`Ë`ä`pÞpÝpTpp``` `ppppp``` @pp p`` pp ``pppp``` +`pp +pp````p```pp +p0@ @`0@pp0@`` @pp @`ppp @ @pp0@ @p` @0@`0@ @```ppp0@ @ @ @p`` ``p0@``pppp0@0@0@0@ @ @ @p0@``` +` pÿœ`…ppp0@p` @pp0@ @ @0@ @``` `pp0@0@ @`````.`H`(p4pSp$p``pp``pp 0@` @`p0@`` @p @```pppp0@` @ @````pp 0@```L`ÀaD`§pÊqp@` p4pTp`6p,pFpp p````` pppppp ` `"`pp&pp```ppp0 +@`p0@`````p0 @`pp0@````pp p0@0@ @ @```p0@` ``ppp @ppp0@` @p @ @ @ @``` `` ppp0@`` @pp0@0@` @ppp0@0@0@0@```ppp0@0@ÿœ"`rp0@ @ @ @0@ @```p0@0@ @ @``` ` `n`ò`Ùpfqpžp``ppp```pp +0@```2`#p"p6p0@`` @pp0@``0@ @``````P`°`Žp\pÊpf0@`ppp`` @pp``&` +p$p` `,`p +p(p``p +ppppp`` ` @ppp ppp0@``````````Ò`Þ`pðpÝpH``2`/p&p;pp```` ```.`p0p7pp` +`&` p +p.p#p` ``ppp0 @ @0@`````pp p``pp0@`ppp0@0@````` `pp p````ppp```ppp @0@0@ @`p0@`0@````` +`p +pp0@ @```ppp````ppppppp``p0@```ppp0@0@ÿœ`rp0@ @`` @0@```p0@0@ @ @`````X`Ê`½pVpóp†pppp0@ @pppp````.`#pp6p0@`` @ppp```0@0@```` `.`–aH`üp¤qppÆp/p``pp````p +``#`2`p0p1p```p p` `)pp4pp pp```(`'pp%pp 0@p0@````````D`’`ž`p¬pŸp8p``ppp +`` ` +pp``+`R`)pHpYp"p` +``p +p"pp``` ppp 0@`````ppp` `pppp0@`ppp0@0@```` ``ppp````ppp```pp p @0@0@ @```ppp0@``````ppp0@0@```pppp```pppppp```p0@```ppp0@0@ÿœ' p@0@ @` @ @0@`` +`pppp @0@0@ @p````/`l`cp,ppFpp0@``pppp0@````pp p0@````ppp``ppp0@````` `0`£a„ap¼q¢pâp5`` `p pp```p```.`p(p'p @pp` `:`3ppDp&ppp```0`-p +p/p&0@```````pp``` `4`8`pBpFpp``p0 @```pp``(`J`'p>pLpp `` +`p +ppp```pp p0@ @` @p` @p`` `pppppp @pp0@``` +` + @p pp```ppp p` @ppp @0@````` +` +pp ppp``` `pp0@ppp`` @pp`pp0@ @ @0@0@0@```p0@`` @pp0@p0@ÿœ p@0@ @` @ @``` +ppp p @0@0@ @``````$`#p p+pp0@``pppp @``` +` +pp p0@``````0@`ppp0@``` +` ``g`ü`ÍpˆqpŽp```pppp` @````pp` +pppp``.`+pp6pp +pp``` `!p +p#p0@`````ppppp`` ``pppp +p @p0@`` `pp```*`pp$pp``p +pp +p p```pp0@ @```ppp @``` `ppppp0@pp @```` @p p +p``ppppp```ppp @0@``````pp"ppp````p0@`pp`` @pppp0@ @0@0@0@0@``p0@`` @pp0@p0@ÿœ`r0@ @ @````ppp 0@ @0@ @0@0@` @```pp p0@`` @pp0@`p0@`` @p0@p```` `ppppp` @p``````$`^`Tpp)p +```ppp0@ @`` +`ppp +p```8```L`p,p,p2p6pp`` pppp p` @p0@`` @`````ppp``ppppp @``pp0@`````pp pp``` @pp0@0@0@p0@0@`` @`pp0@ @pp0@``ppp0@ @`````#`pp-pp0@` @0@0@ @``` +``ppp @0@ @pp0@0@ @0@ @0@0@0@ÿœ`r0@ @``````p0@pp @0@ @0@0@` @```ppp0@` @0@`p0@` @p @0@``` `pp0@`` @`` +`pp p```p pp +````pppp 0@p````*`D`"p pJp1p +p`` `ppp` @p` @ppp``!`l`¼`ˆppŒpjpFp:p```pp#pp p```p0@ @ @` @```` pp`pp p ppp0@` @p0@`````pp p` @ @0@0@0@ppp0@`` @pp0@` @ppp @``ppp0@ @``````pp'pp0@ @0@ @ @`````ppp @0@0@pp0@0@ @ @0@0@0@ÿœ`spp```p0@```` pp0@ppp0@0@``0@0@` @ @`p0@0@ @ @pp @ @```p0@````pp``` ```p``p"p/pp``p0@````pp +pp pppp````"`5` pp4p#ppp``ppp``pp` @pp`` +`,`†`é` p@pÒp—p>p%p` ``pp&pp p`` @p```pp0@``` `` +p0@`pp0@ppp0@```p```pp```pppp`` @pp @pp0@0@ @0@ @ @0@``ppp0@ @ @`` ` ` ` `ppp +0@`0@````` ` `p pp @`pppp0@ @0@0@ @0@ÿœ`spp```pp0@```$`0@p%ppppp0@ @p` @0@` @0@pp @ @0@ @p @pp0@ @```p0@p`` @``` `.`z`€ppVp `pFpWp```p +0 +@```pppppppp``````p +pppppp``ppp`p`` @pp`` +`(`r`±`ppDp²pup*p `` ``pppp0@` @```pp +0@````` pp``pp!pppppp0@```pp``pp```pp p +p`` @ppp`pp0@0@0@ @0@ @0@0@``ppp @ @0@``````pp p0@` @p``` +``` +ppp +0@`pppp0@ @ @0@0@ @0@ÿœ q@`` `pp0@````( @pp/ppppp0@ @ @ @0@`` @pp0@` @0@` @pp0@ @```p0@p```````"`€a~a¦pZqkpÒpQpdp[p``$` p"p p0@ @0@pppp`0@````` @0@ppp``ppp0@````0@````L`_`"p8p\p:pp` @ppppp0@``````p +p0@````$`p``’`jpTp›pRppppppp```pp```ppp p`pp0@```pp``pp 0@pp0@`` @0@0@ @0@`` @p0@0@ @````pp p0@`` @``` ``8`Q`8p?pep1pppppp0@ @ @pp0@0@ @ @0@`ÿœ q@``` `pp +0@`` @``pp!ppppp0@ @ @ @0@`` @pp0@` @0@`` @0@pp0@ @``p0@````````:`ôb²b¸pRrur.põpd0=@`3`P`p:p>p"pp0@0@`ppp`p````pp`` @ppp``ppp0@p``` @````0`3pp.p,pp`` @`ppppp0@``````p +pp`` ` `` `` `–aªa4pìq§pêpNpppppp```p`` `P`XppQpLp!p0@ @pp``pp``pp 0@`p0@`` @0@ @````pp0 @0@0@````ppp @` @````U`¾a*`ºpæq_p›p-ppppp0@ @ @pp0@0@ @ @0@`ÿœ& p@````p0@p @`` ` +`p +pppp0@ @ @p``` +` pp +pp0@` @0@`` @ @pp0@pp @ @p``````````Fa&c2bûpˆrír¤q$pLp``C`d`&p:pDp4p+ppp0@``0@0@``` `ppp```pp0@`ppp0@0@````` +```pppp pp```` +`pp p0@``````ppp` +` `````pp5p4pp 0@````ppp p0@`````p pp`` + @p p +p``````pp p0@0@0@0@ @```` +``p +p p0@```ppp @``` @ppp0@`` `pp +p```M`¸`˜pp†pŒpcp,p``ppp0@```S`Ê`ä`.pªpàpp0p ``` +p +pp p0@ @pp` @0@ @p` @pp0@0@```` ``pp p0@ppp @pp0@ @ @`` ``pppp```1`©aqb>aqérkqpCpppp`` @pp +p0@ @0@` @pp0@0@ @ÿœ o@ @0@`````ppp0@ @0@p```0@ @0@ @0@0@0@```p0@pp0@ @0@0@```` @0@`` @p p pp0@ @`` @pp0@`` ```ppp +p``ppp @`````pp +p0@ @pp0@ @``` `` ppp +ppp``p0@ @``` ` +`pp pp`` +``p p0 +@` +``6`>`(ppFpBpp``ppp0@`` +`"`L`_` p/pPpCp&p ```pp +p +p0@ @pp @ @ @0@0@ @ppp @ @``` `pppp0@ppp @p0@ @ @`` ``pppp````=`~`Ö`\p±pÙp^ppppp````pp p0@0@` @ppp0@ÿœ o@ @0@`````ppp0@ @0@````pp0@ @0@0@0@```` @pp0@ @0@0@```` @0@`` @pppp0@` @p0@``` ` `pppp0@p`` @0@`` @pp0@ @pp0@ @``` ``ppp +pppppp0@``` +`p +p p````$`pp!pp` +` `` @p&p&pp @pp0@``````p ppp p``pppp0@ @pp @0@ @ @0@ @ppp` @ @````pp pp @ppp @0@0@ @```` pp0 @pp```$`'`pp:pp +pppp``` ` pp p +0@ @0@0@` @ppp0@ÿœ p@ @`` @0@0@` @0@0@ @``` `pp +p0@ @` @pppp0@`` @pp0@``0@ @0@` @0@0@`` @ppppp @p @0@`` ```ppp p +p0@`` +`pp +p @ @p0@` @pp`p @``` ``pp p +0@pppp0@pp0@```p0@````"`pp%p`` ` ```pp$pppppp0@0@````` +` `ppp 0@p0@0@ @p0@pp```pp0@`0@````pp`` `ppp0@``pp @0@ @0@0@````````ppp`` ``pppp0@0@`` @pp 0@`ppp0@ @pppp0@ @ÿœ!`n @ @`` @0@0@`` @0@0@0@ @``` `pp +p0@ @````p +p pp0@`` @pp0@`` @ @ @pp0@0@0@`` @`ppp` @p0@0@``` ` `pppppp````p +p"p0@ @p`` @pp` @0@```````pp ppppp0@pp0@``pp```` +``ppp` `` `` `pp0ppppp0@0@p````````pp p0@0@0@ @pp0@pp`````p0@`0@````pp```ppp0@``pp @0@ @0@0@````````pp 0 +@```pppp0@0@`` @p pp`` +pp p0@ @pppp0@ @ÿœ#`l````0@ @ @ @``` `pp +pp0@ @0@ @``pp0@`````` ``ppp p0@`` @ppp``` @````pppp0@``p @ @p``pp0@`` @pp```````pppp``"`L``Y`(p>p^p/p` `pp pp @``p`p````pppp0@`````pp p``0@p````p0@`` +`p0@ppp @pp``` `pp p @pp0@ @``` +`pp +p```2`+p p(p(pp +0@ @``0@`````p pp +p````` `pppp p``` ` +ppp 0@0@` @0@```` `` `ppp`pp p p0@`p0@0@````&` pp +`pppp +pppp0@0@0@ @ @ @````pp0@ppp0@` @ppp```ppp @ @0@`` @0@ @pp @`` @pp0@``` @p0@0@p``ppp @0@ @0@0@ÿœ! o@ @0@`` @p```*`?`p-pBp p``pp +p````pp0@``p0@ @pp0@ @ @```p0@``pp @` @`````ppppp0@0@p```` p p0 @0@0@p`````ppp`` ```pppp +0@0@0@ @`````p +p 0@```4`0pp1p&ppppp` +``ppp``p0@p0@```` +``` +`pppp pp0@0@``0@pp```` ` pp ` `p pppppppp @ @0@0@ @ @``` `pp0@pppp0@0@ @ @pp0@ @0@0@0@ @ @0@0@ @ @ @0@0@0@` @0@pp0@ @0@ @0@ @```pppÿœ o@ @`` @p````` ppp p``ppp```$` ppppppp0@0@ @ @``p0@``p` @pp @`` ` `$`p"p$p pp0@0@````` p pp 0@0@p``` @0@``` ```ppp p0@0@0@ @`` ```pp0@```X`PppcpBp`ppp ```pp```p0@pp0@````` +` +`pppp pp0@0@`` @p0@`` `` pp` ` pppp`pppp0@ @0@0@ @``` `pp0@ppp0@ @p0@0@ @0@0@0@ @ @0@0@ @ @ @ @0@ @ @pp0@ @0@0@ @ @ @p``pppÿœ`n @` @0@ @`` @pp0@``0@```2`L`p(p3p"pppp0@ @0@ @ @0@ @0@`````pppp``` ``$`pp"p pp0@`` ``ppp +0@0@ @ @ @0@0@``` +` + @p ppp0@ppp``````:`F`pFp>pp``!`T`RppfpHp``p +p +p @``` +`ppppp0@ @p`````ppppppp``p``` @pp````p``` ppp +p`pp0@0@ @ppp0@0@ @`` `ppp```ppp0@```ppp0@`p` @0@ @0@``pp0@ @ @ @ @p0@p0@0@ @` @ @pp0@ÿœ`n @` @0@ @ @0@0@` @```@`\`*p$p5p2p/ppp0@ @p0@ @0@```` +`pp 0@`````` p pp pp0@p````ppp0@ @ @ @ @0@0@```` @pp +p`0@ppp`````8`Š`ª`p¢pœp4p p``4`4p +pBp0p +``ppp0@p````ppppp0@````ppppp0@ @pp`` @pp```pp```pp p``pp @ @ @pppp0@0@ @`` @```pppp0@```ppp0@`p` @0@ @0@```pp0@ @ @`` @p0@ @0@pp0@0@ @` @ @pp0@ÿœ p@0@ @0@0@ @ @0@`` @```.`F`%p +pp,p3pp p0@`` @0@0@```p0@`````pp +p0@``` ` + @p +p +0@``p0@```ppp0@ @````0@p0@``` @pp` @pppp`````P`È`ð` päpÜpRpp```pppp```ppp0@```` @` @pp0@0@`` +`pp +p0@p````p0@```pp``pp0@pppp``0@`````ppppppp0@0@``````` @pppppp`` @pp0@`0@ @0@0@ @```ppp0@ @p`````pp```pp p0@ @0@ @ @``pppÿœ p@ @0@0@ @ @0@ @0@`` @````"``ppp!ppp0@`` @0@0@`` `pp pp`````ppp0@``` @pp0@``p0@```ppp0@````ppp0@``p0@```ppppp`````D`¨`Ä`pÀpÂpJp p````ppp````pppp`p````` @p p0@0@`` +`p +pp0@``` `pp +p```p```ppp0@pppp``0@``` `$`pp$ppppp0@0@```````0@ppppp0@` @`p0@p @ @0@0@ @``ppp0@ @```` @p````ppp +0@ @0@0@ @ @``pppÿœ`r0@ @0@0@ @ @ @ @```` +``ppp p0@pp0@p` @0@`` +` @pp0 +@` @pp0@ @0@````0@ppp````p0@pp @`` @pp0@ @0@````pp0@`` +` ` ``K`^`p^pgp&0@pp0@```ppppp```` ``` pppp0@p```ppp0@````` +ppp0@ @p``p0@```ppp0@`` `*`m``#prp„p

ppPp9pp``````ppp +p0@````0`pp(p"p p` @0@`````pp``$`Y`cppmpEpp0@0@0@0@ @0@ @0@ @0@ÿœ%`qp`` ``ppp +0@0@ @pp0@ @``0@0@p`````8`Ñaúaé`vr:r,pÓp.p ppp0@` @ @0@0@```pp0@0@ @``` @pp`` @ppp`pp` @pp0@0@ @`` @0@0@0@ @``````pppp @``p0@p```pp0@0@ @ @0@``` +` @pp0@0@```ppp`` @0@```pp`pp0@0@ @ @``` ```,`pp1pppp``p0@p``pp0@p0@p` @```````4`0pp`p$p@p$p 0@0@ @ppp0@````pppp0@````ppppp````0`pp p p +0@0@0@``0@0@0@`` @```C`y`XpMp‘pApp`ppp0@0@0@ @0@0@ @ @ @`p0@0@ÿœ`p0@ @0@ @ @``````pp0@0@ @ @````&`ƒa(a@`qZqBp{ppp0@ @`p0@`` @0@0@``` @ppp``` ``9`x`appvpVp+pp +p0@ @``` ``ppp0@ @0@` @0@ @``` ` @``J`†`Dp^pŠpGp0@`` @` ` `+` +p*p,p0@p0@0@ @ @`0@ @ @```pp0@0@0@ @`0@p`0@0@ @0@````` ppp0@0@0@````pp0@p```` +`pppppp0@`` @p0@````"`ppppp``ppp0@ @0@`` @``/`S`Bp7php/p p0@0@pp0@ @ @0@ @0@ @ @p0@ÿœ`p0@0@ @ @p`````pp0@0@ @`````'`H`N`pVpVp%p +pp0@``pp0@`` @p @ @p`` ` +`p p p`````/`h`WpplpFpppp0@ @p``` +` +pp +p +0@ @0@`0@0@ @``` ` @``*`X`,p@pbp/p 0@`````)```{`pxp|p-ppp0@p0@ @ @0@ @ @```ppp @0@0@ @``ppp` @0@ @0@ @```pp0@0@p```pp0@```` +`pppppp0@`` @p0@``` `` +p p 0 +@```p pp0@ @0@`` @` +``'`pp1pp0@0@pp0@ @ @ @ @0@ @p0@ÿœ`p0@ @0@` @`0@````pp0@0@ @````` ``pppp pp0@```pp0@ @0@```ppp`` +`p +p +0@`````0`+p p1p(pp0@0@0@`` @pp`p0@```p0@0@0@````` ` ``p```pp&p0@````H`®`Õ`2pÒpÜpMp0@`pp0@ @pp @``0@p````pp0@``pp0@```ppp` @p0@` @0@`p` @0@` `pp +pp````` +`pp +p p0@0@` @0@ @`````ppp```` ppp +pp0@ @ @ @``` +`pp p0@0@`p0@ @ @```p0@0@0@ @0@0@ÿœ`p0@ @0@`` @p0@````pp0@ @` @````pppppp0@```pp0@ @0@`` `` +p +p0 +@``ppp`````` ` ppp 0@0@0@0@`` @pp`p0@```p0@0@0@p`````` `p0@`pp +pp @````L`¾`å`*pÜpèpUp0@```p0@ @ @p0@``0@p````pp0@``pp0@```ppp` @pp`` @0@pp @``` @0@``pp +ppp````` +`p +p p0@0@ @ @ @````pp0@```` ppp +pp0@ @ @` @pp0@0@`p0@ @ @```p0@0@0@ @0@0@ÿœ`q0@ @ @```ppp0@ @ @0@ @0@ @ @ @`` @pp0@0@`` @0@```0@p````&`pp&p0@0@`` @``pppp` @0@0@`` @p0@p0@``pppp @0@ @ @``` `pp0@pp0@ @``` +`-`r`’`pˆpŠp7p +0@`` +`ppppp @pp0@ @ @0@p````ppp```pp pp` @ppp` @0@` @pp0@p0@0@`````pp` @ppp0@ @`` +`pp p0@ @0@p`0@ @````pppp````ppppp0@0@0@ @ @0@ @0@0@0@````pppp0@ @0@ÿœ`q0@ @ @```ppp0@ @ @ @0@ @ @`` @pp0@0@`` @0@````ppp```&`pp&p0@0@0@`` @p`pppp`` @`` @p0@p0@``pppp @0@ @ @```p0@pp0@ @`````*`6`p2p2pp0@` ```ppp p @pp0@0@ @0@p````ppp```pp0@` @pp`` @p``` ppp ppp0@0@ @`` @p``pppp0@ @`` +`pp 0@``pppp @ @`p``ppp``` +`pp p`p0@0@0@0@ @ @ @0@0@0@````pppp0@ @0@ÿœ p@ @`` @p0@ @ @p0@ `` @0@0@0@`` @`0@`` `pp 0@` `` p pp0@0@`` @p @p0@```0@`````pp p +pp0@``pp0@0@```0@``` @pp0@ @p```` + @pp 0@p`` +```ppp +0@`pppp0@``p` @```pppp` @0@ @p0@```p````pppppp0@ @`pp```````pppp0@pp`` @0@` +``pppp0@ @ @0@0@`` @0@0@ @p0@0@ @ @0@0@0@ @ @ @pp0@ @ @ÿœ p@ @ @ @p0@ @ @p0@ `` @0@0@0@`````pp```p pp p```ppp0@ @`` @` @p0@p @0@``` ``ppppp0@``p0@ @```0@```` `pp +p 0@` @pp`````pp0@p`` +```ppp`pppppp0@```` @` @ppp0@ @0@ @ppp```pp````ppp pp0@` @ppp``````p p"pp0@ppp` @```.`4pp8p)p0@ @0@0@0@``0@ @0@ @p0@0@ @ @0@0@0@ @ @pp0@ @ @ÿœ `q0@0@0@ @ @ @0@ @`` @p0@ @0@ @0@ @```` +`pp```ppppp @p0@0@ @`````` `p p +p0@0@0@ @``` ``ppppppp @ @` @` @``` ``p +ppp`` @ppp`` `ppp0@ @```` `pp` ` ppp p0@0@ @``0@```pppp` @0@`pp0@````pp`` +`ppp +p0@````ppp0@`````p +p pp0@p @ @0@```?`@ppFp8p0@0@0@0@ @0@ @0@0@ @ @0@ @0@0@ @0@ @0@ @`p0@ @ @ÿœ`q0@0@0@ @ @ @0@ @`` @p0@ @ @0@ @0@ @``` ``p p ``` pp +p pppp0@ @ @`````.`<`p8p4p0@0@0@ @``` ` +` pp pppp p @ @` @````````&`pp*ppp @pp````pppp``` @```` ``pp$pp +0@0@ @`0@`` @pp`` @pp`pp0@````p0@``pp +p0@```*`.pp,p'pp``` +``pppp @`` @0@0@```3`0pp6p*p0@0@0@0@ @0@ @0@0@ @0@ @ @0@ @0@0@ @ @ @0@ @`p0@ @ @ÿœ`o0@0@ @p` @0@ @ @ @0@ @ @`p0@ @ @0@```` +`pp +p````pp +p pp0@ @` @`````.`ƒ`ª`p¢pp:p 0@0@0@`` + @ppp`ppp0@`` @p`````p` +`!`p p$pp0@0@`` @pp0@ @` @p``` ``*`&p +p4p)p 0@0@0@0@ @```` @` @pp0@0@````` `pp @ppp0@```(`.pp.p)p0@`` @ppp0@````ppp0@`` ``pppp +pp0@ @p @0@`` @p```pp0@0@ @0@ @0@0@ @ @ @0@ @```ppp @ @0@0@0@ @ÿœ`q0@0@ @p` @0@ @ @ @0@`` @pp0@ @ @0@````ppp``` ``p +p pp0@ @````` ```B`Éa`pîpýp^p0@0@0@`` +`ppp```pp0@`` @``````p```pppp0@0@0@`` @pp0@ @` @```` ` +``pp,p!p @0@0@0@ @```` @` @p0@```p``` pp0@ppp0@``` @ppp +0@```pppp0@````ppp0@``` ``pppp p0@ @p @0@`` @```pp0@0@ @0@ @0@0@ @ @0@0@ @```ppp @ @0@0@0@ @ÿœ `vp0@ @0@ @p0@`````ppp0@p` @0@```p0@`````pp +p0@0@ @```` +``*`"`0`ª`ð`!pìpöpbpp0@0@0@```pp0@ @p0@0@`````` @ppp` ` +`ppppp0@0@` @0@` @`` `` p``pppp` @ppp0@`````pp0@0@``` +``ppp``p ppppp0@ @``` ` +ppp p0@```ppp0@````ppp0@`````"`p&p"p0@ @p @`` @`` @pp0@ @0@0@ @pp @ @ @`p0@0@ @```p0@` @0@ @0@ÿœ`zpp0@ @0@ @p0@`````ppp0@p` @0@ @0@`````ppp0@0@ @```` +`"`6`"` `@`|`pˆpšp>p +p0@0@0@ @``p0@0@p @0@```` +` +`ppppp`` @pppp0@ @` @0@` @`` ` `p0@ppp `` `pp pp0@``` @ppp0@ @````<`1pp?p `` p pp0@0@ @``` @ppp0@p``ppp @` @``pp0@````:`J` pJpFp0@0@p @`` @`` @pp0@ @0@0@0@ @pp @ @ @pp0@0@ @p``p0@` @0@ @0@0@ÿœ`{pp0@0@0@ @ @0@``pp0@ @```p0@0@0@ @p0@ @ @ @````(` pp%p0@0@ @``````,`p +p``p0p;pp` @p0@``p @ppp0@ @p0@ @` @`` @pppp0@````pp0@```p0@`p0@` @````pp0@p````ppp +pp````` `pp +p p +p`` @` +`%`R`Gpp\p:p `pp 0@`` @ @pp0@0@ @0@0@`` @```pp0@````E`X`pTpSp0@pp0@p @0@`` @pp`pppp```ppppp` @0@0@ @0@0@0@ @ @ @ @ @p0@ÿœ`wp0@0@0@ @ @0@``pp0@ @ @`0@0@0@ @p0@ @ @ @`` ``,`p&p+p0@0@ @``p````p +0@p pp``` `p +p p``p0@ppp0@ @pp @ @``````p0@ppp0@````pp0@```p0@0@` @````pp0@ @`````pppp0@`` `` @p +ppp``pp```F`;ppNp6pppp0@ @`` @0@ @pp0@0@ @0@0@`` @p``pppp````3`@`p8p?p0@pp0@p @ @`` +` pp ppppp`````pppp` @0@0@ @0@0@0@ @ @ @ @ @p0@ÿœ`r0@0@ @0@ @0@0@ @0@0@ @0@ @0@ @``````ppp0@ @ @ @``` pp0@p`````pp0 +@`ppp0@ p````` +``pp p0@p0@ @`` @0@0@```pp p0@````p0@p0@0@ @ @` `` +ppp ppp`` ```` pppp``pp p``$`pp(pp0@p` @0@```ppp0@ @ @0@```p0@ @pp0@`` +``&`pp%p0 @pp0@` @`````ppp +0@0@``` @ppp0@ @0@0@0@ @ @0@ @0@ @ @0@0@ÿœý`p0@ @0@ @0@0@ @0@0@ @0@ @0@ @ @```` ``p pp0@ @ @0@`` @pp``` ````"` pp&0@`pp0@ @``ppp``` +`"`,` p$p,p0@p0@ @`` @0@`` `pp p0@````ppp0@ @ @ @`` +` +pp +pppp``` `` @ppp``p +p p`` `ppp +p0@`` @0@```ppp0@ @0@0@` @p0@pp @p`````pp"0@pp0@ @`````ppp +0@ @``` @ppp0@ @0@0@0@ @ @0@ @ @0@0@ÿœ n@ @ @0@0@ @ @ @0@ @ @0@0@ @ @ @ @```pppp0@ @ @ @``` ``` +``ppp0@0@ @````p pp````;`T`pFpPp"p @ppp @ @ @```pp p0@0@ @` @p0@ @ @0@` @pp0@``` ```ppp @pp`` +`pp +p p0@0@` @0@0@````p0@p` @pp @``pp0@0@0@0@``` ``!`pp$pp0@0@p @````` +ppppp @ @0@` @ppp @0@0@ @ @0@`` @pp0@0@ @0@0@ÿœ n@ @ @0@0@ @ @ @0@ @ @0@0@ @ @ @ @```pp0@0@ @ @ @ @0@0@``` `p`` `ppp0@ @````pppp```=`\` pNpZp"p @ppp @` @0@```pp0@0@ @` @0@ @ @0@` @pp0@ @```"`0` p&p*ppp`` +``pppp0@0@` @ @```pp0@`` @0@pp @``pp0@0@0@0@`````` pppp @0@p @````pppp0@ @0@```ppp @0@0@ @ @0@`````ppp0@0@ @0@0@ÿœ`n0@ @ @p0@0@ @ @`` @0@0@ @ @0@0@0@ @ @0@ @0@ @p``` @pp0@`` @0@ @p0@0@` @`0@```#`pp pp```%`:`p0p:p0@`pp0@ @`` @0@ @`p0@ @0@0@ @ @0@` @0@ @` @p0@` @0@```:`T`pBpLp p p````pppppp0@ @ @``0@ @pp````pp0@0@0@ @pp @p```` `pp +p0@` @p0@ @ @ @``ppp0@0@ @0@0@0@ @0@ @0@ @`````pp p0@0@ÿœ `n0@ @ @p0@0@ @ @`` @p0@ @ @0@0@0@ @0@ @0@ @0@ @p``` @pp0@ @ @ @0@0@ @0@````0@````p ppp``` `` +ppp +0@``pp0@`` @0@ @`p0@ @0@0@ @ @0@` @0@ @`0@pp`` @0@``@`\`pJpTp$p 0@` +``p p +pppp0@ @ @`` @0@p````pp 0@0@0@ @`p0@p` @ @pppp`` @p0@ @ @0@` @pp0@0@ @0@ @0@0@ @ @0@ @0@ @`````pp 0@0@ @0@ÿœ `o0@ @```ppp @0@ @0@ @`````ppp0@ @ @0@0@ @0@ @0@ @ @0@ @`` @pp0@ @p```pppp0@ @ @ @0@``` +`ppp0@````ppp0@`` +`ppp0@ @ @0@``pp0@pppp @ @`` @pp @0@ @0@``` @` +`(`>`p2p:pppp` @p0@p0@0@ @0@ @``````p +pp +p @p @0@```ppp` @pp0@`` @p0@ @ @0@ @`p0@0@0@p``` @p0@ @0@0@` @p``p0@0@0@```p0@ÿœ `o0@ @ @``pppp @0@ @0@ @`````ppp0@ @ @0@0@ @0@ @0@ @ @0@ @`` @pp0@ @``` @pp p0@ @ @0@ @``p0@pp`p` @``0@` ``ppp0@ @0@```0@0@pppp0@ @```ppp @0@0@0@```` @p```` ppp +pp0@ @p0@0@ @0@ @```````pp p` @p0@0@```pp0@ @pp0@`` @p0@ @ @0@ @`0@0@0@p``` @pp0@ @0@0@` @0@ @0@0@0@```p0@ÿœ`o @`` @pp0@0@ @0@`````ppp0@ @0@0@ @0@0@ @ @0@0@ @ @ @ @0@0@```````pppp```pppp0@ @ @0@0@0@````0@``$` p p)p0 +@0@0@ @ @`pppp0@0@`````ppp``pppp0@ @`` @pp```ppp0@0@0@ @0@ @0@0@ @ @` @`````ppp0@``pp0@p0@`` @pp0@0@0@ @` @p0@ @0@0@0@ @0@0@``` @pp0@ @0@0@ @ @ @0@ @0@0@0@ @ @0@ÿœ`o @ @` @pp0@0@ @0@`````ppp0@ @0@0@ @0@0@ @ @0@ @0@0@ @ @ @0@0@ @p``````pp0@```p p +pp0@0@ @ @0@0@````0@``$` p p)p0@0@0@ @``pppp0@````ppp``pppp0@ @` @pp`` @0@0@0@ @0@ @0@0@ @ @```p``` @p0@0@```p0@p0@`` @pp0@0@0@ @`0@p @ @0@0@0@0@ @0@0@``` @pp0@ @0@0@ @ @ @0@ @0@0@0@ @ @ @ÿœ o@` @ @`ppp0@ @0@0@ @ @ @ @0@0@ @ @0@0@0@ @ @`` @ppp0@ @` @ 0@`````ppp``` `pp"ppp0@ @ @ @ @``pp` ``ppp0@0@0@ @pp @` @p0@ @``pp0@``pp0@ @`p0@ @ @0@ @ @0@0@ @p0@```p0@ @` @p0@ @pp0@0@ @pp`0@ @0@ @0@0@0@ @ @ @ppp`` @0@0@0@0@ @0@0@ @`` @pp0@ @0@ @0@ @0@ @0@ @`` @ÿœú`o`` @0@`ppp0@ @0@0@ @ @ @0@0@ @ @0@0@0@ @ @```pppp0@ @` @ @0@`````p0@` `&`6`p&p:ppp0@ @ @ @ @p`pp``` ppp0@0@0@ @p0@```p0@ @p`0@``pp0@ @`p0@ @ @0@ @0@0@ @p0@```p0@ @```p0@ @pp @ @ppp0@ @0@0@0@0@` @0@ @ppp`` @0@0@0@0@ @0@0@ @`` @pp0@ @ +0@ @0@ @0@ @`` @ÿœ`q`` @0@0@0@0@0@0@ @ @ @0@0@`` @0@0@0@ @0@0@ @`````ppp0@ @ @p``` @pp0@```pp```$`9`p*p8p0@0@0@ @ @ @0@0@` @0@p0@ @0@pp @` @ @0@0@ @0@````pp0@` @pp``0@0@ @ @0@``0@ @ @0@p`0@0@ @ @``0@p` @````ppp0@0@p @0@0@0@`` @0@ @pp @` @p0@ @0@0@0@0@ @p` @ @0@0@ @0@0@0@0@ @0@0@ @ @`` @ÿœ `q`` @0@0@0@0@0@0@ @ @ @0@0@`` @0@0@0@ @0@0@ @`````pp +p0@ @```` @pp0@```pp`` +``!` pp$p0@0@0@ @ @ @0@0@p` @ @p0@ @ @pp0@` @ @0@0@ @0@````pp0@` @pp``0@0@ @ @0@`0@ @ @0@``pp0@ @0@0@`` @p` @p`` `ppp 0@0@p @0@0@0@`` @0@ @pp @``p0@ @0@0@0@0@ @p` @0@0@ @0@0@0@0@ @0@0@ @ @` @ÿœ`p @ @0@0@0@ @ @ @0@ @`` @pp0@ @0@ @0@0@ @`````ppp0@0@ @0@```` @pp0@``0@```` `pp pp @pp0@ @0@`` @pp @ @0@0@`` @pp0@` @0@0@` @p0@` @pppp0@ @0@0@ @0@ @ @0@ @ @ @```ppp`` @p0@`` @` +``ppp``pp0 @ @pp0@0@ @``0@0@ @`pp0@ @0@ @0@0@ @ @ @0@0@ @0@0@0@0@ @ @0@ @0@ @ÿœ p@ @0@ @0@ @ @ @0@ @`` @pp0@ @0@ @0@0@ @`````ppp0@0@ @0@```` @pp0@``0@``p @ppp @pp0@ @0@`` @pp @ @0@0@ @````pp0@` @0@0@ @`` @ppp` @`ppp0@ @0@0@ @ @0@ @ @ @`` `ppp```pppp``````8`-p ppÊp™p$ppp``ppp0@0@` @pp @```ppppp0@0@p`` @p0@0@0@ @ @`` @pp0@0@ @ @0@ @```````p pp0@p```` ``pÿœ n@ @ @0@ @0@ @````ppp0@0@ @```` +@ppp0@0@0@0@ @````pp0@0@`` @0@0@ @ @0@0@0@````pp0@0@ @0@`` @pp0@````p```ppp```pp p0@0@ @ @0@ @pp` @0@`` @0@``pp0@ @0@ @0@ @0@```` @```;`:pp>p+pppp``pp0@0@` @pp0@` @``ppp0@0@p`` @p0@0@0@ @ @p` @p0@0@ @ @0@ @`````p0@`ppp0@p````` `pÿœ m@ @pp @ @ @0@ @`` @pp0@0@ @ @``` ``#` +pp p p0@0@`p0@ @p`` @p0@ @` @pp0@` @0@ @``` +`pppppp0@ @p````ppp0@`` @p0@ @0@`` @p0@0@ @ @ @0@0@ @0@` @```pppp` @pp0@ @0@ @0@ @`` @```` +pp +p`pppppp0@`` @`` +``p p pp0@`` @0@0@0@` @pp @0@`0@ @`p0@```p0@0@ @`````)`7` +p7p6pppp0@ @ @ @ÿœú m@ @pp @ @ @0@ @``0@p0@0@ @ @```B`c`"pUpdp%p0@0@``pp0@ @p @ @0@ @` @pp0@` @0@ @````pppppp0@ @p````ppp0@`` @p0@ @pp @0@ @ @ @0@0@ @ @````` @pp +pp` @pp0@ @0@ @0@`` @``` @p``pppppp0@`` @````ppp p0@ @0@0@` @pp @0@` @```p0@0@```p0@0@ @````L`˜`Æ`)pÎpÇpCppp0@ @ @0@ÿœ `n @ @0@0@` @0@` @0@ @p` @p0@0@ @ @`` +`-`v`£`8ppªpCp 0@0@`` @p0@ @0@ @0@p` @0@ @````pp0@0@0@ @ @0@0@ @ @`p0@ @ @ @0@0@ @0@0@ @ @ @ @0@ @0@0@ @```` @p pp0 +@0@pp0@ @ @0@0@ @0@0@ @`` @p` @ @0@ @pp0@`` @```%`pp$pppp0@ @0@```0@ @0@0@``````ppp0@```ppp0@p @``` `)`„aao`Jqyqlp}ppp0@`0@0@ÿœ `n @ @0@0@` @0@`` @0@ @p` @p0@0@ @ @`` +`+`v`¡`0p‹p¢pAp 0@0@`` @pp0@ @0@ @0@p` @0@ @`p``pp0@0@ @ @0@0@0@ @p0@ @ @ @0@0@ @0@0@ @ @ @ @0@ @0@0@ @````&`p pppp +0@0@pp0@ @ @0@0@ @0@0@ @`` @pp @ @0@ @pp0@`` @````ppp ppp0@ @0@``` @0@0@0@``````pp p0@```ppp @p0@``` `+`a%a—`eqªq“p…p pp0@`0@0@ÿœ`n @ @0@0@``0@0@`` @0@0@ @ @p` @0@````D`b`pUp\p'0@0@`` @pp0@ @ @ @0@`` @pp0@ @0@ @0@0@ @ @ @```pp0@0@0@ @ @ @0@0@ @0@ @ @ @ @ @0@ @p0@`` @```(`pp"pp p0@0@0@ @0@0@ @ @0@ @````p0@ @0@ @p0@ @` @`` +``p p 0@ @0@0@ @0@`` @pp0@0@``p````pp p0@` @0@`` @p0@`` +`"`n`Úa:`ZqFqCpbpp0@0@ @0@0@ÿœ`n @ @0@0@`` @0@``0@0@0@ @ @0@ @p` @0@``` ``&` +p#p$p 0@0@`` @p p0@ @ @ @0@`` @pp0@ @0@ @0@0@ @ @ @```pp p0@0@0@ @ @ @0@0@ @0@ @ @ @ @0@ @p0@```p````ppppp0@ @0@ @0@0@ @ @````p0@`0@0@ @0@ @p` @```ppp0@ @0@0@ @0@`` @pp0@0@``` @`pp0@` @0@`` @pp 0@````9`r`›`%p£pœp5pp0@0@ @0@0@ÿœ`n @ @0@0@ @ @0@ @0@`` @0@ @```p0@ @`` +@pp0@` @p`` @pp0@ @0@ @`` @pp0@````pp0@ @0@ @0@0@` @````pp 0@ @pp @0@ @ @0@`0@0@````pp0@0@` @ppp``` `pp`` `pp p0@0@ @ @ @0@0@0@ @ @```0@p0@ @ @` @0@0@ @0@0@0@ @ @`` @pp0@ @`` @ppp0@` @0@`````ppp0@``` +``#`)` p/p-ppp @0@ @ @0@0@ÿœ`n @ @0@0@ @ + @0@``0@0@ @``pp0@ @` @pp @``pp0@ @pp0@ @0@ @`` @pp0@````pp0@ @ @0@0@` @p````ppp`` @pp @0@ @ @0@`0@0@````p p +0@0@` @ppp``` `ppp``ppp0@0@ @ @ @0@0@0@ @ @ @` @pp0@ @ @` @0@0@ @0@0@0@ @ @ @p`` @pp0@0@``` @ppp0@` @``` ` `pp p0@p````` `pp +p0@0@0@ @ @0@0@ÿœë`m @ @0@0@ @0@ + @`p0@0@` @ @0@p`` +`ppp0@0@``` @p p0@ @0@0@0@ @ @0@ @ @0@ @ @pp```ppp0@0@ @0@````` +ppp0@````ppp````p0@0@ @0@0@ @ @0@0@ @0@ @`` @pp @ @0@0@ @ @0@`` @pppp @ @pp0@ @````0@0@0@0@0@`````p0@0@ @ @ @```ppp @0@``` @p0@pp0@ @0@ÿœê`m @ @0@0@ @0@ + @`p0@0@`` @0@0@``` `pp +p0@ @0@ @0@``` ``ppp0@0@0@0@ @ @0@0@ @0@ @`````ppp0@0@ @0@````` +ppp pp````pp0@` @p0@0@ @0@0@ @ @0@0@ @0@ @`` + @p +p0@0@0@ @ @0@` @`ppp0@ @pp @```` @0@0@0@0@````pp0@0@ @ @```ppp @ @p````p0@ @pp0@ @0@ÿœþ`n0@ @ @0@ @ @0@0@ @ @ @0@`` @p0@````pppp0@ @0@ @ @p````/`<`p0p3ppp0@0@ @pp @ @ @ @0@0@ @ @ @p0@``` `` p +pp +0@0@ @ @0@ @0@```` `` +ppp +p0@```pp0@0@ @``0@0@0@0@ @0@ @0@``` ``ppppp0@ @ @0@ @0@0@ @`` @pp0@ @ @p` @pp```pp0@0@0@0@p` @0@p @ @p0@ @0@ @```p0@ @0@0@ @0@ÿœ`n0@ @ @0@ @ @0@0@ @ @ @0@`` @p0@````pppp0@ @0@ @ @p`` `,``¨` pˆppDpp0@0@ @pp @ @ @ @0@0@ @`` @pp0@````` p +pp +0@0@ @ @0@ @0@p`````pppp0@```0@0@0@ @0@`` @0@0@0@ @0@0@`````pp"ppp0@ @ @0@ @0@ @0@0@ @`` @pp0@ @ @`` @p0 +@``pp0@0@0@0@p` @0@p` @ @`p0@p @ @p``p0@ @0@0@ @0@ÿœ n@ @ @0@ @ @0@0@ @0@ @0@ @ @0@ @``0@pp0@ @0@ @````F`×a`pìpïpppp0@0@ @0@ @ @0@0@ @```` @pp +pp0@```pp0@0@ @ @0@` @0@ @0@ @0@0@ @0@ @ @0@``0@p0@0@ @`` @p0@0@0@``` ``ppp0@0@```p0@0@0@0@` @ @pp0@ @``` +` @ppp`ppp0@ @0@0@0@` @pp0@`` @```ppp0@ @0@````pp0@ @0@0@0@0@ÿœü n@ @ @0@0@ @ @0@0@ @0@ @0@ @0@ @0@ @ @p0@ @0@ @````F`Ïa`&pðpñpppp0@0@ @0@ @ @0@0@ @```` @p +p +pp0@`` @0@0@ @ @0@` @0@ @0@0@ @0@ @ @0@``0@p0@0@ @`` @pp0@0@0@```` ` pp p +0@0@```pp0@0@0@0@` @ @pp0@ @````" %@p'p ppppp @0@0@0@`` @pp0@`` @``ppp0@ @0@````pp0@ @0@0@0@0@ÿœø`m @ @0@ @0@```pp0@0@ @ @ @0@0@``0@0@ @ @0@ @0@ @````*`q`š`pˆp‘pBpp0@0@ @0@ @0@ @0@``````ppp p0@ @ @0@0@ @ @`0@0@``ppp0@ @ @pp @ @ @ @0@0@0@ @`` @p +p0@0@ @```ppp0@```ppp0@p0@ @p``` @0@0@0@ @````pppp +pppp @0@0@ @ @ @pp0@ @` @ppp0@ @ @`` @pp0@ @0@0@0@0@ÿœù`m @ @0@ @0@```pp0@0@ @ @ @0@0@``0@0@ @ @0@ @``````.` p,p7ppp0@0@ @0@ @0@ @ @```` `pp"pp p0@ @0@ @0@0@ @ @` @p``` ppp 0@ @ @pp @ @ @0@0@0@ @`` @pp0@0@` @p0@`p0@0@```ppp0@p0@ @````pp0@0@ @```` pppp0@p` @0@0@ @ @ @pp0@ @ @ @`pp0@ @ @```` +`pp p0@ @0@ @0@0@0@ÿœ n@ @0@0@ @```pp0@0@ @ @pp @0@ @0@0@ @ @0@0@ @ @ @``` ```pp +p p0@0@0@ @ @ @ @`````@`~`_p p€php!p0@0@ @0@ @0@0@ @ @ @```!`p p$pp0@``0@ @p0@ @ @ @p0@ @p`0@ @```p0@p````ppp @0@0@0@`` @0@`p0@0@ @````pppp @0@`````ppp0@0@` @0@0@ @ @0@0@0@0@ @ @``pp0@ @ @``` ` `p pp0@ @ @pp0@ @ÿœ n@ @0@0@ @` @`pp0@0@ @ @pp @0@ @0@0@ @ @0@0@ @ @ @```pppppp0@0@0@ @ @ @0@0@ @````$`ˆa`ÉpHqpÜpCp 0@0@ @0@0@ @0@0@ @ @```+`&pp0pp 0@``0@ @p0@ @ @ @p0@ @p` @```pp0@`````pp +p @0@0@0@``0@``pp0@0@`````ppppp @0@`` @p0@0@` @0@0@ @ @0@0@0@0@ @ @``pp0@ @ @``` ``pp +p0@ @ @pp0@ @ÿœ n@0@ @ @ @0@ @`` @pp0@0@ @0@ @0@ @ @0@0@0@0@ @0@` @0@`` @p0@0@0@ @`` @ppp0@```` +`0`·a4`îp(q\q,pTp0@0@ @ @pp0@0@ @ @0@ @```"`p p$pp0@ @0@ @0@0@ @`ppp` @ @0@p```pp0@ @```pp p0@ @ @0@0@```p0@0@``` ` +pp +p pp0@0@ @ @ @0@ @ @0@``p0@pp @0@0@0@ @0@ @ @0@`````ppp0@ @``p0@` @ÿœ n@0@ @ @ @0@ @`` @pp0@0@ @0@ @0@ @ @0@0@0@0@ @0@` @0@` @ @p0@0@0@ @`` @ppp0@`````$`‡`ä`²pqpàp@p +0@0@ @ @pp0@0@ @ @0@```` ppp p0@ @ @0@ @0@0@ @ @p0@p`` @ @0@p```pp0@ @`ppp @ @ @0@0@```p0@0@```` +pp +pppp0@ @ @ @0@ @ @ @0@``p0@pp @0@0@ @0@0@ @0@ @ @0@``` @pp0@ @``p0@` @ÿœý`o @0@ @0@ @`` @pp0@ @ @0@0@0@0@`` @p0@0@0@ @ @`0@ @`0@ @ @pp @0@````pppp @ @```=`l`Qp pwpfp!p0@ @0@0@ @ @ @0@0@ @````pp0@ @p @0@ @0@```pp p0@```ppp @0@0@``0@ @0@0@ @0@ @0@ @ @0@0@` @0@``` `pppppp @ @ @`` @````pp0@p0@0@0@p` @p0@0@ @ @0@0@ @ @pp0@ @ @0@p` @ÿœù`o @0@ @0@ @` @pp0@ @ @0@0@0@0@`` @p0@0@0@ @ @p0@ @`0@ @ @ @pp @0@````pppp @```` `pp!pp p0@ @0@0@0@ @ @ @0@0@ @ @`0@0@ @ @pp @0@ @0@`` +`pp p0@```ppp @0@0@`0@ @0@ @0@ @0@ @0@ @0@````p0@ppp @ @ @``` `pp````pp p pp0@0@0@`` @pp0@0@ @0@0@ @ @`p0@ @ @0@p`0@ÿœù o@0@0@ @ @0@ @p0@ @ @ @ @0@0@0@`` @p0@ @ @p0@ @ @0@ @ @p0@ @0@ @``` `pppp @p @`` @pp0@pp @0@0@ @ @ @0@0@ @0@ @`````pp +p0@ @ @pp`` @p 0@ @0@ @0@ @ @ @0@0@ @ @0@ @0@0@ @ @0@` @p0@0@0@ @0@ @``` +``.`pp"p``1 G@p;p@pp p0@0@`` @pp0@0@ @0@0@ @0@ @ @ @0@ @0@0@ @ÿœÿ`m @0@0@ @ @0@ @p0@ @ @ @ @0@0@0@`` @p0@ @0@ @p0@ @ @0@ @0@ @0@ @````pppp @pp @` @p0@pp @0@0@ @ @ @0@0@ @0@ @``` +`` ppp0@ @ @pp`` @p0@0@0@ @0@ @ @ @0@0@ @ @0@ @0@0@ @ @ @0@` @p0@0@0@ @0@ @````@`x`6p]pbp`N`ß`Ì` pàpÖpdppp0@0@p` @pp0@0@ @0@0@ @ @ @0@ @0@ @0@ @0@0@ @ÿœú`l @ @0@ @ @p0@ @ @ @0@ @0@0@0@ @ @ @0@p @0@0@` @0@0@0@ @ @`` `` `p!p0 @ @pp0@ @ @pp @0@ @0@ @ @0@ @```pp0@ @0@ @`````ppp0@ @ @p0@ @0@``pp0@ @ @0@ @0@0@ @ @ @0@ @0@`` @0@```pp0@`` @pp @```$`h`¼`RpŽpžp`Êb1ad` qøqÌpÍp3p p0@0@0@ @0@ @0@ @0@` @`` `pp p +p0@0@ @0@0@ @0@0@ÿœù`l @ @0@ @ @p0@ @ @ @0@ @0@0@0@ @ @ @ @pp @ @0@`0@0@ @0@ @ @`` +```pp0 @p0@ @ @pp @0@0@0@ @ @ @` @`` +`p p0@ @0@ @``` ``ppp0@ @ @pp0@ @ @``pp0@ @ @0@ @0@0@ @ @ @0@ @``0@p0@``ppp0@`` @pp @```$```ª`Np|p’` a.caÊprªrcqpCpp0@0@0@0@ @ @0@ @0@`````)`pp)p"p +0@0@ @0@0@ @0@0@ÿœ`n0@ @0@ @0@ @0@ @0@0@ @ @0@0@p` @ @ @pp0@ @ @0@ @0@0@ @0@ @ @0@ @`` + @pp0@0@ @p @` @pp0@ @ @0@0@ @````p`` +`p p0@ @ @`` @p p +0@ @ @0@0@0@````pp0@0@ @ @p0@ @0@ @ @0@ @0@`` ` `pp p0@ @pp0@`` @ @pp @````0`T`,p

`&`úbÊajp!r"È?»?ÈÀ@ƒÆACÈB ÂBѽC“µDP»EÎEÀÛFŽÝGiÚHF×I ÎI÷¾JžKƒÀLAÂMÇMÃÏNŠÙOYßP2æQëQ÷ëRâÝSÍÔTªÕU~äVSïW7ðX&èYÙYþØZ×î[¯ý\ÿ]šø^™ï_‘ë`€ðakùb[cTdTúeTõfNìgCêh/ìiójøjø÷kððlçêm×ãnÁæo¤æpŠßqpÓrOÑs"ÑsóÑtÄÔu•Ôvi×w=ÚxâxîëyÐñz»ù{¬ù|¥î}žã~ŒÜoâ€Ké-ì‚êƒèƒìê„Ô酾ㆧ㇊߈m݉LÕŠ)ÏŠþЋÍÎŒÉkËŽ4ÎŽÿËÍɘÑaÂ’$È’æÖ“®ä”„è•hÞ–PÒ—.Ř»˜Å¸™€Æš8Õšþä›Óî¥ëž“ÛŸ~Å Y°¡¨¡Îª¢v¶£ ½£Ö¼¤“»¥O¸¦ +¶¦Â¼§xÀ¨4À¨ôé´Áªw«8Ë«úÓ¬ÅÖ­˜Ð®nϯ>ذ â°åä±Çݲ«Î³ˆ¿´V°µ¥µÅ›¶jœ·¢·¡¬¸C³¸ïµ¹¢´ºW¶» ¶»Á·¼w²½.©½à¤¾‰Ÿ¿-ž¿Ì•ÀjÀÿÁŠ®ˆÃ8ƒÃÀ{ÄCľ~Å=zÅ»Æ5‚Æ´†Ç6ŒÇ¼“ÈH—ÈÛžÉr«Ê³Ê»´Ën³Ì"¥ÌÕ“Íz‘Î ŸÎž«Ï=¯Ïè©Ð—›Ñ@ÑÛ„Òj~ÒîˆÓl“Óô™Ô‡™Õ “Õ¹“ÖL—Ößš×všØ–تŽÙ@ˆÙÎ~ÚV€ÚÔ‡ÛT”ÛÛ Üo¤Ýpl÷ÞÎÉ11YÙvƒà1 x$»¹ŒÈ¹Š‚Fa€‡‡º`Ã<²×wQ1pf3c30؇ØÒy“¼ˆ„Gx³D—¬ šä8b9½†2Ò„!HJ‘„aj<h €6ÉÖy„aŒ)L0 (Àؾã8B0Œ%Â0”fÞl Ì~xw qc6áͶfygÂPÔ!E€ €2'˜B”„çYÎa +Q,^÷‚B€x0U»Î„ã„f1†ÙíÂb92&#:.î9ˆÁo»‰Ê‰»€ŒÏ@&.8g À‘"TJ%`Y†ÖêÇ“ 0¥‘ €à8ýfžI¤‹,Ur•T)˜3«©Ax3fqc6áͶfy£‚"‚h$‘`h, À°"»`ãË7þ¹cŽ 4A$ÐA. €p@À¥ÝñÁ$Ã0AÌc ³!Û„ DdȨ¼¨»ˆä +€@€X»¸œ¨›¸”ªp ‚ 7B'W" +""‘8w*@u…ÚŽv>6&á!ˆ³÷ƒc$’Í4’F†Ü‡Idšà͘s Y˜Æ{y³Ï BgcÀ€ À{—:5/%±ï›P @"‚`àH +txsW« H0à@ƒ®W³‘ ˜mÈ„F>'dÜÄDÄÇ` 0ÀY÷qѶ*åt@@»t‰Êä@@@@@@AÀ@ÀABEDFR)‚À¨ÒþÕ |\,|ÈaFáÈ`ÆiåšdH² @ÀÏìñ&~lÀs Y˜Æ{y³Ï B¦â@"0sTâì,šŠguû0à@…ð AH(&5 ò\5«Ñ‡$p AHie–$½c ÀB)üa•ì"û<Ò̃€ ãù$1‚œC¹EÀnÝ"r¸ð @8`B‰*E Ž@@ @E +à"îLJ°T¤D€ÁŽèˆ-ƒ«¨i<³FH+ô#€p9ýž$Ð/͘r Yž3o ä&†à‚¤£Ïœ † ÃqZ9 °5÷0C¤‚ ‚($±PP€à Áz»`†`‚`ŠH$'eÜÅÅEÅÄ 1Gà€Â /`™w‘aX×ìLb `4m†Ì ¶lÙ¢‚H ‚X ‚)(£ @0 „NïïŽ ‚ 1YäðÕÎ)눈¹´²Í áìa@£¿’I4 Ìñ€r Yž3o ä%Œ'BÔAƱ¤>]ýàÀØ!ôçFȘˆ¨Ì(`ËØ¨˜ˆ˜¬Œ/¹}Ö„a8NÃ…4»ÿ¿„ …I戋¸ŒÈ¸¸Ììߘ¨B€+€llð³fÉQ‘1qYˆ! €Ðð?î¢"`±„!*a°@“0°ßå8ÒØïBŒÒË40 ÁìdÑ_ù$“@¼ÏpÈN/bÆ‚9’"c2á +²ÿí7ÄÀ`#þ6*UW € À€ÇJRˆŠ—7ºÃT½ëBTQ m=Éà@€˜*op,a(V¤¡XB„¡8B¦8,ÌØˆÑ Þ`Œ;~b(ªšt" €@FÀc:ªA$• 0(€„=ÅM$1ÏG°Rœ € +66è®PFBp¢Àpr!MõÜ@@£åM"11ç¿`ˆ8Wòͼ„4Gœ|Â)ž¹B³ß±8„UýÉà ¡˜¨Ø¬¨Øˆ¨˜ˆˆ¬Æ€!`„GG0y‚0íù„0Âr„d(€ß燑%h-€<Š2m¸0à@ 8ð"@‡,tT\Tb‡€#Àxyÿw‘1Pœ(°p’d$_f …ÈASù BÁ‡ÅBÄÃ…þ2³#ÈaOñC¹f–dId€€ ÁÀsø<’,É'úiæšd¤ €Ä0s¹]JîeE  € #§)Jã•]F‚ †K<°c@ Å9ÇIdSËpC0”+ +B¥  à€ 6DEÿXB„a0?r$EÅb#nbˆ†¾ï¬ÕÄT!ÀÇô0ÄxC„!Û0â<„1 ˆ˜ÎWdRª!1º  ‡3™ `šÁ]g–idšYdI$Aƒtår»•]E„%Ó8a@±Âp¦9+æs„a"‚X$‚ ’@,b°X‡y`‚ †`gìu$EÞgGÞÂÀ3ÀX]Æ¡Qw"  c9]‘NWuD (bêå*œªW9H €C`6áU\ÙJ)ÕG +*8‚Lo”¤T§Pˆ!†@ÀÀy?’M,òI4I`F€1ŒÍ¶a³$d  +ä„Næ–X$‚("‚8$’¤Àl¬à~'ÞX ‚"‚Æ`ÀwÑ?X@€À§òÆ“¢H""†>W ¦3»ª 1ßW)TåR¹Ê@@B ·(¢Ž*ªÂ„Џ0>R‘Τ@€À¦ê•ΪQ\ ‹ÆfÛ0Ù„`xá‚"#6Z”% ”³€À:¸Wõ„!J€XÃÌtGˆ@„8ëò(p²Ë$“M#"õ‰2þY$AÎ ª“R©Ý\ªQ FÀQœî®W"I‰Š`h,^ÄEEgfýDÅB0„#û~|!E½™¶Þa0ðc›¿&ÇEDÄDB0€3ÀÇÝÄÅDD@[ðØrOà‚úŒ‹Öid’ia";&ö2;àƒWq1Œ¯&¢ÏÙæ€Aa 8Æöl@ ›õ0PÄ€ð´ÆDÅgfýEDÆ@\ ‹1Ûóá-ìͶðó` &"ÇÆ7â8Rº¨ˆ€`®UP[ðØq$Ea@`€XoÄDlLTDLTTT0µ!yΔ¥à(¸U:rWÌåˆ^3 ÀDûöÌ30ƒŒÂcž—7”0P ƒàٻ„! B³%Bˆ`Ì Dñ†Â`Cˆ rŠwGU*Šˆc @@üòÌŒŸùd–I r1ðÈLÇ™áÛÍ€q$EaÀ`@ À‚~"âbb¢"b¢¢ ±†¹ îp¥( À@\#2ƒ n8ë0ž"xÏÛ0Í„{„Þ<7„MúŒPà<_ÆDDGDÝåDD@›®R¦ªqJ"à Ê)ÜUu9TQÐ +(PÂ{œ'ÂT•!9Â0„#BBDBc1æxvó`p$Ecƒ€X]ÔLDLLDFDLT .ÒJñž8&‚¤”!w߃À`¨fã$ñË[8Ÿíä-„a›aèC‹À k4B (uè–H‰ä‰4¼wÙ¦’y$žDHd¨#€q ±°ÃÑáÌLh€ Š5Ü_ܰGPC$E1ÃCPAxM·€~37‡ßàp™À8¥’Yd‘$³CA&ZI^³ÇPM†Ø[œ€˜Pv¦8#†°aÀ&"ÿo!0aó`Ãl=qx¹DAƒlÙQ¨¥lwÙ¦’y$ž"$dÈ€08àáƒ[ =! ˜@@€´¼#îX#‚(!’ &‚Xá‚!‚( €<&mˆŒñ™¼>ÿqR  Ž‘;TWQ ’¬"ž™â‚æ’¨#‚ãÀ@APÀ vÞ8 Šcî Ǿî¥qLØH[›7™ ‰J €ˆ 6Ѝ§(‰¾–I’K$žÆIM€FŽL!ˆ3ÙûhÄ@ ƒ@€ÜKœðEAPQ±ËEAFa ‘,3ÞöqV@€0 n;TWQ£’j"‚X"‚Xâ’( ‚ç€l‚àfPÍpÁÇÊ €o»©\0ØP˜1á›o3 ”@DƒæB':œ¢&øNêEJ©ò*  cAb ö~ÈM  +@ 0°ðjî*""*2&ö"*2"3LˆÑa† o0ÿpT@ |D)·)ÕTIŒÈÉŒ‹¹Œ‰Ä(PþÌ7Hˆ "¸©ÕÊ!ƒbá[êCùÔP§eB®"F@" tâ„1°¼Ãð8ŒÐ€ +#0³<ãÈpl<1€‚0`qÊUU;©J¡uW:•BDÀ`mÔ ¢ ÀpT@‚†7Ä@ ˜1Üꪑ,“ýTBŒ8/prÁ¤Eö8‚Æp@D1±ØÒû! ‡Y$’4ò¤ƒ’Ȇ‹ä1 Wð¾ÄŒDsð°Ø~š 8€°›<†Èpl<0¡ÁlÏǼÏ$ÄFDDÄDEDA@ÀxƒWñqPD0oR…QÊ"@F Ôú”=,džÊ‘YcÊ âÁ»ÈÒI$ð„oà ƒ…tM,%åFÜ Àà LVMÜd\V\ +º!]@c8Ý"&*%qÂ.9Y„ aÁØÂ#LÃ"33Cmì íŒ ÞXB„%B0„% aàhƒÂ ëÞõ„ *䉌po™ìÂâó–2OeBG,i¦8`Ýüi䄞B7„€Àpúi¡aIC3Œ8à Sy…©)î„áB®ˆR™>݈™±Ù¤M,XȳM*2 À +8+„lqÂpÈŒÌÆ›ØÛ¼°„!J„aJÁ`4Ð<6lß½ë @UÈ DÆoŸá†ˆ 3dˆ˜ÈÈØ„ +ç`÷ÝÆDáLÿØþYb!'ú"B€Py"hJʽÄ€0€,~Çe_ÜEÆD@FÂM› 9ž2DTR2'â"&3";0€±¾GL!c„Áy Œ(ç†ÛÍù³,!B„aF†0ðhƒ‚`SÍç@UH "1†`oŸáð€ÌÌy’"c#"b ;À`‹»ˆ‰ÎȉMÝÁM¨"pF¢Pòhþ¡@ pÌ›ÿ'‰$¸"”p£€ ÆîU8™†FýÄDÆf £í`(@ð,O‹eLÚˆ¹Ä@ ÇÔ"S‚æÛÍù³$DÄFDÄÄÄF!À€x‚׿*¤30r \;Ã{6ì°„a,J8,„T »9B0¬- B­ôB&ÕPÙCÅp¢S¢D`Á¾ªW8W +œD"Ú€¡ƒˆƒa¾W(°…) r½á8B§ÀP|ÆïO¶ŒÂÈb‡2Ä\$&0ˆ³cÌߘaˆê3®£„B ÀT l€t AÂofÃ$DÇ"£îàdßDþÇGEØ@Ñp‹Cüða„À ¡ˆ#c*¨‘m0qFÍœ®Qâ@‰D #LJ"D¸¸P|X{_§\˜ad1|!€#ˆ¸Pžaìy›ó€@1cn•Ôp‰½º¨> LÆw @d `ÁìÌãlvHDÝæƒ +°a +;Ä „q gˆƒ„Ì¡ EŠ„X0èçR¹Wwg‡„€˜BDf3D4$$4 ,$$…“°À;˜‰½Ã_ .(§B@ Êêªáµ®u*ª«Ä0 ¶êR>® Ÿä!€w @d `ÁìÌâ! Øôñ4ȉºÀÂsÂ88@Î!›d8‹Œ ày,òM,ÈI¢ÅÏ 0„€"Ï4À H$ +À`€B"å2€(ä° )ë þ#‚ÀÅÅE8A"`ÕÕUÃ$¾ÄšYäšI"O1€q€ àÿ’i§‘$ŸI,'ù`u Fcl6Ãl0ØôžK4²DDš…wŒ  ®D ¡¶‚oŽLç3 ‚W7wQ™1Y‘Qwp?4hÄ ÿýP„½ý™,ñ0h +€A p$À`h¥<ÀÊpPç©ó¸|›€ €³Û„fNþ4žÍ$ÒI4ò #Œ¿–i¦žyãK$’Iàs |=°Û °ÃbîWQJ¬t"  ˆn¸D€"€7„&ߊ|ᢠ€p:&ïôDÒ¢M?ð— +à Â×w¸„MýÔvWÜ" + + +2Éh@-°#À9AžÇ«‡ƒƒ›!È@!DYí„# œw'³I4’M<„ @@ `1×)Jsœ+ªª‚á€r Y†l`pŒÞ3D 6¥UDAPÛ¨¡±Ù¥˜@8M$Yd’x ¢€@F D˜ÝU)Í–Œ1D‡p¯9ÖÅ'¸S¥wXç‚("’h Ž8%’j:(à`Ü€v{¼ðA›)NR‘ +ÎP®q€D`Ü(çEw)ÄA@˜@1üaá †0r Y†lfŒÞ3D0ß(§DA Ž*‘lzif :Í,H²É$ð BŽ¢#„!ž"YÂXå48@(6°Uyΰ–);Ãõ3¼À³œá(J’„çF’ǘ"àT6Wð… &éT®D Œ g(W: #ƒxm˜ÂÈ„†3ÇáŒaá †0qó‰$¢8üˆ’,“É4]]B›êPˆ¬€ÃM… `, ^e¯r£³£#ý6?$±¥–I## @@Üp¾¢@‚#2l!D qcf„8ûˆÍ„FÿfÏ„"7„1Äfqóa3?~!1 @s<ÇÑ$•Ds¿‘E’HHXHɈ‰ˆŠˆ¹ˆŠŽÌŠ  X ,¹‚ƒ'†6O´S—MË 9¯·ùÞ³ó6xÀ„†!HC"3!Æá"Œ!cd!ÇØFl8[ý›Üã¶ÈCPšÑ!Œ0Øb,ÁàB #LÃ!DöB`6͘w›ýœ[!0°Ñ`pó͘¶l'î"> ˜€D9T"ã|Uq +Æi$‚9$š cž`‚ †ä’….‚ð†+˸$pKÍ£8ÂÜaM¯ûøÀp þr€X0öB€"Mhˆ „Da†ÃmàB #LÃ^ÈLÙ³óxcd'ÈL,4G˜p˜À„DfØÌ'ød8Ã`ó  D€ ÊR»«¨DP( š) މ$‚ç‚ ‚)!Ž"“ãÀ2‚P7U—pÒŒcÿüá a +_ù‚@>Âÿž(ˆ0î0y²#³`Ûd!°ˆ±³oa…¿ð…›7áaƒ˜p*ª”à@@€Ç(îr„ªª+*¢¸â¹€€€„ € å+”§uŠãe•!JRç +•#8BTHà€¸e²\v1 ‹_Ä¡˜÷ì0@ +ˆ€°õÚ0A07\ÉMõ"7Ȩ#³`Ûd!±áˆ±³l7…¼1à¢6Ç„a† `nši&I$ @ ²OäY ¨®¥W(®¥6"‚0 éì®DW¢"ŒnD „îòÏ,Ò}2aÀ+’â¡F +"}ëႼ?c`Œ,µý£Pcçw +mPcâ”0Ì3DcfŸņ±›l? á3‰ DY‹b¡lã¸n)TЍ  ÀœPÝr‚Þ6a¼ÄHH@LaÅL6W"+»ˆŠ1¸y@ã¼³Í4žÌ•J儸¨qƒˆïZÜO$lD!wwq €ã00! Ì,a˜fˆÆÌ30Â!f3máá¼#fq0!ˆ‹8@ÑlT woR¸¥DA‚qGTT0p‚,ÃáDÆ€b†""˜ åDEnœ¡Ct8†ˆxˆ¤Bÿí$i=䈬(–ŸžÐ؛興»¸DS8®ˆL7Qµv߆h°ffÌ„ˆ@ff3ö3BfD#fò10Á›A‰Î_%€q3aœ!ˆ°Â ÀE³ÃQ|8F! @HpCq³É¦‚ßñ™B0 ‹¿¾ˆŽˆÍ±øÈ úÁ p€:ÅúH“ÿQð€ 0$ÃymJ6˜c Ñ`Ì͘€"ÌÌgìf„̈FÍä&ñç³bD& ÝprÍç†n;0@ˆ@DÌ0{È€DvØœDE3‘@ˆlÛÊwPå1 +Þ0¥€`1Ö¤áHJ˜Ö1{ô Ð;Ùý‘4žrDTvL0 “iºŽÉ„1–J˜"{<ÆÃ #ÃÍÛ͆ÂͳÆ{a!rÍç†f#³@ˆ@v{Þ@ @"#mÄDIìÈ 8 +wYd–0Å!Â0¥ 8pÂ?Ž-IÞp”!1 ˆ…&6åWLè…M²Â„©(0 ŠÁwo Ær„©,(P¤Î“"m½žcxaðÃ4GíæÃaf Ì c1¶-pܤB&ò g(¢)„G ßù€ˆ"lÍI…“ßI%àiXv DhïŽ Ž8#-!ˆF„gŠ 0ƒÐ6#ºq.oýœa8 +ˆ¨ €D mH•A°‚Pm²Ê“…¡ +((A·ç:Ns…©n˜d\@ƒr«nqE‘Mõ„2Áï3lJ®r„]@‚ƒDcwüxpܤ@3 D g( ‰°ˆá›ü6:,Ìð`H™‚¥;òà@‰"‚ ø)À9€6‚š¼øp @2d"&&&ó  6ñ‡3ÞJæ."$„C¿i“D‹Â\¿òÚ“„¡ +aÁ¦‰§8Rs¼-Mp€à÷EÄ`ÇpVÇ8*¹P6u„!Àï`Í“¢âb"c²cpÀÀH>¬kׯ<qšY&™; ˆsù¢!’œ Ùã3!ÂpS“´rpP‘ðt +Øïú>n +&r"I=ù)'u‘‚s‡<žDI Hw•'h¨Ž9ç„R6ê&é²Ó÷… €pÏ p,XÓû,i$ŒCqO䉀fƒ{3"6 ¢‚Xá‚( ‚"’@ + ôáÊ;¤ßºã†ƒí€q,óLƒ§t4@È(p€6Cþ@ øB¦‚D#ÑH¬nA!ŒÁ|lpJÀ×/ýœn€@á0xNˆ*fÑp¢º  ƒºp¨Š„AÈÚ²1Ž‚!HÕìmÌ)s÷…" ±f“ÙcI$1 ŸÉ!Ø,ÌÑØ@'L80!@$Q&\rÀƒð(€ei±¢[·. ÛrŒ—Éæ†Eõw“ €a~ši&˜€‡p;É"&˜ˆÙ8Iˆ˜¸XHHˆJ¡à)ã|æÉZNN& U9UÔQF u(‚&ø§RT"m±b´ÿÄÆdF"oîã1Ùx ŒPË,I%ö$ñœSø‘ LÃÁ7¶6 â@‹P!D‰$IZ €^4$ÝÖ,:sâÀ‹,g±€r$B²nâ⣳nr"â#˜` +€ÀA71QQQ‡€< }ÅÆgE Ä8q"@ƒ I"Pô4À%€ihòàÀ 0ÄVA³•]T@D7QÈ!βI$Ä$É?ì ÁçWyb'„%ÿùÈè0P³BD‹ÖI!IËüHÐ&cx€ ½±°„ñ A‡(¢D$­`( + ðym£ªpsct<ÌlÛ!ð„6"±«»„Lƪ¡G(#fááb˜a“2®"/p À(À,^ÅÝÜÅDDXA˜g°w FBDG`f?ü€H!š±A,jî" ’ã&6"*1A€1ÕÄEuRg +¥8#!Ù›l  BZBPµ)G€À€€Á¶ë +B4…-‰NüˆDàuši¹üˆ„çþ1 6†€6 À¼â|à†à’ ‚ †¨’ hDwö$±&!À¯âM$-))ÂhР B >ây„ç Æ„! „†{y a¶8Hbó0x‘Ì„@£î"0‡a¯œ›˜¨œQƒ08òÉ$DÞII8‚Ørœ§q3œdDj$‚J(‚À @r1¯òÉ$qÁa-óÏ,ãˆb€@ÎPu™ Îï*1/"+ \Xˆñ‚!‚( ‚$‚8$’H!°ƒ°ò×q•@puC˸쨨,ᄨ@€¢DѾÂ0¬#ÂPŒÏÍ€{ c„D^fÆBNÄ0€X øˆÄv7ç&æ*'0€(@h|lDDfUäDd}æ39@ÃŽ@˜á^Ï4ñb! =*"‹<Ò;ëŸ ¨ŠšË#ÎxhA…»ß<°1H80hzb³,¿¸¬¤tM¦# * 8`1ðˆßaF„!(B„)K„…–»ˆ¨¨Œ¬Áàv òþŠ!ÞUï™Â…©áh€È ‰æ…aF„`xm€ M±Â¢ÂÀD ™0…`±yqŽ@aaåÜÅDßgfDÜÆÞbP @<ɈyëÛ˜›¸˜F+2æö+ÃLPXäÝ®u‡a9ú Ú´½Ï'_ž1ÃmMa€  +(A7ç8Zy¼!J…¡XNƒ‘ (;É,‘"K4ÓÌB3¿¸ŒŒŒŠE ÷Üb¢ÈBÛsˆ0¸ EüD\LTLLd!¢„ƒ [c„2,x‰ŽB8pçòÉ*$žF•È<ÿ¹Š‰¾Å3!7±·¤ÍbZöæ&â&ŠÈ¹¹Ž`ã 3À$  üZŽTŒ?n¶m[wÉe“×,pÀ[SX(LOs„§B…aZ„æ„PD{à ±²f]ÝÄdddR8“ËûŒ@`…Œ Âû,Ȉ&8Sù'–ieÙh¡ŠƒP碜ˆ"žë¸Tˆ ›6vTˆ)ÔàS€@Lö­7Q‘‘¤"Óÿ€ 0P0 €l!¿ÞŒë RpÆ- ÎpÅ$À±CZÀ ƒAèYËGZU^óåÅÓ§þ˜&’H'Ž( H[à@@Lq΄±ìFwÝá +Z•˜FÞ6Á†g€8²DTL\Lff †%½s€€0ñ€@?¾H‰‰ìo}šY cဪà±ç‰4Iã ‰úù,°TЦŸeH +霙é´ßDB#2‘¿q‘‘H` + ƒvP¹´ïˆFy…©s„ç8r–`x¡UÀÀTàÉ:ÃÊ-EÿlZëþ0•) ÎP,!,0†Ø>Gp…¡d !]¦Ÿï +Z’˜@`ß¶ 3< Å’"¢bâa˜ ( h=u‚ñ€áÏ÷ò"HDñ‹ìѦö÷$ 'îæ22"&9Ž„®îb¢`Tªq]Ê@0tÙ\ ‡:ÿ4HÈ’É ä"*@ \œ( ÿT®ç +R8J›¼çXká§O‚ƒ`²æ@¬4»Ê´ÜÅGBc —Š Û˜Ä0@!¥’x·Îve„‡ÆE¡ã³J‰Š‰ŠŽÊ`(€P ¿n"qˆèÞIȈaÂp9äˆ ˆp€€³ØÀ7$€,'þæ22"&ÅCWwQ10"º¨®åƒ¦éB…=ÒŠDQÔl ˆˆ€€€Ž¤6 *ØæÜò¢I—H¤N‰.<8r`F‘%)ƒ®ÂC‡=ˆASôÞý4±bB\VR„®ncÁ@†®O?s², ‹! z È@03d¨˜¨¨¨ì¦@ köâ'¸Èˆ›¸Æ +ÂÂì` €Yw„1 ÇÊ®p$$<ÿ¸ŽŠ‹ˆÎ΄ÞÄDÅ@Xxó6`€„\wN”ª"A@0ïÀð @p±¿¼ˆåÅ(’ G‡"@…" ŽA" Òœ+|áì‘’ù ;¢ $!‡ñ¥ã²ÌC!ÐЧY0€àá~‹ôÈJŠˆÌŠŠ`PHÁ $'æ".** +B„gYÃÉûƒHn°œ9È\ #žlÜÀÀáßùiäL–_d–h.*JRˆ £¨  DÄÄÆB2#î㣢"2ˆˆA€‚ /î³ ÃÃÞ†!eþÅEÄ@Fà ¡ƒ @bØB1ð„$DY˜ìI%šIQ„ßø0 ˸N„°ÑO|šu„©jF„€p&¸,Ä‘@Ø|¾ç +bT”è¡Ê~ðÄ# R3"naY—°`@È ÛÌŒÈûFa^0Â%ø†Erù ‘Ýy,.!^¤±jfõ£À( +&_œç +B0*‘(æâVøDcd(4hl:ÜãHSˆbéÞœçÂPœ'ì0Úz 6 0 ‹DrdIáˆïb#AÀ£¬0 (å¬#:BXx‚Ÿ*œ!,Jœa$…À¸L·Â”®ïxÑ®nõ‚ÃK€T?øZœ©I‘xäE§ `<<Û¨¬èM Àpd¾Ñ™•鏯1VßÌߨÈ-© Ös†¡(N¢€ÀØOõ„aHNc‘§BKâû6–HÄ %9à@ÆÐ:°¸µ¾ ‚I&‚9ã‚8!‚("‚#€;2Âx ³`q`Ã(™¢HŠÄEÿ،æ x?b³!>J‰¸ŠABæ®ÈWµuƒ‚<,³…)*Bán.º8< Ò€vá¨fq¥&YÞtÖ!:Ñ P™ug(F’…g‡  ðbï"±˜¿ÛÌc:ÛèÉýŒ‚+"öþ:&.+ ûc“H„‘}öm,‘ˆ N<1ÃP@ŠSOŸâF<àA +(`@€³!Œ u™°8¶žñ’¢±0Ä-wÀÀ sÀð¸Í¹˜Þd@ƒA]1áÝf„B9ܱ…!Š[á.:O¼ʨ^…ï(R„'‚AŒç6®žD†—¯ÓO&ˆ3¼À8à/€¤–¸`‚8à‚ †$Š8㊠ ‚0ƒ7ð€u™°8¶žñL„‹Gï$D gáâ/±`Á‚s*B +ä!ˆîY§òxIŒ„g! vZL€Á…€h¸¨¸¨È-!9–‡ „ÆÛÝç:”Ä#Á@àir@-÷‘1Ñ¿7ð„3"/ïê À°-1wQÑ1Q1Qw10*u¤÷Êt¨‚QA€`0 ¸•œa9΄¡R–žç(Z˜A™„t?à ˜"BxÄȉdTÝDê·Á€œqü‰¯DA qïy‘—•˜‚²ÿnŒXñïLNvFd0¬ãKa@` @6KÞý¼aJZ‚DL€±éЉÅBn㨘èûLB +À|øOƽç(Zœa[çBc¡ ÑÈàBBAÁà‡¦*6â&*&+iù„DX^AÀt<1†"00D„ñ‰‘ˆ›e7Q”‰ÔžD(ˆÜB#ïn1AH=7p¦G‘ñÙØ„+êb˜ì=±8¦1Œ‚£þÎTK Ð`/ «x”% c“"ß±ÑØ¨oíÜRiø@8`P4`é<4W}qÅPE0AÔIqÉÀhC4sy B €! ”l¥w"1ª¦ 4A0v Ã0²„=ÈÄ0 Ž{䳿CŸ$•DåF‚¿š†ÂP_PA3›¬R• €€Â<ÒÄ—÷q( `8  t#¼8$ÂîP€Ø_Sox¥oZ… M½ŠÆë=w‡fü¡P·Ú€a€€à7ÜJä’›ñž) Ž#‚&’ˆéŽ "€8‚#6aE‘BÈxƒ0Ç¢0†â/x †`ðÃ@H@ÀF hŽCp/Ic~‚õ$È4ÿø¨Ð¯&„#ƒ¯È"g5±Í$ÔQ$0KB…ž^µ5ÇpCBL +@žçà0 Årq»53Íqá%7ËÐIob°ÁXYqô@S =(*ÿ@À€ |"t¥~íHNpœ#KSÌéHH8‚ 033¢ŽÈHQa8þB@ÑCq€“K$BvsÄ$Yá#)‚ XYéú¸…"#pÄ%xˆŠÁÎw²Íi¡~)â †ANi`šI ŠH¤ŽOy:^ëŽ8ã‚ $’@˳Ӈ@'&hkm¯\¸p!ÅJ$™r`D‰ +H„›ÛŒ(`dŸX•Á€ÂGë@’÷@ƒKœ.Ñ“ûuÄb~:$1à"aD0a0Ü9 + "ðÈÂ`ch@„†üÒʼnƒ!Ü`@$áúH³Á¢d'â½ò1^! ÈBEBe—óƒ ðòÛy‚¬ Ù¿PìLU€<“„ä)™„CHHÁb×1  ðñ?¢t¥r‚L0aµ"VøJW)Š PÁƒ|¥ +u3~f›¬IPÉ ö;¬ðDJ"¢`Ãtˆ©ª„Bœi žxàŠ †¤£Ã¡áÒ0üF†y¸2 ªÀ´/+ó•) +ÑNws„!(Z–COv @átoAÀX@2K6zp`C‡8¢@‡ +(àDˆYÎ9Ssä7zÂ4¶”ÀLf¡eb”Å9 ²L?ºÂpÔaòîÞ£òi¥˜‚‚¿ödÒûfÌ„a0fg†LE²wÜŠ›å"@(€ø6ê`c† 4:…ÌÍÁA$Á”xt48ü+7÷yð0ªÀ”# ØÄ:jF®â#¢P( 3À±ö€ Øb×øðp +U€àVÖ¸ † cŽ  ŠH`Š8 †Ö”„¨…+:Δ”ã ÏX$„*¯:@²¦±ŠR‚@ Nð6:½ï8CHâm§9ébHˆ 0BÀužx’Ïg™‡€ Íäa„‚#€u rÀEš! @LñR…:"nCÈ #g9J,áhN…!(F˜PH(!sk‘.Ü ©ÐÙ †T ]"¯â#¢P<Á÷!VD¾H è€6â:6î:+*&â6 bâ”Guœ)j[ž`Ð` @CéÎ,ilR…`p‡ÁwáûÂØÕ'½ÎF…’" 1 €@ƒºÉ$³À™æx„0Eæð „Š#€s0„Ä[036Þb®êEˆ€Acu(—•˜ÂÀ†ƒÂÖÁØ<†DúC±8ˆô–‡¶ᬄ@áâKü“"'ò~XRÔ¢)Öp…8H@öÂ&ð0Pýë3K$”EpC%ÍÀXàÀ=W<IqÇ@}˜ VÎ; ¦ºc‹ +8ãŒBõqÐ…uë<4SžLÑ#XHt/l]'³ß…À¼#˜ƽ32L“;3Ó‚B ¸<ˆIµ°0 3ØkÀ0 ¤r8åI ‘ÃbrÜEpP‘׎'`0ã­G  J¸ŠŠ‰‹‰ŠŒˆ¸ŠÎ`y@lvñ„áH[vë•\*” € :…#b¢¢c`„ }s³&šh“Dˆ‚@˜8¨ Fsч*$xð`F¡jD_ H&0A}v\ˆ!ɇÇ„€†#)äú²îîÐq™û{ǼñâH‘90L@)4ð!…õ¸SŽDp¦cÇdHP G— 0¨d"…À`¨dš„vüY „¬R|ñØdÒI‡ÃarxÜ5ðГš €h&+z˜˜8(Hèȸ¸88AȲÉYd‰h‘#ÀÈh>æ*"3| ܪå °€ €` lêPÒY¦–"‚8~Ñ$ŸÙàìÉfš$h‘‚Ǩ!œõaÒ‰><°ZWAØ©LH7®Ë‰DI0âX@@+Á’ôã +KäR“œ9æw˜zŸú á$$*—ƒÀ€Ú8.ÇšŽNFÃ2¿¿NR‘óqp0P“XŽ@bv1L€ƒ¾ò0“‘ð±rrq(€†€ƒŒ ÈrPÚ%x€Û(ú˜8(Hèȸø8(88AWuÝE¢Šcàçöi$@ƒ3«”ê"€˜Â cú¸JE[DAD â(¦st.ʨ¥"E$L`m ÍœwI +:B.V0â ›d!±°—ºwàà€„€˜‹îq„'HNs„%JB37àa›`ŽƒÌEs„I‡t@À À +yä’ +öI&žP¡AAÔâ¦pDˆ0uÈ! ÄÛŠˆ)@¡º¡yp!LÅã¤ùë`xoÒÖcÚ¦~ oá—2A+/Óð†düçEÄb‘q÷X€ !öñºÀ3Gi€õÛgV:b:Nž2.F?z0 0@v%¤'x$ +b € +…û9F„!F¥©[„óÈN8Æ"ó¹D†8t@`Ü(yä‰ +öH“O¡BÅ8)³ˆºàA 0l"&Šˆ®S"œ"ˆ¤AÀCJ_x%#Ô{òL@ à²9Àáþ1дñ1ò°q’cÏ7í2p¤¾ê".ëB‡þ΀2ÌPöÛŽl8!P•\&LJ4907U0ÜV>‚(Æ9C,á8A @€ ÀövŒ' +B0Œ%KR·#†ÆB"óy‰\ˆ"Cs@€@(Ï"I!š"h¼H…s|R ˆØÙ)¾(!Àp " ‘W9JⲉSІ¤»í'´AØ"Œp'F~ìed\,Du!BÆ ‹“ý肾Ôq2o§yÂw„qâE +\Úô0 À˜ûuœa +c‰b{Gsœ¡ ß&€pñGþBK'+¹>#!@ÀÌXÑÿ1YÙ?q1‘6&Á˜á66ósD@QÜ¢!Fĉ\ßPˆ0`Ù¦ø ‚0p!€ÙG8DQÜV@Dxð#XL,'Œä¸¬ƒÐ& Fð<Žýb\ŽÜØ¢@;aAáás½8‡¡³€Xpøl]9Î{ýì‚Xå²×h 3ÂÁeíÌF!ƒ‘åµ1¤g8YAÁ ·:j“œá {‰L"]1¼„˜@ "Ày&Œ†JïIxG °`la ±·„ˆÌÆt (L3Ðá¶a €ÄUSº„LÜBl‘áþè!a;ô0ˆîöI ls` ÐiXBo:aSpŒ¿Ø,¢Iõ® ’¯ +(ø›·(‚Pˆ  ‚ãû÷&Ù¤`Äζ7rô !Žtqz"…¾~Y PKÞ<‘¹oóÁ4G ‘Q‚C€<øa»±:)E& {A€ mºØY›ÀÄXf1ì0Äàx (ƒyclÀ! #O$’É€ G?ˆß À pq¿t!vRÉ #€D:À=ý®0ÚW±ˆœ_q<Ò=Ïy¢ÀѰÎÀx%wò$ÈÈ!p8ë4DE:ÃKAPCRA%C<°QD‘€Dð AxÀäD‰! E9aˆhWâ!)“ë„eGeA€8€$|)šôGÂED@À@ÀGNYf0(ʼ g™ûðq‘q2Y™Óèò.?ô€p!Øæ E®9‹oÊ…þ¢B:^.""&"2"".N +R¹ {À!ÖŽì2YwÑ¿1HE¶æÂƒOøäìÈpF ˆð†p`vOüÒCBàPþi!Ç~h`Š`’`’H ‚ † $šIà‰À +@¬@ u +TA·Cn¨œ„EÇ"}wѸÆV0À„,˜1šôÃ`‘(D€C#“¬ƒ”à‘˜™·9zpàB)•°X¯¶œ —€t9€=‚ÛÉÛûuˆ´Ü¡¯5þ‡g¿àQ"ãnDPÛ ˆß +£¨&Ù„tOäÒb$HŽþh‚wåŒ%Ô!HÂp„# +ST¡@0@£à"Ø€3©J"‹tE ÐECˆþ1¬TtBœX%tÃ`‘h„2€A!“-Á‚–ð”¸þ;¿ù\”N%¹<ŽK*ÔUz¸à€.*LŠéÂðŧ›Â”„áƒAg‰'OœóðEb& ?%î8.Hx Œa[¸¨¿MÎeÍÖ#OûAX·ü!0@d8ˆ„!Ežð›ftžY¢çœYbH@2°•ŠE|ÝÝFÅc²ˆ@ Q`xÄÛª”P ‘·[á ‡ñˆOÊ~ƒ yb&ç0Ø<:IHžI%Y¼–øJGÁ4!à±OëÈ`ð˜„Ú™(“ÓdðØa‘N—x€„àè£8¥ÎY(‚Xâ‚ $’"ÒH)4÷Ùʼð@ãK·Q“ “\—¨»]ÌTTK’…®ñØ—ÜÀ€@0ÌDÏ6Ïm„ t;”@@çʨ D3‰ÑQ1L8‰zn-1±X¬”0凋Ý\PN ±ÆøAR=ñÈF[V¼VM¦3*×€ Ššø›Ä£pØtN˜âLˆˆ<3 ð ±oß++m‰I_‹/ zÑò׉ðHàbxH!6äÄ‘" 8°!Ä‘ÓDÿ—´Wð ÃÏ¢‚áÎä¸Îˆ¿¹ŠŠŠ@€ q HµÞv'î`@ f"g›g‡6ÂÀuˆð@ Þy†Ç‘'€ ç9ý–4Hb$Ç䈛¬ÈA„ç/þ  !¶šëîÂjÝiªVó‡1]îÂßç¯Àm€P 1À¢žx˜‚×AÏÈÍÏÁÍRIGÑÃÂBTz´àü;p'0¡Þz’±û·EË“«ç§D¨EL6VÄP0â$7"D*ccö2N±'’6É¢ûß™¶ð³=uˆð„ ó yyÁ8qþ‹HÑ"ÂD\#:Ó†2 z™kMæS˜Y]M?îÆ1(NvâTíï1”Ó¡`‚ Áãçó„8!à"<à'𠔜:ýŒÆãp¸2À Ãm9Ûàˆ€ÀÄ«²ìÓç2ÃDÄã¶sÑTŠ™ºD `c&qB$\Æc„ÔŠ|S©"ƒ¥PCaŌͷ…™†È€s?0…² ÆÑ%ŒˆL @(8³O2i'• jNv¥'Xc8óÿ…gZ$†”92„[üë:R0¤ãO(ä?¼Ñ¬mt`@  +&ßs›Ë€²ràAWÀ?"›éìrX‰Ãàp8 +„C§†:Àœ ˆ N)#îI§¾;ž œ Ìí¢h)$wш$ž,i"õô<ó lšaá Ì1ÂD!ø! D9„8Øs?0„q¶„Á˜ÚI£$˜@€ ë4ñÄÇuBê—œ©ŠFãÆ>>ýã8ñâთ v›FLE§ +0ÈZ÷ +BÞØƒ‡w78¨ ˜ÐàO€¿‰~Ûû¥ƒƒ‹ƒ„„ƒ‹€†®Nʬ7spW$çœqA›‡Á8™ÓPJ2G{  (wþ"YbK×ÐóÌ1²CáÁ8#˜c„ˆ2?¡ C˜C€q)\ˆA"Á€ÛœªU¢b1™7xV/ã.ãÀÀ0ðƒ×dmÓ f-ðPÀâÃÄÜE (0Ï’(yÿ[²¢-öâñŽFÆcƒõ×.bp\@S@ +àJj™ÌìvãÅ&%*ëÛ¢P@0ãÀ ïØ##+_\3Û.Û27 +  ,,=ô·î2 #ÍŽòlu§ë:o_#"ã1HP˜@y…%Șð<`? si9¼à‡cËH7îx´&€ 4¶­6‡ã2¾ñž˜"³ +8XÊDîÙç²Í9²Bs·ªÔç yÕ(IùZzç¦8 €´Ô):ÀXaPøwñÚ{—‚3òú÷¨åšXÂBœè ‡èHWñ“ðƒá‹fñvB€"³Ü q$EEc2°‚$À@°€H½¹‰ŠÎ‰‚Ê…±F„a*{œé£X@ €@Û{<˜p°, –Ä2?q`B‰##P 6s ¦þ1åXñòæs÷ wÇŸ,aY +:d†ì²:dù¡‘à (Ì”«’é'®ùâáÐ`¬ OÚ‘”ÿ‘A’Q’‚ÀjbìE>š"`‰:áÁÃ_/†^wìõˆy…'XPàxB¢ã?®ÿ»ÁÒrÄ?»Ôof–a!Nt0ÐsôI_ÌŸ„ŶŒDŽÈtB6{„q$Dfb²#‘F a xZb"b³" ²„aÌFóœ!:[c{½8ÀÐpX˜îÑ AÀ UY¶ÿçaá`àá&7 ˆ n°p¿¸øËIJbüÀÌÎYñžO ‡MÃ’ºä’0¿ãÑÐà&œ})×™"]YóàJÀ¸R8W?®¡ù·NsîøðT³¨#äÛ£î}0h³fâ6vàø@áØå|òI9ã@_§;Bw‡a‚ ¯˜ J„̦õ ‘ˆ…80XKšºŠŠ‰¹‰±È„L{Yšid–X~3r`a±†À@E†0Û-! +s½çRž(8¡³hàÀ L +…Ó¼àˆHH‰jŠh»8ÈÈX¸˜ nƒæK€¡ t|viI}ö`9?®;g©À`ðFèGŒQ5—GÍp؉"ë)Ff5ùåÛ}°YcÀh¨ÀF³‚ÊýîÜ@Á5êJùㆠ+RÏŽ·^8l7Zzú4C.÷]¼€8‘°¨ ·8а„'XZ˜ÂXŽû8(4B|_]8òK|`X¿`P0xLF1Žc³Ö˜Æ* pAœ²~ˆ¦ +bË¡|Zí‚%Ü—ÕO÷— à‡LfñOüjmÿ°R#׆2Öœ+'%x‹ù 0‚BÂÿcOIÒ"HøR<0ewŸ$8¦T¡Yq`C€=Ã…ýÿ"Í" ÀPï™í€tŒ!8± †xÌa ¨‚x"‚Xà‚H$’Å‚„Æëþ<f—ß$R?í1L0AÞii¸Ç1 abÉ\Á``à|&¼õÎ]Ö¦8—¥÷ØC‰ B#îVL!…3²¢|»[Ö‚?K’gÍÇîü°‰üË3çS¯sÔ¿wêÇ‘9¼1–½08d‹ -xAö @HY±¦‚)*¢J@Àp;#É|Yò؃*{÷9`Žé":ôCsÿ,Ò € Àð9žØsࣘBd(ƒ< UòC±ÁI'B € € OšÇQ—§ŠŠ¨,oÿæph8P¸"ow¬-‹ab‹]¿ör¡T â*ËÞTÄ+ +ÂPçSPïó +q£@h·½øb(ÀA‰,×ùSÏ‚ ’õñcDܹ¼£ÏÈb@pp›^Åû½'¨ïÓ^,8e¾aÎRz ð €T&Ìå?2¦&]8J4qÁ%IÁ`Tqø^;ÿMÝÿòé±K]0EìY¦ö27/Y¥™pxCÛsà¢#˜Bd(ƒ< Æ$)raÀIš„À(àDýÌ­ùÒ%H,¯ÿæ8@ +øÐM{Ö…¡å={Þ´— +@ÌT —¼iˆJ„a…-ñ—ã +q£’kýz1„‚€CP™ŸÂ—×à U5oÃìHÑ;·2j¼¼„à4|0ìð‹~…ü=' ïÓ~Œ8æ‚X(²‰> >ÑP`!ZYè² à@ª6i%4sÁIF‰¸­:8 ÙøJÝa…cÓµËÐ Žäù{9\ˆ `ö?lsáq`fq„ñ"H‘<¸`A‰"gA€Ø€3ž + Sÿ9°âH™ ¶š{­€€4`Ð&½ï BP–)BÔ’\$VŸ÷!0h…ä^`sáqf "ÃОH’!G‡ 1$LÈX0`þÄ)p$H]Oûµ +€ðl!4ïHF„aHb¥3¡ »0œßyëŽI"’ê žEÂÁ‡aÉœX]„ךš<£•ê`ñ!0 ÀöÍ|Qžöذ¶äëõ,aGùûš)¢€À\'þ–„é?¾žÏ4 Ó'DÄp €ÖÉÏ,J•!Ó£9±âÄ™9§¦ ´ÒKk‡(¾2l.j¿||¤-9C‰ab€  €‹âƒ’ †ß’»oïŒCäýŽC¡?˜Xý0Ä¿PVyëˆè$äßÜÄDEdFÇ` B#n2à,1ðrÃ?üBHÛ¬Ÿ„ž´Æc˜¤àÀ,»˜Ì&EÂWñÑqB„ؘÜ(À uc`‰i9ç<øð¢E&P™#Ð(¹€5ôÉo|ÁãH/3Ohû–8$šhtµÜt*T¹C?ÛôãÀ)¢E˜¨há%N™ ÈÁà'˜®Ù#¯&Âê-¾Øê¢Ií‚híÙ„4wÂ8~‰z ‚#ƒ#BΜçJ…!F@H€:˜Þá ÀDDÜ(6prÃ?üBKÙÊ•½0…/¾Â”µ5‚A€%p ¯9B-!8Sœá(RAÌ.¾ahG‚€@†4c3 +uç—  1Qä(ðÂÄ s@ß™%ÏØ ð°tYäìÛßvhkκh@Pö$©Ì©S% é¹çÀ‰\8R'D‹Pˆ€è(€Á…޹§Ø° € x0ØãŽ,:¢™éž˜ê¢‰íž(å'Ô(ÁP{÷~»Fm§1ž-÷‚ãŽ9 Š`’`† +0(À|p31ÎH#€h“À€Ð +°tö~͇á€dû˜¸¬TÜTTs +°@ò⣠´„ájBp„!*bš‡oR`8 ,@>º+‚ù(vžéšx(yxø¸8HHˆê ‚àÃQžçT¿$ +p+ÇÌH—&Hú¯ÑâI|æ§–üú– #—Æö¸'P•_=¹1'CŸI‘ Xr  H”˜YK¾mâh‚¼ Ïó‚˜4`âD¨ñ®Ùä¢h ŽYå,åÂ@J˜;xBsž§»Þ‰)í·úÓ\4Ó<0EÁPGPI¡ ¢@ }òI$ˆ»@ÀE‚ŶÀtö~ÀßøcbJ–yæš208<Ñ!a ÃT„çBT¥# +ÂT¤(À@€Lsü€ ¨¨q—ü˜ó`B^\8’ @j ÈlG çƉ8qñåÈñþÇ H¼pÅ?·åÐäÐñ¨ïç4¸“#G‹\:Y/S¿><8ðàPJÑ (†·ÛxÊ}^ ËÎ@@ +p2:š·„,ƒœêêž«À 0 àW<ïd9paË$é’¥Ó%i…§ûzÂP„á Bp”)Ãð¸à"#zR%ÅÚXx´Øs¿<<XÀ4Y¼0È@@P†2D\#*ææ;*"*#2)€àÃΈ €€È Øóî]8´%GÃ>% !Ó§>J]”%¥Ÿüù$B¡B¢Œ‰–œò €‡À˜¾ÐçÄ™JælŒìŸû¬Šü`¹ È0&#ç‡o×ûÇG3ùììÎ××gfŽx¤ž‚À“ÓòTùÏ  x²×kÑ!ˆR„c2$À!Æÿ|œ$dŒ<<< $DlD”)í]ÅDÄÆEÆFaAË…“y^±€£¼s¿<<¼4Xà  „">•ss•™À p ðž@¨€ˆ +àK2ã.‹ÑòÏ‘Ä4´»ðâF©» +g§<‰¨P‰9!Ë&v€2)€Â>»&i·“Û§tÈ3æÈÄè Äs_0þ;‘{Å¡‚>x2_1[þäÂè7`X ( Eæ«óž2P`IIY:%ä9€h3Àu€p_©åá! äbààà ¡ à!`àâ"¢†r»ŠqA‚L3dJúPcpr &3 ¼Ña¶Å\QÈŠ'Î)EqB¼Â˜„' +Δ”% R”!Ã0€@˜µÀ2( C2æ£d §SBËÇá 8`“Eœ[ëÙ‡…I“0lÉRXvÀH„ÁÎÁPd¸"™ÐmáDÜ,dtDd\%sjAAõ‚  ‚lè5Ï}Ì|‚CTÁyú9ðÒIžPjí@0,ÁxNbÏxà’ X¼ñ[‡@`F3 +PØf¡äà àâáàà`" à à a ¡‹ð´! DDFŒ!`Øt 'ˆ ˜Í ²DLDLSE­±q‘Q‘P‚ÀáåÆû bœ+8RP”-JB°§ +À02>aMê°õ´t^—: …•Æ*íž=a§¿V &@à±Sß;0ît\P¢ÖϨÀ‰€@W}ÝLN ‹J'‘I|Ž5¸m {G˜› +ór¿ädð¸ƒ@ŠX7'ÉúåÈ¡310D}%Ì4­›ßÒuÓ‡$‰™8lŸÜùá|:ÅÀ¨l<§ËxàÀ‰!À… 0¢yá B¢"1ÃÂ1„ ÛuE0€ €Á²‚ `Çu)²”Y”„/ ( C¥ÛÜáJ„)ƒ€0H6Pù:%Íîóœá BP¶-;Ï4°P*e §jVò`h |.&GtP0Á·S*Oè@¶DÜl$ö§De¬Ç$'|üµ•„u=n!4 \bVvïŦ„I­šIeÞÿ´~‘Ì¥¨\)Ô9a6hM?˜s«‡œá\ÏîŒI<(iÞÚã¥ö´=våÀ‘ŠÝ?Hòfq¨<@4İ•ðAÇ A‘G Iâ:©E +â ÆÇUÁÇÇ0uI€!t@€@8y§¤ÐÑÁ…O\$4aËöùǰE$A& Àe ¸æÓÜç8Bд%OsA”4QfO\RK<Ê@ð./1Úç“…hº6®àߨ^‰¹X:ïD„'ŒýÄm¼œD”Å–ÆT}ÎaD€2¸LF÷Ä&ƒÈ²žÉæ¿_9 a¬Ê#¸@GDTÞ-jM^_”i>Ö €ü/gŒp`À4ÓƒÝ?‹ GÞõÇMBbÁ% ¦Á€ )°2ÅS„)^q…! +Jq†©;ˆçRŠRˆ  ÀaÕT ãã˜s$GF r_Ç ,-±Ñ1›˜¨4TqÄWë]JzFß8çŽ †$Áà&ð‡e€Åæ¶2žgXJ’¦¡:r™‡Ä臠lo‚Ig‰À*Ð ` Ý]yÇV,yc8ïÃeþzö›PÿÀ‡~|)”¨tx$@EÈl@92Xû½JQÙÆ~2®(ú¼OëÊÚ4ðø0lÂü䎌¼Ö‡¥f9ÉÑë|PyX¬X4¢Ióž $¢ä`l¼™ ÿq‚‚Í¿Œ‰¸¸È˜ˆ¼VMˆoª”U@@" mÔS¨!˜sš!!Ïæ±¥‰ ìжÃ-÷w& +*mýÞó…!Bœ( 8Be>ÍïXÎã:ÂTÒ‹A}â’A¨wAä móÉ ñ0 +€X `‡èë®8¨«ÅXü8Ðß·O¨××MeÔ, +5ñÁ ¸òðF1½™ÏÜÂ’”z{¶aKºð€Pa¼´ æzgʱrds×·Nl8+`±/¹0&P™œxq&H´À @°„pʘ6~´†×Ýg;„!B0¤'KR³‰ã0 b@Qð†66`tqDG* " ŠD Ú¸‚ bËýAŒÿûOÜdLT ÀÀU”«í§JVw!¾ +Ÿ®9ñw÷Æ”-Ì!M08#` £yÓŒ(•7|  òVxÙõ–ß™GŒñIÑ °ðȲ~¬tüÒxúoÔp+$K‘r¿¹òy¡Üƒpþ âÚÎ;1ã@ ãáà`!!$¤!"çcâa"¥$!æcàb#$+æ@¾&pÍî¼91æÃ‡,8p À +HbF‰(qa…žŽ ˆ0<0<0ŒlÀtx…ˆaDx˜"Ø‘LgES1Ñ\¢@@ˆÓA}pI,sÇ$pPÍÀ”Om + +^N߸îЈ[a 9‹/c3"7È Àq›–»æ>’}†]Ù*yd©!@°.R#1¯/ÎYÂxôd$ Z- 4;¯ÑÖ‡pä$d?d>4äÀƒ )Ãàh +„@áq< ŽE!ò| ˆPÎRÂ~EÎÀñnœÊ9ðˇ,8p À +HbJ‰(ra…žDd ‹=³0 0€€±˜uBˆðÙãB@ `Š8”‚PcÚ¨ÜB(|¢$F²ˆç‚ã–¬ÃÁ¡Øa>t$$ ‘;7Ëay=ÂÌ1ÿ[Þv„¡ +Bœ Æ h‚˜ìÍßt20 #/?»®H0HH.4œ·¹ïCC༠"1;¿  6·»µ¤Àp F%—Qïǃ91à¢&"."bÒŠŽö^ +B2ÁÀ àz W€Äà#€HOì©Ì¦ë®\8p Àƒ`H‰"8aņ'Ôß +6S«ˆ€@APÄ ÎêPuBˆðÙãB‚8ôbF‚½öI|0Ž9e‘*J$‚8#Ž.³O (#¾º0ñ¢ÄŸ“ë!y8CÈ!uÿ˜B–„+cŽb€Âç[G×N‚q@n‡0Îwmç$H.néR¾šqãÁ¸°Žã`7 Ât3ÄüúY`¢Ç.È?úKk€0X <\±Aˆ µì"Qpä2 Y€À«{sáÒÉùàt ŽA, ">ør¤J:›6^‡>Œ Ü3p ;m:¨\gÐÒFÞÕÏ‹G!ø¬%8³J(vyün*_Þç¡}×ÄïF\®éNˆhà<`¬–Tpp OïŽX ‚9`Š`ºIçŽ ‚0€@)ÃÀX´Üb#ã"obb³¼Ày,/8B„aHR„¡R€€|pGó1 »Œ¹ÈÎÄ€F`óþ&æ Q؈ؤ8 „`{ë"Ór`R -öHÂdÂÛÿ‘˜†8@Ìzˆ4–YÒ 80.ƒs¾ã¢J(ªˆl```²R3Þ×!p;†à áÂÏSï¨É–>\%åĽ¬Eö&dfN}l)ËúÂ7ˆD=éB=qÈ…þ00(¥Î„8‘.dOsŒ/ ΄)êWq„áL °À иfð„¡:b¼áB¤!™³w,/B„aHB„¡b‹(8 €¸ïç¡?‘'õP8/°•ŒŽC‚`=ó‘ssŽB-vHÆ òö>ÿï!ÆA˜<ü!„3Á"E;ßþòUº´{Ç$’Q•H°@aÐVÑÜGDXvdâ 9üïúwœx’!D™" @. ‚ØÅü稔X?$'©Ç®Ê§^ûð¬f‘ŸþÝ Z+Ãt +‚álÊ|ŒÒĸKŸú­£ +B4Õ1I^ôÄÓ"õ€@pX ßÛ¨»ŠÎŒ‹ˆ»Œ ÿ ?=ÜÄ7£ÏƒQ%@—p ÀüÌvMÜWUR²A :„‰Û*¹AMñgDM0€ˆR„p8/B7/ÈBH¨U1=Ë$§'µßü±H`†'½Ñˆ}@ ü F€IŒtþݼ„T<|dD4$dDl<ǃÐäv8ÆžÌðéhåB\: ¦Ý +d{°,÷÷ž/…jú€@ K0Œ­{Zò¢¯X>½ÛK%Z Y¶ìó‚;ÈZ`À@¢ÃOo¦ê"ã±Ññp‚ÀàDfPÅÿ3àÀHÐ#LJ° @…¿3t -f~ÀÀÑBº¹B61¸ ` ‰Y‘0‚a~ˆßÜaY«Æ®+œEx]ƒ/“ü©Hh€ƒ˜½J `F€¤ =ŸÕû§F¾2""J2"2‚2–~iÒ\`,ÉÔ\ê"ä)(¡æáà$8„€+|w³íñôñâç°1£ìø 0.À÷0/9fÖ¼,É#(«îùdš9dÑaÁñy^qÞ1Âüáܼý"¤b +uë4A ñ°*‹ƒ7û\ñÃIðC$PGpC UÜ(€r ,³ÆÀÍÅΨ•Ê¦Æâ€&ÁÑ+26AØÿˆ˜œ@V%h+ÃK)È*ÿðÁPuõÿ*R`£˜‡ƒ€(ÀÊ€Ž@ J@w>ïãdH(Pµ2FÅIŠ?ñj3Y'AÎZSKÙÇÁÌ+€„0¯\SûåéÙÆchY[éà€œLæ?-V–¼4é"+Ø«Þx¤Š9dÐ" Âó´ùæ1ËÌ#÷%IˆH§^³DB€‡€Hö­÷1‘q9Ñwñ1Û@sƒy„1`m¼Ä§+Šâ‘6q +ø‘™†fÞGD^t>Îx$úSc¯·º õOs) ad5€€€ð`éÃx¾Ÿ.VJÒèÀ©ƒ% +kW}C ø–ÄôúñÑ 9i=7['@¸`QHxcs_I¹©EŸ×¼- ó„ÀÝ|ÁgŠYÚôwÇG8 3-N¥º’.83°jææ"/"#‘žß¸˜F@@ 01€7UÝB¦o¨!þÀÀsƒ63bÀÛy„Æo0ÈBÀD qdŒÈ¸ÈFNbŒZñÑl +Áà—ô… +"Ý?wÁT“ÇrIDQUA‘Ð +À‡ àGÉhõæjùš$™: +P)ÄÚΦ>"“A$ÈVRSzT/Ú,Aýè/F»“rOÏ^n ¸ÅÛý±)èàI@ˆ»««B•]V1òý&iânŒ3‚_1×°›¬¢ƒ`$ ‚³¸Ø®á8œa &ŸÌ'À& lmhƒˆ¡L9Êrx`ó7†<ö%wE¢‘$3¦lˆSg‡$P"@…5@ Àôüo48¶Vl‘ç—õ 4Câã)Öq¥1„9 η=‡€À0 tç³ê\Ùtbf`@Õ©O ,€ð àÎsÂfóàL"ð³È2ž²xYiY0QY¥µ3ÿ ˆýé…!µÕ¼aN!¿Þ·œ%D$£€ +À-/ǽà†ã‚#‚J>dÓ2utÉÀ!°Ñ6"<ö1PˆQ¾À€r~ó7þ{»ˆ‘()ÆtÀØD¡´AÀB@A@B@ABEHfL¸(€—£{qÝÖ÷±ðqôd’BM|Â0¢œÚ÷á S`<,€Fü×Á£"qƒ±l 6éæÅDÃ3¯Í<šqø((:a;s×ùÙ÷—p’·ëëŽ-p‡¥Ñ&f¢æáâ`!! $0=‘Æ£A‘eZ_Ïneh ƒ€h±¾œ8/rÉ$Á Q2@XàVÀ ^@<HôÇFýÅÅET}Ì32þö:ìy‘E FAâ!ÈX6€tr•Î""à Æ®R$ À ‘‰Åj™º$<¸Ò?I‘Ããh܆ID˜•žóÏRM$ÐTð*& +ÁY=°]„S×%ÚO˜èìb)‚$6ê*É^˜„¼Ó_žAO‚  À#Q=úmŃifÿß<š8#â»íS— =àžJ*‡¶*Úi¿¸2P€v5Ž=€œ +éóáT±?}¸²$@‰’%t%<Î9óX¾0s¬hïg„ˆ3ôdNïd@àlŒc„A¶ 9â;tr•Î""HÕÊ&!‚Áàp†H&S͈ Ãvø5/=&7„C¡pårc—Ï<I4‘A‘dØ +X Ïñ‚(%‚K(žÒ}G!Y‘8C@ˆN(@)`h[F$òO%Ì!$À<XE}ñ'HB +€½;„w;ôåÑÑu²róòp°óß +lÉï¡p¤$ÎuÚoÎ Ä á4pÀ)€®§¶J™ÿÛ‹"DðáÈ™6Ç"ç².x1åŒë4wÓÂ}/ÞÈ Á¶1ŽH€36üG`sUw(‰PÙ°éñ‚D”$<<<$TdÅ@ŒŠðƒÜ±…€„ƒˆ´È€1:ýㆠ’ˆ ‚Âà8( +À¬Ï!Ž8*¢ië,å„ô/{ÎÜ÷B €KaqµT)EÿDJMFD@M#E N ‡©§ã7 HÊÀxB2ÜöóórppÇÁÃf‰šÒõÕŒ¹J˜#  +Of¶6µ8¢€À¸p°<=ï¨ÒZZø±&DƒIáÔü¡‹^xôçÂ$ MÔF2Ûh¢‚Á¶UšZW·±3qø@€B /a„„ˆ"ÛsUw(ˆ@@¾Ÿ#U$óÇÅ%RYƒ`¬å (ÄÝO€µI—Pkc%YMÖ€‘ +R¦r‚ˆCcÔ¢†Â‚õ–XrQN¥@‚ÁƒîSˆ„D¨Ûˆ¸Ì줃 À’×ws‡`Ê$#u €8u—ÔdÑKŽ áE¶]ÿÃð€,10¸+r”}{óÓ‰€CAÖÁÛ‚ðY!?˜ Mò|—`åÃÞ=ƒ°Ø`¡s÷ët¼9T,(PØÙïjÿ4²..¾g½ÝA@A≆fN02u§1iÞaD§!4X.Ì-O53¤â0E~ˆ "L؉=Æ€ÙxiüˆA`Ps¼é4H3àç½f€rQTå Æ ò¹Ä@ˆHfꈑa‚F 76ùH‡gFD@¹ˆG?Ñz¦F˜¸QôÉ¿¸S  „Áp*¿){Þ§†<‡‹­³×K1IqÉQ†—FÝÃÚ'ŒÃ +Ì©‹:ØÏ6ûãÉ… …—>µ¥é¹A„ú¸Ì`hþ :0#áyŸrÉeG<Ç ÑD‘Á™¯˜j‹PTmÖ½ì$<ÓFÓÌ'Ú”„áhBp‡IAÀñ`È?ûÎt„¡H ‚pç½f€q®¢„@ +1ÑßA !@0câ”R„Q(äͪ¸y4$F0B;¤¿„@pu‚CÅ Úû_ò…h€‘‰ ‡×„) cœPp +!1á/£o«_ G=A_w7Q¨€ä£Ÿ2˜0 +0w… +žl–†#ÒÁPø÷¾ó1Y¿¢zî€|7@@Á´¶‹^ $C,àÀ…DP${„1®hP<€È&vø„4Á£†Ápšõ„èYrÓÜåB8ò€8 …|ÂPŒ)B`ßqÜQHCDÙÄ u)@®L6ªâVTB1L8ˆ[â!6À ƒÍûÌA†,A§aØNÏ9â‚™4ãî"ý}ñÁ$Qež,`8~ŽÒŸ6ž»ñdF.î0@·À€h `ðK÷Éhf>L +ˆE?þ¶ÆB„p0%êäÊ7Ú˜éYäËÀ@DFFAÅÃÄÀ@AÀÀCFH@@À@{‡$¦”@T6#ûÒÂ"2gõ„(_)í·¸ÂŽ,‚ $ Ýë B0¤qºPªç" ¸‚„0êTè¥@VB uÜ[B…©¤Æw:Bu¢€ ˜ ¿zNt4`P&Xœüˆ½ rGMa4‘ßÝpA•IFŸyqáÔ@`˜›Þ,¾yçÕ2DÍ +þç¬&ШKð¾¿\³Â’þTs +)Òì ¶ÝÝgeÚj0IB(ŸC@ "p`EŒÕ]ì¼ 4D„\<< D•$´|¬g˜, +P À‰2eÝ_°!n-J¦ç +`®i“ëÞ„aŒ À ‡ÂíÞq„¡BÈÀq9˜gŒ„â8 :•:)D†w„¡ji!œhÀp +L_Myž8°àtÖð$“ôˉLŠ’"Ë|8"DeLU$›8Ô<Ó^Vn_üsY¦ŒŸˆ[êÐlXŒn+OYgŽKýâˆ(¦_ɂɈ· +‚û4Ai™=õ X¼t0à ^Ùð`B‘"8ðáÁ*†ï–·õ— ðâÈF €<âx°MvãѯV<8p Ä91à@‰@àÁà4zâ"c‚ +"Ï»ºŠˆˆÀ†ˆÃqDÍ©L‚!3uÅN‚‚ó†`â‹òFDGbè]ìdF80€yð RÃ^`XxÓðð¢þàÃË«¦}o¦9`‚Š$Š ¼MG&î»>Ѱ()À¼•ç›`ÈH"¼½ÚšøÂÔϧ‚Hï–ͨ‚ gèÀ‹ór , †`½ú&ˆ³'3y†€@@=btû× pA$Aqч +8'+ÎT@AN'ƒ@„¡5ÀâÆ^n6.@ƒ Å®î*3@Œiï\ÇEDÜà@!ˆ°q@)ÅöiA ŸÍO"@°Íþ€1_Ž$‘‘ˆÓût ÇQÂЙ‚ðå¼ø ™‹_û|±ÃY$°dÑÔ O®œI׃€=XpÎ[ç>ê‘ kÇv\iÇ‘ÓÏsÄ‘týïL +Œ “˜«¡A h ;oÙ&F~PûªA’kÿs¬çB„áŽ0pañ´â˜YÚ(€Q, +àWÈ]6 ƒÃâ±8|€Á ,ƒD Å,Òßq‚€P@$½ŽŠ‰¹ÁS¦øs@À8þM"#Îñ"Mh*Q]Ù"QF wP…"¦E +DÉNR|€LƸd¢5êk©`dèvð­\ñÁadÁáÀ¢3“£ß‰2Ã`$™`0‚8®·žœi“,Z‰6üáJB„` DLmÊpsA„‡?I§FÃâDš,Ðrh’Ë*dЀ€ P8;é,‘†@ÈîþK iycÝa DÔG<²dH€`FF +ÕÁdÏA +‘ŠL_½œPÀ   ~â6ýÍdE$3ÃEQÛ\XT]îð@àÁ;£8_tÆ,‚Ë®` \6>0ù,²Kä³É"wCÀ‹AX4nDÜg&ŠyàF‰l¹±âÀ‰p D­pÛ_ípÏLsIph`éÐÃÕõÁ$A,À!6ܧr !EÆ@" 3 Ù&*"2."2+0`xW••@€(!b×w1Ù„ +C~ãÛŒèŒa¤†ˆ£–Lž@A8¡>l^í=°YeØH œ¢y8)²", H>ÃgS’’½‚ëÃTœ%ù‚ƒ€à£¡rt²å×Fzq¨/ûÞd˜t\øÁËòiˆ7;Ød^„páN‚:dH €ã@?2»äŠ8çž8çŽh"’ä“ •és†9`¢I ‹0`ñpHH/WÁx=±Î˜: ­É³²¿s¯ÂB$b’yœ2zô7ÐÀ‹¤ëë†J„Ì„BmôÆ(¤ÜˆC;‡%K*$ÿÀ€Ü9þë,I¡@Ì,²n£`x‹ b(áü€8ˆ‘Cœðrdd¾Ï4±!"œ½€@ Pü¨ˆ Lgq¦¡.5î°¼#8Ó@ÁcV†xk¶9,ûÉ·ßAÀü‘¾4]÷ÛdBþÃÿœòל0(Šóß•Ì(Öa$Þ6±?uQÚ;cކ úñXŒ§úàɃk20°XNîÐ\y øzƒÇ‰Ïߥ®O<³hg†J€Ú0r#ÅÅ)â“9¾¥Ø,y÷z‹!ˆ£ŸÉy¡‘Îðrd2/Y&–DšoQ€@ä‡ €4ÂWXèœR>æ":é„\.Èþ;­0¡'"ûô€¸‹×‡ÿ™ÓŠopáA$ ŸfsÝèH(€ÉtÐ9lÃFÓË!Ž*ï³ê?GL“Á¡`˜‚±Å}ðUÂfÑÁp(ÀŠ%ë\7&*•Ûëðd@Þçÿ,8$Dƒ.Lx±$ò10Dhø•J@LÆ@Q¶ùµRˆˆÀ€ì<ûÄ"Ѷ4@@  ‚¶áq¦Î"ªU@ `Ã%ãÃO&! ‰ŒÉ½ŽÌÆ +Þ a ݰ¡ˆÑg¿ñ?‘ž¿Û¦ +6’O"†Åƒ†¼÷ycƒBÐ.ü5Ú ¸ŽÝç!¸P‚ ñÏ=>:`Ž †áký`ªÄà,Œ?ûh: 3—ÚëÜDå}Gxñ`D‰XqàH ˜l`á$F¢°!é0Ü+nã¹JDF2 =°¡‚¬ƒ%"žDcˆ†Ôáqa 1á@DQø›×²A%ˆ—¬2"ÏÀBÀi÷x`p@èJÏ}â8†G½ÿ7,8ó"HØÐä\ „$Æ_ñbH¸˜l3o>½Å, V &5¼rÍÃE_¯{éôêÑÓp`°È`°üzÿX*³C Ð,,7ûHxñý½.¼K•§á·.Œ;_¦‚Ömψè`6ì&}qáP±\¹óæ‘1óÖ@¯$ °üaˆYw8¦Uð‚@ÀÇ¢p0g”mDö¤(låS"œN(A0ÎQB)1ÁÁƒ}ÜqEU $þD0 n†ÀÁ»%o”§(@@ƒâÂ…! S…À.T/ºZóǦŒáKBÑÊ Ddz¢(¨ òèÃ#a`€N˜úÌæwtYv¾pŸ¶|ZtdfÉHóôã‹SÄ,ÒúÇô:Rð¶Ò+ß‘*<øqáĸLJ×þ= Ã`D.Ý1IÎs-ËR"ºp¦Ü7Â%QÎAˆƒ|!€øgˆ¦@€„êlßwQUA#„„€x yïÏA™ ‚H$š ¤ `˜ñý¸]~qÍðE$B"C•DTE3tÈUa#Ë‹ƒ0< ÂØUèVÎ%‹dÝq.\^<rdh@ðyh~êÀ¡2dˆ2àDä$¸DÀ%›æØ¥?ø°àÐÀU#Q÷ Q€pl†ÓįÙÎs…1î@@0ŦÛmH‚†øŠgAÁŒ 4T!„& “mAC6§SœUP@…›0tý†üðÃDÌÐA]ÆÑÖH€€¨0˜_j ·W\0IDÑÇ"! ;ª"¢žèˆS@DpMEÐXQ@€+9ì² ç†8¨H@ðòÐýÙ"$ ¦D‰ià%L€–lò¼f¿þüØp°| dN4[áÆ ‹Ð¼CO6âþ1 +bpPÔDØ7È‚†ø‰µAlÌ2*á6Ìcõ ç~³I$yâI$¢3ls?3ò¿34IVcqí`° À‹áA¶ìï†L¸Ó=ë€q=’_¤šY0 c‚3óA–IL|(ú~`A`fœ _×$RGôYfI_ï³=wQ1œ@@,Ǿé +ͱRl€@P0Ýî‚BsòI"I4@€!@p¾iæ‹(äFƒ ÁN³!%øÈ‘ü4ÑVQmrÏ ‘A ”Yfð À´G;‚l”|GðÄ'Â…ÁÁpSñƒW>Þá(YG.ù³–„C &77Š×Ëç©ÿâ’ç‚*"‚cbWè¡âß÷QÙw1ØäS͹@£œãs¡IŒqM’â#*þî*"@ÀàÀ‚ßq™±" >‹4þË$‘%ØsꨪAA€àÚœ®0á0 ˆ"Èw„FCˆe„adÇw˜[ž…”Ck߇ .e< ÙOˆ¯xBt@°(€ ø`E8á,wÄ¡ZR<84…€x +B¸¦Ksß &‹h»èÇ…$8ð!@… Ò`1ÎJÿ¬džÆC Ø!Ì1‚"8€hŒ!ˆ’ò#*þî*"0``0p,¡k¸È‹è‘„€séeì²I$Ð8c{tõ2_$@€póõòY’Î&d[ÃáÄLÈBYÆ¢¼å†)10tœqiÞ S*n¯ùÆvÃ@4>¿ìíˆÞ´¤ëKC'¢ÀLHÀÆ^ÒeÖÁƒ_zðâD…IQ Æ9ˆ<Ëã¯y"#|Lâ¡€Á²`ÔÆÔWR”c’DOýšh`00cPC¼’Hƒ³">›¯$šY$gït$\â³nâ€0.÷7qQ9QaÂÑ3ˆq!4rÁ ”Q•px@‚½è +Ák9°›<àƒ $„–×¾æé ‡ö®Q_·—X¨ÓO&†$€'€¤Ï[2ÂÎÛ§¾8$š,úÊs¼‘D€Þ€H¿ýµüB2®P¯Ü`Ä áú +zN8²ÏY&–QU6Ô®H`ÝUô¨ `@9fëßÉ&šy YûÀr$D0¬Zö)€ "À‚Ó{s)Æè‚ƒ‘UQ·$AÁÀAÂCDEFHbü1f QF¡c­iê²&0ïæâà! Ç)ßïÂ&ž +ê߬ÈD¦‚,ø^ ÆË…PC_w×E%yšþÍÈyûÀ€h À‚6uË7ËERC +N—xFEyì"ƒ‹/,DIç‰ ®A*:”@‚À1õR"ÒÃ@ Ht2_¼g›Î„!Rœ`™îr$F0ìòÓÁЃÀ$^ÞÜÅEFDŠÆ:  äES¶8 ˆÑ 9è:@ÁFéÛ,˜e‡ŸÞ\|<8¤ÛLˆ6 ‚Œy&ÙÙ°²€€˜6 Ÿü±¨Zýç8Jˆq3í¢"Jb«’`¬P:¸£M7G    € XC¨Rø"Å ¢6À&N¨R„&çWC jªÔ?ðPK>‡U™ðeÍ( @8p`f{€@qˆ DsΑ?þH“I(ÐÀ€Îåñ dH“ÿé¤LƒA!ˆt2MŒ)€YöCÁÙ£åærL7"™sÃÙê²8\ +(‰Ü€ @`< ‹n ›çDE§$pBãbêÞ4Ò +Sëöp…¹Äå[ºb‘(DB9&¼àXÐÅ‚F èÜþ#‚Cá084$Õ5ŽÄ‘³qù#ÂÄ/xdçr#‹Ò"$òÊ9€”€ï¥‹¦‰Öxˆ‰¢ "):à2 €zU€0ÿTÍÂÅÊÁÀÀ@AÁ@@ÀA@@ÀAÀad qM„TB!ƒQJr  àç/ˆH³"Gþ/ÓHˆ8(HhHˆˆ¨ÉîÁ@”ÚS€l€ï{ñôÉŒL½=ýZ¸¸8Â$–0 +¤/òuöIÑ Œ0æ2oÎ(@F{nqˆû¹¼Lr%ƒÁ$Y‚ìÀÔ0[Ä=C«Åb‘H|v'€B§ˆqÔ +¡Ç?êéø€qÁfßÇeÝ£=7™‘q1¤ˆÅ +P}DÆÔLEÌD#ÊôÁà fh™0€€&`±ÕîÈá0¸Œ €@à° €À pŒ1ì„qÀ0#D{3ÆF†‡:Í4ÓBœýg‰4§H‘¢J‰CÀ@5ôçýñèjHÉNî¾÷äÀ€4 DwŒ4@åÄÈÎ;–Yf˜‚ CKÌ8ÁVKÓ@PÌ-ó DÄT<\§`‚ ÂÜO»ò4õ³ñp×P-ñ¸0s¤x€Q‚Áâ~ã¢.²/â¢ñw’Eb„@2@x |EÜÄMÌTTq “Ó€D&B\ PîEË‹ß^O ƒÂà¨D À`(€ÁÃqÀ @$@Afüˆ& ò•Ê! :ŠVXR¥©*AÍ.&½á¤¤v¿ó +ƒ0ñF—8¤9Šóß±111DˆG Â8³ÿaLëOÔ Ã X[ö‰ˆèy88JÄÑàXC‘d»^6‚‚>¦~.*¡L%Fá¦/ߤyŒ,<Ÿ¸è»¬‹ˆ¨üD]Üi"³„€d€ð%ñs‘71QѤŠxÊ#H@8Dª¨Yø˜x8Héù88(8„8"Ø`p€„@¿BBcmb,G,Ddh°  S¼Hˆ“a ŽÀ’÷i¼ŒCˆW–½Ž‹½Š$Dcç"†ø‹(ªh¶r!Cb-)LcSÍê€P€&ËÞP”-KN°ò"ÓdË €qy?¸ˆZÓjΉ΅N_tQ(c»¼!8•1‰Rˆ !€ Ž®®Í¢ d&B¶Â + u\j¢Ê Cy·™Qw·1("x !a¯ø ¢3m$f#&&&2* € ¸DÂb¢ˆ‰¿ŽÅg$ óœ‹¹ÌΈ‚#ŽØDdþDõ/³hsÓI’aµ”ßo8`nÝß AT‘G qSW|B“ÐÀ$€D.föP¦&ŒåKBT”$FbÌD° °ÕÜeÌDs!K‚!€c¹ÜåO ACd&À  >Á<1³ArôM?^ˆÑbKÈ ÀQü "3cn,-KR3œ# +B˜( °`®õÈÿ3„(9'DL˜@ P¬D0F8¼‰&Œ”å|Œ†Šê“ªb'ä49ÔÐEy„ùßÀ4Ÿ‚°¾tÁI aòI +¹éLaA·Âåïʳ9Ò¤!  a _áH<ۈ˸˜â€Â¬ˆ +çþÇ’I¦’4Ý¶D +"m«Šu)B·"Sg&Üæ`7Áí€n,-IRSœ# +B˜0€@€ € ƒ»K•_3¤ 9$Dûä…9}ˆƒc…äO(Ñ“uƒ1ËÊ“ÔàîÑÏK Bˆ(„Ó¾ ,¸|>m>ÂP•# + ñD +¹TçDbÛ.}{ààAC£lÎ…) ÂÄÆ K}ÓÄŸ·—q1ÄÀ Y0¡Ç;õžI%š$Ó ‚qÖPˆŒ `"!p,! Bœ)IBt +ðÀ21ùû•O4â0n$è)·( !‘l‰•@ @,=û÷ÀÁ'ÄlY"q¤_Êì Zbbb£ˆâ¦ÏáB@`|†ÝÞÿ ë÷¥¯8Bs… œ`Á†cý'„¿bb²bï@¡dˆáƒ€»¿ÓKI¢L 0…gˆ`ˆl0ð°†6À!Ú, ˜Yä!Dp$DTDDfT~„@Yö¬•Ë€À׬’IäHÒ&ë2TBÂs”4À@1À˜]xÞðŒ%‡Ž0¸Š÷„aDæeEÅ @@vJÓ +Sdo +>›´¿Ñ§±›ãš¾áyÎ&s0Æ_¤ñ¯˜˜ì¨»„RôAÃpÅGwö4°²M$aÂu""?Œ6Øaá`3 ópæ‹0l&a¡‚ o$TDDFTLTc~ÆeÇ„xh£Ówq„3‰mûÅ€ <ÏMìDF0‡.âb‹ +BPŒ' aE‚íîq„g:Zœ@0V;O<„@ +°¿º$Ï9ä‚ &ÒÈëŽXç‚AÎ Ä•Ê8ïÑ>F$wA„N€¡Õø±¤ÿÙf bwtA t‚ ðƒ%S¨®ˆ!G ÀËøƒÞ„3Do$TDDFTLTFD\LfD( Âx$,hÛ¸ˆè‹¸Èˆˆˆ¸¤gd¾2ˆ +xy鹈‹Å1õÜTQaHJ„á,sž†Ó#Îtµ€€¡ƒ€7ï¡@£0Œÿ:(®¹ã‚9*²ÈãŽã‚ȃœ®®ò$õ Hý Ÿ¡L‹e)M·Ç*UB#7 „Ã| ÉUN+ˆ‚G È‹ b/xNÍq$DDLdLLTTDDLfT0 `BÀXà ,›¸ˆ¬¨¸˜ˆäWübE áúÄ@À pï"gñÜî±$4“IpG I4‘AuIñÇ “X˜ èÀN ÁñÔ¡tmÓÛ%RC=sÁ$TU$E±Â9à€ˆpŽðɽ»ù(ùz%ŒB!ÇzëìY‰ˆdÂŒ6lˆ¦Ç ª…w(ˆ{—Ø’£!ˆýpsù¢É4|!Dq’M$²Í4ñ%ˆš €bcÁàÛ¸ˆ¬¨¸˜„'‹üG"„ o¢† Ñ!¸‚>¨ÒU$QÇ0A$ÑÃ]dsϲUb` À(T`øFïT]%÷Ó$ÖE=sÇ$4Ue]µÒ8ð@BÖD#‡|›áŸùI{y“€À%{s•`ÀÒã*$OŠá":¨o!Lu1¢ÂÔ¤+8¤' +QVû„0£ +,8ñ@À¡»Â„#¹Ã”Äã{ÎXóKæIü—„g¿ö0€À`°h»Š‰Ê»ŠF:ç†$àЀŒq¿5ç}sÁRE’Yf€À6n‚"Ž4ùN‰µbâ"± T'í€à@ð qQq1$IŽ"QÀs æñŸžaÂÉ•s{•0 ð€iw“&¢¹‹¨¡´H"n +ñÌ’_d’Hˆ"WñÀsÅN„!Îp¥1Ë]=Ë B„Mü³œáŠ^ð¬(À@Mî…g)Ó @ðõß“MÀ€ +À1€køÓ·^\x!D…J: €€×øˆ’Ë}™rœå„˜¸È¬ ¼KჃϸ¨¸˜È$ÁÄJ8tÍÅþg™ ¤ÌÌ‹Šý¹ˆ‹ŠŽ0Í`Kâ&,U)Ȉ«”Aa&pDã%ÜLTLEÌVVdmÄ0`b@<òYö„) +B“½aÆ›iÕ  +Á—öZNó„¡8J`$ ƒ§÷Îs…(€€(=5ôzpàDØp¤&€7€CzöçÍ(`@‘yA†,üIë¼ÈÊÈ߸Ȭ¡€£‰²\DVrSÂ×ÁÎû{,aˆ^ãE2_fx†@$wF„çûr¨0Àç²Ä—¬ÑË20@‰ä ° +  ò8O‹\\vÀ`$€@ ‚@ 2\EÆFBñbîn/î1@±i²D™4±ç‰‚0@8¢‰œ2M¾WÈ‚P:b„† yp -›ßw*R €øÈfu§(N”g Ƥ¡P´Ã‚†3»Î((åÅLÞ·¬-bÜË(R†,!Z >>ŒãÂ„áƒÆÀr±„$ɤ‰xÉäIO°v8‹N7‚Àà0‚@ ÐH, @ PaN¥°P( "^·œ'ÑAAkŒŸùg*J„)(Nœ¡jb‹XP2a_ʆQ³¹N)HŠÎÅÁŒ7N›:§ÊDR4@.îÎpŒ!HB“¼ç +SŒç9AŒJÉ^Ü <åïüdvOÌ8$’H(h  „<Ñt|×<Á A À ˆØrÈ«e(¢¹Ù8Š‚€$ë à,€5ànÉ-®'‚Àà0‚@ ÐH, @ PQ ŠyàŠK¸0 +Œ­=³ÁpE'NR¿3G‘A IÁqQU’H˜,0°5X÷ø`¨@!™(aÝÎ)H«•X €‚!Œ ºˆ"cª§ÊDE`<ƒÁp £8B0…!Nsœ1D)YÞq$Bm^߀Xå¦..+&& ID4 €d ! +æŽXã‚!‚(!‚a‘qÔ§¤Hˆ˜ûŠQ:`FP h9€Ç^saÇ(p`B‰p A +$ãYõÏ™ À•€¬š£Î9`ФÉbˆÙ£´ÐACEpEÔmÅPxX° Âßç‚¢3 à8ÀÀ ø»ˆ¸ŠŠŒ¸ˆˆŠ 0ˆ ;`p´,fÀ‘``h¿‹‰ŠÌÉý‹Ì Ì[þä—0„"¸Œ €€ð$ùFzîb" ±„±h@ <X€t>«9Â0œã BPŒ%°áÑÀqÕÔR²ÆwRˆ \ âÀ †S¬ç b;Œ%IB¤-Ñ#i&ûÏ• >\ì ·½×0E2U¦‘眥„!HF¤a8ZÃD†@`À`êó…$Ø ž¼ç7ÇpGEPAAD*„A0ÆW ‹Jr¸C„‡É%•G,ˆ@€ˆ8çô—±ˆÈûˆB 0Óˇ ðµìDTb‘Q€ÐZn"bîb¢¢¢ /‡Gqår*N„@0g9Tˆ"0àÀ«…›{qŒEúã¢b!D"Ûl*’M;šà€—!÷8F„a,jœ‰wŠû‰‰ŠÎÄG @ \D$¬\S ÀîY¿&ãÁáÄ(Å2Blq Ę<”n"¡É'’%D–áÇù @A8Wäˆ¸Ì‰ŠŒA‹ÿ ( +(—÷1P*(¨ € êäùJD&±›`q fÀ„0G!„Dy ˜¦*Ò½¹¸Æ"þâ£b(a`’àbcÑ ‚΃–Ig–b4ÿøbgye• #Pâôñ%`,à J€w<Ó~L‘"G‹!ÃQ!Žt1 ÎðCsž Èç¨Ð½'“ô‘2,'?©ˆ_’"ã"**1 Ïÿ‚@Q@Ð<¿½Š€øxC‚/dY˜€ØÍ°r fa€Df3g˜IŽ¿‰ŠÎ‹ŠÊ¸þ@p€°‡¤Uˆ*!0ÞBNnp0Ú¹J€F ÃcŠ%Z"À À3ç\i„wÏ,rAqÁAåCn;áp§èh¾‘£Â‡Qùìò"#'äc@€† +~8’Ê–hˆÈ¿¨€0 (÷Ù [ó1›oá„"EÞr f`Dfy³ÎHäT]ÜLVT\v+?åÀ ` h§pˆ¦[؉UT‚€ÁÂn µr•‚7M¸¨´—ç˜#»Áb†(MôgHNs„ahDr¡„n;áâž&—±r€G‚ÿg‘"''fˆÎðp!ËôÒ%Lþ ÀŒp¯½’±æy¶þ„"QÍàq<€Là ä„eEÅÄÅeE\)‰=°((ðñi²L‰*N³"y$A3C¨D`BˆöBF8‚0ò_cŒÏ\^ ؃˸ͻ¹ŠÉ&T1™ïùB!qQ7¢;è€À†ƒÅïñ"z„#€  ÞÏÑ  Á!ÀQìI&‘eŒšyæ’ùæßì0Â`‹3Àq<Íà äŒÊ‹‹‰ŽÊG] +HxŸSï\Ži&D™'YRy$ €Àp€r¼É|’i“x˜@`‡ÄIÉuŽe{þ"ðÀÀv‡þ]¦îæ+(™P†G¯æv‡?D h<ò|ÜABÛhB†ÀA üÅÝæDB $~ÆDDÄLLVLd\TDùæßï &‹3Àr m†yŒÈM4‘‘±Q˜ãöh,[ï"î$‘QHÄ"-sAÁV ²-·‘Q‘QÂ@ °ṳ́ Nq|H„ ‚¸`%À§³Íia=ýxܾ ˆu E‡,ç )3ç + à‘„ÇÏÞ0„å +Bp@£< ïÞ„!BŒ! B0”! À#ó1æ÷›6ȳÌr m†yŒÈM29âI,Ñ0`pR`%9ÿòbÂP„-Žc@| ›ì'ÂPÒ (”Õýȳo"¢#2"2Œ €`€·îDY.äZÛy™‘œ „€x .b⢖"iz!£¾ëᜰB(s–p…ˆ€æÁpëó¦y¾Ýå +RPœ' ,ÄÄDÄDLDtLtD|aŒÌy½æf !‘g˜p ³ÐžÌÍàfGü‘&ž"aÃðB‡ ×ÉRA$Ö <˜Ñ ‘Ÿ1Á0CÚaóÃ$$[î""#2¢säi€ ð5ÿHìdmüTvEó + 0…€€|ÄÄÅŽi‘HƒA_ÇŒ†…#ŽrÎá@¸6·Xcš…÷ÙšÅ'[Æ €8 X /ob"¢j&+2/—ûf3cÌÌy †ØÌr = ìÌÞ@&ù"M<ˆA3Ÿ„ÁÂõòcÀ…$ÊY:¤3 `<žôà 0%T¡|xQ# ïä’DM21 B B€8甑ّ7qQYá…Ç€'ÔLlXæ™4ˆÐ¯$ È¡ LJÉq  KØC+×sqŠB-?1ƒ 0Š:É4ºY‘$B#ºÀ³±æÇ™˜mŒÀwcªª*º…MÈ€€! CvJ§Q1ÄÆw#À…EN +ˆŒ¨ +à5ˆyáÁ$J‡.ì²I2#IÊáqN¯e$DvD|VDB*ø†û™]Ù""±X‹ûˆ˜Ì0<àÀƒ@ñÿãš2s‚c‡dB:û!1ƒ`PÀ,zb"¢j"323 ý€æ6‰†D2" 3€{ÝUEWP©¹!ü©§’Iy€†À8å–cA”hH,$à Ãà ÀŽóŽ!‚$‚)#Žàid’Ddg?ØD—•ÖaÉ2Hñ’H@`#X§ +@0 ÁÀçå„!nzŸç8Jà  "à:>ƒ +Ÿnð„Å)ŠfÎÂ&6¨‚ˆ¶tZpà +(°`Ì!Â2„!JR¥¡ÛÆ †"a¢Ù¡# 3c|ÝÔâŠê"o”B`Éw@AÀ,!XR’@XOãà*~4”'xbS”#:Ή'±"$0HÅò229Ë™×q—qÙXC/ÛÀÄ‚KòΔÓriªi*A@Ð@ € €šôÊÿ„!ÈO DcÂÈ@ˆËOhAÀàFûÎ0![–„g)æs @€QP˜7‡Œ3Ù£€x ã 7„",Ã2DÄÆD]ÅEEDGÀ,ÐµÄÆ3%€€‚ÅÄ7ù‡ ³í{{p(¦ÔPD&æmÂ!DgZâ.#²"³2þc"8@°h¿,áEŠr 'šjwàðXØ`mùÖó…!ÈL`ˆÆØB""ZhÀƒ€|Dóî0!(yD®®ã:ΔE ƒxcØÃ<9˜8s c=‡¶ÆòDÅDDÄEDDDbˆ‚à4Z㣠 +a^»ˆ”p@ —¶ÝÄDI>L€€úÉÖi‘'ža)ü‘’ùü±¢@`89g$`P‚_ºÚ3x08Ø|M¹Â¥!UDBmºŠQÁC8¡¼°²‚ÁÂφDÑ„o¸R•†$#3à ‰ÑCfáHH€‹1¼‚$; á">ÄpÃm˜`á0Ì@AdŠMÎQÇ$Z Àtœ Ãõ1Á\0IñÁ@x3@ˆ?<4B͆la¼Ç˜l;y˜pÊ*¹Â…aˆ7s© ƒ`m³6‡6Ž$ˆ"sÔIf’p)òS¨lÜ! f7„ 16Џ¡L“QLtDlà †`BA&@(T/«ŽH´8wàF¥Ž8â‚#Ž ‚ÌÞ ÀÉ~xh…› ØÃy0Øvó0p\¥r„B@ Ì›åAæ  ‰ç¿ É""0¬Jíq€À ŸD0°²Â!ŒòÀ!DǪAm¾UA0Ü@„ jwr«…R„BfȬÁãJp@ &BëÎ0„#B0„"|F„0þl,Á†80xÃ=‡˜p\¥r„@+À)ЪQ„ 6ªUuQJE„! +j•Ü1¨^p„ ¿! p\ Ÿ†3Ðï 1ìa +&â•H "67Ê¢™¸€B>wr«…Wn"úÌÆXiÿu|FÃþ`Ä¥ˆª †ÁN)UÁßærÝJ¥"Y0Ä(6Æb©D@Á¾)[ª¢”F‚X"‚h Ž *‚Xä¢JxÍÿx‚AH+5Œaã40„{z+Š'H Dcåd¦â1 q]gši$–"I:!AÜLBp ·I†:â$PÝ4¿0|6ógŽK,Ó"B€!À(u–Y¦–H~ @Àr²É4“JŒ™'x`@`!ŽÀqERˆ ƒ7Å+uTR¢Â0”% +N”+N! ¤aFßÚ p +€DÇ8ªr‘P>wub¸ ‚c‹œ¬ŠTÙbnW³Í4’K~€€ Pqý4` ÀàuöIb#$'¡›óÃo6xä²Í2$ 8 +e–i¥’€r,#Bp”%´-HÎó€àX˜ß ÂÃ~ù""ã#¢bb1Æ_Úÿ€ð° |Ú%7À‚PÊc9!¬€ à +æžY'‰YfŒ8Ÿù,ÒI4ÒÂKð 8SAIáà3ÙÛPEpI%RGpG¡â3¿fx»¢RŠ@@Áºº‘"LC»” r,#Bp”%”%IRÓ @ €€&| . øã’x‘¥–t0‘üIâ p +?§ù?Xb4óÄÖd0 1,O…ƒÀ‰ˆ‹Œˆ‰‰ŽŠNuʪR¸¤ð ` 3ÀDÏ‚à8@1 ®Ì8R%C—$HÑ!Ã8#1°;ög‹¸ˆWVA3n®¡„È_ÌLR +p,!B0”!„%JRP¢€À€`ÄÂ#xfz#?6dE¾¡Jî)Nä†0Ç ?ˆhW²¢Ïyâ @/Ϧ` €È}yÆ„¡(N„¡F…lÛøvnÁ<Ñ"PV€˜#€ð å»qâP¡œ¸°$@ƒ80á„   ƒÞÙøì‘HþËo$–X‚ €9Iîp„-ÇCßp,!B0”!„%HRP§@&.øDo ÀðDgæÌ„$AàfÞyŒ@@QÄŸ¢4W²CK<“Ä‘@@ð,X@€ϹˆŠŠ‹‹Š‰‰ŽŒ ³oáÛahÏ4H”ƒ€ˆàÖ#€G)×…tåÉ(¡Á‡!€€€.#ÀïlüvH„$e‰7’K4A €9Iîp„-¡¯€o’I4“O$ÒĈ€€€€qÃä$ˆ#½ŒÀ„"0aÜE\å +wp€`ñTqJuq£gDEE‡½€€BÁ£Ûs•”x„‹=›ÓI4“P° €`˜{o–Ê£¾yà†$Š cˆ0!ˆ¢Æ„'ÆgŠ©¦ûŠ+•H" € @ »¸¼F–oóÌy°á@ ˆ§*‘( ×W9B !0î"(ç(S»„ Á˜ª:•UÄ ÙÑ €„Àc  €cç)\©ä§"Aƒü!DìØcÉijJ +° +°Wùÿi)Þð„a +zCB ‹œ[ž*¬…O¸¢¹A‚ gþt" 'n óóg˜ˆ’&**18ÀÄýÄÄdÜEDâPÎ(ŠôJu(‚ ƒbmº•TÈAÃc¢¦â †û36ÀØC „""„4{ÏxI•Á†Yš´ÜÿÅgF3žˆÂÁŒxDÇÂÃ-'8B¤§B„!(Zˆ€ò€t “ÎÂ#æ`n óóg¸‰aJ„ X(d.üáR‘œá(FQÅQ¾‰N¥@A`Ì""<üBDp„1>öfm™„ €0ycr«©UÕ+*+‘y“{s÷ІÆ xˆáÞ< ¢cá0€M$uÁYtÁÁA5‹€av„¨k™ƒo ÍŒ!Áï4!ˆÍ0IPE¡Ð †€„»Ë0E$PGEøÃÆ@<Bˆ!±™¶`d@fa±ÿlÃ0ÙŒ`d F À8y,ýbM,²D–Y‰••ÅCÀ0€xðŠ#?yA›pžD¹±áÀ‰"D8ðàÀ"XR â â+=ç„øX0o ÍŒ†4!ˆÍ0IPE¡° „€„;Ë0M$ÐOpEøÃÆ„<…7˜lÑÌÃc"ª«¹E(®9Ê@@€ AaeÜL]ÌdTLLDdLLQ"³¢î¢¢c"nâ#™Ð€` +`žDgï! °n<‰tcÃDHqáÆ"H°¬€p” +`”$ÿžGá`Ào 3c…€ÈL0üÒP„' +pXA@ áßÂ…9èwó„¡üÌxB3Ù´<à @€€#¶fU:R”R¹MÄŠD +°yëø˜˜ˆÈˆ˜˜ˆÈ¨¸ÁÌ„B¼I Ìòl†1³àBh€Î`ZÎp…- ÂÜ$BEÊÞ0•(’A—÷p›3co 3?ó f…ቀˆ°0Er€cqˆ`ú•Js©@B`c"(6W)]o$–0@‡yc$åè@Â8êXÌ0Ç·áä8aÙŠ‹‹‰ˆÄDØFBaDgàÀ„…aÛxÀo<öðÃÁ³d=†0Þ<^lžiš‰€^à˜ø "ÿ9p`A +`@(`A¡€7ÄJ]JV& ß~\‹›®(@A@cwq€B`€3¸ & uÝÔŠ•¼‘Qˆ€ +€€÷ÜþÔLD\Lf"6Â2„"‹? Bˆ3ÛÆn <Ù¿Â";ÂfÇá˜ðÆMX$4FÀ€!ÑÇ ÁAAÁ$ŠD ŒªWUW(ƒ…Œ  Á0⪔îâ‚1÷H „ÃP€ &n•‘ŽvHè„ u€°,»»ž‹ˆ‹ŒŒŽ‹±UOnRª ‚†è&ÛØn <Ù¿À  ;ÂfÇùøc%†p ð8°.D÷8Â0„% „# +BDŠ`pž`y«Ø¨¸è˜ˆˆˆ˜¨ÁÈšr à8È’I4_¦‰ ~öÃÀ°Â'ÇP‚cn”ˆ±Xæ 7ÀçóæžIâDš~7D‰{Í4’D @B +lØØoÍì?ˆ#¼!扰ö36Ã2(€€"Àƒ;º”¥U)I<ÏÀ~ä7ÇGPApAÐC0HHÈÈ¡€€xýŒËŠˆ‰¸ŠŠˆVéYqQ‚²@Á +îäBœ›¸¡!ƒT)Ä@@D0c9È(êå+¸~xÑ#%ï4’M€ÀCÎð8`b ÃoÍì?!…¼!扰ö36Ã2 BŠ ‹o001ŒÉâNH +¤OÖr-xp!Àp!À40 ÀˆHȈP`À <Ÿ±™qQ7QQŠÝ+%T@ † È€€„  +îä\Alw@ L mL>`#y ÌÛœ(¤[rª” €€` ƒ†" o~fóLl†ÏfÛa¸CŠq¨ÝWq@‚ + mÄ£74¸žwW3Û‡ P!@‹ 0#@…$ˆŒ„ Àxƒ_±Q1Q11Q¢o%P§d1œPA&¼rM4²Æ&å–0€`N)×ÉC36fÈG¢oaöŒÃØ€„D*(D7Po~fó@Àl†ÏfÛa¸CŠtJ(ÝWq@‚ƒÜHñ($à“¸0?¿Ó‡ P!@‹ 0#@…#’H‚ à8WY¢EšYd(nh•JqA1ñT&mI¦–Y‰ºË@pâžÿ0flÀÍMì!‡0öBC€ˆÃ†B#p Çùï0„ d6Û@ÄvÃ28d#æz!¿„@DÂh(H:€E¸ @¬†¸àŠ ‚ `‚`’ ŠE¢ "ÆUTÕÊá„À |"&ÚÄGܧ!\¢¹ÄT:„€€ÆÍ•™Â9  1Þ„ høüÃÀ͇0ÚÀp Çùï8Md6Û@ÄvÃG „|Ì0D7䈜‘Œ +€+À$›w(åEqESjáG€B`á6Ô9]H6{áÇ€ˆ Q9&š@avÀÀ ãòË,“ @Ñ<7ï3"0æB0p{ Ù£™çÆöBùàqg9E7Er‚ªP vÕÕ\¥QP£º•Å‚` Š6`ùƒ1žf1†bæÙ†ð†-°–„¡J(  äàôTÆ×Ìᕈ=‡›<Ì|Ø0Àn 7°Íš9žy od&ŽÀâÎ9O4’yY ÀbÏÚp‰„::&ý™áÇ,Y&–$ €Ö4H½€#í˜Ï3Ã1ólÃ1€Cm„ð À…DÍ„Á°ò!á.ø þ±¼ØpàAEì³0ðpp0”!ÂP„# +BP„%E YÐÀ"^ðœ1Œ3` \ No newline at end of file diff --git a/astropy/io/fits/tiled_compression/tests/test_fitsio.py b/astropy/io/fits/tiled_compression/tests/test_fitsio.py new file mode 100644 index 00000000000..8485a7128e1 --- /dev/null +++ b/astropy/io/fits/tiled_compression/tests/test_fitsio.py @@ -0,0 +1,208 @@ +""" +This test file uses the https://github.com/esheldon/fitsio package to verify +our compression and decompression routines against the implementation in +cfitsio. + +*Note*: The fitsio library is GPL licensed, therefore it could be interpreted + that so is this test file. Given that this test file isn't imported anywhere + else in the code this shouldn't cause us any issues. Please bear this in mind + when editing this file. +""" +import os + +import numpy as np +import pytest + +from astropy.io import fits + +from .conftest import _expand, fitsio_param_to_astropy_param + +# This is so that tox can force this file to be run, and not be silently +# skipped on CI, but in all other test runs it's skipped if fitsio isn't present. +if "ASTROPY_ALWAYS_TEST_FITSIO" in os.environ: + import fitsio +else: + fitsio = pytest.importorskip("fitsio") + + +@pytest.fixture( + scope="module", + params=_expand( + [((10,),), ((5,), (1,), (3,))], + [((12, 12),), ((1, 12), (4, 5), (6, 6), None)], + [((15, 15),), ((1, 15), (5, 1), (5, 5))], + [ + ((15, 15, 15),), + ((5, 5, 1), (5, 7, 1), (1, 5, 4), (1, 1, 15), (15, 1, 5)), + ], + # Test the situation where the tile shape is passed larger than the + # array shape + [ + ( + (4, 4, 5), + (5, 5, 5), + ), + ( + (5, 5, 1), + None, + ), + ], + # Test shapes which caused errors + # This one we can't test here as it causes segfaults in cfitsio + # It is tested in test_roundtrip_high_D though. + # [ + # ((3, 4, 5),), + # ((1, 2, 3),), + # ], + # >3D Data are not currently supported by cfitsio + ), + ids=lambda x: f"shape: {x[0]} tile_dims: {x[1]}", +) +def array_shapes_tile_dims(request, compression_type): + shape, tile_dim = request.param + # H_COMPRESS needs >=2D data and always 2D tiles + if compression_type == "HCOMPRESS_1" and ( + len(shape) < 2 or np.count_nonzero(np.array(tile_dim) != 1) != 2 + ): + pytest.xfail("HCOMPRESS requires 2D tiles.") + return shape, tile_dim + + +@pytest.fixture(scope="module") +def tile_dims(array_shapes_tile_dims): + return array_shapes_tile_dims[1] + + +@pytest.fixture(scope="module") +def data_shape(array_shapes_tile_dims): + return array_shapes_tile_dims[0] + + +@pytest.fixture(scope="module") +def base_original_data(data_shape, dtype, numpy_rng, compression_type): + random = numpy_rng.uniform(high=255, size=data_shape) + # Set first value to be exactly zero as zero values require special treatment + # for SUBTRACTIVE_DITHER_2 + random.ravel()[0] = 0.0 + # There seems to be a bug with the fitsio library where HCOMPRESS doesn't + # work with int16 random data, so use a bit for structured test data. + if compression_type.startswith("HCOMPRESS") and "i2" in dtype or "u1" in dtype: + random = np.arange(np.product(data_shape)).reshape(data_shape) + return random.astype(dtype) + + +@pytest.fixture(scope="module") +def fitsio_compressed_file_path( + tmp_path_factory, + comp_param_dtype, + base_original_data, + data_shape, # For debuging + tile_dims, +): + compression_type, param, dtype = comp_param_dtype + + if base_original_data.ndim > 2 and "u1" in dtype: + pytest.xfail("These don't work") + + if compression_type == "PLIO_1" and "f" in dtype: + # fitsio fails with a compression error + pytest.xfail("fitsio fails to write these") + + if ( + compression_type == "HCOMPRESS_1" + and "f" in dtype + and param.get("qmethod", None) == 2 + ): + # fitsio writes these files with very large/incorrect zzero values, whereas + # qmethod == 1 works (and the two methods should be identical except for the + # treatment of zeros) + pytest.xfail("fitsio writes these files with very large/incorrect zzero values") + + tmp_path = tmp_path_factory.mktemp("fitsio") + original_data = base_original_data.astype(dtype) + + filename = tmp_path / f"{compression_type}_{dtype}.fits" + fits = fitsio.FITS(filename, "rw") + fits.write(original_data, compress=compression_type, tile_dims=tile_dims, **param) + + return filename + + +@pytest.fixture(scope="module") +def astropy_compressed_file_path( + comp_param_dtype, + tmp_path_factory, + base_original_data, + data_shape, # For debuging + tile_dims, +): + compression_type, param, dtype = comp_param_dtype + original_data = base_original_data.astype(dtype) + + tmp_path = tmp_path_factory.mktemp("astropy") + filename = tmp_path / f"{compression_type}_{dtype}.fits" + + param = fitsio_param_to_astropy_param(param) + hdu = fits.CompImageHDU( + data=original_data, + compression_type=compression_type, + # TODO: why does this require a list?? + tile_size=list(tile_dims) if tile_dims is not None else tile_dims, + **param, + ) + hdu.writeto(filename) + + return filename + + +def test_decompress( + fitsio_compressed_file_path, + comp_param_dtype, +): + + compression_type, param, dtype = comp_param_dtype + + with fits.open(fitsio_compressed_file_path) as hdul: + data = hdul[1].data + + assert hdul[1]._header["ZCMPTYPE"].replace("ONE", "1") == compression_type + assert hdul[1].data.dtype.kind == np.dtype(dtype).kind + assert hdul[1].data.dtype.itemsize == np.dtype(dtype).itemsize + # assert hdul[1].data.dtype.byteorder == np.dtype(dtype).byteorder + + # The data might not always match the original data exactly in the case of + # lossy compression so instead of comparing the array read by astropy to the + # original data, we compare it to the data read in by fitsio (as those + # should match) + + fts = fitsio.FITS(fitsio_compressed_file_path) + data2 = fts[1].read() + np.testing.assert_allclose(data, data2) + + # The first value should be exactly equal to zero when using SUBTRACTIVE_DITHER_2 + if param.get("qmethod", None) == 2: + assert data.ravel()[0] == 0.0 + + +def test_compress( + astropy_compressed_file_path, + compression_type, + dtype, +): + + fts = fitsio.FITS(astropy_compressed_file_path, "r") + header = fts[1].read_header() + data = fts[1].read() + + assert header["ZCMPTYPE"] == compression_type + assert data.dtype.kind == np.dtype(dtype).kind + assert data.dtype.itemsize == np.dtype(dtype).itemsize + # assert data.dtype.byteorder == np.dtype(dtype).byteorder + + # The data might not always match the original data exactly in the case of + # lossy compression so instead of comparing the array read by fitsio to the + # original data, we compare it to the data read in by astropy (as those + # should match) + + with fits.open(astropy_compressed_file_path) as hdul: + np.testing.assert_allclose(data, hdul[1].data) diff --git a/astropy/io/fits/tiled_compression/tests/test_tiled_compression.py b/astropy/io/fits/tiled_compression/tests/test_tiled_compression.py new file mode 100644 index 00000000000..482c9c188d0 --- /dev/null +++ b/astropy/io/fits/tiled_compression/tests/test_tiled_compression.py @@ -0,0 +1,106 @@ +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_equal + +from astropy.io import fits + +from .conftest import fitsio_param_to_astropy_param + + +@pytest.fixture +def canonical_data_base_path(): + return Path(__file__).parent / "data" + + +@pytest.fixture( + params=(Path(__file__).parent / "data").glob("m13_*.fits"), ids=lambda x: x.name +) +def canonical_int_hdus(request): + """ + This fixture provides 4 files downloaded from https://fits.gsfc.nasa.gov/registry/tilecompression.html + + Which are used as canonical tests of data not compressed by Astropy. + """ + with fits.open(request.param) as hdul: + yield hdul[1] + + +@pytest.fixture +def original_int_hdu(canonical_data_base_path): + with fits.open(canonical_data_base_path / "m13.fits") as hdul: + yield hdul[0] + + +# pytest-openfiles does not correctly check for open files when the files are +# opened in a fixture, so we skip the check here. +# https://github.com/astropy/pytest-openfiles/issues/32 +@pytest.mark.openfiles_ignore +def test_canonical_data(original_int_hdu, canonical_int_hdus): + assert_allclose(original_int_hdu.data, canonical_int_hdus.data) + + +def test_zblank_support(canonical_data_base_path, tmp_path): + + # This uses a test 12x12 image which contains a NaN value in the [1, 1] + # pixel - it was compressed using fpack which automatically added a ZBLANK + # header keyword + + reference = np.arange(144).reshape((12, 12)).astype(float) + reference[1, 1] = np.nan + + with fits.open(canonical_data_base_path / "compressed_with_nan.fits") as hdul: + assert_equal(np.round(hdul[1].data), reference) + + # Now generate a file ourselves and check that the output has the ZBLANK + # keyword set automatically + + hdu = fits.CompImageHDU(data=reference, compression_type="RICE_1", tile_size=(6, 6)) + + hdu.writeto(tmp_path / "test_zblank.fits") + + with fits.open(tmp_path / "test_zblank.fits") as hdul: + assert "ZBLANK" in hdul[1].header + assert_equal(np.round(hdul[1].data), reference) + + +@pytest.mark.parametrize( + ("shape", "tile_dim"), + ( + ([5, 5, 5], [5, 5, 5]), + ([5, 5, 5], [5, 5, 1]), # something for HCOMPRESS + ([10, 15, 20], [5, 5, 5]), + ([10, 5, 12], [5, 5, 5]), + # TODO: There's a stupid bit of code in CompImageHDU which stops this working. + # ([2, 3, 4, 5], [1, 1, 2, 3]), + ([2, 3, 4, 5], [5, 5, 1, 1]), + ), +) +def test_roundtrip_high_D( + numpy_rng, compression_type, compression_param, tmp_path, dtype, shape, tile_dim +): + if compression_type == "HCOMPRESS_1" and ( + len(shape) < 2 or np.count_nonzero(np.array(tile_dim) != 1) != 2 + ): + pytest.xfail("HCOMPRESS requires 2D tiles.") + random = numpy_rng.uniform(high=255, size=shape) + # Set first value to be exactly zero as zero values require special treatment + # for SUBTRACTIVE_DITHER_2 + random.ravel()[0] = 0.0 + original_data = random.astype(dtype) + + filename = tmp_path / f"{compression_type}_{dtype}.fits" + + param = fitsio_param_to_astropy_param(compression_param) + hdu = fits.CompImageHDU( + data=original_data, + compression_type=compression_type, + tile_size=tile_dim, + **param, + ) + hdu.writeto(filename) + + with fits.open(filename) as hdul: + a = hdul[1].data + # np.testing.assert_allclose(original_data, hdul[1].data, atol=1) diff --git a/astropy/io/fits/tiled_compression/tiled_compression.py b/astropy/io/fits/tiled_compression/tiled_compression.py new file mode 100644 index 00000000000..6936cf23ab4 --- /dev/null +++ b/astropy/io/fits/tiled_compression/tiled_compression.py @@ -0,0 +1,552 @@ +""" +This module contains low level helper functions for compressing and +decompressing buffer for the Tiled Table Compression algorithms as specified in +the FITS 4 standard. +""" +import numpy as np + +from astropy.io.fits.hdu.base import BITPIX2DTYPE + +from ._codecs import PLIO1, Gzip1, Gzip2, HCompress1, Rice1 +from ._quantization import DITHER_METHODS, QuantizationFailedException, Quantize + +ALGORITHMS = { + "GZIP_1": Gzip1, + "GZIP_2": Gzip2, + "RICE_1": Rice1, + "RICE_ONE": Rice1, + "PLIO_1": PLIO1, + "HCOMPRESS_1": HCompress1, +} + +DEFAULT_ZBLANK = -2147483648 + + +def decompress_tile(buf, *, algorithm: str, **kwargs): + """ + Decompress the buffer of a tile using the given compression algorithm. + + Parameters + ---------- + buf + The compressed buffer to be decompressed. + algorithm + A supported decompression algorithm. + kwargs + Any parameters for the given compression algorithm + """ + return ALGORITHMS[algorithm](**kwargs).decode(buf) + + +def compress_tile(buf, *, algorithm: str, **kwargs): + """ + Compress the buffer of a tile using the given compression algorithm. + + Parameters + ---------- + buf + The decompressed buffer to be compressed. + algorithm + A supported compression algorithm. + kwargs + Any parameters for the given compression algorithm + """ + return ALGORITHMS[algorithm](**kwargs).encode(buf) + + +def _tile_shape(header): + return tuple(header[f"ZTILE{idx}"] for idx in range(header["ZNAXIS"], 0, -1)) + + +def _data_shape(header): + return tuple(header[f"ZNAXIS{idx}"] for idx in range(header["ZNAXIS"], 0, -1)) + + +def _header_to_settings(header, actual_tile_shape): + + tile_shape = _tile_shape(header) + + settings = {} + + if header["ZCMPTYPE"] == "GZIP_2": + settings["itemsize"] = abs(header["ZBITPIX"]) // 8 + elif header["ZCMPTYPE"] == "PLIO_1": + # We have to calculate the tilesize from the shape of the tile not the + # header, so that it's correct for edge tiles etc. + settings["tilesize"] = np.product(actual_tile_shape) + elif header["ZCMPTYPE"] in ("RICE_1", "RICE_ONE"): + settings["blocksize"] = _get_compression_setting(header, "BLOCKSIZE", 32) + settings["bytepix"] = _get_compression_setting(header, "BYTEPIX", 4) + settings["tilesize"] = np.product(actual_tile_shape) + elif header["ZCMPTYPE"] == "HCOMPRESS_1": + settings["bytepix"] = 4 + settings["scale"] = int(_get_compression_setting(header, "SCALE", 0)) + settings["smooth"] = _get_compression_setting(header, "SMOOTH", 0) + # HCOMPRESS requires 2D tiles, so to find the shape of the 2D tile we + # need to ignore all length 1 tile dimensions + # Also cfitsio expects the tile shape in C order + shape_2d = tuple(nd for nd in actual_tile_shape if nd != 1) + if len(shape_2d) != 2: + raise ValueError(f"HCOMPRESS expects two dimensional tiles, got {shape_2d}") + settings["nx"] = shape_2d[0] + settings["ny"] = shape_2d[1] + + return settings + + +def _buffer_to_array( + tile_buffer, header, tile_shape=None, algorithm=None, lossless=False +): + """ + Convert a buffer to an array using the header. + + This is a helper function which takes a raw buffer (as output by .decode) + and using the FITS header translates it into a numpy array with the correct + dtype, endianess and shape. + """ + + if tile_shape is None: + tile_shape = _tile_shape(header) + + if algorithm is None: + algorithm = header["ZCMPTYPE"] + + if algorithm.startswith("GZIP"): + # This algorithm is taken from fitsio + # https://github.com/astropy/astropy/blob/a8cb1668d4835562b89c0d0b3448ac72ca44db63/cextern/cfitsio/lib/imcompress.c#L6345-L6388 + tilelen = np.product(tile_shape) + tilebytesize = len(tile_buffer) + if tilebytesize == tilelen * 2: + dtype = ">i2" + elif tilebytesize == tilelen * 4: + if header["ZBITPIX"] < 0 and lossless: + dtype = ">f4" + else: + dtype = ">i4" + elif tilebytesize == tilelen * 8: + if header["ZBITPIX"] < 0 and lossless: + dtype = ">f8" + else: + dtype = ">i8" + else: + # Just return the raw bytes + dtype = ">u1" + tile_data = np.asarray(tile_buffer).view(dtype).reshape(tile_shape) + else: + # For RICE_1 compression the tiles that are on the edge can end up + # being padded, so we truncate excess values + if algorithm in ("RICE_1", "RICE_ONE", "PLIO_1"): + tile_buffer = tile_buffer[: np.product(tile_shape)] + + if tile_buffer.format == "b": + # NOTE: this feels like a Numpy bug - need to investigate + tile_data = np.asarray(tile_buffer, dtype=np.uint8).reshape(tile_shape) + else: + tile_data = np.asarray(tile_buffer).reshape(tile_shape) + + return tile_data + + +def _check_compressed_header(header): + + # Check for overflows which might cause issues when calling C code + + for kw in ["ZNAXIS", "ZVAL1", "ZVAL2", "ZBLANK", "BLANK"]: + if kw in header: + if header[kw] > 0 and np.intc(header[kw]) < 0: + raise OverflowError() + + for i in range(1, header["ZNAXIS"] + 1): + for kw_name in ["ZNAXIS", "ZTILE"]: + kw = f"{kw_name}{i}" + if kw in header: + if header[kw] > 0 and np.int32(header[kw]) < 0: + raise OverflowError() + + for i in range(1, header["NAXIS"] + 1): + kw = f"NAXIS{i}" + if kw in header: + if header[kw] > 0 and np.int64(header[kw]) < 0: + raise OverflowError() + + for kw in ["TNULL1", "PCOUNT", "THEAP"]: + if kw in header: + if header[kw] > 0 and np.int64(header[kw]) < 0: + raise OverflowError() + + for kw in ["ZVAL3"]: + if kw in header: + if np.isinf(np.float32(header[kw])): + raise OverflowError() + + # Validate data types + + for kw in ["ZSCALE", "ZZERO", "TZERO1", "TSCAL1"]: + if kw in header: + if not np.isreal(header[kw]): + raise TypeError(f"{kw} should be floating-point") + + for kw in ["TTYPE1", "TFORM1", "ZCMPTYPE", "ZNAME1", "ZQUANTIZ"]: + if kw in header: + if not isinstance(header[kw], str): + raise TypeError(f"{kw} should be a string") + + for kw in ["ZDITHER0"]: + if kw in header: + if not np.isreal(header[kw]) or not float(header[kw]).is_integer(): + raise TypeError(f"{kw} should be an integer") + + if "TFORM1" in header: + for valid in ["1PB", "1PI", "1PJ", "1QB", "1QI", "1QJ"]: + if header["TFORM1"].startswith(valid): + break + else: + raise RuntimeError(f"Invalid TFORM1: {header['TFORM1']}") + + # Check values + + for kw in ["TFIELDS", "PCOUNT"] + [ + f"NAXIS{idx + 1}" for idx in range(header["NAXIS"]) + ]: + if kw in header: + if header[kw] < 0: + raise ValueError(f"{kw} should not be negative.") + + for kw in ["ZNAXIS", "TFIELDS"]: + if kw in header: + if header[kw] < 0 or header[kw] > 999: + raise ValueError(f"{kw} should be in the range 0 to 999") + + if header["ZBITPIX"] not in [8, 16, 32, 64, -32, -64]: + raise ValueError(f"Invalid value for BITPIX: {header['ZBITPIX']}") + + if header["ZCMPTYPE"] not in ALGORITHMS: + raise ValueError(f"Unrecognized compression type: {header['ZCMPTYPE']}") + + # Check that certain keys are present + + header["ZNAXIS"] + header["ZBITPIX"] + + +def _get_compression_setting(header, name, default): + for i in range(1, 1000): + if f"ZNAME{i}" not in header: + break + if header[f"ZNAME{i}"].lower() == name.lower(): + return header[f"ZVAL{i}"] + return default + + +def decompress_hdu(hdu): + """ + Decompress the data in a `~astropy.io.fits.CompImageHDU`. + + Parameters + ---------- + hdu : `astropy.io.fits.CompImageHDU` + Input HDU to decompress the data for. + + Returns + ------- + + data : `numpy.ndarray` + The decompressed data array. + """ + + _check_compressed_header(hdu._header) + + tile_shape = _tile_shape(hdu._header) + data_shape = _data_shape(hdu._header) + + data = np.zeros(data_shape, dtype=BITPIX2DTYPE[hdu._header["ZBITPIX"]]) + + quantize = "ZSCALE" in hdu.compressed_data.dtype.names + + if len(hdu.compressed_data) == 0: + return None + + istart = np.zeros(data.ndim, dtype=int) + for irow, row in enumerate(hdu.compressed_data): + + # In the following, we don't need to special case tiles near the edge + # as Numpy will automatically ignore parts of the slices that are out + # of bounds. + tile_slices = tuple( + [ + slice(istart[idx], istart[idx] + tile_shape[idx]) + for idx in range(len(istart)) + ] + ) + + # For tiles near the edge, the tile shape from the header might not be + # correct so we have to pass the shape manually. + actual_tile_shape = data[tile_slices].shape + settings = _header_to_settings(hdu._header, actual_tile_shape) + + cdata = row["COMPRESSED_DATA"] + + if irow == 0 and hdu._header["ZCMPTYPE"] == "GZIP_2": + # Decompress with GZIP_1 just to find the total number of + # elements in the uncompressed data + tile_data = np.asarray( + decompress_tile(row["COMPRESSED_DATA"], algorithm="GZIP_1") + ) + settings["itemsize"] = tile_data.size // int(np.product(actual_tile_shape)) + + gzip_fallback = len(cdata) == 0 + + if gzip_fallback: + tile_buffer = decompress_tile( + row["GZIP_COMPRESSED_DATA"], algorithm="GZIP_1" + ) + tile_data = _buffer_to_array( + tile_buffer, + hdu._header, + tile_shape=actual_tile_shape, + algorithm="GZIP_1", + lossless=True, + ) + else: + tile_buffer = decompress_tile( + cdata, algorithm=hdu._header["ZCMPTYPE"], **settings + ) + tile_data = _buffer_to_array( + tile_buffer, + hdu._header, + tile_shape=actual_tile_shape, + lossless=not quantize, + ) + + if "ZBLANK" in row.array.names: + zblank = row["ZBLANK"] + elif "ZBLANK" in hdu._header: + zblank = hdu._header["ZBLANK"] + else: + zblank = None + + if zblank is not None: + blank_mask = tile_data == zblank + + if quantize: + dither_method = DITHER_METHODS[hdu._header.get("ZQUANTIZ", "NO_DITHER")] + dither_seed = hdu._header.get("ZDITHER0", 0) + q = Quantize( + irow + dither_seed, dither_method, None, hdu._header["ZBITPIX"] + ) + tile_data = np.asarray( + q.decode_quantized(tile_data, row["ZSCALE"], row["ZZERO"]) + ).reshape(actual_tile_shape) + + if zblank is not None: + if not tile_data.flags.writeable: + tile_data = tile_data.copy() + tile_data[blank_mask] = np.nan + + data[tile_slices] = tile_data + istart[-1] += tile_shape[-1] + for idx in range(data.ndim - 1, 0, -1): + if istart[idx] >= data_shape[idx]: + istart[idx] = 0 + istart[idx - 1] += tile_shape[idx - 1] + + return data + + +def compress_hdu(hdu): + """ + Compress the data in a `~astropy.io.fits.CompImageHDU`. + + The input HDU is expected to have a uncompressed numpy array as it's + ``.data`` attribute. + + Parameters + ---------- + hdu : `astropy.io.fits.CompImageHDU` + Input HDU to compress the data for. + + Returns + ------- + nbytes : `int` + The number of bytes for the data once compressed. + cbytes : `numpy.ndarray` + The compressed bytes as a unit8 numpy array. + """ + + if not isinstance(hdu.data, np.ndarray): + raise TypeError("CompImageHDU.data must be a numpy.ndarray") + + _check_compressed_header(hdu._header) + + # TODO: This implementation is memory inefficient as it generates all the + # compressed bytes before forming them into the heap, leading to 2x the + # potential memory usage. Directly storing the compressed bytes into an + # expanding heap would fix this. + + tile_shape = _tile_shape(hdu._header) + data_shape = _data_shape(hdu._header) + + compressed_bytes = [] + gzip_fallback = [] + scales = [] + zeros = [] + zblank = None + + irow = 0 + istart = np.zeros(len(data_shape), dtype=int) + + noisebit = _get_compression_setting(hdu._header, "noisebit", 0) + + while True: + + if hdu.data is None: + break + + # In the following, we don't need to special case tiles near the edge + # as Numpy will automatically ignore parts of the slices that are out + # of bounds. + slices = tuple( + [ + slice(istart[idx], istart[idx] + tile_shape[idx]) + for idx in range(len(istart)) + ] + ) + + data = hdu.data[slices] + + settings = _header_to_settings(hdu._header, data.shape) + + quantize = "ZSCALE" in hdu.columns.dtype.names + + if data.dtype.kind == "f" and quantize: + noisebit = _get_compression_setting(hdu._header, "noisebit", 0) + dither_method = DITHER_METHODS[hdu._header.get("ZQUANTIZ", "NO_DITHER")] + dither_seed = hdu._header.get("ZDITHER0", 0) + q = Quantize( + irow + dither_seed, dither_method, noisebit, hdu._header["ZBITPIX"] + ) + original_shape = data.shape + + # If there are any NaN values in the data, we should reset them to + # a value that will not affect the quantization (an already existing + # data value in the array) and we can then reset this after quantization + # to ZBLANK and set the appropriate header keyword + nan_mask = np.isnan(data) + any_nan = np.any(nan_mask) + if any_nan: + # Note that we need to copy here to avoid modifying the input array. + data = data.copy() + if np.all(nan_mask): + data[nan_mask] = 0 + else: + data[nan_mask] = np.nanmin(data) + + try: + data, scale, zero = q.encode_quantized(data) + except QuantizationFailedException: + + if any_nan: + # reset NaN values since we will losslessly compress. + data[nan_mask] = np.nan + + scales.append(0) + zeros.append(0) + gzip_fallback.append(True) + + else: + data = np.asarray(data).reshape(original_shape) + + if any_nan: + if not data.flags.writeable: + data = data.copy() + # For now, we just use the default ZBLANK value and assume + # this is the same for all tiles. We could generalize this + # to allow different ZBLANK values (for example if the data + # includes this value by chance) and to allow different values + # per tile, which is allowed by the FITS standard. + data[nan_mask] = DEFAULT_ZBLANK + zblank = DEFAULT_ZBLANK + + scales.append(scale) + zeros.append(zero) + gzip_fallback.append(False) + + else: + scales.append(0) + zeros.append(0) + gzip_fallback.append(False) + + # The original compress_hdu assumed the data was in native endian, so we + # change this here: + if hdu._header["ZCMPTYPE"].startswith("GZIP") or gzip_fallback[-1]: + # This is apparently needed so that our heap data agrees with + # the C implementation!? + data = data.astype(data.dtype.newbyteorder(">")) + else: + if not data.dtype.isnative: + data = data.astype(data.dtype.newbyteorder("=")) + + if gzip_fallback[-1]: + cbytes = compress_tile(data, algorithm="GZIP_1") + else: + cbytes = compress_tile(data, algorithm=hdu._header["ZCMPTYPE"], **settings) + compressed_bytes.append(cbytes) + + istart[-1] += tile_shape[-1] + + for idx in range(data.ndim - 1, 0, -1): + if istart[idx] >= data_shape[idx]: + istart[idx] = 0 + istart[idx - 1] += tile_shape[idx - 1] + + if istart[0] >= data_shape[0]: + break + + irow += 1 + + if zblank is not None: + hdu._header["ZBLANK"] = zblank + + table = np.zeros(len(compressed_bytes), dtype=hdu.columns.dtype.newbyteorder(">")) + + if "ZSCALE" in table.dtype.names: + table["ZSCALE"] = np.array(scales) + table["ZZERO"] = np.array(zeros) + + for irow, cbytes in enumerate(compressed_bytes): + table["COMPRESSED_DATA"][irow, 0] = len(cbytes) + + table["COMPRESSED_DATA"][:1, 1] = 0 + table["COMPRESSED_DATA"][1:, 1] = np.cumsum(table["COMPRESSED_DATA"][:-1, 0]) + + for irow in range(len(compressed_bytes)): + if gzip_fallback[irow]: + table["GZIP_COMPRESSED_DATA"][irow] = table["COMPRESSED_DATA"][irow] + table["COMPRESSED_DATA"][irow] = 0 + + # For PLIO_1, the size of each heap element is a factor of two lower than + # the real size - not clear if this is deliberate or bug somewhere. + if hdu._header["ZCMPTYPE"] == "PLIO_1": + table["COMPRESSED_DATA"][:, 0] //= 2 + + # For PLIO_1, it looks like the compressed data is byteswapped + if hdu._header["ZCMPTYPE"] == "PLIO_1": + for irow in range(len(compressed_bytes)): + if not gzip_fallback[irow]: + compressed_bytes[irow] = ( + np.frombuffer(compressed_bytes[irow], dtype="i2") + .tobytes() + ) + + compressed_bytes = b"".join(compressed_bytes) + + table_bytes = table.tobytes() + + if len(table_bytes) != hdu._theap: + raise Exception( + f"Unexpected compressed table size (expected {hdu._theap}, got {len(table_bytes)})" + ) + heap = table.tobytes() + compressed_bytes + + return len(compressed_bytes), np.frombuffer(heap, dtype=np.uint8) diff --git a/cextern/cfitsio/lib/imcompress.c b/cextern/cfitsio/lib/imcompress.c index ce3ab0fb92e..58f6fbe17f9 100644 --- a/cextern/cfitsio/lib/imcompress.c +++ b/cextern/cfitsio/lib/imcompress.c @@ -21,157 +21,6 @@ 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 */ @@ -182,7 +31,7 @@ int fits_init_randoms(void) { double temp, seed; FFLOCK; - + if (fits_rand_value) { FFUNLOCK; return(0); /* array is already initialized */ @@ -196,14 +45,14 @@ int fits_init_randoms(void) { 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: + 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 - */ + Volume 31 , Issue 10 (October 1988) Pages: 1192 - 1201 + */ /* initialize the random numbers */ seed = 1; @@ -215,10 +64,10 @@ int fits_init_randoms(void) { FFUNLOCK; - /* - IMPORTANT NOTE: the 10000th seed value must have the value 1043618065 if the + /* + 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); @@ -226,9730 +75,487 @@ int fits_init_randoms(void) { 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 */ -{ +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 */ /* - 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. + Unquantize byte values into the scaled floating point values */ - int ii; +{ + long ii; + int nextrand, iseed; - if (ndim < 0 || ndim > MAX_COMPRESS_DIM) - { - *status = BAD_DIMEN; - ffpmsg("illegal number of tile dimensions (fits_set_tile_dim)"); - return(*status); - } + if (!fits_rand_value) + if (fits_init_randoms()) return(MEMORY_ALLOCATION); - for (ii = 0; ii < ndim; ii++) - { - (fptr->Fptr)->request_tilesize[ii] = dims[ii]; - } + /* initialize the index to the next random number in the list */ + iseed = (int) ((row - 1) % N_RANDOM); + nextrand = (int) (fits_rand_value[iseed] * 500); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_set_quantize_level(fitsfile *fptr, /* I - FITS file pointer */ - float qlevel, /* floating point quantization level */ - int *status) /* IO - error status */ -{ + if (nullcheck == 0) /* no null checking required */ + { + for (ii = 0; ii < ntodo; ii++) + { /* - 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 (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) + output[ii] = 0.0; + else */ - 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 { + output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); - (fptr->Fptr)->request_quantize_level = qlevel; + nextrand++; + if (nextrand == N_RANDOM) { + iseed++; + if (iseed == N_RANDOM) iseed = 0; + nextrand = (int) (fits_rand_value[iseed] * 500); + } + } } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_set_quantize_method(fitsfile *fptr, /* I - FITS file pointer */ - int method, /* quantization method */ - int *status) /* IO - error status */ -{ + 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 + { /* - 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 (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); + } - 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; + nextrand++; + if (nextrand == N_RANDOM) { + iseed++; + if (iseed == N_RANDOM) iseed = 0; + nextrand = (int) (fits_rand_value[iseed] * 500); + } + } } return(*status); } /*--------------------------------------------------------------------------*/ -int fits_set_quantize_dither(fitsfile *fptr, /* I - FITS file pointer */ - int dither, /* dither type */ - int *status) /* IO - error status */ -{ +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 */ /* - 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. + Unquantize short integer values into the scaled floating point values */ - - 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 + long ii; + int nextrand, iseed; -*/ - /* 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 */ -{ + 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++) + { /* - The name of this routine has changed. This is kept just for - backwards compatibility with any software that calls the old name + 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); - 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 */ -{ + 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 + { /* - ******************************************************************** - ******************************************************************** - 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. + if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) + output[ii] = 0.0; + else */ - float qlevel; + output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); + } - if (noisebits < 1 || noisebits > 16) - { - *status = DATA_COMPRESSION_ERR; - ffpmsg("illegal number of noise bits (fits_set_noise_bits)"); - return(*status); + nextrand++; + if (nextrand == N_RANDOM) { + iseed++; + if (iseed == N_RANDOM) iseed = 0; + nextrand = (int) (fits_rand_value[iseed] * 500); + } + } } - 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 */ - +int unquantize_i4r4(long row, /* tile number = row number in table */ + 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 */ + 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 */ + int 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 */ /* - 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. + Unquantize int integer values into the scaled floating point values */ { - 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); + long ii; + int nextrand, iseed; - if (naxis < 1 || naxis > MAX_COMPRESS_DIM) - { - ffpmsg("Image cannot be compressed: NAXIS out of range"); - return(*status = BAD_NAXIS); - } + if (fits_rand_value == 0) + if (fits_init_randoms()) return(MEMORY_ALLOCATION); - /* 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 */ + /* 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 ((outfptr->Fptr)->curhdu == 0) /* have to create dummy primary array */ + if (nullcheck == 0) /* no null checking required */ { - 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 (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); - 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"); + nextrand++; + if (nextrand == N_RANDOM) { + iseed++; + if (iseed == N_RANDOM) iseed = 0; + nextrand = (int) (fits_rand_value[iseed] * 500); + } } - - 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) + else /* must check for null values */ { - 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 */ + for (ii = 0; ii < ntodo; ii++) { - 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) + if (input[ii] == tnull) { - /* 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; + *anynull = 1; + if (nullcheck == 1) + output[ii] = 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); + nullarray[ii] = 1; + } 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 */ + { + 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); + } -{ - 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--; + nextrand++; + if (nextrand == N_RANDOM) { + iseed++; + if (iseed == N_RANDOM) iseed = 0; + nextrand = (int) (fits_rand_value[iseed] * 500); + } + } } - - 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. +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 */ - { - 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; - } - } - } + long ii; + int nextrand, iseed; - free(longlongarray); - return(*status); -} -/*--------------------------------------------------------------------------*/ -static int fits_short_to_int_inplace(short *shortarray, long length, int shift, int *status) + if (!fits_rand_value) + if (fits_init_randoms()) return(MEMORY_ALLOCATION); -/* 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. + /* initialize the index to the next random number in the list */ + iseed = (int) ((row - 1) % N_RANDOM); + nextrand = (int) (fits_rand_value[iseed] * 500); -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. + 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); -{ - 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); + 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); + } - 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; - } - } + nextrand++; + if (nextrand == N_RANDOM) { + iseed++; + if (iseed == N_RANDOM) iseed = 0; + nextrand = (int) (fits_rand_value[iseed] * 500); + } + } } - 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 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 */ - { - 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; - } - } - } + long ii; + int nextrand, iseed; - free(intarray); - return(*status); -} -/*--------------------------------------------------------------------------*/ -static int fits_ubyte_to_int_inplace(unsigned char *ubytearray, long length, - int *status) + if (!fits_rand_value) + if (fits_init_randoms()) return(MEMORY_ALLOCATION); -/* 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. + /* initialize the index to the next random number in the list */ + iseed = (int) ((row - 1) % N_RANDOM); + nextrand = (int) (fits_rand_value[iseed] * 500); -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. + 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); -{ - 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); + 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); + } - 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; - } - } + nextrand++; + if (nextrand == N_RANDOM) { + iseed++; + if (iseed == N_RANDOM) iseed = 0; + nextrand = (int) (fits_rand_value[iseed] * 500); + } + } } - 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. -*/ - +int unquantize_i4r8(long row, /* tile number = row number in table */ + 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 */ + 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 */ + int 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 */ /* -!!!!!!!!!!!!!!!!! -NOTE THAT THIS IS A SPECIALIZED ROUTINE THAT ADDS AN OFFSET OF 128 TO THE ARRAY VALUES -!!!!!!!!!!!!!!!!! + Unquantize int integer values into the scaled floating point values */ - { - int *intarray, *aliasarray; - long ii, ntodo, firstelem, nmax = 10000; - - if (*status > 0) - return(*status); + long ii; + int nextrand, iseed; - 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); - } + if (fits_rand_value == 0) + if (fits_init_randoms()) return(MEMORY_ALLOCATION); - aliasarray = (int *) sbytearray; /* alias pointer to the input array */ + /* initialize the index to the next random number in the list */ + iseed = (int) ((row - 1) % N_RANDOM); + nextrand = (int) (fits_rand_value[iseed] * 500); - while (ntodo > 0) { - - /* do datatype conversion into temp array */ - for (ii = 0; ii < ntodo; ii++) { - intarray[ii] = sbytearray[ii + firstelem] + 128; /* !! Note the offset !! */ - } + 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); - /* 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; - } - } + 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); + } - 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 - */ + nextrand++; + if (nextrand == N_RANDOM) { + iseed++; + if (iseed == N_RANDOM) iseed = 0; + nextrand = (int) (fits_rand_value[iseed] * 500); + } + } + } - 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); + return(*status); } diff --git a/docs/io/fits/api/tiled_compression.rst b/docs/io/fits/api/tiled_compression.rst new file mode 100644 index 00000000000..16c92cc2114 --- /dev/null +++ b/docs/io/fits/api/tiled_compression.rst @@ -0,0 +1,5 @@ +***************** +Tiled Compression +***************** + +.. automodapi:: astropy.io.fits.tiled_compression diff --git a/docs/io/fits/index.rst b/docs/io/fits/index.rst index f18029c52cf..a72cd932cf6 100644 --- a/docs/io/fits/index.rst +++ b/docs/io/fits/index.rst @@ -1047,6 +1047,7 @@ Reference/API api/images.rst api/diff.rst api/verification.rst + api/tiled_compression.rst .. rubric:: Footnotes diff --git a/tox.ini b/tox.ini index 824d2a43fe3..7ab75802614 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = - py{38,39,310,311,dev}-test{,-image,-recdeps,-alldeps,-oldestdeps,-devdeps,-devinfra,-predeps,-numpy120,-numpy121,-numpy122,-numpy123,-mpl311}{,-cov}{,-clocale} + py{38,39,310,311,dev}-test{,-image,-recdeps,-alldeps,-oldestdeps,-devdeps,-devinfra,-predeps,-numpy120,-numpy121,-numpy122,-numpy123,-mpl311}{,-cov}{,-clocale}{,-fitsio} build_docs linkcheck codestyle @@ -31,6 +31,7 @@ setenv = clocale: LC_CTYPE = C.ascii clocale: LC_ALL = C devdeps: PIP_EXTRA_INDEX_URL = https://pypi.anaconda.org/scipy-wheels-nightly/simple + fitsio: ASTROPY_ALWAYS_TESTS_FITSIO = "true" # Run the tests in a temporary directory to make sure that we don't import # astropy from the source tree @@ -73,6 +74,9 @@ deps = image: scipy image: pytest-mpl + # Some FITS tests use fitsio as a comparison + fitsio: fitsio + # The oldestdeps factor is intended to be used to install the oldest versions of all # dependencies that have a minimum version. oldestdeps: numpy==1.20.*