Repository: kbarbary/sep Branch: main Commit: 93b3ac52e0f6 Files: 61 Total size: 935.7 KB Directory structure: gitextract_54cmwk4y/ ├── .clang-format ├── .github/ │ └── workflows/ │ ├── build-wheels-upload-pypi.yml │ └── python-package-tox.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yaml ├── AUTHORS.md ├── CHANGES.md ├── CMakeLists.txt ├── FindSEP.cmake ├── MANIFEST.in ├── Makefile ├── README.md ├── bench.py ├── codemeta.json ├── ctest/ │ ├── compare.py │ └── test_image.c ├── data/ │ ├── README.md │ ├── back.fits │ ├── default.conv │ ├── default.nnw │ ├── default.param │ ├── default.sex │ ├── image.cat │ ├── image.fits │ └── rms.fits ├── docs/ │ ├── Makefile │ ├── apertures.rst │ ├── changelogs/ │ │ ├── changelog.rst │ │ ├── changes_to_c_api.rst │ │ ├── new_changes.rst │ │ └── original_changes.md │ ├── conf.py │ ├── filter.rst │ ├── index.rst │ ├── reference.rst │ ├── rtd-pip-requirements │ └── tutorial.ipynb ├── licenses/ │ ├── BSD_LICENSE.txt │ ├── LGPL_LICENSE.txt │ └── MIT_LICENSE.txt ├── paper/ │ ├── paper.bib │ └── paper.md ├── pyproject.toml ├── sep.pyx ├── setup.py ├── src/ │ ├── analyse.c │ ├── aperture.c │ ├── aperture.i │ ├── background.c │ ├── convolve.c │ ├── deblend.c │ ├── extract.c │ ├── extract.h │ ├── lutz.c │ ├── overlap.h │ ├── sep.h │ ├── sepcore.h │ └── util.c ├── test.py └── tox.ini ================================================ FILE CONTENTS ================================================ ================================================ FILE: .clang-format ================================================ # SPDX-License-Identifier: MIT # # Copyright (c) 2023 Intercreate, Inc. # Author: J.P. Hutchins # # Python(black)-inspired .clang-format for C repositories # # Includes Zephyr and Arm macro compatibility --- BasedOnStyle: Google AlignAfterOpenBracket: BlockIndent AlignTrailingComments: false AllowAllArgumentsOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: Never AllowShortCaseLabelsOnASingleLine: false AllowShortEnumsOnASingleLine: false AllowShortFunctionsOnASingleLine: Empty AllowShortIfStatementsOnASingleLine: Never AllowShortLoopsOnASingleLine: false AttributeMacros: - __aligned - __deprecated - __packed - __printf_like - __syscall - __syscall_always_inline - __subsystem BinPackArguments: false BinPackParameters: false BraceWrapping: AfterCaseLabel: false AfterClass: false AfterControlStatement: MultiLine AfterEnum: false AfterFunction: false AfterNamespace: false AfterObjCDeclaration: false AfterStruct: false AfterUnion: false AfterExternBlock: false BeforeCatch: false BeforeElse: false IndentBraces: false SplitEmptyFunction: false SplitEmptyRecord: false SplitEmptyNamespace: false BeforeLambdaBody: false BeforeWhile: false BitFieldColonSpacing: After BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Custom BreakStringLiterals: true ColumnLimit: 88 DerivePointerAlignment: false ForEachMacros: - 'FOR_EACH' - 'FOR_EACH_FIXED_ARG' - 'FOR_EACH_IDX' - 'FOR_EACH_IDX_FIXED_ARG' - 'FOR_EACH_NONEMPTY_TERM' - 'RB_FOR_EACH' - 'RB_FOR_EACH_CONTAINER' - 'SYS_DLIST_FOR_EACH_CONTAINER' - 'SYS_DLIST_FOR_EACH_CONTAINER_SAFE' - 'SYS_DLIST_FOR_EACH_NODE' - 'SYS_DLIST_FOR_EACH_NODE_SAFE' - 'SYS_SFLIST_FOR_EACH_CONTAINER' - 'SYS_SFLIST_FOR_EACH_CONTAINER_SAFE' - 'SYS_SFLIST_FOR_EACH_NODE' - 'SYS_SFLIST_FOR_EACH_NODE_SAFE' - 'SYS_SLIST_FOR_EACH_CONTAINER' - 'SYS_SLIST_FOR_EACH_CONTAINER_SAFE' - 'SYS_SLIST_FOR_EACH_NODE' - 'SYS_SLIST_FOR_EACH_NODE_SAFE' - '_WAIT_Q_FOR_EACH' - 'Z_FOR_EACH' - 'Z_FOR_EACH_ENGINE' - 'Z_FOR_EACH_EXEC' - 'Z_FOR_EACH_FIXED_ARG' - 'Z_FOR_EACH_FIXED_ARG_EXEC' - 'Z_FOR_EACH_IDX' - 'Z_FOR_EACH_IDX_EXEC' - 'Z_FOR_EACH_IDX_FIXED_ARG' - 'Z_FOR_EACH_IDX_FIXED_ARG_EXEC' - 'Z_GENLIST_FOR_EACH_CONTAINER' - 'Z_GENLIST_FOR_EACH_CONTAINER_SAFE' - 'Z_GENLIST_FOR_EACH_NODE' - 'Z_GENLIST_FOR_EACH_NODE_SAFE' - 'STRUCT_SECTION_FOREACH' - 'TYPE_SECTION_FOREACH' IncludeBlocks: Preserve IfMacros: - 'CHECKIF' IndentCaseBlocks: true IndentCaseLabels: false IndentWidth: 2 InsertBraces: true MaxEmptyLinesToKeep: 2 PointerAlignment: Middle SortIncludes: CaseSensitive SpaceBeforeParens: ControlStatementsExceptControlMacros UseTab: Never WhitespaceSensitiveMacros: - STRINGIFY - Z_STRINGIFY ================================================ FILE: .github/workflows/build-wheels-upload-pypi.yml ================================================ # GitHub action for building the distribution and wheels of the sep package # and uploading them to the PyPI package index. name: build-wheels-upload-pypi on: [push, workflow_dispatch] # push: # # Run this action on the trigger event when *any* tag is pushed # tags: # - '*' jobs: # This action is split into three jobs: # - Building the source distribution # - Building the wheels for the distribution # - Uploading the artifacts to PyPI package # The first and second job run in parallel. # The uploading jos needs to have the other two finished without error. # From now on, we run the tests before continuing with these jobs. run_tests: uses: ./.github/workflows/python-package-tox.yml build_sdist: needs: [run_tests] # First the source distribution is done on ubuntu. This is not related # to any operating system, so we could do it on the default os. runs-on: ubuntu-24.04 steps: - name: checkout uses: actions/checkout@v4 with: fetch-depth: 0 fetch-tags: true - name: install_python uses: actions/setup-python@v5 with: python-version: '3.12' # For the build, sep needs numpy and cython and we add twine and wheel # for better testing and checking. - name: Install dependencies run: python -m pip install setuptools twine numpy wheel cython build - name: Build sdist run: python -m build --sdist - name: Show files run: ls -lh dist shell: bash - name: Check metadata run: twine check dist/* - name: Upload sdist uses: actions/upload-artifact@v4 with: name: dist path: dist/*.tar.gz build_wheels: needs: [run_tests] # Second the wheels are build for different OS and python versions. This is # done with the help of the `cibuildwheel` package. # # The wheels are built for Windows, Linux and MacOS and the python versions # 3.9 - 3.13. # # The three operating system could be done in parallel. name: Build wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} env: CIBW_ARCHS_MACOS: "x86_64 universal2 arm64" strategy: max-parallel: 4 matrix: python-version: ["3.12"] os: [windows-latest, macos-latest, ubuntu-24.04, ubuntu-24.04-arm] steps: - uses: actions/checkout@v4 - name: checkout uses: actions/checkout@v4 with: fetch-depth: 0 fetch-tags: true - name: Setup Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install cibuildwheel run: python -m pip install cibuildwheel - name: Build wheels run: python -m cibuildwheel --output-dir wheelhouse env: CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-*" CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014 CIBW_MANYLINUX_I686_IMAGE: manylinux2014 CIBW_BUILD_VERBOSITY: 1 CIBW_SKIP: '*-musllinux_*' CIBW_ARCHS_LINUX: "auto" - name: Show files run: ls -lh wheelhouse shell: bash - name: Upload wheels uses: actions/upload-artifact@v4 with: name: dist-${{ matrix.os }} path: ./wheelhouse/*.whl upload_to_pypi: # Finally we collect all out data from the artifacts and put them back to # dist directory for upload. The final step waits for the other jobs to be # finished and starts only if the trigger event of the action was a push # of a tag starting with as version separation. All other jobs run # without heading runs-on: [ubuntu-latest] needs: [build_wheels, build_sdist] environment: name: pypi url: https://pypi.org/p/sep permissions: id-token: write # upload to PyPI on every tag starting with 'v' if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v') steps: - uses: actions/setup-python@v5 - uses: actions/download-artifact@v4 with: pattern: dist* merge-multiple: true path: dist - name: upload_to_pypi uses: pypa/gh-action-pypi-publish@release/v1 # with: # repository-url: https://test.pypi.org/legacy/ ================================================ FILE: .github/workflows/python-package-tox.yml ================================================ # This workflow will install tox and use it to run tests. # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions name: CI on: [push, workflow_call, workflow_dispatch, pull_request] jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: python: ["3.9", "3.10", "3.11", "3.12", "3.13"] os: [windows-latest, macos-latest, ubuntu-latest] steps: - uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install Tox and any other packages run: | python -m pip install --upgrade pip python -m pip install tox tox-gh-actions - name: Run Tox # Run tox using the version of Python in `PATH`, append platform run: tox env: PLATFORM: ${{ matrix.os }} ================================================ FILE: .gitignore ================================================ # emacs *~ # -------------------------------------------- # C *.o *.os *.so *.so.* *.dylib *.dylib.* *.a ctest/test_image # generated by tests data/sep.cat data/sepback.fits # scons .sconsign.dblite # tarball sep-*.tar.gz # ------------------------------------------- # Python __pycache__ docs/_build docs/api build/ MANIFEST *.egg-info # pytest .pytest_cache .cache # generated C file sep.c # PyCharm .idea .project # Eclipse .pydevproject # Jupyter .ipynb_checkpoints # tox .tox # version *_version.py ================================================ FILE: .pre-commit-config.yaml ================================================ exclude: "^data/" repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - id: check-added-large-files - repo: https://github.com/pycqa/isort rev: 5.13.2 hooks: - id: isort name: isort (python) - repo: https://github.com/psf/black rev: 24.10.0 hooks: - id: black args: [--preview] - repo: https://github.com/numpy/numpydoc rev: v1.8.0 hooks: - id: numpydoc-validation - repo: https://github.com/sphinx-contrib/sphinx-lint rev: v1.0.0 hooks: - id: sphinx-lint args: [--enable=all, --disable=default-role, --max-line-length=75, -v] files: ^docs\/|^.*\.(rst$|md$) - repo: https://github.com/pre-commit/mirrors-clang-format rev: v19.1.4 hooks: - id: clang-format types_or: [c++, c, cuda] ================================================ FILE: .readthedocs.yaml ================================================ # Read the Docs configuration file for Sphinx projects # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Set the OS, Python version and other tools you might need build: os: ubuntu-22.04 tools: python: "3.12" # You can also specify other tool versions: # nodejs: "20" # rust: "1.70" # golang: "1.20" # Build documentation in the "docs/" directory with Sphinx sphinx: configuration: docs/conf.py # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs # builder: "dirhtml" # Fail on all warnings to avoid broken references # fail_on_warning: true # Optionally build your docs in additional formats such as PDF and ePub # formats: # - pdf # - epub # Optional but recommended, declare the Python requirements required # to build your documentation # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html python: install: # - requirements: docs/requirements.txt - method: pip path: . extra_requirements: - docs ================================================ FILE: AUTHORS.md ================================================ * Emmanuel Bertin (bertin@iap.fr) : original SExtractor code * Kyle Barbary (@kbarbary) : Conversion of SExtractor code to library * Kyle Boone (@kboone) : Bugfix, matched filter * Thomas Robitaille (@astrofrog) : Exact aperture overlap code * Matt Craig (@mwcraig) : Windows & OS X support * Curtis McCully (@cmccully): Parameter uncertainties * Evert Rol (@evertrol): setup.py fixes * Joe Lyman (@lyalpha): Make deblending limit settable * Michael Wuertenberger (@mworion): PyPI wheels * Ingvar Stepanyan (@rreverser): Build system, public API and thread safety fixes. * Gabe Brammer (@gbrammer): Fix memory addressing with large arrays. * Peter Watson (@PJ-Watson): Add extraction from existing segmentation map. ================================================ FILE: CHANGES.md ================================================ v1.3.7 (8 November 2024) ======================== * Test against Python 3.13. * Update the Makefile to support Semantic Versioning from git tags. * Update the C libraries to allow for passing the version as a compiler flag. * Update `setup.py` to pass the SCM version to the Cython compiler. * Include C tests in the Tox suite (for linux and macos only). * Document any and all changes to the C API since forking. * Restructure changelog documentation. v1.3.6 (7 October 2024) ======================= * Fix wrong int type in Windows ([#2](https://github.com/PJ-Watson/sep-pjw/issues/2), thanks to @acenko for pointing this out). * Update tests to run on multiple operating systems. v1.3.5 (12 June 2024) ===================== * Small fixes and updates to ensure compatibility with NumPy 2.0. v1.3.4 (21 February 2024) ======================== * Include .clang-format as a pre-commit hook, to ensure consistent code style (improved readability, easier maintenance). * Fixed `make test` to account for the changes in [v1.3.0](https://github.com/PJ-Watson/sep-pjw/releases/tag/v1.3.0). * All header files include the correct definitions. v1.3.3 (7 February 2024) ======================== * Add changelog to documentation. * Add tests for re-running with seg map. * Fix array boundary bugs when re-running with seg map. * Fix bug with precision loss when calculating threshold. * Improve error handling when object pixels exceed pix stack. v1.3.2 (5 February 2024) ======================== * Move documentation to new location, fix package names and imports. * Add wheels for Python 3.11/3.12. * Fix C compilation errors on windows (VLAs). * Publish updated version to PyPI under new name. v1.3.1 (31 January 2024) ======================== * Formatting changes (follow [black](https://github.com/psf/black) formatting style). * Fix `bench.py` and `test.py`, removing deprecated functions. * Move metadata into `pyproject.toml`. * Add pre-commit hooks for code and docstring validation. * Change to dynamic versioning (git tag/commit based). v1.3.0 (1 December 2023) ======================== * The `segmentation_map` argument of `sep.extract()` will now accept either an array or boolean. If an existing segmentation map is passed, the object detection stage is skipped, and sources will be individually analysed according to the provided map. This change is backwards-compatible with respect to the Python module. Please note that as no deblending is performed, the calculated thresholds (and any dependent parameters) may not be the same as originally derived. * Use 64-bit integers throughout, to fix memory addressing with large arrays ([#122](https://github.com/kbarbary/sep/issues/122 "Original issue"), inspired by [Gabe Brammer's fork](https://github.com/gbrammer/sep) with additional fixes). ================================================ FILE: CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.6) project(sep C) LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules/") include(GNUInstallDirs) set(SOURCES ${CMAKE_SOURCE_DIR}/src/analyse.c ${CMAKE_SOURCE_DIR}/src/convolve.c ${CMAKE_SOURCE_DIR}/src/deblend.c ${CMAKE_SOURCE_DIR}/src/extract.c ${CMAKE_SOURCE_DIR}/src/lutz.c ${CMAKE_SOURCE_DIR}/src/aperture.c ${CMAKE_SOURCE_DIR}/src/background.c ${CMAKE_SOURCE_DIR}/src/util.c ) include_directories(${CMAKE_INCLUDE_PATH} ${CMAKE_SOURCE_DIR}/src ${CFITSIO_INCLUDE_DIR}) link_directories(${CMAKE_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/src) add_library(sep SHARED ${SOURCES}) set_target_properties(sep PROPERTIES OUTPUT_NAME sep) set_target_properties(sep PROPERTIES VERSION 0.6.0 SOVERSION 0) set_target_properties(sep PROPERTIES C_VISIBILITY_PRESET hidden) if (MSVC) add_definitions(-D_USE_MATH_DEFINES) else () add_compile_options(-Wcast-qual) target_link_libraries(sep m) endif() install(TARGETS sep LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(FILES ${CMAKE_SOURCE_DIR}/src/sep.h DESTINATION include) ================================================ FILE: FindSEP.cmake ================================================ # - Try to find SEP # Once done this will define # # SEP_FOUND - system has SEP # SEP_INCLUDE_DIR - the SEP include directory # SEP_LIBRARIES - Link these to use SEP # SEP_VERSION_STRING - Human readable version number of sep # SEP_VERSION_MAJOR - Major version number of sep # SEP_VERSION_MINOR - Minor version number of sep # Copyright (c) 2017, Ilia Platone, # Based on FindLibfacile by Carsten Niehaus, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. if (SEP_LIBRARIES) # in cache already set(SEP_FOUND TRUE) message(STATUS "Found SEP: ${SEP_LIBRARIES}") else (SEP_LIBRARIES) find_library(SEP_LIBRARIES NAMES sep PATHS ${_obLinkDir} ${GNUWIN32_DIR}/lib /usr/local/lib ) if(SEP_LIBRARIES) set(SEP_FOUND TRUE) else (SEP_LIBRARIES) set(SEP_FOUND FALSE) endif(SEP_LIBRARIES) if (SEP_FOUND) if (NOT SEP_FIND_QUIETLY) message(STATUS "Found SEP: ${SEP_LIBRARIES}") endif (NOT SEP_FIND_QUIETLY) else (SEP_FOUND) if (SEP_FIND_REQUIRED) message(FATAL_ERROR "SEP not found. Please install libsep-dev") endif (SEP_FIND_REQUIRED) endif (SEP_FOUND) mark_as_advanced(SEP_LIBRARIES) endif (SEP_LIBRARIES) ================================================ FILE: MANIFEST.in ================================================ include README.md include CHANGES.md include AUTHORS.md include licenses/* include pyproject.toml include src/*.[c,h,i] include sep.pyx exclude sep.c ================================================ FILE: Makefile ================================================ OS ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"') DESCRIBE := $(shell git describe --match "v*" --always --tags) DESCRIBE_PARTS := $(subst -, ,$(DESCRIBE)) VERSION_TAG := $(word 1,$(DESCRIBE_PARTS)) COMMITS_SINCE_TAG := $(word 2,$(DESCRIBE_PARTS)) BUILD_ID := $(word 3,$(DESCRIBE_PARTS)) VERSION := $(subst v,,$(VERSION_TAG)) VERSION_PARTS := $(subst ., ,$(VERSION)) MAJOR := $(word 1,$(VERSION_PARTS)) MINOR := $(word 2,$(VERSION_PARTS)) MICRO := $(word 3,$(VERSION_PARTS)) NEXT_MICRO := $(shell echo $$(($(MICRO)+1))) ifeq ($(strip $(COMMITS_SINCE_TAG)),) CURRENT_VERSION_MICRO := $(MAJOR).$(MINOR).$(MICRO) CURRENT_MICRO := $(MICRO) else CURRENT_VERSION_MICRO := $(MAJOR).$(MINOR).$(NEXT_MICRO) CURRENT_MICRO := $(NEXT_MICRO)-dev$(COMMITS_SINCE_TAG)$(if $(BUILD_ID),-${BUILD_ID},) endif ifeq ($(OS), darwin) SONAME = libsep.dylib SONAME_MAJOR = libsep.$(MAJOR).dylib SONAME_FULL = libsep.$(MAJOR).$(MINOR).$(CURRENT_MICRO).dylib SONAME_FLAG = -install_name LDPATHENV = DYLD_LIBRARY_PATH else ifeq ($(OS), linux) SONAME = libsep.so SONAME_MAJOR = libsep.so.$(MAJOR) SONAME_FULL = libsep.so.$(MAJOR).$(MINOR).$(CURRENT_MICRO) SONAME_FLAG = -soname LDPATHENV = LD_LIBRARY_PATH else $(error OS not yet supported) endif endif INSTALL ?= install DESTDIR = PREFIX ?= /usr/local LIBDIR = $(PREFIX)/lib INCLUDEDIR = $(PREFIX)/include CC?=gcc AR?=ar CPPFLAGS ?= LDFLAGS ?= CPPFLAGS += -Isrc CFLAGS += -Wall -Wextra -Wcast-qual -O3 -fvisibility=hidden # -Werror CFLAGS += -DSEP_VERSION_STRING=\"$(MAJOR).$(MINOR).$(CURRENT_MICRO)\" CFLAGS_LIB = $(CFLAGS) -fPIC LDFLAGS_LIB = $(LDFLAGS) -shared -Wl,$(SONAME_FLAG),$(SONAME_MAJOR) OBJS = src/analyse.o src/convolve.o src/deblend.o src/extract.o \ src/lutz.o src/aperture.o src/background.o src/util.o default: all src/analyse.o src/convolve.o src/deblend.o src/extract.o src/lutz.o: src/%.o: src/%.c src/extract.h src/sepcore.h src/sep.h $(CC) $(CPPFLAGS) $(CFLAGS_LIB) -c src/$*.c -o $@ src/aperture.o: src/aperture.c src/aperture.i src/overlap.h src/sepcore.h src/sep.h $(CC) $(CPPFLAGS) $(CFLAGS_LIB) -c src/aperture.c -o $@ src/background.o src/util.o: src/%.o: src/%.c src/sepcore.h src/sep.h $(CC) $(CPPFLAGS) $(CFLAGS_LIB) -c src/$*.c -o $@ src/$(SONAME_FULL) src/$(SONAME_MAJOR) src/$(SONAME) &: $(OBJS) $(CC) $(LDFLAGS_LIB) $^ -lm -o src/$(SONAME_FULL) ln -sf $(SONAME_FULL) src/$(SONAME_MAJOR) ln -sf $(SONAME_FULL) src/$(SONAME) src/libsep.a: $(OBJS) $(AR) rcs src/libsep.a $^ install: all $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) $(INSTALL) -m u=rw,g=r,o=r src/sep.h $(DESTDIR)$(INCLUDEDIR) $(INSTALL) -d $(DESTDIR)$(LIBDIR) $(INSTALL) -m u=rwx,g=rx,o=rx src/$(SONAME_FULL) $(DESTDIR)$(LIBDIR) ln -sf $(SONAME_FULL) $(DESTDIR)$(LIBDIR)/$(SONAME_MAJOR) ln -sf $(SONAME_FULL) $(DESTDIR)$(LIBDIR)/$(SONAME) $(INSTALL) -m u=rw,g=r,o=r src/libsep.a $(DESTDIR)$(LIBDIR) uninstall: rm $(DESTDIR)$(INCLUDEDIR)/sep.h rm $(DESTDIR)$(LIBDIR)/$(SONAME_FULL) rm $(DESTDIR)$(LIBDIR)/$(SONAME_MAJOR) rm $(DESTDIR)$(LIBDIR)/$(SONAME) rm $(DESTDIR)$(LIBDIR)/libsep.a test: ctest/test_image $(LDPATHENV)=src ctest/test_image data/image.fits data/sep.cat ctest/compare.py data/image.cat data/sep.cat ctest/test_image: ctest/test_image.c src/$(SONAME) $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Lsrc ctest/test_image.c -lm -lsep -o ctest/test_image clean: rm -f src/*.o src/*.a src/libsep.* ctest/test_image all: src/$(SONAME_FULL) src/libsep.a .PHONY: all test clean library install uninstall ================================================ FILE: README.md ================================================ SEP === Python and C library for Source Extraction and Photometry. [![PyPI](https://img.shields.io/pypi/v/sep?label=PyPI)](https://pypi.python.org/pypi/sep) [![PyPI - Downloads](https://img.shields.io/pypi/dm/sep?label=PyPI%20Downloads)](https://pypi.python.org/pypi/sep) [![Build Status](https://github.com/sep-developers/sep/workflows/CI/badge.svg)](https://github.com/sep-developers/sep/actions) [![Documentation Status](https://readthedocs.org/projects/sep/badge/?version=latest)](https://sep.readthedocs.io/en/latest/?badge=latest) [![JOSS](http://joss.theoj.org/papers/10.21105/joss.00058/status.svg)](http://dx.doi.org/10.21105/joss.00058) *"... [it's] an SEP: Somebody Else's Problem." "Oh, good. I can relax then."* SEP, SEP-PJW, and Package Names ------------------------------- `sep` was originally released by Kyle Barbary, at [kbarbary/sep](https://github.com/kbarbary/sep) (``sep<=1.2.1``). For a brief period, the package was maintained by Peter Watson, under the `sep-pjw` package name, at [PJ-Watson/sep-pjw](https://github.com/PJ-Watson/sep-pjw) and [PyPI/sep-pjw](https://pypi.org/project/sep-pjw/) (``1.3.0<=sep-pjw<=1.3.8``). Both of these repositories will be archived, and future development will take place at [sep-developers/sep]() (``sep>=1.4.0``). Note that there may be some incompatibilities between ``sep==1.2.1`` and ``sep==1.4.0`` when using the C-API directly (to fix an indexing bug arising with large arrays) - all changes are documented [here](https://sep-pjw.readthedocs.io/en/latest/changelogs/changes_to_c_api.html). About ----- [Source Extractor](http://www.astromatic.net/software/sextractor) (Bertin & Arnouts 1996) is a widely used command-line program for segmentation and analysis of astronomical images. It reads in FITS format files, performs a configurable series of tasks, including background estimation, source detection, deblending and a wide array of source measurements, and finally outputs a FITS format catalog file. While Source Extractor is highly useful, the fact that it can only be used as an executable can limit its applicability or lead to awkward workflows. There is often a desire to have programmatic access to perform one or more of the above tasks on in-memory images as part of a larger custom analysis. **SEP makes the core algorithms of Source Extractor available as a library of stand-alone functions and classes.** These operate directly on in-memory arrays (no FITS files or configuration files). The code is derived from the Source Extractor code base (written in C) and aims to produce results compatible with Source Extractor whenever possible. SEP consists of a C library with no dependencies outside the standard library, and a Python module that wraps the C library in a Pythonic API. The Python wrapper operates on NumPy arrays with NumPy as its only dependency. See below for language-specfic build and usage instructions. Python ------ **Documentation:** http://sep.readthedocs.io **Requirements:** - Python 3.9+ - numpy 1.23+ **Install release version:** SEP can be installed with [pip](https://pip.pypa.io): ``` python -m pip install sep ``` If you get an error about permissions, you are probably using your system Python. In this case, we recommend using [pip's "user install"](https://pip.pypa.io/en/latest/user_guide/#user-installs) option to install sep into your user directory: ``` python -m pip install --user sep ``` Do **not** install sep or other third-party Python packages using `sudo` unless you are fully aware of the risks. **Install development version:** Building the development version (from github) requires Cython. Build and install in the usual place: ``` python -m pip install --editable . ``` **Run tests:** Tests require the [pytest](http://pytest.org) Python package. To run the tests, execute `./test.py` in the top-level directory. Some tests require a FITS reader (either fitsio or astropy) and will be skipped if neither is present. C Library --------- _Note: The build process only works on Linux and OS X._ **CMake:** To build using CMake, enter these commands: ``` cd sep mkdir -p build cd build cmake -DCMAKE_INSTALL_PREFIX=/usr ../ ``` and follow next steps from the build folder **Build:** To build the C library from source: ``` make ``` **Run tests:** ``` make test ``` **Install** The static library and header can be installed with ``` make install make PREFIX=/path/to/prefix install ``` This will install the shared and static library in `/path/to/prefix/lib` and header file in `/path/to/prefix/include`. The default prefix is `/usr/local`. **API:** The C library API is documented in the header file [sep.h](src/sep.h). **Rust bindings:** Low-level Rust wrapper for the C library can be found at https://crates.io/crates/sep-sys Contributing ------------ - Report a bug or documentation issue: http://github.com/sep-developers/issues - Ask (or answer) a question: https://github.com/sep-developers/sep/discussions/categories/q-a Development of SEP takes place on GitHub at [sep-developers/sep](http://github.com/sep-developers/sep). Contributions of bug fixes, documentation improvements and minor feature additions are welcome via GitHub pull requests. For major features, it is best to discuss the change first via [GitHub Discussions](https://github.com/sep-developers/sep/discussions/). Citation -------- If you use SEP in a publication, please cite the following article in the Journal of Open Source Software: [![JOSS](http://joss.theoj.org/papers/10.21105/joss.00058/status.svg)](http://dx.doi.org/10.21105/joss.00058) Please also cite the original Source Extractor paper ([Bertin & Arnouts 1996](http://adsabs.harvard.edu/abs/1996A%26AS..117..393B)). The DOI for the sep v1.0.0 code release is: [![DOI](https://zenodo.org/badge/doi/10.5281/zenodo.159035.svg)](http://dx.doi.org/10.5281/zenodo.159035) License ------- The license for all parts of the code derived from Source Extractor is LGPLv3. The license for code derived from photutils (`src/overlap.h`) is BSD 3-clause. Finally, the license for the Python wrapper (`sep.pyx`) is MIT. The license for the library as a whole is therefore LGPLv3. The license for each file is explicitly stated at the top of the file and the full text of each license can be found in `licenses`. FAQ --- **Why isn't the C library part of Source Extractor?** Source Extractor is *not* designed as a library with an executable built on top of the library. In Source Extractor, background estimation, object detection and photometry are deeply integrated into the Source Extractor executable. Many changes to the code were necessary in order to put the functionality in stand-alone C functions. It's too much to ask of the Source Extractor developer to rewrite large parts of the core of the Source Extractor program with little gain for the executable. **What sort of changes?** - Source Extractor reads in only a small portion of each image at a time. This allows it to keep its memory footprint extremely low and to operate on images that are much larger than the system's physical memory. It also means that a FITS reader is deeply integrated into the code. SEP operates on images in memory, so all the FITS I/O machinery in Source Extractor is not used here. - Error handling: When it encounters a problem, Source Extractor immediately exits with an error message. This is fine for an executable, but a library function doesn't have that luxury. Instead it must ensure that allocated memory is freed and return an error code. - Options: Source Extractor has many options that affect its behavior. These are stored in a global structure used throughout the executable. In SEP, options for a particular function are passed as function parameters. - Array types: Source Extractor can operate on FITS images containing various types of data (float, double, int, etc). Internally, it does this by converting all data to `float` immediately when reading from disk. SEP does something similar, but in memory: SEP functions typically convert input arrays to float on the fly within each function, then perform all operations as floating point. **Is SEP as fast as Source Extractor?** It's fast. It should be similar to Source Extractor as a lot of the code is identical. Source Extractor has the advantage of doing all the operations (detection and analysis) simultaneously on each image section, which may confer CPU cache advantages, but this hasn't been tested at all. On the other hand, depending on your usage SEP might let you avoid writing files to disk, which is likely to be a bigger win. **What happens when Source Extractor is updated in the future?** SEP can be considered a fork of the Source Extractor code base: it's development will not track that of Source Extractor in any automated way. However, the algorithms implemented so far in SEP are stable in Source Extractor: the SEP code was forked from v2.18.11, yet it is tested against the results of v2.8.6. This indicates that the algorithms have not changed in Source Extractor over the last few years. **In the Python interface, why do I have to byte swap data when using astropy.io.fits?** This occurs because FITS files have big-endian [byte order](http://en.wikipedia.org/wiki/Endianness), whereas most widely used CPUs have little-endian byte order. In order for the CPU to operate on the data, it must be byte swapped at *some point.* Some FITS readers such as [fitsio](http://github.com/esheldon/fitsio) do the byte swap immediately when reading the data from disk to memory, returning numpy arrays in native (little-endian) byte order. However, astropy.io.fits does not (for reasons having to do with memory mapping). Most of the time you never notice this because when you do any numpy operations on such arrays, numpy uses an intermediate buffer to byte swap the array behind the scenes and returns the result as a native byte order array. Internally, SEP is not using numpy operations; it's just getting a pointer to the data in the array and passing it to C code. As the C code does not include functionality to do buffered byte swapping, the input array must already be in native byte order. It would be possible to add buffered byte swapping capability to the SEP code, but it would increase the code complexity. A simpler alternative would be to make a byte swapped copy of the entire input array, whenever necessary. However, this would significantly increase memory use, and would have to be done repeatedly in multiple SEP functions: `Background`, `extract`, `sum_circle`, etc. Each would make a copy of the entire data array. Given these considerations, it seemed best to just explicitly tell the user to do the byte swap operation themselves so they could just do it once, immediately after reading in the data. **I have more questions!** Open a discussion on the [GitHub Discussions page](https://github.com/sep-developers/sep/discussions/categories/q-a)! ================================================ FILE: bench.py ================================================ #!/usr/bin/env python """Benchmarking SEP against equivalent photutils functions.""" from __future__ import print_function import time from pathlib import Path import numpy as np import sep # try to import photutils for comparison timing try: import photutils HAVE_PHOTUTILS = True except ImportError: HAVE_PHOTUTILS = False # Try to import any FITS reader try: from fitsio import read as getdata HAVE_FITS = True NEED_BYTESWAP = False except ImportError: try: from astropy.io.fits import getdata HAVE_FITS = True NEED_BYTESWAP = True except ImportError: HAVE_FITS = False import argparse parser = argparse.ArgumentParser(description="SEP Benchmark script.") parser.add_argument( "-c", "--condensed", default=False, action="store_true", help="Only run a condensed subset of the benchmarks.", ) parser.add_argument( "-t", "--tiles", default=4, type=int, help=( "The maximum number of tiles for the image background benchmark, " "i.e. the image size will be `(t*256)^2`." ), ) parser.add_argument( "-a", "--apertures", default=1000, type=int, help=( "The number of apertures to use for benchmarking the aperture " "photometry, by default 1000." ), ) parser.add_argument( "-r", "--radii", default=[3, 5, 10, 20], type=float, nargs="+", help=( "The radii of the apertures to test. Ignored if the `--condensed` " "flag is passed, otherwise defaults to `3, 5, 10, 20`." ), ) parser.add_argument( "-n", "--nloop", default=50, type=int, help=("The number of loops to run for all tests, by default 50."), ) args = parser.parse_args() if HAVE_FITS: rawdata = getdata( Path(__file__).parent / "data" / "image.fits" ) # original is 256 x 256 if NEED_BYTESWAP: rawdata = rawdata.astype(rawdata.dtype.newbyteorder("=")) else: print("No FITS reader found, generating random data instead.") rawdata = np.random.random((256, 256)) data = np.tile(rawdata, (4, 4)) print("test image shape:", data.shape) print("test image dtype:", data.dtype) t0 = time.time() bkg = sep.Background(data) # estimate background t1 = time.time() print("measure background: {0:6.2f} ms".format((t1 - t0) * 1.0e3)) t0 = time.time() bkg.subfrom(data) # subtract it t1 = time.time() print("subtract background: {0:6.2f} ms".format((t1 - t0) * 1.0e3)) t0 = time.time() backarr = bkg.back(dtype=np.float64) # background t1 = time.time() print("background array: {0:6.2f} ms".format((t1 - t0) * 1.0e3)) t0 = time.time() rmsarr = bkg.rms() t1 = time.time() print("rms array: {0:6.2f} ms".format((t1 - t0) * 1.0e3)) t0 = time.time() objects = sep.extract(data, 1.5 * bkg.globalrms) t1 = time.time() print("extract: {0:6.2f} ms [{1:d} objects]".format((t1 - t0) * 1.0e3, len(objects))) # -------------------------------------------------------------------------- # Background subtraction print("") if HAVE_PHOTUTILS: print("sep version: ", sep.__version__) print("photutils version:", photutils.__version__) print( """ | test | sep | photutils | ratio | |-------------------------|-----------------|-----------------|--------|""" ) blankline = ( "| | | | |" ) else: print("sep version: ", sep.__version__) print( """ | test | sep | |-------------------------|-----------------|""" ) blankline = "| | |" for ntile in np.arange(1, args.tiles + 1, dtype=int): data = np.tile(rawdata, (ntile, ntile)) line = "| {0:4d}^2 image background |".format(data.shape[0]) t0 = time.time() for _ in range(0, args.nloop): bkg = sep.Background(data) t1 = time.time() t_sep = (t1 - t0) * 1.0e3 / args.nloop line += " {0:7.2f} ms |".format(t_sep) if HAVE_PHOTUTILS: t0 = time.time() for _ in range(0, args.nloop): from photutils import background bkg = background.Background2D(data, (64, 64)) # estimate background t1 = time.time() t_pu = (t1 - t0) * 1.0e3 / args.nloop line += " {0:7.2f} ms | {1:6.2f} |".format(t_pu, t_pu / t_sep) print(line) # ------------------------------------------------------------------------------ # Circular aperture photometry benchmarks if not args.condensed: print(blankline) line = "| **aperture photometry** | |" if HAVE_PHOTUTILS: line += " | |" print(line) data = np.ones((2000, 2000), dtype=np.float32) x = np.random.uniform(200.0, 1800.0, args.apertures) y = np.random.uniform(200.0, 1800.0, args.apertures) if args.condensed: r_list = [5.0] subpix_list = [(5, "subpixel", "subpix=5"), (0, "exact", "exact")] else: r_list = args.radii subpix_list = [ (1, "center", "subpix=1"), (5, "subpixel", "subpix=5"), (0, "exact", "exact"), ] for r in r_list: for subpix, method, label in subpix_list: line = "| circles r={0:2d} {1:8s} |".format(int(r), label) t0 = time.time() for _ in range(0, args.nloop): flux, fluxerr, flag = sep.sum_circle(data, x, y, r, subpix=subpix) t1 = time.time() t_sep = (t1 - t0) * 1.0e6 / args.apertures / args.nloop line += " {0:7.2f} us/aper |".format(t_sep) if HAVE_PHOTUTILS: from photutils import aperture apertures = photutils.aperture.CircularAperture(np.column_stack((x, y)), r) t0 = time.time() for _ in range(0, args.nloop): res = photutils.aperture.aperture_photometry( data, apertures, method=method, subpixels=subpix ) t1 = time.time() t_pu = (t1 - t0) * 1.0e6 / args.apertures / args.nloop line += " {0:7.2f} us/aper | {1:6.2f} |".format(t_pu, t_pu / t_sep) print(line) if not args.condensed: print(blankline) a = 1.0 b = 1.0 theta = np.pi / 4.0 for r in r_list: for subpix, method, label in subpix_list: line = "| ellipses r={0:2d} {1:8s} |".format(int(r), label) t0 = time.time() for _ in range(0, args.nloop): flux, fluxerr, flag = sep.sum_ellipse( data, x, y, a, b, theta, r, subpix=subpix ) t1 = time.time() t_sep = (t1 - t0) * 1.0e6 / args.apertures / args.nloop line += " {0:7.2f} us/aper |".format(t_sep) if HAVE_PHOTUTILS: from photutils import aperture apertures = photutils.aperture.EllipticalAperture( np.column_stack((x, y)), a * r, b * r, theta ) t0 = time.time() for _ in range(0, args.nloop): res = photutils.aperture.aperture_photometry( data, apertures, method=method, subpixels=subpix ) t1 = time.time() t_pu = (t1 - t0) * 1.0e6 / args.apertures / args.nloop line += " {0:7.2f} us/aper | {1:6.2f} |".format(t_pu, t_pu / t_sep) print(line) ================================================ FILE: codemeta.json ================================================ { "@context": "https://raw.githubusercontent.com/mbjones/codemeta/master/codemeta.jsonld", "@type": "Code", "author": [ { "@id": "http://orcid.org/0000-0002-2532-3696", "@type": "Person", "email": "kylebarbary@gmail.com", "name": "Kyle Barbary", "affiliation": "University of California, Berkeley" } ], "identifier": "http://dx.doi.org/10.5281/zenodo.159035", "codeRepository": "https://github.com/kbarbary/sep", "datePublished": "2016-09-30", "dateModified": "2016-09-30", "dateCreated": "2016-09-30", "description": "Python and C library for Source Extraction and Photometry", "keywords": "astronomy, Python, image analysis", "license": "LGPL v3.0", "title": "SEP", "version": "v1.0.0" } ================================================ FILE: ctest/compare.py ================================================ #!/usr/bin/env python """Compare the output from SEP against SExtractor.""" from __future__ import print_function import sys def read_table(fname): """ Read in a whitespace-separated table. Parameters ---------- fname : path-like The filename of the table to be opened. Returns ------- List[List[int|float]] A list of rows, each of which is a list of the values in that row. """ rows = [] for line in open(fname, "r"): l = line.strip() if len(l) == 0 or l[0] == "#": continue items = l.split() typed_items = [] for it in items: try: typed_items.append(int(it)) except ValueError: typed_items.append(float(it)) rows.append(typed_items) return rows def fracdiff(x, y): """ Return the fraction difference between two numbers. Parameters ---------- x, y : float The numbers to be compared. Returns ------- float The fractional difference. """ return abs((y - x) / max(y, x)) if __name__ == "__main__": fname1, fname2 = sys.argv[1:3] ref = read_table(fname1) sep = read_table(fname2) # sort by y coordinate ref.sort(key=lambda row: row[2]) sep.sort(key=lambda row: row[2]) assert len(ref) == len(sep) for i in range(len(ref)): assert abs(ref[i][1] - sep[i][1] - 1.0) < 1.0e-3 # x coordinate assert abs(ref[i][2] - sep[i][2] - 1.0) < 1.0e-3 # y coordinate assert fracdiff(ref[i][12], sep[i][3]) < 2.0e-4 # flux print("compare passed") ================================================ FILE: ctest/test_image.c ================================================ #include #include #include #include #include #include #include "sep.h" uint64_t gettime_ns() { struct timeval tv; gettimeofday(&tv, NULL); return (uint64_t)tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ULL; } double * ones_dbl(int nx, int ny) { int i, npix; double *im, *imt; im = (double *)malloc((npix = nx * ny) * sizeof(double)); imt = im; for (i = 0; i < npix; i++, imt++) { *imt = 1.0; } return im; } float * uniformf(float a, float b, int n) /* an array of n random numbers from the uniform interval (a, b) */ { int i; float * result; result = (float *)malloc(n * sizeof(float)); for (i = 0; i < n; i++) { result[i] = a + (b - a) * rand() / ((double)RAND_MAX); } return result; } float * ones(int nx, int ny) { int i, npix; float *im, *imt; im = (float *)malloc((npix = nx * ny) * sizeof(float)); imt = im; for (i = 0; i < npix; i++, imt++) { *imt = 1.0; } return im; } void addbox(float * im, int w, int h, float xc, float yc, float r, float val) /* n = sersic index */ { int xmin, xmax, ymin, ymax; int x, y; int rmax = (int)r; xmin = (int)xc - rmax; xmin = (xmin < 0) ? 0 : xmin; xmax = (int)xc + rmax; xmax = (xmax > w) ? w : xmax; ymin = (int)yc - rmax; ymin = (ymin < 0) ? 0 : ymin; ymax = (int)yc + rmax; ymax = (ymax > h) ? h : ymax; for (y = ymin; y < ymax; y++) { for (x = xmin; x < xmax; x++) { im[x + w * y] += val; } } } void printbox(float * im, int w, int h, int xmin, int xmax, int ymin, int ymax) /* print image values to the screen in a grid Don't make box size too big!! */ { int i, j; for (j = ymin; j < ymax && j < h; j++) { for (i = xmin; i < xmax && i < w; i++) { printf("%6.2f ", im[w * j + i]); } printf("\n"); } } /* an extremely dumb reader for our specific test FITS file! */ int read_test_image(char * fname, float ** data, int64_t * nx, int64_t * ny) { FILE * f; char buf[80]; /* buffer to hold a line */ long pos; size_t nbytes, nel, i, elsize, nread; char * rawbytes = NULL; short * rawdata; char tmp; int status = 0; float bscale, bzero; /* hard-code image size & element size */ *nx = 256; *ny = 256; elsize = 2; nel = *nx * *ny; bscale = 2.92273835509; bzero = 3713.66692596; f = fopen(fname, "r"); /* read first line and check if it is a FITS file */ nread = fread(buf, 1, 80, f); if (nread != 80) { status = 1; goto exit; } if (strncmp(buf, "SIMPLE = T", 30) != 0) { printf("not a FITS file"); status = 1; goto exit; } /* read rows until we get to END keyword */ while (strncmp(buf, "END", 3) != 0) { nread = fread(buf, 1, 80, f); if (nread != 80) { status = 1; goto exit; } } /* move to next 2880 byte boundary. */ pos = ftell(f) % 2880; /* position in "page" */ if (pos != 0) { fseek(f, 2880 - pos, SEEK_CUR); } /* read raw data bytes */ nbytes = nel * elsize; rawbytes = (char *)malloc(nbytes); nread = fread(rawbytes, 1, nbytes, f); if (nread != nbytes) { status = 1; goto exit; } /* swap bytes in raw data (FITS is big-endian) */ for (i = 0; i < nbytes; i += 2) { tmp = rawbytes[i]; rawbytes[i] = rawbytes[i + 1]; rawbytes[i + 1] = tmp; } rawdata = (short *)rawbytes; /* buffer is now little-endian */ /* convert to float, applying bscale/bzero */ *data = (float *)malloc(nel * sizeof(float)); for (i = 0; i < nel; i++) { (*data)[i] = bscale * rawdata[i] + bzero; } exit: free(rawbytes); return status; } float * tile_flt( float * im, int nx, int ny, int ntilex, int ntiley, int * nxout, int * nyout ) { int i, x, y; int npixout; float * imout; *nxout = ntilex * nx; *nyout = ntiley * ny; npixout = *nxout * *nyout; imout = (float *)malloc(npixout * sizeof(float)); for (i = 0; i < npixout; i++) { x = (i % (*nxout)) % nx; /* corresponding x on small im */ y = (i / (*nxout)) % ny; /* corresponding y on small im */ imout[i] = im[y * nx + x]; } return imout; } void print_time(char * s, uint64_t tdiff) { printf("%-25s%6.1f ms\n", s, (double)tdiff / 1000000.); } int main(int argc, char ** argv) { char *fname1, *fname2; int i, status; int64_t nx, ny; double *flux, *fluxerr, *fluxt, *fluxerrt, *area, *areat; short *flag, *flagt; float *data, *imback; uint64_t t0, t1; sep_bkg * bkg = NULL; float conv[] = {1, 2, 1, 2, 4, 2, 1, 2, 1}; sep_catalog * catalog = NULL; FILE * catout; status = 0; flux = fluxerr = NULL; flag = NULL; /* Parse command-line arguments */ if (argc != 3) { printf("Usage: test-image IMAGE_NAME CATALOG_NAME\n"); exit(1); } fname1 = argv[1]; fname2 = argv[2]; /* read in image */ status = read_test_image(fname1, &data, &nx, &ny); if (status) { goto exit; } /* test the version string */ printf("sep version: %s\n", sep_version_string); /* background estimation */ t0 = gettime_ns(); sep_image im = { data, NULL, NULL, NULL, SEP_TFLOAT, 0, 0, 0, 0, 0, 0, nx, ny, 0.0, SEP_NOISE_NONE, 1.0, 0.0 }; status = sep_background(&im, 64, 64, 3, 3, 0.0, &bkg); t1 = gettime_ns(); if (status) { goto exit; } print_time("sep_background()", t1 - t0); /* evaluate background */ imback = (float *)malloc((nx * ny) * sizeof(float)); t0 = gettime_ns(); status = sep_bkg_array(bkg, imback, SEP_TFLOAT); t1 = gettime_ns(); if (status) { goto exit; } print_time("sep_bkg_array()", t1 - t0); /* subtract background */ t0 = gettime_ns(); status = sep_bkg_subarray(bkg, data, im.dtype); t1 = gettime_ns(); if (status) { goto exit; } print_time("sep_bkg_subarray()", t1 - t0); /* extract sources * Note that we set deblend_cont = 1.0 to turn off deblending. */ t0 = gettime_ns(); status = sep_extract( &im, 1.5 * bkg->globalrms, SEP_THRESH_ABS, 5, conv, 3, 3, SEP_FILTER_CONV, 32, 1.0, 1, 1.0, &catalog ); t1 = gettime_ns(); if (status) { goto exit; } print_time("sep_extract()", t1 - t0); /* aperture photometry */ im.noise = &(bkg->globalrms); /* set image noise level */ im.ndtype = SEP_TFLOAT; fluxt = flux = (double *)malloc(catalog->nobj * sizeof(double)); fluxerrt = fluxerr = (double *)malloc(catalog->nobj * sizeof(double)); areat = area = (double *)malloc(catalog->nobj * sizeof(double)); flagt = flag = (short *)malloc(catalog->nobj * sizeof(short)); t0 = gettime_ns(); for (i = 0; i < catalog->nobj; i++, fluxt++, fluxerrt++, flagt++, areat++) { sep_sum_circle( &im, catalog->x[i], catalog->y[i], 5.0, 0, 5, 0, fluxt, fluxerrt, areat, flagt ); } t1 = gettime_ns(); printf( "sep_sum_circle() [r= 5.0] %6.3f us/aperture\n", (double)(t1 - t0) / 1000. / catalog->nobj ); /* print results */ printf("writing to file: %s\n", fname2); catout = fopen(fname2, "w+"); fprintf(catout, "# SEP catalog\n"); fprintf(catout, "# 1 NUMBER\n"); fprintf(catout, "# 2 X_IMAGE (0-indexed)\n"); fprintf(catout, "# 3 Y_IMAGE (0-indexed)\n"); fprintf(catout, "# 4 FLUX\n"); fprintf(catout, "# 5 FLUXERR\n"); for (i = 0; i < catalog->nobj; i++) { fprintf( catout, "%3d %#11.7g %#11.7g %#11.7g %#11.7g\n", i + 1, catalog->x[i], catalog->y[i], flux[i], fluxerr[i] ); } fclose(catout); /* clean-up & exit */ exit: sep_bkg_free(bkg); free(data); free(flux); free(fluxerr); free(flag); if (status) { printf("FAILED with status: %d\n", status); char errtext[512]; sep_get_errdetail(errtext); puts(errtext); } else { printf("test_image passed\n"); } return status; } /***************************************************************************/ /* aperture photometry */ /* int naper, j; float *xcs, *ycs; im = ones(nx, ny); naper = 1000; flux = fluxerr = 0.0; flag = 0; float rs[] = {3., 5., 10., 20.}; for (j=0; j<4; j++) { r = rs[j]; xcs = uniformf(2.*r, nx - 2.*r, naper); ycs = uniformf(2.*r, ny - 2.*r, naper); printf("sep_apercirc() [r=%4.1f] ", r); t0 = gettime_ns(); for (i=0; i DATE = '1992-10-26' / Mon Oct 26, 1992 ESO-LOG 03:04:08>-START EXPO EMMI RED / Start exp. on EMMI Red CC ESO-LOG 03:04:09> EXPO EMMI RED NO = 24887 / Exp. num. on EMMI Red CCD ESO-LOG 03:10:52>-STOP EXPO EMMI RED / Stop exp. on EMMI Red CCD HISTORY COMPUTE/IMAG imAR0051.bdf = #0001-bias50 \HISTORY COMPUTE/IMAG imAR0051.bdf = #0001 - 1.51001E-01 \HISTORY COMPUTE/IMAG NA36Rc501 = #0001 * 1.00000E+03 / fRc50 \HISTORY COMPUTE/IMAG NA36Rc50 = NA36Rc501 \HISTORY COMPUTE/IMAG NA36Rc50 = NA36Rc50 + NA36Rc503 \HISTORY COMPUTE/IMAG NA36Rc50 = NA36Rc50 + NA36Rc502 \HISTORY EXTRACT/IMAG intex = NA36Rc50[@0019,@0003:@1042,@1026] \HISTORY Renamed from intex.bdf to NA36Rc50.bdf \HISTORY SELE/TABL cursor MA36Rc50 2 0. 3 Y MA36Rc50 \HISTORY READ/TABL cursor interclean 0 6.85000E+03 3 Y \HISTORY interclean Renamed from interclean.bdf to MA36Rm\HISTORY 50.bdf READ/TABL cursor MA36Rm50 0 \HISTORY 6850 3 Y MA36Rm50 READ/TABL cursor MA\HISTORY 36Rm50 0 6850 3 Y MA36Rm50 READ/TABL \HISTORY cursor MA36Rm50 0 6850 3 Y MA36Rm50 RA = 5.648169994354E+00 / MIDAS desc.: O_POS(1) DEC = -3.018300056458E+01 / MIDAS desc.: O_POS(2) AIRMASS = 1.068349957466E+00 / MIDAS desc.: O_AIRM(1) HIERARCH ESO GEN ID = 'ARC-0001/1.2' HIERARCH ESO GEN PROJ ID = '000.00.000' HIERARCH ESO GEN EXPO NO = 24887 HIERARCH ESO GEN EXPO TYPE = 'SCI ' HIERARCH ESO GEN EXPO LST = 2.420000000000E+03 HIERARCH ESO TEL ID = 'ESONTTB ' HIERARCH ESO TEL LON = 7.073450000000E+01 HIERARCH ESO TEL LAT = -2.925840000000E+01 HIERARCH ESO TEL ALTITUDE = 2440 HIERARCH ESO TEL FOCU LEN = 3.848200000000E+01 HIERARCH ESO TEL FOCU SCALE = 1.489000000000E+00 HIERARCH ESO TEL TRAK RATEA = 4.200000000000E-03 HIERARCH ESO TEL TRAK RATED = 0.000000000000E+00 HIERARCH ESO ADA ID = 'ADAPTB ' HIERARCH ESO ADA MODE = 'STD ' HIERARCH ESO ADA ROT = 0.000000000000E+00 HIERARCH ESO ADA GUID-1 X = 1.294000000000E-02 HIERARCH ESO ADA GUID-1 Y = 1.717000000000E-01 HIERARCH ESO ADA GUID-2 X = 5.070000000000E-04 HIERARCH ESO ADA GUID-2 Y = 1.110000000000E-03 HIERARCH ESO INS ID = 'EMMI #1 ' HIERARCH ESO INS COMP ID = 'HP RTE-A V5' HIERARCH ESO INS MODE = 'RILD ' HIERARCH ESO INS OPTI-2 NO = 1 HIERARCH ESO INS OPTI-2 TYPE = 'MIRROR ' HIERARCH ESO INS OPTI-2 ID = 'RILD MIR' HIERARCH ESO INS OPTI-2 NAME = 'RILD ' HIERARCH ESO INS OPTI-3 NO = 1 HIERARCH ESO INS OPTI-3 TYPE = 'FREE ' HIERARCH ESO INS MIRR-3 NAME = 'UPPER RED' HIERARCH ESO INS MIRR-3 ST = 0 HIERARCH ESO INS OPTI-7 NO = 3 HIERARCH ESO INS OPTI-7 TYPE = 'FILTER ' HIERARCH ESO INS OPTI-7 ID = '#608 ' HIERARCH ESO INS OPTI-7 NAME = 'R ' HIERARCH ESO INS OPTI-9 NO = 9 HIERARCH ESO INS OPTI-9 TYPE = 'FREE ' HIERARCH ESO DET NAME = 'THX31156' HIERARCH ESO DET ID = 'ccd$18 ' HIERARCH ESO DET TYPE = 'CCD Four_Phase' HIERARCH ESO DET PIXSIZE = 1.900000000000E-05 HIERARCH ESO DET BITS = 16 HIERARCH ESO DET FRAM NAXIS1 = 1060 HIERARCH ESO DET FRAM CRVAL1 = 1 HIERARCH ESO DET FRAM CRPIX1 = 1 HIERARCH ESO DET FRAM CDELT1 = 1 HIERARCH ESO DET FRAM NAXIS2 = 1040 HIERARCH ESO DET FRAM CRVAL2 = 1 HIERARCH ESO DET FRAM CRPIX2 = 1 HIERARCH ESO DET FRAM CDELT2 = 1 HIERARCH ESO DET DKTIME = 4.000000000000E+02 HIERARCH ESO DET TEMP_VAR = 1.000000000000E-01 HIERARCH ESO DET TEMPMEAN = 1.376000000000E+02 HIERARCH ESO DET COMP ID = 'ccdr-V1.0' HIERARCH ESO DET PARM1 = 'CLOCK=tho1k' HIERARCH ESO DET PARM2 = 'HLO1 : 2.02 VLO1 : 1.01 VDD1 : 23.03' HIERARCH ESO DET PARM3 = 'HHI1 : 15.00 VHI1 : 12.01 VDR1 : 13.98' HIERARCH ESO DET PARM4 = 'HLO2 : 2.02 RLO1 : 1.01 VGS1 : 4.99' HIERARCH ESO DET PARM5 = 'HHI2 : 15.03 RHI1 : 10.07 ICCD1 : 0.00' HIERARCH ESO DET PARM6 = 'TL 1, 5 telem. data' HIERARCH ESO DET DATE = 1.989794555664E+03 HIERARCH ESO DET MODE = 'SLOW ' HIERARCH ESO DET GAIN = 1 HIERARCH ESO DET AD_VALUE = 2.100000000000E+00 HIERARCH ESO DET DIT = 4.000000000000E+02 HIERARCH ESO DET SHUT TMOPEN = 5.000000000000E-01 HIERARCH ESO DET SHUT TMCLOS = 5.000000000000E-01 HISTORY ESO-DESCRIPTORS START ................ HISTORY 'WIND_RAW' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.9000000E+01 3.0000000E+00 1.0420000E+03 1.0260000E+03 HISTORY HISTORY 'STAT_RAW' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 6.5800000E+02 3.2767000E+04 2.3813201E+03 5.6562799E+02 2.4699001E+10 HISTORY 3.8941301E+14 2.4969999E+09 2.3490701E+03 2.3460000E+03 2.0070000E+03 HISTORY 1.6000000E+01 6.5800000E+02 3.2767000E+04 HISTORY HISTORY 'WIND_OVER' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.0000000E+01 1.0290000E+03 1.0550000E+03 1.0390000E+03 HISTORY HISTORY 'STAT_OVER' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 2.1200000E+02 2.4400000E+02 2.2111700E+02 2.5815699E+00 1.0815500E+07 HISTORY 2.3924700E+09 2.5441800E+06 2.2058000E+02 2.2050000E+02 3.3000000E+01 HISTORY 1.0000000E+00 2.1200000E+02 2.4400000E+02 HISTORY HISTORY 'BIAS_FRAME' ,'C*1 ' , 1, 7,'7A1',' ',' ' HISTORY bias50 HISTORY HISTORY 'BIAS_OVER_DIFF' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 1.5100101E-01 HISTORY HISTORY 'FLAT_WIND' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 4.5000000E+02 3.8000000E+02 7.4000000E+02 6.2000000E+02 HISTORY HISTORY 'FLAT_BKG' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 2.1311699E+03 HISTORY HISTORY 'SKIM_FRAC' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 3.5154400E-04 HISTORY HISTORY 'AV_WIND_NAME' ,'C*1 ' , 1, 5,'5A1',' ',' ' HISTORY fRc50 HISTORY HISTORY 'FLAT_FRAME' ,'C*1 ' , 1, 5,'5A1',' ',' ' HISTORY fRc50 HISTORY HISTORY 'WIND_FIN' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.9000000E+01 3.0000000E+00 1.0420000E+03 1.0260000E+03 HISTORY HISTORY 'STAT_FIN' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 6.0423798E+02 3.2842602E+04 2.1606499E+03 5.5936798E+02 2.0734501E+10 HISTORY 3.5516501E+14 2.2656100E+09 2.1273799E+03 2.1162400E+03 2.0150000E+03 HISTORY 1.6000000E+01 6.0423798E+02 3.2842602E+04 HISTORY HISTORY 'WIND_SUM' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.0000000E+00 1.0000000E+00 1.0240000E+03 1.0240000E+03 HISTORY HISTORY 'STAT_SUM' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 3.7136699E+03 9.8528203E+04 6.9033799E+03 1.6677500E+03 6.1352398E+11 HISTORY 2.8897399E+16 7.2387098E+09 6.8047002E+03 6.7938701E+03 2.0480000E+03 HISTORY 4.6318802E+01 3.7136699E+03 9.8528203E+04 HISTORY HISTORY 'LHCUTS' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 5.5000000E+03 9.0000000E+03 3.7136670E+03 9.8528234E+04 HISTORY HISTORY 'DISPLAY_DATA' ,'I*4 ' , 1, 9,'7I10',' ',' ' HISTORY 2 2 513 513 0 -1 -1 HISTORY -1 -1 HISTORY HISTORY 'BOX_MIN' ,'R*4 ' , 1, 6,'5E14.7',' ',' ' HISTORY 3.2100000E+02 2.1500000E+02 6.9644336E+03 6.3300000E+02 4.2300000E+02 HISTORY 6.8900532E+03 HISTORY HISTORY 'IJBORDER' ,'I*4 ' , 1, 4,'7I10',' ',' ' HISTORY 1 1 1024 1024 HISTORY HISTORY 'LHCUT' ,'R*4 ' , 1, 2,'5E14.7',' ',' ' HISTORY 3.6236699E+03 8.0148297E+04 HISTORY HISTORY 'ZEROMAGN' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 2.4671000E+01 HISTORY HISTORY 'SEEING' ,'R*4 ' , 1, 2,'5E14.7',' ',' ' HISTORY 1.8308023E+00 9.6358800E-01 HISTORY HISTORY 'PAIRSPRT' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 3.1899800E+00 HISTORY HISTORY 'MULTDTCT' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 4.1900001E+00 HISTORY HISTORY 'PRFLCTRL' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY -5 HISTORY HISTORY 'OUPROFIL' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 5 HISTORY HISTORY 'STMETRIC' ,'R*4 ' , 1, 2,'5E14.7',' ',' ' HISTORY 9.3000001E-01 5.5799999E+00 HISTORY HISTORY 'BRGHTLMT' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 1.8387699E+01 HISTORY HISTORY 'NBSTARS' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 17 HISTORY HISTORY 'PSFTAB' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 1 HISTORY HISTORY 'THRESHOLD' ,'R*4 ' , 1, 5,'5E14.7',' ',' ' HISTORY 6.8047002E+03 1.1384800E+02 1.6730800E+00 2.0000000E+00 2.5446301E+01 HISTORY HISTORY 'N_SEARCH_ANA' ,'I*4 ' , 1, 2,'7I10',' ',' ' HISTORY 822 806 HISTORY HISTORY 'N_STAR_GAL_DEF' ,'I*4 ' , 1, 3,'7I10',' ',' ' HISTORY 46 744 16 HISTORY HISTORY 'HIST_BINS' ,'R*4 ' , 1, 5,'5E14.7',' ',' ' HISTORY 2.5600000E+02 2.8824686E+02 3.7136670E+03 7.7216609E+04 0.0000000E+00 HISTORY HISTORY 'HISTOGRAM' ,'I*4 ' , 1, 256,'7I10',' ',' ' HISTORY 1 0 0 0 0 0 0 HISTORY 0 0 0 10 64 23 12 HISTORY 3 3 4 4 3 1 2 HISTORY 0 0 1 1 0 1 0 HISTORY 0 0 0 3 0 1 0 HISTORY 0 1 0 1 0 1 0 HISTORY 0 0 1 1 0 1 0 HISTORY 1 0 0 0 0 0 0 HISTORY 0 0 1 1 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 1 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 1 0 1 0 0 1 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 1 0 0 0 0 0 0 HISTORY 0 0 0 0 0 1 0 HISTORY 0 0 0 0 0 1 0 HISTORY 0 0 0 0 1 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 0 0 0 0 1 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 1 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 1 0 0 0 0 HISTORY 0 0 1 0 HISTORY HISTORY 'STATISTIC' ,'R*4 ' , 1, 11,'5E14.7',' ',' ' HISTORY 3.7136670E+03 9.8528234E+04 6.9033760E+03 1.6677493E+03 6.1352378E+11 HISTORY 2.8897433E+16 7.2387144E+09 6.5048496E+03 3.8995779E+03 2.5600000E+02 HISTORY 3.7182184E+02 HISTORY HISTORY 'WINDOW_FROM' ,'I*4 ' , 1, 2,'7I10',' ',' ' HISTORY 1 1 HISTORY HISTORY 'WINDOW_TO' ,'I*4 ' , 1, 2,'7I10',' ',' ' HISTORY 1024 1024 HISTORY HISTORY 'NBMODIF' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 1 HISTORY HISTORY 'STARS' ,'R*4 ' , 1, 51,'5E14.7',' ',' ' HISTORY 2.6300000E+02 8.8700000E+02 4.6759199E+04 7.5000000E+01 5.6300000E+02 HISTORY 1.5854400E+04 1.3000000E+01 3.1300000E+02 4.9727699E+04 3.3900000E+02 HISTORY 4.3300000E+02 9.6787102E+04 7.0100000E+02 1.6300000E+02 1.2378200E+04 HISTORY 8.5500000E+02 2.5500000E+02 3.5242898E+04 7.6100000E+02 3.3300000E+02 HISTORY 1.4904300E+04 1.0110000E+03 3.5700000E+02 2.5686801E+04 9.0700000E+02 HISTORY 4.0100000E+02 1.6969100E+04 8.4900000E+02 5.2500000E+02 1.4543700E+04 HISTORY 9.1700000E+02 5.4500000E+02 4.4644398E+04 7.7700000E+02 5.7700000E+02 HISTORY 3.6737199E+04 1.0010000E+03 6.9500000E+02 9.8214500E+04 8.2500000E+02 HISTORY 8.0100000E+02 2.0127900E+04 6.3100000E+02 6.3500000E+02 1.6520199E+04 HISTORY 5.8500000E+02 6.7500000E+02 1.5727300E+04 6.5900000E+02 6.6500000E+02 HISTORY 2.1833900E+04 HISTORY HISTORY 'DPROFILE' ,'R*4 ' , 1, 25,'5E14.7',' ',' ' HISTORY 3.2567519E-01 6.4562768E-01 6.5725815E-01 5.2960014E-01 4.1916752E-01 HISTORY 3.0000001E-01 2.8000000E-01 2.5999999E-01 2.3999999E-01 2.0000000E-01 HISTORY 1.8000001E-01 1.6000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 HISTORY 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 HISTORY 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 HISTORY HISTORY ESO-DESCRIPTORS END ................ END EZvEYEYAEXEXEWeEVEV"EU~ETET3ESERER9EQEPEP8EOENEN1EMELEL#EKsEJEJEI_EHEGEGIEFEEEE3EDECECEBjEAEAE@WE?E>E>FE=E2E>E>E?JE?E@E@`E@EAEAnEXEX]EWEW*EVEUEUVETETESwERER2EQEPEPDEOENENKEMELELNEKEJEJLEIEHEHFEGEFEF=EEEDED4ECEBEB*EA}E@E@#E?vE>E>E=rEE_EEEEE ELEyEEE E@EuEEE E ZE E E! E!IE!E!E" E"NE"E"E# E#hE#E#E$FE$E$E%0E%E%E&$E&vE&E'E'tE'E("E(zE(E),E)E)E*>E*E*E+VE+E,E,tE,E-4E-E-E.ZE.E/ E/E/E0LE0E1E1{E1E2EE2E3E3xE3E4EE4E5E5yE5E6FE6E7E7{E7E8HE8E9E9{E9E:FE:E;E;wE;E/E>E>E?RE?E@E@pE@EA.EAEAEBCEWhEVEVBEUEUET|ESESHEREREQrEPEP4EOENENOEMEMELcEKEKEJpEIEI"EHzEGEG*EFEEEE.EDECEC2EBEAEA7E@E?E?E=E=DEE9E6E6E8E=EDELEWEdEtEEEEEEEE7EXE{EEEEEFEuEEEE=EtEEE E [E E E!E!NE!E!E"E"XE"E"E#-E#vE#E$ E$ZE$E$E%JE%E%E&@E&E&E'BE'E'E(LE(E)E)\E)E*E*tE*E+4E+E+E,VE,E-E-~E-E.FE.E/E/vE/E0BE0E1E1xE1E2HE2E3E3E3E4SE4E5&E5E5E6bE6E76E7E8E8rE8E9CE9E:E:~E:E;NE;E<EE>E>E?LE?E@E@vE@EA:EAEAEBZEBECEUEUNETET-ESESERqEQEQDEPEPEOtENENE>VE=E=EE6E2E0E0E2E6EE>lE>E?>E?E@ E@rE@EAE> E=mEOE>E?'E?E?E@fE@EA7EAEBEBnEBEC;ECEDEDhEDERER1EQEQ EPEP EO~ENENaEMEM@ELELEKEJEJ\EIEI0EHEHEGhEFEF6EEEEEDhECEC1EBEAEA`E@E@(E?E>E>VE=E= EE3E3E2E1E1nE0E0VE/E/BE.E.4E-E-+E,E,(E+E++E*E*5E)E)FE(E(]E'E'}E'E&E&:E%E%pE% E$E$NE#E#E#CE"E"E"LE!E!E!nE!)E E E EEEEtE4EEEELEEEEEeE@EEEEEEExEfEUEGE$E>E?E?rE?E@ME@EA&EAEAEBiEBEC=ECEDEDuEDEEBEEEQEPEPEOEO ENEMEMrELEL\EKEKCEJEJ$EIEIEHrEGEGNEFEF&EEEDEDhECEC>EBEBEA{E@E@NE?E?E>E=E=[EE.E/E/E/E0gE0E1HE1E2*E2E3E3E3E4hE4E5NE5E67E6E7 E7E8 E8~E8E9gE9E:PE:E;9E;E<"EbE>E?FE?E@)E@EA EAxEAEBVEBEC2ECED EDvEDEEJEEEFEFEOEOENENEMEMEL|EKEKpEJEJbEIEINEHEH9EGEGEFEFEEuEDEDWECEC6EBEBEAE@E@`E?E?E>E=E$E>E?E?E?E@mE@EATEAEB:EBECECECEDmEDEEIEEEF"EFEFEGaEMEMlELELsEKEKxEJEJxEIEIrEHEHjEGEG`EFEFPEEEE@EDED-ECECEBEBEAuE@E@\E?E?CE>E>)E=E=EE,E,LE+E+^E*E*vE*E)E)$E(E(KE'E'xE'E&E&IE%E%E%+E$E$vE$E#E#wE#$E"E"E"?E!E!E!nE!.E E E aE EEEQEEEEiE6EEEE~EVE0EEEEEEEnE[EJEWE>E?HE?E@8E@EA(EAEBEBEBECtECED[EDEE?EEEF EFEGEGlEGEHFELDEKEKXEJEJdEIEIoEHEHvEGEGyEFEFyEEEEvEDEDpECEChEBEB]EAEAQE@E@BE?E?4E>E>%E=E=EE2E(E EEEEEE$E,E6ECEREbEuEEEEEEE6EZEEEEE-E^EEEE4EmEEE )E jE E E!/E!vE!E"E"QE"E"E#=E#E#E$8E$E$E%@E%E%E&VE&E'E'xE'E(BE(E)E)vE)E*JE*E+#E+E+E,nE,E-PE-E.5E.E/E/E0E0~E0E1nE1E2_E2E3RE3E4HE4E5>E5E67E6E70E7E8)E8E9#E9E:E:E;E;E<EE>E?E?|E?E@sE@EAhEAEBZEBECLECED:EDEE(EEEFEFEFEGjEGEHLEHEI*EJEJ,EIEIDEHEH\EGEGmEFEF{EFEEEE EDEDECECEBEBEAEAE@E@E?E?E>E> E=E=E+E>E?*E?E@(E@EA%EAEB EBECECEDEDEEEE|EEEFnEFEG\EGEHEEHEI,EIEJEHEHEHEGEGE>UE=E=[EEEEyE;EEEE\E,EEEEzESE.E EEEEEEnEZEJENE>E?TE?E@XE@EA[EAEB]EBEC]ECED[EDEEVEEEFPEFEGFEGEH8EHEI(EIEJEJEJEGNEFEF|EFEEEE8EDED\ECEC|EC EBEB(EAEA@E@E@XE?E?nE>E>E> E=E=EE1E'EEEEEEEE%E/E:EJEYEkEEEEEEE)ELEsEEEE"EREEEE-EjEEE ,E nE E E!;E!E!E"E"hE"E# E#`E#E$ E$gE$E% E%E%E&BE&E' E'pE'E(CE(E)E)E)E*gE*E+JE+E,3E,E- E-E.E.E/E/E/E0{E0E1xE1E2xE2E3zE3E4E5E5E6 E6E7E7E8E8E9(E9E:4E:E;BE;EhE>E?sE?E@~EAEAEB EBECECEDEDEEEEEFEFEGEGEHEHEIEIEJEJ~EJEKlEKEEEEE>E>E=E=3EE!E!E!E!LE!E E E pE ,EEEoE3EEEEZE*EEEE|EVE2EEEEEEEpE^EME>E2E(E EEEEEEE#E-E8EFEVEhE|EEEEEE%EHEoEEEEENEEEE*EgEEE +E nE E E!~E?E?E@E@EA*EAEB:EBECGECEDUEDEE^EEEFhEFEGlEGEHnEHEIoEIEJjEJEKcEKELVELECECEC3EBEBnEB EAEA@E@E@tE@ E?E?>E>E>jE>E=E=)EE>E?E?E@3E@EALEAEBbEBECvEDEDEEEEEF$EFEG1EGEHE>E>&E=E=\E E>E?*E?E@IE@EAgEAEBECECED.EDEEFEEEF]EFEGtEGEHEIEIEJEJEK&EKEL,ELEM/EMEN.ENE@E@6E?E?E?,E>E>wE>E=E=bE=EE1E1vE1E0E0NE/E/E/)E.E.fE.E-E-HE,E,E,.E+E+tE+E*E*dE* E)E)ZE)E(E(YE(E'E'`E'E&E&pE&"E%E%E%>E$E$E$gE$ E#E#E#YE#E"E"E"aE"(E!E!E!E!OE!E E E E ZE EEEgE/EEEE^E0EEEEEbE=EEEEEEE}EjEXEHE E>E?1E?E@WE@EA{EBEBEC1ECEDTEDEEtEFEFEG!EGEHE>E>1E=E=E=4EE+E+E+5E*E*E*1E)E)E)3E(E(E(E!E E E E UE EEEfE.EEEEbE4EEEEEfECE!EEEEEEEnE\EME?E4E*E"EEEEEE$E,E6EDEREbEuEEEEEEEE#E#E$UE$E%E%E%E&OE&E'(E'E(E(zE(E)dE)E*TE*E+JE+E,FE,E-GE-E.ME.E/XE/E0hE0E1|E2E2E3!E3E4=E4E5]E5E6E7E7E88E8E9_E9E:E;E;E E>E?6E?E@bE@EAEB#EBECNECEDwEE EEEF1EFEGVEGEHyEI EIEJ'EJEKBEKEL[ELEMnEMEN~EOEOEP EPE=EE,E,E,=E+E+E+?E*E*E*FE)E)E)SE)E(E(fE(E'E'E'4E&E&E&WE&E%E%E%>E$E$E$vE$6E#E#E#zE#?E#E"E"E"\E"&E!E!E!E!^E!0E!E E E E QE EEEgE1EEEEgE:E EEEEnEJE*E EEEEEEuEdETEFE;E1E)E$E E E E$E)E0E:EFETEeEwEEEEEEEE>E?3E?E@fE@EAEB1EBECbECEDEE)EEEFWEFEGEHEHEIBEIEJgEJEKELELEM4EMENNENEOcEOEPsEPEQE;cE;E:E:E:;E9E9E9VE9E8E8lE8E7E7~E7.E6E6E6:E5E5E5CE4E4E4JE3E3E3PE2E2E2TE2E1E1XE1E0E0\E0E/E/aE/ E.E.gE.E-E-oE-E,E,yE,'E+E+E+6E*E*E*JE)E)E)aE)E(E(~E(4E'E'E'YE'E&E&E&@E%E%E%vE%4E$E$E$tE$8E#E#E#E#JE#E"E"E"pE"EEEEEtERE0EEEEEEE|EiEYEKE>E5E,E'E#E"E"E%E)E0E:EEETEdEvEEEEEEE9E_EEEEEAEuEEE#EcEEE 2E yE E! E!UE!E!E"IE"E"E#SE#E$E$sE$E%>E%E&E&E&E'^E'E(EE(E)4E)E**E*E+%E+E,(E,E-0E-E.>E.E/RE/E0jE0E1E2E2E3:E3E4aE4E5E6!E6E7NE7E8E9E9E:ME:E;E<EE?+E?E@cE@EAEB8EBECpED EDEEBEEEFvEGEGEHDEHEIrEJ EJEK6EKEL^ELEMENENEO3EOEPMEPEQbEQERtE9E9dE9E8E8E8LE8E7E7tE7,E6E6E6NE6E5E5mE5!E4E4E4:E3E3E3SE3E2E2iE2E1E1}E1.E0E0E0BE/E/E/WE/ E.E.kE.E-E-E-4E,E,E,ME,E+E+hE+E*E*E*EsEEE"EcEEE 2E zE E! E!YE!E!E"OE"E#E#]E#E$E$E$E%PE%E&&E&E'E'xE'E(dE(E)VE)E*PE*E+PE+E,XE,E-eE-E.xE/E/E0E0E1@E1E2dE2E3E4"E4E5QE5E6E7E7E8RE8E9E:(E:E;bE<EE=E>}E?E?E@\E@EAEB:EBECyEDEDEEUEEEFEG.EGEHhEIEIEJ9EJEKmELELEM4EMEN_ENEOEPEPEQ6EQERREREShE7E7E7lE7-E6E6E6fE6#E5E5E5VE5E4E4E4BE3E3E3nE3&E2E2E2NE2E1E1tE1,E0E0E0QE0E/E/vE/,E.E.E.QE.E-E-vE-.E,E,E,TE, E+E+|E+5E*E*E*aE*E)E)E)LE)E(E(E(E EEEEEEEtEdEVEHE>E6E/E*E(E'E(E-E4EfE?E?E@ME@EAEB7EBEC|EDEDEEcEFEFEGGEGEHEI&EIEJcEKEKEL;ELEMrEN ENEOE5E4E4E4HE4E3E3E3JE3E2E2E2FE2E1E1E1>E0E0E0uE01E/E/E/hE/$E.E.E.XE.E-E-E-JE-E,E,E,=E+E+E+sE+0E*E*E*jE*(E)E)E)eE)$E(E(E(fE(&E'E'E'lE'0E&E&E&{E&@E&E%E%E%ZE%"E$E$E$~E$IE$E#E#E#}E#KE#E"E"E"E"`E"5E" E!E!E!E!hE!AE!E E E E E sE HE EEEpEEHETEdEuEEEEEEE2EXEEEEE9EpEEEE`EEE 5E ~E E!E!`E!E"E"]E"E#E#rE#E$8E$E%E%rE%E&PE&E'7E'E(%E(E)E)E*E*E+#E+E,0E,E-DE-E._E.E/E0E0E1:E1E2hE3E3E45E4E5nE6 E6E7JE7E8E9,E9E:qE;E;E<\E=E=E>JE>E?E@;E@EAEB.EBEC{ED EDEElEFEFEGZEGEHEIEEIEJEK+EKELmEM EMENHENEOEPEPEQMEQER|ESESET6ETEUVE4nE48E4E3E3E3ZE3"E2E2E2uE2;E1E1E1E1NE1E0E0E0]E0!E/E/E/hE/,E.E.E.qE.4E-E-E-zE-;E,E,E,E,BE,E+E+E+KE+ E*E*E*UE*E)E)E)bE)&E(E(E(rE(8E'E'E'E'PE'E&E&E&nE&7E&E%E%E%`E%+E$E$E$E$^E$,E#E#E#E#mE#>E#E"E"E"E"cE":E"E!E!E!E!wE!RE!/E! E E E E E pE FE EEErE@EEEEEZE/EEEEEsEQE2EEEEEEEErEdEVEJE@E9E4E0E.E0E2E8E@EIEUEcEuEEEEEE E0EUE|EEEE6ElEEEE^EEE 4E ~E E!E!bE!E" E"cE"E#E#{E#E$DE$E%E%E%E&dE&E'NE'E(@E(E)'E>E?xE@"E@EAtEBEBECpEDEDEElEFEFEGeEH EHEI\EJEJEKMEKELEM9EMEN|EOEOEP\EPEQER2ERESfESETEU(EUEVNE2E2|E2JE2E1E1E1~E1JE1E0E0E0vE0@E0 E/E/E/gE/0E.E.E.E.QE.E-E-E-pE-8E-E,E,E,VE,E+E+E+sE+;E+E*E*E*YE*!E)E)E)zE)BE) E(E(E(fE(/E'E'E'E'XE'"E&E&E&E&RE&E%E%E%E%VE%$E$E$E$E$fE$7E$ E#E#E#E#XE#,E#E"E"E"E"`E"9E"E!E!E!E!E!`E!?E!E!E E E E E oE GE EEExEGEEEEEbE9EEEEE|E[EE>E?WE@E@EA\EBEBECaEDEDEEgEFEFEGkEHEHEIlEJEJEKjELELEMaENENEOQEOEPEQ8EQERzESESETQETEUEVEVEWFE0E0E0E0bE06E0E/E/E/zE/KE/E.E.E.E.XE.'E-E-E-E-`E-.E,E,E,E,dE,0E+E+E+E+eE+1E*E*E*E*eE*2E)E)E)E)fE)4E)E(E(E(jE(8E(E'E'E'rE'AE'E&E&E&E&PE& E%E%E%E%fE%:E% E$E$E$E$\E$1E$E#E#E#E#aE#8E#E"E"E"E"zE"UE"2E"E!E!E!E!E!hE!HE!+E! E E E E E E lE EE EEEzEKEEEEEiE@EEEEEEdEDE'E EEEEEEEsEdEXEMEDE>E9E8E6E:E>EDENEXEfEvEEEEEE E,ERExEEEE2EhEEEE^EEE 6E E E!E!kE!E"E"pE"E#-E#E#E$^E$E%6E%E&E&E'E'E'E(zE(E)~E*E*E+E+E,,E,E-KE-E.rE/E/E08E0E1nE2 E2E3JE3E4E52E5E6|E7#E7E8sE9E9E:qE;E;EE?.E?E@EAENE?E?E@dEAEAEB|EC0ECEDEEHEEEFEGbEHEHEIxEJ*EJEKELETEUEV&EVEWfEXEXEY9E-dE-AE-E,E,E,E,E,hE,BE,E+E+E+E+E+_E+9E+E*E*E*E*vE*NE*'E*E)E)E)E)`E)8E)E(E(E(E(qE(IE("E'E'E'E'E'ZE'3E' E&E&E&E&oE&HE&!E%E%E%E%E%bE%=E%E$E$E$E$E$`E$=E$E#E#E#E#E#lE#LE#*E# E"E"E"E"E"lE"LE"/E"E!E!E!E!E!E!jE!PE!7E!E!E E E E E E E jE GE EEEEXE+EEEE}ETE-EEEEEzEZEE#E$ E$vE$E%UE%E&>E&E'2E'E(0E(E)7E)E*HE*E+`E+E,E-E-E.DE.E/wE0E0E1RE1E2E3E>E?E@6E@EAEBWECECEDzEE2EEEFEGUEH EHEIvEJ+EJEKELHELEMENaEOEOEPsEQ EQER|ES'ESET|EU#EUEVrEWEWEXZEXEYEZ6E+E+E+dE+EE+&E+E*E*E*E*E*fE*FE*&E*E)E)E)E)E)^E)E?IE@E@EArEB+EBECEDXEEEEEFEG?EGEHEIlEJ$EJEKELLEMEMENpEO%EOEPEQAEQERESRETETEU\EVEVEWZEXEXEYJEYEZE[.E)E)E)E)E)tE)ZE)>E)$E)E(E(E(E(E(E(fE(JE(.E(E'E'E'E'E'E'gE'LE'/E'E&E&E&E&E&E&fE&IE&,E&E%E%E%E%E%E%dE%HE%+E%E$E$E$E$E$E$fE$LE$0E$E#E#E#E#E#E#tE#ZE#@E#&E# E"E"E"E"E"E"xE"_E"HE"0E"E"E!E!E!E!E!E!~E!iE!TE!AE!-E!E!E E E E E E E E zE jE JE EEEEeE9E EEEEiEBEEEEEEpEQE4EEEEEEEEEuEiE^EVEPEKEHEHEJEPEVE`EjEyEEEEEEE&EJEpEEEE*E`EEEE[EEE ;E E E!%E!zE!E"+E"E"E#OE#E$"E$E%E%uE%E&eE&E'`E'E(dE(E)tE)E*E+E+E,DE,E-sE.E.E/HE/E0E1.E1E2zE3$E3E4zE5&E5E6E74E7E8E9NE:E:E;oE<&ERE? E?E@EA>EAEBECtED1EDEEEFhEG$EGEHEI\EJEJEKELKEMEMENzEO2EOEPEQZERERESyET,ETEUEV>EVEWEXDEXEYEZ?EZE[E\*E(E(E'E'E'E'E'E'E'kE'VE'@E')E'E&E&E&E&E&E&E&vE&`E&HE&2E&E&E%E%E%E%E%E%zE%cE%KE%4E%E%E$E$E$E$E$E$|E$fE$NE$8E$!E$ E#E#E#E#E#E#E#nE#XE#BE#-E#E#E"E"E"E"E"E"E"oE"ZE"FE"2E"E" E!E!E!E!E!E!E!E!uE!dE!RE!AE!/E!E!E E E E E E E E E E wE jE LE EEEEkE@EEEEEsELE&EEEEE{E\E?E#EEEEEEEE|EpEdE[ETEPELELENEREXE`ElEzEEEEEEE$EGEnEEEE'E]EEEEXEEE :E E E!&E!{E!E"/E"E"E#WE#E$-E$E%E%E%E&vE&E'tE'E(~E)E)E* E*E+BE+E,lE-E-E.>E.E/}E0 E0E1lE2E2E3iE4E4E5tE6&E6E7E8@E8E9E:fE; E;E E>E?E@DEAEAEBECBEDEDEEEFCEGEGEHEIDEJEJEKELCEMEMEN}EO:EOEPEQmER&ERESETOEUEUEVnEW EWEXEY0EYEZE[2E[E\E]&E&PE&BE&0E&!E&E&E%E%E%E%E%E%E%E%zE%jE%XE%GE%7E%%E%E%E$E$E$E$E$E$E$E$wE$fE$TE$BE$2E$ E$E#E#E#E#E#E#E#E#E#rE#`E#OE#>E#-E#E# E"E"E"E"E"E"E"E"E"tE"dE"SE"DE"3E"#E"E"E!E!E!E!E!E!E!E!E!zE!lE!^E!PE!AE!3E!%E!E! E E E E E E E E E E E E uE iE NE "EEEErEHEEEEE~EWE2E EEEEEhEKE.EEEEEEEEExElEbE[EVEREQEREVE[EdEnE|EEEEEEE$EGEnEEEE'E^EEEEZEEE =E E E!+E!E!E"7E"E"E#bE#E$9E$E%E%E&E&E' E'E(E(E)$E)E*BE*E+hE+E,E-2E-E.pE/E/E0ZE1E1E2VE3E3E4`E5E5E6yE7.E7E8E9UE:E:E;EE?AE@E@EAEBGEC ECEDEETEFEFEGEHbEI&EIEJEKpEL3ELEMENxEO9EOEPEQxER5ERESETjEU$EUEVEWLEXEXEYhEZEZE[xE\$E\E]xE^ E$E$E$tE$jE$_E$TE$HE$2E>E?E@|EA@EBEBECEDXEEEEEFEGsEH;EIEIEJEKVELELEMENnEO2EOEPEQ{ER>ESESETEU>EUEVEWrEX-EXEYEZRE[E[E\jE]E]E^rE_E"E"E"E"E"E"E"E"E"E"E"E"E"zE"tE"nE"gE"aE"ZE"TE"NE"HE"BE";E"5E"/E"(E""E"E"E"E" E"E!E!E!E!E!E!E!E!E!E!E!E!E!E!E!E!E!E!E!E!E!E!zE!sE!mE!fE!`E!ZE!TE!NE!GE!@E!:E!4E!.E!(E! E!E!E!E!E!E E E E E E E E E E E E E E E E E E E E }E wE qE iE QE (EEEEEWE/EEEEElEHE#EEEEE~E`ECE'E EEEEEEEExEmEeE^EZEWEXEYE^EfEoE|EEEEEEEE@EhEEEE!EWEEEEUEEE E?hE@.E@EAEBECPEDEDEEEFwEGAEH EHEIEJkEK5EKELEMEN[EO$EOEPEQzERAESESETEUPEVEVEWEXPEY EYEZE[:E[E\E][E^E^E_kE`E!E!E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E ~E zE vE rE mE iE RE *E EEEE`E8EEEEExETE/E EEEEElEOE4EEEEEEEEEEtElEdE_E\E\E^EbEjErE~EEEEEEEE@EgEEEE EWEEEEVEEE >E E E!2E!E!E"FE"E#E#zE#E$[E$E%GE%E&BE&E'HE'E(ZE(E)xE* E*E+;E+E,tE-E-E.ZE/E/E0VE1E1E2dE3E3E4E5LE?E?E@EAqEB=EC ECEDEEnEF;EG EGEHEIrEJ?EK EKELEMuENAEO EOEPEQpER9ESESETEUYEVEVEWEXiEY*EYEZE[fE\"E\E]E^JE^E_E`cEaEEBEEEJELEPETEXE\E`EeEhEnErEwE{E~EEEEEEEEEEEEEEEEEEEEEEEEEEE E E E E E E E $E (E +E 0E 4E 8E E E E!4E!E!E"JE"E#E#E#E$eE$E%TE%E&RE&E'\E'E(rE)E)E**E*E+\E+E,E-E?E@PEAEAEBECEDXEE)EEEFEGEHkEI=EJ EJEKELEMQEN!ENEOEPEQ^ER,ERESETEU\EV%EVEWEX|EYCEZEZE[E\LE] E]E^E_YE?'E?E@EAEBgEC9ED EDEEEFEGXEH-EIEIEJEK}ELQEM&EMENEOEPsEQEERERESETEUWEV&EVEWEXEYTEZEZE[E\nE]0E]E^E_pE`,E`EaEbVEc EEEEEEEEEE-EE DE JE NE SE XE \E `E bE eE hE WE 2E EEEEvEPE+EEEEEsEPE-E EEEEEnERE6EEEEEEEEEE|ErEmEhEfEfEhEnEvEEEEEEEEEE?E@fEA8EB EBECEDEEaEF7EGEGEHEIEJlEKDELELEMENEOyEPOEQ%EQERESETxEUJEVEVEWEXEY\EZ'EZE[E\E]NE^E^E_E`\EaEaEbEcKEdEEEE$E6EHEZEnEEEEEEEEE$E8EMEbEwEEEEEEEE$E9EPEeE{EEEEEEEE(E>ETEiE~EEEEEEEE#E6EKE^ErEEEEEEEEEE&E6EFEVEfEuEEEEEEEEEEE E E E "E ,E 4E =E DE LE RE XE ^E dE hE XE 5E EEEE~EYE3EEEEE}E[E7EEEEEExE\E@E&E EEEEEEEEExEpElEiEjElEpEwEEEEEEEEE9E_EEEEENEEE EREEE AE E E!=E!E!E"[E"E#-E#E$E$E%E%E&E&E'E'E()E(E)PE)E*E+#E+E,hE-E-E.dE/E/E0xE1,E1E2E3ZE4E4E5E6_E7$E7E8E9E:JE;E;EYE?-E@E@EAEBEC[ED3EE EEEFEGEHtEIOEJ)EKEKELEMENpEOKEP%EPEQERESETaEU7EV EVEWEXEY]EZ.EZE[E\E]eE^0E^E_E`EaJEb EbEcEdEEdE+ECEYEpEEEEEEEE2EKEfEEEEEEEE8ESEmEEEEEEE,EHEbE~EEEEEE"E=EWErEEEEEEE+EDE^ExEEEEEE E"E:EQEhE~EEEEEEEE$E8EKE\EnEEEEEEEEEE E E E *E 4E >E GE QE XE `E gE YE 7E EEEEEaEE?E@nEAFEBEBECEDEEEFhEGEEH"EIEIEJEKELyEMWEN5EOEOEPEQERESdET@EUEUEVEWEX~EYTEZ)EZE[E\E]tE^BE_E_E`EanEb4EbEcEd|Ee:EeElEEEEEEE/ENElEEEEEE#EBEbEEEEEE#ECEdEEEEEE(EJEkEEEEEE/EOEqEEEEEE0EOEnEEEEEE$EBE_E|EEEEEE"ENE?'E@E@EAEBECpEDNEE,EF EFEGEHEIEJpEKPEL2EMEMENEOEPEQzERZES:ETETEUEVEWEXlEYFEZEZE[E\E]zE^NE_ E_E`EaEbVEcEcEdEepEf2EfEEEE E*ELEnEEEEEEAEdEEEEEEBEfEEEEE$EKEqEEEE E1EWE~EEEEE=EdEEEEE EEEjEEEEEECEfEEEEEE2EREsEEEEEE,EIEfEEEEEEEE6ENEdE{EEEEEEE E E "E 0E ?E KE XE bE XE 9E EEEEEnEKE'EEEEExEUE4EEEEEExE[EAE'EEEEEEEEEE}EvErEpEqEuEzEEEEEEEEE4EXEEEEEHEEEEPEEE DE E E!EE!E"E"kE"E#DE#E$.E$E%(E%E&1E&E'HE'E(nE)E)E*>E*E+E,-E,E-E.5E.E/E0VE1E1E2E3PE4E4E5E6lE79E8E8E9E:|E;PE<'EE?E@jEAHEB&ECECEDEEEFEGpEHSEI7EJEKEKELEMENEOxEP\EQAER%ESESETEUEVEWrEXREY/EZEZE[E\E]zE^QE_(E_E`EaEbpEc?Ed EdEeEfdEg(EgEE E2EXE~EEEEEBEjEEEEE9EcEEEEE8EcEEEEE=EiEEEEEEEqEEEE!ELExEEEE$ENEyEEEE!EJEsEEEEE;EbEEEEEEAEfEEEEEE/EOEoEEEEEEE6EPEhEEEEEEE E E #E 4E CE RE _E WE 9E EEEEEtEPE.E EEEEE^EE&E'ZE'E(E)E)E*ZE*E+E,NE,E-E.^E/E/E0E1BE2E2E3E4PE5E5E6E7E8QE9$E9E:E;E6E?E?E@EAEBECxED\EE@EF%EG EGEHEIEJEKELwEM_ENGEO/EPEPEQERESETEUEVfEWJEX.EYEYEZE[E\E]nE^KE_&E_E`EaEbEcUEd&EdEeEfEgVEhEhE*ESE|EEEE*EVEEEE E8EfEEEE$ESEEEEEFEvEEE EE?xE@ZEA=EB!ECECEDEEEFEGEHuEI`EJIEK4EL EM EMENEOEPEQERESxETcEUMEV5EWEXEXEYEZE[E\~E]`E^@E_ E_E`EaEbEceEd;EeEeEfEg~EhJEiEiEnEEEE*EZEEEE EREEEEETEEEE(E\EEEE5ElEEEEGE~EEE"EYEEEE4EkEEE EDExEEEELEEEEENEEEEEFEvEEEE2E`EEEEE9EcEEEEE&ELEpEEEEEE6ETEqEEEEEE E E 3E GE YE TE 8E EEEEE~E\E:EEEEEEnEME,E EEEEErEVEE8E8E9E:E;wEE>E?E@EAEBECtED^EEHEF3EGEH EHEIEJEKELEMENEOzEPiEQWERFES4ET!EUEUEVEWEXEYEZE[zE\aE]FE^+E_E_E`EaEbEckEdEEeEeEfEgEhlEi:EjEjE E EELEEEE"EXEEEE6EpEEEEVEEEEAE|EEE0ElEEE E\EEEENEEEE>E{EEE-EhEEEEREEEE7EoEEEELEEEE"EVEEEEEPEEEE E8EeEEEE E5E\EEEEEE2EREpEEEEEE E *E ?E SE PE 6E EEEEEEbE?EEEEEEvETE3EEEEEEzE]EBE(EEEEEEEEEEEyEvEtEvEzEEEEEEEEE*ENEwEEEE@E|EEELEEE GE E E!QE!E"E"E"E#cE#E$VE$E%ZE%E&oE&E'E(+E(E)fE*E*E+XE,E,E-iE. E.E/E0UE1E1E2E3mE49E5E5E6E7E8XE93E:E:E;EpE?UE@E|EEE4EtEEE1EpEEE2EsEEE7ExEEE>EEEEEEEE EKEEEEOEEEEOEEE EJEEEE?EzEEE,EeEEEEFE}EEEEPEEEEEFEuEEEE&EOExEEEEE3EVEvEEEEE E !E 9E OE NE 5E EEEEEEgEFE%EEEEE~E\EE{EEELEEE HE E E!UE!E"E"E"E#jE#E$aE$E%gE%E&E'E'E(@E(E)~E*#E*E+xE,&E,E-E.HE/E/E0E1HE2E2E3E4tE5FE6E6E7E8E9}E:\E;E?E@EAEBvECbEDQEE@EF0EG"EHEIEIEJEKELEMENEOEPEQERESET{EUpEVcEWVEXHEY:EZ,E[E\ E\E]E^E_E`EaEbvEcZEd?Ee EfEfEgEhEinEjBEkEkElE @E |E E E 4E sE E E 3E tE E E :E ~E EEGEEEE\EEE.EtEEEIEEEEdEEE:EEEEUEEE)EoEEE>EEE EPEEEEZEEEE^EEEEWEEE EEE~EEE&E\EEEE,E^EEEEEFEqEEEEE7EZE}EEEEE E /E HE HE 0E EEEEEEhEJE(EEEEEEaEAE EEEEEEiEME4EEEEEEEEEEE|ExEvEvEzEEEEEEEEE$EIErEEEE;ExEEEJEEE IE E E!WE!E" E"E"E#rE#E$jE$E%tE%E&E'"E'E(TE(E)E*>E*E+E,GE,E-E.nE/,E/E0E1xE2BE3E3E4E5E6XE72E8 E8E9E:E;E?E?(E@EAEAEBECEDEEEFEGEHEIEJzEKqELhEM`ENWEOOEPGEQAER9ES1ET(EU EVEWEXEXEYEZE[E\E]E^E_E`EatEb^EcIEd0EeEeEfEgEhEi|EjVEk0ElElEmEEE E NE E E E ^E E E .E vE E E NE E E *E tE EETEEE6EEEEfEEELEEE2E~EEEbEEEEEEE&EpEEENEEE&EnEEEBEEEESEEEEZEEEETEEEE>ExEEEENEEEEEDEqEEEEE@EeEEEEE E 'E BE DE -E EEEEEElENE,EEEEEEhEHE&EEEEEEnESE8EEEEEEEEEEE|ExEvEvEzEEEEEEEEE"EFEoEEEE8EvEEEIEEE IE E E!YE!E"%E"E#E#yE#E$tE$E%E& E&E'3E'E(iE) E)E*WE+E+E,gE-E-E.E/TE0E0E1E2tE3BE4E4E5E6E7rE8PE90E:E:E;EE?E@rEAaEBRECDED7EE,EF"EGEHEIEJEJEKELEMENEOEPEQERESETEUEVEWEXEYEZE[E\E]E^xE_lE`^EaNEb>Ec-EdEeEeEfEgEhEiEj`Ek>ElElEmEnEEEaEEE8EEE E ^E E E BE E E +E yE E E fE E E WE E EIEEE>EEE3EEE(EzEEEoEEEaEEEREEE?EEE(EvEEEZEEE8EEEEVEEE&EjEEE.EmEEE&EbEEE EDEzEEEEDEsEEEE"EKEqEEEEE E 9E =E (E EEEEEElENE/EEEEEElEKE+E EEEEErEVE;E"E EEEEEEEEE|ExEtEuExE}EEEEEEEEEBEkEEEE6EtEEEHEEE JE E E!\E!E")E"E# E#E#E$~E%E%E&E&E'DE'E(~E)"E)E*rE+ E+E,E-@E-E.E/~E0CE1 E1E2E3wE4LE5"E5E6E7E8E9wE:\E;BE<+E=E>E>E?E@EAEBECEDEEEFEGEHEIEJ|EKyELwEMtENrEOpEPnEQmERkESjEThEUfEVdEWaEX_EY\EZWE[RE\ME]FE^>E_6E`-Ea"EbEcEcEdEeEfEgEhEi|EjaEkDEl$EmEmEnEoE&EnEEEPEEE:EEE(EzEE E oE E E hE E E fE E E hE E E jE EEoEEEsEE!ExEE&E}EE(E~EE*E~EE(E|EE!EtEEEhEEEVEEE@EEE!EjEEEBEEEEREEEESEEEE@ExEEEEKE|EEEE2E[EEEEE E 1E 6E #E EEEEEEnEPE2EEEEEEqEPE0EEEEEEvEZE@E&EEEEEEEEEE}ExEtEtEvE|EEEEEEEEE@EhEEEE4EsEEEHEEE KE E!E!`E!E"/E"E#E#E$E$E%E%E&+E&E'WE'E(E)9E)E*E+VE?GE@:EA.EB#ECEDEE EFEGEGEHEIEJEKELEMENEOEPEQESETEUEVEWEXEYEZE[E\E]E]E^E_E`EaEbEcEdEeEfEgEhEipEjYEk@El%EmEmEnEoEp|EvEEEbEEEVEEEPEEEREEEYEE E bE E E rE E 'E E E 9E E E NE EEcEEEvEE/EEEAEEEREEE^EEEhEEElEEElEEEdEEEVEEE@EEE"EjEEE?EEE EJEEEE@EzEEE ETEEEEEBElEEEE E &E .E E EEEEEEnEQE3EEEEEEtESE3EEEEEEzE^EBE(EEEEEEEEEE}EvEsErEvEzEEEEEEEEE=EfEEEE1EoEEEFEEE LE E!E!cE!E"3E"E#E#E$E$E%E%E&9E&E'hE(E(E)OE)E*E+XE,E,E-E.DE/ E/E0E1fE28E3 E3E4E5E6tE7TE88E9E:E:E;EE?E@EAEBEC}EDxEEtEFrEGpEHpEIpEJrEKtELvEMzEN}EOEPEQERESETEUEVEWEXEYEZE[E\E]E^E_E`EaEbEcEdEeEfEgvEhhEiXEjHEk4ElEmEmEnEoEpEqiEEEpEEEoEEEuEE)EEE:EEEPEE ElEE *E E E JE E E lE E .E E E SE EEvEE8EEEZEEEzEE8EEEQEE EfEEEuEE'E~EE,EEE(EzEEElEEETEEE0ExEEEFEEEEEEEEE,EbEEEE(EUEEEEE E #E EEEEEEElEPE2EEEEEEuETE4EEEEEE{E^ECE)EEEEEEEEEEzEuEqEpErEwEEEEEEEEE9EaEEEE.EmEEEEEEE LE E!E!eE!E"7E"E#E#E$E$E%'E%E&HE&E'zE(E(E)fE*E*E+uE,-E,E-E.jE/0E/E0E1E2gE3=E4E4E5E6E7E8yE9aE:LE;9E<'E=E> E?E?E@EAEBECEDEEEFEGEHEIEJEKELEMEOEPEQERESET'EU/EV6EW>EXDEYLEZRE[WE\]E]`E^dE_gE`hEajEbhEcfEddEe_EfXEgPEhHEiEEEjEE0EEEUEEEvEE2EEEGEEETEEEYEEETEEEDEEE*EtEEEHEEEEPEEEEElEEEE E E EEEEEEEkEOE2EEEEEEwEWE7EEEEEE~EaEFE,EEEEEEEEEEzEtEpEoEpEvE~EEEEEEEE7E_EEEE,EjEEEDEEE ME E!E!jE!E">E"E#%E#E$$E$E%3E%E&WE&E'E(-E(E)}E**E*E+E,LE-E-E.E/VE0!E0E1E2E3oE4JE5(E6E6E7E8E9E:E;E[E?RE@LEAGEBCECAEDAEEBEFDEGGEHLEIREJXEK_ELgEMpENyEOEPEQERESETEUEVEWEXEYEZE[E]E^ E_E`EaEbEc#Ed#Ee"Ef!EgEhEiEjEjEkElEmEnEoEpEqzEr\EsEEEBEEE:EEE'EsEEEOEEEE\EEEEOEEEE$ETEEEE E E EEEEEEEfEKE/EEEEEEwEWE7EEEEEE~E`EEE+EEEEEEEEEExEqEmElEnErEzEEEEEEEE2E[EEEE)EhEEEDEEE NE E! E!mE!E"BE"E#-E#E$,E$E%?E%E&eE&E'E(@E(E)E*BE*E+E,jE-*E-E.E/|E0JE1E1E2E3E4~E5^E6BE7'E8E8E9E:E;EE?E@EAEBECEDEEEFEGEHEIEJEKELEMENEPEQER ES.ETEoEEEE EEEEEEE|EcEHE,EEEEEEwEVE8EEEEEE~EbEFE,EEEEEEEEEEvEoEjEjEjEoEvEEEEEEE E/EXEEEE'EfEEEDEEE PE E! E!pE!E"GE"E#4E#E$6E$E%KE%E&uE'E'E(TE(E)E*\E+E+E,E-JE.E.E/E0tE1FE2E2E3E4E5E6{E7bE8NE9E>E?E@EAEBECEEEF EGEHEI&EJ2EK>ELKEMZENhEOwEPEQERESETEUEVEWEY EZE[+E\:E]HE^WE_dE`pEa|EbEcEdEeEfEgEhEiEjEkElEmEnEoEpvEqfErVEs?Et(Eu E2EEE`EE0EEEnEEFEE EEEoEEPEE6EEEEEwEE`EEKEE5EE E E E E E jE E SE E ;E E"EEEyEE[EE;EEEEE]EE2EEEjEE4EEE\EEExEE/EEE8EEE2EEEEhEEE?EEEEAE}EEE#EVEEEEEEEEEEEtE\EBE&E EEEEEtETE5EEEEEE|E^EDE(EEEEEEEEE|ErEkEfEeEfEjErE|EEEEEEE*ESEEEE$EdEEEAEEE PE E!E!sE!E"ME"E#PE?ME@MEANEBRECVED^EEeEFnEGyEHEIEJEKELEMENEOEQERES.ETBEUUEViEW|EXEYEZE[E\E]E^E`EaEb,Ec8EdEEePEfZEg`EhhEimEjoEkqElqEmpEnjEodEp\EqPErBEs2Et Eu EuEEEeEE:EEEEEbEEDEE+EEEEEtEEdEETEEFEE:EE-EE!EEEE E E E xE E lE E ^E E NE EE?E@EAEBECEDEEEFEGEHEIEKEL EM4ENGEO\EPqEQERESETEUEVEXEY#EZ:E[PE\eE]zE^E_E`EaEbEcEdEfEgEhEi&Ej.Ek4El8Em:En:Eo8Ep5Eq0Er'EsEt EtEuEvEEbEE>EEEEEwEEbEEPEE@EE2EE)EE!EEEEEEEEEEEE EE EE E E E E E E E yE E qE EfEEZEELEE8EE#EE E{EE\EE8EEExEEGEEEtEE4EEEHEEENEEEBEEE%EnEEE6EvEEE$EZEEEEEEEEExEbELE3EEEEEEEkEME-EEEEEEvEZE>E"EEEEEEEEErEiEbE]E[E\E`EgErEEEEEEE EJEwEEEE]EEE?EEE QE E!E!yE!E"VE"E#IE#E$RE$E%nE&E&E'@E'E(E)E?E@EAEBED EEEF#EG2EHBEITEJhEK|ELEMENEOEPERESET6EUOEViEWEXEYEZE[E]E^E_0E`FEa\EbpEcEdEeEfEgEhEiEjEkElEnEoEpEqErErEsEtEuEvEwE^EE@EE&EEEEEyEEnEEfEEbEE`EE`EEcEEgEEmEEsEE{EEEEE EEEE E E !E E %E E (E E (E E%EE EEEEEEEvEEbEEHEE*EEErEEGEEEzEE?EEEXEE EbEE E[EEEAEEEETEEE ECExEEEEEEEElEXEBE*EEEEEEEfEHE*E EEEEEsEVE:E EEEEEEEE{EoEeE^EZEXEXE\EcEnE|EEEEEEEFEtEEEEZEEE>EEE SE E!E!}E!E"[E"E#PE#E$[E$E%|E&E&E'QE'E(E)RE*E*E+{E,0E?4E@9EAAEBJECVEDcEErEFEGEHEIEJEKELENEO1EPKEQfERESETEUEVEXEY+EZGE[cE\E]E^E_E`EbEcEd/EeFEfXEgmEh}EiEjEkElEmEnEoEpEqErEsEtEuEvEwExEEAEE-EEEEEEEE EE EEEEEE EE,EE9EEGEEWEEgEExEEEEE#EE3EE AE E NE E ZE E cE E jE EnEEoEEnEEhEE\EENEE:EE"EEErEEKEEEEELEEElEE"EzEE#EuEEE]EEE/EqEEE'E^EEEEEEEqE^ELE5EEEEEEE~E_EAE#EEEEEEnERE5EEEEEEEEEvEjE`EXETEREREVE^EgEuEEEEEEEBEpEEEEYEEE>EEE UE E!E!E!E"bE"E#YE#E$fE$E%E&"E&E'cE( E(E)hE*E*E+E,ZE- E-E.E/E0dE1=E2E2E3E4E5E6E7E8E9E:yE;vEzE?E@EAEBECEDEEEFEGEI EJ"EK:ELTEMnENEOEPEQERETEUE. E.E/E0E1fE2EE3(E4E4E5E6E7E8E9E:E;EE?E@EAEBEDEEEF'EG=EHTEImEJEKELEMENEPEQ7ERXESxETEUEVEWEY!EZCE[eE\E]E^E_EaEb'EcEEdcEeEfEgEhEiEjElEm En0Eo>EpKEqUEr^EsfEtiEujEviEwdEx^EyTEzHEE)EE&EE(EE.EE8EEHEEZEEpEEEEE2EEPEEpEEE$EEFEEiEEEEE@EEcEEEEE 2E E NE E iE E E E EEE+EE6EEEE:EE2EE#EEEEEbEEE5+E6E7 E8E8E9E:E;EE? E@EA"EB2ECBEDVEEkEFEGEHEIEJEL EM(ENHEOiEPEQERESEUEV;EW_EXEYEZE[E]E^;E_^E`EaEbEcEeEf%EgCEh`EizEjEkElEmEnEoEq ErEs$Et,Eu2Ev6Ew6Ex7Ey2Ez*E{ E%EE&EE-EE8EEJEE_EExEEE$EEDEEiEEE#EEMEEvE EE8EEdEEE&EEREE}EEE;EEbEE E E E :E E XE E tE EEEE$EE1EE8EE:EE6EE,EEEEEtEEQEE&EEEWEEEtEE&E}EE EnEEEIEEE EFEbEaE[EREHE;E-EEEEEEEEyE]EAE$EEEEEEsEVE:EEEEEEEE~EoE`ETEJEBE>EEBEHETEaEtEEEEEE2E`EEE EOEEE9EEE WE E!!E!E!E"qE"E#oE#E$E%E%E&KE&E'E(AE(E)E*dE+"E+E,E-{E.LE/ E/E0E1E2E3E4lE5ZE6LE7BE8:E95E:3E;4E<7E==E>FE?QE@_EAnEBECEDEEEFEGEIEJ.EKNELnEMENEOEPERESEETkEUEVEWEYEZ/E[VE\}E]E^E_EaEbE?E@EAEBECEDEFEG4EHPEIpEJEKELEMEOEPDEQkERESETEV EW7EXaEYEZE[E] E^3E_\E`EaEbEcEe"EfGEglEhEiEjEkEm En(EoCEp[EqpErEsEtEuEvEwExEyEzE{E|E EE2EEHEEcEEEEE=EEhEEE0EEeEEE6EEoE EEHEEE#EE`EEE=EEzEEESEEE*EEbEEE /E E `E E E #E E JE EmEEEEE.EE@EEJEENEELEEBEE0EEEEEaEE2EEEZEEEjEEEdEEEEEEE E*E+E'E"EEEEEEEEEEvE\EAE&E EEEEEzE\E@E&E EEEEEE~EmE\ENECE9E2E.E,E.E2E:EDEREeE{EEEEE'EWEEEEIEEE8EEE [E E!'E!E"E"~E"E#E$ E$E%.E%E&hE'E'E(hE)E)E*E+TE,E,E-E.E/dE0BE1!E2E2E3E4E5E6E7E8E9E:E;EE?E@EBECED6EEOEFlEGEHEIEJELEM8EN`EOEPEQESET.EUZEVEWEXEZ E[7E\dE]E^E_EaEb?EciEdEeEfEh Ei/EjREkwElEmEnEoEq Er$Es=EtPEubEvrEwExEyEzE{E|E}EE.EEJEEjEEE&EEREEEEETEEE-EEkE EEMEEE2EExEEE`EEEJEEE2EEuEEEYEEE7EEsE E E GE E zE E E @E EhEEEEE6EEKEEZEEbEEcEE\EEMEE6EEEEETEEE}EE5EEE7EEEEeEEE E E EEEEEEEEEE|EdEKE1EEEEEEElEQE4EEEEEEEEtEbEREDE8E.E(E#E"E$E)E0E;EJE\ErEEEEE!EQEEEEFEEE6EEE [E E!)E!E" E"E#E#E$E$E%9E%E&vE'E'E(yE)/E)E*E+nE,6E-E-E.E/E0dE1FE2-E3E4E4E5E6E7E8E9E:E;EE?E@&EA:EBQECjEDEEEFEGEIEJ'EKMELsEMENEOEQERFEStETEUEVEX,EY[EZE[E\E^E_GE`uEaEbEcEe*EfUEgEhEiEjElEm@EnbEoEpEqErEsEu EvEw2ExAEyNEzXE{`E|eE}fE~dE*EEJEEnEEE1EEdEEE8EEuEEEXEEE@EEE.EEyE EEmEEEbE EEXEEELEEE>EEE,EEsEEEWEE E 5E E nE E E ;E EhEEE"EEBEE\EEnEEzEE|EExEElEEVEE8EEExEEAEEEYEEEYEEE>EEEEEEEEEEEEEE~EhEQE8EEEEEEEzE]EBE&E EEEEEEzEhEVEFE8E.E$EEEEEE'E2EAETEjEEEEEEKEEEEAEEE4EEE \E E!,E!E"E"E#E#E$E$E%DE%E&E',E'E(E)CE)E*E+E,QE- E-E.E/E0E1lE2TE3@E40E5$E6E7E8E9E:E;E<'E=4E>CE?VE@jEAEBECEDEEEGEH7EI[EJEKELEMEO)EPUEQERESEUEVBEWrEXEYE[E\9E]kE^E_E`Eb0Ec_EdEeEfEhEiDEjnEkElEmEo Ep-EqNErmEsEtEuEvEwExEz E{E|#E}*E~-E.EEJEEtE EEE EpEEE0EETEEpEEEEEEEEEEEEzEE\EE5EEEeEE#E}EE)E{EEE]EEEEEEEEEEEEzEfEREEEE2EEE ]E E!/E!E"E"E#E#E$$E$E%PE%E&E'=E'E(E)XE*E*E+E,lE->E.E.E/E0E1E2|E3jE4\E5QE6JE7FE8FE9HE:NE;XEE?E@EAEBEDEE EFCEGfEHEIEJELEM1EN^EOEPEQESETNEUEVEWEYEZNE[E\E]E_E`TEaEbEcEeEfOEgEhEiEkEl6Em_EnEoEpEqEsEt9EuVEvsEwExEyEzE{E|E}E~EEJEExEEEFEEE"EEfE EEVEEEKEEEJEEEMEEEVEEEaEEEoEEE|E+EEE6EEE?EEEBEEEAEEE8EE E $E E iE E E FE E|EEEBEEjEEEEE,EE8EEE?E@EBEC-EDLEEnEFEGEHEJ EK4ELbEMENEOEQ ERSESETEUEW$EX[EYEZE[E]4E^kE_E`EbEcCEdxEeEfEhEiCEjsEkElEmEo(EpREqyErEsEtEvEw"Ex@EyXEznE{E|E}E~EEրEExEEENEEE2EEyE EEnEEEnEEEwE$EEE4EEEGEEE^EEExE*EEEDEEE[E EEnEEE~E,EEE3EEE2EE E )E E pE E E TE EE*EEZEEEEE6EEMEE\EEaEE\EEOEE8EEEEENEEEkEEEmEE ESE{EEEEEExEnEbEUEDE4EE EEEEEExE^ECE(EEEEEEEzEdEPE>E-EEEEEEEEEEEE$E8EOElEEEEE9EpEEE8EEE0EEE `E E!5E!E"E"E#E#E$8E$E%iE& E&E'^E(E(E)E*BE+E+E,E-vE.PE/,E0E0E1E2E3E4E5E6E7E8E9E:E;E,E?CE@^EA|EBECEDEFEG0EHZEIEJEKEMENHEO|EPEQESETVEUEVEXEYE E E 5E E |EEE\EEE,EEXEE|E EE EE,EE.EE&EEEEEdEE4EEEVEEE\EEE$E/E5E8E8E6E1E)E EEEEEEEEEyE`EHE/EEEEEEEEjEUEAE-EE EEEEEEEEEEEEE#EgE?E@EAEBEDEE)EFREG|EHEIEKEL9EMlENEOEQERGESETEUEW1EXmEYEZE\%E]bE^E_EaEbXEcEdEf EgHEhEiEjEl+EmbEnEoEpEr,EsZEtEuEvExEy$EzFE{eE|E}E~EEրEցEւEEdE EEXEEEYEEEfEEE~E3EEEXEEEE>EEEqE.EEEeE#EEE]EEEETEEEEGEEExE3EEE\EEEE2EEEHEE E PE E E NE E EE?E@EAEC"EDJEErEFEGEHEJ(EKZELEMENEP4EQlERESEUEV]EWEXEZE[WE\E]E_E`WEaEbEdEeSEfEgEi EjGEkElEmEo*Ep`EqErEsEu&EvREw}ExEyEzE|E}.E~JEdEրzEցEւEփEjEEE`E EEgEEEzE.EEEPE EE}E7EEEnE,EEEjE*EEElE.EEErE4EEEwE8EEExE7EEErE.EEE`EEEE?EEEZE E E iE E E jE E E^EEE@EEvEEE9EEZEErEEEEEEzEEfEEFEEEEE?EEEFEEEEEEEEEEEEEEEEEkEUE?E)EEEEEEEEkEUE@E+EEEEEEEEEEEEEEEEE E$EBEeEEEEEWEEE&EvEE*EEE eE E!BE!E"3E"E#E?EAEB@ECfEDEEEFEHEIEEJxEKELENEOSEPEQESETDEUEVEXEYCEZE[E]E^IE_E`EbEcQEdEeEgEhREiEjEl EmGEnEoEpEr'Es\EtEuEvExEyEEznE{E|E}E~EրEց(Eւ>EփPEք`EEElEEEvE(EEEFEEEnE'EEE^EEEE\EEEEeE)EEEuE9EEEEMEEEE`E#EEElE/EEEpE0EEEiE$EEEPEEEpE $E E E 4E E E 4E EE%EEfEEE8EEdEEEEE$EE,EE(EEEEEmEE?EEE`EEEbEEEEEEEEEEEEE~EmE\EIE5E E EEEEEE~EhEREEEOEEVEEQEEAEE$EEE`EE"E}EE*E\EkExEEEEEEEzEpEdEVEHE6E$EEEEEEEExEbELE7E"EEEEEEEEEEEEEEEEEEEE E+EPEwEEEEIEEEEpEE&EEE iE E!JE!E">E"E#ME#E$uE%E%E&^E' E'E(zE);E)E*E+E,lE-FE."E/E/E0E1E2E3E4E5E6E7E8E9E:E<E=E>4E?TE@vEAEBECEEEFEEGvEHEIEKELLEMENEPEQ>ER~ESEUEVCEWEXEZE[UE\E]E_&E`nEaEbEd?EeEfEhEiQEjEkEmEnVEoEpErEsFEtEuEvExEyNEz}E{E|E}EEր@Eց^Eւ{EփEքEօE܌E:EEޞEREEExE2EEEiE(EEEmE2EEEEHEEEEkE4EEEE_E*EEEEWE"EEEEKEEEEnE4EEEEIE EEEME EEE>EEE dE E E {E *E E E,EExEEEZEEE&EENEEjEE{EEEE{EEhEEJEEEEE@EEE#E5EBEMEUEXEYEXETEMEDE:E.E EEEEEEEEEqEZEEE0EEEEEEEEEEEEEEEEEEEEEEE EEEnEEEECEEEEnEE&EEE jE E!NE!E"EE"E#WE#E$E%E%E&mE'E'E(E)PE*E*E+E,E-bE.@E/$E0E0E1E2E3E4E5E6E7E8E: E;E<5E=PE>nE?E@EAECED-EE[EFEGEHEJ(EKaELEMEOEPTEQERETEU]EVEWEY-EZtE[E]E^KE_E`Eb#EckEdEeEgAEhEiEkElUEmEnEpEqXErEsEuEvFEw{ExEyE{E|AE}nE~EEրEւEփEք8EօQEֆdELEEܲEfEEEߐELEEEEHE EEEXE EEExECEEEEqE=E EEEuECEEEE{EIEEEEELEEEExEAE EEE]E"EEEjE)EEE`EEE E ?E E E TE E EXEEEIEEE$EETEE|E EE EE+EE*EEEEEmEE>EEE]EEEE EE E%E'E'E%E EEEEEEEEEEExEdEPE;E&EEEEEEEEEEE{EuErEpErEvE}EEEEEEEE8EcEEEE;E~EEEjEE$EEE lE E!RE!E"KE"E#_E#E$E%*E%E&|E'-E'E(E)bE*+E*E+E,E-|E.^E/CE0,E1E2E3E4E5E6E7 E8E9'E::E;PEE?E@EBEC?EDlEEEFEHEI8EJrEKELEN&EOeEPEQES,ETpEUEVEXEEYEZE\E]hE^E_EaFEbEcEe$EflEgEhEjEEkElEnEoZEpEqEsEtZEuEvEx Ey@EztE{E|E~E-EրWEց|EւEփEքEօEևEEE~E6EEݪEfE&EEEjE-EEEEJEEEEtEAEEEE{EJEEEEE_E/EEEEtEDEEEEERE!EEEETEEEEwE>EEEEJE EEEAEE E hE E E E .E EE,EEvEEEQEEEEE6EELEEUEEQEE@EE"EEE\EEEtEEEEEEEEEEEEEEEEEEEyEfESE>E*EEEEEEEEEE}ErEiEbE]EZEZE\E`EjEtEEEEEEE,EWEEEE2EvEEEeEE!EEE mE E!TE!E"PE"E#fE#E$E%6E%E&E'E@EA&EBPEC}EDEEEGEHHEIEJEKEM4ENuEOEPERE EEEtECEEEEE[E.EEEE|EPE$EEEEsEFEEEEE`E1EEEEjE6EEEE\E$EEEpE0EEEjE $E E E HE E E \EEEZEEEFEEEEECEEbEEuEE|EEwEEcEEBEEEvEE1EjEEEEEEEEEEEEEEEEpE`EOE=E+EEEEEEEEEEzEmEaEWEOEHEEEBEDEFELEUEbErEEEEEEEKE|EEE+EpEE EaEE EEE oE E!YE!E"VE"E#oE$E$E%CE%E&E'ME(E(E)E*UE+%E+E,E-E.E/E0lE1^E2VE3PE4NE5RE6XE7cE8qE9E:E;EEEEEjE8EEEExEJEEEEEpEEEEEEEuEKE"EEEE{EPE&EEEEvEHEEEEEVE#EEEEJEEEE\EEEE RE E E yE ,E E E9EEE1EEuEEEHEEqEEEEE#EE"EEEEEcEE0EEE(E?ESEbEpEyEEEEEEyErEhE]EPEBE4E$EEEEEEEEEExEhE\EOEDE;E4E.E,E*E,E0E6E@EOE^ErEEEEEE@EpEEE#EiEEE]EEEEE pE E!]E!E"]E"E#wE$E$E%OE%E&E'^E(E(E)E*lE+"E?HE@oEAEBECEE*EF^EGEHEJ EKHELEMEO EPREQERET(EUrEVEX EYVEZE[E]@E^E_Ea.Eb~EcEeEflEgEiEjVEkElEn:EoEpErEs\EtEuEw%ExcEyEzE|E}NE~EEրEւEփVE?|E@EAECED1EEeEFEGEIEJNEKELENEOVEPEQES.ETxEUEWEX^EYEZE\LE]E^E`?EaEbEd1EeEfEh$EitEjElEm_EnEoEqBErEsEuEv_EwExEz"E{aE|E}E Eր>EցqEւEփEքEֆEև>Eֈ\E։zEqE.EEװEsE8EEEےE\E)EEEߗEhE;EEEEEfE>EEEEE}EYE4EEEEE~EYE4EEEEExEQE*EEEEEYE.EEEEqE@E EEEiE0EEEzE:EE E nE %E E E @E EEEEEE4EEpE EE6EEVEEgEEnEEfEEPEE-EEEZEEEEEEEEE E E EEEEEEEEEEEEExEhEXEJEE?E@EBEC:EDlEEEFEHEIREJEKEMENYEOEPER1ES|ETEVEWdEXEZE[TE\E]E_IE`EaEcAEdEeEg9EhEiEk-El}EmEoEphEqErEtHEuEvExEy_EzE{E}E~VEEրEցEփ&EքTEօEֆEևEֈE֊ EVEEE֜EaE*EEټEڈEVE%EEEޚEmEBEEEEExESE-E EEEE{EXE6EEEEEEjEGE$EEEEEoEJE#EEEEEUE)EEEElE:EEEE`E&EEElE )E E E XE E E pEEEuEEEbEEE6EE`EE}EEEEE EEElEEDEE EKEgEEEEEEEEEEEEEEEEEEEvEhEZELE=E/E"EE EEEEEEEEEEEEEE E E7ESErEEEEELEEE ESEEEQEEEEE vE E!jE!E"pE"E#E$.E$E%vE&#E&E'E(OE)E)E*E+E,^E->E."E/ E/E0E1E2E3E4E5E6E8 E9 E:8E;TEE?EAEB@ECrEDEEEGEHTEIEJELEMYENEOEQ0ER{ESEUEVdEWEYEZVE[E\E^OE_E`EbKEcEdEfHEgEhEjBEkElEn7EoEpEr"EsnEtEvEwKExEyE{E|YE}E~EրEցBEւwEփEքEֆEև.EֈTE։wE֊EDEEEՑEWE EEظEهEWE(EEEݢExEPE(EEEEEmEJE'EEEEEEbEAE"EEEEEE`E@EEEEEEnEJE$EEEEEWE*EEEElE8EEEEYEEEE ^E E E E @E E EREEEMEEE/EEbEEEEE+EE2EE+EEEEEWEEEE3EIEkExEEEEEEEEEyEqEfE\EPEDE6E)EEEEEEEEEEEEEEEEEEEEEE!E=E^EEEEE>EyEEEIEEEKEEEEE vE E!lE!E"vE#E#E$6E$E%E&1E&E'E(`E)'E)E*E+E,vE-VE.E@EAFEBvECEDEFEGTEHEIEKELVEMENEP-EQxERETEUbEVEXEYVEZE[E]PE^E_EaPEbEcEeREfEgEiREjEkEmLEnEoEq@ErEsEu*EvvEwEyEzME{E|E~ENEրEցEւEք,Eօ\EֆEևEֈE֊E֋ E:EEEԌEVE"EE׾E،E]E2EEEܱE݊EbE>EEEEEElEKE+E EEEEEtEVE8EEEEEEEcECE"EEEEEvERE,EEEEE\E0EEEEmE8EEEETEEE E NE E E tE &E EE/EE|E EE[EEE EE>EENEEQEEFEE-EEEiEEEEEE!E0E:EBEHEKELEJEHEDE>E6E.E%EEEEEEEEEEEEEEEEEEEEEEEEEE E*EKEpEEEE2EnEEEBEEEHEEEEE zE E!rE!E"~E#E#E$CE$E%E&@E&E'E(tE)EEEEܞEyEUE2EEEEEErETE6EEEEEEEoESE7EEEEEEEjEKE,E EEEEE\E6EEEEEdE6EEEEnE8EEEEJE E E E %E?PE@|EAEBEDEENEFEGEIEJJEKELENEOhEPERESRETEUEWGEXEYE[FE\E]E_KE`EaEcTEdEfEg]EhEj EkdElEnEoeEpEr Es^EtEuEwLExEyE{*E|qE}E~Eր8EցvEւEփEօ EֆSEևEֈE։E֋E֌%E:EEEҔEcE2EEE֧E~ERE,EEEۻEܗEvESE4EEEEEEEfEJE/EEEEEEEvE\EAE&E EEEEE{E\EEXEoEEEEEEEEEEEEEEEEEEEEzErEjEbEZEUEPELEJEJEJEMEREZEdEpEEEEEEE"EIEvEEEETEEE0EEE>EEEEE |E E!zE!E"E#E#E$XE$E%E&^E'E'E(E)cE*2E+E+E,E-E.E/E0tE1lE2hE3jE4oE5yE6E7E8E9E:E<E=-E>VE?E@EAECEDLEEEFEHEIDEJEKEMEN^EOEPERFESETEVE?E@EBECHEDEEEFEH:EI|EJELEMRENEOEQ7ERESEU,EVEWEY,EZE[E]5E^E_EaCEbEcEeSEfEh EicEjElEmpEnEp EqvErEt EurEvExEycEzE{E}DE~EEցEւREփEքEֆEև8EֈlE։E֊E֋E֍ETE EEкEъE\E0EEEմE֎EhEEE#EEEEܤE݇EjEOE4EEEEEEEEoEWE@E*EEEEEEEEjEQE6EEEEEEEiEHE%EEEEEeE:EEEE~EJEEEEjE,EE E eE E E E :E EE=EEE'EE^EEEEE0EE8EE3EEEEEBEhEEEEEEE EE E(E-E0E2E2E1E.E,E'E#EEEE EEEEEEEEEEEEEE E/EBEXEpEEEEE EOEEEE9EEEEuEE4EE EEE E!E!E" E"E#/E#E$nE%E%E&{E'7E'E(E)E*]E+5E,E,E-E.E/E0E1E2E3E4E5E6E7E9E:E;E?EAEBCECzEDEEEG.EHpEIEJELBEMENEP&EQvERETEUnEVEXEYqEZE\#E]}E^E`3EaEbEdFEeEfEhZEiEkElkEmEoEpwEqEs%EtzEuEw"ExsEyE{E|\E}E~Eր4EցxEւEփEօ5EֆoEևEֈE֊E֋6E֌bE֍EpE;E EEЪE}ERE(EEEյE֑EnEME/EEEEܹEݞEބEjEQE8E E EEEEEEEnEXEBE,EEEEEEEEnETE9EEEEEEE`EE@EA?EBtECEDEF$EGdEHEIEK2EL|EMEOEPbEQESETZEUEWEX\EYE[E\iE]E_ E`{EaEc4EdEeEgLEhEjEk`ElEnEorEpEr$Es{EtEv&Ew{ExEzE{lE|E~ENEրEցEփEք\EօEֆEֈ E։BE֊rE֋E֌E֍E̐E\E,EEEФE|ERE,EEEE֠EEaEBE'E EEEݽEޤEߍEuE_EHE4EE EEEEEEEwEcELE8E!E EEEEEEvEYE>EEEEEEzETE.EEEEETE#EEEELEEEE RE E E ~E 2E E E>EEE0EElEEE0EELEEZEEZEELEE.EyEEEEEE6EKE]ElExEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE4ESEuEEEE'E]EEEEgEE EdEE*EEEEE E! E!E"E"E#CE#E$E%1E%E&E'ZE(E(E)E*E+fE,DE-)E.E/E/E0E1E2E3E4E6 E7E86E9PE:nE;E E?8E@iEAEBED EEJEFEGEIEJVEKELEN7EOEPER)ES}ETEV*EWEXEZ5E[E\E^JE_EaEbcEcEe EfEgEi=EjEkEmVEnEpEqkErEtEuvEvEx#EyxEzE|E}hE~EրEցJEւEփEօEֆVEևEֈE֊E֋6E֌hE֍E֎EE˺ĚE_E3E EEмEіEuERE2EEEE׻EآEوEnEWE@E*EEEEEEEEEuEcEOE=E+EEEEEEEEErE[ECE*EEEEEEE`E>EEEEEETE&EEEE`E*EEExE8EE E jE !E E E 4E EE.EEoE EE:EE\EEpEEtEEjEESEEEEE:EYEtEEEEEEEEEEEEE E E EEEEEEEEE"E)E1E:EFEREbEsEEEEEEE4E?cE@EAECEDEEEKEEEEE~E E E!E!E",E"E#_E$E$E%[E&E&E'E(VE)$E)E*E+E,E-xE.eE/VE0NE1JE2JE3NE4XE5fE6xE7E8E9E:E< E=4E>`E?E@EAEC0EDlEEEFEH.EItEJELEMTENEOEQEERESEUFEVEWEYSEZE\ E]iE^E`&EaEbEdFEeEgEhfEiEk&ElEmEoCEpEqEsYEtEv EweExEzE{fE|E~ EWEրEցEփ7Eք~EօEևEֈ@E։|E֊E֋E֍E֎KE֏xEdE6EEE̴E͌EfEAEEEEҼEӟEԂEgELE3EEEEEEܭEݚEކEsE`ENEEcEEEEEEEE#E2E>EHEREZEbEhEnEuEzEEEEEEEEEEEEEEEE4EMEjEEEEE-E]EEE ELEEE/EEE@EEEEE|E E E!E!E"3E"E#gE$ E$E%gE& E&E'E(hE)7E* E*E+E,E-E.E/rE0jE1hE2iE3nE4xE5E6E7E8E9E; E<2E=\E>E?E@EB"EC\EDEEEGEH^EIEJEL8EMENEP&EQyERET$EU|EVEX0EYEZE\EE]E_E`bEaEc"EdEeEgDEhEjEkfElEn&EoEpErAEsEtEvSEwEyEzZE{E}E~REEրEւE(EEEEEE߰EEEyEhEVEDE2E!EEEEEEEEErE\EFE/EEEEEEEmEME,EEEEElEAEEEEENEEEEdE$EEE WE E E qE E E tEEE\EEE&EEIEE^EEcEE[EE$EVEEEEEE8ESElEEEEEEEEEEEEEE(E0E8EBELEVEaEmEzEEEEEEE E(EHEjEEEEEKEEEEFEEE0EEEHEE EEEE E E!1E!E"OE"E#E$.E$E%E&FE'E'E(E)bE*8E+E+E,E-E.E/E0E1E2E3E4E5E6E7E9E:"E;FEE?EA&EB\ECEDEFEGSEHEIEK(ELrEMEOEP`EQESET^EUEWEXhEYE[E\|E]E_9E`EaEcXEdEfEgzEhEj:EkElEnYEoEqErsEsEu*EvEwEy5EzE{E}2E~EEց EւlEփEքEֆ>EևEֈE։E֋6E֌lE֍E֎E֏E EEɰEʆE[E3EEEEϤEЄEeEHE)EEEEEשEؒE|EfEQE=E*EEEEEEEEEEqE^ELE9E&EEEEEEEE{EbEHE.EEEEEEvETE.EEEEE_E0EEEEbE*EEErE1EEE \E E E qE E E mEEENEEEEE1EE@EEBEE5EEEEEDElEEEEEEE0EDEVEfEvEEEEEEEEEEEE EE*E:ELE`EvEEEEEE#EJErEEEE9EtEEE>EEE0EEEPEE,EEEE +E E!IE!E"kE#E#E$PE$E%E&kE'+E'E(E)E*dE+?E, E-E-E.E/E0E1E2E3E4E5E7E8E9:E:YE;|EE@*EA^EBECEE EFIEGEHEJEK^ELEMEOFEPEQES=ETEUEWCEXEYE[TE\E^E_lE`Eb*EcEdEfJEgEi EjjEkEm*EnEoEqDErEsEuWEvEx Ey`EzE| E}]E~EEցJEւEփEօ%EֆiEևEֈE֊&E֋`E֌E֍E֎E֐(EjEE?2E@bEAEBEDEEBEFEGEIEJMEKELEN-EO|EPERESsETEVEWxEXEZ+E[E\E^@E_E`Eb[EcEeEfyEgEi8EjEkEmVEnEpEqpErEt'EuEvEx4EyEzE|2E}E~Eր$EցrEւEքEօLEֆEևE։E֊LE֋E֌E֍E֏ E֐NEEǟEsEHEEEE̪E͆EdEBE$EEEEӮEԕE{EcEJE3EEEEEEݳEޠEߌEyEfESE?E,EEEEEEEEEuE_EHE0EEEEEEEoENE.E EEEEtEJE EEEE`E,EEEEFEEEE;E?hE@EAECED=EEzEFEGEI>EJEKEMENbEOEQERSESETEVREWEYEZ\E[E]E^pE_Ea+EbEcEeGEfEhEieEjEl#EmEnEpEEEENE EEErE?E@EBEC:EDtEEEFEH/EIsEJELEMKENEOEQ4ERESEU.EVEWEY3EZE[E]BE^E_EaXEbEdEerEfEh/EiEjElJEmEoEpbEqEsEttEuEw%Ex~EyE{(E|yE}EEրjEցEփEքFEօEֆEֈE։PE֊E֋E֌E֎.E֏bE֐EŵEƆEXE,EEEʰEˋEfEBE EEEEѣE҆EjEOE5EEEEEټEڤEێExEcEME8E#EEEEEEEEzEdELE5EEEEEEEEeEGE(EEEEE|EVE/EEEEERE!EEEEJEEEEREEEE7EEE IE E E DE E E %E EVEE|E EEEE#EEE;EuEEEE?EkEEEEE&EFEcEEEEEEEE6EPEhEEEEEE E(EFEhEEEEE*EVEEEE(EdEEE.EyEEErEE.EEElEE[EE`EE |E!E!E"@E"E#E$(E$E%E&EE'E'E(E)fE*E?EAEB9ECpEDEEEG"EHdEIEJEL4EM~ENEPEQfERET EU^EVEX EYbEZE\E]nE^E`&EaEbEdEqEEEE(EOEvEEEEEE>E\EyEEEEEE"E@E^E|EEEEE$EJEsEEEE)E\EEEEFEEEEgEEEiEE,EEErEEeEEpEE E!*E!E"[E"E#E$GE$E%E&jE'+E'E(E)E*gE+CE,#E- E-E.E/E0E1E2E3E4E5E6E8E9*E:HE;hEE@ EA:EBnECEDEFEGVEHEIEKELfEMENEPGEQERET8EUEVEX6EYEZE\>E]E^E`NEaEcEdcEeEgEhzEiEk3ElEmEoHEpEqEsXEtEv Ew`ExEz E{]E|E~ENEրEցEփ0EքxEօEևEֈ?E։~E֊E֋E֍)E֎[E֏E֐EĺEŊEZE.EEEɯEʆEaE;EEEEϳEВErEVE8EEEEEױEؘEEfENE6EEEEEEEE|EdELE4EEEEEEE~EbEDE&EEEEEE_E:EEEEElE?EEEEyEDE EEEZEEEEQEEErE#EE~E (E E sE E E OE E EEE/EE@EEEEEE&EbEEEE7EgEEEEE5EZE~EEEEE$EDEbEEEEEE'EJEmEEEE E6EdEEEE1EjEEE)EnEEEWEEEbEE*EEExEEpEEE E E!?E!E"uE#E#E$hE%E%E&E'RE(E(E)E*E+oE,QE-9E.#E/E0E1E1E3E4E5E6E71E8FE9`E:|E;EE?EE@rEAEBED EECEF~EGEHEJEEEREEEPEE E 8E E pE E E .E EJEEYEEAEEE EKEEEE,E_EEEEEEEpEEEEE8E_EEEEE#ELEtEEEE$ETEEEE#E\EEEEZEEE6EEE2EEEOEE"EEEEEE EE 1E E!kE" E"E#ME#E$E%\E&E&E'E(hE)9E*E*E+E,E-E.E/tE0iE1dE2bE3eE4lE5vE6E7E8E9E:E<E=(E>NE?yE@EAECED=EEtEFEGEI,EJlEKELENE!EEEEEEgEFE%EEEEEnEFEEEEEpEBEEEEyECE EEEZEEEETEEE{E/EEE;EEE2EE vE E E HE E pE E EEE#EEEE]EEEESEEEE(EXEEEEE>EjEEEEE>EiEEEEEFEvEEE E>EvEEE$EdEEE1EzEEEkEEE{EEDEEEEEEEEEE @E E!E"!E"E#gE$E$E%|E&8E&E'E(E)`E*6E+E+E,E-E.E/E0E1E2E3E4E5E6E7E8E9E;E<6E=ZE>E?E@EBEC8EDnEEEFEHEIYEJEKEM"ENhEOEPERGESETEV4EWEXEZ,E[E\E^,E_E`Eb3EcEdEf>EgEhEjJEkElEnUEoEqEr\EsEuEv\EwEyEzTE{E|E~AEEրEւEփfEքEօEև.EֈmE։E֊E֌E֍PE֎E֏E֐EEEİEŀEPE"EEEɞEtEKE#EEEβEώEhEFE$EEEEգEփEdEEE'E EEEܰEݓEuEXE:EEEEEEEeEFE&EEEEE|EXE2E EEEElE@EEEEEXE%EEEELEEEEZEEEEJEEEiEEEvE EEnEEE PE E E E E @E E YE EgEEEdEEE0EoEEEEWEEEE'EXEEEEEDErEEEE+EZEEEE ETEEEE3EoEEE0EvEEEUEEEPEE EjEE:EEEE EEEE&EE RE E!E"9E"E#E$1E$E%E&\E' E'E(E)E*bE+>E, E-E-E.E/E0E1E2E3E4E5E6E7E9E:-E;JEE?EA EB8ECjEDEEEGEHJEIEJEL EMNENEOEQ&ERqESEU EVZEWEXEZPE[E\E^ME_E`EbQEcEeEfYEgEi EjaEkEmEniEoEqErmEsEuEvjEwEyEz^E{E|E~HEEրEւ&EփjEքEօEև2EֈnE։E֊E֌E֍PE֎E֏E֐EEÌEXE&EEEǖEhEE@EA:EBhECEDEFEG=EHxEIEJEL6EMyENEPEQNERESEU1EVEWEYEZqE[E]E^lE_EaEblEcEeEfpEgEiEjvEkEm#EnzEoEq&ErzEsEu"EvuEwEyEzhE{E}E~MEEրEւ(EփmEքEօEև2EֈoE։E֊E֌E֍LE֎~E֏E֐EnE8EEEŝEnE>EEEɴEʇE\E2EEEθEϔEmEGE"EEEԶEՓEqENE,E EEEۦE܅EcEBE EEEEEwEUE2EEEEE|EVE.EEEEEaE4EEEE|EJEEEEzEBEEEETEEEENEEEvE*EEEEEE0EEE8EEE^EE1EEEEEEEEEEDEE E!%E!E"yE##E#E$E%?E%E&E'E(VE))E)E*E+E,E-E.uE/gE0\E1TE2RE3TE4XE5aE6nE7}E8E9E:E;EE?FE@nEAEBECEE*EF_EGEHEJ EKJELEMEOEPTEQERET.EUxEVEXEY`EZE\E]SE^E_EaJEbEcEeFEfEgEiDEjEkEmBEnEoEq>ErEsEu3EvEwEy"EznE{E}E~PEEրEւ$EփhEքEօEև'EֈbE։E֊E֌ E֍OE?tE@EAEBED%EEWEFEGEHEJ7EKtELEMEO6EPzEQESETPEUEVEX1EYEZE\E]mE^E`Ea`EbEdEeXEfEhEiREjEkEmLEnEoEqCErEsEu6EvEwEy!EzlE{E}E~JEEրEւEփ`EքEօEևEֈWE։E֊E֋E֍,E֎\E֏E֐EEfE,EEĽEʼnETE EEȺEɉEXE)EEE͠EsEGEEEEҜErEHEEEEצE}EUE.EEEܶEݏEgE>EEEEErEHEEEEEqEEEEEEE[E*EEEE\E&EEE~ECEEEENE EEEBEEEhEEEE0EEE3EEE$EEfEEE:EEeEE E E E E jE E E cE E E KE E E%EjEEE7EyEEE>E~EEE@EEEEHEEEEZEEE5EEEEpEEErEE)EEEQEE%EEE}EEtEEzEEE$EEVEE E!EE!E"E#PE$E$E%yE&;E'E'E(E)rE*LE+*E, E,E-E.E/E0E1E2E3E4E5E6E7E8E:E;E<;E=ZE>|E?E@EAEC"EDPEEEFEGEI&EJ_EKELENEO\EPEQES*ETqEUEWEXOEYEZE\7E]E^E`%EavEbEdEekEfEhEiaEjElEmWEnEoEqKErEsEu9EvEwEy!EzkE{E|E~GEEրEւEփVEքEօEևEֈJE։E֊E֋E֍ E֎NE֏|E֐EiE,EEøEEHEEEǨEtE@EEEˬE{ELEEEEГEgE:EEEԷEՌEaE6E EEٷEڍEcE9EEE޺EߏEdE9EEEEE]E0EEEEuEDEEEE~EJEEEEpE8EEEEJE EEEJEEE{E3EEETEEEeEEEfEEEXEEE8EEmEEE/EE NE E NE E E UE E E JE E E 1E |E EEUEEE&ElEEE:E~EEEMEEE!EjEEEHEEE3EEE.EEEE?E@EB"ECNED|EEEFEHEINEJEKEMEN?EOEPERESJETEUEW"EXlEYE[E\PE]E^E`:EaEbEd)EezEfEhEimEjElEm_EnEoEqNErEsEu8EvEwEyEzgE{E|E~E?EA$EBNECyEDEEEG EH?EIvEJEKEM&ENcEOEPER'ESjETEUEW>EXEYE[E\fE]E_E`MEaEbEd9EeEfEh&EivEjElEmcEnEpEqOErEsEu6EvEwEyEz_E{E|E~2EuEրEցEփ9EքxEօEֆEֈ&E։]E֊E֋E֌E֎"E֏NE֐yEEE‰ELEEEŚEaE(EEȺEɃEMEEE̮EzEHEEEвEсEOEEEԾEՏE_E0EEE٢ErECEEEݵEޅEVE&EEEEbE1EEEEfE1EEEE\E$EEEzE@EEEELE EEEHEEEzE3EEETE EEkEEEtEEEnEEEYEEE4EEgEEE%EEFEE E vE E *E E E ,E E E "E qE E E ]E E EBEEE&EtEE EYEEEEEEE9EEE8EEEFEEEdEE.EEEoEESEEDEEAEELEEfEEE*EEmE E E!qE"&E"E#E$JE% E%E&E'`E(0E)E)E*E+E,E-kE.ZE/JE0?E18E24E33E46E5=E6GE7TE8eE9xE:E;EEEE^EE'EEEdEEFEE0EE(EE-EE?EE^EEE,EEtE E E!E"8E"E#E$cE%"E%E&E'~E(QE)'E*E*E+E,E-E.E/sE0jE1bE2`E3`E4dE5jE6tE7E8E9E:E;EE?0E@SEAxEBECEDEF(EGXEHEIEJEL0EMjENEOEQ"ERcESETEV,EWrEXEYE[FE\E]E_#E`nEaEcEdQEeEfEh5EiEjElEmgEnEoEqJErEsEu)EvrEwEyEzFE{E|E~EUEրEցEփEքNEօEֆEևE։,E֊`E֋E֌E֍E֏E֐?EE|E;EEøEzE:EEEǂEGE EEʗE^E$EE͵E|EFEEEѢEmE7EEE՘EbE.EEEِE[E&EEܼE݇ESEEEE{EDEEEEhE/EEEEHE EEEXEEEE\EEEERE EEE8EEEZEEEqE"EE~E*EE~E&EEpEEEVEEE-EE_EEEEE&EEEJEE E aE E E lE E E oE E E nE E E jE EEdEEEbEEEgEEEtEE,EEEMEEE~EESEE2EEEEEE EEEE0EEVEEE-EEzE 'E E!E"HE#E#E$yE%;E&E&E'E(pE)IE*#E+E+E,E-E.E/E0E1E2E3E4E5E6E7E8E9E:E<E=E>:E?ZE@|EAEBECEE EFOEGEHEIEKELSEMENEPEQBERESEUEVFEWEXEZE[[E\E]E_3E`|EaEcEd[EeEfEh;EiEjElEmgEnEoEqFErEsEu EvgEwExEz8E{|E|E~EAEրEցEւEք5EօoEֆEևE։E֊BE֋tE֌E֍E֎E֐ EE`EEEØEUEEEƕEVEEEɞE`E%EE̮ErE9EEEЋEREEEөEqE9EEEגEZE$EEڴE}EEE EEޝEdE,EEEEFE EEEZEEEEgE(EEEjE)EEEbEEEEMEEEtE(EEECEEESEEEXEEEREEE@EEE EEYEEE!EEJEEXEE EEEDEEE [E E E jE E E tE E #E zE E *E E E0EEEbE?E@EAEBEDEEFEFtEGEHEJEK=ELtEMENEP"EQ^ERESEUEV\EWEXEZ(E[mE\E]E_AE`EaEcEdcEeEfEh?EiEjElEmeEnEoEq?ErEsEuEv[EwExEz(E{lE|E}E,EրjEցEւEքEօTEֆEևEֈE֊$E֋TE֌E֍E֎E֏EEFEE¸EvE1EEŬEjE(EEȨEhE*EEˬEoE1EEθE{E@EEEҍEREEEբEgE-EEطE}ECEEEܓEXEEEߦEjE/EEEyE;EEEEBEEEE@EEEyE5EEEeEEEEEEEEdEEEyE*EEE3EEE3EEE&EEmEEENEEE!EEREE{E EEEXEE EEEDEE E ^E E E tE E +E E E EEFEEYEEyEEEAEEE*EEE 4E E!E"dE##E#E$E%hE&3E'E'E(E)E*eE+HE,.E-E.E.E/E0E1E2E3E4E5E6E8E9E:%E;;EE?E@EAECEDBEElEFEGEHEJ*EK^ELEMEOEP>EQzERESEU4EVsEWEXEZ:E[}E\E^E_ME`EaEc"EdiEeEfEhAEiEjElEmaEnEoEq6Er}EsEuEvMEwExEzE{VE|E}EEրREցEւEփEօ6EֆlEևEֈE֊E֋2E֌]E֍E֎E֏ExE.EEžEXEEEňEDEEǼEyE9EEʵEtE3EEͳEtE6EEиEyE;EEӿEԂEDEEE׌ENEEEږEXEEEݟEaE"EEEfE&EEEfE%EEE`EEEEREEEE;EEEcEEEE8EEENEEE^E EEcEEE`EEEREEE:EExEEELEE}EEEEEEzEEVEE7EE!EEEEEEEE!EEE?E@EBEC>EDfEEEFEGEIEJLEK~ELEMEO EPZEQERET EUJEVEWEY EZLE[E\E^E_ZE`EaEc*EdoEeEfEhCEiEjElEm]EnEoEq-ErrEsEtEv>EwExEzE{BE|E}E~Eր7EցrEւEփEօEֆNEևEֈE։E֋E֌;E֍fE֎E֏EjE EEŒECEEıEjE$EEǘESEEEʆECEE̽EzE7EEϴEqE0EEҮEmE-EEիEjE*EEتEiE(EEۧEfE%EEޣE`EEEEXEEEEJEEE|E6EEEbEEEE?EEE^EEEwE(EEE8EEE@EEE?EEE4EE~E!EEeEEE@EExEEE@EEjEEWEE+EEEcEE.EEEYEE E E E GE E E nE E 6E E E dE E0EEEjEEBEEEEEvEEdEEZEEWEE_EEpEEEEELEEE(EEvE#EEE >E E!E"|E#?E$E$E%E&aE'3E( E(E)E*E+E,qE-\E.LE/?E04E1.E2*E3*E4,E52E6:E7DE8RE9dE:vE;EE?EAEB>ECdEDEEEFEH EI:EJlEKELENEOE֎dE֏EbEEE}E0EEĜEQEEEvE/EEɠEZEEĖEBEEηEsE.EEѦEaEEEԖEREEE׈EDEEټExE4EEܬEiE$EEߛEVEEEE>EEEjE#EEEJEEElE"EEE>EEETEEEeEEEpEEEsEEEnEEEbEEEMEEE/EEkEEEEBbECEDEEEGEH,EIZEJEKELEN!EOVEPEQERET8EUtEVEWEY+EZjE[E\E^*E_lE`EaEc2EdvEeEfEh?EiEjEl EmLEnEoEqErVEsEtEvEwXExEyE{E|OE}E~EEց6EւlEփEքEֆEև9EֈgE։E֊E֋E֍E֎;E֏`E]EEErE$EEĊE=EEƦE\EEE|E2EE˟EVEEE}E6EEЧE`EEEӊECEEյEoE'EEؚESE EE~E6EEݨE`EEEE?EEEdEEEEE?$E@CEAbEBECEDEEEG EHLEIxEJEKEMEN;EOpEPEQESETLEUEVEWEY9EZvE[E\E^3E_rE`EaEc5EdvEeEfEh;Ei}EjElEmBEnEoEqErFEsEtEvEwBEx~EyEzE|2E}kE~EEցEւHEփ}EքEօEևEֈ@E։mE֊E֋E֌E֎E֏3E\E EEhEEEzE+EEƎE@EEȦEYE EEsE'EE͐EFEEϰEfEEE҅EEEEEE_EE ;E E E E E fE E JE E 2E EEE EEEEEEEE EEEE8EE[EEE#EE`EEEPEEE]EEEE FE! E!E"E#cE$-E$E%E&E'xE(SE)2E*E*E+E,E-E.E/E0E1E2E3E4E5E6E7E8E9E:E;E=E>-E?HE@fEAEBECEDEFEG@EHjEIEJEKEM#ENVEOEPEQES(ET`EUEVEX EYHEZE[E\E^;E_zE`EaEc7EdvEeEfEh7EiwEjEkEm8EnwEoEpEr4EssEtEuEw+ExfEyEzE|E}NE~EEրEւ&EփZEքEօEֆEֈE։DE֊nE֋E֌E֍E֏E`E EEeEEEnEEE|E*EEȊE:EEʜEKEE̮E`EEEuE'EEьE>EEӣEVEEջEmE EE؅E8EEڜEOEEܳEeEEEzE+EEE>EEENEEE\E EEgEEEoEEEtEEEtEEEoEEEfE EEXEEEDEEE+EElE EEIEEEEESEEEEEEEEqEEUEE7EEEEEiEEJEE,EE E E E iE E TE E @E E 2E E(EE#EE$EE,EE:EEPEEnEEE,EE`EEEBEEE=EEESE EEE GE! E!E"E#oE$;E% E%E&E'E(jE)JE*/E+E+E,E-E.E/E0E1E2E3E4E5E6E7E8E9E; E< E=8E>PE?lE@EAEBECEEEF7EG^EHEIEJELEM=ENmEOEPERESE E :E E:EEBEEMEE`EEzE EE1EE_EEE6EE|E"EEyE(EEEGEEEE FE!E!E"E#wE$EE%E%E&E'E(~E)`E*FE+.E,E-E-E.E/E0E1E2E3E4E5E6E7E9 E:E;.ErE?E@EAEBED EE/EFTEG|EHEIEJEL&EMTENEOEPERESNETEUEVEX(EY`EZE[E] E^GE_E`EaEc7EdtEeEfEh*EihEjEkEmEn[EoEpErEsKEtEuEvEx2EykEzE{E}E~DEyEրEցEփ Eք>EօjEֆEևEֈE֊E֋=E֌dE֍E֎EuEEEjEEüEdE EŶE^EEǴE\EEɰEZEE˱E\EEͲE]EEϴE`E EѷEbEEӺEfEEվEjEEEnEEEpEEEsEEEtEEEtE EEtEEEpEEElEEEfE EE\EEEPEEEAEEE.EEvEEE^EEEBEEE!EE_EEE7EEpE EE?EEqEEsEEdEETEEAEE/EEEE EEEpEEbEEVEE LE E DE E CE E DE E JE EVEEhEEEEE1EEZEEE*EEhE EEXEEE`EEEE:EEE~E DE!E!E"E#~E$PE%"E%E&E'E(E)vE*^E+HE,4E-$E.E/ E0E0E1E2E3E5E6 E7E8E9,E:>E;PEE?E@EAECED)EELEFqEGEHEIEKEL@EMlENEOEPER,ES`ETEUEVEX4EYjEZE[E]E^LE_E`EaEc5EdqEeEfEh"Ei^EjEkEmEnKEoEpEqEs4EtmEuEvExEyLEzE{E|E~ ETEրEցEւEքEօ@EֆnEևEֈE։E֋E֌4E֍XE֎xEE+EEvEEEfE EųEZEEǦEMEEɜEAEEˑE9EE͈E1EEπE)EEyE"EErEEEkEEּEdE EصE^EEڮEVEEܦENEEޝEDEEE:EEE.EE|E"EEnEEE^EEELEEE8EEE"EEhE EELEEE/EEpEEELEEE&EE`EEE4EEiEEE&EEEEEEE~EErEEeEEZEEOEEFEE@EE=EE E.1E/'E0 E1E2E3E4E5"E6)E74E8>E9NE:^E;pEE?E@EBEC%EDFEEhEFEGEHEJEK+ELVEMENEOEQ ER>ESpETEUEWEX>EYsEZE[E]E^NE_E`EaEc1EdkEeEfEhEiREjEkElEn9EorEpEqEsEtSEuEvEwEy.EzbE{E|E}E.Eր]EցEւEփEօEֆ?EևjEֈE։E֊E֌E֍$E֎EEE:EE€E"EEhE EůEREEǙE>EEɆE*EErEE̻E`EEΪEMEEЗEE! E!E"E#E$aE%8E&E&E'E(E)E*E+tE,dE-UE.JE/AE0:E17E26E36E4:E5@E6GE7QE8^E9kE:|E;EE?EAEB"EC@EDaEEEFEGEHEJEK@ELjEMENEOEQERLES}ETEUEWEXEEYzEZE[E]E^PE_E`EaEc,EdeEeEfEh EiEEj}EkElEn&Eo^EpEqEsEt9EuoEvEwEy EzAE{sE|E}EEր4EցdEւEփEքEֆEև:Eֈ`E։E֊E֋E֌E֎EENEEŽE.EEpEEŰEQEEǒE2EEtEEʶEVEE̙E:EE}EEϿE`EEѣEEEEӇE(EEkE E֭EOEEؒE3EEuEE۸EYEEݜEE@EA"EB>EC\ED{EEEFEGEIEJ.EKVEL~EMENEPEQ-ER\ESETEUEWEXNEYEZE[E]E^QE_E`EaEc(Ed]EeEfEhEi8EjoEkElEnEoHEp~EqErEtEuREvEwExEzE{PE|E}E~Eր Eց:EւfEփEքEօEև Eֈ2E։VE֊zE֋E֌E֍EEhEE¢E@EEzEEŴEREEnjE+EEfEEʢE?EEzEEͶETEEώE-EEhEEҤEAEE}EEոEVEEגE/EEkEEڦEDEEEEݻEXEEߔE1EElE EEDEEEEEWEEE.EEhEEE@EEzEEEPEEE&EE^EEE4EElEEE@EExEEELEEEEE,EE/EE1EE4EE8EE>EEFEEPEE]EElEE~E EE"EE ?E E aE E E E E LE EEEE^EEEJEEEFEEEUE EExE3EEErE6EEEEaE 4E!E!E"E#E$mE%IE&)E' E'E(E)E*E+E,E-E.zE/tE0nE1lE2lE3nE4rE5yE6E7E8E9E:E;EEEvEEEIEE\EEbEEiEEpEEzEEE EEEE.EECEE\EExEEE*EE RE E ~E E E JE E E$EEhE EEZEEE\E EEpE&EEESEEEEZE!EEEEYE ,E!E!E"E#E$qE%PE&1E'E'E(E)E*E+E,E-E.E/E0E1E2E3E4E5E6E7E8E9E:E;EE?$E@=EAWEBrECEDEEEFEHEI4EJYEK~ELEMENEP EQJERvESETEUEW-EX\EYEZE[E]E^PE_E`EaEcEdNEeEfEgEiEjOEkElEmEoEpOEqErEsEuEvHEwyExEyE{E|4E}bE~EEրEւEփ7Eք_EօEֆEևEֈE֊E֋6E֌VE֍tE EE9EEjEEĘE0EE^EEnjE$EȺEREEʀEE˭EDEErE EΟE6EEcEEѐE&EҽESEEԁEEծEEEErEE؟E5EEbEEېE'EܾEUEEރEE߲EIEExEEE>EElEEE4EEeEEE.EE^EEE*EE]EEE(EE\EEE,EEaEEE2EEiEEE=EEuEEEEEEE(EE6EEFEEYEEnEEEEE2EETEEyEEE:EE lE E E @E E E "E EiEEEbEEEkEEEE&E?EkpElEmEoEp7EqgErEsEtEv(EwXExEyEzE| E}9E~dEEրEցEփ Eք1EօWEֆzEևEֈE։E֋E֌"E֍@E/EEXEEÂEEĭEAEEhEEǑE$EȺEMEEtEE˚E.EETEEzEEϠE3EEYEEEEӤE7EE]EEփEEרEE'%E(E(E)E*E+E,E-E.E/E0E1E2E3E4E5E6E7E8E9E;E<E=*E>?E?UE@mEAEBECEDEEEGEH8EIZEJ}EKELEMEOEP:EQdERESETEV EW8EXeEYEZE[E]E^LE_zE`EaEc Ed;EekEfEgEhEj,Ek]ElEmEnEpEqNEr|EsEtEvEw6ExdEyEzE{E}E~;EdEրEցEւEքEօ&EֆKEևnEֈE։E֊E֋E֍ EVEEzE EßE1EESEEvEEǘE(EȸEIEEjEEˉEĘE8EEWEEvEEЕE$EѳECEEaEEEE՝E-EּEKEEjEEيEEکE8EEYEEzE EޚE,E߼EMEEpEEE%EEJEEpEEE*EEREEzEEE:EEfEEE*EEZEEE"EEVEEE$EE\EEE2EEbEEtEEEEE*EECEE`EEEEE8EEaEEE(EE\EEE4EEuE E E `E E E XE E E`EEEtE*EEETEEEEQEEEEnE:E EEEEYE2E E E!E"E#E$vE%[E&CE',E(E)E)E*E+E,E-E.E/E0E1E2E3E4E5E6E7E8E: E;E<.E=BE>VE?lE@EAEBECEDEF EG+EHKEIlEJEKELEMEO EPFEQmERESETEVEW=EXhEYEZE[E]E^HE_vE`EaEcEd/Ee_EfEgEhEjEkIElyEmEnEpEq2Er`EsEtEuEwEx@EylEzE{E|E~E;EրaEցEւEփEքEֆEևjE?E@EAEBECEEEFEG:EHZEIzEJEKELENEO*EPPEQvERESETEVEW?EXiEYEZE[E]E^BE_nE`EaEbEd"EePEf}EgEhEjEk4ElbEmEnEoEqErBEsoEtEuEvExEyDEzoE{E|E}EEր6EցZEւEփEքEօEև Eֈ*E։JE֊gE֋E֌EE8EEREEkEEŁE EƘE"EǫE6EEJEE[EEnEEEE͐EEΠE(EϰE8EпEHEEWEEfEEwEEՆEE֖EEצE/EطE@EEQEEcEEvEE݊EEޠE*EߵE@EEXEEpEEEEE4EEREEqEEE$EEHEEnEEE*EEWEEEEEMEEEEEREEE+EEMEEfEEEEE7EE]EEEEENEEEEEZEEE>EEE+EE|E&EE ~E -E E E @E E EdEEEEREEEE^E&EEEEVE&EEEE|EXE4EEE E!E"E#E$sE%\E&GE'5E($E)E* E+E+E,E-E.E/E0E1E2E3E4E6E7E8E9'E:7E;GEE?E@EAEBECEEEF0EGMEHlEIEJEKELENEO6EPZEQERESETEVEWBEXlEYEZE[E]E^=E_hE`EaEbEdEeCEfoEgEhEiEkElLEmwEnEoEpEr%EsOEtzEuEvEwEy EzGE{pE|E}E~EրEց-EւPEփrEքEօEֆEևE։E֊2E֋NE֌kEEfEEzEEċEEŜE$EƫE2EǺE@EELEEXEEdEEnEEwEE΀EEψE EБEEљEEҡE%EөE-EԱE6EչE>EEGEEPEEZEEfEEqEE~EE݋EEޚE"EߪE2EEDEEXEEnEEEEE,EEHEEfEEEEE:EE`EEEEELEE|EEEIEEEEE[EEE EE,EEPEEwE EE:EEmEEE?EE~EEEcEEETEEEQEEE[E E E rE 'E E E PE EEEHE EEEZE$EEEEZE,EEEEEbE@E EEE E!E"E#E$nE%ZE&GE'6E((E)E*E+E,E,E-E.E/E0E1E2E4E5 E6E7 E8,E9:E:JE;YEE?E@EAEBEDEE#EF>EG\EHzEIEJEKELENEO?EPbEQERESETEVEWDEXkEYEZE[E] E^7E_`E`EaEbEd Ee4Ef_EgEhEiEk El5Em_EnEoEpErEs1EtZEuEvEwExEz E{GE|nE}E~EEցEւ"EփDEքdEօEֆEևEֈE֊E֋E֌6E E”EEâE(EįE5EŸE>EEFEENEESEEYEE\EE_EEbEEbEEdEEeEEfEEfEEgEEgEEhEEjEElEEoEErEEvEE|EE܂EE݊EEޒEEߞE$EE0EE@EEPEEdEExEEEEE8EEVEEvEEE,EEVEEEEEHEE{EEENEEE"EEBEEfEEE$EEREEE!EEZEEE:EEE&EEtEEEtE"EEE2EEE PE E E zE 6E E EtE7EEEEREEEEEXE+EEEEEhEFE&E EEE E!E"E#|E$gE%TE&EE'6E()E)E*E+ E,E-E.E/E0E1E2E3 E4E5E6%E70E8E?E@EAEBEDEE2EFLEGiEHEIEJEKEMEN$EOFEPiEQERESETEVEWDEXjEYEZE[E]E^0E_XE`EaEbEcEe%EfOEgxEhEiEjElEmGEnpEoEpEqEsEt:EuaEvEwExEyE{!E|FE}jE~EEրEցEփEք8EօVEֆvEևEֈE։E֊E֌EAEEJEEPEEVEEZEE\EE\EE\EEYEEVEEREELEEGEE@EϾE:EжE4EѰE,EҨE&EӢEEԜEEՕEE֐E E׊E E؆EEكEEځEEۀEE܀EE݂EEކEEߋEEEEE!EE.EE>EEOEEdEE{EEE$EEBEEeEEEEEIEEyEEEGEEEEEVEEyE EE6EEdEEE3EEnE EEPEEE=EEE6EEEE?E@EAEC ED&EE@EFZEGvEHEIEJEKEM EN,EONEPoEQERESETEVEWDEXiEYEZE[E]E^)E_PE`wEaEbEcEeEf>EgfEhEiEjElEm.EnUEo}EpEqErEtEu?EvdEwExEyEzE|E}@E~bEEրEցEւEքEօ&EֆDEևbEֈE։E֊E֋EwEEzEE|EE{EExEEuEEnEEgEE]EEREEGEE;E͵E.EΧE EϙEEЋEE|EEnEE`EEREEDEսE7EֱE+EץE EؚEEِE EڈEEہEE{EExEEvEEvEEyEE~EEE EEEE$EE6EELEEbEEEEE/EEUEE~EEEEEEzEEEPEEEEEDEErE EEAEE{EEE]EEELEEEGEEENEEEdEEEE>EEErE 0E E E vE ;E E EE^E+EEEEoEDEEEEEEdEEE(E EEEEE E!E"xE#hE$XE%IE&=E'2E((E) E*E+E,E-E.E/E0E1E2E3$E4-E56E6BE7ME8ZE9hE:xE;EE?E@EBECED3EELEFfEGEHEIEJEKEMEN4EOSEPtEQERESETEVEWCEXgEYEZE[E\E^ E_FE`mEaEbEcEeEf-EgSEh{EiEjEkEmEnE̴E*E͠EEΌEEvEE`EEJEE5EҪEEӔE E~EEjEEVEECE׺E1EةE!EٙEEڊEE}EErEEjEEbEE^EE\EE]EEaEEhEErEEEEEEE1EELEEkEEE"EELEEzEEEKEEE&EETEEEEELEEE&EEhE EEVEEEQEEEZE EEpE$EEELEEEE@EEE E NE E E E rE?EEEEEZE0EEEEEyEYEE?E@EB EC$EDEسE'EٜEEڈEEvEEeEEWEELEECE߿E=EE:EE:EE>EEFEEQEE`EEtEEEEE8EE\EEEEELEEEEE^EEE$EEVEEE-EEnEEE\EEEVEEE^EEEuE*EEEREEEEIE EEEXE E E E E LE E EEEiE?EEEEEEiEJE.EEEEEEEEE rE!dE"WE#KE$@E%6E&-E'%E(E)E*E+E,E-E.E/E0 E1&E2-E35E4?E5IE6UE7bE8pE9~E:E;EE?EAEBEC.EDFEE_EFxEGEHEIEJELEMENE?EA EB EC7EDOEEgEFEGEHEIEJELEM"EN@EO^EP{EQERESETEVEW9EXZEY|EZE[E\E^E_%E`HEajEbEcEdEeEgEhE?EAEB'EC>EDTEElEFEGEHEIEJEL EM%ENBEO^EP|EQERESETEVEW5EXUEYuEZE[E\E]E_E`EE:EE9EE=EEFEETEEiEEEEE8EEbEEE.EEjE EEAEEyEEE\EEENEEEQEEEbEEEE?EEEuE5EEEEFEEEErE@EEEE E `E 8E E E EEEfEIE,EEEEEEEE|ElE^EPEEE9E1E )E!!E"E#E$E% E& E'E(E)E*E+ E, E-E.E/E0%E1.E28E3BE4ME5YE6fE7uE8E9E:E;EE@EAEB,ECBEDZEErEFEGEHEIEJEL EM&ENBEO^EP{EQERESETEVEW.EXMEYmEZE[E\E]E_ E`.EaNEboEcEdEeEfEhEi4EjUEkvElEmEnEoEqEr9EsYEtzEuEvEwExEzE{2E|PE}mE~EEրEցEւEքEօ1EֆKEևdEֈ}E։E֊EEKEļE*EŚEEuEELEǸE"EȌEE\EE,EʓEE^EE'ĚEETEͷEE~EEDEϦE EkEE1EєEEYEҼEEӃEEJEԮEEwEEBE֨EEvEEFEدEEقEEYEE2E۠EE~EEaEEHE޼E2EߩE!EEEE EE EEEEEE&EE;EEVEEyE EE:EEnE EEJEEEEE]EEEJEEEHEEEWE EEwE0EEEdE#EEElE3EEEE^E-EEEExENE &E E E E E vEVE9EEEEEEEEEnE^EOEBE6E+E"EEE E!E"E#E#E$E%E&E'E(E)E+E,E- E.E/E0"E1,E26E3AE4NE5ZE6hE7wE8E9E:E;EE@EAEB0ECFED^EEtEFEGEHEIEJEL EM&ENBEO]EPzEQERESETEV EW)EXGEYfEZE[E\E]E_E`!Ea@Eb`EcEdEeEfEhEi Ej@Ek`ElEmEnEoEpErEsEӟEE_EE!EՄEEHE֫EErEE>EؤE ErEEEEڮEEۆEE`EE@EݰE"EޖE E߀EEnEEdEE]EE\EEcEEnEEE EE*EEOEEzEEEJEEE'EEbEEEGEEE@EEEIEEEdEEEENE EEEVEEEExEDEEEEE^E4E EEE E }E \E =E !EEEEEEE{EiEXEHE:E,E!EE EEEEEE E!E"E#E$E%E&E'E(E)E*E+E-E. E/E0E1(E23E3?E4LE5ZE6hE7xE8E9E:E;EE@EAEB2ECHED_EEvEFEGEHEIEJEL EM%EN@EO[EPwEQERESETEVEW!EX@EY]EZzE[E\E]E^E`Ea1EbQEcoEdEeEfEgEi Ej*EkIElgEmEnEoEpErEsEt>Eu[EvzEwExEyEzE| E}&E~BE\EրxEցEւEփEքEօEևEֈ*E։BE֊ZEXEE0EŜEElEE9EǠEEgEE,EɏEEOEʰEEnEE*ËEEAE͞EEVEαE EiEE EzEE1EэEEDEҠEEYEӶEEpEE,EՌEEJE֪E EnEE2EؖEEaEE.EږEEiEE@EܮEE݌EEnEEVEEDEE7EE0EE/EE6EEBEEVEEpEEE(EEVEEE,EEkEEEHEEE:EEE=EEETE EE|E8EEEvE:EEEEZE&EEEEiE>EEEEEE^E =E E E E E EEEqE^ELEE@ EAEB3ECJED`EEvEFEGEHEIEJELEM$EN>EOXEPrEQERESETEUEWEX7EYTEZpE[E\E]E^E`Ea"Eb@Ec^Ed|EeEfEgEhEjEk2ElPEmnEnEoEpEqEsEt EuE@EAEB2ECHED^EEtEFEGEHEIEJELEMEN9EOTEPmEQERESETEUEWEX-EYIEZfE[E\E]E^E_EaEb0EcMEdkEeEfEgEhEiEkEl8EmUEnrEoEpEqErEtEuEv:EwWExrEyEzE{E|E}EEր/EցJEւbEփ{EքEօEֆEևEֈE֊ EEFEŬEEtEE7EǘEEVEȳEElEE"E|EE+E˃EE2ẺEE5E͊EE4EΈEE1EφEE.EЂEE+EрEE)E~EE)EEE,EԄEE4EՎEEBE֝EEVE״EEpEE2EٔEE\EE(EېEEdEE=EݬEEގEEvEEdEEYEEUEEYEEcEEwEEE"EEJEE|EEEXEEE7EEE*EEE1EEELEEE|E9EEEEHEEEEvEFEEEEErENE*EEEEEEwE _E HE 2E E E EEEEEEEEEEEEEEEEEEE E!E"E#E$E%E&E'E(E)E*E+E,E-E.E0E1E2E3,E4E@EAEB.ECDEDZEErEFEGEHEIEJELEMEN3EOMEPfEQERESETEUEWEX#EY?EZZE[wE\E]E^E_EaEb Ec=EdZEevEfEgEhEiEkEl"Em>EnZEowEpEqErEsEuEvEw:ExUEyqEzE{E|E}E~EրEց)EւBEփZEքrEօEֆEևEֈE։E"EŅEEKEƫE EhEE"E}EE2EɊEE8EʑEE;EˏEE6E̊EE/ÉEE$EvEEEhEϹE EZEЫEELEўEEAEғEE8EӌEE3EԇEE2EՈEE8E֑EEEEנEEZEظEExEE=EڡEElEE>EܪEE݄EEdEEJEE8EE.EE*EE.EEE?EAEB*EC@EDVEEmEFEGEHEIEJEKEMEN.EOFEP`EQzERESETEUEVEXEY4EZNE[jE\E]E^E_E`EbEc,EdHEedEfEgEhEiEjEl Em(EnCEo`Ep{EqErEsEtEvEwEx:EyTEznE{E|E}E~EEցEւ!Eփ:EքREօjEֆEևEֈE։EdEE&EƆEE@EǚEENEȨEEVEɪEESEʧEELE˜EE=E̎EE,EzEEEdEαEELEϚEE4EЁEEEjEѷEETEҤEECEӒEE4EԇEE-EՀEE*EւEE2E׊EE@E؝EEZEٺEE~EEHEۮEE܂EEZEE:EެE EߖEEEEEEEEEEE.EEPEEzEEENEEE0EExE EEzE)EEEHEEE|EE EE!LE"TE#]E$eE%nE&wE'E(E)E*E+E,E-E.E/E0E2E3E4'E56E6HE7ZE8nE9E:E;EE?EA EB"EC9EDPEEfEF}EGEHEIEJEKEM EN&EO>EPXEQqERESETEUEVEX EY(EZBE[^E\xE]E^E_E`EaEcEd6EeREfmEgEhEiEjEkEmEn,EoGEpbEq~ErEsEtEuEwExEy8EzRE{lE|E}E~EEրEւEփEք2EօJEֆaEևxEֈE։EŧEEdEEEtEE&EzEE&EzEEEnEʾE E\E˪EEDȆEE(EtE;E ESEΞEE2E{EEEYEТEE7EтEEEcEүEEIEӖEE2EԂEE$EtEEEpEEErEE%E؀EE:E٘EEZEھE"EۈEEZEE2EݠEEރEEmEE_EEZEE^EEjEEEEE4EEbEEEE?EAEBEC0EDHEE^EFuEGEHEIEJEKEMENEO5EPNEQgERESETEUEVEXEYEZ5E[PE\kE]E^E_E`EaEc Ed%Ee@EfZEgvEhEiEjEkElEnEo1EpLEqeErEsEtEuEvExEyEz7E{PE|hE}E~EEրEցEւEքEօ-EֆDEևZEֈqE։EEHEƢEETEǫEEVEȪEENEɞEEE?E@EBEC(ED>EEUEFlEGEHEIEJEKELENEO+EPDEQ]ERvESETEUEVEWEYEZ)E[BE\\E]wE^E_E`EaEbEdEe.EfHEgdEh~EiEjEkElEnEoEp5EqPErjEsEtEuEvEwEyEzE{6E|PE}hE~EEրEցEւEփEօEֆ*Eև@EֈWE։nE,EƈEE6ENjEE4EȅEE$ErEEEYEʣEE8EˀEEEUE̜EE%EjEͮEE6EzEνEEDEφEE EPEДEEE`EѥEE.EuEһEEJEӔEE&EqEԼE EVEդEEEE֗EE>EהEEDE؞EEVEٴEEvEE=EۤEExEETEE7EެE#EߜEEEEEEE0EEMEEuE EEEEEE*EEyE%EEE8EEEdE"EEEmE6EEEEnECEEEEEEhEJE.EEEEEEEEEExEpE hE `E \E XE TESERESEVEWE[E`EfElEtE|EEEEEEEE E!E"E#E% E&E')E(8E)GE*WE+hE,xE-E.E/E0E1E2E3E5 E6E70E8DE9XE:nE;EE?E@EBECED2EEHEF_EGwEHEIEJEKELENEOEP8EQPERjESETEUEVEWEYEZE[5E\NE]hE^E_E`EaEbEdEeEf8EgREhlEiEjEkElEmEoEp"EqE?E@EAEC ED$EE;EFSEGjEHEIEJEKELEMEOEP+EQDER]ESvETEUEVEWEXEZ E[&E\@E]YE^sE_E`EaEbEcEeEf(Eg@EhZEitEjEkElEmEnEpEq(ErBEs[EtuEuEvEwExEyE{ E|#E}=E~UEnEրEցEւEփEքEօEևEֈ-E։CEƴEE\EǮEEMEȜEE2E{EE EREʙEE!EeE˦EE)EjE̪EE'EfEͤEEE\EΘEEEOEϋEEEBEEмEE9ExEѶEE7ExEҹEE?EӂEE ETEԜEE.EzEEEbEֲEEWE׬EEZEشEElEE,EڐEE[EE0EܜE E}EEhEE\EEZEEdEEwEEE*EE[EEE:EEE0EEE@EEElE+EEEvE@E EEE~ETE,EEEEEEiEPE9E#EEEEEEEEEEEE E E E E EEEEEEEEEEEEE,EE-RE.eE/xE0E1E2E3E4E5E7E8E92E:IE;_EE?E@EAEBEDEE,EFDEG\EHsEIEJEKELEMEOEPEQ6EROEShETEUEVEWEXEYE[E\2E]JE^dE_}E`EaEbEcEdEfEg1EhKEidEj~EkElEmEnEoEqEr0EsIEtcEu|EvEwExEyEzE|E}*E~DE\EրtEցEւEփEքEօEևEֈE։3EEHEǚEE5EȂEEE`EɨEE1EuEʸEE:EzE˺EE6EtE̱EE)EdE͞EEEME·EEE4EmEϧEEEUEАEEEAE}EѺEE5EtEҲEE4EvEӹEEBEԈEEEaEլEEFE֕EE8E׌EE:EؒEEJE٩E EnEE8EۢEE{EE^EEKEEBEECEEPEEgEEE!EEXEEE>EEE?EEE[EEEETEEEE{EJEEEEE~E^E>E EEEEEEEE~ErEhE`EXESEOEMELE LE NE QE UE ZEaEiEpEzEEEEEEEEEEEE(E:E KE!]E"pE#E$E%E&E'E(E)E+ E,E-2E.GE/[E0pE1E2E3E4E5E6E8E9E:4E;JEE?E@EAEBEDEEEF4EGLEHdEI|EJEKELEMENEPEQ(ER@ESZETrEUEVEWEXEYE[ E\"E];E^UE_nE`EaEbEcEdEfEg!Eh:EiTEjmEkElEmEnEoEqErEs9EtQEulEvEwExEyEzE|E}E~2EJEրcEց{EւEփEքEօEֆEֈ E։#E:ENJEE$EpEȹEEHEɎEEEXEʘEEEUE˒EE EDEE̹EE*EbE͚EEE?EuEάEEENEυEϻEE)E`EИEEEAE{EѶEE,EhEҥEE"EbEӢEE(ElEԲEEAEՊEE"EpEEEfE׺EEjEE"EـEEDEکEEzEEUEE9EݯE(EޤE"EߢE(EE8EETEE}EEEREEEBEEENEEEwE6EEEEJEEEEEbE~E?E@EAEBECEE EF%EG=EHVEInEJEKELEMENEPEQER3ESLETdEU}EVEWEXEYEZE\E]-E^GE_`E`yEaEbEcEdEeEgEh*EiCEj\EkvElEmEnEoEpErEs'Et@EuXEvrEwExEyEzE{E}E~E8EրPEցhEւEփEքEօEֆEևE։E{EEE_EȨEE4EyEɼEEEuEѮEEEYEҕEEELEӊEE EPEԔEE EjEմEEME֜EE@EהEEDE؞EEZEٻEEڄEEWEE3EܥEEݑE EވEEߋEEE&EEGEEuEEESEEENEEEgE EEE^E"EEEEUE'EEEEEmEPE4EEEEEEEEEEEEEEEEEEE E E E E EEEEEEE&E7EJE\EoEEEEEEE!E"E#.E$CE%YE&pE'E(E)E*E+E,E. E/"E09E1PE2hE3E4E5E6E7E8E: E;$E<;E=TE>kE?E@EAEBECEDEFEG-EHEEI^EJvEKELEMENEOEQ ER#ESE IE TE `E mE|EEEEEEEE E E6EKEaEwEEEE E!E#E$E%0E&HE'`E(wE)E*E+E,E-E/E0E14E2ME3dE4}E5E6E7E8E9E;E<&E=?E>XE?pE@EAEBECEDEFEGEH5EINEJgEKELEMENEOEPERES.ETGEU`EVyEWEXEYEZE[E]E^(E_BE`ZEatEbEcEdEeEfEh Ei$Ej>EkVElpEmEnEoEpEqEsEtEu8EvQEwjExEyEzE{E|E}EEր2EցKEւdEփ{EքEօEֆEևEֈEEHEȎEEEYEɚEEEREʎEEE8EmEˣEE E>EoE̡EEE0E_E͍EͼEEEDEqEΞEEE&ESEπEϮEE E:EiEЙEEE-E`EѓEEE4EjEңEEETEӒEEESEԖEE#ElEնEEPE֡EEHEמEEREذEEqEEBE?[E@sEAEBECEDEEEG EH"EIEȅEEEMEɍEE EBE|EʵEE"EVEˊE˾EEEPE~ḘEEE4E`E͋EͷEE E6EaE΋EεEE E4E_EωEϵEE E8EfEГEEE!EQEуEѶEEETEҋEEE8EtEӳEE4EvEԻEEJEՓEE.E~EE%E{EE0E؎EEREٷE EڊEEiEESEEIEELEE\EEzEEEAEEE)EEE2EEEZEEEEiE5EEEEE\E8EEEEEEEEzEnEbEYEREMEJEIEHELEPETE[EcEnEzEE E E E E EEEE'E>EUElEEEEEEEE7EPE kE!E"E#E$E%E'E("E)(E?AE@ZEAtEBECEDEEEFEHEI'EJ@EKZELtEMENEOEPEQES ET%EU?EVXEWrEXEYEZE[E\E^ E_$E`=EaVEboEcEdEeEfEgEiEj!Ek:ElSEmlEnEoEpEqErEtEuEv8EwRExjEyEzE{E|E}EEրEց6EւOEփiEքEօEֆEևEֈE~EEEFEɅEEE8EqEʨEEEDEwE˨EEE5EbE̎E̺EEE9EaE͊EͳEEE)EQExEΠEEEE=EeEώEϷEE E4E^EЊEжEEE@EpEѡEEE:EpEҨEEEVEӓEEETEԘEE&EpEռE EZE֮EEZE׳EEoEE4EٚEEpEEREE?EܻE;EݽEBEEWEE{EEEJEEE>EEESE EEELEEEEwEJEEEEEEwE]EEE0EEEEEEEEEEEEEEEEE EE(E 7E IE ZE mE EEEEEE E$E>EYEsEEEEEEE 4E!OE"kE#E$E%E&E'E)E*+E+FE,bE-}E.E/E0E1E3E4E5:E6SE7nE8E9E:E;E E?'E@BEA\EBvECEDEEEFEGEIEJ,EKFEL`EMzENEOEPEQERETEU.EVHEWbEX|EYEZE[E\E]E_E`/EaIEbcEc|EdEeEfEgEhEjEk/ElIEmbEn|EoEpEqErEsEuEv0EwIExdEy|EzE{E|E}E~EրEց1EւLEփdEքEօEֆEևEֈEȾEE@E~EɺEE.EfEʜEEE5EfE˕EEEEJEtE̜EEEEEmYEnsEoEpEqErEsEuEv(EwCEx\EyxEzE{E|E}E~EրEց/EւJEփdEք~EօEֆEևEֈEE>E{EɶEE*E`EʕEEE,E\EˉE˶EEE7E_ĔE̮EEEECEfE͉EͬEEEE4EVExEΚEλEEE"EEEhEϋEϰEEE EFEoEЗEEEEEErEѢEEE9EnEҤEEEREӐEEEVEԜEE.EzEEEnEEExEE8E؛EElEEHEڻE0E۫E'EܨE+EݲE>EE^EEE+EEtE EEE7EEEoE3EEEEfE:EEEEEEtE\EHE6E'EEEEEEEEEEE EEE,E9EHEYElE~E E E E E EE"E=EXEtEEEEEE'EEEcEEEE E!E#E$:E%WE&vE'E(E)E*E, E-'E.DE/aE0~E1E2E3E4E6E7*E8FE9bE:~E;EE@ EA%EB@EC\EDwEEEFEGEHEJEKEL5EMPENjEOEPEQERESEU EV&EW@EXZEYuEZE[E\E]E^E`Ea-EbHEccEd|EeEfEgEhEjEkEl5EmPEniEoEpEqErEsEuEv"EwE EEEEhEHE)EEEEEEEEEEEEEEEEEEEEEEEE E E 6E ME fE ~E EEEE E'EEEdEEEEEE"EAEbEE E!E"E$E%!E&@E'`E(~E)E*E+E,E.E/6E0SE1pE2E3E4E5E7E8"E9>E:\E;yEE?EAEB$EC@ED[EExEFEGEHEIEKELEM9ENUEOpEPEQERESETEVEW/EXIEYeEZE[E\E]E^E`Ea EbE?E@EBEC"ED?EE\EFxEGEHEIEJELEM"EN>EOZEPvEQERESETEVEWEX8EYTEZpE[E\E]E^E_EaEb/EcJEdfEeEfEgEhEiEk El%EmAEn\EoxEpEqErEsEuEvEw8ExTEyqEzE{E|E}E~EրEց4EւPEփnEքEօEֆEևEֈEɶEE'E]EʐEEE ENExEˢEEEE;E_ÈE̢EEEEE:EVEqE͎EͨEEEEE*EDE^ExEΑEΫEEEEE4EREoEύEϬEEEE3EXE}EФEEE"ENE|EѬEEEFE~EҸEE0EpEӲEE>EԇEE!ErEEEvEE2EהEEbEE>EٱE'EڡEE۠E$EܬE9EE]EEߒE4EEE4EEEXEEEEhE5EEEEEgEGE*EEEEEEEEEEEEEEEEEEEEE EE4EJE`EzE E E E EE&EFEfEEEEEE1ESEvEEEEE $E!FE"iE#E$E%E&E(E)3E*TE+uE,E-E.E/E1E26E3VE4tE5E6E7E8E:E;/EE?E@EAECEDEEEHESE`EnEEEEEEEEE 9E UE sE E EEEE6EYE{EEEE E/ETExEEEE!E"+E#NE$rE%E&E'E(E*E+?E,bE-E.E/E0E2E3)E4IE5hE6E7E8E9E;E<(E=GE>fE?E@EAEBEDEEEF>E?_E@EAEBECEDEFEG;EHZEIxEJEKELEMEOEP/EQNERlESETEUEVEXEYEZEx]Ey{EzE{E|E}EEր0EցOEւnEփEքEօEֆEֈE։(ElEʠEEE,EXE˂E˪EEEE8EXEwE̔E̱EEEEE.EDEZEoE̓E͘EͪE;EEEEEE-E>EQEdExEΊEΟEγEEEE E#EE?8E@YEAzEBECEDEEEGEH:EIZEJzEKELEMENEPEQ6ERTEStETEUEVEWEYEZ,E[KE\jE]E^E_E`EbEc Ed>Ee]Ef{EgEhEiEjElEm2EnPEonEpEqErEsEuEv'EwFExdEyEzE{E|E~EEր>Eց^Eւ~EփEքEօEֆEֈE։>EʧEEE5E`EˊE˲EEEE?E^E|E̘E̲EEEEE*E>ESEfEyE͋E͝EͮE;EEEEEEE/E?EPE`EqE΃EΕEΨEλEEEEE(EAE[EvEϓEϱEEEE6E\EЄEЮEEE5EfEњEEEBEҀEEEHEӎEE&EwEE!E{EE8E֜EEmEENEE=EٻEE[EyEEEE E !E DE jEEEEE.EVEEEEE$EMEvEEEE!E"AE#iE$E%E&E(E)-E*TE+zE,E-E.E0E16E2[E3E4E5E6E8E94E:WE;{EE@EA*EBLECoEDEEEFEGEIEJ:EK\EL~EMENEOEQER$ESEETeEUEVEWEXEZ E[)E\JE]jE^E_E`EaEc Ed-EeMEfmEgEhEiEjElEm/EnPEopEpEqErEsEuEv4EwTExuEyEzE{E|E~EE?EAEB$ECHEDkEEEFEGEHEJEKEw`ExEyEzE{E} E~-ENEրrEցEւEփEքEֆEևCEֈgE։EYE˄EˮEEEE@E`E}E̘E̳EEEEE"E4EEEUEdEtÉE͍E͙EͥEͯE͹EEEEEEEEE EE!E+E5EAEMEYEfEvE΄EΔEΦEθEEEE E&EBE]EzEϛEϼEEE,EVEЂEаEEEHEрEѺEE8E{EE EVEӤEEMEԥEEbEE,E֘EEyEEjEEkEE}E EۡE:EE|E&EE߅E;EEEvE=EEEE|EUE1EEEEEEEEEEEEEEEEEEEEEEEE:EUErEEEEEE =E cE E E EE+EUEEEEE+EXEEEEE0E[E E!E"E$E%.E&XE'E(E)E*E,#E-KE.tE/E0E1E3E48E5^E6E7E8E9E;EE?E@EAEC EDDEEiEFEGEHEIEKELAEMdENEOEPEQESET7EU[EV~EWEXEYE[ E\+E]NE^qE_E`EaEbEdEe?EfcEgEhEiEjElEm1EnTEowEpEqErEtEu%EvGEwkExEyEzE{E}E~?EaEրEցEւEփEօEֆ9Eև^EֈE։EːE˹EEE+ELElËE̦EEEEEE,E=EME[EkExE̓E͏E͙EͣEͬE͵E;EEEEEEEEEEE EEE'E1E;EGERE`EnE}E΍EΞEβEEEE E%E@E^E~EϠEEEE:EfEЕEEE0EjEѥEE%EjEұEEIEӚEEFEԢEEbEE1E֠EE׆EE~EEنEEڠE3EEiE EݶEbEEEEBEEEE`E2E EEEEEiESE@E1E$EEEEEEEE"E.E;EKE\EpEEEEEE E*ELEmEEEE E *E QE zEEEE%ERE}EEEE/E\EEEE E 8E!dE"E#E$E&E':E(eE)E*E+E- E.4E/]E0E1E2E3E5&E6ME7tE8E9E:E<E=8E>^E?E@EAEBEDEEAEFfEGEHEIEJEL EMEENjEOEPEQERET EUEEViEWEXEYEZE\E]@E^dE_E`EaEbEdEe;Ef_EgEhEiEjElEm6EnZEo}EpEqErEtEu1EvVEwzExEyEzE| E}0E~UEzEրEցEւEքEօ4EֆXEևEֈE։EEEE:E\E|E̚E̵EEEEE&E:EJEYEhEuÈE͌E͖E͟EͧEͰEͶEͽEEEEEEEEEEEEEEEEEE(E2E>EIEWEeEtEΆEΗEΫEEEE E$EBEbEτEϧEEE ENE|EЯEEEUEђEEE[EҤEE@EӓEEBEԠEEfEE:E֬E!EיEEؗEE٦E5EE_EEܞEGEEޤEYEEEEXE!EEEEpELE,EEEEEEEEEEEEEEEEEEEEE2ELEhEEEEE E,ERExE E E E EFErEEEE%EREEEEE5EcEEEE!E"DE#pE$E%E&E(E)IE*tE+E,E-E/E0GE1pE2E3E4E6E7-E?UE@|EAEBECEEEF?EGeEHEIEJEKEM%ENKEOpEPEQERETEU-EVREWxEXEYEZE\ E]2E^WE_|E`EaEbEdEe5Ef[EgEhEiEjElEm9En^EoEpEqErEtEu>EvdEwExEyEzE|E}EE~lEEրEցEփEք*EօQEֆyEևEֈE։EE&ELEnĚE̪EEEEE$E6EJEYEgEtE͂E͌E͖E͟EͨEͯE͵EͻEͿEEEEEEEEEEEEEEEEEEE EEE&E0E=EKEYEjEzEΎEΣEιEEEE&EEEhEϋEϲEEE4EdEЗEEEAE~EEELEҘEE7EӍEEAEԢEEmEEHEּE3E׮E0EشEE gE E E EEAEoEEEE'EVEEEEE?EnEE E!E#$E$QE%~E&E'E)E*.E+ZE,E-E.E0E11E2\E3E4E5E7E8.E9XE:E;EEHfEIEJEKEMEN,EOREPzEQERESEUEVE@EAFEBpECEDEEEGEH@EIhEJEKELEN EO4EP[EQERESETEV&EWMEXvEYEZE[E]E^=E_fE`EaEbEdEe,EfTEg{EhEiEjElEmCEnjEoEpEqEs Et3EuZEvEwExEyE{%E|LE}vE~EEրEւEփ@EքkEօEֆEևE։E֊:EpE̔E̵EEE E$E:EMEbErÈE͐E͛EͦEͰE͸EͿEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE EE$E4EFEYElE΃EΜEζEEEE4EZEςEϭEE EE?EAEB@ECkEDEEEFEHEIAEJkEKELEMEOEP=EQgERESETEVEW8EXaEYEZE[E]E^0E_ZE`EaEbEdEe)EfQEgzEhEiEjEl EmJEnsEoEpEqEsEtBEukEvEwExEzE{=E|fE}E~EEցEւ:EփdEքEօEֆEֈE։:E֊eȨEEEEE8ENEbEvE͆E͖EͣEͮEͺEEEEEEEEEEEEEEEEEEEEEEEE;EͼEͻEͺEͺEͺEͼE;EEEEEEEEEEE&E:ENEdE~EΘEεEEEE@EjEϔEEE(E_EИEEEZEѡEE8EҊEE8EӔEEXEE-E՝EE֋E E׊EE؜E,EE[EE۠EJEEݬEcEEEElE8EEEEEpESE:E$EEEEEEEEEEEE EE+E?EUEmEEEEEE$EHEnEEEEE ;E iE E E E"EREEEEEGExEEE E>EoEEE!E"2E#dE$E%E&E("E)QE*E+E,E. E/E?E@EBEC>EDiEEEFEGEIEJFEKqELEMENEPEQJERvESETEUEW"EXNEYxEZE[E\E^$E_OE`zEaEbEcEe%EfOEgzEhEiEjEl%EmPEn{EoEpEqEs&EtREu~EvEwExEz)E{VE|E}E~EրEց.Eւ\EփEքEօEև Eֈ7E։bE֊EEEE7EREhE|E͐E͠EͰEͽEEEEEEEEEEEEEEEEEEEEEEEEEͼEͷEͲEͯEͬEͩEͧEͥEͥEͥEͧEͪEͬEͱEͷEͿEEEEEE EE2EJEbE~EΜEλEEE*ETEπEϰEEEPEЌEEEREћEE8EҌEE>EӞEEhEEBEնE/E֬E,EױEVE?E@EAECED E?PE@EAEBED EEESlETEUEVEX%EYSEZE[E\E^ E_:E`hEaEbEcEe EfNEg|EhEiEkEl4EmcEnEoEpErEsIEtvEuEvExEy0Ez`E{E|E}EEրHEցvEւEփEօEֆ2Eև`EֈE։E֊ELEjË́E͚EͲEEEEEE EEEE"E$E&E%E%E"EEEEE EEEEEEEEE;EͶEͮEͦE͝E͖E͏E͉E̓E~EyEvEtEsEsEtEvEzÈE͆E͎E͘EͤEͲEEEEEE0ELEkEΌEΰEEE.E^EϐEEE:EzEоEENEќEEAEҚEEXEӾE&EԓEE|EEuEEׂEEأE;EEzE!EE~E3EEުEmE4EEEEwERE1EEEEEEEEEEEEEEEEEEEE*EDEaEEEEE E2E[EEEE E 7E fE E E E,E^EEEE-EaEEEE2EfEEE E!4E"hE#E$E&E'4E(gE)E*E,E-2E.dE/E0E1E3,E4^E5E6E7E9$E:UE;EEGnEHEIEJEL/EM`ENEOEPER ESPETEUEVEXEY?EZoE[E\E]E_.E`^EaEbEcEeEfLEg|EhEiEk ElEE7E3E2E4E9EBELEYEhEzEEEEEEE6EXE}EEEEEHEtEEE E 1E cE EEE/EbEEEE7EkEEE E@EuEE E"E#GE${E%E&E(E)KE*E+E,E.E/ME0E1E2E4E5NE6E7E8E:E;KE<~E=E>E@EAHEBzECEDEFEGCEHuEIEJEL EMEE@EEELEUE`EkEzE͊E͜EͲEEEEE>EdEΊEδEEEDEzEϳEE0EtEлEEUEѨEEYEҸEEӁEE]EEJEEIEE\EE؃EEٿEdEE۽EqE*EEަElE6EEEEE`EBE'EEEEEEEEEEEEEEEE"E8ERElEEEEEE6E^EEEE E8EgE E E E .EaEEEE4EiEEE EAEwEEEENE E!E"E$%E%YE&E'E(E*.E+cE,E-E/E06E1jE2E3E5E6E?EAEBEECyEDEEEGEHHEI{EJEKEMENJEO}EPEQESETKEU~EVEWEYEZKE[E\E]E_E`LEaEbEcEeEfLEgEhEiEkElMEmEnEoEqErMEsEtEuEwExNEyEzE{E}E~PEEրEցEփEքREօEֆEևE։"E֊TE֋EEEE.E>ELEZEeEoEuEzE~E΀EEE{EyEsElEeE\ETEJE>E3E'EEEEEEEEͺEͬE͟E͐Ë́EwEkE`ETEJEBE9E1E+E&E#EEEE E$E)E0E9EDEQE`EqË́E͚EͲEEE E,EREzEΦEEE;ErEϮEE0EvEE E_EѵEEkEE4EӞE EEEtEE|EEחE,EEfE EڲEaEEE݆EGE EEEqEFEEEEEEEEtEjEbE^E]E^EcEjEtEEEEEEEEEpE?E@EBECFED|EEEFEHEIREJEKELEN&EO\EPEQERET1EUfEVEWEYEZ;E[pE\E]E_E`DEazEbEcEeEfNEgEhEiEk$ElXEmEnEoEq-ErbEsEtEvEw6ExlEyEzE| E}@E~vEEրEւEփKEքEօEֆEֈ"E։VE֊E֋E!E7ELE^ElE{EΆEΐEΗEΜEΠE΢EΡEΡEΞEΘEΔE΍EΆE|ErEgE\EOEAE4E&EEEEEEE͹EͪE͛E͋E|EnEaESEFE;E0E&EEEEEEEEEEE EEE(E4EDEVEjÉE͚EͶEEEEAElEΘEEE3EmEϪEE1EzEEEkEE EEEOEӼE/EԦE!EաE&EֱE@EEnE EٯEWEE۷ElE'EEީErE>EEEEEvEYE@E,EE EEEEEEEE EE%E6EJEaEzEEEEEE8E`EEEEE6EeEEE E +E ^E EEE4ElEEEEIEEEE(E`EEE!E">E#uE$E%E'E(SE)E*E+E-0E.hE/E0E2E3FE4}E5E6E8"E9ZE:E;E=E>6E?nE@EAECEDJEEEFEGEI'EJ^EKELENEO:EPrEQERETEUMEVEWEXEZ)E[`E\E]E_E`ESEkEͅE͢EEE E4E_EΎEEE/ElEϫEE6EЁEE%E|EE6EҚEEpEEVEEQEE^EEEEصEWEEڪEZEEE݈EJEEEEEWE2EEEEEEEEEEEEEEEEEEEE E(EDEdEEEEEEDEoEEEE*E[E E E E *E`EEEE=EuEEEEVEEEE9ErE E!E#E$SE%E&E'E)6E*oE+E,E.E/RE0E1E2E45E5nE6E7E9E:PE;EE/E!EEEEEEEEEEEEEEEEEEEEE&E>EVErE͐EͲEEE(EVEΆEκEE.ElEϯEE?EЎEE6EѐEEQEҹE$EӔEEԃEEՅE E֛E-EEaEE٧EQEE۶EoE,EE޴EELE EEEEEvE`ELEE@4EAnEBECEEEFXEGEHEJEKDEL~EMENEP.EQjERESEUEVUEWEXEZE[AE\|E]E^E`,EahEbEcEeEfSEgEhEjEk@El{EmEnEp+EqfErEsEuEvREwExEzE{>E|xE}E~Eր*EցdEւEփEօEֆOEևEֈE։E֋8E֌tEνEEEEEE EEEEE E EEEEEEEEεEΤEΔE΂EqE^EKE7E#EEEEEͽEͨE͕ÉEmEZEGE6E$EEEEEEEE̼E̴E̯E̫ĘĘĘE̪E̯E̶E̿EEEEEE'EBE^E~E͢EEEELE΀EζEE.EoEϴEEJEМEEHEѦEEnEEHEӽE6EԳE5EռEIEEpE EجEPEEڨE\EEEݐEUEEEEEmEKE,EEEEEEEEEEEEEEEEEE4EPElEEEEEEBElEEEE#ESEEE E "E XE EEE7EpEEEEWEEEE@EzEEE!*E"dE#E$E&E'PE(E)E+E,=E-xE.E/E1+E2fE3E4E6E7VE8E9E; EE?EA7EBsECEDEF)EGfEHEIEKELXEMENEPEQKERESEUEV>EW{EXEYE[2E\nE]E^E`%EacEbEcEeEfVEgEhEj EkKElEmEoEp>Eq{ErEsEu2EvnEwExEz&E{bE|E}EEրUEցEւEք EօHEֆEևEֈE֊8E֋vE֌EEEEE'E.E3E8E8E8E4E2E,E$EEEEEEEEκEΧEΕE΁EmEXECE.EEEEEEͪE͔EEjEUEAE-EEEEEEE̾E̱E̦E̞E̖E̐ĚE̊E̊ĚE̎E̔E̜E̦E̲EEEEEE0ENEpE͔EͼEEEHE}EζEE2EvEϾE EZEЭEEbEE(EґEErEEfEEnEE֋EE׸EWEE٤EREEۻEvE6EEEߎE`E4E EEEEEEqEdEYERENENEPEVE^EjEwEEEEEEEE>E`EEEEE)EVEEEEELE E E E $E[EEEEBE|EEE,EgEEEESEE E"E#BE$~E%E&E(3E)pE*E+E-&E.bE/E0E2E3VE4E5E7E8LE9E:E<E=DE>E?E@EBDE?E@EBECDEDEEEGEHFEIEJELEMHENEOEQ ERJESETEV EWNEXEYE[E\SE]E^E`EaXEbEcEeEf\EgEhEj EkaElEmEo%EpfEqErEt*EujEvEwEy.EznE{E|E~1EqEրEցEփ4EքtEօEֆEֈ4E։tE֊E֋E֍3EXEfErE|EςEψEϋEϋEϊEφEπEyErEgE[ENE?E/EE EEEEκEΤEΌEtE]EDE+EEEEEͯE͖E}EfENE6E E EEEE̼E̪E̛ĚEEsEiE`EYETEPEOEPEREWE^EhEtÊE̒E̦E̼EEEE4EXÉEͬEEEEE΀EνEEDEύEE,EЂEE:EўEErEEXEEREEaEEցEE׶EUEE٨EWE EE܂EDE EEߣEvEME(EEEEEEEEEE}E~EEEEEEEEEE$ECEbEEEEE!EMEzEEE E=EqEE E E LE EEE4EoEEE#E_EEEEREEE E!HE"E#E%E&BE'E(E)E+>E,}E-E.E0=E1~E2E3E5>E6E7E9E:BE;EE?HE@EAECEDPEEEFEHEIYEJEKEM ENcEOEPER,ESoETEUEW8EX|EYE[E\EE]E^E`EaSEbEcEeEf_EgEhEj)EkmElEmEo7EpzEqEsEtDEuEvExEyPEzE{E}E~\EEրEւ"EփfEքEօEև,EֈnE։E֊E֌3E֍vEϊEϖEϣEϫEϰEϴEϴEϴEϰEϬEϤEϜEϔEψEzElE\EJE8E$EEEEEδEΜE΃EiEOE5EEEEEͱE͗E}EcEJE2EEEEEE̮E̜E̊EzElE_ESEIE@E:E6E2E2E3E6EE3E)E!EEEEEEE"E+E6EDEVEiÈE̚E̶EEEEHEuEͦEEELEΌEEEaEϱEE\EиEEEEXEEEEEEEEYEE}EE׵EYEEٮE`EEEܒEVEEE߻EEiEFE&E EEEEEEEEEEEEEEEEE,EHEdEEEEEEBEnEEEE+E^EEEE 7E oE E EE[EEEEPEEE EHEEEEEE E!E#E$FE%E&E( E)ME*E+E-E.VE/E0E2 E3dE4E5E70E8tE9E:EE@EAZEBECEE,EFrEGEHEJDEKELENEO`EPEQES5ET|EUEW EXTEYEZE\*E]rE^E`EaIEbEcEe!EfiEgEhEjAEkElEnEo`EpEqEs6Et~EuEw ExUEyEzE|)E}qE~EEցFEւEփEօEֆ`EևEֈE֊0E֋wE֌E֎EEEEE E E EEEEEEEEϺEϨEϕEρElEUE=E%E EEEμEΠE΄EgEJE-EEEE͸E͛E~EbEFE+EEEEḘE̗ÊEnE[EJE:E,EEE EEEEEEEE EE!E0ECEXEpĚE̪EEEEFEtEͨEEEUEΘEE(EvEE E{EE@EѩEE҉EE~EEԇEE՞E2EEhE EزE^EEE~EE?EAEBfECEDEF>EGEHEJEKaELEMEOEYEZE\E]gE^E_EaDEbEcEe"EfnEgEiEjLEkElEn)EosEpErEsREtEuEw.ExyEyE{ E|TE}E~Eր/EցyEւEք EօREֆEևE։*E֊sE֋E֍E֎HE#E,E3E8E:E9E6E2E+E EE EEEEEϴEϟEωEpEXE>E$EEEEβEΔEvEWE9EEEEͿE͠E͂EdEGE*EEEE̾E̦E̎ExEbENE;E*EE EEEEEEEEEEEEE EE2EIEdÈE̠EEEEDEvEͫEE!EbEΦEE=EώEE>EОEEhEEGEҾE9EӺE@EEVEE~EE׼EaE EټEoE(EEܧEmE6EEEEEgEIE/EEEEEEEEEEEEEE$E8EPEkEEEEEE8E`EEEEEIE|EEEE VE E E EBEEEE9ExEEE6EvEEE9EzEE E"BE#E$E& E'PE(E)E+E,eE-E.E08E1~E2E4 E5TE6E7E9,E:tE;E=E>PE?E@EB,ECvEDEF EGTEHEIEK5ELEMEOEPbEQERETEEUEVEX*EYvEZE\E]ZE^E_Ea?EbEcEe$EfrEgEi EjWEkElEnE?\E@EAEC?EDEEEG$EHpEIEK ELXEMENEPAEQERET*EUyEVEXEYcEZE\E]OE^E_EaE,EEEEEϻEϠEυEhEKE-EEEEίEΎEmELE*E EEEͦEͅEeEDE&EEEE̯E̔EzE`EHE2EEEEEEE˾E˴EˮE˨E˥EˤE˦E˪E˰E˺EEEEEE.ELElE̒E̺EEEHE~E͹EE;E΂EEEoEE$EІEEVEE:EҴE3EӶE=EEVEEքE"EEmEEEځEE'EEEEEE˶E˪E˟E˗EːEˌEˊEˊEˎE˓E˛E˦E˳EEEEE%EDEhȄE̺EEEOE͉EEELEΗEE8EώEEKEбEEшEEuEEuEEԄEEգE;EEzE EEzE/EEۦEhE.EEEߜEsENE-EEEEEEEEEEEEEEEEEE!EE yE E E1EqEEE3EsEEE8EzEEEHEEE!E"_E#E$E&7E'E(E*E+\E,E-E/E@.EA~EBEDEEnEFEHEIbEJELEMXENEOEQNERESEUFEVEWEY?EZE[E]9E^E_Ea3EbEcEe.EfEgEi)Ej}EkEm$EnwEoEqErqEsEuEvjEwEyEzbE{E}E~XEEրEւMEփEքEֆ@EևEֈE֊2E֋E֌E֎ E֏pEEEEEEEEEEиEЩEЖEЄEpEXEAE(E EEE϶EϘExEWE5EEEEάEΈEdE@EEEEͰE͎EkEHE'EEEE̦ËEkEPE5EEEEEE˴EˤE˖EˊEˁEyEsEpEpEqEvE|EˆE˒EˢE˴EEEEE>EdE̎E̻EE EXE͕EEEbEίEEWEϲEEuEEKEѾE5EҲE4EӹE?EE\EE֍E-EE}E*EEڕEREEEݢEnE@EEEEEE~EjE[ENEFE@E>E@EDEJETEbErEEEEEEE*EMEtEEEE EPEEEEEWEEE E DE E EE@EEEEFEEEETEEE%EkE E!E#BE$E%E'E(jE)E+E,LE-E.E02E1E2E4E5lE6E8 E9[E:E;E=ME>E?EABEBECEE:EFEGEI4EJEKEM0ENEOEQ,ERESEU,EVEWEY,EZE[E].E^E_Ea0EbEcEe2EfEgEi5EjEkEm6EnEoEq7ErEsEu9EvEwEy9EzE{E}7E~EEց3EւEփEօ.EֆEևE։&E֊xE֋E֍E֎lE֏EEEEEEEEEEEEмEЦEБExE`EEE*EEEEϯEώEmEJE'EEEκEΖEpEKE'EEE͸E͓EoEKE(EEEE̢ĒEeEHE,EEEEE˷EˤE˓E˄EwElEdE\EXEVEVEZE_EhEtEˁE˒E˦E˼EEEE`E?EAEB\ECEEEFZEGEIEJ\EKEMEN_EOEQ EReESEUEVkEWEYEZsE[E]$E^|E_Ea.EbEcEe6EfEgEiAEjEkEmJEnEoEqSErEtEu[EvEx EyaEzE|E}hE~EրEցjEւEքEօlEֆEֈE։jE֊E֌E֍gE֎E֐ EJEKELEGEBE:E1E$EEEEEEвEКEEdEFE)EEEEϥEςE^E:EEEEΣE}EWE/E EEͽE͗ErELE(EEE̿E̞E~E^E@E#EEEE˽E˨E˒EˀEpEbEUELEDE>E:E:EE?tE@EB"ECxEDEF&EG~EHEJ/EKELEN9EOEPERFESETEVSEWEYEZbE[E]E^rE_Ea(EbEcEe9EfEgEiJEjElEm\EnEpEqlErEt Eu{EvEx/EyEzE|;E}E~EրGEցEւEքPEօEֆEֈWE։E֋E֌ZE֍E֏E֐YExEzExEtEmEdEYEKEENE_EtEˌE˨EEEE8EfE̗EEEBË́EEEaEδE EgEE.EЗEE|EEuEEwEEԋEEճENEEוE?EE١EYEEEܜEfE4EEEEEtEZEDE0E!EE EEEE EEE,EE,E-E/4E0E1E3.E4E5E7,E8E9E;0EEֈE։E֋JE֌E֍E֏RE֐EѪEѪEѧEѠEњEѐEтEuEdEPEE0E"EEE EEE EEE E.E?EREjE˄EˢEEEE=EmE̡EEEVE͚EE0E΁EE2EϒEE`EEBEѺE9EҸE8EӽEHEEnEE֦EJEEؠEREEEۃEGEEEެE߁EZE6EEEEEEEEEEEEEEEEEEE(EFEdEEEEE%EREEEEEOEEEE9E vE E E 8EzEEEEEEEE\EEE6EEEE dE!E#E$OE%E&E(>E)E*E,6E-E.E02E1E2E43E5E6E89E9E:EE@QEAECEDcEEEGEHxEIEK2ELEMEOKEPERESgETEV%EWEXEZDE[E]E^bE_Ea#EbEcEeCEfEhEicEjEl#EmEnEpBEqEsEtbEuEw ExEyE{E,EEEEEEEEEEEEEE1EFE`E}E˜EEEEAEuE̫EE%EhEͰEEME΢EE[EϿE&EДEE~EEyEE|EEԒE'EտE\EEץEQEEٶEpE/EEܸE݂ERE$EEEEEEkEYELE@E8E4E4E7EE@EApEBED+EEEFEHHEIEKELfEMEO'EPEQESJETEV EWnEXEZ2E[E\E^ZE_EaEbEcEeGEfEh EioEjEl4EmEnEp[EqEs EtEuEwDExEzE{hE|E~*EEրEւJEփEօ EֆhEևE։"E֊E֋E֍:E֎E֏E֑NE EEEEEEEEѱEќEфElEQE7EEEEзEДEpEKE$EEEϭEτE[E0EEEΰE΅EYE.EEEͮE̓EZE1EEE̺E̓EnEJE'EEEE˨EˌErEZEBE-EE EEEEEEEEEEEEEE$EvE?EA4EBECEETEFEHEIxEJEL=EMEOEPfEQES-ETEUEWXEXEZ"E[E\E^PE_EaEbEcEeJEfEhEizEjElEEmEoEptEqEs=EtEvEwiExEz1E{E|E~ZEEց EւEփEօDEֆEֈE։fE֊E֌&E֍E֎E֐@E֑E:E6E0E'EEEEEEEѩEяEtEVE8EEEEЮEЊEdE6E?E@EB\ECEE EFEGEIKEJELEMyENEPDEQESETvEUEWDEXEZE[zE\E^HE_EaEbEcEeOEfEhEiEjElVEmEo%EpEqEs[EtEv)EwExEz\E{E}(E~EEցVEւEքEօEֆEֈHE։E֋ E֌nE֍E֏0E֐E֑EjEeE^ETEHE6E&EEEEEѳEіExEXE7EEEEФE|ETE+EEEϫEERE%EEEΞEpECEEEͼE͏EcE7E EE̺E̒EjEDEEEE˶E˖ExE[E@E(EEEEEEʼEʲEʪEʤEʢEʢEʦEʬEʵEEEEEE0EOEtE˛EEE+EbE̞EE"EkE͸E EaEμEEςEE[EEIEE=EҼE@EEXEEՅE"EElEEE}E7EE۸E~EHEEEEE|E`EGE2E EEEEEEEE EE'E9ENEfEEEEEE+ETEEEEEDEzEEE&EeEEE %E iE E E8E}EE EVEEE7EEE"EtEE E!jE"E$E%jE&E(E)qE*E,#E-~E.E06E1E2E4PE5E7E8oE9E;1EEEEEEEEEEEEEEEEEEEE E(EHEjEEEE E6EfEEEE:EtEEE+EmE E E 6E ~EE EQEEE.E{EEEeEEEZEE!E"XE#E%E&^E'E)E*lE+E-%E.E/E1@E2E4E5aE6E8&E9E:EE@DEAECEDEEEGVEHEJ,EKEMENqEOEQLERET(EUEWEXsEYE[QE\E^0E_EaEb~EcEe^EfEh>EiEkElEmEokEpErJEsEu(EvExEyrEzE|NE}E(EրEւEփmEքEֆBEևE։E֊~E֋E֍QE֎E֐E֑E֒EEEEEEҶEҢEҍEsEZE>EEEEѹEѕEnEGEEEEОErEDEEEϸEψEWE'EEEΕEdE3EEE͢EsEDEEE̼E̐EeEE!EEEEEEEEEEEEEEEE(EDEbEEEEEEKEzEEEELEEEE?EEE E NE E E$ElEEENEEE:EEE2EEE 5E!E"E$@E%E&E(VE)E+E,sE-E/6E0E1E3aE4E6,E7E8E:bE;E=3E>E@EAsEBEDKEEEG%EHEJEKoELENMEOEQ-ERETEUEVEXbEYE[DE\E^(E_Ea EbEcEeeEfEhJEiEk/ElEnEoEpEriEsEuLEvEx.EyE{E|E}E^EրEւE>E?EDELEVEeEvEʋEʤEEEE*EVE˄E˸EE+EjE̯EEFE͙EEKEάEE}EEbEEIEE@EEJEEjEE՝E=EE׍E^E?EA8EBEDEEEFEHcEIEKDELEN(EOEQ ERESEUfEVEXNEYE[6E\E^E_Ea EbEcEeiEfEhSEiEk=ElEn'EoEqErEsEumEvExTEyE{9E|E~EEցEւsEփEօREֆEֈ2E։E֋E֌|E֍E֏TE֐E֒,E֓EXENE@E2E E EEEEҤE҆EdEDEEEEѬEсEUE*EEEСEpE@EEEϬEyEGEEEέEzEGEEEͰEENEEE̾E̐EdE8E EE˼E˔EnEJE(EEEEʲEʚEʂEnE\EME@E5E-E(E&E&E*E0E:EGEXElEʃEʞEʼEEE.E]EˏEEE?ẼEEEhE;EEyEEHEϷE,EОEEцEE҃E EӔE%EԺETEE֗E@EE؞EUEEEےEZE&EEEߢE~E^EBE*EEEEEEEEEEE EE/EFE_E|EEEEE2E^EEEE&E^EEEEPEEE E aE E E:EEEEjEE E]EEEZEE EdE E"E#xE$E&7E'E(E*\E+E-$E.E/E1XE2E4(E5E6E8iE9E;BEE?E@EBmECEEPEFEH4EIEKELENEOxEPERbESEUNEVEX;EYE[)E\E^E_EaEb~EcEenEfEh^EiEkMElEn=EoEq+ErEtEuEwEx|EyE{hE|E~PEEց9EւEք EօEևEֈvE։E֋VE֌E֎6E֏E֑E֒E֓EӈE~EnE]ELE5EEEEEҪE҈EdEAEEEEўEqEDEEEзEЇEVE$EEϾEϊEVE"EEκEΆEREEE͸Ë́ERE!EEE̒EdE6E EE˶EˎEhEBE EEEEʤEʋEsE^EJE:E,E EEE E EEEE*E9ELEbE|EʚEʺEE E6EgE˝EEEVE̜EE9E͌EEFEΪEEπEEeEEJEEDEEQEEtE EժEKEEמENEEټEzE;EEEݚEmEDE EEEEEEEEE{E{E~EEEEEEEEE&EHEkEEEEEFEzEEE E\EEEE_EE E 5E }E EE\EEEHEEEAEEEHEEE YE!E#E$uE%E'8E(E)E+eE,E.2E/E1E2oE3E5FE6E8 E9E:EEMEO2EPER&ESEUEVEXEYE[E\E^E_EaEb~EcEeyEfEhsEiEkmElEnhEoEq`ErEtYEuEwQExEzFE{E}E@JEAEC:EDEF,EGEI EJELEMEOEPER ESEUEVEXEYE[E\E]E_E`EbEcEeEfEh}EiEk}ElEn}EoEq{ErEtyEuEwvExEzsE{E}mE~EրdEցEփZEքEֆOEևE։@E֊E֌0E֍E֏E֐E֒E֓|E֔EEEEEEӳEӘE{E\E;EEEEҤEzENE$EEEѕEdE2EEEЖEaE+EEϾEφEOEEEΩErE:EEE͗EbE.EEE̔EcE2EEE˨E}ESE+EEEʼEʛE}E`EDE,EEEEEEEEEEEEEEEEE0ENEpEʕEEEEVEːEEE\ĘEEQEͬE ErEELEϹE$EДE EуEE҇EEӠE2EEhE EְE\E EؿEyE6EE۾E܈EVE(EEEEEElEZELEAE:E6E6E:E@EKEXEhE{EEEEE E0EXEEEEEHEEEE2ErEEE@EE E E hE EEPEEEHEEEOEEEdEE#E E!E#LE$E&E'E(E*VE+E-.E.E0 E1{E2E4^E5E7FE8E:0E;E=E>E@EAECEDEEEGxEHEJrEKEMnENEPlEQESnETEVoEWEYrEZE\uE]E_yE`Eb~EdEeEgEhEj EkEmEnEpEqEsEtEvEwEyEzE|E}EEրEւEփEօEֆEֈ E։E֋E֌zE֍E֏jE֐E֒XE֓E֕CEFE6E#EEEEEӤEӄEbE>EEEEқEoEAEEEѱEEKEEEЬEvE?EEEϗE^E&EEζE}EDE EE͞EhE3EEE̕EcE2EEEˤExENE$EEEʲEʐEpERE6EEEEEEEɶEɮEɩEɧEɨEɭEɴEɾEEEEE+ELEpEʚEEE,EfEˤEE-EyEEEzEE=EΦEEςEEYEEEEEDEEYEEԂEEսEbE E׺EmE$EEڠEdE-EEEޠEzEXE8EEEEEEEEEEEEEE EE8ETErEEEE E9EhEEEE@E{EEE=EEEE ]E E E ?EEE.EEE.EEE=EEEXEE E!E"E$PE%E'"E(E)E+hE,E.FE/E1*E2E4E5E6E8tE9E;dEZE?EAQEBEDKEEEGHEHEJHEKEMIENEPMEQESRETEVZEWEYaEZE\jE]E_uE`EbEdEeEgEhEjEkEm#EnEp.EqEs7EtEv>EwEyEEzE|LE}EOEրEւPEփEօPEֆEֈLE։E֋HE֌E֎?E֏E֑4E֒E֔$E֕EvEdEQEE?EAEBEDEEEGEHEJEKEM%ENEP-EQES8ETEVDEWEYQEZE\`E]E_oE`EbEdEeEgEhEj'EkEm7EnEpFEqEsUEtEvbEwEyoEzE|yE}EEցEւEք EօEևEֈE֊E֋E֍ E֎E֐E֑E֒E֔xE֕EԥEԓE}EfENE0EEEEӫEӆE^E2EEEҮE|ELEEEѱE|EEEEEОEdE+EE϶E|EAEEEΒEWEEEͪErE:EEE̗EbE.EEE˜ElE@EEEEʜExEVE6EEEEEɶEɤEɔEɇE~EvErErEtEyEɂEɎEɞEɲEEEE$EKEuEʤEEEKEˊEEEhE̻EEpEE:EΧEEuEEOEE?EѾEBEEZEEԆE"EEkEEEzE2EEڰEvEAEEE޷EߒEqESE:E$EEEEEEEEEEE$E8EPEjEEEEEEIExEEEEOEEE ENEEE$EpE E E TE EEJEEENEEEcEE$EEEQE E"#E#E$E&fE'E)EE*E,)E-E/E0E1E3xE4E6kE7E9cE:E<`E=E?^E@EB`ECEEfEFEHoEIEKxEMENEPEQESETEV.EWEYAEZE\UE]E_jE`Eb~Ed EeEg EhEj6EkEmJEnEp_EqEssEtEvExEyE{E|E~.EEց:EւEքFEօEևNEֈE֊TE֋E֍VE֎E֐TE֑E֓RE֔E֖HEEEԬEԒEyEZEEEEϋEOEEEΝEaE&EEͲExE>EEE̘EbE.EEE˘EhE:EEEʺEʒEmEJE(E EEEɹEɣEɐEErEfE^EZEWEYE]EdEpEEɐEɧEEEE$EME|EʮEEE]EˢEE8E̊EE=E͞EEpEE;EϤEEЅEE|EE҆EEӥE;EEvEEErE%EE٘EWEEEܰE݂EXE0EEEEEEEEEEEEEEEEEEEE4EXE|EEEE2EfEEEEREEEEcEEE GE E E 0EEE-EEE9EEEWEEEEE TE!E#*E$E&E'xE(E*]E+E-GE.E06E1E3*E4E6"E7E9E:E<E=E?"E@EB*ECEE4EFEHAEIEKQELENdEOEQxESETEVEWEY1EZE\JE]E_dE`EbEd EeEg(EhEjCEkEm^EnEpxErEsEuEvEx4EyE{KE|E~^EEցqEւEքEֆEևE։E֊E֌E֍E֏"E֐E֒$E֓E֕#E֖EEEEEԢEԆEdECEEEEӦExELEEEҹE҇EQEEEѭEtE;EEEЋEOEEEϚE]E!EEΨEkE/EE͸E}ECE EE̙EcE-EEE˓EbE3EEEʰEʇE`EE@mEAECzEEEFEHEIEK*ELENBEOEQZERETvEVEWEY!EZE\@E]E_`E`EbEdEeEg0EhEjPEkEmpEoEpErEsEu=EvExZEyE{vE}E~EրEցEփ1EքEֆEEևE։TE֊E֌cE֍E֏nE֐E֒tE֓E֕wE֖E4EEEEE԰EԏEkEFEEEEӜEnE>E EEҤEoE8EEEэEREEEРEbE%EEϪElE.EEβEuE8EE;E͂EHE EE̚EbE,EEEˎE\E-EEEʦE|ETE/E EEEɮEɓE|EfESEBE6E,E$E EE"E&E0E=ELE`EwEɓEɲEEE(EXEʍEEECEˊEE%EyEE3E͗EEeEE+EϕEEzEEtEE҂EEӤE;EEyE EEzE.EE٤EeE*EEEݔElEFE%EEEEEEEEEEEEEEEEE*EJEkEEEEEDExEEE$EcEEE.EvEEE]E E E JE EEKEEE^EEEEENEE EE E"jE#E%NE&E(6E)E+%E,E.E/E1E2E4E5E7E8E:E;E=&E>E@6EAECHEDEF\EGEIvEKELENEOEQ>ERET^EUEWEYEZE\6E]E_ZE`EbEdEeEg9EhEj^EkEmEoEpEr;EsEu^EvExEzE{E}0E~EրNEցEփiEքEֆEֈ E։E֋ E֌E֎2E֏E֑=E֒E֔GE֕E֗MEbELE4EEEEԸEԒEmEDEEEӿEӎE\E+EEE҉EREEEѤEiE-EEвEtE6EEϸEzE:EEμE~E@EEE͇EKEEE̛EbE*EE˾EˊEVE&EEEʜEpEHE"EEEɺEɜEɀEhEQE=E,EEE EEEEEEE+E>ETEnEɌEɮEEE.EaEʘEEEZEˤEEFE̟EE`EE,EΊEEWEE9EвE/EѲE:EEXEEԉE(EEwE$EE؎EJEEEەEbE4EEE߿EEEoE]ENEBE;E8E6E:EBELEZElEEEEEEEAElEEEE5EoEEE*EoEEEJEEE 3E E E )EEE3EEENEEE|EEMEE'E E"E#zE$E&cE'E)SE*E,HE-E/CE0E2CE3E5HE6E8QE9E;^EpE?EAECEDEF.EGEIJEJELkEMEOEQERETEEUEWlEYEZE\*E]E_TE`Eb~EdEeEg@EhEjlElEmEo+EpErUEsEu~EwExEz8E{E}^E~EրEւEփEօ.EֆEֈJE։E֋dE֌E֎zE֐E֑E֓E֔E֖E֗EՒEzE`ECE&EEEԺEԒEiE>EEEӯE~EJEEEҥElE3EEѻEEBEEEІEGEEEχEGEEE·EHE EE͌EOEEE̛EbE(EE˺E˄EQEEEʾEʐEfE6E?EAPEBEDnEEEGEI EJELFEMEOnEQERET-EUEWZEXEZE\E]E_NE`EbEdEeEgHEhEjyElEmEoBEpErqEtEuEw4ExEz`E{E}EEրEւEEփEօjEֆEֈE֊E֋E֍6E֎E֐NE֑E֓cE֔E֖sE֗EEթEՎErERE/E EEԺEԐEbE4EEEӝEjE4EEE҈EMEEEїEXEEEЙEXEEEϖETEEEΒEQEEE͒ESEEE̝EbE(EE˸EˁELEEEʶEʈEZE0EEEɼEɘEyE\E@E(EEEEEEEEEEEEEE E$E@E_EɄEɬEE E?ExEʶEEBEˏEE7E̓EEZEͺEEvEEFE϶E+EЦE$EѩE2EETEEԈE)EEzE*EEؖEREEEۤErEDEEEEEEExEkEbE\EZE\EaEjEvEEEEEE E,ETE~EEEEFEEEEEEEʢEpEBEEEEɚEvESE4EEEEEȻEȫEȞEȕEȎEȌEȋEȎEȖEȠEȰEEEEE0EWEɁEɰEEEWEʘEE(EwEE&ẼEEFE͝EE]EE1EϢEEЖEEѝE(EҷELEEԄE'EE{E,EE؛EYEEEۮEESE,EEEEEEEEE|E|EEEEEEEEEEBEhEEEE"EYEEE EPEEE&EsEEEbEE E `E EEsEE7EEElEEDEE%EEE E!E#xE$E&sE'E)tE*E,|E.E/E1E2E4'E5E7BE8E:bE;E=E?E@EBDECEErEG EHEJ>EKEMsEOEPERHESEUEW"EXEZ`E[E]E_?E`EbEd EeEg`EiEjElAEmEoEq!ErEt_EuEwEy:EzE|tE~EEցIEւEք}EֆEևE։EE֊E֌pE֎E֏E֑-E֒E֔NE֕E֗kE֘ERE4EEEEծEՄEZE.EEEԞEjE6EEEӌEQEEEҚEZEEEїEUEEEЊEFEEϽEyE4EEάEhE%EE͟E]EEE̜E^E EE˩EpE8EEEʘEfE6EEEɱEɊEdE@EEEEEȵEȡEȐEȂExEpElEkEnEsE|EȊEțEȰEEEE+ETEɂEɴEE&EeEʪEEBE˖EELE̯E EaEͼEE΂EE]EEMEEPEEiEEӔE1EExE#EE׆E?EEپEڃENEEEEޢE߂EeELE8E(EEEE EEE E.E@ETEmEEEEEEHExEEEEWEEEEfEEEPEEECE E E IE EEfEE0EEEoEENEE6EE $E!E#E$E&E'E)E*E,*E-E/;E0E2RE3E5oE6E8E:#E;E=LE>E@yEBECEEDEFEHzEJEKEMQENEPER.ESEUnEWEXEZRE[E]E_8E`Eb~Ed!EeEggEi EjElPEmEoEq8ErEt|EvEwEy_EzE|E~=EEցxEփEքEֆNEևE։E֋E֌E֎KE֏E֑uE֓E֔E֖.E֗E֙LEւEdEEE$EEEծEՂEUE&EEEԍEWEEEӫEmE1EEҳErE1EEѬEhE$EEКEUEEEτE>EEδEoE*EE͢E`EEE̛E[EEEˤEiE/EEEʌEYE(EEEɠEwEPE+E EEEȲEȚEȅEtEdEXEPEKEHEJENEXEcEsEȇEȞEȺEEE&EREɄEɹEE2EuEʽE E\E˴EEsEE"E|EE?EΨEEϊEEЁEEыEEҪE?EE{E EEwE*EE؜E]E"EE۸E܉E`E9EEEEEEEEEEEEEEEEEE3EUE{EEEE3EjEEEEbEEE;EEE+E|EE %E }E E 5EEE\EE-EEEvEE\EEJEE!BE"E$>E%E'DE(E*PE+E-bE.E0zE2E3E5)E6E8OE9E;zE=E>E@CEAECxEEEFEHQEIEKEM/ENEPqERESEUYEVEXEZEE[E]E_4E`EbEd$EeEgpEiEjElaEnEoEqPErEtEv=EwEyE{'E|E~jEր EցEփKEքEֆEֈ&E։E֋\E֌E֎E֐)E֑E֓VE֔E֖E֘E֙EֲE֒ErENE*EEEիE|ELEEE԰EwE>EEEӋELE EEҊEHEEE{E6EEЪEdEEEϐEIEEμEuE0EEͦEbEEE̚EYEEE˞EbE(EEʶEʁEMEEEɻEɐEeEEEYEEӈE&EEqEEEׄE?EEEڈEVE&EEEްEߒExEaEOE@E6E0E.E.E2EEsE@EAECHEDEFEH'EIEKjEM ENEPUEQESEUDEVEXEZ8E[E]E_/E`EbEd&EeEgwEi EjElpEnEoEqhEsEtEv\ExEyE{LE|E~Eր9EցEփ~EօEֆEֈ`E։E֋E֍7E֎E֐nE֒E֓E֕8E֖E֘`E֙EEE֠E{EVE+EEEդEqE>EEEԘE_E"EEӧEhE&EEҢE^EEEюEHEEкErE*EEϜETE EE}E6EEͪEdE EE̚EXEEE˘E\E EEʬEvE@E EEɬE~ESE*EEEȼEȝEȀEgEPEE?EAGEBEDEF0EGEI|EK$ELENsEPEQESpEUEVEXrEZE[E]wE_$E`Eb~Ed,EeEgEi4EjElEnEEӹEtE.EEҡEYEEE}E3EEНEQEEϺEoE#EE΍ECEEͰEgEEE̒ELEEE˂EBEEEʉENEEEɩEvEFEEEȿEȘErEPE/EEEEEǺEǫEǡEǘEǕEǓEǗEǝEǨEǵEEEEE:E`EȌEȻEE*EhEɫEE@EʒEEGE˛EE8ȄEEMEͳEEΐEEρEEЇEEџE4EEiE EԴE`EEE~E=EEEړEcE8EEEE߶EEEEvEpEoEqEwEEEEEEEE3E[EEEEEYEEEEaEEEJEEEDEEEOE E E tE EEEE EEE|EEpEEmEEtE E"E$ E%E'%E(E*GE+E-pE/E0E2:E3E5rE7E8E:QE;E=E?EEE՘E\EEEԞE^EEEӏEHEEҹEoE&EEяEDEEЫE`EEExE-EEΔEIEEͲEiEEE̐EIEE˿E|E:EEʺE|E@EEEɘEdE2EEEȩEȀEZE6EEEEEǬEǘEljE~EtEoEnEnEtE}ENJEǜEǰEEEE.EYEȈEȻEE1EsEɺEEWEʮE E\E˧EELE̦EEkEEDEιE2EϱE4EоEKEEvEEӲEXEEղEfEEE؜EdE.EEEܩE݅EeEJE4E EEEEEEEEE.EDE]EzEEEEECEtEEE!EbEEE9EEE,EEE*EEE @E E E pEEHEE,EEEEEEEEE E"*E#E%DE&E(fE)E+E-%E.E0XE1E3E51E6E8tE:E;E=`E?E@EBZEDEEEG[EI EJELfENEOEQvES)ETEVEX@EYE[E]]E_E`Eb{Ed1EeEgEiOEkElEnoEp#EqEsEu@EvExEzWE| E}EkEցEւEքvEֆ%EևE։|E֋&E֌E֎xE֐ E֑E֓jE֕ E֖E֘NE֙E֛EE׮E׆E\E1EEE֝EhE0EEջE~E?EEԽEzE5EEӪEbEEE҅E:EEѡETEEкElEEEςE4EEΚEMEEʹEiEEĚEDEE˸EsE0EEʯEpE3EEɾEɆEQEEEȾEȑEfE@EEEEǻEǡENJEvEfEXENEHEDEEEJERE^EnEǁEǙEǵEEE$EREȅEȼEE9E~EEEoEEEdE˳EE_E̾E E͊EEjEE`EEiEEцEEҸEWEEԥEREE־ExE:EEEږEiE@EEEEEEEEEEEEEEEEEE'EKErEEEE6EqEEE3E{EEEfEEEdEEEsEE 6E E EqEEQEE;EE0EE.EE6EE FE!E#`E$E&E(E)E+@E,E.tE0E1E3NE4E6E86E9E;E=*E>E@}EB(ECEEEG2EHEJELCEMEOEQ\ESETEVyEX/EYE[E]RE_ E`EbxEd/EeEgEiWEkElEn}Ep4EqEsEuWEw ExEzvE|,E}EEցCEւEքEֆUEֈE։E֋\E֍ E֎E֐\E֒E֓E֕PE֖E֘E֚8E֛EEE׶E׊E\E,EEE֎EUEEEՠE`EEEԗERE EEzE0EEҙELEEѱEcEEEwE(EEωE:EEΝEOEEʹEgEEĔE=EEˮEiE$EEʠE`E"EEɫErEE@MEAECEEZEG EHEJpEL#EMEOEQCERETEVhEX EYE[E]KE_E`EbxEd2EeEgEi`EkElEnEpGErEsEurEw*ExEzE|OE~EEցoEփ!EքEֆEֈ8E։E֋E֍EE֎E֐E֒HE֓E֕E֗EEԴEnE&EEӒEGEEҭE`EEEsE$EEЂE2EEϒEAEEΡEQEEʹEgEEÊE7EE˦E`EEEʒEREEEɘE^E&EEȽEȋE\E0EEEǹEǗExE\EBE,EE EEEEEEEE EE3ENElEǏEǶEEEGEȁEEEMEɛEEGEʖEE(ExEE)E̊EE[EE@EλE:EEHEEjEEҠEBEEԔEFEEֵEsE6EEEښEpEIE'E EEEEEEEEEEEEEE#EDEgEEEEESEEE EPEEE4EEE4EEE=EEE cE E 6E EEEExEErEEuEEE EE!(E"E$LE%E'xE)E*E,HE-E/E1)E2E4rE6E7E9jE;EoE@EAEC~EE2EFEHEJMELEMEOrEQ*ERETEVVEXEYE[E]AE^E`EbvEd2EeEgEihEk$ElEnEpYErEsEuEwDExEzE|rE~(EEցEփMEօEֆEֈjE֊E֋E֍}E֏+E֐E֒E֔0E֕E֗E֙(E֚E֜qEdE>E?EAECTEEEFEHtEJ,EKEMEOVEQERETEVDEXEYE[|E]:E^E`EbvEd4EeEgEirEk0ElEnEplEr*EsEuEwbEyEzE|E~PEր EցEփ|Eօ2EֆEֈE֊RE֌E֍E֏hE֑E֒E֔tE֖ E֗E֙rE֛E֜EؗEnEBEEE׬EvE>EEEֈEHEEE}E6EEԦEYEEEsE$EE҄E4EEѐE=EEИEDEEϞELEEΦETEEͲEaEEEuE(EEˑEHEEʹEtE0EEɮEpE2EEEȊEVE$EEEǞEwERE1EEEEEƶEƨEƜEƕEƐEƐEƕEƜEƧEƶEEEEEDEmEǜEEEBEȅEEEiEE EOEʘEE9EːEERE̺E'E͚EEΏEEϘE$EеEJEE҅E*EEԂE4EE֩EjE0EEEڜEtEQE1EEEEEEEEEEEE E"E>E^EEEEE7EnEEE(EnEEETEEEWEEEeEE(EE E fE EJEE8EE3EE6EEEEE]EE ~E"E#E%BE&E(xE*E+E-ZE.E0E2KE3E5E7KE8E:E E?EArEC(EDEFEHNEJ EKEM~EO;EPERETsEV1EWEYE[pE]1E^E`EbtEd5EeEgEiyEk:ElEnEp}Er>EsEuEw}Ey;EzE|E~sEր0EցEփEօ`EևEֈE֊E֌EEʬEeE!EEɜE\EEEȨEqEELE]ErEƍEƫEEE"ESEljEEEGEȑEE6EɁEEEPEʡEERE˲EÊEEgEEaEEoEEВE*EEjEEӾEoE$EE֞EbE+EEEڠE|E[E?E(EEEEEEEEEE*EAE\E|EEEE"EUEEEEIEEE(ExEE&EEE2EEEXEE -E E E EEvEEtEE}EEE EEBEE!pE# E$E&CE'E)E+)E,E.wE0 E1E3yE5(E6E8E:>E;E=E?_EAEBEDEFIEHEIEKEMCEOEPERETJEV EWEYE[YE]E^E`EboEd5EeEgEiEkMEmEnEpErcEt(EuEwEyrE{6E|E~EրyEւ:EփEօEևsE։0E֊E֌E֎]E֐E֑E֓~E֕2E֖E֘E֚BE֛E֝E.EEE؞EfE0EE׹E|E:EEֳEnE'EEՓEEEEԨEZEEӷEdEEҼEfEEѻEeEEжE_E EϲEZEEέEWEEͬEXEE̱E`EE˾EoE"EEʋEBEEɴEpE.EEȯErE8EEEǘEhE:EEEEƟEƀEdEJE5E"EEEEEEE EE%E:ESEoEƒEƸEEEGEǂEEEMEțEE8EwEɻEESEʨEEaEE.E̝EE͋E EΌEEϢE5EEhE EҰE[E EEzE9EEEؐEaE7EEEEݼEިEߘEEEEEEEEEEE E/EXEEEEEXEEE!ElEE EbEEElEE(EEE[EE 7E E !EEEEEE#EE:EE\EEE!E"E$XE%E'E)>E*E,E.4E/E1E3EEȶEvE6EEELjEREEEEƖEnEIE'EEEEEŮEŠEŘEŐEŎEŐEŖEŠEŬEEEEE6E^EƌEƾEE2EtEǼEEZEȠEEEeEɲEE[EʷEEˁEE_EEREEYEEtE EХEFEEғEAEEԬEjE+EE׽E،EaE:EEEEE޼E߲EEEEEEEEE E,EPEwEEEE?E{EEEFEEE5EEEAEEEZEE&EEE rE E `E EYEE`EEqEEE EELEE E" E#E%dE' E(E*ZE,E-E/bE1E2E4zE60E7E9E;\E=E>E@EBTEDEEEGEI`EK%ELENEP{ERCET EUEWEYlE[7E]E^E`EbhEd5EfEgEiEkhEm5EoEpErEtdEv/EwEyE{E}VEEրEւEքpEֆ6EևE։E֋|E֍E@iEB,ECEEEGyEI?EKELENEPbER-ESEUEWEY^E[,E\E^E`EbfEd4EfEgEiEkpEm?EoEpErEtxEvDExEyE{E}sE=EցEւEքEֆ^Eֈ"E։E֋E֍mE֏.E֐E֒E֔gE֖#E֗E֙E֛LE֜E֞EEEْEYEEEأE`EEE׎ECEE֫E]E EչEgEEԼEfEEӶE\EEҧELEEѓE6EE}EEEfE EέEPEE͚E@EE̎E6EEˊE5EEʐE@EEɣEXEEEȀEEE (E E "EE&EE6EETEEzEEEIEE!E#.E$E&|E(&E)E+E-3E.E0E2QE4 E5E7~E9|E@>EBECEEEGUEIEJELEN}EPIERESEUEWEYPE[E\E^E`EbbEd2EfEgEiEkvEmHEoEpErEtEvWEx&EyE{E}E[Eց&EւEքEֆEֈJE֊E֋E֍E֏\E֑E֒E֔E֖ZE֘E֙E֛E֝EEЂE"EEfEEΩELEE͒E7EÊE(EEyE"EE{E)EEɊEPE@EAECEEjEG4EHEJELENdEP2ERESEUEWqEYBE[E\E^E`Eb^Ed1EfEgEiEk~EmQEo$EpErEtEvkEx;Ez E{E}ExEցFEփEքEֆEֈqE֊:E֌E֍E֏E֑PE֓E֔E֖E֘NE֚ E֛E֝|E֟2EbE+EEٸEzE;EEزElE#EE׌E&E?EAEC~EEHEGEHEJEL|ENJEPEQESEUEWbEY5E[ E\E^E`Eb\Ed0EfEgEiEkEmZEo/EqErEtEv~ExQEz"E{E}EEցdEփ3EօEֆEֈE֊dE֌*E֍E֏E֑E֓CE֕E֖E֘E֚BE֛E֝E֟p ================================================ FILE: data/default.conv ================================================ CONV NORM # 3x3 ``all-ground'' convolution mask with FWHM = 2 pixels. 1 2 1 2 4 2 1 2 1 ================================================ FILE: data/default.nnw ================================================ NNW # Neural Network Weights for the SExtractor star/galaxy classifier (V1.3) # inputs: 9 for profile parameters + 1 for seeing. # outputs: ``Stellarity index'' (0.0 to 1.0) # Seeing FWHM range: from 0.025 to 5.5'' (images must have 1.5 < FWHM < 5 pixels) # Optimized for Moffat profiles with 2<= beta <= 4. 3 10 10 1 -1.56604e+00 -2.48265e+00 -1.44564e+00 -1.24675e+00 -9.44913e-01 -5.22453e-01 4.61342e-02 8.31957e-01 2.15505e+00 2.64769e-01 3.03477e+00 2.69561e+00 3.16188e+00 3.34497e+00 3.51885e+00 3.65570e+00 3.74856e+00 3.84541e+00 4.22811e+00 3.27734e+00 -3.22480e-01 -2.12804e+00 6.50750e-01 -1.11242e+00 -1.40683e+00 -1.55944e+00 -1.84558e+00 -1.18946e-01 5.52395e-01 -4.36564e-01 -5.30052e+00 4.62594e-01 -3.29127e+00 1.10950e+00 -6.01857e-01 1.29492e-01 1.42290e+00 2.90741e+00 2.44058e+00 -9.19118e-01 8.42851e-01 -4.69824e+00 -2.57424e+00 8.96469e-01 8.34775e-01 2.18845e+00 2.46526e+00 8.60878e-02 -6.88080e-01 -1.33623e-02 9.30403e-02 1.64942e+00 -1.01231e+00 4.81041e+00 1.53747e+00 -1.12216e+00 -3.16008e+00 -1.67404e+00 -1.75767e+00 -1.29310e+00 5.59549e-01 8.08468e-01 -1.01592e-02 -7.54052e+00 1.01933e+01 -2.09484e+01 -1.07426e+00 9.87912e-01 6.05210e-01 -6.04535e-02 -5.87826e-01 -7.94117e-01 -4.89190e-01 -8.12710e-02 -2.07067e+01 -5.31793e+00 7.94240e+00 -4.64165e+00 -4.37436e+00 -1.55417e+00 7.54368e-01 1.09608e+00 1.45967e+00 1.62946e+00 -1.01301e+00 1.13514e-01 2.20336e-01 1.70056e+00 -5.20105e-01 -4.28330e-01 1.57258e-03 -3.36502e-01 -8.18568e-02 -7.16163e+00 8.23195e+00 -1.71561e-02 -1.13749e+01 3.75075e+00 7.25399e+00 -1.75325e+00 -2.68814e+00 -3.71128e+00 -4.62933e+00 -2.13747e+00 -1.89186e-01 1.29122e+00 -7.49380e-01 6.71712e-01 -8.41923e-01 4.64997e+00 5.65808e-01 -3.08277e-01 -1.01687e+00 1.73127e-01 -8.92130e-01 1.89044e+00 -2.75543e-01 -7.72828e-01 5.36745e-01 -3.65598e+00 7.56997e+00 -3.76373e+00 -1.74542e+00 -1.37540e-01 -5.55400e-01 -1.59195e-01 1.27910e-01 1.91906e+00 1.42119e+00 -4.35502e+00 -1.70059e+00 -3.65695e+00 1.22367e+00 -5.74367e-01 -3.29571e+00 2.46316e+00 5.22353e+00 2.42038e+00 1.22919e+00 -9.22250e-01 -2.32028e+00 0.00000e+00 1.00000e+00 ================================================ FILE: data/default.param ================================================ NUMBER X_IMAGE Y_IMAGE XWIN_IMAGE YWIN_IMAGE X2_IMAGE Y2_IMAGE XY_IMAGE ERRX2_IMAGE ERRY2_IMAGE ERRXY_IMAGE A_IMAGE FLUX_APER(1) FLUXERR_APER(1) KRON_RADIUS FLUX_AUTO FLUXERR_AUTO FLUX_RADIUS(3) FLAGS ================================================ FILE: data/default.sex ================================================ # Default configuration file for SExtractor 2.5.0 # EB 2006-07-14 # #-------------------------------- Catalog ------------------------------------ CATALOG_NAME test.cat # name of the output catalog CATALOG_TYPE ASCII_HEAD # NONE,ASCII,ASCII_HEAD, ASCII_SKYCAT, # ASCII_VOTABLE, FITS_1.0 or FITS_LDAC PARAMETERS_NAME default.param # name of the file containing catalog contents #------------------------------- Extraction ---------------------------------- DETECT_TYPE CCD # CCD (linear) or PHOTO (with gamma correction) DETECT_MINAREA 5 # minimum number of pixels above threshold DETECT_THRESH 1.5 # or , in mag.arcsec-2 ANALYSIS_THRESH 1.5 # or , in mag.arcsec-2 FILTER Y # apply filter for detection (Y or N)? FILTER_NAME default.conv # name of the file containing the filter DEBLEND_NTHRESH 32 # Number of deblending sub-thresholds DEBLEND_MINCONT 1.0 # Minimum contrast parameter for deblending CLEAN Y # Clean spurious detections? (Y or N)? CLEAN_PARAM 1.0 # Cleaning efficiency MASK_TYPE NONE # type of detection MASKing: can be one of # NONE, BLANK or CORRECT #------------------------------ Photometry ----------------------------------- PHOT_APERTURES 10.0 # MAG_APER aperture diameter(s) in pixels PHOT_AUTOPARAMS 2.5, 0.0 # MAG_AUTO parameters: , PHOT_PETROPARAMS 2.0, 3.5 # MAG_PETRO parameters: , # PHOT_AUTOAPERS 0.0,0.0 # , minimum apertures # for MAG_AUTO and MAG_PETRO PHOT_FLUXFRAC 0.1,0.5,0.6 # flux fraction[s] used for FLUX_RADIUS SATUR_LEVEL 50000.0 # level (in ADUs) at which arises saturation MAG_ZEROPOINT 0.0 # magnitude zero-point MAG_GAMMA 4.0 # gamma of emulsion (for photographic scans) GAIN 0.0 # detector gain in e-/ADU PIXEL_SCALE 1.0 # size of pixel in arcsec (0=use FITS WCS info) #------------------------- Star/Galaxy Separation ---------------------------- SEEING_FWHM 1.2 # stellar FWHM in arcsec STARNNW_NAME default.nnw # Neural-Network_Weight table filename #------------------------------ Background ----------------------------------- BACK_SIZE 64 # Background mesh: or , BACK_FILTERSIZE 3 # Background filter: or , BACKPHOTO_TYPE GLOBAL # can be GLOBAL or LOCAL #------------------------------ Check Image ---------------------------------- CHECKIMAGE_TYPE BACKGROUND,BACKGROUND_RMS # can be NONE, BACKGROUND, BACKGROUND_RMS, # MINIBACKGROUND, MINIBACK_RMS, -BACKGROUND, # FILTERED, OBJECTS, -OBJECTS, SEGMENTATION, # or APERTURES CHECKIMAGE_NAME back.fits,rms.fits # Filename for the check-image #--------------------- Memory (change with caution!) ------------------------- MEMORY_OBJSTACK 3000 # number of objects in stack MEMORY_PIXSTACK 300000 # number of pixels in stack MEMORY_BUFSIZE 1024 # number of lines in buffer #----------------------------- Miscellaneous --------------------------------- VERBOSE_TYPE NORMAL # can be QUIET, NORMAL or FULL WRITE_XML N # Write XML file (Y/N)? XML_NAME sex.xml # Filename for XML output ================================================ FILE: data/image.cat ================================================ # 1 NUMBER Running object number # 2 X_IMAGE Object position along x [pixel] # 3 Y_IMAGE Object position along y [pixel] # 4 XWIN_IMAGE Windowed position estimate along x [pixel] # 5 YWIN_IMAGE Windowed position estimate along y [pixel] # 6 X2_IMAGE Variance along x [pixel**2] # 7 Y2_IMAGE Variance along y [pixel**2] # 8 XY_IMAGE Covariance between x and y [pixel**2] # 9 ERRX2_IMAGE Variance of position along x [pixel**2] # 10 ERRY2_IMAGE Variance of position along y [pixel**2] # 11 ERRXY_IMAGE Covariance of position between x and y [pixel**2] # 12 A_IMAGE Profile RMS along major axis [pixel] # 13 FLUX_APER Flux vector within fixed circular aperture(s) [count] # 14 FLUXERR_APER RMS error vector for aperture flux(es) [count] # 15 KRON_RADIUS Kron apertures in units of A or B # 16 FLUX_AUTO Flux within a Kron-like elliptical aperture [count] # 17 FLUXERR_AUTO RMS error for AUTO flux [count] # 18 FLUX_RADIUS Fraction-of-light radii [pixel] # 21 FLAGS Extraction flags 1 165.1449 24.0084 165.0857 24.2189 2.4117662184e+00 5.1111829531e+00 -2.9781834691e+00 3.2237837858e-02 7.0561272861e-02 -4.0335820676e-02 2.652 4709.64 580.0665 6.79 7544.724 1077.636 1.397 3.507 4.704 0 2 81.4250 12.3010 81.4266 12.2372 1.7979278944e+00 1.5856033331e+00 -2.7684534399e-02 1.7951855662e-04 1.8787411640e-04 -2.2413198032e-05 1.342 78021.47 579.623 2.95 75826.24 448.7831 0.486 1.211 1.441 0 3 1.4540 10.0726 1.3311 10.2653 2.4788523667e-01 5.9632656000e-01 3.8536281706e-03 6.7016358905e-03 1.7861245422e-02 -8.8750891817e-05 0.772 3036.964 457.2961 6.27 2422.463 370.3076 0.473 1.365 1.703 24 4 56.9256 3.7007 56.0734 4.5638 3.1260762632e+00 3.0958685371e+00 -1.9024062184e+00 9.5447692222e-03 9.5072527517e-03 -5.3677773815e-03 2.239 8434.928 544.0812 0.83 1955.393 146.3769 0.394 0.966 1.070 24 5 72.1789 1.3798 72.2420 1.1556 1.3696335560e+00 2.3555181249e-01 9.7951755535e-02 3.1362187195e-02 4.5511964013e-03 2.2885012662e-03 1.174 2020.332 453.1542 3.13 2143.885 236.0257 0.421 1.122 1.278 24 6 22.7142 244.3529 22.8570 244.3272 9.1893776577e-01 8.3794196752e-01 -1.4270150242e-01 1.3915903687e-02 1.3795759035e-02 -2.2318076518e-03 1.013 3485.881 579.7709 3.93 2869.198 419.1597 0.525 1.447 1.659 0 7 212.9744 239.4159 212.8007 238.7787 6.7864568155e-01 3.6641493373e+00 2.8162026428e-01 5.7771711903e-03 3.1329635742e-02 2.2186015283e-03 1.921 6211.966 580.2142 4.68 5228.282 667.5814 0.784 2.226 2.537 0 8 33.5458 224.5266 33.1938 224.5793 8.9323061747e-01 6.5998523817e-01 -4.8052227732e-01 3.4045596124e-02 2.5799444980e-02 -1.9403836274e-02 1.127 2624.908 579.9187 2.77 1761.229 253.5323 0.574 1.341 1.537 0 9 115.3960 240.4926 115.3567 240.5046 1.5097465362e+00 1.4156012315e+00 1.2556133767e-01 2.6252888502e-03 2.3371204166e-03 2.6047653189e-04 1.264 12136.01 579.1793 4.00 12109.51 570.6823 0.558 1.366 1.626 0 10 234.6673 216.6405 234.9733 216.9610 9.0781870100e-01 8.6570331106e-01 1.7184768190e-01 1.6547326879e-02 1.6513473943e-02 2.6424896208e-03 1.030 2026.462 579.7709 0.00 0 0 0.000 0.000 0.000 0 11 1.4244 210.1944 1.5846 210.8649 2.4428935934e-01 1.4986581068e+00 1.1161394201e-01 6.4146691915e-03 4.4849969733e-02 3.2165567731e-03 1.228 2906.556 455.7943 7.78 4233.695 566.9153 0.813 3.127 4.125 24 12 126.3193 207.9244 126.4065 207.8384 4.4138060722e-01 5.4136281442e-01 -1.2506805858e-02 1.4050698022e-02 1.6518540620e-02 -7.2711627498e-05 0.737 2847.838 580.9523 7.53 2615.73 610.5865 0.608 1.515 1.836 0 13 176.8328 205.2646 176.9555 205.0126 1.2430840404e+00 9.6709083134e-01 -4.4283292007e-02 1.0837750829e-02 7.6174978439e-03 -5.4053560779e-04 1.118 4001.79 580.0665 0.37 452.7749 65.46175 0.183 0.409 0.446 0 14 81.5943 197.2497 81.7258 197.3103 8.8395022323e-01 4.9334948413e-01 4.5089791911e-03 1.3488115882e-02 7.1648024744e-03 5.9706989770e-05 0.940 4147.688 579.9187 5.89 3723.357 547.6923 0.563 1.565 1.884 0 15 22.8032 191.6743 22.8918 191.1192 1.3003014402e+00 4.2147360613e+00 -1.5908296933e-01 6.5243195907e-03 1.9617403228e-02 -1.3393181362e-04 2.055 8182.402 579.3272 4.08 8237.939 714.1033 0.931 2.595 2.981 0 16 233.0300 183.0266 233.0359 182.9746 3.2121599631e+00 2.9102986441e+00 3.0935602815e-03 1.5291224919e-05 1.5270049771e-05 -1.2967724297e-06 1.792 1004553 580.0665 2.75 998347.2 543.7661 0.612 1.640 1.843 4 17 124.8712 189.9921 124.8031 189.9999 1.9026738805e+00 1.9457039936e+00 5.3130651033e-02 3.4202131509e-03 3.4949183558e-03 -9.7341542004e-05 1.408 13212.11 579.9187 3.75 13295.8 610.5865 0.632 1.750 2.027 0 18 77.2926 186.9532 82.5216 184.5483 2.3459953858e+00 1.7389754354e+00 2.0690917437e-01 2.8257480493e-03 2.1636539737e-03 2.8359715067e-04 1.552 18407.47 580.2142 7.91 53166.81 1299.379 1.155 7.508 8.066 0 19 84.8175 183.2709 84.9144 183.3622 1.9151695812e+00 1.7684776165e+00 2.3078230029e-01 8.7816358526e-04 8.1155977924e-04 7.4556704219e-05 1.444 31243.29 580.2142 4.52 32367.72 711.0966 0.540 1.490 1.758 0 20 210.5223 182.8607 210.5312 182.9656 2.2205229812e+00 2.2175936767e+00 5.6598746252e-01 3.4695699422e-03 3.4456898369e-03 1.0645239773e-03 1.669 15746.95 580.5095 4.80 18501.22 814.9922 0.694 2.123 2.620 0 21 122.4357 172.8911 122.3732 173.0247 7.8032857673e-01 7.7996229380e-01 2.6155691729e-01 1.3987586464e-02 1.2636714697e-02 5.0756379778e-03 1.021 3432.119 579.7709 5.66 3285.699 566.9153 0.559 1.514 1.762 0 22 206.5580 168.1489 206.5395 168.2441 1.2755426427e+00 1.6647677698e+00 2.4685295277e-01 1.5532259891e-02 1.9608954908e-02 2.8701604426e-03 1.336 4988.586 580.0665 5.82 5378.024 812.3589 0.969 2.297 2.649 0 23 176.1984 165.8539 176.1821 165.9459 4.0880717061e-01 4.3695100873e-01 -1.2462935529e-01 1.8536748184e-02 1.8513884500e-02 -5.4149039160e-03 0.740 1656.963 579.623 5.38 1709.566 398.1883 0.280 1.172 1.438 0 24 218.9129 162.9750 218.9429 162.9600 1.5646901592e+00 1.9805201012e+00 -1.3006395294e-01 2.7129379089e-03 4.0902085942e-03 -3.3032119626e-04 1.421 13164.45 579.623 3.88 13212.33 592.7813 0.563 1.687 2.040 0 25 6.8210 161.4874 6.6741 161.4759 7.4051616485e-01 8.4505753283e-01 2.7952330817e-01 1.2745838912e-02 1.4204365347e-02 5.1717611973e-03 1.038 3896.863 579.4752 6.43 4353.308 648.0382 0.660 2.093 2.576 16 26 140.8053 156.7552 140.6863 156.6514 1.3160578293e+00 1.2799210328e+00 -1.9101699285e-01 1.3896838871e-02 1.3954113580e-02 -2.1478801009e-03 1.221 4630.906 580.0665 4.25 4457.219 563.1232 0.771 1.830 2.113 0 27 5.0226 153.3513 5.0850 153.3677 1.3812093478e+00 1.2819452292e+00 -2.2326673013e-03 8.9035663925e-04 8.4140382481e-04 -2.1665867313e-05 1.175 21015.76 575.319 3.49 21071.05 481.0436 0.454 1.223 1.425 16 28 103.2910 152.5820 103.2535 152.6135 6.4848157511e-01 7.6408434055e-01 5.0379488014e-02 8.6562006108e-03 1.0807836265e-02 7.9379326869e-04 0.885 3362.644 579.4752 5.89 3279.901 578.1425 0.523 1.223 1.440 0 29 76.6010 151.1864 76.6541 151.2111 1.3999388931e+00 1.1112912740e+00 1.5930004630e-03 2.3345822065e-03 1.6702193987e-03 1.8207497770e-05 1.183 11755.46 578.7352 3.15 11876.7 419.1597 0.458 1.236 1.459 0 30 129.5452 146.2858 129.5487 146.1160 3.1133800305e+00 5.3239438571e+00 1.8301126982e-01 7.4243575058e-04 1.2735389866e-03 3.7016321270e-05 2.311 51816.11 580.5095 3.45 56351.17 812.3589 0.918 2.491 2.892 0 31 89.0675 143.7518 84.4797 142.1559 5.5994070433e+00 1.0052363481e+01 6.5643207439e+00 2.6912706507e-02 4.7340619417e-02 3.1284416162e-02 3.842 6566.429 580.0665 7.00 17896.88 1547.724 1.952 6.832 8.261 0 32 34.7971 148.4138 34.8603 148.5050 8.3906106653e-01 1.1307593979e+00 -4.5818928705e-02 7.0951137946e-03 1.0140561266e-02 -2.7906536578e-04 1.067 4014.413 578.7352 3.24 4044.449 370.3076 0.575 1.436 1.621 0 33 17.9253 148.7255 17.4456 148.1665 9.3806024958e-01 5.5751045660e-01 2.5907018727e-01 2.9432261709e-02 1.8451949905e-02 9.1285654894e-03 1.034 3489.805 580.8047 6.90 3874.485 654.6175 0.843 2.618 3.120 0 34 81.0779 139.0028 81.0958 139.0168 1.2678291601e+00 1.0082149482e+00 -3.3797846878e-03 9.5137392418e-03 7.7776704753e-03 -4.2823041258e-07 1.126 6200.853 579.3272 5.60 6685.173 689.6823 0.611 1.876 2.493 0 35 218.5678 130.0323 218.9711 130.0449 1.1689442136e+01 9.5585724021e+00 -3.6777932942e+00 3.5098971765e-03 2.3493017249e-03 -9.5219415775e-04 3.802 57362.85 580.3619 3.77 89893.6 1379.365 1.225 3.921 4.660 0 36 89.4507 126.8091 89.4414 126.8328 1.6596069607e+00 2.4932080519e+00 1.0754182190e-01 2.6304785127e-03 4.2651740438e-03 5.7314782745e-05 1.583 13217.83 580.0665 3.88 12943.47 644.7234 0.714 1.809 2.068 0 37 104.4412 122.8610 104.3818 122.7879 3.4087896329e+00 3.9765890605e+00 6.4469355515e-01 3.6978043271e-03 4.1752324219e-03 7.6977483418e-04 2.097 21058.86 579.9187 3.58 23111.04 788.2638 0.957 2.600 3.018 0 38 30.3909 124.9055 30.3670 124.9288 8.9279646237e-01 1.1431711101e+00 1.1754521397e-01 4.4565946732e-03 6.8290280311e-03 6.9222772832e-04 1.091 6198.514 579.3272 4.54 5781.133 519.5865 0.495 1.411 1.660 0 39 204.1013 110.0606 203.8184 110.3018 1.8920460791e+00 2.1392097162e+00 -1.2630947095e+00 1.2481055481e-02 1.4558216099e-02 -8.8432249947e-03 1.812 6019.898 580.6572 4.70 6333.816 677.1415 0.709 2.029 2.313 0 40 173.0723 106.6498 173.1069 106.6595 1.9147865609e+00 9.6876633356e-01 1.2532614375e-01 9.5476547091e-03 4.2704604504e-03 5.3201158259e-04 1.390 6677.315 580.0665 6.44 9942.471 861.0148 0.765 2.402 3.055 0 41 179.6409 104.8785 180.1434 105.1714 1.5979411321e+00 1.3388743338e+00 1.0337985111e+00 2.1498056547e-02 1.7153731768e-02 1.3426474409e-02 1.584 4101.509 579.9187 4.62 3156.618 551.5905 0.627 1.582 1.793 0 42 220.0769 98.6018 220.1460 98.6770 1.8652596082e+00 1.8098822241e+00 5.6603409876e-01 3.2996009007e-03 3.0056113916e-03 8.3250914666e-04 1.551 12269.54 579.3272 3.16 11999.49 485.4773 0.667 1.684 1.940 0 43 155.6567 92.2263 155.7182 92.1221 2.2240728437e+00 3.7869086181e+00 3.1132739644e-03 4.3877993545e-03 7.8076305794e-03 2.9309692871e-05 1.946 14439.71 580.0665 4.83 17693.61 955.3828 0.860 2.703 3.277 0 44 240.5087 86.1174 240.5720 86.1796 9.3597469159e-01 2.9418100962e+00 6.9620376421e-01 7.5811265204e-03 2.4480372552e-02 5.7744491982e-03 1.778 5774.488 581.0998 3.60 5538.605 502.8212 0.834 2.088 2.610 0 45 230.7654 85.3477 230.8361 85.4820 1.2973130755e+00 1.4837870179e+00 3.1494803758e-01 4.9420304813e-03 5.8454580762e-03 1.2056974130e-03 1.311 6945.923 580.2142 2.24 6240.462 307.0428 0.568 1.387 1.601 0 46 58.7937 73.5430 58.7834 73.5915 5.2046036398e-01 8.4353408526e-01 3.3024782946e-02 9.9674683407e-03 1.8720557385e-02 -4.8393331367e-06 0.920 3150.871 579.7709 5.36 2948.146 511.2726 0.572 1.444 1.715 0 47 115.0668 70.0057 115.1836 70.0246 5.9532796353e-01 5.8441327141e-01 1.3453996846e-02 1.4550274566e-02 1.4454348241e-02 8.1937525713e-06 0.777 2428.331 580.0665 5.22 2336.701 443.9832 0.481 1.300 1.467 0 48 8.3200 65.4199 8.4308 65.7110 2.2437375977e+00 3.6969794533e+00 7.8300118255e-01 5.2299650471e-05 1.1450962335e-04 3.0429991994e-05 2.010 301448.1 580.0665 2.65 298204.8 515.4463 0.491 1.208 1.445 20 49 74.1752 56.2435 73.6002 55.3558 8.5110337438e+00 9.5334769484e+00 2.7423242592e+00 5.0203406879e-03 5.4446192228e-03 1.4907741748e-03 3.437 32668.39 580.3619 5.29 64335.7 1799.9 1.380 4.895 6.402 0 50 227.4326 57.9254 227.3583 57.9677 9.0008416930e-01 1.0143656234e+00 -5.3189302773e-02 1.0697704302e-02 1.3437765262e-02 -7.4485789904e-04 1.017 4253.892 580.0665 4.16 4020.984 481.0436 0.550 1.628 1.923 0 51 191.2009 47.3116 190.8888 47.3830 3.0209678137e+00 1.4309441931e+00 -2.9294030865e-01 7.2424954139e-03 3.4033807431e-03 -8.0600837980e-04 1.753 10755.48 579.3272 3.87 10882.35 641.3915 0.770 1.991 2.264 0 52 234.8221 50.8470 234.7247 50.8443 1.6659612006e+00 1.0743709875e+00 1.8609858413e-01 8.4618800261e-03 6.2223410079e-03 9.8597771034e-04 1.311 5852.675 580.2142 3.28 5875.994 443.9832 0.627 1.562 1.802 0 53 126.1240 38.8197 126.1587 38.6569 5.4712658088e-01 5.4213374189e-01 8.5731024322e-02 1.3412217559e-02 1.3479582919e-02 3.0963329606e-03 0.794 2509.426 580.0665 5.50 2514.805 458.2322 0.533 1.355 1.547 0 54 223.3892 36.8137 223.5089 36.9238 1.5861108700e+00 9.8442197937e-01 2.5359666066e-01 1.4149273726e-02 9.2991810579e-03 2.2220180956e-03 1.296 4748.268 579.3272 4.88 5010.603 627.887 0.664 1.834 2.115 0 55 149.1998 33.5166 149.2026 33.4995 1.9481386131e+00 1.7962936078e+00 2.8849770240e-02 3.5930564413e-05 3.7216509195e-05 1.4501803237e-06 1.398 281187.6 579.0312 2.71 273153.8 424.2406 0.466 1.234 1.425 0 56 100.0399 37.3241 100.2593 37.3501 5.4951163878e-01 4.4588565844e-01 -1.8847383992e-03 2.0621974653e-02 1.7679803099e-02 5.5066410308e-05 0.741 2605.135 579.7709 6.57 2597.229 527.7695 0.659 1.710 2.050 0 57 117.8179 29.7630 117.9331 29.8244 1.3617932597e+00 9.0294029598e-01 -1.7778972637e-01 2.5443232658e-02 1.6973480948e-02 -3.1706869485e-03 1.193 3156.844 580.0665 2.43 2867.688 292.7538 0.799 1.718 1.891 0 58 85.0164 27.2919 85.0074 27.2640 1.9957447545e+00 1.5333607547e+00 5.7839605402e-02 1.2254294395e-03 1.0209460746e-03 -7.0090464224e-07 1.415 22270.05 579.4752 1.76 18535.74 269.9057 0.488 1.299 1.474 0 59 151.0540 251.3526 150.9982 251.2326 9.0666213960e-01 8.7927920623e-01 5.9000850986e-02 5.2379761124e-03 4.2078632690e-03 3.1762976908e-04 0.976 4793.116 580.3619 2.98 4838.666 327.3087 0.451 1.187 1.353 16 60 228.4717 24.0091 228.2915 24.0102 2.4920137816e-01 5.4089113948e-01 -9.7059953604e-03 3.9695029745e-03 1.0552934094e-02 -4.0534935192e-06 0.736 2267.056 579.9187 5.66 2263.151 408.8085 0.302 0.826 0.927 0 61 9.6445 20.6511 9.5523 20.6481 3.0098865868e+00 1.4137211767e+00 -3.2064125301e-01 1.1256640678e-02 5.6512013744e-03 -1.1821178083e-03 1.753 9886.979 580.3619 5.63 11633.62 932.6863 0.862 2.711 3.272 16 62 90.0475 18.1971 90.0148 18.0331 5.0545950632e-01 6.5261515390e-01 1.3823695511e-02 2.2165746126e-03 3.5332784776e-03 -5.1504438684e-07 0.809 3311.871 580.0665 1.23 2885.72 92.57689 0.219 0.508 0.570 0 63 40.2200 251.1488 40.1873 251.2558 8.8297161564e-01 1.1502325823e+00 -3.6108091866e-01 1.2452153535e-02 1.5870275511e-02 -5.3062994095e-03 1.184 3688.502 579.9187 4.30 4119.301 494.2253 0.670 1.762 2.073 16 64 115.0092 248.9607 115.0083 248.8869 1.1583158277e+00 1.1896244112e+00 3.8801686038e-01 1.1675533368e-02 1.1687597406e-02 3.8886318952e-03 1.250 3975.841 580.0665 3.32 4212.904 398.1883 0.608 1.616 1.834 16 65 221.2122 247.6578 221.1886 247.7202 8.9993287005e-01 1.0942720990e+00 2.3378786982e-01 1.0889861551e-02 1.2555911505e-02 2.4890708172e-03 1.118 4177.043 579.7709 5.33 4270.58 603.5275 0.682 1.758 2.058 0 ================================================ FILE: data/image.fits ================================================ SIMPLE = T / file does conform to FITS standard BITPIX = 16 / number of bits per data pixel NAXIS = 2 / number of data axes NAXIS1 = 256 / length of data axis 1 NAXIS2 = 256 / length of data axis 2 EXTEND = T / FITS dataset may contain extensions COMMENT FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H CRPIX1 = -7.670000000000000E+02 / Reference pixel CRVAL1 = 1.000000000000E+00 / Coordinate at reference pixel CDELT1 = 1.000000000000E+00 / Coordinate increment per pixel CTYPE1 = ' ' / Units of coordinate CRPIX2 = -5.110000000000000E+02 / Reference pixel CRVAL2 = 1.000000000000E+00 / Coordinate at reference pixel CDELT2 = 1.000000000000E+00 / Coordinate increment per pixel CTYPE2 = ' ' / Units of coordinate BUNIT = ' ' / Units of data values BSCALE = 2.92273835509 / Scaling factor: r = f*i + z BZERO = 3713.66692596 / Zero offset: r = f*i + z DATAMAX = 9.852823437500E+04 / Maximum data value DATAMIN = 3.713666992188E+03 / Minimum data value ORIGIN = 'ESO-MIDAS' / Written by MIDAS DATE = '31/08/93' / Date of writting: DD/MM/YY FILENAME= 'NA36Rm50.bdf' / Original file name MIDASFTP= 'IMAGE ' / MIDAS File Type OBJECT = 'NA36Rc50 sum of 3 frames' / MIDAS desc.: IDENT(1) DATE-OBS= '26/10/92' / MIDAS desc.: O_TIME(1) MJD-OBS = 4.892162787000E+04 / MIDAS desc.: O_TIME(4) TM-START= 1.104800000000E+04 / MIDAS desc.: O_TIME(5) EXPTIME = 1.200000000000E+03 / MIDAS desc.: O_TIME(7) INSTRUME= 'EMMI ' / MIDAS desc.: INSTRUME(1) COMMENT IP_JIDNT 7 / IHAP: identifier system \COMMENT COMMENT IP_JSEQ 24887 / IHAP: sequence number \COMMENT COMMENT IP_AHGC 2857.489 / IHAP: high cut \COMMENT COMMENT IP_ALWC 2112.953 / IHAP: low cut \COMMENT COMMENT IP_ASCX 1. / IHAP: scaling in x \COMMENT COMMENT IP_ASCY 1. / IHAP: scaling in y \COMMENT COMMENT IP_FILE 'IHAP/FITS/EM9210260304099.FITS::USER ' / IHAP: Begin of keywor\COMMENT d COMMENT IP_FEND / IHAP: End of keyword file \COMMENT COMMENT EXPTIME 400.000 \COMMENT COMMENT IP_CBEND / IHAP: comment block end \COMMENT TELESCOP= 'ESONTTB ' / MIDAS desc.: TELESCOP(1) OBSERVER= 'LAPPARENT' / MIDAS desc.: OBSERVER(1) RA = 5.648170000000E+00 / MIDAS desc.: RA(1) DEC = -3.018297000000E+01 / MIDAS desc.: DEC(1) AIRMASS = 1.068349957466E+00 / MIDAS desc.: AIRMASS(1) ESO-LOG 00:00:00> DATE = '1992-10-26' / Mon Oct 26, 1992 ESO-LOG 03:04:08>-START EXPO EMMI RED / Start exp. on EMMI Red CC ESO-LOG 03:04:09> EXPO EMMI RED NO = 24887 / Exp. num. on EMMI Red CCD ESO-LOG 03:10:52>-STOP EXPO EMMI RED / Stop exp. on EMMI Red CCD HISTORY COMPUTE/IMAG imAR0051.bdf = #0001-bias50 \HISTORY COMPUTE/IMAG imAR0051.bdf = #0001 - 1.51001E-01 \HISTORY COMPUTE/IMAG NA36Rc501 = #0001 * 1.00000E+03 / fRc50 \HISTORY COMPUTE/IMAG NA36Rc50 = NA36Rc501 \HISTORY COMPUTE/IMAG NA36Rc50 = NA36Rc50 + NA36Rc503 \HISTORY COMPUTE/IMAG NA36Rc50 = NA36Rc50 + NA36Rc502 \HISTORY EXTRACT/IMAG intex = NA36Rc50[@0019,@0003:@1042,@1026] \HISTORY Renamed from intex.bdf to NA36Rc50.bdf \HISTORY SELE/TABL cursor MA36Rc50 2 0. 3 Y MA36Rc50 \HISTORY READ/TABL cursor interclean 0 6.85000E+03 3 Y \HISTORY interclean Renamed from interclean.bdf to MA36Rm\HISTORY 50.bdf READ/TABL cursor MA36Rm50 0 \HISTORY 6850 3 Y MA36Rm50 READ/TABL cursor MA\HISTORY 36Rm50 0 6850 3 Y MA36Rm50 READ/TABL \HISTORY cursor MA36Rm50 0 6850 3 Y MA36Rm50 RA = 5.648169994354E+00 / MIDAS desc.: O_POS(1) DEC = -3.018300056458E+01 / MIDAS desc.: O_POS(2) AIRMASS = 1.068349957466E+00 / MIDAS desc.: O_AIRM(1) HIERARCH ESO GEN ID = 'ARC-0001/1.2' HIERARCH ESO GEN PROJ ID = '000.00.000' HIERARCH ESO GEN EXPO NO = 24887 HIERARCH ESO GEN EXPO TYPE = 'SCI ' HIERARCH ESO GEN EXPO LST = 2.420000000000E+03 HIERARCH ESO TEL ID = 'ESONTTB ' HIERARCH ESO TEL LON = 7.073450000000E+01 HIERARCH ESO TEL LAT = -2.925840000000E+01 HIERARCH ESO TEL ALTITUDE = 2440 HIERARCH ESO TEL FOCU LEN = 3.848200000000E+01 HIERARCH ESO TEL FOCU SCALE = 1.489000000000E+00 HIERARCH ESO TEL TRAK RATEA = 4.200000000000E-03 HIERARCH ESO TEL TRAK RATED = 0.000000000000E+00 HIERARCH ESO ADA ID = 'ADAPTB ' HIERARCH ESO ADA MODE = 'STD ' HIERARCH ESO ADA ROT = 0.000000000000E+00 HIERARCH ESO ADA GUID-1 X = 1.294000000000E-02 HIERARCH ESO ADA GUID-1 Y = 1.717000000000E-01 HIERARCH ESO ADA GUID-2 X = 5.070000000000E-04 HIERARCH ESO ADA GUID-2 Y = 1.110000000000E-03 HIERARCH ESO INS ID = 'EMMI #1 ' HIERARCH ESO INS COMP ID = 'HP RTE-A V5' HIERARCH ESO INS MODE = 'RILD ' HIERARCH ESO INS OPTI-2 NO = 1 HIERARCH ESO INS OPTI-2 TYPE = 'MIRROR ' HIERARCH ESO INS OPTI-2 ID = 'RILD MIR' HIERARCH ESO INS OPTI-2 NAME = 'RILD ' HIERARCH ESO INS OPTI-3 NO = 1 HIERARCH ESO INS OPTI-3 TYPE = 'FREE ' HIERARCH ESO INS MIRR-3 NAME = 'UPPER RED' HIERARCH ESO INS MIRR-3 ST = 0 HIERARCH ESO INS OPTI-7 NO = 3 HIERARCH ESO INS OPTI-7 TYPE = 'FILTER ' HIERARCH ESO INS OPTI-7 ID = '#608 ' HIERARCH ESO INS OPTI-7 NAME = 'R ' HIERARCH ESO INS OPTI-9 NO = 9 HIERARCH ESO INS OPTI-9 TYPE = 'FREE ' HIERARCH ESO DET NAME = 'THX31156' HIERARCH ESO DET ID = 'ccd$18 ' HIERARCH ESO DET TYPE = 'CCD Four_Phase' HIERARCH ESO DET PIXSIZE = 1.900000000000E-05 HIERARCH ESO DET BITS = 16 HIERARCH ESO DET FRAM NAXIS1 = 1060 HIERARCH ESO DET FRAM CRVAL1 = 1 HIERARCH ESO DET FRAM CRPIX1 = 1 HIERARCH ESO DET FRAM CDELT1 = 1 HIERARCH ESO DET FRAM NAXIS2 = 1040 HIERARCH ESO DET FRAM CRVAL2 = 1 HIERARCH ESO DET FRAM CRPIX2 = 1 HIERARCH ESO DET FRAM CDELT2 = 1 HIERARCH ESO DET DKTIME = 4.000000000000E+02 HIERARCH ESO DET TEMP_VAR = 1.000000000000E-01 HIERARCH ESO DET TEMPMEAN = 1.376000000000E+02 HIERARCH ESO DET COMP ID = 'ccdr-V1.0' HIERARCH ESO DET PARM1 = 'CLOCK=tho1k' HIERARCH ESO DET PARM2 = 'HLO1 : 2.02 VLO1 : 1.01 VDD1 : 23.03' HIERARCH ESO DET PARM3 = 'HHI1 : 15.00 VHI1 : 12.01 VDR1 : 13.98' HIERARCH ESO DET PARM4 = 'HLO2 : 2.02 RLO1 : 1.01 VGS1 : 4.99' HIERARCH ESO DET PARM5 = 'HHI2 : 15.03 RHI1 : 10.07 ICCD1 : 0.00' HIERARCH ESO DET PARM6 = 'TL 1, 5 telem. data' HIERARCH ESO DET DATE = 1.989794555664E+03 HIERARCH ESO DET MODE = 'SLOW ' HIERARCH ESO DET GAIN = 1 HIERARCH ESO DET AD_VALUE = 2.100000000000E+00 HIERARCH ESO DET DIT = 4.000000000000E+02 HIERARCH ESO DET SHUT TMOPEN = 5.000000000000E-01 HIERARCH ESO DET SHUT TMCLOS = 5.000000000000E-01 HISTORY ESO-DESCRIPTORS START ................ HISTORY 'WIND_RAW' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.9000000E+01 3.0000000E+00 1.0420000E+03 1.0260000E+03 HISTORY HISTORY 'STAT_RAW' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 6.5800000E+02 3.2767000E+04 2.3813201E+03 5.6562799E+02 2.4699001E+10 HISTORY 3.8941301E+14 2.4969999E+09 2.3490701E+03 2.3460000E+03 2.0070000E+03 HISTORY 1.6000000E+01 6.5800000E+02 3.2767000E+04 HISTORY HISTORY 'WIND_OVER' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.0000000E+01 1.0290000E+03 1.0550000E+03 1.0390000E+03 HISTORY HISTORY 'STAT_OVER' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 2.1200000E+02 2.4400000E+02 2.2111700E+02 2.5815699E+00 1.0815500E+07 HISTORY 2.3924700E+09 2.5441800E+06 2.2058000E+02 2.2050000E+02 3.3000000E+01 HISTORY 1.0000000E+00 2.1200000E+02 2.4400000E+02 HISTORY HISTORY 'BIAS_FRAME' ,'C*1 ' , 1, 7,'7A1',' ',' ' HISTORY bias50 HISTORY HISTORY 'BIAS_OVER_DIFF' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 1.5100101E-01 HISTORY HISTORY 'FLAT_WIND' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 4.5000000E+02 3.8000000E+02 7.4000000E+02 6.2000000E+02 HISTORY HISTORY 'FLAT_BKG' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 2.1311699E+03 HISTORY HISTORY 'SKIM_FRAC' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 3.5154400E-04 HISTORY HISTORY 'AV_WIND_NAME' ,'C*1 ' , 1, 5,'5A1',' ',' ' HISTORY fRc50 HISTORY HISTORY 'FLAT_FRAME' ,'C*1 ' , 1, 5,'5A1',' ',' ' HISTORY fRc50 HISTORY HISTORY 'WIND_FIN' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.9000000E+01 3.0000000E+00 1.0420000E+03 1.0260000E+03 HISTORY HISTORY 'STAT_FIN' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 6.0423798E+02 3.2842602E+04 2.1606499E+03 5.5936798E+02 2.0734501E+10 HISTORY 3.5516501E+14 2.2656100E+09 2.1273799E+03 2.1162400E+03 2.0150000E+03 HISTORY 1.6000000E+01 6.0423798E+02 3.2842602E+04 HISTORY HISTORY 'WIND_SUM' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.0000000E+00 1.0000000E+00 1.0240000E+03 1.0240000E+03 HISTORY HISTORY 'STAT_SUM' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 3.7136699E+03 9.8528203E+04 6.9033799E+03 1.6677500E+03 6.1352398E+11 HISTORY 2.8897399E+16 7.2387098E+09 6.8047002E+03 6.7938701E+03 2.0480000E+03 HISTORY 4.6318802E+01 3.7136699E+03 9.8528203E+04 HISTORY HISTORY 'LHCUTS' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 5.5000000E+03 9.0000000E+03 3.7136670E+03 9.8528234E+04 HISTORY HISTORY 'DISPLAY_DATA' ,'I*4 ' , 1, 9,'7I10',' ',' ' HISTORY 2 2 513 513 0 -1 -1 HISTORY -1 -1 HISTORY HISTORY 'BOX_MIN' ,'R*4 ' , 1, 6,'5E14.7',' ',' ' HISTORY 3.2100000E+02 2.1500000E+02 6.9644336E+03 6.3300000E+02 4.2300000E+02 HISTORY 6.8900532E+03 HISTORY HISTORY 'IJBORDER' ,'I*4 ' , 1, 4,'7I10',' ',' ' HISTORY 1 1 1024 1024 HISTORY HISTORY 'LHCUT' ,'R*4 ' , 1, 2,'5E14.7',' ',' ' HISTORY 3.6236699E+03 8.0148297E+04 HISTORY HISTORY 'ZEROMAGN' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 2.4671000E+01 HISTORY HISTORY 'SEEING' ,'R*4 ' , 1, 2,'5E14.7',' ',' ' HISTORY 1.8308023E+00 9.6358800E-01 HISTORY HISTORY 'PAIRSPRT' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 3.1899800E+00 HISTORY HISTORY 'MULTDTCT' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 4.1900001E+00 HISTORY HISTORY 'PRFLCTRL' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY -5 HISTORY HISTORY 'OUPROFIL' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 5 HISTORY HISTORY 'STMETRIC' ,'R*4 ' , 1, 2,'5E14.7',' ',' ' HISTORY 9.3000001E-01 5.5799999E+00 HISTORY HISTORY 'BRGHTLMT' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 1.8387699E+01 HISTORY HISTORY 'NBSTARS' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 17 HISTORY HISTORY 'PSFTAB' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 1 HISTORY HISTORY 'THRESHOLD' ,'R*4 ' , 1, 5,'5E14.7',' ',' ' HISTORY 6.8047002E+03 1.1384800E+02 1.6730800E+00 2.0000000E+00 2.5446301E+01 HISTORY HISTORY 'N_SEARCH_ANA' ,'I*4 ' , 1, 2,'7I10',' ',' ' HISTORY 822 806 HISTORY HISTORY 'N_STAR_GAL_DEF' ,'I*4 ' , 1, 3,'7I10',' ',' ' HISTORY 46 744 16 HISTORY HISTORY 'HIST_BINS' ,'R*4 ' , 1, 5,'5E14.7',' ',' ' HISTORY 2.5600000E+02 2.8824686E+02 3.7136670E+03 7.7216609E+04 0.0000000E+00 HISTORY HISTORY 'HISTOGRAM' ,'I*4 ' , 1, 256,'7I10',' ',' ' HISTORY 1 0 0 0 0 0 0 HISTORY 0 0 0 10 64 23 12 HISTORY 3 3 4 4 3 1 2 HISTORY 0 0 1 1 0 1 0 HISTORY 0 0 0 3 0 1 0 HISTORY 0 1 0 1 0 1 0 HISTORY 0 0 1 1 0 1 0 HISTORY 1 0 0 0 0 0 0 HISTORY 0 0 1 1 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 1 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 1 0 1 0 0 1 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 1 0 0 0 0 0 0 HISTORY 0 0 0 0 0 1 0 HISTORY 0 0 0 0 0 1 0 HISTORY 0 0 0 0 1 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 0 0 0 0 1 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 1 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 1 0 0 0 0 HISTORY 0 0 1 0 HISTORY HISTORY 'STATISTIC' ,'R*4 ' , 1, 11,'5E14.7',' ',' ' HISTORY 3.7136670E+03 9.8528234E+04 6.9033760E+03 1.6677493E+03 6.1352378E+11 HISTORY 2.8897433E+16 7.2387144E+09 6.5048496E+03 3.8995779E+03 2.5600000E+02 HISTORY 3.7182184E+02 HISTORY HISTORY 'WINDOW_FROM' ,'I*4 ' , 1, 2,'7I10',' ',' ' HISTORY 1 1 HISTORY HISTORY 'WINDOW_TO' ,'I*4 ' , 1, 2,'7I10',' ',' ' HISTORY 1024 1024 HISTORY HISTORY 'NBMODIF' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 1 HISTORY HISTORY 'STARS' ,'R*4 ' , 1, 51,'5E14.7',' ',' ' HISTORY 2.6300000E+02 8.8700000E+02 4.6759199E+04 7.5000000E+01 5.6300000E+02 HISTORY 1.5854400E+04 1.3000000E+01 3.1300000E+02 4.9727699E+04 3.3900000E+02 HISTORY 4.3300000E+02 9.6787102E+04 7.0100000E+02 1.6300000E+02 1.2378200E+04 HISTORY 8.5500000E+02 2.5500000E+02 3.5242898E+04 7.6100000E+02 3.3300000E+02 HISTORY 1.4904300E+04 1.0110000E+03 3.5700000E+02 2.5686801E+04 9.0700000E+02 HISTORY 4.0100000E+02 1.6969100E+04 8.4900000E+02 5.2500000E+02 1.4543700E+04 HISTORY 9.1700000E+02 5.4500000E+02 4.4644398E+04 7.7700000E+02 5.7700000E+02 HISTORY 3.6737199E+04 1.0010000E+03 6.9500000E+02 9.8214500E+04 8.2500000E+02 HISTORY 8.0100000E+02 2.0127900E+04 6.3100000E+02 6.3500000E+02 1.6520199E+04 HISTORY 5.8500000E+02 6.7500000E+02 1.5727300E+04 6.5900000E+02 6.6500000E+02 HISTORY 2.1833900E+04 HISTORY HISTORY 'DPROFILE' ,'R*4 ' , 1, 25,'5E14.7',' ',' ' HISTORY 3.2567519E-01 6.4562768E-01 6.5725815E-01 5.2960014E-01 4.1916752E-01 HISTORY 3.0000001E-01 2.8000000E-01 2.5999999E-01 2.3999999E-01 2.0000000E-01 HISTORY 1.8000001E-01 1.6000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 HISTORY 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 HISTORY 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 HISTORY HISTORY ESO-DESCRIPTORS END ................ END h;X4+-AOD(W/BKS/T6<%)93$m '(@+6* 9E:aMgh4H -8@yv9 HC1PK~h0& )Q=HUc/5&:;7%6&<W?1M?2 =3K/5.8#49862 8/)/2,N4/&;(;S2@7$Z')BNF!'142\,I5R6M6uyM:<8@O2.,3-4.o# /B:=G*N*G$XA42S%AS1%3R&( \K@>'G&KK<Q5D:a3D[3(-<,5,LZF(O5:))2B&4%53$$ (4$9"T*58&H+:"QaO~`y_E1*785&NeNT$@L;77TH8(&" 3.4?;3;'+5/KF+.ED "&- )B*>,>]"'+ 95""<0 &2* 8>;OB4+'=Q/25a4B/=$*3#+*&J0*F>1? @fKR?25E5"*MMO$_2UK':&@M.3G65KWGJ3@6KX=).+]'#:*:P<Q.MG(. I36#N541:#/d-@-$@5#OK.5 %> #D) J0@ '5(&D0"<lHM:&$W2J`U@%I,O+/@1N%e756^%42$(,4 :<=%4VN,KEA)&E0= 040LFC4&4?R74+L$. ;9! 5%35A1J.Q-'6-5ARO*4e 9M28JXK5JB58"P,'O.F)8U=938#9%w5;d8R5=*9?,C -I9 9?52S(0,4D+07,c <./o#GL8"11:>H! ,;5/6(a> 4Z%&2!4)325 'ZR;P+?&?4!8-7%.'::SIBO= $<J?>8P!L6+- : ;*?).@?A1)IS/?"?IJ S.. E,",90-9,(4&6%0/J0+T5J,5CB%VC,2J3&(1  )J-=AS/2B4&H1FS;,e*(0:(m=`KMY",6X^RA5; 9-@.*@>#*[JH3(+Q,[(?$'<$U7E#OM+N(O8_f.T8",C1>4  /: c0/9##F$9;),Q"4S!z9F=5-/<$B,S.P^922#,6(I8=VOR44H-6M`<35"W'=)?>'*4Y.(9 )Q6)B#4?<4'$ 2(?!54&3P!"HE:7GB 8b>9R(LbK #+C%- 8/FH#E6EF@:76&JLc,%P5BB+$q6 %6MK-QE7?BO:X<XSI *'B3F(KX/,23H+B3R#$RF8[1S9##+3*,!G4JJ-(Z>-V4:L5?%#A:8SeWL$79?84%,^9Y B4&/H11470ON4C(APCL-9 !DS)/;$/+@8C54P<%-AT8 &'Y4-$,,<S7, $2@"E$2$[J/ .#%2?))"L&M240CXK*-22D)6X@7<9()M+&G3'F-&O&<KE/E9 ?)-V0K=3,X9<b./</"RD2@*-.=KN3(2'/I$8&O6/9c=>**: >-$DAA-% ;!(&'/<+3H(9/(8)*O@(`x<5&e* ,"Hu@3F^<::=4C;<l2,@KR+5-84yG3>]#=HB;$+2)6W-<6>2O3$?,4+(=@)G=8U47GLF/CD0YJ)(M5-(1 <<W054"3K";D "E*+GT+JVN4:)6<'"B!7I*PM=6;3%AD*c0W+9=9U8.S4:COW/>4&I']B#9:@K 5I<?=Q%B#7YqD0HC];I4"0sZ60);GB\8@0TH1?N/'(V%%RDD8<& ;4#'812BV#*C/9N8`2<E!/H8(9>):-.( OC(70[".(#1"04D'<U8P%Y!&9/D;,6"!TJ @^@8]2- -52<*;>J#=4-Q^/M;(?.F #2R/?hi3#)6>IE;[LF+6G0CR#:%%5#(*7"90)2K'=:%&TE 45-:VI 6D/:K=pZK=Q(N$>d%4:7)[/IH;,72$.94C\DHB4, C<>246<d#!+X/O0IE /,/B!\G@G OIGk6K;oNII7 H@&6?'&Ba05+)3:6DZ##=''$@-"0*05,"4 'P!?47"F9.H!GI<2#3,:]3 D(4 :QL%+lH$( H9)2<3A:!2+CJ:E29M#E8?3%E/%207VV:JA$-\5(?1/9T$5JA/?,H175SvK+4b= 5n@35%2&%)+L6F1$G+Y.,%925C/QIBL>=,T5'9-8FAD>)0*+K6,=5>NSY787?b1CC3<  #<PC;G<#HJ ?$,a ,1D,66'"E% ;;H10&*? :) / -36:3@.4A<6N79G)0*1U9*5=<(<C^' 3:7 ,EQ; .?=2SY285L;!5C%!-kHZ*<?3G0+9)'#09!$P.UEw8 7*R=&#Nj0K4]Q`3B/hOw)4\PE82/%<5(.:&?'./A:ADR8AN"LH>H"'91%2<&3--G8H))5!%;!OR,@5J> / `LF>E)A,%  7-"4*BH4K:^3 (.3(*a  I0/+K .O2P!*P(>-3PH?;7>'35y*#1A^:+Q$+0F;,:3'-q/8+U'K&<,(M.*PL7:%(+f1P":/>A.,Y 9O0K#3;49;1&90UK)H2 T0%)"M,8MXVVM>QUSOJD??/NR4F8(+,0=<5,30&Q_4Q/B?3!-<4%F B%$D:V:+A*/.; F8@_ 8*@3Cqk +FT #"''4#QH9B6#%F#3."6S$9#9)1;7@(+ ?;+3XPAO?5)2&*8P%,8@,:*HU)o')?P,E:V"k?&[- %;?&?>=3<51'[#7@F!# // kF!;,+D?<=@V9+4?5QH^7) ((H=*2&$& )3I,+@I:a6A)%KIO%'!1E;80&30Q(E8N"+L029CKNN<4+6)1M%(::\+"6:56G;J/%9A*UH5sZy +,7<.&J," ,ZDT=G=44Am.;D (<$$1&6F$?5X'P7M(+:$+   "aF :,;X= NIc.T:3V(F]=/#:^,J5^L>D&"C?2-(8A$"HMT=V>;KM(=LQ"/"#G$)%5# !C%R(NB@!7!(KF .-A:<VK+F74:JC8ARD# * +4C):"+#B '@*8C4F71!3GG8iP?/L8;F-4/ 10"$,)8((0* 7 D3B&N'PRwZVoamX0;Y" 3,E? ;[!,"8&)2(QA=![2C2@-4K*5;8P'02D&T7B>SVJ9/>P! *E>308%6#:[<:2,] 1;=45AB2<(I@2PEYA8'=1SC?#7S>*D41F!36IJfG5 ?2H'1.T!"'"A$(1ME0,@ET%T4!$=Mh9&"[>?U%eOZfJ<;$M'<OE=7-2E:*-G>(M2!/-AQFSU\=2/$=FPR%A $7-/6DI>#.+)BH'`]IqS8H/1A;!J@NF;#*[6;/'*8*=76 *6$7 )%9A#3X)+:8% =<#=A$"!CU67C0 (3QF@\,51).8].DM$%>"M4<-)Q!(4M% .!"O#YM-(@-;>>!I9"SDGH*'T$%=t'D4O%"OH58;6HB f@:"4FM;M/7S7 NFL?G@]A11P_R881676,0J,5_&4 B(-3;C[Y*GH:G33OH:01P'<A%BVF=A-,'3#J+(L@bZ"/<CBO"D6-1.32A0, /9J3?9\ %<F20+Vfa+-6>+;I:3%M J-6 6<%)4*L'FL13 FFL6=Q(DC'5\1""F"UE\,[!<7,*):58( 5-% C-@518[<6Y##C*7?&&D6N 5%F<#TO_NJ7"(4S+"/FI $6,E^C!.2P6mCQe(iU4%&%h#,41;18Y>!.H 7 *J/!S4#&C7=10;@$HJ514B+]K[0;>.b2`TW()-,/;MQ^2O#B<%1R7 ! 12J'80D5,)<*-\'F#;,(1'8+IK2E>&-. 8DJ4I159;&1IK"048+55G0A (>FJ>":(B;G',0/,/H2=9V7YFY$1R%#4%M>1$/8(19$KT2"Q+(jI.F-CTS6/$ IUDB61O-F[SPd)R(-2%OO=.-S=0.@ 55ASCK7'%@`. 4@N1=8@8 'aZ#1+C2:O?9^S@I;X4D)[H7&< R Y$/#J:9%1F?+17F@2+?0JN&9,*0[ME!/k#Q:/N2=%R%.*09*-0-5%+V'%I]8P*GGM-S@/C#.9\#=14I M4*$+F4@2":<)'< 3V4e(;"<<N8D59+9:3"V"^-/*rB'O?=NXPk]N&S=,>Q8V H;,JM33 .L/57@[6V\Q^B)%3A?,0/$=6I0RJ--+:/!0<FZ@56K>nT6!QI?2N&*D%?/>[.Q  c@8+?:>EH/0*.6';".,='L10=&XK'3372+K''"$Z65MEQ,C4 :52.E5E4?=>A891(3@<9DDP-E1%AP<&1*G]S<7CTKeW^PH0KM<,XN/OMs]mD\>\D >()!23WHM1G5G2"D2E-5B4>1%C6.B-;'$L#;JB.:>D];T9*'=15:#.A!k-,88'JY %6CU0@)L9)L*MN78` =-2*] 9!^2',6-DC)8:+55$*:I;X5^<I'382U-?AW9&8?>;A.$0<B0?0*$%(D6&@7?J#LN=&6P(*6<%'^.)[;=A 87@`;B.=(568:>R:]a[TC,%/4Xm;'=N mI=(=KJ-]@c,!?D)'?>GJNF - s)C<*,JLL7,'n3CI7F ,"?UNAHHb, >'/B-2(9 BU08!"$R?7CT?4BCD @N:<2'0.?B\ Y(H0<A$A> @7.RIVBIZh33E&?NY9VJSQ/>,R%(#!?UH@77.)'ED_9"(*1&L?14/#;C62:ITO*IO>,H/U/<'86*$ 25'ZM,<5CCAJ&PB*d`zsVW0&F7M50?;=:(8[! ,D2B8`!22%l*!('PQABmN%5-DG!0\%2=4,C1CLT:@<*:4WL,:$#6;H$e ^L+:3A3@!&/[)9@=.EX+B6W1'9 #%(A1(6J9<6!E.KN-,4U"4C& 3P#Corc&]?8$;K5;?96=PIO T0=4F; >{:G624$W/>?&$'KF5KLL<CQR@DD$V7-0$7,9:=6/<G?G 09CV-:<CA8KS6u7p5K O$Q7!-N&&#M?'](6DD9E46'52-S:46<<')d>3:6#?T ;##BK*B/%C!42;4.M0A$BC56@96.M-J9'G)9#B)1:$B8 8U H&,D;(2)A%7%"A+[Q0;0:'A+ %#&#^>06os>2[+fQ.<A"\A7.7(-$H%B#%+H.NI >017='A?#LM7OK#H(1"2"cr,h0 3]V<B;? 21.f5Y% JS&'MS"'Q3>:RWN(=7[3<9#0GDK]PHEI,$!65;3ZV )5=" C=/L/)60=3J9=4:)!)>+YA3 %J67!JG5>C,1-KjlY4.N;M%88/C:2J4@"4;.(C*P(39?"<qJ%;&Y<2"1"4XT$G%+,A4&,J>DjS5767R.>/3F+0ZZ0KEC $?($DF!W#7N(7 Q436*H-$26,5O8]+\<&74+36G-<(!.E!7J.2G9+41%QW<Q\0HMI>3b*;:R3X??=;b%DG!D".8,A5/B&<"E?tfB*:IK<6.6C$=E,>*Q"8/,+Y`S32 ,@_J.Z>':3H/(,&K".#,:%>7--7J6+#D?02),,J&:LL"'<E5JlED0Q92aFn?TA' B3-((";7G6XJ1E)"T>F \0R(0:"$16++5HV@"=5G>Q2"J/<zR1G1-,(D+!!72eCCD):'2j.2MDAG2?I+(R(*(123@G=F-S>2%04- ?1U6F&7=H3EG @K7CMoF[G /Z(N0N8<$*ZOH$X]43 &$X?9&?+2 g %956D6 BnG(AC 4$5_3A>4HG62@D;)H5++"&  73:UF_P|>?GJ;#2 %6Y."1-&*-;)B/?C!L04%N.$ *W 1?< =$M?`.)C$*@5(/gD?-2@3AB*4$M2@]X26=4 !O.&Z-TE5L:JM.;W)";$/19"@^:)(K'D2LWM8;/*&055P"(g8f+rm;?.54M;6!C= 6)_4%#%zpd?Q5.6LY.H:!17Z"@9F0?C/%*3A:G>C)E]Q>9<i#:[-B13:-,EB<:D[LK/ B(5BVT@L &@:;(- -];*-0 Dn 4IY2*AB)7?.B1#0>4(8g5bA\C8P!2"5$F1UEF5&,B,*J5R;*-C(CV2@0 &,5?303):2<'C;P1-R4;,232@L+<B1`2")D1NH:3!C*#^FO&2h77RO,1+8=:<0(B 8i!?E~Y#0; z"- $.$>*&:%5<E-L3UOrNC*=F'_#4J0,-4?+  C;3=U0EQBO02L+/a?OJeI:0 $< .,%2(4]&: AD$E%F82$!2H@9F)CH9L&#L95$DP1- ? 4H,X'/GR#H4OV.$F65+O..DC6Q26>(5?V75;-8B>J<5Q"*=$T"K3`HWO3HKE&0>3/J;=(?)7H.>J(?<B>.353"3#71DcS(;<M<r)F+!#7P2%=9G1-AF:*:8*,k|^cQ90FY*@@=56#6GCoV.>E_x$OCW:/EGUa{JN.7$4"  2.5{ B'CAI':>4(<*B5SH0B>;*&.#<]=%6 f25Z%9@& =C?#1-!(*8/.3B3Gt$<2)B4$9?FH;A9!2:6 6::,"?+GB4@")'G0DD49@C)G.M91A9<97V/&wH,* 5*A *BL*GM8/G\D/-6D=FKZjm9O363+=.+]H=1L?#HD@, ,H*G+\\fqB5 $N97Ka5-&,A"B"4*@XUL{HEB^X.@6V9".9M2T>L6M^0&'B$ FCEH6p?-1"F7&7S6':>-5*$'.8-5RK5/GZ<?64B60)>(==0T<:1:j-(F W.5J<!?3?6=L#7Qi; @S-FV5.S)'G,5Y3-)0+3!;ESF`."B##]Y(D9  (,>U(T!H+6D-.DL&_@&+ khM&%>;2O86P"Sj[EJ(-(1(ZG(K!X 95V*9=>FM;nw6*/>S?(E3'*9/")!9'*-9V.H@648(>EG-,O.);$>@,Q6,<4AM>@ =I-X>.@?5Z2'194!48$"ELC=6?-M*+9S-<58/.AM4@D3V6"A$7D3"3?%3#TLB6:\Q;G76_3C0#(+1(.$5!2F7U%:;(X-.@[.B+9(NP-1;4>+-);*36J5T%>6""ACid'9RB&C/V(gQ#C:?&4+!6.&`>2(T-\&4!GLUl RvM\"?6U;Q3+/(.2I;!MAW=&"<*# 7D:'W>V%<TBS%"50-D<2@,1)3:U%?&B(e1$,:19)!+6 KKD-F>PaAK*8)_8< 5;@15SC8&">jP=O8OK!3?"(P:L='`9#C498$5.%6 5:SX&1!5*81a;2 )%O#>\Y?APe["(T[Er<3#!F..#>+4n+!'J7U,"9%UaI=)(V/*4"2B@-S0:>MR)tU o6)k"FNG];?>24/0N3#:(B 2.8S7L>C'@DB'6GF174@E+O(!LIHD#" +5, 6&9V-"@C%"V2=DDG*]I(D'.Ya"2@P40"-Q LE1P;8S6D*/?99M+2'!VK@&D74/%:.$6XUM4EY03DH80@B-[H*0#/(P,.H26R1@'-.,?~.5H0C*]OR5())L 7*VB%0<)Af(;=-0B-I0pcFL&-+7@92k $6@*l?0U"12.&>&%R* ,t 3CF9<C.G# 9)(R*AZ[6A50.^1O/ <G532GD( HP?6P-2E<9U2KT,L%F3%C#;SuH?eQ]p|;s:6+d3'$"?CM4FX@=g5J R9B$DR@LGXF3/9@Q;4,M&*))jK*.e) %Y3VCC+N&?4 8D,CC>0+*IO('/7PD*":JP>*:/-%3M.B',-@<E*)'.7"2(35L H:+!.X A-TSpP#!1)F0?K)H'(5AB*S8 >I#NJ=!#=45293J- 68 ;%C8,/E2@'$<CP[5WQ&84%0],!6+#9DUGU71MN=?G$%YsCUK3 P;7^279cQHf,K&4%JKv,D:BH<*W.9(677M KY(K35-DR)C 20CI[)6E$+@342?J3L2e$^?I# s83#/HA=Y6]Y>/3%B2.S/2<9=&@,08,C1Rb1>> :VU*57+@;\S jeMWF?;q-I>'$CK? +EDDIM('F9@N.Y)b2#:JI,&:E;-'VbC#A%>C<7)--/@giRG/8%2;<9>9S%3=cAJ I9A7`.0<+R__aNUD& ,,:,U,,#84-$V*>#$5,U])F ':E/'-=$/OKK<JK0SW .:8B:&1*,%45SK.?62A0V|jUI[ 8$F7%=3%:YP@(L=cYI(L0+?LN%ZB"U, ZU4C=JS +AA+* B=S@5G985WPC7E #*(86J 54+Ac3H::i&=/9>G94>=.;CUqU5D;R?L5(8D.!&@UBM-F LJ0G:1@9 N9[\/'";D2;<!F>Q74D\IQ35 &&$*056,]ic@)C<%M"%'=70c?6 <L24O*?AV(W,E."+8&N45KjdRV6S+)*!H2)-)%9.O.hzS7I/\#;-;E1PR6=/iSVmzgSA@YWL)"d)5,O;%<*/-5)J&: (BF)6+3+G;5>m90B8][5/AB A UC 5(UTHdi[uXEB*TI&#E +<K/(c\9=$J]#T@A2)MH55R)2'0M0I%C*D.?C=8PPEJ$"R G 8$+,Q1K5-?R0HA0<)LCI8E8"FR.A,-9G$' 1\6&6<b**8 C7=%ZMAE6!F$F5 >D+?7Q&E8"HGphDH0416SZ5IPQ-*+AW49TM9_V'55*:(: 5B5b<#M4)c298l>A,<;E*2=.@'EM@OMX0188%0K67/M;fU4V,q>8+522X9/'B3_b'$;?%<+4!E!TT9<;3"87-+9I;53HO] 26#a*(?EQN@4H:%+?'7GQIG%q:;SP.;Q)NG5:4:hDOF2$.8  >SKMTM@*8J%8=4H,)((,3'-l.(%:A$;*61G&34V68F ^ !-1L?:?JAD(@*=B&r%(aD/=35e0Q(&%8#>*2I2HC3>mrGxB; :'P7->/9,H64F-*=:)"/I0E+=;A:(!<>H'8S-56H!/!>-**H6?=Q_KD:M-IJT/$7?[!!8':8&JC 9ID$M))96<&Q!'636394;'#`N27+T&/61;D4.-#N/04<,=$@4'.c(#24B%L*A"3+935(>" #6T($/"Y.-3"K0&6-3GHG[H>IFS_,3(T0 H3!0).V -?6-(,R "?2ph9NHOK=V12/%@'#9E3(Q84TV(>Q;;/&K=YA"T;`*5.XOB+!4,b.VO=8+[9qbQ:S52*P*3(fHY(48; 3'2@=M9bb=%(%B/'b.C+60:)*9"@.K0>BWH<D311)'0CV5RBA3ICG)M33*>8ZV4T."'3-=&E>+%*@("+s.H GH%9 H ;D'#MKJQ[@1Y0%7` u)49' LXWF 68.(0IV>>R4K8J2@*6#1`1%).>/CILF) 65OGC:?<5:12|4<*<.(@L@H7"L<+'T%2,+3CM,;3NK8B)3_9d:C"(7OD7##/95a==)0,6F O.3!9!N,: '<(JdC$($C@-2,AN%$,:*>#?(< WF52F*1Y.>K`59B;Q, ;BB,:?*?)D#=/-8J2J++P51C?E$+":GI<;50.2J3,+EC/,H:$E2!Q ,O0'-;]<%^*/&:RRB=A3;"8'F,#9!T;&;Z79N,.!Y.@)3O>`!4>4@Y>=,:+5-(+=BBF K7,3T-/4A;2]5-D>()$>EE!:V:FDS# _a<J>#F/Q,I4(!.%;!'/P'Ja328>'BJ8b?/:57IT4/GR$+:<(!++@+SJJ2/)*T=)=D"7;,I2"5'D,2F4+4F3B/]I:#d7+j7=016%-=>305.*1EA-6 FKAO?/ #C5/F6#6E3: ;.H55+7x# /3;5"2@'@bSD(968:7%NV+'D<2 K?50I?>0ZA2.1N7SB=.C*+="+(#U4V#L1" 7?CD/52# 1/8(#I5*,7-D-/ 0*5%9H5X8DR>)5LW44kUU!`3.)8r<_aJ(2F-! )B47:A4 6>%: F$>:ER;$ ULzB6#J2N44\-+MA0& \&TD@"5I3?;7<=87!?/$Q:!>=8#)0/EWA8OchNiP,9,JdB49/!&60?+6=;3DN0H4!1EJB?ZT-4/;>G?#>W=MeJ #+''-b0!73 ECE61;3:9:I@&$816L8Q3@M@*B/:*1-/=(<7Q3:XWh<.TU:>iH*<8e2N$+'%<F$94;219.'E5N5II! E.,:E< ,0>$MA>!1@R5B@3^KNV7E&@1:=8IA/C(N#&@:6C2c@0Y;6J :+55:.%7Sc.,H->.D3:9A-5?H/!%V;8!Q -,H:&0(:0-<O=;I/6<&E9#/HB+,.%E-R'3*?7<6&%+O?+4=5H/H3++^<,J4FB7&&*6,c80&KJE6K@]I/<=f~j9>B()ADD.B#J3N/&%]6 <3C"U$"770C@O&&A'8,@BG6#G,A$F+);6F%:YP!47C<'B0#%O.S5@/RU=CF:8>4A$N-!#+<,*%(+He'4D@?>(, *)+<5 H!Y;8!%=.cd%5& 78A;A782 B3F/I;1+/MF?+D"D%3G',F<G+2&*1<%4,KANN>DDHLJ(\;'5+E)#D2U+*iQH:);G9@-0ca01?^E-9!6VedF"E$e>EQ</74/)+P8S"58^>B<S84-GCOD.=:)P[ + e1>5O7>-KO@.&.+.R)(AY;V0-<78G<3F+ N O)PAJ1VK(f3 gH=G+=OLL 9> 21G:S+N\Qr&8Eg.cF)JRA?*E8-WA&6'9+;B&AEk>F"BQ\ g^O@0@64;1#-><]%5@)p5"GA1O<'%.AQW""2=>BcN//+G;M(D<;/==1jV\G)[~l<g@2(1>4\VY>9(C=+V!<(- SGWA46'*%  c9#7+?< e:7(L>36SXA;#!;7g2'R>D %Y :3@LGP(:( 2B: -8K0JLgsf"16'(I5Y=(C$C)9%ABR*D=L;2Z XD6-@ZNkT?,h!a>35a8>6#":UJ 25I!O \)"$  1%$%1 HT%QK;1,24?N$F579B$5G:)7;&J#0KOY3<X;Bn@HLAHK0c;A6FM4,**<IGqRKEN)=8DC'10(E%E&W^v.4N+"]#:2C ==308/6*RJ89A>MQ3 E%U@? N@!=,,.1)FG,*%B)L Q-QB.K4DAJ$-J @69"26?b+*GL:Q1'<&AF)Y}zm1G84>9H,7"3O(N K8.-<!?7G&='F32@=<$*  :=G%-$ 17D2/D1+0,AS88J*S;/PSA k4I?aWcohNJ_[I3;ZVB(% F<C\ R&5,@K$7BF]+E"(6/ #!)C TD3$4%J9 &M-@E%BCA@<?1%&914\qV2)'(<'E787F4<<9  A6@!,gFW66B*Em?<#@$]K(C/*?? D #TA80AIO:@G?)7KbBLT63?&?* 36>qIRN@(#94;5.6#4<<'G?26(+BO%4:2L4>2 J"7M51/<;;;M /.)4> 72J)wB.21Fqltoh`HP?J# K)O'%'B?NZ*7$M'X$B,O>/.&=E>9<!'J@4T@a ()AD?,**X-;$K-65FD%'4M"26=2D&&72LIJ973?"J41!G*$+:%(ERB3?WE')W&7+B6F!/(=2K^~476<J,=$)?'19_SP8 ^H5<(X;$1>>/:R/W. %91!TE"Z6f1A. !"1WLSp:'XJ[7/B),9E VCQOjmZ;+E'$7A=P9'/D=<m6K>RmH+GD2@-;@l,XAC7,@2#++U1G0&9+(0$[0#;S-+*?C_)0 =?$1.CI$(273FJR>"708CIG6=3&#IF%2=3@[3GL,1"(=7K20'G>B0N6`?ZR"%8E:5b\@H;02H9BRK,jjlh4^+-V@C2<0(C5A43A)1M@ QO>P50@-K.-%F>M''*(3:$/0H)@23  L97'0He0YLYja$I:zMf&.1F3(:'"O0*&<(O"70$G3).*;%+95N=>/2 !)j\F6@-5:*?A3.8*=I1/ *8 7>-QE$%03>%,6U% ,+H&+82C1,::77G*P9VRL4<T+:'%!O% D#E<X#%B*O7:#08N6*R;)3:,'OA+91.2<1>\A9@*!T<50N*"+I6+#5"R711;O<3?E2=MFL,2)`9;-:#=:4QS:&s2ua?<4-8.:,3<e2/+-5 7;m(&+KBP1=4!DAGY.;-$I.$2 /#h*R8<0(E\jf=6>;g8O,.C)JIB//1W0>0#Z$-SH. >f6&j2:BK-F3 ;L!B4R!3*D'9'J0'7='oTL'#+787,3U0B,]a>29R<C=QS`A)dZGE%3B#?;#S#2+A4O=D5&9H`:.K+/E)#W>44F1#?&=D+D&5D#MXV )aVG7W@C!C 9+IU;?WL;j< U1#/+/AQ0D?>875'<F(52 ?I%J/Y*#(?-36B;FA)::DL??+72U;,1j>.21ND/T,G.-%3P'`L.?2A6D2&##280B;'(>24IFt`hAM-()D:FL*[2NGQ@C+!4XV>7$+_ovebRB3/I1N8(1B>")/=F..*X+9""OT=AA-:5IJC1":_M=O0PZw2[dBJFfA;/'$2=>( 99"0N?'IA//J@8'5f'L;,6M3=+7)1%Q1@.-6:(G%W70JV`A45+& C%"3+%@1 :M%"5 1",2DM#(;-LG$3EM:20#&\P74$b(0Z@&PEQ;@YW'4(QJ_|OH>(4=52*='*%'LL''(,4T4#cWl0RZ@O"*9>02'K2$=CS7M ?,B88/<(K<GG*jK6$J.4FD!"OEK;!pc[T?R4/996b2X.53(! 9(4HG&YL]# 0< 2: C-FP T>3bCG05WIDlJ7*734H$:)0!4M]2[.L9"H#2;!K>&@c#Bt46'(* C<)M4VD-387!G EJ>JA4G-4('ESI.;G_>=+#O*pekVh/'4#9?<=#/(Q*;g.GM,YF6Mk:edrCTJ;106MS0C,A*7G(>+c16"!&H,:HD8+&7F;8($242L8M89g=FSV`yrnmIt}haLC=0V6+6+76[*?95G;+N) 5AK'%5'3@-3FB>1"#<00$FXO041B6G ./&)9&9)D!,A :/2 9A4K1;%.DDM#*La'0J'4&$CO&?7<(6<G6H;c-@IJK K i>KX^GC>70=>&4>6%'$N$BX.)>/(^:coz>DX18"26I!<7,&*0LA(c:. (V.UmR@6GC(CPFI2;5/TRSbo2UbQ[M]cjS?Mw9T_u03$A$ (G155-B> 4;63I((R,D43 VO7*!9*K=S+I+][7- 0219W;#E">"O5 9p33O'#:&5;)?I2>!5;-U8:"FF;H/ /9/0;XK,A,-.272O6h?D-,1;71UHEkO7X.PP"?5?I47;(,73,/5#;3IF2kXhPK8:!#=<;Z&,@99.+A))=@A<61emOD9A6#(</$*F=,A+:'4AzygVbNoU4|1<.7;EF1I2+/-#S-\9D="4,SK=85N03=!86D%"#c!2K%>>0C//8N&F(%J": !&G#.?-=6"9#CE5.&&J6=K8V=;4?36ANA7FtG;(@1."8D.2/;`VG)41>#5I6T" 7IB<C;16Ga1xCW@%;G)9O\DhhYRI ->:B.)>+%<F'):<:,;PGI037=-L7Z&^> E)F>+%57&+IG/b|^prR6TT?ZZJK=70?G.:P' 8=.:CNI,4e #BJKBL.9<.%T",3"*5(/7--IP*7OL:8^90+($4$&37@H<)3O13Y)JH:?6hH+):@_9BD$Y1"=<K+F;"0#'G0K9C925Z_I ='H@,I@3U?G$. )0V#=aDH'>?f]1\]E1>+Z+4<0:B7*E343T7 AN,QB0;&?=UaX7]7j7@ZFK;*Y{bY]W(.MgW\RKPH"?4-%LL"#$D!7A=0(=',^R5P/7T-$'I$.5P5 F'8!<5%<\%L<$'$ALQ,]>167+:3B$B-!C/FI>#=^45,A-/\vb8 '&8C2+6IB:O%7M,@.97$0% CEVONHC?9LAD* )$<1>455H3=  6KKDz 5 R_S92!:+*MF7E6Z'ECDD36FI& ='M* 1'QAg)/?`IS>T.X:wx:j=Ae3VR6^A9qV$#BD-D1;A5("#B[ "6;".I8<?4'5.)7O%(2P%39A8B7R,JW4,J"N,:Z2',(H2/$3*-8*=VEFb j053)<;2FT42$4ROM6;<B+: -"480/.!1;#H"*8P&-);"R/ +%*@8#1(GP"0=&(:KVN7e&E>*<O/RL3AE>U]d1N,#:o^7I5sG0X*@+.<2.P/64*30rX=)&6P&94DO)1,.%15;C<l32<S9G7LIJ<-+06SQ!5/5I!;,Q$)+m$9-:'3(+J>7E87Vi=1$N/0<0/2  10GD8@4).-1*~C(?a;'H5VE;M74=<%8?$4A44>9)35CD5 B+! *I8.E@/Mf@?,-+]>=,B:I'24:0#[UET+?Q&3)H5@M??2+$<%16;8 Lp'=@=Z{RA&@5@9%)5LL!(+,bUH%B24$Q&#B/7$-6a>K#m43)HwM3H;9V>;?H*B3!894<Q!7'L/#6b9HE1R %K1EB5$5!U4 4C)0E8&#;GC-%-4L74&0*!O/F(=<AI30+@.=C1+17*G%f;\J*)AD(9/,1NU(';C.9608R0MEIoAP (:C+B%EHFC(G>"$?"GY ..,c<<;&2G5'!F8A5F?" LcN 7  WJJ@I^E3&2=+9ZWB+TN,/EI : 700`#=G=12R0)-L $:.0$,?lTDJ]f='UO(=G5>@DIK,Jc?DA1/<"i+@))'(FOS@H(26J:87>O79!;>HH;#531%0F'!K7%B2)# ,50B:?:1@zW-/> W:M5-!".GQ2%- KK:'*`7 5d0"2E$2K!3M+ ,n;m46BK2.3/6=?). Z6QMK.= 'M6Ht^1BK}?,'DPJD,9!2C%().<0=R"492b?X8.>oDJ@(:7)1 &0(IVR@*-V'_QHL:&@QC?(HNSNN3$OIG2YP/E-]2 @/$-3.U=(B59_4I.B-8)/CH9YJ H1H8>?:9\<<#,<6!2)$E&B32AP"?,4E-X!R7'8-(?-u!2U19*88,"-=1#/ 10*(;/C1%/H9%D;/a8!7,.!M?9YV3%NE:18A.:278;|FEYhb>Q9BF.\K+I):I+9'67a6>65&'2"8YZI?>4SN+I>S&MDrD/8<RB3I40%Rs%(R08$OLX>@K5?-4G"<(?S1LA]0//'1I .j#. 1 N'$!S6!X?*$0E$ >?Y1 "EI58'--A06C166'4=1-YI^@_bT$&o:<.+;(11m&9 <"7*1@_ AV=!c**KAA=#1$+@94T%73,J?14DP2$2Dr[h&Qd)H)')42 D23*6! &4!,1LU  1&&7GC.8&Q+f8";LC -89M\5/Q%I;];)8/1A3]4%.<)$5AC3-CP;53)?^1)>A^7  (> #(F.?7%2;;/%-#C.n3[>/I;%18B!7NnD''(5531 (/';7;6'78N7*. *[AP>+=</G3 C>N?_21?8D7M%C=84974;L1I:.%0EQ+4>5C/A'0F-88INV 2rJRGT\:DDTMSE2J07LG:+;& .L(0M=1X3$K"-2BD0)3[E=@CT7i5LT<C+,D<<EWM:=5K@.?5$383#:-f/eP,B](@A%29b-CHvx!D,4 ?CB)D5&J+1H46S1 KS&17228D[ GG<0DWW0<-# "24.KPI>-")35(<4567959,J?03(JL +<$&2#0 16J+A;-G.^780'Dd G!L173)M&4'6EJ1H,CA#8<L#N-KN.UVUA2:P)@@2'!8!#e*F+ 4/5)I.*,+?a:1 AD4B:PF`$F=MDfY LV4)D#B(S>9CA(F2769)%K/.=X=C7>%"*&4(@;E>!$=!+<S&m23?*+?MA3%2=X%=-,$ :%-17:.D?52= 8/5+-D+B&!G*%A?OJ/-Y ]1,R0&k:F/&D%,!+5" /LJ4'O)D23P:PDN18 *67I?)94-A7KG(< GA'6I80E$M/0L101L,@G2<)=?2.*09,2@>+:M>FI$'G2`2=EBX*C$ _0*:].AAB-P,3/I:4B/()?H&//K 1CP4L>LY@'%U`ZC21K2/3? E0G3+j-2,AC<J P:E7?I?D#) 0%F:/S'8: 5F).)! $-,*40..+#'6/KT'S4*4 :ECDALX( N$=70ACL=0<1,).G@!.8'B2ISO@f M^MMN(96V'H* XMCO 2+5, 'N\;*#++%69;N,*0N*PB+,'FX39,'c73)A=**fH=NK5*&$Q.C=64-%}$75;M9:0:IJ"F2,FCR202 6/TJ/:3)%6J &@@.,2"H03,(B6;FY 5/:87A'9!q2=3 '&8=G8.#00.+<.7??#0*@+M0C:["R CU,3V.8@;i=-6GAT2'6F.3'@."!*3%Z'77"3JE#L.$/LGG$P H$q5LLJ@'.UB+OdB*V8(Q,_=,6;*,#BcPJ\;858C*9/E5}@6C*%\)>5 UM,57+C'0$-S//V_A!8AU%SN;KF433,A'XB2(_*2T.78*d22I J( O%,G A(4!?G417S&-9$!&U*"E T!0%jHP-<A #4 1(8SC">$.H)C1;G5ZC!E\2!(V3!7>((0C>09'c-VC2/.I3]>*1EO Y8DL"=78 ,:"#sB&T0@S)/>:"IQ/4$A8)?'>;2 9>Q7T.8'Q L40 F^*E:,>b-EAG%g*&3B,3 -G<+V+? L#G(@IU"6,(2,%G/>C*@I JE6E!"5<5#$0&0U^&":iHLB?=0:N<UJ^#) 9%H08 )=9.MM=?-"8/#8"52c4WP(n$#-O73@ ,'2)9, (8@;+8E+,3F3'+U+.9 &+8f(v!0 3113!*2I/*U>#+?6;:>=98%/87=\_V31)WI!~,66L2:(BA &C* N P6!.5$K>:_VB$>"A)7Jf6E4&M(>@@>-A,6'6%*934!J7CC?/.#)B/+/$;!'e"]2D*;<"@1'0jUtE$8\!4Mn:M5QO * 8PG**AR H13D;MP#/XA=Ba!"/:*7b7JL/ K';P!(<2S2"11'32FG?&TR9*F9/,<D)'*-!&F4-0 ?4T"*<.G7)A(4=#a*'P:@8#AN..8P.3,8/A$(*.!2"e*Q.==!19>IWG96 E.EL 922='E?;)B#-2%T?A)?$W$GI%Q!M.185 6/@MS>1@=N@;0LB8L<G@IWXkF'E' M-:&0;ec*) /:DH96'-I'>?9)@P4/2I;%*G"LB,_&HS#'*>#<@,8,C,RK8=<%.5+Yd44'74(5Q>BF./%G0&F,4:D&KoG@?@1@^*>/D,".W"P9@'(4(187(@dN";> %$"98>N\70/:,C(5V<F1/.E>(9K 8J4;2+*EK&.R.:(R5K-a@PE,"5'JC.(@6N0.77=7F&@FAARb^:CCG(RC55C,6!!!1/B*0F4395F0AI&$-!6 D93 AM4*+@(A=!W55M.'%03VBO">6>:(L%K15QG/&' K( LC68,`JF( 1<3!^3505)G<NB6ML+@;^W (6b*K>\L26(8&5>3i B)181FK=(5&AA0=??, K7I!4, # C* LE*/)2H'bG18HS%Cn</N<I7N>29=GO=><T00-q.p?*%40+'W*E=;")A&O7QGX&i=%0 $359%>+18A$ 'HT@8?7`A6#(N9%LT8M+W ">*N?C%H(T>*9(+3W& 8*!9A&0*:,O6,E)C";:71"IO#9;?9I@*;6o11O82@B-W&B&+I4=@V2;A,H:I<))>: +?(`9^]A<:D^F;+2"=YO'"?"2$G;M*!L9$;I3'F@#2:1+H)G6= I?'K4W25?'36 1f V?DG/8%/=NK<%/B %NGN7( :8:BE@D $RD:=G+)1394U /PHA/>=U0H:+$"%'18LVQ%<>=>0-9//E>X77B-  OZ$+82*q?GG( 4&@:LEN7?5])6` /+/2Q"%+8?T%l?+)%>@/:H,X41hr$3/T:9900EL6 *44!B-7+\+R1)EewMC(I:U"@QB-?<A4<&,_819!876;#7#1P3M9L1<k7%0_L,#2a 9N;@BI%+1"9,FFK36: 085IP8mG60;!;#C6`<:]1EB!5&P 0F7(2:AO<?6dG#-*!$A#6/#!V J1>DWDB.8'9*\;D)$1ET?'O3,J11/BW85%%. &0,@OF74:@@93J549&.O+#A1,D O7*),I-3N2 5%87&5'`!/*DcCS@B &Iq$#E:h-!B&3#$9BE1?N1(>@.;Q*$&0B+hV6'5(a.7=N363#9."-<P-=zSEN&* <wF*EM.,'=;KM= $+#3=NC>&::-P71;(-?3=8O):LQ3F[) )A8/'<6NO#f:R-%H W*;(B(N.-9#9GW6F$KR6'6&J8"B5\&CIRb/:1,I@6)5:G5&0h5O%-B&9$L!"PA)/F /T3Oe,-2>& @7H 4/+F0=B9= 9%/2+)0(C+DEU6ROB2 L-GAGH22B4?B46GbceU8"1]Sb]Ae0%"1A6c Q,D=R)7"/<Q+ =\!4+.->0A44V)= P@5V9.X/,e,+F8P+H1:'PA10JI08{TU:';M-'D 2CQ+/$?1:2X>J)3<%@1@>F?2I't(<!:;AE"";)% ;I2M92/FO".:<2./?Ba/5+;)/6<@/)/C:,J#(.+.2)0k0)9E:Y .Ee3/4 VN!R;9@D78b26L'(@9-_'3(0L|Q4IM,S.<-IHE$)#,D3V$%,4.?&-k8C@E.6N9Q69"2&E"#J*0D$1@6&3*)E#h";_*!B4JG%*7+U;$58)? E&1E!MU.7;%@O',*8bUIV%+>5#&;2&8(4"3.KEV&+ULLJ0:W 2GH.<)6F;USZ;?@F,WHQ0-M#%Td4R+>@GD:=3Q+?JV^DO,QRK4M=!0O;HI>77G9E;Q>D+/0>7:@A/P|6YLVOoyC5>8D D35 R)!2J1/T.$3%/ (-2 TOB?:CMN?4: b''JM%3"%I0,!W++*FO1K(',0C'j19;V =W9 4O,S1 9O!/Aa=:#1+9(Z,*7&7J.1Q#4'1#c %5937)+8 1& =1$7+.D8J6A<>C9W-Aa7%>%1<B22;EnB6#S55K@{H5L!#=3(<gBGy>((=!1YVT'?,T )_??6;ACGIw<^[QJ 8FT7J="aA(B 58#4I59!:&$H,?*MOMQI0`1'2L$8 <SH 93: B0+71:?2[A6@ F 8$-G,!014I*P&6;@>>2K2L7X=$G%<!B@&<#K3@::HD*BVS>@/#-O63#F>+J< K0Q#?#D-J!=D6@YXf?L?A^-132O'JG8+>$Z<D9"6H<G<=U/%;RI1<:;$+9BTD(c='0HEU,M:=$;Z'^,E'oWF/*=-DZ;_2)80"0L.$42;1V(!2.(7>%L2F=.<:=9=*N(-=>.I.E,,EPG?,?C::I58:;G)798*]:IV.8,IX*2RGC<A()80X(1*9:Q]8*9&A4: '0KS<@)<++>B.>(825D/#A'&$.`&'6ds`jt}KjB50 66Ja#JB-[ MAK 1#.!;HM>N> *@I20,F>)?5% E;$ !7"%4+,0#> .960?>#6F=ctcI79-1$8&$>*W)WC@+K5TB@1QDK'0,(8*N.>.)-8*%8"+:.(:4%Cc_);O;@CH?2T.E+?+7'=* 9^)#2QE>(5'8dC<IJ,I2HO7($@&d()74A%(B9(,.&G?*Z@V), L,:FWPZ|s3< ,+F"1D )1)(167F.!0EB^68S#6FU5=<,#=&D^8Y/GE(2L^VM*%3P;m+VFU' <P!;H9?D?I0RJ-<#2$TG!KGACOK0#7D>,25R+&;/+j6=>!$&@"-S) +351*A5H8$BN(@75!<E5%jH6?HH4:aDL0$;8,4El>C<?<2=4zIHWBKAA&<=2D.><$IHB==;5 $%5,)260Q/N-HU'^6uN=Q94<=%)#J%,'("/(N=/7T./SO6!6$APFB^[J3?J]'DF*G@Va>*#48<@'6HX :75F46AN#==G.3B%FK1,<0/!DL(Z5B''(8GCAR*=<3-O]A";(1=$5P-(9 ,*!?-1.<,VE";)H!+8>#$M=!BC0 7+H8= %,756/6)#,&@6J2 (2E4\P:/1G6/i-=E8cL'?P=!?S^$55A$% %AS;L6<GaGWb=S*S>&EN$).5%=.%0<H1/A"NGZ%D0&=(6J(-'+9N`EB?6:a/M&)%4$BJ;-.@%/@M@W+!^!=nHE%3C +'">(&U5;D/\ ,;5D%2K9G*g[JC"!:2432FU3%3*-C @ A80A;,91,1'0];&?RD77D35F;3Q#&CL;)$1I<9(\+C>VK3/1L/: FZLE3&4CkO1I0M%Y":%$:>CG@Kkaa'0@#Bp",)#56I3'"F=%K5(-.! ,H8D %Q7@5<2a2/PIY@AA/'B(9$4'; #M&0+<>,'4=:+FD'%`L@#77D$E#*>#&F?'3P&KV(6A 2")8'?:&(77-5Y-=25!K;T7BM4P652("827\=&04^$44LS1.0":;<,%9- 2/-! aE5726T*9= %7,[BB<: I;S*#H,;J3/!V S&GCAyt<@%-KE<+0AER,/B]50!)JS8-&= *< </+H+4,TD<$A7+:;+:D;3,BZ(,V93/6!+)FN+7*1:@Bk%[!D>F 5(H U:M;&6\71K5'E&W!1B,L&5f Ec9)^L4:@(OBDHH#":3'+ 5;'N,D"6-.P@- ;& 97((27;5K[2)]%5$F);UX&.@(6BU2B< S0-#AB653F02PK #*;K(+FXXhw:>)*jD<-+4(MN6( JPb':=4G" :r<I4, %)3.>6='&<4&U/?+M\8ES7@/J5Wz0L?_6HJ -A(I5=K!F2SMH(NEH-377>AO-T'#7>R&7 **71R*"B,% `EP A),$9?C 44: :7]X31)5A&4+O72-3J9;'G8/$F) 5%&)-,:.H/8?/*%H.A% R3''A!6C/- f H4@70/:%N5')N8G%?5MJ`XgUZKVa4A(=44;,W3*+:BL # h4. , H0%V):\05;6I+XB DB AhfE.P=2#WE9 U5<,EG%74#)-%0&!$1N55I=@*42b-G*: (5?EQ%=0$1'83\)3:$IS "B5-"(.,3:*L(#-4/?FJ,#0K<S )562%6/AB)@>@ #*5(,:?0>4+)>W5,4<P8.+A"6I*+2-'B CBWF/QQ1:M3J$,;)%!@_:l5.Akd'M)/3#+*2D=2q$7-@Jag "2/!*$%I2$!@25C%J'I,HA?N-D7Tbawx9I776800iI 8J#N]Ge26'B)Y: >>J- +W05'?)&%4< &R+??209:b,<bRE&.OB&$-2'6s+:*!.,.E";?\'5333D- M07E;I6C)B %)@/.*5,<fJ ,I6./&.+a$B,:(-@&73#5-D &),,'5A,'R&:ALJ[+-R"6]17(A-/^1D]R168 3&8H3",@AD667D(!J/@f%H($NL-:`@Zx1*I/05.Q$>94"!DB#M/;6b-6W*l"J<&&7M@07:OM'%=&B;OGMP,B)B3?L#1:D=hL?@@>EYO6./8;J,@Y$Y6/:*.S-9C-6A2-.;.'<.?@2)&37B: ((@.8<H&UCBC*D9)#?+B:.#6'2V4)+=0%P4H[:U<IJ$=:,5JF;41@y&@M*c&8M23=#+*N54!D#-<[L @^/BRl `VQ0#.C@31+57;(P4<8-7"W.7QJIf2O=-C.)'T"'6UT@TP820">7 >Z"=#!-*'DG*H*1*&0'D%#50;>1WWOB!M)  :J>0:A*R9;3 (!7==G0(:"DF&IM;Q(;=T7;71!;797&<:1?1,>"4C4/,3C01845'8!;3F;.1=$79U 5N!V54^7.'+A)'.9<&/P@,I8J( C !/h/8:/F@`"OI0O>UO&_'^.&*;3VE-?2D%H*,7Q3(@D'*1P 2(8 10C6C[::+'($",)3h4-/.^P25?5G616"N,[#".H5A.7/ /"7-1/?6/EFK"+ E3HM7L!H0.03J  :9#;N+ X,f0"81>ZTcmC()1#CD8!^-,'5. 8SO*%H,9B>TR?2H/0&FF,:=10;FK!@C.A?&@Z,%YO4; .1=8>'294&$\U+(6K@,ARQagjG)=+V;+&K(Ub)?k ">7@ONA7F0?d8*?B6 ?MGAE-,/*%*M92-  N!;LM?,23V79D0&%F&$N1. ,*41%A35>: &-.6)GA1M?EJ>6Q*;RD3JC 94'11$<!4#KGLJI)??>1E$$-EI-g,IW->AD?) wF,$!C5&K#22_G-!(-JGr!V:LL=9 J5TMWK]>@@7$%0"(*!M4a+O8?C6,R5 ZF#!"(R/kL?8[3O)B(?92$ VCR?e8C *)1;48D*0> XN)0&3?2;4#$1"=4/)7/G*M32F03 HC&B%-/Dg$X4Y% '93+<27@$=6pN@;2-6/ @#< 3+/?'.8 "M000+?+h:"4B@<aCHIA$R:NK'C0$9>  7j$ZN!B,-?ZB#QND&F0{f@@F?;IEc6 -!'XDL@"6.(82;ME!?R'D/7:31Q'$-bYL,F5(0:4K42*6@M--QPG16( ,D63@<M;F',4K?)8"?:.h/5?K7S#'L##!6 '/6;)F3#3.<*:H1F-S7G/1. #Lp@(>1(7F17 <B0D\';* %-KVAJ ;4IL e8QK'P`+$66K.&8-2;W+/7<= 6M> 2^@O3+(%&8/B"? SK4/l5<3LQ-1C+#%J7.CW = 0.2[E W'^R3,JJ63.P9*CO!=X^!)K47_,fWE4U=WH<3+IAMRE1,O#=001M6>C.=7HL."D6=7M&R9'9668&W788"4C B1+((:)1+8*2BS81?>&AL,8A:-<6.O#-A& $.+B4AT] P1O(8C;3N))@2A 6D-%2.7&Y%,,DS+84"(LR#P`?5'B1:U^ Q#1?41cC@SWdwvCPdWV #1/0HI.72J f8)$,(R-%Y4MU+-/L[G$!Z#:"?F<?OaO3=;>64#&43K4A/B":MA4?!9"=Z'H(J#+BH5'/1B;IF*:&R!7=(7>4/>.67$;J$,405;E $ L*8B"0U8Y?"b#)"64CF0=@ 6CF%X157C3;&<IJBC$%9DB0%)0=$N0!:BB"*B@'!3P'S9,_`;1C0@J,Q8.MO=%`h5(LTA`< ?EN4/C7#A29?!"X5G&5M72B.<>?%/@*&L1AI17 TJW1<HNL+)<O.QD0<=.%QQ$J"FLC<Y1A/4)/ 2=  .=5E7") "Hh)(VOC7A1C<KJT31$6''/?5+4<.I7/=0XC4)(/6:%+64_1"!2Ae*@ ,BV<?4.1K>f)LDFI? 9!E=?IkD:PF(/<&;EZ%=1,*1 1:AB(5DmX[5)'~C3WR/55=5j6IITE6={eX3!8%'LS)>8X]:#JpK3<DT5GP53M&(L4 K3/C($"_R0<>F2*=F5 N FHA49m7*2&A%')9<T$.('/OF@:Z8I453G0.! (+#69A)1<259%I* ,K05<K54U&:@D5J"9;8.&2<0,7$N<'9R74TM-$K(8"B<y'$8!Qe40;N72*U/?&JG^f%QRQ,948C>O.-Q)=0B-#J*@E)JB#VEJV%AGnKgJCX"..3H*L8ZK<<)S(1B6&&8*%G*FJO4-"(T8;DX3B=;]&G2QO0?$>-91? <=60F*a&#6F8-,$O2/'!0+3<*92BC(#)L.o0%/3,3;LF/5+B;&57>E1;ZJ($/<;5@*: (<)7RBP?/#.:?XD4,%91D,N8NFJ"6BI;6a-##= ?CA$R>11$"&*.I0Q^N[ F<//%cWCF;7:7 *7E4/+(6., K*T[JJ1#=X*76*G0V"2<@>+?->)%I&#=,/5&4gWBXFOCb+c(8!,5ADA5<%I*V%2.8;+-T '*1P$(@:!:*6/.(,1/J$!:8*B#3@ 81.aWF+(A/,;F*.=)2#<%;1- A&?:M /MHeCQ4<%464 $N$!*7QD;@$+2[68<6 A(J2Z,9^4-+,K"0;#?"(M3))'*2.7+&3O 1KCMEDD E)D"= %qy>AY$5L'A]=[5#6@G5i =78a0)K'C'89;I@UFM#L>'<04- 1( -%<E2C!(X5-:'#LB/B63U:@_AJB8:8 Q$19@'@9UC6B/:46@L&8'M\C+S(#4aR&0G9 O*42L98789C:)FF8@21:,A6)I5/%+ #:72+a(.90J))IKC&O3 "IL2L/C*&05e4Y.CB!>FG34O#&, R=-:`%5O7<903uAM-5$HB(57V52E='5TJ8,M*M3"*G>3J3!62A8 -1#`0",4(5 $(%#+-2H3%2^$MCB@ 7,0*)!/O)"?;+B6N81!0./%,>7B-O8-1LJ?=%C D),8@)PD7>%9.'#(D.+"6?C'?0G&721N;@Q&1SE:U?445H 6ChLC>& aGT4-2$AD#",.E90(<#4(3\-/8#7)$R0 A%70,-@jqh)58+6A@BG'$h .7#B> .M@!)PC-D/:<-)HX #:\9#XL <%C0%+ GN3Q3 R8+?D%m@&/$,&S4(4A(2#681(=7(/O7%I>)>-D>U'((F,9XaMcFL63).PH2&4 #.>G*76/1F -)3G0*+2A<J,Q=.7Db0A.(>)%D! 9[4yG&6J,B:*'5))T5H%>9):H2S?` 75-fL/8/-BUO; BM+4>9LQQ873$( @9<U_J7"#&)>3eB)2@I> R$5H7"@SR533)(6$--NS'?0*=NV!E8= 2<JH@3S+ 50G86[P-9?'*/YB#E.#J#9 ?)K996 dQEJA+\;M$16U2W1".0 <@E5/)4+`K86=PC*NU/L1+.4M6*;(#'3$55*/MR;FSD5N#C.87A1HXq'!5/l_<HIb2+ 6Kq6C14UGW* *G)EN(P4Ba!Y\09>Y0.BG*;%*F5a7@:2N7-4E-)P062C,A0%F%L3 5P"1;,=<('&+.9*.!<2,.UD4O+5:,)15C,2Hb5EO@D5;.- E(%6HV'<2G<-<9Y): "L6PS`%35>U./*C)98O,T>#S>*4B*6"I.;2S'V&="A5-2$[2A)4I:"-L7C 6[%/*313#NO J-d=a>a#:L7_@(C94?189f!I,4C,MS:<:;%%7OD:7I<><G:7*+23;Z<:K#BTENC37\**)B:2DD3J&&;1=PX65RB9.=.9!&I,A*"DG6 6!,<'B1Y#VE(@)76-<8K8B72$4,59"%.,.&+&339S"6(1 1C?6<+VAD*B@3 K,(0B7AR4h*+!I.C>H7Epx6A ?+31)1 ]<&>X5LW E(*.[A2G+);D 5OQI_J+<;=I?S:M!710 7+G $IlT>(N.Me?&. B 7'/*$0"<,N9*B7+I$&C78'3-7;-C"@/"',]E!8I)pJU$Kc1)/Gz5G.S/!)+2f6;a5-0@/-+=+`M?=E$-DB.MJSFS/0/<#F%!<fN!G*VD35_C" %5:D&GECN;BeHD+11! <EA1@B53"<(JO >*/_$5U 1Q95EA A(Rlm89=+0:<,,84X4C6]>)1G;DfBE(1MIM;-`3:<102H19F%,'S96*;V?$<$ 08#E`A*",4=8;305+C1'!:7E6"^$:JV(s1!*3  MD.%7VV2@KPQ><'/%">I.**3A3B B0;8?Y.PGkr^;?U5#Bo#>',UC'#F85=*48>.LO(61BOC;b?+:)-;,H.j6H"8;+:HDH2 1+"*-)7!%+E8MF=L*oOHW0(5A.!ED02>* 382h2l4R3-@Z;SRLPJ"G:?16.1M'P+69^"M)&MI'/ I.10/(JB30"8702#EO9IY(?!6+3"/,063/<O3+2K_Y!;EP/+?@0*L4+H=3F2<E9!/264L$;;78%R,<:JF/5Y~=$()J>, M6,N:01+ ",8CIXM8K+F9?UAB/4GW-!'PK'@#$ 4H2+342m<35>RN*'ZSE87@+%p)<D?Y'._A#jICYF<0E;-5=N'2]bC?X?) 7]TMb2.=1F.B<&4^&20,B<:AL1B +6,=J&?",)G)&>35'2W11$U-/9(^<DC%;##G08,?#68/:M&/2"1iZ>K;6F&&9']9bsxmP(7>J/ ?<BEE3 6$%C<( =8V4*EPIKDO< LM&l:11&DC(!%:=/0m1('-Ei!Bg%F%3b0#6 $='A(D (=OJ?/'9%A@WV}IB@B#8IZ>/B3)A(+H?6/k 2N+55@D'.,!4M(?=*); +,+5>3`4*&253AF@/22KX&&1F<.",IS0A+7VMF@&-!HF;<:I2E1fN;8G/*4:21&:9?O.6YIMjjl8B,3YF(%%[5'@A "O,!.4g%[057! (?6KIBKB-.6<?>M*&>#4?*M7$"2LpJM>,@6RP0HI792:2::Y>2 %B5QPKFCI8A_.L[}8JLFl!3:a"=AS#3=IKCe6 n=%0Q52'&=<94.* 2?I).6:2W7>?,&22Q)39B"M==A@BE 52L@%+Y/K"69WM-SG-1,A3I 6I2-<7> DK)1 4?gF,?)sB^fEG"O*#1& I5(KB-/19+=K%7(6^/>*#3-eX#<.A)2(R-96c%E0R; 0-1EH"C#(b '"++4.I8"(647>$1>61 DU3G=.28RVHAZ\]~;_MPP@:-HH6U<)./8;<0(-8!2 L+#.6&4> 5,6#5:ER6Oaa[QK."2'!2,?4b#.F%L_@ .7'&B/(,276,S!8;8@DPV Q0e>;Y 3 j;aK={HV:D&L8+>, T9;7@/U0S/C CF:E;(%&S'!K,!)2J14L J9'`O! >5)/93*G @4)A*Q) ,$9;K"  =&HM74AV+Ht\ZR`ZXZ=T;(-9,D$EG768 Hr/BI 9.&4;7BK0*[ "<[1( 8^)9T$:gE(37 =3D+4@@J7-5$/AJ>4))"/"/.:4!W(47A48CW,@ .\97BB;4JYKDI%Ubwip0(D"6N"+<=/(<-E3?+$>G>+*?(:C CGO+.&$ 0:<* UAEK1751K"6>2%b5LN"3Q$,0,3+NA73#7?2J0-,B%#T-,G.SkQVszTM/kTH7R0-t* @7G;9F 4<SE.C13-F$N<9CI 5##I-<3C!BL0JB7D;#KR+G/;UP^/1'J/B'!;B4H<&9<1A\G3!.$["8S@DEr.->$P/]`mIN$AK88(99]CA/G#8@8/6%KO!,6(B$)06;="P(7="#6/&@V2 ?1;>D:[P+?7+"<*QF+*FVGL(I6(@6A?'.1,L<V\qbB_Tz}.E6Ei(?6=ZW*7<GS8^Q6$([h0:'=T1E>I&/- 5"@D/8!>"<BN <.,G 8eT)BTI3 C$=6 +.eH>+ /,2;3 #)CDEKM-S!,4 'W4j?TB.Y$6]))I.|g}701$H/8H%T? >4+'#F5pHS5(HY8L<*.4*B277#8995PA6$K"%*@G2<88F?6.,?$D:31(3.S19*$($52 ..?\`_f[|Ba3~gAB=Dd4+<9&(%2"C:5&3<G0.:$Cm>,`4=4S1@4>4G2O71R6ANLT5b'E ##F=-51S4=0&-%,(C!U+P=(!)(F T4K7)&,;7cg][n&I7#G"5>pT=m,;'Fo4/2C(H:,3BY> %"&C.%?_8(,'D)BO<5< % IG,#B$"V;!1C)U&C7$6 @ 2-$5@>1=(:0D+A,/@kpK`I]I\N99E89x=&^Y'#AG'.$6''\Y$WK)\N:>3,6/D #!80."496$%;((U&8^U:K.2;6]./;@*I*2%289.+e7W$6K0255SQ5*@P(&OL<3VI=-V*\<J/9*@*H-@DLPEE$2'!#0("# C.KB1.828-,(./CI)559G:d*5(L2"0$Q<=[0.G8C0CI-$#K&8'.J!7CF1/+6 I0=^rQ(SZd;NGDhE}v /h{IY.doiN72F$ !;&O.'5/ E."2_S5/#7E<-0,PK"0!0>K2/J0C=$91D!\!MP-;-;<?)T[. >%=9@0$*='./CM+5#44!()=S-/H,*"$:6!H"M 2@5308['8A>O( %+7,%5.IZ,VH/-2HEP!"4W!Wqn#=E*-)!9fW)3+ $&0111\F07.T@W@*@223G`6+FEzSK@_e4\zV:51>+7`+ /d%4P9G'PG&-*.D3 0,/4J>B(#j6> )(C@HAC@8:0 6'"9)<<11P(-AG&9<E''!#+@)._JSP'5 Q S:C1)=[%*8IP$Bmgf<$V>I,K3I*/CF;;U)1"5!:3:@1H.$G-9(+>,?U6UJ,<5<Aow&8/I0&*$%HU 3$6'+"--&B%9-1@)71^;(M '20*01S{i)IP_lb]IN0O.@T350MA2J*L3;;VL,::,23!T-);D79;&^ #G %Z0UA:$?ND?$5(&A/>7 B0`&.0$I3;!(B(-D:1CSO&,),.4=7.9#7>O**<R -/ 6.+3-K57:0M%;B7+*<6-:H8",3\2M$YG/=%;X+!Fg0-)1a<6IO0 -#K6B8h(I:$+.+B)D3c+6KT)-%;V@L?)0P$8].U%GGeWVjhY'#Ec\eP1, D@,1R-*R%*Q<8< I9hQ,296U(7<%O2J>"^H1 " )("?,B+9?6.M0G?>D()455 , ;k21- -65;<*& 1+=JC 4;0$3C\E"@-E80%=&%4W,H1<M1:533 E2E05C- =/(2.R-VB'R*4&I*+)<-D/RFD"@%>9-OZ3+7E#+'H>*.<<<$A"<oB&9,)P3.>B]40N!X9HfU"YZe\0/6A?I*H.3#<B.A[9E29MT5?/&&2< &@$/V!U5tGS= :mNJ6H6K6D:7- :*".0$@ TW+*3B;.R;6.06X.-Q9 1d!O-EJO)/Q7);$')5(LC.(HFU#!;1I5%,1 F*11U.I$=)-X:[%11/*.3"-^_[4//2; ,c=wT/HR>T 1E /1nZK3_KE>Q.K*AN1J30@r7x]mCyf}SX<1;2B%:T>+6 4Y&B(#E EX$'6*A3D@*^<(PDS%/",AM0D'B-+#3E4<@2/$B5Z$5 @+*b*68T @,.T5!?M4*,A592I9--5%:3!AG(OeD-=)/42@>-/ ?) =?2"EBA#8 OA9,>5%6P0=>03Y('/86"?E7L2;fTN1O*=\5O8)79CWH:H:  $I-8&G3D3&W;E=@<>-"/8?0.:7RY-^yY]S=H2.ASTC]/23&"L> gCbD5W_?,A.&(.,$> ?2;+<g"7B"L8B"-"".+J#8.!3I3h5"%%>5EE)96A ?,,N)?B+$9 0A*()?)731V$4W&T<E@*SI;+L,g:+#)<4=M <65 F.<<P<D2-J4>:$ G%;8:,1!:#BR/+'5I+zBLF1A\$*$ =J9,&9>6TCZ) 4D<&OCK@7mputzRQ=68)>%PZA%#8D,G;rZ7D(%;KF.:IODC: *XR84#X4E1&HA)$C;*-=+!:$#g=. %03N:0G6.H+Z.B3?(91b3#2G&K1L,/=$?;6 +&(9P@[c9?4-<%O/>$G="M+:#/&8?)4.:>?M8[%(;-:FD !(39KW"JP@Q5N)(-A(=6?N \+1XD0-&@,$=6D35*?1Y\.=?74[YBX]c]@v\R(cTn)KQ==)"K#*"(<QfLMGMF&6P%"'8;//+(2366*1;9G&I$,Y*%D+OJ5(F52">;9lKO2+.S)3,!0/0)1B-) ,GCA[KGU<JXF*+?f &Bf/)6:5+B6,>=V9=MK-1* 17'h!5&Z M("Z)9$.J@'9N3^"?<NDF+B=9.$% ;'$2/CF?87V(CJA9]*LJ,.#7S_6JF8=E2)a.`^`QF]qk/LI<<c2J!Z08J.;.9=>DG8+`W3-E1(:?)7,35$#/!)#A!B'.38307dD\O+;U0W=3(/A@8?eFh?')+.$    H8#: -!03G"K+&B0?nORME<%2B2`X DAgDA/6j&BL CVH4 1B 387,@6Q-, *997(4'J.=1B8(F%TE29$Ad5.,-'7=V;+$I]iO%HF5C!-)A,BVR5TnI9G!2.FOXRiF8pXC0SZI.:G6^N=&>(/,e/'71<Q=1e:5JM75!*@*&?3NQA_=I9,X>D,#?>9D\ G5OC(6NY+33'(4,C?4SQ7:L-LA:-/-M C*0B9%[r:H*9123$,SB_7S)'!(&G=2)=:#)(X %FK;:ET.?]?>/,;-X1$ 7U-J='F"DH).E<A*2!9i @9-*-%;MbdH''&51,TG'I*1&<:P?44$w8%3T]O@MdT,CG .$7I9?$534'PHS4.-K8AAS6.+;0 .L W!2;Y9B!=0;4=''F')H;'9(6 9V:6)GNCE+) .6$N 8%6C%,5%D #'<0C/3= U%%=7 ShGtFWIkk@GQ+U/R0='F2BN>.3?  -AC<6;;>< 6C1M%&X. JG/$^("H8"K?99-c!L3M 9-SB,#C9$#6L "?f:*6E,L. "j O(lH8:?"F;'O0&R1M@?ROMG,UZ.,SJ(%5d&LbD"(48H>JG%%6G3%%;.S7)'?!<Z'-P302%.&@D,/#P,746C;)R0MdVG8D7($K) < 9-+dSG:=15HE V9>MU`RV{i0A:9F?&;D)'I% ,=N"VE)T<.=?np+99/ :320!NM&&hA02\,09)9M.7"5%850#."F/ :3WU;B"*<!$A?B]& TZ.BL+7/2a2K3/SGS=)0EK5WS">'R/SEATR'qKH!.%#i..-&P>&6$EWDAC=# >;-4+ R25/W?:C8 E.1E:*(5,^+6?F818 &J)-9S*.4\!;*A>=Q'**1U040,F3QWT8 :!3BKAJ0F%JP3/=,/'@J C'3+ <4u`>),B  </+RA99!C '(E1!:NB%;C -'7.@??+7Ca8@4SA$/FD6H%& B:@F4PT175=3 WK-H<8V)W$bUB S3=V,N+,3;626 0AAK%@86A260<<P07 6Vt?*I5)+"B5&-0?-<+__-=4:L<C\SH D. .37FN(/)/,Q*:)8*+ED1E<?,/_W$@_=A02 (];@'6A ?:27K 6];73:6/d6mt71%3M^06f>FG#7?,<52+J?FD</3$'AG22.)RW3<*(D^%CA2b71'L>R*<7")]SkI#2;>T3+] 7!MAKCHm++*C*&/V K+(CA(C&P?H? 7"2,)E>DT;1!;&92'1(R%?+@7,FMR5$*K5iUD.H7(  1/gK!)KD 76=A6=AQ<L &1L5F YfB8LDE&(:KM@Fi!(-#B(0BC.(A/-$0S+\ZVSME!+,'?57$N!94O'*.;.(;LTU %..-2: '[2 E]81?L1:"2"#S$A\Z4^M=9I4,:&D-L._?CMu6=UN ?0)7% /7.6RBM=V @AA@@=HT*H<(6M9HOSD19N2DF1G-0H@!e+#(<5VAEY,D/6;L8// :9:3"+PO.BCI/N')6 L)/DQg("6N7.84Y:93LJK<00.":2l.H7)ff,W&K:R(<,6) > 6&;(M-/&20%aN)"&/Q#8D9 "E#7#,J)5?(2.(G.&&B;Z#7'9'QS*7(Q= '(=B>(0F:@8cD'JA8E3(C(,(O5N(<x8#F#<A*+$\6:85\ ,@YlNm("),@Q"Q !/GZ LAC&:66.@>J6K,78&/c.R@?V.!0$:$Q?%B:B>!BF0!X1Lw5%J`FJD2;*,=+$  X(T#2$%?+ ,*;Az2cY>hX"#UH68f8AT=A-< ;>D; :44(P- &T ("#+K,37U->')DBG&'3/G5,.c9> "'PJ;YT;-/1F8LABDQ"!@'+  HQ.1%$55735H9".J <PHEQ;D+P^B&)+5=D@,,:C2D: ;79K&l_>3(9PC=I,M ";Z+)<.Wk !Ae1'A2-a,'-<;$SC&H=sHa!40:R(*"B/6"K(2b%BK(*0'$?Aa6G07D:y1Q<*U)R'4E[;2K +.GF'2@7YE.S,1G`3*F0D9+4+ .J 3@H5N/BQR0F+2F>(%/,'G"Ea( ,E &e-":%-4L>@-0A3;0@?.>*6SK"9)V5&"/F40;E%nsDs6**<89'6VNQK.!5+<D0-BJ%G K ,I3+%m@MR:3 -5#<&7+B/\H2(B/J2K0B}qD4c9"V5-?QX/;yH9)!2$E/"+`7~m){=+.D3)?=-#B<$P%&/!RT=V4FGR5TJ]-+(4(CJ(83 4>09LA07R'\.?L42<+Y,, %BAPK%D>O:+++T$L["?18.#696U+S-! 1"0_:9!Q"801'%NIq\|<SD4 #"P6?r(!E*&4B:WMH[5$F94MD,T59M%'O33W;PM>AU<-F91Ds9xVQ,>:J35GF19>>?.Hf55E) @28?#fSs$6I<Y-- 0+)+T)+)*:24. -!-*67*3]?@.@'6?91N!G#K+< 24C76 A@QV6/6M= I>=R+OJ-V.+>I=($ >8#VD>L*\D/c@7_<(!4DZ.%;L"HO7)?>6A-&L=SRI;Y: ?)C .-1"ng0313/$$S@4(*7THi4X<`;CE< . W]2}I21N!$0=CbNt;OTX7(2B+8)[ E7M,-O8QaG 7BDHse:F8+"-&8<H3B13P:$H95@E:/+77*";F&4/#,E!9&@-1CE(4G YRB9RJjROu;/4E,CK50!1G&PN0 /'8<H'*C?( KIGI<>B+*,**(*I%$Okc\rO#*>Ef3.EE61F; %*P.M.0L350.3ED1N 8$VE5I^0?$&<a1;hb6XL9&$\A%`HA2$#6)('3?M:&B>RHES5ZZ4%.!59i2EV;B+2$E1[ndz|.h2$"<+,H ,=3;55M0>*I2*.7O8)4&,6K60KE$0,7OSV3'$*.^rSVLJ*B;0 )#\96? P!5F;&J9;+3=J;Q2H8)K44M/+3&:mxV< 92?#DS)":G9EH,9K/%b$!5%F Rf):%?.6+64=JKBeHF'K6I;b@,hXc]=P_P,4/G06,34*RcFB*p03%aG9B17I:6FU/3K-a?oBs..H>4VE@X7C-%2<:6OPG0+BQ<<@ -%; ( 7P--+=&$>3 2#`CV(!54J4 ?@7>&!FUPB[?C6JU<LM/: >'0U331G=7.3,2&,.I@&&]@qTAa*-IJ/R;RR_,9N%8(0("#&0^91-AE-5 = 2(63@+4.!76DhOZ5%S'CgW7.4I0 2*//#! 'AID! _1;2?9%]>U:P(/4CVA6BPEN j?6T.6S0S*BEF%;%q/D#B*[%52S0)Q6@H-51&R; 7K/0 * %>*@458=3<D-E=N_4_)Q>: #92MuM2Kc.HP7BGB5U3=H#Z0O'+W+")J95\6(JE9 ,2?%'U&+$O'91$MWY&-$2"42B1E-9R'=>O4;'T!.3022#`N/;K) N^611H/"(G-N0!&Y B06>9+/_/qZT8%4B-I>N G:$hC(/F#L2,G9- 3(5_R%N9I*8.O+%~;E.:2G% D*/<H9'1=:5'*6M1N+&G<%*!1CN0%4HL!#?NUD4]J1=L,5L?#=O,,K1<&FM&)S66JQD13EB' 53Z`C'@ 29;'A%8TYZ? ).JC744%<+F0U#>DD!<,M/P,@:'D1L#;0@5NE!a$" 6)#  T7J&F88O37+": .I)6D':$3/; ,d2/*QUC*+"Y&.=>AnN"/ NH;_857?JL5NJM=+B7/>1OF!<49? +"G@LVa'E;B'K>17J.>6Y'&$/ ]4!/MJ:.DR36B&,=/,PZZ, <&6KI0KG*6!bPY:IK#^7+<< 2J@9)gjFC(0%65L:*)/.=9/) R)&0B&Fk'S:<IZ*3N1RS(  $AN8EFYP5'A3KW,?1:F.507H:>57<'O@;)N 'J0;=2 $]I\,6])@-49,,))Q/G_4?H$E5IC"$!PO(((!2?.0)H2AEC`@-4F(;;317b F*DM3W>EHSG( O:TLI'#L/'F2S> /+6L6S4N%G.)028(?3/<4$>9'+ %*8Hs_LC1E-Z$,D#.=0(C@;59;+9:.F!'5B V<=18>Q>O-CL0KK"'&H1$5>$7=F%%+5%)b45(F7 ?&R3VE(<34B:0A%Oo[|ZG2J13"*=L<8@(H%XR+/.M, "(@.h2@/J<(2C8 BG4'7E U5FR>31&&<,S"L*!`=.FB539>CJ.;Q-KG%7I^.3J69>8#,3)14FI8*@):L$;*)IE%0'%&,*%L@7V77AQ,>TE%E75,! <*7'#L/(L+%-+NW<21I8+#=923P2102MFE1I"@,KO+/G.-+=DAN&;RK'd6 + !&;'R7#A,&1JGG>"XE8H>6YA!<LB"L56\TD,*226  )C8;-4}B3%L$%C/&$-6*$TUFB8/HD8+2A24OK5%C@ 3X*ZAO&1#I9IET5NH.P,@:F HB%(1?+(/8$4242UZ(K>V:X<$I:-*]!J9-, - A?J=,S#2A!;6EF&649>95M;E7!=7-T+AG*),Q!512*HMF.8]>;5P1N4<'R=)E)83==:037+CA(Ra*?[=%&)9'g<U[';G''GR5/BT>M137M0J>'"WX"a17)J0,4;L40#"=^-WA*@n/64=h\B>S1"-)!4c?JYZPx??5M74J#;<>9'>S0?*-K2$94+(&0W=Y?Px=,!=N8\<15"B+J5 3:A/:+BT'$( QQ VMA2D"J;I&8+-S*$7#*6N):9f31J1,72*;; 2.-<$, 3=C02G/PB6*?)*'5M>2I**`hW-vGJG_R7DAL8+M:?/'6:!:'E7*!<Y'QU%R/*6?(/HGZ.DC,Z=<4?:B<;@.G:H/EIDM,=&C$]1%94pTKHR07FLFVK '39%G+C+02N3B;9oN'84I%A)LcAM-(OC027E<+&!2&,Ci;E4K' G"&BIM? C0MN04< ,G\-&N'"AHN>N'72I@$I;[);*>JE3-'+L#2O2VA3F3MG.P6e %&?M5"X)C=7V)9l\fAA,#aM46&?$PW(CZ #hB0=H5F60R-/(50N-79M.G!'9$O)$3/J[ :5+,_+(5,Y>?SuC/55#9?-VLF&;F-6?;)<A1<[*^>W!'0O7!Mjo+$AM.=/271'75#%>g> 8,4EE/743D ?))A 2B=e>HA+GH= +2 1/C"ID%81&)C-&%U$<5AV(J94/&>(*/#?+Q(8B6@Z9^&Y+A0<)WU,`;V;R*,(!A..S ,B[1.5o%'8I58=J) IR&%:JE(O>0QB%6>4=k&:A, 96HW&SR#BA#/;"8OIF;=jpV<O0 "VJ$OJdG)22Q:VG@Y!4H#AY09(6.3UK=8Z4:0:**<&3 06686.A>DZ3+0&K) 9.)/%(?GA"#+Bx (%&6 A 0(GI6"%IH%,==A7(@2M1B&*W.ekK A\<. +*-1Sb1QAB6B(U)W]y,I;<4m7!9*B8>PBR--9-L4 9&AM.59=/50P(CE!C?'YBFE6'2<009G-'/GHD*L3NJBaPHR]EaH7g34#.G77*W1?&L4.80L+A)$P3dDJ=B%'.00N%!(2#(AE6=<G#6L*-8I5 $C!8E-DF+0(Q"7[O87P@"X=><?3<?('%+)'4g>*0F8>4$;@/7#(GS'1!6 9K"Pa9dY?P<!a7#6OH>%C 5R'-%>;UAVDBKJ1MS0ZB>!;E.D.;(!8&8F8(./:2G3,=\$9#.'W&?(1Pw*tE&E63=38R"A6H=N7#L2D-C:CBN7?28<0)@BELE+/8/.AGB>&H CQ;#1A0?6f(3-&/?B9=FW"!F:6T"E0RG"N#L?24"(3.?)51A@;<J=.0:6S2C1?9$C7<CC0K:/H9=F4C)K$.BH=F5%GD-O %  I(# B'3_-!'".)T5F$-0+4^>D1 H+FF`31+C5M(7-')=AVX4+J;E7-^0'5=mmDR\4&)Y-c:3%C;;GTAQ1 4!I>-6;U& F)KE"V:40D#K1>E<,9I7 9>&#7D8'E,F8%W("421=*:%:FM;.%BK/17C;!{"R.:P7F;;"j G8F)D2T:[4'N>$/Y-BN+6*D>P)'37Di(TF1L+6/0[QND-#C5-651F3I4/9;, H&!HS4\I343RR: :2/5<4=S4(9.3Q4W/)#"olgc)j.6V7%*T/^zZ1C901>1SOmO<C%545$8!#%?"5("g&L8W37I-/C=72B%"-04(>$1!8a*=/0)! S"92&*<W2AQ@9 8b/C+%B"J2:36EH';S"0"F1E$$AD1Lo5:0N%24/7-T1"r-&HZ@17! #&=,;4T,:9AeqTLP/X-J3JO3$5>5=2$8KD!2Dd1WK<8"^)?/?9L/<583@-$;FH1ZQop;9E><Q4;3LLE7L+%G,QQ&/UER&/H(>\#%CH!<2X$ N?)(81I,9384'.G++!# W] H6: <) Y./ I >O/B9/+K C, <9@F6JHI:'R7GS:7DH*)Q)#,52!!75O<9#=]i/&((/F3aaJ*+96,3CGB(&*f7< I,@##.@5@@ @J*WA3A *!71H!4FM/*285@n4LL: ^&;,%JJ K<:+=7_B<\Um_LJ093E63_,IF[P773aLQ4D);.ZA6> 2N;76,-3j/Cr)T1!#90V!>8(,H027aP<1;8B\(6J<C:WFP$R$8E$B;?,:?X%((52(%KfP<763&8BD%;R<^.[<*6!TI~II0NM-A)8@B# 9/"/A?1OHJ4.9/')41LXI28)B$f(%-Z),;LE6)T33A+4.?XC'<,$\3~4-8*$+2A7Kzpb=<1/=CU;L!JF2=7CWG> q!Y?)>SE$*/+&=X_= 4D6O.#9= A9/2W&&+i>=!"%/SE)06@?398C/)/33 JD3B,%')4-(#=' 7'<?F+.F&F*3'9O$JO8#')LE:LQIM)-T95V641o8A%@< 7?oD*<'PSL0W<-K8P3K!?4VM~F)D@JPK))7--GCA-FT4;Q9AL/b%"(;HCKJ[%]33,D?:H0Q_T{IVH)bS426.RJ)8%;9NH,>+0%82E(4>2C-,;'K5'3(L0C'9:<%:2'@$=  !!06/G2"E&>FZI24>M+W$9+*95)J"<B'(1-:+ Q%c-8P01A =3@a:A$;52==H2:L:8I@\2!/$G0.Fk\'-=T 9.L*\9CN*L`E' (: W-84H'C$'<%39#PI68%+Z@K%rNF<#:1&I!&8HM9*FNYD8!)\7T@Y.ZVBIC-98N6)D'"C5U] /O#2;Y+'($4?A "-/*R/8`7-X@o#4':'&5;K.;A!'(=</!1!+<4%V/E$'`)>R9^H#37*'0-*9W3)=S]@J."T,!#<-!B215OB0H/O'S*4$%FN* &.L2/Sh)*:I( 89RZ`T>=Sx?#%/P %AHB<.a754?0@(46=4<T#I">F5C>9N6CB$85A40>,8+]\&!54MA$C5JC5</?>DA;A,?8+ F5Q=+4M+0,:-F-c.'EQ2%8,OHc97>/"T>(NB!.888- .5!<)o/K$/ F' 6"N*5-=<*4.ED)V+I-l c#\)9-%  D%L>/ <D,2H<,P0Q74WF-p4g%:IF<3*>9M:(LY$Pi89+)9$/7PKQ9!Q")&F7OF4*/G/.[3JA5YS$I$G:)-^ E&= (0:$U+,N8KQDFC:G/*I9A5?.0EAKA]?CE8A?!R)L(Q1:&UNM=K5D19>:82-U5?(XJ?GF*,ME).K27 ^:%8H /0K3A,8.?>*,4A[d?A<M,34=D+E6%3LLE*)',1Q 6)L8N4:'G'?cG3M7U6U&J -6 1RRP~i:1;@-3@'.^2MA099OW/'@O(&6KK+D0W>[AM0+200?2:.0M8g6(O %+L71D<?VHJ?;30?9/J9$)&:RAb]DZJOB-P4<=RP<1gWMV&8MPKO%1/,A:7U20F7?4454;J2@6D'1H363.DL#E5"/2CW#U7P76/'!4?CCQ+/=9M/*;4&)D(HN.B'SCK?8;+:'G%::L5H)'%7;1);R@N2G73)4 '-:,(<)>.N#,Y(]48(K/-`2MM%E895@:3J05;9LC/#*.5I"L?5(. 3&.,S#.?23$640J&;>A$K2LV9GmQHJBmMpdAJ:MJJTA B'0)(22CGA7,/$ !<8!>5+8;N"R$# 3  R*U%.C0^*(/N4L6/)A\+BKBS<6`#] >*KN0 H ?2?5() B4'C?+."->4$97!;#%M9;8(>,''5);924)&$*UB#H;L@>="S+@=3+?)5J!)M16H'.>JW:+\/5 .%H"+XYb'J7P:Z';]GAG83!M>OgE'<_\;5_FMEob6HdAJR=TNK)TC?0(7!2!5/'SH-0`7)$S,".%/Y5 #,.,)"%+  "8)#.;X2 6I&/CG)5* EA137 ;"?S4:;^/D%!<8,3HB=#2'X#8!VHRG9:1/g@8>D&5-.0/%H*H H4N:>/A*)L#,"!)&A07(-*4XDG%>7"?47D/>802J6$8[,3<9\E$='`UI.2+H<45T^3D"$O6pXIq`bf<YxWE,#<2H-VCI@ R&;(Z*4N-?17K'<FL:1Z%:*E,._=12UFS)G-E4#/M..>XC11KG-9D-4\< ]O1@> 4/,L0# 2.@4_<[9=9G*'E&;G.0J=W>4@$%/;;7N".6-48P/I*RT+d_+,!# -7<Q,,3',P@5"PA!B,'`"(*<(=<8F7O2+ D8<2Q_=O:A(D5S+:8[TB0qU@xek|MA&A+3JN4%>:*=I/.>O=',9JL+C(TG6(!C2E? 3)S'4*E,29=K>B33GL* )MGA7ESK@,HB-$AL%7<BII$ *A@';+#'1I<"1%@0O. 95K`!9 5.B0"4M*Q;6C;/NMH"%.>'28<00K/>+71&<9)A/&:?.13"FR H5i /E>@S#H4:S-):= <6N[R:sFLfFU9F(=/ d1H-:%K.pna%mfP 8I3.%2"@78G"[+5<CL12$9"!H#=...L'2%5*264->1-O'"8V,=U*2B$-o=#.+1-9V%#")%4h4>:;TJVD9&4=*f?[*t 0@6,C?/=1-!D:(O<,4*>U.AC3%1n;JT-I<P$:"C7-$07G1<8%,-/0<B)3-<* ~=971$<LS)3*Y=^E8T?'#3#<9Wid]iX"D?"C/%$M, 5HdsE 7e!b`l05DW26 )6&0*5=A9*-E/F8%C363N7,";6SH4P/+D.4K/"#(PD/ ?000>8H81&`C 5)):lA (Ntk4=7(ID-5\4Yb. @+EGT;7DB18%a)_9VE]': -:*0)B!G2.J?..;@/>4=4I4EV F<:S&JPXGBTA)4/3=(=:nqFKKA%EFL:NYaQO^=m73R5<APhw+$ 0K*0g9HAE<l$JD#& F'<P8UO8*30O)>,J+&Z/#3.3:A3 C* j"W-- (# +0C"$WE + 94X.<%T/AKg!(ID0 Y#@1'-%';.990&,=@GC"(0;6(&>3%R`!)H[K6 '-1*2877>H9N594SR 296SBG+&%F5-@<.$T S3C&:/<LXE@.>'1@7i=6?Dy/#WVHP Z=%R(38X !s+Tj0! 5VZ31; >;K2.#&gQI49 W_K51V)OL88"  <A/S'Id<"1*.RO*;;*!.+ EF07M%1,'@!%22Tt)ejINUE2Yre<F K0HI? = :&7B2'QL)A=52:*FL /b@6SD"6?$4,;,6I %9?1F N[_"4@@4O#0!+(L 23SALO\>5%6-R3@c\%'/:ERP K"KttDD[7>?./(3Poy! 50E~M_t8 !^NU+P2?4)8*".: 'M&E,2K4=HGB5 3?.LL(0F6I !#6H&G,A=M8%B=2c553)S0L7H@%4R^A]9G8PL#&7<GSI14.3D5>.!B3=A#&1!!83*FR!W4,8B,8!L-2KOX?(O,IE(:"?#7B@0C>3d2A7EE:8 =V@C:[=,FA*%1($:!WGF/$'?_bn5/U@%5M1,%}9 i.S=& YmKT*Z@60C@@* 2%& .))$+8'>$7Q?F 678M)O-3:<"I J)%6*3 7O,(GQT<d*<3,#B]%F.UPEtGd&I~ racCK$/D&*R>,H245?1%T:-/))245&$3 -F3 84CO"TB$5&)n<5U9^8%0<5)JO2%$JI<'Q<1F:,>0M+"3B>* %,1)30$650gBIzrb48>>QTVEFK{/dd'|v{VT';\M?c@MF 4;A!3MD6! >+8'=/ + CO :"!) <"B49V!41G<&. 1-0]"$<! K" 0 UR6E%{P?QP}IVN%B8A\ZF=D&:7+/(:8Bw&/FZ0"(9>N-(<PQ;? "*16bZ%>pJA$ <A<OVY0)H)'I+"2'--BSACJ?/)e\9a^58/1.+CD;.*%<&G'I5>&FMdYb9:t>.= ,C?5 + O Hd>k>+G&-.hL8 @3=-K[(2<*;93T<+5'-1@'I2DG0<>#3_3)6:S/TQ%$GC9$*41$FD"QA.RN.;8jY?RsSJ<l:P/:C8985B"8|E1.&&21.=^I1E2SQ'[I`?IR%7? 1@.$K25 /HE5P%1.M?(6N!%2:51+&L2*< $/)^FRXF?H7/I)15Z&-3G Q()Q\4Q.;7DG2eIQ23A*\@s7sH{PI:i$g$88-KUE21&6/T%G4 *6  B5X5H53VXL8)12,2M03D# ! "'4;&!I"7'?.FIHJ"+6;"$ "2K2WldYO5-0X&P>E/;AA1bM8.DO+2A;05'06,SRt\>-!:C> #& ):A+ V85M?4m(E,2&*S&E5X%+<]R"5VJ^K>I:1 :S-.N! #<3!5(95NG8J~SI/"?f=G9A*+;PNUgm$|Xg6Ef4@3TKDu)6(G'8I+0=,0'@'A)7G<W_jCVJi9O&L+%*5J 9%0@('<#  #K, 6H&Z#!)?Y@*/%$$*:BZZ~UUL@/Y)UGD# +STI:*<U/F< W?4"-@#8UZ18[:(/AC<;&4 1%*%( 5& Y@?QP#MXM-6];5 "WG-FO;P<LD;7DdB98]6:23" 19:]:6NJ:F"E5"[H;3  51K_a7Zh|wnW?GZYQ462N N92C:\&%E,4>!==T.9J>]\46>:,+& ( 0 4 )4O3F5:5($6#:$;< 26 X$Q#:#A53C^T@FC0;4*('>"G*1`[WFI=2+JW; /C0('G7;=?P7J\e < Q=/1-`%!<JI7 &4E+4)1Q(8A12.?\752M-Fe+V5P*M3R*7HP)"3'2a5D 4DILa$&ZFJ@[bC[&LaVb^IQnN6dE`\x_`/3"eEHHC*495)15:!8:(,/5%(2%$<s^A$2*/;M>>.-12*E=q4'`6;F'%) #:F5#QNH;11T5/Z7AOI ;8 7I060?6@$ 2dC3B.A)]1>=Ar/f!4.57I.188  >IL!7+2; %*'$*9I7#)1)7;_6>(H=?T%U9 JE'B1!+&((O+7)$#.54VV'zFc?;F@XDG3;s;;A~^WWU?*4/H0<!?1&#o%- !&8&8 ;K+8H5SZmk@E\:'K#8:3!R-A/4"]T "48A&D4$< 3D0J. $ &$>D4;+.,"C<D-([3*E2g9K4<2'>@,RK<B;%U(V!JH,j\>/+V)a;LK1110?.010L9443,))9 @4A>7A?2.L]8$D/729+-#1L?/48N(RpEL-\]')96UK0,6J1DY1m;B?*fOGsW-B/+MCO5;>63)]45#/C2=53U;#)1@*1F?;:G1>SD/E$>96>3@=R"<kE'DEN 1Y&@3I'2.(<,.QB4)$BL`IN?600+8$=%h% ;.#:6 +/C+kGGLA("(@.TNY5%#0 6&=RSP>9'+B=,LE4<M85.PD)?'816<>*?<,/4HC#=Y2-&7FL8IkE+]J4C81CQ`b1=C*6>H7h8t46FM`3SqM3e,q%,<E"Q;9#m/5($'5#B)4K(9<_dE9;$D=o >$E:#A.&>'.dCP<'79IJ1#K, 2'6'I:)=:!_<V=?3E1/2/"+ ')*?JB"2KH&,=F'f+"700>+".$3+E]1'BL;B;9"$A=*.9?)h D:VdL593%( 5'JI -M. #0C8,!=/-K0-(7&U;84/+J#.45XjC:8YR%gXGeWKJ.9I-1 59FnW%FI[3?ac6<&&6NE:&N5>=A)31!CCM &DXVDH/6 '#%"/;O@#-&#d@6-:1A5<C F";"%d(%>"87J:9;5577>KA)P!9?0+-/-Uk!>8J( "53EP!*,O@1$YTVQk49@Y]9.3 WI#$*>-33,\fL#&O286-+(-$7H J.@ Y):&3M#+p#92'^)N338$@?-&'F528C:+/? KH'&.@H: > T;7NC:6)50<37DY*<8C<+p:#<SYDFbBH1>.RB. ";E'1Ef ;D<>.0c)75$*5$Q,=9Q@()'=:L)3HL*)/.1%,::0!'-HTE0@2:%<)9-,'M84(]<XN #5'8LHJO%47V0r"E7,2N' 33]hC3->;L 8.C;3J9301$.0+J3=H5.62& %#2>A7+!H*475 D@E+F>@<9 1;H "Gv*W-M/U;3@.fH*L)G56E @'%2].D&3`5]%7]85S+=?H1G.EV,K"L>./%SB#36B/(.( 0K- B"7(1$>7<1 M]Ra2U%<.  D"%AH!A(E'<5<C\:1J/.G .$ (M?3[,6]-6UJe<8W4"SK9N..4+7*)<r3><C(3.!9I /R!55/-00J4J2!" GB5 a".!+(18F>+DAYwEg1#%$OC0U1)9GO>?@AF9E)G&:=($0@S5P 5?#&,#,+@<+@=5$%$ H70%\NF!/>2/"Q 3-$@,!73'#,/%#$L#^7-U BEDC&D^sQ)"283+Q1I))+ 412>*;K)7NL#+S!*(9=6B;8(G_:7,/-9=!4*0 2<)"2>?D@6D&3 - *><2AOW#G6H2N ,A>QM3\$"5%CCoAHC>10S8(CG63GLE4=-<Y%M3W$CC7/&KNCI9@21F(4O;98CA,7)g%(;*8$(8-N8.3*6-<^5,6L>,0& #3LE*FI':2E618 %/K"(R"$<  /')<-M95@LO/<3@(W/:D1"ODD9Q'6* 5^ ,5%*+Q6:!Jgsm9.0.).D<=1=,#/$O%2A\?>8D &B99!9,/G=<("0N7*Y+[E>? =>e_&-4@&?JFf6K02-04I#MHI)-(@8?U70P4!QJ::18:/'XZ/^<=/2=*./$DSN-HFFS% D2I"A)ECM$-A/4,(D-A2D-5 $%-053 O/'H=>[B.% 42+-P&;QD;:B4Y("6, 2"/8E93: 38B<?20::8,vBc=! R)]L<E+@C5 CC<PH4? #: 4( 4Q/O@4=<(G>0('=9%3 C:@!"+D/H-D11>L'7YTdHj$O5',?5AA+gE=1*\8FJ>-@9F7%,>PX8$;? >5BLQGC-+!7.K4:.*W $H?!%8@1 20T>)K%;?I!(?S`<<D.K%</N.. /-),.449/0D2cO0 '3l2.8 /4K6'-R@.'=*F0!%Q!*( $2P(0$R359D1 Q7(@YO9@#-7'" :5H!8=64 %!449LN+Cl`D#=#0aJ75K21EF6&P 5><'+/=S0@JHJPLP/]-II,.D9<=OJ@lL+$=M&a1+>9[+7@Y~Q%94:=F*E<>6L>7A=28<W7'5"52[3 BJ;19J4Fg0   )!"%KB&UG*7Y,<*QD IH *8:,4"!)D NM#SlG9EIGB2:;<=L=G>")A;8'-D4B>((&-#G [&0$ B@/1>'+T(-F;IL"+7_p@*]BJ "!L97526S- /!$6';8[GO:2OY"0*#i.;8UK"HEF=>a@+M]I@H@09[2'NaHQ-Ea02G2MP CV.*('>b8J.=$84D2.>KQ<BF :9 3B);GE+:-)(1J *HS;J&KNFT1%3(29!?)9L#H2+*"/A ,&<6X'#!0%+U1<-'(9(47AF2+A2N9*]HA5U*5C.'."2HD(78])>14/?;B8BQG+,P`GI1A1(20T":2H6DAKD.;@>2R9)R1-I#M01F <"5B$P33!5/5_MA4<H&aK:Us095'<11 G73 ,J86>:R7J83$?@;/62C)*X)@=\49P)):!D5.$ 3d@!#.3[GGA;F4/*0K/   4-?<))3<.1U#&; &#*D +E*[4 -CF/!7JD$"@A2.,*!R$7H?66[KR'65K&E09GxnYj9*JOXIV9@0=@^"- 0LA;Q6 %3"J6,R5/= G72F2>'&I,VS!Mw6C1c*&I8Y?N$C;"CP?58&?I%1$1:c<'=I0 & FG55XNF.#1?"<#. NG'- #) @=)/3+C2 E95Z (FG1%8xZ2<6MHGY<&6:/H2"%9@ )!s,%=00*'$R.R/:< 4K6#E) =/-Ig!.7,-= %WJ):0G!4/Xq?=?#; "#3CI'GAv'E4@RN]P%A<+2 -=8N'?50P:,2P>:"I]J6<B;bX/Jl&;;E=N\C!@?3 8&)" 8'= N !"275 :8H7B+=8.5C0;3(.2(B. 32 "$)I"'1%(ZE 5(-:'*0!;$,D4$,g6D;>CT+.:H 6K.I G(JE*JL\B&4/0I-:%7?3DB*#J2@4 ;%2HKW;NE33EO+J-+1bl-C:8$#F*,((;)':FH* Q!AE127')" U36""KW>6,:+<5H$;: 5PHY&RL*uCC%#C+ BLH63H!%'%$L)5;4 (#L)4EG4A^:E!,+h.)%;43ED$);4LH/\ (/F:P45P"\"(&T$1Mw&E @K72$]0>#5 V850$8.&%0:*.D83+FB@K/&C-18H,DEDDL.*>"8/ 3d$C.@^+,;.V<",r]T//')+-D" 3#O"B<.K6)*N%>#8?(7/'1M8L<HP6K=WW*S>(1($_*F>#]7?F.0K9HOH$o70Q+$1=CYX'2$AS>A+Z)JE*D1>H13(71(I0)Cf^<(K*7(3%19* :.]-8:(TJ?3?K:F,!#++??08)Ue<! V=&0:!PHWP,= 1/,VFXwwF3M83.$0(I-ZA4$Q;50H4)>C28BR/&&-;56C%/$.<@M@&)/:+<)2h. )"!-y:) .K90.9Y;<!2b8VC!1%:2P 801&PTCG1<|w0-*28<"M()C//HX2R],0 ,T1B9B"06"c=4!01OR0 #DR,<;#%=64)x,X/'/ L8+$$-DJ(-<'&JUP;3A0$-Q&*:F :=.+ :#EP;|]2f:;+=;+"FY=.EF&$F)!),*b$77>;&+V'PYL1 *0" ;5(-&;5//:)< .*3-IE_@(M$;3#$F0/#B/IGG@B*"6C1C -%<A31CD;b@755H/&Q."*HL,<%%*0A$C")3Np'5W,8?<; 70.[ D5;%'-"7"CC (E @4-76:AE+K-LQ A *,,5<#5DE&#:7B'(?0;;6P38?'#*DRV<K3=$UN>3$/C8/</22 W`=*$&@30,SC<>'! V1E1=*?BB0+8/($L"+6N&SE8IV @?10/"+5+(.59!N22S0'ZA&Q+=:/'X=7+_(6>0#cH]LAjAB>J08=. )(R2<0%09K <#<%;2 -*+);4AX*?+@(F 6M)"))-(O30 5 :J&8@>=," /\)H'1<39E+>= ST 2G45/N%0=[,JC>O! =23= !AK=:4F,1&<;)G 'Kj2(-=!A" >K{.;8:"9)"'GG,v8PEL1F,$0WSC)C8'*A'96F<* m/<> 6:6SJ+/?S9.(1B;U$7\+S3 .*@=0a>V,/6$2$?=7VT&<8 3*])[CI./MR,EEA6QD(= H-005E"'@R/%G$2#)!!L0-6SD;/)"(66+.7.(14>K",4:Z&4N4;==/8 *JD=,+.#*5!# H'"8?9SP@ :>.E9?N$ "9:# XMN-34/C(=3#:3)*(JS<$&W=6"#%G659 97$1-aQ%7STZ<9AE2>E65]FD%8N,,._@FP^ER<4 )7K&:5G';K>)7N>J->6$E?=%0+]+"+7F00QNC[G1,=!(C.5HD3/" , 05>-30@.*.,"-:4;*-7Dq'B%8P70E"<:+88!$LJIU.'LG  T09` ON[3:h1@")1,M4C"C4f<;0E*<0!8<V4'"-.A/S4/=FN,, 4H51Q0=A/L"C9;N:@&>/OBG&l%UJ41*=D!.7+ 'R"!E>A6H9O303K-!209+K C5-(9*h63$=2VB'J2&.FF.7/A+@OB'('%69W,+)I2& AQ!16<1<9<"r4H.@=K:87H N)$ 1@=&Q2:,$W4+22H&"$'K7-9 PMEC(Q(H>F9183)9:B2(:/ENS>*6$E?*;+E8?P#5BLL%E,#Y@G$8N; ;; 2L%<;=8AC&;>)XWNK443I2[/V#3/;3BIX<&3,E1$:5&@568e4M-<18G#Q0:4956**9!*!17154!''03*S<)^[)?)((#70+0\!6/H@  &=]! C"/.),!JE59*>VD8 ?X?7:O*(+C-181C.9% =P/1"=`/0A('+<@;FS,4.7(']5Fi ?5"5:) 6Q2IX2-`2>-3@FC/#.:8-2 L$2'$/1WTzHC$+$,#J!'88k(=4=T)BFIKZ^ 4%<BK@K=QE*1!]$1CE3#L)9H'0! ' <17 E9EHM)<. 4=+1!8:$I&-2?O5*8DAMP758) (#6?=+:4L./)OI?/<".'0%7-1#@.7<l.6.L3;%B'6$2SN/5a-"'A=6026c8]':5Q,*@3)A+#XM E (#E ]&D;&O9CnH=V#-6)B-H fv+Df.N"C94,CDT88AIR+ [6g'0;+$3C;.6P+.G(-M47* >^0(H(4L6B+%.$>&@+>S);8f>E! '<G,%9$=%',3"#7( $!.7H@-=2VM. :<882>)HBU_@>E,%4.H/H)2::451GG+?Z9@B-#FG<!CJ<' 3*C9O2*('5G F$54+E4a'373T43/9;H4 93KO$,[&O/?biD (7P%7W:Y9;+$H&Fz84 *4<?=K%*E(5&G\1DG*%K-<WRTZ:E$ H3'H0DYA!)E)Fj@HV1P + "2W"+2EB8 ()&K1S<5H?0&W[28=')"*+02=2`A!<=%GEM  CC:N;##"H/,A$8A4!E *(QUO!D68O/4N-17 -2jPxlh >4)%+BI;6 !&-*(C06K;ESQL$&A13=K,&2ZF^V(:+4)NI.1_'?2 & $C@@91B947$9)0/*<,+ ,"/O5:9<J3:&=/*=/ D8 J)E0,E!J")F%AA'  )0 b,71.<%"$,&XIL+D+0B0<AZC z)IGo"/-`@6-'&8,!B4=1@847=@:+@*%+2)7J.'?Tv  =P04.21,F&?.///38>#>!4/0N*NWX<R6$a*9R"DCH-6T$:JFCO.<-TA ',6DG@"D/Q.MO2,/3.D;^H6#/2?9.=* .31040FF70'1&< *5E=Q9C$AE&*)*!H"7E4=++D Y88?;4H4=86L,+&"+)"9D=1@DC648Ka121-;\)0 N'SI)> .- +(4?:DeJ.N??):31E.+@[1?.-10=!-DE0B40F.::+CED]<(D>C87=@30. &9$6A070B'8V1A6H?Z%+.<:N(/7=#68$/43'7-#&.V1:-4:,/3:$&$2-627A@+Y @K=5$V$[IE"A P R XA#+/>=20V&GG3&%L**85$&: ]I"Q.&E16?G3NF/!)ZK=% +<?#jD=<(O790'L#I&;!,-(:(K+R04G5'0S26; .2/, 1&\#@B/51B24J 5Wg%>M"";8%a,I6BH;>*K+,=<(#9C/4*$:4Q;Y!1N6B"2/*=I SXl*2"EIJLN*A%Na? )>1/X:K9T<,,0-3D=BGDI3857L"O.4-+   7- -,!-7*  .!W5+'0D(=<M#5E35 65C87@#3H$9 ;F,3 3<+D" 1;>,F=O8@A73//5 9)HE3!A98A)H5jH@N09+;<1^DCL)5P4:*IC6'536*-4BD6<4P&GLJCP$@#.F* ?@B)&G*:a5U2+ I=XKCI.4DQ#>:KN=t2%77"LH.),*@: L / $L97)$)"$#9;&F@/4+>.99.B4!:0 'cQ43 %%$0B9/I19# \1IJB >4/,+.E, ;1#(CC)+ *^ 3' 3FK!B(:B$Q9E%.850)59;A>>rG63&K*H507UQQPE<6K<$#GCd;0$c$:?%:1CY$>>F61C0@G25< H@(!<=;b,2G.; 9D$A&8)1JiIr'"US:NY;+IKI?#-Y=/,*=@<%/U4,85+BM8C%*0 G<=4<=HI9 5@(,%.*,:?'$8@B%?G(@6D"A?2K8I=+ZD) 41b/2655A$%$K*U9a#I;=QBY;a#+!+)6'E=%HGLo!1.,J93C8;@# B,<+265,W +2?!874M2%W,)+8M5'2-"BAZ3.#3A,,8;&AFY1Y!8"9;JC21):xl?'NV#<3+F27'/<99S& '/-,$2!40AB#'0<C/'<7A*/4 75&# 0B*H63**>!#P#1  ?<)Q#3?*9"F BA.75M'O$1:>"Q+hROX4;G <H*ADG@[3!9=:,X+">?2:(!(7 ;FH;A1B:C068UY!:ES:,-[,=4+$9,;%0Z:(Lk6" 2EG39-:! L7185=Q5(? '+G=T7+7_c$7/<16*"G( )46.8U)<71A67"!F?D10-'?%>F*b.9=1+* $&#%H4/H/HU+7IO52&9=5=!66%*8D*]:-->4Y3-7."7 _&K,8'**:>;&!$H0,QJ&*-*C-;#4HV4Kj7NQ3H_,=Y'8(@:)>B9=%-AI0/#<aCM)a(C2Q/-;,!F /3Q'2.2"3*@C:/5L P)&KG'E$/! ("E1)1"40=(o5L'&FKQLCaH5% C'2:8 D+6A#80=#(2.7 #=%aF,E*UX,*9 D=F()!)-*AL.&DE.!*W3H7<0#1K:&)>GAMF/DC"H91I3BL3(EA6%W47E?'$,95@4*K9=1`/"!F!h-D$*R8GCX+ *;-("Y=f5)U)*D?#?D/*?k,= A<2://.:B 3?%4+,Z>H-+>GC%W%E($!-'@7IB8K?*;OY8_?)%1Lu(F,4 K.Q7;+378",%!/*@#C',. ,":*$3(G8$.;+<# &HJ6RA=*D000@c08?""Q62CE584;284W(95 Q17=72'S'7N$'KD$E-%E;171>-2=9+O)?9`+ICL-/=:B,9!F'44HG6*]>.GT0J <B-27d/-.\ (D3E*Z,8"*( H%%8/_>EU2FL/.@3 D-4<V (?4c8/;B[)tI+%e;OG:8J9+C2$/&71(8 I)B88,*.2GA3$3E8^=J7[2&=-)M>[-'#<FpQ 9#5!C?9%A 1/8`]@26?%JR"X*$;T8X/'#'24E6?L'J=  #I7FR+L;<AN:0U!$+:.7!26;&+, A,$B8'C&1"44QB/KE<E/&R?=+>eJ@EDB*=(DC%rDL( ,L-P:<*D<+6/5??5+(09&G[/?4+%43;+:#!)%T; 0*#=!6b,)%=07*.N /6:4(A P%LP&#2:%< PC-2%H7<_656 L(B3W:B&9&)'A*%%<I!L'.-Z""Z&323WB;''C&GbK2CF67!?/b'E H'K0?-m:++,5.+0H-[K%)%L2&3?$@&%/2:70ANAI?<G$#DW!E8(p8*' ="OI:5?<81%:!4 4,C) ;B7= #KI)8:#C,3.(& 9:;!'"F;05+8AfEG"(A@( :=9[0*7.'0GI#8 O9?:4S+:=P8JA0+/B"7-/7;B8,>#9#.15C*=C6:'VUS4AJ5T/I5@5;&)UK</8@7@75E-3AHJ!&6.(NB$-'5@S*TD)Z!mG2p5 6g37;/-A0M-A2R&9B;Q$A;Fo?=,G L&<CW3&7>7Q!%$HE#"U5E>OK(+53' $?5G&M*(=J.?30%66-%.6  -!5_77@,91& .PJ4 3&#05.N6/8_4.91'5I Z*2/2Q.9-A.40FT:(;2cB?=.< B-;4)U./9;F6F$C5G4 '8H^78C)?F3b BW0<M)Q0DE,?-08H@`F36=E*C5J@T%3L)h&!&@/ b*E!\E9:PX;1:20;@+N5-/@NN-,>(-D3#Z(.90P<,=*3.)%75&E7,S5A22<@A 8F'5 D E<HB:PE$% $.S$, 8RL!'H3"31,;@LK//0?@UB7:$ W12lB9*"D!=&M?2D32HU63$'(;;G)6F.AU?6>!5&O1?"<(=;::6C%870".I,L.#.,*1'w-F=8!BKL9?HO+-*-Z$8  "E6_8?:'2=-U1,:(4/9"F"'a H#(+( ''?:[O+0@.)%B8&9=G5'1A;&!J')}%R1&*5-+/59:<10@1>-#98#C-':$n]c 8(\Gd5)C.($K,+#1756(**TCB QD,E$$#2H$;?VE4)!_J;jBTl^912N04L43F4))8/6-1O EJCJHEDMRb%:R PH32G`]VH1_;:]%/'N9=QI?;;$G;N2E,)!3??A%A#)5(-'CJ ((.H?+'3EAF1;<46 -C0-;C%B#/*R>`AR4A0):J<)0M)!4%9% B#0";I$+B !-, " O;2N2 *1B6(H3(>@50MNc$;+-*8):!%, X@M $%> 1?)0.!B?2%CF <$-G8{7X74$8+O=6Q&'2J 18%4CQZL.)1(LS;BI;BeoJ!^_>?V7C8^\4'-&/%ID'[c-FE#'*'9%53&%%F5 IH5V&GD:e C&&xH+7P?2@V,(&2 (@'2AI&%@ k- @ ,8?)=H5!>%.#,>/:7$4  0;I^-486N$,> &/%02@ "3E%1'KCW3F$IEF3,G9!HX$>&.448GMI'*56 LD>! :11)8m/==:4@%,2*_ Y9ID7FE)5IXgDICK?N;)&E8 3P8&_P-6DK.1ZDC?O:*G\<L09N9-8]R%!=-984-"9C3gK F19!5!B > G'\8"L? Q;4C;:P2R1DF!$#$'$'9+?,.(%+e;.0 '81/ ##1'*4?#,*<. G\+"8L;$!O-W?6".rBJjC#\+-Q?ZD&: "F'N'O-L@<U*4[+-:7@,><7K-p16.":3.7'fB0$'46E%=@-K=XJh`^F8>=6?J^'$/.)jM. %?-(.6&*8IC-G"(,T0-E:I-?1!1LL0%B,4.8-C I'=(!P80$(,'e#5;*4(1*6(;@9K%1, >8)9"7""8,' 5="(B8O# %M,H@&5&' ^,)%NSWJJ16I"375t_@5J#">'1-+0#j.9(3""1G-8"9/H;K!B62G) *N '6C:IB *:*J?-*;A,C=0>]41lPN7ellE=32 M0>$6;7'6e:CH,2;2&*)!A269`8>$,%M*@ >3\Q&'9Y0/C0 H=*N09#,G5CL1@B# $)-=OITJ(! =$dA85H##!RS6 3Z)(?3<<$<D99)E a.:;0Zuc495YB*('6T/1;V+5*"'8&'9#(9%5#4,4 )I%>ALZ0_S':E1',4R;%.-XB0`6J']& 323C67>AWP.V7A@DIGEgFX0-7-; DO_U@-0668>$,P&X1b_8W&T3N?F%T.8'3<597A .0<*-$(1#' ;/9O#.>SD:0%'- ,j96HA%  $G B8#+0=4L#F/-5..I31;#).Q6 -B(-2/))@9[v .b#E?- @#/DGGjV6+B3.:-0; (7'@P=0$KUA');(O37515Q:@P9D$2Vb$&N,4'E,NIUbN$*X>5Qa:^o_<305*=/j?LG6IP4!B:$BHn8&D<5'@?1%E#=.1BA:.:2%%=/R6,1>NI?7CA3)$< 826:9*F.,:;!! 3#,%>,- ?89*%-h2G/0,5]Q D,(-U#/*67@*-C)&?F0+3F"SWo/-G99@'"VN3Z941+&;ACHKKFDR07&=)3=*; $:6N->+"'8>!2L95$;J!6Br9!#4G;0!7E3>M(G4j7R]^d:Qa,QB()T\<S7`&9.,)-<!<.Q'']/KW>38!R(A^@k?D7*@!')2JDJ(&3-Q7~>;%8#+" =866?!a%  "8#-4 5R:< 6 A.=9;3>&-'25+ 8#,M6DAA8HDC8$ ($%7-$`.`)P7< =B3+#)?+>,3?+AI&-F2',2a'#;>)%+;:F4<#C*#D0EB#?&A-m:--PL@9704F%B,:R0)*F_}\(I@//5>$6J0)$(7ZE,-9A=*5$B7)?M@CO?!J!0(8*K8A@%"5;7AA5m7Xl=#,(E>= :('90*\"jA);?/ K#6( !X+@+#73->:E%8L6(' _-N-1 &8FG9,fYT##..0{ ]%S3+( =H+GJ.7'Y!LP1/G17P55H 8A7;+&&6O3,-?2J)*F351))-7n)%2)R9QDUI- )E`FX')@D27B8*CH/0A$9"\9-F9AW)?*T="@,28U5+@)5/';:0'A#@6J@*(RH{: );&+:%9"E579,>!")D/&9& J I&'J$59!@1&<;LI)7:" -)+5#8!GC ,15:A/N,?(3C&/E5=3//DRF4%=) FR863>Y(I#M5L#372:T06'O:F"B/@5a>2LE1DD E(.7'1=.5)*&H+>*!D(*J>*D8cr2)=F-LM5N892O7TA[A7A>u2Ae}:A/:6,5Y)9H:7H:E !2)33F,BE0T1iXjk7C 1K"? @+6?'='4&)A4!67 l;K!%C&-% O@iLQ2'-$)7A$3=>(>M2(;7:CX  C2( !F?*@S2-H7&3<.=/8^.@&/=3(;;=A::M35/+*,==J+Pf!GU-4:%7.%:8W8 &7.?R1 5@PN_6A#,+B+A 6HJKK<M13I3 0L6+ $*c0!X&(C05V35/AEe /47)#k#:+!=1,I1_b;%#C##)/4C(O2/GS+@50#<j!+N20'+T.)M 0sB,;O:9 2.1"G."M .@:;N$%  86 4G22@";:[d(?,1@//HF6: 2$2$%FE8+HL?XF9)IDE8<Y&KB'E"8 H,(-2"0;R@C6&8#=<tP#5H521L8).1l[msRTQ-8e,0:-%2D5=8>2D,0--.JLR*"P!92.;9W7K*{G@ 2!,.S1C]FQ4:7&63CE%8IML'20%1)D.E?(K"6K9Z'B#Z7Kh8J$-5'F?;@N0?B!NO->;4 *9H5(.9T6Og_-LP.Y42I@+&>$@50(8I/!MEL,(76+S+c(# 2!Q-7O3*B$1.%33Mj=>I<^#9D'+*B81a,-:8 33<4:EK)CJ&O/EJ< 8296B@x!9/2$5WN5:>N,>LI(! / +J (H+J9G#,0&%?.+9\ ?[I*,AGK.(*,<AH:#RC)''2,-)3=#(6EL!Ni)&D"6*)))39+?G7H)#/9-;=/Ea*+]<J@cRwbX*I&A$46$ C-90\&@1Ag$a20/R/7!,!2A?-3706&5RB/=?2/F\ _$9FS3O|;,E=J11I90TG$Z;> C2-%#JbW >)"(F2/,%$K@0?C?+X&T+MQ 7jR0h,&26>64nW;,#7( |0037LP+41.1M)QAHbF/10j6&IZ1i\B1B'>F4+4k;2:0 4 91!3 ;A9A%R)+3-"8a!S(@[eEQA0+%IS:S/A1$,.&0?Sn0K>399>I!H .5"C"1 1O(K4LV? .8"W a_9=.V.;S+`#P6BG<? < \"0+>; T/p1O#|tWw'fB802&6<."0"K:1I#AB>=CEHE&?8<]IJ- +.3A3/AB5RI?i*xuE?O5,PwlX>hR6&F65:<R)3vkq0:D2C6+7 C3#6#*%B3 C$ 7+$J)N>*+O4xB)32#A;7*4H9{gHQB.4 08G1BE%%jr0.SH4)=6QD9;6!) C@6<F9S/ a 0=(%42 # 31LG"o0*2 JID T!FK?YC\d:<(-> 4:*0;/5F7Q33?..6(7=?S.4E+;H@]3"AG(B3<A>A)2R;`?D4BUXdf&NRB6:l],-!G+#I5R>#Q/IE=I5K45=.C!>(`AA?+DK<(,?+;6!01\1 /+) )A:Y~@=F6,%<FCC?"L>R-ES46:>C#X'(Q>W[(2-+@)2;.D>62PCF3@/;O& 3p *2'B'"!>!(2</?C1CK#=1=; 244?J>TUN"`$0DD>-0\*Q9,@`O7'8( /<V14@MK0;9%F#05fOD' ]5D9B 8>Fb*@% GI4$6?9/^$0K:9@2GE!5!?.1-Y\#&A$424AA6=/&5!*G.:6<R8$)%-2Q$-?27BCE$GD5/(:H'/E@P+2*?8/D< ^>F]?$10&3/+-<$5@0=#=D84$ B9>)=4;<5d-;%-a=1?'TD3)4:a9*<d-/X7,8"*&4*0&&5L" 0#H.4L*8WV/6/ K?'>#4;,A(J%D?H  5(.7;+28F*.>MJ6M&4C!Z:9G&@$GI*-'2*'@@,($ 7S2)S#56./4X 4)3%* 2=. "1.(7V7OS,-oO4?G&82 IX)Y>,H3"ept4$-D"G?G188^=4*C2K6,G< F6$!K)VH,m55372$?A@83921(A,0?r;22b+?:1H"!>!</)W=<MKBB-J^1L8T 6+88:4$B''E2F( 40-%4 2" +PA &R4 8I4A,,3!70(A'&3.*5+9 J=(*BL<D#!C56M'J&IAE?>.>#X)2.%Z. I9$0+C4%H.<30 <7 N74I;2JNH79R8K@89DT!MP+7/L5 0(9N-6 V+7@Y#@M!4.-9,B36M60f, 2=MC@/p,X"*%:B_ C59DE$<6(<'Byc0*_-B1::DP=W071F&BCH./)3&)=1#K$. J=>1 L28I,&)gJ)Z+/4L,16 j)%KH-5;,. *("62G> 6C.1+S;. '25Q/)="9%3#%f47&K4%F7G(8G*X!.K=,. .Nq[.3?>H<!'_0FC/.247.2&<J3OD+F96<UJ<K$#g807( Z0gI0."3A+ 0L09+-2,@'H%/=&"A:r4-0"[*H25A;MV5B$YD6@UQ36(0L9E&.JH.% <L :F19;B%;!*45,P<C'4]>I?/$419,,F <D 6Ib$ '9#,L/>9 % &"8m%O1-= 0C)010Bb?I?=(7-,&7@C1<D&<:CE-<" @@#\=>;*D@63A3NYH5/$BG4 %D'%.+=9<:2L57YMQ]5EB$  g5=O\@&,0'W 3L8 NeS)?RIS3M1!$1* 6.:H"OWX1?&+6;1 ================================================ FILE: data/rms.fits ================================================ SIMPLE = T / file does conform to FITS standard BITPIX = -32 / number of bits per data pixel NAXIS = 2 / number of data axes NAXIS1 = 256 / length of data axis 1 NAXIS2 = 256 / length of data axis 2 EXTEND = T / FITS dataset may contain extensions COMMENT FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H CRPIX1 = -7.670000000000000E+02 / Reference pixel CRVAL1 = 1.000000000000E+00 / Coordinate at reference pixel CDELT1 = 1.000000000000E+00 / Coordinate increment per pixel CTYPE1 = ' ' / Units of coordinate CRPIX2 = -5.110000000000000E+02 / Reference pixel CRVAL2 = 1.000000000000E+00 / Coordinate at reference pixel CDELT2 = 1.000000000000E+00 / Coordinate increment per pixel CTYPE2 = ' ' / Units of coordinate BUNIT = ' ' / Units of data values BSCALE = 1.00000000 / Scaling factor: r = f*i + z BZERO = 0.00000000 / Zero offset: r = f*i + z DATAMAX = 9.852823437500E+04 / Maximum data value DATAMIN = 3.713666992188E+03 / Minimum data value ORIGIN = 'SExtractor' / Written by MIDAS DATE = '31/08/93' / Date of writting: DD/MM/YY FILENAME= 'NA36Rm50.bdf' / Original file name MIDASFTP= 'IMAGE ' / MIDAS File Type OBJECT = 'NA36Rc50 sum of 3 frames' / MIDAS desc.: IDENT(1) DATE-OBS= '26/10/92' / MIDAS desc.: O_TIME(1) MJD-OBS = 4.892162787000E+04 / MIDAS desc.: O_TIME(4) TM-START= 1.104800000000E+04 / MIDAS desc.: O_TIME(5) EXPTIME = 1.200000000000E+03 / MIDAS desc.: O_TIME(7) INSTRUME= 'EMMI ' / MIDAS desc.: INSTRUME(1) COMMENT IP_JIDNT 7 / IHAP: identifier system \COMMENT COMMENT IP_JSEQ 24887 / IHAP: sequence number \COMMENT COMMENT IP_AHGC 2857.489 / IHAP: high cut \COMMENT COMMENT IP_ALWC 2112.953 / IHAP: low cut \COMMENT COMMENT IP_ASCX 1. / IHAP: scaling in x \COMMENT COMMENT IP_ASCY 1. / IHAP: scaling in y \COMMENT COMMENT IP_FILE 'IHAP/FITS/EM9210260304099.FITS::USER ' / IHAP: Begin of keywor\COMMENT d COMMENT IP_FEND / IHAP: End of keyword file \COMMENT COMMENT EXPTIME 400.000 \COMMENT COMMENT IP_CBEND / IHAP: comment block end \COMMENT TELESCOP= 'ESONTTB ' / MIDAS desc.: TELESCOP(1) OBSERVER= 'LAPPARENT' / MIDAS desc.: OBSERVER(1) RA = 5.648170000000E+00 / MIDAS desc.: RA(1) DEC = -3.018297000000E+01 / MIDAS desc.: DEC(1) AIRMASS = 1.068349957466E+00 / MIDAS desc.: AIRMASS(1) ESO-LOG 00:00:00> DATE = '1992-10-26' / Mon Oct 26, 1992 ESO-LOG 03:04:08>-START EXPO EMMI RED / Start exp. on EMMI Red CC ESO-LOG 03:04:09> EXPO EMMI RED NO = 24887 / Exp. num. on EMMI Red CCD ESO-LOG 03:10:52>-STOP EXPO EMMI RED / Stop exp. on EMMI Red CCD HISTORY COMPUTE/IMAG imAR0051.bdf = #0001-bias50 \HISTORY COMPUTE/IMAG imAR0051.bdf = #0001 - 1.51001E-01 \HISTORY COMPUTE/IMAG NA36Rc501 = #0001 * 1.00000E+03 / fRc50 \HISTORY COMPUTE/IMAG NA36Rc50 = NA36Rc501 \HISTORY COMPUTE/IMAG NA36Rc50 = NA36Rc50 + NA36Rc503 \HISTORY COMPUTE/IMAG NA36Rc50 = NA36Rc50 + NA36Rc502 \HISTORY EXTRACT/IMAG intex = NA36Rc50[@0019,@0003:@1042,@1026] \HISTORY Renamed from intex.bdf to NA36Rc50.bdf \HISTORY SELE/TABL cursor MA36Rc50 2 0. 3 Y MA36Rc50 \HISTORY READ/TABL cursor interclean 0 6.85000E+03 3 Y \HISTORY interclean Renamed from interclean.bdf to MA36Rm\HISTORY 50.bdf READ/TABL cursor MA36Rm50 0 \HISTORY 6850 3 Y MA36Rm50 READ/TABL cursor MA\HISTORY 36Rm50 0 6850 3 Y MA36Rm50 READ/TABL \HISTORY cursor MA36Rm50 0 6850 3 Y MA36Rm50 RA = 5.648169994354E+00 / MIDAS desc.: O_POS(1) DEC = -3.018300056458E+01 / MIDAS desc.: O_POS(2) AIRMASS = 1.068349957466E+00 / MIDAS desc.: O_AIRM(1) HIERARCH ESO GEN ID = 'ARC-0001/1.2' HIERARCH ESO GEN PROJ ID = '000.00.000' HIERARCH ESO GEN EXPO NO = 24887 HIERARCH ESO GEN EXPO TYPE = 'SCI ' HIERARCH ESO GEN EXPO LST = 2.420000000000E+03 HIERARCH ESO TEL ID = 'ESONTTB ' HIERARCH ESO TEL LON = 7.073450000000E+01 HIERARCH ESO TEL LAT = -2.925840000000E+01 HIERARCH ESO TEL ALTITUDE = 2440 HIERARCH ESO TEL FOCU LEN = 3.848200000000E+01 HIERARCH ESO TEL FOCU SCALE = 1.489000000000E+00 HIERARCH ESO TEL TRAK RATEA = 4.200000000000E-03 HIERARCH ESO TEL TRAK RATED = 0.000000000000E+00 HIERARCH ESO ADA ID = 'ADAPTB ' HIERARCH ESO ADA MODE = 'STD ' HIERARCH ESO ADA ROT = 0.000000000000E+00 HIERARCH ESO ADA GUID-1 X = 1.294000000000E-02 HIERARCH ESO ADA GUID-1 Y = 1.717000000000E-01 HIERARCH ESO ADA GUID-2 X = 5.070000000000E-04 HIERARCH ESO ADA GUID-2 Y = 1.110000000000E-03 HIERARCH ESO INS ID = 'EMMI #1 ' HIERARCH ESO INS COMP ID = 'HP RTE-A V5' HIERARCH ESO INS MODE = 'RILD ' HIERARCH ESO INS OPTI-2 NO = 1 HIERARCH ESO INS OPTI-2 TYPE = 'MIRROR ' HIERARCH ESO INS OPTI-2 ID = 'RILD MIR' HIERARCH ESO INS OPTI-2 NAME = 'RILD ' HIERARCH ESO INS OPTI-3 NO = 1 HIERARCH ESO INS OPTI-3 TYPE = 'FREE ' HIERARCH ESO INS MIRR-3 NAME = 'UPPER RED' HIERARCH ESO INS MIRR-3 ST = 0 HIERARCH ESO INS OPTI-7 NO = 3 HIERARCH ESO INS OPTI-7 TYPE = 'FILTER ' HIERARCH ESO INS OPTI-7 ID = '#608 ' HIERARCH ESO INS OPTI-7 NAME = 'R ' HIERARCH ESO INS OPTI-9 NO = 9 HIERARCH ESO INS OPTI-9 TYPE = 'FREE ' HIERARCH ESO DET NAME = 'THX31156' HIERARCH ESO DET ID = 'ccd$18 ' HIERARCH ESO DET TYPE = 'CCD Four_Phase' HIERARCH ESO DET PIXSIZE = 1.900000000000E-05 HIERARCH ESO DET BITS = 16 HIERARCH ESO DET FRAM NAXIS1 = 1060 HIERARCH ESO DET FRAM CRVAL1 = 1 HIERARCH ESO DET FRAM CRPIX1 = 1 HIERARCH ESO DET FRAM CDELT1 = 1 HIERARCH ESO DET FRAM NAXIS2 = 1040 HIERARCH ESO DET FRAM CRVAL2 = 1 HIERARCH ESO DET FRAM CRPIX2 = 1 HIERARCH ESO DET FRAM CDELT2 = 1 HIERARCH ESO DET DKTIME = 4.000000000000E+02 HIERARCH ESO DET TEMP_VAR = 1.000000000000E-01 HIERARCH ESO DET TEMPMEAN = 1.376000000000E+02 HIERARCH ESO DET COMP ID = 'ccdr-V1.0' HIERARCH ESO DET PARM1 = 'CLOCK=tho1k' HIERARCH ESO DET PARM2 = 'HLO1 : 2.02 VLO1 : 1.01 VDD1 : 23.03' HIERARCH ESO DET PARM3 = 'HHI1 : 15.00 VHI1 : 12.01 VDR1 : 13.98' HIERARCH ESO DET PARM4 = 'HLO2 : 2.02 RLO1 : 1.01 VGS1 : 4.99' HIERARCH ESO DET PARM5 = 'HHI2 : 15.03 RHI1 : 10.07 ICCD1 : 0.00' HIERARCH ESO DET PARM6 = 'TL 1, 5 telem. data' HIERARCH ESO DET DATE = 1.989794555664E+03 HIERARCH ESO DET MODE = 'SLOW ' HIERARCH ESO DET GAIN = 1 HIERARCH ESO DET AD_VALUE = 2.100000000000E+00 HIERARCH ESO DET DIT = 4.000000000000E+02 HIERARCH ESO DET SHUT TMOPEN = 5.000000000000E-01 HIERARCH ESO DET SHUT TMCLOS = 5.000000000000E-01 HISTORY ESO-DESCRIPTORS START ................ HISTORY 'WIND_RAW' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.9000000E+01 3.0000000E+00 1.0420000E+03 1.0260000E+03 HISTORY HISTORY 'STAT_RAW' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 6.5800000E+02 3.2767000E+04 2.3813201E+03 5.6562799E+02 2.4699001E+10 HISTORY 3.8941301E+14 2.4969999E+09 2.3490701E+03 2.3460000E+03 2.0070000E+03 HISTORY 1.6000000E+01 6.5800000E+02 3.2767000E+04 HISTORY HISTORY 'WIND_OVER' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.0000000E+01 1.0290000E+03 1.0550000E+03 1.0390000E+03 HISTORY HISTORY 'STAT_OVER' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 2.1200000E+02 2.4400000E+02 2.2111700E+02 2.5815699E+00 1.0815500E+07 HISTORY 2.3924700E+09 2.5441800E+06 2.2058000E+02 2.2050000E+02 3.3000000E+01 HISTORY 1.0000000E+00 2.1200000E+02 2.4400000E+02 HISTORY HISTORY 'BIAS_FRAME' ,'C*1 ' , 1, 7,'7A1',' ',' ' HISTORY bias50 HISTORY HISTORY 'BIAS_OVER_DIFF' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 1.5100101E-01 HISTORY HISTORY 'FLAT_WIND' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 4.5000000E+02 3.8000000E+02 7.4000000E+02 6.2000000E+02 HISTORY HISTORY 'FLAT_BKG' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 2.1311699E+03 HISTORY HISTORY 'SKIM_FRAC' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 3.5154400E-04 HISTORY HISTORY 'AV_WIND_NAME' ,'C*1 ' , 1, 5,'5A1',' ',' ' HISTORY fRc50 HISTORY HISTORY 'FLAT_FRAME' ,'C*1 ' , 1, 5,'5A1',' ',' ' HISTORY fRc50 HISTORY HISTORY 'WIND_FIN' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.9000000E+01 3.0000000E+00 1.0420000E+03 1.0260000E+03 HISTORY HISTORY 'STAT_FIN' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 6.0423798E+02 3.2842602E+04 2.1606499E+03 5.5936798E+02 2.0734501E+10 HISTORY 3.5516501E+14 2.2656100E+09 2.1273799E+03 2.1162400E+03 2.0150000E+03 HISTORY 1.6000000E+01 6.0423798E+02 3.2842602E+04 HISTORY HISTORY 'WIND_SUM' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.0000000E+00 1.0000000E+00 1.0240000E+03 1.0240000E+03 HISTORY HISTORY 'STAT_SUM' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 3.7136699E+03 9.8528203E+04 6.9033799E+03 1.6677500E+03 6.1352398E+11 HISTORY 2.8897399E+16 7.2387098E+09 6.8047002E+03 6.7938701E+03 2.0480000E+03 HISTORY 4.6318802E+01 3.7136699E+03 9.8528203E+04 HISTORY HISTORY 'LHCUTS' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 5.5000000E+03 9.0000000E+03 3.7136670E+03 9.8528234E+04 HISTORY HISTORY 'DISPLAY_DATA' ,'I*4 ' , 1, 9,'7I10',' ',' ' HISTORY 2 2 513 513 0 -1 -1 HISTORY -1 -1 HISTORY HISTORY 'BOX_MIN' ,'R*4 ' , 1, 6,'5E14.7',' ',' ' HISTORY 3.2100000E+02 2.1500000E+02 6.9644336E+03 6.3300000E+02 4.2300000E+02 HISTORY 6.8900532E+03 HISTORY HISTORY 'IJBORDER' ,'I*4 ' , 1, 4,'7I10',' ',' ' HISTORY 1 1 1024 1024 HISTORY HISTORY 'LHCUT' ,'R*4 ' , 1, 2,'5E14.7',' ',' ' HISTORY 3.6236699E+03 8.0148297E+04 HISTORY HISTORY 'ZEROMAGN' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 2.4671000E+01 HISTORY HISTORY 'SEEING' ,'R*4 ' , 1, 2,'5E14.7',' ',' ' HISTORY 1.8308023E+00 9.6358800E-01 HISTORY HISTORY 'PAIRSPRT' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 3.1899800E+00 HISTORY HISTORY 'MULTDTCT' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 4.1900001E+00 HISTORY HISTORY 'PRFLCTRL' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY -5 HISTORY HISTORY 'OUPROFIL' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 5 HISTORY HISTORY 'STMETRIC' ,'R*4 ' , 1, 2,'5E14.7',' ',' ' HISTORY 9.3000001E-01 5.5799999E+00 HISTORY HISTORY 'BRGHTLMT' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 1.8387699E+01 HISTORY HISTORY 'NBSTARS' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 17 HISTORY HISTORY 'PSFTAB' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 1 HISTORY HISTORY 'THRESHOLD' ,'R*4 ' , 1, 5,'5E14.7',' ',' ' HISTORY 6.8047002E+03 1.1384800E+02 1.6730800E+00 2.0000000E+00 2.5446301E+01 HISTORY HISTORY 'N_SEARCH_ANA' ,'I*4 ' , 1, 2,'7I10',' ',' ' HISTORY 822 806 HISTORY HISTORY 'N_STAR_GAL_DEF' ,'I*4 ' , 1, 3,'7I10',' ',' ' HISTORY 46 744 16 HISTORY HISTORY 'HIST_BINS' ,'R*4 ' , 1, 5,'5E14.7',' ',' ' HISTORY 2.5600000E+02 2.8824686E+02 3.7136670E+03 7.7216609E+04 0.0000000E+00 HISTORY HISTORY 'HISTOGRAM' ,'I*4 ' , 1, 256,'7I10',' ',' ' HISTORY 1 0 0 0 0 0 0 HISTORY 0 0 0 10 64 23 12 HISTORY 3 3 4 4 3 1 2 HISTORY 0 0 1 1 0 1 0 HISTORY 0 0 0 3 0 1 0 HISTORY 0 1 0 1 0 1 0 HISTORY 0 0 1 1 0 1 0 HISTORY 1 0 0 0 0 0 0 HISTORY 0 0 1 1 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 1 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 1 0 1 0 0 1 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 1 0 0 0 0 0 0 HISTORY 0 0 0 0 0 1 0 HISTORY 0 0 0 0 0 1 0 HISTORY 0 0 0 0 1 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 0 0 0 0 1 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 1 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 1 0 0 0 0 HISTORY 0 0 1 0 HISTORY HISTORY 'STATISTIC' ,'R*4 ' , 1, 11,'5E14.7',' ',' ' HISTORY 3.7136670E+03 9.8528234E+04 6.9033760E+03 1.6677493E+03 6.1352378E+11 HISTORY 2.8897433E+16 7.2387144E+09 6.5048496E+03 3.8995779E+03 2.5600000E+02 HISTORY 3.7182184E+02 HISTORY HISTORY 'WINDOW_FROM' ,'I*4 ' , 1, 2,'7I10',' ',' ' HISTORY 1 1 HISTORY HISTORY 'WINDOW_TO' ,'I*4 ' , 1, 2,'7I10',' ',' ' HISTORY 1024 1024 HISTORY HISTORY 'NBMODIF' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 1 HISTORY HISTORY 'STARS' ,'R*4 ' , 1, 51,'5E14.7',' ',' ' HISTORY 2.6300000E+02 8.8700000E+02 4.6759199E+04 7.5000000E+01 5.6300000E+02 HISTORY 1.5854400E+04 1.3000000E+01 3.1300000E+02 4.9727699E+04 3.3900000E+02 HISTORY 4.3300000E+02 9.6787102E+04 7.0100000E+02 1.6300000E+02 1.2378200E+04 HISTORY 8.5500000E+02 2.5500000E+02 3.5242898E+04 7.6100000E+02 3.3300000E+02 HISTORY 1.4904300E+04 1.0110000E+03 3.5700000E+02 2.5686801E+04 9.0700000E+02 HISTORY 4.0100000E+02 1.6969100E+04 8.4900000E+02 5.2500000E+02 1.4543700E+04 HISTORY 9.1700000E+02 5.4500000E+02 4.4644398E+04 7.7700000E+02 5.7700000E+02 HISTORY 3.6737199E+04 1.0010000E+03 6.9500000E+02 9.8214500E+04 8.2500000E+02 HISTORY 8.0100000E+02 2.0127900E+04 6.3100000E+02 6.3500000E+02 1.6520199E+04 HISTORY 5.8500000E+02 6.7500000E+02 1.5727300E+04 6.5900000E+02 6.6500000E+02 HISTORY 2.1833900E+04 HISTORY HISTORY 'DPROFILE' ,'R*4 ' , 1, 25,'5E14.7',' ',' ' HISTORY 3.2567519E-01 6.4562768E-01 6.5725815E-01 5.2960014E-01 4.1916752E-01 HISTORY 3.0000001E-01 2.8000000E-01 2.5999999E-01 2.3999999E-01 2.0000000E-01 HISTORY 1.8000001E-01 1.6000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 HISTORY 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 HISTORY 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 HISTORY HISTORY ESO-DESCRIPTORS END ................ END BTBB'BBjB2BB BBEBԁBB5B̬B4BBtB*BBBBBuBpBrB|BBBBBBB6BUBuBBBBBBBBBBB\B BB~BBB}BzxBwBuBr,Bo=Bl6BiBeBbB_#B[BWBT3BPRBLPBH0BCB?B:B6QB1~B,B'fB"BBBKB XB:BBrBBBBܟB+B̈́BŧBBIBB BBBBMBuBkBaBWBM:BBB7B,B!DBB B'BBBJB̡BBBB4BB|BoBaBRBDB6B'pBB BBB-B̺B&BsBBB}BmB]B}B|B| B|6B|bB|[B|5B|B{B{DB{vB{xB{RB{-B{PBzBzBzBzp]BzJBz$ByPBy٬By ByrByhByCQByBxLBxBxbBxBxbBx=?BxBwB߲B,BBsBAB(B(B@BoBôBB}BBB8BBBBjBXBRBXBgB~BBBB%B\BBBBMBBBB7BiBBBBBB B~B{ByBwBunBs$BpBn^BkBiNBfBcBaB^4B[4BXBTBQBN0BJBGBCDB?bB;`B7B0B"lBBB BBBȠB4BBB9BzUBjUBZ;BJB9B)PBB:BBBBB BBBBoaB^BLB;@B)B>BBBsBB4BBBByMBgBUBCB1BB BBBBBBB}B}PBkBXBFB4^B"BBmBBزBLBBsBB|Bj BWBEB2BB fBB|BKBB`B;BNB~B~˰B~\B~B~[B~6HB~B}B}B}B}{DB}UB}0hB} B|B|B|B|u7B|OB|*VB|B{{B{B{B{o>B{IB{$uBzBzٻBzcBz BziBzDrBz(ByByԫBytBy@ByeBy?ByBxBxЮBxBxBxaBxB9B6B2SB.pB*kB&EB!BBB@B`B YB(BBHBBBBvB BsBΩBǬB|BBBBBnBBGB[Bv]BmLBcBZyBPBFBBJBnBBBnBBB3BBBBBBBBB*BlBB B~gB|B{3ByBxBvBuBs{BqBpoBnBm\BkBj=BhBg BeeBcBbB`FB^|B\BZBXBVBTBRBP~BN=BKBIBGBDoBAB?B<&B92B6"B2B/B,JB(B%#B!`B{BtBKBB BB2BKB:BBBBQBgBOBBʑBBBBBHBBBBKB~BuBmBd,B[BQBHB>*B4B)B`BB BBnBBFBiB]B"BB"B`BrBxZBkB]BPBBZB4xB&pBBB BzBB(BLBPB4BBB-BsBcBT%BDCB4HB$4BBBnBB~BBABBB~BmB\BKB:B)BBSBBBӍBCBBB3B|BkVBYBHYB6B%>BBB`B޲BBBBBBBtBb@BP`B>|B,BBBBBҲBBBBvBx]Bf@BTBAB/BB xBB"BB>B`BB}`B};B}NB|B|B|ZB|B|`B|;jB|B{$B{ͅB{B{JB{_B{;B{BzBzoBzBzdBz_Bz;jBzByByByByZByaByYBjB.BB.BBB?B(BBBnB BB}BlB[BK3B:xB)BBBB2BMB_BiBkBeBWBoBB^&BMB;B*BkB+BBBCBBB"BB}DBkBZPBHB7EB%B&BBBUBͱBB[BBBu=BcBQB?B.8BnB BBBXBBbB?BBB~B~B~@B~vB~hB~DB~! B}:B}fB}B}B}mB}J B}&0B}XB|B|B|B|rB|O"B|+MB||B{B{B{B{xHB{TB{0B{ BzFBzŐBzBz~0BzZBz6BzBByByByByByaBy>ByBx4BxBxyBuJBrdBoBlBjRBgBetBc(B`B^B\BZBXBWBU_BSBRBP}BNBMBLBJBIZBH BFBEBDHBCBAB@B?B>^B=4B< B:B9B8B7JB6B4B3B28B0B/B.B,B+B)B'B&3B$sB"B BBBBjBBB?BB B .BHBBB BB|BBTBBBB\BB|BBBBB|BBGBfBWBBBB'BBBy_BqBiBaBYLBPBHTB?B6B-eB#BXBBsB0BBB7B+BBBBB$BB~Br5BeBXBKB>B1fB#BhBBBB޼BzBBBB9B]BxdBiPBZ BJB;sB+BdB BB"B6B8B%BBBB|.BkB[UBJB:FB)BBXBBB0BrBBBB%Bq@B`SBO_B>dB-aBXB HB2BBBBBeB*BBpB_YBNBB{ BzBzQBz Bz|BzYBz6VBz#ByByByByBycBy@|ByxBx}Bx׉B_kB\BYBWjBTBRBPWBN,BLBJBH.BFWBDBBBACB?B>2BB6HB-rB$cBBBBBBBB[BtB]BBBB,B.BxBkB_4BRBEB8B+BdBBmBBBBBBIBB>BBtBeBVBGB8xB)'BB @BBBBBoBBBBoB{EBkBZBJuB:B)B3BB)BBBƆBBNBBBsBBbBQB@B0$BLBmBBB۪BʲBBBBBuBdlBSNBB+B1BBBnB4BBɲBkB!BBBs+BaBPvB?B-BPB BB"BDBaBg{BDB!B~B~ۼB~B~B~rB~OB~,B~ B}B}B}B}}B}ZB}7B}B|B|ΒB|B|B|eB|BB|B{B{ُB{B{B{pB{MB{*B{BzBz.BzWBz|BzYBz6Bz$ByfByήByByPByfByDBy!{BxBI]BFBD-BAB?kB=0B;B9B7B50B3fB1B0 B.|B,B+B*,B(B'B&\B%/B$ B"B!B BBBBBBB1BGB\BpBBBBBBBBkBIB B B B LBB|BBjBBBHBjBvBjBHB BBLBBBYBxBxBYBB׷B2BЊB̾BBĴBuBB}BBBBB#BBBBB=ByBrBkBdB]WBUBMBEB=B5iB,B$=BQB/BBGBBBaBBrBBBBPBB)B}RBqPBe$BXBLNB?B2B%BB B BBBB2B#BBB>BBqBbTBSzBDB5zB&TBBB[BBJBɤBB!BEBZBz^BjSBZ;BJB9B)B`B BBYBBǟB6BBOBBuJBdBT*BCB2B"GBBB*BjBΤBBB0BTBzsBiBXBGB6B%BBBBBНBBsBXB:B{BiBXBGB6sB%BBBBBBBTB{BYUB6BIB~B~.B~B~ B~gvB~DB~"GB}B}B}uB}B}u;B}RB}0B} eB|B|.B|B|B|`cB|=B|BnBh2Ba\BZQBSBKBCB;B3B+B#BB/B 2BBBB#BBB{BBBBBBBvjBjB^BR\BFB9B,B BBBBjBBFBBBBwB7B{BmaB^BPBAVB2uB#|BkBDBBBPBBKBBBABytBiBYBIB9B)BB kB@BBBȹBB@BBBwVBfBVBF.B5B%HBBIBB2BҞBBfBBBhBnB]BM>B<}B+BB BHBqBזBƷBBBBBr&Ba3BPB(BwBiB[@BLB> B/lB BBBBBRBBB8BB(BxBhBYBIXB9B)BB BBBBBBBBByfBi:BY BHB8B(NBBB]BB֟B9BB[BBiBsBcdBRBBKB1B!!BBBCBޜBBCBBB#BzhBiBXBH$B7]B&BBBTBưBB[BaB?BCB~B~B~B~UB~uB~SB~2B~JB}B}̿B}B}2B}glB}EB}#B}B|WB|B|B|{B|YZB|7B|B{2B{B{B{#B{mzB{KB{*7B{BzBzpBzBzZBz`Bz?ZBzByrByByByHByvB,BBBBBB6BBBBBBBXB:B,B.B=BZBBBB?BBBIBBBBBoBB[BBFBB'BߑBBWBݰBBJBۈBڽBBBBBBBӹByB%BϾBBB̲B BLBtBŅBzBVBBB:BBB BBBBNBBB=B>BBBKBBBzBuBpEBjBdB_BXBRBLBEBB>KB7B/B(B ]BB}B9BB B BBۭB&BmBBdBBBBB BsBhuB\BQ6BEWB9PB-!B BPBBBBBBxBBxBBBBt BeBWBIVB:B,\BBB6BSB\BPB2BBBnB BwBhBXBHB9SB)BB 'B[BBBBB>BXBkB{xBkB[BKxB;lB+YBAB #BBBڨBtB;BBBpBy$BhBX|BH"B7B'aBBB BB8BľBABB>BBr.BaBQB@B/BYBBLBBBBwTBV B4BxB~)B~B~B~1B~lB~KB~*-B~B}zB}!B}B}mB}bB}@B}cB| B|ܷB|bB|B|xB|WrB|6$B|B{B{QB{B{B{nB{MhB{,7B{ BzBzBzBzBzexBzDlBz#fBzfBylByzByBxBXBVBnBBBMBBXBB޸B݇BhBZB^BqBؓBBBLBաBBjBBVBB]BByB BСB7BBeBB΍BBͨB/B̰B*B˜BBeBɻBBCBsBƕBŨBĬBÞBBNBBB>BBBfBBBBBRBBBB3BZB_BABBB BXB|BxBKB|BxqBsBnBiBdB_9BYBSBMBGBA>B:B3B,B%BB{BBBBoBBB$BBɖBB=BHB BBEBBwBlBamBV BJ~B>B2B&BBfBBSBB۲BήBBDBBZBB}Bp Bb*BTBEB7B)LBB MBBB-BOB^B\BIB%BBvBg`BXBHB9%B)BB BBTBۺBBrBBBTB}BmB]BN'B>MB.mBBBBB޹BθBBBBB~kBnNB^,BNB=B-B{B EB BB܌BHBBBhBBzBjmBZBIB9[B(BB4BBBB BlFBKiB*B B~B~B~B~B~e%B~D:B~#NB~bB}uB}B}B}~B}]B}BCBBB B9B2BBBBBBBB{BpMBehBZXBOBCB8-B,xB BBpB"BBBdBɊBBuB;BBlByBl*B^`BPzBB|B4dB&5BB BBBBHBBBBBBuBfBWsBH8B8B)BKB BBBܬBBGB3BBB=BBBB}#BzBvBsPBoBlBhBd B_B[kBVBRBM(BH BBB=8B7B1B+B%4BBBB BB'BBBBhBBCBbBNBBBBBB}BsoBhB^#BSBBBtBeBVHBGB7B(rB!B BoBB۩B@BB_BBlB~BojB_BPXB@B17B!BBlBB)BӃBB/BBBBufBeBUBF8B6zB&BB4BBQBB.BpBQB1jBB~3B~ҖB~B~XB~sB~TB~4vB~B}2B}ՓB}B}RB}vB}WB}7zB}B|HB|ذB|B|B|yB|ZlB|:B|{B{VB{B{aB{}B{^~B{?B{B{IBzBzBzDBzBzcBzDsBBBB6BBBgBTBVBoBBB6BBBB=BBBbB2B BBBBBBBBB+BFBbB~BBBBBBBBBBBBBBCBBB>BBBBBBBBqB~B}B|xB{MBzBxBw1BuBsBrBp2Bn(BkBiBgBBdBaB_&B\(BYBUBRFBNBJBFBBB>B:B5qB0B+B&bB B`BBB WBBBBcBgBNBBuBеBȿBB4BBBBBbBBx Bn:Bd'BYBO}BDB:'B/>B$-BB BBcBBޡBҌBTBBBB2B]BzjBm[B`1BRBEB8B*BBBGB^B`BMB)BBBTBBuBrBd`BUBGB8fB)BB BB|B|B{B{|B{tB{sB{evB{F|B{'B{BzBzBzBzBznBB{BzvBy BwBvBuBtBsBs*Br{BqBqXBpBpBp,BoBoBoBosBofBodBokBo|BoBoBoBpBpABpxBpBpBq-BqkBqBqBr BrVBrBrBrBsBsBs-Bs5Bs2Bs%Bs BrBrBrlBrBqBq@BpBpBonBnBmBlBkBjBixBh"BfBe$BczBaB_B]B[BYPBVBTTBQBNBKBHBEPBAB>8B:lB6uB2PB-B)B$BBBB.B BBBPBBBDBQB&BB+BZBVBBBBCBBBByBpBfaB\vBR`BHB=B3B(ZBsBdB.BBRBBBBBBsBBzBBv Bi)B\*BOBAB4B'2BB &BBBBBBBBBBUBrBcBU2BFB88B)BB wBB/BBB1B|BBB:BynBjB[BLB> B/(B >BPB\BeBiBiBeB\BOB>B*B{BkB\BMB>B/cB 6BBBBfB*BBBiB$BBxBiGBYBJB;YB,BB \B BXBBB7Bb~BCB%BIB~B~B~ B~IB~lB~MB~/B~DB}B}B}B}GB}vB}WB}9B}`B|B|B|FB|B|B|bCB|CB|$B|ZB{B{)B{B{B{m|B{NB{0vB{BzBzBzBz@BdqBc$BaB`B_B^B^&B]nB\B\@B[B[bB[BZBZBZ}BZkBZgBZoBZBZBZB[B[>B[B[B\B\pB\B]&B]B]B^DB^B_B__B_B` B`]B`B`Ba'BaZBaBaBaBaBaBaBaBaYBaB`B``B_B_[B^B^B]4B\NB[PBZ8BYBWBVNBTBS!BQ]BOzBMuBKPBIBFBD BAVB>{B;yB8OB4B1B-B*B& B!BBBCBYB >BBpBBBBVBBBKBFB BBBBBBCBBBzBq~BhB^BTBJB@B6tB,B!qBB BBB:BB#BdBBB^BBB~ABqBdBX!BK5B>0B1B#BB -BB(BBB B3BJBQBIB2BqBbBTBFZB8 B)BIB BjBBBBđBBBBeB{Bm/B^BOBA:B2B#BB\BBBB6BcBBBBBr Bc!BT4BEDB6QB'[BbB fBgBfBaBZBQBEB8B(BBsBcBTBEB6B'BfB GBNB BB~B{4B\B>B RBB~B~eB~B~B~juB~L$B~-B~B}4B}B}B}NB}xB}YB};tB}.B|B|B|lB|0B|B|gB|IB|+`B| 4B{ B{B{B{B{vB{XB{:vB{nBzjBzlBztBLBKBJBIBHBHBGgBFBFTBEBEBESBE#BEBDBDBE BE'BERBEBEBFBFmBFBG1BGBHBHBIBIBJBJBKBKBL BLBMBMzBMBNYBNBOBOsBOBPBP9BPdBPBPBPBPBPgBP7BOBOBO5BNBN#BMxBLBKBJBIBHBGeBFBDBBBA!B?@B=?B;B8B6hB3B1!B.DB+?B(B$B!9BBBBzB BBBBBLBBBBBiBB:B[BEBBwBBBBiBB{5BrTBiCB`BVBLBC:B9JB//B$BBB0BNBHBBB[BBB;BEB0BByBm?B`BTBGTB:|B-B BeB1BBBBАBBPBBBB~BpBbBTBEB7B)B~B DBBBB=BBBMBBB~.BoBaVBRBDkB5B'nBB ^BB>BިBBqBB*BBBx&BisBZBLB=FB.BBB8BnBBBB,BVB~BB|BmB_ BP*BAGB2bB#|BBBBϴBBBv-BXRB:vBB~B~B~B~ B~@B~ibB~KB~-B~B}B} B}3B}ZB}zB}\B}>B}!B}4B|fB|ǜB|B|B|nKB|PB|2B|B{cB{ٴB{B{`B{B{cB{EB{'B{ ^BzB56B4/B3CB2rB1B1B0B0"B/B/B/MB/.B/ B/%B/:B/^B/B/B0B0xB0B1LB1B2EB2B3\B3B4B5(B5B6lB7B7B8ZB8B9B:;B:B;jB;BMB>B>B?6B?hB?B?B?B?B?xB?FB?B>B>3B=B= BB7BuBhB\vBOBCoB6B*B)B9B2BBBۤBNBBlBBJBB|Bo*BaZBSBEB7B)BB BBBBnBVB9BBBBBr\Bd!BUBGB9WB+ BBfB BBPBBƄBBB6BB~GBoBaKBRBDDB5B'0BB BBBRBϸBB~BB;BBwBiJBZBKB=KB.BB@BBBVBBBrBTB7IBB~pB~B~B~(B~B~iNB~KB~.tB~ B}B}7B}B}hB}~B}`B}C>B}%B}B|)B|B||B|*B|uB|XB|;HB|B|B{B{OB{B{B{nB{QB{4{B{]BtBBBBB BBXB!BBBBB/BfBBBgBBTBBmBBBVBBB |B!B9B+TBBeBBBBBBo BRB5BB~#B~(B~-B~1B~6B~jB5B,NB"B=BwBBtB8BBPBѥBBBBBPBBOBwBkB_BSBGB;B/PB"BlB B.BqBBֺBBBBwB?BBzBmBB_BR^BDB7OB)B B|BB*BBB!BjBBB)B_BwBiB[BNB@1B2OB$iB~BBBB޲BжB·BBBBB|BnzB`fBRNBD6B6B'BB BBhB>BBBBBQBB}BoBauBS;BDB6B(BFB BBB…BBzBlBPlB3B[B~B~JB~B~9B~B~l)B~OB~3B~B}B}ݒB}B}B}B}kB}OB}2B}2B|B|RB|B||B|B|kB|ORB|2B|B{JB{B{B{jB{(B{lBBBB8BBBBBBBBGBBBBBB`BBBB~B^BHB7B/B,B-B3B;BFBSB_BlBwBBBBBzBjBTB4B BB B RB B B $B B B lB B BB BB B B {B B B B DB pB BqBBBBBB>BfBjBHBBBB8BMB7BBBB&B.BBЬB!BdBsBMBBaBBBB]BB2BLB3BwBphBhB`BXBPBHB?{B6B-B$BUBBFBBBBOBBuBBB(B"BBB~SBrBg5B[{BOBCB7B+BYB BB*BBBCB{BBBBBBy~BlNB_BQBD{B7!B)BUBBnBBBBˈBB|BB^BBz0BlB^BQLBCB5B(DBB BB]BBB BABrBBBBuBg=BY]BK{B=B/B!BBBB BB$B,B4B9B>B@BzABlAB^@BP=BB9B44B&/B)B "B3B"BBBBkBOB3BB~~B~hB~RB~=B~(B~oB~SB~6B~B}B}B}ƲB}B}B}rB}VB}:B}B}B|B|ʞB|B|B|vB|ZB|>B|#B|5B{YB{ςB{B{BBKBBԮBԄBtBzBԗBBBkBBZBB׌BBԡBBBBvBBPBvBkB/BBBHB>BBBB*B4BByBsBlFBeIB^BVBO*BGjB?|B7_B/B&BB2B B7BBBۦBPBBoBBMBBBw1BjcB]BPBCB6B)BBBBBBrBZB=BBBBBrBr>BeBWBJB=JB0B"BoBBBwBBBeBBB:BBeBtBgBZBLB?)B1B$6BB :BB6BB-BŦBBBB{BBt^BfBY=BKB>B0B"B[BB`B3BBBBlyBQJB6BB~B~B~^B~2B~B~wB~\B~AB~&[B~ 3B} B}B}B}B}B}hnB}MVB}2>B}+B|B| B|B|B|B|tB|YB|>B|$B| B{%BByBfBlBBBBvBB~B!BBBtB\BTBYBlBBBB/ByBB$BBBTBB4BBB’BB|BB\BB,B̋BB7BЁBBB$BDBWB]BTBB6B.B&BBB xBBBBVBBZB̥BBBBnB BBBz*BoLBdSBY=BN BBB7\B+B HBBBBBBBBBTBBBBBv BimB\BPBC[B6B)BB"BDBgBBܨBBBBB BBBuBhB[BNB@B3B&BB BBjBHB#BBBBvBEBB{BnBahBT+BFB9B,jB%BBBNBBܶBgBBBtB!BBxBr!BdBWqBJBpB39B'BBBpBBB6BQBZBRB9BBBBBBtBhxB\BOBBB6kB)B3BBB9BBB/B{BBBEBBBwBk#B^QBQ~BDB7B*BB-BGB_BtB݆BЖBãBBBBBBuBhB[BNBAB4B'BB yBiBVBCB.BBBBBBB}yBp[BcBZBOBE B:B/B#BB lBBBBYBӤBBBB%BB BBsBgB[?BNBBB6B~%B~ VB}B}B}B}PB}B}pB}W B}=lB}#B} B|\B|ִB| B|hB|B|p.B]0B]pB]B^=B^B_lB`&B`BaBbBcBeBf8Bg{BhBj0BkBmBnBp=BqBsBuB?B9TB2B+B$BABB%BVB[B6BBrBBB&BBBBBvBBB~BtBjB`5BUBK5B@B5B*BBB BBPBB}BB`BBB9BdBB~BrBfBZzBN^BB;B6B)BBdBBBBQBBǺBiBBBdBB}BqDBdBXuBL B?B3*B&BAB BMBBPBBJBB;BB$BBBwtBjB^JBQBEB8B+BFBBBfBB B{BB.BBB3BBzBn2BaBTBH*B;|B.B"BoBB!BBbBBByBB_BFB-'BB~kB~B~ǴB~[B~B~{B~bTB~HB~/B~XB}B}B}nB}&B}B}~B}eVB}LB}2B}B}dB|1B|B|B|BDBEbBEBFxBG(BGBHBIBJBKBMBN`BOBQBRBTBUBWMBXBZB\xB^FB`BaBcBeBgBiBkBmBoBqBsBuBwByB{B}BBBpBOB&BBBqBBBTBBPBB BPBBBBB|BDBBB BnBBBBBBmBBtBBBBBB:BBBBBB}BB9BRB=B~B{BwBsBoBkBg:BbB]BXBSBN"BHBBBB9B3+B-B&B uBBB BBB"B|BB޲B֑BHBBEBBBBBHBB}`BsBiB`BV BLBAB7B-"B"BB `BBBBBB˜BeBBB`BBjB{BpCBdBXBM;BAzB5B)BB:B\BBBBBBB(B:BIBVB`BwhBkmB_pBSpBGnB;iB/bB#ZBNB AB2B B BBBBBBqBRB0Bz BmBaBUBIrB=HB1B$BB BcB3BBBϚBeB0BBBBSBzBmBaBUnBI3BB@BCBEZBGBIBL1BNzBPBSBUGBWBYB[B^B`EBbcBdwBfBhBjwBl`Bn:BpBqBssBuBvBxBy{BzB| B}2B~BB;BBBB"BBB.BLBJB)BBBBOBBB~qB}0B{Bz4BxyBvBtBrEBoBmBBj|BgBd^BaB]}BYBUBQBMNBHBDB?8B:B4B/RB)B#BBcBB NBBB[BBBBBBBBSBBB@BIB1BBwBn*BdBZBQBG*B=%B3B(B}BB BBXBBBBBBBBrB/BBzBoBcBX-BLBAB5B)BJBBBQBBBMB̜BB1BxBBB=BzzBnBbBW#BKVB?B3B'BB;BbBBBBB B*BFB_BxBBBuBiB]BQBEB:B.B" B*B 4BeB2eB&cBbB`B`BBԺBBBBtB\BDB,BB~B~B~̿B~B~B~B~lB~TB~QB9B5 B0B*B%B BYBmBQBBBBBBBޚBByBǬBBBbBByBBBB{ BqBhB_.BUBLBBKB8sB.B$yBVBBBfBB\BۺBB?BhBBBBsBTBy(BmBbBWgBLB@B5XB)BBBB#BB5BٹB=B¼B:BB.BBB}BqBfjBZBO@BCB8B,rB B5B BBLBBBTBèBBNBBB:B}BqBfBZfBNBBB7:B+~BBBFBBBBFB̈́BBB;BwBBB{(BobBcBWBLB@HB4B(BB+BdB;BۭBBBB}yBeBNbB6BOBB~>B~طB~4B~B~,B~zB~c.B~KB~42B~B~@B}B}TB}B}pB}B}xB}a-B}IBB BBGBBBPBBpBBBBBBBBBB4B|BB (B B BnBBhBBtBBB"B$B';B)B,SB.B1`B3B6ZB8B;:B=B?BBMBDBFBIBK!BM6BO;BQ0BSBTBVBXXBYB[xB\B^@B_B`BaBbBcBdMBdBevBeBf&BfOBfWBf>BfBeBeBdvBcBbBaB`QB^B]KB[BYBW|BU2BRBPBMB}uIBBB2BπBBcBBաB^B0BB BB/BXBBB)BBBhBBoBBB3BB~B*BB B;BBBPBBBRB B#B&*B(B+AB-B06B2B5B7RB9B;B=B@BBBDBEBGBIBK1BLBNBBOBPBR*BSEBTEBU*BUBVBW)BWBWBXBXBXBWBWpBVBVEBUvBTBSaBRBPBO BMBBKMBI+BFBD[BAB>B;B8vB4B1RB-rB)eB%,B BBFB=B BBB1B8BBB=BܒBռBμBǔBCBB.BjBBvBFBBBwBo9BffB]uBTfBK:BAB8B/B%BB B-B:B2BBBաBKBBmBBPBBB@BvvBkB`BUBJB?B4B)BBBBBBBܔB~BgBMB2BBBBBxBmfBb=BWBKB@B5B*[B)BBBBRBBBФBgB*BBBhB&BBvBkXB`BTBIB>8B2B'BYB BBsB%BB؇B8BBBFBBBRB~BrBg\B\ BPBEcB:B.B#jBB BrB@B՛BBUBB{BdnBMB7-B B B~SB~ܶB~B~B~B~TB~kB~U+B~>B~(B~zB}B}aB}B}PB}BBBLBBIBBBpBQBGBPBkBȘBB"B}BB\BBmBBިBTBBBBHBBBBB^B2BBBB|B HBBBBGB?BADBBBCBEBF BFBGBHxBI BIBIBJBJBIBIBIiBHBH>BGmBFtBETBDBBB@B?#B=(B;B8B6 B3gB0}B-`B*B&B"BBBBB nBB}B9BB#BSBUB*BBQBͤBBBB^BBQBBBBBz@BqBiPB`BWBOBFBBBBBBڮBݠBBBB}BvBmBbBTBBB+BBBBB XB BBlBBBBBB 2B"qB$B&B(B*B,B.PB/B1B3B4wB5B6B8B8B9B:B;B;B;B<BB3B)BPBBBB0BdBݘBBB-B^BBBBB|ABqlBfB[BPBFB;:B0aB%BBBBBBBeBىBάBBBB6BXBzBBwBlBaBW BLABAcB6B+B BB B,BBB&BlBB}BhABRBB4tB* BB'B BBOBEB:aB/B% BBBB6jB-B%*BbBB B~BZB BBpBBuBB4B}BBBBB{BqBgB\BRBHB>yB4FB*BBB PB BBBABBͲBjB BBB;BBB{MBpBfB\VBRBGB=VB2B(BMBB B=BBB%BBhBBBFBBBBBxWBmBcBY(BNBD[B9B/B%&BBUBBBBBFBBrBBB3BB]BB~BtBiB_FBTBJqB@B5B+0B B\B BBB&BBBB1BBNBBBdBBBBBnB$B B @B B BBBBBgBBGBBBBNBBfBBBBB BB B BBBB1BBBBEBB#BFB6BB݁BB B BBāBBGBjBdB5BB`BBBB~BwBpdBhBaRBYBQBIBAB9B1B4B*B BB BBBBB٘BτBpBZBCB,BBBB~BtBjB`nBVOBL/BBB7B-B#BBdB@BBBBܨBҀBXB0BBBBB\B1BwBlBbBX~BNPBD#B9B/B%BhB9B BBBxBHBBBBBTB"BBBBx]Bn,BcBYBOBEgB;6B1B&BBsBCB&BBgB BBLBBmBY8BDB0B&BB~vB~ B~B~uB~B~B~yyB;\B=QB?`BABCBFBHBKBMBPDBSBUBXB[B^BaBdBgBkBnVBqBtBxLB{BBBByBBxBBBBB BB BBBiBB6BBB,BjBʞBBBBBBܵB߂B>BB{BBhBBB"B1B&BBBdBBVBBBBBB5BBBSBgBVBBB0B{BBBWBB_BBBB3BBBBBBB\BsBYB BϒBBBBBwBB:B]BXB*BB[BB~BxBqBiBbB[BSBKBDB<1B4.B,B#BBB BBAByBBުBեB̏BfB,BBB"BB,BBxBndBdB[BQFBGB=B3B*B >BeB BBBBB3BSBsBBBBBBB7BxPBniBdBZBPBFBBBBBBB3BBBSBfBSBBB$BjBBtB6BB.BdBiBkB6B.B&BBBrBBB'BBBBDBZBaBVBBBCBBBB=BB%BPBLBB۫B B=B;BB̜BB5B8B BB)BtBBBLBB_BBBB}Bw^BpBj\BcB\BUBNBGB@4B8B12B)B!BBB BBfBBB!B׌BB*B^BBBBBB^B~2BtBkBbnBYBOBF`BB4B+B"9BBBVB BBrB&BBΎBBBBB^BBBzB.BzBqBhKB^BUBLfBCB9B0B'8BBB VB BBBRBB&BBBodB\BJ:B7B%B6B޼BYBBBBBBBBhBB,BB1B BnB BBB|B!YB%?B),B-!B1B5B9 B=(BA3BE@BIOBM]BQlBUyBYB]BaBeBiBmBqmBuSBy0B}BBB>BB|BBBBDBBBBBBBBSBBuBB0BdB|BwBTBBʱB0B͌BBBBѤBNBB/BfBrBVBBҝBB5B>BBB=BʅBȝBƃB6BBBBBB-BBBB^BBfBBBBxBBzBtBoBiBbB\BV[BOBI6BBuB;B4B-zB&BBBBBWBBBBBBذBvB*BB^BBRBB BVBBzBqBiB`%BW4BN@B5-B,B#BBBBBBBBpB\BIB6B#BBBBBBBvBmBdwB[dBRQBI>B@*B7B.B$BBB BBB~BkBXBEB1BB BBBBBBBxBorBf`B]LBT9BK%BBB9B/B&BBB BBBBΦBB[B4BBsBaBOBĤBLB BBBBB*BpBB3BB>BBBBB BBBBB BBBBB!B%6B)`B-B1B5B:B>OBBBFBJBNBSBWBLaBCB:B1B(B B4BWBzBBBB B.BRBvBBBBB-BQBvBBwBnBf B]/BTTBKzBBB9B0B(B4BYB BBBBB:B_BυBƫBBBB@BfBBBBvBn BeEB\jBSBJBAB8B0$B'IBnBB BBBJBҒBB%BnBByB-BBBBBBVBªBBɍBBкBkB+BBBBBBBBB.B`BBB BdBBBRB"B&B+JB/B3B87BBBBBXBBB|B2BBBBBBiBBBBBkBBBB‘BƂBʂBΏBҩBBB8B|BBBwBB>BBBB BoBBYBB!=B%B*B.|B2B78B;B?BDBHVBLBPBTBXB\B`BdBhwBl9BoBsBwBzB}B8BnBBBBXBBB5BBBBBBBvBB_BBBBwBBBBBBBBB]B{BjB)BBB9B,BBrBBBBBCBBBBB{Bw-BrBmBhBcB^BYVBSBNB!BBB@BB>B͠BB+BXBsBB}BnBQB'B}BuBmkBeB\BT`BKBCB;B2B*-B!B6BB=BBDBBMBBWBBeBBtBBBBB#BBx9BoBgQB^BVjBMBEB=B4B,2B#BQBB rBBB%BBHBBmBBB&BBMBBvB BB{3BrBj\BaBYBQBHB@FB7B/rB'BB3B B_BBB!BBMBByBBB:BBfBBB&B~BvPBmBeyB]BTBL6BCB;_B2B*B"BB?BBcBBB0B~BBBBjBB^BBBfB8BBBB(BJByBBBMBʪBB}BBpBBzBBB)BBTBBB BB8BBLB B%LB)B./B2B6B;CB?BCBGBLBP)BT-BX"B\B_BcBgFBjBndBqBu,BxnB{B~BBBBBBrBB-B[BjBXB$BBUBBBBBBlBB6B[BUB#BB7B|BBvB+BBBBBB#BpBBxB7BB,B{dBwpBsTBo BjBfBaFB\aBWWBR'BLBG_BAB<B64B0BBB6BBBtB>BBB̶BюBgB?BBBBBhB2BBBpB !BBhBBB"B&yB*B/5B3}B7B;B?BCBGBKBOBSEBVBZjB]Ba0BdnBgBjBmBpVBsBuBxBzhB|B~BBrBBBB@BSB?BBB BPBjBVBBBB9B9B BB B8B1B~B|ByBw4Bt?BqBmBjTBfBbB^BZBVBRBM|BHBCB>B9B4zB/B)B#B"B@BAB &BBB5BBBfBޟBBBB±BBJBBB7BB8BBBx`BpBhBa-BYbBQBIBAB9B2B*1B"IB`BwB BBBBB B%BCBbBÁBBBB B.BSBzBB|BtBmBeGB]sBUBMBEB>*B6YB.B&BBBQBBBB"BWBBBB3BkBBBBOBBBB9B{tBsBkBd&B\bBTBLBEB=SB5B-B& BEBBBB8BuBBB*BfBТBBBUBBBB@ByBBB{$Bs]BkBcB\BT;BLpBDB BB>BFBJBOKBSBXQB\BaBfFBkBoBtByB~xBkBeBgBnBzBBBBBBB!B;BRBfBwBԄBًBލBBzBeBFBBBB`B BB,BBB lB$B(B- B1B5B8BB:UB5B1B,DB'PB":BBBAB BB?B]BbBLB BB܀BBχBB?B~BBBBBBBzBBB|BtBm]BeB^BW*BOBHBCtBH/BLBQBVB[B`BeBjBoBtByBBHB{BBB!B\BBB BEBzBBBB#B>BRB]B_BXBEB'BBBB,BB TBB7BBB!B&B*B. B1B5B9>BBiBhBgdBeBdhBbB`B^B\*BYBVBTBQBMBJBGBCZB?B;B7pB3.B.B*?B%B BBBB ^BBuBB BNBcB`BFBBBtBBBBGBBBBBBBByBrBkBdB]NBVBNBG~B@0B8B1B*2B"BB)B ByB"BBzB)BBيB>BBéBbBBBBQBBBBVB{BsBlBepB^9BWBOBHBAkB::B3 B+B$B~BRB&BBBBBXB2B BBBǚBvBSB0B BBBBBeBDBy$BrBjBcB\BUBNeBGEB@%B9B1B*B#BBfBFB&BBBBBB]B:BBBBBB`B9BBBBBnBxDBqBiBbBBBBBB 8BBBbBB B%5B)B.B3B8B=zBB|BGBLBQBVB\%BaaBfBkBq9BvB{B8BBBJBBBXBBBLBBBBGBsBЕBծBڼB߾BBByBFBBBKBB MBBB;B`BnB#dB'CB+ B.B2FB5B9BBCbBHBNBSuBXB^KBcBi2BnBt%ByBBBBBBqBBGBBBZBBB!BPBrBԊBٓBޏB|BZB'BBB&BBBwB BBBBB B$kB(B+B.B2B5AB8DB;(B=B@BC BEeBGBIBKBMcBOBPzBQBRBSBTBU^BUBV BVB7B0B*-B#bBBBB:BrBBB(BiB߭BB:B˄BBBmBBBfBBBrBB+B{BtBnNBgBaBZBSBMQBFB@(B9B3B,tB%BWBB>B B*BBBB BBBzBBrBBnBBjBBhBBhBBiBB|jBuBolBhBbmB[BUnBNBHpBAB;pB4B.pB'B!mBBhB BbBBZBBNBB@BٸB.B̥BBBBsBBTBBB BeBB^BBΫBrBJB5B2B@B^BBBBgBB 7BB3BB"QB'B-B36B8B>BDHBJBOBUtB[.B`BfBlZBrBwB}lBBBQBBpBBkBB;BBBBDBbBpBmBXB0BBBDBBB?B@BA5BABABABABARB@B?B>B=B<>B:B8B6B4B2B0#B-B*B'B$B!B0BBBBBB!BB$BBB9BuBBBĽBɮB΋BRBBܝB BBBB+B+BBB|BBnB BBBBB%BBB!B#B$B&B(.B)B*B+B,B-JB-B.B.4B."B-B-AB,B+B*qB)#B'B&B$.B"0B BB=BBBBB B @BB%BeBBBhB,BB`BB&BbB҆B͒BȇBfB/BBBBBBTBBB B*B>BzHBtGBn;Bh'Bb B[BUBOBIWBCB;B8TB2lB,B&B BBBBBBB#B0B;BEBNBTBsRBwB|BBfBbBsBBBBtBB\BBB'BB̛BfB;BBBBBBBBBB*B?B WB&mB,B2B8B>BDBJBPBVB\BbBhBnBt^Bz)BBBDBBhBBPBBB-BQBbB^BEBBBrBBkBBBB BBBxBBlBBBB BBBBBBBBvBB LB!uB"rB#AB#B$SB$B$B$yB$ B#nB"B!B zB#BBBBBBBBpB BBBrBBBBNBtB}BhB7BBۂBBcBͮBBBBBBBXBBBBBBHBB}BxBr0BlOBffB`uBZ}BT~BNzBHqBBeBBZtBTBNBIBC[B=B7B2B,WB&B B"BhBB B?BBBBjBBBQB֟BB=BōBB-B}BBBoBBBaBBBQB{BuBp@BjBdB_*BYwBSBNBH[BBBBcBgBlBqBvB|B\BBBB BBeBBBBB|BpBnBuBׂBݙBBBB+B[BBBB+B`B!B'B-B4 B:HB@jBFBLBRBXB^BdBjBplBv>B|BBeBBBBmBBB7BRBXBHB!BBʋBBӒBB,BPBVB>B BB>BBBBBBBCB B BB BBzBB>B]BOBBB BAB6BBpBBBBBPBBB.B$B B BByBBBBB-BB%BrBBBިBځB@BBpBB?BBBBBBBtB2BB|B BBB{lBuBpBjiBdB^BYBSEBMlBGBAB;B5B/B*B$1BLBhBB BBBB/BZBBBB%B_B̜BBBaBBB>BBB0BBB6BB|BwPBqBlBfyB`B[IBUBPBJBDB?lB9B4PB.B):B#B)BBB BBB BB BB BB B֎BB˓BBBBB"BB)BB/BB6BB:B~By=BsBn>BhBc=B]BX8BRBM1BGBB&BBBƂBB\BӟBBB߷BB-BBBeBBBaBBB BMBdBRB B B B`BtBZBBBB BBBBHBcBQB B B B[BvBhB4BBYBBBBBBxB B|BBB$B$B BBȇB"BBBhBBBBBBBBtB-BB~xBy BsBnBhBbB]VBWBR BL_BFB@B;@B5B/B*B$VBBB0B wBBBeBBBpBB2BڗBBkBBIBB2BB'BB%BB,BB>BBWB|BwyBrBlBg:BaB\oBW BQBLKBFBAB<4B6B1B,)B&B!}B)BBB 2BBBCBBBZB BBvB*BB̔BJBBBkB BBBABBB_BBByB},BwBrBm?BgBbB]JBWBRBMMBGBBB=FB7B2B-4B'B"uBBBLB4B9B>BDBIFBNBT BYB_BdBjzBp@BvB{BBBBBABpBBB5BBB=B̟BBpBBMBB-BB ByB BKBB B&cB,B2B9AB?zBEBKBQBWB]BcBiBoBupB{&BB^BBLBBBB+B*BBBB,B«BBRB{BӄBoB9BBlBBB4B/BBB=BBBBBBBzBBBB>BBBBBLBBBBBB5BBBBBBLBB(BaBzBoBEBBޔBBlBӭBBBBêBjBBB&BBB(BXBwBBBtBVB*B{BvBq`BlBfBa=B[BVSBPBKTBEB@BB:B5(B/B* B$|BBeBBOBBBBBDBBTBBpBBיB3BBmBBB\BBBbBBBB8BBBqB}3BwBrBmBhNBcB]BXBSBNYBI-BDB>B9B4B/eB*BB%BBBBB ~B`BDB'B BBBBB݉BpBXB?B'B BBBBBBxB]BBB(B BBBB|BwxBrYBm8BhBbB]BXBSBN[BI2BDB>B9B4~B/LB*B$B WB%tB*B/B5VB:B@WBEBKBQjBW=B]"BcBiBo+BuJB{vBBBBBBBBfBBPBBBBPBBsBBB(B#BBػB[BBDBʐBBBBBBJBBBBgBBB;BbBzBB~ByqBtWBo2BjBdB_BZCBTBOBJJBDB?B:,B4B/eB*B$B>BBB!B BnBBB{B1BBBhB,BBϼBʉBYB,BBBBBsBWBIBD:BJBB.BB=BBfBBBGBBĘBABBؕB>BBB)BB]BB zBBzB B'WB-B4 B:TB@BFBLBRBXB^BdBjBpMBuB{BBrBBB#B.BBBBPBB9BBBòBǚBbBBҊBB#B9B(BBBB_BBBVBBvBBBBB BEBOB+BBZBBBBBVBB6BjB{BfB,BBRB޲BBBBBϵB]BBZBBBB BBBBzBBB-BBBGBBB{BvBrBm BhBbB]BXBSBNqBIBBDB>B9B4lB/2B)B$BBYB&BB BBlBGB&B BBBBܶBתBҠB͚BȗBØBBBBBBBBBB7BTBtBB~ByBu Bp6BkbBfBaB\BX(BS]BNBIBEB@BB;~B6B1B-:B(|B#BBEBBB B[BBB2B{BB BUBBB1BzBB BTBBB+BqBBBABBB BKBBBB~DByBtBoBk*Bf_BaB\BWBS$BNPBI{BBBB BB-BBB|B%gB+fB1tB7B=BCBJIBPBWB]wBcBjyBq BwB~ABBBKBBBBDB BBB[B BBܣB`BBB{B"BB [BBqBB%^B+B2B8fB>BDBJBPBVB\BbBhBn6BsByYB~B"BcBBBBhB&BBKBBBB&B BBrBBKBBԏBxB:BBEBBBBdBBlBBBB9BBBBB-BBB BBBwBBNBBBxB>BBfBB B0B6BBBÛB1BBBZBBBBB~BHBBB:BB5BB}ByBBtBoBjBfBa!B\3BW>BRCBMCBH=BC5B>*B9B4B.B)B$BBBBB BBBBBBBBB8BXB|BУBBB+B^BBB BJBBBBaBBBMBBB{NBvBrBm`BhBd B_BZBVNBQBM BHBCB?cB:B6BB1B-$B(B$ BBBjBB XBBHBB9BB*BBBBBۇBBxBBhBBVBBABB)BBB~BB]BB6BB BrB{BwBE$BKBRIBXB_BfKBmBsBzBeB:BBBBBBrBTB5BBBBڝBmB7BBBkBB BQBB^B#B*:B0B6B=BCDBI^BOfBU\B[>Ba BfBlhBqBwkB|BB:BLBDB BBBBiBBBBB{BBÑBBBBBҷBIBװBBBBߣB0BBBBBBHBeBUBBBB[BsBbB)BBDBܘBBBֿBԆB-BϲBBaBNJBėBB\BBB>BBBHBtBBB~B[B'BBB*BB{9BvBrBmtBhBdB_SBZBUBPBLBG;BB[B=yB8B3B.B)B%B #BFBhBB BBB6BkBBB$BiBBBMBӡBBQBŮBBrBBBBBBBB{BBqBBrBBzB}BxBtBoBk5BfBbZB]BYBUBPBLRBGBCB?*B:B6kB2 B-B)SB$B BCBBB7B BB0BBB*BBzB#BBrBBBgB BɲBVBBB?BBBBBXBBB%BBQBBuBBzBvBqBm0B-BBjB*BBBBBBTB BBXBB&PB,B3~B:'B@BGBN_BU0B\BbBiBpBwB~BBBBBBB}BwBoBcBSB>B$BBBBrB0BBB)BB=B"B)B/pB5B;BBBH"BN BT BYB_BeJBjBpXBuB{B2BFB>BBB{BBaBBBBBaBBlBBBBȺBjBBOBҀBԈBcBBّBBBBBB'B7BBB^BܿBB BBسBNBBBFBRBBB"BߙBB֔BB͜B%BIJBABBjBBB=BBB*BBB.BBBGB~BzBvtBr2BmBiBevBa:B]BXBTBP\BL(BGBCB?B;cB75B3B.B*B&B"XB-BBBB B _B7B BBBBjBABBBBۖBjB=BBBƲB€BOBBBB|BCB BBBSBBBBFBB~B BûBɀB\BNBTBnBBB-BBBBBB_B"B(B/B6B=fBDPBKDBR>BY>B`DBgOBn^BuqB|BBBBBBB$B3B>BDBEB?B2BBBBBkB#BBmBBB!B(UB.B4B;BA.BG4BM&BSBXB^vBdBiBnBt=BynB~B}BXBBB7BBBBBBBB~BBBBBPBBBDB?B BЭBBbB`BBդBB0B3B BշB:BԒBBBѰBmBByBBBBBúBeBBcBBB B BBB|BBBB~BBB/BFBLBDB~,BzBuBqBmMBhBdB`2B[BWLBRBNLBIBE8B@B<B7B2B.`B)B%>B B&BBBB BB BB%BBNBBB+BB{B)BB̏BGBBBBHBBBBzBLB"BBBBBwB\BBB}+ByBuBpBlBhBdB`B\BXBTBPBLBHBDB@BhB:B6B2B/,B+^B'B#BB)B]BBB B (BZBBBBBMB|BBBB,BVB~BӥBBBB2BRBoBBBBBBBBBB|BBBBEBéBBХB>BBBdB8BBBBBB)B#HB*pB1B8B@BGNBNBUB]#BdnBkBsBzUBBB2BuBBB%BTB|BœBɳBBB޾BBB`B&BBBBBB!B'B. B45B:HB@DBF*BKBQBWLB\Bb8BgBlBqBvB{BVBBjBBB BBBoBBKBBBlB&BBBQB^BBBB:BB/BBB|!BxTBtyBpBlBhBdB`B\jBXGBTBOBKBGBCBB?B:B6}B29B-B)B%tB!7BBBBSB #BBBBBrB\BJB=B3B.B,B/B5B?BLB]BrBÉBBBB B1B\BBBB"BZBBBBRBBB"B{lBwBtBpTBlBhBeIBaB]BZKBVBRBOWBKBHBDkB@B='B9B5B2DB.B+B'cB#B "BBBABB B ]BBBtBB*BBB3BBB0BނBB!BoBϺBBLBđBBBUBBBNBOBfBBB/BBBBIBB̾BӐBpB^BYB`BsBBB B#BeB!B(B0QB7B?BFhBMBU1B\BcBkdBrBz,BBBCBBB/BqBBBB!B4B;B6B$BBBBKBB}BBfB!B(B..B4DB:FB@0BFBKBQWBVB\DBaBfBkBpBuBzUB~B`BBBBBB:BBB,B,BBB2BBBBB BzBBvB.BBBOBZB;BBBB1BOBIBBBcBB"BRBcBVB,BBBBqBBBB(BBBBB*BBDB|ByBuuBqBmBj.BfTBbqB^BZBVBRBNBJtBFaBBJB>1B:B5B1B-B)B%B!xBfBSBAB2B )B %B%B+B4BBBUBlBBBBBBOBւBҺBB2BuBúBBNBBBFBBBVBBBBBRBB.BBBB~B{vBwBtmBpBmjBiBflBbB_tB[BXBUBQBNBJBG,BCB@ABBF0BMBU/B\Bd,BkBs"BzB ByBBCBBB;B|BBBBBBBBBBdBBB,BBB"AB(sB.B4B:~B@QBF BKBQ-BVB[BaBfBkBoBtBy#B}BBB BBBBK!BHBDBAB>B;B8mB5OB20B/B+B(B%B"BgBABBBBB xB JBBBBBOBBBBbB BBBQ?BWB]BdnBjBqBxXB"BBBBBB@ByBBBoBBIBBHBBfBBB @BBB!?B(B0B8NB?BGBOZBWB^BfOBmBuB}BB(BBB~BB-BrBBBBBBBBBLBBB B^BBB$B* B/B5B;BABFBLBQFBVmB[tB`\Be"BiBnJBrBvBzB~BBaBB5BcBfB?BBoBBBBBBDBUB9BBBB B4B BBBBXBBBB[B BB B`BBBBBiBBBABBBTBBB|ByBvBs~BpNBmBiBfkBc B_B\#BXBUBQBMBJZBFBCB?pB;B8B4oB0B-B)qB%B")BBBLBBB B B}BBB BB,BB^BBBKBBܨB]BBBϑBUBBB´BBZB1B BBBBBxBcBPB>B0B$BBB BBBBBB|ByBv BsBpBm"Bj+Bg5Bd?BaJB^UB[aBXmBUyBRBOBLBIBFBCB@B=B:B7B4B1B/B, B)B&B#B BBBBBB B BBBBBBBmBPB@.BFBMBSBZMBa BgBnBuB|BBB(BlBBBBBzBB͗B3BBB0BBB`B "BBB"uB*=B2B9BABIRBQBXB`Bh2BoBwBBB8BB-BBBFBBBBBBBBBeB BBB BB B,B%3B+B0B6B<@BABGBL\BQ~BVB[`B`BdBi7BmBqBuByB}uBBBBBBBGBBBBBmBBBBBuBBNBBBlB*BB8BBBBBB3BB8BBBBBBBrBBB'BB~B|$ByUBvtBsBpBmtBjWBg.BcB`B]mBZBVBSWBOBLxBIBEBBB>B:B7uB3B0gB,B)^B%B"`BBnBBBB B @BBB0BBBMB BBB_B.BBBܶBٕByB`BLB:B,B"BBBBBB&B1B@BPBcBxBBBBBB&BJBpBBBBBCB~rB{BxBvBs4BphBmBjBhBe8BbnB_B\BZBWEBT{BQBNBLBIMBFBCB@B>B;GB8wB5B2B/B-(B*QB'xB$B!BBB#B>BXBpB B BBBB/rB5BBdBkBsBFhBNFBVB]BeBmzBu1B|BBBB&BBBQBBBBBBBBB3BBJBB B:BXBZB"AB( B-B3LB8B>BCFBHZBMLBRBVB[UB_BcBhBlBoBsBwBzYB}BB[BBBBBB&BBBBBlBBgBBBBBBBB:BBBBBrB#BB1BBBBBBB~B|Bz.BwBuGBrBpBmjBjBgBeBbB_-B\0BY*BVBSBOBLBIBFZBC#B?BBBBJBB BoBB?BBBBBlBBXBBJBBCBB@BBBBBGBB}OBzBxYBuBsdBpBnpBkBi|BgBdBb B_B]BZBXBUBSBPBNBKBIBFBDBAyB>BBkBs\BzBBfB*BBBBBBxBrBoBrBwBBBBB BBB!B)B1B9BABIBQBYeBaB;B8B5B2nB/QB,6B)B&B"BBBBBBB B BBB$BHBpBBBBABBBB\BBB\B۹BBրBBUBB7BɭB'BģB#BB*BBBBBBB{B BBBKBpBzBeB5BBBB~nB|BzByBw,Bu&Bs BpBnBlSBiBgBeBbyB_B]:BZBWBUBR:BObBLBIBFBCB@B=B:B7B4B1B.B+B)B&B#$B :BOBbB}BBBB B UBBBBdBB BfBB)BBBpBB`BB`BBoBBՎB"BкBVBBɖB;BBŒB:BBBQBBB~BBBBBBYB,BBB}B{vByHBwBtBrBpBn[Bl)BiBgBeBcWBaB^B\BZnBX/BUBSBQhBO"BLBJBH@BEBCBAHB>BBBBB &BBBB"GB'B-B2ZB7rB BFBNBVB^BeBmBuB};BBBBBBIBBBBBBԩBkBBB B~BBBB BBcBB$hB)B.B3B8B=BBNBFBK%BOWBSbBWFB[B^BaBe7BhHBk-BmBpSBrxBtoBvB;B9#B6iB3B0B.=B+B(B&"B#uB B&B}BB>BBBB B B BB)BBZBBBIBBBbBBBBmB:B BBݸB۔BtBWB>B(BBBBBBBBBBBBBB BB(B:BLB`BvBBBBBB B'BCB_B{BBBBB B&B@B\BuBBBBB}B|BzBx$Bv4BtBBrOBpZBnbBliBjmBhpBfpBdmBbhB``B^VB\IBZ8BX%BJBNBjBBB8BB B BPBB#B+B3hB;RBCHBKIBSUB[mBcBkBsB|"BcBBBEBBBKBBBaB׾BBsBBBoB BBAB"{B*B2B:BCBKBSB[BbBjBrBzeBBBDBB-BBBBBB BBؠBGBBHBBBBB BBXBB!HB&B+B0B5B:OB>BCUBGBKBOBSBW7BZB^ Ba6Bd4BgBiBkBmBoBqvBsBtkBuBvBwBxvByByByBz,BzCBz9BzByBy[BxBx1BwpBvBuBtBsfBr&BpBo^BmBl@BjBhBfBeBc$BaB_ B\BZBXxBV/BSBQ|BOBLBJ+BGBE%BBB@ B=wB:B8HB5B3B0zB-B+KB(B&&B#B!BBBBBB BB RB BBGBBBmB/BBBBgBABBBBBBBBBߦBݨBۮBٸBBBBBB0BNBnBȑBƷBBB4BbBBBB,BbBBB BHBBBB=B|BBB;B{BBB;BzBBB8BuBBB)BdBBB B@BrBB}B|Bz.BxWBvBtBrBpBoBm"Bk:BiOBgbBerBB!BPBٔBBYBBjB BBBWB8B&(B.$B6-B>BBFbBNBVB^BgCBoBwBBBF6BNFBVHB^/BFBNBWjB_Bh`BpByiBBBBB;BBcBBƆBBנB(BB(BBB zBB4B#B+B4B<.BDPBLdBTkB\cBdKBl$BsB{BIBBZBBBZBBBBtB=BB؂BBZBBBBBsB BBBHBgB#bB(9B,B1wB5B:B>1BBBEBI}BLBP0BSGBVBXBZB]B_B`BbBdBe|BfBgBhBi|Bj#BjBk BkKBkmBkpBkTBkBjBjUBiBi"BhbBgBfBeBduBcBBaB`B_2B]B\"BZBXBWBUABSfBQ~BOBMBKBIvBG\BEB<B:EB8 B5B3B1LB/ B,B*B(]B&)B#B!BB{BTB6BB BBBB B B B4BPBrBBBB,BfBBB2B~BB%B~BBBBB&'B$B" BBBBBBBBB=BaB B BB*BiBBBIBBBTBBBBBnBBbBBfBByBBB.BBbBBBFBBܖB@BB؞BPBBԺBqB+BBϢB_BBBʟB`B#BBŪBnB4BBBBHB BBBZBBBBbB"BBB[BBBBB,BBB4B BB BBB#B(&B,B0B4B8B7B<=B:>B8=B69B43B2,B0&B. B,B*B(B&"B$,B"=B LBYBoBBBBB9BtBB B IB BBPBBBBBqBBmBB|B BB2BBkB BB\B BBmB$BBB[BBBBtB@BBB۲BچB]B5BBBBӣB҂BbBBB$BBBBʰBɔBxB\B@B$BBBBBBrBRB0BBBBBwBMB"BBBBaB*BBByB9BBBgBBBB BBJBBBBBBȎBЪBBBTBB BuB BlBB$B-$B5B>oBGBOBXBaHBjBrB{BRBBBBcB#BBBLBBۤBFBBtBBBBaBB(B0\B8B@BHBPBXB`BhBpmBx BBIBBBeBBBBB`BBͦBB{BBBBByBBBB&B8B&BB!B& B*`B.B2B6gB:B=B@BCBFBIUBKBNBPBRBSBUpBVBX@BYrBZB[kB\5B\B]fB]B^B^DB^TB^FB^B]B]~B]B\zB[B[BZFBY`BXdBWVBV6BUBSBRmBQ BOBNBLBJBISBGBEBD0BBhB@B>BHBABCBFEBHBJBLBNBP\BQBSXBTBUBVBWBXaBYBY~BYBZ!BZGBZQBZ?BZBYBYnBXBXjBWBW BV=BUZBTdBS\BRBBQBOBNBM:BKBJaBHBGYBEBD'BBB@B?B=cB;B9B8B6EB4vB2B0B/B-4B+fB)B'B&B$QB"B B"BmBBByBBKBB7BB;B B VB B B&BBwB&BBBSBBBBwBLB#BBBBBBBqBeB\BVBSBRBTBXB_BhBtBBBBBBBB B'BBB]ByBۖBڴBBBB/BMBlBԋBӪBBBBB:BUBoḂB˞BʴBBBBBBBB$B(B*B*B&B BB BBBBkjBrBzBhB9BBB B:BfBBBABӦBBB BBSBBBdB!$B)B2B;BD_BM9BVB^BgBpByB~B_B>BBBBBjB0BBکBYBBB4BBBX5B`BgBoBwUB~BiBB!BZBzBBnB@BBŒBBpBرBBBB}BBBB,B ?B,BBBB"`B&B*B.^B2 B5B8B;B>aB@BC\BEBGBIBKnBMBNBOBQ&BR=BS1BTBTBUMBUBVBVXBVwBV|BVgBV7BUBUBUBTBSBS0BRfBQBPBOBNBM^BL+BJBIBHCBFBEkBCBBlB@B?HB=B< B:aB8B7B5QB3B1B0.B.wB,B+ B)ZB'B&B$_B"B! BBBQBB>BBFBBfBBBDB B B VB BBBbB2BBBBBBqB`BTBKBEBDBFBLBVBbBqBBBBBB B-BRBxBBBB(BXBBBB&B]BBBB?ByBߴBB)BeBܠBBBOBوBBB1BhB՝BBB6BfBєBBBB=BaB̄BˤBBBB BB-B9BBBHB`pBhBoBwBzBnBtBBBB7BBBhBBsB BBZBBBBbB 6B)B1B:BCBLBUB^BgrBpbByRBAB.BBBBBBrB@BBBzB&BB`BBmBBFB'B/B8B@HBH`BPfBXZB`;BhBoBwdB~BiBBBABWBTB4BBB2BˣBB(BGB@BBBDBFBH_BIBKcBLBMBNBOBPBQ=BQBR6BRBRBRBRBRBRBR@BQBQhBPBP;BOBNBMBLBKBJBIBHBGwBF4BDBCBB(B@B?FB=BBdBBB7BBBBBжB[B BBBSB%BBBB(B1B:BCBLBUB^BgBp~ByzBtBlB`BQB=B$BBBɴBBBBBBPBBvBBjBB(&B0lB8B@BHBPBXB`BhnBp BwBBBBBDBiBtBdB:BBBBpBѲBBBB|BBBB$B2B B B|BB=B`B#ZB'(B*B.$B11B4B6B9XB;B=B@BBBCBEuBFBHXBIBJBKBLBMJBMBNkBNBOBOIBO^BOZBO=BO BNBN[BMBMZBLBLBKDBJoBIBHBGBF}BE^BD2BBBAB@kB?B=BBBBB!BB`BBBBcB;BBB BBB(B1B:BCBLBUB^BhBqBzBBBBBBBBBʍB\B"BBB5BB]BBNB B)B1HB9zBABIBQBYBabBi!BpBx^BB>BBBBBBB*BB(ByBѬB׾BݯBB-BB BdBB}BQB BBBBB!B%B)B,9B/,B1B4B7 B9\B;B=B?eBABBBD(BEyBFBGBHBIyBJ,BJBK;BKBKBLBLBL BKBKBKiBKBJBJBIjBHBGBG+BFLBE]BD`BCVBB@BAB?B>B=|B<4B:B9B82B6B5kB4B2B1'B/B.HB,B+kB)B(B'1B%B$tB#B!B pBBBBUB BBBBBsBcBYBSBUB[BgB xB B B B B BEBxBBB*BmBBBNBBBOBB BmBB;BBBBBhBBWBBMBBJBBLBBSBB^BBlBB|BBBBB&BB6BBDBBOBBVBBXBBTBBKBB9BB BBBhBB5BBBSBBBTBB.BIBQBYBaBiBrBz^BB B|BBBBBuB2BBBBBuBhBaB`BdB lB)xB2B;BDBMBVB_BhBrB{B*B2B6B5B.B B BBBԜBdB BBxBBBBB!B*8B2wB:BBBJBRBZBbhBjBqByGBBBQBxBBtBIBBBBzB˺BBBݹBvBBBBBBBB DBBBBB B$?B'mB*qB-JB/B2B4B7B92B;"BB@BA}BBBCBDBEBFBG6BGBH3BHBHBHBHBHBHBHBH@BGBGhBFBFFBEBDBDBC:BBRBA^B@]B?PB>:B=B;B:B9B8BB6B5B4`B3 B1B0^B/B-B,SB*B)B(SB'B%B$tB#5B!B BzBFBBBBBBBBBBBBBBB@BnB B B B TB B B 2BBB6BBB]BB4BBBB BBBB BBBB8BBZBBBBBKBBBBBZBBB8BBxBBBZBBB8BBtBBBGBBxBBB9BBZBBtBBB BB BBByBB^BB5B8B?BGBOBWB`'BhcBpByB|BBB BB{B;BBBϽBئBBBBBBBB B*B3%BB=BcBFuBNBVB_BgvBoBx]BBB)BBBnBGB*BBB BB!B5BPBoBBB!B+B4@B=pBFBOBXBb+BkVBt}B}BBBBBBBBBBעBpB1BBB(B B.BB$B-?B5wB=BEBMBUB]fBe#BlBtXB{B,BoBBBBrB,BBFBBBBBBޗB.BBBBBBB=B BBBBsBB!B$B'B*hB,B/KB1B3B5B7TB8B:B;B=4B>]B?fB@RBA!BABBkBBBCKBCBCBCBCBCBCBCrBC$BBBBQBABA9B@B?B?$B>XB=~BBBBYBB-BBB B B B B B &B B KB B |B BB]BBBWBBBgBBBBDBBB{B;BBBBDB BBBZB BBBtB:BBBBPBBBBYBBBBPB BBxB,BBB=BBB6BB{BBBIBBmB%TB-JB5UB=sBEBMBV@B^Bg"BoBxBBBB_B-BBBBBBBBB5B[BBBB#B#\B,B5B?BHMBQBZBcBm,Bv]BBBBBB B BBBBٷBBGBBB:B BDB? B?B@BB@BABAWBABABABABA`BA$B@B@uB@B?B>B>TB=BBBBBBnBDBBBBBXB&BBBBIB BBBJBBBrB#BB~B(BBoBB$B,B4B=BEpBMBVHB^BgaBpBxBxBGB"BBBBB B"BABhBBBB;B {BBB%JB.B7BA"BJiBSB\Bf1BomBxBBB+BJBbBqBwBsBdBJB%BBBfB BB%BB B)NB1B9BABIBQBYBaUBhBpBxBfBBBBBBbBBwBB B'B BBڪB:BBB BBBB BfB BBXBBB.B "B"B%B(B*oB,B.B0B2pB4B5B7B8YB9B:B;B<\B=B=B>=B>B?B?@B?gB?zB?wB?`B?6B>B>B>LB=B=_BBBBBBBB,BBBdBČBʑBuB6BBLBBBBBsBBmBB BB BbBBBoB"$B$B'B)aB+B-B/]B1B2B4,B5B6B7B8B9B:B;GB;B<]BB1B$BBBBBBBBBiBJB*BB B B B bB 2B B B B PB |BBB%B-[B5B>=BFBOcBXB`BiBrhB{LB=B8B@BRBnBBBB0BsB߻B BZBBBbBB!B*yB3B=4BFBOBYB/jB.B-B,B,B+&B*LB)tB(B'B&B&7B%tB$B#B#-B"vB!B!B wBBCBB&BB!BB2BBZBBB;BBBHBBB~BDB BBBBXB4BBBBBBBBBByBuBtBtBvB{BBBBBBBBBBB BB/BCBWBkBBBBBBBBBB$B3BABMBXBbBiBoBtBvBwBtBpBjBbBVBHB7B#B BBBB,BDBBBEB'B0NB8BABJYBS'B\BdBmBvBBB6BeBBB$BrBB"B܂BBNBB&B BBvB'B1TB:BD,BMBVB`XBiBsB|VBBBBDBhBBBŖBΌBwBSB BBB,B B5BB$B-6B5dB=|BEBMkBU@B\BdBl-BsBzB2BRBTB;BBB8BBBBBBB`BB+BYB`B@BBBB'BBB ABBBBBdBB jB"B$B&B(B*B,BH9BQB[BdpBmBw%BuBBB3B`BBBBɦBҙB}BTBBBzBBBB eB(B0B9BABI BPBXB`[BgBokBvB~B:BHB8B BBSBBBOB`BOBBBFBܤBBBBB7BBBBB .B BBBBB2BB B"@B$UB&IB(B)B+fB,B.7B/tB0B1B2B3]B4B4B5FB5B6B6gB6B6B6B6B6B6B6sB64B5B5B5*B4B4>B3B3*B2B1B1RB0B/B/BB.B-B-B,UB+B*B*B)`B(B'B'@B&B%B%EB$B#B#_B"B"6BGBPBXBbBkBt6B}`BBBBkBB!BBB`BBKBBCBB ABBAB&B0BWBrBBBBBBCBmBBBB#BSBBBB !B VB B B B!0B!gB!B!B" B"CB"zB"B"B#B#MB#B#B#B$B$BB$nB$B$B$B%B%5B%WB%vB%B%B%B%B%B&B&B&B&!B&$B2BBtBB *BBcB'B/B8BABJBSB\BeBnBxBOBBB9BBBiBBPBBJBBOBBZBBhB!B+qB4B>qBGBQbBZBd?BmBwBZBBB)B[BBBBɬBҠBۅB\B"BB~BBBB ]B(B0B8B@BHBPBXzB` BgBoBvtB}BBBByBBB BSBwByBWBBЪBBgBBBcBBBBBBuBB BB kBpBNBBBB_BB!B#B%SB'B(B*B+\B,B-B.B/B0B1>B1B2tB2B3SB3B3B4B4+B44B4/B4B3B3B3B3:B2B2B2B1B1*B0B0B/B.B.\B-B-B,{B+B+3B*B)B)IB(B(B'uB&B&TB%B%6B$B$+B#B#8B"B"_B!B!B!DB B B ]B BBBsBEBBBBBBBBwBpBnBnBrBzBBBBBBB B+BNBsBBBB B PB B B B!"B!ZB!B!B" B"GB"B"B#B#BB#B#B$B$EB$B$B% B%JB%B%B&B&GB&B&B&B'8B'rB'B'B(B(JB(|B(B(B)B)0B)YB)~B)B)B)B)B*B*&B*8B*FB̃BBBBBB5B!B*B3BB~B BBZBBBB6BYB]B!@B#B$B&7B'B(B*/B+LB,QB->B.B.B/wB0 B0B0B1FB1B1B1B1B1B1B1B1B1uB17B0B0B0@B/B/pB.B.B.B-B,B,vB+B+^B*B*BB)B)*B(B(B'B'B&B&.B%B%AB$B$nB$ B#B#_B#B"B"B"FB"B!B!B!B!`B!AB!'B!B!B B B B B B B!B!B!$B!;B!VB!tB!B!B!B" B"8B"hB"B"B#B#@B#|B#B#B$BFqBNCBUB]Be"BlBsB{B(B!BBBVBB0BkBByBMBB͆BB(B@B1BBBBAB)BBBB9B \B ZB2BByBB7BdBqB_B!/B"B$uB%B'JB(B)B*B+B,B-dB.B.B/;B/B0B0`B0B0B0B0B0B0B0B0B0pB02B/B/B/AB.B.xB. B-B- B,B,&B+B+#B*B*B)B)B(B( B'B'6B&B&ZB%B%B%B$B$lB$B#B#B#JB#B"B"B"B"^B">B"#B" B!B!B!B!B!B!B!B!B"B""B":B"VB"vB"B"B"B#B#CB#uB#B#B$B$YB$B$B%B%cB%B%B&?B&B&B'+B'|B'B(#B(xB(B)$B)|B)B*-B*B*B+:B+B+B,FB,B,B-TB-B.B.[B.B/B/^B/B0B0TB0B0B1AB1B1B2B2dB2B2B3&B3dB3B3B4 B4=B4lB4B4BBBҺBBB&B BBB&xB/sB8}BABJBSB]$BfkBoByByBBXBBRBBbBB΅BBBLBBBBBNB$B.vB8BABKBTB^BgBpBzRBBBDBBBBBBBB޺BBBBBB B}BB#%B+XB3vB;}BCmBKDBSBZBb4BiBpBx3BPBOB1BBBB|BBBBBhBBeBժBBBB9BBBBBHBBB?B EB (BBBBRBBBBpB!,B"B$LB%B'B(3B)LB*NB+7B, B,B-nB.B.B.B/DB/B/B/B0B0 B0 B/B/B/B/B/AB.B.B.VB-B-B-,B,B,LB+B+bB*B*pB)B)~B)B(B( B'B'IB&B&B&B%B%_B% B$B$wB$4B#B#B#B#dB#=B#B#B"B"B"B"B"B"B"B"B"B"B"B#B#*B#JB#nB#B#B#B$B$PB$B$B$B%:B%|B%B&B&OB&B&B'4B'B'B(+B(B(B)/B)B)B*?B*B*B+XB+B,B,uB,B-6B-B-B.XB.B/B/xB/B06B0B0B1PB1B2B2_B2B3B3cB3B4 B4ZB4B4B5?B5B5B6B6SB6B6B7B7>B7rB7B}B@B.BBBzBB+BBB"B+B4B=BGBPPBYBbBl.BuB~BbBBVBBcBBBBԳBNBBB(BBcBB!B+.B4B>OBGBQ\BZBdPBmBw%BBB"BaBBBBBBB۵BBFBBBBBB AB(zB0B8B@BHwBP;BWB_uBfBnEBuB|BBBXBBBB8B^B`B?BBȒBBOBuBsBIBB}BBBB.BB B>BMB 8B BB$BBBBBBB!4B"B$1B%B&B'B(B)B*B+B,7B,B-\B-B.6B.B.B.B/B/0B/5B/-B/B.B.B.B.bB.B-B-|B-"B,B,^B+B+B+B*B*?B)B)`B(B(B(B'B'WB&B&B&BB%B%B%MB%B$B$B$[B$,B$B#B#B#B#B#B#vB#oB#mB#pB#vB#B#B#B#B#B#B$B$@B$jB$B$B$B%4B%nB%B%B&.B&sB&B'B'RB'B'B(DB(B(B)HB)B)B*ZB*B+B+xB+B,CB>BBBBB\BBZBBBB"B,B5$B>RBGBPBZ%BcBlBvRBBDBBSBBwBB¬BKBBߐB5BB~B!BBbB"B,B6+B?BIFBRB\FBeBo*BxBB:BBBB B!B(B B BBB`BBBBBB!B)EB1ZB9XBA>BI BPBXZB_Bg@BnBuB|BBBBBBLBBBBBBABBBRB`BGBBBBBBB2BBBBBB BCBBBIBbB\B:BBB 'B!B"B$'B%LB&XB'MB(.B(B)B*QB*B+]B+B,$B,oB,B,B,B- B-B- B,B,B,B,B,^B,$B+B+B+RB+B*B*ZB*B)B)SB(B(B(PB'B'B'eB' B&B&B&PB&B%B%B%B%_B%>B%%B%B$B$B$B$B$B$B%B%B%$B%=B%ZB%zB%B%B%B&$B&XB&B&B'B'FB'B'B(B(gB(B)B)\B)B* B*fB*B+#B+B+B,LB,B-B-B-B.ZB.B/6B/B0B0B0B1jB1B2QB2B38B3B4 B4B5B5|B5B6bB6B7FB7B8'B8B9B9rB9B:HB:B;B;B;BB>pB>B?B?eB?B?B@BBlBFBFBnBּB,BBBBB B)B2B< BEIBNBWBa>BjBtB}BBBBB]B>B?B?yB?B@*B@B@BA#BApBABoBKBNBxBB8BBB BBB'B0B:BCTBLBUB_KBhBrB{BBB$BBKBBB!BBhBBBXBB B>BB(uB2 B;BE'BNBX*BaBkBtuB}B$BlBBBBBBBBBB]BBBB BB&B%TB-lB5mB=WBE(BLBT~B\BclBjBqByBBBB%BBB2BIB=B BBABɣBBBBݫBIBBBBtBBBBB#B BB yB BaBBBBBB=BBQB B!B#0B$KB%NB&AB>B?B?wB?B@B BB0BBBBBB 8B B+BuBBBBrB+BBJBB!B"=B>B?B?B?B@TB@BABABABBkB>B?LB?B@'B@B@BAcBABB,BBBBBCIBCBCBDPBDBBfBhBBBKBBBBBB#B,B6B?LBHBQB[;BdBn Bw}BBzBBB"BBRBB͎B/BBsBBBTBBB$"B-B7BB@BJLBSB]:BfBp BycBBB1B`BBBB”B|BVBBB|BBBBWBB B(B0B8B@BHXBOBW~B^Bf8BmlBtB{}BYBBB3BBBBBBjBB`BʣBBԶBمB+BBBBB1BBBZBtBlBBBB B BPBBBBuB8BBlBB:B }B!B"B#B$B%~B&@B&B'B(B(B(B)ZB)B)B*B*@B*ZB*jB*pB*lB*^B*JB*/B* B)B)B)B)PB)B(B(B(gB(*B'B'B'}B'JB'B&B&B&B&hB&DB&'B&B%B%B%B%B%B%B%B%B&B&B&6B&TB&uB&B&B&B'$B'YB'B'B( B(NB(B(B)(B)vB)B*B*qB*B+&B+B+B,FB,B-B-zB-B.PB.B/.B/B0B0B0B1pB1B2_B2B3RB3B4HB4B5@B5B6:B6B74B7B8/B8B9)B9B:"B:B;B;B<BaB>B?HB?B@(B@BABAlBABB;BBBCBCcBCBDBDuBDBE B@BBB:BɂBB|B*BBBB# B,)B5UB>BGBQBZtBcBm>BvB*BB/BBJBBuBB̬BKBBB)BBdBBB#*B,B6FB?BIKBRB\5BeBoBxWBBBBKBkB}BBxB_B6BBBWBBiBB,BoBB'B/B7B?nBG&BNBVJB]BeBl6BsMBzGB#BBBB[BBBBB7BB/BsBΒBӉBXBBhBBBdBBBBGBeB`B9BB B BXBBBBBTBBB BjBB B!B#B#B$B%B&FB&B'xB'B(gB(B)B)_B)B)B)B)B)B*B)B)B)B)B)B)gB):B)B(B(B(hB(0B'B'B'B'VB'%B&B&B&B&|B&UB&5B&B&B%B%B%B%B%B%B%B&B&B&,B&HB&hB&B&B&B'B'AB'xB'B'B(.B(rB(B)B)OB)B)B*EB*B*B+SB+B,B,vB,B-BB-B.B.B.B/`B/B0DB0B1-B1B2B2B3 B3B4B4}B4B5uB5B6pB6B7kB7B8eB8B9_B9B:ZB:B;QB;B%B>B?B?B?B@bB@BABGXBPBYBcVBlBv+BBBB)BBGBBsB BըBEBB~BBBJBB"pB+B5B?BHBQB[jBdBn.BwBBBCBlBBBBBsBIB BBcBBpBB/BpBB&B.B6B>fBFBMBU?B\BcBk(Br>By7BBBlBBIBBBBpB#BBBaB̀BxBIBBZBBB]BBBBLBmBlBHBBB B tBBBBBB3BBEBBB )B!HB"PB#BB$"B$B%B&LB&B'fB'B(?B(B(B)B)JB)lB)B)B)B)B)B)vB)\B).B>B?B?B?B@jB@BAEBABBBBBBBCHBCBDBDdBDBEBEkBB^BSBlBȭBBB6B|BmBlB"xB+B4B=BG(BPoBYBcBl~BuB]BBTBBcBBBBˬBDBBuBBB=BBaB!B+xB4B>|BGBQhBZBd7BmBvB*BhBBBBBBBȷBщBKBBB(BB B ^BBB%B-B5B=BE;BLBTYB[Bc Bj>BqQBxJB#BB{BBUBBBBzB.BB&BkB̊BтBSBBfBBBoB%BBBgBBBjB(BB CB BBB BBBuBBBBDB}B B!B"B#B$TB%B%B&TB&B'UB'B(B(dB(B(B(B)B)-B)5B)5B)-B)B)B(B(B(B({B(NB(B'B'B'B'ZB'+B&B&B&B&B&bB&B;B<0B B>B>B?dB?B@CB@BABABABBWBBBCBC~BCBD9BDBDBE@B+BBBB,BڈBBBBBB"B+B4B>BG?BPBYBc'BlBuB\BBMBBSBBiBBˋBB޳BGBBoBBBB!B+-B4B>)BGBQ BZtBcBm)BvwBBB"BDBZBcB^BKB)BBٶBdBBBBeB BBB%'B- B5B.B>B?B?B?B@ZB@BA.BABABB_BBBC!BCBCBD4BDBDB_BBBBBBەB BB)BB B#B, B5=B>fBGBPBZ$BcvBlBv3BB BBBBBBB˥B4BBTBBsBBBB!B+B4B> BG{BPBZHBcBlBv=B|BBBB BBBBBГBNBBBBBB 5BmBB$B,B4rB<9BCBK~BRBZ\BaBhBoBvB}B_BBqBBBBBBB!BBBBBԱBYBBBBBBBBBBBBBJBB /B tBBBBhB!BBFBBBFBnB B!~B"fB#B'B&B&B&B&hB&CB&#B&B%B%B%B%B%B%B%zB%yB%{B%B%B%B%B%B%B&B&&B&LB&vB&B&B' B'@B'{B'B'B(=B(B(B)B)gB)B* B*aB*B+B+pB+B,/B,B,B-\B-B.-B.B/B/rB/B0QB0B14B1B2B2B3B3}B3B4kB4B5\B5B6MB6B7>B7B80B8B9!B9B:B:B:B;sB;B<\B#B>B?B?mB?B@AB@BABAsBABB6BBBBBCKBCBCBDLB+BBBBB4BBBBBB#B,B5B? BH;BQvBZBdBm\BvBBBBqBBkBBtBBՅBBB%BB6BB?B!B+9B4B>"BGBPBZOBcBlBv5BoBBBBBBBBǔBZBBBHBB8BB BB.B$7B,)B4B;BCtBKBRBYBa"BhJBoVBvFB}BBdBB1BgB|BpBABB{BB"B>B4BBجBBBBGB%BBqBB+BTBZB>BBB(B B BB BBBB+BB"BzBBBB B!B"B#B$5B$B%hB%B&ZB&B'B'[B'B'B'B(B(B( B(!B(B( B'B'B'B'B'wB'PB'%B&B&B&B&yB&QB&+B&B%B%B%B%B%uB%bB%TB%KB%EB%DB%HB%OB%[B%jB%~B%B%B%B%B&B&AB&nB&B&B'B'BB'~B'B(B(FB(B(B)%B)tB)B*B*rB*B+%B+B+B,AB,B-B-nB-B.>B.B/B/B/B0]B0B1>B1B2#B2B3 B3B3B4jB4B5WB5B6DB6B71B7B8B8B9 B9~B9B:gB:B;NB;B<1BVB>B?*B?B?B@[B@BABA}BABB4BBBBBC8BCBBBBBB,BjBB&B BBB$B-B6B?BI BRSB[BdBn(BwBBDBB BBBB B̍BBߖBBB"BB$BB"B+B5B>lBGBQ0BZBcBmBv\BBBBBBBBBNJBJBBB)BBBfB BBB#B+B3B;zBC!BJBR$BY~B`BgBnBuB|BXBB^BBBBBBdBBPBďBɩBΝBjBBzBBBBBBBFBBBBBiBBB B @BjByBkBBBBB*BBB8BdBzB |B!iB"CB# B#B$cB$B%zB%B&SB&B&B'3B'eB'B'B'B'B'B'B'B'B'B'pB'OB'+B'B&B&B&B&^B&5B&B%B%B%B%B%hB%MB%6B%$B%B% B%B%B% B%B%B%,B%>B%UB%pB%B%B%B%B&(B&XB&B&B&B'3B'pB'B'B(PB>B?B?|B?B@9B@B@BAJBABABBGBBBB0BBBB.BB|B FBBB%B.B8BA BJDBSsB\BeBo5BxBB=BB B{BBdBBYBBTBBPBBHBB8B"B,B5B>BHHBQBZBd;Bm|BvBBBB+B-B!BBBǪBeBBB2BBB`B BBB#B+B3B;OBBBJ{BQBYAB`|BgBnBuB|TBBBBPBBB}BIBBwBBB-BBB׎BB!B%BBBOBB B3B:BBBB B tB B BBBBB$BB"B|BBBB B B!B"B#SB#B$B%B%B%B&HB&B&B'B'1B'OB'dB'oB'sB'nB'dB'RB'B&B%B%B%B%B%bB%CB%"B%B$B$B$B$B$B$B$B$B$B$B$B% B%$B%@B%aB%B%B%B&B&4B&gB&B&B'B'RB'B'B(B(hB(B)B)PB)B)B*MB*B*B+[B+B,B,xB,B->B-B.B.pB.B/BB/B0B0B0B1^B1B2B>rB>B?+B?B?B@3B@B@BA*BAwBBBjBLBRBzBBB BBB'xB0sB9yBBBKBTB^Bg;Bp~ByBBrBB2BBBuBB\BBHBB6BB!BBB#nB,B69B?BHBRAB[BdBnBw8B`B|BBBB}B]B0BBЧBLBBbBB2B}B BBB#B+B3B;DBBBJfBQBY"B`XBgtBnsBuVB|BBQBBB4B@B*BBBBwBñBBʹB|BBۄB߭BBBFBBFBBBBBkBBBB EB qBBtBMB BB;BB BPB~BBB B!iB"3B"B#B$(B$B%%B%B%B&5B&vB&B&B&B' B'B'B'B'B&B&B&B&B&B&hB&BB&B%B%B%B%xB%SB%2B%B$B$B$B$B$B$B$wB$qB$oB$pB$vB$B$B$B$B$B$B%B%&B%KB%sB%B%B%B&2B&jB&B&B' B'aB'B'B(4B(B(B)B)nB)B*B*lB*B+B+|B+B,8B,B,B-\B-B.&B.B.B/[B/B0.B0B1B1nB1B2FB2B3B3B3B4fB4B5AB5B6B6B6B7^B7B82B8B9B9mB9B::B:B;B;fB;B<(BJB>B>B?DB?B?B@,B'BBbB6B/BHBBBBvB PB)6B2)B;)BD4BMJBVjB_BhBrB{CBBB4BBBUBB'BϔBBqBBPBB+BBB$bB-B7B@tBIBSB\QBeBnBwBBB)B(BBBBBcBBٮB;BB!ByBB B BB$B+B3B;ZBBBJpBQBY!B`RBghBnbBu@B|BB+BBBBBBBSBB,BbBsB^B$BB&BOBOB,BBsBB+BSBYB=BBB+BB B BB BBBFBBFBBBB1B6B 'B!B!B"B#0B#B$NB$B%/B%B%B&B&PB&zB&B&B&B&B&B&B&B&B&zB&\B&:B&B%B%B%B%tB%LB%%B%B$B$B$B$B$cB$LB$8B$)B$B$B$B$B$B$ B$+B$:B$LB$cB$|B$B$B$B%B%+B%XB%B%B%B&$B&^B&B&B'B'^B'B'B(6B(B(B) B)rB)B*B*rB*B+$B+B+B,:B,B,B-\B-B."B.B.B/QB/B0B0B0B1VB1B2(B2B2B3cB3B46B4B5B5pB5B6@B6B7 B7sB7B8B=B=B>)B>rB>BBHBB˰BܙBBBBBB"XB+7B4"B=BFBO+BXCBaeBjBsB|B?BBB(BBBB&#B&B%B%B%B%oB%FB%B$B$B$B$B$eB$DB$"B$B#B#B#B#B#B#B#B#B#B#B#B#B#B$B$"B$@B$aB$B$B$B%B%0B%aB%B%B&B&AB&B&B'B'FB'B'B( B(lB(B) B)\B)B*B*ZB*B+ B+eB+B,B,zB,B-8B-B-B.[B.B/ B/B/B0LB0B1B1zB1B2CB2B3B3rB3B4:B4B5B5eB5B6)B6B6B7JB7B8B8bB8B9B9pB9B:B:rB:B;B;hB;B<BB%B$B$B$B$pB$HB$%B$B#B#B#B#B#rB#_B#QB#GB#@B#=B#>B#AB#IB#TB#bB#sB#B#B#B#B#B$B$DB$lB$B$B$B%*B%aB%B%B&B&NB&B&B'B'^B'B'B(=B(B(B)*B)|B)B*$B*zB*B+(B+B+B,7B,B,B-LB-B.B.hB.B/'B/B/B0GB0B1 B1iB1B2*B2B2B3HB3B4B4dB4B5B5yB5B6.B6B6B76B7B7B84B8B8B9&B9tB9B: B:RB:B:B; B;bBBBŃB*BBBtB BBaB'"B/B8BABJBSB\BeBnBwBBHBBBBCBBB+B}BB'B|BB%B wBBB(_B1B:BD#BMYBVB_BhBqBzBBBBBBB@BBʘB-B۳B(BBB!BOB iBpBcB%@B-B4BB5B5B63B6B6B7B7fB7B7B8=B8B8B9B9DB9BBBˌB BBBVBB}B!&B)B2B;tBDQBM9BV,B_)Bh0Bq?BzWBvBBBB4BpBBB;BքBBBeBBBCBB B* B3JBBsNB|TBRBEB-B BBBXBB˜B(BܥBBnBBBB(B&BB%B-B5MBB+B+B,>B,B,B-@B-B-B.DB.B.B/HB/B/B0JB0B0B1HB1B1B2AB2B2B32B3B3B4B4gB4B4B5AB5B5B6B6PB6B6B7 B7FB7~BBBBB@BB vBBB$+B,B5B>[BG-BP BXBaBjBsB|B B(BKBsBBB BCBBؽBB>BBBB=BzB"B+B5B>HBGqBPBYBbBkBtB}BBBBbB)BBB1BBEBݹBBnBBBBBBB&B.]B5B=BDBLRBSBZBaBhBoBvSB|BwBB%BMBXBBB BB9BBBBBBwBBPBiB]B*BBYBBBBBBBDBB"B dB B BBVBBB9BBBEBrBBB|BWB B B!~B"B"B#B#yB#B$ B$aB$B$B$B$B$B%B$B$B$B$B$B$B$fB$>B$B#B#B#B#^B#1B#B"B"B"B"hB"CB"$B"B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B"B" B";B"YB"zB"B"B"B#B#@B#nB#B#B$B$:B$rB$B$B%#B%bB%B%B&%B&iB&B&B'GBEBMBT:B[ZBb_BiJBpBvB}hBBBBBBBBKBBlBBBBBBхBBSBhBWB BBGBBBBBBBBBB 4B WB _BKBBBtBBiBBB,BBBDB1B BB B!/B!B"HB"B#$B#}B#B$B$BBBBB BBB B(zB0B7B?"BFBMBTB\Bc BiBpBwbB}BfBBBB BBB9BBB:BKB7BBѡBBeBtB_B$BBABBBBBBhBBvBB B ,B 1BBBBB B!tB!B"jB"B#'B#rB#B#B$ B$%B$8B$AB$BB$:B$,B$B#B#B#B#B#dB#6B#B"B"B"oB">B"B!B!B!B!\B!4B!B B B B B B vB gB \B UB PB NB NB RB XB bB mB |B B B B B B!B!"B!CB!fB!B!B!B"B"0B"^B"B"B"B#%B#[B#B#B$B$>B$zB$B$B%3B%sB%B%B&6B&yB&B'B'DB'B'B(B(YB(B(B)+B)qB)B)B*CB*B*B+B+XB+B+B,#B,fB,B,B-*B-iB-B-B.#B.^B.B.B/ B/BB/wB/B/B0B0>B0lB0B0BpBmBBBB B3BB&B.B7B?BHVBQ BYBbBk_Bt:B}B BBBBB BB.BFB`B|BBBBBB.B HB)`B2sB;BDBMBVB_BhBqpBzTB/BBBB8BBxBBȆBBZBBB%BGBXB VB@BB!B)B1$B8B@BGjBNBUB\BcBjBqfBx B~BBIBxBB|BOBBBBTBBÉBnB/BBCBڃBލBqB1BBFBBBBBBTBB[BBB B BBBpB BBBIBBBBBB|B@BB B!%B!B"B"|B"B#B#VB#B#B#B#B#B#B#B#B#B#B#nB#GB#B"B"B"B"XB"$B!B!B!B!WB!*B B B B xB SB 1B BBBBBBBBBBBBBBBBBBBB B +B GB eB B B B B!B!>B!iB!B!B!B" B"RB"B"B"B##B#ZB#B#B$B$@B${B$B$B%2B%pB%B%B&,B&lB&B&B',B'lB'B'B(,B(mB(B(B)+B)iB)B)B*$B*`B*B*B+B+MB+B+B+B,,B,`B,B,B,B-(B-WB-B-B-B.B.*B.NBBBBBBB8B!B)B2iB:BCzBLBTB]lBf'BnBwBBtB[BHB=B7B6B:BABLBYBiByBBBBBB"B+B4B=BFBOBXBaBjBsB|nB=BBBpBBB?BB4BҚBB:BrBBBB BBVB#B*B2AB9BABHhBOBVB]BdBktBr(BxB@BBB BBBBuBBgBBBBȲBlBBqBګBޯBBJBBTBBBBBBHBBFBBB B BBBEBB[BBBLBqBB{BcB7BBB HB B!VB!B"(B"{B"B"B#*B#MB#fB#tB#zB#vB#lB#YB#@B#!B"B"B"B"wB"DB"B!B!B!jB!4B B B B gB 5B BBBBlBMB2BBBBBBBBBBBBBBBBBBB)B@BXBsBBBBB B 7B ]B B B B!B!0B!^B!B!B!B""B"UB"B"B"B#*B#`B#B#B$B$AB$zB$B$B%'B%aB%B%B&B&IB&B&B&B'0B'iB'B'B(B(FB(}B(B(B)B)NB)B)B)B*B*@B*lB*B*B*B+B+9B+^B+B+B+BBBBB B5BrB%B.B6~B>BGvBPBXBaBBiBrB{nB9B BBBBBB…BB}B~BBBBB BBB%B.B7B@BI|BRiB[QBd2Bm BuB~BmB&BBzBBB$BÚBB[BܦBBB+B6B0B BBB$ZB+B3wB:BBBSBjBBBBBBB9B\BBBBB B JB uB B B B!+B![B!B!B!B"B"QB"B"B"B#B#QB#B#B#B$!B$UB$B$B$B%"B%UB%B%B%B&B&KB&{B&B&B'B'1B'\B'B'B'B'B(%B(JB(mB(B(B(B(B) B)#BqB'BB BBB!B*B2lB:BC/BKBT&B\BeKBmBvBOB BBBsBMB-BBBBBBBBBB BBB(}B1nB:[BCDBL)BU B]BfBoBxJBBBiB BB0BB'BŏBB8BvBBBBBBBfBB%B-JB4B<%BCqBJBQBXB_BfBmHBsBznBB%BVBjB_B7BBBBXBBBēBaB BҐBBBBBB%BBBBBBBDBB2B|BB B BBQBBBBbBBBBBBBBjBBB 8B B!B!zB!B" B"?B"iB"B"B"B"B"B"B"uB"WB"4B" B!B!B!sB!;B!B B B JB BBB_B'BBBBVB)BBBBByB]BEB0BB BBBBBBBBBBBBBBB&B8BKB`BvBBBBBBB;B\B~BBBBB9BaBBBB B 2B ^B B B B!B!>B!kB!B!B!B"!B"OB"|B"B"B#B#0B#\B#B#B#B$B$1B$YB$B$B$B$B%B%BcBxB~BtBYB ,BBB!:B(B07B7B>BFBM4BT:B[)BbBhBobBuB|[BBBBBBBLBB6B{BBBBBBBBBsBRB3BBBBBBBBBBvBnBhBdBaB`B`BbBfBjBrByBBBBBBBBBBBB.BCBYBpBBBBBBBB4BNBhBBBBBBB B:BSBmBBBBBBBB&B:BMB`BrBBBBBBBBBBBBBBDBBB%B-B5B=BEBMBUB^4Bf|BnBw0BB BB BB,BBgB B̶BeBBBBABB BwB3B#B,B5bB>BFBOzBX$B`BijBrBzB$BB$BBB_BBB:BkB֏BޥBBBBjB4B BB&B$B,B3pB:BABIBPBVB]BdBk+BqBx*B~BBBBBBFBBEBBBBBƐB:BB$BbBoBJBBBBSBBBuB@BBzBBBB/BBBE.BL-BSBYB`BgHBmBtEBzBBB BBB{BBBBB8B2B BBXBBBGBBB BB5BBBBBBB)BB BRB{BB |B TBBBDBBB[BBBBBzBEBBB8BB0BBB3BnBBBBBBBBBBUB#BBBlB&BBB?BBBGBBBPBBB`BBBB:BBBxB=BBBBeB5BBBBBeBAB BBBBBB{BfBQB?B.BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBB&B,B2B9B?BEBKBPBTBYB\B`BcBdBfBfBfBeBcBaB]BXBSBLBCB;B0B$BB BBBB'HB.B6B>NBFBMBUB]BeBmBuB~"BRBBBBpBB/BB B}BBvBB}BBB BB1B&B/HB7B@YBHBQ`BYBbYBjBs=B{B BfBBBJBBBBBBBBBBBDBB BBB"B*SB1B8B?BFBMBTB[wBb$BhBo8BuB{BB0B-BBByBBoBBBBBøBdBBXB՞BٿBݰBsBBBBB0B%BBBHBBB]BBB sB FB BB%BBB,BWBlBmBYB2BBBMBB]BB.BBBB#BABRBYBUBHB1BBBBBJBBBxB*BBB1BBB+BB~B+BBB0BBBJBBBzB:BBBBOBBBBB[B0BBBBBtBUB6BBBBBBBByBhBWBHB:B-B"BB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBuBhBZBKB:B(BBB|B%B-dB4BB&BBrBB4BbBoB]B*BBiBB0BhBBB lB 8B BBBmBBB!B1B,BBBBVBBBBfBBBPBBBBBBBBByBNBBBB]BBBrBBBlBBB[BBBOBBBFBBBSBBBuB0BBBnB2BBBBUB#BBBBnBDBBBBBBpBRB6BBBBBBBB~BlB\BLBB3B;'BBBJOBQBYBa|BiPBq2ByBBB(BABbBBBB8BBBBvBB1BBB ^BB0B&B/B7jB?BH5BPBXBaRBiBqBzHBBB BBEBL^BS"BYB`hBfBmTBsByBB BBBB BBBKBsB}BhB3BBiBBB?BBBBB;BBBBBBB)BB BRB|BB|B UB B BFBBB^BBBBBzBCBBB2BB&BBB BVBBBBBBBB_B4BBBBB "B B B B B B lB JB (B BB2"B9\B@BHBOmBVB^pBfBmBu^B}BBBBB|BxBBBģBBB B:BlBBBB\BBB'&B/jB7B?BH4BPtBXB`Bi$BqVByBBBBBBBB BBBѪBtB2BBB BB#BBB4B$nB+B2B9B@BG~BNGBTB[Bb"BhBnBu2B{^BpBjBHBBBHBBBIBeBbB@BBƞBBzBӶBBBߏB)BBB+B?B2BBBPBB#BaBBBuB FB B B"BBB'BQBeBdBOB&BBB;BBFBBB^BBBB BBBBBBBBNBBB~B,BB|BBBXBBB$BBTBBB"BBYBBBBBBnB-B B B rB 7B B B B XB $B B B B _B 2B B B B B ZB 2B B B B B uB QB /B BBBBBhBHB)B BBBBBrBTB6BBBBBBBaBBB"BBBBB~B\B9BBBBBBXB0BBBBBYB+BBB?BGBN8BUpB\BdBktBrBzgBBB4BBBfB6B BBBB׾BߺBBBBBBB(B DB(aB0B8B@BHBPBYBa%Bi9BqJByWB_BbB_BVBFB.BBBB|B7BBߎB'BB5BB B dBBB" B)#B0*B7B=BDBKBR1BXB_BBeBkBr8Bx\B~iB]B8BBB/BBB2BOBPB2BBÛB!B̆BBBBBB BmBBBBBpBBBBGBuBB~B[B B B VBB.BxBBBBBBmB&BB`BBVBB BPBBBBBBBBB|BLBBBB=BBB1BBiBBB$BBDBBdBBBBB>BBkBBBBBBB+BB|B'BBB4B B B QB B B ~B :B B B yB BBBͦBՁBeBOB=B2B+B(B )B,B3B%:B-DB5NB=XBEbBMlBUtB]zBe}Bm~Bu{B}tBhBXBAB%BBBBhB$BBBBB6BBBBBBLBrB$B+B2B9dB@4BFBMBT3BZBa"BgzBmBsByBBBBZBBpBBBGBWBIBBBlBB>BvBՍBلBXBByBBBBBBB;BBBVB{BBsBGB B B ,BBB9BeB{B|BiBBBBBZBBfBB1BBBBB)B3B0B$B BBBBMB BBkBBBRBBBBB0BBHBB^BByBBB#BBHBBwBBBLBBB4B B B .B B B 7B B B OB B B vB 1B B B iB )BBBqB6BBBBVBBBBBRB!BBBBcB4BBBBBWB,BBBBBZB0BBBBBcB9BBBBBiB>BBBBBfB9B BBBBPBBBBBUB!BBB|BDB BBN]BUPB\SBcfBjBqBxBIBB B~BBBBBdBBBӐBXB'BBBBB BsBbB"UB*HB2=B:3BB)BJBRBZBaBiBqByBBB_B4BBBBGBBǠB?BB^BBRBBBaB BBB B' B.B4B;BBqBIBOBV:B\BcBiNBoBuB{BB^BBBEBBBAB^B_BCB BBBDBKLBQBXFB^BdBk&BqFBwPB}BBBBB BBB=BgBuBgBBBBBEBBBB=BB]BXBcB_B%LB,*B2B9B@`BFBMBSBZWB`BfBmBsByB~BBhBBBB=BrBBBnB5BBkBB(BYBjB[B,BB^BBBBBBBBBB:B`BjBYB/BB B B B B$BPBgBiBVB/BBBGBBSBBBhBBBB BB BBBBBSBBBuBBBXBBB BBBB BBBBBBBB BB(B B :B B SB B tB B B 5B B jB BBEBBB0BBB*BBB/BBBBBBB^BBBB@BBBtB2BBBoB0BBBwB:BBBBMBBBBfB.BBBBLBBBBlB4BBBBSBBBBnB2BBBBFB BBBOBBBBNB BBB?BBBkB!BdBkBr^By8B BBB/BOB{BBBCBBBhBBXBBeBBB*B BsBB"B*{B2.B9BABIOBQBXB`tBh(BoBwB9BBB+BB_BB{BBzBBXBٺBB`BBBB'B 9B>B6B!B'B.B5|B<&BBBIEBOBVB\jBbBhBnBtBzBBLBBxBBBBBBBBtB+BBDBǣBBB BB۲BUBBBBBMB7BBB>BBB;BWBXB>B BB VB B BB BBBBBBBuB!BBCBB BvBBBBBBBHBBB\BBBzB0BBBYBBBBFBBBB@BBBBABBBBIB BBBUBBBBcB&BBBqB4BBB|B>BBBBCBBBB@BBBxB3BBBbBBBB>BBBXBlBs7ByBBBkB\BZBfB|BBBBJBΗBBJBB BBBB BB6B B(bB/B7B?9BFBN{BVB]Be]BlBtB|4BB`BB}BBBBvBBLBΪBBMBBBBB1BBE!BKBQBXEB^BdBjBpBvB|}BBrBBBBiB4BBB&BBBxBB BBBaBBnBBlBB]BBHBB.B B B B B wB B gB B aBBbBBlBB}BBB$BBHBBrB BBB$B,B3{B:BB]BIBQFBXB`2BgBoBvB~BsBBJBBBnBBBaBǥBBBBBeB~BBBB|B^B4BB"B)eB0B6B=BCBIBP/BVjB\BbBhBnBtzBzABBBBBBB@BNBCBBBBB{BBBBBB٨BDBBB8B>B%BBB#BBBB5B4BBBB,BB B eB B BBBBB>BBBB~BB6B|BBBBBBBBBBNB BBlBBBDBB_BBdBBZBBCBB%B B B uB B WB B :B B #BBBBBBBBBB*BBBBBaBBBBBIBB~BBBVBBB:BBB)BBxB!BBvB"BB|B+BBB:BBBOBBBjBBBB=BBB_BBBB:BBB^BBBB9BBB[BBBzB.BBBHBBB^BBBnBBBvB"BBxB BBoBBBBBBBWB BBBtBXBIBCBHBUBlBBBBB QBBB#%B*uB1B9B@yBGBO3BVB]BeRBlBtB{oBB%B|BBBkBBB/BdB˒BҹBBBBBBBB BxB8BB%B,,B2B92B?BEBLDBR~BXB^BdBjBpBvYB|BB6BBBMB|BBBtB?BBBB^BƠBBBҹBօB3BB1BvBBBeB!BBABBBB(BBBBbBBhB B B CB ^BfBXB5BBBYBBkBB8BBBBB,B3B-BBBBBdBBBuBBB@BBRBBPBB>BB B B B gB B ?B B B BBfBBLBB9BB0BB.BB4BB@BBTBBnBBB"BBLBB{BBBLBBB)BBlBBBYBBBNBBBLBBBOBBBYBBBhBBBzB,BBBCBBB[BBBsB'BBB?BBBVBBBjBBB|B,BBB7BBB=BBB=BBB5BBB%BBjBBBIBBCBBtB BBƝBmBGB,BBBBB.BFB fBBB!B)B0VB7B>BFBM]BTB[Bc6BjBqByBYBBB#BaBBBB+BPBpBψB֙BݢBBBBoBIBB BBBB!B(sB.B5mB;BB+BHsBNBTBZB`BfBlBrBx8B}BfBBABBBBBBB]BBBBBXBlB{B̄BӆBځBtB^B@BBBB hBBBPB$B+WB1B8(B>zBDBJBQBW%B]&BcBhBnBttBzBB!BBBB2B=B1B BBxBB}BBBBޱBB/B0BBBxBBjBBBBBBBQBBdBB B NB oB {B rBUB$BBBBBBvBB B>BbByBB~BnBQB)BBBsB$BBjBBBBBBB B }B B VB B %B B B TBBBBBTBB(BBBuBB^BBNBBFBBFBBLBBXBBlBBBBB5BB]BBB!BBTBBB*BBhB BBLBBB7BBB*BByB!BBtBBBrBBBsBBBwB#BB{B)BBB,BBB0BBB2BBB0BBB+BBzB!BBlBBBXBBBBjBBBBB~B^B1BBBlBBBVBBuBB{B B kB B JB B B B B EBB BjBB1BBB^BB0BB BzBB`BBMBBCBB?BBBBBLBB\BBrBBBBBBBBkBBB1BBeBBB;BBxBBB[BBBDBBB3BBB&BBuBBBnBBBiBBBfBBBaB BB]BBBWBBBMBBBABBB0BBwBBB[BBB9BBtBBߪBDBBBBB=BBB2BϝBBܗB%BB`B BB~B DBBBB&B-B4tB;cBBXBIQBPLBWJB^KBeLBlPBsTBzXB\B_BbBbB`B\BTBHB8B$B BBBۛBhB.BBBLBB BBBB$zB*B1*B7nB=BCBIBOBUB[BaBgrBm&BrBxYB}B>BBBBBBBB~BBBBiBBBBͯB|B,BؿB4BߋBBBBB)BB$BwBBBBB{B.BBJBBBBB iB yB tB [B .B BB3BB2BBB1BgBBBBBBB`B.BBB\BBB7BBOB B LB B 5B B B tB B 8BBBUBBBrBB3BBB[BB*BBBqBBVBBABB4BB.BB/BB6BBDBBWBBpBBB BBEBBpBBB8BBlBBBBBBBBB`BBBGBBB3BB}B"BBnBBBaBBBVBBBJBBB>BBB/BB{BBBhB BBPBBB3BBrBB߮BJBBށBBݴBLBBxBB BB?BnBʩBBGBݨBBB BB.BB rBBBB&VB- B3B:BABHyBOYBV=B]$Bd BjBqBxBBBB|BdBKB/BBBBęBhB2BB߲BhBBB[BB{B BtBB!AB'B-B4B:HB@iBF|BLBRsBXXB^,BcBiBoBBtBzLBB BKBwBBB|BPBBBCBBBZB„BƒBʇB`BBվBBBܨBBBBBBLBB.BtBBBBB@BBxBBQBBBB B B B B EB B|BBlBBBXBBBBBBBBYB"BBBABB~BB B B B B B B `B B *BBBFBBBWBBBnBB(BBBMBBBBB`BBBBB,BBBBBBBBBB$BB5BBLBBhBBBBBCBBnBBB8BBmB BBCBBB BB`BBBEBBB-BBtBBBaBBBOBBBBwBBBBBBBzBIBBBxBB B SB B hB B bB B EB B BzBB6BBBCBBBLBBB[BBBqBB5BBBkBBEBB&BBBBBxBBrBBrBByBBBBB#BBBBB#BBhB BBPBBB7BB|BBBbBBBEBB߆B&BBcBBݟBB@B,B B B }B B B %B B B 3B nB B B B B B B |B KB B B {B !B B TB B gB B ^BB=BB BiBBBuBBBpBBBgBBBfBBBlBB'BBBNBBBBBdBBFBB1BB"BBBBBBBB(BB7BBLBBfBBBBB:BBcBBB&BBWBBB&BB]BBB4BBoBBBKBBB)BBiBBߧBGBBކB%BBcBBܞBBDBJBP#BV:B\VBbxBhBnBtB{(B\BBBBCB~BBB3BnBBBBDBrBޜBBBBB(B2B 6B1B%BB B&B,B2dB8 B=BCvBIBNBTBYB^BdLBiBnBsByB~BBBBBKBBtBBNBBBBBBBĢBQBBgBBBJB_B[B;BBBBfBBBBBBGBBrBBABBBBBBBeBBBLBB8BBB B JB iB yB |B qB ZB 6B BBB6BBzB BBBBB}BBIBBBXBBBHBBB%BmBBBFBBB)BuBBBhBBBpBB+BBBUBB&BBBpBBTBBABB4BB.BB.BB4BB@BBQBBgBBBBB1BBVBB~BBߪBABBqB BݣB=BBrBB۩BDBB}BBٶBSBB،B)BBbBB֛B7BBnB BԤB?BBrB BңB;BBhBBВB&BϹBKBBlBB͉BB̡B,B˵B1B~BBBBB 8BB]BB"B(dB.&B3B9B?BE~BKhBQYBWOB]MBcOBiVBocBusB{BBBBBB5BXBzBBBBBB4BKB_BpB|BBBByBjB TB6BBB$B*nB0%B5B;uBA BFBLBQBVB\TBaBfBlBq6BvIB{LB@B#BBBdBBBBbBBBBBBBB}BB̠B B`B֚BټBB߭B}B3BB#BmBBBBBMBBBBvBBB#B2B,BBBBLBBnBBHBBBB=BTB^BZBHB*BBBB@BBB$BB:BB2BBBtBB/BBB(BuBBBOBBB BfBBB?BBB BnBBBjBBB{BB=BBBoBBFBB%BB BBBsBBkBBjBBnBByBBBBB*BBGBBgBBߋBB޳BIBBvB BܥB=BBpB BڥBABBxBBذBMBB׆B"BB]BBՕB2BBjBBӡB=BBqB BѥB>BBlBBϚB.BBWBBzB B̛B*B˸BCBBYBB2BhBB BXBB5BB%>B*B0pB6B;BABGBBM BRBXB^BdpBjYBpFBv8B|.B(B$B$B&B+B0B7B?BEBMBTBZB^B`B`B]BVBLB>B+BBBB BzBBBB"B(lB.B3B9FB>BDNBIBO,BTBYB_BdRBizBnBsBxB}BdB1BBB/BB*BBBB8BHBDB*BB³BUBBTBаBBB+B BBBbBB5BoBBBBQB BB4BBBDBsBBBB[B$BBzB BBBRBBB B(B9B;B1BBBBBEBBB6BBSBBQBB2BBBXBBBSBBB1BvBBBBBBBBTBBB,BwBBBfBBBkBB%BBBNBBBBBgBBKBB8BB,BB%BB'BB-BB:BBLBBbBBBBޞB0BBVBB܀BBۭBDBBuBB٩BCBByBBװBMBBֆB#BB]BBԖB4BBmB BҥBABBxBBЮBGBBzBBΩB@BBkBB̒B&B˸BHBBfBBB BȔBBHBfB BB B[B"B(B-B3B8B>BCBIPBNBTBZ[B`BeBkBqpBwBB}BBBBBBkBVBBB.BBBBBBկB۔BvBUB0BBBBpB 3BBBSB B&B,0B1B7BBBWB\BaBgBlBqBvBzBBB>BBwBBjBBBMBrBBBfB9BBÜB+BʤBBNB~BחBږB{BFBBBB@BkB|BsBPBBBTBB6BBBBBBBB[BBB%BBBTBBBB BBBBBBB@BBB?BBdBBhBBNBBBzBB'BwBBBTBBBB_BBB$BfBBB8B~BBB`BBBYBB BiBB*BBB]BB4BBBBBrBBdBB^BB^BBdBBpBB߂BBޚB&BݶBEBBhBBێB#BڸBNBB~BBدBIBB~BBֵBQBBՊB'BBbBBӜB:BBtBBѯBLBBЅB!BϽBXBB΍B'BBXBḂBB˴BHBBoBBɑB!BȯBYBCBHBNLBSBYB^BdBiBo BtBz,BB`BBBOBBB[B BBwB-BBəBNBBڶBgBBBjBBBMBB xBBB B#B(B.bB3B9B>oBCBHBN'BSPBXmB]BbBg~BlkBqKBvBzBBBBjBBQBBB1B]BzBBB}BdB>B BBB6BBsBBB BBB^BB BxBBBdBBB0BoBBB#B]BBBBLBBBBPBBB%BrBBBhBBBwBB9BBBlBBEBB&BBB߈BB~BBzBBBBۊBBښB%BٲB>BB^BBׂBB֪B@BBnBBԠB:BBpB BҪBGBBуB"BB`BBϠB@BB΀B"BBbBB̢BBBBˀBBʽB[BBɖB2BBhBBǜB4BBbBBŌB!BijBDBBdBB|BBB(LB-B1B6B;B@jBE_BJ^BOgBTzBYB^BcBiBnYBsBxB~9BBBLBBBBBpBB`BBYBBUBBRBBLBBABB,BB BvB B=BBB!@B&B+B1 B6@B;mB@BEBJBOBTBYB^BcBhZBm"BqBvB{+BBCBB!BzBBB$B;B@B5BBBBMBBdBB)BkB͘BЮBӭB֖BhB"BBLBBB?BFB3BBBfBBgBBB@B^BfBZB:BBBgBBBBSBBBBBݷB1BܮB,B۫B-BڰB6BټBEBBZBBvBB֖B)BռBQBB}BBӮBHBB~BBѷBUBBВB1BBqBBγBTBB͗B8BB|BBBaBBʤBDBBɅB$BBcBBǟBBBBB!BBBVBBBBBB~B?BBBBBBNBBBBB BBBBBB\BBBaBBBBBBqBB:BBBBBcBBӎB$BҽBVBBьB(BBbBBϠB?BB΁B"BBfBB̬BNBB˕B8BBB"BBiB BȮBPBBǓB4BBtBBŲBOBBĉB$BþBWBB‡BBBDBBgBBBBB;:B?BDVBHBMBRVBWB[B`BeBjxBogBt^By\B~cBpBBBBB B7BiBBBBRBBBB`B֦BB1BuBBB>B|BBB (BYBBBB$B*B/!B4.B94B>2BC)BHBLBQBVB[zB`:BdBiBn:BrBwVB{B@BBBBBSBBB>BKB1BBBPBBEBBBB&B)BBBBtBBB(BBBDBBBBBBBBBzB@BBBPBBBBBBtBBABBBHBBB"BcBBBBLBBBB BUBBBB7BtBBB/BsBBBPBBBIBBB[B߼B BކBBZBB8B۪BBږBBيBB؆BB׋BB֘B BժB6BBSBBvB BҞB4BBdBBЙB4BBoBBέBMBB͏B2BBxBB˿BcBBʭBRBBɜBBBBȌB1BB{BBBgB BŬBOBBĐB1BBoB BªBEBByBBB?BBhBBBBB4BDBI7BMBR6BVB[bB`BdBiqBn3BrBwB|BBzBlBcB`BbBkBxBBBBBBBBTBfBsB${B)~B.{B3sB8dB=NBB0BG BKBPBUmBZ&B^Bc|BhBlBq-BuBzB~wBBBPB}BBBBBBTBBBfBBnBB.BpBƠBɼBBϴBґBXB BڤB(BߖBB(BMBJB BBBBBB2BfBBBBjB:BBB8BB5BBB3BhBBBBBB~BUBBBB;BBqBBBBqBBCBBBNBBB,BmBBBBUBBBB#BVBBBB+BdBBBBYBBB+BwBBBmBB"BBBDBܪBB~BB]BBFBؽB7BײB0BֱB4BոB>BBPBBhBB҈BBѮBCBBqB BϤB@BBzBB͸BYBB̜B>BBˆB+BBvBBBhBBȷB^BBǭBTBBƢBIBBŖBBBBBIBfBuBvBkBRB,BBBvB$BB`BBwBBlBBBBBBRBBB2BtBBB%B[BBBB#BTBBBBBTBBBB?B}BBBLBBB8BގBBABܠBBdBB4B٠BB؀BBiBB]BBYBB]BBjBBB BћB,BоBQBB~BBίBJBB̈́B"BBcBB˦BJBBʓB9BBɆB-BB~B&BByB"BBuBBBrBBBmBBÿBgBBµB[BBBJBBB1BBrBBBJBB~BBBCBBhBBBXB\NB`BdBi@BmBrBvB{BB2BBrBBBBFB BBByBQB-BBBBоBթBڕB߂BqB`BNB=B,BBBB BBBB]B$5B) B-B2B7hB<&B@BEBJBBBSBBB6ByBBB*B_BBBB#BRBBBBBDByBBB&B`BBB#BkB޶BBWBܫBB_BڽBBكBBTBB/B֡BBՌBBԁBBӀBB҇BBіB"BЮB=BB`BBΉB B͹BSBB̌B*BBjB BʮBRBBɜBCBBȒB:BBǎB8BBƎB9BBőB=BBĕBABBÙBDBB›BFBBBCBBB;BBB,BBrBBBTBBB+BB^BBBBBABaBeBjBnPBrBvB{0BBBeBB]BBtB BBHBBBPBBBĂBEB BBןBlB:B BBBBPB!BBB BYB!BBB$iB)%B-B2B7B^BrBzBwBeBGBBBBDBBjBBQBBB/BWBlBoB`B=BBѽB_BBeBBBMBoByBlB7BBeBB8BBBBBBBBCBBB BBB=BBBBBBBBBBvB6BBB4BBXBBXBB7BBBRBBB7BzBBB,BaBBBB BNBzBBBB4BfBBB BDB}B߹BB>B݅BBBpBBBxBB9BםBBoBBLBԿB4BӬB'BҤB#BѤB(BЯB7BBNBBlBB͓B(BBZBBˑB.BBnBBɳBVBBȢBIBBǚBDBBƚBFBBşBLBBĨBWBBôBcBBBoBBBzB(BBB/BBB0BBB+BBxBBBeBBBEBBBBBLBBvBBkBoBsBwB{B"BZBBB=BBBhBBTBBYBBtB B¤BBBBЊB2BBދB;BBBRBBBnB!BB B5BBB 6B$B)~B.B2B7LB;B@gBDBIlBMBRXBVB[(B_BcBh#BlfBpBtBxB}BB%BB BBBBHBBB&BBBBBBKBnBB~BlBGBBBgBBnBB$B_BBBBoB)BB5BBB"BGBVBRB;BBBBBB&BBB5BpBBBBBBBBOBBBxBBBCBBHBB,BBBLBBB5ByBBB*B_BBBBBGBrBBBB!BPBBBB#B[BޔBBBSBۚBB3BلBB2B׎BBNBմBBԇBBfBBPBBDBBDBBLBB^BBxBB̛B0BB]BBʒB0BBnBBȲBVBBǢBJBBƝBHBBŠBNBBĪBYB BùBiBBB}B.BBBCBBBXB BBjBBBvB$BBB*BBB(BBvBBBbBBBCBB{BBBBBBuuBy_B}VBVB`BtBBBBB_BBBLBB BtBBUBBJBBOBBbBBBBB:BBeBBB (BBPBBrB!B%B*B.B3B7B< B@BDBIWBMBRBVlBZB_BcCBgzBkBoBsBxB| B BBBBBhB$BBuB BBBrBBBVBBBB¥BŏBgB-BBЀBBՈBB@B~BަBBBBoBBBBWBBBBBBBdBBBLBB;BBB(BXBzBBBBvBTB'BBBXBBB,BB7BBBBBCBBB0BtBBB'B\BBBBB?BhBBBBB:BgBBBB7BnBܥBB BdB٪BBCBוBBBB՟BBaBB/BҜB B|BBhBB`BBbBBnBB̃BBˢB4BB^BBɒB-BBjB BǮBRBBƞBFBBŚBFBBĠBOBBîB_BBBvB)BBBEBBBcBBBB5BBBQBBBiBBB|B+BBB4BBB4BBB(BBnBBBMBBBBBZB*BBBBBBBB B1B\BBBBLBBB?B͚BB\BB-BB B}BBfBBTBBEB B5BB"BB"B&xB*B/OB3B8BBwAB{9B(B BBB|B5BBBBBBBBBBĒB?BBÛBKBB­B`BBB{B1BBBTB BBzB2BBBZBBBB8BBB[BBBzB-BBBABBBMBBBNBBBBBBB(BBbBBBPBBBBaB=B#BB BBBB3BOBrBĚBBB4BrBٳBBABBB/BBB0BBB BBĉB1BBÆB3BBB@BBBYBBBzB1BBB[BBBBEBBBvB2BBBdBBBBMBBBwB.BBBOBBBhBBBuB"BBwBBBjB BBMBBBPBBB=BBBBQB+BBBBBBBBBB2BRBuBBBB&BZBBBB;B wBBB)BeB B$B)B-FB1yB5B9B>BB+BFOBJnBNBRBVBZB^BbBfBjBnBrtBvPBz!B}BBdBBBOBBbBBGBBBFBBBBBBBBB\BBȺBOBBGBҪBB6B`BwB|BlBGBBBaBB BWByBBBgB;BBBIBBPBBB_BBBBBBBBBBCBBBLBBvBB{BB^BB"BzBBB]BBBBFBwBBBBBCBgBBBBBB?BgBۑBڽBB!BXB׎BBBB;BBBHBBBBBBBcBBBNBB?BBB0BcBBBBBBiB>BBBuBBBMBBWBB@BB BbBBBJBBBB3BbBBBBB%BGBfBކBݥBBBB&BIBoBטBBB"BYBӎBBB;B~BBB_BͲB BfBB)BʐBBiBBPBBFBBHBBXBBrBBØB/BBeBBBHBBB?BBBIBBBbBBBBEBBB}BNBB&BEBIBMBQkBU4BXB\B`uBd,BgBkBo0BrBvjByB}B BBBjBB'BwBBB.BVBtBBBBtBVB*BBBXBBĆBByBB.BpBҢBBBBBܞBgBBBRBB9ByBBBB\B&BBBBB BoBBB9B_BvBB{BjBLB"BBB_BBB;BBHBB2BBBXBBB@BBBB)BXBBBBBB6BUBqB܏B۫BBBB&BHBnBՕBԿBBBUBъBоBB6BxBB BZB˯BBdBB)BȑBBmBBXBBPBBWBBjBBŠBBBNBBB+BBvBBBvB&BBB?BBBhB#BBB_B BBBjB/BBBBLBBBBrB=BBBBgB1BBBBZB"BBByB?BBBBNBBBBKBBBxB/BBBHBBBOBBBBB3BpBȷBB^BҽB$BٓBBBBBBBJBBB0BBB8B BB\BBBB"QB&B)B-B1SB5B8BBʙBB BLBhBuBpBZB3BBޱBTBBcBB&BTBXBIB'BBBSBBnBBFBBBB=BVBaB_BPB4B BBBLBBB,BB;BB'BBBNBBB7BxBBB BNByBBBBB%BBB]BxBړB٭BBBB"BCBgBӎBҷBBBLBρBεBB,BoB˷BBSBɨBB^BB&BƏBBnBB\BBYBBdBB|B BB6BBlB BBRBBBNBBB`BBBB>BBBwB8BBBBIBBBBlB7BBBBjB8BBBBrBBBBBB|BJBBBB|BHBBBBjB1BBB|BBBBF(BIBM^BPBTBXB[B_7BbBfBBiBmBBBBlBBBQBBTBB"BsB˶BBB&B,B"B BBۣBVBBBBrBBB-BBBBB.BBKBB'B|BBB#B=BIBHB:B BBBB BABE BHBL BOBSBVyBYB]bB`Bd?BgBk BnmBqBu BxrB{BBEBBBBB!B7BDBJBFB9B#BBBBfBBBhBBBBpBB(BoBʨBBBBBBBءBaBBݰB?BB&BBBBBBBlBBB4BBBiBBBB,B:B:B,BBBB|B2BBBBB(BBBBB?BBB(BiBBB B;BdBߊBެBBBBB5BLBcByB֎BեBԼBBB B+BMBrBΜBBB/BcBʗBBBRBǚBB:BŐBBJBïBB„BBiBB^BBcBBwBBB.BBdBBBKBBBKBBBcBBBBNBBBBZB!BBBBMBBBBBaB5B BBBBaB8BBBBBoBGBBBBBxBMB!BBBBjB:BBBBlB5BBBBHBBBB;BBBZB BڦB}B]BFB6B/B/B7BEB[BxBBBB$B\B BB!BkBB B^B"B& B)hB,B0$B3B6B:GB=BA BDoBGBK2BNBQBUNBXB\B_YBbBeBiKBlBoBsBvZByB|BBB?B[BqBBBBBqBYB9BBBB\B BBOBBfBBNBBBQBǍBɼBBBBBBղB|B8BBB B߃BBDBBBBBBcB BB+BB B`BBB B&B4B4B(BBBByB/BB}BBB'BBBBB=BBB%BfBBBB4B\BށBݢBBBB B"B8BKB_BsBԆBӛBұBBBBB;B`B̈B˴BBBOBȃBǼBB?BŇBB(BÀBB=BB BzBBcBB\BBfBB~BBB=BBxBBBhBBBsB'BBBRBBBBTBBBBxBEBBBBB\B1BBBBBjBDBBBBBBjBHB$BBBBBnBHB"BBBBBVB*BBBBnB:BBBB^B"BBB`BBBB?BBBBLB BBBBBBBBB B BBB>BeBB B#B'#B*[B-B0B4B7MB:B=BABDTBGBJBNBQ\BTBWB[B^VBaBdBgBk-Bn[BqBtBwBzB~BB,B6B:B9B0B!B BBBBiB,BBBABBtBBBBbBBB_BĜBBBBB BBBԯBrB'BBbBB_BBB_BBBBBgBBB/BB BcBBB B)B7B7B+BBBB{B2BBBBB*BBBBB>BBB$BeBBBB0BVBzBܚB۷BBBBB$B6BGBXBiB{BюBТBϷBBBB&BJBrBɞBBB9BnBŦBB*BsBBBmBB.BBBoBB[BBYBBfBBBBBLBBB2BBB6BBBSB BBBJBBBBfB2BBBBtBHBBBBBB_BBBBBBBlBFBBBBBtBEBBBByBABBBBJBBBxBfBBBXBBBB_B3B B B BBBBBBB"B%B(B+B.B2B5B8yBABDBGBKBN$BQFBTiBWBZB]B`BdBgBj7BmLBp^BsmBvxByB|BBBuBfBRB8BBBBBWBBBzB!BBTBBdBBMBBB_BBBB2BJBTBSBEB)BBBՄB2BB`BBSB޵BBIBzBBBB{B$BBBBBBtBBBB7BDBDB8BBBBB=BBB"BB2BBBBBDBBB(BgBBBB-BSBuBۓBڮBBBBBB!B/B>BKB[BkB{B΍B͢B̸BBB B0BWBǃBƴBBBRBÌBBBZBBBWBBBBB`BBPBBRBBdBBBBBWBBBGBBBTB BB}B;BBBBKBBBBBRB&BBBBBdBABBBBBBBjBOB4BBBBBBB|BbBHB,BBBBBB}B]B;BBBBBBVB*BBBBgB2BBBBBBBBBUBBpB BB SB BBrB4BBBBsB"NB%/B(B*B-B0B3B6B9BBBBB8BSB`B_BPB6BBBBRBBB4BBCBB.BBBPBBB0BnBߦBBB/BTBtBڐB٪BBBBBBBB'B2B>BKBXBgBxBˊBʟBɷBBBB;BgBĘBBB7BqBBB@BBB@BBBoBBQBBEBBKBBcBBB$BBcBBB]B BBuB.BBBjB.BBBBYB)BBBBB[B6BBBBBB~BdBJB2BBBBBBBBBlBWBBB,BBBBBBBBnBRB6BBBBBBlBEBBBBBbB.BBBBDBBIBB B B BBBBBBBB +B"B%B(FB+B-B0B3RB6B8B;B>BApBDKBG(BJBLBOBRBUBXmB[OB^2BaBcBfBiBlBoqBrLBu$BwBzB}BjB3BBBwB/BBB:BB{BBB-BB,BBBrBB#BoBBBB>BZBjBqBlB\BABBBЩB^BBՠB.BخB!BۄBB"B[BBBBBBhBBB BpBBB=BdB|BBBuBYB0BBBpBBBNBB[BBDBB BbBBB>BzBޱBBB5BXBvBِBبB׼BBBBBB BBB#B-B6BABNB]BoBȃBǙBƴBBBBFBwBBBBPBBB"BtBB&BBBXBB>BB7BBBBB^BBB(BBnBBBqB$BBBPBBBBaB,BBBBrBIB"BBBBB}BaBFB-BBBBBBBBBzBiBYBIB9B)BB BBBBBBBBxBcBMB4BBBBBBBeB@BBBBBhB6BBBBRBBB^BBByBBYB!B$RB&B)`B+B.B1B3B6]B9B;B>[BA BCBFtBI,BKBNBQbBT"BVBYB\fB_)BaBdBgpBj2BlBoBrpBu-BwBzB}VB BBgBBBXBBB$BB>BBBBB.BBB_BBBNBBBBB9BMBWBXBNB:BBB̾B~B2BBwBB֋BBkBBBVBމB߬BBBBB~BFBBSBBBFBxBBBBBBB`B)BBBBBBtBB|BBbBB&B|BBBSBގBBBB@BaB}BؖB׫BּBBBBBBBBB BBB B)B4BABQBdBzBēBðBBB$BTBBBB/BpBBBUBB BlBBABB+BB'BB7BBXBBB+BBvB"BBB:BBBrB6BBBBbB4B BBBBsBSB5BBBBBBBBBpB`BRBDB8B+BBB BBBBBBBBBBBB{BlB\BIB7B#BBBBBBBiBHB"BBBBzBIBBBBLBwBBB"$B$lB&B)B+kB-B02B2B5B7B9B<|B>BABDBFBI.BKBNXBPBSBV'BXB[dB^B`BcGBeBhBk.BmBprBsBuBxOBzB}BBBHBBfBBvBBxBBhBBDBB BfBB BQBBBB*BNBhB{BBBBoBTB0BBB̆B8BB{B BԐBBtBB'BlBܥBBBBBBBBlB!BB BVBBBBBBBBBBcBBBvBBB*BBBBBHBBB/BnBݦBBB.BQBoB؉BנBֲBBBBBBBBBBBBBBB BB!B0BABVBnBBBBB.BfBBB BLBBB4BBBOBB(BBBBBB*BBRBBB-BB~B-BBBQBBBB\B&BBBBoBHB$BBBBBByBdBPB>B-BBBBBBBBBBBBBBBBBBBBBBBwBnBdBXBKB>B.BB BBBBBBzBZB8BBBBBgB6BB#B%B'B*B,>B.hB0B2B5 B7NB9B;B>4B@BBBEDBGBJBLyBNBQWBSBVABXB[3B]B`-BbBe,BgBj.BlBo2BqBt5BvBy6B{B~3BB*BBBBBiBB:BBBXBBBLBBBBJBzBBBBBBB BBBBôBňBSBBBxBBϴBBBBBtBBB'BoBBBkBB0BB BBB}BBBBBHBBB.BBB8BBBfB(BBBBPB"BBBBBhBJB0BBBBBBBBBBBBB~ByBvBtBrBqBpBpBpBpBpBpBpBpBoBnBlBjBgBcB]BWBPBHB=B2B%BBBBBBBBxBYB5BBBBB_B.lB0^B2VB4UB6[B8gB:yBB@BBBE*BG\BIBKBNBPSBRBTBW2BYB[B^,B`BbBe:BgBiBlUBnBqBsxBuBx;BzB|B\BBBtBB&B|BB BnBBBCBBBB(BVBBBBBBBBBBBBBB^B(BBǡBQBB̔B&BϰB/BңB BlBBBFBvBۛBܵBBB߳BBoB:BBBCBB9BpBBBBBBBsBABBBdBBB&BB BBBVB߬BBDB݄BܽBBBFBiB؆BנBִBBBBBBBBBBBBBBBBBBBBBBBBB B;B[BBBBBKBBBBHBBBHBBB}BBgBBfBB{B BB@BBB-BBBBBBB|BAB BBByBPB*BBBBBB~BjBXBIBB@BBnBDbBF\BH[BJ`BLjBNzBPBRBTBVBYB[,B]WB_BaBcBfBhVBjBlBoBqEBsBuBxBzFB|B~BBHBBBB=BvBBBBGBuBBBB B(B@BSBaBlBpBpBjB^BLB4BBBBBVBBBxBBɻBNBB\BBEBҪBBVB֛BBB-BFBTBWBMB6BBBB]BBB,BBB!B8BABB݆BBB4BaBوBةBBBBBBBBB BBBBBBBBǾBƲBŧBĜBÔBŒBBBBBBBBBBBB&BQBBBB)BfBBBFBBB`BB:BB,BB5BBTBBB(BBzB*BBBTBBBBqBBBBBBBBtB\BHB6B(BBB BBBBBB BBB B*B5BBBOB^BlB|BBBBBBBBBB B.B=BJBVBaBmBuB}BBBBBBBB{BqBdBVBDB0BBBBBBNOBOBQBS.BTBVBXCBZB[B]B_UBa&BbBdBfBhBjvBl^BnHBp6Br&BtBv BxByB{B}BBBBBBBBBBBBBBBBBBBBtB\B@B!BBBB|BHBBBBFBBBJBBÄBBƢB&BɤBḂBBKBРBB1BlB՞BBBBBBBBBޙBbB BByBBB!BBBVBBBqBVB.BBBnBBBJBBUBB9BߝBBLBݘBBBPBB٨BBBBB#B,B3B6B5B1B*B"BB BBBBBƼBŬBĜBÍB€BtBjBaB\BYBYB]BeBqBBBBBB BSBBBB7B|BBBsBB8BBBB BBBB>BBvBBBsB&BBB[B BBBB^B8BBBBBBBB{BrBjBfBcBdBfBjBpBxBBBBBBBBBBB-BCBYBoBBBBBBB BB3BFBXBiBxBBBBBBBBBBBBBBBBxBcBJB.BBXBZvB[B]B_B`BbB^BxB֍B՜BԧBӭBҮBѬBЦBϜBΐB́BpB\BFB0BBBBBóBšBBjBTB@B/BBB BBBBBBB1BJBiBBBB'B_BBBBjBBB|BBTBBGBBRBBtBBBSBBBcBBBBhB5BBBBBvB\BEB2B#BBBBBBBBB!B.B>BNBbBwBBBBBBB3BRBrBBBBBB=B_BBBBBB%BDBaB}BBBBBB BB*B6BABJBOBRBSBPBJBBB6B&BBBn_BoBpBr3BsBtBv8BwBxBziB{B}IB~B:BB9BBDBB[BB{BBB:BBkBBBBBB&BB6BBB߆BB8B݄BBB;BiBّBزBBBBBBBBBBBB̺BˤBʌBrBVB9BBBBBBBjBOB6BB BBBBBBBBBBBB4BZBBBB,BcBBB9BBBOBB+BB"BB1BBXBBBABBBZBBBBnB?BBBBBBBmB_BUBMBIBHBKBPBYBdBqBBBBBBBB-BLBmBBBBB"BIBpBBBBB8B`BBBBB"BEBhBBBBBB B9BPBeBwBBBBBBBBBBBByByBz;B{cB|B}B~B;B~BBB^BB BdBB"BBBVBB1BBBBBuBBfBB\BBRBBIBB?BB3BB"BB B~BB]BB3BBB_BBBnBBB\BƢBB"BZBˎB̼BB B&B>BPBZB`B]BTBDB-BBBںBۄBFBBݯBWBBߌBBBBBBHBBBBLBsBBB~B/BBpBBBBvBB?BޖBB+BiB۠BBBB6BKBZBeBjBjBeB]BQBAB.BBBBBȦBDžBcB@BBBBBBpBPB2BBBBBBBBBBBBBBBB"BNBBBB.BnBBB]BB!BBBzBBBBBBB~BBݩB6B޾B?BߺB0BBBhBBBbBBBBHBnBBBBBBBBnBFBBBmBB,B}BBB>BnBܕB۷BBBBBBBBBҾBѤBЇBdB?BBBʻBɊBVB!BBıBxB>BBBBRBBBBrB>B BBBB^B;BBBBBBBBBBBBB9BgBBBBPBBB4BBB_BBMBBYBBBBBnB BBBZB$BBBBBhBSBBB6B/B,B.B3B=BKB]BrBBBBBB:BeBBBB-BdBBBBTBBBBZBBB)BoBBBBBBBBZBBB'BiBBB)BeBBBBGByBBBB-BTBvBBBBBBB BBBrBBB9BB|B%BB~B0BBBXBBBB^B&BBBBVB%BBBBoBDBBBBƙBnBDBBBB˔BfB7BBBϡBmB6BBBӅBEBBվBvB,BB،B8BBڃB#BۿBWBBzBBފB B߅BBlBB=BBBKBBB!B[BBBBBB"B(B(BBBBBBvB9BBB'BxBBB5BcB݊BܩBBBBBBBBԵBӜBҀB^B8BBB̲B~BHBBBƙB\BBBBZBBBBUBBBB`B'BBBB_B5BBBBBBBBBBBBBBB,BaBBBB\BBB[BB.BBBB/BB[BBBRBBBBKBBBBBBqB`BSBLBHBJBQB\BjB~BBBBBBBXBoBBBBBBB BB BBBB3BB[BBB,BBoBBûBcBBźBgBBBvB(BBʎBABB̪B^BBBzB-BBђBCBBӢBOBBեBMBBיB;BBzBBڬBBBBdBByBBހBBvBB]BB2BBBNBBBB BBΜB_BBBɗBOBBźBlBBBB0BBB@BBBXB BB}B8BBB|BEBBBBBlBNB6B%BBBBB*BAB_BBBB(BfBBB8BBBWBB@BBIBBpBBBcBBBB\B*BBBBBBBwBsBtB{BBBBBBB&BOB{BBBBNBBB BQBBB,ByBBBjBBBhBBBnBBByBB+BBB5BBB8BBB2BBBBiBBB>BBBB4BlBBBB$BIBjBBBB>BtBϭBB*BpBжBBNBѠBBIBҢBB[BӺBBԀBBMBյBB֋BBfBBCBشB%BٖBByBB]BB@BܰB BݐBBlBBEB߯BBBBHBB BgBBBqBBBcBBB9ByBBB&BXBBBBBB(B;BHBPBTBRBKB>B+BBBBBtB=BBBnBBBbBBBBB BUBkB{BނB݃B}BoB\BCB%BBBԩBvB>BBB΂BBBBIBBBHBBB4BBB BNBBBB6BhBBBB B&B@B B"B=B[B~BڤBBB'BXBیBBB6BtBܴBB7B|BB BTBޞBB7B߄BB"BrBBBbBBBSBBBABBB*BuBB BQBBB BaBBBBRBBBBBHBpBBBBB BB/B:BCBGBGBBB9B,BBBBBBpB>BBBB>BBB?BBuBBBBBBsBBBB BBBBڻBٗBnB?B BBӖBUBBB{B,BBʅB.BBzBBB`BBBABBB"BBfB BBXBBB^BBB~B;BBBBYB,BBBBBBBBBBBB B8BpBBB.BuBB BBBaBBbBBBBBoB"BBBfB4B BBBBBBBBBBBBBBBBBnBBBBBBBBBNBBB7BBB6BBBFBBBdBB*BBBVBB!BBBQBBB~BBDBBBbBBBsBBBrBBBZBBB(BfBBB B:BfBBBBBBBBBBBBBB$B:BTBoBBBBBB9BaBBBBB5BbBBBBBKByBBBB4BbBBBBB;BdBBBBBB8BUBpBBBBBBBBBBBBBBBBBB}B\B8BBBBxB;BBBjBBBiB BB6BBLBBIBB-BBBRBBB߷BޠB݃B_B5BBBטBYBBB҄B4BB΋B2BBxBBǵBQBBÄBBBKBBzBBBCBBzBBBYBBBNBBBaBBBB`B+BBBBB{BkBbB`BfBsBBBBB2BtBBB;BBBKBB.BB2BBXBBBLBBBBNB BBBBBBBBBBBBBB BHBtBBBBNBBBBcBBBTBBB]BBBzBBABBBvBBIBBBBBbBB:BBByBBJBBB{BB?BBBVBBBWBBB@BBB BGBBBBB8B\BB|B[B=B"B BBBBBBBBBBBBBBBBBBBBBBB BB$B2B@BNB\BiBvBBBBBBBBBBBBBBBBBBBBB|BgBOB4BBBBBBSB"BBBxB7BBB\B BBZBBB-BBLBBVBBJBB(BBBIBBB2BrBB^B3BBBړBRB BBuB"BBrBBγBPBBʂBBǫB=BB^BBzB BB%BBCBBfBBB$BBZBBB@BBBDBBBqB5BBBB{B\BCB2B(B$B*B6BLBiBBBB8ByBBBTBBBBBzBBB-BBwB(BBBhB7B BBBBBBBBBBBBB BHBtBBBBRBBB#BpBBBiBBB|BB?BB BtBBJBB&BBBvBBYBB=BB!BBBsBBPBB*BBBdBB,BBBFBBBHBBB.BtBBB.BcBBBBgB&BBBrBBBJBBTBB\BBfBBtBBBBB1BBZBBB/BB{B(BBBIB BBBnBEB%B BBBBBBB+BQBBBB>B~BBBxBBNBBIBBfBBBPBBBBNB BBBBBBBBBBBBBBBBnBBBBPBBB%BtBBBtBB/BBB[BB/BB B|BBaBBKBB8BB(BBBB BBBmBBWBB=BBBBB]BB(BBBDBBBDBBB&BhBBBBJBvB0BBuBBBnBBB}B1BBBXBBBBOBBBB[B!BBBxBAB BBBjB5BBBBbB-BBBBTBBBBqB6BBB~B=BBBtB.BBBOBBB^BBBWBBB8BBlBBB"BB4BB:BB1BBBBBTBBBiBB BVBBBBMBBBBB BBޫB[BBڬBMBBօBBӫB:BBNBBYBBZBBVBBNBBBBB6BB-BB(BB'BB.BB@BB\BBB!BBdB BBlB#BBBmBB̵B,BɠBBƅBBfBBFBB&BBByBBbBBRBBKBBOBB^BB~BBBNBBBIBBBxB>B BBBBBzBuBxBBBBB BDBBB BXBB BuBBeBBxBBBXBBBBKBBBBBBBBBBBBBB+BWBBBB:BBBBgBBBtBB8BB BwBBYBBDBB8BB3BB2BB7BB>BBGBBPBBXBB^BB`BB]BBUBBEBB+BBBsBB>BBBUBBBJBBBBSBBB#BBB`BB=BB"BBBBB|BBwBBwBB{BBBBBB B "B B 2B B CB B TB B fBBvBBB BBBB"BB(BB*BB'BBBBBBBqBBRBB,BBBbBB&BBB8BBB2BBBBVBBBBGB{BBBB$BFBbB{BBBBBBBBBjBB܃B BٌB BֆBBrBBTBB,B˗BBgBB2BÖBB`BB)BBB]BB0BB B}BBfBB]BBaBBvBBB6BB{B&BBBLBBBBBgBPB@B:BBBB^BBBtBB'B~BB)B{BBBiBBBFBBBBNBBBB0BcBBBBB4BUBtBBBBBBBBBBBBBBBBwB&BݡBBڌBBiBB:BҟBBaBBByBB-BņBB8BBBCBBBUBBBuBB?BBBBBmBBeBBnBBB BB^BBBfB!BBBzBRB1BBBBB BBBB BBBBBB[BB~B~|B~BB~B}B}B}B}B}B}B}B}B}B}B}B~B~-B~\B~B~B BQBBB>BBBRBBBBBlBBZBBTBBVBBbBBtBBBBB9BBZBB{B BB-BBKBBfBB|BBBBBBB BBBmBBGBBBtBB(B|BBBZBB0@B/jB.B-B,B,#B+UB*B)B(B(,B'fB&B%B%B$VB#B"B"B!WB BB BdBBB2BxBBBJBBBBdBBB6B{BBBIBBBBRB B B B OB B B B;BsBBBBFBvBBBB)BPBvBBBBBB0BFB[BlB}BBBBBBBBBBBpB\BFB,BBBBBuBEBBJBۯBBnBB"BxBB BpBBB[BǩBBBBŽBB'BuBBBdBB BbBBBtBB;BBB~BBjBBhBBzB BBABBB?BBB|BJBBBBBBBBBB)BZBBB BbBB BlBBOB~B~[B}B}B}3B|B|B|[B|%B{B{B{B{B{B{B{B{B{B{B{B{B|B|BB|vB|B|B}4B}~B}B~!B~yB~B8BBBtBB[BBNBBMBBWBBjBBBBB:BBbBBB%BBRBBBBBABBhBBBBB.BB>BBBBBB~BBBEBBBBeBBBVBBBbBB(BBBpBBdBBmBBB&BBmBBBBOBBBBBBBBBBBB#B_BBB.B}B~B~8B}B}B|B|/B{B{cB{ BzBzxBzBBOBBhBBB BBNBBBBBSBBB*BBdBBB6BBiBBB*BBNBBhBBwBB|BBtBB^BB8BBB^BB BYBBEBDBCBBBAxB@lB?`B>WB=OBB~BBBKBBB4BBBBBB BxBB`BB_BBwB BBLBBBaB#BBBB|BhB^B\BeBwBBBB'BoB~B}B}GB|B|B{vBzBzsBzByBy:BxBxBxVBxBwBwBwBwBwzBwrBwrBwyBwBwBwBwBxBx8BxnBxBxBy6ByByBz0BzBzB{XB{B|4B|B} B}B~B~B%BB;BB\BBBBBTBBB0BBsBBB[BBBCBBB(BBfBBB9BBhBBBBB3BBB=B<9B:B9|B8B6B5`B4B2B1CB/B.B-&B+B*fB)B'B&EB$B#B" B B[BBB0BBfBBB4BBcBBB &B B PBBvBBB(BBDBB]BBtBBB BBBBBBBBBBBBBuBB^BݜBۣB٩B׮BմBӸBѼBϿBBBBBBBBBB BB.BBBZBtBBBBB/B`BBBBRBBB@BBBaBBCBBABB\BBB?BBBnB:BBBBB~B}B|B{B{BzPByBxBxBwcBvBvBuxBtBtiBsBsBs BrBrxBr3BqBqBqBq{BqcBqTBqNBqOBqYBqjBqBqBqBqBr2BrnBrBrBsKBsBsBt^BtBu1BuBvBvBwBwBxBxBy:ByBzcBzB{B|:B|B}B~)B~B~B+BBB;BBBTBBBqB&BBBABBBUBBB\BBBRBBB1BBbBBBBBBBBBBiBB1BBplBnBm^BkBjRBhBgIBeBd@BbBa:B_B^5B\B[0BYBX.BVBU+BSBR*BPBO*BMBL*BJBI*BGBF,BDBC-BAB@.B>B=/B;B:1B8B72B5B42B2B12B/B.1B,B+0B)B(-B&B%*B#B"%B BBBBBBBB~BBpBBaB B OB BB{BBBTBBBfBB>BB2BBEBBxBBBBFBBBB~B}B|B{BzByBxBxBw\BvBuBu2BtBsBsJBrBr=BqBq\BpBpBpVBpBoBoBoBodBoOBoCBo@BoEBoRBofBoBoBoBpBp@BpBpBqBqjBqBr%BrBrBsgBsBtXBtBu\BuBvrBwBwBx0BxBykBzBzB{[B|B|B}bB~B~BzB/BBBWBBBB?BBBmB&BBBJBBBbBBBiBBBXBBB,BBRBBhBBlBB]BB9BBB{ ByfBwBvBt{BrBq5BoBmBlNBjBi BghBeBd$BbB`B_AB]B\BZ_BXBWBU~BSBR>BPBNBM]BKBJBH}BFBE=BCBAB@]B>B=B;|B9B8Bm5Bm4BmBB0BB BnBBB#BbB~B|B{By^BwBuBtBrYBpBnBmBkUBiBgBfBdRBbB`B_B]OB[BYBX BVLBTBRBQ BOJBMBKBJ BHHBFBDBCBAEB?B=B<B:BB8B6B5B3@B1~B/B-B,BBBBBOB!BBBBBBBBBBBBB B;BuBBBSBBBB~B}yB|BzBy6BwBvBuPBtBrBqBpBoBnBmBlBkBk*BjiBiBhBhEBgBfBfhBeBegBdBdBd=BcBcBcvBcIBc&Bc BbBbBbBc Bc!Bc@BchBcBcBdBdZBdBeBe`BeBf2BfBgBgBh$BhBi@BiBjrBkBkBlbBmBmBnyBo3BoBpBqvBr=BsBsBtBusBvFBwBwBxByBzzB{TB|.B} B}B~BBuBMB&BBBB{BLBBBBxBBVBT~BRBOBM`BKBHBFGBCBAB?2BBB^BBxBBBBB)BB6BB@BBGBBLBBNBBNBBMBBKBBHB|BzDBwBu@BrBpBJBHFBEBCRB@B>`B;B9sB6B4B2B/B-3B*B(UB%B#|B!BB@BBvBBBRB B B =BBB8BBBEBBBdBBBBWBBBBpBBKBHBFBCjB@B>B;YB8B5B3TB0B.B+^B(B&B#yB B>BB BwBBQBB 6B B$BBBBBB,BBFBBkBBB:BBB&BBCB{BոBB=B͆BB$B{BB6BBBvBBhBBpBBB-BBwB'BBBaB/BBBBBBBBBBB*B`B}B{Bz=BxBwBuvBsBr|BqBoBnXBm BkBjBitBhYBgJBfHBeQBdhBcBbBaBaGB`B_B_0B^B^B]}B]B\B\B;B9,B6dB3B0B.B+ZB(B%B#(B qBB BZBBBZB B BqBB:BBB~BBeBBZBB\BBkBBB BݹBB?BjBҙBBBABǂBBBgBBB~BBUBBEBBQBBxBBBiBBBBlBBBBBBBBB B)BPB}B{BzBxPBvBuBs~BqBp}Bo BmBlQBkBiBhBgeBfIBe9Bd5Bc>BbTBaxB`B_B_2B^|B]B]B\}B[B[jBZBZBZ+BYBYBYXBY(BYBXBXBXBXBXBYBY(BYUBYBYBZBZ`BZB[B[B[B\fB\B]jB]B^B_!B_B`eBaBaBbuBc0BcBdBe|BfHBgBgBhBiBjBk`BlDBm*BnBnBoBpBqBrBsBtBuBvBwwBxjBy]BzPB{AB|2B}"B~B~BBBBB{BYB4B BBB~BGB BBB:BBB:BBrBBBB&BEBaB{BߔBܪBٿBBBBBBB&B/B8B@BEBKBOBSBVBXBZB[B\B\B\B\B\B\BZBZBZBZBZBZB}[Bz\Bw^Bt`BqcBngBkkBhqBewBb~B_B\BYBVBSBPBMBJBGBE BB#B?;BBc,Bb(Ba0B`FB_iB^B]B]"B\lB[B[ BZmBYBYZBXBX{BXBWBWBWNBW BVBVBVBVBVBVBW BW/BW^BWBWBX BXrBXBY1BYBZBZB[ B[B\"B\B]TB]B^B_NB`B`BazBb=BcBcBdBewBfOBg+Bh BhBiBjBkBlBmBnsBoeBpYBqOBrEBsB`BBB B B?BvBBB1BwBBB`BBBoBB:BBBݍBBBBBBB#BEBnBBB BMBBB9BBBeBBQBB^BBB,BBBHBBBBBBtBrBzB}B{ByBxBv=BtBrBq2BoBnBlBkBiBhPBgBeBdBcVBb6Ba$B`B_&B^:B]\B\B[B[BZ`BYBXBX`BWBWNBVBVpBVBUBUBUFBUBTBTBTBTBTBTBUBU7BUhBUBUBV2BVBVBWJBWBX.BXBY0BYBZNBZB[B\.B\B]B^CB_B_B`BaUBb%BbBcBdBeBfrBgZBhCBi/BjBkBlBlBmBnBoBpBqBrBsBtBuBvBwBxByBzB{B|B}B~|BkBWB@B'B BBBBtBEBBBBVBBBlBBBLBBrB\BAB&BBBBBvBMB"BBBٗBeB3BBBɒBZB!BBBqB5BBB}B?BBBBDBBBBKB BBBVBB{BxBunBr6BoBkBhBebBb1B_B[BXBU{BRRBO*BLBHBEBBB?BB/BBBBBBBhBBBB(BBmBBBUBBBBBNBBbB{BxzBuBqBn*BjBgRBcB`B]BYBVWBRBOBLCBHBEBBFB>B;B8cB5B1B.B+bB(*B$B!BBrBNB-BBB BBBBBBBBBB0BTB~BBBB^BdB0BBBͻBʡBǎBĂB}BBBBBBB,BdBBB?BBBhBB\BBuBBBaBBBBB~`B|LBzBBxDBvPBthBrBpBnBm9BkBiBhQBfBeHBcBbrBaB_B^B]^B\:B[#BZBYBX1BWQBV~BUBUBTNBSBRBRNBQBQ=BPBPaBPBOBOwBOBBOBNBNBNBNBNBO BO.BO\BOBOBPBPqBPBQ2BQBRBRBSBSBT:BTBUxBV"BVBWBXDBYBYBZB[kB\BB]B]B^B_B`BaBbBcBdBe}BfzBgyBhzBi}BjBkBlBmBnBoBpBqBrBsBtBuBvBwBxByBzB{B|B}B~BBBtBXB8BBBBBOBBBB2BB~BB BXBB{BBB BB"BBBBBBBuBBWBB4BڠB BvBBGBȯBB|BBHBBBvBBABB BrBBABBB|BBTBB}0ByBvBrBnBktBgBdiB`B]fBYBVnBRBOBL BHBE/BAB>^B:B7B4>B0B-B*@B&B#B dB"BBByBJB B BBBBBBBBBBBBBB$BTBHBBBЋBZB0BBBBBBBBB B/B\BBBBeBB BBBBBB5BBBGB B~B|BzBxBvBtBrBpBnBm"BkdBiBh BfqBdBcbBaB`B_,B]B\B[jBZDBY,BX"BW%BV6BUVBTBSBS BRRBQBPBPPBOBO?BNBNdBN BMBM|BMFBMBMBLBLBLBLBMBM>BMmBMBMBN5BNBNBOOBOBP7BPBQ@BQBRfBSBSBTVBU BUBVBWFBXBXBYBZB[nB\QB]8B^#B_B`B`BaBbBcBdBeBfBgBiBjBkBl$Bm0Bn;BoIBpUBq`BrlBsvBtBuBvBwBxByBzB{B|B}B~rBaBLB3BBBBBsB>BBBzB-BB~B ================================================ FILE: docs/Makefile ================================================ # Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* rm -rf api/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/sep.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sep.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/sep" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/sep" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." latexpdfja: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." ================================================ FILE: docs/apertures.rst ================================================ Aperture photometry =================== There are four aperture functions available: ================== ========================= Function Sums data within... ================== ========================= `sep.sum_circle` circle(s) `sep.sum_circann` circular annulus/annuli `sep.sum_ellipse` ellipse(s) `sep.sum_ellipann` elliptical annulus/annuli ================== ========================= The follow examples demonstrate options for circular aperture photometry. The other functions behave similarly. .. code-block:: python # sum flux in circles of radius=3.0 flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0) # x, y and r can be arrays and obey numpy broadcasting rules. # Here, r is an array instead of a single number: flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0 * np.ones(len(objs))) # use a different subpixel sampling (default is 5; 0 means "exact") flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0, subpix=0) **Error calculation** In the default modes illustrated above, the uncertainty ``fluxerr`` is not calculated and values of 0 are simply returned. The uncertainty can be flexibly and efficiently calculated, depending on the characteristics of your data. The presence of an ``err`` or ``var`` keyword indicates a per-pixel noise, while the presense of a ``gain`` keyword indicates that the Poisson uncertainty on the total sum should be included. Some illustrative examples: .. code-block:: python # Specify a per-pixel "background" error and a gain. This is suitable # when the data have been background subtracted. flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0, err=bkg.globalrms, gain=1.0) # Variance can be passed instead of error, with identical results. flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0, var=bkg.globalrms**2, gain=1.0) # Error or variance can be arrays, indicating that the background error # is variable. bkgrms = bkg.rms() # array, same shape as data flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0, err=bkgrms, gain=1.0) # If your uncertainty array already includes Poisson noise from the object, # leave gain as None (default): flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0, err=error_array) # If your data represent raw counts (it is not background-subtracted), # set only gain to get the poisson error: flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0, gain=1.0) The error is calculated as .. math:: \sigma_F^2 = \sum_i \sigma_i^2 + F/g where the sum is over pixels in the aperture, :math:`\sigma_i` is the noise in each pixel, :math:`F` is the sum in the aperture and :math:`g` is the gain. The last term is not added if ``gain`` is `None`. **Masking** Apply a mask (same shape as data). Pixels where the mask is True are "corrected" to the average value within the aperture. .. code-block:: python flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0, mask=mask) **Local background subtraction** The `~sep.sum_circle` and `~sep.sum_ellipse` functions have options for performing local background subtraction. For example, to subtract the background calculated in an annulus between 6 and 8 pixel radius: .. code-block:: python flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0, mask=mask, bkgann=(6., 8.)) Pixels in the background annulus are not subsampled and any masked pixels in the annulus are completely igored rather than corrected. The inner and outer radii can also be arrays. The error in the background is included in the reported error. Equivalent of FLUX_AUTO (e.g., MAG_AUTO) in Source Extractor ------------------------------------------------------------ This is a two-step process. First we calculate the Kron radius for each object, then we perform elliptical aperture photometry within that radius: .. code-block:: python kronrad, krflag = sep.kron_radius(data, x, y, a, b, theta, 6.0) flux, fluxerr, flag = sep.sum_ellipse(data, x, y, a, b, theta, 2.5*kronrad, subpix=1) flag |= krflag # combine flags into 'flag' This specific example is the equilvalent of setting ``PHOT_AUTOPARAMS 2.5, 0.0`` in Source Extractor (note the 2.5 in the argument to ``sep.sum_ellipse``). The second Source Extractor parameter is a minimum diameter. To replicate Source Extractor behavior for non-zero values of the minimum diameter, one would put in logic to use circular aperture photometry if the Kron radius is too small. For example: .. code-block:: python r_min = 1.75 # minimum diameter = 3.5 use_circle = kronrad * np.sqrt(a * b) < r_min cflux, cfluxerr, cflag = sep.sum_circle(data, x[use_circle], y[use_circle], r_min, subpix=1) flux[use_circle] = cflux fluxerr[use_circle] = cfluxerr flag[use_circle] = cflag .. warning:: Caution should be used when calculating Kron radii in crowded fields. In almost all cases, one would want to pass in a segmentation map to mask out nearby objects, as described below in :ref:`segmentation masking`. Equivalent of FLUX_RADIUS in Source Extractor --------------------------------------------- In Source Extractor, the FLUX_RADIUS parameter gives the radius of a circle enclosing a desired fraction of the total flux. For example, with the setting ``PHOT_FLUXFRAC 0.5``, FLUX_RADIUS will give the radius of a circle containing half the "total flux" of the object. For the definition of "total flux", Source Extractor uses its measurement of FLUX_AUTO, which is taken through an elliptical aperture (see above). Thus, with the setting ``PHOT_FLUXFRAC 1.0``, you would find the circle containing the same flux as whatever ellipse Source Extractor used for ``FLUX_AUTO``. Given a previous calculation of ``flux`` as above, calculate the radius for a flux fraction of 0.5: .. code-block:: python r, flag = sep.flux_radius(data, objs['x'], objs['y'], 6.*objs['a'], 0.5, normflux=flux, subpix=5) And for multiple flux fractions: .. code-block:: python r, flag = sep.flux_radius(data, objs['x'], objs['y'], 6.*objs['a'], [0.5, 0.6], normflux=flux, subpix=5) Equivalent of XWIN_IMAGE, YWIN_IMAGE in Source Extractor -------------------------------------------------------- Source Extractor's XWIN_IMAGE, YWIN_IMAGE parameters can be used for more accurate object centroids than the default X_IMAGE, Y_IMAGE. Here, the ``winpos`` function provides this behavior. To match Source Extractor exactly, the right ``sig`` parameter (giving a description of the effective width) must be used for each object. Source Extractor uses ``2. / 2.35 * (half-light radius)`` where the half-light radius is calculated using ``flux_radius`` with a fraction of 0.5 and a normalizing flux of ``FLUX_AUTO``. The equivalent here is: .. code-block:: python sig = 2. / 2.35 * r # r from sep.flux_radius() above, with fluxfrac = 0.5 xwin, ywin, flag = sep.winpos(data, objs['x'], objs['y'], sig) .. _segmentation masking: Segmentation-masked image measurements -------------------------------------- SourceExtractor provides a mechanism for measuring the "AUTO" and "FLUX_RADIUS" parameters for a given object including a mask for neighboring sources. In addition to the mask, setting the SourceExtractor parameter ``MASK_TYPE=CORRECT`` further fills the masked pixels of a given source with "good" pixel values reflected opposite of the masked pixels. The ``SEP`` photometry and measurement functions provide an option for simple masking without reflection or subtracting neighbor flux. For example, using a segmentation array provided by ``sep.extract``, we can compute the masked ``flux_radius`` that could otherwise be artificially large due to flux from nearby sources: .. code-block:: python # list of object id numbers that correspond to the segments seg_id = np.arange(1, len(objs)+1, dtype=np.int32) r, flag = sep.flux_radius(data, objs['x'], objs['y'], 6.*objs['a'], 0.5, seg_id=seg_id, seg=seg, normflux=flux, subpix=5) To enforce that a given measurement **only** includes pixels within a segment, provide negative values in the ``seg_id`` list. Otherwise the mask for a given object will be pixels with ``(seg == 0) | (seg_id == id_i)``. The following functions include the segmentation masking: ``sum_circle``, ``sum_circann``, ``sum_ellipse``, ``sum_ellipann``, ``flux_radius`` , and ``kron_radius`` (``winpos`` **currently does not**). Masking image regions --------------------- Create a boolean array with elliptical regions set to True: .. code-block:: python mask = np.zeros(data.shape, dtype=np.bool) sep.mask_ellipse(mask, objs['x'], objs['y'], obs['a'], objs['b'], objs['theta'], r=3.) ================================================ FILE: docs/changelogs/changelog.rst ================================================ .. _changelog: Changelog ========= Upgrading From kbarbary/sep --------------------------- .. toctree:: :maxdepth: 2 changes_to_c_api Full Changelog -------------- .. toctree:: :maxdepth: 2 new_changes original_changes ================================================ FILE: docs/changelogs/changes_to_c_api.rst ================================================ Changes to the C API ==================== This page details cumulative changes to the C API between v1.2.1 and v1.4.0, or since this package was forked from `kbarbary/sep `_. Almost all changes to the public API are to integer parameters, many of which have been changed from ``int`` to ``int64_t``, to fix problems which may arise with extremely large arrays. The other change of note is to the ``sep_image`` struct, which enables the user to pass an existing segmentation map, and re-extract all morphological and photometric quantities on a different image. All changes here are transparent to users of the Python interface. .. c:struct:: sep_image - Three new parameters have been added: .. c:var:: int64_t * segids The unique ids in an existing segmentation map. .. c:var:: int64_t * idcounts The number of occurrences of each unique id in an existing segmentation map. .. c:var:: int64_t numids The total number of unique ids in an existing segmentation map. - The type of ``w`` and ``h`` has changed from ``int`` to ``int64_t``. .. c:struct:: sep_bkg - The type of the following parameters has changed from ``int`` to ``int64_t``: ``w``, ``h``, ``bw``, ``bh``, ``nx``, ``ny``, and ``n``. .. c:struct:: sep_catalog - The type of the following parameters has changed from ``int`` to ``int64_t``: ``npix``, ``tnpix``, ``xmin``, ``xmax``, ``ymin``, ``ymax``, ``xcpeak``, ``ycpeak``, ``xpeak``, ``ypeak``, ``pix``, and ``objectspix``. .. c:function:: int sep_background() - The type of the following parameters has changed from ``int`` to ``int64_t``: ``bw``, ``bh``, ``fw``, and ``fh``. .. c:function:: float sep_bkg_pix() - The type of ``x`` and ``y`` has changed from ``int`` to ``int64_t``. .. c:function:: int sep_bkg_line() - The type of ``y`` has changed from ``int`` to ``int64_t``. .. c:function:: int sep_bkg_subline() - The type of ``y`` has changed from ``int`` to ``int64_t``. .. c:function:: int sep_bkg_rmsline() - The type of ``y`` has changed from ``int`` to ``int64_t``. .. c:function:: int sep_extract() - The type of ``convw`` and ``convh`` has changed from ``int`` to ``int64_t``. .. c:function:: int sep_sum_circann_multi() - The type of ``n`` has changed from ``int`` to ``int64_t``. .. c:function:: int sep_flux_radius() - The type of ``n`` has changed from ``int`` to ``int64_t``. .. c:function:: void sep_set_ellipse() - The type of ``w`` and ``h`` has changed from ``int`` to ``int64_t``. ================================================ FILE: docs/changelogs/new_changes.rst ================================================ New Changelog ============= **Full Changelog** .. include:: ../../CHANGES.md :parser: myst_parser.sphinx_ ================================================ FILE: docs/changelogs/original_changes.md ================================================ Original Changelog ================== This is the original changelog from [kbarbary/sep](https://github.com/kbarbary/sep), copied here for posterity. v1.2.1 (1 June 2022) -------------------- * Same as v1.2.0 but with new wheels for Python 3.10 and AArch64. v1.2.0 (1 May 2021) ------------------- * Changed `numpy.float` and `numpy.int` types for deprecations in numpy 1.20 (#96). * Make it possible to safely invoke C library from multiple threads on independent inputs. Global config functions such as `set_sub_object_limit()` and `set_extract_pixstack()` still configure global params (once for all threads), while other functions will retain their data in thread-local storages, so they can be invoked from multiple threads as long as they work on independent structures. Library compilation will now require a C11 compatible compiler, which should be nowadays available on all supported platforms. * Mark some pointer parameters with `const *`. This is a backward-compatible change, but makes it easier to extract constants that can be safely shared between multiple threads and/or invocations. v1.1.1 (6 January 2021) ----------------------- * Same as v1.1.0 but with wheels built and uploaded to PyPI. Please report if you have problems with wheels. v1.1.0 (3 January 2021) ----------------------- * Add segmentation masking to the photometry and kron/auto functions (#69). * Add functions `sep.set_sub_object_limit(limit)` and `sep.get_sub_object_limit()` for modifying and retrieving the sub-object deblending limit. Previously this parameter was hard-coded to 1024. 1024 is now the default value. * This and future versions are now Python 3 only. Python 2 is no longer supported. * Modernize setup.py with pyproject.toml v1.0.3 (12 June 2018) --------------------- * Fix double-free bug in sep_extract() arising when an error status occurs and convolution is on. (#56) * Work around numpy dependency in setup. (#59) v1.0.2 (19 September 2017) -------------------------- * Fix makefile so that `make install` works on OS X for the C library. Python module and C code are unchanged. v1.0.1 (10 July 2017) --------------------- * Fix bug when using masked filter and noise array where objects with member pixels at end of image (maximum y coordinate) were erroneously missed. v1.0.0 (30 September 2016) -------------------------- * Remove features deprecated in previous versions. * Fix bug in Background.rms() giving nonsensical results. v0.6.0 (25 August 2016) ----------------------- * New, more coherent C API. This change should be transparent to users of the Python module. * Add variance uncertainty parameters `errx2`, `erry2` and `errxy` to output of `sep.extract()`. * Add a minimum sigma to `sep.winpos()` to match Source Extractor behavior. * Fix use of boolean masks in `sep.kron_radius()`. Formerly, using a boolean mask resulted in nonsense results. * Fix segfault in `Background.back()` when box size is same as image size. * Fix bug in creating long error messages on Python 3. v0.5.2 (4 January 2016) ----------------------- Adds OS X and Windows support. v0.5.1 (30 November 2015) ------------------------- Bugfix release for problem in setup.py in packaged code. v0.5.0 (22 November 2015) ------------------------- * `sep.extract()` now uses a more correct matched filter algorithm in the presence of a noise array, rather than simple convolution. The `conv` keyword has been changed to `filter_kernel` to reflect this, and a `filter_type` keyword has been added to allow selecting the old behavior of simple convolution. * `sep.extract()` now accepts a `mask` keyword argument. * `sep.extract()` can now return a segmentation map. * Special methods added to allow `data - bkg` and `np.array(bkg)` where `bkg` is a Background object. v0.4.1 (10 November 2015) ------------------------- Bugfix release, fixing error estimate in `sep.sum_circle` and `sep.sum_ellipse` when `bkgann` keyword argument is given. v0.4.0 (1 June 2015) -------------------- * New `sep.winpos()` function. v0.3.0 (23 February 2015) ------------------------- * New `sep.flux_radius()` function. v0.2.0 (13 December 2014) ------------------------- * **[breaking change]** `theta` field in `extract()` output is now in radians rather than degrees, for compatibility with new ellipse aperture functions. * **[deprecation]** Change `mask_ellipse()` parameters from ellipse coefficients to ellipse axes and position angle, to match aperture functions. (Old behavior still works as well.) * **[deprecation]** Change `apercirc()` to `sum_circle()`, to match new aperture functions. (Old name, `apercirc()`, still works.) * Add `sum_circann()`, `sum_ellipse()`, `sum_ellipann()`, `kron_radius()`, `ellipse_coeffs()`, `ellipse_axes()` functions. * Exact mode aperture photometery in all functions, with `subpix=0`. * Enable variable thresholding in `sep.extract`. [#11] * Fix bug in background masking. This bug impacted masking in all functions that used masking. Also affected C library. * More detail in error messages coming from within the C library. More helpful error message for non-native byteorder arrays. * Add ability to change pixel stack size used in `extract()`, with `set_extract_pixstack()` function v0.1.0 (11 August 2014) ----------------------- This is the first official release. ================================================ FILE: docs/conf.py ================================================ # -*- coding: utf-8 -*- # # seppy documentation build configuration file, created by # sphinx-quickstart on Mon Jul 7 18:52:28 2014. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. """The sphinx configuration file for the SEP documentation.""" import os import sys import sep try: from sphinx_astropy.conf.v2 import * except ImportError: print( "ERROR: the documentation requires the sphinx-astropy package to be installed." ) sys.exit(1) # generate api directory if it doesn't already exist if not os.path.exists("api"): os.mkdir("api") # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) # sys.path.append(os.path.abspath('ext')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # intersphinx_mapping = { # "python": ("http://docs.python.org/", None), # "numpy": ("http://docs.scipy.org/doc/numpy/", None), # } # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ "sphinx.ext.autodoc", "sphinx.ext.autosummary", "sphinx.ext.intersphinx", "sphinx.ext.mathjax", "numpydoc", "nbsphinx", "IPython.sphinxext.ipython_console_highlighting", "sphinx_copybutton", "myst_parser", ] numpydoc_show_class_members = False autosummary_generate = ["reference.rst"] autoclass_content = "class" autodoc_default_flags = ["members", "no-special-members"] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # The suffix of source filenames. source_suffix = ".rst" # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = "index" # General information about the project. project = "sep" copyright = "2014-2024, Peter Watson and contributors" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # THe short X.Y version. version = ".".join(sep.__version__.split(".")[0:2]) # The full version, including alpha/beta/rc tags. release = sep.__version__ html_title = f"{project} {release.split('+')[0]} documentation" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ["_build", "**.ipynb_checkpoints"] # The reST default role (used for this markup: `text`) to use for all # documents. default_role = "autolink" # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = "pydata_sphinx_theme" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = [] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = "sepdoc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ("index", "sep.tex", "sep Documentation", "Peter Watson", "manual"), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [("index", "sep", "sep Documentation", ["Peter Watson"], 1)] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ( "index", "sep", "sep Documentation", "Peter Watson", "sep", "One line description of project.", "Miscellaneous", ), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False ================================================ FILE: docs/filter.rst ================================================ Matched Filter (Convolution) ============================ For source detection, SEP supports using a matched filter, which can give the optimal detection signal-to-noise for objects with some known shape. This is controlled using the ``filter_kernel`` keyword in `sep.extract`. For example: .. code-block:: python import sep kernel = np.array([[1., 2., 3., 2., 1.], [2., 3., 5., 3., 2.], [3., 5., 8., 5., 3.], [2., 3., 5., 3., 2.], [1., 2., 3., 2., 1.]]) objects = sep.extract(data, thresh, filter_kernel=kernel) If ``filter_kernel`` is not specified, a default 3-by-3 kernel is used. To disable filtering entirely, specify ``filter_kernel=None``. What array should be used for ``filter_kernel``? It should be approximately the shape of the objects you are trying to detect. For example, to optimize for the detection of point sources, ``filter_kernel`` should be set to shape of the point spread function (PSF) in the data. For galaxy detection, a larger kernel could be used. In practice, anything that is roughly the shape of the desired object works well since the main goal is to negate the effects of background noise, and a reasonable estimate is good enough. Correct treatment in the presence of variable noise --------------------------------------------------- In Source Extractor, the matched filter is implemented assuming there is equal noise across all pixels in the kernel. The matched filter then simplifies to a convolution of the data with the kernel. In `sep.extract`, this is also the behavior when there is constant noise (when ``err`` is not specified). In the presence of independent noise on each pixel, SEP uses a full matched filter implementation that correctly accounts for the noise in each pixel. This is not available in Source Extractor. Some benefits of this method are that detector sensitivity can be taken into account and edge effects are handled gracefully. For example, suppose we have an image with noise that is higher in one region than another. This can often occur when coadding images: .. code-block:: python # create a small image with higher noise in the upper left n = 16 X, Y = np.meshgrid(np.arange(n), np.arange(n)) mask = Y > X error = np.ones((n, n)) error[mask] = 4.0 data = error * np.random.normal(size=(n, n)) # add source to middle of data source = 3.0 * np.array([[1., 2., 1.], [2., 4., 2.], [1., 2., 1.]]) m = n // 2 - 1 data[m:m+3, m:m+3] += source plt.imshow(data, interpolation='nearest', origin='lower', cmap='bone') .. image:: matched_filter_example.png :width: 500px Specifying ``filter_type='conv'`` will use simple convolution, matching the behavior of Source Extractor. The object is not detected: >>> objects = sep.extract(data, 3.0, err=error, filter_type='conv') >>> len(objects) 0 Setting ``filter_type='matched'`` (the default) correctly deweights the noisier pixels around the source and detects the object: >>> objects = sep.extract(data, 3.0, err=error, filter_type='matched') >>> len(objects) 1 Derivation of the matched filter formula ---------------------------------------- Assume that we have an image containing a single point source. This produces a signal with PSF :math:`S_i` and noise :math:`N_i` at each pixel indexed by :math:`i`. Then the measured image data :math:`D_i` (i.e. our pixel values) is given by: .. math:: D_i = S_i + N_i Then we want to apply a linear transformation :math:`T_i` which gives an output :math:`Y`: .. math:: Y = \sum_i T_i D_i = T^T D We use matrix notation from here on and drop the explicit sums. Our objective is to find the transformation :math:`T_i` which maximizes the signal-to-noise ratio :math:`SNR`. .. math:: SNR^2 = \frac{(T^T S)^2}{E[(T^T N)^2]} We can expand the denominator as: .. math:: E[(T^T N)^2] = E[(T^T N)(N^T T)] = T^T \cdot E[N N^T] \cdot T = T^T C T Where :math:`C_{ik}` is the covariance of the noise between pixels :math:`i` and :math:`k`. Now using the Cauchy-Schwarz inequality on the numerator: .. math:: (T^T S)^2 = (T^T C^{1/2} C^{-1/2} S)^2 \le (T^T C^{1/2})^2 (C^{-1/2} S)^2 = (T^T C T) (S^T C^{-1} S) since :math:`C^T = C`. The signal-to-noise ratio is therefore bounded by: .. math:: &SNR^2 \le \frac{(T^T C T)(S^T C^{-1} S)}{(T^T C T)} \\ &SNR^2 \le S^T C^{-1} S Choosing :math:`T = \alpha C^{-1} S` where :math:`\alpha` is an arbitrary normalization constant, we get equality. Hence this choise of :math:`T` is the optimal linear tranformation. We normalize this linear transformation so that if there is no signal and only noise, we get an expected signal-to-noise ratio of 1. With this definition, the output :math:`SNR` represents the number of standard deviations above the background. This gives: .. math:: &E[(T^T N)^2] = T^T C T = \alpha^2 S^T C^{-1} C C^{-1} S = \alpha^2 S^T C^{-1} S = 1 \\ &\alpha = \frac{1}{\sqrt{S^T C^{-1} S}} Putting everything together, our normalized linear transformation is: .. math:: T = \frac{C^{-1} S}{\sqrt{S^T C^{-1} S}} And the optimal signal-to-noise is given in terms of the known variables as: .. math:: SNR = \frac{S^T C^{-1} D}{\sqrt{S^T C^{-1} S}} ================================================ FILE: docs/index.rst ================================================ SEP === *Python library for Source Extraction and Photometry* About ----- `Source Extractor `_ (Bertin & Arnouts 1996) is a widely used command-line program for segmentation and analysis of astronomical images. It reads in FITS format files, performs a configurable series of tasks, including background estimation, source detection, deblending and a wide array of source measurements, and finally outputs a FITS format catalog file. While Source Extractor is highly useful, the fact that it can only be used as an executable can limit its applicability or lead to awkward workflows. There is often a desire to have programmatic access to perform one or more of the above tasks on in-memory images as part of a larger custom analysis. **SEP makes the core algorithms of Source Extractor available as a library of stand-alone functions and classes.** These operate directly on in-memory arrays (no FITS files or configuration files). The code is derived from the Source Extractor code base (written in C) and aims to produce results compatible with Source Extractor whenever possible. SEP consists of a C library with no dependencies outside the standard library, and a Python module that wraps the C library in a Pythonic API. The Python wrapper operates on NumPy arrays with NumPy as its only dependency. See below for language-specfic build and usage instructions. **Some features:** - spatially variable background and noise estimation - source extraction, with on-the-fly convolution and source deblending - circular and elliptical aperture photometry - fast: implemented in C with Python bindings via Cython **Additional features not in Source Extractor:** - Optimized matched filter for variable noise in source extraction. - Circular annulus and elliptical annulus aperture photometry functions. - Local background subtraction in shape consistent with aperture in aperture photometry functions. - Exact pixel overlap mode in all aperture photometry functions. - Masking of elliptical regions on images. SEP, SEP-PJW, and Package Names ............................... ``sep`` was originally released by Kyle Barbary, at `kbarbary/sep `_ (``sep<=1.2.1``). For a brief period, the package was maintained by Peter Watson, under the ``sep-pjw`` package name, at `PJ-Watson/sep-pjw `_ and `PyPI/sep-pjw `_ (``1.3.0<=sep-pjw<=1.3.8``). Both of these repositories will be archived, and future development will take place at `sep-developers/sep `_ (``sep>=1.4.0``). Note that there may be some incompatibilities between ``sep==1.2.1`` and ``sep==1.4.0`` when using the C-API directly -- the changes are documented :doc:`here `. Installation ------------ with conda .......... SEP can be installed with conda from the ``conda-forge`` channel:: conda install -c conda-forge sep with pip ........ SEP can also be installed with `pip `_. After ensuring that numpy is installed, run :: python -m pip install sep If you get an error about permissions, you are probably using your system Python. In this case, I recommend using `pip's "user install" `_ option to install sep into your user directory :: python -m pip install --user sep Do **not** install ``sep`` or other third-party Python packages using ``sudo`` unless you are fully aware of the risks. Usage Guide ----------- .. toctree:: :maxdepth: 1 tutorial filter apertures changelogs/changelog .. toctree:: :hidden: reference For complete API documentation, see :doc:`reference`. Contributing ------------ Report a bug or documentation issue: http://github.com/sep-developers/sep/issues Development of ``sep`` takes place on GitHub at http://github.com/sep-developers/sep. Contributions of bug fixes, documentation improvements and minor feature additions are welcome via GitHub pull requests. For major features, it is best to open an issue discussing the change first. License and Citation -------------------- The license for SEP is the Lesser GNU Public License (LGPL), granted with the permission from the original author of Source Extractor. If you use SEP in a publication, please cite `Barbary (2016) `_ and the original Source Extractor paper: `Bertin & Arnouts 1996 `_. The DOI for the sep v1.0.0 code release is `10.5281/zenodo.159035 `_. ================================================ FILE: docs/reference.rst ================================================ Reference/API ============= **Background estimation & source detection** .. autosummary:: :toctree: api sep.Background sep.extract **Aperture photometry** .. autosummary:: :toctree: api sep.sum_circle sep.sum_circann sep.sum_ellipse sep.sum_ellipann **Aperture utilities** .. autosummary:: :toctree: api sep.kron_radius sep.flux_radius sep.winpos sep.mask_ellipse sep.ellipse_axes sep.ellipse_coeffs **Low-level utilities** .. autosummary:: :toctree: api sep.get_extract_pixstack sep.set_extract_pixstack sep.get_sub_object_limit sep.set_sub_object_limit **Flags** ======================== =========================================== Flag Description ======================== =========================================== ``sep.OBJ_MERGED`` object is result of deblending ``sep.OBJ_TRUNC`` object is truncated at image boundary ``sep.OBJ_SINGU`` x, y fully correlated in object ``sep.APER_TRUNC`` aperture truncated at image boundary ``sep.APER_HASMASKED`` aperture contains one or more masked pixels ``sep.APER_ALLMASKED`` aperture contains only masked pixels ``sep.APER_NONPOSITIVE`` aperture sum is negative in ``kron_radius`` ======================== =========================================== To see if a given flag is set in ``flags``:: is_merged = (flags & sep.OBJ_MERGED) != 0 .. note:: The coordinate convention in SEP is that (0, 0) corresponds to the center of the first element of the data array. This agrees with the 0-based indexing in Python and C. However, note that this differs from the FITS convention where the center of the first element is at coordinates (1, 1). As Source Extractor deals with FITS files, its outputs follow the FITS convention. Thus, the coordinates from SEP will be offset from Source Extractor coordinates by -1 in x and y. ================================================ FILE: docs/rtd-pip-requirements ================================================ numpy Cython nbsphinx matplotlib fitsio numpydoc jupyter sphinx-astropy[confv2] ================================================ FILE: docs/tutorial.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Tutorial\n", "\n", "This tutorial shows the basic steps of using SEP to detect objects in an image and perform some basic aperture photometry.\n", "\n", "Here, we use the `fitsio` package, just to read the test image, but you can also use `astropy.io.fits` for this purpose (or any other FITS reader)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy as np\n", "import sep" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# additional setup for reading the test image and displaying plots\n", "import fitsio\n", "import matplotlib.pyplot as plt\n", "from matplotlib import rcParams\n", "\n", "%matplotlib inline\n", "\n", "rcParams['figure.figsize'] = [10., 8.]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, we'll read an example image from a FITS file and display it, just to show what we're dealing with. The example image is just 256 x 256 pixels." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# read image into standard 2-d numpy array\n", "data = fitsio.read(\"../data/image.fits\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# show the image\n", "m, s = np.mean(data), np.std(data)\n", "plt.imshow(data, interpolation='nearest', cmap='gray', vmin=m-s, vmax=m+s, origin='lower')\n", "plt.colorbar();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Background subtraction\n", "\n", "Most optical/IR data must be background subtracted before sources can be detected. In SEP, background estimation and source detection are two separate steps." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# measure a spatially varying background on the image\n", "bkg = sep.Background(data)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are various options for controlling the box size used in estimating the background. It is also possible to mask pixels. For example:\n", "```python\n", "bkg = sep.Background(data, mask=mask, bw=64, bh=64, fw=3, fh=3)\n", "```\n", "See the reference section for descriptions of these parameters.\n", "\n", "This returns an `Background` object that holds information on the spatially varying background and spatially varying background noise level. We can now do various things with this `Background` object:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# get a \"global\" mean and noise of the image background:\n", "print(bkg.globalback)\n", "print(bkg.globalrms)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# evaluate background as 2-d array, same size as original image\n", "bkg_image = bkg.back()\n", "# bkg_image = np.array(bkg) # equivalent to above" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# show the background\n", "plt.imshow(bkg_image, interpolation='nearest', cmap='gray', origin='lower')\n", "plt.colorbar();" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# evaluate the background noise as 2-d array, same size as original image\n", "bkg_rms = bkg.rms()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# show the background noise\n", "plt.imshow(bkg_rms, interpolation='nearest', cmap='gray', origin='lower')\n", "plt.colorbar();" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# subtract the background\n", "data_sub = data - bkg\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One can also subtract the background from the data array in-place by doing `bkg.subfrom(data)`.\n", "\n", "
\n", "\n", "**Warning:**\n", "\n", "If the data array is not background-subtracted or the threshold is too low, you will tend to get one giant object when you run object detection using `sep.extract`. Or, more likely, an exception will be raised due to exceeding the internal memory constraints of the `sep.extract` function.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Object detection\n", "\n", "Now that we've subtracted the background, we can run object detection on the background-subtracted data. You can see the background noise level is pretty flat. So here we're setting the detection threshold to be a constant value of $1.5 \\sigma$ where $\\sigma$ is the global background RMS." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "objects = sep.extract(data_sub, 1.5, err=bkg.globalrms)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`sep.extract` has many options for controlling detection threshold, pixel masking, filtering, and object deblending. See the reference documentation for details.\n", "\n", "`objects` is a NumPy structured array with many fields." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# how many objects were detected\n", "len(objects)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`objects['x']` and `objects['y']` will give the centroid coordinates of the objects. Just to check where the detected objects are, we'll over-plot the object coordinates with some basic shape parameters on the image:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from matplotlib.patches import Ellipse\n", "\n", "# plot background-subtracted image\n", "fig, ax = plt.subplots()\n", "m, s = np.mean(data_sub), np.std(data_sub)\n", "im = ax.imshow(data_sub, interpolation='nearest', cmap='gray',\n", " vmin=m-s, vmax=m+s, origin='lower')\n", "\n", "# plot an ellipse for each object\n", "for i in range(len(objects)):\n", " e = Ellipse(xy=(objects['x'][i], objects['y'][i]),\n", " width=6*objects['a'][i],\n", " height=6*objects['b'][i],\n", " angle=objects['theta'][i] * 180. / np.pi)\n", " e.set_facecolor('none')\n", " e.set_edgecolor('red')\n", " ax.add_artist(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`objects` has many other fields, giving information such as second moments, and peak pixel positions and values. See the reference documentation for `sep.extract` for descriptions of these fields. You can see the available fields:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "scrolled": false }, "outputs": [], "source": [ "# available fields\n", "objects.dtype.names" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Aperture photometry\n", "\n", "Finally, we'll perform simple circular aperture photometry with a 3 pixel radius at the locations of the objects:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "flux, fluxerr, flag = sep.sum_circle(data_sub, objects['x'], objects['y'],\n", " 3.0, err=bkg.globalrms, gain=1.0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`flux`, `fluxerr` and `flag` are all 1-d arrays with one entry per object." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# show the first 10 objects results:\n", "for i in range(10):\n", " print(\"object {:d}: flux = {:f} +/- {:f}\".format(i, flux[i], fluxerr[i]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Finally a brief word on byte order\n", "\n", "
\n", "\n", "**Note:**\n", "\n", "If you are using SEP to analyze data read from FITS files with\n", "[astropy.io.fits](http://astropy.readthedocs.org/en/stable/io/fits/)\n", "you may see an error message such as:\n", "\n", "```\n", "ValueError: Input array with dtype '>f4' has non-native byte order.\n", "Only native byte order arrays are supported. To change the byte\n", "order of the array 'data', do 'data = data.astype(data.dtype.newbyteorder(\"=\"))'\n", "```\n", "\n", "It is usually easiest to do this byte-swap operation directly after\n", "reading the array from the FITS file. The exact procedure is slightly different,\n", "depending on the version of ``numpy``. For ``numpy<2.0``, the operation was:\n", "\n", "```python\n", "# Byte order changed in-place\n", ">>> data = data.byteswap(inplace=True).newbyteorder() \n", "# Data copied to a new array\n", ">>> new_data = data.byteswap().newbyteorder()\n", "```\n", "\n", "For ``numpy>=2.0``, the correct operation is one of the following:\n", "\n", "```python\n", "# Copies data to a new array, preserves the ordering of the original array\n", ">>> new_data = data.astype(data.dtype.newbyteorder(\"=\")) \n", "# The same outcome as the previous operation\n", ">>> new_data = data.byteswap()\n", ">>> new_data = new_data.view(new_data.dtype.newbyteorder(\"=\"))\n", "# Changes data in-place\n", ">>> data = data.byteswap()\n", ">>> data = data.view(data.dtype.newbyteorder(\"=\"))\n", "```\n", "\n", "If you do this in-place operation, ensure that there are no other\n", "references to ``data``, as they will be rendered nonsensical.\n", "\n", "For the interested reader, this byteswap operation is necessary because\n", "``astropy.io.fits`` always returns big-endian byte order arrays, even on\n", "little-endian machines. This is due to the FITS standard requiring\n", "big-endian arrays (see the \n", "[FITS Standard](https://fits.gsfc.nasa.gov/fits_standard.html)), and \n", "``astropy.io.fits`` aiming for backwards compatibility.\n", "
" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: licenses/BSD_LICENSE.txt ================================================ Copyright (c) 2011-14, photutils developers All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of the Astropy Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: licenses/LGPL_LICENSE.txt ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ================================================ FILE: licenses/MIT_LICENSE.txt ================================================ The MIT License (MIT) Copyright (c) 2014-2016: SEP developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: paper/paper.bib ================================================ @ARTICLE{bertin96, author = {{Bertin}, E. and {Arnouts}, S.}, title = "{SExtractor: Software for source extraction.}", journal = {\aaps}, keywords = {METHODS: DATA ANALYSIS, TECHNIQUES: IMAGE PROCESSING, GALAXIES: PHOTOMETRY}, year = 1996, month = jun, volume = 117, pages = {393-404}, doi = {10.1051/aas:1996164}, adsurl = {http://adsabs.harvard.edu/abs/1996A\%26AS..117..393B}, adsnote = {Provided by the SAO/NASA Astrophysics Data System} } @online{sextractor, author = {Emanuel Bertin}, title = {SExtractor}, year = 2016, url = {http://www.astromatic.net/software/sextractor}, urldate = {2016-08-25} } ================================================ FILE: paper/paper.md ================================================ --- title: 'SEP: Source Extractor as a library' tags: - astronomy authors: - name: Kyle Barbary orcid: 0000-0002-2532-3696 affiliation: University of California, Berkeley date: 29 August 2016 bibliography: paper.bib --- # Summary Source Extractor [@bertin96; @sextractor] is a widely used command-line program for segmentation and analysis of astronomical images. It reads in FITS format files, performs a configurable series of tasks, including background estimation, source detection, deblending and a wide array of source measurements, and finally outputs a FITS format catalog file. While Source Extractor is highly useful, the fact that it can only be used as an executable -- reading input files, producing output files and controlled by a limited set of configuration options specified in another file -- can limit its applicability or lead to awkward workflows. There is often a desire to have programmatic access to perform one or more of the above tasks on in-memory images as part of a larger custom analysis. SEP makes available the core algorithms of Source Extractor in a library of stand-alone functions and classes. These operate directly on in-memory arrays (no FITS files or configuration files). The code is derived from the Source Extractor code base (written in C) and aims to produce results compatible with Source Extractor whenever possible. SEP consists of a C library with no dependencies outside the standard library, and a Python module that wraps the C library in a Pythonic API. The Python wrapper operates on NumPy arrays with NumPy as its only dependency. It is generated using Cython. From Source Extractor, SEP includes background estimation, image segmentation (including on-the-fly filtering and source deblending), aperture photometry in circular and elliptical apertures, and source measurements such as Kron radius, "windowed" position fitting, and half-light radius. Additionally, several features not in Source Extractor have been added: - Optimized matched filter for variable noise in source extraction. - Circular annulus and elliptical annulus aperture photometry functions. - Local background subtraction in shape consistent with aperture in aperture photometry functions. - Exact pixel overlap mode in all aperture photometry functions. - Masking of elliptical regions on images. Finally, note that SEP is essentially a fork of Source Extractor that has already diverged significantly from the original code base. One might ask why SEP is not part of Source Extractor itself: the command-line interface in Source Extractor could be built on top of such a library. The answer is that a vast array of changes were necessary in order to expose the functionality as stand-alone C functions. It would be a lot of work to rewrite Source Extractor itself in this way, with little gain for the executable itself. # References ================================================ FILE: pyproject.toml ================================================ [build-system] requires = [ "setuptools>=61.0, <72.2.0", "wheel", "numpy>=2.0.0rc2", "Cython", "setuptools_scm>=8.0", ] build-backend = "setuptools.build_meta" [project] name = "sep" dynamic = ["version"] authors = [ { name="Emmanuel Bertin"}, { name="Kyle Barbary"}, { name="Kyle Boone"}, { name="Thomas Robitaille"}, { name="Matt Craig"}, { name="Curtis McCully"}, { name="Evert Rol"}, { name="Joe Lyman"}, { name="Michael Wuertenberger"}, { name="Ingvar Stepanyan"}, { name="Gabe Brammer"}, { name="Peter Watson"}, ] maintainers = [ { name="Peter Watson", email="peter.watson+sep@inaf.it" }, ] description="Astronomical source extraction and photometry library" readme = "README.md" license = { text = "LGPLv3+" } classifiers=[ "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 3", "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)", "Topic :: Scientific/Engineering :: Astronomy", "Intended Audience :: Science/Research", ] requires-python = ">=3.9" dependencies = [ "numpy>=1.26.4" ] [project.optional-dependencies] docs = [ "sphinx-copybutton>=0.5", "sphinx>=7.2", "numpydoc>=1.6", "matplotlib>=3.6", "sphinx-astropy[confv2]>=1.9.1", "nbsphinx>=0.9.3", "pandoc>=2.3", "fitsio>=1.2.1", "jupyter", "myst-parser>=2.0.0", ] [project.urls] "Homepage" = "https://github.com/sep-developers/sep" "Bug Tracker" = "https://github.com/sep-developers/sep/issues" "Documentation" = "http://sep-pjw.readthedocs.org" [tool.setuptools_scm] [tool.black] line-length = 88 target-version = ['py312'] extend-exclude = '(.*.txt|.*.md|.*.toml|.*.odg)' preview = true [tool.isort] profile = "black" [tool.numpydoc_validation] checks = [ "all", # report on all checks, except the below "EX01", "SA01", "ES01", ] exclude = [ # don't report on objects that match any of these regex '\.undocumented_method$', '\.__repr__$', '\._.*$', # Ignore anything that's private (e.g., starts with _) ] override_SS05 = [ # override SS05 to allow docstrings starting with these words '^Process ', '^Assess ', '^Access ', ] ================================================ FILE: sep.pyx ================================================ # This wrapper licensed under an MIT license. """ Source Extraction and Photometry This module is a wrapper of the SEP C library. """ import numpy as np cimport cython cimport numpy as np from cpython.mem cimport PyMem_Free, PyMem_Malloc from cpython.version cimport PY_MAJOR_VERSION from libc cimport limits from libc.math cimport sqrt np.import_array() # To access the numpy C-API. from importlib.metadata import PackageNotFoundError, version try: __version__ = version("sep") except PackageNotFoundError: # package is not installed pass # ----------------------------------------------------------------------------- # Definitions from the SEP C library # macro definitions from sep.h DEF SEP_TBYTE = 11 DEF SEP_TINT = 31 DEF SEP_TFLOAT = 42 DEF SEP_TDOUBLE = 82 # input flag values (C macros) DEF SEP_NOISE_NONE = 0 DEF SEP_NOISE_STDDEV = 1 DEF SEP_NOISE_VAR = 2 # filter types for sep_extract DEF SEP_FILTER_CONV = 0 DEF SEP_FILTER_MATCHED = 1 # Threshold types DEF SEP_THRESH_REL = 0 DEF SEP_THRESH_ABS = 1 # input flags for aperture photometry DEF SEP_MASK_IGNORE = 0x0004 # Output flag values accessible from python OBJ_MERGED = np.short(0x0001) OBJ_TRUNC = np.short(0x0002) OBJ_DOVERFLOW = np.short(0x0004) OBJ_SINGU = np.short(0x0008) APER_TRUNC = np.short(0x0010) APER_HASMASKED = np.short(0x0020) APER_ALLMASKED = np.short(0x0040) APER_NONPOSITIVE = np.short(0x0080) # macro defintion from sepcore.h # This is not part of the SEP API, but we pull it out because want to # explicitly detect memory errors so that we can raise MemoryError(). DEF MEMORY_ALLOC_ERROR = 1 # header definitions cdef extern from "sep.h": ctypedef struct sep_image: const void *data const void *noise const void *mask const void *segmap int dtype int ndtype int mdtype int sdtype np.int64_t *segids np.int64_t *idcounts np.int64_t numids np.int64_t w np.int64_t h double noiseval short noise_type double gain double maskthresh ctypedef struct sep_bkg: np.int64_t w np.int64_t h float globalback float globalrms ctypedef struct sep_catalog: np.int64_t nobj float *thresh np.int64_t *npix np.int64_t *tnpix np.int64_t *xmin np.int64_t *xmax np.int64_t *ymin np.int64_t *ymax double *x double *y double *x2 double *y2 double *xy double *errx2 double *erry2 double *errxy float *a float *b float *theta float *cxx float *cyy float *cxy float *cflux float *flux float *cpeak float *peak np.int64_t *xcpeak np.int64_t *ycpeak np.int64_t *xpeak np.int64_t *ypeak short *flag np.int64_t **pix np.int64_t *objectspix int sep_background(const sep_image *im, np.int64_t bw, np.int64_t bh, np.int64_t fw, np.int64_t fh, double fthresh, sep_bkg **bkg) float sep_bkg_global(const sep_bkg *bkg) float sep_bkg_globalrms(const sep_bkg *bkg) int sep_bkg_array(const sep_bkg *bkg, void *arr, int dtype) int sep_bkg_rmsarray(const sep_bkg *bkg, void *arr, int dtype) int sep_bkg_subarray(const sep_bkg *bkg, void *arr, int dtype) void sep_bkg_free(sep_bkg *bkg) int sep_extract(const sep_image *image, float thresh, int thresh_type, int minarea, float *conv, np.int64_t convw, np.int64_t convh, int filter_type, int deblend_nthresh, double deblend_cont, int clean_flag, double clean_param, sep_catalog **catalog) void sep_catalog_free(sep_catalog *catalog) int sep_sum_circle(const sep_image *image, double x, double y, double r, int id, int subpix, short inflags, double *sum, double *sumerr, double *area, short *flag) int sep_sum_circann(const sep_image *image, double x, double y, double rin, double rout, int id, int subpix, short inflags, double *sum, double *sumerr, double *area, short *flag) int sep_sum_ellipse(const sep_image *image, double x, double y, double a, double b, double theta, double r, int id, int subpix, short inflags, double *sum, double *sumerr, double *area, short *flag) int sep_sum_ellipann(const sep_image *image, double x, double y, double a, double b, double theta, double rin, double rout, int id, int subpix, short inflags, double *sum, double *sumerr, double *area, short *flag) int sep_flux_radius(const sep_image *image, double x, double y, double rmax, int id, int subpix, short inflag, double *fluxtot, double *fluxfrac, int n, double *r, short *flag) int sep_kron_radius(const sep_image *image, double x, double y, double cxx, double cyy, double cxy, double r, int id, double *kronrad, short *flag) int sep_windowed(const sep_image *image, double x, double y, double sig, int subpix, short inflag, double *xout, double *yout, int *niter, short *flag) int sep_ellipse_axes(double cxx, double cyy, double cxy, double *a, double *b, double *theta) void sep_ellipse_coeffs(double a, double b, double theta, double *cxx, double *cyy, double *cxy) void sep_set_ellipse(unsigned char *arr, np.int64_t w, np.int64_t h, double x, double y, double cxx, double cyy, double cxy, double r, unsigned char val) void sep_set_extract_pixstack(size_t val) size_t sep_get_extract_pixstack() void sep_set_sub_object_limit(int val) int sep_get_sub_object_limit() void sep_get_errmsg(int status, char *errtext) void sep_get_errdetail(char *errtext) # ----------------------------------------------------------------------------- # Utility functions cdef int _get_sep_dtype(dtype) except -1: """Convert a numpy dtype to the corresponding SEP dtype integer code.""" if not dtype.isnative: raise ValueError( "Input array with dtype `{0}` has non-native byte order. " "Only native byte order arrays are supported. " "To change the byte order of the array `data`, do " "`data = data.astype(data.dtype.newbyteorder('='))`".format(dtype)) t = dtype.type if t is np.single: return SEP_TFLOAT elif t is np.bool_ or t is np.ubyte: return SEP_TBYTE elif dtype == np.double: return SEP_TDOUBLE elif dtype == np.intc: return SEP_TINT raise ValueError('input array dtype not supported: {0}'.format(dtype)) cdef int _check_array_get_dims(np.ndarray arr, np.int64_t *w, np.int64_t *h) except -1: """Check some things about an array and return dimensions""" # Raise an informative message if array is not C-contiguous if not arr.flags["C_CONTIGUOUS"]: raise ValueError("array is not C-contiguous") # Check that there are exactly 2 dimensions if arr.ndim != 2: raise ValueError("array must be 2-d") # ensure that arr dimensions are not too large for C ints. if arr.shape[0] <= limits.INT_MAX: h[0] = arr.shape[0] else: raise ValueError("array height ({0:d}) greater than INT_MAX ({1:d})" .format(arr.shape[0], limits.INT_MAX)) if arr.shape[1] <= limits.INT_MAX: w[0] = arr.shape[1] else: raise ValueError("array width ({0:d}) greater than INT_MAX ({1:d})" .format(arr.shape[1], limits.INT_MAX)) return 0 cdef int _assert_ok(int status) except -1: """Get the SEP error message corresponding to status code""" cdef char *errmsg cdef char *errdetail if status == 0: return 0 # First check if we have an out-of-memory error, so we don't try to # allocate more memory to hold the error message. if status == MEMORY_ALLOC_ERROR: raise MemoryError # Otherwise, get error message. errmsg = PyMem_Malloc(61 * sizeof(char)) sep_get_errmsg(status, errmsg) pyerrmsg = errmsg PyMem_Free(errmsg) # Get error detail. errdetail = PyMem_Malloc(512 * sizeof(char)) sep_get_errdetail(errdetail) pyerrdetail = errdetail PyMem_Free(errdetail) # If error detail is present, append it to the message. if pyerrdetail != b"": pyerrmsg = pyerrmsg + b": " + pyerrdetail # Convert string to unicode if on python 3 if PY_MAJOR_VERSION == 3: msg = pyerrmsg.decode() else: msg = pyerrmsg raise Exception(msg) cdef int _parse_arrays(np.ndarray data, err, var, mask, segmap, sep_image *im) except -1: """Helper function for functions accepting data, error, mask & segmap arrays. Fills in an sep_image struct.""" cdef np.int64_t ew, eh, mw, mh, sw, sh cdef np.uint8_t[:,:] buf, ebuf, mbuf, sbuf # Clear im fields we might not touch (everything besides data, dtype, w, h) im.noise = NULL im.mask = NULL im.segmap = NULL im.numids = 0 im.ndtype = 0 im.mdtype = 0 im.noiseval = 0.0 im.noise_type = SEP_NOISE_NONE im.gain = 0.0 im.maskthresh = 0.0 # Get main image info _check_array_get_dims(data, &(im.w), &(im.h)) im.dtype = _get_sep_dtype(data.dtype) buf = data.view(dtype=np.uint8) im.data = &buf[0, 0] # Check if noise is error or variance. noise = None # will point to either error or variance. if err is not None: if var is not None: raise ValueError("Cannot specify both err and var") noise = err im.noise_type = SEP_NOISE_STDDEV elif var is not None: noise = var im.noise_type = SEP_NOISE_VAR # parse noise if noise is None: im.noise = NULL im.noise_type = SEP_NOISE_NONE im.noiseval = 0.0 elif isinstance(noise, np.ndarray): if noise.ndim == 0: im.noise = NULL im.noiseval = noise elif noise.ndim == 2: _check_array_get_dims(noise, &ew, &eh) if ew != im.w or eh != im.h: raise ValueError("size of error/variance array must match" " data") im.ndtype = _get_sep_dtype(noise.dtype) ebuf = noise.view(dtype=np.uint8) im.noise = &ebuf[0, 0] else: raise ValueError("error/variance array must be 0-d or 2-d") else: im.noise = NULL im.noiseval = noise # Optional input: mask if mask is None: im.mask = NULL else: _check_array_get_dims(mask, &mw, &mh) if mw != im.w or mh != im.h: raise ValueError("size of mask array must match data") im.mdtype = _get_sep_dtype(mask.dtype) mbuf = mask.view(dtype=np.uint8) im.mask = &mbuf[0, 0] # Optional input: segmap if segmap is None: im.segmap = NULL else: _check_array_get_dims(segmap, &sw, &sh) if sw != im.w or sh != im.h: raise ValueError("size of segmap array must match data") im.sdtype = _get_sep_dtype(segmap.dtype) sbuf = segmap.view(dtype=np.uint8) im.segmap = &sbuf[0, 0] # ----------------------------------------------------------------------------- # Background Estimation cdef class Background: """ Background(data, mask=None, maskthresh=0.0, bw=64, bh=64, fw=3, fh=3, fthresh=0.0) Representation of spatially variable image background and noise. Parameters ---------- data : 2-d `~numpy.ndarray` Data array. mask : 2-d `~numpy.ndarray`, optional Mask array, optional maskthresh : float, optional Mask threshold. This is the inclusive upper limit on the mask value in order for the corresponding pixel to be unmasked. For boolean arrays, False and True are interpreted as 0 and 1, respectively. Thus, given a threshold of zero, True corresponds to masked and False corresponds to unmasked. bw, bh : int, optional Size of background boxes in pixels. Default is 64. fw, fh : int, optional Filter width and height in boxes. Default is 3. fthresh : float, optional Filter threshold. Default is 0.0. """ cdef sep_bkg *ptr # pointer to C struct cdef np.dtype orig_dtype # dtype code of original image @cython.boundscheck(False) @cython.wraparound(False) def __cinit__(self, np.ndarray data not None, np.ndarray mask=None, float maskthresh=0.0, int bw=64, int bh=64, int fw=3, int fh=3, float fthresh=0.0): cdef int status cdef sep_image im _parse_arrays(data, None, None, mask, None, &im) im.maskthresh = maskthresh status = sep_background(&im, bw, bh, fw, fh, fthresh, &self.ptr) _assert_ok(status) self.orig_dtype = data.dtype # Note: all initialization work is done in __cinit__. This is just here # for the docstring. def __init__(self, np.ndarray data not None, np.ndarray mask=None, float maskthresh=0.0, int bw=64, int bh=64, int fw=3, int fh=3, float fthresh=0.0): """Background(data, mask=None, maskthresh=0.0, bw=64, bh=64, fw=3, fh=3, fthresh=0.0)""" pass property globalback: """Global background level.""" def __get__(self): return sep_bkg_global(self.ptr) property globalrms: """Global background RMS.""" def __get__(self): return sep_bkg_globalrms(self.ptr) def back(self, dtype=None, copy=None): """back(dtype=None) Create an array of the background. Parameters ---------- dtype : `~numpy.dtype`, optional Data type of output array. Default is the dtype of the original data. Returns ------- back : `~numpy.ndarray` Array with same dimensions as original data. """ cdef int sep_dtype cdef np.uint8_t[:, :] buf if dtype is None: dtype = self.orig_dtype else: dtype = np.dtype(dtype) sep_dtype = _get_sep_dtype(dtype) result = np.empty((self.ptr.h, self.ptr.w), dtype=dtype) buf = result.view(dtype=np.uint8) status = sep_bkg_array(self.ptr, &buf[0, 0], sep_dtype) _assert_ok(status) if copy: return result.copy() else: return result def rms(self, dtype=None): """rms(dtype=None) Create an array of the background rms. Parameters ---------- dtype : `~numpy.dtype`, optional Data type of output array. Default is the dtype of the original data. Returns ------- rms : `~numpy.ndarray` Array with same dimensions as original data. """ cdef int sep_dtype cdef np.uint8_t[:, :] buf if dtype is None: dtype = self.orig_dtype else: dtype = np.dtype(dtype) sep_dtype = _get_sep_dtype(dtype) result = np.empty((self.ptr.h, self.ptr.w), dtype=dtype) buf = result.view(dtype=np.uint8) status = sep_bkg_rmsarray(self.ptr, &buf[0, 0], sep_dtype) _assert_ok(status) return result def subfrom(self, np.ndarray data not None): """subfrom(data) Subtract the background from an existing array. Like ``data = data - bkg``, but avoids making a copy of the data. Parameters ---------- data : `~numpy.ndarray` Input array, which will be updated in-place. Shape must match that of the original image used to measure the background. """ cdef np.int64_t w, h cdef int status, sep_dtype cdef np.uint8_t[:, :] buf assert self.ptr is not NULL _check_array_get_dims(data, &w, &h) sep_dtype = _get_sep_dtype(data.dtype) buf = data.view(dtype=np.uint8) # ensure dimensions match original image if (w != self.ptr.w or h != self.ptr.h): raise ValueError("Data dimensions do not match background " "dimensions") status = sep_bkg_subarray(self.ptr, &buf[0, 0], sep_dtype) _assert_ok(status) def __array__(self, dtype=None, copy=None): return self.back(dtype=dtype, copy=copy) def __rsub__(self, np.ndarray data not None): data = np.copy(data) self.subfrom(data) return data def __dealloc__(self): if self.ptr is not NULL: sep_bkg_free(self.ptr) # ----------------------------------------------------------------------------- # Source Extraction # This needs to match the result from extract cdef packed struct Object: np.float64_t thresh np.int64_t npix np.int64_t tnpix np.int64_t xmin np.int64_t xmax np.int64_t ymin np.int64_t ymax np.float64_t x np.float64_t y np.float64_t x2 np.float64_t y2 np.float64_t xy np.float64_t a np.float64_t b np.float64_t theta np.float64_t cxx np.float64_t cyy np.float64_t cxy np.float64_t cflux np.float64_t flux np.float64_t cpeak np.float64_t peak np.float64_t errx2 np.float64_t erry2 np.float64_t errxy np.int64_t xcpeak np.int64_t ycpeak np.int64_t xpeak np.int64_t ypeak short flag default_kernel = np.array([[1.0, 2.0, 1.0], [2.0, 4.0, 2.0], [1.0, 2.0, 1.0]], dtype=np.float32) @cython.boundscheck(False) @cython.wraparound(False) def extract(np.ndarray data not None, float thresh, err=None, var=None, gain=None, np.ndarray mask=None, double maskthresh=0.0, int minarea=5, np.ndarray filter_kernel=default_kernel, filter_type='matched', int deblend_nthresh=32, double deblend_cont=0.005, bint clean=True, double clean_param=1.0, segmentation_map=None): """extract(data, thresh, err=None, mask=None, minarea=5, filter_kernel=default_kernel, filter_type='matched', deblend_nthresh=32, deblend_cont=0.005, clean=True, clean_param=1.0, segmentation_map=False) Extract sources from an image. Parameters ---------- data : `~numpy.ndarray` Data array (2-d). thresh : float Threshold pixel value for detection. If an ``err`` or ``var`` array is not given, this is interpreted as an absolute threshold. If ``err`` or ``var`` is given, this is interpreted as a relative threshold: the absolute threshold at pixel (j, i) will be ``thresh * err[j, i]`` or ``thresh * sqrt(var[j, i])``. err, var : float or `~numpy.ndarray`, optional Error *or* variance (specify at most one). This can be used to specify a pixel-by-pixel detection threshold; see "thresh" argument. gain : float, optional Conversion factor between data array units and poisson counts. This does not affect detection; it is used only in calculating Poisson noise contribution to uncertainty parameters such as ``errx2``. If not given, no Poisson noise will be added. mask : `~numpy.ndarray`, optional Mask array. ``True`` values, or numeric values greater than ``maskthresh``, are considered masked. Masking a pixel is equivalent to setting data to zero and noise (if present) to infinity, and occurs *before* filtering. maskthresh : float, optional Threshold for a pixel to be masked. Default is ``0.0``. minarea : int, optional Minimum number of pixels required for an object. Default is 5. filter_kernel : `~numpy.ndarray` or None, optional Filter kernel used for on-the-fly filtering (used to enhance detection). Default is a 3x3 array: [[1,2,1], [2,4,2], [1,2,1]]. Set to ``None`` to skip convolution. filter_type : {'matched', 'conv'}, optional Filter treatment. This affects filtering behavior when a noise array is supplied. ``'matched'`` (default) accounts for pixel-to-pixel noise in the filter kernel. ``'conv'`` is simple convolution of the data array, ignoring pixel-to-pixel noise across the kernel. ``'matched'`` should yield better detection of faint sources in areas of rapidly varying noise (such as found in coadded images made from semi-overlapping exposures). The two options are equivalent when noise is constant. deblend_nthresh : int, optional Number of thresholds used for object deblending. Default is 32. deblend_cont : float, optional Minimum contrast ratio used for object deblending. Default is 0.005. To entirely disable deblending, set to 1.0. clean : bool, optional Perform cleaning? Default is True. clean_param : float, optional Cleaning parameter (see SExtractor manual). Default is 1.0. segmentation_map : `~numpy.ndarray` or bool, optional If ``True``, also return a "segmentation map" giving the member pixels of each object. Default is False. *New in v1.3.0*: An existing segmentation map can also be supplied in the form of an `~numpy.ndarray`. If this is the case, then the object detection stage is skipped, and the objects in the segmentation map are analysed and extracted. Returns ------- objects : `~numpy.ndarray` Extracted object parameters (structured array). Available fields are: * ``thresh`` (float) Threshold at object location. * ``npix`` (int) Number of pixels belonging to the object. * ``tnpix`` (int) Number of pixels above threshold (unconvolved data). * ``xmin``, ``xmax`` (int) Minimum, maximum x coordinates of pixels. * ``ymin``, ``ymax`` (int) Minimum, maximum y coordinates of pixels. * ``x``, ``y`` (float) object barycenter (first moments). * ``x2``, ``y2``, ``xy`` (float) Second moments. * ``errx2``, ``erry2``, ``errxy`` (float) Second moment errors. Note that these will be zero if error is not given. * ``a``, ``b``, ``theta`` (float) Ellipse parameters, scaled as described by Section 8.4.2 in "The Source Extractor Guide" or Section 10.1.5-6 of v2.13 of SExtractor's User Manual. * ``cxx``, ``cyy``, ``cxy`` (float) Alternative ellipse parameters. * ``cflux`` (float) Sum of member pixels in convolved data. * ``flux`` (float) Sum of member pixels in unconvolved data. * ``cpeak`` (float) Peak value in convolved data. * ``peak`` (float) Peak value in unconvolved data. * ``xcpeak``, ``ycpeak`` (int) Coordinate of convolved peak pixel. * ``xpeak``, ``ypeak`` (int) Coordinate of unconvolved peak pixel. * ``flag`` (int) Extraction flags. segmap : `~numpy.ndarray`, optional Array of integers with same shape as data. Pixels not belonging to any object have value 0. All pixels belonging to the ``i``-th object (e.g., ``objects[i]``) have value ``i+1``. Only returned if ``segmentation_map = True | ~numpy.ndarray``. """ cdef int kernelw, kernelh, status, i, j cdef int filter_typecode, thresh_type cdef sep_catalog *catalog = NULL cdef np.ndarray[Object] result cdef float[:, :] kernelflt cdef float *kernelptr cdef np.int32_t[:, :] segmap_buf cdef np.int32_t *segmap_ptr cdef np.int64_t *objpix cdef sep_image im cdef np.int64_t[:] idbuf, countbuf # parse arrays if type(segmentation_map) is np.ndarray: _parse_arrays(data, err, var, mask, segmentation_map, &im) ids, counts = np.unique(segmentation_map, return_counts=True) # Remove non-object IDs: filter_ids = ids>0 segids = np.ascontiguousarray(ids[filter_ids].astype(dtype=np.int64)) idcounts = np.ascontiguousarray(counts[filter_ids].astype(dtype=np.int64)) if np.nansum(idcounts)>get_extract_pixstack(): raise ValueError( f"The number of object pixels ({np.nansum(idcounts)}) in " "the segmentation map exceeds the allocated pixel stack " f"({get_extract_pixstack()}). Use " "`sep.set_extract_pixstack()` to increase the size, " "or check that the correct segmentation map has been " "supplied." ) idbuf = segids.view(dtype=np.int64) countbuf = idcounts.view(dtype=np.int64) im.segids = &idbuf[0] im.idcounts = &countbuf[0] im.numids = len(segids) else: _parse_arrays(data, err, var, mask, None, &im) im.maskthresh = maskthresh if gain is not None: im.gain = gain # Parse filter input if filter_kernel is None: kernelptr = NULL kernelw = 0 kernelh = 0 else: kernelflt = filter_kernel.astype(np.float32) kernelptr = &kernelflt[0, 0] kernelw = kernelflt.shape[1] kernelh = kernelflt.shape[0] if filter_type == 'matched': filter_typecode = SEP_FILTER_MATCHED elif filter_type == 'conv': filter_typecode = SEP_FILTER_CONV else: raise ValueError("unknown filter_type: {!r}".format(filter_type)) # If image has error info, the threshold is relative, otherwise # it is absolute. if im.noise_type == SEP_NOISE_NONE: thresh_type = SEP_THRESH_ABS else: thresh_type = SEP_THRESH_REL status = sep_extract(&im, thresh, thresh_type, minarea, kernelptr, kernelw, kernelh, filter_typecode, deblend_nthresh, deblend_cont, clean, clean_param, &catalog) _assert_ok(status) # Allocate result record array and fill it result = np.empty(catalog.nobj, dtype=np.dtype([('thresh', np.float64), ('npix', np.int64), ('tnpix', np.int64), ('xmin', np.int64), ('xmax', np.int64), ('ymin', np.int64), ('ymax', np.int64), ('x', np.float64), ('y', np.float64), ('x2', np.float64), ('y2', np.float64), ('xy', np.float64), ('errx2', np.float64), ('erry2', np.float64), ('errxy', np.float64), ('a', np.float64), ('b', np.float64), ('theta', np.float64), ('cxx', np.float64), ('cyy', np.float64), ('cxy', np.float64), ('cflux', np.float64), ('flux', np.float64), ('cpeak', np.float64), ('peak', np.float64), ('xcpeak', np.int64), ('ycpeak', np.int64), ('xpeak', np.int64), ('ypeak', np.int64), ('flag', np.short)])) for i in range(catalog.nobj): result['thresh'][i] = catalog.thresh[i] result['npix'][i] = catalog.npix[i] result['tnpix'][i] = catalog.tnpix[i] result['xmin'][i] = catalog.xmin[i] result['xmax'][i] = catalog.xmax[i] result['ymin'][i] = catalog.ymin[i] result['ymax'][i] = catalog.ymax[i] result['x'][i] = catalog.x[i] result['y'][i] = catalog.y[i] result['x2'][i] = catalog.x2[i] result['y2'][i] = catalog.y2[i] result['xy'][i] = catalog.xy[i] result['errx2'][i] = catalog.errx2[i] result['erry2'][i] = catalog.erry2[i] result['errxy'][i] = catalog.errxy[i] result['a'][i] = catalog.a[i] result['b'][i] = catalog.b[i] result['theta'][i] = catalog.theta[i] result['cxx'][i] = catalog.cxx[i] result['cyy'][i] = catalog.cyy[i] result['cxy'][i] = catalog.cxy[i] result['cflux'][i] = catalog.cflux[i] result['flux'][i] = catalog.flux[i] result['cpeak'][i] = catalog.cpeak[i] result['peak'][i] = catalog.peak[i] result['xcpeak'][i] = catalog.xcpeak[i] result['ycpeak'][i] = catalog.ycpeak[i] result['xpeak'][i] = catalog.xpeak[i] result['ypeak'][i] = catalog.ypeak[i] result['flag'][i] = catalog.flag[i] # construct a segmentation map, if it was requested. if type(segmentation_map) is np.ndarray or segmentation_map: # Note: We have to write out `(data.shape[0], data.shape[1])` because # because Cython turns `data.shape` later into an int pointer when # the function argument is typed as np.ndarray. segmap = np.zeros((data.shape[0], data.shape[1]), dtype=np.int32) segmap_buf = segmap segmap_ptr = &segmap_buf[0, 0] for i in range(catalog.nobj): objpix = catalog.pix[i] for j in range(catalog.npix[i]): segmap_ptr[objpix[j]] = i + 1 # Free the C catalog sep_catalog_free(catalog) if type(segmentation_map) is np.ndarray or segmentation_map: return result, segmap else: return result # ----------------------------------------------------------------------------- # Aperture Photometry @cython.boundscheck(False) @cython.wraparound(False) def sum_circle(np.ndarray data not None, x, y, r, var=None, err=None, gain=None, np.ndarray mask=None, double maskthresh=0.0, seg_id=None, np.ndarray segmap=None, bkgann=None, int subpix=5): """sum_circle(data, x, y, r, err=None, var=None, mask=None, maskthresh=0.0, segmap=None, seg_id=None, bkgann=None, gain=None, subpix=5) Sum data in circular aperture(s). Parameters ---------- data : `~numpy.ndarray` 2-d array to be summed. x, y, r : array_like Center coordinates and radius (radii) of aperture(s). ``x`` corresponds to the second ("fast") axis of the input array and ``y`` corresponds to the first ("slow") axis. ``x, y = (0.0, 0.0)`` corresponds to the center of the first element of the array. These inputs obey numpy broadcasting rules. err, var : float or `~numpy.ndarray` Error *or* variance (specify at most one). mask : `~numpy.ndarray`, optional Mask array. If supplied, a given pixel is masked if its value is greater than ``maskthresh``. maskthresh : float, optional Threshold for a pixel to be masked. Default is ``0.0``. segmap : `~numpy.ndarray`, optional Segmentation image with dimensions of ``data`` and dtype ``np.int32``. This is an optional input and corresponds to the segmentation map output by `~sep.extract`. seg_id : array_like, optional Array of segmentation ids used to mask additional pixels in the image. Dimensions correspond to the dimensions of ``x`` and ``y``. The behavior differs depending on whether ``seg_id`` is negative or positive. If ``seg_id`` is positive, all pixels belonging to other objects are masked. (Pixel ``j, i`` is masked if ``seg[j, i] != seg_id and seg[j, i] != 0``). If ``seg_id`` is negative, all pixels other than those belonging to the object of interest are masked. (Pixel ``j, i`` is masked if ``seg[j, i] != -seg_id``). NB: must be included if ``segmap`` is provided. bkgann : tuple, optional Length 2 tuple giving the inner and outer radius of a "background annulus". If supplied, the background is estimated by averaging unmasked pixels in this annulus. If supplied, the inner and outer radii obey numpy broadcasting rules along with ``x``, ``y`` and ``r``. gain : float, optional Conversion factor between data array units and poisson counts, used in calculating poisson noise in aperture sum. If ``None`` (default), do not add poisson noise. subpix : int, optional Subpixel sampling factor. If 0, exact overlap is calculated. Default is 5. Returns ------- sum : `~numpy.ndarray` The sum of the data array within the aperture. sumerr : `~numpy.ndarray` Error on the sum. flags : `~numpy.ndarray` Integer giving flags. (0 if no flags set.) """ cdef double flux1, fluxerr1, area1, cdef double bkgflux, bkgfluxerr, bkgarea cdef short flag1, bkgflag cdef size_t i cdef int status cdef np.broadcast it cdef sep_image im # Test for map without seg_id. Nothing happens if seg_id supplied but # without segmap. if (segmap is not None) and (seg_id is None): raise ValueError('`segmap` supplied but not `seg_id`.') _parse_arrays(data, err, var, mask, segmap, &im) im.maskthresh = maskthresh if gain is not None: im.gain = gain # Require that inputs are float64 arrays. This has to be done because we # are using a broadcasting iterator below, where we need to know the type # in advance. There are other ways to do this, e.g., using NpyIter_Multi # in the numpy C-API. However, the best way to use this from cython # is not clear to me at this time. # # docs.scipy.org/doc/numpy/reference/c-api.iterator.html#NpyIter_MultiNew dt = np.dtype(np.double) dint = np.dtype(np.int32) x = np.require(x, dtype=dt) y = np.require(y, dtype=dt) r = np.require(r, dtype=dt) # Segmentation image and ids with same dimensions as x, y, etc. if seg_id is not None: seg_id = np.require(seg_id, dtype=dint) if seg_id.shape != x.shape: raise ValueError('Shapes of `x` and `seg_id` do not match') else: seg_id = np.zeros(len(x), dtype=dint) if bkgann is None: # allocate ouput arrays shape = np.broadcast(x, y, r).shape sum = np.empty(shape, dt) sumerr = np.empty(shape, dt) flag = np.empty(shape, np.short) it = np.broadcast(x, y, r, seg_id, sum, sumerr, flag) while np.PyArray_MultiIter_NOTDONE(it): status = sep_sum_circle( &im, (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], (np.PyArray_MultiIter_DATA(it, 2))[0], (np.PyArray_MultiIter_DATA(it, 3))[0], subpix, 0, np.PyArray_MultiIter_DATA(it, 4), np.PyArray_MultiIter_DATA(it, 5), &area1, np.PyArray_MultiIter_DATA(it, 6)) _assert_ok(status) # Advance the iterator np.PyArray_MultiIter_NEXT(it) return sum, sumerr, flag else: rin, rout = bkgann # Require float arrays (see note above) rin = np.require(rin, dtype=dt) rout = np.require(rout, dtype=dt) # allocate ouput arrays shape = np.broadcast(x, y, r, rin, rout).shape sum = np.empty(shape, dt) sumerr = np.empty(shape, dt) flag = np.empty(shape, np.short) it = np.broadcast(x, y, r, rin, rout, seg_id, sum, sumerr, flag) while np.PyArray_MultiIter_NOTDONE(it): status = sep_sum_circle( &im, (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], (np.PyArray_MultiIter_DATA(it, 2))[0], (np.PyArray_MultiIter_DATA(it, 5))[0], subpix, 0, &flux1, &fluxerr1, &area1, &flag1) _assert_ok(status) # background subtraction # Note that background output flags are not used. status = sep_sum_circann( &im, (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], (np.PyArray_MultiIter_DATA(it, 3))[0], (np.PyArray_MultiIter_DATA(it, 4))[0], (np.PyArray_MultiIter_DATA(it, 5))[0], 1, SEP_MASK_IGNORE, &bkgflux, &bkgfluxerr, &bkgarea, &bkgflag) _assert_ok(status) if not bkgarea > 0: raise ValueError( "The background annulus does not contain any valid pixels, " "for the object at index " f"{np.PyArray_MultiIter_INDEX(it)}." ) if area1 > 0: flux1 -= bkgflux / bkgarea * area1 bkgfluxerr = bkgfluxerr / bkgarea * area1 fluxerr1 = sqrt(fluxerr1*fluxerr1 + bkgfluxerr*bkgfluxerr) (np.PyArray_MultiIter_DATA(it, 6))[0] = flux1 (np.PyArray_MultiIter_DATA(it, 7))[0] = fluxerr1 (np.PyArray_MultiIter_DATA(it, 8))[0] = flag1 np.PyArray_MultiIter_NEXT(it) return sum, sumerr, flag @cython.boundscheck(False) @cython.wraparound(False) def sum_circann(np.ndarray data not None, x, y, rin, rout, var=None, err=None, gain=None, np.ndarray mask=None, double maskthresh=0.0, seg_id=None, np.ndarray segmap=None, int subpix=5): """sum_circann(data, x, y, rin, rout, err=None, var=None, mask=None, maskthresh=0.0, seg_id=None, segmap=None, gain=None, subpix=5) Sum data in circular annular aperture(s). Parameters ---------- data : `~numpy.ndarray` 2-d array to be summed. x, y, rin, rout : array_like Center coordinates and inner and outer radii of aperture(s). ``x`` corresponds to the second ("fast") axis of the input array and ``y`` corresponds to the first ("slow") axis. ``x, y = (0.0, 0.0)`` corresponds to the center of the first element of the array. These inputs obey numpy broadcasting rules. It is required that ``rout >= rin >= 0.0``. err, var : float or ndarray Error *or* variance (specify at most one). mask : `~numpy.ndarray`, optional Mask array. If supplied, a given pixel is masked if its value is greater than ``maskthresh``. maskthresh : float, optional Threshold for a pixel to be masked. Default is ``0.0``. segmap : `~numpy.ndarray`, optional Segmentation image with dimensions of ``data`` and dtype ``np.int32``. This is an optional input and corresponds to the segmentation map output by `~sep.extract`. seg_id : array_like, optional Array of segmentation ids used to mask additional pixels in the image. Dimensions correspond to the dimensions of ``x`` and ``y``. The behavior differs depending on whether ``seg_id`` is negative or positive. If ``seg_id`` is positive, all pixels belonging to other objects are masked. (Pixel ``j, i`` is masked if ``seg[j, i] != seg_id and seg[j, i] != 0``). If ``seg_id`` is negative, all pixels other than those belonging to the object of interest are masked. (Pixel ``j, i`` is masked if ``seg[j, i] != -seg_id``). NB: must be included if ``segmap`` is provided. gain : float, optional Conversion factor between data array units and poisson counts, used in calculating poisson noise in aperture sum. If ``None`` (default), do not add poisson noise. subpix : int, optional Subpixel sampling factor. Default is 5. Returns ------- sum : `~numpy.ndarray` The sum of the data array within the aperture. sumerr : `~numpy.ndarray` Error on the sum. flags : `~numpy.ndarray` Integer giving flags. (0 if no flags set.) """ cdef double area1 cdef size_t i cdef int status cdef np.broadcast it cdef sep_image im # Test for segmap without seg_id. Nothing happens if seg_id supplied but # without segmap. if (segmap is not None) and (seg_id is None): raise ValueError('`segmap` supplied but not `seg_id`.') _parse_arrays(data, err, var, mask, segmap, &im) im.maskthresh = maskthresh if gain is not None: im.gain = gain # convert inputs to double arrays dt = np.dtype(np.double) dint = np.dtype(np.int32) x = np.require(x, dtype=dt) y = np.require(y, dtype=dt) rin = np.require(rin, dtype=dt) rout = np.require(rout, dtype=dt) # Segmentation image and ids with same dimensions as x, y, etc. if seg_id is not None: seg_id = np.require(seg_id, dtype=dint) if seg_id.shape != x.shape: raise ValueError('Shapes of `x` and `seg_id` do not match') else: seg_id = np.zeros(len(x), dtype=dint) # allocate ouput arrays shape = np.broadcast(x, y, rin, rout).shape sum = np.empty(shape, dt) sumerr = np.empty(shape, dt) flag = np.empty(shape, np.short) # it = np.broadcast(x, y, rin, rout, sum, sumerr, flag) it = np.broadcast(x, y, rin, rout, seg_id, sum, sumerr, flag) while np.PyArray_MultiIter_NOTDONE(it): status = sep_sum_circann( &im, (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], (np.PyArray_MultiIter_DATA(it, 2))[0], (np.PyArray_MultiIter_DATA(it, 3))[0], (np.PyArray_MultiIter_DATA(it, 4))[0], subpix, 0, np.PyArray_MultiIter_DATA(it, 5), np.PyArray_MultiIter_DATA(it, 6), &area1, np.PyArray_MultiIter_DATA(it, 7)) _assert_ok(status) np.PyArray_MultiIter_NEXT(it) return sum, sumerr, flag def sum_ellipse(np.ndarray data not None, x, y, a, b, theta, r=1.0, var=None, err=None, gain=None, np.ndarray mask=None, double maskthresh=0.0, seg_id=None, np.ndarray segmap=None, bkgann=None, int subpix=5): """sum_ellipse(data, x, y, a, b, theta, r, err=None, var=None, mask=None, maskthresh=0.0, seg_id=None, segmap=None, bkgann=None, gain=None, subpix=5) Sum data in elliptical aperture(s). Parameters ---------- data : `~numpy.ndarray` 2-d array to be summed. x, y : array_like Center coordinates and radius (radii) of aperture(s). ``x`` corresponds to the second ("fast") axis of the input array and ``y`` corresponds to the first ("slow") axis. ``x, y = (0.0, 0.0)`` corresponds to the center of the first element of the array. These inputs obey numpy broadcasting rules. a, b, theta : array_like Ellipse parameters. These inputs, along with ``x``, ``y``, and ``r``, obey numpy broadcasting rules. ``a`` is the semi-major axis, ``b`` is the semi-minor axis and ``theta`` is angle in radians between the positive x axis and the major axis. It must be in the range ``[-pi/2, pi/2]``. It is also required that ``a >= b >= 0.0``. r : array_like, optional Scaling factor for the semi-minor and semi-major axes. The actual ellipse used will have semi-major axis ``a * r`` and semi-minor axis ``b * r``. Setting this parameter to a value other than 1.0 is exactly equivalent to scaling both ``a`` and ``b`` by the same value. Default is 1.0. err, var : float or `~numpy.ndarray` Error *or* variance (specify at most one). mask : `~numpy.ndarray`, optional Mask array. If supplied, a given pixel is masked if its value is greater than ``maskthresh``. maskthresh : float, optional Threshold for a pixel to be masked. Default is ``0.0``. segmap : `~numpy.ndarray`, optional Segmentation image with dimensions of ``data`` and dtype ``np.int32``. This is an optional input and corresponds to the segmentation map output by `~sep.extract`. seg_id : array_like, optional Array of segmentation ids used to mask additional pixels in the image. Dimensions correspond to the dimensions of ``x`` and ``y``. The behavior differs depending on whether ``seg_id`` is negative or positive. If ``seg_id`` is positive, all pixels belonging to other objects are masked. (Pixel ``j, i`` is masked if ``seg[j, i] != seg_id and seg[j, i] != 0``). If ``seg_id`` is negative, all pixels other than those belonging to the object of interest are masked. (Pixel ``j, i`` is masked if ``seg[j, i] != -seg_id``). NB: must be included if ``segmap`` is provided. bkgann : tuple, optional Length 2 tuple giving the inner and outer radius of a "background annulus". If supplied, the background is estimated by averaging unmasked pixels in this annulus. If supplied, the inner and outer radii obey numpy broadcasting rules, along with ``x``, ``y``, and ellipse parameters. gain : float, optional Conversion factor between data array units and poisson counts, used in calculating poisson noise in aperture sum. If ``None`` (default), do not add poisson noise. subpix : int, optional Subpixel sampling factor. Default is 5. Returns ------- sum : `~numpy.ndarray` The sum of the data array within the aperture. sumerr : `~numpy.ndarray` Error on the sum. flags : `~numpy.ndarray` Integer giving flags. (0 if no flags set.) """ cdef double flux1, fluxerr1, x1, y1, r1, area1, rin1, rout1 cdef double bkgflux, bkgfluxerr, bkgarea cdef short flag1, bkgflag cdef size_t i cdef int status cdef np.broadcast it cdef sep_image im # Test for seg without seg_id. Nothing happens if seg_id supplied but # without segmap. if (segmap is not None) and (seg_id is None): raise ValueError('`segmap` supplied but not `seg_id`.') _parse_arrays(data, err, var, mask, segmap, &im) im.maskthresh = maskthresh if gain is not None: im.gain = gain # Require that inputs are float64 arrays. See note in circular aperture. dt = np.dtype(np.double) dint = np.dtype(np.int32) x = np.require(x, dtype=dt) y = np.require(y, dtype=dt) a = np.require(a, dtype=dt) b = np.require(b, dtype=dt) theta = np.require(theta, dtype=dt) r = np.require(r, dtype=dt) # Segmentation image and ids with same dimensions as x, y, etc. if seg_id is not None: seg_id = np.require(seg_id, dtype=dint) if seg_id.shape != x.shape: raise ValueError('Shapes of `x` and `seg_id` do not match') else: seg_id = np.zeros(len(x), dtype=dint) if bkgann is None: # allocate ouput arrays shape = np.broadcast(x, y, a, b, theta, r).shape sum = np.empty(shape, dt) sumerr = np.empty(shape, dt) flag = np.empty(shape, np.short) it = np.broadcast(x, y, a, b, theta, r, seg_id, sum, sumerr, flag) while np.PyArray_MultiIter_NOTDONE(it): status = sep_sum_ellipse( &im, (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], (np.PyArray_MultiIter_DATA(it, 2))[0], (np.PyArray_MultiIter_DATA(it, 3))[0], (np.PyArray_MultiIter_DATA(it, 4))[0], (np.PyArray_MultiIter_DATA(it, 5))[0], (np.PyArray_MultiIter_DATA(it, 6))[0], subpix, 0, np.PyArray_MultiIter_DATA(it, 7), np.PyArray_MultiIter_DATA(it, 8), &area1, np.PyArray_MultiIter_DATA(it, 9)) _assert_ok(status) np.PyArray_MultiIter_NEXT(it) return sum, sumerr, flag else: rin, rout = bkgann # Require float arrays (see note above) rin = np.require(rin, dtype=dt) rout = np.require(rout, dtype=dt) # allocate ouput arrays shape = np.broadcast(x, y, a, b, theta, r, rin, rout).shape sum = np.empty(shape, dt) sumerr = np.empty(shape, dt) flag = np.empty(shape, np.short) it = np.broadcast(x, y, a, b, theta, r, rin, rout, seg_id, sum, sumerr, flag) while np.PyArray_MultiIter_NOTDONE(it): status = sep_sum_ellipse( &im, (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], (np.PyArray_MultiIter_DATA(it, 2))[0], (np.PyArray_MultiIter_DATA(it, 3))[0], (np.PyArray_MultiIter_DATA(it, 4))[0], (np.PyArray_MultiIter_DATA(it, 5))[0], (np.PyArray_MultiIter_DATA(it, 8))[0], subpix, 0, &flux1, &fluxerr1, &area1, &flag1) _assert_ok(status) status = sep_sum_ellipann( &im, (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], (np.PyArray_MultiIter_DATA(it, 2))[0], (np.PyArray_MultiIter_DATA(it, 3))[0], (np.PyArray_MultiIter_DATA(it, 4))[0], (np.PyArray_MultiIter_DATA(it, 6))[0], (np.PyArray_MultiIter_DATA(it, 7))[0], (np.PyArray_MultiIter_DATA(it, 8))[0], subpix, 0, &bkgflux, &bkgfluxerr, &bkgarea, &bkgflag) _assert_ok(status) if not bkgarea > 0: raise ValueError( "The background annulus does not contain any valid pixels, " "for the object at index " f"{np.PyArray_MultiIter_INDEX(it)}." ) if (area1 > 0): flux1 -= bkgflux / bkgarea * area1 bkgfluxerr = bkgfluxerr / bkgarea * area1 fluxerr1 = sqrt(fluxerr1*fluxerr1 + bkgfluxerr*bkgfluxerr) (np.PyArray_MultiIter_DATA(it, 9))[0] = flux1 (np.PyArray_MultiIter_DATA(it, 10))[0] = fluxerr1 (np.PyArray_MultiIter_DATA(it, 11))[0] = flag1 #PyArray_MultiIter_NEXT is used to advance the iterator np.PyArray_MultiIter_NEXT(it) return sum, sumerr, flag @cython.boundscheck(False) @cython.wraparound(False) def sum_ellipann(np.ndarray data not None, x, y, a, b, theta, rin, rout, var=None, err=None, gain=None, np.ndarray mask=None, double maskthresh=0.0, seg_id=None, np.ndarray segmap=None, int subpix=5): """sum_ellipann(data, x, y, a, b, theta, rin, rout, err=None, var=None, mask=None, maskthresh=0.0, gain=None, subpix=5) Sum data in elliptical annular aperture(s). Parameters ---------- data : `~numpy.ndarray` 2-d array to be summed. x, y : array_like Center coordinates and radius (radii) of aperture(s). ``x`` corresponds to the second ("fast") axis of the input array and ``y`` corresponds to the first ("slow") axis. ``x, y = (0.0, 0.0)`` corresponds to the center of the first element of the array. These inputs obey numpy broadcasting rules. a, b, theta, rin, rout : array_like Elliptical annulus parameters. These inputs, along with ``x`` and ``y``, obey numpy broadcasting rules. ``a`` is the semi-major axis, ``b`` is the semi-minor axis and ``theta`` is angle in radians between the positive x axis and the major axis. It must be in the range ``[-pi/2, pi/2]``. It is also required that ``a >= b >= 0.0`` and ``rout >= rin >= 0.0`` err, var : float or `~numpy.ndarray` Error *or* variance (specify at most one). mask : `~numpy.ndarray`, optional Mask array. If supplied, a given pixel is masked if its value is greater than ``maskthresh``. maskthresh : float, optional Threshold for a pixel to be masked. Default is ``0.0``. gain : float, optional Conversion factor between data array units and poisson counts, used in calculating poisson noise in aperture sum. If ``None`` (default), do not add poisson noise. segmap : `~numpy.ndarray`, optional Segmentation image with dimensions of ``data`` and dtype ``np.int32``. This is an optional input and corresponds to the segmentation map output by `~sep.extract`. seg_id : array_like, optional Array of segmentation ids used to mask additional pixels in the image. Dimensions correspond to the dimensions of ``x`` and ``y``. The behavior differs depending on whether ``seg_id`` is negative or positive. If ``seg_id`` is positive, all pixels belonging to other objects are masked. (Pixel ``j, i`` is masked if ``seg[j, i] != seg_id and seg[j, i] != 0``). If ``seg_id`` is negative, all pixels other than those belonging to the object of interest are masked. (Pixel ``j, i`` is masked if ``seg[j, i] != -seg_id``). NB: must be included if ``segmap`` is provided. subpix : int, optional Subpixel sampling factor. Default is 5. Returns ------- sum : `~numpy.ndarray` The sum of the data array within the aperture(s). sumerr : `~numpy.ndarray` Error on the sum. flags : `~numpy.ndarray` Integer giving flags. (0 if no flags set.) """ cdef double flux1, fluxerr1, x1, y1, r1, area1, rin1, rout1 cdef double bkgflux, bkgfluxerr, bkgarea cdef short flag1, bkgflag cdef size_t i cdef int status cdef np.broadcast it cdef sep_image im # Test for segmap without seg_id. Nothing happens if seg_id supplied but # without segmap. if (segmap is not None) and (seg_id is None): raise ValueError('`segmap` supplied but not `seg_id`.') _parse_arrays(data, err, var, mask, segmap, &im) im.maskthresh = maskthresh if gain is not None: im.gain = gain # Require that inputs are float64 arrays. See note in circular aperture. dt = np.dtype(np.double) dint = np.dtype(np.int32) x = np.require(x, dtype=dt) y = np.require(y, dtype=dt) a = np.require(a, dtype=dt) b = np.require(b, dtype=dt) theta = np.require(theta, dtype=dt) rin = np.require(rin, dtype=dt) rout = np.require(rout, dtype=dt) # Segmentation image and ids with same dimensions as x, y, etc. if seg_id is not None: seg_id = np.require(seg_id, dtype=dint) if seg_id.shape != x.shape: raise ValueError('Shapes of `x` and `seg_id` do not match') else: seg_id = np.zeros(len(x), dtype=dint) # allocate ouput arrays shape = np.broadcast(x, y, a, b, theta, rin, rout).shape sum = np.empty(shape, dt) sumerr = np.empty(shape, dt) flag = np.empty(shape, np.short) it = np.broadcast(x, y, a, b, theta, rin, rout, seg_id, sum, sumerr, flag) while np.PyArray_MultiIter_NOTDONE(it): status = sep_sum_ellipann( &im, (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], (np.PyArray_MultiIter_DATA(it, 2))[0], (np.PyArray_MultiIter_DATA(it, 3))[0], (np.PyArray_MultiIter_DATA(it, 4))[0], (np.PyArray_MultiIter_DATA(it, 5))[0], (np.PyArray_MultiIter_DATA(it, 6))[0], (np.PyArray_MultiIter_DATA(it, 7))[0], subpix, 0, np.PyArray_MultiIter_DATA(it, 8), np.PyArray_MultiIter_DATA(it, 9), &area1, np.PyArray_MultiIter_DATA(it, 10)) _assert_ok(status) np.PyArray_MultiIter_NEXT(it) return sum, sumerr, flag @cython.boundscheck(False) @cython.wraparound(False) def flux_radius(np.ndarray data not None, x, y, rmax, frac, normflux=None, np.ndarray mask=None, double maskthresh=0.0, seg_id=None, np.ndarray segmap=None, int subpix=5): """flux_radius(data, x, y, rmax, frac, normflux=None, mask=None, maskthresh=0.0, subpix=5) Return radius of a circle enclosing requested fraction of total flux. Parameters ---------- data : `~numpy.ndarray` 2-d array to be summed. x, y : array_like Center coordinates and radius (radii) of aperture(s). ``x`` corresponds to the second ("fast") axis of the input array and ``y`` corresponds to the first ("slow") axis. ``x, y = (0.0, 0.0)`` corresponds to the center of the first element of the array. Shapes must match. rmax : array_like Maximum radius to analyze. Used as normalizing flux if ``normflux`` is None. Shape must match x and y. frac : array_like Requested fraction of light (in range 0 to 1). Can be scalar or array. normflux : array_like, optional Normalizing flux for each position. If not given, the sum within ``rmax`` is used as the normalizing flux. If given, shape must match x, y and rmax. mask : `~numpy.ndarray`, optional Mask array. If supplied, a given pixel is masked if its value is greater than ``maskthresh``. maskthresh : float, optional Threshold for a pixel to be masked. Default is ``0.0``. segmap : `~numpy.ndarray`, optional Segmentation image with dimensions of ``data`` and dtype ``np.int32``. This is an optional input and corresponds to the segmentation map output by `~sep.extract`. seg_id : array_like, optional Array of segmentation ids used to mask additional pixels in the image. Dimensions correspond to the dimensions of ``x`` and ``y``. The behavior differs depending on whether ``seg_id`` is negative or positive. If ``seg_id`` is positive, all pixels belonging to other objects are masked. (Pixel ``j, i`` is masked if ``seg[j, i] != seg_id and seg[j, i] != 0``). If ``seg_id`` is negative, all pixels other than those belonging to the object of interest are masked. (Pixel ``j, i`` is masked if ``seg[j, i] != -seg_id``). NB: must be included if ``segmap`` is provided. subpix : int, optional Subpixel sampling factor. Default is 5. Returns ------- radius : `~numpy.ndarray` The sum of the data array within the aperture(s). Shape is same as ``x``, except if ``frac`` is an array; then the dimension of ``frac`` will be appended. For example, if ``x`` and ``frac`` are both 1-d arrays, the result will be a 2-d array with the trailing dimension corresponding to ``frac``. flags : `~numpy.ndarray` Integer giving flags. Same shape as ``x``. (0 if no flags set.) """ cdef double flux1, fluxerr1, x1, y1, r1, area1, rin1, rout1 cdef double bkgflux, bkgfluxerr, bkgarea cdef short flag1, bkgflag cdef int i cdef int status, fracn cdef short[:] flag cdef double[:, :] radius cdef double[:] fractmp cdef double[:] xtmp cdef double[:] ytmp cdef double[:] rtmp cdef double[:] normfluxbuf cdef double *normfluxptr cdef sep_image im # Test for segmap without seg_id. Nothing happens if seg_id supplied but # without segmap. if (segmap is not None) and (seg_id is None): raise ValueError('`segmap` supplied but not `seg_id`.') _parse_arrays(data, None, None, mask, segmap, &im) im.maskthresh = maskthresh # Require that inputs are float64 arrays with same shape. See note in # circular aperture. # Also require that frac is a contiguous array. dt = np.dtype(np.double) dint = np.dtype(np.int32) x = np.require(x, dtype=dt) y = np.require(y, dtype=dt) rmax = np.require(rmax, dtype=dt) frac = np.require(frac, dtype=dt) inshape = x.shape infracshape = frac.shape if (y.shape != inshape or rmax.shape != inshape): raise ValueError("shape of x, y, and r must match") if seg_id is not None: seg_id = np.require(seg_id, dtype=dint) if seg_id.shape != x.shape: raise ValueError('Shapes of `x` and `seg_id` do not match') else: seg_id = np.zeros(len(x), dtype=dint) # Convert input arrays to 1-d for correct looping and indexing. xtmp = np.ravel(x) ytmp = np.ravel(y) rtmp = np.ravel(rmax) itmp = np.ravel(seg_id) fractmp = np.ravel(np.ascontiguousarray(frac)) fracn = len(fractmp) # optional `normflux` input. normfluxptr = NULL if normflux is not None: normflux = np.require(normflux, dtype=dt) if normflux.shape != inshape: raise ValueError("shape of normflux must match shape of " "x, y and r") normfluxbuf = np.ravel(normflux) normfluxptr = &normfluxbuf[0] # Allocate ouput arrays. (We'll reshape these later to match the # input shapes.) flag = np.empty(len(xtmp), np.short) radius = np.empty((len(xtmp), len(fractmp)), dt) for i in range(len(xtmp)): if normfluxptr != NULL: normfluxptr = &normfluxbuf[i] status = sep_flux_radius(&im, xtmp[i], ytmp[i], rtmp[i], itmp[i], subpix, 0, normfluxptr, &fractmp[0], fracn, &radius[i, 0], &flag[i]) _assert_ok(status) return (np.asarray(radius).reshape(inshape + infracshape), np.asarray(flag).reshape(inshape)) @cython.boundscheck(False) @cython.wraparound(False) def mask_ellipse(np.ndarray arr not None, x, y, a=None, b=None, theta=None, r=1.0, cxx=None, cyy=None, cxy=None): """mask_ellipse(arr, x, y, a, b, theta, r=1.0) Mask ellipse(s) in an array. Set array elements to True (or 1) if they fall within the given ellipse. The ``r`` keyword can be used to scale the ellipse. Equivalently, after converting ``a``, ``b``, ``theta`` to a coefficient ellipse representation (``cxx``, ``cyy``, ``cxy``), pixels that fulfill the condition .. math:: cxx(x_i - x)^2 + cyy(y_i - y)^2 + cxx(x_i - x)(y_i - y) < r^2 will be masked. Parameters ---------- arr : `~numpy.ndarray` Input array to be masked. Array is updated in-place. x, y : array_like Center of ellipse(s). a, b, theta : array_like, optional Parameters defining the extent of the ellipe(s). cxx, cyy, cxy : array_like, optional Alternative ellipse representation. Can be used as ``mask_ellipse(arr, x, y, cxx=..., cyy=..., cxy=...)``. r : array_like, optional Scale factor of ellipse(s). Default is 1. """ cdef np.int64_t w, h cdef np.uint8_t[:,:] buf cdef double cxx_, cyy_, cxy_ dt = np.dtype(np.double) # only boolean arrays supported if not (arr.dtype.type is np.bool_ or arr.dtype.type is np.ubyte): raise ValueError("Array data type not supported: {0:s}" .format(arr.dtype)) _check_array_get_dims(arr, &w, &h) buf = arr.view(dtype=np.uint8) x = np.require(x, dtype=dt) y = np.require(y, dtype=dt) r = np.require(r, dtype=dt) # a, b, theta representation if (a is not None and b is not None and theta is not None): a = np.require(a, dtype=dt) b = np.require(b, dtype=dt) theta = np.require(theta, dtype=dt) it = np.broadcast(x, y, a, b, theta, r) while np.PyArray_MultiIter_NOTDONE(it): sep_ellipse_coeffs((np.PyArray_MultiIter_DATA(it, 2))[0], (np.PyArray_MultiIter_DATA(it, 3))[0], (np.PyArray_MultiIter_DATA(it, 4))[0], &cxx_, &cyy_, &cxy_) sep_set_ellipse(&buf[0, 0], w, h, (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], cxx_, cyy_, cxy_, (np.PyArray_MultiIter_DATA(it, 5))[0], 1) np.PyArray_MultiIter_NEXT(it) # cxx, cyy, cxy representation elif (cxx is not None and cyy is not None and cxy is not None): cxx = np.require(cxx, dtype=dt) cyy = np.require(cyy, dtype=dt) cxy = np.require(cxy, dtype=dt) it = np.broadcast(x, y, cxx, cyy, cxy, r) while np.PyArray_MultiIter_NOTDONE(it): sep_set_ellipse(&buf[0, 0], w, h, (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], (np.PyArray_MultiIter_DATA(it, 2))[0], (np.PyArray_MultiIter_DATA(it, 3))[0], (np.PyArray_MultiIter_DATA(it, 4))[0], (np.PyArray_MultiIter_DATA(it, 5))[0], 1) np.PyArray_MultiIter_NEXT(it) else: raise ValueError("Must specify either a, b and theta or " "cxx, cyy and cxy.") def kron_radius(np.ndarray data not None, x, y, a, b, theta, r, np.ndarray mask=None, double maskthresh=0.0, seg_id=None, np.ndarray segmap=None): """kron_radius(data, x, y, a, b, theta, r, mask=None, maskthresh=0.0, seg_id=None, segmap=None) Calculate Kron "radius" within an ellipse. The Kron radius is given by .. math:: \sum_i r_i I(r_i) / \sum_i I(r_i) where the sum is over all pixels in the aperture and the radius is given in units of ``a`` and ``b``: ``r_i`` is the distance to the pixel relative to the distance to the ellipse specified by ``a``, ``b``, ``theta``. Equivalently, after converting the ellipse parameters to their coefficient representation, ``r_i`` is given by .. math:: r_i^2 = cxx(x_i - x)^2 + cyy(y_i - y)^2 + cxx(x_i - x)(y_i - y) Parameters ---------- data : `~numpy.ndarray` Data array. x, y : array_like Ellipse center(s). a, b, theta : array_like Ellipse parameters. r : array_like "Radius" of ellipse over which to integrate. If the ellipse extent correponds to second moments of an object, this is the number of "isophotal radii" in Source Extractor parlance. A Fixed value of 6 is used in Source Extractor. mask : `numpy.ndarray`, optional An optional mask. maskthresh : float, optional Pixels with mask > maskthresh will be ignored. segmap : `~numpy.ndarray`, optional Segmentation image with dimensions of ``data`` and dtype ``np.int32``. This is an optional input and corresponds to the segmentation map output by `~sep.extract`. seg_id : array_like, optional Array of segmentation ids used to mask additional pixels in the image. Dimensions correspond to the dimensions of ``x`` and ``y``. The behavior differs depending on whether ``seg_id`` is negative or positive. If ``seg_id`` is positive, all pixels belonging to other objects are masked. (Pixel ``j, i`` is masked if ``seg[j, i] != seg_id and seg[j, i] != 0``). If ``seg_id`` is negative, all pixels other than those belonging to the object of interest are masked. (Pixel ``j, i`` is masked if ``seg[j, i] != -seg_id``). NB: must be included if ``segmap`` is provided. Returns ------- kronrad : array_like The Kron radius. flag : array_like Integer value indicating conditions about the aperture or how many masked pixels it contains. """ cdef double cxx, cyy, cxy cdef sep_image im # Test for segmap without seg_id. Nothing happens if seg_id supplied but # without segmap. if (segmap is not None) and (seg_id is None): raise ValueError('`segmap` supplied but not `seg_id`.') _parse_arrays(data, None, None, mask, segmap, &im) im.maskthresh = maskthresh # See note in apercirc on requiring specific array type dt = np.dtype(np.double) dint = np.dtype(np.int32) x = np.require(x, dtype=dt) y = np.require(y, dtype=dt) a = np.require(a, dtype=dt) b = np.require(b, dtype=dt) theta = np.require(theta, dtype=dt) r = np.require(r, dtype=dt) # Segmentation image and ids with same dimensions as x, y, etc. if seg_id is not None: seg_id = np.require(seg_id, dtype=dint) if seg_id.shape != x.shape: raise ValueError('Shapes of `x` and `seg_id` do not match') else: seg_id = np.zeros(len(x), dtype=dint) # allocate output arrays shape = np.broadcast(x, y, a, b, theta, r).shape kr = np.empty(shape, np.float64) flag = np.empty(shape, np.short) it = np.broadcast(x, y, a, b, theta, r, seg_id, kr, flag) while np.PyArray_MultiIter_NOTDONE(it): sep_ellipse_coeffs((np.PyArray_MultiIter_DATA(it, 2))[0], (np.PyArray_MultiIter_DATA(it, 3))[0], (np.PyArray_MultiIter_DATA(it, 4))[0], &cxx, &cyy, &cxy) status = sep_kron_radius(&im, (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], cxx, cyy, cxy, (np.PyArray_MultiIter_DATA(it, 5))[0], (np.PyArray_MultiIter_DATA(it, 6))[0], np.PyArray_MultiIter_DATA(it, 7), np.PyArray_MultiIter_DATA(it, 8)) _assert_ok(status) np.PyArray_MultiIter_NEXT(it) return kr, flag def winpos(np.ndarray data not None, xinit, yinit, sig, np.ndarray mask=None, double maskthresh=0.0, int subpix=11, double minsig=2.0/2.35*0.5): """winpos(data, xinit, yinit, sig, mask=None, maskthresh=0.0, subpix=11, minsig=2.0/2.35*0.5) Calculate more accurate object centroids using 'windowed' algorithm. Starting from the supplied initial center position, an iterative algorithm is used to determine a better object centroid. On each iteration, the centroid is calculated using all pixels within a circular aperture of ``4*sig`` from the current position, weighting pixel positions by their flux and the amplitude of a 2-d Gaussian with sigma ``sig``. Iteration stops when the change in position falls under some threshold or a maximum number of iterations is reached. This is equivalent to ``XWIN_IMAGE`` and ``YWIN_IMAGE`` parameters in Source Extractor (for the correct choice of sigma for each object). **Note:** One should be cautious about using windowed positions in crowded fields or for sources with nearby neighbors, as the iterative algorithm can fail catastrophically. Parameters ---------- data : `~numpy.ndarray` Data array. xinit, yinit : array_like Initial center(s). sig : array_like Gaussian sigma used for weighting pixels. Pixels within a circular aperture of radius 4*sig are included. mask : `numpy.ndarray`, optional An optional mask. maskthresh : float, optional Pixels with mask > maskthresh will be ignored. subpix : int, optional Subpixel sampling used to determine pixel overlap with aperture. 11 is used in Source Extractor. For exact overlap calculation, use 0. minsig : float, optional Minimum bound on ``sig`` parameter. ``sig`` values smaller than this are increased to ``minsig`` to replicate Source Extractor behavior. Source Extractor uses a minimum half-light radius of 0.5 pixels, equivalent to a sigma of 0.5 * 2.0 / 2.35. Returns ------- x, y : np.ndarray New x and y position(s). flag : np.ndarray Flags. """ cdef int status cdef double cxx, cyy, cxy, sigval cdef int niter = 0 # not currently returned cdef sep_image im _parse_arrays(data, None, None, mask, None, &im) im.maskthresh = maskthresh # See note in apercirc on requiring specific array type dt = np.dtype(np.double) xinit = np.require(xinit, dtype=dt) yinit = np.require(yinit, dtype=dt) sig = np.require(sig, dtype=dt) # allocate output arrays shape = np.broadcast(xinit, yinit, sig).shape x = np.empty(shape, np.float64) y = np.empty(shape, np.float64) flag = np.empty(shape, np.short) it = np.broadcast(xinit, yinit, sig, x, y, flag) while np.PyArray_MultiIter_NOTDONE(it): sigval = (np.PyArray_MultiIter_DATA(it, 2))[0] if sigval < minsig: sigval = minsig status = sep_windowed(&im, (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], sigval, subpix, 0, np.PyArray_MultiIter_DATA(it, 3), np.PyArray_MultiIter_DATA(it, 4), &niter, np.PyArray_MultiIter_DATA(it, 5)) _assert_ok(status) np.PyArray_MultiIter_NEXT(it) return x, y, flag def ellipse_coeffs(a, b, theta): """ellipse_coeffs(a, b, theta) Convert from ellipse axes and angle to coefficient representation. Parameters ---------- a, b, theta : array_like Ellipse(s) semi-major, semi-minor axes and position angle respectively. Position angle is radians counter clockwise from positive x axis to major axis, and lies in range ``[-pi/2, pi/2]`` Returns ------- cxx, cyy, cxy : `~numpy.ndarray` Describes the ellipse(s) ``cxx * x^2 + cyy * y^2 + cxy * xy = 1`` """ dt = np.dtype(np.double) a = np.require(a, dtype=dt) b = np.require(b, dtype=dt) theta = np.require(theta, dtype=dt) shape = np.broadcast(a, b, theta).shape cxx = np.empty(shape, dt) cyy = np.empty(shape, dt) cxy = np.empty(shape, dt) it = np.broadcast(a, b, theta, cxx, cyy, cxy) while np.PyArray_MultiIter_NOTDONE(it): sep_ellipse_coeffs((np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], (np.PyArray_MultiIter_DATA(it, 2))[0], np.PyArray_MultiIter_DATA(it, 3), np.PyArray_MultiIter_DATA(it, 4), np.PyArray_MultiIter_DATA(it, 5)) np.PyArray_MultiIter_NEXT(it) return cxx, cyy, cxy def ellipse_axes(cxx, cyy, cxy): """ellipse_axes(cxx, cyy, cxy) Convert from coefficient ellipse representation to ellipse axes and angle. Parameters ---------- cxx, cyy, cxy : array_like Describes the ellipse(s) ``cxx * x**2 + cyy * y**2 + cxy * x * y = 1`` Returns ------- a, b, theta : `~numpy.ndarray` Ellipse(s) semi-major, semi-minor axes and position angle respectively. Position angle is radians counter clockwise from positive x axis to major axis, and lies in range ``(-pi/2, pi/2)`` Raises ------ ValueError If input parameters do not describe an ellipse. """ cdef int status dt = np.dtype(np.double) cxx = np.require(cxx, dtype=dt) cyy = np.require(cyy, dtype=dt) cxy = np.require(cxy, dtype=dt) shape = np.broadcast(cxx, cyy, cxy).shape a = np.empty(shape, dt) b = np.empty(shape, dt) theta = np.empty(shape, dt) status = 0 it = np.broadcast(cxx, cyy, cxy, a, b, theta) while np.PyArray_MultiIter_NOTDONE(it): status = sep_ellipse_axes( (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], (np.PyArray_MultiIter_DATA(it, 2))[0], np.PyArray_MultiIter_DATA(it, 3), np.PyArray_MultiIter_DATA(it, 4), np.PyArray_MultiIter_DATA(it, 5)) if status: break np.PyArray_MultiIter_NEXT(it) if status: raise ValueError( "parameters do not describe ellipse: " "cxx={0:f}, cyy={1:f}, cxy={2:f}".format( (np.PyArray_MultiIter_DATA(it, 0))[0], (np.PyArray_MultiIter_DATA(it, 1))[0], (np.PyArray_MultiIter_DATA(it, 2))[0])) return a, b, theta # ----------------------------------------------------------------------------- # Utility functions def set_extract_pixstack(size_t size): """set_extract_pixstack(size) Set the size in pixels of the internal pixel buffer used in extract(). The current value can be retrieved with get_extract_pixstack. The initial default is 300000. """ sep_set_extract_pixstack(size) def get_extract_pixstack(): """get_extract_pixstack() Get the size in pixels of the internal pixel buffer used in extract(). """ return sep_get_extract_pixstack() def set_sub_object_limit(int limit): """set_sub_object_limit(limit) Set the limit on the number of sub-objects when deblending in extract(). The current value can be retrieved with get_sub_object_limit. The initial default is 1024. """ sep_set_sub_object_limit(limit) def get_sub_object_limit(): """get_sub_object_limit() Get the limit on the number of sub-objects when deblending in extract(). """ return sep_get_sub_object_limit() ================================================ FILE: setup.py ================================================ """Setup file to build the C library.""" import os import re import sys from glob import glob from setuptools import Extension, setup from setuptools_scm import ScmVersion, get_version from setuptools_scm.version import guess_next_version def _new_version_scheme(version: ScmVersion) -> str: return version.format_next_version(guess_next_version, "{guessed}-dev{distance}") def _new_local_scheme(version: ScmVersion) -> str: return version.format_choice("", "-{node}") c_version_string = get_version( version_scheme=_new_version_scheme, local_scheme=_new_local_scheme, ) # from setuptools import setup from setuptools.dist import Distribution # Detect if setup.py is being run with an argument that doesn't require # building anything. (egg info, help commands, etc) options = Distribution.display_option_names + ["help-commands", "help"] is_non_build = ( any("--" + opt in sys.argv for opt in options) or len(sys.argv) == 1 or sys.argv[1] in ("egg_info", "clean", "help") ) # extension module(s): only add if we actually need to build, because we need # to import numpy and cython to build, and we'd rather non-build commands # work when those dependencies are not installed. if is_non_build: extensions = None else: import numpy from Cython.Build import cythonize sourcefiles = ["sep.pyx"] + glob(os.path.join("src", "*.c")) headerfiles = glob(os.path.join("src", "*.h")) include_dirs = [numpy.get_include(), "src"] extensions = [ Extension( "sep", sourcefiles, include_dirs=include_dirs, depends=headerfiles, define_macros=[ ("_USE_MATH_DEFINES", "1"), ("NPY_NO_DEPRECATED_API", "NPY_2_0_API_VERSION"), ], extra_compile_args=['-DSEP_VERSION_STRING="' + c_version_string + '"'], ) ] extensions = cythonize( extensions, language_level=3, ) setup(ext_modules=extensions) ================================================ FILE: src/analyse.c ================================================ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file is part of SEP * * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC * Copyright 2014 SEP developers * * SEP is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SEP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SEP. If not, see . * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include #include #include #include #include #include "extract.h" #include "sep.h" #include "sepcore.h" /********************************** cleanprep ********************************/ /* * Prepare object for cleaning, by calculating mthresh. * This used to be in analyse() / examineiso(). */ int analysemthresh(int objnb, objliststruct * objlist, int minarea, PIXTYPE thresh) { objstruct * obj = objlist->obj + objnb; pliststruct * pixel = objlist->plist; pliststruct * pixt; PIXTYPE tpix; float *heap, *heapt, *heapj, *heapk, swap; int j, k, h, status; status = RETURN_OK; heap = heapt = heapj = heapk = NULL; h = minarea; if (obj->fdnpix < minarea) { obj->mthresh = 0.0; return status; } QCALLOC(heap, float, minarea, status); heapt = heap; /*-- Find the minareath pixel in decreasing intensity for CLEANing */ for (pixt = pixel + obj->firstpix; pixt >= pixel; pixt = pixel + PLIST(pixt, nextpix)) { /* amount pixel is above threshold */ tpix = PLISTPIX(pixt, cdvalue) - (PLISTEXIST(thresh) ? PLISTPIX(pixt, thresh) : thresh); if (h > 0) { *(heapt++) = (float)tpix; } else if (h) { if ((float)tpix > *heap) { *heap = (float)tpix; for (j = 0; (k = (j + 1) << 1) <= minarea; j = k) { heapk = heap + k; heapj = heap + j; if (k != minarea && *(heapk - 1) > *heapk) { heapk++; k++; } if (*heapj <= *(--heapk)) { break; } swap = *heapk; *heapk = *heapj; *heapj = swap; } } } else { fqmedian(heap, minarea); } h--; } obj->mthresh = *heap; exit: free(heap); return status; } /************************* preanalyse **************************************/ void preanalyse(int no, objliststruct * objlist) { objstruct * obj = &objlist->obj[no]; pliststruct *pixel = objlist->plist, *pixt; PIXTYPE peak, cpeak, val, cval; double rv; int64_t x, y, xmin, xmax, ymin, ymax, fdnpix; int64_t xpeak, ypeak, xcpeak, ycpeak; /*----- initialize stacks and bounds */ fdnpix = 0; rv = 0.0; peak = cpeak = -BIG; ymin = xmin = 2 * MAXPICSIZE; /* to be really sure!! */ ymax = xmax = 0; xpeak = ypeak = xcpeak = ycpeak = 0; /* avoid -Wall warnings */ /*----- integrate results */ for (pixt = pixel + obj->firstpix; pixt >= pixel; pixt = pixel + PLIST(pixt, nextpix)) { x = PLIST(pixt, x); y = PLIST(pixt, y); val = PLISTPIX(pixt, value); cval = PLISTPIX(pixt, cdvalue); if (peak < val) { peak = val; xpeak = x; ypeak = y; } if (cpeak < cval) { cpeak = cval; xcpeak = x; ycpeak = y; } rv += cval; if (xmin > x) { xmin = x; } if (xmax < x) { xmax = x; } if (ymin > y) { ymin = y; } if (ymax < y) { ymax = y; } fdnpix++; } obj->fdnpix = fdnpix; obj->fdflux = (float)rv; obj->fdpeak = cpeak; obj->dpeak = peak; obj->xpeak = xpeak; obj->ypeak = ypeak; obj->xcpeak = xcpeak; obj->ycpeak = ycpeak; obj->xmin = xmin; obj->xmax = xmax; obj->ymin = ymin; obj->ymax = ymax; } /******************************** analyse *********************************/ /* If robust = 1, you must have run previously with robust=0 */ void analyse(int no, objliststruct * objlist, int robust, double gain) { objstruct * obj = &objlist->obj[no]; pliststruct *pixel = objlist->plist, *pixt; PIXTYPE peak, val, cval; double thresh, thresh2, t1t2, darea, mx, my, mx2, my2, mxy, rv, rv2, tv, xm, ym, xm2, ym2, xym, temp, temp2, theta, pmx2, pmy2, errx2, erry2, errxy, cvar, cvarsum; int64_t x, y, xmin, ymin, area2, dnpix; preanalyse(no, objlist); dnpix = 0; mx = my = tv = 0.0; mx2 = my2 = mxy = 0.0; cvarsum = errx2 = erry2 = errxy = 0.0; thresh = obj->thresh; peak = obj->dpeak; rv = obj->fdflux; rv2 = rv * rv; thresh2 = (thresh + peak) / 2.0; area2 = 0; xmin = obj->xmin; ymin = obj->ymin; for (pixt = pixel + obj->firstpix; pixt >= pixel; pixt = pixel + PLIST(pixt, nextpix)) { x = PLIST(pixt, x) - xmin; /* avoid roundoff errors on big images */ y = PLIST(pixt, y) - ymin; /* avoid roundoff errors on big images */ cval = PLISTPIX(pixt, cdvalue); tv += (val = PLISTPIX(pixt, value)); if (val > thresh) { dnpix++; } if (val > thresh2) { area2++; } mx += cval * x; my += cval * y; mx2 += cval * x * x; my2 += cval * y * y; mxy += cval * x * y; } /* compute object's properties */ xm = mx / rv; /* mean x */ ym = my / rv; /* mean y */ /* In case of blending, use previous barycenters */ if ((robust) && (obj->flag & SEP_OBJ_MERGED)) { double xn, yn; xn = obj->mx - xmin; yn = obj->my - ymin; xm2 = mx2 / rv + xn * xn - 2 * xm * xn; ym2 = my2 / rv + yn * yn - 2 * ym * yn; xym = mxy / rv + xn * yn - xm * yn - xn * ym; xm = xn; ym = yn; } else { xm2 = mx2 / rv - xm * xm; /* variance of x */ ym2 = my2 / rv - ym * ym; /* variance of y */ xym = mxy / rv - xm * ym; /* covariance */ } /* Calculate the errors on the variances */ for (pixt = pixel + obj->firstpix; pixt >= pixel; pixt = pixel + PLIST(pixt, nextpix)) { x = PLIST(pixt, x) - xmin; /* avoid roundoff errors on big images */ y = PLIST(pixt, y) - ymin; /* avoid roundoff errors on big images */ cvar = PLISTEXIST(var) ? PLISTPIX(pixt, var) : 0.0; if (gain > 0.0) { /* add poisson noise if given */ cval = PLISTPIX(pixt, cdvalue); if (cval > 0.0) { cvar += cval / gain; } } /* Note that this works for both blended and non-blended cases * because xm is set to xn above for the blended case. */ cvarsum += cvar; errx2 += cvar * (x - xm) * (x - xm); erry2 += cvar * (y - ym) * (y - ym); errxy += cvar * (x - xm) * (y - ym); } errx2 /= rv2; erry2 /= rv2; errxy /= rv2; /* Handle fully correlated x/y (which cause a singularity...) */ if ((temp2 = xm2 * ym2 - xym * xym) < 0.00694) { xm2 += 0.0833333; ym2 += 0.0833333; temp2 = xm2 * ym2 - xym * xym; obj->flag |= SEP_OBJ_SINGU; /* handle it for the error parameters */ cvarsum *= 0.08333 / rv2; if (errx2 * erry2 - errxy * errxy < cvarsum * cvarsum) { errx2 += cvarsum; erry2 += cvarsum; } } if ((fabs(temp = xm2 - ym2)) > 0.0) { theta = atan2(2.0 * xym, temp) / 2.0; } else { theta = PI / 4.0; } temp = sqrt(0.25 * temp * temp + xym * xym); pmy2 = pmx2 = 0.5 * (xm2 + ym2); pmx2 += temp; pmy2 -= temp; obj->dnpix = (LONG)dnpix; obj->dflux = tv; obj->mx = xm + xmin; /* add back xmin */ obj->my = ym + ymin; /* add back ymin */ obj->mx2 = xm2; obj->errx2 = errx2; obj->my2 = ym2; obj->erry2 = erry2; obj->mxy = xym; obj->errxy = errxy; obj->a = (float)sqrt(pmx2); obj->b = (float)sqrt(pmy2); obj->theta = theta; obj->cxx = (float)(ym2 / temp2); obj->cyy = (float)(xm2 / temp2); obj->cxy = (float)(-2 * xym / temp2); darea = (double)area2 - dnpix; t1t2 = thresh / thresh2; /* debugging */ /*if (t1t2>0.0 && !PLISTEXIST(thresh)) */ /* was: prefs.dweight_flag */ if (t1t2 > 0.0) { obj->abcor = (darea < 0.0 ? darea : -1.0) / (2 * PI * log(t1t2 < 1.0 ? t1t2 : 0.99) * obj->a * obj->b); if (obj->abcor > 1.0) { obj->abcor = 1.0; } } else { obj->abcor = 1.0; } } ================================================ FILE: src/aperture.c ================================================ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file is part of SEP * * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC * Copyright 2014 SEP developers * * SEP is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SEP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SEP. If not, see . * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include #include #include #include #include #include "overlap.h" #include "sep.h" #include "sepcore.h" #define FLUX_RADIUS_BUFSIZE 64 #define WINPOS_NITERMAX 16 /* Maximum number of steps */ #define WINPOS_NSIG 4 /* Measurement radius */ #define WINPOS_STEPMIN 0.0001 /* Minimum change in position for continuing */ #define WINPOS_FAC 2.0 /* Centroid offset factor (2 for a Gaussian) */ /* Adding (void *) pointers is a GNU C extension, not part of standard C. When compiling on Windows with MS VIsual C compiler need to cast the (void *) to something the size of one byte. */ #if defined(_MSC_VER) #define MSVC_VOID_CAST (char *) #else #define MSVC_VOID_CAST #endif /****************************************************************************/ /* conversions between ellipse representations */ /* return ellipse semi-major and semi-minor axes and position angle, given representation: cxx*x^2 + cyy*y^2 + cxy*x*y = 1 derived from http://mathworld.wolfram.com/Ellipse.html Input requirements: cxx*cyy - cxy*cxy/4. > 0. cxx + cyy > 0. */ int sep_ellipse_axes( double cxx, double cyy, double cxy, double * a, double * b, double * theta ) { double p, q, t; p = cxx + cyy; q = cxx - cyy; t = sqrt(q * q + cxy * cxy); /* Ensure that parameters actually describe an ellipse. */ if ((cxx * cyy - cxy * cxy / 4. <= 0.) || (p <= 0.)) { return NON_ELLIPSE_PARAMS; } *a = sqrt(2. / (p - t)); *b = sqrt(2. / (p + t)); /* theta = 0 if cxy == 0, else (1/2) acot(q/cxy) */ *theta = (cxy == 0.) ? 0. : (q == 0. ? 0. : atan(cxy / q)) / 2.; if (cxx > cyy) { *theta += PI / 2.; } if (*theta > PI / 2.) { *theta -= PI; } return RETURN_OK; } void sep_ellipse_coeffs( double a, double b, double theta, double * cxx, double * cyy, double * cxy ) { double costheta, sintheta; costheta = cos(theta); sintheta = sin(theta); *cxx = costheta * costheta / (a * a) + sintheta * sintheta / (b * b); *cyy = sintheta * sintheta / (a * a) + costheta * costheta / (b * b); *cxy = 2. * costheta * sintheta * (1. / (a * a) - 1. / (b * b)); } /*****************************************************************************/ /* Helper functions for aperture functions */ /* determine the extent of the box that just contains the circle with * parameters x, y, r. xmin is inclusive and xmax is exclusive. * Ensures that box is within image bound and sets a flag if it is not. */ static void boxextent( double x, double y, double rx, double ry, int64_t w, int64_t h, int64_t * xmin, int64_t * xmax, int64_t * ymin, int64_t * ymax, short * flag ) { *xmin = (int64_t)(x - rx + 0.5); *xmax = (int64_t)(x + rx + 1.4999999); *ymin = (int64_t)(y - ry + 0.5); *ymax = (int64_t)(y + ry + 1.4999999); if (*xmin < 0) { *xmin = 0; *flag |= SEP_APER_TRUNC; } if (*xmax > w) { *xmax = w; *flag |= SEP_APER_TRUNC; } if (*ymin < 0) { *ymin = 0; *flag |= SEP_APER_TRUNC; } if (*ymax > h) { *ymax = h; *flag |= SEP_APER_TRUNC; } } static void boxextent_ellipse( double x, double y, double cxx, double cyy, double cxy, double r, int64_t w, int64_t h, int64_t * xmin, int64_t * xmax, int64_t * ymin, int64_t * ymax, short * flag ) { double dxlim, dylim; dxlim = cxx - cxy * cxy / (4.0 * cyy); dxlim = dxlim > 0.0 ? r / sqrt(dxlim) : 0.0; dylim = cyy - cxy * cxy / (4.0 * cxx); dylim = dylim > 0.0 ? r / sqrt(dylim) : 0.0; boxextent(x, y, dxlim, dylim, w, h, xmin, xmax, ymin, ymax, flag); } /* determine oversampled annulus for a circle */ static void oversamp_ann_circle(double r, double * r_in2, double * r_out2) { *r_in2 = r - 0.7072; *r_in2 = (*r_in2 > 0.0) ? (*r_in2) * (*r_in2) : 0.0; *r_out2 = r + 0.7072; *r_out2 = (*r_out2) * (*r_out2); } /* determine oversampled "annulus" for an ellipse */ static void oversamp_ann_ellipse(double r, double b, double * r_in2, double * r_out2) { *r_in2 = r - 0.7072 / b; *r_in2 = (*r_in2 > 0.0) ? (*r_in2) * (*r_in2) : 0.0; *r_out2 = r + 0.7072 / b; *r_out2 = (*r_out2) * (*r_out2); } /*****************************************************************************/ /* circular aperture */ #define APER_NAME sep_sum_circle #define APER_ARGS double r #define APER_DECL double r2, r_in2, r_out2 #define APER_CHECKS \ if (r < 0.0) \ return ILLEGAL_APER_PARAMS #define APER_INIT \ r2 = r * r; \ oversamp_ann_circle(r, &r_in2, &r_out2) #define APER_BOXEXTENT \ boxextent(x, y, r, r, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag) #define APER_EXACT circoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, r) #define APER_RPIX2 dx * dx + dy * dy #define APER_RPIX2_SUBPIX dx1 * dx1 + dy2 #define APER_COMPARE1 rpix2 < r_out2 #define APER_COMPARE2 rpix2 > r_in2 #define APER_COMPARE3 rpix2 < r2 #include "aperture.i" #undef APER_NAME #undef APER_ARGS #undef APER_DECL #undef APER_CHECKS #undef APER_INIT #undef APER_BOXEXTENT #undef APER_EXACT #undef APER_RPIX2 #undef APER_RPIX2_SUBPIX #undef APER_COMPARE1 #undef APER_COMPARE2 #undef APER_COMPARE3 /*****************************************************************************/ /* elliptical aperture */ #define APER_NAME sep_sum_ellipse #define APER_ARGS double a, double b, double theta, double r #define APER_DECL double cxx, cyy, cxy, r2, r_in2, r_out2 #define APER_CHECKS \ if (!(r >= 0.0 && b >= 0.0 && a >= b && theta >= -PI / 2. && theta <= PI / 2.)) \ return ILLEGAL_APER_PARAMS #define APER_INIT \ r2 = r * r; \ oversamp_ann_ellipse(r, b, &r_in2, &r_out2); \ sep_ellipse_coeffs(a, b, theta, &cxx, &cyy, &cxy); \ a *= r; \ b *= r #define APER_BOXEXTENT \ boxextent_ellipse( \ x, y, cxx, cyy, cxy, r, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag \ ) #define APER_EXACT ellipoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, a, b, theta) #define APER_RPIX2 cxx * dx * dx + cyy * dy * dy + cxy * dx * dy #define APER_RPIX2_SUBPIX cxx * dx1 * dx1 + cyy * dy2 + cxy * dx1 * dy #define APER_COMPARE1 rpix2 < r_out2 #define APER_COMPARE2 rpix2 > r_in2 #define APER_COMPARE3 rpix2 < r2 #include "aperture.i" #undef APER_NAME #undef APER_ARGS #undef APER_DECL #undef APER_CHECKS #undef APER_INIT #undef APER_BOXEXTENT #undef APER_EXACT #undef APER_RPIX2 #undef APER_RPIX2_SUBPIX #undef APER_COMPARE1 #undef APER_COMPARE2 #undef APER_COMPARE3 /*****************************************************************************/ /* circular annulus aperture */ #define APER_NAME sep_sum_circann #define APER_ARGS double rin, double rout #define APER_DECL double rin2, rin_in2, rin_out2, rout2, rout_in2, rout_out2 #define APER_CHECKS \ if (!(rin >= 0.0 && rout >= rin)) \ return ILLEGAL_APER_PARAMS #define APER_INIT \ rin2 = rin * rin; \ oversamp_ann_circle(rin, &rin_in2, &rin_out2); \ rout2 = rout * rout; \ oversamp_ann_circle(rout, &rout_in2, &rout_out2) #define APER_BOXEXTENT \ boxextent(x, y, rout, rout, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag) #define APER_EXACT \ (circoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, rout) \ - circoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, rin)) #define APER_RPIX2 dx * dx + dy * dy #define APER_RPIX2_SUBPIX dx1 * dx1 + dy2 #define APER_COMPARE1 (rpix2 < rout_out2) && (rpix2 > rin_in2) #define APER_COMPARE2 (rpix2 > rout_in2) || (rpix2 < rin_out2) #define APER_COMPARE3 (rpix2 < rout2) && (rpix2 > rin2) #include "aperture.i" #undef APER_NAME #undef APER_ARGS #undef APER_DECL #undef APER_CHECKS #undef APER_INIT #undef APER_BOXEXTENT #undef APER_EXACT #undef APER_RPIX2 #undef APER_RPIX2_SUBPIX #undef APER_COMPARE1 #undef APER_COMPARE2 #undef APER_COMPARE3 /*****************************************************************************/ /* elliptical annulus aperture */ #define APER_NAME sep_sum_ellipann #define APER_ARGS double a, double b, double theta, double rin, double rout #define APER_DECL \ double cxx, cyy, cxy; \ double rin2, rin_in2, rin_out2, rout2, rout_in2, rout_out2 #define APER_CHECKS \ if (!(rin >= 0.0 && rout >= rin && b >= 0.0 && a >= b && theta >= -PI / 2. \ && theta <= PI / 2.)) \ return ILLEGAL_APER_PARAMS #define APER_INIT \ rin2 = rin * rin; \ oversamp_ann_ellipse(rin, b, &rin_in2, &rin_out2); \ rout2 = rout * rout; \ oversamp_ann_ellipse(rout, b, &rout_in2, &rout_out2); \ sep_ellipse_coeffs(a, b, theta, &cxx, &cyy, &cxy) #define APER_BOXEXTENT \ boxextent_ellipse( \ x, y, cxx, cyy, cxy, rout, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag \ ) #define APER_EXACT \ (ellipoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, a * rout, b * rout, theta) \ - ellipoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, a * rin, b * rin, theta)) #define APER_RPIX2 cxx * dx * dx + cyy * dy * dy + cxy * dx * dy #define APER_RPIX2_SUBPIX cxx * dx1 * dx1 + cyy * dy2 + cxy * dx1 * dy #define APER_COMPARE1 (rpix2 < rout_out2) && (rpix2 > rin_in2) #define APER_COMPARE2 (rpix2 > rout_in2) || (rpix2 < rin_out2) #define APER_COMPARE3 (rpix2 < rout2) && (rpix2 > rin2) #include "aperture.i" #undef APER_NAME #undef APER_ARGS #undef APER_DECL #undef APER_CHECKS #undef APER_INIT #undef APER_BOXEXTENT #undef APER_EXACT #undef APER_RPIX2 #undef APER_RPIX2_SUBPIX #undef APER_COMPARE1 #undef APER_COMPARE2 #undef APER_COMPARE3 /*****************************************************************************/ /* * This is just different enough from the other aperture functions * that it doesn't quite make sense to use aperture.i. */ int sep_sum_circann_multi( const sep_image * im, double x, double y, double rmax, int64_t n, int id, int subpix, short inflag, double * sum, double * sumvar, double * area, double * maskarea, short * flag ) { PIXTYPE pix, varpix; double dx, dy, dx1, dy2, offset, scale, scale2, tmp, rpix2; int64_t ix, iy, xmin, xmax, ymin, ymax, sx, sy, size, esize, msize, ssize, pos; int status; short errisarray, errisstd; const BYTE *datat, *errort, *maskt, *segt; converter convert, econvert, mconvert, sconvert; double rpix, r_out, r_out2, d, prevbinmargin, nextbinmargin, step, stepdens; int64_t j, ismasked; /* input checks */ if (rmax < 0.0 || n < 1) { return ILLEGAL_APER_PARAMS; } if (subpix < 1) { return ILLEGAL_SUBPIX; } /* clear results arrays */ memset(sum, 0, (size_t)(n * sizeof(double))); memset(sumvar, 0, (size_t)(n * sizeof(double))); memset(area, 0, (size_t)(n * sizeof(double))); if (im->mask) { memset(maskarea, 0, (size_t)(n * sizeof(double))); } /* initializations */ size = esize = msize = ssize = 0; datat = maskt = segt = NULL; errort = im->noise; *flag = 0; varpix = 0.0; scale = 1.0 / subpix; scale2 = scale * scale; offset = 0.5 * (scale - 1.0); r_out = rmax + 1.5; /* margin for interpolation */ r_out2 = r_out * r_out; step = rmax / n; stepdens = 1.0 / step; prevbinmargin = 0.7072; nextbinmargin = step - 0.7072; j = 0; d = 0.; ismasked = 0; errisarray = 0; errisstd = 0; /* get data converter(s) for input array(s) */ if ((status = get_converter(im->dtype, &convert, &size))) { return status; } if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize))) { return status; } if (im->segmap && (status = get_converter(im->sdtype, &sconvert, &ssize))) { return status; } /* get image noise */ if (im->noise_type != SEP_NOISE_NONE) { errisstd = (im->noise_type == SEP_NOISE_STDDEV); if (im->noise) { errisarray = 1; if ((status = get_converter(im->ndtype, &econvert, &esize))) { return status; } } else { varpix = (errisstd) ? im->noiseval * im->noiseval : im->noiseval; } } /* get extent of box */ boxextent(x, y, r_out, r_out, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag); /* loop over rows in the box */ for (iy = ymin; iy < ymax; iy++) { /* set pointers to the start of this row */ pos = (iy % im->h) * im->w + xmin; datat = MSVC_VOID_CAST im->data + pos * size; if (errisarray) { errort = MSVC_VOID_CAST im->noise + pos * esize; } if (im->mask) { maskt = MSVC_VOID_CAST im->mask + pos * msize; } if (im->segmap) { segt = MSVC_VOID_CAST im->segmap + pos * ssize; } /* loop over pixels in this row */ for (ix = xmin; ix < xmax; ix++) { dx = ix - x; dy = iy - y; rpix2 = dx * dx + dy * dy; if (rpix2 < r_out2) { /* get pixel values */ pix = convert(datat); if (errisarray) { varpix = econvert(errort); if (errisstd) { varpix *= varpix; } } ismasked = 0; if (im->mask) { if (mconvert(maskt) > im->maskthresh) { *flag |= SEP_APER_HASMASKED; ismasked = 1; } } /* Segmentation image: If `id` is negative, require segmented pixels within the aperture. If `id` is positive, mask pixels with nonzero segment ids not equal to `id`. */ if (im->segmap) { if (id > 0) { if ((sconvert(segt) > 0.) && (sconvert(segt) != id)) { *flag |= SEP_APER_HASMASKED; ismasked = 1; } } else { if (sconvert(segt) != -1 * id) { *flag |= SEP_APER_HASMASKED; ismasked = 1; } } } /* check if oversampling is needed (close to bin boundary?) */ rpix = sqrt(rpix2); d = fmod(rpix, step); if (d < prevbinmargin || d > nextbinmargin) { dx += offset; dy += offset; for (sy = subpix; sy--; dy += scale) { dx1 = dx; dy2 = dy * dy; for (sx = subpix; sx--; dx1 += scale) { j = (int64_t)(sqrt(dx1 * dx1 + dy2) * stepdens); if (j < n) { if (ismasked) { maskarea[j] += scale2; } else { sum[j] += scale2 * pix; sumvar[j] += scale2 * varpix; } area[j] += scale2; } } } } else /* pixel not close to bin boundary */ { j = (int64_t)(rpix * stepdens); if (j < n) { if (ismasked) { maskarea[j] += 1.0; } else { sum[j] += pix; sumvar[j] += varpix; } area[j] += 1.0; } } } /* closes "if pixel might be within aperture" */ /* increment pointers by one element */ datat += size; if (errisarray) { errort += esize; } maskt += msize; segt += ssize; } } /* correct for masked values */ if (im->mask) { if (inflag & SEP_MASK_IGNORE) { for (j = n; j--;) { area[j] -= maskarea[j]; } } else { for (j = n; j--;) { tmp = area[j] == maskarea[j] ? 0.0 : area[j] / (area[j] - maskarea[j]); sum[j] *= tmp; sumvar[j] *= tmp; } } } /* add poisson noise, only if gain > 0 */ if (im->gain > 0.0) { for (j = n; j--;) { if (sum[j] > 0.0) { sumvar[j] += sum[j] / im->gain; } } } return status; } /* for use in flux_radius */ static double inverse(double xmax, const double * y, int64_t n, double ytarg) { double step; int64_t i; step = xmax / n; i = 0; /* increment i until y[i] is >= to ytarg */ while (i < n && y[i] < ytarg) { i++; } if (i == 0) { if (ytarg <= 0. || y[0] == 0.) { return 0.; } return step * ytarg / y[0]; } if (i == n) { return xmax; } /* note that y[i-1] corresponds to x=step*i. */ return step * (i + (ytarg - y[i - 1]) / (y[i] - y[i - 1])); } int sep_flux_radius( const sep_image * im, double x, double y, double rmax, int id, int subpix, short inflag, const double * fluxtot, const double * fluxfrac, int64_t n, double * r, short * flag ) { int status; int64_t i; double f; double sumbuf[FLUX_RADIUS_BUFSIZE] = {0.}; double sumvarbuf[FLUX_RADIUS_BUFSIZE]; double areabuf[FLUX_RADIUS_BUFSIZE]; double maskareabuf[FLUX_RADIUS_BUFSIZE]; /* measure FLUX_RADIUS_BUFSIZE annuli out to rmax. */ status = sep_sum_circann_multi( im, x, y, rmax, FLUX_RADIUS_BUFSIZE, id, subpix, inflag, sumbuf, sumvarbuf, areabuf, maskareabuf, flag ); /* sum up sumbuf array */ for (i = 1; i < FLUX_RADIUS_BUFSIZE; i++) { sumbuf[i] += sumbuf[i - 1]; } /* if given, use "total flux", else, use sum within rmax. */ f = fluxtot ? *fluxtot : sumbuf[FLUX_RADIUS_BUFSIZE - 1]; /* Use inverse to get the radii corresponding to the requested flux fracs */ for (i = 0; i < n; i++) { r[i] = inverse(rmax, sumbuf, FLUX_RADIUS_BUFSIZE, fluxfrac[i] * f); } return status; } /*****************************************************************************/ /* calculate Kron radius from pixels within an ellipse. */ int sep_kron_radius( const sep_image * im, double x, double y, double cxx, double cyy, double cxy, double r, int id, double * kronrad, short * flag ) { float pix; double r1, v1, r2, area, rpix2, dx, dy; int64_t ix, iy, xmin, xmax, ymin, ymax, pos, size, msize, ssize; int status; int ismasked; const BYTE *datat, *maskt, *segt; converter convert, mconvert, sconvert; r2 = r * r; r1 = v1 = 0.0; area = 0.0; *flag = 0; datat = maskt = segt = NULL; size = msize = ssize = 0; /* get data converter(s) for input array(s) */ if ((status = get_converter(im->dtype, &convert, &size))) { return status; } if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize))) { return status; } if (im->segmap && (status = get_converter(im->sdtype, &sconvert, &ssize))) { return status; } /* get extent of ellipse in x and y */ boxextent_ellipse( x, y, cxx, cyy, cxy, r, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag ); /* loop over rows in the box */ for (iy = ymin; iy < ymax; iy++) { /* set pointers to the start of this row */ pos = (iy % im->h) * im->w + xmin; datat = MSVC_VOID_CAST im->data + pos * size; if (im->mask) { maskt = MSVC_VOID_CAST im->mask + pos * msize; } if (im->segmap) { segt = MSVC_VOID_CAST im->segmap + pos * ssize; } /* loop over pixels in this row */ for (ix = xmin; ix < xmax; ix++) { dx = ix - x; dy = iy - y; rpix2 = cxx * dx * dx + cyy * dy * dy + cxy * dx * dy; if (rpix2 <= r2) { pix = convert(datat); ismasked = 0; if ((pix < -BIG) || (im->mask && mconvert(maskt) > im->maskthresh)) { ismasked = 1; } /* Segmentation image: If `id` is negative, require segmented pixels within the aperture. If `id` is positive, mask pixels with nonzero segment ids not equal to `id`. */ if (im->segmap) { if (id > 0) { if ((sconvert(segt) > 0.) && (sconvert(segt) != id)) { ismasked = 1; } } else { if (sconvert(segt) != -1 * id) { ismasked = 1; } } } if (ismasked > 0) { *flag |= SEP_APER_HASMASKED; } else { r1 += sqrt(rpix2) * pix; v1 += pix; area++; } } /* increment pointers by one element */ datat += size; maskt += msize; segt += ssize; } } if (area == 0) { *flag |= SEP_APER_ALLMASKED; *kronrad = 0.0; } else if (r1 <= 0.0 || v1 <= 0.0) { *flag |= SEP_APER_NONPOSITIVE; *kronrad = 0.0; } else { *kronrad = r1 / v1; } return RETURN_OK; } /* set array values within an ellipse (uc = unsigned char array) */ void sep_set_ellipse( unsigned char * arr, int64_t w, int64_t h, double x, double y, double cxx, double cyy, double cxy, double r, unsigned char val ) { unsigned char * arrt; int64_t xmin, xmax, ymin, ymax, xi, yi; double r2, dx, dy, dy2; short flag; /* not actually used, but input to boxextent */ flag = 0; r2 = r * r; boxextent_ellipse(x, y, cxx, cyy, cxy, r, w, h, &xmin, &xmax, &ymin, &ymax, &flag); for (yi = ymin; yi < ymax; yi++) { arrt = arr + (yi * w + xmin); dy = yi - y; dy2 = dy * dy; for (xi = xmin; xi < xmax; xi++, arrt++) { dx = xi - x; if ((cxx * dx * dx + cyy * dy2 + cxy * dx * dy) <= r2) { *arrt = val; } } } } /*****************************************************************************/ /* * As with `sep_sum_circann_multi`, this is different enough from the other * aperture functions that it doesn't quite make sense to use aperture.i. * * To reproduce SExtractor: * - use sig = obj.hl_radius * 2/2.35. * - use obj.posx/posy for initial position * */ int sep_windowed( const sep_image * im, double x, double y, double sig, int subpix, short inflag, double * xout, double * yout, int * niter, short * flag ) { PIXTYPE pix, varpix; double dx, dy, dx1, dy2, offset, scale, scale2, tmp, dxpos, dypos, weight; double maskarea, maskweight, maskdxpos, maskdypos; double r, tv, twv, sigtv, totarea, overlap, rpix2, invtwosig2; double wpix; int64_t ix, iy, xmin, xmax, ymin, ymax, sx, sy, pos, size, esize, msize; int i, status; short errisarray, errisstd; const BYTE *datat, *errort, *maskt; converter convert, econvert, mconvert; double r2, r_in2, r_out2; /* input checks */ if (sig < 0.0) { return ILLEGAL_APER_PARAMS; } if (subpix < 0) { return ILLEGAL_SUBPIX; } /* initializations */ size = esize = msize = 0; tv = sigtv = 0.0; overlap = totarea = maskweight = 0.0; datat = maskt = NULL; errort = im->noise; *flag = 0; varpix = 0.0; scale = 1.0 / subpix; scale2 = scale * scale; offset = 0.5 * (scale - 1.0); invtwosig2 = 1.0 / (2.0 * sig * sig); errisarray = 0; errisstd = 0; /* Integration radius */ r = WINPOS_NSIG * sig; /* calculate oversampled annulus */ r2 = r * r; oversamp_ann_circle(r, &r_in2, &r_out2); /* get data converter(s) for input array(s) */ if ((status = get_converter(im->dtype, &convert, &size))) { return status; } if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize))) { return status; } /* get image noise */ if (im->noise_type != SEP_NOISE_NONE) { errisstd = (im->noise_type == SEP_NOISE_STDDEV); if (im->noise) { errisarray = 1; if ((status = get_converter(im->ndtype, &econvert, &esize))) { return status; } } else { varpix = (errisstd) ? im->noiseval * im->noiseval : im->noiseval; } } /* iteration loop */ for (i = 0; i < WINPOS_NITERMAX; i++) { /* get extent of box */ boxextent(x, y, r, r, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag); /* TODO: initialize values */ // mx2ph // my2ph // esum, emxy, emx2, emy2, mx2, my2, mxy tv = twv = sigtv = 0.0; overlap = totarea = maskarea = maskweight = 0.0; dxpos = dypos = 0.0; maskdxpos = maskdypos = 0.0; /* loop over rows in the box */ for (iy = ymin; iy < ymax; iy++) { /* set pointers to the start of this row */ pos = (iy % im->h) * im->w + xmin; datat = MSVC_VOID_CAST im->data + pos * size; if (errisarray) { errort = MSVC_VOID_CAST im->noise + pos * esize; } if (im->mask) { maskt = MSVC_VOID_CAST im->mask + pos * msize; } /* loop over pixels in this row */ for (ix = xmin; ix < xmax; ix++) { dx = ix - x; dy = iy - y; rpix2 = dx * dx + dy * dy; if (rpix2 < r_out2) { if (rpix2 > r_in2) /* might be partially in aperture */ { if (subpix == 0) { overlap = circoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, r); } else { dx += offset; dy += offset; overlap = 0.0; for (sy = subpix; sy--; dy += scale) { dx1 = dx; dy2 = dy * dy; for (sx = subpix; sx--; dx1 += scale) { if (dx1 * dx1 + dy2 < r2) { overlap += scale2; } } } } } else { /* definitely fully in aperture */ overlap = 1.0; } /* get pixel value and variance value */ pix = convert(datat); if (errisarray) { varpix = econvert(errort); if (errisstd) { varpix *= varpix; } } /* offset of this pixel from center */ dx = ix - x; dy = iy - y; /* weight by gaussian */ weight = exp(-rpix2 * invtwosig2); if (im->mask && (mconvert(maskt) > im->maskthresh)) { *flag |= SEP_APER_HASMASKED; maskarea += overlap; maskweight += overlap * weight; maskdxpos += overlap * weight * dx; maskdypos += overlap * weight * dy; } else { tv += pix * overlap; wpix = pix * overlap * weight; twv += wpix; dxpos += wpix * dx; dypos += wpix * dy; } totarea += overlap; } /* closes "if pixel might be within aperture" */ /* increment pointers by one element */ datat += size; if (errisarray) { errort += esize; } maskt += msize; } /* closes loop over x */ } /* closes loop over y */ /* we're done looping over pixels for this iteration. * Our summary statistics are: * * tv : total value * twv : total weighted value * dxpos : weighted dx * dypos : weighted dy */ /* Correct for masked values: This effectively makes it as if * the masked pixels had the value of the average unmasked value * in the aperture. */ if (im->mask) { /* this option will probably not yield accurate values */ if (inflag & SEP_MASK_IGNORE) { totarea -= maskarea; } else { tmp = tv / (totarea - maskarea); /* avg unmasked pixel value */ twv += tmp * maskweight; dxpos += tmp * maskdxpos; dypos += tmp * maskdypos; } } /* update center */ if (twv > 0.0) { x += (dxpos /= twv) * WINPOS_FAC; y += (dypos /= twv) * WINPOS_FAC; } else { break; } /* Stop here if position does not change */ if (dxpos * dxpos + dypos * dypos < WINPOS_STEPMIN * WINPOS_STEPMIN) { break; } } /* closes loop over interations */ /* assign output results */ *xout = x; *yout = y; *niter = i + 1; return status; } ================================================ FILE: src/aperture.i ================================================ /* Adding (void *) pointers is a GNU C extension, not part of standard C. When compiling on Windows with MS Visual C compiler need to cast the (void *) to something the size of one byte. */ #if defined(_MSC_VER) #define MSVC_VOID_CAST (char *) #else #define MSVC_VOID_CAST #endif int APER_NAME( const sep_image * im, double x, double y, APER_ARGS, int id, int subpix, short inflag, double * sum, double * sumerr, double * area, short * flag ) { PIXTYPE pix, varpix; double dx, dy, dx1, dy2, offset, scale, scale2, tmp; double tv, sigtv, totarea, maskarea, overlap, rpix2; int64_t ix, iy, xmin, xmax, ymin, ymax, sx, sy, pos, size, esize, msize, ssize; int ismasked, status; short errisarray, errisstd; const BYTE *datat, *errort, *maskt, *segt; converter convert, econvert, mconvert, sconvert; APER_DECL; /* input checks */ APER_CHECKS; if (subpix < 0) { return ILLEGAL_SUBPIX; } /* initializations */ size = esize = msize = ssize = 0; tv = sigtv = 0.0; overlap = totarea = maskarea = 0.0; datat = maskt = segt = NULL; errort = im->noise; *flag = 0; varpix = 0.0; scale = 1.0 / subpix; scale2 = scale * scale; offset = 0.5 * (scale - 1.0); errisarray = 0; errisstd = 0; APER_INIT; /* get data converter(s) for input array(s) */ if ((status = get_converter(im->dtype, &convert, &size))) { return status; } if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize))) { return status; } if (im->segmap && (status = get_converter(im->sdtype, &sconvert, &ssize))) { return status; } /* get image noise */ if (im->noise_type != SEP_NOISE_NONE) { errisstd = (im->noise_type == SEP_NOISE_STDDEV); if (im->noise) { errisarray = 1; if ((status = get_converter(im->ndtype, &econvert, &esize))) { return status; } } else { varpix = (errisstd) ? im->noiseval * im->noiseval : im->noiseval; } } /* get extent of box */ APER_BOXEXTENT; /* loop over rows in the box */ for (iy = ymin; iy < ymax; iy++) { /* set pointers to the start of this row */ pos = (iy % im->h) * im->w + xmin; datat = MSVC_VOID_CAST im->data + pos * size; if (errisarray) { errort = MSVC_VOID_CAST im->noise + pos * esize; } if (im->mask) { maskt = MSVC_VOID_CAST im->mask + pos * msize; } if (im->segmap) { segt = MSVC_VOID_CAST im->segmap + pos * ssize; } /* loop over pixels in this row */ for (ix = xmin; ix < xmax; ix++) { dx = ix - x; dy = iy - y; rpix2 = APER_RPIX2; if (APER_COMPARE1) { if (APER_COMPARE2) /* might be partially in aperture */ { if (subpix == 0) { overlap = APER_EXACT; } else { dx += offset; dy += offset; overlap = 0.0; for (sy = subpix; sy--; dy += scale) { dx1 = dx; dy2 = dy * dy; for (sx = subpix; sx--; dx1 += scale) { rpix2 = APER_RPIX2_SUBPIX; if (APER_COMPARE3) { overlap += scale2; } } } } } else { /* definitely fully in aperture */ overlap = 1.0; } pix = convert(datat); if (errisarray) { varpix = econvert(errort); if (errisstd) { varpix *= varpix; } } ismasked = 0; if (im->mask && (mconvert(maskt) > im->maskthresh)) { ismasked = 1; } /* Segmentation image: If `id` is negative, require segmented pixels within the aperture. If `id` is positive, mask pixels with nonzero segment ids not equal to `id`. */ if (im->segmap) { if (id > 0) { if ((sconvert(segt) > 0.) && (sconvert(segt) != id)) { ismasked = 1; } } else { if (sconvert(segt) != -1 * id) { ismasked = 1; } } } if (ismasked > 0) { *flag |= SEP_APER_HASMASKED; maskarea += overlap; } else { tv += pix * overlap; sigtv += varpix * overlap; } totarea += overlap; } /* closes "if pixel might be within aperture" */ /* increment pointers by one element */ datat += size; if (errisarray) { errort += esize; } maskt += msize; segt += ssize; } } /* correct for masked values */ if (im->mask) { if (inflag & SEP_MASK_IGNORE) { totarea -= maskarea; } else { tv *= (tmp = totarea / (totarea - maskarea)); sigtv *= tmp; } } /* add poisson noise, only if gain > 0 */ if (im->gain > 0.0 && tv > 0.0) { sigtv += tv / im->gain; } *sum = tv; *sumerr = sqrt(sigtv); *area = totarea; return status; } ================================================ FILE: src/background.c ================================================ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file is part of SEP * * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC * Copyright 2014 SEP developers * * SEP is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SEP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SEP. If not, see . * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include #include #include #include #include #include "sep.h" #include "sepcore.h" #define BACK_MINGOODFRAC 0.5 /* min frac with good weights*/ #define QUANTIF_NSIGMA 5 /* histogram limits */ #define QUANTIF_NMAXLEVELS 4096 /* max nb of quantif. levels */ #define QUANTIF_AMIN 4 /* min nb of "mode pixels" */ /* Background info in a single mesh*/ typedef struct { float mode, mean, sigma; /* Background mode, mean and sigma */ int64_t * histo; /* Pointer to a histogram */ int nlevels; /* Nb of histogram bins */ float qzero, qscale; /* Position of histogram */ float lcut, hcut; /* Histogram cuts */ int64_t npix; /* Number of pixels involved */ } backstruct; /* internal helper functions */ void backhisto( backstruct * backmesh, const PIXTYPE * buf, const PIXTYPE * wbuf, int64_t bufsize, int64_t n, int64_t w, int64_t bw, PIXTYPE maskthresh ); void backstat( backstruct * backmesh, const PIXTYPE * buf, const PIXTYPE * wbuf, int64_t bufsize, int64_t n, int64_t w, int64_t bw, PIXTYPE maskthresh ); int filterback(sep_bkg * bkg, int64_t fw, int64_t fh, double fthresh); float backguess(backstruct * bkg, float * mean, float * sigma); int makebackspline(const sep_bkg * bkg, float * map, float * dmap); int sep_background( const sep_image * image, int64_t bw, int64_t bh, int64_t fw, int64_t fh, double fthresh, sep_bkg ** bkg ) { const BYTE *imt, *maskt; int64_t npix; /* size of image */ int64_t nx, ny, nb; /* number of background boxes in x, y, total */ int64_t bufsize; /* size of a "row" of boxes in pixels (w*bh) */ int64_t elsize; /* size (in bytes) of an image array element */ int64_t melsize; /* size (in bytes) of a mask array element */ PIXTYPE *buf, *mbuf; const PIXTYPE *buft, *mbuft; PIXTYPE maskthresh; array_converter convert, mconvert; backstruct *backmesh, *bm; /* info about each background "box" */ sep_bkg * bkgout; /* output */ int64_t j, k, m; int status; status = RETURN_OK; npix = image->w * image->h; bufsize = image->w * bh; maskthresh = image->maskthresh; if (image->mask == NULL) { maskthresh = 0.0; } backmesh = bm = NULL; bkgout = NULL; buf = mbuf = NULL; buft = mbuft = NULL; convert = mconvert = NULL; /* determine number of background boxes */ if ((nx = (image->w - 1) / bw + 1) < 1) { nx = 1; } if ((ny = (image->h - 1) / bh + 1) < 1) { ny = 1; } nb = nx * ny; /* Allocate temp memory & initialize */ QCALLOC(backmesh, backstruct, nx, status); bm = backmesh; /* Allocate the returned struct */ QMALLOC(bkgout, sep_bkg, 1, status); bkgout->w = image->w; bkgout->h = image->h; bkgout->nx = nx; bkgout->ny = ny; bkgout->n = nb; bkgout->bw = bw; bkgout->bh = bh; bkgout->back = NULL; bkgout->sigma = NULL; bkgout->dback = NULL; bkgout->dsigma = NULL; QMALLOC(bkgout->back, float, nb, status); QMALLOC(bkgout->sigma, float, nb, status); QMALLOC(bkgout->dback, float, nb, status); QMALLOC(bkgout->dsigma, float, nb, status); /* cast input array pointers. These are used to step through the arrays. */ imt = (const BYTE *)image->data; maskt = (const BYTE *)image->mask; /* get the correct array converter and element size, based on dtype code */ status = get_array_converter(image->dtype, &convert, &elsize); if (status != RETURN_OK) { goto exit; } if (image->mask) { status = get_array_converter(image->mdtype, &mconvert, &melsize); if (status != RETURN_OK) { goto exit; } } /* If the input array type is not PIXTYPE, allocate a buffer to hold converted values */ if (image->dtype != PIXDTYPE) { QMALLOC(buf, PIXTYPE, bufsize, status); buft = buf; if (status != RETURN_OK) { goto exit; } } if (image->mask && (image->mdtype != PIXDTYPE)) { QMALLOC(mbuf, PIXTYPE, bufsize, status); mbuft = mbuf; if (status != RETURN_OK) { goto exit; } } /* loop over rows of background boxes. * (here, we could loop over individual boxes rather than entire * rows, but this is convenient for converting the image and mask * arrays. This is also how it is originally done in SExtractor, * because the pixel buffers are only read in from disk in * increments of a row of background boxes at a time.) */ for (j = 0; j < ny; j++) { /* if the last row, modify the width appropriately*/ if (j == ny - 1 && npix % bufsize) { bufsize = npix % bufsize; } /* convert this row to PIXTYPE and store in buffer(s)*/ if (image->dtype != PIXDTYPE) { convert(imt, bufsize, buf); } else { buft = (const PIXTYPE *)imt; } if (image->mask) { if (image->mdtype != PIXDTYPE) { mconvert(maskt, bufsize, mbuf); } else { mbuft = (const PIXTYPE *)maskt; } } /* Get clipped mean, sigma for all boxes in the row */ backstat(backmesh, buft, mbuft, bufsize, nx, image->w, bw, maskthresh); /* Allocate histograms in each box in this row. */ bm = backmesh; for (m = nx; m--; bm++) { if (bm->mean <= -BIG) { bm->histo = NULL; } else { QCALLOC(bm->histo, int64_t, bm->nlevels, status); } } backhisto(backmesh, buft, mbuft, bufsize, nx, image->w, bw, maskthresh); /* Compute background statistics from the histograms */ bm = backmesh; for (m = 0; m < nx; m++, bm++) { k = m + nx * j; backguess(bm, bkgout->back + k, bkgout->sigma + k); free(bm->histo); bm->histo = NULL; } /* increment array pointers to next row of background boxes */ imt += elsize * bufsize; if (image->mask) { maskt += melsize * bufsize; } } /* free memory */ free(buf); buf = NULL; free(mbuf); mbuf = NULL; free(backmesh); backmesh = NULL; /* Median-filter and check suitability of the background map */ if ((status = filterback(bkgout, fw, fh, fthresh)) != RETURN_OK) { goto exit; } /* Compute 2nd derivatives along the y-direction */ if ((status = makebackspline(bkgout, bkgout->back, bkgout->dback)) != RETURN_OK) { goto exit; } if ((status = makebackspline(bkgout, bkgout->sigma, bkgout->dsigma)) != RETURN_OK) { goto exit; } *bkg = bkgout; return status; /* If we encountered a problem, clean up any allocated memory */ exit: free(buf); free(mbuf); if (backmesh) { bm = backmesh; for (m = 0; m < nx; m++, bm++) { free(bm->histo); } } free(backmesh); sep_bkg_free(bkgout); *bkg = NULL; return status; } /******************************** backstat **********************************/ /* Compute robust statistical estimators in a row of meshes. */ void backstat( backstruct * backmesh, const PIXTYPE * buf, const PIXTYPE * wbuf, int64_t bufsize, int64_t n, int64_t w, int64_t bw, PIXTYPE maskthresh ) { backstruct * bm; double pix, wpix, sig, mean, sigma, step; const PIXTYPE *buft, *wbuft; PIXTYPE lcut, hcut; int64_t m, h, x, y, npix, wnpix, offset, lastbite; h = bufsize / w; /* height of background boxes in this row */ bm = backmesh; offset = w - bw; step = sqrt(2 / PI) * QUANTIF_NSIGMA / QUANTIF_AMIN; for (m = n; m--; bm++, buf += bw) { if (!m && (lastbite = w % bw)) { bw = lastbite; offset = w - bw; } mean = sigma = 0.0; buft = buf; npix = 0; /* We separate the weighted case at this level to avoid penalty in CPU */ if (wbuf) { wbuft = wbuf; for (y = h; y--; buft += offset, wbuft += offset) { for (x = bw; x--;) { pix = *(buft++); if ((wpix = *(wbuft++)) <= maskthresh && pix > -BIG) { mean += pix; sigma += pix * pix; npix++; } } } } else { for (y = h; y--; buft += offset) { for (x = bw; x--;) { if ((pix = *(buft++)) > -BIG) { mean += pix; sigma += pix * pix; npix++; } } } } /*-- If not enough valid pixels, discard this mesh */ if ((float)npix < (float)(bw * h * BACK_MINGOODFRAC)) { bm->mean = bm->sigma = -BIG; if (wbuf) { wbuf += bw; } continue; } mean /= (double)npix; sigma = (sig = sigma / npix - mean * mean) > 0.0 ? sqrt(sig) : 0.0; lcut = bm->lcut = (PIXTYPE)(mean - 2.0 * sigma); hcut = bm->hcut = (PIXTYPE)(mean + 2.0 * sigma); mean = sigma = 0.0; npix = wnpix = 0; buft = buf; /* do statistics for this mesh again, with cuts */ if (wbuf) { wbuft = wbuf; for (y = h; y--; buft += offset, wbuft += offset) { for (x = bw; x--;) { pix = *(buft++); if ((wpix = *(wbuft++)) <= maskthresh && pix <= hcut && pix >= lcut) { mean += pix; sigma += pix * pix; npix++; } } } } else { for (y = h; y--; buft += offset) { for (x = bw; x--;) { pix = *(buft++); if (pix <= hcut && pix >= lcut) { mean += pix; sigma += pix * pix; npix++; } } } } bm->npix = npix; mean /= (double)npix; sig = sigma / npix - mean * mean; sigma = sig > 0.0 ? sqrt(sig) : 0.0; bm->mean = mean; bm->sigma = sigma; if ((bm->nlevels = (int)(step * npix + 1)) > QUANTIF_NMAXLEVELS) { bm->nlevels = QUANTIF_NMAXLEVELS; } bm->qscale = sigma > 0.0 ? 2 * QUANTIF_NSIGMA * sigma / bm->nlevels : 1.0; bm->qzero = mean - QUANTIF_NSIGMA * sigma; if (wbuf) { wbuf += bw; } } } /******************************** backhisto *********************************/ /* Fill histograms in a row of meshes. */ void backhisto( backstruct * backmesh, const PIXTYPE * buf, const PIXTYPE * wbuf, int64_t bufsize, int64_t n, int64_t w, int64_t bw, PIXTYPE maskthresh ) { backstruct * bm; const PIXTYPE *buft, *wbuft; float qscale, cste, wpix; int64_t * histo; int64_t h, m, x, y, nlevels, lastbite, offset, bin; h = bufsize / w; bm = backmesh; offset = w - bw; for (m = 0; m++ < n; bm++, buf += bw) { if (m == n && (lastbite = w % bw)) { bw = lastbite; offset = w - bw; } /*-- Skip bad meshes */ if (bm->mean <= -BIG) { if (wbuf) { wbuf += bw; } continue; } nlevels = bm->nlevels; histo = bm->histo; qscale = bm->qscale; cste = 0.499999 - bm->qzero / qscale; buft = buf; if (wbuf) { wbuft = wbuf; for (y = h; y--; buft += offset, wbuft += offset) { for (x = bw; x--;) { bin = (int64_t)(*(buft++) / qscale + cste); if ((wpix = *(wbuft++)) <= maskthresh && bin < nlevels && bin >= 0) { (*(histo + bin))++; } } } wbuf += bw; } else { for (y = h; y--; buft += offset) { for (x = bw; x--;) { bin = (int64_t)(*(buft++) / qscale + cste); if (bin >= 0 && bin < nlevels) { (*(histo + bin))++; } } } } } } /******************************* backguess **********************************/ /* Estimate the background from a histogram; */ float backguess(backstruct * bkg, float * mean, float * sigma) #define EPS (1e-4) /* a small number */ { int64_t *histo, *hilow, *hihigh, *histot; unsigned long lowsum, highsum, sum; double ftemp, mea, sig, sig1, med, dpix; int64_t i, n, lcut, hcut, nlevelsm1, pix; /* Leave here if the mesh is already classified as `bad' */ if (bkg->mean <= -BIG) { *mean = *sigma = -BIG; return -BIG; } histo = bkg->histo; hcut = nlevelsm1 = bkg->nlevels - 1; lcut = 0; sig = 10.0 * nlevelsm1; sig1 = 1.0; mea = med = bkg->mean; /* iterate until sigma converges or drops below 0.1 (up to 100 iterations) */ for (n = 100; n-- && (sig >= 0.1) && (fabs(sig / sig1 - 1.0) > EPS);) { sig1 = sig; sum = mea = sig = 0.0; lowsum = highsum = 0; histot = hilow = histo + lcut; hihigh = histo + hcut; for (i = lcut; i <= hcut; i++) { if (lowsum < highsum) { lowsum += *(hilow++); } else { highsum += *(hihigh--); } sum += (pix = *(histot++)); mea += (dpix = (double)pix * i); sig += dpix * i; } med = hihigh >= histo ? ((hihigh - histo) + 0.5 + ((double)highsum - lowsum) / (2.0 * (*hilow > *hihigh ? *hilow : *hihigh))) : 0.0; if (sum) { mea /= (double)sum; sig = sig / sum - mea * mea; } sig = sig > 0.0 ? sqrt(sig) : 0.0; lcut = (ftemp = med - 3.0 * sig) > 0.0 ? (int64_t)(ftemp > 0.0 ? ftemp + 0.5 : ftemp - 0.5) : 0; hcut = (ftemp = med + 3.0 * sig) < nlevelsm1 ? (int64_t)(ftemp > 0.0 ? ftemp + 0.5 : ftemp - 0.5) : nlevelsm1; } *mean = fabs(sig) > 0.0 ? (fabs(bkg->sigma / (sig * bkg->qscale) - 1) < 0.0 ? bkg->qzero + mea * bkg->qscale : (fabs((mea - med) / sig) < 0.3 ? bkg->qzero + (2.5 * med - 1.5 * mea) * bkg->qscale : bkg->qzero + med * bkg->qscale)) : bkg->qzero + mea * bkg->qscale; *sigma = sig * bkg->qscale; return *mean; } /****************************************************************************/ int filterback(sep_bkg * bkg, int64_t fw, int64_t fh, double fthresh) /* Median filterthe background map to remove the contribution * from bright sources. */ { float *back, *sigma, *back2, *sigma2, *bmask, *smask, *sigmat; float d2, d2min, med, val, sval; int64_t i, j, px, py, np, nx, ny, npx, npx2, npy, npy2, dpx, dpy, x, y, nmin; int status; status = RETURN_OK; bmask = smask = back2 = sigma2 = NULL; nx = bkg->nx; ny = bkg->ny; np = bkg->n; npx = fw / 2; npy = fh / 2; npy *= nx; QMALLOC(bmask, float, (2 * npx + 1) * (2 * npy + 1), status); QMALLOC(smask, float, (2 * npx + 1) * (2 * npy + 1), status); QMALLOC(back2, float, np, status); QMALLOC(sigma2, float, np, status); back = bkg->back; sigma = bkg->sigma; val = sval = 0.0; /* to avoid gcc -Wall warnings */ /* Look for `bad' meshes and interpolate them if necessary */ for (i = 0, py = 0; py < ny; py++) { for (px = 0; px < nx; px++, i++) { if ((back2[i] = back[i]) <= -BIG) { /*------ Seek the closest valid mesh */ d2min = BIG; nmin = 0; for (j = 0, y = 0; y < ny; y++) { for (x = 0; x < nx; x++, j++) { if (back[j] > -BIG) { d2 = (float)(x - px) * (x - px) + (y - py) * (y - py); if (d2 < d2min) { val = back[j]; sval = sigma[j]; nmin = 1; d2min = d2; } else if (d2 == d2min) { val += back[j]; sval += sigma[j]; nmin++; } } } } back2[i] = nmin ? val / nmin : 0.0; sigma[i] = nmin ? sval / nmin : 1.0; } } } memcpy(back, back2, (size_t)np * sizeof(float)); /* Do the actual filtering */ for (py = 0; py < np; py += nx) { npy2 = np - py - nx; if (npy2 > npy) { npy2 = npy; } if (npy2 > py) { npy2 = py; } for (px = 0; px < nx; px++) { npx2 = nx - px - 1; if (npx2 > npx) { npx2 = npx; } if (npx2 > px) { npx2 = px; } i = 0; for (dpy = -npy2; dpy <= npy2; dpy += nx) { y = py + dpy; for (dpx = -npx2; dpx <= npx2; dpx++) { x = px + dpx; bmask[i] = back[x + y]; smask[i++] = sigma[x + y]; } } if (fabs((med = fqmedian(bmask, i)) - back[px + py]) >= fthresh) { back2[px + py] = med; sigma2[px + py] = fqmedian(smask, i); } else { back2[px + py] = back[px + py]; sigma2[px + py] = sigma[px + py]; } } } free(bmask); free(smask); bmask = smask = NULL; memcpy(back, back2, np * sizeof(float)); bkg->global = fqmedian(back2, np); free(back2); back2 = NULL; memcpy(sigma, sigma2, np * sizeof(float)); bkg->globalrms = fqmedian(sigma2, np); if (bkg->globalrms <= 0.0) { sigmat = sigma2 + np; for (i = np; i-- && *(--sigmat) > 0.0;) ; if (i >= 0 && i < (np - 1)) { bkg->globalrms = fqmedian(sigmat + 1, np - 1 - i); } else { bkg->globalrms = 1.0; } } free(sigma2); sigma2 = NULL; return status; exit: if (bmask) { free(bmask); } if (smask) { free(smask); } if (back2) { free(back2); } if (sigma2) { free(sigma2); } return status; } /******************************* makebackspline ******************************/ /* * Pre-compute 2nd derivatives along the y direction at background nodes. */ int makebackspline(const sep_bkg * bkg, float * map, float * dmap) { int64_t x, y, nbx, nby, nbym1; int status; float *dmapt, *mapt, *u, temp; u = NULL; status = RETURN_OK; nbx = bkg->nx; nby = bkg->ny; nbym1 = nby - 1; for (x = 0; x < nbx; x++) { mapt = map + x; dmapt = dmap + x; if (nby > 1) { QMALLOC(u, float, nbym1, status); /* temporary array */ *dmapt = *u = 0.0; /* "natural" lower boundary condition */ mapt += nbx; for (y = 1; y < nbym1; y++, mapt += nbx) { temp = -1 / (*dmapt + 4); *(dmapt += nbx) = temp; temp *= *(u++) - 6 * (*(mapt + nbx) + *(mapt - nbx) - 2 * *mapt); *u = temp; } *(dmapt += nbx) = 0.0; /* "natural" upper boundary condition */ for (y = nby - 2; y--;) { temp = *dmapt; dmapt -= nbx; *dmapt = (*dmapt * temp + *(u--)) / 6.0; } free(u); u = NULL; } else { *dmapt = 0.0; } } return status; exit: if (u) { free(u); } return status; } /*****************************************************************************/ float sep_bkg_global(const sep_bkg * bkg) { return bkg->global; } float sep_bkg_globalrms(const sep_bkg * bkg) { return bkg->globalrms; } /*****************************************************************************/ float sep_bkg_pix(const sep_bkg * bkg, int64_t x, int64_t y) /* * return background at position x,y. * (linear interpolation between background map vertices). */ { int64_t nx, ny, xl, yl, pos; double dx, dy, cdx; float * b; float b0, b1, b2, b3; b = bkg->back; nx = bkg->nx; ny = bkg->ny; dx = (double)x / bkg->bw - 0.5; dy = (double)y / bkg->bh - 0.5; dx -= (xl = (int64_t)dx); dy -= (yl = (int64_t)dy); if (xl < 0) { xl = 0; dx -= 1.0; } else if (xl >= nx - 1) { xl = nx < 2 ? 0 : nx - 2; dx += 1.0; } if (yl < 0) { yl = 0; dy -= 1.0; } else if (yl >= ny - 1) { yl = ny < 2 ? 0 : ny - 2; dy += 1.0; } pos = yl * nx + xl; cdx = 1 - dx; b0 = *(b += pos); /* consider when nbackx or nbacky = 1 */ b1 = nx < 2 ? b0 : *(++b); b2 = ny < 2 ? *b : *(b += nx); b3 = nx < 2 ? *b : *(--b); return (float)((1 - dy) * (cdx * b0 + dx * b1) + dy * (dx * b2 + cdx * b3)); } /*****************************************************************************/ int bkg_line_flt_internal( const sep_bkg * bkg, float * values, float * dvalues, int64_t y, float * line ) /* Interpolate background at line y (bicubic spline interpolation between * background map vertices) and save to line. * (values, dvalues) is either (bkg->back, bkg->dback) or * (bkg->sigma, bkg->dsigma) depending on whether the background value or rms * is being evaluated. */ { int64_t i, j, x, yl, nbx, nbxm1, nby, nx, width, ystep, changepoint; int status; float dx, dx0, dy, dy3, cdx, cdy, cdy3, temp, xstep; float *nodebuf, *dnodebuf, *u; float *node, *nodep, *dnode, *blo, *bhi, *dblo, *dbhi; status = RETURN_OK; nodebuf = node = NULL; dnodebuf = dnode = NULL; u = NULL; width = bkg->w; nbx = bkg->nx; nbxm1 = nbx - 1; nby = bkg->ny; if (nby > 1) { dy = (float)y / bkg->bh - 0.5; dy -= (yl = (int64_t)dy); if (yl < 0) { yl = 0; dy -= 1.0; } else if (yl >= nby - 1) { yl = nby < 2 ? 0 : nby - 2; dy += 1.0; } /*-- Interpolation along y for each node */ cdy = 1 - dy; dy3 = (dy * dy * dy - dy); cdy3 = (cdy * cdy * cdy - cdy); ystep = nbx * yl; blo = values + ystep; bhi = blo + nbx; dblo = dvalues + ystep; dbhi = dblo + nbx; QMALLOC(nodebuf, float, nbx, status); /* Interpolated background */ nodep = node = nodebuf; for (x = nbx; x--;) { *(nodep++) = cdy * *(blo++) + dy * *(bhi++) + cdy3 * *(dblo++) + dy3 * *(dbhi++); } /*-- Computation of 2nd derivatives along x */ QMALLOC(dnodebuf, float, nbx, status); /* 2nd derivative along x */ dnode = dnodebuf; if (nbx > 1) { QMALLOC(u, float, nbxm1, status); /* temporary array */ *dnode = *u = 0.0; /* "natural" lower boundary condition */ nodep = node + 1; for (x = nbxm1; --x; nodep++) { temp = -1 / (*(dnode++) + 4); *dnode = temp; temp *= *(u++) - 6 * (*(nodep + 1) + *(nodep - 1) - 2 * *nodep); *u = temp; } *(++dnode) = 0.0; /* "natural" upper boundary condition */ for (x = nbx - 2; x--;) { temp = *(dnode--); *dnode = (*dnode * temp + *(u--)) / 6.0; } free(u); u = NULL; dnode--; } } else { /*-- No interpolation and no new 2nd derivatives needed along y */ node = values; dnode = dvalues; } /*-- Interpolation along x */ if (nbx > 1) { nx = bkg->bw; xstep = 1.0 / nx; changepoint = nx / 2; dx = (xstep - 1) / 2; /* dx of the first pixel in the row */ dx0 = ((nx + 1) % 2) * xstep / 2; /* dx of the 1st pixel right to a bkgnd node */ blo = node; bhi = node + 1; dblo = dnode; dbhi = dnode + 1; for (x = i = 0, j = width; j--; i++, dx += xstep) { if (i == changepoint && x > 0 && x < nbxm1) { blo++; bhi++; dblo++; dbhi++; dx = dx0; } cdx = 1 - dx; *(line++) = (float)(cdx * (*blo + (cdx * cdx - 1) * *dblo) + dx * (*bhi + (dx * dx - 1) * *dbhi)); if (i == nx) { x++; i = 0; } } } else { for (j = width; j--;) { *(line++) = (float)*node; } } exit: if (nodebuf) { free(nodebuf); } if (dnodebuf) { free(dnodebuf); } if (u) { free(u); } return status; } int sep_bkg_line_flt(const sep_bkg * bkg, int64_t y, float * line) /* Interpolate background at line y (bicubic spline interpolation between * background map vertices) and save to line */ { return bkg_line_flt_internal(bkg, bkg->back, bkg->dback, y, line); } /*****************************************************************************/ int sep_bkg_rmsline_flt(const sep_bkg * bkg, int64_t y, float * line) /* Interpolate background rms at line y (bicubic spline interpolation between * background map vertices) and save to line */ { return bkg_line_flt_internal(bkg, bkg->sigma, bkg->dsigma, y, line); } /*****************************************************************************/ /* Multiple dtype functions and convenience functions. * These mostly wrap the two "line" functions above. */ int sep_bkg_line(const sep_bkg * bkg, int64_t y, void * line, int dtype) { array_writer write_array; int64_t size; int status; float * tmpline; if (dtype == SEP_TFLOAT) { return sep_bkg_line_flt(bkg, y, (float *)line); } tmpline = NULL; status = get_array_writer(dtype, &write_array, &size); if (status != RETURN_OK) { goto exit; } QMALLOC(tmpline, float, bkg->w, status); status = sep_bkg_line_flt(bkg, y, tmpline); if (status != RETURN_OK) { goto exit; } /* write to desired output type */ write_array(tmpline, bkg->w, line); exit: free(tmpline); return status; } int sep_bkg_rmsline(const sep_bkg * bkg, int64_t y, void * line, int dtype) { array_writer write_array; int64_t size; int status; float * tmpline; if (dtype == SEP_TFLOAT) { return sep_bkg_rmsline_flt(bkg, y, (float *)line); } tmpline = NULL; status = get_array_writer(dtype, &write_array, &size); if (status != RETURN_OK) { goto exit; } QMALLOC(tmpline, float, bkg->w, status); status = sep_bkg_rmsline_flt(bkg, y, tmpline); if (status != RETURN_OK) { goto exit; } /* write to desired output type */ write_array(tmpline, bkg->w, line); exit: free(tmpline); return status; } int sep_bkg_array(const sep_bkg * bkg, void * arr, int dtype) { int64_t y, width, size; int status; array_writer write_array; float * tmpline; BYTE * line; tmpline = NULL; status = RETURN_OK; width = bkg->w; if (dtype == SEP_TFLOAT) { tmpline = (float *)arr; for (y = 0; y < bkg->h; y++, tmpline += width) { if ((status = sep_bkg_line_flt(bkg, y, tmpline)) != RETURN_OK) { return status; } } return status; } if ((status = get_array_writer(dtype, &write_array, &size)) != RETURN_OK) { goto exit; } QMALLOC(tmpline, float, width, status); line = (BYTE *)arr; for (y = 0; y < bkg->h; y++, line += size * width) { if ((status = sep_bkg_line_flt(bkg, y, tmpline)) != RETURN_OK) { goto exit; } write_array(tmpline, width, line); } exit: free(tmpline); return status; } int sep_bkg_rmsarray(const sep_bkg * bkg, void * arr, int dtype) { int64_t y, width, size; int status; array_writer write_array; float * tmpline; BYTE * line; tmpline = NULL; status = RETURN_OK; width = bkg->w; if (dtype == SEP_TFLOAT) { tmpline = (float *)arr; for (y = 0; y < bkg->h; y++, tmpline += width) { if ((status = sep_bkg_rmsline_flt(bkg, y, tmpline)) != RETURN_OK) { return status; } } return status; } if ((status = get_array_writer(dtype, &write_array, &size)) != RETURN_OK) { goto exit; } QMALLOC(tmpline, float, width, status); line = (BYTE *)arr; for (y = 0; y < bkg->h; y++, line += size * width) { if ((status = sep_bkg_rmsline_flt(bkg, y, tmpline)) != RETURN_OK) { goto exit; } write_array(tmpline, width, line); } exit: free(tmpline); return status; } int sep_bkg_subline(const sep_bkg * bkg, int64_t y, void * line, int dtype) { array_writer subtract_array; int status; int64_t size; PIXTYPE * tmpline; tmpline = NULL; status = RETURN_OK; QMALLOC(tmpline, PIXTYPE, bkg->w, status); status = sep_bkg_line_flt(bkg, y, tmpline); if (status != RETURN_OK) { goto exit; } status = get_array_subtractor(dtype, &subtract_array, &size); if (status != RETURN_OK) { goto exit; } subtract_array(tmpline, bkg->w, line); exit: free(tmpline); return status; } int sep_bkg_subarray(const sep_bkg * bkg, void * arr, int dtype) { array_writer subtract_array; int64_t y, size, width; int status; PIXTYPE * tmpline; BYTE * arrt; tmpline = NULL; status = RETURN_OK; width = bkg->w; arrt = (BYTE *)arr; QMALLOC(tmpline, PIXTYPE, width, status); status = get_array_subtractor(dtype, &subtract_array, &size); if (status != RETURN_OK) { goto exit; } for (y = 0; y < bkg->h; y++, arrt += (width * size)) { if ((status = sep_bkg_line_flt(bkg, y, tmpline)) != RETURN_OK) { goto exit; } subtract_array(tmpline, width, arrt); } exit: free(tmpline); return status; } /*****************************************************************************/ void sep_bkg_free(sep_bkg * bkg) { if (bkg) { free(bkg->back); free(bkg->dback); free(bkg->sigma); free(bkg->dsigma); } free(bkg); } ================================================ FILE: src/convolve.c ================================================ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file is part of SEP * * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC * Copyright 2014 SEP developers * * SEP is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SEP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the f* GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SEP. If not, see . * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include #include #include #include "extract.h" #include "sep.h" #include "sepcore.h" /* Convolve one line of an image with a given kernel. * * buf : arraybuffer struct containing buffer of data to convolve, and image dimension metadata. * conv : convolution kernel * convw, convh : width and height of conv * buf : output convolved line (buf->dw elements long) */ int convolve( arraybuffer * buf, int64_t y, const float * conv, int64_t convw, int64_t convh, PIXTYPE * out ) { int64_t convw2, convn, cx, cy, i, dcx, y0; PIXTYPE * line; /* current line in input buffer */ PIXTYPE * outend; /* end of output buffer */ PIXTYPE *src, *dst, *dstend; outend = out + buf->dw; convw2 = convw / 2; y0 = y - convh / 2; /* start line in image */ /* Cut off top of kernel if it extends beyond image */ if (y0 + convh > buf->dh) { convh = buf->dh - y0; } /* cut off bottom of kernel if it extends beyond image */ if (y0 < 0) { convh = convh + y0; conv += convw * (-y0); y0 = 0; } /* check that buffer has needed lines */ if ((y0 < buf->yoff) || (y0 + convh > buf->yoff + buf->bh)) { return LINE_NOT_IN_BUF; } memset(out, 0, buf->dw * sizeof(PIXTYPE)); /* initialize output to zero */ /* loop over pixels in the convolution kernel */ convn = convw * convh; for (i = 0; i < convn; i++) { cx = i % convw; /* x index in conv kernel */ cy = i / convw; /* y index in conv kernel */ line = buf->bptr + buf->bw * (y0 - buf->yoff + cy); /* start of line */ /* get start and end positions in the source and target line */ dcx = cx - convw2; /* offset of conv pixel from conv center; determines offset between in and out line */ if (dcx >= 0) { src = line + dcx; dst = out; dstend = outend - dcx; } else { src = line; dst = out - dcx; dstend = outend; } /* multiply and add the values */ while (dst < dstend) { *(dst++) += conv[i] * *(src++); } } return RETURN_OK; } /* Apply a matched filter to one line of an image with a given kernel. * * Calculates * * sum(conv_i * f_i / n_i^2) / sqrt(sum(conv_i^2 / n_i^2)) * * at each pixel in the line, where the sums are over i (pixels in the * convolution kernel). * * imbuf : arraybuffer for data array * nbuf : arraybuffer for noise array * y : line to apply the matched filter to in an image * conv : convolution kernel * convw, convh : width and height of conv * work : work buffer (`imbuf->dw` elements long) * out : output line (`imbuf->dw` elements long) * noise_type : indicates contents of nbuf (std dev or variance) * * imbuf and nbuf should have same data dimensions and be on the same line * (their `yoff` fields should be the same). */ int matched_filter( arraybuffer * imbuf, arraybuffer * nbuf, int64_t y, const float * conv, int64_t convw, int64_t convh, PIXTYPE * work, PIXTYPE * out, int noise_type ) { int64_t convw2, convn, cx, cy, i, dcx, y0; PIXTYPE imval, varval; PIXTYPE *imline, *nline; /* current line in input buffer */ PIXTYPE * outend; /* end of output buffer */ PIXTYPE *src_im, *src_n, *dst_num, *dst_denom, *dst_num_end; outend = out + imbuf->dw; convw2 = convw / 2; y0 = y - convh / 2; /* start line in image */ /* Cut off top of kernel if it extends beyond image */ if (y0 + convh > imbuf->dh) { convh = imbuf->dh - y0; } /* cut off bottom of kernel if it extends beyond image */ if (y0 < 0) { convh = convh + y0; conv += convw * (-y0); y0 = 0; } /* check that buffer has needed lines */ if ((y0 < imbuf->yoff) || (y0 + convh > imbuf->yoff + imbuf->bh) || (y0 < nbuf->yoff) || (y0 + convh > nbuf->yoff + nbuf->bh)) { return LINE_NOT_IN_BUF; } /* check that image and noise buffer match */ if ((imbuf->yoff != nbuf->yoff) || (imbuf->dw != nbuf->dw)) { return LINE_NOT_IN_BUF; /* TODO new error status code */ } /* initialize output buffers to zero */ memset(out, 0, imbuf->bw * sizeof(PIXTYPE)); memset(work, 0, imbuf->bw * sizeof(PIXTYPE)); /* loop over pixels in the convolution kernel */ convn = convw * convh; for (i = 0; i < convn; i++) { cx = i % convw; /* x index in conv kernel */ cy = i / convw; /* y index in conv kernel */ imline = imbuf->bptr + imbuf->bw * (y0 - imbuf->yoff + cy); nline = nbuf->bptr + nbuf->bw * (y0 - nbuf->yoff + cy); /* get start and end positions in the source and target line */ dcx = cx - convw2; /* offset of conv pixel from conv center; determines offset between in and out line */ if (dcx >= 0) { src_im = imline + dcx; src_n = nline + dcx; dst_num = out; dst_denom = work; dst_num_end = outend - dcx; } else { src_im = imline; src_n = nline; dst_num = out - dcx; dst_denom = work - dcx; dst_num_end = outend; } /* actually calculate values */ while (dst_num < dst_num_end) { imval = *src_im; varval = (noise_type == SEP_NOISE_VAR) ? (*src_n) : (*src_n) * (*src_n); if (varval != 0.0) { *dst_num += conv[i] * imval / varval; *dst_denom += conv[i] * conv[i] / varval; } src_im++; src_n++; dst_num++; dst_denom++; } } /* close loop over convolution kernel */ /* take the square root of the denominator (work) buffer and divide the * numerator by it. */ for (dst_num = out, dst_denom = work; dst_num < outend; dst_num++, dst_denom++) { *dst_num = *dst_num / sqrt(*dst_denom); } return RETURN_OK; } ================================================ FILE: src/deblend.c ================================================ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file is part of SEP * * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC * Copyright 2014 SEP developers * * SEP is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SEP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SEP. If not, see . * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include #include #include #include #include #include "extract.h" #include "sep.h" #include "sepcore.h" #ifndef RAND_MAX #define RAND_MAX 2147483647 #endif #define NBRANCH 16 /* starting number per branch */ static _Atomic int nsonmax = 1024; /* max. number sub-objects per level */ /* get and set pixstack */ void sep_set_sub_object_limit(int val) { nsonmax = val; } int sep_get_sub_object_limit() { return nsonmax; } int belong(int, objliststruct *, int, objliststruct *); int64_t * createsubmap(objliststruct *, int64_t, int64_t *, int64_t *, int64_t *, int64_t *); int gatherup(objliststruct *, objliststruct *); /******************************** deblend ************************************/ /* Divide a list of isophotal detections in several parts (deblending). NOTE: Even if the object is not deblended, the output objlist threshold is recomputed if a variable threshold is used. This can return two error codes: DEBLEND_OVERFLOW or MEMORY_ALLOC_ERROR */ int deblend( objliststruct * objlistin, objliststruct * objlistout, int deblend_nthresh, double deblend_mincont, int minarea, deblendctx * ctx ) { objstruct * obj; objliststruct debobjlist, debobjlist2; double thresh, thresh0, value0; int64_t h, i, j, k, l, m, subx, suby, subh, subw, xn, nbm = NBRANCH; int64_t * submap; int status; submap = NULL; status = RETURN_OK; xn = deblend_nthresh; l = 0; /* reset global static objlist for deblending */ objliststruct * const objlist = ctx->objlist; memset(objlist, 0, (size_t)xn * sizeof(objliststruct)); /* initialize local object lists */ debobjlist.obj = debobjlist2.obj = NULL; debobjlist.plist = debobjlist2.plist = NULL; debobjlist.nobj = debobjlist2.nobj = 0; debobjlist.npix = debobjlist2.npix = 0; /* Create the submap for the object. * The submap is used in lutz(). We create it here because we may call * lutz multiple times below, and we only want to create it once. */ submap = createsubmap(objlistin, l, &subx, &suby, &subw, &subh); if (!submap) { status = MEMORY_ALLOC_ERROR; goto exit; } for (l = 0; l < objlistin->nobj && status == RETURN_OK; l++) { /* set thresholds of object lists based on object threshold */ thresh0 = objlistin->obj[l].thresh; objlistout->thresh = debobjlist2.thresh = thresh0; /* add input object to global deblending objlist and one local objlist */ if ((status = addobjdeep(l, objlistin, &objlist[0])) != RETURN_OK) { goto exit; } if ((status = addobjdeep(l, objlistin, &debobjlist2)) != RETURN_OK) { goto exit; } value0 = objlist[0].obj[0].fdflux * deblend_mincont; ctx->ok[0] = (short)1; for (k = 1; k < xn; k++) { /*------ Calculate threshold */ thresh = objlistin->obj[l].fdpeak; debobjlist.thresh = thresh > 0.0 ? thresh0 * pow(thresh / thresh0, (double)k / xn) : thresh0; /*--------- Build tree (bottom->up) */ if (objlist[k - 1].nobj >= nsonmax) { status = DEBLEND_OVERFLOW; goto exit; } for (i = 0; i < objlist[k - 1].nobj; i++) { status = lutz( objlistin->plist, submap, subx, suby, subw, &objlist[k - 1].obj[i], &debobjlist, minarea, &ctx->lutz ); if (status != RETURN_OK) { goto exit; } for (j = h = 0; j < debobjlist.nobj; j++) { if (belong(j, &debobjlist, i, &objlist[k - 1])) { debobjlist.obj[j].thresh = debobjlist.thresh; if ((status = addobjdeep(j, &debobjlist, &objlist[k])) != RETURN_OK) { goto exit; } m = objlist[k].nobj - 1; if (m >= nsonmax) { status = DEBLEND_OVERFLOW; goto exit; } if (h >= nbm - 1) { if (!(ctx->son = (short *) realloc(ctx->son, xn * nsonmax * (nbm += 16) * sizeof(short)))) { status = MEMORY_ALLOC_ERROR; goto exit; } } ctx->son[k - 1 + xn * (i + nsonmax * (h++))] = (short)m; ctx->ok[k + xn * m] = (short)1; } } ctx->son[k - 1 + xn * (i + nsonmax * h)] = (short)-1; } } /*------- cut the right branches (top->down) */ for (k = xn - 2; k >= 0; k--) { obj = objlist[k + 1].obj; for (i = 0; i < objlist[k].nobj; i++) { for (m = h = 0; (j = (int64_t)ctx->son[k + xn * (i + nsonmax * h)]) != -1; h++) { if (obj[j].fdflux - obj[j].thresh * obj[j].fdnpix > value0) { m++; } ctx->ok[k + xn * i] &= ctx->ok[k + 1 + xn * j]; } if (m > 1) { for (h = 0; (j = (int64_t)ctx->son[k + xn * (i + nsonmax * h)]) != -1; h++) { if (ctx->ok[k + 1 + xn * j] && obj[j].fdflux - obj[j].thresh * obj[j].fdnpix > value0) { objlist[k + 1].obj[j].flag |= SEP_OBJ_MERGED; status = addobjdeep(j, &objlist[k + 1], &debobjlist2); if (status != RETURN_OK) { goto exit; } } } ctx->ok[k + xn * i] = (short)0; } } } if (ctx->ok[0]) { status = addobjdeep(0, &debobjlist2, objlistout); } else { status = gatherup(&debobjlist2, objlistout); } } exit: if (status == DEBLEND_OVERFLOW) { put_errdetail( "limit of sub-objects reached while deblending. Increase " "it with sep.set_sub_object_limit(), decrease number of deblending " "thresholds ,or increase the detection threshold." ); } free(submap); submap = NULL; free(debobjlist2.obj); free(debobjlist2.plist); for (k = 0; k < xn; k++) { free(objlist[k].obj); free(objlist[k].plist); } free(debobjlist.obj); free(debobjlist.plist); return status; } /******************************* allocdeblend ******************************/ /* Allocate the memory allocated by global pointers in refine.c */ int allocdeblend(int deblend_nthresh, int64_t w, int64_t h, deblendctx * ctx) { int status = RETURN_OK; memset(ctx, 0, sizeof(deblendctx)); QMALLOC(ctx->son, short, deblend_nthresh * nsonmax * NBRANCH, status); QMALLOC(ctx->ok, short, deblend_nthresh * nsonmax, status); QMALLOC(ctx->objlist, objliststruct, deblend_nthresh, status); status = lutzalloc(w, h, &ctx->lutz); if (status != RETURN_OK) { goto exit; } return status; exit: freedeblend(ctx); return status; } /******************************* freedeblend *******************************/ /* Free the memory allocated by global pointers in refine.c */ void freedeblend(deblendctx * ctx) { lutzfree(&ctx->lutz); free(ctx->son); ctx->son = NULL; free(ctx->ok); ctx->ok = NULL; free(ctx->objlist); ctx->objlist = NULL; } /********************************* gatherup **********************************/ /* Collect faint remaining pixels and allocate them to their most probable progenitor. */ int gatherup(objliststruct * objlistin, objliststruct * objlistout) { char * bmp; float *amp, *p, dx, dy, drand, dist, distmin; objstruct *objin = objlistin->obj, *objout, *objt; pliststruct *pixelin = objlistin->plist, *pixelout, *pixt, *pixt2; int64_t i, k, l, *n, iclst, npix, bmwidth, nobj = objlistin->nobj, xs, ys, x, y; int status; bmp = NULL; amp = p = NULL; n = NULL; status = RETURN_OK; objlistout->thresh = objlistin->thresh; QMALLOC(amp, float, nobj, status); QMALLOC(p, float, nobj, status); QMALLOC(n, int64_t, nobj, status); for (i = 1; i < nobj; i++) { analyse(i, objlistin, 0, 0.0); } p[0] = 0.0; bmwidth = objin->xmax - (xs = objin->xmin) + 1; npix = bmwidth * (objin->ymax - (ys = objin->ymin) + 1); if (!(bmp = (char *)calloc(1, npix * sizeof(char)))) { bmp = NULL; status = MEMORY_ALLOC_ERROR; goto exit; } for (objt = objin + (i = 1); i < nobj; i++, objt++) { /*-- Now we have passed the deblending section, reset threshold */ objt->thresh = objlistin->thresh; /* ------------ flag pixels which are already allocated */ for (pixt = pixelin + objin[i].firstpix; pixt >= pixelin; pixt = pixelin + PLIST(pixt, nextpix)) { bmp[(PLIST(pixt, x) - xs) + (PLIST(pixt, y) - ys) * bmwidth] = '\1'; } status = addobjdeep(i, objlistin, objlistout); if (status != RETURN_OK) { goto exit; } n[i] = objlistout->nobj - 1; dist = objt->fdnpix / (2 * PI * objt->abcor * objt->a * objt->b); amp[i] = dist < 70.0 ? objt->thresh * expf(dist) : 4.0 * objt->fdpeak; /* ------------ limitate expansion ! */ if (amp[i] > 4.0 * objt->fdpeak) { amp[i] = 4.0 * objt->fdpeak; } } objout = objlistout->obj; /* DO NOT MOVE !!! */ if (!(pixelout = realloc(objlistout->plist, (objlistout->npix + npix) * plistsize))) { status = MEMORY_ALLOC_ERROR; goto exit; } objlistout->plist = pixelout; k = objlistout->npix; iclst = 0; /* To avoid gcc -Wall warnings */ for (pixt = pixelin + objin->firstpix; pixt >= pixelin; pixt = pixelin + PLIST(pixt, nextpix)) { x = PLIST(pixt, x); y = PLIST(pixt, y); if (!bmp[(x - xs) + (y - ys) * bmwidth]) { pixt2 = pixelout + (l = (k++ * plistsize)); memcpy(pixt2, pixt, (size_t)plistsize); PLIST(pixt2, nextpix) = -1; distmin = 1e+31; for (objt = objin + (i = 1); i < nobj; i++, objt++) { dx = x - objt->mx; dy = y - objt->my; dist = 0.5 * (objt->cxx * dx * dx + objt->cyy * dy * dy + objt->cxy * dx * dy) / objt->abcor; p[i] = p[i - 1] + (dist < 70.0 ? amp[i] * expf(-dist) : 0.0); if (dist < distmin) { distmin = dist; iclst = i; } } if (p[nobj - 1] > 1.0e-31) { drand = p[nobj - 1] * rand_r(&randseed) / (float)RAND_MAX; for (i = 1; i < nobj && p[i] < drand; i++) ; if (i == nobj) { i = iclst; } } else { i = iclst; } objout[n[i]].lastpix = PLIST(pixelout + objout[n[i]].lastpix, nextpix) = l; } } objlistout->npix = k; if (!(objlistout->plist = realloc(pixelout, objlistout->npix * plistsize))) { status = MEMORY_ALLOC_ERROR; } exit: free(bmp); free(amp); free(p); free(n); return status; } /**************** belong (originally in manobjlist.c) ************************/ /* * say if an object is "included" in another. Returns 1 if the pixels of the * first object are included in the pixels of the second object. */ int belong( int corenb, objliststruct * coreobjlist, int shellnb, objliststruct * shellobjlist ) { objstruct *cobj = &(coreobjlist->obj[corenb]), *sobj = &(shellobjlist->obj[shellnb]); pliststruct *cpl = coreobjlist->plist, *spl = shellobjlist->plist, *pixt; int64_t xc = PLIST(cpl + cobj->firstpix, x), yc = PLIST(cpl + cobj->firstpix, y); for (pixt = spl + sobj->firstpix; pixt >= spl; pixt = spl + PLIST(pixt, nextpix)) { if ((PLIST(pixt, x) == xc) && (PLIST(pixt, y) == yc)) { return 1; } } return 0; } /******************************** createsubmap *******************************/ /* Create pixel-index submap for deblending. */ int64_t * createsubmap( objliststruct * objlistin, int64_t no, int64_t * subx, int64_t * suby, int64_t * subw, int64_t * subh ) { objstruct * obj; pliststruct *pixel, *pixt; int64_t i, n, xmin, ymin, w, *pix, *pt, *submap; obj = objlistin->obj + no; pixel = objlistin->plist; *subx = xmin = obj->xmin; *suby = ymin = obj->ymin; *subw = w = obj->xmax - xmin + 1; *subh = obj->ymax - ymin + 1; n = w * *subh; if (!(submap = pix = malloc(n * sizeof(int64_t)))) { return NULL; } pt = pix; for (i = n; i--;) { *(pt++) = -1; } for (i = obj->firstpix; i != -1; i = PLIST(pixt, nextpix)) { pixt = pixel + i; *(pix + (PLIST(pixt, x) - xmin) + (PLIST(pixt, y) - ymin) * w) = i; } return submap; } ================================================ FILE: src/extract.c ================================================ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file is part of SEP * * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC * Copyright 2014 SEP developers * * SEP is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SEP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SEP. If not, see . * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /* Note: was scan.c in SExtractor. */ #include #include #include #include #include #include #include "extract.h" #include "sep.h" #include "sepcore.h" #define DETECT_MAXAREA 0 /* replaces prefs.ext_maxarea */ #define WTHRESH_CONVFAC 1e-4 /* Factor to apply to weights when */ /* thresholding filtered weight-maps */ /* globals */ _Thread_local int64_t plistexist_cdvalue, plistexist_thresh, plistexist_var; _Thread_local int64_t plistoff_value, plistoff_cdvalue, plistoff_thresh, plistoff_var; _Thread_local int64_t plistsize; _Thread_local unsigned int randseed; static _Atomic size_t extract_pixstack = 300000; /* get and set pixstack */ void sep_set_extract_pixstack(size_t val) { extract_pixstack = val; } size_t sep_get_extract_pixstack() { return extract_pixstack; } int sortit( infostruct * info, objliststruct * objlist, int minarea, objliststruct * finalobjlist, int deblend_nthresh, double deblend_mincont, double gain, deblendctx * deblendctx ); int segsortit( infostruct * info, objliststruct * objlist, objliststruct * finalobjlist, double gain ); void plistinit(int hasconv, int hasvar); void clean(objliststruct * objlist, double clean_param, int * survives); PIXTYPE get_mean_thresh(infostruct * info, pliststruct * pixel); int convert_to_catalog( objliststruct * objlist, const int * survives, sep_catalog * cat, int64_t w, int include_pixels ); int arraybuffer_init( arraybuffer * buf, const void * arr, int dtype, int64_t w, int64_t h, int64_t bufw, int64_t bufh ); void arraybuffer_readline(arraybuffer * buf); void arraybuffer_free(arraybuffer * buf); /********************* array buffer functions ********************************/ /* initialize buffer */ /* bufw must be less than or equal to w */ int arraybuffer_init( arraybuffer * buf, const void * arr, int dtype, int64_t w, int64_t h, int64_t bufw, int64_t bufh ) { int status; int64_t yl; status = RETURN_OK; /* data info */ buf->dptr = arr; buf->dw = w; buf->dh = h; /* buffer array info */ buf->bptr = NULL; QMALLOC(buf->bptr, PIXTYPE, bufw * bufh, status); buf->bw = bufw; buf->bh = bufh; /* pointers to within buffer */ buf->midline = buf->bptr + bufw * (bufh / 2); /* ptr to middle buffer line */ buf->lastline = buf->bptr + bufw * (bufh - 1); /* ptr to last buffer line */ status = get_array_converter(dtype, &(buf->readline), &(buf->elsize)); if (status != RETURN_OK) { goto exit; } /* initialize yoff */ buf->yoff = -bufh; /* read in lines until the first data line is one line above midline */ for (yl = 0; yl < bufh - bufh / 2 - 1; yl++) { arraybuffer_readline(buf); } return status; exit: free(buf->bptr); buf->bptr = NULL; return status; } /* read a line into the buffer at the top, shifting all lines down one */ void arraybuffer_readline(arraybuffer * buf) { PIXTYPE * line; int64_t y; /* shift all lines down one */ for (line = buf->bptr; line < buf->lastline; line += buf->bw) { memcpy(line, line + buf->bw, sizeof(PIXTYPE) * buf->bw); } /* which image line now corresponds to the last line in buffer? */ buf->yoff++; y = buf->yoff + buf->bh - 1; if (y < buf->dh) { buf->readline(buf->dptr + buf->elsize * buf->dw * y, buf->dw, buf->lastline); } } void arraybuffer_free(arraybuffer * buf) { free(buf->bptr); buf->bptr = NULL; } /* apply_mask_line: Apply the mask to the image and noise buffers. * * If convolution is off, masked values should simply be not * detected. For this, would be sufficient to either set data to zero or * set noise (if present) to infinity. * * If convolution is on, strictly speaking, a masked (unknown) pixel * should "poison" the convolved value whenever it is present in the * convolution kernel (e.g., NaN behavior). However, practically we'd * rather use a "best guess" for the value. Without doing * interpolation from neighbors, 0 is the best guess (assuming image * is background subtracted). * * For the purpose of the full matched filter, we should set noise = infinity. * * So, this routine sets masked pixels to zero in the image buffer and * infinity in the noise buffer (if present). It affects the first */ void apply_mask_line( arraybuffer * mbuf, arraybuffer * imbuf, arraybuffer * nbuf, double maskthresh ) { int64_t i; for (i = 0; i < mbuf->bw; i++) { if (mbuf->lastline[i] > maskthresh) { imbuf->lastline[i] = 0.0; if (nbuf) { nbuf->lastline[i] = BIG; } } } } /****************************** extract **************************************/ int sep_extract( const sep_image * image, float thresh, int thresh_type, int minarea, const float * conv, int64_t convw, int64_t convh, int filter_type, int deblend_nthresh, double deblend_cont, int clean_flag, double clean_param, sep_catalog ** catalog ) { arraybuffer dbuf, nbuf, mbuf, sbuf; infostruct curpixinfo, initinfo, freeinfo; objliststruct objlist; char newmarker; size_t mem_pixstack; int64_t nposize, oldnposize; int64_t w, h; int64_t co, i, pstop, xl, xl2, yl, cn; int64_t ididx, numids, totnpix; int64_t prevpix, bufh; int64_t stacksize, convn; int status, isvarthresh, isvarnoise, luflag; short trunflag; PIXTYPE relthresh, cdnewsymbol, pixvar, pixsig; float sum; pixstatus cs, ps; infostruct *info, *store, *idinfo; objliststruct * finalobjlist; pliststruct *pixel, *pixt; char * marker; PIXTYPE *scan, *cdscan, *wscan, *dummyscan, *sscan; PIXTYPE *sigscan, *workscan; float * convnorm; int64_t *start, *end, *cumcounts; int * survives; pixstatus * psstack; char errtext[512]; sep_catalog * cat; deblendctx deblendctx; status = RETURN_OK; pixel = NULL; convnorm = NULL; scan = wscan = cdscan = dummyscan = sscan = NULL; sigscan = workscan = NULL; info = NULL; store = NULL; idinfo = NULL; marker = NULL; psstack = NULL; start = end = cumcounts = NULL; finalobjlist = NULL; survives = NULL; cat = NULL; convn = 0; sum = 0.0; w = image->w; h = image->h; numids = (image->numids) ? image->numids : 1; prevpix = 0; isvarthresh = 0; relthresh = 0.0; pixvar = 0.0; pixsig = 0.0; isvarnoise = 0; memset(&deblendctx, 0, sizeof(deblendctx)); mem_pixstack = sep_get_extract_pixstack(); if (image->segmap) { QCALLOC(cumcounts, int64_t, numids, status); QCALLOC(idinfo, infostruct, numids, status); totnpix = 0; for (i = 0; i < numids; i++) { cumcounts[i] = totnpix; totnpix += image->idcounts[i]; } if ((size_t)totnpix > mem_pixstack) { goto exit; } } /* seed the random number generator consistently on each call to get * consistent results. rand_r() is used in deblending. */ randseed = 1; /* Noise characteristics of the image: None, scalar or variable? */ if (image->noise_type == SEP_NOISE_NONE) { } /* nothing to do */ else if (image->noise == NULL) { /* noise is constant; we can set pixel noise now. */ if (image->noise_type == SEP_NOISE_STDDEV) { pixsig = image->noiseval; pixvar = pixsig * pixsig; } else if (image->noise_type == SEP_NOISE_VAR) { pixvar = image->noiseval; pixsig = sqrt(pixvar); } else { return UNKNOWN_NOISE_TYPE; } } else { /* noise is variable; we deal with setting pixvar and pixsig at each * pixel. */ isvarnoise = 1; } /* Deal with relative thresholding. (For an absolute threshold * nothing needs to be done, as `thresh` should already contain the constant * threshold, and `isvarthresh` is already 0.) */ if (thresh_type == SEP_THRESH_REL) { /* The image must have noise information. */ if (image->noise_type == SEP_NOISE_NONE) { return RELTHRESH_NO_NOISE; } isvarthresh = isvarnoise; /* threshold is variable if noise is */ if (isvarthresh) { relthresh = thresh; /* used below to set `thresh` for each pixel. */ } else { /* thresh is constant; convert relative threshold to absolute */ thresh *= pixsig; } } /* this is input `thresh` regardless of thresh_type. */ objlist.thresh = thresh; /*Allocate memory for buffers */ stacksize = w + 1; QMALLOC(info, infostruct, stacksize, status); QCALLOC(store, infostruct, stacksize, status); QMALLOC(marker, char, stacksize, status); QMALLOC(dummyscan, PIXTYPE, stacksize, status); QMALLOC(psstack, pixstatus, stacksize, status); QCALLOC(start, int64_t, stacksize, status); QMALLOC(end, int64_t, stacksize, status); if ((status = allocdeblend(deblend_nthresh, w, h, &deblendctx)) != RETURN_OK) { goto exit; } /* Initialize buffers for input array(s). * The buffer size depends on whether or not convolution is active. * If not convolving, the buffer size is just a single line. If convolving, * the buffer height equals the height of the convolution kernel. */ bufh = conv ? convh : 1; status = arraybuffer_init(&dbuf, image->data, image->dtype, w, h, stacksize, bufh); if (status != RETURN_OK) { goto exit; } if (isvarnoise) { status = arraybuffer_init(&nbuf, image->noise, image->ndtype, w, h, stacksize, bufh); if (status != RETURN_OK) { goto exit; } } if (image->mask) { status = arraybuffer_init(&mbuf, image->mask, image->mdtype, w, h, stacksize, bufh); if (status != RETURN_OK) { goto exit; } } if (image->segmap) { status = arraybuffer_init(&sbuf, image->segmap, image->sdtype, w, h, stacksize, bufh); if (status != RETURN_OK) { goto exit; } } /* `scan` (or `wscan`) is always a pointer to the current line being * processed. It might be the only line in the buffer, or it might be the * middle line. */ scan = dbuf.midline; if (isvarnoise) { wscan = nbuf.midline; } /* More initializations */ initinfo.pixnb = 0; initinfo.flag = 0; initinfo.firstpix = initinfo.lastpix = -1; if (image->segmap) { sscan = sbuf.midline; for (i = 0; i < numids; i++) { idinfo[i].pixnb = 0; idinfo[i].flag = 0; idinfo[i].firstpix = idinfo[i].lastpix = -1; } } for (xl = 0; xl < stacksize; xl++) { marker[xl] = 0; dummyscan[xl] = -BIG; } co = pstop = 0; if (image->segmap) { objlist.nobj = numids; QMALLOC(objlist.obj, objstruct, numids, status); } else { objlist.nobj = 1; } curpixinfo.pixnb = 1; /* Init finalobjlist */ QMALLOC(finalobjlist, objliststruct, 1, status); finalobjlist->obj = NULL; finalobjlist->plist = NULL; finalobjlist->nobj = finalobjlist->npix = 0; /* Allocate memory for the pixel list */ plistinit((conv != NULL), (image->noise_type != SEP_NOISE_NONE)); if (!(pixel = objlist.plist = malloc(nposize = mem_pixstack * plistsize))) { status = MEMORY_ALLOC_ERROR; goto exit; } /*----- at the beginning, "free" object fills the whole pixel list */ freeinfo.firstpix = 0; freeinfo.lastpix = nposize - plistsize; pixt = pixel; for (i = plistsize; i < nposize; i += plistsize, pixt += plistsize) { PLIST(pixt, nextpix) = i; } PLIST(pixt, nextpix) = -1; /* can only use a matched filter when convolving and when there is a noise * array */ if (!(conv && isvarnoise)) { filter_type = SEP_FILTER_CONV; } if (conv) { /* allocate memory for convolved buffers */ QMALLOC(cdscan, PIXTYPE, stacksize, status); if (filter_type == SEP_FILTER_MATCHED) { QMALLOC(sigscan, PIXTYPE, stacksize, status); QMALLOC(workscan, PIXTYPE, stacksize, status); } /* normalize the filter */ convn = convw * convh; QMALLOC(convnorm, PIXTYPE, convn, status); for (i = 0; i < convn; i++) { sum += fabs(conv[i]); } for (i = 0; i < convn; i++) { convnorm[i] = conv[i] / sum; } } /*----- MAIN LOOP ------ */ for (yl = 0; yl <= h; yl++) { ps = COMPLETE; cs = NONOBJECT; /* Need an empty line for Lutz' algorithm to end gracely */ if (yl == h) { if (conv) { free(cdscan); // cdscan set to dummyscan below if (filter_type == SEP_FILTER_MATCHED) { for (xl = 0; xl < stacksize; xl++) { sigscan[xl] = -BIG; } } } cdscan = dummyscan; } else { arraybuffer_readline(&dbuf); if (isvarnoise) { arraybuffer_readline(&nbuf); } if (image->mask) { arraybuffer_readline(&mbuf); apply_mask_line(&mbuf, &dbuf, (isvarnoise ? &nbuf : NULL), image->maskthresh); } if (image->segmap) { arraybuffer_readline(&sbuf); } /* filter the lines */ if (conv) { status = convolve(&dbuf, yl, convnorm, convw, convh, cdscan); if (status != RETURN_OK) { goto exit; } if (filter_type == SEP_FILTER_MATCHED) { status = matched_filter( &dbuf, &nbuf, yl, convnorm, convw, convh, workscan, sigscan, image->noise_type ); if (status != RETURN_OK) { goto exit; } } } else { cdscan = scan; } } trunflag = (yl == 0 || yl == h - 1) ? SEP_OBJ_TRUNC : 0; for (xl = 0; xl <= w; xl++) { if (xl == w) { cdnewsymbol = -BIG; } else { cdnewsymbol = cdscan[xl]; } newmarker = marker[xl]; /* marker at this pixel */ marker[xl] = 0; curpixinfo.flag = trunflag; /* set pixel variance/noise based on noise array */ if (isvarthresh) { if (xl == w || yl == h) { pixsig = pixvar = 0.0; } else if (image->noise_type == SEP_NOISE_VAR) { pixvar = wscan[xl]; pixsig = sqrt(pixvar); } else if (image->noise_type == SEP_NOISE_STDDEV) { pixsig = wscan[xl]; pixvar = pixsig * pixsig; } else { status = UNKNOWN_NOISE_TYPE; goto exit; } /* set `thresh` (This is needed later, even * if filter_type is SEP_FILTER_MATCHED */ thresh = relthresh * pixsig; } /* luflag: is pixel above thresh (Y/N)? */ /* First check if segmap exists */ if (image->segmap) { if ((sscan[xl] > 0) && (xl != w) && (yl != h)) { if (xl == 0 || xl == w - 1) { curpixinfo.flag |= SEP_OBJ_TRUNC; } for (ididx = 0; ididx < numids; ididx++) { if (image->segids[ididx] == (int64_t)sscan[xl]) { pixt = pixel + prevpix * plistsize; prevpix = cumcounts[ididx] + idinfo[ididx].pixnb; pixt = pixel + prevpix * plistsize; PLIST(pixt, x) = xl; PLIST(pixt, y) = yl; PLIST(pixt, value) = scan[xl]; if (PLISTEXIST(cdvalue)) { PLISTPIX(pixt, cdvalue) = cdnewsymbol; }; if (PLISTEXIST(var)) { PLISTPIX(pixt, var) = pixvar; }; if (PLISTEXIST(thresh)) { PLISTPIX(pixt, thresh) = thresh; }; if (idinfo[ididx].pixnb == 0) { idinfo[ididx].firstpix = prevpix * plistsize; idinfo[ididx].pixnb = 1; } else if (idinfo[ididx].pixnb == image->idcounts[ididx] - 1) { idinfo[ididx].pixnb++; idinfo[ididx].lastpix = prevpix * plistsize; PLIST(pixt, nextpix) = -1; } else { idinfo[ididx].pixnb++; }; break; } } } } else { if (filter_type == SEP_FILTER_MATCHED) { luflag = ((xl != w) && (sigscan[xl] > relthresh)) ? 1 : 0; } else { luflag = cdnewsymbol > thresh ? 1 : 0; } if (luflag) { /* flag the current object if we're near the image bounds */ if (xl == 0 || xl == w - 1) { curpixinfo.flag |= SEP_OBJ_TRUNC; }; /* point pixt to first free pixel in pixel list */ /* and increment the "first free pixel" */ pixt = pixel + (cn = freeinfo.firstpix); freeinfo.firstpix = PLIST(pixt, nextpix); curpixinfo.lastpix = curpixinfo.firstpix = cn; /* set values for the new pixel */ PLIST(pixt, nextpix) = -1; PLIST(pixt, x) = xl; PLIST(pixt, y) = yl; PLIST(pixt, value) = scan[xl]; if (PLISTEXIST(cdvalue)) { PLISTPIX(pixt, cdvalue) = cdnewsymbol; }; if (PLISTEXIST(var)) { PLISTPIX(pixt, var) = pixvar; }; if (PLISTEXIST(thresh)) { PLISTPIX(pixt, thresh) = thresh; }; /* Check if we have run out of free pixels in objlist.plist */ if (freeinfo.firstpix == freeinfo.lastpix) { status = PIXSTACK_FULL; sprintf( errtext, "The limit of %d active object pixels over the " "detection threshold was reached. Check that " "the image is background subtracted and the " "detection threshold is not too low. If you " "need to increase the limit, use " "set_extract_pixstack.", (int)mem_pixstack ); put_errdetail(errtext); goto exit; /* The code in the rest of this block increases the * stack size as needed. Currently, it is never * executed. This is because it isn't clear that * this is a good idea: most times when the stack * overflows it is due to user error: too-low * threshold or image not background subtracted. */ /* increase the stack size */ oldnposize = nposize; mem_pixstack = (int)(mem_pixstack * 2); nposize = mem_pixstack * plistsize; pixel = realloc(pixel, nposize); objlist.plist = pixel; if (!pixel) { status = MEMORY_ALLOC_ERROR; goto exit; } /* set next free pixel to the start of the new block * and link up all the pixels in the new block */ PLIST(pixel + freeinfo.firstpix, nextpix) = oldnposize; pixt = pixel + oldnposize; for (i = oldnposize + plistsize; i < nposize; i += plistsize, pixt += plistsize) { PLIST(pixt, nextpix) = i; } PLIST(pixt, nextpix) = -1; /* last free pixel is now at the end of the new block */ freeinfo.lastpix = nposize - plistsize; } /*------------------------------------------------------------*/ /* if the current status on this line is not already OBJECT... */ /* start segment */ if (cs != OBJECT) { cs = OBJECT; if (ps == OBJECT) { if (start[co] == UNKNOWN) { marker[xl] = 'S'; start[co] = xl; } else { marker[xl] = 's'; } } else { psstack[pstop++] = ps; marker[xl] = 'S'; start[++co] = xl; ps = COMPLETE; info[co] = initinfo; } } } /* closes if pixel above threshold */ /* process new marker ---------------------------------------------*/ /* newmarker is marker[ ] at this pixel position before we got to it. We'll only enter this if marker[ ] was set on a previous loop iteration. */ if (newmarker) { if (newmarker == 'S') { psstack[pstop++] = ps; if (cs == NONOBJECT) { psstack[pstop++] = COMPLETE; info[++co] = store[xl]; start[co] = UNKNOWN; } else { update(&info[co], &store[xl], pixel); } ps = OBJECT; } else if (newmarker == 's') { if ((cs == OBJECT) && (ps == COMPLETE)) { pstop--; xl2 = start[co]; update(&info[co - 1], &info[co], pixel); if (start[--co] == UNKNOWN) { start[co] = xl2; } else { marker[xl2] = 's'; } } ps = OBJECT; } else if (newmarker == 'f') { ps = INCOMPLETE; } else if (newmarker == 'F') { ps = psstack[--pstop]; if ((cs == NONOBJECT) && (ps == COMPLETE)) { if (start[co] == UNKNOWN) { if ((int64_t)info[co].pixnb >= minarea) { /* update threshold before object is processed */ if (PLISTEXIST(thresh)) { objlist.thresh = get_mean_thresh(&info[co], objlist.plist); } else { objlist.thresh = thresh; } status = sortit( &info[co], &objlist, minarea, finalobjlist, deblend_nthresh, deblend_cont, image->gain, &deblendctx ); if (status != RETURN_OK) { goto exit; }; } /* free the chain-list */ PLIST(pixel + info[co].lastpix, nextpix) = freeinfo.firstpix; freeinfo.firstpix = info[co].firstpix; } else { marker[end[co]] = 'F'; store[start[co]] = info[co]; } co--; ps = psstack[--pstop]; } } } /* end of if (newmarker) ------------------------------------------*/ /* update the info or end segment */ if (luflag) { update(&info[co], &curpixinfo, pixel); } else if (cs == OBJECT) { cs = NONOBJECT; if (ps != COMPLETE) { marker[xl] = 'f'; end[co] = xl; } else { ps = psstack[--pstop]; marker[xl] = 'F'; store[start[co]] = info[co]; co--; } } } } /*------------ End of the loop over the x's -----------------------*/ } /*---------------- End of the loop over the y's -----------------------*/ if (image->segmap) { for (i = 0; i < numids; i++) { status = segsortit(&idinfo[i], &objlist, finalobjlist, image->gain); } } else { /* convert `finalobjlist` to an array of `sepobj` structs */ /* if cleaning, see which objects "survive" cleaning. */ if (clean_flag) { /* Calculate mthresh for all objects in the list (needed for cleaning) */ for (i = 0; i < finalobjlist->nobj; i++) { status = analysemthresh(i, finalobjlist, minarea, thresh); if (status != RETURN_OK) { goto exit; } } QMALLOC(survives, int, finalobjlist->nobj, status); clean(finalobjlist, clean_param, survives); } } /* convert to output catalog */ QCALLOC(cat, sep_catalog, 1, status); status = convert_to_catalog(finalobjlist, survives, cat, w, 1); if (status != RETURN_OK) { goto exit; } exit: if (finalobjlist) { free(finalobjlist->obj); free(finalobjlist->plist); free(finalobjlist); } if (image->segmap) { arraybuffer_free(&sbuf); free(idinfo); free(cumcounts); } freedeblend(&deblendctx); free(pixel); free(info); free(store); free(marker); free(dummyscan); free(psstack); free(start); free(end); free(survives); arraybuffer_free(&dbuf); if (image->noise) { arraybuffer_free(&nbuf); } if (image->mask) { arraybuffer_free(&mbuf); } if (conv) { free(convnorm); } if (filter_type == SEP_FILTER_MATCHED) { free(sigscan); free(workscan); } if (status != RETURN_OK) { /* free cdscan if we didn't do it on the last `yl` line */ if (conv && (cdscan != dummyscan)) { free(cdscan); } /* clean up catalog if it was allocated */ sep_catalog_free(cat); cat = NULL; } *catalog = cat; return status; } int segsortit( infostruct * info, objliststruct * objlist, objliststruct * finalobjlist, double gain ) { objstruct obj; int status; status = RETURN_OK; /*----- Allocate memory to store object data */ objlist->obj = &obj; objlist->nobj = 1; memset(&obj, 0, (size_t)sizeof(objstruct)); objlist->npix = info->pixnb; obj.firstpix = info->firstpix; obj.lastpix = info->lastpix; obj.flag = info->flag; obj.thresh = plistexist_thresh ? get_mean_thresh(info, objlist->plist) : objlist->thresh; analyse(0, objlist, 1, gain); status = addobjdeep(0, objlist, finalobjlist); if (status != RETURN_OK) { goto exit; } exit: return status; } /********************************* sortit ************************************/ /* build the object structure. */ int sortit( infostruct * info, objliststruct * objlist, int minarea, objliststruct * finalobjlist, int deblend_nthresh, double deblend_mincont, double gain, deblendctx * deblendctx ) { objliststruct objlistout, *objlist2; objstruct obj; int64_t i; int status; status = RETURN_OK; objlistout.obj = NULL; objlistout.plist = NULL; objlistout.nobj = objlistout.npix = 0; /*----- Allocate memory to store object data */ objlist->obj = &obj; objlist->nobj = 1; memset(&obj, 0, (size_t)sizeof(objstruct)); objlist->npix = info->pixnb; obj.firstpix = info->firstpix; obj.lastpix = info->lastpix; obj.flag = info->flag; obj.thresh = objlist->thresh; preanalyse(0, objlist); status = deblend( objlist, &objlistout, deblend_nthresh, deblend_mincont, minarea, deblendctx ); if (status) { /* formerly, this wasn't a fatal error, so a flag was set for * the object and we continued. I'm leaving the flag-setting * here in case we want to change this to a non-fatal error in * the future, but currently the flag setting is irrelevant. */ objlist2 = objlist; for (i = 0; i < objlist2->nobj; i++) { objlist2->obj[i].flag |= SEP_OBJ_DOVERFLOW; } goto exit; } else { objlist2 = &objlistout; } /* Analyze the deblended objects and add to the final list */ for (i = 0; i < objlist2->nobj; i++) { analyse(i, objlist2, 1, gain); /* this does nothing if DETECT_MAXAREA is 0 (and it currently is) */ if (DETECT_MAXAREA && objlist2->obj[i].fdnpix > DETECT_MAXAREA) { continue; } /* add the object to the final list */ status = addobjdeep(i, objlist2, finalobjlist); if (status != RETURN_OK) { goto exit; } } exit: free(objlistout.plist); free(objlistout.obj); return status; } /********** addobjdeep (originally in manobjlist.c) **************************/ /* Add object number `objnb` from list `objl1` to list `objl2`. Unlike `addobjshallow` this also copies plist pixels to the second list. */ int addobjdeep(int objnb, objliststruct * objl1, objliststruct * objl2) { objstruct * objl2obj; pliststruct *plist1 = objl1->plist, *plist2 = objl2->plist; int64_t fp, i, j, npx, objnb2; fp = objl2->npix; /* 2nd list's plist size in pixels */ j = fp * plistsize; /* 2nd list's plist size in bytes */ objnb2 = objl2->nobj; /* # of objects currently in 2nd list*/ /* Allocate space in `objl2` for the new object */ if (objnb2) { objl2obj = realloc(objl2->obj, (++objl2->nobj) * sizeof(objstruct)); } else { objl2obj = malloc((++objl2->nobj) * sizeof(objstruct)); } if (!objl2obj) { goto earlyexit; } objl2->obj = objl2obj; /* Allocate space for the new object's pixels in 2nd list's plist */ npx = objl1->obj[objnb].fdnpix; if (fp) { plist2 = realloc(plist2, (objl2->npix += npx) * plistsize); } else { plist2 = malloc((objl2->npix = npx) * plistsize); } if (!plist2) { goto earlyexit; } objl2->plist = plist2; /* copy the plist */ plist2 += j; for (i = objl1->obj[objnb].firstpix; i != -1; i = PLIST(plist1 + i, nextpix)) { memcpy(plist2, plist1 + i, (size_t)plistsize); PLIST(plist2, nextpix) = (j += plistsize); plist2 += plistsize; } PLIST(plist2 -= plistsize, nextpix) = -1; /* copy the object itself */ objl2->obj[objnb2] = objl1->obj[objnb]; objl2->obj[objnb2].firstpix = fp * plistsize; objl2->obj[objnb2].lastpix = j - plistsize; return RETURN_OK; /* if early exit, reset 2nd list */ earlyexit: objl2->nobj--; objl2->npix = fp; return MEMORY_ALLOC_ERROR; } /****************************** plistinit ************************************ * (originally init_plist() in sextractor) PURPOSE initialize a pixel-list and its components. ***/ void plistinit(int hasconv, int hasvar) { pbliststruct * pbdum = NULL; plistsize = sizeof(pbliststruct); plistoff_value = (char *)&pbdum->value - (char *)pbdum; if (hasconv) { plistexist_cdvalue = 1; plistoff_cdvalue = plistsize; plistsize += sizeof(PIXTYPE); } else { plistexist_cdvalue = 0; plistoff_cdvalue = plistoff_value; } if (hasvar) { plistexist_var = 1; plistoff_var = plistsize; plistsize += sizeof(PIXTYPE); plistexist_thresh = 1; plistoff_thresh = plistsize; plistsize += sizeof(PIXTYPE); } else { plistexist_var = 0; plistexist_thresh = 0; } } /************************** clean an objliststruct ***************************/ /* Fill a list with whether each object in the list survived the cleaning (assumes that mthresh has already been calculated for all objects in the list) */ void clean(objliststruct * objlist, double clean_param, int * survives) { objstruct *obj1, *obj2; int64_t i, j; double amp, ampin, alpha, alphain, unitarea, unitareain, beta, val; float dx, dy, rlim; beta = clean_param; /* initialize to all surviving */ for (i = 0; i < objlist->nobj; i++) { survives[i] = 1; } obj1 = objlist->obj; for (i = 0; i < objlist->nobj; i++, obj1++) { if (!survives[i]) { continue; } /* parameters for test object */ unitareain = PI * obj1->a * obj1->b; ampin = obj1->fdflux / (2 * unitareain * obj1->abcor); alphain = (pow(ampin / obj1->thresh, 1.0 / beta) - 1) * unitareain / obj1->fdnpix; /* loop over remaining objects in list*/ obj2 = obj1 + 1; for (j = i + 1; j < objlist->nobj; j++, obj2++) { if (!survives[j]) { continue; } dx = obj1->mx - obj2->mx; dy = obj1->my - obj2->my; rlim = obj1->a + obj2->a; rlim *= rlim; if (dx * dx + dy * dy > rlim * CLEAN_ZONE * CLEAN_ZONE) { continue; } /* if obj1 is bigger, see if it eats obj2 */ if (obj2->fdflux < obj1->fdflux) { val = 1 + alphain * (obj1->cxx * dx * dx + obj1->cyy * dy * dy + obj1->cxy * dx * dy); if (val > 1.0 && ((float)(val < 1e10 ? ampin * pow(val, -beta) : 0.0) > obj2->mthresh)) { survives[j] = 0; /* the test object eats this one */ } } /* if obj2 is bigger, see if it eats obj1 */ else { unitarea = PI * obj2->a * obj2->b; amp = obj2->fdflux / (2 * unitarea * obj2->abcor); alpha = (pow(amp / obj2->thresh, 1.0 / beta) - 1) * unitarea / obj2->fdnpix; val = 1 + alpha * (obj2->cxx * dx * dx + obj2->cyy * dy * dy + obj2->cxy * dx * dy); if (val > 1.0 && ((float)(val < 1e10 ? amp * pow(val, -beta) : 0.0) > obj1->mthresh)) { survives[i] = 0; /* this object eats the test object */ } } } /* inner loop over objlist (obj2) */ } /* outer loop of objlist (obj1) */ } /************************** get_mean_thresh **********************************/ /* Compute an average threshold from all pixels in the cluster */ PIXTYPE get_mean_thresh(infostruct * info, pliststruct * pixel) { pliststruct * pixt; int pix_accum = 0; double thresh_accum = 0; // Threshold must be cast to double to avoid precision loss for (pixt = pixel + info->firstpix; pixt >= pixel; pixt = pixel + PLIST(pixt, nextpix)) { thresh_accum += (double)PLISTPIX(pixt, thresh); pix_accum++; } return (PIXTYPE)(thresh_accum / pix_accum); } /*****************************************************************************/ /* sep_catalog manipulations */ void free_catalog_fields(sep_catalog * catalog) { free(catalog->thresh); free(catalog->npix); free(catalog->tnpix); free(catalog->xmin); free(catalog->xmax); free(catalog->ymin); free(catalog->ymax); free(catalog->x); free(catalog->y); free(catalog->x2); free(catalog->y2); free(catalog->xy); free(catalog->errx2); free(catalog->erry2); free(catalog->errxy); free(catalog->a); free(catalog->b); free(catalog->theta); free(catalog->cxx); free(catalog->cyy); free(catalog->cxy); free(catalog->cflux); free(catalog->flux); free(catalog->cpeak); free(catalog->peak); free(catalog->xcpeak); free(catalog->ycpeak); free(catalog->xpeak); free(catalog->ypeak); free(catalog->flag); free(catalog->pix); free(catalog->objectspix); memset(catalog, 0, sizeof(sep_catalog)); } /* convert_to_catalog() * * Convert the final object list to an output catalog. * * `survives`: array of 0 or 1 indicating whether or not to output each object * (ignored if NULL) * `cat`: catalog object to be filled. * `w`: width of image (used to calculate linear indicies). */ int convert_to_catalog( objliststruct * objlist, const int * survives, sep_catalog * cat, int64_t w, int include_pixels ) { int64_t i, j, k; int64_t totnpix; int nobj = 0; int status = RETURN_OK; objstruct * obj; pliststruct *pixt, *pixel; /* Set struct to zero in case the caller didn't. * This is important if there is a memory error and we have to call * free_catalog_fields() to recover at exit */ memset(cat, 0, sizeof(sep_catalog)); /* Count number of surviving objects so that we can allocate the appropriate amount of space in the output catalog. */ if (survives) { for (i = 0; i < objlist->nobj; i++) { nobj += survives[i]; } } else { nobj = objlist->nobj; } /* allocate catalog fields */ cat->nobj = nobj; QMALLOC(cat->thresh, float, nobj, status); QMALLOC(cat->npix, int64_t, nobj, status); QMALLOC(cat->tnpix, int64_t, nobj, status); QMALLOC(cat->xmin, int64_t, nobj, status); QMALLOC(cat->xmax, int64_t, nobj, status); QMALLOC(cat->ymin, int64_t, nobj, status); QMALLOC(cat->ymax, int64_t, nobj, status); QMALLOC(cat->x, double, nobj, status); QMALLOC(cat->y, double, nobj, status); QMALLOC(cat->x2, double, nobj, status); QMALLOC(cat->y2, double, nobj, status); QMALLOC(cat->xy, double, nobj, status); QMALLOC(cat->errx2, double, nobj, status); QMALLOC(cat->erry2, double, nobj, status); QMALLOC(cat->errxy, double, nobj, status); QMALLOC(cat->a, float, nobj, status); QMALLOC(cat->b, float, nobj, status); QMALLOC(cat->theta, float, nobj, status); QMALLOC(cat->cxx, float, nobj, status); QMALLOC(cat->cyy, float, nobj, status); QMALLOC(cat->cxy, float, nobj, status); QMALLOC(cat->cflux, float, nobj, status); QMALLOC(cat->flux, float, nobj, status); QMALLOC(cat->cpeak, float, nobj, status); QMALLOC(cat->peak, float, nobj, status); QMALLOC(cat->xcpeak, int64_t, nobj, status); QMALLOC(cat->ycpeak, int64_t, nobj, status); QMALLOC(cat->xpeak, int64_t, nobj, status); QMALLOC(cat->ypeak, int64_t, nobj, status); QMALLOC(cat->cflux, float, nobj, status); QMALLOC(cat->flux, float, nobj, status); QMALLOC(cat->flag, short, nobj, status); /* fill output arrays */ j = 0; /* running index in output array */ for (i = 0; i < objlist->nobj; i++) { if ((survives == NULL) || survives[i]) { obj = objlist->obj + i; cat->thresh[j] = obj->thresh; cat->npix[j] = obj->fdnpix; cat->tnpix[j] = obj->dnpix; cat->xmin[j] = obj->xmin; cat->xmax[j] = obj->xmax; cat->ymin[j] = obj->ymin; cat->ymax[j] = obj->ymax; cat->x[j] = obj->mx; cat->y[j] = obj->my; cat->x2[j] = obj->mx2; cat->y2[j] = obj->my2; cat->xy[j] = obj->mxy; cat->errx2[j] = obj->errx2; cat->erry2[j] = obj->erry2; cat->errxy[j] = obj->errxy; cat->a[j] = obj->a; cat->b[j] = obj->b; cat->theta[j] = obj->theta; cat->cxx[j] = obj->cxx; cat->cyy[j] = obj->cyy; cat->cxy[j] = obj->cxy; cat->cflux[j] = obj->fdflux; /* these change names */ cat->flux[j] = obj->dflux; cat->cpeak[j] = obj->fdpeak; cat->peak[j] = obj->dpeak; cat->xpeak[j] = obj->xpeak; cat->ypeak[j] = obj->ypeak; cat->xcpeak[j] = obj->xcpeak; cat->ycpeak[j] = obj->ycpeak; cat->flag[j] = obj->flag; j++; } } if (include_pixels) { /* count the total number of pixels */ totnpix = 0; for (i = 0; i < cat->nobj; i++) { totnpix += cat->npix[i]; } /* allocate buffer for all objects' pixels */ QMALLOC(cat->objectspix, int64_t, totnpix, status); /* allocate array of pointers into the above buffer */ QMALLOC(cat->pix, int64_t *, nobj, status); pixel = objlist->plist; /* for each object, fill buffer and direct object's to it */ k = 0; /* current position in `objectspix` buffer */ j = 0; /* output object index */ for (i = 0; i < objlist->nobj; i++) { obj = objlist->obj + i; /* input object */ if ((survives == NULL) || survives[i]) { /* point this object's pixel list into the buffer. */ cat->pix[j] = cat->objectspix + k; /* fill the actual pixel values */ for (pixt = pixel + obj->firstpix; pixt >= pixel; pixt = pixel + PLIST(pixt, nextpix), k++) { cat->objectspix[k] = PLIST(pixt, x) + w * PLIST(pixt, y); } j++; } } } exit: if (status != RETURN_OK) { free_catalog_fields(cat); } return status; } void sep_catalog_free(sep_catalog * catalog) { if (catalog != NULL) { free_catalog_fields(catalog); } free(catalog); } ================================================ FILE: src/extract.h ================================================ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file is part of SEP * * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC * Copyright 2014 SEP developers * * SEP is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SEP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SEP. If not, see . * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include "sepcore.h" #define UNKNOWN -1 /* flag for LUTZ */ #define CLEAN_ZONE 10.0 /* zone (in sigma) to consider for processing */ #define CLEAN_STACKSIZE 3000 /* replaces prefs.clean_stacksize */ /* (MEMORY_OBJSTACK in sextractor inputs) */ #define CLEAN_MARGIN 0 /* replaces prefs.cleanmargin which was set based */ /* on stuff like apertures and vignet size */ #define MARGIN_SCALE 2.0 /* Margin / object height */ #define MARGIN_OFFSET 4.0 /* Margin offset (pixels) */ #define MAXDEBAREA 3 /* max. area for deblending (must be >= 1)*/ #define MAXPICSIZE 1048576 /* max. image size in any dimension */ /* plist-related macros */ #define PLIST(ptr, elem) (((pbliststruct *)(ptr))->elem) #define PLISTEXIST(elem) (plistexist_##elem) #define PLISTPIX(ptr, elem) (*((PIXTYPE *)((ptr) + plistoff_##elem))) /* Extraction status */ typedef enum { COMPLETE, INCOMPLETE, NONOBJECT, OBJECT } pixstatus; /* Temporary object parameters during extraction */ typedef struct structinfo { int64_t pixnb; /* Number of pixels included */ int64_t firstpix; /* Pointer to first pixel of pixlist */ int64_t lastpix; /* Pointer to last pixel of pixlist */ short flag; /* Extraction flag */ } infostruct; typedef char pliststruct; /* Dummy type for plist */ typedef struct { int64_t nextpix; int64_t x, y; PIXTYPE value; } pbliststruct; /* array buffer struct */ typedef struct { const BYTE * dptr; /* pointer to original data, can be any supported type */ int dtype; /* data type of original data */ int64_t dw, dh; /* original data width, height */ PIXTYPE * bptr; /* buffer pointer (self-managed memory) */ int64_t bw, bh; /* buffer width, height (bufw can be larger than w due */ /* to padding). */ PIXTYPE * midline; /* "middle" line in buffer (at index bh/2) */ PIXTYPE * lastline; /* last line in buffer */ array_converter readline; /* function to read a data line into buffer */ int64_t elsize; /* size in bytes of one element in original data */ int64_t yoff; /* line index in original data corresponding to bufptr */ } arraybuffer; /* globals */ extern _Thread_local int64_t plistexist_cdvalue, plistexist_thresh, plistexist_var; extern _Thread_local int64_t plistoff_value, plistoff_cdvalue, plistoff_thresh, plistoff_var; extern _Thread_local int64_t plistsize; extern _Thread_local unsigned int randseed; typedef struct { /* thresholds */ float thresh; /* detect threshold (ADU) */ float mthresh; /* max. threshold (ADU) */ /* # pixels */ int64_t fdnpix; /* nb of extracted pix */ int64_t dnpix; /* nb of pix above thresh */ int64_t npix; /* "" in measured frame */ int64_t nzdwpix; /* nb of zero-dweights around */ int64_t nzwpix; /* nb of zero-weights inside */ /* position */ int64_t xpeak, ypeak; /* pos of brightest pix */ int64_t xcpeak, ycpeak; /* pos of brightest pix */ double mx, my; /* barycenter */ int64_t xmin, xmax, ymin, ymax, ycmin, ycmax; /* x,y limits */ /* shape */ double mx2, my2, mxy; /* variances and covariance */ float a, b, theta, abcor; /* moments and angle */ float cxx, cyy, cxy; /* ellipse parameters */ double errx2, erry2, errxy; /* Uncertainties on the variances */ /* flux */ float fdflux; /* integrated ext. flux */ float dflux; /* integrated det. flux */ float flux; /* integrated mes. flux */ float fluxerr; /* integrated variance */ PIXTYPE fdpeak; /* peak intensity (ADU) */ PIXTYPE dpeak; /* peak intensity (ADU) */ PIXTYPE peak; /* peak intensity (ADU) */ /* flags */ short flag; /* extraction flags */ /* accessing individual pixels in plist*/ int64_t firstpix; /* ptr to first pixel */ int64_t lastpix; /* ptr to last pixel */ } objstruct; typedef struct { int64_t nobj; /* number of objects in list */ objstruct * obj; /* pointer to the object array */ int64_t npix; /* number of pixels in pixel-list */ pliststruct * plist; /* pointer to the pixel-list */ PIXTYPE thresh; /* detection threshold */ } objliststruct; int analysemthresh(int objnb, objliststruct * objlist, int minarea, PIXTYPE thresh); void preanalyse(int, objliststruct *); void analyse(int, objliststruct *, int, double); typedef struct { infostruct *info, *store; char * marker; pixstatus * psstack; int64_t *start, *end, *discan; int64_t xmin, ymin, xmax, ymax; } lutzbuffers; int lutzalloc(int64_t, int64_t, lutzbuffers *); void lutzfree(lutzbuffers *); int lutz( pliststruct * plistin, int64_t * objrootsubmap, int64_t subx, int64_t suby, int64_t subw, objstruct * objparent, objliststruct * objlist, int minarea, lutzbuffers * buffers ); void update(infostruct *, infostruct *, pliststruct *); typedef struct { objliststruct * objlist; short *son, *ok; lutzbuffers lutz; } deblendctx; int allocdeblend(int deblend_nthresh, int64_t w, int64_t h, deblendctx *); void freedeblend(deblendctx *); int deblend(objliststruct *, objliststruct *, int, double, int, deblendctx *); /*int addobjshallow(objstruct *, objliststruct *); int rmobjshallow(int, objliststruct *); void mergeobjshallow(objstruct *, objstruct *); */ int addobjdeep(int, objliststruct *, objliststruct *); int convolve( arraybuffer * buf, int64_t y, const float * conv, int64_t convw, int64_t convh, PIXTYPE * out ); int matched_filter( arraybuffer * imbuf, arraybuffer * nbuf, int64_t y, const float * conv, int64_t convw, int64_t convh, PIXTYPE * work, PIXTYPE * out, int noise_type ); ================================================ FILE: src/lutz.c ================================================ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file is part of SEP * * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC * Copyright 2014 SEP developers * * SEP is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SEP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SEP. If not, see . * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /* Note: was extract.c in SExtractor. */ #include #include #include #include #include "extract.h" #include "sep.h" #include "sepcore.h" #define NOBJ 256 /* starting number of obj. */ void lutzsort(infostruct *, objliststruct *); /******************************* lutzalloc ***********************************/ /* Allocate once for all memory space for buffers used by lutz(). */ int lutzalloc(int64_t width, int64_t height, lutzbuffers * buffers) { int64_t * discant; int64_t stacksize, i; int status = RETURN_OK; memset(buffers, 0, sizeof(lutzbuffers)); stacksize = width + 1; buffers->xmin = buffers->ymin = 0; buffers->xmax = width - 1; buffers->ymax = height - 1; QMALLOC(buffers->info, infostruct, stacksize, status); QMALLOC(buffers->store, infostruct, stacksize, status); QMALLOC(buffers->marker, char, stacksize, status); QMALLOC(buffers->psstack, pixstatus, stacksize, status); QMALLOC(buffers->start, int64_t, stacksize, status); QMALLOC(buffers->end, int64_t, stacksize, status); QMALLOC(buffers->discan, int64_t, stacksize, status); discant = buffers->discan; for (i = stacksize; i--;) { *(discant++) = -1; } return status; exit: lutzfree(buffers); return status; } /******************************* lutzfree ************************************/ /* Free once for all memory space for buffers used by lutz(). */ void lutzfree(lutzbuffers * buffers) { free(buffers->discan); buffers->discan = NULL; free(buffers->info); buffers->info = NULL; free(buffers->store); buffers->store = NULL; free(buffers->marker); buffers->marker = NULL; free(buffers->psstack); buffers->psstack = NULL; free(buffers->start); buffers->start = NULL; free(buffers->end); buffers->end = NULL; } static const infostruct initinfo = {.firstpix = -1, .lastpix = -1}; /********************************** lutz *************************************/ /* C implementation of R.K LUTZ' algorithm for the extraction of 8-connected pi- xels in an image */ int lutz( pliststruct * plistin, int64_t * objrootsubmap, int64_t subx, int64_t suby, int64_t subw, objstruct * objparent, objliststruct * objlist, int minarea, lutzbuffers * buffers ) { infostruct curpixinfo; objstruct * obj; pliststruct *plist, *pixel, *plistint; char newmarker; int64_t cn, co, luflag, pstop, xl, xl2, yl, out, deb_maxarea, stx, sty, enx, eny, step, nobjm = NOBJ, inewsymbol, *iscan; short trunflag; PIXTYPE thresh; pixstatus cs, ps; out = RETURN_OK; deb_maxarea = minarea < MAXDEBAREA ? minarea : MAXDEBAREA; /* 3 or less */ plistint = plistin; stx = objparent->xmin; sty = objparent->ymin; enx = objparent->xmax; eny = objparent->ymax; thresh = objlist->thresh; cn = 0; iscan = objrootsubmap + (sty - suby) * subw + (stx - subx); /* As we only analyse a fraction of the map, a step occurs between lines */ step = subw - (++enx - stx); eny++; /*------Allocate memory to store object data */ free(objlist->obj); if (!(obj = objlist->obj = malloc(nobjm * sizeof(objstruct)))) { out = MEMORY_ALLOC_ERROR; plist = NULL; /* To avoid gcc -Wall warnings */ goto exit_lutz; } /*------Allocate memory for the pixel list */ free(objlist->plist); if (!(objlist->plist = malloc((eny - sty) * (enx - stx) * plistsize))) { out = MEMORY_ALLOC_ERROR; plist = NULL; /* To avoid gcc -Wall warnings */ goto exit_lutz; } pixel = plist = objlist->plist; /*----------------------------------------*/ for (xl = stx; xl <= enx; xl++) { buffers->marker[xl] = 0; } objlist->nobj = 0; co = pstop = 0; curpixinfo.pixnb = 1; curpixinfo.flag = curpixinfo.firstpix = curpixinfo.lastpix = 0; for (yl = sty; yl <= eny; yl++, iscan += step) { ps = COMPLETE; cs = NONOBJECT; trunflag = (yl == 0 || yl == buffers->ymax) ? SEP_OBJ_TRUNC : 0; if (yl == eny) { iscan = buffers->discan; } for (xl = stx; xl <= enx; xl++) { newmarker = buffers->marker[xl]; buffers->marker[xl] = 0; if ((inewsymbol = (xl != enx) ? *(iscan++) : -1) < 0) { luflag = 0; } else { curpixinfo.flag = trunflag; plistint = plistin + inewsymbol; luflag = (PLISTPIX(plistint, cdvalue) > thresh ? 1 : 0); } if (luflag) { if (xl == 0 || xl == buffers->xmax) { curpixinfo.flag |= SEP_OBJ_TRUNC; } memcpy(pixel, plistint, (size_t)plistsize); PLIST(pixel, nextpix) = -1; curpixinfo.lastpix = curpixinfo.firstpix = cn; cn += plistsize; pixel += plistsize; /*----------------- Start Segment -----------------------------*/ if (cs != OBJECT) { cs = OBJECT; if (ps == OBJECT) { if (buffers->start[co] == UNKNOWN) { buffers->marker[xl] = 'S'; buffers->start[co] = xl; } else { buffers->marker[xl] = 's'; } } else { buffers->psstack[pstop++] = ps; buffers->marker[xl] = 'S'; buffers->start[++co] = xl; ps = COMPLETE; buffers->info[co] = initinfo; } } } /*-------------------Process New Marker ---------------------------*/ if (newmarker) { if (newmarker == 'S') { buffers->psstack[pstop++] = ps; if (cs == NONOBJECT) { buffers->psstack[pstop++] = COMPLETE; buffers->info[++co] = buffers->store[xl]; buffers->start[co] = UNKNOWN; } else { update(&buffers->info[co], &buffers->store[xl], plist); } ps = OBJECT; } else if (newmarker == 's') { if ((cs == OBJECT) && (ps == COMPLETE)) { pstop--; xl2 = buffers->start[co]; update(&buffers->info[co - 1], &buffers->info[co], plist); if (buffers->start[--co] == UNKNOWN) { buffers->start[co] = xl2; } else { buffers->marker[xl2] = 's'; } } ps = OBJECT; } else if (newmarker == 'f') { ps = INCOMPLETE; } else if (newmarker == 'F') { ps = buffers->psstack[--pstop]; if ((cs == NONOBJECT) && (ps == COMPLETE)) { if (buffers->start[co] == UNKNOWN) { if ((int64_t)buffers->info[co].pixnb >= deb_maxarea) { if (objlist->nobj >= nobjm) { if (!(obj = objlist->obj = (objstruct *) realloc(obj, (nobjm += nobjm / 2) * sizeof(objstruct)))) { out = MEMORY_ALLOC_ERROR; goto exit_lutz; } } lutzsort(&buffers->info[co], objlist); } } else { buffers->marker[buffers->end[co]] = 'F'; buffers->store[buffers->start[co]] = buffers->info[co]; } co--; ps = buffers->psstack[--pstop]; } } } /* end process new marker -----------------------------------------*/ if (luflag) { update(&buffers->info[co], &curpixinfo, plist); } else { /* ----------------- End Segment ------------------------------*/ if (cs == OBJECT) { cs = NONOBJECT; if (ps != COMPLETE) { buffers->marker[xl] = 'f'; buffers->end[co] = xl; } else { ps = buffers->psstack[--pstop]; buffers->marker[xl] = 'F'; buffers->store[buffers->start[co]] = buffers->info[co]; co--; } } } } } exit_lutz: if (objlist->nobj && out == RETURN_OK) { if (!(objlist->obj = realloc(obj, objlist->nobj * sizeof(objstruct)))) { out = MEMORY_ALLOC_ERROR; } } else { free(obj); objlist->obj = NULL; } if (cn && out == RETURN_OK) { if (!(objlist->plist = realloc(plist, cn))) { out = MEMORY_ALLOC_ERROR; } } else { free(objlist->plist); objlist->plist = NULL; } return out; } /********************************* lutzsort ***********************************/ /* Add an object to the object list based on info (pixel info) */ void lutzsort(infostruct * info, objliststruct * objlist) { objstruct * obj = objlist->obj + objlist->nobj; memset(obj, 0, (size_t)sizeof(objstruct)); obj->firstpix = info->firstpix; obj->lastpix = info->lastpix; obj->flag = info->flag; objlist->npix += info->pixnb; preanalyse(objlist->nobj, objlist); objlist->nobj++; } /********************************* update ************************************/ /* update object's properties each time one of its pixels is scanned by lutz() */ void update(infostruct * infoptr1, infostruct * infoptr2, pliststruct * pixel) { infoptr1->pixnb += infoptr2->pixnb; infoptr1->flag |= infoptr2->flag; if (infoptr1->firstpix == -1) { infoptr1->firstpix = infoptr2->firstpix; infoptr1->lastpix = infoptr2->lastpix; } else if (infoptr2->lastpix != -1) { PLIST(pixel + infoptr1->lastpix, nextpix) = infoptr2->firstpix; infoptr1->lastpix = infoptr2->lastpix; } } ================================================ FILE: src/overlap.h ================================================ /* Licensed under a 3-clause BSD style license. * * Functions for calculating exact overlap between shapes. * * Original cython version by Thomas Robitaille. Converted to C by Kyle * Barbary. */ #include #include "sepcore.h" #if defined(_MSC_VER) #define INLINE _inline #else #define INLINE inline #endif /* Return area of a circle arc between (x1, y1) and (x2, y2) with radius r */ /* reference: http://mathworld.wolfram.com/CircularSegment.html */ static INLINE double area_arc(double x1, double y1, double x2, double y2, double r) { double a, theta; a = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); theta = 2. * asin(0.5 * a / r); return 0.5 * r * r * (theta - sin(theta)); } /* Area of a triangle defined by three verticies */ static INLINE double area_triangle( double x1, double y1, double x2, double y2, double x3, double y3 ) { return 0.5 * fabs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)); } /* Core of circular overlap routine. * Assumes that xmax >= xmin >= 0.0, ymax >= ymin >= 0.0. * (can always modify input to conform to this). */ static INLINE double circoverlap_core( double xmin, double ymin, double xmax, double ymax, double r ) { double a, b, x1, x2, y1, y2, r2, xmin2, ymin2, xmax2, ymax2; xmin2 = xmin * xmin; ymin2 = ymin * ymin; r2 = r * r; if (xmin2 + ymin2 > r2) { return 0.; } xmax2 = xmax * xmax; ymax2 = ymax * ymax; if (xmax2 + ymax2 < r2) { return (xmax - xmin) * (ymax - ymin); } a = xmax2 + ymin2; /* (corner 1 distance)^2 */ b = xmin2 + ymax2; /* (corner 2 distance)^2 */ if (a < r2 && b < r2) { x1 = sqrt(r2 - ymax2); y1 = ymax; x2 = xmax; y2 = sqrt(r2 - xmax2); return ( (xmax - xmin) * (ymax - ymin) - area_triangle(x1, y1, x2, y2, xmax, ymax) + area_arc(x1, y1, x2, y2, r) ); } if (a < r2) { x1 = xmin; y1 = sqrt(r2 - xmin2); x2 = xmax; y2 = sqrt(r2 - xmax2); return ( area_arc(x1, y1, x2, y2, r) + area_triangle(x1, y1, x1, ymin, xmax, ymin) + area_triangle(x1, y1, x2, ymin, x2, y2) ); } if (b < r2) { x1 = sqrt(r2 - ymin2); y1 = ymin; x2 = sqrt(r2 - ymax2); y2 = ymax; return ( area_arc(x1, y1, x2, y2, r) + area_triangle(x1, y1, xmin, y1, xmin, ymax) + area_triangle(x1, y1, xmin, y2, x2, y2) ); } /* else */ x1 = sqrt(r2 - ymin2); y1 = ymin; x2 = xmin; y2 = sqrt(r2 - xmin2); return (area_arc(x1, y1, x2, y2, r) + area_triangle(x1, y1, x2, y2, xmin, ymin)); } /* Area of overlap of a rectangle and a circle */ static double circoverlap( double xmin, double ymin, double xmax, double ymax, double r ) { /* some subroutines demand that r > 0 */ if (r <= 0.) { return 0.; } if (0. <= xmin) { if (0. <= ymin) { return circoverlap_core(xmin, ymin, xmax, ymax, r); } else if (0. >= ymax) { return circoverlap_core(-ymax, xmin, -ymin, xmax, r); } else { return ( circoverlap(xmin, ymin, xmax, 0., r) + circoverlap(xmin, 0., xmax, ymax, r) ); } } else if (0. >= xmax) { if (0. <= ymin) { return circoverlap_core(-xmax, ymin, -xmin, ymax, r); } else if (0. >= ymax) { return circoverlap_core(-xmax, -ymax, -xmin, -ymin, r); } else { return ( circoverlap(xmin, ymin, xmax, 0., r) + circoverlap(xmin, 0., xmax, ymax, r) ); } } else { if (0. <= ymin) { return ( circoverlap(xmin, ymin, 0., ymax, r) + circoverlap(0., ymin, xmax, ymax, r) ); } if (0. >= ymax) { return ( circoverlap(xmin, ymin, 0., ymax, r) + circoverlap(0., ymin, xmax, ymax, r) ); } else { return ( circoverlap(xmin, ymin, 0., 0., r) + circoverlap(0., ymin, xmax, 0., r) + circoverlap(xmin, 0., 0., ymax, r) + circoverlap(0., 0., xmax, ymax, r) ); } } } /* Start of new circular overlap routine that might be faster. double circoverlap_new(double dx, double dy, double r) { double xmin, xmax, ymin, ymax, xmin2, xmax2, ymin2, ymax2, r2; if (dx < 0.) dx = -dx; if (dy < 0.) dy = -dy; if (dy > dx) { r2 = dy; dy = dx; dx = r2; } xmax = dx + 0.5; ymax = dy + 0.5; xmax2 = xmax*xmax; ymax2 = ymax*ymax; r2 = r*r; if (xmax2 + ymax2 < r2) return 1.; xmin2 = xmin*xmin; if (xmin2 + } */ /*****************************************************************************/ /* ellipse overlap functions */ typedef struct { double x, y; } point; typedef struct { point p1, p2; } intersections; static INLINE void swap(double * a, double * b) { double temp; temp = *a; *a = *b; *b = temp; } static INLINE void swap_point(point * a, point * b) { point temp; temp = *a; *a = *b; *b = temp; } /* rotate values to the left: a=b, b=c, c=a */ static INLINE void rotate(double * a, double * b, double * c) { double temp; temp = *a; *a = *b; *b = *c; *c = temp; } /* Check if a point (x,y) is inside a triangle */ static int in_triangle( double x, double y, double x1, double y1, double x2, double y2, double x3, double y3 ) { int c; c = 0; c += ((y1 > y) != (y2 > y)) && (x < (x2 - x1) * (y - y1) / (y2 - y1) + x1); c += ((y2 > y) != (y3 > y)) && (x < (x3 - x2) * (y - y2) / (y3 - y2) + x2); c += ((y3 > y) != (y1 > y)) && (x < (x1 - x3) * (y - y3) / (y1 - y3) + x3); return c % 2 == 1; } /* Intersection of a line defined by two points with a unit circle */ static intersections circle_line(double x1, double y1, double x2, double y2) { double a, b, delta, dx, dy; double tol = 1.e-10; intersections inter; dx = x2 - x1; dy = y2 - y1; if (fabs(dx) < tol && fabs(dy) < tol) { inter.p1.x = 2.; inter.p1.y = 2.; inter.p2.x = 2.; inter.p2.y = 2.; } else if (fabs(dx) > fabs(dy)) { /* Find the slope and intercept of the line */ a = dy / dx; b = y1 - a * x1; /* Find the determinant of the quadratic equation */ delta = 1. + a * a - b * b; if (delta > 0.) /* solutions exist */ { delta = sqrt(delta); inter.p1.x = (-a * b - delta) / (1. + a * a); inter.p1.y = a * inter.p1.x + b; inter.p2.x = (-a * b + delta) / (1. + a * a); inter.p2.y = a * inter.p2.x + b; } else /* no solution, return values > 1 */ { inter.p1.x = 2.; inter.p1.y = 2.; inter.p2.x = 2.; inter.p2.y = 2.; } } else { /* Find the slope and intercept of the line */ a = dx / dy; b = x1 - a * y1; /* Find the determinant of the quadratic equation */ delta = 1. + a * a - b * b; if (delta > 0.) /* solutions exist */ { delta = sqrt(delta); inter.p1.y = (-a * b - delta) / (1. + a * a); inter.p1.x = a * inter.p1.y + b; inter.p2.y = (-a * b + delta) / (1. + a * a); inter.p2.x = a * inter.p2.y + b; } else /* no solution, return values > 1 */ { inter.p1.x = 2.; inter.p1.y = 2.; inter.p2.x = 2.; inter.p2.y = 2.; } } return inter; } /* The intersection of a line with the unit circle. The intersection the * closest to (x2, y2) is chosen. */ static point circle_segment_single2(double x1, double y1, double x2, double y2) { double dx1, dy1, dx2, dy2; intersections inter; point pt1, pt2, pt; inter = circle_line(x1, y1, x2, y2); pt1 = inter.p1; pt2 = inter.p2; /*Can be optimized, but just checking for correctness right now */ dx1 = fabs(pt1.x - x2); dy1 = fabs(pt1.y - y2); dx2 = fabs(pt2.x - x2); dy2 = fabs(pt2.y - y2); if (dx1 > dy1) /* compare based on x-axis */ { pt = (dx1 > dx2) ? pt2 : pt1; } else { pt = (dy1 > dy2) ? pt2 : pt1; } return pt; } /* Intersection(s) of a segment with the unit circle. Discard any solution not on the segment. */ static inline intersections circle_segment(double x1, double y1, double x2, double y2) { intersections inter, inter_new; point pt1, pt2; inter = circle_line(x1, y1, x2, y2); pt1 = inter.p1; pt2 = inter.p2; if ((pt1.x > x1 && pt1.x > x2) || (pt1.x < x1 && pt1.x < x2) || (pt1.y > y1 && pt1.y > y2) || (pt1.y < y1 && pt1.y < y2)) { pt1.x = 2.; pt1.y = 2.; } if ((pt2.x > x1 && pt2.x > x2) || (pt2.x < x1 && pt2.x < x2) || (pt2.y > y1 && pt2.y > y2) || (pt2.y < y1 && pt2.y < y2)) { pt2.x = 2.; pt2.y = 2.; } if (pt1.x > 1. && pt2.x < 2.) { inter_new.p1 = pt1; inter_new.p2 = pt2; } else { inter_new.p1 = pt2; inter_new.p2 = pt1; } return inter_new; } /* Given a triangle defined by three points (x1, y1), (x2, y2), and (x3, y3), find the area of overlap with the unit circle. */ static double triangle_unitcircle_overlap( double x1, double y1, double x2, double y2, double x3, double y3 ) { double d1, d2, d3, area, xp, yp; int in1, in2, in3, on1, on2, on3; int intersect13, intersect23; intersections inter; point pt1, pt2, pt3, pt4, pt5, pt6; /* Find distance of all vertices to circle center */ d1 = x1 * x1 + y1 * y1; d2 = x2 * x2 + y2 * y2; d3 = x3 * x3 + y3 * y3; /* Order vertices by distance from origin */ if (d1 < d2) { if (d2 < d3) { } else if (d1 < d3) { swap(&x2, &x3); swap(&y2, &y3); swap(&d2, &d3); } else { rotate(&x1, &x3, &x2); rotate(&y1, &y3, &y2); rotate(&d1, &d3, &d2); } } else { if (d1 < d3) { swap(&x1, &x2); swap(&y1, &y2); swap(&d1, &d2); } else if (d2 < d3) { rotate(&x1, &x2, &x3); rotate(&y1, &y2, &y3); rotate(&d1, &d2, &d3); } else { swap(&x1, &x3); swap(&y1, &y3); swap(&d1, &d3); } } /* Determine number of vertices inside circle */ in1 = d1 < 1.; in2 = d2 < 1.; in3 = d3 < 1.; /* Determine which vertices are on the circle */ on1 = fabs(d1 - 1.) < 1.e-10; on2 = fabs(d2 - 1.) < 1.e-10; on3 = fabs(d3 - 1.) < 1.e-10; if (on3 || in3) /* triangle completely within circle */ { area = area_triangle(x1, y1, x2, y2, x3, y3); } else if (in2 || on2) { /* If vertex 1 or 2 are on the edge of the circle, then we use * the dot product to vertex 3 to determine whether an * intersection takes place. */ intersect13 = !on1 || (x1 * (x3 - x1) + y1 * (y3 - y1) < 0.); intersect23 = !on2 || (x2 * (x3 - x2) + y2 * (y3 - y2) < 0.); if (intersect13 && intersect23) { pt1 = circle_segment_single2(x1, y1, x3, y3); pt2 = circle_segment_single2(x2, y2, x3, y3); area = (area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) + area_triangle(x2, y2, pt1.x, pt1.y, pt2.x, pt2.y) + area_arc(pt1.x, pt1.y, pt2.x, pt2.y, 1.)); } else if (intersect13) { pt1 = circle_segment_single2(x1, y1, x3, y3); area = (area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) + area_arc(x2, y2, pt1.x, pt1.y, 1.)); } else if (intersect23) { pt2 = circle_segment_single2(x2, y2, x3, y3); area = (area_triangle(x1, y1, x2, y2, pt2.x, pt2.y) + area_arc(x1, y1, pt2.x, pt2.y, 1.)); } else { area = area_arc(x1, y1, x2, y2, 1.); } } else if (in1) { /* Check for intersections of far side with circle */ inter = circle_segment(x2, y2, x3, y3); pt1 = inter.p1; pt2 = inter.p2; pt3 = circle_segment_single2(x1, y1, x2, y2); pt4 = circle_segment_single2(x1, y1, x3, y3); if (pt1.x > 1.) /* indicates no intersection */ { /* check if the pixel vertex (x1, y2) and the origin are on * different sides of the circle segment. If they are, the * circle segment spans more than pi radians. * We use the formula (y-y1) * (x2-x1) > (y2-y1) * (x-x1) * to determine if (x, y) is on the left of the directed * line segment from (x1, y1) to (x2, y2) */ if (((0. - pt3.y) * (pt4.x - pt3.x) > (pt4.y - pt3.y) * (0. - pt3.x)) != ((y1 - pt3.y) * (pt4.x - pt3.x) > (pt4.y - pt3.y) * (x1 - pt3.x))) { area = (area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) + PI - area_arc(pt3.x, pt3.y, pt4.x, pt4.y, 1.)); } else { area = (area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) + area_arc(pt3.x, pt3.y, pt4.x, pt4.y, 1.)); } } else { /* ensure that pt1 is the point closest to (x2, y2) */ if (((pt2.x - x2) * (pt2.x - x2) + (pt2.y - y2) * (pt2.y - y2)) < ((pt1.x - x2) * (pt1.x - x2) + (pt1.y - y2) * (pt1.y - y2))) { swap_point(&pt1, &pt2); } area = (area_triangle(x1, y1, pt3.x, pt3.y, pt1.x, pt1.y) + area_triangle(x1, y1, pt1.x, pt1.y, pt2.x, pt2.y) + area_triangle(x1, y1, pt2.x, pt2.y, pt4.x, pt4.y) + area_arc(pt1.x, pt1.y, pt3.x, pt3.y, 1.) + area_arc(pt2.x, pt2.y, pt4.x, pt4.y, 1.)); } } else { inter = circle_segment(x1, y1, x2, y2); pt1 = inter.p1; pt2 = inter.p2; inter = circle_segment(x2, y2, x3, y3); pt3 = inter.p1; pt4 = inter.p2; inter = circle_segment(x3, y3, x1, y1); pt5 = inter.p1; pt6 = inter.p2; if (pt1.x <= 1.) { xp = 0.5 * (pt1.x + pt2.x); yp = 0.5 * (pt1.y + pt2.y); area = (triangle_unitcircle_overlap(x1, y1, x3, y3, xp, yp) + triangle_unitcircle_overlap(x2, y2, x3, y3, xp, yp)); } else if (pt3.x <= 1.) { xp = 0.5 * (pt3.x + pt4.x); yp = 0.5 * (pt3.y + pt4.y); area = (triangle_unitcircle_overlap(x3, y3, x1, y1, xp, yp) + triangle_unitcircle_overlap(x2, y2, x1, y1, xp, yp)); } else if (pt5.x <= 1.) { xp = 0.5 * (pt5.x + pt6.x); yp = 0.5 * (pt5.y + pt6.y); area = (triangle_unitcircle_overlap(x1, y1, x2, y2, xp, yp) + triangle_unitcircle_overlap(x3, y3, x2, y2, xp, yp)); } else /* no intersections */ { if (in_triangle(0., 0., x1, y1, x2, y2, x3, y3)) { return PI; } else { return 0.; } } } return area; } /* exact overlap between a rectangle defined by (xmin, ymin, xmax, ymax) and an ellipse with major and minor axes rx and ry respectively and position angle theta. */ static double ellipoverlap( double xmin, double ymin, double xmax, double ymax, double a, double b, double theta ) { double cos_m_theta, sin_m_theta, scale; double x1, y1, x2, y2, x3, y3, x4, y4; cos_m_theta = cos(-theta); sin_m_theta = sin(-theta); /* scale by which the areas will be shrunk */ scale = a * b; /* Reproject rectangle to a frame in which ellipse is a unit circle */ x1 = (xmin * cos_m_theta - ymin * sin_m_theta) / a; y1 = (xmin * sin_m_theta + ymin * cos_m_theta) / b; x2 = (xmax * cos_m_theta - ymin * sin_m_theta) / a; y2 = (xmax * sin_m_theta + ymin * cos_m_theta) / b; x3 = (xmax * cos_m_theta - ymax * sin_m_theta) / a; y3 = (xmax * sin_m_theta + ymax * cos_m_theta) / b; x4 = (xmin * cos_m_theta - ymax * sin_m_theta) / a; y4 = (xmin * sin_m_theta + ymax * cos_m_theta) / b; /* Divide resulting quadrilateral into two triangles and find intersection with unit circle */ return scale * (triangle_unitcircle_overlap(x1, y1, x2, y2, x3, y3) + triangle_unitcircle_overlap(x1, y1, x4, y4, x3, y3)); } ================================================ FILE: src/sep.h ================================================ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file is part of SEP * * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC * Copyright 2014 SEP developers * * SEP is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SEP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SEP. If not, see . * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include #include #ifdef _MSC_VER #define SEP_API __declspec(dllexport) #else #define SEP_API __attribute__((visibility("default"))) #endif /* datatype codes */ #define SEP_TBYTE 11 /* 8-bit unsigned byte */ #define SEP_TINT 31 /* native int type */ #define SEP_TFLOAT 42 #define SEP_TDOUBLE 82 /* object & aperture flags */ #define SEP_OBJ_MERGED 0x0001 /* object is result of deblending */ #define SEP_OBJ_TRUNC 0x0002 /* object truncated at image boundary */ #define SEP_OBJ_DOVERFLOW 0x0004 /* not currently used, but could be */ #define SEP_OBJ_SINGU 0x0008 /* x,y fully correlated */ #define SEP_APER_TRUNC 0x0010 #define SEP_APER_HASMASKED 0x0020 #define SEP_APER_ALLMASKED 0x0040 #define SEP_APER_NONPOSITIVE 0x0080 /* noise_type values in sep_image */ #define SEP_NOISE_NONE 0 #define SEP_NOISE_STDDEV 1 #define SEP_NOISE_VAR 2 /* input flags for aperture photometry */ #define SEP_MASK_IGNORE 0x0004 /* threshold interpretation for sep_extract */ #define SEP_THRESH_REL 0 /* in units of standard deviations (sigma) */ #define SEP_THRESH_ABS 1 /* absolute data values */ /* filter types for sep_extract */ #define SEP_FILTER_CONV 0 #define SEP_FILTER_MATCHED 1 /* structs ------------------------------------------------------------------*/ /* sep_image * * Represents an image, including data, noise and mask arrays, and * gain. */ typedef struct { const void * data; /* data array */ const void * noise; /* noise array (can be NULL) */ const void * mask; /* mask array (can be NULL) */ const void * segmap; /* segmap array (can be NULL) */ int dtype; /* element type of image */ int ndtype; /* element type of noise */ int mdtype; /* element type of mask */ int sdtype; /* element type of segmap */ int64_t * segids; /* unique ids in segmap */ int64_t * idcounts; /* counts of unique ids in segmap */ int64_t numids; /* total number of unique ids in segmap */ int64_t w; /* array width */ int64_t h; /* array height */ double noiseval; /* scalar noise value; used only if noise == NULL */ short noise_type; /* interpretation of noise value */ double gain; /* (poisson counts / data unit) */ double maskthresh; /* pixel considered masked if mask > maskthresh */ } sep_image; /* sep_bkg * * The result of sep_background() -- represents a smooth image background * and its noise with splines. */ typedef struct { int64_t w, h; /* original image width, height */ int64_t bw, bh; /* single tile width, height */ int64_t nx, ny; /* number of tiles in x, y */ int64_t n; /* nx*ny */ float global; /* global mean */ float globalrms; /* global sigma */ float * back; /* node data for interpolation */ float * dback; float * sigma; float * dsigma; } sep_bkg; /* sep_catalog * * The result of sep_extract(). This is a struct of arrays. Each array has * one entry per detected object. */ typedef struct { int nobj; /* number of objects (length of all arrays) */ float * thresh; /* threshold (ADU) */ int64_t * npix; /* # pixels extracted (size of pix array) */ int64_t * tnpix; /* # pixels above thresh (unconvolved) */ int64_t *xmin, *xmax; int64_t *ymin, *ymax; double *x, *y; /* barycenter (first moments) */ double *x2, *y2, *xy; /* second moments */ double *errx2, *erry2, *errxy; /* second moment errors */ float *a, *b, *theta; /* ellipse parameters */ float *cxx, *cyy, *cxy; /* ellipse parameters (alternative) */ float * cflux; /* total flux of pixels (convolved im) */ float * flux; /* total flux of pixels (unconvolved) */ float * cpeak; /* peak intensity (ADU) (convolved) */ float * peak; /* peak intensity (ADU) (unconvolved) */ int64_t *xcpeak, *ycpeak; /* x, y coords of peak (convolved) pixel */ int64_t *xpeak, *ypeak; /* x, y coords of peak (unconvolved) pixel */ short * flag; /* extraction flags */ int64_t ** pix; /* array giving indicies of object's pixels in */ /* image (linearly indexed). Length is `npix`. */ /* (pointer to within the `objectspix` buffer) */ int64_t * objectspix; /* buffer holding pixel indicies for all objects */ } sep_catalog; /*--------------------- global background estimation ------------------------*/ /* sep_background() * * Create representation of spatially varying image background and variance. * * Note that the returned pointer must eventually be freed by calling * `sep_bkg_free()`. * * In addition to the image mask (if present), pixels <= -1e30 and NaN * are ignored. * * Source Extractor defaults: * * - bw, bh = (64, 64) * - fw, fh = (3, 3) * - fthresh = 0.0 */ SEP_API int sep_background( const sep_image * image, int64_t bw, int64_t bh, /* size of a single background tile */ int64_t fw, int64_t fh, /* filter size in tiles */ double fthresh, /* filter threshold */ sep_bkg ** bkg ); /* OUTPUT */ /* sep_bkg_global[rms]() * * Get the estimate of the global background "median" or standard deviation. */ SEP_API float sep_bkg_global(const sep_bkg * bkg); SEP_API float sep_bkg_globalrms(const sep_bkg * bkg); /* sep_bkg_pix() * * Return background at (x, y). * Unlike other routines, this uses simple linear interpolation. */ SEP_API float sep_bkg_pix(const sep_bkg * bkg, int64_t x, int64_t y); /* sep_bkg_[sub,rms]line() * * Evaluate the background or RMS at line `y`. * Uses bicubic spline interpolation between background map verticies. * The second function subtracts the background from the input array. * Line must be an array with same width as original image. */ SEP_API int sep_bkg_line(const sep_bkg * bkg, int64_t y, void * line, int dtype); SEP_API int sep_bkg_subline(const sep_bkg * bkg, int64_t y, void * line, int dtype); SEP_API int sep_bkg_rmsline(const sep_bkg * bkg, int64_t y, void * line, int dtype); /* sep_bkg_[sub,rms]array() * * Evaluate the background or RMS for entire image. * Uses bicubic spline interpolation between background map verticies. * The second function subtracts the background from the input array. * `arr` must be an array of the same size as original image. */ SEP_API int sep_bkg_array(const sep_bkg * bkg, void * arr, int dtype); SEP_API int sep_bkg_subarray(const sep_bkg * bkg, void * arr, int dtype); SEP_API int sep_bkg_rmsarray(const sep_bkg * bkg, void * arr, int dtype); /* sep_bkg_free() * * Free memory associated with bkg. */ SEP_API void sep_bkg_free(sep_bkg * bkg); /*-------------------------- source extraction ------------------------------*/ /* sep_extract() * * Extract sources from an image. Source Extractor defaults are shown * in [ ] above. * * Notes * ----- * `dtype` and `ndtype` indicate the data type (float, int, double) of the * image and noise arrays, respectively. * * If `noise` is NULL, thresh is interpreted as an absolute threshold. * If `noise` is not null, thresh is interpreted as a relative threshold * (the absolute threshold will be thresh*noise[i,j]). * */ SEP_API int sep_extract( const sep_image * image, float thresh, /* detection threshold [1.5] */ int thresh_type, /* threshold units [SEP_THRESH_REL] */ int minarea, /* minimum area in pixels [5] */ const float * conv, /* convolution array (can be NULL) */ /* [{1 2 1 2 4 2 1 2 1}] */ int64_t convw, int64_t convh, /* w, h of convolution array [3,3] */ int filter_type, /* convolution (0) or matched (1) [0] */ int deblend_nthresh, /* deblending thresholds [32] */ double deblend_cont, /* min. deblending contrast [0.005] */ int clean_flag, /* perform cleaning? [1] */ double clean_param, /* clean parameter [1.0] */ sep_catalog ** catalog ); /* OUTPUT catalog */ /* set and get the size of the pixel stack used in extract() */ SEP_API void sep_set_extract_pixstack(size_t val); SEP_API size_t sep_get_extract_pixstack(void); /* set and get the number of sub-objects limit when deblending in extract() */ SEP_API void sep_set_sub_object_limit(int val); SEP_API int sep_get_sub_object_limit(void); /* free memory associated with a catalog */ SEP_API void sep_catalog_free(sep_catalog * catalog); /*-------------------------- aperture photometry ----------------------------*/ /* Sum array values within a circular aperture. * * Notes * ----- * error : Can be a scalar (default), an array, or NULL * If an array, set the flag SEP_ERROR_IS_ARRAY in `inflags`. * Can represent 1-sigma std. deviation (default) or variance. * If variance, set the flag SEP_ERROR_IS_VARIANCE in `inflags`. * * gain : If 0.0, poisson noise on sum is ignored when calculating error. * Otherwise, (sum / gain) is added to the variance on sum. * * area : Total pixel area included in sum. Includes masked pixels that were * corrected. The area can differ from the exact area of a circle due * to inexact subpixel sampling and intersection with array boundaries. */ SEP_API int sep_sum_circle( const sep_image * image, double x, /* center of aperture in x */ double y, /* center of aperture in y */ double r, /* radius of aperture */ int id, /* optional id to test against segmap array */ int subpix, /* subpixel sampling */ short inflags, /* input flags (see below) */ double * sum, /* OUTPUT: sum */ double * sumerr, /* OUTPUT: error on sum */ double * area, /* OUTPUT: area included in sum */ short * flag ); /* OUTPUT: flags */ SEP_API int sep_sum_circann( const sep_image * image, double x, double y, double rin, double rout, int id, int subpix, short inflags, double * sum, double * sumerr, double * area, short * flag ); SEP_API int sep_sum_ellipse( const sep_image * image, double x, double y, double a, double b, double theta, double r, int id, int subpix, short inflags, double * sum, double * sumerr, double * area, short * flag ); SEP_API int sep_sum_ellipann( const sep_image * image, double x, double y, double a, double b, double theta, double rin, double rout, int id, int subpix, short inflags, double * sum, double * sumerr, double * area, short * flag ); /* sep_sum_circann_multi() * * Sum an array of circular annuli more efficiently (but with no exact mode). * * Notable parameters: * * rmax: Input radii are [rmax/n, 2*rmax/n, 3*rmax/n, ..., rmax]. * n: Length of input and output arrays. * sum: Preallocated array of length n holding sums in annuli. sum[0] * corrresponds to r=[0, rmax/n], sum[n-1] to outermost annulus. * sumvar: Preallocated array of length n holding variance on sums. * area: Preallocated array of length n holding area summed in each annulus. * maskarea: Preallocated array of length n holding masked area in each annulus (if mask not NULL). * flag: Output flag (non-array). */ SEP_API int sep_sum_circann_multi( const sep_image * im, double x, double y, double rmax, int64_t n, int id, int subpix, short inflag, double * sum, double * sumvar, double * area, double * maskarea, short * flag ); /* sep_flux_radius() * * Calculate the radii enclosing the requested fraction of flux relative * to radius rmax. * * (see previous functions for most arguments) * rmax : maximum radius to analyze * fluxtot : scale requested flux fractions to this. (If NULL, flux within `rmax` is used.) * fluxfrac : array of requested fractions. * n : length of fluxfrac * r : (output) result array of length n. * flag : (output) scalar flag */ SEP_API int sep_flux_radius( const sep_image * im, double x, double y, double rmax, int id, int subpix, short inflag, const double * fluxtot, const double * fluxfrac, int64_t n, double * r, short * flag ); /* sep_kron_radius() * * Calculate Kron radius within an ellipse given by * * cxx*(x'-x)^2 + cyy*(y'-y)^2 + cxy*(x'-x)*(y'-y) < r^2 * * The Kron radius is sum(r_i * v_i) / sum(v_i) where v_i is the value of pixel * i and r_i is the "radius" of pixel i, as given by the left hand side of * the above equation. * * Flags that might be set: * SEP_APER_HASMASKED - at least one of the pixels in the ellipse is masked. * SEP_APER_ALLMASKED - All pixels in the ellipse are masked. kronrad = 0. * SEP_APER_NONPOSITIVE - There was a nonpositive numerator or deminator. * kronrad = 0. */ SEP_API int sep_kron_radius( const sep_image * im, double x, double y, double cxx, double cyy, double cxy, double r, int id, double * kronrad, short * flag ); /* sep_windowed() * * Calculate "windowed" position parameters via an iterative procedure. * * x, y : initial center * sig : sigma of Gaussian to use for weighting. The integration * radius is 4 * sig. * subpix : Subpixels to use in aperture-pixel overlap. * SExtractor uses 11. 0 is supported for exact overlap. * xout, yout : output center. * niter : number of iterations used. */ SEP_API int sep_windowed( const sep_image * im, double x, double y, double sig, int subpix, short inflag, double * xout, double * yout, int * niter, short * flag ); /* sep_set_ellipse() * * Set array elements within an ellipitcal aperture to a given value. * * Ellipse: cxx*(x'-x)^2 + cyy*(y'-y)^2 + cxy*(x'-x)*(y'-y) = r^2 */ SEP_API void sep_set_ellipse( unsigned char * arr, int64_t w, int64_t h, double x, double y, double cxx, double cyy, double cxy, double r, unsigned char val ); /* sep_ellipse_axes() * sep_ellipse_coeffs() * * Convert between coefficient representation of ellipse, * cxx*(x'-x)^2 + cyy*(y'-y)^2 + cxy*(x'-x)*(y'-y) = r^2, * and axis representation of an ellipse. The axis representation is * defined by: * * a = semimajor axis * b = semiminor axis * theta = angle in radians counter-clockwise from positive x axis */ SEP_API int sep_ellipse_axes( double cxx, double cyy, double cxy, double * a, double * b, double * theta ); SEP_API void sep_ellipse_coeffs( double a, double b, double theta, double * cxx, double * cyy, double * cxy ); /*----------------------- info & error messaging ----------------------------*/ /* sep_version_string : library version (e.g., "0.2.0") */ SEP_API extern const char * const sep_version_string; /* sep_get_errmsg() * * Return a short descriptive error message that corresponds to the input * error status value. The message may be up to 60 characters long, plus * the terminating null character. */ SEP_API void sep_get_errmsg(int status, char * errtext); /* sep_get_errdetail() * * Return a longer error message with more specifics about the problem. * The message may be up to 512 characters. */ SEP_API void sep_get_errdetail(char * errtext); ================================================ FILE: src/sepcore.h ================================================ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file is part of SEP * * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC * Copyright 2014 SEP developers * * SEP is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SEP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SEP. If not, see . * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include #define RETURN_OK 0 /* must be zero */ #define MEMORY_ALLOC_ERROR 1 #define PIXSTACK_FULL 2 #define ILLEGAL_DTYPE 3 #define ILLEGAL_SUBPIX 4 #define NON_ELLIPSE_PARAMS 5 #define ILLEGAL_APER_PARAMS 6 #define DEBLEND_OVERFLOW 7 #define LINE_NOT_IN_BUF 8 #define RELTHRESH_NO_NOISE 9 #define UNKNOWN_NOISE_TYPE 10 #define BIG 1e+30 /* a huge number (< biggest value a float can store) */ #define PI M_PI #define DEG (PI / 180.0) /* 1 deg in radians */ typedef int LONG; typedef unsigned int ULONG; typedef unsigned char BYTE; /* a byte */ /* keep these synchronized */ typedef float PIXTYPE; /* type used inside of functions */ #define PIXDTYPE SEP_TFLOAT /* dtype code corresponding to PIXTYPE */ /* signature of converters */ typedef PIXTYPE (*converter)(const void * ptr); typedef void (*array_converter)(const void * ptr, int64_t n, PIXTYPE * target); typedef void (*array_writer)(const float * ptr, int64_t n, void * target); #define QCALLOC(ptr, typ, nel, status) \ { \ if (!(ptr = (typ *)calloc((size_t)(nel), sizeof(typ)))) { \ char errtext[160]; \ sprintf( \ errtext, \ #ptr " (" #nel \ "=%lu elements) " \ "at line %d in module " __FILE__ " !", \ (size_t)(nel) * sizeof(typ), \ __LINE__ \ ); \ put_errdetail(errtext); \ status = MEMORY_ALLOC_ERROR; \ goto exit; \ }; \ } #define QMALLOC(ptr, typ, nel, status) \ { \ if (!(ptr = malloc((size_t)(nel) * sizeof(typ)))) { \ char errtext[160]; \ sprintf( \ errtext, \ #ptr " (" #nel \ "=%lu elements) " \ "at line %d in module " __FILE__ " !", \ (size_t)(nel) * sizeof(typ), \ __LINE__ \ ); \ put_errdetail(errtext); \ status = MEMORY_ALLOC_ERROR; \ goto exit; \ }; \ } float fqmedian(float * ra, int64_t n); void put_errdetail(const char * errtext); int get_converter(int dtype, converter * f, int64_t * size); int get_array_converter(int dtype, array_converter * f, int64_t * size); int get_array_writer(int dtype, array_writer * f, int64_t * size); int get_array_subtractor(int dtype, array_writer * f, int64_t * size); #if defined(_MSC_VER) #define _Thread_local __declspec(thread) #define _Atomic // this isn't great, but we only use atomic for global settings #define rand_r(SEED) \ rand() // MSVC doesn't provide rand_r, but makes rand safe for re-entrancy #endif ================================================ FILE: src/util.c ================================================ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file is part of SEP * * All content except array comparison functions fqcmp() and fqmedian() is * distributed under an MIT license. * * Copyright 2014 SEP developers * * Array comparison functions fqcmp() and fqmedian() are distributed under an * LGPL license: * * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC * Copyright 2014 SEP developers * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include #include #include #include #include "sep.h" #include "sepcore.h" #define DETAILSIZE 512 #ifndef SEP_VERSION_STRING #define SEP_VERSION_STRING "1.3.6" #endif const char * const sep_version_string = SEP_VERSION_STRING; static _Thread_local char _errdetail_buffer[DETAILSIZE] = ""; /****************************************************************************/ /* data type conversion mechanics for runtime type conversion */ PIXTYPE convert_dbl(const void * ptr) { return *(const double *)ptr; } PIXTYPE convert_flt(const void * ptr) { return *(const float *)ptr; } PIXTYPE convert_int(const void * ptr) { return *(const int *)ptr; } PIXTYPE convert_byt(const void * ptr) { return *(const BYTE *)ptr; } /* return the correct converter depending on the datatype code */ int get_converter(int dtype, converter * f, int64_t * size) { int status = RETURN_OK; if (dtype == SEP_TFLOAT) { *f = convert_flt; *size = sizeof(float); } else if (dtype == SEP_TINT) { *f = convert_int; *size = sizeof(int); } else if (dtype == SEP_TDOUBLE) { *f = convert_dbl; *size = sizeof(double); } else if (dtype == SEP_TBYTE) { *f = convert_byt; *size = sizeof(BYTE); } else { *f = NULL; *size = 0; status = ILLEGAL_DTYPE; } return status; } /* array conversions */ void convert_array_flt(const void * ptr, int64_t n, PIXTYPE * target) { const float * source = ptr; int64_t i; for (i = 0; i < n; i++, source++) { target[i] = *source; } } void convert_array_dbl(const void * ptr, int64_t n, PIXTYPE * target) { const double * source = ptr; int64_t i; for (i = 0; i < n; i++, source++) { target[i] = *source; } } void convert_array_int(const void * ptr, int64_t n, PIXTYPE * target) { const int * source = ptr; int64_t i; for (i = 0; i < n; i++, source++) { target[i] = *source; } } void convert_array_byt(const void * ptr, int64_t n, PIXTYPE * target) { const BYTE * source = ptr; int64_t i; for (i = 0; i < n; i++, source++) { target[i] = *source; } } int get_array_converter(int dtype, array_converter * f, int64_t * size) { int status = RETURN_OK; if (dtype == SEP_TFLOAT) { *f = convert_array_flt; *size = sizeof(float); } else if (dtype == SEP_TBYTE) { *f = convert_array_byt; *size = sizeof(BYTE); } else if (dtype == SEP_TINT) { *f = convert_array_int; *size = sizeof(int); } else if (dtype == SEP_TDOUBLE) { *f = convert_array_dbl; *size = sizeof(double); } else { *f = NULL; *size = 0; status = ILLEGAL_DTYPE; } return status; } /****************************************************************************/ /* Copy a float array to various sorts of arrays */ void write_array_dbl(const float * ptr, int64_t n, void * target) { double * t = target; int64_t i; for (i = 0; i < n; i++, ptr++) { t[i] = (double)(*ptr); } } void write_array_int(const float * ptr, int64_t n, void * target) { int * t = target; int64_t i; for (i = 0; i < n; i++, ptr++) { t[i] = (int)(*ptr + 0.5); } } /* return the correct writer depending on the datatype code */ int get_array_writer(int dtype, array_writer * f, int64_t * size) { int status = RETURN_OK; if (dtype == SEP_TINT) { *f = write_array_int; *size = sizeof(int); } else if (dtype == SEP_TDOUBLE) { *f = write_array_dbl; *size = sizeof(double); } else { *f = NULL; *size = 0; status = ILLEGAL_DTYPE; } return status; } /* subtract a float array from arrays of various types */ void subtract_array_dbl(const float * ptr, int64_t n, void * target) { double * t = target; int64_t i; for (i = 0; i < n; i++, ptr++) { t[i] -= (double)(*ptr); } } void subtract_array_flt(const float * ptr, int64_t n, void * target) { float * t = target; int64_t i; for (i = 0; i < n; i++, ptr++) { t[i] -= *ptr; } } void subtract_array_int(const float * ptr, int64_t n, void * target) { int * t = target; int64_t i; for (i = 0; i < n; i++, ptr++) { t[i] -= (int)(*ptr + 0.5); } } /* return the correct subtractor depending on the datatype code */ int get_array_subtractor(int dtype, array_writer * f, int64_t * size) { int status = RETURN_OK; char errtext[80]; if (dtype == SEP_TFLOAT) { *f = subtract_array_flt; *size = sizeof(float); } else if (dtype == SEP_TINT) { *f = subtract_array_int; *size = sizeof(int); } else if (dtype == SEP_TDOUBLE) { *f = subtract_array_dbl; *size = sizeof(double); } else { *f = NULL; *size = 0; status = ILLEGAL_DTYPE; sprintf(errtext, "in get_array_subtractor(): %d", dtype); put_errdetail(errtext); } return status; } /*****************************************************************************/ /* Error messaging */ void sep_get_errmsg(int status, char * errtext) /* Return a short descriptive error message that corresponds to the input * error status value. The message may be up to 60 characters long, plus * the terminating null character. */ { errtext[0] = '\0'; switch (status) { case RETURN_OK: strcpy(errtext, "OK - no error"); break; case MEMORY_ALLOC_ERROR: strcpy(errtext, "memory allocation"); break; case PIXSTACK_FULL: strcpy(errtext, "internal pixel buffer full"); break; case DEBLEND_OVERFLOW: strcpy(errtext, "object deblending overflow"); break; case ILLEGAL_DTYPE: strcpy(errtext, "dtype not recognized/unsupported"); break; case ILLEGAL_SUBPIX: strcpy(errtext, "subpix value must be nonnegative"); break; case NON_ELLIPSE_PARAMS: strcpy(errtext, "parameters do not describe ellipse"); break; case ILLEGAL_APER_PARAMS: strcpy(errtext, "invalid aperture parameters"); break; case LINE_NOT_IN_BUF: strcpy(errtext, "array line out of buffer"); break; case RELTHRESH_NO_NOISE: strcpy(errtext, "relative threshold but image has noise_type of NONE"); break; case UNKNOWN_NOISE_TYPE: strcpy(errtext, "image has unknown noise_type"); break; default: strcpy(errtext, "unknown error status"); break; } } void sep_get_errdetail(char * errtext) { strcpy(errtext, _errdetail_buffer); memset(_errdetail_buffer, 0, DETAILSIZE); } void put_errdetail(const char * errtext) { strcpy(_errdetail_buffer, errtext); } /*****************************************************************************/ /* Array median */ static int fqcmp(const void * p1, const void * p2) /* Sorting function for floats, used in fqmedian() below. * Return value is 1 if *p1>*p2, 0 if *p1==*p2, -1 otherwise */ { double f1 = *((const float *)p1); double f2 = *((const float *)p2); return f1 > f2 ? 1 : (f1 < f2 ? -1 : 0); } float fqmedian(float * ra, int64_t n) /* Compute median of an array of floats. * * WARNING: input data are reordered! */ { qsort(ra, n, sizeof(float), fqcmp); if (n < 2) { return *ra; } else { return n & 1 ? ra[n / 2] : (ra[n / 2 - 1] + ra[n / 2]) / 2.0; } } ================================================ FILE: test.py ================================================ #!/usr/bin/env py.test """Test the python functionality of SEP.""" from __future__ import division, print_function import os import numpy as np import pytest from numpy.lib import recfunctions as rfn from numpy.testing import assert_allclose, assert_approx_equal, assert_equal import sep # unicode_literals doesn't play well with numpy dtype field names # Try to import any FITS reader try: from fitsio import read as getdata NO_FITS = False except: try: from astropy.io.fits import getdata NO_FITS = False except: NO_FITS = True IMAGE_FNAME = os.path.join("data", "image.fits") BACKIMAGE_FNAME = os.path.join("data", "back.fits") RMSIMAGE_FNAME = os.path.join("data", "rms.fits") IMAGECAT_FNAME = os.path.join("data", "image.cat") IMAGECAT_DTYPE = [ ("number", np.int64), ("x", np.float64), ("y", np.float64), ("xwin", np.float64), ("ywin", np.float64), ("x2", np.float64), ("y2", np.float64), ("xy", np.float64), ("errx2", np.float64), ("erry2", np.float64), ("errxy", np.float64), ("a", np.float64), ("flux_aper", np.float64), ("fluxerr_aper", np.float64), ("kron_radius", np.float64), ("flux_auto", np.float64), ("fluxerr_auto", np.float64), ("flux_radius", np.float64, (3,)), ("flags", np.int64), ] SUPPORTED_IMAGE_DTYPES = [np.float64, np.float32, np.int32] # If we have a FITS reader, read in the necessary test images if not NO_FITS: image_data = getdata(IMAGE_FNAME) image_refback = getdata(BACKIMAGE_FNAME) image_refrms = getdata(RMSIMAGE_FNAME) # ----------------------------------------------------------------------------- # Helpers def assert_allclose_structured(x, y): """ Assert that two structured arrays are close. Compares floats relatively and everything else exactly. Parameters ---------- x, y : array-like Structured arrays to be compared. """ assert x.dtype == y.dtype for name in x.dtype.names: if np.issubdtype(x.dtype[name], float): assert_allclose(x[name], y[name]) else: assert_equal(x[name], y[name]) def matched_filter_snr(data, noise, kernel): r""" Super slow implementation of matched filter SNR for testing. At each output pixel :math:`i`, the value is: .. math:: \frac{\sum(\text{data}[i] * \text{kernel}[i] / \text{noise}[i]^2)} {\sqrt\sum(\text{kernel}[i]^2 / \text{noise}[i]^2)} Parameters ---------- data : array-like The 2D data to be tested. noise : array-like The noise corresponding to the input ``data``. kernel : array-like The kernel used for filtering. Returns ------- array-like The output SNR array, the same size as ``data``. """ ctr = kernel.shape[0] // 2, kernel.shape[1] // 2 kslice = ( (0 - ctr[0], kernel.shape[0] - ctr[0]), # range in axis 0 (0 - ctr[1], kernel.shape[1] - ctr[1]), ) # range in axis 1 out = np.empty_like(data) for y in range(data.shape[0]): jmin = y + kslice[0][0] # min and max indicies to sum over jmax = y + kslice[0][1] kjmin = 0 # min and max kernel indicies to sum over kjmax = kernel.shape[0] # if we're over the edge of the image, limit extent if jmin < 0: offset = -jmin jmin += offset kjmin += offset if jmax > data.shape[0]: offset = data.shape[0] - jmax jmax += offset kjmax += offset for x in range(data.shape[1]): imin = x + kslice[1][0] # min and max indicies to sum over imax = x + kslice[1][1] kimin = 0 # min and max kernel indicies to sum over kimax = kernel.shape[1] # if we're over the edge of the image, limit extent if imin < 0: offset = -imin imin += offset kimin += offset if imax > data.shape[1]: offset = data.shape[1] - imax imax += offset kimax += offset d = data[jmin:jmax, imin:imax] n = noise[jmin:jmax, imin:imax] w = 1.0 / n**2 k = kernel[kjmin:kjmax, kimin:kimax] out[y, x] = np.sum(d * k * w) / np.sqrt(np.sum(k**2 * w)) return out # ----------------------------------------------------------------------------- # Test versus Source Extractor results @pytest.mark.skipif(NO_FITS, reason="no FITS reader") def test_vs_sextractor(): """ Test behavior of sep versus sextractor. Note: we turn deblending off for this test. This is because the deblending algorithm uses a random number generator. Since the sequence of random numbers is not the same between sextractor and sep or between different platforms, object member pixels (and even the number of objects) can differ when deblending is on. Deblending is turned off by setting DEBLEND_MINCONT=1.0 in the sextractor configuration file and by setting deblend_cont=1.0 in sep.extract(). """ data = np.copy(image_data) # make an explicit copy so we can 'subfrom' bkg = sep.Background(data, bw=64, bh=64, fw=3, fh=3) # Test that SExtractor background is same as SEP: bkgarr = bkg.back(dtype=np.float32) assert_allclose(bkgarr, image_refback, rtol=1.0e-5) # Test that SExtractor background rms is same as SEP: rmsarr = bkg.rms(dtype=np.float32) assert_allclose(rmsarr, image_refrms, rtol=1.0e-4) # Extract objects (use deblend_cont=1.0 to disable deblending). bkg.subfrom(data) objs = sep.extract(data, 1.5, err=bkg.globalrms, deblend_cont=1.0) objs = np.sort(objs, order=["y"]) # Read SExtractor result refobjs = np.loadtxt(IMAGECAT_FNAME, dtype=IMAGECAT_DTYPE) refobjs = np.sort(refobjs, order=["y"]) # Found correct number of sources at the right locations? assert_allclose(objs["x"], refobjs["x"] - 1.0, atol=1.0e-3) assert_allclose(objs["y"], refobjs["y"] - 1.0, atol=1.0e-3) # Correct Variance and Variance Errors? assert_allclose(objs["x2"], refobjs["x2"], atol=1.0e-4) assert_allclose(objs["y2"], refobjs["y2"], atol=1.0e-4) assert_allclose(objs["xy"], refobjs["xy"], atol=1.0e-4) assert_allclose(objs["errx2"], refobjs["errx2"], rtol=1.0e-4) assert_allclose(objs["erry2"], refobjs["erry2"], rtol=1.0e-4) assert_allclose(objs["errxy"], refobjs["errxy"], rtol=1.0e-3) # Test aperture flux flux, fluxerr, flag = sep.sum_circle( data, objs["x"], objs["y"], 5.0, err=bkg.globalrms ) assert_allclose(flux, refobjs["flux_aper"], rtol=2.0e-4) assert_allclose(fluxerr, refobjs["fluxerr_aper"], rtol=1.0e-5) # check if the flags work at all (comparison values assert ((flag & sep.APER_TRUNC) != 0).sum() == 4 assert ((flag & sep.APER_HASMASKED) != 0).sum() == 0 # Test "flux_auto" kr, flag = sep.kron_radius( data, objs["x"], objs["y"], objs["a"], objs["b"], objs["theta"], 6.0 ) flux, fluxerr, flag = sep.sum_ellipse( data, objs["x"], objs["y"], objs["a"], objs["b"], objs["theta"], r=2.5 * kr, err=bkg.globalrms, subpix=1, ) # For some reason, one object doesn't match. It's very small # and kron_radius is set to 0.0 in SExtractor, but 0.08 in sep. # Could be due to a change in SExtractor between v2.8.6 (used to # generate "truth" catalog) and v2.18.11 (from which sep was forked). i = 56 # index is 59 when deblending is on. kr[i] = 0.0 flux[i] = 0.0 fluxerr[i] = 0.0 # We use atol for radius because it is reported to nearest 0.01 in # reference objects. assert_allclose(2.5 * kr, refobjs["kron_radius"], atol=0.01, rtol=0.0) assert_allclose(flux, refobjs["flux_auto"], rtol=0.0005) assert_allclose(fluxerr, refobjs["fluxerr_auto"], rtol=0.0005) # Test using a mask in kron_radius and sum_ellipse. for dtype in [np.bool_, np.int32, np.float32, np.float64]: mask = np.zeros_like(data, dtype=dtype) kr2, flag = sep.kron_radius( data, objs["x"], objs["y"], objs["a"], objs["b"], objs["theta"], 6.0, mask=mask, ) kr2[i] = 0.0 assert np.all(kr == kr2) # Test ellipse representation conversion cxx, cyy, cxy = sep.ellipse_coeffs(objs["a"], objs["b"], objs["theta"]) assert_allclose(cxx, objs["cxx"], rtol=1.0e-4) assert_allclose(cyy, objs["cyy"], rtol=1.0e-4) assert_allclose(cxy, objs["cxy"], rtol=1.0e-4) a, b, theta = sep.ellipse_axes(objs["cxx"], objs["cyy"], objs["cxy"]) assert_allclose(a, objs["a"], rtol=1.0e-4) assert_allclose(b, objs["b"], rtol=1.0e-4) assert_allclose(theta, objs["theta"], rtol=1.0e-4) # test round trip cxx, cyy, cxy = sep.ellipse_coeffs(a, b, theta) assert_allclose(cxx, objs["cxx"], rtol=1.0e-4) assert_allclose(cyy, objs["cyy"], rtol=1.0e-4) assert_allclose(cxy, objs["cxy"], rtol=1.0e-4) # test flux_radius fr, flags = sep.flux_radius( data, objs["x"], objs["y"], 6.0 * refobjs["a"], [0.1, 0.5, 0.6], normflux=refobjs["flux_auto"], subpix=5, ) assert_allclose(fr, refobjs["flux_radius"], rtol=0.04, atol=0.01) # test winpos sig = 2.0 / 2.35 * fr[:, 1] # flux_radius = 0.5 xwin, ywin, flag = sep.winpos(data, objs["x"], objs["y"], sig) assert_allclose(xwin, refobjs["xwin"] - 1.0, rtol=0.0, atol=0.0015) assert_allclose(ywin, refobjs["ywin"] - 1.0, rtol=0.0, atol=0.0015) # ----------------------------------------------------------------------------- # Background def test_masked_background(): """ Check the background filtering. Check that the derived background is consistent with an explicit mask, masking no pixels. Also check that the expected result is returned if certain pixels are masked. """ data = 0.1 * np.ones((6, 6)) data[1, 1] = 1.0 data[4, 1] = 1.0 data[1, 4] = 1.0 data[4, 4] = 1.0 mask = np.zeros((6, 6), dtype=np.bool_) # Background array without mask sky = sep.Background(data, bw=3, bh=3, fw=1, fh=1) bkg1 = sky.back() # Background array with all False mask sky = sep.Background(data, mask=mask, bw=3, bh=3, fw=1, fh=1) bkg2 = sky.back() # All False mask should be the same assert_allclose(bkg1, bkg2) # Masking high pixels should give a flat background mask[1, 1] = True mask[4, 1] = True mask[1, 4] = True mask[4, 4] = True sky = sep.Background(data, mask=mask, bw=3, bh=3, fw=1, fh=1) assert_approx_equal(sky.globalback, 0.1) assert_allclose(sky.back(), 0.1 * np.ones((6, 6))) @pytest.mark.skipif(NO_FITS, reason="no FITS reader") def test_background_special(): """ Test the special methods of `sep.Background`. """ bkg = sep.Background(image_data, bw=64, bh=64, fw=3, fh=3) # test __array__ method assert np.all(np.array(bkg) == bkg.back()) # test __rsub__ method d1 = image_data - bkg d2 = np.copy(image_data) bkg.subfrom(d2) assert np.all(d1 == d2) def test_background_boxsize(): """ Test that `sep.Background` works when boxsize is same as image. """ ny, nx = 100, 100 data = np.ones((ny, nx), dtype=np.float64) bkg = sep.Background(data, bh=ny, bw=nx, fh=1, fw=1) bkg.back() def test_background_rms(): """ Test that `sep.Background.rms` at least works. """ ny, nx = 1024, 1024 data = np.random.randn(ny, nx) bkg = sep.Background(data) rms = bkg.rms() assert rms.dtype == np.float64 assert rms.shape == (ny, nx) # ----------------------------------------------------------------------------- # Extract @pytest.mark.skipif(NO_FITS, reason="no FITS reader") def test_extract_with_noise_array(): """ Test extraction with a flat noise array. This checks that a constant noise array gives the same result as extracting without a noise array, for a given threshold. """ # Get some background-subtracted test data: data = np.copy(image_data) bkg = sep.Background(data, bw=64, bh=64, fw=3, fh=3) bkg.subfrom(data) # Ensure that extraction with constant noise array gives the expected # result. We have to use conv=None here because the results are *not* # the same when convolution is on! This is because the noise map is # convolved. Near edges, the convolution doesn't adjust for pixels # off edge boundaries. As a result, the convolved noise map is not # all ones. # Deblending is also turned off, as this appears to differ slightly # across platforms - see `test_vs_sextractor()`. objects = sep.extract( data, 1.5 * bkg.globalrms, filter_kernel=None, deblend_cont=1.0 ) objects2 = sep.extract( data, 1.5 * bkg.globalrms, err=np.ones_like(data), filter_kernel=None, deblend_cont=1.0, ) names_to_remove = ["errx2", "erry2", "errxy"] names_to_keep = [i for i in objects.dtype.names if i not in names_to_remove] objects = objects[names_to_keep] objects2 = objects2[names_to_keep] assert_allclose_structured(objects, objects2) # Less trivial test where thresh is realistic. Still a flat noise map. noise = bkg.globalrms * np.ones_like(data) objects2 = sep.extract(data, 1.5, err=noise, filter_kernel=None, deblend_cont=1.0) names_to_remove = ["errx2", "erry2", "errxy"] names_to_keep = [i for i in objects.dtype.names if i not in names_to_remove] objects = objects[names_to_keep] objects2 = objects2[names_to_keep] assert_allclose_structured(objects, objects2) def test_extract_with_noise_convolution(): """ Test extraction when there is both noise and convolution. This will use the matched filter implementation, and will handle bad pixels and edge effects gracefully. """ # Start with an empty image where we label the noise as 1 sigma everywhere. image = np.zeros((20, 20)) error = np.ones((20, 20)) # Add some noise representing bad pixels. We do not want to detect these. image[17, 3] = 100.0 error[17, 3] = 100.0 image[10, 0] = 100.0 error[10, 0] = 100.0 image[17, 17] = 100.0 error[17, 17] = 100.0 # Add some real point sources that we should find. image[3, 17] = 10.0 image[6, 6] = 2.0 image[7, 6] = 1.0 image[5, 6] = 1.0 image[6, 5] = 1.0 image[6, 7] = 1.0 objects = sep.extract(image, 2.0, minarea=1, err=error) objects.sort(order=["x", "y"]) # Check that we recovered the two correct objects and not the others. assert len(objects) == 2 assert_approx_equal(objects[0]["x"], 6.0) assert_approx_equal(objects[0]["y"], 6.0) assert_approx_equal(objects[1]["x"], 17.0) assert_approx_equal(objects[1]["y"], 3.0) def test_extract_matched_filter_at_edge(): """ Test bright source detection at the edge of an image. Exercise bug where bright star at end of image not detected with noise array and matched filter on. """ data = np.zeros((20, 20)) err = np.ones_like(data) kernel = np.array([[1.0, 2.0, 1.0], [2.0, 4.0, 2.0], [1.0, 2.0, 1.0]]) data[18:20, 9:12] = kernel[0:2, :] objects, pix = sep.extract( data, 2.0, err=err, filter_kernel=kernel, filter_type="matched", segmentation_map=True, ) assert len(objects) == 1 assert objects["npix"][0] == 6 @pytest.mark.skipif(NO_FITS, reason="no FITS reader") def test_extract_with_mask(): """ Test that object detection only occurs in unmasked regions. """ # Get some background-subtracted test data: data = np.copy(image_data) bkg = sep.Background(data, bw=64, bh=64, fw=3, fh=3) bkg.subfrom(data) # mask half the image ylim = data.shape[0] // 2 mask = np.zeros(data.shape, dtype=np.bool_) mask[ylim:, :] = True objects = sep.extract(data, 1.5 * bkg.globalrms, mask=mask) # check that we found some objects and that they are all in the unmasked # region. assert len(objects) > 0 assert np.all(objects["y"] < ylim) @pytest.mark.skipif(NO_FITS, reason="no FITS reader") def test_extract_with_maskthresh(): """ Test that object detection only occurs in unmasked regions. """ # Get some background-subtracted test data: data = np.copy(image_data) bkg = sep.Background(data, bw=64, bh=64, fw=3, fh=3) bkg.subfrom(data) # mask half the image ylim = data.shape[0] // 2 mask = np.zeros(data.shape, dtype=float) mask[ylim:, :] = 1.0 objects_unmasked = sep.extract(data, 1.5 * bkg.globalrms, deblend_cont=1.0) objects_unmasked_w_thresh = sep.extract( data, 1.5 * bkg.globalrms, maskthresh=1.0, deblend_cont=1.0 ) # Check that changing the mask threshold does not change anything, # if no mask is provided assert_allclose_structured(objects_unmasked, objects_unmasked_w_thresh) objects_masked = sep.extract(data, 1.5 * bkg.globalrms, mask=mask, deblend_cont=1.0) objects_masked_w_hthresh = sep.extract( data, 1.5 * bkg.globalrms, mask=mask, maskthresh=1.0, deblend_cont=1.0 ) objects_masked_w_lthresh = sep.extract( data, 1.5 * bkg.globalrms, mask=mask, maskthresh=0.5, deblend_cont=1.0 ) # Applying a mask should return a different number of objects assert len(objects_unmasked) != len(objects_masked) # As long as the mask is above the threshold, the results should not change assert_allclose_structured(objects_masked, objects_masked_w_lthresh) # Object detection where the maskthresh >= max(mask) should be the same # as if no mask were provided assert_allclose_structured(objects_unmasked, objects_masked_w_hthresh) @pytest.mark.skipif(NO_FITS, reason="no FITS reader") def test_extract_segmentation_map(): """ Test the returned segmentation map. Check that the segmentation map has the same dimensions as the input image, and that the number of object pixels match the catalogue field. """ # Get some background-subtracted test data: data = np.copy(image_data) bkg = sep.Background(data, bw=64, bh=64, fw=3, fh=3) bkg.subfrom(data) objects, segmap = sep.extract(data, 1.5 * bkg.globalrms, segmentation_map=True) assert type(segmap) is np.ndarray assert segmap.shape == data.shape for i in range(len(objects)): assert objects["npix"][i] == (segmap == i + 1).sum() @pytest.mark.skipif(NO_FITS, reason="no FITS reader") def test_extract_seg_map_array(): """ Test the extraction when an existing segmentation map is supplied. Test that the returned catalogue is equal with and without a variable noise array, and that the majority of fields match even when deblending is performed on the original extraction. """ # Get some background-subtracted test data: data = np.copy(image_data) bkg = sep.Background(data, bw=64, bh=64, fw=3, fh=3) bkg.subfrom(data) noise = bkg.globalrms * np.ones_like(data) for err in [None, noise]: # err=None # err=noise objects, segmap = sep.extract(data, 1.5, err, segmentation_map=True) assert type(segmap) is np.ndarray assert segmap.shape == data.shape for i in range(len(objects)): assert objects["npix"][i] == (segmap == i + 1).sum() objects2, segmap2 = sep.extract(data, 1.5, err, segmentation_map=segmap) # Test the values for which we expect an exact match names_exact_match = [ "thresh", "npix", "tnpix", "xmin", "xmax", "ymin", "ymax", "cflux", "flux", "cpeak", "peak", "xcpeak", "ycpeak", "xpeak", "ypeak", ] # The position depends on the object being deblended. As no deblending # is performed when a segmentation map is supplied, all derived # parameters may vary slightly. We test those for which we have a # measurement of the uncertainty names_close = ["x", "y"] names_close_var = ["x2", "y2"] assert segmap2.shape == data.shape for o_i, o_ii in zip(objects, objects2): o_i_exact = o_i[names_exact_match] o_ii_exact = o_ii[names_exact_match] assert_equal(o_i_exact, o_ii_exact) o_i_close = o_i[names_close] o_ii_close = o_ii[names_close] for n, v in zip(names_close, names_close_var): if o_i["flag"] == 0: assert_equal(o_i[n], o_ii[n]) else: assert_allclose(o_i[n], o_ii[n], atol=np.sqrt(o_i[v])) # Perform a second test with deblending disabled. objects3, segmap3 = sep.extract( data, 1.5, err, segmentation_map=True, deblend_cont=1.0 ) objects4, segmap4 = sep.extract( data, 1.5, err, segmentation_map=segmap3, deblend_cont=1.0 ) # The flag will not be the same, as the second extraction does not test # for deblended objects. objects3 = rfn.drop_fields(objects3, "flag") objects4 = rfn.drop_fields(objects4, "flag") assert_allclose_structured(objects3, objects4) # ----------------------------------------------------------------------------- # aperture tests naper = 1000 x = np.random.uniform(200.0, 800.0, naper) y = np.random.uniform(200.0, 800.0, naper) data_shape = (1000, 1000) def test_aperture_dtypes(): """ Test the aperture extraction of multiple data types. Ensure that all supported image dtypes work in sum_circle() and give the same answer. """ r = 3.0 fluxes = [] for dt in SUPPORTED_IMAGE_DTYPES: data = np.ones(data_shape, dtype=dt) flux, fluxerr, flag = sep.sum_circle(data, x, y, r) fluxes.append(flux) for i in range(1, len(fluxes)): assert_allclose(fluxes[0], fluxes[i]) def test_apertures_small_ellipse_exact(): """Regression test for a bug that manifested primarily when x == y.""" data = np.ones(data_shape) r = 0.3 rtol = 1.0e-10 flux, fluxerr, flag = sep.sum_ellipse(data, x, x, r, r, 0.0, subpix=0) assert_allclose(flux, np.pi * r**2, rtol=rtol) def test_apertures_all(): """ Test that aperture subpixel sampling works. """ data = np.random.rand(*data_shape) r = 3.0 rtol = 1.0e-8 for subpix in [0, 1, 5]: flux_ref, fluxerr_ref, flag_ref = sep.sum_circle(data, x, y, r, subpix=subpix) flux, fluxerr, flag = sep.sum_circann(data, x, y, 0.0, r, subpix=subpix) assert_allclose(flux, flux_ref, rtol=rtol) flux, fluxerr, flag = sep.sum_ellipse(data, x, y, r, r, 0.0, subpix=subpix) assert_allclose(flux, flux_ref, rtol=rtol) flux, fluxerr, flag = sep.sum_ellipse( data, x, y, 1.0, 1.0, 0.0, r=r, subpix=subpix ) assert_allclose(flux, flux_ref, rtol=rtol) def test_apertures_exact(): """ Test area as measured by exact aperture modes on array of ones. """ theta = np.random.uniform(-np.pi / 2.0, np.pi / 2.0, naper) ratio = np.random.uniform(0.2, 1.0, naper) r = 3.0 for dt in SUPPORTED_IMAGE_DTYPES: data = np.ones(data_shape, dtype=dt) for r in [0.5, 1.0, 3.0]: flux, fluxerr, flag = sep.sum_circle(data, x, y, r, subpix=0) assert_allclose(flux, np.pi * r**2) rout = r * 1.1 flux, fluxerr, flag = sep.sum_circann(data, x, y, r, rout, subpix=0) assert_allclose(flux, np.pi * (rout**2 - r**2)) flux, fluxerr, flag = sep.sum_ellipse( data, x, y, 1.0, ratio, theta, r=r, subpix=0 ) assert_allclose(flux, np.pi * ratio * r**2) rout = r * 1.1 flux, fluxerr, flag = sep.sum_ellipann( data, x, y, 1.0, ratio, theta, r, rout, subpix=0 ) assert_allclose(flux, np.pi * ratio * (rout**2 - r**2)) def test_aperture_bkgann_overlapping(): """ Test bkgann functionality in circular & elliptical apertures. """ # If bkgann overlaps aperture exactly, result should be zero # (with subpix=1) data = np.random.rand(*data_shape) r = 5.0 f, _, _ = sep.sum_circle(data, x, y, r, bkgann=(0.0, r), subpix=1) assert_allclose(f, 0.0, rtol=0.0, atol=1.0e-13) f, _, _ = sep.sum_ellipse( data, x, y, 2.0, 1.0, np.pi / 4.0, r=r, bkgann=(0.0, r), subpix=1 ) assert_allclose(f, 0.0, rtol=0.0, atol=1.0e-13) def test_aperture_bkgann_ones(): """ Test bkgann functionality with flat data. """ data = np.ones(data_shape) r = 5.0 bkgann = (6.0, 8.0) # On flat data, result should be zero for any bkgann and subpix f, fe, _ = sep.sum_circle(data, x, y, r, bkgann=bkgann, gain=1.0) assert_allclose(f, 0.0, rtol=0.0, atol=1.0e-13) # for all ones data and no error array, error should be close to # sqrt(Npix_aper + Npix_ann * (Npix_aper**2 / Npix_ann**2)) aper_area = np.pi * r**2 bkg_area = np.pi * (bkgann[1] ** 2 - bkgann[0] ** 2) expected_error = np.sqrt(aper_area + bkg_area * (aper_area / bkg_area) ** 2) assert_allclose(fe, expected_error, rtol=0.1) f, _, _ = sep.sum_ellipse(data, x, y, 2.0, 1.0, np.pi / 4.0, r, bkgann=bkgann) assert_allclose(f, 0.0, rtol=0.0, atol=1.0e-13) def test_masked_segmentation_measurements(): """ Test measurements with segmentation masking. """ NX = 100 data = np.zeros((NX * 2, NX * 2)) yp, xp = np.indices(data.shape) #### # Make two 2D gaussians that slightly overlap # width of the 2D objects gsigma = 10.0 # offset between two gaussians in sigmas off = 4 for xy in [[NX, NX], [NX + off * gsigma, NX + off * gsigma]]: R = np.sqrt((xp - xy[0]) ** 2 + (yp - xy[1]) ** 2) g_i = np.exp(-(R**2) / 2 / gsigma**2) data += g_i # Absolute total total_exact = g_i.sum() # Add some noise rms = 0.02 np.random.seed(1) data += np.random.normal(size=data.shape) * rms # Run source detection objs, segmap = sep.extract( data, thresh=1.2, err=rms, mask=None, segmentation_map=True ) seg_id = np.arange(1, len(objs) + 1, dtype=np.int32) # Compute Kron/Auto parameters x, y, a, b = objs["x"], objs["y"], objs["a"], objs["b"] theta = objs["theta"] kronrad, krflag = sep.kron_radius(data, x, y, a, b, theta, 6.0) flux_auto, fluxerr, flag = sep.sum_ellipse( data, x, y, a, b, theta, 2.5 * kronrad, segmap=segmap, seg_id=seg_id, subpix=1 ) # Test total flux assert_allclose(flux_auto, total_exact, rtol=5.0e-2) # Flux_radius for flux_fraction in [0.2, 0.5]: # Exact solution rhalf_exact = np.sqrt(-np.log(1 - flux_fraction) * gsigma**2 * 2) # Masked measurement flux_radius, flag = sep.flux_radius( data, x, y, 6.0 * a, flux_fraction, seg_id=seg_id, segmap=segmap, normflux=flux_auto, subpix=5, ) # Test flux fraction assert_allclose(flux_radius, rhalf_exact, rtol=5.0e-2) if False: print("test_masked_flux_radius") print(total_exact, flux_auto) print(rhalf_exact, flux_radius) def test_mask_ellipse(): """ Test that the correct number of elements are masked with an ellipse. """ arr = np.zeros((20, 20), dtype=np.bool_) # should mask 5 pixels: sep.mask_ellipse(arr, 10.0, 10.0, 1.0, 1.0, 0.0, r=1.001) assert arr.sum() == 5 # should mask 13 pixels: sep.mask_ellipse(arr, 10.0, 10.0, 1.0, 1.0, 0.0, r=2.001) assert arr.sum() == 13 def test_flux_radius(): """ Test that the correct radius is returned for varying flux fractions. """ data = np.ones(data_shape) fluxfrac = [0.2**2, 0.3**2, 0.7**2, 1.0] true_r = [2.0, 3.0, 7.0, 10.0] r, _ = sep.flux_radius( data, x, y, 10.0 * np.ones_like(x), [0.2**2, 0.3**2, 0.7**2, 1.0], subpix=5 ) for i in range(len(fluxfrac)): assert_allclose(r[:, i], true_r[i], rtol=0.01) def test_mask_ellipse_alt(): """ Mask_ellipse with cxx, cyy, cxy parameters. """ arr = np.zeros((20, 20), dtype=np.bool_) # should mask 5 pixels: sep.mask_ellipse(arr, 10.0, 10.0, cxx=1.0, cyy=1.0, cxy=0.0, r=1.001) assert arr.sum() == 5 # should mask 13 pixels: sep.mask_ellipse(arr, 10.0, 10.0, cxx=1.0, cyy=1.0, cxy=0.0, r=2.001) assert arr.sum() == 13 # ----------------------------------------------------------------------------- # General behavior and utilities def test_byte_order_exception(): """ Test that SEP will not run with non-native byte order. Test that error about byte order is raised with non-native byte order input array. This should happen for Background, extract, and aperture functions. """ data = np.ones((100, 100), dtype=np.float64) data = data.view(data.dtype.newbyteorder("S")) with pytest.raises(ValueError) as excinfo: bkg = sep.Background(data) assert "byte order" in excinfo.value.args[0] def test_set_pixstack(): """ Ensure that setting the pixel stack size works. """ old = sep.get_extract_pixstack() new = old * 2 sep.set_extract_pixstack(new) assert new == sep.get_extract_pixstack() sep.set_extract_pixstack(old) def test_set_sub_object_limit(): """ Ensure that setting the sub-object deblending limit works. """ old = sep.get_sub_object_limit() new = old * 2 sep.set_sub_object_limit(new) assert new == sep.get_sub_object_limit() sep.set_sub_object_limit(old) def test_long_error_msg(): """ Test the error handling in SEP. Ensure that the error message is created successfully when there is an error detail. """ # set extract pixstack to an insanely small value; this will trigger # a detailed error message when running sep.extract() old = sep.get_extract_pixstack() sep.set_extract_pixstack(5) data = np.ones((10, 10), dtype=np.float64) with pytest.raises(Exception) as excinfo: sep.extract(data, 0.1) msg = excinfo.value.args[0] assert type(msg) == str # check that message is the native string type assert msg.startswith("internal pixel buffer full: The limit") # restore sep.set_extract_pixstack(old) ================================================ FILE: tox.ini ================================================ [tox] minversion = 4.0 envlist = py-{linux,macos,windows} isolated_build = true [gh-actions:env] PLATFORM = ubuntu-latest: linux macos-latest: macos windows-latest: windows [testenv] passenv = HOME deps = pytest astropy allowlist_externals = make commands = pytest test.py linux: make test macos: make test