pax_global_header00006660000000000000000000000064122331377730014522gustar00rootroot0000000000000052 comment=af16654230a0323ed67ed8931f74fc4d7ff6244c scikit-image-0.9.3/000077500000000000000000000000001223313777300141015ustar00rootroot00000000000000scikit-image-0.9.3/.gitignore000066400000000000000000000005501223313777300160710ustar00rootroot00000000000000*.pyc *~ *# *egg-info *.so *.bak *.c *.new *.md5 *.old doc/source/api doc/build source/api build dist skimage/version.py *.swp .coverage doc/source/auto_examples/*.py doc/source/auto_examples/*.txt doc/source/auto_examples/images/plot_*.png doc/source/auto_examples/images/thumb doc/source/auto_examples/applications/ doc/source/_static/random.js .idea/ *.log scikit-image-0.9.3/.gitmodules000066400000000000000000000001541223313777300162560ustar00rootroot00000000000000[submodule "doc/tools/gitwash"] path = doc/tools/gitwash url = git://github.com/matthew-brett/gitwash.git scikit-image-0.9.3/.travis.yml000066400000000000000000000034701223313777300162160ustar00rootroot00000000000000# vim ft=yaml # travis-ci.org definition for skimage build # # We pretend to be erlang because we can't use the python support in # travis-ci; it uses virtualenvs, they do not have numpy, scipy, matplotlib, # and it is impractical to build them language: erlang env: - PYTHON=python PYSUF='' PYVER=2.7 - PYTHON=python3 PYSUF='3' PYVER=3.2 install: - sudo apt-get update # needed for python3-numpy - sudo apt-get install $PYTHON-dev - sudo apt-get install $PYTHON-numpy - sudo apt-get install $PYTHON-scipy - sudo apt-get install $PYTHON-setuptools - sudo apt-get install $PYTHON-nose - sudo easy_install$PYSUF pip - sudo pip-$PYVER install cython - sudo apt-get install libfreeimage3 - if [[ $PYVER == '2.7' ]]; then sudo apt-get install $PYTHON-matplotlib; fi - if [[ $PYVER == '3.2' ]]; then sudo pip-$PYVER install git+git://github.com/matplotlib/matplotlib.git@v1.2.x; fi - sudo pip-$PYVER install flake8 - $PYTHON setup.py build - sudo $PYTHON setup.py install script: # Check if setup.py's match bento.info - $PYTHON check_bento_build.py # Change into an innocuous directory and find tests from installation - mkdir $HOME/.matplotlib - "echo 'backend : Agg' > $HOME/.matplotlib/matplotlibrc" - "echo 'backend.qt4 : PyQt4' >> $HOME/.matplotlib/matplotlibrc" - mkdir for_test - cd for_test - nosetests-$PYVER --exe -v --cover-package=skimage skimage # Change back to repository root directory and run all doc examples - cd .. - for f in doc/examples/*.py; do $PYTHON "$f"; if [ $? -ne 0 ]; then exit 1; fi done - for f in doc/examples/applications/*.py; do $PYTHON "$f"; if [ $? -ne 0 ]; then exit 1; fi done # Run pep8 and flake tests - flake8 --exit-zero --exclude=test_*,six.py skimage doc/examples viewer_examples scikit-image-0.9.3/CONTRIBUTING.txt000066400000000000000000000134501223313777300165540ustar00rootroot00000000000000Development process ------------------- Here's the long and short of it: 1. If you are a first-time contributor: * Go to `https://github.com/scikit-image/scikit-image `_ and click the "fork" button to create your own copy of the project. * Clone the project to your local computer:: git clone git@github.com:your-username/scikit-image.git * Add upstream repository:: git remote add upstream git@github.com:scikit-image/scikit-image.git * Now, you have remote repositories named: - ``upstream``, which refers to the ``scikit-image`` repository - ``origin``, which refers to your personal fork 2. Develop your contribution: * Pull the latest changes from upstream:: git checkout master git pull upstream master * Create a branch for the feature you want to work on. Since the branch name will appear in the merge message, use a sensible name such as 'transform-speedups':: git checkout -b transform-speedups * Commit locally as you progress (``git add`` and ``git commit``) 3. To submit your contribution: * Push your changes back to your fork on GitHub:: git push origin transform-speedups * Go to GitHub. The new branch will show up with a Pull Request button - click it. * If you want, post on the `mailing list `_ to explain your changes or to ask for review. For a more detailed discussion, read these :doc:`detailed documents ` on how to use Git with ``scikit-image`` (``_). .. note:: To reviewers: add a short explanation of what a branch did to the merge message and, if closing a bug, also add "Closes gh-123" where 123 is the bug number. Divergence between ``upstream master`` and your feature branch .............................................................. Do *not* ever merge the main branch into yours. If GitHub indicates that the branch of your Pull Request can no longer be merged automatically, rebase onto master:: git checkout master git pull upstream master git checkout transform-speedups git rebase master If any conflicts occur, fix the according files and continue:: git add conflict-file1 conflict-file2 git rebase --continue However, you should only rebase your own branches and must generally not rebase any branch which you collaborate on with someone else. Finally, you must push your rebased branch:: git push --force origin transform-speedups (If you are curious, here's a further discussion on the `dangers of rebasing `__. Also see this `LWN article `__.) Guidelines ---------- * All code should have tests (see `test coverage`_ below for more details). * All code should be documented, to the same `standard `_ as NumPy and SciPy. * For new functionality, always add an example to the gallery. * No changes should be committed without review. Ask on the `mailing list `_ if you get no response to your pull request. **Never merge your own pull request.** * Examples in the gallery should have a maximum figure width of 8 inches. Stylistic Guidelines -------------------- * Set up your editor to remove trailing whitespace. Follow `PEP08 `__. Check code with pyflakes / flake8. * Use numpy data types instead of strings (``np.uint8`` instead of ``"uint8"``). * Use the following import conventions:: import numpy as np import matplotlib.pyplot as plt cimport numpy as cnp # in Cython code * When documenting array parameters, use ``image : (M, N) ndarray`` and then refer to ``M`` and ``N`` in the docstring, if necessary. * Functions should support all input image dtypes. Use utility functions such as ``img_as_float`` to help convert to an appropriate type. The output format can be whatever is most efficient. This allows us to string together several functions into a pipeline, e.g.:: hough(canny(my_image)) * Use ``Py_ssize_t`` as data type for all indexing, shape and size variables in C/C++ and Cython code. Test coverage ------------- Tests for a module should ideally cover all code in that module, i.e., statement coverage should be at 100%. To measure the test coverage, install `coverage.py `__ (using ``easy_install coverage``) and then run:: $ make coverage This will print a report with one line for each file in `skimage`, detailing the test coverage:: Name Stmts Exec Cover Missing ------------------------------------------------------------------------------ skimage/color/colorconv 77 77 100% skimage/filter/__init__ 1 1 100% ... Activate Travis-CI for your fork (optional) ------------------------------------------- Travis-CI checks all unittests in the project to prevent breakage. Before sending a pull request, you may want to check that Travis-CI successfully passes all tests. To do so, * Go to `Travis-CI `__ and follow the Sign In link at the top * Go to your `profile page `__ and switch on your scikit-image fork It corresponds to steps one and two in `Travis-CI documentation `__ (Step three is already done in scikit-image). Thus, as soon as you push your code to your fork, it will trigger Travis-CI, and you will receive an email notification when the process is done. Bugs ---- Please `report bugs on GitHub `_. scikit-image-0.9.3/CONTRIBUTORS.txt000066400000000000000000000101161223313777300165760ustar00rootroot00000000000000- Stefan van der Walt Project coordination - Nicolas Pinto Colour spaces and filters, and image resizing. Shape views: ``util.shape.view_as_windows`` and ``util.shape.view_as_blocks`` Montage helpers: ``util.montage``. - Damian Eads Morphological operators - Mahipal Raythattha Documentation infrastructure - S. Chris Colbert OpenCV wrappers, Scivi, Qt and Gtk gui bits, fast Hough transform, and much more. - Holger Rapp OpenCV functions and better OSX library loader - Ralf Gommers Image IO, color spaces, plots in documentation, cleaner API docs - Helge Reikeras Logic around API docs generation - Tony Yu Reading of paletted images; build, bug and doc fixes. Code to generate skimage logo. Otsu thresholding, histogram equalisation, template matching, and more. - Zachary Pincus Tracing of low cost paths, FreeImage I/O plugin, iso-contours, and more. - Almar Klein Binary heap class for graph algorithms - Lee Kamentsky and Thouis Jones of the CellProfiler team, Broad Institute, MIT Constant time per pixel median filter, edge detectors, and more. - Dan Farmer Incorporating CellProfiler's Canny edge detector, ctypes loader with Windows support. - Pieter Holtzhausen Incorporating CellProfiler's Sobel edge detector, build and bug fixes. Radon transform, template matching. - Emmanuelle Gouillart Total variation noise filtering, integration of CellProfiler's mathematical morphology tools, random walker segmentation, tutorials, and more. - Maël Primet Total variation noise filtering - Martin Bergholdt Fix missing math.h functions in Windows 7 + MSVCC. - Neil Muller Numerous fixes, including those for Python 3 compatibility, QT image reading. - The IPython team From whom we borrowed the github+web tools / style. - Kyle Mandli CSV to ReST code for feature comparison table. - The Scikit Learn team From whom we borrowed the example generation tools. - Andreas Mueller Example data set loader. Nosetest compatibility functions. Quickshift image segmentation, Felzenszwalbs fast graph based segmentation. - Yaroslav Halchenko For sharing his expert advice on Debian packaging. - Brian Holt Histograms of Oriented Gradients - David-Warde Farley, Sturla Molden Bresenheim line drawing, from snippets on numpy-discussion. - Christoph Gohlke Windows packaging and Python 3 compatibility. - Neil Yager Skeletonization and grey level co-occurrence matrices. - Nelle Varoquaux Renaming of the package to ``skimage``. Harris corner detector - W. Randolph Franklin Point in polygon test. - Gaël Varoquaux Harris corner detector - Nicolas Poilvert Shape views: ``util.shape.view_as_windows`` and ``util.shape.view_as_blocks`` Image resizing. - Johannes Schönberger Drawing functions, adaptive thresholding, regionprops, geometric transformations, LBPs, polygon approximations, web layout, and more. - Pavel Campr Fixes and tests for Histograms of Oriented Gradients. - Joshua Warner Multichannel random walker segmentation, unified peak finder backend, n-dimensional array padding, marching cubes, bug and doc fixes. - Petter Strandmark Perimeter calculation in regionprops. - Olivier Debeir Rank filters (8- and 16-bits) using sliding window. - Luis Pedro Coelho imread plugin - Steven Silvester, Karel Zuiderveld Adaptive Histogram Equalization - Anders Boesen Lindbo Larsen Dense DAISY feature description, circle perimeter drawing. - François Boulogne Drawing: Andres Method for circle perimeter, ellipse perimeter drawing, Bezier curve, anti-aliasing. Circular and elliptical Hough Transforms Various fixes - Thouis Jones Vectorized operators for arrays of 16-bit ints. - Xavier Moles Lopez Color separation (color deconvolution) for several stainings. - Jostein Bø Fløystad Reconstruction circle mode for Radon transform Simultaneous Algebraic Reconstruction Technique for inverse Radon transform - Matt Terry Color difference functions - Eugene Dvoretsky Yen threshold implementation. - Riaan van den Dool skimage.io plugin: GDAL - Fedor Morozov Drawing: Wu's anti-aliased circle scikit-image-0.9.3/DEPENDS.txt000066400000000000000000000033471223313777300157330ustar00rootroot00000000000000Build Requirements ------------------ * `Python >= 2.5 `__ * `Numpy >= 1.6 `__ * `Cython >= 0.17 `__ `Matplotlib >= 1.0 `__ is needed to generate the examples in the documentation. You can use pip to automatically install the base dependencies as follows:: $ pip install -r requirements.txt Runtime requirements -------------------- * `SciPy >= 0.10 `__ Known build errors ------------------ On Windows, the error ``Error:unable to find vcvarsall.bat`` means that distutils is not correctly configured to use the C compiler. Modify (or create, if not existing) the configuration file ``distutils.cfg`` (located for example at ``C:\Python26\Lib\distutils\distutils.cfg``) to contain:: [build] compiler=mingw32 Usage Requirements ------------------ * `Scipy `__ Optional Requirements --------------------- You can use this scikit with the basic requirements listed above, but some functionality is only available with the following installed: * `PyQt4 `__ The ``qt`` plugin that provides ``imshow(x, fancy=True)`` and `skivi`. * `FreeImage `__ The ``freeimage`` plugin provides support for reading various types of image file formats, including multi-page TIFFs. * `PyAMG `__ The ``pyamg`` module is used for the fast `cg_mg` mode of random walker segmentation. Testing requirements -------------------- * `Nose `__ A Python Unit Testing Framework * `Coverage.py `__ A tool that generates a unit test code coverage report scikit-image-0.9.3/LICENSE.txt000066400000000000000000000030041223313777300157210ustar00rootroot00000000000000Unless otherwise specified by LICENSE.txt files in individual directories, all code is Copyright (C) 2011, the scikit-image team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of skimage 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. scikit-image-0.9.3/MANIFEST.in000066400000000000000000000006211223313777300156360ustar00rootroot00000000000000include setup.cfg include setup*.py include MANIFEST.in include *.txt include Makefile recursive-include skimage *.pyx *.pxd *.pxi *.py *.c *.h *.ini *.md5 *.rst *.txt recursive-include skimage/data * include doc/Makefile recursive-include doc/source *.txt recursive-include doc/tools *.txt recursive-include doc/source/_templates *.html recursive-include doc *.py prune doc/build prune doc/gh-pages scikit-image-0.9.3/Makefile000066400000000000000000000003631223313777300155430ustar00rootroot00000000000000.PHONY: all clean test all: python setup.py build_ext --inplace clean: find . -name "*.so" -o -name "*.pyc" -o -name "*.pyx.md5" | xargs rm -f test: nosetests skimage coverage: nosetests skimage --with-coverage --cover-package=skimage scikit-image-0.9.3/README.md000066400000000000000000000012141223313777300153560ustar00rootroot00000000000000Image Processing SciKit ======================= Source ------ https://github.com/scikit-image/scikit-image Mailing List ------------ http://groups.google.com/group/scikit-image Installation from source ------------------------ Refer to DEPENDS.txt for a list of dependencies. The SciKit may be installed globally using $ python setup.py install or locally using $ python setup.py install --prefix=${HOME} If you prefer, you can use it without installing, by simply adding this path to your PYTHONPATH variable and compiling the extensions: $ python setup.py build_ext -i License ------- Please read LICENSE.txt in this directory. scikit-image-0.9.3/RELEASE.txt000066400000000000000000000056611223313777300157320ustar00rootroot00000000000000How to make a new release of ``skimage`` ======================================== - Check ``TODO.txt`` for any outstanding tasks. - Update release notes. - To show a list of contributors and changes, run ``doc/release/contribs.py ``. - Update the version number in ``setup.py`` and ``bento.info`` and commit - Update the docs: - Edit ``doc/source/_static/docversions.js`` and commit - Build a clean version of the docs. Run ``make`` in the root dir, then ``rm -rf build; make html`` in the docs. - Run ``make html`` again to copy the newly generated ``random.js`` into place. Double check ``random.js``, otherwise the skimage.org front page gets broken! - Build using ``make gh-pages``. - Push upstream: ``git push origin gh-pages`` in ``doc/gh-pages``. - Add the version number as a tag in git:: git tag v0.X.0 - Push the new meta-data to github:: git push --tags origin master - Publish on PyPi:: python setup.py register python setup.py sdist upload - Increase the version number - In ``setup.py``, set to ``0.Xdev``. - In ``bento.info``, set to ``0.X.dev0``. - Update the web frontpage: The webpage is kept in a separate repo: scikit-image-web - Sync your branch with the remote repo: ``git pull``. If you try to ``make gh-pages`` when your branch is out of sync, it creates headaches. - Update stable and development version numbers in ``_templates/sidebar_versions.html``. - Add release date to ``index.rst`` under "Announcements". - Add previous stable version documentation path to disallowed paths in `robots.txt` - Build using ``make gh-pages``. - Push upstream: ``git push`` in ``gh-pages``. - Update the development docs for the new version ``0.Xdev`` just like above - Post release notes on mailing lists, blog, G+, etc. - scikit-image@googlegroups.com - scipy-user@scipy.org - scikit-learn-general@lists.sourceforge.net - pythonvision@googlegroups.com Debian ------ - Tag the release as per instructions above. - git checkout debian - git merge v0.x.x - uscan <- not sure if this step is necessary - Update changelog (emacs has a good mode, requires package dpkg-dev-el) - C-C C-v add new version, C-c C-c timestamp / save - git commit -m 'Changelog entry for 0.x.x' - git-buildpackage -uc -us -rfakeroot - Sign the changes: debsign skimage_0.x.x-x_amd64.changes - cd ../build-area && dput mentors skimage_0.x.x-x_amd64.changes - The package should now be available at: http://mentors.debian.net/package/skimage For the last lines above to work, you need ``~/.gbp.conf``:: [DEFAULT] upstream-tag = %(version)s [git-buildpackage] sign-tags = True export-dir = ../build-area/ tarball-dir = ../tarballs/ As well as ``~/dput.cf``:: [mentors] fqdn = mentors.debian.net incoming = /upload method = http allow_unsigned_uploads = 0 progress_indicator = 2 # Allow uploads for UNRELEASED packages allowed_distributions = .* scikit-image-0.9.3/TASKS.txt000066400000000000000000000016741223313777300155370ustar00rootroot00000000000000 .. role:: strike .. _howto_contribute: How to contribute to ``skimage`` ====================================== .. toctree:: :hidden: gitwash/index gsoc2011 coverage_table cell_profiler Developing Open Source is great fun! Join us on the `scikit-image mailing list `_ and tell us which of the following challenges you'd like to solve. * Mentoring is available for those new to scientific programming in Python. * If you're looking for something to implement, you can find a list of `requested features on GitHub `__. In addition, you can browse the `open issues on GitHub `__. * The technical detail of the `development process`_ is summed up below. Refer to the :doc:`gitwash ` for a step-by-step tutorial. .. contents:: :local: scikit-image-0.9.3/TODO.txt000066400000000000000000000014151223313777300154100ustar00rootroot00000000000000Version 0.10 ------------ * Remove deprecated functions in `skimage.filter.rank.*` * Remove deprecated parameter `epsilon` of `skimage.viewer.LineProfile` * Remove backwards-compatability of `skimage.measure.regionprops` * Remove {`ratio`, `sigma`} deprecation warnings of `skimage.segmentation.slic` * Change default mode of random_walker segmentation to 'cg_mg' > 'cg' > 'bf', depending on which optional dependencies are available. * Remove deprecated `out` parameter of `skimage.morphology.binary_*` * Remove deprecated parameter `depth` in `skimage.segmentation.random_walker` * Remove deprecated logger function in `skimage/__init__.py` * Remove deprecated function `filter.median_filter` * Remove deprecated `skimage.color.is_gray` and `skimage.color.is_rgb` functions scikit-image-0.9.3/bento.info000066400000000000000000000120671223313777300160730ustar00rootroot00000000000000Name: scikit-image Version: 0.9.3 Summary: Image processing routines for SciPy Url: http://scikit-image.org DownloadUrl: http://github.com/scikit-image/scikit-image Description: Image Processing SciKit Image processing algorithms for SciPy, including IO, morphology, filtering, warping, color manipulation, object detection, etc. Please refer to the online documentation at http://scikit-image.org/ Maintainer: Stefan van der Walt MaintainerEmail: stefan@sun.ac.za License: Modified BSD Classifiers: Development Status :: 4 - Beta, Environment :: Console, Intended Audience :: Developers, Intended Audience :: Science/Research, License :: OSI Approved :: BSD License, Programming Language :: C, Programming Language :: Python, Programming Language :: Python :: 3, Topic :: Scientific/Engineering, Operating System :: Microsoft :: Windows, Operating System :: POSIX, Operating System :: Unix, Operating System :: MacOS UseBackends: Waf Library: Packages: skimage, skimage.color, skimage.data, skimage.draw, skimage.exposure, skimage.feature, skimage.filter, skimage.graph, skimage.io, skimage.io._plugins, skimage.measure, skimage.morphology, skimage.scripts, skimage.segmentation, skimage.transform, skimage.util Extension: skimage.morphology._pnpoly Sources: skimage/morphology/_pnpoly.pyx Extension: skimage.feature._template Sources: skimage/feature/_template.pyx Extension: skimage.io._plugins._colormixer Sources: skimage/io/_plugins/_colormixer.pyx Extension: skimage.measure._find_contours Sources: skimage/measure/_find_contours.pyx Extension: skimage.measure._moments Sources: skimage/measure/_moments.pyx Extension: skimage.measure._marching_cubes_cy Sources: skimage/measure/_marching_cubes_cy.pyx Extension: skimage.graph._mcp Sources: skimage/graph/_mcp.pyx Extension: skimage.io._plugins._histograms Sources: skimage/io/_plugins/_histograms.pyx Extension: skimage.transform._hough_transform Sources: skimage/transform/_hough_transform.pyx Extension: skimage.filter._ctmf Sources: skimage/filter/_ctmf.pyx Extension: skimage.filter._denoise_cy Sources: skimage/filter/_denoise_cy.pyx Extension: skimage.morphology.ccomp Sources: skimage/morphology/ccomp.pyx Extension: skimage.morphology._watershed Sources: skimage/morphology/_watershed.pyx Extension: skimage.morphology._convex_hull Sources: skimage/morphology/_convex_hull.pyx Extension: skimage.draw._draw Sources: skimage/draw/_draw.pyx Extension: skimage.graph._spath Sources: skimage/graph/_spath.pyx Extension: skimage.morphology.cmorph Sources: skimage/morphology/cmorph.pyx Extension: skimage.graph.heap Sources: skimage/graph/heap.pyx Extension: skimage.morphology._greyreconstruct Sources: skimage/morphology/_greyreconstruct.pyx Extension: skimage.feature.censure_cy Sources: skimage/feature/censure_cy.pyx Extension: skimage.feature._brief_cy Sources: skimage/feature/_brief_cy.pyx Extension: skimage.feature.corner_cy Sources: skimage/feature/corner_cy.pyx Extension: skimage.feature._texture Sources: skimage/feature/_texture.pyx Extension: skimage._shared.transform Sources: skimage/_shared/transform.pyx Extension: skimage.segmentation._slic Sources: skimage/segmentation/_slic.pyx Extension: skimage.segmentation._quickshift Sources: skimage/segmentation/_quickshift.pyx Extension: skimage.morphology._skeletonize_cy Sources: skimage/morphology/_skeletonize_cy.pyx Extension: skimage.transform._radon_transform Sources: skimage/transform/_radon_transform.pyx Extension: skimage.transform._warps_cy Sources: skimage/transform/_warps_cy.pyx Extension: skimage._shared.interpolation Sources: skimage/_shared/interpolation.pyx Extension: skimage.segmentation._felzenszwalb_cy Sources: skimage/segmentation/_felzenszwalb_cy.pyx Extension: skimage._shared.geometry Sources: skimage/_shared/geometry.pyx Extension: skimage.filter.rank.generic_cy Sources: skimage/filter/rank/generic_cy.pyx Extension: skimage.filter.rank.percentile_cy Sources: skimage/filter/rank/percentile_cy.pyx Extension: skimage.filter.rank.core_cy Sources: skimage/filter/rank/core_cy.pyx Extension: skimage.filter.rank.bilateral_cy Sources: skimage/filter/rank/bilateral_cy.pyx Executable: skivi Module: skimage.scripts.skivi Function: main scikit-image-0.9.3/check_bento_build.py000066400000000000000000000062461223313777300201060ustar00rootroot00000000000000""" Check that Cython extensions in setup.py files match those in bento.info. """ import os import re import sys RE_CYTHON = re.compile("config.add_extension\(\s*['\"]([\S]+)['\"]") BENTO_TEMPLATE = """ Extension: {module_path} Sources: {dir_path}.pyx""" def each_setup_in_pkg(top_dir): """Yield path and file object for each setup.py file""" for dir_path, dir_names, filenames in os.walk(top_dir): for fname in filenames: if fname == 'setup.py': with open(os.path.join(dir_path, 'setup.py')) as f: yield dir_path, f def each_cy_in_setup(top_dir): """Yield path for each cython extension package's setup file.""" for dir_path, f in each_setup_in_pkg(top_dir): text = f.read() match = RE_CYTHON.findall(text) if match: for cy_file in match: # if cython files in different directory than setup.py if '.' in cy_file: parts = cy_file.split('.') cy_file = parts[-1] # Don't overwrite dir_path for subsequent iterations. path = os.path.join(dir_path, *parts[:-1]) else: path = dir_path full_path = os.path.join(path, cy_file) yield full_path def each_cy_in_bento(bento_file='bento.info'): """Yield path for each cython extension in bento info file.""" with open(bento_file) as f: for line in f: line = line.strip() if line.startswith('Extension:'): path = line.lstrip('Extension:').strip() yield path def remove_common_extensions(cy_bento, cy_setup): # normalize so that cy_setup and cy_bento have the same separator cy_setup = set(ext.replace('/', '.') for ext in cy_setup) cy_setup_diff = cy_setup.difference(cy_bento) cy_setup_diff = set(ext.replace('.', '/') for ext in cy_setup_diff) cy_bento_diff = cy_bento.difference(cy_setup) return cy_bento_diff, cy_setup_diff def print_results(cy_bento, cy_setup): def info(text): print('') print(text) print('-' * len(text)) if not (cy_bento or cy_setup): print("bento.info and setup.py files match.") if cy_bento: info("Extensions found in 'bento.info' but not in any 'setup.py:") print('\n'.join(cy_bento)) if cy_setup: info("Extensions found in a 'setup.py' but not in any 'bento.info:") print('\n'.join(cy_setup)) info("Consider adding the following to the 'bento.info' Library:") for dir_path in cy_setup: module_path = dir_path.replace('/', '.') print(BENTO_TEMPLATE.format(module_path=module_path, dir_path=dir_path)) if __name__ == '__main__': # All cython extensions defined in 'setup.py' files. cy_setup = set(each_cy_in_setup('skimage')) # All cython extensions defined 'bento.info' file. cy_bento = set(each_cy_in_bento()) cy_bento, cy_setup = remove_common_extensions(cy_bento, cy_setup) print_results(cy_bento, cy_setup) if cy_setup or cy_bento: sys.exit(1) scikit-image-0.9.3/doc/000077500000000000000000000000001223313777300146465ustar00rootroot00000000000000scikit-image-0.9.3/doc/.gitignore000066400000000000000000000000441223313777300166340ustar00rootroot00000000000000gh-pages source/coverage_table.txt scikit-image-0.9.3/doc/Makefile000066400000000000000000000105031223313777300163050ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. PYTHON ?= python SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build PAPER ?= # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source DEST = build .PHONY: all help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest gitwash gh-pages coveragetable random_gallery all: html 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 " 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 " 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 " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(DEST)/* -rm -rf source/api -find ./source/auto_examples/* -type f | grep -v blank | xargs rm -f api: @mkdir -p source/api $(PYTHON) tools/build_modref_templates.py @echo "Build API docs...done." random_gallery: @cd source && $(PYTHON) random_gallery.py coveragetable: @cd source && $(PYTHON) coverage_generator.py html: api coveragetable random_gallery $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(DEST)/html cp -r source/plots $(DEST)/html @echo @echo "Build finished. The HTML pages are in build/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(DEST)/dirhtml @echo @echo "Build finished. The HTML pages are in build/dirhtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(DEST)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(DEST)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(DEST)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in build/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(DEST)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in build/qthelp, like this:" @echo "# qcollectiongenerator build/qthelp/scikitimage.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile build/qthelp/scikitimage.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(DEST)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/scikitimage" @echo "# ln -s build/devhelp $$HOME/.local/share/devhelp/scikitimage" @echo "# devhelp" latex: api $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(DEST)/latex @echo @echo "Build finished; the LaTeX files are in $(DEST)/latex." @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ "run these through (pdf)latex." latexpdf: latex $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(DEST)/latex @echo "Running LaTeX files through pdflatex..." make -C build/latex all-pdf @echo "pdflatex finished; the PDF files are in build/latex." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(DEST)/changes @echo @echo "The overview file is in build/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(DEST)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in build/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(DEST)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in build/doctest/output.txt." gh-pages: $(PYTHON) gh-pages.py gitwash: $(PYTHON) tools/gitwash/gitwash_dumper.py source scikit-image \ --project-url=http://scikit-image.org \ --project-ml-url=http://groups.google.com/group/scikit-image \ --repo-name=scikit-image \ --github-user=scikit-image \ --source-suffix=.txt scikit-image-0.9.3/doc/__init__.py000066400000000000000000000000001223313777300167450ustar00rootroot00000000000000scikit-image-0.9.3/doc/examples/000077500000000000000000000000001223313777300164645ustar00rootroot00000000000000scikit-image-0.9.3/doc/examples/README.txt000066400000000000000000000001701223313777300201600ustar00rootroot00000000000000.. _examples_gallery: General examples ------------------- General-purpose and introductory examples for the scikit. scikit-image-0.9.3/doc/examples/applications/000077500000000000000000000000001223313777300211525ustar00rootroot00000000000000scikit-image-0.9.3/doc/examples/applications/README.txt000066400000000000000000000001061223313777300226450ustar00rootroot00000000000000Longer examples and demonstrations ---------------------------------- scikit-image-0.9.3/doc/examples/applications/plot_coins_segmentation.py000066400000000000000000000110601223313777300264500ustar00rootroot00000000000000""" =============================================================== Comparing edge-based segmentation and region-based segmentation =============================================================== In this example, we will see how to segment objects from a background. We use the ``coins`` image from ``skimage.data``, which shows several coins outlined against a darker background. """ import numpy as np import matplotlib.pyplot as plt from skimage import data coins = data.coins() hist = np.histogram(coins, bins=np.arange(0, 256)) plt.figure(figsize=(8, 3)) plt.subplot(121) plt.imshow(coins, cmap=plt.cm.gray, interpolation='nearest') plt.axis('off') plt.subplot(122) plt.plot(hist[1][:-1], hist[0], lw=2) plt.title('histogram of grey values') """ .. image:: PLOT2RST.current_figure Thresholding ============ A simple way to segment the coins is to choose a threshold based on the histogram of grey values. Unfortunately, thresholding this image gives a binary image that either misses significant parts of the coins or merges parts of the background with the coins: """ plt.figure(figsize=(6, 3)) plt.subplot(121) plt.imshow(coins > 100, cmap=plt.cm.gray, interpolation='nearest') plt.title('coins > 100') plt.axis('off') plt.subplot(122) plt.imshow(coins > 150, cmap=plt.cm.gray, interpolation='nearest') plt.title('coins > 150') plt.axis('off') margins = dict(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1) plt.subplots_adjust(**margins) """ .. image:: PLOT2RST.current_figure Edge-based segmentation ======================= Next, we try to delineate the contours of the coins using edge-based segmentation. To do this, we first get the edges of features using the Canny edge-detector. """ from skimage.filter import canny edges = canny(coins/255.) plt.figure(figsize=(4, 3)) plt.imshow(edges, cmap=plt.cm.gray, interpolation='nearest') plt.axis('off') plt.title('Canny detector') """ .. image:: PLOT2RST.current_figure These contours are then filled using mathematical morphology. """ from scipy import ndimage fill_coins = ndimage.binary_fill_holes(edges) plt.figure(figsize=(4, 3)) plt.imshow(fill_coins, cmap=plt.cm.gray, interpolation='nearest') plt.axis('off') plt.title('Filling the holes') """ .. image:: PLOT2RST.current_figure Small spurious objects are easily removed by setting a minimum size for valid objects. """ from skimage import morphology coins_cleaned = morphology.remove_small_objects(fill_coins, 21) plt.figure(figsize=(4, 3)) plt.imshow(coins_cleaned, cmap=plt.cm.gray, interpolation='nearest') plt.axis('off') plt.title('Removing small objects') """ .. image:: PLOT2RST.current_figure However, this method is not very robust, since contours that are not perfectly closed are not filled correctly, as is the case for one unfilled coin above. Region-based segmentation ========================= We therefore try a region-based method using the watershed transform. First, we find an elevation map using the Sobel gradient of the image. """ from skimage.filter import sobel elevation_map = sobel(coins) plt.figure(figsize=(4, 3)) plt.imshow(elevation_map, cmap=plt.cm.jet, interpolation='nearest') plt.axis('off') plt.title('elevation_map') """ .. image:: PLOT2RST.current_figure Next we find markers of the background and the coins based on the extreme parts of the histogram of grey values. """ markers = np.zeros_like(coins) markers[coins < 30] = 1 markers[coins > 150] = 2 plt.figure(figsize=(4, 3)) plt.imshow(markers, cmap=plt.cm.spectral, interpolation='nearest') plt.axis('off') plt.title('markers') """ .. image:: PLOT2RST.current_figure Finally, we use the watershed transform to fill regions of the elevation map starting from the markers determined above: """ segmentation = morphology.watershed(elevation_map, markers) plt.figure(figsize=(4, 3)) plt.imshow(segmentation, cmap=plt.cm.gray, interpolation='nearest') plt.axis('off') plt.title('segmentation') """ .. image:: PLOT2RST.current_figure This last method works even better, and the coins can be segmented and labeled individually. """ from skimage.color import label2rgb segmentation = ndimage.binary_fill_holes(segmentation - 1) labeled_coins, _ = ndimage.label(segmentation) image_label_overlay = label2rgb(labeled_coins, image=coins) plt.figure(figsize=(6, 3)) plt.subplot(121) plt.imshow(coins, cmap=plt.cm.gray, interpolation='nearest') plt.contour(segmentation, [0.5], linewidths=1.2, colors='y') plt.axis('off') plt.subplot(122) plt.imshow(image_label_overlay, interpolation='nearest') plt.axis('off') plt.subplots_adjust(**margins) """ .. image:: PLOT2RST.current_figure """ plt.show() scikit-image-0.9.3/doc/examples/applications/plot_geometric.py000066400000000000000000000062671223313777300245530ustar00rootroot00000000000000""" =============================== Using geometric transformations =============================== In this example, we will see how to use geometric transformations in the context of image processing. """ from __future__ import print_function import math import numpy as np import matplotlib.pyplot as plt from skimage import data from skimage import transform as tf margins = dict(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1) """ Basics ====== Several different geometric transformation types are supported: similarity, affine, projective and polynomial. Geometric transformations can either be created using the explicit parameters (e.g. scale, shear, rotation and translation) or the transformation matrix: First we create a transformation using explicit parameters: """ tform = tf.SimilarityTransform(scale=1, rotation=math.pi / 2, translation=(0, 1)) print(tform._matrix) """ Alternatively you can define a transformation by the transformation matrix itself: """ matrix = tform._matrix.copy() matrix[1, 2] = 2 tform2 = tf.SimilarityTransform(matrix) """ These transformation objects can then be used to apply forward and inverse coordinate transformations between the source and destination coordinate systems: """ coord = [1, 0] print(tform2(coord)) print(tform2.inverse(tform(coord))) """ Image warping ============= Geometric transformations can also be used to warp images: """ text = data.text() tform = tf.SimilarityTransform(scale=1, rotation=math.pi / 4, translation=(text.shape[0] / 2, -100)) rotated = tf.warp(text, tform) back_rotated = tf.warp(rotated, tform.inverse) fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(8, 3)) fig.subplots_adjust(**margins) plt.gray() ax1.imshow(text) ax1.axis('off') ax2.imshow(rotated) ax2.axis('off') ax3.imshow(back_rotated) ax3.axis('off') """ .. image:: PLOT2RST.current_figure Parameter estimation ==================== In addition to the basic functionality mentioned above you can also estimate the parameters of a geometric transformation using the least-squares method. This can amongst other things be used for image registration or rectification, where you have a set of control points or homologous/corresponding points in two images. Let's assume we want to recognize letters on a photograph which was not taken from the front but at a certain angle. In the simplest case of a plane paper surface the letters are projectively distorted. Simple matching algorithms would not be able to match such symbols. One solution to this problem would be to warp the image so that the distortion is removed and then apply a matching algorithm: """ text = data.text() src = np.array(( (0, 0), (0, 50), (300, 50), (300, 0) )) dst = np.array(( (155, 15), (65, 40), (260, 130), (360, 95) )) tform3 = tf.ProjectiveTransform() tform3.estimate(src, dst) warped = tf.warp(text, tform3, output_shape=(50, 300)) fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(8, 3)) fig.subplots_adjust(**margins) plt.gray() ax1.imshow(text) ax1.plot(dst[:, 0], dst[:, 1], '.r') ax1.axis('off') ax2.imshow(warped) ax2.axis('off') """ .. image:: PLOT2RST.current_figure """ plt.show() scikit-image-0.9.3/doc/examples/applications/plot_morphology.py000066400000000000000000000177421223313777300247740ustar00rootroot00000000000000""" ======================= Morphological Filtering ======================= Morphological image processing is a collection of non-linear operations related to the shape or morphology of features in an image, such as boundaries, skeletons, etc. In any given technique, we probe an image with a small shape or template called a structuring element, which defines the region of interest or neighborhood around a pixel. In this document we outline the following basic morphological operations: 1. Erosion 2. Dilation 3. Opening 4. Closing 5. White Tophat 6. Black Tophat 7. Skeletonize 8. Convex Hull To get started, let's load an image using ``io.imread``. Note that morphology functions only work on gray-scale or binary images, so we set ``as_grey=True``. """ import matplotlib.pyplot as plt from skimage.data import data_dir from skimage.util import img_as_ubyte from skimage import io plt.gray() phantom = img_as_ubyte(io.imread(data_dir+'/phantom.png', as_grey=True)) plt.imshow(phantom) """ .. image:: PLOT2RST.current_figure Let's also define a convenience function for plotting comparisons: """ def plot_comparison(original, filtered, filter_name): fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(8, 4)) ax1.imshow(original) ax1.set_title('original') ax1.axis('off') ax2.imshow(filtered) ax2.set_title(filter_name) ax2.axis('off') """ Erosion ======= Morphological ``erosion`` sets a pixel at (i, j) to the *minimum over all pixels in the neighborhood centered at (i, j)*. The structuring element, ``selem``, passed to ``erosion`` is a boolean array that describes this neighborhood. Below, we use ``disk`` to create a circular structuring element, which we use for most of the following examples. """ from skimage.morphology import erosion, dilation, opening, closing, white_tophat from skimage.morphology import black_tophat, skeletonize, convex_hull_image from skimage.morphology import disk selem = disk(6) eroded = erosion(phantom, selem) plot_comparison(phantom, eroded, 'erosion') """ .. image:: PLOT2RST.current_figure Notice how the white boundary of the image disappears or gets eroded as we increase the size of the disk. Also notice the increase in size of the two black ellipses in the center and the disappearance of the 3 light grey patches in the lower part of the image. Dilation ======== Morphological ``dilation`` sets a pixel at (i, j) to the *maximum over all pixels in the neighborhood centered at (i, j)*. Dilation enlarges bright regions and shrinks dark regions. """ dilated = dilation(phantom, selem) plot_comparison(phantom, dilated, 'dilation') """ .. image:: PLOT2RST.current_figure Notice how the white boundary of the image thickens, or gets dilated, as we increase the size of the disk. Also notice the decrease in size of the two black ellipses in the centre, and the thickening of the light grey circle in the center and the 3 patches in the lower part of the image. Opening ======= Morphological ``opening`` on an image is defined as an *erosion followed by a dilation*. Opening can remove small bright spots (i.e. "salt") and connect small dark cracks. """ opened = opening(phantom, selem) plot_comparison(phantom, opened, 'opening') """ .. image:: PLOT2RST.current_figure Since ``opening`` an image starts with an erosion operation, light regions that are *smaller* than the structuring element are removed. The dilation operation that follows ensures that light regions that are *larger* than the structuring element retain their original size. Notice how the light and dark shapes in the center their original thickness but the 3 lighter patches in the bottom get completely eroded. The size dependence is highlighted by the outer white ring: The parts of the ring thinner than the structuring element were completely erased, while the thicker region at the top retains its original thickness. Closing ======= Morphological ``closing`` on an image is defined as a *dilation followed by an erosion*. Closing can remove small dark spots (i.e. "pepper") and connect small bright cracks. To illustrate this more clearly, let's add a small crack to the white border: """ phantom = img_as_ubyte(io.imread(data_dir+'/phantom.png', as_grey=True)) phantom[10:30, 200:210] = 0 closed = closing(phantom, selem) plot_comparison(phantom, closed, 'closing') """ .. image:: PLOT2RST.current_figure Since ``closing`` an image starts with an dilation operation, dark regions that are *smaller* than the structuring element are removed. The dilation operation that follows ensures that dark regions that are *larger* than the structuring element retain their original size. Notice how the white ellipses at the bottom get connected because of dilation, but other dark region retain their original sizes. Also notice how the crack we added is mostly removed. White tophat ============ The ``white_tophat`` of an image is defined as the *image minus its morphological opening*. This operation returns the bright spots of the image that are smaller than the structuring element. To make things interesting, we'll add bright and dark spots to the image: """ phantom = img_as_ubyte(io.imread(data_dir+'/phantom.png', as_grey=True)) phantom[340:350, 200:210] = 255 phantom[100:110, 200:210] = 0 w_tophat = white_tophat(phantom, selem) plot_comparison(phantom, w_tophat, 'white tophat') """ .. image:: PLOT2RST.current_figure As you can see, the 10-pixel wide white square is highlighted since it is smaller than the structuring element. Also, the thin, white edges around most of the ellipse are retained because they're smaller than the structuring element, but the thicker region at the top disappears. Black tophat ============ The ``black_tophat`` of an image is defined as its morphological **closing minus the original image**. This operation returns the *dark spots of the image that are smaller than the structuring element*. """ b_tophat = black_tophat(phantom, selem) plot_comparison(phantom, b_tophat, 'black tophat') """ .. image:: PLOT2RST.current_figure As you can see, the 10-pixel wide black square is highlighted since it is smaller than the structuring element. Duality ------- As you should have noticed, many of these operations are simply the reverse of another operation. This duality can be summarized as follows: 1. Erosion <-> Dilation 2. Opening <-> Closing 3. White tophat <-> Black tophat Skeletonize =========== Thinning is used to reduce each connected component in a binary image to a *single-pixel wide skeleton*. It is important to note that this is performed on binary images only. """ from skimage import img_as_bool horse = ~img_as_bool(io.imread(data_dir+'/horse.png', as_grey=True)) sk = skeletonize(horse) plot_comparison(horse, sk, 'skeletonize') """ .. image:: PLOT2RST.current_figure As the name suggests, this technique is used to thin the image to 1-pixel wide skeleton by applying thinning successively. Convex hull =========== The ``convex_hull_image`` is the *set of pixels included in the smallest convex polygon that surround all white pixels in the input image*. Again note that this is also performed on binary images. """ hull1 = convex_hull_image(horse) plot_comparison(horse, hull1, 'convex hull') """ .. image:: PLOT2RST.current_figure As the figure illustrates, ``convex_hull_image`` gives the smallest polygon which covers the white or True completely in the image. If we add a small grain to the image, we can see how the convex hull adapts to enclose that grain: """ import numpy as np horse2 = np.copy(horse) horse2[45:50, 75:80] = 1 hull2 = convex_hull_image(horse2) plot_comparison(horse2, hull2, 'convex hull') """ .. image:: PLOT2RST.current_figure Additional Resources ==================== 1. `MathWorks tutorial on morphological processing `_ 2. `Auckland university's tutorial on Morphological Image Processing `_ 3. http://en.wikipedia.org/wiki/Mathematical_morphology """ plt.show() scikit-image-0.9.3/doc/examples/applications/plot_rank_filters.py000066400000000000000000000437541223313777300252620ustar00rootroot00000000000000""" ============ Rank filters ============ Rank filters are non-linear filters using the local gray-level ordering to compute the filtered value. This ensemble of filters share a common base: the local gray-level histogram is computed on the neighborhood of a pixel (defined by a 2-D structuring element). If the filtered value is taken as the middle value of the histogram, we get the classical median filter. Rank filters can be used for several purposes such as: * image quality enhancement e.g. image smoothing, sharpening * image pre-processing e.g. noise reduction, contrast enhancement * feature extraction e.g. border detection, isolated point detection * post-processing e.g. small object removal, object grouping, contour smoothing Some well known filters are specific cases of rank filters [1]_ e.g. morphological dilation, morphological erosion, median filters. In this example, we will see how to filter a gray-level image using some of the linear and non-linear filters available in skimage. We use the `camera` image from `skimage.data` for all comparisons. .. [1] Pierre Soille, On morphological operators based on rank filters, Pattern Recognition 35 (2002) 527-535. """ import numpy as np import matplotlib.pyplot as plt from skimage import img_as_ubyte from skimage import data noisy_image = img_as_ubyte(data.camera()) hist = np.histogram(noisy_image, bins=np.arange(0, 256)) plt.figure(figsize=(8, 3)) plt.subplot(1, 2, 1) plt.imshow(noisy_image, interpolation='nearest') plt.axis('off') plt.subplot(1, 2, 2) plt.plot(hist[1][:-1], hist[0], lw=2) plt.title('Histogram of grey values') """ .. image:: PLOT2RST.current_figure Noise removal ============= Some noise is added to the image, 1% of pixels are randomly set to 255, 1% are randomly set to 0. The **median** filter is applied to remove the noise. .. note:: There are different implementations of median filter: `skimage.filter.median_filter` and `skimage.filter.rank.median` """ from skimage.filter.rank import median from skimage.morphology import disk noise = np.random.random(noisy_image.shape) noisy_image = img_as_ubyte(data.camera()) noisy_image[noise > 0.99] = 255 noisy_image[noise < 0.01] = 0 fig = plt.figure(figsize=(10, 7)) plt.subplot(2, 2, 1) plt.imshow(noisy_image, vmin=0, vmax=255) plt.title('Noisy image') plt.axis('off') plt.subplot(2, 2, 2) plt.imshow(median(noisy_image, disk(1)), vmin=0, vmax=255) plt.title('Median $r=1$') plt.axis('off') plt.subplot(2, 2, 3) plt.imshow(median(noisy_image, disk(5)), vmin=0, vmax=255) plt.title('Median $r=5$') plt.axis('off') plt.subplot(2, 2, 4) plt.imshow(median(noisy_image, disk(20)), vmin=0, vmax=255) plt.title('Median $r=20$') plt.axis('off') """ .. image:: PLOT2RST.current_figure The added noise is efficiently removed, as the image defaults are small (1 pixel wide), a small filter radius is sufficient. As the radius is increasing, objects with bigger sizes are filtered as well, such as the camera tripod. The median filter is often used for noise removal because borders are preserved and e.g. salt and pepper noise typically does not distort the gray-level. Image smoothing ================ The example hereunder shows how a local **mean** filter smooths the camera man image. """ from skimage.filter.rank import mean fig = plt.figure(figsize=[10, 7]) loc_mean = mean(noisy_image, disk(10)) plt.subplot(1, 2, 1) plt.imshow(noisy_image, vmin=0, vmax=255) plt.title('Original') plt.axis('off') plt.subplot(1, 2, 2) plt.imshow(loc_mean, vmin=0, vmax=255) plt.title('Local mean $r=10$') plt.axis('off') """ .. image:: PLOT2RST.current_figure One may be interested in smoothing an image while preserving important borders (median filters already achieved this), here we use the **bilateral** filter that restricts the local neighborhood to pixel having a gray-level similar to the central one. .. note:: A different implementation is available for color images in `skimage.filter.denoise_bilateral`. """ from skimage.filter.rank import bilateral_mean noisy_image = img_as_ubyte(data.camera()) bilat = bilateral_mean(noisy_image.astype(np.uint16), disk(20), s0=10, s1=10) fig = plt.figure(figsize=[10, 7]) plt.subplot(2, 2, 1) plt.imshow(noisy_image, cmap=plt.cm.gray) plt.title('Original') plt.axis('off') plt.subplot(2, 2, 3) plt.imshow(bilat, cmap=plt.cm.gray) plt.title('Bilateral mean') plt.axis('off') plt.subplot(2, 2, 2) plt.imshow(noisy_image[200:350, 350:450], cmap=plt.cm.gray) plt.axis('off') plt.subplot(2, 2, 4) plt.imshow(bilat[200:350, 350:450], cmap=plt.cm.gray) plt.axis('off') """ .. image:: PLOT2RST.current_figure One can see that the large continuous part of the image (e.g. sky) is smoothed whereas other details are preserved. Contrast enhancement ==================== We compare here how the global histogram equalization is applied locally. The equalized image [2]_ has a roughly linear cumulative distribution function for each pixel neighborhood. The local version [3]_ of the histogram equalization emphasizes every local gray-level variations. .. [2] http://en.wikipedia.org/wiki/Histogram_equalization .. [3] http://en.wikipedia.org/wiki/Adaptive_histogram_equalization """ from skimage import exposure from skimage.filter import rank noisy_image = img_as_ubyte(data.camera()) # equalize globally and locally glob = exposure.equalize(noisy_image) * 255 loc = rank.equalize(noisy_image, disk(20)) # extract histogram for each image hist = np.histogram(noisy_image, bins=np.arange(0, 256)) glob_hist = np.histogram(glob, bins=np.arange(0, 256)) loc_hist = np.histogram(loc, bins=np.arange(0, 256)) plt.figure(figsize=(10, 10)) plt.subplot(321) plt.imshow(noisy_image, interpolation='nearest') plt.axis('off') plt.subplot(322) plt.plot(hist[1][:-1], hist[0], lw=2) plt.title('Histogram of gray values') plt.subplot(323) plt.imshow(glob, interpolation='nearest') plt.axis('off') plt.subplot(324) plt.plot(glob_hist[1][:-1], glob_hist[0], lw=2) plt.title('Histogram of gray values') plt.subplot(325) plt.imshow(loc, interpolation='nearest') plt.axis('off') plt.subplot(326) plt.plot(loc_hist[1][:-1], loc_hist[0], lw=2) plt.title('Histogram of gray values') """ .. image:: PLOT2RST.current_figure Another way to maximize the number of gray-levels used for an image is to apply a local auto-leveling, i.e. the gray-value of a pixel is proportionally remapped between local minimum and local maximum. The following example shows how local auto-level enhances the camara man picture. """ from skimage.filter.rank import autolevel noisy_image = img_as_ubyte(data.camera()) auto = autolevel(noisy_image.astype(np.uint16), disk(20)) fig = plt.figure(figsize=[10, 7]) plt.subplot(1, 2, 1) plt.imshow(noisy_image, cmap=plt.cm.gray) plt.title('Original') plt.axis('off') plt.subplot(1, 2, 2) plt.imshow(auto, cmap=plt.cm.gray) plt.title('Local autolevel') plt.axis('off') """ .. image:: PLOT2RST.current_figure This filter is very sensitive to local outliers, see the little white spot in the left part of the sky. This is due to a local maximum which is very high comparing to the rest of the neighborhood. One can moderate this using the percentile version of the auto-level filter which uses given percentiles (one inferior, one superior) in place of local minimum and maximum. The example below illustrates how the percentile parameters influence the local auto-level result. """ from skimage.filter.rank import autolevel_percentile image = data.camera() selem = disk(20) loc_autolevel = autolevel(image, selem=selem) loc_perc_autolevel0 = autolevel_percentile(image, selem=selem, p0=.00, p1=1.0) loc_perc_autolevel1 = autolevel_percentile(image, selem=selem, p0=.01, p1=.99) loc_perc_autolevel2 = autolevel_percentile(image, selem=selem, p0=.05, p1=.95) loc_perc_autolevel3 = autolevel_percentile(image, selem=selem, p0=.1, p1=.9) fig, axes = plt.subplots(nrows=3, figsize=(7, 8)) ax0, ax1, ax2 = axes plt.gray() ax0.imshow(np.hstack((image, loc_autolevel))) ax0.set_title('Original / auto-level') ax1.imshow( np.hstack((loc_perc_autolevel0, loc_perc_autolevel1)), vmin=0, vmax=255) ax1.set_title('Percentile auto-level 0%,1%') ax2.imshow( np.hstack((loc_perc_autolevel2, loc_perc_autolevel3)), vmin=0, vmax=255) ax2.set_title('Percentile auto-level 5% and 10%') for ax in axes: ax.axis('off') """ .. image:: PLOT2RST.current_figure The morphological contrast enhancement filter replaces the central pixel by the local maximum if the original pixel value is closest to local maximum, otherwise by the minimum local. """ from skimage.filter.rank import enhance_contrast noisy_image = img_as_ubyte(data.camera()) enh = enhance_contrast(noisy_image, disk(5)) fig = plt.figure(figsize=[10, 7]) plt.subplot(2, 2, 1) plt.imshow(noisy_image, cmap=plt.cm.gray) plt.title('Original') plt.axis('off') plt.subplot(2, 2, 3) plt.imshow(enh, cmap=plt.cm.gray) plt.title('Local morphological contrast enhancement') plt.axis('off') plt.subplot(2, 2, 2) plt.imshow(noisy_image[200:350, 350:450], cmap=plt.cm.gray) plt.axis('off') plt.subplot(2, 2, 4) plt.imshow(enh[200:350, 350:450], cmap=plt.cm.gray) plt.axis('off') """ .. image:: PLOT2RST.current_figure The percentile version of the local morphological contrast enhancement uses percentile *p0* and *p1* instead of the local minimum and maximum. """ from skimage.filter.rank import enhance_contrast_percentile noisy_image = img_as_ubyte(data.camera()) penh = enhance_contrast_percentile(noisy_image, disk(5), p0=.1, p1=.9) fig = plt.figure(figsize=[10, 7]) plt.subplot(2, 2, 1) plt.imshow(noisy_image, cmap=plt.cm.gray) plt.title('Original') plt.axis('off') plt.subplot(2, 2, 3) plt.imshow(penh, cmap=plt.cm.gray) plt.title('Local percentile morphological\n contrast enhancement') plt.axis('off') plt.subplot(2, 2, 2) plt.imshow(noisy_image[200:350, 350:450], cmap=plt.cm.gray) plt.axis('off') plt.subplot(2, 2, 4) plt.imshow(penh[200:350, 350:450], cmap=plt.cm.gray) plt.axis('off') """ .. image:: PLOT2RST.current_figure Image threshold =============== The Otsu threshold [1]_ method can be applied locally using the local gray- level distribution. In the example below, for each pixel, an "optimal" threshold is determined by maximizing the variance between two classes of pixels of the local neighborhood defined by a structuring element. The example compares the local threshold with the global threshold `skimage.filter.threshold_otsu`. .. note:: Local is much slower than global thresholding. A function for global Otsu thresholding can be found in : `skimage.filter.threshold_otsu`. .. [4] http://en.wikipedia.org/wiki/Otsu's_method """ from skimage.filter.rank import otsu from skimage.filter import threshold_otsu p8 = data.page() radius = 10 selem = disk(radius) # t_loc_otsu is an image t_loc_otsu = otsu(p8, selem) loc_otsu = p8 >= t_loc_otsu # t_glob_otsu is a scalar t_glob_otsu = threshold_otsu(p8) glob_otsu = p8 >= t_glob_otsu plt.figure() plt.subplot(2, 2, 1) plt.imshow(p8, cmap=plt.cm.gray) plt.title('Original') plt.colorbar() plt.axis('off') plt.subplot(2, 2, 2) plt.imshow(t_loc_otsu, cmap=plt.cm.gray) plt.title('Local Otsu ($r=%d$)' % radius) plt.colorbar() plt.axis('off') plt.subplot(2, 2, 3) plt.imshow(p8 >= t_loc_otsu, cmap=plt.cm.gray) plt.title('Original >= local Otsu' % t_glob_otsu) plt.axis('off') plt.subplot(2, 2, 4) plt.imshow(glob_otsu, cmap=plt.cm.gray) plt.title('Global Otsu ($t=%d$)' % t_glob_otsu) plt.axis('off') """ .. image:: PLOT2RST.current_figure The following example shows how local Otsu thresholding handles a global level shift applied to a synthetic image. """ n = 100 theta = np.linspace(0, 10 * np.pi, n) x = np.sin(theta) m = (np.tile(x, (n, 1)) * np.linspace(0.1, 1, n) * 128 + 128).astype(np.uint8) radius = 10 t = rank.otsu(m, disk(radius)) plt.figure() plt.subplot(1, 2, 1) plt.imshow(m) plt.title('Original') plt.axis('off') plt.subplot(1, 2, 2) plt.imshow(m >= t, interpolation='nearest') plt.title('Local Otsu ($r=%d$)' % radius) plt.axis('off') """ .. image:: PLOT2RST.current_figure Image morphology ================ Local maximum and local minimum are the base operators for gray-level morphology. .. note:: `skimage.dilate` and `skimage.erode` are equivalent filters (see below for comparison). Here is an example of the classical morphological gray-level filters: opening, closing and morphological gradient. """ from skimage.filter.rank import maximum, minimum, gradient noisy_image = img_as_ubyte(data.camera()) closing = maximum(minimum(noisy_image, disk(5)), disk(5)) opening = minimum(maximum(noisy_image, disk(5)), disk(5)) grad = gradient(noisy_image, disk(5)) # display results fig = plt.figure(figsize=[10, 7]) plt.subplot(2, 2, 1) plt.imshow(noisy_image, cmap=plt.cm.gray) plt.title('Original') plt.axis('off') plt.subplot(2, 2, 2) plt.imshow(closing, cmap=plt.cm.gray) plt.title('Gray-level closing') plt.axis('off') plt.subplot(2, 2, 3) plt.imshow(opening, cmap=plt.cm.gray) plt.title('Gray-level opening') plt.axis('off') plt.subplot(2, 2, 4) plt.imshow(grad, cmap=plt.cm.gray) plt.title('Morphological gradient') plt.axis('off') """ .. image:: PLOT2RST.current_figure Feature extraction =================== Local histograms can be exploited to compute local entropy, which is related to the local image complexity. Entropy is computed using base 2 logarithm i.e. the filter returns the minimum number of bits needed to encode local gray-level distribution. `skimage.rank.entropy` returns the local entropy on a given structuring element. The following example shows applies this filter on 8- and 16-bit images. .. note:: to better use the available image bit, the function returns 10x entropy for 8-bit images and 1000x entropy for 16-bit images. """ from skimage import data from skimage.filter.rank import entropy from skimage.morphology import disk import numpy as np import matplotlib.pyplot as plt image = data.camera() plt.figure(figsize=(10, 4)) plt.subplot(1, 2, 1) plt.imshow(image, cmap=plt.cm.gray) plt.title('Image') plt.colorbar() plt.axis('off') plt.subplot(1, 2, 2) plt.imshow(entropy(image, disk(5)), cmap=plt.cm.jet) plt.title('Entropy') plt.colorbar() plt.axis('off') """ .. image:: PLOT2RST.current_figure Implementation ============== The central part of the `skimage.rank` filters is build on a sliding window that updates the local gray-level histogram. This approach limits the algorithm complexity to O(n) where n is the number of image pixels. The complexity is also limited with respect to the structuring element size. In the following we compare the performance of different implementations available in `skimage`. """ from time import time from scipy.ndimage.filters import percentile_filter from skimage.morphology import dilation from skimage.filter import median_filter from skimage.filter.rank import median, maximum def exec_and_timeit(func): """Decorator that returns both function results and execution time.""" def wrapper(*arg): t1 = time() res = func(*arg) t2 = time() ms = (t2 - t1) * 1000.0 return (res, ms) return wrapper @exec_and_timeit def cr_med(image, selem): return median(image=image, selem=selem) @exec_and_timeit def cr_max(image, selem): return maximum(image=image, selem=selem) @exec_and_timeit def cm_dil(image, selem): return dilation(image=image, selem=selem) @exec_and_timeit def ctmf_med(image, radius): return median_filter(image=image, radius=radius) @exec_and_timeit def ndi_med(image, n): return percentile_filter(image, 50, size=n * 2 - 1) """ Comparison between * `filter.rank.maximum` * `morphology.dilate` on increasing structuring element size: """ a = data.camera() rec = [] e_range = range(1, 20, 2) for r in e_range: elem = disk(r + 1) rc, ms_rc = cr_max(a, elem) rcm, ms_rcm = cm_dil(a, elem) rec.append((ms_rc, ms_rcm)) rec = np.asarray(rec) plt.figure() plt.title('Performance with respect to element size') plt.ylabel('Time (ms)') plt.title('Element radius') plt.plot(e_range, rec) plt.legend(['filter.rank.maximum', 'morphology.dilate']) """ .. image:: PLOT2RST.current_figure and increasing image size: """ r = 9 elem = disk(r + 1) rec = [] s_range = range(100, 1000, 100) for s in s_range: a = (np.random.random((s, s)) * 256).astype(np.uint8) (rc, ms_rc) = cr_max(a, elem) (rcm, ms_rcm) = cm_dil(a, elem) rec.append((ms_rc, ms_rcm)) rec = np.asarray(rec) plt.figure() plt.title('Performance with respect to image size') plt.ylabel('Time (ms)') plt.title('Image size') plt.plot(s_range, rec) plt.legend(['filter.rank.maximum', 'morphology.dilate']) """ .. image:: PLOT2RST.current_figure Comparison between: * `filter.rank.median` * `filter.median_filter` * `scipy.ndimage.percentile` on increasing structuring element size: """ a = data.camera() rec = [] e_range = range(2, 30, 4) for r in e_range: elem = disk(r + 1) rc, ms_rc = cr_med(a, elem) rctmf, ms_rctmf = ctmf_med(a, r) rndi, ms_ndi = ndi_med(a, r) rec.append((ms_rc, ms_rctmf, ms_ndi)) rec = np.asarray(rec) plt.figure() plt.title('Performance with respect to element size') plt.plot(e_range, rec) plt.legend(['filter.rank.median', 'filter.median_filter', 'scipy.ndimage.percentile']) plt.ylabel('Time (ms)') plt.title('Element radius') """ .. image:: PLOT2RST.current_figure Comparison of outcome of the three methods: """ plt.figure() plt.imshow(np.hstack((rc, rctmf, rndi))) plt.title('filter.rank.median vs filtermedian_filter vs scipy.ndimage.percentile') plt.axis('off') """ .. image:: PLOT2RST.current_figure and increasing image size: """ r = 9 elem = disk(r + 1) rec = [] s_range = [100, 200, 500, 1000] for s in s_range: a = (np.random.random((s, s)) * 256).astype(np.uint8) (rc, ms_rc) = cr_med(a, elem) rctmf, ms_rctmf = ctmf_med(a, r) rndi, ms_ndi = ndi_med(a, r) rec.append((ms_rc, ms_rctmf, ms_ndi)) rec = np.asarray(rec) plt.figure() plt.title('Performance with respect to image size') plt.plot(s_range, rec) plt.legend(['filter.rank.median', 'filter.median_filter', 'scipy.ndimage.percentile']) plt.ylabel('Time (ms)') plt.title('Image size') """ .. image:: PLOT2RST.current_figure """ plt.show() scikit-image-0.9.3/doc/examples/plot_canny.py000066400000000000000000000031331223313777300212040ustar00rootroot00000000000000""" =================== Canny edge detector =================== The Canny filter is a multi-stage edge detector. It uses a filter based on the derivative of a Gaussian in order to compute the intensity of the gradients.The Gaussian reduces the effect of noise present in the image. Then, potential edges are thinned down to 1-pixel curves by removing non-maximum pixels of the gradient magnitude. Finally, edge pixels are kept or removed using hysteresis thresholding on the gradient magnitude. The Canny has three adjustable parameters: the width of the Gaussian (the noisier the image, the greater the width), and the low and high threshold for the hysteresis thresholding. """ import numpy as np import matplotlib.pyplot as plt from scipy import ndimage from skimage import filter # Generate noisy image of a square im = np.zeros((128, 128)) im[32:-32, 32:-32] = 1 im = ndimage.rotate(im, 15, mode='constant') im = ndimage.gaussian_filter(im, 4) im += 0.2 * np.random.random(im.shape) # Compute the Canny filter for two values of sigma edges1 = filter.canny(im) edges2 = filter.canny(im, sigma=3) # display results plt.figure(figsize=(8, 3)) plt.subplot(131) plt.imshow(im, cmap=plt.cm.jet) plt.axis('off') plt.title('noisy image', fontsize=20) plt.subplot(132) plt.imshow(edges1, cmap=plt.cm.gray) plt.axis('off') plt.title('Canny filter, $\sigma=1$', fontsize=20) plt.subplot(133) plt.imshow(edges2, cmap=plt.cm.gray) plt.axis('off') plt.title('Canny filter, $\sigma=3$', fontsize=20) plt.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9, bottom=0.02, left=0.02, right=0.98) plt.show() scikit-image-0.9.3/doc/examples/plot_circular_elliptical_hough_transform.py000077500000000000000000000110641223313777300273740ustar00rootroot00000000000000""" ======================================== Circular and Elliptical Hough Transforms ======================================== The Hough transform in its simplest form is a `method to detect straight lines `__ but it can also be used to detect circles or ellipses. The algorithm assumes that the edge is detected and it is robust against noise or missing points. Circle detection ================ In the following example, the Hough transform is used to detect coin positions and match their edges. We provide a range of plausible radii. For each radius, two circles are extracted and we finally keep the five most prominent candidates. The result shows that coin positions are well-detected. Algorithm overview ------------------ Given a black circle on a white background, we first guess its radius (or a range of radii) to construct a new circle. This circle is applied on each black pixel of the original picture and the coordinates of this circle are voting in an accumulator. From this geometrical construction, the original circle center position receives the highest score. Note that the accumulator size is built to be larger than the original picture in order to detect centers outside the frame. Its size is extended by two times the larger radius. """ import numpy as np import matplotlib.pyplot as plt from skimage import data, filter, color from skimage.transform import hough_circle from skimage.feature import peak_local_max from skimage.draw import circle_perimeter from skimage.util import img_as_ubyte # Load picture and detect edges image = img_as_ubyte(data.coins()[0:95, 70:370]) edges = filter.canny(image, sigma=3, low_threshold=10, high_threshold=50) fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6)) # Detect two radii hough_radii = np.arange(15, 30, 2) hough_res = hough_circle(edges, hough_radii) centers = [] accums = [] radii = [] for radius, h in zip(hough_radii, hough_res): # For each radius, extract two circles peaks = peak_local_max(h, num_peaks=2) centers.extend(peaks) accums.extend(h[peaks[:, 0], peaks[:, 1]]) radii.extend([radius, radius]) # Draw the most prominent 5 circles image = color.gray2rgb(image) for idx in np.argsort(accums)[::-1][:5]: center_x, center_y = centers[idx] radius = radii[idx] cx, cy = circle_perimeter(center_y, center_x, radius) image[cy, cx] = (220, 20, 20) ax.imshow(image, cmap=plt.cm.gray) """ Ellipse detection ================= In this second example, the aim is to detect the edge of a coffee cup. Basically, this is a projection of a circle, i.e. an ellipse. The problem to solve is much more difficult because five parameters have to be determined, instead of three for circles. Algorithm overview ------------------ The algorithm takes two different points belonging to the ellipse. It assumes that it is the main axis. A loop on all the other points determines how much an ellipse passes to them. A good match corresponds to high accumulator values. A full description of the algorithm can be found in reference [1]_. References ---------- .. [1] Xie, Yonghong, and Qiang Ji. "A new efficient ellipse detection method." Pattern Recognition, 2002. Proceedings. 16th International Conference on. Vol. 2. IEEE, 2002 """ import matplotlib.pyplot as plt from skimage import data, filter, color from skimage.transform import hough_ellipse from skimage.draw import ellipse_perimeter # Load picture, convert to grayscale and detect edges image_rgb = data.coffee()[0:220, 160:420] image_gray = color.rgb2gray(image_rgb) edges = filter.canny(image_gray, sigma=2.0, low_threshold=0.55, high_threshold=0.8) # Perform a Hough Transform # The accuracy corresponds to the bin size of a major axis. # The value is chosen in order to get a single high accumulator. # The threshold eliminates low accumulators result = hough_ellipse(edges, accuracy=20, threshold=250, min_size=100, max_size=120) result.sort(order='accumulator') # Estimated parameters for the ellipse best = result[-1] yc = int(best[1]) xc = int(best[2]) a = int(best[3]) b = int(best[4]) orientation = best[5] # Draw the ellipse on the original image cy, cx = ellipse_perimeter(yc, xc, a, b, orientation) image_rgb[cy, cx] = (0, 0, 255) # Draw the edge (white) and the resulting ellipse (red) edges = color.gray2rgb(edges) edges[cy, cx] = (250, 0, 0) fig2, (ax1, ax2) = plt.subplots(ncols=2, nrows=1, figsize=(10, 6)) ax1.set_title('Original picture') ax1.imshow(image_rgb) ax2.set_title('Edge (white) and result (red)') ax2.imshow(edges) plt.show() scikit-image-0.9.3/doc/examples/plot_contours.py000066400000000000000000000022611223313777300217510ustar00rootroot00000000000000""" =============== Contour finding =============== ``skimage.measure.find_contours`` uses a marching squares method to find constant valued contours in an image. Array values are linearly interpolated to provide better precision of the output contours. Contours which intersect the image edge are open; all others are closed. The `marching squares algorithm `__ is a special case of the marching cubes algorithm (Lorensen, William and Harvey E. Cline. Marching Cubes: A High Resolution 3D Surface Construction Algorithm. Computer Graphics (SIGGRAPH 87 Proceedings) 21(4) July 1987, p. 163-170). """ import numpy as np import matplotlib.pyplot as plt from skimage import measure # Construct some test data x, y = np.ogrid[-np.pi:np.pi:100j, -np.pi:np.pi:100j] r = np.sin(np.exp((np.sin(x)**3 + np.cos(y)**2))) # Find contours at a constant value of 0.8 contours = measure.find_contours(r, 0.8) # Display the image and plot all contours found plt.imshow(r, interpolation='nearest') for n, contour in enumerate(contours): plt.plot(contour[:, 1], contour[:, 0], linewidth=2) plt.axis('image') plt.xticks([]) plt.yticks([]) plt.show() scikit-image-0.9.3/doc/examples/plot_convex_hull.py000066400000000000000000000026101223313777300224210ustar00rootroot00000000000000""" =========== Convex Hull =========== The convex hull of a binary image is the set of pixels included in the smallest convex polygon that surround all white pixels in the input. In this example, we show how the input pixels (white) get filled in by the convex hull (white and grey). A good overview of the algorithm is given on `Steve Eddin's blog `__. """ import numpy as np import matplotlib.pyplot as plt from skimage.morphology import convex_hull_image image = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=float) original_image = np.copy(image) chull = convex_hull_image(image) image[chull] += 1 # image is now: #[[ 0. 0. 0. 0. 0. 0. 0. 0. 0.] # [ 0. 0. 0. 0. 2. 0. 0. 0. 0.] # [ 0. 0. 0. 2. 1. 2. 0. 0. 0.] # [ 0. 0. 2. 1. 1. 1. 2. 0. 0.] # [ 0. 2. 1. 1. 1. 1. 1. 2. 0.] # [ 0. 0. 0. 0. 0. 0. 0. 0. 0.]] fig = plt.subplots(figsize=(10, 6)) plt.subplot(1, 2, 1) plt.title('Original picture') plt.imshow(original_image, cmap=plt.cm.gray, interpolation='nearest') plt.subplot(1, 2, 2) plt.title('Transformed picture') plt.imshow(image, cmap=plt.cm.gray, interpolation='nearest') plt.show() scikit-image-0.9.3/doc/examples/plot_corner.py000066400000000000000000000021541223313777300213660ustar00rootroot00000000000000""" ================ Corner detection ================ Detect corner points using the Harris corner detector and determine subpixel position of corners. .. [1] http://en.wikipedia.org/wiki/Corner_detection .. [2] http://en.wikipedia.org/wiki/Interest_point_detection """ from matplotlib import pyplot as plt from skimage import data from skimage.feature import corner_harris, corner_subpix, corner_peaks from skimage.transform import warp, AffineTransform from skimage.draw import ellipse tform = AffineTransform(scale=(1.3, 1.1), rotation=1, shear=0.7, translation=(210, 50)) image = warp(data.checkerboard(), tform.inverse, output_shape=(350, 350)) rr, cc = ellipse(310, 175, 10, 100) image[rr, cc] = 1 image[180:230, 10:60] = 1 image[230:280, 60:110] = 1 coords = corner_peaks(corner_harris(image), min_distance=5) coords_subpix = corner_subpix(image, coords, window_size=13) plt.gray() plt.imshow(image, interpolation='nearest') plt.plot(coords[:, 1], coords[:, 0], '.b', markersize=3) plt.plot(coords_subpix[:, 1], coords_subpix[:, 0], '+r', markersize=15) plt.axis((0, 350, 350, 0)) plt.show() scikit-image-0.9.3/doc/examples/plot_daisy.py000066400000000000000000000015221223313777300212050ustar00rootroot00000000000000""" =============================== Dense DAISY feature description =============================== The DAISY local image descriptor is based on gradient orientation histograms similar to the SIFT descriptor. It is formulated in a way that allows for fast dense extraction which is useful for e.g. bag-of-features image representations. In this example a limited number of DAISY descriptors are extracted at a large scale for illustrative purposes. """ from skimage.feature import daisy from skimage import data import matplotlib.pyplot as plt img = data.camera() descs, descs_img = daisy(img, step=180, radius=58, rings=2, histograms=6, orientations=8, visualize=True) plt.axis('off') plt.imshow(descs_img) descs_num = descs.shape[0] * descs.shape[1] plt.title('%i DAISY descriptors extracted:' % descs_num) plt.show() scikit-image-0.9.3/doc/examples/plot_denoise.py000066400000000000000000000040211223313777300215170ustar00rootroot00000000000000""" ============================= Denoising the picture of Lena ============================= In this example, we denoise a noisy version of the picture of Lena using the total variation and bilateral denoising filter. These algorithms typically produce "posterized" images with flat domains separated by sharp edges. It is possible to change the degree of posterization by controlling the tradeoff between denoising and faithfulness to the original image. Total variation filter ---------------------- The result of this filter is an image that has a minimal total variation norm, while being as close to the initial image as possible. The total variation is the L1 norm of the gradient of the image. Bilateral filter ---------------- A bilateral filter is an edge-preserving and noise reducing filter. It averages pixels based on their spatial closeness and radiometric similarity. """ import numpy as np import matplotlib.pyplot as plt from skimage import data, img_as_float from skimage.filter import denoise_tv_chambolle, denoise_bilateral lena = img_as_float(data.lena()) lena = lena[220:300, 220:320] noisy = lena + 0.6 * lena.std() * np.random.random(lena.shape) noisy = np.clip(noisy, 0, 1) fig, ax = plt.subplots(nrows=2, ncols=3, figsize=(8, 5)) plt.gray() ax[0, 0].imshow(noisy) ax[0, 0].axis('off') ax[0, 0].set_title('noisy') ax[0, 1].imshow(denoise_tv_chambolle(noisy, weight=0.1, multichannel=True)) ax[0, 1].axis('off') ax[0, 1].set_title('TV') ax[0, 2].imshow(denoise_bilateral(noisy, sigma_range=0.05, sigma_spatial=15)) ax[0, 2].axis('off') ax[0, 2].set_title('Bilateral') ax[1, 0].imshow(denoise_tv_chambolle(noisy, weight=0.2, multichannel=True)) ax[1, 0].axis('off') ax[1, 0].set_title('(more) TV') ax[1, 1].imshow(denoise_bilateral(noisy, sigma_range=0.1, sigma_spatial=15)) ax[1, 1].axis('off') ax[1, 1].set_title('(more) Bilateral') ax[1, 2].imshow(lena) ax[1, 2].axis('off') ax[1, 2].set_title('original') fig.subplots_adjust(wspace=0.02, hspace=0.2, top=0.9, bottom=0.05, left=0, right=1) plt.show() scikit-image-0.9.3/doc/examples/plot_edge_filter.py000066400000000000000000000012551223313777300223500ustar00rootroot00000000000000""" ============== Edge operators ============== Edge operators are used in image processing within edge detection algorithms. They are discrete differentiation operators, computing an approximation of the gradient of the image intensity function. """ import matplotlib.pyplot as plt from skimage.data import camera from skimage.filter import roberts, sobel image = camera() edge_roberts = roberts(image) edge_sobel = sobel(image) fig, (ax0, ax1) = plt.subplots(ncols=2) ax0.imshow(edge_roberts, cmap=plt.cm.gray) ax0.set_title('Roberts Edge Detection') ax0.axis('off') ax1.imshow(edge_sobel, cmap=plt.cm.gray) ax1.set_title('Sobel Edge Detection') ax1.axis('off') plt.show() scikit-image-0.9.3/doc/examples/plot_entropy.py000066400000000000000000000012141223313777300215720ustar00rootroot00000000000000""" ======= Entropy ======= Image entropy is a quantity which is used to describe the amount of information coded in an image. """ import matplotlib.pyplot as plt from skimage import data from skimage.filter.rank import entropy from skimage.morphology import disk from skimage.util import img_as_ubyte image = img_as_ubyte(data.camera()) fig, (ax0, ax1) = plt.subplots(ncols=2, figsize=(10, 4)) img0 = ax0.imshow(image, cmap=plt.cm.gray) ax0.set_title('Image') ax0.axis('off') plt.colorbar(img0, ax=ax0) img1 = ax1.imshow(entropy(image, disk(5)), cmap=plt.cm.jet) ax1.set_title('Entropy') ax1.axis('off') plt.colorbar(img1, ax=ax1) plt.show() scikit-image-0.9.3/doc/examples/plot_equalize.py000066400000000000000000000052541223313777300217210ustar00rootroot00000000000000""" ====================== Histogram Equalization ====================== This examples enhances an image with low contrast, using a method called *histogram equalization*, which "spreads out the most frequent intensity values" in an image [1]_. The equalized image has a roughly linear cumulative distribution function. While histogram equalization has the advantage that it requires no parameters, it sometimes yields unnatural looking images. An alternative method is *contrast stretching*, where the image is rescaled to include all intensities that fall within the 2nd and 98th percentiles [2]_. .. [1] http://en.wikipedia.org/wiki/Histogram_equalization .. [2] http://homepages.inf.ed.ac.uk/rbf/HIPR2/stretch.htm """ import matplotlib.pyplot as plt import numpy as np from skimage import data, img_as_float from skimage import exposure def plot_img_and_hist(img, axes, bins=256): """Plot an image along with its histogram and cumulative histogram. """ img = img_as_float(img) ax_img, ax_hist = axes ax_cdf = ax_hist.twinx() # Display image ax_img.imshow(img, cmap=plt.cm.gray) ax_img.set_axis_off() # Display histogram ax_hist.hist(img.ravel(), bins=bins, histtype='step', color='black') ax_hist.ticklabel_format(axis='y', style='scientific', scilimits=(0, 0)) ax_hist.set_xlabel('Pixel intensity') ax_hist.set_xlim(0, 1) ax_hist.set_yticks([]) # Display cumulative distribution img_cdf, bins = exposure.cumulative_distribution(img, bins) ax_cdf.plot(bins, img_cdf, 'r') ax_cdf.set_yticks([]) return ax_img, ax_hist, ax_cdf # Load an example image img = data.moon() # Contrast stretching p2 = np.percentile(img, 2) p98 = np.percentile(img, 98) img_rescale = exposure.rescale_intensity(img, in_range=(p2, p98)) # Equalization img_eq = exposure.equalize_hist(img) # Adaptive Equalization img_adapteq = exposure.equalize_adapthist(img, clip_limit=0.03) # Display results f, axes = plt.subplots(2, 4, figsize=(8, 4)) ax_img, ax_hist, ax_cdf = plot_img_and_hist(img, axes[:, 0]) ax_img.set_title('Low contrast image') y_min, y_max = ax_hist.get_ylim() ax_hist.set_ylabel('Number of pixels') ax_hist.set_yticks(np.linspace(0, y_max, 5)) ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_rescale, axes[:, 1]) ax_img.set_title('Contrast stretching') ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_eq, axes[:, 2]) ax_img.set_title('Histogram equalization') ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_adapteq, axes[:, 3]) ax_img.set_title('Adaptive equalization') ax_cdf.set_ylabel('Fraction of total intensity') ax_cdf.set_yticks(np.linspace(0, 1, 5)) # prevent overlap of y-axis labels plt.subplots_adjust(wspace=0.4) plt.show() scikit-image-0.9.3/doc/examples/plot_gabor.py000066400000000000000000000105731223313777300211740ustar00rootroot00000000000000""" ============================================= Gabor filter banks for texture classification ============================================= In this example, we will see how to classify textures based on Gabor filter banks. Frequency and orientation representations of the Gabor filter are similar to those of the human visual system. The images are filtered using the real parts of various different Gabor filter kernels. The mean and variance of the filtered images are then used as features for classification, which is based on the least squared error for simplicity. """ from __future__ import print_function import matplotlib import matplotlib.pyplot as plt import numpy as np from scipy import ndimage as nd from skimage import data from skimage.util import img_as_float from skimage.filter import gabor_kernel matplotlib.rcParams['font.size'] = 9 def compute_feats(image, kernels): feats = np.zeros((len(kernels), 2), dtype=np.double) for k, kernel in enumerate(kernels): filtered = nd.convolve(image, kernel, mode='wrap') feats[k, 0] = filtered.mean() feats[k, 1] = filtered.var() return feats def match(feats, ref_feats): min_error = np.inf min_i = None for i in range(ref_feats.shape[0]): error = np.sum((feats - ref_feats[i, :])**2) if error < min_error: min_error = error min_i = i return min_i # prepare filter bank kernels kernels = [] for theta in range(4): theta = theta / 4. * np.pi for sigma in (1, 3): for frequency in (0.05, 0.25): kernel = np.real(gabor_kernel(frequency, theta=theta, sigma_x=sigma, sigma_y=sigma)) kernels.append(kernel) shrink = (slice(0, None, 3), slice(0, None, 3)) brick = img_as_float(data.load('brick.png'))[shrink] grass = img_as_float(data.load('grass.png'))[shrink] wall = img_as_float(data.load('rough-wall.png'))[shrink] image_names = ('brick', 'grass', 'wall') images = (brick, grass, wall) # prepare reference features ref_feats = np.zeros((3, len(kernels), 2), dtype=np.double) ref_feats[0, :, :] = compute_feats(brick, kernels) ref_feats[1, :, :] = compute_feats(grass, kernels) ref_feats[2, :, :] = compute_feats(wall, kernels) print('Rotated images matched against references using Gabor filter banks:') print('original: brick, rotated: 30deg, match result: ', end='') feats = compute_feats(nd.rotate(brick, angle=190, reshape=False), kernels) print(image_names[match(feats, ref_feats)]) print('original: brick, rotated: 70deg, match result: ', end='') feats = compute_feats(nd.rotate(brick, angle=70, reshape=False), kernels) print(image_names[match(feats, ref_feats)]) print('original: grass, rotated: 145deg, match result: ', end='') feats = compute_feats(nd.rotate(grass, angle=145, reshape=False), kernels) print(image_names[match(feats, ref_feats)]) def power(image, kernel): # Normalize images for better comparison. image = (image - image.mean()) / image.std() return np.sqrt(nd.convolve(image, np.real(kernel), mode='wrap')**2 + nd.convolve(image, np.imag(kernel), mode='wrap')**2) # Plot a selection of the filter bank kernels and their responses. results = [] kernel_params = [] for theta in (0, 1): theta = theta / 4. * np.pi for frequency in (0.1, 0.4): kernel = gabor_kernel(frequency, theta=theta) params = 'theta=%d,\nfrequency=%.2f' % (theta * 180 / np.pi, frequency) kernel_params.append(params) # Save kernel and the power image for each image results.append((kernel, [power(img, kernel) for img in images])) fig, axes = plt.subplots(nrows=5, ncols=4, figsize=(9, 6)) plt.gray() fig.suptitle('Image responses for Gabor filter kernels', fontsize=15) axes[0][0].axis('off') # Plot original images for label, img, ax in zip(image_names, images, axes[0][1:]): ax.imshow(img) ax.set_title(label) ax.axis('off') for label, (kernel, powers), ax_row in zip(kernel_params, results, axes[1:]): # Plot Gabor kernel ax = ax_row[0] ax.imshow(np.real(kernel), interpolation='nearest') ax.set_ylabel(label) ax.set_xticks([]) ax.set_yticks([]) # Plot Gabor responses with the contrast normalized for each filter vmin = np.min(powers) vmax = np.max(powers) for patch, ax in zip(powers, ax_row[1:]): ax.imshow(patch, vmin=vmin, vmax=vmax) ax.axis('off') plt.show() scikit-image-0.9.3/doc/examples/plot_gabors_from_lena.py000066400000000000000000000064151223313777300234010ustar00rootroot00000000000000""" ======================================================= Gabors / Primary Visual Cortex "Simple Cells" from Lena ======================================================= How to build a (bio-plausible) "sparse" dictionary (or 'codebook', or 'filterbank') for e.g. image classification without any fancy math and with just standard python scientific libraries? Please find below a short answer ;-) This simple example shows how to get Gabor-like filters [1]_ using just the famous Lena image. Gabor filters are good approximations of the "Simple Cells" [2]_ receptive fields [3]_ found in the mammalian primary visual cortex (V1) (for details, see e.g. the Nobel-prize winning work of Hubel & Wiesel done in the 60s [4]_ [5]_). Here we use McQueen's 'kmeans' algorithm [6]_, as a simple biologically plausible hebbian-like learning rule and we apply it (a) to patches of the original Lena image (retinal projection), and (b) to patches of an LGN-like [7]_ Lena image using a simple difference of gaussians (DoG) approximation. Enjoy ;-) And keep in mind that getting Gabors on natural image patches is not rocket science. .. [1] http://en.wikipedia.org/wiki/Gabor_filter .. [2] http://en.wikipedia.org/wiki/Simple_cell .. [3] http://en.wikipedia.org/wiki/Receptive_field .. [4] http://en.wikipedia.org/wiki/K-means_clustering .. [5] http://en.wikipedia.org/wiki/Lateral_geniculate_nucleus .. [6] D. H. Hubel and T. N., Wiesel Receptive Fields of Single Neurones in the Cat's Striate Cortex, J. Physiol. pp. 574-591 (148) 1959 .. [7] D. H. Hubel and T. N., Wiesel Receptive Fields, Binocular Interaction, and Functional Architecture in the Cat's Visual Cortex, J. Physiol. 160 pp. 106-154 1962 """ import numpy as np from scipy.cluster.vq import kmeans2 from scipy import ndimage as ndi import matplotlib.pyplot as plt from skimage import data from skimage import color from skimage.util.shape import view_as_windows from skimage.util.montage import montage2d np.random.seed(42) patch_shape = 8, 8 n_filters = 49 lena = color.rgb2gray(data.lena()) # -- filterbank1 on original Lena patches1 = view_as_windows(lena, patch_shape) patches1 = patches1.reshape(-1, patch_shape[0] * patch_shape[1])[::8] fb1, _ = kmeans2(patches1, n_filters, minit='points') fb1 = fb1.reshape((-1,) + patch_shape) fb1_montage = montage2d(fb1, rescale_intensity=True) # -- filterbank2 LGN-like Lena lena_dog = ndi.gaussian_filter(lena, .5) - ndi.gaussian_filter(lena, 1) patches2 = view_as_windows(lena_dog, patch_shape) patches2 = patches2.reshape(-1, patch_shape[0] * patch_shape[1])[::8] fb2, _ = kmeans2(patches2, n_filters, minit='points') fb2 = fb2.reshape((-1,) + patch_shape) fb2_montage = montage2d(fb2, rescale_intensity=True) # -- fig, axes = plt.subplots(2, 2, figsize=(7, 6)) ax0, ax1, ax2, ax3 = axes.ravel() ax0.imshow(lena, cmap=plt.cm.gray) ax0.set_title("Lena (original)") ax1.imshow(fb1_montage, cmap=plt.cm.gray, interpolation='nearest') ax1.set_title("K-means filterbank (codebook)\non Lena (original)") ax2.imshow(lena_dog, cmap=plt.cm.gray) ax2.set_title("Lena (LGN-like DoG)") ax3.imshow(fb2_montage, cmap=plt.cm.gray, interpolation='nearest') ax3.set_title("K-means filterbank (codebook)\non Lena (LGN-like DoG)") for ax in axes.ravel(): ax.axis('off') fig.subplots_adjust(hspace=0.3) plt.show() scikit-image-0.9.3/doc/examples/plot_glcm.py000066400000000000000000000063151223313777300210230ustar00rootroot00000000000000""" ===================== GLCM Texture Features ===================== This example illustrates texture classification using texture classification using grey level co-occurrence matrices (GLCMs). A GLCM is a histogram of co-occurring greyscale values at a given offset over an image. In this example, samples of two different textures are extracted from an image: grassy areas and sky areas. For each patch, a GLCM with a horizontal offset of 5 is computed. Next, two features of the GLCM matrices are computed: dissimilarity and correlation. These are plotted to illustrate that the classes form clusters in feature space. In a typical classification problem, the final step (not included in this example) would be to train a classifier, such as logistic regression, to label image patches from new images. """ import matplotlib.pyplot as plt from skimage.feature import greycomatrix, greycoprops from skimage import data PATCH_SIZE = 21 # open the camera image image = data.camera() # select some patches from grassy areas of the image grass_locations = [(474, 291), (440, 433), (466, 18), (462, 236)] grass_patches = [] for loc in grass_locations: grass_patches.append(image[loc[0]:loc[0] + PATCH_SIZE, loc[1]:loc[1] + PATCH_SIZE]) # select some patches from sky areas of the image sky_locations = [(54, 48), (21, 233), (90, 380), (195, 330)] sky_patches = [] for loc in sky_locations: sky_patches.append(image[loc[0]:loc[0] + PATCH_SIZE, loc[1]:loc[1] + PATCH_SIZE]) # compute some GLCM properties each patch xs = [] ys = [] for i, patch in enumerate(grass_patches + sky_patches): glcm = greycomatrix(patch, [5], [0], 256, symmetric=True, normed=True) xs.append(greycoprops(glcm, 'dissimilarity')[0, 0]) ys.append(greycoprops(glcm, 'correlation')[0, 0]) # create the figure plt.figure(figsize=(8, 8)) # display the image patches for i, patch in enumerate(grass_patches): plt.subplot(3, len(grass_patches), len(grass_patches) * 1 + i + 1) plt.imshow(patch, cmap=plt.cm.gray, interpolation='nearest', vmin=0, vmax=255) plt.xlabel('Grass %d' % (i + 1)) for i, patch in enumerate(sky_patches): plt.subplot(3, len(grass_patches), len(grass_patches) * 2 + i + 1) plt.imshow(patch, cmap=plt.cm.gray, interpolation='nearest', vmin=0, vmax=255) plt.xlabel('Sky %d' % (i + 1)) # display original image with locations of patches plt.subplot(3, 2, 1) plt.imshow(image, cmap=plt.cm.gray, interpolation='nearest', vmin=0, vmax=255) for (y, x) in grass_locations: plt.plot(x + PATCH_SIZE / 2, y + PATCH_SIZE / 2, 'gs') for (y, x) in sky_locations: plt.plot(x + PATCH_SIZE / 2, y + PATCH_SIZE / 2, 'bs') plt.xlabel('Original Image') plt.xticks([]) plt.yticks([]) plt.axis('image') # for each patch, plot (dissimilarity, correlation) plt.subplot(3, 2, 2) plt.plot(xs[:len(grass_patches)], ys[:len(grass_patches)], 'go', label='Grass') plt.plot(xs[len(grass_patches):], ys[len(grass_patches):], 'bo', label='Sky') plt.xlabel('GLCM Dissimilarity') plt.ylabel('GLVM Correlation') plt.legend() # display the patches and plot plt.suptitle('Grey level co-occurrence matrix features', fontsize=14) plt.show() scikit-image-0.9.3/doc/examples/plot_hog.py000066400000000000000000000103771223313777300206610ustar00rootroot00000000000000""" =============================== Histogram of Oriented Gradients =============================== The `Histogram of Oriented Gradient `__ (HOG) feature descriptor [1]_ is popular for object detection. In the following example, we compute the HOG descriptor and display a visualisation. Algorithm overview ------------------ Compute a Histogram of Oriented Gradients (HOG) by 1. (optional) global image normalisation 2. computing the gradient image in x and y 3. computing gradient histograms 4. normalising across blocks 5. flattening into a feature vector The first stage applies an optional global image normalisation equalisation that is designed to reduce the influence of illumination effects. In practice we use gamma (power law) compression, either computing the square root or the log of each colour channel. Image texture strength is typically proportional to the local surface illumination so this compression helps to reduce the effects of local shadowing and illumination variations. The second stage computes first order image gradients. These capture contour, silhouette and some texture information, while providing further resistance to illumination variations. The locally dominant colour channel is used, which provides colour invariance to a large extent. Variant methods may also include second order image derivatives, which act as primitive bar detectors - a useful feature for capturing, e.g. bar like structures in bicycles and limbs in humans. The third stage aims to produce an encoding that is sensitive to local image content while remaining resistant to small changes in pose or appearance. The adopted method pools gradient orientation information locally in the same way as the SIFT [2]_ feature. The image window is divided into small spatial regions, called "cells". For each cell we accumulate a local 1-D histogram of gradient or edge orientations over all the pixels in the cell. This combined cell-level 1-D histogram forms the basic "orientation histogram" representation. Each orientation histogram divides the gradient angle range into a fixed number of predetermined bins. The gradient magnitudes of the pixels in the cell are used to vote into the orientation histogram. The fourth stage computes normalisation, which takes local groups of cells and contrast normalises their overall responses before passing to next stage. Normalisation introduces better invariance to illumination, shadowing, and edge contrast. It is performed by accumulating a measure of local histogram "energy" over local groups of cells that we call "blocks". The result is used to normalise each cell in the block. Typically each individual cell is shared between several blocks, but its normalisations are block dependent and thus different. The cell thus appears several times in the final output vector with different normalisations. This may seem redundant but it improves the performance. We refer to the normalised block descriptors as Histogram of Oriented Gradient (HOG) descriptors. The final step collects the HOG descriptors from all blocks of a dense overlapping grid of blocks covering the detection window into a combined feature vector for use in the window classifier. References ---------- .. [1] Dalal, N. and Triggs, B., "Histograms of Oriented Gradients for Human Detection," IEEE Computer Society Conference on Computer Vision and Pattern Recognition, 2005, San Diego, CA, USA. .. [2] David G. Lowe, "Distinctive image features from scale-invariant keypoints," International Journal of Computer Vision, 60, 2 (2004), pp. 91-110. """ import matplotlib.pyplot as plt from skimage.feature import hog from skimage import data, color, exposure image = color.rgb2gray(data.lena()) fd, hog_image = hog(image, orientations=8, pixels_per_cell=(16, 16), cells_per_block=(1, 1), visualise=True) plt.figure(figsize=(8, 4)) plt.subplot(121).set_axis_off() plt.imshow(image, cmap=plt.cm.gray) plt.title('Input image') # Rescale histogram for better display hog_image_rescaled = exposure.rescale_intensity(hog_image, in_range=(0, 0.02)) plt.subplot(122).set_axis_off() plt.imshow(hog_image_rescaled, cmap=plt.cm.gray) plt.title('Histogram of Oriented Gradients') plt.show() scikit-image-0.9.3/doc/examples/plot_holes_and_peaks.py000066400000000000000000000050521223313777300232150ustar00rootroot00000000000000""" =============================== Filling holes and finding peaks =============================== In this example, we fill holes (i.e. isolated, dark spots) in an image using morphological reconstruction by erosion. Erosion expands the minimal values of the seed image until it encounters a mask image. Thus, the seed image and mask image represent the maximum and minimum possible values of the reconstructed image. We start with an image containing both peaks and holes: """ import matplotlib.pyplot as plt from skimage import data from skimage.exposure import rescale_intensity image = data.moon() # Rescale image intensity so that we can see dim features. image = rescale_intensity(image, in_range=(50, 200)) # convenience function for plotting images def imshow(image, **kwargs): plt.figure(figsize=(5, 4)) plt.imshow(image, **kwargs) plt.axis('off') imshow(image) plt.title('original image') """ .. image:: PLOT2RST.current_figure Now we need to create the seed image, where the minima represent the starting points for erosion. To fill holes, we initialize the seed image to the maximum value of the original image. Along the borders, however, we use the original values of the image. These border pixels will be the starting points for the erosion process. We then limit the erosion by setting the mask to the values of the original image. """ import numpy as np from skimage.morphology import reconstruction seed = np.copy(image) seed[1:-1, 1:-1] = image.max() mask = image filled = reconstruction(seed, mask, method='erosion') imshow(filled, vmin=image.min(), vmax=image.max()) plt.title('after filling holes') """ .. image:: PLOT2RST.current_figure As shown above, eroding inward from the edges removes holes, since (by definition) holes are surrounded by pixels of brighter value. Finally, we can isolate the dark regions by subtracting the reconstructed image from the original image. """ imshow(image - filled) plt.title('holes') """ .. image:: PLOT2RST.current_figure Alternatively, we can find bright spots in an image using morphological reconstruction by dilation. Dilation is the inverse of erosion and expands the *maximal* values of the seed image until it encounters a mask image. Since this is an inverse operation, we initialize the seed image to the minimum image intensity instead of the maximum. The remainder of the process is the same. """ seed = np.copy(image) seed[1:-1, 1:-1] = image.min() rec = reconstruction(seed, mask, method='dilation') imshow(image - rec) plt.title('peaks') plt.show() """ .. image:: PLOT2RST.current_figure """ scikit-image-0.9.3/doc/examples/plot_ihc_color_separation.py000066400000000000000000000035701223313777300242670ustar00rootroot00000000000000""" ============================================== Immunohistochemical staining colors separation ============================================== In this example we separate the immunohistochemical (IHC) staining from the hematoxylin counterstaining. The separation is achieved with the method described in [1]_, known as "color deconvolution". The IHC staining expression of the FHL2 protein is here revealed with Diaminobenzidine (DAB) which gives a brown color. .. [1] A. C. Ruifrok and D. A. Johnston, "Quantification of histochemical staining by color deconvolution.," Analytical and quantitative cytology and histology / the International Academy of Cytology [and] American Society of Cytology, vol. 23, no. 4, pp. 291-9, Aug. 2001. """ import matplotlib.pyplot as plt from skimage import data from skimage.color import rgb2hed ihc_rgb = data.immunohistochemistry() ihc_hed = rgb2hed(ihc_rgb) fig, axes = plt.subplots(2, 2, figsize=(7, 6)) ax0, ax1, ax2, ax3 = axes.ravel() ax0.imshow(ihc_rgb) ax0.set_title("Original image") ax1.imshow(ihc_hed[:, :, 0], cmap=plt.cm.gray) ax1.set_title("Hematoxylin") ax2.imshow(ihc_hed[:, :, 1], cmap=plt.cm.gray) ax2.set_title("Eosin") ax3.imshow(ihc_hed[:, :, 2], cmap=plt.cm.gray) ax3.set_title("DAB") for ax in axes.ravel(): ax.axis('off') fig.subplots_adjust(hspace=0.3) """ .. image:: PLOT2RST.current_figure Now we can easily manipulate the hematoxylin and DAB "channels": """ import numpy as np from skimage.exposure import rescale_intensity # Rescale hematoxylin and DAB signals and give them a fluorescence look h = rescale_intensity(ihc_hed[:, :, 0], out_range=(0, 1)) d = rescale_intensity(ihc_hed[:, :, 2], out_range=(0, 1)) zdh = np.dstack((np.zeros_like(h), d, h)) plt.figure() plt.imshow(zdh) plt.title("Stain separated image (rescaled)") plt.axis('off') plt.show() """ .. image:: PLOT2RST.current_figure """ scikit-image-0.9.3/doc/examples/plot_join_segmentations.py000066400000000000000000000036541223313777300240030ustar00rootroot00000000000000""" ========================================== Find the intersection of two segmentations ========================================== When segmenting an image, you may want to combine multiple alternative segmentations. The `skimage.segmentation.join_segmentations` function computes the join of two segmentations, in which a pixel is placed in the same segment if and only if it is in the same segment in _both_ segmentations. """ import numpy as np from scipy import ndimage as nd import matplotlib.pyplot as plt from skimage.filter import sobel from skimage.segmentation import slic, join_segmentations from skimage.morphology import watershed from skimage.color import label2rgb from skimage import data, img_as_float coins = img_as_float(data.coins()) # make segmentation using edge-detection and watershed edges = sobel(coins) markers = np.zeros_like(coins) foreground, background = 1, 2 markers[coins < 30.0 / 255] = background markers[coins > 150.0 / 255] = foreground ws = watershed(edges, markers) seg1 = nd.label(ws == foreground)[0] # make segmentation using SLIC superpixels seg2 = slic(coins, n_segments=117, max_iter=160, sigma=1, compactness=0.75, multichannel=False) # combine the two segj = join_segmentations(seg1, seg2) # show the segmentations fig, axes = plt.subplots(ncols=4, figsize=(9, 2.5)) axes[0].imshow(coins, cmap=plt.cm.gray, interpolation='nearest') axes[0].set_title('Image') color1 = label2rgb(seg1, image=coins, bg_label=0) axes[1].imshow(color1, interpolation='nearest') axes[1].set_title('Sobel+Watershed') color2 = label2rgb(seg2, image=coins, image_alpha=0.5) axes[2].imshow(color2, interpolation='nearest') axes[2].set_title('SLIC superpixels') color3 = label2rgb(segj, image=coins, image_alpha=0.5) axes[3].imshow(color3, interpolation='nearest') axes[3].set_title('Join') for ax in axes: ax.axis('off') plt.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1) plt.show() scikit-image-0.9.3/doc/examples/plot_label.py000066400000000000000000000030371223313777300211560ustar00rootroot00000000000000""" =================== Label image regions =================== This example shows how to segment an image with image labelling. The following steps are applied: 1. Thresholding with automatic Otsu method 2. Close small holes with binary closing 3. Remove artifacts touching image border 4. Measure image regions to filter small objects """ import numpy as np import matplotlib.pyplot as plt import matplotlib.patches as mpatches from skimage import data from skimage.filter import threshold_otsu from skimage.segmentation import clear_border from skimage.morphology import label, closing, square from skimage.measure import regionprops from skimage.color import label2rgb image = data.coins()[50:-50, 50:-50] # apply threshold thresh = threshold_otsu(image) bw = closing(image > thresh, square(3)) # remove artifacts connected to image border cleared = bw.copy() clear_border(cleared) # label image regions label_image = label(cleared) borders = np.logical_xor(bw, cleared) label_image[borders] = -1 image_label_overlay = label2rgb(label_image, image=image) fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6)) ax.imshow(image_label_overlay) for region in regionprops(label_image, ['Area', 'BoundingBox']): # skip small images if region['Area'] < 100: continue # draw rectangle around segmented coins minr, minc, maxr, maxc = region['BoundingBox'] rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr, fill=False, edgecolor='red', linewidth=2) ax.add_patch(rect) plt.show() scikit-image-0.9.3/doc/examples/plot_line_hough_transform.py000066400000000000000000000104111223313777300243050ustar00rootroot00000000000000r""" ============================= Straight line Hough transform ============================= The Hough transform in its simplest form is a `method to detect straight lines `__. In the following example, we construct an image with a line intersection. We then use the Hough transform to explore a parameter space for straight lines that may run through the image. Algorithm overview ------------------ Usually, lines are parameterised as :math:`y = mx + c`, with a gradient :math:`m` and y-intercept `c`. However, this would mean that :math:`m` goes to infinity for vertical lines. Instead, we therefore construct a segment perpendicular to the line, leading to the origin. The line is represented by the length of that segment, :math:`r`, and the angle it makes with the x-axis, :math:`\theta`. The Hough transform constructs a histogram array representing the parameter space (i.e., an :math:`M \times N` matrix, for :math:`M` different values of the radius and :math:`N` different values of :math:`\theta`). For each parameter combination, :math:`r` and :math:`\theta`, we then find the number of non-zero pixels in the input image that would fall close to the corresponding line, and increment the array at position :math:`(r, \theta)` appropriately. We can think of each non-zero pixel "voting" for potential line candidates. The local maxima in the resulting histogram indicates the parameters of the most probably lines. In our example, the maxima occur at 45 and 135 degrees, corresponding to the normal vector angles of each line. Another approach is the Progressive Probabilistic Hough Transform [1]_. It is based on the assumption that using a random subset of voting points give a good approximation to the actual result, and that lines can be extracted during the voting process by walking along connected components. This returns the beginning and end of each line segment, which is useful. The function `probabilistic_hough` has three parameters: a general threshold that is applied to the Hough accumulator, a minimum line length and the line gap that influences line merging. In the example below, we find lines longer than 10 with a gap less than 3 pixels. References ---------- .. [1] C. Galamhos, J. Matas and J. Kittler,"Progressive probabilistic Hough transform for line detection", in IEEE Computer Society Conference on Computer Vision and Pattern Recognition, 1999. .. [2] Duda, R. O. and P. E. Hart, "Use of the Hough Transformation to Detect Lines and Curves in Pictures," Comm. ACM, Vol. 15, pp. 11-15 (January, 1972) """ from skimage.transform import (hough_line, hough_line_peaks, probabilistic_hough_line) from skimage.filter import canny from skimage import data import numpy as np import matplotlib.pyplot as plt # Construct test image image = np.zeros((100, 100)) # Classic straight-line Hough transform idx = np.arange(25, 75) image[idx[::-1], idx] = 255 image[idx, idx] = 255 h, theta, d = hough_line(image) plt.figure(figsize=(8, 4)) plt.subplot(131) plt.imshow(image, cmap=plt.cm.gray) plt.title('Input image') plt.subplot(132) plt.imshow(np.log(1 + h), extent=[np.rad2deg(theta[-1]), np.rad2deg(theta[0]), d[-1], d[0]], cmap=plt.cm.gray, aspect=1/1.5) plt.title('Hough transform') plt.xlabel('Angles (degrees)') plt.ylabel('Distance (pixels)') plt.subplot(133) plt.imshow(image, cmap=plt.cm.gray) rows, cols = image.shape for _, angle, dist in zip(*hough_line_peaks(h, theta, d)): y0 = (dist - 0 * np.cos(angle)) / np.sin(angle) y1 = (dist - cols * np.cos(angle)) / np.sin(angle) plt.plot((0, cols), (y0, y1), '-r') plt.axis((0, cols, rows, 0)) plt.title('Detected lines') # Line finding, using the Probabilistic Hough Transform image = data.camera() edges = canny(image, 2, 1, 25) lines = probabilistic_hough_line(edges, threshold=10, line_length=5, line_gap=3) plt.figure(figsize=(8, 3)) plt.subplot(131) plt.imshow(image, cmap=plt.cm.gray) plt.title('Input image') plt.subplot(132) plt.imshow(edges, cmap=plt.cm.gray) plt.title('Canny edges') plt.subplot(133) plt.imshow(edges * 0) for line in lines: p0, p1 = line plt.plot((p0[0], p1[0]), (p0[1], p1[1])) plt.title('Probabilistic Hough') plt.axis('image') plt.show() scikit-image-0.9.3/doc/examples/plot_local_binary_pattern.py000066400000000000000000000151661223313777300243000ustar00rootroot00000000000000""" =============================================== Local Binary Pattern for texture classification =============================================== In this example, we will see how to classify textures based on LBP (Local Binary Pattern). LBP looks at points surrounding a central point and tests whether the surrounding points are greater than or less than the central point (i.e. gives a binary result). Before trying out LBP on an image, it helps to look at a schematic of LBPs. The below code is just used to plot the schematic. """ from __future__ import print_function import numpy as np import matplotlib.pyplot as plt METHOD = 'uniform' plt.rcParams['font.size'] = 9 def plot_circle(ax, center, radius, color): circle = plt.Circle(center, radius, facecolor=color, edgecolor='0.5') ax.add_patch(circle) def plot_lbp_model(ax, binary_values): """Draw the schematic for a local binary pattern.""" # Geometry spec theta = np.deg2rad(45) R = 1 r = 0.15 w = 1.5 gray = '0.5' # Draw the central pixel. plot_circle(ax, (0, 0), radius=r, color=gray) # Draw the surrounding pixels. for i, facecolor in enumerate(binary_values): x = R * np.cos(i * theta) y = R * np.sin(i * theta) plot_circle(ax, (x, y), radius=r, color=str(facecolor)) # Draw the pixel grid. for x in np.linspace(-w, w, 4): ax.axvline(x, color=gray) ax.axhline(x, color=gray) # Tweak the layout. ax.axis('image') ax.axis('off') size = w + 0.2 ax.set_xlim(-size, size) ax.set_ylim(-size, size) fig, axes = plt.subplots(ncols=5, figsize=(7, 2)) titles = ['flat', 'flat', 'edge', 'corner', 'non-uniform'] binary_patterns = [np.zeros(8), np.ones(8), np.hstack([np.ones(4), np.zeros(4)]), np.hstack([np.zeros(3), np.ones(5)]), [1, 0, 0, 1, 1, 1, 0, 0]] for ax, values, name in zip(axes, binary_patterns, titles): plot_lbp_model(ax, values) ax.set_title(name) """ .. image:: PLOT2RST.current_figure The figure above shows example results with black (or white) representing pixels that are less (or more) intense than the central pixel. When surrounding pixels are all black or all white, then that image region is flat (i.e. featureless). Groups of continuous black or white pixels are considered "uniform" patterns that can be interpreted as corners or edges. If pixels switch back-and-forth between black and white pixels, the pattern is considered "non-uniform". When using LBP to detect texture, you measure a collection of LBPs over an image patch and look at the distribution of these LBPs. Lets apply LBP to a brick texture. """ from skimage.transform import rotate from skimage.feature import local_binary_pattern from skimage import data from skimage.color import label2rgb # settings for LBP radius = 3 n_points = 8 * radius def overlay_labels(image, lbp, labels): mask = np.logical_or.reduce([lbp == each for each in labels]) return label2rgb(mask, image=image, bg_label=0, alpha=0.5) def highlight_bars(bars, indexes): for i in indexes: bars[i].set_facecolor('r') image = data.load('brick.png') lbp = local_binary_pattern(image, n_points, radius, METHOD) def hist(ax, lbp): n_bins = lbp.max() + 1 return ax.hist(lbp.ravel(), normed=True, bins=n_bins, range=(0, n_bins), facecolor='0.5') # plot histograms of LBP of textures fig, (ax_img, ax_hist) = plt.subplots(nrows=2, ncols=3, figsize=(9, 6)) plt.gray() titles = ('edge', 'flat', 'corner') w = width = radius - 1 edge_labels = range(n_points // 2 - w, n_points // 2 + w + 1) flat_labels = list(range(0, w + 1)) + list(range(n_points - w, n_points + 2)) i_14 = n_points // 4 # 1/4th of the histogram i_34 = 3 * (n_points // 4) # 3/4th of the histogram corner_labels = (list(range(i_14 - w, i_14 + w + 1)) + list(range(i_34 - w, i_34 + w + 1))) label_sets = (edge_labels, flat_labels, corner_labels) for ax, labels in zip(ax_img, label_sets): ax.imshow(overlay_labels(image, lbp, labels)) for ax, labels, name in zip(ax_hist, label_sets, titles): counts, _, bars = hist(ax, lbp) highlight_bars(bars, labels) ax.set_ylim(ymax=np.max(counts[:-1])) ax.set_xlim(xmax=n_points + 2) ax.set_title(name) ax_hist[0].set_ylabel('Percentage') for ax in ax_img: ax.axis('off') """ .. image:: PLOT2RST.current_figure The above plot highlights flat, edge-like, and corner-like regions of the image. The histogram of the LBP result is a good measure to classify textures. Here, we test the histogram distributions against each other using the Kullback-Leibler-Divergence. """ # settings for LBP radius = 2 n_points = 8 * radius def kullback_leibler_divergence(p, q): p = np.asarray(p) q = np.asarray(q) filt = np.logical_and(p != 0, q != 0) return np.sum(p[filt] * np.log2(p[filt] / q[filt])) def match(refs, img): best_score = 10 best_name = None lbp = local_binary_pattern(img, n_points, radius, METHOD) n_bins = lbp.max() + 1 hist, _ = np.histogram(lbp, normed=True, bins=n_bins, range=(0, n_bins)) for name, ref in refs.items(): ref_hist, _ = np.histogram(ref, normed=True, bins=n_bins, range=(0, n_bins)) score = kullback_leibler_divergence(hist, ref_hist) if score < best_score: best_score = score best_name = name return best_name brick = data.load('brick.png') grass = data.load('grass.png') wall = data.load('rough-wall.png') refs = { 'brick': local_binary_pattern(brick, n_points, radius, METHOD), 'grass': local_binary_pattern(grass, n_points, radius, METHOD), 'wall': local_binary_pattern(wall, n_points, radius, METHOD) } # classify rotated textures print('Rotated images matched against references using LBP:') print('original: brick, rotated: 30deg, match result: ', match(refs, rotate(brick, angle=30, resize=False))) print('original: brick, rotated: 70deg, match result: ', match(refs, rotate(brick, angle=70, resize=False))) print('original: grass, rotated: 145deg, match result: ', match(refs, rotate(grass, angle=145, resize=False))) # plot histograms of LBP of textures fig, ((ax1, ax2, ax3), (ax4, ax5, ax6)) = plt.subplots(nrows=2, ncols=3, figsize=(9, 6)) plt.gray() ax1.imshow(brick) ax1.axis('off') hist(ax4, refs['brick']) ax4.set_ylabel('Percentage') ax2.imshow(grass) ax2.axis('off') hist(ax5, refs['grass']) ax5.set_xlabel('Uniform LBP values') ax3.imshow(wall) ax3.axis('off') hist(ax6, refs['wall']) """ .. image:: PLOT2RST.current_figure """ plt.show() scikit-image-0.9.3/doc/examples/plot_local_equalize.py000066400000000000000000000045201223313777300230660ustar00rootroot00000000000000""" ============================ Local Histogram Equalization ============================ This examples enhances an image with low contrast, using a method called *local histogram equalization*, which spreads out the most frequent intensity values in an image. The equalized image [1]_ has a roughly linear cumulative distribution function for each pixel neighborhood. The local version [2]_ of the histogram equalization emphasized every local graylevel variations. References ---------- .. [1] http://en.wikipedia.org/wiki/Histogram_equalization .. [2] http://en.wikipedia.org/wiki/Adaptive_histogram_equalization """ import numpy as np import matplotlib.pyplot as plt from skimage import data from skimage.util.dtype import dtype_range from skimage.util import img_as_ubyte from skimage import exposure from skimage.morphology import disk from skimage.filter import rank def plot_img_and_hist(img, axes, bins=256): """Plot an image along with its histogram and cumulative histogram. """ ax_img, ax_hist = axes ax_cdf = ax_hist.twinx() # Display image ax_img.imshow(img, cmap=plt.cm.gray) ax_img.set_axis_off() # Display histogram ax_hist.hist(img.ravel(), bins=bins) ax_hist.ticklabel_format(axis='y', style='scientific', scilimits=(0, 0)) ax_hist.set_xlabel('Pixel intensity') xmin, xmax = dtype_range[img.dtype.type] ax_hist.set_xlim(xmin, xmax) # Display cumulative distribution img_cdf, bins = exposure.cumulative_distribution(img, bins) ax_cdf.plot(bins, img_cdf, 'r') return ax_img, ax_hist, ax_cdf # Load an example image img = img_as_ubyte(data.moon()) # Contrast stretching p2 = np.percentile(img, 2) p98 = np.percentile(img, 98) img_rescale = exposure.equalize_hist(img) # Equalization selem = disk(30) img_eq = rank.equalize(img, selem=selem) # Display results f, axes = plt.subplots(2, 3, figsize=(8, 4)) ax_img, ax_hist, ax_cdf = plot_img_and_hist(img, axes[:, 0]) ax_img.set_title('Low contrast image') ax_hist.set_ylabel('Number of pixels') ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_rescale, axes[:, 1]) ax_img.set_title('Global equalise') ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_eq, axes[:, 2]) ax_img.set_title('Local equalize') ax_cdf.set_ylabel('Fraction of total intensity') # prevent overlap of y-axis labels plt.subplots_adjust(wspace=0.4) plt.show() scikit-image-0.9.3/doc/examples/plot_local_otsu.py000066400000000000000000000024341223313777300222430ustar00rootroot00000000000000""" ==================== Local Otsu Threshold ==================== This example shows how Otsu's threshold [1]_ method can be applied locally. For each pixel, an "optimal" threshold is determined by maximizing the variance between two classes of pixels of the local neighborhood defined by a structuring element. The example compares the local threshold with the global threshold. .. note: local is much slower than global thresholding .. [1] http://en.wikipedia.org/wiki/Otsu's_method """ import matplotlib.pyplot as plt from skimage import data from skimage.morphology import disk from skimage.filter import threshold_otsu, rank from skimage.util import img_as_ubyte p8 = img_as_ubyte(data.page()) radius = 10 selem = disk(radius) loc_otsu = rank.otsu(p8, selem) t_glob_otsu = threshold_otsu(p8) glob_otsu = p8 >= t_glob_otsu plt.figure() plt.subplot(2, 2, 1) plt.imshow(p8, cmap=plt.cm.gray) plt.xlabel('original') plt.colorbar() plt.subplot(2, 2, 2) plt.imshow(loc_otsu, cmap=plt.cm.gray) plt.xlabel('local Otsu ($radius=%d$)' % radius) plt.colorbar() plt.subplot(2, 2, 3) plt.imshow(p8 >= loc_otsu, cmap=plt.cm.gray) plt.xlabel('original >= local Otsu' % t_glob_otsu) plt.subplot(2, 2, 4) plt.imshow(glob_otsu, cmap=plt.cm.gray) plt.xlabel('global Otsu ($t = %d$)' % t_glob_otsu) plt.show() scikit-image-0.9.3/doc/examples/plot_marching_cubes.py000066400000000000000000000040031223313777300230420ustar00rootroot00000000000000""" ============== Marching Cubes ============== Marching cubes is an algorithm to extract a 2D surface mesh from a 3D volume. This can be conceptualized as a 3D generalization of isolines on topographical or weather maps. It works by iterating across the volume, looking for regions which cross the level of interest. If such regions are found, triangulations are generated and added to an output mesh. The final result is a set of vertices and a set of triangular faces. The algorithm requires a data volume and an isosurface value. For example, in CT imaging Hounsfield units of +700 to +3000 represent bone. So, one potential input would be a reconstructed CT set of data and the value +700, to extract a mesh for regions of bone or bone-like density. This implementation also works correctly on anisotropic datasets, where the voxel spacing is not equal for every spatial dimension, through use of the `spacing` kwarg. """ import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d.art3d import Poly3DCollection from skimage import measure from skimage.draw import ellipsoid # Generate a level set about zero of two identical ellipsoids in 3D ellip_base = ellipsoid(6, 10, 16, levelset=True) ellip_double = np.concatenate((ellip_base[:-1, ...], ellip_base[2:, ...]), axis=0) # Use marching cubes to obtain the surface mesh of these ellipsoids verts, faces = measure.marching_cubes(ellip_double, 0) # Display resulting triangular mesh using Matplotlib. This can also be done # with mayavi (see skimage.measure.marching_cubes docstring). fig = plt.figure(figsize=(10, 12)) ax = fig.add_subplot(111, projection='3d') # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh = Poly3DCollection(verts[faces]) ax.add_collection3d(mesh) ax.set_xlabel("x-axis: a = 6 per ellipsoid") ax.set_ylabel("y-axis: b = 10") ax.set_zlabel("z-axis: c = 16") ax.set_xlim(0, 24) # a = 6 (times two for 2nd ellipsoid) ax.set_ylim(0, 20) # b = 10 ax.set_zlim(0, 32) # c = 16 plt.show() scikit-image-0.9.3/doc/examples/plot_marked_watershed.py000066400000000000000000000030141223313777300234030ustar00rootroot00000000000000""" =============================== Markers for watershed transform =============================== The watershed is a classical algorithm used for **segmentation**, that is, for separating different objects in an image. Here a marker image is build from the region of low gradient inside the image. See Wikipedia_ for more details on the algorithm. .. _Wikipedia: http://en.wikipedia.org/wiki/Watershed_(image_processing) """ from scipy import ndimage import matplotlib.pyplot as plt from skimage.morphology import watershed, disk from skimage import data from skimage.filter import rank from skimage.util import img_as_ubyte image = img_as_ubyte(data.camera()) # denoise image denoised = rank.median(image, disk(2)) # find continuous region (low gradient) --> markers markers = rank.gradient(denoised, disk(5)) < 10 markers = ndimage.label(markers)[0] #local gradient gradient = rank.gradient(denoised, disk(2)) # process the watershed labels = watershed(gradient, markers) # display results fig, axes = plt.subplots(ncols=4, figsize=(8, 2.7)) ax0, ax1, ax2, ax3 = axes ax0.imshow(image, cmap=plt.cm.gray, interpolation='nearest') ax1.imshow(gradient, cmap=plt.cm.spectral, interpolation='nearest') ax2.imshow(markers, cmap=plt.cm.spectral, interpolation='nearest') ax3.imshow(image, cmap=plt.cm.gray, interpolation='nearest') ax3.imshow(labels, cmap=plt.cm.spectral, interpolation='nearest', alpha=.7) for ax in axes: ax.axis('off') plt.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1) plt.show() scikit-image-0.9.3/doc/examples/plot_matching.py000066400000000000000000000122441223313777300216710ustar00rootroot00000000000000""" ============================ Robust matching using RANSAC ============================ In this simplified example we first generate two synthetic images as if they were taken from different view points. In the next step we find interest points in both images and find correspondences based on a weighted sum of squared differences of a small neighborhood around them. Note, that this measure is only robust towards linear radiometric and not geometric distortions and is thus only usable with slight view point changes. After finding the correspondences we end up having a set of source and destination coordinates which can be used to estimate the geometric transformation between both images. However, many of the correspondences are faulty and simply estimating the parameter set with all coordinates is not sufficient. Therefore, the RANSAC algorithm is used on top of the normal model to robustly estimate the parameter set by detecting outliers. """ from __future__ import print_function import numpy as np from matplotlib import pyplot as plt from skimage import data from skimage.util import img_as_float from skimage.feature import corner_harris, corner_subpix, corner_peaks from skimage.transform import warp, AffineTransform from skimage.exposure import rescale_intensity from skimage.color import rgb2gray from skimage.measure import ransac # generate synthetic checkerboard image and add gradient for the later matching checkerboard = img_as_float(data.checkerboard()) img_orig = np.zeros(list(checkerboard.shape) + [3]) img_orig[..., 0] = checkerboard gradient_r, gradient_c = np.mgrid[0:img_orig.shape[0], 0:img_orig.shape[1]] / float(img_orig.shape[0]) img_orig[..., 1] = gradient_r img_orig[..., 2] = gradient_c img_orig = rescale_intensity(img_orig) img_orig_gray = rgb2gray(img_orig) # warp synthetic image tform = AffineTransform(scale=(0.9, 0.9), rotation=0.2, translation=(20, -10)) img_warped = warp(img_orig, tform.inverse, output_shape=(200, 200)) img_warped_gray = rgb2gray(img_warped) # extract corners using Harris' corner measure coords_orig = corner_peaks(corner_harris(img_orig_gray), threshold_rel=0.001, min_distance=5) coords_warped = corner_peaks(corner_harris(img_warped_gray), threshold_rel=0.001, min_distance=5) # determine sub-pixel corner position coords_orig_subpix = corner_subpix(img_orig_gray, coords_orig, window_size=9) coords_warped_subpix = corner_subpix(img_warped_gray, coords_warped, window_size=9) def gaussian_weights(window_ext, sigma=1): y, x = np.mgrid[-window_ext:window_ext+1, -window_ext:window_ext+1] g = np.zeros(y.shape, dtype=np.double) g[:] = np.exp(-0.5 * (x**2 / sigma**2 + y**2 / sigma**2)) g /= 2 * np.pi * sigma * sigma return g def match_corner(coord, window_ext=5): r, c = np.round(coord) window_orig = img_orig[r-window_ext:r+window_ext+1, c-window_ext:c+window_ext+1, :] # weight pixels depending on distance to center pixel weights = gaussian_weights(window_ext, 3) weights = np.dstack((weights, weights, weights)) # compute sum of squared differences to all corners in warped image SSDs = [] for cr, cc in coords_warped: window_warped = img_warped[cr-window_ext:cr+window_ext+1, cc-window_ext:cc+window_ext+1, :] SSD = np.sum(weights * (window_orig - window_warped)**2) SSDs.append(SSD) # use corner with minimum SSD as correspondence min_idx = np.argmin(SSDs) return coords_warped_subpix[min_idx] # find correspondences using simple weighted sum of squared differences src = [] dst = [] for coord in coords_orig_subpix: src.append(coord) dst.append(match_corner(coord)) src = np.array(src) dst = np.array(dst) # estimate affine transform model using all coordinates model = AffineTransform() model.estimate(src, dst) # robustly estimate affine transform model with RANSAC model_robust, inliers = ransac((src, dst), AffineTransform, min_samples=3, residual_threshold=2, max_trials=100) outliers = inliers == False # compare "true" and estimated transform parameters print(tform.scale, tform.translation, tform.rotation) print(model.scale, model.translation, model.rotation) print(model_robust.scale, model_robust.translation, model_robust.rotation) # visualize correspondences img_combined = np.concatenate((img_orig_gray, img_warped_gray), axis=1) fig, ax = plt.subplots(nrows=2, ncols=1) plt.gray() ax[0].imshow(img_combined, interpolation='nearest') ax[0].axis('off') ax[0].axis((0, 400, 200, 0)) ax[0].set_title('Correct correspondences') ax[1].imshow(img_combined, interpolation='nearest') ax[1].axis('off') ax[1].axis((0, 400, 200, 0)) ax[1].set_title('Faulty correspondences') for ax_idx, (m, color) in enumerate(((inliers, 'g'), (outliers, 'r'))): ax[ax_idx].plot((src[m, 1], dst[m, 1] + 200), (src[m, 0], dst[m, 0]), '-', color=color) ax[ax_idx].plot(src[m, 1], src[m, 0], '.', markersize=10, color=color) ax[ax_idx].plot(dst[m, 1] + 200, dst[m, 0], '.', markersize=10, color=color) plt.show() scikit-image-0.9.3/doc/examples/plot_medial_transform.py000066400000000000000000000043511223313777300234250ustar00rootroot00000000000000""" =========================== Medial axis skeletonization =========================== The medial axis of an object is the set of all points having more than one closest point on the object's boundary. It is often called the **topological skeleton**, because it is a 1-pixel wide skeleton of the object, with the same connectivity as the original object. Here, we use the medial axis transform to compute the width of the foreground objects. As the function ``medial_axis`` (``skimage.morphology.medial_axis``) returns the distance transform in addition to the medial axis (with the keyword argument ``return_distance=True``), it is possible to compute the distance to the background for all points of the medial axis with this function. This gives an estimate of the local width of the objects. For a skeleton with fewer branches, there exists another skeletonization algorithm in ``skimage``: ``skimage.morphology.skeletonize``, that computes a skeleton by iterative morphological thinnings. """ import numpy as np from scipy import ndimage from skimage.morphology import medial_axis import matplotlib.pyplot as plt def microstructure(l=256): """ Synthetic binary data: binary microstructure with blobs. Parameters ---------- l: int, optional linear size of the returned image """ n = 5 x, y = np.ogrid[0:l, 0:l] mask_outer = (x - l/2)**2 + (y - l/2)**2 < (l/2)**2 mask = np.zeros((l, l)) generator = np.random.RandomState(1) points = l * generator.rand(2, n**2) mask[(points[0]).astype(np.int), (points[1]).astype(np.int)] = 1 mask = ndimage.gaussian_filter(mask, sigma=l/(4.*n)) return mask > mask.mean() data = microstructure(l=64) # Compute the medial axis (skeleton) and the distance transform skel, distance = medial_axis(data, return_distance=True) # Distance to the background for pixels of the skeleton dist_on_skel = distance * skel plt.figure(figsize=(8, 4)) plt.subplot(121) plt.imshow(data, cmap=plt.cm.gray, interpolation='nearest') plt.axis('off') plt.subplot(122) plt.imshow(dist_on_skel, cmap=plt.cm.spectral, interpolation='nearest') plt.contour(data, [0.5], colors='w') plt.axis('off') plt.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1) plt.show() scikit-image-0.9.3/doc/examples/plot_otsu.py000066400000000000000000000017431223313777300210730ustar00rootroot00000000000000""" ============ Thresholding ============ Thresholding is used to create a binary image. This example uses Otsu's method to calculate the threshold value. Otsu's method calculates an "optimal" threshold (marked by a red line in the histogram below) by maximizing the variance between two classes of pixels, which are separated by the threshold. Equivalently, this threshold minimizes the intra-class variance. .. [1] http://en.wikipedia.org/wiki/Otsu's_method """ import matplotlib.pyplot as plt from skimage.data import camera from skimage.filter import threshold_otsu image = camera() thresh = threshold_otsu(image) binary = image > thresh plt.figure(figsize=(8, 2.5)) plt.subplot(1, 3, 1) plt.imshow(image, cmap=plt.cm.gray) plt.title('Original') plt.axis('off') plt.subplot(1, 3, 2, aspect='equal') plt.hist(image) plt.title('Histogram') plt.axvline(thresh, color='r') plt.subplot(1, 3, 3) plt.imshow(binary, cmap=plt.cm.gray) plt.title('Thresholded') plt.axis('off') plt.show() scikit-image-0.9.3/doc/examples/plot_peak_local_max.py000066400000000000000000000026601223313777300230370ustar00rootroot00000000000000""" ==================== Finding local maxima ==================== The ``peak_local_max`` function returns the coordinates of local peaks (maxima) in an image. A maximum filter is used for finding local maxima. This operation dilates the original image and merges neighboring local maxima closer than the size of the dilation. Locations where the original image is equal to the dilated image are returned as local maxima. """ from scipy import ndimage import matplotlib.pyplot as plt from skimage.feature import peak_local_max from skimage import data, img_as_float im = img_as_float(data.coins()) # image_max is the dilation of im with a 20*20 structuring element # It is used within peak_local_max function image_max = ndimage.maximum_filter(im, size=20, mode='constant') # Comparison between image_max and im to find the coordinates of local maxima coordinates = peak_local_max(im, min_distance=20) # display results plt.figure(figsize=(8, 3)) plt.subplot(131) plt.imshow(im, cmap=plt.cm.gray) plt.axis('off') plt.title('Original') plt.subplot(132) plt.imshow(image_max, cmap=plt.cm.gray) plt.axis('off') plt.title('Maximum filter') plt.subplot(133) plt.imshow(im, cmap=plt.cm.gray) plt.autoscale(False) plt.plot([p[1] for p in coordinates], [p[0] for p in coordinates], 'r.') plt.axis('off') plt.title('Peak local max') plt.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9, bottom=0.02, left=0.02, right=0.98) plt.show() scikit-image-0.9.3/doc/examples/plot_piecewise_affine.py000066400000000000000000000020741223313777300233640ustar00rootroot00000000000000""" =============================== Piecewise Affine Transformation =============================== This example shows how to use the Piecewise Affine Transformation. """ import numpy as np import matplotlib.pyplot as plt from skimage.transform import PiecewiseAffineTransform, warp from skimage import data image = data.lena() rows, cols = image.shape[0], image.shape[1] src_cols = np.linspace(0, cols, 20) src_rows = np.linspace(0, rows, 10) src_rows, src_cols = np.meshgrid(src_rows, src_cols) src = np.dstack([src_cols.flat, src_rows.flat])[0] # add sinusoidal oscillation to row coordinates dst_rows = src[:, 1] - np.sin(np.linspace(0, 3 * np.pi, src.shape[0])) * 50 dst_cols = src[:, 0] dst_rows *= 1.5 dst_rows -= 1.5 * 50 dst = np.vstack([dst_cols, dst_rows]).T tform = PiecewiseAffineTransform() tform.estimate(src, dst) out_rows = image.shape[0] - 1.5 * 50 out_cols = cols out = warp(image, tform, output_shape=(out_rows, out_cols)) plt.imshow(out) plt.plot(tform.inverse(src)[:, 0], tform.inverse(src)[:, 1], '.b') plt.axis((0, out_cols, out_rows, 0)) plt.show() scikit-image-0.9.3/doc/examples/plot_polygon.py000066400000000000000000000050451223313777300215670ustar00rootroot00000000000000""" ================================== Approximate and subdivide polygons ================================== This example shows how to approximate (Douglas-Peucker algorithm) and subdivide (B-Splines) polygonal chains. """ from __future__ import print_function import numpy as np import matplotlib.pyplot as plt from skimage.draw import ellipse from skimage.measure import find_contours, approximate_polygon, \ subdivide_polygon hand = np.array([[1.64516129, 1.16145833], [1.64516129, 1.59375 ], [1.35080645, 1.921875 ], [1.375 , 2.18229167], [1.68548387, 1.9375 ], [1.60887097, 2.55208333], [1.68548387, 2.69791667], [1.76209677, 2.56770833], [1.83064516, 1.97395833], [1.89516129, 2.75 ], [1.9516129 , 2.84895833], [2.01209677, 2.76041667], [1.99193548, 1.99479167], [2.11290323, 2.63020833], [2.2016129 , 2.734375 ], [2.25403226, 2.60416667], [2.14919355, 1.953125 ], [2.30645161, 2.36979167], [2.39112903, 2.36979167], [2.41532258, 2.1875 ], [2.1733871 , 1.703125 ], [2.07782258, 1.16666667]]) # subdivide polygon using 2nd degree B-Splines new_hand = hand.copy() for _ in range(5): new_hand = subdivide_polygon(new_hand, degree=2, preserve_ends=True) # approximate subdivided polygon with Douglas-Peucker algorithm appr_hand = approximate_polygon(new_hand, tolerance=0.02) print("Number of coordinates:", len(hand), len(new_hand), len(appr_hand)) fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(9, 4)) ax1.plot(hand[:, 0], hand[:, 1]) ax1.plot(new_hand[:, 0], new_hand[:, 1]) ax1.plot(appr_hand[:, 0], appr_hand[:, 1]) # create two ellipses in image img = np.zeros((800, 800), 'int32') rr, cc = ellipse(250, 250, 180, 230, img.shape) img[rr, cc] = 1 rr, cc = ellipse(600, 600, 150, 90, img.shape) img[rr, cc] = 1 plt.gray() ax2.imshow(img) # approximate / simplify coordinates of the two ellipses for contour in find_contours(img, 0): coords = approximate_polygon(contour, tolerance=2.5) ax2.plot(coords[:, 1], coords[:, 0], '-r', linewidth=2) coords2 = approximate_polygon(contour, tolerance=39.5) ax2.plot(coords2[:, 1], coords2[:, 0], '-g', linewidth=2) print("Number of coordinates:", len(contour), len(coords), len(coords2)) ax2.axis((0, 800, 0, 800)) plt.show() scikit-image-0.9.3/doc/examples/plot_pyramid.py000066400000000000000000000015321223313777300215420ustar00rootroot00000000000000""" ==================== Build image pyramids ==================== The `pyramid_gaussian` function takes an image and yields successive images shrunk by a constant scale factor. Image pyramids are often used, e.g., to implement algorithms for denoising, texture discrimination, and scale- invariant detection. """ import numpy as np import matplotlib.pyplot as plt from skimage import data from skimage.transform import pyramid_gaussian image = data.lena() rows, cols, dim = image.shape pyramid = tuple(pyramid_gaussian(image, downscale=2)) composite_image = np.zeros((rows, cols + cols / 2, 3), dtype=np.double) composite_image[:rows, :cols, :] = pyramid[0] i_row = 0 for p in pyramid[1:]: n_rows, n_cols = p.shape[:2] composite_image[i_row:i_row + n_rows, cols:cols + n_cols] = p i_row += n_rows plt.imshow(composite_image) plt.show() scikit-image-0.9.3/doc/examples/plot_radon_transform.py000066400000000000000000000202741223313777300232770ustar00rootroot00000000000000""" =============== Radon transform =============== In computed tomography, the tomography reconstruction problem is to obtain a tomographic slice image from a set of projections [1]_. A projection is formed by drawing a set of parallel rays through the 2D object of interest, assigning the integral of the object's contrast along each ray to a single pixel in the projection. A single projection of a 2D object is one dimensional. To enable computed tomography reconstruction of the object, several projections must be acquired, each of them corresponding to a different angle between the rays with respect to the object. A collection of projections at several angles is called a sinogram, which is a linear transform of the original image. The inverse Radon transform is used in computed tomography to reconstruct a 2D image from the measured projections (the sinogram). A practical, exact implementation of the inverse Radon transform does not exist, but there are several good approximate algorithms available. As the inverse Radon transform reconstructs the object from a set of projections, the (forward) Radon transform can be used to simulate a tomography experiment. This script performs the Radon transform to simulate a tomography experiment and reconstructs the input image based on the resulting sinogram formed by the simulation. Two methods for performing the inverse Radon transform and reconstructing the original image are compared: The Filtered Back Projection (FBP) and the Simultaneous Algebraic Reconstruction Technique (SART). .. seealso:: - AC Kak, M Slaney, "Principles of Computerized Tomographic Imaging", http://www.slaney.org/pct/pct-toc.html - http://en.wikipedia.org/wiki/Radon_transform The forward transform ===================== As our original image, we will use the Shepp-Logan phantom. When calculating the Radon transform, we need to decide how many projection angles we wish to use. As a rule of thumb, the number of projections should be about the same as the number of pixels there are across the object (to see why this is so, consider how many unknown pixel values must be determined in the reconstruction process and compare this to the number of measurements provided by the projections), and we follow that rule here. Below is the original image and its Radon transform, often known as its _sinogram_: """ from __future__ import print_function, division import numpy as np import matplotlib.pyplot as plt from skimage.io import imread from skimage import data_dir from skimage.transform import radon, rescale image = imread(data_dir + "/phantom.png", as_grey=True) image = rescale(image, scale=0.4) plt.figure(figsize=(8, 4.5)) plt.subplot(121) plt.title("Original") plt.imshow(image, cmap=plt.cm.Greys_r) theta = np.linspace(0., 180., max(image.shape), endpoint=True) sinogram = radon(image, theta=theta, circle=True) plt.subplot(122) plt.title("Radon transform\n(Sinogram)") plt.xlabel("Projection angle (deg)") plt.ylabel("Projection position (pixels)") plt.imshow(sinogram, cmap=plt.cm.Greys_r, extent=(0, 180, 0, sinogram.shape[0]), aspect='auto') plt.subplots_adjust(hspace=0.4, wspace=0.5) plt.show() """ .. image:: PLOT2RST.current_figure Reconstruction with the Filtered Back Projection (FBP) ====================================================== The mathematical foundation of the filtered back projection is the Fourier slice theorem [2]_. It uses Fourier transform of the projection and interpolation in Fourier space to obtain the 2D Fourier transform of the image, which is then inverted to form the reconstructed image. The filtered back projection is among the fastest methods of performing the inverse Radon transform. The only tunable parameter for the FBP is the filter, which is applied to the Fourier transformed projections. It may be used to suppress high frequency noise in the reconstruction. ``skimage`` provides a few different options for the filter. """ from skimage.transform import iradon reconstruction_fbp = iradon(sinogram, theta=theta, circle=True) error = reconstruction_fbp - image print('FBP rms reconstruction error: %.3g' % np.sqrt(np.mean(error**2))) imkwargs = dict(vmin=-0.2, vmax=0.2) plt.figure(figsize=(8, 4.5)) plt.subplot(121) plt.title("Reconstruction\nFiltered back projection") plt.imshow(reconstruction_fbp, cmap=plt.cm.Greys_r) plt.subplot(122) plt.title("Reconstruction error\nFiltered back projection") plt.imshow(reconstruction_fbp - image, cmap=plt.cm.Greys_r, **imkwargs) plt.show() """ .. image:: PLOT2RST.current_figure Reconstruction with the Simultaneous Algebraic Reconstruction Technique ======================================================================= Algebraic reconstruction techniques for tomography are based on a straightforward idea: for a pixelated image the value of a single ray in a particular projection is simply a sum of all the pixels the ray passes through on its way through the object. This is a way of expressing the forward Radon transform. The inverse Radon transform can then be formulated as a (large) set of linear equations. As each ray passes through a small fraction of the pixels in the image, this set of equations is sparse, allowing iterative solvers for sparse linear systems to tackle the system of equations. One iterative method has been particularly popular, namely Kaczmarz' method [3]_, which has the property that the solution will approach a least-squares solution of the equation set. The combination of the formulation of the reconstruction problem as a set of linear equations and an iterative solver makes algebraic techniques relatively flexible, hence some forms of prior knowledge can be incorporated with relative ease. ``skimage`` provides one of the more popular variations of the algebraic reconstruction techniques: the Simultaneous Algebraic Reconstruction Technique (SART) [1]_ [4]_. It uses Kaczmarz' method [3]_ as the iterative solver. A good reconstruction is normally obtained in a single iteration, making the method computationally effective. Running one or more extra iterations will normally improve the reconstruction of sharp, high frequency features and reduce the mean squared error at the expense of increased high frequency noise (the user will need to decide on what number of iterations is best suited to the problem at hand. The implementation in ``skimage`` allows prior information of the form of a lower and upper threshold on the reconstructed values to be supplied to the reconstruction. """ from skimage.transform import iradon_sart reconstruction_sart = iradon_sart(sinogram, theta=theta) error = reconstruction_sart - image print('SART (1 iteration) rms reconstruction error: %.3g' % np.sqrt(np.mean(error**2))) plt.figure(figsize=(8, 8.5)) plt.subplot(221) plt.title("Reconstruction\nSART") plt.imshow(reconstruction_sart, cmap=plt.cm.Greys_r) plt.subplot(222) plt.title("Reconstruction error\nSART") plt.imshow(reconstruction_sart - image, cmap=plt.cm.Greys_r, **imkwargs) # Run a second iteration of SART by supplying the reconstruction # from the first iteration as an initial estimate reconstruction_sart2 = iradon_sart(sinogram, theta=theta, image=reconstruction_sart) error = reconstruction_sart2 - image print('SART (2 iterations) rms reconstruction error: %.3g' % np.sqrt(np.mean(error**2))) plt.subplot(223) plt.title("Reconstruction\nSART, 2 iterations") plt.imshow(reconstruction_sart2, cmap=plt.cm.Greys_r) plt.subplot(224) plt.title("Reconstruction error\nSART, 2 iterations") plt.imshow(reconstruction_sart2 - image, cmap=plt.cm.Greys_r, **imkwargs) plt.show() """ .. image:: PLOT2RST.current_figure .. [1] AC Kak, M Slaney, "Principles of Computerized Tomographic Imaging", IEEE Press 1988. http://www.slaney.org/pct/pct-toc.html .. [2] Wikipedia, Radon transform, http://en.wikipedia.org/wiki/Radon_transform#Relationship_with_the_Fourier_transform .. [3] S Kaczmarz, "Angenaeherte Aufloesung von Systemen linearer Gleichungen", Bulletin International de l'Academie Polonaise des Sciences et des Lettres 35 pp 355--357 (1937) .. [4] AH Andersen, AC Kak, "Simultaneous algebraic reconstruction technique (SART): a superior implementation of the ART algorithm", Ultrasonic Imaging 6 pp 81--94 (1984) """ scikit-image-0.9.3/doc/examples/plot_random_walker_segmentation.py000066400000000000000000000046451223313777300255070ustar00rootroot00000000000000""" ========================== Random walker segmentation ========================== The random walker algorithm [1]_ determines the segmentation of an image from a set of markers labeling several phases (2 or more). An anisotropic diffusion equation is solved with tracers initiated at the markers' position. The local diffusivity coefficient is greater if neighboring pixels have similar values, so that diffusion is difficult across high gradients. The label of each unknown pixel is attributed to the label of the known marker that has the highest probability to be reached first during this diffusion process. In this example, two phases are clearly visible, but the data are too noisy to perform the segmentation from the histogram only. We determine markers of the two phases from the extreme tails of the histogram of gray values, and use the random walker for the segmentation. .. [1] *Random walks for image segmentation*, Leo Grady, IEEE Trans. Pattern Anal. Mach. Intell. 2006 Nov; 28(11):1768-83 """ import numpy as np from scipy import ndimage import matplotlib.pyplot as plt from skimage.segmentation import random_walker def microstructure(l=256): """ Synthetic binary data: binary microstructure with blobs. Parameters ---------- l: int, optional linear size of the returned image """ n = 5 x, y = np.ogrid[0:l, 0:l] mask = np.zeros((l, l)) generator = np.random.RandomState(1) points = l * generator.rand(2, n ** 2) mask[(points[0]).astype(np.int), (points[1]).astype(np.int)] = 1 mask = ndimage.gaussian_filter(mask, sigma=l / (4. * n)) return (mask > mask.mean()).astype(np.float) # Generate noisy synthetic data data = microstructure(l=128) data += 0.35 * np.random.randn(*data.shape) markers = np.zeros(data.shape, dtype=np.uint) markers[data < -0.3] = 1 markers[data > 1.3] = 2 # Run random walker algorithm labels = random_walker(data, markers, beta=10, mode='bf') # Plot results plt.figure(figsize=(8, 3.2)) plt.subplot(131) plt.imshow(data, cmap='gray', interpolation='nearest') plt.axis('off') plt.title('Noisy data') plt.subplot(132) plt.imshow(markers, cmap='hot', interpolation='nearest') plt.axis('off') plt.title('Markers') plt.subplot(133) plt.imshow(labels, cmap='gray', interpolation='nearest') plt.axis('off') plt.title('Segmentation') plt.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1) plt.show() scikit-image-0.9.3/doc/examples/plot_rank_mean.py000066400000000000000000000027321223313777300220330ustar00rootroot00000000000000""" ============ Mean filters ============ This example compares the following mean filters of the rank filter package: * **local mean**: all pixels belonging to the structuring element to compute average gray level. * **percentile mean**: only use values between percentiles p0 and p1 (here 10% and 90%). * **bilateral mean**: only use pixels of the structuring element having a gray level situated inside g-s0 and g+s1 (here g-500 and g+500) Percentile and usual mean give here similar results, these filters smooth the complete image (background and details). Bilateral mean exhibits a high filtering rate for continuous area (i.e. background) while higher image frequencies remain untouched. """ import numpy as np import matplotlib.pyplot as plt from skimage import data from skimage.morphology import disk from skimage.filter import rank image = (data.coins()).astype(np.uint16) * 16 selem = disk(20) percentile_result = rank.mean_percentile(image, selem=selem, p0=.1, p1=.9) bilateral_result = rank.mean_bilateral(image, selem=selem, s0=500, s1=500) normal_result = rank.mean(image, selem=selem) fig, axes = plt.subplots(nrows=3, figsize=(8, 10)) ax0, ax1, ax2 = axes ax0.imshow(np.hstack((image, percentile_result))) ax0.set_title('Percentile mean') ax0.axis('off') ax1.imshow(np.hstack((image, bilateral_result))) ax1.set_title('Bilateral mean') ax1.axis('off') ax2.imshow(np.hstack((image, normal_result))) ax2.set_title('Local mean') ax2.axis('off') plt.show() scikit-image-0.9.3/doc/examples/plot_ransac.py000066400000000000000000000030431223313777300213430ustar00rootroot00000000000000""" ========================================= Robust line model estimation using RANSAC ========================================= In this example we see how to robustly fit a line model to faulty data using the RANSAC algorithm. """ import numpy as np from matplotlib import pyplot as plt from skimage.measure import LineModel, ransac np.random.seed(seed=1) # generate coordinates of line x = np.arange(-200, 200) y = 0.2 * x + 20 data = np.column_stack([x, y]) # add faulty data faulty = np.array(30 * [(180., -100)]) faulty += 5 * np.random.normal(size=faulty.shape) data[:faulty.shape[0]] = faulty # add gaussian noise to coordinates noise = np.random.normal(size=data.shape) data += 0.5 * noise data[::2] += 5 * noise[::2] data[::4] += 20 * noise[::4] # fit line using all data model = LineModel() model.estimate(data) # robustly fit line only using inlier data with RANSAC algorithm model_robust, inliers = ransac(data, LineModel, min_samples=2, residual_threshold=1, max_trials=1000) outliers = inliers == False # generate coordinates of estimated models line_x = np.arange(-250, 250) line_y = model.predict_y(line_x) line_y_robust = model_robust.predict_y(line_x) plt.plot(data[inliers, 0], data[inliers, 1], '.b', alpha=0.6, label='Inlier data') plt.plot(data[outliers, 0], data[outliers, 1], '.r', alpha=0.6, label='Outlier data') plt.plot(line_x, line_y, '-k', label='Line model from all data') plt.plot(line_x, line_y_robust, '-b', label='Robust line model') plt.legend(loc='lower left') plt.show() scikit-image-0.9.3/doc/examples/plot_regional_maxima.py000066400000000000000000000063641223313777300232410ustar00rootroot00000000000000""" ========================= Filtering regional maxima ========================= Here, we use morphological reconstruction to create a background image, which we can subtract from the original image to isolate bright features (regional maxima). First we try reconstruction by dilation starting at the edges of the image. We initialize a seed image to the minimum intensity of the image, and set its border to be the pixel values in the original image. These maximal pixels will get dilated in order to reconstruct the background image. """ import numpy as np from scipy.ndimage import gaussian_filter import matplotlib.pyplot as plt from skimage import data from skimage import img_as_float from skimage.morphology import reconstruction # Convert to float: Important for subtraction later which won't work with uint8 image = img_as_float(data.coins()) image = gaussian_filter(image, 1) seed = np.copy(image) seed[1:-1, 1:-1] = image.min() mask = image dilated = reconstruction(seed, mask, method='dilation') """ Subtracting the dilated image leaves an image with just the coins and a flat, black background, as shown below. """ fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(8, 2.5)) ax1.imshow(image) ax1.set_title('original image') ax1.axis('off') ax2.imshow(dilated, vmin=image.min(), vmax=image.max()) ax2.set_title('dilated') ax2.axis('off') ax3.imshow(image - dilated) ax3.set_title('image - dilated') ax3.axis('off') plt.tight_layout() """ .. image:: PLOT2RST.current_figure Although the features (i.e. the coins) are clearly isolated, the coins surrounded by a bright background in the original image are dimmer in the subtracted image. We can attempt to correct this using a different seed image. Instead of creating a seed image with maxima along the image border, we can use the features of the image itself to seed the reconstruction process. Here, the seed image is the original image minus a fixed value, ``h``. """ h = 0.4 seed = image - h dilated = reconstruction(seed, mask, method='dilation') hdome = image - dilated """ To get a feel for the reconstruction process, we plot the intensity of the mask, seed, and dilated images along a slice of the image (indicated by red line). """ fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(8, 2.5)) yslice = 197 ax1.plot(mask[yslice], '0.5', label='mask') ax1.plot(seed[yslice], 'k', label='seed') ax1.plot(dilated[yslice], 'r', label='dilated') ax1.set_ylim(-0.2, 2) ax1.set_title('image slice') ax1.set_xticks([]) ax1.legend() ax2.imshow(dilated, vmin=image.min(), vmax=image.max()) ax2.axhline(yslice, color='r', alpha=0.4) ax2.set_title('dilated') ax2.axis('off') ax3.imshow(hdome) ax3.axhline(yslice, color='r', alpha=0.4) ax3.set_title('image - dilated') ax3.axis('off') plt.tight_layout() plt.show() """ .. image:: PLOT2RST.current_figure As you can see in the image slice, each coin is given a different baseline intensity in the reconstructed image; this is because we used the local intensity (shifted by ``h``) as a seed value. As a result, the coins in the subtracted image have similar pixel intensities. The final result is known as the h-dome of an image since this tends to isolate regional maxima of height ``h``. This operation is particularly useful when your images are unevenly illuminated. """ scikit-image-0.9.3/doc/examples/plot_regionprops.py000066400000000000000000000024241223313777300224450ustar00rootroot00000000000000""" ========================= Measure region properties ========================= This example shows how to measure properties of labelled image regions. """ import math import matplotlib.pyplot as plt import numpy as np from skimage.draw import ellipse from skimage.morphology import label from skimage.measure import regionprops from skimage.transform import rotate image = np.zeros((600, 600)) rr, cc = ellipse(300, 350, 100, 220) image[rr,cc] = 1 image = rotate(image, angle=15, order=0) label_img = label(image) regions = regionprops(label_img) plt.imshow(image) for props in regions: y0, x0 = props.centroid orientation = props.orientation x1 = x0 + math.cos(orientation) * 0.5 * props.major_axis_length y1 = y0 - math.sin(orientation) * 0.5 * props.major_axis_length x2 = x0 - math.sin(orientation) * 0.5 * props.minor_axis_length y2 = y0 - math.cos(orientation) * 0.5 * props.minor_axis_length plt.plot((x0, x1), (y0, y1), '-r', linewidth=2.5) plt.plot((x0, x2), (y0, y2), '-r', linewidth=2.5) plt.plot(x0, y0, '.g', markersize=15) minr, minc, maxr, maxc = props.bbox bx = (minc, maxc, maxc, minc, minc) by = (minr, minr, maxr, maxr, minr) plt.plot(bx, by, '-b', linewidth=2.5) plt.gray() plt.axis((0, 600, 600, 0)) plt.show() scikit-image-0.9.3/doc/examples/plot_segmentations.py000066400000000000000000000075741223313777300227710ustar00rootroot00000000000000""" ==================================================== Comparison of segmentation and superpixel algorithms ==================================================== This example compares three popular low-level image segmentation methods. As it is difficult to obtain good segmentations, and the definition of "good" often depends on the application, these methods are usually used for obtaining an oversegmentation, also known as superpixels. These superpixels then serve as a basis for more sophisticated algorithms such as conditional random fields (CRF). Felzenszwalb's efficient graph based segmentation ------------------------------------------------- This fast 2D image segmentation algorithm, proposed in [1]_ is popular in the computer vision community. The algorithm has a single ``scale`` parameter that influences the segment size. The actual size and number of segments can vary greatly, depending on local contrast. .. [1] Efficient graph-based image segmentation, Felzenszwalb, P.F. and Huttenlocher, D.P. International Journal of Computer Vision, 2004 Quickshift image segmentation ----------------------------- Quickshift is a relatively recent 2D image segmentation algorithm, based on an approximation of kernelized mean-shift. Therefore it belongs to the family of local mode-seeking algorithms and is applied to the 5D space consisting of color information and image location [2]_. One of the benefits of quickshift is that it actually computes a hierarchical segmentation on multiple scales simultaneously. Quickshift has two main parameters: ``sigma`` controls the scale of the local density approximation, ``max_dist`` selects a level in the hierarchical segmentation that is produced. There is also a trade-off between distance in color-space and distance in image-space, given by ``ratio``. .. [2] Quick shift and kernel methods for mode seeking, Vedaldi, A. and Soatto, S. European Conference on Computer Vision, 2008 SLIC - K-Means based image segmentation --------------------------------------- This algorithm simply performs K-means in the 5d space of color information and image location and is therefore closely related to quickshift. As the clustering method is simpler, it is very efficient. It is essential for this algorithm to work in Lab color space to obtain good results. The algorithm quickly gained momentum and is now widely used. See [3] for details. The ``ratio`` parameter trades off color-similarity and proximity, as in the case of Quickshift, while ``n_segments`` chooses the number of centers for kmeans. .. [3] Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi, Pascal Fua, and Sabine Suesstrunk, SLIC Superpixels Compared to State-of-the-art Superpixel Methods, TPAMI, May 2012. """ from __future__ import print_function import matplotlib.pyplot as plt import numpy as np from skimage.data import lena from skimage.segmentation import felzenszwalb, slic, quickshift from skimage.segmentation import mark_boundaries from skimage.util import img_as_float img = img_as_float(lena()[::2, ::2]) segments_fz = felzenszwalb(img, scale=100, sigma=0.5, min_size=50) segments_slic = slic(img, ratio=10, n_segments=250, sigma=1) segments_quick = quickshift(img, kernel_size=3, max_dist=6, ratio=0.5) print("Felzenszwalb's number of segments: %d" % len(np.unique(segments_fz))) print("Slic number of segments: %d" % len(np.unique(segments_slic))) print("Quickshift number of segments: %d" % len(np.unique(segments_quick))) fig, ax = plt.subplots(1, 3) fig.set_size_inches(8, 3, forward=True) plt.subplots_adjust(0.05, 0.05, 0.95, 0.95, 0.05, 0.05) ax[0].imshow(mark_boundaries(img, segments_fz)) ax[0].set_title("Felzenszwalbs's method") ax[1].imshow(mark_boundaries(img, segments_slic)) ax[1].set_title("SLIC") ax[2].imshow(mark_boundaries(img, segments_quick)) ax[2].set_title("Quickshift") for a in ax: a.set_xticks(()) a.set_yticks(()) plt.show() scikit-image-0.9.3/doc/examples/plot_shapes.py000066400000000000000000000035711223313777300213650ustar00rootroot00000000000000""" ====== Shapes ====== This example shows how to draw several different shapes: * line * Bezier curve * polygon * circle * ellipse """ import math import numpy as np import matplotlib.pyplot as plt from skimage.draw import (line, polygon, circle, circle_perimeter, ellipse, ellipse_perimeter, bezier_curve) fig, (ax1, ax2) = plt.subplots(ncols=2, nrows=1, figsize=(10, 6)) img = np.zeros((500, 500, 3), dtype=np.double) # draw line rr, cc = line(120, 123, 20, 400) img[rr, cc, 0] = 255 # fill polygon poly = np.array(( (300, 300), (480, 320), (380, 430), (220, 590), (300, 300), )) rr, cc = polygon(poly[:, 0], poly[:, 1], img.shape) img[rr, cc, 1] = 1 # fill circle rr, cc = circle(200, 200, 100, img.shape) img[rr, cc, :] = (1, 1, 0) # fill ellipse rr, cc = ellipse(300, 300, 100, 200, img.shape) img[rr, cc, 2] = 1 # circle rr, cc = circle_perimeter(120, 400, 15) img[rr, cc, :] = (1, 0, 0) # Bezier curve rr, cc = bezier_curve(70, 100, 10, 10, 150, 100, 1) img[rr, cc, :] = (1, 0, 0) # ellipses rr, cc = ellipse_perimeter(120, 400, 60, 20, orientation=math.pi / 4.) img[rr, cc, :] = (1, 0, 1) rr, cc = ellipse_perimeter(120, 400, 60, 20, orientation=-math.pi / 4.) img[rr, cc, :] = (0, 0, 1) rr, cc = ellipse_perimeter(120, 400, 60, 20, orientation=math.pi / 2.) img[rr, cc, :] = (1, 1, 1) ax1.imshow(img) ax1.set_title('No anti-aliasing') ax1.axis('off') """ Anti-aliased drawing for: * line * circle """ from skimage.draw import line_aa, circle_perimeter_aa img = np.zeros((100, 100), dtype=np.double) # anti-aliased line rr, cc, val = line_aa(12, 12, 20, 50) img[rr, cc] = val # anti-aliased circle rr, cc, val = circle_perimeter_aa(60, 40, 30) img[rr, cc] = val ax2.imshow(img, cmap=plt.cm.gray, interpolation='nearest') ax2.set_title('Anti-aliasing') ax2.axis('off') plt.show() scikit-image-0.9.3/doc/examples/plot_skeleton.py000066400000000000000000000033311223313777300217200ustar00rootroot00000000000000""" =========== Skeletonize =========== Skeletonization reduces binary objects to 1 pixel wide representations. This can be useful for feature extraction, and/or representing an object's topology. The algorithm works by making successive passes of the image. On each pass, border pixels are identified and removed on the condition that they do not break the connectivity of the corresponding object. This module provides an example of calling the routine and displaying the results. The input is a 2D ndarray, with either boolean or integer elements. In the case of boolean, 'True' indicates foreground, and for integer arrays, the foreground is 1's. """ from skimage.morphology import skeletonize from skimage import draw import numpy as np import matplotlib.pyplot as plt # an empty image image = np.zeros((400, 400)) # foreground object 1 image[10:-10, 10:100] = 1 image[-100:-10, 10:-10] = 1 image[10:-10, -100:-10] = 1 # foreground object 2 rs, cs = draw.line(250, 150, 10, 280) for i in range(10): image[rs + i, cs] = 1 rs, cs = draw.line(10, 150, 250, 280) for i in range(20): image[rs + i, cs] = 1 # foreground object 3 ir, ic = np.indices(image.shape) circle1 = (ic - 135)**2 + (ir - 150)**2 < 30**2 circle2 = (ic - 135)**2 + (ir - 150)**2 < 20**2 image[circle1] = 1 image[circle2] = 0 # perform skeletonization skeleton = skeletonize(image) # display results plt.figure(figsize=(8, 4.5)) plt.subplot(121) plt.imshow(image, cmap=plt.cm.gray) plt.axis('off') plt.title('original', fontsize=20) plt.subplot(122) plt.imshow(skeleton, cmap=plt.cm.gray) plt.axis('off') plt.title('skeleton', fontsize=20) plt.subplots_adjust(wspace=0.02, hspace=0.02, top=0.98, bottom=0.02, left=0.02, right=0.98) plt.show() scikit-image-0.9.3/doc/examples/plot_ssim.py000066400000000000000000000041471223313777300210550ustar00rootroot00000000000000""" =========================== Structural similarity index =========================== When comparing images, the mean squared error (MSE)--while simple to implement--is not highly indicative of perceived similarity. Structural similarity aims to address this shortcoming by taking texture into account [1]_, [2]_. The example shows two modifications of the input image, each with the same MSE, but with very different mean structural similarity indices. .. [1] Zhou Wang; Bovik, A.C.; ,"Mean squared error: Love it or leave it? A new look at Signal Fidelity Measures," Signal Processing Magazine, IEEE, vol. 26, no. 1, pp. 98-117, Jan. 2009. .. [2] Z. Wang, A. C. Bovik, H. R. Sheikh and E. P. Simoncelli, "Image quality assessment: From error visibility to structural similarity," IEEE Transactions on Image Processing, vol. 13, no. 4, pp. 600-612, Apr. 2004. """ import numpy as np import matplotlib.pyplot as plt from skimage import data, img_as_float from skimage.measure import structural_similarity as ssim img = img_as_float(data.camera()) rows, cols = img.shape noise = np.ones_like(img) * 0.2 * (img.max() - img.min()) noise[np.random.random(size=noise.shape) > 0.5] *= -1 def mse(x, y): return np.linalg.norm(x - y) img_noise = img + noise img_const = img + abs(noise) f, (ax0, ax1, ax2) = plt.subplots(1, 3) mse_none = mse(img, img) ssim_none = ssim(img, img, dynamic_range=img.max() - img.min()) mse_noise = mse(img, img_noise) ssim_noise = ssim(img, img_noise, dynamic_range=img_const.max() - img_const.min()) mse_const = mse(img, img_const) ssim_const = ssim(img, img_const, dynamic_range=img_noise.max() - img_noise.min()) label = 'MSE: %2.f, SSIM: %.2f' ax0.imshow(img, cmap=plt.cm.gray, vmin=0, vmax=1) ax0.set_xlabel(label % (mse_none, ssim_none)) ax0.set_title('Original image') ax1.imshow(img_noise, cmap=plt.cm.gray, vmin=0, vmax=1) ax1.set_xlabel(label % (mse_noise, ssim_noise)) ax1.set_title('Image with noise') ax2.imshow(img_const, cmap=plt.cm.gray, vmin=0, vmax=1) ax2.set_xlabel(label % (mse_const, ssim_const)) ax2.set_title('Image plus constant') plt.show() scikit-image-0.9.3/doc/examples/plot_swirl.py000066400000000000000000000050231223313777300212340ustar00rootroot00000000000000""" ===== Swirl ===== Image swirling is a non-linear image deformation that creates a whirlpool effect. This example describes the implementation of this transform in ``skimage``, as well as the underlying warp mechanism. Image warping ------------- When applying a geometric transformation on an image, we typically make use of a reverse mapping, i.e., for each pixel in the output image, we compute its corresponding position in the input. The reason is that, if we were to do it the other way around (map each input pixel to its new output position), some pixels in the output may be left empty. On the other hand, each output coordinate has exactly one corresponding location in (or outside) the input image, and even if that position is non-integer, we may use interpolation to compute the corresponding image value. Performing a reverse mapping ---------------------------- To perform a geometric warp in ``skimage``, you simply need to provide the reverse mapping to the ``skimage.transform.warp`` function. E.g., consider the case where we would like to shift an image 50 pixels to the left. The reverse mapping for such a shift would be:: def shift_left(xy): xy[:, 0] += 50 return xy The corresponding call to warp is:: from skimage.transform import warp warp(image, shift_left) The swirl transformation ------------------------ Consider the coordinate :math:`(x, y)` in the output image. The reverse mapping for the swirl transformation first computes, relative to a center :math:`(x_0, y_0)`, its polar coordinates, .. math:: \\theta = \\arctan(y/x) \\rho = \sqrt{(x - x_0)^2 + (y - y_0)^2}, and then transforms them according to .. math:: r = \ln(2) \, \mathtt{radius} / 5 \phi = \mathtt{rotation} s = \mathtt{strength} \\theta' = \phi + s \, e^{-\\rho / r + \\theta} where ``strength`` is a parameter for the amount of swirl, ``radius`` indicates the swirl extent in pixels, and ``rotation`` adds a rotation angle. The transformation of ``radius`` into :math:`r` is to ensure that the transformation decays to :math:`\\approx 1/1000^{\mathsf{th}}` within the specified radius. """ import matplotlib.pyplot as plt from skimage import data from skimage.transform import swirl image = data.checkerboard() swirled = swirl(image, rotation=0, strength=10, radius=120, order=2) f, (ax0, ax1) = plt.subplots(1, 2, figsize=(8, 3)) ax0.imshow(image, cmap=plt.cm.gray, interpolation='none') ax0.axis('off') ax1.imshow(swirled, cmap=plt.cm.gray, interpolation='none') ax1.axis('off') plt.show() scikit-image-0.9.3/doc/examples/plot_template.py000066400000000000000000000031771223313777300217170ustar00rootroot00000000000000""" ================= Template Matching ================= In this example, we use template matching to identify the occurrence of an image patch (in this case, a sub-image centered on a single coin). Here, we return a single match (the exact same coin), so the maximum value in the ``match_template`` result corresponds to the coin location. The other coins look similar, and thus have local maxima; if you expect multiple matches, you should use a proper peak-finding function. The ``match_template`` function uses fast, normalized cross-correlation [1]_ to find instances of the template in the image. Note that the peaks in the output of ``match_template`` correspond to the origin (i.e. top-left corner) of the template. .. [1] J. P. Lewis, "Fast Normalized Cross-Correlation", Industrial Light and Magic. """ import numpy as np import matplotlib.pyplot as plt from skimage import data from skimage.feature import match_template image = data.coins() coin = image[170:220, 75:130] result = match_template(image, coin) ij = np.unravel_index(np.argmax(result), result.shape) x, y = ij[::-1] fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(8, 3)) ax1.imshow(coin) ax1.set_axis_off() ax1.set_title('template') ax2.imshow(image) ax2.set_axis_off() ax2.set_title('image') # highlight matched region hcoin, wcoin = coin.shape rect = plt.Rectangle((x, y), wcoin, hcoin, edgecolor='r', facecolor='none') ax2.add_patch(rect) ax3.imshow(result) ax3.set_axis_off() ax3.set_title('`match_template`\nresult') # highlight matched region ax3.autoscale(False) ax3.plot(x, y, 'o', markeredgecolor='r', markerfacecolor='none', markersize=10) plt.show() scikit-image-0.9.3/doc/examples/plot_threshold_adaptive.py000066400000000000000000000024321223313777300237460ustar00rootroot00000000000000""" ===================== Adaptive Thresholding ===================== Thresholding is the simplest way to segment objects from a background. If that background is relatively uniform, then you can use a global threshold value to binarize the image by pixel-intensity. If there's large variation in the background intensity, however, adaptive thresholding (a.k.a. local or dynamic thresholding) may produce better results. Here, we binarize an image using the `threshold_adaptive` function, which calculates thresholds in regions of size `block_size` surrounding each pixel (i.e. local neighborhoods). Each threshold value is the weighted mean of the local neighborhood minus an offset value. """ import matplotlib.pyplot as plt from skimage import data from skimage.filter import threshold_otsu, threshold_adaptive image = data.page() global_thresh = threshold_otsu(image) binary_global = image > global_thresh block_size = 40 binary_adaptive = threshold_adaptive(image, block_size, offset=10) fig, axes = plt.subplots(nrows=3, figsize=(7, 8)) ax0, ax1, ax2 = axes plt.gray() ax0.imshow(image) ax0.set_title('Image') ax1.imshow(binary_global) ax1.set_title('Global thresholding') ax2.imshow(binary_adaptive) ax2.set_title('Adaptive thresholding') for ax in axes: ax.axis('off') plt.show() scikit-image-0.9.3/doc/examples/plot_view_as_blocks.py000066400000000000000000000036641223313777300230770ustar00rootroot00000000000000""" ============================ Block views on images/arrays ============================ This example illustrates the use of `view_as_blocks` from `skimage.util.shape`. Block views can be incredibly useful when one wants to perform local operations on non-overlapping image patches. We use `lena` from `skimage.data` and virtually 'slice' it into square blocks. Then, on each block, we either pool the mean, the max or the median value of that block. The results are displayed altogether, along with a spline interpolation of order 3 rescaling of the original `lena` image. """ import numpy as np from scipy import ndimage as ndi from matplotlib import pyplot as plt import matplotlib.cm as cm from skimage import data from skimage import color from skimage.util.shape import view_as_blocks # -- get `lena` from skimage.data in grayscale l = color.rgb2gray(data.lena()) # -- size of blocks block_shape = (4, 4) # -- see `lena` as a matrix of blocks (of shape # `block_shape`) view = view_as_blocks(l, block_shape) # -- collapse the last two dimensions in one flatten_view = view.reshape(view.shape[0], view.shape[1], -1) # -- resampling `lena` by taking either the `mean`, # the `max` or the `median` value of each blocks. mean_view = np.mean(flatten_view, axis=2) max_view = np.max(flatten_view, axis=2) median_view = np.median(flatten_view, axis=2) # -- display resampled images fig, axes = plt.subplots(2, 2, figsize=(8, 8)) ax0, ax1, ax2, ax3 = axes.ravel() ax0.set_title("Original rescaled with\n spline interpolation (order=3)") l_resized = ndi.zoom(l, 2, order=3) ax0.imshow(l_resized, cmap=cm.Greys_r) ax1.set_title("Block view with\n local mean pooling") ax1.imshow(mean_view, cmap=cm.Greys_r) ax2.set_title("Block view with\n local max pooling") ax2.imshow(max_view, cmap=cm.Greys_r) ax3.set_title("Block view with\n local median pooling") ax3.imshow(median_view, cmap=cm.Greys_r) plt.subplots_adjust(hspace=0.4, wspace=0.4) plt.show() scikit-image-0.9.3/doc/examples/plot_watershed.py000066400000000000000000000044371223313777300220720ustar00rootroot00000000000000""" ====================== Watershed segmentation ====================== The watershed is a classical algorithm used for **segmentation**, that is, for separating different objects in an image. Starting from user-defined markers, the watershed algorithm treats pixels values as a local topography (elevation). The algorithm floods basins from the markers, until basins attributed to different markers meet on watershed lines. In many cases, markers are chosen as local minima of the image, from which basins are flooded. In the example below, two overlapping circles are to be separated. To do so, one computes an image that is the distance to the background. The maxima of this distance (i.e., the minima of the opposite of the distance) are chosen as markers, and the flooding of basins from such markers separates the two circles along a watershed line. See Wikipedia_ for more details on the algorithm. .. _Wikipedia: http://en.wikipedia.org/wiki/Watershed_(image_processing) """ import numpy as np import matplotlib.pyplot as plt from scipy import ndimage from skimage.morphology import watershed from skimage.feature import peak_local_max # Generate an initial image with two overlapping circles x, y = np.indices((80, 80)) x1, y1, x2, y2 = 28, 28, 44, 52 r1, r2 = 16, 20 mask_circle1 = (x - x1)**2 + (y - y1)**2 < r1**2 mask_circle2 = (x - x2)**2 + (y - y2)**2 < r2**2 image = np.logical_or(mask_circle1, mask_circle2) # Now we want to separate the two objects in image # Generate the markers as local maxima of the distance to the background distance = ndimage.distance_transform_edt(image) local_maxi = peak_local_max(distance, indices=False, footprint=np.ones((3, 3)), labels=image) markers = ndimage.label(local_maxi)[0] labels = watershed(-distance, markers, mask=image) fig, axes = plt.subplots(ncols=3, figsize=(8, 2.7)) ax0, ax1, ax2 = axes ax0.imshow(image, cmap=plt.cm.gray, interpolation='nearest') ax0.set_title('Overlapping objects') ax1.imshow(-distance, cmap=plt.cm.jet, interpolation='nearest') ax1.set_title('Distances') ax2.imshow(labels, cmap=plt.cm.spectral, interpolation='nearest') ax2.set_title('Separated objects') for ax in axes: ax.axis('off') plt.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1) plt.show() scikit-image-0.9.3/doc/ext/000077500000000000000000000000001223313777300154465ustar00rootroot00000000000000scikit-image-0.9.3/doc/ext/LICENSE.txt000066400000000000000000000105751223313777300173010ustar00rootroot00000000000000The files - docscrape.py - docscrape_sphinx.py - numpydoc.py are Copyright (C) 2008 Stefan van der Walt , Pauli Virtanen and are distributed under the modified BSD license. The file - plot_directive.py was derived from code in Matplotlib (http://matplotlib.sf.net/), which has the following license: Copyright (c) 2002-2008 John D. Hunter; All Rights Reserved. 1. This LICENSE AGREEMENT is between John D. Hunter (“JDH”), and the Individual or Organization (“Licensee”) accessing and otherwise using matplotlib software in source or binary form and its associated documentation. 2. Subject to the terms and conditions of this License Agreement, JDH hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use matplotlib 0.98.3 alone or in any derivative version, provided, however, that JDH’s License Agreement and JDH’s notice of copyright, i.e., “Copyright (c) 2002-2008 John D. Hunter; All Rights Reserved” are retained in matplotlib 0.98.3 alone or in any derivative version prepared by Licensee. 3. In the event Licensee prepares a derivative work that is based on or incorporates matplotlib 0.98.3 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to matplotlib 0.98.3. 4. JDH is making matplotlib 0.98.3 available to Licensee on an “AS IS” basis. JDH MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, JDH MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF MATPLOTLIB 0.98.3 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. JDH SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF MATPLOTLIB 0.98.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING MATPLOTLIB 0.98.3, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between JDH and Licensee. This License Agreement does not grant permission to use JDH trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 8. By copying, installing or otherwise using matplotlib 0.98.3, Licensee agrees to be bound by the terms and conditions of this License Agreement. The file - gen_rst.py was taken from the scikit-learn (http://scikit-learn.sourceforge.net), which has the following license: New BSD License Copyright (c) 2007 - 2011 The scikit-learn 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: a. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b. 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. c. Neither the name of the Scikit-learn Developers 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 REGENTS 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. scikit-image-0.9.3/doc/ext/docscrape.py000066400000000000000000000355071223313777300177750ustar00rootroot00000000000000"""Extract reference documentation from the NumPy source tree. """ import inspect import textwrap import re import pydoc from StringIO import StringIO from warnings import warn class Reader(object): """A line-based string reader. """ def __init__(self, data): """ Parameters ---------- data : str String with lines separated by '\n'. """ if isinstance(data,list): self._str = data else: self._str = data.split('\n') # store string as list of lines self.reset() def __getitem__(self, n): return self._str[n] def reset(self): self._l = 0 # current line nr def read(self): if not self.eof(): out = self[self._l] self._l += 1 return out else: return '' def seek_next_non_empty_line(self): for l in self[self._l:]: if l.strip(): break else: self._l += 1 def eof(self): return self._l >= len(self._str) def read_to_condition(self, condition_func): start = self._l for line in self[start:]: if condition_func(line): return self[start:self._l] self._l += 1 if self.eof(): return self[start:self._l+1] return [] def read_to_next_empty_line(self): self.seek_next_non_empty_line() def is_empty(line): return not line.strip() return self.read_to_condition(is_empty) def read_to_next_unindented_line(self): def is_unindented(line): return (line.strip() and (len(line.lstrip()) == len(line))) return self.read_to_condition(is_unindented) def peek(self,n=0): if self._l + n < len(self._str): return self[self._l + n] else: return '' def is_empty(self): return not ''.join(self._str).strip() class NumpyDocString(object): def __init__(self, docstring, config={}): docstring = textwrap.dedent(docstring).split('\n') self._doc = Reader(docstring) self._parsed_data = { 'Signature': '', 'Summary': [''], 'Extended Summary': [], 'Parameters': [], 'Returns': [], 'Raises': [], 'Warns': [], 'Other Parameters': [], 'Attributes': [], 'Methods': [], 'See Also': [], 'Notes': [], 'Warnings': [], 'References': '', 'Examples': '', 'index': {} } self._parse() def __getitem__(self,key): return self._parsed_data[key] def __setitem__(self,key,val): if not self._parsed_data.has_key(key): warn("Unknown section %s" % key) else: self._parsed_data[key] = val def _is_at_section(self): self._doc.seek_next_non_empty_line() if self._doc.eof(): return False l1 = self._doc.peek().strip() # e.g. Parameters if l1.startswith('.. index::'): return True l2 = self._doc.peek(1).strip() # ---------- or ========== return l2.startswith('-'*len(l1)) or l2.startswith('='*len(l1)) def _strip(self,doc): i = 0 j = 0 for i,line in enumerate(doc): if line.strip(): break for j,line in enumerate(doc[::-1]): if line.strip(): break return doc[i:len(doc)-j] def _read_to_next_section(self): section = self._doc.read_to_next_empty_line() while not self._is_at_section() and not self._doc.eof(): if not self._doc.peek(-1).strip(): # previous line was empty section += [''] section += self._doc.read_to_next_empty_line() return section def _read_sections(self): while not self._doc.eof(): data = self._read_to_next_section() name = data[0].strip() if name.startswith('..'): # index section yield name, data[1:] elif len(data) < 2: yield StopIteration else: yield name, self._strip(data[2:]) def _parse_param_list(self,content): r = Reader(content) params = [] while not r.eof(): header = r.read().strip() if ' : ' in header: arg_name, arg_type = header.split(' : ')[:2] else: arg_name, arg_type = header, '' desc = r.read_to_next_unindented_line() desc = dedent_lines(desc) params.append((arg_name,arg_type,desc)) return params _name_rgx = re.compile(r"^\s*(:(?P\w+):`(?P[a-zA-Z0-9_.-]+)`|" r" (?P[a-zA-Z0-9_.-]+))\s*", re.X) def _parse_see_also(self, content): """ func_name : Descriptive text continued text another_func_name : Descriptive text func_name1, func_name2, :meth:`func_name`, func_name3 """ items = [] def parse_item_name(text): """Match ':role:`name`' or 'name'""" m = self._name_rgx.match(text) if m: g = m.groups() if g[1] is None: return g[3], None else: return g[2], g[1] raise ValueError("%s is not a item name" % text) def push_item(name, rest): if not name: return name, role = parse_item_name(name) items.append((name, list(rest), role)) del rest[:] current_func = None rest = [] for line in content: if not line.strip(): continue m = self._name_rgx.match(line) if m and line[m.end():].strip().startswith(':'): push_item(current_func, rest) current_func, line = line[:m.end()], line[m.end():] rest = [line.split(':', 1)[1].strip()] if not rest[0]: rest = [] elif not line.startswith(' '): push_item(current_func, rest) current_func = None if ',' in line: for func in line.split(','): push_item(func, []) elif line.strip(): current_func = line elif current_func is not None: rest.append(line.strip()) push_item(current_func, rest) return items def _parse_index(self, section, content): """ .. index: default :refguide: something, else, and more """ def strip_each_in(lst): return [s.strip() for s in lst] out = {} section = section.split('::') if len(section) > 1: out['default'] = strip_each_in(section[1].split(','))[0] for line in content: line = line.split(':') if len(line) > 2: out[line[1]] = strip_each_in(line[2].split(',')) return out def _parse_summary(self): """Grab signature (if given) and summary""" if self._is_at_section(): return summary = self._doc.read_to_next_empty_line() summary_str = " ".join([s.strip() for s in summary]).strip() if re.compile('^([\w., ]+=)?\s*[\w\.]+\(.*\)$').match(summary_str): self['Signature'] = summary_str if not self._is_at_section(): self['Summary'] = self._doc.read_to_next_empty_line() else: self['Summary'] = summary if not self._is_at_section(): self['Extended Summary'] = self._read_to_next_section() def _parse(self): self._doc.reset() self._parse_summary() for (section,content) in self._read_sections(): if not section.startswith('..'): section = ' '.join([s.capitalize() for s in section.split(' ')]) if section in ('Parameters', 'Attributes', 'Methods', 'Returns', 'Raises', 'Warns'): self[section] = self._parse_param_list(content) elif section.startswith('.. index::'): self['index'] = self._parse_index(section, content) elif section == 'See Also': self['See Also'] = self._parse_see_also(content) else: self[section] = content # string conversion routines def _str_header(self, name, symbol='-'): return [name, len(name)*symbol] def _str_indent(self, doc, indent=4): out = [] for line in doc: out += [' '*indent + line] return out def _str_signature(self): if self['Signature']: return [self['Signature'].replace('*','\*')] + [''] else: return [''] def _str_summary(self): if self['Summary']: return self['Summary'] + [''] else: return [] def _str_extended_summary(self): if self['Extended Summary']: return self['Extended Summary'] + [''] else: return [] def _str_param_list(self, name): out = [] if self[name]: out += self._str_header(name) for param,param_type,desc in self[name]: out += ['%s : %s' % (param, param_type)] out += self._str_indent(desc) out += [''] return out def _str_section(self, name): out = [] if self[name]: out += self._str_header(name) out += self[name] out += [''] return out def _str_see_also(self, func_role): if not self['See Also']: return [] out = [] out += self._str_header("See Also") last_had_desc = True for func, desc, role in self['See Also']: if role: link = ':%s:`%s`' % (role, func) elif func_role: link = ':%s:`%s`' % (func_role, func) else: link = "`%s`_" % func if desc or last_had_desc: out += [''] out += [link] else: out[-1] += ", %s" % link if desc: out += self._str_indent([' '.join(desc)]) last_had_desc = True else: last_had_desc = False out += [''] return out def _str_index(self): idx = self['index'] out = [] out += ['.. index:: %s' % idx.get('default','')] for section, references in idx.items(): if section == 'default': continue out += [' :%s: %s' % (section, ', '.join(references))] return out def __str__(self, func_role=''): out = [] out += self._str_signature() out += self._str_summary() out += self._str_extended_summary() for param_list in ('Parameters','Returns','Raises'): out += self._str_param_list(param_list) out += self._str_section('Warnings') out += self._str_see_also(func_role) for s in ('Notes','References','Examples'): out += self._str_section(s) for param_list in ('Attributes', 'Methods'): out += self._str_param_list(param_list) out += self._str_index() return '\n'.join(out) def indent(str,indent=4): indent_str = ' '*indent if str is None: return indent_str lines = str.split('\n') return '\n'.join(indent_str + l for l in lines) def dedent_lines(lines): """Deindent a list of lines maximally""" return textwrap.dedent("\n".join(lines)).split("\n") def header(text, style='-'): return text + '\n' + style*len(text) + '\n' class FunctionDoc(NumpyDocString): def __init__(self, func, role='func', doc=None, config={}): self._f = func self._role = role # e.g. "func" or "meth" if doc is None: if func is None: raise ValueError("No function or docstring given") doc = inspect.getdoc(func) or '' NumpyDocString.__init__(self, doc) if not self['Signature'] and func is not None: func, func_name = self.get_func() try: # try to read signature argspec = inspect.getargspec(func) argspec = inspect.formatargspec(*argspec) argspec = argspec.replace('*','\*') signature = '%s%s' % (func_name, argspec) except TypeError, e: signature = '%s()' % func_name self['Signature'] = signature def get_func(self): func_name = getattr(self._f, '__name__', self.__class__.__name__) if inspect.isclass(self._f): func = getattr(self._f, '__call__', self._f.__init__) else: func = self._f return func, func_name def __str__(self): out = '' func, func_name = self.get_func() signature = self['Signature'].replace('*', '\*') roles = {'func': 'function', 'meth': 'method'} if self._role: if not roles.has_key(self._role): print "Warning: invalid role %s" % self._role out += '.. %s:: %s\n \n\n' % (roles.get(self._role,''), func_name) out += super(FunctionDoc, self).__str__(func_role=self._role) return out class ClassDoc(NumpyDocString): def __init__(self, cls, doc=None, modulename='', func_doc=FunctionDoc, config={}): if not inspect.isclass(cls) and cls is not None: raise ValueError("Expected a class or None, but got %r" % cls) self._cls = cls if modulename and not modulename.endswith('.'): modulename += '.' self._mod = modulename if doc is None: if cls is None: raise ValueError("No class or documentation string given") doc = pydoc.getdoc(cls) NumpyDocString.__init__(self, doc) if config.get('show_class_members', True): if not self['Methods']: self['Methods'] = [(name, '', '') for name in sorted(self.methods)] if not self['Attributes']: self['Attributes'] = [(name, '', '') for name in sorted(self.properties)] @property def methods(self): if self._cls is None: return [] return [name for name,func in inspect.getmembers(self._cls) if not name.startswith('_') and callable(func)] @property def properties(self): if self._cls is None: return [] return [name for name,func in inspect.getmembers(self._cls) if not name.startswith('_') and func is None] scikit-image-0.9.3/doc/ext/docscrape_sphinx.py000066400000000000000000000170241223313777300213600ustar00rootroot00000000000000import re, inspect, textwrap, pydoc import sphinx from docscrape import NumpyDocString, FunctionDoc, ClassDoc class SphinxDocString(NumpyDocString): def __init__(self, docstring, config={}): self.use_plots = config.get('use_plots', False) NumpyDocString.__init__(self, docstring, config=config) # string conversion routines def _str_header(self, name, symbol='`'): return ['.. rubric:: ' + name, ''] def _str_field_list(self, name): return [':' + name + ':'] def _str_indent(self, doc, indent=4): out = [] for line in doc: out += [' '*indent + line] return out def _str_signature(self): return [''] if self['Signature']: return ['``%s``' % self['Signature']] + [''] else: return [''] def _str_summary(self): return self['Summary'] + [''] def _str_extended_summary(self): return self['Extended Summary'] + [''] def _str_param_list(self, name): out = [] if self[name]: out += self._str_field_list(name) out += [''] for param,param_type,desc in self[name]: out += self._str_indent(['**%s** : %s' % (param.strip(), param_type)]) out += [''] out += self._str_indent(desc,8) out += [''] return out @property def _obj(self): if hasattr(self, '_cls'): return self._cls elif hasattr(self, '_f'): return self._f return None def _str_member_list(self, name): """ Generate a member listing, autosummary:: table where possible, and a table where not. """ out = [] if self[name]: out += ['.. rubric:: %s' % name, ''] prefix = getattr(self, '_name', '') if prefix: prefix = '~%s.' % prefix autosum = [] others = [] for param, param_type, desc in self[name]: param = param.strip() if not self._obj or hasattr(self._obj, param): autosum += [" %s%s" % (prefix, param)] else: others.append((param, param_type, desc)) if autosum: out += ['.. autosummary::', ' :toctree:', ''] out += autosum if others: maxlen_0 = max([len(x[0]) for x in others]) maxlen_1 = max([len(x[1]) for x in others]) hdr = "="*maxlen_0 + " " + "="*maxlen_1 + " " + "="*10 fmt = '%%%ds %%%ds ' % (maxlen_0, maxlen_1) n_indent = maxlen_0 + maxlen_1 + 4 out += [hdr] for param, param_type, desc in others: out += [fmt % (param.strip(), param_type)] out += self._str_indent(desc, n_indent) out += [hdr] out += [''] return out def _str_section(self, name): out = [] if self[name]: out += self._str_header(name) out += [''] content = textwrap.dedent("\n".join(self[name])).split("\n") out += content out += [''] return out def _str_see_also(self, func_role): out = [] if self['See Also']: see_also = super(SphinxDocString, self)._str_see_also(func_role) out = ['.. seealso::', ''] out += self._str_indent(see_also[2:]) return out def _str_warnings(self): out = [] if self['Warnings']: out = ['.. warning::', ''] out += self._str_indent(self['Warnings']) return out def _str_index(self): idx = self['index'] out = [] if len(idx) == 0: return out out += ['.. index:: %s' % idx.get('default','')] for section, references in idx.items(): if section == 'default': continue elif section == 'refguide': out += [' single: %s' % (', '.join(references))] else: out += [' %s: %s' % (section, ','.join(references))] return out def _str_references(self): out = [] if self['References']: out += self._str_header('References') if isinstance(self['References'], str): self['References'] = [self['References']] out.extend(self['References']) out += [''] # Latex collects all references to a separate bibliography, # so we need to insert links to it if sphinx.__version__ >= "0.6": out += ['.. only:: latex',''] else: out += ['.. latexonly::',''] items = [] for line in self['References']: m = re.match(r'.. \[([a-z0-9._-]+)\]', line, re.I) if m: items.append(m.group(1)) out += [' ' + ", ".join(["[%s]_" % item for item in items]), ''] return out def _str_examples(self): examples_str = "\n".join(self['Examples']) if (self.use_plots and 'import matplotlib' in examples_str and 'plot::' not in examples_str): out = [] out += self._str_header('Examples') out += ['.. plot::', ''] out += self._str_indent(self['Examples']) out += [''] return out else: return self._str_section('Examples') def __str__(self, indent=0, func_role="obj"): out = [] out += self._str_signature() out += self._str_index() + [''] out += self._str_summary() out += self._str_extended_summary() for param_list in ('Parameters', 'Returns', 'Raises'): out += self._str_param_list(param_list) out += self._str_warnings() out += self._str_see_also(func_role) out += self._str_section('Notes') out += self._str_references() out += self._str_examples() for param_list in ('Attributes', 'Methods'): out += self._str_member_list(param_list) out = self._str_indent(out,indent) return '\n'.join(out) class SphinxFunctionDoc(SphinxDocString, FunctionDoc): def __init__(self, obj, doc=None, config={}): self.use_plots = config.get('use_plots', False) FunctionDoc.__init__(self, obj, doc=doc, config=config) class SphinxClassDoc(SphinxDocString, ClassDoc): def __init__(self, obj, doc=None, func_doc=None, config={}): self.use_plots = config.get('use_plots', False) ClassDoc.__init__(self, obj, doc=doc, func_doc=None, config=config) class SphinxObjDoc(SphinxDocString): def __init__(self, obj, doc=None, config={}): self._f = obj SphinxDocString.__init__(self, doc, config=config) def get_doc_object(obj, what=None, doc=None, config={}): if what is None: if inspect.isclass(obj): what = 'class' elif inspect.ismodule(obj): what = 'module' elif callable(obj): what = 'function' else: what = 'object' if what == 'class': return SphinxClassDoc(obj, func_doc=SphinxFunctionDoc, doc=doc, config=config) elif what in ('function', 'method'): return SphinxFunctionDoc(obj, doc=doc, config=config) else: if doc is None: doc = pydoc.getdoc(obj) return SphinxObjDoc(obj, doc, config=config) scikit-image-0.9.3/doc/ext/numpydoc.py000066400000000000000000000127131223313777300176620ustar00rootroot00000000000000""" ======== numpydoc ======== Sphinx extension that handles docstrings in the Numpy standard format. [1] It will: - Convert Parameters etc. sections to field lists. - Convert See Also section to a See also entry. - Renumber references. - Extract the signature from the docstring, if it can't be determined otherwise. .. [1] http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines#docstring-standard """ import os, re, pydoc from docscrape_sphinx import get_doc_object, SphinxDocString from sphinx.util.compat import Directive import inspect def mangle_docstrings(app, what, name, obj, options, lines, reference_offset=[0]): cfg = dict(use_plots=app.config.numpydoc_use_plots, show_class_members=app.config.numpydoc_show_class_members) if what == 'module': # Strip top title title_re = re.compile(ur'^\s*[#*=]{4,}\n[a-z0-9 -]+\n[#*=]{4,}\s*', re.I|re.S) lines[:] = title_re.sub(u'', u"\n".join(lines)).split(u"\n") else: doc = get_doc_object(obj, what, u"\n".join(lines), config=cfg) lines[:] = unicode(doc).split(u"\n") if app.config.numpydoc_edit_link and hasattr(obj, '__name__') and \ obj.__name__: if hasattr(obj, '__module__'): v = dict(full_name=u"%s.%s" % (obj.__module__, obj.__name__)) else: v = dict(full_name=obj.__name__) lines += [u'', u'.. htmlonly::', ''] lines += [u' %s' % x for x in (app.config.numpydoc_edit_link % v).split("\n")] # replace reference numbers so that there are no duplicates references = [] for line in lines: line = line.strip() m = re.match(ur'^.. \[([a-z0-9_.-])\]', line, re.I) if m: references.append(m.group(1)) # start renaming from the longest string, to avoid overwriting parts references.sort(key=lambda x: -len(x)) if references: for i, line in enumerate(lines): for r in references: if re.match(ur'^\d+$', r): new_r = u"R%d" % (reference_offset[0] + int(r)) else: new_r = u"%s%d" % (r, reference_offset[0]) lines[i] = lines[i].replace(u'[%s]_' % r, u'[%s]_' % new_r) lines[i] = lines[i].replace(u'.. [%s]' % r, u'.. [%s]' % new_r) reference_offset[0] += len(references) def mangle_signature(app, what, name, obj, options, sig, retann): # Do not try to inspect classes that don't define `__init__` if (inspect.isclass(obj) and (not hasattr(obj, '__init__') or 'initializes x; see ' in pydoc.getdoc(obj.__init__))): return '', '' if not (callable(obj) or hasattr(obj, '__argspec_is_invalid_')): return if not hasattr(obj, '__doc__'): return doc = SphinxDocString(pydoc.getdoc(obj)) if doc['Signature']: sig = re.sub(u"^[^(]*", u"", doc['Signature']) return sig, u'' def setup(app, get_doc_object_=get_doc_object): global get_doc_object get_doc_object = get_doc_object_ app.connect('autodoc-process-docstring', mangle_docstrings) app.connect('autodoc-process-signature', mangle_signature) app.add_config_value('numpydoc_edit_link', None, False) app.add_config_value('numpydoc_use_plots', None, False) app.add_config_value('numpydoc_show_class_members', True, True) # Extra mangling domains app.add_domain(NumpyPythonDomain) app.add_domain(NumpyCDomain) #------------------------------------------------------------------------------ # Docstring-mangling domains #------------------------------------------------------------------------------ from docutils.statemachine import ViewList from sphinx.domains.c import CDomain from sphinx.domains.python import PythonDomain class ManglingDomainBase(object): directive_mangling_map = {} def __init__(self, *a, **kw): super(ManglingDomainBase, self).__init__(*a, **kw) self.wrap_mangling_directives() def wrap_mangling_directives(self): for name, objtype in self.directive_mangling_map.items(): self.directives[name] = wrap_mangling_directive( self.directives[name], objtype) class NumpyPythonDomain(ManglingDomainBase, PythonDomain): name = 'np' directive_mangling_map = { 'function': 'function', 'class': 'class', 'exception': 'class', 'method': 'function', 'classmethod': 'function', 'staticmethod': 'function', 'attribute': 'attribute', } class NumpyCDomain(ManglingDomainBase, CDomain): name = 'np-c' directive_mangling_map = { 'function': 'function', 'member': 'attribute', 'macro': 'function', 'type': 'class', 'var': 'object', } def wrap_mangling_directive(base_directive, objtype): class directive(base_directive): def run(self): env = self.state.document.settings.env name = None if self.arguments: m = re.match(r'^(.*\s+)?(.*?)(\(.*)?', self.arguments[0]) name = m.group(2).strip() if not name: name = self.arguments[0] lines = list(self.content) mangle_docstrings(env.app, objtype, name, None, None, lines) self.content = ViewList(lines, self.content.parent) return base_directive.run(self) return directive scikit-image-0.9.3/doc/ext/plot2rst.py000066400000000000000000000417031223313777300176160ustar00rootroot00000000000000""" Example generation from python files. Generate the rst files for the examples by iterating over the python example files. Files that generate images should start with 'plot'. To generate your own examples, add this extension to the list of ``extensions``in your Sphinx configuration file. In addition, make sure the example directory(ies) in `plot2rst_paths` (see below) points to a directory with examples named `plot_*.py` and include an `index.rst` file. This code was adapted from scikit-image, which took it from scikit-learn. Options ------- The ``plot2rst`` extension accepts the following options: plot2rst_paths : length-2 tuple, or list of tuples Tuple or list of tuples of paths to (python plot, generated rst) files, i.e. (source, destination). Note that both paths are relative to Sphinx 'source' directory. Defaults to ('../examples', 'auto_examples') plot2rst_rcparams : dict Matplotlib configuration parameters. See http://matplotlib.sourceforge.net/users/customizing.html for details. plot2rst_default_thumb : str Path (relative to doc root) of default thumbnail image. plot2rst_thumb_shape : float Shape of thumbnail in pixels. The image is resized to fit within this shape and the excess is filled with white pixels. This fixed size ensures that that gallery images are displayed in a grid. plot2rst_plot_tag : str When this tag is found in the example file, the current plot is saved and tag is replaced with plot path. Defaults to 'PLOT2RST.current_figure'. Suggested CSS definitions ------------------------- div.body h2 { border-bottom: 1px solid #BBB; clear: left; } /*---- example gallery ----*/ .gallery.figure { float: left; margin: 1em; } .gallery.figure img{ display: block; margin-left: auto; margin-right: auto; width: 200px; } .gallery.figure .caption { width: 200px; text-align: center !important; } """ import os import shutil import token import tokenize import traceback import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from skimage import io from skimage import transform from skimage.util.dtype import dtype_range LITERALINCLUDE = """ .. literalinclude:: {src_name} :lines: {code_start}- """ CODE_LINK = """ **Python source code:** :download:`download <{0}>` (generated using ``skimage`` |version|) """ TOCTREE_TEMPLATE = """ .. toctree:: :hidden: %s """ IMAGE_TEMPLATE = """ .. image:: images/%s :align: center """ GALLERY_IMAGE_TEMPLATE = """ .. figure:: %(thumb)s :figclass: gallery :target: ./%(source)s.html :ref:`example_%(link_name)s` """ class Path(str): """Path object for manipulating directory and file paths.""" def __init__(self, path): super(Path, self).__init__(path) @property def isdir(self): return os.path.isdir(self) @property def exists(self): """Return True if path exists""" return os.path.exists(self) def pjoin(self, *args): """Join paths. `p` prefix prevents confusion with string method.""" return self.__class__(os.path.join(self, *args)) def psplit(self): """Split paths. `p` prefix prevents confusion with string method.""" return [self.__class__(p) for p in os.path.split(self)] def makedirs(self): if not self.exists: os.makedirs(self) def listdir(self): return os.listdir(self) def format(self, *args, **kwargs): return self.__class__(super(Path, self).format(*args, **kwargs)) def __add__(self, other): return self.__class__(super(Path, self).__add__(other)) def __iadd__(self, other): return self.__add__(other) def setup(app): app.connect('builder-inited', generate_example_galleries) app.add_config_value('plot2rst_paths', ('../examples', 'auto_examples'), True) app.add_config_value('plot2rst_rcparams', {}, True) app.add_config_value('plot2rst_default_thumb', None, True) app.add_config_value('plot2rst_thumb_shape', (250, 300), True) app.add_config_value('plot2rst_plot_tag', 'PLOT2RST.current_figure', True) app.add_config_value('plot2rst_index_name', 'index', True) def generate_example_galleries(app): cfg = app.builder.config doc_src = Path(os.path.abspath(app.builder.srcdir)) # path/to/doc/source if isinstance(cfg.plot2rst_paths, tuple): cfg.plot2rst_paths = [cfg.plot2rst_paths] for src_dest in cfg.plot2rst_paths: plot_path, rst_path = [Path(p) for p in src_dest] example_dir = doc_src.pjoin(plot_path) rst_dir = doc_src.pjoin(rst_path) generate_examples_and_gallery(example_dir, rst_dir, cfg) def generate_examples_and_gallery(example_dir, rst_dir, cfg): """Generate rst from examples and create gallery to showcase examples.""" if not example_dir.exists: print("No example directory found at", example_dir) return rst_dir.makedirs() # we create an index.rst with all examples gallery_index = file(rst_dir.pjoin('index'+cfg.source_suffix), 'w') # Here we don't use an os.walk, but we recurse only twice: flat is # better than nested. write_gallery(gallery_index, example_dir, rst_dir, cfg) for d in sorted(example_dir.listdir()): example_sub = example_dir.pjoin(d) if example_sub.isdir: rst_sub = rst_dir.pjoin(d) rst_sub.makedirs() write_gallery(gallery_index, example_sub, rst_sub, cfg, depth=1) gallery_index.flush() def write_gallery(gallery_index, src_dir, rst_dir, cfg, depth=0): """Generate the rst files for an example directory, i.e. gallery. Write rst files from python examples and add example links to gallery. Parameters ---------- gallery_index : file Index file for plot gallery. src_dir : 'str' Source directory for python examples. rst_dir : 'str' Destination directory for rst files generated from python examples. cfg : config object Sphinx config object created by Sphinx. """ index_name = cfg.plot2rst_index_name + cfg.source_suffix gallery_template = src_dir.pjoin(index_name) if not os.path.exists(gallery_template): print(src_dir) print(80*'_') print('Example directory %s does not have a %s file' % (src_dir, index_name)) print('Skipping this directory') print(80*'_') return gallery_description = file(gallery_template).read() gallery_index.write('\n\n%s\n\n' % gallery_description) rst_dir.makedirs() examples = [fname for fname in sorted(src_dir.listdir(), key=_plots_first) if fname.endswith('py')] ex_names = [ex[:-3] for ex in examples] # strip '.py' extension if depth == 0: sub_dir = Path('') else: sub_dir_list = src_dir.psplit()[-depth:] sub_dir = Path('/'.join(sub_dir_list) + '/') gallery_index.write(TOCTREE_TEMPLATE % (sub_dir + '\n '.join(ex_names))) for src_name in examples: try: write_example(src_name, src_dir, rst_dir, cfg) except Exception: print("Exception raised while running:") print("%s in %s" % (src_name, src_dir)) print('~' * 60) traceback.print_exc() print('~' * 60) continue link_name = sub_dir.pjoin(src_name) link_name = link_name.replace(os.path.sep, '_') if link_name.startswith('._'): link_name = link_name[2:] info = {} info['thumb'] = sub_dir.pjoin('images/thumb', src_name[:-3] + '.png') info['source'] = sub_dir + src_name[:-3] info['link_name'] = link_name gallery_index.write(GALLERY_IMAGE_TEMPLATE % info) def _plots_first(fname): """Decorate filename so that examples with plots are displayed first.""" if not (fname.startswith('plot') and fname.endswith('.py')): return 'zz' + fname return fname def write_example(src_name, src_dir, rst_dir, cfg): """Write rst file from a given python example. Parameters ---------- src_name : str Name of example file. src_dir : 'str' Source directory for python examples. rst_dir : 'str' Destination directory for rst files generated from python examples. cfg : config object Sphinx config object created by Sphinx. """ last_dir = src_dir.psplit()[-1] # to avoid leading . in file names, and wrong names in links if last_dir == '.' or last_dir == 'examples': last_dir = Path('') else: last_dir += '_' src_path = src_dir.pjoin(src_name) example_file = rst_dir.pjoin(src_name) shutil.copyfile(src_path, example_file) image_dir = rst_dir.pjoin('images') thumb_dir = image_dir.pjoin('thumb') image_dir.makedirs() thumb_dir.makedirs() base_image_name = os.path.splitext(src_name)[0] image_path = image_dir.pjoin(base_image_name + '_{0}.png') basename, py_ext = os.path.splitext(src_name) rst_path = rst_dir.pjoin(basename + cfg.source_suffix) if _plots_are_current(src_path, image_path) and rst_path.exists: return blocks = split_code_and_text_blocks(example_file) if blocks[0][2].startswith('#!'): blocks.pop(0) # don't add shebang line to rst file. rst_link = '.. _example_%s:\n\n' % (last_dir + src_name) figure_list, rst = process_blocks(blocks, src_path, image_path, cfg) has_inline_plots = any(cfg.plot2rst_plot_tag in b[2] for b in blocks) if has_inline_plots: example_rst = ''.join([rst_link, rst]) else: # print first block of text, display all plots, then display code. first_text_block = [b for b in blocks if b[0] == 'text'][0] label, (start, end), content = first_text_block figure_list = save_all_figures(image_path) rst_blocks = [IMAGE_TEMPLATE % f.lstrip('/') for f in figure_list] example_rst = rst_link example_rst += eval(content) example_rst += ''.join(rst_blocks) code_info = dict(src_name=src_name, code_start=end) example_rst += LITERALINCLUDE.format(**code_info) example_rst += CODE_LINK.format(src_name) f = open(rst_path,'w') f.write(example_rst) f.flush() thumb_path = thumb_dir.pjoin(src_name[:-3] + '.png') first_image_file = image_dir.pjoin(figure_list[0].lstrip('/')) if first_image_file.exists: first_image = io.imread(first_image_file) save_thumbnail(first_image, thumb_path, cfg.plot2rst_thumb_shape) if not thumb_path.exists: if cfg.plot2rst_default_thumb is None: print("WARNING: No plots found and default thumbnail not defined.") print("Specify 'plot2rst_default_thumb' in Sphinx config file.") else: shutil.copy(cfg.plot2rst_default_thumb, thumb_path) def save_thumbnail(image, thumb_path, shape): """Save image as a thumbnail with the specified shape. The image is first resized to fit within the specified shape and then centered in an array of the specified shape before saving. """ rescale = min(float(w_1) / w_2 for w_1, w_2 in zip(shape, image.shape)) small_shape = (rescale * np.asarray(image.shape[:2])).astype(int) small_image = transform.resize(image, small_shape) if len(image.shape) == 3: shape = shape + (image.shape[2],) background_value = dtype_range[small_image.dtype.type][1] thumb = background_value * np.ones(shape, dtype=small_image.dtype) i = (shape[0] - small_shape[0]) // 2 j = (shape[1] - small_shape[1]) // 2 thumb[i:i+small_shape[0], j:j+small_shape[1]] = small_image io.imsave(thumb_path, thumb) def _plots_are_current(src_path, image_path): first_image_file = Path(image_path.format(1)) needs_replot = (not first_image_file.exists or _mod_time(first_image_file) <= _mod_time(src_path)) return not needs_replot def _mod_time(file_path): return os.stat(file_path).st_mtime def split_code_and_text_blocks(source_file): """Return list with source file separated into code and text blocks. Returns ------- blocks : list of (label, (start, end+1), content) List where each element is a tuple with the label ('text' or 'code'), the (start, end+1) line numbers, and content string of block. """ block_edges, idx_first_text_block = get_block_edges(source_file) with open(source_file) as f: source_lines = f.readlines() # Every other block should be a text block idx_text_block = np.arange(idx_first_text_block, len(block_edges), 2) blocks = [] slice_ranges = zip(block_edges[:-1], block_edges[1:]) for i, (start, end) in enumerate(slice_ranges): block_label = 'text' if i in idx_text_block else 'code' # subtract 1 from indices b/c line numbers start at 1, not 0 content = ''.join(source_lines[start-1:end-1]) blocks.append((block_label, (start, end), content)) return blocks def get_block_edges(source_file): """Return starting line numbers of code and text blocks Returns ------- block_edges : list of int Line number for the start of each block. Note the idx_first_text_block : {0 | 1} 0 if first block is text then, else 1 (second block better be text). """ block_edges = [] with open(source_file) as f: token_iter = tokenize.generate_tokens(f.readline) for token_tuple in token_iter: t_id, t_str, (srow, scol), (erow, ecol), src_line = token_tuple if (token.tok_name[t_id] == 'STRING' and scol == 0): # Add one point to line after text (for later slicing) block_edges.extend((srow, erow+1)) idx_first_text_block = 0 # when example doesn't start with text block. if not block_edges[0] == 1: block_edges.insert(0, 1) idx_first_text_block = 1 # when example doesn't end with text block. if not block_edges[-1] == erow: # iffy: I'm using end state of loop block_edges.append(erow) return block_edges, idx_first_text_block def process_blocks(blocks, src_path, image_path, cfg): """Run source, save plots as images, and convert blocks to rst. Parameters ---------- blocks : list of block tuples Code and text blocks from example. See `split_code_and_text_blocks`. src_path : str Path to example file. image_path : str Path where plots are saved (format string which accepts figure number). cfg : config object Sphinx config object created by Sphinx. Returns ------- figure_list : list List of figure names saved by the example. rst_text : str Text with code wrapped code-block directives. """ src_dir, src_name = src_path.psplit() if not src_name.startswith('plot'): return [], '' # index of blocks which have inline plots inline_tag = cfg.plot2rst_plot_tag idx_inline_plot = [i for i, b in enumerate(blocks) if inline_tag in b[2]] image_dir, image_fmt_str = image_path.psplit() figure_list = [] plt.rcdefaults() plt.rcParams.update(cfg.plot2rst_rcparams) plt.close('all') example_globals = {} rst_blocks = [] fig_num = 1 for i, (blabel, brange, bcontent) in enumerate(blocks): if blabel == 'code': exec(bcontent, example_globals) rst_blocks.append(codestr2rst(bcontent)) else: if i in idx_inline_plot: plt.savefig(image_path.format(fig_num)) figure_name = image_fmt_str.format(fig_num) fig_num += 1 figure_list.append(figure_name) figure_link = os.path.join('images', figure_name) bcontent = bcontent.replace(inline_tag, figure_link) rst_blocks.append(docstr2rst(bcontent)) return figure_list, '\n'.join(rst_blocks) def codestr2rst(codestr): """Return reStructuredText code block from code string""" code_directive = ".. code-block:: python\n\n" indented_block = '\t' + codestr.replace('\n', '\n\t') return code_directive + indented_block def docstr2rst(docstr): """Return reStructuredText from docstring""" idx_whitespace = len(docstr.rstrip()) - len(docstr) whitespace = docstr[idx_whitespace:] return eval(docstr) + whitespace def save_all_figures(image_path): """Save all matplotlib figures. Parameters ---------- image_path : str Path where plots are saved (format string which accepts figure number). """ figure_list = [] image_dir, image_fmt_str = image_path.psplit() fig_mngr = matplotlib._pylab_helpers.Gcf.get_all_fig_managers() for fig_num in (m.num for m in fig_mngr): # Set the fig_num figure as the current figure as we can't # save a figure that's not the current figure. plt.figure(fig_num) plt.savefig(image_path.format(fig_num)) figure_list.append(image_fmt_str.format(fig_num)) return figure_list scikit-image-0.9.3/doc/ext/plot_directive.py000066400000000000000000000614561223313777300210500ustar00rootroot00000000000000""" A directive for including a matplotlib plot in a Sphinx document. By default, in HTML output, `plot` will include a .png file with a link to a high-res .png and .pdf. In LaTeX output, it will include a .pdf. The source code for the plot may be included in one of three ways: 1. **A path to a source file** as the argument to the directive:: .. plot:: path/to/plot.py When a path to a source file is given, the content of the directive may optionally contain a caption for the plot:: .. plot:: path/to/plot.py This is the caption for the plot Additionally, one my specify the name of a function to call (with no arguments) immediately after importing the module:: .. plot:: path/to/plot.py plot_function1 2. Included as **inline content** to the directive:: .. plot:: import matplotlib.pyplot as plt import matplotlib.image as mpimg import numpy as np img = mpimg.imread('_static/stinkbug.png') imgplot = plt.imshow(img) 3. Using **doctest** syntax:: .. plot:: A plotting example: >>> import matplotlib.pyplot as plt >>> plt.plot([1,2,3], [4,5,6]) Options ------- The ``plot`` directive supports the following options: format : {'python', 'doctest'} Specify the format of the input include-source : bool Whether to display the source code. The default can be changed using the `plot_include_source` variable in conf.py encoding : str If this source file is in a non-UTF8 or non-ASCII encoding, the encoding must be specified using the `:encoding:` option. The encoding will not be inferred using the ``-*- coding -*-`` metacomment. context : bool If provided, the code will be run in the context of all previous plot directives for which the `:context:` option was specified. This only applies to inline code plot directives, not those run from files. nofigs : bool If specified, the code block will be run, but no figures will be inserted. This is usually useful with the ``:context:`` option. Additionally, this directive supports all of the options of the `image` directive, except for `target` (since plot will add its own target). These include `alt`, `height`, `width`, `scale`, `align` and `class`. Configuration options --------------------- The plot directive has the following configuration options: plot_include_source Default value for the include-source option plot_pre_code Code that should be executed before each plot. plot_basedir Base directory, to which ``plot::`` file names are relative to. (If None or empty, file names are relative to the directoly where the file containing the directive is.) plot_formats File formats to generate. List of tuples or strings:: [(suffix, dpi), suffix, ...] that determine the file format and the DPI. For entries whose DPI was omitted, sensible defaults are chosen. plot_html_show_formats Whether to show links to the files in HTML. plot_rcparams A dictionary containing any non-standard rcParams that should be applied before each plot. """ import sys, os, glob, shutil, imp, warnings, cStringIO, re, textwrap, \ traceback, exceptions from docutils.parsers.rst import directives from docutils import nodes from docutils.parsers.rst.directives.images import Image align = Image.align import sphinx sphinx_version = sphinx.__version__.split(".") # The split is necessary for sphinx beta versions where the string is # '6b1' sphinx_version = tuple([int(re.split('[a-z]', x)[0]) for x in sphinx_version[:2]]) try: # Sphinx depends on either Jinja or Jinja2 import jinja2 def format_template(template, **kw): return jinja2.Template(template).render(**kw) except ImportError: import jinja def format_template(template, **kw): return jinja.from_string(template, **kw) import matplotlib import matplotlib.cbook as cbook matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib import _pylab_helpers __version__ = 2 #------------------------------------------------------------------------------ # Relative pathnames #------------------------------------------------------------------------------ # os.path.relpath is new in Python 2.6 try: from os.path import relpath except ImportError: # Copied from Python 2.7 if 'posix' in sys.builtin_module_names: def relpath(path, start=os.path.curdir): """Return a relative version of a path""" from os.path import sep, curdir, join, abspath, commonprefix, \ pardir if not path: raise ValueError("no path specified") start_list = abspath(start).split(sep) path_list = abspath(path).split(sep) # Work out how much of the filepath is shared by start and path. i = len(commonprefix([start_list, path_list])) rel_list = [pardir] * (len(start_list)-i) + path_list[i:] if not rel_list: return curdir return join(*rel_list) elif 'nt' in sys.builtin_module_names: def relpath(path, start=os.path.curdir): """Return a relative version of a path""" from os.path import sep, curdir, join, abspath, commonprefix, \ pardir, splitunc if not path: raise ValueError("no path specified") start_list = abspath(start).split(sep) path_list = abspath(path).split(sep) if start_list[0].lower() != path_list[0].lower(): unc_path, rest = splitunc(path) unc_start, rest = splitunc(start) if bool(unc_path) ^ bool(unc_start): raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)" % (path, start)) else: raise ValueError("path is on drive %s, start on drive %s" % (path_list[0], start_list[0])) # Work out how much of the filepath is shared by start and path. for i in range(min(len(start_list), len(path_list))): if start_list[i].lower() != path_list[i].lower(): break else: i += 1 rel_list = [pardir] * (len(start_list)-i) + path_list[i:] if not rel_list: return curdir return join(*rel_list) else: raise RuntimeError("Unsupported platform (no relpath available!)") #------------------------------------------------------------------------------ # Registration hook #------------------------------------------------------------------------------ def plot_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): return run(arguments, content, options, state_machine, state, lineno) plot_directive.__doc__ = __doc__ def _option_boolean(arg): if not arg or not arg.strip(): # no argument given, assume used as a flag return True elif arg.strip().lower() in ('no', '0', 'false'): return False elif arg.strip().lower() in ('yes', '1', 'true'): return True else: raise ValueError('"%s" unknown boolean' % arg) def _option_format(arg): return directives.choice(arg, ('python', 'doctest')) def _option_align(arg): return directives.choice(arg, ("top", "middle", "bottom", "left", "center", "right")) def mark_plot_labels(app, document): """ To make plots referenceable, we need to move the reference from the "htmlonly" (or "latexonly") node to the actual figure node itself. """ for name, explicit in document.nametypes.items(): if not explicit: continue labelid = document.nameids[name] if labelid is None: continue node = document.ids[labelid] if node.tagname in ('html_only', 'latex_only'): for n in node: if n.tagname == 'figure': sectname = name for c in n: if c.tagname == 'caption': sectname = c.astext() break node['ids'].remove(labelid) node['names'].remove(name) n['ids'].append(labelid) n['names'].append(name) document.settings.env.labels[name] = \ document.settings.env.docname, labelid, sectname break def setup(app): setup.app = app setup.config = app.config setup.confdir = app.confdir options = {'alt': directives.unchanged, 'height': directives.length_or_unitless, 'width': directives.length_or_percentage_or_unitless, 'scale': directives.nonnegative_int, 'align': _option_align, 'class': directives.class_option, 'include-source': _option_boolean, 'format': _option_format, 'context': directives.flag, 'nofigs': directives.flag, 'encoding': directives.encoding } app.add_directive('plot', plot_directive, True, (0, 2, False), **options) app.add_config_value('plot_pre_code', None, True) app.add_config_value('plot_include_source', False, True) app.add_config_value('plot_formats', ['png', 'hires.png', 'pdf'], True) app.add_config_value('plot_basedir', None, True) app.add_config_value('plot_html_show_formats', True, True) app.add_config_value('plot_rcparams', {}, True) app.connect('doctree-read', mark_plot_labels) #------------------------------------------------------------------------------ # Doctest handling #------------------------------------------------------------------------------ def contains_doctest(text): try: # check if it's valid Python as-is compile(text, '', 'exec') return False except SyntaxError: pass r = re.compile(r'^\s*>>>', re.M) m = r.search(text) return bool(m) def unescape_doctest(text): """ Extract code from a piece of text, which contains either Python code or doctests. """ if not contains_doctest(text): return text code = "" for line in text.split("\n"): m = re.match(r'^\s*(>>>|\.\.\.) (.*)$', line) if m: code += m.group(2) + "\n" elif line.strip(): code += "# " + line.strip() + "\n" else: code += "\n" return code def split_code_at_show(text): """ Split code at plt.show() """ parts = [] is_doctest = contains_doctest(text) part = [] for line in text.split("\n"): if (not is_doctest and line.strip() == 'plt.show()') or \ (is_doctest and line.strip() == '>>> plt.show()'): part.append(line) parts.append("\n".join(part)) part = [] else: part.append(line) if "\n".join(part).strip(): parts.append("\n".join(part)) return parts #------------------------------------------------------------------------------ # Template #------------------------------------------------------------------------------ TEMPLATE = """ {{ source_code }} {{ only_html }} {% if source_link or (html_show_formats and not multi_image) %} ( {%- if source_link -%} `Source code <{{ source_link }}>`__ {%- endif -%} {%- if html_show_formats and not multi_image -%} {%- for img in images -%} {%- for fmt in img.formats -%} {%- if source_link or not loop.first -%}, {% endif -%} `{{ fmt }} <{{ dest_dir }}/{{ img.basename }}.{{ fmt }}>`__ {%- endfor -%} {%- endfor -%} {%- endif -%} ) {% endif %} {% for img in images %} .. figure:: {{ build_dir }}/{{ img.basename }}.png {%- for option in options %} {{ option }} {% endfor %} {% if html_show_formats and multi_image -%} ( {%- for fmt in img.formats -%} {%- if not loop.first -%}, {% endif -%} `{{ fmt }} <{{ dest_dir }}/{{ img.basename }}.{{ fmt }}>`__ {%- endfor -%} ) {%- endif -%} {{ caption }} {% endfor %} {{ only_latex }} {% for img in images %} .. image:: {{ build_dir }}/{{ img.basename }}.pdf {% endfor %} """ exception_template = """ .. htmlonly:: [`source code <%(linkdir)s/%(basename)s.py>`__] Exception occurred rendering plot. """ # the context of the plot for all directives specified with the # :context: option plot_context = dict() class ImageFile(object): def __init__(self, basename, dirname): self.basename = basename self.dirname = dirname self.formats = [] def filename(self, format): return os.path.join(self.dirname, "%s.%s" % (self.basename, format)) def filenames(self): return [self.filename(fmt) for fmt in self.formats] def out_of_date(original, derived): """ Returns True if derivative is out-of-date wrt original, both of which are full file paths. """ return (not os.path.exists(derived) or (os.path.exists(original) and os.stat(derived).st_mtime < os.stat(original).st_mtime)) class PlotError(RuntimeError): pass def run_code(code, code_path, ns=None, function_name=None): """ Import a Python module from a path, and run the function given by name, if function_name is not None. """ # Change the working directory to the directory of the example, so # it can get at its data files, if any. Add its path to sys.path # so it can import any helper modules sitting beside it. pwd = os.getcwd() old_sys_path = list(sys.path) if code_path is not None: dirname = os.path.abspath(os.path.dirname(code_path)) os.chdir(dirname) sys.path.insert(0, dirname) # Redirect stdout stdout = sys.stdout sys.stdout = cStringIO.StringIO() # Reset sys.argv old_sys_argv = sys.argv sys.argv = [code_path] try: try: code = unescape_doctest(code) if ns is None: ns = {} if not ns: if setup.config.plot_pre_code is None: exec "import numpy as np\nfrom matplotlib import pyplot as plt\n" in ns else: exec setup.config.plot_pre_code in ns exec code in ns if function_name is not None: exec function_name + "()" in ns except (Exception, SystemExit), err: raise PlotError(traceback.format_exc()) finally: os.chdir(pwd) sys.argv = old_sys_argv sys.path[:] = old_sys_path sys.stdout = stdout return ns def clear_state(plot_rcparams): plt.close('all') matplotlib.rcdefaults() matplotlib.rcParams.update(plot_rcparams) def render_figures(code, code_path, output_dir, output_base, context, function_name, config): """ Run a pyplot script and save the low and high res PNGs and a PDF in outdir. Save the images under *output_dir* with file names derived from *output_base* """ # -- Parse format list default_dpi = {'png': 80, 'hires.png': 200, 'pdf': 200} formats = [] for fmt in config.plot_formats: if isinstance(fmt, str): formats.append((fmt, default_dpi.get(fmt, 80))) elif type(fmt) in (tuple, list) and len(fmt)==2: formats.append((str(fmt[0]), int(fmt[1]))) else: raise PlotError('invalid image format "%r" in plot_formats' % fmt) # -- Try to determine if all images already exist code_pieces = split_code_at_show(code) # Look for single-figure output files first # Look for single-figure output files first all_exists = True img = ImageFile(output_base, output_dir) for format, dpi in formats: if out_of_date(code_path, img.filename(format)): all_exists = False break img.formats.append(format) if all_exists: return [(code, [img])] # Then look for multi-figure output files results = [] all_exists = True for i, code_piece in enumerate(code_pieces): images = [] for j in xrange(1000): if len(code_pieces) > 1: img = ImageFile('%s_%02d_%02d' % (output_base, i, j), output_dir) else: img = ImageFile('%s_%02d' % (output_base, j), output_dir) for format, dpi in formats: if out_of_date(code_path, img.filename(format)): all_exists = False break img.formats.append(format) # assume that if we have one, we have them all if not all_exists: all_exists = (j > 0) break images.append(img) if not all_exists: break results.append((code_piece, images)) if all_exists: return results # We didn't find the files, so build them results = [] if context: ns = plot_context else: ns = {} for i, code_piece in enumerate(code_pieces): if not context: clear_state(config.plot_rcparams) run_code(code_piece, code_path, ns, function_name) images = [] fig_managers = _pylab_helpers.Gcf.get_all_fig_managers() for j, figman in enumerate(fig_managers): if len(fig_managers) == 1 and len(code_pieces) == 1: img = ImageFile(output_base, output_dir) elif len(code_pieces) == 1: img = ImageFile("%s_%02d" % (output_base, j), output_dir) else: img = ImageFile("%s_%02d_%02d" % (output_base, i, j), output_dir) images.append(img) for format, dpi in formats: try: figman.canvas.figure.savefig(img.filename(format), dpi=dpi, bbox_inches='tight') except exceptions.BaseException as err: raise PlotError(traceback.format_exc()) img.formats.append(format) results.append((code_piece, images)) return results def run(arguments, content, options, state_machine, state, lineno): # The user may provide a filename *or* Python code content, but not both if arguments and content: raise RuntimeError("plot:: directive can't have both args and content") document = state_machine.document config = document.settings.env.config nofigs = options.has_key('nofigs') options.setdefault('include-source', config.plot_include_source) context = options.has_key('context') rst_file = document.attributes['source'] rst_dir = os.path.dirname(rst_file) if len(arguments): if not config.plot_basedir: source_file_name = os.path.join(setup.app.builder.srcdir, directives.uri(arguments[0])) else: source_file_name = os.path.join(setup.confdir, config.plot_basedir, directives.uri(arguments[0])) # If there is content, it will be passed as a caption. caption = '\n'.join(content) # If the optional function name is provided, use it if len(arguments) == 2: function_name = arguments[1] else: function_name = None fd = open(source_file_name, 'r') code = fd.read() fd.close() output_base = os.path.basename(source_file_name) else: source_file_name = rst_file code = textwrap.dedent("\n".join(map(str, content))) counter = document.attributes.get('_plot_counter', 0) + 1 document.attributes['_plot_counter'] = counter base, ext = os.path.splitext(os.path.basename(source_file_name)) output_base = '%s-%d.py' % (base, counter) function_name = None caption = '' base, source_ext = os.path.splitext(output_base) if source_ext in ('.py', '.rst', '.txt'): output_base = base else: source_ext = '' # ensure that LaTeX includegraphics doesn't choke in foo.bar.pdf filenames output_base = output_base.replace('.', '-') # is it in doctest format? is_doctest = contains_doctest(code) if options.has_key('format'): if options['format'] == 'python': is_doctest = False else: is_doctest = True # determine output directory name fragment source_rel_name = relpath(source_file_name, setup.confdir) source_rel_dir = os.path.dirname(source_rel_name) while source_rel_dir.startswith(os.path.sep): source_rel_dir = source_rel_dir[1:] # build_dir: where to place output files (temporarily) build_dir = os.path.join(os.path.dirname(setup.app.doctreedir), 'plot_directive', source_rel_dir) # get rid of .. in paths, also changes pathsep # see note in Python docs for warning about symbolic links on Windows. # need to compare source and dest paths at end build_dir = os.path.normpath(build_dir) if not os.path.exists(build_dir): os.makedirs(build_dir) # output_dir: final location in the builder's directory dest_dir = os.path.abspath(os.path.join(setup.app.builder.outdir, source_rel_dir)) if not os.path.exists(dest_dir): os.makedirs(dest_dir) # no problem here for me, but just use built-ins # how to link to files from the RST file dest_dir_link = os.path.join(relpath(setup.confdir, rst_dir), source_rel_dir).replace(os.path.sep, '/') build_dir_link = relpath(build_dir, rst_dir).replace(os.path.sep, '/') source_link = dest_dir_link + '/' + output_base + source_ext # make figures try: results = render_figures(code, source_file_name, build_dir, output_base, context, function_name, config) errors = [] except PlotError, err: reporter = state.memo.reporter sm = reporter.system_message( 2, "Exception occurred in plotting %s: %s" % (output_base, err), line=lineno) results = [(code, [])] errors = [sm] # Properly indent the caption caption = '\n'.join(' ' + line.strip() for line in caption.split('\n')) # generate output restructuredtext total_lines = [] for j, (code_piece, images) in enumerate(results): if options['include-source']: if is_doctest: lines = [''] lines += [row.rstrip() for row in code_piece.split('\n')] else: lines = ['.. code-block:: python', ''] lines += [' %s' % row.rstrip() for row in code_piece.split('\n')] source_code = "\n".join(lines) else: source_code = "" if nofigs: images = [] opts = [':%s: %s' % (key, val) for key, val in options.items() if key in ('alt', 'height', 'width', 'scale', 'align', 'class')] only_html = ".. only:: html" only_latex = ".. only:: latex" if j == 0: src_link = source_link else: src_link = None result = format_template( TEMPLATE, dest_dir=dest_dir_link, build_dir=build_dir_link, source_link=src_link, multi_image=len(images) > 1, only_html=only_html, only_latex=only_latex, options=opts, images=images, source_code=source_code, html_show_formats=config.plot_html_show_formats, caption=caption) total_lines.extend(result.split("\n")) total_lines.extend("\n") if total_lines: state_machine.insert_input(total_lines, source=source_file_name) # copy image files to builder's output directory, if necessary if not os.path.exists(dest_dir): cbook.mkdirs(dest_dir) for code_piece, images in results: for img in images: for fn in img.filenames(): destimg = os.path.join(dest_dir, os.path.basename(fn)) if fn != destimg: shutil.copyfile(fn, destimg) # copy script (if necessary) if source_file_name == rst_file: target_name = os.path.join(dest_dir, output_base + source_ext) f = open(target_name, 'w') f.write(unescape_doctest(code)) f.close() return errors scikit-image-0.9.3/doc/gh-pages.py000066400000000000000000000103121223313777300167100ustar00rootroot00000000000000#!/usr/bin/env python """Script to commit the doc build outputs into the github-pages repo. Use: gh-pages.py [tag] If no tag is given, the current output of 'git describe' is used. If given, that is how the resulting directory will be named. In practice, you should use either actual clean tags from a current build or something like 'current' as a stable URL for the mest current version of the """ #----------------------------------------------------------------------------- # Imports #----------------------------------------------------------------------------- import os import re import shutil import sys from os import chdir as cd from os.path import join as pjoin from subprocess import Popen, PIPE, CalledProcessError, check_call #----------------------------------------------------------------------------- # Globals #----------------------------------------------------------------------------- pages_dir = 'gh-pages' html_dir = 'build/html' pdf_dir = 'build/latex' pages_repo = 'git@github.com:scikit-image/docs.git' #----------------------------------------------------------------------------- # Functions #----------------------------------------------------------------------------- def sh(cmd): """Execute command in a subshell, return status code.""" return check_call(cmd, shell=True) def sh2(cmd): """Execute command in a subshell, return stdout. Stderr is unbuffered from the subshell.x""" p = Popen(cmd, stdout=PIPE, shell=True) out = p.communicate()[0] retcode = p.returncode if retcode: print(out.rstrip()) raise CalledProcessError(retcode, cmd) else: return out.rstrip() def sh3(cmd): """Execute command in a subshell, return stdout, stderr If anything appears in stderr, print it out to sys.stderr""" p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True) out, err = p.communicate() retcode = p.returncode if retcode: raise CalledProcessError(retcode, cmd) else: return out.rstrip(), err.rstrip() def init_repo(path): """clone the gh-pages repo if we haven't already.""" sh("git clone %s %s"%(pages_repo, path)) here = os.getcwd() cd(path) sh('git checkout gh-pages') cd(here) #----------------------------------------------------------------------------- # Script starts #----------------------------------------------------------------------------- if __name__ == '__main__': # find the version number from setup.py setup_lines = open('../setup.py').readlines() tag = 'vUndefined' for l in setup_lines: if l.startswith('VERSION'): tag = l.split("'")[1] # Rename to, e.g., 0.9.x tag = '.'.join(tag.split('.')[:-1] + ['x']) break if "dev" in tag: tag = "dev" startdir = os.getcwd() if not os.path.exists(pages_dir): # init the repo init_repo(pages_dir) else: # ensure up-to-date before operating cd(pages_dir) sh('git checkout gh-pages') sh('git pull') cd(startdir) dest = os.path.join(pages_dir, tag) # This is pretty unforgiving: we unconditionally nuke the destination # directory, and then copy the html tree in there shutil.rmtree(dest, ignore_errors=True) shutil.copytree(html_dir, dest) # copy pdf file into tree #shutil.copy(pjoin(pdf_dir, 'scikits.image.pdf'), pjoin(dest, 'scikits.image.pdf')) try: cd(pages_dir) status = sh2('git status | head -1') branch = re.match('\# On branch (.*)$', status).group(1) if branch != 'gh-pages': e = 'On %r, git branch is %r, MUST be "gh-pages"' % (pages_dir, branch) raise RuntimeError(e) sh("touch .nojekyll") sh('git add .nojekyll') sh('git add index.html') sh('git add %s' % tag) sh2('git commit -m"Updated doc release: %s"' % tag) print('Most recent commit:') sys.stdout.flush() sh('git --no-pager log --oneline HEAD~1..') finally: cd(startdir) print('') print('Now verify the build in: %r' % dest) print("If everything looks good, run 'git push' inside doc/gh-pages.") scikit-image-0.9.3/doc/logo/000077500000000000000000000000001223313777300156065ustar00rootroot00000000000000scikit-image-0.9.3/doc/logo/Makefile000066400000000000000000000004421223313777300172460ustar00rootroot00000000000000.PHONY: logo logo: green_orange_snake.png snake_logo.svg inkscape --export-png=scikit_image_logo.png --export-dpi=100 \ --export-area-drawing --export-background-opacity=1 \ snake_logo.svg python shrink_logo.py green_orange_snake.png: python scikit_image_logo.py --no-plot scikit-image-0.9.3/doc/logo/data/000077500000000000000000000000001223313777300165175ustar00rootroot00000000000000scikit-image-0.9.3/doc/logo/data/scipy.png000066400000000000000000001326611223313777300203650ustar00rootroot00000000000000PNG  IHDRxQoiCCPICC ProfilexTkA6n"Zkx"IYhE6bk Ed3In6&*Ezd/JZE(ޫ(b-nL~7}ov r4 Ril|Bj A4%UN$As{z[V{wwҶ@G*q Y<ߡ)t9Nyx+=Y"|@5-MS%@H8qR>׋infObN~N>! ?F?aĆ=5`5_M'Tq. VJp8dasZHOLn}&wVQygE0  HPEaP@<14r?#{2u$jtbDA{6=Q<("qCA*Oy\V;噹sM^|vWGyz?W15s-_̗)UKuZ17ߟl;=..s7VgjHUO^gc)1&v!.K `m)m$``/]?[xF QT*d4o(/lșmSqens}nk~8X<R5 vz)Ӗ9R,bRPCRR%eKUbvؙn9BħJeRR~NցoEx pHYs   IDATxTUg;襻CQDIElV TDAkYva6e;yٙgޝ{9^9\PRtOOL$./3A=19CS3%5=3%M=RGfVde\c]z>O{_)Y,@{i)g)w5Q1$H* 2%t$(@@@@S|=ub .dJDLI`Kh dIKRyW#Do-[1$S{^|1]%@@@@ /£q9,"8}^{{>՞.#{}.g ԭZJKj^-۹eUgNY!   HZnɭ9ᤔ Y,.˷Z-] TPܖzmUզ;|V`   ^闐 %P,&˶Z-]%M딕^mkؒU?    `fX%bK@t)Y,&qv]G#.('][U%{/.9   &@W!B $ɜ5'dnvJ\S+Dn \W+k%A@@@&@m ,a2KKIm- P@*dP:rhӸbi   Z)"d겣ײ#r$7Hs *Ij2sm[·s*U@@@pD#j\SI2}ſIc2& @^ Y]88b5    ^ܸEI)2}1࠭nNNF[\#ФNY-@h Us     ^ 9eƒZ]axL@Q ][U;]Ń%#   W ཊ%$%võr x@p VOFj"Vi2/@@@0@V2;;GpR~Oow$в~yyp`C+P,JSg    .@˫N`K69@`No}94Ǎ٬~`   8*@Q9K`H3}Zs\23FXMk*#778?_oM"   @HKsHȖˏ;ވW@*eɣ4v62%:     $xwY{e=p?\ݧ}>p)8"м^9[8r9    ut9#Ml s0v\S+Ė轭[=    G eu$vD8czC" ԯ^Z^Zuo >>dz J   L̝n?#$7cם#u7k#zwrA@@@ 5¹2}'beΚ@zj/TwAt    UmE TtmŇ%''H*pCDT(jW\    UxqZBR|>rOFmbH3/@@@0X `sמƮ q@%{LJ4?_o7p    PUqwkeS GIh JKgOtmkrF@@@7u C%ɻ7ˏIVV !,лmMNRZ)#ax@@@pTr&k?ns 5Ѳ*n'nm.}s˘     Rt/$KIŐ )('A>n В_Y9-YY̖4Iqit9"I,Z{$#Fj)lbE@@@$xܧ%w{?;[Ƨњ&MKU+-떵SԩZJU+Zy\'#^%{OF'@hqyy=單u@@@0@o]=Cr)N;*'s;5,UI:em;rץgGش?R'HN;~mM xW{뀫@@@0 |n>8rXa2ZRtr f;FҭlCڎ_w{իa06   n 8,v 5qohYU=jH%$-#b.ś$%-$' I_^.wlIb.   +@7aY r%;+;ԖbAv\MS3eƓ2sqY1T3ji^^`&@G:H+u8fz(WU_ @\"   flW%f\3bv@%mx$/H`hx|AM9]oo/@@@,'+T_s@PZynX+ q @fVFlUS3j-2v!   * X.|[ |idff.fnwZ§Nnfz L'?_%K} K`m:   FR 'b'gJBRi@]+PD|Xo#DNnħ8O:ϯtZs@@@c,MΏ-aQxLh:ն}MBunГkeVYs|}dDρ   Y,MI˔O͒퇢ͺND@?@N앮7g4v=y1]kUV<,)@@@,'`+Znq6 ^!$Rhx<c xF5CdCD   .d{5m$wMj [걷u a֫VJVEb``s <+#Y,99#  XSwY{BncvnͷK2} Q oHV    Ge*Mܦ0ѸMKu ^t//ϟ$s J`yM   !15xELx.|ݺCvg3ckz]K`7I5A@@@@YH5;?6]v=,4N@)ѽz\7={/X7v)(&5+5M@@@pGhxq:(1ܝ#r(wߠ|@\b9zgd    p3VgdJnrWjbS$|$fJJzu[Djb~Rx*/eJh N돎<[_o{D   L} 3z9)n/IT-a9u>'O sA9b`%W,. kƵBqyi%GDۙy0@UdWE@@@%L]#B>7Grrr@$ D}o$kwuO˺=gPXde&OrmҦqEجЪ,6`$} IDATY}Y1`t4;Zy֌3    .&G'yr0z)3?IvUՒ 6cX%:Qն \ǶWD\btyl9<s\۰'N9!  Lt ޻F/+эgEiZBe -r_*uiL]vM&i_헃'ةoyؼ{} ɣ^ }c!_̵lE2   I5Iw:+u;eii O),>$i(W:Hȏ n&C{ٴ?GY>մ{WtA @@@KL0j,vI<^/Ǟc߶;ԓo 2JTLdz=A/͓śƴ+ n@@@)Wl%_W]6skfG'v\ =@=KRW6Rȩe|wl _a| D   `IaQI)boO=1aRlf&"?+٦Y* h-i.~m)e5t 4~ҷKxR0@@@rg]x9]˽-E~u)nwN1w[>1%_~jgawqfۚ.n6F/VQ#zFE@@,/twb{jhb7P,[)V[|{4<^z?3[>w7xnX+mWf-3L Dh7}izFgX@@@+ ([!*6EZ3Y͕sY uFwnC߭O%5--y˸IL3ir*:41q|>To@@@Y}$w&绚&1ykIw9{a8vdf>qH4VGYi7‡=V~0w@@@J&x+ۂ WCy}uoHś컀Vrrr䛩S _WI۩")"z漼FE! @@@+(MJɐZm{x@A/yEݧN-}-Qi6v#,7m-f a^}Q0<   UKf N?n/eK*x2jZ4GyAŇUϯtN4 diV<rN/+ɤI=iCA@@@ (w"VES[UZ5(/wijx_HJi3*~z=U~Pߡ>aA$7mF& ϐ3h\҂   faxf:|][3OcHfJL|`U6FO !';)?1wn|h^zf;LCo6NJG\瘏تޣ RGJל   &PfŇHM0o]&`ݵ]q}O@O>Pcv3==sK_9W >w̪pߐ1ҭdGˤы$+K}U#@@@@y% I"@ ^{WCOВT #㚠xmݤvI 2ol;ml,:T` ir6>U|| lK@@@uH͖a!weoXewP0zYsūjZZR9 ݕk}72wC@@@`GNˏ)-B`?[=^ r\r^]Ǵ]\1vm@@@@=?/OĪ'BD.򒧇ptfiy\5nozHvh Ѣ^9N]UֹNZd_ya=c0@@@~7Or/\)лm iX̕/{TlCtdf<4HYH41r`ڽ~'yM`ƒZsnIU;#k @@@s z.tT͹<3TnR#?Z&qڴr& eGv ]~JHp ^=tjP^)@@@p{lB|17QRa5"][UUj[oS*&_@ޡxxvo 50 VY`vQwfbC@@ p{$198FYHmT*&)XBJVwv̂ԢiS a q8F,νޣȈ@@@ &xOF&O /{ܥ.G?])i& =PԹ'XUn\zڍ8M`ב2kN95{wnSSʕ tʘt   `[U3)*пc-; p Ň<‰1w5պ .;7KN%r ͕#SU=    bnK8/ 52OHJ742 R@^n:z=@_sto kMN^R`eJMk؎   j -{733[m s@Y[WsIߎtބ-r֎#}s{wH_Pw!3] hx-mg[=s 0͚(   `6hxlI:/'Vn0:ESTj}MG~\dDFWʯ)K8B v7\vM#@@@ܒ}Oۡݫ--]*3woL@+ N dʹ]N5|lVk:WS |wsvN_y̮G֫VZ4hj7G@@W ^}۝™K@/pc+53<{\oBEڏeB]z?-ł9,c@@{'ը]3f]L4B@@L!陸;)d &ЯC-e3|ՁvvKY}g]I4u"F5ȷpūȧIN7F&ʺg ;{5, @@@!oxLL^L]s\ekB$W9<[ <:I{ғW_cc$8 xg*ڟQܥeQ'Ɉ   .pi);we3G^J߻J>E߷~"ӝiEK=Q?w84fεߡ=h   `pEgR%%-ӧ ~^HɔZC~tc!.lxmU (GNKIRrWs ,bgW uc TۺՓ!]IŐN@@@.vG{&|G81mؽ]鵖}oD&+me]\[_бYi:|8kozY#oM>7G? q֯.Ȅ   \WOֽwfGV~9H2~eǦQ_+tnQEiC}GS5<2@`CErWrG|>y,v9g#=.C:ՖA~>@@@\,ڎgZ^eo 54Caq? xk彇D>gIgCڮLs /8eVrH1)S2@J&C+˱&x[2͞zYgnm|oZmWS}-}   @ ^FLhQl7p~"úzdKV'ڍF)H-ImO^ՓzcpyPZm.nOKεmU_->@@@u.Tn}ufH$<2|LgCƾtVNs )(&5+Pv8*^l|f,d䕨o2f}%r+hI[Bdm }eMe9$oVCw:2{}Ңjܪͅx@@@OpzSdӞ<Zgvegpr]⻛W݇zY{<(U<ಝݵN2Alj>yhSˍ\9@䖮um޶+r(F@@G ^mpkj1t_O%/]gh 77/6~gy^*reᘼXul65VVҝn?#KM4"o0dgk\|q(t   S̽k^z)gdw|?stjQEhUԡ|dXܰVҨfM-:֥kZ_y   Fגun]S3>C(ФNY -5=K* ER2 oۤ^5?ȋg2ͅy[u'u.Y_D\+eՓήMۥYݲˋ   pZ1ʉ uZwkF[F5z?19ݖNgxfuרfR794e0ٮ_-fRtPavx@@@NI.rJ'?zFTRNa/ ^% 2A{z[tUCtz\o>Uޛ~v٩yMs0o#'E=kszNW~:@n$&}| #  A2u"&PR çp1|ZU6ZK]V9j^H5Ie!rSZy5+>>^+Z}dpX{\WM*8Hr1   E"'x&ʼu; +7!!)]"b !݄OYR7i}-bs^[5w;}4_ ђul7ӓ^%kc^.   \/5dd{"%Ees{-ԥ*,Dh#OVe,GP׸/hEND{Q ڕ?¥Jh%$Fio试qG|oZYJktl:G@@(X Ggӣ/&^oDsyH\>x+(W59ito)S"г௘N Vy] 7ؔ+~#6Fx+Yk7x vr   +PQr+_ |u/^.j7.Fڨ.@l<@ƄХei^\gffŇyw7zvұyef%Vo[@<'@@@%PGl!k7 X=\Y8ަWU+l R`wZhZtiY5ONHJZf9   `-B'x#߫nmJk-z.[JI|4q,ެW˖ 9Ã]oݧ[TszڍN9@@@ dgs> Px_*}/$v%u_2}ue]܃(33 <@@@w :;cQw8&H46sAReŒ|MգIY%y+ V5<,<^|_|} R ƓiW   u /Y y{~ɩׅdo׍+ ظ/R^aC lXK{4Y(mJ=ԻaDGږkww Y1,6D@@@<52Yw8~.D ?oks+UcnnKnʈ>dO֣ꯢܺɮ#g tQS @@@+_ 9kN\ "p@r;x+3W/W7x4[NʇJ%jT,! j*Fq0 IDAT-0My̢MaM"  V{ zg_" s\ 9- ZʐVHHJ;Z(iכKջ_F5Cks7^[MW9\^^q]b{D=r@@@N.ެR;enFeQBqC`|п>ܷkL1M+ɖ_J`?\,OTvNC|1Pv-Zƙ#_bOWʓ͚+M@@ yBf|Mv*^RsA-W_ɋzN/h!O m!AZ\Wz}]CSFtvfo(l[FKQs%)p߂J@@<YY9@ ؔ|j\> <*9x24ڷTZ5(`\   `v(hQ>s{A8M$dmGNN*֣zw 12m;C$JXT$$KV{][l@ )--MkbAIhO]vTpdff6+C#  W/By.#?q&AKVpجN9xԵS+ȁM\;{u.2o<.3qi@@@@5xWx9WhxM]֮Er.뛎MR 57^J૿v㟭tJrW\O/rqx@@@&xm=}=;,unJ)%P%Pܝf[;=śQ@@0@ ^3d% hxѴ_NJXK@[{ŒŇbZyfk [k\V]]H0#  $P`wp.SqS'x}J.c pu/K(z"oܜ}?QfX@fV g`m`v>-!#  f7zi3Ή HM˔'c BOۚ@x5| 7DRC^] 3Vs ênA@@@( ?Z.DYÃm^ԨX8r[Da= 0j,tm_vST @   ȁ#;8rӯסCHHJ/Γ${/ĞO>w{>Uv35XB  J ~mSM`ؼ?J`uDa]-;`<ѓ~/pFYfʶцLv>5A@@@Lfbwh;x/d> -p 4V8Wsx@hdtrmԱnf\@@@Ln? ZV?^ޣG2 s ;:oyeh7!6t@@0@ }j|tjܤoxN P4&/Ch]Y,,q}Dj%">ot   F\Q)z qTʽQ"@?GJgȱco_O(Z\]zi֣L^NI Ko勹aD }{ȩoݨL[<ͺOZ~יݺm   ("pUƍ}& 7TfFs^W&>A`;ȩ`:*k 7kJ% >;[WbH~KM=KJZ@@@rq5_q7eaFzغUKÃ^}WPHl||y󕒜jDsVOp5OZmnbrz+ty|{2=#[P\Ο]ƮΑ}'b s m@@@L*pYdd7@ׇ~#)U7k#Jq /sKҭlI'⵿K5ɖ^%P75dKѬܵ'LM9SO    \=nhUXR,e.k_`[O8S@ߙZe̮Km竤έKc ا+.Ր.7=?Go wx|U.{ā  R/_t%5}Z鉦'o,U;"lR 7$L}svmFt  B/7d1Ţ9gU*5J[Z=^&(\=ٖ,ˠ~%ޟU ]+ǰHe=- lz8,^k# lkq%=̴Ċ  Z+G;A 󓤤YnF x{{ɞwJݪ~f=g p\bH߿QBq;rz[r 'MDȋw]+OBJlv,IE/ qYҹEE! @@@W\LF&Ja]1}"pȁMn5 FN'f?Dy}u֣ TGSdHL_qTN`8^SRzi˳?}^>?k?s9@@@V$<&I29!PJ)?.sK    \{,"G_H/wGsr^3]$26Y=qoفj8?Dwi;? zD@@p '?#0v%oj]}⛽u( ֧]   +p1JD]eEgv!%C>]}dJGP 'NS^+!  f%xgd1~b6Jhd#wld|#@%   %xOEM.#OKϒW_$_!=Aayqû p3`҄@@@O;(= -0s1YL 8-H %@£~-Z"  %xùV"~۵nhYU9\&-UV;XC_ "   ,`KQSy$F٧|zɆ!]ooM?6l |   wM`IQhQR796yR|qN `!r3U@@-yYp핛rBRj9! -S Hx@t<zؒ2@@@ࢀwrj\HɸO0ZTt<po^ҡYeK' @abNah  JݻZ/;y!W/pd7^aDF1c" Yv@D  A;* ER <*zq/wcl+Uw"]#"h]  xwyk;{{yEeM)ߐ#@(P4?F@@TO4ͬT% ,zJF)V|G0nf$x@@@ |Ns >]5>7D_Z o7uʊFgT$>Եe^   / ^ h5~w,jnXAp_Rr{ޡٰ}F9#EKZzSƢ| | @@@qϪoy_Hɐ/͗cHݪ%Sb-U_i{gd˖Q^KEJ<-;ŚNDvz2'@@@_J4^0@vӵʒKLk*!;qΖ]%}7쉔Sщ^@t$xMd  -59"`@*dVzFaQIrv%~i`-́ ܼ0   `/mGdaV+s ڕK/IJ%)K6D`gu]7"  'U׏9i3n mT"-spQbd0Y)L6B\MSW`'Ef   g x}Nf& ZVf<8u)[*0&f^wPڻ訪BI({齃 E](ώ<}T,ED^!o|2-k"?g3ьu_>Y"L&8]ۧ)%rA@@0B=k ne"u-5~D3EGO,;{?~NuXޟ0@;VWPD   PjE}Ԏ ٹ7z Sf尗@Dx'jp皺fdsWIyZrh`"GYGu+A"  x.kb~Q@ XR*sZ 7!㦐FL_D^!C X@@@|-Ùپp@ń]1.DIe0eW&\~T FrFcOdd-9@@@! #% (W mu*`F(ffqS>]7,(׻QPV)nL@@@2=2(JUĴoȢNy l}X}H>Y"m_=1XZT<@@@@HWw=Q  zMտ}b9-ph&\OVoo`Lr:7@@@ !5O߼P d.-`w{N L5na_}gsꗕ;(!gY SF< #  Z 9QٙMշmHWU\gsWջ\ I#լ6}=@@@I!}3}NX@ltWzx́}-Y;=~&Y֤  _ eb3%C,`wNinxes<чC4NsWJEZ8z @@(D 5B^){}黱/4ns}70#!`3-\Q6p@@@J+2a]iz(@ݴDkG?6ЍO֗smFJ}*:2@@@!;-04C"TMZ{w1 ёolLZ IDAT   H𸘈@\ Pl;7wmfMWUZU<=kG]zk~c @2@@@"r3sk@&c({Kn+>V)X$^9^+9Ϣٙ@@@.c#wNIPUԾhTYu|0 C&0S n .nFY9E !9e@@(@xB?R`}2~ (vhl}+UJHɇ T|z 7y|'ptB 0_gfA@@7C \3Ou+Ym\YGX&hCCCtEmԹYݼ;ATx=L@@@ib3")sr5ǓS(S K toYM'>ג5 ='-*Ą  F b;x}C(W`͖2oM[Qd2jgu0w;}}fĄ7EYO9wMմl P@RY/ZW@@@g Gx%p #8y@&5˫÷]?{Vj`(>6B=xj&~(R&G $'i/!#  E ;xH^@ Hrs몝g?`bxݽUQUհFRhxٗ_vVe"B"Jᶈi@@@ GG͎PƑlO M;齯W<̨~ݝUUxOOtN2~sZ*:2\7=3ۏ04H.Ot\  W馹}}GG#<ars۫vv:o=C y   xW'Ir `Yݨ-9)Vg1F[: ЇQ<sw{Do @N͸@@p@^/ H{mr[{z d~˼wQ >H/q}ʀ   l@^- |Y=MuG_I{uy)SWC`3׍@@@O b5E`ˮ <nlv/rІ5܍9%s!p@;xO@@@m^3eݖ C2dF缩&MɟaY[W o޹5sW@@@*֡OdZ5z=}].}kr rfu*rHBXըR8@@@+spY}jz[ڹ ě+̸Hsf@@@ ~꫓ʝޭXDrr'K Z7<ί6wѢnE]=V NZ3ZO8} @@(Vov  ` Ymjnnu F5ﭧ^W:ZxN@@@ U@D?6יs昶 ёazʎ'&wI_ a@@@ UZD(4BA<xy9رzNuBpziπ@@@kNx*{.0CCoBv?I'lρ k$90jBF@@( ՅA$xr:d~X~QD]}od#Р:g@@Yo` wp@NNn8WKee2IbX[FPS9_C2@@@<8^O8#ٜ:i˷e7ReD26r@$z@@@3 n 1]Y C>~xt-M*7ellƴ]r=   ^z(i (_,}.e7STd-c#( 4C%#   RB8$0aB}0ۅַ]\\U*1>ʹ 9   x'"u3]bșTtfD   Pbx[ׯTAp9:i:t$V!תVNOKUL\u4sW@@@ [/-;0hΎS(U)_FiZFGC`}om!l9SE]v:s@@(@ɗ6w~Ӧ_ f+q򪓚U*R*%"s@68TXiۣkvk=+Z^@ wfT6i:O]+/t~m ~yaB_I<hYOxjy   V5:A2^[եyUulZUOUec78bmf,ب˶+(s `OV֩NC);f`C<[CRNE;3xF@@(@qӡu:/N~]"Z)^{֙jg?h Ĵ́@C;-5+ܰ~]lE8@sKt`䄌   @;xk+kA խE5K5[=ӧ^cL=}^l-8G/Ӏ=u%ǩc*B_Ih0Sx@@@E5ZR TuF7m>^JXQO[ޢy!`~WϒjǤO7eP&, @@@ "BFҝcjՔt%mm_5zP?}dnxA_`q̛>rxZF96sDqL@@@(۹YQpQī7ӊwmRþӎT'ԗVZ>:T7~G ͪ!bp@&8@@@Goi %]WO/ңWuY rѽe57>jȕUhhH6訞|WD4c B Y,"E@@|$PdnZXM0 wzi*cƏhFẃq))`i{?xl Sqq]Z8@@ " f{UJH]7b[ZiSC vF׭ly^24ŖaG[s0m<~s&R@@@Se'O0HQͽᬖ3U?]v:k[b\Q<x+G_ 8A ЮaeEF P E@@@ N`x c),voY~x~5\<[wgoV{?4Ps <<@@@],\kܬ4J}ڤ+Gi 4L d6 g:=ւRq   *b+[V<44DZS*&G?\$mc~3P˺-/PL6W@@@ [62b*%G鮋,r(p'>wR+J9o.ocU@8n/ceOq.  @^ʼ5/TOntvV<(;Wtۺ~%m_́   x+72ojXs?.mu$@@@b 栴ik/SP5 l.Wtj"F+=]Z9%GnBfr@r^9qq0   o<*ago=WԂ ZTlN9Y,Og/5Y |ú_ Hǰm] i   x#QMd%G{3>x(;Ǵ-{}p!W)ʝ:x8r鉖@8CuGd   ~k5ohuh#toǸGoq0n,O~;x-_P..J]Wit   _; b7(ujZ]W?>F6r\[:;x}AJ"˅+KJ   xKWTd#s)CuCU/NUo9̾x+po/u5X .3k=@@F״G+ e |MJ8MtN˓_{ 7]{e@Ekv{sOI/ KsG2d   ീ^s4xׅWIԾq忞 ;_~Uv݇-MDnhq.ͪ*ˁ   %*XVy~ӃWtЇ PRY~ wi\KZ7ρú>[F@@Rx;!X)5!vT_>0[bm(xo;hyfEQaƍՆti@@@*x wʒ,֠N54oHi\8O/SfdJ"xvd~ٞt}@@Lޡ]k)4Ըs)"#ȕ}xJhBkޜO6l~/^OW+8֭Vp$J    U|6V|B*eC5~D`fm m#0 ڗiyPL%MgR   ` xͨGkGUJv +pС:x$QIx묱 1 h@@@&Uwqc0āM'颷rqNLؘ+vj/ϛ ޼3zKTZr]#. ء?6R$_ Շ_ʒq@@@7{D2о>o.w5S;y mqc56~2 Ř`e݊&Mg7Y#̞oG=H9 8t8ۚ5iҙ s@@@^xaFCpѣc#gu~g}&žG 5Ͽm\hkG5WR4Lքt3sm,^;aALu;!EbD@@(?%oWhEUӣȕu{Qr@뻂ESfAxn-R뻨NjBqY#߶k-8;xO<ݻ^$K    x%,9{p~L,X~왮* n'fI]2E?Z|K[{zg^d +~7},EPX)1VZAH$  X u׌ZSUW?0RMj6~h.}k1S3}g4;W, V_4!0?   JU53x'jFi+ ts?l>o&7t #x5/f7Xn١IMw?BI@@@ {VﺊǗ%un5):ْ%Cq<9W5meqY tWͪ,%`P##3B ٽk>S#  (u71>XYz]lt^&C^`Kdxc[2*VoS,}8>x-]MR1ȴ<F >6Ҹimk&gV@@@ kfxwihh:}/U[2ۡ:ΩsOu++;@j% S _U5h+)@@@O [VSjH19FF]7Z2\5-2\.El/Xgvcל- R-@bK`Yc8@@@(J'^sˇ4)jG<_&&B_/Mbђaٺj%CQoI.߬.e[6Bo7-M QdqӎC6!@ 8b.@@@ X|V5oLunzsxP uR{a%|m<ՒXddܻ);'S,izl|g k+vWfVv=l Z&]kZ6?#  8Cg^3+:MyWG53͖ ڷ%CQ%~^C<;m%/F7:>f+Xm-/0f`C'   ~OzN{ХY =7zhP="}:{mQ/ynm PѮQe#]"#t   C|Z5 .^.;4c-.{kŐqChv3zL}w_܄ϲv[_]q#{QeE    ;}uլZy#k(2i<s¥k8%CQX{fx*'׾x=~5xZC=V*Yw#,&[@@@|@% IDAT^4n8kFӖFfޤ֭PvV*_]xGqE7}wC:7j_-zRԤVyC   ~y׌ T1!ϡ{6g6շ S*e=gkp3ߒ('6-gp@6)t~wM鳻fd   A#otdы Qr_=6"f3?~{zc 5ڼ3#Ӗhpm0?^[Q 4m3   Bo+5V\5ů$kދ#uFX$3׾\&S%{.wOu5T ofk;_`-n<ɒ)   OVMҘ }dIڸ17OUz\fs͖ ?0S=ͱml[t1<_=ׯc  n?.f"@uШu:#  Oo^͌aQK*?@0|I̖ ƾ7؜v7̟6-y.2wrG 7dTϺHxm-fܩ@@@R1Ngnv*kޤ:2K`S'%}s%Eж=Oe1QF?޻L5-Iݭs>-U* 9ռ|]ptڟyӶ:ُ7.~Z1oxAv;B]bX]>ݻX @@@*isk)wV4>u%mmk %&ܺ;k%0IM37t L+mrў n<5r    @ +~!Kj(wwadt%CWt z͟K~aճ.(32Ui_"֤_볱ȞUʗѥwžCT   sV5In="#6Ҷ1؟ '3쳓/\U˿s$9@@@kt\\)*E'RNy^|edmqP?0ǣv83|.:,,z;߬Rs]UxX va"  D ?]&Mg,40;ƴ)عS9N{ْG%˹0<[-]>>]};F:w]4~dc,M.Zԭ=jadD@@FxM䫆7Uq'x73tbt'Xoݣc-J*WZ|G. _QfQ^=zU'[… Z3al{ɀ   +`I׼S4i4z)y% {չwOѮGdD4מĮ5m+/U<[^Se!@@@@Wx[OMkW=ӧ TEc'Z2X؇frgYZ?5ha;]v X|(`!zρ   /,+gޏחIjkvӒ!P؅w}ҥ<} H&艫.>[bwcNoF5|7 #!   `0[2\H!h3gy ǟ5kWEaӻg7~jgY9` ~O @@@.`^g h h9e㝪="~\>63^튻w)_Ajw/G7{2?O^^ev0{}ۦ=LC@@p,ޱ XY8*t8ޅ+6քbrOKӛwUX=wJOrn=u,'W@@@ PЛ Bj,sY-tǘ6gJ%`|oBEF󟺬<=wK6Z)-9   Y,-l^z%i[+;=L7K-?a#lK-my/P'5A׏n\   !Awْ;j}AWDۧt*''57ֿlRsԮ}GH\޲Z)FR@@@<`oNZ2P-aO.Ǜk/@=xʖ}v 0$$D\AO]] ( x_⮏,@@@xvddd7zwƪ^[7\tzC=wS7Gl^ǗZ,XB|^OtKYiZ\s K8yXYJ4ޏ   B)/c]6q&nϗݙ(7XV5ݶ >ϧI Gwozf] 1Wuk @@@ h(w͛u[f٦aʽN wD́ lpf3qjV-ȩY˹뼾 +Я]Fm @@@AߢБl?Z2]dRTWds~alptjWy ԫucw訚9옘 31?2Z<@@@s[>Ja̖ /{(AY$َʶe0bx7ohh k_'f(:o>4#]Ϲ8@@@AwҧKuӳy4LJ 4]v9lZ*hYbƱڤ7|bgmC< #   P@x͖ )VƳ(_UѿgY<;mjU+;Ǵulӽwy硓.`˫UBgB   Nْ;j}N]/@4awnǒ_^]E?oZrn=.__aa!~X 9?3T[{~:'!   p@xipG4#Wv=vN5}] i   8U^Z28ߟ0@;V~ܭ'Kъd~CF7ֵ.PTtuea8%P|~zyʗvWbd   8Wx_[gEKǽ+- 81>Z_JqEi3reox՚`n*ͫjD:7K08c3ZwKJ_i     k^9+hYpJv*kSC$3y5}\Iw,4?g{NQv6Mb>yVL͜~̦zl|'?   x&ْGf齯Wy&Y$pz'=o͝soӂe /DuSԬv5睚VQeltqk u]c&װF>?BQaJ@   6pU 6{w98nwp%=?_ZVlأu[jCڴv>lܼ|(6:\ёJR%'*59N5+xKKBؔu}ӕorJ ={p52   E5^Z2-8"٣ܑYD`΢p':j9'5f`%FF   p|7Ix}3h跡=7{~01Z p P@fqF @@@NO044DIeP`L~ l!H` 36Z_R;%A͗C2   >p|הxNj]?g( 1 T>&cco^9 7S{뮾px&   VWx#C}n]'P`冽h=eaLmG53pSiL@@@\!iqz⊅! { jgN(ke,-<m]W 4j~fp@@@_kbi[k @o oW>6k<\Qk>+vWAmz](cRE@@p@Hq856tӧpca/h\| UL)X <;h&28o<|h}ad'C<@@@NU;xMFCwQr֩2̏wZ^’[ac9CMgo.YO@@@Au^s 5$G Voگ>0>ӂٙ oݬW~ Z1=sH;W4   ^^~z -E {XHSm(wVhiqc5 ׯ̽    +\[5Wk@\8@Ƒl s=ί(|*`s<]|Letl@F     nVX=Mx UWo0@ 5v^ptMmV!03TӜ#č#,   9}Z|/ [QoW5k<_W;:nE221P5S @@@k\ݢmLT>x`St;FŸ~eNd ;ap]@`[̦zl|'`   X!t^i+t3f 0?>~x3}I[vl͂Oֻ3V,25}Y@@@eפ0y}e~`Cu]սe5K {@@@7 P漢>Cܰ׍LNhRn=uŎ^/Mr{mqQ QaգU!@@@ {uZq%GY*(Rq/sMp&~H/l8[ <Gσ8x8[oO_>[V f r?I $$DM@@@@ (ʫ6S/c'=ܜ"H !>J#67SƕWofVq|J_]/. ݧKht|   (byݣ>}]FoO(Ak5սe5E}GtҌ霵l:<Ňw}P   [r-c8q `gHui^M=[GOOsƖ/.\`%۔W<1]t`v3O@@@Z/[WoXvӮ.N@eԱiiղ^EE۬w#â]M]J"іa%s@@@p^Oy!4%nohX=Ѡz_70vVR2h͖&ޥߍyC|s.^7]u^\%   Co ,F3zn~Wq*0?ޞJj˨|h%E!<,fBo,WGrt$3GǞڹHAKƟvgqwe΋.x?Nq @@@bn~kF@@dD^go R33#   6łlٕoTj.AV :*\O}ۦy;!   * ^.ރG55o6/G2@-' PUKr"   j Е-IDATX^;ҴJ1 "'Ow*#   TxK9ysLM#q9 @a5gRͪe {@@@j >X|g?X@@:Cs)D@@@(Q/~g9i͊/ @zJѻW|lDb@@@,@ǫ;ej]L y빛)<,4x&S@@@ZqYU#K9Yܩ p?/jI-   &@0u$cD@@@xg[2tuE  jT)w˻1=rB@@@ xN ~g|@}ڤi?{+1>Y   Xϛuїw#{'@7Mvo>-vݰ   `+ 6X-2t]4wVDC ʗKTv@@@@/ QXENnn}n~7kav@GWwVJ80    pޓE,k5o@ő0= ْu% \    P)'mޙ&wn̆RBB&ڃ tr@@@<Tϗx}&L^\} `wާzrRC%>@@@\#@K9w6]ptm~@dD,X @@@(ZFe}wf"D P?=I[MjlL   ' P=Y[wQy#7սStdX0L   R-v=qgs} ~Q^0nֹYU?    ^Olxk_.׍Oց,FGH VK5C:LL[S$/@@@%@Qubwҕni7!>HK37vSR}<2!   @i(F&׾5mnzfvϴIDn Cv۳k-J   ewozw*dD `@$M5lu(̏   EP-ƩOz;mqЩ)7X,nkPaz@@@8S8CGu܇,"EO]Eu9@@@@xKӗݣVs~ꤰ,HNC:jt:Δ    ^otݛVs}aEM &jc7ݗU29@@@@x}iddmbҶkElJKjzl|'5U>PS2   XA>5u˳?hv@O4[-?    ( <_][A+7YdЍg[(:2_0.   Po6Unnx&L^3 >;ƴQ e|4*    (a,a,BMhfZ #/Kc۫a$_X    ` 6Y;q!1u7bÂhY7R@@@@ Puz tk8\hP=Iw\FC ̈   prLʝy`s&RTVrDžit RF@@@ (ᢗ49 5sƒ^ gxz^k]п¨@@@^-}t{Aw sMԹ})<,4H&M@@@8Y"|_+v9k=@u빭4gc׷   (:olwѷ [S2(K/|X~H[wgX#t0UG׍j5#   (7X65=}eAU;(@rR.Hn    @qxR d&~OoVvnb*к~];A ufZ;4LI@@@|%@W@nn>V|LlP^^Gqn0{mSW qQnI<@@@@" 3z2z\+a]kA վqeIb    x 7gBfYz?~2rO!,ujZE_Њ!.&Y -   8B#)x<[wgYC[2Y\A[r["@@@^. aI{3Wm `[5G֠m$0@@@p^+3Zq|Z~IYb4KM0Uё@@@ހ3ai|@}Xw(??Cr= TjhQܴBCzI    7 ~e@lޙ9*''/2G OOҠN5(궪G ZzRE@@@xLٚ`^m\9 ͫ_to΍N@@@^LUՏ5(.Xݽ>u@uRԫuIScy9@@@@'Pu*c߶蛟7k/-s\>V[GTuoUM)㜛 #   @P P 8~5F߷hٺ=fmn}GVWǦU UUDJ^    dxlIpYt~\M?.٦g~2Z ,,Tj$MduhREnZ2;tmh   ^ P ,ol]fwA;]ge9mG斖 *tOku+Cב+I    ^oԸ&(rrt^j~](⵻upvPz:POKT:Ԭv55柉Q@@@@PRS68dݫ=Z~oAO_G"#T;\AIY=QuSZ@@@p^/.Y+uaٲ_k6ڭ<`|_;68g W*eUj9լ矵S-*,,@@@p^gQL H6l?ͻi mݝ-2sص?S9 bT11F#)V)|TߟElEI@@@F5̊GdjQ5 {̯8t$[3sdqQ38'7x)77"g 5><,Tёa#\7+3wۚRB\R2ƟF[ FQ-_6Z!lhm9 @@@tи+KIENDB`scikit-image-0.9.3/doc/logo/data/snake_pixabay.jpg000066400000000000000000002274161223313777300220530ustar00rootroot00000000000000JFIFC  !"$"$C" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?&1juޣ:ӻR _«q ֖)660ӿ BE/I1*z:[iQhaE?=Oc>ӻiWE7ݞiܟPغFv1K@:4'4GnŠJ? (9yt奠RE/=z->_z?١wSvmsK4ߘR) ҌN%9~zisLEPz N^3NUPh7T\M45ABZr^KUk&%=A-}jR4LCӳGiM2ZC>J-Z)4+ })뺘3=yQKiX7(TjrXShcK֒+\鰌VzQQGMƅ斓?vKK&yTzzPRO[ GGB>ڛ(NHvh*E zujq=Kw)FBoO NR~U T/Jvi=CrԔS)zqڔU.B(S_A1V"✴u~-WA!1BǚZu|Z@m)ѧ@Վ_zړcIMy9zRfC\3@ǩ&9QLMXwӅ5vӔSDҖUX. HHMZ^-;kvu24  '&yg4 XwG҅]E)ޖ1N}M=64PƥVF8{СuhTj$E( )W4@u7t qZx݊Nf4#Ue4v)iK4iȦ;ҝցzu[bҝMmJ8Q5v;; j=E;zT$Q/JbV;/QIҜ(r^/?R_Qz*RRЗajSTqNij:Qޗ斊h@ۨi>}im ӽ-79i/JwZmJV)~qOE/JEjaGz>&KaT-7~BBU)sNST:\}iTb!Xr)Wg=iwf# ЃS4A}Qa wfjs{Sih4sE})hpJf5,M\u7֌MM\=E)-:2ri%.?=ifG>IZN4/2}/ZbU4W'څ=џZO}fo7/N~SE+{ a77ݦ酴-I\z5?4b~$;zд`ƻ Sۥ'4T]4☿z6PރUH)ӊLz"Ri;9 \{SIE ;q4zS 1Q֗Qq{ &ZZu!xNB:Jl/^i)ۊij-Eϵ.i]l/K 6)4U ? ^tVd(SzԢ9zh^(L[^ /֓4LH)NZ\Raq3Go_j8hz9 N_zkJ@Z?R;IZEkŤ4b٦CJ3=UE>g=58Ejhț2 c֮ލ9CB$ϼRKVd>\qsW>a{D &nP&KkJ~RЇ] _֣7_9tۑB-.VBKnjcW(HZ*Eڗ ܫIO(][^ߺ+1 Y>C0x8;ڵSL5c-?*֒' 347v^jES_vӱE*{?&SInH 7S4mQIޝUf ^vQyiݨНh^ޤf9A1zR-RxZ1NHk31GJPӸN (RwچG4"cv zQя2 (gNAҌCG$TIM~Z?KS5A֗NqTҞaUЗaKۚEM=A 9L0b6){!~妰)74sRQp4/8&( +JGZV :iߥ-WfsO^jisKZ.=$SJAmISZoN\b =it]\NH)q $49M'NXZUhR}-E\SI@S*LޜY SӺуI׭9zP.f*MzӔzqsKIKHsB(▚>joSh/_zZjGf< ZESxwfߺqR0ZG?3}ZxzZҷUr3\*c Ϣj6 NBRd)%(QN^iJrrb^:✼Ra~Z~>n[AR!2J@)Wړ:3aE:i: /B- 7ޤ >\ތ~4}hlb})4`jvX 7۸4nڅGcъL4oֆO )u)v}4)JjLBvSP;% vHkK{ Fjw^֤4g&yKPoE'mԫ@+S4ߚA¨m9 &WAVHGз%;47(U=zS=*ncr{-ay~?M)ݪˏ#L+zte3"0wdVwӈl-f=#Ll<MlcTī}WOGOE$mݿsEatUT5mcĈ~%w&(η+ (avFW/#ח?ŷ^,QץKyHON-B_jVuHVOBm-Ϧiֶ㝑VWJvT7ʼ5@CZ6w+cD9HVUD$ΣU ёʊ''1` MI'e;09T&W! }YM\Rgl\b{bYs\fؼDu6 =+6]G%ulK: e#f˩[ְ̓j՜+nwUgX9!BN[wY.: lnC#zgڥ=V/;'Jn_305MoVzxh.dtS8ַjXҾyH{ٻM+~ K6RG5ug'sӥN39̏$1#f_oֺ-Z H~59#ZAhtjơ"yPF7f8~j7bB8\ٯ'm-6dS|ETi@85$t:iS5z*Оc*ԉs^u*S;]FnF o2<5>}~(ݹ{vϸL}80t)\b{V/қN+[ :дڙTUˠt+{S枼fIրhU4SQzE /AiN AڤMjHRxH qCR/TJ*[O^KޒԡK֙qN]Y}GӗK4xR(b۩˚kpӳjm֞vŰҝBBC PqړEtNX. zNoK&/?MʖhhwNZ4J$)>[@^S{SbJo;X^1kD.Tɥ*a ֝ӓF3JhЖ J_ ؖ?w{Nm-DO׺Vs\Ch)rN'?t a6 BU(p1qiK⟊ދ9|c <}am:!wڣX/,6g?$c{t 75h!D{HB.8ӄ~5/ga.Kqh&Xp7WGCc(Enz1,%EK_8Q= ս֟ ?uU[Hvgy\pvZq;Onwu o&j4e ([^3^5\5%ʴgL0Tc1\Z əG+7R|2Lnt1q?*s)fMQH!=~U]bWz)%qIWj3M@wQl: gӽitLW tkmYL;An2$sZrqP旺TlUbdlt Da2wp 匰sFGDG(prYڣa+t?ZᔧМ˔OcJfj.2Yc$zjtV)wS$Py&1<úe'4.?J-sOVg^H'~;)\I$,Kpq֪L->؆^i3Ǵb+XXfi{y|q qTj|Jħ[m܈Za#9:׊?څŤiT|I/Kv4HGT=ij; qF8BF)3K )#LU_`bŊ^Ը[9cޑGSI-Jln1S"x#[x)1G֝ڸ:WoʌӱBNJ\R@z>nAJF5i[ޒ-Fy{JlL.iͷ>ŀ})/jL-+9G֝XdW0N_MhҒ9Oҝ)NSBQ&Z]ܕxS?5u(iW>jJ\aJƑ!n)ui 5"^QMiKQ*woIJ/Q۰~"+E O^zS0)?cNSRPh+gpڛNO@D)枿P;.?qҘn>Z)qjING8w&s;KJ4`PX^OS֙NS,aOw$r"iO\}_iتVFiM^OqT✡UaH ={:vo\²`V|?H5Ha-Y:-)x]3fYpz_%>($w&bP7w9GZ&&"C "0_%rp!`9RrXwO8ߔCL}6Hsؖ"n*)%瓪E";xHA"DDs67c't?|3f^aya-g=>A2{"M0;ծ|)XmI y4en?*_ IGþfuqͦ/}޺ /JҭŽJ6~[v/㷵EO6Gr;:VN^fqK#JvV@NF{g&c/_9Esrj8k+Gn[r WxM/jJJz?]}O礎Z+uk"hĺMҫHH/늉mzGhtoq{;):xiԧ;7Q=I̛aB[Gv&;ҸfMՕi WJ,E!o`$aBZ&V!&{WKpcI|nw 'Ԅpjw>Y\[Alʠ=h֊I)J<ɏۭ^vlpVimD@=3]yF8'𧃮n.nђHZ3ȝ1]rmI PM2,cV:һ'Y ֠Ze 3]_#CȎ<}>$|>OLnD ;Ү8i]4]%/=ձ|٤G;Z1Si{qM ÖsIiziU^du*4sM$ QNZm/T=jEQݩZv9`*p8AHJWR-Gz!Z9')հ)◷mHq=M%.GݣS@mR~"h>jm/˚\qM=XQSKv11.)2Iݔb:уIv:юxjv=h+Xs掝iW(\RE*z[cNQ3V|1!Wvii˶ _ P:i6qE݀Jk{摨[үfB"=h*u=j'niQۚQR.u4QRJoz^3M rӔEɏiBM.)9\c;Jwhi^vQq1qP- 6Z,^Ծ}i~jV ))|۪sz# ZrSvzShi6QV*.J:c.xSBXKX-izpX!Q'FˆTl;+ .' oA.XH:Iro޻[97QArr;UnB${EJ{\<iˌ{W5M~3ĞnNVX 1!%r:sQ7G{@OJ 8>#mlK{E-çOx;4sledK=SwΚ8G8&<~)aji&RIq\54u(BINr<u/?{~?ʝYooYKΙa\5#/oMm(۹\VoTz1WF5鹹ӶKr(OQ±%>iڃ$vSCt1L :x՜u/z^4x^$5i冉,^$d ?dQ: >]Z|GMHI`YU7MіE0#N#&mJ|pnӑ^* udJMH Aǧ57s{ӮM?_V8 خuXc|;T ߻Tg)7ߴ4Ǹ}?O[EϘ|_tUM$M,>d'$NEquFѠVտOGztgG*PN>h#"4G29PCI%7'=DBe,,[ڶl3q7Ԓ\x~yqqW"]ͫF#5ĕG'hzIImjڭg̕@{5kĬdp{⥸/Zqqٷ19͕h{dilp)+$Iso ֺ#\HYΧ"jJZvNdaӂ*†ݼse5-VL—TҜ&ބެv%_$cJCc/ nڍp)=WmV)FșE'}>뒃 yzиJasNӾI__H5]IcgV–@U?Lbý9}齳BHiu?V;ݪbZNSLR1YjEt#[l=G^h5w;VzS݈R GF=h4\ٞԊ贬f?١4m;mm_Ս_QAxW:ѷڗ)j$*iT}hRַaʮAZ1?*4W.?FUJvݙȗiWV▝ ^isLNV ^'Z^4&y ۚc wjcu@%) @ gZ?Hg辴M mS RX~)Wޓ?ү&+]1^(Ԕ==}=N4jK\R/mMz*H)hڌ1sON7R~w)i٥`)WޅOB(SsFjPj8R<ҩX֞\'.ż8^I}nJ*#wVO@s]^a9vB{ gVNHּPW] jg9h4`Ne8Zp[sֱPm+~*KB(v}.?S^"k>rGp+ ºh<i%F$cA7aR m).P$pf,\i#oj֚wn,bYUd-2y5j:6=)$%=8*{MԉVIorpqy>^uW|ֽnmקռ3}Gjy~721?x5)]Pևmwb+q* uU qֽ_DMKD(I^<{V͇[\Xޞ,Z5;Pu5Dc;wV6H5ӧ cz715W F}i)gaq@j;qB4&ޗ6U:|I4IéšQwA1.=+EwwjCE?10iQҩME9x5HQJr fSLa*Иؠi)ȇvnu_A3NOQ.iV#QFzz\zU8ZV#an*VZU_j# ԁqO:˥Zr-ѲTҗȪLWfzR~eb~ZnU& -OE[/+ñu潶)]5OķV)|%d3#]RɄz\ +yae?ǭm-Q~WO -֛z].7&x;qZzo,#Kl8Ls٦Wi6CejL;xQ{z[)emܸ󎂽65gkWF)qQ 9e{YOm=C: ^kmsxjy>Rr ߅{4qtOl?c,ҪI8KftGg9 &wq\d m܂`ߊ|k-=SiӞcB{}+AE3HvG'7:TּV}a]6C"`犸Gݝ1J(Oi7c7zzfp;vv<ц }Iz"y4x$⚚H"u]>"!^皣=9oh?e|ߓJ<QQ՗bDJ~}p"owpNЦZB֎iҖ&N^{SqN\_JKZaJ-*=)E1GLS Rݦ} M_SN^v zV)ק{Cmħ/_JfsOZx"h:Қ[漨bMh΅-̅U*>TO  .+R*c>*V6Hk\0m)9?ޥn?ŷ4p-+595縪r'ۜwS:c~\W >I]%叝nsxd&o^q, %wޫۆG'ic9#8JWx_q_4䷴>3}LZBz0[cp e̶{̮w^fNsQf@;Ԭ٩i(y}Uc*wZWQ08l;WKI<}kcg7VW/[+gZhvJǒ}Ok)AMʜ#fỉIzZ'\3ԧw=Ӻ(AB=A*ŸTOO/h <tr&J$¾9$8M ;=Q!kru-?rǮU^FbVdz4]F{G-SNbL7wLWMHE=vL#84[Ė 7wGxrih==MǓbkj;hR/\ڌw%i8oߘz擌} ;q^1raF9)~r[Җ4iI ҨħuG;W-.[F;S v&_U`׭=E1M=}j9i>PxJaҝF(cvzq~QGMvi!2)< SS5~cGM3!g]X[[:TR*^<"cM9Ƕjn\Ef v+Zڗ~VWԪjX&%42Ri ̇EI6b\qC=*6|9Qq*m{T 儧 E&1+p*&,zPUTQ;-V]jj]YzV2mDǚ|r@L'viǽ5N4VeA? idL*t3q{7RlM*ŚM'EIIgL͏PEfgT;Vٛ++ TТjDE_[FMmI̗vfkrzzjFP7<5Vn8A+IhEp:VoeSʶ_Ԋ~[]fķ<}l5e$?i\';៙Sͻg'xJCsU-2~j|VڣNlsvNHuO xF.c1QkZޒ4;@ep+5ލ3_`Ǡ w!0Few>mN1uy1L+YiVdrbDcs],Kl#?N*WWAȒޡi^_z֍fk5c`2 qW~$ZyD'rpI\ZVfΗss/¹o7;{2mr؅lZi7>ӴC^I/Sp4Te/^sU/fF&׍tnAcROTbY>t|Gckuap> r7JZέ7ȵUAR7o';·'7R޺ԍU1@R~v1^ǘdҒv'>vT%Iq!q#୭/Nv|hK][46+`>'tp/^ ۲[lczPIh >^2):5WBJwAF8iCa+Q'SMwbvznjBhES~ju% )Z)L^)kQ1zgu6Q)>giwғ>⡖LtZU!lpXݥsڨg[۫T[ZgF_+284s{}) f5{++Mդ?CJu]9YƧ2!~ 5I+|tBj{9G8PZ*,H?7zSW`>&Y^*x"RE[vR?"sQ}Gkpj4-Q31s9Jrw<Ȩ\WZkS$ V8k ȂYSީRu*4uUcijDeRb?+:COb rmҨF٫1[qjhqfU[E붟/EkAvӅrLdP[?jm?٫žksEh}+E@4RhƇ,190FwR*.E1ޅAF\gYIf+MSEr›9VDT9]'tJY]g75z)YɣXJЂzSZS$EJMrNr6V(K@ks zsQOEDj]BP+==ܧסGљJou5kv8K˃WT{+B =MqwmصRPH!{T5):jI!Cʢo2KgbGԁڷXM@}EzY^/QsX\<(1d+JDNv0(.coiIk :^*>y+\hIKPRԜC|.}ӥa &dk*Iί[v=^}J_-N^qSg:-5 $ZZJuo ߈}`\mnLG>xt Ql X8#5tT◺zHΝXb֠Ӥ 7_Q%%F'zǡK+Mv\2I5Zg|M[ȡDO/b7ӏɆzǶ uGoioó?,FrG4|E]:I_WFl9ht(*7t8.0*Wvr[Kd{ԏ6:DݕUH,%.#o[߁]Co2 eqk?FnuL.WEkqw' d}P6w!pB]ڃrf=» 6LCm "c9U؉֌Q^&'kw>lCP _,"M2kÂ0LVV隈2d~y6&҇]*2XE}jfTR܌+5ﲝV~4rֲE֙ufܥf3Hy z95&z?%OzJp:y= d vҼ+.,gWT5R̤k*̩ ~aQ)2TjڰKH*)Ӟ&V[u3M01is5QQ3;_kkY'jZ)TUG`掽ii/Pr)ZRL]Aĝyn vb@.~^(iTz-L^)֩h+\vڍ\IքF*:sV5#K:ȨSv-O cHќ,ۉH+1\堾gGf/21ھji;qlym{d'5Լ[J% OzrUJ-Nϑ\mtH v;ϡQ4ȽrݠsT5ޯn;Ջ>۩굙y/??{/?>ke33F8(y;V&{ԗI3V_ya]fy5)ԑں[ bII ^{|iR%yF2Ղ߭XI}j{}$cش9Z՜҃ܨrئnesWC7=.?g4eQ5=O+MkЍhO.2:N U5S9YjcQJ#}ꍓDVv&YI9 OH}i*'5J).zԫ'ޕj+\Sƾ+2Hie[Z{Th<[d3{F7ݮHj?x ZtfB<ڟ>z+*D +UTб 8بj'QN?GQ3'}n".~dv:5&t HK\~=.?zDgL j;W7ޫ]ue-6lCRɬ.V珽Xa6^ZXBMI)5h=OJ=t ȩSe]ͮ2Oºۋe#MV[ӬT`ڭAs:-Uh wBdcvv jTש\)QMv+9Vִfn\h$K$SfEd[ˑ}h댓<@]媔?-lSMd#qyj5ؑ^gfrՎVnW |7`~WLHc:g׊0&8+ql,m '͟β2R/'Q![Zq So1{*N0[RnkNky;,J=YZd+ApkGԗU)&nFi#Z-Fd^ W0hl}v.iC)/xjđ$Q 8t7 YK8jᣊMZJ'I5aVpgܗkԢ5YkfP'N=i/; wG0}O&˝ip},zs\ \)5iE < u$Cٴ6^czja{?=_׭F@\1~BgWr{E(M{-R&iW@iVE sVv-J@]K wg|i $FOMJc9ԄzS7GmR6%3'Y澹[H#By<z[]&89/pH u&1Xc|ԚA--(H85;Gaة5w$WAuګOE:mI(Tz%Ҟqzμ6yԩܻ\oJK3ߎS(T&xSEzWg/+ڨwɥ=/-P79z+̜[zT,K>IXGwq S% :6sY.78?Ukšu5Քt2 TQd/=OҭjK0|m`{SlnMeHǜ;g#_^gVljZ\y~u}p_Zۼ{kFҮYB\_g|gbЩ|F5 /Q+٧N4h &Ê^H8Nh i߅4+/=K bwRRڟTP)ت[phj:S-zE>~4;i-ťQM(iSXV$]vA=()!Z>LqYR|L4-lQ`gڡxZ#JV%m\E% ~N 3WO`9E˭62kbw+ m/An)薊3R˧om x]05Mi HGt3_1^:DHV08;d2ۃ5R{AگM|W%OF̧w!XZN89T3%QX¤ZZ|G|wQ]. ւXR>zT>oj3.E^*L:\*9S֨У}j.^41fGzO/j͡|T_-T[ӼV'̝žƧoVqj% 2B.~@)ݩwRfLN[^V`P:P4ʺ9|G=-o ChN*R0hV72v.2z$6:8xVlZIr7VZYMc5ZZJũ&^hi&jU&ݬkc*{5?YV ҴjEA<#=5NF{VU|VU$;mjri`hں0jpwa]3Z0[I֌9o;V\#- X]`RSh%xwU;% hNdV*zs_q.$ջ/hm,c 6=k[2C"' $kr<<yu<\uXk pًVA<%2A1qژڧًivq彆n1/c[kBRq0IOX[DT]ccȎvQ'Áӵxu9m)kYPoǵ,'t6dƫ\VKW$܊|I=s\F{0斦`V9_~> ޮ=q"*%s :g姀pwo1YhmduꚬshH˹<+]*(ѐ}+ǠE=J#<~X#y*SXqmn=kb/1tNOW* [,6&O֮!eOƻe-NJؙXx^]>+nL "q-IJռQgl D?"\_Q.z#n{=~OR4rwzKzY.Gkx \-?G+7_V՝漉Qg/l,"u)hN}!k1!#J];SquCB|iObxu2̻GӦ H85~ մ(|Ei$}1$=^Юb;&9#뚭Z-sUw:0J{5iߠК4X'C&ymxk?j c5׎kD(Ԕgu>[.5qD7Uk<)el2%tɤ|ߍ~9p7 } jՒ$ѸҪl۹MG4cXyͻQmϺU>{fm!R-uю|PLj9-x,-~=luΝ e^m(F6j-xjy8`9Q9EBj맋s\|̍8mQ/^us J:M-zmZ*V8nֻKYgZ:QQV.,j;-1ەδ#5BQթϏZ7iXuxޔV}tk 7f{]-o _5`^ќvW)6^(a̷9SQ0WI" \ʑ^MJFW#jQ% #H؉b`}ڴTVzn73n$Ys-WoAVns_iWUh[Tj}ev5۫fHD!YQ 'UZs36͍۹WS^ҳSDfK!&05z[cUu#-% 갲1/^ro7J_UݹZ\SWZҎ~*eZCzIKbu -*ZM_/`Q{Wb cDQL_H\^x?٪3aX&aJU8[rftRd5jGq^Xis׊G" rynYs<V+;ڳKx.{  \3c.+r=ɫqjsQZI'D)G h%*l7J [ͬ-ib@r#rih85z-@l.3Q#2Tً35[YRy$U;0zbj\cZqmwqFqU䵶WtkrX:*\~u+Ju=NnCQ k$tzcM27 QoA-:Y3~T ƥ>$˯u^ xj.jzqsPko&]asi7moTCOJ?v_zrȃVĦb߅9|ku, Ly{VmriE8;"F.{Zn^ R%P9SjtO:XLxHƦ6%=#ՊB-r17ۃs1U ;SBGRWd ׊nsJo_jɵs٦}h)'N"ӭ E #9?0(FiBwSz1OZJEMyBTW+?v2IⲭB.r{nk]kKp=*OXē uvD>jj|}^J:DtJtVH5EZd qU'a*󲤑}yZEV|?zW;ݎgWކw%޽oR)yߌQ53Tk^6M'ף|9Кk-\vjeA_B3Єgvqvrqмiz[[ +U@EUEw'vjTٝx4'ZXֆw3H͖ܚ< #5R(kzuG+@ \YB7NJ5c9E}6Qi8)Ƅiݟ6IAu_T'ʔRݳ VDXӡM*ܔuGg>jj6e%V ^ML$-Qk]jLgG)T-:횭(aÊ-tRKc55s*<5) n-Z=V|+_yi+^]y!!mq[N,Yߴ\w8ZW*>;٣IX{6ګ=kU@ɺ@?~N*ю\r g]ky?~o'z,)3u$LڛDz(q7RLM[!YWb(RwŻzbTW<7R?¶mk 4[GWY#)j ;kJ0\RFOfnD^ir[qԄQwaU䒺՚9]+cVc9S=)8Ր.{ԷjqMh5701R\wY03LHXUai\Vȧ VV 'Gj%E =h+3GQU/jε^VHԗWr٪bޤ/4yjԑGleE'JmVbF^|"ۊn1W+IoYVt [5::9JQI屮 *VH:q[:ȝK @N+ҴRLc8^yA+07cZ)j䈓CM4n -[=DGrQCեBO_.;,-i|Z.c~xXv޼ 9V( ?R&܏j,"_8`2_Z唣'Λi{R{G =ޮEcmu0k/i_`pj 'Ό*{ŚFL|?)}QA('u^dOGIDY-]`T$R]GXs=#;;h3plveW'ЪAk%4жq"lsTFyfuHebMn,__¢iTRFylE(,4YyGQ9w`SqSQ..Dȕ:O]z zR9Jqɦaij=iit.bu}i~DߥA66.}(9%=ݭKL9;"X#?oid4p:)\6v'MY, T}BWN(ӎ{nq%˦sv-ե(x>}v 4y`x5+:2o8e5^*MҊԅH y\qgOk7 J|mSb}MuwR q:ӗiu[)Nx,V>^Lc="&usVCnZG0f1u9)- %Wd:M/t 6byXq<ǽze `W1STbڍ3iڼqSOڝaTirg<+ze9LV}X%^BH懏k٩fT\c-N4vYNAWEi^b68dJTs׍NhUGy'56ks+мUv:וm7慎F%Ub[nu o> _ƾѭEA8~Aȋ$;hJ>"ǼF!8X)l𸦹T7Rș>&RRӥ:Z0ٮE3zI/zμߵ:P~$ ʺ1uѡ6c -cw˱_ιy6ҴuD\6=[d {)*ˡkAFɞpk>|֤YwI_5FGQ_RGVݪ>ӓNs-ꀀKw! [Y7n^JNz= .DNrz^/ݽʰʌT_24|ڂy?gj yH.$8?5[s85ق*׈9JF&d \d8аxxʕR~}1CѼ6bci])ʤ{ɿNO;75~`s[vz1^-l4:#ݞkoٟj;9 ^t`tZ?ٯ?a yEDžڭ*D+]Ւ,>SWC7xrIO ,ֱG/ִ1k&)i˿^n+(]iS$8_jדRN\:[pRޥ*aNqJe=Vt?7U5Vxpٟ6\ sl|GujqT%nkۧET Rjˊ{J˚oS-v-WzMWc4qh[ɚ9I] =MUYO1cҥ]h9""ݩf:֟!hjhisҨDOZp7?5~-1K%Pdո5UKf[IjNjTp)D5Ojˎ#g/4/ɚu&O 2Dɫ.zUH?5^*稢*ӱO\PBsW@  7ZdFO(tz>sߧ{hB4Y]3[ p(qtkVȱ݁=#S .W8qֲ,Q8kD%NWrGh4|Aqf{8ڼ Y^ Yz 9u7GoJZ#,DԥuEa8+$Ф9skQ puF{iLrȬKxz';9У҂8Kp=1Ҩ\FyU{52YMsIl -H<q)r:kT%hVQ&=Z)a(Ȫ`СE(j=ol1SɎG2ʦp>~;>I'bP{SxR.̝Jiˀ 4ZFw'EE:SSaST{ *&si֏3¶ua9Bsٻ'ҩ<~kV %]MjY/?y'Bk+@h= +bBsyՔT6Qrfb?49=y9;Ss_cP[>wZU.EJ&ZGH"1e+kj7Zɺ9<5y؉.m$Sl֦aOvzHQIwZH((QEhp4'nHݯQW G-%AǭzZ-z&{>;n{ʔ#ءZc^]N|2f=7  E8 T)~ݘRéL<T-L9kP˄k GWxCvs 0}kq|q]j243r<^p+͵Lsס漋Prpq_8\<\m+J5>ӐiπrjMih \F sq]G4p;ԭ ?ҷo05ueMs #Z˚u||ت*Wv9{iK GT9oxZqtNJu̿yUSF)]hZ|OVֳ zyno_jn`#Oޞ47(G5#;sܸܬk2ׯ< G܋0S-{F t]'K+.F}+s78wPgDLpjL|귻:ʡ~~jPvUD[EYȕZriGuѬoQ|48Wj7to.ھ X|8O͜ u\=P!zVNe7 4ͩ˙]R{^T:Nh2/TO(SSOBen.6쬛*{*^uхHţ.y95$95ɳ8U풌_mO)su]]1J+wU%4S׿qkTRCSWd3!r*;-]]!+<\猚X#1Saft5+\E52]sG&-ѱ<9Ȩz汥aL֡^MN4lia?9!bjfjk*=q+P2k*ӵ{mFhjay*2CmkN(.ABcMq_9[V Ҡ.[2i^w9J2k2zߞ5fߕX뢓d |eh|+KU}k|[*?v } |0NRyR| ybJ;409RgGK[41[km1ͪb'=QPwbѓkMm075\fI#91{UZwkZ\{TZ\ÿRJhy>Kq!⽼,!;ՠBǃ*cN* w胦}+kƶ'.*:yL< hpSf{g#B+x1 +Ӄd⧽(z+#&}d/?'4ջ8?5'6*-njўZ+񨮮UVe;~h+BV84s5JTP}*(䳊Q#?7^<ο21"t7^Ar~]u&dxsATG=  a?hfy2:,]Kno9*>rɂZ,kw Q*2[ 86Oynڣp3&zSޣͼ0~NNqG9\SςzP?!Sq۪gmtڔ!׮Tdg! ]x..l.%̇w>&寠90]KtӜqw.p7]00L_z<>B]Vi?>Qz԰9 (ch.}խ6Q9b*9]f-枥8 Ȗ9-][`j0[ iGa}7Zقlx_)Vۥ4f 83C+*Ue^#OS1* W{TRi u)]' J pxXpT^%bdo-m-tF$ W1p+t{)\Ё= p4O;-uΕ]V1 \;W1 q]4ь-tZ9|-ԠVól?5J\j5 X7K`VSBʶ.69gJwuAƷ4:)Jtks<֚V՘M0o3ʵm*TӢ׏๖Jr+r#⺩gp\9<>"Khu~NSՓޘs4ѣZΞm506sqڠWVC:&Nm7z$ʃµz jEuV\rſZϸJFi%DbhسWa.6Jc2bڼ}aMǚ. 6V䙆G˫()U^@6zpdJ)"3ʑ~+l!x_{QJ6h>j.gWM(N,*k׵@o$0}cQěyo}I]"76=ktM..BQVm*=: s6\f>XSKT TWo.ӻu&Es:L2^)"oK?_Z%OP1>:V;Z+`Bѯ>p}FePr樁O5jpk|&rЙH]8lW \\֭]#V×7GqB l U*/U 7o. hhy\W&oQpR(6zg3ֵ++F"_gQdgCZ,P8&H`˜Îxo@D*Xͣ: ;2gWJ̽Zp;2g iwVW>%7 ӵ?5шsx >Vu ~J<`YS%|=Qqv7MnGObzTFSLMg~bpZ"5+Et'o51)6sTCH[2WqϚuMGzCگiSdu;EQI +_3$ӳ;4&Ɔ+LvFZ#\tOk.j(]tvDJ(ߦk`&/}fl85Uj睉Qh<~$EJ{nqI HXu( 9~Z/٤eA9OGn6j=nϷ}LDF.4=_W.#ZXhgSTiެ9B Z*SU^=NPEu}Hǹ9뺣e U[+8Yr)jM6zU[?v,B%654z cknpV͜lmc\jPS,=6E5Njj3W. Yss/'H?*ϽcMǬ@"R lR)MjG(p?H::_jC[FUD[AsYQMe-T3ܩ\Ψ]cJ[ݙ^j`|LzV]6þ;|ߝvsJV:IkV(\/Vō>ka5qE^0zzVwU6$sA{Y=zoʼnd 1Z S7vRОQ`Ʈ7o?LWQ!:-=,ڬ)^)hvFsVЕwܿJC\Fm{Vs?j9+նڏr'"֧e%,r_Y[H#xQދj~*jr#G ёp.ew.-7]f2;Գ˨ +kvIVSĤ9jjv̓D?c}F9ĉ_{0Qӽ_&ҵ=V!o7˜žbW繿U0V= Xhݜz#r;Vt' rQ$VwTma+dž6itlǗj)"dcRT2FY'ڼWfrpfqz٘TZ6wZf.zɰҽ]td#4;l.s^4\2(}Wę]ZJԾ R2^gj2ÞFcԸb^Z,<9KSyFyOBJs:;WNf.^ Y3⸝f6}+4/Qu<t۝BM[?hnnO<׳xCH#LMo(E:2t? U$=tTqV~u+UcN01[GjpWA)29hbfje|lQWug^[dpH$ ]Ow0mvK".+#MUyUʔΘMI7=j7B’iUqj)xY幮MI+"޹]c?1[m}>W>orG%xsSN'/Z_k,m@";6^LEguDudr@nk ÈsZ:Nszrk:(ޫ'u`]%܄*13<%XZ'U@fJ= H1zO )`<º;:y AT_J̟GAZKr Wfzwvq#G [WYޯ*REjcBO(j+zUٔsڣt*۟V:ׯ'(jf{K޻mG| `rOqU:YY#m%8Zv[[KEQ9-26+Mr՝>bkb{E}ry*QNoRCx-\kó]ִ84YR[?Zq(nVS yr1zׇ!V-我Jq_AXY;D嫇8tC.0n/N$e7uNV󚔣iG6z,궺 eojG2xZZyJ=F(?cLۇwZV̪=.O8pOVU׆&_%zƘ<kc%Qۘt#ǜ{|۶zC\i y *׿sMEK[s,ի9y\7^L<fD%̵qkZV<ݒVFt㊮p9"}s]5%)DF~>\VNl'e߮P_V&PM\ +ͯQQcfĶmyGl=k1ux Q"N]YRdpe)ѕeJyrp84XtT̤,'Sy>e$Hyn%C]0z# <;erkμrDѵ'u5Իwq_SDߐ&sI8rVqֻos"1Nбs EͦvxG~NTMӬ>jGn;JqW3qD#;=;85ɬDՁX~ET9QҰ58ҽlάcQ\=n5jKRhD sܾ=j 6ia8k# 8ϡ4}Uwjp_V/*D5O{ x4w sygYR߅jy] Kb젧5k!I8WՁ,$+ lȟn|9(z_{B\\MFrIzj\`/Kf ǐi%5L?+=)LH܎Un)ecn%QH8VNkZr^!Y [uJKsY7QnŊ!MWS {w}+.PYFj]9YxJSYwCҔ pz2֔k} q!B?]62?6kMy־"s3Q(Ư6dlU Wynht}1yi;FO"`kt=тd E&^q_縺MCyj8qSqP94To-Zq^1&*Ijy sQ[CXw U&;e0M~kӵ0+KWŪA3U\d5fKއ5pgjS*sҸ],]Vuok|QvpٳMla^]0p5[wAqJ>6n#ϭ}>kYH:34 ȹϵuV~W/DQ'e~?eZZVȎ% ZgqRnn)q=R#uuf]E^-g u#Zkw@QGjZe J+ۖҤm'QR=qRָm']S+TΨVM\GT}5\xMUԹQ$-ǡOFYĎnsS6rкZ晜RKDO %7! h:,?J"}ܶX{^. hT=̳!*;cCݭ4mLp;@0?v<ˈaIrK޷9:V;pºk[qW8 vwhxWr-TpK-A۴QeS1upE5^֦wJQI+A;kQARH|üzĖ$;@8ҤPW v5ZPý]ӊž-vƷX2y:Hbt5 +HqQn9Fz\ "S~C9K}ⵃmu6ڞ?J;b QbQM*Vd T9l4"S5A,J26 8&pJTˊ<,e`*K+wUI[+"ɦ1Q&iAݫtZMҪOxg\j մ(JBrHҺkH~jn<牢w1"R*gEXire#ҬY5үXK*дn:T-%q*si#|:I_Cӧ8Z@n+pҪp:nn Ͻ_#UrUaѝZȸƜX4?QӥAj}l&W @}h0ƙ23\.vڅ{YV Ƨ?DsW~q{1^_EE[-:5!A#'^ui&)^ ,k|ԩCJ0\W*'&֣٠|+cUk:䕊3VahKIp87aJX{IR{.~c߷/e +Q߭t+9hs *"'y^"EhDMw'(QC˪Ԫ${?(A{$1W cBÞknz9sw,F-l{tڌC.s_AT''P=yZl5)r"1\]\Zθo:g5Q͗|ΫO! Azmwos3W) Jk]\*:/RcF"!¨i=;&ݑKCUM{g8}<0~խzv2xu`iq#ڱ%ϭ]yF+~U)Dd;sTcӧ\]e)쌤,cqr>%ŻFJk.廛ga^_73rԒ~錖uvp3t*9NMZts#;+}CF1kfs7A(pՔÌע_%s\$SƲ%Zn׼ecI" /P\jׇŽQ*G,96+)K3)0 zuF6HQ9+ ]AAۀtm @REkf?XFѣj]t}WҼjװYSnVjKnʦ:y=[Gh[\Zja썓7=#+.+㚝;ns:M}j҉K3 iq]49i2^ZvmEU?-춳uP*>fZz-0߭e^kO)iee^!\WTRuՋy޷v9N{껤RkCHھ`#zS|_pmq1[nz_T .'2/OjpiC$/ Ð 뎕v_KOa[#3 ʽNcԤyD)j0JMfʔ9ݶ [šI@zskslﱙ/f0Zgܕ殌9SwG)xdj{ cY W\5}N d-✜苨+'ZݨBwWgmgu-xjaTR+)MR@̵纴<ڶ'KF\F=nDxl8UZ`j =1zbnL~}<|:W1tֈ롅|"Ij z&ЅZֺ~2)VVftzkH1YRK\_tp*VupkV1B}+|OrCWq%wWd's"4ryaZ4{+k,޽1Kgb49pSvoA_ ].bJAj(+n:ݹf8&D";-w(A]k4!q][k+J2јIRM^)xţ%eiIߥ}/*Xjtާ :Ό-ik;R.{ hHW9gczGSG!7͟S+CKĠYr@kx-h+*5%8-FIPdb4BcT=$"X9]h9QIG{k%)*1AXIU5ZE]ҸPD m:8AGs'Z]9ƤӤtƒ{K]uj4SJۙ,aFQV4}? Y|UkL!rqWU#$ނ{ ;d{=dNd0l+uAIݱs4wR8l ɞTPz%ǵh׹bYxrˎZ{?zqzWvRög*:iMߕQ{$=RB晜=?_OTyJiλZ$trdsS`ꖓ?fl룕R#9V֑6}^C;gqmLzeT&j|GcynOk2̧ RJ*yVHQgźݹ"6J<ˁ)3xƝ*>J5)6>PwPGj֟_q5#yP^ix|lK8+=OVG0]O(ו$=fǶjqE5E(gL1n3w֜Ay95xg ϳ=k?Q_=[.W!%.\'n=+5})YHATǸMu{q]|22buIa=MlaZ$w^R3$WDu*;GD.Tx-g/ ݱZwV+<P7 ->gNw>ҵTY_R]}ּšE!h seF=SZ#XWx\B:Md&ÆWVK+n,~Z<qTZF+mv5שz]*rv[uVR`z3]$* /-{P m^*Q׽15!$q0;+E~CPOo֏{u?_Έ? ^Moc=ݥc%]&iZ&e2U_]-+&{4ic2X*U%c7TgkҥS Ib֨*+*{$OM{vV(EҽǬW-VQ#] /Ehd+.r>j_U[V[?+T8474I057z{A95A;ՋȦY&H{WsMqZق%Z ^Q^ujDkF T"DWWR얥5jp+&W޼ѹQf{VNos*V4\4fyE'X\<~e;gFfBɔ37K wB8oCZZoaOMZ3rC|)gʤuVx^;Mj[޵%rx*זt*)SG=)Rpnb0挃֦2V5N-2]hȭ-/P-T cY}Tj>,]w@-׫]ӣDZZz#{\26>nO.뛺eMt ANT\ T// ub\M$U`2VsԨm[ʻ}kic]_tK޺9Җlj\?jڶVv)ˊ]C.jm^{ ۉө;*V?ŚnՊe1ԡMFebJ:c+]9~'ÊT$C] k򙹭&wWMԖ$m|d᱔*[Fusd̸8Q=W0 X|,Qڢ>^6kw[%qn|m/-T0y*Dd EvVZ@8gĴ+StkC?t=vph*"a+exM~M֫=|6?>UFvj\vjϸ^(Ι15xprrW p-۵_]Tg&"+kꩵW 渍Fhle\ 1}/n֧.Or}BP̌s^En|9 i-t>JF8 _ ֗-CXUs6(*ƜiG3V^5"*p̓V.RDomk-Ӧ7OzcIɮkB U$޴rl(WOsFUAֹ}v:?2xWid)dVcK,ٮUtɮ܊خN.'z< hX5"՜ԩo4lnN:׶rF0SD>HTOe5eͽc';ٳTnvhFsQ*\}s/5k(> |ɦuKhJwfq%*kC};\wpڻ ׉P$Pmڱ-0{~UqDByNcH2¸q3[X~/qM9zIOgi1W(GSɑw5lD=8 ν)[fVߕ"$3I'qCjy&,tp8ZclNrޣCի~ vӴ+ۘe[MpkN;V3E:R"\*xU+9&2ZgܵEU9Li%OW4-@8U"?Wdǭqqܝ_1o',IrZK#fMT۽ h[i#'ւI׼i$p"Şltag=*J59Uik! ;I,Z"s[B&rmܞ6HGZYx5J@ޮp[Ч#9?ɶԃ´ߏ5T؅ ϥ{ LQ#{&+ZM".{W㱋 G)/bÓtF0x@!ҡbp+*b%^nMQW`#Ҍu8\Q>;f ovxr113Α幯Os+J|<=k'RnֶGMk]B(u"*P[(A^TVP61yosi%c>9jY8Z%W,}}+bJ^G-Xs-5]~+[Mު,ug޽*xn Ȑ9f sMj\)8쎨TR4Qy6}7M&?*}ՀL:VLZSJD(rC[\^+{kFZ4-=ڑϴ{<ҹcJVW7U;ӜcެAF9|̝Rt#9Z uEfOpox^שVpwއ6~V%TܹLWHǼҐ X09!8yT.%RVkՏQ4Q3w:7+r.#fn*#A`8O~uwI>^|\ɦur$H/}j0w&.S"TԴMe)5jAx -I!8[+mlj8 ݶxsYI,NTN:gpʖHӘiyR̸T ~51UD?rZXQ\6~kˢ^5d2SQY2yMݗ%`ASo5{9JiUUa*يJ25-ۿl$uxW3.N*WZe~zgR-8aҪ!ɯ2kjݗ|5<\ݎgQf[Th޸w ]7W0rV>כmNklN4}+eMBHH*1PxmJ>ee9xBC!j\7jLk֎2Sw^Wny`+еb<X?v'ZW<𳹛u9>R7&|/M\#ȬI576yz67E]ٟ+\XZj3gÞ!\Һ$X UU.%/R{N1d۞ѣ|jӯ5ZT"JZ8dؤkԢpVf r ZODr־!3~&S\IS;^>W2Ҿ SŮj{hBu%UST{˟*'Mak77!ۚɮ&F^P)O3&V[!n$dczf .1ZcE_Pm |7bjއ a )8]F,I<|˼fC\OV'J Z%b^9\Σ 3_ITIZG<鮧ǖJh_G-}zA8 OfpՇ.cj zyr|OĆqaQїZWmn[mOP ]D8ZXpVknzT-:9!Z:FKGLdI5G] f|)0sWe\(j2!ʔV e\']y# R sVrRZ>ZܷxJ!EXpRP=qS"YXjULv:U RETOV2JEe)ܫ$2 ~ ~5hב @ z'y!Iy_T(Y6)|ñNaUVo%**>9{U-צ#ƘzR"0i~W.if]=@e}52]S^]g⇋?Z&D X!=|n'Wב:$⹍;VGuCr *rGO:u&:b_Sj-rzBץ9jZ͑ qZw7nY&m>{7ɸ ՋJ26׽GO t8\*^ C+^q /Ƽ{VI&~:})ft2Q|v1yg;뉕56Ny9K*RJݐ&U>Su:NxT th74hnV]蚮 Wxl_s3mjq8~׷|#^h^'0kX<2&{ GԦ־"{#4C54'lj̼%{XnV i94W;3*\*ʽl ҜeqZC  ^a"ZC~#,טbS_p Ss)DCz~k_ٽ|/=kezW|/$D.@<+PNee~ɢy{H9exVMVz*:Hڹfӭyo43"Yf5K "9OZuȜg0NIT8ʓmkXj 3U&;U$/np&7[Г"՟%+j)ʓֽ|UPb{kMl%VuRa'^[Tn5kJ}0w5J},:3æ9FV0.^I+w#8:kGkGF>YҺrӍZzU$-dE01w&gC,q\4?`2VR8jRl]L<}^[?5zM3[R=6Uk}+G6+͹gڽFFLqZ|ΌJ-tՙyw?B&fcTo4p~F2*{R}O<Ԯ oXH_ktf)V^cd%FG5ok$ѫ$%?Jl4V x#jxm./5Y_F w+TIn.G+tŸ-oQL k3(.- gBДdfLA#&1ON RT])VzLJwGO* 3 tRЉOMH/$ZFy 9P[w$z+ -ʣIݖtm1- R[ ҧ¤|t7M|˜,ZX9RvkTϰǷ׽Rfs.l+ڹmnrJ-t=zz(HO)FJsHn `+5dךxb:WneB2ѓJMu.ye0LT3a1YR0Z7mnQ.vɮJRLZ5)Y6 KَH} G O]>WRFuZA\%8^E ?. cTv-kfg6;j4POhWU.+(73OS<=pǼkV[¸#X؁$j܆d@DqXYƣr:>ZN١fbǵeXdF桐ʞj)95CԎ/1HۓX 5*bR+]fRskxp\r{\F{gCJcVURouu&Mz.ީwk 2~4W)OᬔS3 kcUYqjD5/)]5+gV*3O`}*G R[x 6J꧆)M#ԙ}v L~jF/c4FU/8iړڦ-Hl1WsUPEg!BNdq?[5u!kjN[k"rk ʥP6WBW ɰIb1ܤU+Xr$g NU4֝?\6[RDNke򥭫#*k :¢l/`5u돲m@'+}40yy|2t}7 Z QLc/ǭ~w峧^RsRHe#P%Y:MxjF"I\Yx7 PJZ3"(W1G-]+s֬Pnk7)jNlJJZռIDjo1WdqQE_uj綧Vu#gA}B@t'^mT %4e6תAvu!OCiBvDEf][wqYח4%sM1R Wx][v^VOJϓqZð1_ISTՎj5gvzܰC !tjji6 >F4e*lkBU wR3mX(]qVz1pB+Vj̸E[3/5_9]Ue9kQrW9*gub:l,0MvFAe,r5=z[3ڮEc_m+xHAM Uv6~$֝Įv|F+މP}$b}jhPFyKF&eImq+>ןA^ZS$:&Z CWH t,#̍95)I^$)n>AzLR;'sWMJuh&\m9qv~\-Һ [)c0SV6RʣV{(N]jpO )=QjT5mMFZ;]׷Kr{Χ3=S°q] 1\v[ז|M6껞$IeMF1f4 32y\/\H^L#+AʩhqWfm>ӡ@q43yתxZ$hFO= vfT#mySRf|w1|K|pk%\RYd9|FR7 ڕB$_p*M.L|{V+5jvmb29iGbT4G^gx󋌎ja2ˍQІTr5.rRAI>IVyrWsұz.:>ݕhJP`[?i}\g TnaR=e˜=Z42E[Zg:U6a].ΐ1]V{Ek_HR&*H)ִ*=+[MvRe]հt;>{l>PǑroH I7fk+y[3喆6ZZ)74W*FR6?:nkXKHk6ɳmm"Z|]ӹ4OZ ե-UH?%zQBŧryM^IB3QXUZBRHbTҳjeqceYX;Z&cU{w/I=G/xak2oNҝt:v`[FM2<U#:.Ŵ9RzV;'\n)݋S.X~4\W ZSGMڑ:v-/q?3<ў>66?jX{hS+b۾ZϺk{4KH=N:Od_py_ƻ)m* z"wk186+f[*,ܻ"AU+Q4frc>5&{ֵ$+9 V_V#-liqRHY[)Hdkq6c]9$/SҚb1;g֮8jȹX+Adf,]KRƜ[ulft}1] Ww_jW(G*LQ9r6|+݀OQY…(Ib'M%t^ХO(/u#q6Wo>7VZw5ɉINS5]`sҳ'|YW,$)ձTUs\~uZid][N^ ZrNA7aZ]瓌ל~2`kHyyU?t-U2g!x9IS1fgh-a3]CcPͧ9Z'SL11L]xIZ87vJZ+mf(k~7T5+d+* skIMWkWW#޹/2$ ٍ=MAՖ|gzƱo.g ƽu^MuQAyuH~oR{sm|mj0g%K͌7Ai:pv^hks-r&t8OQHȭ6Q6Y#w'ҾNSuԒAK*85j/qjr*5#k8&4*;HۺՏw8mZoh+0*՚9j]=CI;n1" 6f)tIUs)Ȫr)VAթV)Ոӊ~+oY$4ajm~!Ph*`m^]Y'6tcp9WR-bO+iF6N],To2N:-쥓 [n+s x*ݍR Qҕ;FcI&qȬIA,|ULn[DZF{m*C]$O"gO.qlZat;x{.&9#宛Mҕ+F#U^+XEd7e[cY^ [K@)#P!L>TPӚO"!V榏kASީ!4 Cn5r-٤(aϭUU8g֢hct&4|Lv zM;9Iv; zҰf/]Gb7A-նh^zԽs=n,X uLC-=j;3j#d .cn-995??kOi|U[:T#kX]*/J"GQ[(R~nBB*99W5ϧ5iw 7jMˑWMCiN+>taNn;fJ櫴_V+>+rP]_">Gcn6+V\j VH_ybͼkм< vX+ב^yDnJ -JC}c43ɨ S׃-{6W8̧*i8̩rfe\.I1eђn$S5RV{rƂ3~N瀣/$P9:% f|jvl$vF-uM r> "J|?Uw:Qyҳ_$n+k*㞜UZ5FsֹfŁ/]|k*s^ 'MHK>vg]c1cڥ{RF\Vc'3NRwgk1x3Іǿ/kzٍ{qڹq7KӇajP׹vhg9&/ w6߲ 7]쁫2eû+SaD̘,NOy2ВOZ5ޑ\/'k_X¦ڙRyw9D{s\޺Ȅ vTӍAɑU|Շ?>RtzA#F\Ͽ(돥YQ`<ϵ+KrIY#w#ml/Z{ L L&dznwx\Yne Y$jh6o%Iabepiq$Se*W%z<ڜobN$ Sfs^o36e ٫>:[T+FQZ4g]^b>j(*4:=*>35YLQ@qXnY]BwnF|Îhc\YƘǧ;>ɫ@5g^ZqS0SʴYw@9wxjxcs[n{jh!RViz+yBI" SNjRqFR\MY`ZظeޔZyիea,оvʱ@_f, 8ihQ[tǽi;);nR@kI# PqKtl4[59xZKSVsVҤOj8R) u%SLڑ(zjezBj㨎!zzt^%34КƓ?4|{UJ\y)!&Niiq \"r*^}&})c5*a 'z9fу=6銚ڄ݆RZ[~jm$tZ==+xZk} :UMݮOSY%O\!ĩnT>N F20ZZ/HzGN _~Ӧh5[LQZi%*|ik{]o9k ޕäΈ6O;$L8=+rZĊSkgT9SX,q.}E:VgGy.& Z- U|1**mVT5vB[E>3`<;~QXYo=d:V[RgB]Rm5ޠ .kX]Xz@jo<ڛ,qRML^ODsw%9 |nӮ4v>&^"jR 7 jwvGhk*Y9M"{}+'M;&nFY䖪yF^Aob/(PZ Ze}v+`VcJo>nZxAWxjz}:@"sf*kB-+72|ҫ6G<,s׭W32 OM \)8q\.t]>tg-\6zL G%Y> q]\f/^e?v#5&c qھ3;K$S͑_ :K;a%`FcL\sXW2ٮ4cGrFIO[ߜ5_յ=sWlpVamH/g+GisiV8DN:%koqUFZqvCk \?R ߚpN<Ć[w|Ƶ-)^fJ.ne8@;!=Fѕx[ݙ2FŮ$ALDU#ժՁ{g4< ct{|ii@.^ѬGZr‘myV|5R4Ql7WRTYBMM,e^[,呍󶺗jJr+ѡ429; Z1/`aRimսzJyD%λȤs >gktfYj"p Y7SqwD91ӭhZڸݬ ^rĕ)e^&iʢ44;G5t_q~b) %`ιquv7[݁P*ިyי=QОM/o n< 0>cU^"kIUiɌ\~78q])aSJKHBo6zHdLNYN:RGL =٥۪֎mvQ T/B ?ǞJ;n .THӃ]BiRc=`خ(Iޣ;(WLJJ{i}G:Ʈg#Ef0`fxRGAFco5痶f2>wM #cּ^8~(ڜ=v׌9wy:[Zƚk0\> T[ANk &mݫwN)Zɣ?3']K RpϢ2G>{}+8c[+ ϖ{2*SQWh]jY f+-Zpj0|؈]A6k1Ή=oiqNEVs1i!%Z"3] TgsQZiZO `uW$ssl."3\IkTCeC5_ld՞cnHR^ kKoaǸ b>p+BY#qȸ+ƌ֖36q9 B]BVM]-) Bcrkb=9Y:vw:kE7Mqz]Etw+(zדrMZSfFy+/PⰊ5#bjP*F8kh7dQ|Y5LH񂆲pXptg=DCxִd s\ַ:uBlV;2=aF8f2s2):[-*Xx*5&=&WJ}#⭛ Z:RwF2赥gH]-# Mܴ0l`ⶭ죍z-[P C1D43 : GJiӊН^I'AHNJP6'ZH *Zf9yjЧҪ+څԘSONj3N^ ȧVҪ(zn7Lm#K 5zjCTqGZsjVln:PFj/ܤ*ԋSE9j^ Ug֜KpCCg41㏼i>Ihf9qMﶅQɡ~!QL?K^mwzO= ڧ2))Ȣ=Q[iݫ! ,)Ɛz%^jcۂh5s{WÊ,Dz)lԎjƞc(_PQ9LU kҳ.l˓R%6ZR6GCꨣZ&QYÊcr*8.Wn{_ү0]Z)H$1њ9xM&0aO귧KWU!c $qSLcJ5ye<5M1db’s+ $aZ FkQrc|TCC{ [*W=kvόտ7#|ܲ:i#UYe88jBimbDOVzx],p$+TiTWW7<=mܵ#^y-몃UmƝIMҒHֺ"=T2߼gqS%В!5h)WUp{W|]*+*IWcZ@5'qu]]9$&KCӤ+7[0p[{ԭ|6jatvsh6,?Zÿb'5I q2LuKR˗5VE$ hȯV8wN<k,Ep5 y x+ΨN<i05ZY91’Xq7JVZL5ZS馝mܼ+Vw]WQTmݢeZΛ;X.26Xuڲm< WR"V5GSHnۑ>a ´%5aI]f74eVnAwFJѷS^ Lֱ͓0kA$߂9WR茮J9FњUuLhu52-v͘l5ʙD@̦T1cĦ&Qbtf#'V⛎Ni%F8]-SF4\^FVrUۍ<+,̵v)DU,]f\;Y#+W-t?ZzBȪ#ٻ1k=7袲0>UIᮈPq9eqG?i%GTEtCFG˺iGRՑFc 6W4ƥjO BjF>*sԫCftД:-5O4U!n?>})iUޞ6暣4Ђ)Դ)_7ˆQ+{QGQ\ƶ5S\zSoZ~ 8 ޝŒ \Bc旷JJ)6$=yc4OI\RSAjZLoj?L4c{Qgh.ii*\F};L: *z:u4>+M1ޗ4bӿSR= #}/j Ө,E1G4d 8d9:ЖفqvgҘO E,.G>?-OOWZ'jCK.>QXt`VxyW{gbۊ[1k/Vjڭ5U^;xA'J,F}*Ld*/4Ӱ=v u}MQ&|6w\+8;7+ xZo+l}ڮ2ºhVŘWՄU*Tx19gVTj>?|;W$N&IGյsV"'YȽԩdڷtmtkX`ž+BBݲ\a*WLc+]tF%yZԂ5 ]$5"Ev)>]Y ?+I6S,ResIO[ FOօ4$#gS)XM jniZI4/ZO&r)ph\m+Qӽb1ɥR}ET|qƙRvZ i3+ۊU<}w)٨T O^R֝ښZ+_ᦵ;Fyz(jw:Zhy.ij'Z)}(jywEUXOEt;o~hVisL}+ó⢛JRi Z2sLlOPi Fi>_Z3K4?(U(k_IE;(F=E^&?߭?4+/RLϭ/қ?3CR@4jқL{|ix;>jJF>;0ӻuvLxT:>ke{~I&W9JC|ie-N ,|kkD5!Rح T+JBw.ǠG,$N{WQ>-QHsc4,eM蠒e97zN=a8 y9r9j?V!5teExZ7aRu~? cЦҚJ^:5zv)1cQ7_}WޝtC4f!jn 1ȨMl4+IڕX>)^zhg=pBhnJۊ&M5LQ)> pjUz\s?}fySݦZLi.ArL[3#>EShoZVͪ- Gi? halNC`sD?OOW. t1쪲ܴQSZJV<}$YP+ў"~V{-uCc78[W_]ujSҪXgr=G"u556iJS5, Rdqj .yd)?vM?Fwg2p,VҎ6w)S?si'tg-->c&yyP} Wvqmj}jJB2Cg4ҏ]ݦ\ӓNOVKtM~2ܮ~ԋbqW5)E=:-11VLJoʤ2vte)(rzsR!]:i9s*h:t*n BiQةNcgD!Tl*^t.5cNOP`(T2B?p  P 'nkU hSstk>oJ(B4"uT=sN^)Zia?Z>UX[^LfХsN'PZ&Eg֘ǚhz4 F5-[7;&= ޔdF0>4B[ݤMXS)TGQwSCv})*O]*iqE2ENt`Rf 0AӚќQOq5ޣ`{݅ j ]j;)ɣ>Y7- &>lRt`4Î9Cj_qJ'9DKIQJSK*4r{ >cE hou[0oF3TRl9:ќ/z\/zL74t:ݩ_]Bz7*;&^G?JKPqLvwS/I}:P!s*n'R(IX/i3KE^ӳRťz}ڝޚbچ4ޒCW#m S5Dva3 GRZCS{):SLvw?ݤ)V Jv8 MŽQHx{ 1QuvhZ?JTshPI*EYhivZW:>(Mq((4кh FjȖ~\Qq47ݦ!ӳ*'sKIhBy/"Ӫbњ(an;c-#Î)X|jZgzy}h֣v9=ϭ1ibtv4i34ƱBH)~E'4sL qj-HxM!/=)j,N^RiiYқ3Fk&ޢ4/z/=Ӿ>n1hw w6wړ9Qga֒JVi;RQK,GjoA T;Ȧi'Ҹ 46MbFhw~ WwݦӖ K ySiˊ]B I$bNh6QNvJ4hSNQa/F9"V+B`iyқM! >.hJ\zQsJ ,/ҝ֛rѰz JԘ_e!ԿO/Hn7w^JJ-&h)^Svxqzu/4@44OSOA5q:dț@㊲ZѱҴYܪ8L\5DZz?OG7a$0jDG5"}MD݊5"W=i3CL4QT5 Rie/lRgօ 3l;֗ʆ47~`›\r;T6 :_Cc >ZJOȫ.3ޕiKQ݊zvr)|—=G/TءjNi: \"lsu73'g֏a1٦-aa߁N3.x}*Q֝:zJkrj;&xw5VЖ'Zm+SЬ&i)O@ю5H59qMjLnhh6QvLRvU M0fzIK!_REQߊnirl1cei^abW%U+ƌMϽ9M`sIQJ*F0i)٧nwbh<jHum 3GEކ֕g{Qq/J>`i2~oJ.1:iqhFiKPN)cG2}hn/mԴJAuPE* jgp]*q[AOŽJozp I1zrSzryK`mBcҒݾ#~tv9 Ϡa}hwv Qޛލ.tЦZ4J>QJB=)sI߅Sq_\H){Ӱ$/CO1iԴqOZni68^(R?RuAW֞~ZZ-njU(aM fj{2'z6z]6 F z~1LOp\v֛WChcRf oGQi\_…zsIN AqKI]~;SyKznj(mhn?4fPu/(hI1ӾqKSvgM%O-Zu3+K酦Pz7u R] nh7}[RH,7ޢR/ޤnVd-2v(N(SF렅 qғ47q!r)Zsmi3K1zRu⡩9AZw|tSsўi2L,.i>ZL:>S1Tf\Qi>lFi kS3JySK3Ng4ӻn/I %5`1:&+_-'4fɣb iю9LwC?zF拆)  vwzRt;sG@[=zяz4 hjΌ4uZjzj&>niR^)Ofck}dIQM4H9jaZhs@g"41LiwJj6Bl.|z Wq] h4sMD%5pP8g֗!h)4N44I1izSsFhHmKS:z@RR0QT-i{RiN4E+ EiD&p)񫶢 RJv%C>1jtS~\׽J5 on?=EWap>hǭ1?@ЧCi64uޗ=W]ޗ5Ih%p*6FųBc8?IjLEXMHҡ&SJNNƓvzPB scikit-image-0.9.3/doc/logo/scikit_image_logo.py000066400000000000000000000116721223313777300216370ustar00rootroot00000000000000""" Script to draw skimage logo using Scipy logo as stencil. The easiest starting point is the `plot_colorized_logo`. Original snake image from pixabay [1]_ .. [1] http://pixabay.com/en/snake-green-toxic-close-yellow-3237/ """ import sys if len(sys.argv) != 2 or sys.argv[1] != '--no-plot': print("Run with '--no-plot' flag to generate logo silently.") else: import matplotlib as mpl mpl.use('Agg') import matplotlib.pyplot as plt import numpy as np import skimage.io as sio from skimage import img_as_float from skimage.color import gray2rgb, rgb2gray from skimage.exposure import rescale_intensity from skimage.filter import sobel import scipy_logo # Utility functions # ================= def colorize(image, color, whiten=False): """Return colorized image from gray scale image. The colorized image has values from ranging between black at the lowest intensity to `color` at the highest. If `whiten=True`, then the color ranges from `color` to white. """ color = np.asarray(color)[np.newaxis, np.newaxis, :] image = image[:, :, np.newaxis] if whiten: # truncate and stretch intensity range to enhance contrast image = rescale_intensity(image, in_range=(0.3, 1)) return color * (1 - image) + image else: return image * color def prepare_axes(ax): plt.sca(ax) ax.xaxis.set_visible(False) ax.yaxis.set_visible(False) for spine in ax.spines.values(): spine.set_visible(False) # Logo generating classes # ======================= class LogoBase(object): def __init__(self): self.logo = scipy_logo.ScipyLogo(radius=self.radius) self.mask_1 = self.logo.get_mask(self.image.shape, 'upper left') self.mask_2 = self.logo.get_mask(self.image.shape, 'lower right') edges = np.array([sobel(img) for img in self.image.T]).T # truncate and stretch intensity range to enhance contrast self.edges = rescale_intensity(edges, in_range=(0, 0.4)) def _crop_image(self, image): w = 2 * self.radius x, y = self.origin return image[y:y + w, x:x + w] def plot_curve(self, **kwargs): self.logo.plot_snake_curve(**kwargs) class SnakeLogo(LogoBase): radius = 250 origin = (420, 0) def __init__(self): image = sio.imread('data/snake_pixabay.jpg') image = self._crop_image(image) self.image = img_as_float(image) LogoBase.__init__(self) snake_color = SnakeLogo() snake = SnakeLogo() # turn RGB image into gray image snake.image = rgb2gray(snake.image) snake.edges = rgb2gray(snake.edges) # Demo plotting functions # ======================= def plot_colorized_logo(logo, color, edges='light', whiten=False): """Convenience function to plot artificially-colored logo. The upper-left half of the logo is an edge filtered image, while the lower-right half is unfiltered. Parameters ---------- logo : LogoBase instance color : length-3 sequence of floats or 2 length-3 sequences RGB color spec. Float values should be between 0 and 1. edges : {'light'|'dark'} Specifies whether Sobel edges are drawn light or dark whiten : bool or 2 bools If True, a color value less than 1 increases the image intensity. """ if not hasattr(color[0], '__iter__'): color = [color] * 2 # use same color for upper-left & lower-right if not hasattr(whiten, '__iter__'): whiten = [whiten] * 2 # use same setting for upper-left & lower-right image = gray2rgb(np.ones_like(logo.image)) mask_img = gray2rgb(logo.mask_2) mask_edge = gray2rgb(logo.mask_1) # Compose image with colorized image and edge-image. if edges == 'dark': logo_edge = colorize(1 - logo.edges, color[0], whiten=whiten[0]) else: logo_edge = colorize(logo.edges, color[0], whiten=whiten[0]) logo_img = colorize(logo.image, color[1], whiten=whiten[1]) image[mask_img] = logo_img[mask_img] image[mask_edge] = logo_edge[mask_edge] logo.plot_curve(lw=5, color='w') # plot snake curve on current axes plt.imshow(image) if __name__ == '__main__': # Colors to use for the logo: red = (1, 0, 0) blue = (0.35, 0.55, 0.85) green_orange = ((0.6, 0.8, 0.3), (1, 0.5, 0.1)) def plot_all(): color_list = [red, blue, green_orange] edge_list = ['light', 'dark'] f, axes = plt.subplots(nrows=len(edge_list), ncols=len(color_list)) for axes_row, edges in zip(axes, edge_list): for ax, color in zip(axes_row, color_list): prepare_axes(ax) plot_colorized_logo(snake, color, edges=edges) plt.tight_layout() def plot_official_logo(): f, ax = plt.subplots() prepare_axes(ax) plot_colorized_logo(snake, green_orange, edges='dark', whiten=(False, True)) plt.savefig('green_orange_snake.png', bbox_inches='tight') plot_all() plot_official_logo() plt.show() scikit-image-0.9.3/doc/logo/scipy_logo.py000066400000000000000000000173661223313777300203440ustar00rootroot00000000000000""" Code used to trace Scipy logo. """ import numpy as np import matplotlib.pyplot as plt import matplotlib.nxutils as nx from skimage import io from skimage import data class SymmetricAnchorPoint(object): """Anchor point in a parametric curve with symmetric handles Parameters ---------- pt : length-2 sequence (x, y) coordinates of anchor point theta : float angle of control handle length : float half-length of symmetric control handle. Each control point is `length` distance away from the anchor point. use_degrees : bool If True, convert input `theta` from degrees to radians. """ def __init__(self, pt, theta, length, use_degrees=False): self.pt = pt if use_degrees: theta = theta * np.pi / 180 self.theta = theta self.length = length def control_points(self): """Return control points for symmetric handles The first point is in the direction of theta and the second is directly opposite. For example, if `theta = 0`, then the first `p1` will be directly to the right of the anchor point, and `p2` will be directly to the left. """ theta = self.theta offset = self.length * np.array([np.cos(theta), np.sin(theta)]) p1 = self.pt + offset p2 = self.pt - offset return p1, p2 def __repr__(self): v = (self.pt, self.theta * 180/np.pi, self.length) return 'SymmetricAnchorPoint(pt={0}, theta={1}, length={2})'.format(*v) def curve_from_anchor_points(pts): """Return curve from a list of SymmetricAnchorPoints""" assert len(pts) > 1 bezier_pts = [] for anchor in pts: c1, c2 = anchor.control_points() bezier_pts.extend([c2, anchor.pt, c1]) # clip control points from ends bezier_pts = bezier_pts[1:-1] x, y = [], [] # every third point is an anchor point for i in range(0, len(bezier_pts)-1, 3): xi, yi = cubic_curve(*bezier_pts[i:i+4]) x.append(xi) y.append(yi) return np.hstack(x), np.hstack(y) def cubic_curve(p0, p1, p2, p3, npts=20): """Return points on a cubic Bezier curve Parameters ---------- p0, p3 : length-2 sequences end points of curve p1, p2 : length-2 sequences control points of curve npts : int number of points to return (including end points) Returns ------- x, y : arrays points on cubic curve """ t = np.linspace(0, 1, npts)[:, np.newaxis] # cubic bezier curve from http://en.wikipedia.org/wiki/Bezier_curve b = (1-t)**3 * p0 + 3*t*(1-t)**2 * p1 + 3*t**2*(1-t) * p2 + t**3 * p3 x, y = b.transpose() return x, y class Circle(object): def __init__(self, center, radius): self.center = center self.radius = radius def point_from_angle(self, angle): r = self.radius # `angle` can be a scalar or 1D array: transpose twice for best results pts = r * np.array((np.cos(angle), np.sin(angle))).T + self.center return pts.T def plot(self, **kwargs): ax = kwargs.pop('ax', plt.gca()) fc = kwargs.pop('fc', 'none') c = plt.Circle(self.center, self.radius, fc=fc, **kwargs) ax.add_patch(c) class ScipyLogo(object): """Object to generate scipy logo Parameters ---------- center : length-2 array the Scipy logo will be centered on this point. radius : float radius of logo """ CENTER = np.array((254, 246)) RADIUS = 252.0 THETA_START = 2.58 THETA_END = -0.368 def __init__(self, center=None, radius=None): if center is None: if radius is None: center = self.CENTER else: center = np.array((radius, radius)) self.center = center if radius is None: radius = self.RADIUS self.radius = radius # calculate end points of curve so that it lies exactly on circle logo_circle = Circle(self.CENTER, self.RADIUS) s_start = logo_circle.point_from_angle(self.THETA_START) s_end = logo_circle.point_from_angle(self.THETA_END) self.circle = Circle(self.center, self.radius) # note that angles are clockwise because of inverted y-axis self._anchors = [SymmetricAnchorPoint(*t, use_degrees=True) for t in [(s_start, -37, 90), ((144, 312), 7, 20), ((205, 375), 52, 50), ((330, 380), -53, 60), ((290, 260),-168, 50), ((217, 245),-168, 50), ((182, 118), -50, 60), ((317, 125), 53, 60), ((385, 198), 10, 20), (s_end, -25, 60)]] # normalize anchors so they have unit radius and are centered at origin for a in self._anchors: a.pt = (a.pt - self.CENTER) / self.RADIUS a.length = a.length / self.RADIUS def snake_anchors(self): """Return list of SymmetricAnchorPoints defining snake curve""" anchors = [] for a in self._anchors: pt = self.radius * a.pt + self.center length = self.radius * a.length anchors.append(SymmetricAnchorPoint(pt, a.theta, length)) return anchors def snake_curve(self): """Return x, y coordinates of snake curve""" return curve_from_anchor_points(self.snake_anchors()) def plot_snake_curve(self, **kwargs): ax = kwargs.pop('ax', plt.gca()) x, y = self.snake_curve() ax.plot(x, y, 'k', **kwargs) def plot_circle(self, **kwargs): self.circle.plot(**kwargs) def plot_image(self, **kwargs): ax = kwargs.pop('ax', plt.gca()) img = io.imread('data/scipy.png') ax.imshow(img, **kwargs) def get_mask(self, shape, region): """ Parameters ---------- region : {'upper left', 'lower right'} """ if region == 'upper left': theta = np.linspace(self.THETA_END, self.THETA_START - 2 * np.pi) elif region == 'lower right': theta = np.linspace(self.THETA_END, self.THETA_START) else: msg = "Expected 'upper left' or 'lower right'; got %s" % region raise ValueError(msg) xy_circle = self.circle.point_from_angle(theta).T x, y = self.snake_curve() xy_curve = np.array((x, y)).T xy_poly = np.vstack((xy_curve, xy_circle)) h, w = shape[:2] y_img, x_img = np.mgrid[:h, :w] xy_points = np.column_stack((x_img.flat, y_img.flat)) mask = nx.points_inside_poly(xy_points, xy_poly) return mask.reshape((h, w)) def plot_scipy_trace(): plt.figure() logo = ScipyLogo() logo.plot_snake_curve() logo.plot_circle() logo.plot_image() plot_anchors(logo.snake_anchors()) def plot_anchors(anchors, color='r', alpha=0.7): for a in anchors: c = a.control_points() x, y = np.transpose(c) plt.plot(x, y, 'o-', color=color, mfc='w', mec=color, alpha=alpha) plt.plot(a.pt[0], a.pt[1], 'o', color=color, alpha=alpha) def plot_snake_overlay(): plt.figure() logo = ScipyLogo((670, 250), 250) logo.plot_snake_curve() logo.plot_circle() img = io.imread('data/snake_pixabay.jpg') plt.imshow(img) def plot_lena_overlay(): plt.figure() logo = ScipyLogo((300, 300), 180) logo.plot_snake_curve() logo.plot_circle() img = data.lena() plt.imshow(img) if __name__ == '__main__': plot_scipy_trace() plot_snake_overlay() plot_lena_overlay() plt.show() scikit-image-0.9.3/doc/logo/shrink_logo.py000066400000000000000000000006601223313777300205000ustar00rootroot00000000000000from skimage import io, transform s = 0.7 img = io.imread('scikit_image_logo.png') h, w, c = img.shape print "\nScaling down logo by %.1fx..." % s img = transform.homography(img, [[s, 0, 0], [0, s, 0], [0, 0, 1]], output_shape=(int(h*s), int(w*s), 4), order=3) io.imsave('scikit_image_logo_small.png', img) scikit-image-0.9.3/doc/logo/snake_logo.svg000066400000000000000000000065111223313777300204530ustar00rootroot00000000000000 image/svg+xml scikit-image image processing in python scikit-image-0.9.3/doc/make.bat000066400000000000000000000064221223313777300162570ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation set SPHINXBUILD=sphinx-build set ALLSPHINXOPTS=-d build/doctrees %SPHINXOPTS% source if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :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. 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. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) for %%x in (html htmlhelp latex qthelp) do ( if "%1" == "%%x" ( md source\api 2>NUL python tools/build_modref_templates.py ) ) if "%1" == "clean" ( for /d %%i in (build\*) do rmdir /q /s %%i del /q /s build\* goto end ) if "%1" == "html" ( cd source && python random_gallery.py && python coverage_generator.py && cd .. %SPHINXBUILD% -b html %ALLSPHINXOPTS% build/html echo. echo.Build finished. The HTML pages are in build/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% build/dirhtml echo. echo.Build finished. The HTML pages are in build/dirhtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% build/pickle echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% build/json echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% build/htmlhelp echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in build/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% build/qthelp echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in build/qthelp, like this: echo.^> qcollectiongenerator build\qthelp\scikitimage.qhcp echo.To view the help file: echo.^> assistant -collectionFile build\qthelp\scikitimage.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% build/devhelp echo. echo.Build finished. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% build/latex echo. echo.Build finished; the LaTeX files are in build/latex. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% build/changes echo. echo.The overview file is in build/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% build/linkcheck echo. echo.Link check complete; look for any errors in the above output ^ or in build/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% build/doctest echo. echo.Testing of doctests in the sources finished, look at the ^ results in build/doctest/output.txt. goto end ) :end scikit-image-0.9.3/doc/release/000077500000000000000000000000001223313777300162665ustar00rootroot00000000000000scikit-image-0.9.3/doc/release/contribs.py000077500000000000000000000024031223313777300204650ustar00rootroot00000000000000#!/usr/bin/env python import subprocess import sys import string import shlex if len(sys.argv) != 2: print "Usage: ./contributors.py tag-of-previous-release" sys.exit(-1) tag = sys.argv[1] def call(cmd): return subprocess.check_output(shlex.split(cmd)).split('\n') tag_date = call("git show --format='%%ci' %s" % tag)[0] print "Release %s was on %s" % (tag, tag_date) merges = call("git log --since='%s' --merges --format='>>>%%B' --reverse" % tag_date) merges = [m for m in merges if m.strip()] merges = '\n'.join(merges).split('>>>') merges = [m.split('\n')[:2] for m in merges] merges = [m for m in merges if len(m) == 2 and m[1].strip()] print "\nIt contained the following %d merges:" % len(merges) print for (merge, message) in merges: if merge.startswith('Merge pull request #'): PR = ' (%s)' % merge.split()[3] else: PR = '' print '- ' + message + PR print "\nMade by the following committers [alphabetical by last name]:\n" authors = call("git log --since='%s' --format=%%aN" % tag_date) authors = [a.strip() for a in authors if a.strip()] def key(author): author = [v for v in author.split() if v[0] in string.letters] return author[-1] authors = sorted(set(authors), key=key) for a in authors: print '-', a scikit-image-0.9.3/doc/release/release_0.3.txt000066400000000000000000000025711223313777300210340ustar00rootroot00000000000000Announcement: scikits.image 0.3 =============================== After a brief (!) absence, we're back with a new and shiny version of scikits.image, the image processing toolbox for SciPy. This release runs under all major operating systems where Python (>=2.6 or 3.x), NumPy and SciPy can be installed. For more information, visit our website http://scikits-image.org or the examples gallery at http://scikits-image.org/docs/0.3/auto_examples/ New Features ------------ - Shortest paths - Total variation denoising - Hough and probabilistic Hough transforms - Radon transform with reconstruction - Histogram of gradients - Morphology, including watershed, connected components - Faster homography transformations (rotations, zoom, etc.) - Image dtype conversion routines - Line drawing - Better image collection handling - Constant time median filter - Edge detection (canny, sobel, etc.) - IO: Freeimage, FITS, Qt and other image loaders; video support. - SIFT feature loader - Example data-sets ... as well as many bug fixes and minor updates. Contributors for this release ----------------------------- Martin Bergtholdt Luis Pedro Coelho Chris Colbert Damian Eads Dan Farmer Emmanuelle Gouillart Brian Holt Pieter Holtzhausen Thouis (Ray) Jones Lee Kamentsky Almar Klein Kyle Mandli Andreas Mueller Neil Muller Zachary Pincus James Turner Stefan van der Walt Gael Varoquaux Tony Yu scikit-image-0.9.3/doc/release/release_0.4.txt000066400000000000000000000024441223313777300210340ustar00rootroot00000000000000Announcement: scikits-image 0.4 =============================== We're happy to announce the 0.4 release of scikits-image, an image processing toolbox for SciPy. Please visit our examples gallery to see what we've been up to: http://scikits-image.org/docs/0.4/auto_examples/ Note that, in this release, we renamed the module from ``scikits.image`` to ``skimage``, to work around name space conflicts with other scikits (similarly, the machine learning scikit is now imported as ``sklearn``). A big shout-out also to everyone currently at SciPy India; have fun, and remember to join the scikits-image sprint! This release runs under all major operating systems where Python (>=2.6 or 3.x), NumPy and SciPy can be installed. For more information, visit our website http://scikits-image.org New Features ------------ - Module rename from ``scikits.image`` to ``skimage`` - Contour finding - Grey-level co-occurrence matrices - Skeletonization and medial axis transform - Convex hull images - New test data sets - GDAL I/O plugin ... as well as some bug fixes. Contributors to this release ---------------------------- * Andreas Mueller * Christopher Gohlke * Emmanuelle Gouillart * Neil Yager * Nelle Varoquaux * Riaan van den Dool * Stefan van der Walt * Thouis (Ray) Jones * Tony S Yu * Zachary Pincus scikit-image-0.9.3/doc/release/release_0.5.txt000066400000000000000000000017221223313777300210330ustar00rootroot00000000000000Announcement: scikits-image 0.5 =============================== We're happy to announce the 0.5 release of scikits-image, our image processing toolbox for SciPy. For more information, please visit our website http://scikits-image.org New Features ------------ - Consistent intensity rescaling and improved range conversion. - Random walker segmentation. - Harris corner detection. - Otsu thresholding. - Block views, window views and montage. - Plugin for Christoph Gohlke's "tifffile". - Peak detection. - Improved FreeImage wrappers and meta-data reading. - 8-neighbor and background labelling. ... along with updates to the documentation and website, and a number of bug fixes. Contributors to this release ---------------------------- * Andreas Mueller * Brian Holt * Christoph Gohlke * Emmanuelle Gouillart * Michael Aye * Nelle Varoquaux * Nicolas Pinto * Nicolas Poilvert * Pieter Holtzhausen * Stefan van der Walt * Tony S Yu * Warren Weckesser * Zachary Pincus scikit-image-0.9.3/doc/release/release_0.6.txt000066400000000000000000000020211223313777300210250ustar00rootroot00000000000000Announcement: scikits-image 0.6 =============================== We're happy to announce the 6th version of scikits-image! Scikits-image is an image processing toolbox for SciPy that includes algorithms for segmentation, geometric transformations, color space manipulation, analysis, filtering, morphology, feature detection, and more. For more information, examples, and documentation, please visit our website http://skimage.org New Features ------------ - Packaged in Debian as ``python-skimage`` - Template matching - Fast user-defined image warping - Adaptive thresholding - Structural similarity index - Polygon, circle and ellipse drawing - Peak detection - Region properties - TiffFile I/O plugin ... along with some bug fixes and performance tweaks. Contributors to this release ---------------------------- - Vincent Albufera - David Cournapeau - Christoph Gohlke - Emmanuelle Gouillart - Pieter Holtzhausen - Zachary Pincus - Johannes Schönberger - Tom (tangofoxtrotmike) - James Turner - Stefan van der Walt - Tony S Yu scikit-image-0.9.3/doc/release/release_0.7.txt000066400000000000000000000035401223313777300210350ustar00rootroot00000000000000Announcement: scikits-image 0.7.0 ================================= We're happy to announce the 7th version of scikits-image! Scikits-image is an image processing toolbox for SciPy that includes algorithms for segmentation, geometric transformations, color space manipulation, analysis, filtering, morphology, feature detection, and more. For more information, examples, and documentation, please visit our website http://skimage.org New Features ------------ It's been only 3 months since scikits-image 0.6 was released, but in that short time, we've managed to add plenty of new features and enhancements, including - Geometric image transforms - 3 new image segmentation routines (Felsenzwalb, Quickshift, SLIC) - Local binary patterns for texture characterization - Morphological reconstruction - Polygon approximation - CIE Lab color space conversion - Image pyramids - Multispectral support in random walker segmentation - Slicing, concatenation, and natural sorting of image collections - Perimeter and coordinates measurements in regionprops - An extensible image viewer based on Qt and Matplotlib, with plugins for edge detection, line-profiling, and viewing image collections Plus, this release adds a number of bug fixes, new examples, and performance enhancements. Contributors to this release ---------------------------- This release was only possible due to the efforts of many contributors, both new and old. - Andreas Mueller - Andreas Wuerl - Andy Wilson - Brian Holt - Christoph Gohlke - Dharhas Pothina - Emmanuelle Gouillart - Guillaume Gay - Josh Warner - James Bergstra - Johannes Schonberger - Jonathan J. Helmus - Juan Nunez-Iglesias - Leon Tietz - Marianne Corvellec - Matt McCormick - Neil Yager - Nicolas Pinto - Nicolas Poilvert - Pavel Campr - Petter Strandmark - Stefan van der Walt - Tim Sheerman-Chase - Tomas Kazmar - Tony S Yu - Wei Li scikit-image-0.9.3/doc/release/release_0.8.txt000066400000000000000000000044421223313777300210400ustar00rootroot00000000000000Announcement: scikits-image 0.8.0 ================================= We're happy to announce the 8th version of scikit-image! scikit-image is an image processing toolbox for SciPy that includes algorithms for segmentation, geometric transformations, color space manipulation, analysis, filtering, morphology, feature detection, and more. For more information, examples, and documentation, please visit our website: http://scikit-image.org New Features ------------ - New rank filter package with many new functions and a very fast underlying local histogram algorithm, especially for large structuring elements `skimage.filter.rank.*` - New function for small object removal `skimage.morphology.remove_small_objects` - New circular hough transformation `skimage.transform.hough_circle` - New function to draw circle perimeter `skimage.draw.circle_perimeter` and ellipse perimeter `skimage.draw.ellipse_perimeter` - New dense DAISY feature descriptor `skimage.feature.daisy` - New bilateral filter `skimage.filter.denoise_bilateral` - New faster TV denoising filter based on split-Bregman algorithm `skimage.filter.denoise_tv_bregman` - New linear hough peak detection `skimage.transform.hough_peaks` - New Scharr edge detection `skimage.filter.scharr` - New geometric image scaling as convenience function `skimage.transform.rescale` - New theme for documentation and website - Faster median filter through vectorization `skimage.filter.median_filter` - Grayscale images supported for SLIC segmentation - Unified peak detection with more options `skimage.feature.peak_local_max` - `imread` can read images via URL and knows more formats `skimage.io.imread` Additionally, this release adds lots of bug fixes, new examples, and performance enhancements. Contributors to this release ---------------------------- This release was only possible due to the efforts of many contributors, both new and old. - Adam Ginsburg - Anders Boesen Lindbo Larsen - Andreas Mueller - Christoph Gohlke - Christos Psaltis - Colin Lea - François Boulogne - Jan Margeta - Johannes Schönberger - Josh Warner (Mac) - Juan Nunez-Iglesias - Luis Pedro Coelho - Marianne Corvellec - Matt McCormick - Nicolas Pinto - Olivier Debeir - Paul Ivanov - Sergey Karayev - Stefan van der Walt - Steven Silvester - Thouis (Ray) Jones - Tony S Yu scikit-image-0.9.3/doc/release/release_0.9.txt000066400000000000000000000074301223313777300210410ustar00rootroot00000000000000Announcement: scikit-image 0.9.0 ================================ We're happy to announce the release of scikit-image v0.9.0! scikit-image is an image processing toolbox for SciPy that includes algorithms for segmentation, geometric transformations, color space manipulation, analysis, filtering, morphology, feature detection, and more. For more information, examples, and documentation, please visit our website: http://scikit-image.org New Features ------------ `scikit-image` now runs without translation under both Python 2 and 3. In addition to several bug fixes, speed improvements and examples, the 204 pull requests merged for this release include the following new features (PR number in brackets): Segmentation: - 3D support in SLIC segmentation (#546) - SLIC voxel spacing (#719) - Generalized anisotropic spacing support for random_walker (#775) - Yen threshold method (#686) Transforms and filters: - SART algorithm for tomography reconstruction (#584) - Gabor filters (#371) - Hough transform for ellipses (#597) - Fast resampling of nD arrays (#511) - Rotation axis center for Radon transforms with inverses. (#654) - Reconstruction circle in inverse Radon transform (#567) - Pixelwise image adjustment curves and methods (#505) Feature detection: - [experimental API] BRIEF feature descriptor (#591) - [experimental API] Censure (STAR) Feature Detector (#668) - Octagon structural element (#669) - Add non rotation invariant uniform LBPs (#704) Color and noise: - Add deltaE color comparison and lab2lch conversion (#665) - Isotropic denoising (#653) - Generator to add various types of random noise to images (#625) - Color deconvolution for immunohistochemical images (#441) - Color label visualization (#485) Drawing and visualization: - Wu's anti-aliased circle, line, bezier curve (#709) - Linked image viewers and docked plugins (#575) - Rotated ellipse + bezier curve drawing (#510) - PySide & PyQt4 compatibility in skimage-viewer (#551) Other: - Python 3 support without 2to3. (#620) - 3D Marching Cubes (#469) - Line, Circle, Ellipse total least squares fitting and RANSAC algorithm (#440) - N-dimensional array padding (#577) - Add a wrapper around `scipy.ndimage.gaussian_filter` with useful default behaviors. (#712) - Predefined structuring elements for 3D morphology (#484) API changes ----------- The following backward-incompatible API changes were made between 0.8 and 0.9: - No longer wrap ``imread`` output in an ``Image`` class - Change default value of `sigma` parameter in ``skimage.segmentation.slic`` to 0 - ``hough_circle`` now returns a stack of arrays that are the same size as the input image. Set the ``full_output`` flag to True for the old behavior. - The following functions were deprecated over two releases: `skimage.filter.denoise_tv_chambolle`, `skimage.morphology.is_local_maximum`, `skimage.transform.hough`, `skimage.transform.probabilistic_hough`,`skimage.transform.hough_peaks`. Their functionality still exists, but under different names. Contributors to this release ---------------------------- This release was made possible by the collaborative efforts of many contributors, both new and old. They are listed in alphabetical order by surname: - Ankit Agrawal - K.-Michael Aye - Chris Beaumont - François Boulogne - Luis Pedro Coelho - Marianne Corvellec - Olivier Debeir - Ferdinand Deger - Kemal Eren - Jostein Bø Fløystad - Christoph Gohlke - Emmanuelle Gouillart - Christian Horea - Thouis (Ray) Jones - Almar Klein - Xavier Moles Lopez - Alexis Mignon - Juan Nunez-Iglesias - Zachary Pincus - Nicolas Pinto - Davin Potts - Malcolm Reynolds - Umesh Sharma - Johannes Schönberger - Chintak Sheth - Kirill Shklovsky - Steven Silvester - Matt Terry - Riaan van den Dool - Stéfan van der Walt - Josh Warner - Adam Wisniewski - Yang Zetian - Tony S Yu scikit-image-0.9.3/doc/source/000077500000000000000000000000001223313777300161465ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/_static/000077500000000000000000000000001223313777300175745ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/_static/docversions.js000066400000000000000000000014111223313777300224650ustar00rootroot00000000000000var versions = ['dev', '0.9.x', '0.8.0', '0.7.0', '0.6', '0.5', '0.4', '0.3']; function insert_version_links() { for (i = 0; i < versions.length; i++){ open_list = '
  • ' if (typeof(DOCUMENTATION_OPTIONS) !== 'undefined') { if ((DOCUMENTATION_OPTIONS['VERSION'] == versions[i]) || (DOCUMENTATION_OPTIONS['VERSION'].match(/dev$/) && (i == 0))) { open_list = '
  • ' } } document.write(open_list); document.write('skimage VERSION
  • \n' .replace('VERSION', versions[i]) .replace('URL', 'http://scikit-image.org/docs/' + versions[i])); } } function stable_version() { return versions[1]; } scikit-image-0.9.3/doc/source/_templates/000077500000000000000000000000001223313777300203035ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/_templates/localtoc.html000066400000000000000000000004111223313777300227650ustar00rootroot00000000000000{% if pagename != 'index' %} {%- if display_toc %} {%- endif %} {% endif %} scikit-image-0.9.3/doc/source/_templates/navbar.html000066400000000000000000000003761223313777300224500ustar00rootroot00000000000000
  • Home
  • Download
  • Gallery
  • Documentation
  • Source
  • scikit-image-0.9.3/doc/source/_templates/navigation.html000066400000000000000000000014321223313777300233300ustar00rootroot00000000000000 {%- if prev %} {%- endif %} {%- if next %} {%- endif %} scikit-image-0.9.3/doc/source/_templates/versions.html000066400000000000000000000004571223313777300230470ustar00rootroot00000000000000 scikit-image-0.9.3/doc/source/api_changes.txt000066400000000000000000000015551223313777300211560ustar00rootroot00000000000000Version 0.9 ----------- - No longer wrap ``imread`` output in an ``Image`` class - Change default value of `sigma` parameter in ``skimage.segmentation.slic`` to 0 - ``hough_circle`` now returns a stack of arrays that are the same size as the input image. Set the ``full_output`` flag to True for the old behavior. - The following functions were deprecated over two releases: `skimage.filter.denoise_tv_chambolle`, `skimage.morphology.is_local_maximum`, `skimage.transform.hough`, `skimage.transform.probabilistic_hough`,`skimage.transform.hough_peaks`. Their functionality still exists, but under different names. Version 0.4 ----------- - Switch mask and radius arguments for ``median_filter`` Version 0.3 ----------- - Remove ``as_grey``, ``dtype`` keyword from ImageCollection - Remove ``dtype`` from imread - Generalise ImageCollection to accept a load_func scikit-image-0.9.3/doc/source/auto_examples/000077500000000000000000000000001223313777300210145ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/auto_examples/images/000077500000000000000000000000001223313777300222615ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/auto_examples/images/blank_image.png000066400000000000000000000027441223313777300252270ustar00rootroot00000000000000PNG  IHDRy XsRGBbKGD pHYs B(xtIME  62].dIDATxݿo[U\I!0U@GHJ@?ZBH;j)I CX0P6qkr`q_ǎkTQ#ɓscK0p< Ibڛ<0gяU9Ubu~Jn?P~-*Jh΍ן)Djto#>D sҧM+sii~SNf^ zS2L?s<җn1rc-wK/TK<SA#5z@,jCms$3Y=o"fyKWJTsN.Te55[\@BIGw* YM/+6KGK/yw0BVE^Ս⮖ɳ)ew400o=ۭz{?a&j;[wگ90rha| -~C tf1mf][z 9F" co|h }^ۘ@c#Ewj|Sh$^ikSCH;)۟KCcd۹S4 A(:[s~ Cwk l*m}xؑq2OH= 2) except AttributeError: use_matplotlib_plot_directive = False if use_matplotlib_plot_directive: extensions.append('matplotlib.sphinxext.plot_directive') else: extensions.append('plot_directive') # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.txt' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = 'skimage' copyright = '2013, the scikit-image team' # 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. setup_lines = open('../../setup.py').readlines() version = 'vUndefined' for l in setup_lines: if l.startswith('VERSION'): version = l.split("'")[1] break # The full version, including alpha/beta/rc tags. release = version # 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 documents that shouldn't be included in the build. #unused_docs = [] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = [] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. html_theme = 'scikit-image' # 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 = ['themes'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". html_title = 'skimage v%s docs' % version # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = 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 = ['_static'] # 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 = { '**': ['navigation.html', 'localtoc.html', 'versions.html'], } # 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_use_modindex = 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 = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'scikitimagedoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('contents', 'scikit-image.tex', u'The scikit-image Documentation', u'scikit-image development team', '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 # Additional stuff for the LaTeX preamble. latex_preamble = r''' \usepackage{enumitem} \setlistdepth{100} \usepackage{amsmath} \DeclareUnicodeCharacter{00A0}{\nobreakspace} % In the parameters section, place a newline after the Parameters header \usepackage{expdlist} \let\latexdescription=\description \def\description{\latexdescription{}{} \breaklabel} % Make Examples/etc section headers smaller and more compact \makeatletter \titleformat{\paragraph}{\normalsize\py@HeaderFamily}% {\py@TitleColor}{0em}{\py@TitleColor}{\py@NormalColor} \titlespacing*{\paragraph}{0pt}{1ex}{0pt} \makeatother ''' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. latex_use_modindex = False # ----------------------------------------------------------------------------- # Numpy extensions # ----------------------------------------------------------------------------- numpydoc_show_class_members = False # ----------------------------------------------------------------------------- # Plots # ----------------------------------------------------------------------------- plot_basedir = os.path.join(curpath, "plots") plot_pre_code = """ import numpy as np import matplotlib.pyplot as plt np.random.seed(0) import matplotlib matplotlib.rcParams.update({ 'font.size': 14, 'axes.titlesize': 12, 'axes.labelsize': 10, 'xtick.labelsize': 8, 'ytick.labelsize': 8, 'legend.fontsize': 10, 'figure.subplot.bottom': 0.2, 'figure.subplot.left': 0.2, 'figure.subplot.right': 0.9, 'figure.subplot.top': 0.85, 'figure.subplot.wspace': 0.4, 'text.usetex': False, }) """ plot_include_source = True plot_formats = [('png', 100), ('pdf', 100)] plot2rst_index_name = 'README' plot2rst_rcparams = {'image.cmap' : 'gray', 'image.interpolation' : 'none'} # ----------------------------------------------------------------------------- # intersphinx # ----------------------------------------------------------------------------- _python_doc_base = 'http://docs.python.org/2.7' intersphinx_mapping = { _python_doc_base: None, 'http://docs.scipy.org/doc/numpy': None, 'http://docs.scipy.org/doc/scipy/reference': None, 'http://scikit-learn.org/stable': None } scikit-image-0.9.3/doc/source/contents.txt000066400000000000000000000001001223313777300205330ustar00rootroot00000000000000Table of Contents ================= .. toctree:: /api/api scikit-image-0.9.3/doc/source/contribute.txt000066400000000000000000000001011223313777300210550ustar00rootroot00000000000000.. include:: ../../TASKS.txt .. include:: ../../CONTRIBUTING.txt scikit-image-0.9.3/doc/source/coverage.csv000066400000000000000000000332271223313777300204650ustar00rootroot00000000000000Image Display and Exploration,Image Display and Exploration,Image File I/O,Image Types and Type Conversions GUI Tools,Modular Interactive Tools,Navigational Tools for Image Scroll Panel,Utilities for Interactive Tools Spatial Transformations and Image Registration,Spatial Transformations,Image Registration, Image Analysis and Statistics,Image Analysis,Texture Analysis,Pixel Values and Statistics Image Arithmetic,,, Image Enhancement and Restoration,Image Enhancement,Image Restoration (Deblurring), Linear Filtering and Transforms,Linear Filtering,Linear 2-D Filter Design,Image Transforms Morphological Operations,Intensity and Binary Images,Binary Images,Structuring Element Creation and Manipulation "ROI-Based, Neighborhood, and Block Processing",ROI-Based Processing,Neighborhood and Block Processing, Colormaps and Color Space,Color Space Conversions,, Utilities,Validation,Array Operations,Performance ,,, Make movie from multiframe image ,immovie ,:done:`immovie`,:partial:`immovie` "Play movies, videos, or image sequences ",implay ,:na:`n/a`, Display image ,imshow ,, Image Tool ,imtool ,, Display multiple image frames as rectangular montage,montage ,, Display multiple images in single figure ,subimage,, Display image as texture-mapped surface ,warp ,, , ,, Read metadata from header file of Analyze 7.5 data set ,analyze75info,, Read image data from image file of Analyze 7.5 data set ,analyze75read,, Anonymize DICOM file ,dicomanon ,, Get or set active DICOM data dictionary ,dicomdict ,, Read metadata from DICOM message ,dicominfo ,, Find attribute in DICOM data dictionary ,dicomlookup ,, Read DICOM image ,dicomread ,, Generate DICOM unique identifier ,dicomuid ,, Write images as DICOM files ,dicomwrite ,, Read high dynamic range (HDR) image ,hdrread ,, Write Radiance high dynamic range (HDR) image file ,hdrwrite ,, Read metadata from Interfile file ,interfileinfo,, Read images in Interfile format ,interfileread,, Check if file is R-Set ,isrset ,, Create high dynamic range image ,makehdr ,, Read metadata from National Imagery Transmission Format (NITF) file,nitfinfo ,, Read image from NITF file ,nitfread ,, Open R-Set file ,openrset ,, Create reduced resolution data set from image file ,rsetwrite ,, Render high dynamic range image for viewing ,tonemap ,, ,,, Convert Bayer pattern encoded image to truecolor image,demosaic,, Convert grayscale or binary image to indexed image,gray2ind,, Convert grayscale image to indexed image using multilevel thresholding,grayslice,, Global image threshold using Otsu's method,graythresh,, "Convert image to binary image, based on threshold",im2bw,, Convert image to double precision,im2double,, Convert image to 16-bit signed integers,im2int16,, Convert image to Java buffered image,im2java2d,, Convert image to single precision,im2single,, Convert image to 16-bit unsigned integers,im2uint16,, Convert image to 8-bit unsigned integers,im2uint8,, Convert indexed image to grayscale image,ind2gray,, Convert indexed image to RGB image,ind2rgb,, Convert label matrix into RGB image,label2rgb,, Convert matrix to grayscale image,mat2gray,, Convert RGB image or colormap to grayscale,rgb2gray,, ,,, Image Information tool,imageinfo,, Adjust Contrast tool,imcontrast,, Display Range tool,imdisplayrange,, Distance tool,imdistline,, Pixel Information tool,impixelinfo,, Pixel Information tool without text label,impixelinfoval,, Pixel Region tool,impixelregion,, Pixel Region tool panel,impixelregionpanel,, ,,, Magnification box for scroll panel,immagbox,, Overview tool for image displayed in scroll panel,imoverview,, Overview tool panel for image displayed in scroll panel,imoverviewpanel,, Scroll panel for interactive image navigation,imscrollpanel,, ,,, Convert axes coordinates to pixel coordinates,axes2pix,, Image data from axes,getimage,, Image model object from image object,getimagemodel,, Information about image attributes,imattributes,, Create draggable ellipse,imellipse,, Create draggable freehand region,imfreehand,, Get handle to current axes containing image,imgca,, Get handle to current figure containing image,imgcf,, Open Image dialog box,imgetfile,, Get all image handles,imhandles,, "Create draggable, resizable line",imline,, Create draggable point,impoint,, "Create draggable, resizable polygon",impoly,, Create draggable rectangle,imrect,, Region-of-interest (ROI) base class,imroi,, Add function handle to callback list,iptaddcallback,, Check validity of handle,iptcheckhandle,, Get Application Programmer Interface (API) for handle,iptgetapi,, Retrieve pointer behavior from HG object,iptGetPointerBehavior,, Directories containing IPT and MATLAB icons,ipticondir,, Create pointer manager in figure,iptPointerManager,, Delete function handle from callback list,iptremovecallback,, Store pointer behavior structure in Handle Graphics object,iptSetPointerBehavior,, Align figure windows,iptwindowalign,, Create rectangularly bounded drag constraint function,makeConstrainToRectFcn,, Adjust display size of image,truesize,, ,,, Create checkerboard image,checkerboard,, Find output bounds for spatial transformation,findbounds,, Flip input and output roles of TFORM structure,fliptform,, Crop image,imcrop,, Image pyramid reduction and expansion,impyramid,, Resize image,imresize,, Rotate image,imrotate,, Apply 2-D spatial transformation to image,imtransform,, Create resampling structure,makeresampler,, Create spatial transformation structure (TFORM),maketform,, Apply spatial transformation to N-D array,tformarray,, Apply forward spatial transformation,tformfwd,, Apply inverse spatial transformation,tforminv,, ,,, Infer spatial transformation from control point pairs,cp2tform,, Tune control-point locations using cross correlation,cpcorr,, Control Point Selection Tool,cpselect,, Convert CPSTRUCT to valid pairs of control points,cpstruct2pairs,, Normalized 2-D cross-correlation,normxcorr2,, ,,, Trace region boundaries in binary image,bwboundaries,, Trace object in binary image,bwtraceboundary,, Find corner points in image,corner,, Create corner metric matrix from image,cornermetric,, Find edges in grayscale image,edge,, Hough transform,hough,, Extract line segments based on Hough transform,houghlines,, Identify peaks in Hough transform,houghpeaks,, Quadtree decomposition,qtdecomp,, Block values in quadtree decomposition,qtgetblk,, Set block values in quadtree decomposition,qtsetblk,, ,,, Entropy of grayscale image,entropy,, Local entropy of grayscale image,entropyfilt,, Create gray-level co-occurrence matrix from image,graycomatrix,, Properties of gray-level co-occurrence matrix,graycoprops,, Local range of image,rangefilt,, Local standard deviation of image,stdfilt,, ,,, 2-D correlation coefficient,corr2,, Create contour plot of image data,imcontour,, Display histogram of image data,imhist,, Pixel color values,impixel,, Pixel-value cross-sections along line segments,improfile,, Average or mean of matrix elements,mean2,, Measure properties of image regions,regionprops,, Standard deviation of matrix elements,std2,, ,,, Absolute difference of two images,imabsdiff,, Add two images or add constant to image,imadd,, Complement image,imcomplement,, Divide one image into another or divide image by constant,imdivide,, Linear combination of images,imlincomb,, Multiply two images or multiply image by constant,immultiply,, Subtract one image from another or subtract constant from image,imsubtract,, ,,, Contrast-limited adaptive histogram equalization (CLAHE),adapthisteq,, Apply decorrelation stretch to multichannel image,decorrstretch,, Enhance contrast using histogram equalization,histeq,, Adjust image intensity values or colormap,imadjust,, Add noise to image,imnoise,, Convert integer values using lookup table,intlut,, 2-D median filtering,medfilt2,, 2-D order-statistic filtering,ordfilt2,, Find limits to contrast stretch image,stretchlim,, 2-D adaptive noise-removal filtering,wiener2,, ,,, Deblur image using blind deconvolution,deconvblind,, Deblur image using Lucy-Richardson method,deconvlucy,, Deblur image using regularized filter,deconvreg,, Deblur image using Wiener filter,deconvwnr,, Taper discontinuities along image edges,edgetaper,, Convert optical transfer function to point-spread function,otf2psf,, Convert point-spread function to optical transfer function,psf2otf,, ,,, 2-D convolution matrix,convmtx2,, Create predefined 2-D filter,fspecial,, N-D filtering of multidimensional images,imfilter,, ,,, 2-D frequency response,freqz2,, 2-D FIR filter using frequency sampling,fsamp2,, 2-D FIR filter using frequency transformation,ftrans2,, 2-D FIR filter using 1-D window method,fwind1,, 2-D FIR filter using 2-D window method,fwind2,, ,,, 2-D discrete cosine transform,dct2,, Discrete cosine transform matrix,dctmtx,, Convert fan-beam projections to parallel-beam,fan2para,, Fan-beam transform,fanbeam,, 2-D inverse discrete cosine transform,idct2,, Inverse fan-beam transform,ifanbeam,, Inverse Radon transform,iradon,, Convert parallel-beam projections to fan-beam,para2fan,, Create head phantom image,phantom,, Radon transform,radon,, ,,, Create connectivity array,conndef,, Bottom-hat filtering,imbothat,, Suppress light structures connected to image border,imclearborder,, Morphologically close image,imclose,, Dilate image,imdilate,, Erode image,imerode,, Extended-maxima transform,imextendedmax,, Extended-minima transform,imextendedmin,, Fill image regions and holes,imfill,, H-maxima transform,imhmax,, H-minima transform,imhmin,, Impose minima,imimposemin,, Morphologically open image,imopen,, Morphological reconstruction,imreconstruct,, Regional maxima,imregionalmax,, Regional minima,imregionalmin,, Top-hat filtering,imtophat,, Watershed transform,watershed,, ,,, Generate convex hull image from binary image,bwconvhull,, Neighborhood operations on binary images using lookup tables,applylut,, Area of objects in binary image,bwarea,, Morphologically open binary image (remove small objects),bwareaopen,, Find connected components in binary image,bwconncomp,, Distance transform of binary image,bwdist,, Euler number of binary image,bweuler,, Binary hit-miss operation,bwhitmiss,, Label connected components in 2-D binary image,bwlabel,, Label connected components in binary image,bwlabeln,, Morphological operations on binary images,bwmorph,, Pack binary image,bwpack,, Find perimeter of objects in binary image,bwperim,, Select objects in binary image,bwselect,, Ultimate erosion,bwulterode,, Unpack binary image,bwunpack,, Top-hat filtering,imtophat,, Create lookup table for use with ``applylut``,makelut,, ,,, Height of structuring element,getheight,, Structuring element neighbor locations and heights,getneighbors,, Structuring element neighborhood,getnhood,, Sequence of decomposed structuring elements,getsequence,, True for flat structuring element,isflat,, Reflect structuring element,reflect,, Create morphological structuring element (``STREL``),strel,, Translate structuring element (``STREL``),translate,, ,,, Convert region of interest (ROI) polygon to region mask,poly2mask,, Select region of interest (ROI) based on color,roicolor,, Fill in specified region of interest (ROI) polygon in grayscale image,roifill,, Filter region of interest (ROI) in image,roifilt2,, Specify polygonal region of interest (ROI),roipoly,, ,,, Determine optimal block size for block processing,bestblk,, Distinct block processing for image,blockproc,, Close ImageAdapter object,close (ImageAdapter),, Rearrange matrix columns into blocks,col2im,, Columnwise neighborhood operations,colfilt,, Rearrange image blocks into columns,im2col,, Interface for image I/O,ImageAdapter,, General sliding-neighborhood operations,nlfilter,, Read region of image,readRegion (ImageAdapter),, Write block of data to region of image,writeRegion (ImageAdapter),, ,,, Apply device-independent color space transformation,applycform,, Search for ICC profiles,iccfind,, Read ICC profile,iccread,, Find system default ICC profile repository,iccroot,, Write ICC color profile to disk file,iccwrite,, True for valid ICC color profile,isicc,, Convert L*a*b* data to double,lab2double,, Convert L*a*b* data to uint16,lab2uint16,, Convert L*a*b* data to uint8,lab2uint8,, Create color transformation structure,makecform,, Convert NTSC values to RGB color space,ntsc2rgb,, Convert RGB color values to NTSC color space,rgb2ntsc,, Convert RGB color values to YCbCr color space,rgb2ycbcr,, XYZ color values of standard illuminants,whitepoint,, Convert XYZ color values to double,xyz2double,, Convert XYZ color values to uint16,xyz2uint16,, Convert YCbCr color values to RGB color space,ycbcr2rgb,, ,,, Default display range of image based on its class,getrangefromclass,, Check validity of connectivity argument,iptcheckconn,, Check validity of array,iptcheckinput,, Check validity of colormap,iptcheckmap,, Check number of input arguments,iptchecknargin,, Check validity of option string,iptcheckstrs,, Convert positive integer to ordinal string,iptnum2ordinal,, ,,, Pad array,padarray,, ,,, Check for presence of Intel Integrated Performance Primitives (Intel IPP) library,ippl,,scikit-image-0.9.3/doc/source/coverage_generator.py000077500000000000000000000202461223313777300223700ustar00rootroot00000000000000#!/usr/bin/env python from __future__ import division import sys import os import csv # Import StringIO module try: import cStringIO as StringIO except ImportError: import StringIO # Missing item value MISSING_STRING=":missing:`Not Implemented`" def calculate_coverage(reader): """Calculate portions of code that are in one of the coverage categories Returns a tuple representing the weighted items. The order is (done, partial, missing, not applicable) """ # Coverage counters total_items = 0 partial_items = 0 done_items = 0 na_items = 0 # Skip table names for row in reader: if len(row[0]) == 0: break # Count items for row in reader: if len(row[0]) > 0: total_items += 1 if ":done:" in row[2] or ":done:" in row[3]: done_items += 1 if ":partial:" in row[2] or ":partial:" in row[3]: partial_items += 1 if ":na:" in row[2] or ":na:" in row[3]: na_items += 1 counts = (done_items, partial_items, total_items - (partial_items + done_items + na_items), na_items) return list(i / total_items for i in counts) def read_table_titles(reader): r"""Create a dictionary with keys as section names and values as a list of table names return (dict) """ section_titles = [] table_names = {} try: for row in reader: names = [] # End of names table if len(row[0]) == 0: break # Extract names of the tables for name in row[1:]: if len(name) > 0: names.append(name) else: break section_titles.append(row[0]) table_names[row[0]] = names except csv.Error, e: sys.exit('line %d: %s' % (reader.line_num, e)) return section_titles,table_names def table_seperator(stream,lengths,character="-"): r"""Write out table row seperator :Input: - *stream* (io/stream) Stream where output is put - *lengths* (list) A list of the lengths of the columns - *character* (string) Character to be filled between +, defaults to "-". """ stream.write("+") stream.write('+'.join([character*(length+2) for length in lengths])) stream.write("+") def table_row(stream,data,lengths,num_columns=None): r"""Write out table row data :Input: - *stream* (io/stream) Stream where output is put - *data* (list) List of strings containing data - *lengths* (list) A list of the lengths of the columns - *num_columns* (string) Number of columns, defaults to the length of the data array """ if num_columns is None: num_columns = len(data) stream.write("|") for i in xrange(num_columns): if len(data)-1 >= i: if len(data[i]) == 0: entry = MISSING_STRING else: entry = data[i] else: entry = MISSING_STRING stream.write(" " + entry + " "*(lengths[i] - len(entry)) + " |") def generate_table(reader,stream,table_name=None, column_titles=["Functionality","Matlab","Scipy","Scipy"]): r"""Generate a reST grid table based on the CSV data in reader Reads CSV data from *reader* until an empty line is found and generates a reST table based on the data into *stream*. A table name can be given for a section and table label. All rows are read in and checked for maximum number of columns (defaults to the size of column_titles) and column widths so that the table can be constructed. If a row contains less than the maximum number of columns a string is inserted that defaults to the string *MISSING_STRING* which is a global parameter. :Input: - reader (csv.reader) The CSV reader to read in from - stream (iostream) Output target - table_name (string) Optional name of table, defaults to *None* - column_titles (list) List of column titles """ # Find number of columns and column widths, base number of columns is # determined by the headers num_columns = len(column_titles) data = [column_titles] try: for row in reader: if len(row[0]) == 0: break data.append([entry.expandtabs() for entry in row]) num_columns = max(num_columns,len(row)) except csv.Error, e: sys.exit('line %d: %s' % (reader.line_num, e)) column_lengths = [len(MISSING_STRING)]*num_columns for row in data: for i in xrange(len(row)): column_lengths[i] = max(column_lengths[i],len(row[i])) # Output table header stream.write(table_name + "\n") if table_name is not None: stream.write("~"*len(table_name)+"\n\n") stream.write(".. tabularcolumns:: |p{40%}|p{20%}|p{20%}|p{20%}|\n\n") if table_name is not None: stream.write(".. table::%s\n\n" % table_name) table_seperator(stream,column_lengths,character="-") stream.write("\n") table_row(stream,data[0],column_lengths,num_columns) stream.write("\n") table_seperator(stream,column_lengths,character="=") stream.write("\n") # Output table data for row in data[1:]: table_row(stream,row,column_lengths,num_columns) stream.write("\n") table_seperator(stream,column_lengths,character='-') stream.write("\n") stream.write("\n\n") def generate_page(csv_path,stream,page_title="Coverage Tables"): r"""Generate coverage table page Generates all reST for all tables contained in the CSV file at *csv_path* and output it to *stream*. :Input: - *csv_path* (path) Path to CSV file - *stream* (iostream) Output stream - *page_title* (string) Optional page title, defaults to ``Coverage Tables``. """ # Open reader csv_file = open(csv_path,'U') # Sniffer does not seem to work all the time even when an Excel # spread sheet is being used # dialect = csv.Sniffer().sniff(csv_file.read(1024)) # csv_file.seek(0) # reader = csv.reader(csv_file, dialect) reader = csv.reader(csv_file) item_counts = calculate_coverage(reader) csv_file.seek(0) # Write out header stream.write("%s\n" % page_title) stream.write("="*len(page_title) + "\n\n") stream.write(""" .. role:: missing .. role:: partial .. role:: done .. role:: na .. role:: missing-bar .. role:: partial-bar .. role:: done-bar .. role:: na-bar .. warning:: This table has not yet been updated. We've just finished setting up its structure. Color Key --------- :done:`Complete` :partial:`Partial` :missing:`Missing` :na:`Not Applicable` Coverage Bar ------------ .. raw:: html """) for item, style in enumerate(('done-bar', 'partial-bar', 'missing-bar', 'na-bar')): stream.write('' % \ (item_counts[item] * 100, style)) stream.write("
     
    \n\n") sections,table_names = read_table_titles(reader) for section_name in sections: stream.write(section_name + "\n") stream.write("-"*len(section_name) + "\n\n") for table_name in table_names[section_name]: generate_table(reader,stream,table_name) csv_file.close() if __name__ == "__main__": csv_path = './coverage.csv' output_path = './coverage_table.txt' if len(sys.argv) > 1: if sys.argv[1][:5].lower() == "help": print("Coverage Table Generator: coverage_generator.py") print(" Usage: coverage_generator.py [csv] [output]") print(" csv - Path to csv file, defaults to ./coverage.csv") print(" output - Ouput path, defaults to ./coverage_table.txt") print('') sys.exit(0) if len(sys.argv) == 2: csv_path = os.path.abspath(sys.argv[1]) if len(sys.argv) == 3: output_path = os.path.abspath(sys.argv[2]) output = open(output_path,'w') generate_page(csv_path,output) output.close() print("Generated %s from %s." % (output_path,csv_path)) scikit-image-0.9.3/doc/source/gitwash/000077500000000000000000000000001223313777300176145ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/gitwash/branch_dropdown.png000066400000000000000000000376671223313777300235160ustar00rootroot00000000000000PNG  IHDR7'piCCPICC ProfilexTkA6n"Zkx"IYhE6bk Ed3In6&*Ezd/JZE(ޫ(b-nL~7}ov r4 Ril|Bj A4%UN$As{z[V{wwҶ@G*q Y<ߡ)t9Nyx+=Y"|@5-MS%@H8qR>׋infObN~N>! ?F?aĆ=5`5_M'Tq. VJp8dasZHOLn}&wVQygE0  HPEaP@<14r?#{2u$jtbDA{6=Q<("qCA*Oy\V;噹sM^|vWGyz?W15s-_̗)UKuZ17ߟl;=..s7VgjHUO^gc)1&v!.K `m)m$``/]?[xF QT*d4o(/lșmSqens}nk~8X<R5 vz)Ӗ9R,bRPCRR%eKUbvؙn9BħJeRR~NցoEx pHYs   IDATxEi9'IdADO' z9ܙ!D# I0P3Kf[l M;3vOwW~aHIvio.UTCo+"dEcml"E?%E@PE@ʄx(182:"(@!G .eSE ĬLHP$e͢(@!G fe(bŊrHy"("2={[WE@(ĬLjEcRȡ)"8 :`ӣ"( s&§犀"( 2qt^"( AڸqdggKNN.A(@!2!Pݎsʮ]L2Rre)RTnI4Z"(B &e*G8%7"P+$S-CPD .ecR&x$,;cOMKPE bd(ݱc(QS%E@P4D feIL\i(@#W+?% ,6mʘ^/_~x-(G nLKsQ$ ,FI˖-3&<Ɨ.W\i畊+*{viM(@)<I9%ڼuVٶml߽=E8S6E@[$ X\H2J,)[lї:3uhE xU'@+t;d.-[P@̞S$ #KVKW.L Wӵ5"(B fτ Yɕ\}|]xŇV"2I&+۰iԩl2^vav#d#N^(UVɺuZjRFjNzh/;%dee%͠D۷oKsznO9L /;1Xxnb +~z!Mr墲2$*q&[nիWr䭷*gyf蚞Ew}.;lР{RfiÆ r=?OUL:Ejת9pnw`~{Nxd~ew}jd=䓂p;t sLTՍ~xRby:uEʒ%K^T)]virAw/`>Bzٽ{} ?mڴv wyGڨ2I7བɁv .H6m*gϖ^{Mn69m۶ZMO$^~ >\;8.\P|Myg妛nҥKh{K/&M~p޽U,OYێ*U]_msc/g cǎ!#_}U+vȚkGJB8q؇n"sNQ:t(Txo\xRlYK/$x G}={R;wJCkB <,N(FZ3g ^K|VHq0y.ȑ#_ꫯUW]%͚5#8B "X͛7{W~+tbLÆ m9Xb6mbh{/|r'_Wڵk@c;~wߑ[ ˱W^ ޼y }?|p\ƍg:BKWU6? Huֶ<'AK.:/+sD](@/ݏ.Æ G$ba/_܎-ZȔ)S/~ 7ZƳ|;G+0ygołڰWζV=_Te2.b v BGG3y?;(y~| k֬}֬Y{=}t s \rp=a0.?DG)sذa?[h b*4ƀ9ꨣd` /1O>9JKٖMP:i$lZL6ncYNaѢE¡켤Gx@Xx*Z11]NW\!u-( 0

    "9F+<<_XG'KZog5;R+ٚcsN;Iǘ&-a0ȏgt!뮻jSc1 oRqpFgeG_EsN`KS'9XtoBcb`mϋ;rI'> N P" Lh}acgkSh7l0p<2s]G#yY.| w϶?cJD;Q&<xx2ž6 HyCNPsqJx@y7"K^ Gye=V0 uȥ "rP Xoz#er M^~ߴ {8|Y=A}= sG:9o1@9Ƴ+7^xu]/WopCymLgr1ec(ǟ~ɮ"v>j(hYb(>euͷS47cB.$9e8 -,,9gyBX,pĈ@(Q&eYgMs p2eO Q\n1^_>d +3ʧ?Ƴw|;1Y!ƒwj<V1~Q<'ƌÈ3V["+ bVp&<bAXXj(E`0)d3AzuG C(zZLb9(^k& BVĬ/bC!# sw;PXTXX=1QZx6 a Cµ aG{L)G @p>u1YBxxڽցB(EP Yy6k*+lD7 4ÍX>lx($r%/l)Bsm(x1&! Z#ؿ:E;?ZAhUB[b` ?ﴉX4&0?f lIt :v屰...{X( ڋB[<WQ(XgD!xq便m\l%a /Ed ;ʉ0uxN9~Tv)%m=;e&l%&O:b JH ~'ZA?>z|ǭ (o.x1^ 2q -Ld){CD;Ὗ F=?y.mߏ;'r.ZY픉kc4~‘ 7ڽ(lu(^3pD)3gA ")aq??H(AGݥK#8S$o[~gbx^#O˛YE  \M8-OuޙۍeNCi =E@P ŢHh sYE dS4WO8c&n(+^YP3$ԕĪP[P@Lh&AI!PҀdCA#,e",V WSP2I*@e2q.OF~E@P1+<]qDIIPE 5Y$] $a-_P!vɃBKVE@+LSE@!az("WR&0^k늀">q)d6)E@PQ&[^J"(@ʄ0$LOPkE@P2 ]͕i=UE $4\RRE@HORFU̙3Q:fZjsZM(@(p0q.Bĉ A+ "Hea.'s>Ϝ֖zRF\ymh P )Lמ ڒ> 'M)LThI0 TS ~dٲeI`WٹsgvMM, ޴i#9RnuP\GrrrK<t:/毰ԟ2]|G2d|ouѣwߕ\~m"&3f|3DL3m4KbŊ6 Cx@ʖ-1߁܈ͷȣ>j7N|M)"'tL0~*.k狣ϸ׼ dʔ)&|ʹN:裥٭!-^,gϖݻ˜9sU˖/1iУG4_*]wK{4NG1߁/{nr*/tmOڵe%ˌ-ZhU ɿp"yᇥ|+tӦMK.R%K&!oꫯ ^|<q믥wض}|7ܥ=2S$>AygeRn]믗^{MXȱkfثL ܬ^5^A!x?5sJ#FHfͤtҲ]ZL\8.ާl^'#G/8?vfR(KL' ,*UHdk6/K.@|ҨqcOQ&U2+r,{l߶]8it9KR."q֭Qvl&cƎ=T21xL Odƍ%C5;%9[o2fs 5a0`<H>c)W\pҧO \yrmmV{VVL2RjU!1eԯ__nQ4PnlXLrXXSXi{YP_XS3FYѶm[˃߰a﷗]v^޿4(X˧|y?kS(Ν:ncpR$kc93beWQ& .wBA?o-x!%J&?V3C t옱f[f7c ܢxa^¥\rԠ`;eT;w7cRRVm_|w4*U,mBg\iƌ(p\pT6iFFQZR%Rv-kn}No/yP$M~4-[ӌт,;̸XmfO27}[8-ttR5҇(B͟7O~|~+fq/;#ϟo"+"a&B=΄XyymƏ/O= vw /o 7 dy(3<ӆ 9}";#"qGh1y;/%8CkrMʲ crs$EKL?ۍC[ O?]N0b c"*#QNc~fԑx{Xx{ {93{3{UH8-sڵ/o 7vt5kJ+Y,ܽ>n6J%#ع&mH KV^-r@:Frmٱ2F:͆`$k9oo#G`G3,P&ccN8a PK䷡&?slF܄CI._]KeBypDXc"KCuGpф#p8G*U moL>J3%I=ocIDATX9-wqͱpp^阏p"x&4 Q&oЮGyTnN?ZL &%̬Y/ #+y;/XsgY(͛['aF(!4ŏ,i GG9qП,uD>ƆnǂI~m͢ʯf+}Y5廴(+'%Jڹqƣui7DE̘ܽ> !7:(;ǜ ![j5kAаaCۇ^}}\g/c[ل]^\]ys4 ?c C}wǔQ&`'㈉o0eJw%  AUQ>>8/`fnPHe|!(^/؆X+bC\sUB-$Gi/õϛ6 :ƬC &K;aܲX-j&kըi ,\,L`/X; F)ϦXe5 X5CPV4R^Ь_^s%=WHe";qk,.pCA!nx줴R'G8(bHe`-X;ڍQڦMkU[xKxJX=Wx)G>,Oa1OM11Ka,᥏7wC@ Tgs8K(#K[+ׄth9\΍p@@ LW26[ݽleO2̋q`LK/ԄP Ʋs:$B)Y1{cBxn|1G6[TbRы/h{XD{1yvn9D!-!^²@aI:x3 " %E) X,ѡCeya1`𜼫E 2Y|LBM'BP/W]iP[m#dwѷ,dJռh4&JB" ,dBPhtd?~ "cxMX~#GV"(/}^,D(Oe[\)p#(?7K_12B<%ry? iiR7k"g{)sy/DJnuQ޹P^,,yR3!%lx#@|ax83ibB1NLHPho! pD -rÕ R3 bR( ‚VJ,eEjm{X:)LrWyGA@mO"2Ŀ-zv0#0nfM'sݲc C+@"t>\ g>8E|ʳ@x1d"%%E@P W&vgÛU?攬9PC>~lKXrE@D eLܜ`0ztjQY-eJKבWX!7l>Gז.~PVdo.ij>ZT|gfE=][v%d)oD"ҾIA2m&8rt_%D19k-bOVMҺay߫<>bIx8CI2a|>m1ewm]E.^/!VhnRe~qRSJ:emY?(5 ~ώZ":T_))"+i'16%sdT˷}oϕV_T^b>(#sn_Ⱥ-;euҠF?jZS#t[/+(P>}59}U5i|;glپ;vֺ߸C_nfo)ύ\lQT15F@iӻ_+KS߮wXLPsAKv˲5$g95vȲ[m{C.ꕲdњuOPH;ĵcjˑk0}4WN֣jyTaE^W+e֣Ueyl"Y*su{@FKKm#`:1}6R{_W"h]{m\T*-!233+*Wח*QT~0&ay;_>lTԭRJf-߫8Vzd=HuX#\6(@XV/=|n2$DUPoѠLAV/ePT,%Kx27c 4 s*ұy%pcLNʕޛ7J{o)*+V.e-Wfowt#jHrY7˄Gݐ0U-HuoE@P;AISMdž~[/o{]A %%sCdY% uK8>R,>|2m4+Ԃ3g|=cܹsn$׿T~TXQn>''G;+L/j_P Q{+? &iFV^N=APxt%|С2sL^P?s2"űT}>xqKLo7X;'|ڵK7n,SL Dwmn0|Pϟ/ӧO5ju]g|r 'Xo&MX˞˖-<?!UW]%>޽[(W+]t0yfڵ 6L*UڻARļԨQ#yWyhhBB 8PUۻh/M 6E7Qz1h֬Y`y,6OK(!}/ԩuY6-B}Q~~,<!ʈijǢEA+(ȔV&u֥}J@@2ʮ\~J*UNM2˒%Kc A^f۵kN)2)S̛7Oz衰|\xA 䡠z ;V.+_]{!>'(VZ.תU A2zx,MbMGX#Zyx]%T|8ʇzAދ;B$(7gʏDx}USZDb^+Baopks׽GC=Z:}ժUvڲ`w* a,k/BX>=)~G9#w^2wy ]?ކr6mjP<ՆN|+++zjSNL($}䊉5chE*#ZիW;mpT1exoşJ+@B@M0NFGu<ʆ֯_oqI>}֭_g=nIPE)qR|y;ҦM C?O?ٹ* j_PA#(M翼,&Md%:bQP?4юy-Ëc:3^Wpb=z#FE,UuYN=T KI{feur)0Q}儢ݻ XrT/:̩ 3<3l\dmps<({,bzw#}Am"֡C2Hm']T"\AX9F˖-CϠWOky-O>z8SzGJ@aA`ĉvN8tBT􌇘#aC7/)VԬwj=9&^~ suL[(@!$D9RE Pev] +"z2I>QE@H;RzuJ"(@*N~_{5c:uo³Y"/3^~cv3pyK~l^Xxّ - !CwY7ߴoE owU֮]kʇ"7=gƌ6lX9zhzmӦMv;q'KhvȧU}rԩ[ZK Cmʕ+oav8Xڿ[4o}JoܩsD kРAv71/Gmp;$nΧ(PX6QP!oc1;+W.|xGn:Yξ XӢ8_l:I{#L Ldɒ69O*]J*WKAuMtk[!Xp\wuv_5ppJܕv#@UG)(/epn"H[ejd<O<Ɵ}1cX=& ^ ^"ć@ʆkdh.ڶBAC.X3(z&dE@P. N4Z"(* tm"(F@IE@@Td`kE@H4L(@"$;](@PehD= 1.7 you can ensure that the link is correctly set by using the ``--set-upstream`` option:: git push --set-upstream origin my-new-feature From now on git will know that ``my-new-feature`` is related to the ``my-new-feature`` branch in the github repo. .. _edit-flow: The editing workflow ==================== Overview -------- :: # hack hack git add my_new_file git commit -am 'NF - some message' git push In more detail -------------- #. Make some changes #. See which files have changed with ``git status`` (see `git status`_). You'll see a listing like this one:: # On branch ny-new-feature # Changed but not updated: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: README # # Untracked files: # (use "git add ..." to include in what will be committed) # # INSTALL no changes added to commit (use "git add" and/or "git commit -a") #. Check what the actual changes are with ``git diff`` (`git diff`_). #. Add any new files to version control ``git add new_file_name`` (see `git add`_). #. To commit all modified files into the local copy of your repo,, do ``git commit -am 'A commit message'``. Note the ``-am`` options to ``commit``. The ``m`` flag just signals that you're going to type a message on the command line. The ``a`` flag |emdash| you can just take on faith |emdash| or see `why the -a flag?`_ |emdash| and the helpful use-case description in the `tangled working copy problem`_. The `git commit`_ manual page might also be useful. #. To push the changes up to your forked repo on github, do a ``git push`` (see `git push`_). Ask for your changes to be reviewed or merged ============================================= When you are ready to ask for someone to review your code and consider a merge: #. Go to the URL of your forked repo, say ``http://github.com/your-user-name/scikit-image``. #. Use the 'Switch Branches' dropdown menu near the top left of the page to select the branch with your changes: .. image:: branch_dropdown.png #. Click on the 'Pull request' button: .. image:: pull_button.png Enter a title for the set of changes, and some explanation of what you've done. Say if there is anything you'd like particular attention for - like a complicated change or some code you are not happy with. If you don't think your request is ready to be merged, just say so in your pull request message. This is still a good way of getting some preliminary code review. Some other things you might want to do ====================================== Delete a branch on github ------------------------- :: git checkout master # delete branch locally git branch -D my-unwanted-branch # delete branch on github git push origin :my-unwanted-branch (Note the colon ``:`` before ``test-branch``. See also: http://github.com/guides/remove-a-remote-branch Several people sharing a single repository ------------------------------------------ If you want to work on some stuff with other people, where you are all committing into the same repository, or even the same branch, then just share it via github. First fork scikit-image into your account, as from :ref:`forking`. Then, go to your forked repository github page, say ``http://github.com/your-user-name/scikit-image`` Click on the 'Admin' button, and add anyone else to the repo as a collaborator: .. image:: pull_button.png Now all those people can do:: git clone git@githhub.com:your-user-name/scikit-image.git Remember that links starting with ``git@`` use the ssh protocol and are read-write; links starting with ``git://`` are read-only. Your collaborators can then commit directly into that repo with the usual:: git commit -am 'ENH - much better code' git push origin master # pushes directly into your repo Explore your repository ----------------------- To see a graphical representation of the repository branches and commits:: gitk --all To see a linear list of commits for this branch:: git log You can also look at the `network graph visualizer`_ for your github repo. Finally the :ref:`fancy-log` ``lg`` alias will give you a reasonable text-based graph of the repository. .. _rebase-on-trunk: Rebasing on trunk ----------------- Let's say you thought of some work you'd like to do. You :ref:`update-mirror-trunk` and :ref:`make-feature-branch` called ``cool-feature``. At this stage trunk is at some commit, let's call it E. Now you make some new commits on your ``cool-feature`` branch, let's call them A, B, C. Maybe your changes take a while, or you come back to them after a while. In the meantime, trunk has progressed from commit E to commit (say) G:: A---B---C cool-feature / D---E---F---G trunk At this stage you consider merging trunk into your feature branch, and you remember that this here page sternly advises you not to do that, because the history will get messy. Most of the time you can just ask for a review, and not worry that trunk has got a little ahead. But sometimes, the changes in trunk might affect your changes, and you need to harmonize them. In this situation you may prefer to do a rebase. rebase takes your changes (A, B, C) and replays them as if they had been made to the current state of ``trunk``. In other words, in this case, it takes the changes represented by A, B, C and replays them on top of G. After the rebase, your history will look like this:: A'--B'--C' cool-feature / D---E---F---G trunk See `rebase without tears`_ for more detail. To do a rebase on trunk:: # Update the mirror of trunk git fetch upstream # go to the feature branch git checkout cool-feature # make a backup in case you mess up git branch tmp cool-feature # rebase cool-feature onto trunk git rebase --onto upstream/master upstream/master cool-feature In this situation, where you are already on branch ``cool-feature``, the last command can be written more succinctly as:: git rebase upstream/master When all looks good you can delete your backup branch:: git branch -D tmp If it doesn't look good you may need to have a look at :ref:`recovering-from-mess-up`. If you have made changes to files that have also changed in trunk, this may generate merge conflicts that you need to resolve - see the `git rebase`_ man page for some instructions at the end of the "Description" section. There is some related help on merging in the git user manual - see `resolving a merge`_. .. _recovering-from-mess-up: Recovering from mess-ups ------------------------ Sometimes, you mess up merges or rebases. Luckily, in git it is relatively straightforward to recover from such mistakes. If you mess up during a rebase:: git rebase --abort If you notice you messed up after the rebase:: # reset branch back to the saved point git reset --hard tmp If you forgot to make a backup branch:: # look at the reflog of the branch git reflog show cool-feature 8630830 cool-feature@{0}: commit: BUG: io: close file handles immediately 278dd2a cool-feature@{1}: rebase finished: refs/heads/my-feature-branch onto 11ee694744f2552d 26aa21a cool-feature@{2}: commit: BUG: lib: make seek_gzip_factory not leak gzip obj ... # reset the branch to where it was before the botched rebase git reset --hard cool-feature@{2} .. _rewriting-commit-history: Rewriting commit history ------------------------ .. note:: Do this only for your own feature branches. There's an embarassing typo in a commit you made? Or perhaps the you made several false starts you would like the posterity not to see. This can be done via *interactive rebasing*. Suppose that the commit history looks like this:: git log --oneline eadc391 Fix some remaining bugs a815645 Modify it so that it works 2dec1ac Fix a few bugs + disable 13d7934 First implementation 6ad92e5 * masked is now an instance of a new object, MaskedConstant 29001ed Add pre-nep for a copule of structured_array_extensions. ... and ``6ad92e5`` is the last commit in the ``cool-feature`` branch. Suppose we want to make the following changes: * Rewrite the commit message for ``13d7934`` to something more sensible. * Combine the commits ``2dec1ac``, ``a815645``, ``eadc391`` into a single one. We do as follows:: # make a backup of the current state git branch tmp HEAD # interactive rebase git rebase -i 6ad92e5 This will open an editor with the following text in it:: pick 13d7934 First implementation pick 2dec1ac Fix a few bugs + disable pick a815645 Modify it so that it works pick eadc391 Fix some remaining bugs # Rebase 6ad92e5..eadc391 onto 6ad92e5 # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. # To achieve what we want, we will make the following changes to it:: r 13d7934 First implementation pick 2dec1ac Fix a few bugs + disable f a815645 Modify it so that it works f eadc391 Fix some remaining bugs This means that (i) we want to edit the commit message for ``13d7934``, and (ii) collapse the last three commits into one. Now we save and quit the editor. Git will then immediately bring up an editor for editing the commit message. After revising it, we get the output:: [detached HEAD 721fc64] FOO: First implementation 2 files changed, 199 insertions(+), 66 deletions(-) [detached HEAD 0f22701] Fix a few bugs + disable 1 files changed, 79 insertions(+), 61 deletions(-) Successfully rebased and updated refs/heads/my-feature-branch. and the history looks now like this:: 0f22701 Fix a few bugs + disable 721fc64 ENH: Sophisticated feature 6ad92e5 * masked is now an instance of a new object, MaskedConstant If it went wrong, recovery is again possible as explained :ref:`above `. .. include:: links.inc scikit-image-0.9.3/doc/source/gitwash/following_latest.txt000066400000000000000000000015561223313777300237400ustar00rootroot00000000000000.. _following-latest: ============================= Following the latest source ============================= These are the instructions if you just want to follow the latest *scikit-image* source, but you don't need to do any development for now. The steps are: * :ref:`install-git` * get local copy of the `scikit-image github`_ git repository * update local copy from time to time Get the local copy of the code ============================== From the command line:: git clone git://github.com/scikit-image/scikit-image.git You now have a copy of the code tree in the new ``scikit-image`` directory. Updating the code ================= From time to time you may want to pull down the latest code. Do this with:: cd scikit-image git pull The tree in ``scikit-image`` will now have the latest changes from the initial repository. .. include:: links.inc scikit-image-0.9.3/doc/source/gitwash/forking_button.png000066400000000000000000000314441223313777300233620ustar00rootroot00000000000000PNG  IHDR]Vl8E pHYs   IDATx]|Tv7ݴMN]&O  X(("}`@z!!@$ I6{wHŐ ww|s,JlG#i7p8t"p8Dn ͛p8tp8Dn ͛p8tp8D۪SMYVܺu jN:H;Ц22{wG(7o#77}Z+6/_18+{22+ߔ'Tnn.\\\z)H~cCEҿ++3^KX,`B`UC(s*Ҁ{/22'7#G>F},\>ë˗ sݿ/^v;s+p[cF5nGd2{VVՍÙ3gh"A0'OFvٱ߹nɊd-ڕzzz:mۆ9s=33ž鯬C~0~Ure$!nm,W#q(gǝ݌XlP844\K7n' USֽ__\] \d 222@h[/Aadr]3\ĻTnJo8aӻ%&52_VN߫nV䭄ha9r0`0vލM6 駟.ڙ٦z$])Fg,Zn.P:٠3Uӕ+17sBo aMM0V9EGի3f S`f Bq]_w34&k%dAG=pS*V999;w.Fc$o0}tNANj̈́B!@<E~=ֹG ~Jk6hubC}@#S1@H³^gȌn1j˕+W" AAA5kؽS6> |oZlY`ݖ>,uh ؽę}&|~4Ú`{a{hi_}UΘ(d]ٳÐD74'Xfm Z`zd ޚ0Ԥ/{q٫!Lq)5(J/1+pũK|K+bէƏ>ƺ9Bc>GSޝfDND?](f[<kcc\wviprr\*씝6vTJ%m㿳b%/Q8`[BLjo?@ ew26؆c޻E'6W  _B8'^m6@m_ϚA'|%=s}]j8HGǦ`wgiSbȜy8|b7r$*&t+|Nc;#p헏P:GJ+.2. Ô)S'|RHc_}=Z6P(QKؘUN|N6ؤlEqbs!ES0nl"\CoBvn>lB{o6IBѽs#-F!#ؾ= D*βă84I!V<.#\iZe?`(l 6 >َ; pOoʼnU %/8. D/8˨㻘vn'[UH+w-_|@l1b9&N(rY-47{=Q/W[n4b`vq=b,bpu&=\Ip`g8ً+V!JJ@Gc?ExF(>1JO 2/s@~λvH4rl.ӻ-,Ĩc#U"~T|bBǽzDؗLrK@硫]+d)J ('Y<3nʲJZLeE;)yc3QiXʊYc,^A>,#El %I_ɎƙHB# <$W|,S. FqF{-.-R=F?zGzys> 2ȭ0.峂dSr%b>\f1eiggg和ܸhME(p]_ ĶC`zP__cgA ~U%%Yt5q˞ՁÈ!kl;HdiLט\.8>n0y: aPK%:`#"DJ.])b#P|cl,:hՂNB"C^~.n,"NG.zc2jb7Xƶň % ^.nJ?DKVfʃ,/S)].`:2= ]EXE>H{ Xt`qܹϟ/={~xxx7Do*|]k=&teAN:mj>:EO![N>EqwpJx CqḬlRR4TƋ k ¯Ɍr тTRF0r,zp9pG%4oo~)dߞn ƅ*X攝D4Ta3'XJB%Qj`.KPˋ9i M&[Yp{yq,Y\0*9a=!aON:`AB,l"mӏWr~ţcah|4$ꔠ`Bo3 {e5;Q#m.擏810I"'S33~^fӘah#18mkSp`rGZ(D}woo5+p_ +9[Kc;91czꅤ$pq>|*OJJ\ uX*:e> Q+ƌ8c1>[f(h^ de 76ѯ=.]a6 y_Bzϡg#3.7 1P-FbM&'c3Иz >5<( /^ Kj(ǸO1wٟ|e=?6M~A q`lѩS'!XYJN&&<9soVC_=똧s-? !:bs". ۿϛ/R􅊔ʫQБ=ˋs ONS.VM>‘tװ}ؿe"_^5^оMNָ.W 6C':ep[ȶ)o۠m]h c'q&iI>7`=p!xhVEφ2HGa{T*{ӾߊVC&&iɲv.p)2br-ˈYk:NgϞ &y @L W?}@+8w4¤sщfF 'ڲ3S9HF@O4)PZMh1Q̞0 pQ!E/G ز`sa&^~fXh4|]D7pTZ͛z/^T 53ĉ,"{e[C}#+N!vr_b\ \*w2l%7=gadaR.^H7n\A ޗ$ - Lj,::Sycr67'nAp_A+Y'A>0|1ާWg`ΆH<'x*A_IS"PNkcoǓf!#&Ǿo,ċt(r3i"m7с{ 55 N\D"R"G"_gRdU2VޖSqI=?r2eȶD]Rhew pMyhZ=#hӓ&6-P*/w;R\\=i&UZg&&3|=)L5@mh`+  =R\V;ӍZˡP J|MKKCHHH_+믿^Ph•ijrJ@J>K gOBC.gGZ-LdyzcW q!pKa1h_vPtE^5km+d4FAwJd`iǝg]7,)H/n@1 7Ȝ!w;CFq{Eƫ-ɭpÇZt+IF zm vAFZXԆAThO";l \vHftoTJ6PSwRrƀMvSfΪ%ҒU# ŋ.,VJ~C4T*R\VKe0fRفٯ*,^l2FF?qd__fޖ"*'ov(JH*VZ`E½<^?olz[wG8 7Z18'{322];aVun 1ǡ" +#3~{.ɍxq9.5s_VMv6Gy~ǘPʹȌ);+G>E|S>4G#-8]GN"IN#-8]GN"IN#-8]GN"IN#-8]GN"IN#-8]GN"IN#-8]GN"IN#-8]GN"IN#-8]GN"IN#-8]GN"IN#-km.G#s8yyyչAs8Bj y.G#P'plur|G6nmp,t9@ju&G#Pgn=8G#Ppҭ y@E9@[:o#pKΊ# [69:lʔ)ӫ:fD}$U-\OhZ #r4՛t.Y?p"ͭHbѦ…xe!-/_]oxDE"QxR5|\ing8]ܢ>d:jpv]9kMDMTMtȼQ Rq!1psqxÔeɦK/m804sayF ,YWcu DMkYaIߢ#GwgSp&"V(OaRa_7`?ķ"lQk\Nȸr+~ك[LW^w CQ#OCj$6l(=㥁Q8}KV}6"öduSLꫛj2dFaǎs4*ծŞp݋xUkشgM3k[KӜ[@)xl&!͟#c ZʧN0k"lV CDҁHt`12^$XL6]1wV7 R~ҟtp vGxcʳh+8f6$w'Ӟ*Y̮Pa܊9<=4/}k |MP[D??|e_ϫO˘0qHsK<1TO=$_jF¾q,^ v2b(Zkǖ}r 4n=26`Q`mBG*s[Ȃ͕'-/@Ett /2Dz%D;yxa` ",DYKTU8k$褰!awU1Hv͌ m}1v0 oÑ/w||}%DϨ=4ƀ^a”W81ra4ޱ O›<`p4]һ>-%t'`!'W'|t59*֯ .!H?1~@S$Dg!'0ok8[2m h  \ Nmؓe1rHsIYvPTѾC!,z >b0Z+q`8-4&5IȒ*i5f^GVB>T0K6z%6.sQ/C1bpONᗅ{`0(wʕЭPk:R6FhBd":Ҥ%زy%y\]4eBDGiK$[HUu1#е-#|֟"ԄHw#Ȉˑκ˩(ɇwסA#?S{h'\}(YQY0F 6p}Q#,|4_`IšP7t8 F- םi._i&Mg@LAPiySpխwm$QMՔ|rU{ KHI%-C1\ˆt˰)W2P Md,a#T:Qx 9ߦZ\s'LfA>[5&Mo£W'Q B " q1't"񮐑QKY˷yyUDC;"ڤB O/;Çggd \'!2<Ύe q1pUzbCå'iV#KxM¬ 4)7֞ z[ѭ[s@v)]BKKS*읤VF6fIVbs&4莽!ȴ6sg sx[9l0p#3ѡl̀ JgAR3 F3dMKdYìuXlr_udMȻ!?f|`IF(ĥg"W$ꎩS?YJڶrlsçtܳk&R0,bE<=;$bTv_F2+ԭ(rxȿoo!+a[I[.`EC/3aĠIDATF6`!vdI#:T ZT=$&{+-O^#XA>c 01x(`61ʠ\g/IkM"݊J/.\EK[4i@_ĥ,훉hZ5T=:df?ʒ47n@{mFL-\-yM4X>'6icTr9lthJGN}gr>\u#O/.d':F6$vgp&70eڹ;j?B;W*s=lɇ#m5Х>d aF~0 ޭ >e"4XPG^Cf1f`D=Ef@@61X?{26CmukhDii/( ;H#$2h)aQz#1hfˉ YKO im,?-(aoak&*"HI+q0<ӔR 5$ ! /Hw"\4~1߯u@9LGAeñ+7KE{KȲ!:ՆaP،ɡе\:1oJݣ`ީoȥcu bBGzBWZ $^!g67: c tf q$&_p=IB-4"{8W趒#zlBZ%RhEk5!Gk4(F'4 ͪe}-.PuKV`s@|^+D=.xێ.#6)Ei* i,<ĢFڡ)Vjq%|;-Phk&v!_ޱ㈊?oSc0HT#[ Tcv$zھ-OFd3[ 7PѷڊS.#!Uqe8pƍ4諔F`#I žHػvñq6RMdÉq*җHXgk1d mmT@R)[X vI2!d0˒yÍpv;0 if" YidD!YӬ3▧PgJȓ{%!rP]PN!CV:X[iAxx2BAvͰoWf:4Ul$+Š"RgCoڦ-4p/HgQacfANDf5.],$ &&ӡ&] 9 B 5$ە_xaI6ƢBKm&=?߹OgQ!xE= :Ǹsss^6'_3Y0I!6€aKm|T[0hj:B4R⥧GgB/AT}۰!IiCۋ+\FlpJUw ]qOҤ" t:Y~, F"/ĨehE@ m:HMh{Q}lD17R4ep&mq+C[D/]V q[xN-lH7ɔ *49v0i{= hN=)B !~2rHXXB=4΂gyXFH8 E +EP _-("Cv|ċT͚ةKHS_Xf&Y8vEI 9h dP]z :.'M;D-ċccwM˓ 歡ƉYrm߁_* ++pCtJߍҰ ,Y{U!aeҲ^4{F&G4Y\XciG%hأTV:@kv i׈Z6e7wع2VڤP߉~©rkbhr\Tn]_fc-jxV4hۊ&sVj\?a$N'WRdt;$dLV;[GYJG~4d%ŚG&F֣t]k#X):j_`pgx!$7Uy`X{ARؙ@c=ca&ůN%ȅ:(h6Wь"H[Oؿ E,3N^'7O¼6'[KUDt ?gc JtA`V>rV:~^O_$ڙ9匉gѧoZNuIUti $3KB;fA4.ApT#z5Act9EY* <HSI_4!4Kװh vb-!3iGךp! hEYqڴ\#It[0vcX=p)>)/)m'dۆ?>b]yOM\1phmO}P/+^5h5p4W]paزO֠&6ȅY*\6dg#UZ,)#a=MpǘIHOeߙ²4b+CflZ [z?? = ^]111 V%߅ ɕTwWVWNt^MŐ@oZ+\_"o_=4w1#ڒ0PxEKwDǚѵ]؏Sm3hڈ'RT*ꀓ™ɂ#n䅕8tyS`QZіᓸ9d2`9+L>MΡ LeMKvGv]+hRQφƒUO6fdUC88~+e=9ܝc[ȍKA !6w沸tƂہ ^Bf;W5H^C?K4 (NidQ8)TӬFnYE,tH樗.Ɓ]tp"W]) rA5*`9ɹ^|PZf>NÛ"nNHf:tc DE)Y~f|JMr+sjQU/QxCub|M. [Г޴"2QJ((/DYYEI?vX0&)<|}lVAlK ZJד_ |-f'DbYt`&wV+|UtKĂ'YwZ:H4* J %ʂnTN@aW;%x1paLͿUSg My::WY:Ҕ*_wY(Ț%pYFrZ<b7ɇ~?MehdE{ix*# hSId3}n÷coK[95w?]sN W9ёӎOQ١܂2V2rWᏠk3t@ -݂ɢX;l :+Jݙ\ڛ\s"Ǵ&&}/o/[^@[f%~5[,A\GFm˲feK'\Vd"kTirMn .Mƿ;8su*$TVY䋑poo kJ U-ro~Z p/gRUkiKJf$h.kj)$\]'q0tJ 7NGA^Ąv} &O Lj_DUXʪӒ(c3|WںhkpYIݮ`e )V2d 3YB^5 )qXE%W[{ {ѿDWҲ4} zTYx|# UC5[:TI/_wrȭpM~XL[,E1w<$!!sJM p8@8G#P>U2V~}<#pA[Ó8@u#-FpA[Ó8@u#Iq8rrIGd-N$IENDB`scikit-image-0.9.3/doc/source/gitwash/forking_hell.txt000066400000000000000000000022131223313777300230160ustar00rootroot00000000000000.. _forking: ============================================ Making your own copy (fork) of scikit-image ============================================ You need to do this only once. The instructions here are very similar to the instructions at http://help.github.com/forking/ |emdash| please see that page for more detail. We're repeating some of it here just to give the specifics for the scikit-image_ project, and to suggest some default names. Set up and configure a github account ====================================== If you don't have a github account, go to the github page, and make one. You then need to configure your account to allow write access |emdash| see the ``Generating SSH keys`` help on `github help`_. Create your own forked copy of scikit-image_ ============================================= #. Log into your github account. #. Go to the scikit-image_ github home at `scikit-image github`_. #. Click on the *fork* button: .. image:: forking_button.png Now, after a short pause and some 'Hardcore forking action', you should find yourself at the home page for your own forked copy of scikit-image_. .. include:: links.inc scikit-image-0.9.3/doc/source/gitwash/git_development.txt000066400000000000000000000003401223313777300235370ustar00rootroot00000000000000.. _git-development: ===================== Git for development ===================== Contents: .. toctree:: :maxdepth: 2 forking_hell set_up_fork configure_git development_workflow maintainer_workflow scikit-image-0.9.3/doc/source/gitwash/git_install.txt000066400000000000000000000011071223313777300226650ustar00rootroot00000000000000.. _install-git: ============= Install git ============= Overview ======== ================ ============= Debian / Ubuntu ``sudo apt-get install git-core`` Fedora ``sudo yum install git-core`` Windows Download and install msysGit_ OS X Use the git-osx-installer_ ================ ============= In detail ========= See the git page for the most recent information. Have a look at the github install help pages available from `github help`_ There are good instructions here: http://book.git-scm.com/2_installing_git.html .. include:: links.inc scikit-image-0.9.3/doc/source/gitwash/git_intro.txt000066400000000000000000000010471223313777300223550ustar00rootroot00000000000000============== Introduction ============== These pages describe a git_ and github_ workflow for the scikit-image_ project. There are several different workflows here, for different ways of working with *scikit-image*. This is not a comprehensive git reference, it's just a workflow for our own project. It's tailored to the github hosting service. You may well find better or quicker ways of getting stuff done with git, but these should get you started. For general resources for learning git, see :ref:`git-resources`. .. include:: links.inc scikit-image-0.9.3/doc/source/gitwash/git_links.inc000066400000000000000000000070241223313777300222750ustar00rootroot00000000000000.. This (-*- rst -*-) format file contains commonly used link targets and name substitutions. It may be included in many files, therefore it should only contain link targets and name substitutions. Try grepping for "^\.\. _" to find plausible candidates for this list. .. NOTE: reST targets are __not_case_sensitive__, so only one target definition is needed for nipy, NIPY, Nipy, etc... .. git stuff .. _git: http://git-scm.com/ .. _github: http://github.com .. _github help: http://help.github.com .. _msysgit: http://code.google.com/p/msysgit/downloads/list .. _git-osx-installer: http://code.google.com/p/git-osx-installer/downloads/list .. _subversion: http://subversion.tigris.org/ .. _git cheat sheet: http://github.com/guides/git-cheat-sheet .. _pro git book: http://progit.org/ .. _git svn crash course: http://git-scm.com/course/svn.html .. _learn.github: http://learn.github.com/ .. _network graph visualizer: http://github.com/blog/39-say-hello-to-the-network-graph-visualizer .. _git user manual: http://www.kernel.org/pub/software/scm/git/docs/user-manual.html .. _git tutorial: http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html .. _git community book: http://book.git-scm.com/ .. _git ready: http://www.gitready.com/ .. _git casts: http://www.gitcasts.com/ .. _Fernando's git page: http://www.fperez.org/py4science/git.html .. _git magic: http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html .. _git concepts: http://www.eecs.harvard.edu/~cduan/technical/git/ .. _git clone: http://www.kernel.org/pub/software/scm/git/docs/git-clone.html .. _git checkout: http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html .. _git commit: http://www.kernel.org/pub/software/scm/git/docs/git-commit.html .. _git push: http://www.kernel.org/pub/software/scm/git/docs/git-push.html .. _git pull: http://www.kernel.org/pub/software/scm/git/docs/git-pull.html .. _git add: http://www.kernel.org/pub/software/scm/git/docs/git-add.html .. _git status: http://www.kernel.org/pub/software/scm/git/docs/git-status.html .. _git diff: http://www.kernel.org/pub/software/scm/git/docs/git-diff.html .. _git log: http://www.kernel.org/pub/software/scm/git/docs/git-log.html .. _git branch: http://www.kernel.org/pub/software/scm/git/docs/git-branch.html .. _git remote: http://www.kernel.org/pub/software/scm/git/docs/git-remote.html .. _git rebase: http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html .. _git config: http://www.kernel.org/pub/software/scm/git/docs/git-config.html .. _why the -a flag?: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html .. _git staging area: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html .. _tangled working copy problem: http://tomayko.com/writings/the-thing-about-git .. _git management: http://kerneltrap.org/Linux/Git_Management .. _linux git workflow: http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html .. _git parable: http://tom.preston-werner.com/2009/05/19/the-git-parable.html .. _git foundation: http://matthew-brett.github.com/pydagogue/foundation.html .. _deleting master on github: http://matthew-brett.github.com/pydagogue/gh_delete_master.html .. _rebase without tears: http://matthew-brett.github.com/pydagogue/rebase_without_tears.html .. _resolving a merge: http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#resolving-a-merge .. _ipython git workflow: http://mail.scipy.org/pipermail/ipython-dev/2010-October/006746.html .. other stuff .. _python: http://www.python.org .. |emdash| unicode:: U+02014 .. vim: ft=rst scikit-image-0.9.3/doc/source/gitwash/git_resources.txt000066400000000000000000000034221223313777300232330ustar00rootroot00000000000000.. _git-resources: ============= git resources ============= Tutorials and summaries ======================= * `github help`_ has an excellent series of how-to guides. * `learn.github`_ has an excellent series of tutorials * The `pro git book`_ is a good in-depth book on git. * A `git cheat sheet`_ is a page giving summaries of common commands. * The `git user manual`_ * The `git tutorial`_ * The `git community book`_ * `git ready`_ |emdash| a nice series of tutorials * `git casts`_ |emdash| video snippets giving git how-tos. * `git magic`_ |emdash| extended introduction with intermediate detail * The `git parable`_ is an easy read explaining the concepts behind git. * `git foundation`_ expands on the `git parable`_. * Fernando Perez' git page |emdash| `Fernando's git page`_ |emdash| many links and tips * A good but technical page on `git concepts`_ * `git svn crash course`_: git for those of us used to subversion_ Advanced git workflow ===================== There are many ways of working with git; here are some posts on the rules of thumb that other projects have come up with: * Linus Torvalds on `git management`_ * Linus Torvalds on `linux git workflow`_ . Summary; use the git tools to make the history of your edits as clean as possible; merge from upstream edits as little as possible in branches where you are doing active development. Manual pages online =================== You can get these on your own machine with (e.g) ``git help push`` or (same thing) ``git push --help``, but, for convenience, here are the online manual pages for some common commands: * `git add`_ * `git branch`_ * `git checkout`_ * `git clone`_ * `git commit`_ * `git config`_ * `git diff`_ * `git log`_ * `git pull`_ * `git push`_ * `git remote`_ * `git status`_ .. include:: links.inc scikit-image-0.9.3/doc/source/gitwash/index.txt000066400000000000000000000003551223313777300214670ustar00rootroot00000000000000.. _using-git: Working with *scikit-image* source code ======================================== Contents: .. toctree:: :maxdepth: 2 git_intro git_install following_latest patching git_development git_resources scikit-image-0.9.3/doc/source/gitwash/known_projects.inc000066400000000000000000000027031223313777300233560ustar00rootroot00000000000000.. Known projects .. PROJECTNAME placeholders .. _PROJECTNAME: http://neuroimaging.scipy.org .. _`PROJECTNAME github`: http://github.com/nipy .. _`PROJECTNAME mailing list`: http://projects.scipy.org/mailman/listinfo/nipy-devel .. numpy .. _numpy: hhttp://numpy.scipy.org .. _`numpy github`: http://github.com/numpy/numpy .. _`numpy mailing list`: http://mail.scipy.org/mailman/listinfo/numpy-discussion .. scipy .. _scipy: http://www.scipy.org .. _`scipy github`: http://github.com/scipy/scipy .. _`scipy mailing list`: http://mail.scipy.org/mailman/listinfo/scipy-dev .. nipy .. _nipy: http://nipy.org/nipy .. _`nipy github`: http://github.com/nipy/nipy .. _`nipy mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel .. ipython .. _ipython: http://ipython.scipy.org .. _`ipython github`: http://github.com/ipython/ipython .. _`ipython mailing list`: http://mail.scipy.org/mailman/listinfo/IPython-dev .. dipy .. _dipy: http://nipy.org/dipy .. _`dipy github`: http://github.com/Garyfallidis/dipy .. _`dipy mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel .. nibabel .. _nibabel: http://nipy.org/nibabel .. _`nibabel github`: http://github.com/nipy/nibabel .. _`nibabel mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel .. marsbar .. _marsbar: http://marsbar.sourceforge.net .. _`marsbar github`: http://github.com/matthew-brett/marsbar .. _`MarsBaR mailing list`: https://lists.sourceforge.net/lists/listinfo/marsbar-users scikit-image-0.9.3/doc/source/gitwash/links.inc000066400000000000000000000001611223313777300214250ustar00rootroot00000000000000.. compiling links file .. include:: known_projects.inc .. include:: this_project.inc .. include:: git_links.inc scikit-image-0.9.3/doc/source/gitwash/maintainer_workflow.txt000066400000000000000000000060301223313777300244350ustar00rootroot00000000000000.. _maintainer-workflow: ################### Maintainer workflow ################### This page is for maintainers |emdash| those of us who merge our own or other peoples' changes into the upstream repository. Being as how you're a maintainer, you are completely on top of the basic stuff in :ref:`development-workflow`. The instructions in :ref:`linking-to-upstream` add a remote that has read-only access to the upstream repo. Being a maintainer, you've got read-write access. It's good to have your upstream remote have a scary name, to remind you that it's a read-write remote:: git remote add upstream-rw git@github.com:scikit-image/scikit-image.git git fetch upstream-rw ******************* Integrating changes ******************* Let's say you have some changes that need to go into trunk (``upstream-rw/master``). The changes are in some branch that you are currently on. For example, you are looking at someone's changes like this:: git remote add someone git://github.com/someone/scikit-image.git git fetch someone git branch cool-feature --track someone/cool-feature git checkout cool-feature So now you are on the branch with the changes to be incorporated upstream. The rest of this section assumes you are on this branch. A few commits ============= If there are only a few commits, consider rebasing to upstream:: # Fetch upstream changes git fetch upstream-rw # rebase git rebase upstream-rw/master Remember that, if you do a rebase, and push that, you'll have to close any github pull requests manually, because github will not be able to detect the changes have already been merged. A long series of commits ======================== If there are a longer series of related commits, consider a merge instead:: git fetch upstream-rw git merge --no-ff upstream-rw/master The merge will be detected by github, and should close any related pull requests automatically. Note the ``--no-ff`` above. This forces git to make a merge commit, rather than doing a fast-forward, so that these set of commits branch off trunk then rejoin the main history with a merge, rather than appearing to have been made directly on top of trunk. Check the history ================= Now, in either case, you should check that the history is sensible and you have the right commits:: git log --oneline --graph git log -p upstream-rw/master.. The first line above just shows the history in a compact way, with a text representation of the history graph. The second line shows the log of commits excluding those that can be reached from trunk (``upstream-rw/master``), and including those that can be reached from current HEAD (implied with the ``..`` at the end). So, it shows the commits unique to this branch compared to trunk. The ``-p`` option shows the diff for these commits in patch form. Push to trunk ============= :: git push upstream-rw my-new-feature:master This pushes the ``my-new-feature`` branch in this repository to the ``master`` branch in the ``upstream-rw`` repository. .. include:: links.inc scikit-image-0.9.3/doc/source/gitwash/patching.txt000066400000000000000000000077771223313777300221740ustar00rootroot00000000000000================ Making a patch ================ You've discovered a bug or something else you want to change in scikit-image_ .. |emdash| excellent! You've worked out a way to fix it |emdash| even better! You want to tell us about it |emdash| best of all! The easiest way is to make a *patch* or set of patches. Here we explain how. Making a patch is the simplest and quickest, but if you're going to be doing anything more than simple quick things, please consider following the :ref:`git-development` model instead. .. _making-patches: Making patches ============== Overview -------- :: # tell git who you are git config --global user.email you@yourdomain.example.com git config --global user.name "Your Name Comes Here" # get the repository if you don't have it git clone git://github.com/scikit-image/scikit-image.git # make a branch for your patching cd scikit-image git branch the-fix-im-thinking-of git checkout the-fix-im-thinking-of # hack, hack, hack # Tell git about any new files you've made git add somewhere/tests/test_my_bug.py # commit work in progress as you go git commit -am 'BF - added tests for Funny bug' # hack hack, hack git commit -am 'BF - added fix for Funny bug' # make the patch files git format-patch -M -C master Then, send the generated patch files to the `scikit-image mailing list`_ |emdash| where we will thank you warmly. In detail --------- #. Tell git who you are so it can label the commits you've made:: git config --global user.email you@yourdomain.example.com git config --global user.name "Your Name Comes Here" #. If you don't already have one, clone a copy of the scikit-image_ repository:: git clone git://github.com/scikit-image/scikit-image.git cd scikit-image #. Make a 'feature branch'. This will be where you work on your bug fix. It's nice and safe and leaves you with access to an unmodified copy of the code in the main branch:: git branch the-fix-im-thinking-of git checkout the-fix-im-thinking-of #. Do some edits, and commit them as you go:: # hack, hack, hack # Tell git about any new files you've made git add somewhere/tests/test_my_bug.py # commit work in progress as you go git commit -am 'BF - added tests for Funny bug' # hack hack, hack git commit -am 'BF - added fix for Funny bug' Note the ``-am`` options to ``commit``. The ``m`` flag just signals that you're going to type a message on the command line. The ``a`` flag |emdash| you can just take on faith |emdash| or see `why the -a flag?`_. #. When you have finished, check you have committed all your changes:: git status #. Finally, make your commits into patches. You want all the commits since you branched from the ``master`` branch:: git format-patch -M -C master You will now have several files named for the commits:: 0001-BF-added-tests-for-Funny-bug.patch 0002-BF-added-fix-for-Funny-bug.patch Send these files to the `scikit-image mailing list`_. When you are done, to switch back to the main copy of the code, just return to the ``master`` branch:: git checkout master Moving from patching to development =================================== If you find you have done some patches, and you have one or more feature branches, you will probably want to switch to development mode. You can do this with the repository you have. Fork the scikit-image_ repository on github |emdash| :ref:`forking`. Then:: # checkout and refresh master branch from main repo git checkout master git pull origin master # rename pointer to main repository to 'upstream' git remote rename origin upstream # point your repo to default read / write to your fork on github git remote add origin git@github.com:your-user-name/scikit-image.git # push up any branches you've made and want to keep git push origin the-fix-im-thinking-of Then you can, if you want, follow the :ref:`development-workflow`. .. include:: links.inc scikit-image-0.9.3/doc/source/gitwash/pull_button.png000066400000000000000000000311351223313777300226740ustar00rootroot00000000000000PNG  IHDR~\iu pHYs   IDATx]|ToߔMHH PKT,"S, O}%"]zHR@dw޽fIBB$a&{3s̙3s72p8 G# ?G#p!}p]G#?G#p!}p]G#?G#p!HKKCVVVuNPF C./y>xbpˏUVe͛7׭=Obyyy()6c\,4lYѬ)4,= {$H& 0,n8^CtqѸ˱gEsZzl6~?vu;Oͽyv+gkx G#}كSԩSª8xy$;w}Z*.6.O[B$ɴ r)ɝĻB? Z}|?ìqu'.=IXHG.A0[rgcǎN,YDx_>kƮG όSN3^ǶQX+PmY+ˁ\K_,?~\#GBPN$,"E؟ A~ǧGLVs',o<5#3( fa0`9UI l>`ŒOлa彣p0e3ggx~Zb>1cƠiӦE*(O_˝)ޝ:8G| < 'g>!A>; oxMۍ9gH0taق.IFp̟3W6bά|`xhs &އĶ?EK+X4|ad#,0+VCSȦٳоq?$` 0ot$WRsp-.vx3k;~ŒO >`4|H>Og,O5E 4}LZ'Š&^xz` hXl,CbM8ִvXI:?? $̯?c{+]DJ___L4 ׿h5 &O  ^d g|tU"?5yɟ0pwX&<[?GWirToV|){<3mLAmxs 6'@9l>.#0}H4tŅx-w}__n Ơu~1b{֮҇#`4|(6y{fm^g][l?2wagsxqt'`oqѪ!!CMcZxL8ϦmE)*ue/fJ{ ž{LhϞ=WZˀ8y36 ‘3ݟL?w $ZMsѬ^ tɉ)"NKto+Щw+N7oG@2_ >tł@Y``0<\"aJ)Ϭ &57"&I! Rs=oֱ8) V8ޑxkme: #Hxӧp8ƿRh,@ #膣kw )@Ȥ r-e0gG|)o$b}"1bPddpyC#W.?E'\lǂ\Zز\m4rognYr2y^ /&욟*SY|!ڜi&rE|v9#' eH\|=0i;@F%!_Am62bK ? ( #`H.Ң #ӑݐ`6ֿfO< ͨOzde/mȄ<@soΛXyɒKcs30oOIZM}5 R-AnJiz$HlY3"1j^8A: GZE_ErrV $1W,PߐT?M!1v\w'_w :\db5nMQ^&SZ ,h׮Knq7mP?څ3PBK2}G6IjwMF:,`*Lъ<-r$PjZaY4l/,y&q-[$e]u߾}'ABWՂgyL&%1/H}0 3wSJ;Fc~1{NĿ?\ꂠ8\"`}H`5%zf40>-|ڊyJw-<˖-1}tt ؿ?q7ni#)}ӡd:җ؁hn)U8D_Nҗ"z@vM$Y/ kg߲CC0[mğev= Lg!Kĩ֮#_<*JzPp. ˌA"ө)(5K@0Mm?_@~}'v U8k ~Z(tn@Pu/71fM |_7P>1/fGn, K/)_QWKcAtهK嗰EVG,]0>\!dD6]4}.>_F MX5GfNY {;Ga1 Z*,Rf-Nslff*e0gJ1)#36fKGzܰ W&}9cpNA-[XP&ɹ[u.lNw}M=]gT̚ghSOgϞ`&eؤ) |4xnwH{ n>X'5!ȋQ(0Mз"d]H001\ka/<[`0->BkG8.ТVUo[1㥓l&IUF˾B["^.W".=REIiWiMb6WW/.MDvT~kg ;DY(4(sy#jᓟephn×/?Wx,j[ П|\Ld1q@)2j8ˊ}'`㝑|v ( j:/}Za;,Tw(pDQBU2Z}d.s^_|~j?^4IaA'¯vW>TaS I) ֖4$^+0ܹ^=NѺs ""]tg:ea3YLN˳g/tZ9llv4AAslnf6L4Ծbf"^}ϱS Y9P{“].ã䞠{'śrx)帬V _cO%U8c\LdҗVHe =S9SnLH'?lm|,:Z( cq8@,o]UW8UKi<+{? f˘0`X.pnPⱹWS8nL8ftv\+­=bcNIU:%qK^L<+B-p8!PiX\)p8U,8G|p_>x)G#PeʲpʇWÍp8U,8G|p_>x)G#PeʲpʇWÍp8U,8G|p_>x)G#PeʲpʇWÍp8U,8G|p_>x)G#PeʲpʇWÍp8U,8G|p_>x)G#PeʲpʇWÍp8U,8G|p_>x)G#Peʲpʇ+Kq8@D@YF*I8'#pʇw7^#TY p8#-cKp8*WU}xG#PvGJ#-*>NP{@)#mq57 B"hC<jE@O>ǧ"ӪC:9ш /1g.%O_V0$t3D& S݆WT`3kA-sprNdlg.Ν8x"g/!Eo.0nUՆ+ZjUW*@\=SXXe(^l0T:2hVquSM(lx:}0^su*i 7 ,I&g-51xk/cx2S&2[qyZHAͩ#ɑz[Pw ~!} _lH2pm0q;W۶q6_1\=D"|+`-'B-09Tyy0 "u Aj>{`ƄpmȭWw1XXZM90t$Q6h@<FsxE(٤mҮ/}|%fg7е7IAvAPz^TTKu8L: ځ,{+NZ*(Vw_Bn+oAxbPSĬɊ-ʋB_zeʠhƕ qB뗐Њ$㲞CzegڪZO$<g_b̛F>-rOG`V'%|<|࡮x y-U rYѦfdLYǾy8dAZ>\ IfEnA$_Nͳ/[liQyNxvyC;S[>SXm1dqd4v:mS`- ܈6tAx5nCfy9A7Nnʭ kja&5Rnhۼ6^6䦜ǁh3|zc՘W)0;BHwb9bj4 cuɰhjt/nF蓮!mHPHs`"nfVbl8l#ߠ@ {/|3cGw|g,h42G`Ӯ|l7aCwa\]T߉ 7"9=$FNm:6ݒ!c)v5.gBgNϧV㔃+Pw yF+D_ҝ EzqLhIf/@1[Ix}!⃺uB?m"A VD{lŔycۡtxb]?ca6JZIbvby-z==\dryW)ih__:(\JNESOgL"VtjڹkuImvHtUBe_h^&*oM6hGN>g WCaBU|A _ I+,N,ɉ~ʕF)2\ju~]8kGP^AwԈ9ʇum %O6B\ti-%IT2ꃊr*Cm& o^ f2f쒘pF6r%߾tzfdQ OQ2 hZKwV&v@taa iZV~ jOadtNC},ŏ4<RdL'Sԥ9s>ǡa,Jm{|˨CLN]3>^| vM.\5|xU wnsI,!Τ-gI<4 nۣ 1f4GOJ~F\VD؜A<)IaR$1tX6{y _?x$ ;6\KC=;!keؖpMhBT1X9]l A&-q4 ž|Yj:/; PÓ͂bdٱILMQjb =)7M7@ >G'5j4abwTm |9٠9!mʻ@ w+ۀVJh-7iĽ>;$ \V&·/>:=C+:joxFjobpH;;x'#%nȋJ$9nYioP.eӠ1Ypr>̦ oH ^Bs@jr)l+kl7QWSg]-u9[ӈՑIU.d+)/'Ъ jFw$@20HV~$˛')^ЫI-l}V z'&h`űbi.2b J+W"lR*d f$He bɔ)D{2E= u yS/,oe@t6Gځ+Fk 4UZ됰{-"ikKpq ώ u9yG; bYR~S&@tmļԀMBHygCju/.Ykس4c|:(>*6mBjڐ&lM4X.mv6\[lS)o"jegGʸ4@|d:tjH.*ъ x=ŷj 4$e%z FN8џEgD׎K( _kҥȩF~JeY.i7!%5O߫cm'lŶN6ܔl$ɊfD9hP3;okJ-RY~uʒ{?$Zܶ;۱yՏ$:ڣK;r;zCbwād >vvQ 6at܆BDȗ*XMTcKVGӪ. >,o;~g&M~)?lFRv_;r1gbK5$_5::EuZsZG)&rЊMn.@gT"T:5,JVC`R]Ehi~ 2߶hk'5!h߆k[&xB4v>EMWBb<iR+UŖ)$K'Ϯ3pSb7\8X0: <;+K#;Yv#^;7҆ZtBZш՘Xj,8(G0S[ gbI T&(dt Vn O t…NAF*Qϓtj#+)e& LdȾSx 2K.Ҳ ]?tj rrjCm#-ϡ{.M9d,de8_7,mf$i3O(lI IɆл 5$PER Cg1~wf )kVzփϥ7csb7?ƳSn>yH̫TShj$R:;o .<Ѫfڌ;^EapiWSGJ6#>|nV7ՄԠpǟxL{.鴡)kK~b$|& r's;% '* ;mAӬ?g~ݒ<|}=p)LW|>}LIRT/M}twI4mP{Ċuo" vZ ,7:t`J!6%) E ge4)ZF,{ MX%Ft8W23- ^ y/pQP2ZSyfRC1.6ꈼ>^l$ཹo9"l$Crr#6R $36iXiEG ╭_cYd;̚=3!k-Nr䲘dF #UəPFPBxKI+\;&{&{eTR%}@Y3rr)|wE1`h׬&RF\C1T~4j%3&lgz dQ4#-ߝYzr/! zjI^p8@+ hWp8:youSp8eA[eAp8nW&.p8 -r8jWՀ G,pWOYy9@5@[Հ G,?V#9}nIENDB`scikit-image-0.9.3/doc/source/gitwash/set_up_fork.txt000066400000000000000000000040621223313777300226770ustar00rootroot00000000000000.. _set-up-fork: ================== Set up your fork ================== First you follow the instructions for :ref:`forking`. Overview ======== :: git clone git@github.com:your-user-name/scikit-image.git cd scikit-image git remote add upstream git://github.com/scikit-image/scikit-image.git In detail ========= Clone your fork --------------- #. Clone your fork to the local computer with ``git clone git@github.com:your-user-name/scikit-image.git`` #. Investigate. Change directory to your new repo: ``cd scikit-image``. Then ``git branch -a`` to show you all branches. You'll get something like:: * master remotes/origin/master This tells you that you are currently on the ``master`` branch, and that you also have a ``remote`` connection to ``origin/master``. What remote repository is ``remote/origin``? Try ``git remote -v`` to see the URLs for the remote. They will point to your github fork. Now you want to connect to the upstream `scikit-image github`_ repository, so you can merge in changes from trunk. .. _linking-to-upstream: Linking your repository to the upstream repo -------------------------------------------- :: cd scikit-image git remote add upstream git://github.com/scikit-image/scikit-image.git ``upstream`` here is just the arbitrary name we're using to refer to the main scikit-image_ repository at `scikit-image github`_. Note that we've used ``git://`` for the URL rather than ``git@``. The ``git://`` URL is read only. This means we that we can't accidentally (or deliberately) write to the upstream repo, and we are only going to use it to merge into our own code. Just for your own satisfaction, show yourself that you now have a new 'remote', with ``git remote -v show``, giving you something like:: upstream git://github.com/scikit-image/scikit-image.git (fetch) upstream git://github.com/scikit-image/scikit-image.git (push) origin git@github.com:your-user-name/scikit-image.git (fetch) origin git@github.com:your-user-name/scikit-image.git (push) .. include:: links.inc scikit-image-0.9.3/doc/source/gitwash/this_project.inc000066400000000000000000000003171223313777300230050ustar00rootroot00000000000000.. scikit-image .. _scikit-image: http://scikit-image.org .. _`scikit-image github`: http://github.com/scikit-image/scikit-image .. _`scikit-image mailing list`: http://groups.google.com/group/scikit-image scikit-image-0.9.3/doc/source/gsoc2011.txt000066400000000000000000000011461223313777300201500ustar00rootroot00000000000000Project ideas for Google Summer of Code 2011 ============================================ - Vastly increase the number of algorithms covered by the SciKit, by implementing several prominent algorithms (probabilistic hough, radon transform, etc.) from papers. Also incorporate code from the Broad Institute's CellProfiler team. - Implement a new backend infrastructure so that the same results may be obtained using either NumPy, OpenCL, Theano, etc. - Implement optimised core routines, such as fast 2D convolution. This should be as fast as CvFilter2D (which is faster than ndimage, for example). scikit-image-0.9.3/doc/source/index.txt000066400000000000000000000023161223313777300200200ustar00rootroot00000000000000**************************** skimage |version| docs **************************** This SciKit_ is an image processing toolbox for SciPy_. .. _SciKit: http://scikits.appspot.com .. _SciPy: http://www.scipy.org Sections ======== .. toctree:: :hidden: overview api api_changes install user_guide contribute license auto_examples/index .. list-table:: :class: contentstable * - `Overview `_ Introduction to skimage. - `API Reference `_ (`changes `_) Documentation for the functions included in skimage. * - `Installation Steps `_ How to install skimage. - `User Guide `_ Usage guidelines. * - `Contribute `_ Take part in development. - `License Info `_ Conditions on the use and redistribution of this package. * - `Examples `_ Introductory examples - Indices and Tables ================== `Table of Contents `_ Lists all sections and subsections. :ref:`search` Search this documentation. :ref:`genindex` All functions, classes, terms. scikit-image-0.9.3/doc/source/install.txt000066400000000000000000000051071223313777300203600ustar00rootroot00000000000000Pre-built installation ---------------------- `Windows binaries `__ are kindly provided by Christoph Gohlke. The latest stable release is also included as part of the `Enthought Python Distribution (EPD) `__, `Python(x,y) `__ and `Anaconda `__. On Debian and Ubuntu, a Debian package ``python-skimage`` can be found in `the Neurodebian repository `__. Follow `the instructions `__ to add Neurodebian to your system package manager, then look for ``python-skimage`` in the package manager. On systems that support setuptools, the package can be installed from the `Python packaging index `__ using :: easy_install -U scikit-image or :: pip install -U scikit-image Installation from source ------------------------ Obtain the source from the git-repository at `http://github.com/scikit-image/scikit-image `_ by running:: git clone http://github.com/scikit-image/scikit-image.git in a terminal (you will need to have git installed on your machine). If you do not have git installed, you can also download a zipball from `https://github.com/scikit-image/scikit-image/zipball/master `_. The SciKit can be installed globally using:: python setup.py install or locally using:: python setup.py install --prefix=${HOME} If you prefer, you can use it without installing, by simply adding this path to your ``PYTHONPATH`` variable and compiling extensions in-place:: python setup.py build_ext -i Building with bento ------------------- ``scikit-image`` can also be built using `bento `__. Bento depends on `WAF `__ for compilation. Follow the `Bento installation instructions `__ and `download the WAF source `__. Tell Bento where to find WAF by setting the ``WAFDIR`` environment variable:: export WAFDIR= From the ``scikit-image`` source directory:: bentomaker configure bentomaker build -j # (add -i for in-place build) bentomaker install # (when not builing in-place) Depending on file permissions, the install commands may need to be run as sudo. .. include:: ../../DEPENDS.txt scikit-image-0.9.3/doc/source/license.txt000066400000000000000000000000671223313777300203340ustar00rootroot00000000000000License ======= .. literalinclude:: ../../LICENSE.txt scikit-image-0.9.3/doc/source/overview.txt000066400000000000000000000013541223313777300205600ustar00rootroot00000000000000Image Processing SciKit ======================= The `scikit-image `__ SciKit (toolkit for `SciPy `__) extends ``scipy.ndimage`` to provide a versatile set of image processing routines. It is written in the `Python `_ language. This `SciKit `_ is developed by the SciPy community. All contributions are most welcome! Please join us on the mailing list (address provided below). Homepage -------- http://scikit-image.org Source, bugs and patches ------------------------ http://github.com/scikit-image/scikit-image Mailing List ------------ http://groups.google.com/group/scikit-image Contact ------- Stefan van der Walt scikit-image-0.9.3/doc/source/plots/000077500000000000000000000000001223313777300173075ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/plots/hough_tf.py000066400000000000000000000013041223313777300214620ustar00rootroot00000000000000import numpy as np import matplotlib.pyplot as plt from skimage.transform import hough_line from skimage.draw import line img = np.zeros((100, 150), dtype=bool) img[30, :] = 1 img[:, 65] = 1 img[35:45, 35:50] = 1 rr, cc = line(60, 130, 80, 10) img[rr, cc] = 1 img += np.random.random(img.shape) > 0.95 out, angles, d = hough_line(img) plt.subplot(1, 2, 1) plt.imshow(img, cmap=plt.cm.gray) plt.title('Input image') plt.subplot(1, 2, 2) plt.imshow(out, cmap=plt.cm.bone, extent=(np.rad2deg(angles[-1]), np.rad2deg(angles[0]), d[-1], d[0])) plt.title('Hough transform') plt.xlabel('Angle (degree)') plt.ylabel('Distance (pixel)') plt.subplots_adjust(wspace=0.4) plt.show() scikit-image-0.9.3/doc/source/plots/show_collection.py000066400000000000000000000011711223313777300230540ustar00rootroot00000000000000import os import matplotlib.pyplot as plt from mpl_toolkits.axes_grid import AxesGrid from skimage.io import MultiImage from skimage import data_dir # Load the multi-layer image fname = os.path.join(data_dir, 'multipage.tif') img = MultiImage(fname) # Create an image grid fig = plt.figure() grid = AxesGrid(fig, rect=(1, 1, 1), nrows_ncols=(1, 2), axes_pad=0.1) # Plot the layers on the image grid for i, frame in enumerate(img): grid[i].imshow(frame, cmap=plt.cm.gray) grid[i].set_xlabel('Frame %s' % i) grid[i].set_xticks([]) grid[i].set_yticks([]) plt.show() scikit-image-0.9.3/doc/source/random_gallery.py000066400000000000000000000024601223313777300215210ustar00rootroot00000000000000# Generate a javascript snippet that links to a random gallery example import os import glob base = os.path.abspath(os.path.dirname(__file__)) example_dir = os.path.join(base, 'auto_examples') js_fn = os.path.join(base, '_static/random.js') javascript = '''\ function insert_gallery() { var images = {{IMAGES}}; var links = {{LINKS}}; ix = Math.floor(Math.random() * images.length); document.write( '{{GALLERY_DIV}}'.replace('IMG', images[ix]).replace('URL', links[ix]) ); console.log('{{GALLERY_DIV}}'.replace('IMG', images[ix]).replace('URL', links[ix])); }; ''' gallery_div = '''\

    \ ''' examples = glob.glob(os.path.join(example_dir, 'plot_*.py')) images, links = [], [] image_url = 'http://scikit-image.org/docs/dev/_images/%s.png' link_url = 'http://scikit-image.org/docs/dev/auto_examples/%s.html' for e in examples: e = os.path.basename(e) e = e[:-len('.py')] images.append(image_url % e) links.append(link_url % e) javascript = javascript.replace('{{IMAGES}}', str(images)) javascript = javascript.replace('{{LINKS}}', str(links)) javascript = javascript.replace('{{GALLERY_DIV}}', ''.join(gallery_div.split('\n'))) f = open(js_fn, 'w') f.write(javascript) f.close() scikit-image-0.9.3/doc/source/themes/000077500000000000000000000000001223313777300174335ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/themes/scikit-image/000077500000000000000000000000001223313777300220015ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/themes/scikit-image/layout.html000066400000000000000000000103741223313777300242110ustar00rootroot00000000000000{# scikit-image/layout.html ~~~~~~~~~~~~~~~~~ Sphinx layout template for the scikit-image theme, written by Johannes Schönberger. #} {%- set url_root = pathto('', 1) %} {# XXX necessary? #} {%- if url_root == '#' %}{% set url_root = '' %}{% endif %} {%- if not embedded and docstitle %} {%- set titlesuffix = " — "|safe + docstitle|e %} {%- else %} {%- set titlesuffix = "" %} {%- endif %} {%- macro script() %} {%- for scriptfile in script_files %} {%- endfor %} {%- endmacro %} {%- macro css() %} {%- for cssfile in css_files %} {%- endfor %} {%- endmacro %} {%- block htmltitle %} {{ title|striptags|e }}{{ titlesuffix }} {%- endblock %} {{ metatags }} {{ css() }} {{ script() }} {%- if hasdoc('about') %} {%- endif %} {%- if hasdoc('genindex') %} {%- endif %} {%- if hasdoc('search') %} {%- endif %} {%- if hasdoc('copyright') %} {%- endif %} {%- if parents %} {%- endif %} {%- if next %} {%- endif %} {%- if prev %} {%- endif %} {%- block extrahead %}{% endblock %}
    {% block body %}{% endblock %}
    {%- for sidebartemplate in sidebars %} {%- include sidebartemplate %} {%- endfor %}
    scikit-image-0.9.3/doc/source/themes/scikit-image/search.html000066400000000000000000000026601223313777300241400ustar00rootroot00000000000000{# basic/search.html ~~~~~~~~~~~~~~~~~ Template for the search page. :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {% extends "layout.html" %} {% set title = _('Search') %} {% set script_files = script_files + ['_static/searchtools.js'] %} {% set script_files = script_files + ['searchindex.js'] %} {% block body %}

    {{ _('Search') }}

    {% trans %}Please activate JavaScript to enable the search functionality.{% endtrans %}

    {% trans %}From here you can search these documents. Enter your search words into the box in the navigation bar and press "Enter". Note that the search function will automatically search for all of the words. Pages containing fewer words won't appear in the result list.{% endtrans %}

    {% if search_performed %} {% if not search_results %}

    {{ _('Your search did not match any results.') }}

    {% endif %} {% endif %}
    {% if search_results %}
      {% for href, caption, context in search_results %}
    • {{ caption }}
    • {% endfor %}
    {% endif %}
    {% endblock %} scikit-image-0.9.3/doc/source/themes/scikit-image/static/000077500000000000000000000000001223313777300232705ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/themes/scikit-image/static/css/000077500000000000000000000000001223313777300240605ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/themes/scikit-image/static/css/bootstrap-responsive.min.css000066400000000000000000000371321223313777300315720ustar00rootroot00000000000000/*! * Bootstrap Responsive v2.1.1 * * Copyright 2012 Twitter, Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world @twitter by @mdo and @fat. */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade.in{top:auto}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:hover{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:block;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} scikit-image-0.9.3/doc/source/themes/scikit-image/static/css/bootstrap.min.css000066400000000000000000002775651223313777300274170ustar00rootroot00000000000000/*! * Bootstrap v2.1.1 * * Copyright 2012 Twitter, Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world @twitter by @mdo and @fat. */article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}.text-warning{color:#c09853}.text-error{color:#b94a48}.text-info{color:#3a87ad}.text-success{color:#468847}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:1;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1{font-size:36px;line-height:40px}h2{font-size:30px;line-height:40px}h3{font-size:24px;line-height:40px}h4{font-size:18px;line-height:20px}h5{font-size:14px;line-height:20px}h6{font-size:12px;line-height:20px}h1 small{font-size:24px}h2 small{font-size:18px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:25px}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:9px;font-size:14px;line-height:20px;color:#555;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal;cursor:pointer}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:18px;padding-left:18px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"]{float:left}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning>label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error>label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success>label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info>label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{margin-bottom:5px;font-size:0;white-space:nowrap}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;font-size:14px;vertical-align:top;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-append .add-on,.input-append .btn{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child,.table-bordered tfoot:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child,.table-bordered tfoot:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topleft:4px}.table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9}.table-hover tbody tr:hover td,.table-hover tbody tr:hover th{background-color:#f5f5f5}table [class*=span],.row-fluid table [class*=span]{display:table-cell;float:none;margin-left:0}.table .span1{float:none;width:44px;margin-left:0}.table .span2{float:none;width:124px;margin-left:0}.table .span3{float:none;width:204px;margin-left:0}.table .span4{float:none;width:284px;margin-left:0}.table .span5{float:none;width:364px;margin-left:0}.table .span6{float:none;width:444px;margin-left:0}.table .span7{float:none;width:524px;margin-left:0}.table .span8{float:none;width:604px;margin-left:0}.table .span9{float:none;width:684px;margin-left:0}.table .span10{float:none;width:764px;margin-left:0}.table .span11{float:none;width:844px;margin-left:0}.table .span12{float:none;width:924px;margin-left:0}.table .span13{float:none;width:1004px;margin-left:0}.table .span14{float:none;width:1084px;margin-left:0}.table .span15{float:none;width:1164px;margin-left:0}.table .span16{float:none;width:1244px;margin-left:0}.table .span17{float:none;width:1324px;margin-left:0}.table .span18{float:none;width:1404px;margin-left:0}.table .span19{float:none;width:1484px;margin-left:0}.table .span20{float:none;width:1564px;margin-left:0}.table .span21{float:none;width:1644px;margin-left:0}.table .span22{float:none;width:1724px;margin-left:0}.table .span23{float:none;width:1804px;margin-left:0}.table .span24{float:none;width:1884px;margin-left:0}.table tbody tr.success td{background-color:#dff0d8}.table tbody tr.error td{background-color:#f2dede}.table tbody tr.warning td{background-color:#fcf8e3}.table tbody tr.info td{background-color:#d9edf7}.table-hover tbody tr.success:hover td{background-color:#d0e9c6}.table-hover tbody tr.error:hover td{background-color:#ebcccc}.table-hover tbody tr.warning:hover td{background-color:#faf2cc}.table-hover tbody tr.info:hover td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-tabs>.active>a>[class^="icon-"],.nav-tabs>.active>a>[class*=" icon-"],.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a{color:#fff;text-decoration:none;background-color:#08c;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#fff;text-decoration:none;background-color:#08c;background-color:#0081c2;background-image:linear-gradient(to bottom,#08c,#0077b3);background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .disabled>a,.dropdown-menu .disabled>a:hover{color:#999}.dropdown-menu .disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 14px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;*line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #bbb;*border:0;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-bottom-color:#a2a2a2;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover{color:#333;text-decoration:none;background-color:#e6e6e6;*background-color:#d9d9d9;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-color:#e6e6e6;background-color:#d9d9d9 \9;background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-color:#e6e6e6;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:9px 14px;font-size:16px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.btn-large [class^="icon-"]{margin-top:2px}.btn-small{padding:3px 9px;font-size:12px;line-height:18px}.btn-small [class^="icon-"]{margin-top:0}.btn-mini{padding:2px 6px;font-size:11px;line-height:17px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn{border-color:#c5c5c5;border-color:rgba(0,0,0,0.15) rgba(0,0,0,0.15) rgba(0,0,0,0.25)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-image:-moz-linear-gradient(top,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-image:-moz-linear-gradient(top,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-image:-moz-linear-gradient(top,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover{color:#333;text-decoration:none}.btn-group{position:relative;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar .btn-group{display:inline-block;*display:inline;*zoom:1}.btn-toolbar .btn+.btn,.btn-toolbar .btn-group+.btn,.btn-toolbar .btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu{font-size:14px}.btn-group>.btn-mini{font-size:11px}.btn-group>.btn-small{font-size:12px}.btn-group>.btn-large{font-size:16px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-mini .caret,.btn-small .caret,.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.dropup .btn-large .caret{border-top:0;border-bottom:5px solid #000}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical .btn{display:block;float:none;width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical .btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical .btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical .btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical .btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical .btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;color:#c09853;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible;color:#777}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px}.navbar-link{color:#777}.navbar-link:hover{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:6px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;width:100%;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.1),0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.1),0 1px 10px rgba(0,0,0,0.1);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.1),0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:inset 0 1px 0 rgba(0,0,0,0.1),0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 0 rgba(0,0,0,0.1),0 -1px 10px rgba(0,0,0,0.1);box-shadow:inset 0 1px 0 rgba(0,0,0,0.1),0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse{color:#999}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover{color:#fff}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-image:-moz-linear-gradient(top,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb .divider{padding:0 5px;color:#ccc}.breadcrumb .active{color:#999}.pagination{height:40px;margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:0 14px;line-height:38px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager a,.pager span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager a:hover{text-decoration:none;background-color:#f5f5f5}.pager .next a,.pager .next span{float:right}.pager .previous a{float:left}.pager .disabled a,.pager .disabled a:hover,.pager .disabled span{color:#999;cursor:default;background-color:#fff}.modal-open .modal .dropdown-menu{z-index:2050}.modal-open .modal .dropdown.open{*z-index:2050}.modal-open .modal .popover{z-index:2060}.modal-open .modal .tooltip{z-index:2080}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:50%;left:50%;z-index:1050;width:560px;margin:-250px 0 0 -280px;overflow:auto;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:50%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.tooltip{position:absolute;z-index:1030;display:block;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{margin-top:-3px}.tooltip.right{margin-left:3px}.tooltip.bottom{margin-top:3px}.tooltip.left{margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;width:236px;padding:1px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-bottom:10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-right:10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0}.popover .arrow,.popover .arrow:after{position:absolute;display:inline-block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow:after{z-index:-1;content:""}.popover.top .arrow{bottom:-10px;left:50%;margin-left:-10px;border-top-color:#fff;border-width:10px 10px 0}.popover.top .arrow:after{bottom:-1px;left:-11px;border-top-color:rgba(0,0,0,0.25);border-width:11px 11px 0}.popover.right .arrow{top:50%;left:-10px;margin-top:-10px;border-right-color:#fff;border-width:10px 10px 10px 0}.popover.right .arrow:after{bottom:-11px;left:-1px;border-right-color:rgba(0,0,0,0.25);border-width:11px 11px 11px 0}.popover.bottom .arrow{top:-10px;left:50%;margin-left:-10px;border-bottom-color:#fff;border-width:0 10px 10px}.popover.bottom .arrow:after{top:-1px;left:-11px;border-bottom-color:rgba(0,0,0,0.25);border-width:0 11px 11px}.popover.left .arrow{top:50%;right:-10px;margin-top:-10px;border-left-color:#fff;border-width:10px 0 10px 10px}.popover.left .arrow:after{right:-1px;bottom:-11px;border-left-color:rgba(0,0,0,0.25);border-width:11px 0 11px 11px}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.label,.badge{font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{padding:1px 4px 2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding:1px 9px 2px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}a.label:hover,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel .item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel .item>img{display:block;line-height:1}.carousel .active,.carousel .next,.carousel .prev{display:block}.carousel .active{left:0}.carousel .next,.carousel .prev{position:absolute;top:0;width:100%}.carousel .next{left:100%}.carousel .prev{left:-100%}.carousel .next.left,.carousel .prev.right{left:0}.carousel .active.left{left:-100%}.carousel .active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit p{font-size:18px;font-weight:200;line-height:30px;color:inherit}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed} scikit-image-0.9.3/doc/source/themes/scikit-image/static/css/custom.css000066400000000000000000000070551223313777300261130ustar00rootroot00000000000000body { font-family: "Raleway"; } a { color: #CE5C00; } input, button, select, textarea { font-family: "Raleway"; } pre { font-size: 11px; } h1, h2, h3, h4, h5, h6 { clear: left; } h1 { font-size: 30px; line-height: 36px; } h2 { font-size: 24px; line-height: 30px; } h3 { font-size: 19px; line-height: 21px; } h4 { font-size: 17px; line-height: 19px; } h5 { font-size: 15px; line-height: 17px; } h6 { font-size: 13px; line-height: 15px; } blockquote { border-left: 0; } dt { font-weight: normal; } .logo { float: left; margin: 20px 0 20px 22px; } .logo img { height: 70px; } .hero { padding: 10px 25px; } .gallery-random { float: right; line-height: 180px; } .gallery-random img { max-height: 180px; } .coins-sample { padding: 5px; } .sidebar-box { padding: 0; } .sidebar-box-heading { padding-left: 15px; } #current { font-weight: bold; } .headerlink { margin-left: 10px; color: #ddd; display: none; } h1:hover .headerlink, h2:hover .headerlink, h3:hover .headerlink, h4:hover .headerlink, h5:hover .headerlink, h6:hover .headerlink { display: inline; } .headerlink:hover { color: #CE5C00; text-decoration: none; } .footer { margin-top: 30px; padding: 5px 10px; color: #999; } .footer a { color: #999; text-decoration: underline; } .ohloh-use, .gplus-use { float: left; margin: 0 0 10px 15px; } /* Documentation */ /* general table settings */ table.docutils { margin-bottom: 10px; border-color: #ccc; } table.docutils td, table.docutils th { padding: 5px; border-color: #ccc; text-align: left; } .toc ul ul { font-size: 13px; margin-right: -15px; } /* master content table */ .contentstable.docutils, .contentstable.docutils td { border-color: transparent; } .contentstable.docutils .first { font-weight: bold; } .contentstable.docutils .last { padding-left: 10px; } .docutils .label, .docutils .badge { background: transparent; text-shadow: none; font-size: 13px; padding: 5px; line-height: 20px; color: #333; } /* module summary table */ .longtable.docutils { font-size: 12px; margin-bottom: 30px; } .longtable.docutils, .longtable.docutils td { border-color: #ccc; } /* function and class description */ dl.class, dl.function, dl.method, dl.attribute { border-top: 1px solid #ccc; padding-top: 10px; } .descclassname { color: #aaa; font-weight: normal; font-family: monospace; } .descname { font-family: monospace; } dl.class em, dl.function em, dl.class big, dl.function big { font-weight: normal; font-family: monospace; } dl.class dd, dl.function dd { padding: 10px; } .docutils.field-list th { background-color: #eee; padding: 10px; text-align: left; vertical-align: top; width: 100px; } .docutils.field-list td { padding: 10px 10px 10px 20px; text-align: left; vertical-align: top; } .docutils.field-list td blockquote p { font-size: 13px; line-height: 18px; } p.rubric { font-weight: bold; font-size: 19px; margin: 15px 0 10px 0; } p.admonition-title { font-weight: bold; text-decoration: underline; } /* example gallery */ .gallery { height: 200px; } .figure { float: left; margin: 1em; } .figure img { display: block; margin-left: auto; margin-right: auto; max-height: 150px; max-width: 200px; } .figure .caption { width: 200px; text-align: center !important; } /* misc */ div.math { text-align: center; } scikit-image-0.9.3/doc/source/themes/scikit-image/static/img/000077500000000000000000000000001223313777300240445ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/themes/scikit-image/static/img/favicon.ico000066400000000000000000000236261223313777300261760ustar00rootroot00000000000000(f 00hvh F00( gltσ.חPۡa{弎Ù̩ԷTV A8qB^ 0ڒ `| N@r0G0 0*1 @Z\x?z@|A~BBCDEEGGGHJKLMNOPPPQRRKHSA$MQFxARTE(SW Q/ p@ U QN\]^W8`ef~R#f&|T'hJ(uP(_G-Z-kN.qQ.p.q/u;i<f=dEoFsFGs_HInKPzgTTTTpUvUmXnX}lYYZ]r`aajsÝsuzɤ|ΩЯˮϰӳϱӵոƶϻ¨ƫ˽ɯɳ̴̵̷η˸Ϲͺѽѽɿʿpclv_;/000U~>.05]eG0,k(,0EV-)mI1?0x8(!y9F21KB&X[&aJ22<|7"AN '*+dM%PCsW3#D:Zq4$#!oTz {\YtH `LRg @ wr i=SfOh^6Q}nbju( @?!A#E$I&M(P*S,V-Z/]0a3c4e5h6j8m9q;r<u=x?z@|ABCDEFGHIJJKLLMNNPQRRRSST~BSTLA#E&OQV0G)WQ K [ ^K1\9N[T5S`zJcP5Z^`eQUfE Y c!W@%]&]D'l'o+^F,j,q,n-q-~Y2\2m5s5`6dO7w7pV8q;{=jU>z?uB}BBr\DlDgEkEF{bGpGhHvHIqMtN}gOPyfQRSrTTVoWXv[’\q^`“`bŖb•cƘegkllśmpɟqƞrsɢwz{ʤ{|~̩ѬʬԳѱֶĮϴ˳ѷ׻ۿȶ׾پмæν·Ź¹Ļļʿ³dzʴȶ̶йҾ{]XXXe{@&&&&''''&S{5&&&'''())))('IH%&''(()))**+**)'&m9$&')*));xY+++)'%V1#&'*,,+`;,*'&"V %&),-,Wǎ0*'&#vI'+--;;)))hr)'&"fc,--<))))))'%!QqGEY+*****T/&% ?4,,,++**Y/&"o!&cه--,,,+*)&$ D$&8SE---,,,+*|g%!j!%')*++++J`&#  [!%&''Cy%#! Z !#%gձ]&$#! k Oe@%$#"! B.   !!!! b~s  :\fp>> LBNKtn DN: ۺ} D 6>ain lo^ A u3zU7Mz>RFiw2Fw=Pw_UUUd? @0  0 @?(0`> A"F$I&M(Q*S+U,X.]0a2c4e5h7m9p;r<u=x?z@|ABCDEGHIJJKLLMNOPQRRRST}BOTMQKSVTYY3 o> V2 sB L Z R V E* I, P Y]N2WZ`MYaU7_=qHW_cQ[dAX_AgY"V>#{Q#g#k#iH$h%W&b&\C(m)X,q,i-p-b2eM3u4m5s5nU9`=d=v\>|>zAmXBDt^FyFFmGiIIKsLyNPyQ~jSlSUVpYxYwZ[\\^aĕbef—hȚh|iilĚmǝqrtt̢txʤy{ΫƧҮũԲϰūԴ׸˴ѷٺֽæĨνŪĹŮƮȮ̿Ļó˳̵˶ζƸϹɺͺƼҼ޳sX<,##,@[v[####$$$$$$$$$#_s@##$$$$%%%%%%%%%%%%Aw<"#$%%%%%%%&''''''''&&&@b "#$%%%%%&&'''(((()(((('%$hG "#%%&'''''''2ENA)))))))('%$M; "#%%'((((''NǨz:)))))'%$#<;!#%%')))))(m))))(&$#!CP #$%')***))z)))(&%#!P.!#%')****)܈cTff))(&%#!rN$%()****aE&''''_2)(&%#!٭s')****AH''''''(cw)'%$#!R4****f(''''''(()'%$# LbY**))((((((()m('%#" UDތ)))))))))))a'%$#!y!/~E*))))))))))p&%#" {F!#%_Y***)))))))((%$#!\ #$'24*****))))))(fm$#!6!$%()*********)))))-w%$"   #$&()******))))-cX$#! t!#%&')))))))Y[%#"  k !#$%&'''YЃ@$#"! k !##$%3޶c1###"! u  !",h<$####"!   nh#####""!! ?L  ; !!!!!! Pѽ8x  bMg 5J 0]Zu 9yO{} d`J +{ Klq| dOd 5QQIS 6O8 I} t8OW i ։`Wdx qI I>jB>QƲu5>B7J7I^e=>q=>qVVݰoV==Vq8? 0`a3  88xǃ `09?scikit-image-0.9.3/doc/source/themes/scikit-image/static/img/glyphicons-halflings-white.png000066400000000000000000000211111223313777300320100ustar00rootroot00000000000000PNG  IHDRӳ{PLTEmmmⰰᒒttt󻻻bbbeeeggg𶶶xxx󛛛Ƽ몪֢UUU鿿rOtRNS#_ /oS?C kDOS_6>4!~a @1_'onҋM3BQjp&%!l"Xqr; A[<`am}43/0IPCM!6(*gK&YQGDP,`{VP-x)h7e1]W$1bzSܕcO]U;Zi'y"؆K 64Y*.v@c.};tN%DI !ZЏ5LH26 ɯ" -bE,,)ʏ B>mn6pmRO wm@V#?'CȑZ#qb|$:)/E%nRqChn%i̓}lm ?idd",`H"r.z~(bQU&)5X#EMR<*p[[%.Ọk7lIoJF lV!̡ăuH`&,zRk$|$lXbjߪdU?Σ$HW$U'HE3*խU\}( zhVk}guRk$%|T|ck獳"D_W+.Q)@ƽHbslTDR2Xm#a 3lYzj㒚#! 4J8(cvt]aT D ΅Q?^-_^$:\V $N|=(vZ'q6Z׆B5V!y3K㱿bv4xR]al!IoP@tVyL٪mlڿIUb|[*lke'*WddDӝ}\W_WߝrN?vޫ۲X%0uoui*JVƦb%}i5IYlNE-wςf_W3mI-mQ)S kTC7m<"܌bT|'$ҘR&>O p6tSN\ׯLm\r@3uT b7t.5.q3r0=8TiJ\6uF R32^'ŪxI F8O{%8kJMSȴdBEdWCYO:/ON/I_=xFE! =i:o~ y?''[͓[͓[͓[͓[ͭ.U>$PƦc%]\c:| ,eSZ,oXrX!R@Zv 0>?* <|N60;{ad2v+D^t[q!۞V}fۨϏYeॗ)Vyl|" fUq@Ǽ4Y-Y-!6aB:o%JIUQ|UKO`=\ :0x Pau@!KPdxhw1>$j΍vZdxSUA&[URd7øzk/rU^w:I.VǮc>q.!zSr&2)Wg R -iQ 8Pa\ОU%iݡU_=p Lu(N?0?Æ:]άtB%U|NsorNf ,P !v" Y6hL_@@bscqgv4||0lϟ$S9bʱj#~?o}}7sAPm:IV=n !{{hEࢪ8suoLT$;VscqD3 ༂3.DBB4&V' T `D6Ϸqyj8V*X%@s\jrN$|=5Ά 'mUiKi%CI:ssaƅ`*`=l)>u՘MeuSI_OL_}o&jzp{lu:O)s%Q@$<]f xO%PCbhr2PKpf5Në3^o]eJiB464^tuٲU֌:G4'22YpuG'/Py4?.SBP_>I 1t3ΓBɭɭɭɭVVVVVs]!67(g y@ 4>Q VF}^Xׇڼje26 L%YGh lC})< !EEPZWZV+@†R 5{@ouɐ4&H6ey V݀VťcqZޒrJyByFzFN$Hb*+jՏqэ ګkݿUXle1d0d^-B%} {Y%r*j5Ak5u",:~ҸY~ hSA~6 fulՇf{ȵQtATHZkƭ/_Sn u']b]|m`BāJ,O$du]Zs FL:aǙT4o~by?wpj滥A(x]†f~an֧/^dڲcՇ,!1i&xi_VK@ip̓9Vi%a; L?0J*Ū5U'x^6V[^ {eU|:0=0d۫o*Jq%[YN.sQLud[29I:WnmXlڃ6!lNlVէKUjV\J%UߊBLcKfb>a=b~R]aG%[js@/9MطݘU>yɲX@} Ftg^vO\Ӹwvpz3K5i!$P>ā'VƛL2r@UMKZ6tw맟¦bm1h||]}~0MjA(JJP68C&yr׉e}j_cJ?I0k>šW |Bޝ."TEXd 8!cw*E(J)![W"j_ТeX_XB;oO0~?:PC (.[!Wq%*leY)E<^KZT60.#A\5;Rmtkd/8)5~^0 #Ckgey)ͶԺ6ĥ<(?&uAVm0^h.txR*a':,H|ō l5z;8+e#b'#|}2w(|KcJ l6 w^Տoi3H R ̔9,YgPְ:N [5SR![)]i}`mN4Хv`|;f(FltL8÷Z#AO%Y)NU5YedJE3dZذݣHT1 ;8MjnʏӤqp 1h^<<>yt{?|'j)}YUU{@V/J1F+7䀉[OWO[ yUY!?BD%DWj>-Ai6xz)U R7 d@g\so)a4zf[W+> P> |qLG8vȣlj2Zt+VA6gT *ʆUz(m)CD `He/.:zN9pgo &NC׃އ>Wհ_Hj)Xe6F7pm-`'c.AZ=^e8F;{Rtn(z!S7o Iew3]bܗ85|iϠRJkʱZRO+8U&:]ZieR(JMޗ7Z@5a^\GzsρU*rMezT^:ɬͦX=>$ bi>U&XQoybbGk8 Ҙn).Սo ^MmdZi$soo*{4eLbLٳ""mx:`:mk[geTެ)'0*TB{!I ''''[͓[͓[͓[͓[]Zj Q.e '/yvQ71(Z&X?(_Z){tڀmZWϏ)-C jqn,̋"IvUL!h꛿skAcrN佚фVE40yX~4zʸV㳰%,)fqtpu~  *^0:ܲ33JO(ZB?K^ v]unlWi0p6[착C_5X#[wX3b廫R{NKAe Se|wxso>P\儔ԕ6;nVmfI$V͓J-J%֌0UwYЎSnum藮xz˗VƫIvnW_qLZ"_Xz 8]Ap?C543zw({7e*Ȳ`۰!AQ:KUnz]1yVGaCm0PY ٚUx6TT&hV9V ӬzÑ 1[XzZ9erqJND/gX*9oN6D` {I%Mz9—TQ7f\"j_3~xB'ܷY]*KЌ%"5"qxq~ƕ=jS>jV&~]2xzF1X_yD<#NRB}K/iy !V^˿eJ}/FkA7 S+.(ecJ:zWZ몖wQ~ä́p6,e5,+,tv%O^OO}ן -O7>ekC6wa_C |9*WA)UJg8=:mjUvqysܒLglC6+[FSWg9wV31A ND<$5e(s[ ۨbaF.]KIENDB`scikit-image-0.9.3/doc/source/themes/scikit-image/static/img/glyphicons-halflings.png000066400000000000000000000307771223313777300307140ustar00rootroot00000000000000PNG  IHDRtEXtSoftwareAdobe ImageReadyqe<1IDATx}ml\EW^ɺD$|nw';vю8m0kQSnSV;1KGsԩ>UoTU1cƖYuּca&#C,pؚ>kں ULW -sn3Vq~NocI~L{- H8%_M£wB6EW,ĢpY2+(Y@&A/3kXhߍ-aA<>P'\J;(}#Qz:4%m?nfntK*l9J+DIYu1YZ^(]YYEf@ОlXz]Ut u &5-PW}@t|#LY=s܂,w#+R+?Ƌax X0"ea)tG*ԡwVwV^rf%xB(qּ4>WG#lWU<ЁXJVѶlR$kDVrI7:X%X1NEzw;y9z9O%~~uɗ*=Ixcy}Y(ou ±N$^j e\iX񝜬];Y-rѲ&>!zlYaVHVN԰9=]=mRMdOUC JUiT}rWW'ڹu)ʢF"YU#P׾&ܑЅROwyzm$Os? +^FTIEq%&~ >M}]ԖwA? [Nteexn(措BdMTpʥnqqS?bWXmW6x*{V_!VjΧsVL^j XkQjU6sk̩n~[qǸ-` O:G7l"ksRe2vQ=QƼJUX`gQy~ ďKȰE]#P:td\T/u;س:Jc-%'e q ?j"/yh48Zi1|JUu>_N;hxwNU JQU7\j̮bT:B?6oJ1Ί%I UY-Ii4{=rǤ7@)HKJ+f4X8Cd?'j1 N< 39EWo VTGzg# %D0#ܠ3[tiآ( U,]125|Ṋfw7w u+Š]Db]K xbW ՛7|ВX㕛{UcGXk¬|(h)IUa)lp 3luPU]D)/7~4Wt5J}V X0z VM;>Gԙ^|gF:jaZ^)74C#jwr,еSlGu;1vm><)}ZQՖ&mZ:1UMB~ a:/᜗:KWWOҠ&Y2f7cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘g*3fF5LbN2#Tf=C`!ZGUe꣇e2V<1mkS4iϗ*.{N8Xaj~ڀnAx,%fE:|YDVj ¢lg6(:k~MM5?4 ]WO>诋WZiG|QGJeK[YcյpmjE\f/ǎ8&OQ3 .3tt2'-V8pXSrY#J!Q ",ub@FK:u^iy[]<.Cw+W\)b kr-.MtڀMqʄ۰#$^X$"V`T4m~w%Pp1|+&UxY8*r8:k7QЃҀT$Ўƙ S>~Sjs:5q.w&_Z.X=:ވbw` _kd{'0:ds#qi!224nq\9-KUTsSUuVo@;Uz>^=Np>oPO @I@'Gj5o*U>^*ew>ͫʧ᫠Q5 ̈́<$#5Jٻj6e)_ d]2B:^(*:8JYS鬆Kݗ ]U4_rj{5ׇaǑ/yV?GtGb@xPU7O3|鍪 IQ5QGw *(;wf0*PUU<YƔvbt5{2!,}Ҧ:)j2OkΪ' ֊0I.q\(%ojQĖՇa<ԍexAgt'[d;׸`rcdjPFU$UeJI6T&Z}z(z vfuz {}ۿߝݞlxUZ謊.Y岟b%nw@ǩS9|źs%>_o#9\EU~/ځt(r[QZuOo;!MrU]0TcpDő?.cPuF;L_Sb}R/J_+h2$ai UǩS9>Є}76rzu~国4oĨ 1J ^̘~iC޸55G׹]gwsn zTuO=?/zƲc>Οb#7ֻcgkޛTUj*-T=]uu}>ݨNЭ [ ]:%/_ Sz]6D.mD7Uƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1c>J4hPP+A;'G_XKmL5I.},wFFum$S-E-;Õ C3I-`BRx1ғTJݕ;hΊ8 DYJo;Yš5MKɰM;%Pd9KhnD[zgVh,'C p!^M(WK2X>UQ%^p8 ˽^#Ζ؄+.@gCz%ɔ-Pr KX n>=ՔѨeSvRLz5%9UQS \WիK'hp)ô Jrh M0F (f_R5///G+x 1"eS 5 :Tf=+7Qɧ\TEs༬rYs8&k#pSՊ5MTbD܊[Ng5Q\s5PB@[8ɨV1&4Wsy[Ǿ wU2V77jމd^~YfC_h;a.&M i UWpzs`>/"'OI۲y:BzdTq£=йb:"m/-/PWDQǴ͐57m`H%AV!Hԛ׿@"Qzދ|ߒT-*OU^Ҧ6!Cwk|h&Hd5LEYy'ƣ7%*{=)Z%ٝP *G]/8Lw$?8M)\į/#7Ufd7'6\h1 vIfEIr=1w\WKVZHKgZ͡$mx % `j}TuTQJZ*H>*QxkLFTyU-)ôbiA|q`F'+ 4^Qy xH)#t^?@]^`ARSqjgB:rK۷l<2-4YKhgQLxVwP~M Φ0l 3ƅaŊITȀhwJmxIMչ|U7xˆS~2ߕ?kW1kC3];YnSґAeXYz8,'x< k7Kx]$x$vgT#w;o@ z_Vmn|HֵhZg-^TAn- )@4[*9xKƋj>!,Vt:eqn8%ohS(2\Q^aigF3vTUDVlQꅧWc%Ueq4ҝº/U $_Q!>t| ,țG<tC[xTXmf|Q%d#jUՆ|; H[bά#,Ws7NT1~m&ǻ{' \㟾 bBKJo8%!$Qj:/RX)$Sy޳ 䍧RDUg_D軦J\jN֖SU;~?Ohssdƣ}6(T <_4b5 ^N N%8QejF7toMyө`)g[/|?өJuGL坕/=CTܠhdifHcǞG4,`D՞{'xG_p/5@m +$jVH3a"*ũ,,HJҵȸT^Qyo&IÉJUVwWLeM~3tA6rwɤ6տ \0HL%LX5c@HHÃZ|NV+7WM{cig*ȸU7iÉбzd * ?gtX8̝OX:]2ɍ]p^++>AVڛE{ DB.&/56ArxY#ܕy)cKQtȪ~! ;C}ʃtf{6$NVsj wupZ)zŁ|-wg+nMVj/d+U~ͯi:_ix whqr>駃-x뼬)ݷyR=! ì:J/lIkV@n74758Z KJ(Uxz1w)^\ԣzȪ󲦨c2f؍v+6f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘2N oC\F1ִ UZJV̚\4Mgq1z{&YT ,HX~D u\g}x>+YdN̮ol ZX+F[/j+S~2/jV8Jr^ԉ]J}J*ۏ<2԰&JݣjOM@ѯ#0O[SXB^ uze\]dd./xXE f'vO_H${%;kt7ށmő|d{aފ^ǛڎE5ʋBr]W=_SAf(0 oU5q ,_\luz˪uz㻲o=Yi~| 0+=VJت /ލzM\zCL[U:|k*^8"\Wٚ\ .XTjX5 SkFu\1 q'mģ/QUؕ*AɽDNZ׮?_[# ˍ4:^j|5LG ||øBW{6[uQF.1$qF9IHg)\5>C#uXZ$#*<ߐsRv1Tj>Jm>*#( [Fhsש5*jQʼ&&&P犛L[Q1* ;X}Iΰ[Q?qQZ Hݙ֞VEsBCZ9JTK tup˷ /O,.kUdsOHMg4=-)+ؿh2Nw/r|WQn=GIU;'j,vfdzpe$V GTYsBZO1pj:r"nTUSCgr veAۘ˜FC+Ֆ#[JTe'v9-3 Dmӻuuz?0 o hxuY &_54=f07kלU0]D:jdw/+PGUVS<\2uatc^zYRąmC+7#,|:iNw*|^sm|X>Ъ^1\#͹ &%{,2U>ݎ.c05z# ogNO+Q쓭 ,˗-%K\[S_`y+b_94"U+Ύap}I[M,B.NtwHj漬E L߀ 0DX(kڵ NoU{gquz RwkէRx'uZ[3'zyyד%sƕ3jYF\s=m1&VAɼ?k\+]6yモ1gtOIW7al|1 >$]e 7؝WIe?ަL#>| ҭ] pM5MUdI61ԠeǼYGhOn3խR:^k_'Yuuq#p# J2xl>OjcY馃!ڡ+sZ/ D}2AY mpc#<'xSKx`*W[,e|6BH)㶤kjpDU(2qzx9*tqa/, Z[ 0>Ө֜xN)fă@qըFU՝w(a;ˋ>|Tc|w2eiT]*!_\WG{ ]^݅Z5t|6oYHaO@= my^akE.uz]#٥hWv(:,6A߉JFa\ wWex>vetuMYA>).,;ɦCbwjE)W Fӫ@s4e6^Q9oI}4x<.B?B߫#$Hx.x9,a!RTpgd5xBe.L7@* AsduttSVUaRU|I xG߃$T񭟬#_IFMŒ_X@foQIDII?|%$r {ENĸwޕqq?Dؽ}}o/`ӣCTi /ywO rD 9YUD] Ή@s]+'UaL} hrU'7:sU|k)H@hNq#ϵ8y˭Xű#w 1!흉R'7fuד0p!WÖW+Nmp\-ioD$g٠˅%%ÐmV]̱rw*Z}y+L Nouj}xt)lStuqxmNyKUOnDbhf}k>6ufT%{ <񐮸mjFcmUïc;w8@dGFUA& =nq5]iP}z:k⼶-ʓ Κl*'UzaxWFdZzTNRs+# wzgi:MBqtM l#^'Gߣ*^t{=rERnQ$adJl02%Tڊ^<~g?Of*U^?:N+o[PUs|QR']V-L)H K䐞 mYn\4}YVD hR;g-'3aסM Dh}1cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌk*Ț4`L$b U4\dt'>HȄ|.+Y+/Gy2OCWv3v,'kia W O6߯E=Hv $LlxI躍/}^]x\3 ɮ5 QT&G9Ay^i}O[5ޱwq4,s JJI.myE^%'VB~dׯ}*j* ~uTk\fKЬ*Y]_v'I˨鑩6Xo'j&uɧngT]oڌ9\*wVHӖ| >:5EF'J ɝ`!A e~_;5ױϊ镋m_&OVi<}"靍hW9X6KPƣ G"ƭ?/O^hCHLciPj)}QQզ#tMg9 xGw~d;_J+RỲ<;e 5/Qs/5N[!a+NPb+ѺI}-t_qU=MKʞY5no*vvbʊ{]| ~ Z{-끇^FVviϵ3Ya=6ndS;-ʹ^;uꪪ^ |=_w+"i&4l#wir|W3U$"J~O@]~tRJVMHw:̦@?>O?vdrtS*$&~1>Z}^nL(]f*&*QaIꝄ|3*O?r?*4Gyz[k/tkQϖWCCKk/x5|S*`ϹγQEwy o KYqTb$-/PtsZNKQ*>ݢU@Џ"JQ;¹& Lx;+T /+O赟> (T?ķD^N*'p$IW֐W~ =J|_UTe7ְP`;CYjk=sU[mߙ-;};2|wo1p0~>0m @Jrǟcٷ4͜?q\UUIV?2L/+Шꄾ< ܇^T ?tj\JrҀB*=km X,n}aՒIadp׷ll{\6v8RꅟҲf1F|Տ;e=\D ,D:ψrxQT◎*|{nS 9~=}ӕG~%j:Dj<ឫ:jO% $T8!jvm|'OЗ¹➱z\vsIv`Ȕʨj-^$-^G Q{m`T#c֞㸝|n.ߪN$O JUVʼt,jg-mסּNV z:(Ι*|1Ux=Yk*t MNNDUhK ؞X(刄Rv!#B_cxRŹoE5Dg>?fXQQ˔|@"աMveC>mO$H#]Y I=)_`k* :a>!X!W^wҒl'<;vwgIt_?Jh`#E:fdx=6Wu<Ӌd2di˂c#h¬c4?<HFYoVpN;ݷJ\ >` (t3{>⦊;;qFx4YcS$w.da*k|Q,+xs^K߫P^nO֮L5mIwl?-.ʲJ8 F B.-:2Ȕ!/A#b_m%I($|PZ[1G{^#o>3mw?'cx[^:Wk/`'=~֥W(gQbfv7UzM3+؍K:4|GCtA+Kʨ{@Ɩ [05E|yn4MIENDB`scikit-image-0.9.3/doc/source/themes/scikit-image/static/img/logo.png000066400000000000000000001305171223313777300255210ustar00rootroot00000000000000PNG  IHDR8D$iCCPICC Profile8UoT>oR? XGůUS[IJ*$:7鶪O{7@Hkk?<kktq݋m6nƶد-mR;`zv x#=\% oYRڱ#&?>ҹЪn_;j;$}*}+(}'}/LtY"$].9⦅%{_a݊]hk5'SN{<_ t jM{-4%TńtY۟R6#v\喊x:'HO3^&0::m,L%3:qVE t]~Iv6Wٯ) |ʸ2]G4(6w‹$"AEv m[D;Vh[}چN|3HS:KtxU'D;77;_"e?Yqxl+ pHYs  iTXtXML:com.adobe.xmp 1 2 1 䒏)@IDATx$Gu'oΗ^N9$,mr0`lm066IƀHHI$!@9/9N}UI]7S]]N_WyΓv S!Hp^e-fw2|o<98T.DV8VJu pk^2U񜖺xWkjEkjic94m5:'jYH!B ; 6 V4X!]g$g4w [NJt)U*r>QL,RqP= CčXu#?" K!) 7BF@B!"$Yb2^fL+{)kJ2p@},,tQj"ݠ iT(RnXsm gBR @H NTP 6,>ޟ޺ۆnG#1@d);*̞XGaa#"Q$SoS垀.*LeT\'@i HҠ(-ι1[uIc!XטXzƮl캄KWF:1@H!Gy> w䊓B,KB!ȩH2!K$P#cF'՟lZ $ilAΔ$"էjQuWeʸ'8ah)hM9',le~tR @HQ*9|êhn߶[wܾkP̍G8P+b:*@ Z txPbaAX%8tϙ.}*b*62i*P[ADefFzG۫ZmQF,[zftc1[L*饍';.fmd5T;@H! Tt8ѥKm{2)-uEƼ4 &m]ݢq;SpTJ^ HJf$0"45%%J2[(  Zk 7fT>PQvHUWMb%?k;LL\)@H! TftYL~SqѨq1 ?`S#S zLS@9Iq6 0RJHԗVM?u[UYl̈UE:Tg:T_Pw T(o{Iϟaԁq!V`a )R PȀ@Q̍Tl_?m2&KXf$fiP@5妵Ju,()4r ]"%u*UѝE E0%ጀZ"̳#Y2"jX1vX̎@N5`IxNH^+(F5a )R @Hã|),|Hź_s[7F򻣑xsd6a-])u$/oA]F1dja.>8~d`DwHLU3@aIYEeX(7dPJ -u!c㹁w%]:\4IB )Rp)0 txdwェor[] TD1H YnAP*.%ҹimjmƪcjHak6Ơs[ jض5H,*Yu*ؒ 0a$J́z.lSB )R`V  G \7O/+ JN2UDMP17W %L3}WflsIݙsӳQq*rL Qu%ajUD|Z#+.֒-?wm<~7.i<^hP0)R )0_Rf;}o9ufdDB6L\#owT axA),3)2I'CHS[[njUTnJZ:"5:80HTCX⩖ةrϫ6+ه b=o{Vʒg֐S)@H!f1^E<躓[|_'l2R_! :8.ph'aELP!o<( _EelnHRvlsej6r3 @13ekz; !Gm3ƴVj $tBj$.j1>Bl?n3(hZM~)R lP Rd&םUK%Mha*Xk62{8L\~^Vݤ-SMO}[T`PNMZ4vM+gP6Sg xFEHSjxO)?]7=PXND$ΫLxhE[ qO)Ҡ=R]ZrqB )R)X 5;p[dPI b'X:T IL[)c5e7%Z|`G[:1#љtnOme\{vAf4 \הV; k[{OpIo*׌@<ߚQ5n@TU%{U6[!p2 ^'SUx )R @Hs*F|H?"HPĻ3Ҕz2+ҫA,?Mr*`P|ߴ悒.j'ԌJXI^L .2a :vPNurW3E 4E59UD{JZ[V\6ޔ6KHsr)c3\ !B )`(0'& 8w{|?[ñ ՝`I`݊zAY6RUAA.U2U" +ŕHHq2T.P=O,iHb͉HS"V2QR:WGv!bѸzРfT:k b9J2M~MUӀ.ߚ4e:}I{D)+ӏ _͍NuhB3L!B )8 TtmgjU\D%um?P`V0GK LVyu;%U*8n4$wԯnO.kOړz$˗3a6LN$ST@[;b:$%AJ:L‘*׍řj`9vzUx$R2֘)>3{S0S))@H!84Pʰw|/ 9f)ආ$' 3!1zÿbWJ&&xan GR,扞|ˮXzf2d'핽{[Nv-0ĝdSvt,=iY0\`O7ciR8̵ P`F޹&N7p4i^'aT`%xO #.D݌H7s,K3-Jgk}߾gՓX&95[ -*yѾ|v-K͝EIDPb&fP܁AcO@z/}y9!JAO7x=wҗtv:~=չ4-rXP`f|j,s7ضCX$0)?@Hed?F >f3LpEHG n{rXձxy;nwD*EM#d/"̄  A p@Onv=x{s[zλpͻ7vk܉jnSS'-*#6Upߙޛo׵2}[3{rx#ltt{$lixAțcn)VdnV~ޯL'RR`۶m>)bتU0R෕3 dv޼KT(2H%jH\(++#СʎYa.Sh`̂4J=87uT!' 3\q7ڼ-EB)ӑl5-pҐ҉%T\r8._sVê:t~̬v3 Ā%xROFRM1n]Rq #W.LQO"[yR![ilwyb{הu"O%kOowvuٚ*)@H!(0,aY ϩ%QŲTs:2 qJ:=U m^&tN@BUuFPW}*tZQ +H'zLIdW,bN][:o-F;_|7d& hF|\XD&Rd*u_,)%@ƶX-˹I/7YNhܑSȁ-ϣD]5f Js)Jt#X]kW4[]FJ0)R tR8zl}-N eV QNB [lFI ϠY]kZ81ʩK_xΊ%ǹ*.Ñ"6jz$oa4%d$5#8 X_~Gpt:$q"V ,L9PM sǸT&J":m6 08"Q ly9H~L̊V TeܶDCH!B TbzwC=~OeIHaCT K(-0 I%?3tgmD#Roomy^nwa`U(eQG=ʘt4 ,J!] 9M;$xXL$?QN5-7 ݽGMM{]Z%2命p+rg}vWWCCCd3<,Ba{XR`pOVشut~ Gp`X lBwV [M'UTMuQڡ*9~s9NqۮtAT])~8R3MsmBN #hoY6u9 m`lO-K NA s^a*fV._spޭ7SI'RoE*JО<㔊X, [WP-ohSL+ɺ&.X56g֞ Ii"nyX{ӁkO_Z~m8 5c?"oֽ*j > J1C?F 'B`¸o2Uva*?6 -J攈^Q22.X8-6ƻ\+nrs)1EЈC%GL qۜEn*y )&QQKœN}ҭN0U@0鴯[lw56c-49R‡E`R{ Jr"6Yf ,R4u& bBy `!*K (s_,gBRa )R @H @e( 72jJi)L`t` SbT 2ir}0 Y~ .U궳N]b'=-gbmԪ۫S>5;zv^~BlKk&RxӼˌݡʥQadOy`Gte]oGv'G\21TNq CA`,eVkPȅ΍"щHdSr97N[bT;@Hw)^޶H 8w W6Lr*E+s kah (ۜ/#S U+^$[n:ŗ'v=,7tCTQMKN)lhw1;iUo-r?wvH4QT]UqCZUaߣ>UvjLU/ۿ-e#HqbidZGB%G1ׁ㚮`j`X+ůXTQBJr$ G=g7%4 SH!,*8+W̎C&R% ab8O!U,#F,^6EþU 6FR|d;/MFE{Ux)R U )z™lie #|dBY$ÏUETi%ƍ\ c2HJd׊3Sn{;ljT{2b;S_tqG!,OSu{%i'3e"eF>gTql-DFxuE#[ҨTZO&3 ouʙ#˺@U;oJEt`P2ep!)Wx0B1L!B yXLa!~ |XEd<|g) c,d Mѐ:p|ϥ@O$-%:W9#+n7@r/=|Mܓ.vݣJW8=bWOq:Va0J<9 ᖨwyw}Ɍғ>HB}c?vLS[-mb4 q<;IL]UIZ!>ԐBtz'@X,g8a ?4Dc6L&o߾l6{F zQ`Ԥ0꾾q+G7J%>#M띻;m *q桞! ? %}]۔ky%:I2(X ark.UMX5TmC{M)緱rJbq}sk[laݻw</]|&]Yfs{wu<ߐP,;Sg1nXЦQS[oby $J\W%)dĩ%'"ÆȖNJ"?隅,cQ)jI\ʿए\EoH}Y;ϻަ_D֜;.߼\ƙvou;Eآtmf'+xa`p֝,^YiZʋ6Ďt>?_ybLʮ"8R jLYvK5F)-rз=ƺ87N;*qCEA(1jJ4Ip'=_8_d Dãa}߆-Y<^W_z!w ֭[gȿt.dO47 ?XW)+lܸSLJc=g׽uo}[^AjvjF ևe?sMwkƂSU̘;_+џٟכ7]tn~ҷz+c?TJ&/x PPu}Ņ>`mIwy5{^ʷs~yӦMsx+ lDkz7ţu> Sl#ŗjf9[QAH}%h!Y6 揥fJhͷ1ow&G*@%@Ҿ ɕ|? jwmwzNwy{^C{& 8&5ԌrsgUH",[Bm}=`nmZ.Z9׼xϽUCX\ƢaOUG#o{wz׻``믿[L/)?{uNVS}y~_Ҕy&_*g$Ї6gKvnmjpO|t_Ӫ3vd~9Յ Iఠ\ⓤ *^,#(5֡ 4tt>X#xn6.!ӲJ SQ@vgG~ t&'HTFbIsf z][fB~MeEiKOh-;gxɚAx%"9oyBgg'-;`_%ꅚNfNt\> XzX؍NrId x- Mfrwl(|ݎn91e={ URPMN|ιbe%nUlK/hK,KzQD _>Sc8բETUznZO&[SK7nhu):=2U>߂(.63}dA agcN?я[ g̀s<ӯboyFIo}c&ʴA͹gꯂ#G) ?P|̬]6x4JcnP1a5LuOD),ޱtza4u71s0LEG̀f¯ 5^u20u`N1HcHkj# c28![nM| As?rG' k<ۤs9F 00_qoP4OH* E?r۽C!]JU/"*ynTa rg7ņ)C2$-{ZsnCzup=^I 5͛mS?\)mh>$&Lv[y׹'^Ƃ_' V,B#Ky.֣ͱ<ʑxW?k`nGkD2uDz_םb/-jrPg*Lfʉz$052(D&B8'-g%#'>I&DQn$C<0~===h ƔxLym쵯}t#k@$-lN`Z0O.䒏AUW_"X<\|z漟Ǡ m-C_Jxg8VfI_MH 5 o3 Sd`"DuEt٪m@DŔ/*K5dƢRN-]呤Ao#^MY$!"q*b7$4s 7R.NSxdsvm4%o@݂UV\DE${6~mu[κD"TvD,dFKZB1ȝc  T]P wGdʅrxᆿ}q:d&Sk> 뤚gh+;51E3r.җB~U(g|A)'@y J iG`ɓGYpzR[Rx|^'lԹjQ .W 3 1i>E179nmv[O?YP*ؘE],qK5y"5(x Jۢ犦m<:  JA^:J{?Ϡ PXoc>3ޑ~X6H\I @=:da># S9 N*`YX+=𫡉Igz7W?rE^o=9 7Hw41/^.fj@:$Eb1J?!Q1EckT̸\!q C{~dh^12>͍A$.Pqc"`3*= + eqĉc~B93:='K6~tu_-]&|1n `6ҫ?^J,)_>KMիWRK#}:r ܁5X8KkpyVgh\B%V јSO8#I^p0C ܗiyf.agûܰ ӟ=fM 8>JFi^Ss)8%sAG㋄oHsN8!Xx<"/3#ˢdFv3ĿK4qmκXAdEۏqF:퍳u ASS#6&a\QB#q d},S\ T۲DnsO= Eq\-P%S3# `&QmjEXa*S*R򪈡 dA0Gx IT n >=w|,x1.Ynӱq ĚuƳ?|rzt`w{~y!;>":^_~w(}̀_8 B/WF}6X:#z<^~~K_:X]jJt/(BIqXE`k`Շg.=`aB&@%/8 6(l(؊D3^:d!"`5`y0\`%~xhD7R&',e<ڑ FlJӰȅX::g -Sag2 ט  @0?j92tP ۰j,r2ze+$n{ 0ÕÛډ.;ٻŻ璊3Fh| MUX&GA9O +lKjF^X9y'}{B60rȠ,Ibf+=RrgYsx0lZ&rH_ ٟ{Dʋ'ONgt[W WCz /]' -+%w Yo-']bYhuwwg.-"!Ej UɑB+&~U.}7*WX?Ƣ\ZC%4^,[C,0K),E9J@f@tŔ[Ց(͍= {VD=ꄵ!QQ'őg-N1t k+ܧ;^ [*(9!N)̨xY)k@9 F;,wC!(@IDAT8bãT,a?ς%HI&P;ZT/1X Ip*V )cԶ ~;FF\w̝?Woym|ދ~;]b.( q2go~<8TX]tQi_JB !#Ewc{Hc\M5J|BbrX͛F!Q':%&ÿl ΪӢ7X3ҿU⦇X墫L6sbq czy$aڙ;8R@{~7],rZ*( Ca_'f9\ :Q%Xcg1Co>P!ܠ|2Ƕj4D=<, `aS*r 9,`zվK+.*Xg7^$x> WS48D T|ҦR%aXbއ'76ڲ(,&cUA>/^Qeʫk8a|ZJ}fI?:j&ZkR`A}eb$IfJN!0J{aEFm)F6w{Tn鈰&\*(`ظ;&1b>?zo@OihhDyF+;HG'2?? <F"RɒxtKgw\2%cLk5/hˏ%p;Sܹh B7m͌6ϟ (bx mg 5gx!B9cZ|@Ksb+ozRዀ²Mô⇑hQrU엜N0|*gvg[$vn b؞ȳoSq K4%:'GSߵ Jw_NcF R.XY,9*V[՗ VY?Wlpݏ䱨I@Q[ūADC{X\g3Qq4݊@QX$Z^.3PP &BF\?R"$L@j!j哻L"}yĒI"7RaPwS!'.(;SB"6.~6T]gnW [8zuj!H<b|nV~awAgұD ,B``ɏ66~HITN;~aR2 ? 2a>XFvd J+B'CxqxqS{<9.6ۺ=EWXfDt>fQo"M%kr;6ƾ]1K I?RM&G. !z' !"|Hr)=edI${P˰LOC3qԭPdՒfRs({cV&GFAW(8'bp2|:CRcH*gx/& h)xbX%_ 3)&< PHxH޼rAD ֡Upg hO'9cs,ysl;jDAڋ5% Ef>r@2 X>ӄB.UqF 9kNkfQz/◀3;[;JXd~d\v׶ɀ(C|ܖdw[aH#,cvyNM|5'> R?@xC=ncG ӸcrX6jߒb.x^Hcخ0j@ X 0Z,zٴKWb %ԴddM2c"Q?G~ے EЫ'8>/;<$V"$ }:*ʈd;{zz.iL£7#_D$TQ (sƼt%JYDEɳn׷<&~j-Rsm} Fx?J)BG)EgW5b*>SCibNq+׷vUs]s\~hJ$-1vw>LpF?+-V(-?[=6Z,XxNU` HW=Q2X* 1MyƓZTUj!?[n+L I<_DB3,pf߷-D ">$?5,Dk9A"~ȡcn;ys3 0} 6h7`>zϨ?j e[iH9OUP8υ-dW,p&Y@ `:IW+\,( F~c_$"mq ="sl}6Mhr"̗[om]{ ܩ(]2lab%/q(n× 3C0-Z t 1Hb,LY5 !2A />2Q*E"UYyo 1., 8Y)"۔'[$12Z/,X,㉯\1c[Od'a  sߟ]d_ > }Q!P'j0R:z*O=σ}x mfFo'R~$ckOoLhyOoP%55ݢ}#Z@ԗJR9.%G*$_aq@*}n$FrE]X2$m#bWov^N1r+ pa# &p bj=TsH0D{t#9΁4ֶrp mA LJKW NJtZQ0HNYKj8(UJ3K砳^|?#:iAM8/R͚*;פf<bZb{V+ ϴQr Qdu'R5IT`HSf4'^d<;_>/^eG]Z Jk\FQ/ F)0@؋I=Td0 b7Oz?6˪ #S22a$ϤQ=|P8&IQC~FHf?[D*UJꫲBIΠ &p l{sk^}QM_=#i^}=_f~[)]#Lejve|R_|Z,>zw7|b'BlEL[+՗ĂX[HٝLj(}Hdhk4hB[ZV됍TW?vkY9^>|" EE p@ WOsmH2k z{0/%p%CZ?=Bw/M]~Q @J&5_NHc) )Q[:S5\L]ʃZ0Ω/uUsp_mR\ I>0mHJ$ caӅ5?Mѻ <0y뮻VY255NRgi8KC ? x%eqP5 Qeb7)m(!tKk;D2嘣5R 66X/4%oە꾻~#ec%XyɎ-;Wfw{}G^3PpQeJ] ܩ>(Go|TX]mYb™E|F XyCɤMX +*>(\'LS\xUc1TfC#>{(C<-:TKEsU51=U\y_gn<5s&;f~UO{ g5o Ԅ?Y ?{ VQ>X2<<ԟgkϽԌyOH#N_u%2X15! &NHK ٜ&˥\)=ヘo+d* $SqElۚ Iت\<Xnm_{Mǯh=?[,0 NaJc^x.<.[^Y `RX3 v%@EbN*8@`MqP Т Y]6r$.$IkO2Bf~ cqKUPZ@!mmSYKӶ=ԙ{]MqgrՆd ͥ'$W.o{vZ(JUq1/%CxC.⋉taޯs믿>yCMs|?dY* ~%=س0c\!(X6y:ʈVe$pHKb^UJPc=p{ןӺx>[ܓςjݩɞӛ`ń`!pߎVΊh/t~ts]&|7so;Wwn_Ѻw)b>Z^~{2׋H11J-xygIqdU*VK|QEM >dNp[*O24c3K'x<1M9Q-W[p\4|G%&vtϥvf V k?y{I7?BC: 7o|  %8 @sMdy~6 GG>7A"`_rX<2j2akMF'  qbi3ѓ}cX=$AuyEKnP0P-exFZ'wut~pћ;dmZcէ45ux!8Kn^>SfгYM,ubfF >[Z~iS|Q]3h]lMNg#("ێ㛾똯쨗f, ĕ0Uc[ lIb9bCjD'd&OZxf2_% 1ۇ%A8?UN^R'TǠgx4ix3:^d3{c34]jؠ5jBCZvk7oοV6<䌠bDajTe %#ȢĐ! \QZj#9Ȳh_ow K'klJӚwnZ ܌Őd(:q| FƣM ;n&Rhڍ+*nk[l+;ڗ44w/ZY,u'v86y;i{ܔ-*,,Qx,lo& -F2FdbPMTc[RSQ1T團|t~:u i):v~J#C9X| ^|܃O`Boy[<.#t*۞'7ЌXV`.p8fJ=F :3N <kDc! u &(է`ث$G0I~5U GWJ<+(մOAD`A*n:"L'9~$Sm$z=ׅ;w~),Y( 8!{F Οc24xB'<<`{p\e1>*hkΘ4k55kR8ruf_Yż7+^ BD2|)<$Jx ES6""C)3V'IK7ȳb\-I6utapLd} R Nur,d@t0tlW~x_u1uChQr'V*R>_ڗ-ʬJGl]}Y$ʅhzч<Ɔ䢮mg.m>sթM_9qs`8Y)Ji\&!): I“I\WO妎 fydl:"_Pp"׿7bI5"o} ::oo|[= S0qp1K <~%zd`d'' d;ӟ4O^z&_װY3AOBE:"?ߦ ”%py{T[258E4 r7fM_mwM>2!k\(D%LfO6J"saɚ8*JdscC[!|ɍV*@vg_v{wF[W5~E^tJ>ww;MN"@"?TC6E4JJ+fe*nߐN Oj?Ė:M8dIvN"ZnyAqAy 0>8΅HBJw^:z׻fɠfdA[L>Q- j{~H@s'hOK.T8Q}-$X|"(g/fفjb6,GK;; x29RkRsy-b7 iz$d)CF\G:',Y?9gQKE|ʽ{NЄZ, bi{0]TThM )##i1(~\Ug"hQHW}_ĩ!0~Z3b^7~z`^(GXgk?ENq hw@~[@lEU}5\*uG^N(,N!9LVn 4{s*/v_h3HH5$),FBK߸Jw0I4V Ht 8a{~B(q@ҀÈ5_Nn.lH4XE"q!+vmر6^жVbX>1TDHx05,F?'M '6#Q-[_ oh-<0Qh&#t܀O 4'۷9}/{6].;)yEs T owۗvF<LF*}ߖu1M1ijPS uf|1ZLۅ?wΖT;m 6~OprJ Xʠ)D="(<O}kOdž\PRg;v ^P=0lu<J|s|"]ĠE`Vjwӈ5&ڌ8Xvo*1 HZ*O EbαRv4;W\%r $Wy391HH3: vef:؈A,5ux1Ol ڈKFBIHhsHsh#*USS=깤|_f}}^BpdZũLPr͝CFJ%cCl2Xo,F3K{!.qVT$% 0dp2 :dDI5(GliK6=OIL]?Q"ȳ?zslQ#"()T6[:gG5'ږTP}SbڃhVJGȉj'?=yc$>dBYDB߼yw1000k 9spp. /9.䇍/yyUI=" ָV2S JNx ,78GP+-[Ζ_'L3B~(y1Sթ(j}z4#;?C^q=^k=$'tKH8_ǼY̱?5Q]p5}1/~a0F8$Waj}*.REddsYP'z9"_rxlĨKdSbLE0ruIN?rVڕ/(2), `'Y҅sg Oѷ2j: at'R'gsc`+Z{ ;%] XN& (Dg蝹z%w;[PbdcVP9HRVCaD몵NfPAE26bidfEuv6̭D9⧂:%2AW6Tq&w6ơŽг (mM\1?s͔gYo ncANn8skMfq0 +&oN լ=sΝA k-ވD>Ǐ75s<^ DbTyځ\*Y 9IDkwŽ'c] "2Q  a@svyɃjR*p%K +H~?܏w"u6>/^sWv_ޏ'P5 ؐvA (lup",T.3ߖp\)~Zaz ?B )p)`g7$$2Rc?幱 a&Ȟ#l)bOx.?C%ԀZ[R8Px=>n /![yz%,'IF̴jJ%S~XlGm!CP00Z54Qdjh&!%aC`*.#-]R9ܡ.X%'”VTf")35$!+GUH妐 *;q}U6p헴:4\g xN>rXTi8!*@b<-L  %&o8%!0dE\Zzn L 4r -f@Nc+%X *GMak&'Cd)9T=Mm|Dqp7Zsv<;Ԩ6#Hm5ǎF~le}j40Uk)Xge?YE AK-6)"M;GH!9u'za^e˖ӻ/N$TX4F(^a 5NzYCƿ Y\|pɃO3AA%.\t"ňO"XВ+ E\Jt~ a`nSk X4Ш>N0ڊׂ7V3'TN 0":?)వ/'Px$clo(t'6*l\hdV'.4o2*שK imjvҭND~p'@HPP!%I]1&`mCj$ږxⶂW+f?O ݬO L@K%F3)bRK_N5rQꞎx{ԉ #;v1 ^Hk} -$!WLP,=|,d6uMW;fbPRp'ou@Awt3^3TOf]GdN4iZ36KLÆZ*f3SAM|bޙEAiy9,ʶK,Z"v0- ,/hN-Ng{)I/LotvLƎa Aa/ ثm(}?bD$wx%h𤘓$(Pjp jai0l&І^W{Ϻn\v\mV=o͒kIwт˹ip`z11v;`m$ij1ZE>K{ Y wTSD/5A>B"hs`3G{ iǠv,85Hdx cRעvrc?9Z}NbGUils:QU I82~J l6lꬠD"^"rkW2^٧ 6šnCؓNxq7$a痸'[n=f$*d3,l)3P$ "`} %r|+VGH=D2e"ÊKl_拗xykˏ;^֜LGgmOhG/37x]?-EEtm2@EBNE,. fqj&8屡 R"Z Qp8Zw3[fCS{Ʀ;5nr3Jc243>v J!8i.Q#Kq܇55AdZ] Ide.urlLK%c[HH19IdHf!]b|b!x9ScByPA_g z֑^ܚʽ=3 ԇ3+mY-@ؓX䄘U9;m|6wFJ=sr%(+.UWkU+4eKx$ Lz<0 18GYx"-Ei1j@trVdK_n7~D|_ʱHb84YV\ۖJV[MR-?0PM\#.STC0ʍGTi%jՔ% `X#[ڂO&O.N?HFⱞI['H ڿ .)]E>o'q˒)B=j.VN=DK̬loZsItgS8ZUHZ<۾(J|ͳhXZԾ8io޴(!L _piz7\L6O}ЍJСksHhfD(U00p`ý^ Ű7r~J˄c *gڢx҃/p"5%Z(MMIwf0 X:9z@W zj2\sҜENBRcC丛Lm~2MAg쀮BJeX m9PmִWJi+llDx:v&h φl'yȀ Tt"o1\۶j]<5Agb"ߜk^J4D{LuqIP&/JF9JMN>tnXEW *|gzZUϒc*}l\/MKSb,aLsvBh QF% KԆʄ, v.K$xȊ=j`jCYN9YU%[Ibd&\%th"lЅ JNL7ۺL/PM*T­\i]jA:XW*C f`=@mx1)Pnjj8cD*#r3Q>!_GDK;+!-߿@a+djȈ/߰lݐ "2֥0Aو70ǀugG 8^6k;2kwbYsH8\˸3zvjo mhP⯻Xwfuc *'C*8;Hj/ݟl'?y~Arg6[­33G\jwyd?c_#$#GWGS\SݣCG=[fWz U 5'  Ď'=Ŀ`bQAc<*ϑ6:ȉbS Rq ڙ!oUQGr,BvF9:-n(Ԅ> F䤞jhm +4QmӁ=$-[0ҒN]x(Orkn|:e[ne&&-;wZF@J?Mb upw"_;aZ;NXT;N|`21Lя~i>ϒoq%;<Ɇ56ONAr™y'^]AV@:  كւgC?/BHD;SdśdPnV҆٫>=H|=ػ w&qTuq{챠5\0PgKl_3?́PƲgfG8WK.~~```f#AI } 9rIu]<Ոs=E_õ-!^!6;-Yz5vg:4#G DVAaJڒ}[ż.U;k{2/;v/yV%뾌F=<HPOdžsȺu/]sݓҏ1$LBC$w8wp/{T߸vǦx3w#=sO]J)\6̰%H-wR$"q]PQXXShZJoi|Z v^ٱbkUq@O9iJ jjO ]+rZhN|| 7W|;Y8׾馛ἤ[We'?IOs4HkB?_l֯_V^#Em5"* [1(_*@vf^U[AZa0~~L !Fc,n0Ar4ΑwÚmo$XAMЂyæSD@ћY Oj6>;w L:AJN$C@J=WiFsM AprDێI*qPA_7Њ}T#EqDK Ȏ@h$a 8YO++bbn@*D>BAӶM甞Q$sDn#m~m[Ox,b7%<]l>,Aiu_-)Ypm.i>y;dt=7;H' ,1w]kgڡabM}s8v/D~S6\51T$h M۳2yյݲCѱ£_?ܑNk\l3x>?b! L JP9C{H JrX#eK<5 #"JD=2=Bi< LF\E ! $D4Cx '?ѠT 4Ӟ(`_ARG#Ia=2%j3x?*zQ)rİ?v%~mytN͆5]oH!^*6<@)ƃů`x0BdNbBJC!=E`RHP~P((9w_]0͠Bzr m4/(~`<ʁ16l1@)[ԧ>nč-`P2"6 AkAfu!s`j9ky!]RP?w!h9@)[I\4xyWPU7R7!^7.Xphf.A o4x gu E *5|A&f D~u9GA\*Vu\n\$?l+#x-b'G }kҭ=ɶE^wm]zgC_3 a vBCU V:`(Pz߃wmZ.$H.Ku(\E*fY7,IVnFxSS("H{@VXP[Y$W`2"$YL6B98bm.:W(AC,\d#b ƅO"A5vnx67$Kp*A 8#B10/a+%w6xYcc˔g}Ol9sxfLgp:TF3/$phk }x,2X<Z 1N8& !gb}͑pLk0ZlcvACAĺ6k@S9j g3U@6NpxoYqx)!@X2Iz _%ʒdd) c5q12gc@uǵ?5a8=4Epls-P1f>:c.AVrAM^(dNq?6!wSi'ۦP`r 줝 Y8) :??SjtBNQεxCQzsjvj{|ܹ TPRQpVu B,.sU2(ٱcAA;05`̝gٺu+f9>*ouKG^ fJ543 ]#1:Q8V ٙk}]4~yCE T4nV'(ݬK;x㱷 u کB&Ѽ=o=R ֏N,*X4]9gտqkx>};zOӱ$Rbw8UuD%)4j1F?~y`榎4qݥc9"LVH\CPAi$r#=jB}Ћb@='R~rv?̚m%T39X>Ӝ,U*%?7OИ [a6b{ȡɗ BWFeX[8TKwz:qN8C4:@L>hE'Fp0>lSG%5Rt[6UEJ[yYJ)UfVW8[pȏ(FSVwD6P=k@ٺQ cmOo r(b YmXv^݂+YϾΆ5=Syf|z˸Z4ںBKל)UhzQEL:nAʹejjVt@{Mâ`.i,gĻ M| Z`A;XVp񘣎s>lEbJnU,~feBS3ՕwvabڏepOؽ)* LVp~||/<]g_,UnUh4xA #])[h#\t6 sSĉ^ʼ͸dADL':\迬m;'C @ ȥEx-g6Â[ёeAy}ؿ뢁mZ"L:?b̖ is' $_K~X O Z@)R!K%-g#&Df6F8SCiEmL)$!t ݥnb:! 7ѤT.v]B6YabyRf*ϥ9,u`UhҎzyJ@!3ݨu!Y'vxl5>nSfj6 jCp±t(`gVnۇOg^RgY$bpEl]*r *}|`7kS! znnbVʗ{[ޱhOvyyףw]V‚񴞚@"c3A*/<Zm"4C+B"M y9PHR A QG "*+#$&Uܲb#ʯLBc6.*Eizmp˿wjlC~$Z,u PnwVIhLgKKv`X-A&/UM'L5;>4"oZvxF.AQYݱAj@hcs& $i`rE\$dsW F8ǎ]5̒YRdzxpNᕂQ@6;풸FL%wpXzC2vgbD 0q)ĔX?)`U[r(M;R~滝M+޶H1=9)@7J?J}+9Q3$ I@dP 0GJq7纖xwX'W yS+DӶH9gzR{+p gU>P\+w|.D1(NUK*"x( uc£ j)zP;7+F.ټy32@>v+yY3L|OƝ5og^kK,`9a6lGP_ be1MhaO! ښ̎dkwnS/~uu8+ά` {23I `h6n(Y>kӬ kNlz`NUY! \w W޶SmEF;u,=[?!|8+rWF9F`/5$װOjM\ X,es&׶ZؖV=P#Gjss*>X 0AeFNxy׎i1cc#@"c]T[s5$ƕY4Z   P)}#7{^>Ow400Xٍ <<>*Egu.mq]>%?0^ym̏&RK@(|ą)r^|S ةC{\l0R `Nٷ%=e/ oo20n>mD9Jhu9%tnbFPc2ߘܨe@ep`ԝ wK5+> y'KDRvIz)rs0.{)$Һz9 4r%NsPD'~[%y4Ѫr![ЪSC:QoS"|k_<8a#Fgg K@jb-;vv` /s᳀{~w`Tv!NP; XVri _b#KN%qs֧1NL#̔Ds3\9{S&}edw. QI2. `갤*jŤE٘_.-i~ۇ߱cپo%⥦DOpT@P rds$C<|Bx46Ųu^@ Sm r p>ʓDIXBIE΢/Q =sB0H)cx^H/! c'ҾJԕq :1~BQ;GcV 3£Vmڦ\T{Uë>k6>kQ踽c8d;nV)6رp!|\ _kqQ@j^̂t&kdv4Z5<ao)<&)7j81g -Z+c.5 v%hEHD#{/zU+>b?]$/mRg9=$dŧЄ# E!ݽѩ1;g>~=dbra*v WvGaxe5""XE oإdBgt0X\$Ǧef&%K/1fceB0_c) |UX姅%r:~A92NgΆg f*ظE)lQnGӵޫ|TxCIx.X#LC;*9B?{/ZۮY[HsqػbA( ,=ǿ*RO A0Y!34$"_ 錤'0DfC뢴W_u : ΕJB#U!B )PQ -A'$@8P1e[Ӕp2j}Sxª?PbQKa/>[w 1'?6ge*'a)" աeY8S]5(>rٹew\)!u[! )R @H(PRtݡAg5eZٚ^زz&ICJ c׷]Xׄ1I1sJ H"#;K_y;[&2 dΆ`Aq,R+6\|͝ZI&k(w$T،iBLk]7y,uBZ7%b(P-"骔W?aʰ1Thw)j!sK&OU}k[^|s-΢ &@uL)FH!Z ,(P6Vj11u9/?s`S ە#ݫǧL 5w2䑴-| SIf6k&d`0=!B X`Hx=WV,\Q~_CԀªXE"SiTh@)5g)ulnB93NYu!N76XHgj1 >p˻.8_8O bAdۨ*!|0M9,pbĉ8 FfiҨBZ*l0@H&Ld]Ipڋ_n4b'-xQ`)*0ɺ[D 2bTzd 17⭼ܽvrCZ&y i5p )R @HIZBhQd Q"^w#.5I+%8%U1%aEU$,kT\h@K0#]Z-w3eX}sg!F5-@H!N"NPT`ʬ! sĐ?}:;~R܃T0D p5[ 1PTD%f%r%y{ Xã)-[ot_/k[;X jv!B X( D}S{wj{?31Rg!pX%ZVD% UbV T`RK <ڦw -k]v\{۷v+`l !ʒ# )R ɥ)t@Dxos%>_t_sǏX\ ["p2=]^.4xn2䡾-{$ApK=qϮ:e6t0L+{. )R @HFTfBMXm]W20z%@%s *QU4f0XKz%T,6Fw֒ސ_~瀁l*bUK!B 88@ef`VX<ǟs`?GbԨOrbC$GQWv;A6㼪yL`?vpnwVwV4)ZY9o; NH!B < ^X*O¡>1+aN'RlXQ=J7·XFP>Ss߱Md3{HC:ZAH!N ?RncYIENDB`scikit-image-0.9.3/doc/source/themes/scikit-image/static/js/000077500000000000000000000000001223313777300237045ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/themes/scikit-image/static/js/bootstrap.min.js000066400000000000000000000617331223313777300270530ustar00rootroot00000000000000/*! * Bootstrap.js by @fat & @mdo * Copyright 2012 Twitter, Inc. * http://www.apache.org/licenses/LICENSE-2.0.txt */ !function(e){e(function(){"use strict";e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()},e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e(function(){e("body").on("click.alert.data-api",t,n.prototype.close)})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")},e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e(function(){e("body").on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=n,this.options.slide&&this.slide(this.options.slide),this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},to:function(t){var n=this.$element.find(".item.active"),r=n.parent().children(),i=r.index(n),s=this;if(t>r.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){s.to(t)}):i==t?this.pause().cycle():this.slide(t>i?"next":"prev",e(r[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f=e.Event("slide",{relatedTarget:i[0]});this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u]();if(i.hasClass("active"))return;if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}},e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e(function(){e("body").on("click.carousel.data-api","[data-slide]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=!i.data("modal")&&e.extend({},i.data(),n.data());i.carousel(s),t.preventDefault()})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning)return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning)return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}},e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=typeof n=="object"&&n;i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e(function(){e("body").on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})})}(window.jQuery),!function(e){"use strict";function r(){i(e(t)).removeClass("open")}function i(t){var n=t.attr("data-target"),r;return n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=e(n),r.length||(r=t.parent()),r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||(s.toggleClass("open"),n.focus()),!1},keydown:function(t){var n,r,s,o,u,a;if(!/(38|40|27)/.test(t.keyCode))return;n=e(this),t.preventDefault(),t.stopPropagation();if(n.is(".disabled, :disabled"))return;o=i(n),u=o.hasClass("open");if(!u||u&&t.keyCode==27)return n.click();r=e("[role=menu] li:not(.divider) a",o);if(!r.length)return;a=r.index(r.filter(":focus")),t.keyCode==38&&a>0&&a--,t.keyCode==40&&a').appendTo(document.body),this.options.backdrop!="static"&&this.$backdrop.click(e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.transition.end,e.proxy(this.removeBackdrop,this)):this.removeBackdrop()):t&&t()}},e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e(function(){e("body").on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,this.options.trigger=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):this.options.trigger!="manual"&&(i=this.options.trigger=="hover"?"mouseenter":"focus",s=this.options.trigger=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this))),this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,t,this.$element.data()),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);if(!n.options.delay||!n.options.delay.show)return n.show();clearTimeout(this.timeout),n.hoverState="in",this.timeout=setTimeout(function(){n.hoverState=="in"&&n.show()},n.options.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var e,t,n,r,i,s,o;if(this.hasContent()&&this.enabled){e=this.tip(),this.setContent(),this.options.animation&&e.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,t=/in/.test(s),e.remove().css({top:0,left:0,display:"block"}).appendTo(t?this.$element:document.body),n=this.getPosition(t),r=e[0].offsetWidth,i=e[0].offsetHeight;switch(t?s.split(" ")[1]:s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}e.css(o).addClass(s).addClass("in")}},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function r(){var t=setTimeout(function(){n.off(e.support.transition.end).remove()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.remove()})}var t=this,n=this.tip();return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?r():n.remove(),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(t){return e.extend({},t?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(){this[this.tip().hasClass("in")?"hide":"show"]()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}},e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'
    ',trigger:"hover",title:"",delay:0,html:!0}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.prototype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content > *")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-content")||(typeof n.content=="function"?n.content.call(t[0]):n.content),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}}),e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'

    '})}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var t=e(this),n=t.data("target")||t.attr("href"),r=/^#\w/.test(n)&&e(n);return r&&r.length&&[[r.position().top,n]]||null}).sort(function(e,t){return e[0]-t[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}},e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scrollspy.defaults={offset:10},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active a").last()[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dropdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}},e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e(function(){e("body").on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.$menu=e(this.options.menu).appendTo("body"),this.source=this.options.source,this.shown=!1,this.listen()};t.prototype={constructor:t,select:function(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.offset(),{height:this.$element[0].offsetHeight});return this.$menu.css({top:t.top+t.height,left:t.left}),this.$menu.show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length"+t+""})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),(e.browser.chrome||e.browser.webkit||e.browser.msie)&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this))},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=!~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},blur:function(e){var t=this;setTimeout(function(){t.hide()},150)},click:function(e){e.stopPropagation(),e.preventDefault(),this.select()},mouseenter:function(t){this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")}},e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'',item:'
  • ',minLength:1},e.fn.typeahead.Constructor=t,e(function(){e("body").on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;t.preventDefault(),n.typeahead(n.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))},e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery);scikit-image-0.9.3/doc/source/themes/scikit-image/theme.conf000066400000000000000000000001031223313777300237440ustar00rootroot00000000000000[theme] inherit = basic stylesheet = none pygments_style = default scikit-image-0.9.3/doc/source/user_guide.txt000066400000000000000000000002541223313777300210430ustar00rootroot00000000000000User Guide ========== .. toctree:: :maxdepth: 2 user_guide/data_types user_guide/plugins user_guide/tutorials user_guide/getting_help user_guide/viewer scikit-image-0.9.3/doc/source/user_guide/000077500000000000000000000000001223313777300203015ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/user_guide/data/000077500000000000000000000000001223313777300212125ustar00rootroot00000000000000scikit-image-0.9.3/doc/source/user_guide/data/denoise_plugin_window.png000066400000000000000000000310541223313777300263160ustar00rootroot00000000000000PNG  IHDRoz diCCPICC ProfileHPiǿɉ0C0%KC20CP1+( Q0DT@`€ z.@8p궮~^~_rKEH&]C!! a&+g RSuV$/‘$V"eߔCiyYy\5'3HCHʊAf69\:۰bl{IL0kDN?Ռ\d,,I%0JLHYz 27{ۈ!1f:y,1/w9 XbnG]';}8-{Nr8S8)5ޢsϊ,\0&-9js;nmsbbCgpYz:t#C?k$sɇXe﹵;8 8=҉ \gSs02Mi Eh pPr,HD l } ('A'n~p<0 ^ 0f AIC * A yBP(@\(ry @ahz}Q0`5X6a8^ 48 Õ oaD %RDQ(T*G@堊PTu%@A}Fc44B,Ft]nFwo F0011MlLӄLaX : abGv;q8kKeN.Fq$s"q%K AJ$؄-|Bp0J!Չ@b1XLl ^%?H$%ɏ!IHIäd*YH'kG EbG $SR(W((hBzB !NRf;Bo ªӄ ~#BQqa)9/2(2)J5M=.zCtQlj u)i,.Z*mT +.;)'6!N_),YT@%&Hȗ8#@⋤d;R+줢rK}K;KKn~*ђ$sT̛b+VV8,,%/Ul줜O7vqh 6 B t{zMPUtSLQPSQRW RTjTzLT6WV.TRPQPR٦RXjzHGuZM]-DmZژ:C=M^}HaQR&V\3^feUu[6hXpu*uuɺzzzz-zoU301H02xbH5t74l3|oe2*5gL1v1ijnʨGW>4x62jjf7m07S10+34353npin2VVVǭVZUjZɚi]a-Dl#UeV>ScU۽״?a0hݱ Lur.q~R2jյ m!`1fݻ=%=L̂̏BveegC}P6?{p?r~co9윛Ey?T}Gaq=o@ `ׁBzaNǃ(ZYT~x(吠س}gKbK:6ɖ)>>rцr/?s~~XZ\VYt {,؋ઞ_έZívי=_קԏ?dknCEDc)p*ԫ8ul9seMfyKDKl5u6 zjK/_̿Duir^ǛΘΑ]Orۯ\]|z olezפW_LonoX5pλNwcܻu%;˺1qWk^潞y7ѿx{?z'VO㿛{ACǕ&}'M%NL|Tsϗ//g6fj~mmh.qn3 8:5PB!(-ŋ~yATue"!v66^()xќAĚ}@!Nss3-ss_f1| @71?T! pHYs   IDATx{|-6M@ "Th H-Si"Z^mZ/j-⩗Vij k pMȆl:;c/.XrW^3γ|癉bEfƿ Bndz0u8+sMӮu '3L濚L9H$25_cFGK!D'DukeRWWCӴA](!]lީ=zٮaN8RYYIb)t۷/NłdBQswEǏ?)MNNO)'N}v;nBݹK8<BrȑfH$! ~vtH |>x П"l6gܹGt'4;@Fo# 4^={(//'=AӉÑG9dbBSS-.]`0܋۝CNv6nL àǩ;^ǞJP IKKk6Ϫv۝CFf& P_?~ z޽{ٹs'y֭ݺ呙y=V˱c5ܹD>}StEA~g6Ճ ^:lK5LO|W?Rs7\֭ki1|>O^^.YYY^B Hq9XfV ǝHKUUf(&¡`R2\N V*r*=zKZE1 0P399p8TUUlkj\&jHxﳵ,/f\mA6 5iq&v:x".B-rvX,hDln"";;yP36X1: Z^&FmA۰hnj>㳬*(a¤n(=n +vMO|鋬(廷^O/%2@uv;&ftZxl۩k6O05Q&ZjyZxYZyʽ/0s;{n`vr=c=1O!T V-%2u_b2KJJ>/wr5>x<Yb$d:-躎dJ\ʊm.x^< H9<϶gtT7j*0qcpDWD D`j+}3 Y̷O|K:}7_K(d_U|1Œh|㗱3D#ic4?Hiu=[H<3:64#=(!!Hm&@516fjCK`X4! 0y$aAi1!:{ GffI=>p4{ƕ';;Bro0Ę'--<|ddd$GrN>t93/M^6DzN0ω'/Z-ջ rx"{Wu Þ$ "z e9H Ec ݺuc޽~l6[=6~p8L=Z̳OffiA)yi={6 9// 퉀gϳ/PP(l3:oGey=#|YeHWa1ի #MVﰠ7oyHH^^łjrScc#f3cXp:x{>1 1D9Hve iYĶ9^VoO67nxmؘb^?ụ,C5ZcL }ʒ4^"ąDٽ{w28qD1w:X|C^7-##ǎ'z!#vF>xCFffYzihh ##Ľ+p8t\.? p Lӝ(Zda&W-8]6TՄyFU8%?ł˕o6Z(]k׮?D" o$b$i[zyg[AMQʳ>QbI\2;Gδiۯ/:PTTč7ȨQx79|0attх Vw+ckV.Y/S{ųe&? lܸn2^^w8wĽonMlJJ{-Y r*>|y.cl]C̟M̓ojۃ ϟgJKK:t(H- ÄB!0ѯ_?J}]~Yqq;E+^o9-ZA/h{e.o>cxbk# lE @PB9yyezcinjXHIiDb'0ivJT`-^pch=Rt4N ٱc={b|4bD"f3ڵ`0!BwpOl#j~w5?(zd K;v$/F5[*8[ŝs?N]`* \׽kYxw ҚVݓ:a2j8d 0|>OLz9t cZ çʹ2 p8ZVߏ:x[ә*e=eep!8.JxGw>=r+8< ?LAB`npKrŁat%sb>/}#hUW/}'WOwcD!82Y[O/"dskpU/;Ǫ*w+8K,` >w f -&:DbY ?sIY`0@vn.V aMCUUL&(J YVa`bFw*N'@DcvQ) {1pKk} ^ W\zcW*u3}+7]տ34-Kш|Ke80PMxicJݻ?\gG34ъ5<6/xY H Śc6عΧ\{Io^9ûNzk1) UUCUUfsb1Lc㯩x<MreE] Hf '&P]SZzW1Ϭ^`\Ě3WEpqMɭSfsj8pܞTsף+vFu1I;-uvE}p~?VGح߿"@H"]lvaD"YZP@0 l6oS,%'#] :(?.k'1Z=l?51ytr,fb=9sOz9ym ;uYiii8\,ߏjvZ:ĀZX,6Dѣ]3AEC> CyxONУ(z).a,&y\ ?iLl6a;ftpnӳgO . !̗򽟍;r_4l=K@o̹3Fh1=Q Maߧ<`$K@F~qut1΋d"33 eС%zl޼?,Lff FRſpC{xּ-gNG[hVԉA СCٳ{( .4~?^]ӧi&D{ٲe #Fhǹ< ,te7y|>3r[C'oBQv;={$##|jjjzD"ݺu#77|\.VU GeXs]y:ijHEfaXp: MӢ7ƦZn0B$ 1LvvIkކQku]袴h@( B. Q]]biHo}B!Bآ !H\0B B!R"D!DJ$!H!)""%@BDBHB B!R"D!DJ$!H!)""%@BDBHB B!R"D!DJ$!H!)""%@BDBHB B!R"D!DJ$!H!)""%@BDBHBsG@\4M͛7SQQACCz"a(rkd BFF}aȐ!`6O[mwdB= J `˖-ۤs50l0ӱZ] B8e><7tC 9qj R=|Hm&b 6n=C߾};՗B?u*z)J&Nuz$6:+Vロ\L&M0 zP p~_re1aLlgP]T]al޼͛7s7t:u=J}f1n=*r4 #\r-2tД{ Z}zma4ѿS5YSr٬(O/?{Kկ~ܓWiS΢V0,\$淫W8V̷iцF'ڸ\.F_WHzzzJTy{/ѕ{p_3?/b>)8θ9OoY{ik>vCJ͊X|9?6k_ غr)o;n{֭[ɡW^B!"H9u1br_}}Y>C/Əa ?9>}Yˠfnp?f_/_QBn7۶m;iT׬3/CË/r4-=zУT/, XZ+J\۱|N[S@GlF滴v,gg3yda; ٱczn'^uՊYU^&+{"Ͻ5}YQF%g? E DG1 *iL:n4xz~HEQPUL^^.^gE oÌG/~#Z٣xV/_K۳N[S%c,6xxi:̟gjeHI65qߘh-#,& JW| Xĵ3^{McP2kVbOWl&6[ IgɺYtsL< NLTUd2%&(S2%v}=NYOe{ w1hcN?g9LKǿ&[fڷDqch=Rx7}cqŅO? <Ίr}љcd?IbI5G>oRw9J=*C&L^*͘^В^XM.ϾIӍ||&L,yx%ϞĠ^z8p`2)(J^}r6+dm>WQIzMUUTz17͘f, NMNԵ곙EQmWsWsyc/`KJ =~,p7U'ڵU@0s䩙׳h q{1~1] PRKGZ++kS`˾:`-S~.}y5%ex0g I?vTO7m=FknDc߷b쪊( ]Ni7q{~ w<}a$g򠬢(躎dBӴ&m>f25޷)uMb og(&i받ںN[S 1R2]2ͻ ϔynMgQtvݎWbIDATgG\<,O-,Fj@l9}ruI=A\![c^TUĉ|>nigY&4=9mvcsFcV&x6)s˵{8z3NODLxl)ӎ>3VZAד%I`2x<N[@2uyڶ0Ʉ^x*f sYZޞuښ:V/uְGr~8A7:;&fP΢ES2gṇdm+xp)5^lZ&8 |26x hq~/ޚ ^ w7Ӟ:;EQZX/w$_8Ҟiiq{h7Ru8-+ (\[U)*bwt{{xˀ|jfl"~v-G>r4/L}`T̒O_ϰKM-i~zNNWl*& %Q躪d^v#scojl sۧN[[@#?{.^GLh\p sF/b=s0l8s2 2Mx}͔ 1 _<;T>.%Ol;r%Y٥pD\+Y,0cWn|M&Mb'bѣǏvOlp#_T,y`f3_u ))?ɑs_3~=?ĤK%, e=xh~XK&9/ES/j_%C=l_f.\v3>Ȅ3fGxϳah~ev,Mgn>ΓMbvfa7Nl~َ/8I!o 3YYf,4Mc,_[n|gTq^h᭫!ag}@K K߀ٕ@I! i.'$$n>DB9r^{ &0`s~$x϶[pe;;IakikD\0 à?Mnc6mdx<.]JNNcǎ%33{ R5IV( .R"˖-#4kG5`0{0\ώuښx`A@\pL&v,***Xbݻw[ng|d8?7o3|+_V`lYChsW/P'NH$F<NFFѦH}TI0Sopf'϶ёuz.:O_H\EI<Nt}R7'"%@BDBHB B!R"D!DJ$!H!)""%@BDBHB B!R"D!DJ$!H!)"TVV@BJ{=@BgV\HD!YH"w>)xBܹ/'BѬ;wswp8HB&44x62jjf7m07S10+34353npin2VVVǭVZUjZɚi]a-Dl#UeV>ScU۽״?a0hݱ Lur.q~R2jյ m!`1fݻ=%=L̂̏BveegC}P6?{p?r~co9윛Ey?T}Gaq=o@ `ׁBzaNǃ(ZYT~x(吠س}gKbK:6ɖ)>>rцr/?s~~XZ\VYt {,؋ઞ_έZívי=_קԏ?dknCEDc)p*ԫ8ul9seMfyKDKl5u6 zjK/_̿Duir^ǛΘΑ]Orۯ\]|z olezפW_LonoX5pλNwcܻu%;˺1qWk^潞y7ѿx{?z'VO㿛{ACǕ&}'M%NL|Tsϗ//g6fj~mmh.qn3 8:5PB!(-ŋ~yATue"!v66^()xќAĚ}@!Nss3-ss_f1| @71?T! pHYs   IDATxydWy'{žGdFYY{T%$ >0==nۃr3x>Ǹh0; `,BP%^Q߭/n޷DV+SSٲD"irikZo0Mn\Ї>|o}v,zՇ>}na~{ӭVk+ݨ>}Ï|>myyQ, ilT*ŋW0N0==X,]סi2ϝ?g2 ޽2 N: ˲A08D">} Ғ#hۨ똝sFDXT*((ػg7&'' akggqDD1D!@VCTF\ƾ}2/\'O" ! 2;,]-صkk}COjf\ŋΤ1Ɛd`4hXX\aF|e^d0<4QO#;8H8MӰ0PKpi `|bS0b 4M|>c}*qk G_ƹ'?=Krs_gN} ܜJfJ uZ&b|@&#SAT˗1" fMӠk~?~?._L:̱1 "At `h>D"\|eaP>Τ^qW<?]"h]Kǻ/}V/, c``~jv @}H&fI6Fv4AdYy ؖpRv@ 022" 2U(E7#lBK`&t] 4sX=uou_\_<'4 ye@r,}I[TB2NSM@i0Bbp*T*!uG Tf绡NxeeR2ǑVe:y?Cow|z;/ƹ}?~>s;>7cG$?ţ'&4'w~-.۟G9P4S׽2ή܎:/|ڞwcG]>8x׭#c,ٛ1,ేգ o9<?hn?>;P{Dn:~Cb4U}xUe&BWODVnB+Q,kSa@ 躾V|]z(RJ}`jhƗ!4_v~Oޏ?C^vFDPTL&7If'_RA$qD"meFQQ&7#q 4 4QTF aVԁLh_տix?!U l6aYX\a21ϝ 2M4UX?}d8ЬQkZƒ?@~W'`̫ė@,e_ղ RM-o"e_G}_a f 6;#Q>`p hZBuwZEАch6e꺎zVa2,ZVWiͯUUZ-dFMݢ@ j@C+£9ܕTgţ}Kϋrc7>gauuξKmV G{;tc:HF IէKX]B ԱA[`<ք>{cfYGF> "#oMD\F.ࠫm!N2cӤ2Z"ϋ7@&q-R c``a@3i&t W}Z'DTׄ hދ>?*¯޷?{~;>~sh&0{ߧ>g?6v̞؃gAli]%oC?}4hQ|GDn(;!46Rf܉;M0xUA"IpA;wk*( H&b: FRIK$:vni R$g@:#Lz.T*X,"H 2ͦ(3#هp<_b h~aET5(V4bq&*4j}h54u Zk4Ń0 V#x[t?0F-SG0D=x,(}`ˆ ԪujaFhV(Bo#6ׇ>(Ξ= $v54MA86~YmUXUUf>$gG2\f^AдC=u]e*?ӷON *BYL8S5&n˥6Π9s8q%;: QI)?nUY…KXW{ӭؑ4Qw'@@,! AI)?>` BQCٷ>S2+F +݊>'|w_6}C^pЇ> ۇ>}q>CЇW)@Ї>JЇ>U }Ї>R3>}xB}ë }C^g}C*>CЇW)@Ї>J /Ca߾}]+܁ky^S9ߨYnm3bԩvmsqTYNs@/=fG:ވnc:;̣+޸4t݁=N}q[{Wr:S54l6p1T*X~XrLD<G&ARql.z-';֫"/b^^S3׳ȼ\#^?]c #bn=77U龗4*k;ݴ*NڵG]וײ26,B殻b|z%[!0BLW6mt-3^A/+ƭ0I*\ӳ^tjDF׹6K_{S7kWxRj^S1X7FTX9'#x+@ƮYMT Lkkk[,me0$oɼ2WeH^|i"qy!v*b͵\bhU"z1Qx1S IvuW&vύ;ڜ)_c@o¢L뻼 'Lep+O_8PatGmll mu](/nNJ"xY(Nz%^[P/"^NXdU'{^l*(^)g̖<eDɝߎ>!hݧmdp|dY߿30^y8HJnvmu$_ܮ˦GPpd݋/i0a%Cm\N&>U4%q%_4Ucw˚;SCӴ.z!2=|> u_M:a؂H1'+¼iGT N1g+l7#U:/%^LY3y zY2KN‰tg?nLdJBT nZA SyrYpY/-N`{/L+r^[ڳDǮ ;b"g*Vw&ٕ߫"(4f|Ĭuq"^Vˆ'/D>kY&mXsI3 n \öWD&nWUWBĈzoDLn[=^Bzk^\v?#T DUDK*ͯV&OaN_wr݋+P1/Z]]|lL[6߽7¯"^^U^YEtҵ[2A7Ptz7BZ^WB&;I!ﴘ{#x=*UW/Ϲ\ T㩪>Uvq;GJ8+?4M36G+lBtܐȍB̽aǯyeN V2hHnqN=v^۫ne*~^愷^y>UI/[[^qMubJܩ<~y퓛#_8 ?g[3n @N/辝Z m|-[%XnD'Ok/pl{qڹA/^zu^pzk;Uk+Ӱ+ϩ^#XfFq2wdinh'ܿbTy}-,PWdw;Z7:&^)inQ꓾bg\nU9t_n˟#*&iIf)LĞoRWgݵ]t:8# -2nlUwd盪|/AyD"D"ܹ`8vsGso& ð͎iؖdp^{V^.dY!W1']ĥ^I@/[xD UԠ"PЩ~]P%ds $hYZ~jN/^lNsƟ7 ccc8r|>\:&籶d2CAuT*A5MCRATz |>|ALLL^|EuC8@;}yvWӉNg]^IvX%]S!zi8IdZOzeb"N̎IAHi^Θ >i.yqߔpƍלnhhCCCC:&0p6.,,`@V!7 6RLѣG1::|;MB~9;迗 ^`Vn7B*׿\F/ҿ.Qn}U-RUU Ӳ#^C}])&ː2aE ǃs[0o]/W܄v Ї^#3NT }k Fd`YT"!L6Ġ#122\.e&@ L&ϣjattBR'/ڭ+G?V~$uޑwĝB%BJncNpnmmG;nK*ED_ T1[nRmS<0' k\w k^$ \.P(x'X,\.#B4|>4;6ȷ/3bMFDPDP޽{sN.N+wnv=;00i ,R`}}R >+++[P(P_\\D$A0<{Fh4 ɩ_~hR iZ"J~7>O"ϋȴ x 3/Ѯ^a[eY{SuzKn e+}r!-\-6;ܩ-rƉ };j/ NҒqg<NQ+ws@ A]df(7<*n߫jeaxxFFFi;.]^tѲ,elll  "#LT*!'{<74ׁ@b"]zaiikLhO}f2b{/ |bkl'm1ҥy#vUE8"t[U,[VǦ*?_2a[^UpA[7[P3Nu|NNN"!#V4qYxR9F5޽bVT*h6P{ i7iAej5H~@$I B3XWcz  %lĭz[f;1U^pNϨQ52qRm ÓV;Bv!^Q,S"LpkL 2 4FGGF尸Vfs!ıciJr }' ò,8h6BCu;8ϣh4MR)__vWihh4K_^7"rH:*a]!nVmv ̉{?Y+2nQ#M7$%χrSNM(˸曑f100'xV T z]OMMahhh~˦YЕn#cee|B`~כ?J :nrK*TE2Q]ٹb* i: NY".6'/G:]QR~?k"rc}}ZmCUg'x8 >a @p |>'3dN4ѫ@4!NjBRFƩSij@h/^ɓ'166eٳtV صk4M8e*`n0Pՠ`v~9002258p<om;gr: U zaNĎI#^uTq-iTInⳫωٍvT*]v! mBj0Ĝx<XcǎV9JAvP/ 022d2P($ V F@`c[]]EXZp ;Dekn}}:WxC%T |Νd2d2|8}tW`'&&h4/ncppi\.cii ccc"OՂC>`~?6:"H6)D"j5ᦛn±cDx).?JW߫dpvܞU~W!:eʃ(#ILne¯~˿B%Y:۵`dd;v@ (Įj g7p&ۯ:=cyy 8{n$ ?wu]!(Z"ceeBA.^?O-Icҽ/܋ & Xmܿ? @@8F.C>R7%ȈW,qem>|T a@44Md2b1籸Gʕ+T*رc~?&FFF 籱!ٳgQTӸo~(z]vm$B{n)|d2T*]6'JvҴS잱[dn}S-F72#x-~&)(`JF"2D";fQ*裏 Gj TaQ> "ܾϥriBalllnc``x嗻C)x$ arr>XYYxt]GDJ723>&F~ bvj]pc_1>>e\ti|bj~?Dn7Z O<sNa]vL&g'm݆Fl6a~~^0J\.J"L+++|2pmadd/_זɚ+*{׎@-}ߏx<.2[ݒqZDzޝ|"0`Y0yrXߏp8jd4w@loy[cayyyӜ_lT7﫦ijPTfV%(Iॗ^qBĽad2KƀgRq5MC*0D@4Z D y1eLMMufgg71 $5M*&t]G Xu3P(`zz!X%lTv(;3 LN`*JM\C.}݇O~]†ʇr&7aGB:ٚbzbÈF|H&]&x&ժɵkVnNVvҐ@;vpgvm߷, > rW$-и[Vh4#tGp&ax!i01>>.*bZ###8ϋhٵ*S`0(8>X^^VI6z4 s %$.-0l6rFr,lv ?G  327_"Ţr|i& 9X~E.O;Dyr}A4>|Z>Zxm_4b1%%ij$ѼJ%j5mo{/)뽎'i;vl"Lvir˗A!t?\K$ UfSI$;34ͮ12+/Car ԉB!q^yiXXX@.&XY悕JcǎF=$H9E h,,VWW133a CӴMvp8,N*Jd2BҔP=!VTj077r={駟V2a*ljoǎmJ%vj9SIDcB-h2GDFG(;H*,MS^e'˄D$h\T)Tu%`ը Itozz]h5/=Jm*_6 Y59Ke1J 9r'Nŋ7MjRgddt[Q*ƞLSazzdaiih4Qua}1, ؿ?N8|ThhTC)NtVZE^urR)TUܹs]5*)WŰ<t$op p|>TU!PO"ؤu~Xjwmh'O⦛n“O>i;|+Ķ*BO67O/! Աdq,K,[/RcZ8q$[>=/XKeJhn&4ͮ<$1X,օ~My,ZՇR oxA}ia$Ic6 P(@:=0L&#'LINѴ3K伬jرcml/NNbb3* !y]^^F ;Nܧ~ZdTݼt:bM0>>j@ %sMִiめ/P(`ee099)hkmR Q] $q0MS0p8F]vuݧcΐ7p|˯I"J)T咤%;ȄDFH$D"K.Rl*ێ@:,hBb ;"tccB: K][T1{R Fhv[HܞM} 4$3˲Dczn# v١:<(>"ADQQ?zV}ᥗ^lZ\\ĪVرc2&3<d$io;l> ׂHƟDL%pgM FZ 'O޽{qaq|_8i5t= ɛS(w56VVV`Y |i4/ bQ7՗1MZ T gΜ}W u/$C ɍ~&8=K`gWd022~X%6fZMI,<ǻLD,ro>:Avڅ[n˜ѴNX[V" " !!cqqQHYnL@X7LF a Dɞ- I4\ S]˲DHy?~4P;HQ uC4q1m6[&  qDuˑ`166X,)ӋϿ<`L@_hy<3 vڅ!RӮE~a5 񗛂hZUYrxC !{aΝ"*@DT8QnXLo,yik(Űх|N\*TZ2app>OEbL슧j(d2BXu"Dk!iyXaj51>f\.|\|"EL{n1O$QATD׻( b Tϲ,ݤAj&Jsh0s}i^hݕJ%Z-?O jþ}011|76]{w)GQ~n,5 omm '/,FcFpC'DP &H9V! SXYln H[7?D"!89-P"48I4>v[!¦K~? Hf2ƆNѣV(P.dj\s!LXe!"nb=N"Һc||\NҴh?!L:jb'31eh%V;wbll >>|X+:;; Mp=K0"*NyX۷/2%m"B!OR{\N1ʡ?22" @)Wߏ\.ğ0 u:?Hˡu0d0;;9:uJe$ Èbɴm!`ii vjj.Ok\.no21'O/eiɑN"@G #_ўBbJ sNON7s}-`hh]m$fEk6]NJ"$n}{oPE#IXpX,t:-4+bn/.iZ'tvuP(I r[H{& J&BРjp.]$RZ&rHR2'~@pK|2( ĉ(JmFs>ܟGJcǏo9SWb~b>sUudD a,z!v vhh;v˥uܕvqMd$FFFlml1 ;l۫j?}l`wqGWc"z6ժ8Ӕ$Ci~Qva^`Ϟ="2LCfrDSzEKe͔!LPSib@‹|>.%ϋ莝;whA޽cccfD"baR) bbbFdRI~Ț.whhH0>"t KrPL" >SR}{;5ʗÃ!Hk$eghMk$,-- )ƒ,2]$&''m9eߐv"z^|Pc,kvkᄜ0\ʣt]G60'Q]FCP%ӅܦL&jΝ;0>>.c9#EKDl6?>DL&QDٴ?c&VWW79depVU1޴MUTP iػwh,O>Yj0`PPb*B8FR9_fggX,H$A1F$r~4b~E,--attyq_FHR;>>P(T*%XLDXĹsp={.]{D/.--aee{,k1O9u,s $ 9oBJDhWVV`> } $BI8W> Tz2u󃃃ػwJ&"+NIJҒivv]G@-J]ā4"4ĉ'\Ul>|>/,mfb!gt\%Oj*$H$h4J"?Gy ]HJmC*]qAyGpij ONwl&:d:ǻFC(R`qqwy'w}tZ!%K&pYJ%b1,;&y}ïʯcXsZ:}Y,2~?bئ|,M;Љ𚚚B49tZŋqBM$' T*. Va``ccc"L4d)l\'|_.СCBŤ-| Iʕ9.7 JFq0!NFbt4vKm0ۖi)i@'hZBꞛg+r]rH0^[^z x\vV%u(ʏT$4B d 1[rTǏ,GQx,?'THqCCCHR39ZfImmqn^7Ɍ5"م7p! =W׻9i4(J @6THb5BƻK48c`.Y$DJu<&\ 4 ؽ{7^~e*%-V O "4<:I2L8ť?)Jcʁ3!iVVVD߈rӗiC tsD=[J}}NvxLZvOMӄVB!!nݻ &p^cnnz+"zm( &aN4II(pD6r nlllݵw`;~ 3lzn߾}]R'! -21"d sQYdrXXG Cp͹B&I"Dn2|8wܦ˼| HRNȫժp2 _xy`rI&X§9T*u\v HrɤHKMiU8MĝKjH$"Ž&*DP HdIOuqa#18gFfSl0$$T:1|3d (bG(8E Cxe 3go>gƊጊ@DصkjaYqQ$g(Wn֍F8qĦq;9{ k7e|>sΡX,b}}rK2|g/p-.9C@l6IRhC3x%)Vyfmm x+]\&P&>1Z\#SEțSHSx!xi1Q˫<$9Lv9Q(%3&MD0>>.2щU{=y|oUFNPyPϣRwRs'n\&zϋ9)0* 5.h^xDFMyw8s\@SN]ЖeabbasoA䤁;ٹ攈A$?ޕvʴ;{},I\JE@>f@ xvW;=-˺"3O9RMŽ$IR~333]x\Z9Kwl(TDQ&hҒz(B"D; IDAT>Hǝ/Zm/^67Se  b8$XdY `uuj 2ҳd榠;v`}}]HϲCQ4*1KaίQ]k#ND29j5(Vl6X,ymLOOٳ@ZM7$puxxXh)Px̰>ϣR L"HBoYؘH@&d{9YO<M$T*H(Jxgq mR=zuAeyQrii /_ :l NҳmTJTnEhIv[BBcs[4AT<$)d2x#MÑ$:2 @q19|%$!')150k.<34;;'L'BrM-ɹ"j$X"f$Un9KKKVh6عs8 $ 4Ȳ96N4M7lT9{ml6T"k9N''NNTծ{E:ٳgJpw#  LrB ( عs'Z`>E(*OO=wX,l"`uuu$e't$㵯}-ժȼJhT˗E!&;>tot]‚H='OȦ ܞqNK_ڦi G hdBHA4IlDHE']^=CS٬`2h Iߐ<7%p_ ִN^q! - m<=(eYNqL =-D8n8ULn.bʰJҡ "*Ɨ:{(t}}]֓C'& ĉ–8hȌo>Rٮ]`Y"\`0("~ɤȳC*wm:Ciٳrb&&&>@6":^|E Vӥ3Vˌ#5 4\67{e  nB +p H~ETUqNjzAٳX[[Õ+WP*$>.\]\\m&b]=Y#Sa"Ja׮]ɌLGt6gsO5<DV?"kȪuz}C]4ˡk4hA" /$vTmqLT*ۨL+cl6!f|<蓈ϙuPm* @E9ήc߾}Z|EH$ _)e,vo>oT"Fi\|BZgN aX[[p>77'#,1Fx<_N<)^399h4DxBDToȑ#(J"ȇAO(kZpw2VWWųbQhzE{%ԆEAs8ZN*myf^BsDtR|dF+HUt$MӐJ`ŢHEБqNZ70+i -iT>NиiN\uOibvv+GC!y*'3.;n]4lь te咭$QzO}a:LMJRkGM=mիǏN+J> @07r)Ґ6EcLsH$DzOE$ Hۭjc=&pG9{¹sD>JnF˗B;Y@)iN/dYH~GFQ,// Pwuȗk.:uwǏ[ob.D˗p0:< GTV|!<'!SĬ<, t ]mSa`[M@ZvL(흢d' HgŮOJE!o9ȚH;4 wu,§>.I]2 /[nqz8Gh#gg4 .2l}K_=#Ə4˥W Tqӆ)Z\e$i[ޑx#<| /F˲D pmr"MDsppPn8ݑ)4FK4KvتrbD"rġ:"$2LWt<еIX__ D2{9fN:J஻GG]]C Ҽ ٟ> X*B6ŕ+W~?=*.\El6{ <044V\Qϝ;zC!Ɉ'NC=iNT><. u%.BdneY+k$ "'*0 싧MR"+M*C۶Ϝ9ӕ̋C hҥKdBP,3߲\2f$  ic IEbr{hh|x.L ܌Eu>}%3-\*3 br޽JO2qpU5M<3ke]\  lbyyvT`7C1d"zYٳFKKK",;ˡT* SȬԩS( xD[ ggggl6cǎP4NaX,就y7!mBOy`(!q S3mLֱa|8.\.D"ogSQ|1 i!ZV<q"Ov@"$a ID>'ILFlF!(Onj&\s54C1֔rs13GjPJgҎL4|T"#YsS*'MZ3lȈ6K? #J!N;$V 2ĈpD$hOȄI;l7:PQc*JX]]T*0 Cl3;;+ًA1 D"biiI"Ţ`a|_m땩麎O}S9ay,//wgJx21,--accV XL3>KKK|0!qIz^AJϮqn #3N~H"Pq/94Ml:Dp!,p8d2/v6r7Gp,5"d2)_}ə\a*U?(P$INĀ15L DB 077z.@&A*}j"2"Nthn; ?_WQT!`$leYEa^?"a[\@χh4L&#P:hll drVa;}׭ؙ gϟir)M-CR!H-E#I셚 o*?Wdx'pi:IrYH4cT< ),gA7!>JDt]ؘrgig?+Ƌ4"t,2jO:iVZ􈱒ɂ7[ϋ{JsssB4c ػw/AzWEσ2*N<)AʐIk^cmm `Pe䧨VX^^frRJD"|>/Nݒ5 ooXӡMk-,,ujvk'IAKN<ϋt '"0ZB $ɧѬ @<eYЇ>e֖a|Aےډ0`pٳCCCBF<0 q p-l8!ϳfEµ ַ%b{tX,?B n8uI~_%AhW?ݧt.\ (| -6|K_>=y˲ "xYf-jRͩ8a'>!".&'fK/V[oP#"Mf.2mP| b(620Bڸƙ5 (d~LRw e;CuE3vy:u '-9?J~ɼSSSh48w<^xV x~;,> 'OBTwio}+41::v d2qHM&d^eYŸNq}_F*B0zA",//#HW:q~l^m?;CȤ΋=O&QI}݇|>/'2B:;y:M*W4ŷm|zK9rD*Sݻ7Wj7q/!]7THB C'Nn8n'ǃ0rҡ7+Q4i޽SNumuAP9J%q^h1"i1|Uɉ ^dM||a9N=MpwIT2?'.ZD.ѣGzBoQ$Yj7g Ć"< fff6!jN*1}ܜ ccc]뺎/{u\{򶓻,bHuYVAV,;pIb!qiAkAG8Al IȱV\d TcePHK.?w{_\#f/^{&j*"Ȅq"% Έl:oajjJ(Qo FNu;F'ȜO*>}زet!BW(L]Z\m&*)E# JRV1+A[ZZ¯kJ@ lrYDiYTWM$ND4Gwe.J)';|aVR>ٷɮu\gk ojsr {9ٳGs Bpya"79GW^њ@^?P%=^,1?? Q*p!"I*pГĽ_|Ӧ>ѭ)=v(qzؽ{7<=>bszϮ謾>P(ॗ^·mӚkK^k$<ʡzvn0>СCx"v-6"(9JPVqF,,,VaiiC^ĉswzGOOQՐ&6RY)0.^(r x("G<-vx!s. l'N˗b֭_${lrݴ1̘q|9s#cnn=݋1qdKiC9IS >],qI<ԥWYP%TY7 CF1>>aLMMGxGy$Kh4p;wN<16kKxӘ 8~84qw^;Y46ba"LP46oތf .p)!>.܄ tкou&Q".\2vڅuPNX8F{n#Ix<6io:Nq>cppbj5lݺ{=,//Zo7*a^/,7qJ擙ŋ#n?A$I,}Ef*! Re{ aߕcU^W_2cJb i\b1$ R),,,رc8{pLR[i2W%4Llxx\5`0(. o{tVڴ]oYMRiLOOcvvX  ,G~p8@ ~={xw~W^LD}G{isJGTi'ZZZjI|7'|R t"Of)x<lٲ[lcIU'IZz)g}:*ˋLy޽/PԵm6Q,2 O=G+1K [% ߿w0cLrS;vǏv1Vy|hǮlcQ9ObP{Fkml I$bwCK/s˾jSwrS.̈}}}lR,qqf/EO:1p;Wȸ V%T}H$N1:: 6¹(¶/\nL||&WXw^V+r(L$=AU A"Hm$sHZET6 077'Lg8Xo2`bbB012P^r6ëWbvvlvd'ƎF1W->il۶M8yږŁ|1se _& 6 JP!"e8:SoE@T #p㧛*9*j u풉jnqV O*Z/2MWd 1,@& W~N;{]$eE\t6H\tkD޵F|yĴvmvcO' \-;33#u]upv,];%Vc‰(!ʗqԙI:A7,@76Sğsx9:Qnˠ݀J Y _6'9TeZI.N=.C:Ԫwt`V'tL_E|7݂L['_57wBuYA7c>.iru kX*`fٵ[2 sT`Е_kϣx]v/.AEX跊a;/ex4:0N#svf&f ?8m2ص[GɅ@ IDATS}TL"N ;DϯY Y.Gi T`:VL};MvNz?@aqJ3HvqӘ98;ϊZt/'A%i*⯳epwUmlyM :'zjIM׺M޷`@gv<)US 蘀,u\X[ \TAۑ4NXI\ToL8$y?U}:BjtTO'`G֛h߱SVSϟәrN;RVU5~VsUg%ekݠS%\+ĿhGtV:+ɗ*P.+)J1UwUv"9YIr6UҺ^=^Mw֛̣+ +n"lġUszcDhMLɼjtŮ[ڼ>"qlĬk6!t82puZ A˰"̭s!PN+B+[D#WN[E+|U[q;V.z!?H/Sdiv;ѩ$Df-+&fDŽu vi5w9P'Qfj<`ݳ['1VkLéڊǤtLI8Q @`0 ;hg#SΔ`%E[V^SF pll ^;Fڴ"2ӎ ^+sj\l9۠F`Ť龝GwSvϴv~: tu:33NrnGjt1pp@uЎJ{8Be@"@O3dNXi|5veYIvRog8x}:rĹ282w^o+9J wtĉ}'CLt_WĢC\!RIiw@g6QMdy&NRs^.py3aYוe5E'Wo*vKqo(? W' j 2N j]I6Jd\h{O7sVu;1*ͷЙtDZZ#㘭\Sf^EHQ :}PS @d"7'xꛗktT׬$y;ۢ[C2E?jg*bH'UN$kE8mhn|:fvA~¯˩v$vBosw@']:ܝ03;Fg]I*I=}*yJ2L=*m@v„T;ս.[=KI@8w;겛42Ȅ]xu'TⷻfǠZS,UĂ߳j3xڣ+߮nXXTm _G]]VwT .5KN"x]vTW=/ (VÁiV[qڵ;V%=;_I:Ukyz}"2#[i&q*!P-0꿮-tiՙdusN2+&ԭ/X@>Xapjj$N>%^//]NN]UN6B2؁SL~Vuqh4gC ]詮 Ao8U|+WN@Flj,z+ V't"dP}[Z2Qv*#b>BW?˲zFj-R'Yҳv1:jS3hwd%9:BNVJYЍW(FZE\Gv'q9v^IH/)WM[;e .hte#j&Vr`s+Ҿ']+UI%q[IbvI8:[TTpӖpVX&0NcU  l6fQ(!&LJZRW ^t E.'RF⭂F4v&1'VVn%[El;;qꈿS[+ox:]@؇tLT+ӁQ"|(2]}Umi;F*BOO :L&I.K|(j 0 ~LOO[iy+AM5]? ?ݘ9Teˎḅv& ;ǦxvUuR~ҿovKtBc%i'!]}+ T?*9uN s]MO&a"Jappa`dd^~,^/<|>h4PvL&011Ñ#Gm'y9qxL?V9a*p+V݂i,? f)~'kExtyъhb˹tdNىN5XɄ_zG5|0HzWF>'ZIrI0 SL:0#g{^nx<q/aii ~;qim[1ּߪq|'Bo]=؊XjVek2TgE䬈=;uRsSuOE|ZaV Eu]Ĭ\TI [Ex ;qʿ6_ruR'(h0 BHRذal" @\FZ˵؍@xT8\.x<yٳ~`b2U}tf^~Ύpn89 ݀S{w+e8޲@f":*B":Nڠ#5ssMFuR?ְS6q󎌯(' j!s|ړy6 KLmLU&}}}Foo/ @.R?\!A Z Gj\F#o[Sv;_M*[尵YPi*^{.tigayB798 n>yi>nUE0IV8guҘꞪ=Nz}t d\>LXu5>"ߏM6!JpҺ8c"@{hbfKKKTD ں;SSSVfTfwd'4:5yDˣg6:oS'"ƥ"&]GP4($"( c֙p),,,`qq>OToTҿuBN L@:""VN8'f!;*׭bvfA5ҟJQ15]~y#B<0PV0@ƚs[oŏ~#eZvUοD"H$-[A2 fuYT*!9/'ҽ! C98h+TQ<(JB- "+Mm۶ᦛn«x<Lt *_'-s)T}yBV,!322/z^ ve~n!#Nc||\ o===d2]v0 ,//̙3xw1??o[/-vkK^7EBd2~q\.~ux^$ L=D耵ex^ >Ry˱Ha bƍ;+U`gQJVA<p7bBbp\.U9r/^ŋWqp@PR FCiPH5zzjXZZB.C"8T*LOOcddpa+ ŶmF-nѠ|#;BT*O}x166&066{ɓ'MkMaj]a*Ν LR)Suak-aaaAQ,ECP8qU|@Rsj/{+6zL"f###x1::jIK9aƍdTx:%2r"&h ˭VjICLHMcgΒb1lڴ [l^/QױeSj ߏVŘB!x^㳟,~R(ю |5nĹ-}>śfQVXXX<ŢЦ5H$D>XE +E,.."nmW+l۶ =v)@|Md2H~?6olGc0D?6oތO?^ة~$<__+/͉߯:sCN/~QLL&~d@@LZr,6k?V" nttX É'LPrIt:O}S뮻DL!s|Pͦ@+$R2VWWM*y皌 ccc[p]w݅o{~?2:-d鉮9#r=`׮]fNUDXD doD"h6(JPVɐ$p8`0 G5m̚&gݻWX>t\#fr XKV.qieb1,..T*attTT*%ʆaҥKXZZ­ފJ"C,6mڄu ZѼy^|G&~3d2a\rǏK/r9J%!R>8J%abbɷCOe g'Cnqo``q]J0144|P,RUܹS8xXAJFP($7 M`0={ɓ&tmׅnDQ|+_A4mӤm4zf׋͛7cll /2^}U,Ro+O2o(mۆAx<AժUDZ?SN!jeM@IǃADQ ѯD0L%& J!ɘ-j2 _җ@\s V#C`PhĀ5̝4ǣ("0kd24M\t$l4 B$jTBRf[nEX|\Hc"n݊>ϯkŮ䩩)trp8{#ΡT* 0 LLL`ƍkJ%W:T p---Գo裏X?AeǠb\.|K_aa Hh q\tvAS0 L8!rW_}O?,.3?Dgg&3%FB b(p-,,ņ daO4|^G:;@T?/gåfzv㓟$o§Zzy&reRVQ,FH$eq@G">)\|/^s'cGmD"Q}vj/귿 /~H$pw ='i8Ċ3Q rӃD"a ]JL0nVK '7AP4) c-?r(9/e.\ R)1ۼyDZ65(xnf?Զ}Dp 7`ttT ,~X,&˵-U,MϐH~*Ÿ\.aϞ=8{,Ν;$nRkYxޗ}|ʋ_ e$ d2ᕧIL@fZ DP!4B]Hz8pfff;ï?m۶$!&yOe"[$rFVC*_Olj 8۷[nוSl6zP(d w Oo, G;w?1fffc "Xl#- 79J+vڵ ~;&&&ДN]E8F86T^foo/"x_7 p=`nnNh rUfWbE.qfw0NEh }qqsssX^^D#lP5IZNG088- T\n2Wq! 1\px<>1a|DZw^aTԖ~_nV# ٜ/^M6VP( ͢X, xf7 ,//c֭WT*RXoߎ[ ģjt籰YT*b1 pS@fΪVjyX$]__6nV4lsfŻ333^HCCC 8I:&SAX\WWWe>nVrEܹ}D&ϋ]τ a%J&+ͳD"ݻwc&0km ;eOdB#n[F]*$G[9^YYҒ 6ȄHţ lT;"D4>>.p&h 015T}H/D,˸-rYMFZ}}}x衇)"VT*y i͉#rs|ۋ|3#++++xׅMgzq  6LH9GV͛[fիW\3cf fE`POMMZualذA&X,PX,f¥h`ffFA֨61p8,M3*P1 ļj4XYY}pM7arr###HRzx<B4jLMc\ 8pJ*tlUvW;0w\c333pΜ˧"Hbܻw/4._L@w}(ēx[ZfmVBjH&s),@Y dܶm<k:['X [nE455,J"˗aDžIB!r918no6l"#Fz'Y]]>ji4zk.$ a)3.\͛7 \P{ili {1r9B!LLLmÎf,]Mgځ4vu:I&bp^/, %<2"L>sNlkY )^\b%౻N0l (Z&|BbQ椝CYZZM7ݴݺ![;LF,2`͡xӄ0Xr3vfJzcX.aїJLFt_AH1x^`aa/2jm&,1eړBbxxXh3:"3\tzݳ`Ľz*\.Ȕi$iBA!IӤiy 46i ؃ DQ _ iD|^$D'05ɡ$xٳT*sh>2dF6M|܎Ο?sΉg)" @>*|>I&32d c-yJ n g $߹sK'pX~m7ہL@-v99u c- WBL>v"Era$ & Nx 'E$Bdߊ3wY_)I%pDdP(PVI玧6onRARA$M7$ބ՜KR|ӃW=fϟLZQZnf21s"fdF"-1I4dSQ2rۭ[ x7bd4γBoo/ժJLLAT&giCc2ٵ)-хXVU\|!d" -zڐ 15qrr9$IŎ>dLLV _LedU-"ܔB A9FplVp2 E@H(Ï$|xZ di^uDQzN  ~L"N),q@j_!bH=Ȅ@eQ*0tbt&9s˓x0337xc]FG+韛~(qk'98dޢP,U ]~<}eS$ -Y YuEǬW\YH&̙3H&x7 IR/V'CNВ7K\.qLXDX!\!#<"49>@z)Kرch9Fs2#:# B qI,--_-"U\}}}S4U(Booo +ʮwZE2}*k 6WA.y(|ރ)PXj,//4H m5"ǃcǎ ɐF#TʤzeS@xZ0iJ633 .9DB8JoxSjD ^[]_$0sh.] $I_0k!h6|0Q92IDn`(gΜ3 .!|BNGZqP]<̓G豣|wX]Z9Cv{allLle'zE6?p'Rd2ATDO!a._,=OT)$,NsQp"ܹ=SӳDejhJ%,--fDԋF(Ҋk ʼn'pSk^e[ZT v؁{X jr?(Jd2H`H'd<{r2=zTk~kh HdZ`0hr0N1;;+R$0 cXy?I3`X%W;@)2k|nRW.r9qnzzZR'\`t \:yK:WAĩSDW4ÿ9HvDsF!@H` zxgSl~^7EvqjLRrN(I bD&&ZNmxM1Dm4tŢ=l6E($`fX*oNTYNJgϞjx3`-Ä{Iz)h@8{vID"ƚ6k5틴yorD!G  $x9\ L0ifqq333JEnM,,,C_(trrRl~d2`N&*3nJqO2d&~?ch4P(á5kD|9bb14 '?1MU^cvv>8gbb Iz'INdH&bܟ!i onyD":tLٌfZ.ӧOc||dRl 2 q$,8yF:|mq r̰f=k tU} z#ҥKbSa" H.e!+܆IDOP/uQ,V1b(2QD*L̈QQr7M瓄O"9|xQ*lD\ơCя~T0ޕj5B!ƏObμȗ#S%Yӣg|>@CyVTp18p@0"h?|*-v!&BxP`פ]}D_$ <:ICr"%^8ۋi9rD>^a1p@0 `VLao~8q:ժ&p9l߾])D|k4[ HA*dao&˅SN^[V+2Wtt%ȝUyxy Ihs)M vLed#IO>ig*uL7+|ܱHUzz3Ggۺn8qBtx&ĉBW\3g;i󬓲}_7Gdܹs[O\SO=%BH F(J"~_@QU2JiAhTM'7{Ii@SdYe|%͊P( _ߏ={ছn¦MJL&NQ*JVWWd:lbpp;v@ 0jkk9H#f'K46yM餁5sx ZAGydHn+M`VY!,3"< ׋/ M6],,, b֭b×RFPJ2?s D˿eiDeR1@^ѣGя~Tw%r,p-i6+r<J{L؂ TT /#"ـp&- yR!OBea<゠oYo{ wy#rdRcEŋE2e%/ͧ>?\"' }8z)x^q<8ʕ+HRG _J^0}AqK\VWWD<??ͧnCիW[o! >(WqQN%Z[nikR hTh<0\.}Q\|y|ؔJATÇ+Ny#TTB08"\yO<_n>.p&~ꩧTx\===x<8x D=:R,S(t"Q*B4E.fJۙ3gٳ&V6z æMLϐYLCD}>pa`rrR/OApo} NZef$@ ]a*_(;g?uޑ#GuVXˌH1dϤ"z^~'O$-Ϫ?dMRm0J&b^ܑH5"PK~%- pee?0==m&t~nh4_qN$7"C52_ИP yLdqALNNbrQ _DzzzF2(D4O~1\"|/"}vرOIҖpGū;v`ppP[iNRyN_կ~.8AP^*w/YdD:n 'lzzG r-}2mPi*<J%&%;U,jߎ 60x"6^@n$q8pϹ;&Ka/8#JߏtZ)֒eɪr4*˸r *8y'ꫯymM EN"ΔDLx IDAT)t6EVn7{9aB |U 4L.oڴ v/!իW{!cΝ"3,B;`1&|I<31{\+rbU!j+C@\IE V8rrG8?:)3L=&Rume8qcccرc* 1<|3H&¯Jp 7`vv=fffp]w ۯaW*V1 6ޕ#~ߘp'_%p{?h6xV^k*Ffr>b~~===bHEELr 5q^Rc8N:zK9TEpU Kt󘝝޽{xĦh6׶F #ZՐJ˅iq%Q71q֜«"{$\.|#ڦ],:XgTR`FU@=GBdY9r۷oG<Q>$ݻBǏǾ}"wb>B!\| 6{};d:);2MMMxwvf~b4KKK®Ng4155BsݚR9'LRn|}hh=N:%·LIsUl-GDl6oo8|iNƜEj.˔%Xn>:U`5iޡr9LLL1x<affî]"֢VVVСCJ@u vA7ל8GyF}y?~jz+݋͛7` c֭X]]~sB%IuX}{0ËΞ=CnvD@>Ek"&_*p!)A"Goy|ڒSTRj@'0 s=عs'(nF!Rd 9DɡG]r=}]u7avvV$[5 C} qc!a˖-b=^($\.3M:"\o-rllꢐ}s"h4b%A2jv.ÓO>z\#0Z!2i" edd뮻0::*U\F*B> x ={Vds7y #2~:xP:sB!q [n{gej5ҥKxWD#T[5Q9f(߳Ґ\.oVop0HRH$ƶm+B'ic&믿ruyeLgVef#:'"qر۷oa"'i&"Ν;.< [u<pƥc.iq HکV8ذGW-N>-ƈq0+uĄx<aqq X]]5%]ٮb] U;ة3.#7*O@T`ex_Ӂ6QX ;wĮ]L&obf*\,QE,@  VR5fSHm2"@Y ڙJfڼ* Ixq&wNNmxvM_j ?*TTf*"&Nf2_@ @ K;D'4+`/N{r9FCgcMkdSu?bdb,'f˥#WUgȶ;$0tʸs|t E}jGMɯ+;uITv"Vr{V >T ح7R;)rl,>>r9NzNnBW⊺NhEbmT1Do(=WE\'XD t6gjhl+Ҟ%:o}4ճ׃uMGOZ'|zWQ@pV;pJ}&/rCghr>n>vUYgk{h^SN<.v]f*U @Qi v&񧺯3yv_;NfVV`%w :afV֪v}NsFP.Ȩ}#!;zV7JreIa%xrPID.1xqA'm_}%;SSF'&Vd_.w7Ǿ]m:nEۑ\J?H.p算p]|28![rIHc7IU6;Iת%ø^Ъ9BV+*·##sRW6YA;sEZm.e/%ͨ TN{>'BSډ`TXINY5cZV9:$Sl'>s[)N*3,VkK . uSs,g*Utv~kEp YE=Pvj[$ߥɂE]8Kxb@8y4w vڍ]N\w=;WwbFE:F"=B8X,R cnnSSSr)G7q_0n,vQ)ᷛ\v)85׻EL[ e"Z>N34^: H*'qh<kt p!Kc|۶m80sx<&@ip)={sss" 'fn:N!R0hNHz![>Y4u+ b;)Z\g*a.&1' )8[Nʱ*Z{*~+&v]^/088`ddDX(PLJ06tt{/^u8ws /;Ukv *u=jUVi&0=*b-b‘"o'g]X9|,[{*KtL4]w^/&&&gl۶t>^ߌI@R={099ӧOØ_o|h"Ve\bmۼn:1@'Q&u"Ӌo'u1 ǯ1tb:jGWSd.vnGŸLӘw܁d2 gyyP|^N2Xo:)w7cG:Dut~"Sj$NVR]NKU uS62i&~T@u:1Ys fI: ׊V 8qx[Wߏow}74Ѩ0]ӡR\Pzz/OpBv? _~_bjjt$աbįkNt mElTf]IԊڮ3}M#Pd<ۭ[ Ħ{f)I~IVcN'wߍ Q.zh4B Nࣃx;c@^W\#m ##cbbqa=zju]5 OB~ s"iGTI'vu& U *$ӪO> Gev VmB*qw*G:D9=ɫp+ ʜ#4]I'H${n߿ÈbȮ|>׋Bl6sZlc~#h6@b>Pw2N>b.u*LWlVG* >vTNU2" -"tG *-:!vR: $]7Fri&BD`wE"JT|J|'nN48~U^!|_E(9s7oFP ǑH$J033#2$æI%W0pmОfUR)|>|ӟF\ƙ3g_RI+u ZQ[!:iIe#$NIOeIr}Vm1GCtlUw;D6 v ]ׅA#QZNtSi Fi&e\pDž 0;; 0 JcX^SZ; X\\CXD,Í7ވ\._rqH;bNw`EX9!N%B8ᗙ`76JY12Cx֛Z'vVn<8d_j7J+?MV22l#˅h4n vZ˗q L̽il\u>p3ÝDR-ɒ-񒸶'A[h($@&hѦPд?I"ꦉĎѸ,N#$GRDQܗ!oap}ޙ;$@˻9ˋ . p!0 SWO?.%AP.Q(PT |%gFL]maW4zw*QN:gf}i>YI?DA! lEPK HVZV}Vj>nZc:Z[eN){:=fWxHi߾}B<<*~?077ALNN"󡿿DHx܄FȾCm#!|>or~Rڏ|I|CB0I!ݖnEtXu rhvNRi-2KO<;mtiYuKiV϶u^3YuW%Im#t P4p?nVGCkN+NV?dAv7i+l^orè9$4 T*!li x<c`` Unjni[ µFՍL˓tjةN 4jj)y>1A)AR3|~7 v2% !#f rR޽{qi ׮]X,r}avvgΜ=܃)ܸq. BAo%ktN}!!¯ n-)ӈC0::P(RL{yy0<t/ߕ!1&*Z!gfz>H k\nS[U>Uڑ36B,1" 7L\R*3Tj\@3/j>R{Ubvc+ ґϤ f,S";Lb||GA*Boo/vލbbr9TU|>DQd2~ ٳؽ{7:;;1??i-tA}kEY͡넼.χP(cppNl똛Õ+W`5hNh+B{zz{n 0 R)8N d2VX,"3h>* 'IZ\\DR2й\΄ӓM )czpX]]-r. rpw^ucx[΄[i5WM.م-T AVtB@}GtlLO [eV> Ni84fhg;Rۥû[YĝӸP{vL&qw#T*v*Q,9 ayywF("`޽\+ øx"VVVbVˎGOc``>(~a޽@]D(cw,._9mKhd8<صk\.zr033׋@ \.B! "X,2} `.#!v177\.|>cp#\.zTFEnjʰ(Μ9mNȿ6zM QMFI:v5ImAIUf7QqVz/C~Áv>رcVkkkr̙3X[[?/Zbvvܞh4\.a$8pʕMsjj}7#bw(y1sgJ%f$J(8a߿\3338w&&&xݻ\-kU?]w݅={ #`qqoQTP.L&a,"t 钓Ƈ ^4pxJ2<߿(-Çg?i;hG2oeZ #]ԦE:ܬWL Y܍Qgg'Ӄq$IbMQVmn1t#+ `pp}}}طo@ݹ.gffr022X,!,//P(۬|>A΢ D\|8{9ru{/|I1jfjX]]lع9VJ24*z{{ߏo~X__f|Y i=<ޙLE ~}}K4ol61ğZHVc@žk> ;ɴ#uaIne w~9r@TǩѣG{'ӟa0Czh:x5c:XG#@o IDATR!8w koogqE\.z*,,<~ab~~qX,8{,<>iT*"ahhɓ'MVH7'A<3xq^NLlyyH 033X,jLNNܹsxp8v}7P.7i[zFoo/*(ktm\琕fD2K @.C\Ptn Ȫ 0_BUvhG VFEaJxI}ablbEQyχRu̘0:ji%5rY1@F&M;I{/>Ϡ333Á|>|>ϛ4|Z$HĤ #G੧믿^{  U# jտU2Ү$,uڞyɛV1t .]xGq1 cn߾P(Uy\|n+ Bك۷osۍ1Eŧ>)qk].ɀ೟,yF. x<4N>wyq=_h4eڵ سgC#@hۿ[?~o3Y9ojt\6B9. ֆ T*֬1_.f2H -4(1p8yDrvMUx</@#rb4mhȕԊ*ޣ?aϞ=zHdM0 4nܸ .0ImӅڍ6m#Ip~i|EƱ|>Q |Bf&a'a~~ć?arjvLK5g0̻nB󘚚$n޼j`0htmtLQnD"afX KKKIf2$IdYJՅR (<ͲHa333 /HFr0776q,//^wvcx fbTÁyK(Xutt"xǙ`qC'%3T-UKmz-9W=< {9ߪMվ ,{5P.}EZ!T*JI0Hy zWTЈݣj~2jKك/\CJz v2]?<^T*dY,--NoWN!d$H8`xxmmmd2p0667M>n€yH$r0ARA&ARG>&@$޽{SO" \.W_ŭ[Lx^޽j@n`hoog!~R񵱱1|_߳oy}/#Yρ@. br}"uq#U>4\GHOB166sih+ hF:)v㮻@3 Law:u=X"XHLMRn7|AF=Nyuu'ʊe!Ohqb1d2ޜN'fff7"G?[nFpJM~LBlv9jkkÇ?a>K.ĉF$|La,CV/IR@~ab(Cjfgga+^9|0vލ .b~ZY@ra``R lIFKڴ|^| 3{^d2y@Qie*M0P wcxjgvQn{<`kvSf&1P]~?9>ЎZRq:FGG9 ,D34 t\H$pqx ͮѪ1::eRk3Z}}}( HҲt}&BcnGЃy#ǃJ 011҆aЇOx u<Hˢvf pw&GuK""3tԕwǃNѣfx7qm:u C>@a>Sk(:b9& ܷӟ4{SKK-]]Ñ=ƤeNcG\0cEr݈F,J%vm׫?or fvQ94@fܕI[!LneeVVVLx|bxꩧLI3RW+F>gxxO<( (ˈD"hooMfhiKD0DOOc`G!M_җXHmb:?C6*籱ZXcv8QNlr Rk'gy7|ԤTVŰo\y2y6[o̙3rawrVVVP,EB1>>={`ff󘛛{ކ}iVV}(8{,Ο?0 ,.."`Bx20 iѵISO=ÇrotN_,yZ *AʠIcJFϐD"" =Ɛ|tIUڱaTRN'{1AE:::شf|BR:6~p8L&O} /ڪs8W&G?Q:tΝs.@ъ@B6}GSDKOO~?Ν;'N```prC* PTتYo6k4&4w8t^~Pk#@?滼kŞ={iQG/Ͳs0c=+&a7a _/,Z[ͣ P T;dKGt}\.>Yh}}QO`IѣGMQ DVf9O?HBǃ"n$ SR ?xp8VS(?KKKō7X'Hmݍ\.6ܸqd2|, If&p\Hp\7"ͪsr0::ʚ?)DEgg'piD<+^@]|>0qKWω}GX,릌^H_=SR2B%iҜv/G±ݾLjߥж-U$T8O?͝|r鞞j5D"p/%SvYS!ҳb%td?e pN#hP>}633nEe<#x76[Zl>;rcn7"2 '`b(aK)+,7(%J%߿!֙Jmmmطo'Hdpeni#T*188㰱s*9 OBi__puJ%r$P+ CaeeMpΞ'!377&(0xH w҂uH̑!,.l>_6KR$KKKf) >pǪU2sU3 a=CjRﵚ>]w*TDd]IjN'݋p8̃i*F8LRLZXX@Tښ)Zb";Q?i ˖$~G+j#MPV%+vS9iXEMVHa> H$LM3r\?mT* M!0! 0o5n~ tuu#{9w<49ID|P EVb*4:;;q!\p5t:l6@ D R)NB\^^fK2Zߏ%,--8NOOc||"mf; "ҥKO08DqBq$My˓ގx5_~SƬ,9AVdI1A˶HjPߩk/;w%$ӖکtxZ $ 2D#?i#'Aڣ4HyrHठz5Schn޼Ɍg, 0ԀBM}`ܹsKt3pc;CPw%+d9Ø̡vst:v:~ӹU+?Qš) tגy&"n޼ ǃie ={T `^:FEk`+91~,..b~~ϩ]]]ŭ[022N try*xt:ٗA(ibh-5w^?`OCeTZ6'A._+%I=V{eNV|X&t⸓8$w+9MBoo)Jcmm uu 9z<NI=###ljJCajj NFԣ&''Q*83Lbcc|ȘbZ9f >kkk&Y?Ajjj vboNrsrRČ$è;Co_7o4r"LUheq&7J`666 \(4|>XRDeF⨣Un7ߏӧOcg R)~J#} ~_GaymAɉDY x<|QA[apQRP(x<Ӊ MBDv0:͛`k0ԡ1Ft_Đs9ֹۙڣ7PGڗ} 0|Injw4m[A7 $8 GĨ&d47KB``b)~]4>{ VaZ(bH&ױa0%}8H 8GˌߒD厭V$dxUMGR)\P[HplllpIea ƍAEL'78Y4V !e$ V?66fʕ+!!p!C}6K#\HB1??x<#%3۷t:G;Cj#_LV?,VZ'|(fOgx<75YFNT,Z^^6At:x)=vvtts4PVbठHXV|hf$'V#=`)UӑQ_~?M)Td-//LVOTVgXp}ٳx3yeA&CKn892jZ"b?ŠIVUmtl .\p8}q|(7wj;j8v옭9Q*-5k׮aff`wuFGG1::{)jӃT*t,n޼\ƭ[aj•+Wp]w!"`޽P= Ň|4"$35:j1769Lp]kשi,IæW*$XJ!O\|I"]!Qr ϵ"Z @dw$9-"$ bddn&PfggtDGGW~$ӟ~hb:N-JT*azzP*VWW~9!M}'A1117LihGNjɄXRnݺ׋xGjB1<<̵ZDAJrX__g0꥟cl6˵\{jttXɓu':"d7ꗊ2zd:Ud,* 0K AN6)Lh?1vdr<{z?);08RoQ@[%ӛarwL5p8Hfuu\hmmmC5ϛiM2QuڔNYw8z$Ii$Id2J%b1,..](LI |jEҼ9{iuK>(amm n¡Cd&,2{Y{ڌhXpHuɱsTW6-_hLH J!ϣk6` d`L}.5Q/SV ` 6  qr9lllp kߏx>,Î\y&X__gnrr X0k9*AVGu2_΁=$`%@k"r@ɉTa`S+l|>^P?+#T"koӉ7o\79 IDAT̮xCwcc㧳,3)iȄzoWW*D",N'{ɁCf^$%T]2 h8p/^o%w peW7$Z46Px"klREmC^-%bFxyHJF9I ) }Ny9_ͩ4_1+)hza6 yB!`9tvvX^^F"G8<3BC4Ņ  p8 i9s'aԝSSS,2[7`KKKػw/ (!o:A,VߏP(S]'*9BkZ=hSEMYLn+wVLH$$DNX,*((p IҒVT / I2D033I@j&23ҚיQ3 Ly>dp}0X#Oi6 p iFZU ZXXw>x2p޽|Ґ,w-5d\CeuFhcM:나'MUF^u۷7JcxL;dR[񔇘wȗQ,M!dObv;t:J%֭[X^^rF>NGI:Nl vVF d=Z 'NypInE|>C+/Vޢ1 xHB\Q5#g(QJ]ܑs_HH4x!$$4"([dy["R }A%wvDXi6 f(q&,xFT(2ao IN'wҠSq.è`cCeVVVLW*b1\|haۍ5J%vz:)4i NC̚N8b1tBnr"9s7¤jҪ}#$puP GӘbOwzc34Tj'N`Ϟ=b&244h6er˚1Np8g"XФJ8ƇyOOΞ=5.a8y$U@;::؟F!YCV#9R캻111ѰvQ^~栣KpIϣg YTAtydT"q&!%h.һ lEVDpgp;qh4ʅdFfXUe†A`T|r5"(UMOOLnDx뭷X"',BL#X_jb'p?>ҳϟ?~p8,//cbbed2|y>| \/^ϳ}G}FڡI8ڿRa9/Ў4u$J¡otwwc޽3`PjIRCz\X|/8q¤X֭[\4L:~?bFGGݍ. Z2fyzp'UcyaT? I#1|>> $,ex^$I\.er/WZE6$__WrX\\dG9 H$h4jaD"v59֔ jdКB2>>Ç0ے$1??crrgΜ2cjl}XC<~֬TKNyF__Cua5,!E|>K"a9d\ S%oڿZv OL;)}G_2 ivQ"IfȒg#9᯿:<ȑJ9HpbZgg'Je:SV򑏘INԩ$ʶBN9z9e "Rmmmf V2emjr\.B!>‰we4 [Ze+#L0,#˳}&dcii W\urW^E*¹sFODQ*$H$R`hvP'K!?fVjř3g8$Jq`Z#+@R@NdHd^*=KU?f`\ `GX%4 r\8}4ver`5Jg.mFYݑ-1IZT? q3]`:®ٳ8~8=Lq~r0r,јEO I7Lv##q(̙3!-g}ǎG R?HĔGpaC`͛~_xjp8̥,9z٬p\ן(3_!~dYۿ/wuB;R EN1[}iEpKKK&H\.~9idDNaӧ:ֽ[7䨬T*wG`yQ`0V)lLW񠣣L̡HK4$+:2N'L :zPGj* ֨vԞ/ˬdp,#aRv> rq&MJGTxhh===HRFzLg6c' CYYYA @$3<-Y[}6nJW=Ŏxs@!pF*!:s d MqF"b1f2JoBTmXadjwO|zhcM1R3%"4@ q̹\O"؁pkjT3^%Ӊx'n*r8ƁoG϶C_|E|Ggg'[|?BIyc;T$E`": К:pn7k~]]],)xlr~_ȑ#j|~C&O~o}[x9%d;TKb'''ꫯbxx.$"ל%h^ݲle 9̠J_׹rs"~u 9T$IlD(BWWۇi?#BիW9*֙:X[[8vl'(|9Ns8zY<Ѝ/~D O6)Itm] v@ۗlK:u$ɨAjԅNw0CUB *Ta+iVђIuiNyr=BoT+_ݠ %E6MGGQ4UX|lH79~ ?<rD\ q_hXKKK|N0R*C% 7sG?[H%ݼڰi$ auuH$md(r6 r [vV~_1??ic?)o*ip%?~׮]C&2 SN!JavvTN9 "HptB{{;*G~Nd$!NW[A*[VLQ*"`9RZYL{HCE7 mT*y&x ~Nd$.bm>ot:;b2,Y'oXD&(_ |>94Ip/^č76*~Qz(㔩-=?궶6H +ƍARɉDI;x љ:!Z g&6Ie(*H>Rɢ) m͑J:e>M<99ƾ}p"W.NieBA&r&\rOƉ'0??& H5맪q~AOOFFF<`?R""(B|MnR)V.6jH]*DWTpuܺu dMXªa?*t:M'CTp Soݸ- 'Uv:!!IKiNȈ"1T*!Wܼy+$OSS=65u@zx_gq1N8"Hܹs~)1A(z-i*e+MBfKm]8Qnqq6&…Vp%=FUgV;ɧjY2oS+++-HΝO N;j R!"͟>$B8t8{I{HZ۷os \|9fEr ?gGѣ0:L&z1??`0h:hB:Y0˗/#v>~|Ip!<#hooG:,Wy+ ] ۜq*f$?si&+s;gF__qa\q"~H|p`j[evtz&ek~ttt`H$\)HFww7(* oŋt;5e[eR m"o/?unU 8χBnRqt|at}&a(qeek#=O2;W߮{zzz088X,gRYR_˗/ڵk:<V|8ԕr>gsp%c܊X[z0x<0֢bhElll`zzl0#Q[V hN1B\k|MrᓕVȗUe؈<5r,tB@>+ c&7m THT걫XYYከVSZ$ }k6k24J%:i%ԅdtLS7Zl1h}6#k- Ԫ?:+G8[llw3UQA4G#bX[WguN1eU@@dʳj#\:oYYpjjY{x1xc_)j,Թ&N!eS>~+_Z;r&oI l!<<բWG5 O20c¨̪FVo6`"نV:h幍~[_fn~k{]jucG;sV\OVz=\˱^ &KO^Lg=K]ԞЎ0Q-9hܩa IDAT`+WUH,IѵLٷfx#N?Tjkb3?Lwq;wV@0{t{Y{tLN.0Hf d˧=g>usLYj6 +n[XD C$y3xXKk;Yu&Nd0QH1;# ]dYw:z䳬گVSOwu*#HZ,fIjfZYD:U-Ѩ :W\*T3Un /\ .٫c jvhKƮV=+mFe2Vשff3-FU`s^JtgY1~6b]WYa[8^u2:0P!fXvf։vI76@yd6Ԛ=CΩn\u϶dVmR:^ .) 7bf҃Nf# @2۪[[F0o?E{ֿvH UY*Y-ڮbsc3٪Vcit!`g^[Yv4s+HӊXYrvګڧvn3tY=*W}Fj[jT&`fp@ԪM[jP9vʤ׍چFЂzt57[9wֵU~fGoGPۙ;+#2vL Wf56:ގR!IzLUW?ko+MڡfίjvyZtV~fa%0Hb42 zNFڞyViĀeoVQ+kHVfm]ju-kv|znw4#R1F㮮"vڧ[VVL!vJ;jXi41+clJim"G'$5jҪc']=Fj=bV_2tFj$OL ;IU]3XKm3N16.fAVccR!(5 }ԵJ PYhvNX]k5nV}iEjtJ{Udu9=OwzԇV`U)1:V0]#i+ vnV+1A*6*] ΦVL곚 g:fnaڈ;aXB[{E4[V&n [Y@0P\yݽH)hm7iD:ފ BKV0ʅDm1e50 SE3 I HFv#e%dվj*EjVfљVU m~fl.9 kn qak ٌ۵"VfkеMFOm7 !*q|IkRapk<Q(P(P.bT7.=3Uf 5`0 quW5U*ߧU>ՒuSU iv{O+3vXgJ[fdw ۵HўHgi7*: F㝢mC@VeGţB&$su᨟\044vvvutFQ[+W i8U쌕 $YA$VM!g+#bph65+.׌m#!Hl@R߻.ЪE{fZ7[%]Uf'hG:laiOT$>H L cccp\L^/ l6U>ăD>G8#<ߏo}[@&6jݴBXC<4tU&%-FB Q#-J:;Zt{Hv{L[ljt鬑֯{~6,Fi5S};Dh[@j$;1Q9`}z{رcF&LS,N7x1s=T*eE[Bu].4"ְmbJ ڌiozfo$${Ti\vd!עnslӎFoFqɝh" >j%#h$I7 RBk.,,,Ah`в*TM\.ٛtz:<.8qKKK|4\ɱhQ-.7{f3x`aͬۍQ0 A ^@]r(r0 p@7o͛7133֌qe:jf鮵 صuibZ/ш]umR?k&yY:Κȫf9{-FАt:~&&& @\`^tR4RzrA?:;;qU\p+++i7꺭jH`Fh/VMΝ֌n7ۋ.$IBMRxÁX,WUT*tvva׮]rfHRX^^-ڪju:*m+)**}7"vmYVZi_3ډueЈ ~d4XD6~?nEt+Q8ޤgYlll Dbyp|La`||>Ν‚e?2VU7hv\-\FH&hooG<G4tlHCS2  hooNj/uLMMiH7fvF۵Tgts a%g+j7;;;ىh4 zndZET&&&6~[g;H8XZ1>Ny>### BV( ؀﷔p>?XZZ2BFFF8zQVMmY^^Fgg'8y曘߶pI}46؞dh.Ҡ@[(ЋMoE.ERYN2dgǖ,KQHQ.{>},5/>/ H"ͦ/YeI3Bľk qka\>~JNX-Z`@\\jj&&&&cxYG6~Z)Ax GbHRbH$fHRtp& yVk VGo8FGGK/ƍFW0;;R5yW_yoU{{]"L,el2A4S_4Jda03TԓF144B{o`ggǥb1'8ˡP(`xxSSSxq-x&1y/Oߦ% 4~ϿeLֆE\xPh< .?8'2,ta$A:F͛71??|;.k@%!/̟!d2LNNbbbSSSLayRh4&6ߩii`q\v d2'H$"̙sK$A,ozzx) (f|]{%dlBEmi yCȆo&$JƉzrab1iumE7b~~w }4 nO@ A7Wbm2W"Dخ? BT*p||pz]6:EtC~E3 &Z D:?Cۿ@}> 3P(X,x< !N١PH1qH$D8Jz^[['|IypuݾիWkabbf ^\.r!ҥKX^^+L ˏekBl6թ>Zl@O>Dۿ[(XS%25J§ljv^z%/:$@ݖ l6B0v]Ӻ\.cii0<<,. FĢz9]p IS> d2d2)6AZ> Ǧ%odqn/}KHH&w1hmqB!uTU8(FGGl6 H&xW8"0>c& (˨X__GZ8`/ck!L"!KxQM@W.j!@: acc,nͶskm0-YD0??ׯcjj[R9l o0ᅬ> FC:Ŧ362 o+R7olIgyve2g;0.\لzl6((D"abTJKt X,R?AHnBz oޞZ35~ d2L&t:dYqT*fM^RRFhCg XijjJV%f?7|(BV~6 aX@wh4x<1AAuL? 8fffl6??__zf豌F|xjjI{y--^ 4A&zmVatt" i;`e>R¼9Fz켬 Mf =A@)HVT\L'`xxXt4y/C€cϟF!j*6M"# ILxF26R*03ZQ*$\maaO acX /_o1S3ij5 I7MB!,..bqq?яNmsMMkh4066ciVGNExEZ!D6uW]T::o?K}p8+W !Ң!si`Pj_qpL?!P(#R)WikCqLD"xWob~~^?#!" L&.NL/^ē'O}3tol"JМWBvZkt9X XL@8kvwwL&EhSQ&B_\Kl= 60,0j*P362W ip }u}arbYYo}}k^~]1>AR P(bBz8p8ZCr9\zU͟eK~~jllLhj5LY,Q,m.6=Oރ3 ӚYtcկ c1!VjdP.qxxNX,\.d(C8NYV8]|bbDbylll`jj tZLhs󒑖e/}@066W^y ^*ߛ&6}>؎l6+p8,!''w۷ohMqSxnDl6122":XGj bȣ(b666'ϸzgϞ8q B_~BoAmI<{ \7oޔ5pf_Bg8ŢX?T H$jd6xW^I5ݿ^}~(TԨ q R)/Dp% J]N縶׵kz( ۾Jd]iG>ЅDZVl6+$ltnMyTC HRh4u9qM"hPlll7??Jd044H$ WҞ֒www%mܸq~ቘr='!SCܸqC=Z7"+)N2p8T*Qmxpp ׾5?}uT L&#u츠:5Oι%:@'Z&>?=|/Kȁ^0AO#*]qDȑgIp\y HzmQ8bhhH^8ёX,D$*B;6=uiӧWUT*kVyP}\xo8(ie֬p-].677b!׏oDNqcHe^wEq̃ vvvMTJ<45> !h3(XZZr},NtJ~).\p8J$&I; H$DhC|km{=ۮD,~VXE`xxX,QF{鵠a)}]+20ֱfԦ2kk߭s?=77 ZBfŧyhǂ }bTrX$LbssӕdYQsM"4Y1#V'|EQe|>/B%qEc{{q&3'&&$qd@\N|>'lŋ}$E R6ŗe Sp Ί6FJƱck +mcbbGKX":Z7B0r=Z[EP16j|CZ:uL<^u<~تL;Z"ɠH՚ IDATyXp-vӲԎ!'yXk7%WċȨ^K.T󘞞KVg@>KdGܜ N-\pi' y$H,ّgZ#:AʬtDF?-5kJy!$&@ޔ 뒿&ɐx<.D"!̟ccc`& &VXޱ&%o ϼF!yc R)ajaR}+!9IEUb!tÂ3Vɺ Jի92 pccLD8.\+&tOEܜeA|+_Z._, Zΐ6"ǓBpR k&>77_~oaB ʕ+'l^fffD(p#G0֟m# F_B2t +סRkjޤ;9ܼyS e9 @;煊-"32A A&ttnfDf iG"E{{{BXXXgic'-f<ɥӗL;֭[ 47E4lD"b+ nl1f\$6.Mk\|Y6D!MfF̅txxX*2HR `o6&n f"M&&|ךС DRN(FJǜ]3+ >s͹`qBv/FYi_.4æq:JEk{^;z-<~X,eY/^+2F˶T*! u/b$bIpJ[~nnNJ95+fjjJ'21ye,CRAVё<)='f;}O<~t^t&acr^EO \v Px.\+A;DagvvV4 2`07nH%wl|V ###xW8XHq'P,95CD;j,D###pႫm׾oڵk͢WGsݧ Ny24-ɴKhDh4*lbgg+++Rځvv:TV],nQ%v^$uaD"k׮Ię(~ ' I@5DkǺ1Z‚fRCat{jEomm@=hsssrz% 25!+W hky>׮]X8#D"YH&VL-”wEdzй$j uT`|hYbh@7}ggG ^Cܔ(~װ*!{=taJi˰N4`}}]**IP+MR姙N .[HS^؇0 Ja*@ LtO< -Ԡ_E+ #xHb.JO ! {rPH&ߗaބ}H"q/>pYH;7Es8) NF&􍌌H;Y2-0O4n`B.T*ayy_'piZ)pnʊ;TYbkƯА&Cectt 0aTR*ؘsR)Qvvv\ )MWCMCeTU\pZ\! X)7 st@ V%٠4K=P(r0j-L }}}ݥU*̱0EP(7nqo?3.pdܵ_mbtܱA>|7o~p} n177'}B6ojV O>Ą_RS\.K(K\Spr I5MJ w/(vX\\:0 Ib}3|_L;9z.(`t5 fU*јO0#k%hƦGXDP3YUGbE"I畅 SfG:$e1bJ?#]tIJhșJ?}fS"~=MR>iiHZ^e s}< '85C))^ &6 ^`A}$It:lll&0fgg1==mu4NK!x8x  4&666DႩTJH])vfqۙKwuE9`)~7@t_ˌH$d*".]$k( 0KOl5?'cmΥ3/ Bz*YтxSPr ͊m6¬ɤ+ܓmx^oM% PG `P|<&etfaγgP*d$FϣXG>&}DākC0== X#Jb[iZjSJ83}K!KD04?"$ƍ͍Gg L"NczzZJZ3NenѵZ-D Bġwz#T:4y2Dܤ4E766PVQ(D,qbvooo#Nʕ+gԜmiϛ& ]]"Xq<cyvڲH9Wp}6H^9DodEVK}(d~:4jw:݊SBT/sk' h?5E5 ښbls*###(6Z<< B$\cZ0,>'HHp2hiA2|>ۺR$55g2*0#:Ή25s=8?WK4>,JtZqd29Y3LSx~\ֱX wޕyN]-q '4}B2xb\g4H$&f|jMeD e;I gI6sj&B!d2$  >C;@w/nmmIfnQ(0::*7rpp ~ *DwdEDAߋy^R;jZpefYxb-ЁLH+kZbllLPPfɈt:x< `eecccE̍~p)B^z%IɍFLF-̠T*Im iC|\ib1,..Ν;` Fr(&&&$56B'LoZF8ؘ=y4f0ܘp}P, s~gZ {R@T(=z9Z OI{ Qi{  x$atM,>!lܘkX ˗/#F4U*LMM! DdR>Pa$Pa*dz^:X3~'TVN@2u&]йJP,QVҞ jaooO4^:JD!tɤ눽D" W5dyaAb =v@"5>L*a2 hhhHʅ \0l s(N]s$j+hu8dz}LOOK+?~ [bhhHߪ*,j&'']P35kV4 )$A6E^hT¯Hq/fYQ0X{q$υ\|ёٶxW\Nka*t1 ;11P($q|'>0@&Qcd2~8Gõ-NMa؎`{{uĄk@,˒|]d2aB K|s{t[Oɓ'r(,+##ެ)J2׼nfZs7dltƛNN}qS7L`YH$".kJfjFJk NhTN>EF a ?/InӋk*HbFZƆLȲ#1crr$4ӡf1J%9g`_͝q @ D2%]'Ek\LrVKb#%gVnBl37.ju뵰z&V>Kюs|\ƗKriKbvvu9uCOƍhXK&8q4 ۜfrY4GFGA2&rxZg&el7tj8]BJD"!6>ĭ)P5I{8۞J6m縷 r̨ oIñca<qqRFhu:`6H?03'bggG4"JafܪfKBqu)a}hgЂ)ޮ7ǍPM>iH$"Xӑ3 6oCn08Ήjٳgqb@032677W^y˨V((IӉ Vn]5etBt0P(HM6kz@esZȀ4K% e ֙n';5H hNG"d2ܻwDy}^FM>J4*O>!ZݺX}:\D!'BR[-6qfkuޓ ,h#t06rmB4t.p33緑6mLd:t2)cwwW6/ C3+HBet{}Q(\mx ?!s>T*VSs0b'S2ǒ‡ݘU2^[kn6LF*caō{IOx7 SQ C嘙e:Xj&J% 2:meF0ޝ###v6?lHzfYJ%ӌ+F|G"M6l2\ԶY1?5f{{{'\ѕ4TGȉ]z,~›;q$,LM?D?/K- +*\8ZZzL&% cnn(PMjMzh{{{r7x|>/Όx-c}kۢ}OK^㷺&:t_cVMWawvv\Y`v)PL+RkB888k&b.* 8<GcjriQy}wo"Jɸ#ollP͛71<KGYq]ϦBcS𞹎nݺtדq2,];HuSMOOVawwbѕ̨'& ?5 Ie[)h!Ŋ0uBΣH1 RHEb+[i\ t; ^<%GkZUGGGL&1R ad+2F%ps& lnnJ&zLL?pIIs3! >Ǹl;N_D3 fU߹sgGi\zcsCpSS"'x1}ooO:Uw+"$ im,--Pึh" 666<mzA?M:ne$ )ZvVt:Rb<#>O@ CTbcj7訥Jbi~Zq$VNR:궛V-<~Q0a^6NgqqļJn旜H$"㴵%ppe~ҙM^:*hn,q:N7dO'sQ;#̒sjjJKZScedcܹswߕB]OMV kkkse͚=ǵgS}zH,_b6Ͱs8H<@:viu'&4ñ8GGG(CmL|o,G} ^d2|,t5O>CCCx@mll jU`.r"Lf5L&#!LTJ2>1tN Bܜ5KDsxxMǎ=J1h4*-//ncbbd}odLZ>SJa/.hh*K;)I U+BSUZ-G?rn)^T,39}##lC}:Z@s 21F.]LVczznvփ\,ŌI&%*\tw:bAppszE:[B?X {mhrQylll`jjJEJmEŢhՓm?tlmNhRsffeU}R=/pY(tԩkM!qԤtG3M݄ZVjꫯ"LkiZY*d-;wݻ:ur99Sm.J;kwUL8]''|"9^1WWW122QmQ0(|y>S /afsLcWe?oӬ ˧,Ǐ#T*!LJ=W=[]|jLLjZ_Ȇd;cg --P8<<ziApxX[[oF9`G}a\~]`K't:3R_Wp^XZZ ?{see.\@&q}sO=3 bT(L֪~YS.t__p@i?(hJF.ZӲJf]8a⦝ 1di/=t9 NҤ7Q/`MKH41"ijj R_>f{0ZjU4Z &SHך}472T*9 MRbК16&y@ת;88kmGz=̿Mvu\zR 8K8nԄ̉V>>c!i\_KqNQD|cʱf83I,N#,--=>9Zyś~FVN jќsG>֖wſ7odڄd0v E9hZjZ>]P;ěn'OaJ`=nf$iFV*9Focc< 2,5Kguy޽{RH׋!В1q.&|i90Nc~~/L&H$"777D98d"/6ݻgϞarr.]K/tD,2?VVVC ^ç͢ u,h+F83N6FYr$LNNJ}&C;w1k}ALV|>|>%\t W^ (H篬16K1:Wױ&sss' T-&Eyܽ{j N?{)k\k Ǽv]RS4?-1$_053d#0~lMfRLvȈlx_Rahֆ'D/귗0Ko.r2޽#ŋ.bRI.s ^cjuk Ç]AVџOrKKK 066&F藿u/$q~34Kߘx  Oӗ .ڵk|1}ZJ%lnn:cйX&6;ܯZiLu ն6>(6ڠ}Qnc0\ĺmB7{aՒ%ٗZ^1~Ӓ({);v{]C 7Ӗtdr=J*SZ*mk fkv:d> ffulR,ѣGrbzó2je^Sb$ {\(\jD^Bf\Ae3I6?}wP hc6?swJ=8kݘ~i 7#{z?8xP-k֯޻N!.uJqNe[O/ѤA7 wzFu^Q4Vo#ݷl^^\@f6jhˆڄ "$z_^}0ҫ^ZyРʎI^PI{xY/`0kZt^^>פ̵g" ft$Y\lR,Dˉj$]aOt\8ֈzm|ex9qm~cf-+Mo3I 5/vy6w5#:+AAu AkntA|hky 0z盿`bҙY=Ml.0/`sm |tyil*Ll^M0Fms1B4?OM_?l41zWi6L6??Kwy))f^c^5൮Bge 0kvyV*lj/kL7Ɇki`6y^L}~6><4/֏zo]4(TijTu߽Y/M&b;lQ[;Ϳm׽4*ǼG4]C4Q|s[?] fy[̶~ ~ݟ^OKg>iȦ͙,^}6󯟆яڋqd CZ3fu,)[R 3dZI٘ M󷑭z-xe!yF̬EY>.~euIͭ-Ѐ9<*j:6ͳttk*JX^^>y\ơ3O30Qhc)ڞMcyy -LǑ|Me¤^֎[?^}b۾ ړ^5ךMO[PϷW;md2B/~17ۭ lfO^PMxyW1etzZ:0P s6gjNk~Poc6ǑmҖeژsjPlfjé15!$A7 Q۠~LKkzcP>>Lu[;{۶~z ^لf 4d$zB&:{sѥZ$#xi/4x=& cf jџsMFcZK Fgsޯ1^;b62g2^sۥ[sM-ûcflZ35,/݆N2~¤W}7X LFOי6^Ew$r?E_k4^dD|·EgD Llj/6ֶNi9^R e|Zkc:s!{i^dj^6 ^}3=>E6A؏'۽>Bqsz^V[n!2~z/ƓZLXxCvrw4Lϓ̶""Пg!V{1rw ƺyMCUw 0^8pyT*0GD0|'~5\,|'#_O> |ɧ|O>/|'^PO> J'|zA>O/('|%_O> |ɧ|O>/|'^PO> J'|zA>O/('|%_O> |ɧ|O>/|'^PO> Dkkk+'|E5˿ ~~sss'|zdO>ʓ'|&>|ɧlO>S?O>ӯ _O>JQ?|'~iwvww;FO>0IENDB`scikit-image-0.9.3/doc/source/user_guide/data/elevation_map.jpg000066400000000000000000002236531223313777300245520ustar00rootroot00000000000000JFIFHHC       C " N!1A"Qa2q#BR3br$CS %4Dc&s E!1AQa"q2R#Bb3r$CS%c ?                                    ˜fb_'rX+ ZIk1u?G 9Y6cARRzLCSN 15F%),;$~"\6dOPˈ0c1&; >cz3A A A A A< H25ʢ6FheEv[v$v&Ș/2A } 0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0`.@߇<'B Tq t\iQ4DOO,"fR4#:-{HN :z:%es]iC@ia$%[Puѡͨ+4sk<[`a# 2HR{B %lI'L8v0i+2d!'PQbJQN1᪶2§G9bt1Xmb{)JL3ZXzPleU]^m ^:xb|JI(rѳ9k6}$X|(x}b-.ayo<eJ2Y{$A'}#r82oEi䕍'7 ϔBى&/34Zϗ2ˤLu]Y2F$O`2kGd>.xw.㖦rP 8 d@Yik*xMOpnj(s&MoO\3qQB:5EL*2g)[llZwS nmBe(k AϜk]Y0jbDb]T+a{ٟf%E8ZiY aGW*)&- ȫ0`TA7PqcMN:^&*ԩ*NA8 3xs8 c -9e`uK{{4renDF+I)Md(9`HK4LXyj]yPA,Eжxj`;-uNNp cmrOk2 z{;ī$-2 "ZR_fhX)ljFB.A::v'܁TUSJ!GR ͹` =}56bؑk}E1sYlK+.YhIIJR#BX&IX*W\l6UX2T; "TirE$jԗS/-gv>~QSx,W68Ϡ)jjl.GNTd㬿C*lyC&EOF{LEk:|Yy. tK)tHCORu=w4 yj~UuN]+(UsVSBҤ42:kuJTo8#O3~!/˞4葒Eh%ҽE9:0Fn\$UITiVeMN_R@YbW;'hkaE&d9᪘D d`@܂ r. <GА'@vɛxqMطJE>;O |V̸e (: % PS`"T]7- X,Ұ<8Š66PI;`ŷ,Qf~1efeME%e }<.F+)iTϑ%M̓c0JAY8Å)&i(oSGW V$̌ǷZzuS'4\Γ/9~]MJ$t ǡR8iÉz1E*yZ Ǩomiۭ]TWә.GU Xp M߾î,Ȉ 3G0`0`0`0`0`0`0`0`0`0`0`12>ZGj:تLT[u,h{_K[S/9yQJre/5b/Zj}gKlʧ LQ#H1Tk% 6v'%sE3ܾXd%^E8b#9MCYL\B%1J4 =1UkKt.u,rGܢ?-A3Y:~;qBU'jPoq|C[2ZtblZħG~>x6 -vou|%%63}GQlUȷЦ?ONJJյkA3ِ u*Vt j>Y|; 9\S%jtܙ]$Lyi_qUU4= z N=:zޖSTHl xqIԁ0](1s :7n{ԷI[*i!13 X8hI։*be:DJs7V>AF"Yz* 5'~՟D+x?J +Tn{s1ZsGSW߅DZ0aT74b8d޺4j##iQ9.nbeq湦a乥RxkE=ǀqxt̢fY?-3D|B PJwW$6}MJb9 4FYh(=o0snnL0Uyل[CEw_D*^N dVg kdYO{g銓xw,r*% V`-.zv9¸(=B]\~vo #,:H)~h=$ĤȀ* $x2o\˓T} u6" Yq>QD+rhUʠۑ1LPh?#bse"g ՛\AIgٖG.yu\ԍX7*n;x\rc׌<1'wgѼ.B66?"f~I;].:ҟb^v5Ccb[ !$:ż0`              a9eyW2X>XuB}c %Y r@UaF Gęcޞ#k)#cN&:T[" ~PA;oU'"M1=z}X|MCLopFzŻ39G`D5e7^"KTQ(:#_Rװ7N u_ͧ@k\sm?%EMJJI>8<@|TXM?cĕRH3&yx;e.H 4'k*3gt\)5@ Q~𶻆dh$\eu96@ûU""觡Koq" `t,N *)GO0'E~t>N?Ix*8+!u ̡A֚KȠU6 k5=VĔ#Ljܒ'Y%džC/t)П@cۂY|(i%ER$[U\9YOO!$\ [p#nU1]~3AE^jji3S4+n16ܐmld6zh # Y%OS\>P~&Yq/6m3`3IğB:I&/H?H 8bs[(ʤ.6늛Ŀ )3 ̥.gдfx)"?v!$} [:q0fT5"REt1)@HaT+0=#<3ٲ*#[4]~}|rҋ-ghHJJ~p7!{M<1X  M':L+*52Ν=^`?(3F+OdwL 9?BG>]ϝeO9?.%~ҶmJʄlHTf8j4UUIWP2\"(LyxX6RGAqP|oUT-cZڋtU8MG]b[WW2O#8nK)7`=Śp<1ZOh[?1YFUJ" m[lGUWLd%g 6=:r̈ߎGAP2vt~9&L)}>Bj#$IiGbnXp`_ Re=ɩ!>e&?׆~9Y~{QyjC] @5Nm3jjdVKVD# i{Z]YE}(Jo4Nn#>eH+sЂSGc?Y}5õ$NYYӠZ)3A %r?tg0ety9q*[}̺ҡ/8~;[)_-oIFCpf=\akB.}_͗Hj&{>|]YpMMV+j+*UTZ֥OCXbY 5TͱOpf4?TΚ#J\s:?cIVHأ)Aȷ8 #0`0`0`0`0`0`n,K-(sZFHUb 5mmL/ar!0%ُCM*G4F3B5Z$ lM팒DibSU"t)J:hF1\\ELN姌|յ: UM5-qybr_2\taqؒ;a߉uGQ:plTl"gS6YYJ._n=o`v#{b W2e&*і?Q`R箭 J%#D~r |afPe@m Q&ݕ}qsieoo$j*LLCY\c´P9}*mc0¥z%'!uݺzi0'j DPcG#k $w0hj_G2q؍ .I,&irGp@H+ :mcԑ[|OR?[K_E;rF̒fK0m}Ii$k%YOJYd݉?btaJU|I~URN^s(ˤR*"W}`N+22m{vlj|٦]e$*If~ɽHqehm* B*,6^1Ju3_ACp I#!o W*r 'PDeOYŬllw"2iJ*KQaXϑm)5^XߵS}`9VC? VaՊJl:ʇ8)fDٛ;x[xJjs < 0;;w 1;#r1/kw_jh4zwwYd&X1[ v ӻ"IȳtTh )šYVq7P9(YCŹ$,V*BS8</)OeF ǽa.1/gJG]7춿$`RXu 7 5cK9˦Йasȧ @VS6oty%eNWQQS7]ɰϹSKotd}# a(ɡig47E]zk+fqZIKhB‹v?,maeM< pX۫ẜH\fqkczWeUn#H Ԟb~.0u6gCу,n,T#3ʦcD)B2^8'v,K,"J\Ǖ2bǺ;&:Db5(N^&`KX%3f4)s2*Ԓi'RFAm0c qUeU]$1DdaL@Km}=x'6'jtÎfʸxƸӰ(s̠9.TJЁoؓJl7UW%Gk;)Ln9mC2Q ¦PD_A,X&bB. *~d:dab"r =ZiELʎ9KI˨i MS\=k*CqJI;8H#]z* .]*u V CHju.V#;ݶ S)QHPm .a-[~lL#QH)jKnR] ypEWLEK%!CD5ۑ>b+'IYR)թCBoxT⸛#?$\?UJBy,;zᮺJ*967*?8Ғ4uf_K]llJt7QUX`3VKЦN id/n??q5G6Uu r.=EPqrp5 HjAn4u\Rm (#iM&I5?1 @n`<^x:fc0gWDJ5Z1m܆{ž/!41[P?KmG3R);ZY`Tx.ȳ.(ϲɠ3QQRrT~$cmUdnM\TTIK7-îbfpwt߁!p1%&Kf3@h$` \𽍜hc9Tj`:`T5H Ǵ(ACQRQ!rf 5 X[<–:95h2:0# C36kn≠d/#C^I2I7 dC.n7j%RyR 6ۣ q;BNK#;2dT*%@,6$ڃp\Cq-JA܁z5&j飒K C{ȸ%|e`BI xI6Iߦ+CPkسnv T m6U.sCTXkۗq _:n;\W1o ႽVL Vt[ 5;G~,7v" n> xKgZO|=@=Pp:ف[chKpE2RRl e&ªj4ܦ[?-WJʣmD C\G]5RC-E(x) SLĨ6?)I#pu.D\=&K&ua`~\9s"/yigg5J_"$adMY" z8᦮̤ E*ƕҫ0*wX`{QG'/QEV3D[/{Q~Mg YkG6YTwVC2j|,%m˝-2c4ɡ%cA=I!i;]B`SWY/ =cH2OX^᪘#&ƪ\#E`{]u 7jOf{|7W.rX98b^-Ll失 w;6Aٔl@ [f5F@!m-fBU.5a&20Y5IkfC2UcJDWELx+Q I+Κj)2LQۋ}lVCUb3MJ Ymп&,u L)T^bd KJzRTfw4 4ܩlHe2O2=Yfk3\>/щG0†&I-_8EML6tX?K4Xح5:{>YWj?)G1qܥ}qQtUP$RmmC\f퉉%-IBmylv1&}sbg(t ωbszl89i!5͜j"ݭ$C{nc8n7rT懷^{X=q{%Dq\Vؑ{? P Nk:Ytע1\m>KYi«w hM@%>h\uET0(w.5%XLDo5z&xZ&VK_c!rU9$Ԁ†5'L'щUN,7bnX10m-Yذ2L+#. 7<*h"S_16=)mmeg9ܿ}2LYhh_=k@() @n+͝>@Ep2\㚜3a{ZyO09W[Yd۝z8VThd5Ђ1K"0~U¹ kHVJ!ր1Oo bjs {91B6#"N*VJG'\r9_(3E tR< *!+Ѕcq$rT$.~r.7ՕxYĜsiUQl9QQ<yHPXDoCb$,(߼zioL yfaւ,,y[C7 Jf ́v-LOA.rI nHK=4O ^B s&IN` bv`a`3( 3T(eqJ /lS\?#De!ɘg_{( ⪛J0@Y T!1*:S@&s&IKbS2Ț%mstLM[k؁nE|^oP3:5iPq| '>Τ*4nO䭋{i.m1q)E#I,J,T=Cq#f>aG/5.3#>nz^6;TKfyD{)AX|-Rd%Hj)#%?v|hD.GG XfzkWrqos i6RdS,%'i|: +J_kFρ __[5 \ӺG MDn6v6"B+C23йP.5َ"[Rq UYS$rټʷ"SX}&aPE]V1[kW&J2欅)2&jP=/? R%- 5r yElb`FA=-p4zg$GY2霙4/è k3>.$h?. I )$0`0`0`0ayφeMJKhe/O( LрUJ ! @NϠ}K HPN\1Iԥ&uQ>Vr&GFB#FCh,-<Ã_M_@9QM,|8ш_nupҸhHVC 2wN)l30_tFVU lQa`FPdy+DѢMg/=9 16ɎA$l&D:$55R.JbC{~ /ĥ͒AӘgqӘqg)3|jk0IPh$ vW]2F) ~sESrE,i 6hk֑ji$Dn0qڴۮ)+/!IOG9l56߈$hkY,4QW q5')3h,wI-%*9WIwmCgU6yvVاLÕT$/6MZU-I;k3Ņ߀sJ3 S7FGCj&,T@V+U+IbTpN%U|Oߐ ЃBatWVsp;E=sRDPV-m3 I\Ut -+QIxx1 rP=77ׄ2b)u&kF$e0+BnO_0 9WOJ Qo 2գ5p>Y;{@XvK{T{߯ϔJebZI)os v>$baSfVct?~XCThK AO,ƗpC 3 JٵOXKNŕK/8| #4k⤪Q U)#ֳAŋ \_(^#(n&ȡQTF[`ѹ$ QvܛgHEh$rie6 $u o #uXZ>*?q*gU,0e(3SR1DLI~G|7kI%J\~oVRybdR1~{̢Xk6 }BdW6upKY,@DeENL:(Ϸ>4ˣ@˘h#J6΀Ԡz,BpV]"%ߐa#񫟩APl,͒ܶ9"x_삕bOMw J Igkx!m}}2S 5.Õ"~ۦmR?~jH+B~b2f6hE*$*Rq - bWUGa>YYLB/SlԕY+,c=Dۧ?)H*4mHX?w,֤NfRoȗeߧNb1}ɗ7%2kYI8RS)̸.DfT`]@9k1;UNUQ 28_ȏ7F|h8[9+!-5 DUHiCMJ˟Ӻ ,ZgWH PO7LF&K-0ېAO' MzG{vO0TЯX[*V=8_Jl>j^ؿ'#>aQFk^ %DDRI߆=S1-!jd'p!=6/\'M?RLV2IXy$r>(OZUVub|}XPq"@$R*fMH'6>m_qfuU"0Iر_cc{'ç1qRPS0/wcKl*X9f?;LTPj3#ɪ3&۸ !ـ!uKXa RuwRRj ByICTeũFaMcl),V*fu)kC6[|7%LOw?|hʱ6ial'.`P=5?q*`$>D O''*KH}b]4FeR؁qV5;SF\p,p ch[A)?~cēQn 3ϯR) y&S4DcI+"/ e; 49qU*Kjh£U m(m{os._x{5͌8BFJrm֞&ʏb'6EE3.v':S$xrnzD~1S&,x9+_`xGQҡnlUa͞(xt6[UҪ5}u>p g_"ᰴ0` Q; 0A 0A 0A-׉s/ |E|Al֪ .{SMK% ̱ȵTs`,Ȯ0&2s j/>)UtyǜAj|-I7y]VYK);EcfTaӥFrRF[w\\v$v?R<8C/ ͸,8HZD˩n[}-ʄuk,<("E +ZG#xV4 9ri餖JIsr5Ibuؐ vce;1|&jk Dիozb|WSW.|;3_7iQ= B(3Q Y C؍WӪ-Ԇ$8JjJ$8k orgLtj r/ #a2$6TH6Y2qD`ȗ-縺Z*VfJM‡H6pt,}J$e*_b={~5?`A7,}H'q+e.3~l{k{X6_Un[!uR:lv,jĥ:~J%Qϒ޶&01@ڀ_ۧs*bUᷯm3,gʉ?pJ?Md7PftYxY"9lN WM&]/]w*Ehyka7t $3rR@O NQe Qe4EOCQ26dC7W o~VKCMr&M3FYǖdmpQv%lT,Yr.4jۡ6?ăz=]&gSh#b7AۃЋ8f97!U$ˮRs%'tEJNS$rM-$!9f 3 k 晿m SQ?3_YtYS$RFҞM7Y!Z|mYRx2נC 55x"hr[t`:Jb?_VQD)47k[ߧzR0t[%hOWOB%/+LvT3Y5§Mf<ާ75ޯTQ8 K#eSVfyUb1j gh˴*7''FT&QZA PdJ҅E6*Yx"3y^8vnE܀7#o U3Hf0q<+agUrE$KFXbysCl˳g ,b$ULҐ?ҕ=<"Sdrѧ`I>-֨.~YZ4 ؋17UwzZ2ax|pkJ w#{-?t]*JKv**< }>F&. FvVƳƺIfZyn=z[3R+MHupD)B\z?BdfUckm\p9 Q?O*u,b U-k)04TϘ};T_mUc& \9Zr*\u`A{}9ܜ S'eiIH`.Er$^&[&yYSOy +y4UUYiZO.'_E^[I)}>UM=<9f%- A HP)Ta*^U *gNI~✥I*RJyÆj >QJ 5?waj~ X%2jBI 0 PEQ65!+cII{`4SopA?_ȑX႔(({,/wR} ~*U2Lp#${b2l*%D 3ZJ)W{! vڛ[Q-\RAabc`:z;f ,*b 󨽿۱$zBO>:5ovNı~O7 _?h&JHv$?ߟSG? ,C|gsZܕh+,rwR㮛Un{&y:^߇)#UTDמ!}7Ӹ^paIbj)a;,#݀6YI>_( zi J]m撞eҭTIey%sFE&2WSDT;k t߾#j)"Lv'/ͩ,?i 1 k"_a_M\!M⸙euRm3k\F4hr`gp:$Et+z~.I!X>HqI^2}5(QocJY"2}klBs5IڹPsE'09Y`n ;b _Ob.7¬^Tz}'*jiVuW+TcP= (rܩ.[N5}&K=#|l}zD K5 7-Pp=N!y"1{mxAK]م߿;u8H6IDdH*A!T)s u8bxfT%;B k#1 -tWMxzCj^9u,p(blv>nOA1Qg\צTT,q啭F5 h#@=-~62F'msx9vs&S|Z>?v銟)_W(O?b"[> y-VLʣO{533 TU+ho=}Zʨr<9F1OJĸ~|5y&eP%,̠FϦUOC2? ^IJr  N]I r( ,4-Rw6Rq\q |~[ENR#uř@[Ɂ`Stoog)jG/B}1'#`E?:C(w5ȲUE 4ƪF7*Ljm<7?'NԬ43 kޝ}T<:a?$cN-_3R(I%v-rX?MƵ Md0J"1*yW L -jM(MٶjqIDvB%ˣ*zP,l3晀JXi#k<-cԄOtHRE nF*ͨ.'+(~#WɮKw@nOcB8W m9/«/`PFƦc^TF|D兼ƤL<7Vaĭ'j( ijeG&O~ ZhJI$2U#@t8UA ^#Ig]0ִJ@6 }.G4a4 ,Jΰ,fI]5Nf-YGDـY,9v`/Z)%2q}z2F"nB7v%*(*PJ46u/kWű@.ZH# 1p```b86ihj95yW>68~%˼+IP+ <)z6׍!J錹.m#r8s1fR&槍Ab<1Z]P\C2ҤH˻ hBc=>RMjAx鞃2B -P},T>h(b"ˋ|z|rZ*1!Ł7% 0Ua{63k6JeVR±:+~ۗ`D! 󢰧E;* u[K/ʣr 󢸭ӏӒaň#}AH6`XEyM SP[C(A7nzav<,¤EE7n#G겍f[II˫[4HAt=]T:yH*CwRYy?< \kI?]-լG,om:UpAuqy 5 c'8(iwa˳ِ<2 "h!Pn YFjVBOˇj$Zgm B5v'u ^Ʃ*V6`XKkD?p9n[q>#Z栶cAGA6 IѺGSRfcuCs|mxy QJ|m>{ﵔfuy6 @,Quywi򥐒*#/)ՕxV'JNM:*Il%d{ Y)0]A3pj:/[Q j"ɪdU!*u5[0:&[TVPOOsz`Lȁ)+EzcCT mULĦOR~WcQU<ij- ]r*D@t~IW1tlQ23}xo:䬙uK-o{ƬUԐEG̃#/U5%BV@J0:~V,X-oHΩLF{r-c␆]H-dJl5ZTjv"rTy#q x3`RmjЮ}b@=qUQ%-T< kB :Qp`JENә%(rƏuU$Jx _:JeHACƊb-$r0u'؆"jz4 i Q7hntܑ{_WOs*7agLpb4,JA1p"OaF2 R Y@9IxXZD$3Fނ|yhb;S6n1 *\HΟ*۹o(}:mRg wf]$}aLqd%$2O:DSJeM_ɧZYN=y&''43W ]Ÿ{4G$RST>ÖoLaT:_k7-FJ%Zr;JMp>"aBI`Nry>RۛNJK47dVUyzG\o<(bsٙv:o8iDfP[1SS) ^7Qr!|xkO]_':JP"4?>mg@)1L#b B=D*Z) # i+yMvqۡ3"CRO温buMv ed W3xd5ǜ}5jSs :4$O![[ߢ%HdmJ}) ;h1e`[Qh?XYRDRK[TMf&aUI=~DL# -oRO؜°RiXd%D(bRD [rVbUP=o!qL3f/RS;Wn.Cb/|X>5I.oF%j[Ck;o^{L`9ZxP]:=׶ v_8vBlJOĨoH9^z0 SUS5_ʣV[7P}.[kdjs @ )# pzAL@=L4/1~)1NuE*LjdUT!3J/S,r(.//Misr V+epG(6)wqv }0W G28ݐI{v 6caS0U)Dh^R\ODU髛)Ƅ+oQ՘yʫm[ * 4 h&c傡EJJp#7i$2EDP!SR=m>@5HNujyC a2Se;E[|a/2[D%#m?^i fhY$jIx||95O/>y&ӧs|xX-܁sZQ$`#0`0`0`d4#V4ךW)}’ױ ӗ$x13$ETKôe3LdVY j_?5ǿ&HdȵK&INNQ`VVIUF]7e" 0Ќˎ+3 'L26ጮ*qSC;Fم$3ūKULR;\_W ԏO"> 0(z Ƣ9f*3CCQտ1H*9a*PIv/TZc1ɫV)ç++E8J@씎c1\IMQ19-b3/dFow~5\+lS!i"=TqFqK._3E :nt=# A_^*"#AԎEs^ yw=m Vr^eXz RUU^UU=-Hhj)d),N,TaL}>XG?BWVSUAuMj#uCAa:uv{v+UBXHXPn`/QUG޵Y o}Q}fre@Mר߸ ¤/]XZE"4~&|*؇C]BwοÓPHAyl|!|֦K+#@A֗)>݆6s8䞵e5/ro2e/kf|Y)M[nXR%<}>S:lUeVXi{!u%⽄&mǡ~b!8ۂrje)UkYۨ`AuYF+3R7nu.\ Dۮ _6Ad4YAJ$i+)V^ iv*tweB )D!*< 7s: _CO(͔ZϙFzĮ5[a"ʡVSDlM?ͩ\#XtU'"xYPw;OEp%u]Ug$rzY/qCbXRpU `,R#`if-2I,w,7?2bs'y4&K*cO>fcR\,0qR+SK*d]K{/8{&‚##l,1 ϒ:*)"1e.+25 %;ڠyzBƌMam)ê,Cb1 _t@hD.u̖y#[- ]l_i}-,&,Vc|}6?l(pY +!Y߾&oQ*jBGӮLS5xgϖGBKt`UbNGPl|'k%O@tGicٿ|NuU-!i\4D̀o`bFU<o0 d<y!栻,#Z؉7$0<)Q)RFOUBv9L+DU碇ºDwb"_ un"*xAVዌS≯s4NU^YS$ lEpApe̳qTԃ$XH_V`7&*,>\ ABZ!kEkCE0N)o"*j) ى^)FC#XYI`Vڬ; Wo? M՜ș(pMt=R6?8Z'If,l,O%@Ɲ-t*^%'cc⼫fQS$o{Sq!c2c#S~l.I262ci'ИHm|:EQAeHPl&f>I)fЖP/#Edl]Ua]zF 0iu]X\,C\zt[^WTe5k˟/jiVFukwV*J\lA YUqG̎,u50Z1e뇿fղ8X5@aPRv K[`M [Vs,?i_*O jP4s=:iloa1 Ohٴsooy̒1,eMl)6/bln{nq|5+ZZp$>$6h৚t& Ae6,)H۹Y86]5 JqB\2LȖk\j vъu>-6*c^$39$KJ;  n>Qi*DHŌv=+rL͙Cx"ᙯmq&&$UXSM5:$"jKO_&E<L7Ǥ2ôI\s%}D6?o * #ㅘ2GGs^`!}_F;gqTÝKS$ypbsf icCsfTcvh0$#-&'P=S!75\cdS>S-4J$[򅺏ǨֹYOjUON35i=wPvuA*O43PLU|Uԙ<:dGj,ƣ++A؎ϛPslKN.77Ro{I-kz*QrߚN3ȩHLۑqp\[AR%8뵾kZq_@\ڗ>1br=45F|̷Ik%嬌.V" C- wqӽ8h ~"4iQR6\!'乶cVR~bj!@ʁr#m[vg>e4KͩXM!@lF xbj=j*DrC\`mmz3dDD%R'sZ Jr]XlJu*w):uC1uU3jY#&0)+ It0BUS+!zz.nQ,/Waj/ܹcfI(x|n7BOSŴxwP?g51aq*jp@.LաOТ)gnœXX@pF9Fe5#́VO~xS ˔pXƴW@3sSAO|+em!>p;0SXIR=>:Ruy'?`H#X#)04_tVhM=؝ lUi<ۡ;;!._ Ϝ)Uc( UJs\Os$d! =e=Tj: ĘxZJfș}TфDME>ݔ@tn2FǠx$o?EZF`2KM.rL b!ɑ9Y;-~WXjpPv\=U`M[II!IShàեkMzjt,Dʠx%3p{ "IYIkY6{'č *f `o!2PL8vt8;*I,ṅs1CV?wr]Ifk k =5 KF>S0q#P64zusK_baoR1$M8ܑސRw ]4lTq1!/R̘ȵqV;mՊ GQqQ"ؗqNҀR>A>eE#euY7o ~#&SM5<%*t{{Xy{'֫gkj,JJۗp"$J%e+,O,~d$"J8GlﴼY\W2O(h` {n?) Lβ3uRd+1.mGH mF\ʧKĸ+Q2^c:Wb-%2tψT@IWeVgU\M]N%' c1cG >%)s^/!FCX%G,4K:,qBTX|Bg`X _'DW6][%5AX2.<7I/fse^Li67)OP>[H؞x@)AU=MU'>"IZݎc(8-XԵ8#p XM_@ ?A0/8R0g$j4ƽ.UėQ'ՄH H=m1]\e(RrV"ija2N),Vڶl;z:_4i \ik\ !R!c=h`T n/zk-\4®c;YkA;;nr@kv_1A]xDG<8,|S{ opqgMܩc hJ=Oon Y*hcX X.K\ior䬮f.>.J;Fe`u {t&{naB-a R˄lHot0p$,SÛ7_GӋ \Ox*"C!TEArA` /յE#)~v&=|pY:VΤ-*c`X#  ]f$6qrn .lrڇC]`j=Ib/۶9(3+Y.8U +YQX78.:0ϸN/e,p3'{LN02P2u-1&FzpY1Tb3*j':ƙ$@,tDʕvrVV] =BQMMd6I(ﰎi> .|j 9Uۗ4+lLcaC)3:.r3#Ũ1<,@d~5OPK JJ0,O#J1QtJ1x\pԔQe 2>lOqÂx,fbD3R}@),lr-sgLFXb*Ȱ`     #GE?c)EE!K1:.ִy-eAt`ncg7 e9o-GJdi"7 6b>OIlR7.;I|)C*rll}z#00IWv^w i!;d'$&u7G_ T)QM8xE7A3B9uǨmX(,†]%I#NtbGC,V:R8/ݐ {\>)"JyU=XM &ч^ htNZoz< !y>" On3|:zgeMަ6wjdU $9=y{[Xq6Ys@ѥFZ1,5\ @2X8#u-E٬$tPa+;wu=o?Ņc=< 3D OS@kcb5Yi&+RK3h*2B,%X@4LKCp<1Z&ZJDJj`uSHn:{^eZCQC"kmo7#I6!o8Gxb|eȈfb/hKC,`0tv vӘ?|FWKT>#E:Q 9U.pFܜ=Y[4lC"ZA#T$?ETg˧Fy]r n\j)f 9|5i?0\pSȠkAt'MkmX9!2iV^zrl*xT-k<ŵX ?J YRq&m^H3S)!}0CfyrO!Muko 7桬M-b>8FᚏL1;,;tR&%KS2pQYQ.Tr?u^J&(W*x7I8`7NvPeکgLA 1_mA{*x>/)ڝ}B14lfBۦěß*Ƣ(($l5[6=p+8|jLM .Ê8TyFϺNSnAy(.sU]Z (wqRfϐg2Q\Fؼ\ʚJh3¶7[zOęEFyFb3˔ybSqv]8E~`^P P8yb2}EIIKs8<סG0(byU)~}qS#}1cp}HUCC2ʴ  7&Kog*:gpM!4T+9bӦ PZI$·6ĩKy+b5"lŬK8o>zrGHs>1*Ic!k[̭m%ļǹ "ݩg04yo޿:33q-c zi>-/ҳdRc#,6.f{YdN**Udvpwf\iK1'O[4mm\rc JI(R:n0U>:p}vaJsC Xo:WT*~q=@UTIe-mbp^7f)SPvR\0wZjɪu*e _hzfQ 4A>?̌3 .\@}E[EG!9$I>WdRWOr\n28~tKK.D뾛a0i8rԥRA6KR@GV*Q6)!ib3 yhKcrL+rn^&S ׅ I k;0}?$?/[<:6,_PGb JYVb{Xo+ermPط$[ K>-K|s770ԫ4Ւ_~# zwˢ>-dUH5ih<4/$cH>z|RR޶jb,cx(5 فhnvy~/QfZDIE$r;#XFЃ1NGD2B Y֌> {sz6}pv#더&@h(#, q/1}3ݩr~%U,SSIA(F_W|s`؄+1U߆R^HhpQRN4-PWP?ZBE9T+`/YO޻ztel2elɖ)M)rb;=Fy*TɦZ5kqpypM|K~`V*AExE 4"&1`źߊ9RoGGHaB24جhGY ?:8Yu`Wʞ03.ӓ rGD YI3cnNr#O_9;w?'F)=1);I뱲L9'>lgلtTqĚ38#If@2OS nbqf&3)BD[ 8Ev_q^BfdX\!* ql=/~4<ἶ CR+$# \ŬXAgyb edw;{ҿM/_krz'-SӲ-Elo^opt1je ۠>lt)c4I*h91.,oԮf;, y MH0`0`0`1eTԍ]JRrh@*uvP%:jr-"D<בC5pNkMMSJbrҳKHi"b,+%}r %ƌĠAX:}^@D .O>{\e%E4uSX@"Y^Ƕ{.k3)sKI;,rׂHh꣞v 8**.t+6UVſe43DHVC01dEZGY4b<:%2].C/6-d-tQxZf3K*#:BS}~gn֖8 V]:Sc+8:dHbjO j1l$22xA($ہfؐBXl6]8StEOK(n!I!dty_)qDBT͇APBROP8O*f[kj[#~],#q<X16Y GO)j;hieDžSN+ZGym^oܿ3s*̺5Gs|33$\342#sm氱t̪zF Q]F޷u8f⨉uM+5W=5^ů Ƶ⚾8&u֪0Rb,9%`##Jgb;"%%˥e O#{t6M=Bpkh]Vs,DrڬAm,.- }5iPu[p;j/3TR [r$H,mo!ON8-|I9e&(u5pli%p>m:Q:%}WUg9~[5m.7G'բjB!:`C`m ["7 /\2%YҴbΒ CMuhĩE=8>ׅp k ;[Se- O5^\jlCj<>9t0#Gn qvte(@O[^ȁm~Z9'P6@;yDxQ6 zq*ÌgsiҖ4۽"C9Ap7#8aYs:IYJݙXR@=olV(UM-nWK+hՙl{t;bǰ5Ie𒔖Bbsa 2Uez%`l>A A AԴuUi),Dh\ 6w.[GBGQ4G 5Q7{A,nįNqC[fpCd)j,6E6 n#@ԦEÍI|9 Rft).R5:22wBx^|=r\I*Lˆ $UP<ehI dXQΖig_-nIcb:{{[84k[F9ƕb^IVM4W)xή|<>˸&2nܷ$9ʅ5Ya@\]?剺)jfY$Y=A{&ÊY֗03ndmG@/lI eLUT!#^w2elF;# \958=@Z[RKkI#2T<꤫!,Q"lDcز0F:̸Eٴ-Ӭjb]Hvvk {\:v͗Tlf٥UKifjRČ{:,(fJH" *n/.z8)R+pf2 -l2K_/+ ؂݌hLzm_/8ׇеT亃`W]Mh+2Y1iڏ0;NɌ\oլlG6pc]CMeҤ( ^)Cbݣ+KM* :dE`w='\S(PBKǗ]v ]}4Oad)r}A YI-%Ubz[8h)6#>ޣbF hn4z[?Nt ckMB~c-uSPCLDU2fʘq Y*Vzw%lAk>~~Hڧ˫UUсP~#|߯lG9\5fTˍ*B)"-˻ /~3JJb Z5-w#I7 cΖ(j!Yؐ'[IӮ k⭪8!h@ 6.n7.5e!B{y=xlSw)Z{ğWTd\sBLr+pH$ vfYTYs J b")ڡ e4bvwpCTFK.ѐ/ak7zza? ELwcw}*D䛟_[K샷Zj誩RyAA%̗f݇S8:sCۜuiH/) +k믬cݨyfRu[?kHUseM*=~Ɵf1[?߷ᄌi$:jRkq%ɩIBtjSvSw"_8 "`^O"00ӥnl(ai>pOU;lt턪&**hcURAmCM܁{in M4K<-`՞[re"P+R|tS(!}]٨%{Js[1ytLV~x2>$C,zJu=@e+obs.U=>S]4,'C&D/O0Sś_Kl1)TGת27uao8LG*h{ؒV.Sc,Po|~Q!KLK LK:U$+$l\Ѓ߭cc*0&2BDjV8Xڀ,PaЂYl,=jj֎J6f b`?tF 2-[s'O) e$ |OKПI Õc/NDWef#88W2Kw6rz&aN/$7azUJg gDÖi[+ ,ޖ3&Oa;~7&9/N5|\6AP۳~2.pfE*q8%OBfuYeS0HwrvUPI?))LbFR!$`^mR6z ?z2ܣ1J}!JVְ{fH*M2@Ѕ: HG]tV0/sI4@|ɭ>D߬u};CĪI_̭{.o[\#ƛz1SK(+ F6iKrĐ;* {Ϧ*u;FoڟiRJ19rE?dSQ 4e44Đ pN\nXA QɄ?"SM:`O1QM:aH$7G< \LV?[gUR2jє%HnPIWGyU'Xʷ8en.O^JGf,]17I5YeڱcKfi!ĤsrlC'Rﱇ W }ag v    ?7?dټr¼/O cEO4Nژ 1@v+K=!@8cb DY3U%ah-<<8ox Syȡ2c ,CB )SL% "o.,ܢ-HV<vI54&h,Kj}J; *^BN:잦|l%F Fz{l =s?uTe{}q~ATm APu @'^7a톜s fQ c<f1bXèq͢/8Ӯ-+>m X vQqȠiGV[* 7hc~6A6Ʒ3|)eB:_ _r5E5iA<@kX.H7\n]RSgNW6:?2Mh?~3eu43GQ[dpR̗6+{?po7*>@'Nشhx&W14n~ͷ{-*5͑]Q·4Aث0_؍EFx 6+,Sx]$!’u DBrFcp5ᓘ$w =z~]y'fqYofʮ)1IBI$V8lJ\*ڨeXJI[scnZub 5|>vwOh\\7-؃v--XQʗ</!y+9&$jC jjSO!v.$ 1Υ+e+XϓZTXJu'xjF+SE]Ozu-!td`VhKP.Buw <3@T&V.Z6"7=?4E$3OTt O4r9K+Ze.H@_ʞ4GVJ~)?Zf(*\eN+ ̓~e/{/E NUJhx)0l5O"e%ΙBm[ܴx2h~V$eD3@_ D-eW˶ wff<-Rr/RBTةSE$J*V17Σ+ٔ- ;NY 2;= S`\uuPYkc.9 ^di vO|Wt~q&UK$Ujq+e1 V{ $TdӾ_ț^v$Hxe?_X|'/P ,2. AYKq}n]U,jIpG]g:**̲h0à P M;Y5}mX6Tjx_ue"ġomomJNi 9OUȴ\=IPfjvUZeÆS&}tyu~T2#ᚅb!Yw;> nA6 Z :g%:RT,^#E!Hb0$n`'}6s{LqIaʹj K HpAA(R*Dbe}=0 \~xGb1" *ˉHHܷ ) z**'H@gkZڌdcz tZMFu=n6- #0R`,"̧Bj)F!(: +F,T,{d݃Cbʹ}xl9mL#x0Af#ۯ'+3flY y i=4jiht?) aaoz8" a'C&l*t NYG0OD,f?EOR#H&(J\7A{lbwZHiQ*1#r*ZĆ׸#F|jˣS"Z3#2KZNq9Hp_rThk5l@7e#q ὴmv%fX tPKNM9bҀjFL}r9srzi"O+BKO9Rkn6N7 >̧/MOP)y ؓM\u dTF +" j9*y=bx!) l*Q)6FX헕JʞN?"DspFo²TO,YeDt[ʺȮіB"k/r(9U:OM`9IV7Ht$o{J悮)T9^q#Ê^ʇesSO"*m E\(6˸-s_{6OE$KYJVK*XXfJ@7JTS IKwvx3,yOQV`F@QlB ،xM4IeR7lƔ԰|LŬ*J}>kkc41,4Tr<ܽomf~b"_`:QluN4h% ']yY|c5Lp[FBئ7&﵆1͘TE TyV9FC{8řS4E=;FY鲀#y=wØE.[W:3I"󣑙ZJ[ؑeU:U2Jl#r h |=BV?Ս/xkdR?X<;ƵIuWKQ8P.k1)ln{c "Z܆s(O!]* K5ԕULzH>UIx*havr$bQ&iWWFEv)7-Hsm6ft Ir(ahjs$CA}eaH. $ 4~4r5y_b~r IM( YY`I<3-:n?\UVE]uBZXM+ yYmkc>_SM4huGŃ x;?$x?T.[ޜw톜i(ZK"VTMINfV4h~qJ<+M=߱ R4_!播b5 +HA:EFcW<T4yl2$,u5F @lBDre.]2$rT}X}LEq<_ *g7TWvŠK[BeFg`B0$seexi,Ft*},vzzEidTu ?mռ-ڕj\9~C4X 3pMVi$"i(P!>==1QqN($ K€obʔh+!zj\1[_fkV̺pX=K%JnbzQ(eflto'~{^ 1BC0`0`0`\>y9b;|epi()*KAkR,Fh*Y[bE#3c )87³2S,3k>`/,g&B{|Ek=9KQ-JZa˨5ߢ7gW>F q gIxjer㩤$(IS$1U-+j !L`JM@$JQra1O4R6onxх -M2ꍏPjJ=D 4j%=lEs<…U3Z1SN<^`,=qC=)\HD}܃>cE&*L٪%@Sk`$EMQyosNO=N.JXTic!o{ o 9dDMl 6uhI[8kH)zecranE.SAnv]#1ǀՃLs*Li!r]KYbnM:2n1RzGCo5k.m6yB92]-"ad}ͮ'l3ܞqDQ&[Zw&֊O- ah1мR%6-W?&PP͵Gk'oGS~cb,0#R,Q<ء}\.'`=pWM_ôR,b)Бd*w xq*^0CCT:ۋOOe߰8kR9t b=wmo-m$t0g ri&ZD$ą`3QCFg-1ND3~LwPydX0*M5aD$^PFB# {ѲnY qU˄K T?a=ebEn>Uq5KR.#G7yGMٜ?WWY[WRTuc悡IYIkzEn ̪!\LhHԠuH{o닿qrLI+Lî[0H}0De=Y]EE)삂벚i hH%Nr(b9 獘U6jrAX`w)7*C}>} . `\8٥_˫ؿ" UTrmK)*7TO_N"^p*EBP[:kaU6_2fUen^!G WPS.xdҥU~IPnj:KJy#z}:#r32$sR&wI&y1Sk_Kױ ` p] EihBw@íff]q66sT_ WOKlAkrn`#aIL\ц[ ;4}ۧAiet[.I7؃b,AJْ /3<=ly+slY K)m|D4f93i h0 /} v8.#tUO>` vt@G*H}Qnj65s2ʢPeMΠGXzS\KZn'7 $et%Km݃{)R_B7<'QkPWHQ}/ X ؼ)3.UXUiKTlE6MAF1Xq w֣Fi% tAr@ة&J'P OTΤ,(~V\"GQ4!Ձ:m-vZ$V{^\ՁI?yO MMU5#/rUcqЍ>(j\,8s <gr$dMB~IƼtajH:ך豱- ˏ\J槑vITGI* qFT%4lLF`?up㭽qe򄹲ֹj@r M$YD^\L1&ݷ4l ³*WTLE V D]lsI\CDE K %2Zļid%Ch&jsHO-r-oԋҍ%*c52,'cgMQ -$8m@lz)w`aiqYlfBS5] 9RN_hH82֩ ,UkݚA#ֵbT訍x<)pt܍@jXRv9Vo*DPm2z;gy.}EGQSJ0Pn W= !b^+ƺg6$,]tu)'L %P CA/Ȇ]s^ci3JA͒24E"jU$cz*%MPif6G rnolFKPY DSL0܃q-ld:GwlzBU0o f@`A%Т\e%\uuM]J܍_C|NY SI\s:tV؍H3fqAd4],H" sBnoyKHNu)L-ssFe S7⺚' 6Zq%aZ-- -sh|sY(A S,던fhdZyI$Xz>ZÔLBC!PA1~]-~65OH8Yb6vcH\xu#) ۠N&4- $x?,_|lSY\gW͝BU` wIJP=uv@lp1⒪ 9gi!$JG@:n=IٵlY*d`cZyfjC-fRB׿)bY7'94R 7$K[Hk`.j>.|4h0`b  ##F*n6 -<=ދƑޚ2#YJđ‘sO-nl)(!R CQCcCx%._ÿGV-s b*RiU }>oWFژx^V)[0%k~&!+5E~hʡAʑIPO\v[<+X' hA!ZK5U#YǼ`}BEwm Lɪtj|:gJZFb#"lCcm6®ykSq.T; ӚRVhZtTG[܋}= ]S3k 45R\ʋ&@GJ2ˆOd@I?ǜFd0G>Lxc;t(e-\j;/\QPTer'f-3RAO_+BduGZ#>p>׶C1dpOVp=LJ G_&e- Q9Uǭ:}a2V^ L.Y\tܝ>J,,PHYCs%MtiI(RK$1usWU 3ImkߖM`;[OgZ^e5d&4mX>^Ǣ⑓5amv{w&o4+* $YN_f~&F{{c=Y*J5"uхk83\:Zz2%h˸ܨI'i>dabɳ200!v[ lf \7s ,UJx P(k\ܞM"/]R$ \0$5(:Mm5BB`*nװsr1CFr=+?@dk1 k.j8^ 68 Od-aS\mbK;ɫb2Z'ZoE]m{-{ig4#0x`)`t\ -G{}#-]2A%)qmͽ/_ٟ Ƒd`K݇Yv]ùꜫ8ᖙIM[zUϼ9)j5; ٴ?~1E&B]ɃPC꛱V,b^n/3 $WAyrNf<I97MùQ]D&y`Qe:ݕn suR&rb&6}( Z$9G]ĴԊ$D70$#XKR51]77S|tZl1kxXS+W$Ը-6Y)S6u߼@1#O% K;D8RS\OEtٽ*'D$HITYGS^v XG[\8ޭϨ(+k'(gf]^Ftv"Z +s5T%o nVݴl[48=P$g;OLP;6Ebr嗆fV|Rr\cf#UiE(*ٚf)3Tz?80``   #= }vYWaOIUkx$1z-?Ltτ?eRőx"p]f@-tkb;©14P#ER|(үé9FMRG8.3HU"arݓPUJ6cr3|cD:Yt ‡`WHmPs fOfP5oSE_ QJCF @] !׷6f (^tC`('QU jb4c*✃5U+0vӥAqm62=QH"ٜ YĒzBq/\ɡS@b :ԔUO4e0(.649 B,M:/.q+YqU;$Q[,IHGW E@ }7]CŹKsƟky]_~n[lEC,c6Mě\aM*ny +PAG~"QDi NN1a1hcFU)Х$ SYf *occ=. ņs|0aY$qRK$n&װƫ񤲰z m:}O8anT 6pĀOK1~j̞s.x{=G|l-[¦ibd?^۾3\IJ*@Īu`8r!i)s>ӆa_ma|a˝n$Zʪ0Dj/$q[] ;I0z}Ĩ55bl-{@(\´>c*VSPa[$h/-&XQiu`Tsf'QGI4'ݮSӌV|bӛ.3(8i {w=oe•Ҙe,TFodFRKm{VÇ敪hjeەS r%gPnCB'%J*I3:]IpT&E(e>xdrE(+0O,ЃBMA{XA_dhD2( ?K/1v 4n w'2Z8 jJC,Uuk D\q+'MJbeïU <uhĀnvy{d&v7I!D#*^ŴxYZa(safFMKzZ6q齯k)鸣-5(kR#82.,C`scYT2i\hdk,lPw:I7ߥ瓢|]KTkXM Tb B0ljLrH )RTtpW\ii)jlqDiOVxs4fZz%u ayu~]uBj%I5ͱfUMk2ߩ=NުX鑦zf2jS^u{WEQQ4TʖXQ]RH- 40 ƴ<rQ$z QPR4zٮ>RA=} ~VwGGHH*m{Ar7?^*,)qU{7V]0jy+K7ē­vb@=E[pl(u-(RKgQO4H#_׷oWVQS]8I+iQ`s>zʘ4`pAmmɗd/M 9Ykڷ]Ru GW;AUmZKX߂媇Dt)i-3:X`?m}aJIGUD٢%lE,{}3Jlڲ eŘƈ*)(YS潼ۅYjhW:ZYgz:FX v~UU\JƐc'/t$1nB6d @K MR.3K[z\# )S2v7ݬ>f&GDШ7:1% ~lIe٤ 1'/?랛$Hꦡ Ȭ*UV兾bI6P1&9 bi3\u/c4+ȇ,s6w?|ኯ;u|Nܟb^RU̪ټ~aPvb;2a5(o 3ʚ5e7GB bqTLUXt%Ey1v$bFeZfr=䞰IER_2Rreu8% è ±[IÓj *ͤw0WҋM+ SM8++3<0Ͳ\ƪĴ44R#O8 K_4_@/6_ZQ`1Ł'Z$ؓæQYjшpP J@2KOho3Y2%P\q6+(vlSǃ^+dUC{ S8?);l6Cv-`D&6-fH@LsՅ^O8C"8 (sR #yg)'ᘈ!c-F z*ʾEJUӲp,,k؝ïk^fBύ_'l@RNeq$h݆ylCk;b°j^eѠ0u Nh4f0q? 5hnr19K]IUfib UV,d!':HiU- @#f Q= 8sg*JLכGJM]@ ~UuZNHȖ%ERE[{[l3RW,Hbk|I> /YEOSic՘.X|@ .b{ MQ:f1T5ԟ9JGS5=U[,0{]/ jl^i xkP:o~ۥϳ`fd3%p:UZO+`$Kt=mߖ1R ܩ6q={@0Kyܶ alkMxpI8\1'1 @nRT/2oC祀m)5&6UyEX+tzizc}5]+SG%4% )f!clwXcYk֘CTTE]N؀q[)XA$Tɾc͵=nOKD뤛hXg< = UWqHԊXLT8?#̿ҫZ$op+@u :V76tǩ;L?p$yP@fh#]9Z|dɄ#q0Xлy i7܃kðí6kR3Lޡ4{X)z!LT]PIفa.\4M,MqN)t؋M\WxH=Sa/K?6+p9S&'Ȼe2n)iㆂF(s&־ڬHϳlţц2\Gl{;7@@MEUSH!iuj_ja"FݦP5{2癁s7f|W$r*K(=F6 {oP\u5 ,pkq~[mr׿-nbD`bc-a@'okcR7rzLΚ!2JKb/ 2n|_)0LGd/FѹDMpj G*!@HSoܩr;/BST Z+ bzvJj4-|Xz%RGb\k!Ǭ& <|*'gT`}cm*8{*kgjӮq{JR h#i竚TE&k1bH#k k0Ks=.~QtL '@IS_ax֙P]F߭Rfl瓗Pa2wfzӦl7e"~TDQ@fbֳyOFq 9M#=\lu_ \:lɃpܒoȹesn_%*)J!w;zlm튗O3$*TVUAӯlVئ=q0BnENjۤ>p2QH0`'`    O \BGW ;HZ&=VZSun F Y̪$@#|1ds%٢KHmll7'[CQM._S2F=]#kL`ŁCWZWdmb FVikxb#M(^dS]Q^\cv;) fhvO(\7풯+URZXÅ90i*@/+O0S'>VԚPSmp73xYgLOv&ۏm9ØWTFeĔgΪ4ZX&j $IӸ^#fp\A;>Y5JMHӮo;|]'1t)Yy 2nnz71RST &ߧLoS:%=oQ,Sݘy@;+wT,-STy'VC>8_ ) :ZyTTVN%B)[K|؜b/=lK,4`U Ś|&e4eRCT76|KLϜ L<А߷wlNRq>KJب Cr4Z ^ uT3S%Y,edt`7*Z ^bߗ#5z}OQ,VfzQMQY Hڐ^>bn<'1iV d *NU=P= uIwAr:Vadb >aٜ93I yFw, 0q`.-7*2fJYgf12 @kO1:w]/A6 h }F08VQ H+Irl n 3V96,Aq0fǔj4/,PU%WDl`ʾ_-U,LNX(C !ɿM`LGWMZ^'AMӊzhvzdg sō]^.;r`l=b6 tWOnVIh9yskH 6"y婥(<`E6]ŕUM>z] .Dhbotcnm6̛)*zz+XSqM%%$$rd}N4KTEߣ|4iLK!7^ePR'rn=7yjnG0A{Eab8ZNcH>62N8 zň b؍`7pJeۖ.-%H_r _NƔ<,e(Mmk\2=T G ;3[b.eC*DO0B˾N6eSR+,b[/}nN4'(!iGs M&1a)%u!x*ZG*.$/Q5ܞcV(uU{T6[kZj6YiF[YHQ:czZ]Ҡbt߶HA$;[s cԤm[a(VS6KjON,uO]dfԻV[oq{v:,pL 6$*eXL%#p^1D6͋ 5Թգ<(/^1.c="FELF& ůkm W?^IV*jʥxRF Yqct0,8jFx:U)h,[`?^zFE4LH?~~p?TUA fe5 6*WwsZ:{0{z=pYF.UZInq{}}~Rq9I_c[-}[DvǙ=JTyS{]G\*}[_GU iU7RPo}y-eE8AM m'FaLke)d54r)0%u>]ߦq+0ˣfV8,Y$ M$" Re`YC[S );6txr Tbt@'mlf㨆͘]Ak^ڙϿK {Ch`Q* 'zeԙ/LI$0ѕai .,ib `X391lɪ tgm5o+XQMrM9` ;=,? 4)d1P7 "Aĩ,Q!M,3u!ōa0y'gD=̷X1>Jj<mmԸT(f]>.ҵEK[<$1(ejunG\XR 2^ntOSVXPJ7,H^Ө*w'%xVBt*'7Gr`5NjKo=})j*T0XXw(AxjddQ-\ C#ENRVTsUDZhf m6[ Y)-N#*1(P3n`,4о׸oH>"h5*(r˽C [9WTd~D61∢Q´8rFĎWU9_2XjmT)VQphQ e 7 ʱNQkgB5\SC9V1VnImМh7 g[QY Țr9*w.ڗx~2C6'qƵgVDY#.Mcp}{1 ' R@ ()JBFWEn{ɵ'HG5vv2HbKmvZ%xej|+?ȳFm}SWf|Ss1ӶX6m4MtPUizR4:F.~nQ7 X/ JRN5p|e(.`8(iQ́&H#-BCk$=Qѵ\Q 2 ;YLkB҆w jX {o^~nD宵²({opcIkZ slnH p$6b5 %%<!Ī[)ʲLdA4 M|DZIyY\v9gʐP2$ tdQ 3 0``````````cI$M7d#yIZ" cz : ÚU &?xۉ! `]z~"?,oGh]$EHOHᆖ .,o`1x  Hԩ{(6"ߝ'{EI'%@e%']nҙPLwqR,0zzY̬qo|IR UG<1<$]`E[ N@ϕ-l!ܾŵk27ٷ{PKM3S|E7o=Z#H呯rn6f ,NSb̐S`6;pIysNGFV:j6^3%wz j426` QU آ!9iT6fտkGo9"_M/KKbTj+Oi/jJC~~qk45U/ż:Xcя@m#e2(4O2 E7kOչ55Jgkq$(R._5PO58eaW.ȴ@fPR[M Ha:aV @FWi_CȁAJ[BHnB5**,&iMb%ImGWK*&hR]Y m}1'GbH8Z[\qFv m'4ʢBeYC}\*wK.ߔct<疟ciczGKNJHx22 B nmTbHꡞ]LP)"CJ:BhhÛ7sۦ+Rw/{XP3XZ8YmXbien@R-~Wa$rcf[X۹>R]$bYD9p4uæ3 t1,w[_Ԟ٪`Z;6b}c*j?_לh_X֐8X؊'4/-P式FH,Ņ:x IIUah-A__1[2>\aH\C$:А:u.aHv{Fk@,YǎH8ȍq,C6Gݏ:1dHsbU#Z8a,|);6!5E-qwuCGq7<) R3..P9bEjY>Kb9qEj^@@x(X ;Z?PqUW>y,n:1˶}l%#ۣ!ouNVg2Pt+R<@>:RiT wpu}G(Y`esjAxrPv sMPкTIS 7mjev(\%)ES;l-o\c S$1,EWcbL.rMu<,[dw9G*I9$hR a~Q4SQFS+OɆF,Tj&n}XcS/54Y>A˵`-m@mʚx3 O±&Tؕf6-mU)Lԓͬ52}A9oMnFgTli̊ʚ_&)>yR( 30JLuS+:ʅX{[#VI0ɚsu n@#eӨgKF(׎:bb{^}sǪJyXt*:{L/Fıd,$9]$nMo`wQ͈%6uRA;8\- Gw2am\wk }CB>> from skimage import img_as_float >>> image = np.arange(0, 50, 10, dtype=np.uint8) >>> print(image.astype(np.float)) # These float values are out of range. [ 0. 10. 20. 30. 40.] >>> print(img_as_float(image)) [ 0. 0.03921569 0.07843137 0.11764706 0.15686275] Input types =========== Functions may choose to support only a subset of these data-types. In such a case, the input will be converted to the required type (if possible), and a warning message is printed to the log if a memory copy is needed. Type requirements should be noted in the docstrings. The following utility functions in the main package are available to developers and users: ============= ================================= Function name Description ============= ================================= img_as_float Convert to 64-bit floating point. img_as_ubyte Convert to 8-bit uint. img_as_uint Convert to 16-bit uint. img_as_int Convert to 16-bit int. ============= ================================= These functions convert images to the desired dtype and *properly rescale their values*. If conversion reduces the precision of the image, then a warning is issued:: >>> from skimage import img_as_ubyte >>> image = np.array([0, 0.5, 1], dtype=float) >>> img_as_ubyte(image) WARNING:dtype_converter:Possible precision loss when converting from float64 to uint8 array([ 0, 128, 255], dtype=uint8) Output types ============ The output type of a function is determined by the function author and is documented for the benefit of the user. While this requires the user to explicitly convert the output to whichever format is needed, it ensures that no unnecessary data copies take place. A user that requires a specific type of output (e.g., for display purposes), may write:: >>> from skimage import img_as_uint >>> out = img_as_uint(sobel(image)) >>> plt.imshow(out) Image processing pipeline ========================= This dtype behavior allows you to string together any ``skimage`` function without worrying about the image dtype. On the other hand, if you want to use a custom function that requires a particular dtype, you should call one of the dtype conversion functions (here, ``func1`` and ``func2`` are ``skimage`` functions):: >>> from skimage import img_as_float >>> image = img_as_float(func1(func2(image))) >>> processed_image = custom_func(image) Better yet, you can convert the image internally and use a simplified processing pipeline:: >>> def custom_func(image): ... image = img_as_float(image) ... # do something ... >>> processed_image = custom_func(func1(func2(image))) Rescaling intensity values ========================== When possible, functions should avoid blindly stretching image intensities (e.g. rescaling a float image so that the min and max intensities are 0 and 1), since this can heavily distort an image. For example, if you're looking for bright markers in dark images, there may be an image where no markers are present; stretching its input intensity to span the full range would make background noise look like markers. Sometimes, however, you have images that should span the entire intensity range but do not. For example, some cameras store images with 10-, 12-, or 14-bit depth per pixel. If these images are stored in an array with dtype uint16, then the image won't extend over the full intensity range, and thus, would appear dimmer than it should. To correct for this, you can use the ``rescale_intensity`` function to rescale the image so that it uses the full dtype range:: >>> from skimage import exposure >>> image = exposure.rescale_intensity(img10bit, in_range=(0, 2**10 - 1)) Here, the ``in_range`` argument is set to the maximum range for a 10-bit image. By default, ``rescale_intensity`` stretches the values of ``in_range`` to match the range of the dtype. Note about negative values ========================== People very often represent images in signed dtypes, even though they only manipulate the positive values of the image (e.g., using only 0-127 in an int8 image). For this reason, conversion functions *only spread the positive values* of a signed dtype over the entire range of an unsigned dtype. In other words, negative values are clipped to 0 when converting from signed to unsigned dtypes. (Negative values are preserved when converting between signed dtypes.) To prevent this clipping behavior, you should rescale your image beforehand:: >>> image = exposure.rescale_intensity(img_int32, out_range=(0, 2**31 - 1)) >>> img_uint8 = img_as_ubyte(image) This behavior is symmetric: The values in an unsigned dtype are spread over just the positive range of a signed dtype. References ========== .. _numpy: http://docs.scipy.org/doc/numpy/user/ .. [1] http://docs.scipy.org/doc/numpy/user/basics.types.html scikit-image-0.9.3/doc/source/user_guide/getting_help.txt000066400000000000000000000040141223313777300235120ustar00rootroot00000000000000================================= Getting help on using ``skimage`` ================================= Besides the user guide, there exist other opportunities to get help on using ``skimage``. Examples gallery ---------------- The :ref:`examples_gallery` gallery provides graphical examples of typical image processing tasks. By a quick glance at the different thumbnails, the user may find an example close to a typical use case of interest. Each graphical example page displays an introductory paragraph, a figure, and the source code that generated the figure. Downloading the Python source code enables one to modify quickly the example into a case closer to one's image processing applications. Users are warmly encouraged to report on their use of ``skimage`` on the :ref:`mailing_list`, in order to propose more examples in the future. Contributing examples to the gallery can be done on github (see :ref:`howto_contribute`). Search field ------------ The ``quick search`` field located in the navigation bar of the html documentation can be used to search for specific keywords (segmentation, rescaling, denoising, etc.). Docstrings ---------- Docstrings of ``skimage`` functions are formatted using `Numpy's documentation standard `_, starting with a ``Parameters`` section for the arguments and a ``Returns`` section for the objects returned by the function. Also, most functions include one or more examples. .. _mailing_list: Mailing-list ------------ The scikit-image mailing-list is scikit-image@googlegroups.com (users should join the `Google Group `_ before posting). This mailing-list is shared by users and developers, and it is the right place to ask any question about ``skimage``, or in general, image processing using Python. Posting snippets of code with minimal examples ensures to get more relevant and focused answers. We would love to hear from how you use ``skimage`` for your work on the mailing-list! scikit-image-0.9.3/doc/source/user_guide/plugins.txt000066400000000000000000000042031223313777300225220ustar00rootroot00000000000000I/O Plugin Infrastructure ------------------------- A plugin consists of two files, the source and the descriptor ``.ini``. Let's say we'd like to provide a plugin for ``imshow`` using ``matplotlib``. We'll call our plugin ``mpl``:: skimage/io/_plugins/mpl.py skimage/io/_plugins/mpl.ini The name of the ``.py`` and ``.ini`` files must correspond. Inside the ``.ini`` file, we give the plugin meta-data:: [mpl] <-- name of the plugin, may be anything description = Matplotlib image I/O plugin provides = imshow <-- a comma-separated list, one or more of imshow, imsave, imread, _app_show The "provides"-line lists all the functions provided by the plugin. Since our plugin provides ``imshow``, we have to define it inside ``mpl.py``:: # This is mpl.py import matplotlib.pyplot as plt def imshow(img): plt.imshow(img) Note that, by default, ``imshow`` is non-blocking, so a special function ``_app_show`` must be provided to block the GUI. We can modify our plugin to provide it as follows:: [mpl] provides = imshow, _app_show :: # This is mpl.py import matplotlib.pyplot as plt def imshow(img): plt.imshow(img) def _app_show(): plt.show() Any plugin in the ``_plugins`` directory is automatically examined by ``skimage.io`` upon import. You may list all the plugins on your system:: >>> import skimage.io as io >>> io.plugins() {'gtk': ['imshow'], 'matplotlib': ['imshow', 'imsave'], 'pil': ['imread'], 'qt': ['imshow'], 'test': ['imsave', 'imshow', 'imread']} or only those already loaded:: >>> io.plugins(loaded=True) {'pil': ['imread']} A plugin is loaded using the ``use_plugin`` command:: >>> import skimage.io as io >>> io.use_plugin('pil') # Use all capabilities provided by PIL or :: >>> io.use_plugin('pil', 'imread') # Use only the imread capability of PIL Note that, if more than one plugin provides certain functionality, the last plugin loaded is used. To query a plugin's capabilities, use ``plugin_info``:: >>> io.plugin_info('pil') >>> {'description': 'Image reading via the Python Imaging Library', 'provides': 'imread'} scikit-image-0.9.3/doc/source/user_guide/tutorial_segmentation.txt000066400000000000000000000140611223313777300254640ustar00rootroot00000000000000Image Segmentation ------------------ Image segmentation is the task of labeling the pixels of objects of interest in an image. In this tutorial, we will see how to segment objects from a background. We use the ``coins`` image from ``skimage.data``. This image shows several coins outlined against a darker background. The segmentation of the coins cannot be done directly from the histogram of grey values, because the background shares enough grey levels with the coins that a thresholding segmentation is not sufficient. .. image:: ../../_images/plot_coins_segmentation_1.png :target: ../auto_examples/applications/plot_coins_segmentation.html :align: center :: >>> import numpy as np >>> from skimage import data >>> coins = data.coins() >>> histo = np.histogram(coins, bins=np.arange(0, 256)) Simply thresholding the image leads either to missing significant parts of the coins, or to merging parts of the background with the coins. This is due to the inhomogeneous lighting of the image. .. image:: ../../_images/plot_coins_segmentation_2.png :target: ../auto_examples/applications/plot_coins_segmentation.html :align: center A first idea is to take advantage of the local contrast, that is, to use the gradients rather than the grey values. Edge-based segmentation ~~~~~~~~~~~~~~~~~~~~~~~ Let us first try to detect edges that enclose the coins. For edge detection, we use the `Canny detector `_ of ``skimage.filter.canny`` :: >>> from skimage.filter import canny >>> edges = canny(coins/255.) As the background is very smooth, almost all edges are found at the boundary of the coins, or inside the coins. :: >>> from scipy import ndimage >>> fill_coins = ndimage.binary_fill_holes(edges) .. image:: ../../_images/plot_coins_segmentation_3.png :target: ../auto_examples/applications/plot_coins_segmentation.html :align: center Now that we have contours that delineate the outer boundary of the coins, we fill the inner part of the coins using the ``ndimage.binary_fill_holes`` function, which uses mathematical morphology to fill the holes. .. image:: ../../_images/plot_coins_segmentation_4.png :target: ../auto_examples/applications/plot_coins_segmentation.html :align: center Most coins are well segmented out of the background. Small objects from the background can be easily removed using the ``ndimage.label`` function to remove objects smaller than a small threshold. :: >>> label_objects, nb_labels = ndimage.label(fill_coins) >>> sizes = np.bincount(label_objects.ravel()) >>> mask_sizes = sizes > 20 >>> mask_sizes[0] = 0 >>> coins_cleaned = mask_sizes[label_objects] However, the segmentation is not very satisfying, since one of the coins has not been segmented correctly at all. The reason is that the contour that we got from the Canny detector was not completely closed, therefore the filling function did not fill the inner part of the coin. .. image:: ../../_images/plot_coins_segmentation_5.png :target: ../auto_examples/applications/plot_coins_segmentation.html :align: center Therefore, this segmentation method is not very robust: if we miss a single pixel of the contour of the object, we will not be able to fill it. Of course, we could try to dilate the contours in order to close them. However, it is preferable to try a more robust method. Region-based segmentation ~~~~~~~~~~~~~~~~~~~~~~~~~ Let us first determine markers of the coins and the background. These markers are pixels that we can label unambiguously as either object or background. Here, the markers are found at the two extreme parts of the histogram of grey values: :: >>> markers = np.zeros_like(coins) >>> markers[coins < 30] = 1 >>> markers[coins > 150] = 2 We will use these markers in a watershed segmentation. The name watershed comes from an analogy with hydrology. The `watershed transform `_ floods an image of elevation starting from markers, in order to determine the catchment basins of these markers. Watershed lines separate these catchment basins, and correspond to the desired segmentation. The choice of the elevation map is critical for good segmentation. Here, the amplitude of the gradient provides a good elevation map. We use the Sobel operator for computing the amplitude of the gradient:: >>> from skimage.filter import sobel >>> elevation_map = sobel(coins) From the 3-D surface plot shown below, we see that high barriers effectively separate the coins from the background. .. image:: data/elevation_map.jpg :align: center and here is the corresponding 2-D plot: .. image:: ../../_images/plot_coins_segmentation_6.png :target: ../auto_examples/applications/plot_coins_segmentation.html :align: center The next step is to find markers of the background and the coins based on the extreme parts of the histogram of grey values:: >>> markers = np.zeros_like(coins) >>> markers[coins < 30] = 1 >>> markers[coins > 150] = 2 .. image:: ../../_images/plot_coins_segmentation_7.png :target: ../auto_examples/applications/plot_coins_segmentation.html :align: center Let us now compute the watershed transform:: >>> from skimage.morphology import watershed >>> segmentation = watershed(elevation_map, markers) .. image:: ../../_images/plot_coins_segmentation_8.png :target: ../auto_examples/applications/plot_coins_segmentation.html :align: center With this method, the result is satisfying for all coins. Even if the markers for the background were not well distributed, the barriers in the elevation map were high enough for these markers to flood the entire background. We remove a few small holes with mathematical morphology:: >>> segmentation = ndimage.binary_fill_holes(segmentation - 1) We can now label all the coins one by one using ``ndimage.label``:: >>> labeled_coins, _ = ndimage.label(segmentation) .. image:: ../../_images/plot_coins_segmentation_9.png :target: ../auto_examples/applications/plot_coins_segmentation.html :align: center scikit-image-0.9.3/doc/source/user_guide/tutorials.txt000066400000000000000000000001141223313777300230640ustar00rootroot00000000000000Tutorials ========= .. toctree:: :maxdepth: 1 tutorial_segmentation scikit-image-0.9.3/doc/source/user_guide/viewer.txt000066400000000000000000000051471223313777300223520ustar00rootroot00000000000000Image Viewer ============ Quick Start ----------- ``skimage.viewer`` provides a matplotlib_-based canvas for displaying images and a Qt-based GUI-toolkit, with the goal of making it easy to create interactive image editors. You can simply use it to display an image: .. code-block:: python from skimage import data from skimage.viewer import ImageViewer image = data.coins() viewer = ImageViewer(image) viewer.show() Of course, you could just as easily use ``imshow`` from matplotlib_ (or alternatively, ``skimage.io.imshow`` which adds support for multiple io-plugins) to display images. The advantage of ``ImageViewer`` is that you can easily add plugins for manipulating images. Currently, only a few plugins are implemented, but it is easy to write your own. Before going into the details, let's see an example of how a plugin is added to the viewer: .. code-block:: python from skimage.viewer.plugins import Canny viewer = ImageViewer(image) viewer += Canny(view) viewer.show() At the moment, there aren't very many plugins pre-defined, but there's a really simple interface for creating your own plugin. First, let's create a plugin to call the total-variation denoising function, ``tv_denoise``: .. code-block:: python from skimage.filter import tv_denoise from skimage.viewer.plugins.base import Plugin denoise_plugin = Plugin(image_filter=tv_denoise) .. note:: The ``Plugin`` assumes the first argument given to the image filter is the image from the image viewer. In the future, this should be changed so you can pass the image to a different argument of the filter function. To actually interact with the filter, you have to add widgets that adjust the parameters of the function. Typically, that means adding a slider widget and connecting it to the filter parameter and the minimum and maximum values of the slider: .. code-block:: python from skimage.viewer.widgets import Slider from skimage.viewer.widgets.history import SaveButtons denoise_plugin += Slider('weight', 0.01, 0.5, update_on='release') denoise_plugin += SaveButtons() Here, we connect a slider widget to the filter's 'weight' argument. We also added some buttons for saving the image to file or to the ``scikit-image`` image stack (see ``skimage.io.push`` and ``skimage.io.pop``). All that's left is to create an image viewer and add the plugin to that viewer. .. code-block:: python viewer = ImageViewer(image) viewer += denoise_plugin viewer.show() .. image:: data/denoise_viewer_window.png .. image:: data/denoise_plugin_window.png .. _matplotlib: http://matplotlib.sourceforge.net/ scikit-image-0.9.3/doc/tools/000077500000000000000000000000001223313777300160065ustar00rootroot00000000000000scikit-image-0.9.3/doc/tools/LICENSE.txt000066400000000000000000000003231223313777300176270ustar00rootroot00000000000000These files were obtained from http://groups.google.com/group/sphinx-dev/browse_thread/thread/595ef2eff60084c5/ and were released under a BSD/MIT license by Fernando Perez, Matthew Brett and the PyMVPA guys. scikit-image-0.9.3/doc/tools/apigen.py000066400000000000000000000375621223313777300176400ustar00rootroot00000000000000""" Attempt to generate templates for module reference with Sphinx To include extension modules, first identify them as valid in the ``_uri2path`` method, then handle them in the ``_parse_module_with_import`` script. Notes ----- This parsing is based on import and introspection of modules. Previously functions and classes were found by parsing the text of .py files. Extension modules should be discovered and included as well. This is a modified version of a script originally shipped with the PyMVPA project, then adapted for use first in NIPY and then in skimage. PyMVPA is an MIT-licensed project. """ # Stdlib imports import os import re from types import BuiltinFunctionType # suppress print statements (warnings for empty files) DEBUG = True class ApiDocWriter(object): ''' Class for automatic detection and parsing of API docs to Sphinx-parsable reST format''' # only separating first two levels rst_section_levels = ['*', '=', '-', '~', '^'] def __init__(self, package_name, rst_extension='.txt', package_skip_patterns=None, module_skip_patterns=None, ): ''' Initialize package for parsing Parameters ---------- package_name : string Name of the top-level package. *package_name* must be the name of an importable package rst_extension : string, optional Extension for reST files, default '.rst' package_skip_patterns : None or sequence of {strings, regexps} Sequence of strings giving URIs of packages to be excluded Operates on the package path, starting at (including) the first dot in the package path, after *package_name* - so, if *package_name* is ``sphinx``, then ``sphinx.util`` will result in ``.util`` being passed for earching by these regexps. If is None, gives default. Default is: ['\.tests$'] module_skip_patterns : None or sequence Sequence of strings giving URIs of modules to be excluded Operates on the module name including preceding URI path, back to the first dot after *package_name*. For example ``sphinx.util.console`` results in the string to search of ``.util.console`` If is None, gives default. Default is: ['\.setup$', '\._'] ''' if package_skip_patterns is None: package_skip_patterns = ['\\.tests$'] if module_skip_patterns is None: module_skip_patterns = ['\\.setup$', '\\._'] self.package_name = package_name self.rst_extension = rst_extension self.package_skip_patterns = package_skip_patterns self.module_skip_patterns = module_skip_patterns def get_package_name(self): return self._package_name def set_package_name(self, package_name): ''' Set package_name >>> docwriter = ApiDocWriter('sphinx') >>> import sphinx >>> docwriter.root_path == sphinx.__path__[0] True >>> docwriter.package_name = 'docutils' >>> import docutils >>> docwriter.root_path == docutils.__path__[0] True ''' # It's also possible to imagine caching the module parsing here self._package_name = package_name root_module = self._import(package_name) self.root_path = root_module.__path__[-1] self.written_modules = None package_name = property(get_package_name, set_package_name, None, 'get/set package_name') def _import(self, name): ''' Import namespace package ''' mod = __import__(name) components = name.split('.') for comp in components[1:]: mod = getattr(mod, comp) return mod def _get_object_name(self, line): ''' Get second token in line >>> docwriter = ApiDocWriter('sphinx') >>> docwriter._get_object_name(" def func(): ") 'func' >>> docwriter._get_object_name(" class Klass(object): ") 'Klass' >>> docwriter._get_object_name(" class Klass: ") 'Klass' ''' name = line.split()[1].split('(')[0].strip() # in case we have classes which are not derived from object # ie. old style classes return name.rstrip(':') def _uri2path(self, uri): ''' Convert uri to absolute filepath Parameters ---------- uri : string URI of python module to return path for Returns ------- path : None or string Returns None if there is no valid path for this URI Otherwise returns absolute file system path for URI Examples -------- >>> docwriter = ApiDocWriter('sphinx') >>> import sphinx >>> modpath = sphinx.__path__[0] >>> res = docwriter._uri2path('sphinx.builder') >>> res == os.path.join(modpath, 'builder.py') True >>> res = docwriter._uri2path('sphinx') >>> res == os.path.join(modpath, '__init__.py') True >>> docwriter._uri2path('sphinx.does_not_exist') ''' if uri == self.package_name: return os.path.join(self.root_path, '__init__.py') path = uri.replace(self.package_name + '.', '') path = path.replace('.', os.path.sep) path = os.path.join(self.root_path, path) # XXX maybe check for extensions as well? if os.path.exists(path + '.py'): # file path += '.py' elif os.path.exists(os.path.join(path, '__init__.py')): path = os.path.join(path, '__init__.py') else: return None return path def _path2uri(self, dirpath): ''' Convert directory path to uri ''' package_dir = self.package_name.replace('.', os.path.sep) relpath = dirpath.replace(self.root_path, package_dir) if relpath.startswith(os.path.sep): relpath = relpath[1:] return relpath.replace(os.path.sep, '.') def _parse_module(self, uri): ''' Parse module defined in *uri* ''' filename = self._uri2path(uri) if filename is None: print(filename, 'erk') # nothing that we could handle here. return ([],[]) f = open(filename, 'rt') functions, classes = self._parse_lines(f) f.close() return functions, classes def _parse_module_with_import(self, uri): """Look for functions and classes in an importable module. Parameters ---------- uri : str The name of the module to be parsed. This module needs to be importable. Returns ------- functions : list of str A list of (public) function names in the module. classes : list of str A list of (public) class names in the module. """ mod = __import__(uri, fromlist=[uri]) # find all public objects in the module. obj_strs = [obj for obj in dir(mod) if not obj.startswith('_')] functions = [] classes = [] for obj_str in obj_strs: # find the actual object from its string representation if obj_str not in mod.__dict__: continue obj = mod.__dict__[obj_str] # figure out if obj is a function or class if hasattr(obj, 'func_name') or \ isinstance(obj, BuiltinFunctionType): functions.append(obj_str) else: try: issubclass(obj, object) classes.append(obj_str) except TypeError: # not a function or class pass return functions, classes def _parse_lines(self, linesource): ''' Parse lines of text for functions and classes ''' functions = [] classes = [] for line in linesource: if line.startswith('def ') and line.count('('): # exclude private stuff name = self._get_object_name(line) if not name.startswith('_'): functions.append(name) elif line.startswith('class '): # exclude private stuff name = self._get_object_name(line) if not name.startswith('_'): classes.append(name) else: pass functions.sort() classes.sort() return functions, classes def generate_api_doc(self, uri): '''Make autodoc documentation template string for a module Parameters ---------- uri : string python location of module - e.g 'sphinx.builder' Returns ------- S : string Contents of API doc ''' # get the names of all classes and functions functions, classes = self._parse_module_with_import(uri) if not len(functions) and not len(classes) and DEBUG: print('WARNING: Empty -', uri) # dbg return '' # Make a shorter version of the uri that omits the package name for # titles uri_short = re.sub(r'^%s\.' % self.package_name,'',uri) ad = '.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n' # Set the chapter title to read 'module' for all modules except for the # main packages if '.' in uri: title = 'Module: :mod:`' + uri_short + '`' else: title = ':mod:`' + uri_short + '`' ad += title + '\n' + self.rst_section_levels[1] * len(title) ad += '\n.. automodule:: ' + uri + '\n' ad += '\n.. currentmodule:: ' + uri + '\n' for c in classes: ad += '\n:class:`' + c + '`\n' \ + self.rst_section_levels[2] * \ (len(c)+9) + '\n\n' ad += '\n.. autoclass:: ' + c + '\n' # must NOT exclude from index to keep cross-refs working ad += ' :members:\n' \ ' :undoc-members:\n' \ ' :show-inheritance:\n' \ '\n' \ ' .. automethod:: __init__\n' ad += '.. autosummary::\n\n' for f in functions: ad += ' ' + uri + '.' + f + '\n' ad += '\n' for f in functions: # must NOT exclude from index to keep cross-refs working full_f = uri + '.' + f ad += f + '\n' ad += self.rst_section_levels[2] * len(f) + '\n' ad += '\n.. autofunction:: ' + full_f + '\n\n' return ad def _survives_exclude(self, matchstr, match_type): ''' Returns True if *matchstr* does not match patterns ``self.package_name`` removed from front of string if present Examples -------- >>> dw = ApiDocWriter('sphinx') >>> dw._survives_exclude('sphinx.okpkg', 'package') True >>> dw.package_skip_patterns.append('^\\.badpkg$') >>> dw._survives_exclude('sphinx.badpkg', 'package') False >>> dw._survives_exclude('sphinx.badpkg', 'module') True >>> dw._survives_exclude('sphinx.badmod', 'module') True >>> dw.module_skip_patterns.append('^\\.badmod$') >>> dw._survives_exclude('sphinx.badmod', 'module') False ''' if match_type == 'module': patterns = self.module_skip_patterns elif match_type == 'package': patterns = self.package_skip_patterns else: raise ValueError('Cannot interpret match type "%s"' % match_type) # Match to URI without package name L = len(self.package_name) if matchstr[:L] == self.package_name: matchstr = matchstr[L:] for pat in patterns: try: pat.search except AttributeError: pat = re.compile(pat) if pat.search(matchstr): return False return True def discover_modules(self): ''' Return module sequence discovered from ``self.package_name`` Parameters ---------- None Returns ------- mods : sequence Sequence of module names within ``self.package_name`` Examples -------- >>> dw = ApiDocWriter('sphinx') >>> mods = dw.discover_modules() >>> 'sphinx.util' in mods True >>> dw.package_skip_patterns.append('\.util$') >>> 'sphinx.util' in dw.discover_modules() False >>> ''' modules = [self.package_name] # raw directory parsing for dirpath, dirnames, filenames in os.walk(self.root_path): # Check directory names for packages root_uri = self._path2uri(os.path.join(self.root_path, dirpath)) for dirname in dirnames[:]: # copy list - we modify inplace package_uri = '.'.join((root_uri, dirname)) if (self._uri2path(package_uri) and self._survives_exclude(package_uri, 'package')): modules.append(package_uri) else: dirnames.remove(dirname) return sorted(modules) def write_modules_api(self, modules, outdir): # write the list written_modules = [] for m in modules: api_str = self.generate_api_doc(m) if not api_str: continue # write out to file outfile = os.path.join(outdir, m + self.rst_extension) fileobj = open(outfile, 'wt') fileobj.write(api_str) fileobj.close() written_modules.append(m) self.written_modules = written_modules def write_api_docs(self, outdir): """Generate API reST files. Parameters ---------- outdir : string Directory name in which to store files We create automatic filenames for each module Returns ------- None Notes ----- Sets self.written_modules to list of written modules """ if not os.path.exists(outdir): os.mkdir(outdir) # compose list of modules modules = self.discover_modules() self.write_modules_api(modules,outdir) def write_index(self, outdir, froot='gen', relative_to=None): """Make a reST API index file from written files Parameters ---------- path : string Filename to write index to outdir : string Directory to which to write generated index file froot : string, optional root (filename without extension) of filename to write to Defaults to 'gen'. We add ``self.rst_extension``. relative_to : string path to which written filenames are relative. This component of the written file path will be removed from outdir, in the generated index. Default is None, meaning, leave path as it is. """ if self.written_modules is None: raise ValueError('No modules written') # Get full filename path path = os.path.join(outdir, froot+self.rst_extension) # Path written into index is relative to rootpath if relative_to is not None: relpath = (outdir + os.path.sep).replace(relative_to + os.path.sep, '') else: relpath = outdir print("outdir: ", relpath) idx = open(path,'wt') w = idx.write w('.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n') title = "API Reference" w(title + "\n") w("=" * len(title) + "\n\n") w('.. toctree::\n\n') for f in self.written_modules: w(' %s\n' % os.path.join(relpath,f)) idx.close() scikit-image-0.9.3/doc/tools/build_modref_templates.py000066400000000000000000000034021223313777300230700ustar00rootroot00000000000000#!/usr/bin/env python """Script to auto-generate our API docs. """ # stdlib imports import os, sys # local imports from apigen import ApiDocWriter # version comparison from distutils.version import LooseVersion as V #***************************************************************************** def abort(error): print('*WARNING* API documentation not generated: %s' % error) exit() if __name__ == '__main__': package = 'skimage' # Check that the 'image' package is available. If not, the API # documentation is not (re)generated and existing API documentation # sources will be used. try: __import__(package) except ImportError, e: abort("Can not import skimage") module = sys.modules[package] # Check that the source version is equal to the installed # version. If the versions mismatch the API documentation sources # are not (re)generated. This avoids automatic generation of documentation # for older or newer versions if such versions are installed on the system. installed_version = V(module.__version__) setup_lines = open('../setup.py').readlines() version = 'vUndefined' for l in setup_lines: if l.startswith('VERSION'): source_version = V(l.split("'")[1]) break if source_version != installed_version: abort("Installed version does not match source version") outdir = 'source/api' docwriter = ApiDocWriter(package) docwriter.package_skip_patterns += [r'\.fixes$', r'\.externals$', ] docwriter.write_api_docs(outdir) docwriter.write_index(outdir, 'api', relative_to='source/api') print('%d files written' % len(docwriter.written_modules)) scikit-image-0.9.3/doc/tools/gitwash/000077500000000000000000000000001223313777300174545ustar00rootroot00000000000000scikit-image-0.9.3/doc/tools/plot_pr.py000066400000000000000000000100401223313777300200320ustar00rootroot00000000000000import json import urllib import dateutil.parser from collections import OrderedDict from datetime import datetime, timedelta from dateutil.relativedelta import relativedelta import numpy as np import matplotlib.pyplot as plt from matplotlib.ticker import FuncFormatter from matplotlib.transforms import blended_transform_factory cache = '_pr_cache.txt' # Obtain release dates using, e.g., # # git log v0.4 -n 1 --format='%ai' # # The first two releases are commented out. # This was in the era before PRs. # releases = OrderedDict([ #('0.1', u'2009-10-07 13:52:19 +0200'), #('0.2', u'2009-11-12 14:48:45 +0200'), #('0.3', u'2011-10-10 03:28:47 -0700'), ('0.4', u'2011-12-03 14:31:32 -0800'), ('0.5', u'2012-02-26 21:00:51 -0800'), ('0.6', u'2012-06-24 21:37:05 -0700'), ('0.7', u'2012-09-29 18:08:49 -0700'), ('0.8', u'2013-03-04 20:46:09 +0100')]) month_duration = 24 def fetch_PRs(user='scikit-image', repo='scikit-image', state='open'): params = {'state': state, 'per_page': 100, 'page': 1} data = [] page_data = True while page_data: config = {'user': user, 'repo': repo, 'params': urllib.urlencode(params)} fetch_status = ('Fetching page %(page)d (state=%(state)s)' % params + ' from %(user)s/%(repo)s...' % config) print(fetch_status) f = urllib.urlopen( 'https://api.github.com/repos/%(user)s/%(repo)s/pulls?%(params)s' % config ) params['page'] += 1 page_data = json.loads(f.read()) if 'message' in page_data and page_data['message'] == "Not Found": page_data = [] print('Warning: Repo not found (%(user)s/%(repo)s)' % config) else: data.extend(page_data) return data def seconds_from_epoch(dates): seconds = [(dt - epoch).total_seconds() for dt in dates] return seconds def get_month_bins(dates): now = datetime.now(tz=dates[0].tzinfo) this_month = datetime(year=now.year, month=now.month, day=1, tzinfo=dates[0].tzinfo) bins = [this_month - relativedelta(months=i) for i in reversed(range(-1, month_duration))] return seconds_from_epoch(bins) def date_formatter(value, _): dt = epoch + timedelta(seconds=value) return dt.strftime('%Y/%m') for r in releases: releases[r] = dateutil.parser.parse(releases[r]) try: PRs = json.loads(open(cache, 'r').read()) print('Loaded PRs from cache...') except IOError: PRs = fetch_PRs(user='stefanv', repo='scikits.image', state='closed') PRs.extend(fetch_PRs(state='open')) PRs.extend(fetch_PRs(state='closed')) cf = open(cache, 'w') cf.write(json.dumps(PRs)) cf.flush() nrs = [pr['number'] for pr in PRs] print('Processing %d pull requests...' % len(nrs)) dates = [dateutil.parser.parse(pr['created_at']) for pr in PRs] epoch = datetime(2009, 1, 1, tzinfo=dates[0].tzinfo) dates_f = seconds_from_epoch(dates) bins = get_month_bins(dates) fig, ax = plt.subplots(figsize=(7, 5)) n, bins, _ = ax.hist(dates_f, bins=bins, color='blue', alpha=0.6) ax.xaxis.set_major_formatter(FuncFormatter(date_formatter)) ax.set_xticks(bins[2:-1:3]) # Date label every 3 months. labels = ax.get_xticklabels() for l in labels: l.set_rotation(40) l.set_size(10) mixed_transform = blended_transform_factory(ax.transData, ax.transAxes) for version, date in releases.items(): date = seconds_from_epoch([date])[0] ax.axvline(date, color='black', linestyle=':', label=version) ax.text(date, 1, version, color='r', va='bottom', ha='center', transform=mixed_transform) ax.set_title('Pull request activity').set_y(1.05) ax.set_xlabel('Date') ax.set_ylabel('PRs per month', color='blue') fig.subplots_adjust(top=0.875, bottom=0.225) cumulative = np.cumsum(n) cumulative += len(dates) - cumulative[-1] ax2 = ax.twinx() ax2.plot(bins[1:], cumulative, color='black', linewidth=2) ax2.set_ylabel('Total PRs', color='black') fig.savefig('PRs.png') plt.show() scikit-image-0.9.3/requirements.txt000066400000000000000000000000501223313777300173600ustar00rootroot00000000000000cython>=0.17 matplotlib>=1.0 numpy>=1.6 scikit-image-0.9.3/setup.py000066400000000000000000000103721223313777300156160ustar00rootroot00000000000000#! /usr/bin/env python descr = """Image Processing SciKit Image processing algorithms for SciPy, including IO, morphology, filtering, warping, color manipulation, object detection, etc. Please refer to the online documentation at http://scikit-image.org/ """ DISTNAME = 'scikit-image' DESCRIPTION = 'Image processing routines for SciPy' LONG_DESCRIPTION = descr MAINTAINER = 'Stefan van der Walt' MAINTAINER_EMAIL = 'stefan@sun.ac.za' URL = 'http://scikit-image.org' LICENSE = 'Modified BSD' DOWNLOAD_URL = 'http://github.com/scikit-image/scikit-image' VERSION = '0.9.3' PYTHON_VERSION = (2, 5) DEPENDENCIES = { 'numpy': (1, 6), 'Cython': (0, 17), } import os import sys import re import setuptools from numpy.distutils.core import setup from distutils.command.build_py import build_py def configuration(parent_package='', top_path=None): if os.path.exists('MANIFEST'): os.remove('MANIFEST') from numpy.distutils.misc_util import Configuration config = Configuration(None, parent_package, top_path) config.set_options( ignore_setup_xxx_py=True, assume_default_configuration=True, delegate_options_to_subpackages=True, quiet=True) config.add_subpackage('skimage') config.add_data_dir('skimage/data') return config def write_version_py(filename='skimage/version.py'): template = """# THIS FILE IS GENERATED FROM THE SKIMAGE SETUP.PY version='%s' """ vfile = open(os.path.join(os.path.dirname(__file__), filename), 'w') try: vfile.write(template % VERSION) finally: vfile.close() def get_package_version(package): version = [] for version_attr in ('version', 'VERSION', '__version__'): if hasattr(package, version_attr) \ and isinstance(getattr(package, version_attr), str): version_info = getattr(package, version_attr, '') for part in re.split('\D+', version_info): try: version.append(int(part)) except ValueError: pass return tuple(version) def check_requirements(): if sys.version_info < PYTHON_VERSION: raise SystemExit('You need Python version %d.%d or later.' \ % PYTHON_VERSION) for package_name, min_version in DEPENDENCIES.items(): dep_error = False try: package = __import__(package_name) except ImportError: dep_error = True else: package_version = get_package_version(package) if min_version > package_version: dep_error = True if dep_error: raise ImportError('You need `%s` version %d.%d or later.' \ % ((package_name, ) + min_version)) if __name__ == "__main__": check_requirements() write_version_py() setup( name=DISTNAME, description=DESCRIPTION, long_description=LONG_DESCRIPTION, maintainer=MAINTAINER, maintainer_email=MAINTAINER_EMAIL, url=URL, license=LICENSE, download_url=DOWNLOAD_URL, version=VERSION, classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: Console', 'Intended Audience :: Developers', 'Intended Audience :: Science/Research', 'License :: OSI Approved :: BSD License', 'Programming Language :: C', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Topic :: Scientific/Engineering', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', 'Operating System :: Unix', 'Operating System :: MacOS', ], configuration=configuration, packages=setuptools.find_packages(exclude=['doc']), include_package_data=True, zip_safe=False, # the package can run out of an .egg file entry_points={ 'console_scripts': ['skivi = skimage.scripts.skivi:main'], }, cmdclass={'build_py': build_py}, ) scikit-image-0.9.3/skimage/000077500000000000000000000000001223313777300155215ustar00rootroot00000000000000scikit-image-0.9.3/skimage/__init__.py000066400000000000000000000077721223313777300176470ustar00rootroot00000000000000"""Image Processing SciKit (Toolbox for SciPy) ``scikit-image`` (a.k.a. ``skimage``) is a collection of algorithms for image processing and computer vision. The main package of ``skimage`` only provides a few utilities for converting between image data types; for most features, you need to import one of the following subpackages: Subpackages ----------- color Color space conversion. data Test images and example data. draw Image drawing primitives (lines, text, etc.). exposure Image intensity adjustment (e.g., histogram equalization). feature Feature detection (e.g. texture analysis, corners, etc.). filter Sharpening, edge finding, denoising, etc. graph Graph-theoretic operations, e.g. dynamic programming (shortest paths). io Reading, saving, and displaying images and video. measure Measurement of image properties, e.g., similarity and contours. morphology Morphological operations, e.g. opening or skeletonization. segmentation Splitting an image into self-similar regions. transform Geometric and other transforms, e.g. rotation or the Radon transform. util Generic utilities. Utility Functions ----------------- img_as_float Convert an image to floating point format, with values in [0, 1]. img_as_uint Convert an image to unsigned integer format, with values in [0, 65535]. img_as_int Convert an image to signed integer format, with values in [-32768, 32767]. img_as_ubyte Convert an image to unsigned byte format, with values in [0, 255]. """ import os.path as _osp import imp as _imp import functools as _functools from skimage._shared.utils import deprecated as _deprecated pkg_dir = _osp.abspath(_osp.dirname(__file__)) data_dir = _osp.join(pkg_dir, 'data') try: from .version import version as __version__ except ImportError: __version__ = "unbuilt-dev" del version try: _imp.find_module('nose') except ImportError: def _test(verbose=False): """This would invoke the skimage test suite, but nose couldn't be imported so the test suite can not run. """ raise ImportError("Could not load nose. Unit tests not available.") else: def _test(verbose=False): """Invoke the skimage test suite.""" import nose args = ['', pkg_dir, '--exe'] if verbose: args.extend(['-v', '-s']) nose.run('skimage', argv=args) # do not use `test` as function name as this leads to a recursion problem with # the nose test suite test = _test test_verbose = _functools.partial(test, verbose=True) test_verbose.__doc__ = test.__doc__ class _Log(Warning): pass class _FakeLog(object): def __init__(self, name): """ Parameters ---------- name : str Name of the log. repeat : bool Whether to print repeating messages more than once (False by default). """ self._name = name import warnings warnings.simplefilter("always", _Log) self._warnings = warnings def _warn(self, msg, wtype): self._warnings.warn('%s: %s' % (wtype, msg), _Log) def debug(self, msg): self._warn(msg, 'DEBUG') def info(self, msg): self._warn(msg, 'INFO') def warning(self, msg): self._warn(msg, 'WARNING') warn = warning def error(self, msg): self._warn(msg, 'ERROR') def critical(self, msg): self._warn(msg, 'CRITICAL') def addHandler(*args): pass def setLevel(*args): pass @_deprecated() def get_log(name=None): """Return a console logger. Output may be sent to the logger using the `debug`, `info`, `warning`, `error` and `critical` methods. Parameters ---------- name : str Name of the log. References ---------- .. [1] Logging facility for Python, http://docs.python.org/library/logging.html """ if name is None: name = 'skimage' else: name = 'skimage.' + name return _FakeLog(name) from .util.dtype import * scikit-image-0.9.3/skimage/_build.py000066400000000000000000000045251223313777300173370ustar00rootroot00000000000000import sys import os import hashlib import subprocess # WindowsError is not defined on unix systems try: WindowsError except NameError: class WindowsError(Exception): pass def cython(pyx_files, working_path=''): """Use Cython to convert the given files to C. Parameters ---------- pyx_files : list of str The input .pyx files. """ # Do not build cython files if target is clean if len(sys.argv) >= 2 and sys.argv[1] == 'clean': return try: import Cython except ImportError: # If cython is not found, we do nothing -- the build will make use of # the distributed .c files print("Cython not found; falling back to pre-built %s" \ % " ".join([f.replace('.pyx', '.c') for f in pyx_files])) else: for pyxfile in [os.path.join(working_path, f) for f in pyx_files]: # if the .pyx file stayed the same, we don't need to recompile if not _changed(pyxfile): continue c_file = pyxfile[:-4] + '.c' # run cython compiler cmd = 'cython -o %s %s' % (c_file, pyxfile) print(cmd) try: subprocess.call(['cython', '-o', c_file, pyxfile]) except WindowsError: # On Windows cython.exe may be missing if Cython was installed # via distutils. Run the cython.py script instead. subprocess.call( [sys.executable, os.path.join(os.path.dirname(sys.executable), 'Scripts', 'cython.py'), '-o', c_file, pyxfile], shell=True) def _md5sum(f): m = hashlib.new('md5') while True: # Hash one 8096 byte block at a time d = f.read(8096) if not d: break m.update(d) return m.hexdigest() def _changed(filename): """Compare the hash of a Cython file to the cached hash value on disk. """ filename_cache = filename + '.md5' try: md5_cached = open(filename_cache, 'rb').read() except IOError: md5_cached = '0' with open(filename, 'rb') as f: md5_new = _md5sum(f) with open(filename_cache, 'wb') as cf: cf.write(md5_new.encode('utf-8')) return md5_cached != md5_new scikit-image-0.9.3/skimage/_shared/000077500000000000000000000000001223313777300171265ustar00rootroot00000000000000scikit-image-0.9.3/skimage/_shared/__init__.py000066400000000000000000000000001223313777300212250ustar00rootroot00000000000000scikit-image-0.9.3/skimage/_shared/geometry.pxd000066400000000000000000000005161223313777300215000ustar00rootroot00000000000000cdef unsigned char point_in_polygon(Py_ssize_t nr_verts, double *xp, double *yp, double x, double y) cdef void points_in_polygon(Py_ssize_t nr_verts, double *xp, double *yp, Py_ssize_t nr_points, double *x, double *y, unsigned char *result) scikit-image-0.9.3/skimage/_shared/geometry.pyx000066400000000000000000000031141223313777300215220ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False cdef inline unsigned char point_in_polygon(Py_ssize_t nr_verts, double *xp, double *yp, double x, double y): """Test whether point lies inside a polygon. Parameters ---------- nr_verts : int Number of vertices of polygon. xp, yp : double array Coordinates of polygon with length nr_verts. x, y : double Coordinates of point. """ cdef Py_ssize_t i cdef unsigned char c = 0 cdef Py_ssize_t j = nr_verts - 1 for i in range(nr_verts): if ( (((yp[i] <= y) and (y < yp[j])) or ((yp[j] <= y) and (y < yp[i]))) and (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]) ): c = not c j = i return c cdef void points_in_polygon(Py_ssize_t nr_verts, double *xp, double *yp, Py_ssize_t nr_points, double *x, double *y, unsigned char *result): """Test whether points lie inside a polygon. Parameters ---------- nr_verts : int Number of vertices of polygon. xp, yp : double array Coordinates of polygon with length nr_verts. nr_points : int Number of points to test. x, y : double array Coordinates of points. result : unsigned char array Test results for each point. """ cdef Py_ssize_t n for n in range(nr_points): result[n] = point_in_polygon(nr_verts, xp, yp, x[n], y[n]) scikit-image-0.9.3/skimage/_shared/interpolation.pxd000066400000000000000000000025561223313777300225420ustar00rootroot00000000000000 cdef double nearest_neighbour_interpolation(double* image, Py_ssize_t rows, Py_ssize_t cols, double r, double c, char mode, double cval) cdef double bilinear_interpolation(double* image, Py_ssize_t rows, Py_ssize_t cols, double r, double c, char mode, double cval) cdef double quadratic_interpolation(double x, double[3] f) cdef double biquadratic_interpolation(double* image, Py_ssize_t rows, Py_ssize_t cols, double r, double c, char mode, double cval) cdef double cubic_interpolation(double x, double[4] f) cdef double bicubic_interpolation(double* image, Py_ssize_t rows, Py_ssize_t cols, double r, double c, char mode, double cval) cdef double get_pixel2d(double* image, Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t r, Py_ssize_t c, char mode, double cval) cdef double get_pixel3d(double* image, Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t dims, Py_ssize_t r, Py_ssize_t c, Py_ssize_t d, char mode, double cval) cdef Py_ssize_t coord_map(Py_ssize_t dim, Py_ssize_t coord, char mode) scikit-image-0.9.3/skimage/_shared/interpolation.pyx000066400000000000000000000221371223313777300225640ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False from libc.math cimport ceil, floor cdef inline Py_ssize_t round(double r): return ((r + 0.5) if (r > 0.0) else (r - 0.5)) cdef inline double nearest_neighbour_interpolation(double* image, Py_ssize_t rows, Py_ssize_t cols, double r, double c, char mode, double cval): """Nearest neighbour interpolation at a given position in the image. Parameters ---------- image : double array Input image. rows, cols : int Shape of image. r, c : double Position at which to interpolate. mode : {'C', 'W', 'R', 'N'} Wrapping mode. Constant, Wrap, Reflect or Nearest. cval : double Constant value to use for constant mode. Returns ------- value : double Interpolated value. """ return get_pixel2d(image, rows, cols, round(r), round(c), mode, cval) cdef inline double bilinear_interpolation(double* image, Py_ssize_t rows, Py_ssize_t cols, double r, double c, char mode, double cval): """Bilinear interpolation at a given position in the image. Parameters ---------- image : double array Input image. rows, cols : int Shape of image. r, c : double Position at which to interpolate. mode : {'C', 'W', 'R', 'N'} Wrapping mode. Constant, Wrap, Reflect or Nearest. cval : double Constant value to use for constant mode. Returns ------- value : double Interpolated value. """ cdef double dr, dc cdef Py_ssize_t minr, minc, maxr, maxc minr = floor(r) minc = floor(c) maxr = ceil(r) maxc = ceil(c) dr = r - minr dc = c - minc top = (1 - dc) * get_pixel2d(image, rows, cols, minr, minc, mode, cval) \ + dc * get_pixel2d(image, rows, cols, minr, maxc, mode, cval) bottom = (1 - dc) * get_pixel2d(image, rows, cols, maxr, minc, mode, cval) \ + dc * get_pixel2d(image, rows, cols, maxr, maxc, mode, cval) return (1 - dr) * top + dr * bottom cdef inline double quadratic_interpolation(double x, double[3] f): """Quadratic interpolation. Parameters ---------- x : double Position in the interval [-1, 1]. f : double[4] Function values at positions [-1, 0, 1]. Returns ------- value : double Interpolated value. """ return f[1] - 0.25 * (f[0] - f[2]) * x cdef inline double biquadratic_interpolation(double* image, Py_ssize_t rows, Py_ssize_t cols, double r, double c, char mode, double cval): """Biquadratic interpolation at a given position in the image. Parameters ---------- image : double array Input image. rows, cols : int Shape of image. r, c : double Position at which to interpolate. mode : {'C', 'W', 'R', 'N'} Wrapping mode. Constant, Wrap, Reflect or Nearest. cval : double Constant value to use for constant mode. Returns ------- value : double Interpolated value. """ cdef Py_ssize_t r0 = round(r) cdef Py_ssize_t c0 = round(c) if r < 0: r0 -= 1 if c < 0: c0 -= 1 # scale position to range [-1, 1] cdef double xr = (r - r0) - 1 cdef double xc = (c - c0) - 1 if r == r0: xr += 1 if c == c0: xc += 1 cdef double fc[3], fr[3] cdef Py_ssize_t pr, pc # row-wise cubic interpolation for pr in range(r0, r0 + 3): for pc in range(c0, c0 + 3): fc[pc - c0] = get_pixel2d(image, rows, cols, pr, pc, mode, cval) fr[pr - r0] = quadratic_interpolation(xc, fc) # cubic interpolation for interpolated values of each row return quadratic_interpolation(xr, fr) cdef inline double cubic_interpolation(double x, double[4] f): """Cubic interpolation. Parameters ---------- x : double Position in the interval [0, 1]. f : double[4] Function values at positions [0, 1/3, 2/3, 1]. Returns ------- value : double Interpolated value. """ return \ f[1] + 0.5 * x * \ (f[2] - f[0] + x * \ (2.0 * f[0] - 5.0 * f[1] + 4.0 * f[2] - f[3] + x * \ (3.0 * (f[1] - f[2]) + f[3] - f[0]))) cdef inline double bicubic_interpolation(double* image, Py_ssize_t rows, Py_ssize_t cols, double r, double c, char mode, double cval): """Bicubic interpolation at a given position in the image. Parameters ---------- image : double array Input image. rows, cols : int Shape of image. r, c : double Position at which to interpolate. mode : {'C', 'W', 'R', 'N'} Wrapping mode. Constant, Wrap, Reflect or Nearest. cval : double Constant value to use for constant mode. Returns ------- value : double Interpolated value. """ cdef Py_ssize_t r0 = r - 1 cdef Py_ssize_t c0 = c - 1 if r < 0: r0 -= 1 if c < 0: c0 -= 1 # scale position to range [0, 1] cdef double xr = (r - r0) / 3 cdef double xc = (c - c0) / 3 cdef double fc[4], fr[4] cdef Py_ssize_t pr, pc # row-wise cubic interpolation for pr in range(r0, r0 + 4): for pc in range(c0, c0 + 4): fc[pc - c0] = get_pixel2d(image, rows, cols, pr, pc, mode, cval) fr[pr - r0] = cubic_interpolation(xc, fc) # cubic interpolation for interpolated values of each row return cubic_interpolation(xr, fr) cdef inline double get_pixel2d(double* image, Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t r, Py_ssize_t c, char mode, double cval): """Get a pixel from the image, taking wrapping mode into consideration. Parameters ---------- image : double array Input image. rows, cols : int Shape of image. r, c : int Position at which to get the pixel. mode : {'C', 'W', 'R', 'N'} Wrapping mode. Constant, Wrap, Reflect or Nearest. cval : double Constant value to use for constant mode. Returns ------- value : double Pixel value at given position. """ if mode == 'C': if (r < 0) or (r > rows - 1) or (c < 0) or (c > cols - 1): return cval else: return image[r * cols + c] else: return image[coord_map(rows, r, mode) * cols + coord_map(cols, c, mode)] cdef inline double get_pixel3d(double* image, Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t dims, Py_ssize_t r, Py_ssize_t c, Py_ssize_t d, char mode, double cval): """Get a pixel from the image, taking wrapping mode into consideration. Parameters ---------- image : double array Input image. rows, cols, dims : int Shape of image. r, c, d : int Position at which to get the pixel. mode : {'C', 'W', 'R', 'N'} Wrapping mode. Constant, Wrap, Reflect or Nearest. cval : double Constant value to use for constant mode. Returns ------- value : double Pixel value at given position. """ if mode == 'C': if (r < 0) or (r > rows - 1) or (c < 0) or (c > cols - 1): return cval else: return image[r * cols * dims + c * dims + d] else: return image[coord_map(rows, r, mode) * cols * dims + coord_map(cols, c, mode) * dims + d] cdef inline Py_ssize_t coord_map(Py_ssize_t dim, Py_ssize_t coord, char mode): """ Wrap a coordinate, according to a given mode. Parameters ---------- dim : int Maximum coordinate. coord : int Coord provided by user. May be < 0 or > dim. mode : {'W', 'R', 'N'} Whether to wrap or reflect the coordinate if it falls outside [0, dim). """ dim = dim - 1 if mode == 'R': # reflect if coord < 0: # How many times times does the coordinate wrap? if (-coord / dim) % 2 != 0: return dim - (-coord % dim) else: return (-coord % dim) elif coord > dim: if (coord / dim) % 2 != 0: return (dim - (coord % dim)) else: return (coord % dim) elif mode == 'W': # wrap if coord < 0: return (dim - (-coord % dim)) elif coord > dim: return (coord % dim) elif mode == 'N': # nearest if coord < 0: return 0 elif coord > dim: return dim return coord scikit-image-0.9.3/skimage/_shared/setup.py000066400000000000000000000024251223313777300206430ustar00rootroot00000000000000#!/usr/bin/env python import os from skimage._build import cython base_path = os.path.abspath(os.path.dirname(__file__)) def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs config = Configuration('_shared', parent_package, top_path) config.add_data_dir('tests') cython(['geometry.pyx'], working_path=base_path) cython(['interpolation.pyx'], working_path=base_path) cython(['transform.pyx'], working_path=base_path) config.add_extension('geometry', sources=['geometry.c']) config.add_extension('interpolation', sources=['interpolation.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('transform', sources=['transform.c'], include_dirs=[get_numpy_include_dirs()]) return config if __name__ == '__main__': from numpy.distutils.core import setup setup(maintainer='scikit-image Developers', author='scikit-image Developers', maintainer_email='scikit-image@googlegroups.com', description='Transforms', url='https://github.com/scikit-image/scikit-image', license='SciPy License (BSD Style)', **(configuration(top_path='').todict()) ) scikit-image-0.9.3/skimage/_shared/six.py000066400000000000000000000312471223313777300203120ustar00rootroot00000000000000"""Utilities for writing code that runs on Python 2 and 3""" # Copyright (c) 2010-2013 Benjamin Peterson # # 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. import operator import sys import types __author__ = "Benjamin Peterson " __version__ = "1.3.0" # Useful for very coarse version differentiation. PY2 = sys.version_info[0] == 2 PY3 = sys.version_info[0] == 3 if PY3: string_types = str, integer_types = int, class_types = type, text_type = str binary_type = bytes MAXSIZE = sys.maxsize else: string_types = basestring, integer_types = (int, long) class_types = (type, types.ClassType) text_type = unicode binary_type = str if sys.platform.startswith("java"): # Jython always uses 32 bits. MAXSIZE = int((1 << 31) - 1) else: # It's possible to have sizeof(long) != sizeof(Py_ssize_t). class X(object): def __len__(self): return 1 << 31 try: len(X()) except OverflowError: # 32-bit MAXSIZE = int((1 << 31) - 1) else: # 64-bit MAXSIZE = int((1 << 63) - 1) del X def _add_doc(func, doc): """Add documentation to a function.""" func.__doc__ = doc def _import_module(name): """Import module, returning the module after the last dot.""" __import__(name) return sys.modules[name] class _LazyDescr(object): def __init__(self, name): self.name = name def __get__(self, obj, tp): result = self._resolve() setattr(obj, self.name, result) # This is a bit ugly, but it avoids running this again. delattr(tp, self.name) return result class MovedModule(_LazyDescr): def __init__(self, name, old, new=None): super(MovedModule, self).__init__(name) if PY3: if new is None: new = name self.mod = new else: self.mod = old def _resolve(self): return _import_module(self.mod) class MovedAttribute(_LazyDescr): def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): super(MovedAttribute, self).__init__(name) if PY3: if new_mod is None: new_mod = name self.mod = new_mod if new_attr is None: if old_attr is None: new_attr = name else: new_attr = old_attr self.attr = new_attr else: self.mod = old_mod if old_attr is None: old_attr = name self.attr = old_attr def _resolve(self): module = _import_module(self.mod) return getattr(module, self.attr) class _MovedItems(types.ModuleType): """Lazy loading of moved objects""" _moved_attributes = [ MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), MovedAttribute("map", "itertools", "builtins", "imap", "map"), MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("reload_module", "__builtin__", "imp", "reload"), MovedAttribute("reduce", "__builtin__", "functools"), MovedAttribute("StringIO", "StringIO", "io"), MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), MovedModule("builtins", "__builtin__"), MovedModule("configparser", "ConfigParser"), MovedModule("copyreg", "copy_reg"), MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), MovedModule("http_cookies", "Cookie", "http.cookies"), MovedModule("html_entities", "htmlentitydefs", "html.entities"), MovedModule("html_parser", "HTMLParser", "html.parser"), MovedModule("http_client", "httplib", "http.client"), MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), MovedModule("cPickle", "cPickle", "pickle"), MovedModule("queue", "Queue"), MovedModule("reprlib", "repr"), MovedModule("socketserver", "SocketServer"), MovedModule("tkinter", "Tkinter"), MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), MovedModule("tkinter_tix", "Tix", "tkinter.tix"), MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), MovedModule("tkinter_colorchooser", "tkColorChooser", "tkinter.colorchooser"), MovedModule("tkinter_commondialog", "tkCommonDialog", "tkinter.commondialog"), MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), MovedModule("tkinter_font", "tkFont", "tkinter.font"), MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", "tkinter.simpledialog"), MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), MovedModule("winreg", "_winreg"), ] for attr in _moved_attributes: setattr(_MovedItems, attr.name, attr) del attr moves = sys.modules[__name__ + ".moves"] = _MovedItems("moves") def add_move(move): """Add an item to six.moves.""" setattr(_MovedItems, move.name, move) def remove_move(name): """Remove item from six.moves.""" try: delattr(_MovedItems, name) except AttributeError: try: del moves.__dict__[name] except KeyError: raise AttributeError("no such move, %r" % (name,)) if PY3: _meth_func = "__func__" _meth_self = "__self__" _func_closure = "__closure__" _func_code = "__code__" _func_defaults = "__defaults__" _func_globals = "__globals__" _iterkeys = "keys" _itervalues = "values" _iteritems = "items" _iterlists = "lists" else: _meth_func = "im_func" _meth_self = "im_self" _func_closure = "func_closure" _func_code = "func_code" _func_defaults = "func_defaults" _func_globals = "func_globals" _iterkeys = "iterkeys" _itervalues = "itervalues" _iteritems = "iteritems" _iterlists = "iterlists" try: advance_iterator = next except NameError: def advance_iterator(it): return it.next() next = advance_iterator try: callable = callable except NameError: def callable(obj): return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) if PY3: def get_unbound_function(unbound): return unbound create_bound_method = types.MethodType Iterator = object else: def get_unbound_function(unbound): return unbound.im_func def create_bound_method(func, obj): return types.MethodType(func, obj, obj.__class__) class Iterator(object): def next(self): return type(self).__next__(self) callable = callable _add_doc(get_unbound_function, """Get the function out of a possibly unbound function""") get_method_function = operator.attrgetter(_meth_func) get_method_self = operator.attrgetter(_meth_self) get_function_closure = operator.attrgetter(_func_closure) get_function_code = operator.attrgetter(_func_code) get_function_defaults = operator.attrgetter(_func_defaults) get_function_globals = operator.attrgetter(_func_globals) def iterkeys(d, **kw): """Return an iterator over the keys of a dictionary.""" return iter(getattr(d, _iterkeys)(**kw)) def itervalues(d, **kw): """Return an iterator over the values of a dictionary.""" return iter(getattr(d, _itervalues)(**kw)) def iteritems(d, **kw): """Return an iterator over the (key, value) pairs of a dictionary.""" return iter(getattr(d, _iteritems)(**kw)) def iterlists(d, **kw): """Return an iterator over the (key, [values]) pairs of a dictionary.""" return iter(getattr(d, _iterlists)(**kw)) if PY3: def b(s): return s.encode("latin-1") def u(s): return s unichr = chr if sys.version_info[1] <= 1: def int2byte(i): return bytes((i,)) else: # This is about 2x faster than the implementation above on 3.2+ int2byte = operator.methodcaller("to_bytes", 1, "big") byte2int = operator.itemgetter(0) indexbytes = operator.getitem iterbytes = iter import io StringIO = io.StringIO BytesIO = io.BytesIO else: def b(s): return s def u(s): return unicode(s, "unicode_escape") unichr = unichr int2byte = chr def byte2int(bs): return ord(bs[0]) def indexbytes(buf, i): return ord(buf[i]) def iterbytes(buf): return (ord(byte) for byte in buf) import StringIO StringIO = BytesIO = StringIO.StringIO _add_doc(b, """Byte literal""") _add_doc(u, """Text literal""") if PY3: import builtins exec_ = getattr(builtins, "exec") def reraise(tp, value, tb=None): if value.__traceback__ is not tb: raise value.with_traceback(tb) raise value print_ = getattr(builtins, "print") del builtins else: def exec_(_code_, _globs_=None, _locs_=None): """Execute code in a namespace.""" if _globs_ is None: frame = sys._getframe(1) _globs_ = frame.f_globals if _locs_ is None: _locs_ = frame.f_locals del frame elif _locs_ is None: _locs_ = _globs_ exec("""exec _code_ in _globs_, _locs_""") exec_("""def reraise(tp, value, tb=None): raise tp, value, tb """) def print_(*args, **kwargs): """The new-style print function.""" fp = kwargs.pop("file", sys.stdout) if fp is None: return def write(data): if not isinstance(data, basestring): data = str(data) fp.write(data) want_unicode = False sep = kwargs.pop("sep", None) if sep is not None: if isinstance(sep, unicode): want_unicode = True elif not isinstance(sep, str): raise TypeError("sep must be None or a string") end = kwargs.pop("end", None) if end is not None: if isinstance(end, unicode): want_unicode = True elif not isinstance(end, str): raise TypeError("end must be None or a string") if kwargs: raise TypeError("invalid keyword arguments to print()") if not want_unicode: for arg in args: if isinstance(arg, unicode): want_unicode = True break if want_unicode: newline = unicode("\n") space = unicode(" ") else: newline = "\n" space = " " if sep is None: sep = space if end is None: end = newline for i, arg in enumerate(args): if i: write(sep) write(arg) write(end) _add_doc(reraise, """Reraise an exception.""") def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" return meta("NewBase", bases, {}) scikit-image-0.9.3/skimage/_shared/testing.py000066400000000000000000000010621223313777300211540ustar00rootroot00000000000000"""Testing utilities.""" def _assert_less(a, b, msg=None): message = "%r is not lower than %r" % (a, b) if msg is not None: message += ": " + msg assert a < b, message def _assert_greater(a, b, msg=None): message = "%r is not greater than %r" % (a, b) if msg is not None: message += ": " + msg assert a > b, message try: from nose.tools import assert_less except ImportError: assert_less = _assert_less try: from nose.tools import assert_greater except ImportError: assert_greater = _assert_greater scikit-image-0.9.3/skimage/_shared/transform.pxd000066400000000000000000000002201223313777300216500ustar00rootroot00000000000000cimport numpy as cnp cdef float integrate(float[:, ::1] sat, Py_ssize_t r0, Py_ssize_t c0, Py_ssize_t r1, Py_ssize_t c1) scikit-image-0.9.3/skimage/_shared/transform.pyx000066400000000000000000000020351223313777300217030ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False cimport numpy as cnp cdef float integrate(float[:, ::1] sat, Py_ssize_t r0, Py_ssize_t c0, Py_ssize_t r1, Py_ssize_t c1): """ Using a summed area table / integral image, calculate the sum over a given window. This function is the same as the `integrate` function in `skimage.transform.integrate`, but this Cython version significantly speeds up the code. Parameters ---------- sat : ndarray of float Summed area table / integral image. r0, c0 : int Top-left corner of block to be summed. r1, c1 : int Bottom-right corner of block to be summed. Returns ------- S : int Sum over the given window. """ cdef float S = 0 S += sat[r1, c1] if (r0 - 1 >= 0) and (c0 - 1 >= 0): S += sat[r0 - 1, c0 - 1] if (r0 - 1 >= 0): S -= sat[r0 - 1, c1] if (c0 - 1 >= 0): S -= sat[r1, c0 - 1] return S scikit-image-0.9.3/skimage/_shared/utils.py000066400000000000000000000040471223313777300206450ustar00rootroot00000000000000import warnings import functools import sys from . import six __all__ = ['deprecated', 'get_bound_method_class'] class skimage_deprecation(Warning): """Create our own deprecation class, since Python >= 2.7 silences deprecations by default. """ pass class deprecated(object): """Decorator to mark deprecated functions with warning. Adapted from . Parameters ---------- alt_func : str If given, tell user what function to use instead. behavior : {'warn', 'raise'} Behavior during call to deprecated function: 'warn' = warn user that function is deprecated; 'raise' = raise error. """ def __init__(self, alt_func=None, behavior='warn'): self.alt_func = alt_func self.behavior = behavior def __call__(self, func): alt_msg = '' if self.alt_func is not None: alt_msg = ' Use ``%s`` instead.' % self.alt_func msg = 'Call to deprecated function ``%s``.' % func.__name__ msg += alt_msg @functools.wraps(func) def wrapped(*args, **kwargs): if self.behavior == 'warn': func_code = six.get_function_code(func) warnings.simplefilter('always', skimage_deprecation) warnings.warn_explicit(msg, category=skimage_deprecation, filename=func_code.co_filename, lineno=func_code.co_firstlineno + 1) elif self.behavior == 'raise': raise skimage_deprecation(msg) return func(*args, **kwargs) # modify doc string to display deprecation warning doc = '**Deprecated function**.' + alt_msg if wrapped.__doc__ is None: wrapped.__doc__ = doc else: wrapped.__doc__ = doc + '\n\n ' + wrapped.__doc__ return wrapped def get_bound_method_class(m): """Return the class for a bound method. """ return m.im_class if sys.version < '3' else m.__self__.__class__ scikit-image-0.9.3/skimage/_shared/vectorized_ops.h000066400000000000000000000045471223313777300223500ustar00rootroot00000000000000/* Intrinsic declarations */ #if defined(__SSE2__) #include #elif defined(__MMX__) #include #elif defined(__ALTIVEC__) #include #endif /* Compiler peculiarities */ #if defined(__GNUC__) #include #elif defined(_MSC_VER) #define inline __inline typedef unsigned __int16 uint16_t; #endif /** * Add 16 unsigned 16-bit integers using SSE2, MMX or Altivec, if * available. */ #if defined(__SSE2__) static inline void add16(uint16_t *dest, uint16_t *src) { __m128i *d, *s; d = (__m128i *) dest; s = (__m128i *) src; *d = _mm_add_epi16(*d, *s); d++; s++; *d = _mm_add_epi16(*d, *s); } #elif defined(__MMX__) static inline void add16(uint16_t *dest, uint16_t *src) { __m64 *d, *s; d = (__m64 *) dest; s = (__m64 *) src; *d = _mm_add_pi16(*d, *s); d++; s++; *d = _mm_add_pi16(*d, *s); d++; s++; *d = _mm_add_pi16(*d, *s); d++; s++; *d = _mm_add_pi16(*d, *s); } #elif defined(__ALTIVEC__) static inline void add16(uint16_t *dest, uint16_t *src) { vector unsigned short *d, *s; d = (vector unsigned short *) dest; s = (vector unsigned short *) src; *d = vec_add(*d, *s); d++; s++; *d = vec_add(*d, *s); } #else static inline void add16(uint16_t *dest, uint16_t *src) { int i; for (i = 0; i < 16; i++) dest[i] += src[i]; } #endif /** * Subtract 16 unsigned 16-bit integers using SSE2, MMX or Altivec, if * available. */ #if defined(__SSE2__) static inline void sub16(uint16_t *dest, uint16_t *src) { __m128i *d, *s; d = (__m128i *) dest; s = (__m128i *) src; *d = _mm_sub_epi16(*d, *s); d++; s++; *d = _mm_sub_epi16(*d, *s); } #elif defined(__MMX__) static inline void sub16(uint16_t *dest, uint16_t *src) { __m64 *d, *s; d = (__m64 *) dest; s = (__m64 *) src; *d = _mm_sub_pi16(*d, *s); d++; s++; *d = _mm_sub_pi16(*d, *s); d++; s++; *d = _mm_sub_pi16(*d, *s); d++; s++; *d = _mm_sub_pi16(*d, *s); } #elif defined(__ALTIVEC__) static inline void sub16(uint16_t *dest, uint16_t *src) { vector unsigned short *d, *s; d = (vector unsigned short *) dest; s = (vector unsigned short *) src; *d = vec_sub(*d, *s); d++; s++; *d = vec_sub(*d, *s); } #else static inline void sub16(uint16_t *dest, uint16_t *src) { int i; for (i = 0; i < 16; i++) dest[i] -= src[i]; } #endif scikit-image-0.9.3/skimage/color/000077500000000000000000000000001223313777300166375ustar00rootroot00000000000000scikit-image-0.9.3/skimage/color/__init__.py000066400000000000000000000061711223313777300207550ustar00rootroot00000000000000from .colorconv import (convert_colorspace, guess_spatial_dimensions, rgb2hsv, hsv2rgb, rgb2xyz, xyz2rgb, rgb2rgbcie, rgbcie2rgb, rgb2grey, rgb2gray, gray2rgb, xyz2lab, lab2xyz, lab2rgb, rgb2lab, rgb2hed, hed2rgb, lab2lch, lch2lab, separate_stains, combine_stains, rgb_from_hed, hed_from_rgb, rgb_from_hdx, hdx_from_rgb, rgb_from_fgx, fgx_from_rgb, rgb_from_bex, bex_from_rgb, rgb_from_rbd, rbd_from_rgb, rgb_from_gdx, gdx_from_rgb, rgb_from_hax, hax_from_rgb, rgb_from_bro, bro_from_rgb, rgb_from_bpx, bpx_from_rgb, rgb_from_ahx, ahx_from_rgb, rgb_from_hpx, hpx_from_rgb, is_rgb, is_gray) from .colorlabel import color_dict, label2rgb from .delta_e import (deltaE_cie76, deltaE_ciede94, deltaE_ciede2000, deltaE_cmc, ) __all__ = ['convert_colorspace', 'guess_spatial_dimensions', 'rgb2hsv', 'hsv2rgb', 'rgb2xyz', 'xyz2rgb', 'rgb2rgbcie', 'rgbcie2rgb', 'rgb2grey', 'rgb2gray', 'gray2rgb', 'xyz2lab', 'lab2xyz', 'lab2rgb', 'rgb2lab', 'rgb2hed', 'hed2rgb', 'lab2lch', 'lch2lab', 'separate_stains', 'combine_stains', 'rgb_from_hed', 'hed_from_rgb', 'rgb_from_hdx', 'hdx_from_rgb', 'rgb_from_fgx', 'fgx_from_rgb', 'rgb_from_bex', 'bex_from_rgb', 'rgb_from_rbd', 'rbd_from_rgb', 'rgb_from_gdx', 'gdx_from_rgb', 'rgb_from_hax', 'hax_from_rgb', 'rgb_from_bro', 'bro_from_rgb', 'rgb_from_bpx', 'bpx_from_rgb', 'rgb_from_ahx', 'ahx_from_rgb', 'rgb_from_hpx', 'hpx_from_rgb', 'is_rgb', 'is_gray', 'color_dict', 'label2rgb', 'deltaE_cie76', 'deltaE_ciede94', 'deltaE_ciede2000', 'deltaE_cmc', ] scikit-image-0.9.3/skimage/color/colorconv.py000066400000000000000000000761271223313777300212320ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """Functions for converting between color spaces. The "central" color space in this module is RGB, more specifically the linear sRGB color space using D65 as a white-point [1]_. This represents a standard monitor (w/o gamma correction). For a good FAQ on color spaces see [2]_. The API consists of functions to convert to and from RGB as defined above, as well as a generic function to convert to and from any supported color space (which is done through RGB in most cases). Supported color spaces ---------------------- * RGB : Red Green Blue. Here the sRGB standard [1]_. * HSV : Hue, Saturation, Value. Uniquely defined when related to sRGB [3]_. * RGB CIE : Red Green Blue. The original RGB CIE standard from 1931 [4]_. Primary colors are 700 nm (red), 546.1 nm (blue) and 435.8 nm (green). * XYZ CIE : XYZ Derived from the RGB CIE color space. Chosen such that ``x == y == z == 1/3`` at the whitepoint, and all color matching functions are greater than zero everywhere. * LAB CIE : Lightness, a, b Colorspace derived from XYZ CIE that is intended to be more perceptually uniform * LCH CIE : Lightness, Chroma, Hue Defined in terms of LAB CIE. C and H are the polar representation of a and b. The polar angle C is defined to be on (0, 2*pi) :author: Nicolas Pinto (rgb2hsv) :author: Ralf Gommers (hsv2rgb) :author: Travis Oliphant (XYZ and RGB CIE functions) :author: Matt Terry (lab2lch) :license: modified BSD References ---------- .. [1] Official specification of sRGB, IEC 61966-2-1:1999. .. [2] http://www.poynton.com/ColorFAQ.html .. [3] http://en.wikipedia.org/wiki/HSL_and_HSV .. [4] http://en.wikipedia.org/wiki/CIE_1931_color_space """ from __future__ import division import numpy as np from scipy import linalg from ..util import dtype from skimage._shared.utils import deprecated def guess_spatial_dimensions(image): """Make an educated guess about whether an image has a channels dimension. Parameters ---------- image : ndarray The input image. Returns ------- spatial_dims : int or None The number of spatial dimensions of `image`. If ambiguous, the value is `None`. Raises ------ ValueError If the image array has less than two or more than four dimensions. """ if image.ndim == 2: return 2 if image.ndim == 3 and image.shape[-1] != 3: return 3 if image.ndim == 3 and image.shape[-1] == 3: return None if image.ndim == 4 and image.shape[-1] == 3: return 3 else: raise ValueError("Expected 2D, 3D, or 4D array, got %iD." % image.ndim) @deprecated() def is_rgb(image): """Test whether the image is RGB or RGBA. Parameters ---------- image : ndarray Input image. """ return (image.ndim == 3 and image.shape[2] in (3, 4)) @deprecated() def is_gray(image): """Test whether the image is gray (i.e. has only one color band). Parameters ---------- image : ndarray Input image. """ return image.ndim in (2, 3) and not is_rgb(image) def convert_colorspace(arr, fromspace, tospace): """Convert an image array to a new color space. Parameters ---------- arr : array_like The image to convert. fromspace : str The color space to convert from. Valid color space strings are ['RGB', 'HSV', 'RGB CIE', 'XYZ']. Value may also be specified as lower case. tospace : str The color space to convert to. Valid color space strings are ['RGB', 'HSV', 'RGB CIE', 'XYZ']. Value may also be specified as lower case. Returns ------- newarr : ndarray The converted image. Notes ----- Conversion occurs through the "central" RGB color space, i.e. conversion from XYZ to HSV is implemented as XYZ -> RGB -> HSV instead of directly. Examples -------- >>> from skimage import data >>> lena = data.lena() >>> lena_hsv = convert_colorspace(lena, 'RGB', 'HSV') """ fromdict = {'RGB': lambda im: im, 'HSV': hsv2rgb, 'RGB CIE': rgbcie2rgb, 'XYZ': xyz2rgb} todict = {'RGB': lambda im: im, 'HSV': rgb2hsv, 'RGB CIE': rgb2rgbcie, 'XYZ': rgb2xyz} fromspace = fromspace.upper() tospace = tospace.upper() if not fromspace in fromdict.keys(): raise ValueError('fromspace needs to be one of %s' % fromdict.keys()) if not tospace in todict.keys(): raise ValueError('tospace needs to be one of %s' % todict.keys()) return todict[tospace](fromdict[fromspace](arr)) def _prepare_colorarray(arr): """Check the shape of the array and convert it to floating point representation. """ arr = np.asanyarray(arr) if arr.ndim not in [3, 4] or arr.shape[-1] != 3: msg = ("the input array must be have a shape == (.., ..,[ ..,] 3)), " + "got (" + (", ".join(map(str, arr.shape))) + ")") raise ValueError(msg) return dtype.img_as_float(arr) def rgb2hsv(rgb): """RGB to HSV color space conversion. Parameters ---------- rgb : array_like The image in RGB format, in a 3-D array of shape (.., .., 3). Returns ------- out : ndarray The image in HSV format, in a 3-D array of shape (.., .., 3). Raises ------ ValueError If `rgb` is not a 3-D array of shape (.., .., 3). Notes ----- The conversion assumes an input data range of [0, 1] for all color components. Conversion between RGB and HSV color spaces results in some loss of precision, due to integer arithmetic and rounding [1]_. References ---------- .. [1] http://en.wikipedia.org/wiki/HSL_and_HSV Examples -------- >>> from skimage import color >>> from skimage import data >>> lena = data.lena() >>> lena_hsv = color.rgb2hsv(lena) """ arr = _prepare_colorarray(rgb) out = np.empty_like(arr) # -- V channel out_v = arr.max(-1) # -- S channel delta = arr.ptp(-1) # Ignore warning for zero divided by zero old_settings = np.seterr(invalid='ignore') out_s = delta / out_v out_s[delta == 0.] = 0. # -- H channel # red is max idx = (arr[:, :, 0] == out_v) out[idx, 0] = (arr[idx, 1] - arr[idx, 2]) / delta[idx] # green is max idx = (arr[:, :, 1] == out_v) out[idx, 0] = 2. + (arr[idx, 2] - arr[idx, 0]) / delta[idx] # blue is max idx = (arr[:, :, 2] == out_v) out[idx, 0] = 4. + (arr[idx, 0] - arr[idx, 1]) / delta[idx] out_h = (out[:, :, 0] / 6.) % 1. out_h[delta == 0.] = 0. np.seterr(**old_settings) # -- output out[:, :, 0] = out_h out[:, :, 1] = out_s out[:, :, 2] = out_v # remove NaN out[np.isnan(out)] = 0 return out def hsv2rgb(hsv): """HSV to RGB color space conversion. Parameters ---------- hsv : array_like The image in HSV format, in a 3-D array of shape (.., .., 3). Returns ------- out : ndarray The image in RGB format, in a 3-D array of shape (.., .., 3). Raises ------ ValueError If `hsv` is not a 3-D array of shape (.., .., 3). Notes ----- The conversion assumes an input data range of [0, 1] for all color components. Conversion between RGB and HSV color spaces results in some loss of precision, due to integer arithmetic and rounding [1]_. References ---------- .. [1] http://en.wikipedia.org/wiki/HSL_and_HSV Examples -------- >>> from skimage import data >>> lena = data.lena() >>> lena_hsv = rgb2hsv(lena) >>> lena_rgb = hsv2rgb(lena_hsv) """ arr = _prepare_colorarray(hsv) hi = np.floor(arr[:, :, 0] * 6) f = arr[:, :, 0] * 6 - hi p = arr[:, :, 2] * (1 - arr[:, :, 1]) q = arr[:, :, 2] * (1 - f * arr[:, :, 1]) t = arr[:, :, 2] * (1 - (1 - f) * arr[:, :, 1]) v = arr[:, :, 2] hi = np.dstack([hi, hi, hi]).astype(np.uint8) % 6 out = np.choose(hi, [np.dstack((v, t, p)), np.dstack((q, v, p)), np.dstack((p, v, t)), np.dstack((p, q, v)), np.dstack((t, p, v)), np.dstack((v, p, q))]) return out #--------------------------------------------------------------- # Primaries for the coordinate systems #--------------------------------------------------------------- cie_primaries = np.array([700, 546.1, 435.8]) sb_primaries = np.array([1. / 155, 1. / 190, 1. / 225]) * 1e5 #--------------------------------------------------------------- # Matrices that define conversion between different color spaces #--------------------------------------------------------------- # From sRGB specification xyz_from_rgb = np.array([[0.412453, 0.357580, 0.180423], [0.212671, 0.715160, 0.072169], [0.019334, 0.119193, 0.950227]]) rgb_from_xyz = linalg.inv(xyz_from_rgb) # From http://en.wikipedia.org/wiki/CIE_1931_color_space # Note: Travis's code did not have the divide by 0.17697 xyz_from_rgbcie = np.array([[0.49, 0.31, 0.20], [0.17697, 0.81240, 0.01063], [0.00, 0.01, 0.99]]) / 0.17697 rgbcie_from_xyz = linalg.inv(xyz_from_rgbcie) # construct matrices to and from rgb: rgbcie_from_rgb = np.dot(rgbcie_from_xyz, xyz_from_rgb) rgb_from_rgbcie = np.dot(rgb_from_xyz, xyz_from_rgbcie) gray_from_rgb = np.array([[0.2125, 0.7154, 0.0721], [0, 0, 0], [0, 0, 0]]) # CIE LAB constants for Observer= 2A, Illuminant= D65 lab_ref_white = np.array([0.95047, 1., 1.08883]) # Haematoxylin-Eosin-DAB colorspace # From original Ruifrok's paper: A. C. Ruifrok and D. A. Johnston, # "Quantification of histochemical staining by color deconvolution.," # Analytical and quantitative cytology and histology / the International # Academy of Cytology [and] American Society of Cytology, vol. 23, no. 4, # pp. 291-9, Aug. 2001. rgb_from_hed = np.array([[0.65, 0.70, 0.29], [0.07, 0.99, 0.11], [0.27, 0.57, 0.78]]) hed_from_rgb = linalg.inv(rgb_from_hed) # Following matrices are adapted form the Java code written by G.Landini. # The original code is available at: # http://www.dentistry.bham.ac.uk/landinig/software/cdeconv/cdeconv.html # Hematoxylin + DAB rgb_from_hdx = np.array([[0.650, 0.704, 0.286], [0.268, 0.570, 0.776], [0.0, 0.0, 0.0]]) rgb_from_hdx[2, :] = np.cross(rgb_from_hdx[0, :], rgb_from_hdx[1, :]) hdx_from_rgb = linalg.inv(rgb_from_hdx) # Feulgen + Light Green rgb_from_fgx = np.array([[0.46420921, 0.83008335, 0.30827187], [0.94705542, 0.25373821, 0.19650764], [0.0, 0.0, 0.0]]) rgb_from_fgx[2, :] = np.cross(rgb_from_fgx[0, :], rgb_from_fgx[1, :]) fgx_from_rgb = linalg.inv(rgb_from_fgx) # Giemsa: Methyl Blue + Eosin rgb_from_bex = np.array([[0.834750233, 0.513556283, 0.196330403], [0.092789, 0.954111, 0.283111], [0.0, 0.0, 0.0]]) rgb_from_bex[2, :] = np.cross(rgb_from_bex[0, :], rgb_from_bex[1, :]) bex_from_rgb = linalg.inv(rgb_from_bex) # FastRed + FastBlue + DAB rgb_from_rbd = np.array([[0.21393921, 0.85112669, 0.47794022], [0.74890292, 0.60624161, 0.26731082], [0.268, 0.570, 0.776]]) rbd_from_rgb = linalg.inv(rgb_from_rbd) # Methyl Green + DAB rgb_from_gdx = np.array([[0.98003, 0.144316, 0.133146], [0.268, 0.570, 0.776], [0.0, 0.0, 0.0]]) rgb_from_gdx[2, :] = np.cross(rgb_from_gdx[0, :], rgb_from_gdx[1, :]) gdx_from_rgb = linalg.inv(rgb_from_gdx) # Hematoxylin + AEC rgb_from_hax = np.array([[0.650, 0.704, 0.286], [0.2743, 0.6796, 0.6803], [0.0, 0.0, 0.0]]) rgb_from_hax[2, :] = np.cross(rgb_from_hax[0, :], rgb_from_hax[1, :]) hax_from_rgb = linalg.inv(rgb_from_hax) # Blue matrix Anilline Blue + Red matrix Azocarmine + Orange matrix Orange-G rgb_from_bro = np.array([[0.853033, 0.508733, 0.112656], [0.09289875, 0.8662008, 0.49098468], [0.10732849, 0.36765403, 0.9237484]]) bro_from_rgb = linalg.inv(rgb_from_bro) # Methyl Blue + Ponceau Fuchsin rgb_from_bpx = np.array([[0.7995107, 0.5913521, 0.10528667], [0.09997159, 0.73738605, 0.6680326], [0.0, 0.0, 0.0]]) rgb_from_bpx[2, :] = np.cross(rgb_from_bpx[0, :], rgb_from_bpx[1, :]) bpx_from_rgb = linalg.inv(rgb_from_bpx) # Alcian Blue + Hematoxylin rgb_from_ahx = np.array([[0.874622, 0.457711, 0.158256], [0.552556, 0.7544, 0.353744], [0.0, 0.0, 0.0]]) rgb_from_ahx[2, :] = np.cross(rgb_from_ahx[0, :], rgb_from_ahx[1, :]) ahx_from_rgb = linalg.inv(rgb_from_ahx) # Hematoxylin + PAS rgb_from_hpx = np.array([[0.644211, 0.716556, 0.266844], [0.175411, 0.972178, 0.154589], [0.0, 0.0, 0.0]]) rgb_from_hpx[2, :] = np.cross(rgb_from_hpx[0, :], rgb_from_hpx[1, :]) hpx_from_rgb = linalg.inv(rgb_from_hpx) #------------------------------------------------------------- # The conversion functions that make use of the matrices above #------------------------------------------------------------- def _convert(matrix, arr): """Do the color space conversion. Parameters ---------- matrix : array_like The 3x3 matrix to use. arr : array_like The input array. Returns ------- out : ndarray, dtype=float The converted array. """ arr = _prepare_colorarray(arr) arr = np.swapaxes(arr, 0, -1) oldshape = arr.shape arr = np.reshape(arr, (3, -1)) out = np.dot(matrix, arr) out.shape = oldshape out = np.swapaxes(out, -1, 0) return np.ascontiguousarray(out) def xyz2rgb(xyz): """XYZ to RGB color space conversion. Parameters ---------- xyz : array_like The image in XYZ format, in a 3-D array of shape (.., .., 3). Returns ------- out : ndarray The image in RGB format, in a 3-D array of shape (.., .., 3). Raises ------ ValueError If `xyz` is not a 3-D array of shape (.., .., 3). Notes ----- The CIE XYZ color space is derived from the CIE RGB color space. Note however that this function converts to sRGB. References ---------- .. [1] http://en.wikipedia.org/wiki/CIE_1931_color_space Examples -------- >>> from skimage import data >>> from skimage.color import rgb2xyz, xyz2rgb >>> lena = data.lena() >>> lena_xyz = rgb2xyz(lena) >>> lena_rgb = xyz2rgb(lena_xyz) """ # Follow the algorithm from http://www.easyrgb.com/index.php # except we don't multiply/divide by 100 in the conversion arr = _convert(rgb_from_xyz, xyz) mask = arr > 0.0031308 arr[mask] = 1.055 * np.power(arr[mask], 1 / 2.4) - 0.055 arr[~mask] *= 12.92 return arr def rgb2xyz(rgb): """RGB to XYZ color space conversion. Parameters ---------- rgb : array_like The image in RGB format, in a 3- or 4-D array of shape (.., ..,[ ..,] 3). Returns ------- out : ndarray The image in XYZ format, in a 3- or 4-D array of shape (.., ..,[ ..,] 3). Raises ------ ValueError If `rgb` is not a 3- or 4-D array of shape (.., ..,[ ..,] 3). Notes ----- The CIE XYZ color space is derived from the CIE RGB color space. Note however that this function converts from sRGB. References ---------- .. [1] http://en.wikipedia.org/wiki/CIE_1931_color_space Examples -------- >>> from skimage import data >>> lena = data.lena() >>> lena_xyz = rgb2xyz(lena) """ # Follow the algorithm from http://www.easyrgb.com/index.php # except we don't multiply/divide by 100 in the conversion arr = _prepare_colorarray(rgb).copy() mask = arr > 0.04045 arr[mask] = np.power((arr[mask] + 0.055) / 1.055, 2.4) arr[~mask] /= 12.92 return _convert(xyz_from_rgb, arr) def rgb2rgbcie(rgb): """RGB to RGB CIE color space conversion. Parameters ---------- rgb : array_like The image in RGB format, in a 3-D array of shape (.., .., 3). Returns ------- out : ndarray The image in RGB CIE format, in a 3-D array of shape (.., .., 3). Raises ------ ValueError If `rgb` is not a 3-D array of shape (.., .., 3). References ---------- .. [1] http://en.wikipedia.org/wiki/CIE_1931_color_space Examples -------- >>> from skimage import data >>> from skimage.color import rgb2rgbcie >>> lena = data.lena() >>> lena_rgbcie = rgb2rgbcie(lena) """ return _convert(rgbcie_from_rgb, rgb) def rgbcie2rgb(rgbcie): """RGB CIE to RGB color space conversion. Parameters ---------- rgbcie : array_like The image in RGB CIE format, in a 3-D array of shape (.., .., 3). Returns ------- out : ndarray The image in RGB format, in a 3-D array of shape (.., .., 3). Raises ------ ValueError If `rgbcie` is not a 3-D array of shape (.., .., 3). References ---------- .. [1] http://en.wikipedia.org/wiki/CIE_1931_color_space Examples -------- >>> from skimage import data >>> from skimage.color import rgb2rgbcie, rgbcie2rgb >>> lena = data.lena() >>> lena_rgbcie = rgb2rgbcie(lena) >>> lena_rgb = rgbcie2rgb(lena_rgbcie) """ return _convert(rgb_from_rgbcie, rgbcie) def rgb2gray(rgb): """Compute luminance of an RGB image. Parameters ---------- rgb : array_like The image in RGB format, in a 3-D array of shape (.., .., 3), or in RGBA format with shape (.., .., 4). Returns ------- out : ndarray The luminance image, a 2-D array. Raises ------ ValueError If `rgb2gray` is not a 3-D array of shape (.., .., 3) or (.., .., 4). References ---------- .. [1] http://www.poynton.com/PDFs/ColorFAQ.pdf Notes ----- The weights used in this conversion are calibrated for contemporary CRT phosphors:: Y = 0.2125 R + 0.7154 G + 0.0721 B If there is an alpha channel present, it is ignored. Examples -------- >>> from skimage.color import rgb2gray >>> from skimage import data >>> lena = data.lena() >>> lena_gray = rgb2gray(lena) """ if rgb.ndim == 2: return rgb return _convert(gray_from_rgb, rgb[:, :, :3])[..., 0] rgb2grey = rgb2gray def gray2rgb(image): """Create an RGB representation of a gray-level image. Parameters ---------- image : array_like Input image of shape ``(M, N [, P])``. Returns ------- rgb : ndarray RGB image of shape ``(M, N, [, P], 3)``. Raises ------ ValueError If the input is not a 2- or 3-dimensional image. """ if np.squeeze(image).ndim == 3 and image.shape[2] in (3, 4): return image elif image.ndim != 1 and np.squeeze(image).ndim in (1, 2, 3): image = image[..., np.newaxis] return np.concatenate(3 * (image,), axis=-1) else: raise ValueError("Input image expected to be RGB, RGBA or gray.") def xyz2lab(xyz): """XYZ to CIE-LAB color space conversion. Parameters ---------- xyz : array_like The image in XYZ format, in a 3- or 4-D array of shape (.., ..,[ ..,] 3). Returns ------- out : ndarray The image in CIE-LAB format, in a 3- or 4-D array of shape (.., ..,[ ..,] 3). Raises ------ ValueError If `xyz` is not a 3-D array of shape (.., ..,[ ..,] 3). Notes ----- Observer= 2A, Illuminant= D65 CIE XYZ tristimulus values x_ref = 95.047, y_ref = 100., z_ref = 108.883 References ---------- .. [1] http://www.easyrgb.com/index.php?X=MATH&H=07#text7 .. [2] http://en.wikipedia.org/wiki/Lab_color_space Examples -------- >>> from skimage import data >>> from skimage.color import rgb2xyz, xyz2lab >>> lena = data.lena() >>> lena_xyz = rgb2xyz(lena) >>> lena_lab = xyz2lab(lena_xyz) """ arr = _prepare_colorarray(xyz) # scale by CIE XYZ tristimulus values of the reference white point arr = arr / lab_ref_white # Nonlinear distortion and linear transformation mask = arr > 0.008856 arr[mask] = np.power(arr[mask], 1. / 3.) arr[~mask] = 7.787 * arr[~mask] + 16. / 116. x, y, z = arr[..., 0], arr[..., 1], arr[..., 2] # Vector scaling L = (116. * y) - 16. a = 500.0 * (x - y) b = 200.0 * (y - z) return np.concatenate([x[..., np.newaxis] for x in [L, a, b]], axis=-1) def lab2xyz(lab): """CIE-LAB to XYZcolor space conversion. Parameters ---------- lab : array_like The image in lab format, in a 3-D array of shape (.., .., 3). Returns ------- out : ndarray The image in XYZ format, in a 3-D array of shape (.., .., 3). Raises ------ ValueError If `lab` is not a 3-D array of shape (.., .., 3). Notes ----- Observer= 2A, Illuminant= D65 CIE XYZ tristimulus values x_ref = 95.047, y_ref = 100., z_ref = 108.883 References ---------- .. [1] http://www.easyrgb.com/index.php?X=MATH&H=07#text7 .. [2] http://en.wikipedia.org/wiki/Lab_color_space """ arr = _prepare_colorarray(lab).copy() L, a, b = arr[:, :, 0], arr[:, :, 1], arr[:, :, 2] y = (L + 16.) / 116. x = (a / 500.) + y z = y - (b / 200.) out = np.dstack([x, y, z]) mask = out > 0.2068966 out[mask] = np.power(out[mask], 3.) out[~mask] = (out[~mask] - 16.0 / 116.) / 7.787 # rescale Observer= 2 deg, Illuminant= D65 out *= lab_ref_white return out def rgb2lab(rgb): """RGB to lab color space conversion. Parameters ---------- rgb : array_like The image in RGB format, in a 3- or 4-D array of shape (.., ..,[ ..,] 3). Returns ------- out : ndarray The image in Lab format, in a 3- or 4-D array of shape (.., ..,[ ..,] 3). Raises ------ ValueError If `rgb` is not a 3- or 4-D array of shape (.., ..,[ ..,] 3). Notes ----- This function uses rgb2xyz and xyz2lab. """ return xyz2lab(rgb2xyz(rgb)) def lab2rgb(lab): """Lab to RGB color space conversion. Parameters ---------- rgb : array_like The image in Lab format, in a 3-D array of shape (.., .., 3). Returns ------- out : ndarray The image in RGB format, in a 3-D array of shape (.., .., 3). Raises ------ ValueError If `lab` is not a 3-D array of shape (.., .., 3). Notes ----- This function uses lab2xyz and xyz2rgb. """ return xyz2rgb(lab2xyz(lab)) def rgb2hed(rgb): """RGB to Haematoxylin-Eosin-DAB (HED) color space conversion. Parameters ---------- rgb : array_like The image in RGB format, in a 3-D array of shape (.., .., 3). Returns ------- out : ndarray The image in HED format, in a 3-D array of shape (.., .., 3). Raises ------ ValueError If `rgb` is not a 3-D array of shape (.., .., 3). References ---------- .. [1] A. C. Ruifrok and D. A. Johnston, "Quantification of histochemical staining by color deconvolution.," Analytical and quantitative cytology and histology / the International Academy of Cytology [and] American Society of Cytology, vol. 23, no. 4, pp. 291-9, Aug. 2001. Examples -------- >>> from skimage import data >>> from skimage.color import rgb2hed >>> ihc = data.immunohistochemistry() >>> ihc_hed = rgb2hed(ihc) """ return separate_stains(rgb, hed_from_rgb) def hed2rgb(hed): """Haematoxylin-Eosin-DAB (HED) to RGB color space conversion. Parameters ---------- hed : array_like The image in the HED color space, in a 3-D array of shape (.., .., 3). Returns ------- out : ndarray The image in RGB, in a 3-D array of shape (.., .., 3). Raises ------ ValueError If `hed` is not a 3-D array of shape (.., .., 3). References ---------- .. [1] A. C. Ruifrok and D. A. Johnston, "Quantification of histochemical staining by color deconvolution.," Analytical and quantitative cytology and histology / the International Academy of Cytology [and] American Society of Cytology, vol. 23, no. 4, pp. 291-9, Aug. 2001. Examples -------- >>> from skimage import data >>> from skimage.color import rgb2hed, hed2rgb >>> ihc = data.immunohistochemistry() >>> ihc_hed = rgb2hed(ihc) >>> ihc_rgb = hed2rgb(ihc_hed) """ return combine_stains(hed, rgb_from_hed) def separate_stains(rgb, conv_matrix): """RGB to stain color space conversion. Parameters ---------- rgb : array_like The image in RGB format, in a 3-D array of shape (.., .., 3). conv_matrix: ndarray The stain separation matrix as described by G. Landini [1]_. Returns ------- out : ndarray The image in stain color space, in a 3-D array of shape (.., .., 3). Raises ------ ValueError If `rgb` is not a 3-D array of shape (.., .., 3). Notes ----- Stain separation matrices available in the ``color`` module and their respective colorspace: * ``hed_from_rgb``: Hematoxylin + Eosin + DAB * ``hdx_from_rgb``: Hematoxylin + DAB * ``fgx_from_rgb``: Feulgen + Light Green * ``bex_from_rgb``: Giemsa stain : Methyl Blue + Eosin * ``rbd_from_rgb``: FastRed + FastBlue + DAB * ``gdx_from_rgb``: Methyl Green + DAB * ``hax_from_rgb``: Hematoxylin + AEC * ``bro_from_rgb``: Blue matrix Anilline Blue + Red matrix Azocarmine\ + Orange matrix Orange-G * ``bpx_from_rgb``: Methyl Blue + Ponceau Fuchsin * ``ahx_from_rgb``: Alcian Blue + Hematoxylin * ``hpx_from_rgb``: Hematoxylin + PAS References ---------- .. [1] http://www.dentistry.bham.ac.uk/landinig/software/cdeconv/cdeconv.html Examples -------- >>> from skimage import data >>> from skimage.color import separate_stains, hdx_from_rgb >>> ihc = data.immunohistochemistry() >>> ihc_hdx = separate_stains(ihc, hdx_from_rgb) """ rgb = dtype.img_as_float(rgb) + 2 stains = np.dot(np.reshape(-np.log(rgb), (-1, 3)), conv_matrix) return np.reshape(stains, rgb.shape) def combine_stains(stains, conv_matrix): """Stain to RGB color space conversion. Parameters ---------- stains : array_like The image in stain color space, in a 3-D array of shape (.., .., 3). conv_matrix: ndarray The stain separation matrix as described by G. Landini [1]_. Returns ------- out : ndarray The image in RGB format, in a 3-D array of shape (.., .., 3). Raises ------ ValueError If `stains` is not a 3-D array of shape (.., .., 3). Notes ----- Stain combination matrices available in the ``color`` module and their respective colorspace: * ``rgb_from_hed``: Hematoxylin + Eosin + DAB * ``rgb_from_hdx``: Hematoxylin + DAB * ``rgb_from_fgx``: Feulgen + Light Green * ``rgb_from_bex``: Giemsa stain : Methyl Blue + Eosin * ``rgb_from_rbd``: FastRed + FastBlue + DAB * ``rgb_from_gdx``: Methyl Green + DAB * ``rgb_from_hax``: Hematoxylin + AEC * ``rgb_from_bro``: Blue matrix Anilline Blue + Red matrix Azocarmine\ + Orange matrix Orange-G * ``rgb_from_bpx``: Methyl Blue + Ponceau Fuchsin * ``rgb_from_ahx``: Alcian Blue + Hematoxylin * ``rgb_from_hpx``: Hematoxylin + PAS References ---------- .. [1] http://www.dentistry.bham.ac.uk/landinig/software/cdeconv/cdeconv.html Examples -------- >>> from skimage import data >>> from skimage.color import (separate_stains, combine_stains, ... hdx_from_rgb, rgb_from_hdx) >>> ihc = data.immunohistochemistry() >>> ihc_hdx = separate_stains(ihc, hdx_from_rgb) >>> ihc_rgb = combine_stains(ihc_hdx, rgb_from_hdx) """ from ..exposure import rescale_intensity stains = dtype.img_as_float(stains) logrgb2 = np.dot(-np.reshape(stains, (-1, 3)), conv_matrix) rgb2 = np.exp(logrgb2) return rescale_intensity(np.reshape(rgb2 - 2, stains.shape), in_range=(-1, 1)) def lab2lch(lab): """CIE-LAB to CIE-LCH color space conversion. LCH is the cylindrical representation of the LAB (Cartesian) colorspace Parameters ---------- lab : array_like The N-D image in CIE-LAB format. The last (`N+1`th) dimension must have at least 3 elements, corresponding to the ``L``, ``a``, and ``b`` color channels. Subsequent elements are copied. Returns ------- out : ndarray The image in LCH format, in a N-D array with same shape as input `lab`. Raises ------ ValueError If `lch` does not have at least 3 color channels (i.e. l, a, b). Notes ----- The Hue is expressed as an angle between (0, 2*pi) Examples -------- >>> from skimage import data >>> from skimage.color import rgb2lab, lab2lch >>> lena = data.lena() >>> lena_lab = rgb2lab(lena) >>> lena_lch = lab2lch(lena_lab) """ lch = _prepare_lab_array(lab) a, b = lch[..., 1], lch[..., 2] lch[..., 1], lch[..., 2] = _cart2polar_2pi(a, b) return lch def _cart2polar_2pi(x, y): """convert cartesian coordiantes to polar (uses non-standard theta range!) NON-STANDARD RANGE! Maps to (0, 2*pi) rather than usual (-pi, +pi) """ r, t = np.hypot(x, y), np.arctan2(y, x) t += np.where(t < 0., 2 * np.pi, 0) return r, t def lch2lab(lch): """CIE-LCH to CIE-LAB color space conversion. LCH is the cylindrical representation of the LAB (Cartesian) colorspace Parameters ---------- lch : array_like The N-D image in CIE-LCH format. The last (`N+1`th) dimension must have at least 3 elements, corresponding to the ``L``, ``a``, and ``b`` color channels. Subsequent elements are copied. Returns ------- out : ndarray The image in LAB format, with same shape as input `lch`. Raises ------ ValueError If `lch` does not have at least 3 color channels (i.e. l, c, h). Examples -------- >>> from skimage import data >>> from skimage.color import rgb2lab, lch2lab >>> lena = data.lena() >>> lena_lab = rgb2lab(lena) >>> lena_lch = lab2lch(lena_lab) >>> lena_lab2 = lch2lab(lena_lch) """ lch = _prepare_lab_array(lch) c, h = lch[..., 1], lch[..., 2] lch[..., 1], lch[..., 2] = c * np.cos(h), c * np.sin(h) return lch def _prepare_lab_array(arr): """Ensure input for lab2lch, lch2lab are well-posed. Arrays must be in floating point and have at least 3 elements in last dimension. Return a new array. """ arr = np.asarray(arr) shape = arr.shape if shape[-1] < 3: raise ValueError('Input array has less than 3 color channels') return dtype.img_as_float(arr, force_copy=True) scikit-image-0.9.3/skimage/color/colorlabel.py000066400000000000000000000105161223313777300213320ustar00rootroot00000000000000import warnings import itertools import numpy as np from skimage import img_as_float from skimage._shared import six from skimage._shared.six.moves import zip from .colorconv import rgb2gray, gray2rgb from . import rgb_colors __all__ = ['color_dict', 'label2rgb', 'DEFAULT_COLORS'] DEFAULT_COLORS = ('red', 'blue', 'yellow', 'magenta', 'green', 'indigo', 'darkorange', 'cyan', 'pink', 'yellowgreen') color_dict = rgb_colors.__dict__ def _rgb_vector(color): """Return RGB color as (1, 3) array. This RGB array gets multiplied by masked regions of an RGB image, which are partially flattened by masking (i.e. dimensions 2D + RGB -> 1D + RGB). Parameters ---------- color : str or array Color name in `color_dict` or RGB float values between [0, 1]. """ if isinstance(color, six.string_types): color = color_dict[color] # Slice to handle RGBA colors. return np.array(color[:3]) def _match_label_with_color(label, colors, bg_label, bg_color): """Return `unique_labels` and `color_cycle` for label array and color list. Colors are cycled for normal labels, but the background color should only be used for the background. """ # Temporarily set background color; it will be removed later. if bg_color is None: bg_color = (0, 0, 0) bg_color = _rgb_vector([bg_color]) unique_labels = list(set(label.flat)) # Ensure that the background label is in front to match call to `chain`. if bg_label in unique_labels: unique_labels.remove(bg_label) unique_labels.insert(0, bg_label) # Modify labels and color cycle so background color is used only once. color_cycle = itertools.cycle(colors) color_cycle = itertools.chain(bg_color, color_cycle) return unique_labels, color_cycle def label2rgb(label, image=None, colors=None, alpha=0.3, bg_label=-1, bg_color=None, image_alpha=1): """Return an RGB image where color-coded labels are painted over the image. Parameters ---------- label : array Integer array of labels with the same shape as `image`. image : array Image used as underlay for labels. If the input is an RGB image, it's converted to grayscale before coloring. colors : list List of colors. If the number of labels exceeds the number of colors, then the colors are cycled. alpha : float [0, 1] Opacity of colorized labels. Ignored if image is `None`. bg_label : int Label that's treated as the background. bg_color : str or array Background color. Must be a name in `color_dict` or RGB float values between [0, 1]. image_alpha : float [0, 1] Opacity of the image. """ if colors is None: colors = DEFAULT_COLORS colors = [_rgb_vector(c) for c in colors] if image is None: image = np.zeros(label.shape + (3,), dtype=np.float64) # Opacity doesn't make sense if no image exists. alpha = 1 else: if not image.shape[:2] == label.shape: raise ValueError("`image` and `label` must be the same shape") if image.min() < 0: warnings.warn("Negative intensities in `image` are not supported") image = img_as_float(rgb2gray(image)) image = gray2rgb(image) * image_alpha + (1 - image_alpha) # Ensure that all labels are non-negative so we can index into # `label_to_color` correctly. offset = min(label.min(), bg_label) if offset != 0: label = label - offset # Make sure you don't modify the input array. bg_label -= offset new_type = np.min_scalar_type(label.max()) if new_type == np.bool: new_type = np.uint8 label = label.astype(new_type) unique_labels, color_cycle = _match_label_with_color(label, colors, bg_label, bg_color) if len(unique_labels) == 0: return image dense_labels = range(max(unique_labels) + 1) label_to_color = np.array([c for i, c in zip(dense_labels, color_cycle)]) result = label_to_color[label] * alpha + image * (1 - alpha) # Remove background label if its color was not specified. remove_background = bg_label in unique_labels and bg_color is None if remove_background: result[label == bg_label] = image[label == bg_label] return result scikit-image-0.9.3/skimage/color/delta_e.py000066400000000000000000000243441223313777300206150ustar00rootroot00000000000000""" Functions for calculating the "distance" between colors. Implicit in these definitions of "distance" is the notion of "Just Noticeable Distance" (JND). This represents the distance between colors where a human can perceive different colors. Humans are more sensitive to certain colors than others, which different deltaE metrics correct for with varying degrees of sophistication. The literature often mentions 1 as the minimum distance for visual differentiation, but more recent studies (Mahy 1994) peg JND at 2.3 The delta-E notation comes from the German word for "Sensation" (Empfindung). Reference --------- http://en.wikipedia.org/wiki/Color_difference """ from __future__ import division import numpy as np from skimage.color.colorconv import lab2lch, _cart2polar_2pi def deltaE_cie76(lab1, lab2): """Euclidean distance between two points in Lab color space Parameters ---------- lab1 : array_like reference color (Lab colorspace) lab2 : array_like comparison color (Lab colorspace) Returns ------- dE : array_like distance between colors `lab1` and `lab2` References ---------- .. [1] http://en.wikipedia.org/wiki/Color_difference .. [2] A. R. Robertson, "The CIE 1976 color-difference formulae," Color Res. Appl. 2, 7-11 (1977). """ lab1 = np.asarray(lab1) lab2 = np.asarray(lab2) L1, a1, b1 = np.rollaxis(lab1, -1)[:3] L2, a2, b2 = np.rollaxis(lab2, -1)[:3] return np.sqrt((L2 - L1) ** 2 + (a2 - a1) ** 2 + (b2 - b1) ** 2) def deltaE_ciede94(lab1, lab2, kH=1, kC=1, kL=1, k1=0.045, k2=0.015): """Color difference according to CIEDE 94 standard Accommodates perceptual non-uniformities through the use of application specific scale factors (`kH`, `kC`, `kL`, `k1`, and `k2`). Parameters ---------- lab1 : array_like reference color (Lab colorspace) lab2 : array_like comparison color (Lab colorspace) kH : float, optional Hue scale kC : float, optional Chroma scale kL : float, optional Lightness scale k1 : float, optional first scale parameter k2 : float, optional second scale parameter Returns ------- dE : array_like color difference between `lab1` and `lab2` Notes ----- deltaE_ciede94 is not symmetric with respect to lab1 and lab2. CIEDE94 defines the scales for the lightness, hue, and chroma in terms of the first color. Consequently, the first color should be regarded as the "reference" color. `kL`, `k1`, `k2` depend on the application and default to the values suggested for graphic arts ========== ============== ========== Parameter Graphic Arts Textiles ========== ============== ========== `kL` 1.000 2.000 `k1` 0.045 0.048 `k2` 0.015 0.014 ========== ============== ========== References ---------- .. [1] http://en.wikipedia.org/wiki/Color_difference .. [2] http://www.brucelindbloom.com/index.html?Eqn_DeltaE_CIE94.html """ L1, C1 = np.rollaxis(lab2lch(lab1), -1)[:2] L2, C2 = np.rollaxis(lab2lch(lab2), -1)[:2] dL = L1 - L2 dC = C1 - C2 dH2 = get_dH2(lab1, lab2) SL = 1 SC = 1 + k1 * C1 SH = 1 + k2 * C1 dE2 = (dL / (kL * SL)) ** 2 dE2 += (dC / (kC * SC)) ** 2 dE2 += dH2 / (kH * SH) ** 2 return np.sqrt(dE2) def deltaE_ciede2000(lab1, lab2, kL=1, kC=1, kH=1): """Color difference as given by the CIEDE 2000 standard. CIEDE 2000 is a major revision of CIDE94. The perceptual calibration is largely based on experience with automotive paint on smooth surfaces. Parameters ---------- lab1 : array_like reference color (Lab colorspace) lab2 : array_like comparison color (Lab colorspace) kL : float (range), optional lightness scale factor, 1 for "acceptably close"; 2 for "imperceptible" see deltaE_cmc kC : float (range), optional chroma scale factor, usually 1 kH : float (range), optional hue scale factor, usually 1 Returns ------- deltaE : array_like The distance between `lab1` and `lab2` Notes ----- CIEDE 2000 assumes parametric weighting factors for the lightness, chroma, and hue (`kL`, `kC`, `kH` respectively). These default to 1. References ---------- .. [1] http://en.wikipedia.org/wiki/Color_difference .. [2] http://www.ece.rochester.edu/~gsharma/ciede2000/ciede2000noteCRNA.pdf (doi:10.1364/AO.33.008069) .. [3] M. Melgosa, J. Quesada, and E. Hita, "Uniformity of some recent color metrics tested with an accurate color-difference tolerance dataset," Appl. Opt. 33, 8069-8077 (1994). """ lab1 = np.asarray(lab1) lab2 = np.asarray(lab2) unroll = False if lab1.ndim == 1 and lab2.ndim == 1: unroll = True if lab1.ndim == 1: lab1 = lab1[None, :] if lab2.ndim == 1: lab2 = lab2[None, :] L1, a1, b1 = np.rollaxis(lab1, -1)[:3] L2, a2, b2 = np.rollaxis(lab2, -1)[:3] # distort `a` based on average chroma # then convert to lch coordines from distorted `a` # all subsequence calculations are in the new coordiantes # (often denoted "prime" in the literature) Cbar = 0.5 * (np.hypot(a1, b1) + np.hypot(a2, b2)) c7 = Cbar ** 7 G = 0.5 * (1 - np.sqrt(c7 / (c7 + 25 ** 7))) scale = 1 + G C1, h1 = _cart2polar_2pi(a1 * scale, b1) C2, h2 = _cart2polar_2pi(a2 * scale, b2) # recall that c, h are polar coordiantes. c==r, h==theta # cide2000 has four terms to delta_e: # 1) Luminance term # 2) Hue term # 3) Chroma term # 4) hue Rotation term # lightness term Lbar = 0.5 * (L1 + L2) tmp = (Lbar - 50) ** 2 SL = 1 + 0.015 * tmp / np.sqrt(20 + tmp) L_term = (L2 - L1) / (kL * SL) # chroma term Cbar = 0.5 * (C1 + C2) # new coordiantes SC = 1 + 0.045 * Cbar C_term = (C2 - C1) / (kC * SC) # hue term h_diff = h2 - h1 h_sum = h1 + h2 CC = C1 * C2 dH = h_diff.copy() dH[h_diff > np.pi] -= 2 * np.pi dH[h_diff < -np.pi] += 2 * np.pi dH[CC == 0.] = 0. # if r == 0, dtheta == 0 dH_term = 2 * np.sqrt(CC) * np.sin(dH / 2) Hbar = h_sum.copy() mask = np.logical_and(CC != 0., np.abs(h_diff) > np.pi) Hbar[mask * (h_sum < 2 * np.pi)] += 2 * np.pi Hbar[mask * (h_sum >= 2 * np.pi)] -= 2 * np.pi Hbar[CC == 0.] *= 2 Hbar *= 0.5 T = (1 - 0.17 * np.cos(Hbar - np.deg2rad(30)) + 0.24 * np.cos(2 * Hbar) + 0.32 * np.cos(3 * Hbar + np.deg2rad(6)) - 0.20 * np.cos(4 * Hbar - np.deg2rad(63)) ) SH = 1 + 0.015 * Cbar * T H_term = dH_term / (kH * SH) # hue rotation c7 = Cbar ** 7 Rc = 2 * np.sqrt(c7 / (c7 + 25 ** 7)) dtheta = np.deg2rad(30) * np.exp(-((np.rad2deg(Hbar) - 275) / 25) ** 2) R_term = -np.sin(2 * dtheta) * Rc * C_term * H_term # put it all together dE2 = L_term ** 2 dE2 += C_term ** 2 dE2 += H_term ** 2 dE2 += R_term ans = np.sqrt(dE2) if unroll: ans = ans[0] return ans def deltaE_cmc(lab1, lab2, kL=1, kC=1): """Color difference from the CMC l:c standard. This color difference was developed by the Colour Measurement Committee (CMC) of the Society of Dyers and Colourists (United Kingdom). It is intended for use in the textile industry. The scale factors `kL`, `kC` set the weight given to differences in lightness and chroma relative to differences in hue. The usual values are ``kL=2``, ``kC=1`` for "acceptability" and ``kL=1``, ``kC=1`` for "imperceptibility". Colors with ``dE > 1`` are "different" for the given scale factors. Parameters ---------- lab1 : array_like reference color (Lab colorspace) lab2 : array_like comparison color (Lab colorspace) Returns ------- dE : array_like distance between colors `lab1` and `lab2` Notes ----- deltaE_cmc the defines the scales for the lightness, hue, and chroma in terms of the first color. Consequently ``deltaE_cmc(lab1, lab2) != deltaE_cmc(lab2, lab1)`` References ---------- .. [1] http://en.wikipedia.org/wiki/Color_difference .. [2] http://www.brucelindbloom.com/index.html?Eqn_DeltaE_CIE94.html .. [3] F. J. J. Clarke, R. McDonald, and B. Rigg, "Modification to the JPC79 colour-difference formula," J. Soc. Dyers Colour. 100, 128-132 (1984). """ L1, C1, h1 = np.rollaxis(lab2lch(lab1), -1)[:3] L2, C2, h2 = np.rollaxis(lab2lch(lab2), -1)[:3] dC = C1 - C2 dL = L1 - L2 dH2 = get_dH2(lab1, lab2) T = np.where(np.logical_and(np.rad2deg(h1) >= 164, np.rad2deg(h1) <= 345), 0.56 + 0.2 * np.abs(np.cos(h1 + np.deg2rad(168))), 0.36 + 0.4 * np.abs(np.cos(h1 + np.deg2rad(35))) ) c1_4 = C1 ** 4 F = np.sqrt(c1_4 / (c1_4 + 1900)) SL = np.where(L1 < 16, 0.511, 0.040975 * L1 / (1. + 0.01765 * L1)) SC = 0.638 + 0.0638 * C1 / (1. + 0.0131 * C1) SH = SC * (F * T + 1 - F) dE2 = (dL / (kL * SL)) ** 2 dE2 += (dC / (kC * SC)) ** 2 dE2 += dH2 / (SH ** 2) return np.sqrt(dE2) def get_dH2(lab1, lab2): """squared hue difference term occurring in deltaE_cmc and deltaE_ciede94 Despite its name, "dH" is not a simple difference of hue values. We avoid working directly with the hue value, since differencing angles is troublesome. The hue term is usually written as: c1 = sqrt(a1**2 + b1**2) c2 = sqrt(a2**2 + b2**2) term = (a1-a2)**2 + (b1-b2)**2 - (c1-c2)**2 dH = sqrt(term) However, this has poor roundoff properties when a or b is dominant. Instead, ab is a vector with elements a and b. The same dH term can be re-written as: |ab1-ab2|**2 - (|ab1| - |ab2|)**2 and then simplified to: 2*|ab1|*|ab2| - 2*dot(ab1, ab2) """ lab1 = np.asarray(lab1) lab2 = np.asarray(lab2) a1, b1 = np.rollaxis(lab1, -1)[1:3] a2, b2 = np.rollaxis(lab2, -1)[1:3] # magnitude of (a, b) is the chroma C1 = np.hypot(a1, b1) C2 = np.hypot(a2, b2) term = (C1 * C2) - (a1 * a2 + b1 * b2) return 2*term scikit-image-0.9.3/skimage/color/rgb_colors.py000066400000000000000000000106151223313777300213470ustar00rootroot00000000000000aliceblue = (0.941, 0.973, 1) antiquewhite = (0.98, 0.922, 0.843) aqua = (0, 1, 1) aquamarine = (0.498, 1, 0.831) azure = (0.941, 1, 1) beige = (0.961, 0.961, 0.863) bisque = (1, 0.894, 0.769) black = (0, 0, 0) blanchedalmond = (1, 0.922, 0.804) blue = (0, 0, 1) blueviolet = (0.541, 0.169, 0.886) brown = (0.647, 0.165, 0.165) burlywood = (0.871, 0.722, 0.529) cadetblue = (0.373, 0.62, 0.627) chartreuse = (0.498, 1, 0) chocolate = (0.824, 0.412, 0.118) coral = (1, 0.498, 0.314) cornflowerblue = (0.392, 0.584, 0.929) cornsilk = (1, 0.973, 0.863) crimson = (0.863, 0.0784, 0.235) cyan = (0, 1, 1) darkblue = (0, 0, 0.545) darkcyan = (0, 0.545, 0.545) darkgoldenrod = (0.722, 0.525, 0.0431) darkgray = (0.663, 0.663, 0.663) darkgreen = (0, 0.392, 0) darkgrey = (0.663, 0.663, 0.663) darkkhaki = (0.741, 0.718, 0.42) darkmagenta = (0.545, 0, 0.545) darkolivegreen = (0.333, 0.42, 0.184) darkorange = (1, 0.549, 0) darkorchid = (0.6, 0.196, 0.8) darkred = (0.545, 0, 0) darksalmon = (0.914, 0.588, 0.478) darkseagreen = (0.561, 0.737, 0.561) darkslateblue = (0.282, 0.239, 0.545) darkslategray = (0.184, 0.31, 0.31) darkslategrey = (0.184, 0.31, 0.31) darkturquoise = (0, 0.808, 0.82) darkviolet = (0.58, 0, 0.827) deeppink = (1, 0.0784, 0.576) deepskyblue = (0, 0.749, 1) dimgray = (0.412, 0.412, 0.412) dimgrey = (0.412, 0.412, 0.412) dodgerblue = (0.118, 0.565, 1) firebrick = (0.698, 0.133, 0.133) floralwhite = (1, 0.98, 0.941) forestgreen = (0.133, 0.545, 0.133) fuchsia = (1, 0, 1) gainsboro = (0.863, 0.863, 0.863) ghostwhite = (0.973, 0.973, 1) gold = (1, 0.843, 0) goldenrod = (0.855, 0.647, 0.125) gray = (0.502, 0.502, 0.502) green = (0, 0.502, 0) greenyellow = (0.678, 1, 0.184) grey = (0.502, 0.502, 0.502) honeydew = (0.941, 1, 0.941) hotpink = (1, 0.412, 0.706) indianred = (0.804, 0.361, 0.361) indigo = (0.294, 0, 0.51) ivory = (1, 1, 0.941) khaki = (0.941, 0.902, 0.549) lavender = (0.902, 0.902, 0.98) lavenderblush = (1, 0.941, 0.961) lawngreen = (0.486, 0.988, 0) lemonchiffon = (1, 0.98, 0.804) lightblue = (0.678, 0.847, 0.902) lightcoral = (0.941, 0.502, 0.502) lightcyan = (0.878, 1, 1) lightgoldenrodyellow = (0.98, 0.98, 0.824) lightgray = (0.827, 0.827, 0.827) lightgreen = (0.565, 0.933, 0.565) lightgrey = (0.827, 0.827, 0.827) lightpink = (1, 0.714, 0.757) lightsalmon = (1, 0.627, 0.478) lightseagreen = (0.125, 0.698, 0.667) lightskyblue = (0.529, 0.808, 0.98) lightslategray = (0.467, 0.533, 0.6) lightslategrey = (0.467, 0.533, 0.6) lightsteelblue = (0.69, 0.769, 0.871) lightyellow = (1, 1, 0.878) lime = (0, 1, 0) limegreen = (0.196, 0.804, 0.196) linen = (0.98, 0.941, 0.902) magenta = (1, 0, 1) maroon = (0.502, 0, 0) mediumaquamarine = (0.4, 0.804, 0.667) mediumblue = (0, 0, 0.804) mediumorchid = (0.729, 0.333, 0.827) mediumpurple = (0.576, 0.439, 0.859) mediumseagreen = (0.235, 0.702, 0.443) mediumslateblue = (0.482, 0.408, 0.933) mediumspringgreen = (0, 0.98, 0.604) mediumturquoise = (0.282, 0.82, 0.8) mediumvioletred = (0.78, 0.0824, 0.522) midnightblue = (0.098, 0.098, 0.439) mintcream = (0.961, 1, 0.98) mistyrose = (1, 0.894, 0.882) moccasin = (1, 0.894, 0.71) navajowhite = (1, 0.871, 0.678) navy = (0, 0, 0.502) oldlace = (0.992, 0.961, 0.902) olive = (0.502, 0.502, 0) olivedrab = (0.42, 0.557, 0.137) orange = (1, 0.647, 0) orangered = (1, 0.271, 0) orchid = (0.855, 0.439, 0.839) palegoldenrod = (0.933, 0.91, 0.667) palegreen = (0.596, 0.984, 0.596) palevioletred = (0.686, 0.933, 0.933) papayawhip = (1, 0.937, 0.835) peachpuff = (1, 0.855, 0.725) peru = (0.804, 0.522, 0.247) pink = (1, 0.753, 0.796) plum = (0.867, 0.627, 0.867) powderblue = (0.69, 0.878, 0.902) purple = (0.502, 0, 0.502) red = (1, 0, 0) rosybrown = (0.737, 0.561, 0.561) royalblue = (0.255, 0.412, 0.882) saddlebrown = (0.545, 0.271, 0.0745) salmon = (0.98, 0.502, 0.447) sandybrown = (0.98, 0.643, 0.376) seagreen = (0.18, 0.545, 0.341) seashell = (1, 0.961, 0.933) sienna = (0.627, 0.322, 0.176) silver = (0.753, 0.753, 0.753) skyblue = (0.529, 0.808, 0.922) slateblue = (0.416, 0.353, 0.804) slategray = (0.439, 0.502, 0.565) slategrey = (0.439, 0.502, 0.565) snow = (1, 0.98, 0.98) springgreen = (0, 1, 0.498) steelblue = (0.275, 0.51, 0.706) tan = (0.824, 0.706, 0.549) teal = (0, 0.502, 0.502) thistle = (0.847, 0.749, 0.847) tomato = (1, 0.388, 0.278) turquoise = (0.251, 0.878, 0.816) violet = (0.933, 0.51, 0.933) wheat = (0.961, 0.871, 0.702) white = (1, 1, 1) whitesmoke = (0.961, 0.961, 0.961) yellow = (1, 1, 0) yellowgreen = (0.604, 0.804, 0.196) scikit-image-0.9.3/skimage/color/tests/000077500000000000000000000000001223313777300200015ustar00rootroot00000000000000scikit-image-0.9.3/skimage/color/tests/ciede2000_test_data.txt000066400000000000000000000131151223313777300241460ustar00rootroot00000000000000# input, intermediate, and output values for CIEDE2000 dE function # data taken from "The CIEDE2000 Color-Difference Formula: Implementation Notes, ..." http://www.ece.rochester.edu/~gsharma/ciede2000/ciede2000noteCRNA.pdf # tab delimited data # pair 1 L1 a1 b1 ap1 cp1 hp1 hbar1 G T SL SC SH RT dE 2 L2 a2 b2 ap2 cp2 hp2 1 1 50.0000 2.6772 -79.7751 2.6774 79.8200 271.9222 270.9611 0.0001 0.6907 1.0000 4.6578 1.8421 -1.7042 2.0425 2 50.0000 0.0000 -82.7485 0.0000 82.7485 270.0000 2 1 50.0000 3.1571 -77.2803 3.1573 77.3448 272.3395 271.1698 0.0001 0.6843 1.0000 4.6021 1.8216 -1.7070 2.8615 2 50.0000 0.0000 -82.7485 0.0000 82.7485 270.0000 3 1 50.0000 2.8361 -74.0200 2.8363 74.0743 272.1944 271.0972 0.0001 0.6865 1.0000 4.5285 1.8074 -1.7060 3.4412 2 50.0000 0.0000 -82.7485 0.0000 82.7485 270.0000 4 1 50.0000 -1.3802 -84.2814 -1.3803 84.2927 269.0618 269.5309 0.0001 0.7357 1.0000 4.7584 1.9217 -1.6809 1.0000 2 50.0000 0.0000 -82.7485 0.0000 82.7485 270.0000 5 1 50.0000 -1.1848 -84.8006 -1.1849 84.8089 269.1995 269.5997 0.0001 0.7335 1.0000 4.7700 1.9218 -1.6822 1.0000 2 50.0000 0.0000 -82.7485 0.0000 82.7485 270.0000 6 1 50.0000 -0.9009 -85.5211 -0.9009 85.5258 269.3964 269.6982 0.0001 0.7303 1.0000 4.7862 1.9217 -1.6840 1.0000 2 50.0000 0.0000 -82.7485 0.0000 82.7485 270.0000 7 1 50.0000 0.0000 0.0000 0.0000 0.0000 0.0000 126.8697 0.5000 1.2200 1.0000 1.0562 1.0229 0.0000 2.3669 2 50.0000 -1.0000 2.0000 -1.5000 2.5000 126.8697 8 1 50.0000 -1.0000 2.0000 -1.5000 2.5000 126.8697 126.8697 0.5000 1.2200 1.0000 1.0562 1.0229 0.0000 2.3669 2 50.0000 0.0000 0.0000 0.0000 0.0000 0.0000 9 1 50.0000 2.4900 -0.0010 3.7346 3.7346 359.9847 269.9854 0.4998 0.7212 1.0000 1.1681 1.0404 -0.0022 7.1792 2 50.0000 -2.4900 0.0009 -3.7346 3.7346 179.9862 10 1 50.0000 2.4900 -0.0010 3.7346 3.7346 359.9847 269.9847 0.4998 0.7212 1.0000 1.1681 1.0404 -0.0022 7.1792 2 50.0000 -2.4900 0.0010 -3.7346 3.7346 179.9847 11 1 50.0000 2.4900 -0.0010 3.7346 3.7346 359.9847 89.9839 0.4998 0.6175 1.0000 1.1681 1.0346 0.0000 7.2195 2 50.0000 -2.4900 0.0011 -3.7346 3.7346 179.9831 12 1 50.0000 2.4900 -0.0010 3.7346 3.7346 359.9847 89.9831 0.4998 0.6175 1.0000 1.1681 1.0346 0.0000 7.2195 2 50.0000 -2.4900 0.0012 -3.7346 3.7346 179.9816 13 1 50.0000 -0.0010 2.4900 -0.0015 2.4900 90.0345 180.0328 0.4998 0.9779 1.0000 1.1121 1.0365 0.0000 4.8045 2 50.0000 0.0009 -2.4900 0.0013 2.4900 270.0311 14 1 50.0000 -0.0010 2.4900 -0.0015 2.4900 90.0345 180.0345 0.4998 0.9779 1.0000 1.1121 1.0365 0.0000 4.8045 2 50.0000 0.0010 -2.4900 0.0015 2.4900 270.0345 15 1 50.0000 -0.0010 2.4900 -0.0015 2.4900 90.0345 0.0362 0.4998 1.3197 1.0000 1.1121 1.0493 0.0000 4.7461 2 50.0000 0.0011 -2.4900 0.0016 2.4900 270.0380 16 1 50.0000 2.5000 0.0000 3.7496 3.7496 0.0000 315.0000 0.4998 0.8454 1.0000 1.1406 1.0396 -0.0001 4.3065 2 50.0000 0.0000 -2.5000 0.0000 2.5000 270.0000 17 1 50.0000 2.5000 0.0000 3.4569 3.4569 0.0000 346.2470 0.3827 1.4453 1.1608 1.9547 1.4599 -0.0003 27.1492 2 73.0000 25.0000 -18.0000 34.5687 38.9743 332.4939 18 1 50.0000 2.5000 0.0000 3.4954 3.4954 0.0000 51.7766 0.3981 0.6447 1.0640 1.7498 1.1612 0.0000 22.8977 2 61.0000 -5.0000 29.0000 -6.9907 29.8307 103.5532 19 1 50.0000 2.5000 0.0000 3.5514 3.5514 0.0000 272.2362 0.4206 0.6521 1.0251 1.9455 1.2055 -0.8219 31.9030 2 56.0000 -27.0000 -3.0000 -38.3556 38.4728 184.4723 20 1 50.0000 2.5000 0.0000 3.5244 3.5244 0.0000 11.9548 0.4098 1.1031 1.0400 1.9120 1.3353 0.0000 19.4535 2 58.0000 24.0000 15.0000 33.8342 37.0102 23.9095 21 1 50.0000 2.5000 0.0000 3.7494 3.7494 0.0000 3.5056 0.4997 1.2616 1.0000 1.1923 1.0808 0.0000 1.0000 2 50.0000 3.1736 0.5854 4.7596 4.7954 7.0113 22 1 50.0000 2.5000 0.0000 3.7493 3.7493 0.0000 0.0000 0.4997 1.3202 1.0000 1.1956 1.0861 0.0000 1.0000 2 50.0000 3.2972 0.0000 4.9450 4.9450 0.0000 23 1 50.0000 2.5000 0.0000 3.7497 3.7497 0.0000 5.8190 0.4999 1.2197 1.0000 1.1486 1.0604 0.0000 1.0000 2 50.0000 1.8634 0.5757 2.7949 2.8536 11.6380 24 1 50.0000 2.5000 0.0000 3.7493 3.7493 0.0000 1.9603 0.4997 1.2883 1.0000 1.1946 1.0836 0.0000 1.0000 2 50.0000 3.2592 0.3350 4.8879 4.8994 3.9206 25 1 60.2574 -34.0099 36.2677 -34.0678 49.7590 133.2085 132.0835 0.0017 1.3010 1.1427 3.2946 1.9951 0.0000 1.2644 2 60.4626 -34.1751 39.4387 -34.2333 52.2238 130.9584 26 1 63.0109 -31.0961 -5.8663 -32.6194 33.1427 190.1951 188.8221 0.0490 0.9402 1.1831 2.4549 1.4560 0.0000 1.2630 2 62.8187 -29.7946 -4.0864 -31.2542 31.5202 187.4490 27 1 61.2901 3.7196 -5.3901 5.5668 7.7487 315.9240 310.0313 0.4966 0.6952 1.1586 1.3092 1.0717 -0.0032 1.8731 2 61.4292 2.2480 -4.9620 3.3644 5.9950 304.1385 28 1 35.0831 -44.1164 3.7933 -44.3939 44.5557 175.1161 176.4290 0.0063 1.0168 1.2148 2.9105 1.6476 0.0000 1.8645 2 35.0232 -40.0716 1.5901 -40.3237 40.3550 177.7418 29 1 22.7233 20.0904 -46.6940 20.1424 50.8532 293.3339 291.3809 0.0026 0.3636 1.4014 3.1597 1.2617 -1.2537 2.0373 2 23.0331 14.9730 -42.5619 15.0118 45.1317 289.4279 30 1 36.4612 47.8580 18.3852 47.9197 51.3256 20.9901 21.8781 0.0013 0.9239 1.1943 3.3888 1.7357 0.0000 1.4146 2 36.2715 50.5065 21.2231 50.5716 54.8444 22.7660 31 1 90.8027 -2.0831 1.4410 -3.1245 3.4408 155.2410 167.1011 0.4999 1.1546 1.6110 1.1329 1.0511 0.0000 1.4441 2 91.1528 -1.6435 0.0447 -2.4651 2.4655 178.9612 32 1 90.9257 -0.5406 -0.9208 -0.8109 1.2270 228.6315 218.4363 0.5000 1.3916 1.5930 1.0620 1.0288 0.0000 1.5381 2 88.6381 -0.8985 -0.7239 -1.3477 1.5298 208.2412 33 1 6.7747 -0.2908 -2.4247 -0.4362 2.4636 259.8025 263.0049 0.4999 0.9556 1.6517 1.1057 1.0337 -0.0004 0.6377 2 5.8714 -0.0985 -2.2286 -0.1477 2.2335 266.2073 34 1 2.0776 0.0795 -1.1350 0.1192 1.1412 275.9978 268.0910 0.5000 0.7826 1.7246 1.0383 1.0100 0.0000 0.9082 2 0.9033 -0.0636 -0.5514 -0.0954 0.5596 260.18421 scikit-image-0.9.3/skimage/color/tests/test_colorconv.py000066400000000000000000000274671223313777300234360ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """Tests for color conversion functions. Authors ------- - the rgb2hsv test was written by Nicolas Pinto, 2009 - other tests written by Ralf Gommers, 2009 :license: modified BSD """ import os.path import numpy as np from numpy.testing import (assert_equal, assert_almost_equal, assert_array_almost_equal, assert_raises, TestCase, ) from skimage import img_as_float, img_as_ubyte from skimage.io import imread from skimage.color import (rgb2hsv, hsv2rgb, rgb2xyz, xyz2rgb, rgb2hed, hed2rgb, separate_stains, combine_stains, rgb2rgbcie, rgbcie2rgb, convert_colorspace, rgb2grey, gray2rgb, xyz2lab, lab2xyz, lab2rgb, rgb2lab, is_rgb, is_gray, lab2lch, lch2lab, guess_spatial_dimensions ) from skimage import data_dir, data import colorsys def test_guess_spatial_dimensions(): im1 = np.zeros((5, 5)) im2 = np.zeros((5, 5, 5)) im3 = np.zeros((5, 5, 3)) im4 = np.zeros((5, 5, 5, 3)) im5 = np.zeros((5,)) assert_equal(guess_spatial_dimensions(im1), 2) assert_equal(guess_spatial_dimensions(im2), 3) assert_equal(guess_spatial_dimensions(im3), None) assert_equal(guess_spatial_dimensions(im4), 3) assert_raises(ValueError, guess_spatial_dimensions, im5) class TestColorconv(TestCase): img_rgb = imread(os.path.join(data_dir, 'color.png')) img_grayscale = imread(os.path.join(data_dir, 'camera.png')) colbars = np.array([[1, 1, 0, 0, 1, 1, 0, 0], [1, 1, 1, 1, 0, 0, 0, 0], [1, 0, 1, 0, 1, 0, 1, 0]]).astype(np.float) colbars_array = np.swapaxes(colbars.reshape(3, 4, 2), 0, 2) colbars_point75 = colbars * 0.75 colbars_point75_array = np.swapaxes(colbars_point75.reshape(3, 4, 2), 0, 2) xyz_array = np.array([[[0.4124, 0.21260, 0.01930]], # red [[0, 0, 0]], # black [[.9505, 1., 1.089]], # white [[.1805, .0722, .9505]], # blue [[.07719, .15438, .02573]], # green ]) lab_array = np.array([[[53.233, 80.109, 67.220]], # red [[0., 0., 0.]], # black [[100.0, 0.005, -0.010]], # white [[32.303, 79.197, -107.864]], # blue [[46.229, -51.7, 49.898]], # green ]) # RGB to HSV def test_rgb2hsv_conversion(self): rgb = img_as_float(self.img_rgb)[::16, ::16] hsv = rgb2hsv(rgb).reshape(-1, 3) # ground truth from colorsys gt = np.array([colorsys.rgb_to_hsv(pt[0], pt[1], pt[2]) for pt in rgb.reshape(-1, 3)] ) assert_almost_equal(hsv, gt) def test_rgb2hsv_error_grayscale(self): self.assertRaises(ValueError, rgb2hsv, self.img_grayscale) def test_rgb2hsv_error_one_element(self): self.assertRaises(ValueError, rgb2hsv, self.img_rgb[0, 0]) # HSV to RGB def test_hsv2rgb_conversion(self): rgb = self.img_rgb.astype("float32")[::16, ::16] # create HSV image with colorsys hsv = np.array([colorsys.rgb_to_hsv(pt[0], pt[1], pt[2]) for pt in rgb.reshape(-1, 3)]).reshape(rgb.shape) # convert back to RGB and compare with original. # relative precision for RGB -> HSV roundtrip is about 1e-6 assert_almost_equal(rgb, hsv2rgb(hsv), decimal=4) def test_hsv2rgb_error_grayscale(self): self.assertRaises(ValueError, hsv2rgb, self.img_grayscale) def test_hsv2rgb_error_one_element(self): self.assertRaises(ValueError, hsv2rgb, self.img_rgb[0, 0]) # RGB to XYZ def test_rgb2xyz_conversion(self): gt = np.array([[[0.950456, 1. , 1.088754], [0.538003, 0.787329, 1.06942 ], [0.592876, 0.28484 , 0.969561], [0.180423, 0.072169, 0.950227]], [[0.770033, 0.927831, 0.138527], [0.35758 , 0.71516 , 0.119193], [0.412453, 0.212671, 0.019334], [0. , 0. , 0. ]]]) assert_almost_equal(rgb2xyz(self.colbars_array), gt) # stop repeating the "raises" checks for all other functions that are # implemented with color._convert() def test_rgb2xyz_error_grayscale(self): self.assertRaises(ValueError, rgb2xyz, self.img_grayscale) def test_rgb2xyz_error_one_element(self): self.assertRaises(ValueError, rgb2xyz, self.img_rgb[0, 0]) # XYZ to RGB def test_xyz2rgb_conversion(self): assert_almost_equal(xyz2rgb(rgb2xyz(self.colbars_array)), self.colbars_array) # RGB<->XYZ roundtrip on another image def test_xyz_rgb_roundtrip(self): img_rgb = img_as_float(self.img_rgb) assert_array_almost_equal(xyz2rgb(rgb2xyz(img_rgb)), img_rgb) # RGB<->HED roundtrip with ubyte image def test_hed_rgb_roundtrip(self): img_rgb = img_as_ubyte(self.img_rgb) assert_equal(img_as_ubyte(hed2rgb(rgb2hed(img_rgb))), img_rgb) # RGB<->HED roundtrip with float image def test_hed_rgb_float_roundtrip(self): img_rgb = img_as_float(self.img_rgb) assert_array_almost_equal(hed2rgb(rgb2hed(img_rgb)), img_rgb) # RGB<->HDX roundtrip with ubyte image def test_hdx_rgb_roundtrip(self): from skimage.color.colorconv import hdx_from_rgb, rgb_from_hdx img_rgb = self.img_rgb conv = combine_stains(separate_stains(img_rgb, hdx_from_rgb), rgb_from_hdx) assert_equal(img_as_ubyte(conv), img_rgb) # RGB<->HDX roundtrip with ubyte image def test_hdx_rgb_roundtrip(self): from skimage.color.colorconv import hdx_from_rgb, rgb_from_hdx img_rgb = img_as_float(self.img_rgb) conv = combine_stains(separate_stains(img_rgb, hdx_from_rgb), rgb_from_hdx) assert_array_almost_equal(conv, img_rgb) # RGB to RGB CIE def test_rgb2rgbcie_conversion(self): gt = np.array([[[ 0.1488856 , 0.18288098, 0.19277574], [ 0.01163224, 0.16649536, 0.18948516], [ 0.12259182, 0.03308008, 0.17298223], [-0.01466154, 0.01669446, 0.16969164]], [[ 0.16354714, 0.16618652, 0.0230841 ], [ 0.02629378, 0.1498009 , 0.01979351], [ 0.13725336, 0.01638562, 0.00329059], [ 0. , 0. , 0. ]]]) assert_almost_equal(rgb2rgbcie(self.colbars_array), gt) # RGB CIE to RGB def test_rgbcie2rgb_conversion(self): # only roundtrip test, we checked rgb2rgbcie above already assert_almost_equal(rgbcie2rgb(rgb2rgbcie(self.colbars_array)), self.colbars_array) def test_convert_colorspace(self): colspaces = ['HSV', 'RGB CIE', 'XYZ'] colfuncs_from = [hsv2rgb, rgbcie2rgb, xyz2rgb] colfuncs_to = [rgb2hsv, rgb2rgbcie, rgb2xyz] assert_almost_equal(convert_colorspace(self.colbars_array, 'RGB', 'RGB'), self.colbars_array) for i, space in enumerate(colspaces): gt = colfuncs_from[i](self.colbars_array) assert_almost_equal(convert_colorspace(self.colbars_array, space, 'RGB'), gt) gt = colfuncs_to[i](self.colbars_array) assert_almost_equal(convert_colorspace(self.colbars_array, 'RGB', space), gt) self.assertRaises(ValueError, convert_colorspace, self.colbars_array, 'nokey', 'XYZ') self.assertRaises(ValueError, convert_colorspace, self.colbars_array, 'RGB', 'nokey') def test_rgb2grey(self): x = np.array([1, 1, 1]).reshape((1, 1, 3)).astype(np.float) g = rgb2grey(x) assert_array_almost_equal(g, 1) assert_equal(g.shape, (1, 1)) def test_rgb2grey_on_grey(self): rgb2grey(np.random.random((5, 5))) # test matrices for xyz2lab and lab2xyz generated using http://www.easyrgb.com/index.php?X=CALC # Note: easyrgb website displays xyz*100 def test_xyz2lab(self): assert_array_almost_equal(xyz2lab(self.xyz_array), self.lab_array, decimal=3) def test_lab2xyz(self): assert_array_almost_equal(lab2xyz(self.lab_array), self.xyz_array, decimal=3) def test_rgb2lab_brucelindbloom(self): """ Test the RGB->Lab conversion by comparing to the calculator on the authoritative Bruce Lindbloom [website](http://brucelindbloom.com/index.html?ColorCalculator.html). """ # Obtained with D65 white point, sRGB model and gamma gt_for_colbars = np.array([ [100,0,0], [97.1393, -21.5537, 94.4780], [91.1132, -48.0875, -14.1312], [87.7347, -86.1827, 83.1793], [60.3242, 98.2343, -60.8249], [53.2408, 80.0925, 67.2032], [32.2970, 79.1875, -107.8602], [0,0,0]]).T gt_array = np.swapaxes(gt_for_colbars.reshape(3, 4, 2), 0, 2) assert_array_almost_equal(rgb2lab(self.colbars_array), gt_array, decimal=2) def test_lab_rgb_roundtrip(self): img_rgb = img_as_float(self.img_rgb) assert_array_almost_equal(lab2rgb(rgb2lab(img_rgb)), img_rgb) def test_lab_lch_roundtrip(self): rgb = img_as_float(self.img_rgb) lab = rgb2lab(rgb) lab2 = lch2lab(lab2lch(lab)) assert_array_almost_equal(lab2, lab) def test_rgb_lch_roundtrip(self): rgb = img_as_float(self.img_rgb) lab = rgb2lab(rgb) lch = lab2lch(lab) lab2 = lch2lab(lch) rgb2 = lab2rgb(lab2) assert_array_almost_equal(rgb, rgb2) def test_lab_lch_0d(self): lab0 = self._get_lab0() lch0 = lab2lch(lab0) lch2 = lab2lch(lab0[None, None, :]) assert_array_almost_equal(lch0, lch2[0, 0, :]) def test_lab_lch_1d(self): lab0 = self._get_lab0() lch0 = lab2lch(lab0) lch1 = lab2lch(lab0[None, :]) assert_array_almost_equal(lch0, lch1[0, :]) def test_lab_lch_3d(self): lab0 = self._get_lab0() lch0 = lab2lch(lab0) lch3 = lab2lch(lab0[None, None, None, :]) assert_array_almost_equal(lch0, lch3[0, 0, 0, :]) def _get_lab0(self): rgb = img_as_float(self.img_rgb[:1, :1, :]) return rgb2lab(rgb)[0, 0, :] def test_gray2rgb(): x = np.array([0, 0.5, 1]) assert_raises(ValueError, gray2rgb, x) x = x.reshape((3, 1)) y = gray2rgb(x) assert_equal(y.shape, (3, 1, 3)) assert_equal(y.dtype, x.dtype) x = np.array([[0, 128, 255]], dtype=np.uint8) z = gray2rgb(x) assert_equal(z.shape, (1, 3, 3)) assert_equal(z[..., 0], x) assert_equal(z[0, 1, :], [128, 128, 128]) def test_gray2rgb_rgb(): x = np.random.random((5, 5, 4)) y = gray2rgb(x) assert_equal(x, y) def test_is_rgb(): color = data.lena() gray = data.camera() assert is_rgb(color) assert not is_gray(color) assert is_gray(gray) assert not is_gray(color) if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/color/tests/test_colorlabel.py000066400000000000000000000060121223313777300235270ustar00rootroot00000000000000import itertools import numpy as np from numpy import testing from skimage.color.colorlabel import label2rgb from numpy.testing import (assert_array_almost_equal as assert_close, assert_array_equal) def test_shape_mismatch(): image = np.ones((3, 3)) label = np.ones((2, 2)) testing.assert_raises(ValueError, label2rgb, image, label) def test_rgb(): image = np.ones((1, 3)) label = np.arange(3).reshape(1, -1) colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1)] # Set alphas just in case the defaults change rgb = label2rgb(label, image=image, colors=colors, alpha=1, image_alpha=1) assert_close(rgb, [colors]) def test_alpha(): image = np.random.uniform(size=(3, 3)) label = np.random.randint(0, 9, size=(3, 3)) # If we set `alpha = 0`, then rgb should match image exactly. rgb = label2rgb(label, image=image, alpha=0, image_alpha=1) assert_close(rgb[..., 0], image) assert_close(rgb[..., 1], image) assert_close(rgb[..., 2], image) def test_no_input_image(): label = np.arange(3).reshape(1, -1) colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1)] rgb = label2rgb(label, colors=colors) assert_close(rgb, [colors]) def test_image_alpha(): image = np.random.uniform(size=(1, 3)) label = np.arange(3).reshape(1, -1) colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1)] # If we set `image_alpha = 0`, then rgb should match label colors exactly. rgb = label2rgb(label, image=image, colors=colors, alpha=1, image_alpha=0) assert_close(rgb, [colors]) def test_color_names(): image = np.ones((1, 3)) label = np.arange(3).reshape(1, -1) cnames = ['red', 'lime', 'blue'] colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1)] # Set alphas just in case the defaults change rgb = label2rgb(label, image=image, colors=cnames, alpha=1, image_alpha=1) assert_close(rgb, [colors]) def test_bg_and_color_cycle(): image = np.zeros((1, 10)) # dummy image label = np.arange(10).reshape(1, -1) colors = [(1, 0, 0), (0, 0, 1)] bg_color = (0, 0, 0) rgb = label2rgb(label, image=image, bg_label=0, bg_color=bg_color, colors=colors, alpha=1) assert_close(rgb[0, 0], bg_color) for pixel, color in zip(rgb[0, 1:], itertools.cycle(colors)): assert_close(pixel, color) def test_label_consistency(): """Assert that the same labels map to the same colors.""" label_1 = np.arange(5).reshape(1, -1) label_2 = np.array([2, 4]) colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1)] # Set alphas just in case the defaults change rgb_1 = label2rgb(label_1, colors=colors) rgb_2 = label2rgb(label_2, colors=colors) for label_id in label_2.flat: assert_close(rgb_1[label_1 == label_id], rgb_2[label_2 == label_id]) def test_leave_labels_alone(): labels = np.array([-1, 0, 1]) labels_saved = labels.copy() label2rgb(labels) label2rgb(labels, bg_label=1) assert_array_equal(labels, labels_saved) if __name__ == '__main__': testing.run_module_suite() scikit-image-0.9.3/skimage/color/tests/test_delta_e.py000066400000000000000000000113261223313777300230120ustar00rootroot00000000000000"""Test for correctness of color distance functions""" from os.path import abspath, dirname, join as pjoin import numpy as np from numpy.testing import assert_allclose from skimage.color import (deltaE_cie76, deltaE_ciede94, deltaE_ciede2000, deltaE_cmc) def test_ciede2000_dE(): data = load_ciede2000_data() N = len(data) lab1 = np.zeros((N, 3)) lab1[:, 0] = data['L1'] lab1[:, 1] = data['a1'] lab1[:, 2] = data['b1'] lab2 = np.zeros((N, 3)) lab2[:, 0] = data['L2'] lab2[:, 1] = data['a2'] lab2[:, 2] = data['b2'] dE2 = deltaE_ciede2000(lab1, lab2) assert_allclose(dE2, data['dE'], rtol=1.e-4) def load_ciede2000_data(): dtype = [('pair', int), ('1', int), ('L1', float), ('a1', float), ('b1', float), ('a1_prime', float), ('C1_prime', float), ('h1_prime', float), ('hbar_prime', float), ('G', float), ('T', float), ('SL', float), ('SC', float), ('SH', float), ('RT', float), ('dE', float), ('2', int), ('L2', float), ('a2', float), ('b2', float), ('a2_prime', float), ('C2_prime', float), ('h2_prime', float), ] # note: ciede_test_data.txt contains several intermediate quantities path = pjoin(dirname(abspath(__file__)), 'ciede2000_test_data.txt') return np.loadtxt(path, dtype=dtype) def test_cie76(): data = load_ciede2000_data() N = len(data) lab1 = np.zeros((N, 3)) lab1[:, 0] = data['L1'] lab1[:, 1] = data['a1'] lab1[:, 2] = data['b1'] lab2 = np.zeros((N, 3)) lab2[:, 0] = data['L2'] lab2[:, 1] = data['a2'] lab2[:, 2] = data['b2'] dE2 = deltaE_cie76(lab1, lab2) oracle = np.array([ 4.00106328, 6.31415011, 9.1776999, 2.06270077, 2.36957073, 2.91529271, 2.23606798, 2.23606798, 4.98000036, 4.9800004, 4.98000044, 4.98000049, 4.98000036, 4.9800004, 4.98000044, 3.53553391, 36.86800781, 31.91002977, 30.25309901, 27.40894015, 0.89242934, 0.7972, 0.8583065, 0.82982507, 3.1819238, 2.21334297, 1.53890382, 4.60630929, 6.58467989, 3.88641412, 1.50514845, 2.3237848, 0.94413208, 1.31910843 ]) assert_allclose(dE2, oracle, rtol=1.e-8) def test_ciede94(): data = load_ciede2000_data() N = len(data) lab1 = np.zeros((N, 3)) lab1[:, 0] = data['L1'] lab1[:, 1] = data['a1'] lab1[:, 2] = data['b1'] lab2 = np.zeros((N, 3)) lab2[:, 0] = data['L2'] lab2[:, 1] = data['a2'] lab2[:, 2] = data['b2'] dE2 = deltaE_ciede94(lab1, lab2) oracle = np.array([ 1.39503887, 1.93410055, 2.45433566, 0.68449187, 0.6695627, 0.69194527, 2.23606798, 2.03163832, 4.80069441, 4.80069445, 4.80069449, 4.80069453, 4.80069441, 4.80069445, 4.80069449, 3.40774352, 34.6891632, 29.44137328, 27.91408781, 24.93766082, 0.82213163, 0.71658427, 0.8048753, 0.75284394, 1.39099471, 1.24808929, 1.29795787, 1.82045088, 2.55613309, 1.42491303, 1.41945261, 2.3225685, 0.93853308, 1.30654464 ]) assert_allclose(dE2, oracle, rtol=1.e-8) def test_cmc(): data = load_ciede2000_data() N = len(data) lab1 = np.zeros((N, 3)) lab1[:, 0] = data['L1'] lab1[:, 1] = data['a1'] lab1[:, 2] = data['b1'] lab2 = np.zeros((N, 3)) lab2[:, 0] = data['L2'] lab2[:, 1] = data['a2'] lab2[:, 2] = data['b2'] dE2 = deltaE_cmc(lab1, lab2) oracle = np.array([ 1.73873611, 2.49660844, 3.30494501, 0.85735576, 0.88332927, 0.97822692, 3.50480874, 2.87930032, 6.5783807, 6.57838075, 6.5783808, 6.57838086, 6.67492321, 6.67492326, 6.67492331, 4.66852997, 42.10875485, 39.45889064, 38.36005919, 33.93663807, 1.14400168, 1.00600419, 1.11302547, 1.05335328, 1.42822951, 1.2548143, 1.76838061, 2.02583367, 3.08695508, 1.74893533, 1.90095165, 1.70258148, 1.80317207, 2.44934417 ]) assert_allclose(dE2, oracle, rtol=1.e-8) def test_single_color_cie76(): lab1 = (0.5, 0.5, 0.5) lab2 = (0.4, 0.4, 0.4) deltaE_cie76(lab1, lab2) def test_single_color_ciede94(): lab1 = (0.5, 0.5, 0.5) lab2 = (0.4, 0.4, 0.4) deltaE_ciede94(lab1, lab2) def test_single_color_ciede2000(): lab1 = (0.5, 0.5, 0.5) lab2 = (0.4, 0.4, 0.4) deltaE_ciede2000(lab1, lab2) def test_single_color_cmc(): lab1 = (0.5, 0.5, 0.5) lab2 = (0.4, 0.4, 0.4) deltaE_cmc(lab1, lab2) if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/data/000077500000000000000000000000001223313777300164325ustar00rootroot00000000000000scikit-image-0.9.3/skimage/data/__init__.py000066400000000000000000000107611223313777300205500ustar00rootroot00000000000000"""Standard test images. For more images, see - http://sipi.usc.edu/database/database.php """ import os as _os from ..io import imread from skimage import data_dir __all__ = ['load', 'camera', 'lena', 'text', 'checkerboard', 'coins', 'moon', 'page', 'horse', 'clock', 'immunohistochemistry', 'chelsea', 'coffee'] def load(f): """Load an image file located in the data directory. Parameters ---------- f : string File name. Returns ------- img : ndarray Image loaded from skimage.data_dir. """ return imread(_os.path.join(data_dir, f)) def camera(): """Gray-level "camera" image. Often used for segmentation and denoising examples. """ return load("camera.png") def lena(): """Colour "Lena" image. The standard, yet sometimes controversial Lena test image was scanned from the November 1972 edition of Playboy magazine. From an image processing perspective, this image is useful because it contains smooth, textured, shaded as well as detail areas. """ return load("lena.png") def text(): """Gray-level "text" image used for corner detection. Notes ----- This image was downloaded from Wikipedia `__. No known copyright restrictions, released into the public domain. """ return load("text.png") def checkerboard(): """Checkerboard image. Checkerboards are often used in image calibration, since the corner-points are easy to locate. Because of the many parallel edges, they also visualise distortions particularly well. """ return load("chessboard_GRAY.png") def coins(): """Greek coins from Pompeii. This image shows several coins outlined against a gray background. It is especially useful in, e.g. segmentation tests, where individual objects need to be identified against a background. The background shares enough grey levels with the coins that a simple segmentation is not sufficient. Notes ----- This image was downloaded from the `Brooklyn Museum Collection `__. No known copyright restrictions. """ return load("coins.png") def moon(): """Surface of the moon. This low-contrast image of the surface of the moon is useful for illustrating histogram equalization and contrast stretching. """ return load("moon.png") def page(): """Scanned page. This image of printed text is useful for demonstrations requiring uneven background illumination. """ return load("page.png") def horse(): """Black and white silhouette of a horse. This image was downloaded from `openclipart ` Released into public domain and drawn and uploaded by Andreas Preuss (marauder). """ return load("horse.png") def clock(): """Motion blurred clock. This photograph of a wall clock was taken while moving the camera in an aproximately horizontal direction. It may be used to illustrate inverse filters and deconvolution. Released into the public domain by the photographer (Stefan van der Walt). """ return load("clock_motion.png") def immunohistochemistry(): """Immunohistochemical (IHC) staining with hematoxylin counterstaining. This picture shows colonic glands where the IHC expression of FHL2 protein is revealed with DAB. Hematoxylin counterstaining is applied to enhance the negative parts of the tissue. This image was acquired at the Center for Microscopy And Molecular Imaging (CMMI). No known copyright restrictions. """ return load("ihc.png") def chelsea(): """Chelsea the cat. An example with texture, prominent edges in horizontal and diagonal directions, as well as features of differing scales. Notes ----- No copyright restrictions. CC0 by the photographer (Stefan van der Walt). """ return load("chelsea.png") def coffee(): """Coffee cup. This photograph is courtesy of Pikolo Espresso Bar. It contains several elliptical shapes as well as varying texture (smooth porcelain to course wood grain). Notes ----- No copyright restrictions. CC0 by the photographer (Rachel Michetti). """ return load("coffee.png") scikit-image-0.9.3/skimage/data/brick.png000066400000000000000000005237651223313777300202540ustar00rootroot00000000000000PNG  IHDR& pHYs  iTXtXML:com.adobe.xmp 1 1 1 #a@IDATx$$Y%fU-Y5_ob =U]nfonL fz#Mg$Yuo_"9}Kt6YZ8C?˳g>G<>| ɿ]g}.ٜSv"<ˬh9[y_Q/oՙNY&6>*=~>ﷹ>²C#۷uۊ=۩}ۼ_ڗžMǑ<9=z mogRgnZcߋ\δ.5s|k6OվY:}*]GTa?o߇ڽ$=Τ٪l9aL˚?1zW鹆bRKǞIۄn?=&|#; !؄vuM.36}}B~$I6%eN_ߓ?^X&K.=.guVձm֞{~-oEZn628κ GWK\slY$/yHt$)j/keQgZeg%]fJuɞy,s-8=$]am-+)O)-=?xKզsVpt.{W/9$-C8ꬓl M)iɒG k7<#*͆[Vrq芳YED-KjhCCkH9;|퓳q$vdLukCY1g!R*q^C2cY#93dya[}ϧ,wc{$en]ZN=+Eȓ=tm$xۿgKSʭOKG-d5||.wٜ;Ry#Zs n88u ͞|.tX9if#:A$;"}v~+9ymxۻCoqHK7{.\%$QEk8ιNdӥiԾCț1BiY괖9vGgϪ\lYh~?DxRe8.! !#pَd T.c9/[;r ކ<^iSL6[mMa=g^Ǐ9q{k-W7i+.ɒh铏j۞gs_eKlں}lr%kr|3XT0MېfudF[rB0{֕>1C-/sH$}tcnC9}j|Es )`K*oe^i6y/X5޹ܭZI6}HJ/Ò yJ߾]ll, C}t}} #keŶ^l.QN]]˚o|1Fo\8NG-6oRa]$u#k?6ٺ属eYRy,B|I\>m|;[qX5xG~bG2v@@PeG>]mZ,—eU( >h&t)s.\ʴތ>4j!TLD5W!b^'gaγZ])>Cth|Y@ܗ$0@=+kl>iK9Bq{]L \q䛐=)ueߪ<B{[7zvK 1t髬|w'mUqTGU_*t7؏ 69ֺzKƳ} IC19Aqz٧ؙ|BѷbkHLd!d?m_oK''Fx%a_d"]!2-au,ol,2,\nKVgZ @F݇Ԛl+8?^B[/s ?>3XY.>tPg:=qXY.۹c$jW9Xn@u[pQ]R= x-ɏ/e`A_ *4x)iHKv_bu+-PCA|8,Tw.g|9n 44t9ۢ=m?T#3I۴zV'Lڮt2-AMGDXf{ȗZX֏ \0܇;BG89[V.2)R.!%rE:A1R?'rO܎uͲz8wUmGBU?EĽ{.+GeaQ.MʻpLIU\De%`~r4GuQ>VGLx4]-k,utXsDv3o|<|V\RJ/$U^P欉JqWxCKA@<%+$ Nҹq) I"TQ䳓 Al/ER|-4[R&۟emM&4kB{>Dy[ث'X'p,N/@[qwB> oRz?Ao#6b˞gj xp6148e<<Ƕ5+b&E{+|=sġfj#d[w6Z]tbխTxsP7sy?c?_F~>lxq%0ɾ9F@>,uqdW|rЀϢ]Qڋz>TBUp .t"ym%Epl۸Wzr$,/ny[u%=3 Y>U"PG-k*3z%]WN?uG׬t;| ;Rba> v6|dt?o?c<|+UH^hlHͫď3: .|Or9|!Sǔ|oY߲gŀ Yrd)t(Oa=%Xf nR4DZkwVx50Ndr.WvVȮyu+4Kv]5NSS#7 Ƭ=sI[]dT|WW!ano3|8/e 9qP,_*sxkotBR<}|B@YpekWw6< 6TC^gJbSB{?)Q  )_WrY]Έ鼪cp*c#+_hn aYdZ$%X_hկ:/r\V|ܑ}CladOf\iG!3(<0w&E9N?N0ɏ7t=n|k+$Y]p*quم#Dv H+/ꚪ!A㢭 bA ܏I(},9/!Q%*(\C=$0 畂P<%rQu eiJ ܒ2*gO[C@s mQ3 6!|g*b*^e%o0Do瞆B G,T*=ZJׄ?ס)6 FqJa?URi⁞<_yo'"-tx[ DSY˶o]'DƋL'4W7 @"#!m@#TNd4e+{_H:T:jOQvϫuaxߐ knu*7T~cQru̐,gL/䂥tiʪ+ s+fҹr1n0\a{#:۾\s,./F{y:s?R˚,"J`|L$>W\l̀ PYÞCG O:mC ="kI,{PU$*XGYeo:Gg &sNaHa X;R$ߒTcҍ >lis\BuCS_-CUo?sH1ljCTE*lC Bh7@W=blPQuH=+%½g-G͚̀Pm'zXktHN`4!hCoQbX>>%ovًt#TP3FGPξ[Ʒз .M}U~HT<*Hd!"[ \g+r>]E# }_d&sA ϕ>E!T?>OT, G &81iV J]z]Y|~.+|}6Sڶ:1+j};y\ctL/ȐT$JߊđEJmGc Q""Mt H q N{q$W"*69M iE>KBxPHL,[Asjڥ8 I󜎼N6|jV:p߱S8YpK۵zpFdtlul"$?{9[v95v&ثǟ^Eˬo(m2x\kr ҈RPKO}$DP1f)pqyNa=߅D?GOkԧ#n 4~by `u(iA6F Rbv//h0&"%Q#q<=uN~)'8שfȁ=Z+Ac.SH5L`[E'5%aY?$M{.&)[|s1AN$/??ZBPrpeQ93%( ,(4g@"+oB ^conoGpW _FD*-ﳛZ?C꭫X&Q* zªbth殡a#hJEHscH|R<b`I6(BpJ$8:(=[犤B[~!͍G XSzu+@VbAtomteL|`Q "B/d0D{#yV߿E&deʭ|^"y8Q p$mQ/\7ƣE:2úwWcz Q TMFPe: ˋgSFnlYwv!pMyJje͒F$aͷ<&s$bj6S*b 򍓦1Zt*ز}&,!W4qȃ]TLѹѾ_ZJS`9XSCG!o (|/^S$Eyn%C@YS oB~Wч|e4Z] 1TG:CM8J+r!n4XKIA[H5Zۺg{czGg"c~vE Ӱv77x|eu<|Cu8k \*>Yns"vTl *X<4+;fja<ʞζ?d?S92⒓]JX=eAXRr8[j &C1a,xŮNEMgC1]½9:7_8":΢J|V ,Aʤa?&ScKat2~rIHȤ::&(ƅ ON k7b2cn~󃮙<#Q-i5GN~YQgB\6}bOE"hX |lO 3˺&P9rMܲ7?qL0dYR{y@]MkcW<3>FB+ru1~QI+ZLR NYr>. +lOD}fvAє*jgie?+d_<ҞCKl`h*Fg*J:PzjQ0kޮk ˂KR#{x%E`͙Os_VԺ!)yh C#3OeSAQ*hz_EnqJb2>o‰d~QYWf7Ndqĭ_K6(a>|5%g 2$S18n@9ةNE>CѼ]@Px<µxU(Zd@:B8\ 5@Tє,R4*&ɅÔ!g_TtOFl}JvZ(bqy{W~LXTWďe)aQX_W:a*L\7\q lNO3_ (,i#G֒ kuMFLz0 I8 0|v p͉;.mID jĬ|^mQs0`t )zD@., +i(@zzU>!@5]҄#=E3Ioe@N-e8Ep\/;G B"8{>ܯ*lo6&V+!:-:uvbyH{(oRsA~",{gy4+;G8`۱zU*a[cc˳b6tkZmݿD,/p ##d Y,wg-s8d(VX=W7jnd#8GېnMٌP|0'gv>[o- IҋG˫K bX׾$ ""'9v "mGbv#tuUtG8!yC('VN-]QVH#kc;# ~';^#.Z7藃/%1C~9`&&U0\0LZ]_qTTߖ((%ypa#֝O Z=;71ASHt;) 0x$9dwS:COO.P4_@."V!Vd:qX?/!Uxr7oOeU S0*>9td'ܪv9A5o#)bPkʺ#pR)*V|@x >6[gH#<|*? `Wᒗ mnz@'j{rxsvZp @ hћWE5Rj ++[&iSYU @Vwqt,/DIxA}Ȱ6RE [9aEDDNllh3T8y#'F 9D%VMg-b@ߢ}.ϮJ~py\ կM_[&Qݡ0tyyb;zh}Q~9n+jnØSJ䭲O?Cهw?OOŌY.#_>8AhR`nX\X8Hvv1ƓNä+IN[zX}NYJEQ,.`>gA<lD:L4B/\" 9Ś.-*Ն3=|T[JݲV<͍j5D+ Z-c3\tЙ*lkyzKEv/\U-B[s :u<*vWQJ*zpJ1EB$M9mY1m| Kav8P֢`˯hΞʇ*k(ziQ%$ sg['Bp1dI80L`P h=X WythSSq,CdY 7S|&k=l\4tJ([ڏ˵>8SȴXܭ(]x2+i QO!~u\sE5 XIWQMrTŚo `\ \Iu5MctVo`['iͦq=q BV,NG@Gl8U_'iɵׯvh8gB6o;2@jok z8(dܬ9::XƵŬa+gNXF)68W3Fta\iq$h5%NqFR zE*PMv))rhth)ᣴSpݳ3ڣcpEtee+Y ݡZ,bO\MYIZRog}~hH9&Uk#o=SqcaLƢ}!;\eA8w"ݮa%D^A`#$>Euړa@8nr^0lnnU|dmqN5} cbwu08e">*~hBa5㾯a@(Alo~^9LU#oشaF^߆q9g6;%<'2#RY _ysB`JnhPfh@߉b X՜zXsY7eF+j!5eNO7oƄ?qQ}9}Ł_S/R}1-vJ4qݵ`u^ !n`;maJ!UV/EAaNدiPS/4f6a!2饓qp^٪2АʒHq=juc#md Dy1#Ri;01G^v9' ]qEs.P[Y{܄.A<_|Q]bWvH\wSij=;0h0JTN]Ki~,P,Si;t%iC\D3Unm-cXJ \{dzN nb;ϧ!izeQ{ 0O2׹Q7I@) \(֟I8bM˽ƶfI*$~>sU$LS2cͫL0%4gC|4Il|L"UJ̍Ux|<9Ay=irVek4Pccytgx ꂿq%$:X3R0HZ>W_ 6dړٸ5[ޔ[e+j,CT!r27N+OՔhz&nwa;3}ML !QvJ;!}\` HH9}] D $IV_N܋A2mCvt.\=SoPUqZO`Gt^> 7OKG85~6"pj =ֺd{Yb?RsO+{R<0vk5GWsZ~-[|=uChX|6ϣ"'Bb_!QQ|Cb݃O7%L#"'^&ENkyif7zCaC2^{>IZC(Bʧgڢ>appu7ڽ<\-subβ? ^zL J'AB!dbkGUCQJ~$@${AnaM0*ՠG<^j9WC5Y>%ix>f tsk!b"[G'H TJ8`Jp+, 1!.BT|g?%|׭JJr͏e\g?5:z+RϷo+AXǟEs,<N޴Y?7ui,gXK6" % W= =d(*xp/N!)iȓ,1͖X96JL!|1*+$]@ݿ&E~by^_AgT捒d6E*CnMqsŤ.{{K|+ڣn% *E̛.g^~vvWVjU PkyGL4)K=#efV:-9c٤}5"\%)gUj)Gum%hƔ_t$3<nC LXװ !NG=_T$ajChۥL4@RomJZ-:Z[>O$Rv cr.»kP"(6&iN.STw;"FݨHA {¦E  Z"6rdΐi* zH#GwF Լv;v1v~BmN)zA畴DbciRH<"w|˞؈reQksߵq|yjU8iucYWֈȰ ӆDmh(̪RfJn./X \r/^s30GnaM6,H]Ҥ/BLòcҮ9RjS?Jb&]v:\9)9f.K WaJPd&9¿ Q 廦-ox VP;2idDʹa4] ģ#*%bANJWq5_ljF>6U<)&;b Y]!@/)v,<!S;]0v> ;x?367"pL0 "Gp-4.R܁G-S0gcR@.n呺cWAъ'BHrͿ^xz&?U)z %H(86A$ΊIOB0[UQ_-%gGR AaЍn"ybS lUv}W#%|7j`ee O~8HO5}8TKl2 t5FQcش=DmWc}_GC qkM NA+Ii1m bѱiXr8u5BOǮ Og(v NStzG*ߟ*#v-~Ms++Gzc#G3=Q0rEy-|tPJM^8;(n EQS&=ٹCϐ:FOu敖Vtusچ.iH1AVDKǙ\zVd%mgLVkg+ݸ,2ue.PD3T+{PTRc؃jGۺ `B*g$:\{#xĝXdOnH_:Jz|e(.]tlGNYG#t Wt3B_E!۠_4L =# m7Ӧ"Jm>ԍc*̐it-`Vilx3 F3oh.L˗?.ϧ_b4s'8& G0͹@f6B\]wy38@$TbG 9!8ɱ!fz8 OHתIO$K\1cl>Rz|JDi@+# T6P~ܨF!j=I P=[:VQ/opװc"ղp.C_4?s]fSPAP4jm";D_4cr꾻m67&My')rfP!X<e:}Q(:q֍}:IU5KktjNjlN{ڌVKosPU\:|a[hF(^|fk$3^>δ dLٖ8'_%A&#AZm֌C,K֮GTK@#fR*וݻKj/M0Q3Sf>TJ}_GaT6XU._l 5sRgeDN@IDATW;|# QJ]cYV*?2BrxNjݻ$ cd~_4.Db{ LZ3cO٦CRo5Um7ul͍ieїx'Br;q%/`j|˯ʑQOɯAPV0kJ?ƏXL@`ŠިWQg"[Z'PLlԓ&Q` gi,kydP2:gg˵~`ub_+8NcCq/WF.̔w|2(1u[Ubfk23#nh4J#=:em\w!L1.]!!W\@>":k]Aq"QJһq:RuζEUty=,&$X,ř1dڰ2Mj<,, >9Ԋo vGՍ"K$uL:[ tǨq+l t# ݯ;9Y6+/2I1i=>x ̭?[ülE`Yn+8я#\W[nTP1&?^ōh tXF j;Lti%Ă2+V" j4LdJ(_~鰇eYFOљ  ބI9}R5 jcᕸ4qvwi˕`F0!g,$ iY@e#=C}yej0;SqX>gqn( LLq? 6v8U`=8ԑ  k'4")ƻ DMt_uXd3%JKߙ]-S-C`O[p(/+h湽YU:c'imX,?nsLaNJQȪ+J2N"hI 0 x(Ģ\%pG{UGgq'.7N2uS<9(PnubMh9#֨؏s*j=ؠhR9:wZCA]a#Fy \1p ΄tĞd1"ziH,h+lII[|f:/7s٧z ߂ I"oYM:UjYwXv۬hx|'~RL1G`vDA[dLZц}?tF { :XN\7ڿTs'ZaaluZ<_0vt&^)>R. d\/:F5Sz0F9Yƺ[KS-X9@t)֚m' DI^o &*z@&T^*$׃ex=+ 5>B%&"gڑ%N4?"ǎzDTYwjj, %'c6$I<:FXts?QO:$bz˩Vb'}Cd1+m;-cowGudɤb@\aWozFxۋb쓱w=痉@]" nm_UhYTtd{q=M=L#ѵ"H!qΟr#lI!MKc(ح_\Bi| oZ4C@X7 3{U8! 4c^Fk|A)5x)i";7hޝkyk613ƎN,t΍4돈eRȵ.{sc[ip;`ľA:T/&Y7nu}q ]S vR-IkY3+IrqKؒ0BbBa8`Q*x4{Iy JB ό{&vir^-+b3cvs_^BjCA,mh/֫ ~ Hm|4ffAHoėI)Ut.yC1+MDѪH:wdI.B1q9\zMOH?0\d;(VTM\(&&KoSSGUM>FD9\OMan [ـ 'ZPql̞j0PcB)N!Y EN>H{/yb9иG-j_ &xĸz{C׸ZWЀ+H/>IJ%? D א{p4wyp1iHaT\@H2GQ[.-s!leiR4)(oٝbl7`EÃ!Z̓GGJ#q0eٴ^d(5ͭr` sV;2bdMP(uRmmhKw5n-#2FV!.K}yJ,Y@2K^aG]7h3 ^<jCr #8?Q);ooHZԺx+̄fdchveK-[[xJLu!@qz\@Gv$|y 7mKG4Z8yۊl*~&Wf$3O[a懛a)2錑t*Mqrȕ!ELӖ(rPFvb<:l Wq+dd2Fb(al"?lD# њ@0^,48GҠŮrZbP.OЅcQ5,RoYZS:}ơ$ӭ$*j̈E~LMD;GØ4]!lĎyFtf&E!&nY 7#ud|5 gl;7zŵ*i%8ؿS/yy놲~;C28zm n"z(9N׫ ’>A@znOyk1uġDj O b,w:^&i-Ǒf* !\#yDW*zi0ڌ}s )N헸G!3mjG( 5 MO `DS,M4^uqRtZwX`{w @Ym Ґ Za}[>SdDYV,.#E rӘ)ּ#-`[*sԐ{`mKLr6z99ruf%DUJ3]'8LAJ(;>tyUlwYZM̉Fx.=/kOMPRo,GzШ{Q] $"]V'["!ꀲdnO (j|oFK;N E"NnpD(S !*jh5E3" Whđwd4W~i_5Q=f_8IMvM08͆<~y{ƮAsfܣǞ,w&kyl9v|S>ڍuD$VX]0E>c Dr+Eɴ ЈUWvjpiJ}H@)Ҕ\R+4pXݹV9DB|J$6=O[ pℤ;[rd"",OӦ+uBfU%cUH ^럖[LZY% dF{)LW:OL~ !4tH؊^6aC^7@%75skesUTOdrK18!_u7row$/kN!/h4R;Yv,IQۏ""1B7[vLY/JlH S@iG`2 J ff}+> :BP':=u/W\+nU4py34|p$`ʐY23? OAF`棣4K$)RK?u,xu)dqݾQg}5ȻF0w\?()C&~1mTaRRp1iWT R4.h>CI<"Tw05@U̓^=BhrSH1/m0Sj_S0$H"UI0fľN!x?VW^u;u1X[]c aa^ nSKT~2gEY> 5[ui]AHaOBٿtgcDvlT%0= kPi!e.gd"Q;Z?ŧm# n YՓV8-.hIlYf#`{*}J#LO#z$i'I4s@W{1KX$͖/۾g\nDmfJ kI G{MˊU]ˡ91uZ  cп#=Pgp_4]=㹱7IpԲ>3[o?Ã\jN,[]b,G^CM -$>YᆗHdaIЍKND1-U8F& :]C}cSC['BHkb=EJCR-^/t'irZ5_ä*m]}s%,KX`CP T<1cA6 G9Yhӈ;F58 !/vc7b n%9v{7;EG)Eif;0HAL,^%Bclp 0qk0ڧaMTÈdB̎pсGz wY-ȚW|%f--uC<SOb6aT~\ƯzcوR@3J2\76BopQK)4Rz/CWC_A곰k5 IЀ\,Z ۫zI` =doHj%ZI7Gw0;R2*^6͋>:du Cht<~]7bD(*Ҍ#zI>(X9dLP4סTSxH$0i7T:D\\#LX|,>V+wJΞr}N: 6@XrM K]%P8܂p*BW !^سq4o?7dwXCE@\/ _.D y G#ڿE\O'X+ HomriFJ64D~W+L`}N҇)n3ɝ3zhċOre0l`9(DAnD>-k*zShi7F+0%m2I9e)>d1Otj3{:+/&biSR<iO˚ 1#gʣ{ӔdR|9= #Px[q> ?_FB6+]6*,z۷td7;ET+#7Xԙr% =x d: @{lRELx(0AƏU[I~T;m@`& mhJw;*HLP4 (X,I3S!J7I^Ӷ򡋆@VilH"xǧRkn.uE^pȌͰ$5w4ƌʋM~%A<$H+Z[1uWg&VQfqu(80ŐsF:0.<)cAʢ\MZ;4כ^PyCɢ?-KKH95|CCNGf͐^Ar[gjjEn.`=T̠>r9dɩg($0Z9"}Sl!{LϬ њG(NJfJc4(t76I#őB~?ȂA5T&4睓[% ,Ef4]x{nx8đʘ&8wS87^./"/T{jʤQj),˒0.xZ$xVϝ ;C zHЉZř8|b`Fa7NFŽ_iȁ=E8m0~-w.'cRV$qο!g_\ҝϣ,Cz(x{A.d$cv&EDxZaSuTP:(,ƢS1}£f7(q}vk2 FϤO''sLt)G\b@(_&XأQ7F>"Q6rJ47QoK3 4 iXr ^#V5D FS GØm/Uc`_=P5dTyowmÀsE8#+L$ޤmSQJd(3K5J%YH?G^5VLwؿB`~ժB@OEVvDꔨXD8'e>v:gY[/C - 6+nT)|f) * lX&D:L"Raq6WOJ9)&byjRw3)HB Nژ_;MW3@#)]B=T8n<ūe fgLb%ܵ[ƌ  y4o`Nļ w}nj,wmLj 7Y[¨v2P}+Q\yll}J{&rѼQmW۴^׎77A.uf.M=$2^ʾC~7(^A6QbnP CrQ?-g=̼jKw 9 (ہW}?=d;xϖ C0^pEsM_5Di =u\m[Ep7qE7$[MgP D[6nPJ[B% `aPc~3l݌i$N}4(UtY)=d[Icԑ71WupL9f#$,!n00L=ssu]u|虬Xm a+dCg]&@WL@"$8ms6EBFC\2z;+Z7HyŀwGd89~-al/U0?vW~b $^YM3mqC,@.\WE fpeQT hݪ.=<9vD#r֨Øa[g&13fShB/IPvy(Bz",`K J$,H^ 鰔b؞?j-]uGN!:$ HR.3]!j3 mHm]f4f8/q؟OwДAIJv|/)hm^ݤ.҇]<}臆:zPc_g76yLxNpDmyNwM$>cejh%XS7rDtr5y&+yB|sWXLDɊ Yh!8m-0Q%lֳߎX]p=k"#sRT5+dY,8N5~uMӛo߆6E+쐫pu4LbHAG%gzu-:Vl~UHݫ]jP ڽ1EXT+U"[G }P;{UOm_\yP=Ayݗ$$)8 @[H?PNiF/c:>"ޖ5--b&jJ1c+8!fX{:mΘ~S,˜+`ɗJM?PDb/t gߌ|<8Ǣ\H?q<,VVYq!AepJؑU喛VZΜiq5>1Y400׳QDye0A^ViW-79R0Td.PWH|Ӯ{Z_GU I>FuaX ZV_>:X|;2SjmV׏^R nny 51esX誈p B} mlMuڃ&fy݇Jyrtu)ЪKDDH&n 5˛4 bG&" OrH?#ƙXyG F‹!^:5F`ETfkE=}^0㩽{ (%ֹI`Twi8eЮSh6~ R'4dE,nṰ܉*DJݞԷ<]]v=21'ٯb6Xt\Z_4kbő>9?Y2 SLL̚ܛ\ :p3[R(C}ۑ6 w{[טCVU{/sOrb7b%k*:8ۉ@&WQ1HG6WEE$4&>l%4`ھ:( _w?qvKO \"v//dkMQ˚֌~!U~˶RI W` T>A.8#o#6L SaznuWpƒmc ^Vޥ%S6)t)vpwLY9^_?{PѾYezHŧLD*{lBr6YtȸCN)MCmPg3sG:}J02iwTAKpe<}z,Х@5.-v `BLP-D+l=CEˆu! FiO/euMX5N Gmn℁a+ 'eQ:=*o3{,~q1<+2|!{2hп^cZnlor?~A.Vl:}'M Q%_|Sk.*z4-7>Cnr^/sz.jK{?^~ӡrb<QRs A|_TvoSPEfTT޵)zhcE l@'v pTE i;p]GoM Oj"VrTL O=l1>?C z~Fͪ29ЪaWI,5@ZZF{GLI |Ȩt󸌡D2M6s?vkGA7^fHk߹= J '(ebLӥۅvBN~0i  Xfש}cQڷdrÔaiK `ɭs @B$ERYv: #RV4,bPb}׾̙s}Fc@(^qs}"wUA DQl[C9Yr Y@|CuNwC#l` Fw]@apcC9iY-v.m^hd5\L\- `Sr^S@A*X-,Y>Tkc9ǿ @ePZ/q}ef;g}T"s&l-qrb}$4r@&<6,n~mZ,8"|>Z)R~73ascrqJo4k1f'PùM[32d8-$:Qs7=+Lz힭?I A7[+bbq?fOki)ZߩF>͠LN(4×1̷kt8RQQp.xdc[Z0#l=l ,+F_Rǹb&Ju-s̩ɰ4pα6k'Bj ֲIz< 1Xtj7/߉L`I{bn6 >XWa`c*˜|CeÌtCI+3;E_Bt4uS_6\K6H|  >GqєOGaGM<oK4"IS)RG-)7Y],Z >Gp,]r"m 0 * N\a뚑p[JP{?TNƻseJ[9 snWQb峡.@VN228ƞy}?[V-VDjCdcף Q]Qr] iD6 \S4N!}~$=d8hj|o/L?5kد{p5_. o|&mUr_d6SێlA|D l^'diIӳ&V=qb9w+RrP@&?LjRpKP兊HS W8wXAbUu-+n gr5@ 02gQV Trpae~Q";6 /v?@B1|PgzR1"86ԅkxx|}{fΈDViN..5oDX/:yr3PJ-+ցOE[bGtp쮮qn <=f2=n;"iִvn( ÐLwnUq!6Ig+|/hDeBgc"@*DFٞ6ej0S[f|\pFYn!w:oj\.6~עQ&;I-1E#_nfPߪՙi!4FZQ]v:Ljp}V7J!*@/엛76{zQ*<s[kuH8\9{1C:lv >_OTK3ԓj m^s0H# >kp2PhG%(]lajך,$P*Vgr)0tp`9^B: >sQMGgb]]X >nc18V@L̖jLƹ>Pj@@|Ta'cuT%WW'Pf4G*Aa*r:z+&MyA?"z1$nTs{^¿x<*NKcඅeVNc8g8rHc^=g|-> =i~}LKog˥3" X{ JbA\)6x^,\^f0Ǝ8`tB· Eq^wui\"~IzKr|&yw) Ų6KJ Bd\qՂq Ġu6"dI}h^PI9/vw *&2x]XbLF7[;:lWuM3^%04s/0ALx*GT#wH4],5G9h.ZDX@iԥ1qd9J!VҐ,|# ^~T|>4.w#Qxf Ӓc+]+oL3ϓs_$\̀BQaE0FڿbMLx P UosM39dZfs'm%8*7fUfo'?{ao 2v[/i(\%ݢ'_V ~}rC}0cx{9IdRrkcsZ ߦ~V]:] ny :=/8ŮP'JjׇO(Š:=#.Vumt,ykrIZu+#6}O1,IOa!?R PQ~ :+30Vö†bHX'&b#tDAG`nMh"C jVYUc0DgPQ=C ~C4Q 7̂Tu%j ǻ  'g5﬍AE_ } e3?evLrhUa5S jzpӠlYԉATrkHeTI^U&/uō% F~}-?u!gB &KKCoTSׅi6ei=y0 saqA"%(!7Fe٠`RӖ%6PFD;LEbk) bD#h 3zH1ز%zPfHʫ"iН] Xc -Yd`g`" ]=KMA/We,Y_/I!)" E1ō^jK<`\z f 8F߹eM<{b×׸>\֥%sCZ@Ŋʠ FB*q!|>s8Nj>OLDoo(_ZV =l݋΂Ϝ um aΛZݷJKPh<7rnK1WlPf񣤔ۏcW,;Kϡ8Àѣo[IG [`M yFo5K1 3o2Ώ E PNǣ>ۏ4Ls(i5XgֺZzJjׂ\qFSO3"pծ.  (B31#ZxQ+-Q&<*/aLp: _5;Sm7TxsNuh2 a2i?3 ~eߺz@6Z0:̏e5m}7H9h#$Ыy#igO[n3!1/ku0`^'b޾)=?XUfRҾl.6DXSn*&zGl#$Jgvc9_}Bйs)Rd Fz;vsgJј(CHGfzlaSر&'A璕ҢkAK5_:lz^t>7 J#qjfqsn_ڧm({8O/?Mq i[\ ChZbo DQ ÿ{%'Pd@J0IxQvx%$^,AV@݁|DsuƋ4"bx6s<˝fv=@&r6*cSt Z M:Ad*ݝ0}ɔd4û5f Z;ߎ!|׷tjb'X;Ix6(^  n(I|0|M*r_tѝ6,Fm8%bq uzty 1GgT`Pg翆O?~xWA87r޺:ipV;FBk*i'ܑWaLQ9\At,r/8UH.N:8e.GLZBb4\0A{Vl'vp-|^tp 89q<(#$Ž 7y\w{QL}8]55ʙ!9ڀ3RQvr!ce .[twvHK1Bf⥽[||Zw|gd2IT FzǶYpAГhz9N)54DR3Ҭ2ZN5,\' OW漞箶[b\_1`3|؅̫ZH(.{0b }Mez3JfSHA9_WhУ.aФmpq{#I`Eo ⰑU+zx)+e'f6LRh7_u8t%xA%q[>>ɠ" db3U3d"&&o]ۼkD?to0w4BS0g-(~b F۵'Du8ʸD?,tI_Ui#h 7MĎ^(/HVǰc@MԚ{ZU;j[{qt+zӗZU#g.N6Q)z _sf2I2el_0"Ӈ  bdU%*ϸn7>VB 7cJjQsbaUIvY9pN49k`yaTa@6UBN14Y!Yg~%!k(\¶ywY?@jϣ`,Jh95=~cU+b 2~qRB!j?9z}iܓ4m)ݑUYiL Q!|tb_?"b;J$0JthƳh[l a"'(3ZV\>OK,zyrIEj1! 2`DHuЕc&{?U "% EuyͱW19F&|-}G/< Ss9B=P&mBwC^J.`md0Z(|s,lV*C7,vEI<Q)ArIy;t@LASǫ,[{ɀjX$ d %~$yeWUϐE%UP䅻{8Ѯ/{mAJDKf oFBbL$2l4Z,Al{$H%ӃLmO9NNO 3.r+4B<ѭȥ] _xE&WLqkl}649Xp8".#^'&ju>"[oyNJVa^%M'j:}ᒫ^ȋׯN2Pt{u @'ݷ6@:ꙫEGP`h Ոѧ@w`Wlޞ}ٗf"7V.wBk"iװM!+pzLN|ڦ@ dXD@Jc9¤R`0= ͥnv{S^ѹu3 xђy7z7C>CgZHRN^jHEqC{]SlXs3?.s硳Џ#XL`JSׇȧJUJ}`"MݦEc|c A3 YZEoyD>T|k+{!ڙa+ 1UDyÒ<<<A6"Ȭ/I%>Эډoi勱s#ۣo oB(xא !@aҽ(iO6=E-e4)-У @ Xs?ah1zT0_PZG8@jzrX@Y9;W~8ΓZ~&¢es\.2q71V}=ę`m@+Um_}c22"V OBmpL7ٗ#"MNl*n_Kb!jkkI#w+b|˄Ih8zf@JU= >L>C}LCxИ?곥Al吮fЫC ,p[7BjP 673BJ9uwn ;Kf6vtAiƢ_R!"?M5Y!j &̳:tI_lXD1ޓ?v5 4K@CzCvþlU&5xVV @_^D鯉~tLw)KFY$YxuAECqki%y@-ԘK;9ױNՇpQacsBpjÁڑ ܤ,7TIl|鉅?E4 |KT -$ƛLSf'_-G-~ 4Wv6`wh[9z)1i A􆺐ƚ0e23x) +@'3Ƥ nI.Yb}gP:&bڼkbnzlR۽d.mym5"b@ŷV9\|f&pq2f{P^÷mMH" Ryw֮ K2{lxMTH6 \2Ƭ!~ pË $K*B6Je}x0zb;aƤ.ocHh(±6E!e\HDkH3f24cК!haGU<"LKDnw:N.w? W EN'm&%cM^5IJ=BkSM5FXꆸta"um&֜D7.iVS 4t ΅/T0q bF"Y覧v|݌=OإGgK~;RmE;ǤD!$9|`A &.^EYT̫{`K0灆}pt;@kDC%}!-H9QM#3$7GK5$?1׾>҈WR'lʅ fk2ZOb6{_ mj Id*lhD)'X*hRb(sxfQgφ㮹ڠ54A-qܸq:y{j}6tKnxHҌm2\v h=…@LQa=G` (T/UKc]ʬUvvg b9:~y9!3;?СPWt,)?a-}΅8Bhi8*0`[#CaG٢7gJ5w%jD%,g٨a]Y~]/:ӣ˃i+_o?-l!eDW.RyG243Tg{jy{^IL>lFe3¬Q] %j[M(pD4,f+$u6RkԚ!=udOY!~r&_.+>ll"GV{i<[݅H8줗dzT玓wa@0h*+V܍Tn|s;ºk=͋PD[$]u%dv* jxUrQֽ]]]A^4*J8TR#bBy8tyxb$X>5BPWV-YSvpRK65ʬ,uWI?]$x4 x5[:QS)P\Ўx3+ ,u饖,sehPD2kX]RG@"lKqi3*2K[Uы]dhn>CÆ}1pT^=l.-Th=3Wc5IfWPE@`_$ȃGNp}0A <cu5%crMD[JQOh%;!\S kEI~ȍN<S,4m ++*q܁pĽ;]xwGEwIS]ی-젵͘_ÿ1p:ZȋSsuX$M++M]{ฬ_QS-zcr'7B!̮FA?Dn#HA˳"?{`W&~'C 4ٛ¡&xCyBi6*`0ep *RxU]ܚZǫj)DAjd\T"[uA\!tjGp-@}lkf/i<, Gf'2G6gD^P~膤K=P^8 {2UOȈ( &,fɻlEQx\ CqU+QZxym}dbInto2Hb˵fLgUϖ$u_M.=QN%yI6T >WB+* K_ک={W|3Nu;v~] T_hDMh'NQeRƦuv_:6C"^*gP\8~*ٞTrS 4ݭqXl~*0"xBvv[oy ABOx=mXNA&i}Dg))Ƀz`ԕh &(ce}V*a3KrjhӇZq6g>oF]+jnYը]>wZZ/ *6Θ֒ ,t5apmv7YF$\oN̖FQ"lz=ZCuS+灎Y"r}1^'Ѧu^->#|f#BDl !"e80tw=6j$<(V-l0 :_4fvح7h =5Q `M%F@!@3m,[eUhKY/k) x1H8uF [.OFrLW-Æ!/xx$/F4Q*ТoU MpHP3p >_UED8x]hBe4;}2A :!? U-&Qgu ɠ1]xJȹ@0haP^﫡5XpN@!¸y$ZY>q7oBReSt6!9 r8( v?>#IrJ- ?kL V_gLwe׮mN&R%3B}2AFgQ"h--W̻@10TAik] .O?7∯֒hغwPIYth "-yJsBYIUMZV ~a[~rg 5E͠0 Y;!;J ]Bu+mK`JZf@r!ɦ @ $!L8Ujy qP|В$ܷ/f2[#+`b_0tZ9o㨤p-jC5_wx>Pd0H<_Z9ઢ9Rґj2WI K+LwU]`G.bBg#f]#f@Tguq?\ap44ߚMhH ڇwK%Х@|%? ?5]dAbZBzRMqiɾ=qā _l$MqL]DRRgHHm zStJ`F(<l;O-qGn%DXwB#&qVpT"z+A[j ލ_Y5 UܙsTR:(:EL3MkcR|`;vH<2kfp*Af^m͍X}L~GKz=RZxѲW>jD_â\[OT\\xh=9 x -o;*zȭ@,p%RJo`٭_~낑d,RSB_0` _?kPuKˏHzćY״;_T*MZf{]:?=>{eV_Y,(RpQW1Eu`r͢Ãқە]PmF^ !vk|NlIsٳ\? <@ mC̼%#˨0% J7 Iݼ˟5QiLN7B|R.1r~ߜ3{S&e%Ez`Nb y -a?^kV 2c,\ZWU r6 R *|ӓY^\"r VTm>]_ R+D$Q"ӎ s@ieR@M23闊 e+ 굯ϋ!9=[`e},,85GΟiᅬ8ͅƗ&ւ!sI9Bhub(3dDu&zI'^-R-i8 t}f{ݩ|1V\G[#$LwROЭOBYODf벛%zDKHDI01VE߁TgI#6H̅g3%]_:{.ί0a l{,-U^ꠙ!II@] ,.)aSM)%4s~B%Sh2 ,r)ُ֫uN̓۽*`}M}PSpj$<*2/-c1UꃭcR G͋Hx"eLsxֵkL 'Q%JW/u; `9Ҍ,}QjbedSE#sfWTIh M[Z7a T)ܶ ,rRJՀDja%Eqe:%fش"ij5?CDn4^>Go0TABr2TLdm[ݷ[x36L xcD.:p6{yVk*UсR |M1 .Z$ v(6; *pGALs)]OP58 CwcpԃOa;*aQ̬zt#XKqM$vV|MHKctӍx!xL'Iap}92Zzj'A"-ӄ.0GV <ɡUwd>QHU&l*!1<ԟ!yprq̑}+|As|K.Q 19.d]ITsiq2qnEA3ʲPZE)Wt_nN+[kCڦ;q:nBL~>zQᾨ(Cr GP,AFvEӝD@,Sk01m/щ?2@^`3%Od5ө- 6U4aF$'mL߅MR'_f(+rNgCC8I9ý+fTS͍?{)Zeϖ>f\"{R0ە%:Rͪ_әL`X]W,f<G>r۫ @8J!CR {<׳G1yMH.M8󷵦]NzFKBH՜+h%FgDO-h<Q SΥqAx[8y:qhk(R_g'YL\E[d8m#/5KWAQYX)o{=vjf7>>pgLz픕6e_)}ګI+ި5y2.B5[rKF3E?Hó_}uNL$bR"瞩9,p6=QB(׾ BdZjU sx )\wbQ[Nq=nVrRQ/?mfVظՀ)3_X US{V cY 1P8HYEbr\`pNtzRL[X1^K0͈SMfFXe%m?HR¡n1-,)h&N?eQvE§Vpf0U>kv6B]m9 XHuF_`ԞSo.B4,U$VU0,ѥ'ENT fF7 mORgUiE2CAx+k儙2w~x7),5&aYf`1?„MԮ++X;'SS'P.QcF'%iѸ$6BABNauɟǯt9x}A}F| BD2V ysU淗M+ b $QMwfS6te˽Td˰F D߂XLsbk9ޢIg[QZVD\^gҪnE$%mw1DKXԛv6j*> `..h^}A3q'2 /wID)D$C9S׆r~J)J`X %vzkx֐'$1 wVuqgIc7yM P+zQ i:H3]&oD pWVJ ^xo ڵ<3ؠJ=MWOvq&<̓3Sf,[e <A  ;d?d^N, > a_Pm̠+Wn/DxuT &TBRsS@)R$^oM𓊙I^t +z6e#0*i,#zaTNߡ.[6yy '|Lv|P5{&"$|Jt,\X讲EbcoHSgމ='[lb Dzҋ9N#p wYq0?oQح  Lį xSF BROaZB|xڒmc?' ^M gA<Ah2!Iv{:MSkۥXO2Yz .X8e2I\ ZB9''֯zf^~ 0f۱ D)Y$Pk<ͻC(7\BHiP/V't+ Y(UIF߱\0:窳8F\,QMFyԨb~b94% XYZT_hbx$.\_jz"0F5Ph$ꕐ(/$ ,4]Cdw]vY9Av8 Rhj\Q4PyG}_]EBR@^/ny"#Ng >a_e$k5Ah%]ha׫5#&xe1muKgHyE:&-:jqOiD 6:{/ JUЉulP|-E'M3^u WWiհzy)nt ŻRK:4R& d @ν,ôEbKOVه?X F!9.|*('`|Υ[(9=@JKQaE;m=n}h77LAی[Ɓ4qqhlvlO*}=1&S&nA9[+N)tGBL6hdǪ{䏗A֥2u^UU VrQ ȻrELDp4YKHg5%ƒ|ʩJ*cҗ;-';ԓaחd C&D f\͑Q%^˯u :,(fI Kpnrkld 9G"ר5it=' #2>(A;$,uĄn s):48ܐMQMAEۯkaW *OLh1* 4F-{SU!=ƄI#SJ0v14VKcyB{i2ѻ\q,:L!(;^ٰ 6 D`2@@IDAT) ,z0mMK"@2Bɠ*iff1Ӽ>.8΅<mC~l|$Z Te%榟_ !jAB>FFCp(O@?X0]&Q_v3G}||9O4Yږ#Zv>XFl@-xFLhg,/es/l?ބ.;m D%᠔GNtI_S,W^пY/BkȒf&]Mƻ/^EƹDpi~ӝ&Qv$~R:o2fz^ZNEo\ ZN{Ռ؎Ű} %daGD%l; gS5Mb4rb n*.(G[#}VA0b(]͡]hQʰ ?k`95˲`5wt>Y,$ ;ŎCR ܉0;m͡۰on ?.l<$fqob=!gGF .t_=O"5%d6 Hق"j[l2q5yx.%XHp:W ׃xq}\я[A`$bx{9 'M4N1tƚŮx`\{c[Z8L/\[d)bTgsYþﳳ"h{\.guB% ;/Ep MDc pȨ?(tJ+v9)A!eCѨsԅ5 σ0)Et?RU ~ˆq)Y i2h{7RE6D/>2êKdDϸlỮ68,Dt]7y6عC9fG&Bb|(C,d<гr8ƵLGIBf~;̃z|2jZ ^ԡsY}$gȓk9X~ZVSմ̿` v>*eޝ[)y& bq}-{h -*@Ja; 2AMs%Z{<. D&2:kZqڑy4b&?-%OsU4&o.]kb8PfBi(f Ţ;]62e 9?OR++-x5\meMY,EG!ѱ a@سԌYwVd;HAQu/тM8^&&1-NMIp"1iw>:k5RC~,zZ0¬$J·bͷd ߪ4-ܜҙ?ߋ pO. yi"*'b\IvŃ~@-Eؓxu>[5}a/D +SK_S+$w DIqGpaN.ICfh^4)AէvǀF^+Z/G=6QN-C rl:1L0)͘4 s'[͔--0a/(o1yĭrl:xj*1L,0B}]reD7K FfJ:n~|7 a‚g#d֞(f+<́1O ˳ 5 2-+4JSV%'V*S5^h%fQw4qQ Z?Hr:Z'IOhƏi36ƨA0K2fI6H!#ŏuHKjE0ZzIjy1Xc.>o*n[A:L#B}TMVX5; Lm'ϙEd悋n雛^fގZ)L $qqMuG:Y)aТvC@?mL)yzzNZ!7|p\/`H^C;L_3N>pmt3'#GPSu{p1@"O:Q%k(|IօNo)MkgG >E)dvV7+^ ¯4f7fF!@K/zl|i7YrV\1pid t!p_JB䀷/7dcO2R39;[\7ˆ 4GK%Ā??~)7fekpo3LJT[t5$GGkZ;.b=a;t.h_v.̳`qTgs+9vC_ Eq_@P礰p/)z7=fs;gRuO{2k;Cw5&6њ͹nZLd솔(40v^ n|ؘ$+ \bgLpo|BRR^`uɅJhNޢ1 9vAqZ2'5 ˎ&G8JyF~_vHNވ4HE<BM `^X/s3cyWEZy/ )ֽ3iS BGXTB{(tә1;<:OSmtcK)OM @@B_:b'1}u]vl5U:Tg:&(SĨˣq2#F%p@lе *Ö*$J[ö>yUqVYo"ҷP R 00A L$'ث1Ԟdkc_3K1M_ynzp+8@߇Jā _WҙrY!lgذ6p!rD0QN¼ xG,;s= 95'%BG Ä#fv4ODxbb*E#, :\T's`"{ϊ$y,b }D^SԋgH1OA3&pI|c*^YlrQ(s/=gz?@zKzEh|/< FQĖLwлy*%z[8;vl>-K~cIX/)&XG/;59Iyh,F oZ9!Oku\tauY~mER>W ڀRFZ()0Z7[W;\P?$zHV*Npע}f-l92"U;87|T4 <F'Vr,iDsfzkQyi$\JLM*׭BLÀS{[=-̫!e5ݬfZtoz?GY)cJ;+v]:ĩzli!IԁZc%UaNQk2c}M*(i\SO?]ˮfWh}Y]sJq幋sG*HTRv%KG\ulT-ȿ}GD{}W c !IJor9q=!I:M`ڸ̼hY+i@8jv#ƹ @- Y=3Yit;W}9(~2r?+ `ߴ*,Mi>rkLW\O Zy$=+>ڝc/Z= R 3cx>x GMh/Ntw@cb![2HN(Ga&|enqWwlVٷ//en`@ T9n)܋pÒ[CnZNayoO`4o5+nj8bE\`B>N.6 [ͭkM!Wƣt{hB)I%TXjDB7 `aZT`l%o#6-m>H)’H~Wo*\_-~ *K(12l oCL8pdl;eRKCa]Y ' &z쟋X%edAαLOCwsζC-|.#qkaq6MŁV[S3s=59 %~/ T5g][@P~{v~Pb˟kpMr8KN};[X*U442'W -&^n>I@4ژ5J=vIg 1ۤl+BN?M.=QwH6FpBrW[fRd6icaQ+(ojvfsQAJMC5.D7b_%N*^ah59̀,}&~gO=!:UwR7 n72[+i"4u&̎r,D+]i_|^rU;ah2X:-69z2|ߩ\8$yNo5M-A6>w`tDdwц]X|ng@ рsXQ1&|1aabZ,6!Tn018r2$ty{>UhC;"q'l"0̰xTʕ Y~j.-7!osǕ.86=xy4ќ1BY6WqyT7G ^2D\kXh| .&'UG͗ìn$bF (?բňfʈhqmדuĹ>XimlaU;ɪFpIk  nf'@eoHgd5m'1 wkgMӖ>> fYrI5B kGamzNBULg^Y/0b#"`S)֩HmY:l,MKlA@z6rpC~Eֿ.v?{(@N۔B@t>|&Df396PW׉T+4=^DN/|OLܼ6uBH3)U90{!iR# gcI)ȶsY 7Br $NZN_X vV\y^})z*N'zbc3ԝmc,20Aݪ SGRǐܜף4\{wv/BwC .f9Ȧc/ߎ+8q4:#2 ZL$ًڷf>)%qs3 Rd T ^d$Ll3XGYC\t??~j]{dB̓xa yovf#)'opz nPY 3~ێv68 FEZ0>KdMvʢXMSW?1sT3 C7VFtkOϻtElm?p`U^HaVU:E& wlKlI.seMYq8W˧(Z1Zs[́ o6|4 (qMǍـw06+.e9:I݃IV7ohzlL}a 7,Sα7>0 4ceEϽ۲~(>_85C_a"(u̎HbMޕ"(Hy| bpJ,x lkquP PkF#9!m/'ڪZ1+[\pvƨY6TqϿP߳PR`y>ܜg gOUmlat?k+lp9[?zԤ#cx,]XnNTiomulX8?$`1]{@ּ'q Yh-|-QY?Jj[~Bz^يqYu68Y%Γ߳,Wr5&KtW4Jg}^lzlwuZ9A/Z‰`)r-%ba-4աץzx+fI?׬b_qa'fgYm-!F=oU؉ CC [,fF}8@ j%, aIˉ!za朑yP%[ߪbq?{D|,b˿T3ǫ7E~g"KxSK5#}D4{|>u+MsG6E!0B Sv>sY#qA kӁRwau$gC#? R塁mUa7͞*-EψÃG0+u)zvɈuSIu,( JP̲/G so>QJx +F5ovV3횳 CЯV;a>/o8G"Ő(䬋ᓗ0@ԫ5Wiɨ"Y`s(`GOmaǩr-%s4Kޠ)C 6=Q4?B+JHro+AzS^),61B0uBG//>` 6ImAg.2 3l>˵r8?O~`ǹe8Sof~ξAnd! !@M*ݳ]QMT+hUNu,~7lur*'Jѥ61Fb-j ӧݙLEUNQ5:: S!1 &Cx;R$?%niES8:F$7b$DI! S_X'[⽭j`b%@Hj Q4T :\]s ^Îbʮ}0Ƶ!I-l{c,}Ľ"'MVm4<y0VlVyKi :9.11.Xjo/qޑ} 6J0D#+M6Rz#yNN6m1Dle|л \H%3ńFz+hBY2ު^iI ZB1B_>rmypM.:o8L6#yqd` C/;?Jluѱpf{4u'`Y#vIR'xM09N=`q/aϡ6">T&a >A c:0[y>[~<:N;ybAԲjX9XvCXʇh aXN!끨8%; Ӵs0cF*=ui#`憗""cjnʁ\`}UTǥ?"cq7*"(.@]6 \ݴ]|enFۢۆ_i N kcGc .RWe-3 j_E_髵$4 1X]_4 mڹ8[5_j>0"Mjwm epT% Ƈ]jƮYV/wd-r)] $Rnmj[T]/0%f~#aδ'DgFP²OWeZM14m]td{;Ufɞ)|vBoK x86| _l9Ɍ,fxށk|RZʨT͵ts;U('8bcNxD",s#iJvFol%R`"\~FՌ਽φ(S"o&: ҈ܚː 7Vf-Lg|~2S>}Ӕ]S|#/y?(Uj  vlp ߇5gvH%s`/nٟ#K6 oft'YحĐYʂ ld8qb.<1PS['#«&OMn?qpr6;O]{gI"ILyr>K  Qꑲ #IqXcµ 8mXDI9{eC:?62U{H*p0xAt†L{o$^{OL }FxUd@6g^Ze_ }iJXN'^Ee|NyFXdXĵ&ΛqkJcaxN MăG%-}`%T,[*{aLORfrۣP VSOzqr߻r'\!#,Z|9?u-Ve;#KV"  n 6& Fj2x Gg|T0$\՚د@!(4ޡ.S^YP1kzw,b}v;ѓ iW?Y|4vrԿ*pS '\"(T_z~)C˧|@s:DU _PZZ=M_r16.vqٰ:.eiP$%A]b.lt:LO]`e[=G 8=VW{xAرl౫II5SU?&ZLd*a=Л3-=( heV_;Τ~y75AH36T?<=LRQ|~oD4mxJ8 8*A~u0pSE oR2GxPa$/b)+DzKbl= ]t1)\^8yP8/L,h"um(,Wy<ހ~|of0 d5դWh?87D;I077)w ¬HI^m0xhH^6將Sm G5ng!HȀ`2JA[:s]ؓ f5_*Z=Uxd3-mHUw^c'J`71  -%٩2 ׻ ܧsRhvV3@5{՟ASo7/l!BSѠb]-ձ 1KPSlxy̆q^9@:5T9wW rX=@' q)݆rCU65m[+(c֣$kՕf t)1:c'nt.e\,#!kՐΙ/A.c^]ixJ]4v4}Nh;Hr$sz]w(P.V`%F[Egݢʆ/Yk*{g&@:+FT tB:jzbZ2߬ӊmE֮O0K s⻭Ygh iF8$P:o0ģMnRT!w%v2m$} \7Uv=U 8G0&6#L?tUʳRC2!?]_YDU7ZRTCq,Q\8dtc[~ըqQGMBbddynB\L+ v6,GhДƓ9~jnUVR V1pebt=!Ȥ'EYא7+LP% ;70e ͊xAe@LRBȀ(VF:LHHha(,!8Ք:l^VDrboߑo FoDYza7 TuؕyEyL>eh[ -;ZJņEЧAX3\Xe6hE-|U y.&eS@"H,`ԯaS6&H? DBkS@'nh>̖&R\ Xe1籱!d q}/VPu!4Y%橰I&дQaG$s#_̹cbe=8<<͗'a]`0 {Bg7 T_-*l:z3Px R70D&f ;O<{$x!9e2RQ8Bf|tHTvE&~gu6oYfA<9"bJʴAbFͰQH;.Pqwt6bWiym6t,x*g;{1vyT bD'z' Z޲ϒpl2ײ/rO*jV_f.3|1V=V==pL[#Nh (z5HRFQ 9P7JգUd+uVo㙪Ѽv[l~vZ!iw"{qF<ly[Yl& ܺVd}V摌{Zbc]@)R/ k$KXe6M%WJe:_X:3(Ior{J+k=Æ^&d}CҢp<Ýh;Ja/I~XlC$ta/\u70h/]=i=Rvo`oΨd7/L (GP1Sj҉ײWW-Jr+RL=*<]|nyi2 $Ad@PAP=jʟX)1F{ϢqsŭtUL)YjV A<9b-1plb"%xm'ԡ-.D?}]JcJpda9V&1$Lb'@;Z'Y`8h_pp~ABE- "4 3) L-paDu!궦툯-_+ï/ JXnZaM!dm:8Գwa9cܧ5HȲ ǽ2Y]pJ@T:VL20qjf2"TSxq&]Íɮ 7n^k)&U#~؉9\-x}&Yu6\]+ϰբL"Gso(3WP$Eޓ4Q܊p<b(&Օ("!`we+%ƈvwl@hڙXC(dTۨU c\}.`Ax<͘sxͮ#}g&0ڳJLzB Dq^!yĴ ϳ+DFB_E|۱vuɞ eNcl% fƈGQKa bWR:ӎ_ ֥TZ-eh' x1tJ&>t^5Q>$5nڙIѳ|a.!4?m-dYIjK.&H@0I`wA ؤ2 w۱_DO 7qjo N& '!haOy䨏׈-k՗'"? 4ԋ+2Ywbe$:tyϐșՌIДQ@PA=`{oJFE8#D?L_SA/#hze"Dl܋~TvO S izE')>?FLtT`fI6so==ǒcB>d[o(}l]kfY")0Y^]L]0:\WT= q1aE[wCqRȀĜHK R+ӭ2=t f]|¹L^Ӕɠ5`3)p g 4S,x K֚YS;p7Zk^=wA̳I}Կfo o^؝4Z0dΦR,;M6oxgP=! 0`7iȜȺ j˻؍H^a:rcё Ɗp.2LW\e\(rE&VNCd/b4[Gǜ #*bOTpUlx(> 7`NW@.;{>6.Ꮲ3Q}`aYKxFGo\|B<01trTPw-3&y"Q)&Ĺ85H[kMwf (d )$gB8,j[Jt]*?!1#W$3!)`Xb-Ka3#f -ovTYzѱ"xSorg)vJ: 5qzB>Urs&oS$gYX?[a4cl?PMZa@dJXS g,pqR'"0F4  U1LW%`> ۟.)d(g ׇ@&Ho,={> D|,ؘs h Ԏ|Bлˑe ԙU2{w[F!wFrS uol}1+<0\YsŅIl<ߚ턈Ӷ wo<iI.pE6ށ_3CΘu'*qKY6Dؒ}ٚ9FmJ'҆+,+84+*=XQ[Չ|.&MTOH~:.xɁc"lhڲ:O0t)AlDJ偟6X:-ZNuj ht^븍94 Y1#ș\jDE6$鵧ldSsv-?J&:J:`z&&9\s 4@݌%KOUNw^]'k՘WVAWP$$ؚfR~$f[n' %$98nNӂPbt^.['g\\Qq8piQ\M z 8a/E7qMd~*d($a1]U, I'zSAë;ju zh $*G/B>BP0;1im&  ^BCj!)8e:m*6Aפ,=`ap!+޸/.|Z:=ިTG: BͰ[)UlIA ظ B3X ̟Ekpa 阭޲T=4h[&Z/=r| D1W{GQgmKY41av6i=ޘ+; S J°'c5/h:B0:hDPoSJ>ǥlhʪFff3D)4Іme=?KрIqUBTC=w?{!jJ!"ųƢאf[_d|}ʌ1GeY0-`3 '-ǓCmeڴM;ېTAn / t&ri=/ok@8AN7׻c~ylL?[`e^߁vפ/؋8(5[ؾQ]C=3S~i%YaޏmfX"SC4 FmgfxWf} ʍ5J'BѣAduQP@!_;ј 6Ϯ5v{iDT'T asysމZl}̰ϒSe~ f@w<1υI] !0x6@T1"sm(存x(|pDnk/hVkX 4#de: Ht/l v5hitmAhA*\gC8Ѩ:*݄ʗa mkA}8ۖAduӒbTej+{:$-Lތ˽ՙo]( p@f%k5TGUGwZM `\bޝy,{04^})n Of`uK9ЀI6 ftZaFT{>K FRV3~@(ԴJ>[y`b+\ftG5XXvcMV&P4e:QҾ!E AtT6-,ѐ&'q(^A &%-)⌘0Korn]: T:D2XEL=+» 獛=;\-!;Y eS[B')Kxƃ<-vW^aV \Ic#Kl ϊVҨZNh34V64 &X1ގQ7"sXg 5dK2YAܤGhP8n;0Ÿ<(V'Og-=_d铋ywQ#(Qβ(Zͪwur0!ZVb`AYei,NHԄ T_Oȣ5d# *_+fGb|Y,@UԱcVˤ3<T3U"ԟ 7egpJJp}U2*Za2js[)$5pQ[Sz#oT]o3`eÁa5,t@10z@1 D1~d~_~IR#-88YĀdhj^ȘCLw9E;V wdb?~Z4:gr&b!In1H e2{R$}x^̪l' ].s,_2et1,4wO D`ѲL̈NC"LfJqIʅEӋLgl#ϟx&H$+cwRm D2`3=7M]nGUy4&êymk+b;%6r"UyG]» o`1WN_}N+  7hjXNŠIǍ(D>SF6viߌ~zڪ"};$Zǘ[QhQLUYnB,iFTVh3\DRDNGuH8Vꞁ'HT;>Xd_Gg\Ǭlill v`6j~ PՉbÚHx <:o;zOX =NaCYTrӑ-Ei/'Wi+(ErD`Do|k ыh g`u9$u|_if$?mEWKߌ_+6 S<ya`PF 3;(4WӾhgBv-FuU%qQEb- 裒2b!m) [d yJpf\@ ΀t8vPRߙ] . ,E|Ƽ iŽaqL0SVkDF 6MbujJRۗ.1ʧ u`,*+jS,a[|Nb1AQRsiLjܓ9>)La[ lZMGda?`:qcXNڋ},~=RyBy?*WjԥحU~`Pk;!re P?uη ;ClF9 M%URJe_=$F#s"5=+]e5pb3d񑴄)qixl&˭ٌ\9NX;fU aӈ$."iWT<4`o' 9UcWϠ[u[^hi5Ťv|88Zä$%zs20hkτ% NS gua0|urgS0䫃.57CJ ~{UZ9}aŏ!HO DSFb"0\ ӗFX!ɂL+^uo=:^Pԟ䖴49/}%}=Ow֟l꒫,-RXJ6a J\y}/duު8Um-H[aa`v`(veu*ըma5bY}5+JobdaI1t22tbWEh$' I@+B;USf"["Au2:8tOM S@@D@t@ձż},Y#) > 1aB$xsps.相1`.!hHD[#F2U|$5jw.mRt(dO%V=}LGAea51u L%dQ%#n]Z{ 1Z5?v=@Gg`pB~Sdkejc/-kScŒ,$_P9h3/U&s#h\0dתѤ#Q|Z&#I]mw+½U/!#+Gc}k@s ʁctl* Cr'`% b6Ng"Asb.(.IEűC)^w!n`|8<(7Е.!2"r-EwRV:!{C`\խ{;e.Kfi YUËvc]FY|ubO%̶A5*1cj& FԭNL />kڜeY1^0u ҝ ""AHo8@L\Bǒ} bL`"86Pra@ !M6#O&!iro8|* 0 o ^Bi3|~p@hQI%"ď9/yi"AK@7!cW# |hX[.,0]#!zkLX"{'2,aV*u|CF#^߸dVtioKfx}v$F ;iǢ Do@6J$U+̔s.hd^hE^ Վ+ Ȁ쮖#3J4mUIZL8,c럢C#fx/7,c۶+bB"]so:yUw _=-Ŕ08ʼn4O=Oe5jɊ f QWYj.RjSGkwjX#` >d'QZ(x lԬ >P$œn8`c=//( 0@$ l9qʥl}v8s- L&!F<8 r[X0\aξqR7;Zs7Wᆃ7CE*XK+aN|aRT!~#L$Cuc3&+~rY?/)~VZoIfZyyndJKRP+*AY2O?؛:=J+Hg b@˅fʪ/}np ;ӒCw9! \CCH}$\a$tfj`7};VSH*ĢXZIvg&)jljKȄG No+Y!o}kȫ'35a |(^( 5f;N Rq_[ֈmwT[v<H4#?'s% ldHL%KH.S~ l]ڔ <7:l Ъ.{䪴2<^#*È30[+5+E2bΡfWHKG8n۠>)S2 nz?$e4L{`sjjxݐ)y.A1f{dW m!P Nڱbh9Hk<6``$kQ=9ǹ8fɆ^h칥 S3Wu@Q&ڰpjcNoʈ⬹B48`PHm`\,KUg0gW;6:OA4IMV)uHƐG&*9ES2 LTTg1@}aZ Mռˆ0Rhd)YV}7jY]xOτjdC^.W$>㠢]sFb]-+[yBgڛ&Pspؒxd9:#ΖyI5B@.UXf4E܀TaKcOFCe٥YlW,cr:%HѳCV[^Fw Y@J 42~Vڠ-S%)Eumg2x[L[dbKѽu'r <3:r:\#>n1qM'V} 5%Z")14ξpv:r3 ]T-wmMB6(I/r4C?eP{߀< *ȳ\+,9b`zȶ&_eX\4l20;+HkCѾN s=@)J8ixE4n{SE@&70zfQguyU?s]v >BpX5 )>bEdT K )EK$KJUu:QFor0$mn'KSQI'"FzY[">s ڐfb(B\8wWm@S_ {dAS,-mԱA]=wJ*,D"CPLqc~hSqDo߅Q5nOa'L9ޠ-#p":sjcP˳Ã" ci1 6:XMaƪ:8׳B&_~(S^n^2A-TF#oOPw<˳ƈ |X<DѰ &L-$ g§V<3S,H+{t1gW B4 DOx\wz8ic3{(LEFp`A\>!S8xT.BLC902 2beNĊLԌK\`׹wVkcA)Ro$b5f`FTs c#lP>Ď,jv,:rW=Tp+inl/N;}j 睟9EB e|I!tl?a.(nb5h 0/?p`jZ// %T'Ԧ5ꨓ.2=ï(Xӣ^}Leq|CHkϔҳO2\'jb1ԚӘ}5פG\43L Big?yN.>b4Qa~%Z3B厣}Tl}/r`I驟sX+w$-bɡOdmIh$Ny1 .%b"5 D@Uyt>ltY/&`BR{c1Rnz-;]MfjiL\K(،~@\X^l6_z4^%\cj WImڬ L 4DҶ"p^EQV Eϗ$<|QƅwJhQ` \оHd-TN~D:nbd״t;ja`! X:b)!zČWHHLyX%g?Ӻ0 qD(CdK.*G/ej U<ck){h'Z@TR5RU]à<7ş{œV]42nU(Օ7,{ պ@o{z Zd +K8|?'^σ4vr͔Aj pyi=>u(<|/5o<”xq\9yB K*cy򦍐“gpOr(SHPܘWOecwQdU_!g=ӻZnOf2rU lK:0B%g=ž "h ;#B}qj=TR_tad Gӛ4w-Ȉ]6L o%l1^q1Ė6'mdv|^[ B23&>8ĈVT> ZmI@#[582Ŗi5˫36X* )3GwŸc/,el󠀒zAFYBIH},l!b{ 2zIu%U\") *10UD!igx. B붓!JA=Bx;mTa^,),mxDD}Ik}/1-)n ~oZ ׁt!q XLg YtC0-Ɠ?潲yH]Ϭ\ @*lUh`=̴E7*j|sAJu'5ܔ쭭^{5 h+B7 o,(8L IlJ%g){v֬.3LDvMQ1vWynٹY0:eT&gK]|kF4t`MP@IDATjd"tRaXf:2e5FɅ!0{<)X˃HdinI rTHKc DDD03FpI2&]lo% RuօW{ṱH-&笚yd'##$>9{ n}0D9% yן<6귂ÎoGսV=͌KП3S!'#ݤ>}#.Qӳmq=|dzG5rnz(yfjjհ(<^:4b{ǞLR+Ws]7&{3:S2~75e%:o&?7),HAsUlPIí6N L&፣"aՒ|%1|7D؅wp^=l?ȥJuLـGb/u6> SD[B0ᬩy#ӺjrR7j< l2W!JCft- Ĝoߵ5*L**DtㄭJ)WEBwj@٬FlޜYORW>A-D!|>@TСaho\_%{nG{ Mt:2> -(`4^hSL+%8O[>bt`I+H@mZݟ)ݜ\~p((7+[`9?ϛ 0G؋߇_wJ46:J ~.ܵ?u&9{9gtO07 [0h'G S"Fs#M8[>@zQdt"Yw Ni7ūJ6YVm;!u73cw|R5/r;0 ܦ}hso-)[~ZjĤ;K6 ,_ΛۓK=gdЧFb>>M_%,qdXRiF^'j"4ieZPt T֩8Ƕ +T_(ĹȌc_Qsh>TJ7p]ǭ#5= R5'߿ھ W ;BLan0~P֗N8W _șW v3)mL04342V|w[˅E<٦ yT\a8("dËwAٌ!@DaIs\OkhAXt5˥QBI./ ƫL4Lc-e qG ǀ]զiUْHz$+z_]jWI244ŶA4$YNI,i(z&Hq O¶{^^Ϥ{s3%$ .iWLqza #=?񅂏o4Li]; m++:XȈB.L83jUɷJPXNlPHr6b깿!f)jɿRifsw҂s17o  @D@y8` Pu3}q}a|t*0q+DM0~Eo:ôa@q=rMa!c]Վ3`%J͒ k-DQΙi]ȸXf^}KƬ[;-OdOtp,npmr5rLD¯yq2cpi @oC3-[-yJ^~MMN}}d I Ii^ÇhU 4E(xNJNQI!Sw u˴n%) $LL:=*C"k]V5hYp2SH(Ye|pjp^/M\zD l ^BP#EW-@3oV!hb" 1 ld,j $G+#RQ%` `pe9Tէl$pD g&8dKՒ9-FԤ$6X) Gvd>|B֥<45Vغ3#,OjL~(Ù=dS dhڗa 0'_J5J x^QC,-"$ a*d[ ćm̍$Ұj)X+<<%r/~orp鄖-x}T0q+>Qml+ i7EOjy]x:C-ߥц6%gFG~|i$IXd9Ӷ!~{Q1bSQ&ǮEMZ|,O=f@l8,?Ak@Y??=yי-8 1U4cΩ:LHHP# :sX|dH›deaߢQ\ {V#gќQʐ0- 2 dcq(26 N 6>sef*{0'oc̦hʸs'HV7zǤt0x+G \6i^fd׏aI՝Kucg ч:/W*nW2& s"t!ΘYǓAcT\l| uLr pբ&1' жz}1ݢ6,j#e>4W\p/\n2M;IqRl9yAr> 0a EDI60c ͺov8U5//6@63A|7/z~է)9x<|<3u |G ũ򨞶gC:+ְ WhYn<Zsib#x)OԊ6͓y=jXD1, "sd/Mhݰ7nvn@3HmLf--2*N=kABF!.%fb v'B8ZYe䶑¢`:Z0SKHJΖ=}'Zz/M,;Hnbӟ_=b!Kbyd=uR=Ƭxm,NkH"ciqD1EQ. )Y t<GPʭ=2\dgϯ`pY_/MQ޺eTb<Ġ-Kfv.zv B0>x_d?G61kVt{8}Xb֙=n9ֆ#@gn:dP-6?1ʈ ˆztt K$I8Ȑ)3Y^rs{R>-V;b#̀fO5L$_(pNoI2: ?EH&6VҔl~Żm\ 5)A3fh9z_HVcr VkAFOW[M bi8q5JK$8+ Dұ¶Q< ]<;J~hdޛ=#}xk5Ov*˪bv><݆f޿&㙚_[aƟ.0kׯS,7O˚8[U$,g~FhCekYrt*Q c#HQߌwg <ЀwohltYG{6=%8[q]68!Ҵ zn݅zl/\&\5׸5ץ aЋO͖XQ"BE)E*K="cz2aof egn޼$O(T54n~ZH)7w$0qN]ZG_` T)Z9 x-]m/dyжd$yEv, h:Cj~ -E^,p. GO%hxHӬ-~V9@ꬍ%H9@M#?ctG/N#zF1!b.f-osz(H+@mPIN ,Zs}Zb/#J@K"ĬUn*ke3RL%{I $uqAlDuq1w oޜ#*EIAG43$_B2rMU[SjREN6 U02 dHIqhNl6z`DBpi\,`4d2bWNdnFR\IYZ4bR '|XH`&3R+.&Cd2ݟxcM爘^LD5mZQFz!lkąCR=ADK+oUYQ͛]U0JA:ʾz Rq-qSձpަJf84-.%q [HxDOӦWʘ RC@ltabt+-//P]]:OBSab+ÞT R\ \,u?4<~eH֖*,zg䅽HMv}Y֎ rz&l&'."-`*ןFr)hK ĒS3V=\ iHKM/@e7 .ƲhS?j]tt:v'! W;=.fW17 %WF s^_JAExdCbLPjxڡ$XY@1Ɣ97 "hœMV;RS@B3MgkCs`]~5>1WIڀdcChiΣL brq{,L)V.Jgt̥|#]j bΏ8rߊ p\h>x+4?H {u\mYcDwLfHm55#cCk}!' WJz}c6V'p瀰lhڬ򱸾qlYR؃F e IX0cu)->rMl0_P٪X计j{iߡNIF" N#8eZGgRPS_H+b#Q֡NV(ˬ+Ze־k0 QĹ$~YsVkz92Vc-S즒:$zYRo0}7KZ'EOq If6IGd2)A's m< 6*q0*)3Pf% +@ i$j/K\:h:'7XJcmZ]GFzL7*ק["!D ߒ pXM~2#`B#YqLRu(ptUj/QK'&va.lv_J zU/bv] UOfpb]S%9R"eUy[,2i@$:DӱDu@`ܬC$\c\B9HyU/%oC];Q$X 0ą'3^5gֺtbB?؟ˬO!T)<nOgD곶M]zUۮ:k$PV& Uˆ$:xǚN05~􆿿VΌaʬg 4_\Bj Frh΋ іVz׊]JU* ,GW*|8^#,99a?7,uK~q+9kfy?%bqҘ-푁"R+_½Jk⢛= va##r q3TQ &qI߂uCgVf&8ɒ_g7n {Aք/0 `&3a7K15sH-s ;A1InNXE[[-i@hXS颡D#`074gU0Slxm5v5^=lN @!Y''/uAnjuA2M.ki h 3_XiYΞAi-Z\PC>V0 ˍJ/y0*d]֏-okXeH O! \o7|%ik|ZLv;ȗd\Đo(g=ߺNY|xEy]h٨q>d'oZ`q1 SF&%ŴCN;2'S-JM%Aj PLCUOY8>Üh & =^40޳,x%9)?kcms¿++Atڛ .ŅNQYXf}Hq%ьNFs }/t,Uo,TFGc*`/r<!fJ Zd6E[Q' Әݿx >Y[њ_1ǥb x@XD+ D8ƾkexAU "mZ手Ե} ~HI4W=;$~+ܚ8N1s--6n|M= ?@ W< 37KflO`mt +[kh\楖S@&M4M~NzPb#X(M0#Dv74^L=+y*ڣjj05oyThogdߵf32yQ3uSs 7=t~e.z8&I/I(G,>)gb.Z~Pμ /"c!꾳ra.Cuӭr dEJ[K I,eqÏëv;wOLLik=xʉ-jNgHa.W7ڈ(oԈԇmÊbv3Df|g|oeg #)JU7s刘 ( l`QsRjnz211C +^h 1ZBi+8+ø8X~k#5FBX t1dBcOAxӍarW-rq 7@.>)+/y9?z _{%:25pC*2aHpb UQ G`a(7tToW 1yL*(GG#IOVͅVd5X0ˌQxL!YW81r=dy=dɼF+ [}&۫F7*Z$O0F_h`)j |)-gi+L"۔bLf4 Qn˂;ݷy(DjvρŅdǼj G/D&yD\Ϭ;&+|i鞩_thf SLH[yZaDI޸>D{oUJ61&)J1t5E"xܖYKrC% rbR}1Qg(>k ]ޫV/sPz>/B a1$VpjF tAhz# %t|=EEoo')giv,t+K9mI . x`yG߿֬APpF&ha1-N!FVYyS"|' h&osZp!X(O:F&@@g<DD*y`m^YX aEcnS@vmƦADU} &V((bphA5!¶&D92Z܃fN,Z^yGY`se WnQ(P:]gj69~Čh+ά| wkD!LG`yiH8W@vmnGx2׋\t'K{UNAl ܩ{վVbGا1aV!- L['KRL(/b:SJUSq (RBPR6"lr~z~0[)Gj;+6MH`BぽPݾ1`$l@hq҂9h^~uV?k[9 (D0z fj1>Ns՗j[ mE4.r9.\r=~x"俔,6ȬA )׈+_e!br=,;Ap D|=( @/y7N3ЌV}r-@_ <|v42?iϬdpU2"A p]$1OBMxs] 6Ȓ#t$2aR6(=hjoq"7@5˜_,][AM394Oeĩ@ZWWi55`' $wO앴 o'qۙā!}2KOןVK+z~j$}a܎#vzg :+kO?DA%4]6{HKaTx4sgW-V'R,F !b[A_V9*&W#29dLь8?$J$+ >]Y.J˗Flq14Nb4[Gy)95]`}oU+ՊbQo74pAe ƥ(o֡9@ S4b3kLue^ W{u\Zfp4ʕ9CY`M) kb/GQȚ;D[a'fsWbY*Slb e73nŐTDi- QZlGv"J*{7&dFē`[J SRс.K[R90) M~@Ru)_&#N}a 1Q{' ,L^ψq 1"-ú4( ɋGe縶"FƁ::LIi=5a_Iu['*^3Jj;LvSk}YCYysv|\ML`K7tQ~~լaI;<31Yk$I%1tq1Y AۃAU!tJŗ(S{b2W<:W3m%>ئ0 *`&zX{w0C"I%-|3{?8a'@Xܜ>Rz~5^&yX2eC4@*ieCE;ń`xr pN|j(IPv{zܑ,.ƴ$lcFIP005 y#velknQy u}!J9z$hZW+cV1DAk2EW\gYihhlQyQh4x|vMeyW1٭;qyl%i~m R90t=02ѣ|kC7ݭY@6J(&tf;'pZNw&z_>_ PPԘ9|?&3A#P,2a증cR9M`8Y6`)Аl\FTC_.R1Dbc Y(W1Y8Vdop<ެ% =s}@ӟߌ2 ZGa_چԯ`7Y8|ߖcHr|/HlLx U |/k-` .A˝ݜzv)7$f_ %l ,Pz!;РxIϞS 0x!PWrQK˟WSZ.k"4$w2EڬCBE因[&(9U\#oA!INS9MRuDG(ҺsMfZ+'9w,gX?=2]=U>f'$w0DPW,;T%2,,e)"t2RT[SzΉ;Sq\g^ 7 6.*cKJeYf_ZC-\y˗z9ؓ"fDV|zHJћ#.gMNM@Y\sVekc>_6O>$l=׊S;鴫՗ۣPg~ wFM!=.e4 g ?bGXny|w_^GqP3ew#qv|XԘN|B aOrR1i KUxP@daHVX`/?xvj < ]4l&}هػWM9k5h3I.>XK+{uTEr֡*բDBf`P';4)mErt'ֵ٘Y~ 2&z&T(cIt3̜TC|hcG{I'4"z 'OW01.q~>xVV["'SIώB t; U$raՐ,K AjҚik:W;q _.DPX0hN26~S1jO܏C]sҽ7Z"7 J!L} S. ׶bF 7 Iɪ0Q K$慫qS(Icu*OFk"Jj4w%X6vbYc'bőU鶔~@N!!gQUKa1 ZB]3<:3,/S{B2C=yStD hFj54ǥɵ)ɕ˧}a8iYgɐ}KjUդR 4WC:tM=iSu7 }Qï+5_Áv\ EM;ākVv[Gun6I6SZ\_rG#f6"5tK8vFޗ! dNJƁka]/<͍Ӈ$dآ z5w(hKړ,ϡrG}DG_TK(a.vhtsJ kr39]bS.tW4鮕#FeEǢC\-8fs6lkZ:p-QlY,09A_ɢI -0I[w<@ 6KvQ-Q07`K7 ҇Hl|,uސ+}Uw&/c_W9„1u1z+̘x0bX4"?l&w*Q, ;:~'}xzVB$P)RDDk-36|,!m \G8 -8L1O*0#MK><%H|?dq})Bnr\}ea.\CwB哑d-]DCfȹ@:F%!ֽdυB@^(3& B- ML{8?5-=Hp,zO)m/ m3fU$o*pKa0p{S&% )h^>H}n7୉zvt: lVOXVf-FԈ׈ހD#B)m#/JYVR45Z΂uÜM1^TXZI7צCzuLXeȨ<ŋFW1$ ̎wRteBOD-j,lS޹2`1#R\H)ukM2b@NԨ} q(@5U< D*h1~3=Njal3> A&v{oT>ؓ*Ÿ`NJP {ge}-=F G^Bť-!BQ!S4zmE4?꧰Cg܆>?џ)՝UH>#<Z:AYOCPz܇Bp*$<@Ƃ V1Ǥ_H4pd¥:7)0UpzA{xTko.Xטf`߳O'r0B䧖2!yS FX cZ?S.iiDhL;|dNe Sh3Ge'+nd[tJp 6=k [:~ɐ8}?@IDATJ@wg(^_+88˅CBJ%L4=,9L/9/bqjf}U=!TL0+I0FMƓzALCD)I`ͪ7o?\V$ZRs B*4D.W@Rq(cV"1e8 Wr[R4hm\Kl*f؊Smgc#'&N rmgF5+P߀4v!5'3i/y;A<ۑQRqpJ @O$Ty͈kR>? bD=Q^9k4]JhS~>UV澪[)F7)DA2śʅiΈ>نEt3Zs>/ЎYP(/탯 ʧ~yqC T495f%N-Bb;]mB-'xt U O9'h` 杨@K`md @VdKsтҪFwaeV<:B~+Z9,Bg)Lk*xiOSjM'dF?<7D9E*>Rx_Uϰ^( Y g[PQ=IgZ561ɫgP\ww]Ew.r!zѬ\}ZLEZQA< έE#+<]]38zP=7N;,oAKbadYu..ٕ[8>EٞA1ߑ8l_ Bq?6k8?HPCD6HX(g" :g!W0٠.|Yz/ 1e_~H{6L'^G{s,f > aZ)kRV-xS]y0 fI(89  !ahb-rq"˵ND@MI/sȹh(fl^Wy;s*j]WB('Y!_kzN} |ސ;Sx+웜' V=ycHRDf T16]+Ia:92W+U(yV ٙL@na>ǮůVȽZphp#чs*p(p^p!dA¨ +-؀qYFgրچ Hd64Oe?5fǼi~8 *J0 Zt6" |Zz,Pi9'C*$!@Nj^-aiEӑ1* Sׁr<0؛Ѳض3}? fQdCIgRD% x` XK A9 )Pyg:{8{ed IB8FzؘyΌpf4ޯi-b㡿jڎHj'ZH&:-(gqTS)fζT:,vdj( ^pg4;+ɐ h/`Qұc֛63 |q.|:20&G 4N_Q p3fVaZ\MtvˆQ~#j+4< !WX}-` [Ãʚ1RXlDeK0FrH3:19)t(Q` !/9pfqG<)ea "wG; b- ; 'avzAa8\|}.DjTNš zF̖HyLr2Hz`6C eGgQqsO&ͽq$`ɳ&L,@GKlWq YU4Tu#ȶ%G4Yܝ6 ټ`yBw@dՀ25'cћ5tv &,, IuVkQr&ۢk7)ExOtx}3QZ+f0uFP(&{䎉FΚ,[3L:ϫ{ -_ t9 /FR3katx2yϸǩM ZnAtVAj+ϮbTC;p\f,"/$yJZmKH=@>(KQX(&44j,pUvJ N0P!&O Mҷy@&V_'pH#8c^xZ*:ވ#=J V쮙:Y_? kwTVU)A8)ORL͒s$'ARu= #$&6wE@głs^cc$ `x|~Ɲ(:4#my|SY)'_(uK#ttiW9!SFT <1QAo *=&j_2a^vtX,FИ$hb+6^v،sؗHKZCţ7~/֋)GﳺtXQV퐌&JL5Ɲ[y_8^[̈́@c`&D4Vl^!7ɺAE8:-KrtoG<hYK.Gf d ,q1W ax!i"VZJ.#wÎp\Ui~H^^W#.>NŻh=$i e.t i-sSG{Vӳ,ѧ1H(jʭ]T!;(a#D"GH2Fd<=7ڊ;EO`>PO 5 7C lx}WW<2惞c⿺:d- `Ȧs9C(#gegc8=,i}!U3}1+N;6ILKO.֫h+l}8ɟRx'\O(w4ڙN,!ϘzY*a{nszI ]^ ضKe1)}zUzpnN(}A_Wk`o䌈'UKzL4+US3;XXSXL+)1UhO J\?8I""/0 rjdD)zf4j<1\$+U|KNJO d2˔+T(jI*8H:Ā7U"qIkⶮ|ьpw"4D-qp*DŽ"?EjgݠEknaT4n$6ꋪؕq%G6Ss+;RGCMGď ±%Z7hÔDz NP܊y#eZCБõ6d,` ߮E~5l{`aĞeڜj,( !6;B~9+DDomIunCv0h?;& D* pM*˿4g8m{aˣIʍtP2xɉwH^*"[Q>qbh ӏqx2tq%zT1&nL[jƊ8-c+o8HcPzw7z<*LY2E#ǭ%I{;´3ݢAiȑ(qj7o|Fln[(mY~ƓhSeAzGG`ؐ!JD_FwPo62\غm-4@'յ?[RP0}tBg ,G]:bs3QNH"X_axs㋗ZN+p%HRZ2`Лw(c#[/9 zcXbmHL-/L+NA(t1nd1"wzJq w雖3=}XKO adISCTFsc )yJt^x;Hp$LGo4!qPE{oXp58*/ސ=/D0ś Rm`63ؾR{3dS2~މ Q +^?nhW >rMBu34 X4ۍ ȪD /}lA $Iga@G ur |.b0|xDu,F gkE) kuzVrﭐZzIŅ_ lPxަ)UZ  cOo$ϻ7W%vK+Fc8(9lϓtslɑ 2zʺ~6)2%ສhF4- f<ãDU,QRd\Q wlVlIie5>].n"K߁awl}zuйT! ] wT<;Ѱj5w=:$&'/ ?ba<-⢅T)3i~,QPOfл@Ֆ{c6;XxtdHhU,΋- )wi*sM,U܇2=]T*'Ћ@/^u6g ]Sy`;3(5 A]>؉֎nQe-,Zc œ$d)!0x (=SC ώGے[$wLJdmI(TDπF+v߶#FzP042| zYs h݊"]FvoZZ)k^"SlKwY-'zpm|!A I^!vz IIxp$7t9hx2QDp%垹LC5yTh+S\%$GMZxۖc]3$MsԝkfPQxoRC@`ʢ lLD9uMޑ"P/}Qy T1U0IFoxJ g_mt IU|¦xgxG"L; )H%;'*g{)N)^Y+a[wbrLmYj3v/V \{HK_g nJo4Cһj ґUhzUl5~X'UGKHFmPavޫ_>4͖ _jѭ&|D w2dS@*ߨ2#A܆b]tms)qzj%(Wbm0.7*r = GW{HVI[Ω$P)N b\9f pB-|M?dTJESS(rZ&8!Iݔ1{VJ6Y^C=D9]lmFydz)jr,ܧ$2;ϯ΄ Qf+Hߗ8\Jafa[“UB"[KGH(Uw -;G\cI=R  M8WGjiIvߢTe`n6ѤyW:tɏW}4tsv QN,fֈQLSvmo罃' I/KV ٪FD"ԣ^٢y"؂2[m A@$cAEa۰>=e5EFn\㨢촟6r&lb(gc8+-dDM A)ҳ\{XA PԹ '2WjeeڻPcNwqnbG!AYP"T6%iUTjn>'B/ET1Zu@(۳^ɔe[$TUz6bH;%6g$[̟lAmG ^KM-үG8,sIBYƅ}R+ _dJmck)S$Wsjxuz_'QS'rGp0u\,@'uϦhȽ#c}4LUjNRk!3-BsDP Z cfv!!W@C1(u(ɳjn4XoA@ JE8 !¿~SI wu:P[ WP@F8bV"B)y6Ϲ@ώVP&奝P)rb}wzƷu]FQi*rw@]_/9 d+۰4*uvtZ faK ^e!9)g 6uoXI?>K[ɅA(ڦD 6O6 yB[B_S_3GMK-g wA0d5U m 'FVK b(s=4?ȯw8smfE-6#8*FŔ6'mc_?lw`mw0NE=#-sUuY2:-ș*yUԾO!{yjaw'%pjD"@y:(%ʄ[ i+z/`G:d&_s/afrCl3b9SX.5}; l@8^*0ublD/g::EaS }rBE$b&$8?G) ֌0^bs:[{Q1D )̋oK;Az_ЖҘ*|4 %lf>R@].N3Y.޼;GFuD8?^oOnVdL #҉D= OpB<;ʛYy3A;@8 -pK1 kus5H[E@ m.n*P3 HhȰ ^1J|b--${%pG1T :Xd1[ :p2T oؓf腘Y"a~|^7+kL_' V3/ %EοǙBw٪D;Ǟ{| rzhП ~zR<LԤ|ݩs`< {Xg\7 !Dp!aҦL~/KU46E{T/!Lg$O/= }o EdTzgлɉJ!ۃ,߿BLCӮ1dRL >'68z2?֨IУwSy-wN5 %Ӽ'(]9HDP>sPϑڀjC=!N37xZRHpԳv!vn*m ;ZiO#tf!I <π(8&ktChބb"géL '8 a& `.8_EaTvE>ТB:]CDPpƾ\ DkKrՙ܍#\~z P\&PTWmA)D@E >{ I0c 譬w6hcᕝ%> bjo$_udK[U>vV4JDžT(ɮ@B`ѵ c]D!1bRnOeOBRHjأUtJvfZ.,6PiHj|OzTQ m+:; 5Hk]C"h\ A1ӨTc)`{mߊorm!]SFcP[a ,j [;`s_0e hG%%չP=YH@)G2%()o5S 4'v^oQ'Q-x?+M8D~^_8{) Xx ] 3gYB`A֩\%ڜ 黪S5ͽ`K9@Sr$ mfB ϙbI ]?u2LOf0` M3QBӰf[g څXPU'(Rrlah]z̺_E&($B$~԰f? [z< TayV}=vp3Uu~5SHqЂ?:aqC2kVpHY-ϒ!5UG4o@4Ϥ.d$*ku3DCώ6F[F%n6I!ef.l-;set&)|AИ1FT-'fFy'1ї!:bC C޴szCPzG& "s&pA:E%T|[J̥'tGs^ֹHqw46Ǡ#1PuS+=l Y_z& g8{ 9sx7ijGg$ D%o8r<3\\] x e)-P͑X`߫&่@$#U("x%4R8|-t3~iF݌7 +ϣ5Ș:96@a3h[G1oVK]\I"S@Yoq:,Pe;QKmqN'ES1mJm@*O;'q8ib,R GІt5j>pL"A;=dW@#HM*xm\øq͖ʈ {ob3;*HIaɁdK ֞fzg2p*tDq_w͕!\h$GM2ȕG4]atZ|N*wCS| ݠ+6$ .k*q?Y7!; *`[|;J^kS _!Ց{Ca(mFnwꁓ r|.-Bpb{19\])N>{ͫ3I'} bsp@`\vQK;8ߒ"> a5@ ^23Q,sS=:7I_G׸--_#4dV^==ɠbɰZ6zV>I#JXn><>gJ m'XԶfQس1~0]TRsPM[.L yS'bL UU.uh1'dxZsNx z1IY YnYUrh)Mi٥Sr4uʭgXOX(XAGɄg PumBQ>;)&Md$R6JVԨh+RL{8N1޹dн+<ZVMe4BSo g>R 21 0rtD  &|v`EQ5fGʮ&BtEnO$D*ȀJ28%XO&S_(N .$)GˡA("W0tĨ^ ͠5]A T^v{=/.0wU㑎[2J =tvxjbO(!_iC7{Ćޗӡn[bB1. ^2}'6hQ'V](s빐ӁXbem]P*-30A]('l%)l@O)ѴYHuB4cњ-~yMQe= k8rU9 ~ӾAx=g D y^E"] |tgi!@[?g dZdl]T+^MK|Ux>Rhi|ڵ9]k ïa(;lr'obZd"ԩ:7wwW8 mJ֡|R8k\ECȂ1sIfӇ[I^KRϔ2*JlF˫A= з#d-~3JEt5..bhq%S _BΕL #_O0:|\T,b*bӝ+ALh.o;!7mgfek֩"6e[: 鰏LjM1;|UtE8l|oy$68he!๦OՙsTb0Ҁ(!G6a>1@aUQ{MvXDN$uֲ8qGOL1rOϝ?c /7>q{Xݡw_Gw3tƔL~U_UB"WӱFbDS7l>Z=.'4߳,M 䈼WVohN΍Z&1vۺ_'S}uY'}p䡍Tw}O " z*!`˷#G9$lrȚ_i3̍<UArsߪ,$+;<7:OF{^'gQ{V1qjhȥpRR@Rt pͨq/\ڭ͏Q3ZVpl*Ժ'D"9Yfy|6S0yŐe!yv6ڷgCNi>/w uYG0ngbF*Zeus n9[UY'Qԏ)Sq-:F<~^ni.]/LzÝ[ק C:F$M%^`@&a޵ܗ~x؋Ʊ1}wݧB0v~#}^=]ڋg$0_'\X.B B)(?}b_vL !dP9PmK&[s)?wP}?ZcP`uAl[aޓ6cCǤv?7;/Elp~`Y0J Uy:޻Sä23=EHEeE@c-5ήAQ>hW9bގqsoRǍ\ٶiooj M]6 6W!µ@lρ*@g:8xBTTp~r8KoSu@N9υ cAG@@GEfuur-2G/Zu=ES( \AZ:ՂE4jR8I9!KSɐVfu3R}ݳ(- !!cU0wn: Δ'Y?3*uF~ > "SbR", 2\_&&ʘG i=Д~ b}z8H7cbs*E"g2/$̵<~uT̥V'*7`#PNUAG*46vRR:YZ3x8lc KXTQɝwR?S ڠE9Nba6H,]57QVtdR]^7ܳg.؄Q.H n!C TWSРkoyx&Y垍 燎i<`jJIoڬQoDHې뀗w6MpИlgIuFn NCa@_{+x8n0HVQN̙(~w8)kJ֋kE$H%W-fi!p1޷'Ji,_Fi] g"b(Ź輒?etS U*0X||*f>" }{Pj"Γ'ViA iYIv 0ҰPWˣBQ}c7XR'7S}@I0IIУu%jj[8 FK'9,x͢$dQ2*j-…\S%6@2 Ĉ&WWB8~VL15FR-LAgs֓%`" >ʪdK[mF ҡF@&8K@S9%Tb{Uf;h1]\Ũsh_NFKc *VeNWAq1 ? k>.WoL_= cYN -!K0ϕ"(8S.kU(e&_9>m5'3EaU@IDATҜk:; b(+_;^;As{ObIESJGOa}Dc#ZZ,G*L4ts>/;U||A!ចP|MXCN)J0jz ̈jg(֗W1rhF^,;|fr,kCSr;Fh9$ұoNI r<@VՎCx_r Xk9> _)ZܾmV3/)84(Zb0jbFيp( %SIhzilp$K|iG:,/t+mwzBvtC&'O* mEB|bG E!'s&܄WnNIbm-ae^ȁQXtGN",al @\4PA!=ʇ͓IGd٫T.Iv[mhSM-.e]l!U(/ocKDUɗu+n{Hb"];WAcAJchKIs|#Ί$4y8}pj!wI%)gV9zY>'xJ u #&o~O>eGF܎+Iy&e r`?KAv(SS԰dbh$n Df^j 2:䤶_Sj:!F֘4Li.r=|2Yk5طr)Jʴ^P[ A}PzWAR}+&YjP) 2xN \|i_5y(MLy*Xn)`VY]J$IldZhEW "(gtvZ$i{ nPN.vhLQ_0f> fSl7ڢR2"\$q\3*$_M/ w{%gU qKáK_`j6 OKH+u?j4 %fQܚ^xLN bc(UYsN9CN2փn#%ˆEErMG ÈrQP]?Kx8RP rq>ہA4\q?lτ]묮*]'7 ]>%- rP^3^R^AXIm_FBcנ63*~k ?QH%4e[ƴezI1*VD <6KK,z }j~MN$+@rA!td$AHQRm;wM꟦_/Ω4]S9rF4}Ilۥ"쎄Dȩ߲?o> ?gPC/5O(cÜXGѷ=gk0Oj#xJ:ow$2wF'^Cd텅P8Lj?wx*v;hsN3wlۑ@N JΓG"#" 3-H12:O}=%=Hm⯓CH)M 83>O:TO,j;eTmMqoѫq׭ؑqѤ:`Sx#K.>B64;OHIֈ(a=t$S02VaWfh!ce9&IL{1].~5? GQ'lNuh@L?u"}2m)?u?`.3Kk9j0uC SU#ϿtB+@RXG0UAYHL0>Zo[{kdw0-{JwN MradV.sן e|N8mZGFb.8= 1J>lcCw?Eok/d1Ek+IRJfyߪFTW(.<;A提[*a?s,%ȈS %P(RH<{Qb53b~joS%vP2]@'`:ͪ+ױrk~1o3a@NVs%ޡTo?&k 5j\~n%dRkkad:OȬwb%تy#V,:1>Qh`8v%Y&aʌ~ WX(.}}uX2)jU }SJʁ$[y(MF*OY$NK!:W`p̏.lv"֙kbęFmڑdu8&C%/@nNOdrFQ`!lsMbs%ℓhڈ:RV`s_.=a O2{XIb7:gyUl`j@ Xv0[Ejj4 ^~l_tlAܖ+{QLG *tH+de?mSk9sX")j3$L=|BYh<4揯Uyٌ #Z8gE2<C>_ciژ'Vt JFî&;f[%)h.e 7LƑOo|AvЙ<$=J|@$B͝S/X>!.E҄TB4iv;RhNGFr!TK߸U8PC2)_D4ƕ xsաٌ\̯ :·RHP9 IN>?ͨz;OiÉ) ĕi~gy_|C }CQGH|lLK6mȿZO] ~M95u =@v, 9*ࣹP+>}L^NnX/dӁvߩINoH03t`{_Fɵ zI Xw"q+Ʒ2 GX1 FP;tjxvcC <ʔTNTdZx;F'ʹc$8ώ0GU9X\kq J@Vu~oA}!H5#$s"h>v4^+Tсjot1|&&8>/JJ|^KM,8hw}QaCr'abX# RVݨCQv;K  4DQFAkk!̘JTϥuơCʻF9ߐȫ7Cnqjz( ܿZ!6/\Cߩ%qKfJj ]'QX>-IaНTB_y5<{ntumQȪ?zr[·yVNO~G/)>6]&+%sݰ/ >]5*'!Y=baaBgJW}[hT R4 & ߈)*Be=s/k2Xg-֡; $`(7H02*NJf Tݿ}a cXcnը-sl/|# ݣ[բ#t@{1Ho$r] F* 4v|Xѝ<.M2 a=?r "s7ulB,zS8yK/JN=c> +F+o!!4V$7H//d1A):yl#T`RTh ;Bj)1]n3r/]yKhոk+$W=aD)g"/~2*YVa[}S:I 7O^>ia+h|c RR- aHi OtDG\|ӆ(/ B_(1Jpp!|PRύdR1ZHހEMǐV{L$BCJyz),XL9O+F/>*"&%L M!#%Uؓ_Ӻ۰dXbM5uu _6\ ;w_]rJo8HNodC|$\HDLk /kw<>O$nXtœPVX/lq/F3o:63t̸$-RC6@Vڭ(Df*3oN\g%Kb{xyL_tRH<0.﷏tnY['LLn|}:q`]O~xie_o ԴLC0)׸h`lQg}_)%ڊp/񊌎nLV0ͳξ;xnExv|Fvg/R2fNB')U1.XŹ&Wgrē 0#)dػ6tGP(YqzcG$40 r1AfBwf~t*^' GZv(ӇjTA)VY=#|F1΀&YPVȜ0GqPf(B7HTj>QĹC8LDA$g8G&e~ۥOɒcHuŤ9Yetyڲbi}cC!@QCЏRv?]TQf:~&15_aΧ&EGsjtSP +%Kv&5.@F~2YC3v p~7Lte ;v7Qor-&X4D)sv66.[!kYkc U#?I\@AV\IExt榹/ Z'3`t*Yy@M+ށHFI2Pߠ]f܈Hr:x0nz:@6ŝH*ˇ(? PEݡ.eW+湘a`}clm s=AR@q?eU"^n*i$7XsAf0_2eUV\_"U~{U?r?[uo+R1&FsX_b/Nh5, @ԌDCq%L{0I\[O'EVjI#EqN$YYW WFQT*,$WՂ)0mjCNCB@53GMd"QR,EoMv{)uT{3%BFk(pJe,:=ZSH!H&Œm??McgD.Ka]{JZvyd aC0(j33Ɩ]pr`C602z }vcQv{UC{$jMSZ+EuXQ=B| WV!lJQu.. '))AH,]"u=hfb0xs/'+u gbg0r!/ U}'b1Xf<-: )fZ^580J>=%t1gQAn?z/ݣ-G9/`1$m5`c=SQre8!tj'.JiK;|lThZ)!-Eʔgђ/HBvMV?*PM/m (([e϶c Qɷ$#˨`p*bfRV塿|4^<rTB]Odڳ4Zư;u=[s鐜jkVrӍ_nrFI3]JM 0 ld긶kڦޡҬnG% 2)tNnUm7_ MX2lm5WE:,ar+7sR+\m+!e}B=wx5u/ ~HQ9mʳHr!;Ņ )㊻UO L,7nߔ򓰌f)no$'i\>Lx7uj3ΙA'_,}fq?ԟhi-)bC+JI끾Qp(Bg`Usa7fl +n R`QXiGnCZ97H2/h-sqiXva0, J,}LEb'Sv-Wak8MΝ a$tuzWH%hu Bk1Ou/E7IUpٱ,j1Rbz n0X4emM|x]p$Lz#,4.BPP5v3dbs{}EW.mO~EWkS݆K5}P#ޣ@*E2 ʂy.gZ#"Xq d*WHpDs{@GWhZ=h33 ӠP0#LT4rP# b9֌"*a{=J2/èur 8!/0+8m^jTNMg#u1ZE+z (H'I=qgdoDK[Hӽ א;@Y3Fʅ ߀3,VMR;)&HҲْ8ot\;/iR4z>C !ނ|hR"-.h\dυ&^hw:ьrJ1Y֑XP!G1X@ r4h$ ΍޴K8NX6=IMi<َ&CΚZJX"h,i!mar^.:' [jܤIf ^7Nu.\jp95'^ ޓ$x"ﮨ3mcB(}k ]=Z#Sj7U\zEL>A.l]5~!uVZ MŕS^KprHU-=P:(j0=FpAO8Xnd8FJA?~0m^O:4I E<9 S2)jԕqÉs%?/v "Y\g荆w:La M: Nk15ɚ.p:l&x g6Z\_PL>XEJBjiw(y8 I⾠JbdJ%dIܙ(g8#'=a:x D(vU|23|Ո4G{QMfw)HaNK sW=Pۺ)g/)0TT gsHke|m-Hd%)x)rAٿ3t8X N{,RKd9S7RZM۱0-¦6adZptà:7H*RŶru蕗Wޡv-"Lc6ғ]GsU8@ÎfX')[fMhw2c!ThWF C@i%O쮊.w+9 ؈Rw'vn&x BmV0"?;zD%ҌVO2U4#)׿nSn^e}5ê)*2ik" xG o[gÍȈ z[&֢iq JZ^JSK1l`)7<2 tjO$m2Zrno 裠0+A/~Kcur< HEz $X1lINj`f 6 ).N-WdidI@,e6L@cWo|U0q qoc~ڤTJʺ w)hr2zNdhѓ-YG!m Qu}ёI5O ͍%ݹ^j˞܁[jE qsIxq[q~tH_pD- !`Ǻ9_ `sb-#srBRu,+H(F7AS/ 'WtU exEʣҜNzVmݮ:ONa%aŬ27% SmZq8ii,u!hZ5G8Nش{)d}n*h3 U.6^sIJD}s9c/uVlya1At-=K* DAG$4[W![-*,D$}bĔL wz;TYǓTSGүԐ(q_?HRYPd<:i\7f5mj9 9]IJ(JH],ؠE:E16PN1DE?_P,9),KINn}gFbrB( { g2 g7 0C{oIAapg 7/stUZ? a:y,Cg5E *t?W6͈sXt=(km!i鳾^co/ bїR&:8Gd o5U%XZ.#ǁ@/A4u#N&p/"3vroJGJ=~od_5`cRҩDB_BPC頥I]Ǩѿ!֩^J4G0H:/V& -lДGDqF$b \tB*HDN**Ϥ3\۽xxs1-gCIq6cU}H6Z-?o?Zw 3)IVcN=y O:s=P ǟ@@LO`8ҼпeK'WiÒs]Ҏ6I͢7^-QB3O: ʪ+w"k i6_RT)L8D[.6 m$XFPzqʔe Y] ;zDZlwZ9ZK'B2'%*!)Ao̅Oc9X.PH7a0wh U^WC"=EUDbM9+y0.cGifwڼHU!(ĉcɇpi xx/t7DE zq:f8H, RvvP _x_c^Ap (_};5~b5a+FR} ߊa…|% 8;I|s(3#e !D0 46ʶxEaX~.y@{ Ѓ˻a"| aV,kkQ"5p5^mElcVfW+B Sc>x]FNDٞH1,LƁE hhl翭Y\g , av!1*t^ ww{T`ݷ97y,SsaI:aNP# Ҹ_"crX~#pk6Fn =vyfE%l#Ղ4#Ğ]C4rXfJݬɌ62 9x,Prsx_W)n!JUJF;s) O#C\|Z5X BAEtO |u#glNsNYvܺ 6ʩ="V^;y0+r@ZBW ~Jng.1);D>,Akn6\[i|1 ef81N-4{2zK9Y~;) \O8R?A}}6|y8zlSiIg`5IL !E;u? yŠ=JTM[o@۝2`yRSE1ljs(]XYeǪ n#5CC؆d +hL i@8n"#Ih= ^=֑(EIH)j󟌤mɦv6Jl;%H|:Z\7Hx:`jA\UFxYdz(nΌҹETH3dʼn E;QZ^ΊufnZ sC| GAdWDi qe }qc|Saj,1fScf5X<~IFOѕ-=BQk?g.o* 3L] Vn EhnLNpٖN -KL Ȧ03̍\R~;ކAK1{4G4l (xB 8asd56קjןŬbbFT檖G Pf9B9ZLբ@,6BѤ ̢v_-h43~*u4AuN7V9hɸUDqK^bGNසŴa2ѻ%{TgG5G-ɕo @V[ڊ?2Yp # Z$;XaH6+QzG!\l1cUImhΰ92c#_;ؾb(<iè/F\l#ohTX٧÷Te!.omB2zxڌ1 }Kэ< ŖG.:it5fu=^De8jN ax~ް \%*ϲdbM9{ [wj˥1s'MQDᓓ҇Ey=<t@01WOb9^n㵭A9P '1d?măHrY<7KLNg*sc10Ҭ^`ҫeUԹq9m}_)y|]Qif6UW L*LX5n= `Ñ xc0 XoQn)iV*}f)@'ʅ1 o :/SB]vI9e0Ol\J"pjи*)S*vT((|Q*f絶ֻR3r;EW&?aEiBKCnuJ7,ZkJOjl^fEVz~L6 )nX)M >7V)DpEpx9rv-sBkӽxv9~y.=S3x(X!'l-bxV)ILpQPrHvs=q,p)|_; {"MiNA԰kbsU-D8h~g 6m/Ґ;kIK3 S'ڹ S|+o ƫ-2͕g_^x *N}޸sDvoP HB Lmeey8X%8$87)<| NYYJ{j'l^)pbA{;8(!*lQam*PDgQ"=P0#Vb~{-eT<ɽZ%<[-GT ZW)oo,zh(tiZOV[psՕyUH^yFh! z,+ ΜVƎZt#[o[2] B)jR|s4.UU"iqI=6S"7ʸIa|"1gݪ)hJņ3Jaoe/5Ej7 4 =nī-hEFQ05t{W0n@D-vn|oOH7[kNJ@!~߳~IkyzLꡞJՋ )ƙ.ZݻcoN<ʞ9ې},@⮫TI!FR)Jjssimt9se*cw5n {CBcz@ C"wIXH (\krڙQnٟKt@G.s|uA>("1'J d/N9(8Iĸ#![-VCȤc=JD~."T3N4-TQ¬L*^Ho1YDQ E-z[yjk gFU]5 v*> ~)u-<\0D f:^3>@F us&E ER_:[$LU9I.]k&IUp`,ug.E5yQ!n MR74;IТÒ}6iiHɳYM<\q`pVc9=pja, ☏PtjUIqb8:;d`%bDͩ6bĄ)kELXIkcB2 49'`߭\ qxLL(=5.|@Pݠ>v(d8Qa( ؎쒉wm4FK9T\vBs$A6_kٙ0 m~ˬK `xԱs -fa{(- S(f Q2V,%rbe˙G(=RA277H]S ~t q3 @1L|3Ȓ၎(2F=átC}MJ`᫒Ը!R܄> x@us  YVy0=Wngk{GhD5Wf~ÍP6X6SêfNιr+w@P»d +́7{`Zj[C0o0fT3k48QNUI.݈/;dROGHϘ3sW}eY+'4)iP# YZk0*v%tQ~d/#,"~%"-\~zdvjm-KݾmZ^8*HC+IP&OklbZjR DﶞP $gv&99^\8mT4ŶB{tGޗ5]&(lk&!P;{-6D@O$03[jtpB.&r>9!K[9Y\8t´O`bB'STEG Qc,G"{G':\q3i=sǮ/Y3QX.tiYY<[vcoG-Ƀ1 :&8:2"O/!2x8ү&+ D'$,J޲ZJR+fG*B]Vl%R*@%5*'E4@Ͻ>){̣p5|Nx6E-,UɄZ$ўxcr%W"p,ZXDžOtNߑ#U"̳; #Fae#޷,(l%9/==m\~"%w)[*hL˾ݻ%CksY#T%43w+e;*:*J"X!-EHՄ|~n6lgːf+< ؂iGFO5PQLJ,<lvz'/5E<H@ӧ[K|aNJ)K 6'ePz\]Qٹ1d֤qHcŶX/DٰXBtPCa/O^)B^%7HtG5Md]]ӄq[FAs~!=4 & ѳ3¸$t BjF b8&p˴yY4S0QSq5 *4}qa1!j^X}Ϸ <00yd~Y`=ſ_\pW@ba{ z>`IlzH!ov浢H6y >)ͺԼ:^\]j Z_B|@шB Ê="h2A1ˠY][Q E$RΎglJ=d`w1P>1;|Ƒ{ Щ3m+2,9~ /6lU 6/T+EE !W%ϾwQ+ZSkZ=ӐYfe-&0 885f.چ+_H}Nj2T ) 鄨*28i?cge MT{_ z32>g=hY9mEPt/4f{#k@f1c²VUlhV׎ox>^D3RV襴Rh˙JѺN#VF>]O/ȦHp$[7U3muĨ_E_9VuKP@Iz6CRC 6UqgeVЏB>'Ym)NwP[}\,X4ڢm\Dqc? =VhC(D ]-ѓH2t?F$׽:s4ڢ?҃Cnqdշ Sq CGW/{MCdMWa m/c,;z(=,-A7*Lm F:Fw~eyWhޠu_vȁ牜˙5C*+kHzFhdJ7)x XlR+0YjcyK*k`ʰUU'D/.YلD`f !r?C >ui Bj)pJ _]Eoe1[]W9k^=m|P %Yߋ[U8蚋r8JV0W@+]25{šf8ArzVtKʌWSaI"Y,t0Ā!S!H@=dqHSIicPc3 Y ?Z8lv_Y_D|L#i;);Yda21fy,]vqg?1lIsY3#Dv(6q F55r7␲D6(>0t]ܣخ>nj CE'aXhwTaqV4 Uf:*[_.) *n3ٰSc(,\ik`b,[AXjE ՛@{UT6kt;[7Eh-O,W5!qH3ޜBgۢ7]&T HPܻ^OV/ے*bG)fK2^{B& yi,Vag ΖkAoWOOoYGx <~[^[u!EYfE#-<%&(7-~R\鸝 z&fQo]^&U#X(=f˶vk r*rݖ5+%bhy٫~cBߺw%DX_&طTIp{2,)qȺed\c$fbߗn'~&`*-lQY%aGyr*`ZQl)H`6@` 6Z'??^Mt{"ݳN(f޽Պ*ÎhGpk=Sx="jg=RiF-*ՇN=v4 B^I@llH=7s%nf)h+YS!q^C/75F8cyB8/W, }ck W2]Mݓc+,ٷ l̀wϸ@U`J:,j(W{ֳgL9t"+- .a) 39 U^]~WěarEq!a!SEE4`Q4yB } z!4x_fP((?R<=b| ٌRȑ igj%=2|Gu&>heOaxRĠ}3[C ZD9z0C xM  3fE'M aUR젵74?;3 ˄&sV=K: Pq}sI6*YP4&ao(Noxλ(bkyF5a0:[5OYC'BP,w$֌/A%{ܙp!ע̛:kELjVNZb TMy;QE6"~ ԃaMr xcBBҲ坑u81lAs=p +$fx*ӐlV^4 +sZ7SXul<,;?kO̮ūsIζI4o8F0<Ie࠿,o 0'ASnN@:*cU*紅Bə7נFbDz?Ϗ y@>3_omSeȂ^.O_,Ƅ9g6b&ĕ᫥ :O'[wfޏ%Pe,r0)'3$UktHB@:55{ q4Ed~JِFExk5!6?.aSN8~/.( 4( p$;QS00f6hh_COhtWVa )|&_Ԅ^4n=p1R0ӈJvT@@=LhKͤZ RQ0ʠKP,ku%=٪&m֜8dJySKҠ^f= *QΓ"V1EAf>6ϣL [LNc9Y- aco2/1 J{ **1}۠Ue.>f%4@J XR3:IM*\s(\6bJ3zAuUQtC M#L #>zFaʇ- | Pp _  "a&LR2F G5w ^rs s*=@XO {QM_CH(%}ϏW8@mMu>`zҜD(AV\m _ *?!mv8*=fIٷ9)'[C#'#i܍g vݷt8VFƧrBp5^ZmsF~!\*SX)\0|US0[6;2}c*q? [nբNwx-"8t\k2՝e$J.yni7 QL,Z}XraV0q1[WG 0$uN,w@.;^H8A`?04Moh`N&r)쓲vH`$n>.9qMl E]CDi_@ ΫD ϓ%~q~[)<`;J|e0W 5yjK)&W `6L@-ti%-1om6Y]~$}.%uqk(@ >G۸5PchSbŨuWBۊKg(LJTTa؋18&4DvƱ3Nmķ|yvm+*XUmU5[G4]f.,DGxYs?X7<ܐPEalGK*l{>UؠF:Sg 2T[J.OwI/Z0~\:ȖRHbivebT[YS6eo83¬~KPċ!z%($t kd4S7U%|wOc+/ 1LGJ6u/Ttm pϓrSZX)3IAr)6P4BH6ʪ*>R0G0/J<0Dd~E%%_q9f%]qm,`r ~XދU""PRJl׭c.#P.Le/T4QW,m8'251tA!A'j%za= LusA5kHɁD'T*@)=c8v *Ȇ1F&>#No̻TRohj5& þJ0t{5 L &)&cGY#.`k‚ɉ<놾!4k<-7VUnI#%Tףhy3!U nLD>ܿ|:36bwD&S!̋ukJ8JL-f:~Dm{QzTA-xVf޵}k;a23 ;O}UCE]th fwZ*dž>M0Vxyj9( y qb=np)H};KML$4*|ɦE"3VxJG=5Ndj`H1 OSg!%Tg)đgڐPxTYY v%GAXaJ49њRc| s5R4G>8PTְ^QC`]Xmڥ&qݝZ,v{@#tz=b9QJBb24Ty1}6RMM0bv?R(ۛqZo`cΨs "PDvz0CR۱$=4-Xwkfum0 # \,1UDFkmLZH޷TŮSg@ .gfr ྐDAPwг)pԄF> w\u SOՆ7~:O1QXk'$+6\ɋ_o`(wI AVֽG:" P$[KOf'X>alˤ(tn:s̈́}x2uV*KKb,ћk#y"RP`U &JH#hA:oXuRV(Z1Mbh%J8&l}ذZm1!1% y2o$aJEG}(Z> Ű{y7W ֊+u?fzkn 1GIENAëߦ4E惭8]OyK`&2jH`B 9bC2jQdĺآtyD'$Qm1Ԑ/ UTfmJHʘz՚7g.ɶ38mzIH =Sˬ_:Fc^C}$ | cX4"eV`4'} 4-)0 /Q{+%,:B =AgboB9\۬y*?'\qXϿAތJ@@F;1jKn$,lcV;ͨbvꢽ"bdpgR=olu!aNW~Y;ɧ#|1g*#J2]£A/1=ls0dat r԰OHAPW`Qf Z(#^XL"ѢƋfƍ J+= %86\] P8L'YLli\aISR盧x yTdF@IDATa=2CkVk,]ÁD7Jd 9nS(/&(Cd3=+׺>)u]$x鱮{ߝd ִoA`mEGh ?GcLDa "lmYxvY1[rGT5Ve:{By_C&>l 'VL:5@}QȈ!) f3_F!d΋X>[ۡEB_?m&=L$ԨլBޣ֋#W-ȫ +0{)Jƫ)MdͭݪHGPh-3C j޿ mFu!7:*51m*hV1mL%bs[[WP]Gu(9 Pa4 )4N~lW߿lܥFݖp9)];U \Պ M捽Jfh|kՊdUjm\S63wYe[x?Qmk p:?Fl-$(#D=RaXCU8䰥o/f7PSU#RAhX=:፠:;?.[[$_3eRT¯ص䌸3|oPpOĠ1J8F+o}phamg!^mrzƔBg@?)*QnLA߲ШR@frjU#XVop+?x[w0*zVVT̙3!Z#q~tzh)\x8e %Mv>28,- WֳP#X%O=DP}azgIw8WpwTA:QA?wMR{~>f ( Ćw$#411ZiXL t %iy 4[H;NmQshw/AUKn Gz2NEfR T~S3:+UEknΑ]a^hU 3Nv:`𱺮vox W_ʹyTQKlX#_]qпKݣuK vi.>}>a)}yNS*{&x}FPgm%@VLB%R)PLL,FT2^gғslգ[ۭ+L T$1VU@04kZmFւW,`!hFlk[2@*,֗sec>ڭ~VLao)1dHvs `+n#U]s4-/ A]=Z8'`P!  ؼp-MgX8X= J逬bĉAԣST+M^]/HVsbƹN? KBee (?Wayv* $^p4@si#2^«e&@MNlg{\Lʉ:RiZk _&dNygjb^HMѥ~90*GoDҶ>ñt8Mh@z:# e-s P<1[+ 3[.t)[=/{rlԩY42qƪw IAG*=_`A;Eؽ~|0@M:R\yő/d' Z7imE+fxɢû!m*gb,=]a".,1ÿ#&aZC@ayfjbbqBSۦ#_t%dC8(V= dJKDɏ5H^}B<ץ'}Cl܀:J-t! Іpd!'B yX: > ,nFciE׏.*tQΏץ[] =0GGJe?{gmw7PȘFX Goq谫+nf=x԰Sab;K`GGUf@LKΣ%jOj`dF8ZlR=FmV n^~?wiqr[6_<6m)qPO=a/Zl[恸k#tdtX@b8̚TZ Zu1q]E72Pf_} UPEp9VwS(uNq_POV. OK[!uWoJAdAV1S3PF`zVLHt| {/M6Di ǧ~$ j}V8TVk۬&Kʛ{my~,m]q*,Y0  +ӆ {Y޸vW\z$K54X Tofdb֪eᴴtFl] P1B :>BZ@_b+-%MIFwzoX*o=^V4y+[՛2ڠgSߧ @΀4^V0$RPqڢ I40WŸI5#?42T40h>tT)Wq}EaH4 T_eQѰ`6lW䂬#A1}08+"Lx<` D pn;ߚWsgbN*TmUoa=/:}‚I, !|V7pT h5~ɑ*>;6psQzpS{vJ;LW JՏ3]_J\a*$R"T" 2kYϘfî-Pf# y8>tժ J p Fa'6FPƔwhb녘Uhx 21e|I*M;r3CazN$:vgOzsSְu.%깤T3ihe?S\P8;!\>=`׵ڇ" ԍ-/]Я"e&to!7DteN ]& ׆ uvo, C+i_2R*Gs; bp œyWZ !8&aD.xxؙG׀k{;zB ;.G s>u$L`QH#FʆJ.+oD?.TQYg'| ݣE UpSN"SS$C|U4̃/&&18B64yo%^] aͨ|6@@\ Y$CD C|&4o<2&_#] q,(L ӁFψHibE}#xLU1ߊJ"57wLDXTd[,:HQK)9J}{‚cq 4j`ƨ _Ƣ.YkoE)Aݢv uu}mHI ?-2ㇱlht,hޭ/<4{uLʌ'KL,y;/Q)C⋡}a>a ڶii [GRVijkzvn8x<9?]As'"J]3ÞP47x:Q V䑿ۮܬ/Ze))c|Gca5oP~?m@#`'U>ݴ!=|?wW OhRv!~ zA֔ͣԁ`qSOJrFnqc~ѹf.|@;S!~}ڦ־Jt5*<4=(XN,=FƄOΞ~ wKR6!EeuM:ڛXxc)JM\SW*4Vu7fWnջxw˲TX鈧դP ED6;װ{VH.Ɉ.kmե`%yР I 0FF]BE'P2UINvdH=7?2=u^h@Ad ؐY)~5?K&8 O`UEe{ 8-nў]X/Z-ɯzoY@4 xƨX ^-lf)eʾ, @BiӲ0w% Ws EJqז1<& -څ67

    }Pk)+ -:&9n JM#ȣ( 0YDשPitd8SxA1_vK҅+0 Lc<#:Gƫqnٞԫ3V >7!F+VzɺE!{0r`[l$ߴ}2%Ctիb&]imX*`beAĔ3&LxNҲ9keV JNـ6'-f#+ )i>` 5āc,H2P& a:89ufNJQ?<7!i|M@~|pf) Vʘ!*Q(x-VfgKy?$Kpֈ<"ah[ #!DM*.Z@RWԵ*$8Ҽ9! gӛSq]v~0=}GNe#Q2_Ŧ3ovNj4}0 $_ 7$mkQ\oo9`DMd$xO,#37+ oֳ%fXǥZZݟɎFMI$ o7v&H/`vRi@ufC%o4BC84@T (Ea\a,v3m Q Dmu}ef $'gZ›fE0[b+HY-xW RĹ5 4I {%|z Dh)j=QwlPƩ|&ZcApi@\GC}N[vo!gNMĆ{`~WO Mb{ Yɜ UgX0t A<. W0 sCpmo-$`Da9T(8!"zov]SDhh,D|zр^ХWydh.g* _1uɣԶ> i,esJDe :q"HBPD_;aҐR:57edboK?Ac͔/cg1{sRٌRl܎6zD T8]!t}ҫ{ ^"ìSd5쭿D{0476zݑ}˞t`1sHWHR bJP|`gy"]kE?daӶ*7G wU]#SYJZ=h,9taIR) =}ζb7F=$s32ڊ,0`Rx]yN\.Clvᆠq T)t#`%'BNɿң!{ ;L6?- v0kcR \V>u'q"*">8l)~Qtx NτA-kwh]҈l̩ BzcIDV omf]3: WLȚkQ]Fosj'zf^"8zI%#p=t$ߚ'6@Œ{7h `tGI"D ܐy8<4lզ.[۪ەΎ+JJVkrx9 br ǹK4#^CT5( ՓhaWJsCNP6Y ur A.x-,[P:Mo"U&*7eQH2eE*98<[b{_úf-ߞq/*h2qM/ UŽEG1TڄH r'Y `yV}w: P' lpE~覑Ϛ|A-W3]9dQZppx9v@vyb68D9" LetN#}Kq ϱӌl4eN3 G0Pnȧ >J{BF[2 S1! D0k쬇P;־%#9U@:C#]b4G5kTl04 po?I$5YzsΌЬ=<@hC۱:g4[|D\މ:*sf>Vӵ2tꐼ)@yh7O潸% 9DKwB]H rT~%UVdCQ}EMtWqfYJ<`{BW3r[5 ]q2FyƝp]su:%fWXԹ + f؀'V Pq!|X@ (X[ҫ#w>]%Mb *6rC"z¯Ne]KDFy‚buwg8~I(FGMY>:L|hfa0M|$6#H#n}ŏe?LjI(rM@3ϗB=}i-X)dW ;o}~gSrG]]\HHy&eC4xd<#aXjخ r>8 Nk_O]Hu bky0F^(3"6= ME㧀+-Bu(a_kxmɵ_iUXc#Չ-+" N{irLɪk6^[Rx [*>@v8BLw {y2,Ph|gu&%A8bsbᩓ|4,hZE )yg׌&dp޾ h|4"K դ4xV,dw HфyL}G<ʨJSP5// B2/Ǻȧh ڀ?cX򏹃T{ 75K Ɣج=6f&@.vbnj/."jU& H<{ HE{0@Ҥi<4OW0e`60kN/|hE7Y.=5~vc "V>C+h0vB'L\Ռ`)gMukHe؁r P8Ӭ5y,X  \Vs|B% ŁEEaAͷ\E3yʍ]0eNlriK4ZNVE)Bl5LѝHd\N˰z|8Clb CU퐈fd=P,AR7G x}rEzc; / ɍ -:͡ 0]V %Lj]h%1Ū7Զuv4z<˔5|ҍج &Hآ>1֨ޒ_RĚeޱ'J,H+pJj*/f>5t"f%Y2&ڙmv>r]Q 定Xa; W1vF DOpr8Mt7<T:rmZP!jaXk:ޒ--lP^*tD.4Mѹ8ΒoE5\~Yk=  \r6 nV R:2Q0KY[Ūkm`#> $Nˠ:U})Y +Φ\ Sz5?yŧ(uQ!zHNŒPS1Г/o95xV YK涄ϜcmG$Q|SS8`FA}*|됻y%Wɢs.˿I 5$\fpKD~! k' 3r1lE$!2Iau7Pfߤ9#va&=L&qŽU_7/ǫ ,6QU伵=#N"0r'>5J' Cp'4ʳUUW)|5Hк9{HB89#@ǩu[07v^(i< &1i8k>I&ή9Ga\\)̡T8 ⚫iN\0:nf4RK \GG C|VuR=Tr>iuR 1Wblpvy;yg,K5w7? ud㟫qc-99]$s%`{Fn<6^0-|/nP'ܰZmg U_]BZjdQwjVeTj Ɩ%eM\OSyPfr}hq"BB)HAspxA/0Y؄ۆi(!5b9[Z6z~%d WNJ.Cϐ`$_E0]Zae~Zb(yOd ܩxIqѧ,mf@*QI;^xF8"ȑG|R_L6:Y闊 ፞A43+)$znk;1*T7sL4q$,7roGE4gpĶ$Xk7A$O+b?0[ -5[MMϔF #Z ij RtA aifB/5a;#2rΆaV0|~z S7GPV(EnN#԰bQ>xK9#H<R]Ti#ߗ:?Q <0/ d׼L-#CT@W8bIQm1XZk(nWBd M*|B-3Ϟ$'%ȭ=ahX}ڂP\,Ln_T{܋'2W4VR507Qa,b<9-DZ{m;X.W҇ 5 כu+,aaî Y[ceg˭ `x@ۀ@8,VxӆXڤ]tƩl3NX]gp;J:B7nT e-7%w!@cmbf|=uz27mK2=IߚEa!ơ~b*>&i2)2޸$';{ŴBm7Ҡlv̱$ڵ jnO 񺠁tJh+@*eR.,3zIr()_k-sb#޽Nl$66Y4`(DZH`WbCSI҈H!XzKh6!@Z1(=)JK]62ԙ\A]DUs˹95kkGI,rVf%7iOr&9 e"i6}Th,GI2$< 8[8 ӆ_aUsn;4h.m=p*-Ve:kh]:Ǥ4gh_%hoqߖ60 Ak$aXcOMdV(O j "W Dz:~3x;mhۃZTT5VzYM:4CrrB<"Oj.qVx7ƙ ^#@zxᄀYn>hOr*1tUP6Y抧ߑ zx=bvNǏv;2%f8[ աS|!w jt d, tܘ*rUp({uNGOS)UcNXNcW;1n4KN+R9"ZW>f ZTM۲ɽjM`QO  ?˂ 0a&mW%%9=l-Waf 5ƶ.  Gq5\_{},E朮S8)-{ @¯u 5Xq&GHV_kU,cUYb!Y= E4tNvB-0tMrLudyU3i;(M d`^gĘfNjMH_F+< ЫvW/Bhi .~y@ 4JG%1VB0߲lS\ôxEI*s˨ӭn].+ lP wdvshȮZB(qY$xDmYVQELUοږ(y}lhjz\X/vstlwP")HeN1Lax能F! &wDdmҧPWw /)SUm,),sWCpWJyT k<51IE職n [[НuTX@ 9 LaeAީ 4!S7 ŸTg'bŦ0uQ k\)6h^oak<^2,+yذ|H `B$] \G+p@~?Gƿ]ȥS=N<qMLr"p,JZULV&n[ZMk_\%yiQ- "X#{W8}$L7jX8iFl90Bչ8hvy?,HCB4*<[O_4u>F珨ThxZGPD01"ia?7((͎|lg8Q[_zq=l5m -rG1Ac7FMfQ;l6^X`1Wj<c Vi"Y`BY,Y])XA"rH8gF$E>+_4N'(5a$Rrb!DԪ+k^/”!:t$3Ќ*Fsԣ+ᜱ,%|cwhN/k@gPH(LI{wB=0Qt xCf,: \6^hu,L[\z{Sq2jRef,SVA S*sO3QI (L GmO\kW%s%NIDAT{4"?8D F+lb_qi#;;4 Ƹ(jKCqubY\77h Eҋf"Kڤ~0 y`.Xi5f{@U7.š1E*VVєXZ}dEbnΦ%lY[I!Znq3[X{s4(wlP/ 3 dc3mU:,VT9-{-l~'Pnz^ot ߭뿘dWWXUXlK<נCMt:,Re\ZiI 0? s"Jם'ܚsIOWϕ v'#m5O{c5ȕs"eGQb3JDjuGxNMỹCIo*ZqDzK)/t1'F(cx*d `* /f)2q\`&Hի^f;4(U >glKL=BTIW*?r@P*ZK#~CL' A02֟.斺 eu%|^G:=0$ +eFŏ'@-#?N$ :<@՚ EbN#0/%JTPssOT:' Rpw&?e92 ]2_d}D_.1ڠaDx#L\?Y2iPHm5dWX%L"֮!q|Pgu</(.'8\]/e^1!SV" @t^2fnO-VWM&ǁ!eL@{Kp%G|g3~`)q/u3Gb j5 3F9_xVdjf } Fk/_~ç}2rsQ–nLq9ߕÜyd^F_[FWkYj :\㫗*jC ԝIOiGV^Ph&KT0MyNY*a$h5>p/[DϪ*!%8@TʱѐPهtQT gx%劫3bk\Ζ}/PA5.4̾Py?M_*ȃDP3A={Mej4*/Q4|ߐHҼ D`ߊ~$WXIo?PU~$-'1<)gIf|\%fRD7CybcȮY%HmAB$jhW4_@Q  !&ZFo<2Q5AΡ.>w'Gd_f-#/p bf$V_ bAW5m}ָ჉r||sՕPnE?UuGo[ ;9): 9Xnmsv+MӢR&_jXox\;7''VpmaZz'Uԩͯi۔a`cI.l%̬ zX/m$.Ts$?so$o ⢘%遌p}q `,q$0Nz!mFBcia9*̌L")N99i(CV  5<$εОj_Aj znu*F4c$+o]"*1'z-Ϙ_;8sqr۲8>@Al{T0fvaAKG`'8qmll$[K-,Ďy`\Cd1sATr~ A;@Kk=r p闅kr&ejpCdfBٹG:ڰJV >°C{sJRQCOɻEJC^^gz.Q+;~`$I'>`x)==h.28=/}_le AHnt R+GGeT 3n9\3/D1rW~ymhPkh50DLrV8auQYV0M+% p8m0`l x|7 V<6n'gφ+W-N.>Jj\ #ⓀBis_9-QI7]m'`&keћ0"9[2^ndW9হ-FnV2X*' ˏ0Eb{χMݍG Ю%Ԫq A[ 2 `OWy t0Xё:c BiQpV`\ Hbp^ƒ)pRy%1Მ 4eXM7N"D#mupp=k Fؚ7nWsl@]:! _IxwlwKmmöj~szrUBv`Ȝn fyQibk1JyÐZN:-/P/8WwcF!Nj4]M_7MLLԒb*t<~a ,yJ)6ʈ7Y.Ǿ7Ic\hu@0T8FG8^~#%QK6T:e}zϋR TT2 C\Z?ڀ%~\r%N`,8ӹʊYd˯XCkB:wc٣,Hg27VH1Zv䠔;Rm }nE-T =:z DKoN Vbk̙+R6㋶)-N=m,Gψ1ġ*'3|$ 1*BFh (h q;k8ĈwhXL\>r@Iܠxy5djGUF},SK*\7Xѣ f(r['gH^Q6VM5U`N,aյm*ԿL_L Q ] q@seAt53Ske7sg ۧE|p=AF2 |rn{!2dyMVyodZN^\m0!@]c@vDUmЄI 9OyU[l&YlP t@`u7U2[64I}pΐlh"Oe%N!ZKx*${kͼ7&vInp[W"R.Ђcy+ƄJev@Jq82C`75hlKVnbT.شU[w~]Eص Ps\G]:KA 4JW׾Z#IxgFxM:mU du j l;Do3Xbl~EF(ߔ3!6GGLJ BLumA"aP4CH*.m/\3c8?Zռ}rWOX! :M2h0˔H0h̨FWiO{/YɃ|G9gR[`De b9|W˷ j,NN6p\˶T+r< G1NS @ճ1 3OVؗn5-+pP6.QٜHAPY' rxhfpF} u>$@y͖`"ǐ8]2Gȯm8J*uxj]&$*/?0O Ga ʈ?j&9v;VL%wa_=hı>Wq',*&v2N{"V" /φm{lj 8N}{ai>e2Vdsޔԃ倇9ssU-> 3A24Y1P5 Qwh.w=^1X۝>ÀFٰq:gD`"=:ۄf)-=(f D~t3ȘbZu@Y7BgT9A T+7s\v@H|(y4 eR;!gn }4"CbgGb%߫47kes_á ^8 \vRֲF6FUp% H-"KoI! NozME@fj$3>}+r?0BE%HtD{ck#H{I Jݧ Sb*z >Iy z;R1;L3s5•>2ZZGV'kFAcx0$|Ìe(#eO`t#aLw%1qq?GU@WVGڢbfq,Зk0[=_"C M9P31KHcG5֐x0vh(RmX'd1#0$+!ݡwutC 7.r5YqwA0;Ae\לa RЇ##>J}{2h61]o`mw6}Bd9˫CN Le Ql 3jF74(6K~3ύ񕶟qxb?ݪybUrJ0b@w͌¥Djyu+`b064#2D&a1$[ɑ.bG3bĨިlH"ςIa7qQPCu_1&t2y 9@E'9{ I49J %Ap鱞y؁KdN$?_y=%n\DtW@%0_e(~[E1(毣YkѦ5b(/3,^4 A4{7Z č&`چʲfw,^ThJ"4^38 ƒ&pнDø0BQfv;%zBҰjm֨RÓUm00 g2EЂɽT`nc 6=s1`3֍ ƈ"#pX֧tX#Y{LaQGGZ iBCU/Y3T)5c;`f,dQf\숉ua<-%ߔm;:5U/BG*\nȧ#0BAުqZRq\L."Tb֗Ϗ/Π E׬Iuꎰ7Pi(о]A[Qdޝ^h![CxI]8`&$al %DMDY=89b@X3 7cY"dxf'0+EAK=}a Krc#|FǬ:֑0 C?l]I&P<;BbmP5"Cce̬SAc{27[z%V HoJ(:qg :u8vp}Ydu?V Cb0=x{lu@Mn6`k#0eQێ"P2B*$}U 䜩 c-O&s~!xE  6Ytɖ# ߸ưM] 9LtFr;>r{'KpI9ߴKInV!(in9k @8Q#cp$&5MMN[diMG id{&vS;1Jb&CՑ*^m,tRR!Pj!ИVF"XHߨ/y.aPEdȗzo Cj(QbT̖}<)#XB@c [ZvYF+`*1>ɢNeX4%>2g67GA& p9Z5'Ȱ/~":޾Hi*,dJi28]tnR D ՂFVeZ:cVc{Py!BHR4jQKӧ!4P; pmiIn?14RoX,?\>Z'>Wd#t .3LXgҝ?$ 2eL=e14մbfos(CQ/]7ք.C|=:"&F"o$v}H+e E&Ҫ9êu4Hj9A$ZQd C}'&ȑ'3Ƒs^~w"82BK-3Lm[bd/#$%[|+c zdәvx8m`7&O| iAXH S=A>{{%F辋> hӫ=anzұ  `,) l건~P^/WH|p( Hf z#8M`|k+_-ZƾpA76oݓgNHBɆ! |=%H5ComCngȚ,Mrv`<7p@M%glK9`§dN@ [8 %, mVU XG3v:ߌ@Q'E ~lJX 8':,%U+ce1bW_:~C&&TFo:;u5fHZ)NIE|{[(ׄ#D8^oXٕШcJB rlz l͌(|Uu355cW7IAhȀvc{^!:D=0ڙn_`Ss>vtf%8a,wR???֐\Oj-s? ~PS ԬIPUw(m\PwfBTէZ4t "hNYBf0R{>1fZo Rgf5jN2^;]m3YTvT0$$^^-4HVA:If^Q .5kpx<SCm {jx0I'6$W sj)&ڪrz%8?y䫞PÑ˵ a6*L@޿#Zrn33=׋q|`z[pt O-Ql07?"@ & f mC`Po]溟/ ԾEh;gX^RՎE`` <<1 ؍ٵF N5g;ZWsuAon$ܻ:Dx=G 7. /:,ц* ?kR=f>C7(h\M7flVmqX.U㯜3$p֪K,ٞZ礡WQW&~#k8ǞǢl x{i,4pLqp3,t{[LL+C1݄f$3l  TgޠXqtH؎# Pn7޲u+ 5Waf?3j8{usmcgܦXTJé>*(7 5+=WsOo_buV'][Tm^MV5ioǚa'{@@VbU;3D;ϭfP;(3[}Fqbg/|\ 6Nf {f6Ա]JY8i jSuƜB]eCFB]t<7Iu˔ݛZzvհAc2gc o!t6as> H52UcලfþU z[`;Iiŵ Ibk# p:ӧuMᶬX gLmk/V*1h#TXY=k:٨'-CAuT Y><5C{% 9 t3\o֔E+GO!#71 jR炵*=$yfm5d$AW$dGڇ3ߞ {h" 3݄u͚W*T0_ָ T}X)p0BY/v$:}Ckz=+K vkI|`p$ 2bgh+Uw\_!-c)C@Z%:ZOKR1ϰii5;[59; t)RS@mw)ǼA;+R&Q^QS\ W#S,&o~>\yd惂Wg>wO݂`DFAy7|֥R[{2Q` t(GLDRyG3C!iɀ'/5'l=_:QC:CD#L!^_Bb mdMg@$(f1ӃidGo ( |3 `D7`a%. s>)ff囵rmQv]erڛw E_v6ɉ۸vk2Dx^-yoWUcP ț Cj󠑄_͘TԞHeYR^glo a T>k-{@3\*jFݢ&Q?ƹ&fȵQy7sP^zϸcZOͅS(nyd}ݢm@Sx?{ 2a#:rcQHΞW,rnMȬyMnU>ce/Lp NBfPrn}ͅÖ٤꠪[ƄIL!ڼM0QC`'˾yD6ve}}6N087 1嫪CGSRaWޝtmo"+f א5R>$\I=~ vHYAuKӇު}RB[*Mo^塙V\示yolrʨ+ QfPP~M{5l>#V~{cꎳ$,]k Sa22u3&y&PiV\B0xD)h5sa2> @9B}Dn @$$aS|%@LJg4x|z-^SC<@ AɉTt[riTbuF ץU~AP0!F|hf0&f >ޫ65_Bϱ"-F㫫J<)}ل+?w\VRұm8\Lۋ\:UQꖖ^߅_ [䯞>x6ȰŅj(\%>L">oJBvsdgZ r٣@m ެOe?-dg0FQqۅWMQR-W8_!,*ƒJD0/sȕ/FxO0jqJzUx5/o W9W@ߞ^*L

    ny s!̢9w ig=v]W0apƩ+Sj5ij@.5\cC)XiPԬMImY۷O>E"寈tb 1˾: V&-O/$ xpIn <fC0X\Ky~;D2D ;BR!|3`  ^KpPi ⊨q v|c.` a ȱ౲nf&[e{j~Pkp r%7{Ux?>I8V[9JvhcNS~<*Sn=syȠ+U Dsz]j338Ջ!カ/_|b=W y,ɩLgh~M*=MtQJARcdLi" 6 ___$  ,]>Ut+ =ꇷk.ɽ^%*/H~onY:idT2>+3GD[3%_a Ϋ"SեLQA<n^ :AHRx0n yW.YKH  +)|ig7GzR}+%*yTUPi %dse{RRQ5&C)Bs ^{+Q=ҭm2>+3wvY?JO %e8'Uƃ~w 4DG MljљAȄr:9Uԕ*\Oi} >ZsOW&Oܲy[ pյw?zZVMgbuz S;UԻGCHÓ;w'I˴wfQf7[-3Hds 'χ'žWTPBB٤(U;)68bGQoҾn“v]eʫw!+̧V4!Q߬#._*wyNioE/IKK^]?V&E^%BUj߹UoJw|>dv%Tꟴ=y"!; isC6U"}8ePYT:JzPӭ'6[*kJ @$>D @0 UЬβgK@0,& `#T,}WOtQt\ @0HNWԏ EHwc M&r WS@\u m  U7^p{,mm7C]2B4##p=j\2;cAp'OJJTlPBJ!S/) /!:*%8%uG-ոհnCqӐDe$KHR8KHS5HԖ`S ]9#uyNFxt0%KH y*U%H1ˬg*cR۷4_`X}Le\8}tUno/IiЌ1(مyikemU|x{b=S]J3<$Y[5,l/Q&jF8s:N%Mg){[o9.`JNf "=D!% eđ=< ³qBmأ%eQURKC 0~ѤUOU _4y%-Q)!GsGT+AÆBlvvVW,y.7T1#kwN# OD&~3!©@0|*~8~gsU`9GLH -5e !JR9ń=moHޢ]|wg%k^ɨ}$ )ӱ?7Af|8s.)@0 `xL0xy\ 悎CwL<e'T`sƧ xff𮉵j@[Rn:޸t|tѫxlñ(C^#y%w< f{^M|xVf _=v^ O)dlH +> =pvŌ&2gPS$؞reI) 3nC+Oh謕  Bdp Umk]R9 3h~ƼC9 iz˓}EYK,}L^5 >.~f&}4 ̠WSHFUmM2 kηCfE`~0ʤiOjˣY<V!k|"!{ʁ|zT < o093xYG0S<Uޮ6 7Hzauz.eǽ<{ /Պa 5/!9dV5P ` @0 ` @0 ` @0 ` ޒwdIENDB`scikit-image-0.9.3/skimage/data/bw_text_skeleton.npy000066400000000000000000005176041223313777300225570ustar00rootroot00000000000000NUMPYF{'descr': '|u1', 'fortran_order': False, 'shape': (333, 516), } scikit-image-0.9.3/skimage/data/camera.png000066400000000000000000003370641223313777300204050ustar00rootroot00000000000000PNG  IHDR& pHYs   cHRMz%u0`:o_FIDATxڔgq{sOY (84|7ט2ݭQ3f֌%$ $\`,\{w|-rz4Ve{nc?UJJ !"!.JDB`QBB VQU"RE *AT@*D V%f(JDM6OJJ`U!1 DP"&DD (wE"IJĬ*BLPbeQJ&` %("4O*UQDri M|D>'wD&\[A!(JB&JD?%TU%bw$Q%R|"ϟ?EwC}CG@o_Zh^W>aSiUs/UV۬JD[_D`[ RH{ "Q0`ڿcUm_Mj?*+EU /QDJP%/!JE3*xxqYo>^>,k tb" ~~Xb0L`%XEv1C$ߙmwCa~2)_IDJĶRM*T[= A H ?ƉT\*LDH.Odo?A"%VRRǟM @-RU#$_ B>-]{˾/")$PXz`0QJ`[_WQ*[{D`A`(v6@j{l)q:3 l7-r%xh"fJ Bla&xVY2"@lFΓDsO;)N$%ON, v4$"U&~lr?8Q* "i {SSTDA%()EDJb QS@%@013s \$/TmڊGf^\ȟ4'bR;JO^5߆jac~]*֨-/ch(&*ET3ƙcŪ(IS[c;"Hʬy`_4"@kA hB^+D"w{U/ o(/8&%%f}OrD`{lF;m Hsl Xt>^5@VVéiʪfR_🣤?2RL$vc% Jݴ~GDV{.^#Yf@LOcHC N;'B خ8D,x(*7D܄ Ãþ4້H'+ 8ϑ\ا֏HJ"_E~IHE!Jib߉//?K4EȒy Q mB^niPQ[~ ?UA`RadM+ XM 0ET ľuqUٍ^*Q_EI⛆"I@q6!SI6@КBk[*AUPHްBTE"G>E s(4nX?iUl.7âe g B!QI<8Q>BvԨJL;$(*H sV (G P9{%]%W(zKc3~SkTU)1pFD i#Y ^+H(ٷQ/8 iDpFU |gV @Q:XQjO6QBQP Q[7d%4* Ly{e/ D*{ժ$lg 0^L~zD`m$jM:MNC"D۝,D VkaH&I 6*6Ģ$e/BTrN٢&ȵ j'(C7?FwJ"`|9ŵ}½*E ^`D*m.Ո,Li<.E@6*EBwrQb R(PPp)0C;ELMʌPB xiz*"Ukk b%lAEaF&~[ѦϬꨅ6vw0D+%FoWNHɞ |o°g!@@TN2L@L`ՊwQom R;H$n omOHLy̫vΟaeYrRIdjmKbs\ ǘ|W:Ͳc aiI%&j^?K4֡'¤BP?#qi$>K[ު -ڼ}5@BhpKEh 9҈*s /8΃gއ BIyKW}lF4疡{7o(v~0CMe͜t=ygm8 P)*ׁ&uW jbw%0H4=@^1ȉD#v  B%$tLX)p\^YDN`6\j.Tajk(owDVARJ@gMLUJT8P/" vU"8]u*Qv򃼪+hRB6kNQɋoPQ.Ev4; !U iƟU*w ޲ -U%)T 1%2Q+ "CB!֪MipijTXU ;ܺ&V=G 'U۴v}Z&sh"05"Km҂f`[T{j8iw=l,Tk b\,+r lH{a&m4 .*m㡊l/U" >E0@Ǿ9':OŨ&u4?}@a *k%Wm/!QĎc Mx% {ދ#XMA~{c'8KQtX#ة\|HQN04O쟍c-bgtBJݞsYnҌd'jl1UZ=3PyQogP?g%oFmKfSw'N`2tώ|j׌ ^ 1g[NPa7C'\I@:-@{{mŅ[,nJĵ5 4o6,Q'2RR#Dmf%}ڡnEHHZ7Qr!{wz'($k>NY|Tur\> R~3ڠBa)J)\J[b&B) 3O O~ r\̝~;ȣ.s }!.V rG i\ fiq>31HtVN>{VM~+0#HKqT}V[||O@Rv8|G:Glc29ᛙ?p!jEHj)3bxQj;WY}O"ETLfb,] FQ𾪉mlFi5XTV9I/F  lIr"ґ34 Ucl}l4o8(lD(y*$=Ԃ/:_(Δ*!jĬzx&Ur l(co~"DrMYhA0ib]P(s[@bUB&*ۇLPIhZ%ڜ+۴hY|`)Q.N4] %q\0:ro '1F?rqvꠊjgduhv~Np_.S;YrǿюD &?|df]>[Z͉`6~1B[a * ^WiS; V;H=苃^Kf_65C]gE3"0U9dο쀿3:;}|ŋW{q9P[X|9:J"U;'j,DƄ_cr jk!IԚy[bA`RԵl=G"M IKwA5 FJiw`i\kW76%q$979kOpAWdqKxǛ .bnlL[cp-ޯu @UɄ:\֪_@*J$:Y%50TXLm#VMV$V@}Sf&1vBL"9@{զy&D wI *pT}(5`\jد [a\P^h ɨN9׵ʚ[MI|$0XRш %̪!1-# s1BİWf_E)1YSiHBF P-4F4k ^!Ȳ1޷zce1ec(ͥ[ _nюR:)e1[ ^jbh8RD^ AS/R$珻 4Zs UHŷv%@+!?~٘B150惨 dGuvȢj/3%]C Jbͫd P:Smʶ TX ͋SvBZG Bc& )gMVj"ͧF^LAJh<gQ4h~"®,/9r:t)S|I Q )B/cuMK%u8xWC pYDg)QJ$})],N Fx.V'QI.~gaA W֊CӖD $ld) m',~*[:& + C)x8M򼱞A{mFv5OXq(,B 1AUF2ؒԙsJl"^ySL)pàB/i44HV*9)]J"! 8WW]$EEf]?:[&5C9 .J@&PɚXF~ܙK]?6uuimkh)z}8"ؑj͋p$a63q2 @ű;_)Zܬ-$WJr@g AB{ ' H JKJ9B認$d)QVm9h!6*$?>ӉfpL6"'L9?])/t(3LM S T񱖣IhAu2CD+l.Aƌ)e'g G!F*+J:rO!|l& dc_$^=.xE#;l$ic|>]e#3AD1=RNRCQSbp9!pP:5wNJ>$ptږ82lP,'uv-+?v5' RGEРkȺ?{^CoNzQb&֨_]lfȎAb0ދst;&EAPJO0*Z8qkYFTP#cZ3_/AnUP8]ʀ Z|/*Vľ7YL1Bm3 mmQpM% ޻vk) 35]x]`z߷15U/0{`\JjRKEmKQ ">M2l! v8|H[} A/vn m.T6>NicJw6+$ɴ]bqOc%44|B(WG3r EBJB`OQ)fdiJR 1033ûWܤHS,vѸr=Kd5 *8&{6~jǜFK2cVl%"m#E\B2Q cm1uD5l=`F[{%Ǡx(pnQ0XsoZxBd;YGhS 0D H#}sݡS}hch@ kal,`T8-Jԩլ $gM38}D!y *\fAI\LV9@,`I!,yWt. ~ &-I:iuL>mY~4dz-ܖ*dIγ N37l:y]I]"2ˁPw+w?RX%]ݔ9I$T;Q4=NXRvZ;#!)UJ $73b8R<$!58jbaUv:}F8)F\Aӂf*Vt2mn^^(.!Ad5 _=Q@m*co.tE_KՍw`cr{ȑU*R(͹OެWh&rnCfVԛDfhKJ),WBI)oSfP҅Yo1ZUMژEs_/f8{EK%>b0/IF6^Fb"b;iTa0.tmPЯ&@? }ݛQqY IIZ&msDpTz&~zqӂH}"8% t__X8Bk}]-0SZUE\vq֔(A)vBUj0c`⊁sTu9+5Xä5|]i͓dSJĮCn7uxL Eξ˳4uT_K\>jTQ1ZTheq,2"*EAuCTL`wJkCH5tD\l'֩J˜83݌-ZHںg_ }KX4wڃTLj-\Lg:a^F*M!De+`kbQ"5BY(~(^n41vi 7*fT4R/̌xL,-ܟ)MtRUV T#~6*l'с*Bd);fy9yrVm>` & i7d,D4ͯ4X &e^/6VmU-hq ~\niD8^} FSU`g0e"bGMF #n sW$+J* %w#Ps,smT!.̆L2H^53\\~I4/lv $3)0@2ĦqR P9M鈗U"609]ݠmT( %䠇FitU"4?6:]Lcˢ 0Oo08t jzr& &u3M#)W KS4حw>iǧ=b*/mÒۉYBPYV* an~E p5 DּGFgpg^`.O3u1.9ŧeD eQeõW`fvҽ.9\B%J8d.8j-byպq'rdE։xH<18̬4I[ƆI|4ȵʖ2Ⱦtz5&JF|& "gS@3)!p6Kͫ&fo6ep>}|6|1B=Qšִ72 -$"Cb{;1A oR fIDΞ= B'CL1N#OVHW P*.88Q;6@43ԉ0Y vRS" qBiI#;\ _בcwsY09ʢmE""2[ʈdȌ\PCc Nؤy'SYp.2ÒXYthmЉH &@!u ؍<|&}ه:JX#KZD$) Aw`m ]eJqw"QA1ٲ Av1u7 FӕwٚF_nNIPM)KV١&=|$s2R}l$yx$О-NJ.)TBZ:(NB_畣Ʊo Js6{èR?96|H %dYH#]D_!b&JU%w@QD8DuO6Sglj?J1zEPvQTPJk.%$"MIl>]k$q0-|^蹎?iГ(pt'?VK;7urHP&s?=}đ10nTG 5s9`?)i3_ވXIU"z~X<0\g<4-9@!fKvnA4 ^_J1%t`Tĭˬp8ZUvXkT_ R#_&)|fͬ 5ٞCZJD|VDB% uar0eŶj[uwˢ&Ha_+9fȞCV҆2?ך:CPӻsg IH0(T\̤ҊBU;5X{2MT"y?xZ_^9!?,lN 9z|H B&{g[M7H4G ,f 4o4=JC9_j!bC@_%5SěI)5Ĕ4\hkb1j1q;Cx B-&wף+s{h E$;mv̦ \:3~A t1EvO0%La@0OViu!C0z_PxXA kA#!(WGpQc#(ΐsJ5=S<+6JkN >MFaaXq#9b=xA x7;A⇬s] }fqOT%\`(ɻSErIx0icU9YYC͢al"Sjl]g,r6&#BXtN)m3o:%7ɸJA uJVh2"@a4'@R7*&~sqKXՓ\^q .IdATtcj*"uMt-_(tH04*YDgxУ dԾ5}~(mḚ @MP UJ*T+( 5OKEQxZwckقuv:a+r'\`] oW| NA옉;*i3$8'S[xB&Fz ؂KO|%Q.FDFNwm5륊Jݒ,!e0k9[W;lFkgj$/ӂ|V xN~>cDt][JC3!2v}VLJ,ߓ$ Ba$*ΚLa&H¬_WR A ft-ut'plfg}!c)1\jK\DbF,MbloE|(bɸ!-eT7cL⍖ߨiI|. F+53@k)eP.MӴc?qNDTdfbH0~_7m:{D7?xp`gh^k)nڐ C2Ոp]tÞȍ[~EDE8没4oļc\wG1,Iy\MfoW,F)J轣ő l[LcC bQPaM  ;nRVgS϶W?{q:}riuypwQ;;7n<֩@ƾKޣvKĸHk7 [\`{ÆNIIƞEFRb4*P"m#w-#SHkrŦ7JIx`.gH66a=k2\RBR{bB҈Yp(K Z6W[iue~eT8qw eeG:=Ɯi#k= Z⼥J$ j8".(YrNBTN9)q7dSʶRG @n'1ebpz{)S},HOKc1WC/K>Ga߳A3>LC{Nmj$kMa:}?񭝶i~]jeAncL^$m 6u**IJP&2C|+,!iP!*!H3F}At^J}L=\BZXKDR='Y٤vƽ&fah <`+ZÎGGXjl`JpT r՚u1m |Cᐉ3ȍn#DjޡLIq<3[{DԦb~ci67gK̷|.4鹖d*>>Yv솋?J]*-SK dԍ>Ϫ&m* loIxi%r>Ւ*sk- #Om?|v: (_ L:F6RK b "HA%fvJ) n8>瘈 M5:a۪ C(T쬐*303c6˔& )s1$ћzv1;gp)*HeH9DYƎqsP.g25M5:+of{4Q&otZ?"ae[ٴ ~Jsԕ$j: q%uvASE2C{l{]("Mpڝq3'{tX=; y_.~,mT{./v"|P]ji7!]DH.Wx|e4uFFU'mg;10Tܡ)u@iROx_ 6]w f%F6~Hl@L,f:ҹDd\\=,ʘw_H4vQPZXǘ Z"HNfTӦ¯Lfd#+wY,vw zheUlmnܔΪE7;&)2#&.83/Y޸""r' % Z»AJU RCLBMxBY?hOpaX ƘmSkg)dPZ/`^s"Ґ >܋h~d@16 h"S?Q<8^V;0=aeI ;)@Ь{ŐdLKIBp[%ewJy ):Ll2NRƒf:ːR&u+sM !ĵAZ/7F)f `ZC. co1H@'w&Fg-qc)A),"aRGh>G'|!f:!Lz5 OWFᅤ .!V;'q nLU՘~F|<_pGZNNQi}S^cL(ɮ*n6M.Ej)DP!yvz0B b"0Rbs~'OP:SE!z 3l!FRgD=B)j$G"[y&rFfyA͍fpb@k|r[iG- } P %)1>sPLȀ'QkncծS"?lǶpDjVipgy.t \(l]\b. . N{tfҽAfdfY䎴k g;X,8Oʦ1kvG3˵8NU O—k򆡨4@H`XDCyRB*Yr;mEN =(s~^hŜ4T3Nb:CeIp}azkvt@ng `_/MhG9ۗKd/۸:[Qvz5<ǤMLcQ[$Ͻi,[VXFDR!#@P*le{#QP7Lpj;]Pp[5;:kwهmIuwطD0mh&L3FPg":'vc00 ` 7|Vtw+;3ߎEZm W"tDFTCͳI(ujy,#]3* EPbS˽Wh͌ⱃ58xt:TD tR1ŶIؐ6hߝ9˜R 0!M*XN9{iU~biv >-{S({j$deDjxhz& `'y ]TSCM{LV PO^c|ҥJsZuD$sQ^3R'V7Iir Q\Xg0PߊQ!Ci˨P׺ f9 |oe\,zFh/V7ޚ@L-/J2-k .RϪef`Ψ3TV}"s3ib†UMyYJ(4{񑅋ڽl:ѩ2]&hƠ3,I%zݫYΆC}Bߪy%4ň>AD`!kVk,-"|I,0C)H\#fInZ|^;iۍ˹4}.anc L+$bps1 3r;rim5k1nKӵ g )qXr뚀H, d8dLjV**b;PN7ɳ m6DA9\lCeG=7s%һ%qR{G_E E/r"3õ7 իIGCJM'lF㮃(eyY#R RZv<#ݒ91?LN cmVh92l"ip/4zgvW-DMA>e4*&Ÿ:`bԦzW@ bF3R1 D0x,BFNWLSH8'oqA_]-P+{)?plq=@4=%Rlb#C$O[%kKgDQ2O@?lӬp PNA(XSJḚן9.4P0Cgt qd`zskQVGs|z%p"g 7G+) /wl8i31pRg?DRS!kL(<" fVjgg4Xk W&U6&spFi+zv0~bdcpT)Mc6Х>[ד8$\VWkqc Ɣی[PٻsXVbeMH.H9d`LCόM!1AE p܉q(pKM%7|&5e`M0)>@@+qˌ.6%W49ftVCo#=`x횩[yRWD2X| -C73ص|NT_Dzq%.1{PޏPT0>زS;=| {ɶT@L8YszDwr/Jm-ų řvvX|4N+CDAa( j{21D3ra抡LS9߾!3"'=3-Э&zUI%(PBd,&/?Yޫ<D Vpf=[չ5lLk NATPC˽t&L׆z$&&8߹i9X-:ϼ/<×V( egoY޹q^Qbwg$K o4ȿL}|B8u5; LAP|zG-14C2jf,pei1E!1h'Op[2+xZo}8 [MqF&#M0=,#cr-R2tp<_MT֝ogM_*- Ia4ͦƃ՘Չ~zv I5PˏƦ6?"Pf޸*b&&4 ey^^YB hiyHxpY@(xwJoFw?~K ([\ eQnH{JYzՒvougMVUR bqO]')dxTE^T7D Ў1ia!J&H{N/`1RKHQ*yj~e :QJ*gei{a YC09 K+bë\P,??\fm>k]7َܿ&e8[wqneC:|oN`pSLsf#@0;D<98|Q`AeٝDy&d.gtXH6O2g۝TnJ",lodlCY)6=D;xyM9~cb Rr,ɻ{ G"U+\H>K &iAHKw#**=JyE%Luo̗Q•o)Ԉ!bJ3AWݮP O2Y{өt`ìGoytu5|qygٌ޽wjm_%U  \p]/ Q _!Anu]x u$vGy CIoΟ_hK9;˧;($xPy`% wB')ExarB}X^4,d/A-rQRlIz36ba>};ժ+q*+nb1J` TxS=f"v$UJճ/^ 8Z[?hp!zqL|p6ju~q68,[g/@`*<^ sD%OQ/~䴺*5vnP/4Z Ca@9\}H"/jlUa++96(#X+0P"(:ف<#gssrݦͣOoq^5>:y~vuyuy\cU}'l }r\cXݛ]\h7leA1SҚ3-8}*#bYS * xdg4RT*.;Ôf.=ʉ&~#h="E"R׮M4NlЫOm^N.f];/M$RUv~u\ͻJlq.O8:~*47eWLV)3~~w +bS,#QViۗkeE„*DȲl`SJd*q2]3x"\DU< &#tbۿiȟi݄9">}! @0@۶ٖzqn@n`Z»ׂ7΃g۫'vg_7')z@^|)~Q;̕O!$i`U2fvP Bv6j2Im!~H}_Jej _+PEam)<' ݄[Fm\晫a&(ܼA]WyXRfBr)V[ɩ#~/\dZVgx~6!BҔ f;e۾wwWtx|Czu5xB.^lJz5͋ *Qk(!ϑ ep-`)9SclQy +2%'N=DtxJLXU! W {woZZ70iۀЌ |I]U'Xk>{N*mDWg+Q* mVj~w]޿|ty{C7'gӮ[SQ|k>f"2וlI\ez8WhbNb!C1IDɸԐw&2w^@JmڽzhG\p1TႮ$KnAN@P)OSe /Y3cQO~~I$26,emώ/'|wwKR6-?xpM],~ꫯw~v&mOϨ' Okݻqpx8?}>|qnNn߾8]z5!QָTZ_BHN`Ӓj:XNFaĝU]`Ӝt; m&͉YUAf gh.|xV0c65)4B@sl2Z Lɦ= $ j?骶˩|qtGYrVikO% .G{eaf҆\vEM[Yr`EMc[-D-ӜHB%K ""_5F&&pYf&WHD9mue(]夜f ÆH /_W#u;`m||,A; F;oi*Kٹ}爧֨=y)?30X!V[Wl;7?KY-~~o7{JgRRAsO {-PkcŰj}2B{D)18  F<зKU ivr+!!ފvǁ aDҴ;@$hXE)'O?{J2Kē(9'/qޮ(4ij)[iS)ٽ}5E; \JM[L7o.'eMaݿUN |ڬH0mbh6B\+r@vUn ┋S$9OHO_V}urW8oEQJas!&#.5ww{z>v̊M0"9?9^ϕ+`B\lԖN|ց WzZ縚8(K<.P$4m %˳?|p]mΦ.OmP!m*2W@TlV[-$WWe&-]p_/>ix3*-}mo_Zz;#Zi`=5A= CJV5}Z΄q HD2fy%fm uMPT w Jsqd@=P2U=(QP=A|ƸfC!Ƃ,e^wWXTdJɤWviJb|w`ͭsy">W{3^=}[Q۲w̧<,1eOCGϘb!kE{t{)pֺ? %_9 ]u ˒‚=F3,2nEfxA޷5,+JDgP nRQ@E@eZX&6nlQ!YE{ol/Oo\6B7wGg7o,HD_߸[qܜ-vރYD g :k+C% !!ɔ2Zy[IAk~!$աS%TY ?/!xީ} h _0z}Wcmڐ7v^ ރՊkJ[@lZ_nxZLf;mh&I %9{d÷7Lb|sLwh6xyb~qK)egLX vڙi g3Jt>F7W$} <\67\TC67z,+5N96 "5+E}<_쌏Ŋ97֣[կCjʴ\~o}>وLV4MTEѦnɻU"Șeme’jbn\>rw?{{<<7_48=Ҵ3KL9yz}Lxghf |M58T^ɛ~_ƒ,+Q˃ Mel( 5QPMbvn,b"H44я 5edewnQRPAb~k]n*<=;]UF3Z9H`.^VcyArEM!tQ6p-[ˍjy0 a(v;)+Hm(9Ww,3,;($/;{"My{^fo{ΜcM^zo31e:]#nAf7yK6yܚ8R<Ӻu4Ӹ,0q{%bAvlހKu3hጎJnRdxP9q',gWuХtg06}ҭTXZz;;^65+jۃbX,vh#pzͶ!$ZgJDƝq;;8e6ܻ )4۝ZC岻[UUMB*ɰW`3r0q6QډyX*IHTWF̠i5-94S/:ŻMh^g;Ʌ3[0O -1%STJܠ#Xwu0s&Q_}Mͻl"v[ǓLWͦbmuz{?~Ĕ"EbOg>3ʭ7.w߽upwolγy[.9f QLgkl5|ϲ .iAdtVuEaiQ$(R;ZS#:Dt)OHaZ9DiE՗8Q8+Z-[f|r6UҾ}Nșwb\U q=r*m]7[ԺZoenYDvKu`7A( M bЮ^/VX^tl>[3~nf}gpJZ'!42uFEk-` ϼx xBb |L]"mB\Ao98]c(/zTF^R7-b__}\peݣue=+*S[ί4m t;m:[hoowxK,*TK lo4V'v9mt;?᫯.VgO^LE9fC:!Hv[7)CƠg6wOUaw8%;gx8/6*Px 3YD j//BÀŶ4v) 4"V]9{sbSjUg &%9E<*&eeט`I;ǧgWGOt_}^=[Mˋ`Zm"rB(xR!Tτ2HPܡ1cҚPD9{auA@w"* 1SUaa Τ /In-bBJ U db^b_a@ǿe]zZ'idg_c?,SbV vKŴN B) M!`o8yqr[~;4>YY285_+<{t'CWp=0BUQMpMxѣ{~i[2>BP )J<™Xෟ.SE5rvע4HώQP<' ir.^bv-GE g\f V]P_DR{V}ruJTejfj7mUE ׍H˗i&F8Wb'ZVE8 oT)pE{>]f%qɵb^~.k/'n-D! ^N߸q{quvjsVVH]9XԆ(ʠAxF4ђZ9\ܫg+.06M"n=S˷`M8PAP(ݩ=s/eNJh)`7V?PH=O;rzM`1~!ȓTAɬ sJPY'KV!QScHiJ0:a]>/g'Mi?'U(+)&.ցNKm#b-]ՠO\3L(Bz /͕ ŲŹR"wWoݿCHYRi+)ْ ;GG7WlIT[՗sjUeYN~$Q!"r [ &qf5eeF NüKv:f7hHƢW@dJ˼5 xDpߧnN4"v?Y'dln_n\\n.0k zuz:`_-߹;+-󴭨<<ۛtW/O?{oR:RRRHh9[D rhF4HZ,mXoa[:׃] ~xm|ÆAy?ٳ&XŔ0̓yRTB-/~וSq}cz"0NGo^^./׍tqz6M m7XVEj{h-bWn^/}{i/~vX*MU9"u^c&֯~7ζUz-{&t=tFs=bwKeirɼUY9~/ZՁD7]Vvoryu5ګ77KKAS1g@C2@l|s3\25<㛘XILa?9MfNM Rg;\)v:&LyAWnˌΞ_OW)g,k1RW/ݾSՍ|~f$]\[]2MoJ1W"o._MSk&I&^ 먣t5/,RteF4[-B^#I Ƃ4')?Qo!&T&KĜ81zVڳ)m b{Mf#&@Y֏?gfdY\A\TN:kӴzd>g,_^lw{p9~T/Rtq"GafZ(z/QvU&+eTj,1W3mh<;M(~BQt'rd 0HfqCC,"HeӹlQiJ08{YD HC:)|g_>>|+35>cNUm~^jMWg6]?;ӛwWW/WM#ǁKR\2mA у[8}eb̶$Κ:M}sy<*7hRj$:]\k+q9Fӌ#!@MÔ~-j&qIn0,tR!p/71 (xy*)vqx\[D }9D̈$OǭE珼.vݮ>k!t$j^DgO?;^ "f)UJ|Mw@wo>wn-TS٢1ܡQ-$c>}nb>Cth2` )PyzN[uzZ1$dN堃Y5RAi8oD0Dϩh0QNU` j菟jN k9 \6.YiuǧsɫWW-\8;'eZ**K!Q!e46"[kMQջBe9G .n&z A؛s`˓Bt+;Oq#vG4{va4aOej+t?Up3={+EbwrXŁMLq0M~z='-%-yF3*xpخ^6,lkNT&/W)leʌ W4{DpKKD)/z'oap 5YC -)")2$T`(E̠@FD0*{բDT\|O.bkhqftՈ^ *V%r̓J7G2ԗvƙX?)˗_[!IW[1Ŵ|}Xu3Q\NKuKN*| &NSt?lw=tզHM9%܇Cn5U.R%ssl:'L4"pz|i{Ak` 9$ZLE $[Qmiw.>]T;8)̛w 7&l@zRZ;_]m6BjkTIH%-%0[rNOL͜D?^qKI94"׌mx&LPjJ(01*z 5woV1wSTyu}:6ˏALluQlqywJ:{O?y~>iD)ϧzm8jZk-ϷݻG|o씽m'lѯ8XsPK}8ChC8Ip]dɐh} !':lՐv[;ݡ5-Y9}}~xLr2+Mµ(T'.jR󭈨d8&`FlD;7wcxM;^ZA-q޲~m~sj[gal@h- Z@̷Y='wo19!!R"GJ5>FBjؒb0xTr:FG'R)'Jk%` %]5c_s! ҸYJGo/MPwbqQW__Rn@^/QL o*HtmCQz /OxcOK3 I+2b#dG".0Wǯ/ux}:{NMa L\lvSni=&yΏ>i 8Ԑ.6[ѲsÅ٫W>tyH}R@JVw9x3Ylֻo.RѾVE"0Qesws [,&wS&Î [WIÎuŵ3%Nib׮`h:+ 24Z+8t->2G!-6baf8yK}d$VUZV*{eQnכf'7swzV{Lˍ#\!6%+$Sf^rcMཱི_M~u1K|O~#\/RuQ"mjsoow6r=(Mk}{Td I@klux$% '0άB%A'S'jh8;aNB%Y'S`LnVX2#KoDi[L?/7ז~ih~Z^}MԴr %*}lv4߾쫋'I 3i[?\^]W[&no)v˩"W~yKMDTDh/~t|uHA'r6Y~8V_}vog9֦à A]]skI+}V$J sx /rЗj((#@Y̬?R \"a!Q%(!ww7J7Zy~DOlERXBD-CcKdtyl`F@*?᫿/^,蔂,hOWMǗI}5u{nǫt'ur4Ƿ~N93c7b*U w8y .bYgBN√voQ]'?뀸D/?x},T JA&(âY!K= t+'ʹ $1%0l.D;WČFNq́82)+ɓi/?{.iqvyβk`Z4yn!\&- Pkǭ[iX FЦɍT - 7k\ReZMsqDa6aT{? %e IV~*!N68רU]9#I B7s 0JۥtmHPXPr;,>c|AЃnF[z011H9z>>^cpk սw%{/m.g7  tIU$DbcSSMp-\;!;>DGŽ2Ġ7?T'0Jj {[Qִ^ ,_n zT8"<,{b)!$J m"qzg}%6`Ak\l@;APA9橊 6l~g&Q4x,G/@7@bn.fNGqdh~1pzB>xԝXm, o*.?˻~'!Qm\gMIw;nB*aƧw񏖏8 &65 DD{X $mk, C SKCxa>*2˜Y4xžXsuR*lpBѮERFnB)/8̼o?~ni:}fu0ծNsT:=`RZ:v^_X~F3ity\ts5˗{z⹂6_OٿϯfOݳ=-1@Tg׷Re g3 jj Ӧc x_ ]=:ݝowX:w9l/}`zDuFYf$zAhj.fӛ1.pe-?|t<øDY{ezx7ٍ\.ylo~ku 1~Ͼޘ'`njNvA:DO00եg)otD C$ZuJ3z\j&*\R#~/_EA~`a49r+Go#zm&T(xqAe矿ؼol כ9T`OtvVSSviK&M|.\IB0 m`Rt[O> O#c &,>4#Cţ#u_^\jS.o>쏁覰4eoGlHzmWJjfɤm?~O_McdjqW׏^Ln[ʫ_/أ*Z3*#/Yy%ئP1vKĂ/mB9M&tHZ #PZ#V3UaJ{] >PO>f/ߛ깃շq= 0N ${40Udݿu>}w;[mg}̘p}gӂ.zyn,=tOEGh^܁LcpWT?g 1(y# e) 2\V)U;ILf"C&|Ւ3?&i98У{[ց)lWԖwm44kWWV={?V&>~-ZkB7~)ͪ(UҐ^=EEr =9x ;QX˙s:@:h<~"I*0w2kf z ׆~M O/Duq勓Cu])ò9{LJ?ցH˧Jvk%oZ2_l6ehhs43HvTvt|}HXT) ]JHmA+XU/:g'P"-|9[jpې]G 1ukscj`_q ЖgiL}q+yH+>82bhM_7$O.tC{[9=25I{m%NeT*v;;@ژ̆5-T:"F3w H6n/hAQ ꝼ$ "f[EVk#PP|Ŝq-r~̑LH,~HKDGr55A>_~wV1^Z1^lmW-fM>;NZUt),M4^Qb4AA!-3ƟLo+"GTVp;WE_^3EoU_\SDG9c4E*H^>Bb0<YMb\0icPJ-󽝓"Wm㝢oNd U񟿍i$)"akg @N_vmq`?E ɎDLtp%UyB)p:e qQp"dm Ţ %H+'T[T@i}Գ}懰Fz){t %&fw?<<ʰ:x${,ngJĪmu$>Ҙ.ˀ&:FQfR1q8ɻJӌ O' 9l( AR菶zX83̃c^gg 17AKC48Z>VQO.h~_篧%d>ӳ`ӖȢZ\0!Ϟ%IN,jf=+*PM4O="4"=r`=n-yo$fR@!3+↻Y) -q4RKlqx/.?i砭,Čٕ 2&*TD+TJZIC;@ZrC54`(.\T`F^+f漤"'ٻ>>TX«RSXYMKURߢED#T]8xJvVޘfx1 C sDF2'ՀK1얡9iD>1瘥좆yiM9DRM(YZxZ \)QlNz^0d%) rLCrߴ: ,jfHLcO =ßt ʵuVy^2*[G {a'54l\P>?|X&q1O *URh7ijp4Y_G+u:פ0d>`j^ "h15mC M JDT vLRbH,V)yˡ2Pd^E(}"X+ ԲjWef g\g5VTPٔQ*:Zwӟ;8@t,\zƹ0lN&UGVRc%}\P J ̯s!;''\` E+M[A?z|EE{LRJ %2}J!K<iEJޘh=Y햃zFL+r͋ſ/o?c?h)Oˣ@PDv̞u96+PTyn{L-FdFD1+f4h(ztb` %!Б!d.c,[Rc(r pQmuVIP| (jn(F!? 0哿fzEFL1KnIcS/Ahޅ2xB! tɮӔ2d(@ s)pÉ83ޜࢲdϓP;/rbU(⃩@r^bQѫ׀y IU?=u~q8G嬪zG}zvDՒ(?738sZy(%ZB tݢEe2XwX,aQ6&Y5񵡈)bh&# b=-S.Ŭay.&eZ\<$y8Ͼ)]쇔Հ ^r"/ס?F=12s#33G15 ?|JA5ga&b?ż4#b}g6J,9E\ӵl~bJ.x!DɑhPV wgr,f$Tͻ(f_TtJhkާQq{3WAhM¨˅(ygR¨F`^fd֊*I$(рK,!M0X\Gd5!ۖ|MWTC\A朐 >Hl/Ct奉c.jw;z*6hS ppnn>[n6wo j7YsP\Yd>ʎA;*ݨ%/}/aZ&{W%O4 %;cF/Xzj9O,s]IZJt5 /f$^c̊V#$A<[@h t_?MY {s}}˧O.;b7e 5E(Ono%о3v0t0)qEAu4ٚ77f/>򿿼NluddW×;}zs٩e; @v٩YE WqdASdwC:<T X-[bv# }aVhhJ*)iJ`FJҹϩAs{dqk;YuXt8HioHTy 'tN<)(1dkL=IPls#ƥ [>+F,cwK!-S;#j݋>8z/*)̇Uq$?!Q!?dsӒ *ٸA.,Bb'qYQ\6)X3{8/-\ R'ŢdO%uU LԺ]#RR2⾁ L;܂bn %܆h,jgy1+d<Ènٟ X.)3VӈQ w߼ntvBCBwcc)g ".gu.\wk>=ܦ|rv$ gUtN iXDa^@85DtMʠgԘ2 QFHjȒos=c)k?~ -Ae](zGׯ=:wΰHVܤqZ˶mM@Oѡ}w~tPD $b+d+T"4BQ3NbXQy 9j}Q8M XJʹhFFi@`lCq q ^QB:w2l5$rr&ڃ/F߿~7@Cqa8%6V=6)P{xt;qҶGzI9GUfBG0R{_2dpD9V7CϤ*tkvΎ1#H2HD΅B5[:T R,jT R4z,Zd$jb&#u-~uFV/ Z W\3ԃ& ڮw8.@ȂdZ~Y:m/i8m1^6 |zʖ#_ɓ9r=:ũdлzsMI%Y *0BY^,Tى(DFRU]T[I'P/IGG,Tjd9$s'r]SR΁=l&B66vHUaQ ,\0"Ade7k9܊ބǷ>BR&|?p)$SO-ej~SVaVy-f(R(ZԷ3VȖ8(,T $,gy-ӔPqm)+^ⓈYy?<ЇJk{/܌J^@O A5Ր&"yga3b թW6i! '5QMvFCeri&V$XםͼKtNW4dT!!$2 Vk\)X0&1 Rr$/$,}ڏ1h ,k~%IqkYbQE>XiP#?`Oo2k* 2R4D* #|oէfG=iH4U1"@$ceSr lk5Ϊ>XM0,J).RQAb#, 0o?9[M~@6)4 ! w&E!IR4VIq>>xc5r)N|gyRtfH>SEHowIhDF fJrO ~0jgcٛTD*JL2/b tIYjoeֻ*R"Mf ;8)_aM5*Chۍ6Lj'Yʖ1Xj%ǣk*%> !U4V9MgA܇_c]FIEI#EBۍ3= LuT#M+V,*axfBAGx\zcb JA՘ kKB\1 n@ ~z 7؃ث"b|0Bt7Ώu{8yd0@"@a9hz(>臻s!MI5f*+ƣ9,^l蝥iߛs5I+;{4#<(\`iT KAl7moQ&qaJHXrIAYĶF 0V:g$xCj=>22f(*G 1tgm>}d2Xd;yKnc|t] wK !X%39qt6g ERIn1v90%SɢdB e͜3$* .qx v M@O##2IbuI`J-0&bz+֑*$qԢ_j ޶ _=dKQ雱sB߿N|uvhߔDcdYN:@R4ԤJOuHq(f"$]ȩ%44b YT2q2 HDKSZ]"yYQLsհ[ߏl= S%plUR%&ِ]?vK?~HA/9L9q1`VO3ef`,XM. ,] TەIZ2] N^[ڌkc3#?\Q\44٦iL@EIEpQ+PhL5cGf9$MJa{U$J'tt:8Dbّp@3>?%\|@)l':3-co%?Ο& ~h>k4h,̌qW3H2X\ 0E|f )dgˆe-΄ Lвdy6W3hz/"rfcHi!5DqC@be@d8=۾@HjۃHF:WjZ:(Ue!iy2 tD"]f"MG1L e [WZl7@0/Ș= pG|c7؛yHacQg`MI13;d IayP~Lјvr Qɗ?rW߾Qv0@ $tk˞l@+fT4VU*y`HLʱ8!K,ü2Tم7gOt]hַ%h2\ƈ9dHd'z1%eD>kj"3 ;f A%6 i|Pf1W@.O_-n~[cd&bQ3զ?v0)ޖ?@diSM, T%1amH1h=,0>g@C h!=2cu1q&1M9 0Md|*mz蛐3u+A2k8g&R,[E% 0 )ou '_AhcDExXd*/($Rj'9Fo4 ^s6*raö=<:\xUlM FlNf6$^eBmyޒD˼LH$"=*ʄ V:5hq3^YY 0W|KI8|;ؕ VT6׻H(?ٞP ${& y>ETNYc8Y;\]5Reqٔ;NTrf{{BPr'! F0*HqNP D|^OJqNg3ӄ]p6TM/'XH&鰈.2T#"5ܕ`WF%2SL`L-6ջѩ75K+R5ĩP{ ŀe}p.z Bv9fR 6>9``*L+|M-'J fFH KQi3ˉ&4*v[#rSqG`96!)*v6Y.5/k&M^V x:SBm]UD^aa}cyG56YBg?յhEg5LX*DFu ےekqk'#% xXnb($o\h60mS[/)G%v-/ch{b+++DݻMRa/s 1йވ_)1blzaxn+ƄMg$P|FQw;,aJ<7۷z)6j ƘNQjCM;WP|2Ku[ -)e*q) 2_%&&)XT ͌=:؃+ feM]!4 eA<%WVGӃ!ѳDat-ß/o^`~_@ /8jaZ-g97 J9$4UsBҖfMI%.Ž˩+򟦛fO`B@1էT_yWɭ`U0%V |}I0SDՠLsB!W3:'`mEO=3S?Nb`/~;|W)m=޹y Ȣ;*Ҍ)/+B$"ȁL6`WNx+YN(h5 afz %*8%`6{fɛ aHx:9ACRO~~s 7dU U45DƇ;PG0J?l@Z .b'??rޟw턄;}~pKG? D`o}>LSE#@bFb:CR}o>avjp({T >?YcJq/шD6N$@4R[25Ut%+6-}9=s^(K,>7 "JfSpgCbLHږtR$wE!'HyA q6g= `Ĩ TAM|0W]=]u.bLEU DÿJ,vNTm N{IOl]ېeBRSS]klQ&Q.iU-z7''ڌEj :Q7 uf;B 75b _A8bx22ɓxv ,qW I.*)y0E)*2*HYg61PTaq:\m/-^Ę4qȘԪ2":\FmZw9O\unc3&!E%JxszmTp ٔڮ;`w/W/d !9pЛݪ_'0Y-3yS^P˜wQkٔc|b5טɁp8Zڌ쏿}јEsČR=-֡ Nw6Ikgy*?)qt_ 9jrteYT@գ0AJ]niE[/:%㋗gOF LЮ~AH:Mh9525J+<ٌ"{OT?%G9Xg!^1W![ҕ-q6Z+0y ـ*JۋC\Q{3|âjYP#Gc?y ,̈́>Whn?XË[f"ED¦%U3024xy!7_XS:3ZE,7-~7Ĝ&q;HLf%FT8fT`@TAy* lpemar*Q>Hs\qQB1hY* |/{Oz4bsD.0ܪx Q*s~Ʒpr> IdrSOwW*5NVs&ClF%1n)j,S֢H!vVVp'Z&bJp P$'!Eb@E8CpQG;DK;N"[uz kތ~T9K 9 +`BNAmty>iHG% 89>]0'&,:q;؆Nwϗ0+=B]Hgf(z$&Q*Wfش7{4(Fal`xeeA.#Pt#\ySԐ9)QyxD0nB}Z @P'No@Db0$&cl&/qFړn|r  W]P 7G"2 d 6?4 iTK1 /.aEϛ'H@Qҋ`iK2#M_ۃ֩LɶfubvZ驕 `m*rC̋r*c& !mȯj69ם)zf"RHLEU2' U`_(tGGk7Y1wPn0UͬYuR`bY"<ĿSTʉU@Wя73ٻsкjyRL A1j#~)6m~i/K K]]Ia)gĔrTFKnAKL$lὺ~lH'(Z`lm""Ii=<;m<;>;svG Bt- `^H#+ 'w~7? MABMnlѴ,[y.ܶP+$QLuVYͯ7d* B (j2ErEOQF0.SUۂ: CZ3{yx8x*`Clhf,Q>(*@PSn1{U =j}Kyf@Bj6!߀"˻FԢk<-y)5*~$Ә"H98į%Rȼ7nEbQW4-hIyhFa*idIo%t֞SfPN%{8v\kV\/0jL买'?yjfv}$D۬"B$tQy+x,&$ɋG:+҅&J2G9kv n_"c<9]Д]fأK%0զ󟰉G$`Gjmj2yzܣ-,=(IO!L Eiq)%jݶ,CIRǶ/%Z!U_hIjI90u^5jg +5|:ýاp Pp0 7ԲE^5}bO~ۻa{rxyy :x/š_[ErcNͳ9/FL200l?`#diPu N`H`JJ+ 5w܆PSQ@U#Ofdn'nU=gS )m0 萐 z3 +8M ѽ8]0|ٛqO.#II^OOiXɹM-/!E2&pPk ]Q9٢g>>0s !$08$f}UL #qP[.Mț (TVK w3 ʈ.#87Bڐo# 7ܑ g h6GP cvIӸ/X]VrG_e(T-NO|P}z"(&g;-Kc9ba;s8Vp\ ;"tKI9TɶD*?>mVPBj^Ib̹ⰀkQۋmB}dT @N#5egE@Qr: $NvA5'!gc)㕁xlͻ_?``I+3HR:^dPoRbx UeEe0Y0M3ESt<ʿ5BTVg$9f)`Qi!>!0ܼy X{u{A,@=⁥ނLMMzjdu$MN^Vː5=hf`OwB*;[T$Brč !Q3R Er?(>8qaeZ1DnQ}԰Mfd.aN"cNT8e6iN}Dnz6W[)^xC=kcTVrUq]t'`Ƅ6@v4n'CH+WYN67`{Iwm\qÍ/:=0zmA,*t`+~k(zAf52Ȭ(JaMl⹏9Jk1lNl8vQGT2W@ +"1@*5!`>#p_ 4i kK1#Qau4m;; $qk˺ފRw.-:GqոQfm3-ЫG'vxzpww?:%1D QZG ^%OyJ0]1{ QuimNg(UjdbgjT`Y IS4opaI{@7Dj5C7Jy6  Xws"ϔL|`)`O:/`xp&oo;Xz ڥ8'h8r{ӔE'?LjTQ4!x"-A4gb[=I?ؔ3 sG,]<9 N%vZ?P{  Ӻ9eΡoy;5])}6l%ɓDdfwì`'hr1흁?77itH =A; Jc'h-"$Has6Gea\wEw0l"0Aئ FV|(;ay׊U?oxdQ G~{ZFN{3Eq;j5YDD\l A˻'" dXAfV*/0NH*~ejÙhcAgdTڢXrU7*Dp?]3XCgϹ3Jd9-~47TAOOlռgzcL, ww;kק+o>=o9ʭH0:# 9 5Ì,J{9Ru%#U L*Q:#:f u F;K R(*p&)u2EBd!+6tw@e X`& @ uESMQ O>:6I+ huL].D)ofXD^_hy2i=C`AIM~hS46DcC[&@y.ET-#O:.P㉪9bjcSbPcC"Un*#UlzX/dl -}r,: A4 !/V4Nx uVw^YϦG?i!#y|PJXM>nZt.'r`Sif@ 5`U d'JhB+=e^1rAzJ2 Iɥ?Z7 QdD8#UzJTrm@=>U{Ӽ*j❣4feڼ4=cm wyULxtnv{c춎a05ۋU)2k 9.N{47{7ho{ZHΡ1rSn65qUJm͸A0 vaBcQnukPz݇Vd1e_GvDQtJ%Ǫ6O"ABCdvp|x٫ + wW q`yx6᰹|⨉zm(I49 -zp* .ތ!)(mh%>,;%!1rzT"mw q~/Ej6qwpn-#saڌ;< goxZPv"vXcn0 zÅ= Hdj,4r9l9͸Ёz&,'Vۄ$ɰF9F.5g` (>kŸS[ ۓhl}a8X!c롐e. T˂Rœ'"@& 1Vd `BEn [8@״U8FѓOEz9 Jgh@hnۏJ$e.jQr_XY82 _UTT tH9z~"+H0 $M?Scf"MR c3}џJNp˙$58Uhv#[, 7(cIHbŁa:]Ʃ/A* 1Z^n`,VEK3;7Dz\ܿs]W dž)ӗ]cj>R&D`NkLDA$5,SMr֥iYV}QCl[EdjOyhZ. u\~.~F̪Ú5k?mUI#~u I<۝]E# rPc*f:NZ/r]Ch Lִ_8~}\4 4XKGR%&&UsFc^73`#"$fD3I "g\C`80P0 .)#JVr)3$$y8Q5%6ت`1>,(`۵])u 1ˁn/n\,̒H \jP /;?{栢G'6C k3@C{vM`BY4HP"N¤hWUN>{Z;CveȎ1F!+`7-}I*1bIEIkuqQbK3Vq0ѱfl wm&&l J1V"Y [0ʕwo-u:QmT= F9vH >n/olb4i وNMb]S7! >6k$!3i Rkm+!DC4'ܦwJyWyZd33"F(2$Cq)y- J^a4ƈ)Pc b̥2!DK)lݢג'9#85&+Baf/wKoQ䎃 &xmg8<@Gm2 *$((2LJ^Fxl:[z%6+"h>)05] ڣ8t@E'_u*2i 4Ev`ꃠ!; 󕹁QD fY& *RJ"u] gD1,Cз9axP?Hy?0+`KPx/gbs=z١(F#PşQ̖C!F`pk"AZ5JL- Ԟ\M90b5-g%fl CaG**H-@h$D6 u sju Ir!pXr# jBuiԺp-S pop<]3"f4+an0GDEgϖNIՐf; ?L"HM;4L<:3i BS{< 9H\#z*q""IRWd}R3U3 BdQdVSd؄I,P((j u^*B`d@jZG1HԈ!4X7lF| i5AY7T:O)Tˆg?{ ireƶyw"B)"DB4AǤmjȌH-X @O|'[ Lpfb@n1F܁>4JVB5j*Ӿ" ,Ŏ;GLNP5l]8c cƾ$YIE21DI@=OUMUU;|K J+Wג[ 5]aUK 8d5p>I)uP?{>Tf4x]nuGKCtC0d43Y Z2P׶S%BWX/7#mɣVek9JX ZD&Ф8liVkByAPQL?)˥~{tr;IRb 1C2HSRn\9ĝ6EKQU^Vt9{bՊ@FhݽA̷Lbg?>:q !r xm ?Ь5"t1Hq^CٛZz8dFbf&$yXMIՈB mJ.K czD"bW63P@ЀP = j?pu9rMZX}s_ T{9a=i,hԡ!9) kmVYÕ^$nU p!_o- Beg9dX 90nև7U^&+w-ƯԓrQAE"#fsI0:BMH$V\8b=UAaj"3']iR| A31j,&rF68 a-.\C]=>ہ<<X£5&Ъ+>-JcRϞ| }]д@Ec).QUSD"׶yB~uX|rwF`w%0AZP;((;g(e1 bH+ D6b"8@U3/qD``Mg (*(1A5frӴb=NHnj\H"ô\e/Twҟ$.ffosMP !e!$IO>I~x#8xv99hYvS\n֖G+G\W !!P,4ǢAC>xq<ݽ}y* ^fŢb 2Bܻ!,kɉz%g*IjV@.-\ .lq1l7e*Sc6% _>ɧ΍ CUæ]q7[U,4`8nvB0Q旯먬Y`!;#AIȀ01Q%XS=i'儝OD@MOߟ #'$@Ĩ0IUcyb|d9H}|As*ܠgN`Dl[l)MGzqqwM~2o-P뛳 g{끤Gi9 py IkZMQ;'&q<(Ml b4is NL]`#< l[q"/W$ -;n>X4GdH.*,4QH5ɇH{nn;[^ dvs:nۍ]˰)[&H.wS@ ۭu_{2/."a|ֽR8 '^8V[,:ǍCa "aGTgᥐɰUN|':;ѣ.]܇w ^,2s̕@`LHwQUfrbYTY4xD6+jV8 At{#f3:ڽ!2 NLx; FHHl06ʵ\+O bw ,mh1CKp1T@%}k z3oiTp[Y D_[0#4j}X~7At*Ƿ ;hw#훯37_ۧ.0!a0 EfU6b2)p|*=ܜ\^-ATÖa A~l l++d>{OlS!#p#_(yє3GͳC G=q2lP^bl&#BS(w!,ŽQ{-?i[?=ɴ3nZtR[ h'2aƷnޞtYT@{Q$j6y5r- őT07BRr֌`{$b4mGCA@$PM <˜?6Mِy/с)=vݴ^gLt)._MS?dUށ5mDu~R4AڼK-ht[{&U͏$`6ҹ[EbQqlf*+p0aDtdUZ&pDT)q72r< EE >E#I\^9L-[$< X p2R _vS{HAhnp LscON]JsΠ0 #r:xl:ine\X6Ͳ%<|_ʄ]3b$^vސܢefl –# e\y}3kf>X,+lO\!̘MB@Ѥ(P>pUEnԐ!(6 d1O*c)Pn8rhM)cFRYm۟ㅭ .#?7>Gϻ["%P<;雫4ԗ)- HY25]@F[2kqm>0[Oݭ,#!6O8j32˭WDv 7eZwn.Hмcqv6C4MBNM~mZb&oH$y\fUzINBM582")( #|Vs00yZl4'UQ"Bƫ{ Ae6/t*vӍ^42e4v Om08zi"^wj`.իݢK_Hȵc #vmTHwW}Ոfyprvvxp YdvP. $!l7~o'nDAEԻnv* Ę$,́ő^|b./Ah EUVs_jE<.wdDÌ˰̶tx}.:+* c` o"ÍMݶ9\wO +8E (P׷iP2 p T%M/~ WQ,G^=>=2%]񛉐i"cs$")kghAr: 9 tF0E eZ1)̻/pÏuW[,=^t\qB~D*xsLU*bJձ [LΡ~da{Cø<<P McJ6Q#t&w铖R6ՀF pw0L~|^^Mie>zUC6U`\}i܅:6~qGHWD욄Ν8ZJӭh ݩ$D{y0c_qXLC>]\0 s"bbePpӰNADM S*A`m SPd :`:lq5?~N"DBܨcB?)ٸq_ѸϘ0'NV׈JRcHs~wyu !pN @ITߛ1dA,Ռ!9d, %{ cTɁƼZGM5n<ʦmn'aIA&:< xvFwKs-&j`אּU1A'O??;ZvihDLE!Nah۩]<'RQCq[ ދRt?"kL JN5Ljfq8D,lF$jܶփWg<0Zո[uPWTU]%o"U6SI MHC5K݊' $ɪ~7aD:V=KQmɫG\Lpqz0[7@ wkR  aIIw|"s*T]UW~6Lq5in...F8X8JAK)Fqt`0 x5sKnT0hNw-$M;.7"̣ƀ=ć!ft>j.is,lBk䘐Ƒ b qu$Ϛ[7"=yB aVOm%Iccf*b*>>*~ #EfP5YswqmLpL5fɳtf9 %۫AEv.={ef&4SnBۍ$4-,Dc څMӏm=wK z&[5WW}tX10ݛC&n=І@CW[A'pqY^,??~:_6xl eP  싻7¦Κ2..9B5S!#@&C N, v&0>݋g4SOfƨfKњpSna"tQ3N܉z5MeSj=Nv.|Ld 0-vݸX=/V wQFس[ݱ? ۟c}nLC8X>G84\,;jh}vbp#w~tZ:O~/;>z[?9_;oDE ,LF/܉X'nqVuHa)tNK|Q8dqtLwW- A$|Tw/nvbi`3DDP Z;Rƴ"7CO AM|H&FZ=?䣽"l?f_а霝^>\sƔ>^a<AP䴝z__;lMu|#q=(`F ދ@'ˣv OwQ!x F/~JA9ASw-D&@\4m//7 , (2Ҡ4 vĜT5 4HB cF ̦0v4 77V.hk")`Y^bl~E;#v('[ߴ+M WC>nZu~3 Wr#Eߙ 6nl" AUDD͂p">J^̏tVԧ7?ǽ̌0x}3q̠~ܼz}q;:SAkCB7^QݦrÀ䧀l"n''}< xcqQ$^| dε v8_X78pAs |H[(ё:;9thĬs+lTY~ݍp bDHx/ 5al(̭<9&AR`A6$oȸG==nT&_0 5(:hB@d ^Lc(55C ŋ6AջZ Aѵ`qww#f5Enhiѫ끧)xQ$FFl;@v]xP# @*DWOsKewo6ˣgm/ @v}<޼Ovj:D#2lJuF%&GwJ`ýtĈ`bA45L ~2Ay9N*Z>@v|~JH&a^;x(!>bjEf]h >&=z:ꈡ :R3ŵ)iVpM8m/7Mtߝ ã՛N~jn]i1Lѐċ6t|D9j])F &Gf"%QT(BNÔ0hy`a^_}6o_vF#f5 &1JyIVQ8Q ACGu#މ7ײMS( 6Ai0mۥHzׯ[]tIWTb={uU~_Ua i.c аie 2JOV7odV}}ѿ#<_^'[4Q [,V!v}(@qMH  ~k:( 4v ޗ% '>w# 7 A0 g; Џ>AmTU!H5 y/*BʰE7mpims},DZY4ۻ'xD(^fVvZj:V-N8ڑk;1ܸ:{N$5_ٸE@ܐi_N77wd8Κ `8"ʄt?F9@nvLC0dޏ^!rR:܎Wh9On%4d`Ji&&fB8 &Jzi)"" Ӛ9LQJ1ȼ}pK:@*>>6VBDB#4Nv `>+K)w߾鋻85n hoDGO~HAMA\{vNp30mofvY0Nh' K?mɼUBDfq"](8z(xdHtLTcÔYqOOfijiဨ"7;F#BOb"1bqm qo%; N׶AQ|[TG?9rd6"ndJb,c49;Ԧ# A]PzBDPyټD^bVT0E;a@DGVSUER֥hjGص_1ݽ/!V!޿t ,9 vz @/ۛoz^}.Ol0WR0}?{׏@FGM׊_,,ϭ;^tj}}/ö[?lu|n90[o& QtƍS3@hK?!ŀue@fP׸a3?Q p1"ѵ-2#Bu]ךm`n\Ep~h$ hV+UQZzX68e=EelO9$MrFY;]? %wv5N'hlBf5vpvj-tcFsW;9iWv?Q, 4 >:;PaB?x v.֝ Ү ? ӄG".VKfUA̵蚶a^v c0?^ k/f3W\ 8,V*uI GCqDFFn{j߷$3N* `2/Y ~t&Tz2dW78:xz'{xw;.AC׭T[R/.|_|ί˻]o Zl']~rAav:}z`K@@@øxa)d v ܱYX8ki'k u9sZa 5]"">zl]K&Sj~I"8B" Ak8Gт5idfd 9΀Z`$ݏSkv~V~?4u, *UCOr Q0gMI'|=\.]Dym> ߟ un}4M3fx^W^}vZo6;nLa"x2/ͣ~l[q2 צC@ VSC ̏jnDRAeۨcf@ܠe'(@=-i.SoAUE H$uǔil0:8lhďۻ]#K]F} @D?ɱH8֨ _B`-{Ea0Ǣ.V#XܳCģs@_ūۅ Fm$FO><<[OF ѓHSU0*|//m426iR$mqM{cרzb] 4S 36ByDj.ƉS `*5K6BD]z"#"NUbB<0Z2`"K=@!%VEs;}x1fBvGOFG}|=5%9l C/(d#j7? 8Ȣ9 a:I-Rׁ Z&&80fa^  4~^^Y=~|zW5p܀k]&2[v T5vܐܞCiPyUA@ 11- 07`)vސ#i q,Fu^P E>[5rO \״EDfi .eF4sͻwĀ/BqXy$U\2"|3$6&wq[:{fx'oG=u 5 tŧEx9 bjbFƉ|~ H8m>MM %9Q͈!1DNX8 J)H)BAvQ?"9jih`Ȅ.1w#Hގ`W e5ЏCXXw77}Xq6DCYj9hyr]M"cntw_`ﺖc4d}fp=aDo&v(䰭 KF|JlхaG85# TKP23$-F*3j9`ŝcm QailA[6sF`j"0m~E*}r*þ[1ʭ> >gETOaӱcGԪnM~a`عq k߻e_UV6A펎o~kgwK=+ ro˳ EsFjYʧE'ZoF b8d<"pH oޤD#Y@R*";;# ~bM4 7#Ģ -b4r7h0Bbu+EER dj: ˙+X?B]LjۻQZ=ho~WO8q*n [f,()H`: ![ w# JmA[(Aaqdlu@pAxmvp>}z,_GQ6}}rm`K{z'mhx"J|v<@u7>}RORdwן?_}0MG+׬0kɋf;=2PITӛ_ <<8xFX& 5 dwGX'p\p goH՛{}|ȶN=݉+o-*Ĉ-MkxBڃ=U>~=~><(>: 'e]AܐF&cK5Jde!h^pHJ׋/ǘv\v҈2c0bYKQ);6>zʙ$5'˯(>wg!qxޖҝ"HNIF)Tw0lvQfFlbHH  mjO"!$2CST?#!rY4?4讜axyͿۭt;LO"[9w?{u$"# ݼ^>Ͼ^=}˗_6IDލӇhoGФ?8$sO| NZor~TPl1e9PX [7tllq#9gCTG]q ~ l@ttO!v TD25ZlG  .t")yڦ䜏wo=  QrAw|0%'#Bwrq^.s@W?^?\+%k32:&Y4Jdqs)̈Z3.jnioDCIN4Hm Q HGbƤ~{IHzdCI90c"qGt  x'3&qᤛb9>`")7&9éњ䈀OyN8GH{rߒ37}]Dk:{q}O^8"=-n دGRPv,OKc'x+F$|8?Fif럼' G2VD%'"-T2"3-Xpdo 2$Qxf88e6dbٷgHYA"PO PtJ(0!I2E{w3>F~kn ld>ߞ;eI7/ɛ 7k~ޝ=myS^bbjÿH\כ=qnϊByqQI:\/?{I1V>o %G&"҃$a e&xƷ 'Ș8 wd 2IӃxg=l3?ݶo=; 飝 b,Ad[,{F}o99<BBۿ_Noqc?~64g#F %~RHD-` {X$o:DCÎ P'ؘ$y;#ջnX ]8 DR^a{k {-?+mB`H0D|8mɁՒû~O-bt{t lgv;^Rt~t^yclOnc4ƫۈxf[5e 0TsIzI GPei1L) fa2u$H)/Q ,9"LŤ$r^?\G,H<\  gp1KF:I!.޾g/I&Woׯvo>[y#r E$mLm>Oÿ_siݙqkat>K B\")L<^9 o ̰X$g9 xBm($ޢ")ȑEKf)mr1$sHRnQDy:ohi~qxwz|cgT2~\\ڛxoޝ2rb$<He.7W/yqU*)wŰ3dƽ@& ߳oMmsg!y厉#0O)`6%c3lQ"3roq EAifX`j=RB1H pG[8Ef@i8;j |@7w{1| E]sd=01[nrD咔I/LxY~x_}Qc" 3DɃ c)gq?/?Aݓ#{ϖvʲp%)ғNb2qO+{0!Ż;Qx8Nad •Y%AeZa"hfF&˸R8]h 6)̇np?Ex?A{c0>:c V; aG89/7}'_Dݰ>3TaQa@DY$= JY0cH ó_W1SElx¯K5LwՅi`6#C9ݚHfؘfo66 E rh@$sюT5="LsO1ȌؒF1#N|+P+HQ]Ct3?շɔGnx|?]wWߝ_쫙J'ͯfi?_|w!BHzR̾آ!u#~ogc%F.?- @DI[ v}1Bxg]>_>^">C7s!I,ICEZ>r1#"(\ʠL touR] `Ѓ69ķh'!4o=B`D[F~u '͇v[נ{W_lo?Sㆼb }<0F"Hd/P4p݋s홱\__1綤 H xKP&ovc;-v^"1/)`v$ΰ&nL#lN h<:nH} Z_|ُ@`"[ؾߙ6C]C V6Kz_~?͸TsHf "TJ\i#! xxn{[ f3P1' v-JØo(oE13G'MHX#:0/^2 {ۜ&xARƯq3z|!/ԮNADr^:њtx39[8+Qo㈠L' m ?̣pHyy׿ݪ:yҮlsQ .>r)X (r G8G`kYDЅGXÚ-". qgN"I9K'KL:N["}~-ё o =[Q)e0PfYnVp?>&(\w/<ɧtaP7OlgLJƵqd oszy,)\@@O<"Л>ȁD`$JerEm71K΄8Z܂#Dęyd7s3-bLK-?DLACy"` oӇxɿe*@>2)JwbL~'/(I"/w1]`7DR`J` qgBc$Ek aS b1*ts5FCm#STaxv!A:=d=?n~wǽJdj?'2wq@"ɢz8ؓ{hW(eC{$ma>iUO a6nCP_Gؓ>?ՉIK$opX'+S& pY X<8qoFv`DBo12ZZ|;j%R=3t qĪPxn #c}tc>q_ Ow|h;趴[<$03yKđ`Qw7Kx\tr}s*c$=11%32-$QR(1wfB=Y/7; QO!{4B76PCK:mx, U43%3%ɒtT3==!f9& (dns"H)4*b#_<@?IOyvg 4!o>C=Ot* "xx:B)#7o+#R?\{l"xPSzk7.ɲmFHtTckmgHjTd5 UJ&#"ғ9GA:#$wQv)3۰ez_Y-,v`e o/ JHۚƈ1B?^e۽%9 %!֬ͱ{H` $ƅ)W1=eW`͔wsARIH `Me#@xлQ'X$T"Ԁ~A߾uٷ?,Ld.J|RrOf,`XB [.w5YS(듳n@DSRDyBZf PHes ݜ [ۅBcm/M%{Rxff7кJ&etK]DR1,,9=ns;Z= <},0Q!qց'&>?%=>[Dw(Ax͋Pm 5\Z=XN8zToѲAff˓uiyi=ddu2II9hjbyH8XD" 7 $`6 2'r fEA ٦ʽJ2XE< ,ඕ쾤9R,7/~EƷJ<>5hN w_}H|\+|gevѩn6]z[*ѓ۷z>x6 FnL[>))#M!L9y@ahMvO\[jz['-W}tZ{OȈcIb0 A"YAЪԶr( E%#`״2MB2c!h 0X3dk{ P^-Avg(' ];cݹq0PϦAXE@3Ye~?R=|8^kt߁R;E8 9NQN5buˆ[mL b&iWO~?DaqD۟in'","@*Hčq,9e& RI$c!R V,jffc)`Ɠ7#3nABRJ^go?2%[sXH,FQ%4sLsnR]}1A=,W_W=ƎCABN\R5+2zCLIlQ}(XNKF''J+v9N$< ˬCW8"=̬L<ZsL 8?lS[%q>ܢ 3g[ P?\(~W=o`ֻb=vSaEYEX$AJĶ.asR@b^~f?vnx ؼ;͕jn ppM .$ۆf!K23$&BXJ5KJz& lOi,C ss<(1f-em?l;"3C;O2ˉMR# KHaB5iv?{oohrgS&S@]SB2RFX,ND;cb_QpL:9Ho>Sb bmR"@"*QXN(IJŷǐJosNcAz>ʨAEh\uUR ȜychEDpDAm`%"*Qsq{{ٶ|!SW?\#Y>39Pv;s\! Vlt6,Dan\4}J_|~oR_rC339{h9ҽۤgd>i#.H btw}Pi $NP׌#,̠Isڸ T"̓<ȓRdm8-lMOgw;>IRRb>EAqZRnNX[O!o/^қFxu_=!R,C:yNhҍԍ3Y$ k'xv$yGdcA?خɓ>Qt}w5XIJ5" h1$p,㹜-AbYZ ywύF4x:(pUiR1#dhۇ*cN0(y斓yzjqH$hncwHJIY=fO2"{z2W@y̘4ʰB6(H&ޕNSyFXP.*=$YûMRw ~\`iI(J;#)8  dgZd;[O0E8Q[D‚:3\$JAY70-3hM۾*"Ń5rhϘ 2`GGK'J..40FnO&'4|iB,KN#  qn0Fvk -`4\8H߽/޵"a]©? 1wf aSL4҅Ȋ)SxhD|LR2R2GI] !Jwp8D:)ĺey\! sa``2Hxҹ)mDt<(&x)(it? ۉo622b}w߾'_>r)KkLtwwN$=1"B$/e ;0u͜cg<'gFh] JpǦs3WF@K"7f5&JEZOap&4pq#"0G]@(JF).OYE$%*6{H;Ⱦ<r>Axt!,i,=hv\{&McdGVF3Q" N"\b)<ҳ<)AdiQ"n00NedOl)ٗ_N?F]1: 02lƊ%<0f+CYjyzfΙXRBv譧$rGɤd Biᢐa$36! fCs&`Er06ozo?ǖL|J|3,EFJT}W?~HfP$sF7dzu %U'aoRGN,«4N"D$_D$2SR,+F:o|wW>1<_6 TaB*HRd屟J\lȃ1ޘDD EL%_%G5Cʸp@rt0J7'HZA9V-}( A;}ZȓBXOLB"Óg^3}+%GNһ\*yxh(^TLf"wȼW:SfPK-f\l@a?&?O/??P\KfZ!T{Ҝ7粦VNiW}xS );D&UFŦjS- D< WDFoaLar6^1>)+aYI8ngw\MN( @`;?1XˆݓÛE&V_|ӟ~~wN!SXXh[TvZTjp%Y0 L2k/TJNr2t:sw3^!YfeTfJe!3(!աZ8fPa U5ANݹx nVjZH3izK U< =KA-˜k&Q5ҁn)$ [)o= <$U1sff,i"zg?'?zGo QpBDԣLu)"Pfp*{QZ=)>Z4e ߅EPf:=ڷv_OK^{sVy D,V@QX٩݂4e=[IClI6sc61"Z[0xO¤D[_^v/^==ճ/: c+a.q`ÛP;kfw͹ɔH@ M#{D$x\ug^ooLRMb+35QP&Ԝ̃-ك -Xǵ>"ɺj>I@fJN .czĚd.*fA3hee.IYH0EO%9 H' nv{~wςq+);^C}@[ ?IHŠLBA<ܖ kkH㯚D#azW@ 2:6NDE}\>SpZ"Qjdzl@z>Zl׮^O_< #A9p%8 $#͔A$DZS DϴTcSȍ5H@W OL')Bݺx&Tͤd2Eޒ@L7N,ȤtH9{b#'Ӟ;S8=ޞ#Ͽ8OG 6MJeͩ}/~.z{`dF\)n{wKxx{gҩTRAs(@-n=X@ݺˋJ?o}]oO]}^ ٻ=a\K8p?%tт$#x73)$3wL%C,}3WV@-9cL)"ӴD$]F'WG&M}}>{Gܒ cwO99AȢ݄9;%jWKoe {w*/ݖp {x Bge Oעr>c~1,\Y,z 2N>D5ZF-2 "J ܪBtO`|"ΤȳϞVހnA J.eNbYKxt}fG 0GxtH:}eFHY8b1xoÌyp˨.H\)u%pKIke.×\(#XTI":[2rZ)ifNR(t̴cZۆa)H:4Uh0qDZ-9JiDsFK-wbOqq5&=n#b*O& D33qznfgU 9Q$ إB2yӆx' |$A VVV UwjTIջTbOUikDs» :[jF\)pv4AP)NesQzoݵJqDiK֭e1LnΕ px*< ZlENRٜ*2渡Jgk>=2'PRy܊Fi0 EƟ /AyAb-!?k(ep3u֒K~։ FB=( xsDid-\LԽϣ;H^^EO^@k-1cAYU vu]h(Px0,}TL0'KAY[Fss*g RN@D/Ӳ@UY1.D\#o ﰀm ML)uDTҳw_%hy| $ȃ<TfLq{oNLrq觶.5Ҭ5WX%u{X_2DPw;#"]-/{w*⨇% ( 5 dU^!"@aSj(scAL c:۷5iYwuOB?B3X+@$! UQ]5+D_73{W{c nq"yO14B&A'ήWmKźTT]^+FEfX.pϹ^^OLԹriGkD6o͓,xѢ%"'Ee&G d;d>%{Y- ,ɺ?\%2?~;='@(CJQ VѢV,)T T'u&HV!b"VV;"Nr2pL QCfѰ0A|uL 9:iN"K3*%^]r#Ǖ')B-S1jNei[ n-4Z@ퟬ`2qz;#HC$ޭ݅~^'2r]bڵTЗ#R@ H(G$k1cMdg49$ciĕ,̡h.S[_\Sa\(|u':R֕,XҐt l hz2[Nol{*(U+3zxDydyPL>+MeiZ3{3s&% Gݳ]|s*Xvڵ`"+i" g:M IPYd$#F)/Ԓ-rF'Nfagf*,^ƕtE40bDYKEFZvuzu]Ϊ $F% --JE.Qd7o,zþG6uJn‰{sサe-W׺W-^BaLEd]B#N pw CXk9Ćr!åH ID4?}\E3o#\zMW&Au9BqU2+sм]nRdS&LE.e.zP)Dg>MтI2<*1՝nQnrjDp;;[N] Q53&.*N@g7K[o*a spii'3?>+"d4y$k?+ՈIZ7)SUf@#ubVM;Kwp7S.}-Z4CT'(&1ăBC@=*AkAbL\X͇斋BǷBH:0I]<2_E&V,0%,&ug -@7ˡiAfUUA~mfFcH${Y2yl<{ofq=Ta$ʾ:B + 'Jd-HGI--靴NÁ$ރZ$ODe'n(HH7szTD65R# #!#i?bYp$ftD/ާ¶dLUs]}~Yx_L&ɂX2GW~PDH! ־5YKXSw|y4WUPX'@zfPڐwŠZgmKs@Eyx}+{q1OZfq7'y&Bo3H߽:Wx<3 }әTI'Z 3um:|mmf{ZK.U'.Q$GPEĵnRڛxV21ȁ\Ljg2"@z:\.$w"C4؟MN|>_0T*ܹv}GXt'g2Lnޗ%EwnZ{etoǥe݉ Ӄ,ԗ0O||B6tFոDj-iWJ)>.J4wk ;n*( o`N+p*(Z'CzE-݃fZt7-umlx>0kQwzpxn\c2uj) A%(e\a]:#){vt1.r;-9H/5^tr׶%j!+{Aj*An5 <'j3ୣI.f=w-4*:;  ')4&[~"ªRj eޯ( I+l7T LXРn'mLEBvܖ|jg)j*3*PRYy';ggr>W뉬zs(A(a} H E%Yf\(3zb}Y n)`4waٕy*$Jt%n\2d޼O?'T1Iw.\er܈uOSUzJN$RvrUXKF,%X&Ӻ"r(2 ̔4Eũj6F`ɋR!6Nc܌J,U"~\>jjfH98Dtsj+A衮ݣCKv;}>.)Bځs܌g\lt bX3k˕u"HWukwٺS9ÏZypp~Ld˻_' )9Z)ha~:rst|;!pA֙>5NT27KQg"fgk@RgIV'ڤ>#ZwQde yyapOa.ͷO=o L7@R$y<_co2"R0iLE"&(2=I{B rjuw$̇8{7Z- Z{\ Iii˚OcQx,Sx;1H5=I鮥{Ar'-}'ԏWNnóHp wf8]P}vQUIIb}]cLM0tI &LzBYr%:)U<"bܻΌ\4&FqZވזpR?-]4QJsXV@R:"sW`8'r0-Ё(yud΢E]H0e}wMՓ>rI@zVZXv򶐞. ֚(5b돓Dc ^fYfOZ+eቈݺN`quVuN:.1v8]͵g -PrYd绳ʔ \T5$ikVz W-lJ]`ԉ ޤ `~f=ʼ-(V#&3KQA$z2zEzcu+r:^-9L=(Yt#Bek=NxhJnANh\S+:EʄeYw{w͛ٯHf㱞qsvCvЌu{4y%n,2aftۻ!ٖĒN4sDwT#!j++im-' .p]V8+~=5?+N,2NaOz7k dBDuއEDPXZZSikHyZrjbbSDf-'CepyXgXG4dڗN#RK})z%@dZ!%piGpQo.U Yy \/S DR ]=={_?{"hS/ؕyx@5)YOT"w8h:\J` zK'=\zn6qϖ Vt 0[,|:M?)xjz;ե\N[bH}}-U"fRtw>_ސ߹ypܖ,c5on%`'oEkF$R*Jysuy/KE5܍~ 1Wf2u?eiCo0c:&P+Y{R[ֶ81 spcҠ,* nIMwɒ|-oZy'g_uz;r9 s !.7ԛ [ L륧J,umBT iEb9*XwwIR)ydyiuLDR8imt?r,s4nd/-Γ>TCH8*Pı>@S(\ C3@e/;fua ѡ[u;zj؆gA:{Xybu~N} %QltS4˴4Y1eYk7xƎK JJݵ:xj|+~6Qȼ]a> á n!^7)5sgB.HLj̇ {r6J >Z7ԮF>O>GqC|Z~wӱ_1j'ѧg1tJkHQFWp psnXD$9:pFX'<@"<-8{4%hJqzw.Ny`HV6Y^̐8C 6da-Ž>Z3z&SGIz#Fiл:eb!KȲ2$qN\:f#c) ԮUZSp>ŋxW׏U?}AyeUp?9 PrG= t{sd̺YX 4s=4 /C[f&h0`ZTI z>F )|.mv Z#攮WZQ+ui4Os^~4뒐bVeomn5DqԨ6uZ6un}Ͼm]цp>koFb&l4J:?>8*C_b]#uIx=:E$9|gJ;5@PtJ˵(K;̽U32Q4:rØnkobn:QfX)[z?v6̙[MBփ1"X!V͡`޶hǍ!ľ +(|{;6fxl&m\e] V0.3zmHG@WK=Bn:9|M{5ADPf<0.~o{.l =C\ݶRb_U2Exɝ2v9@{a)=U]U͐،P[?za  LlpZZqԡ[ikf}PJ9/sodz嶥Ӛzc?$6?*qI`; ι7FkyuFvSs+{.#" }5}DB!dJd"$V ᣎqp& ˆĈ:q8)M_i}@LԺG}I:v 8P9Sȋb)N,\(); |&+qL̳'ңBψGŠ$ZWD WD52 EOC4Ih+l멷9=gy–>k]2~~!Wqgsf0q#ĵ>"`2[כN.HS1'wuJqQSt{>KJaV( {, '<Z8IEYT%ÁN4뙞XE>~! 0>be%#vK//glD6x׳BJSI~xErH !ʨ 9+T (Ѩǘ2]1` k ~閲}y%㔃UEEC!VՀGǵ/O$YzX@}XwJF,EGoԁcZvx"v\28D& 9 Ke84 :"AH{l7܎CAǑؐ]QPu3b =-8A$$@E}?Z0$;A8=.Q1AH߷/Q"0 yeV^}\ bBF>A0U= 3yW\ mw--KsYH V\P}0Jxz{p~_~9ACusôXݏ$1;&0ETOgGQʜH6"/>_@GGf[&ZS@P+Hk3+K?C#o؎n:ϥ([j-lj_.O_D4l;yg']:2y3Q\zl:[MA{5k ff G` mA3 l@b0Mԁ|Ԕت8J6?`Hl9>T#C!@QP\,:уgI`GI Y؛(GUQ3!fpQ{hNA 8:t["\k1T&41z |_UbV>lVL^ݧhét$ncS;JBÐqT3r`@$y ,NO02hv躼_aӝצIH.i4J>(.};=~7~?|JIUo4/zODhpc{oGUnf1:>(63j*(Af=ZbD#ajf<H.UB:YQIF)1,Ovv;BuSJR Z,2/  V 'VӎmNybbH£#c-Ďn{;=)JXmgc˓dO{죃Ay*ձ9ȌZ<˗/?nS&Ir}s9?ýarΧre!^Y赜,)5Gf,{NG|*$fCURic&~s\2pN>t^nLTQ&C #dI;^ߏ۞Xwhz>O/'(M` j̜HAd'Jb*34EWw)Jeb WFsqMRxĕ4BWM"M<xZU_{^NP%s^#&.!p7Xۘ)g20eVuGf7uuכO FkRHH}ˉ$?Z8^SYjNP)lX7D}=XqP[8ʰKߢe{쁚LnwL|}?<,nVM@?Ogc5-N[/5JFW!0@mklG0"*N'BV[:iuS n%dWs|{o]!:,޽_Sjڊݶukt^|63r7#uZ) V*Cu)p[bP!G9G+xAoxۧ)sS\γ5aVHHQj9(ݘZ=4i4x. scg6+fnpA\UH>`HU!!@Bt1 u)K*N6p? O Q(flrF ~MَVq]ځ[9BHX(ϧVI{P K.t:pSbjc⾷zZl-)~L$4v0?*N9dXjj(:p[=P܏w8ou=߻mO/_m jQ8: [XXbܺ0|}źp9|qfc).t c! "?% om'C(TԽ:Xգf?>a:x%7YV>}#؃†DvK^iyٕx)\}0a9 xyiJq-i?:; Yc|wC kwUXB#ЕV<= u.ĽJHam](\%-1G"t\ I N S}D 4F-_{w ϩy ?Js;! pmu:ecQ8ADbr|dqF=etzJ|}Kk݋zk66G){3tهLPV;[ yues@"Mkk;%2Uu#F['BX"@owJØ>y/O'<㒥7ewa@!c):([j84iz䛶˖Ϧk}LYx)SG К"BEׁkdǾ 8qG!XDP?cA+~t ]`!H#RvڝDv?Ϸv({Hɻ 691){cNdžb*7e@ Fiz Y%(i* CN8k14H"@zLfh0}cYmT )@[\*MA8zu|B"P+9Qo7>%Χ { n0xլp>m 7xt3ACm4HD_;p!Wp9N ۀaܷ5E)pZ3ЮUb@#0u@oeQzkA@Etֹo9o׸@-0,Dܦ@A֑U@,O N~P3ZǮaZɇLcz/׿ӗ2K)m|GY0Ǯ/[5‘ yŠ7ÜPLv :MT`ԝ Mzȧ5Vo{?bhgWim6Gs[mOz̔]A~( lVj#>n-ADw.6b? a^4ZO{Q4 pdӺHk{Wle)*(ZܿB8R)Sk؇A慼6B֙5(J;D(c:w|Tss; s{l >|4?D-gm[RL; '0Χ}IBS9CHU&꜖68*\==xsI%܏h"he MFڴtG(kƵXox[" jjf q8#LQFE|,)Vb^3Sy"= 8% Fo6RlEep7AmIO=$ΈȻOM XM%-EHo(-x`Y`JLwQư 4(I_~֧L(y:L¤cks#6a8iL%>dZ%8n^nb:BSތxlH[s &&b-^)6H̑Xf9 XKNˣ48qDYnS"G%M :B=rk y,)X;Fzo{8/)VTtvGęc"SSsC@ڏN|ݜht{㷷E)1$)3ߎM;c>OiEU_ZC24jE`1~AzAg-ͣ&{xch[q$R zIY<3#GӺ‰ =A2Ʈt8b2}xi@dM#ࣦdfn>}Εrcއp4DXVk7$ոo98)1Z(׍dh;B,O!vsQ_< pOx\s+=|E䜇"c%9PͶnIR )R4) *"6zw Sԛm 408@tQ,0Kw]˞q') aG=em,} Rܻ#:==e؋Ls:J1Ny=-q irn:M% eu>>Nv_A(MYI؎(g3`#F `mx3@o~.۟~fd:78-'㊴j9' ‰K:3AxKmnõvJֿ>~v~ ԋ!WÉ`#@PR dӂ}},v93c 0DLe-!L2b,i"b`r}' (sM٭)CGAI` Cp /k`QLYxPR ) Fw fCF #؏1L{cƙW3Ob|n z͏oAM]s^5<"ՈB$aeהk2ΌV;|ʑ ceo}9tN/} >B)`Π\1cBOR5TJtni~L9Dz0?G\򔵮ra:(6۞VVh]JX /Suy֊59bdw0Ҿ_H!?KrK'Tk!}a)ߪOL8`q/COp\ϑFJʁoN.LޯȡᠣRfXGHB; ueqSnIdԊ17zQH{D]>эYHˋ0qDr@"&7pP:aCCH} s9a]KVGs! *) iD^/¢ŐqϥQ,DӜ1Ρ|:c"y naɵTn1j4Ioel|\י~4ri%'!f3|k(1?WzY?@}^GL{ 9_4^ GrHic<-A;ωTe,_ov߻p>̱̉[sFbsC0IbG;z0B3чAqz~[ Q b&wz w SGNZI" ]F])RH_z>nʫLx)cAp/OP1ӧHBA5&3 1岏iKΑ:a;BLS{}?4lBQrMdp ?oe2߽}៞~[#~ )`"è% @)7#/ &(Өd:v~bK&avev/!BI`]N[u~@>$7?߈6@3QqӗOs} SH1ă8 ~׾^JCb\؁l` ˜SEMHiMzΨ(iZjŕsvH4(ygidiB.̈DeyvLnzJ83)>Fm_(N1>` 2/_|Uv]]:_[=/yf:(ayu!*_>Fk}ER^cGGA*uFgKUkڔb@nk"3f/ZxGX>ЏfBp c,l .}£夭+eꞟy~911%18ZDaIXGzk3iNd}9 Y(Ts}x`G+@\Go,2rQq m ?+3So$AGkP[B={TM 1$Y^)g(:r.G &1 c%#Q7(4 /_F.ښ^o)M{)˪`P3VZ~\n#"K*cmm H˫20PQd!{Sw6s3#~z:k=<%e/ ?EPF)hty16J ŧr-KXn;33sb{Ƚ}a]Nxpxi TfXh$qqybHD1%f8L#Rr L:J<|2 EK}OC{OB9mvLP-U"Xo\$ABGh쵆v0,!GWyY]|UOD!w;:I;h<$Ln 8a9ЕkEfw@ꛏJZRZb=J'go99FPz0{anڬ isGBj%{?ۭ,2U=&cb 1zU0N)oƫݟ{+rmY}؄!wzO(n]H()Ԝ¢}1qI$Tm`z:a弼$a ԯ0~Oǧ=餘ikiGda9|uc>c&ھk':emw]R(?ͯG;[É$g!}|QaTꥎxFB4}hu EwOs\*R*?萄ޏ8Zc8$6vFaN&TYQ8E9.c8eg{/s Av?XsBx4m=(0k( >J=ޕ%hwzHԡɊe=)%!:$.LoĈUP$6bV[Cq0EAȼTaEEC|]aaSƳ֐>HýVa9Ma.R<p ]H]%hAO^dIN^VhHTPR4QNȥ3OԀ(Xx$ڴ]Qdi-%7;J#D`= #y&SB/XeX~__"byO#֥#޷y aZnx\$Y5MJ_1%~X; [0;uQhiu>V bᅤ$| m; c@߾tǸG}/H(GĴu{)3!X[νIߎ!к2$rsm;%AP 7>glaH8i6NZ'hAӉT!"Tt5ϭX55LgY1+2?lCH,.>̓r&soײP{`yBIʭhJɤWc mu4 mƤM&;.U1I$9lv?}Og%:qR8&KC5,S-6 J,wD掑 Jmôa- Yo?_et/>mPk'[l{ :\^^bzؕl6 @h{PkzQt PIS}<7^l:O_nB=/5 ydFߡ pƙ* @.;!e}8Wd@j$0w$9o{9 Q!tq 似k敀oEqr)k;'s)!iC&` (~ r\fa:M]GQNSfA؇zI&v)NQFOYRs"Rlϒ_>{BN|굹fe raKi qL0zCaޯךe1(9YmK5}c}K/[OLjD;ڧvPȧ~?<}7ax܏4^ur}zb }Y$oYĥ痾˓˹܎qx:7I1PdK lxl<{KV{KB0I:'เ?.7n!Ltw Fg&Dh2~ !a^K@1{w2k~L] WbʡT9y8#0LOQ5Zm8@?'y9^Luz.oNiS2sSfG 1/T}~x ; {\ B"3\\a~9/ƎlP(Lr5Da%YUXU0z+2(}RlY>#*alܾE0\yq2lc8" }8%~xۛCв'd^ *JS/ŘP@Vnח7a2lÐc%L\.{s] SCƕV}2QhO3zaZn_ =ԚCqo]tB=%(~>*>n8={H dBM]}9FL)九Ϊ5]hF`@b\WFYO(G.}ȗz8SoK)mS9Ŷev ˙t*S\?k-$nC}7nS_~;.S{i\Śӿ!hu7j Axc<=pkÎ'yyr5$廥oЗGi#bFSs$3 ~h@ݾcF;4B#F {3 ? 'H8O|N0S#H7>&Y=z#e*@tx;`6M HqjfOcmDH;X=O>f߿~>oG,>th b>߉~ o3o;߁&?LHL\У:cOX9|M q 3a& ePCqT-$%栏e|x{ ( ?TIENDB`scikit-image-0.9.3/skimage/data/checker_bilevel.png000066400000000000000000000004261223313777300222500ustar00rootroot00000000000000PNG  IHDR IgAMA asRGB cHRMz&u0`:pQ<bKGD#2 pHYsaa?iIDATcpV%tEXtdate:create2011-12-12T15:51:51-08:00K%tEXtdate:modify2011-12-12T15:48:15-08:00IENDB`scikit-image-0.9.3/skimage/data/chelsea.png000066400000000000000000007256001223313777300205560ustar00rootroot00000000000000PNG  IHDR,0O AiCCPICC ProfileH wTSϽ7" %z ;HQIP&vDF)VdTG"cE b PQDE݌k 5ޚYg}׺PtX4X\XffGD=HƳ.d,P&s"7C$ E6<~&S2)212 "įl+ɘ&Y4Pޚ%ᣌ\%g|eTI(L0_&l2E9r9hxgIbטifSb1+MxL 0oE%YmhYh~S=zU&ϞAYl/$ZUm@O ޜl^ ' lsk.+7oʿ9V;?#I3eE妧KD d9i,UQ h A1vjpԁzN6p\W p G@ K0ށiABZyCAP8C@&*CP=#t] 4}a ٰ;GDxJ>,_“@FXDBX$!k"EHqaYbVabJ0՘cVL6f3bձX'?v 6-V``[a;p~\2n5׌ &x*sb|! ߏƿ' Zk! $l$T4QOt"y\b)AI&NI$R$)TIj"]&=&!:dGrY@^O$ _%?P(&OJEBN9J@y@yCR nXZOD}J}/G3ɭk{%Oחw_.'_!JQ@SVF=IEbbbb5Q%O@%!BӥyҸM:e0G7ӓ e%e[(R0`3R46i^)*n*|"fLUo՝mO0j&jajj.ϧwϝ_4갺zj=U45nɚ4ǴhZ ZZ^0Tf%9->ݫ=cXgN].[7A\SwBOK/X/_Q>QG[ `Aaac#*Z;8cq>[&IIMST`ϴ kh&45ǢYYF֠9<|y+ =X_,,S-,Y)YXmĚk]c}džjcΦ浭-v};]N"&1=xtv(}'{'IߝY) Σ -rqr.d._xpUەZM׍vm=+KGǔ ^WWbj>:>>>v}/avO8 FV> 2 u/_$\BCv< 5 ]s.,4&yUx~xw-bEDCĻHGKwFGEGME{EEKX,YFZ ={$vrK .3\rϮ_Yq*©L_wד+]eD]cIIIOAu_䩔)3ѩiB%a+]3='/40CiU@ёL(sYfLH$%Y jgGeQn~5f5wugv5k֮\۹Nw]m mHFˍenQQ`hBBQ-[lllfjۗ"^bO%ܒY}WwvwXbY^Ю]WVa[q`id2JjGէ{׿m>PkAma꺿g_DHGGu;776ƱqoC{P38!9 ҝˁ^r۽Ug9];}}_~imp㭎}]/}.{^=}^?z8hc' O*?f`ϳgC/Oϩ+FFGGόzˌㅿ)ѫ~wgbk?Jި9mdwi獵ޫ?cǑOO?w| x&mf2:Y~ pHYs   2iTXtXML:com.adobe.xmp 1 1 55/1 3008 2 82 1/6 0 5 0221 0 1 2 3 0 0 False False 0 2 False 0 8/1 0 3 0 2000 0 5 800 1 0100 0 1 2 PENTAX Corporation 72 72 PENTAX K100D Super f-spot version 0.5.0.3 2009-02-09T11:11:30 2009-02-09T17:50:29 2009-02-09T09:11:30 ׬G@IDATxT݉$Gv&׌+P(9$5#Aoә4i6ٍF3]o^hQBvow3oZp8h4khI֨Fx<6MOu-?ԎQcǽkqxt:NYojvl]n[?=zjuZfZ6s=yhv7ͤІv<6vCM&o߶vwךn9\kwuVk^)pܹ<7ڧF^obj`u;?`xyy1 `0P^E.kN0kn.#趤V}_mnw<_r{\ovV1{\.h0?l/_]N_z_~mk]54;7ׯڝbdׯ_u~Oz5Gv۞_jmɠޥFl5l:_=ϖo~5/O^|8 ;M.6r9tZOyx<<jz\/&~8^3lEݾL-Z;z3E۽˕Ynv}+ӀL`I.vn:I@{q%"FDyRH!!ZkS똶戸 5kK~lvX4a:NRBk < x+6`zlq/mȀjaO d;)_}z3l"g|v0{kU18R>|f(R˰F54?s5b_-7 bf.WCwgy*gׯU2mnRw#}ȥr5~ːeb3~mt3zt4e33{0eV鶑!P!Jm(m( nk<kԠ(._^^iJg~v Xԃ؞(o.sin Vp!(O&7N-)}niX*:S^FZYaBpj]nVod7j8Nf<]~N÷h؛-7υEj/ۛnP;l+(~7N?v|yy ШiF3m짟ߟc ''cnW[X<~Yl߼r;9mvF@L֪եhN[s6ba!5Ms1fgͳnS,_OEUڜzϗ]BbԛۺBXްZ.f}m+2wnYvp[/iOYpnm0j j!NC5k0˓6 Lh+(i5ސ0ppeu3lR"ш~! ?eK|#C_i'H; ]Ek{TŲ:K:}/Q27ձpZr{zYY/aJ@ׯnx~jw+߼6.OzP[JqիW uOipן/׋K[mn48vOON3Ï״&-d2iЂe2"ؐM֢Z ޖ,jv.\; ݻӨCSfb{0b{\̡>ڮJwUwWwvn 7hɠຝVߩu1cc-ѵhDBA/3ݦՅ҉"KPѦjP)ˆ*k< uZ"!o=V*l00&7  6&#ARMZgd84 65[VZXD,>if8b%" 5(g`,cF̏%q`r m7ra˲SV|Fx+BO*JS 1^|q$(ٓ+lTT$e$00jpU1deJ+ЪҎLC\5>+g<-%The cYBAA}y=2vX'kھ֓5@ LM`IKRuVp8\5*Dw36*C8F: !+ZТ1_|jMLΒ]okmJ\Dt"fVe ťKTlN C^~jt9}V:ޠK%Rp$WbijiR1мN eݺ8NGF{|qp҅/=U 뛟>|}}c$: Z_۫OOϓr{ćo[߽^,Wc > Io=?Oى1޳is\6ŧ[x@2-NP@qV5Hʞ 'hOzf3/q!BS{b~`c1Ŵ),F>lMqGT< bCcC Mz[TBfB00#Mn&մaK*y'~) H$VGHTe!=/0jR^f gX Hঐ\1$Gf 2;`q+$ s%.0vR㡠p{CaHV&f8r* #uJ{:ScH!չrF* .CUjU5&QLύeH_Eo0iU{"2"nJ:R@8r>kPq yi>L4M&C4[!qˢy Y?hF.Ė&m]7 aD9n*HF"Q=?3\Z Њ2ڙ628gu=)BX_ׄQazB": >1AfJqwtcHt ut6ܚePi0h~fsֆw߾iv?|?$ݻWWS`d͘dEC?|||xFО GYȺ9voVryz˗6>}z|1c JJFcƤ4X aA_ЯJSc2nFfpe7aHՕp'e_=qV-֫d ,(|ᔟp#EÇbFiGOdTTuX(C!u2fj%>#z[d \{u*Qvd"ʎ|Y^)mZuނ8$ b#~5E f\i*oc iL_Bp@].Ѻ΀60hu'lvр4ZCR 9@+Vk[U׾rYEfS, i1|F\NlLz=n%*x՘XPpwX/N1-~Dϖm퇿yg,?~!bG)ף!Kk'}|> NO'\7s۟?/MvZ̻֩s4)mXLAWrN~vzݜ^^ܣ.2zjn,6dV4;\wx)@xmo﷖47 8Ntm$YS B5``" {\>A"Id%iaLh/l *$$FJVHZaG_ݓ$-?KYoeAicJ.rK\PoXO5͉(m减hK#ÓaᲬoO6d$~Ckuܱ^q1En-IX/M#b)-Y?Tc\5˱KZSR@[Mʅrdv \VС:"PBXV;d4!۽U ed#$~- B8b1*`JR@HK !) Y]D}nE\-R#dF2jTO M;&^ Ib\6i^|_#1 1VJ3)YL $Q* M:Wx3"UhlВU c*X 4*VRUvef}fqZ*s~Ԗƿ\eƷ)s,ôgp-.@[Yy xA{$:"*擁67D0^iG Ď{HDFc `_+l Yq=ΐ-(rn+o{YV]Vh딾vSIIjX8z H"׀mxqTfBwF= 6&!RT^jrav2Qc7,MVmRN w \Lks2tڽ 63w z|uښ|suŪxv:$7?>>o?}?F?Z//F'ffj?ǻ%`Ҩ?ln^]-7ͯ?f?wǓOif!_ ]-#L-kbC ٚb.8 ʲ/ibjimAg :.j&iU 6%@]߿I,J7.a"-:Mqt۳8 3r07IʀtZ-~XH8z-&qX|⸗?KRFQvVÛYzf+~LҤa@5~"7U,3+M r w㇬ {u'tsŽfO(1WzX#Dhn O<ʌt|nyYp \)ՕAt% p9b%/cP/VFZ0QS ,2gGkOf3U~ [߀brnE\0ؤ[Ĝԗ֕iKegȔJHjJG+7ZJI{=jP8J?*Kz Yr`Y֛?1[~&-TcKbt^f/2YM}И2 ǯ`;p{ICcwa-8_< O|3ٵ S9d %}]{#B`HHeNd*-J3_p|zYaɾ&aÒp2FZ_n }^i꧴JΤHSis˝t΋Xcd<~5NOO8xrOny:8ݷ%|!?"``0xk?}h%-Fɻ)χaG6;ӧlP)5#P\2у~om7DH&>5/N'ٸy?N8%I|:;ij 0 -= i~ig5{7j7Pc`1x\Syj>#cq͊\#fVY*$95@eE_%H3P+Ш=1;^$ۺu!Gx/y)+G}/zҿM؛ErScH2Es-x2쬨P6> a6Bu5CBy4{>9 NI\NN/>ܤʯc\A@;pAGK)W SFTip* ?hJ1ɐDj-K!5dF˴ITKXp2(K %4L)6}fL,1Fh;UDk (e#uIj*բKP>uՎA-E&g+&@#%hK Fү6haITi^ `b8U&[Ta3?Ä&N*W&@eerNXmˡBFq%چ"+|bg')S Eo%/v_̷on..=7? Hnw0><>-Pi޾,xl|y:8;NN'g|O?}j_ȀlքGWAӧO+K$:)&d ūڧN>"˓D9P/ZEm;>lސ"_{] 2ZDY mm ILSLeJHd&4_R9w_% ]5,% !'6isUxqpz:S Uq@!PY2 +pMzZ4*9_1J!i%wp:W( =3#_*[U*칇rUViQ:Ncǰ`5ZNC&+L;('fr> E>Q Nn&j}b4d[|ԞٔFH/h.OQ1j'QY{ʓ {@E1LՒDRZ`bt!=B\NKHô0V1.JmALjEWWinXᠵx]0\\F[jg`:?c?:ַӴ~ qCI߼}|μцut-dn?Ѡ{@_>|gg& 9pAիk<߿D4' .Oӂ.'Q!<.Qzl&7XkcςD@:I{BvF^*On/"l]s؉e臁5n~ gcbܸ^AH#ea9aF$0,Xxg:VNpi I\ږA,b'BrdsRBJHFM=BpD$y l|R+b0$^q,/VccbL4Q"\nީ4Q;!Ʌ҆R4k 5ip*-R{ZoiZJz.ޠ0< QrUGBDBчATO0$+WFM`8՞ܗ3FsLÛa|s3M ڠׂtϳHRfN]m׋Q{Via-~F(XiT{Q6Exz?G^{pxƍF?}ws?? 'f}~CY&Ni /FS7~Ssu1aj4n~uMOZ8ΞxY==9?,kM1Snfp pl /?:ivZuT?CF8}uD /?R.IU͖aM(:/J%"N@BWTbx}bDue|eޒ+(5ܗhb ,yvX>0GT=JiUT/`Y~#Ov;B#zEZ>ȇBD[dA#.ᾂ$l+%0qrIJDJ2%/ 35SWZK2E/c eIhWTM%*3Y)nf[HeͮnfpK 1iOܔE7~g*!+aOw6K'CA-7r,"ҝ8]EdTjt*+bUf3!e{T\0_ÉieVe凁('td=YeJz Z@bm6+ybNLgH%b2Cg.wg^aͺ,8%3e_S8X(z:ZRy %Wae'WӔq<<༧>k9˨ ds4 IXԀHBc.JY]՞jY)r9鹶+?Q>+$!v"1rkIZ*\bR~aTC6VJWL-|ZS&Q1 K{'ʺ@ik/(80jؿ.=nef: |/|]u-'UuE4JSBa=uv`SnV`K'KP-!s&htXd^đ'UK}&PRj%WJ.X2=_ zbq'KJ(WWL"琹IL˴esC<m-X_ٕ„ Cѭ6oWfaV +(PeY8ҢC $l~ qYb6Sgn8 ,+b\S22BrɲsszzcpO8ŃTyE$8NIcEM?L J{uyyP2:93t *!f@Z(7n(I'Ѧ6ϣk5i |z뷯.\߼L>~#H`kXwӻWyxf{=|eOL//&ϋ˧/hRqI.nUE8LSb9c 18>!d}"o_f.;8%G>W&E$e}zfNi\8~ճpII#ttþKmO>@RW\QLP0}&iBÝS" TcLQ‚Y6 0j]x5,"*Dgſ(Ņ{T%A 7*ªEZr|w2b$Xc*h a\i0{,IV$QJH7szDO5mk6lH!eǖ^#R4NisZ5_1pA%E3 +`^$//bJߌJOR>#Xl-r75fxa%< T2.y44/D.cWRTV )%) '[!*M||iْ =|0QӲ(,!)1mU uP\YS.2t$C!#BTROYfj 03" cX„ 9]:;-q`䂭8eV{= QY3g6Ҵ{=Tpq04턅nPSD.M?8*Ph|d97IïūS!^+y\͍p>ᄍfd~k{T4yڼ=<<9RKD)5d28NONklYvdpy zo ¹-_=&իB8>=Lg}k? : nF!%6-R.jIw5ln)d/DP_9.t #joJ q1o:m@+[ (+}% >th Fu< dz$ #*!sE2p145@n /:e'D D (KQ|hl*u1Sd."v,- qE$y6jjʎU){(RTS8W6&kJi/\\_Y>y`oRy`:#R,%iO%6O̍%R$k2^ITȂ]j}9Ѵ)MCGZ*K.) ~C" tf D66@2|wcLi c\B}T42.Gp"̄I04 5W KЌ1#iR5*iŜ@% '.w-wq ӣɠwMxuF!GSM^fub9(ʔwEZmڱF,8 b!ߠ̤F|] ֞6KGz{$./_\N🾀gNtu}y>f$Y>?_\5ٳQ^ljQkܝo>Q&o/+tH0,A Os@S>~Dq>_]\3槗9/X(/0 ?/q@ ?0/ ]mpJLt-$,QvKJ'E8~S3j5n9&{2GS녭2Wz7daT z6}IN5`Mna\@P6 ^nfIv6cZK=)+N| EAN ڔ@bFkVeusrZ@L6 ̢紊,o,XU2a.Vۥ}_cR&.) ~bN0 +`Mpj5 GgE)3B"*42IüZ"zGJM3ɛ́y x#Th*&1ܗ 5{sdb` r =Ja-~e!ł!MHc4,O_?`zmɾIU22UӿYѳBŌCz#(ىE)V:,|Efp:'"l|Xx6>%q^sw7Ɉc@d3E qr \IBo|ȘvT_dj<̐͋ ?;$Cflpf`4w@!eHr!um֛7WxL';tf`s^ 4y`|Es|v(|2I]fh]tO_@<5ݏo*~[a$7?\'/:CߏTi:RPt)EG0HbZ7W\NwϽ֖7>ۖȰ.{qX@. 0j ňudS*_+R4}I]{ !sC u -#DsM`RÛd=Kǔ=w><8I<1>zRAג"$XZhQK#gMse"*EPZ7(IOg ʊv{IRjj,:QrT#Hch? pE jUnڒ}tFh;/`EV$)}ʓ?VR<`vbhx4 (47Rs͗Gr8 ;^A)y2VBЏu<08]Z5wlȻ0O9;΢d8OJd䐦ᗻۗ%Й0۾ff0uNΧ %VD.' @Y1L|k{'}>=>os2leJ堾@ͯ~ϟ>><<;/_7N#vwン-x7\CJ?t&.&pS/;< ?'#cFo__O'9von9rqumM'l@tL8uFd՗hO מQ!V,1Vw Y*-d^CȈzS0+x-c(-gXa૔pd6zB)K J_ճ }L[ ퟮ@Z%KYW2*&oj!KC#2s:*Cъiecj?ZA)O)6g5VKe[0Q[Cw^ ,:i֦/ @q-䰻>X5hSs[Ω8dsQJ0Ap#pr&8:CKiB  "{{Mǟ>4ȳWNo~+؝f5y6{0g3c"0MBƶ˗[;vA&ؼk j&!j$r"҉8gyb|{;@v?=hINNω3kVCǴ w*Y^IҎҢ8CВ,G/{vP(IU 6Xl,cXLD<^a*єAT ;dzS"E~LS!a&L󼵕=}8g-~l"n36@IDAT|ߞ˵x=j脇?~_Ow|8MtXGomB ==|&xs>>[M\d/glzk3\^><6Wo> >e^ag?=70ht(]xŰxj3G#jƹ~v~" b >Sin YzM7,8Riҹp;-OM@f$A)8y< ~YFMI (PF50t3YE&"z"PiTM"r~ :]/RPEc,mL#/*8e "lViG'}h1R'p~zrgYۉP^j@(&d4VЀ֠u 48(V)_\Y!3ņm‡Ѣz~J~r%wQP8ekvrv&*\9L!r6mWKg>_gD?2\\XBO+}ϟoOǧnmC//|ׯw\Wn|yoˇLp&JӠNUN+]\7]U9wN{M ;x4euNozҽ&VTƣΎP,DIW>:;kg<@Ep3l\<}P-Qt2>_ZwnXi'pnn;El,JH+$Ǭ m*# fa+;N"$ eK0$@m`FD[m>Ȯb͠i4JR_dhe8ZXu \chsc];( 'I++PP/"Fg9`BX`$iSĎ,s ]$$J1^ Rd]/jeIUR>TkJ|~Qe8.M |/9baqS>mZ+n.'I>?#~tr^l(σE1pv"aE};vȂgӓW5.FCaoV@^L8;[7\p;b5)=!uB>L)PB+^v `?gh24.KaZ贐vPNXty}K:&n[t&m`g1GoUIĿVHvodP|X)ڗ7; H]ge[gDg+"`_ JxԪNaG$/>-->7"< -é'WN/ !J{h)\Br[0< N%AXJ|"1]AկW%H.)kYc䊼UQ+Sbf)hX RZ0dJ8qDDF6mHѸc܈6}..#B2gȬWMR9[.LW<=$P˯IPF]HaPJ;=2[re#:tgǛMKD9cBOBx"q]fg♍UlgҼ}z>G+HWxP]`(OM!]zK DNTs.Ό}П Kn# ?X:FމDAl׻ɉ i~:[m6/hW{!jgzl%ƻ;1>2tfo(>y--tZ&N_ڣ_OʿHW^ǧΥO?^\,qzX{j%l|̺ G201SY/hlL2h.+b ߌۤ Q'㡼<˧UZk&6Mh VN|4+YC8o^[c}8]]AL{" z"޴o!1P5蜜@eup+:+)/D`oqa`ewbScʲϵco,U9kÒ.|i)DPg^4U ԟ)S`ȟ0,aAYOR%ʴHS_l`i"d_E,Py)[B<8O|LOU@ (?:ܼzAY[i1Kw2"* 2X^f+dɵ|h 7 J9=?!r23Sr2S^iRH =B"͙qHX|vF(d4Pz]dfSl SłD|SPB!e (?Ev:|@gȊ;Y 0H wO oãWPa¢;s-৔旀[ c <2ɸ%RS=@`rUL˿g'_)ϸz^9yYFҬP /WiSnVUdZh2-Τ s cj¸g$l'!j[j,LL4@ujS%/9[g)* 'Gמ ¡Td ?+xK];PP"T H[)c(u4_k޹6=[ f$a&N|S OS N'%q 7B?=>2t(wJv{zv2ż8m\ݠRbny Ud8d0j͗J_Lo>l{ /uaU?|cyi..O?}-)Go[bE×/ަ[?|,d2faO8,mXxmcbŤ :ul_n*œKq}%U-i]8 bK0WPx$ ab|+qB|JBuWɂ~TO}EZDCJ8m2Ȝr/H`闢2F5B2< mJTRe--/UKSp6AY|05[, L .$~7)A#k4RXI\/tn6|p/8yDM@{u$$fo-(PIHz!W6'/lj0,kʹR=?NNz޽m@k8iOn_1X)ǃd0gR]TG0NF13Xs>Q;s'l+d΍KcE;t;۬l]oHdl[$7E ۘ,7G}/ tpho&><D ")4k|5}QZ\⤌#&A`<1%j_1#vT8(\EN*lJ]VΡ2$!<תb `.c$g\-V Ok"s!%Ԃ``啑 4-A\*UWJ6͚46/P`0 TJR^͈"[ gJZW;iY*L\Og\fgI's"W?ƦYVY`ez@0[Ap`'G!兒 1J5 Y B"4 B R &B m%r @%32+&m/8@2\qy1QnT]{ס%}*K"Upl[6_:1Ż/MGWCaD" oxj3| yv:{qETP,*44Gp@ Aizj6)/)WE `c [?L|(,?ְL!h ^O v= 'ms88|%K2Ž OGLNvQ,55 A#1ĩj!;/nyG$ {ߎn3/~ _|]_PDsMXPﰟi-y.pP6{UhݛI[QOw6h˿}Er}~py~/ gqsڜL@h―OO/V~W8%4X;ΛɁ~g [/ sD,y.WO%fBpA-=+lu_;(VbN|2.c]~G" B|!MDrB iD`/ɱ  qF@{7. 3%TW=x61t콠3ʒ% Cˀ;}#eD(rU ~a9!#x BgjԆDJTf؝HJ0'EE kB)8PP,o#0) R[&13☍+oR~Mj^gӁ)!uջ, H3ȭ*${68D# aHL(1,$ׇ$I ZC*5;=ˋ!yxL^PrtHH>9p7777~  C%Lo&ɬPk^# 4]ji[ fne#s]!~sqqrnvs$2~Qԋڻo1jt7;^b 8C4z^7%fKm_}!'AY$fVXc+ktx<-ӟ~`M`l.Z\?mdjEѸW짏_cE"fnB7ԚřNwG/i~3`_n`CH+v${>Z\rYݓٌeyoL8f|xޜQ3kNsm XۀN7JF՞tYCcK[8m5`eK,JPEQ&KGkx Nu.,DRLpRMz ֲL,ʓIׂ|qT-,࿿,fKndeYAUUϬ /, >Ep*Q0Pn `2 e)4byzC<+^\ }ښr[~J=EO\ծ]T% -L~^kcHYECNWTQNL:+7dܢ .Pt)Ma^" YHy&q*FqP*8#D{o sЎ;qBL[6[m@vhܼ+tz6B.(+C ]SQ (^6,ڇnZ]]ۍ΍(+1KUΖԚ lA;_ՒW̳wi Bz-r7j#褤\ +tǿ޳Tᛲ||;WW/;\;u|Rނj75BϿ}nVH·O5?`q^GN<ˇa/ߗsgC1nd^?z:Yvz훫k~x?oGϿjRR[z_ piy˶Wdx䟵$IQ'Sj~gAߑȯdJj]X3ӗG`8[?nNيm d|FRYUpc;tay2ѕr(d_hsȸJsH^j]YVڌ@h'ykD#~.yt*lD¸ Ϣ *(P tM lP % Up gerM˜pvr4 j'z/0y/lĄd8T/yiyX$Ӈe5W>ԥHK=iITUZ4Ol =J1\: j$u˻k&iD`P?.׌VuxWՐ.]a.yqJx]ʒ$(1YL5_t*.DP2Tb.EP JNW ?wm$pjַ$J %j [}` SGcG:YH]`y'c'>%KJr(?, yz>lO1(|ϝVMof#O:+qb5p^YܢU"շ߳QHSRXt:hDi1gtv>PV(qM_.6gqCjzs1m׿FANF%5,׃^[٢.vΗFld@mFZ:]ho̷'.oO/.ߝdܭ\|ʉ5sR lmqt{7 0tԛHE\q^U3x/c QPNl~/IY~F7yI's?_L_֡ͰpV}ll<tyi$e <8!-Qǿ9ʊHwޝ?2ym([4"q_=8Ͱ A.É!Xܾ!U%I)2!Ԇ\ƗP`ev*5U ã8[Uqq@mEJGmiE*R'kSf * p.J1w?G5l>/|+/J}D#. /Xū2& m\r{tFG0!͖&p|9!cq Qb Nr!S#pz?QsB\^uzr*be_KQ%xm%I)aRH6nsdT?6:MIO!!ewg5_q>BCx4\P,uGHG7Yv ~g0_Iܽ|F_o}r]+ bog23:_C[nӆhy$u~}I)nX#scyx-A) `[d6jߌ'J F}`+u,('/N9z5z?WSi\  &Z 6e!5cgWK%KK!3;}E;Hj9ؐjI# '6B0ߪ큠5"{: A:[ݴ$[XƜ?Zxi^UKL{=w*)'ܝd1m@O ^)u3 gZWmbâ}޹/ұ(Md^>gkGHl)L HB@M縝DX$^2e@` @f] gA`/%+z3W^9E3C!$P[@3"q؁J⽟K }RIƢ/וu6:ԑ_N%~uRi)[C;6aJq"1s?]cX6B[ Q`vb/s.`&Oe+ҠO]?zEuycു0;;6G zqV pN UrVڧlo4?#=W33^L)Ѷ-@@[ҿ{}srbXDۤ00)@xRX$M1 }ʊ;ْ^QwFŌ#`ŷX᲎L'{]>~Sք`.KMخsFNE~Mo,#]bjc\~|:/DtgFם zFo>! rջ=J^>7SN{1G}đFmim@Z GA6(fɾZQiDkIkTl[@()40y~ u`tŢPl7Vm"2:Kشtnα|ر``@ 7 a,;e;$b%nWZxsVaױYv {-y *m7khMýXq-F~-`|pT9Ep\,s)PeGeItl -+2`TZm2؁ZY?rc9ԆRkˁgJEJ Z c)'lmnp8\cX+]x; MxiTeG?y܊;iHiU)ӫ(ּWْCCQ|h1$ZLZkUs43GhLj`b&VeқD3XJCF("OD]fptߜddwrP΂LÆ͍ے lMS|~}B{X:4.FῨHQ(PyNYaO9z.ƝXǍ%i@p}^"?;j]Zmg:iO[]''GrdJold-QMrdntGJ3:;-m1 m,WgeP<:MciLӏ?>ɞ_?̓,z?ty\9;(&ͯbA|4 kн&6Zbjg5嶖U|nS=oO@V^al{#*'r*k>јMP^Gg ѡwDV>TE@dX^Ak!?,P;K6BKLB {q.(z'Ő^J>I7PWH0Ta?d. /^PI[$80ͥȣ.`[# ;꒦D›TAՠQ8r^Q!\YBQb:D~[ڥ<;SU(XW+/Rƹ2)L7OiH)Pd`JH*Y80/P*/Jj VX ṠfBL?g" a$w .*$ol WXH=bJ23 Y?ۧaIV jzQ$=EW y0CI.騟 0-i%T4)Rj"kSqmP6Iymq&{" zik5bvcPtb.ӣXm% =[5ٚЉh!&pZvPtFI}yuuiXuuc_Vb_8YK^#mIJ̘$_H64K9|sq})fsftٯ;T2_oMgWOx,DC`r}q/w< GZ%0fK![#^ZiCvJL3Tz;xc\ϦS*4Q<8oVyk-GA{J7IP,RlmYcw2M0& --0(1rf&2o$*E߷eZ92.ʲo%dD E~(wduR%zd 9e*Q$G[y(JQwUx (pe͞USQS,YAs-וWԕ۲KC`N+65`.?"py%#G*:`}@&|(S(@`Dj*'RY[Ʌ)BħV<jԗBZ珷 9*[($.D^Ј] 0nz.\c~|M`S$r<&F=SVctځK:y.doQSD3o=bfc΀958NouÿFJzC1_ʫɬu" Y I,D&7kSM@ѫ}g:'^7h{8ýSW{|ئik ]|ZL<-λ%w1կ?6]v%n7>F=h_LQ]qy#?"z>߳oΓjߒ0߾{?֯֎/'S^rVN'U"^EiHɬ|{ `MdKdaw e7F] OOf|7t^'޽z%$Z'0mږl`h W_SD!viN@i"M77\`DLŒn=Q*f[ |tX"5YL,(֔MҙaME0Ej5w) "We`%zMgH]r0"0^y[IoIP`JÕςp{ײ*s;Kɇ5Uyo1$Nw>(>uŒ1*, W`U`[di#)윥p.g\QyA׭yLRk[ݯ%jl25k sRA~s /Ͽr~Ipr9[}/]:4pąkF ,5UåWsBkHW?a#Q{5(yfHF(bk<Ēd4`sNhdLU_itN&#J)D y-FHk" B~zy4IOHM^`RJ!>A-|!3Ŭu'nY#P*I0Cx3W,H{tn%NG0̜4,jdn.x:_'8rlǫEyڌoN"P4IA*g/{Sg=nqT;X8 I\\[9]۪&NR4 ǂuAT/zR}<饽Q񁇇v+yfm?#ӹK*(G+cAܮQA$}}o\R_MB!i""If';&oDYMi~GSRrݨSɈGE ?Zj",7Tq} yq+ '*V2SMvkk12ȇN֪\OwakrҜ[.;5LW;îYt#Luh%HT tJ5ڬHMkt"&;uZԃ:ת5"١õ|Ҕ lVp`n]+z;Yq<pN['CZ)3ҤRaP U>@ؽZ ~8t=B0U}dЧBG)d<ڽZ 4¼rD΅ ؁H坢)/crA}pal<ÂL}W 65kа2c| CjwDj̜ zy;zYs'-4$ɌKaByw9)b#%$9!y(MbْbM@_DB6Uq cվ#%}6vh}iՒGcM >ݖIn B llμ3.p"a%LvqucZat&Sm׾13E@IDAT\G9 PrzR0nV}Dмxew0Iy t9\R ե0~U=MUjQ%-&cU|-}{O٪ i k zԒy{2=v͟Gީ[k`_4!kmi~>f=IXx*auvjŧ5H/@ig:A+k$`o>>QG^lɨ+Q[2IdmNA+{YNdY!l-IdY@Y%ul65jFkJ(i{)QMi).q 8ܞkZʚHe[o%puYس\g P"ByP V8 ǀ氡w:w8@  wS%t Q1X&h=5hC 69_8b]U5rka4%/~ (ejTz/9KW~vOj/)`20ԯҴ 4.- GH`{HDzD/79tW.єV"QlTf&;[B❒H*l<F; Mᤦ&:fh_tgqBi`sߒ9/1Df2znj) Y;<3ItSL=^8q>Ig Giqz_qK I։A&X/]&U&SMZ'tz؆5EmxMq||~䅤<2)YaٖsЉCRv-ʶDn[NdWáil~vA쥺E9JǶۭ:{֦Q7`,}nՔ.Nkq^7~gcۯi^j|o:M#wo5Y9N0Z)9nccYqjP^SsVV< Nwˠt]i1ت tKK2&I <=۝i;m ΁\y׷E+cs#d锰jO{IW3Q,ƌEF% D۲ d-.-H1K#7)ċc<3X"GS(CU`b|, Z}8.r@y3 "Oәs( =XTnORU:@;YU#Fo]QD>S<-BA쭎ƾ1ݣ-7+GI%sQ8LPȀ'2G(늀zم%&aJvm#Lo*َ0]H p ©&Ύx)7>-S0PWM\V&cA3M|; ļ3 t q4{jaL;+Cys8Zv<֡qbr̆LSDGKTI4W7\m m!aAo*\<=>BmvJ\ \plM ˓VZp~٪|Nɧ]IbH^\mz.S48LRj4}FV![up`={bM&>r/ʏL$,`E#ٔ [ՏX>?|(:h@\xI4tͶ JdMc9j,pMr Џ֐\-7,m#zzdBY{;YVyk< `@&`CE6;-,>3T\ pUm_Ղ~s &jS S zJ*OHAʗiby*/d|ˬ N^|/+Ƹ/(o/X nrr ɉP^8BTn=m- y?۝wHq=`v>zZֳ^b:lQ-K9lϷ =G'' yZ-=fWJ\F#psv1 IJ?aUzTP@H|&0br5 ۔-tЩ;LJp$is\|3 |u|2t<akZp,{߽}' Rs4fpupOgx5Oj=csrLgOq}CR _A$7L7MrMgtse0eS 3% #++xo>P7fJ>?frjkYyP}eb8i!I^Z sw6l<ά'AH!uY"Wvٗ@x:{ԣu/Xlm*gWYQ[Q{RYFx`ʐ@-3Œڅ*Xsw1lwǂ[zӖQ&5EVvZ0 Z6πC)wKj?p 0j~f@H.Ti ˝dÑJ/ !Q}t_#0B40.c k= owQjWH˕""0hhiPLsO3`UKuutDN!&hi@$ ox,.FRV5"Xny^J^Ov6SEfyسB$)0i!,:8 M*25cY&7Vy #0sqqT`h;tQL[> ^IGx7_tgs hp$^{s=D80G?_R6[_..뫛ÑW WI>ґ5J&Kkb5 2`+x==#\ :0xsxLId迼0m##3 P>?| suu?EGEF(rsqy)4d>{XMFR/ģ*پcؗ]FX.}k &. 6:A1ݠG, bQ34PE&U? G/q `o"RuLJ)Dwf(וH,?ՒDQh efj&ӚCԕ/6xRPTʭɯ_Vgm婿Ѧ\2SN7QsWNz+LwT[`|곰rk(8Up5('oy@u=]m3tb5.hzciMw .m%W^:<;Ǯĸo0QRZAD$gqӒbH].}ݨ]?aE;u` 3舞 f)Ebާ_]fYlF{p29ۮrIIL *ՠ[ˢX-V]zdh$Tš[bF56B~ۛ (u3y=+OI_]\UfFlbx쏇oҖ*7Ht@ ^&!׻uO݂;f޲ BDDhON,+* >}Y=8ϙoJlkOգ[rdxz ɘcTz|ؖ4OW|f5Nu(3Hv`5{oڜ_\_^\cf_ΪfU.󠸿Lס(5G,H]< RR1ѡt72-oV3%M3\->rIK! DzmnKXuV`tcV`maSn)xU>} É P*hf`//+̬}˪ #ֺS"QIa &Us49X 8^Q2z'8s@fUNU?APnJs/*zח#4ܥ|#.WZiy}VZQ^ʯpYm::5mJ9\jKO]t΢Nqrw:[e:|J)/Y0 Qm ƣCzOޑ8s{{o][ZJСn_zHS#,F^4\ns:Zm0Q0:ZrV%c4A;hwѻh7SBV`=߃``2~3?L]EsB'& R@*s9 xJ€!n4WOwvu-?Yf@dTɫoa"(T7BqKYi oho~n۰6c,Z~בiq] 3D8' |v$HgV v3-<m!1a BiZ}AyB3L071+AJQme;Љ#X!M>VqDf^fX d\ÊJmqI@eYdIdxd,U^ס -'07PDѠEctamF^(CgX?ǜ'rIe +2ZFlߩj1*'ᔬ,=F/ b Xr,}崵h̐Rs~(55&s*r 箊v9M[h`i ֕ز(61cCԍuHiK֠lX62bMwVpFs{ߛrexf֓Fn3ÀBp &C4yQ]g)v P Wͭ|v 5&exر?SD 0k,잉/%o}k~8 9'!8XY?I;mvwz11+9yQմ9Hd&<чD'iaZJRt 0Ʋl~oҺx'6(ٶ:ulonW`a1. "EJI !vskٲ7N <[Vͧk8u!|Rx:My+*pRHDJDR7u(]`ur!j¥&(jsZ~6C+R@WWK^yjՔ*X͍AJwupQl3%-Fn\ESKEX(/G$8u ie*45']nӬr ;kz$#sEd|gi: q]21qСy0o[#oI(M{P$=T~]HFc<\usUlJ[2/91%R|rNyu[棨/_fůWk3ȟ޼w[ r4C~e%q E_7P~dS5i$ YqwܩrY WӅU"vp8RS6lJ|pf/'zNzդJq^sf Ūr ;뱖YSC"A+2&6) soʅE( >JK11&li=n5MNMob-c|yKD|{8>~}@dt}9 >͞??gO'+c<@/&ם2 Yy; 0zUEmd%.l p|tw?6%F c3=ϧ黓#MN!\h|y8c1S~صw_Dŋx MH-G~hf~g.]nf+l;G.L}FV+ |o]oBddSV]0FqkѼNKp#/V-.{ |}$ F'EGnd< XAN'6YC Y!]jɿˍ0/S^ 9,T:VK99S.߃q_T{~!8YMU94"GlwYgTI >Vs<;kq% >>R80,Il )0.87 ,(]§B?4iNT 6#[y7Im5b%8ҫmYbEe#@c!B/IDS4p%q /g6+n6ĥ9~Z'O1h7vhEs6}R~ d6* nͰm=!!i۩4QĶl`$3hLiSߡ^I[S$̗2>G} Mb.yUA~nXwY;H`| +n|1K|Ƕk ze x4xШ3{I!#<Я݊=fs! ǮCa3DR c䮾sz!@%5C5fO1&RzA QC޽:USQYni1@O^]qcֻQ\, |TYȊ‡[RoĹ<Gy ]&s/hJHgM/-`8L1HfU߃4m}x*V՘w hJLCS1V"ٔn/. ?D\>L# 4?Ybr.;ݎ9*TN$dk #_;萙C+sDc7;wkm9V7w`XM,;F;ǽam4}NrUNr&!igqE@-R|qOvXXl2Ф* m=QkSmyRS%0>Ep8FIu \YBSS+p0Pa(w7v:l9#UPϬY>T`/ %ox sٿ@_sLuqF('$%TX, )B'-y,\g/|&9 ʍ8p]B'Ur|/xH3gZ1G)SWg.Cy_(m.DAkQ ,Bz`Yt:HJ΃ {5IޠP:\QPJ}F _X؟0?8ِm \(Ng {5>G3B9&6DMhH?} l΁11`gm PtipoRiy)E $BU6mW,}Z5@um;uNxl'fdKIoNO˞(ZHg"pКJxƦJ)b;pO_en8HBg$>WTej ScwF]oǣ\Zx6)YEK %RwbĠ!\\\ӊ ^C nӂ`~Yw$?~&6]٥nr|tPh N)t}2b+ώPz2F#3 f74py3]'n S1H'Cwsel<7.nq7vMJO!mXqX6@^d2K(YRi♾|n1bˏtF͂]! Ҋ|QG[E`C7b5!gQR4W:#ɞzn=GN("N ;NilVtdK6YBhĎxysN{OwP"7b0 `&7i/nV2?^|]H`ҧH8CwEgRCUC/'g/F||#~H2إkekO~%%wOIv)$u8ǃ|A?heh}s?m_ໃ=IFc:dwۑuĽWX [msw98Z03[GA)S6OŭX\ZMɳKGM*JL=S8SZ@LYo+F\R)gd&C 3.}i,&ӛkNb끓teETT$(Dї<6[DJ+LZsd9f]7F PK 'ru7;GI?J`C+( L-I ~3JY@Tta0K*R&-E1B冼Ey~8S#琢|WEIn,NW O꫷ˍժ7$ (>h ©ҦZt>jCrWLaJ4H 3I,#yLRma>u4ōJ"P]|9h(&ezgLeqWvoP<%J58qxc#3+AmH{#q5"/r{u8JK/pU9X%4g@3 P6=&I9j.15mm4OQt%ᰫB86@5{>F3Ȑ%`MoN8tӹ4X#F/g;x̖=n=?t(R(Ub-dW DP9>oGa֏FϿb|w|o'}c~MLm>nGASF&4t{dS#Br_5K29YT+7CAi"G#9+Thx g+,-R"e rY?y.hYnHX߫9?g`^#H{uJjެԓFYՠ*]mRSU i,hnׇ&b^#&@dP3 TDGDl)y*L'ӔbqI`y0_N.M 5q4ulOC6mjd-\&xۼX[։v36V3+Tsd4vƩ>$cրIpMYJ+su }ٷOJ͸v~LmR.r6/$SbHk}u:o8Vϭ4^ٳj ߮%+b!NouC񤗴ҍԟ#Jd{/ ÑI WN`=I>9m7{,W3^;+tJB b8]5dQn &PUT)5V?_$k:x5allZuě>+72'!y%EWMa\$ DnJb޾~ϚA7d73WѪd&?K@?[ټ찧% XD[X?mK:nh J-2@Jr$ee#$8SS/yT"L\}A_Y+:,F͢aIhBФ,D7OZ |\#,,߯G̽jr!H՗e~KRK;(IQO*|T8V@16$}Z wHtw}N#p Z^"%*46WsO94JTpYUWhpa,0ئƢ݈fj%5HizGʊUƗɞA陆0j5&qDZX!VtȣUন.7*A5@% ~4۝;24 kqrD7Qr.Bzӌ7Y҃uY(3^Q Jajgr > +[bK2!0vH/%M(bB-88zt'ug^tNmt%T#I,ez`]AT˫2O*9{ӛdv0u(!Gl4`JRhm}}~7W_. k`ݩ' -ÛZnt^$c28&?4@ Ǻ\q2{w[ϧ6F%oTjV<%Z/ ;B&B@X;o7Vf-i7@U_N. S Lbkѫ$abpl4{'ZBmɼgjׂfIImN b[L=9a(}fb92b L_D}Eb-ư7̋BaEIhXyo-&>:zL%ֹ/5ID"ΨN`@ уVIykmFM6t?H*b枕"  =<H`ha68xr{6h@JIQ_9S@KA)C3jUU^uw_u<}r/ɩ!fzx8-Kjѐ!lN7`ڥs{RXd@aie`dOԊCJk;=6P#SA,9CfA=}OW TV'_5q_>8E.t|B0Y݀_?~:sxwҠlel$̛MW4GԱt2>nS_l4&5;UL^ DEtF/i[ToR˷TK@|~Scڪ3 ^".~溷 "Khbd;2pFiK²$_2P'wjI{Ԭ8Bn2k`.M,I_nL;-z]Q-O(θE_8&6q;hX8 ++o/ζ\[I'_]B޹j9?V۰Og=fYfOP6A0vz fj 4<~::N<[JH&T7[ţ]#{[iZr3ϓ6s=j>;ק5kgo^ 8jcg;H6sMP7.sI+|5{;I5,j8"O%y=J0\_u,Dޘ8A,=[&C${ʐ'+43IL/^5z2[rw@8a+6,1krETAFC,W|gVhԸ3_C-x]N{aU.8|@,"YNl<}eqvs&Em]5LFZ EkEkO#H +igZh8|Xj?4~0bFK*(fxx #[RN•X ͉Ǚ+k-ʉh^8", rDWHeWq4]J*tDGnF/߼E~-4K|zI v:֕RYW!0?rn ߰ǯP !y<$S}ʁ\U2U]_?tz #NC)؉e'IC7e'G@ I SChBŨ7Z w$wSB4 אebwK I1PEꯃ[V8GZD%d\ȨaG~Sc +VYO)tKRT&'(zILEgfբGMBD_Vxi41j|FL-jӚΚ:ITc՛׋ӳU2jui>~6Xe۟OL$z4gqí5AW$y;/żM)^s&S-]<$Nڕ"A!-(7ޞcMl\1k%* bL4JO%u%hj3CLt?ؤ/gc3Y#Ѷ]k&W *2bo.~JBU`8Bا-׮(a)vxF60fً4*a>dv+[R 8w%Ǡ ysO#pA!lrI :E}$8yC */]B<Ϭ_9넧4q1D/n U RU iN, :-  eWyAV(0E^K/ V~bu0An+E4ZYT8`.ggYyO9W01` ̔lJ. o{}{y Ū?~R0OS_kU, zЪzgW\ԌSfp0*-9ԉ% PP4%AJ %; I;Ӛ׋s_ q6==Q r\q7e=Y-h*YI^Q5T1v6L"6-|'-8^g>0X(NS{L-;q 1{zo:l<:zQ1pQfe"S >*{|t34FD˅AJvo֗#_<-m|YYͷNwh0 3{|c˼ɜFFUW|yydIЦpQna?7-=[~چ2(MHEʢ$[1@IDAT+J\N@Rl/x&m6iFD05ПfE,;u1Fw.K&d|.O[iR1]d4"l]Xphd&0؝. zsTi\1qI0oeLf*IK(L ;@u0hq‹m")ŒT7ЩelhD؏DzV:Xa@YY]f+4g X^ R}~3) IfQeZA )6zHB|/I=T:ENs`}>K*rT'!U~y2MMT'XIbAtoQBSO{K!R:dbz8txؾYd<ޭKݴ?82ɥg~wh0^'$ʲaf\ CȮf`6߅-c@nav4 -Mwʢ/{xzLf2]ؘNWtײ"Wg٘¡Ϯ/3[ɴg<98It˟ϴ'o^WZmFi)mZrsˮmqgSNn?>EHHC:]FM1ɽS}w-tVɫX{&@D`@Y&ӓ7n{o;mH {y3gnmauזkltt+ OB})EӂrDBxrR_T (x9T9\*;o-|$YIVR-9̘G}=GegbHHزmvyEH]z=(&&F)f5`HAmӷ'fo/f ?S7[ڼZb4XP ֡ r^"G1Ae' m$M#h>7b z>=#GkAoǧ/Ep=?m6eM+ʼnJb, IX_teYU);8r$!eFB !4,+I|ÇG?dJWׄyV$*=Cp v宣=a`%A?iEԾsv0[V.JO's163eGrgu#N7I--?eD6|;D._*j3Ku6,tS_+%KlytՐZV'**-妵O·Wg_}x:#ֹ䬑WEU0F']dHcWzx_[صӥlv*u PR猟 Y$\BwaSn*E<҉H:Wg#Gʒ+UdRGNKdb9qq3&j$S<4+_g͚ xVY5kݓ?-,Z/;/ᲰME:,ڞ4ETl]p[zᵃ6T18h ؑWskrY6t6o@WЃN4S ":2 {\s 3 3JLf!ry+F,s (l PRyV~4I 1M1@lv+&0&7X<)n!SNDpXKiӡ[<=2en#P\+0ڤlƱ$.0o%PV^ڠ^i~sJsQ&lWOR %0t)yd C.^v)*T"1bTM@_6(E/Gc^RQE/~z[~Wj=|W_}ærw7_mmlBy$rMO?O7wޜ L Z+Ǩl(`Peܵ"KZ(1䔔=w/=y7{򽐲uq8|t,˫Cd$mMZ9:'VkJ0>:ɚ*LOawH3:^\IɣHjY7W!yhrRnuIMy/)O^S'v2,3@ ӲkgSX :grtESt6AĞ8Xh*RCz,֎Y5Ȓ:Q= $PeG}naFQϓNQ}KeQ - []h @pAL(yp%Z4=X3Hs]p4@ڇz nX4yhe6 FəMH ilYWJKYC]BD{0fzNcfT6\>frY#ZNM^ah:Q]nШy(Gv ~#K|rG㔍==R~iNwkaW&0,ގɏX`3bHzcM 1`91Kq;Kq+ZڬɌ w/MZn̡\#F1!2hb}|h!KРnΏll YQu1P|⤉3[ɉȠ 6aH>twbdB0ێukruW J:}jW^q-0 vgoxwO*Vag8UԣĜN"P5 ia3yfaFYͩywhj22o;s;n_ԁv,I;p\0עŒiKXtAg1y XdqBQVny8%eYe㰂8pjzTkIWޅ]^~r{2C D^Y>r3dƓ[.̮y磜xx8m@=MZŀ:6ϒ֣(O 6\T5VojBu/^_|Vwn} -yFK?dT'r58;t~!++ڱ=؋qFA&=¸Q2m2z{CI|"n)IRór7 W Y~AO,dd:  IJiή3ЭŎ6d_r8umJu3C$b/́WG4O#tlo7 hL6 GM%-4U"&/Gf-5nN>'~0ɠ]V\BC0</â>o>]\lYK|mJ u-y?h:?HAkzcy7] ҥ%+n!G.m&$vf7)UTRU7bէǧ#R^(:jw-kNW/ߞZ:ĹF"'#dY>||ԇS;x"BbHbX-W7$nhǨQnbMi]L3VF- 6lmLK0mCf p`B: kP3e&˧Pv௺.1Ր"B@吸-? &[&`[& GVhDpFKCnaF<'B ?ɳ ZEoX @2A-#O58jbs jHY]Vs4峴=+ u4N-0g| #dz/.Hiknjj ' >nnGXj`[OmWGSyfyEeY'K׺qvm`/o4dFt@q14DĔSZ[5ɊjZ9%FS*Hэ7_ͭnObԼjˣhty$BXńaotf6 .n̋e GwƛI>i[ $s8*NK @ƌ瀑pMp5Zp{+,1[k97Pk|t.MvG[+_1ate:HPbA. l d^`QT՝ဎfin%PA̻֮Ó Ϙ|iL qlƏU26˗ W󳐍h1U4(M&w?_>FgsCz2 ~[>Z5kiҤb͋ߴDjӒHqC|DFJ~4VF%gVIEx"B+=>HuSJa7^!`g/#-:e.,#eRI 6ۃ}؄V5W5= tdw' 4HVi+ )ϦOVB^p@ Yh)pCus}GZVgt³KS5<(ח r#|FTAh[ 2/G Eqcv)cy2~.{>r]'eD҈/?w/p 26;@_Jv}4%a ,dXl\r,hlKv:g q3&Pd%/_*Zfdö5D8>>2xHmPڄ\Lw;9=8|ޟ4u%t%SS,W/>| ''RL|$G*vA}CAMw6Z4L,Wr6jVZx5}ϝ7O#9aJxb:|J _(7`PP2zitOPY̛$PDQV:f1U'4R?EtGPX?yzl:H(j: aܘ Rz]ەeXKSaolA=DP92YJ i>vʕ0 `/Hly* eMnry:oL} PqMt9PiQEEAʄdSg`Q}htZ8 %rN `fW2T(̩%ai(ɽe]|"tpcYɖ8@ _ڬ8NPRb-!cGpa-Y'\EflB ֢ KbMTNA,|-˲ztMd PՑt\gA0\U?t3Z0` wGuoi0py 2}e*EY~-HZjTLr_?]Ap9 }՟w~93_XI,R?VlGˤkAQ3Yj"L%޺8BBdl-A()[ 3E(Ϥu-eܸ'C)I'0Zv`t"A5<j >:Id)L#ɇfK08BݚWy%mcIk*fSh3?kSJV\;v^c .j9>ـWZ{ݭ*p*gsj #~!1ajh^;OKkʆ$`X{sFE'_]a^#?_Ejbӳd99!`1⅕1NZ 1"I"/zZ]6O%[h[´*]sQ$KIۦewY / G / hd?W ǹMtFqҡ4v}_ {c5N6nHy#BHN/J+ۻZC6-Vi&Nl\$锻[gOΌ- )g2&4Pÿ}eEO&V&6#\o|)\Y)s>z@a/u7~?i J% 1jB]#zɯu8p'̮ٖ,2)LdhZt|#Ĩ*(zfWu SC;p 04&N3c7թ6wё.ʖSú9dp"mQzƳχ#C!|?_3!~w'bDwgMOVVEJS<-ɳ3կZ\U$vUf7!&.@stlˢ0A;X`lVQi7ٍ8cG#>ucpW*_ E6Mu;R$6 |Q H?()>Y=j n}N707"M7ɩe]37YK4~? lrva UңCɟhg[0eBقBo}/@z Ehv{ C'Sa魗-Ra ('u e3c{Yc,?՛ L`%cs@,!0rN*QX3}zU{t{v}0[PO_ޝ?^<\cw:~!ӘZfg[,N͟%zRVz5r {\_߈.(\-s;FhI:wq].j`$Y՚SꩻQb1 V~8ɰe76rIuo x %_5Tʠoo؁q@V RגNk|1nTeEu;+4 -PhuT0=f: jG!,%Њ6}\X9yE| \9IX򧋟ۙhӂ@C2yWa܎<<8Guiv}fAñ?&Xɝ& 7$Kfwf>fXb^G>4i$9\0ͧB!6t|2M >W٬hOѣ 6 I94MPɴY V+`°d@E旟?jڑLT5k19 dLn&PZrmS BQ$4"^? "Bvn &-Lܝ_'(ݠzG@cdf .Zo\ivmc}ԞWY5F,\icl2<\Hž1 IX&d$FmA;Qp 0ŦFV?&ǬrK{/bHYtKYQVdϰ^Qn^%cdGp=]rl2Y!Z,k#}paU2hϓ՟.sJcƅFWK8A JthW\V heu'jbBn/@s\br>LDg⢎Dko/ {+$ 2C&htE6V_KMkɾm_aîԽ%骂6 <\ShMM~HHsՙrտX},ƒ0fٗ3_8[T"ojpxG{xrUpkDco'T<s =a]'UM\j!a]U2>V*1ӳq$xOhh42M:Vn8"SkXtFk.H>Aq&F cƗ(x6^c4ȹQ9T0 ӔL8sLf8aRzAmULlw 73-R2,\n"ɫϸ_;|!I^j] &m4-GƢΠ/Jq_@|{w_훷_Qr7W/U_{W=On ʖD"I.6|d߽8߫eJuaYDvϴ`Mawb?>gi! ǽWQ67p{ͫ U NlUcw\yn`8_LEGo|vۓ~}޸^f$i8բU |827-Ay*&`uaCMnЗna=ԐaEu,-=qD(ϤŒ=޵_,q fOvFղTsWjP &gm!a"0fNZ:vqWE-Y$} 򼬸ꨞG% [ g1/}ƻ `[ƂV紶׽S2.ȓ5Dy#zRG{Yt`,OGZ>xB= e 8HDʵ97 5Z|~Ů8$>Zm&[۔.T5: sTEd8|oXb4Cgh6i~(yro ⼒=bIxm/s4tvwX3(!On4h}7/_^v5̘[n~s۬.^ksNl_^u{?NfᄑM ` ^+M%*PfQVK H@{UX]{[45g_w䌥kn ,?U3<$ __~(XdW=< ?oՙ{b˗|q)cB+kc"*tA}G٦Eد-X!ow:}t ,13tz(l#sj9 {2(޴J^%2RE}#kfHL%w̾ NqG2tVy&)F 6Z}c. ϭ}LHy 41:%ms[Iʘ~N냊zױSJnpcy+Dq>8'<OOݴݕNߊi|rz2rHxУN Ejd\ 7/'j1i]HQP#jf4v@YšS,d?c>9b0[S { S$ O"qP}{X0MvєN9Ju>=q/&cd>fK>CF@ v Pȓk*b# ktaӌCY$]ynef*M>"Gx>q!fԲ6jsđ¸3kŋˋ箺W{0h3 <_BSщ]ZPQ%7pV3Eƍ2 i p1X䂴mxY#[gTD ',kr/~~vQKA <3ׂY\sʃ-Wi@5h9].ȵyO\y%()`l?/_"9v}9?B[/8JD𠨅]Qgz:W/~R޳Ef聆1`M 6(1%t; d)E{E[GRٵ ==ɾs={MW2k~QeE@Hʚׂ;tԕ)PTy&/.^%mI:1v’C z1'>,VPɱTf7yB.Cls~c0D/J|ےciV͋:Ql-|[hKRH,h̬~p:|RWp͗4^;;;}cOMɢ@<(eE`5jؽOh)lr!q6ZyL퇣aysh;/dӄ$L׿y Z-tlx@v$^e S$dw@?Ñ^?}'9@bO0 Z[+ʆrlh&PL1ݢT(Ll% g,ug"CGJdVyڻF4(wp$q6d.U+G_l!t9^y .iMC!.+**vx|f4C~q&Mnhp0PEOZ@ K0 +0+%KGnC"E.,\Ifũp`Ϩ˯W1DO3+X*xY)W,,w/GƠiaʗ<%WRT5OlՐBzNn*?-ynC~*or-OC{cTtsWqHgx@YHX-yhbp Y`N3Oܧ01 dͮ7NQh+gwcSǻ2~@!X2p83ʫ.nts "Y8ik'_&708非 KGj֤}|e}5#هvIJ,t#\7w,(- [ Y%qg1=qjN%cjH,@nz]!*!y@N*] x(N"QIQs(̯g\P] &A)TUῒ.3P_.ȟջGytSUåZsDKGJ[4,qrMRE R yD&P)Lڬ{̷1*$k!,Xx{FLZ6R¢Mm_Odv~oe|JR(^ּ7G#R<0~ݓ% RR8i| ch{"ŏ8l>ԲY6$)3Y T+[A2 ͵è[kT AIy4YMY ;.NCio41`CЀ#;+۴3iX!`@vP0Ztj^Nhk'>h[A?L '4bNOcfJަ<pi_:~3ț"FHCn>P-"jaB1xp jP(O`k^8c`WWh‹*g*T y@NR`kAҨ!c؄YS̑|/"? #{B`*_ʣ}QV^5UXyx=9@s;_UZB߫W+('M F1⃙>Cd*O )F :j!Iv1%TLB;|^zܙgΆM jj<&N'  OI*7VZǜSu**N^2;|%$~b$DON&m,RuثW1 R\./2* Y;(4qp;z$k"Ɓu ^XFR1xx Pjxм\?9[Dԓ-nVřX1?a2ХLW ,Drΰ>ydO =K[^x  8ϏݞjgĦac Fp.Ҟ*fqY/R\_a=QhޢT*6[Qj=ɿaьT GZݷ@XEf035G6u i})i1;oD2,u IBEL[$ܨC/P}0R,ZA߈"+Z80DjVĦq*HBd~yya Gm V)zR&[(G:˫6ŷMb!-HjtWQIܵAl3g˔e2B2 Ɠ,U'0Cr:]Tx2p*fٱ> _,$zn^`حp@̒ǂ%اߍ4Ӓg@IDATtXbcf3l+Dun~aF 6waEWE=X6&~Pi ךNT0TMNahs@#8Bjn,p2!@MUX<[龬<٨0 nǜA`~hJ }V.\O*?M?Jn҂YTUtEpax0-(Ɲ]i,"x}jP^HI{I;VdRu-M>*F` t z%0FPXC1<_iý,--JmE5(oE⤤t8ŨRMq8-R o5zx'JS jpKǃVX*ӟT9>w;IM?Qh6Kʱ/HVJ-ko1v~1D 5^5^bEe2dJQE vΘ7Lx7.$JujE妋'#fNEGd2.4)\Çw\%L<r?l"N lwh=o/bdӋ-.ηɡpf7K~:Ś=?wbJ?,){1{xO!6h5UfRj-.+xB) a*t܈{ɢ89y"ʁ%QPҧ­TXa aHрߴ31߶;ok4J I=)8PTߝ**?TE`[rVـ7B 0bo`R;>(ѨEe7Տy"g`XYk%~̐z.ͧ{:Nus˧yaF/[BœI-^{W}-ru9uCԫ_m +IWkda㟯\hZD| )|G1z33# ~d"/hRc,㖜*;[ ƤC HOs-_Yrҋ_ 5ƒ8qKb;_քQ)YZbT TR^elK O&Y24%!*o+N3k'C:ͽ3*[ahaX's(~>YK Xma듥z17l!NiF@7HcV^5~ýrfČvv1Cbwqk-Ј ~zrZuVԪ`c߾@!3)>TÆGSpV{X!O93a;f9D9CئZ%W{>W>SA_)i o0̑LP%]Ȼѣ5w"A׳I5bXzj)m[| 4^C&1jz9>`ڀ-}G O ("$DK)$b֑}Ro 6Jp{8_pzY#7FS%jW0~'ـ:{5u#4VUz &DFO-uHXva Tx n|w?}>.W/?!u%vr ~hܳ<`n~+?ƂGoBltXn&TN!'4stEJGe7u-%fkjUB贍qvzI'Dg0"UɗKts0TQ&yiiwhr 0Ϟ<>1+߃CzG<sICGOA幍yM?&@աv4K{R->gl9O/./O΅q+uޏ?odnm;^{)hxP ͜A:mP-6d4k`!'", M,//L-1#q>g*_V(N7aj_4"d ߧlɽOD+5#7KJe;y'ek9` ^PR%}ʑ'a ~f+N%FkPʔOqVQ+D7= JRSI i hQx;!&/DSVY}F҂5)YC"M[У¸<3+v8?/cgubwdC{T=-鼇N. 95~eaNbOc<BD_l=ݍݕ퀏dnF~r' eѿhL01U SK M آQK#ճG%1=ښPT*iT4$-57c^8MwXg+ʐ\boO_L$vˏ>ܞ' t:846[UUd,>YvGPK1QPFΖ̿g;>E|Nٗݱ@$9XbZ8Bx d#lw†sǃ#d²GM2} τ*p~#!k2 k±g  m`<"H@*}/V T*5Pm, $xdl%YYl}RjE{߅2[h$"  8XQFJ** DTx'U|Ur AA5~3WqPÁӌ,T^WV]vat…E;攊i3 K,!'˶ "(4PHEgq{}p **(Qxju #Uz P-0sv6u|Mճvhg/ːd>xfw)_܂_T/xnSiAu{a4ڪneK[*-)hb)8/jx,oJ$YXe-ۢ^1FwDA.c6bٞi4NJC%4F/*PHg$qOV*GLY[xN.ggXxp020y8~W7#648EyxKE-SIֻhv {u,E;I@\ j/Q1"vthJ甚+ z wʺΪ/)J#v҄AԻ܃&  ^禢$DzFpׅs@q#- #/g G )R!m<4?rV+ ӡUo{>U)uGʥ2 8tܑ7y}˝_~0fӁDҖtkёfgtVp>ev2?xF\KeRKII'AL{t-e gC‰ң1]Ԍg[k}H)qx0 r"sZk6xNXedMV#Jh"gΖG](ʞD|rq +fdôz:GE4xӕ . 2X20*,9{Se*6 &*o"X̽#{[i}܁Q9F92~bO&:N;$$(q.?F )/Hb4v=27*C 6.2Z%{T/AFxqzFP*6|aJ-2 vat92o&L# f]yФ;K5 ( ڵkESnU`FL,8hJx eRM6@"tphWKbs*}l$84*q%+[EX*l!($VCnvH3sWȒa\lz6XѥG-͚2)kG f͍ ml?2ȞK?@I(>Ҙ!ŎAƻFJ:[H,R Ps"i~=BSDp>-of;v:g\s3Xr{Һ4 ݞ!ygs"ȫ.埻brs󙳎wđp4q&ZO{75PP(Π¥H٤DzSWSaekJ6FդP4?ZKʗu#'K-RRz4VsQձ.q!P2Va"SrZ@r ٻ-N@X(NBkυ|8Ѓ~{}X407\*vl)Ngw1a-5rOoU@[==Hp^bw@)~Mf:'NJQ"nw}PY*!kc^4 u0iC3%x@Ɖ4ŖtqL7ʼnht{v{bJ&ybQIZn6zfv|ǗVB,z"ghvۘ☭15[{ V4T'1eB]UZ.Փ8qÁOSDZ{XLԸ,l_TJ)%q I\Ͻa)aY{&p p`\B Q2Z, 80,Jn[&Dm$>:?Qp|":ERɥp-1dOOK_f3`XI|<{xqM@'%¬a+vl*W! ڳ0>7gƒ;>Lnp;(Awa3<kى{+FEC 1jJL 4㠜>?:ۢ҆*W2SCHҊ~ދ1K~9`9~msj#*4ѩ 3-Wz`h.g~'- \FDɄԇヶf fԋ|LJ<}BD"ӎBV]sȰI9m]lR| e ڱjl4n +DlưĩEH@CwL:'ҦȒQDgd]W0daGy hcW\7n&p_M w;+c.VHbVL;T#cs!lA*c3, t)P"bJÿ{HHw<$)>{.xi$QBGh$UՒfuIp{vzf6:[D4QSDezyJW,Jap]m| (Ȃ-ZE 3Nf牱JtMA/UD8F%kh\zT uy܄΢bpyQƢ\ǒN>+7Თr~.LW Q uqp de\pL0. .ᇚ˂ /-X *6uL<ޜk>C??](%H˕O>U|odu̽zƂy -g!zeZK&%шj!:ޤ0yyB(u"i+pa bjTdNqA#hSZA.}lIJN;k&܅o@0_N?8E7޿WnF0vu3@"9XvMp9j?ӄ GϞ&E)Xi#AFzd^ dPDpHd]s+Eݴx[8?ۗ^$ X֬ìs˘M2|"%}HQkhİPE QO'HQHL'QUAvfSeW?K\07b)+֚҉HiY&f )^z޸7ƮqbIHTޯxP6 "^vЬ(;?zP6$)!4gg;"g t:gW@_ƈԭ&r !=0zfɳm'o4AH gxˬrJ[xnϾrd6By&/kpx":! ~]Q;_Xв|>YZ?y4`b~_T2d[·39C$_T[ë˩KSB5$;Caa&ʹjڦ8= n/:XrRy۪jpJO~tcxZ67{=<"y{{<|x*z:-`{VC`:= qp jYB@&7 Sgț}\H"fo<.FjOkm{~M)g0Ʌ ;MQA ;0#>\P u1(3O ^"c឴TX:!a {*) V0/Qw//^FK'qJX% !ܧW$ ^n@C)ܭe^$X~H% nEZC-"0\O$X l/|6rd$ϖYn^O ?F0ԱMfKaNriOaDj27K3l$_$0$CP|@kܨ "Ks@\2#WA7NDFES0n 0!5Ѵ(-qyG:N_}zg=iinp8GyC?'sv8^In.O}Ed0F1.v ˜f| cdʸ*K& Y: 5"f"22`m[Ο6nhfdԾ [ڬS>byͮ3'$iU려M0.x9٦r:-ؒd*anV}+Қ}]jDUm''Cqw\H-&U@هL!K' jR)uB!Eބهv$h> }m+%=ٔYQxEߴԾfl&^gOu;J#fGcIF3&sx璐+Ʒw3l2]nR -ODa(`E-pO'ߣ$XJ4ŭ]<,*3)v(^Kr3J~y[h̞l1YnGJpK ~͒CS!|C4Y1fר>E6F5:pZ3vCVđ̍^$.I\5 i _MB)#Cn'/L9j^+B#oQR"|1?%xXaܢrQ0&=Ͷ"u[`#,ԂX L\M !P¢gtAcp!hIR0Z秕vz}}iy\~.=G%B~m3*.GEn.-'OͫZ~} 2ύ Z̑3M,<',%øȌSA,K.lD?\K8,qW6)E*(q҃%3 x7P`έ &bELUǗ'g漡%\Cˬahm |0|utqq|q8Uy0q5zݡ [t`-Opnp!x`.WΥ$TptHщ3GCR(bR[Ȱf# Vɽ@9y %Tz! <Ã~qy\q/yk`pLFro*$nr-?x *eiA> S6:8`?9b- ,QJ<9BQ'o1t䗑-7ouٕ$cUXƯ1zzP7R!Ϻ3iLeQ@#0#3d("d4tS='8`1>TnvGC-s'W?A@. "Uא $K瓳hq5!'S!@8 ʟ&涢0[JY68H"e;gJM.V}*w~,/, ++s}y<.Ъ[,'_\;*%ƸlbWyqebZ$Nd؍ -wdVsgZJa Eߌf_LB*\d fx%}kl;I0}u6WZBd)!y9{yv9W>6{!hO;Յ!2\ JCИ&߲dF $=1ٕQOK {d +dN̢H~>yd`8Vxh]`p~(?f?? %ĄQu򈪥J/ԯ7U*gk Z*E=Ը/ڊ_ X"?EqR!JCc# j$Ft[?8^5 ?TU?wjⱬG" V#[&';X?vnbvRs$EI+k-TuiPv(kJa*Vό;A+hEir̆Vr)M<~㳞4V+1q[Fav9ؽvDZֺ4IN %> Q &|kk}.סLfؾ:,oRLVT7C)x%i뒿-Rb-ߛOmSDC'P OznaƬ^Wr/Gxse9ȉfe ,5d@@mއ}JhH !@ۭhX)΀]e5*) "@m|tܦ8.M޷gc/V 'g46sA+_,%^k?/ $(=<@s\cԂd =ިVݡAjP v,Kc$)^ 5GhBJŽI!FJdț1l6،}CY" QU:Ӫ_YNPëU>g|G ?ÖNZs#iSn'1Fcgp/7'3( +p;;[(2\j;ha\f=-7pPBq"cr +|}nqU׬|8;95t,}+( A=nm(gզ4Vj3oXޜab*vkYR#~l.kSkp *QP \WlPsS?4F]z0i&Բ=^ z*#tnޘz^'BE 0S:g@fbA}a !#,BUW?N6Pz}V:?ڍ.<], V+裝(5`vtD -}W,E{;Az~(~xp[#8Ȉz/5(8N8ز,Yb8gY\!G\pWPpѝcv]PMN:?)SeK ZwBƩfQsTqn.TVh)lTZMK7ĖiLFKlIaʒZ~n&S4i=DuX2bZqeP"tzcgFUK{]#TݑZP%Pjڬ{ 13Q΃[Oۜ*-1蚁Jsg=<^d BF+ 6QpCWɯ05ywkcgoXԢOO(ű}9hJVODo jQ%JTGɀxyWbL%,7׷6P5%EDw:"E)l,r["S+˄ F as+E|~zFiw^W `@C,XS*\ܖGf$/R2\f(#/K4rPǺii?bx24֤/ ]$7{ppi8Ngu ӑ g2ZiI{T!56Lx}G=iC饳5n!5kqI1?:5>F8r@;e:sN 9 F6YUx,2tJL*+2gҬvnzVR"efТœ_A^dgrI ^fK4R0JYA=_$!VuV~#'ۛ7-)x<|o$Ώ8O ىg.J0ք_״J.s~=]!8y׶P.oHG"z*"(\uvI+"[XٟSRΜmAnl{vǏǔ>G /*8Cp_et%*!VKqEiވ|L\ViTJRfgF`Wɸ/G0Fq6f lQ^=ekvցw{5ڊ9,I $@ ہ%Sf!h)yXfľU6E!3,܀K< # 8ܫZ(aeM(7~.> '^RfOGS  ̉ǽfaBgVt__܉X⧱9C|=٣}tmW4^L/OÿozVg^4;chjth !Nȱ5"ihI7MRAsFr4LܰƳ_Q5dXͷajH𖲑KW!RlL{3O@%&b0W4#VrC3ܘ:1Bl"Ns\}WM9f |tAЦ9nԞ,ʘzKZbT'unPS񌘉RXc~}e%ړ z0𲠑Or|Vm kѦ^sx.cʉ%lwjf%rX[ߵZaLtENW (WYTp><<9= m :1Vx۴xS{(3"YNK,j&s+m(06kU" v91!bZw@ !qzgsA4]0tQW㤯_6Wܶ5>1}'LF ipQ#vq77/^CH~S]܏>pS0uJi0oܨd?icn覎 V ҇/+OH,jLɌ&ZϊY(nټij0Li@@;1фG;jոFL3Rkb"dSi i%Y6qyZ]=Uu*tReHV@.^^n! F2y#s 'Ub6Ո_QT>7&vtb!ʀQpD(#S9nRk,4Wm[g ۠bK%´OMae3ADXU)po/?j`7#JDr =pR V'Ι;;qb% D\RA8+V]x)Lc&{zyZOHjuR -N `n26  KJj޸W kp,ȫJIk9: Ouu|JQ5B]dBźR͓$MyA;d-O&-.wZ2Ӆ-QV3(6 @ ;23LNJhs(8 V {nBq wIe￾\g\#;4.cW8e6a#JXq&]9u{ A^\\w7}HyG{g-}uvp7WᯟF7}Ewkpt$tO2I5f$a~A^+ ܸ ր$bGXD U&I9K;@IDAT BoV"]1wwy5Z^ؔT"&X\uXM!C6%yP.*ojmڪTީkׯ^<̲-vy] d&:j&R0&FbьVyJJZ_Rjj{oÎ&s.H`I!BA@6ЭSוT Ǽ&WWk_\L s}#e# ݔ8;x'cZ8à@J;m~CkU%7"-ݬ2y)#!CޚRj ':n) WRSUM'2S޼yGiLAF9>?ſ4~1xsVqBBlxS `YDFP/AK@qCeoTk(XfvZdaA-&S3T,UilMK*`KAd.{(c7\ڒUߪ|S6r@Vyts=\P)C"i1'hVҚZǙ4FQYCGh+Y88JZe}':{tdfn>wgzykL xԏ5O5^ '>"@#Ёrhqᒰ<'.j֘v3J)gP_Siɾ/`nv:gvuR_ZZ7I5ce<.Ba.(5ߕ hU CĊ`}ewn%;,5|úD^&΁&|!Q$]ӠeD>v|թFF=kۯ{EnS[bX^[W*Ej WAe {j5%E.ӛw'-j+ bZ˄ WKehxY~Fj2¨-hu$= @oRO&Vwo1ˑ3pH# ;#YܧgRVpSWA<8dcl亾-0K| #x@.0com%Rq83O3Gt&A&l (OtcuU%T!Y9.N5SxpS9+*O|1r{ꍁö[ IBŸh!,5^gIOMa~wb=Lw3vh3U) oD0R|K?فqwqr_ 8L!!Q,Hd3)qn@jc0yugܟyux1ޑsҏՇ{wV4{ a5CrbdN8;6[)Rh%"j' h6FUpעY K 2CSJ_2-&'S2He]$ bc;m*e_uOF5`wnPGlFE7w^:p<}Y8g| L| n۷/0>:HC\| ӄ"wrk(C CK`m]3ZR =tԯ&֎'n8[m{젻;b}|$ 9"WAp#^~C\zl?i돶th ͺ=X8yey1;+\O 6wYI=@zOQ@3e;)G*[ᕝ}:AI?ԺWH2X:~H)/MSإZ OĢ(HIFu.BF Os6W1{.X*틌5V1֢k2]`l3fJs{  Q0=)vyÊ2LU(i~;Έ|*ambYsB*YԜ0|mwy[iJܜH[fJIMEf+3rfSxy!) +%4bFyKvqvfjOc1 ~AX 8\E^f7ㅞ^ViA;$Z;f[bhAP@֞XLs'"ߚoO V ~^h&`P]d*BVXodyzR[+ H|-M0顱8܃фt/(oh[ ƉڍGxT嫃Sk[;{#:{GX*Xv7QP830[h(Rlm#hnKյ\c6,.c|x5:Lkk;fDH]+9Ai:e4S"6"h\KU/яT.]taW%@F!{L@f:!;u)7^M?Qq6eG>f>;0Np .|U #>ԲP O !IYn,|NqRo=rɳ:cNnuݜC3 rwG)~p^=C'l=Y>3ͧv{gFt F`$0CgWaUipvFuz|{6͘/<ʐPB$7胛q ܥ\WWbHgLTݧ սZƴEW +}RLעP:!ň(əH,_Ηɋv!/\?C"t~޳11(n*#:V5i(+xk}7kiӆf3ݒYt*mo[Tyस~0(#9hld|>HՐ*["kQ#=yz͔ZbCseڕ[ZC19r2xG}3p*[69PmS V1"_z?F~ЃLlzm|"GC<ɘGPOvn^*w~JF'4c'CSfA%ln2I J)oi[tCTD %c+ nYF_B=iha;uOR@89)3?h({$gPG:Aа<ï_4nnoϮ_뗗:u_'LBwOO N3kd$Z0@x.s4oPlP?QOD9gꏋPd6mKYe63w> @BfAc,dotL"(Y ueGOhH[+l. )H拑1i"ʴ8sPf|#ϯM$'Mw7~v/NO\L^~o}㏷?}Zyĭ}L&χ0F7BY!)QH.c:Zg]LU67 ɣI)xR)7).͒>5Ll1L@  К+!B$u{Tɲ()rHdi  )b)H!SPxfF9%b-/&`aazsxʱchҤjkcԮ#UG3cJu5;WTXZEEkNJ/OLC.4vЀYE#H=9fM* vL/i0FqȀ|҆E+nnD^̭Ek@+A^Qۏ " wb!B9ܤ ZRe4f/hhlC@KyҴ9hvs^KT0ЁXQ("M5c~ 9Zke IWXk.p;EqQ?ؿBRw0= >'yb_/O%i5 {fz/9?͟f=LZp[>>j !i`:<kGtՁ3HH䭁x<:3.b(qӻܭ堰.ZR~%suCJ͙prߌ]hna r'^j@"Vѩnl#`+3 s,*Cʐ44xؚ.鸣t@ٷNɇǽ^b\Lo[{ݲ/Cﮯm:ō]W*P% @sJot@2kd gM 'gb-%%pR6k7vIc1&C)Gg'v`>nZKkg/`<^YCg/4@z9σѓ,DŽ)^X D֑?tauOJ,r^Q=2)nFR3|p{i tN]˓ͼ#yod.y\ugD8L67Jlf&E*0*hs 5pr~DY^돫b+LD!Rjo!?t~rbiVbpb9N+3ӪylQ~q^G'Ga P` J%h*Nw7~gd$7W ol9uS .ҊF'Q0ffʓ EBϚU|T`wkj3 a{l83"`<36O8 : N1;gҚ񬳖v- ʲdjx{xL7OOe\-&ū~ RysN`% ](y/b%(HP(jxVuɻ"JD=3UWP>YBO8 (~Jǜ~}`415ϑryZ oY5k@2Cf ~Wx4`SkoA;.!N7'N4ȡ߼V]#Z6w, (C9ØY,$9 }8SqڊԷI-b}=P0l-[ڥ 0Bfb}q< MFuz;\s4ȝO~hb0ׯַsͰ.任 ֆ]@ 8\b+W8+܋ֵyF3pȅMq/H~S[]GeJ̏LSݻ?}8Bf>q:֝$׵۫Oǟ_)2/#4TWz҅b`yhI=g!r7BÅ3bV*]h8L;MP;;gՑ1k4{3?=oj_z{cd_ F#YV(KF- bst8iLլXWJR!ƓW^G %j3Po ]ۥ!m$f  ͰPEJM6bktEQ:dӫř2lJ<ѸnWܿnlW?p*NJE\16`r϶VvNrxB|LnOIxHG L5 j|-C E&ϟ?ODEc_nHTE3$កjk`!$16÷TY1ZڏnLN֣0}ҹ/fX.,DxnD U5+WLpڃJ:M0Tb*/OoI^@7 x{oSx?+BF#G`e ⵕLJ( EӀOA;o.V.i OI[z\Y Aª%)b(w!J2ljcڇ5>\6mX+uk ]z& L8c>CR609eya#GC[H0zDžڃJoNcS/iqGBjF oȍ캭P-A 2?||$9I몈11̹VJ~sSx{V!?|  Ztv.VXHYx};G.҈5VU.ޱMвЮzU>J.}7V,4LomY`n}YIk(ոq5&0!}xy59<;9Xvu ܧAQNix,\N*D"OoƟ_ҜyH.w&şRW3mT=0(Y cBFoKۖ' i >*}=L]o[7|c'M)g)8!Y/ܹ)Zkz?ݷJiw#ܳ](_㥵;4"a޶+{2RDly-٠H>jᅤtZؕR8:je!iD X+ ֻ8L?_~?dɆ~5qFxZ{0{O`g$NꢮP:]2]ꇴÀ5^b'A^zXI 8;Yг#Qa׻&UK?.5kA"FO;&} D!96c݉%*NL1Bx6W7-Q9Q1EIRn+T B 2Q1=!3xKcK<@cMP?[MrJ櫹PX wx]hdƧ)\~l3rD5- ݙ238"6IAսYAKK|8}ٔUpn>=:gӫKƛmFkHܱ) zvqf464EHb8b}+uL,(BZʉ Prcmhw<μV&Z1-HB`5"Tp293T8'IPX!g j(XA#8m(Wc6;EEʲ,rt5r %u8ucrz5yN.h R)ROWf}t''铭Ő!NhhL> - ]Da=ۜ%}`i(,3[P+a\ሠH#xNΦ|Gyt(&<etoqaF\N%WLZ']+[ta?>rUi^f"b(lyѷҜɀh$ÚMPri1J_2=*[ O\܎#ѳa(7(7?*Lp0O 5?)ocW0c`'l6 =Em kT$[7Y4wsr/^Ɛ7'v؇)mn@t2*^`l⻳S>yZE~mm-o*-zGËt2cr칧o.~|ȹg;G4UZl/WRi~h#ADb;OA9G'd RZMMeX mF/5B TL.]$ ɰO~tqr!.8ֆYY榥@ ~X-#U)HTvl8 ㈠Rã,N@)P >  }kO۽•lR't1&C>Dp$';[G^ƞF{g>j''D4H8tҎԚj b̝^膷FSkY/#)HFXeCvK(WE`hX1691KQ l{+dHųi{IJ739t.IA)KS!FG/t-j@Z]u>ݠePwB>Bn;0K *:oǓ9EbO7/^`??Lfu9ƚ:,.XDOn1n7V.%0a!Ч呇syAbo7v6drupVP%PLao9ӀhB@-P]+yhb-FԻ~xxx X1ڊX̑_@8=&}wv1WGbL //;[g F!bJrz;qrv+AwyRT ߞ}ON=?xG2l_MC-2sͤ-:|Gۀ_i*ܵɤTUMfZs 5211;vug]fX\LWk3XMVY}h FP*7Ѩ!tD5o0C'&/\cܸx+R>4o ;|7i!Ӎ4Cu.NJ#&-iًoo^q͖>2 RKSly^hqq;Y"uCZ ϚWyuO򬔅rv(OD%xY?<$Z ͭkk-<؞+~)nHKÔLmnn|ByO7l4JyRH7SP7JaL |WkP  g<1q]U>q{$lVTjvrQC \ 2kR-ŋ-D(qT5ٴ+R9 ҉Tlrt.m2&SjČ}>SV#O0]''g}Z֧|X3|Lh8 #{PY :'9^A,r #M'։\Gc =8P{zPJ&MaCgtr3ƃn75%X(>POR$-XyxqM?ӢN/zRaX NxmŒL0iƄ.E$FYUwܥsN{ۓ3>?<gA96o}UgvA}kKᕕ ulS:'Qeee9LFW)j(?HY^- T`SHM ӭR(e )GJ _>ӻSUl)Ö#DELhf ٓќ߅FI18W:L;Lh&%ą*r!Z.eDRqseft2-'d)ȧH\? a$rv\=3i"録;Ӊ-w̯oQ3Z !: ˖K! rK]o[1N v>=*YE)d^ 4"j+ƥLw4VՙdȠ{~J0/G{Oݱ2SS E@^r{مZ5ToJL僥@Z!'`*s:([Ts$Pn*XFbᒬGCA+ӋjUVO2%jiakc!V{[|ǡi>tyq:~z&鳓2"̭<ӇQ*Onm⨅߼}c>o{{znWUcIR-|`e/*4'} M7D*RcgWbNO 8a֢= 74z*-qu +KYmVy\b!g*,l6G߿x,&j d$p%6rX+H9ME_]cF+`&SYb]¬q1a|Fx6 BҝHHd30\O6|T30@10b#JhHK ,c#;~PJ 4I6j=%Ho@z`~Ce 4Hq&Lk j5uO%B1=ir3Em9Osi^ l>Č'3R8:򜆂߬)yJ0h?v Y ΠSu%_)+l^c0V'T- _L~ohr_ | 5[Ld(ɯ"]y=CК:?ǭҨ!g;˞RQMF}>=r&q߾7޴Dc~kVt;yS4B0C6X=fbg6bi253Zlm RlTCe)FR e4`y^6JNk2{ b%JzVƑ]]? wF}Zh.ΦgYn0U𒒢=RʒEɥ|HQU+ܵ_~qK ?UR#x/LZ 3"Ȟe!6D'JXW`tʈ"[G75W&I,_GoOOODT%a(S"( [~OAWSjم&K,`q'f\>ުe{ۊ; `F> v"4Jh_rvd)ȓoJ-͠f Ni~,@IDATut:#<1HƢLy|]P@e Eo_~8җ gQ!q۸hx̸A&uȠVZjezJGDǂXh;^ Hj9 3\ʃaԴM?+PC7qkjLdk޽5h<4C߭Dx~^4cTn,ˮnmY^tȿݤ}oP0SؒSAٻ{(D GqjvnjbVW~3!fZYdkiTG*mNNhO. MLCЯכoS8'qjVdq`!Y%+kg. i 2I WSxY^ upxj!#zb`8ǡ!tCNKň@&kj@/:gB96?r}k:@B8ir*;co-BWm7a*ᝂϢZ71bx(p>#}7n33sG;:Um,H ʺ $L#!~H*\37!ZYSXXC+tY= gd~40Jח?>S_+5neO&kxroD)2ط3~ $L')r LѾ0w<Kv|4jjr-mɤlf)Xír9=Ig6@B.S9| ,>Q1I8֋,g03x~$]- ԙ~u7N[r/WuލU>!AhYLs] ft'|X7ߑ%m 2 1yH[(n80x9֫Yjp3@ɂJl+0I=~&ZdF=R~KNK^N'4Rol0yjz2/w W6:/lZU;Y+@H=E|hlFjJ{oNgn J/^Mi_ٹXeStrL7RВ|˩Tt\pEc B[BBz 8YFq<;TP{|-i .H5ipNm!5sxVwx1 ܝCbњ7+6B9E,&V]1[lp7G+דTxWfz~Vӣs:=ڪq\X_? I>0%5=`GVCyNsFVq8.?)'.q ,&],8P)a;DY "}u*j%Ϳm`$39PʜHTXas0/@$YkjVt_l 0&n8@$UQY| FG=qXP3 HwŮ{@P MvN (΋ Y\rQf+ Á 3<+D.,j4s Ο={@NkzGdQ[AY&Me(QO94їӘY WV uKe 2bԘ)dy(#3M.Wo]zmL[<Ĕ#Z=z#1h银g;CW|j Kg-ʴʕ3)f%.lhh\pNn*7qOvȁ\*,ŋWFX9MF]V׶UL5wDCMyT>8)'rH좷Gˑ '%XDMYG2O;[Z[eDXhq#lb#AKvيlyP oZz5L|vQBQi2NEOciGkWEIk?M:;},M0W 8 V4'loo7N>UpbS᷿`_#Q&?hk$Jg@53'c,V,9,- b7nOD٨ 4hÏ,Ń0]#jga-|e1PA*}yҁ5ݕfe.ㆂwHSc\M(m|V<U58>gjVҸ_A=Di۸ W=>y-䝟1&7W9x9CfOq,!$(,.ӵF@Vr+8b^(5,-L7y%O^*lݒ˪%tdh>";SרIͬԦa+RXYxicm\*ig@R'S?ӗGau5mLtO`L IgMM|N0az7BB4& ٣'z; 5\ ]R 3z/ZOtJ?DKB%Cz=QYߴz+'~x@΁ɍyNA(HtI&=sZE+^*i;XQ5$_]!gH UMqy3KÍ&]a )l B!:kj3Gŷrg\?R99VԖw*m+Vlѻ5PyEVZff 2@#94zSȗ7oy:;a(gyJ>{Єb}c'RkIZ5L:;>W=zP^7wzɜ0Zh0` {JkJ_L2v5~eSMBeOV,Xfвa:i7ogϟO/._~ @ϟpn!#͡ZoB 7+_"$ ʦ0 5Cʗ+ř-Kᇿdz5}T-#9Q$\ Rgp+?\q K$Iriq`SŖx}/q@,T €ŋ] FR wbh7U?IvrR|5\ 'ͪS~5O1 j{Bq3rhvwtQ7mItٳj}|ujjӇ a@ P%;P?v/ݐ94CzԷly3V锞4Q`d5 eQ{b\m'1c5;' 0[Ā59KdNNrc~PNW(\i @|unڂ OYt O+?t蔎Y^sC_^Mw[>fimkma /s~vƕa~L_~N\ta[i@ֺ kLI.|B6[a{[oF`/_(?p(;"sM摲}kK*nƝ6[z>*)Z0C*&z* ֚LfvHAHYr&O`9*b& Nn J=JE~Þ1 ? [>|@ZOHBAoN^>y>HNEʪ 74" (B{X|s^э}Q/L/߾Vo.q 2|7md,M~#5wwE[ݺ>:[4r8TxgqYT=ݫn,gWN.=Ok}WFw7}cA%롴C5~MAG"/A5`۰*Iݟ_.]ܰF7w6U~/f7r8ˋӓ#`ގXe!G炀,j(jx}}DaPSA<ٳ`-54,WggVg^~=I+me;p ,<jIOy~7/?~:YZftf$((~h0BRFBer[+yut%v[jZ--HrPHȣ#b4IDdU+M˳ۇ QrHV ?be3:fRjКa>9OVkAnr0M5{b-KXkDVi].n؋q ԢƨCFCDX;cZK#,ݛ#{ΏtJ` $ 4VS}`:ÖTI iUl5i"ok0fGQ{Xo1g諫FqI>zY׆ A&TISM AcZf)cnE*Ut~XGG<,-SM)Yt1WktnRT9A@PCa@'69Լ4I4/+ ac)"s4lv$]ldAH`Rи6V|9t,_*~wq5Uhc}?tX$VN-lM _=΢唭jē5Y4c'nԢ%Èaip SPRJeWn3Vcqo/Zj"-I\d^4(si@a&|\+4cEPO/2#wd(qouqOB@dϴh[6̄ o[t$2I%no=yF6孉8rtD; !`kko2VWwU^t|vrhw!w:;!,px"pzPJavA\79H4Ȓ]b&ge~ba憉WZZՕ:!x78fŤh0+~|()C*= $kt 51`86nhz}ފpۋ.$I'Fҵ=fx[ؑp mtNh (t%Jj6,7 1 ϵtrƯxtJrC5JC~<_5:ZCp/MAv%V ژyڣII̚*s(](ϢXzNLͤx!9hSVFr +4]w3~߲Q_* WŊ *bz- 1EkKU 97+叙ٗ ՠ=iiwNcEjVn ;./>M&BQnGjHppM*s$kү$ЎtcJ˒64yZX4ek,B%[!o) z& "m!Lw! $5ŠL['HGiB(Uφ 7ћ PEfm4PUSKCa As*jaA: *qq;T(Tς^-s@wF쾘t%gs=ͼ4NwviCuρRad*jVb15Q2>=k(pG4AXJ%wh,"ͰDL܂ l0DV!>m '1f%;4bTn23Ga;EÑd%'mg.yLTCgK4 ?{#i 詪aR%`ֻ;˾zÇ'*gXUq1o?TZJ呡0iU*#JD&D=IP;枳:"p3Cz)JDιq.>Ǫ_ala7x 䟺rI7F=tzRgT1|cOEyҒ$(d+&s1,06o1k/E*xTs2&ir @jq bG#TtU96A9qv,# GoQs܉$| 0W9 s/mQL/hyaԘ4rhP@d;0%+NC醼3rrXdmcQɒ2a.(yń<'Oh_) ՗;+_HѸ܎>nu~ЍqS$2K A-ZmkId̺,zc)XS'Rw?2G|FCZ\֨T5c%w~s;RM6 ]_݊h: OIqJ OQ⾕S pƩ @T8f<:JQaTh>,Ȓ_ȅyBJ>EAsۤ0v.; rvK]ՒگF^z1FW 4֖>04 trG뺻3.3PF8â4ƃ\&`tB=")?}%r|zI0q>L`hv ɩafY1%󻯗_EB_w&f@y+2 #B /˹*~mQBwL7q}n,?t{8;mIZ yR%T- 1Q@pBPQp_paYlYe6Hag~0P%i-~K+=<7 4_#bG Umq,zGs0_:1$ F(ȧ"`"M 7 |rB)w .j;&H3thhzN/1LgC L񹤃qVeWH -,sl{U"sfii6HX ď6K Dv~=`m#y~"US%t2yru^ (s_^]L/wz7~t99e}EOkѰW۩[N [ 8PB> Kk/+- JFK;#̳epMFr -Y PZBC%]3o*r qˡ{,D-fPpy,^f{ӵVpO<+\u믤/L"p_ Fj|M'o|H@R:ܮ%Qcx`%~%hEzl>G#F]=Ҕ wBp''Gev.wn}i{qqp$JYrx)8^ͧ2i]%?-/⎝:;\ IH}+d$|@ F{q]55/Ħ!sw*]IIAX0(QP. /ց+G/@cZ2ljǙ p:ѫ"Y\_jIdnF/Wq{^l.oTt^'NL(EciC@ ,ywوr\p1W~ %i,*JiA(QZ X70a.-z}0GH.(zrjϡAKT=/-R8Lrh8ČщԤjf坁hn' ǧs7)^hMVyؙ\6"e 9hK9?||GTT0Ng9/OETw2_^|)ޞLכO_iɛy_},1Zɑbݯ|9_>yY[;Rg^֍E@ 0Bq(ȭ6BK.!S纥2 5y: COw7+0z,k tZ"i??lg ވaJrE^K:S] r7\\j*ʊ ?#`~}Thq^yZMNW?}>"i%\^Nx392ō=W 3]ǀBF=:>EBmW H?S`"|F5yAbS)!LTDHZ_v[eeڅ `@Ul02 j8HtizH$U(IEbz 7sNAO>ϫh.Ta|$04FĹd/~AhI_ W.V5P[V>UlNQ Gbj҇whGTۿq!7T{'nޢš;8cP3">( Y^|ӇU.!HTǖqC=&a%*par[gs"xzH47ҡ:I;ܨmG{LMz/Uo*DDH!}QrfJSxCl24%UAn.;h6"/p:|xtl"3fc___]$ ]eZ-(V7Jؤ5bW1̿ު`/6{?]Oo ruv>c,lσ\-`%*!S7'TfƽqQ KTDƴ 3 wf~;Yxb{#S-7)W"D3a94-驺?`F)Gt'h4TAe312efPԡ6wSУ%途"]RӈbIlv) $k?Ic~ϧfXYD=t?) -H͉d)߳Dy@5v5L#Q,CN^^b: 1c$Ɋ3;0(+j@4t(B@<|Rɋ6Qa7 Xh5o|m{}ku,(be"''AGC.*VCIe8.zZ0dW%H?o2i"\ 4]UFBEr2[^Ֆ. X|jk&^!N<ƛ pr*pY;\u!(N*F!1 # 06M (ka"Gb #H9)bAOjٍecgRV빩ɁRz-I^;QMr37J2Ljl[G>yxG\xn7_ ./|x7'[?iMSYYm}Y;.ZU. r~d7r s:*'=@L[",D3|&Qh^/hۇd|Be%#\7Ҝ_o/WOv~)9h4Dӗ?g[@]Q6 k:C%2xx2g1hZjFg Q!3J>I^1j8 U?Q)ۇԱ 8y|G߿Ä֋Gþ!_u \D,U9I: 4ztXJGatƦ㨈"D5 m:,"?[wcesifm+B}^ {rt"}\i\~C nwMG ɮ,'BE80'y%y+L1|zFUV Ȋ;y\+=?E!WxoV`z-'W4Y}}< +#l).I =O}(ϱ@$!0&MSkPkJpUcH$)~xUvVe1C[O=V:)2(4Y:HH|p 24F(f 4Mx(@1d&/ٱe,PKxaGe˥%/߰1^k[*.+EMdWp\D&gAipPox|}$htok'C tx0 n&YFչ{\^^Vk\_ / ZsƝGꤡ+1Hp6x9mxD̓4[#*Brs*\ TtU0%KaOA-|veziQ&ul^ڜJu}"{<)g,ipbw ,4eS{Y,ݷ$ {O\5SGpJ/I73=U+m. d<F͸?Z=5PO?~2vݻwl[U -ol>"~B̴݃ԛ} W{Jl,c Y(FD~щ =#<Ë q|. pvt7Ht#\ :3Jⲁr)rN hO/D $ʌ,*:N·BvZw@k| Cn`.Zy#Cs /;|V0ǩKҸg{XQ UV::׍'‚`DfPP(A`S.i,2Mkz3UwBb~fgIŏ"Zh')z]W Uh[#!)- *symIq:{4#:ܳz=e{DT"B0iwH~cW(gU@jo$𝏧0@F/yѠӪ\rMSMlO;Xe4-ޱ`|8騿_R^2>@&~Rmmϩ%_|Ydt`T(G{>2vO|w5֙}I@撴ܿsttz6?_n/Tٟtawg妐tWJ"rRo/ǩ^zII جX<4aԏoWy:K Yii v nt$}|t&^rt:f SQ~WU\a4eHxGd )=,誝~ >eIZE<wj'( _m/'GDZ` 2~cRmQ4 :?]RaU#c8l`'[¥_..4y.^6;zMU J S /s$Rt+tUx*8b S7).J#`2E/0zN9lXNu/=D <04p]#4(rj7:&S.8br 풄6 o̰y (ix fSċh.+0_`yW Z@` 政Y/.vlNOTG,iBuKF',; zh i^4z3w%`OqxΩ!Yq>\2Q"}Haܷ&KL4$l.Z^R'C):Oݷ7i\%V'}&od}uKc#3&yJjPKS˶$,[^2rAUR;+6rG6B@DةVhhka.s^~S;xw:N2[ńPW/W?1ZummBn3|,UNjtXxpk/'< 0>^bB 95Q դL)J5V>j4{f*ptrttDKIf&6E'CW|*c-q̏?̏oOa#VYQkAv,̃]k<*w5TMjR ";zU-K%xXo K6#R1kQ ] .rZ;1e (*RiIo[G<9.Sj3 bz͛DTcuuKZ? JDE뿌G+ ΁v0Q /@ayhWo+I.[AVtɷ8:%3v >^v dH %E`>;7HJWu<,; ;9Nܹ8'[Bw$꿏>q{uQ# &1* +uc$kv尘ݱNe~OT%.JU.b@IDATXIxN( ZRȯTJӨeccdl|JVglJTK€ gꑤ1LS oFq"Xs;nln[2DX-{8*rfqDzss}~wr66?鯼ewNrygQOw?V&c0QJ%ѭ,h;ѯ#Fjkcn?a?9]H@ $ yXLJ]>LCiȺZ>."!Rԟ!Ў;Nscg&b[oCfk z}PKqi4rWd?j>V+CH ȩxaKn|FK\cAw!5P .mz=b?*UeA&쵞_B1£>5#FR;]W:{z1Jw=>x o~Z}t}q_tqeO9U[fl\t`BQz= ~I)W$χ%^f ё:309h^t)`>ZxJ >R;Ru7Iq?ZTB$@ ;E`2b$P$uNk%BΏMT~ ^L_>&;)\SC\DV9C(5QܞL`7ޥWPNf%jTY)uiS4A~<0w OO_n= UJ#Roڮz3֫(ЄsCxvի>╥ 6 .y pp\u~dgu ]*63/mջ$EHz)FKLN5rt7QS,̹^&7boP(]0_e$>9eHyNnBx/|hA%l`mjy;8-:R]gܧ4 X[:C>x+ύscf:HjsUT" b$)}mW)4 PCeQRQȽk[ׅ0N zQR` ֿH8GV_e5 K9w%e8=;zQKMːnz!#*ir bjrM^.dil~-V }ZnDVѳ8:)TʼLz,aJ`YD6^IK2C0zyݞ^ l&]9Rԏ?}LN*r45Z2&Lџkzo1&eTPڻw?}[TEյ;A1HO=B)!S %j `hTa*@v2 @s a[A +\N )8l;?i"#j\p^Lk߰͏埝( ^#[~q )ADtIʏI֕oD1kROk(*VԢB[1+cx ȫŐVt.2♍7Fֺkwm?=>AƤHE߄QmN>PTvʍ!Nrr[- l<:=Sݕ9&Qql3m9dsE|m{][D8<s1<[ YSmӪT<*/'ݻ7cwj[B'+fQlӬt|$A, L\^NxxxxԪ^ t"c :NS/IjLs!P>p@21 e(1Ԍ˖E$(i֚57jHYf_B$3fɖl"5 ]jftҤ!jdD=-Ӣ+^ '^Y)DSP*b"ʞ$؇maՋW31F`(x4u+BCV"f$5U44LHi(ZffgȔ^C!}_#P ەKu{;#,] |w bc7/^P=^7gtfMGW]W%!5 sq7]w*uuԋh)ZI42Õ%5L)U9%ӒHۥqG?n &BxۤF̞ly.vP!>At|/N!C77ٺ!16ۉ^*yTyz )0t㧟?)3T 1xaSNLE(&ofJP= a4k6Uk[6,bQuյ:&T|Vo'Dٌ/,.2hD;rHOh)PjCP2OwVpߺKܬqg0л*v^җ`}@qE"P+DM4nװa1<ݪ|-9^Ĵo WQnʧfB @z3m{rFEN/c/o{0AIL5'Ɂhd uEkNHof(.Z91-xo(ʆ҉b^bу<2TCﵵP"FvbE$ynU'%Wt`Ymy 7/o]~;G3c J1dŖY4).'{"חWlÕ"eG2lq)!f3*puO?~ݺgm>/_56ZX|>^d1]|ܤ콬/w^ϊ-"ɠŽ Œ͗ԔO&,7*hM Z.輠`paay2ݫ-6CQ&˺=3IW&hc nP 1L8FG KqѵMjZ F1CA1NzaUwU+@IKfEXL!3N6l82?~x?ސ#uBd<}K+;\5bob7MY1M:h?c%FrI,N#4/VB"!ZۏC0T CN"7RZѤr^'|Val]m^DsDpnc5N _-5Q /ӪJnQe+@&3rJv˾W>I?ZƧe:/BTk(`҆2>܋(`,˾YR.PꜲtW2 z&Lpec \z9˹,¥`c-ٙq VLRKNahǐ"g 4>(8l6(KH8qe(<]xv\TԨ1ydB Fk93=J/O Ѩ1N1BY*3gh1_s͜{eg-^gӼƇ֨;@݌ܿΎO2n.RU,?7'g}sU*u~=^V?ђdd 4e3yoCN-sMOnw|-A(K* Q Ǐo'x׷ѳh[ΖPSbp??QnkWH& 2/$7JQjFMQ4PUrr3V9jyMh^Y&@AR&D;+MRA ) ͙ԙJSդ#40C63q{}_)yDw)_yQx*5}s?7cI'6X\ML-Сɏ!qӍ(!$:|DyGrFs '1z ǜC{I:Ḧ́N`()d$A4.?|.boLn(A_ȭ-pL@ϱ!IœF+L;p+3NUcb0 (/Q9BR;6=V`Aq",6KBvB\2L'BRb_|~ws{Z52W]&Ea+VU kl,[NQ8Ȝ`9Y)7 qeϼt#B TzHv߁^eDofǍK4,1a'^g.ЦCO7Iq5`<}zjlQ aF {YH+AGAÈզɋy&n$ѥ.v&/&\T<ֵ+0^/nKG@Mm8zPD;EAw 0/ LR"]C *FxyLBZ,YS5'*H07`>|]WqIN';bnh$T6_qųiq-J!^GjATcş dбǟ_`6+y9f?Agò"{&rmb{k+BuGYvur|zw36'V=-exԳ!哒\߽ќr+]JrXz[ƍp) MYƃ%I6EГ9 %~$$-DiK[H.Cq(YP$!^b9'de jX8S`O\ Nkɢ|:*/D -_@ϏN szP$|p9fqbJI{w;Y 2uЯf h!ą c+Vo:̌!%D92k1m!,,G2Jj]wrܸL7l? 6&50^&{Fv>:6Ob i _'?O%Q|_=Tٍ5&Z11Ԙ@ X~v F2EWKEF"7?h""lQauL_!e)[WrWw/Hnc q};G2m5~4~~,o\.Ҁtw(W^:d))}DGYKc=;1P ė#3 N 0E=i{> )a5]z$cؔ'C@?iRz"q?6`D7)6ݶ̬pW*Bxrx[JrgS!E s4deɩvEA|ss39t408.2$Y*$aCٱ؈{mf 7]EZz| H eIt$OR|.U4Lf ,p{&"Onj@ }!qx}sG) F7fֵ(DrvYi,اfIQyN{?vFŴP5ap}{Qt^wbMfC)'\b]mU'Kt\"9VTZLfk;4J O1C[kQ=y)51{ p~"1JGj=]I|>zyqkcc%o$8(roEV28b8\`t ,vY^(t2#* 6n@AvŲ% 8m;TVFw-3VtVw h@<82   jt %Ksa%@fP]=':|\?3ƃ!}4$+5ߢ)<6 b^py];j(Pe37"OEOژQp s|ކ1( q{gk~#o==zmP&ӓ|%e}Z7uEen i3ydl>fO2iwfC5{GC"˟qys?޼O?*{bHZĐ'T}kl׮npoyY?@xbQƈB& aRbΨl:"e`M*00nkux+c/4 $sZS%5R`}M \S\ZCfLx4Irȸhǜl`9cnj!PMbNpyq\-NOφaލ,w6I.O;+-@ww''':}`C/zv6ONE M;Qf*d Z,*B%3uё73ZzQf:,EG䋜!E2R*MlJh0nHY(0xx)~#e\LDɈ'D& fvLP RyV͔cbApX.3TomM[F%_"[a[rœĈ0G @PPc*D*2Vٜ(=m b~D+$ Yq~F*}[9'pW>oy/7眜ooG~.z:/zyA%Qmp(!!ꙔkKCC Z}C]\یA9hAاhC3eȔNKKHCK(!..o f ՕԢl]PTnȖxٓ&%RR*݃M|r}˕U@ >ѮjE6n`R ~x˂c1:N8>~nHiw_wAxa{-.ruu/_ӡyz;`_oX|͉S!hd B1lNrBe[t Eb9u*ڰmUoRԪ J)BVUDOxJz9.Ã4xڸٞXˍ˺'7^yZ |;J0(Mf\15;Jz9dl_jHSQ|!f_Bt zt^uwwsqqOU!+z2l@q&A`LR2y_aÄz%pIdzLXV.3M+i paD2/@FιxO8#]M%YG \:p~}r?H5IO6s>dXY\Ixb* r_JY$+ELhJ $Ikxkg1:ta zU0#"?:)B vkTiOVX]Şd/>]ŴVj<đGLZ5 HRdjL-8ۍuJ%zYa8v^Lf4"c1_`*od}uEKd %<&/EeR1 fxʀ{G |O˩E lr0yI%!o|Wr8@i@0j]HME+r6eO.P32*i*v*QQn[TuzGuav9dH 艼M1Bn $H.SſP(3oF{DCpsDBD_Nb\QrL,BWDږ* ur=jwo*B7$?F滷gyf껏 y MyJ#\  D=5~ a%n.dO+&~r&)ۅ*6gS>1XeAÚpOWJ UXWo'qBhh!rB'q>%Ф4~ jAy~i*r~kA%^$+9QK@kb) ^q ůnQAVAQRrxܡي|Jm 쨣U&:V6L^_QW*ث7cbۘWYaE,RNx;DQK3^9]Oj!R"޶k`?J$s4"&.êQCɿTD/M2Ag ( m0*i`F=C5((Xqg,1]!wWU;Qɿ]RX>Ubh /]=+ƠXАj9'z-l^I}9U;8rR>f=B9>Փu"0DcT˷>w)nEr'R E{!+NNͥɪi'AaH%^r~ Q׸Y|5z486KEeh}RB=f0ʱj/&OhFa^^X)I.Y?\. 荼OϬHlj|zKm g$:I(ϕ2E!Oj.1T<4FKӭ/nEաooBZ%ܤ`{`QsUY`G+<_PV<Ϧ8WGk"dOG g~YU|>Ik06ySc;4:;HO%ᅵ;CQ<q {#vL._/*PaK"&wJ#ONeizt{FÒ3.ql|yG#)T\k7t$CGQQwMQ=$E?tBvVz2=F1>= z5]!28LGGg4_äXl:K9A[cr8CSUl-yÃY u DM"J*8x,V5`If=lP wzBDYohin٥4$4R7X*V^^ ~I:x=srw'zPl$f+E)Il`f!)v]OMiyiz{UP{^{8hSM2\*qWIŋ0`j54kζ+ȎK&cڌSk4f|/XN̰YpB_ȋ%${sѓKUx.rN&LY:\Sb+Z9lU /kwӑA5sugՒ3Ԅ_ne1ѫm+faJ[UPz7쥤Ca}Uj=~K_c9qyl óAtuppE'#ն/ǃVL qj[GUe5B6`zd<=neˣ@>KVFOF~b7DŮoo/랈n>>gg6ۣ)hM~ߝ&-.p9.+F頏Kj[hZAu4;\)*5'E<ޜ)]:*} <:VtJ}k^a 0=Ӿr63[6;M>U*}TQ|0dh3Y˭^"֒'9 ׯ": uU*>Aa:[_Ƙx~TpBs(k U>-晭k5y_e t -᬴[")˥ 02sqŴVo%]ofEǕ", 'smM·IhJ1F=E2igX =w'N:}8{s,a>z 7;V äw3ooKxѳRE rqy\q{?nvЉKnn,FĽODuާ'CQ:hy'JxĬ6y޻ibbls$Iy=1x?uogwO{6%smYl|ٵۆo@IDAT{z1G$<#7eEC|R^P ʣ`Tiٸ{S<9xG7[۽ڲ<7Ӛ|TmZbRW)M'׫,4O$r(eAfDA(tb͑ ec/w뵎ͽa5<ԧ]KηLv wX5 ń%Ρm/KW-dF#%c3]`I 簜<2wC z{&N1@#zW!{ -lt}*Bz4&, "0})<\$7JT sv(Jӿ)Is~[^{B.8f8!'ZUF#?(U kOU?cAyݼJv'o YL%YpkS#PŜԗLo?g&{yPhE8<i ~ZEtP?ۤGId+Ks΂IޚfRR.A4/䳅]WRSҕ;NGCܳ ^["prS{S4KU )h ,Ձ.G$ _"0;>X=ad?ܓ監})z _a񗷄q3+AmHD{*UbWa^?u?Y`ͅR1D|Oi*٘ۿ8^Xc,$;2"?'aV&cяn-NeWh] yZ~@-5?08 v+*Sfkxڻ"DžԇK^ ԺdIpqMFj?b[_Km,dp$GKMDtd09K3N!uGVlFv˞Uu>$EE|\ ɽbuduiӮ'a݌p[1"}wАs>JMbƿBbTnEᴘbeZm]]L:;&Bɍ~{xN/d{ RU|-+㋉N͠nõն'3'`'Nea qmݕ}h3>ٳ|m)6I?;fA/&I,~e1O(ĶK[ȸa hˋXb |0P*66 c]q$Īy w}wv [o?y[mtd;Ig\': jhFϏ_NHFt[rٛa""} 2R/WçYql$]fF@=n^cc@D|fGK|L&*6S"jɒV?/fwS̐U@d98?a©CKˁ " ߳{~(υ_8wsQ9fRe9 y$s!(B_ɾJ_ZHePEK1'kUj9Az>8印{t矏\#Þæ!HRcy0g꽅&@Zc wM%(_~. %z;4&ZL5nDܹP`(QDaH ̼L7\1N\hXvObݭH^䚞h*ddؑ h1xOPC(4NS""r;ȝ5)f%w cM  !-HC!?)te~˧{ߟ}n6/Xgav;vC껣NW`Ў(xR#df*JcVqo֐0pD|OakX7E+n )* rū`6n/Qދ/ҦzBBRE) ф i ( |%Uߒm/Niah( 1m:ב_u{!s%;a4sܽ鸒~:73U(P&-!-DYsLZk:rCzZ_Qt~(&7 Krh& 14v@JpĂqI4o=YO7SRjPlIT;ܨtr0@a6G ;Xj"^InI|}ut)} &| 55wȲ߽=1z!x8 YW]NCL9K'mm]Vt E_Y={zuM)͹R+&!b:caU$(ӔjXj X4RHG<HASĔbzG=$ Z -VL<\tZO$X ΗiA2bzĺ76ĵs-/ ѪlYKs*m?XThLeے!"E{+ٕd]S[afES~):Qr\L?8_i˴DN$My5g:j C((hJ3 wб"F_׍QE (S/(EYzv;?@ͭoW\XVF"t'JA!MpnُHu(4ou#&.ʊ5<638nXǾycbDg9w"G隘qҥEsѯ_bȤ뛓L'$&N7nG6 #wmۜb *n.eIv&ܜC rv]MC2^r"Mޫ`S"nxC?P67>y20#hٲ&4ɏ 5SZ/op#t6qITCڞcMA eSt -JVIhP|6j ˱(LsL5a:UA047,tD?O .VCE9ԁx5iSlX3ᦵ7 0] YJħϡ&䰘)"mFA͑'[7oLƗh$SҒ˪ز?' 'A& QVɞD,9�c[Gif-D0D(58y9]A?{ V/ v:J*$n7'Ix^1cv!$Y&\"b$깳bLe͝ypZ2-@.עXqY!aAk,q%H:{ȼaU F@S$ށn W7#Ϲ>g We`,GNlj )WokNEn9ܝ{@}V_RlfN'Ua(q DgZmAJ>]/eۛy+ɰA}gFsQE9wjT<8J/ EY2ۂHeN!lPW[ 2T?zVi)W E!h6gC0JQJVG!FSoQ!̋y')W,u@D|UL,a5pF)V `ڈ!;x9#>2 7 ΛV^DEGTRaiUHE2h2 r= }I1 L?\={!huߢP$r'uUV2+ю4 Ƙ+OU8{ry :ՎC`)SWB )H)#GppI$şVs6L7io]$1 a_A*g(8C.ƽ.@j&Xuؼ N'DWyRӬvlt͆܎PMX`VlL"߱M7q,sozKeV/"w]줷VW4u*^ؿOzE9ե$yND#xf+!XOrl؆X^eei0n"dYqf 5Q68PF7L0ApdeM*<W6  SF2A6VcYcb't%Ti !bp@Qx؞ 5KB۾t 2VЈ*X 4UQˠ] b3'!=ׄ߬o *9J "^1C{%W4^kYc(tLAV$Ķuݹ;b ZSf-ݕg(S& @1wxy^*/ͽiAz[!Oݞ78#!ʾT2޿ DoUII-Hр$,Tʧ"+,ǧ}M/(/ap7UAYtڧl:SEEt9A8鷚Q%T I`[NN3RY_3;&!ALo:kJ0Ҳ=UUb*+ 1;4ڪَu!'" v9x@E:nBRح{2Dg<$O M )0 /L7=؅gcHݷ^GtTR.q>{OdqIxj&:bsEvo. Z( Y9ucr$wa*~g+^׭mG;s?mXet8u~wzk3X(߭HnVX;zi/ ZG3#y*CLY-g,ġHTfli ׽a5)<^.`IQ3m2aB f m&6tEӲr?Իa:gr9 @v_]OGnGSNMn$ᩉ_p8|HH~zA*;zfr*W`_q^1-Y:kypr1f-+Q:dtC\9Af\7LN{b0VW6"J6gL+2m-X_cjb24LBWeGR5)/n7ZGԋ"q34.1oi_iWAoa{qKA&@v벓< kksiuztBMPu?WE2m0XE.;njY6fz`7|?9[qjsg>_|WCE|ׯvt)s?/Hp70YiY1$גHx}{3:߻1lZ 1t<|w? PP1 [5Z~6LzUmh\./ ;zQwC(]i8?L"ZWo'}\k,/d0,&.-uqT`dv^0{$9}9?rD#糋ʬ)z[7.ɦ .}fj۲ch[ufc1?_ZL#9D__نFǽI%qi[}u}RM](!1Эdz?k}>MeEf;+"f%2m-,"w ~"v"swA[=J]GH}]|dˣ:ߟ݋ěyg۶)䄁v>嬺Kz++K=Pd$qB48R y!_&^Ä xDsԱ QS^>L.;m*cpg. ă.H.+$RS0'A3#_¦;^3A/<ԟLI:*OР^V% M2MrW7YFմ"C/'`?KߪuICT\IJS*S/iHnHEvy!^5ADC3$Ji)+T' MWB0S)PPhR,S 2;&A!m!%I%΀kVK&Sxb.,(OڝȤĹPs|doEG;_Aw../.޽⚿MV`Q< 3=D1 ggKIٔ#5$25k3ҵ' ET[ J,!1o>Sr})yF("* ? G2 4@H54 N_H-~(I&b HgG5wBgkK((]1fǃDA.mǽuu^|MT#c/O۫wwyQ?֍^g^ՅDKlj2fcnd2gfVY+JC! 0*b"k  5Gf"=))\y﹛`TۣK^^ތ&1^dTOw!n;Fz*O^f# AE3e6I*&ʇ_N~X6Ƕiv; G{Dh$L77Յ4%JH߀˼nvxOpk&?=ᅵ@!Hlz2.$U`T>13EkX̀lN֛'ay`DGٌ;{]T+[0,N ]B:\A@r@[IW,Y&،ϚVJo?KF3&rɜ'j|u!˪*Ql ,B*Ϛn@D]`b@ :"l%HrGLkuS|)Ó s;6 hgfTjhy.\_~'W`u›</ŧ*ܛ7M&l4r- ^F JJ::VY$S֋+wQSGDSrёf=29}5SW|tFPrSPy02#3>렔  eOw3:7:i 2 ,z={/wNɖ>X,RDD)1-es2:Q @xOKXFoԽv Kyvzy=!L[-ԕOӵ; ?>9d&\N>0n2.{[v32`<,?|*)qR}¬ 0cDW^ތ/ġjr7X~g m6C7߽ٜ.2?\{w4a@%!c vèkƲ~9CAvzK&-ս#.2Z à5I~m G=-vLS+4&M>%"5c,Z,bO4|&wa<^hv#IiYL^drWbe"AJZ#]l#W5!'j)Ywer_cΊvG$gJa]PHEsU\][зf*"-Z*PJ#h2FPbǺ%vD!(*#T(Q9>s i5c캾|!i^r}A,CDQ$NmՁ^}8oM@ELDʠA#*#K-ـH1@f>M׮ItzB][%gT2f_=]bI5Ւ6S45UJЧt^A?քKc_,G+euW>ǒ-XR̪ JOQJH3N+0 {DE\|tvGLۧEd(~gWvu\\ز*נޛwx2LVw2 qʷd+6PyBdX`xsX3Ǖ-i8ZOcwwVXbPK XL lmUr(qY{jzR!vCd2A~S!Lol }u}_}?Q'I~:@!R~-N.N.ݧ~@kOQ0@˫h 0۪\i%b-`]Jg~]ڨイ@7;(ޑ''kvZ2PL\ym\ݲ}IkLӉ~n45DzKG6瓓s1m9Q{r-nncôD`Ăih([2 ڙZpb |bNL@̙a Y҂1l `rh*D WTSukq졽3$=G A(Q/w-櫏Ϫb\hO?*-s!NsS{4'J0jJ `M&!tsޞ*!A*8 6 @\8zbDe#'p_c맺{ bN7 _C7a|7ޡp_>mw;'۷o~;_\N{3nPQgʵG5?v$X%9Gp 5&!e1l%Uu NkmEg D/=bVdfZ6ota0ZZ:uȚHJ!4EaFKN.jd?į&R^h3?qZrl6qoeaȪPg x̪&c; x$"yɲR Qs5? ##Z>:" v F s6®dw-0Dt0V6q#4[p(QOY8A7lE9g~̟GRD Z+:,?%C n֦ݻ&^?P%30X~=#MPuE&5rBf]\@ WFzRF5h(*+uHjُyJ2$3VLAUv|#n!)i(kH3s GaۖEF^m^?$_sa\ak扣 E 73, H8[aQ5>1GT^\1-C?'WmU?>=0 cذEMA Y=_nn9Ye_^[$RyxI%1#M)+Vx zm.$K*ub˃\">}h]룝.{ے.Y-Hp+KkI_ؖ,mg͊&R>DɧcN۝/gK鞗vD1ك*ds |h]-`2mJcD؁H^$͵hrzvrw ?1^NfYb!YfͅcQF{ЦOf7Lq !UW=@IDAT03 iR G' (O뼓ƚϤ8H~IGcD.ͫV²B=(,toaANFp4}g=~Grk@p[T~KTbJFQd?Q1aCwR@JY_-ԣd 9 *4KGS0'!'&_p |K.oBNpt( qr%N`HRBgWIw'EF:eV<^]B0f))',&5gyQԼ6ۚ8jy;Gh͙synh+m΋Ӊ0eB0Q&)/ujP>5膕$_M|DN|p zRZH9>Yv!cbh,n x]‘kPhJRJo)s?38|re+M%@ Gؼͽ>9"#۔OvTaW|Ͷrݑxaol]Hb^NɧJ$_Oϯ7wwojBx{Q8x~zl^y"t;a:o,-#exTy2#>e w_,4F/wReZz{d~>fvO?/?<|m]:Z󋳽?͢ng4#8nwtgbsUHN3Qz|}DTx㛡gn;}!%T5Ý?2FbR_kɸó G&"JP8uF=/Jmk?mmom$dF&k"X(ۜ.jzzvR$=coO9i8QP(SV"IJ+U;M+J a;B3[)g"F5Ć/B# ZRf(.2:ـ{B$TXAб+)+64~FôiP.H_ }zc?;S0g ^~V? s* vɎ\̘,4SB'9 \HskE۠D.䟯ۿ1tH3ʳTɀVyWfh3_Okԙ@SNHN#63O{*=q]̶ 35e Rk.iF@=*uw$O΂o#ALs!-1Xog+ViJ:],ή7;nt=X>Xsý#qgK2?}t~~e7e7LL ˣpFhw_뾓@f7]g@W@k|MVaG&^B/|_\ܞʄg<'Xۃ=*\^q4=.f DzQv:s`.֣?w;?NT)8 aq!:qa[S2^78Q.n•Gtl&11h&>!2S&[|w3<`=gad3JhPFP0mEgK9ֻmSb|3}ws3F0m%" E[_LCћ'  e BŪb-*}|v C,L0YCjȌ0)5+NeTi.@E2EHDý`$th [b?`YGMzPxXgs4Օ%\)!j*ևQULTH Fa,7}xI (#q2[' Zl|6ϹWe/XT GWQ [(ΙZohH/u+SH ҤOrd04 @g:ڧ.2OH!m,% eX"z׏#wıu< 0ROoPSYJ- IL +tNus8UI~\MV5ҎSpz|kjY'un6' 8CXEz~iX5Z1&`qմ3qLTU)jٷCNjNYTrGǯϛWݻ$O o7y'_Fl~YFN'֦ +RRB>(J$P }x<a~$Dt0;8>1llߌoCHPdJ`{k=B[=I1D R=Y6{..e&ØO#XeGk%"Fb,IigaڈdD;gc̊x Dli" Chhgoo-gz( ><%i7u%4G$6MU9&/)]n?㳪*cX%'+bߛ7򗷴59 GU'@HBчE?T$ ʂ61!ί9i~v9onqwR0$?bM졩[qnPAQyKyByCɿ^_mjR:pPO!´;SeT~V_ѓ&?mH!`c W.+>Ѡ͟eеfjy=p rTOgy$"wHl*1,qvOhoUVe%̋_c:U5WF4ŕ`2>-A(*R!mv*QʮhoҺ'R*LZy"I*~}S;Ols.>V};RE_]i:F2zuM`{[쎨`Aɛ$knX``/*eя/..f .m'ʗOVOf8yHL>F\"+~{>Ku 2Ղ, &ݟ\=vb\#Ohk-ʥ9)jc]Sњq$c"8 5DEMR ,U-~ *]IN!aiM *mg-9Ƹv"¯TL5G~e"@0 S],y֖5` ϻ=TB{$+FF4|jm`5.OEdPۣkb3{"ҰoEh8 m-O_,4Dr}/ Z.5UW|s=HP=0+<|:o.%& #5U('^dAΈޅ9)SPWOLL0(; 0*GGU{'BMJu54A۵R28t D9(}it5G: yiם\8k*j_!'VgMi@U(J2yzW]XT]R~Cmш$XZ͌@ vZb G J2Fx*(bUdOAL~[\o+L)o$ ZVkX¾(o`6kSF9JM:dQ_OmOu]<\2+X{Wq>%_zPK^#T~u9ѧaǧ񍭋?\KBy҂?|hЖzU< M]c+[G80r<==-V7׳j3k^i}RJcZfBᛣN |<fY.r Q5=Gg5TЈ D6Q_@IHd&_zz͑K%SI͚-z Yov τŴZ+։eK=.fkKZ/ 5"չhIndl#WaQؒTy0"@#'Ƨ0A{vlb.n+ 9o:"0QsW4/'/P\oG7)'7(}NJC>Ik `Vt qufbPAOS Pr9xgKT BR[Gr:Cw*_)SNj'c%—lxY&S\Tt0@ Je" |MJe eT)ysqTT./3O{y3ly:囙3t5.R!=K)V˜wc Dɉ$c[7i (8=6æ<]%,1IXkdۧCur;~8>&ћ];̭?:|oKfC)ge<&^[ٓǟ~Z8?a$__na-ֲSD[&Ã>lڒbjd!L'^Ro7̟gWͣ$Dž&˂<2%U9'|#&DP`fv[YI'+,jytׯ_.,_o?>ީlLoMxrt٧_Og[P`uà 9VR QR>f7Cic|VDos=2KH8 ,&Sdra<=%-y(K.D̸-W"H2I᥏],MDPH0y(%?5[]3Xf RcW$u2 ,B-=@uZjlQ ~%a`1 \1k{FlX F>2)#0!KݡQBKx/gJ]!xzFz{*-S$'txr̔uG45;~ (<ܯ(9Xt*1*$@ ~YR@J8 x{ +cW89ª^u~󣟂9ɯ2HYi^[A9T$2y&lLkrD8+@T?&U̇I.2мU72S c?ULzT髌ORB3.S5x붴20=ERSHip'12~tUzI{H^< Q!HY YhHh b]_r"h0L؅Um+B2P֦;rZ )GߤIґU붰SFg_>?&9[t̫r5RQM(>k²4պyX~>M'.q*\JIgF>f]Yܽ:JDԛ7 ;;=5;n.?A:D B)n?mluVή?<ov:+lL$5GZmRС۔T.IF*[3Hi+{&+,,: ho-33Lɗ_6+kt]erl<~I`OB,_.?CZG$Wjޠ'I8:HH&D,pDeOscRd^`@B[`%>AYuE ɏrvz\vomJI8S&?U9ccEO 2 uh/G8ww k^Ә5Z'dbX4 2k<}JAzĹͤt%x2bpK?GqQ+͇w\5$uʹRmuO2iU9DkI4V8@QZRARSB jy/iz[1ϼ/ѥpFC*n  b/hPz\1fJ&'3 EdbDtWqN'eZ6s=UʨV|Vfq1dT& NS`S&"{m=UoZjx־xʨC4-bu=>|d$g-q|Ux>%a aZ`ʞ}7=g'G==i<j8"R/O?^~㮵pfheocG8]q(di<<<8XTywhɖW`4~ ҅6.X*1)QQ|[;'%:^!ܜ9]ޜ1 [lw.ƫW-ͺ[-zVK!aeoӕGIbrpE7><~c66 2JӭUϾRBL8I3bɰGoLf"CJƱ3+W&6Zj덉ju7zzd,n(:pP(r  ;ݖ#>%QRN=JW㡸2ܠj' VGȯyyҔ&>(*Ap}*kXR#:(T6%f'/<^WG5͕9aēV=P.ۀBЁ Z h d=o8l:7*sxe*3H[ !F*d?F͑uzZzֿLQ:㥕:8ȼDE&'PE -& J8x5>tK9bYM<**WVe6&- :NU4w @lr J_0 ݑV vlAYCz7[Z֯8z:}U:{/mMhD(Ȩ`lm3kf/d2pVQ'"#H2M'{ꉘ$ei%"Yή)C&9O oJ!`{@Rǘk( |Q}=ND~^SFq̧=*%VU7 nƫ85A@5VZ|$zbt7=4u4JJï%4? #EP Cpؓ=J k'/>=ykb%?8M-4KPݯCkMW]Oht7e "h7悗ʒQ3z0ZH]ꂭ2U"y gyژ7 kD]=hLT +Z 9hV%@* ;|'_2IC;VFpJ6F5աəUm7RI/?_ɀs-ݖMg4xonQ2>>[h1#EoYVY=p`>cVrOrr3"k"`o(;eMP)8faXodD{nkNaJԚ%ˁezgL'328" &T,{ԽVvdNE%޳3R,!x DkNOߙOPNdm 򖩐yM\Ai7Є.Eeu0:hu}QV v+!j,g\& NKv%XKͱ-,cmm66q m\~jd'2iF[Ux aB}?\,;'!h' ]`+X@jS U"m2Q<=xIpР̈aJG!?^_UK4ГyN™Uu_8+> K:`u 8\JG 2iޗ@ݖIz}K)qg.DqhIn`4{2W?PbLC_@Tw\GΪxwo&sa.d:e{{n3Z禋!-^\\Vvs6;63!Y9ܝ.DwՖ̲kkvfP0ʔ4jjA'n,3 G΁Q|`4t5"}4#RU7 ͨ<)rp$UkGWbN,H#bxQ~MjҚ4Y]UNdL&]L(tkl&#@: fι!7&{±1$"Z?>$[2$Gf|; ՓXɪVF*Hj!hh1{ͅ_^0&&k}em5Mzys=%0FG${Rj/8N/ǧ8lm{iok-Ke5 ?>7o*vjfafFp$<Od&i`ёG=L\Բ&ݜamM9Z.ڜQ<+a&ZX/8B\٧e`ʯbg+Qң4]* nEްTohDyHn/o'B %E{p zG-w޾="Kl"D[(-}W2 lapc_ςTLjqx!1%.H^lDS3aQFP!m' xzj'4^_6 ^%d *XZ :O\xݣ#4O( Bٶ#Bz]$lyNqUǿT]MS+GYy*x^G`NiUДbf[!g=_&O}WAa|5zJ𘆧C7cեkuRK*-֋H"ff<0颢IƣaP,)ce_yDpOT&SRpDKxSHWղ&z[Bief~'+q;;= u4Ȫ;{,K҄n[x,Y=="0  CLgUefDbnfn>YMs3U;zTةL`:y;t>I@Rz<Hvxuv 96W|s}) Zڮ qm,h <5[ՇƤМW9gΧ-'r7s4ztm69mf!G;;l8& Da<[{b$` lulHg퇗ݷ,GϿ<};؂u'H`zh/JkKp ۑvmK0_QFZ.}B%3Ԃ `q?~i|%8pnE-#Uk,(؎X:| 1X^$IsWɼ42nkrDRGbp6Q>nf./SYid"'EIsn.qsN]ܐnL;hC$5#/FdQ{\SM6'?s~, " @+)S@Qp$; xD4z"L?f]j-o>( H.䢋)ȋIiR(A覼,֯>ederʆR?!ȾY +h{yMsG+SA8uf?.fdy^jɟpׯnwѫ眲pCyE;k~0q֑yY ɷ90V뻯noEY"3!nA* ?maw[?_>ҿg O'N F،E݇Yq.Ժ)v#%hl`ߞΧv-I3Bfe< \5dsEVBնT9ynN|f$N9U ~Y.ȨxBW2Fh f4qrY֟N擫w&?e[;$~?enԿ QV˒Oa3O?;޴Voq#c'5Y~!L%]GʥX(\-3e>#y#7\).8xK04Oh;Kg'/ejmy(oALE>n1P|3F;7Ȓ\x۹~`p@Iy '% I6iZ%#C28Iչj*p_DƤ&L9ipf#OpOӿZ[,]ZK8x)Q$?|jp"M%Қu VGRMARA>ϛi[4BޅG+tJ_dȑLWs{EL(F)U#J#4RG6&qUcJ˿lakx$&J Jƴ@\:.톨R]}Sd 2N7rf.B]]YԙdlGOyҕ+xjGcNQjBys8&q21&tĆ{28cida_1\ݚk&O)矾-x~|60t'?J(>b6?}la?lz<) vN_x4ݘ)Mḯ2@MW*sWX D?$dHVo&S[1،S7I|MQj5qLkl{nnGV;n+LΫipg sp]@  jӑ X]^pC@ ,f?o5o >lI&2@?t 7ZNw+j[D[|#TG aK#¿TRP2 )Vzx+S9wr 1Na8 oB'y1JV|֐pF48L^q_!S3[EwekrH+㡼WPli%٤ƐVu7nx9s?d8k"@!.5&^Ri wEWJN9ʐb?SHpJ[{).p//OҚ>LQJp܇Z\1ݷ>͍'S^!4f`T|tR:Zd-16IoAmr.G%*3PFs=%ͿH1\}rǧ=iNL=c,@3e4,w/+''敬=ԑ瀵i1c`HKzdqѿ+ W|Ό}z$БZ3Ж8!L<ի)ߓmmz_sv;Ci픧qno3b?Oa6xq ,Ύٜi;_Jd-CN$phȖ(|_9>4aHiTra/3zcaGWEXkFqf+,;kS$ck _PXgaD6OJ=OM@UR-ƧCIi7zғ^G%TM~py]K,^дC0PڐZ5vHS{2W:BmZ?5kl [f:bWkJ.鋦 KqUrV鐝'*fGWٮh)9Ɏ$,Y(hd1x8҅9IttN)FB\fo_\ly x/_?|"w}t{wC|YD7#9 λtxyg93MG"4/xk'|K`-"eg ʶbњ͟2ٴK v>ǚA.PgN) ̀?))o:2`=(yn)"uD1Ygaj*.fF#w50>'%&H!^BWD&li|ak aѶe0)̰y;xv`z3P0(zK+`h.cIJ)|ŸD@X0Bgo&# ƕIp-(f\޼f¡с7`[WGJqI1J_#ILC菩dpwKgC/8!`v}2YxjV7S*%GD?M&uWAcoTsR&Q@YD^je_?>qťvR]%(ޅ.L~{ {Yo[m3̘D4 =+u ɁέuN|Ja&jPQv9YfH,F3_ػz=a蓍A 5|<):$.AzwoIq:6-%[u7Cx1zyn-)//,;ن7,%يĎdw?n @IDAT?ӟɳ޿'\6˛ !ruf[cFw8 BЁ3se^3$ٶ o'MoS= *b`W'a4Ag 6B!XXZP`td4V4LYs>K^C2!~#ET"0L 77m[Nh;E-\'չ]J{uJ8 jrMֿIH6Im@:15ПEo`Dյ$C!ƬeHQFoH+Sjml*CM RBL7)LU) \78#~] 6B/f`(7YSZ`-iIrE,|)K@TC"0 wӸ*j!J<"OO?\]ڛw|&vp^Nm_nxy_NsYUhdiT~ph[0fYVЉh}lgcUqp&K;$:YPq{@{mUDղ0LlV3,AyxGw*^·=e.m1 }CHY"IA p6jJ"֬8OХO牬-"UW-9jd.T7xd( "L*#$碁#+"J*TPЙlj.X3& tjjHN!Wg04,R;6ԥF. O9r?um6S?=Nop DѸy -cRbGj oPAf-._A*HOm9iUs~{O݈݉:BiBeHju`^!SRVSHK[7h mpB:!; ex2IդJ \;{ d|yP WɪI/[l,.5ȌKξ0wb]2ieKqEmѢD٤J'@ut(~ fbE3H'wU*NG%ZrbFX:[IyT I>RBT!R%YI)@F)]gB0h< zFMVx?)eaej4qy`yljz)4w)"&&7q}cGrXP"['Ce O!+U&&ZƍIWIH@aU9媒|I!Fp*q& &l{ xԈR,TJtID m/ K)2 /CIut(-3[rbC?\TҗD@qg "@+Wҁz./wgl;\lΑCDyd N /`s9S`#>_'kjvV'm._?Lm7kP?ϟ}AULgpV 2i, ϧJ9ahGm̰v߳ yJ_iKhĻuh5.m[{D^/~;za[]sdZ>@Cɫ]GVdoj㯓%XxJjac P{!ȫ'E <,jlzu;'e%#+,[}e}@\'zkn*{F5|W1V -`lM̋jsd)1}v "x1w.E\a\^6T\M0!T붝-x.,+dإFq%ͤ:;K dxP@ M.g7WS3ڶc8ƺ*qwҴ 3vI AXr^fXG^:oQ2$%auɝBjv_ƾxQru,\m6$~.QYFl:UJ'/)`D(3ɥy9ԠgqHܣUݵ;oY ߞYer&guT⇚7Q /oZ@~&6oZ| ?M49'J^-er%L^nPRX> \7 tW92)CH ݁6|KdY/ZeŜWgڦɶK}sԣL,6]@ǤM 5o&$*^*FS$?)xd$"/|MI*la`LÇyϵbelJ/"' ]։sJE a EEzޔt( L@3:(苌ԡѐkX!/(/5blP 2z GLA)]Rc*k?KٚGn{o 77Q\w'?)r¹pӻo*~9p.S@Rr yWlD%$R5RhPos2U n$00Q[I"u^i/U ee7Ec5٣6q N̝Zє>#\YYDW6U*2rRQ ::1-[+Oo功vE`$RT e "O._NeSVO&P•:~18^:)4:QTR8kr3+jx< Ch$mۍ:Rr\iz8ņHlTC,HY{z&Cd˕5D&tu[7Eo ,>qFE`$#~r"J c9Ǣ~<ߥ찕UrC |lJee:%}ek*q4mO<ΊAX]:KYͫp:$qҖ{eβFPMsޓ70WFN/Fjȳ=󅘌py4=]N1lCd:b@J1CB+ v'5{LcU[ ~eqUb%^ hB%>]p8"_RtAPC I ԒįI6M|.?_G(`{us:kJo2~"QEtNCWSfJ`'jN\tL,A=`#ńfO!LPڪBty3=?%hܯ'#. 3*~xfTFR[2 gJGh?5(8)<,D+2-Mmӱox1ix;fSALfŭݖo3^lzSV4٥ur5)V$m6g&v-|$ CB]ب-3]\>Iv f{]DWJ2O-ZP RhGT,T"lY G>(PuG![ 7&*gR;K)YF;.{MŪqo>2e"D^ qyPyh,`)1A}a33eͻC yfMvH,{;#FDah3'+j&˙o&)O!%ClNSӼe> b2w) rOvF NYly >fAdzSrxj 85sg l(hX"r :zJf@%Fdg|6e9$`?jg/ukI<;=WPҎz'8Ⱦ? 2.Mhv/As]AWWx鑈(:wdD2˞=". TpZ.t$l ȎZo'$q:6V uu5ı!_.Ɠ Lf ^N ޥmId:̅hMyIwF- u.9d^"8ΰzee"dkaQvju+dE Ȣ)s1bw$z$b>hN'I u͖&ka¤(6'ê&sWDȘ  G=$Qpm+i.X/])ftE}ai9pQ`w/xAvWm y* 3T4$:vxXEG& Rr%Lk 0e&Y1Gҳ}^0dԡ^g"DQ݉ +lUsfO HvQTCY`u[?2] -ϤNV6(]J_oV;hLȨ\dkӢK+n7,챡K6FEV? pg0"ԳMKqO*Ge\9w7wLJ¢v;N^4͆S8hE0Ǻ\E\@" IcUoyz^zSLSk=2!),MhNaH G@NBր%Nኩ^]M$3PsdkK$RLό^"ג-x1\ecGŨ2EIfUۛ I{|zP{P\rU_b%NPvg{?{'-b "aXc羽W77 o8o1Y=G x~#2G xwOjV>S\m RaU#~^0"y#+kʙbQs$vn>V9͝"IA|[eh\|TW~הWgȭ"FJŰO *c { P ̅x{q¼[ii5MUb#O떪;^HqHic!bJSAK M{gUR+F:LVP&(>?qELL5r$׸=4Pxݶ_ؠt*o*=FVD'(ea`#kҷfyGURWE"GCIU1eHԫ7c-ⱒ 5֗T2ι`ɣ̅e#}:6~M'ۤN.ЍbE: eAOt|nl)\4+ZbAK矾:jOjlj.h l;"ҋL/9霛ϳj_om:W:?3wy|r|S ;FQkf^&ϴZY-l:7 a9ce $U~C6ֈIJeC4@B\%5'DaO/K"n2$<>dfJB>n>thŏIHBL}7&aKCA nhĜ혬|dNns5MDɞfR]')a뗲h$ t)QYw.V|kEw㧇%i^}W7&Lç0EZ$۠w.dů_#*9#'\t;;_6V\~b!9l5׈NH$AFy#^Tr-(~6&*-t,2%Ē~t2Kg5&' M $}'юQ5Y(EG2!,WǧN Z5PczS5b #H51@0xP-;/ hәuz:J^ 'Z柴espf=\\# ]kEw~ڥ_hw.D_:Qz~%M,j+ד&Ѵ_h(ݍq}~8s.MN5;ǫ㧹YF%MSzY>\ѷjxI"Fzyz| i~A9?އQ5?; ;v|^Oϒ?]JYꢲn4(yJ{%)?Olsubbxe9Z#?oF'iP~s䒀s`3>1"qhա`S%XJj(\ (TS4OUPx{VSŀC.0 ktչa+E%Yx> =+Ŭ4@jiB4kl!BUt QhDysR]/ od4-t (Z{]KTJ+ݜ22!S*@x3Gf/  vKn%`&6p zhㄸѳu;hiRm!`sӬϟ:;s1b oߩ8!38#4a+#s[xzD_o'E ?-"z~9T6ޢ=]_:n!FH=(9:=Ei8. 9'vWGBS_~\>.(Nw>X;MtYh٨V"hX[:l"ްc({}K(MEW/hlM^4DȨ!Z`yVeSpnҮX$uC H,'J?)!:iʝ'm|9\CdPPxS=]׸X1"A"f -gAMrLipĿI΁_qMj-'ޡ?6RmCp,&VK^>ZΗըk٨jeT@P T -L1hZqO?,`5df]*z bJ~_ӓW˟1^xˏ?mM^R oyᅫ{|hOk xy^7;a꺰30;`֛B,<:ƪnW?ܶmcڙ,#l OϞ:Ͳ3 ؼސU=r~3sV 98TG%\pe {5"Y%k_{X{-]C1b?>>qHa\/ʭ [X,KrRiSEGs= qZMeO*hn?&oKDid=56bQdG#fҿE/o/rAb<$Z a"=SOE'_ AzOa+{u$ HӍ]~'b源qq:ٛ)EJq,JeZ9T}>܉g5Z.N?)EOE˹s(4)[be_ՖAZDA/#E_5_6Iɨ!_ȄDIp .dMHLʪ*6KAsd⴯'Lcd 0f333& ;2I?ń5UDk_m|mAi@HA{՚4s%L4D$9M'&AhLUܛ:G !+MG u{Jw JaKJIUR C -3^ -]p[х˹ǯSקAG-ן~yzJ@YZ~^]ɤ{4-7?O6#[!"<8x48A/0[X 9֒Zyu.ޭy/x,[?ݎ}eK{X@/aԣ Ac| ޗޚ(ٜB`MrbZ1uh2/ptb]V/OC}҄:ڝnl޿6>N%fjAa@^"ƨD:\e"4lZ(O%KtLzRe! F"_H!9FԐ_.FE / B{9BLa= ˈGVx=#/n$΂A, # :u6o~ ߅;Ư%e՜ϣor눑Fɇ14WPȁ|00r+P㚰_3Ky5I6A.6m*{J114b\h] ze2SɀMi OPyjA@/UJW$稂UI -ikY0G^2JKGokVhR/cd Uk>)7)gYӺqh*niMH5XaWQU]@IDATBVӐ*wfk|ohg8(5'-pC\CR>+Fv$ #s@a7C{u* LzDPg.3鳧{W9D`sIT'4}_\] !/?~6m&AUk<{XN:?_7ɋ݇4:H0!cuw¶Սd3Q1sQZmmZj93jrn<O֖w%XsƋz`"ZJVk5'l׎!\++Mˆ WVѳg6nSy9+M);ɱL&H$^o ySm}΀5629뉹!~D;v؏=#@' )>>bN=aCМ('i=- t Kȩ"wrxW=fJ7$\sp4wAKu" ֜3*Zmo,d4}Y^8VzS "  h{EuÓ&oΑM}Wc @EFp HlY&ZYɢ@%Q-+cMz$қRܬ.7SNZ C6p_j٤U]]BGsy:4uC V8bnsz4aFfޑqq]{)fiqulh/gGL=b0Tʸ AlW|vtMcIMu D\[MBxBw>C2;/1quM&b*Z4ˣ dV|r*bt![Q_>i4kQK%ė:-yoFc:_xyQ ׼!##ȋ%\sDPSmѻZ1jY5$>s!#aQ1>۝jdd*ڞQO4l-@O%-]+Xt85?s'FށדRx0S,0\YrjmgCT.h7<^N{.˾˙&"lۏݣ/?}ӗMkyf`jk>'0|}>#~-Ʊ3G*EϷNˋ0e+,d00Ni a%L>꧿/fl؟=7O?,2nu|<}`W '2/gP-rW`֜Bv2].Y-K/ON'+QK&1.ߙ/ww7ev&dT1= ֶe#"}}KBĀ-#Y1Iu;&sakLI D` ,'o .~"YOȽ)7 N2FMD AC_qMyC +q:^ri q>IñUjfothpJ~(ED4P+M/Ho%@i[:oRyƗd"kB ^ğ򑉒()hMO`=^H'x@͑*I/W=EL_6 OGc-u@I3EOb$CjDL=h*@S;2w߲$P t9diP<8 gM5yNG4:,#wR2^ نQ̡0|S  f"YgDHKV3L6󝐪֠ʬv~M<{xL+$>|pt2D⏉}qO͍ u]^q' ZNb^^Ri6tzѿdcXl@,KqE;;]6ᛍ}+Uwz}ԛxA0ڶJb^07 t2OT]\EAvG;АiToۛ,C鸳,C&8J;nUp3㒿_3+lAd߄^h|=II(Ttnkd]~tbm%$T-F,C/BEVag/dWh*Bwr)LСH?QrnTXIONM}n)"IN:!2L4#Mqq[u3#UJR*M)[XPJ&fk)^ai7e>d+one>GA Ea5F*!'hFٲߖJc0(S^ܷtB 6ԑenVJVN )N~xWߣ|1 q GtXKp:!.6,JI &6IW9=Q+J{b *I槉hH̦4+IYM[ uB%ղ| BYRj G1솆4052>nVpѤqف=3nH ܏vXXƱvzd*)K[9w y|6[im-֪kpзv+4+@~ R5MМdt1F3i ɨO_3Tk8Ų^~oa}tgAwb?Έd< '"4 5g*4 Ǐz-?,1AbxkQBA֔(ѿ貹f==e/??|AM\σF$YPWNnMSO^z"ٙΝL`O't zb?U I8Sy%jFp"ЦS;dCNAyH(ORG=d]P$axxEө3fيI3[òj|ߘpaW@~7t]l2ooSo ˠ%?T|rH!\};W燖iJ5%L%4W%~0ʭsM&M\ǼG!T$?͢;wRy3Ū [B<"YV)kj8XP(u:$A`ѝjJ^cn8v*G+Y@Zq"`GL\KdArzSR`l6@{q"FMc쩑! f*c+o(@ev.|$E"葔\CܱV[SS-u獲ik}{ev.U%j2|uv9 mZ`nAz=#=EF~=<#ɻ+Cw&b(v&r4+bd[CT14r(ࡰO@c*p6&y> S OyЫ¤AP\BTOh$_=d/猩NGV1ɰ)Vh9!jLR%#^\܂Ov 6<b2hʖ -gQows}p4uƟMS}+}h&;#7 75JMw\f;Dv÷~LpRLxc/mJ 6K>CdJJ5ѷdR D&oZ5"9`@%pO5ٛ3B5:7a>C "jBX;;T+OsHÒ@/rf(Mw70dtPC\zÃD MoCgq 붎ł{XqqUȫ`px2S؈ˏ.!65 p;oG sb|ݳۖUEk?Om?=MB99bE;Nf-g†S'ﯮ.X˭pWD 8U;'q#t&_>?k^DIbs{Ǽ*yz?cͅU<'ࢺ )EqF .6`l;,2@v[:؂A}@khLD /&-f⋻`^g<@h{|Gꛞ#RQ ߅ӣ?|gj000@K uCibHDb4PV _Dɟ2)[t—(%|Pa&"W5.INږ41Hp(LwS];w#u3J$ @ {]k1]r7:"ϒNPayuM*…)tz=Uw$s64M/TG!SkuA@2֬JR ;a4FjFI+lP yl7`7=֧PTf 8uG?ml̩NoD Sa@: ERЉ""w:-갖WJW,垫X߲>}1[(.!HBf@^M\|_׭v}sAA5d=!?#`Cx|ek{ft7] dD*|L /qXgvpKW:oZEƻ9t "Į'羽xNΜ:?z6I8M'^|Pgp}uaD|؃nTHzٴ,x`(OdomGaX7+u~AlV'/>qٲ~1ݢ-;.rPmԾ &h,e Zjg!q3;4ʕWa6wLa.d4BjC gU@ %P4yH8}QTU|kf՗Q䪛bF׿~=ImISkzz 22uVϤO~79aR[|Wl.dh+dz3af軀R&K26U"ޑe2:ֿ g6/1Jh|,K wOY1}D:Y)?~pW)'\@+jmywѝ96 X!o[4 +67^d8&Lkkϋ9+hǷ}Oc;(/^ N onƳ5iM׷$lLzk;Se3ʓ:Grjhk/uËXsZg}ʻP}r}w^EU"ܷc3(*JInFw@g:n NOj2`Rn#ٺ#2tRӦߣ̈́Ԋ3me%f*1sNPhN86GfP.ʉyǚVt;YX߃E]9qED 0xFrb!0PLjS 9!f5ytZUݞQBAN4JK|>_R?QjВ\e+]SO . l~EMiIi:5 IJ)7WnIYf!,&^ܻgl.fnZ"jz--SS$MwgQ)LC%rClxD82]>B ,ec7cx HZ(⁝A1s$τԧ[k:4#¯v7d3CipϞtF`&[sj U?]KHn7,!lw ^_g#Ͱ<0"kj=wqo R,c?Qm]V`7gr|hu0l]_]^Ο95ndp~l2bm246o3tX_WX3 KܾA<[{d0aGo ]9V6~<>Z=nO?;9xMp{XَP1GZU2K a/q c*$@LQ,c@XrzzwB`X|e& $K$ mzgQQ,H ?ta ӭ-+ o5Gڠsj?5 ZckM6(.OG뽂 uWW/7TG?Kaj*z7@Haftm^"?V|iӤO"U=h2rCf&Q?5HZß$kWEVu72yZM4Gˊ|?_bͨ??JMhI!=)Ddq/HI+\\O"K[VL.뼲 /N)y=rz=}5sYHy# +ӵk[MN"ޅ$O{:k.-HW<=ϊͬk\׻Sd-Ӥs_Вm~siZVoFG <B Cxj՝CX8I~: IMz#$"]qIC{[Q3d:"s$Qz;O8%,-5(t@v.N(~_JI3CP+':~-I2G(v hʨK6͍~Nʪ|kSa0*mKQ ~e@erեrE47LJL¥泩O9K9&GտTz*VF ٦JNW/BB.\eQr`t ŘKҀn 7=V6}U~Y$%+R4^CD3#g0jL(Z$eX4y5vτוg1!W(=*x8IşptSb:+`TD"8؎UNT;y"uHƜC-mL+9cZJDSvݝcn9&,<_YW,%ށXg(`.^ S8/Fj{kh-zuC_d"RyL&#+9~k1yne-Ys0,|忽u,]fԶj]'VmB3wNG³62jr1M-μt`+ G<>^l>qV֌#L~ "!B(yďN IRU V,(6lZ3MCcľUSƖi.+u6~dV&E ]ShMT'1a0Z櫷пO *q Fh=wld[yE Ak0lVSEDR|O>C5> MHuWP+]un]Mo'0U>ׯAgD+4g^媒y4z\$=iMQ"G*xDc3L`Eʀ(L9W~5Prl6TWk4σT3C^JiEY&qnxxy92m 5kËZ @T^TLP$yzzfG74%b,↢;9EیqQ= GM147%Ֆ\9Bfĩ|Y3 :q2;9+<)Ҕvb7og\zc<ᩐ9K`{)}6?g̈́{QطF5( vBfmvRm!]51oۦ)RL_Yc vO?~AO:.QTcY$,%f"z0ug;Nur.Ĕ>~$c-:XH:9p'nᨻqc$ST0ٱj@|?8*{Iz\9]ͼVk_(MF'P`pd3(cT,"Bi0ЬJ*$_kO_ pS%|W*fh5G( [Rz]6HgsT7`%A.i[rrI*)$ U^Pe.Tz*,VɿT24~lz=sI%扢sW!R!T16U|y4g![&Wێ3N<ţVUI\aXR'Y1+LtBOEBcY418VCvt2SpW}gu#xJmRk]Yo܋(8NjlT3LQ)s5}e$y⇂WHf΍co7Wvث>n@ {6'F\~5`TSI8L0#7a~sh; /mXFy< LQ2[8~N_2F gƈ~g4 BKo74ǧ'/7oQrJgaA"'Mэ1 n'iG袱5X;CGNhFͮFԵlٍ6>q \^OXxu}UUIJ(F&_I_l)-'4b&ூ5nɨxܞ9,*<.NX EX'>-k"Cɧ2ÔXon>JlE_) GWϏW*0Qf\4M"i凟V"c֎zClյV m8ufP(񿣄dSXB9ʘ? W~Q(`"VZY-C?%U1 6rC-?u˜ :Q¦uy)o[9-pGM#CbHDճ˄o,(&5&ʹDi3Y%"Es lǬ!i>uo<jS 9/l'}ލ]_;g#*AxVmU"i`)d!@Gh/-]PMh6:x.!A0yFo* '#jZn)iCj{J%x+^"m\[ѹiFX{{Qz1AB.569]5{fJ;K%iԲQ)6J&-z-zz|Z>S$Dо2}Xl}-DÂ"3 skiuq$+0]g5cBuBl*I+9}y!Aj dhDlNpkjǍ'G 9n/ׅ5;"d?O:#k>a,HP -ߤUbZ zO|~yy)%yxWaH_!Bm m,jVJyBqh>-| {Ɋ"#52ڂ.B"kcuCK)s](k*BTHj1~%HhN%I ngy2# UYkJZ+|;|j1j(喇~r6;QɄI|8' uY\`#7vAWj,BuXR4ƴƩZe?eR6_Bf4rC Zz fEB&ݫF5~3 aIL0i@5]!&؈8+otu oX!v$>lh"sg ȑWʐ?i %9-;"9t~lltyi:z;5]ireScxg/h3@o|CEpbUՊӘgz%G)!wWSH'6~fP.n3.b[.,[5\7Qfo54GbN'kZm9?TǛmBV>}?讶;@gگyc+#am&Mڿtboݵyf&K.w8a.D&,ڜrC $eߝETV*8X],=8pfNEI>tXHDKr8%2z#?h=׺q%nB|ݮUuG8hT.^ N UPGA[>'yJ_/1E/< 4S6SCISF0 gp*ordɻ>i;1a¡V"3-9d8*ur65Y~& uϒ:#W4Iw*C@Ib2e pA heC(nOR¢Pc{r&ҳg*'|In)N3x2+ D2pLzf4OV=Гlq QW59*KBn|^p:o꫺TdhǎwJ((Z=͌0fKhw-ǫe9B/Xp[:-֥2*$S=ms7bj_fs)g.?ts=nCO6nP &9tw=7k[yqO. r:fYl߿f2GYl I :vgG@&Eyސf@Ok)T54|zus7qVYJ;Kzwj&mLr|\ 8wwb;"pƞTDz:M[-|L45U8%bDmMA\AG0hvV]qOJ,L$,FfU>CLt쀡լnɳq6 ~:2&hŪTn`C K \BmB=ˌQH ;3F G7 D,#ij+-PC͈6 "X΀.}<0^ٔT0_ճ\W ATk:qڒKϟM=OW0oXS-ͤD,~diZS1>2c l}梙m>]b12Xw7ܡe&t6SvZtC`sg˴di3#)MK/uL4KπVfv̶,hy+:(g̺ShӦPlmIyOc_U-c3VN_%AJUe!A hp0(;{T5t r.~0`qn}vƘS,IW񛛩β7 OHC2r )_Mvw{j嫫bъE;Ű5.wB+ӊ2~=CȇK~Y>]`GN)`qQ1,*q+:],K1#aO-fڠ-CAQ/2cY\e:Ypc.w݁iAðmUT5;h:umt5v}zZ [3) x٘rXf^N'!ipdVS}eiɧ"PѤdOFkmй _tEH&//Gy<~;pcV5JEk>X65_̚+)p$C <ΜQWL]ݧ[}&#_/$z !ӵ՞VtF?J# u"a2;@JOkKC& 9&Eo0ؤ+'~XӚ.%Ռ|sc >JbmF{Y"I*Q>Ȧ5SNR) ͨSal{A* j1pjgb]VQ(M֜V>þB^9/]-?8AڥS_q!bmQjzc]-M\、=Njv7RI,}\f޽mk2XM۝`xsk{X\fχˡ$\l'AT^Ys~ `*Q#JUrVZWM9% B!d-&?$o e;l[aLErlngtr5Ϧtaԓ|\c%24 }N}"s򾺽13G*wN\A ŌphݺF-,jX͓qo)ӴdMG})"X(bi=:? &fC&6|5Y]^/!Zk{e޿<-Qn3Q 7g o)-OfQlҜ b0VTL#°r+ `b VSdW_ZmuK"<ɢ2 VWprϵnU| ~~߽,W2]CdR_ ܐaMT@nZ}P5HD{G/HF&'ܭI=8R13f̑Me=H]9M:뗦g*I6T hO 4jK7 Mv4 hfx:,c*-DM_b_OQĖ<Jw^sߟi: Ӷ՛×'W+pc9:Ҝqmjϝ{xkb1mB%q__lw3F;E3./Gzr:R? ؖnO ߼yiw;0O޾[;tw}9M':nc[u)ӛH 9e_{xk{8!-w;?ҋ CMh@IDATXJHS3Wc|I*V8\3&sݱEjq/;鐇ow:AIoS,<"Qt$ X?! v߮8 Pa=vVC?4F#+wwfIADkxU?a}%0$36]?%2i$0kPs/ڳH66PLpj|6뤾0ACD45U3"VP0(Lb CGˉR3T[rzq o@*$M>ɮ}/[T$wyJVN%Ur{QӒW7Fh[=ayptp:&~{v_;Tr˯};/2Z9c')l+@baov\Dqª9{LSK93бor+=ɉenB\o$ˉskWTZ9WGßU@hhW߷-߼~gQbr9Y tBnEɧc):f4>tujtlh[@xC& 9G=X׉˩+>*;pxt<ǣdM'Kw:Lm̏B)ޖ5A/$ ΑY[W' 9/M6ZYvf~*r2QE$,$7)I|T?%k[`buhfNAsjs<=%8Z} ;K|#j24?'6 *r$TqB sJ:};a~~_pdq5%_￞_?|zLSD/svPYeٗ~[$TWEsEįӑUm_19$-̧'"zv7 ufП9 9IG+&/wwׅp::xbq5ynv-4gL{!f>}r?OUaS7/~}zvZǺ " "9gAF*i1`Xoٽgv6׬ok_ݜ2XwV2[O<B'; "3{C^낁 Z<_ 9znOXW =Um"p+zK؇\ c%a.5['Xeer)P^lfC˨daJaԎkK@`⋠FJcdCyGmd,]da ٕGrŜ ;!BFO9[3K+?{9TA<&o' "{Dʐe,m( lc OzS^dbD} 2< gQZ.Égq)SyO:ԕ7{"4hI[֎PP/n> 6ok%Q4-ڶEVPuJDwsBߐ k|vyͳVB;Khp;O)|W0ms5OTm٢EzXӆ`*bK\vGh֟||&}%y4ˏb ^vЂGIAZTC=!O>\]\,Οnmvpot}:_jd} ;ߴĮ_S_9kM+ g+-!ĮiNK~9?oō1xBk뛂f$.>'bC"ԊNT:k{Q/57fW'[Fz%$eً@`…"@4bvN=K]?J6f=v>R<̎)<4e/W|Y5 ?R:J Q3~Zr@֦n) *ÈDp#z 4Pwvy]U:#0[IhF$铰磲 KV=w!5?lqR|6#M+BO7(3 oĬ%o7-όWs7R;QF*Wj/6}ifG>*Fm"Zmы rNO~ Zcn\ڰ*ȗ/ZWcKG%hEF+}&UTzM˯I\.JӒI4bsJͼ FWc9/K'~ZM>&)HVmXg2hogۮ|w"%(; eQSxDpmw4pEbx76&օ1fSov_ʩsb~!VLruLR"=k)z )o~OE7 !N;}ۉ)5\ۿ}@ -‰ilIy;ýΖHF.r+EC[x{{.S%u!P+^4Y3JG)S9'Ա}KыɌ=-zZ#gf}YCdECs=d 7ZVyt^ hZ"ܤ^iL1i@X'9 ~ 4tJW'' ':N~8vNW/_]* dL+*''~PzfM\fͷ=QsHtlsL8^8T"A͵w/BbvEmpZy26ȼiK}BḆki~+)OON.l_oo-WZ; o[9A nk$*NW#hrNHЎ=ES>HN7)EcLZ#.bz׺фa:\8>Ζ M_q4rR>qh1w96!$G>mbj~V=+Hۼ,wu%B&T rT?Y'Vb^GEfΦ+hS 'N 2W,L 'p@rfY{ɢ`(W&}^!t\L5W@ˊqVOoWjV‚{o wdbg$ "'.c2"zERpLT>,u~p$/-eU؛}Sgsզ)J$p(Zl=(y:0+OQvc#h)+ }DQv"$[P}fLez!AK?Ky 3fSL͛QפoZyRJaC=[K KZ&]kMp7?F=23nhA1XKo0vdwё#&?v6"%hH&;_Üt>Fu*Zc1 s'$ɊE~"^\TvZAGddgES)훺OY~<&X  l3#äg'և_ُ{ er@,7ӻ[UJw[%s⊢JculyhboO4%F׮WTaJ [KpD͸CG힄p](АA1*=yLɀ/%&If  ,YH ^u`Ay;0lJ&]JTW'|6'ZI4B)Us骓Vo׿\M4sWbB;j(ZO^~Qlrg;) qN0Bcqn2qd=; ~$ZMZ;Ti'!$s3VCE'Q_,DWUqeO' J 顣O?oj"?bB"b@PȎ}hh?ND6Dg(B9IȬl&f=_IH]4ђ6¯ɺfW )ly:Ŷ>/ .S-. 0'wC \L۽Wh2 ɣ9}Grw2ї)KPr|2y}nd_Iˇ{J ˁ![ bD~deL">??+fGK~ui2;87{}ǻ*,] ZegMVxq&Jb{feMлn^ vxb C%%);h[O+ oHi\ X ,jBR-`+S^ַ {,B0AH] 7~N$3?"B6{dX wvy}5@'Y"mfQKuiye9I+PM9JǛUO1yUQu\ 1Q \Ix=8t$y=%AWjsP]6َZ˦:R~J3GDW`՞iRKRRCKJ QI>u8WՒ 4t}-P.i9}_sooJ#+Yec!&HiYXMk`cCw!4xz۲O'~1 ?ȸPg0m)QLx 4&I\拵1 G[R~ů k>;Ff|mF?~Ǜ3k k.[_Nq9y[࣬ݽ]a0Rơ11Lr͂Ne9>u^`ē!ϧ.qH^&=!6i;u;Si5@bzE4sX̢[UBoa6d+/p hi˜*%c 2x gWWp'- *C ~;T*l6A∦|ǁBN %#Cٱ \لKP߬FV !iUQ7LeJoBZp Xȼ>*KKC@ԭ'Y}+C0/ -qyjRg8w?t$-cIN~qB|ӏ'_}O+gk[[;ggD7];M mQGVe[mu=<]]Г3Q:n80 27BL$-bE%Q Z(0 kџ+VT<5"=KYCl,~P#2.'VwijވLO`;W7诟I6<.ݼyq O`j:axq d!UR?$3S-9fvs;^XVj4¯le68i}uGҴ,M=J աC~/Gx;&SP=1i#OLZ8Q{  =_-L ȷ$[ YT䷭ )HRxADB--Ȋ>"3Y2*ԥ$TzР5KG^#U~Ҧu癯%eGb \4ƍ/y҄!r/i$+< u=ީTo`L ȥE`hjR|⓱! [9{-lL1 V) SkC9<4\H84~MR6ccR_"9xvt[~Z(oW'<~U#M5b4ȡ!Du={횰6+Ԙ͵-3~7|ɾ߽};Nb@]z_}B;-*˜0Z[׬܉y~*ۻ/?-Y0vwﮮߟDJ W\Ӊ-v tGk\%w_,eqx/袏s/"?78o(,r6K%J) dm;: /ؔN*)`W7LwSCwews֠1m% p9d&[: *D]i:ssa* ONs_}W/"jрV>U*#}k+ f" xnʴql.ܶ`*6u74,9N-%7,3ClzP $Y)=| 0.$b`rzy;D|EP|fXk"!l:eϦ\taȑЃK%h*&^f+(jQvb.b3} NG*y‘)moצo~ ,"[-QZt(d>p.Y3DQ[tA\o@C$qKeVaM#FeLo*;Z,#( i y4l.}?慘JpFw*f;J/pGʊpD mm@9!'s!ThBS=x='X= OُfT3f/HɤEaGBo:T]>[a#_ddV LE 1m.J1@8g3pךǷ?k *T"C?9V1vo?Y}A 6֑/>$arᰖ]J,[un:lBTŋYi9-]^M?ޞ]^,Z OW7vnm"EsJT՗{{^|R/ZX@)dY" lٛN!D[1=8ҵjEcE$G7MBd^$d`(1fO؀˰4ֶO0~pHx]qtq0l p'ސC YRH0gH&b%n4W*6vJ&?{׷|ґaTBV0;2eOz&$]dP뤑R#e""`z@|PW*ܧVRXRq0U4_nSr2j~OJ|'1^]@m*ffjuGERȊf8ḰT 9"2ƣV0){h4tU)V>)ҡ;;?3xwZjǫHOqΡ\+Duqs&; 1]}xzvz?ǯO/eM~55O6SNG]G+ދV-ӯ7,l$lf h(΁ओ\}œ[vYitKY=Wn"}w;2 z~iSr@‘ [m9Swoŋ_M^<F& ;f[ru2꒧J EGooCoІFYq>DJ h`}ZtDe u[1%<אD *NbA)ri!oʋ*J\U#>-BE4WY'T)nȸ7L vv5TBwn+sdHcÙa}%X%z΢Rn `.x)9"U4uy3:HI37}I˜Z׫C0if˷lRkT$դʔ[yTTGan7z3=Be&heFh4a$ q-T \ >ۊ5> ~nRI0 ~rijŘ{Śa/YZ_켃_QN\E}ˤY͈'bF:R(yN+'?N?XZ?:xmakQ[7}x9rue kkJZsM3x6"'j>,-w ?12d(qz򾵾ؠ\ <*D8`LLX;,% o$ Rf^/FS蟋$f AU *JUV8[8Ef] |4Y)hD&pO 9 @doCC œ KBqƐJ#w|.CIeK-sUצ晊ךyR|~7^Lvb=;2edФq~'3cMZ:)@CrV#F,3$BNxnZTq#{UQW].}94h.-.0MOxtH:~xNؼIsS# WEm>mXJm 3IALSLiX֚ܘ[ )6#QX3%ҡgDSpf:2 sr_2{uHM3}TP,k .eY q 1kF*n Z rΞMfj>%VSu٧!D0ʎǿJ3# 2Z ,㵶Cr`aWO~zs}(O]/>pLGbQ[JUT plwy-I//O6|^51:2w)16:ceaim_>x 6nk,=8ca;vpsv]|i͊UǕtz\e^# m˱x"!4Ic`ݻ^&, ±Ϝ7;d Eb C^O,xS9R*J|&J2d ̷Y]Q*WTZ} d*!I"Ρ"B2b0G^lS)ˊ`pBJmsEwò, m""ہm3av?+9*]r/g]ԑ9P^{G5D s>)+I>;-`]F7EVM-S\g.uR/YXXD+'ߥt|) l!֋]C[Jieggz;s'G$Le(IdmuN%ӉEX qfDar`w azfޒ>T{Bw7Kդķ'[[a>N\%,pǓTTԶ3KVw_Zbo1Co?s l+7q[ 2˜ɒYՌq;UgmfQd؈nrdD OtV008b#K3:.u`&P&r Qd"C4)Miw4.e>О+/}".Op@o4psXMXuEu)27)=ϻ/鑢}O44ݠ/iVpe- ԩ[7LIi~ 8bQ<~^^n+#NBa(m@RNy{B MTZh7ꡕ57'OutfFa^9FNa(<|h4oL~ÿ8 Iu0!IO!k5WX{{'2;F: :5tj5u3TC_*Z.MMqxK8{/߽{7X7%G:dA$H* wN!~b` xe|,ZGn#ڪ~̻Eq,apnkZ%X:ߚVv'SƂ7_ NZsLl̘u{NG#}엥0[;vDq&m6J_"RT92 CKD{ ԚNViL+  RslC(:j+먞N>7凃 X0OV] , zU?5Uٌ=  F4+K<磊fD@#ur <.5gP4W`Sd:ԭGW1z#c>lͽ |kR/e2D Qd3YdjHMפN pdfdnr4.==,rI{B(ͯz^OFIƓw|2IVfZ# 5CrA+5cVve[~B7K A|&jY Éu,]om_;f2-IzKdpF';h{xs??D+]K)e'F:D5UvV~N&ŢHFwd3{}H析R+ )]=]X ?N{4/V0']w9p@PZ1MGB!.A\Xߎ?{2F sz)e}jƆp/1p-淴vatTʒ5\S(IƐj&/+fNu)/gqH}iϴpOd!xKO:sa2 y/kVd4@ ;tv~񝙀/ "5eA.L2\Jj_~3>3VKU$LH$)L}F R@IDAT@쎌v4>}`н1>}ʤZ^jL3ڡ oOգk֍Y ϘG9>ыN[4 غ`P1 >heSÒыQ8vڣaJ >/uщ& %aL%obCAmLNM&& aO&q%Dis>tHnӌ0aBJڇ~yZLR&Xڧ,Bijfrx' *KE܉,> 6n{)0 ~\7$#"4 tgU4PcX ( 2ɌZѠH6u?׳UR 1Ԏj@q^%:2 4H~X|9A_6 vi0oBl؜Be"OHRl~-ೲ n6MX'veasoO1t7о.B^Y滖xDtY~E{?oB}풞8o~z@9 -߿kCB՛ /WZcd ܸs/Ovf7ejhest+̂_hq޼v\h #l?r9̳sҵw,}Nni=t1dlrk-/n:dǒ|jX5tb01gN?zo=~$7޾|}ž<S}Mwnݺ.2/^ܾoFT!yvj"ɫiwo_x̔/]oũ[2gVM].{wZӤ{)tCT Nf")1 (9?#{Fy׎5^916+ߜ9[%=`z,i16I̅uˏ YQbv~@Dz. ]ӣdX_P]"3Zߔꜛj3_!L̦/%*f>.<>^X`|?[gY>n1H6t2MǴ255r##on]K]ksc{僻\rwNU2[wwKNfⰋPu-o[~k:ݜ5ê֊I &m{m(0н blkdFրwAQI+u2Â,昑Vf>7N1f#zVe+lD1skRVHdRh[*> %͹E\'<]ȆΞEe%.5U; vK)9䓸c񳾗& gJcO&"{BW![au V$,^vvOb )UMi^q6٨son acKw'2 Ĵls.?2`h)`78 ˎw*}P՘ 6 喇G7hFR7w;pl8dfq4#d4+_;mPZRN)+ L YÆ>|P&wT^?3q6?XCZgFk04bԋW_8",QPgU%=Aqˢn^0XëfuGQA4Z=si߸zo-w'uW9 GWo}DLܓO!ƿPGWRA-<ؖ~اtM gp\xsL'o_~o5TCUӫ:1Du}fɫF~:W` xP3 cp`*堅_r٧%c4%DZrNtzˆ1"A@HertpNN$7:! 7a)X[Bs ȟ~X!za:C5u(䕩޾Fb+^fZ4'y YtimK~-S(8م* p'u&@+nuVo^wpk/&궏^_cլKws'jHO飧$$֝gwٰ╝1ΓW/IռZWoI'.[;eԑqO12Wwgiu'^`7ט :`Рjk}t v+nŴ!3nXg`4\ 9l_.whH+tಫZӦshx_2b{? ڲfXW_`f^Mx9WE*W&ωH&`ٙ+yaNv ͒910o!U~!/ k_7a`[Xkl Ѷ~"2Jd;WyèU7 ͧ=)|i6$ϱ Rj]t|Ȕċ_^tks ^9vE_ْ 'K8rGmTM/7vѴ/\52L.ūW}yyjI!b3cuQϏ~yw >ASU4Ν"t9b3ȃ&Ko9 znf.-7I?3,h.i!E4uD鸏U4(=ɽU_w\S"k[ wJKeߕt4ܔaK"IPf^Oޤ5'+:ڃg9kӃͳŚ&4Ls)6+Ҍ~)bg< %@ q^F\(\kp6)Y0pP^Kt,Hr3IW-^[ˋ~HY! ZEt鳮*,j^{Mq٬=l!wp a)vdi6v!|KؤX[&'4 GZ3}@ bm-q;|%z۰|4F-7I?/fOU:"[J?A~O gaA~8u%[ i,#6Ǵ[ww`slݺ>]h4ԜJg驹Y 2vN:d\`wM-/̪AzijOqŽ)%?g?_m@F#6R?߁qH9˙^?E_Ύ;A+%P{wh|hf׮|)yՋvoO]R#0Xl4U-ET֒jw 0w@+sZ?1 'IE،5R9S035>X4fI$V",m]B3ew^7N x>bl4i2)dyKh>fh_1 #pR<^A>&"2Jtg3L߿+Q +el;iI3 6Ґ~Kڬ'_[/9 8|PGO / ԗ[յsZqT93 PׁDBDԘ4VrkcU1 VNcÞ7’uέ VƶV6)Ĭw/H(r)Ʉe=`8Y@ь<~\ 㡋,86B]9>?:z4*Ag ӟѓ5D@uܯQ_ә3Fy4ڮR>Ť7~=cLҴ_ghda+l:WQg^va:Q]qVwϷ3OX@M}&4,zco&\kq]ߞ={a8W岉8gT$cM ^wg[tx/L١_ w>h /:ozc*y{_r3ٕ֚œuGoh8}"HC_0\{@\,GŮڬ2 Vq@?h[x ^|J*iR|/! \?w[23t^&yKuNŽ f&K "F+8'_2ʢ4>eI_A:8I TTaf b{T$rBDP=eFEE%I¤6bx;OUc^DiUzA#9C^ mpK|=.L ;,CqDPıGJk԰}Jڠ]&ēB=yUaX&+䩕&t珟I&`L[HuͤJ[)m@7aaph2\%6KobO^?yd 3qnp5+gY~]Pj33kpCD&ϖ}Џbϰ_?| Z,[5ۭ>Uprb.&e.ap-B3j]ep|wϤ:/ۧϧ(<:pC_9 a8x ػ{p I=<jQY&.{͙:>b}޳@O9"?snz<-҉.㍛׸m'߮<4pFmVx~NWCcBx(Ɉ=8ۂr㚛>Ǚ1!N |mW+ͅ^p6VUp`,&3Bwz1=fj)jkoZpȢpC{6X݊oa}+{Yj# ً߿é]LrZ]cA:$54ZQz'bSzWe ){;Y_$c_1؂o0@oL"ȑ-4 ^OcxW| ^Œ6F^3sQKґ)MV&UşV)d5 #K!1cY-ׯH+~oZyEg`pL:m\Ro>68Γ g*.5ZǥRJQnʂ2VIw,J᨝%d^)g/|*C̖e;V:_éyԩUKq-e ~Cz!GqT%6Q$ñ*) d~W{J.2s2cs,Q 䎡9O9Rf=WOZqˢĔor{!|f$ |r-\iϬ @J(.?2.`X{ײPbșZؐ\Yj웶K\5-RwWh<3N;i -[U'_VoP-.鮁nl"b4SI\f ծ\9,K'#j=-;7+S2m`7ܿz\͑ #':Y7ks{YO=P$^USxYalϵT߽u K/_lջdUJHwTKVP_8gtnt_w٢{/[p(5'L"[CjȶŦ2uyXfu2Si($z.B<Z s9e{1Q,]SL #D{`KƟ趰__W>l`]J ?q5\*ELaWBp*%URX\p]Zn1@ڌ) 黖3EfdRfXPؗ XJ!p2z*ܨlS`$mr&k-PC$yM5Z `U̮6QւѿԬgͿv~mGa؏4,.͗# )σoyn-caӟ:6 ) B~% BQQzV+!wԍ8Ww?wN%XOV}3l/=|0ߓk&Tdg=OsW~$!4N=m4bgF:n6n={ף.-b_]tj$IQ|Zv VdRd z~>^s9g42؃k.Ռefe|5 j/k/Wvp%܏ '.klD ֲcn-i4D8E"j-ȏ \<ڡZCu]ze$>FiEx \R4w74kϑcSY 8q+݂*)a᧜bj+/!X`$+YOۺY1Z?&<&}VX2㮅pX%z(S.NL<KlHFSԀ\ٙh< ssv1R6)TX&, I_m*\W:dʻZE>mS31ʑFK#높?q\U8@~SPWa{2}tt݉7'y*n\#IxDm~LUXzW=(h`#-; VYl@o$4$XH G憐[^R LK %SMnCv(PQ6u*ZNͨPfhm/(P$օXUWAH6i,% Pt dtN3wDBT%`JS0a,, k9t&kr6iZQ[M2~ff_nc9`pbGQ˟B9 1{q)ʅb~K3 M;׎tS24qnP!H/}4(2c[0m 4 06~|Ah;k-c~)g8y10fdThe$eaH(Ȃ{qR#YRel1hIʒIu -޶Rqk8N=^=ck1z՛ P2 mP1Lgx7d}]+IP1.U~:ꨰ#q~&tWedn*/?cөqp' Z$%~)CT^@4}K̤FG@ytáݻ7~{ Q,j99$KX6pW0Qj ٬oV#Fu$OuH[X$#Ľmtav+Y@fEpG6C`;f&7l̙e:r//UJЖyvxB;cS5O"-Lk+miej75J>ZW#T?F2֝Mee,Y25V1O%=!}# NUbꤺ73Ռd6m9$&#)9Jg {4 %߮={\DV_ UUѣ+( MJuE·kK \0!Em߆(E詘QdN_YR7D.>)ȇڡOa1O/[?Γ|-;Wrhϔ-ךGڨYthը^ܳyHFs^|qA}I0!9½U̕+$vaHy©DT$;:w5̚I[ ~s-ޡY ~fcHʐ fA)u1ڜmr|l8OT@f9[BϋE?_~ k.I ̝|rjr1|-gq{is.ĻͿsKḯ@CLsLK; ]+=SGrFܼ{yKRfs}b|uqum}fךc 5+i n-gҬc[B6[kM:" ;pCc650}MBFPU%z^ycY1V!Df#]Ot_%TT`*RLiNkY1uj]4a% r;r$-aަ --r Bb#P8"LC3 ڃVb^nbHS3x-"S&,pKIv P|ɶ-MۺY}m@ןzIu 2倯5ؤY"HJ@ݟV=ՖZA,Q-Of.e;Xt䬢!'_C \C syxpϡ٠>Þe)}jp|iQRqnzS_;rvTe)U lef SJnۻňѨhEE"Eز,~) &bsEQu*tz '!M[<~OčJClZz&_˒wTO>S$SJ(2+qtB[a(0vDBEV#t|9.d7n[',܄/>U9@D"6 J5 hFe1(w ĶoYM!םW1Du?8Dž FI"sXI([*3jY"DySPM {DBzݲK=Y(剺J/meQS 琀J!4j1ݥ:)wƞ$p=ws3y❄Bd- (7)U]،,>2*hݨݙYi;W۱caZm#^FU56[c\ތ&} >⪲rVUl[igO8*L'܄@CEW.*{x^-B f&|mU;_]iR-dWfDN}:Wm T>QD ^βufjPB-t=^^B3`G:W+R|u?ǪCƧDz]O?"{\s2 ě䲵 >`;v@!DIC>OeI%Ԡhxg(TS{O mC]p`.7b4;J) Ɯ([74ysr/Nwd?7:{j]<$v}*<T lVRo Dxj1,DTOL/l'ִؗNu3~5Ec=KdI xKCم8=4ӏ.D6;~q?J4W./⤹iب&pblxuʫDɠCobJhAE 5eH&{5WXM`!\Ǒ<DVEs)`*uIJ46z*:ϓ4 &ᨶ6a*wQTc\( `J3}W=Z.ǎ ߸FK`'m3 g$0T8$~?A7@yGŽF$؉q#"Ӣ.V|$1*֌k BOF%K %^q;K5BJ_BsG  5]!.70&'J3 ÿ$~b pwި[jIYl(Wx LUT>MAHP XTd`c1.Bt,=0*`PFGl/CN+Z':ֻv+ 㓐i,łl {@x1 Ouւgs4SU3GƑ|{^ïJ̓HGCj"Vd&ظǏLbӯ ۔ [yWb:x˓[H\ϾTr9_lq`xĄHaHEzxKM31zv88:Y91M7B>8[9a5 QO̱b2BQ֑Vᤋ1:Jf5`bp -\tMH d,.*ᾔ"% j-I.yTe Tub>&X7Kw^xpvħZ$e /o=j9 +# Z)9X{.0'FbA2̂6kLk&ϨI0(pv-$5;TBnTY Ց]2k|-i%\)1N@wUCW\m1Y誰+3uLPa=pQ!8W"NK?uwMv|Ő$%q^?Rgăk[bGQ{7kɈUlBޔ}zP׈d$+FǪsUw~Ȏ_[: [2'?ɥsM}c 4r/š0z|3 o66hɂH(/ѼCD_s83{{~NL?aG~htm:6I0KVvm MդEt1TmkbHHʛ_t) ,2 #DqՃYI2CŰ0qf|)pmf} #1$B;`t&՞d)Iq~UDz&j0VV&<~2DK?eHBG "x-ƟŨoEM<`0; n1f6{V m?Z,lX8ʴ> ]_~ FG׆wTCl"уypoWN)E7A-OCFvr4e3WdͰ2PP֕HHĐ1:s$3t4K%Z%K, d4h*= -7 5^6VBNЖ>}xɱ"!m:Z;2;pyլ!޾'tQ| U! F}q`Յ ل)NPK)HHds#FU@ⱼfFbR!JA SL{JS@c|INj=SV>xL _eOFz׭vrgQSNmi7q$ԅ*-[[w+bcqsȂ|RҒȉO!szL,sM+n#=?w,S-!kϡ1YӃc +f}1Dz&zChUW [T$l1G~&nqt"N&h%-rEbY ܪ P@>)N&bZN8ׯHlJT$aA\azC8:jF!b-"vVC^jV2O__5n% ~QdX(<_|Vzԍ)νGi۷nLEyX}V.\~{_a7*f/^}9S3fɚ§O[V~T)a4G$l芗3bea2ߎrC`ĘTp@򍲩Dr[O͸ H$񆬘A;n]8:4E.M9Gi5NfEw-9nqF-\j(ժX#-_Ԥ_Ln]tvT޹ɇ,] |} S"J!2d&q+Jł[wKkEay\?:T73wj!so;n =?{:nѻ!,[kmƯ #m G|m0gk!Ȓa0M6Em4]esH́%fB? ^ '"]?X \JF}LO#cniK; f+lnjEX tnܼ{|7lZ4E;z`<{ %lnFHEx|1GG92NtsH*}[)NOh`K0Q}=!&$|׳nсӗ9/E@Ȓ#SssdM)ՉNgCiD'&T)8 ߿?"jJ)I'ikv/° E~ NRpM^,=~OX-wŽh5+(gO(rPVZ,`,!>+$Pըa"'B#=d) 6wd*l(sSg& ˲b'U7p}ؿ=fGJ(&uCF $ʔH=˟]LK38c`Sbİ$f`q!ׅeX3\\LHز,dC5|#ū~.5wёQʴ'QdW 1{\b1%LYe G!F*_9Pl0.K3+K^ d,rc$ ]jSPlC쌭T}ԼhQwI1>*\KtAxێn:#ny OLt-DPɾ W`5%-\@U N6=|qNLvUB"2S`SH̳7"KO}Љ-(>&O[kꢈ__ttxt}߾} uZ["JȕDg5?fRq?yNZ\ʌYKcPJvf*/f$U&J# _\R;4Ǎ ^ׂ5<8IɻZxny6ŖuXy`<`-Rv1g#kX+*Q . *) 7RduIw}jhjW NdVXeỹ7}6MTlb1 rt{U8&5: <5TN@tϵ^;3),SHÙ/\(x1N VF,X 8t/1+i0T4淦v\e^̧40ryژCЗK4wNo%O@[ lҮٓ])l)G.OsZ5Dz[YHM+}*)b W>SnK*Q虙)P3WrĆR 5-4S>B!K6iYi`8/WX't}WSsB*w 8 IṫbE$WǘDŽ4q1൝:32oT%^5R#|"ǟܺf5>-j h8uN o4$wT ܴã۷=70mnYe+5h61:lءC(DjВ9 ~x2~_qZ+@0GQ#t&ɗ0f4A$IR^jd|zOA):7T H[Rtw ܿ{']T'K'WJ H2`K`%bgWŵ|Ko޸流O,p JP6S  &E fan$s'b4>&^(֚l Z23%v%OT3L k5V!֊R|OȄ~g {1i-4݇X$1:q0i T W^:N'7KQ%nBz_1=82PRy(K\M]@BLg˿22+L.YU! :|d⦒N"KyViFjLx aK%8ɧEIB'ԻSjhzC;IbU `;yek躡J.^r3)Ԋ6cG钿X8R6m<]:p7>oف굪NG{]߾\O?l3 EхcU6`'pfHM]#Q.SrGE9!Ϟ9jȽn=_\ݙz&%J3|Y vxҥKkTT'c3DA,p \BQŠ\[f`~.s`JeVMы>9XaT#(񻁰CLeoZڦZ%RrWؠ&'<Q3r*/6L&L#gS9So#`=5Y.b%fQ=)B$ FI YLkYWuq{=)| TgC6 71r;r"hD`dd!˒5ڑ1= /`E^3'wAђ"^w^wb^<}?,Y숩dA&06YtY*z:0^+[,i9]*Msd رZ( kCY"%d'z[HM4;)bٞ`j #_/PyN!Yk.wX*Q$ ڼO\$tz;G?XƸ#Z:S+sX#jV%Lֆ_ YaX#$J R-6yx³j[Ƽad-S7J[w<{̱#b㴴qAEC7ss… zA jh= . \~_Pʰ-մPƎyIz oMT;$,,rju0==&' phvLLVvO<]uI-S9f-kmLrǢMbfL  #)aO Uϲ jQan~)x7`7TFPUhjE c0EohsR+AqfR|`No]?V2- W +RLrV ekj?LBC/&ƇϾ{Lf]D!nk1d9mA.JN]{N -s!oAZC( J3^oyŐ/)Ds"HX2:. 2q~YjcJs1XA$wϥl #ЩxDjCD z:^15K^G-FE%=$VQa1+τe )jN,\b>yƘaG5ϡ4z. z5jZ死6FPl!,0rmR2">#`5f d*rc$.џe[ɀhǴ\"bH.^ڞ[+Hwe95cv*yK^&?R&,;ȩѠР hJhYvA4j%4,; ttb Z :Z* :nfIENDB`scikit-image-0.9.3/skimage/data/chessboard_GRAY_U16.tif000066400000000000000000002343561223313777300225450ustar00rootroot00000000000000II*n8222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222P,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,P2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222P,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,P2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222P,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,P2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222P,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,P222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222scikit-image-0.9.3/skimage/data/chessboard_GRAY_U16B.tif000066400000000000000000002343561223313777300226470ustar00rootroot00000000000000MM*n8222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222P,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,P2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222P,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,P2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222P,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,P2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222P,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,2222222222222222222222222222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,PP,222222222222222222222,P222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222scikit-image-0.9.3/skimage/data/chessboard_GRAY_U8.npy000066400000000000000000001162201223313777300224770ustar00rootroot00000000000000NUMPYF{'descr': '|u1', 'fortran_order': False, 'shape': (200, 200), } 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222ӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,2222222222222222222222222222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,P2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222ӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,2222222222222222222222222222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,P2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222ӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,2222222222222222222222222222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,P2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222ӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,2222222222222222222222222222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,PӯP,222222222222222222222,P222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222scikit-image-0.9.3/skimage/data/chessboard_GRAY_U8.npz000066400000000000000000000011221223313777300224720ustar00rootroot00000000000000PK̖K? > arr_0.npy1J@FztQbMSXXIp#Jz 'I: M![ u}sܞu}_]Ea߿ݾu?oۧ?ۗnlR99Og{Nu|ꑸ(t:X BkZ`-t:X E6qMNjG"S@-t:X BkZ`-t8r 3p:tU`U`U`U`U`U`U`U`UؑUpӡCJJJJJJJJjŎ\=:hU:XU:XU:XU:XU:XU:XU:XU:XU+vrftAZ#0s}CZVVVVVVVVV?PK̖K? > arr_0.npyPK7scikit-image-0.9.3/skimage/data/chessboard_RGB.png000066400000000000000000000021471223313777300217530ustar00rootroot00000000000000PNG  IHDRr pHYsHHFk> vpAgJ|IDATx!nhQgeQPiI7eteYP jZy!3R~tAUѯLߍzy~y~y6cyƭ?%X@`d!X@`d!X@`d!X@`d!X@`d!X@`qqZ0 :_|z?omzz{=Ov}Vis˟t|:/?=ϗ|9/?oV4pme+[!X@`d!X@`d!X@`d!X@`d!X@`d!X@~;'lr}lg ӒZ0ONKV7, C 2 , C 2 , C 2 , C 2 , C 2 , C88apZV#\sZVUӒ , C 2 , C 2 , C 2 , C 2 , C 2 , cCNKVn>3iI[V}'%me+[!X@`d!X@`d!X@`d!X@`d!X@`d!X@~i~08-i+[v9-i+[*iI[Vd!X@`d!X@`d!X@`d!X@`d!X@`dΉ!%me+[n\[തle>Ӓ , C 2 , C 2 , C 2 , C 2 , C 2 , c?N4Nk?cln;ǜl㴤le{|2 , C 2 , C 2 , C 2 , C 2 , C 2 , ?82j޹yqIENDB`scikit-image-0.9.3/skimage/data/chessboard_RGB_U8.npy000066400000000000000000003524201223313777300223530ustar00rootroot00000000000000NUMPYF{'descr': '|u1', 'fortran_order': False, 'shape': (200, 200, 3), } 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222ӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPP222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222ӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPP222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222ӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPP222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222ӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPPӯPPP,,,222222222222222222222222222222222222222222222222222222222222222,,,PPP222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222scikit-image-0.9.3/skimage/data/chessboard_RGB_U8.npz000066400000000000000000000027221223313777300223510ustar00rootroot00000000000000PK̖K?5W^ arr_0.npy1n t ( H@$rǂOČS Aa}k;_^xH}wlzs盫?~~z_׿?Y<zv˴,[?g4TWBf UkW5VZB՚Uͼ,$jPf!yU3o5 ɫy+TYH^[jBf UkW5VZB՚Uͼ,$jPf!yU3o5 ɫy+TYH^[jBf UkW5VZB՚Uͼ,$jPf!yU3o5 ɫy+T8˿msO[?CT7Qm:[FQmZg!yU3o5 ɫy+TYH^[jBf UkW5VZB՚Uͼ,$jPf!yU3o5 ɫy+TYH^[jBf UkW5VZB՚Uͼ,$jPf!yU3o5 ɫy+TYH^[jBf UkW5VZBPmjiq &**Jt*] DW*Jt*] DW*Jt*] DW*Jt*] DW*Jt*] DW*J^**ʸji2jU+TU U@Ut**BP] PTEW+TU U@Ut**BP] PTEW+TU U@Ut**BPʭ2nDuwBFJ|Jt*] DW*Jt*] DW*Jt*] DW*Jt*] DW*Jt*] DW*Jt*ʭ2nDu뽷|!DU| U@Ut**BP] PTEW+TU U@Ut**BP] PTEW+TU U@Ut**BP] PT異r6QzGQm*] DW*Jt*] DW*Jt*] DW*Jt*] DW*Jt*] DW*Jt*] 異r6Qz-#_Ȩ6Q**BP] PTEW+TU U@Ut**BP] PTEW+TU U@Ut**BP] PTEW+TUjoPK̖K?5W^ arr_0.npyPK7scikit-image-0.9.3/skimage/data/clock_motion.png000066400000000000000000001626401223313777300216310ustar00rootroot00000000000000PNG  IHDR,ܺ pHYsHHFk> vpAg,0gIDATxTeci$zw;3;]Ubs`T(9afw빙YTJJz='ڝv]Y魬6 G6\5{___X[[X7WGյ*~h0`ykv{Nt;Nݲw5vh6zQ6F^UjZUCZ]*W+ryT^^Z.--/X,JBɾ\/ }Ys >d|.ڗ!g-%Qi|3P,(ߊ}gy{/c{>ſ}l&ڧt*dRT"[,Fgggff&vڹcǎm[m 3G a4VxYb}sc 6Zpm62 gV~];fآe{khIް53Cj61R./Uhe3}E %gjH`={|:xLYb~ Fd';쀿?q͈렐˘`,Φ&t"M"h4LOOMONn۶l {p+={~`1 Y&p ~Okpsy``N2ʹVGI:f٤1CX4{۰Bְ09IZUjrV.5dXbiis]^/Ԣ^xf)x9<, S;lc¿.3+ 1>p5^B.%O[s0lˤ,ɴyJ"OX.bsss33"vر}vs {~zG&VW7 khcu]?M`gkX2"]. i-@h9f Zfz qoVò[dɢ"|dNRa\[g|4+3pl݊Bt{Aeda?)X/ r D59fV /23V:L&,hY؊ۼɜ)۶m曉.^]{t{{G}fٳ?@2wҳBb(0Q453V\A*%Q.="H#$yeyBE XGe\Q9BN_ z0BfZM:i–ŭ2IъRQUIH0LczXo)qbF`+ȸfdpcֳP#]iYT[G0[$EbޅJk[&͇xZm` n&0 uX C?٪>c k,GNf}ANo=Xd)4,|ΰeyVF2KQeࣰS`Q«6|psPoF`bQ ɿ80Ren}2 -d3#%D̊-jEPN[ey}N+,dGUPC [ YbWWH!{G4}7+ VQՀv`6 @`^[)>\Ebȵ5ǚ2uJz* d (E+d"s> _ P#h?ͱE t#u$HV:M,DFЌLbb:xAנ f&ejaX>ÕG0ū~tLm6#Whj X /b2:C׿4;D4rD{ y%T,>|N!k}MisJ,3&,Њ䤏g0YѳCU޺е{%VM2z2: b:"KLEZ0 p`5'(WB_ky5-i?+(9M*Z#GQ_S E9B4ey}vzɝC *p={2~-2DFNbkUE4"0  YrѨ=?10O|4 @^beXrN#@^|7:ϧG "+Pʝ<I&=-%rw,3ʺ1}dC:zCs +Y&D.V=$h1*_YwN B؛/_sWDkg XHCWCT|m+k t.zjA7@{Z|-WVp]􌎐U\"~–X,x*LU7jZ޼K({Fwj=_b^Gk]]N$H$[h y0-vN0a*GLP̢17v3Tl`UcuOb}Y - & KFªR!x'2SHXt4 H!DԅWwE'7NY#(A!-X(!wWi{_gϧ.=v!E0s%7-m~O_lJYЂM9D;~jߝ;&"k­-6ڦ}W,q&2tLҧ==v0 Y1O)f]}j=ӭ;$^a!Phq"2N#EЯ/*x՛+:tU`;f*@sލdsSڳWGZ'DΟ(ЄJKf-Cls4#\ 0izT.wzj 2 HW?^ TK7"h O F}XXla Nq-|Y!,ѥ`TgX^UKuxBe$+HU9Lٴ|!1,A4b+)ه=BFĺЇp ]!]&Ag:# i[N]GkRRuHV h- '˄|%F Y F|Z䲜ebd+&9} ܣ:Av_0ֺzhLKo|.8 z+ I*4bq+D5_H"{5{Û6l x"V;Y!ЋJ~9ħW):U,GjNjXg!@MJuZ0Ě/0g5rQgi B4Ď4SPd}zF7,dÄYKOi$lD}aj9RlxcO}!l8hNY:nwfL60Ro,RkTze`[6UK"gxe9PbQf CY1C=3k /C>w/XhJC٬Y4YY/;l1I*X$H êD,XZ€bAdk6Y\c}Zk[uGOqvW:􃀱:Z[CX/8GCjU"'e(z1./ EAHׇ2'i׳ysƧAyK*A0~zZQ݀]<w:n>TL9Oic欘h쬏vJa,X= }잜Od8S ^.:H8/$oA+fD %bq6%~ьpv4!#a{ o]8I͆hEB<I<9NrV2o%omRIl_4Z֙:2Liuz+bd5L5T`> y)@Vd&EBHCbj!Wg=qc*@)W9=IcAA_IxHĭA ~nabsƦ,O0Q$K)"1]K"l 92;Z-WJmB&dY2QΚBQ{n:@U"8`M&"0M( uGD3)4qО=݀\ jI SuIm'+(򬺳\EE+rO^R !"h|߅{5RZ(4")#'EnQ9&d=Emi˙*" %u-h̪EVYu!ztn#y'-¸aqov؟Zr}c= fMg5˨U*]'^PG~R֫ggạ̄bFԱF sh$<)KPt<@7%h@B*Tdd } -K,YD{хAKˍ)^gt.=L>?F9HEYbɗɈ^9gstW+h![pJ澠e5EnGŬx Cb:F*HZ{D={j(,jRo0|5g DxbE86Շ,U<՝x@[7_)- -7wy2$l/d/W KmM[Dgxc3 yq=A1TSr'-(j~~B@yHX Aid9H_8XLiv=(LAV|"E*.,#GiQlxșTDԾ|>"ɞ'0w1'0enp,2 `q'I2>]gO2x=0Mҏ׼}MpqH0`PI:,Šr~!:!^j;ȶaf !PﲏE٦|;nڡU'~+4Bl&C9V#֐)g2)Iṙ/좆]Ca׮-"O&vLj9X/V~9]CV2 cr:v1 ۽E;\! X6u(c.K'Y$IkT%.T1b@Gς\>0n&*iSRqŵVȣx:՘I2g}J7Z`AAn)V|d֦\d×|NpBP&ƍ>Q,E)0ŊW9u~}E('͚v?gPCCX}h%Wɢwh!B` z e.!\R׬ZV{Ec,ju{thk>)+xII^y̘b#^!  }uST 2Y]aber+֐@X[t^v@EvoսatX-ù _-& V᫺ 7q)KZK! R7j@|͆~Dt.-$ΦrdYOd2fEӔQ1y_*K|ƹIྉX2`idb]Ȇ*@imw ӎu^)c `ƃ⛐Sk4=46Aȋ5RQmK!le!"vr\"uN ;=<}nɕ?9+'Yƴ<"Sf { DEb|5+^GˣMZeY\!kSD5U_1DĒh$ՠ7y yv[AڡSӤl.aΐeR/k4WQ M eH)K()n0Hq(bN[S+,GDS8!JVe\ߨh HAIkDbrFYdlK} G'WTdJV+4ItE.鐕.d"P_XczZ/K mD _.픔I.qQ> C?"|JGRhYkoAeēp j3`c(ug9TN|rtEER$Is1+"C{6\h"Qѯh zrY0Aor Xuby6 ,YqR[m;,-iPX/b1)sec( ܄N'9$2bs:lH*2坛p}%)'N*XVH/1tx9dnfj\] f&X(X:!@dbúlE B7aI7Pl!SZh"%`Z)-t\ eTb KVd(r9>>~Ji9d <* 2iga۫_͆_!Ҝ[˼~Jpy=|ލMMC_Ӷ:1̺>M`h2ix%MXb`-h >BrCDAC*idiI"vε=R|rdGҞ2Ld&DB~[iN^}|Z 01eeLRwE/d'PA֥H ^#=..a̐kpr=vPQXl[4J^ 6hsε FιiX&d"r NM ;0o/Bʧ`)A'ihj:l(}4g^"ZA_@es>3#Lh$}7 Xåt4(qcf@ko +lƅZ;5o]BAǀ1{0"lT$>/O$jSd:lq!Y>{HA3"ྈdT9B^2>&S^jPRJaN9Y<-)@h>w/'e">dN'0OgͻXҘ-n'QޑV}ߩAGN#Q4]h_儐3ۦyӛ󰗠HM; ZnbNE.$zZ2! _ʹ7IҸӧW7#)ltFV!I%,y L.[PjEeY>9se6hFbCvcNX_udE5@ DEBERo;nh֝ԫ .OH(u*nZOB^dEk1RTsU:n䍭d i" Z&bЅD'2 U 989a81naYmb)'";^}dR:<[ϋq:?]Φz YI:gT_2.9.:,ֽ O\\ 98"!\fK:K`R!C"$R$mbBD1BIerV9qyki:ꈴVWܲ$ΥO d 58mY!AE-Mlq*VS^{tGؐFC-W\M•6Xѻ"4Vv r1i%M4?D/et#OZ8y0dΤ f嬤fi'e}q#d\f댖dL2[E{͘*QGClX•Rq=VcjiDEt݆V d9I*KE  #|@XOQːQ@.g68{-I$L:%s`,ΓvZ[:Կ5]x=WsI9: AY L޽{3zj&bVs-}Nb:+].z5jB [Z+Tnsl CtݶJe _ҭ+W6RZrעkI8r9LIT?ҐÒ~$u*)_V@x#TKٱGNԓ/ !4ғ xHbzAy!=? 6\GK< F$)4Cx+e,I,_vdVL8oiTjj%$u3!WJK : 38V~+~x΀Ki6d&IoPnߟS _O9&1(pC> 7lE2Y_\}E1*iITM?ȐŌ)8R坬 UA|l%(|RZY'ܡ:)gS%4hKa;UycݬJR5x'agp'$ >xJ SI,".S IiA(ˉZ +`KAQMmEV"Hwk_jcc"k"Z(>xÖ'I@O\  j5p_ԣ75MwNԄ(rXOv!.5'%8E!FkMe\R LmX݄0sz*%+Mn"C'8 Ax QrWg|†UI&uC؃k )'EqI(E&,+4KbӑIİy Zu(7H!K?fj# Yz\L.R\eN-JTߵD\Kb]Mb2WWIA Lcg0NyRvIq6$ѣkm©5ߌWcrxGi';x͇W ,*\KV2K(suL9E˲W!l %0 kHKً6iS24GJ +x`yXfig\A _|WI(%"Њ3t Z'THkt),ՂJ`s̟8sY)d6d]/rU>g!#?`BM?#\jG0#lST[+ѭk^p5Zrې\mR#fcbJƔي,KrY^M,ckB3٧G+ -"M^2v`iB{xpPҍ_2Ƿ Q]B#:: rE "&AVIl8SY]enF)#J+/CkWk/2݅X)㘯zL%lW;40AJo"zÚA,Nx"J/^qW^NxDuH AI!M.z~-8/CeU؄,WBRUZUX2Zȕ{^êx0F,|VpR</ ,'؃8-TLMi83:nռbjp6}q+Mi ?2h?5,lToXӺ=~*aޥ+`Z'Tiyad7VKwWZ*5;L˜8{BTDL>lkL_#ǐwopmBk[ YHkqE+PH'mhj9D Һ ߺ /r3JaxmFrUv\ZÕNEg5SDĵL\IS. %r*ԍ7-ƣjӱA)J&JL59 Wr{m.ڃo3|!b:mAס]U=pIлUr<9530c{JhCNG91D% 0PXO2wpC5O91 2RK-̫ѡ֨|s)c]$=؝HGzw1 RΥK;3FsaN2~Yg;ҡӈt:7$C:]Ϙˬߤ*i dT:RLidik]aaQ,QR%Z@瘋2L ,i gg[κp Uab7DztBNH!TEŮه)kDxuuJ#N!C[*|6U5\vۖƆ ZBf1ļI JD.2IDZ%&pٴLZ.dBzVWr5\[48c*k>Je5HYe_R_ zg$;#)GM ix7%j:_%*5CʄPYx"µ9 >Y^I7X\KoD㇤sv*ۄ7WX}.|(']!͕ߴw'0tyk/|t *D*Cv{WTDZ8Y0k с*l325b(wLn4v(_,CK$^)T+Z v%+&avD}'V" y$=fgx(QOڕ#]rgF|ơNԉ=a9}tC?[XmONGtͥdQڪ+n%X H%0x+ D t]rI\DN|*ނ[Ecb3XCZwRi$&t8݄_]|an1f>*BSOmYMEsbOlvG`A*{+\%%k"H%W'61j% 5Z"ZsX*i!OU%dnLaeDˬ0Yy٤6O-N4Tv {:'jU "df3VJ//5IgߔKW%2.MrjYky[*Ѳ!W,A},r2PhV[NLXPiBUS6 4{mudz0]8%_1\UOxa0mJ)=2{ׁ]Gsxu3ޡ: 4aِ~7[ ) 9~lYH ivtK3jQo$P8*LDx`½2TUʗAh|`//te1ԼkcxW`׭Z*xԴv"4K.B#Ej++Vv( ];B;i';dRa wCE9c@Ln>=ДrhsUAUv! f]VPXh* UߡR٧!űM)(fl{s -%ڿ2z 4Rܙ,|$=;NENa:-6G+lFi_&JOr. `ӬJ*YUjcU#"}cJG0ĥҢ$`?b.jEU j. FAԁ/EV)u2nRD0vPx^ՑBǕÎm6֞H Z-"LG 7i҃)RPIcRaBXW=NBjAh!W)q(Y]J³:XCZ:irk"ͰPY("jP*'TˡxE$U u$Br3B?3zL/ d‡$t)E.@JI$Cw[1zw)+$1)Q:siAsH`n|᪆8: }\bdhm@ NXTu  Ld1|Ck̾×T|5G"9*~,zqM8 <ɄXo*OxiNЌidSYap>L.$Km~ԊCCN8,rI_RLS$+z4$[1 <"uۙi;ȸNixyz f%K-M ./ڻSk6BԽy:Jdg 0&ЬNN)g@_\x~kE!aUˆ ;86,+SQC K.$LQ.i2_h&5Jd:FX*FKAєӸ$y QV]y(&h# "|F2uP ̚)xK h" WWC֧h-,Χ7Wa*Bs 㪦Tlj.6}JE/$Mu~,_bGS* <1ϙTH#NՑqE51cKMY̐sRkd*'f|ʅOg'x:5KFn$ܝ(P]:ؽ^HMPnIaޔ4 ,j3)[NҲU:4\~Q&)\针ni^)AP([+ۘ24W[=xGPLɄǭrJa_\N q:|$MQ'lt1-aMl7AFas {_U:o 6]B]H.')!V8'TcQ;;X.r;ZD$>-|!8(g>N'A]$Ǹ'w $DJI 59R僔ߛe6-Ii'@bYܝB_F}_[T@$!9$FJxT/'\$ ԡ ă4\; aT(JsmBZ]/BBS(LBWhcQV٪ڐD*TOl!}JJb8o"+'b()1uY:$ND_ՀvxBg}ĉሌEaV+D˞Xב8pxʅGբs6ê_o&}CPuV}muss9дm˖ƿ_?__ofm۶H6m20ĢxHyWua r%|'1bh)U~"%6r}0׬ ttPTܚw@,Q"  q%~)E)1ґrΫ6![bk=PJE_ce)dK3+m۾b_?afO_f~-_oݲ};gghX¡DԲ &XWRU(qP3yB>);Rg$ULu|jU;Oc|; U5ZQ_x ]ɱvC H)J{S(uSWvusn@TufN#ssHS;mߺa5ꫯ7_}mkێ, vG #ĈS2jO9~URCIAJsX[_7d$DdBoWwlbmu }$҉oC%B +ڈVꌅ5]Ŗtw%HEФuCeFk=ggwl߾}7[lj޷ؾsǮ;-ܱ}ۖon曯;n߾cǤ_SH'QDžd?TBqhD=()jNˆ|yX+: aԢmD;.>Z n^vA81PJ{ⶂa jV /jo] |>L2G'pf!08tp+UrXFϥ[of۾}"<gRS4MyNhT1JRgԘ-dmꖨMP0TvBod,+#tA(kB})*]ъZ:qKmZES1iV)*ΨaXCm_/-?-dKVnv:>,{-tO8Q8jR玈՚cF8Nԕ{'$WkkNn!RNw0w W`'O_}Ǐ}~ϟ>{[W/9~QӄI$vޚeɝe@UvIM!ބI?ݗvΎWۜΑ,^jHg5hYAVs>R3H5ʪ6ﹴuAug:xowXEJ"!P^ov{=p;~__~ͳ,n=~daը./ Y sS`]S33Vo-ފk,ݹxҫ┯ qm3rgC"tDԤҤT2ːNVoPfdUNz9)~a;wpuT Z:L<.pNVõzрT80ψTY`Ӟ(HaIV_w79|O-?.;sݫN^)-_hian;GfPBwv&qĹ@N|BY$9&A *8:$̸dX aB.Ce(ֻ ;u!u g{Ph&7CB 9FɘTRat&h7GLE Xs3_S ;ozѳWo~4¿_}>zͫOvߞA]_^.}" ,AO2I(ZՌ8"MwC\d4bOC^qo"=RjCL''k$5uUaQ:<ʲW(oD9x@[js ]~f|>lQu/dǥQ9xxӏ?;?x郻o޸r…O?|pϺeVudb*. >oqk>Bh^;6B]bn ?I kt4+P=nZk:  #\ױ^ 'tom8 .6F4O-55Urh? Qiٓ8"QտN|RX;UE sT:uʍo\vʕkׯ]j%0ޮ]v .;wgϞ>uıGڿ{6,l5+<Ԑs)`/VNo(o:Wnih!CIՔk~i̪$8ZXwX>o{+Vݷ~|ڽ{cݻw;yKv=פ:wUk4INޚƬd=DgOd'q7riNqҢ6fv|O/I+rkT\q:k":¨E5`^GnGEo`! u3OG%Ӑ~w?M5+vWťe.V/tU -'O:mΜ9}셋W\~ν{wn_r쩣YbۂmQ5ɤb]SI4,GnŤ/*oE/M.( Y\I])-JJ#ܰ=`%2HgS7覎tjD:]fOh{a @wT:պBѱ(V">NVJwU Q<{M{у޹usO9rp.T`D27999qnv.v$1^]yLPo3k1 >%ڛ ::P.{;,JׅŠ:PAb}|<$t96/y#ldxXrȉg/^2{ܽgx/?ϞYgs3޾u%s= l-bwm"aZĘ-|#t05J&]7BX<53 i0;!uYWG9R| [nPJBUBơ);kG;}QD(WkV[m=pȱS_|ݻ>zlbFyi ܹuƕϜ<~hس|>B2<`H _a\$seX[Ly(&0ceõ1}*{` МCŇO^@C.Owm07T:Ļ䌙Bk :+ڟt![VVv;` ._~$޼}ӧO?.?so\E*K5J"fiV0p@JYEs?1xcv3RīT&=nuO>|o޼~Ջg޻sK-9H)\̂-4@071WB6qEd"n1:b&=XZO&=Pϋbw%IׄǛ׊G6E,琂kBxQ,npP^뜽gkT5,z+Chle^1`:qW߾s'ϟw?Lѽ{n޼yZgN=dz^UU(ϓODg&47&\BT<Q!/~Z5-e #ٜ`ެ  Bp'CX|'sbHpWzTr@hFu-6 ֚JxNҹ?pURL2R9y]go8X][ܳ Xs&Y)B%Ϟ>zd%pW/?{CYb [%9[Բ3B4;8og~,B.&OXE t8`IPi@lu2/ !I]\  #.j y'I7Y:LQQ&V[5ɩ0Fn+ AS؀^o*EhwzV1=xѓLW\vXye o߼~c^=ɓܽ{ ԾΜ8~=k+ W߭}Xe9pBbg 6G4h5IY?bn0jHy!|BbOta(#B7u: i2h!l)G~\/]Vyvh"ԭ!"ai rm1/u'N rmk?yf%o߽{뗯^x{Vgݹs"f*RqTۣgҚ[<$2Xqՠnʯ(e~߻JCL]*h,\J%͐aqyw:2(ҋ!H)Zw;4)z\S =fk.&%b&x˄R҇ev[yʊhЈ%cNQĺq^։<|d9 ^GOz`}۷oݼqUssO%AihdazvP"h4##M``'['ɰձ/5Ӵy7JKꫛ8YwƉYd 8Nc݃VmDE.gm)d]lź#؎j-Ep *Y딋J^ȼB 6wCG<{KXqw={Ҋ,Vo޼{;u%$D?wݻ{XiZt `ViE%dX™)vƳ6~YK^k}~glI[bl*qϞ"!8pPۚ@/RHOvĩ3Z{[>КB3+|뷯^Ds{w޴~%O9|`^ [þz{'ևZ'0;= #Z/f `r CLq_>,|NI7ŐsyVFȒ>t̢@JN֡ fa6]W%B\n՝d3R W-NK [=chtg{ZeEI"\Tg^| xK'y;kB^@ynݺvվ=|5{g׸P*d2f&#`GgKj'ł5Z҅_ BʏPDްDNPgxz3 PpFj}rNi4%i6 "*RA'qI: ܟN!40/ aϵ.LHgY1L3v,w` 'O>wׯA/4xWo!f@?CbB֭ׯ]r'Cܷx<в"Xl4+-k#p҈Y#PpM|"呞RJ9!I$K U *% )*s><];!bO}Vc4yj\+Yıt[DN>y캙c}{Ri{;{…W޸)l:u3śV1kK3[um#=#Z|&e:v, GP.NJQߐK$ TH-өW]%kK֟׭,|V6wstփ>c>w?|􉵂hA&xswo2 h]8{c6X[ϥf[DA\UO0tb gpa 2ۘsIb^'cO!Q&:z208s&ߎH{ڙ"46uwwAÁ as4>5WcU¢dz)Nn'myT@r KgΞ=ҥKܳSTYJo_xSUn޸y횹ș'2b?dIb)fY "Qf#[DDB}8eN ޔHP*xӝۻH1B*E8 *AL~C!!wum;ކb6>T[R5v[ڭhV6C|es֠EӭȺO"_I,R;f rܯ\t9ߢZn5j=2?k昢A c@Zf'//Sgz09w K}pL"f WEsE_}㦽ݸa9ԩG-ۋ,߬1jGf`sy(Lb""6 ODU|L"9tRQtB5Mf2X*8H5X۞ #C5(*du4Hosy-b$Xf9>x%᱐2;B,-W{c}>A?j3֣;EY7n߻k1'O]%>#Rȋ"md6NvU3H3fvy@][P8gP7:{RHb %WIXx\5*F'q76o#ǎ?yԙx;w7"E0z23[JGܲe\:k/? 1{FkկuHZ$Na%$U1RYtگ!gS)_ەYvKY37CPiA݄`o ;]D4!utSk1~tīDA %VeUf,Ut_U(xϞAe.sf&G,Y_h:+W_z(~O:fQ=?\.`R5;O >ڗvcNٵvKGF4,(2$ YWzbUk#݅CءF+&R|맩޼B3 GNQʼ3π>Pޒj>`zwߞ-h9j>rɩO97wzO*ٓ'h4Bw.׀V|  kPp`%&LeFG~<({-_fy{w=ٳg?zS=zwf˗/_t 3k-h?{qZѱH,4B WH#h*0Fb<V׺ꒂ2 CO9_=S~h1oC1ꌋ7Tdj[u$Ï *ZA]iaMƐOL^2J oo=r1xO>{ŋ.p>rǭ<{Y1~ &yzݽ}Ej]Ǽ5Gߏ$2bY؊=ER,bWQpLfL%ùLr+S {Ĭ}-y&҇izXV"F\e[T]W}u'!s:vrU8]g:FtyKW-jjqYĞZw]I-eY[Ex]K)V;sıoAZ[ڨ=]/XS1dͲ,0d&pQ\"CH pz 0~~5H/:Gr5g΢/ ݄JOOf|{,a'O1--o[n^v<%{йlIb֊rQ70]$+:JJY롙p 5 IQ.P~49/UOp:$٧8qm67x<4QUiUU\-0i XU7I͆~:|؉gXqG-m'QZ} =xo߼{>}wO߿5g޿Gػ:쵛5h @8k~Z 2AҸ##r` L7)o4ЛRIgȧWa¹j!^ՄH4@tz@o;I#/J)Ar3*  :MPݲº& =ru.\v,| \>xxry+_ckw>|O?l&O/I޾3,rV=} <ÕNF R. \dvrfypbUE""D8EBSL|Mtwu{:}9BוdR&t{ի  W};} ȑ[HUV7],UtI*DH(rag#˖Wٳ!k=."r&$(=ߛ;?T?~bA^x6y.wn&f[Bf֊$s Q[PMH` Xvc}ĤSJh 7lOW1~J-}x+/eqmeA\:&+T9@;N<7Δ[Z\Z{9o72xWgϞZa.g/>~~Ѿ/5~O} ?|-%ՓG&ݳNxCffFЊ;BW$ U;EHLr[Q)EVШo,rF:Z TH# Φ~@kԽeqU֐B(';t"NY/K޼~kFΟ?}BVy2i̔90_X#:g!U qk+KA".$aIuSaMf|fv&]Ƭ>Λ! 7Xf Pzej[w yEjF\cYKbU^w~⾽=t Ku! {/9x*YKo?Ǐf,.}W`~/f_y^?}I,CsW/;y={G+p=J1XadFh4A1I J@)2#85bc I1SFAfq PIQmvcS>ZEFPsxnE熩4ʓ: 5^{;y 2ܯ[|S,cýzۏ >ڷ6?|?,xfG7ysK?|pC*K!$E#`Ifvn>Bf+8&%r/KB3uh@p]UUJT`5(h לOE0ZZ=M! &;h UELQkFF=[5=ݷСA!gPIYH?/^aݛW{s/çfKȏ?5%_cI٣{ֈX~ء{1Xo-d-.2šiP (|d^9҇վ_t C!7%!:(q!N ]RA&%nRv,F: q"l2 hE '<;pGj- g(FeJT.1YVN#˪^K{ٳ#'N9wK@Pe=<ŋgO-{Xg fʬa B}{`W_-fYo=D.9y:F_]湋,4s3f( <+bj=/8Yep%R~.)%9:/$G5]#! MHLeOVgmBApݶ}tɐwHbm98UYj-S_u!쳤~ٳDO4{ܻO񠽽z~ _?Ak?@g<{ҳvϦ?wu,r9!S֙CΣxxTdpÌulWyfD)L%+E?$)=z삸L*P׆ݪ$tO$p4Fٽw߷A9+׮޼uF'yn g8PKYwA3~ן~d޼nC&c]z߮[so,{ʚ,4-#^%/Jnl:G4ha'ΉWJi2!.uu!lB F ID&؂n6R.YUPe%sx Fv_.V7-ܻ'Nbrc7{lBdϞ[?OX?3*-;,~-/<$ 'YcH!ZǬ hpC /x B\N}&{"<+ܹH8ۄJpg2%QvpQR TH}5uMPZt"ך3HAU&^]./N˪B]f"Ν={[hC6qDz+hOOF2G!6ތ#lV4<-kUr^iҩx<:?>ZCZUq?DEXo, qHu ]8,y&$G;+~ٓ۞X&9B*J/\)gR 06r$d6`xn<}e,޺w'ix;<{=ڛ <>Og|GoP |[7,?Ja!TQeMUA^9d~^Cy"C47"($w9yM_C H琵M.*WB#]ԡU󙺨mh!D)\=ï2faV[^ydtHW[>_سi+W޽𱵅BxG3Z|?>z>Zy&VNC{K k 6wy`Yk^Y[^,@q3f2|Uf-`7a]WzBjHf+KFSTrЯ^pVEҐ_i[_0d}կH,B!Ix #CS76\AN^"W,^":Ƽ^EZk?[/foc%vN9*c0Az\49*A\H:iHy1Lb֘aflxq0Kĉ|ᾨkKcMQD"4Pbz-ı yKcFts?Y d0"T۝={6LfB=<|"~Wk5~-#9fgϞ<{ 42O>}Fn\vR̲ay,#3Fyv 1\"Z zB$+ӵR7.DisƩ)JsebePBhvTh%@}6*Y˪yE/G˞@"dalK 8,j}jc`gs澃ZuEk d1v<]Pݹ}S{n2Յ>w}X3tHdn}yTWV2^Ҋ4Od@NCim,א$b)lt=4k&xsKRn-)>2BWXhH ^;\#oI-U(ԭ[!h#=:zԙ r|{_2@B_͚?Zxnȝ<0TG3-^<{#n ) k@ bBZ? ",KԓD2.>MH?$AcCrwT:ܮVDKBoG˹Y\]LKYRo;bXD٘qHvZbBӅdIDAT,%Kz2Z };At3=y*%U?֝?[sA$@>~mbU(lѴ/?sؑvzN.AvM#LGзFYAZI|9 )qUf^ `Tڠҝ :gTZTrβiRZ7Y*~`X.{e] p.Mj C h08s5"ׁdY25@1eEH9~_~`rܵdqʵ+v /A$4ZpҩX {z*3:0WzDKx㠝ўtbρ i'yPL}aCf<nw0+u6]G;~҈zR ,Z(NPE`97xʢ6a5[D^,އXw2`">}Ͽ;Dĭ_~OPj= ( /^ps_QYC7s r 33ńgY"ʨn{Cq0r2~ýf.5N,Sq3ؠOv[`V8Etק(ɤm΀48rEJgSDv [%.z-bD W9Sg_B~ϟ?Xز/?}UV/ r+/@3Ν9{gN:}$,`m Wڍr k ɜ-WǾt@ ( !(/2k?MbuQ,C667yx aBC~;DRd_LZv9)\v'L|Ţ TH13YZ gϷN>%=ZY>Xpe믘yXZAsul={4ՖO>yǎ&A]+/Y崀K8dLYжGG J{R  g&;:nN;h*ׂ2fCu:\|zيtzXfqER?~JB}d* ZV6'Z95љfTfևkRM($Y7/|le>o^={K,{e1ѣG` Hk۷^k^Q?*%Ӻo.TOF8WEyZрhq4fl!Kt.)zl2U!dYg&(/JC Er.mqZ. @*LU2/f}8֒q/T5 ,r,!\|uwO82|Wo}?,]nf{t޽}ޭ O>u#ǎ؇G>ݫ<#?굛uqR (LD,vD`E!A12h:& I0' !V@a WK"")7ҡ_9E}cqK`[A֊۞KH~T|eo_߉ӧ7/]?}{Í}kuךR"" 5Dy@$ccYYjB$uKUFqEq6oC/#BE ךag8%IF-hixRp ָCx;5Z,Kz lˌ="V@{%/_7}}ÇWO?{˱z,< -eu 漰k.1㷥0?\֬G-дdcAU c;Df$=쩴Y7 d6|ې#?#ъcZ$|+.*ކsԭ%e3pDk :g[qZܒ X@Rp Zwҗj( :)ND qPQs&],HO?|,ˊݻ ]bs~>ܷ atP.Ydu$RQ.x~%_Ďԋ\K&?k<־Vwo hWJHχ`G~ab({e*L$%TI!݄ԬRA=n=uΜHO?YPC5fG=>{۳1Z s MG=fp 8֬ y 6ey Hc"ʟԛB.,Z)~.mPzu1oENJ*w)7dmNDԎ}iªu&e8 z\upNY;$rڭTy/,CL@xųO>x>Ν&@w^6܀0DI8ȋdQ=gwM$(K$qƫyenE,3ԩƠ|9e h6yː{^nXd"/Gk/ZqhъTtEl %"C]C~YQ&~N:lMaEɣ'lI>`V1. >l.[ׯ,##$]piZY*2Ip&u3}X Ey6N {#J4.LJiP8JZt k fRbģ1eq "($]^Dh2+-aEZ-U Љd-N F\$/Yr-\+cC,~`y e4^}C) k_oܸvcGjs]jPe .o7`z]<89v^DA]PcHA9O` uq|J:'9pXHFʩ! 1K&#=\i6L'V@g!Rݢ2KoHJz rN?}9Uַ[GTWo߁w?`nsH߿sڕKO?znP\a u"P$a57;7;mʾq-n+ǍȼG!1gia*pt/\ERqg123(;e7(KC(v4Ȉbf2liLE*TY!-4ٍHN{995)1|-nnS|kIssCH^ÂwߛI>D@Nxf@Ks,[,qHY_NWF@E .;;$i1Z%=\<(24n=XjIC~BR%Hif$Elq]&ľ0Ѫ^-͘VذВ/讹xZL֕yԿ|)/!nU# !v+ޜьI$րmzz! Dd1G,6NJz鋔N1F:9g؃5eL'r{XdKnC `&qI!Np@ustROʞϑ4J.θo{ܫ3ml?<-\qD m K}'ɫWP/9a)'D"TB1$.~8mLNx'fxcBG,69QH .Ix"CÔuzkgu{בFԩmRP'+\8ڎ.u%3c~}KLU~FSKDxEXb1ٗmYWCCM=.!&Koeܻ !?~F F$Xȹrc+=uWxΞI`Q>'0vxi 5^ޖE[r2MA*W [*.o}#.^ÇO^<'O?liض}9K/3ٿת$CM kEB@qfjf*Sc`!2J:d lMBd]K{ܓa@(jb1kxYdD)Lį}-tx K.Jd9OڗPYo,DyV3EH Wuou}sރ:v'/_yzA w?BLag?kI⹓Ǿ=ǚARYRX&О,isK4¸%TCAkx(4<f!Jqc?+P6A?:40̋H$. :Kd5Z%AWLf YΚ0'P"՞ەk7>yb bv޽zB9?r[1 wX)0Wqc*)3d֒0$l I_N&HLnr_5))$t)rkBlHD+(}Ia)`+茡oCA }%CĥcYGiQPVն֑ŬEzi5wpbs}L$]yǏ_Ep.ǏY+'?Xzºǻ]<{ÇEm4,aWqCf4{ TěPY?!/(sbN=L#08^"M$%C0ApW)2䬊^c˫NB<ᐆB#f542t\"U׀v~uX#lv|?޷#8{kZ%xo߽ -?{k ;/y{k=z;X TX^%l8g!k!U6bY '-3GϹEbn_tIri>"]%^P5RȢg_u$u(NKQ9:sp^k-y!U'aBZE+:(i&ؿr-ܸuSo?`w!XGn^t,#4B.G͈W 3!ޥ8F+DuPfͻD& &wJmFR3g.NQRNAC&^!= t 3'6D@N5Wvhߖ޲6Ex_T[Rb%\k~E܈.[joR}kZ&oaū]GF~ׯ_?,r `}C3v3rE"VkM )/QoIҀv9zjw-bR_XMXa*U+( W yIYT{@jEzfIYe YINqMuaWBi}NKK5 o|:ؒ*NiC0wi8y7X_TAZ&Egސgpms^RΞxL%ChX{u?{C"ZjR!Nc_[fvl߾sfzsoe;𮝶/$!K?5|BxEed};Ι77HqX#S[CIgH'١S7:utBQ 6 Eg8Yd@+X*ذKKtG.k \j}{{wI셞5 ϞS֕cGu% >y pΧ̱c۷s|aa,gkNUS1}֘lBqT=Ɯ Ƥc@7(鰮.~0peE,xW츦\KD ܗ{EX.;Ĕ6Ynha `\dQ|:!KP-=~cG:@2"&-2筫aPA"Y];;mݶݼ:33QX#dzjVߑ?X&P~26s (ŝֽ\  lEt] Jn24.\ZFc :~OTҶtBLoy5 z_8Gn LQƻ QJ95\> V6{x SO&Y[} %FuLAٴu H0aرc۶- s<tlʢz8\قH:6|U2$%m3b5 g5*4 5BQQmuؤE^C"p}sJ(r͋E-sj^t#|Ɯ p1k։Px o Ǐn  Jn޺emsgI^^,䰭{LY]e|[mCGc iݒoBI0Py #G`/;$D=IOg%$*)S䭑9M; #J4*&S\~HlR,R5\|Rv:k^qaI,[O!+8mض=vWߺsXopGe/_|!)Ξ7iwߡ#%X6d^yui\$~Ӈq N;gcmTK-qL`j0l{9B@~gy ԫ.$䝪hp)$u}|B!۟IݠQ!'ht5/,}(AZ\PT)^Y/k\rX:v"I Pildi*WB5=5 XR4h<=9ޫ]¾K&Mꎋ+'\%]E@(EI-ȀCbWq9a[͚9I~'\ܺqKϞ8hS_.擖m1@:e7_eێ;/%ͩ<ue.(> ^Z 9.eoxʻ IRjc'YQ[N-\q#3,0აyg % :Ke)b+ETWEu,R@oRMS=}ݸu.ܹsǁnZGҰ|ͥA݅|ׯ6؁ Wbfq!8 PN %FbndA?a}cB%'ى/ *䉐Fq?Z%&Jz%UX qPDY-&m`B-Q%M q+gAwMYfv|B\Q \l2|ay\4$?y x nܸ}7n\`c#ܱm_kyi "Q<[X&Hsba% #d2 rј2b6֩ٔ//(|M/!zcuBoCWJ'br^v^wpC Z~ xO$k&srFug$r/в\blÅ_|~VkG{<"hRԗ.?udJMnW_}7[n[cS4Q4M9_d2nh0$+Jk79Fޱ!UUcT)b]\sm:$ Nxͅ:\U>t:v9 SBҋnY Bb*X?1U_Pmeat&}:ރ~>&L.^AƁ{PQ>44"˪+B5KڒS`VꁒUI'{b[QsA)XA!H~s9:dY A@p\#3^KjTpҢ;!/__mٶ*]tsp F#gNq<#6]LQʶ~sR!9RiT% >KuVYZN۪0ƷWХ_[x[XUN0kC$-NeNأ#9#},ʳ⇒7$YnhEÒ@[p7bvo7oob=Hq=B5*w2*q,#,&e|j+(.?pؔ\!ncojMxu7G@X[lu"u]u1{Ud}^v)?>NEVQʾ J9I&<+π?kg\k|f!3VZڎ9m3uC* /ZojiԼWgg9RQ,ռYiVfTƷtEb1quC$C@&=mms:ErC8.\&e`-d (x1 Ԫw8K!%"7[۷l׿/Qmٺu;wE y}娮G\^S؊]=?7?XI1gp-J5!wRwJ+^jqzUֿ5VH8Xҝm- DpS)[$i5(аQN͡S}|W*4Ev%`b^Sqo$md?]zЙE|ͯwsqBj!aVE{]jB|TFk$\,=4Ɖ]hrN.3gp3Gܓ I8yCSqsGEB8EТfQ"ѱd<ꬭĹN~ߠx #5햐EbyRoχSBhI269BHZW%ϫar0U HڏMϟnO`a6mb".d|R /)7Ce;O3uM]nFx0qB"`ٱ2*òtBE&N`UjMl`>G>"[BE,(ΈU6=&fβIZP/!~aIֽI'`>Pb)o,ƌQ4Kh U&ˡ9 OjD1e1 ͏(ryPjPiF n6cigءGo4 *œRe+Րdx7mOHom|8G`oH=yTl$ 8tQ8 9 8ˁe>ˢ 2 h-H;u(K󭀬ѩ@S D::'z԰,C\AgPqEygr]넑9+Dz$;'m}k7?!?5)Ψr l'e\W02:q $ E9JI8 _6D0K=:Ң,@l0=/dsz7GaCtJc,I5\! hgGp]_|'@#Yww=e$εnW}źO,Rn:J5EMpaJyTF!]B): -@r"B1 nDk݀ȢJ#hҋKBLHJ Y YZ"U6 7fm!5 QVKp|^9,r"ĹND~/MJI[l|S p:$e{Yr6E4]/EKBVۯ}6t8O!ZjiᲟD@uU^"z0/7 $8XOX+=_w>5&T 6EAֶ VL 3}xxރ̘uUPGaf3sИ}CBgvp4">*nT3Q i0%]Aðf\53:pMu(dc 0 Pa1iu}C]ө6iH CW&x+.-Ϙ> ,K90*@ΘΒ#g T g[Js,q ws˹Z~AFca.7D&+TOh D| @ƤN) rL uNVYn dǻ6f!F"T%m X@Q#^V}[QBL8$t|!KBx)= R~qIkf-DƓA=t?g1AJcN_ĄdifH -eW bVto#jQJߗ SV%:< y.R dKߧA0K,D-|Aae似J$eD\}'<os416 0ZgfZgє;y=D*,KsnyZMVR֞Yk;^k;Z3]P6S ut^lBMA>NWIO)8 [{u2ߡ(IRꋾw%rYypG1'BeSy#ԑ0٤qxfĀKfp%6ŸR{IY8p CZV1yyb;I7$LiMU;^Zud^d 6,,$u@Y\$_qb(븎t*:W5tDк'qR~ȗ|YZ)=Ѯqiq({{:AVF!1a/݂)]-04,rpܟht$><⋅jBJF܈.\w SS\'| QIyf!/~8s|3L pԞfR4\VB5D,@)K2’J%UK![Q$of9-׆wIZtřdUy}J u)fÒ5PQ xIc|dٙ }C'2by  Xh"D_"*׳\$Pg*x(ū B=/ u )xB%<|oYQeNŹ"gڭ;y*B;G-%LHmNT|=Ap,$H  +Z+a Q\ls$QL 猠 "D PHq:8 &Ar3jPfcrYXaafgHZ--R1,.h0 'pdVx"[9>XfuA:(zJV'H|NE\߯>wٴRXP"f"RL%yqr @Xces4 t {|]' QWKM(q.Is֊Ux30yObՖm+(w]"ڡ&#b4.Q9D}B}C%^JprJ˶r_ &eemu\ Be^J'DD!-EU171'ݚf}F倮*]Ѧ$ pUiβyh4h ìSL:{Afr0֬ƭ(=#])\XV(bV3s?1>-K 3pٟMWD>M϶Hwu.m./;l\..j٠ȉ b^jK/GI RZC_,&Pʋooj:.cv}=6˺>Ef ,f7V؜DJJk:%}CZN?,WxpA<3C5Fd|]J&O1tts[Wn);J6uH) ps)osqMК;О6rwh"M‡o^wHb+-cn.a1Gߘ5AA5CG86,x:0 k쇌׼ 5ř* ݡxXjœuAC wtD]51KRuƢAEwJI^<(rb?Ԝ#dH$$: $֙d'ĽrQJnFiqÜG)qerLzS%~,y5B fs;qFɀ0*d.7} aW:FԱ~䅊67 ; C ,lFs'Z~V&,y>̆\ ~s0pahERIVkJs UYJLw6)Ff2Y ;Mda?0YG /Zy߆5܄v1<6!O$=[Ftl{L!.8. $G2,J:h$2n?O)?Jq"ҕ\VܜP{J$ .<;ϱU/qB`x 7ffB_2Y^cYp\_ܟh!ŽA$є#@ap>`Њ!S%a]qe,@ 5ۇZt;-,R~KןW4$diETBC튺gKEbFc^]98Aͱ,z |cR`+YYlfV54azZQ wNK\Ǩ$4A+%Ic2bR H][/D]m{#5iVQ[g鋾)U2"\Y:[ 5x͋惉$FʲHw5x؃+/s0:+%+ M3~ޞ25x>u1l`=,|gA0Fb+Z"ID@DrBD+]s#Ɛ=uG{Ssa5UW=^v5MALx9A/34GVx;EZ$>݄O?.NsaFB|޻kSh=(Bwx~ -v&x`pZ]C9ћwNGr2=Db@Kp%W]ѱ.hqC;LA@ U&H'dТyg~&`-  W6B؂dXf4_A:*ooDܙxKNwp֗f WfǴ >#ȳPjz>*, IB*N֤_]K̔dWEO'VwћMBY|s)ScMYP+2QAːE]j,8"CE/Qit-(&j{~ ur'w ΁l09C^n X OȌ9^]+#RqRE"0_Tt1T_+6~$/ty[$)Yqdsvo ]r8=(1XE'crbmn !%p6|d'dJĚ`(Y8O.Z*|wҭ h)193I3x~fvjvz6^16Rqv, $k5($=$'|}7{>+\)mSDbLЛiuʽMo UM!:E.{2ܑ*i&!>$'Z{FLXX,0+uDB'dSh5=%pbӤ1s8)9ICMp S}=&(:J?`H%y'DN01J4b4.:7n i$WW@W!$'(ө4۲507o"$y&6d$zRuK٤梽1oWABGYqxBsSz5ؤiV=\m!=rz~Y2"Qnj|wwUEz ncXrlӛ^dW լE-Eߘ裨ż C{8LP)Dډ ZyUB G2>9ٌ,Eb@@9 w]@qpP?L cGq#O;qY%w]D!N\TX7Bw(HФ?VtfѢF/oB{gcŀ*IZH^bqyb)lE1s☀ې%S+'] Zeh> KXXz` 4cS_^sHN}QvMd G$4UKX7 ˫m $pd:x.OO5ZkӍn?ͥ[4ES.bC&&dU& u[Na7H,+-d3().QD4IsBZ\'!1aJykaJ֘Vyt=Eqɯi]fTi Y6 ϊ.\0dƣ#QOĻ10Ɍ]$.XʗFT_nS#y,DHyVQSBxηAA%y,Z 9&)9݋izZJ^t|mJ Cӧyap F(#zjS4Q7 r(l(h^kTPPF]Id0T39vЇ{Wtȏz:m<ۀyu8,T EXN&{tiY?&s?j*=4gr]ėq& ŀKm8#ZCzR`H9e?+M1Ŷ~zV5+̸`T*AYrڞ Ó~t7 :>W<^K|w@% ݶvyO4ѣPA0FU,A׍Renh2GNFð06ԆtMkR%K,p|aNy p24䬝vsR8Vk箝Kڷ]2)E;6/]*/dE"_vGF` 2rj=);Jo -ZАC!Wu.*p]ҵI"Ai-`]\7@9̞W-W 1(ۂy[mBޥ1Ŝ*jLB;=vTL;$ρ`R$;IAnjQE!`ј sl 8+F_X>,Bݽ:Kj6t @Lj5k`I<Mpvief` +nז$``*ŜtxхиC_4Wg| VSzTb+N_SiBf O ER_ͨm7nKŔ4dX<'-:Ⰲ-vz)q:B Zԭ۰ƦBQ؃,-qDI>p4T_Ɋ O;^Nns.9cԊB2BHaj4;?TSL(iwCEIi)+$<_I'4!qcW]\IWJb #etZN&9\>sX|YuhCZrцEs "|!'DxXyuόsg#GY5 xTu}BdNKܹc}GYXOT%V ҺN-2]7F|2I&d9B+:㽍4zWנ\R:z:uMo7TT7nPZ55CI$B&G*<Vй=! tvfS By[T G&Nb.\U{U8Nd+rg}}nV9%9=Q1dat(~iBgn{9{ q,T~PTdf]FewM .)M P:DxfwY|IOE#Ѥ'@!(jm!+C1y6yuA:K\^oiB:ղ_p@}\Ž'~'A,)%:sܳdVg]\" i K4(q 02-1X"6N؄>O~vZbՎt X:hP#횔&:o!0.Dp . </AO ykG ̄)WfirLѪ])WX]qnmBη donrf<"Zk4X))Kgb~wƚѿ!sNF*a{}޾v~=h];uI]688i3$H1S7_(e@N~'ߗT_G {VwưIC=$j|GY},U @8ՆTIlR2RPrFk_swsx9$]K,)A.E\ޕ!N qaL;+%`mJn߰}j; #C= bY& >v:$j<7e]ѷE9ظ?2V8@v'os ) n'DҖ8x$zЫS|> }]ѫlW"GERFW0&%g@@UW;r |vd]i|m0q@ `q`L (%ጂ"q^ RIOV xXPNi͓띾RňcMQMAZCoz&ۢtSHoIt^by<W4냜 J/q5T8b=)0JH8Tx[*aτޅS 9qCt*VnDZ!}6tTqQJEZRU&("B+8kT -_RV͋0-\wxɰG+y67Ŗ[c]042ڛI2#M QXhiaLp~37 xiLh昏/L(T|kxwYw~o5‰:SU{߽_zL D]6#CHeb$u$Չ}J+f+Mg}q;̰C؆y[u_>ͼc0dwd:d;Yli(8nO"Bs:cHD| nORˉ:m2$ۺXWVVQb&@aIB(עl%*S}dGu#H: dGX/DƲ$DnUng#)W ~3lkl$u|~yVLxՓLWJWCʞ:>=`,aF!+5^M) _,rN]B+83J<$.94c2ѓPyUo<\j*Æs`XR-%[J$ј0G,K2@W aI{%ɍķX@teμ'9ѸuM;5Bz kVxvwm'$NӜ5q%(bd="H)d4!%$\N:F-yՀ4(!`QqᾧC"3xME(I*K>Jp<@/LϨQrL1daB+-TOp UTVf\_`߶DAOwqJgik#CDi1ЬWZBwF>$[P&NذWhؒ2w6*s4Ο[Aƴ_op6$ -PpK֜xp6K7Y6_b:1G):a29M2L%ѡؽmv$X)d|i;1~nbuCY-|j,kߗE.Aw3`ũ:Jrvç؊ޘz-0EYS/7"{K1b 댚Mf}ѶǗλvJ^+VEJr딵Q4 YT~֚ 4w /^mgwe ,f°2~_x{n@hMu:/Dŝ ,5*dKx(%*qqsl~AW0P)KHzxFVDgV4Q9!R̪m EQQ}ƪݔJ pz(V>м0 j_x m@n+>8G eACڤQ1A!LԿ(8\Ў ~a&OjXap|΀d:Vf|};_{hpΚiWqeR7h&sxGk lXukW:[dc8R9y]R!,1eMA_+M`ʫUWH\'Q}"ELA0"913C̒OjBPe x\.I˃yK3H*z1u׷TlpW9/=} G uY ._hԯ/hA"Oqwg>w{p 8a8p̣>FIQbefX!ei8l*0\׍GNLk|t%x$VnLLpኩI1)zKDrAJ(8-uzd5,/? |4m,6Ƴ/rpYœM\f3@)Og~2Z8qxM|S (5H١"E9BRu^JbW(L#"D;M%UU^FlSF!33ֲM'Bc]E^N6x"i,,2M7 oQopDo>‰MTVev`jsCZ.VK=;s7 I#=b(%wB؂ezVS 6 ıavx[NKe -C  Hyhav*}P,uErdIYWrNq8+{d@ՃAi8A&~P٣(C/ANp%%HO^yc>WTC3bhM*5$-f8ɤ͌yɕN "B+ya3>%q*FXJbk݀"QEέ]ӏ7ˈڽš56q^n(d宛̄BVc6A0RʉP 92t;(J*넦 wHF()ݥw]Ņ0NB66]eꙗyjG&Fs7yӤ 'x<`iS_jMJar~#l *tD.qiK [7}ܜY:xt&"ǎGK5|AJy:L0r:"=P0ԗayW]F)%*Rk=p0<`5A䂪ֵ}e i=Yu:^%qBwևv)J)] կuӱ|,=<#nBXrݼLBYDFz2捐Ռd=Ud;&Y&$4/ۑOJ5$ЄjFX~iN?myH ~]̽w=8/ DaI*yJ}5Epu36)ɽUL9|${>b|ǫK70Q:Jo PoyGyT*&+ܥG\Dfї!א_Nj(i@vM؊+[-*#Գ.^-5-^ kt~%tEXtdate:create2010-09-14T23:28:12+02:00ͼ%tEXtdate:modify2010-09-14T23:28:12+02:00`uIENDB`scikit-image-0.9.3/skimage/data/coffee.png000066400000000000000000016174221223313777300204040ustar00rootroot00000000000000PNG  IHDRXW pHYs+tIME"=n IDATx^d$WvGn44I 4L鯗dH4#QcKUf< D*3#{s^/'Au\z8΃ kUU^|S~UꪾF?wGy^ROok= _r=.A]m]W+_/c:3|!jxe +\Լ1IW{iPߴrPM*4_,Yt>ϧ;fXK3l4ߎQ]q5j.n0a}tyb/p>#>s빻\w|0W|lo~ Ɠq}>c/LWu3mףn0̮iv2j?n7p9w\r^I5njg{Ꞷpp0wקq?LSfqm7ԗtwr]u5NMu֗ׯ淫c>],nXz8"aҜӰ:mOáxE)=؍uT h܌چ:a8<.ʓ6vѲ'|v].M3;w:ת1GiQuۻxsH2!5cQͯXuw>#uCtxF"G^]j0b5W\:bDXEȆC$wHoH c lȍjhx Q Jx9ݞGsE1twMvGgYf'<#8:xO.CwOIctkVAy:pWvhnK5l툹e|YAe{%02*>T{ f׻R|<ϣT Q l0W[`fyU0vv`K KwAq67fGh 'k} yx俙6p.'dۅ=+_.j8xm.< /@Us=6bY l֋U1!!^}vS,fZ ַ+ &Y# ˢ*\Uk䕻\O,F?|aDnp9[7!آO8D?\q2ًJ*b'- F|"gutgoe;f+zrKQԿ_.+j0:aw@4ؕcnQ|LǑe>GV)[2Y=x7ҎXnF\twlܴu9l,yٮM3ӹCű_Gc/vew)b3$tx:jhy^epӎeG;]f٤A=b'HBS'/ձ;_j*5(Kvi{FtPn˵iQiu>yKd7:Qlhzfz193Xwtx(#p&HppKӐ|H"nj?Momb c"HϢm%xe!]z+&a2rc AE8¾',.aW.[gf#{5Xpܷ7CձյšveSu8f-atPT8&A7'٢9Wdli#6t;{dAO8\Ohd~Կ<ؼaЃX# P05mN"-2ĒKnٜ+a`?x`bXR?o{~ 1{`m覺wFG<}X''^t8 op̷{ipvVG4Kdj#sVBی+>񙉟2LvJVROPAP3|Fޱ7 76T]u)f*AZRKN7ЍfLKL^,eyɿ#el]F$ċ\Vf)wa7㧅`N5\^~iK7An?(>dtc21lgL|bq$鄷< dp#nشl2Bv2jg!lµE {@Qj&hXTC;ZbY6n_u` @!'quDŽ^/ wOܘwĬq>!< ۛٗ_=͆hZqI̖w2Wӹmw3:*ڊ5u!WOv v ɸH\v4fCeA(cz6 <"ǁDҙD,x=pqb} P 4Ȋs`Dߠ}lc $ **tFA'jmxSgpN&!\ѼٚF^LV[]C,8-i&NK `B/t:΀16v0W=^Pf tLB!YPmb/G`M]C! 4+f9ˌPM QJ 2Y'Bcui2'cL@H⎢"00dujysc3+d'z֡"d#VHga+f^q,:s׈?e:XnWd8b⾡pfqwO&و t3Z*ce\aEVn<VE=:1cc|M)vj7C&-WPC.Ue2#|CfIDt[ V/?NefEOIћ+E⟨"Z#զkfd}ޢxڑ u3ތ7l8 Ll6)Ch*~"yks9 I'R|Ɩ:F"T62EH>sHBz&(a6t%mj lX;|ޜHO(~G ,IQœ)Ӊ?s4&Wl8ٶmue vϗr ZG ;] "8&msp806&~'ERHGcd[M ♨y,1oǺ1S"h8krKZ"M&ru]@< PbX:l9U9x,%5ig1h-_p2iO"_"Fd 2X !&`7!D4mB2(ԁ2n1%k/zԹqHk\ux;/H~H|)24bћdIš$=tL֐ ,#.rF}Qqlp0%V2,'.0 e"6~jEssDWtL .:B- Ȥ ˛I{1M>:ѡlqW SFOR|L s4F %^rg# (Dq53H8^PbAOGN3K-n;_NH7i`c{bHz[R#E}\E$rӕtJ0_M4{MBx%6'Z_j0b{UKjՏGi,*2&J~kNtFD|<zIۓmYcw5y!)ʎJp\'W3L̊%XS+g_L7= <QJBU7~d|@qV+v%IAAwtCWt{#5iI_eߚPj/O{a08r5D*98xi`20Tn.m*9}vAﯛ9e@q l wP2x"?\8MeF6dz"e;8U$^On\ uϗ4НxYilc} 8L -!(!ߛj-#߅}&t.}L8$ /BB^Ҫhbȟ@X2ZX$Xhj2Ciʦg, h,-i"%:_S']2:=dd8W@A/g%J )'k;Lz f&2d Fw/S;\Z@RD!p0bOC@P  1ыOސ!C]^VG4Q %j<\6&u0aOi7IuUELd+7R^{rR%6 t82t9mƫ#mGf4&UQ0 䕹 f}3L h,rY.>BxHI4OR|vfݪS<:IF@7g9x!?$M*CGbx}H1LG#^A*. OJUn@!Ȓ$ -b'$q1Q[Beq]U?:dIx XvM0p9Mb M"Tt^K4k4Qj%ߜl>ĴvPvTY.N@qv$֘jA16=M//2(T!JE)dhXbR6m3֏^!$pSc1_eb~ cL AUPys -HQxPP6nx1PL2>0w0Y2 OBW/iA=f>llRhN"VXȫ謃9<4j7F'`̦g2[@tXLOk, xFS<9Huur +ᒺ/ )Z7~O*Z9gI5g?* @1K?)[c0+J A^%1D IDAT xl~{^c9]&UӫB }FD K¯,PP3BrXGh.Õ-NL L9F,Yǔ!g <jϼw[bM21e|$P׃ͧ+X DM!/^1B~w0BW&WHtiR~~1Y2vhYo 6RuUm{:~s7 ~n߽Z&f}>lfPp?mVT`t~=;i  Ue*jK6(q!W7`KK ]WG+"=#Imqju>驪AyZ9``,2F+ Y,WÌ4$e5匉vC]8B(=x.x'`e԰`QFda(RQPMnPbƤv9:h&DYpgYY‘̙T >!\"kf6 S2W2 r99 p MWXCǿ.>XO&  u3Tƚ]$`RI\A)JvXiKшtYDBȮuNхX'!Gk|2U)VcV!0TFs;"c]wb g7ӕMh>ZT-.Pn@^yFBD\HSV1)&#1α AT֥$D)]:H +Z^uYLA+MTgn'aa(gcHB}t'v%͓ΈƒcȀ ҂UA 'a@Hk."&P,ʒcA.kbl~]3P߂ Pʲ0$JQ]&-燯 -AF)^*Y2cM>N5lḳ@-NL\{PMeʙN#C<('< T8d LT]DfX엻_"+Ola)Z0JެdLrk4;5$X5 M^:h^{X}U|Y__.uk-O Ia?>&́Q|;Rp&&kl:6{Ο@&p#r(m]H`yٯDfUЀKMo,a!S/!Jw  ^ݍ.; aX h%EUxuݯpHwY.`35ı"*ɆuEo0QtAhh*̇hJahߺ%Ge2nO޴RPg@c"F,j) H2Қ>'KP|\ 8An>5 *Du)91R*n%LYa vJ r&1FEE9CQ(L%\]K]yfl/0A(3=@΁I)>Hw q̥L+dѳٟ6p3yAtwsSc:(nnR Xȷhr$|B!?jzX0v?Pե0u&>4A+w C@b9RT["u,QCma!0_~]]uH~+˕HSz"(zTk7zFi|EbjZ trYЇXbqi>X5UbՎ? F2c0Fra"VmsD5wV! 8b_!,ς FK@Oʼ8)m$"~( <叡-߫bys ڊ5\hUy~ 7FUwE` A߬1DlMY^LX|(-̟쥼g)oЫ@bn3}TFe۽@W N kL2->3G%.фB}8.lgjYnfQ F,:|:B^Rb,džHja%}E{Q;ͬW߱aWX3lػ)('Zhm;Ưp58jGWVJÓ: RMЌ/Ȁh+^H v+Teya"YF&,2r}G+ \$uS:zs&sS81_1H%O=fh[ʸQ!]5 nW`n!p鷻G ]CN((MEfuF2N Ʃ0x9c2uT=T1(}~qۛT:氹R87OE?C2rNaBIyh:ʸ1Ҧ?IfCڞ-1]E#@6v BbrU;$e0^'n`nhXe!4[dS ,0fNw| ʌt4!8sq" >.ܸG~[ZW aʧVlY5ʅ7vBXP4q1zšT"NtJq { 岿`,&)4!LU?[VE<ɠ qC˲)ZQ2(%T+4P,ƋEtߕ7$:^h MVT9IFG2$ Odj1@Tz z+(v5+np^}z;궽Taא\z>mHZh y$#v ߾i3lGOO(هfYnhݫ6?~h66֐QbN[[Dn|VQιx#\\Wue.D~=כ# FL# N(=N`3C¢8TzR?.2b \Sdlrm*-7A JZفoבfø^cZH3 P'Ȥ^rsla%EhK{\!|i#lh h\HHFK{$FRF E_I}>Ƅch\nOS_͈am'e ltU{| k@Bt4/)do9Soco, 8`o;AӼh+9 Ӕ4-26r;E~AwM-uw-#b B%$lMl00vM1*5Xii0klj&X*\؀d%h8a8ҢBl ?1z67:>a`JgmtY/5}] TlZj$O5 ȴB=*5­3!blhH-pz IEQR`5E^@;L;B\4 @.I~qcnK_kD2zH: DW[;33^e hx֑ޤz抬hlLT;Db>Z|*fJ\Ro+6/4W&S{11)IԆKpSz+‡<jҵ 3Ȱ,+Q,mW ŚB9o]!UdDzKO]L?DȒuҪȒB']\ظN2(UOoZ^o@Aw .@RHbazœִiy/n4]>WPLj5*Lp3u>><>߾=o>VO<Y ΂JI+l[T0PcL5*IgGD#i,#1$۝gc.F1ը#J\l{5{Rc`_/hfj’ f;=^իM}q#q*1uqo5#ءm-s4X?sq#phŢL-PR6䒔سęƒ0ᦊ<*3id[vU!V,/HwPiQ)@Ù!|JQ7SL(yۘGV1D< H1[J ^Nr25ĴXS-$•:d B}_<w9.v}{Pbʰu _2Zk]RFb^~,Q|1p5mޜcB+H bWo> s* gE4qfdR[AZ=;N鸫 ,eyχ{(jQU|kJK`ZQ> \WEs9c![m;xO틇dpȪD=M?{VҫjOɎo2ihQ$$-(ZKsX'~?#sER$[)T F/kN+d5ƵuҌ2}Y}x?apԐxԑaE7uTJDm4 ?!`0j U̒mIyJ )H\܁!q~T^8ΰ[C {\f>I غ%y40$c4Dr{,ƿ 7L4/%a(N!<2"XZ cVI2kV4w(䮫9=YpbXh!3Urc Ī} ESoz001TV)x{Kh%K\'G%(ͥb.tM G'F(\pQڴ:nIP}JƀJ Iīhr`b~yx/7*V,O?Wxj{ 9g(*P]\Pcʀ{@ZxzooòNst E񔳣řЏ-uO͠X||tG[ h*o(3onfen;LtX.0h㏿TJtRHI(ƽ& .Rrj#F|nЦV{䅛FfYkϿoHe<=~{u 6-8xǦaʠ0- H x8]b{`gGe29K)Hdı1F: =%4WoP+a0vR ]1eCqI'J龛%y=ZNŠ-qꀇKqBJWٓUp,A-Ʀbzh)((vYE,s _,$SLS?2؆FPtGs[fq Dj_5bJdbwB% mBHj.>_`4,^!<;+#4 ݧdtA6 ɊZ֖;}l5Bq3?Rnhp))\V|vI7rJў$Q'@B,LH0k$J+X}T~Y*^"e$9l%f.uK1.uF KcczX@LإT!ֱ*I7NōC/Ke6]cn.\bXDhy錊qiD P[b,aL Ȫk&;>#JtٴnWv!raEݚS@C[{+W?ݸ:>}0zi!{% IDAT>_F|5NP/Z9nYnKװM.گX!ͫtB10葥v6Ԣ)Sy|,-S,h(Xڞ-@pk{ C:F[zp;Ov Fc&H!K8:BIw3ij(6s2o&t$ Ig3V@4M3f:< i ۚ,4@ k?LMbiC Em-2q8r@a62BC͎͆oy'A;9RN+hxPeqƍMHqO`rU/ݷ1nKU[ Vp&2ť3)^-fƹ ⣯@]Syv%Q+ .qAMH>\eck\+hdC D1B(U4.t'0ٔ*3< X =:%UCMsav&&qC2q?"q;YS4բK,A :N,㑓*j;0K'S@qm"0Цh9c9WXJӃxܢR)9hbF.sIL܊۶=X+/Cڿ6?gDiOsD+ $<ׯČP)J:>N>^(Ȉe+}K-"P*$Eڀ\'E٨rQ5mqlw f CRI)MX.тX61ዥt&Sks ʬr.SdhlE^<}j&$DJ-fe#ӫQKP'"v^^y\XG/"#*Q{Z%IPYԦQ ~Rq(> OkL鮑(dC_k, ل0^:-/G.:7e/ |[p^lePR>HeBSw$A ŏ'M4:k6Qf2fjR~:m/)ڎCj4a/eU"S}{ԳpNurh6EvA4[DؚG7£{䤾,O,*i:ͫ՛Wۛ o MǘpdFnc,rt{`o{Aaqow?p<e5*pMRR˘7cֻ+):94>ӒM Ǵ U|C^2=(Ջ*󓸶ߎnZxIQSY_?i,ѝx7 R]'2!p'լn13KPY>XgI4K4~O3\#jMD(B'XĒ.6V5F6wОgb>=&;eE f`sef0(̎u{=ϨRI8klĬ鳔V(n ^5d 2|JedQ >y}xzv~c``D|"B)qP_V?x._^dVJZ{<{Zmuiwͺ-F'#)%UgtJz $gCӆm 29[6$hdMp$sKHyT[HXֆ&Prac=Ag+"!EVDSEy u(ep%)kOmFr= $'lqP.}Uȓ4忚@[C8"8MY 3ÊjPnZ1 mr͌:4j_d;ߣ |V: C'6TI_22Z dXbH3 V[R0LjQ(camJUUP$}eG6^'bB7!h_L `n`Ѻ̕h¢k`%U[4:vmnPfAobrQMXPӿ=HUkMkQPKdƤ,Mƹ}C/}Qsq`ӳięF۾]mQh+2mܛCy{j!Ӂ3* A;}0;57* Xx)>̢u^u`7ys(bqMm*@3y-CIV2nF$}00Qhc(xl9JF҇ B){]g+-vadg&4IE|^Nj>͛ӻ%C BpZj`'pz# Oo'j˻_PW=~h~z u'ǡcop U|~ ~A|"*T4|U{&Clu c1CJL9Q3|<;.NV~V8b6)T&5b;sb^K\?4̴~^|śͭO)'ɭ,Y%ޡԔj?Ȥ {PR7~5램<l^?/| hB'gn~ʦh5:q0\[. A>{Iֽ$ OsnCR `(3̚=x̀4F`^.*R@"%&Zs"YRc w)X&R%U PfV4'™[ 9&l)h5pv䖔-L]hVֱaOThsr0zHNc?^`Li7_g1?-4pNjBrb)pQ6] $ę +W EI9He?H}p=PX<1PIⓛ_Λ+0N$%tnn&+:)Zj@}yBsP29=mAѣ .IԖEA= 9[/i'_ׇ%oO=Mxx" *jSD?@C9nw EѤ9|p2IHy1CZlq;%7ɜإEv"K}U 3ƁTڑp`・t>1!<a36eG) /_OaKp^}կٗ_5),!Nbpv7 @P4,@@a0/tݤV?5{y0EZ$EسJ2UG} =NFf?fԽ'sG3xKLzAd*~R)iS  pni}eU }`v\lʪb`6 mHΉ,nڔ=1@w=ל.C5(OJq 6*됳yT>DZ}v/IeQA ٲFc0N 1, ca(u|Hț4e6ԓbn^ !E"SWaĒaX49&of9LH-v~LOȩ+y&.9 -NL[90F[P9(UOdJEYplcbX`8mbOcU8/X{/35IzГ'j΋)=$ygzD$+u æ(Sjqm` hqв.p9M4]9CѢ#R)TJي6ÄJzZ Oߍmz4(Y—o?q@ Q)=ng$~)ɉH)q-0PXrvˏ`7x)RT myg naf4ʃ 걳f 9 lOqm+Yz UM dԔl۷jN:/n A#b*jGjoI^e{s7Gp2lR'/޿ʃ6t^@8oxz~X-[ڻ_|99mϰI^{t6\)_)Md:[`Zi6oxgL @' U՛#0.7S !R6PVC>2Oyl,8׺j/''rӂ^TS=ҁVj_/{P|Ag5_w_ݵ!ۤ ޞ/Ώ#MOdÒ~1*۰*R]@`Tʰh$3dbw0"d \xyvpz~=s{WV \ s!koƈEhc- ,3d o01P1&i8VPQa4A_aBjtG1G1$@xY jI;M,gm:''R"+ DT).L\`M@<$&Qa_)L-Yʜ>X莱vcYx*a"@B('H## B:l"(q6D? i *a1 QutS n)2n \5C[M |(`;QPY<3vFvgOށj_7U d-y[?~nۻ7M1̞t[@niۊ&_L @d)~˻?ٱ,Q ^o :e8))5˗,tAo{X"c=T xA{1 W4HǶ%;*%IR齀+u7 @յ&!y6=׳8kp=kp'a 1sLOuaͫá~ \h$3O/P)[7nRGJhnc"jhi`hT&=Oflez_BrR|ޒYӸƃ'aoSZxaY̦|K}#(+{mh[:Foౝ-}BYBGDPPYO^QMfr[flqQC%@h`9bV@$8wW嶺hA KMB$wR?TIRCI%_\,gdo<@"M:L{?X;CPRQ6AAdm&}7{wsÇw?0e8B(bBaQ:E&=Y֝ lcSbmUPAN(C:~k22\ij(',$壼IrEKgZH$,QV뉈LA3Jt$MH7'-Y)l)"vB'BC!`A@b%4)8"5T6i5~7C.6O)Z§!E{O%&up2Z{Z8ekhAyϝӒ1U-P{B`fc{2y41/.P82' CB8A|OLe_lZZ)-4(aȚ+TRjaR בVbbi^˭0%eRXA2|0qRҿ_f"'êpi&@tbA! Ag*v dwqfKj0)$^X/R+ߞt<,q[Ѩ kLc?GF {J 0o& wз %$i,7PgH7upcoaqW)ˤ!xq~;<^{ԦK3WV`4+iӖ>bw81(U#)-?g`$CLe޳Tt34!dqm4(eW1D nP< i <ׅ zp)qCl .GӏxYa )?tϤϠxRx~uak[ nf QOD\/G~R-ZLMɭ썀sn w8)ʲX$(dwy?.hŋm!mύYA!E*(JiA!e{s׵ W<*,UQ+F;NonMoaǗЋfӋ ק,Y,q<tf_Y~J_~A?AMEwn:XZG\=dH5sL '%MϿ<{qpv~Ja!n]Y/~~ DjaY3{d1E߿T%WJاɮ ;J$RlL8(H$ׄl-~ vV퇧o":'E\DY#-#V8Ӕrի% F@uQoϖ [(ǻ2f #dͪ#T$ ?H{x8PvU4#IJwmύ_1zl?Yy1{/ ]z#`2e?+,.KjR67w( ehm@Y=0nT&E!LJ~UwĔvP>."qSYc D`~1Eh8}Ph޺"n1KU.~a]X;XB.{ʴ6>:Y hų-0!9{fLCqp*O5&)VyfٰS)J["JM eioFnGyG8e$$/4`ic .P&1dx{|,䎵3 a^©b==Էz>Knc}I=Mkq:*',j}_␸ʍ~>>* 8jT(Ųv 6y|)Uk 2Z.! Q%G "L` GzZv;nݫ7sy^.MXB$nA[H%qm >%zs/oV3xr)I=c(C`9/` j;<8o{yZNm.AoT(U;ZQ .e 63a|0XहgW=We>=Iܶ=ݾk=-/ }Rؤa>V mLaP\֣ 5_|?O_ߴ˙RIĠ}]qh_U >ьS7DJ(0?iE,?MNWaTtTzxjptv徂bRl ƻغ ru z [\or=?/2<Ɓ:˹f b=,|`q,හ~O X3C@:gPxFe))rg4C?p# ibV$d常AcDz Kp$+&=0,Q]ox.s'\x _Yhja&jtt٩r8x Dݦԍp: \F1+8̇2!xb8ғ(0ư8TAiܞ2 vt(Z2N>/4?0{Zn8z%#Y\\M KKqbzK,"}h"J ޘx4dnWb*%$@d$jͱqTX/_z5˞ϛį<@x4y7P,UJ5|ǒ}rGlڎ-rxH+w7pN듘_\V[]nx״ۦSg: |\Fə&!0a`x4嬿\/v$ *H'DqL+?L۫W+d? +]I?\דivW}fe6c.`Z0h QA"gJ׺P !BR("K,.;mʤJyY*ϼ1ysvy,TK ḌsZvLV#8k1o^tXzIVp/hLJ2Z~rVNnǾ4O/tnWK*:C[|cry<^0[KwyZ'??dGd)j_ɪ1SlITP3EtVfEs_=QЙp ћ`ҭtJL_}=FpXPdaV9x7zr@`z;+ˇHC;]nTGL?g~%[o)PgX Ù.24J#*0!LZK-(> I,l9?n7= i/_oz``BK  ,Cs1j"ɰڳlzqgIlѦ#XC{s5Vۻ{z-~\Ϭ5a9 в?O64BU523 lT!%UV3ihzqM)b)d9`u.o>9 aĜA0:E?u46}wڨ7pV ]m$ܤ?ϾxDj߲+ցB2^x:QMᴔD3%xG]lesT%X%Mf ~%`c UE#a9nr*0j ldAByW+7{R$|k;sMIP\ GxEٚGBW*+ e I<` / "Ah?L<.it\c-u(񉝭ϩXtǑ} ;L͝ecaqjOIe9G Y54b gjz*Ы v. PUBC0Ee=ReۢvA+F C\}(בY >#ݰ bva-Yԏ[kVS hFY4$=<->~jY3`_IїS׸vِɂw PDRujLl]7W]pcE!nOIO"m[[ C&1zjw0-`!!D%ܭny0ڴFts\D\yT4$xXˡV8"7L'Mb(G7aٖn” PG&8ya4g锈 /Xo 5f:2τ[9Rf)e>KY=M]j"M@(@R+_;c[iN{C :AhFb_:0Ŀ;rlZLi;rn0ÁO3IbhZ:Th}snas4TȊ`Ţl9@lR7.H͙vOx@1 I8;Ve,-ta0q,ۼB8-t ½^-@Da|C+εR2>U[KA|6ͯ-w=x)`نxۉ* PʐT͂ (#-%*rQ{7t2gςQ-"SA|^"mD]Va"4+#† `Kw%Qj7 ٞnn뷤m!oxE;-b;ѣyeaX>s*ut̨=.$2HU7dbƽHˠ-WXUNW6Ӕyl%oho~<_[{]zGOy]z,kZ3aB:8pyj  LGW~].@0VZ2 Ȋ'b%g_"=hbDIaz̑$2R$q&AV1Ϻ>-.[xA 5PT^Yi7xsjG/* nUpQ?1UBk\Da[c|~Mjg'h!$zPi 1aZQavoVmj2^9CŧSUA#M#{BBpYh߭nf<47!/0C}4M/7 d--jhuT- JB`)17ɶ:^[̏Sam nǔ#d0``ȡZq~t:1#U.oq5pt: 8HhG(/bCqͺ.S X4tH)[@9vV?aM[L5˄p WeB]J2, t@6ïR_)J(>jZ 祦3 8 (f 7OֺcD Pap>6l_;BΑ~9zJ[C]v1<%Yka9_WƧۘenL&,)fb-oP=56KbstC!RfqPG;=- K[AHq=% ,\)TExdJSh ڱ` P,DU'O/F_2o.(r90rX`{ِU?^0)H4S \uJ(ȀBSLo /y'U fpi7W$~ٮ7(`^!)= FL D׾i:.0PfQp1l5,h@d|<Ʀ_|}g.3gOSyO:'0@-’9u,t8{·nv,c= ;_{5Ǜd! [=Ӧp2 (KQo{jn1(cA@̕w[Q 9dNI}׼+ n73B>a=d+q$G0S6 gԏ2d.{]-%Ss}:bYÿG߫/OzOa/R}VUyftyD|;c VIXnv=LeN:};BuZS4^Po;W'FK (?Sk*Ǟ0!@NAATlNQ  VH+263ȩ#8{ >GiB[."'=B h!w!i"K9+qWX 9Way8Qx d:!.&WXhdɏN~btqf_Of'3l`;pn+ɜw 욷-dYHgXH{8=`f;{ ܦ&/fe(*ZU6v)zMw H8N DXc(K`y,b<|#?9k>,#c?[ν>/p8-e?Q<7XSI( T^?9E7WR249e_мZUY&`;H$WlV{"q7u2%~00^,9`8 IDAT84gs+M1v?C9>:m{ #a.h[*ňi)P򥉢+b}vCid:[jgB&ЭSY٢rw>Pb;ޝ@@%TSԝ>TpS(`( \ sHd7skI,S0zF"ڀ0xͯ}k8Ͱ泷 3NIVDlY}( b*z,R"ft BpcSl{՟_D Րbu mRu+S(kԃf.ve?0@yzt.]+7Q;:eA}su`Bph/w>6Ld]ȡtʃrܦ;6pui&PFD_I+*$iii6XCxr/%ÔA%I33hv zU,%tV[:neI lfk.̪x0D$͐Ad<$ppqFYdFKs ;2X\wPblUˊ(݄ @)d;dʢ?RL{{M {k2_33͇&訨2rY}Dك:3AP,%2, 7'=]}$>˙JR<7_вߴPzpÔ%^QQ:.o䖳z @X aY -\CnD$Fuƙsq=?t'CUYP 5Z<kN- m&?fo$ԬPYS&tIy_2)I~쐖Rxa\23̬-;Vd"0SN+1 #,W%+lԒ{^ج@Qsìz ŨA֚+ShF[FJȰTO7׫0GiZA"'+\%ܶd~;󷌞PP%4g+48#QXCu-S0qd9K= \rx4dt얓Stz)wlkL69mR%JT\0FE[֖]=i,=)*j$3ΚԤ{̦qZUǓLb7sڴ-X A&GESz8F;y^"\'joY`1 Nvp}Ntsʠ#aI F[b7x".24` 1[S>hxOҐPHkC}tI^d h|o^-oq2NR4!'$|&7#a|z&9Z ,d|V]bYy`a<֊z` \\$0"0Ʋ6S]WDX2ޗ>6ھ2Dblzzp8&PyUMѤPq&6b5Szf n%Ĭ )0"Mx)ơ/#/ܺK8Cɴ]pa,]xbbVy"͢P|UKfhY)C0(?ya~g$ #pz WL􇘥x2b2 c*&[kq_a*RxU:5`vtz>>[9_ebev9HIʠZޙ兆TA9NXWSfLKoXv(Mt zB%FgJQ} JA4[l>8?7幠G:WIjY#nL3Ѥ>Oա՜:z53tfNX 3[,7zKYL:㗌Uq+w2U52+®r9$`U*X"2)?pAN4554?dq2d c?q%i2 an _HT v`8߀RՏk-Tcq6Y/o_;neꀝo+LW;t ڷ%k6)SEGO&kH[KJxmz}d$|̱9 {(Pg2%DžH6yVKH? gP!oleol Qz+Fa,ƒ HpF_'v 3yH畊 `zb,MhEEpukI(LȊWCʲXKo3j#0ՇдQ6G~Rv!$JEI%_4 y2Eu"9nuyʊ:\E]DdR1U "@p|!S *4y9u>lp-0^ӥs ׫bIW #cN;:oF)UDKUٷqqj*TN]bWwίD K_`R%Klp7Q:d?DH5+d/%N.X0xAG+U%-_g=M[&/J/g;+W^*?!@n/L?u=}߰4!Z`j"L πN߾JYx. |" bg}oA!< ;x ʬ!ys"{@F2=pxD[ϷmЕ<4G\g.` 46X㏿tؾ>]ךgX/Z6\{*r( ºU@D$uΓ Pa9?_Y&L0KLj " N{P ?Ka&px,%+ʴ bTp# f]KPFvȓT2RȵBB&֨WRK['A]o2G;2~ܕEqnȣNJn% Q;9с W M'=[~;ooM?$BmVL] 1&#=o'Yէ#S iITp0] G,6xi8Ajԃ)qxeD劂(Bn6BkNQN Ѭ=nbtI25-0`{,fa G cĔw8'xbǝE@_*ԕ:xIki!Bm>,z3iVF˳n!FG\/ESQNlfD8tb1AtYU]FVN'Zj(I_-S7Ow (%K Um0AMVf7k:(c O mt1 ΢$*W2x^J_ZuLѫ7fq\" <.Kff 11Y_-dnT0Ϫ Vx稅Z[.¸dF`_~u:eoLf\ՙb.˓-N[߻hW^N+hEeMDIP[.Qk4X/7+[,ٕ;ؠnB$*E;l FBm_ HGqh";&;YsC:>WŎ f߿nCdn(kŮPlbXڔzS. }6UVrY?D\2y8 3bJc=e! ŃLwJS+Y }r[yX{"& oYV`aswJrRBt +kgw\%DbZӜH-w0c(:c/O4oOX$tWnm#}Z bBO =h4Cl'hw>_?y!Y~p fquZCLT ybw;s^Ph#[j)m; t #G7QE dE0, }=w֔ 33i7v $9AUY-zOBiTeAX& >g\!Z?kO{Y#R ,XB6 FݲӔCPDgjkM^P)^-% zNfP1yz jְa@EZ<(pGX.!]bڄ#J2)d<ŭ͊q# DqUrLPC@Ksd\esi;1V2۶.w΢2l^?C5-PSu2<mvq!1Vl|x=&{F@cyytaOfKsGXyU_&Dgh{6Z_ \7!<5KeJѥx烋*i_1DMЕ* d8Iy9#Ӻ1X*G4#;ONQu7%N]vg2aGJx穟tkf!'6AF>ZE֡~v~ n20-k!> DVNSBtl*ܣqgz <9lw~Y¾?c=aZ;idA~5f3֔"B%>(aRN) b<G_X4lH\:VA3bTǘ/뱌pʺ==Rz},ZNX쿇vj\Ks{ӗ.7ivPD,r<&5uP q 4P?e_~,F"lR5V6xiCyel9-6;*qed;KV@%w3֙"ExMH6ե#R3]T&$ :+9 Md0E֨Qb!F,&DC1IGz%2Cԗ^5Iiu & a-gY1,#kve')} ȟP5P!AmT3UJ65U3P U}bvtH*a) ݲ2(D# o Dy#aOz<kє-!gb@R gqpwK(0H.PH]J( yS3,-"MCّC:wtg`c<2zCs%҄Ģm"~ .&V ^ H3^/=37i.Eč2QW7[x Qe'̭t٘ѿ'5TT0RBvFE:Y#BUQk!*=SFTp {*Wej K]`3%M*%T̊ rv*ӒKF0"3>njKFJie'Ԙ [.LZ$;"-EF1q٥`>U|>t)5lY Pɚ{&!ߠөIjjԟ^wN^읏4#0ψҹNhF+l-lORقXh3cb큢e7nw0%=s~f3=i:B%nܝ=L-!>o#scYw$7Τ{=0sZIx_/G6uzɝ9^Q#X'͜6{s~D(*% j?$ݳeK5 =0VHw,ػP4aJE'5aCx²dUR,*-m n6 ]*QVg+. cX2 B:݄x-y *7"c'ev}^uy"f"&Cyڡһf~ 7|_o69崾6N4Kb~LjUC \b7h*^T*+g hrL uȝ30@Iȵy ]DNaJV ۧ )/%gE9D0tTST t#ƥ@ o:_42'Q8EyOkZO=`ӄD ?'ZIl3вSXDۜ=-X#Р샎=wYb 3%<3!YB{ q-*\ͤN_L1M-URpvAY_BPc" PwqW{Lt]k0ϐ@.<NhTɧU5'è-W'{3 IDATP Xj]ht/A!uwXܽj;?èpLN`[bgCqȾ{wT|˧rs1Y%(qSjj=̦qDPv_XHz%fO桼%4).7q-淏o6Z؝+AqLlɸ{65hT G+ zU91993GeRě;:Db4W^>~?z3<-Oػj}7SB&dq~2Lqꂁ7'pqoww҇M͌2֪o~_\菿 6j^ngO.FŇ/Y`,`YP̆[ɀz7~y{x)k9lU]Oc }$|բ(4ڢh "'?tJO Ce&-cxi(*5e\'O*8"T9l6ys8lLDVfJMxZ3_Y䜲\|YP{,PSL~['$M N3m LKf o,+$宺ψ1*_n'/U;9Po~п}ݏ&hư]C@+~5.bZ%PR1#6E22&N+XPht׋yL: G=( : -a Bq 7b0; 5#&fn/ݥaR|$aK5(vwiR5;&`{Z>4[J*F0ԙEytL(ڡ{|3?+cR?PFx`࢓쩰"BpҐ;oᲈX^)fx37" 6'P U8 d&mCۇ3eBḈ(dخkÐْwEUZB /uE 7xF*(-T`б^ ܵg*[hKkR75M<_T`g#@p0aA#D$'T靓k-!ٷ)_p̶/o¤Aad|e9Z~G^ 2-K{.L2¤{Hv$ڠt-›ǭ㧧ov'MÐXW62˶*%ng+y*HJAT#2T_8 6>|-_?H)e,aS9;:uB>r}\;cGwD8;08 b<*5BUf RL͖@aryz}<-䖝Ŵ{vlz|pzb{Zuv}JT@/ϟ\|tUI!n뗾90ehKzSIzxH*cFWhbӔǠ!IDY721Dc5Rh5`8 {֜#mp)竒0Y Qz[ޡq4'/C!|^\-ddBV'H2DN<.PT:JJce悪9ӦKLӁuJDk8+sT| K*Ta XڂY}.uD3e=[),-E|… PVJEaB7M^)Ât$Steq/J1R{ EI%B!bY|l>iw|1'H\f/Qw@_*w:,bFO?]wc2N{@r(ֻ%\FϳlA\ <ԭͼ3P 3)I o*.+-eĎ^)ESmq9 }xYD:g׾>տQx5REޒg ̆^T|$4#fY%Y(AVa{HZ+5'+Usg4+f<6y&J8HdQdR1$2mӡ:kSy1+f;]%SZ)jvzߒ)qQ~ѷVA[6pK40YMt+c=wqO&lTe1ۻvJޯj ghhyjtJj Gi]t@Fi=I5,~%r%r~eRTIz]:r(`ey bV CJ]?%Ra(LЂ/ v)j G^>?@V)(Z)VB*-I=mu AȽFixbo14i  ]ڴrew? *Ci2'mggl>W3H]"Fr G3T/&c"WhS=q~[mEQ"45abs,gDn5]aHm()%J+x mw^_BDž]XV\vK)5})$ KpǍU2Dߘ8x* }=j#%jn>Mk5mYk"d>添}LN +okYVCCjIZ bfsg;zXga(x-5xd] s ΧzZa}6(^P]!&E% p@Ll#eIH8 #CKᦽ$̖:Q'* bg1ТXV@)V̹dijJ\ fHd­zAv9 QHuA+G<!EqoBu~ޒz /Mzf4~B_~ɋk͛W`ˣ@M]"5Ϣ(Hp4)؛4[cf: 9 g'hrV|6 hOj6#> A<@ҴG%GΛ%~9ĨA)u5 zk"jrP>A2vNܿxm̒d}vֹvA>Ն!qDix1f<) N1rZ-ְFpyXlyV@W>6H]V4 [Jp.DYAH+TU_$h<~vزBb٧`[]5rTXh!r)Sn 1&w>"u7%4ztTc׳փ҄mpNW\QC?X<)t $`gRԠ#uơl/*)H$nBZ|V8/Rpfl5pv]Uz.$yIq蕓5s(3gN>IAn2IN!:}sGw8B5:0t|nG]pL?` Nz&ն(,ЧZ ZFO~;b/on }ט͠~D >+F`RqܮQMS= تC/$t/f}=2ܗ϶PRpbMnOVBsh)Es+.Okë:5n*e+fD]J(B8.ܖuv*Vq$RMev1C"R:V!Ӫz/X)o\*DY2kˣɽɿCݲ%ȥS)DB ?\s <}=2l#SjRWԵiϾt.FJ({#̨}ِLp q(gAH\DO}]Y"\֍a ӈBb@AV)%dWsU;@4o~pUjY)m|eה`7+ެtfW}&ܻll*_sַOR{RI nPR1mҚYN}:ٖQ,-z+ȩ {9!Tua]0WV'C"fة*g'O&OWP;U?6E q2&&lbO ?-c= Og;# {?O>Cd`vmb~=ҟ{~NhuKcK3Jt/9>E7dI>Zm?ܳy')j̶ST=^fdL+yТ6-fQj<WR;'QPMrx #҉%Psfd:!t*j]I${_R/s%ot'*KIw|^}.T,Zs3rxq!.gw3HjN3EWtߚ$7~aA@3%^f͘u}=FЙHMvS2b^4N_<_1$"\'tMh79J_vh7a! 4M} F)|cYSD'i>Ye{hcM*rgЫf _jpdB,hgQga" QkH;Cu<\URҽDCP5Cv 2N4re*bG8&2?Q5J#؊Q=! ܪzp,S~H"|68n l.H& i3;\׼9%FZuGO` Vawpc 6Z{~*G[ߘZU{ =؀w։Ɣ l{ݞ2TUZY2fG߾U=p=ˢw|z1D͟1SKJAsKi盞S[]uVv* [6c}%G+yw7['#.$8^=$Qu34`?~i~4`ҋ|آ/{HNcC]]4peS刽էtjJj Ф,ء] g& [sI,EYJ%k'+_oZwfOgYS50u6oiCp>k 2-V<p;Y'5@Ƽv4 $"=`>/_\PkdKea+25tRKSHpI9ZcH0 5ASf ڜiB xvd&UĐ LQE?]5?$Q#3 s@Pgj"j={I:mn\JV|HWfIy[]HًƩhADYT{;Pw/L$>)&((t=T!eCd($l3<=o5ťjWr&R@+ Cإ*)!ռrEU )0NgqڬЩ2^~s IDAT8z@F=ڳ8>}E{E aɴ̇o!YH>főBrawwg[Չ6OϞ<=C͝\Xr{FV V{D_qI|. YMb=?v5[C ()TDU^:ؽ"@Sqd@Y>).ǔao{:k.kY<ɿ*Y2/w{Xx&,@KfX^EUO'K$B5k4. V|l0j{?Ǫ,2J>^h7ݜ$-e8aI{5z{y6M%2Se!-xZt6,Zq^:4 05e@YJxd0GOn{kٔcx=4%-%N7:W:Kb:P 4ba<f_V/3ƾmr}˄jQmIɎޣY!{kB(q,S[u5q5& sfgY j+.̻Bw n=UowWE>[-+uxccL|!_^=ڼ.?`8&CP@O:BG'S?hhh=@1'Qf<=BI SWEqcq֔IͯtD4ww?.yTNTM.O.OqӋ^XtlRp79\Ln+Fߎ!C65ogjg[K!PUuW@$i6n4gQʅ\z[b_=vh|Ofm-`d@zw ?O/lj./Qvx___ePXcO|pɟ|F6lkD) ؂T<=PApviGI82E9{\gO,!Ql ipGhSP*7κ/8gF9Ţ/)pQJa˾xВH&K$9&i,m2 x>}d+'f 1aIQ-P鑨+k`^+_-ɘ q)N9hP\MuEEiB|0XaDiaB~3aEA n #3dVa7 JfsE"d$$a(j]\mUV:*R?[M*vgEyBV0UJgݣ%I ~v# H? E_l/\ɁVNe] nrbgl`*]`"Z]Ag⥉\ ).@(L- YCPƘHb]->˨dg7q,[/+*owqBYs0ꊈ&Gb1vkW!`dݻd>:3D|kÍ"6PEnD4I}k;0دYOk4t6"Uβͷ $X5"9ERꆄfl86䡚+yb&uoygHrq<8C&#H*YvXxu ';#a҉&@%!s%j29|.nQVv{h{+ ՠ.D8_u !S)9^~Ɨ5Q|\_>Vi^<|k~|YuXYMv,{3;v2 خ/sF|Z12lAͶg~4a og'_슎+ )iRP!-&s j;45P4.fD"&J&Zz%bUQ(n:B*EYƉ/WliI+AGAg~E\34Ŕ &i@z υ>j_2 sj2q3'͟|peAOp]9W7B BӶcattƎR:DwNhMSgNO{!4'ѯ.x3h!KP y5\wKN T2! dT A!;JX^Ƅx3HKY+ҧ\J)*D/BW2kIB:=י173|saAeϲcr9ai"uiM_侀.q}IcP5uw 8{蹔GO&/GwQUfN#4@cZ\Xb\3W”`'T xǰܜq_F뛰 eD %yXW? xͰGwX H J`ȌT(^P9bgƒ /J!m P$qd}v"D. #E[x $lop,2nj֛D~Q`y>bAFLB ʎB fkE.R"\Q 1^])MJY6DSI~(M::7sGQ4d1x;*H~ zCĕ+;NIyRt?mk@B =%Gv[4/Xp܂WxFg (QfHr% #ເYKx㊷7#м8p~-.;iWJqq=Zhc`llŠQ6IbfJ`y<~`#z~& 87 /-wN2 j lG$AkBqco@VOhKihwjLAMU@K{Hqn:6vG_`9W"uNhb8CYR=C]OOY.3v|B=l͟_L'S"W$?')ј.]]@236ECrT>1#;oᷛ6(/g8%C>jٱf<Tr>ǝ/m *|GG/wD;Ϧo.d6COYJpʣ\@$ `0ha} (MGe9*S\C"R,qs8Wk6<-h`8- HBśD_"߁abBޑ_LFnwiiFM%iGS"+9Z1RC=eb L-p-XeryPL,TR* Ʀ;&W rM% \ Uwo@‡򃼡\Bƕ PP}*fJ"mehj<4m b2xt 8"=%Hټ=3:0@w4i[(& 6HtRkkβ)\v7]5US9b4,??l~#+*q$J\d Bi*Nt,V_@1pnT#;\ 4}(g lp'Q`MLmꞟ!FbY6PJnnn}RL`\Buw0V13Ţ9R›tdhoOa\Ù5  (i~h~B GAb"~vQfXlO3rdy_r>#R '9d=nhR Pl>RAi0}ZWp~v:mq*uf pjDAWxj/m m{@B Ztb̝yI. Vs1Z-k# !dʞ0X:kQp*}eSti2Sbfe0#vKQC&M8\C}`ؖ(W(։>st648j(LUVvHR^hԌ,R2AyĽƕ#[̉Y.iT')e zZt(zsOYp Ypp, 2 <*<,'-6~;ʓƛ!eIly5ԤHm==:c%zJ`ץ)Ȃsꇳ^?z_|vW_b|e-SezĘnB5s{FTzJe(k KʭhZ0j?Xfэ. 5; j`_+Waڑ7ܓPKKHES#ިPSbT#4{&|R&% |D_eVݳނ#eJ{RY̚u2¬.6,X@ MlzqKܻr' @Z2\',61j\`h9lžI\דO#ʎMKD#`tܪ,չX& lE G_XITկ|z~/Sj93uqX%co1jHu-Х6IfiKU2B5aNI*=& :Bk{M?_o85rEWf%"- 8LW-A!+ͽMe-%3lts>.5z_JWpTg8س IjKܺb)7ZZEw:a}h-JL]{TS2" <87[2d&$~|!_P2@xà F0<@)-m, HY2XqV"4QTkXwQvyhߤ:\\̣I폎hrqȘJNB0Q:I-~LXjK!UW qn '0@j`:.X4DHxc2<)AqIB# llzߢF˨)\L"9ǕDARq6#Qs8JJyw7]eVb!v $vg;RHQtVz< (|2ז4פ߳o7=6ӕb:=::oè䰯]`WHWOEbJVz]eL>%,`?23Yȥ>y`=.,jq/'{G`rg Y~' F~~3 (jWk+n';  \HJan{ٓFob O4IQZL8 ( v38J^<2.hJPOÈO"wmyt/ +ۭ/F7!cp ;hF}Vbqf%lWe(H L7R jGy2V4M~Mҝv^]\u=)xnvC>=hÙRKplϗx叆'%vLbR<ݾi)+ Ծ=d Ӱ(ZLIJ#IKAOtŖыݸYٳ+?CTh#o+Jˆ~*c0n mQeble# };,O65]"jlQ"B^N&%G$fضQDt[pZIImЧHmJcXdڒJ79)Vs=G?6U-' RHդ'Yn]I\b]p`&!r qAIpij $Qg;BlXS/k=7筹uը.ujl*ʽQ$35**48I[PdAS%W]vB;4%0ǎ.Y[] f+Oi(Ql;ԄNj Uت FnNT^ ܃nPc ~TB̂%OZl0'ZL I*/+X+sW4Jm` ה{aH]L-#d3G[}$@}QgYJ[]@{ ʰ-oe6:LwOOO&Wxȇzr}y1#5{$_QXhP\zTX![d E]$ nҧC_BkJΖlM^ioq¶癶81鼝ED<9:$ܢN'mO>_k F7@› f\LZ ^PV֌Ab BEFL2U*|ԚEyfL@b-S*?>V=" ZvZiMoRI&i/D-T؍je<wHĸJ 1ɤKG Vp$uU4#ICCJ*?wxp-'?r!J8-W1fˑs+'&[36O+wz:% a?}$8 X\4-ã^ٟ MK{: Em O )1G gE3.rWsZ?pt9B!RXi5eѐ#@dq~>@HJṒM 0:x IԊ_ׄ}HsHoW~S\f_QIJXYT7E&DK#˟g ۖ[K믂"(~!]Xןwk;@U Kthtػ]^[_0s|s39G7f{pت_.&ONWS258;ͫ) 6X4~}2sW ҭz%o ᧗:I 8KY%})nK(H6o!i%I&xl pS.-sSsnQ4XX jx%}Q`CMW m@ 8M뗱 #̼`E XGt@3̚R+@J%7 ؁PD /QP)@ 4gXSn^PFRo,0п\ OEE~muO!|h+ hgsCW>dg*_ymg)c>V#B X:#7ZTܙo߹<[1;~5ǷHH7EC@DNƃ]ؗ]+R/=>5.\ {ma $Twmb=7Ѕߢܣqbڐ6[ ¤=7ltW p)89L{y7`b @?~<<DZN> u ԛt)0̷'NպF{LSήRWk8ؙvxkah Ρp4\Tc]ʙJ_=_R&ѿp[B<_hO׈N=G'7~z[@rڜ2aqǂJn6.1 b%VU+`jxڗrq؛gCa%e#l 7?q ]ڢWѦ)|H2 $z)QV^/QpRlGNuJj1`f9"S"c/5BqlxGLPOǖ"Wv``W o036I!(]уK2͗lqg e|&YaJb,ĭHx_D!< S kC5K'KnkѮEibDTFE}2"ݒ9 F,a3{'@&_)Nd8\Wسw\CSc@ȡ%CʱI]dҎ n9 3x51r6׹2+G\%l3U`0%eo0Ncw}t5BfLפs;aܕ[KK,DLZr'E\>dC3k˓HdjmSǯ[e%u*AaA/ #X 5ktG^ﲤQk\^N5vhZOu_'g|t6}g"c!A\F%VaHQDPfvu;eQcdQ+S:bx -I9S }|`n/}2:.ys?{NCٓ~w/.=~IO_zrBkv}}]ʎ;L_ChYG*?~|8B偦_>F p.ݿ?9}L r(* +;-!(Af.XƄ!TjWxAI'B)Kէ Ihꎧ]a힪uSb˯y\rhÓ}T>^-Ps)6Pg:@qr½|8QfBP[9 c#wI~ -8<"9 ?g\@Yu*l 0@d7 <9oyꈥz`E:-ܽCۼo}KmZ`|q@cg{+DqB$o*CevyxCJfEw r\`LKD1(:y71Y fg_{jÜ0|E  AMa&^wjyC縅T] /&KȢȷR;C/IH(M?kpq]eVځBQ-"}B1Ɏ|YWH \)TBBL@gbF(V\69 xg/Bn9(EؘcP'n7H|6\|q:hjJF3vvɿG>uH퓏+Ob!DQ/-@yQkXRs%snl n0>[6D0h0W\.,QFNF0*L e[|J) )bF| FdQ)fsKb8O8bܯ7Vvuu~7t6侪D8$4A ZEur`ȉ-{$k T0`\ 1LUk]nqαkˁ1UIv5yݤt~g_ޞ}L&Mxg$b* UD v&˞bi&dT`-JTΥ3*4!q)mKtm㯔{Ldd7DO>L4co#W3# ;:4sGU U4* ~ÚܒeG/6gؘl[ӯ.G$ԙ0%ĄO!\ӨL1]Zu-A<&]$A=(J 䰊7DM@QJt2²N r]UbSڙ(vH}h*C`M-xG4nNS 얈\=KYt$'?g v{#rrM>fZv6U:sg[C7U(3ZDhm,ɕSyl ,B]>!G-Qfu=Hik8[ɠݽFms<" q5[ Ђ BhǰG!԰d7l<=jݹIp`@><;zdz3Ҳzͽ-پ#X1V<8a֒ez lF9vGHka Y PIp vcԝ//tEϳvD{榾.)l]o:G-4bNi,װh#}xIH''RhGO>A#`NwOx"9Vi}:kĄn#NSN %-wbM*Q2g%)(b2-%YDxeb =.[%q(ѡxc(Gūe0d^Z 9&)SbՄCvrk SByĂQ/˥74rԁՃx )f[ƒK᝝:O iovM)Zo)&ﳆp8Ⱦ-i2x i՚g% <\_K) @i, i̗N7@Y +2V)H%y|B0Sa-=&P\=M#FVI426I Hwb1CM, 4>i'ѬU*f}xBP5E57qa{tP+*xR[X 2D16R_vť=yJq9W>r}Y!T9FكvuU rLcL;Orx|y:Å Ű$ (" !oTo+2ώ(R6YHO ^^~ukv\%@ޭWO8K+ eXk>=9V䤋R[do ɢbClcQTCD<;M+.4t&%vuD3t# S:^ahߥsy$gNwUichk2T>M*삎&ǖv?Om3kN IDAT\L=PnX\}7k3j@vtbbkJ8 kz׋KwظO)4K 45VZ?}\TJxKEi9UʙDjFImJL8Ԅf铲WQPT^6I*>+HL)\ظgfj?U< #&ZǢRՕ*$Ϫv =9%u)'}`$%J1d)A.LTݜH HkL4·hE-[>gpG)Ω2i8kDqBjT:DZep=4Y5V,2]i澾mRp6:ՏN\H(s;"dn /xj ,{$WNmHA}\M!EN"+=JϽƒCF_i G93cd[UJ#_dW 8H*:2)MDuU _&8q HR)wp9bKΔUfG( zJ@W4-ǿvj>`,vJ2>句97S) ҍN[S R첥n^aQ!,j>ҭw3d ;ζ{my$I&W;ф?AG&@j;g0N,|v{4DR42 zJ1^:p4G{vLZh GsWS֤0;yؗ+4`\o 4FQdiIls=9yTOL\]"Ȃ I }>&T{Zd.f˫ p7_-]ND)8WWbu~!5)UAvH//JZ-ɜ)^^/ZP9ٺMt'6AAQ8eҧhTR34%ggrnwQBJQ _H0%1Mw_än,x{ ؛µMA@H7w ~xrH\9HnXTx,]R[2W{3CI+_RȔDrչsreYb'ho-wL)UѪ^@UI9FAKdG~ۛ+6V30O4 fpRnw9~wƸg|߾e ,zj!m-yz@v_NCFREZmBplaoN+4+@0Y+ Qk8>Y.W"Ψ$AԠ_9dTLgE  Wc]#-bdH< 28Fqb҇ G[9 O5%}RۮfD`R5 T0ըdC7Ĩ-F~$pȄ(<^R j! ^_tqTlk4vx% T AKMU-QKJY*J&˒jcr^@K|Azm\&Hi~k׾}]|Լ{4p2.a##lt:sD6sQ:GS-:eh'Ov֫_~t:[Gc97.f_ wy4dL G!Li0q$pd= F}b. GIՇCTR5P~,,V#mEfjA44>JW \CHn@4Lsr'4z^{27gS2A7?ۛZְNҠjv{}^?j|w?UMe`f˄ELࢎ``j5t%Ԅgl*j[\~l\J%q*[1/$."*6ܕ y=饣sB$o,3Uԕ3q.ɲK-0M/Ԏ I_plR cnq N\]VcR*@.{ы`NJ*,`^Ct4Ajs-0߹@-҇(z>/%#hUuhc~r H?syN &9 v]SHo^1fd]87u{xtT]_h4G7dv}p\K^$zn _ǃ *q=%-*e!lwHHia2k@2Y["VsۻfNY\s6ʎQexOJ"`F\z:0YjPIf`aUI]ƺ17_wEThIG8 K^Ch%[%8Vk ~_H dz!ٯTR]ÏCބ1DPj!ػ܎JȁSۮ|cClG?p2^O*{'Αg"&('}ɣ䇣UW16ίrbcn. 6dCb+}*'7[ǖ!l!@:]T>y~rnigbe |&IaL?7铃ٻ|q}7;0xXNp4|+$Z(ㅓ٘VCqRI{ QUY[of3vl[&Ҩ8]'U)׷^f[<~Nִ(v!tj=;WHnogWRɓθGJ\.DO&F5\ ~-5tk6.oٍ׭L& ).A ~dT2NYyH0ɚf-IĻ^8f/a iYjo-R =mA hK*J28i3RjkB}؜Fǎ+۵dQ *̚yS^q)IrV}&eĥo*k5ta. ީdU\'\5]8WսITC W.M;©B䇃[ƻ>`AwbAF"̵'$HB.Fߛl͛/zI v;Ǐ?/..l;@ U1f7FI 4{kQ|xC&j^ $v]ZBAm{|:ӑTSOW=6qF'aB$+= 04EqA'v`yIZi J>ص7h؀ަ1!L9B2bp̿]PCt: Mv6F6 E: (Mc3m`)Zp(&Ș{iΓF;=| |{? D)/#S~ɴ5i]d8>Rŷ *^n7 Dƿ6↙J:F=FPËi)͆-'lrUY ]h"OM:j.p |I)+K@H%y{u0Us t"g6$*Y m!]:v{~Dvi<ё4a&ç?A_{=uw؁r9]]qi0yfJ.nwTs6~F>nmcG>C=d]|n.(GDp̪ނv2Lf-{>TQ.?f@ I`zo?3W)Ø%ڠ-BF4?Ig@vh14듆AG'=;Y"q'Ku6~ Iķ_]v7MEl;_GOZGq* qb2$0_`Dh$Ƶw~AMqPh\ݪhGkDPhV.1uLzl7ǑvS3HA02_fDB@rDr)إ`&x7&%ׂ,QH-;dL湮IT "aRUQO%>ܕNߤ WR<|Id!HqeJt8G U9G;oqJQ>^.4d9nAG{~?_IE>_M_8@MLB`O<5$K;~twji{v hH(,& e9S;$x  _ Nz}ɭbO'üB+;ї -*ka`7ar, ͔Ael_Ga*m YF=*HTwxY/IECM/UbCekx4e(-0z^x<Pݰ2V$iԉL _ A,l@8ժwXIGTu%~pjEfjnHR|E n7DgKgi12%,oRe°S.Vu(Y$ 謍ɀʽ;DXN]8 K~ywEɯI]y2E,w d!ob_}C|``oXS i9|4 6/ sX!S_#TC]K_zMjNbB-"(787BRXw1rtg>6.Y q,PFlO Fܷy{jz2N2.,wÝj`c pH0t߫+%$re@HW?=>hHZ<^߬<\3 ?3_N~﷘bRHS6Kss^iEA,8@Q9JrlKeMQJ-Yq3?1IF_C'&*za#?J\&~'vTa +%BKDp $:0ZLͲayORu8Yݙ,!ð}L%S\qRXt[lR52% I'|4+7-#Z>$U"UJeL"U.zdk;`g3LiyB,&7;/onZě=((QpvZ$;<`//^GO_M] -LVH;|%#+EQ ADiAM=!uL~om|dOUZkQL@Ӡ UP$mob!3M| {2`qp׬GvNj5&vo I7"mE0ŀ T(5@gBwET!8;kV;-zBUmGR7w=^X+ Z m$z|# Ik<哢.4'"($ _\xS؜hps+>ˊ6:gc%(*uZi;Coq}pe*N:._C:=Ki 4BcćKnEՇ¤Ƞ#^}뻃 Ґnv'P'[<+P䛟a#߼1&qBM s}S Ng7cZoIH:odwAFt띳%md,>C9^>pXDj9Š*t\LAKМ]h;bgH>Gy1%[6 *y7=fM lӼ{r|BF_?Cv  ńNt}i3@ IDAT (hx&jyKw 7  dkm^-Eoi;hV?{{;cK [M3H6{ⴲR-kdf뷌JdLIa*7Y:GEfbZrTaȟڊf[2,)4PXuoFRʲhԖ41Lx~L/tWݳٹӤ C/~!Y wkQk Ʃ\+>[ =s,3#;a >ܷ?VT^.krG(pJl'sܕ+D{!ZzI%>TAk+ӑp /*@; (9ӥQ31b`XϨ o̷[;E}0:=闯~3|[ɸaX $WXp?deL|E9;8[l]o?&jPĢG‘>+NO$X@,yqKl8B0N@ *w$G>FUNa^v*P82 ta$W?&6 ӗʽq`$RɤY{ iNC^no`[&a6<yZVu5QXJY+iMF: qe?A%\c {\= >,nNS cda&cBxQB>V+Y(]jǵ|([ATP#:Bo_h ! ]?_f)7J!2;&ǘrFTPںӸGtP#aU>`y6EًC@_z #h5"":[ݬ즷~/^BoVIt2qK5J'Oc_ۼd(ΤS;އ`dX>hvMy`N{@m[FL oCOnʗy{~u)$տm bg`ٔ P,onFr B46-)"6 CpOhrXx9v3l^ySklagO}3)/;ş|ӯ 'q;!=ӿH`ëjb{ִ'igj>1tUI7R(Qa5>~+^mk4VԖcEZr51٣eaAMKF9:[PY~ZW$wRvbJ1,Ct(͔APxpד,}vШs><7h@ƢC!,HB_MKkKK 9~H.8Z3qOX% )FŅ!Y-gKQggXZ@ɾa}!to~p=?zt|Mn|F⾱{t䖛ok~R0qv2b.?}yw<p)%6*~{[suLn +j5G] t6'c0U ?Ŧ2dN5q r|$.#._7\N]GZ۰gQHT'r۴%JÔh^&7"@O@8]`f |:}$ &BwZ eP˒6'ϛ7eVD+4pE{=7ff- hq Ȅ%>>,:HU`+3-T.!>>qҍFp\VUb:[r f@ JJvfNTε VRN{;a_]o2_Y{0~d,Y  3`qgt{=ju>zPa00 N%%P0o޾GF/RJ2wIUCta/TS^ x /Obhp@Zr@ĦYۦazCR$EP_oHm2,u0O& 4Ni%dڵAL]&u_nfVo=S1jZ,W)8AxMElDA=ǪJ̺C2Ï!P*7\_&=|9Ĭ(!}D%;99I{OܜWgu'xrdOkڛqgDϵ59+N$"L02Tꄙ @JX]ۃ `c!)|(T"-4@}J1-9xR)\α7}L495jǭ?|vS6]eNxb.s`5CC!0y{훫t|{LA;=3w6C)h 0 Ob>qC rvk{s2;q:&p"!9 XU]`bA!mG5hf|KҿѓGn%ƅDr=?,ŗh1TO<}~^7S֫bV2C]x~I{88t>@qŐtX?<%%_ Q)hio 8\u9D¹Lfy ͅPYrؗ [8;t.-/&RkpaHG|4s°QRe͗7?} m>GyƕZ.U"A;h[N'(epA 9XGÜhiIb~BP>+^oƻwZf^ 5ks`qurD'K1ڭuR;.2!^FFe*IH iA0%~GJGԈR)Q_YQǩ$ȥ1r/Ǻc"rϒLOcl+_V^l~E1UW/p@/qt@(5^98~ũ\fb dzq%.EYYyM\'b4=\*e1I+Sbi[AW(t`'|cDEF kDgoP3Sڽ$G, jd }~؀pYN0=n_)s^"yO~++0_nK!ޣA'q&uGfD$h%M7gJ#/+ "#>>&ӿ7b/z9I:.}r82;Kh=U6*K%ʐ:6}EG.[sɒ/Nźh5΂$s>) X`n"d`B%P >voT%VBMb2lRvy9!oOv-;4E/_]_7?_+hSg[??/ٻOKT\0 Х gnF.Bԭc2$+9 TƇE) ~EiÀ"F{$H+KŰ((ԤJo{LjE_8zQ`w"@>W,֜7LfQrCPZCJVg?c"fZqIHr n-$@#>3|)o &V.0J pfH+6ƢZdt6c8i%pIC5~}oB( ikj5հhU0b@\~Uo?F ~?<}ُɞ&#Dw-ՅNY6+Eچ~E[2gj8e(D[JUHt4ӓA޺G "(Lt asRvw'Ӳyd E{&(tSpT(9&{t ٘TuH!D`0js%{ylWwKZTJ(wEgr꩚-AbaI F% F =Rws%Q:A45}wHTً0$lnV˫b"TjgV4dto1Щ7_<N&L u4%.Y^G[oڄtЂZj`g4( Lv6(h! fI1 cD7{R`J4'j@}6l}عp(BGh+u_}Q|_W k"9?wn=՗IooVtQjv4SԮΗ4.O_QMG~ .pቺ*50<|5j72JXb^JE G͢]?nS޶W ^.v'%4(ߜ/zIs wb6F_~'>C&$b>T/l iMRT:@ Յunnu"l7NNOp_7l?lLvGo{hs_dӗ=O=`'sR7`PGbNY@v|## dTI! 4[K)9G{j>:>cdzJ >BaGNIͯgAnJ҆etXx'׭##o (Jqe92~8^VRq|JX 7"IY>_ a^`|&fcB1k; y/W$ŭiA.anܗՏ Mj Р<$S&g̮] %Rl1EAe>=V|43ƍK@HC{stwɋf_97ѣ$ hE-T5 Zހd$A>-/Z,nOgӟmw𹅭ej~ ϑ28ڈE㭵KM^{+ɋ X] x w$zC̉J%,[i 1kenv\8sCOٕ!DUDЃgqfSW4shMVN"_5 t3( ni(~Pf|jpo#~[x!ɳr>~ʎ>cK}~ Z` 2"1}C[Mk "C(q;%f1zD6=+ H=5D  IDATl>+{4 F#AwJA+*O"SVwU4cuaٸ[x[s$؋O_~23wG** bxś wv?~4q:D/Yn>v4l!8Zm# @=6[_-y 'B p<\89-NvUFɭ^KlZ, 6™|CDs*p w׵z>ހ!goB5lS9>?t((ع(aAOP4EgMwT#[W|v}šc'ы?{GnzvvūYdͦ{G}FiNYFD/T͓?:JǠhɊR+qTi-"SR"kěc!pvER=,VF;|ѩG??wd(y:i &A:™9"?:讱AFL?0!f~X#ƭ}Ȍ=3[I?밥Y2ђ!4k 4KIԝH09Rs<98˦K~j .!v5ܣ" ͏i!R^Ӫ_N&72yrQp'uvjD8!OǑzCR[0۾Xy C>_|}پ%5Qw[Pvj l(knO3hz1煽/^]o.6yYB0rB龡e.CDu65ZpTzqp wS85*KMb<c|K`& MgI;M_ p<6nG-[!xf[zFٷٴ^gf;q?Đ-U"W%( `´q"L7yؔ*c`$wʢcD_$H r>\'$lbOﱚ@L&P7)\>c^!C_)~s hU0>dӣO|s\HIYyouKU+mAII}~;:6.ãOgg -[Ywxb<>ٝ(ȾX]СQ>z4Ekf!ilTjw4}!"3C3/C|~3Cva9.jfO-*3ngO9NWw0{PP|gvx{1Ro|p > mgrd}~q!w\._Ewu?j33j5<5Zۛ^]\ۦD?:NDoԻN?ދ/O~fy\og{.lG ů,LTtH{5HЎٌϖEt`?y{+B)>:UJ\/8):iB/n]@e{EHv5gZV"貍+&ig٘/dM*bXzSpd>oD8'` [ &j@oKj$1B!/z8HYit)k_ӘZ 3.{3C~c]%ᬆ*K4 `jl3JXE~m_K %cfTK%Eu<}(JDٍcBg8P01쎧SCDj5[>|  YICQkONd4ٞb+Rۨ??@kmCCQ4|_!n9kЇ@;/#A;< } ʓh;$_$0i[4>Bwվ+ȴ`EV]0d̰ 8^#G) JHzįZQQLIk:{⇃kꦥRC~uGUah3RE"&{ɡ`}'#f[94l.V~G}SGu1M0j8ajxo$R)n}KKp_ ]+pޫ>. BRc ,b ZRm%{R)s֢`(aHwZrIb|Ə 2HZGť1f9.ACBwiL,i8 ,U*dQ\7Yjjy~tveUd`_,L~U?wqI*(!M^6ɧl[73bǜH U@lvZHesiQ?/lڔ$%VuW C"Ș!W8G>EP )%tm !.:JM]oAd7mf.iv\Bc Eo0{S{ϞNۿjSP׵o~SntZr {\DHW0M#ϋ ˅t%,8wAKq)EȞvUBޒ'!N?0<b c?-GG*'^T#ģ//O(jPuy}Ä.W<!F(0s>¼`Ele_CP8ֈ~iaP"1&/B"EcC0 N23Ra+q frl}TH"iZ 1)QJ*$leE\5YHwfPb24c b-0ɐM>\t D`''D["fڬŠVgb9B"].ك (lnVgGg/vn6%t֔Dkf}Z/k(3Cw ˘c <bgWX V)!8R%u> {,*OK^@Qvs"Q {Rȶ2$$|Ԁ n&=GTяhϨdlL.6[?YSO& vlǏώL- ;I l+s92AO%"c0Ky| kg=hgbp|>ӓ2:YMc`oVj)ֳ2~JZHvm!$`6;&[VF'\uPPɭ>T7`#%2bkJ"$ (7n)82CQ7x`B؎TTf~T\[v*vGgs^cQ˜É xiv~5.<]` MC@5 '1U2׌.dN,oFr2ʾZ'@ezx=8ʥfX?;?\?O౭ֿz=p4#ѝ‰iteB Tn g`Dz:#\u~CH_qW7N>9]or'BG"WK8T2F}!lIe F_T =Y% r{᧬N<-Wr!F6PE6%fd$.etË=ыJ7ᗳ=>?<SG_7 wjdr"D2r_֠N/D>RP|.7&{7[5TLA"*heH8r'-+@1m*?@q bω\4&:Fԇfn]JaR%z;'QǤ[_ƍYwQyfcA׃\N4HŹnZg8hP+7(?Î.ez>g^Y3~zM+Q%9ǼBJ QLe&bTrJH;R3ɻ}ﮍ 7B(G*BdM3ӊ bg9RQ~8M"E"ƨcq xt޲WdDܢۙ6bA.t\֋.QFxneHBh(zqEOi|-EtVve4n=b&w̓?m/Q%ū_|W껓>nI"ifwt2SQ +L?]{q6!nh*q(nj!p>{v}oQ(OWTO&gM9?AMS#@Yn.zUC.cj;d=] ظXa(1VVxG-cǣb{黙8*cF0x_C4]N_>upjpv7o9yDLWM1Q#%t!-%Um??oe? TK-><8]S+Sn8x]?!y n4!BW"Oo~u$'u$J&:gPh5lLN&gm a1WA ܏^U%؀Vx Ϊ9M0:@U{! ev8PPS#b>?#bR^iX46St,H0%݆ yT<ńgYNW qx޾y*bS"ԇ=̽ԡLp/jIo9gM2Q3Ki?VE"Nxɶryq=q[ް.ҥXTb =RV'|=XomҌ RjԷ< ZhE  le  "2U+i] 4*7ެx۰|ٯSiF /-8zX| Rei܀A}lTI)Dd9WRV\2`UIl?9|{hiQ%p Ko *Jt?[O-Ncv#sxۤ{F;u@ k'MÛw'SL43K>jzWh JHU۵ݼca f xX &> s*Lefe\Y<,č`)ѷ>|u7n?gO/?QĽn,; a]Y Z$urpƔZü \O~0}= (Uc\gFI?vPd?+H-PÄmQI!4 i<;/?9$&' ʔDttʫkJ;հ0ܖ*reC@d6[;Ӽɓ* hu]vJAaU#ӊ@ 8 vȜT %h1WՍwvK IDATGйPrνҠ䵄ѿyn tG5 BtC2*&ze6c Xi? h|+ ?l5?mkBAѕ?BP*(PPyHeW;rcxPm{ֹ?N#o >T _h/%gRo@4&c2 c><=$)/^wmi):u{ƀqgr5Q~bV'n2# 勹?8yS.+@&)9+$ԙlSCY*`]AW_ΊwЌp}ЖqxxT8O' xrFÑż.{~3b:fÓ~x ҫle8[ ߾>,g?ɜ`v?Z^fy [3Ew_8yz:l;zY R%)؇2+R1Eh՛iR:ɊXFT'ph؝Cc9qP~*9bJLRZk`; ,8"f$iԄUqHs 2uk硋 2bjƫ 1 +@S ieۉ(6FUWwJiO% \Iu/X 7ن M0<DS=st d7)90L5!Y;Z!:)a/:v>mHPAAiC"a81f6ggl9,0Vfq7kqdAV$^6T( @ 10 {PΈ`ҠxAHlЌyeޝL0Ls2sIM4QƷ`j#Ycrybwʻ8J8~1.i2~ Hh uq.GA, FDIpW-Q#H7tĹu[LSXceCNJzdH{&ЁQ2'.$xvy[Zl^, RJ49juN}!&-ƂC(6 *].9x)gC8M{(?lSLu =|~! Q4Atgsb@՞Zj7ӣrf"ec!2ώ;F]:q{r}t9;i-[>LُCLmQ:wlW̼zuv|TOn׽?^& \K<9$fgG3%4T8⣠؟yHw{IJux ״$; 8@S*gG 6xxfMmW7!+Ԭjc՜_:Ys:"W<_L34evt[1IrS2J̕9tb wq9Y\]Eb,ND{5TClܓb8)8X 4S7,-%4}`RۮD G\`Tǭ,#[1`G}Rk$ iOϷXs67%%n' LzrXqj C #)8ݯp!gS@fmkϽ o36yrBzWyG.*䗕P->i+gdR {XtIngvpr1PPF/amb}Nć%f.=Zv0h!wt܄0DSfΖ۳MydQϗtNN>?ݽۏA5:yppڇ!mFJXA* )7 gm՚O`uv" T$X,l|ʶe-) 9>[n*uDyo#Ufk&zogOOZ`Ҧn.pzPzq~DI.Gd.}(Y))ӄ[aO94~zɒy*18kP?œ~0JH@j

    IJ]gwEy yѨ O!^# }t51&.$?2@q glcEb3-{_|Xq{N7[ (CUGBғ({\_/~x0 3iʙd$˂Opil·*_X0e]\HR. v VTbA4!Z >zM0zf[j7zCF`M0s"#H-A%Ubn:͞$\Yx%b)̞v+rm+gWGCHABx&pm$;& 41!xtWjQb:,=u1K!bgHuἼVo2eT}rEE p8LgKULK0z9y< Ɗ)NYic |z҈4/̌@xݮ}m=L 8\A!i"<9n矾:޽p^??^ jTM:v=hAlT; ~8XUsɑ1:.7ƠV-5?:9,3pIV9\A9;}"r KAV4&adz ܕwsf}쓋wAɑM;1ok*|8=bKL] /t$0R~tvEofK{nuo&[͡"K* m;^mp&%+RwϦǧtO;bI"e5P}1c eZy9x9kLIP1HYNgk:&/ ^@ yVnWO..?߭.)ŋc`:8~Y.F&Ǩj;ajhN48̇y/o:WZ?dxFB_8 ̛ȋ.tWa ŻgM!XJ IU# 9q~c4)%12#oW 1$<lfSQ) @#leqM71e^fB D<(\\WoeJWTG݃cAtwJtOT}hxP-ꠑzy!h5~(,p$_2hwIicٚٓ6]A1%dlC\%SZ@2e^#^:iE3 Mr<:s^W?Ϲ!,/*Z_m0Wt{ōxVN`9Mf EH=̵BU``loW8* ƮHɂ~IYtR:AX$]I".m$"?Ĩ*ic !FM#0=%m9>@r+ɔц&)\SEüDvD& EH@]+66/r^X#LEr ¸q 09CUM2c˄X@̨SKt!GYj{ƴFMc{+2tw<z#ğPH|ACbx~4A y԰ayK'Lϴ=a 3ڀUϪ??[6dT:?BzWc/6O?;9. qX_3F͟tR|jQ/b\ݵ;OTK=jxjr 93O3~~R  iU+dF#+1}7Oj/<||zЭN=jיm l:Dp|㇛J{~폇=?cٮ` tI^U;iw<]g7)8h>^}=@Ȇ~&װώS~7GFg#%|h}+z:ZTh.z#h! im lwR-N#2.!цÄEsOh1mb"RMl;e1HQأaN6KaAƊ)TtbQ77B>?y0Ƿ 'l% @5ϼkHgtyPV {)C,i[ejOd;KőK#xlA0WQUAcq)DDb-yT=&Zd o(Z3,5wld/ΐaSެs)ˈ׾ZาvY~bsr~y&~IޣGi IMh4EF"`i\Ss,9=TJp2o/^ࡏ1׬ǵa IDAT[@hԨH3o^^=lSQɮ{Q"]7f IzLu;t3^{ω_p|q|".nUHƅ=qݎ?nFQIϢ6p\N6IPfzD"By`*lY'*tͶbj?Z QHSJwzZ èٮg) 뗜)AAj@l<-e91"1 'rY񡉠覭ZU۠#FZNmK*k~2z<| [{Lv!9'aňkdv?5rf,G8DHeg]ޖNnu(A&٭&t4h%ܦ9F=))g9|t-AmK9 f\w XpdiD:.ՄZeg%T6X?2P?G~L#/AxH`˄4(5?\m沔HLG7Ao;1˒HH`/!4v$gx@FM1~!SƑDE2P];*%jFc4*&{48bNF}NWl]\ןnѢ{}*?jɪ>8:_nҧ燸:nɜV'Vz|@펯$farfpPsUo^/Nx Ã6m`e|<̖vD!pj>+c=?=>a֖Ñ|=]ʷy+8,GO]Zla0g ^cT( LbD yBU|]6shCf2GU•MLmNT7W7C#,rH~N)ѝ?x-*9Sp#=Ϧy|V)qAzQkҔDC3IRP-ɐ&2 8c'e8a{IGVҥLTe)5:HdG IUŔy0O2Q?GOމpb,X._p7!sr 뷙Z+X3N3jC۵#ڽhrlt锨{̯ "50jv=Lљe qKL5?JҽƑT[fPlbs}oyoش@`+'N☜"R!zJNx,Cm+]hS^hgx D@E  #l`qodWlcՏk>W;yZ2UFͦ7@d1![sA"Jцr `X5eCk:PZ}Jmif3Q;N[bqc䒶~EE”]-hAM79RNiPr,G1T>Nb0Ab U85uCagPWbO( vBEcJ]QPl"y3ETIrfukXESqͰM⵬+pىe2lY+%ٷGJ=`IAV'3bX{HaipЌ #0[)\ڰLQ.luM@4XߪM&6c8<#8L̨V@f4WrhS),fs։]#Dfˣ;VZ~~K)Mop)^|-I燹'ةڔ1gN'[gOO5nB5.dJ .@lV dJ#!~>/UjVn6(>}ۅ_D?IƬQ?=xLfF3< R-VU^q9(ݕ*'۷O[MlpHI#fAlgYdg_r1On{%Ɉ Fd|ɚ@ qnwQ 0\0/6(H\1JՃB9:EQ;tr*wO8*W(@q IB/!eL'&@0KX LUS1o&"L%ZBbRDWEOjOU%|$0L0KI> lIL>:?@wd=-bQC.p٢u`^Soi31.ĉ]"OUbj9XL<'&u),f0tu6)a20.2rXM{E0Fr1O+zTeӑEZfS: "ܡ!C# J-Fg7X~yRQ9]G !]#UL9Sְ a9erP$fU!LG Ýg~h'l}i=L8:p#2,C[a[Y4@eHآ@5q}%Դ!S#m@pqzƂ†%{֥fƅTmI>1396`q#N\e26`U%iF8y2 ^Do Y@tB~5# A~jE'QEvq [ralB%$'3eQ[)!Ekǿ`T4~$>:qCI1;>aTVCf՞F@jԣ+[֠2'( *5  =0M (<|AOIÝ ՘VF1)p+4:e?Pn4(Ĥ耻"F0 U .@ykAwTi1SO!3#"G4PrPȫg7 jw?luJ}>b߭D\iл^o43% C ̢W|(1?LP#<eD{@h< "SJl,w2Sɂq3:Xa46 FJM{)J59q] Dݺ#P^M01 ӃKINzvXsh G(HTt;tQǠ6z8#):}Ucu'⮭Wfɶ=2ɸ6G&@(@Z {6$Q%'d{/ӃToTH<>JRΑc'GG}o9\\ BFt-M[pӯՋj}=/{'ʇ() Ns&3f_ɾ]N;;+:+ۚGn1ɲ+亵b:==[/5~ܪwE~ܾnm^H@fʖkv.g0Byn7]S }(Q߬4!VְaҮBm`l rvPGΕ;4cH#C>cQ<[*tL %ש%^yhqz ?:o,e"c*^ĖJN&a ]0!E$D{=x*x0Fe6EDmVpJo_|ׇIzp=CN|x*zz;;D$?Ͽxrz48/ͨ_>Մ|@ lBs:rSؘ)lwVg>rbDAY*eYk,]"GjwQ̣ϐ 9fRمZ矢0Aa8_ i:9T?=="'spt<ٞ.Ҫ` oT]3R `_}J1~blmIX$uAAlTATa6?MiLL{HHed?=Zh`J63Q9d*'(BFU(TUr3x8Gq##Lm*IFI/]073̵9.& rAPZqO﷣14mo;'۩g[,eD8v{%! m Rʪ` F E,ʉ_s!"vTC)B^4fa h 7W C5fc>ҧ0=-Q7Fe YT1k#Gq,Q(3i%D{l0*O0ti N1Cݡl rZg(d;&dMG[h#ϰ@0?v=kl7GP%/NDRG&ģD"PS( ab Bf9٣EHr,KKӑS%ks=VnC!#X`C(.(J;ňEǀExNT5ⳣjwddi^ܠo<;-3ٯ}Ϳ2 GxzŸWvNGumoP_|ÐkZfwEdݟΧ])u =1O_nz3&$UZeC/1fDtT<wJ5ǩWznTKWvp&gg6nt9f i)jyp'x|mKe_AQv06X̚$yui5jtTzOA&Vg?$*r6GY@Z2Kw)hSi /xl͜xNh6>_H$9:#TLƈZp:t\ g ҩC;iC>oێPhTI  #SŅr YȡQ|\nǶ* WMcg8Gv)+ƑVb9ֈ}sD%@;c*jRӆi D[Ze29\2XUPgGΤ$ trb7*4.VH̶6+;|z`tUͰC.Uh'c{$`gz ʚȡq1ODyDa0sOCn=WF>G- Nc5Lo w2 5=pt}y9]AABt_?5 Y:]\&,a6c' 0#H(uH?-E) 7ҚHzD .F3OpFP87a6r v3/z{t%\hN\䧁 -IS&OjfD?jE9׌䧈aV`pMBDH lō7$ b#|Sؘ>皺B%K5tH c,znJm6oDaI_;=d"4j\0<|3anŋRin.)sjG`Ϙ{gwV#Dh86*vҭ~]^4K-T~uܿwCGNapц~gg ]&`ÿo2û7?_N{͋G2} O>9iujtvpu?yz>/VPUo\~Ū?o[SJk4|aѾypT,yhy>ÕZ DEe(sepy89=׽iU)XLOʗ {ɓ~ջNϚ']PMtjw~tw_ZΗ͓Gk>2 x2^B]+RIQBvΏM)D6u˿.L &3]A0  D.EgޚN<2{Co%L$BWMH'Zʁc~w/*'hrD)L4l [YLj:̗p5Ak[#i$A & >GA8MQ>˄ȟʅ1)\SgvӍ{b2)6qF=:dT= IDATzwD,/ry%:x-vfe"rS*71IJҌiHŜ&U,ijžOҔ1uhDWby҆W4s68ҫQ'bjD;n`נ>T|z:+696/F&Ek_*szv`_rd!|*Wvr]ahnըlLvQ5 È)Z? VZvmm伐RISj7FûAg, 8"^ƇBDFVN43›sH%:&zP:brLjejIn%1j2.,*uaf/ \4 S:c#:dQd:eߣN_d&dn\w?U}dUj^v~mFw?^bj7ǭºSw`}_~O_-Fhg,̗–nʘp;9>dN[s+hO 2@S=%,d Viw!ҷ( Sa?؁ 7S:;w-&qzrXNp\ӡG}uyGܿ/$ϠEuWV`;kWzLHFfmH\播&gU`T]4rv0 L#ZNⰱٟ#åJ5JE*;ng[".8U-EH?Yѡ@& _%tqNK,: I@Zn֗WM8IkX_0SXsUd UPpOwͯE>~v[,nq봃6OoMT0IN{b(TdM i_=*%y23*1#wJ`8֒/bV2@,t8b0%)2AäߦOF@JQB4fT >[Za ɱ2˟%m|fdLdA: ),Y W9eL\ ؆}Oꠠ4y#ZDy)i `I{]!1ejeQFb/P2Cǧ>C R7n(eZspԹE2}bYȸB,Gib+7B.+) ؼhsJsBґSflZʠ( e s|O87Y+$HQ"0nRly2[",>L1;?` X]Уs#t 3M+(>kVBgh4٬/^<9o vQw7u T_\~n@Ӄ?ӻr~oWۇ4^]_,'TN;`!ǻj}p6I*,jIG)f;cb\aOv9>ѾAo7k`O> yNv BN}ϫ޼k!;8K=դ?eRw?6$`D RO@jAmUZ;l3cTᱜqULh.'k5Ղz>)Y㺢<7{.FoLC"6%î\- M:x3poRUMݤK[gOt@.=FƒpL&S H< }Z\dp }zdbO)}MD*jMb\x9T75iMЌ3zRqhsir|.Z6Iadd ,ఔ a~Ǵ1'ƣOWa4IN+BMWZm14M-OQhveB7р12a1QѳO-kkJH$ݬCao6 T%㜹(S%El2˰ҹLµa L*kB K`MHkɊ(܎ T#A]:՝If]EMo2DŽ'4}btk$L',MJ9qMóc4@H\s{+̶D_!Uo1]9R:g2 # x# ^7`7-x3 T9,7 #tB49V SNjlL@ߋx K, d; :O: k*E0$O%ѧzVjB)=&pO8醌2~ Ij)uUk-H ؁;i(ƦaR)orcYX4T̝lzrcxD(m'c$ڈ<}%ve@Ь؛Ni.Z>NkciĹ^1V$1"SD[i9: rp~QW\|#:Gs=~ ^4D>gOWwv6*:jOF_8vn9ŝ?[בȒY>H9qtDkBbr\wc'O/``th(Yޞ| /yjrva՟?urO-\}՟{Ty0_1@\jGGw!"i ݳNvzo]/E?.`MdoUfT_A oi)wO$:%5u Ea6%ք>zxN7δ4= REz>7P@([6/"s6˓SauKbÑF]1!KU&uQ6IӱhvIeV*f?R\У&gPm b*2m ^e TL Nh-%&OC0-y8P7/bN%(F0V"d ^ 2jFM6<0ybIf$d4&$w2,P&V=>F d[Q%G,鵴?aRؼ.#ϮamH@A xIhkΟ::oקJqHh[vQGu w]1C->;Ą\}7޻px~E=_c]6qTC/ iNmY:dߟR6XM%b a9h=F6-i"GӋ7?L*Y7v?͆j=lVN_}6Vz=Խx3iҩ6pt2HTRoeC%Fl~*.⤰)P{Ԉ$/a+iUC[8bFGlfidpmΫR}u?z5 |Ƹ-ZI@o\s AxAk5G(ġ)ONE)Kph_#:B7)S (s[9=Gc8șJAehgx/j&a2KSo(2A^@XFe߯" ^_ڶ;l:5eLI&F@3D6(ך:9nԅE_@]oC=HB\!ve)4&?DPc4Y(݄+§ƲO鐚&C0@ g R{GM`8 v*pM8`)ɉ{/(JS ۀpC&m4`zhKeH1x(Uf9p<ƔNwgAN>BjnN. 91OC,by#uUDT0޶+H+(U!(ԹT4Tz0Z(M DMVBiG]9⌨qs0_݄|#ÖZ9d6&8<IzEq6u2 9e1[W@nOқ$2wC{sRq ZPN=`(X4G4SͦzP x,sjOW3m ġ1ˋЇG]:MȋF9'O /;f2[ je_}iYC~usrʓKѴ"'usyE~W#/'*Ut nF4-v,Ud1v6jH^1bߔkT8|nK7/ݿ7dgpL x&~i=tFF]t}q,BطtV]9a,CTKBӳhG,]f&]=EP*ܺ>ߠf1izWsb_22#תڻf ,Ȗ HE!neK2Bl{f<险Zrό='/duUWeF8߻</a5LZ #Fwg wj=dDL.^Th'{~{ꍎS !wKp 1p) pat64_ Ex{!_a^0 _gʤ?v/fBP:KN|Su>'[\0@Y -n&%=aHD]jTRKIjIqx ˄5SP&̩Xb% f=DpVpEܥ*"$H_:Mm)G >sRv|Y &u t\-Gy E/FaL$YXlX3&uufh*kUСRMjx!#qҘ!$Bj,jHՓ硊%"[pPi~ fYg0n۬~û{'ň$` S2bΫ"[ӄH6]D!T+&;Mw}Si_ne}O3X{ed+//@j`>Esy(@Bo} ݁Kbr&n> O@dH<ڜdLJ|OtR XDΈ _V7݋i!)܋}iN^Na:ς6Kj*zj*anZU*1u1yd@:tb+o.mZ$)4@~NLG'ِ6)o ˥~NTKgcph?3}Ӆ$8M=I_a/9*-UA}-iUyC 縺!:`g,@luiJ1O`@Fk_(n6xf6yj ^;;{;-HAd-0l](6;H<ҹD4+5 Jv6u+ o:H0`kGא{A|`u0ˍ9 GVBHY = (ldmU2+w ӛGR%*+j/o _ɻ:ڼufr\fc0D#|b>E)I#n}hf|<Ƀz[VӺlf$ِʍf $5ۿSBywg]wcֽ;uٿwztfqsf/BaoV@3)i]e f8ڧykݍ͝Ͼ A^QPQXt=lҩUmF~qE5C<%Cw8mu֪Zp~~·x:gm8T~o}}MheW]فȗ::ZRyۗDBP/z1˒ʥ!?ZtyH4-yc4o)ά^x]CcMq7's68h,o '(V#̄՚1,*sR d?ϊf _J㙵 *:j1-ACf QL](_żΦ`DaT]i:9'L6öZ0;6 ΞKu%NV, ~l`e"AXو#~84n!o¯3 W?ݪ75 ]gȲ:ʪTݐ3:QĠ%U}j3EK]S?>vfMh剴!+6jj'|q#WbGX5J9@I2[̐&Η2|Y68/"ך9##01F0LJTd= lrxZi,n;1 ZHRہNphSWjPbh)|āL>|7P@?3V";8Zd!Au#7XNTe~Q 7/Ik+"{a.R0tU FM||dH>qv?> wτ =Q⍐4FŕŜ3(DoldxTqolTro4[n}U^H"f7%Avzl6lsX *AQ @[}*KC/$O(i౯#0⻈JaYjg>{!z]N% @Pa4>jO`DMwN7bVb$ vEg2: :" /fZbm l* 1gf_[ʙQ"äRVh.H=ŽZį͟BlOE&H]M{YQ,i|;#7aR "a@{AWcQtqѩP"(2˵RmeZFZ]d6뼇+ 5;ڃ_̭@e?9}1̎^bj̳8%޹W.0_\eόjqۤ=jc'6`eZJFO EE3I.J( H3p8ZwRvw~=:Lzo}K=?:Nk;+7~Ebx/017VA]^1ltj3d0{w]4Ŝ*wV.UaG0#םo23Yj'BGfL=1v \;8l z%7;SQ-z@Mky6o>ҠmU#R>L荶aKS);FLD4roFK\ejIs%vr桊D;.;!d2@jlXfq`=&{t4)_g%#Z`sHfE`ZX[: &88 Et*cc>Jץ!VxjI@n9#h`wYɛ ,' j'2\kfWˍrak3Q5'Kzh)D9 %ڪ&m6C3ɖkbQAQO^,`,*B  ވy~g\Obw]tήTK˯~ۅxt)iz* b4EMWoؖdI厬㙒',er`o-^F 'Uup8I钡gbfub{3r`N4+Au<"o4P,YBJ Rm_уAqYgwA @/(ȢEΧ% -vIsnIl笚h(OzͬI 2l3dˍ" l!jIJP 4=ޘ֒ɦ5k;ڭMپDTIJIhcOgVE F;MM3@e=2b<lǥTu9@ŕ0zEe(뻏6vYh5Xa{sΠ\UG/[{\Ϗ_ 7jKW7f٨6J\ /P^ا2r(\Y]1uHPݛ rzgtomYk8k䧣iv4od;o휼~rdSt/؛cO96jcke6ut5R@F/ Yp#.w9<}Y`bd7mV3y Jr J ^O3a\@|*YwIpe;L#A74HB >TvI` tVn^@gR8fRMs'}=)0f\8 >( 1y‚2zWܬeëo #\$|rR`KO ;Y-~HO|$PI[0 -Aďs΍jNx\~3 _H|0\"穪D9vKe=P<^8|QrYE|l/q)G@bnAMj. Kk%->bIVdNANQ 7CAʤ 62|jpggá FYc٢)$-Ҁ+f8?*=$H81ȌZ)Z&o~HH^W9mvnMqZ޽@t1~3$<ڛ$ëFf44+w0*/~t2;"҅TsC$票B <)J 8&Vjc"9c (!ٳʹ#fwhLCͺ@/>NP1cZs, q oRT㕌4$!1S&%5@姨l!H)rPK,)ddė0@x"dR15*Ŋ4/!3 .\O1$L {?$yS5/BfECdk>透 vFuZ.BSL7w$j, Y>ugTOs 6ituHe^$11vq%׏dG7Kj}:8yqpqU,5lY[_?{^\YYq]YR,ᬶ.(/{GGKg:lrzI:kC'/ViihEԩ>+X`{%IVYk6xxp0/g{ `\ۭoQ\u~=6~~-Y `BB]?\.ҋib:.V8nfc" Vrd권.~{k;yT&Vpy M`pO\_Ӷ4l_[+uih 9x-hp|oErJ3 1BXqW@:Kv2Y$VqIv < `G<kZl=p 2sϤ{tImRMzmy8\ gG D3FBG=ap%ڏ@[3BHf=qԹ =hEE9_~J-/w)^|oσ߾}J٢(+c=GRښJ7& XmHiuѨc2S66@]ڊhc04q{t#62\b?6e * s T7 ptIk,4do_Ů_R;ywXέU/8Y?qQܠ ' 2x{o޻wnliJEbeszܢx3%Hn­yzAfûz,yѭ^]^vNtZNɽz(ܧJ(V}g,:}c~Y7 *d٩ZiuM0Bڨ1Dxžj /w=w1H>η(OOfXhhXᴂKPbt0Ue^> M ٻ?Qyc-p$HIy9;z - 00QbG=a> 3v5e d8.ҌM</ .5eL~Y*<%$ȿܸș@RdW4nqK@3dTժ3Lhb#Nل cmIEE\i!+0̵qgOylϢL9GYm}n! 8'Æ{P%^RN (\.;s]lR:5?WpY4mp`AUtxZ!2RSt]}:0Q{H)c$ z߬Az_^"{h \*tyg4>S.34pON*+ij;<cEvPtOUa1XRӼ*&uhn ɎQ8Ճ ɡ1N kyLF|{w5fI;R`$']c` VLQ8C:@8u1@%!\Q$Xc3 .dͧu[bFQ( ,ʟ. >tKڒ!:&{40.]0B7|ȱX+HYQlwpx. kXH|#x ty)$5 7@rg.þtX,6*HvS؉ ),^KQw|K Mة~g4$n&WEtoBvzSh6{E.2ʀCiYЂBLB rG֐qMZ&ԪDFb$7qP`\Hދ4R]cKycRVhFbLfM·t& RP$E M Oo|i0\gKmnzW W,{fO_&3]Zy!oOaGx#Q; bCt| ?>m4[kBk#4qq{ 5I"QWT?ߌE'١)⩑CTb|9s^`qzLVs~Qcf>?.iÚ[?+Aa:vGl  0wPAS9Ii”i #6҂fD$-Cl`8y/_h7]KfEF{4G^FQq<*.x,Mbk[ǨPq~rd lnwG$_y??\Wru9D[ŭz𼺷[_p+:,Uk[^/s{YQg>JW':~j}Q`KsďF+iX:]~‰9Wo6Yo޼x݄@mY\%ƵVTLKӗEg:4OǷ7ҋ>T~^H2׽֝GfqX|ӟ-rY I#ڤ?i4\uH}V >#{rv{g9XujT]'\v.se9 t;Y.6J Wh*8i:ZDFЂث DICQ QRS1cU-<+A &@<&In:5 kDW9hV) W`܁$nJsSpkpw=DtΧe'SJ~F*hFw%6"@2H$(;>a1nh I[ t,8"{7r*,JZnɹ@38Cc08,;)\C}mA?N]`"VHrD[0[7Ql`cYb~'vlŸGo5bz4\IR@4qto}2SO\\? \P$[Y w{e`X.т[hض;#:9šBa-dtqdSYj2;q&Gim0! x#bV]*XĠMymғlD#H2fe.()Lf8VχC8$^>||zVZZQW?R=Teo_w|jK"29{ -\^m NbbgBl *F;*]áy IDAT(wζe2ѶRW|+"=A<*s (=s36c*X,HMV\u'I\TD+zePձηPA*F9+cGENl EF9%LC+ь㦸3QvDs:ʄ&,tolxE ^WA_,@HR8t),Km&T":8uRwEuqk1,=<\}+L{)Y,^֭YރRpq-P 'g΍_=[J/V~;ooV9}Zf}urwYIkA{pD[bA LV竩ՍEū.dk+5wd8އﬖS_++g}jvTQkЙ^NKyxA3Ɨ3)N tfZoT6a0.`Ooj^eg#{ngx~UV~×5@!)V* Y!/%sJnF_v}$$HrXCEsZa +(܍?EXj΄,Sv܅9+L![KVHVrXjY}Rq= bd9T%fpoL{ }"K,.%?kceu쁶M aoJ+k0"둦' cXPT3e M}UE\΢@-03Ȓ$+ {] ˲ZƲ=vfx|h)$)=io͖;@Ljc{W̤jT]ALc8/)MLv0/(!N@p2oH.\ư8_OF5Ŀӹ`p's˘[#GP(T;mT4FH=@7/I XTxhd Z-Mwq@$%U a12(E"ȥ YQv/ĕЀ$Bɻk)'O?=6~ @r;>?_Uztfeg[-lȄc_Nic.'")>5\iA1` 3ՑSH8Q%L&RoҺPչRZ1m)F@Pv So>{g;{7V]OϞ\`}j~y =r:gaO/NW6o~"UZ7 wytiq(4vV..xw^\tpA7@ؑ[7lנzݞ}]nxKוrn<\2~pvcl$qQ>C=kfƋR:EH gZXhsJQ~u@LB'$Ԩu '-VV,5aT+W.]zP _0eQު7ԸHIb,-:'*ݞ-]IiLfe^ s 'YI}* ,~)]#euL!2+&("3 `!V K H2p'29no)08.ůK2"` YY_Nzȸn{cUØr&<ɇɖD\X F&w!,ȰM|18~p̢~G_2/o>*otq,(DUN| R8Q: v9mĄ_pg2F]L`BjpT‚__JllE& yd1j<~V"Lflv%Xl'%( n3Y ;:!e>'P?L2V_̚@/33$p_(yǪ- N]0UY&KW\`5'cmNC0iJbZU} m}56i?4۾ucPR{!iأuhb I3_)>?<ηNwɋTۗTP3h@=qܟN g}UWU$V[Z37.=.8̂-SO:wɃ"7|L)ܐpܺV&$/A -Xz/L8!ADz^VOx)Rڗ V9֗At'm71tyB\zY[=2[lVlHgx52NF< 2="hgvu˂:`K֨^g ;Bn+h\._0CpG—+]`1_~~0 NPGtxGFxUSu{J18e|o~7óy{2XN/GagxŶzh4FΙ!:J%)1d(_rymg1Eut맸װ0JGoշq籉8 1 W4jRrdgL}8%+\ΘC8$[%J?AKNp oJ8q&5R pC"(|=/D):6H,B ~ ;(#i`k ɮʀiٿ6|)@M+yYTs ѐf\Uiԗ\V7;_~9;k^o=Y/u;7mSa >v Å%t .9kW&'Xc[ A]IDC|dGn4 e "+S88&@Q2rcW Яj$qmiQF8-4sbX _HG-ihN 5A\Ëofk|bh@{kp}AG4i] UBk@>;|#ymYx]jkZB{l[^ r%K+ Tβzf#N9pXvO~pi8yvp{>b Q3sk^+<8`Ж:m]켵᣽z;n]xqٺ:m}3)}>si -BdF) fsظX\MIi 0+Av pmcX>g]a >_ųGVPYC8x޼X7T~@8w)s!n2le7R\g0 ;5:I6M#å',' m\T@{n6a7DO! '`Q$Lza X1‚F-)^#+A@!;JFRF[`?D5_,h FئfYPg"6]umWoօ R'x;ZZLѽAIDL; 8JD L8λ|ebPAɑ(CO˄ZM+;7ؙ2PϏOj6R[=+j6""p1TEEYI$^/M a63`/c}?[O~ez餷:_٪7v?};oYMu:lI;.30t5#w? A/P'%756G2S*!fo JA>dtskcXUo ET\ JB  Z&J'Up7@#f\q&; 4 KX]-e2hn0cdsNLzH-S(S9?w hɖ L...6tY'% {D~|o;Vjomofm89<;Mhw~YAz7GqeiٍO^eJ~MS{ݺ]hyF_s4k\~R(^J+9h޳C |xMr)UZe\(3S<8<%8gK. UVv;k |2hg+ EE|ASrv :Z<;<^vŽ 7_,oCW)Zܧ ߟ3Xt 'Ezb\ꁹ[f@,[4-A bobtw֬fÞZ[AO23U`|f=EYx7pK @~fhZ.ڀBB7ɶ5DյHueea`3[Gx*H]m#s M*o;pM"1A:sF7dY 5w:c.Fxy,^^}+TYG,0ܚ[C (5{&5/?[$6)XG&lו/˷on'T}IJ~py~qŚs[ YPTR1q2#-H(r |@@E6 `4jt#h9V0+?(NI£"Nx`ҸVM`&?Ί/~^W%Uk\vCMagϙtSB-= w<8;z-?g42T4{A ~g~doG/Gd9Je{d:v Y53jheJik^:s’۹;|uKm-I/Җ]b&?(% Xv]JH3a,?w4MUt'w9 GLB-Cm*7 59H?I*9V zB ` ~\n?}QtQZMz5Ag*,&6i{l9rBJUO{ËVk~ӷK]HV#.ZI9hcbѯ}X>Nbݽdqtpq7۷{:jv<; i$3y^vvNcP/ɕ'q*0HGn lV7{ΠT3+o? EsF( zO7 ~\-8M:v9SŞf7+67UJP*v Zs^od#bRvGb ]Q3-2V|Yz1 [a\ܼW9fYa,0G%gW<~1qP0JDR2z>tz|\$hf<11 T6 T5(i1 8Z@W&X"GóJQhNҡ>P肭_NEw(^'hv=UJgB^5'r@~י˧oI. y: ~Cd6URҤf(Z\а3&2TZ&&J@"GKpF@aUؔ4PXRfIO0Thpu/W xϹ5eH6* oLta(D[L:mF, 7>\k-a\Vr5p6˜8Qud|Ȍ15F8d'ʳp(#bPƗjj1 ѠGq؊6ߡRl ꇰd!|0cqCb8%74/7?Kѭmy:@:z٥NκN|.߾Ztqyw?a}Փf>Iu4:)Z䃌a~ĻZz4K}H(6-K,Ôl, ;L@uq d;KP>黠;XV#2`{ yFL><2lNÝ24GY"G9? praqY``#xsۧҦw>&GNJvٻSWֳkaGXGYW(&1@m( {vxL"?aFAa5NyT 9%0UU@)M!syLݍRyz;ۥy{bn֋gT Nރ۟yIY_-urw0os٫gfe1WJxMN~V-0g) j5x}::Ӳ~s1U tEG!Wgٕ9+S^X1!NC\%yasmus>'] @?|o{~xxGB m-cbL9E7MpW:_/N$pրQĘ]\A{gKm,yYA>$=#oz87W ‰/at1!dS"JR<.v3L($a* `?_I `EƤ0q[(%"h؟3 KQGLx̣XB TwhRˆcָ\j8n[\[󁠃 ')4H",⮎Kn6K}j'^ASdK/iJS\jxw`.N- 7$!9>坎4€ 7Hod TX7aߢڳj@dksWW^ =Dv?( 84OUVbtZ0{1z\ ,kdzo# $R*BZGŁ&qzr{?y+ WW7˙U+µJq$To^(;]Շ6$YyQY!+N4BNݐ`7i,EŠGI֙$%h!:EЇxM</z8RWpG=a<QR#cm^wƋQ6`JHx6N2n'n2Í'6IXCe?6MQ~$-%LJs}X KJUHe ,{ 2c?qMO+A_!M>p^I> sm!RsafdA͗U.*. ր{i3B==<:h-//6n|۩AI0& Nnl7lo7{76JaMX7<_)/'>agVve VRZkuGQJ9usqт}mmo'ԓnZ['N;{{koxA@0PWt]*⌕Kw6^~u:ֹBȑZ[)sNdR*Uhjc{GG=Υb®+swU Q'U=3`v2wȠ9cC̩Tf) ;WR*GP7l|1# +VQ ޥb2OIɏ&%˦\0LCI_E*'W "hyJߙ8XԫµR~|# wx>nO$eJ-A1# 7qpqFwR4,m$[|D͗JtzQfj+,*J\Ƥ@B(=&K ' 1V`O'QOWw}a_E ˽:2MW]^s>_q^ 7 C:93!; =~?}oy+{nw*V7o/mlz%0Taf&y(  %ax#y70/`3Bl:j(7QւB7 u%g4Tآfءt`Zk3l>ѭ~d_J\$L45i|P\7˵Tqka6>o>gʭ'(MԾ62ɱ!d n9LkS>} KS diMbfB9D_+嚌G"˜1J*2:ZK%U.TϷGS߰ȐGIGr/洠d l3ʤ&؀ZW~^Kkf5ɾp-5KIjՃF>nyա65@VEZ8x[E|G)O-4>#BKD"![@i Qݮ8c*^ YLM]!Q >4}%bKnoW}כ۷yE~`,rZгɻٮ熧f?FP(__3~k;8;8f.~RBSwjƴODkxfE\,7\ O}SFQLS^UVrMNh!zUq<[}v{Vy>{^n$u-+y?Z߼@h: %Ád*bK37 Lj7ŋeGrٴ%d"ᆢeH$il=Ȇv0 4 C R(ҋi\.gp1h4ƻ03 8DӪ%>?y?;zq(Z}B *"EYAgxZ`{[O܆KNƭ"UQp0:%iZX[[{6$Aaл3ԑږSb)נA'Ho޷ 9ﭜ%I22am#%'ZbAdS`В>L2j$cVб .LTsm}n3oSsxq,.S(ɕo!=Y'gXF'U>:x2 c([A*ȔS_`|kTʨ+#,R~Wt1rqބC-ݘf]oIs8}w{{y݄A3p>{ݛw)>CrszF!P6wkIeڕt~u]/kn1??MY^C;]_ O;'#:vSM&v#K`*?e)y#BѬZ޾wbyRw #[k78ۗ}>tw/bt.},G<=ecK9lpY.;^j6wGN3J јݖsй6Q%1'"[&)/(vQ; M1 0|b_Т H{'R{_0L 0 0;6D ϱ(@FK$,WGw  c~I%?nj,ۚ:%!@*Q3gJQBQѰ9)46A#X@ F(n<# ţQSȰ;5䢏jaw1{R;"6VZcUpM Ft* b*I#TGb 20 a߷u`rp4s9|YKlQ袵տ[u;O͙IK`Vъ 0`d)_ @D 8`}5a)rTscYzS}s&+yA;qT;(0 y@l_/߹||g0`1R36LŇjz+,Zms_,.OCxì"HI}bu{x9v6KZ3T@$/x%8ɝdhNɧћ~<(t GDMBʄljy ҕY@+5 %,pve2qɕmOo0̫a=(FaUƪF_DȽl##kɇ`OeEуz,Cr9Zrϕa DQxLܴ0}<`.S{l BX'/Bb.e+O7n;:;=;이&_8wz{FsYZ޽weoZH,meu <|m4*YP,Ò[_"VbD7 ~tF r,_Y7772XBS}uk (/Az8aRgVs+؂L^l-ēw]-|v⬵Y* dG)z\.Hz]HhMɴ䰰$eLVcIZtў.E6Bj􂆘'֋W!+ !28KtB\hB@2(Wy|ƶ=-2ϪUВJOB#49oeB2Lh=_!0EDR*|ȞCN @W!uzu;{vd4atZK7aXG`%ǔa!/叺}5! $ ʙÏ2E3| !M&"8|VpޅFI=:tPH3tG>fL^ gX7ִ(%v>?3XsyR. 1H2Qwt*m$us*m|xG .SPE1={Ӛ75L7v؞ϭ'ɬ5={'[Y=T+l19;o[g.Rh=G,p\1vSM/yL]O 1 ,Y.&h4jCHSZ {,+4wT]+2]r;?6CusN!+s%ֶv7GsDۍG90XPBvqv?6$i-^RjYOk Q`\F7ZTc-KJM C3݈ !F(`uvKIULG1#+iv{4G+/>5f@ѸyՏi흇;&tXX'ԏv?eR\{>Do6oK_fjФ4&Sª㕶*#Q,PY&."cʰ]˜:'Bfo W٢z.c#0Ǻ̵_"<\d@WaRh )TsQ$AQ _tLyXi1$*6S qA CJu$yD&؟ yj^'ȅ1)< @"BZ -F.'ø E}}А'z;a%lY7/.͇֐.Nk76^~Fns.z=\17ol̠:=xW'>*L{Ͼx m%UPfaJwmW {5zu!"vܬƫV,p!l1?4;Uvλr:uBygCj Q#d `l XVdD3Ct>T9o}Oo zֳ2E r57Jf)ޓ4/-$w~CTc]9,nm;DžFX9 @/,ʌp;by!WӶ6?,um6Asy w5p` |ո8F⠌ֽ8ؠ6Zsq6O s8"ȃ ] u y*[(bA$W"v;FW؛b1Wllޠ7^zĻv-Ir4jd0x8Ȁ{  w`GIy}3^2THbvkKmz7]oϪUnk?[4zռ}Q\n/_,7u'~"A IDAT$I/O4Q1IBȤY [AvTXxZzR|1acZZht>TB}5(݉Nf6AI }@\w`(Lyx5iU|j"Y$}#f=q ];(8pmESAE!?Oj=Z%}|c 2W_\@e<#\f4Fkto_?6,>oCCdT+fc}}],QwM*_LpJlJ.`>|7W-^wg[vb]uyhit=T˻h[=M>{lX=zOObN7D86Dkј(#״G&|ML/ƶR KprNtѸI1U&KÏ>Dv9vl@)atoGE8 ( X*n ÝwsCډ$ dx0G=]zcZXT0o`ܒ׏'=؉&0ѻtu}y%d#B7Rntb]t.UAT;s({fdj!@n 8F 6݉;7_1KNY)PӦTĸc\l5!Qeډ*Ĥxڃ],PCeK"b=hn2,0TB@;X9,q+];}qO(Wo] Šdnj[x6ߞq񧗽gL;ބ[3j+i{E▋\i֝-:Z_zbӭ|jQR>)GjݝKPhK:iXRCZ2&~&dHeps6qD.rcLY7])#PE2^ GA@U&P|H~i* uP| 1 1zQqx)62i>{5dh6M eȤ;Rx"G0! CF.)AENB0*1(l֊^WRd1FeIै+Kުvӆ _Thi>;M3=xSeg<~<}u9}v5(ʛ9&}[]e^)7Z~2ymͭ:Q >yΥh~`y.1v6aLUh/W1GfԷ]^>ޣ[.jD}T dUp=ݣw&o2O|d~7v F fWt7O:yԼw~?5oHvvl׿U _^ۏ )`E%|$5;7 #Ǜwp. "%OW1O2H(?bQG6;<|Զ:&o1j\Xt2w>U z㏧G)hz ;zKھGepk`7לx<7g`*ybA6$PMvG~} l8 &a1a/yI4xS ZD f>g7bu2%Ɏ1rX^PI#v7"ipUEGoïL1jAVąJS4rA*Ci{&w DR!A"k,}Cx97-سL\=[ V 5 b,H>&FcgDxw6 @WҞbkE.(OWT0=;ə]2yKS+Vr` [O6n2 \Ph:t~{~Ό4;'UƹJ>/J$oPe1)UQk8\NڽOrM;|T~vaCh F ^N׊XWIF>Xm2YPTuQ&󽠇y XOeƘӾokGeFK5m ;ü8 /S<1WfDi&fB?06qDaha2r %jF̆ <ۊ>d SEq(N]6G 1jVe6(Jeӕ*6hѮ[ͻTz+؞Sأ3;gO5zBNbAnў>{,L[o6@es| t=lE mEJ7IU;Hbӌq֛Ўx@l ?8jg(Iicٳ\pXFp;Էh~fLJRcNj;k ͍vuqrw`\%0 ߼>2:>~xpmbJ>} 3wv?ypuut}V8g=jbe>{[+Q@P/y4FǞ0L} ^Hƒ?> !;G޶ONbiǣha[}ѓ#1[ >ݤd&)q >P'PiUX'$5Űd`F헓SD)G XHS5ԌDDDsn7 ߛJhw-)whQyJ&B($R_ L-$=4~A*duI}! {4ˢxg+pበ&H8V']>ts"bY*Ɗ@ bOk ~ 6JgP6[ūre;]o҇.=6l֥8"5pitImH7%\Fj1x#56V&ٰ\]Uٿպl/>;ZBhW۳cTN Yr%W; -NatϟOIǭBK0KRB(<rpYj{TV??F`y:#w/3Wk)|| N3dڬ A3Iգ}Lj<NHlu- X6M@v}4=A&r)"\ R4ƽҕ!?H{6 J.SI2(h@;4J6ۚVd8 Ň 8#fŚy$Wa|L0yD-0j:=#tN## (a)KEoY;`ncgjm5^/.[W/ټmNz-l=Ř/ I "aFfOW_y1zY VreCah H3o}f>_|a}wZqIR0hIڜI:{G̓r^(BF+|}z #d i>hO_>|ޣΫ+g=>ämuۛ岙5#v- D$~aL.//NZlZ=| Gx %vDڲXZë zt`Y//mr-b5:ƞ0UUqr2'.vF)"2HETv5ؿ*mS)2:0QmQ4DH,b؀nI1h7i-8Ĝ)灁f˭ρ&&ePxwad3WH$RT#a B Ra|@\H`{saaNe6K1arXM%&hĴ2=jI!Ly58,B'p!!VwȝS3K(C:akT6ɜ fE4;ҎL.US!t(f{b[q%z/lVxAW.}Q"J$UY*3_`cnT- :kj5xy#P#0$hoXf!6}k+R& ;_gjaYdi`3  Y~g(;GK9A4|$/Zs>]imD h!'ȵ;gܹw{tz}?~la>u«4nl{ӪÝFqA-znno!N!SZXVw#`:?M16-EJxx2gIA1d_%TC ga8F.X>!ryВB[A8"QOZ)-`FA^yYI3"ShAq&Lާ* 248P%`4e 2I\R !ń8 }$ \\LZ BwƬ9jupiFn$taOW&.i_$[V^)T_P@pA:lwϮڝyy=Cgڃ,vs=j]a%ȥF@ >5HVȖ+Z^tǫUkH5&mLI` ]bj5~׾ sG_ɬڴ;zٚp#N*[2)G{UzgihTiϧtohFB'p>-N:7ė] Arݻ~?U{[ʣP\N &6ʁF'4J&O$Y^\ Hy`OD> :ꨋF?pI2Ojc8xCe8NA4D8?aВs.'蛛-ow?(!aߗ@Cb~W l8 $,,5%1<IL&j>05la?jQ؛>2p`G!{8ZP@;L.^v(:D="37F*ȠԀ,B)CHåvJ=޺W''/ϊUѱXY؍ ! Mt"y/zN6h2) 8eԈ@`A[+r hA7$~ .A"t* O| ^1x4(f}Ƴ2>2>ѹ |LmWB̚S &3VY%&(՛-J"] LU@W(I؂(ć$* U٠0tA E?lfe(/oĥG;l!XBX)EZcJ׏f॑O˥gxKˋv?vw/6Qs;1yGōJPOgߜv5{OވH/}׽Ψ߿A3pmJŽAkJ`ȺMxɼOFTɏ&7R B[ 3ѽ-HkOy8m]Ċ=:< [QKMY~G$u8lnsb<=k?;5N#i#:?f$6eȂX#0KO%hBinpGpcgA\!wPǓ:vϨW vjj(z[:(cF[ *@4usnu} 6 $!h͜ޭQ& (q(qϡN4\0X$ٓi $4g]Q5( :Q$bkXNMPPa"!` `%|3|ʦA ()߾7 hb |:N~b}2Щ8唟OaaixK#8@'Ly2Č $6@>ⶻ)Lh$p`lJ>xJa =Z4+0gC1FP#Jbl8C',*X8,3hk)A.ʂg3o+Әx6u. .Zۓ{;{ U|@0OL @D)p@Cm-'MF}Y/}1Cn~|t Mӌ(d0i4e2[QS VIn^j_ Y!˨~QW_`ldr8hm ;tY*nuZlT= 7*PC1L^U |K4U7ZJC/.Hc")bjzV\%C5ig;쬣G$-.ɡlͫgcI ?B&PMw%ĥJJ(3"Vv'qVxW(gB$*U|%d>x0TT$ұ\a>yPs8"js#b H@!cᅄs'\h'c;4?N,o/`Y |ۆ$]7;OLa$FPHA鴶 sO Yn'CwWX"apyB `J޹ )&XP$G)\=q 2Ψa_EW^jEMQVAqmDʄdọ普%|aO"_%TGsgW̋u6VСϾy.F#=*- %9Q;Ap!ħ+mnZrAu`D0|j ph9MT&aY"G.ɔkjt|2<4ZBaAUᓂṡݗ??/P9ta=x7GV]wm(hmJW- Ũm-zH7ibɨ_}8t-E 6}.~0ɮiu2` !h[) ؛YP+l5!EvDhJ ͘u6 ̆M ěT}9&2ƵJ""S{&eRАvSkĝ)JF)`t2+ЫLoTOaHplrdg(Ɂh4? IDAT/Gh@ۋoCcxa#[?kw+aqHw6G1~H~|[M]&Q~hД*s{~q0\+4+X^zF![-d*Ç[Z0X,z}Ze75X A)Dc`>zA6ckz9V n`)SKkU5ł|s [gvSlMAY7g_\@bvt=,*f>۶;bJ[ݽ7?d6{F1VI~{ %Ob=?oz0)7KFADD:* "` <"lC("+Hr(5-!NZ oǦ AMܦxN{i6T&δABZ /KLECRs2}^mm(߲)kYSЙdQ{(jgoREis8! ֔%&{*z(j-S>}*+:ԱVcJKx8v9MBgWCC,9>I*8{s҂vR2+n]uÊ k ױ3~/ZtvMJIC$Fe=^ A}2t=Rg{%IK,D#fZ$}OC@0ȌDn^?~5 \cr+11b^vcMR$j%K{qOjTW&-syLhLߨ/@TWJjH3Šbgw\?m77#."(]ؒ@5A}*){*Fm`؝v4in])Ǔ~r3W7m?L*:E| ii*"ؼovs4٢8\\փ𠋨NsU֍!Mb95Flg`"n1WK؋($v ,Q! %%b̈,&o߉}P#s!58i$yJ8ʪH~>mT*7+Zu sIMD}kEߏ^EYY|uDWBwFsNR[@Xڪo+ Oѯ (ᴟtFsuxz!k1޾K*e9::\P+*r\7>9S63-Wo"G{TЏ+J Q$N$:ߏZ~08(!Aj4fB *x+wtelqmgVhyٴF@qD 2()Z(# ]HŰ?8yX?ϕ.)q"3g r5T`4~_g6$WٔD7$=>nE\"x+v>| "G9:5 !OFnɡ@+&v('=ZVD'Vz ~1;PGnvK*uhh` >="{7`Q[/XrS IPm9IIC&3o6KXZCb@GeTKh1%[Ct(W\D#ޮDY} X0^^u6i#bFJ|V>z0,/SH!Rā3˰@]&7"p\z/(enoL&xwk՝g/}tAm-to d99ޮy܇ ̃3QL`R;hE^w^wЛ0?3A7pNrYif^A MRȠ"Q\G^-v7d}8P;ޢJT_V|;wDaNH7vͭ7bn0BP5YtTl4Ͽb pARlV#U\go([} /J ,+s~vCP"71I@.#֍,@JXڑI[Kps * $9&wL kJ  Q[1@5NLHv(gGT;L}bI]c6Q`Ǯdp4=tpFt&M &DASn Wb)cUGQ=?Ez{H}LɮS wH{[Dˆ]혐MuRūLUBk0#gFLeJŒIA:*OJ .,QzGkj9kml:?m'QF8E[3 Wj |2 m6ty]dA` D K|XF ; lwjF2 .aw YP- s ;3\:2M~h$00jî5`}\!WNˤ_@+ȥ4%lkF9'ߗѠ?XjPn5Z̈́AT =?4 @1DŽZrnXm+hzs7U٫6vOt|W~u~3Eefʖ{L[Au aGMbfmQ cd!p)Z8U@%EEgEd!(/c=%9 NB ~.5SpQrtW.<.0͝@ 7.?`:PeֹMD>~YMy&!CrҒ`3N|#jQ 5*V[p*=d{\n?zz5/luY"ʬ(XnV gl0u3~BF? fTPhjgܛ cV"(ζK.st%KOS##*J&%ɢ{Z\Fʞ{RKel˸ x51u!uIG>y30Yԃ 4\A:_$JEZ0s( :EBLU5Q"Ew,e[ڠݥi K29RGJtILdI1 N46ULZUv0-n?x_][!d~ %ykU3jFkݭjSw@uA"=SzTvzYˬv!d+%ZO4Yr沏#OSHBZg2iaݓoIj}Zg:=ھrthvTLgu Bu_ߦΞ:{;7?<2vu]T%J'$-2bs{5R[zQ3;rG6X#LOư%Bߓ!N%}jZ!u8j<]`%uA7(ݙ"{(֐6K"jW:k`v T3 ezT.B}?$Nx;\Mu~9%(*iA8FrM8eę+@ 6fE .0z<9GTHB!KPLH&<Pr3јc,T^X2znVW_T"y}<;x9 $wDnC*l"adz3hd+׃29<kEH (EnE0\im@p0]|H‚Cq}= ]OWb R"(JiLZUy;S$z*^Fנ,Eu"VJN,T3ź Ȍ@vO):k [1og=_0B柃MH I&[@Syjp‘wfB7g#! ËDma#/ 7)5}X2?z0>]"w |V&ȝqXk!DGXg|$mKu9.? 6K9F1".=DrjRT[=C ٢ 0c~6nog.[z,!pГxV?&1ga Kߜ3ѐ9;׬rWbٳggpFr^C`rSa9G V:] wP>: 4j>މ) %Z 9mbftgPqvxehjJW͡VR"MҬsB_9&0_57ICdpa>*W/iN8-rUuɐ)-9&_Mh⼣O& x!K1v|^oa-xRuށZaXh&Hk4 0:dR+p'hȾK0@% D4e*&x!ئ\^(ja5^COA͸k\on4D29c )Qp ,㡠Ha nNsbjAO~JN4ʋ~U^؍-j! e1P&IӖpO FB:'xbJ)=9 DBűꬸIMEiTK[k"ĵ]b[E *ZKRgc; JY1CP&. r۫unv:E)[h<ɖvϭRSwf IDK U!Յ:$aj΢Y*[} |:tT:^q@ibY{ϩHѬ'N$]k4 lpӫ5-R]zvj;ԇeZJV[V{?}u;A?<ޤ2̊lή_6xq k,_ƋBF#quBDi0]u뜫7|Gbk!>߾"f,t-_m?)vc+Z)={p %d[-&߆0Y裱CgIAiD&㓾IR"E'QѲy8wճ , ^߈X=12!WpK4 tz@#2 ZQF;[U tqddT+`tS3_}ŏ~Z;SG/1~k-͠C\̻7"p3)#Ũ.ƜH ׍Djcz ~ճWά:B,ɝi.܅.z E. 4MU%mHpЗqjj0Dϸ.$J`fbb20K'kLA^ǯٯqBT37Ü]bm;鐌~c/ϯ:s ;LIlfQq#Hy#*6g ٜ/->~hػ/ǝZԝ,z1rl7?{ZLuEPmFQa5;Q5BO?+Q IDATĈ@#;C4vsTQ$%)M1Hib8W/MQLpR/e$IjG21OaU!:$pdL[w7+$DXFwIGA Kbϗ?EդukO uC%m%Ԩ:gLd-;؉9'C rDxTHsoN ʺH&GqDvlċ PبNȻ yI-*S`xlX}I4TfKI>%;&?.2\>owQsȗ8}c?Yh+gYF -7s~\ ai08Z1/ł.zi7䤨`H<5?ۃR1FEa ?iufI2s r! LeD܎tzo֛[O^WilԏLZD6 Tj!n'w(c98kiBMp0p/ԹI$ȹ5U ~󆿉6>%'Ik#k (/ I -0L>GaABȯaaۆ$ YA6ChL=[z3rn8fp^:nho/;0gRs޿]|͐>PhI3syDa2bP_NUcqSBeYvcegs;61kN^z/G3P,6ʛ;~R~?{}1h [EoDon:H# ҬwFnu5::8_C[:[mG?Qnzx. 3mtTX1o0)kaz76_Rkf [yx=gfTxʊDzUf$2,A4-uEٮ,ff|t.ͩlʄYpGaiҺH4@\B9Q|RQɎS]&! ,"U+QH[i#ꁘsv=J.{\to E= eEJ J'iԵ8Hk-CK[X8d$U0,w!ȔT#蠎֕Շ'>@@Ajh0F\s(,"S%x""r)j?$Ż5<(a1 q1{5aJ=\9gPG#z3jsڱ߈}Xh%cMqPFh pl1\uC 4DΌbAc|f=z~,*jWѓx- rFC liI23Y5$"4HJz4EvTE:#lIEPCo(QFeIdKQ93AC.N{ ۻ|ǿ իvOf:f$ " @@|Y ţ 濁fc3a 0`G R(U?W?Q jh (7_΄(PE|tk .F`MuGw]tdIOd` bsTpMPېٙ*rH+mQx܁ҪqReWJ J@zR|frlkCYfqҡ $f]!P5!WNy.cf1Ȏ)%)>e bݶx̹(x2ATJL8%?xՁu}CF {<(褹Ui|WT1w7_elkcp#nި p1.{m"oGrWjn4n1q‘K|n ٲ^oWKE^G{(3f{~޶Z+ϯ./O!l_fz[s ~lx 5d5Z,+B\jP`UZVc>FT>o J#G'j]6и_ Z\8H v"4QhBPP#sE^[nFxGG2,pM1||vS$gf;zN6+4 :zC\-k 86qNP@;b`zT@ٌPL>cAQq\@Y8@۱Lj=\γ6.GX6u_l)fanu ߼YC!~|qy! j8''t1}4k3 Q̿~Cf@l-V1倖~ V<`ĕEC %Vf-3h!CBS/n75V?'b%LwOUF` U믿/_^ժ%!f:9c2N j77 U&ֺ8m<:U@-хo%swO+9w*G^<9{jo>}gb@DC0hmܐ.M& R*.,~Q@]Egf͟4#5_-襑&2K/}~17ʦ{*.* R W4v_EY՝(%!Y}n*րp s3'@>+XPt*8gz+<##so2_8 3AgAdHeƠi*vK&Ax} M-7םR nF(!*665D{4_:6.f7חW]$٤vjnvXdC\Eɖ1(q>K Ss~zJ9A5Ux'.[[oOq''z0 2vAz~vuj6vWE]+W_.ѵOekTpx1)7H1lUHP;|W\|ov%wZOM;m`4wYT4ˊw@l3 IZ<WMNRch:Ǎ}HIwTQ)/!!5x:hĵElr h=+3N@>f}9%BN-S'rYn4xk<wQdRnF]'1 qDC{B A,@]8B?GS WyyE%R)7)tJ(aH*7PJɼShW3iڡXO>s[8>=`bTRqhī ń&;U n((9FQATuFSµB^mj(\aVQEը8_&CC!e3@~fsmə_.t41k# sBm [LeigvOEn |b;aG?oFC?T 4lyMZE"b}e@R4N8\nNNZ|/DM٣v6nך{{]9#q/83Y Ge|4 ^NqROd-F.zix`@caƴvb$$:bAx|PP7chF,9O&FQDwTWgU\+0 !q~qq54UCBt& w-)7-;D@XO1b[Y-4e 7 EєqW‘Š@3d!&bBL(A/Erl$ŝFۡAY61NvL`8\ ج4xݳpտyscto>5ERf٨ e hvl0N,[)pFw#7qamѩчzx5쌘Koמz dN7թ50-vm6ʭɈI=xZ}u6n1p>Q&ލ Q{Gƈh?si5i4J4_-:S%1WmRJI©:7ֶG24_ip{h]ڕBp(\>P(!zuX H "XADeCddqٔt{ÖSC;F_xL陼ad0UDz@0E) 1e B"2(9%bs<tgɢX x}?_<i7Mfn iRV~]zqhC2#I9)c,7Zכ[rʿ>a;an:z{lC'q22ʥVH-oTʻp){zk7G$?t'EnPLVy*_C]1  ,5olO XST1fub>R^kg?-UDM.'M,k^`L\6 7qm +eU`'S7$*2^tA#sd,M=m$9AL^UbY{@puzMpIgG xj3so \5X_foߜ.[u(,.U ZEk=_nm4/h,ʹtT BV,//XOX0UD72hq[Pu9K{Agt5y`kRpe.@򮝃|k]t;%T^x1ro0$omV'Aש?!o*Xʤųӕ`8<<_X%rmا U>[7aw@ULJ0i@.Ik1h45Ǡ$ nLeMV1J"N`$KQ"S,1fhVg]TM&IgdTE0#`OM[vS)jM#l8hCt 2$!*V0_>ǢBii0Cw\kһZ{= \範%ޕbr;qx\ND4z81M)zMO$?< SR+eZ>iࣘ8]}RM`S& Aj D雁###ImTU%i@`ҦƐ| l s[ n0["ЄH.,EF"1MZʸ\{4Uia$\#P>Jlæ.Y>*91#jh26ʀkzyf`kl x#M]f2#b'"_-fiM o}2e%<љi7=y1 A}X:}z`DЦl;J1 D^|luCIܙd%mE%_1MȔhyKP tL d m*Kf|;5lrQ=+(ќ@%!(Io*ڈ;$%=T- $xI kQ.J]7qNF&#5Rt <^c7TB(ҲXr HZ4=w'l Rbe73 GCK Z BhIA TSaѩP/q!wyʥ2S\ %0}Nmg?$Wm~g㵫xB`#ӨE:BgaU$P9$RYnݴ3n ( l8c"p}EUZMGd>Y"!K^b.+X\,F4@4%&2=XE*< Co\fO ~Tzë[N `4ID|`HYu `w6s·UP~{F#;H=+Ɓ9j+=h'K𰱳(Vs=?Xd_uϮ/^g>Ng(QDx爍w./;4_yqәp?+UFQxxٹ/Έyސ\,ʛZ +:n|~Z5{7lޭ4`8@Ȟ~{'>/߼g'wwڭdN.Ӏl|:~s(7~?$vgP[ LUjר%$K's`$}iк77D#*Bm vq,ĩ傚&sJS%Q)6N8(%XdT(΋k`CPɝ ddBcY60vwxɈW|.=F: u@‰FYǥP#zcbC g7cG`\lTrD y cY$-ƠK !b cd5Z1jAYidTb46G!*Y${t:w"F@cV2{ FB]q,]dR3Rn(9ӗrXlU" J,2֐t z\ɓm IDATeIgUK".RzΩ b4<.4@b4b4M(0)NѲuLg[ v6-CX8 b?U8ߎHG :F#=H FSiT_j`DSRJ?`&t\8 6 G]m<CF 5dA#Z䢶Xļ21v,4iJJp6w|bm> ZhPh"4aXq OKt塑K3옔z4t\ޕ95~r` ^ R*QaQ{adߘt `f&ٮ#-cTpb1c [;z#K;fֺp[+T6ZA/2/?o7l+ENWog?tR KXiܬ/G=Է>hԪ跱R[.Y~?#sח>٣>Gx;N8e\:^&ү7vPl.Է|Ɗ9J V[{a7s_;:~;..>?eO{UY8yYa*%5zzkQwdI F:s'Zs _ל$qšhOEd-MyOjLTIHTFh`!Cq8DO (/Kw4C殯ѡ wQdE .Oŧ& RNO! 13͠%9ԫ IA婃rP1Ͱ!:B;u" F B C/]EOvqd'H$<:}ؗ(ͪwVQ4aDuIpL) (CwF (SD i^L-@t ٸ=j mo2|!TK[zNl>Gsin083&Ut*Qռ_inniK I,`Ƿj. $4p6A1 ww)5O|1cyVٟ\Q=|&"ﲄP;c M!yj"닯GQo$gz՚{fe+ ;@&"54-;c c<13{(w7@5+Z}]3htU ny{E~z}b4gӶeZ[" g3`߹+#ngSݽRo9fXCI^NLKH$cHڌQbReFu!F"_$_ #W Kq:GVc@f)Fk\D R/Du{2sq*0DVS_#㔓XJ }Acm1.n?D:LMcd΋'OJcsS7[;k Е:3~kZڦn|(e{e knii1v^7RqTJU']*Ir f}D`j m5y:\ ,gt n,a h$q^$=D-Q#&-r=7l|,Pe%.*L*}1j ]=x(kog{fz0Q Sp,D$0z| .#0JM.'v##s/!y4d#MB,PAK7lœ'Nuid,Y6 Lz?u".Si`X~ U^vɻ ǣfl^MTшjڟvqLh{)Xpp\"rl0 up,i9SVsv\-KWf/zͨm(/ gVG7Ieߝw8TĨ+|4{)7q'; #j0`"KG~fmuIÎNZ J9 E;)3Tz+uFGVb":~nxcl׫"ho6hiueq_j=SvoyꃧuiAvFe0k5y2CcSsvskei}mel­[~*{{o#hx`vyZf2g?. `x1  ٜ8Id IǀEao>@;=l^gUHITA \RIfU-&1ft?g xW'rO׳d,~S^[ |i9C#0[^xٽeOǿf``}Lϔɐ0*93qQ'óiE󤁯G>εґ\_׉`KZ J hxʴ P#ԩԭy,XX iH~n@c^cҸ> _0V>hgUF:ʘ4H.UyМˆIx<)1J{NeD8]w@,s'-_:7UyÁWda_5,χhz8_mџk:!!hjKύRJ[ 櫇 0/-T)lf,u+OKϞtqу=ĝ?J<2unʹsLGFw)ֱ6`RLsu'sNI@[d EH, .Vdd9ˁ=$)8zq oHdg`.32!i=ޮFLj#'~4|SBn4180H4+Бݾ~FӬ՛XFopx~ Kӊ})Pg$Ng/󯴷;HzEGcAM@M-ʨC߼#y>Кt&YBds)=r8`zhf#ytRE1>b0fsâR#E/*%rP)hy9]6D\i,#Bѱڒ0e&.셃v}{ѳۿi wPk@8)zy^h%, Iי: _]0´ehL'IrJpVn\;-ݨ.ml=/}y{kdq Zv{- Fϒ"S%Y,8PzRJ^4@Gvs[3|fyi:@l1ĝoKFx`@5FAUX6v&&ȡ-ٵKӀ*Qq\0=H k8LOBLa ]Xg`e}3I3-/Ѯ,L_~wF{a |&8rG1Vw8Qt3H!&.z4YmNL,n E{W&t]&mְ&r0 I/T N ,N] K~XP]^uʼnB,}$A 7(m@BZfτ͍̅f.=ޣ#8J{9Kv#ܙU !WLxĩdT/)DS̠./%L1ׯbދf/߄ŔڲED*W%SK_& RAT)@ 1z'J K⡮+ ~GhfާL'ڐgki>bk/y_"U'3P\LAPٹVgp3O$ |-䣆Rxt_3he w#?2èh@1c˛ '!c~"*-\N]͍8GI{8c )6Xo bʳ/~1.CDvut`k@Jԑ*EH[ j@a]'J&@=i]qW3G qF>y +O?yT_x2tK3%Ԁqs|3,^uKi1&J g1җ nD&.z`EJ$oLQKTõu ؀]),0O@$g qϹiX(A{ 9$WArvp 8Iz5(Lv( iJ9ʛf:Q˗ mME7U.P6;:=J{k;_.kc~) B2˷d3v6_4_www%9P?xiggsku;ܽ^~zk˟mowB?Yc#\[gfj*lASĐ(j_'ucQWo؅r;Ey_[#<y*C6441m= *PCFܣC1 ': ޗCHIb2@Jɳ5%GD?|o|>t;10BU¸tƵ'i7⯢VH9mnN4 1bvGkdR?evEl!AyB?Zπ^rf$y1]G,AERr,Ba Z)n(6odhLƵ5CUo $fQ rba[ Z׺/N0 B 1) 2U`jB5yaXlwϨ+*TWu=4-dLcGsRUy_*Ҕh(^^՗aBB`"q'=$DF$ſNanyH,Y h]aPT*%%|b8 NKg`m j-da73l7fssjVIxif[˧]D!ٞ%V @vE%LDF`4/ ui[<[}&A@l]MmE:$fm<7b.Ex t> rk34N0a =n1M;$hʰw}p, JS-.A (R[,omuV]A/TV a*AdDѣ:V_eImr~΁[WzO:^цӝ*v#؍|\̕3;Z&yH1={6; sn+{ۗf*GMʛ;<6ʾ~tn7 +#/r7Zk[Oww3Óo~ٯV!@672xJ:*R~[͕+Oe[_P!7?jtRݣAkQ/:vy*-D-MA=ڥ오w:FLJneQ#P,#ZErʥm"勀ϪLjF7odIp"?ܭۑs h( t r!:nxpsk=`a>}~?G@CKNW H@Fk"/0S= XxNă9)k2l#,=BKMJ:fȇ*qZ(BGKN)W5 4=4$^@dvFK%:8,З=(kBZ{ y] ]F/D A#N'UUD :1H?Tf#ӊV#I*k/Zb:2S,nrРKgqb$^&!$ַ˹ E4Z9qMAGrW&zMZ[zfGL̑:+ѡ"1bF'gCl*oj~gDP4먖&GCG~e]~dpxnt~%w40 #CCX-f/\l7kKOXY^W~v׾}J=zyxH*[`6=;?ws\ԫ 7߸G=inWʓ7~䴹`y|:GA ⺏{!RjusH*؅>r#v B-$J` 蜘 |3MRfdI@_k6%ٕ=h@&""}u\˕cYu좵(3VWH5t@vy{_g' ~-޹`Bnp]&aPJ{!!M Ms$ðmkb9c;\*ed ,8Ql &: Ƴ:, v@S὇˱[mӣ&7Gj KFyg4gD6p7˰Py9^ _:'LҶGr #4|խeVaӂI&hc" %ιNY=4x#~{Ee_O2E}^&>xjà m:1CzuavZۮ22Rﷺmn H09q|_*]X]k+̜bHEBa:촳 x!nmlo{_<3#?Ο~UtNKcu޸򢺃ʨ)Œrn9j>ogv'`-vF}U(} $+z2ݿ8$t@BRxlU&攦g"ى,0Pf" V}>Ͽ:K$VKV8F&QS[7 )$nwS]@W  )x@,x׾󍃞ipu}Ժ6񶟭LLOf0M9k;'8;_ڠ]3I3h6SH@0geBAуo1Ȕ bbԢX bf@[fJW9k2J>9cP7{8=zV*.^M^Ϗ5'dQ[!+Sg:R n|V}c__=[i. ӧ(~2h,l|U,ن@t'N~m`$-p'ddJЅ\&qӖɂǟ=]rf&kŗhg_Aƃ=bRxT8 Ts+$F,x@cx<$B/D:}ɐ_¸NAG:mQZ/i2h.%g2w!a3 "B?1W™'G=?ԡ05jkM8)R" m *T RHNӹ`l 6KBA&Wv*58R%G˨Na.[qaӪɄ¨cdp,+cq͢,j [M '@n6aJ`D͛B勑$@ǗzF1gP_N.\d5 'a/VacfXGX0K44g\02(GnlIqܲ4otWO`G]ٮ5&&*nm jwZSa#P~t#]uO^3([͔ߺ:VX{t thdhm{VƓ=ҹ6WXz 67KţOVn^?z흯~vwuuuyirn[o`C:[ t}uuog_|֋=G|_ʓ<͵z>7^|Wha `@ qr1'=*yYT$h $:pXQYĤ욣بg@L6dHcX˄s(JLv>Ec#!Fw2_una\HdnD 80l/\ s`2J\o~͇-fqj%H"Y{NS `;zǨٲ[>8a<.GO:W&u~H$zן%s&#걢BqnF!9XA):Cȓ?ډBhx)\{@yoV gA(c4r $XDZ{h~Q)Շ-$d^H$ejc`" %aF 5"3®1IJkuiT@ V08|HOx)_6i4 &zH<#jKAzvUFy$G.O_+Ma@|CR[%yԑݲ`:wxT=_T/!jͧo|Ǩx4JQt$#)" Ӿr?'I8)haūOap]ad'Rj\KFogjodJ[~n8( K OL1c6?1\DIC,tkT&|`&w|ԛfZw-Mi) Xm \\G6P/A PzS*N O'.RcBPO1$x"\эYS"\k;m.η` 5mg=r=۬i \\;أ>(~'x4b:t'0=t\X=T*TosA'Ltڭ\:u'sE?_o2X ˽S 7_|֩z-SnH"lX$ZQ[ ͟λk>yJe;ϋn=]Uگ|{fss~gL;)w{>’~|~ cً7F #[봂*qraqꘕY̗@[&C'H:G2{De`-mF7DVlp,/cs6cE8j%d&dGG,4<'_Bnr~OB ao5&'rǝھИ= $ye8(P@rsƑ (JtL"0 fIn{ĭ8d%p::SU0ZFYbhԳNг~z*x4\9C"Yt;'z6ƵxXO 00!\sZagE8Tb  =WWa#.:zFZP%Rby,KCCnoϡ +FH`(U)`OVLMJg}gWGsÅႮ(X{ (v`h:2o ;iך+zpC|Hq(8&F+6Q)wHuHfÁJۗ򵵽*3xQb(Tj6VcS0>=35T.>b}>xmT2˝Շx4Ns.O͜{~/.БxǟY|wZ}GHyKT~ymsknjiCJ>Dx:R&8m7,K*_pOcT諢wTI 4zA]y, ?E3n9֢b]F1KYAr|X$NPPn~(~t|wkKm0Dc|*U%ogPa?)d ~:ߤrY']@( Sҽ8#-`P|<$|@9 F Ucssf7+GaDѤH&/uDPJ y)(LbQJ2 o[|^.dشY\DۼL0}d<*1gāv\!>ä1!,=8KrPw45N?[<j"} pNʇ9-c1E/lk`[@8_# rlAazpHB3Q<\3ogM4?{_)N-mW: ~ ܈5 yɈLTj # &1XIN"<ݪF($)+̀DtHjaR_Fi.S;{rX1G={lVk͇?W2eG [%LXPʛĽ\0?Ky| G|#1؜"mQGj:J~jLga(64oI !udlc`)S ^?11:$Z S*%;)t# <NofA0|pǐ& bqlj6W؅/Bɽ_yk~%`Wo?_3'+_g l.7XSGf_,bwmǔKRy2uZ)lZ2?\/,! XbS,trO8]hyRR9}8p_F.J^౤Ӯ6ΎK F#NuzS?ҝ;k=P&@gUZpdo(|RqRv\]ŏ6P9y~p\XO)$%90/jBIb-cL&Fw&wG߼[]?8z|_Ly7?lVOwjNN23*O6Nr0]mcM `VijE> &bV9xLD A8zfFVj̳c?t",+5_`b)[ȃ#z'7Ij"?a.DD@pto};'` Ld*驹]IdM46r`$PҘ4^@Du5 +Z(Qh\zf6 փf)H QC5=`-B")&>^|D\m O#u4.ο`1yqkh>vs1~yCnceRUF8+yxْ}0ӓך/Ea?ugt IE) 7n)(M6`?Hdjrฦ08q4] nif<`gB'U(U!lWv6tHpmĞrۺfه2ҟ8EBK]q ;z|u/O^n|FPacD>a (xͤ)<]mS( Bz (Y:xb&Zޠ!᠑9[a;IKgECuT6-Ȕ$$϶K p#{›Q( F5M?+&d*baΖ"Ah"XD5pn9~n=H*s1 yhCHȮ1{ݎ M&5 : IwsRSy9B+vkBS;o9wUN@}/\yu̝ *ãQv039ɓm2>=7=;Oo{?o|稵~[~֝/~ÿ<)Ύ]1sH7+O>}<\x~o &p/N'TSwh_Xr_B Wӕȟce>u{ y M{S+Y|=,aQlqOGm$S3:HR\^ku%$cLym3Cx=^?!g/Щ?8HH"CfusCԜ'ۗF6!ãO:5;O_ $ـ13 ;ϗKCLCӇhG!dxrj$* >wj"F`jP >j@l,;.pw%nJ(@`>ӺQ')SV9rxR0hmRe_+#-L@QwVt#$+ Ovmg{UI􃎨5KY9dZYHTJ́Kuz}|omO C;1ڈ8E{O'57w `Dpz0hb ("ߒs_€3B BL/'EX-*ru]vM|hQ$ޑ26\{lR?n' W޻7^0Ø7CD& : ƞu_jp)Y68j{ڢJTL؊ۈ*>ʎt xX40`D#en;p9Q7 a)R]༯Cܣ2>:8Տ@k0pC];*X"EgCqETuH D`:mъdpz=]Y 1A! Q+\yk6N_swcNz5}nMW+a_ݪ?'d eH&槆Uk8K cѱ"c]Lj(s=Kln3k_g=_sq{~de]ЯH駿\{G'KC흍Fg_swseOc5z囯kV&lm6*a:[2?€J̯7hMĆ.=͗zBBS#{ƶ[;1 |Q%NGM~] H%T![*uPj( ܿM6~KмdO O:YLޏd㣢ID ]/0gcDŽ8gKjP8/{[ojo4)$p/fIī0}p65VJ5ڗ~|Z[{?URqP301>d8^fHL Rd.|/gܹ}TLtᔕv۩=$-!Us60PHfNF[}"3%@()zg9z,SD*9GqM99`B8 `W/aCmaj1óɐ=J\,F R7Ħ栠b:g'*)\N8ɤ KU^ޏ_-Zߞ{ga, 1ո"܀S,(Y=(Ux&/?Tqƛ.iĩhTTr2I@ m%|, v0@/*泭F_ Ƃ>L:ad"b!b-pJk5I)%;]#xEFu%cOblIPA2\BžL4q*, RW4w3Dl3%7iN zzY-$˰(Xl&U.AJRPO, }Oyˆ$KVԊ'+%^t4gG*VJ!d7mu FPZv^o}XjpyucfjVڭs s]̕vuZ= o+dx47?;Ǭf(囯k/lemkoL~vdagt7?ƃ>\o4 u;P7W6g/%Ҥ˗ø5Zs w/.<>|Fdv~(VCa+%nڹHh\V'y>z8F29;%#a@⟘QldkΊ2) _F^}G;aT4Q+<_xcFI.,)<ݩnc !6Q(N2/!M73**B5d9׋fKcd{,7;#v:t<I(eg,Ġҗ \:}d4Ho}`ƠLBўk@ Uqn3lEZ]=~nU&/Wd`A`1:s2nb"7Yݺ5w={ҁtB˅=y;WOJ3Jlt?݊bOx0E☄hGB5FXG#]eښ=~%f#Q[°%\_ z #۵qh,/|I*C 2ŢGDkټ'r76ġaTH(#!fW1hsyڢ'oe'װYI L,Gs dv"++0a|*b/e>9tQ^IHN::FW:+zAG :ެ;(iVu-';mCt -sX̊pϸt1#S>rOr|.mrkTʤTMԖj3=ϋenw_tj<;!DuE?cD =!3ST~U(V4ҹ eOrܬE .#ry8ge=gF@ϑצ= [C'd#e&MId@.khD*Kᄉ35+,4DF*(w3zsA&ϴTtqdv*=/SS`MX֓!'12ܑLD2pNtR w659D1Պ,R fi/wZ#ꍆc AŰ/)=K#+W{}z$S~ag~w!{@酀Tw^<^~b:Ztx4((ԏd._6>=0e iA?g[2dǴAШ"*0QI& ZACk bCjKX10k+$o \ 5:W\$2i75w1Px"Vj[cx><< oX2 gv@1˻DJ% !uܐZ^c8*XXh!NҌ JԖhL1oe0aPB'Mi4%0Pނɻ/nڗBV/60{oIv4#)t,Z2cecYbм@sX}/7g lUR=^'yh}Z|.h@jJ+|1I"6׶%$жκĎ+,]jFYAp<M* 1rGȋy3AM!r` WNXLCuM#LbT(yg!lLb豈E^DAV;!5O y !*jf%{o%z?1oM8 ލJ/567|BåJ?硱_4Q.'«0hg8057\c{LoP_|ϟ؞p.vDϟ.U[[oړ/?_b01;EL߭0*m x,e66J2FU;p१[k/sP͒bk=:"YXJًZ ˢ\6<coZ(;l242Mt!?բL8hExLwrRFp%p__qhQ#0 fNd@_Nc`1TӚՊI9inxu m,6gKrm<~{w&i*Myd>ĵسIe{A]Vx}:ؤ/ x~7I]YEnrЪ`O6}qQ!?, ҫDJ-1x}\Շ*-"L)$$cs(B(̵ ?+cǻ;ľXp&7(38r?g=u_2#4%II5ζ^Eﰱ?_Ҏ .wzʅ_fePVH};N ^!zJX Hi*whBJDD2}B_Ql+1ep`t*cX<%4TB΃" ř]xO۫}ތFz4A3w ϔO`6]pˋ{$PQ njO: Ю"z`X7,6‰ULѪW'4&l-' 'jj*W3w9ɬ(LQZcb2)(x87C'4b4D}Bi?7NTtXܘ➯5R7Ӗq֩4 v6UN\8?9kE"<3aW+#CX5 Xy{[V`rfǝ=Ϝ[#;_ղ+_|&K#O>YxHeC87xsa{|qykַk6[.xlHnDwtb+Ns7?xxlhtd|x޹j&_]ZzԪ60:5/f|qZkW֔kv>p7p $$ yUV<fL hJA"62hM/-"]DNxnwVyl!W)8[mEMC8$:0Q"Z4OZ-ӄ,>Yf| P/^֖b#|zd̶mCq扃P^ʛ'mcqw#PR1Fkҋ/ (4NZ*qZQ"3&.2ȂE)W8rFQ⥴W)H*M<6ZBPD%яBj&_gȧ!Nи76-RcBgP9\IL+W27oTO~". MYb8~,U\?D:JŤ; ّ\A"攺M=z684{JB24sGWo0`+ͼ8`baJbs(CITkqzrt ڡfƝPF PPf_8@Afb գvhZ£aƑ$&~2!|?bSX@:lUBeԋsbguLQV 'pblsޙHh$9S*L+,Le S-LHud}˷Q/jhNhSbtY\9Ņс^cmd\scjh"-́)kӠ-tlz٧?zosy׾~w^w;S͏~d'/;?xz\X?zհxR~œjX.,\v_|0?KvkMt@ztzp2CXF?So%Wze H";ə¹RoQoaU#?3/}!DpT7KERz@٩(4HK^/?u0Be(mRM kZ 5"b th@fϪ|/f^Hh u  vMjQq1v5`;6D/#1d^HOu05="ViȆZP=1|;uz7wCJ.WgΓB/MM/{zf\a\c Rt͔dFPY2e kSǤ2]+Vկn>I> Ǔצ\h`IR-v̱LP鮅& s>ȫH wmXF)BE%lmU&w3}_[>zXZ ޮf ;1iK9^1z4هR.k ."@L"*QEt1 r?RRnywW SD(uwm=ăū$CY6Y2g]N\!jx'r2R݃|AtTK QWCXi5I!ߚBI'9_rmڵ_5oSyoݹ\5y[vn}#c/^^^W%с>%`oG{;˘C.^Z<'SgsDxAȇN&h8_8ȓr%FF6B$OwY:xp+/e~o;5K֮6FZ˦&s%`S=G=P` K.wZEE89[R` F L Oet wyqY($b֑Ơε"cgQdM鳬WۼTTmJ@Q͉uavb+fc,i:0)U%utJn=-G`RZ{ ۠TEmCq$I6+/v3yFAr/q5eId4km&jp'V'E.xI`&R.gmKgYPb0:`8e;܉ F.{ƽ~ѩGrmaWSqd!vb/l|9wTX]G?FnGx4zzgFA7֞,!c{Wl`TMjZBPԵxN 6\Dmf D{f}dB)Gyc~Q.*Hjζ V06BSٲ@1bYw?Z{ҥᖿWرZ&an$Fɢk)E =s_"5UM PSk$__a{f7=l7)*ѶHŧ6'@j\qaZq/}1Ř׬-:UưHŢ`<ƼDl&lDlN; [,3%TC871$`44'Tۦ}. [/}V֋ͦ`AC#8AI{rJ!]$&8U}ǰ-p7W/UP+Qk{d,PWkue' əu~b(rU3@K ӧ.S}_y(ީxڛG;djƛ615q_<ƹ3t?e0O=|rltltogoaurj2X[,Ήѡl ^_&3p56Y=@ P &D0 >~ۧi}w3n2fI& d3\ Ka`S+IҶٶ Qho—P]NۅiLæG(D$L@rO`ڪ$Ej3#]!z6WN̝p Nr= u03pe8ӣ.Y[]˜~d1 Ugr˛1 wư.%f] F=Gb۷Q& +xּJ^G me5R}y(D򙕊 `(=S)d/*";M\VAi/L͜-%Qc: Zd#ُ9% W?fJh)捔ס" [J*;QZ-<+[)]5xS2zS@J#b7 i7 藒2`]}3:giOߔ;1 'Q"1)gq4գ>z瓧h,Uw^Oww8IjңͽXMp{5, #b. [%(BF55ŧ{FIC7P ? `9^^2}e? BTӈc¨U#sV lebfoDf;G? E#c<;O uW!f &wjTI|+Uk9ōD@, =ʛh65yL T"[^D=uk- !#r$a 5),$Z8En j $< 6?BB0@FkK5yўAU#r348rqmP5y7}ryk3,'փ N'"E'M|xYЈ/ gkC2`tzdp(Q:X*8vJ% CY@AdY *Kra;Mʩcw<ST\M66GR{5-(&!KOv)L5RPe9(̨Y<% vXJ&! +tNU CDN$ȁ7INBo.D*8V[ ũ%.ӆclyJ(X72^vJ(#'-bH%YFzeq- ?(dWZ{śVkLZ\H)΅vr'lBOC](m;~*XrCzHT|C7FZ#bئt# "k+uB.:Pn3Z42ˊ?IOy&^,P P'.Eod y,h yB) \δ'7oDڥzITcNi=r]5RځhPXĚkUQͅYGN(G:aػ4lJRr_UW)O$wv E@<8!CdPC@1tPumtQuVEiEմ^9kPFOF>Xw:9@nCS3#,YS1j7M周XH)ZH>1Vl 荽.:G>;E$:m2fe Cq8ߞ M'bɝ };wj+T%op'z!292`گP$j0: REX4ap7!HÑëH b@4vZFJ iaB9iPAg@}1uԺzW爴6dǂ(I F E-!V< o864T+s2C7  `jOi7: \^o(f %HfT1;/L|nE;K\͕nU"К@ @M!kWc2 m6e6< Ait5ՠeYW͔p,~%ps)AzLSW[\كیu&pJ|@X`hNyoj; uӸiBI-):Y3 =:j6 17DAj^Z|gg˙ my0h:1_{'pLjFEw4k'ɮ}|Vۢhd4 6WI*ּa?L}&[1NOc*Hpp/Pni1hRc7X^|2W4a3JC)WVfK頧 E"$rS!McV rխR jF(̠ 1UTE/F04a֧F )V;F-s@T4~X^2&T~O!Xn3(X`(UJNw\E x%ܱNcGt5:j/o,2X:şm;P 4 6Q_/MUZZ0D8*oe 33Liiik?DM:0{4p:=<\1偁kQܞ_gZ3o$R=Xi//=bʴ'7[x$^yxv$<91ۗJc,GʩYȍŕݗl<{$3t+ TOGiļ$$vp^~?uS ^ץ/6v4:25O(R:՝d|C\w%\0f7Ri*z0p!yE7Z 7txp&Z,C bKivK9" (4bKjVH:@M35 '0C#S6+~Eu A#)> |:*J)Lc48)r5w7uw}C^)cfM*2)զqjޝ8?=sMfT& )rQx0.%POc$x]P6wnfE@ւe»-92DH)% lXϵF#'S:ЗmVN ,PTЎ~BkF a#*!§ kgUiBi$1J|Z!4(OXʎMU.2Ă^hxp3xړ$\~/LacMʾTIk[Cyj jqf"]cTxow׊ !Hg;;wK`6[ss{\% t=l(!O,7p HŋGL-/Dt=U~*HdcI0tXq$t]!̚@QIpԤk NO6Ckh~ K n툻Iu;on29uR+:k '; zS'䦃QBE c `bT<(3{2m3#?l3aiqz]g\UrK6s1V( tbHT9k5{Lj$w b_, DP3Ɣ4AmE ETs}R._yt:ݒT笺ERǺ;T̬@[`L^2FCxhP)ZpL DE6,xj 7S*W@bĭ0k!Z,[Bk\44Tpܑ"TW=_|.G0c=_Ϭs<,TR=&s>8~8}ȩ%kJ@+#)>Jz3ړQrE,@MZN EEYV-c pl/!9d謼l;#*;1Rk5 ؾ$ǂ~ZL/JB3HIU\BR"C1wdH`8u#hdeTL"TZrflNKeՏ UqU}mY B]W$CdJeeVj7nf\PT)%IE)߬PMɗO\Amu SrOy!b0وtPAvYUubP.2R2QFj4eyEjE'pKACIqbwO2 |KTZC⬆pGg7,DaX;4]`5?^z?(Ug_ڹKl,/_|[Ͻ'O/?Y?/Åb35;H&v #|^:[JN:w=c0GOv7NF16[-WN%00{D$ _+>#1:=ufqb }Q K%q1@#e8)[dV1 z|U.(䎔>dNҴTOr/GaOb-i_:_p^bqR3> ɒԡ,d_\ ,-Q2&хhFcUNG `Dc$ L.#& G à!@]7>x,!8-͐NlACS lyH,%:W$]NK!WR""iRnxSbpY i4rg"NOsRϊIDrO0$Ѱvʅ8ʂ QvD^q3 up JobLa$K+c w `%ݛS>353U45Exd'@aЇ ԰vUQj\i/sCjSJ1(.~j8Qd4 x6(o1D^t֜pKȅ#nBJw/ HE?L2u=!8 OG,Ert:7$+4\\nj=;ݛ4ƞXd`56USPEbj za&Nz$2vsk? 3ESDmx4-;dtF@Uv/V2qK#>5ELTV]б$zp^ xSsJ@obDRx µI#PsK4< !/'H )щܨ*;o>%7- B#yBtAT7 ?9*mc)`i,yCI|t oBoߎDZn{.ש$73 !p0kZ/!>>y*9 -n{A?fHo"(+1Y`+J]t#.Qh<?w^llnӈO>miPA}-fCQ[2/mۀ2,&5#RZ+`cHj#Xq$xZx/Ra!Bb3iNjYUU#4c\B7=߇WewJY#FЍc^,Jq(|f2V*yի6gsqf3M \n88No߮V͖\EswgR Sj`nm L_>}wZ׿;w?QcoKo+/}ϻJų[Or'_9[lsSeofQԙ RvJel 5@pHtMbAA7auGi)}/C ujj|z]I-%+ 6IE6듉R!LR%IS`IiY49(̹>VbԑklA#d0ZjPx^5|f tNNzO'4ysu0!u >SZήYuB)aknBQn{him>Ͽ0o Pjd#hOg+k\XbH&I(XخZkCڝbIDS +tZ,XUf:w$KwfY8J(>w[t=w֘& ͆[F,尗uKK9I>'*/KH¥l]'{P37kYv\-K2P{: d%JuƍGuMF4 ;~)ͮԦa+yJHKE{hڈ Pmd/ Xy02$v}M6^A0>/N;8VPG„j@)ZNITIjd@:2l!ό.M%& t7 } EJ1꘢ oZl3 NĽ[ŜzAD>AD$/^O0(jggO_n?5{vf$Ϳ;n݅e{xWvRC[[ҍF&NTvާkU&'={tu?_C:C33dI`7؏-ln|jNkinum/yD\Sc~|ޛtYm'O19yR<Z걧I Y 3 IDATI. 5s>=Yֺz- ̍&;U}ݲKg+ʛ52i7K[dHZ Ƞ*F}DHK"@aԋજX۩҆DiLK.2w QƸ<*.iL''a$0v4Y¶4w˩5c d 筭7FJi*ThaXď-Kygg|3qoh'6 4xcU -TLy&D>Rqf%S=ll<||8V#OAK-.3YXvL_>||{ T5]ƪp9[ɡv{0PQ'iV&vlz]77edpd맵 kALҦb dFYwZx?)S(&i1 EW28B &^Nb>_CbT8G;3WI(Y\VuDOb͉AT'j (3(O,L x 5JXI$}M<;țq"xQ LϐcP]r]B&Xw2x֧8F(mie' MQv _a-:#{{QU ΐlæpJoQ#vT^ L$/"&}-rCbAfkfB{b ]@l:ʘk2Sk.^wz{7??8:Ośo}ټ˿;دTZ׿~;ϞlD{n->oO9wͽ]Nɳ._Yz-6f&=g wwv=nsɱSStodg90՗v/S%R _HHe X(W!-6u䷩b]~[ `pu|8d.M\t]\ˢXF q([Q3Mk _ i@M>4;6a ۡ|o׾zHa @B$ޗ}.&-V+T Y<6fQ:tB q'Ywj 'st dQ$Z_4TG7OQ0J@ۑ^_C3ޞ OrB bz.>UOi1ސ뭄W,DV&a{Ǎ6Af#\ݟ[Z'w:LD7T+vB&EMmnWS.x_P˩+ͺFϖ3䑐| &RVA.OgIk9f-Q\ܙ.bjA3Qh 2<)?/)1ELm?Xڮ:]nABYȧ±(JP!nqH?hD/ei^_WT0@}#$&V039! B Y(;EPiWpQoBY4PuVD1+G${FP[gΈу3G~s&TA'~IQ0*)@M:FwN-O?8Ӕr2b•kO^s?xDTkCi5jVFAXSt zK3b[ uΕ(PVӸ fC1k&% _z午9-*oM.~uoi}SܳhUo{݅tz{|>)T<<7{zS,H^a~if/KKgo76vcWM ;q,RˏԅKLXY\+i KɬO]s_K&_}44z"ml 1zsy>WϾ뿾M.%'8 K 2{&Aam:!Mtl+.LGыF[Ya򷛘fBBMq j/ Kv%9I[G;]}ݡRV1!P\rQ.Œl;5KStv3>8+}cTחaÅf.t u\ B[FVPsk2Vuh*4'۝zPMzQFΝHzvQ1t)4KCrs!%:Rj`u]U0P 4yHfKի4•eUPYG6Ĥղ/ՀV xOM}^XMh8tJqjVD9a!}MkѬimO[o:~6έfU݉}g]:8'&Ibnde|3#Ub .BOXfL\ϳ:Cjc`?!P;8BpESH0|А I>rR!`P׌@,BU5HoBt:hk 3kا[5Y E325 @dmMK[?}7tsC;tpTJ OK{=/$ONfe?ޠUp~{o}xϙMk_swBL<қߦam~T$Ư'Z~~30:=;L1쳱\yUtC!ѝd6 퐹:{O٫_?뗟uou{e75Z<7B*:;[~!5BkG@4p"F.f/im m8SIc^56^J*4pdv*[31/rN);(/.O\8u `_&Oz0*N]qz@x9 UZI*{8@bv*H*?Ojn!F񳌪w:); ޢQjҮZSeZ6CdԅP7&c Ag*58f7JE:-["SjQKVm]6@Z\m[p`F/CEv0BcI8Nug2.]UH g#iƆ|SgG"8Rk b=(?^\];2( E 0\Em0S'g&\%*c!+jz7FpHhab'Ɣ%@Z(Cn*P)KSVzou;!aSǫ8VJٶeek"c^X̧V_ 1r0 B0l\5ڙ'IyrWy<ٵ\lXOw!eğD_t  uR XB\`m?$>uhlrnx)-] L%' 4qJb`MU~wZ^=(6O6SN*9 +Pyq[ ב 04  1lNR( SDcxW*+WʎL09&NZssvJ~mFZeQʿIqcT0 XnPEYPz^2=1)2Uj @1Vz #-4dž/:USpo -Zf$ۣxG'N1}T!)ݾ7e5q.r:i#>r)h|Y '|vHHջtT@_o6}PdjUE$vg}AHj+M cuSK|tx~14OL"oLDAm:eq⢲o{|zXv] uL.RժULӚs`[މx bB3ۮ*fUTN5>EqL9TpB_W%ᡱV"s 7\ǨT@kΠhc}d$;z<eH=B̰F %pUr"89A[LL'_A$h)"V'礘iԦ"H %_jW28%[|ţLك,#$IwTZZ:+q<71Tf Ϝ**5Qn{lXj߀dT "y\6KΑE)D(-A8< ﰘ=ɀ; jRzzH a))pbBw 0`J0/Xb,EBCAYGXz5*@JZo !rt\a"3^5fe{ltZG~/H=KX砋BՎ@BHřEDlW־^Bu `B$mpXeD@Cج>WS[x!4wJv|`{D>Czə[>{p.5:ÿ8|oD"[d .xig޿wPK7&ƾK/}XxrUɯ2{LYt Z}M==,f$;[|Dhgѹ/5_.I?LeFe-KvBd|smDq4 %c?DbhT*v$9 $,Dww_.?z:{p7FOW| :ա=@ a:xr7cjUo$HbՁjς6}fiN- 1J4LMfJ5$)W(s|S E(5Ok?SZ~Jf}yBIWܿ?@RRTQ\S46Q^R_DWh+y"=5CSQ(}tk뙢xg@BD.ݦl"=+_7)˙7Z;wPvBTy‘D1V֘_ll3%lc Lpjs+]ʢ'pHl!5L yBex%cQ/ 5Y2jisc"FHs󾊛p C'BRv,-T}9x4eW-FX%:"xkm?.OP~J܁9l Mk@<6h+ h2FL  t hM_1}X&5vK>B4WH^m4CKH䮔j ;RaB?x#6IʘLs]W* #@@s풐M=.yTo8>HAj(H Pw)M)ׁw|3Wn,}o~)_'/]v0TnRUؠk/]|<ց=_z;ˏL*^x׾6W>,|/6:9>յRzbj&?xtTj 1xa칑;4-v%Mb}Gsݛ7bd4H837827ǿYw;+8mDj-o'i}92g` S]ON.{jDîH+Gm[uT~`h ヽ\8D@1H7讗X؃g/ҶՕ5r^*,j!tMpU(eTuѰcX̤YVOipSQfk@ul ,̷Uz(#(2)ԧۨY9ɀbqvlHm1 ӡϼ֣W0>hԋpW#FꢯXf% \8%ôQ((TڥHBh[9UinUojlrYPc5U& *F`lĭIݓ*yZ[2ݮ 7UDcYc-Eis0gQQ }N=c4 PBVJnAyJFf}sꓵl|Ka&CVqzCc}npw Y0*A^~jZh5dRR>X׍sMo/LCӂ*Q6R&tk('* G ** XUKY}8/YMOv쀯`,΂/he2)VUQ6X-KJe-`VƁKZM# (7ToJN9׆D6!xQ\9u~'&B͒ * ǡvf sjrz\%a=K2["kN/p[13P~% Q2F)$fea #^ slT= ꁾA ўP40\U%#;Aꀛ '^kZx'`.qn@jr'}r뫟|b-_W9|!/a)֓X{v_/eG\߮o]|Zd'\X[Z:*T_H?U0ힽjp,29(& 1«UVt\ 'd=J;J͎CS|( '` *Si>>1x+ cQSnmʤS`*JY/+X@l67gRpiHU1$@W 2"LUHw =X:;L{Gn੹!6fip{ ahPeR!)fj'FV!d_ښz<>2D ibцd W弼&gO+'{|EJ P`\C9o9>pu2Hcz~/2ѕXO8G( ;Xh;e0h9М"Ykxo:H?iՂ95? y4PATY`δAǕ}[s|lƙpTqNnqmLu~zi:ŭ#,p,GW { A>&p*WF9SÂ!L7zyC2x)fCm)W1*H1Js'|4w2z>~F/ ~Y1OY|T0+F£Jv8 ˉ53P*KZP$0M}S^U3>b6 94YS76)e<,tJn8fZ&y< PR-"=+;vfs-9Sֲ%'ʭ@Tr/a=vh&3$tPB=9kbF'!H^!Tl=bnK\Mh1)m|Q/"k9~Pj+R5P>O4p,7D,H cW([F{4CUkH ˗+e4qj"VN1a89(-J,ڛp4!@S3YYwnkJʦPȄ[H^} L>F=5_[ F^w֟Y[ȕ#<4?\ް) ^/8y—>)*c~Yl<\z1~bbldl{s\jF'ƦO,ܽ Ɛޜ[_A.]rMN\>)1^yǿo{ٳ;^O[?i9\ nB'vЩi,`)bbØZEdN$WU>-z+N$:3ua*TiOtm>G&8MnïZ$ďr^XaUQuSB{84'en̗9@m8xojf6cŚjDji0 1_Ɠׇ :c P׼gkҪ_:= b?xv -ƨg.l&1uЁ0i Ut`S5YpQ-QɊX2CGOw:nyљsѡT=]]h陦"a |R*MPۧ' #T&);~4WD[bC4¿$(!|<۵/3+F2esapި6X2͛I 9a{Tvt48ֈp~d GTJAg^H;9O2hг' \|DCV*|Irۦ? W#3/صkpuإfS}>/xP7&Nmxav{SSw/~Z̽ ? z9lkK(  +%xX;W 7pWBR/V2aVR<߶h.r& :Ns)rs:_qGNZOmӳg*rfihm wP[]4m[\LTٲ$-ɂMmUl8yU8AFMwDH:hn u.B0Bxx{hvvQ2QQѴ"YJXtLXg>IQh'[e 8S2QP.GvVc) */qy3{XiikJ!^lB# 5!o%m2XX&\Ft` چ\K5[/VulYY^ ~[ #Schׄ椢xrgwW\f;  tǑtG4527j~\pN$SYy7ZK#ۇXoeZ ޺߳?ԝvm9ܾ>=\I~TrVl#.b<%rGMgxSYf$4atսҀF'MoEm&G{N*;+ƕq6? D׋/-3K'fWsX[ҰIX;5Z]) $ MV2 0P=/^aރrRJ&^I YGPG'k{_ϳ;XXjeS-\_#) 2@Jq S[榖4 FYcriyQS.> #4MM!I |8Yw$vSUgKCT.Nz鲀8JeyQh^d CF9rD!UL45y.QB`qyjip1mRKi6-XLa5Of,Q\uTĀP ~ A dR+p;#q&2}VO&%%  ѭG$a(Sz?Bp(xYGxd!F©G(5@ k.Wm/\u݀kAMA1E_tU7A9~gȱrfG?_JϽށ*|qۡC{ַf]{Jl$BfxԒB!93zKz?ыSXyP!NLL$owrFQ/b|-ZDeOҞw4Ш m=p*+~#S+gBAsU9i `\N!_gJ,[ 鹹ɩtZhxq',ClذT` IDAT2 tgnɬu><3Ϟ{^g/6*E&@Z„y|U(ĺ?kWzϭ,OOGѽH&CJبV| # P6V.ps̪UՒ4O77`ԧ@gr53^]`K^v/ 95H&tZ`fl,?uX1 7V {7B^kIkjRG+ <(#\: &6xeJ\@Kq*x : L0UTA bc2܁`ʰ,HA}(U((aiq55ZH!\[뚚$*kр#[!̇>Ob0z/j򩅷m! 5"?0乇 mTYK٣Fq6YR`-݁P`u3 ݨ+F:J M5IV!'L _G\87Pg7.^Ŭys׾T-_ُV+峟zcێ>sJmyaffXHdrń?2}#M/,U/}jmOr9_(Ni۹k{'P _lۺ\,;n[bWS7.vM0xL1-=2p{wPܿvэDq>hQi!BHk5[E'hE*mUFL0᳞|Na.kŊ)?@ފzY Z!lMiR<ʲDVRuCĜ7-BxF mDW D 4Fyak{kn9;E#fԝ7a޼7 6KhWLdKF_cwP6}ΎO:, fzXW_ĞKk̉e2& "!MHhԭj'6cLVVb|/C' NHi<[JB+V R0N;j>ri^GcQZCIoPj@yiy솧kdR.Ѩ/\pp1vљ+ӨOK\`Y(C-͝4fH-S4SґU+mΪf._ճd6bEϬ08=t'%KnHD~R8#@ C7ʢ`b1i^:!f_*!f}DQV).b'w&j;رg|rqar2P)]m(7u({\#D@a?. M#w"1bW\ϙT8X3 D]q5Ѥ5"+5i!'>N{5"Mh^gC? Eh!TJg`+I1x~ԐO dRA 9,~\j?WW` H&k1ˀI(W lͲx.ʽ9 s3Nb ^% 32,P&mC1w !W/L($ʃC7\p9psZAxMA`DTrn"\S&F聆_KFVFBO =$\t*IYf?_#գ@Ev\FUTw!j?uȃoO 5|[z"S " Z-=;{r//-{9w߹"Ѭa2mҞF6 \1I'LM8W+IMԍ-b s\Z˩s^*Sr) a(lo#-HN,9yi[Ϩ~}ic*YGPh.-E#lUS(ʘHGEADK˧fvz5*ew_Oji9iC^%Fm[wMF9*ԩ^x! U](ޅ"FU0_d4Q݂آ$XqB. /`6E?Z {ZhR?E+#CfU T۫*xS 1?P,ɟ}^Fv}kO+LDѨ?52-覃ņF+a{A"*7[cpywa=4B8b]1 Q:i-ãò &R-2FZ"`6j>ZLgg2˙,v9N [Id?rʹuBT(ݪskX|*&A|ɫ];{3E F)rfZw4'1=;1|*sAXtZ,>ېg$j:$5M rI'oxkڣ\Pt%}&m#CGrW-|)4}HpfzR͠[ӦB~ eJCZgG}cKh4@2ʗ+h(&eܣD*5׃jnxnX!. e+[M׃I6/u>H{_|7ߞ_N}걍Jn'u-mfz>wi׾9\ԙB_Y.;o;cߺ[$ZW&icd[}'` Vxw‚<ת{vvݺ)=)WpN2%\ǖVG͚|_fKrviqu~iaz1Z`,>C*2$4TCJaMլO"FΩvTt/p޿#+B-ŵESŌgCfZeҕl('  嗲(MccW֘Y_$J&+:&<&o3u7†EqȽGbM,"tPVF"P?cTdC&4Cq͡]g_8ޜ}0^)ӹO>sbeQSrڑ?0oy%}=?z9||RmN$b_yKe9 vl;?z}q"zs^_,GXA.=J Sjh<*X e$\CZzuywnf2 O= 2%G/dHe\a:ޞƂsvsôifW Bɵ*Ǭs>AҤenЦ/l& =uqYXYW5s[{ @<L-4Oy`!Dd2OڶuE: b0MaYB s\#g[Лغ͖2*8r̕ Mޜ8YG%tB⦋vasǽKgyժ=h-HJ&85Ǔ**-F3T yKYv ^N9 FIZ{Eyt#NEj#*4@L ln5f'&" ZU`0W|o?رxޘbh Bkz mĀ~!ˉCeƶĖ1GK=񍈐<P8k..zge~m,vMt'ؐ.z-Tm1iZ[$Tǚ~[,irМM-PFqk(X%zBLr01@(ġI?Gv8XH&z+W1@"'[ ( O*tҷʥT,ra)ʥa @P ˁ?$zU拦؛uy v:V솙a2'_ (cmЭ9%spz9SY] 1.H'ۢojL FʺgY0BUh4$:n K\Nr!ɴɔ&p=JZ,Q:+B3SD7Č%VyFUYoozـýmzJ* $qڔXx=r|]bp怲, EY`H#:ZSV䆆8:@/BNWuP5_8j5Wwɨ84a:tGeCѠ5z7U,gYMQ7N'|@e zGJ]KC7 p6RS~ k5bJ;@k{VbD +Yo#a4#R DGro=7e_Q( DB,YL FX-{ݫ^]&[_ﯗoGJO^.T|dL[s/֎;p&dsGNN=dj Ͻ<F1M-;~<7yWc8H,M-z66YwޡTvBf!2z..Ҫٔ7|^9?r_,eWo]čwCH[̔S+ʊB!Fߘr4\mx4yǭ,?'Z޸ihǁ\H!]'V{/XIQapkj*ـQ-ǭ-. y"hh\ Ȣ0Aۓ|%ZͨNm `|ϓh鮽$bA!2Z BΕeņEƨrW*^D3Z]?O}텣Ϯ}TK`;AEг*R s 8 !ar"\Z$}|@@l>K 9J79qegy XhI4i:>khdErdWX3d^g9gyYx Gp ZBlĥL#,zoYyоQ6/rkJiHM3o'_"T ܗJ猥3 ?)\"b8RI8'_nv s[C48b %]b䉁-}|1DamK /)#Q+W&Wr]4XrY.~j`⥟Z^{9k?CPtltMD*qsT>>}JNMf9FcYb@.:?HgVV3qW\H\IBy%$aCb+%4>63ɴrV$3LТn:szSܹw|v jT{I>&r"]}"4XNnVE khu\*AŦ>Z0/k<:΂AAO%i9`T}Xr<.6Yg{&}ʆHG MOA9ڱw>p|(Ƣ%^kTyx:Ihۤ Q-a,Rw9[]^]坞yUV뎎 ;EG2/n9D=[')}Γg\vܾClR7/=[ð$HTTsPXl`: J \q[Ŏ,TDW^D` m3o^ETzKc(|K' )XWE6m3Ws]h ޗM҃umJNWrb%okAafnjFޕO ZGn~ IDATA.x% xwj$xf Q ?bZVF$`ϭ$ACexxRqUr.(_|̎f.{O> (~t *ڱ7Sښi}`$Qa 6/r[T|\EP7#1&,Q XRC& U9F[+gOs)o,<)8+NMZ^K8ˆ] l P^K:Q0.2h4tHaK@B:7Z->ཙ6_X}7ͰRʨxcϻJ1;`` N`2T@AIP$A\ (L7P #9X 5ktuKaa t-*IۮMO(# wY5K.[i6[[W!|Ԗ)G S9E]nh%66VrXz jJYP`j x m*h_Hb<啩&5h-WoBp*j$L?Aj P-*Hi| 5< eAGc u$aR1S#-,1<ل瓖Nca1dri KC/b yX$G1V+z: l&Gl ͱ7Bk7+jH X!CjǦdCÏcp77t'-z# ?Ա8pho-ڗ W?Zq},Oym YgxncG9|ffWf'>ףwS#$5>tMKR\=so`ׂݻG\/&;֦Jann1\edNo?x`jyzӌƮ~P,m? wLo((Ȝ4ց>OXY^˱,Tei*k 0):uْ4{-8t˷E^#YGT7K׹unh r lh GíI&Kvl~b=#\`i-KU|[Y_$K&Hc"Wp|*QNI˿Dʱ5A4"9ypEMcU@hH[y?$g8]$:[ۻ(*KlL)9#jN.O$A[f=Lç٘&f d,b+4B$XXՉa"p 9^mv% Zcn"oaZee 1F42uOlQmޕX8)i@:==ϪN-/h[5k)T_p޶*ϫAMVa_w/=vY7)ͅsG-G]]z. m$PW+Ǟ{kW 5W[q0S܈ _iT1[pEZe]V _|FsqHY2t$}>85USjѦ|=Nѳ(a^bsуv-Wzu BWҞLI3a8Z-x,%d4b-f *3k GEcB1d}B]q_3EPD  &j@clcr`S%$zƥP>gn{\IfSuv%ǰrcW1)oR;( 2kf #F-VM W*28ubFYRP @e*DB8ZCQ0,ԚId$dA:֩iTS&I<( W8P, Olm蝡KG>73x83S$tE^x)Z,82c?>g3 '_駟w鍷u|Rg_gF"g>폷<{ߞ˿ʡOWS#Éx{ Ho.∏֭8QM:Xky*^:c 炉'F?ٯ51b/!)Wp4.A][r;=43͘UQYh1R%U<0byGqqHB1hxrfc- ȯq5ӂxaO$;0#c<$ƫA3<y 5fQU/LFPCgЕ!p^y m/k,R(-SEJOZsOVPLx1NfccƝ3 W7i=CD:? cL ;V*,یܦ~fУ-h✻.8>4oRr $_0Yvr9[%R?`yגo V,bnrQJ:G%AfTdIl4"8=1c,=.}.ROWI M;Aj ַ Qq{;[}ÇOvgg( 2]0F J-iiBP?|-e䵟p<>PBLL L[aP=G`lp6D[Fۼߌi/6r,K醋Uouy'_ɃV3=Z_UKl1? DcE44Vtgb@cE^ * UTB'(5/osi•}E˒w@쪡2@^A(c(B(qqQQ<[[h^6n72",-SC/"KboK`g.@Jj__0b8#(5G1A KF' Π|[1xJFF:|6ʆj.8jrF`Qm A&w _^[yxe๧g\;ҟYWg/:t6}z޻6y$?x/O<غj%?Kՙ_V79sven" b8SY`X[Yر'?<`dώ[ ݸвeGّ έ#/y/Z?3׎' [d;6zBEM7ܱ;]M/zreh远uF9f6wAS2A%&&&@3GT̳Ձo#Lk 콬^\rz)C}&IE!&\@m֖ CPwa`8D"TH KKURl@ 't g(doӫ;wtl4'fEDK9.SLΝ|Jp!%BD0|F u"cTh"f W R`@C7ˋ?Ed>k,M\bBfTԶ>Tɫdd^<-"*&5Ff]9Ol C6_H\9*=6nc@\vyJ ^SU.[b,8KG&vdIQ.BokYK 'STCaLYuRGo5.jCd ź'!}~о m֘s820jkK Ki~Byp])mxvX߮OTM|GoSlbymYEif+/A nXx`*dj c3+7(A+Ԙo/`7-̺S?lJVr:,ⵔhRQTv!2:[tt\. E G[XXtPkZGF߃V3.n\gތ@$Q>k frn )/kۻ^INijN qq(Rp$ԷЩ`/O Jrnᜟwe } 5Sh#R0Ԫ{3`q ^i@,ݺ̺aK/nՐ2r2e+*vU؂=]6F"KoV6q$#|wwBeK^XGfl?iIg K9I3֌\bҪR&QB&[f8]5ߍwÖh`W&Z/jesŦxGS˫Ʀ-xpVnRػ?)w(L{A {ߑg57`HRS tqtQVw`nXow'7ICc? bvbGUcvaUⴌ/yq!g0KKcu+WSo \E5(l+!@*é1vPh!eGvQ2\ E϶A^ "[x;  CZkKIԦu"4gRS C7- m\*aj:D%ѺAFE_3 3ղCfLAvsUɦ@ޡ^W$ҰB!% i|.F Bd{DJcjPݚj):kF8ab kPeFɑAWycgϝ}aqtlnjiǟ}:57:?66|Nk<тHRʡξ_~}Zs_߽~=.|O}Ź/ }g'GF=timJf۞#}l/ط~号?x<2+!o{\z_ ٽwmii~toێ=cW}&-O<5cr>ŽD.5?/ Gy~$P/f1@J- 3u7vH+VJ,k1e7M'4Rl +(1Q^Ӡo as(i1OXH[ZWӂ@*B%q!x>DըA@< XiA @״ ]xaf-EZl_@ҤBfbɷ2*$L]_L*ԅAvoӺ}^˫kѩWĶMA Dқ(cv*5xڞ#6ޯ1(6ik8yAu*d݁?,.7O]>3WiNkI˦v3HՀ_QI\¶.S2V&XS%Jʥ.Zڏ7+|ކqmb.0O/i=ڄjnal`Q *lbjB猍J E'礇(q:#<_$!>9wHٮ"-DފT4q\D"f|^{@uTQhB‰`tFKCʎ1 ` ATP4CP!Pb=rS8j)T |zA3Q(.uV{"1 [6l;aXd<,Eb">>{KZskye~jjij=Ćlr׉SO^}r/ʛc'8mm{s KvD&$H,xjM..㽻3UpgfF'2ifT?+=-7.ݼ~ [L'Ͻ_}L51wFsŽfC,N>~Թٱ۷Ɓ?ٷDzx,!51HH$7hmeYLskG8ItftU"!5m'b\LŜXWo60:$)!v9xlb{e/fB0& Q!鉏%GQZaa9;aS|( Ik[zoQSu ƒ4)-௔c4BPƛ@u@x'--"66'bx-,t&K,) '2PjrB0M%D8-iAx~,\Ꭿw" !gքѠ{guNtվ' l ʩPxw\b%E3ѷ4쓼Q+W$vaBM=_] S@ci+RO#¤iDAer+D%{wH^ZZ% "{QOc]mJ+K'P\MS=I^FB}m!ކ']ˍe,N嵮`46>:6?3ZI{&G"}@s Lw_xV.we Dג5h֭;{:f"^1yJ_$תXRᑺFf2v-mYUTҥj1]D%݈ Tfc=܃-e,v'`Y|_PmbΎ^ o`914#iILdY - 0x||WXKFԅ#83p1(B!kjԇxאu],]i˙fU [(, -k&EMkB47@ۏs&I`=`ğu:BŜ݁HQG8r0~@ڶ$]p`ae* 5Y*A<[b1slc5?;:75q ٵ6\OfƯ]K͉?&gxco{m-='^xia|dݎ,Bvgw?tTq=z}N*W< sbZXb˦,2L|#=zvܾc_~9u3_^ĕK=ߜ89;ͷyW+d,hɥzq4V߈ FwOߙh'٥Z1UMeMW 6(̙_X`j[B)k3IA&֢iZll1̃ 67y=NuZ%J3BObK|(+$C>HY?ScXp>[IE'V,iF0WyƄBA&I~bKdXTY%(?J`F?zcmFa9ThC 8o΋dƖ(^PR Yx Bˇ61J; V<%?u1=yT+mN ]nZcodN5,yMɯ\ O߅l~&WsM-=t5Ρqԁ|YfM Du+v޲e[Tzr5qT6VO>=l*ܘZZ YԖXhZoэvw}Jt Q3Pl hPdr X]/ͬbow9LȰwKG2IcPݙɵNȋ#z͓Ӷ=*P2=g}M]PՄosG1J{NZm8DdJ~^b5ĉ60l@Cr&jTBwq/^ UT@$z+n_tF#IBm=U ͓zρh9cjyuKJ?o2BZ!A-BYrAvR*l5H#X\&jJ ל)3YH4%ژ3ac¬aeh*8ITP)F4A<'ê}ܦ[C9 a߂mV^ M|JWɴD1_b@&s 6,3HƨXj#dW'+Q"'JѰѴ^H-Aw,<ػ oW׊3s<'GXb؉/fϯtiǾc͍Pgۓr5zT>^qZWC͌J${) NaCF46pSۯKsK<Ŷس_ٱ鶭Wܺ??صt5ֱG\/ܿq3/{/- >̱b6牗&pit5/ ztH )B>2Z,RѬkQ;Yg \|ZgxE)Ǹ22:+#h2jjQZB# KL{V5u>r݄<_FJDE{q͜ݍ\m-zr{aީq(sQ2"VTL5T€iUQ橳Dm<թ%v=Y%FӮl7șĪNA&*W򁊅&,AҪuU2U&sqX pdÍls5wiTnސOzC(5 yS\VtYm3[TCd*SZ~Wvͨ{UQ jgiRq 7fy!e{75Ӧq=\NTwMNJ9L({bmζHήm sILo>RRmfIZ"FdJ@òk|<$[:<9ı._AM%",c4{]+v}79$ߛ`j8 ʤH~8n сw7S|W;*:,P l.h~k֪S5}lʠYhxޮꀰb\.a2az2d\9Nm}Zd6zbe pޭ .*o)*:#W{sZ)9Ar37Qɣp0ԫzbG~#fƉBKm$Ri qT*|h,[mO4 \yfƊZȩYO^зFgzG"yA2گֶ{ɖJsjԹG߻{s/V&Wgbj ] 1_vbom۫5vJimx]K`8tYRN3ƂL{]؈JR>~g#LF Cp>vgr: 55%@P"HxՖqMF6Ȃz'A dJAVs.sa+E-F&6\'dG]zJPZ}!(*N%ߦJs#b݀Ψ#Pk"*,Npq,hgNjT`cE 'zեt*l^wE  ':吗t&r㩐`:,Sk8dhk̽hj $[ԋUila%<%6so4LlG] @UZUQ84.ZsH\vrH'3\BM(CcaM0hܞ- PJ խf` UN)-fTuE 5h5 F-N}l{܉+渴C-bw#΁(V+yДaIVvB[dň %ۘО0jiB/nuf-ۺP-@=TRVZmkg>YiVwI/9^1,͟\Qd Idn C*;OZZZ%T6d*d7e^Ȥ8 ޵&CDf1^mP񀴉d[Qj ^O Ayc& *8a6޺\J"⍠58i(%4B%/ԁ-NaְN;bd8*1a؏@@ ;%ٕ#)pӯ5Y.zP$TSs#PeNS ?WBš!Lj-V2fұH8S.Պo)خwv.2MR{\wu4RNOMo=p;{7~r!Ov=ɷ/ 0$zm?trp[JU<1 =v̎* 6صDö}.޹랝xӯt[%': x  S.̯w?9[ƈ}Cp?]yW;?#vܸs;o,618\Oy|מT0|kMM]laN0ݒ/.{QMd@(?I$e;J5T~\X.eyMTa;(NE̛ҊU*Eӆ\cS6O&T! XâH%e1Lr:X`̼+wm) GKonet:YS8H"BR`_WI\&!i HgA'JG2S嗡wn^&F Cc~W+x5B]Z dy:Nbü446 j$Q˲NxXitU$RY4< :9jH'|(Tr|u;8nilBzȞlA'31˻:Ysx1'P[XCM)w*'v2^4ȏ8+ a}QP:L*b}GHE$,Z򘺐݅Y-6sݙZ ?FP_8Lab_hKEK#T<[.m-E cFmM#o3kХ'K(+wZWR@nrAq=% A!i8v+DD%նɗcK3/zMowPP\$تU1pfФh4WP Nƚgw?9c* Hqx(_j ث*CC)b1H9R͘G> .4TEdVn$yy~s_a|A|=bo ,;ߤ÷xS5ȞA{ 1y;ګҨh& XqL0 }U4hj2UKхQU=IHC"d~VNB3D+Iy Ha"_ufvm'N_O޽/#7R}[ߡ܍Y*#0GyrG?[F?koy3O<ۗ>[\^sX)hD(9;襩mYN?K<x/_w^W_+/~jkGy{)e.[wӣH 3{\*G<΁ IDAT3{g}9Gw\|#XBt].Ą`$}{L\W;3l#hтZ A#Wb0yMj6R尙6B5Vlo~,\GH"PfBRuHS4D QV02]dpk20WU'ɜMPǢo[̸DU![IƄ ,R8aLM榔)GI!1Y sz1T`5o UK U2ft #m*'ID,aPRJڍYx]^K$GU~9[TːgٌfWIPe,0T)YP_PcA8N k'ܴ(i]C]ilEY: GZl<4 J"1wS@$4]Na z a=(T75=Z-W矜,UBLFZJss2, ʉVBC@9A0Jy͈})M֞Z["INR2!Fq~Ӥs֠@10]ܧ3.=^m|Nb8R8 l`9H5؛bpžB#EWũTj֩:K3MFqh`ڪVgs6"-FIc1#ޏ!7HWf@L/M2wZ1WvܙR7rz.k܅[^ cx %{iFvy/Sxב~Z=xgMnazhӧ14GZ}m>5m'l>o9yo/ccS~W/ ѡ-بZhw=}G`WEyÓ۲9 E2o, Hʼn'bsg_VsJʩPa1PВ`Tƃ)9M GM s [HwjbDQFo}R@cY)o@C{gVT/ߨVSf@JP?71vwq&fT=Kz$b?`uc6ajM?ШZ,\=S ԙOO^ki*| " q$0\#=IAKTe;cLpEհ[`hg+ȷ> zI >m)$H0-u֩c':Pӳt&yj@B ȗ:-8D'Oh.:I `)CN+\l[27 U[dfnx8 1nP@1ȜV͘|z2䓷μ/BHs5B3|}t?|? _:v;#O=pßg ~0뾃'N7Jr1SO?¼ûWnKKwzS/N3'^Ζэ7N~7Nt'^jaϽǟ{J+k('y|꥕;SRoeJ]YҏJ,h蒠~&*۶zji  [J({DzS|6W(5JB qQ*DE]t mŽ9u4c:>XK_`mI[PVgO/:fc9i(oL@%VrR@m`(iҾgX$C +0gbULYMQ֛}5R&EYJ'c1c! )61‘-iLqSi<`җۥ~䱭ōr.~W2쭿]gH]{řW rC7f{b>_5W_ oşBg^fyŅ_~\lF}anv Ń4ZLædH  8<o7:7\# ٍИU_>,;3Ǩ4ZG@'NDp5Jtqz؊O,Vq@պ8}.*T`AзjHAE!*VWѷztm^A5-bcЌKoBLmaKIڇW:ؗH&K0%/mitB4O>8O;(䡻Kݜd_ugKZX$;5O0Qmb4R%DX29)S'O'/TnĀ(m~K{<&Mǽ݋9:{K6-|f 4g٤nƣp22Vurte)Z֦(։>LnwS$4;ܧAr8ꋦCx(i&+)5b~nv|Tb۷ZZxfO[%_}p3HnՂ\l\FH X֡7g>UF7h$*C\%szu R}AA'o2I|5$fq ٌM*f'S^RlT0jc~^,Zˣn҄'C06:0!~0YD*NĤG<&o@Z(5ʪRTA@bIWjC?Q_5i4D=JOZ.A$:Bݼjc 5.d4&}p &=ıuņ B"E 2BQ[AI~Tʢa1I.,LAJGr$g`Ѡ r8Sў=nڦ}Bl=č # Y)}ĝGv3/ 9~vg_ͯ䘂ޱ^^{ƥοVi1 FnZ> gttci }mn,.ЮCut瞉w.b/{ӯ|ݟ|oz7x]~CV+k]ڣ#<ŕE1Cr8RhQcG(n`vTL'i1 JCF]4sVv-+Ybl mO_8Y"h\$l97 &-C[; :U9 nznj&c'lm"e:9"=bS3Nl IQ6ntZ U&,52 A@*yPQЛ_괙k|+P*%JͲ@WnJ\Mҹuй"48bHZa&[B/bg+XA + F)"E݇ƕ t7I\Y IaQ41t7ԏ q * n h@UK~3{*Z )aŎ戓)@q{>i%_YSFvϱ:ý&n+iJ`E=;t #L H/}Ļdb8E tF(rW^je3ٹbGji=7:lo+zqƍ=}nDzVV^3c2P6D/њHFia1H8F*˱LICMijҳӶS@amV>Cͪ dg@R[2BCҘ2lS_s..F$I-򙢺*øt89*kt rѿd;Y5ٱSDʈяq83"kJ]8TܝO䈂=)Y,.ku ,dD$ qcD"X2fq&*yj7@9X.ܚ^],TR=NW}`)$+D5#/J{5[TOgiQIҰsȤ]6@[-HH1%^NV 7w,l悛 &S3dؤ.*C[*d(ZsT;;7"1-x2m}L:>Z i8hłHnxXibs?g=50ҏhbp"%dQO4b\q0D1>FT8A}m-'C"F<@y\/Hz(r /!'fQtaV+U& **6KRC*{`+OWSQ![KUl)3PBΆ-qf 8^uH5Ku6Q)|1IQ ոiqT_ƬFП$o uLFÚh!j߮GBcJ|@ɮ;DJB>h8,DjS|{a4: EAz3BhdٔNM^ww]9J|[@KoNd$" l  JsGn '\.7 E U'i@ :z,44P4zop%:ㅅ[<0/6 صx.Bϸ IDAT6ʺ knxzZw+sO?|sxhHzNq,g>)D~k;q3.>?2sᆱޫW;CO܍wv#OMF |KwA8xcGub}d]GNMߙ=O}`fvyFGF@mc|kg?35 Nz([ᬎ^x[izbѓ7._}[zvh6 ujٻSdCCPhמs^`&)v6/ dYX1>_U.bk_+åB^I8od ĉ4;9EQfNb8 Kl99*A 9j .葤AøA7+fB|h U`Dz@(qj2Vc)kX#gOq<$\Įˤl#H/k"Izh~f =# N'2UM%> >Ԁd 4R+au99!?w":-vQ7zaːe8ZΗaxEX%A*!Q)iY(ޯWj#L\ኔVKݤy^}֑;@UJeLEXWzmμzEАDF(xZ&Gb@eFO2xRS`0u8D#0`Jp2@ڔ惕Wc/ d,3B6X؝*pYE[@=VUXBXVP.{_ 3;@{|dn#Ho3wٛW&߭ݸ/}#f$b{|K_,B%^+{νffaa3SR[Gx7kr0}zg^^6n oM'{?[(@:Wm3BaI҃k8*{:ێ=pG.p;&*dA`w#Xv J0_]-0Iw5OR,i6f}& ?I ͺ:GH]VdE5 KY:J,*vMapq#τbȰd 6-!Avy]z)[^AF.ZuQ`1U7/t,x#UVL<`5ᙈt} T!%/?e)JyN$29]"Y3_:C~OXr@jt`ۮ-^OMhZ.VJT]~m$VSP-Hdd%ܮ3҉7-@հkK(Ҭ6=8KKdkj_+QQAЏ( \QިqfHp}C5|qzTyԕgca_XOɈDԝQiafƄ`-yD¡0ba$O'&ԑ`WMVdp{JJ\F4p_֌:pI`@/א$zˡzD{HD |ձ,E`IHt1rxQRZ)5C8$՛C6Fp8NеQnhʀm ќaxd*@() mDQI$F)/JmTi t7i|ǖSBI4h%/yō2ܼ8Suw۹[P,q/ӱ w=ddh?iáMMx273mo4}ų^|䃧_$5}l||bbI?O kC.-?܍չK0߷Z˯KYqxJP p-^V*i=:~G\+ӳ>kzw2N |+![@]![$х5O,n))qtt0h$ѨdfZ$}XSb31BlKabE0 F?䦥+@jNa|̅ReYsH'e0ԴG \(ATHjQcTKֈ\攒nӞ(~y173^nh8*ᐲ4ڒ:[jFl/"q } qžVrxS3a٥Y&zdD}E%dJ,Lt/]$ u:z Kbh$1T 1D i(UQ_ڸQ͜ʽT!u;_+@OYtEߛ6oaaR yX(OT4>?G)l@aP/EZ!,,ャcNOo)0%sV3ӟ+cn`[+0ٷ|~ҍ{HVʵW$ŏ޽˷#1|͛gά,'w&;SؑVyp2J2Y}/GOǙX|/O-}=t6O*BϾ۳WΞ{jqSP%dJc_ ҷ'e2@+~mpO\:lg=]a(Q#9qHD-flShLK?*gt,fP6ViM%~a!&oP.PZYXHYq픢Qً P[f9Uj!  q#8p%V!}³bi-UDHڑn9gkW.֐q> B 3QպfxtmO}p.~*'ԇRgo㉚=kC'L2Z* V"ps1]WףYPhU]jMt4f91dVmq o! u*VP_#4 *@L3W䎄r`^fW*%lJ^?~dY ph@+FsƓ5)%ĚB1H1T]FJ}9$dY0H耦hI&bޡXD5(%JxT_p-%H{P3 1"c<~23qnel?^T^4]8zh/2ZNܿ'vݹQae(gvH}p֝c~t5ɉUMw(}ԑj661<:(ъMSccWOػrfڇ:u4+̺fZd ݿ,,\^Lm_kSEpgpqh<$ #XZ2ETbꌱà O(E٠ԋL!WQ 0Ӄ&oKݣb4\X~f ?*RF -TYtʽxCb$`ʋqu 5X ,L᪵`ŊaAT& 4e'b*7&J}r(  ;kuQY(]l'b>~^5 +vލWO==Νn]u;m\6v ]ؚ-Ht]F L到$0D2c72EK+U\[5%4S*很aWrlc 筮.z6N(e};xgND~,:(D7(K)S"7ڈ6? b;fkMEWT<4ZI]sJPi*2cr fMt֢uP*Z%,Q )0$65WKabfjoĐ :6~p Ruh6(5Ջc fT:70jd y"PjN3NB ~< rѳmS'T۰7Q靿p@HX_#<d4SW`L-,G$k8A]%d ;r6#HF:XQ$2pt+e06Ž~9NSA8Mdw$?6D@IOOc~S^HVCD)%ajr', ؟0Fą8䎠 كaM%3m' u 'vkL&]0خƔfD7hg7!0Ď:gp0Bnwaw+H-D-Y-EF1*9X |!58h4r t(i(ڴP5v B/'"3ZN--Oתpr\JNN SS7ob#r.GA\ ]Dn^>Fc+// <_η \{XOz6[*x-[ 3t } l}鑉3S.᝻';O ɡmʥsG[C o~pc;Ƿܘ)n橿VN'W'LZBF) ơBiW3]}mDEƛ҅ / r=gte\Q1?tL-X,Q{e5J'"4164fm\ONP'f< bIQclxŝ:x+/-N*t?%6;{$5l.!iÌB7MIKS 1E":{I;Zbj!E\T:z})p@" ?wG:E;ggttw!P!n/IO##1k"}ұ$i55\9=Fj간2г(FS$qAtQj(7jN, յfD*&R25G#`v],#BR/@)( jJ#1r$R=dW(A"SbD>HI IDAT0WED\#}MV Tc)$*MKpB8H8<8-"(2;T44q) T 97U>M%uV7֑n2R@xO*^jqGQ #pa''~$ZlneH)kP(A pP v(zDØAt'y?+N޿p~uzqҶ-khZG?/|L(1T>&Jٍ`X,wiU+VJP2mO6}z9hЃ$"Tɱgo{m^p^JK_ GB3>)m>whs0FzyÁtteza=wop߁ӏe(DeP k.Hm(KRJ!HQmUp{)s{m9svjB[[[2!<Y@gnA$x cScY:-FR#${kpLP<?Hlp`K?1ZPH}g+U0ڹ wt-Exlr1W&QUq,qjmꕢ+a锎NhbhHu&7=@,yU0Qf+@B_z$;\x_>izM#Y,3gs㲛FwcR |/&l 4+B&)aax`t)L,cF˥zvMvx|02U%W3/R~Nr ZM4N=a\14^#AT с`~o~4傘I񙲂hP)\I7Ú0Ļ[EAjĠ$ԫuy"w5},[ZlJEr;gY͔vֻzͩ66\~?]/7cv;NV'{j%;OZ^OoygoN+oTw._ 8_g/]DۆZtxˁS6֋ Y˟^n+`<}Gb^y0I_~+{wz.JN[+o|'-CjXa ri.ȭf<骬~Gǎ1"jGB'kƺPtOMH$EJL؁~(VVsb Y#( #Eʉ#`/b./V#~*=_ZEe(8mF`= r򿬵( Vϥ'L$TXeIe aoeA5?Uhbar2e9MOR%'D흲=v#tqff" GɎ$UiD1$r VZRK)8A - Ȧ6[T9,XArA}U92 a_Ձ"ilxQ}9l-m \Ȯs~-4酞i1^Z?Ywa<2H2c1[Tno"lNyQ!_QS8V &١ӦAZi5i xįT GR}?FޝHAnC!x;ܻœN;'hfHiAJW7QJ"GFq!X-ڌqM2!f|v-/h)[A & m"A*MR ֩g\*2` `H*MRbI)HfW_TsH5j@:Z-zTЅTʸۢ=6/ol-#wIǹnJ{Ѡo-<:^A.*ͺ}%EP16I0\V7t_EfX6e`,**KvQꑰvgWvM]J314J!1U}G{T"O&]KJ SU"of*5P'D }S(\c&ۀ3QVbo*΢Jmtqɗ 25F6 h*l%Med+ Эkk1B%L%s=~/|_NMG[vuiֳo o//yk::?u+1[YY ;vLe}94),!8ʘ70ud3wn`hRi~ M]:߽ Ŏ>u¥ȶv+_kJJY-5UL.wDp/0.xveQ_VnP j ĝ&ت,5PN©+n!it`UBR:cP= [7)G!F50QڔaJU59E}ĩln0An͹eQT^N8)82Jd9X9c"'i~ј6^E޶@`Wؗz#狚 @.6r %0nFnG8 Q8ϺdLMа8{x4㢐GH _>͒mICТ S'0"}SA!K[ l8mD[,.GB!.HakHxd**Y]V(+Q yqұɖ۳μz5KG/jH_1y*lܝ?|>& x[̕9g*)0e k@$#۷GTb@C5BS*,#-vZڳ{Q/͵=:1ţw0U;Ti#XJ^ʰ ݕꬢ˻+FTga6ùٌ{x58jTnwf6aMHaYa6:!.VCWj{]Ar;UeU.߱hKP&$\'Ƈ[Ja[?h.(jBOG[IĈEdE`p_(r&wPK8zxrȍ(L3$N4˿4-[)dEWn~|'ƔƷb ګ .g^[#P 18N2TQ )O+Rèa&CU&LɴF @vE @uح̜2k@l` M!In4\N ҥu?"jRеKSӱ{bPSI"?iW+U2L<]p㦼i_gߋG?ݥC#O ʱǟ:~8bzxYNvf6= A"jtK`祆E`"O[qj0T䳿HLj4ɈRF\ÌF:(0AgtjRG3gMu;Yo4Sc6X8vx='63PJ%mujY*xj ܰ D"lz As*33є4%‰*o(JTYJcN)j AfFjXvDqjt5p>jsyN񔏊&*lmzvECm31|BFiu t6q4Ȯ٦2\ߏ ϖM UިjmXH3DBƑʎ~ Fҧqz*嫙5 zI5V]Z\I)N:,6o}򙏮_?qײ?{ltGjαGo՟ݽv-8_*;I3B m:UɮVV ar-U3DTs@TE4hrGla>=l%p&Ʒwo4ˬQ+u(ۦ_&Xv2j|(LPŮ8T\a$$ZG]BJ5 m+"l#UI5Q^)c/4_s(X"Ҭ`Tu$NPĿ3IGS+\YN.vݡڛg#HM pj% Vd.Ft͛H+p Lv@'c, sJuP6W:Rorm5AW5O|9]h' R1GPfRmGna[c4XoNNn2m(5@&lοwfɧ~_c?VWK7oԳ٤-ªHkq<Դ  `,NKMz0?e-#GN3vsc\c@ Pe$PcNVӐHJ58W!NOe0,cծLTSMX0 ȏ?_ZpuRjvjZ+k;mC" QC]=(>Ik#Ki /*mBV@]qJAKYʂɯp@R1X(o)K 6[l%T(HH[AƕZ=m(=) ځG))n+y T b/)lM?ݩRDB 7J$k9)pyxlG(\<Y ,Y&p.L.[$ Nf o")h ‰L^]*(I'•tcTz]I˚`2pdޗǞ|{CrcO Nldǽ(B t%Y\Ķ8qf2/֟ه=~Kk{/7>苿z+ W?w=OtxlRSB^߻>qiDD0'J<ݘw-hw B*}] XaVȱ's)H27(EU1xD~f7Z=(3ռfdR%J'mKӓ4n@i/QWr>s|)J⍀,&Kr{ڄ!h# o1-@266>̤@Ll6Bfm`p eV]t~PzCc#VUIR4R+"IBQScEE/Rv.![|W/J}T1628q*BفV#**@8ڼU,TPO+m*j9pP; wg=Kbqf *`+d Z&*bV1Evno[ȢӎsKx,>aAגB*Dfk8h,0.5(T)I-a8#YEo O#5{btp82ҧ *hވ=jǓ+U"fS&z`wsN/ι{{"AAi  咫*,[UD*ے\Hȃ `Rt_oy i8hNp|߷^{ЪU"P\h6p,Rc GtŘEM$oDB=F<| 9Rdݕbt^8`gHVoxʏy tcb@õ8RzQwoZȑ&#׋_\|GNOŇG8D{>l`dt=?o<:ǎ"uxC'}vd8O[ϕ6Vw )ν4 &;8L3#^U]<:uх7ݾ K7~aNWn,LFS5xwD2)o2ZI֮T|+ xtzB,O{GTu3uae:T¼tزt,Js5U$Z|u B4O ` . !z'ؗ7K”0TX ,H=<* VU*r'&0eШ^L, ckzaQZR9ѝ~ۇ +^F8pO'c}!w #kTzwb Pm:U Ř egen()U<]xxipZ.I?5q*Dn8jq2'чEMl\@jQU (`/hxe6=^$mK ǂxVd99g*RX,%Q4+2)' >#wx</ʤP'TeqTT. Cͭ5N}S<0 VZ^D|HBu==X"}6f=xDBЫF )DMtM X(r{~ 0,dE= IDATǐpKLǠgUI *Liiy`Y@MZ2c:]=e a:W!i_:-]!\*5R>izzPo5g8d VӟⴙF!{^օb6P Ӣ"l!I#1Ŧ<( (jA|HC?(j|>K cNބF<5ZU@opi$]0`[Tdp%ADQw MDaj:1Z N4X`3j?"p!S-RQ|1ϩr=8O]&H&|ܽ}ƛHXL)LZ,e{զYMZ}s=yC{cSg?,Ja{̝<}vX=tk??rg\}'K+C_ P/ooHO?l fojbow}Cը$Nw1\oZq}+JM`|{ Ğ?Zs)Xѝˌ.o^B"He!O࢚+x[UOX^N"ԅju/@G׶Ҹm31F]ؒ@9͞T%lv#Lfv +hk2Rawj}g/oB6& UHdL#rl#I\%,R{_PVZ6mZ)P`R̲ ]"ш (qTti~kc0NC<%񨾫1 MJQomwJA${Z!> Sv[M5 o+Ee%%tttFp~v tL9,l?dB"XSt˪!B"*Vɑ*EC۽o$ ǞxǞ}hjC'z\'!KOLDdHFr&qdژ?7K ~|l+o-.7k)2I)bR 7p^a7ɱDzjcx`'s Ӽդ>Ҥn;y6JHPhWܨI?}%b̥' z2VaI,̄Eb@nz*;K8&3'5=p lOq 7r䋵-W4z $O׃un㨼ḋH^$dH:._54Zuɤ-\ō!Ĝ@nG>Z5,|lp[E&GƧ#M,m7>(d<82eCe]B TPN2PmK#vHA!ºгF6:̍h?#^-2l5D#1n<"H0h1,SePKקCIHѻÛy H%R[JtRp?ټT̠"Tfte;bǽSӇ^9zd4t嗯]h-=X_^i{TDZ]zx>%};7nq ³{56$E$H\64l@B{ftFFߎ N[?lJ&݆W/ G9~_GE8顛q{_3t3ڮwu=NQgآ!7c (Jvt%hGR(*jɱRH DDc1*bj!,0B![̣&SAת BRn8ˠ0̬6d:=)(WC -6XH8ꉳ>huP3Vn d)#y!$NXOg"(*ruRCBøZkphh_?6ޚ,2W]vŇ?4[YV. 5MA1I6:P$+aP%`U%u`*k3Bެ 7Q,CL.!?H 5e +?׾'(o|»wGV[hxիFmG?|Y+yV;wg'(lV.7^xFN<~#OdF25ȟp'~cA ȹ=}LbQE\zik;1g {1Gx1T-R3q܍߽+V"X$9~ZsS|Z%ugQR<ޝDA/A1bd +p}VBFp*-rKfHc#zv0"lfl8Ҳ̒E)|C0*)Է(6h"U7G-t:]bSrɚdK3G鉆nʕș%yh)a!<_s3_yggj?1lgtF{N.,,&;zplft67V|al^Z}ʍҝ BQ)6Z{yO?Xo_<&&/=o p!=p2m$4{ݺ G58wSdDl~Fb~8GO^ؾp\/ՍȎe!wkwhy=_XflsυwO29Խog:ǔ'Yݲ|GD˨4FqQN}HF +l#.&4lFZZf$@P:hӱa.ձNeX?a:Vt ԯ`w GepFiT\+MoAN@`:%"B93.3®hY};4A}TAt8udkcm,YuԼC/C"}3qiolVJ1QPCc3t';йvbZho`o9hyN}k1!9 {Fqc uuTtjydfk(QxNنݻ_u*(f .Zu_%h[ׯ]-E_BϵNʹʼlr,8oox$ݒP"YY6Ia;b'E9:Ar;!g7e5v6n7Eżt:%9VLݣv!)HqJꤴ̖Y⶧fKG?[sCy3mC#X6Ik纣R`)mfm`V+PTEf{pZe`-=6%C *{"Fx3(3"aIh2!/`HjYO"v5VBdrhcيik qՊ Mp/:bʷWTAhS.oGӁCS0̂m$>DN{$K\D buCvvHA_.qZHx^u  q|:D}B|5smrzGj#`^SH1GA}sɃ&;LbpL2 #_Q$ E9>kP}4?OOWߦytt&9L8zwq}mc">ܮVV<=魵̹'>+Sɥ;s٫W_{y]k+{T˭]}?y|K۩n^{U(Rr ƃ&P$t^>QnsskcϜi#wsߧo<c7 ATR͗> tytFBbDNڅ$lz~ dRSSZSG)tR\yC3 \y'QzxuBlB"r؏ᕥ&UWYhiM d)sBASSu 2 T!&i㑐̍$Js}S5]`Z4-< +N[qw;(PR_fjupI81KM~d40si<3P\zzG6W S$- k+$7Л[fceác  ɦHL^qk_Hh7~{yʽR#SGqN՝_G}?o~Riv}iR9Y۬#ZQF}E|6\=7Mm)k-8Q+Jzo[|//1A6E 7K\D Le9skjuN"E0 Y3٢C{vOd۰l*xU\C(2;bW˂ T7JuKJq/,'i޲\!9# swxTH4L5lȾ*[$XX/rcXa Frќ{sJU,q[&+l._]{54<&z,%X>妤䠚+fuBIk՝+dĜW0i"Ԃ01 ϗ%ETzT]d|b"4qw5RyZ zg*0͈8YxtgʝpV_ A3f}X$2hJdhF1, ^^@Ķ #!wѬ7pD%f2BJ-xHY]^'w8LezsZ fF%4iv DIbwASidr86gfdbV)0fNwf챻W.n++HDbg.l @;3}mi>y1?B-r [O'Zޅ7x {W?tYZ3.痖82ccdFv-GR9-f˥A3?sǷ6󋋕\:q޳~VV6r.T8I@%f2)T7jdXL0lGa(ms67]B bI'ˆ0NΩ% DmIB&D&kz,x_ `6g1?\kP|eZY j p, 7:45dzb*Npȋ4MqaF"H+1$V2^baP:RIE?>LOBx=25KzDq儘pU^|?'ިgK= 9BbL†BؘGΠ$ko앟sT_`Xa_fhȩVir-#YM[;Ms;0LjiT9uK+Ҭ v Lw^w#r GQѡ:aRFG(rzWx|ݸ~֭lĠgcJ1EuK;hcȝTHO>&(s#cZf3>8:l#E I`]aιn%"+>wV5BAH[d6itšQƚ+\a ,QT^—,L 3 1 lCYL5䚵Y$OA06nfJj-۩R$#`5y4>J)=ZmQ͸v6rdt-T~ج*5J:7&-ܙ"jh[i>Qq"@{xb I$o\Y=14I ^"-+Ы;&L%a6cP ݸϕ !^ &m %6F nѐM T 929{Y.oPOFoUJ<=) b`NQ=/M1]eaE"4*a`Uvv 6zdKo$^ ׶?}ӯ~/ͮ-DGchzn^ZjkS{FwU6h'v?D09\X\qӮ9ybT:-.n jT4 ˌ@ Tfz 'v͒5/[f('ЇȺEJl/nrT HԦBPLwf󝨨- FTuڄ'|u C uD?zD!"H`o=p'jʁuvl|rD Fدjvwߞvqѿ~_y~D/.?{DXtt<޿^Qg3sܽ⭹p5gl|A;ί,v@vǟ샨=9!3Eh6*Q )8S鳢{h.)%va`6OGE`u7cTAiFm3!澩I:Us 9ѱVL ]~&QJjGm`۶'rUjv9 CഷZ!S#TDX˷伨P6))M1VGPB3PEүY͓kPЙlߪ^J'l2ZαoAoui摐g5*ZB |@8AĐ2Z<"I-%qyHtT!i]C&@v!NNsCʑMuC!%iK1K HGT~^Hn#'ˍu[ تJzbj/a%Km!Xk R$>1&lJ#ݓ,Z $7xA\遱hI~,9iCbAC?bGޡע/U݋Fg CpͅVחLFJE{#f5^V voY cD|nX$Si 6iK@ jI",b03!FuΩ}̭jՍA|.aao4s$B4z$@0AVVC4'C;(V<=0CQ^'x';W_f:rփ;ShrZR|io;ŕHʻz'R[KG_|ʷ_V-1|޻ yvcəi`newxρɃ@ db,5qp2@GN9-d[CT(uY7m$Wۿ)a&-Ajr O3~ܫY7IsGʄ`.+3[μ?a `I֝LCcDHd.ػ6iePoˁ}C ZJmMEdCic )yd̋nrjR$4{s)A P Mam"GěQx9 NQSF}doT`S[&l;c`gCLćUrNDp ug^RrxKA~711ouKb-7YiAWmv9%eNqJwsڡTiUd J)3rG,w%7N,ԏ؟ R "8Ǎ[Zdr(0SY܃7_b`[c?/Q3pJ_3GNH`( Ջ7ngSm8nc&GݻK˩do@(~qD"N<+$׳[gFPLj q LL|&&'ߟϕ,x0p2,z*5z$jDzv=4)OpFy m,Z#4JQ'7(K*Ki 6. NCaŞZ.~D_Q_B$< fwӖZDbA&=&_MCUXxG Y(ՆHG1!В!CU9hۜ\r[Us`SgCҘz_dwwtNThI 4E!ށZ">fǧ3G'{GN&fSһFpzf86D$gFV[/-\IE'@U6ND囫Mbl)ҍE0Mk3uM6@bGw&&!R' &<}휰gڙ0*Q1R {7F *,e`vӸ^=*@j2gس_KO|拟vzRԭ>ܧ bMG>wחoD!tVY y=:??fh{մlpf8*&=Vf7޺7'!i05́%M 8 oP\6,ke"! :J֐Ty)(U4\Gf$#x>ҡ~ďf'OrSuF#2D YTCjh^BcI;VbEU|ףCVzV,Ēp|\xWښZ%(d#-C&%ԂzaЄ9yP)@jƒ7yZP:f@X q׉Xaal%-kLV0&BaO^HZ?q\hüϠ$@($R, za'!ʶ;H5d807L M$uH{ 7P{GӕRO~iܽv>s{uu$>rYb>}x|jz/ObPNn/Uʅh:sg?{?yy]{kM(hawO_ysK-@'VpA鶍ٻ;19YEai!JO:{k+ ׯyM1T OD<12E;𽻷. YxR,{Ȧgh,?4_ܯS@F;ԫ/TP#ֶ&F=rl=YJEɶC0=N%=DsC{M+:@t@uFMZ U*T:^vTbPL$d(PyfZ!u*?O  )-Gnq1 )J6byN(n̫Ԋ}I[9;,UCt}A \Ҥ;>q$spXlL ;6zԩcNό`ñRE#  ĂYxSLD}kJ39` 5SimPȦR6c/z ؉ŠUu`3qI,"Z~ kRI © {DZ#"8\.#[œiČAv{N9[ zO˼_}^FDY geK&HI$#t҇G hLSu%ԕCaY겖d%Q&A&$Tٺҩ Kʱwo(yiDd)0%k$`24ڐ i֠|MiF|k4: @i1Io-wu($IHeJM?!8~bQBkvjX-=iM哟EbQy:"*"VjĤh]6n Qi&SW<\xB݀ϊ J# Uj-|%y9Nժ#VŨ36+c0}lO9@>ۋD=Nϛo&̭@?e=/ic)D6>bSj6##&"w/izklS USX(2tS l5MDgő@Z5(:Z$hFbt|'谷g&ik̚pfHYG?k* R]89|}Ԙ/'|@fWhbo|oxtwdwpd4g(_iu$"J"]_Df> #j$x :*)( ¬0WU0 8U+,VrpJL{ܲwhPyi/ML_}UGgqOT3fwom:.6޺^|<or8pN0./޻P ĝ O}iusO2)l?/n.K4`dl}؞W.So;DP7TjlӮEX2=d:3kGht@ % Jke?4)mdWk=g–Ko4 &C"l 3+`6(C;%M]A32@@j5>5FDU%r4:J]ڧڟ gdxAҔ5%lԎU4tOE5AmhG#˂ǭMү`*mObWA'MnXwP ̝MGp %ORH3% t%[!=cN558&㤲qѤ=;n/@ĦZnkVUp]O>F17ZXS!,zv}1m~f_dgՎrtgy5rw2Ý׷b'YtX{67e& Dn&8`$^hgLM`g95%ť=wܮhU,sYL>4&q^,pWh bUf 3 &qAysAgA^/` !mTI4d,lzB8}lTF/}K+ׯav(Dhbq+_,tFZܳ`4*:E)SOT z",bK}";xG F,[( mY&-͖ȀY@1kDq#]ƀr];h{>GeRSRP"_L悲c{9>s {J|qssHdJWpe{1d ľ%`SҫcGr:<hÄwgK0Rz-Fy#fFfcPB&'FE'IY^5L9`5%^R y #\R0=x"͜b^"U,HNaۀZЂr)8Lf~'J)(p#yA!uF;9Ԍ]8| 2N+y+6kCH owt{HhXD開}sT|e_2s_7f[`,ío{¸IK?fbb/%:*]ic2],5Std*][N0 lk1>9><5RSg^F IDATݙ_iD>~߁(iFEhf+x"eLUiԉ#ڍ[+h  \V!&@Q̨ȘpNo(:% :L_^j~ ?Jr2r|)r5HdģXnVr)' ' bu }g[IȨ2mRg4W' Y 504ok%aZh7Z ݡ_!cιZXj,ֱmI@ 5=Xf])w+X~d"24qekgYg 1D(zv)FbD: =$$UZȌϕK+(!y|6oݟe>ξ?y|0MA'b8|3Ϟ({'O#%_ǣO\sqjw&o\\njHJ~e~y>I'ܿ4wcۉyNsp{hQYF1t;&gȇ!W*JgXpC較O5ю[#[Bm]dA(Xbz+ţQ~`CgEvL5s@ ȶ[tMSIZ-HVjX ֻft6u8y9J-.vLĤiT'HI칙m$KUP&A+UIʼnъF(Һ8LEAo:Z7"4-+zFg;^fq?>4X嬡L̡EQݘ߾{of;hd;Fk;Tf݅Rf1HHc]CEst#;`ÀdYݒRYQ(Lr'ZMmШ Nc?$ܠ4 qUB@jg~e9p foqKλ-}ġTS' *>gu7$VGF f.=4 rBS(B$UVG֤ F򵏍;]%8 &"j7>fthҪi]ڭ8X8h*Fo1xGJ{_ ;XSAq tZ",5e'gGO3bOK[|!$V нa NҾcx"3cS/Ce|Q;PJ:̆e06kNh&>vVuE$huHy\کT .)8l %΂髣 G2*I3âsnutrJC rX8PqI,)7Cfa, %l NXFē/)[i*NNM %(t5V`@8А1#H/'6 -S^ltһWhQćudȪp3=t QyM׷P:]\X\>P Ƈ<'9};o?}G>ͷ߯Tʻ޷kܵk,]O|շÅ-TU}ӿ̎^Y<ϗ7.ǃ˛d\wkCZvN>H-܇#34 [+sw % 05k=qgVTj3{|wZrKS Ts :+r3y|5[% 5u{ٯJ%W ~jM!Yu-N9$%Nߌp \"S O6-(STh=̔Ztƴq6kUꘁ\6FKh 7bFl\r܌1 SL3eX:5j@< 2e .VW m8{[q$ Li"F0sGNwm6rom^/[P|ꕈ`zbj.:HX$y}uLJYRz&mCEw;KΩ5k7:%mGlc*ffgN;3ňdC&"M^Ñm~捷/- u̗僧| ͅRӨMn5䆾˟xb=Y_<3aF)NNpsۡ|HϙG42raTZ[D`E G'C{pO>vҕ*x*m$^r}H  jF|qsOU[;h'vL2sp jV PGe U|W%(N0UUXTצ/)d g ?Q)j/2]&nllX*viF9UDz1?`AqekĐ];+_792cb,m Yܔ$" At8rh1U`Xx0Ѩ²n0axF\0 hG/ՠ7Tdz!??SU+ ,zi"ut ߓ/λ2amMd7zZZMN(*ح\I0q[-jmP& ك`G7!V3!h׹QǞy#k+'Bg#ÌIl͛@L%g&fv^xObr=O~'k֙7~nk?O0./Uss/<2+AίW˝eݫ.G"# Ww#g76g,r^}߁=NW][9 wPIDλ n@!*Bu<7B{O샪T2HF{K%M"{"~L6gb0H rڏJm#/f9wZUgI%鸘sXlWk]FEr 6RϗNQ6.-ypͶ# lJv 3}v#,lq9ުE_:•-ۜ?*UadVVw*&M9OĊm5¤Iטކ !1Jz}7/}uB}ljd߮6J>oxg$ek!^5 g=A y] .Ñ0X\l~)}5=0t́ˌ8^qyX߿Ϳ^y-K)Q˨XKҌ1:*MҭWveBFSTKTș*UL&H[+4 8uu|26ejchVҲVj],Ee+PmU b} ӵ7J 54< T5dRDak!:REUatiЍ 0?U(à]\Ne.rXȂ27<6JS+Z;qeMJIlmj\bGFƧ%ƎnolnV7?6o?^{WtWǞ'/~ ϝcօ%a+ŏ=,o;wss3/|rěwq?xhk w,d04$g]{K 8uЗ@(W&f8pXٮlΜ<{3+ѩ4`Nh9vѡtKH?'MrcAxhL GC&-&NO=_ ή\DO s=1r2|mx@FH৙UaVI#ɀ-eJXun;$Ku2pdm9ǥU$V57wfд'^32U)Q6k?5Mcft ٵt%CRlFH.CO G 4>B!FkhlcN'za~-JocR驭g7.x+;KPڜb-6*ZJw ʻ~➕Hpڝ$0s'xh(ڸC{qhBz5'9EI"V4T;*,ʜ+fS GxRFT(opAL=[6^tj*{8HoVq`#tyA?;MQTjܛkE"Hr2&&ש7"qm6'JAɐ!5B,%bjԒ̆# Fu#=~c2w]> xj,o5ꢌXG OZ=c-J}A-&n5*8A h4睐A [ .XAC=H2cH4B~H̟1N7L@tn;߈ TTUB 3&症ߐJ2fl&#Aiz {;T:AhB‰'Xmr ʹ b1 5}˼2=G)Fe u ;;4dqLCt@ܣmf+㠯X"ΜݘDJE1 o)DRԫ-P Bk7 pV;$n{s [|Vs$*2*z?ZX TI@tݍR$cQs- IH^9I[^8:Bײog~|_k?v2{g!.>u+`CL {wpaFwOz@t{jg)8ο>xauukaoO5ީÇ/!OOOMOcX,j0hqv2.Xxd|?2Vb%F^*wʻwP`''Iv[@etRP}˃&1s ǟ^JL˫\po.Y sDu[FvDY&_ôkɗqtR%0bGykՃ,&}R^qᔊjEcAH?4 `[=pYKESR,u+ZBPf2,44.[BFSQu%XQ!FqNJ<B4Y+0(:a$$.'+͛x|hV*v녅V7F q'Xרojd^sn/"s:-culYk!a4Zqى{;QhN8OA)z"N PJޒ 22v|9I,D@)/%Lݥ͋綶M=wZ)PY+tt"6~j Y§5X!B>e (.hD QCF`fVc V~5"҄XH|OĐ2~ؼ2BX!Q#o֕ONB6'=Z[`Cf!7n5~&mb& H=;}D G9`oDF1Ύ@$ Us$ 2{k\r.4iɊ(BsԓQhކ;pc= bPo uND0m95{3O{i5!\ z%qhZA`ن,$J<^8-T೫tͶ]+7}v )zU*#/NO,\oZ?hlrwyBFV4 p4GFko2*q2>׹X`9͊m(a2~($jI Uu'GkR4~T~xiѺͨ 5*҃Ѱٟv&{!h:XZ[ڛ;k'ipDG?NMό֩ 5{_& A#v4HL5᧩^8QB+ P4`8(0I׮^L:?]k.N,if. qmb5I;On{ Ĉ%qPjXA3p"e }~FV'njD5gsF hr:;VX'Ԑ/&>,؊WXw0<$4$G`gTϬm8OB6'n RD.C+9{w*h<%xvl&O[lܤ`uVLZ f^N&&H]:}m4 #otOH_h|iL,zrj> j 3 IDAT"WTSYڭǀA21' \VҮB& 1V L9uCLR`g1`D95:m`(A("!2_(3EU#dƓrF`6 df s\:X?F땣E{?Z}awr܀עhiF`<軹TA; ƖbzUqb]i$@=0PR+ǙG}e1z',\QA81?7.kأf9m áް/qgOpn@aEaaB.s,4.wHXQ^29T$[DNomTͣbz\UWzVrkkϽ"i~atm |N ?گ7yѽ`le;7}n\>''x;\\QyZVm>&2Ңy;ƆQbI zِڒH TۊVs1zv0_=B0dm,caRTƵQ$!x_6 ̹aؔg/G"EcCY H_`ֵ58 s&I!{BT0BgG`IdCU'GH ItGm!l ?NADhung.9!_·FX FN/[#XR(R4VqH< /+F2:L$+2MTm3}34)Y6|A 9Aazڅ7w,8yy +3:v*$M LRzvyCa5';bL ≖_97pHE=j|YcY;j‘@&əVjc~0Wx Or(LAz^#1BMzxpe%-qki}ArԄAu ~Hx&yXK"ZGa(i70"`u#f%go 8n$E{Ҫ$'3FEG :u;- PHŢT{j|P  |>΃+l6c~ߋg^K/|J~wsΗ˕cDt|3կm={eW^ҙg=sF>*,dWv9s B9KQ|4Zjqg8R6G8[nqYb=il|W;}p?ipbL[t<66LLH%RT~\_+_}`s5vA2~gуƧL`h:!yhb+_X?=WLJFhJ)B͢P#qYcٳo]J H'd:|D0JjSEubu )x&k4T]'e~jdҲP$vb+۾dRcqf{~ bGQȼ '"r"!~S_\LH ~e^瀀XHJ-egD6џ4d뮛"PפPmĝ 2 :m&ilɧRɒN%s㼳FdZ]JcRt1o4cE*.P劐~+`@tp79S` J#O5v]`1X7u|)0V4@C[7ǒiVrr nw McˈxJJ4 8Zh D~#r\94(QVgHGNBI1R;Wt[^>wvAf ( sN) + Wi6ZȦ i%x"fzFGjT14fϳ䈥jێ gCǂYWs"yUn X3qcf K3bZw.Π!zR l#&^C=grY9 폄>pV~ȑCV8:Snwr1/uT8OdaȔuuPt~B2 2vgKF:e!+"H{ޡǷQ(인"l2a⪫+S^W?K`0%/(uZmqq3)`_ G8"}>qaJ˥Dfިݡ,q(|0-#!ze*;k0gOCiq,dX !oF̨I" &KGo;lœ(e]mRkN:HZT< d::CF|Wnya{I8qLU>`,'8"hd̤㙅%TI + e!ۭ7}n!Qw&vbE·Y` k]|h2A}|fs_jx[Yz]f~4l#vL;7=@'SȞ~oUŭ ;?ٽw;xgqFJVHvY0 s !Hܻ55k_l6'|ꃻ7_Re٭x|B4 wk49j(4rAq4|?0(j6$L'Q[>qTo\&aDJ\~*"n~~ "K ݒA)ڴ[Ri|fQ^%j>|1%Ӕ7,bLܖAt:`D2v:EnMRfBTխ~ڢyYlb_NƋa{1v~ب]tR!:#)pK^$ ҏQȒ$ ikeINo|4&F1I+j)Xц{(.i=°!˜&<9'rOdYk!֚(8 4b;KPU:61 XVp=q@/\=pHmED7ƩΝG" (l" K\!fؔ,&Ice֚.TP3QgNǯZocX$f /kmM@je SA#vzz '%ku6eX]5~ot1y;OF73K;fl):9nDkztq#(@<4ݧw1CL1iPl"[/|a G(@HWQMS+&,pY= `xozĝIDi1V4@jLC FG@NAžDwICG, Zj׃H }յ#$w[VnO,t{0h⺺%~鸐dҙ8E#4l ZN X6A8s2Sp0 rg0BHAg+Ե@('+o^ru8/fOgKyll+hwjxby9n`EK/>w'\>Rz)`8o7rv)N+' o0y&}θ{k~ǔC%"DN]laeh#nxauҥÏ=|6g X>~]$'z:T&yjq%!Sg}$G_>}鹋o~tН?{ {8X8 F%xbPER7Sc_hi%}Q!zPxYJ+LA4RaE.Zz o$MnSϚOXSƄ jF~%Po1ጬwƐИJ31a. kI^4Z0g j8 e-["FRyG\g> Қe0Boԃi;hU ;Qkt1gT3"_swb6Hn%39'919ݱNU:Eӓit)NcSͣ%;+"A~ٚEMZ!h4ޔ?m^09]u)iʮ8"[r=DN33/m=o@ T:ܔ&kl" I!)ےprR봪Z|8hap?3r˖(7I _wgtOsA=H7r:kjRMbx.KV\Z!Ҳ@fk_zs,C(կPF‹#; k[ 8-qzρUI/??BpG2'vphX˪%CsngGJ6dGCkbO?)VlIca.BF''O͜[qp=cHc])B];uΝP zPV.!T&dҫ o}~s"OЀ G߫Y^xT.y?sgl /yZ^,+KXI7dI>K0>}|zT6ݔ*htتp6EB3>a[C&MqB@c7!fkCwl52.x,'ݽqni@8t#k+C2"fzg8y3λN_eLDAmCN!!H_.?1gT5=z 4%5_Ot՘ v4*LanO}M,-[wɻcq ΢Xrqb5\ӵwYQ0Ha|^Tǖ/T۲'Z.gX* MFYe9H3iіy&|Qt9ONd=gfIt Nvv TtFyGBZq@A86im˾i`9/7tp N-GؓR2aC*'ϝP-u/ `>N4l7/-#И(UOl&> I]λËgxN:pRN|.:)IbT,p01 iZ6ULh}5n *Vu'cjb!PCEӒdSq'T'9u`+($*鴝FrPGω &hlt`ꢋQcFUꙠGs 6 ])fxHKjZT8L|`JPrV3]jH[ؾZGyqXG2x'凬#B2@R \aI\ gZ|Q;opNҗQSZܔ `?Yɠɤ\HW^ WRm)U$Cm8uʌH]w08ZhIv wX S Bb&A1(;B3/a#<횂] UrwN !iFLdh2X#x ]\.w9H.[SA]'|3v5-Whtz=w:OL['=v>`/3~d} l @𚭉+LZN=Yor͜ ajD4xʘR$DZ!<4 @W P P9C Կt0l/2V{CH7̦yʁ:A^R}3SSE\ sd}')Ұ؉T t$B6z+alxhJ7Cf4r2.h7-NX¹~>N _,i @˖Re< 21cvK n6;<+[/'ٛ?Ͽe{go'TocXX7jTFZ{_{&$l/ LV ?CB69 ^VbP3Ih_[g9VZ-"R\~l.EhF"p2sEFvF&ƳјF{@ԛe,DHT x.յOf+s#RC%b9K qw pA̵m DQ0g/iIu3a)3!k[(fYsJ^H*dj,}|JD(0>e  Q"@ro0L0??!|o^~/޻~ Sgϸ9;'H#Q=lVLnysi6f k`֞~a]\J2w?~o6+M"{}nquYy0'sIMM݃~8>̙g~|?6&nt&YDaxZ¥SϾ7>xlɅl܅%=9AʻroE$ MV1ikHp(1/5Lcs/֯\B{&BfK;^[Qb{]YJGDT4{=UMPw71`=0:5%!1HQBf \__o3_ W6A "jN FLI~l^y>T>_T\+J(WZk֛_̵q0~{(.]0*4>wC)lQ`mEB:G7ϺܔP";`S& :ΌQpyAnkKYgTJ8LF*AD&iF} Lx=hTQDa@xk^U3q5o/#!ccrYp!]?"oq>G  X$},ES'OY I?aRC"Y}W N96dls)W*B]][pYX0}n׭Ԓ>ŕdp'꛿r앟kl U*JskimA Y\?M߭aI;CݧP* k_|j|뭃&ܔKnzˋ/*g{6ܣR:Zy߻j^y׿'?~rҊŽg6Vv{o} pi1PWluKL;iGfCդ&՞I}RQjC`s)I|VirMfy0ɷӛ8 ^ơ[i/˼EתB-CgZۉ뤴fJKYI9PP%@K)Nx]il 9۱3@XKxhsϺ=3u=6-`YD)ˎƱ{ Fԛ=鍋dDBraEӑ2(3 dțgA%6]b \C}:W6 (Cs];H}/T;pNVդ9=n>(0 @T…hO).vHQ||7LXh8X}7eҹ|p\ݳφ֮M=vYO7N :A +`m/˷tm2;u\{:T1͚QJCQ= ֲ#飺HzMK%9 3/5`& %njiE~rxCt$㽆2夐}ZC 8(l"_jaC0һoA!b^W~r ؆H6OW\zZv|?QNְ/P,k6NmR<׾W q-}S?yM.?}O3||6eP,E˅+w j$g"{s2"Kn Zq7fQXRKFf bm5MSC-Nڴv`;W9G!$? i-fKCMpKH,@mBQSgѦ`BI8#Tf*)h6ˎ8.3s~kli DIťУ`(\` U$% R,+s1Xmͻ-3X+ [Aw:Zۀ gS֜A06jo:HHWކiqp=z;k 7 ֋.1lj?uwg-LtƳnGz% Iy֙^mSNK\Ct-;ΟВZ2X%B$pFh tz)k_o^;^p/HRo  vCK+_g?:޾[9z®];Kg._=<8^;Yـ'dr@IpX{ B+1%>!&-6.7 ەg3@zW* ,6KlvLPp Ttx@zzpT2kCN[O+j(ejSHyU;̲C݃cI8)U\Lɗ|6Pdn`u5۝X2n (ڳ:4= :Ss -^ErlAcgD|x:N)Vk\LOQLQꀞ1O"|NRPVD==Pݡcx cjF=9|܉X=wzIg׷<}ɓ7nF3ô]sgMM$aх /_\c$}OGVזf+@66VO%sهS>(mċŜ _{a_6;p 6{5O ~}J{oSTL蹭t.;OJFK~?<&hdq < gL(ߔAmQ=?oN Nk~[!ij4R!H~gh/mxj4cV6pNfD\ra-zmU$96NfRY^Za6#՘XLNiե`&{vuz4PG糤6sRe8mF`Ae_ex#I%zEPN>{YT)݈+*~-7zNrf bye4)U# uϜ_+ןBrjޏv쟴Nl%"ᕵ>!" ^4NNq󘬻'jR4%@4IΝw(}° @rV 0 &YiĞl)_R3Ys$ٸ@>7eA7Sot!34ppIp*A&~I#( P@kA(BD36Zd}mgy ~.pM 8g {gA*Ec"H8B3 sJ&H O+=s;+\/"7?9K"KKō v0:hp9BHBOPI} N׋Ors~G갉w!n hgO{C;'52vx5B"2Q?wѮ";r7nn/]{[wL>9>xKT:ϳOkJRXPf{=I #2d*O ON_zDG8ݻc7%Is PVfn;C~Ӭә:0=fDHMya<#}iikc90՛2fSk"&>CIT H|nĶ8q!(4:?٨5;N묜$Zv_Jh4W&&~[G~Wn;LHglpp|u͵g,vUxmTs/:!N흃bMzP*3^ b/RXz8LnZr2C9v)JZͫ )nɬc%ꅲ)vljkof3知CtRs6pT-[I'Kh iڷARcV;&dk/}".lC¹W;Mx* `e2Qf /\6>>.41nTzn`~(c1nw5_')ѣq> R+ά(I3PC_l!r^]L8Cw^tG( ! *A2#Rt߇.dQeXwN\"ȭ1!P5JLzPw UvIռz6t؄5\2 !T, "VCh B.`; r1M79(˾ysH@X¥`hpRnтB .bDM!L]W'>+RcdLf#9E#pTO%`2vw<7*UfHY/g6r׻Z<{3o~z?GK٥b `lT+ZKnQ4 ,'X2{D< 5Nܻp^jW |q64lbiI?nc6KQ5Fsw?_&~Σۨ LO$/rk,˷R+/p7T[XJ@vG%eE }b\BEp45ER^Se j,Hn0C^aւɏ Lh\,t 6{}wgg8Ԇ/tLVo}U+ )}8syA:*he 7j!7mW[)/֜5'C=sfyqnku=5F퓮e93 {PĩYC= 1$S6Z7&¡Q;JtMsLG nRt͢Vsȳf#Re0(DP'bO|x; {kL]r Բ;00;Phbb{1"MT%+ {aWgJ`\G=ʯDAnd "}4:8PJxEY& IJ/\kٕ̓O>Ԛp{K/to{X\NDq`Wڼx-Z~J=9> p-w;*E)0Xrx,C^u8MlDc#NX>FZ\zI۝f3޻B]L&o]څ[Ͼ~?M _}r?4ɭnK`UBl͆P!ĴD%PrW Glg~LmoTYSЪZ؁vH1~&2q?7ދnyˍ/!E ;춁 Psq_ITkdLʟ&'39WD1pWtfZXN^[*M,(ʉdXDW_RX7Ahfͨ_KC3#f)ӚMj%fϺbX'D=SHzi{TI߂>N")"Gz@-F폌LqIC$sQ%r<6‚$d:ȅO$:e-+,S52a&2iOvE//Nb 8ޘۏ'wgߠM>|ht+;" xB" ?Mpl9c +j?.FV?ι_~>p^)e~x2ϜΟ⍥!# zq9vϿow/ ;B>~ ɠrt|ݍӧ@/;>{Sn( zR Z% g)̅fQD0BQ&{T!5l6Ѿ5K8g]z= 2*;iC5ZcpйjF!-*M^n'X%ɮҞ5.VAΔU_Q,,[Wy 3ئbUvԱGO4iKpgCkEma,ϛI1m2o?=}lt5zJ8VcN~\9ZaCxi4Em FQ-`?Gw"[o~G޴᪚f5y^WME%[;3h9aY`| CgiN畍S34x`R9N(h{3^5D_!ch./-l.- &C?z_hp_J];s]-vo\o:w0mN do~NVbĽ1 DF"q b&R#0nI R߰/#k5>V'j#.J40`!"I`9pz1Ժ2/n5<3~?e1L|r g(T[V/ad_hbjFm@. <;>ܞUV_z b[yEԃi[f^Ԇj_?.5q<9|<KΊĸ%s @q9튱UIu|ReE9az2M@."`KAX_,I qÀ,jv.A*bFO04D4H A 6E~@ÑkLJ? :ׂt,u"U<< "M|!9wX2qTIn7,fkCh AT@szA4XN*hl7:85q \xvsH[ vNP~MţAXx+_7O>yIk9xkV/"mh󗚍B~xjB=={MѰz9(8~7J$Fx5A?eRD JJ,Q ** 0EFQ LREO9QX|\PFFyRrHTlj^ZGvZx#n5}lvRS5cuf,(tZSj'Niδf),A9qwPcCC@ wl@E# Ә>r4MRܙB"xtRo2WΎh`A4>xH!pvžv]n:uv%i6_(ȘXeNrqA )|:V_GIC:OeŢֹBCD~B:vulu4 G ZJi׿B^~yY IfKϝo\s酵S^V #n|Y +Vo'Y?|z|j?vf )6zaGA_SOstc0c%iW#@w&)x ;k w)Iji"/%^m p%m+(ztP*ip.jm nIjk-Y̘XT1Q˄@fjt)*40=Hw'/Ȫ؀,xZ:%PB޻?V5dx(@.=&;^ i}1z,Dl2b6B< ȏ&P 8qzuUzk'ܓPYK26\X\8p\]Qp-M{DdH(Iך $ޙ=/#Peayw4N"g='N Y6ġe$F]Wg :]x$>`Ax xlTPJe ǽk2l$F?ꩫO~j a !Cް5Ls$\~aCs:_:ţsv|Ԡ]A NѠ}&ᙳN-,_<}{?N=xzz&/Rkŋ>xRqHZ?ksBV(5ڋCeַ6V#+,#'PdAS!Cqi9B.O tŜ,< T'n@Z1RWR^\ Iѥ w՞mԃAd>_r)`_75 kt)fc QhCF@?by 5ةYXQPPYԲ-cZɳjJ-$)<P;$k7 ( ZN(cO4ðT^ Jk#i>ꀹ,&R Pˣ 7v͔f VYF/j̹ePZk:ݎ>t KՕ_-@N_?kɼV(m0lNh9֚rr~ a9d9!zA+PjRuQxrz2M44`б e="; \^ԵY_6B d XOz7]V FfYk`W鑍%%ޟv<`T't<҅T]Z/7K|&_%V@6.Yb#G^}Liijhuspoc$q]D l!_kFbR c g߁70JQ}(Qq4pt?m'5I=W6Jp@dP0^p*zRPAFqԬ0Jt+J1WžbsEP>-ևv]ofuwvOf0 pQ_ ^vC gXOWP);.yY.1?|=BdfgLc4:tE f ϟbkl,֤\EтhpKKEJeII7$K?'5Rpfjun<>V*v%,=Zܶv7^u<ޙ=skA ǖ;  B2 )!banݣ_\?q ̵kW_~yGw}{ns:kg.\lU?(UhWB :e=]2Ǥ%meOzC:NZԻX:t6P8: D^MZ4Գm!bۃBLoS@m2sQ( hG7ȍ,PJ\\z4P4uU rЮR䰃#q󕥓鬟1̃I *5GJ:pu TJ8`$Jgcf$b-%̱#o^d:[A-Jrt}XІ|;*'BUbs|@\kT7k -ގH))m^0Gɋc̿xٴ1w$ C)3Q`'}??&-b2J[.\5<6T̢=&z鰀 a2FpcJ7hgSjWt҂1DӢqǺ2Emp>B:Ȅ5mk ݳfwܴz>AM?>\ dN"h|>8ĘgVCU Fڵ=.@u'JK'eeiWv0&NE֫Ouw0Zr9v'trb}v[]bJ -0s[B尸swsuډh C{|?_+>_ {B.lW^׷\|Ͽm3%4 46Cw6W.*qbB[mN&6IP}޲ BP >NR~CUS!BU-9)*sZoYMfcTy1SX%C !fF@kbwa,_?#†|@3' z{pxU)4ҡYUdP#U).q^-a}k%pՇ,I]TY\v:V$[\.+C!! *?_-}f6 b魧o4jG>h՛?PW5ULk%I:߶h'heyBI,گW?Z:wېmy U<$٢$>O>0m&ݙD=[};$T/ /Fu`W2NdIufF*&*siJDžZ)K"7I-7ims]xS Bn݇*;vȥ4:Çޭ>"ii\x^l<$͛bL<KK2009tlqeqw0sj4kR\$ib̎Akf0ih~"^<,bl*VVcɏh3zIpY?b;;jAl31Zz6j Z`8ז2#w`i0R_jx!`a&1k-2imiPbC\_fzEd6Vѕ@EE4X1b/9JuԦfl ۱ǥƍ!h{zzasy|YkU¹VCpi{uKgMg^yݗo?<:STh[-Jf 1Rn,]:sG?};iХbk_^iHJ "i&\z*B\R%sj3U(a@a ɖ$hGV\s-gԧtBQt$/QemdXNU~%Xs%ACmig%1wRlgڛl[K1T|g0/j)8!:WA_sO `  A(2we+\e캲ξ]I.:T") b69 ==o{7H2d֬g߃HK榷\ *S#e[ʧeևdZFGN{QV3>X)d B+.U4A؆6L&8jIq(()*Ƴ|.B ^gs˯7X{ɝjv+ƍka}YBHpq`~$y's{4Z+VcB#P h`fy>SE"Ex%"s~Y׎v׏SPPe}s,|1PMK:7xq7.vU3dx@#Yi2+L@{v#fddGx0*$3[zr=>HGB=ǽd`%8F]X3&#PRJ"5G&nRvT[4Qc3X*(X:KId =T@9W8?9yά%:h5ϝ[}ÝGw2![!+A"a]=:>OsAo0]?گƝXv򻸉&]| VLdk׹镔; -'FGdalޭ||k2]x9壻]3Jנ:ѽzWP_[ׄ)2JI#Hh\!Ǘ)+%%g~ټ@1-`"D٪nB=@QMk*9%4%Jj+LoVmcBhȨz F ?iaT•8 QZmi}١^Ւ ^:v2ά/*(?IN8E Dy?^0FQ$ [B/pd'4zjHΒ]/o;Ӳ ה({WS++_?hjSq8L4$C;"((K.>b-&jDq iՖOM[ :gY XG);QZFG"~U+F\^Q7V)3vya6r_ϓ^X]J tfX#~; Z44^ps$`+ ș~8~*3.CdrRqzrqqqe:!KP`8 vݣv1 QsQ۩֛̊`4vKhJέM듡 )մ}i?~ov{b>7:JGבߤPe78=&{ƥW?[ Bat{h}΃.Oڵ*4BfpFt?]*Zf5pսhau.vŒ2+P.𗤦5ERaW߰NAˉ.]ײ?ΨLirƳA VV6%|nA`ZܦK0PJgJrܑ(0٨;|2,M0Rd?Ing _x$Zl368݃a%Pu g V>?"7l.P ըJKYuy)A6Q jQ[LK f;B<> 3վ' 9Yyd9cƇ¨B H''y| {~%+vS0@} Lty~ zdv 8)H \!b䵻[h+3֏M#pbyW˹'w>TF Tx#I"ޣhҡ5>KDDH2?tV 3@0rG\|kA;M,\9̓qqo+rϟzFaJ Z#tÏ@$zid(t[JCƆ[/i2j?񅜵i8QCJ/EpR{1'; r]$RPY"v1- SEW*Z,}m+ǾĭBA=.v o(?Y1Z'FN(OiJxe)dM=%5>ڌ!k}EHu6,Z +"!>a@dCZȠ>F[R> l~<Ž都]c Ta('8~/_eJwRkA0%h adBq77=(zl(춤}Ogdat觥ObFJi :AeRTEҴ|o}5ۨI6!#b3=QQKz?|u J`)Yn(Z\o=en  KTpS eޮT%IeSS&fD9 eccQHCp7^iyQ4I.EpV3LOR{wd6+ O]hP$*M Ɣ= ᨶ;XӁܐ|R!9Pը2FjW|vI&m0.vii&;) q;,)xk,1H)(:ma7H nkFU!)9` m1{ '2Vd'F40pDFgiEE&M&tb[n$C ޸}+ȍJĭ|y ^"g^1,m'>jֈ%0^H 7w L2C)0hɄ 3n}p2zCR1sG`,Yϥn^yqS瞪n\x7g[v!X+_|;ąsy=܃;DK'O(f,=Zvm4@.~ttxW'lĤ1Fbc, KH#ꇖգiIʹѻ A")3"٨#ş.)ux,7X iRycʜʷE N F@-ׅҒO`4/ō1&Ъj8"g*うhç["?'xJ5#;ĜȼPǸl R5F 0Lڡ/G ɇA%({ 2DA~3H#=d3K2dFwMR5?.-)Bd $>,[EG%Q s} YZ=e2ȃFBP)B3_ONS5BWS܍dfȃ㞉7~e-^H1g"y` )RxROh2aeT,؍9p\A_R"֊{9t#B{Jhņw,g΁ /BkZfŅ"LDI~l.x Fkjq7l3/]KY]zZͦ|:t%ӟ9 'S< fKouڤsC&mᘰ)e 14$_i xH.?amL$ 4P9ؓa[()U[8@tR|ib-9{%  D"vϟXaBu6ioYo9,'Ϝ\Oaـ zig^p  ePN#Iz7=YM̵[˯V)3l*|ᥧO\zvkO&ˬӉLgtc`ͫd xx0Ѹob@I,-V^Af%\[9mm*oOA?cdWV=c .⚤Bh8٨b$YQZc$_@,LNq=օFՐO*2aio@#Ւ*IB|y-60Zl7 qI c@NNyF&-@-bMUsi4Ezvn:͡QsK:s"_i)-VL!`ejFŅZjwS*bMfh4O/YG;fO`d\Z`ɍ@ 7̊)fL*6L#Tk4N"FJ?6_j`4w'Nl ,dRB1'zh+ UktX|M/]ŝ/C+NVϽ@QxC O?!i@$sAr (F0 "m?xktbNZc _9w_֣{J9uGݣFN7BX4ܥaxaOHApqrAܙmݳNZqeLJd:5a'. 7Kv\/B Jlq(IT>IxjcR*!8u":1Љ Snc| v2]i Gf┄+౅1(1L \ b~z!.QL-ٞݯ *|2.*mk\P5mxLCNFN/tYZLt5jQbhXQ-b~T(aCE.tz{Qo44L)FךQ=OE!𬫀@qqB͋Ƞ߄:P f!" vuAOr.ҌmkOiR>(Kૉ|}PM:x,@ft@F@!*"VlҬvsiX#Vmo/Pynۗ %ș;P'wB׳aѵpxV0l5 {)r$Tn,Pz`G{;wݭKۏdN-eS7 sJV PP"NwNuw^ڍZUr)Fc"Jډܼqe\^Ξ;Id?-p uݿer[:%?Qɩ+C-p@f/VTXMfP@%,A >X&)6T 8Ӛנ %\wʕft9kkȎS)F;R Q#Q*2ӯJ$v05I4ҿ>V{Y z׵ oI 5#/C)GEԆS1:Jd|m=ƅW(W5OOTUa3*ՊPJ)3,DmV2C'PDE$.4);0E#`x)cEɨ۟"x-г^^ ,fJBs=9)dI){<:V! ƜuM7$0ũ34YMr޼vq,!ɴX*Z^?X!`Y0|_yÃׯ~L dzQOJ$N8>87|/^g>3e\Gf|/[(hnmt%: GPP1ԣf"FzԐqD]r(_Ȅd[#7SFxc<:5v>'NO L&P-F(!0']O,miB CJ4"։"zq0@?+e,mm . H PX{f'#&??&S1d虦> 6iW]C xL ڀ:p3"uGn@u=s/iuFXENŘZ:YKmFI%I#+#`(Ԫ.:f7Lw[v<F_hPrqzC pY z>Ԃd:YF3=, b|k1ENmgn#vheޟNZغfƜ+ūq.?ur@Ԧq}:|EE~_|-Ew*<88IZg 5NPFÛ7|?:}S +UK˙3GFp&pouc Ű1NG+_Yk?rZ E>Y)xƁcFdz~Q:骄Id{ S9-k3^~!|r;J va.C#)c5@iWȷ*/AMÙ^~J*LbvVDV=/(i[~c!%V;ہ,^7B(9S-VH@=Oa~2豾y2p7'Yzkx=p&kw2cLגz=ߩfKff_k:I%O0vNqwk\2Api,}neVɐ"Oݭ;_>f1rC/9!N7MtjTބGvD?z=էiJ>0t˭FGpEX$b5" KF2x8lQTwigGW{nV6R^ija/# %$N 7QcV,mej*_Te5㮛]DPbQgꆕs\a[^-[TFE U0Jf!0qը֘* :'J 4@~v\NnDt5 ?C:#fQS )P[tBQj2!w[R2ĜF> 40qW FI~8P7m$>ʣUԽ`O=)=NyP (I&9X͏$TO3Z&dH~- *W[%jn,j'dHl RRrp1 9t \< -H<ۂ ]~.&2@œ 9epRG]EX8r:NDnMtiZ=A2 ?l9e1u)oEj9d^R]LR'ՠB#MZ_B EGDn"f\{ ӡd{^jyޓ]} (:tȖL,C9M6"6fYV-7JHlpT J}\R0݄.shOר7,v%#(A#Qr)H47R)ʭB3AmazWV{ z?fK˫L,Q05W/ܙ_;N@y}ܣ[Q$wnuTch~nA%XgF񴶌yP:b٩ xW^^>yɃOy#4@@ǦPC1wV&M1?)D](cр"C ln8R*)[I$ (3uRn  DIDfJi=.t#Mդџ/Gb 0D^!* $yca~0>>S\yGG4ECqx2sv UX^XQ_;BJ%*MAH_"Y*Yz[ō`Og}ۅ᭭Lyi㔪:^kZF㪲qr]OEp qɨIU4PjGZNM֣XV}{Ni6{ 6^ J5v*5X7Ne|ٕq,^c=p,dv_o)>rWڕ67],h_kӐ/%"/Y3r4!2(z}B)t=..OBAYI?Ds,Eat$j=<[]! .|@ p:vAor]ȫ\Um{n&IdfTR跕=o,06+A»^ !-3YPSfTh́/WnNϛ3]>ha:㵔!'ۗ5ƀٌqAm(ʭ|`c]*2 |ŽM̬'V\f!6%.LG%+3h fw&מ~k;dl8hFaa1Z\Jbl;7n"ɓqiqw>U)pijap=[ͭ_b[|b..6):{ 8Z&9VBbncPE52\ү/#/cd(RG}d$L\1ڦ#x/`|h*͉*mEII6`% btQڰL& %=N=%*F{riE7 C%~Q[ehcdFXEAIpbb"h%k`Va\(m\h4{Z 3E4\I($d{i9sgG8%LL2hed+FOT EWsFWÑ1/t2}"xشݕH%3m!6ǁ[\56qT2-SJkK[z.; 8cR&E8O1{"ZNO`_UG{5Jp^JGpSˉg38F3Y=^v:/h(H&ysZ^T];y oZ =5%{O&d_o%wrU"vY y7xUi۠uC$'mmj9#݂ RH\MG 9al۬>4O۝wδu'L\ŁS&FX@)IC@Mez'K8|EphHQ@JFQj_*0).E$Xف:rNw\Rr]ȐZN84EP ^%dv;=>h`9;6co!Xz};Ϭ$e#!.h#a1#pmCA7.e(T[}'=-Ni?3᜴QQT& ̶ao8*eEH6g h= \4ILFXkFM( a'&Jk1$u|^Jr(@@8"s) DI6]>hZ;FJhuZDkh5Qwj粦!+bf}=IKNVjrl3i-FaDZBv%Wz 'N{g?j7Z]@f=R ^(vdD8l~:Rւ*ը1/IX~"S̩o,|?Gy!k\/ ! [\̢-y0؈:V8SeHE/Fr9}62LN񫿉Y-`5=߼iԨW qOMk_lo789CՃF|kfҟE4m. E0Yx˭F=1<hh3!hv`̛(gۨNubK8 IcfKfzP {0^+\sjŒѻ90Ksڟ4諉i{b8O*fu<8`.}^{`"a0 >0`w>e~.`S[mj|7Gl&0^dv;<5~* LtxccZǩoF5BɜX[>sImg‰x*;?|>_|G?-K]~˟xGkus_U64T1 iL<v^g{ڬ^nv!Z{ν@k])M6Oic=}d$#'>@8}49EvK"┣l S_v$ n|dB( I\J=&uD%ؚ(.DTQPKq!~[Аw_ ąD~.XT$ ЊSJP9g1XybףAT3b͵"4O˥=fuDo|قp4 ?V;8=<$II!,H[R~Gj V3e;!#vQ]%bIɛթ|bt)AJ-('4mHnIS爛Rc-q}keԬAN[J 1)l@+񸦔B C_Zp4.wgVgW+vOv!W&8 p~y14EV\:q( ,; 2g[y:'wK;~kNg^عy=㷯~W| Zܸ>18U֣p0f`4P&JAϽr'MM~)fέ{m(}+,A,-7DW5ʣ3Ԃxщ`>;N7?EQ62,Vpea*&]y KL) `@/瀤"S$bJ;Ng๦xG4&U=.Wh8ozXC|*kc롑0j1C9g~]O(sg4<<BPy&ʯ|H",5 F(Oa_4xe1FAjbenf}^n[ !VkY F|I5Q8ti{Ef[BVj#V> ]p$Ú/1)!ZgMVh&,5'pu2Fw+'Wϝ6ivqCH*c NMQ2x?)*zlf *и:o0fv|bOkMbע|f2p2A'&%l+7RN6]rA4j`G|F MzhҠ6 h9iGFGdFR6W}zFRE1Q#]VYS!Yq>_Nŵsϼfh?cFjM)H<1/,yBIn0Fb<+ x*&3S^.;ts~-ghanBVGoG':ȣL[67-R[Nw)Gi[jHL֐M$DaՋ˧^{>`/%ޡ;*ҹs(M..lӧ#6ƺe'bCPgDrI(c{JRV针֚2( pa΀C DT0T5t1!j6:ukn H.vjb-U}̘د㱳Bt8s0꽐ˊY}`6>$68anpi_$2-4편h _>z}'@R&6_(f*?r?ty(l޼=rGR^ԌQ#ar88:32]+<:GDPU8Ν2#S1 Q)(.23_k> F0ԮJPĪ T9F?U2 $Tv[YP?@c9mٳ([rKcHrLիm㫑q>ӐJ9=:ze!rI"!ɄH|DLUW 5i9!GHYhDrziSk+qyjӚ3=8I=ueL)6R7(#PU_Q>}B:ɔ)15auظ]8WWLěLuz* w l7;>gr k"c@F{]-spq x{vjny-^~Q:鎄(tger\3Dλ9u;qV{ۛ~da;¥/AǷ -czR_rX'W~.ؚC1T#GGAc fQ#B g/">x4 ospH(:Qڽu)WOIFQtBpV Z,tYL7(NԳP[22r5\p2,Ia"NE[ơF֚_*g!xΊAIQb`25•XpQ49y?J}'mJfo@L-(265є11hs1Ht,疪JId|B#\F6mc<;tƷ,S l5-PrPBhHnx{=o-?MǙ|\%gN)QFUxJuXAAgH_ZYFH8,1P80 `!a[VkPFLJG f]ҋľu{aX27O(QGݵlXͧQBa:S 1zc{ ȿrG½jp`w?Xm5k(V@:aQjG,9$L (0PCINЗ-"&L:?/s۟}5u|%ϭ=n Ҫ5!_N^'Ox($gߠM:,27T!1.7 I,tXH 2!rOJgE<<%F 랝cVTF64ROs3J$5vXΚtˍD$}*[z-Ӆ=ȣz! q;zcN^,/P~z㳙pL"zchR?|ѓ"S;g.q$%,Z;s22x:\ޭ|"3YJŻ8vQ'O0!(HF!o!涍c~kG i\KfC7(p-vmmPۤDlm7ҜJMP| F7 k"CwP5\:tS pZZnG4~D`/I/Ң,HiЪdbr 9\8wY\zolv@:k+eio|-YBv.mCD>#^2X r2"P_| 5Fc1hC9=%Z͖dBb$T5"!a@jdv&P2KZH pJ\`2^ a &lΤsz`r:n!(RԺ\Fy rhI@2j7 ZQq#&1J2``|p`i,<>ތF e2GZDE> :tˇ1C ON bh:X0b)A  _x\0D] b7,._y#m&WV:\>3mK\ Sf/eF8esGQ "ZXLgGVb?DQ;,ֵkGro _$q@efAPͮ9HII%&i ~[arJ=35 taJ^ F@' fdN/n括__2FGt僧:Ҏ!0$s ± 6 _0NY4Pò{| SXX# C].1U;l!Xs W]7\~4Q&ð:Z,,+;قv6 yu5P, Rgϼ]ߠQĈFP.̈J]e=`pĨYG Ѐ̞r;aAw|7#o$R>V</vZ<7cX>ɕq^kU'I$nI0FuK/BOcK'RK˧OQ kWn((W(iXh{\=͋aBҩ@*ocDɕ *WcjУ@mպPCFπ*0FM5#i n^+J)%T58 :1(?Wk<2n>g2z4˫ d\Dá\ؘi.YD:Ӭ<^G $%S8 \j&'^V)GCK{{g_Wͅ~4ҴӿlzWm rWɝr3ߝ;}"V6hFXx< `h޳xfȠ />魭Oޝw\3s/J9PZIFEVvJu GBDdWK G/E#_bthH$6Ԛ2vw {f5s8*;uv.rib$|ՓtWΝHng&pW> TD2EHg*7QEkzAǠG^d"b&`f'F)(MrpIƠaWVrKa cd_JV.BI'hCuFDX:dʭSCC:2p(ﭵy***.E_fI*RX#*#Fkjn:9%'PQԧ2.d-$XRMAiױ7%5Ѫ0p8<"&¤ޗkc;ʶ ѽ[lr~E*wU> Fi 1x{FGi"cJ4.MÕ#'A]# ;~U%*W^qU͸v+*%tgVTWP<#8FtT/ލT6P,LEJ/ESO]'|/a oB'+Ϳ Na6n}\|;xf?iD?P11CŽ0כeCijA ]1}/֙(yvp^ RNvbTZ9˜7D:RqA/X-Y^D%gY|ˆ;'`d.+_[S2SWO& _ P|ym}KWjVgvdσ,!dўQ ԵC/5{/][H~y4,Lr*aM!Ĭ&x u!B* sj;u_8İ'`:=6!TӉq0#L h:ýRepЎR. A:D3%ԟK"3鞝}ĘL1Fnuy8s Yt6w/}Ûwjt&椦46*F<+h$2 <~VMwvX>Q8gЏvSfTڄV/e/A5/aO8^B025;(--%_I_EȄE ٬Y7l*aF|<'* O(Cli`0rS1/5Z hNgx#i|'4hĞyUسއ/pbdd=ã{ft6P,jj/ߞ=vd LQ9L]d$l5\g8 P8Pg!m{fYEƹU&Z J TÑ\^6t׸:hƈ e0 虵;wT-.ǔs 8^h fAo 'RKkirש VtZ0Ir2 { {@q%DX1~sSnd6(3MLǩttZm%DC<m+'{oR(W\w~LH{}m3t:qym4?wX}*3߫<پ񣟁G_gҠ+c D0<^ %{w{L̋՝8~o^Pċ/DV3{w"˯ݿYyp*~'60JFMNGfL $[JbK ,q`ԁ "Vkq#''sS:;4N=EE.czi a1ՆfhzA*ee2M~f+Q]B*W@g(ǴЙE_u5fV"X 8)did#5W)ҍ2x3ډ2 d #Zq,1LAX*c&rVz$u 5v|OñTˁ*-Y|wtV3~tJsٍxOZ>+w4Je /L;*!6(F朅b|7_xvKZ'_>ɭ^`Yd4$w=Kӝw_-+V莟;y 2GzaaiM,n𝴺vO,a $j|P:1 R/߹ kЛzbҍa+3x}JZo2JTXJqԗ dY4OSe8`oiۨ{D),40y?Ľmr֨iwpT2!ƧT?r: %C/|0GbmYZHͶh,sn)[l̥vFl$t*J6?9Xu=bbKg +ס%Q#B1'.ذ{Ll%Z @ځkӑNAB赍3 ӳ^=Lv'9[-%CۆY ʠVMFPgw7O5;4¡nqb*vxr-;Gl6KyuM/0N@o=xB2ܭV̯PwbΏvq?L!rN#~=a&+I i;֏G^4kȋϪ{D?ӁH>%3F0 P8l:v^.儂j͍_?:d-huq(5"sp\!&QJIŕJQ,_x{?!膺vR\C |jq#-A@rA FMme}jGh'MϋU)/X;/5$lyqX=2{v9?_(؇uV-zU! y2ϣ$QxdXILFA ŌJW:o6ALWlы@.}Fx#wV\^I-.d9/W(դ9p5Xu ,vv(>auknv|~8\p!Aw,yC.=ևnmwwn)t wo+szZ1uٔ2vD(*Ѯ c#b){8xB"V&ҋɉ躈ˎI-<-^/)f-&$嵲} ]wY! XlCm뽙I PYMk"%6Rl_5?V+yK-) Vn.r:BV\hu4 uDa/q34bJTéDA G!W@X"^, e룝%{633g$ekAx$eEc c nfˠT 0$!0MoP?4ɏa `t*I ufm_# g^EӆhDXMWC6v~vc[sd)谣i6Vi5 y;% +k6O3w;{۞U3=-mie/\Ko}|~ܛv^L_X?ovzM10eD*`x2D\Sʶʰ֔x 2;*~ ^᧿Ͳ/xlCaeD<!-cBI*2 8NHdȽ9 "YH2ɍp0E9) `}'(0"GW=Ij!P)6s=~$ mLB +Z~} ~,ySfAN<3 #ZUO>bbgo^*j_ʦ91n~`js_j_:כ4JـϷ {#yf\tat ۽1|f(;;5WOO}Ӫ]~&gggH"mV}blӉ/9c{`6htÙ~{^X~noꉈe.]*5k]we'C空y΄Vv\-nE꽱L{EggEҎ(2917:62-z`T0gW|w[*" 7-<4"N&НT`: c>>@DitVᓧ[?LE^۵J괾LlTEZYJ.U"E{ZhK"aCi]rI d<Ȧ $JtCQaj"PV*űX 5K#p1qkci^ fHb G\RҾgӀ_1Ŗ^9Yuke–!R2MRyyY vƦiьbvfКkmr{`iiDI𤬾LxvΦ0Up8Q&r$ Є= ]Iq1{R{5 lT;f%cPY&5H|Aqd; ǞOÜvk4 :a5fo4JEuWS/z;V}֠3`|hkQOxbx4?2/ICTHz6w<~46t43Ш-.y|ኋ< /u]yIŲނZ5#C)I56Bil+A0gd&m= Pn Gɘ ɹ=~¢@sVMCO'Ȍl."<6m?89k6-LbǥAwCݰtؽ&9ܢA,w%;̕n$ b;w![,ˆnamXD2m{04V?`G4gx~6]vm4ηڵYNԜP\^ ^j/]yv?Mhэמ}>vFFN-CO4bgߢuX"ڼn(t&'ۓN^},rr8aq8m;*WCN$?0 dZA&NGe×~t}piO(IC2hvP/_cf9.ۂ[l&DOz?'eME]*VU&z_*0jYt;$S0_/}2/U*ɩ"{5>Flyek:j{VE+`䩵kHɗIZU%{2\n%a3 #҃Gn^ZD.Ƌ{[TUٔs8N͛a*@4|DP;|FGe/xv_^ [ c/! }Q%OZ.Y(v4ۣ4&lèU0=x7N:Whd090N[z3=}I nlhzk"ǃKbm;w@Ba*5m9\ /*/(Q Bgm 48F^fA?|:c;{g8#k^3vk;JoW^'vOxQZN7/_9xvVe1ҋJ4!.m2iVK^{v뤲̅vV@ 6Pf.R p_WO흇 |xgkoW^E.o1/|@sGGϭ]]ka?x\UXmjBmV@l2O*Rk^+/Ja"{y!#z fj81G܌LѝˠM{q=Vږ&)RQ&͂P"qhRGgIJIh39-UUJK;YP9L۩( <P{q"@$WiuGb . *wT{=x;e! U]L#i(FBiyW*5J#&C`M*Anߎen P|W<lĩNR!KͯWr1W2,]Y@n,@GY>ǣCgsիL  GpIcZ@xppxC:3RIE+HOyZ8젅z XA;B'σ-+:=p(vWS ka\ӛt`׎v :yOH Ϥ* x;_i{SXZclRdux\B`-ZC߽!+X%_vv7ԑy_gF#3Wt+h/jI'3(^On: QN,$mSJF٘ IDOcZJRTDffx)S䦡oAnA}K>F12iv#W,m܅2g 4-"f^4b,T:,mKfSBZ? V;`[MBS Dt`L) KA]ϨaO{hut"^T>'gRy*6&p|;i2ZND#5-7v7A<&`f=zR)n.{XxҞv׻}vV2")6#0ho܋lx!D@6 Rg:=p ȦR{l ђ@wL#M\eDj=pJ+VpI1zN@Q=g[tgX1?LEm".G)ۿvd;Ѧ'(:BBwRvQшFuiZ7>oy~m0sg)P%~L-!ca.}s<.d 4kpЧ1NcOZ#~|E]"L;XKr@r!kmbivt"~壐x}dӓ^_\ zzM5 CK/ғ 㴑5Kit5#[*[C5/P[-(Ֆ&^K^p[4P+*1I/PJ{Nf;Owq 3р%(-}W5/T^$`zSEEg-!9F[e]jpi?++?^z]+P-K7/^8=:;(Ⱜ5\S=K%,̦2JGGM6]PA4ώ^Od_T@5fqKzd1:UFQHҪ6j]X5g RGWKB 7>yn_,D?F؀흴D8jе[@"VJ{Ggشj D1p@w}.hۘń+W2|dhr(wPelӚv:lݚ ZA`^ loD6ϊ*t^ A2)^&HQYW//0f!JBb&|pK5*Jӟ̜j::?[]H8#|أyF["bMtdwfaݳ yA+qFV޻MW"(=w (0k,j@|X__40n*כnrWl}wkwqaT' &=O*d2OBuؠL=1^j `ow<^ pvt驽j ht|U(`=c}hE-rDeVnK|p FU%?)+vr eumۓY[ۼ{xêt,_M*{ܸ§G3!3 B@ms(&%}vk, rH$Lzvo{?N"g+V'E_]r`vg0o\UVHZ4K[w =Q+g}'ϼp7?K~_ur+WƬ7ݏU8L7 UHN; NKӰG1M25TW5s *dvI x--ٱeCӞ,">V;)/]fEeKt%"ۆh6PfZxDDA]ә9ʄED9_OKX@[֔Z(Ɣ ҪBF!@8}p5(y[ 6Ix_U>3.='^3Q)́icU&-LWGõ1?{k~.1ek5dLFoOl=*9{@Z\iaz65c@Ua3* Lij\Ec f ABUz~|Ǭh4"rVӎ)p5{oh]_kR7ᅮIwiboZhfxZk>ȎVgH.`ikΨC}LHH'tcxg "۔Ñp٠+2-<@gxi3BD9٪TK_g?n(Br V` Dbe?9LL!hlR2BΉ+Z~Z('NNqȗwؠ1Ći,ugџrLZ2MļPJN85q;|r!?:/.Ao \9J56i_*x饏;wOܧ>w6?gF{0<+p$'/\޿;9O||)^xck|7~ch&  ː_aQ{G9\ <|BM4 2@ j3[']{0;nMyLO#4UDRKK(mO,*eX`eƭܕc)6xߥ"vi(PSIАp/$$*`EC^%?yR&;YRe߬f4P._ЦnZ :pה[DT<⧾%3Ol>dBޅD hxĒq1xhe.Yju]{&$sCPWqoz%eq9OMcDaiNu7֏N:M{wڝik5+iۃʠplza186-V{}) Q=:8q"c>u~BV&oB0ABѕ6ND0v>RD[s ##8b&}gtIw:gp?חϚA5q±㣐ד\],ְzx叜U\vD hѾJ>i vpRW>̓;'S KϾR*Nwr;;!_^XO ?~ҩT]0MLk\D:̗O(;M1UQv5Fse(*oN:RBϵl"١YZҘyDtSO?-fzqfڬd4U) V/f7Kix'a3++قw Y gO,KYC4=[e<80tg^:9vxWljhblYyiRKӬ ikWPZ']}TvE/\z199dYJt :.MlJ I{h| zcjX*uʐ1tF6 0v6H/hb컖O/|5ί\w:g[j;l+2= q7&@Q@C`x$ ²@uM&I(e&<#ZP$s#h,@irp9{PFd2H*!mHp7G<'7#T3rS21<#&C.sJ"\x^~~$0.#͑];zsi>}ayya*ܺިGxqqڐvp@vhCƿa xɰԠ?eX[;!M0?2MD$g\')C ʄ,c lchqOΒ !L 43?*!G/-3ldř3E dla$jD([HSzSx)@G,/⩣e`2ɐGd\9#ES+X\s]@ar9GPhSNFD,Geo^l4>kgV 5RK):m&QjT"ƭ4̹\+ZO3qc:v2:v"et9gyOa2bpq$fBgxŵV}R9f3\iN 7#KSo!W>'6D 66gf '.3%@8zB!G2(֙(قc 1E VJdxPhu;܈gIO:q^3p]LEvp0zs^ I[Ǜ il~Z/^nQ3`q]vSa/."PдB;~a.Z#miެprMG~~thha5u޽<xj`T&Ŏ_}v(yeh>(jTLQl#栭S 7nSrz-)A+ F.kwRս -B?A/8Rk3uҬZ4)Ji݈e'ȫջTC ބ5&~l^gŠ-O4Z肨ϰ &5 f՗.,D!)(iԤ*BlzxY^Ya#23)9AȸG{rBm?:ɀ3fLҕ4 tMcYKV9y9G']9諟_O?;_vNm<9eL0@Rr8?t-C-J12;X? Z(*92qp2%m2gkx)(b'#Fj{!js2BoQ@!z1X3It:2-/&[8eL[GD R GI `Ev--1=WwzgQ~s#oXHn+6+I6;*2j8W;C.[nY(߃dq8Z!T굳aq\GV5:/Vc}pR/tǜ/#)<-=8 n7}A<>(x <>TϽ>;V `oP-u|8)`۹[F4:Bİ/еK+T =l!":N:내Zs 2=iuM4ᕋ7vCmnayftyѫm2˟R?wkTKG'Rpg+/# [V*ܳ~^wDH.N|;BHpGZ<꾰q1q={|λ,_ˬnā<=|>O_ŸD+?L&W{ 1V/nL;#4@h"jT {b!.߸Znmsev twyuحAd Ơ ۶*6w>?s"2MZ(B])d@%t?aI`5?é͠t|ĢWq\;K (HԃlG}5,ii"r 䳴pӀ۾ im*6m:9Ȫ9mLMM%BIJ+A4lHnKizl<7$~f$S>ezD>9Z6!XGE2\ٶ8 &vAP S۞yjפz83HrzX[hֺR5j5l4[bQ W?ׄ(=`rIfߝ%  k,T;H[AdsV饔Ēˬ6R_(ե[/ڵg.]՚aI _ Bqpt~Սxd'Ӕי{A˃Ef,WۢD_ 2e7u94EdXv}D<؅fp|ZܗKy=1A7%SQD$8 F0j7耼O_c?|wo\vYZ& ؈t-Ko{j^|hyuq:df7Φu4̮\HDҙٺʫ˯{vo΁}9~Oqg x}x:-gnͯ_!I];QL:zxV;ݪ!is Zn^q6{6Ci13Ce¦vCd nzN/ Ϗ[&eVy$vr6Dw/^Ȯe\ft4 |'yIig,k؆;yTiY'Xm)_eT4;EC) Y kժR5C=[DA5o҄XL)S./:ڼәl&_yHQ'5U ]dUxYC4R/iCjnȔdQMg,V g=O͙?jm'5!Mc0hZE7 qh6#=Jx-4Z~dbj3^e{vrGխ:xX'X(p`_M|?B nS!̈zQ {W{]k lusg?_*^?ţѰs#Шr2C^֐󘖂6?u0Nj0zctNZ!xw$dC࿔֐GcPz`(:-g;I/jGf2j7\tIF}P﬷)-/Oꭥ՟KӋwN<=zx=oఞm5LlWtKn0(7_OP蓡0B8:o}T4eX)ÉL:~b}b(苧?|2lן}'B'?CyO.ϫ,STrgW?ݽc]Yשrvڣ!O"I/Ǹ17wr旛pT/xZPmVHx@ \~wE}}n5[\Q\(̜P,۬0yR(.{,ڤ Ee z+:Ѓws=;-HHy˫ϽBz|X;B{kxzHu ~nns;鸈mR>aS0O_;"zEg%{qt{m U(3i<-oj7?g4.Ri2[6ϴgpM,?;!~l9PАrv^^̈́vϽL@^+%1MAngI܎ݕfݧR̟r9#^{۹uNƁ=6jBcq@{xxq(](*/”=~1BV[&,TQ{F&T QP@ ^dֈ@̌B [!np3Gz!hDtܟ Eᨴ[la~P|zZ&ջC;5~x._(6° yIeSb@w.[ȅM+h<>Aʭ Ur0}㍏g.^GkU(>&aRO}"5]$kh!p'[-*(D<ǰ }GnWtm 6eǽ|ZG;4KVF7s7co|;߿ǀ_ҫ_'-ZY#Wod.=z'3q;B]ۗ{+ZOP<:Uڵ\Y=;;.uz0>TZX62nfn#4M_>2ا+&diX}QQBEz2pd78?9^ FSblp7>D> =4LS7mSRl+t"aUY8d 6#s*<+XrcdJ]+Ov_LQeA^ez4i!o"P$-MۺQE%3VPóOc9;RPFe5m`Yk2m?O_k҂YkVji3sMgE}QÑ4* ^ j#yG=T9 ||ˢkT'{,#5ErʄS_EZq< 1+mMY#7Z\48DM߻^zrX@[|/=;+DKZ Jln %3!$Rɭ^vc( Xڧ#4Oze3J%P7:Tl&_Zso5HntwUe5{G?MݿwN/o&Ws3,H잝>L)`?~K&Z9S#Px8j#Ƭ <|G)[/pGK[7RKL3NKhPK@y 6}%5I5ɬQɉ4la` AyΟˑz^Tbm#Õ@a%yiݳj[i|o`( ~}h qP[62 326_#UbPu:&SahM7i9R qv̨6>EX{9LUQ{/LzAChKB8Ierd*`y.2rO$$iyWw`&LLesMiRRY4W/ sML`U%[|P?JVsuYve{g[i<|;::=|xr4w5aQ lhC$R&i{CKL&ΣG{j,.b0W1wSt.m䋟_~Ӈ>#7Dnp`BB I7Q8)8C'g@W+@7ZĆe&/cRI_&~)fT*K"|k‘ˣņY;n ·34qN/tҒ(O"rKKgܒ|LDKP?to #lv8Sa"Y8y,A2 U$r9O>!zs;^}a1qť<`&W7# 3Hl"A< ! (*a8`ƏtQ6mߤZ$˭FknD 3֭վwN>֬MjU'+հǕe!PП ۝F; X`x+Njn3cLƢ~PZq.? 㬥lwFSC5qC42@gD|Hf),·;/jGw}x ɅW_}pJw^xiU/ r O SԼ|eO(׿6 T:H*q`VHP`?z nI5Ч@7{ln Sq[~w(ZX<~VX> wv[P֩1{Tߛ 7z3L,j5I>gܪuk+ T"Vm0&jV,6hqrDsjxv'rT0dP'ug;B \9ԡ:e )/a$,v;+J?8I$'pֺR*/4h~l#m؆8.h|4Oc0j++KGw@&F2F f6d> x$`V/IeCjHБZ ڴ˥b~\;H4LdQu夅 zCB0z}.CI^vV_ru0tOw.l޺{&r/#~}=L&ӽǕŵ-)ٓB E.O%4d͑G-D!KCKk7??xߡ6_> #$`ݧ@t7p@"U+<|qq1*?Φ aow'7*'G*2ӿ +<@'dlm {O IDATMp3s?y!A T0z YP 23{SyYEɌ*iy 3!t0]HEbViUf~Xr^i"}Չ6d+{jҋ̯d[ZWGSL`&(P2*%bd&U#%Se 6s(-dj$,7z=N^T^n!rW/c,u:wYhcKc˷ZE=R'g`03kgܤYj"( ?][%Sgh/*sqY"=S_KF ;jzȜY~:|~|b}/_rW|lkwPE`JZ>~볯nFXrGCb>g?iqX=f/ګxտy>8::CWS@E&MQ|BYH/2 *]eDs&r,2)KrPTT1]iVrk"h|w:N <b)P-k`t=]7F)\if=N$ z&dCbOH^licewg0yy/ 30ˍF@oB~u0>,$8Ed4WrQM!h]Y7hÒ0Wbu~O388)|.b4%&#Na?H0՗NB=TF,GWtCC^gRL> gITM+sms'I&u"bAqVt#7EFX<y\{F^h׈h `@'=4yˍOߛZ 1UmDH& ټ&ڙq)1q⦦Tqۇ!S|7j gϚB TՂ$b+a4ToN7<>06_O햟qMjȌOF/ Bs{3nn`xq}<9kh\Ey'jQ!Dڽ);trz\7-VA( 'P.dG>u~O*BP.sfAC"s.PSgӅx `x OGOvPXv.g24YT[2nbALF ;GLW j>O'vTJCgWz$Y^KhÙAԻG"|4n}4u镚[{jܗJ\p*#f#,<<: Y2ӯ D0 EP!OGOVתbw;8 㩅믿2hL4[~cxVE7$KXO cl =+y~t'_DIS2tC0q,zSp|Ko0(W6Ҳ+@w S;G?&Rfo ÿoO$~(c*%ghGB rIN(YyOmsiZOb zbL(MaJ53Ob\?/*m]SlT/jE{Y (|F:v[Qȍ,e'8DsH{cDg5Ƒ=ˑ֫iiF~u u$0֗ taďݬ@H_^~26gӼ??Cح7\;//jz @3^ˈ3K}]L5j fy^CUw>/9-EHWd~6M?Q2pTxE!Aҝ>0h;R&*e-:S'LhԺh2ázϚ|~LM >hp@ dL :'2(Ȉ0ۙ: ë)Ce3Ikf:V>Ԅ/5:d-;#9c0 p2UFY;JNB`C14(h^EX±q 8%%GwufCV p" mo=.@$|̓bw0w$[V*m(f8gTt"1?rc;Aѩ aaM zIcTrBF9b @j{=S$[U^/t\A@ptj,.>=>` +!g<} Sna~ot^(cTz-cf>CI<ϓfK(çM}zY]NarAv@@i  u*b,& T1uSp +늄/ 5h 3tj R=:X{O{{zwN=Dg2:b)g~!`b.$+f=dٓd"OG6gG c֥5:psS _ݼ*w|[4cu4mA}|ı:]B.y鸰KfirSaaү1}̯yy$-7:1Tz~pٕѠu58:bJwzãsT<"*&8)*t:#@0bLaO,NY1H/7ؘ'VgױvNpa+`<Gp/~g{_t[&qdBHVq `&€}Q $z[uI ֐4LKHJ g 'nW,Xt!iV\IXvIN*\Tv7+#|vf,L$d-"PJZRX=I΍Ibd/oߚy^(Ǧ\[NGu-c(a9k_[Β2-Y')7؏&:)zp]fB{.3&3+tY OMvyl2n!_GeGbAIfd ]UHZn:$\e0-kbS\q9Ƙ0[:0k w^uREPFj9D)pj Lوr|\PnJ)L.V2hT_B:p{”C[VgxmƧAOĺjg6yb(r9~9"p8ʟ]h;!fz<2D6'̂GbnnOžH?!6Nj͹ =WНͣ]3 &zZZHQ.B)jp2cSHe&v7[f@RswhЯ 6`T!@J >;å#QF^CՕ2%#65s4O)gp\f= v>2M/zX@4QhT  Y|-%s?zX<ɿ;ˬ:@+<?3;=1_&/ܶigH l lZ (ͯ10BH,ZJN5rRZ&4v^| $gSaR4)HPzNZ%lAUqH&&q,';:\APPY8Y(sBə yi:,[IgܓS[cuMtx&ۙ|żj [z<"Y|MZ)2|8-;Md,i0@=\i)tdW=6jLS9[7*w0kRU=Bo! i>{HH˝Җ*Bʄl j uIf:UZa"nA\(-LAW,7 }Uepz tSTO z8ÖuQ@k@#Y&n` )e6$7!O|l;;HL8a ⚉cRD!pl(#G"~p3Z2\lQ('G 9*/Đdq%ɳX ܾ]oAA ;4JEէ[HEq=j- XlP  ^ PT45Fh$ }d0E v{qF<}d܋֫Cxh+0ݪxGw $4.*,ɴwTg6ȬOK|:yӦO݂`'٥kn~~xnUeDž3>5Blha9S=;FJS?\*fsi1qm(T7o|(Wz?jP, v +>r/]w|vf!Qhzio(͓ڹEh,=N*7YxdkHdy_Ob#S.p| )1vAN C2.RgBZ%bԌ VǤ$!jȉZoBrޡ`##h7h$ď*stZ|+k>YcKAR6L,f@݆b?eJ RGicLJڙýEWXܤG;D6"peV1+eK,j$,!i#X Kqlr+Ҡc҆,~F&fxK㢌Qo"gz9zaWg|~x!X'a!Rd= 6gd5a^7g>ګϚ{1L=h#'/v#崌y&i5Vqfcҋzqŗ|WoeC/$ax(Q%ӻU6,˥4L꟥ ,}m?>>w~;bq\[xՑi<)UMYP F8Yui%G_dZO:pdQPr}eLBJeyi1:Jc`ɺnxn3iOFD%|N]饗@0m6MD#ɳ0 r&upq:0"61%CO(iM`5<({qui1Z5͓9n{,`F|^/ȚL`iw?1>Il}7J0w84 |`jd*0@V6 s;ž |Yڤw\?>sN-fJ̲3rZ1uJU,D]q4jGAx ]l Z=%),zEO 04 kF܂'5Ǿ?:]0zMcE2GEj.G?O&4qݵb59?:?WVW CZꊚSå7`QHIő. M$ ?ŻQUmq\Be 4A>MdW.4a! pbͥY1XLi*Q& = Z_R%~RWQn<+?p)u>~FeƿtXU2T,֘@}qeNl8PG*)^] >m+bF_Vis^:q]!s@0DV&T׵3o5bϦl&0gTc*L,baUE;ڔFPgT5Yn't$˨kՋ^HW ]UXг!LOX]>)1h.Tظo hܻUIn(d2ff'i:<8 ybMD^AؼFэcKՍlЋ$LMY%O=.6 L"7J8`CA~@8¼* "~ AGӥr+6cxF5aZ1VS'͊>xleB眡D$V,ewRA|}'_ПLVWg6k\zW!*=![|;/Π=;D4vh%x"#x||!70lٓQvOߍn7չKӃX$䝐{>YJ(ܰEӣ 2BnpoFra7{Ў>(^y͹m@Cqʝju ̤Q0!}ÛaUD&'Jv։-8ÉՕX>mWc\$$SyInO<vI{6\1Pt4fRD*2/ݴo)GLAZ輛鱉eWSMgq̙,[)ZŨ@X>h0'7"y5a1>_AĄJi.=啌{~ʼnA_1K&'d켄5VQ mV'˧>wR֓ԭZnyѲ_H~I4@ɰ"\]p;&Jb'si»{խ+;فz=R̵N84mzj$ᅾE8kQOc6kZ#?4ѫ(%e=o  a9l#c2+|4$L vV,Э}D9?qk45uqKt(hS=HI> =DY ivKمy<߫kdw9N=|bhOj2e!! 2s[i{4&N>xmXJɽhƐJ&bʰťycY}\I9;\:IBf落:@R$e5efNc @Vm*9uJR _hMnldGc A,MRDzHE#/j42d=Ba!$Fg>\ ʷRW8 %ge\KL94v ߹I!{"NW8F T5 yCZ5BlDד%Ѩvvd xi3 1RG1xL Gm*jSOem-q#]ћO'zջ/Fbqw:~g~pQk7%nۋ/},=z Nܾr#oS}e /td~;/ gjdڭ&33"X0H<};?ڼumLlvqyy9 G}HDR#`IXE]MSP<4ixwe<^[8 jG-VkQ+ zǿ5P@ozm`(xAcd{Bth`P)uvALήHUbF$2H.n! Gp28RZ}1z0QTWŁ\\bS+ Z4d/slR4KVυtfٕX>>0ْhWhn,%L#g(9H++x}֊ZGh#{LEPkNƌmڥ&ܲV`ٔjFZ[t_1yE6yN*o[k=9qi1@5K`?3ӓ,8nI(ٕo.Sِ8'{HNq:2.V㰟3iޮnW|Dӟ~neZ~~SV͚ψ8,uYl)ҀE5uݰöt (Yzk./h&f ~ >48DML/J-O7zdwTpMФRqC"0@r еI:HJRht=kK98Cv?v[9VO !E'Q^y6b yLh]Tlp+B݂2EC`xgϺZţlF1o̦=J&H8^vZ;`C)=c 09Pࢀ8-eL3X'Q+>+K4^zq|zp c{KSѩ ϯ}׷wWR]l];^q5sVDXL3:Y;h88E\|%gRG303w}Lq >D6=mSTpcFuu:⸧y5t>1#*~?}eؗ~Uj((l]Yg?oWmE7|[K[㙧Y]}{](( >pog':KWy5ISDj/ jwk?v]\CȤd[Xc֮ݓglraaI>D"=(wd?(xYxN{ 7/]ѓwރ-nm j*!Ruy4UXQW 9 ^]Pxl`#)NW o'"[3=++.u.j<Х<-sl s]H1뮖\̈́u=Ԕ_r~+cGht0<ːkeYjy̖8 "2$&SfH$RR#n9 twh`əo.wY#5m/5׷\فqّ6_)(\f+18I=眭zH&=LG茠_ e< *nx^agkj]_PS$yi x( %Uoe@ Ff .܇<ɬ5U*t^;HلDC=Gǭy3| ݓt:mPDXGsvI` 8Ńʚ NSlhƜ3{ϛғ5no.~R-ƇG&_.^RjWvoO^CW(˴Hy}wqL\02F4eM%>(ʮy6⻃Y8GŜR/-z9w t!a\1WSg0At?~XGn J+4Խ 4I|Ѕ1gIttz^ vzJ0DʤB2mEN @`Ov ǩ'>DJRϴ[FG 4Ih6pgvЬ0It O}{|;_?YZ߽dDo:>=nR\ x'eDfF QN-Nő|Ewuk) tJ"UajbtF]#Y1gkJG94:._UEj`:B c۝~6WV>g! ?/7Ǐt /e\REN e"5[/q %ӗk2Eի7ѴrzHYhO#?st}޾l5^`. `On99$: zY^"p.UO`[/5N1cۺ(nO?Sf G'Z+$9b8Ն,H,w&8`>K|DIπ;hcAlfBTy*D}i;nϦH4B`Ӳ,ǢO}7#'¬8C/3 B1E!T!v hvND6#sfCIF8:咹Ωf'&Emg2Kx1"s&Z}Bq4 [ B0+O,^MgS`iflҬIj٨\Vd!2h3*FΚ~b6ՇѤw[.\.]9yX7Ǧɩ,ǨH9I՘uYZ룿m(cą)[>ZKkEd.,f̩byH R4f0kh9Zfs.Ƶ\PqF8]c L99=ݮ KMԫb MZ :YҚOAf"K0jĊQ/]`=j4Jդ'.'5h " M9=w.j8n &g>CHHCL#a? zFˋ‹I\`t1v$*BIj6С얊u&Pk|i4IK{ӹ_AL٠b~8C:ϼVnn9w^QZ/Q[:TL^8;>lZ"MG:cpf' a$zqEdQ~oneŝ9Z&+S,\kABJ,dW^., &C;vme1kk ^XY]@GɄdppwpK7³g߿Szm ҢZ|^|0OeMНy{?xOn\|o>x+O~ w"ŭQb8_HZ.Q( ,J,;xC)e|L&a]n6ClNgW>xqsu8  ]q.X3fj UAg.b&TM =@R|ĵjۜRo6sFޏ-篼z65znkk3i|6MJcD IDATB1$T4S_[{0yB`\A+ųD6QҍA,]Poupte%u3N|k_{?p_Ͻ{`U>+*X9U{]|V+W6nܽg_ohy}J7dGopt% Il,e}'CdwCb|4t. hU8g}&dC;Xrb34F@!(`R? .ӫ [9ԠiȮҎZ4LQ2t^Ex7֯ϾU/'~ /wZ>ׅy9ьi󹽀|h\\-ʺp, Hڃd96g= NM)Ž|G-fϝ~[S"{OIGCmU烘?[l<9+ ~r4{b, Ò\шXwAO&*d*FRm3;ЂLelՕN|;@$ҏA*ta0{o[̅|& k0!ta)|Iz1{VVk&> HC}A00I$vN03L4˲VM/men5˻KW^1_?`4]\,=fHL8aΏ@Ȑ( TeJvP#8-Aop'2!;/Ceg)_o}2#A:hޱW 'eb!9š#1Cj߉ ƤW̼7L 2lqZs utDyYof2x.gAAmx`!-bQc0G$3KJ&2RR)Md `P %cf 1b|H 2*:) 2ꄥqZJ{o5ɐz|_܍J9$5Ri/WDq\,{tȗH~s2=tWr7F@QvbE:ƙ\"L@˅@2e1rMWQMVFh dVֹݱ(&%EDN5wj dh|?4x/``KL\~@}vxG0/']8B#2PY=7Γ*%sC 4oeeu Zq@--9,#$+d೿4G:cJIuf6[I?kv2sPцN݊;)RSROh@!P)0WesGgtt4E*ndwyaSB,~sP(oϷ˽dٹ`7\\RIqI!ڵ%=-/ޒM!6a2q&Ix'r~"M7E13 j-泽J)O *`{¨ݹga̴X[@|pW{LKl' Jz] s}g.YTQD ]7P8xtX)/][zo x)A H)8xƵc=/7Y:h̸yLV4 ?s薏 4 ~q|+ ˡt̺[W)͠;rMRU-^]ϥ"˛k?vlns7$䡝ۗ RMË7nGo5lurȫ?|<*?V~PnwAϳ/ʕZT=+~ q n3/ͤZ0’M,, |K SME!)2ߙ^]c'IVw'V.m4/ DQ8H/.d7J6d ~L塜CX(uj)Y?[H6AyMt>`%lיbWWf1M:D#tv$#m[^e2Jjz(\jf܊E$r 0̘-ne}~[Lt(>I>ZA|'/.a9 pVSVke2LFp3k D̔$uW4~4G]YqGZ1KEHRP:)[iW F$)t'*j(;#Rsڞ3I~2/L%˯ZAΚW-/N\h&+irї+lJLbvL^'WGk͕7'lQ 2F~o\ٓz$iV6iÛ +t֏~^4T St`qr&.SN w C3.u{aC8 Ȁ `dXv2>W1#R*\d2w!O 9mdQ ՅЪd2./#I]*$~%Wi+þVz xA0vW48FG-gMv}U쎳<#PF6)sRR5+Jf>+*)`n-Rew>JЎj䐷ԭ]o"^>YP(,BE{}u#ۺ bJqԓ*!/Di8MÐN6C4A``2 D€y@D/Z:L$1 Phulcƙt&nw!=y"'sv3KEv=>;AAӌ;j Y55) 5B(QbORbmq&=Õ}Cb2R.o8y@L&3xn& f*;/P #i/e,Plu1-z$^F5asadBEH:'Jc9ITGnY4 wY5r!6t\ D-2LRkBy\ r|<o~ovsG lG-q^1%y^:s?ww%%W&)[2d @6(o _Н Q+.33z{:9V©NVtN: ~E:-$VzvQV+%G!eQVQ^N;dw`0qϯۗ=qZe*pQIn7ەs@Tۃ>߳Mxa2ñ܃lMX}0T9P:wz8p=3;p@'s Bg94|ERA`1 MZv"!O,]]%Bݠޙ<8=vœKB{#4QBL(&Xf1,ofk&ƃ7?ytԅ#41cþ_\^&</8΋Z,uvKռXqJJgzB(vm-ۿ.ORY W3mm&) Wb܉^c>&a>ZpN3kÒyh$13B=O jåݏ|jQߔ%|'. }*|+GkBW)V`UGj2 jX Pꕩ QlJQE{n'6fxhTf1SO0GPַf>e>͆67li $H_`Jv6e{Xܠ8sl(&y9쥊`TU8f?@ۈ-_g'K<3#9i6lN y[^K&39pqU&7 4IlPЋ)kYc؆#q޺#Ɏ˓p(  'k0C]hb48Z.2SϞU;؊L0՝ R# y :0?juI=RVa!qbYd3ZF..+bK1x|p a'y?HǨ}aw4a4,'A14,&RĎ 5E9r0a$l,>L>kS4zC~s F߾$3ž8;zH:~{kW/"ox<`i %pƵ Id߾bׯqgijʅ#Qd%zqh4ʂ' 1{\ 'l̬D28R^| N$"?=et۵ߌ_:WsX7chD8\^s]Ƀx:&X?};p < JdTTa_^ YFF dinWڣXYH+fI6A(5jר>}v$.PTӕ83krE[۱ɨ_@K;1IO[(!Ha9z3jaC!nӈ%V]3M8y&|@^2 M<_J@*mU^WТP/svl4QVB_-7ܦy&[eU6ljvӞ^K+WFnn'q R >be癝GyI\~")jу?f£uGPE87VН̮ ]_UNaq+u&dA1" R;z)i.dcim t+T~i˿SI1SD2NBSEG+NK].͙gFpC E,.88 r<>m+Ņ}p 1%ݒKHTZd( e6Hc7['[B"sZ+ZF zhkf-Z,,ie>lT׳ᵔÈ%^wf|!{0%޸֟fw~w\IAǻ[E*xx IDATf5-yNnC UʂY\dҬA,O81[v{Jo!Ayl>GrQgO>O4H^rb?:*ƓH..drvF3VYhݬR,E8HjT;+zi{t&+T@[3Mw0!8 Hv{1D>]GODY=FaJpZ,j" ,ф.7TBi@R\E1A&\vku.Hh$9H1Q/f_q B<=!cI?|}1vv(ncS1$X0ȁ?TA4e!-!,eVQT Ig,ntt2p& w?b+/l$ްJ'WP}ր3mslΒy16K|wjng25ݼTjVy}Kp_Ow&<;ST&΋`賏1CpD BcozXWX,M$y`gtveYmBlc_ 4@;׳'+)G"RJ.95iQ:, "vTқ($WTΌHD%I!;HOجGH*tJlA_Ԭ+nij߂ HGaj/]:h#-+j I8*mƘyV+'_sZ59ڽk*͜]0hzfhc*[vmtrez6.Oќi0xŒdZQezG6R᷆t?9<:z1>c^H?:cA|YЈ\L-q.3P2oN!#4-Ѩ$;Ш+ޫAdS2Le'U֖!sk2+>K>$i#W,sX3(}`x&e|p™@3sxuY}:F0"n=_D:60`mhЉcQ|"GܥËstYlt1[ؼgv#/3Ia\`qu|zXlg@a]ep-W!![Brԭ|O8Y !NJDwGv/a/ܪ4~ߑliƬϹ*qG8#5G.vh_1f(34v;,HKNƷ{ :⩪F +AM*mrO?+Io57i[@эceeOV;QMFG{A)wc'Ob$ˈ9i摢\36u+HQt꿶x$,V6@eJ|/͙Ua=O/ȂQ E3!YN[0U,[eUMn+P>盂FOyA$!uEP*O#?*#il)_BLc5#c;#(5j5PbmtRbT4kjonB I (*7t(kc'R H*W(Ux12oS'hI0J0,@t,vOf_%/ t)G0]DW'aQ,ؔU`Y9:A>mp z^5o ^)x=l OGy1_VnEb̫x#j%Nڂ'xg -t0|^>5lD>cr s}[vi#_$zw`:|5ދJ*Ӻ:} ;'C3h#`96Mg T6OXW:CgR< {&lmX&Tzf: A.AAÏkf$IE[ijX82W~Oe0h*+3DX[!nGb2fYYxCaO(51{W?ʖܼ ߣ}y촲iP9dH-2z! U" !t)bMQH9L?Rfo"99iƪk&!W,,MOtZh>]2},)Hk-m=Nv"zD}.xIdicJi`$<۰d7TJ5#h/-y,I}(\0>r%(@my'QfC; #UZ6íԪGٲ0B7W-bXLs!5qgXve)b1$ KEdpT=%@ɏ$܊[?s6]va wrhOjѤj-tF)ySϴBr5_5 H%9#kpIOxfHH(ipl{8HG;nONwoldF=`i v?6Mk1dC:k<>d 6v/|ώ' wbzo6EXG-om&sF{ҨwFG~gޮ7I' +g>Q\".]ZJt#4!}@NG. ^Y#ɡGÚ hL|Ӡ' 9PfBTp1# h8POn+#8crn}3;g=>B"跽rxFKׁ9`du s鶮m<=#2 V) cL?O'~; RՋAuNw! tWIG T[}ξn*}zLO~cwZD2 J^F ݑ|fZm y-x*׵zTR>l8.d[|rh̻Md^v^|שYt_ P@9xrPo6caGiȿ2tdRH1м&vv4 yiZ$o׬Q Iq' ER3G#QC [JŰW@~&Oh!i!%Tṉ},lOD_pz}%Jž@&w< !% t,ƌʯV kF+VRi73}k;̬~zrkͧR.Pr;BǍl4kLWdFӁ~"+0~:ꉝw)TԶpBIQ40Si,;ԏ7q폰6RJQN*Q.h;?xV}:`W=k#jT{)\&nM<F}nBq{m={d<rDvm/;c7]zި?&hp!ER`0Q:U1hmݸvRgl[,F OxAtg:H[x}ڣE y#贮__3C/5dwJO-ǎ.=Y }ؓ*(>} >|:cǢ眒{ƌɼvQ.{v ~4;k VG~TT޸^0wv՜gh|`3gè kݸwk{id"u!)`l@gČw߸YWoS=SkTT!(Egavyt,YӸqZUkO}hw} mNƛ\/+./ OYB/'cQ5(D=5&^XFw} rZW$,"dcdQ?KRN!)DUhŊLpsLTm˼GxQb^ 7Nt֒3bH8aA!?|쓃?v7\N(Daj"$ZKL P=G;0 r`ënMi"t!\n{1vmI $F~Ɏgd(mkEؽ;-iҸi"__5uaJao@mc|~|Gt醉N* }( VT5V6>KPgv{(iU--S?M6Q_tz )EтB0r#Tg`BKy\.$[,:j(h=ll^]S(y4XIs`p K6]it5bvS':jrT.[!Վ ΕpoAݯ;͆@m&#qSfP!֞-ɢpgTqo@.Օ-4,6אkӾ"XBh:#`]mpC bFIceC/'6\>Qm̪xO/\_{v}'y|VA*4S+^'h(37RY^L#GOv&RN;\t+HwQ{Fa^{mִǢn΍ 8lN D+{'W洁=*>6,iqNK_jBLJF ' +BĔ?JlDT//>JNƩVA" x "chJSJtp0R㎕2Y&lԽYʧO9i7;Vc6wsYvGU*qt3Z|*a2*F'0Yy\OzD !7ca{_VN:<_Α>c~^\tԹ^1A-.P(wt-%ۇ~~z&o~5?wWA^&D_h&$1NϏPGx_sDhv2d A9.Uytת15[CdSթr -nSLjv5nV;;n;t?..䅫;y&G)j$22M(mMcvV<.,_}R ;)[d, _JsM M+~dʢ@+ dp<:A8:/~q-nSaWl7|zfgN"(٠Xu"p,qA^ J&98BRAw)A2v.W  1HV )b]J3OS?اSsfI4B$;tz.TWciHtDA#&ӀǑ֫H0(Vاšr/jrѺ.KJvư(,^~<ꏛ3GcF#+d:eý>6p$ W4SXr)BW׈Heh#l@LF*[ˁ,ii ȃ!-0.Фsvz_>9,FBְ-s3]+VH7D (vݵ5kLE8}o~T۟}Nяޗ_$t+,=3n&YXDՋwn@b#so?$%,Rvn,%~?%Ȋ2S{:,t hq]io4: WcS9 z7j *PGV,ج A EE'짴^'4L#tFZ˴^fbKPHC >2 kpUGGO؟^/3uwwof >ÜcͻHf&O yUJ*ЮA24W~BqBY&["] xi%cj*Q;a{ CӪPUE@g+96ir:u-\v$hS݁i5M0$fK4" ʼ~ɋi,=dնDuD]mSCM+U;\;jRrYl!M$IҾU7ˀGПQʕ͝pd$B<Ƀ`ɤqV.Ȑo9HX^(W$cӉ#eA#v<-KŝK?v:<[:TU+ AUI0.#lAw.| n45<S-F]i>9#N:Ebע͜_9>zz\:3LNTRF*$gse+9,n3?Obf.pei>@Z@hLwHc(\ߺWGB!#2œA騘}y|078r]3tXlZ+ Vrof|;IM#f#)h20s*0 E{޽[Ө6 <caϵ~Hcugjte>7;UpB r~\N d{E9$Rr ݞl$]ݞ1V&&Chvc8n|ztcd4($X^ #챜V/_*f˝I^xá6b4] W!zT=Mhbbz _z'?ٸٻ}?ɷ~wnl.zk/ny[䘚?wXvL3㧏`B9m\^kobH|jw( FΠd?ŦyH`•NA8DD|0h2¡O1?(b\vZ=UOr 1юpX@ϛX*cݛ" `%  H%$$cB)uׂ=lY{[[v&z&5f!Rc:*Čn IU /7I6cF)Reρ` UP$/~_"H坞g}+uOyYa? 3F!_K+tK}$2I2 C:6E IwYbV/E976%S-{䗊& h8nW6&jlig~>tl{egm{ ӋɣIb8gLVcvN+Y[Q`"ż:e*VAr kKpH0Y*Wj x ` 6Ƹmvg2!"I6p; 6;7/Q=;DtnTy\hf85/\ؗ-*p1ub-A?Ǐ)wjfwnM3h0{`Xa|Ȑ*"fHURrr2Ҕ*GH&4TMI86i'E8 m,V,T~坾Im<qۻOf+>v^ҦTSXySM ".!{vF),'y$PFWE[5[1%zR>E/+vGW!ySo*+3l (MQ㲾' Щ ǃ[:p]v$2DFSylL3!CQU@%'"[b @Ts"aef,*xƍŲ2[X6RzhM ]:nCe[ADQmbʜ? O"X0 mxĦw z7 ̡·z?;fQo hYg'2'f$Kt0p!OEVp!6gVs8~kkE|2{7~OI~#*me1o"ZYX |^scJosz#mۛyjcx3@pl%rg0\d&SR&^4 zkI.ZQȵD]HQ=}p)!3f&`T]T\>(-Qtk)__~e)eBީT&sy0Ox>-,?9hoъI4yjxk/ZX?C Mקv!lyF;7ծi<BAOf[Z!Fܿm԰oFGƄ!g"18V<`۾mjWx;hV4׽Yņ_% (||>;{0?J[z??;ʕoʄhO(`8NR<;z~׹ PikcLg}dǜwu=[Q'XlcgOE3L?324 K˳ӭ;~oV13b0 L$b*oV~~-}EF=Gh_ m ^$dF}Mqf T@3yR+@߱xLUD DDPQ p] 1t-B". Zs(Q񶍓'nʌPZFsS/e N֨eZҭH M9btu fHՋNVݧfH2갅̈́]v֞O^N"0UV"a+ߵz?H_P`d4EPϥ!'Q l8~^ Cys IV R3/GrlЕs(vSr&eBh;RHQ:X3 EtTJF}DoڑtQCҎyyf6w&hF77C}4R '~AѢhrKH8}H!Pkjyq]B$11/^22bR-hk̫&{Y8oxӾiwvUX.kdZǵO|mu!Mì0/Gl׌cfq`?  lS]wxeo\zp+$L:n:'· ' 'ȡ0nS,d.dgO-s莩nNgnf~=ZV/8c0h26adc笵Sf{|z犚:B.V$М&dD /yw0"A9̳Z$3*hv^˧fQt$>F,3[). hWaQLQ6^Ǝb&jiLvRueUS} y,^p:Ǯ/>~#,8xqh1ΎNKwGeNw^'QxO>g_lݽsҩ?|W{7nQovՊܛ`o8#eMjrƋozM(@&4R3D\bZ' zG :,zo__c O|-ST0gKlt[#?ؽup0f˅ @Zpx8-m4ͧOFѯs9Mϖ׎p<dFnx/wStKh䶇F*ܞ \=L,),J[4)' %!掎j1'$W~]%D z¤!Ld|zOI< Ēv|- a&e7m:Q5jS!e=4$C(1o4퐹E6XuOsGM[v2BM2ђ_Ϧ JSN:iyd(]94`YUF(v`F5HOgWI:+ҭj-_ghӯ{uD)џٌS)3¯hR'Ǝl'Dŕb(S?"Q'[fzr,HBQU6@{xot)KcgIwǓ) - N'o'6 r4:.>/:]:`O7-kS#HTI㳇Ѭ|6ÔɢVVZ~IZYqHu׃->Hz (vclƆ*څ#}=9[q qSkjeBˑ3fgkI.:9=adhe$>M0J6vpZޓ nt@hB,j-Nٜnެ.+{`fa@vԝLF0hRB?H*Jb\b\n !J&OTcG RMJ+g#c0cHhM ,7o&C.r]tNΓF}TCK r1Sl2W4yDA_TƎ(07:-Qob"TnO<h #/p4qȠkosO?߲&Ͼ8b9ŚMg|xutgg'O6ֶw^j jN|N\.<>zy{cWѿٿs7xr Gz.WhEz;Rcݭv}>ZCtꜣnwڭ R&8uMMG-;pԟp NѠp@)2Ot6m4n,x>3\5PIu )m knw?z#: t@A?Q;YnaH" TΥ4sLpTLF'2JQ~%TF>k'՞HZfKjtYȲWZQ6Z:K#' /&9*PdH79_B$ʯB_fփ>bҟ̰Er%_(ewdIYِJ,)dC%$‘='UOc$& r-MbT(,(ܩ6՚JlDeI(U0ON&(=n9u0%6 _^Er5RB#_~[!T%X;z;e*B+a-SHu6֪ʊƢ'B RO%pqthjN <- 30SR)rлYaj $w h+jNsZz{ u~A8!0e J&NɾpVJ_)(_)}119Q-j!ni|:֜Rd:au}Ԟ6fq2]^B+²=^U G?9|Tݕ؝hB%MiƨNJ|ґ28SO픓@RW; dGxLY ICY%~֊P6C>[q-l 6jW쭭˳V牯mWpfZQt6ZtjT/@\޾u|VMG^i,.%?Cgl!%G>ibP ŸF|)e2hAGՒtYSX4 .GS_ g1_/&cZg q+eNi0 Lڭr(Yj#;\6YXdqāՔw<ʞ-&jqbz6BHY%͡@ƽBMQp 1eb1/0DjdtED4DBh~ }TN>Xl.CV^n{YlWp,CN"0:J[_/_T>K`qKz7~;E@@=v`V.IdžqxZM ,G!&r"].lp % kڼN2/QRԮr_JPTƩܩc$BA aH8(PD#7/kHTu:(3e/ J.AC G'lU{W_|'X`ҕ{3 +9Zh@0:SEU v]|v ~$ :Ӕ#RuUzS+%iʰiVI"OÛؒˋ:(,m&KIo(j*LY>lP+p5jek)ϭV6ko/NkJ4{3O[OI;6*yBGX*F^;Y?; ^iPl4J"5S<4`\Ѱ֔)A|5O~*'D򝶹'n]UZȅͲ]"&öν9mVZ/}i1'Mf` $YR&a)b %niܲ]:V{ɂppb!{)-.B=8Zݳw~td(Vmb 6D8^ J3.Ӎ"\ 9,HI/MS-\Q_>-t>yt+Ģ 2QBk 3bc#zGDj2|0Da'xrɡ#fNgK8]\#_.1kѳۅ`vr AY4,%ө1nah:5 xGTt)qTjrvRi$N0 TFŜOX'Uk2 e֞\5SkxV{l>,po9[ń1.jV^dWd6:&>hi !`k[[1@r:zc*l7j8[Uv7K\dC}MfUY~zx&b =  k01r"YxO6z[zC?2AyzS_q=t b>fmėqH~R98D-x4Z2%鿘6,>ݹ}e#>;/V8xҪ_H~>W!0YJ6>8+?hA,uS+mS!|^T+>7 ZDIhG [n ]Ү8iIBRQCHjM ' |&kFfo2U^Uw_,oG\(q"¶D}@f"V>~tق'vfvY/ڸeR%n 9^w0pDi= S Tt;b&F2lB+lR┶[9j4hoyT~n-$J]3/hs3I5TrdD\}yoy˹`Zu4"&Օ'qiOBT6}:\'r FosG.w$Y\̯B@)F MKZw0zo|tzygw gyj#Ȟ~dBn9_5{-iCZkǬ?0a}N72D&5L0+0wj$^ۊ?>:ӐOnvr@p\fܣh S\#\&ЧEEq$;xS2T\# l~=Co={ p Y]Iˬݐ1.tj{wbidTll8_*?o~OCY2Nds@*ʫtCDv(PtrgjcA[j6>[/D$ .GOl>c/BU|Rk27-xH$aX@aݞe(B\X!q[ SnbmD3\:_aARHX͗\X"(EY4M~OwR汒}_˽ۗ^{vJ"mKd 2Ap 0, H Al81HDEBJPC9ۗzj߫ns9y^խ|wI2lҽB>J:5G5N>j78?I@d!VF"(`SƜҊڳ~芮`,Π{j$;Cp4H?I\;lspYx^{g~wkfh  g. 炞{aS(ἀ'M}n&#bKnܞ4j%ao֯ vJLŬJ%}|_O0 T: 3 ԥ7$&Kvs%rOl.Fa}&̧<_?߻Pf*8L";I!wgDc{>hO\QV?$=㏞Y0&lFt4bD6$'R 5AXm[iaN wNmNHW iIUSR֤D/%.{(OEIeab"-SY͓M3 ҩ`9*ZIk'G tau.{_|♴̎qAn6c#o(7νp/#B慀&JV$WlJQZ iZhk'k,Pm)/@RN6 @"= ?LHRd!zsUQNgTH[!S&WfL'F\jDPm#B8*eS+xMu\2YCO#4eK2b`"j^D-GE#$t pst  /P] GcoG+?nݥlؕJ·)3+QpIE*{Bjvc3tt䁴1cBB WLҔ3qiUF/( b%hY6::W.gly(tL!|cw{PPpRIul.؃rJ%7mLt=b=Zϻ#Y~GGnVU6(_^1357)W& f#PjMWz`_p7@/>([5tݡdSٿ)c%&a0$X(CI P.$W"?p:`Ԩbx7,@pC眠+&(eCځD<9'=$LGVWc+E 'ޘ` 9<|Cfc^eE<`XU ƋKAp ƫvYL2ó~;8\n8| '4 5uQ4{7.;`f7‡H`Yba@W.aA%L_VH^<}.w?|/uN Aŵ%0v e-ɺT^i'$Cv?A7@< T&>9qf&egXi/UoDG.&/?R;9 "4R, o!Vnn.oP!h0 [J٭ۜ8cggo &B5p{M1V0%}VPie*#+#l$Yx S|D%܀^IUC.PX%B&J)lRݵnv-RQOqQ Hp!E')=13[X7 M,Bl<ۤ?%äU xtRb-qK!x4OXD9k/ZΨ5Yvy<_ MHߌbGWtT[!%֥v^Ջɔ4zq)R<RHIp;J1:.xbajGroV?G9ykh9o~cc60B1ʧU LXN+-H ԟӖHQ7δ,yq^gf\3ܹ i# bU="Bp^k @'<.wPfQYҋZ d۶ ,~gg SmTG| g*Gʜc^r }xvɓ՛L}^#^E&Lzw#&N Ygw[]lTLYosgacڈi6.#0 =&bS7 &IL,<IN ,Аg;ˆ3.)/l?ˋpZ?o;o'/#tjG`"kNϲ{+ 'mfﰜwR=THb>>(ar֛NQ]@XR 2t6|Mk ]@e I;*w($N$:3.:Y&VIniBlG|Q# B˖F(f`$$t#xԃx؉4xfP;yW-Gwj8| c:.*{姜35h.['= ;^NylcB6 |ZNEXe<Π Fq&`u&7~[?Oby XwU΄C,;Sr?OEx|vP|ԕʤV~mW՘F>`,p1˷BF\8+/³*R=FK(oŔhB.N5*5>Z%⵷~q'1cܰKåu|Ԁ!v<E\c q-;Gs؂!vԑ0aL[s2}s;+dd\\v/ɧ:- k`0D b/N 0 >:N:r7Q*E˃){ FaR wm'~x&T*Vg%Wֻs(Et"-od4tɵBagnԈ BYͬpo3`rFFEl6`hI2nbGw IȔz*:ng ;RB](4NH KYテZCY5H3UX/mvْ8! HߓEC^:u#b!j2q_}n֞wUK ygX)R@Qm>Y)"0N"go]&NaH-R7)/+}Jk)G6RKQu YO IDAT M*/(bJR@ D:~9^+Xd@# UMٜb:-1FAJODէ0/, f /Ѧ=bh2)MuZ)ʛ|V^\iug5BX Ŕ?NXדΈ/"(MD}͘5$UBwfĢk.f ";A83X%F}׋|lx*e.zlp]@D\N7bQ\E on袜˗JɈ1gL27/k}~ݝT,@hDr_̈́2%"><'g?]kH*n8F{ۡvwZ0襒F&g{Ź!8$p0F'tA>;Xټa 0~c }FB[O1'\VFys =v񺢙L6nUQ#m|-7 a33*#F.!v61uQl{wg+|: h{†t (\\W]r4NJ< \0ߎÂ̬yG7Ipk-'Y`[?Ջn e4$Rv_e[f {?;;_|f帼.'ٟs$SFzy0] SÌ ]Z ֫3k9-67N?!w~">s>kF QzN[h0DV)Zti?/_|L׿oY !8kkKav9/WboW{¢~|p2ŭ]`ƨۺ{{hAH|qR.&VשּׂyUD1Kb ̨/eP3"ލ13D[Ly8]Ku5>qF3$qm9;x 3}zzpkו l;  p@"42l>AW3!np'{BCW 14>Shc3!e g&nw&; -̐1fƖ{yiy È3}nZL=oyrƢhvv!5,lȦ./3 x)`6OFfi YX^H'h/os:DN?<߽[~?狯l4^|)7/>~l&Y.w^Elig O_`6^N0Eb_Ki'dA #pV[HhH¦e~% lYc%Y-F2Vo}/o߽v }l<ljfm^]XsR:pd,}4`b ^z /\!hs姝{]jhJ%([Xh=Ƙ488bS<-Rτ:*]OWdb$f-28V RX퉔`㢢[(+ v*+S )n/ 6QG>^|p'p{5Q1Ja,Y?On}l`Lv/s $'Ud=j$!YeU~MVIJ9[kao)gM4CK'U7Kƒs_I!JCXf0$G*rXbNڬȤ ⟾ij҃!r`@<-JTyRD)XJ!jaOE Y[/% 1Iߧ{RTpDe7#UTGl\7a*E[pEԛ_}Q=1.xYqRȍmCy#_>?]ԻbvZܳ6ͭɢқuikjA\:BzɍyI`"Igj]+Wo^pm!=ne2U;}j0?#%OCƠ{\6NL;'i博f{RZ4'#n1|#+PY֠[(|Aw)sݿJͣZv`r&Wri+<C3}v9"+bA!d S08??# peMoI:pq5V{c1 N"HO Y#ۉ,*\^1 xaR0k䅐 f<ˇ͂~AI<jۄL𪿾~Xmpp8!Z hҶnM]FFWnNs'֓ 8ʻkc'#Nڜ6p{ѰݝJ촁OtLgkۥsWJ}K$W<;gO:Wz-^,G/Q[J ѯ(ߍ#/< H^Qzy 6d6+l>pyx4  T%S8uq(&%^d:Nog`mH|`0 1Ja߫<_Cʇ7u"v +QTRZ_kΦcqk#>noOK78WQ; <jݹW=; Jc}KoDD7,q>F`6N'Cbst௺ڰ/!HR*dq j?cP ͷÿ}ӭ3'EWݓAhIBŴiώϾY{8d,V(CU ǻp2l! qr/|,f|, Ov@8N= =c&ru(,' (f,ޝ[J b6qp" /l56a幸Gdޡ V؜:lPWQt+p` lڝ9`C>|UeV,0W&ݼ];?d܁#;ZAJR>T}SZ#Lăo? ?I4HIUi:QHP\|ɰy[НouOo3[܃=:xr'nOE,$pBֺKʗ %`0 b&lguuOBx@NMr!io4v)l9vg3$  ˕ʱTv@S]pb hd:Oq%C5__&BV.&Ƅ4<'whѱU GЎ(:E= <'mg2AEM%vJg>2W:R6 Ici>@ ` 5|Ҟ~Zb/*Mcj.!&H|d4D#uؙ7S$ Yev"γknV S AqTJP EL嵇Zʊd*| t$hQtro6DK@2A( | jsGmtIr^Toݘ9Xwr(ޞJ$tE!$ RM4Ay!j) ?BiO-d[鵃)fCR՚i_?l,'Ali #/[vl*STkI wu %Ff&HmY#S7[Q!ku&zjX_4gǃieLR@%]|g#U ĐWZTZԉs?uR Z5-]ʫ<"M`!>$[RvΤ_Y:_'V: #l\5{Dք  :z&hk;Эۿ"?a2ո_zsҭ鏭,<:僮ݭH  &ώ.AAQt]z3Y07qI`2 VÉӃ9p޶gZÈ "_D$lyw_z"  Oa3BqoαgLmz+L]5 M!gG[!ɁS;RbWJ;LEtD`BU2)2Sٮy>,6DA@VHjܑʂ{?Jp|G_h~$br#4'ݿ:o|pace(L;"{mm8,ö8L3A)dOeeg&,b$m3E!H-=[ wBKG *YFf2b7a!277%v,|!s#iO)#I+UM/Vmbr/Կ%.t_ud~xHR8 *H S@+)yiXOϧ򗶠Ao1j.1-) H)$0q;HZrAʏN+w;nbب=wTH=d|a.9i׆3,I;]Uj*6QuHgUʁtG*]$1HΕ؆h3B^TٯK'DX_X [1 8 K)ffqqOxǓu{'{vݬ^ /I~As9ڴIZ:(~J?<:Tbao8|J0 >IıolFn}z1h/43k~Ùuoc:J{5+mH;alF. 6"Ad390!NM1KNՠUmP Uoj,T{>[t:k|22ccCtZ"4S6JZygaΫM’f QӠD)0bcǸXt7\XVP`@R`:'<$:ucI=6>*cUy{q}6$Q<"{J"@p :A,4̗xz2a_^/ -5vKIf#ۿ:O.Pv_~prxPjd˅d:}t4UvONqQX+"|?p6!D~`r΃v_<) oͯ{hR;f͊ҷNJ-my#l k0"Ys3g;dC8Zp`^f^9_MF!!lR-K GuуEe5>}%@b `"S uMȯհ\Xbj_CM|K>`"^(BIt) 0_%<7i)/L/"j IDATB9pJӣ~ӈU&\BYN|x~Bm}v|}y  œ}7>^9`Q:$1|e$3S`v=]ra'V>_'`%Φ۹ݺzbpj b.v_`Y|x<] v=7{F þՅwc 8NE t t-rgxv*SY+ݼ/bkU3+ lXac$Lradӯ4Ԙ ;YmL]j{hNZxN"VOF+P/UAxW HDl FU/1" ̅cX()["S ȃtEϒHxk F0^BKK B72>Lh!Uyf -9r()(D!SMJCn88ݭ$OrG)*BB9$eP.N;M(䰹EVU)KNaV/$@Q뀌ud-'Hď3UNK(5Pqc™{M_$ooD/>=}hѨ{8(Hw}ㅧݛwf|_gys<$-WDF",dH>i]6;֔-BE>biE94FhSpLVof4{X:~g7J"Xј9+7ﮟڋޭ򏟝I[L}zx~RdҦ uҰ ƨyp߂2eD!~ߞ5on'o|?}N hhŗoADQ #t*[?6LN>bN43La`sѫz +w>yQAk|"p6z[9_sհ1mOPO] >daxt0vH'}!ulSt260iz4 GB&U:g )|}fTѱ`ܱAMXw.zz4m{X|G][[qڇ?|%Dj)uof1&ܹ</S۷JAss|r%#|!|f߹gxlzzdJƓ~#HS,1ji<ʋ?1XMϞDi*?eW>\S0fHzF>}\p`g)%:)ObUł,2 TI_yeprfUnleɐ0)y?XF6ZY@_^Da= 3"⽢LE9l~:T:wD "ד%D};U):EW ^(J(lԩB~2C2/m$SCڥB \)ꊪuN $6sG$ Nʶsmt0Md)!Ƙ[k?Ug a+zּy܋ȋiKVgͪ`z_ǘAR&(\9 t֝ޫQ~+Vr+}J<&: ׻YKҤ|APlyqATaF8'q޸ F`L*,|ó\+m)-Kw?;f(BͩE7%m} ȹ?7AqU%Nkk Riv'uW~|Q}ʦ?rɓ+b׭蝟Kw=ۯIüTŒ4].(ed]U0hrK\jxT4qUM2d Wg4*2ć®5iv7ײ??!3Y%>Nc MD`|,,tJ7'Wq3Fd't⎇ԚIƆ&N9DoB/nWSY9;z\jn<ժtV[Ӱ$ȴ Ylgf>%sd*}mtUd=)r6`EgBӁ5Tn( 0T0O(EpnX:T(KD/EUWd$oߊA0tUt )zh&a,$W2f.:ȜVx:{&齘F|"k{;;fy3~xVyU)t3^_j'd+͚Chzޟ_HQ:b;z]ʎJsF7㶇nDs%Bb[-*9: 0ŹH,R;4<Gɮ-4ɳut)1VV|z諾GD=ϸ&GR.|GmevKXԍ{m̔V?"!QÍ)gj?Q7ھ( uP8Fo܍׾Ncbf3vqg9it!SR{І"`M7_v|Qt3[`kzyzNUZMyysO gB`A߹`NtPlwz]]dctx`\H!}F+@V=0(l8,N"%0A!?<&ϱy-oOF&UHy`xk-De#t41^H ('Lγc"-Z9`px RXrI':I(l]7eՖ(LWbQPp΢%+>M[gOtl78kC(V^f3jikZ7&U3(%)ބ %o+`)m{$t.٪R9Dpn{0h!nw0BJk:nHʛ%sP.!؉/qNd~ǩ tJ&X J)c*͋Mt$ UsXLۦwJ//aF+,Sg{"Uo\t'lIk.4-JCwR "e:ELs4ot8&%Ik!W[)* *5BJX^VՊAN}ion?s_{9ƫ'GO61+Pi$>B)^nwEs8Zђ E(9OEk8_,ZU#[FF"Lq$(Je`PD0BHMRXs  _` US$s]7QiXr g9F"Phә| SӃZ"$ xEWLl]~Bap{-`{壓{;y\3;>"ҜvJ65[/% N'LqN.ؐΖNu>o'+L<ZejlA;*JNKd {2)R/N&}ph:_Xk .6v\>b۸s־6B%cමvrWgm6N/eJ}Q,CwEb4Aq+k=n7]6ӉH=E~ro~V7`S{bAJ`yqjdX5g&Ckn9&Va/x dNf xj?{f"_6Fl MM5bq4F$wەz-izz.m bi)nE^ç.4MyL<{01c #FUVKBs1Vqvh"Nol2-IVu}^vtrivXDSk[ij!zN&pc0έf+LX82ҔѿIӜ${|%8UFlZjubvo%Q duUHS]w5DvɔFCxex.Pɉ哢 9oW|r֫5Ȋb62z=@v^޻UV;B&0\ݯo{QGԋ囅  2#I2<0MTуUZvʐҢ4\o T4ZtxsJoI5<Z$xJpR5PF6(lfmVI1IMj$׾tv&YJVC n.lI@:'B8w'ݝL#kĻ!rF!/\ O]Vor=]U-N5@H,'|s_ǧȂۣBf?mulIշ5 |d##lϗdg6mg?>QW.`$0js;h,|ow3P.wi?~z~ns;28f/ qȹYfBFN:+> o۝8|1O*>Sxz퍹%{'{^No1r G08%3&n5w(pf<bB /Wns4pQ`HĄ5XN lf^ỒϘ B;D#hn<\:M(KTHiuzew2o[HP+& %vrgk%!xObfF/^rf;NNm|p+=Xb8[I lrw#ONO/]Yƽߤ7GhB%OӋj;L'$$7~<42e ໟQX 7jv.(r tuH+TjHc\=7 |4OCijfӸ'2qc7w!rIv[]%JyP{Z7o$ k4f ? ,:l, =܋i+^mf" ,P}B2AiO9*l\]CJ[85] &H5nӼIr=m׽Ew"مu]oSJ{١ݯ h)~/DnMWqAbu |WvH  ڔ97ri%+)t Kx–̋Pd6 +Kً>c w͹^1{H4گ-%#d)߻FkD- ƍ>W:&d}h *oIʫg{Qùkwx`b:ۏxF`^Nw9L` ,0l uA#R99tM2bj]d2|48\]Z0BԚN.OS M*`t. \눳5F,t٨gw/OΦ=bjՈ @Kw h0護s?vpϥXiZҐB IC/pLF18z|zEǻśެN@)`ˁaxj vL{i+l%h1uE+ zxd@/᎚{PBd`p_Js dH`tM/sl(?RTB2]zP9;sfbظztHu}!I ta`iW XU²F(jA"ns9 WWZ5QZAFH GbXi: M <.KG hLO&t,Mw DmxR-bq¬lL!9'S(j.l8B9nL(_lɑ4þw "KeUuUlv=ِԘ7L2jF ;=Ao04qHRݵoYEdw8EVWWeeF ; pZg] Pwip`?% Rt=+ @*,zѻfV~u9grm?j`ǕX~ p,%2َ#49@F2 %K SW)G%e(02).[_}Nrj^ DR. eRa*Jzնo9SFY娑Sv8р΀cV[8ѭʖ-&6mt*ڮE3\Ku+́y[ĔSfh3 Ʃ~=.ydanr~qf8eܴ;7-3󰕜J褜EϦxH HS, pNt0\nߖ-RM!\%A;y/e%~r+klx%J'!r "%M4U6 S@1DahD#Jٞ deSӫWVgM-0ۙ.;/NףAj=&Ԑ.K\qPQIl{6_a僷X!`/CY+S,)H)AKs>Q i\]"*Z-I>SMjS;p9B_?8xvʙQnQ|w?yRI-hsFf^t_f#'YNDl2&84P?|wT8>qW=ӰdcVl}VkhﶶQ1lbE$MDşt"kG~uHdLkh|e_چ@,0&iDbxYཕjڵb~ sgXgwjk-c6f@*!2twh bmϺ77J^Vupœ_pIq}E{?Ԧ9IbS=zyh>gk9NucM :3 $a#LG޵ e-tM);D5Тj*23/|IQk:u|/Q*sŪpfBO+Uv适j|?֋?>}{?30vK#S䋯ƴFH2h!qҊ!ɢO I0#PMkjyZnf?U`kICUo6u36qzkMRvJ\"mB+2'*D7BTQXT\, ш^h˒2r,ď IT%#39 dHᦷ DVx(V~)keU$ ͰsjZ9Cs=̇7͇qA _ؘ<$k Ry(n/6;VYBZ3E_j/ZleJ8i1 ɗ+3&JVꪱ ǻ؊R;7۲E\;?Sa%b³l+A:/YOHP^ĕ+M%n'mxr]0.fcMdmx% 6Sw\ |b^"ܐ8Fx&減|Ư!H+֋"-S4XB%Pz4u2Hs7G jV> Fj6x@ StQpH .^@[$B 1❉{dlvV:> [E-CKzְK X;pe߳ ړ![bl?Lqz0rvɨa|n3(μTZtyru7;Ig^Q是8!2dDsMMouV39CeZ˅bHYUf}go*u&,[dϯyR)L^^ӭtlH˹^;̧D[1v :%- \eͰ>:4wwR068[vo7rܾ|{,hf:vNL@ټsj]]>, B`۶S˄f= ǎik!EzdM]@W_wPm6 =XǑ~f^>>#}goјCL ;H" <Fm֤ f,?aKԹ9zY9H4.F (kLL) d)R.n%v]?޷ pKUGpC݉ʒ̣!#w\ћF'P;GqzU Vn,ՃT&jˍAѨl鸇_Sx_mQ'F ̳?R$1p8[(G݋+Sud h,NI.طs""<;^gDcxod ?N_. "~VQ-@!yRe =茨?fۄ !N %ׅTM\s*Ɉ7ejʱ娰>%pGcJI2%]oZK{?f=HB|kN1BƊ,󺆆AQ~v>- Dr$}8'n$VI,ʠ;'oBxwlݤy羪G1zr/5۷hXRo^"~ʼnf6#){2BD/ݥzvgDL" QMJfZm;+nN!6)N.O-k{lՋx~uƼod^v#QaHC~:nw -8zƁ<3dt[,Q\8k&J}a5pFhW%#@YNE{[8bg(2<ǨZY̦7vea v֨HHɃCFKwZN'%+\R ˊmJ>n[/F-1P삙r!;e;O 86eW)B{yNLxWi?v[?;'\i^'_H*\WSg 0G1v\Hzi2I%=PT_f3hQ"Ţl[zmZ* O8HAMsi?/jfQȉ&ظ(ͦJMê\7ͺdSpQSq <DfX؀9SD J/{BGV)deheD@c%V^,T8PbY%(I݊sf}˪Hić ӸNI|q ʮʛ,A^ouX. IdMiI9ȦJYDfwQûl))_*C&"ݖle"0@e~~J?g^F% <e3G˅; {c+iS|Mkr{=VzQ`"b E$1 J e%PT ;T&T)mfen FN 8jdzKh ́! $+E/֡*j.եvdZ`2~R%05u\Z{;[14^PA`Y~(D(Wύu{3I3- ѣ5.FGI̖uvoTcӧA2qwqAީןӒUZ8$"N;rxK|S9|AǓOkU4}{v.+;Lq]qNSb_uIR@i_2f'NkѴ1i'[jmx.iwwWȏx%~6KlpZwo ]g.ikw8xC);n0nm?媵\כu ]jd2$V10הP:i6o8޷HLD}Gk @4I0/c'IkȬg{ *PLz77/~Ѻ:{A94 7.ї_|H'Q=za sC:p]6@SvTcA6E XS{VRC'(_Yo*;do` HƼ7_cR#{ DG VZT]"'` sj0!쨔7Ͼu31v䧋P)h8Gp5ҋ0 ЁF|pIUZuؾF矜=#sKt}y"!%M4L:’i{^5*m\iƔBU$A? Jr_c}"$Gb '$QZ jƥ)Uz֍oC< 䥤2RrVfp'QVC&UN|=B!ZW8>H S;[ :H›#ӕQeXaa$@o}ZP*L֌k(Un3d#R1lʰ~B B%˙aMh`!Q! -!@CA- Cc$; |*W?Wq$'cvZD5 BU7(KɐϜ{8n9e0$[7/+"UJ@aSP3q/Ky!:qW.τI[M' 6QmSFRf*-M }8h4F((ܜ\e|7RO+!Bv䖨@ P=HB5B)Yf~$#$2TT'oܤ+W^baǫFf{gڛNPիFu{VɆ 3U;-NN^EvP􂵾*iM)'Qܥ}/x`GbdVר)3wPh$-P*U4/;^3&I)2 kȇx.t^V;؅,7gNSmkyu}yEB9eV POE_I&`PҵGᎂ 8&A1<.VԱ4[@bB ,KQh5&g q3 {}sqVx}p0GA`J.znZV.I`ȇ*t_>?6B-qP9%Nv~1+u4 aiNzoԞY;ΜP wA+T4Lڮo5;IYk0šRP-0{!l&\cS.3"4l(!Enw#Ȕ:h,¦$nN" 7J%ŗWYBEӨs32nJ)QUٟ`Z/Dpy3˜ 3XPU+χ-(AoM.SRؓ+P%Ϡ4g4LZPLތ =g+ÒY0RJDj+'BOfdɋ 殠"CM&t*E#[E͜5 ww>%-Z*\(q߅A~}r2i+[2U2Ķn>"];IS+8>|Y 4U5ތX|Ѭw=>$I5%NF.[5u04s_.9E&@..W7!JFc^1] >ԊoN5?q ;88Qβ@ళ)!.%حHŒ`-f:.f`ZxP?;n'Lfwv>b$.ߜzVi4o.Cm1gLd(.WlfؕafMzZWzdΜ}{J\d.Z'N1"̙\K|Jh:P`fFa#!]9$xGӛyÞ#)|ʠۭ%t?5T7)bQIROwoW|5n. Pߟ1Z3bgnHOPEq;A w'A8;$ӫ$&a{l2DG8R“`Giv,wӅr![n;24>=@{J[g:]%B؉-\SZ07_dg,NJSFq+K[VqjG3m0hݚN1e!Ŋ%ձb@-ډlj>b;AD匓* P 8$_A*5)\q+&}+NQA830HOdBu \vq!f-BؔsGRpP$Xq75@s O'^pM$oеtLaodlטE8xrqA+|.DOa-%3@(ρ&%XP4]-d 9"{,~j L>m7yYځ]N <9byQǣS?Dr RjְH8YQxBTd+n/6J.">ʳ0w#(Q!JԨpūշjBC $Qc|)N|rV׎(}b#q?~+okffg[1V!t$jbD6}cbL 8/' 0mFD#"g @|O w鼍LjiEw6o㯞V]vAdqEPܟ_޼99QF6A#fV(xg`W'oH ӈ, .C+I^'{;]D"YL [PT$S) \U^(zc0uK aMoj8}s̀Hg+`՝t>5 [ uFykJwLEj`KB$ 1Z|ʿ"0 v>uuyyԈRn[-hEM3q=O{K7l(/SR7ES /T eףAH*E͸;=1pǓxd3! 6ga\؋`a(,6/Y <}D^W˧@"J` 8Eg&czYQM`"Z*] niY源ɎvX7;NaZ[X.{ =Đ$ 4;wP?7Va@~)@*ՃZkc|hfX5^TrԟO,A.&AF,Mg &/=g/hL8xo>}=%S(N؈m'.ufb]c!B$͢YuD?gy݀Ҍd̥=~s]dGsprUDӿ{'gF§_ FG3B\)L&:MﴔSooH/O#6O'#o~;[? F GUAI8À@ŝx%VA1,>=FA'CbޘcM!vEp?}ysۛٔbzrm;U e^w +n+'FLegYڨKl D |rT5jRRUm7ƍiˀA*WH:J݅hrš).jF |R,$$ZHEOWe.gfDpƬ9Ks"G3łdWh ښe&!6db_ϗ ۨo:Эͩ>D(=ϋ ;bA8PxN$4 \Lq~ ϒ'VbAk$nBAb!Gdc)F8٬/ `Og-/hO-0D"ea AF8BE%: 15AH1򡖍PS5a͛]Uf,̔J?՞ ~tegH=TM 6+UP:+K8AnKRdh$z$Q1<Ѯ,DQ| ^RR>u,u>pYoW̎&.Lx6YJ6_X2B&Teh!."N:ns}DSvHXo?q$RtH4}L"C*@omf 콳YO+W ڣS\B+(a!f U` i\823ui`06YƸ;;?-gw=w8IxP' 蠜>^YR.Ģt. zNklQm߆ ē!+3fWOWiv!g鳳%R*.Z̚i^@-~}өTJA:&3vD<,IW? ᑻ 9r!l2Kv)^]ty霟5jzܔ ©{݀ƓݪwQ 9|4lE8~~ÝGôT>< M˓dhw,RvGɓ1\5ξ@ r}jĨ+^.=} BmLhY Tp"lx XЉ,2`Mp~ rwysН(j*rC¶_ `/2sw8q]Nclѷ$^}'x0C_^$ z<ר;? ɂîpgObfϾ/<p{i|o7OzH,l#ypd8Zʆ ؄ʲfH!K1Ql@'I,#J YpE<$+ RFA7S}aQ"~Jڸ(M!H "{`P½0X S\`ɫo"ΩS&)(m tOA7cֈ_y H1oRyQZVeOetb:/ 4*$R0"Sْ#O,v +HC(e|>QP,[XxN' 0+c *ĞcQE(?_bz)jN*1QdH],=g ~rč `Ns̆ 3kJ@ #H1%"&.@nl*LY%',A@"|7XgHDLf;%bexRoU$NJެ=5nاnGڡSQzV/Ov?KrOç9lI'~M'G/9Y ׸J<:DSp%(X 'Vf6wϸ >it;N66}qu('Lu욡*8?X\ǽrJEqo9ݖABoe1t =_o'pBƽ lnw >! a~yw/dX5pF2eiю3UPT6TrmlY75]~A(Z>k`HOq٫p}?Bt?}v /< _dQ-JUDž%]RM@8 335oMv Qh.|Џf.mC<ͰI8SODXLhGX_ ;voW0s;W,?{v給T*.yzk3z ZYdoǒPwοO8_T"zC /_{v  FnLJ{\ nQ\:k]ݐOۨاl8)@f^dvgiuI i)phD8_oΩO12LDRt$xbvb4 k-rqR9wFNb%6 Ql&%.|U;sm']ʹ9#}+Ԅs&Z һ7in.;sx,a2uaED~c ' ,Lo]7݃QeZiv80mᗢ"r)%_݈RSjtjLn-Q D'VsDW2E#MFU*PO-p3*_P,9څ* k'5SJV bu9o\*^vCdZQS8JMu#$_k$@'gL奥d%{BeB?sъ&zM)Q3D! b%zAA\umc_t87{ Jy[XPBDW>g 8!LCdGqcn̠ȓd rarBQe/ ׊oafZUOi(rEEZLL"UeUn@Ω>EHfW xe(Z"S`sU䡢M![ {#P^0ܸcH2fC^ˍj!'@Y$fb~1y[ -k%JYr&Ěrs{j#`z7?}ţ?n^|hR^As "!q|I"*tL᠞,Ϛ7ޤ1")QLo@VIz3 a rջH ck?~rvu1_d6ͻ#Ab%O@4 g+8j U/}{ӔD[Lj*4i?)5GѕU"DbLO;̦BY;nj}7M'z6lAwP֚HU>mwH@}WZ?s޽qgF.6!j!Q.]LbDܤf> )7{>)I;>s>ے vp3Ús:%e5S7!t(91rqJ qBJp][xa|]x25 -7Q)-[zѼqFbgu qٛf_Z(Fq޽+R} a5miݫtw]$d,=I7n|%]?̅jh8)ovLlVtjDiK6H#c ǡQ[L{N|S5ipJiqT^_i]8l4)S?k9(]o5RޖUJaVbjlhd|(B_e$?_ p1%z3hqQK;-k׷{oN{o MM,ґJQ.N!\?#hZpiI%t#*f0ynԴHZ%-LG*lvLt<Ϗ]]勍b~Sw|[*ꑥ?9D:@lOft?^݃hHICB/Ҳtb 55i:"yрD7X~͋.9!~ӻBF%U\ϦW= 0siFo<oښ:7O?%9JLH//jeg?_#\雫0,bW IDAT4,8=-p`hSORcFTm}֨V·]9yX-x*Ylw͋+灙U eFVFoW*BR.~wѰƭVl{]g.)N(;]8,u4-S9żrJ[q6Ftڷ-|3^t4Z_S  GGx頟ne-ұ=54M?[?t>tHcA6YRG0)\?X9t'IcKX5w{dJ3 t{'IZ7Ë09j8+XO`RsNb~6jGF:~ޓ~+ cӽ޽LO;t{Vu Ow?gmg<|nP{&ZB8`!;ޘ YOh0f‚Y?^^1-s{xIL2kdb_SVa3UY A@<ՏsHQ+QGe*"n4o_ᜂ_\\5sʺq@6 PqA*.l: h' ܨ)ǻByXKK:"}l-c LX7*uUa% H*RAJRX<6 C& r_@zpσ"4(clk^N3L4W+ ܭA=#&QEEBH`jUX" VDt&*CV'YR/"K@OU ꨢz%NǛ$-jmwlˎt R8A=ݐkH^ȍo6"%Vީ8U_%,cw,6rQ 厓2L%}LdC4Y8$[uAK>3pܑ[-#5 Hݿov o6)<>mDq-E|8EFǣ[NOfViuOwI#?_478mف陸$j'qk_1۝Vwwnc0`r1L<ˈشZg<4{ :}tIq@TK#%OZtNG% ]_"4B‘rBϲxzBj$+#(wxWb`D~}@L$'#b%eEk3dSM{&žΩP*vM : BM֍ lj䨃N6puZ%"1X?nx8!R\gA}ҽ{u3dMJu:i>P} 0WA@#(l,1v($yF~~(Jk/׭>ƒJ~F6ϧ>wS 2 L6fAEO)f2 W/UAR>UC`Q% *(4sJ{Tѕ VV_'7 d(=C1.oRHS%Tw[#AA4(:E(x^)}  P1dLcIit5Ch+3*Xxя/YimҬ>sp)8:dIgIFl>ZYݧ3Cͪqоf7"zuFT<~s,#-S9vi_<)cm4š |āb6!|o b&eJ/O/mLH؃AuAN] |e)3f=_,FBw{2 t\-^D_McwILjy77P@*Joݛc,UL4 \sU1}OV,gw pf=wo WwjHHx~XM&i`E#hi9Jl?w: ],i0wz7/_\V; ̔V.{'͋;ugِWG'0rqAV[+o;e:˱HlOelLetr \ZL\BƟJYP@O$ K%H%t[" t8hKQd(l5GxӰNbF{ 'I e-aF4hZ!ޓe?v'1Wkep1I\x|{BON5:z5LO9A6Lxu#cv1Sޭ:I`[noZc>l͏ή;{HjkKCP7 x3;X 3z&>vz@KPl{q,_<;GKF_o$oYOޭY`'qBTr ^&jg^?? eꖕ>n`ZN~J<~RgPcc'A,a D }, (Ih˻սw ؼnA!:6WkH6;<|#dUPs*}}Y6ދW7,uh+&-7`d'{` RsQK-JlMwdђ@Ejv6q³A[_"AdL }GypC:8 =dce'(+/NY"i} ;rz'̬rV waz4i_}SZJ[֛(8$Q|kϰ%*[oMضCd,h'@FQ9bUd;%bRJؔ7UVboxWEC#)/TFI7.^fR$@IYFZ)%H"Tt! X6U6"POrىQ2K:)BN$$TVf/Y7 ZJIe'Ra9J_WOD= ,?}ӗ]TN66)C TGNlEU&S8:`DiƁZRgXA$^PXe 1bB(`\dw4:[ c`{O^TR]?PY"J.o 4rI`YVA2[ _I }sJ)5I=${S?aE'ōm|[Y"Jk١s6ٌ' zr˩Q>`ji*B7MQۼJ L;b/"VHfzcbS.#4wP)A; dI, #7ultYౝ9(DudO9Kxzh@k w~~rRt^qѺ>Mg[BVAu}'::+;%N&~"Uv P(9T+^yza?D{d4y0r7ݮ_:TJ6̘N֝sU|}7,ͭ]pjs}DҼu~翼E𷭞U\.VEyyi"zQ-v;iE²yYe <ҹ2pV 7h;5܉Xdcs k-t|v|HC_<.r-#b=uÒ2)kx4Q5Z(E_:IDSac,96HH~sB*-mєɗ,Wb E8Fll&!6ǽ'pcbN>?lWS4 )GG O[!YEq[-KKǓB/rHm~wҼک>@X<{B|> {±{䎺ż&%w̏Z|Ō7-1bH,JN#n f h4 2Vw7;;^ݧB$Y +b AUv7~7)8a>z0A!K)!g C~%rSb Dq'V8AV\UCT/ Pɪ_L^QJ' jLz,p*)$|yN vnpGLمФf\pljU)RSbA` .YW~b,ŗV i%Cn?}?LBZؘe+gʹ/;M$=0S4orŅ^P~7]4p-|ĵ!~%ZEbKkAH!`u{_6;^(cҭ{Y?>0x+$ 2♈!ʨ?2Jgw{O؉u?=~%դfѭ<ӮY[.8G9s'nR^o]a.,Ƅe,Tb W^05ЙZް^q![gtilƇ=yJtfnlsy= rANٴݝDT oS#c6۝ALޕVn0XpA׆7[ -O±a:g7^GLbO<9gr)cs;,[TBQ#*zY`-K$~bF_Fto8^ zPٔf2Ɔ+j59GSWݩc1F hbXxw'a+oNB&IguY(Jn&<_ETAhfn?u4 Œqs=iEGrTB7tdª +g^,ɘ!U͈ޝ!k"'o^/[y Ny& ݋؞`%yu[_EdA5U@EH. Z_*COZƑ$2@QQma*#שKP\( '$]%RxШ8-%8tכlE(V|ыMmQn϶64yѼ۳^~ՌLR?֝^[f8tjBusv{ ^bw7Wnad/˵cJ:_5bCRp:/*vC)uQEo_8\JE)ŽU $81*]m@u-+Ե~˳K9M0,8` O8 sA@LF\ O>Io~ U zB`,Ԕ^ⶉn{l-ג!'glϲEz׬&( sLoC/F\REUD3XޘEϾiok|"\nO>?b"s|h;緞_dLF 'agƀ4l{"f8=Y RSׅy7O ,Y Qc Z$;fG"4rl@,F}Jf7I$>T'NJ[ Vh*x+@$Ԫ76 WA; GɂR ݃b1$/ޅyqoW:AI(({R 2>˥IH%麈|:S%sjn )X/mT֧Aw[))V PszJʔ_Bӝ#29jt4A r2D%Uf`5 *t uЇˊm2b!=n,%X4\ta[$磊zE#w(cr,]~PAEdET>_zG '^٦J}U'r hJXӔrΌv9YZ5td cưHUF[k/=:\9@)j[7 ӔWz _:8@5RR w~X˳~E4:eU;puO3NwZMv3/C 5}ŏU6cF7]١afyT)A;>;ꗧ{= ; v76XD&6ҞVOFih巃J<Ƣ@n44d%용VoT}v;}vxR*j䰉p1)iHF\ʍHMVžTy_:Ŝ,SOsfo7\Ė>hxƤ}ifk:T最j"a^ v1DA/E6pkLW06nv< âը@^/WQR+eFWL4S{bE @NyBd*GL*QTTLZhNnw\T*?o4m)?%i*^)[|ʿb%X*- +=EѲҘ4Z%WNNLUj4&}fX*ygiu;&V9yOމm7T$^q|b}0:F fr7(sCNEVE%TPD~쾻HsabS`O=#z6_d.bR6EsZP_ZmlN{~r { 3QnEg|y~kMrWonM8}tذ^{ҹ`cĢm)l"[dJ)ڈ| 7J9>}{aЉ©uliKԗ F`/MO;k~h"qb'3^^5RB< QhJeT_- iqw(QMAE靓t׷*ɣ7/Z_2VɚNYhy3Hrx_i7nV y2 5 GqY,#0C[! }<,]X` NÔvɢuqC{X ʽ|Ѣ?m7tڹy;h]kʃS jɗ_?aqϔ}{vD*_DԖp(ѤZ$AYqF6L lL8sV-s g? ݼ ?Hy&\u's/*T%NK |—?>!r9NJ<t2z&ppp~P8'#XʡIBQt/Q$ Ov/L9 ټѾ+SQɰ 1ґL2e((3D}a%PϥcCŴwm18Bh&\nh隴R)GаnwSvcf˟NTՕwW8 h}3M#IX UM"!]өcy]fe$QP$2A,M(v"nL$>>U,EZ p2w^Je9304-@+o1I] $D \B˂@_] ZEhO 6JQ~adfm<.JҐ:K*w'-F gr7˟{7t^7&e)n<%/9DmIJQpuXf뽃“WB('R+g)Fn9}{f,I>n+xNRl}?ܛw\oO/pݩU@~,S&vk;0oλ1*B 2ݜM"H4X3Yt;ݬo V%XfMKA9Ƴe;:'[xѪ5i[2z+fkОv<;o@ilW߽< {Ֆ5$҆@ ٬EU۝^[Ow$M.BEK?¹ֲd/8B Q ⭧7 `n,&FcG1,KDXt;=8$w+/[o>>Cw EpօbI-,fy2w5> 5DrL1%q pnsf( ?KǟM1 ^fpNA3;L->Ÿ7w6sPY0_٘y~?T%DPN7g< Qx68˾İca5x~DqF<(kn AyL /G}g@zf-UcE|sԘ趼chgX5Xb:֎-Ӆ:A7ovP.)ڹnD0`9-`ψa_VPNA @$2K"=stĠ)V5f,d|"XwQ"՘\":\2[.d"}۸N!">0Ji RZRf *CyJd w0wmAvyA("*Um\\.  (Aw@q1=)]Qu'Tl̼1b5u=619s 4zA>S Ҧ Ꮋ9z T MES؇@H$v9;'ܦUu,ȉljTy2RŬPa@F\QP~[S 6Fە+/h d%ӂ5h2%N *Hxr<LEQ2f 弫!n.X9n  hVh],be6Xס@I>Lt2dG ) 3 PZ!{ ~bA+PI0N/,Mȡ̸F2Td%$;7]j'@Zܒ(S1q=iy5ADßew?byA`tНECHֿ Z|4KxuXe9i;x ѮBH,=) Ceu&ь3c۫Es0jE(I1ˈnsqRh v_y猪@Vqsvbfi,'AgRHΣӯ>3˦ޫBWk#je {K<2%}hPY֍:΢L rŕ3_wSt131 1c%c61Gc@2msV;yYk@,/S~~=Z}||\S0K[&i÷oi*?Wg }r| w/Ê'H(a;v" Q#i d:j7Z4,vI<̔0=)ol8^FYVD Ž/l? Jw?>u)Z3'""ݽYiIDNN@s3)-'B,~Ty3bdȾk\TKыA>v X+Q:XdrkS-6Q hv$Z>4d mq^j+ pz$ eKnyLdT[aJV2iFݯFO8-"ܜr le*7oE=$l.mFYnbt_r{abE~+#T$( xT0"jt YNFV 6Pz > w-4*$&H5mјXLnNĠEaK#c`lUC*8vG{a$izBcQl]Ίf3N9ޯGsCLo|GulRTl}1r&+e5PVNoG ; H;i3h n2Z95/[53yXoudjr0X:aE)⦇n8wpvp GVd 5KU32 b_zk-qs9yVxZC_Qb!fjsI 9 V83H ̂hf )L ` &``FDjH,] 38&$2[*TC%zϢ3 337!/esJ\: {KR25aNW C~j0s÷+`d ذ`N`y?%Q^̔LB (3S#H),`,#klo'DEG*H I8h-?L,DLL̘`J,)̔$#7}XI!bf 3#@d0!1 jffLW+&D$ @|I1\D"&`%:|8ikȋր+ d X=ژ |3S()`yA;ٓBZ("/'H2(fޓ9@ JFlϾAuPɢ'bf &pQ `}!0S{P"叀,R My j fJLP2Uc$ BD*D P3eD/Es FQQ*ީ) %-<yݹ0#ǒ "x/[D %`djP!O@pfD LɌKLMw/m8ꆼF@ `F'țGW(]mߛ95@c3"g)<`]hVRTYRCtlbL&B4bc@ 8e!6#nr^D6%aq[rÃEe5&H~{FHJ$ O0! N^Avfdd0 vygfdBOfًr@aNa1gm,2DjF0aFf 2&4%4R UrIJY"#"S7;ͫ3d DEvSSDQ%21֛@M 2')9hx 'T)_lNz!f)y a*C)SS1Lh7wO|PGd'ʧ̮Ȑ(؛)by8|pwAU{o{*$9a&5Rru0 \0:\o0^)RM̤T%o&NA75"@d DĈ&z6ߩ^\}`y^ b*0ajlDPl߾XzPrc!Vc2%%3Hm`bDPJ̖ya$`<iTGjقs0x6cbTˮKB"JĀ[]0ĎTi'#`k=P5%9p "bK Q-irLb#%6 0s#$1]"!$ Ef/L|"ðlL1 9lA@޾CL`朁YT 9"CxU 9U/ T,"Ga3( p+3KDL(^L\ f&c j b!ppM )JQ"2bҔ9Srd6tHA:df1erC`1v1y ̠3٥^t Ǩ1ȐݒJdH?8̦ b`6&$*j6$#&yTMl0S12X23.D6L g(%H<,6rp #J Kp@CCP!91aIm3%386i@2;?5s. !栌rKDd(**i )`B9 aC =Y+I*`*:K^ f":cKJ=USbΫiJ PB͘,]e9WP59arfwp0jAaNވg3@j9HÆx11 9g*O0'Jnjnxc83 ;`?7UJ$QҤj"(;r@[(pJÒ竚yf'Zι$f4W `P5S0tBs؟0ÈJr (GJ!61'mj Ȕ@j0&ͷ3!z|)j3T UqW68d@Ό(Gf Q"&RU/fKC1bh6cL8`,%)(8VQ\Qa^Š5Uk6D$E Pa02B1Xw035-m@@0cNҧWD Oq|u͈sPpXU}6T+>圳!=eE "1qAe"E3 P̣' SQb`#ŀ$ @ScdjaB2tRUno:F!\#%4Ng 8'#%s^3"H(َ˿AT( ĉ(`",D`牉̔jL| c䄙͋nHGq.7G[ " nbdJ0`U`46C(l8}JDOw~v,{(q5>Cf*g h493M=iaJ`(;X#u.m〉fǐf6d +C*.`&_1RgXм~_j ҫէ Ұ4kt"I \ay%f5ewHR+A!8 z.zf8U@ǤJ.[Yp.ы!8!A13t.vŸ;_FW?:r>Y]p??v;*4@CTiPw:|"iFpuuR J||<_ae@(0G cQTA5ׂ1v0UAjFQ,yZO+[e1U6 1Ĉ]cCP R|*^پFŇŵ;uU;[7t-#9)BA(o@Nm@~x-DoP4rD5gD b A T20hΑdb2RFl)%D ,۵+9-GfX54ձX!\3 {3ꀂ7Rq?~5~q i9ytOWĹI9Kb3y`ejC lg.y2s Ԁ2 pLEռ*9D0 z"bf#Hꔃ c!Djt8hEssaAEp(AiM.SW3n&=>dzwro_K闗{~ZhoLT.;*n!EJ&}J@@<`̎4)+yO cYo;&1*CBkŅTRR1Fa' uׂ)S@E$ IM mEM١oJj蝢qĭD%GTR"6cvҷј9H2v3R/k5DQNa5ǟ_<{:= x?bP tޏ·cw愕r }g$Q|x܋Sa IM u)Ҍd䘁{Wճ PC+`DA9D08::DU-~U9R1oU2.V5T@""~M#,iZhIEf1<#\2nQg3@A))9 2|z+7:woŴ~Kx{|j:Fb :e'Cc Wa 6'a̬k00(TMRȾtlZ[?Zy6%P2 S6d p,"XG2j{T]!-a|33SGf,LEQzkcl2^U2E DqG/<~cl:7op:(k@~$!󎋦 ͲǧkodfU v@&6-[X6I`"aS@ #],ƵRhP:)'}48! C .9iBH}2GUرKـV”SeF9ҎE ͣGpd^r{7n4o̗c^NOF_qe)rFp)xXdQSuw5Wm<8Z&]k 1L͌õ Gf.P1235m ڵ-<٪Ro5 z110!:22 %zm5G UL>gF ͘RF2(5i3.jid[9q>gc~?;8:Z~hMJj{v1|6 ~Py"E^ {! >L f 3 q1+Cr MS ScU53fL=iiܾ۬:\\.Nhr&w?]CӞ)u~$ӢsKDjĤʤ`Ψ"SGpNGJemzk6ˍo/~.ܦ;xt!S87t} cMI*;wL{mSɓ$/oS)?z WKN_˗G?įr''L.E!3޲"k[ZvވU{JV$>U7exYXۓ=ހ'G7룛_ϊDrÞd``hYM5TmBU"DLfh"jNb.(I^?s(cF`~OWlkDiVydaSotꕿ, )d _}ai\mK!X}o޺,2.HEw&6]Ԣu|l_VMz?wwzbE}̉TQtg4-snNYӮ;Uן}g6zr6'S+/jY`;$))Gyj$"Dy@ThK[Oӡm[y+kkh*lg'Gv?ݘv4NBW٨A66IUZMsK[o4w?;M:.VgNy9x|XjܟnMwWfDgx;̎1Ef8xSx\T̻ypoԜ1 d"C*#Wt޺8GCrYNF{eӵ\e\lDҡW>WwE*bt\Oˮpsܖm?EISx;u7|jtڲ.(;insTw.T"^I=~j}!H\Yw? 荴tϾ=1l/f5+M3Yb66S 5Vrke2`3ռw"Re_V~k8,&o5IS$j.t2q Js-/h1M\$a2{|C$T#uk{\6_p[o}]&II oN˝g&iܷ;a1uuxUg$f36v׾Z󛞓J{A>uM3;hO|]QHe͎ؒUKOpga 1T׷_t[QFZ/'bhKٜ4]QTEA@*K~(6ópŵmYōeq*'m$X͓'7OnϮ_{8iNۯQ9}sOFL4mkMґMn<^|2ߣ;Uǣ%{tvH%Jh7rqYE*Ɲ>Z3bvO麌2s0R%7+v +w sx~E<{r.QW,\-4]XK[ٴ[׮;?i܀ɂ4zsv-}pEu|˃;}GiçLۜAXϮy^*6zouܚ^6˧\_"`f7 dbkktwΗ_OO澚RSYԓz;>'6M7x߼{Tu׉gcj WD:f$z5S(5?A"~:|bxc>[PvZL`n^[[,E~WeHՀRVCwFkSZo?ss =zogZ8:2TLUEDRpYW?Vtx'ym❝F>ݍ(g^iܸg/4Ъ_Q#a2U\H)аi[™lo|^S~^DZ NgQɽvUDfT_;o<= 3.yV-:=_!82Yn|p6yrx.pfӪ0=3ƪRhtrqcU%vNos+ONBvuY|p/g{iZqS>.7GTϮWITӏngJo~tZj\R~<X7/8lT`{7u(MrFM'isZuRd~շ 4$? a:zA> Kq:Z=ڎlVX߮^^G71&twtz:uYBɤ>w׎w][ָĮtƧJvܥMdY>fO^/5/0Y|sBIwFU}^z0P+q篗Z/;'7xtǫ«3MK)e<7 wݕ]m&xK7[ЯHw9cz^:QiyFsJXQ%v"zBWޮ%ە-zlONᄃfyUJ8Jb;c*h8~b;ϥ׮?ksgR6 [ixd~WOFW61~`w^yl].)VlIj֎lOf϶\B'j95+G䘈1g2ȅL;.EHL!c0M iMtQrϝWjXkhVu6hoyeXE׺B֫.^)u\%8DX,q/͕]7&ؠB8L9mzFOl5$qpݴ.4~^G_˳D[gO{O'wM[MՃyW/v{욂zk#=[}RAUvlE;\KGt 8Vw~Os [[-)YiktYN{[]q1)%Ďǎ$2vtsԖI i<1>C*lvl5i+4Yǻe;N{k^8bOǿ`/T6hOz9[4r<pyJ%x-%-8NZ''7m3go^XVo~؍/_!NiyqQ:mvS-ZS#_්%,%#'v9Ke׮󓗎w{\SEMtp [2)d*̵<_lOڢww(6?F[OtT.MՊ'rǧ:,jŨvg\MV1k*NبMrmK蓛#t(l$QLDt|GAp;~|&}t<<{Vq2C}||zq&Kn(J>uQ/rz{Z*mJH}[7,$uW[Ğ올av<,NͭUA ԮS$w)gcGŢ'x6]Wݭ^#{d~|ym:k/ohCk\=r֥cRIЗy>f5\.H9=kڂnbι,X]{6 F4jV+]^;ǤiUFlajopޫc>O[uW_vO5:ɗxdq`8x탍qGd\/vr^oG 9u;uɞ]Ο7wHh'#&DRmOz=ٛU05J+ S]t`i]<./)9ALD\&s<&nY]f ҉x|o;gtBDLsLGyy?^,X.Rֳ/CD6Hrƨ75;Riwk|sѲ=?jW>|+iB粋uwſc7]|OGn:{6» Yd{#~S3:mU{b`MBUz;M5V sIrXM6ٸz8qݥa#,RWkn1+z(:h͈WƷݙS.ԶAэVN WcT>zԿRf.o6+9m~pQCV>wRxZza <?]qoD \s0y!qG|i|}- /싒FQUaI|o?xjK|(f t)FA ߾}k΍G?z!mX+[;η8KRQmwzzVV6C-)U+{R4tg::(cYdoqؑ?nv9kcVk y?.{<[vg+ U “9SZZS֎=чO~x6v⿪ViTO7{!+lvpw?]['Ms;ONTg~_4#A)ѓ93f F7O19$Ł\@^{J_.=)Qcmn-~/2WᲒ_?09Kf[=lW˽~پ{OJ맏]O>s,E:[loAҔ%U%BV_}*yƙn6/orE[B%5=z[4776;ǖ~gfacL<2=_Zo%Zn㦹m;ԄZs+)YꍔyxIe.Նo> zz})l":[s7G),gJ֭~qF=qqt8{R$KA\yL'tLE;|sl۪o]ª5O~?jUk4"/'//C;^m(Omy{?Qvah_}>~X5+۳x7;/? .]pKjfܽ;lwKŅVnc{_NوHC qΌ}oQ`S^Ӛ/?:+Ǔ{QoSu/MV~:NDxob.1E{?~~y*?pK޲g[lG66/~o>xidgY7w?Dݕs>z[uu>i^]HʢAd9ߑl˪E.)U=kǞ{=2߼eSqy|ۋkܖF#4g7z 1qnM4(ѳK<[]<:x/B86ߙΛUgY6-XF\|߹?ùN<[d]SFfE5<ԎفFq.d>q̻j]<1I2Oj74UvoTz>yJ35_Cz7O7ɬJHnj^ٯNݵw.zȉ2mY:<"i ;qP7RFCGĜ[K`0,w_xr||n'/c a2dfs?ۼx4ys{7ìoM1@n]쟍W}Mx/x~ŮӰ}lɕk1p6t',pp™/g7Ϯ/+4хDK@ԑFFon?rov_~ڈ4 *RRpm_|396_7h4 vgUS]?r޷=Iٻ`пQfn:r~؛>g2حjܶZJ|ϫX sW_;sY/}i_hme1u!?_ַ1\,GxyάUa! I7Zt|qZ]xhm^omyJ `% -n_O9׫;{sO޿DRgO]eѕ yo~g~F ڗ~1P(A59U2%һϾ[+ ?( E3ه4ꘈaCB?`'}͎F]i뚂qܥ3sg&GVq쏿{qxc"Z`܈:Bӹ7~,ϖxr /IGMd=-8vPSM.nV/Ǘy3He:JJA!3IbUG+ n޻;a sXu:-{o1!<@Ȣ=8+ALҞzpU28nH*"Y D2:˺plTy ;Pu޵Dj䑺S=u]" f@9SsdQ#S2o Jss+!Ŝ).XB L Ņ,e UL E$"f>,*q.a Y0H:7Zxw֥k٠ΤNi i@WRuM0ӞGdIL$L:gp`OD$XK;fx03a({ (7Ԓ z hU$0sZD<Q*0zFLe)#$L\@àK}cC30띙xrAXķGӴ۬j9ԍslSs(tnMM1Fl1(0QHD'1 (`դ98si{W~{ȹi !紳D S10tD1DL43Y@x$9΄c(3r`X;g X2 ( Źh0f#S3w,sRg!"H pGjPsM?,pu L{á%r:x !hʽAM T3 d2K`\4A\<ވ ,oe~nK!8A:Ic-\S)*X5g*0`H@ed`ޤUT" *[('f *v3S&YyґȊʆ2;r V,qRMWDD 2k0"c`(XؙK@ȇpѐYyI |y?٤9>=& _ ĤYG3`5S2j{!k'miBW#1%&C|֏҆Fܨ:Hj 2sJY 4^ETAE;2.iu dWIic! nC"FlW޺+YY5x˺.P,0X&b"Q" ! *|=^Vq?@芬I3y|]aW#uW} fg0⭪4 2vC\)F@4"AD i!c(V$,gZ2RYIOة+df; gSB`SabyL<1;QP5zAo;vDR!)T ɱA5,26]ʨɹ,;&a3D,Q0 %')ycMJJo7\{%eGB`9TtՈ)0scMy !:6FLd@$ޒ1Ys*]VTҍu1C ŢHxfĄÒ;5Li&ZJ Q$&«tJ3ȊZSo+*$Г+DH$e?lj9&3I$Β7EnePcҴ-rmLSP+44UU@4]C׮2Z JjDЄ!KfJP`d,*Ȳ伙A) ewm QSEf>5H켨*w9E1 dbEYȐ|wk/$EcW?Xf՛˦=lYMMYSܔ2|%4&3 w- B渺F$LFn0a2(0=Tf2"4Fk\RYhY$@AL@^:k]qyf#f!O %HC5/WpLj)_8Pd &PAKى+*щDs 5ʌTԙkYLu晨E6)uq*ģԢF#̙θth)b2V[YiD %bmFծLUS5"A( 0a૾q+f,1OYy!i- $v#{26EgSYLyZZrr>)3+4% >F2!(XD왃k-DP ՙ;"{EuTo8#Zp"G5ۻ|gߝnp֓h\+/7V$99Q$ЛS<K)]V.9RGixD& ҒI9J*p~TY;YUU3UG Ci P ^C\\˞5И/_瘷uL`#J aM:[jTS'Ǟ!:3TU=ھËaQTUHWoeISQcUJr86Fn,̨Ϛ"u%EI 4,ch+}arj)XUyDl}=~HKEҨsVTu>[ɫAbՉyOUt4Mζ> 7wQɏ8tƾ~?cβ0fRIͅyq>9ry gz#DeL=<'xy5uS#HÙhαOQMR }\]ŠZc1Zsf4.).R_RUtny K!'!ӪΡsLx4Rizsv6>\k'' Ÿ_zmJ쀠(uu/<-d瓉;>˟.r6:(R!⓱#fڷazŬ~$?븻\_L#pB@|F)^ QbR`]n|zV^l.KwKʹg :zfaTOp?^Wb fd73vI"GX8)QխZq` b_b }Xo?/pncce9ϺD+ тbK')m-7w}~|K)m0.uw>`2T9*]ηO&uxw':6ch``3 3x9`KR9q}**G~~:r[du\nhaFKn^ n|j贪=wД0gf}.̩$>+9N0:F=Ap]y/F8{>ܸˣo^\jkn@Kgm{/>f?[]b4)ͤi/-lG;6FlbKIΩ(ꃛԯ1K؇grv E RᣜT@A01MOʩUw=9n>pd`!68YŌF<}BGD/J*xj 3TA"Wۉ۷_pcӉ$7b8r`2IOĊe5q *E[-ӨvKyeWIlR|=ǴJhtS1~|2 1_I{"ޑ9߹""}n.>WavO%$6&\ u,&}W_^Swa" MB9xcRѭ7XƺX#S 7WE#_zqy^lry"/b2^uvPK&|WPso7SYekׯ1fL9ԀR \fn(̪ʺ(0(IJ)eFFd>~kqn`<~9{c:wUzol,| f&d6ǃYy0AtAɯ %VNNWJZE9 q i#fSjߍhO%&YaU5PgLV e4ԧ`o%(&Hg^z"57]&υO\8:,bל9Ǔis=͇?p[9\O]e#Xշ7=O|; V>}v||dT+HD QBPŸVVK1~@ELun'Ӌ4퇽۩$LV w![=]7[glփۃK_m;4mxLJΣ ϖ``w8iU&@e' IǞx?{lwzzd0iO]2.V$ 6`ޜ|`6tkfxP Nz;7+pHο'PZň"JT/oQ{ks^yOndP`,!G D4L(VD 26CyA磝ߖyfksSFY{T35'q>׏Ƀ8JK E|ږI>e*=z{欷3@TڑDkHѳ'U/7?-Ci(hҟq/ݒعgyogAӧ擧^ڙwLcx!PMRu,ŕO]BF`G +hqѷAk^V~DR BQ6` i7ԧe I/Mח^,7ΉELqiztMNj'T^7lNIo}j,FƥZ0-+WǶҫGM!jfk3 0U5h0=/>;-Íit${fZ ?;}7AT`p55n||Rk[/fnel=3׾ԀST%;+9>, kKi7;@iE`jcւ[u'i[|ޕWܭT4Y;q0+`&ٙO/rDvZyG)nt5o6{we|7f$n|ѳu^ Җ'?|ڛy`īF8{'>lxr9sxxv9XfٲnoOf Lջ(C\\h?,f~A9k>ygk/yE8MLR? ̥dxsV3j;)SD\=;Sm~AUPQKgV ;κt&G+oJ5-uɏ}=1pG{BzGd1t^9|<vgghn`HFߵ؝zENۮL ,!*(fºb}g,u<ŦHhuD'/ΛMsx{'K WG,=w`.ぎbzb *$4 F Aǟd'n1 f\85:V>qwBӶMt12Y~K<4Cٽ`!nJ?r4!"n-_~pQO;]M^SD*'1Dr'4 -amRVn3!@~},}㧖+VFM,h%w;WrS7 @9 cLt RrqS|SL Dik5DcѴxkXT7-]1 \?ᢝ6Kڪ_#"("Rn#}?mѬ~k/Dbr|ow^sp?5Jysɲ H7W~L3Z&M}y]W0py# tmo o'#D(8snyNoe@fyo8y{i.>C]^^.vˠ!PJFN03 1m A[{>?wn>Zo?[okdJuɱ6GWhBW06ަyo3{lp~Wz/-l9bj|%t&KB$zUU>2?;^]9D5Y[ع_4'iq 5]MhX`uj+??&E]|鵕ū桠,5_$V{3uOfk1Ql冀QN&͍n_z_5RcQtkHTZH 3ER"2@G|3`ך׿L\_o4fz>S jv֦]@5g/6.]wl's4h+J}']utBb~9>ԐiOJT R=A#]#xj~tqm+>~~|Z949HꊏIЁl:VN)U.th+''wq yq'OM\[ TEv7"|\𦛾ulݶplRlޣ=b⽏Vy< `dj1G@sNS8. Iޝ ߕf)ۃ,Iwbڙ/)⊼ƙ`7 č0-?{/^_{x6 PDb4&NCx=z>~gnpR1ݱ5Fn(]pl7/1Ag+O 0tOP|?M>6&I;pÜ_Qxfe iiFÅDJ&X1|y44Je)\Dm} R: ,&%0"N̑;rs4Y%-+[z% (Jε!tBbEc>|pkSԒT'Gav̹Nu#@$,q޴ojQ>ӓM((Ʈ}V%&Ϧ4}ՋtŖ6IAM9MEW$hY:clQ>^Xewf^}$ֶqDO"N#nR̜SFQ_3P&ЯX4jis6~:%py$9X YZ5sc&zPJ̒7{puc[sglo첹EEf<ƻIK"By\7KP8w-LG;q4G>\| +Tjw-<ञ7hV{]mbHc-F#'N4s$ltǾӳsWUAb>RǙYrV $6zZDCsB3~qI ߺi6~2t.8^`n `(܌4dZwn~qŗyL6t]g dެ#F#Xk,):9R*&gX.s17B^ FrD%aX6ٖDA%*% Ig;)5Onv׃.V}t]*jL#39ޢ,^cÍ̛]S^1`bQ +8ZD2Xl²0XB0|@h8=YWΊ,ϫtUU^4qܖz7-YΣX|:3u}ȫΑʒ6޽y[]/vOӑ[B|ud նN[ۢܭYh}rNFpةAگb*=7! krW =AGj488,}/ݽ{F425+\}/hDrFwfD66XrlnVn.gݾyZ'˘)J3>n^z"?InbެD(Qu^ypx{ymѬf(K,Fϥ&1II"AU;fa&asԩ;/?wy7h5[j8d1XcH# fTKv~\h $͠C|K?&aQf=M,Dd@*i[pڗQ߸d@M8,yL~<M#Ө!*(h;+G<<;Q njTyddwPF0Q`srx˸GCcnS>u"ɧ^9>{O5\Pey17.kOQ Q%N`&<; 4I t}2:ߛ~ ٸ #xBmSzln?,weVn;g.+*5,"' { @*m9#JYTA'L4yrOz\q47!څiT鴻6yc6D[ۡN:@ ."]]]8̈%Ȝv7Ys3xjFzOPa\HIf)f']yK uT$:vNoNBP.NόV22yLBŊiR/ 'u.{FG~0.iAύͪX>ɷ2pP(i>^[1If[d`$Kxpvw% $F]|7N}~csJG)+ dswewg](||)3Mݷʚ}kfrYE.I!c޸[(sp W0X\|ݎOiSkFydd9z Yg[{)5q31au'Fv_᰹NƳCE UZ[pMعv~Q7)Pۥiw*޽MQ &4%Ej۝-BsZk_]~z~9dx/q+AMz)3~t:e&- ]{puj Q8,& @ FO_}v0vut_Hl<(h_l%Ō#3@_ѫJwtx?qB92&դJԒB9%_*)yϞ~V 1rxvVD},_};;]6$jwDdE_7Vؕf1fctŻVEO?L^Q0 /?\Õ"ocNfm!M׷?w;Y~왵bӹ[7W{cG?% 0 DAţUp^7re|xF4Iؠ)* O)3R(i[_ÃøW-d{d;Y3uk76QEL uϕeú4{  ?6U:u쾼~g͍noy @yWs?bQ)m'kW,3U7m6h,aK[qd@hf߽z6\ :wx?fؐcbE!RERf@g?+2$I=ꞬgJdD.qA.526]#1 ZdZg3eMe5nxndc[3wQmZ` !Y]e@qDh>^ћ?{TvK`Z3ȑ.[I>MM8ՅjERa WBfc0;jnXģn_<9ӹF&&0X|/;\8[\sp%;_]+/L)KZdvl2DcPk.G%RKw.=oſz#nw'{1o͇.`!qZfiq9 m'M$0Rlؘ:7.=Sgq\6߽S߁_{QЖFD4 [3O~ߪe먚*Z%2H$ !vE5C/&-['woYpu.e~3d3-Vnq"!53j@S;οdᥘ"2Ȣ>^a>IA?b&6{cvLiegS?~>|uƥn/S,eV=.ZAʞU{v= =jCTNH#(AD_Yx;?tc1LP@4<ֲIȈM)+LY|Cl I#|߫:ʄ814Uǩ]8Z[|l'~2O̤;ܭβ-V*E7iЛvmALsLtK3oz\cc@-'MC+38ws]hˬ1tjֱheA"ԥj_$FPl4}Nye9,4c1!~b9o D0-{^{fsvryf5D,&ܲԀH'gi)@UILhU+VblДqM'Su1OڿD&hhɚSOTaӣMNrc$Nk(^Dn|ih,fn <JFk8iR׹IQ0uBIRv l #.% F\iRÇl0ylW2p(\2@B")@c$E] X7ޞԕ*T mI4sZcT `KWE!؃leămљ,[A;aJje ,r!|D- ؖcƀM}/r}G$T1`$Dd4q֨@D2S"&F jQW~U6z9@,1ZƠHI:ªZZU!ǀj!B@D H ӝ2"#+EU'cON'ld$1&@[HdDQb"` D1+hh@,Y#ګ!1T=8[cT4:6L @B1A7ac1Bd5Dal,NlBR"0@4 @ "{NlҡIcjL$A#GFJkicQN+ di1zJWi!5PdE4`!clL+ Iԣ[W:6MKk!@Y zPLPpe |h),"&p,Ɂ$ Vh"! @Ě1`D$"j0Vkjm { QԀS@#ijr,}(SPEj%Df"!Q0m`B6\J/Q%c!"  VpĢ̈Ȉ . H(AQ%B#ߩс\DԨV6.ZH @`@I" A 7.S3ZjI؋:Z$"*:U[Щ+pKul |FT0  b@LC0<.EڜAcj@3""S AEˌJLhZZUQ1"Hl"0l"12рVMT0z!A0'h LP]H%Eɠ 5@$a"%E)e" lѢ 5H!CTQ<((*VYhڠM%"Oq}FaEP4N#Pd, wQ ƶR0*!P֏hQEUAEHШ@c۬(*:TɋU,F\ [GȑD"(2),&l4(ȘA $ѕhX2,Ɓ|$b4MƚZ%GC$ `@VKj[jթ}OIۇ@@rjZd'ȩ/%4V"Vh*/aTC d! &]-L S0`"R^h[ `DbbUlpW$F\JX AQ4$>Ml) )(~H 4^$*4HP0IB*hCX1L]M(jR֘PE 4%ƪfך$H,b4i@QU8$ c,ԄƤL5yb< B,# dil thL4F} 5 E q Ip*k$ eD]R"3,"`,(E֪@8S19i D4fF-rAxi`o #Zcf#@16QɴlY@9Qt"ؐ%ERQ2qmmp(Mh(!!HFVnQVUQԘeY G8,22TcS[B IjED# ;*iM(BmءHX%UKH̒j#(1-~hiBj[an$AQ0DBFQ1L)I'a_XiE4 TH&**(M(V~3qj- hSG\@_"P, I0`L5ѳ52""21 - ƪ*S-1$h=%ѐvD â-sDZXTp##@*' *[ b0v>mnfPU,*=5c@ҶʂLX[4Ywec;W7T]j vObY*!361Q뛞Eɷ&Pk kƠF$@D" Y9kgSTbRfb EVLЂ2pK0PcY AT6)Qn%LEU>t .g1*hN C S[\wFh+7ID c۫x+j,HPCs!d"o$)KhVD U0UTQGFgbLز fh!hEAٴS+(2slL)ajZ0  DPlZ *"h[jF&vF(훀u!I@Vx8s"iI3ņna7_!Z"U2f10a"be*̎89h+bBK"ћ<-qC=&Ie!IUU=UXv AUgm:]0$lQH5t,qlD!+!B)jDAa"+"h +fPD"+!A(d5(QZ7*mG@AXQ?aI>*&1,{ߺ]yvRP"ڐTu,JBBz9P 2*h50(5b^1MEX%SM{ !eiq?Ƥ=QEcqt#3+wi5*>zc]r;#*^AAEUQQT*J 5!5IC#Tʤ/<8KasRAΑi^[]f@Ţ1j!VEUix*`g13^xCjQj`΂7&7EduDb7Y#Z2˨K;F?$310#ڈ2*GF\m-(B";OHMVm56.mkEE 댱><崮 -cI)@7gD/OLC]r>_1,+Sր`? -6؞C+$T!"`"Mz)m+ 1{jZ+ "*KKPd@Hʧv/Fڼ0 "1fF(ؘ:F01N_d! UX lb&hڋ7*hO>} " (2!ɇBGAૢ66K&7fzt:ɘn3G6kZN`nے钂xUKm7O/E+s( K$rg"Xm4DF85[" @P$"Ӑx(jS8jDEveE#%ԅFuVI$j3-VFTN n1HTUX'ޚpzҙ~\֎K@@"Z-Lǽ/ߞƞLTA 6.eT#@A'b\dںQ>FmYSxk,jJ3O2HJmB RU4$a4&.ۚ#6EJU!Eêh,r%-#"P hl`DHҚYa6MKUSW!P%!1jĊ/=j}l83fac<1 rdԗ~éNWSJv'jjNi) `4&mœ/m8F$E(LN%MK @jap" *l 4E,x0R,@T:}(Ed== c"B5dڮD;~8UTi5*;!&63ȋۚۏI 4$C^bud꿘t&bI"%BV2`rD(zMn 6H ,T2L=FR+xDbE G^#Epc!IF 4 *gijVT%&T0xҵ翴/S7UkVFvbTUE^Lw~ޅ0Yq J*q+:ntn4* R[4B l h`gh,0C"6a l]5A;̬J4BΡTAƠJ hbEi&Y;"APaB֠:h-̖zsb/)󹖚ii,YCJF'PQP Y,KELR{yiU@ bxk7d@"$V'3pY|g|^څ RBn$ k6/;]mZ2֌hmCD ,hGib3% dQ"%ZU q&DU PAtơ u% ,4N$6s'$jZ%.|C)ȒZ<5#I( 2Hi81MF%@ր&FNL\4PG4!1EUQB&& Pz޿[WVW:pV)I$ɶRNdT!D$*4 &&` 2iIEXn"Z8RB4K5 <1f""'@$[QiȢ, 1<VBE>K,pk+ϼxnmlt1g"Mw.qQ''YQ=6 Sw=ګ5vLiko#EJ-aSSτ˿{nK{ 7^H9Ogr@/f7vT`ё1P r #h#1IK'2K@2Zg œFTH)3+"B Pm|Sæua40) /Zyj#6׬1zB5?WXЙNԹ7zO?;kk_𭰯+CdT R8 I?u"l$%RLz QEH%@_-.߿dwn.H@E,3Beݷ]Ѳ;x FXQQ0kUpz7FRd%f@Xb4QP=M:,8 bfT81 ԈGKBL&j V?4h H;Dd! %3gՏn'ޯarbNW`DJQo>Dg]ls k ɒ:E3X/o38>fwgp;-!z3*ՙŠtه`恡XE3h.ΨITCZ倄dJKhej@E@>I!xnck-ŔZ[nzL"@VYK;9Ү,(An3\g8\ZmWng~ɧo,rPQ2,(G~s Oє['Ut;@ pF`D4+bɓ~Rc4YI8pO($e,;C- jɖ4) cbZ7z@+*; A@%AB'*׷V ShyLmAJ(E$FŤZiG ѫFQ`P$ dP[)&38mݪ;\~Pl&[KӴB2D*Ӫx@R{wxqO vMp׻; P qdA* Y0Ǥ+I1Φ&]Dב{w}W 7CZR-P`Dh 4JWBe)qbb;QոOJdoNFDh[?u|a:qRi`K+qi!uL&<8*leF{W~GPD^ٱ- 'MN$.hW W+3 eڟ~-=DTs\vmZK "rT`4x)S T}hV= ,24˭YK?B5/ Z?ʬ/ .r;DnQS1֔X!> M Σ!mF,5Mgp 6׆;7|}@;RQTrLS Q=Q1)ů'ֳǴ?-7 kB`HF TYNLRаzؽQtUvm 0yD4] ͼKbb٘KFcQ%%icvCʽ١=4tѷ^/[I*Hөei7MڤD' c-M ogvgzpU};{ғk7dl 4X# T!q58㿟KwʛR<#WR,O<'7ǏE01XPBpneߥILaeh`m&GGaHZD$X8b+Gu…Gr:~7c(i8Z`wD$OIfg{ieo6{o]&>U?D猦͵?ɂ4_AZw%FEphz[?2 {iH> gomo\?ԖFTX!d,_潝{oܜg^Ym-+;$:GOWmyҬ,-EڌdE$ &%anR hRj%F-y= 'lVae{UtBJFBMYs1.yA;K:I>R QF8s7;vg`w./ל?du_Zsbt%ƫ?K8Oqg6 iV6*}tTtNs;R}B=s/'TY#8J1Lã,Q)=\m AњŤ;3e'ctP͆d'㝅ɽZѢ8&TbI~~z${'´ !^?3^ݯmvRL?gwnNh?w?X] :DŽxc9yGZgv/>UKj&.~i#Ɗko-;פp81ڜtYcowq:V P=cxqaQ.`5mIܚ[\\$0/vuxk0Y s @EnW&1U);}Xu'Z%` bÙ?cn@+6[Î̽]~a' i*?k i],.}񏆛I~G=8LM;(!x|MzؾM^^}o?9g̽Y+geMDVr?ű>M^á qA[s+cY\SZ,"qA26I͜`'6VZwQUA;JJ#)U韜B:u(MTٓk񌤝GV˸~6~+oraYfk9YA4UƕĢ} w϶6NX;_;5r{Y!a&)2ygX`z?LBu+gq/tooǽF_jQYąGޠq4>BW26CBQ$V֎5's̿T1ZD+':,ٮ:uB7W_嚬nsMU^<G)kM}f|ܹ8hq}Ļ?~灆|5.zۡȎ:詋_wϟyH{'wB?vwu}׏ DT:2^7{ʼn3Oɭ7C%9*G'ؼ[`ک0)"` F:vb` bl"{ ה(^d$CgU ޤKVIJa@u}Yؾty+Lі}ATc*LWz͸0,V;=drJ4:~_.SYTvNnⵋ뱦NW&:Vv8~#G'KWLr4<=zs#FwNk#zg7.4|z"Pibؤg gӻROډA72qң3yF4dPQ;IWPNZqlITD.ujhRj@TIXG$I9λ+O{om?vpۤ{,'1(rUCRs)zg˷> yۮ`~xgŭ߼qq nWs/~nmyou}\nm?X!GpOE$IۡNۿwɟl~;h0W ~gcur}d3{q"u2){-A`$>8ރ{5Q:n CZZY_q ZBZc)H)I"*K A( W{"6d-bD628D"eLyM=:wӵ#?[*pB9>JjOB5L?RiwE]œ !磳VyWI:nQ),pCeL;͉û9JyU>,NaQ'BM v˿o{(^ޜ$l+}V?{_?ypUEf"@ԡC9|ގk5vHy/7d4@᣶XB41*` /m1 j2#H1 ,|i2T W@][aLJ'[}͵W5ݘ~~yyMk~JTXGtVd=vNW~w}>޴;>7!_OwmAMd$.;cwW>$\.T;K@"6i~򇆿GoﲬwOZSGs@\dEfIp"1$trEy \(Ph4|OJ}u칭O3_Xf1,o ݳӃ}YOb S {aC&'7'?ᛛ,ʃA$i&Տm@Xt]{#qy_~VSoM3Io|""fPupWv}]~dj>(bY{qvU2mȴSĥ%#'p)̦͝*BxZG8iKKH2^X˪ĆJ ^b9Y&lk,K0|W.M.٥`Xd2rj8u[LahȬzݟx@pā_x~u%ɒ2kBp׀+&<=<(}Th״޼nP Y$ƕ٦gcdaQ}Zc^R_ߘ困dwXR6iKO@|#g2"/~L]'~fĥuѺd<:W t T i2$/c:2[|mʛHB1zcʅ~ws!O9+>57L{pi+iq82`#pcW7f܃PP ?BaHx=r+Ob]>31M'@ g$y?<pd4(Iշ;j,-'Yձ=/Nh&; kV0-ykܛtUeͽ&֫at\־sF|iIj݉, >u{1ɒ&uL$1x&͸:I3JGe%׍^sIilEUVb(C|re E9tq~Γr<^YBA""?b)e㿴,iX֛|wRt=ܻB7/0m r .&gv7`#I#]J0eמ9*?7Ù15_t Y}^=޼Yz ?e6iSf Xfj%D bX{ƧN5ep :MTQdi僨VR0k "*eUhb۠VQ! yJ\v^Wv–l"m!ׯ]RJwSkYN}޳cӉE& "r&޵5j}Nkk$gQi*6lb>ֿkN=9[ oKs4I{ƾ߹kŷޕm'AV=ϛ؍&]m-m*;[w{+^hEӀBS(JTe@养VسQ"#HY nU+ԃjK&]j>o> 9f=LNTG~ϣc}ϞjC(R_Y!/]If\Ol~{yt~ h& 2lrͦG9';!I>9?odq7އl_F_BGM٧'h4Hzvm}ȈJu^\`WD%2Sy) lRg9w eQ5%&qy$0Hz_"YFEk9!t9T^=w079s97ع]L3 ܽ=cbB( e187s|cԜo=WQG2g0~P^%ΎF6uud%UU56Y`Uyun2yytssX_޺ԥe?{svs^p1Yߝ-a|x9MvvneO.Rb<8…!i& m&X֎ .Ua$-˖b2Im*UۺnбyUa%4A @9ָ<αyZ.cܒ8}N7S,cgU8'!=x$oܾ>wۋ$fQ q^$8~XF10fvd~+M²@ | [_est j<8`֧~&k(Iӳ $!6pQ=MӋgk*X=J5N IY(d9kǿNSFixiUQ&&zͿ};x8c{ycZ][L @BٱZV}>\*7ǫ 9n'xg؍ih0`wͥU]DN޵G'=3N$ыJ71RLQe5,)Gh^sר\Y4 O/ ^<̒޸X1ei'dG 3oKt*X6Ź'#:p ޝϽ15ڀ}|~~vb1˭wǸ_%4+[lj_ײW~hqܬm8[ťUyF2*BN=<#'ptmvI|wda ZZa钍o&HȻK^]ep&3t;iroLQt`3y짪ee%{ǏdulxӔ>4Λ~Yok7~SH#+A8Y)D}+h$[Kt6k]<^u΁"swywֳ$,hs<;fsl?nNR}k|άI+PR;7eTiH^tu:2d{Y ˦~E;ƥNjJNF;Lo%ߋ~/v_mjo|ߚW._J+)- Dk)$ +k~WSe{+@BhCZڞԋ?(G盓q&$鰰u\lS' d6? Z 3& @Z_QsAj{g"c{ѽ{ YڝcE{0њ#K$O?o^><OT'eU7.1[L`v,֜EQ3hЬ=${M/|skiXPAW vW\ݗ˽a7|}G#s5҃[qoD|]0Q`w4{n5ޏ]e7K7H$ڶEꡌųTGV+TXG×x{2R@0Gba~k6uٰ0((-{ ^4"oyz\!ӗwO͊ԌNxvݬ=#,Y -V폿_fF$dA65ѠrӾ@ 4ouZ.Մo7qQ7iWHr%[|X/ty=uynܼA8n1@)ORi2uk`g +;|g|Sz4[o%wmӫO^>{WE-Fj`]MNCgh)8[?[^kz*0/^N2ljg$"@/[nA)7_2t4=$`"VV|r0;4P5K(O .ǂelW;}TW.حc N'iUb?7k߱7g?{uD߲oxga_+2k%CN;o\ÿP(ƍv/}ѤT728DGYg!/d~X;~yrd7N6R&Mm~Oh1L0E(;flzq.rry'.[W?޽Oϱ\}bl6ԍjϯONVw/vѴyђhwWa0?̗1Bc]?>N_H}-}wOW^}[_c/wW_7ߡc,%3A. Lŗ"+'u^~Q!|OZ%iD:*#ueѬ/ƥTyqyT ;9i7Ϳb_8b45 E݆A y_ }Zfk7|_?xשmC3b>޿tmN=(°Cze;ͤwu iTE-F %L{a䓓nΊo;ɪI AىZtUN}1ޤ'}WM+ǻ^3$ nF/w`1 S݁Eͩ&P#4eg}_vG\>Lb\9תqzQ&@2@`~g6FtWKYMWkA{2ɿ6 ܒdfHjیF[N/˛Ҹ~ٌW&>oiB^TmeG." 6-~^.-B|\?/vm7¾jpߣn2j 44K>}s3(]pZZ;2Ƿ7`HL-`4ùOEqؾwO2mF7o}S~{a-B{cNR5bp=s^Or<ސ\?'K5. WT m+o~&|:ߨt!}?E+qfhX6{IW7~xp;{;w?;y %a@QTlz9V/axR!EE񪎑O>;dcUC3P1h u3h;ʯiY贰ŋp].TIVdh6ͮ_gyٻtXw{OX-1jW~>!G5Y,C=;VEt!/ן dmZ_~6/{REj3FȬDXH8j^{?o]%mHLKGHٯ5W.x$!ኃ5D]J̰3 Up *-Fw`XlF|Ul̵`u. 4>;C; @RczhH6M_'O>V?z/ZM¢v=łï|/>2?ˠ4I 6l[o/ɷݼui nE|߈Ɉ 歡ahީ;_^^:lK``PCTEfl &{w=8PlGs兝?01ލ2' 7>R7Pjg;`MV/&w%.&U\r>B*@ZfXXDkwǕ:OONj3II6z7_;2 89DBD޾1 D]"j곆>;_2CaFNlj.'UhL, 3mn|rnDf0t'.}oR߮ႀŞod)z+\\.="DDf4m@br%ftٗKK42}QbƤ/Md.+:D`G-KH5a2mzh=y{h⒊@[fLA#lu 8){R>D!#jfuNʜGX 6\0#sסP:l2#9N!8]RJ'*Utņ Af. (O]F BU+`P vDMT1;hdozD̜DTDLp09PDd9'u5cE!q1c-}C+p]%P.E}Dۈ&G!4@h,"Y ղӞ+s Ȳ^7+HXSÀĎ)Oc. 9p$fG1 $1PQչB^32+h04ր B%$pyHc)+D(#У)o@EEJG-Zܾn+)gb_;cbej92H@**Z,;1UE@D.̣%Kڦl1s(f Kj * lAgDݦm+Xv0vb:k XC%FɆe= \d&""#>&W("cp\#bP;T2mO s!(ZRCQ3nhY`뜙vY IT' ha3DFdjdRy*!C4!QiH&Sm9!:;Pef4KTД9nSk}zj)kO2$ՖT!HYC-dJoٔ}'D` g1&_)X4n@ !bD!$.8]| moƈ0. dSDzd'uH@CSlPy 0!yWX66@Rs6V T9 HML@aI.n3`f[?SBJI0hrdRKY $YblMJ+8G(\-+0'u!dީP0Ѷɴ4!9d4hׅ920pf"Ab)f,nhAMUͲ(VF`ِUe%D(eSdt@&I"XV$Ɍ̚18f$WD%@ Ř,WqJ+s1gARo>*ABk"&lʖ],d9V& zeAz&&BGE 6;2{AFRUT3>h6!36O=B_ "59#++R4U#v QQ0D f UEVHY0)6u ',Mi^I"2[)o!3BUQU;0ݵN ;M-mC70pPeMI"#9-k"Hz#ЌtE"x/Еa,D)*bоX.*REbC%`hKRD3!!0Ct)sދi`bSF\A7Q- A1h5 AL5dQIT " ALYMcZ&v>f#c(>8̅Kh=n+0}tPkiֆ\M )oYn ̒92CL`F1֡K4)$Y]hH:R.[r#U!eȆd5jP,sbpU GHTIr#Bl2ljכ zTłs,U-fTI=6'M mHT2 djy;|fف$-t K$̚cAalDRFHLff:؃ }rjT_0$@ߟLD M킐8K#b,GbǁRO̕\ـ QעNP!+8ܣFp]7t3h{i *D˒>y]UfdYEfPDA !"HF`J-g}YTȈL@(j>_m H2{DscjĐ6hfj ȶ'@Ls"ECuv/y1.2u@8V6q&٧h[!YI,zLz#ekzi״1UWP]9f NPQg@@j"f,Yx IV歌`i+mRF%iO[TŮe.=1nMqB4D-eL"jȁj9rk*!P2u=;Gd&1,HN 2%W1˱8t};;F~8\̋߼ yfx}__运wyEͩAF@Q@29FDlCe"5C4 FmC:(T)uu?鷿c$HmϢYFL@/kWU@m5]3*Ρ=3/T4g ( yfDFlX$PA&TcS=⨃>e8ɋƏo}sb^Б7''wßvRl!mhk6VeɊHZnU١H((XRXalc8Y]-DR^_-c-: ("2 v%2:"AZ1#!PF$l2BDC3boMĶCj~,@%3XԀQM %.U"0![3ssxl[_`ŋU*'/߾̽`y<E(`ړ3834dQ 0aeҌȒ1$ZH _ã͠;^~sO>{~s]tHMQ^ObDJL2dc 뇱!#F0CE0Q2D"bl^T=_h<m##VЄjTE@$¥䰉ypm#wvշk7tֈ󔦇 ! n_?{͈2^x[.F P|O|D ^Tz nSca.^@y3#M)RPv ,D9o Ln&.rev˺u!6v-mcPD%A==>=Iq=}~~UJ+ 4Sdni/hg%*,h=."V}&ibd5=D1)y?ƿ3R4Q{t͖7ߚ؝\S7pДgzwNo=XY;8[Qfl#^u~ HjEYP-kT#>oYh>  |hGp0{yzzwRVN-fR3jjXûSd 颞=,:9F0[A Mfb_=̛<&EnaK m>|Jp| h )]odDH1+&-2 3K!"8'Qbaz<}^)f_}ժi/iouH6;@ƅЩBph<Nz8\a@-̿~ Z3$:LZͻr>NHVkSRr42^r+ِvIFzSwY MQp|U7~5X$fwWͺ~{4"7g_ӟ¾b Jb98(=*r4ܩQ9[/SYt{2,yԤs[ $jOXwwdT= <l`jv &̂{wF%{Qf&O^~|??>u0v,]]ф1!nrY2q-<-# e`fWv5A;lb^4?CLӖCO/^__}'t?b;%Gf{HeS!z2sڴ\fӯNVZGĄέzBtٽu>ɳM ΋4<=\?( H@LT5P7,˲b2zHzo}ٍ ߞS+7UTz0ѹEҟo~,mO=fzAlIc6}`qmN(ݍb,awv;h{q.]9ޮS|u},ƎM)%ܯovg7k>3USl2xh+Qk,<['`'oniWf,7yB@(ɡ""& 1hSѻQQ?d8[<*wdƏ/M逄l;o* B23 H!#x@TNW1Cڽt9rM =.5Kn?y{Yo7ag1/CҿP9}jaoM&prEF _o,dBcۋ/?‰6U\ʥ.&\-|l&!.osue+֭=|PΕ/h{PSoB}U5_u( 1S_1({dW.ڦ'7B@hY{WS|1Y԰s2~;SZѦa}pZ==͝bw'qF7oڷߞZ9~]7)vM^xyRy6OЍ7xр&Rɛ֫IrUW=mQ֖ԔN=ЗA w]y%pv\pp"Iٰ - ](4׾\PZfQ&:^av "54Eطx>o'}]NT1]%KN:"XxKq1q!/ڪQLuy%+D2`l(d_]kۥ/-8_w_;\28h>Voq^kHbTR0V8 ow_ʹx4r\"эw4U5W7سd@.`?t3iy9)V;e?T_q^NƗWM7k{}ko=n٠*sQ^=;[:7{1h'3jS_Ґs</Wi#^whyrUxY  J&&5aoy@M;W3z ]*\aaL\racAk9Un/'_ uqnځlzu0n!7uvv'Wq!EAVvxxot`_µc+\Leyv415.7g47 )Vlfx+bܚ}}+ߜޣC"ˊ6U+fn9ڽDFGQ4 `Y :>~'o4}5j_ΓzR8; 65nH?zՒB! = z55gi3C{@<12㖭ڬe^K%n,sY6U~8rݐEMFvx:G/ݰdiϚ)\f9ѕDi0%()aݐϫwz{/otlsJb>NOs K:z1WۓHzzs=gCեR9[)_/SJ.{"-%f8r=Z}7܏N])MwnK,7cҸ ٮ8;lnd6l\;NĹC0C<~Q/[ @`z2qۏ5GC27eTLPNg(1y6J7&!(c0)㈥p-b@ h9o6^6T9$>jFiW7?.W˼6 B_=a]f,nGP·⊫"~8Z%]φ82WyǠK};!K,4$__^o?/_zjabAC0ޜb?$pqG6/ji* ;@=#@lF)V\vgя;5_I1ch&X Àk6<ݿW'ʪҒDnGu2굈seoa4q|b:?nWIu+^=M7(ZWvfIȏtpprHck E(KVV6{on:tC`y2(bLцͤo2\Si4g hoJc~lU]l?:(rȡ(xr93dF4obDQn?屙3C`C>']Hir1 n|Bu3P4AΧyn袎'=VhO;:>VWsڿv͗iy;On40Ԧ0,V^ ˴,JG2gs=eCϢ#ffALN=~xbuMZ7=Q179 /6̎I2_9)aBW6-M7.<H]]ԾHDEYAjbz59~ݪ: S9\YPO \-$܎>_rop[,b}򼑻7vԷƾ㧦ӵWhXf9~1qݜR(o0jܼ̃jN4"t4J >MVMYԂ_j,u詾7gץݢCCWj.J GO~8_~no״ppnQ4VF ӻzxDžfUb%YAqw9W]-'B'IDATՃ.aVD\BfVeD5^6gsQ\,ŹMBui*_NԍL-v]*^]|vӚ1|'/wg2gXexiYkuzzy.<K}7Qp7|v:ի]="_ n_~o\ j[۾ZϠ's݌|ƴԽƪz7n\Ѫ]M= C_=ѱ:ry~Gqot) '/La,CΙj#F Tc~= ob~R|>~sgp\h:*]`)֣`z5z[gpO|^Lp{bɽDՆ'kv6?o|6<9Jm!`[Cvx<\᲼nœ݃S!7G8bUaP.hRWw<^Hw޹Ӿr`+><ƪ)t_==U30vޮ:܄\wg|+"$9~ν8Y6JNh5Ysn+B %`Ҽ1;"<*/Oý!Pwu8XGݢGaNAch]{rf:Uqxqac;.&Nf/?/yY Fo]-_ͪ -밧ZY}I\l|#ՠi,یb:< RC;>EIVRΑ!g_ VzΊQ~!:R̬Q'Mq@:z՛o>;>,?97pTM?\n7{[5Bc\$/,xeGxoˮ:T@Wӈ .ӃM^x~}~ލ֟ٹn~̥V'o~|~kjZP`ݦhG;j+mUϣ8N# anZۗ0(Ww'M.,T\:"`IT;4-o>׿8|YθIMwyԫgrYdk"k&WE_^x/ ,jq$n I6-z.`4yVraNuWe,NvgX¹ܻz-p L 0m6)ټ\;EBP1Kd7>IXWѪ/Ƈc:xft=])&uww^jw$" j3l|車C 3Eғ:_ʦ."8o7o}R-XG;~\7iSU%s xAc&qigBLhj/) 'RrHmvyOcI&8|xR0 "KŠ5 Ҫ?<EȬt4ac4퐓uYٷ^ ?x}7CvFj:Q W4;Wk  3z^m]9#P!&fuLD*<~o)&>_W]f?xetQ+oާҠC(ʄ߻=E%Mi{5<~w.jKQvIW(:(wtJ闋MYAy?l搖MӤ힯4zJ~O׽ "bf3p%3WQ  ZG U+K=~إ'urgBy @a9E%ߓ4I[udNviS!M<;OƮWLZTS򓍠$C/GIݽxXôm?j᠐ygg8P @}83Qѥ_MlO@MTCT >0'pE1tҵ0h&i 2rΖ>!h!-79ox<,bTSu+@JѨXlF؄6j]~]?۾×j={1 M{.emx~'Ivt)qΫ ~^ ݜ'WnX_Q)=n?Ĕp{^pZ|ܮ/^\i#2??{Wm=Y!:3&4B̪RDg|h7z%mƜܫAgEΌ8AEfMI\-o7y&1n6yQfCW[%÷i71}~oW5#pKg_<}ⲮnppnKW|[jQڻ3nڇ< e.VmZH{8n6œn"AFU,փ*zeË.W\ fnl66!4;v{o$W(}]uO2qi9LbrTA#޹ ?bf)>aA{d]ynP>}\ԛ.hy5=ZF8!p-ed12 : /\n R&&jJt jI3YQtEB|AzUiZ/W^{ƼjOoI9\ZFBɸnW%gofo֗u!&őhϠD.oCt1dn>*mX-*wÂroAq:r_I,AH{޺AV*^x3.?_Nuix~ Y]Ιz~;'w]OfM9ulk4=b!Rs_V'IV4ɠ-O/^{?X!SB>[7rVٳa kr9iӝulͣ tyչU#!5yOGҳX7W+]8ף6ŢR{jVd `^;՟j͞7i\?OIi'>n\ܸ-?9N9lpx#|p{6wG?[01vyzܰ~Pxziڧ٨mRizw?Xu_bĪ#~{T5'؏nТqޭ'bG|\΋U@Abŕ: 7Y-bT{bUER` AgZ=H| ΑBX;u,0<32u Հ8sq6k_{=݄[9[EW7Oǹ{2#ݹ7lF{U72뺯(N~P}j1 -滝o@'xM̈@;[5ț,+Oϥ!Tm%"cyr8 !"u_M+S0t3w>HpkjthXF}M|U`pQwC,8K`gAЄKMGKR@L{?9]qO}(lw!޸Zd@4)rȦ3X<ڃEOA[՝a|xXu<4v8h? q_q|1[hΪ&,(nv]( h4z۝~|KzT@B?2Cn#lwgFy}U }SrϚQqUrG#~ Z\븷He\Tϩ-"󬔢%CKu鋣I 7WsܿiiL֘tovu!z7V)88 ;Pv^;̢ĉWoG}i;r^Z˪ӐSG`"@dPXNo5!jIdO/^4,*_Ar1T)AAMڨ!@K#5/JϙG?֖8Sp>k_y=.zsg$oiî1Qj*`!EoKلM_%]kyANקVT!/ l@kP3qV5)_<~!W O>ܹ1l<7?8~,̥}EEQqǷ-" n n޳gD&@, Q,B~UݪP.7VӇ˂u- BJJhꝝ?/K-|ƃvCk˧OU.#(Hfyf!j 2sM[nޟ%dѡy(]0V$d[`97a^iܼ6 x'?'}CG$,jHXh[N>\&F6//#L 7;8c_jsYv~Ayw?NE6[ ׇٸғNRӼLD.&? 0O pLБi4 &`$72O{z ɌРr9V,8VIXz١'2TH5ƃO?cdBaLz ǣ[YSzREBbޖzqT%)_^}͝^V$س6ӱ#-~!e .,:?~A Q-aVkbbtuOIg )HuX^-VV>"hG؟ =:z$G߅h[t8;)C57Ԡ/~E%u,΁os1L}:ʳ8ʛwV}@|,Ƚ]!{p:zXZT~TP҃g~~=($&d jGA0.rg>ne]q#&7Fw}:lFζUwQ$2};q|ѕ]U:Mګ>_#m0\^:`i}ÓMO |4Xx!mddLT+^v zoٓ秏|VDy42Hr2F23hvVF@~CB=}:mv ULM2Wwj, 6 Z<:Ao#3SHKA~LXr21_8(ٓX+Z ݢܴP@)XUR?hڱb<,w4 ^TKOYF#-#"@0lԓ%_;띪=j=zަay [)Ԉ@ЬAjt{WZm6(֥"Y (:)//1~[oTÓqa6 Ր4ݻwCYtl,wgCקv D–ɀ9_~e攳uBp.6Q3ڒc.2oRAz5:lbFM+krs=6`e֫F*!v⤃Y,B=B5۽Q-iYF)Hiz  0[b2Z2 j&.oǮ)+@D9@l셭^z>AG,$Ue.GAhaPj#*dsQ /:&;k54W޹Syv$Ū f`(⇋=v di8Dq&H[֜=.5Ϯ&HۢPeUVBx{ ;2#ǐy fU D3eK s5#2mq_@ =NE7d-EU! $q} (,=1%x@[эRiVEp)E*$5 Zer gLM] f*]-9 ('9bӄ )8oRzHbRș ،`&~Z/- 舕4(u I` r-갍&190'Pu a{ P5oĴ)VfUf+ EBBDb63Tx`f#>=R{Ryf0TPX'#4bL'7K>R{K\YzFǮ-Tn+WH,(P,U ֒Yf0@d:B"Jf\^(^fPV<2ޛ}X^g~rӿhWܝMw0X2c<'92#wLDjK56̠1J F * 30_T-)F%[f5T1e}h Ykn Kf9jT!As8hzY5%#h2o)Dq<%^r|x{ݢͯÿ?]|9^Uyٴ~hyLk6jr!x>~oVUYת#AƂ@% Ƈ3i/uhs6%JP3|t7û@qܟ6\FɗbBn6xҜ; 4̑pʶ2Ƣi q bCo[@Ƥ:x޶ek?u=#zlgm߾43ǜ.g^rJVeNELgUɎ9lVgQkha2w:a l$2z`T:X#iZyb,y++`eQY>< 6dĚd,ߪ,rd]%7RYrgB\hfcjvꜻ]۾K[{vw[q].?TȜyVU4,!k<};5 U80)ЪeAk+,*c~jO -5C5 h~WhtsGp4+L mhzv"à**eT@U?ZoIENDB`scikit-image-0.9.3/skimage/data/color.png000066400000000000000000002471201223313777300202640ustar00rootroot00000000000000PNG  IHDRsr`NiCCPICC ProfilexWy8o?1>3,ƾed'; c2iKOQ)B) %[JQB"KC}>Ϲs_}^a8v /e!9fV_BDEgjX/ 6;$0 (H]H5`C7q#`6q7`ȡq/B`PcXPbQ#( O(i8YPoLY0D`  .O0 |ˮ{ ,r`^`l`h$~@39Ø`N\g`bȱŎQ53wp "4X8x$TL|tكr?PXtmkrʀ*]CFSKC;U\޺!̶Q)Sm N.˛|6v>;98vt{!u?1``o7ٙr4Y({95>6b !?nl oImOYzWH}sWs6Br̗8xXy.9-s-|Z1_a[KYY_Z-?~af0Ph&>4Y#ʶkl/w;OoqlD.!ga JTF_VUNeVa2QN[L(lz˫fbxhИDtY,Q2mݐcS؎Pw׈/m 5= %!vr55ޟ8sDH%K8hgo{wߑBc1i''ciN ,.u9kU[zNBJ*rղ.^*^#Z+rM` [\ \yqMw[[t8u`CåG揅?y{i3bDj/dV^ ż6ftHڨo''LM̿?{}"?ݝ?ڧ]./+-/}&6^mV??16ZcZDagggcx[]ƓǛGw r .gĘ+%%FQ2Wr{((*SZ|H%NuA\McMsZ_Mn^~h61xd1 *JZ~ ͪ{ UNι.I;B]=܍(/wNҿ73%|r>87fCU`XꏾSK}WlR\XSIzt@*:u9힧2dߛ/dsv6.Y;0d}y]͇.(9WqvrI"bŞ>3T[zղc+\ UzUh[mtI2\rjq unrkй8\z'.xoK+sd[g{UGV'*zJ?xx*̠Ϸ?yɋ^? mmɽؙ.x?tsrJ7 (p(PUpQȕl@, ~VIPSpHȁpvDCB( 0+ SS?ZMAס癿b\0Y,$6VilluYs^\,\\Xgl 2w1 O,8 o 2_1?3<@ ALJ}z+#LdH61]fq >Ioi)/-)}SVf\6UN@n˖%"I|%'-UTՄs VѢeͤݡ'_040IiY9btv{_`'~u=nwO.Cr2Y\nύ)}4z m624>MR9wX`Ա'?מN/q<_6~|a%%+W.\wc~aqglS{Lgƃ枱',O }Ϗļ&獎Hx v9VbצY`l$Ata/Nx!&HR P6C&6&g"q2:,܌b.%\.ll>wspTpq\ zuƶsp_9{'_?\`+A'G8k\Pm-ZQ kbb& Rix6|V699I-[V3mMR+wĪJTRR"ihlh6hEkiuO<6l0qIiYvm][;c{kG_dUnk^Q>žOw֓&l8),r,Z<&V{!V3.9~"63$e:MwONLI9:o{h''Z9P]X>[qBbY5wW֜Ptm&;-ƭN]=6?]{EGN|11Wxyuo/@  * BDb*d %@Ƙщf}r ;&32:ƶm=}ʱșܭ<;xy ;  _ ;,n#HIKY.#2;eeW:P *?+=zQy:4GFHkv6= }=cC3#m^$',.oZvX XA ػ;:uwށqv p/B}2|w94.))PHjs:=\*:#')Q$)1yvZY:&#,ollN=j=qR3b%g·W TuWg^ֽ2WSyRtc!ѾYR"t_~$X/i~O_ ѳcco&Mޙ^y'0G9yOKKԮR,yǾ^Џэҟ Ę:ށhEENj;@_,`*:X+_X?jm\@M s,B'ٹ™ёN@S-~^ǻzRc PpoU P0&%@Kb bT2Ёр2Ё $$C$Pa7( !!` $C(/ S@bQ7Bc =W ?mG1dTFˣ5:h 1mx4- hm>m6B ݞS@UBtH`:DP:$u=5U\pR1Li`<1&LWFT{Lb)F IDATxG#P;)̾LԺ?#E]HD[~if0<-e p.0M`/^=/8 Ïa'XMs7 777,ݼotb~D|Z>,2RsXlёiᆼiˁFG?vMWǃc[O'|N=cwisDvhL[p9[[>nt7?m-Η=q~x~_^~`a;TlT'1c>ÐiXQ!q+=~,nqssŋڏyխ_x͕P4?:'Ye/01XHq&k[n?]nC)cVg,P._lI|P(d =%J+>!Y.c|  O!c+9⟕t2?8q(R~b,znIY~K;S7r|2ADŽŎG7>jgmMliO]0h_?ǧ<],2U9pm9ۭ<匘P8P##Mvi˜`rUڢ;nqxĽc=iry"oKY>4~4>;GfdA77h(LnM4_mqdMoٰ%abN[ r,,+y_>Dc3#DB9P&Aĭ\g4sLuj+#}eJHg'vim7mBFЭ YOY$ |%~O)GXo-1~&G?G qڲ[$4)s-k?xWcxn @-ڍҍS;> tKŐ5DvM_?,^:!7JOwI[) to㻇?-?sy"/[ x+]0F#/,reS(X.U[M^VFw? g!>c3;(KNv!w>7֤\`E 8b'tHH"W7o|+Y~ w/q]4F^sr)7VP[n:n胲lG4bu{'v8 PV}9P(O}py"ˣx{Lk1-(7#dEV/kҏS>` )^P9ˁ,,bkyofK5qP*G!ē6>\_]rcqw\O>gG͂֓qZ@$L폒-Xy;Z%vDnsܮe#K*]]Vm'H99UOk>hr3?uyr (3In,Od9./pǘJgʙ/&=b)C9갍7Fҏnh5%Gz6yv#=Eqx_,) 1Ś?O˾<{wx>%R ;d%[dpzΈA)7Yܲ1ԁv0.[չţ'gvu=k9ˣݚ ^@V}{IuJG *7޹ے߾K-? |x#MlNPk]Kpv`@;t6{|>߯bW+\,N`AᱳM@32[ SP/eCQ]H%!@qr1r O Detu3`]eL/a Kv0!I"E"ö~\1>«;ÿ~~EߟpK5c6; w L͌AdXm]vUX{[5cҁ)hj\dmec.U p4Yh1]RA˓HxѴOZźSB%*`s} /]9oΟvy7x>#iWZh2fLJ\(Ǎs:+1GKm#dH5EB\V`Z"8&whB;I#ΆePW7M6\l׾ҕ ۷ű늗"Y._3{d+k#~\`F~ߡ KE}c aYJXQs\_d镖3SI9[^)ኯx.oөkC}Np%r(sGH=* F9OWlā}1GS9[=BqU*A+m4Gk߿  mS82 t\Ym M:g3at+я8lGO#1gq|@EPp(rc2<ش+[܁,'l-v n^0ѯ~7-'/߽?s ;f|rϖ4YZY; |jEiW/߷Q.¢_>)/H#{:Jdi)  Dr\Z;.l*| Tn2¯|C5{\퟼&g,-=|ք2޶j{ Ia=IJh~w׷c3Guj7lf /S屶[>8Vonen˓SE+qIR\~|?ϩY/^~ioZ9wLmq5XE0'W(@S[JюM8C$Hw\J,/Rpq&0N<)h(z- ƞ;XBR2ÿd̎p w։6"9UiCx9`8OH5WeA*C9$/\Pfv}"2wEa-*:kc:2:\5b6FmI7dU=go;x!# 2,HFTıVH o/VSm9rWnbG'DyO|__o5?YJPn2]G۸2)[ \!As86l+\ؚVZpQwvoZ)p.;C&InL寄j"_KwOV$s&bÅBtru̱#Qz|b.kلE@ZPvO%3qz2zeW.'>DXAAM.BL>z~룋sޤ݀[W!߅-mGÇvpߺu#aщGtPkY]: | _AV%[*$OJqƷ?gIb|@9@tq\[BG<3`>]P|[䃚 \@Z6%5Qӛ\RE-p U20<ǃQ>ꪱV4K`H*h jcL5ծ12>zNhW>bA?@^ߵ`Ec @ikq/̰-b +P72.;W~p\-[ȑމbtJ2zsǻr{y!ߣ՞a-9ʙȋH(gPrr&):Fk?yp!~],}LϝӪ$T[lRn*UXJ,@w*aQX;OolGIJ'7-=C'e7 (*P9(bS)QanF4#PT< `{< w_TE CdHG?XG|}$Vl>V IB4=,<ƎS1<7Z~XÃy=t{hhC/A!o-+8WS=BOg9!a*} J|P{E ðxw|ǷsgL$Mق҉kطiLHaK ejź!7xUK '#ybYG Ytx%*Όey%"H]nJO{2RYtʾbo*O yѕKr}\Pn`q ^]8*ȜBf wϕ,ɖ(sQa% qtP=I$kr[YK2[jE0"].Y,ƣӱ(| }:Vy0`|'|fJ>)1\w|T#XiJQKh%b1M%η3ߊY#6IȘW껟z?$V޺rXߙ,-ء 1՞`(c)/T jZ΃Zz2#Ja A+!ձ"GV8qW{7)[$50EwY|qj*< s羔 ѳ)/x{wPfpX+]2+A'C2I'>)Sij )gX7E }*p9AG$r0z(uAp%RZ)d$f69ӺWt @?UZRGsێL#YlgYeT3,?2>J<+{ߊ$ `#i"#S @qD3MK< d9l_>'qK)v4%>6+4Pj=ew\dMP[>U:#!CCE.ƴCh&t5@35ٵPߞ-ͼAaJ*`2@AjXśr͔ڧ8rqE2aP :WaS%_d0HCf3̉90l206Y$,nqOӱc5PD,%9ڐf8JJ4V+"d✀R4$0'f{p};*TgC?Emv/CCܒ1UWH(?>8B"*9- vX?^l3:b5#zM7Y`zDžlN[E ojtFZ^To <#;lsqƽl䓫Wh's)Ltok!/`uVUպZa&/cJi} ɹn)l+Ea9|uI-c-@ /Ne lۡ-E[l [` `Qc"ێdKOpő ]pCW(x."Mkz+di ,-Jtkq&@|/Zq/CN8;r.X\&BDVTwVkI GԕCmÌ.Y*63b|<%ߠz)΂k῿Osb/1<&[v?SF=&AM(dD] }; +xZ|ɼv4ڦVpR+=ĭx&V0*aTKItEMpbGo[ѼLOF0YqEQ wϧQek04耾iHgt@Wcmϑ3|St?]?NG5hJCB z۳14,@APe+ZUDl*KSx$/HFjvMGS?*(UɛM@alsU1 P@I|aWriB1.O1 O^3?i[*b| |I]. [9?T`q՘o-"a{|*O,w YnVPt eGTxIvP8!F,75FIHPū$5 e1qdiP"blE7G;hr9tگŗ)8CeEfk(P)7ޚ4AT"q+uP}R.X%;H<@F kVBs: YQa|*O,_3F.~[ ul5S"+ASq^[Qn5pjpAS'lJH,Oϝ=,پV^6n"%$2T.\  q5O(e!%O W>Et-DP]=}Ěq+p-*Bג,Vc# : E-޶<× S$;ǝR,u|P1}}SeT,-Uڭs0\_Ě,Cfm11ѰbuVcHNGh]z_t)IN&n5sAlpw鈾(P2*1(>eAZfP¼лZZ-+|i  ^yʡ*"LtӃH"!KZc .d䛂 E)mPpYQQw\ ċ"[=9do$kI=|sd`~-dA~Sh#cLJZT衾GCO.) V vl]vJ`=V6VW$Nź7oHj(v$*aToJZH^6*Gܪ|{{A3$d[-Mu[GT!$ Z+߾bwxsqiCM}P\Apqg\ B,i +wMꂋIמEc3 G-q fIģ!?MΈ/:B~mp/enջY;2)sjPK|J9rg!-p*:$v΂Eyޔ6aB`J(ݾ[6dgCf.mDb&XXƖ _9B n&$PVuKyc}?,o96 Ś[R`=:»iyn1x؎AEs$QT?j /JU\`K'9 +oU i$i{V)TDHԿ=jV塒bF c:Ɉ:pS1qMuH9#Jn.#Yda{Hx˓n1pɰlg+ UJ n byDWĄkJ|zqں96Ki.a69#aP7r]R4;[άUIx)q/oQpk*`9KmK2Hoh;z/%Z# k6(:\g$2:ŭ( bXB0r{yʬ S!/K?laؚq uhjfIb [S*dyW,AReni`d/K91_Uwh CH`rAR]/մf|uF~m煉p4v>l& ҇Jn2aز3K') F`]w( :N"t4ZjL3tXKNˁƧL"_hFɀ*[LYTwyiM7x2SgpG֊нZϕp"1' ŔqibКk u[IdK/E+XP]j"_izV2MӄO kLXRkj9V%!:1 (qr)z;;.f&SBׅ;QqZZt56ZPS,Yvk/?)3%޿%w%% JUI S7r;ĬnpE;~k/A@LK^`¹ZBR'SQFEۘsP 6w, V"%.p3AtO/%\z'lQ!fAT:9 &. ĘlK1|9pҗqQ$wV{s2.UKv6< ߒBq诽VRČ2D MǗG쿷Ndyg')MHP"4`wMζ{Jl0Y`4>%:7M_Wr48x.JoepdvpbjE'GAĩhjaT&&ưw| ucr9ٳ%7/Dτ#KQjJ ګι۠YI.=]“x9?Cd[fYPe(4[]ubz^A>e.Vb7#- U'$Aw0FFGZ8'4ǷƜtF? =5|iu$M2h6/]/VYcJE-s6! ق[Ck}^>z)#;KM.+9VZM ˱2I`sՈ2n:bx{ ^]ʶXovB+sZN(҄ɠXX Yf6QZf?[iyVo> ޕ G'jpO xZ N*=Ftp,)Py8ɀiq}KڶxE{(R,%-%}!Um?Hk<Å˷bY4.4ǵ$BY$x>[9P22.?!fѣɋY@++eMΜ/ÇGX~sx :F4鸱uNS+[%B,q8U+ .,2`"D@_ɨ[Sl4 M%h7('R(XŚk|Z j3Z CRKV,17"_ۨ RiYtёO^f5sTHE0>" l7ԊkAkPLbuʥY;)2'> ^ķߖ,{7dVxkE->6Ak=4=s8%kcjO^z"0d`2}P )德l{(BٟYБ%oAs:`iSmKehd]|^ V+v}P}PνBS[P2$Zj iB )3.Iպ 鸮d3U ztm-N&,sk+ye VA:)w\lHp-qS+P˘9|^4.^]-Ӥ``5Ӷg֛N 1j)Lem; pt Sp݃ptv \ ė]C2'6.{̲h%U `^n<0۷xi~+ѡb 8hAա~0M%v8TqaWG(^-| u 4IpA΍`-q@ >`]}4SB%%'$Q?-7W <ŏ&I> D1<ߚI /$`jUBfYfx囲 `/de2ĞŞE͸0O7iɹ悱іcUф굀hi(N2DʃEo75>5{x?~sM @xkZRG \đ.jEꮧC;}fly{:qꐦ0йu,2cX/éE-R}\nQR&~ؙ$Y/pF%qL[Oϲt6Zh)(I:RȘrndĝe󢃿lQ(N2|јC 79n/"?s6[ ] }Sax zX'w5cb?tt<Njse`+!X=D_ktc= al'u*"0GkG%&HJDUPelβBV]fbufdqny7dزIL,/l]N%1>Φ8YIKk}rb(s\~!~`S[>Va)ۅX2o[jdn`J%\qkmx쏯lR^oǏ?X5^OYǧQ b;w9Z!KƼk0\bcu.zvs'5 \*)qCL6\"QEFmc֡m1{j-|t`193EHi-ד/1n!d1`tO.TQBf<$'.}$(֢b])" WVjA< *6{ T+zkt4ZL=Դ"cED7DNcx]+_{qPtL~ؿ9/_NƗV$ (IaYIՏ${0pm{cko\$=TYS?x!w@-@!11R\*]s!}\#Nłp{ȈpHk?0SւČ2CILnw2}}pchS׸n׸zaՊ @ 1J@1ͩ_vt+p7ΝLvDh&+ rGBlK0iv4*,)%#G,␞Rށfz|R+@iE5ةgi#9"!@p)ID-ZzI@OzvA?EƚM a-< [a1NWA_$3ޔ\B։$s_hAq(. o3G Q6qO ˆJ?Nl.sW?g9&*J,\ ko'`W َK]_~?& >&Y^]xP.=>27Naf|EeY}fU?+#U>&>vrٳS<1YvnefcP-,-ޞPqfA{ cYr/R%a5{UL<lp9/ڐ=ߵ'cqC׶ Vzbx`\v!GFWv%D.e`P"PXêIa,l,:),^ZܐChG˔rF7 Cv)c%,}نK? d+Ƅr&|w9֙s ,93ݙjrYI1Dn+Sפ01N ,7ᇏ6 U &_2yAn4 (!CGQHɘ2Mp= 5220--|B*lTjEp=֪ȑy""cOuLA,N I0.|&Nn>!&!gl:f7ߨ|X/8ޅL-#0͍SipX%W/@@&̬କR#j1%bZuJoKLEa5c0U$*8 w |LnaH) ^ͪlk~&x_\4%h›O1Fe6}|s@ IDATH5ږB49q dfjoEz >>Ya)ף-SU.g"gTyضwHˉHFc n(ŋLJ%OWlG>H/ GQ|#Z9G{e1hY!v\6Xˈzh1~R(r{mȑ!NAB`,k@$΢r߽8],B!]EK%-U+ZRqsET7;q6ӎe4J=$pXKaL27M\xk <2dT+psކ䕬1re,t]3%z(Šq x䆘^xʓ!ʾX:Z[d[KfIiXf uV Rv qJp}v#[4Jn\-O! 0WJ3d!̓#C]x+9뚆WȲr] Ϟ3ohwtm9EfBEjUD-)W bAͅo*Z{'$r:cλ 1wV3nfnQ`6 nDF-d(Ib:_`l݀b #I6jdl+?2d"a|23 KXTP̆O[~xQn#SјmŖ&e`-V-0QZvWgPFI0.%LJex1*Đ%|UYYl n %LYL[K(} AX8Xb:>f%P4s&^ZQ Ux1ov86T>u@gyrP%Q\ȕ۳)% m+lu8Mܐd3)F≋)Ml9O7,L 14ncYՏ\cYzdY2;~:5`  V뮣7˅gvb|aũh&5ې* ~*Mmf40 ~V%KB6tL&DjEg6KeǜVԧ2/ (D6xYVd n+f{ pッfIFVhFvFȤY4) 3~'P /^dy\PN‘DRw`\X 4qLk1j~m,@%cȢ ƌ9BHFWںlz^ 0DsW.T&rs_ߞ+"+:*Bˏ F"^4W5Aʀ8P*^9D-vЃEp-E }ARDr`GC+yk7\k#e(sQ_u>JDz`cu"co˨~T42X7q,+Gi00ݯ>(SqTt{%Af9sx7%3xӮaf+̸>H"#Ty5r{, a q-D:V2br]4XhDuP΋wi62Pd'  3;޼wTdye(M)#(Rf5`e8V>==l<QèCpVKa67wWc_`2 8l3s+sq{DF٢ E bV!np0-[#6\̢o3 #S tmCL7A0iG!ߜGe/3GQ% Pf'CH-څѱ#@7nM{'Kcb񠸭$*xIBAZZiaN<~ld1+>$&MXnH^i6V36)R`S%Qi|5Pߚp>vKP5ATKD3\.zh(j!p{o6,K$JrDbkePBVАFcc>X*tt0̍"1q @f.YcpkXɮ'D( Q)|!ŋ u\ȫ Xj%@R%YәOvY~^o fUlQPJK_w4pDy(JAм~ldy`s@)|Wg,Iؒ, q&m84Ӷ!Gc]#h*ܛg)Cl|s&UdhֱC\l\|<2}Тl˲kuV O,ё05 D ]5( %567TVzhij%iRIm0c# sa Fdb/lWAX4,p& .`5 uyI+4pTo¼/ ӷМYDi~<`1pwWM+"{mŷh b_}9*Y$57ģU,Ճaΐ jtb8nz-$YN.!!_M_.-' 7KQl:VO\?Xk2˳p`!J"Y ZoƄ@Y29z0\>(2GtCX~pkxG?c@{oྴ*A 0W pόsnrR%1LI> kk̃jc>l uQvU#;8=uUdyW ]z$eRXsnasuMKU/ 5\̛Qf|հ2w1b.dMmCfp{W3cb 6;r qYI>hd_g{ fKWm499hb (Dl.PfZ̳%7s\"=p  nɚVlfߺ8(X|aD2GYTL-\!.j%g_Sn`vi[M(5v1 ;W xsTtΨ&+_ e# |'5dyԕ]uG4.pІ;7=hT=`r'I)dZvsp*UϤ ,ʌ6V2`q <3ĸ "4T˘ CrXџ8` f v4>X\-FlyF!+7hTRZDpJXɓ-(1FpKĥf13erCLXwD/lfڜ] e@2Zx;|%[phj=^(n!se!9Y~,h4㛒*8F*Uy՟H ئ\(^޾]QB8&jʺ*0)i^x^!/Tw%Rx4@]]Rph~)QXITx;hPIs@[+&xq zP%z۟n@pPa%ֳ_--qh-7TimQ/\ \-q^87vCK`hVt`rCcuPs$a>ִ5yhl#V(Lbw"gN'h}0J`ůt=((/F*)y.SZ!FF6:+_zQӊRnK,/AJ*;TmS,J^ fa`'K쯷*LQJJŗ_ws@?eR@*QI&NLI.BG”Atu:k medrP15儛{z@ݥJE 0\hFSw|LBʬ~{5/:|\mܹ=؈r'z`m(ک3pBD])e~J9Fmr, e ^i5'mrLT& /J 2޺'[T%gXA~lqJ \NI_ %PðE,@֒bBߪ=7i>BLWFw#ひmL \v\B (R{HeWViBUx3BVC%XBC@=2־# Qp8T1uńշ+Abe+6/#ca,ك ^-0RJ~ꂱ9Ԇk@oT`/GZONM7~Y5IE تYr!{0jGJ*NYrj.6oF/vy!R{P؋A.M+]9R3]:!1HgXbqE3'pavqY RGx9(^(@_[젋TePZsF:Dc.lC66Ŀ,yDdKs k*R+V*&ˢ4pXs~LRBd$/FURA2!ا"+߀eݿw 3lh J:Y 3Z'lhdctuubf"74sx7rhh[^Ŀ1P,x :J6`|xPlqPnh YuƘĠY7e,I19ا1۸ MϨp[63+LnijbP/gQʕD]޻3dA}hJuږ222λw} $FNҔ dq'+m1cyp*BlAtǃDJ,}ƈ,ΜH' ^6Aahf\97o-0+]s YM=5Ar{_F^~fǭqXf6’);LZ*;Vb0$g #| ~$~jv˖lQ,pfw.\n)U^mrI(@욟u]=eER)t\K΀'Sgp`C$) @ _dY:nHyWHJAQӚsĉ ଒Ŋ&]F#1jAT+9*$~Ҥ&U0E%[rF<(ʅf`<:&[ԒCPVeZ|ëՕ1ƹB&,Q ԏ}LIm|bʀ_3& c2a_vs`[_,wr@J6+tڳP/Tᙇ|"CW^JaKIbm9u ۴Hp Nx)aYiY.2Fg C`dZVʕ\`(1ʹ kĔI\G&"Č,sBT2GlQ*$eab.3NG TJԶ"9{ĬD(-fv,w8敓W^:@4_}IFƑH}`s K\M@џ0.,+3 ږ*'K/N}Nj4dHվ#f_dIcU?Eʹ|WbMgsʦ\ث2l\0l\ĸf2#(E_s,=,-Vs;Bѷ UKvǹ ׷7$W(jYF\T% 2;YZnm&pꬌ JbHn=hW0Zb-S"h=ȁ Jok5(lH,,E}RpK)g0>_'|^7HdnW(]tsV|ca-D@CiIUj{0mX8/A,j4G5. =2(jZX`bbҖՔ[?J@-X|Ιd@Pć[FGao15qbIŌc8Q9eӊ$bXX[(^2yq>І| VCЛ$zGiĺ9Q3p`Y7"Ղߍ*5x5S ۡ`Ԥǹ޼ɜZǮCk;^Hdn4p~OwMWS9`."%2`*GQdxML1 {m$44t[6۸&(Ӽ%Gl()>>@76|f°#.671 _0lRb\ {֌8 ߇TjQD:_+8'~5"Ƞof1% qnh\#%,䧭86F- ,sȂG {aD?Mnv4tğZie.v:>8qaQb đƗw:S̚xjHwFlr 3H57߹=؜>lM:]TY968I$bCkFOBI,l,l,,&S# 9p1$X fc0wFYVRyS|D j3G'+hXŏuoZkv ÅjcDž[.k0)l2%~m_^VEh1:2yzy",Ù5vb6Y 6s b#z *u[?$_PSZ $s0ohءlОfhkj N21{Y6!'2Jz΃%[ĕ簵׆zi¦@LX,2[͍BN )E3t3?NWn$jd(!42a ³?NylA+'mǙTvwgL;Rduمe)F8d.[FClÂi)vo:?f˿A?if%Pዪ1~ 2׃8H D3/&+C5]tRX2t-kljNt.5&4C8H L-UIJ\x-t|݈x4e%d֌*ՏȞQy4n*_0eࣄ#yȋc[| OY,,倒O(3@_Q 6(^5,ȉ)vsJ+P <(aTs҂E5Z~?WM+f1<+CdM \Af@y@ݽGt(`)ĎUs&ސDgu& "R8b rI8\g{bMDg>iWVj6&aE\!Zsk[lK+VnW蒪 䍨wg, Xڍ%G)J^3ROZyuq U`|  +ɢLLGty:QIu:SِBDOҪzĭ]a%ˬ4W-= IZ:"/Yi+kA2|P2S3w$=U]!)3e3YAx+hO=|oj`#O9hK<6etlq-@eiĂ &:TDL8Bȹ +"* '\ݟQV],z]" l>{Ў_Jr/N@ YAx (L<)Smw ǶgرG1if(T..){#Ũ<` /y`5V` !*THNˠA|a<#t))[e0諆6 M&n<ŷ/zF55TI_-e-_\ĉD"[ͽmƜ@?% !6ܞ?qu #9I8\pDj2eU{_'䜈ĹX{ڔ=lqDL*sYU I\((㎒kk~Bd`ghCE_MdLS` AqqRo4}!J;#6|s@6R~~P* J?s/ = q\y&vrg =Ol8(D|8십\sd9$[fBmӈ#FdfUSgF_v) M7 b3h gY Buע. +@4MYY+;NT-  @瀠%gB͸):G )u949Јt hS(/ e/y~]4gd .dTKůNg&@{<joB u)ڂK"s y5/V*l%m |3]jjbw 4.(*5 Mm$(k7qD^pӔ4Љ_;RQ!8Yq优hUg`֒gj.ZW8CE\, @\_ V =v9̵E$}Nxp{?a媹)=&8eօ1&W"|`E8j=d?hF09,Kiz! .٥s Bx[х/XjkKQ`P''țjF eqo./@iLǪp+VoL[e wL"1D DΑcr}LT>n."˷$o2RGCZf䰍e> =~px eUIJgtvJuFY-FcXf/ͱɭ;X5U1`$xsKA+QO@DШ0*/`o40{tmUQH\ktbC!)bqx :)t ?8-cZ05D`5;t)uT̽G7T^o[^ 7d0Գ-B!g ;` )+9WrJ~BϱNb ft\Wcts.T 4 ILpێ>X + \6(V*֜UЉ Ww&iiΦP2 z+oNHPFߞIwwE$5$jr8Hd^ p5YDĺq'a;+LYm Y7ќQE3t&\I/aa No!?@k4T s?DY9D!{ғ0+4@Q`Z X 8-<%ZB܊UNS[]' *ʒLGw 9D߱Pk#XSVd7N9(-4akg2nLZqXĹ&&z\#:+Q^[Lɫ+lW %dtBXWt\h@Nų$0+XU鍕kX${ /8'0[n 2np]lhp 0<:O럿, >U'%yÀC 2J1}`e27DL_H6G*n9Ϋg7A/Z1?V1-/2CveXj/:)عEiHXbۯl,^1uVSn ȼc-WPAǹF `: :Wjh'"Zk{p1MNO$&꼙F`$~1@b?a|"52?(B/i_뛧8 p\N"ȁVpyFqeU2GŦp&WlEsUFpaHP11" 4\&P;yki rf6(K;`A\@[y塳+i:2yJjJp`LОQ?C I@MP(?%{i{il;s6as.]wyj.⤭IIɺedSrP Xk*_"_ : egpG֮TzC Ch_ywMLRiȕpj?4%$2 *]QLh%6CDUH;=NVՖ "`C . .ɇʑ{f[YF8~c{UpS١P2/ 3.q!1* 笤_##Q#0f7]If DFcJ S"ZX7M=-muup4r]B g.*SG;aYҊ (?b0Dh% "dSMdrLH 5}&@ywp< G iPGv::dmaqʕuAbJ[dѢq;5&j(sRҬDXs4jɳnkv2a$%8ɋ,P!ƈ&)sg5LyC^+ Ju~lr me΅9M6 Оu(" ԣ_eі;K59*AEpKt~>=TTCnQr"HvТQٙff,|ƞSi+'݌, x<< $]|SW=5zQƩ@oJ-V\*|F;*Àj[K NY$,Z|'@u@EAW urXTArd+DU(=*%2'Ad/:k-+)-:'l\ŌF=*3.wCIr8r6?DreGH{Z9G6jկe<&W-"22~HuGk`Ťk-v$V=ڳJfu', Š5%2@'h `Ղ%O[7!\gPA6ɑl}:eZi+ ]LGieMe;3y@RQZuD5Ɯ9'p@ڇSu.u%G.SeZBdYlCjL0Ɠ'e7xI$_~ L؝2=\ԝ梩Pn * ݵsWE'EK-LɡrpQk!7# Dy aL:+bRiafv؊+J~<[*!ޫDr8B#JeJ߇ ݍ=ytP[T"ԒJTn%n]UF'ڄN珉9|4"V<$ <R?~FBF%QSI? (:=Yn>ꁚ*:#dF`tXt UdFǞ3c>j!"DM;2V\KQgj8H̛|Q!4A^IId4#I[N'/c&': D֥h U~bj=hvl` V ;IQ$1S1T3%qrNwV(IBƑ얱?rVzoQ諏 zPy.(=Bv(~DN}}BL"z|slcRhŘIm@)נ$I< &Pt7$1c묩>7ԀGIm@_HSU͛/9 qiHVWj,^e\-l95*AVTbmjzJIQЩzWh)"ŸA]%(߆śy1$$OQt싕AU3e5P2v>\?XJrOG8jD|"t IDATD{s2F{. 1ɋVMhG b%O0ͻ5iK 㿿岁A4g]n{bH!D-7xaO?OJ#%R᱿\|"p:-ZF7p)E M;ptp6zd*j H=i6 ul9`ťBjͰQEw[ԎҊ7I.zx$MºFA)j4ݢ$U22 & t̜P J#0@ Hh'"B`v"KA txvXAc 2qyo@B3\%0`&,BO$Ll!wnj[쯌CLIgL!%M7V͐ALJ!dѐ;ۏzAO9Muy=#@Rݡ(IO]!2MgL_ e8m&0U O !^3 Y(P;8RޭŽ}\@&)Q=LLhX i(YLaML z5CՆ¯uzr+\J*t- J n9lN"dvP&mA-lY}@@1ჸ.%um X Π>ZYZ^=[OҸ9TIIO !*( b"[g1 Cdʤ< Q;SL'\%0(IA ZI|8QCؤ рk_,_-m+z *^Z@#m<6pHŘ4:Eb#[MwDDfM R RJP@B{`)(hq7V "z2f,ubyq@E..f͙ҀB\&J9vyϿ%Yss|C#ZGkglʴk/P7aٽصq@5HF (AG:k6J05G7e' }z0TLG6JA(y mP;+1#ꗟeȂ6>ݜ|?;3\)Jr2[P}$ZF׀] `<"2We gDhK WʋY=TQ֑Z<5SVD>v " H bvг=6s`+8BEZ*Ŷ:Rf(ᶾ.6L.,97 LYvʻYJv*'JpnΈBlL[`Lp"Qd\ 6*VM_$Oid:1ye`4P2 a hܦ84O|aDo&6a԰e‹<vlOi#DRH<#2& |CT #LdԸ*, < 0d#P4٢G51)yk&EV Ktf-{&= *7րd(õi'EQ >#h}ʼ;C+Os$hM 5ڄa x@'"埨št${Y͚h:_hWH`/p5I4ީn:T+zp%T{l̢+T̍* %4w,f29o [`1OhAwY^ .![r1f=#;8BEX̾eNҰFG 奾ܹ(4م)D3+".kЖgOd#2PHBvhʋIG!B =!F >&VJdƺs@- 2֝vfڋ* wbn38Z[[>=`O>p$@(vvph ‡GP(SU܀ުJگ$Z_@! C·/US6>B<*?u6޳BA: .QWd?|G͕y7?o69{T2M˃ytY@הbaE}EUSɕHWBHɰ´ lLkm# Mܥҫ^91tU4 jJaib^:k}aw.li.%eIQ›}pkg[d'=I 4Pvoƞm2n %ݵ[y[jL,>Ν;F:EIV/Nd-EU7$"EϗPҏ¹A#ZU%/~HP>yM*4i'( M":UIUf"(@*HQ`FRE7DEy:*I?rM(Z`Ap1BA.9Qzn W`5Z'P#z5)@"RH.''$4 M$+E<*?"ѤpUQ[n3-ICSrG4{^|qü*l~wwMSzpQmv8c:CiԒӍfe>\f+#TW`qctoi%o,AhPHNt]?~*60TgF kȒ@U a#Ɣ 3kw 2*&9(O-w"X(XPibw3ϺZyCwCpo)I1Y[z˄ ' ,j=7Dps2:D,HR&mYC͖={(<2nuPc2,$MI.^ Zm]FAhZI@{:.#Orb~AF@8c@A%]LSOd=p!\ !"*X[z-|1q0,?rf!Alݿ.ǝ/c8ޑӟOI}dywGA˚ Dǀ .ez.ƏFDq*2J[!dlqh)?MZ@괺N6dKlS2,ivuaTrYP]e5wʏNrD~r@ś{b 4g=f5%n0 tMZlraWV'#*aT1ցuM;Љ/QOpbtoռ7455>&%V;!e`&g/|ًKXɨq7Y= NA]z21^d4uԲ|\s8<YN/Sҙ2 l@V6 @35~P7PJg^ܙanT_Pظ*ՠG۠zPԹ_= htOh#> >c"g!@^w!%]4S`jKI(dvT#y,q8+f~$IF|`BlK^3l0wxįH1ݨ˺F/{,Lò\/g/AB"X£2 !e+.g4"-(\ NO)d:JD: WfD{=׾Dv#ض:mH2M:@ :\e)DqZuVYo'#,0ӕZWF΀pRgo@]l 'Ԣ3~> \-|vN.u6oCd:8TexΡ$9D G/XX%\!ZOt+뽝 Ap?cu;+ M #;X+6Ђ$8^+Q"`Kyw/Xk].1$m|"y=@r:VlxaܟL/ 8ѤQ1ӈ@OjB7u:i~xNljCU' 9^I̳J;&4(n{ȬϛP>{C'Q,kMO >{40O@VgZ5,6^E;!)i˦elk"_ƗZ./18_=I5UboeEΚCBʹ>zGX^򔿤T22NdEMT#,M^x:s*̹ >x=מ$8X J$)LSǁLQ)rVBt3(e"2cr *5av:H;EsUD]4cOx4:8{|>`oM>Hsɪ)Vyj2ix_ܻ_R9/חTRcwD?`%xG:q8Oy%).V:#ЋkG,0x`ۃ,ɼ='| ~B2qA!87\PIlgGRpykQy+ݾwhi*heӖ|K>R]P&yO$#_1% fןJi[j4'.gy܃3oEtFم;ۏs'G&(~!3f΄+PPB bkB˝Y*I흫/} !ԹjM6SX Iv ec8G/e1Dwɳ^V'ү1tm- h젵 JA}NXl4$}&ʾ44팪ZPGv5R8ɗMWQa +`: ībb)1]…A;S!S?1FW^PB.~eNሸOe˻B~JߢWѐ`rHcO9qH:'[%(rB[B=-b(F^)&=͆CilQ@P".*ݍŤ'6CaBHc45t6O}H:`1m|x?uyCB XWowW5A`ݜ~.يIm,V5W~SvpI@ H$bqEpì=׹S"4@S(tGݠ̒oXy8DՄޑ ?v4L$ohO:뽻#q=.4Vqސt*xo]`M|a @ CQ)Dp߇ xS7"<ӽ{&ic8v'C8I4mtJqb @kP|$שF!qmԹ8mVY>";ME 2 >'Xi?U`V.JbnyLzU?7jUPToERDfx;G5p`gѪ_4 7[kȇsDy V%tUk#*LRN簸bRH P|+2L3D?>n jFu{Vm7c8,dzf;K9)2n*aBE'%1:7Tp6%4\ vW`JW"oݠ%,<(-R(2A!iԀF YӯGh(av.Ab<#wv2Hrv/ %}ynF.H,fg<ִOg_W;o/ ϨC9 >wZ.H2R.Dj骐O 4m '# #s%>#DuVpXH RLI^[Ci>#_fфKZ ŗCvyA,g мA'LN7jR"띜hNG4t`(&8}ھ_p#&Deȭ؋hFO')߼/?kf}~vݯo}~&z1E* &Rxs#y԰>A }ni(0XXA/DF/Ѵcu(.!Ւc:cSL'/=| J=[bҙ׿Se)<*9A4RXaөK<ߧK nDR|6ՓI1lcfk8 @rؕ֩Eb G$Rut0'N1dAKGaL왔'vnV|ެaeUF=}J?߹]?80L^m~.0EEy{8iDtn7G^Bkh\  \F--$c@')\<{8ipH"vGA(\Uc~3P JJ&ql@3$<"<\byNq0SГF8 nNX\q_JdzlPn |9 _lM!#tZ&&wN}z{:$s1[cdŠB9m$f*V/C(eP,bb@)dgj;C4ڲ)[4q a,va γOmݦNxw~qs_'j|>?=_?tR#څB D =LudžB>ZU?Vˍ)%W0_V|GVm_s 1[5ޯ{Oۀ=a/,S_S=쀢x6ZY$3yi#{8Xluz0N~,5Ͽj|31ux_ W!GoH'wدo^ /^K.Ǎv{CU 1}6ᱡ?lL Оg9{|bDMh8n>S)1nYu*GY@P"&/@5_5<>v֯;@ ,؜g;PpH'yUЇ_ ̑K0N Q'`zzSNIW5Bƌ8 Y|O!Ϗ)ىS:ɸ?^w89 temKobi&lk<F)3D)ؐk</$(TsCY xTw/G"_@׼8 _:_G^o˃`545.|7%i ȍmvA-p:a(U۝:Ӻ6$*ߙ@A<+T(#*3u9ky?}Q,2_ُզU9,NV/txoi̥ 6'3#ӗID  P->j[%@Jr ^M&\hDi!^CX%x _hw:*6pyK?(:ynD؍щ ]C}tm>d1;Dmh|v'A?]SpW"t7w2'ILe#.`ͱ0}` 4 Dq4 9K [Hܫm);gޤ-^Ro Z_ 98v5 ;Z/*a.HKҠ IִՇb|ICrqD[3 hj N]/Sˇ2Lyh>{7^Yi^mH͍|7?lg#8D?sQ>LMDU`ǝ&{ƫ"H趒9{`j>56q y}N Oc32nMPa`34q zhs=!+F(yi$PEA}ŽMq]V<63Wpn'J::ָÏHbNu:#!2& E"*SA 7YFf[PRa 44]eS3G)A_H 8E().? . Yk`PM01`_Ð(D\I#g#ƻj T"~?ʵd _(es)wtu5uݖǁ'.U$$9hҗK(YMIz% @2(ϣo3.d"KzҪʝBkň݄X \/`!ALZiNrH qP<_s 8(jnmO /OrqBVފtmүQ֖)1e {Y#vP`MWvhny֑,g52L =uٿ ?y~~&JrnǑ`Ν޸'(\޲ztk?P&Tr\NQ62MpȈ);/Zl6mR$iY|1=#`PNS!Όl|Tx7= '1x/|d t ^^?%a6-TO62WpHkJyy1; > &Fm3 ~u 1E pr4p%:cUYK6Y@dڌ.¶  ]{V/b,^MFJDPUI`7O!ijU}`%W);6[bI~OlH\,7r6y)z/f)5IOC[XƋ{74ufO-|qG_aJWd҉)<:6ҞVȝNN' A1}SbQp79v5#aUA ls>O5$עH^@ǯ7TP1XΎ܏*Y k66\CM$=)0l:̈D0@SMIv9~BjB, kWc14ӷ6<bJYi0{|oڲvyMv/ w@rܹ(($Ya;T738;ssSB4Z4@''0rRZ 2eتD5#@_u(dΣds0Ȳ_ 2tשΝhmJwoE`gzJ0uq^捶| z[ti.@fLf3 dF{X"#Gbao˨UYG*7B{6aCLW6` 6Oܐhg&fy(s3 MSxqzC@;6#Pi۱=;-8iâ)QΆ|oP=lvݧrJΉ(ȧZy:s> T`ܤGJxC۵Mem;TaBgVӉ^M#Q4'R-9rDxD,"%3܈4DA mѮտ5-ׯ TTJl 1|6bd6 qS1V'ʌ/ׂx;Lg4412&W@!%T]aǠ8GIf0Z&{1M"x4<="]ǣ|?"( Z5>)d<ɀxNz$04N$(ј +gT]Sb}V1D;8$6QŪ-ȖSgٝ+o(d vW`e,X[RHQ^H`hCttQf/zKڭ!K[uF3Փ6A5xJ.>yQnk[]oȻPdN=pr؜@Ʋ8F`r;jd509 :#,gˢ8= 8׵ ܵNX r9hN^,L 2`t, )z|Ҡg|hnL*𱌿2fEDFҜ\1uqd?Gˆܘw=bYst+åBj{.ص`vkbD0BHT(Зgs1qxW(蓭1 1bB5Tpk*B-؈*kvL3ͯSz1h. b|[1n#[×bXlZBsR-%"Q Y!f#TERM4^ЊZWi_0crFKQ!QsIksS4u4wXaޞk[- .Lq!l/TR]h)phxVc("~y 7o%DЄ"dܣM؜~1hS6Y,̉} .k blXoifoƁ66Xk}7%u,]HNu|ۅL׸d ǩay3eO6 㙛kܰ&X2J. m.cV Ԍ=wakf7V3Fm<70ؤ#a̚ O˙hg%M^Pц#kh3A}"JFR+\~9>އ(z@.g-Gab:PYr~]1SRu߉ANߚ1~<0[[{k$lTx(אܘP&fq 6 -:[-?l$B7,QwO3*">K(呮htXokin_DEU v0J-!qukl8q Q-3NqKLiJ[m#6,(5#D Uvde;yD,V Qg>so~:/Y)jj1%KƊ{[8%<2nBFj"+RYpQ184?]r0qH:6tOc_app[3J,X)ɭ )y MB)\Ely _H{F3:+{HOl7A3cY*F7KJǐ u'ZYl<!%B,/Y\GBLgٽfݵyyqfV,9;CgL0HX<Bgs[ݛfƒXil]`^jaRkSQiHaJuL8KSgqN"(P'Qk 2Ld8Qmlv" 3vQ1JD`4 ˕ҥ՛; qx XR[ 5.M,d4vy$BÕX2.*&Z3FID &AIm't}8T51llQb-ihKٷLz2(kZq(b;F3 ]}dڱᛐn{h9HRE(p K8/F Rd!3ӈel-nȵ0}˦}Tazo[`/vB{5 h& Ѱ[sXϾIYʹtF =M^*z¥3۷($,c?,Rta8;|,((҉mOYJ,HXA1-<ٗQ1b 5B}c: E3XBYi3^׫1fmzELڒd.  7LLܲ?Jnߖgb#(sX&o;ŋ$}5ҬT=Tp4,:k0%4ɬ5vp- vmk\-!b[5܎7j'ID _fZ5 դ!^狆.oÆ5r^"$qy#\NJ]%giH<U6Y2,˅.S~2!1IĨHe?9gխ*?K VF:շ+(mn(:T+VV,3T,`nQ e8zd;)mGy8Q5*Oْqu@7rBpJD8w 1Bs>r/I1q4Iֽ= OigQ1v&˘۩Ăa<* 1xǿ{N8K2hO.W#5rhnf,_&󣝄>2VBij4ٷդ fVJLdOOi»)ˌh0ݩ['a)@1LtyS stW[=i&2sIF&ddd:Ȳ ÝH%tk9֝5w`Nħg"YtU=zR  q;[@̖ZtX),/[ DjcZmq p%tn lл-ՋNs7-T&;m܉>0^ 5NWM/YH+r؊,5c [f-e̖9h {cB +T`ᶬW#Pi,8ź %=vа,S02b-xG]{l7f0H W#l$Т\猉6 ,}g"iMe[H&SWZ 6PuvQqL+YDX&.î%2 "QA4X:}3[ c4@\^e9MXcUh'Vx2PEq+5F` K _5pg3tInćr3yd9MiuXnP %"T$֑Ϧ}ZJbI=}omJ= }jD H-p`GMbկ@S׻r #k?TIap^!I!`G_1L 6`Q JL#)͠SY63 OVD,c@12yeE>#ъLH5t-u DD( DVRD"r[Jk|_k? ]Z^Q57Rb;YpZǜe?r|"z(̢sU}q[% |hC<(}A}bf$DLPPC=pO:qd'2 xî2x P6d@< PC,Ba:mMOL(,(8$8?ÇlbW ##Oqe78kq"&|?2-OyYtr6,@Hf6ڈE@(ʒU*Ji?q:ejIL 1>j&՛.C[O,|܌:wn̨=~Ƿ7+JmbBGi"PI₏ :"p2@E16 @0t.T_HQgd .lخAd8G. GPΜF5nyUA7iGKιV圻|BZ-e\H<wpHG}egq3s\&G֒]xʩUL]Qd7KEBNZ 08Q` T%c@:cʯ`32;]l `BόܦfV> tEʂ>[;yI^@YswB[JJ!#(GrD4-,^Vi]M2e xƬjύT=Sۮs!СX$,bjPn♅AsEamd_D/ܘ(@!;C/Ԧ|~`eqlEkHf[D6O2_Tt,JbWzmT%7ȯrUF%$+(W%."LMѦL8rU m]dѤ&SJt0z!qz:y*[w~ ԄC%aĪ;QY-v#쭹πb+d3#b ˍ>r " U~i Qpp##* cG8vEvS(Fihd!Ǹd.Y˲إCX}NWe+b)&B!.WN ys1!Owѷb~;%GGf,0b Fb*EJ.8W>nEKIH7+/e/#S Dm.yGLK4am{Z'lp4A։A;4%iwmv6w?>B.aTIL]֎VR;v)TL9 skJ C)c=+L)5F" -ו7EgYdZ#\lb#K]{}ʀ4e%p𢭎+\ |A?D#v䘱*83#F t')۸VbD!O7o! hP:H݅2mW2Wch܊[zULaOCu*α_\w,>Nm HNn" KBā)Шg z >s>DwģpaR;0o\W)4m⎅;O,f9v0P5,r5e$OOq/K_f N* $Wqy7Q`mJ\&V[-d19HZ<`ʀ2F'[h8(To69U]7P E׳"T9/A^31GK TT%HJ7Z,)p;Ɓ/O\2 0~vdaI1= Apz(sX\`|ƎjoЇas2vz2I1%yW 8ڎ29` PEbK=$2=P 3xΟ)\mȏVǗeQBJ"CCk49q5D&I> vcgJiY}m(vc]};y9c,z0q/ /bT.%Ɋq9 ؐ)uNV6Jm*Lcv[(~ 8Ě/z:OKfg`Ot͟I1'Rx6j=jG)(9sXs˟N FFკ͜"sً:gہ)6pAQyt#R)e`P%vIgAP-DYy%V)mVBZ `A}>Fgm Z56^p i@5@ y/2:hv&L:fF_МXefD" rXf pjRkf=a'W Đb @i^ pĶsxE)H%R+"&y J[wGT˂]9Q|* 5ɘ"%a"ڭLtIbBOBs9$2 =qQm( "hp>KP9+x1s+ςb T'` DݘE1 QSM}Ҧbw_I;SY d"6>B8_M!O:6t,0k_IʔH[X2 m}U:\kĔ"󊪍OOXt`m,9;2w͔&-V"ѓĕ/X(4#SxE#kj +1mO'Cr)PDa D_Qyլ5Q<b wȗ[MV4Y\9pܒC3ő!DKLᖫ_ ܔ8WAc}^ln^s۷_Ro,ḑ̌gӖq?EThʥjPo}tt3ÓsfEθۑcS0na!P_U4c#|y %| >˙JdI Pp[hCY->'8+a72S뉅c;7U%bH|q=V\`LL %¹l2% SMn} vco^+ SoD.njR-򺩆xV  uq~ww>5FQsqAFTuCsF( <%RGфS*)vsOS> QpC-ܖHᩗ| S )n3gwz j q#J~h%j3nhIR6xQO_'~Y?/g @H6I$)VC6JRsAzA>a) Ά+B05qaڕ(ͯ=bLBWҟ[G uE - .FKcŎVz5IX Ȍaن?U}{OǷp Sz9b~d~m\h%$H  1uG>|iNFYCEF:j rH1_B1C[6_T~w< xyj IM T0?SiB5Ma&˗%/Bd73|)_ e /q9t{?S\WG J@ OBP7, +Njy]-rf/T LMS9$O1Tj? 25In]師Muw :$нPŒ4i9Ѐ(@ xT*6z9WtPFnT9"@HnHqkߺ ޽)n8UhrԻ3ۜ-j[Z R_B8 p@kmȠK,ćer0W]-CHLi/%s0#6W#"nT!%ZtNhEj/TQD:Sf.5bύ/Unũr`w&˲_^<~eIT6 7Î,}ܞA,GGvST[ga S%ޠOVdv֬BӋ*^CRg2q #یC/gŻ%d!~JO >ny5f1@A3c{` 8 a tbGb?QwjSP=_𐀺r.?D^>tˢKKd,hZ t_Yd͋P=f)گBٔۖ 3N^U0% N6oڸؙ8gz}~"ETD r!EX %cmaMjs9Ծr';ßU]Թy.Ə}FT՜D?s&L&2Wrmʟ+!$LE&XܹDb3F)s8lYnʈeL-CZ3r2.jȲ2*Y NzCϣ.#[Dr͆Yƭ*Z) /-Α")&\ˆȦ䆕E*/}W>ZXNKi/L5*Ry=,#ŲaزeaY-˖ӂD;7(hFXO)|Za-כ"mLؘp}+9~cg:;r-UM`& yX^x n^./q1,$q@,|+#^ϱXW |ύ6J@Q^ٌ@N^8 DTŲibKI̧6S鞌>Ij~Ë Bgl mȀ?rRS[> o-UQ!|(|1J/*R:CԽ].pT~m~.ES$8!y,7ha28?,[pWQYс!@0I -*hdܪ b2 UR1"2wxlPm ֚'bby6r&Q,FBj &<[Y '9F$R%{G'4))"h<"M4[e7r[$j XfU qi9vMAl S^xyQ5SPIٱy\GO'h炚cVW=G]ǒȺ4~i{ DV"WXHT!sE`ĺQe=aWf!E} L0D)Nb`c{)mBNG?k?DUʔY;1#%|ΥtqQ9 &u( ARFT{b]둑ijqa D\\LHP " aSbC[<^Կ~ p08`2TA.VEEafT b렄:%闥5+\¸ VnHKFxhmX;2*G-SPPrL.cʛ;a?w|*d?4o~V7IcM,sb/yn)?)̛\ -Ho%DL*"UlO̊ ë4Q\:קT@a{l3"Ga4ON7JtYx5$F'o}# d.K,.5a岲=%het.+2~q;B %LY駼ZP]p0P `S[MG/jLRdVx2͍Ll¾B*5o ;%0>H󽓹6o2BWfIl.M#UlXWK=¤dQ4XwNDWKVhħXn\v/2vC]:(Jd*U1) e/]Py⣖I5l5D%}[nIH0騞qh:Tx|9?6z4HǷ3j39D* tpjiqCO5Rh=4oq-*f*QI8׭x+.P23@+}R|- | jQc cfm +DC6UKd־,cÏ?%/ԥ-_ #! oEH.k?L1+ݶ+M\C&ye#" k'F%^> :-[`Wd 1G2% 8Y@K'Bk> a0dvw#Rن7 x6SYifѰtkzp-sNtdN%03!,WiH?nKN ~+G,E @b%AG<8r;ۨtX(JD]$^YU 3=qU2~f:/(DA Zu:TTJ?#/NQ̐KG"'aDOiӬ8آZWY!H8tJU<'VSJ;&0L 0g- {%y |8RڞWJ GlTJ$έ -ҽvɅWZ(Pf+>N)|)(ݸ] <i, q$)0uGCTBќv3NM!plЖ00, (t~*lPt抭\";'Y8QtF\)v|#D^XLqP7!gTa#VCK6T(V-^qPh{+wD;nEOozꠔE^TV;( s&Vrsf_D:0[3(LA>:$bw")HȋkS<.\n̫9/A_Y||RiGvVm̼ T%sj6S+ebFXcڊSi X+C޹  ܎B!  &>''-9@= uѾq|<0%0`?A0\BBȔUom4!;@#Tz!.СQ2,Ibehڝj ! b P"lɠ28BBRl)$Կn+[r;~2BCڔBJn,o6V0PXI 9Xbα2%fXOda7++4@o>Eժ>+GXi-@T%οW<.-asD6ѠiB]4 @ˌ,-\=]M%|V[Ė#6ΨD93'.ÂTƭsc1SZث`>FLd%%_Q{<[o0܁R$*YtѨ|^B%8?̗—*v=IUL /Yo}o73}uBZ=Z[L#Ur@ɵѶjy oVRPO"G# sy&w&Ćā]K%*ēAfjoWfm(Lf3j{- g,Bb7f-4*.N1A3WX"H5'T"ysLW߀ ,3nPIc|9>2Y8\XtJ||2O`dvUl%|+{P"*ϭC|Yl% _<*jInq:(1ju#9/F̆J;.N+73PwX=氇N f:ի )W@3cgy'*mFv @5Di6< ڟ9Dl&mB5Jc ROņ}>D+Md823w2e1aHNt2_62|kL-؛g+n׿, 5py$BWiнoF]#T=0x>,ae"֕dfx0Ժjp"[ @D(T~qE=n0""X6e[ÿ[AL'u9CB4q#~+kh.KBM Diܶ+N nēۊA:2՜6LqED=:rG:,ecZ@D Rb(.[CkW?\(33c̣ ~ d;ÿjs*$(5m= IDATWên!2%w!gHЮs|eWYeF[ȇ+|v|mAUg^`7XlX"G}8A.-y5`ۈH),C5I >--O#hO+ճs4+!Fh8_ )Tw!€{4 W9RBdOSI012w[-glmޏ]ҐPudwTȣa"EU%BўVe.ơg[ ISV jAj/VfuG TatZ{('`B[Ar)XV(7i{?&-?cR}< "t&]n`B"b `v{d*[ "S%Jm&tX|Rr&)WY?SۺB1tɞ( qӂ/J;^ -h~ ~Jurtn*JT B0(}&@M2\'[kޭ 'wF-SZLKm~dWі8k?^lr_L.3mlȜW1S,2Vb3aL`+Xr>HY?bm=x\(7GD6eފ֊:NKطH"2P4'cCGDyϔ+>r_1.m?Ҡ6`F^&$B7R=g+ BS|Dwp R>˖?fo)ꜙzA@6Q!)6ڢ%Lp|#8v^:(XɵG9qF} .‰7 ++(2TῢɆ)Lυ8Vk_CԇcӠB:L/kJl**4%pp+D@ 6 DnE%dV]6'hKsD˞ʨw Q'{k#.^B_Yno"2b,c b Y62TGlpZڃ@JPb+'k[Sr[r[jEk5x0U+d7epe7& z64Cl&RjEDmH+ڒűL Ȧ!s,#o:@>VĈ ޵8?9,尰Bi\xHϵeňPHt/6pG؝' mWwׯ, }zsZЌHM2IB"C;}\{)+e V(dmT;Nk\qVK[#h9DJ"*å0:qcꆵ*Ng dI)DM\:O 9#Yp=EH<)!J2YZGB$-y_q] VIFwf+Ld'w;)R`FT#qXJ?u_:ZHvqc; ^smT'Fl=ynrpHy&AT_$tq\ > ;߼4,]H IOWK6|'&6m-DZ߼/q &2)S; 8VLM-  !\A ROtW8%2!2V2@s'U쌏ֈ+`V_'5x}߾a ;7MMu.B<6\9*㎅$6P檍uUfqg 0FwFP&<2 r V 2 Kg|E7; Q<x4s9tޕVjs/(LdܸJN6. HV{az#nÍPF#vL6 ]6F1X5R>yTel6o_,lzэN3>A96~V\ ,#l其\;)6 g %b{ÁO 3Ӿqy'/sç@ ظ97 O7 \+##TO]ep,xg:NMw+5Ѹ4= 4-=@A)9Y/I|@UGz3VӘʞR=/g9Tb3%SH=V"i3,>N286[1A߄7CUzc&ސʈL-!0Z|<]#å;Xy}E4ȟPc.:2n `B<\0n,c"";Ag +%bXB6ћQNm_Fd@0g{%%FbʨF½pxA_^wa)tl:g?'@=U?ޱ,iFn5v8oq oLށ"b0NAl,V?4TAcȏH<׺\ȓ? rtBC.jae+(-i|>F3%:y/͡`Ҹ]bE irʐ2J ;k=K)t aPwNl \oRƊB}YǞމi vUT~SFGlB 8ix[ T^aF!m`%Q#tƎ2(bBF۷~JOO4s- +qqj*P։h , Ov1s0¦w\i9DکD]#LŘA@;#J`q7Z_jB[x"AG g8rwK{G,sd1oKrfT-LQkrAy1=I6mǚ2b~Q~" \HL'`TI; 2ʘA͵ W -0yo_NamdKLTN1T52d.7Ųߍ2ezSb+"`3IC en'Rd/%1H:RnﶢT\iBomSFTlj};i\O^ٯAWhp r}~( AIMOLB4&(L2c5vMQvݴl B/ p.iMX0a@`.N"4` @Ol>⋳wvp28GwqoSqG(Rkh`1< [{Ng=UCg+b*cȝLA4Uf.9)F}-8&)Kɡ&x.%X Y"6dQ 82L p* ,1q MJ$82Y\bs&-#8tS@Qe$QFDjV0PĀX~ .nh 6WlM EYК4 t S1KgLmv[]N\y)i#:[r~1>S*TaƹQP~ rzZ L48,J! [P,_bA|E"3i mٔ))"x:"AS31sIvS? &A-s)jʼqQϞQc6c o '>2$ ;CG3{'xWR~EǽC &wcYo|A=dߚb.ER Zdq\=ɈdZ*m)KeCƆjcem7PFNJ`J:-TQR@.?GpxnN|:~Ħ'Q!R2YܰO6d>R:mXjM["QD" {-U5< AHy ;/sŤ+մZ'ϴ`LE!{54<h MeĊF5^3CxPXu׎P9H RrUvd _de VF S2[l% N9S!r&0宯^J+^RGBv+XA0 H,LfᝄF%9vfebDKɷ2_9AMO&6QsJJ2z_8~'`=a tdL̐Hcb8mT ?8B2g^]El p1Ӭ')cZP Gv\55-41,Y SpO Ԡ\Xo)p!H&֙[HQo jZ1_yl>KŃh:]&/L1 d.o@'pp}{J~_dAl xֻ $hbah5)vj]5iJ-RBŃz_6˘"$[D` ۅŃ19kPL@cfaLg;S˅-;ynSUf9k#@Ijg<0Ivh:vυ[ y"]zBFAUp瀡w*CR|Q㋰`aWYS+ʩWTUA 6|@C M7PL)Rhdֻ+^L_4&#R=Uh9cxÔxi虫 $jKe&`GuMޮ{ns߉iGa߾tl V1.8l,po91B.#sw))IU(PiD5qA2*j h(s[54AfaS$ɢ@ueDk # e9]JE[ |6Msxiz9x,v;Dc=QuUްrs#>umb5oϰ~+T6Q$pa o(V;lQ"R5$FPLF|hZ-8I іn2S3eTLchBTƁAF[Q/ZK22Q0H<">,2q+d??D:e0qJ-31d1`wR㟍%Xy%/g@Z>54kF23%^] 1iS0!wJv~B]u2Ds P;ߋpط< f.6n\hSlZ '0TFo|)qDfrtԙAX9/3oehH&|"3My1Pkő{*\b$&%^0_?~M^.dp8, 3.iަڈ12{92甄:UHܢ<噂7H 0s#p^ KΉ2Įkd5CݸѼ&oܖVFxܡq&PbO y70HxSS Ɍ MUMa]PUAk4ZXs@y;pȥ)(]S@/D(]} w/@&^#MQ xKӣ8c]r=&@JGih?*3PJIL2boVZ9[D*}ԩ3p3F["(vR 2-:'`ӡq)| ^hk:Ȏh>r:ݵ)Z+Oo?6M>}kHt}f%dȥÎڸk$f.u#ߢv榪tkbSA\с2޹nq+K0vy7?n$D,/`.ROǓ9 },8Kg[9ʂZ =AkO/E 2V3 aIkӠXQr%dpXޅ(IR+DA2Hç{eCԎ3NZt@('qԶ }H]/T[M@ rG|u %~;=O7 Y*9#J k {Ӡ0YSgH0Gm5;pc$#t C14n*1X!ǫ ,($1 Ck^z HGK/ôQA>[%=xA+#Pіx}S-p9u M1|88b+@ƌ=8׼H)#cJ8*"I0dH e+̝tݗ>QIDATɪgb%ycATO+T,PJK "VrZjHҸ/4蜲V!Ak n}2K1߫ir>lL>t̎ vZDS4r9#$7dkUHBPFk3"l$ҏKu(Jqk t@BIK>QC n'ړ_`L_*ÓA\Y><7  V6#o4[umGnyaG3(-rlN O[]I &}V%56^D5?GγcYBY_#G`⤶g.u\6Z9 SF FV+z0 F$r[aF5)gT් +FʶK #]Hx{ ^zLc > t1WU%HܟSׯ ǷTHߕWA#&U$BAܛ$ cilT\<_$W9 晅GϩbEcp2*x.K9g +;ptuX S4եMS4/B w?11ѭ򆧥 4^ @@~f/p@%mH$OdqES#,ebL"qTMj$/ c"%R㚥@+5,[1"PDfhq=Qx?#TDS&*~2nY)mĉΊ2.$+033J7S.s\:%MT0 fgX6l}L@תYg' WK@ [ML<DCgLnVh$n?<_-VpdД˻]d,7r!,)E>h4lr),ahv !IP 9a@LQX#кE+BX1Jx&jE+JQ" U 7EygNG[xǨ\ Sl#^.q "QƲ~[^rf ,O 3h (t(R1Q-᩷)C+6sc̖mN\w!24ZL0j} h]5\HnHofqᮇ¡vq(@5BD/jT'[$V+$ _Xa(VZ&@/ Fhmv@0D#ڍ۲bf%-#An+X"Q؟wڀJ&dht!bhtD\eNPhntmV y=}G}L~LWLwč)u$˘ڊNZcu:X )PUpB \JZ%! 7j6SDքwf|\}P.w<,Z n,A&inkL'&a(Ņ ( F& $@+ ![g/;)EGf`g"Άh#A2VXz$>ZR%v|hQ.=y岾5lŴ&aZ֩'R<Vpcd,XzV!2_[ijeAf<8d.ymZd<<1 h<,)vAnGo vaX D.EYf /p5b%/џb"Pf̑|-xd!X֧[Ʃ(UE{+:E: ģ0!-~\Z Y f:t O6ۏQbܡƐTDŽIAL ߊ_KI3((lV(ՅF>t,#AE~X@JGk -=͵U'Wn,3%$yH]VX(;-x> ?-]쾡8qD~m& (޺q-gAdL}Ͼ!X01eeIJErjkK2S>sLI"1Z,dbKnc‚ǨAQ1XX@\ Wʍ*䈲/ A3ګS >vXsXDž0M2Ĉ$)G\ A(LSŶ5(6 7,H&" ¢à H,Aʕ ̦ޞO*J*8#Ų᱕B8e3JCri zM)pP'a2̠ejz o5ElOyUz@(\v$au$bdnMVI\;%.G|I_WXO6瞭s*_lSA0̒ؔP;BA]ֳQz*\l2hV¶Hu HT}^O_gyEdP',}QCYa!ëQ%$5x+s2*&pRd[b}LTZ)'&OgXd'"z11aՄ &ɋiUYmFPB8U̕c3A3Rų6c~&lsybAXrtNM" Y YIDaKj>٣ERb~ {0 qH)㫝Y$HC\ r!( zڏO3q-Q"L݊_%-*a>`8"c@M&*O|mZqP|H~0XS(j5bq؏$q~k P5jj'BeOGzlĂ>R'6 a҃uRm!tGӊU¸NRl- FxWuxKXh3AG/?v!1J¥wrY-//?q|UJ*,|҇m>78h !,}Cotའ2׊0t)ZgMzhXee"0 zD]h1ĢrJZA!Ə3M;Q_V ˾\": *bAҕQN"OskҖ)Σ.b=鯺ia}PJ^Hؓt FpF +@f;GѾ/8NZ'$mZY/gjsHoRX;EQHnLP*aؒ9f>pI)L50!bGfH}c(u+DfcǥY!Co}R JmJCBX맠# /G$p.#@D p"L., ϯ17CɊ̓4‘ƊT8!)/ca07GS ^)( -ófQ.yaB?)h"X2@\,Dx'29D (F4Gt̿ol++GyDWW@njv`"@,X d,5#,,KSϵ,[kW"mKi!,}+gT_b@{!P,nttaK:c Z,pM:Tq?LZӆ91+cŠWxkke썔GeA_}øKq|m)E)C:(֦mPj.%zi0 "܋#`, A{=:\@LFiT  L brP.*rįo"U[rCv^ZXC?3>X!ؒ9I|:HB(' >@'h\_0$Oa'n$]O^{R}9R.? )x\O78oR0YH ,[Z20BZƼȆűKvC k?V.0^]3g˪AGP̡Jp.gY` K2#S$"SّZώ=*ϯIMynKY=H,ݘn ʢ8T1+4-ztv{"~9,J+, DᏜ$~骂o惪((.ѪYC2{ \_ 2Ba`qX1Mx/M6CXQ"HQ`1#>hec<*hWb)͠UH :xv}+ TJ}$ia)P| P۴ ~|%ʝ,C}4yaZE6򢊉$UP II @fcgF.ڽ]c@Hy_/B8G*,/]28TLf"8W|97^*wJ#vNjLTSwLd;bR>@6s$s~tH%mnNYx5h4Aؚ;: 2/~gʝ,˲fdiӗuK,ޒŋ% e(fPC :\tC28X!)pD *zbꦒJs$!3s:sBYD~Z\*w^}wK/Dn/y"d )x| (5bzG7#=C9C'$/SĀ]e4 q :#&:Nue6—@ .쏵O"c/𖔰.)0)A}cjT fi,j#(&,SXd=9ve-3L91@烘/rHoGG?\O@D@ؗ=Qw@0!f -c^k=K&x+,dhW+IpC >) 8?xo bReHX.,T,L+[gAb$[e̸#W)S-rx/Gߪf?s#%$f8!R9ie䋵b"ʀ+,h(j(L0S db.g(e~|ΔoUdebKJ[hJoBLJ#BJna(K䂵/V>5L4[;Y="_ƴ8a!&МQXGXaB~Zb;"[ZERݔK2Ai{Y”s (dL=LKʝ,qY7l"Mh\FOo 4F;k`.qʐ2G@ؚ5 Dmb-̑1pI$v;GvTlZ>i*=( l@P4\SLD0kZ b{IpI4aE\-%3n( n GIQd{K)ؽû/,9aAXGjMo; Hΰ3j4CrKDL LNj@'ʥ'ɦ_^dJY{ (Bka.蔒8beoM,^M!"F([f "E2C@ OGΚZdKC̻$40f4>2cb,('iZ2J\<'st =Fg˝,WSJvؿ7%apC1l3bY&ʥ,$CA72>t (0Gߡ֊#'oo<~|ڋ\]Ӯ۰xyXǟ/~O~vQ|4V;Ou,v^Q>y}9}>wst}3R8899<{>w}?ss~99}>?{~RT?vO}]}'UK}%TA?P'ǾPT?vO}]}'UK}%TA?P'ǾPT?vO}]}'UK}%PKAK?Fo arr_3.npyPZ\nnf_TR_ wK)Ng$: ƚ: p岿6\Ḿ -RZ|ggmXpIA5pqTPKAK?˻/P$ arr_2.npy-y\O/ c,a)מ%Y(df|SBD_.n= ,3?J2o~sssss!#<)S9ϙ<۩}J'gi!}gL9Y;wrV۷tV?&8Dr~"XrlwKF V.e_>n6\'8~+z)ϙ*BlZfvVWw.^?&6`c/>1I`m`Ӌkke3[~`Af#`~ ed\Y+X k%Xyq/6V;s`< \z6w>HfߩmLG &!)P|z _VU7xLlwKlZ*4_?y9/1 R*ld?wlkaN~rE~cZWQrX7pt#jD~R뙳}v8*XOEЦ0~zyƅɸGs~_"π6;QYP#\ujV-mPZ~K3O V~߿ 6j_eC?e+=F ?~#dޜ,1;D@+%Oی<{1Գg_o_L~呗4WXߩ7pURc;˱_;]` ΫCE2tx湊ou.WJß.+Ġj"[SgO{y*XeS(Xs)\+-jl'Xtt2{Yr<$:Ԇn >[u<ߖxXN]^-2F ,(֐"_.zQΜ+WЯ:H|U {MyjQ*|6^ȳZo :QSxd?Vyzr&z7d=/+޷KY`1zW$ N$OE|m%|Jg3:b ?>oZy r`5!0G=`ȷb,'Fȳ=>,x/~k::Fo_X9݌?=lŞnMˠQyݩGqhy7u4BǺ[gUe7zxK^U~k1](Q :Y ?z;jWlFcĿ? E_作8U`/{EMǞ^Fy>㽗~IG~#J״OʿGg4Ⱥ>s Ru?Bg6|ej2kDȼ_wr6\*^l#volt1㝫'et[ܡ~(<#߬o("77 H*A_83f/s_[Q|>ls{"XI?D߿+|aoejSl׿$YmZ r`0Rz?@}wySy{F|~= ;$bWGK+eMp.>F7dB8We/֫ '>O_'q>E뙿@kZ5syn~,'"#J4캗8f|]lۑ?Bp~ۛ|ꊙVb-`3p`sc/΍K2oRu\ԠnX<(;'r4a"ߌ(" |*K5~섑֓\F?;w-~<ĥ'}zoGIm~TBqju;~jQ uOp2J)AUi'hR͡g };ԷάQAS?U#^SOxyk[(Y)L:z@*l;}nWxOu!fbq& qqOx~3ߊ(KnMjOC&w?>s{s8&jvy}fO&i􁭒?ws ~J*iϽ&snz0d=uÑ7}qbp/49.P'C1O &.j߱sDžzHP փSE vC(#Z&]c~\ T.>T ;[={6uX@污"g_2IJ>ܧd'(JX۝~Brfӿ.j:C_|y/2>o?XO(g)kNG\, eC6x\ G[q{f|ʷ_}1ch7_K/Y}# O/csN%[ҟR˼u,X}g#ilrJFՌ}O|J?TgJC?}ɺ@;~hk:Mc!c;~5UҟHtUk*f?պс'pPGN2 W}Pg"NW.z~k9^GU~kN!=~%}Fw~-XbOIkWT^'+>l_%OI9|6/!5H*$.RO8Fʜ̟[~c'j;; u"/$jz>g|"ߓsֳ#R\|zO!9-X%{Y¯xt,Sk/Yۺ>wgȋݡydPώ$Ou)/$oiy> }2ld偯'H_;6ra} 6X|/޶\?ȧ|عq!Kn=3zk]B3߶{EN;U(X-ÿU[/*{ 5ܝ'?VzR:w|[{^wpgw)5IxaoQ$}TwmKUK\о}BP!Bz`ډy]/F'r1GW.b`3y]]<yqIo|W2y`Wvܟv(gonXHݖA"Wn VRw|XyU_|qz7E?鷟|35廽j0ᛏSo7)|\\ :Ee96%JTÕCk[7o'8E(q(w/eUwWjù2?zϿ߾oeeyOu(%6\HWVԱenζe17%jsl p;Jc4yWϿW_hg:i;Kpm-07xQfW6ca B0{b('RQ-̥RF( Fqxp;o_mfٮS Έ=# vx0Q r@J kfqg.wpf b q8 jO-x}rpNB0l &rW* e†U֑=ŕ 8"?M\xl[d?>)[GVII'N/G !/;TNH0qb@Z9_[P޸3Ioƻjv <}-'b'P*Į"prk#RG{ Y"%X*'>Mך@9 nhy:p> a!{8V:!YO`'ϧdr>) pzm ${ټ=6b_Exi:lr&L֢yJҗz0b8ث ޶cza4޺ 2i=gumύ;gi!.^\;#0p6>ڵGJB\>ppȴMBw̙ObG%~)hA_~ +aW ^&|kWZSb&`pP< &>|fvRZ3?iNsYt{1O!=-::444jWszw# JHHkC#l:@"#p*K&bMf)B{a.uGvZQWhE3gNLhJ9IL{ڸeI- l,&-xPXECX7x#NB('>"v<$169hd`a, DYg՞PG‘D#I,=r1݄k?p@}  dƹ)P3cl:T{ zpQĨA ?MQ|sm_5>[kd!O&q'{OwTuj$|r)ktCh|\qXfk`wFȸqx&w`uJ05zC*Oh(&X&M9f:Ti>4 \[]!W0 #>b-HFgSroIABqDz[;9:&Aw|9ޚm$'6|o?}bH uQ%)9}3чW,Ƥ-Z f07)_i>rэּ Զwg:X}4&۩.ݪAgkCO{ Dt#*4 Uٕ =. fv#7kn"\$/\sԠ A;ړdt HadsLV7q@y-D\1^H*DC2w64餳mE$!>  0ǹT(.Ф}xh53  ? aMI\$퍉Qe؂yb,VG~0:.[z:Q3A bu hX"\(?앍t9|6b?M#Zv0kߏFيU^ 4Ɣ Mur6h7]I܈;IRnt2;U,hBnPǾ{7]s˭'/zE~\#Y#IRaMym`nj{knB!g$(Y@e^Uh{wOo ZNJwQ ]*av%$g*Gg%`k{#LGeLJzҶMwэA sL}Tq&Dya*=ЀL!wA:h`{B+;W($JFvT6|aA09@%ݛ .EQ)L5B06z.˔TVfn`Ծwyt]k@ 'n5l63𽤉rou,Q&ۇY$*x6TLWx.,Gic+ߟٟ +g`Z8Y$בh`2fČTG`?8 xU?Jdqg1p`a6Fj(!ѝ';ƽba3 8,HUG8#DD (Acӥwx4Oëkd:d ?b_ɰ{[[eFyE8K(3'{p=if7z`Fq _ٜܺɓ'g{nrzh[Tc0cW'T6t=JNG 6p ,u~?NƤ Yh6F*&a<1$P`V|`)z | 5&?աFs@Yz(u"M]P!L rE2's WGv~:?Z;޼ľcUjSDqF50c\|wABjma^?՞z.Y:uDe5EL̖&{Degx见ƐxDE3_fʘ0fkm)_.N2X+ě$v"L(fv[;[!x^>Vh C00r IcZ'S13rS3C#9v7'JO=/ڞd& '/eVNҫy:vW L3V1p,5&5jEdVg&a 8MOn6ZI c5KŠө*1njG$H 0 aT; <͜>f-1)u ,UWU ,5w!#@O_?|Qaf`1mA 4p}LPoayp^h:7&sdE|ǭ]2gidah_jh:䷑q[U{ 0&"h ԓ_|:|6eqӃd:R2T2lyI-V낟c{IjA Q`@S(I€dTP^692{)D`O5 b2G _+^70,+ÅJ7N/{(a=<E 84C*E~|"4"?#Ok}\@Cmyum`n- I"u U[`f )O*_A%sX/c&mA3n_N><{R'C}E1 ;&4 49?N\tڻR~W 214$X6"sKrn=8<8朜 4jP턡 P#CXW=)XXB Ó^L^{'''0bkœNWyo4'y?}'x,wo(NQ1ݺŏǴ|կTB|hcZe'{=ϏjIa+ }oNnm7| .?/}/<狗.E[O x|ֻ߸zH؝I?1HÈ>:b6ZIa|/xrr \2F5?&~ Wߜj˧ď*S\Ɣ?,k'˭a&-=0 Yy|6۴EMWǣ=Xܕ]|8H@ڮ *G6at((Žx[/.6#/ǘܪ$+0>sظM]8[?H g GjEcq?^\~{@yWEpT]5 #}ٱCV!40=&ݳ' };|of>Z. 89o} lI t Z'Xո *.C 0v4MvH:-s~o~PGk0SO0k6gGobOJ%`iSy^-C[kaN+S׹xE7@@;a쵿|RJ7 5X(U:xt>ǃЫZD8jl[^ EMPۙԅm*hC EO"_~fARG$xGysCGxL!V?atU&"uBKgTpVyL#|8; H4"{JsQUʛ}ԢkF:1yg+L[|(FcKb'ԃB'n*p$-}9ZϢVkV m 6Zǧwr,^<昤.@F zpj@i?hӦzZGN %@Ⱥ!i(ӑY5U.J! \( L_ {kϦ` AT }<_*#E䁜#UFEkRVHjջ~iEB ^GyIמ5뇙HzGt5NJ`bFú7@L +Ju6< rqi`u!?CMiz0NA J 45O0f:̾݀&SД5u8|P\2i݈X+,#f3/8ϫ 6}vI({UT봩UU 0L<AxU|mvKMS/H @!"v,JpѓU%TTg+¶e.,^Ur4%aR]b <*Q^>=a">wȕA{u\ Kxsc j|cAШFj.Ň cQVv5zy>0:()6k_wbFأ'[@;%Eu_;'@jXծZfqM^I6J-˾d慹i#)C%E^iu1!ZJc QIs?S̯aj>AګZAZ=8.>0 O9㣃VezU8 " m|kS3u53>vO\^ LK 8< sk6bl^T@^XDŽ9{or2`t6JXPKK?AW0P@010.npySk[&xdw:!BH;Ix{ \}&ɗY=Y=5Qow>Sիs/ k}KJ#ò؛s.<8<>߼GϷWۗ?<>=oCηΗR42E8N$)0L%'˵fPt*eB6[,ӋT*ͥ3|P*rPՕZo{7.gޡ??u׎o (a9bH+h?jVʥR)Y̦3l˕0LzaerT(jKBloomu76vϮo_~~x~x<?w+o=N P8$TTӪJ|:K|P,rt>[(*bT/-˝ͭ 0{ux~q'Y$-xrvp{N)wo)ai" B05s+/,-Uy|&ťbT*r-_,KJhW67vvwvvw7_\?y/߿ތ5J ,-/w!M.i}iRyr0L>S(V`T,jZ]^o:><;=9?:ؽzzn6e(` Xd$i`9XehR)(O,ow[f٨z-_sBͥ`(Rެۭ6L~yqu{puxpkezvku;p*% rcO05Rٙٹlb!\L.&fff dlf:OKezVk6W7woίon Z )O??`X QO}0ϒ$ Hb(#ir{>áPhl$4:b3sBz~fq xDx$ζַvw:>MOOgfgst4NF&񩩩H$ OMMGF`6 䥞B O[5IM:N `pdxd,<:NJN{e]ﮣe}VNmoubZ(pfuB>+fze=*LkꛓB&<~? G`8-VWWVzk[[{;{{[ۻ[[tT4Z9rwsY/au6\c1 [BޱRX:.?==v9nP8/7+P݋ZZYu;+k+&:leyckiZ|&/gZIkW;Z5WkU\. l 6 "d1&&lYfkj|U\X.Wkz b uVԖLWVZ,$'csYGLizGrn|f۽^[Yn6rV}\$l.W& r$`6,&fPߨBū/KJP\XB651uNECsx8S#?*ԷN/wVk5Nd"sr!YAB&5f }vo 6Gp Z^G(- r<PȐkM&[kݵJoswk].Ne~$2-&R„du#$Gm`Tx* @RsaonFpn%󱹵f,^ZͷZfZHcsL,тId0 z##cө4Je n\R" PZ*ݶ5*b:4Z]X98?V2bX(ז{хl2_SAZ:$u:b֙TR :,5P+O,/ƔA,93|a<]=;\79:߬k4L<Ij%=(j4ZA#OzBf_,\DIR,Q^yLZWfx4s-w3|kBG'''"b6E@lxAHtXA,A )QҚӉTX@AV @J&*J:JG hjq6۩Anh!j9'cBr";Ic2P41=FU0A ˕JXU˥|4P*&D*aQmFjlwXjm7\bh[^Ϗ/RV^'c)aD(PETFBI[\ X6V D~j~nџHⱙ?`b9 yuá8jE:~Q)NO&Jz#;>ʅy`iӳPZ1l䨕&|/ddz1Gœ s\jj&2= D#X*BL$ăP.Oxu4{K9 TtVӤuW]qTp0ꋡͰo|`3a?ќ r%26=2S>3@]uer5"JjEeTZ9JD]d^6`$L نfr٨ЇSUD4sՍv/'sN!J H(7p=%2JBg{ 'vh}b2WMƓQ)4ŴBD p]޶.@Vg\AEr1s AlL'#椐!! n ,3LRM9knIF3Zl/ :[΀MڞL,i-4d"-ڍjsf25^Zc!$7dhyBH|3.ggn$, ۚu+9_ 򓍈&84Hd&1ʵ|r4Иљ n#`Tw6\ut4 7L+rk-M 6;0/ b--݃V; [iԈF+2pxS1tEƣ~IL ZS4I[jj|wRIUGVR FĂSK+xq5e7T`1=sE:(5:BO >iwV\lr207>-=(HfZ2X5*dr~~n)['oZxGr$&D>NX85*Ji'ͤB> RJ NvHd|t":0Y@ oLxӑJ5737950g|[bDM0Bb׳Ns9&K U$q@`KN~]Miw8ճ- Tc)/@`,OYBtUtY0 |!갛XVTNXM5gSHJ`qqmod{k;JmV*oGvhqd4Z%EBMsj 4K^mW*a]JI$ F*@#$ Zrw 䔀+)aq}m-@fu]V>Ugۋn>hjH+rzm^m֗Z1:PP=$5Trj$ij TdR\GqSoϠwݵn9i7zz۹ύT)@;hs1`BC ' `ŊhbyW Qja ZRީų4jW=v[u[LDB Ǩ5YL6ѢwL+ d|"pѐ E3+p8`3 RrH tYA a%1,&KىX;h bFHT9ӧjn.7 [MFb'dm2Cvh3T&qx0pJJ >X^w -&qFvMuӃID CK}TO.SЀ(0f9/EA/jܑ_T4K҂ {fH)bue)tQâ6b*LzD2'BskV`];y h0L+URZ_xةSr9LaCB_T+}ާ Pd=HԘj7[ɪ͐V1 pguaYtF(Fj$X^o2Mn3T\E7fB. s T8(_(ty鬭/ P]7rTˋ^V7:AI̞tpkF┛Uu} J1ixFzp /01Z3-<< HbQdAs6*0:azr-ȥ$b@\ Ml%,P|&._ힸ8!bjK%Bv IP0*(i+/`,.9 @FJfoWvZ ach".`Α+TFĊAAK34]` LN  2L$XP+x6 F!~ !4 mU7rH㶆Ĩ&Gl@O}Gz9@և1R !rjv;YpZLhh =%RN "D0Z8}DdTPV9xoﷃ1=>@*RXEXX?N(/33`)AfP=!p 4 oQ brȳmiV AJu(r?~lb!VA³hєl\ϒPѼ A ^V_z} FkP_c0uZ)PUPr-+ u]XBqA)7ÀXA1cϒ0K M =$i >nNІ~Ԙ)t8`YO?!( zgfr$ Fċ~A/Єl7RD X$H !gA9 }K( XݣW;ۗQonu<| LzP?6oUi$S<H~V,4z9 M-?M@X>k88:pu.r{xq~2$Ő1K6X!)P:j5j#CAhNta1P p)W 6CO#fd#.ɸvR:iuۍ@hrz~fro):f^ $cyǥF>H9ogԎ}D W0R(F0(yAb 'ccb&:`$ؤ 3D W8v__268!~p( SHOB 3@I̦!H$tvYorv sɹf1b!0ݬ sF48pV_lxS]wY̡  'N +Xyx5xDh(tkXbP7fI:JdVS SX09_`Tb9CP *Ur=4B2}cIZdA%)􏎍Ǧ9Bkjeq0/ze߰/H1 GM qCK3CI=HVhAeF" `Ak 2n4Ew+8OA 4:ॱZkeq3 6g奙ɱ!_0g.^]]\_<<P&g0 N ]7֠5 9е?^ T?7Ej99= jWחgWOWGGgwkSˤ'G*<[3qWOnO;1_ӷGw\<Yl\__^_^ /ЧrDˠD(!o?Fҽܛ_ިk7w7w'{g7W'w7o pOoƣGG7@Е+%jLxW޹?_nwo\=ㇷOOwo>^^ow:rX-7_uļ^3J?eTNpW ,YuS}/÷o>}W|7W'{V\m7:zXYtc$QK蘚z9)qjʯl{7ߝݠ?~?=ހ/wַ{rYWjY>}zsP CvS(V4ڌzA(A YJK'rtεO^]^lmnwV;ÃݝWǯc~hw'96OGUR$$7pJC+g쁉D|q7WWΏ6WZ+Nl\>_N4M|2DpR;;ky̢T#%/ 1˽nzh OR5S՝x}ut|l締lA QaP|^]^^]\]a&IuA7CSˏOnonWܨI'YҞDuc`m81lH t#Be$988<_o6[{wٰ ]D)QVoK,W?|z;T+;"29Nr"K1]<0>Rzw0={~t??9;=<8>?~_|r:>d8Ii3i'a_bH_{ }LeC/xFX:{a#YWqh]ɫӛ޿>{Wˋ>4=8|<ܟ^ݽ{)c'( JB;<6ja5E.ݻ۫Ood"4zI KbSS CF8ɲ<:~ʡseէ?y||yx}xPvCUH?3@!iBBB`fcLmv]eg^"4aq/\Al㻧w'Yd[`K(@} d0 9H{cad2mDgY6Cݦ͹~B@w8p MYeGח'gokn=>\?=5c^g)hOACqtXEs:98VǛb)q glffw~g#FM7PnpΡ=Ls@ B11B::$v:jd(*2CC3I:*h G7Я_]]_<^]==Ou`-D! A2(_x*G@Akza[inQsd^,l]]?=|uqtiwwsyZD١SCIDЁE'KI n/6j6,O,A349jћ@,NϹֻ;;}}uywYj$hH|} SBqA rZ C#LbbТCI }C|e5X>+#OoOvw/Ϗp9'Mkh>'J($h;Ym@[ LDT"Yh`Btbr1 5I`vHw|yuuG Zm 40doSB}#NCm6F&C.7.u(_΄C> y6t ó<PV ad(JMv9}C>]->FޱgD_v{zuwx~t{lAO@/;Rrc9#9@N_ouqF?%S6P4}I+2 GGׯϏ=8)j(ԗ OU<چAt>dM0$gc!EB2]=9|u|}wp~w|z&e0yt(={9r d|#xR":p`Z 0߫No|t~qբSrvY +*$qymj orDdʲJ lƗ2,XBXةAw1C(zݵzX<:8;>8xu$夀:P>m% + 6yv`[}L͎XX⁋krU_l읟VJaUh3\?Zeh@Qs:_ _lV&< QgBN#ƕX[iԚ.wT4O@э`$ C^.+Q! E `iA fDTXh}ۮחfk[X_^# @'9=DXBas@]_0t{'1V߸jLF=CeY%$8X{RTךRmynSs9CkXLJz3Q@+j$@2X\cM l2Z_}tیRizECU6H 3Ή,@{}ueUuVjVen!A"W^8-tCOg#1BE—zo#uC_X<"VCxNjN[X,YI%F܁i#RT*T39yF҂͗⧻j131`f(P[(JLiqU{ vKJţ)A##]J[u0{>A֔/ M;Gm~z. 5URuቩhtSz˫+n4V_D!,U"!6 qlzS//]}4 ώҢ׉n)tޤ`82:1CBm7No/Up,XV{] t^3&lã@i)ZN=UZ^뙘G'gPKK?m< P@002.npy{ǕfVʬ,OL ш+i%JJVnE.n{eU RV.+gg~|ˀ}o.׿],o} _~?Od\< u2 F0#BwpAgFH)B2^|ן~tU Ua΀ ń0D%]Y) *~_;}=ܟM!L4j3}b9ȅ%a QbuG| |ӓ3 XZ@0bo]ƆȚh oPR8 +is!}Хm=0* pxR'$@utj ũb8D}ݪY* jzudK,+Xfd0քyYUZUyZhX*ͅ+$oY[eiW`#9ʍV'X.ڀhh)MҢjdZ5uQ vt)%̤ˏkP~W=8kGņ _qJWrtu?|~?|?35CMoMg[ݽ'=yz+0L b;E ~޿)%RfV c?do Cx]IȻh`YFhowPzxϡgrv؞ܦҕ5syQr8r4cӝlx= 0iHYeyVVeVWE>ˢ,2-i2+v'YV>)ށoihzyz<'{uwPq+,Kʤ(ڢΫA]MYUQwPfTßaU0ӫw;۫g>ŇWC;5_TfҐR੍2G j(q U ( CW_,/pﰊElxk1m|Vge9h#8"5Wiigju΢W+[ur0ܿ||yr *%hXdE ZpLx[&⻱f+ f@3NvY)XBhG'O{>aYoVEE#1{&* "޿*mX3aqI:D’T q9y=qcɑ65.볣h2[yD]ԑ )a`SI{G`hNA P& @t$~E(#T=dl3WL/qIbLqR*11R`q<8xPR{dՀ%JX vgɤ)ע2*_:P&_=%q{` @J36}D%cho1'EK[8SVEb}k*GW#k>S[ ^<K@)Ad_ұ-dž)p$OOn+P~ O}SA[l)Bq袳 Ҽ t?eIXFg[H.7ʭ uvv2Y=l$YS 4*  74Eo[L:q{V]<~n!1^' O5WE$ D,qg]\ܹ?{XCP[UhD{ S+W ^F>G;mbe(L uik9c>۾OvNA]xF j1l$"!'l(?iֱo8L>q$bE,;EFw"nMGicf]~v~fmkE:<;Zİ_Rne:aOOf[\/vV 2"ʪHmڶ,* >=`f0S8ŭwZvOcZF%dtm~xO\R{yElbq}@˼R.pLc;ҀP ٧p^wY D::F/:83< K$ + P`h)OԈŠE =gxp~W CHh҈E]]-fr'[0 q@ːR(w(˜v[=L;>$zXÖ_ elhnmFs6X{w [rxJRDםFpVb -`۽O>>?9Á;5/0)&챟? ?jY :MFaz(zI8jnT^(N{N9 bϿë"`BrrrҮ8-q\RG>hZP7&||68sr:Z#!~?'*0)aeTyJ'Bd6zCc* ƈcŶ"ݜ2$/oe1!`oO;V7HB`2@8;@ VSØOpT0Zib;q:4HFAw5N[ `x|.(h">n%a;@G1!9]e1vp<ó[ĉ lW}c!o:= ! 0ae܆冾5)7b 6<Ѻ\ A;`2GP!ȍMd@j+:"t>O$[9+<.@V7^8A}-*c  { %wdlIٙ^{m@рKH&m $Sc kF lTp{0uzD 2x_*__ 3(׏و ـJCCǷmg[܋Σ|Tl*FfERQj_^ |܇:@h&(F(+#i`#եcK/hLjDFAim:2| WXF(E$ˬ ` ^LpQ 0xg9I<_.Wq>LKl ̛6x ή!x.k BMAhN9d>H0Vi{7d=]^/%\O<X(0V^0LD E@`0Zx!F_4Mf:9+HF&>hE@ʴp0~~ѣ.gLۧɯAEC-aJnkDL?}5g뚣xh;f!anH9R(7[`aV"uْe>8Băi.$ࠋpJ@¹bRWOAՇu>섭/3vu2yo϶gE<9yiAR]# @?*P/HI~~X]ᶧq5昿iՁ#Rly'_ztdkv-G >8̛ &8+&;*Uf:~ssdK]q۶Mi_WWe/bXј H#)V @O} QGQZ nJ5=}z2g>XD4ϥ',+?jj~.ID본~y+" 0ņab.ZX$hI?b ڸ|B@ߤ8'q*-# Aֶˈ%Q2qdj8 Ck 1[:Zu|6tlr#Eͮ@R|c[ҧ}4]8 :V=*g'{(^yKv Wvy]J,  K:,4l5=z /0A_2ՋGx>oJ/r& F{OPF[(0댹(A*! pQ؉cY={l>Ǥ5/L7ػБP 'xa 恑?>yNbI>ķjFbrBRJ9lXg;$3vqt{v n7)![s?H˲,/)'b x'QDO&"\4BPf/).Hk 8goGl^ꘁ@wMyJ"2E @9⎈C_|эI&xozSga""Po'|M]}TAX%Y4yȱ$G\[ i,EBDj+L[CEn+d*H7I+q ި,"ܗlL+!Y2Id*R߱,;0d o @rO%$"URu-Yt"N mUN,aw(% 8v]p^8H,%[EpG`j*Jn@n)A'^ ֍n* eXB  uڛxxḇf4vLH]Ҿ¿6λvcdKKaJvr#2ѽf'R ?Ƌ*ߥT4kW{7WX) G}03"ms,:6a_~vj!;.CZZMGHWЊEI:h+ RY\ۆO?v3$;D*H>룞_>n獭d_ͽ4/XI,yyx~r|A)Ժ4?st/턜{x|؃À!$vyl&.]Vmޤ&gu&@m{Ld f2,GgdCf%uUzR֧Z%{bDTr>tڅmRUeuASyLn6G%u }ݳ#2g<6 N_|ّ)&aqYk Tot j߁)qSQ\YovN;8?y[æijp&0"7EO&& X4{rˮZXe ~(=YN_/ndG88 LM4sM:IQMdL(ü|_oHٛV@r길نw~}d)Fۻiۦq!S&V?`Qn_>}+^,"NzONfyrzr`ow96sguۼ_NUک%\AJ'MYϿDvȋzWe39ܝitr{ڴ/>g0lڦ.Pik~-MȂ +V=K8]fo]2R V6VP?Mеpp~BvS]~``kC H$wן}xdqiOQM3\BT&iw0bN%!Euˏ+x[$9) WOr&=i4j IdHՃYJpJPx`ͦys 廰a`q"G -tB'EלެN@a% Mo^&cNf;_]id}AiCAuw:N!UͰD}\.|B'yz7tLO!?@mΦ݊ܘ!뵺DkJM=H:aj w Ψ\B|Ė#-IH݈ ToT7!= V&BFJAWt]ʭA@?p|\v=Dұ=k( H Rx^Rwi]K!.;Mr/}'UBwǍ,q2QgM~ _S`ʰQYK/Q,Juָ*'ȭT)4k h3|N*&PNKm̜J)F \ω!2Ov:;ϩ Lv-ڬ3Ib[ܯ_٤.mʒ@Ѷ!EYVM3 RWCeyLᑳ$RB("1 ?dZ7!u\f/LեOJoB0qbCҬc .:!,%%u|ѐ 3 ׺(V2 FkJG YhA5HcڬάQS$Ż\7&ST=4!$Dvbv=z+[80Oدe}y\95UnQ%]2Ȧ a,ryD7:4-uN .SӇy[UdšXbkTt+#3Me@zU>8M_<,[g{")@ DTJt@F<[KSymP?mERWap(w'9 lA(|q9VM"%jwAw·X & I>řc{.x0!ΚAe2K<%m7~--0no'3xkQԩ6E.%ren~ Es'7"S#0d?z~ GΎ 莅ikQ#! {ЀwX+F-2D(\B;Kȟ]R%%aI渥\9V+q*X4F  GVHlp_G7dP7$M\ᆞLJ=$lׄi[6lld%|ۍ ʣ1ꆈ/̾ܣPߎ,I#Lבԃ:2/DA-Bw:3{gUոpzCR K|̗E|il^K+y\ /2;A*3RY=zb9OG?Ǚ+Mt*\NDLMfï/ʬ(|#ͥJO\1 mS .o/W%|2Ux ځ4>&vb,('gߤϥ)Pl5b sW60t>:ʼn\| E;dڔU(Ξ36,˦ݸ8%[~&A!REQ3@a΀Lh$A,S86P/2!DK꽤JN2b2-o ~_jt0-㳳mO7Ƣg0^$ )28}p(p@}?:8Dhԛe%NnU1txy9‘ؗ|7pehA_/35̪v olJ0dFAJ G 0 % NP?fV|9 ܏Ao&  %Eb xP*S/=sdؼg]-k%3@uwGE#O`d\@˖'A)0jU'Nj1H&"Mbndզ{ؽ Hx9m9פ/QH$'̇])N'1`0c:mcvE2nE[0nķf>c@:78Ga堛TOPl| 8Y-%Y&Y'j:o{ϗ&#1OΎa ϟS}!L ̂B!Ĩ <-Ӡdس uc2W/ϏQZ8__5W~@b;Ƥ4'0z;Xf` nhy1(XQ)7 qkφG7zKWGcOU8C_ЂSc Tjt peqm.h]߮Psyk<EidEoB`1|KѫeFe6ƕ],5a?5Z#6^`t6%a]9uy${>cjE:W7/,]8-=.?FMa200{F0ɣX@QZi9IEVL?XXK39 J J^T)Yf@1H>s4LCXrz-Ыyy=%$$U8cڪ"#Mv\7&XwQ EXܽ>?ֵg7d(ٶ~/fnpNi^%/U2FS _ړ39G~K~@~=l=ώ7gG$I[Rpg$KIY L.K"Dsc x$ݯ&޴Lh;.쭜D~yTmj?0)U!R9JZ!χC"~$D@5VY$*Z(\[.F/Fb YYblJ4[Ҋz5C",5*Ɣ,(ʆdM1j"kG`]aLNgIݠğ>C _TFg?E:B~XBAED"lK[AasZլfii&G5kzQ)#E EʢQ2r089ibKuXu`>J*nqG˙xNhلЖ C! ݰ٤na[ߌwt \;t*+{`{)M>ԙRl:*- '&Pq;[!BNb@ ֜F:]NP֠]%DU7btVGph靤,V@taH@ɂWq_\qݥ3H}¡HI MEJNs#>ġh509 ?lWOc4[:ץQNIa<:4최64Uo8$AOp{~&Ȩ!_2Kn1g [=*j}gz2XX؇Ǵ鯱YvkqC!+>+F}|eR8-KSlkSz!5zkZQ\vStum&Lۊ<pᤪ߂aY*j2^r3A6*.ÌhqI_S݈θFX=)lVi@ÕY t*d&{dz#CmčNG4lR֞L*>}&V[hlIH@FL83:ѳ8k39Uv}sH]GI,a^ ?Zmֻ w`[=92I'u'N'ݣ5Te3-9߿8?[( ɾUiMH>uȵQqʑo!#5x} bWqɵ-f3nŲB*Y''x20EG@C%<&3JblꋿxvtBKF ܕ{<Doouۖ$Ѐ w\{o^yJUO}42[;k+ 3JyLƺ4g U}\2x [;~tP2J/ij^P(]BZG,6iY+q%| XiECM Άpu xIulUtKY4O>x؃|f w~R 狚ԉRokLH˅_u/:1KJӡ;*MDşb8Y.+ >1 3zk^J5#o F=j"Ra2K֣mV~<8m~w=PnVVCXX7B RV:*e{ ppƑ^+y>?MQDw^@ē*-Q m9Pi3|NsqI CASz9d _ U,w_࿰&TCN:mh,ă ̢'-"=$}{N@ϸ4T;~gR]rܬ\>)/.kO_v&)Ч٩Ok;V۬|57PL&c*:kSi ָR˦)!`.:C)Fu3Lڡ쵦^=L6g8iq0<tLDŽ;حWI_d~das!2mkܼC/y0YN;;O2LK7;T0i^ҧaQ6A믔xLD)$i ^$XϦx4M+K#2jҡ _?I|ы( NUIN@t7U/BM?:s/W$Xډ_t$ .L2lKoEk\~:彎FCB]oSI$'%r [tJ8}kC݁+[<}e}ʽ]q5rN̅Bx7(ΰe4IΘa: >wmm5 ̳[Ïӑa9Q+-#>ϩ's#9vgUNEz-[G$D"oF?cry:8)9-hO/´<0还TߙV]R1+؆;"@-ś6}'nBvyai3Oc=Y~d" ߭UN)߿Lo~G1 3R AJ<}6i}ۂ~֝U4)"Y̭z!_PKK?E sP@000.npyȱPZ=.IH4zŤr x '9{ԇI.M)Uϡe.ss=vM߾Csinij,82ϴPKK?͠*,P@007.npy{sIfޡ7@O 轧,e[5vj3f\nlq%tE^5[@2}_<>! p뻯 —ojpէn?z}7o/V?JW%"a8i FH\z(JB>LL&d B8cڶcZ&K"sGQsÑp2S_Zw[[!9}_O_?ǿ4rs04ŊFX(ʅL*NSR>&Hw-s}s<1 [S$N05#Lģ?KernX_ l_oo~ɰ,K4"AXsquvT,B6L'3B2dfUPmQACx2O`x?[,vՒ%jW/Iދw#-IB$k{Ӎ\\gT: B/d`h!B®i*NT2̏MͭNW )ųdy1TY_?wrx)nߙBJB«L"bhZjE`.S+Pe\*HeA" ]K8B5Ԩ֫but{oc}kk{gcsm8'<2Zwz4VkN.m X׷&GC^X{j:bY$BGe/ x0 4DHNeXY ˰=WQ> aQ]Z>?= Wɉ|y5592~x;>2|$/3Hzhnj"њ.Hxɢd8Akp, IaYgk3Fwn~fnW:.OonwW'gg4YX,Gf& @ڢtҫn@dlw0ҀAk"\(ɺ!ƒZ{$U^雵󓍹jnWPR%Pig"1ke%kے("- D*HA?0=r|yduݱImVkߏ^OCz uW2@2 `"PJO0,C` T>auheKhj` b1oMgW.%Vw{k+;[h,"܈xrh,W 1> G$>Έu蓀pB,2stReԛN3RZKcC^-%W{b]ojV2QQČ +UD{kfsj.W7|Yڼ]:>P2+js$*l&Pjs95C%pV@H)žtMsr2(("َɍ}MuƳ~d}dq㒭YYl*4m̎ *xT'd=7 SN8!` ͎$RL<AJ|C!i*KG}3/&Ճ#;:;98^GՉbtq!ZB^-oٙfzVNQ4V?0> :#x84#oApd EF8,h9WŝㅅagަZ CP-:G\- KMg&R;}{)|C^ 9@Jxd$oV/D숦5!SBknnz}ra]8?9󠋚/O#JKBs8&{~qJI*JLTA 1JD[JYe&D},6DE ]˶-Ñ\=E<#3(ͰRnd#QX.hݻu{CHD]ђkVSr%m$ AiHrl3hmifhbDT1qZIJUM+QWw)L(x)Puc/ #1iGFAha*iU2 %|MUMWU tٴF  B b!+&TRH@.T\2/h^r$ \H]@NlZG4!YQ Nl+nCyƼ,y# &bCHẙXmܭ,lsf6fӇa_֐MiD̳_]5>ވÓ{kK֤ Ŝ!@A]qUUX *oJN 8MQ0X+NwΦU/ٗQ]eSkZPOB^dFVEĔWWݥ?hqFDN*ޏ@L9A˰*dN Z1D{Y͕Gfۛ[['Lׯ~=gX$V0L6 [{+ݕ Niɶ*XFHC!fp/R9FF%aTz>ktv%C kSPrp\\0;@׺ՅzEh avk-SJSB-3q@EHޤ UR\soggc\gc{?ce* _smdH&T) =ԵgP9]ܥW͏y$Hfiix?بD+M2(psd9?5_\ĕv, iALa2x*wzZ6V<9'{^D D&I dR:$H^-%.D2mX qLatwul\RM)B"_u&CL1R>V%o˰`4:8QU@I `AX uFáxRbn}:Rb,!$UDƟlH a*@8,*v BP9i4vqbakz|fmsA4C"8(* 2Z:a\ :b˝V EME4 4" 6Z /"U~v|*bC0)F 2$R{"❱J&a=4|CfE=^Ev Jidp,I9e]蘐soҺ$H/id { I^ :J0}itp{vQ cᡁ`?!o FMA :Oa7s%l+Ƥƥx1-2^,o%ul=w*:3$G>X QM Ƨ8o,_g%J;O 6剪Vlz4RvI{CAS9`p?R`w]P=)'( 4 .~wI? Zևܛ×2t+J fq, q/0›!#t5Vƒ=ٚ9Ri#~=4ZR$J":X2*`"?< =! "i/. <C_iK$2ՋֿÍ2ވ$y C OSX8۴ <s7ۍ .gYäD(yce4G`es㆕|9;*t,]6T͚l,R4U)z/HB2e`hT=MќNk؞)DC%VX,ՋٹFL9y㐼/DЀ~pt/[!I9ϰ,.ʞ[.Q>oZev6 vb`abllbtܟ+C3&}59ڌ~탱q<dEg/ljZ(W` $%@t ʋӕəɩXerozM.x̨ >ăpx(AI3L˦ALA9L7qSl?G4'*Cc õpUSVh$n(R΁e |n,(u4l;Wd\$r5cV͂ƒ^iۻ&4$7yJMpchB.$ȺfQs5vIZ؋UP^2l0Gl~pq`yY woknʆ;o\͵ڋ{p-3^DJE,L=n=K=عLSnN|r".>g0j`Ld˩e~~&/ˢiӻT:3 *k5 rcU\<"!xn$+ ';gŢ.a .pA*tQ#&ĎeXwWr٫ORU DRi 'f;+[9 )*$ :>t{Hϋڢo4kj/ȿ|8\6W,Ok5!YCA'rtgۨ7,2X4ɄFTq?-=v5ێ<] r'955LQk5|x$_M*J27.XFUG"@뇷6Ƴȣw߿d/^]\kjX.rnJ{0GbJNB.ј]=Ԁ䍟}_~:Q,w?=]X\?˭F zRSjoC,Shtp/(GgFH#X>ńvOo=7=z뷏>99ؘOcL²$%ٯE9|:LXq@ i* m~|wq/޼|'Wg'33Cjf}63BHV$,ddփ7?~^>xʸˊ$q, {pv_PrGLdDYs,NKЇ`=& | Ό,?yA$Q:_~:[bo7_X*%ѐá_\4h.eH뭬_kL $ʍ?yu-aW_}?o޽~|،@- Ȏ# ]ݙ\|w?=I@ƃ{p ؀`z!" ::~`뻟|WysaWPd%)NCVg=Gy\S$ e=DQLm۷9?^\_[ݻ}x}ٻw_{/zA)x E֣29^zp5=;7OLpq Y@, CO ʉ7W)5os3}~:- b*`>Vluf8xgw|r|uz~2l$YP,6VZ2(~9uq}6?RX8nc.*n{:͛G;{gGNmUC! p/% J6|O˗>9OV \xpsPEKXf,0͟>{y/UV$.o \X5`ufIX;Q m~DVɉG0 ]ٛC%O?ٳ{O: \P) Д d۪,)d5%VWj/1t4> 1vg_~'^|1!ځձ1lf |7WcchG|FE5ghS} T DS)/y/xO^?7y]{e` x12Ke 7#@W[ҖOJ[+S/908ɏa W`e~|U[[gݴܾ UØ28 SV`2>i 6HFդƒ]nN2tP#Zz,lYH*_>ޙ8A?D0*-v8V""꘶ŒDX)l.mG f p2䫟0M< ۔8a(ǰ7$q^éCcKbiۮ煣D"+Cyie9ZglPh, % C6gr㍪Dɦ  JlB0V8_lkX Y|;`jɥB $E1>KiT!HK&C I}i(VQL G`Fb&bUtu-E5\@#/hheEdH+BsohP9^ p-9 RnB5IEbFYEU X@¼0+^\<<x~ᆿJz~g%my6/PP e/LA5M(J-[ue5H6H6n@@?X}APAK/$d)BTX'*TE {i jx3i0 Ph(>IwBx?f#3No%  GΖf ٨ )x}XlkBUy$s)'&\bYvp* 2OYI, !Da,@եV֗ 1dCI îKjÚS<*!BtML8=2uX~ m OnJ٘ ,,#JTS8yQgezI܆V>"PAszxwuOx\ۗj3W}_/\euYRU -h(Jq,syPвHK$#D:/VjFkjb|nj6?~?_g;^|OH̛eYB"G\ԖF&+$4/I˳\%4/rkkh0Cg4IgZٝEBD?--||gpzׯJ) vn7hv#iy6Ƀg߿WϞ=3SeKp /08葅b6B2uК[߾s'߼ۯ?ܸTl S CdM`u>x|Vj4ftǦ[;` yx">ih uV~LY0jg`߻N%̛Q4 !ʢ *:58~3vHspsO/LSXQr8*^?pNp<<{ ~ׇ[Z@Xn=ox ST:MK&0t5@hIU"(tƋiJT5?| 0]TeiB6Igc2 ;a|vD8)S ͑j6_\jNMMLOvɉ5}bH.*ѝOxMae n2T6dtċ DAYY\)zT]_>8loo7W7vf2gYkLOl-4ETZfYaX 9˶]Ob slls]zfjE^QvZ]]XNMzwrzfja1o/d-:a毟>=<ڛZ(TZ(Zr,Gd+6E7-SWuCSLE}C 9,D2ϵ36>ѭ4:V+t]#?UfF+Rnh`ʵzVJgS 0FiIeGӁeTH CdK &ayIj8V8rݮճA"ɦRfRSHE@29 JS.D("͋97ᚁ8 pT7IhOl̵Qj⤦ڵ{K7ͽuRLY3Y(dRtBA$$+]Ƅ <"P P"i)9[&UfK3shk7:2[^nOoi"OsRR>_ܞhP4։o)x0T"h #'l$l{Ukfu?X_8=<ٛų:ၑf2J%RˍaaFmjArThLX A"I}uvQy~ldspk22478Գi/2%8@P&^Qh2vWM*`ksȳ*Lwb&9HݔnoY E-ŶDiE&k փJ[cÙqR391½“__ %Dn!c%LG2ʛUbGI A¨ 4GԄ"paچʑ'(yBJB}l4Z3M^=Hn΅p""]L:34B:붤U6ZVh9"'nd{`\-J\T.D(Y(fdoFJ̊hw?F1iIW|۟3pg7B~N5h~of{D.;SnVJ W.VΪ$3&fpO3ȗs|&X[ɇywGp}wHUB-U>oLLKLP비-9fI%JKp) pKqv^rR>5-2Qݔ.oDSA=>r}zpі#IAj;,N#02T"vd3?1e a9LdhKe/ 8Wm=uѽk.h*ɔ;Z?UZl5xubsq[83CcxЂ74 D.9d-0ǹLbDY+ BەݱӣkO{itR@ԉVj"IV;^O-@^S <{eKaR.w| EYdO)b4;_+^v~ހԷ a5j-5T湝6!٩Aŕb\a 9q]`W4 ( $qnFwCNJ`l9Y鯌/ݧ)tl+`ɠPXu[#:7gkc ei ɺXD-Ƕ}˰[Ѳ&kn4 :fzRmtksw68d(Z*A"#®4H%)ODW 9M3hminxɲ]*2`DMJ{Fz#FdXgcWݾY޸>,w2sSlL&$R*' fD\O7U6]U5Dn IE+%$^sj &:!fzB%Awk-/ $֨,UMIx%=|מb@ x0z# URMtP_ X1cqL Mf|=h.7w3L]Ó$MNorLPo}L"slr`{iu{us{BZy98`VT~EY]pLF`2fRj:ܪͬoܘp,~iܱIɶ{?U_ BUK`iiyd|U$P*|UaU4obXf1a{*;3Z_:8?ޝ^ץ{JMNgB][[X_ KK] TrtF4cbKS<Ml7;\Z]vVuobjU1iٜY_Zk+ 8,#ցәǤA4\Pq%ZHUU7b^Z>8_BA/ A*+B&lJU0]Y<@MxM#% !&^Qe_Y̬-{l(2!ٶ F3ZT*5;74/YvN3e*EXYk(@i83@L\@~ dry’ՍՅb7;GyV"O@j>tҙ#͝T% R`@P)"rM.2b|RPrmlٚ.奭kWe n. p:&ǻRne1"BC]'*ϊHAҁgf"Bd3%"csqR6ZHusWwN3|lcWL1ꪡzt B/3lwgVfC1ӄ\ WEY Hw8>99Ў+Ǩq ;T$U 0n9a:jzInL1Ӑ2V$( =Y$=$&Kd#& BZܯD?UHV32M 1_ ?89[]ldljN'12cD3s S# q#7 W4 4Vu#(˚,b6ayyF[**m&*>DJ;\ڋNdKX#Xԇ0>%@:'&'``]RQnYO%v&.|?g &LU,rDndbz\ͺі&1pZ pEۃ1.r]HjTs,M1#Džpa홹X\ͻ> Ő Y2 D^%&o!Y@ N㹄QyykLJ% z7/^3 :H-A~ I0&<, 2|Ks˄! . qr27\kN&IKpW/@MQ$DU1 v,R#\X h8,4I1pQ?Plt&@l:Vյk=R! X"F Gx5Nl+ o,:øðZʐ@`ugMk󃍃 ^ӳN):,\Oqd옕n6m{03:=\3h5L 9~8M8x(*V…{a & );پhLh_Ty@L\]Xq᢯&n6q(8KD᎗.l@; 7|XV5n=kj!4ۋ2Bz2/#g0wJ k?V K4^xQ%#;Ko?tK؊_yaa]Vj@eG4!8%=G[@ + #VBH8x>`u54ɄM9;~y_ -"]=QMh"ѱ_= eA#q 8SbD6hI}O(ɟL(62UR@PLL^>tgw6v7]H[GgPbuL5\eM`[њf& 'A\nN7ǺZQ<+'buAVp/9C / ;Wg|w?Ͼ :$c[-`@y٫o^;>ÿIP'Diebrt7W/TݻO޽>=qճG݌_e 0_}W={mlQDٲu!]yƭ矼Y%$5ҿq׮ыMd8D]4Y#)M.ýn٩Us߿`]/1Ia[L6ՠuçϞ>K)l^ko3ZPO:];?<;?X/l/tB /#V^C(R08[k U1dzvtЍ I1TS! -`oغ{I.plnSD K67"mdPOR#St]>>~O?_~tLHJ)E7.P`Hmqea֪&a+.VU(Ä|sᇯna)1\n͛7nܹsG5_ p:MJYJLMNd|Hs:_(+q?.I11)Ҍ^"OXy}t?x I߁hѢfy7N?k ߄uǀlD4l΅K_Y%lX0̊gb%*/LH@Fn%[''qrYX" 0gWoypf3yA8\FBրHH{' LS")Hj!1qEXĖH%.M~(ikO9ۚA ,-AVK9u DX׮K1L扦 BxGFF Xz<ىAdYZc̓Ŧ.a.*1qWAjтl8>:3ZI7v#1ud*{]Ǿzy`Ke^ZۛLR[zM#yau1^XqU9rك~7gk%CA^ ͆p?>q|ڛ*ҺD2Il*=,a %F4G;UUU,]f?z:*AXZ}O{^7H=0Ǝ*Dƭq(3NշUYR4W۵J;=0H94 OA(G<|X3Mf(ܿcр DOzC1ZchZ?Z\u]bD3@5lܠ o=z<&y!9]n8`,~=Xwl|'TH熗<&o& %=|ҩ?x'{QlCҊ} ">S I Scf,n8܄F2 s]P(v:-X%t@@ v퇏?|уOwslI0N~]ƎMs 馪8n9ޅ9|-$:7Y(@&@ <=~\7xaIq݈a|~t@70#B􁠋Mҵ T-mKp*i[u; |bz.Wl`NC,_"bp|@M!~CT [S]7'3x9Y(H:քK%lP7.aY'vKQęP((,(m^sLZuWB8}hh~/Z!nhIO3Pd jo-Hz˻|#}vJ7d.``?٢d:ɕE{gze@I_;HUvdVaab\0U[ IXQЭn&BwǯKc#ͲڙLǧ8ɶUbؠo$*ki g%\prIWeMdtJG vErQI6 AK J7eRĚ)H]/3:ռ[.‘IH& { 0J&3iEE2oi2TJ ҉_3Xq!-Wʁ&b :P4S&\EGbB7y[M]yЬ,^%uz0%txE&Źv=T!ܢѪ*!nqOnXAuPZ쭄P"!g#=CT3;X)F /&,f^!0p* ,G˜Q E7/+VC)ۙHA6[f02V4.Aj7`HspF^p|W &[n2^nP< R@jlhHqn%jӁ $pqiO =[d45OhF\Ch%nB,sFЕx&pYŮk<T,V֝ŒXEf FVrӀ-iHfxZw?v7hc"&+hd5ܝCV2JUbJo|qb$ٵ-VE]bwZ/RaC?yoL1#~oSH&3x› ,jrzW5PKK?xb/)P@005.npy{ו櫜sF!g4n Lb")R(QYd{glϜ?$%svxV(ww?ή^͐}yZ-~+}>y'O^|^G>?r ?:R <0 (,.YdA$^`cyeYamxps'"!bFIOJyv~ӫ>_?}7?Qx(#I_)t3i׏_Ń?/<" HŜɲX'IN$xgxV?$,'$I҈bՍ$Jd>_޾u_O, |M'ט. .o7t$"$ˢd؍43p54ET؄ke*H l6;{WO ϢXOW'\Nu+p,+]]d*hG vbZxaw"е=/BwʍvfUh;TˑTCTdsׯ=}hww~~؞c(^9&й$Ɇeii(IfRV+9vVJpxիkRT)Sq,;7r AA>`dcman_T}]j& p㴘*zgSmʹ \ۯ?w?On]XnQ*$Ѳ#a4qyߗ^\~O`'}[ǓH?ej_8BizٹxiqucgpKN$4Op/p:/.p4mC7`\/%i>_ۭvG|xPfe9k jՒ+,y.0hG ) p, Uj@.p.&l89Nx#/rJo,t=[B/aeh+2nuy7\bT[~ WE4a+ I) \r0L?7Z;X_]ޜWfإŅ{|8~qEr}w Ӥ8q.Kj1K$qxET74͕[Q79޹xhg|xwt`=<9^"+[%Ճ uZX(dJ4 :O(G gt訲3jdv8.-nf_Ѫ;œ\,F=ͲaXb R؎d/k@m)슐 wN'5^~ȯk}occ2)g؜P4/OIJ44fCP$]KH Do^ތ8-v;+7řG ugjbvP.;NjTᯔ LG_-4$qZH\3!^e5԰8;Y\ݪ> JP)5Jq5JjLxzF*Y5̷_:uJC%Ќܨ$, طnb /Փf*˧Ԇ;^~(J:Z\]m8#f4GHyr qz20+*o&$߸]XN&~갣h%|]ڎ][ZD#Fe 3$!>* !h*)/SoNַ&^x׹V:3R'مLډSБWIIu\7gSbe`Ⱎ^Ed ]CRYG秎P'n.h=8x9>։/RգZ攪nSO#th0SMrm+Q,6Ғ)p~`i}ug{ٙ6Vu^ `D4(/wAݨlc6zA:)fhA+PjnwShzqi[4V'ۻ{Gۤs藥'b9ZoL:,_U>GK?n`Xv<4 _5Y^ /ETQh,`vY=,%~9GlFZH#Gu =Js=}ASczç[Y"bhP/Yc3tzRhy3t+ DĸQ9$;4ٖ'O>zI!>i'F>$9Am[mZmBkC#sX!&)ʉ.*qҜ8oV ؤ.hƂs(-ԋ`B7ǀTu+9#6Q~~`r N O4r+-[QEIWMQj%+!F(ZB%'MT^»ӽ(t݄da)wftm8 |;Ok@,I Ց _",IFIj2˴ťwnG~=ۯ\u% ;@-O#c2;^/(ʠHEk@W xSde M%KmIfd ^9>]Vdl~풺L>(a ,(47fg'==sX攉%CLD CТ n}bq{a23zw,To>)>~@oꦩF8-5`i{0 G*0{dSHe:NQB0y)D6 Qo=-9dr|x{WlA3eYEb);,9~M_]Fx~؍U E %8V,&A䜯2ȒI]f5il6͂;=8p'~%uHK\諎yQ9-4մ1ӫWfՅDbە,x%= J`$, Fх(U' bhgk>흭ݕ͝{O?ڣ"Ѐ-YxU2ẂGZG<4p"f! !$**cu/gkR58wyrZ0p}ai4?tkwUZ@Sx+My~!YQu0#}-1}=>,׺`m\iݤI [4~4 #De 2<Ā ah!Ha1*D,>\ N4+`TYdurʿj0 #tM 9,)#co*zW \Y*\_qY2sTVZQ~Yϡ6:V9Y_! r[HFn[<[׷7;=+Rys3dYF0#F>6+1p"r+P_&L@d+o+)]|xvRx\,Vo0b)~.D(ߡb ,/ET5z<1okDnH=â &<.m_; bOe(YJі40YŁxNR!A$ Vx`Drv@Y[@l]2螱 1w\gX@4%+믲}y)r+~mΆ߭|nټ J1Redh +,*4AK4\c{K4/[DXB;E֪G!z /tFCZ>0OZf B⩰ɬR%lo!-<+8>_FU51 HNTղ]Cб(pc "4;R`ȫ|8ɕ1l) 2(tSyJf\Lb[k_ݺZ: Y?9\tC|i`k(@^uNC~D9 t'# 5WM{fxb^RS77ǭgro*k+l"1,\ӴġKVqm;2i3ūn;7<"7./ζZ$Whԯz D :DZ2_WtP 2:= vZeoH,&pI)Ѐqoquhgqq̴[ pTWR\#q~W .(@̰L=b G`,ʷHM_} 4:3^;=YZAcCCm flJRqapzew}^†ئ;S(ߐ\X?eFwZQi*b ̇)L`pv0ll_hWn \J$GSӊNDrT5 HKOPE,B~w5C/<`@ay^\ }f9֧j| J]7sK|6,Go馭Z蒢zq~8P];ly ta/]8~m|aTHkDF7b^sz P`5 ZS$"<| 8ϻUsSя`*ZP/34 td[͎[fB!MEKO~Ý\o:שF<y[& ӱGCbIC6KHq_~ݺ񳇝{fQW r6N@_\T[~=Ftd5y9vOvɠg/GFT(3b%;ކc{L$J,mo صMr1-U%?kBWbDqt%DSXKjqw>yvLE~8~mRV*rX%z_U_&K%xq?d^34J/wn?;7WfZ39Xؾx͕ZV,$n!-T+zYBw/Y@Cv #Z* ѿ޿y??Ńǧ7~O}֍{num\̹g:Kh'<C89u'h%gH06Bk}vt_ݾ{g>y'۷.lRᦅOEbϿ3d<7B^V r,Sj chPD<`TZٸrߺs쭇7n߹sʕK'3^YxeyA.~E^bOxt{A8^LԐ3!&T?{>5$~mvq;|W_=aܽz2dž naŻqO?t?V /Qs߾{8tW {,d'D`nu;vU}frOwg;؏^IL*pz<{чO??K F!EixR4Nq#g8)fĹ|8jH%]'O 2ɒQ {Ϟ}_9%2F Qb7_lvmRcuRÍ[F;Jpa96lX8ZsWi(rۥ=]Ⱥw{M1+gWozǟ|}͗|p05M]D}O5h[=^ ߝ:?q1E䁜IH'*jRHC> >{?{G_Ӌkz(J{噒(E…nRop<$z8y\zooE:XȐ8/->|x㝏^wڑ AfZ/u䌭Xׇ's8\1KIpά)"K9Xo_퓂)z.fìff08q>j5 64L _bR[rhtD <2rl""tt3^L \`N8O'XR ,q8<8)% 2 J0D<~:Y䰠W庆uv}œoa;+#x(5n&(@ɒN߳0pf \,IմLj6z&Z bXJӪRVlxx yr3qlgqR1h^Л syߴl@ N"nCnBS6D|*B$ ݽwG)]C|,k_`zњed{לBo: [,q庹WJ`u\aV߽чoM:  ,C  3Q@F9DU(*(W29DՂkGM;^|`qSUl@fT3ǃ2N*>帐FtfЮEn jTwC *xv8 (DKJ52tBa-dDl[C OP;9 tӲ)cB:cuC7 ,n'Ih6y.vԌ8jx~=tU-*2Vַ؞1NqE9[~Âx-gz@w1σ p!, XiH)(u!)530}ULˏ_/L@lG\QnbHC\  y9! % 3`M §փ7΀^ӤĮ 4d2}H#p=ƪ_gzjN;y,驺aCKQc ']N?&Fڈ%l:1l n$h2A &<cx6e+ˆ~ybQYR(qX*Aj3;SgS˂LsnYXHwBe46iKx[~`$NDs4S ߤ:LW 8orE%BXT5|A1di Dzx9Jap&`+8Y4Of{U_؂-$NKtSh4a4Hύ *P$,@:xTԴFT7l)%?i+c=ktuX*s:'Ű/bMz>OOO)KEaP^ŵYF6\%Ѩp` Td* Ɣim{(1^5Hi":KI͐>:V`=XQ1)k3+s 1 C M0Z[vG(@GL,nYR`iT}8l 9vrly[ťZT.E:C PǀTq "uTS#Or mj;&-X+Z=PjF#K'ʃCkH1,-fD2{n2v E]jHX>khfxOU2KX^9]U][&J+ iT1TER̰]OLTUa2YZ7HSM{I^ipų`=|8TGw%X J`q: `:U5vL p' ge*z痿ͷ}o/Ͽ=~x۱P 8LGhtqyec}{A cLĵL#4z{($%P9Ucf``e,`Őt F~8 .ai< É`πdW4W"8Ws%SqW_y?@qXH8 #/E$Fk$ʒ ɠD!1Zެj&˭V,H}?#?,T,O( ìf9|?N848$J glu(n.|tj^=muMr}s aAW4β,L4Z$ (L* }ZQd"jwomvOONW㳋֪$HJlp1 7j*OL]/jX93lӶ0ѵLuct"p Zӝ-NY6&[܄Lt5rSkƸx!`Ҩm`U/zT87\eqQo@`ZͰОQ;QӄM#D~W?qTMt\~a&2 r!13zZ na1v'luh)kk#`4ӳlǵId&i`K}yB*=yP '[%Isfptp7wvwjqpr0Uă Lᷚ˯<јe{s?*O%xGGz~qlyj|3~'oK^AT &! uizy"O| b<O ,Yrbq `_e&IZ^= J]Ï00EQ1\G bU4SUJNxYmaTַG7E'_;*n뱥QlxvoMrxf`h$Ym2ߎU៝.x^)Rcpe4MVv(IjҤ^T>L^^J,A~̖{i(kO:B׋׎r'H!ӭ{ѭ߸IѸuF%/5Յq8%18sE]U7䉣)?I^yuA mt+1Z`8IJf& zFM&\`sl#%E85,/ĵ !BV FNlj^1%ov0tiqe^Hw% /JHZc 9iezAT*jy -L]F&z<7V558O77vVˋݺIӓI^ͤx<+zd4,ooe6=[jРE2wA4C3tKpǮĮHxt׽JEwu{R,Nf;Kव|iz5ז~ &4.yZ]`4'2D{,3m'ϒIY 帥Å~g9(<2V7.Hw.Ep5d݃ ob 3H[KTr 6 XH5L PՒ4u+p*VqJXaf6ݚ7Z FٻVѪ$ZJZO1BVyKN膆%U \djf5b(nd+nTMwhJ.x[u[yzTU7HRO@T`CLM<_nNdL7|kaTY.C}tS &*U׸~ kf `DңE.vKa Gyaj@g:T$Q'^:I$M˜I2NA/k{[Ud q'!E%tY#nH"b$dp{ws )\unm¼FmzNZf)#|،CH@KdCUQSYPZ4awaCK>&OU3!L 0;}X_=M8:^ϫN4'%!Zg\'l2wWƋtjqoainڇ][oik47ꋓcd} j4E2‡G.eK U`nXuB]>^bllpa2m_3JkD^@중zE+,;)[@ؗv;o!`܁u`D(fM)Vk`o]/abՠ4]hMcD}43QHqhr% k^C"3 oRk,%= >&/FjՅ!ttGlmXgJbM! ʂZZoTmb@=p?s SK~Y Rٰ:*eQ5w{KKE8MMOi`Q4T,z<1~_CHQ>1A퀀R^ݐy ک8k^@LϼvY4d0tg@\ݬNۤL\`s j%$gEp BQFǒ40(Gm@E'F:8;0}۷g$diZH644JrNMsJf1]G hwBzImP#%.,Rk51[դ0xi*ihōӓɠq6AeF ^ OnHu쫢aXcr*@].d_5Aeci87Z|,ΗOH.0gWVf%HAAVq( OKdmsQ50HJhsz 2FUVu),ݶ;[.Sb'ٜ(SdQ+@U㤚h:,aw^O!WAI+0aA\$tkh)#)YeIon,zgxV"qWIdmfW+ Qiܶ_ŀH&Hh6QSMkzQ簷`p w]W]/bg< f.K/,Ig "Oqjl+9 (-8zGVG&!5B\Yk1,ȕrX.ܝ9:tXk|W 4D^Y@n)6 ?Qi04Nt3׎WI9*f w`Gso|:X?ݞW@ `ȥߑd3@?èK2i`mJw_/`^T˴6XERBō燻R@"iG+rL -8%e G7!BgklB1(ug:!)/)lp)P tzhCSk(͛"@rPf0)aQd7e 0b`vK"`!WnKPA_xz?ݘL;؊qD0"SüfWTƃXSK?|  xDiIuyL_}3+,R;YnzJ/<b&v!: & )K^,% *Ȍ@F ` j?2}1Tщ v￁sNPn;\:uW@cyyEbB q}"RqtqZ~syQ;[y~'82k``Ȋu4rBD/f}o%ei)?PAaz"r")~-LXX ";_?>X$ (sZ(I*'z"OcIt;oUI/% GAPb&3&Q hϞlgN-p(kVCu%RH%]4)))\yΕ']ր衺L,.`fV.P8=6 ^9XwJz)t'"&Q}_7Q 4Ri 8AaeNBPKZ"E)jy$Z:^Z=MѠ.y8+jXWkO4TCa~ [,(2`:NON 5,'v5A3[M&kKnJzcDx G_UDF: e/X8fanY 1v`VZQ,̠赋Zc'г_1>?@ PuT4}`IN>fKAPBq`7dM30xx{;24$\ɾ4DX+]۱,K(Ve`؅Ϲb$QD1f_,]ċw1$v+KW AP7\'lU|>XqutDuu> r=&) W1sJknPdL0kں1o(!ExBF !NwZ{!%qx@ߥO[IA>x~\gwJv⎑O8왣J,۟,N~J3ʒ7 ksWe@?0I ;KxRW+5QqؖzU+㋶ ht8\_Rnd0iInƁo@f;cynQb 0n;߾׾m'sYV%M剣^iL)ctk?=j#"*+;L)TMM6,s~v9;;'wn5Zjja~۩ ?=>p]hĂXRC KPiwٷ,+gG׎o=6k|$E*~'X(/E!-!C@\ϭ|ogҾ'?y}rr~7kIyRv{aC#/'e,QU7tE $E XThu:9}Ï~߸qq~k'6lLReUO3XϱM qkH"]t*az_lWXsͧwmmܽsuz[T2'#Nigo>7K-{IkDf'٨?hTxi.aJV] ᣃ[~O":;35ۡe{o ~|PKtF$)Vһӧ^ܸNI^ ?jk<?>b1LajVqIw>_><ޝ;?0y No۟Nbh>G"7,,szҀy%b'd&NU v0aѮ ֮7nY䲙C2ԭ 6={[~@orG.ii*W7֎G0"Dz@$*ÓÅ^]?  ԱGA p8uML6n>z}W_|G.tNA342nr`hȠg5r5\Ŭ><#`CV~߾>(zb:Y3+w|׿^+ mv@4b4ܫi@Y<"r.yFbͭV!$W (h?|[Oy 8$a:R~a* uZTǾ>m>< l=CDn*K˟?HHL1PL;r=t)\UK6kOMt{6nctBx=}lsFSAuAKR T4q},/vU} րYQ;(+zjkʼ &b0bL* fZe8\-W)$ sfhsШM^z1.3f T"_qa+iN˵~y,[nT?jJfIUX,>,<3?2.-f9hT ,(8E4w#a e MónnW]|e lWe 4ST0 2/?mͅ8@-k*ns]aMAu*۹o;V>4nR@ߡ2RLMK#`NP\,H)`W_En 㧵<+Z./P2\i֪K5!B_TYwub; &@(* V"W0 i;y72DP1%b|Y1īG,bSPaGDʑVsk"Ү26iRT[V":9#fIal`%ЊD7i|uEqqMrb6E ՎE6N+Tv#' tCP\4w!O( ¤56Y ,~)YJFj4P3\] sWP|0ie<Isu]Q(j)DUi>D)G[:&!̊>+slShQfN%nZ[x)F U襀؁t0V/<E44}F41y,bT/L'ܘ&i2UzI9oCTC)}Y.叼Ǽ+Ge#|xO~ KpdYfh89A `nDʔe]īD;nW?X N uH%QsDVYe#sCWN Tp*5 )#RY/@˂O ,/K JGGzrE#O`<F,n.Jc%vk0V\H 0qU`nmw&ʂ=/{`{X ;oВё!]2!7:n"(5E(@9dL(jPV+'߳:&X 1 MBsҴ6f/Lf/DDͱ1˘7D - 2w5;ӝ̮,nllonm_W^XY8Xy{l,Sl`h}& #odZ Ktkn֫rZMMO5Zs5t}lf斗V7vwO.NNNήnnζ7__oM[9 y3(~,XM$]G'V7fZ^5`d^oLOwf:m6|ͯ޷wNϯ_>=^,-NJz=t.jD;,q ¹IV/'F&&'&F c#CCÅb9C֞Y\?>yxvo^tFT/xh==xv[( &0-("}~{nz<. p8Edx5 BwF"aOKIT$k]/Zͥ|qQWA IfRMPzs6:2iufWxirb4?UƧ{e/X6QG)-&o ,ˁe ǰcF{Uh N>P(-jwT.&[Z||fhnԭJՁH,Khqx<1NdUع4P [L&3|+jo #x x/2DMxcZKwwx]ζ+tyqnyqRWzeb|"F3ګTYV  ֠GGv 40T"}P ^ Jm1"/FT*W>/̗KPy<<4J`N_ Rj>/)EU *H6,TUITݑ*W68s_V-F';Gphcm{kmaqb$BʼnR1[ ',#(V=[TK6S,V&|3s@6,oeed'&.έז inw]oVFw+k\Y^k7+b!fF|.s,p4C "CyY=[Z^Yg>فY,*RNS^YIO E#|5U1wv_[(t+pn$.$AOh@KS:>>֜Zf|to8M!_iIq(}yTۜIO4Ā)`#ȿ9mD>90Ģ4@?$`M5\Lu(LlqY|52眹H :Xq77"wRK|XQ9&8BzUT.!Bhh 'z?&KÃ}vM~Icbhr:& [p::4>LL:Db9خOLMrm؁#CPa 0gz<3CpxVZ<ѦԐ< Z>J6Jd9Ύy(x:\F30{1f/Ù[Y c湍롖<Z]Z[+?01xl\KZYYZ^] M+C+m" m- RFzDYjLF>YQL2$Z Z|5G,]V3EJ򃹭Ɋ60ZMbrQLL.!g`?Àp<Fbㅡ\mV)# ,;k.ꓗʋ[7WG'[Knytn(tO(]NFR#^;Q".. M +nl`hen( B>۟:YAqUV0nV<;;>89w?+gőL! :WLV,fui$f`"xѝO/n&+\ Xk$ -@NcXh^MY2chܐ<IEܾP?Χ<K"eH&fb빾jZAwMIw$-熃9"ct݈K/1:ظh 5-zG`JN{Mn5IaFv44MtѲ06҉v7G{? /e˒P_'0 SL 4#az.[x<6/0&1 iF~pn@VֶP=d<$K4".: \P#(VaVW<L:q`@JvZFv^\_茓Ot1d9& 68|iϷa[vK2} r"~bq84EIwH6PdzFN 5C¶|1Z_^ڎ}=Y`cAdQU&IQm[+ sB C@,Ǜ4]m, F#)2&.$z +&h8&wz*ݹo&=uPI}e_K@MK l8CPi%(ʢM"I&"0N%4a 4X1KkH2j5#cYlc-`[-" kGFF#͎PoԻEٜfAGuɤ"E<z2k4i(V0wPIUk#yԘ]iRKh.ހt;܀T=NnWT&=VZŕZn5C |X@;YRxI!) ?b^aX57ۮRnlDHФId8fXK ƌ(+.# )K_"/SPv`oOw[#)7\*vAj@̭r^`I\A 0,Fhȅ1JdS<^̐Bz3Nt́{y5ߙ.^giY>mNrmG2M@ZTY A٢r0E0؀1ΕKdsiohCXw7Ve<1!Lv9-D896ҟprNDbhE4r`~)xa1Ls';p.ƪde! X#:mǣ6h,.Ȧ&YhQ`jD  +R *@/8ь2/lp3F0(v_(^b=9/2@0 \VMST1q&W$4s(ʿ<eh"@?!A6T(6 y٩-'Y<90p #+k4,6",C2fM@$ >8g…/Df 1,h %i&` Ϯy\½51 lgyp7bUͤqY!x^l1j q -"|(BDP73;XYZ^=e0r:춣s#3x$ɽ6*.uBe72 Td1=m4DYg`fD381ࡱ䘧o~u}lV֩DcSeAF$(<;5?x5&x\NJ#xHIQߓxAPƟy 7B݀.FwLIDQ8S2kR5W㇉݅$Sn/񯏑N¡eSL\s !Fi{DP8?D`; y^C*g,"gvJ{Ȩ+pW| D`9{8jY(="iYވ&? =1b繞!zKt/\io028i !>N! 2 '›OfJ$JcEt&FV|N2hhPԂuQOe!y%0Br ن\b!EЊEbȇ~GXL# w_ʱf6\@$d)V~E{ gpKɄ"@X (p]#YyoPK<E,^(y+ve!_?ߝG P}(r5Ȁ _qt( A-XC.L c`q((Fm.)tP T*[vjgbq}[ R屁Kb' j&̗G>BQ"a:$vG3) *6VIVB6jՓA51Vw:r230O념KvZTZ~2~J z p Ԓ.+s:r>(e͡l]^\X*Kn{`Q;h2◽?FjEfCXAuj qn2h PyIb]XʓC Hf%"bURb@3O d/H@^Tށ@ zX(n %9 MviԊnFәDfht6CCKCI3k0{qHn$aPUUQ(H/(:d2;V0 $xݞ$h̪2@":1ޠ "~oA7=K yBeM\p$W{ (Q5ABpݤ;Th _lmoT~(ntM&فWΨ40Q_F(>`6tvjs\Y"קG;ۻ{33 !YVÑd"4f7խ(+e9%?k??HLcppٽޠӭg6/.NΎv#P(IIX.7 T[7Fk1R*A~.>èۋʸqzl 독D>8;:8>\]Xޛ'p24H 8bb "xIk!f?ݷ3!+{D]UޭsT69:>>;:>Z:?:SSCϼu#۠4::qJbFt滷'!7ۅz*3'g'';ۇw_Wfx1T!Fqh"@ZdJeG'볯_ӏ?\w?~z\czޙՊݙՍ7D>Ѩ D1K $$5@cj:F[. e_Z;~揟޿}|xNַW7WZFV.Uf;sWo=|1~Ήj6ih$ƤCaVeAcOd!_\:zyys}v}{~yusuuu~uu}syzr|{Y[_??8<8xWu[G@R#t6ןG0F*ȱ8EzWJ'#,C'Z;/~ÏwG'h`}y÷.?3͝lÛvN0'A^ZW~͢p_רf_Wo^>zxoǀP=IV ̞^{z캑E 3ƿ ѷno^y{8]YY^ovTTTKݭoߞls @Z1jՏ?j9 q,¡T{SiJ n^x. XkDBa^]^޾88998^\\::~zd]$K$%)LϿ7?};aR(PbDEqt*Esb`J}8Ig'7GW'77޼oJu8bAd%&iK׼,Bm۟^=ܿ~v3DHe tM7׽z=ӄ MJ^<˳㣫Ǘ/^}R 9,yLk<Tl9!)WՇO=>IFD%j)FEj[K5pBzn|zrt?=~yuûWq"t V͘Y& /_~=;%|+Nr*hc@G ^y}}}V_=^A={xx|y7K! $\AxXHLwOEr E "|ME,-ɂysnnɆ^C?>׷/nn߼z{J\^êD/7#jGj P"U>VWaXFg44K(J$2dM* Pё;?8=?F뿺<|fN7n@śD#Eh{uA 8^ܝ@H2H!/(2HE˽YN|syuy|spxss~}p{V ?03S@e=UQGDSU<?Aj;"2 :x-wM K|~2 0~{(hvj84 |7F[^k,eS'/w?"H@gT׿w߽yxx}b-r8}}.G" 3Edq- AnϏ_7f5*nEӰѠ ޼yV%$k>l@CK $Ty4=ƠSn\6L2ym.5UEkWO~[HqOo> o.g5ǩZ2y1C =/@J)7?⠛lV\2IٓEUr^Bb}7Wi7OwOOo<ݼ}}J;Z@M2 7ǠC',XTwvWjOsv V $*p1s~~x|zrxTNj1+7Jo  Ř ='Q5ek<^+|TAb> ݀z?}۷yؠhRB1 x ;tRfq8mt!󘝟'l@5'2enwJ4n6]߾y%z'nVrs#r,>!@)LU@ f]0YAt{Pbi7 >+\ޞ]. <ﶃnٞ7G{9!zeMB: 6?6ؽ&hSHFÑSFB3e׽Ý㋫7Mk30kFV%LYUtD9NW_4*;8:#uDbUļPxNe˫ӽCt n)&D ̑bS$UZN©l:fRSX+@,p;d,dLJ<=wVM0`nQed!'7ȉx! f(Wfˋӫ݃W3G ) E# =dMF@Fl~ G`k`eq_{$P5 Xd\t⟯)ocUf>  &H 'sX?H$3b0JC $[9`Ƥ rx(^w;18i6N"6I0*a%ۥn)δ@" GT29VDA^6)jPP&2GCZt:,{nnSB"p$LE@}FٗoШ!̤X4fɐ.(x} {GCz8%E,n_1<tIx{1 ojb N9ڀ1mIbBj 'ST*}f+1%jh%$3 @-+f'7퟇Shu]χwxҀ38ÊK(dӠ`:cn3hK8H(j\@7k#0Ŭ>\"ЂGWʐ8J@r%B!as6l>ϔsͦ \DsifAEͧ}55|nÂ[+Ap$ьjRHfD~t4eWG2l WQ|d=(Pw{B p8txpgxoCje."1]dOP!Nj9PKK?bz.P@008.npy{WwcGf;x'A zgyoT^RK-jmϚy9saF^$Z={έ" ̰[K{4BW/.'[Wd.~'O_^7_={zʕF.ҹ!+IC6`X֊ڭXu|^7કJb.ϗʅbR-UcR)/Zp؟N&gWvwN/64-D__/o{xwVh!(` hmzj۞Nxl6*r)- b2VJccRX53?55;ttvtr|RbO^}_o?o~'( D0 ͫdoXZ5[-XBVTJ z*R//mnm_\\\.9g0_W?W{ SO?}#R4I6+A${8ӛhzV6?^Niu[jkjeݬ`znvv47;3=YZ_^[wGI޴*C􇃑T9]/_^`h}AX,V7&^Yڝnha15:pD8Z[ZZ[\[^]?ߜm^ucNžeA Ei"I8՝>;\Y_^YFAqcVSUc[uNnu'FsL_K-kG'{՘/yuUS$6 +Yci@t%*ANyxZ3x!OetX7j"׶wv/[f4|4ܸ/?ܿ=FNn@}__}B/)jX¶xYENDQAX/+Al1F?=;!,VjYm_n^'$I;T`4J"-FQ6E?.8[ f8c^KVo[!Agle ,V+;z{nuBx>!D'Y;6b6;w1fTGh (jr :$ahꚮT]vfndȒjm\ !q 08ʌ(2@~/,׫j*q- xJ5g 8R x>_ye8\Ñ-7|k,ПMM<2 DX<M҉ x.=ihlmlmCFf3:TJ&wtp0?czqeW|=ި*<73-MM Xpq4DST2OqHvo,/-Kv#_ WW'ːKVVwwgc3ٹ}rrw ZȠl27>OyIU;^or^xw Ax=WXR.*`EL$1 D|4=BٟƺFѬw'TA =~rgN6WWfV76kH4F``nۡC3_s8!;i@){Fـ}Aiڽf&bT,]mololmm/ X"kH͐TE ]tաuEk.]X|we7YY]\r8aO^w8 &b*/u=@ "ˠ mVkLg #Pr^vy}DdQchANvfXҰ'KǣqgBخVaBAT[e5éh v$rb>F%U`dgm|UZ\x+In{R' M)rx[!+5ӯF(n+E#~&9brk|1x*ՆZPtE6r3Ai&X.jx ~*`#X~]Q$I 3N9MhKS5ak6 !2Z.e6a!WXڐ3J;\ͮԳBs`D`f3+Y)gk$RbQY\=iWn'pYϔT@do7lns\Ou_Q$>~Ar㎷WJ{q~}{puzU\^6kx{fUm'u`7b6(X*OF3J2F[N53 [wG?sqttvsr~}铚+tڧa'57NvzuEWf'BJ|0:!~,Fx8IVbq3,ݒ#T=VF~޽:riil.[i$p Af[юn`w6+,D8B>O0B-Z"rpZNs4&Y:՝{DgrԨ" dgz\DP@(ڪOjw,q6pCkA Ľh4ΗՀCGp `&0n K4hczg;I(̡J#FǟLTх(#P:XK&[ `8 ǧ@$);ih E )de[%QYBZy|yzV^s $Le(d ޒmπmHz+#dp9>(^nÕ1lH,IdZBn'F#e=83 ֗V6<Q BjF0G1"98@ \DvO8:]~oéZ\&yK󱔨#=VBPA+"zV_yL!d5'Q|}PTMl vz |Tr;C)&qKlN1Xw}m_]^X,w;+yGiEe4`>yK^YX]XZ[mVׁ0-,\NvE]eZ@!yFwkgT8F3@Ӝ j~qv#) x^e./4 @ t )DC[X[ǽDb! 9]w0y::J@d@F.ͯb _~9\Y ؜X\8:;Cg@?x6дFM~ E{Y90053;Uh;=Z'z\Σ(f0uQH@U ّM&"IX!oLԆSj5v+3!ۈB. }>[\? &fWV'r^@;Ϧ3qK٪sz K}|vЭ:Gl\׫Ó65nVN!0($( A-A"0D EA 6tD:FoH5痵k6|w87h'ѐ2C|nw{ dMl5&UʒCۀh)k!2 gقb@x4\dXύ~{r =W":]521#cWeq@L!'$WݐUQp??A00Ȧ9:w6P9ck1TA;s"M_pԛ&|RUXE!d(v1B t<\#x&JS%9T&6'F+=AQ'wߟUѰa4F'' o>O}_.bE!v;TL 6Fޒ @7(F,{vۛ gV7nL5Q)~l8)fț_nr&a5yz%CChqk4e)t+`d'('KǛ^[:t*)?^a!:IcȋǹAV ,FwF)֮Dp{Y3rRvhu:AC| D 2ఀ1,-b}YMXIT_C(,S $M`<[j+X?MB9UîB!n`En<谹>ZXĶ6lp1YS4ep4P~7gIxsBg%sKo*aChgk_-޺x(b8!J}r}s;I)L+ 2 ƆAk/1B _I`$+*_lk)sDD tNgFk8vY{Sd4ePaS_}ܯՀt|phg EHxnn<`!՝d@H,DZ[mݝNӝr:|^w0 |jxowBCɿgf^qؽ@07oRyaT@[;>꛻kVJD4KdAq~ztO6d f$  nAC$|>MM,|{$+'R.=?gDA6(K`6J$.^;]0C};/˅J=|vrr|zr||twpux|c5v,7DCl(f}No䥟]^<\if޿wgS _^_on={3@U| %'p}$kMf[O?Ҕ&`Fq ߄ͬdK$rm+ˏ?/?:8zݧo~/S?+x(Zr%Gq9~><6a(N4GK;Waa>;UV_>{ûWW{ǗǗw^>t}8Dn_ 89x hTt/yѓg^!ba0&p@ ={'׏\o̯mE]**ck f; [[{~xz}3_I n?qݚc1, O=cagY]]޽8?_l^^zeT|~8 RD.YXoNqPc58 Gp'ۏ^>{B)܈`]#u.@{w\Jw_~7~ía bH(̜g_9p>|4j%y swXFlIu/@__}'/ǯ>}W[q!$9)fsN -N-vo_PSH>QRGȧZ8 cx7?C'trw ,EHW|Sy.HL5Uթ/ޜ_\bR`d* r@@G ^҉VKw7WW=|٣|(`[RTL4Omvv0 vm d0`a넆"%}WWml['gw=zӣٜ x2xVZ ' ?c@24 "Gvk[VT A,Z@ K:/v./Ϗ|dry\Nwć(L&lpqt@`[U /6嵥mк$cXcɀe8|9,'C!(-τ/O% >])Ν+{˳ f 0$/;Htip^@|Ʈ~C@g''JH K@'6Oa ^#U'1vՅ͛ tO]X7I$O|''ggwO.ti9KV 7sUM.YI'^|GGkk+CMSAI`!X?"h]W߼x7NONNJ '\\NG$+r{۫MU@-9]틋^}zųW>zۏo_>yto}2ʁg Hx~GN:^@w;X4Q(㤸[p9%ϯ"ːp6< ϟ<~gϞ}/^\B<946a-YILQŭyQ08XA,+8r( J?r{Z67<] Ɵ"=[*eF`e\myiazv_zل]5>d5FqOx@[S4ðݙ(jeч-AĥNJ^'ToF0N?y|"L-Be9gYDWY,#*Q+J>  E{\*LY/\Y,{p7?9?<~pLU|K<-"qfƦI_\#6IƟvUN )%|V q?O!EbD Fo8mӴ?,3}G%G;TCx#+e lˋȳc+_fR4 \,Z\3ϊ6ܵ=`8[zADbtɁBV/%2N/PKK?if$P@003.npyPKK?AW0P@$010.npyPKK?m< P@U002.npyPKK?i7P@ v001.npyPKK?E sP@ 000.npyPKK?͠*,P@007.npyPKK?.*P@006.npyPKK?xb/)P@005.npyPKK?{i#'P@004.npyPKK?y'0P@D8009.npyPKK?bz.P@h008.npyPK GAscikit-image-0.9.3/skimage/data/diamond-close-matlab-output.npz000066400000000000000000002664231223313777300245120ustar00rootroot00000000000000PKK?Qv%P@003.npy[[I{LnigmMN"GI(BB9Y`l0L493_Wu6`,UUWuqKz%+_U&8׿%z^AM^-S?ÏeuqL" -= HgWWWX-/2233_XXXPP%;f>޻}ֵ?TԤ39p4z\.g=L{}k:3@QFQ:oܸ KK >@t?} dBM\gg<|LTv~S?V=bώܺqR HG8FZSSG#ߘ@|6#53o'^N嵆@'ήNd1J?.p)o޾ ’XXoOOOˉWk~"@' s2 8Ғ򪊊rNB ? 32=| I^  y? Z)>.(W*2T*)2Q٤RTrA 7D_WW[]Q\^)$&\٤ E8?mook 3Pp86fZ6iw]n8] aY- l2 &A.^ruzbl'}@, HhiC@  h3F# wvwmmVm -?G`D-#E#ntvut;vwvNw/V½oOG) X "PͮKwOwo/z3TbC##}$;A`Hu @w(ÏvuuDZ` ahP5 $@ `{bĠ k>824:6:::܏mC#C#? !~4yx|f.t: N? CFۢ;˻; <@HP!|o  "w⇇{|0jIݬִU͍JBíI٨nitZ3f3:YvnsNu0}n xm S[D%mkAhE۰-cbUue%%e%ŜNYaaSZRZRQVZQYVQ]QQS˭q|>"A@,JdzB")tJJelj2HŽ 6[:Ao2FI]$=+**$YJVv69e? \_d׬XsrJ\H2D"0wXrk,xRu,3Yc񟕈J|W1|B1&ϡg: M&\h` G: c ϟO\~ .+ɦ >??wj 1ǃ@M= \q뜯rhV"9Yg@&+NV2LHMME0H>0B5 q4 8(Q_IX|_PPUSs^ D o߮.ٽ Vq9r!SK'a}s `^RP96cD@n\z*p/??*//*(-+ҒbNIqii1/TUif(0xͯpK_x2+/:(`RbWVPyYIIE)#P(PJq|JuuοkvAHTR1 |ON>+z~=˃U5@eeu5c[?l-o~8% x/ DZ 5*LTU 4 EH( |~@e-ЍoL ]\^[:j@Fv$(7DԄDU࿑VTH`P_/nDm5??rdh6iq+pÛ7o޸K _XSAQ GF28>;͈o!6 ?rzZ#?]IKy-#?e)(RVFc pD v1 #V p^zFDO@Rr,cҙ3_H:՛g3i)/U:tZAFC!+'J)(Y.a30//TJsV*< ۢQ<F('.kUUO?&ƞ8g.^ xnF6+kjY<4nw[@`0f6=ҧOQR3Z "1Lq%ϥ# ?Da5 Ԁ7@{8Fͦo˲ ^yXY6֒ii.]9KFq Ų:.O& 9]D@b2ipzAZ-(~jfwݒY0Ү\)HJ>dٿdsH] dB%ˏDv9L&ɌCpWttP' Q:::*"xA>{s "dC^Y)G|]녔kq82mf蚜D\O`klltȄT7Df @aUqy5$= /%KoCChx+zv;Q`xhhIUxyMx>$qB;ׯO ì,qcORohd'6 hW4zWR](,{!n ^Yq5@MU%mEiA&'?-.V(i:7`i%  뚘&##C QL7>p8T?3O_Z;r 9DGA`rpKXXzSC6$RQM,,,H,NBx_ RR+HR˱1/'͂qގ`|!Wi^^XTJ!$BI2?9*"#v\ B)"^%6əEx`_{; ̀YT)kVC~ܨPȉ@)\XS /j@RԨd,r)f`Rfrr33 +D`r `P^ɡ%Bg?wPkc[ (5̪ VX+U bH*W4c _B~H)]f~} 4𽝝!y=''m)/@~BNn5 Z5+@^XSX $ v:U`H0oG`: ̃`3ڪ&,6211vP]/4zR#rhL"+PqFͪ&u#9H8?Bzsgg X,iw?UށXw7*!iPZS/hZ4`)2tf _+05EO|͖w2mQ x (edkZ9z痗WEV@`j¯=`#rlD@7uu <uEh4u'xRkkgvb ,)=!rݫ鱗Pߙvwz^X=bੀVk /2x* woU~=9MOBPbDzU4 tV;^32xӨZXV 6G; ˛'^mcGh4Fp u:m0pTEchwbzD__|<% F}NKiLFVKzl"1־?P`VA`L ~  _^,CDX`o;|9mHpo4ExiY=|aloomSgWSӳDUOB1왬7SzH- LPȡ/  PwͼxŹ]Qۆ1hUet/OHkdx OXY}C!!% ?]x}˗߿MO{&]Yʥy_Hb{c0G¾s[ǯۛ߾%KPg"0n* ̮)&&o?cm!LzXc#=0rr-fofŅw++[.[<9%ب+:#ý]pXmv55*þ燭eXAyF76/>DrAl`onҔy8#0 u5yap o (0 3C(hM\*˻CsTfNw~vN-o P ClI7 ;RReQY 4 yP/ޏ Gl^R5)-/0;5xE F`i9jqugw{5TZ 5Yeu5o߾B0#Gƒݝ͍奥W#0}C0F> K٨>jm6Cn,pyno$?O_ŋiiT?~z `07zC_  k2Vaw:qGAn<+W ~P@8=ihŅ7agC~ + Sbq@'Ż[+Dd  @OzB 5^3OO#kv ܀YaĘ4@Vh{hӎnkX 6֗x"@DNڭi=HB&5y b6fPmkk 2םTa1RxNN%_?cGlC.zac3xIݑ vv!__[_$nO08TZovwa[T Z⛔Ҫ""ءx(;(lH*OTjtG _`ۏ㋈6t?C_.$t̺e?A/@`kxqMtP8fw]X@`{Ǥ$ {<-vl1gOPQ͇y @o2/*roo@-ڬQ 4Nb7jmkvDa٨9NT/8w30XcUG-?uk3x'IR 큘Lfق $Jʫ}^]5PO`tc;NSٳI))I.R^aabyF;lO_M?>}+ϨWgRx_@Z`![o0- `.%+3Uw\x: A4Z]K **wx1D{\Q>K!I[tNOVPHq#n"IGNj*c^u:I-?5Tr2y@r^8f$uHmVg5+'/}r۩ |3@PNbarVg @ͽng0@aw;]0h/ v| pL=@Gw]D^8~cu(֘&ťJxxH> KyFĻZa+>uR1j+վWsdTJr9}WYSO'h--a^/'OÛ͈($[,>j O<~?Yw*.O~"4&PG}x `SqEއ(^ţ/'_z`1C=0I[1:0q!`A_?fe1??;'Í}̎٩-m-e-S< (_d-@#wk,8CmP"қ ;xV kG&3?>XjiΜ!,aē[4qd6w{`lbr~cl7&\*nAE?E%rx10>CNx;!- 1O_~3lyNqUY Zv! ԓBOM~\=>>(w-q<D߼__x#Nꘅ[SYV<]Vp(N!ܩp$j9rVi3|͕١@a! tQ@$%xF}XQ#NixR@[ xXɴcq }ekgo|8ĭf"/rO~9F pJYP}D}rW6wvP,+g.w-z i?P d0>IB== S;;{G!v6;s@̓o5>=sC|Jҳ `Ǥa/ "uwvG '֗ш' ܹ9FXO;in(l@q;P  |t,?3)l>DԹ˗6p1[ex4A`&w ;Xw6@}ά +#2=zzbyqSߑ ޸S';jGiX\&={8mm1 >gdP|*NAP`D``rzz#gLxеnE<+32(x2Ÿz5x/gxMkk>}~LKfn^Qx?PKK?L[?P@010.npysbI~EڎP;&]Sew6UZ P!Bc;bA XR 2|Pө:JR|Rof?ߟ}|;~ͷًgߞ<ӏ??}77ߐ~PC^4uF(`0$H$Ǔx[[[R>Rh~K~O ~[ģH5JH0#&)% DWy PHeGb>ѨVJ<-R>. @||^S< %qr v8'aN0X~cCE|_Ϗx|/CEX"'(h(2x, GR">w<F >/ܸP({ G(СFц8ʤ3p(l IxIAG#OnJBr9(v3Na!$<.CN">l:ǚJgҩd2LD|?Ϻ]k++6j٬uej8B~0߭Ãc)vd:w" < s|dNt:V743zj 8Ixݾp9`yNة [},1h415R^~˗ϟ?}> ,iy ;Y¼qqqqAz|89>>._Sjx8hh/tZT*10Ѡxq@ݘ*x ryqa ! ?P< :(E( @'ʼ(`Ne Ṁ_ųx0g0?8J<CP ǏG>~W ouQ d4 Ո?"Rrу=|?Q@4J`?9Q6++Qpݵ땋m;Oa4RaםF1ʥ6Ói_!/ mh\jQw4}OXNnmX0ln&菄 rC%D?$\?ٜL7κJZ#%@+FoNkT55cSl)` <h5y < <`E[*v81ʨc?N :(@D_1cO |nyBѤѰ~z|nR`m۪=x nlVODŽ>@!@#^݈fySS4`‹,< O!QP}멾a/ X8-F yC=C^/!= Mi"E>`, ^?NI5Q}: I/u: O8 sՋ+ Ojy. `Ǽ:`~B)B͠W!cw)|v, q_CTRpՀW2T$ y!xNpĵjhU9s2yZ*ĒmJp@!N&-@c~紆bWs<]e2F2MSx^2T&Vj( W֔Fnss3*+(M/⹭r| |Q$]Dv3Y,TJGG`<*㹝 !r^D '&?99M I ~kC7afn@Bã (34% w?`8lDP:yL&??oעSa`31~8_-F1&$<py |KP,.˥=Yzn[^Y2YDm?C@Rp& ^ۻpm#ēϪ}E\ ^sjY1~i/}s- 8*g]C.=(]}0\@FrL" n Ғd^N˧ٙ燀' (nost4:{8˹j1(,&xq@n[|,13e,hM'%F/ ~xvZ갸Sp<8 %M)_)~ûm6]bq6벜_ h6>Lxvn|~[-#a'LJ\5୰DV+q@@ y zvCq}u~vZb5[)ugi.)own߻ѣj^ñjxto!G.Sـ.}ָPdytD!hHȋ8`yRuo(1/ @<,o;e^$@ԀnWxQ˷'r^et~ q |/H%ޅ$<y.[ `߬ [w/ h). Nto1F^fy/QoJ>zmZ}.܇ZnN@ 'c?DwQ\pJH~׽d[˗ϟya `2lV#[^/}._ T ,o.. (:vj wNc .$z*s͜}xcx~TN? X4";T3@ӯDlU*kﺇ^!Cŗ8tpq[)O ʋ.@~ۿ{k xh/?EUX_.?B\kє?/x~h"L_>_7azR_|E.<,B N ˛N OڝN_D !'OI ?x=XOo۷`yXl-ѣOx>s{ʥYչ K}XSF-Ǐ0@S8&+u` Gx"5??|( wȌ4`=}_T F#̟^^7*Q]a@dZMk|29{bߴo\($*x_<:߇Qr ـaK)#W< I˵Y3ʼ[v yRxh yI@wp\d`iNy:`m9l{'lZaqY?|PKK?:"_C+P@002.npyg[S|n}-^TTEDQz =B I  Hz REXk| ~s]3XKF=Ӗq'-G~))~_ !/eºa]I)A]C)~,(-ŷ+$4__/\W^oddV~~Fƃ쬬LWXX\\\TTTXXXM&߸q#VJrRÃ/\JRgPK**rR/PIOϸ?zF&=6mcNz:J||\J˗ ;wRA TEp| z3<Ld1|~~jKx>I#W >1dž}C}^Yo4Ztʜ{i]AzW`x"x@p'f n$&Gfg&sk+NW W(8g0ox=}op`h1Vo~|?48Da@ ]n\ o/_?>|CCёQQVЅcS tF'&1GF''gP񱑳?å^ GF'pѱqG8$ffq 0g @1\`L` ?] ^o|@FǨc`W.,.,,MQ[/4p`>3ٹ>ju`"`8i٭v͊1T_?z|]>:щQ47:-:Ij,bh-c&ǧUeee%Ңb^IIyYyYUEyJPUU# u"QX\WWP ʤf9*}腀hԨtFd4 mZԒWEVD G2sf!g C b9͢u19!^"444T*Ix& ::/5fA~FNx*la>#[2D+@fxd,JKhaǫ×63IPK$ڴqa(oܸv5)>:(2444gd= b*&H^𹹙oGGG+WCñ#+/,E:I&|H<H3=ȤFa@~>~%~Ion./щDgxN !?!!A᱔R>Ď.wVrȅ9y,d4? +k5)檪rҌE_JxD Q"#bcy$ s_Bf"H} _PEjm 2rnMCq%?h0t3@Y @GmV F]a9 4ܼy3]'N$&&:: z#F_@{v;,^L^Ua@*̀@2B !4&Qї W^Z╔cRk#NY|JJK ˫>: 99)E5y7R pҥhON*++9W+-)A<.a,A멢ReEIb&P.CQƢ/;+SjAϯTTWWVW@h)@ 7/ 8v_ Nu)_.ݼSR'jQBT@*+U(+*7(d 9|iEee g ގ@6ۥv{9an>Q\/aU%Z&$?+G_~<%yXP#/-r0k vyzGF^&|XX~ezJJScc X\+׉j|tKoOWgggg&y{t:tl/7[R^-jj7A !@x& HaD:U ޝQ]Т1Y]'[ذl?66 aUr!PPP&e>T*BFݘV1snA,yKD GN#`Y+.䗕 $.[w?6yPdY-i& P[Rvtoibn2 \s߽WV  SJR+g i]xC҈dһ>=X^!WνS 7yWJ$7rx)*mFIAo߹s:::xXpaMD~~MG(K7J&!WL@e*uT)EE.eIA׮h@Jn+&.RHwQ+)1N'? q+\0<& )ͥx+CZ!`0$ +E "x)LNAVVo[C Mc [|~:-[e77^MxI@K(͕6* "cKDX|vlxlϗu=MdVwpx>_^+NLl֡(R5j\Uiigo.&<J eJ %hͽ[~4JVábG $% *[Zҟ$@QC" JEbZ /)D2AW$j6}zI%JI:NB¦ˑWb*[r&( 4Qj [MMu bF%9$Py^ZDQvH^Y&5 Usn{rp0'P N h"ĠĔȩƍ@55:๙ hH\NϹ~kx\gK<]gkI0hi_ /hr@P$ |YO֖f4mEXU (iA\/G+O |@xMcK+ooGN*kR *d37H V L /pA7Ze`&2ZNZn&UzKT#-@S󫼴hCCCB#"  ?rO:Eь&Cс۪ꂀJ"[G0|p0:4x%RlZ496'\h_W‡%|[‹CP(WU?Lp1"~=&VT[r|qC>҂FȈ607;;76:|-ݺuK E 0<'pŋ#.{99Uuh$DeTٱi( {#'O 277==6Ӆ.cȔ(,ӋKOww&|LON |%BZX! +-lJX/.>yxW/ |ia~vvr|hqx[n''>{h4ժV9FE@AR|̼Krae`!WB1+WV֗66 Axd[L@h~*@2di6,LkUt@M>zeYPE#P.u={-˓L Uۦ~]1{=.l7tXT>(6jk$H0lWF[6EO)\_{ÝW1?>& nGF5J i_sFǧ'F;LZ-Q/5 [葄h5 4pQ]@Ʃ @`VW!0<Pzxk5L7&ch#W/N=rhLfx^ZAEqP֞,cp :m$0`{rmrt |}7O~`t[鑜mQg1 (Oz3<Hm9<3~/ l0:22ob7T&Y:ݍ (!afQUsxNoh|߀E^ܸ7!0 l-I-&`6:hD;(FZ3V=  xQO|8>z{szjsCF ᇆ0Y]P0@CEсPi0%}~cXF9,niiN'&@ 74 N{d0Z}'N? y%VWg 02MYsu(~+ uz7LnYL&Iex`6כ`7+K!5zr?:re1!1&U˚WOx]]6@3όD^gt"2.Aq24}]\_N? <^Lڋe&6 xcnr;a]~xiӹ1E#`э`4 ;"AMU2`lm"]/VW^Zo\{nx [^1667_xśϧoO?מ|&]EdDDΫ@70s{6LJ#;gg"PvpsDW"~ۧƗo?6&NW$.v{А\`Չ):ዋMmۃݝgty,Lɋm [59oeﱚl֣ `ԙw:Vk!¶7~:A=!u0!`ZNc۠ө;9+ɇ4^<47bRk[9:'7I+FH:ão߾]cLUhju[L^̞>T֞=]Zz\KnN,P$úwW;ۜԳ̓w޽;?kn)V,㣯`tkȯ֟?{4;5|}>4SmoW*ؑVE9B;{6;dk=oiiףΩQ\};.:<$"##i!2 ̡I F#VQ9ήnv.~ZWToZNt­4Dŷb⢣=bsû:ng{k%̇ɉq`L]VfÈfx ew]QQQ}eI]Kyѱ(e%\W6Ǐ޳f@+nm?{DOOxzmH7uZ$`ޣ3J+/*GLii@|˗\ \OI{Nԛ=pD% a"~uy.WG#lݶnh!}o;OW+5?×/Ơ⒓o&$݊OHI?O'hULEJ itDcfw~vQ?\[7 ;ŕӏ>PG`mD@ubcro@/eTߣf}?4z{_8v'&ܹsÓo_>~H-bP/N:ft^.o(.* ~85o*%{M ߾AC,tx0-8ȐFCOL\:&$Y-:Tiutp^:aǃ^໐|szϿCoH;x@Tj.zXAV x\fE;rBlLJAnPX'l7?{wY&?>ZۧEwzޞ|PΟ; #HoVuLFlr2oimW:~fݶ/+Hh4&^eo*8c=,ޝXo@dxEa}zV>M_PR{㏿z$@ؕN3*?4WjoFL+gE=Åwg|ǹssrD\׉ R٤;!90$?cOpxƀYr/_~rs'>r69<=Slcj:ix;(>^T`Ix2߽|eaͻO>ۃ* ;kX{$YXÞjwyPi`jGkzpN/.l?|%ݧVF›I܇cL>3([/Q.6(ov&`v =~r/Gz&(˻yrg|*XXEyę C!{XN0n^i {k 3!_z GN>}JxO-vjtȩ|x54I3hʝg!C gDlq Bꖛީ[Je Kv`{i3>1^EeE1/7+rt:)n74>ݹq@ :L iyt8gkt+TKF 3J#F s/)u]=>)mb =>&b <; Y|^ 4Je?, !E{JCσ ~lmZȝ6>d@N@H|~AA<P- Cd> @/"G8~Oe~dt&@_TSHx +{1%F';YqP—;n}lrx>i$WREJ}:V?BOZ\Zhw\E]#Bdޞ3ɒ zjuxۇネ᬴4䕕Ћ^w\!P_%uw<L%fZc7 e xLdݦv_윌+KyfBc\磮^-Yz 6@ԍk#;l7ܾ 9و.'?b L"&}=\+Ѓf յ7o(?75v*;oԼ PKK?Ke2P@001.npy{W[[ٶek{SL49"$@I $E1&9Nsܯ_WXo B1\s9ksKr7ՃZIAOҠ?=k9-ZzXZ%UaPpO槻?FF5b3YL&(/ǧ .UUUq\NUƋLfY(00N Y?ן':.D$-M2/*(((*cd@EEe%[] JN%"˙x~JRRRJjzrjB\lX|||rU6O~%~~bvM}^!5_\ pV9`(0pbsY%T'%&'''EG|}aC(Ne6*Vnr# ^X]Dwbvqhyyy K,//+iͮl& g%EEyiI?NSمىAj6h,U0`A%"jf9,`Y܂̴ᡑ wBCңJZG4;<3`˪cjOx2ٕU\݌\ >DMMO/ ,SA&!e3zzF7w?Y{ 'x5ռ*n%[9쪚jn_(hjhT FaAQeᕃ@MV%m [zszDǧ' ЩtzFJJШZ^4t:v].EaC_SWS㋕ZJwdrEJ,(H'j ^Bc=Q+zt>g_oos!J515=9191b=zGəɩ٩)4e ?Lϐo'''Ʃ٩1wg4q/^&'pi11{''&&ff1ff橱08?80 :K˫5 kyqanfKW4 >"tX^𙞚[\UŅE,%\ kO6ˋKK,hH-{ux(xauemnnfb|1^G'ŅY@_X,J'[+l]x 8B`ah {Vd}clthG@d 0)yWL_Z^Y^'^[[XVW(7mll,S<6𱽽0cM e0 .Vсkum1#g::9{{ANFcq yGỉqxtthbybtad;UEhMM_.+M V__['VskkjyE5:~]C=A"jiDmX,JeriTT)jYkFiZAԶ~dغv,nEeTK+He//ŧҒ¢ܬ‚|¼ܬ으̼̔ܜܬ⢢¢l)U35rVIJ57}H!1څas #&28</岲 \ "Ǒ  |^#Q?| _[]]B(}J[;B0h`;E"mҢh ?>:-FrX̊ (J6Yj^RVR\J ~aI.WIqq %佹PHJ.W!m1E"VVéf [ʃriw_/o74qj,Q=Q+ĥ>00Y8iІ~a)9Г Ruq 3P$ꗊ V9p;*"N.TfeX,$](6;ݯ 2.i~L_?`hǰRCs*a,Y\JQ—% 2Dy|\(cVr]gai2b+3sEFFUら~D E%TUĭPwBLfA eem/ooga ϧ?ĈʊA&&:"7<<@KIO!WQGOE 2l^̯'qz9Ec;]eeCB\|\,f>3?qpDrTQmRR=(OuG=_[[VWֆ,!08ܚJe{ 2 pT%oe3^AQx\X-"D}|\.epppDQSA~RUS"%+9"8"f?)A(4 (UkuMIn 0YdU!U5nb?EdU)Լg'%E .T&745 [¦&Alu5u|~-%E`s/ d dx\NUu}Zg"0>}{;#;р?0vjREˀdUW!#UVdD'0KS(|xRijy5\d"$jP`o1X FR/mR 9 dt_>>>4.T3 !-Ͳtz My2Ri\."@/ƺ~5yTR+99IIRs'66*)s Q.hkSdfqy>iϏN.,drW#2.||AnCH.EܬQʕRH,<xQZ,]pVjl !jMدw@+U&&vޮ2D*ƅ ^P<(ihF vZ[ZR!WUnII9f8kD𢭗W/g'R`0d.إ&TV |K]+39]&$h1ꚠaM$jni S{UgrQ;i`5T-`{gϔZwR*%(v@Й&0+&d&|j)E"qH"R::@RmB+B9oJc;kcښ{rMg"ij ҢcjJE` (eY($"/RuR-Ž(߰*fUN喕_X,h`]+) Ec8$5k &Um H xD$ÒPЊjudH,(HKU}|Z Zzi;b#J%e37%w1F8F _q(]X2a )h:aB{l[ K ZHH.A 88 aŃ6<%"6N{`xoW*H)DC+D-hi՝y"MS\|Az|XyTR{mjC`G'$< IWGD{ 2餣6;Z b1Lf}lũE)YS3RW/#4z§>::&>.:<)~€ZVmWId2~T;,&K'ڡSKY)EQO "!!ծ&҃A #0$_7ȹO @އ"Ha3vM>:??7>o0-H g_^T:˯*-NM #A &.om77d{|xR:+nm=X_ߘ_|++-$<<5:E~kkkǯrќV~@rܣGaB!?N)`d6U,)z*E'sKd[;57t.18iMCON)ggMhheBCU1A1 KB^U,5!X2]h`ƓյՍ幧ϷAɓՅՙ~pllHR~&=gPϯ>=?S*ERT#fܲG%2vSׄ-V(Uƭ S"86766v׶vvvV׎Owwmo\__\z<NyylcAZb]4hXz|&W*Ɏ5+LT-MKDNO@MZuCMC)v67vv?Y;9y٫' 0339Vyi}y/_گuh jNN)[]^b2*UD ]Ů(ZTu<{٫'G_xjgɓQU=+9榦@UQnhs6KrZFWEe[ ja |̺k]z SQ)2g^a_>| .;O66&4ܚ̔&OR3r&w;Eej2HXiZښ!(C#-`oo5/./OOv1!ˋS^M[E]]`8?h贎L 8fR:d͜f!QG%wQ]^N᫕P[G ˷'GG Ww :&C=1!#!Ak../z@m4ZZĶYI[ml;SoВepg?#pY]Z"F:wrffiggP-NOPK#:KNۡ ,%7TFre"E6ʛ#}4;;ROw)O@[XA B.lJζVg4&0(v9I@::9=>>z)Xq+ ʗ67>}u0p8 o[gWf'GAcQ%j`ԑYF2]?`LfiH$Bf>99}wg½G1g{[;^x{s43Xc!*u:e DMvw̽l1Tr$"5so޼OOv"܏L_`M,z@3D舫ܒuQzBtn69B^Vr[N'PKDo.?wߞ|ؐj=Qs/|onon.o.5t M80T :'Udvojk;;NnOR<.nf.BaǬ#Ϳ&>;W-/̼X=;$ 7dmq \3bhЃ.HX,l<A`g %xk>?{z O -(:jvUƲۻdŰlxԄNw;``Eء,Z[Dz~M]g@Cn~aO=px`$?Fىq`iﶚ A hh~f_[Kˊ Bsbϐ^~o_.|rqtph-aao^ȀrtۺmG]P_T, jjyU첢Oחo߼zzx/v_}s~~L*E_urӗG񏣥I(V$Ğ='++ 33cȅںz^(Cc߿]?{r{{Ký{/_"3=Vkl>pNV\З=݆^BOW) :iz׫7Gv<48|sw ExKo$ ~Ibp܋5񱑡A~C.mhI ]E mdj7/ww_9>4}ۏc,VqcRܮQi;h }w{g!=  %z c5wv"f4N{zo^'GGvNewYВl?__@x }A9xszzzų'KKHiÃa@r[qovOFNȭrFU[Bmmn`Drf>HdbGv@F 25>16Ҍ ;:2jrn:>ۣ7ggo J#3%FL6\|P$=0ĥ_~xxgO6V34t9 <{%%ee%fd /? W77WU0 Ϟn\^dw/$Df{ ~_p߽O??wk@HvaAd +@dbzzzFrZfRrVV^>9Go߾~0/|Kru؉Hٻ{{z<^DA=)AՠSCq1 q i>'8?;5z}G21`=d ̦NXLl.!aH^S!(K  }q7ٖ MHMMO#rrrS㢃}i~[woώ0Ń0|s9{/xCuULB-߯H=ީnʴK-/JMy#a? MIOMINOLLNN|HMV߾~ti,aH7,FFPpxdD8p9Ào٣hดtfdL--viKOlbb9uGj]Ono#=C&u#ܻwN}qs󖂿=nmmq߿7 8&&&*2=-?+/Y=ndB4=#n Qe{ p{ =tb&U+SK/.>wzszH (LHIĠ3 v9pԽ^ԧ^@-G2.H!g$A֗>" _.>^ݛSW|`@pHx!r+5 LmNۦ'' KKJx,OS#wqA_$hѵU>mл˓)߳qw?(*؏HNt;jR-;.-/--%edIzV ]Ia3/?FĿY7g HP~ #{ ?04`[v۵Ҽ2nu!PVFN" tdV4JĀnm.0ޭzѳ;xdGB8 $V* V ɩAF*0YagQ,Myyy &V%wQM)F%,tӵ DŽ@:CBCFQF#~!4W/un+fצK/grk#wg]no&_?^TI&7J,%6cH&'M|gJb]ա.IL-jΏ&)x1Bx_~E\nCi!|RȆwxvxHt.g7C`;*?p@''25[ğ?t#6x˝ݷۯ__qC{CTFr*"^I.lFPA!=$ǷJMKx!!!Y솖o_>;OQ4AJ8?\@R~/@m2,ɠ"uj BuYO}td=B(~7 Ŋt$K{@nwAOn1+qwzf<x'y&! Bac[;,u(&dohh ÷n˘Onׂ%4iuZFM=C@$I s&څz&<$ͮߨjP>b~~u ͯ7{$-wwޟ#àTd02z@ECr~MA&Aoߟ|mhhllx_ze%޷;z@x\wSGQM7g= @@j=ZxhFBɓ ;x; !L6;R.F%mh:W~j~ϷnIk+B{?fksT?-lǜ:zgf&FƐ"` ^r |3t^}$n۷vRZn!D$ji sE͋1 ? ’ z?btCSSS#ɱaI'dGa!Zw O(큜$@T"jiJ6kNG %6PU;11151zHqEQ~֫ͽw_~۷O6A'%2 D%Gz?)u/I| Y؞ѱɻ'|O GN]vLίn==z/h?ߝtiqqqIEFH{U@Ӄ_A"^16C!cv fcէ|%o݊ĸ$43zX,ii+Ěu` U@dp54 32B@p`F+IƦ헇ҏ^}IonnV$X)i9bXDre?D\UHRFDQ!TM&fw=9>~5&n íf1J@ UU!%RH S3R#R34::[)PmlDt>T]|@ I l9]RRXUQƬ'm BSr}>T lhϽTS!((ՊOk>};x6U`*ɳ-mJbLR|OEE@ꥧ(IzsR$Q(]/_>ܼ;-%S*xl|0jE L"uE>9rj& 2D(<&}:xòl,oo?|ӧ/n޽vu]efZއJWD $G {FHkL=D=(K5( }Éέ4JN/> y:W95 N3[R+%75EA>@*CbrDhz(= *( jwّmGG'7@A"2S@zady1t<'L| 3<1JYO!ҰzGIgz5;xD)HId2ؼz.UEK$ ,8ÇH Ʃ".`E@&A*''2&Uɭ`Q&>4vDD45Og䤗2D'<.#Þ>nd^;<qc=&/zSR3s(bJ^BDH,FXXht,<PKK?t/C9P@000.npy-W[[k.xmӻj sYD%@!(#I" 66W]U{?}ӿt!&y7CU 5?+*ش(^%Ea;J9O."UBx[!K+.B'<) '"ȠQUhofffS#dxm6>r9l.d87+F)D,"&vzq҃{Q9¨ɧ$xh4 Tȡf2jjkꚘfŬklnnr[ZZyVbf`de&h"KHU:wNz_~JjhoJ$Sɱddn{ ҚZjf7775Kp[y6ᱛ9M5Ey $+-=!>Bht )u(mZ]UJD%׵K8qhxll|b22=86IU c2Ml6'00uu윜dJQ#<437vyVӪbN s#V9QSUSmb56ԃ4ě YfFUmmEYqAvNzzrRBrZJzbRrBBIK д܆>wdaemc+[;[K{G@8^;¢ʪfVcSS#r8ںZdH}mMIQAQA^jRrb'ĥddg0E%JONDf6<}P8 g秂.].hoZx\V+y6agGwWX%sfvCScc]}^^NFBjB8ܱ bwvwvvwX__YD[A<?v@MYCVj!ˠd4BͦAt;3! A0111191:>>5 N͂G͹HdjzlRka&VK, ;:PB@H!uEbX'dJB.T~R=AkAo&hi#9=nf^76A#[UV\ZWX\XTX\RR_\XXTTXRRTR\TPPT<V%5pTVWkj" Es㇣6jivπKH'%4B/eTVUVWUU.(/.@ZVaa^V^AQaaA><x閝 ]?.(,//Jݢܼ*SvzRRZFJf(:/GǥdPt"Eks#<5640++aVTVWV,aVT.,-+,-*+)T_WWͨS +TNYQaΥk3@'`X%h,DqZ8hQP__Ј 02Ls!p9-ZMZskR76$}h&ţ1xT4*C"D2ZֶV)@Wͬ B0 FB8EXL.&x|(BK+[;&h(H$.9\RVSCy )Z[UOƣq8TR~FP-R])loA#(V"<8|@bCx6Z)P]IYYUy\S$ӓHD)MtD%%o|AP hkt.ST' d>E8_GǺMwZSFE_KOU'`Pd*/1X|JK,`tJ^IOoOOSڈ:;DBASyf5VUB,lwttjw*II܌:^_uzE~NravN7he54ZM O0qɴ4zZB|<.+d2io4vEbPK$6IbT0-K$Hz5:62#.E *WB]C: A.;.}l|N:BpܤBPerѡO#%pY,y| &0P ^:`pubWQΫ{x.6'QxJl,X](/WUJJPHe ТO"ӺyǷ_wwl>zqrvͷŪ&VkC8^yr*W'R 4 ]3 !J\*CJ mdՐyi̓߮/{RNfg5&aI9rKyq!$50;6M,%e)Ff@j4~C U">υocZ"~p “An{=8 '"v? L$q*Ks[cTt+E\v;:@4׵pKcIyiY4Z 2P@ȤrJw <M Ez.Uf xBZ:iG1*`` Y[gיT=A@\iBҟLHBG,~Hԡ fbC![N"i2%O91C3KiPQQQI^-@e'W($RuSe5!_%QiDF9 4<Keζن(DCGd'c5d)ְO(Z.“8Խ dU8EQkTA{~ÐRSu]]nJW#b1$F=)6"Q( 9>э{)RK$SH$:=-531\?]Q'2`1(,f_U3H=UaȠ PC&}(dgdш8:a ZxFf_9 F՚,zѢJNs[UzNi51hZBR5RÌUH8":eQk"(XJē8<-LNO)(ʈJ(t<1r|W8Qo6ꑕ!Ūt/~ǪpV;Qh^\OzEeDQx,ITG$ %Qr* (MvQgQL HW<6upHg 6uK05NPH?d7wfC͑ ؘ?=4u8v?i*d&IxZ||M$QHX DơDjB`q2&[gi|; Ab*;#;s#ãc-0dut %99E3 Pظ6mUޟ"ŧ'&$@x4: iq4(*V$([f2@Vi}r x.ժG]#k3?j]$sMf =K\yDMu}hL gf''R)<42lO*f E1bLJکp`j8m֡!FbٟZ LX|EfUŗGjb(幉h ײ Hi 蘘hEs!V*btzsF>*yo#-0? 9Z -1Fe#.W{E r 0JC.% +y\d|l4N<~:866fńIEFOAh廞2v[g/+˳RSS􌔌Z6[ IVd\ءFf݇;Ks++ +ݣg[6@1_K0)Hhk:k{\v7z>Jt;L4K$m|TV%0mT~du=|d{Gw#$& }de.\^/*F #4NyMqIyq(Ԣ(%.##_3gxm{`ѓ';wvGl¼Z2 O bs>-b!(@JQ{b,1? #3FA @xNo Frߠ:Bdɳ'?}zuzry̤!<^ٖ@6d\\xbm︵Gfx\PFͩ4xihzE3b0뚘lNkTaMFIo՛ Ϟ>zȫ/^>_|9=3;1H_Dpeea ^7FAɠm}vI| 7,feITϞ8zƇ7N^>=X[YXqtAzj\UۇgfsZ-ɠWennYz_LڣR!D_g0Z1|&h~_tLJϏO^\{᫳g7mlnG4n,1xxxpt|!/!Wdnyyb,02h4 @l6nY,?Kv_puuq m//F aHUsO}/.o,OZ:p YZCv04ЯTQPkdbǫn/n.޽998;;ۛYՠQQ2=>8zd!dۻs؈k)C9<Ղ\K (csNU!+_~zӵʼnP_2u/O?z<=>ݳT$ <PИ!C YoCs`2;l.rT4ѣKpqw?}wW; v*:`{ifu>46R`u-g"{a] T\C1vylېlDiN4kJ#`^ͯ>^}{s}ۓw{Om/ͱr鳪WGOwgW3&ejSw=6Q%ѺG.P)=p1 ؆&qd:hȺRI7Gw~xwoMG4уO!' +]52}WOiC>Nfv{G<~/043; ٬HA nW?B iWk˿Ϸ߽~}tí㋫k{s"[ܭ2 NU֑0_ N=D8y^ᰛMfHBrA]~d^q{_o?ypgqߞ?͝q@&z`@Z#6휡Ko`zy7;6=47;19>8 Z\^QXl-Y?>ݼts㣝)'w6?y<X-zR hN% L>ġ9&417f '.!{ׅ#^!/A.`0yoS+0o^ߞy}||g{+Nm,D&'g&GCN 0ƁE/2)|LJ/m-,M#Bv{ɤwO&E.߿~t{}G SO@yhçϞ|ӣ'+ ~A#ԗozq~th1;;==w]%nB!iεׯ~{ExyWgͻOO/^]\<9y~㏿gcNS ~ŹX8v{ܞ>O%utvuu:څ|>TW1뗛߾~%@ϟ]} #@o~o,OOV&/.>1yˣ=Z[ZF\X$hA}utD緵MUǯo^xp389|>GDꐺ33ᱠ;86G^9N_^>.-F'FA/0t#|Xcs8 9t{;0*gg"p(r%BX ',V#0=aOvN_<>>>=8ԧa'6۠AoM@ax,BQȤ^8;=9zy$P()e29rW)lg<ًǯϟ[//>~ ;>[&x@&2 ,Oi )tjp۷o/_|׹9pd~h@߻`OO__<7ןx{%alM9a+z*JqT @͇a^^?|Id bp#`63m###þmt7yUUL=utQ)lT 8<@HqtB珷 ޿y}c͍@]d 7LchH`((?v9 j؛sd-ÇwmЇ|VA˷Wj# nbpPk//O#&zfaIQaAI^qeE%D"/J&vm}߾|0|(IȮNǬSzC WWwjyGe:UX’ΑbېGĠjRV^nvafV"s/U.FWn/ 桉qdWipqUX*ˋo.!>^0KOBq(CL KkJZ:U_M/-4NyFrrg uHmNuU~7p`w8tҸXtԽ矯^z}㝧[BGcd2OH-/ɦ0Y - pGgWfƆ=u G>(V̼3PU {=5܏'7|H`%)iqk3GCHXmvA%sO@}x514]? j IYit"#bXzsgL!Si8= _,7a^xߘW.leV4"=@84:y]N+@Ȍ:W@1ˡٳˌX"B萟p<I  rcc^Pe/A|MmM8ZجƉ` qiڽ=7Ƕ}ڞ(mbjj<M'ӨTL ע@g( ml|bo1]n`:o9=Ξʼj&օAG@RI߿|xݫgK;9sG‰82Ƣ2F ('< <<:l }Ah8]vhkY-"!%`h m6:vOo!=|<(qTB$ 9e3CC] Qca_.D GߐR\G.|`LY/,B^폏~t?1 D'`@%bи"n7k)t%dHfdpVf*`+b=Ԛ@Lɯhlɿ~>wz<>db|n? GPhG@cDZ>4 tC,&&'|҄ 0V,V3>^ծ8V!72O18"؍F d.ӥZ!"{*c׾K` L]͏-fà5PRꖩo?^slNz 3qȔ Oh%`QJ 3.NgE"c= md8GC!`Q3LvWY(-;hp2gڝb'h+E>FmR)x"6 p%t@edACB2a/rW >ZZc0{FL+c~Hmu_zw4@cPx*9$O"X,'VwmY?>ߞr;M~uqyN%r'RѧꆠZ#i bQvQ:G"\dj~kxddI 2Ƚv0Ftn@\7ta3YgW/=MH&1^Lj_3 MNNL I煙3 fhgwz'7+Fg-tw_NBް<:!!Q$bX,ONW{|^udzjGTC:b~px0b:q$V٠ F{oW?^[T*5H2@O?4`4А" @cKK s#vԸnۃ  8RqFZiH5o?zQŨz~>6& +B5cxb~~aaqa> LLBC7}]7 FdKWTxv˷~߾ijM@$2L S1x2@ zy5 s807YvdtXfRQdk˃w}oFϮdەˤ2)xC6{B) &Ix/t ٹphvI@]G=jן ߗ/_~JxH+Oȯ4d}J\*eͱcPhdb42HC3|./855=?7;=?AF&Ǒ r;K{O^?߿޾{㐦[JKcW2@4XOYЉNCŐ1j<%{ 0ATcm3 t/΀_HczգYo[QP\U,j.*++2H_ˈAapȦ1 8Lb'uy'&NrOVȝb>h<Y#xh?}|(7'v^Ϊj(,c j LѯPбX4F'cቩHlE@O {02e!魃四;6_>}{{xNQY`443b[_]) RjTT=HN!E%tyWщȿ}07=.\GYŃӳ7׷w`o"Oj,V# AMM)*}2@"QKM aw|/72>&:h47=50ۻŌt[eMB_-Wh$chhlxDDNL H$va+G֦NN_\ӗ`/w^V728.,_TSvU*n.J%P(2 INxFp0|JdA >69O|}tS¨m "on/hv5f*UJ"i]~~C/hb-<.QMDz\BfDOBH`h,LkDXd2h0B0# zۭz[$P|tWTVY]SuMչJzCT*FuS~,r|7N"]l-&0ջwW?>9ѩEUUeuVn;Y_H&3SHĤ*PKK?{.:P@007.npySgٷW]v͸2UIUImՌR3;V%@B' #>HF!!q9N=-u&؅l}?}?M ˟˯>UOv#?>P:=!xO᯻o?dP_=Gc5pGG!ޮΎ֧O>y\ Jљ͖Pt||<9A)@'ϞB/Sps>,H`2 1dYmVnX7>a4u#nDVբhoW^AG5}^/FP$ç0a h$߆?h(3 /5X ^"?~P pZ0xxr7=h4 <OA|j:=3;33It&=9L*`~3>n6vYvw3dX̰,6j jG`c Ɠ1ªLRr"5YLfҰjd2)ggpL TCCCʁAB!]zR3֎z`0YL&hXc$lt86q ܰQV7 k.q$ pwwttmkkkKˋֶ/Z=k}Z*{Z[;::]pFDtٴ848&fu@6:rH3:Ս(%:YUPͷw0V /{1.o 0l###9zT2ѾG-m0XZT:@̷@<FpLbdv5{B-<Pyy 0Ǽ@*y q )<sml@<<iϞ=~|#a^);Oy><y?~|#?_o.? O%my}}~[~0Lb^~/ ^:7V`y#B~Pz9(82y`0~9 .#LaΧiݩN`fsQ< ,1! eU)vTy'ykcjN6@($ 醇/_ pt& U|'{ <ƼëtVH kVtL t`L0@E)0N9g9ziv s `YW*z_Cwr) k|$oOr^Isva6@ENH *T q\./> b |gίt5jzr9wS6@DF\ %[y?#'Ia#&OvT3oz]XO7䅵<UYj``z"`h0䇪*fx g< (@-ZZ@MrbVژ=Ḭo@퀳 `Sut~~jb]jky6r7kaP 7'%?|Ic@'ЩQS0L u(D6X|˟>+ &04Q yhpMt~|ekmO~J:;4?xBʧ¡Q;(>YٚXF9ή.r*Raچ3HvhHJћx&7pAЉkatƯ$b~ch|@Jff~?yf=BN߉_;yfg;SxObKX} ff efi{=|zhbzP(lg&?O^^(*r\W]*-ǹYXๅs U,gqHD@~Tdn˯y y&ǃ^*R^ _^XXYD驩p V![Z|@.#SS{鼨O&Ó͠L%yG/=L] K\Y8&«Lfj L ЭXy`pH!@ߛ:D]m=^qX"aR /JX[YZ^Y!X^i4h0X||Ơ=H P!𡢌{Jd>JFl@-_ ֪~^X$J$2\ >W7 08R2s>qlh#^:,)22$Pͯrn: ZR!Hu ;RGY~kskkE ʳX4wli)̩`ͳ8&vð['GEmoo/X՝R!l*@3Lps0F4 b?9cx5v~uu*hG^R~~ sBa_a|r5@<˯<`DlFxUs##oxyl_g`sy7 l֏ w8=Ak^G"NVFxyw< ' \P v?x;Az]P}a7J%6 wx2y ''a8vUzQ^(]`  ޤ΀x6{^X pa}T `֙)wםZk .K0 .7Jnj::kPP:<w8Ba/*GוZ.juW_L0pT~1ޔX͝][@WoO^'ia`fSH$÷\Mؘ^oPyŖSl(a"{#QțYܫt&G~i3 F`Vmy?(n@$y5GVauy1exov:,VM;,jyv E860t7O{;.-/Τ?d1tEOy(BpP:>=>&y9",0ZY^|Mh NqlL;Lv <my{[8Imv:1r\6ͬ k}6<qXL2ÇFamudx=nŨj4#T(|*uÇɫ`-loV_ÝE*y/9,&ɛռּN E޾Oa5ary«Y˃-fR6BVӷo.˰vH s9L(1pج&:?7Rq[C.rvzU.輞 8.1j>@@<~qnv;зX< >f'E&ot<hč*o'ydJ//+gǰa+SNӀ@Py9_90O_7H?7dĊח0@} 7Vac1" MM %0&=J :p鼎 8=x@z&y F Bڠ[ӺҀ*_,2τHF'ܱ6 yilm-Lގg*G-'@d0t&oY Tد0z\@穲H̘۟HW*<q `wH`vqQyS-O.+W\`%Gw4Hv&lNP<`pqaty}ݚw3<Ƽ}7$^fw5W-z\ռFfN`㟾Ocϻ< z@5o?~^Yn' <8@=VM]$979y6Tր `E*pKW XWtߒowI^!^\,̷@=^:+ph(ޜg)>7 oía pNZb򛉞{$o^L!@5`Om;Gq@/Pm]wWUj#+8 +^p8;9?GOT(?>'xH$A{ί\z8}(~];RBPh9WW'eoo\~@9\兙=>8;:Oڻ`{|gF^yyrs㓳 En2^Fbց5w\w[sg5\"ŕwo*2ds'k.ejyo\`;[vsPvq=_v 8^@'ٱ-l/p.7V_ vww?9>^Ml% 3`yYɓvS%@wk-ـQ@odj/*b k$}p7+'gVo${|$F𒉕R[1T "~xC7` <%^0y8C:, LR kGZ x2Z3)oelZZշ-U04kzaZϷT 0=̻ybwxi L|K{X ս{@|s\1 'n!O=4Rn#^}u=)ސ"o|``|`raiie} 'Gjo}-Ly MyKo[#&+0?PKK?P@006.npyW[gٷW]vϙ{$3;9d<38$=;6#($@ z]7cDq'g_sDlj1{s}[W7~%BXBwλOEMGu֋+_$iQC_~s_wP}DӧxQc=zH?7>/ܹQF3XHޞqhp<_U6%xˏ|GJ,+h5URW֡ujd2UJXWvi<x:V<PzzFRH.X\^駷>͛o_Y³y"ӿ l@U'U2>/y*3_*e<x:Ky(ɋD</˯wҼHD7oosx n7oZrs|HT<?i746*9D@>q#|59 KK~Y^Lj]Jx <\Ok š:am]m-OFPDPQ_!6ENA&|1[X"qccz(ij\.xITr  ֦=Z bͰ-`n7D"bF  I|qxqx~2`xCj9 xx|E =Y$ pImĀz$@7zYX];<r `x6E]^5jYk3`I"z&bDm2Z=@:9 7,G_z`(^,Wd-R)|x Ydh]l.d cTrzyveūR<%XT(rZTF#ŭF]z}/ w`drvlglmU<<`. 05 hͭ$$x=D&a *X,%~~o4K 6tu;C}dݻ<]b:afx94V3P|KKP'8yrzz  `TrGN*@|E8tCPAH@ ȓ6NMۮmmT\EONyM70oѢƆЖusp#Z\ˢPgnH@A5I0|w< UD@olBF Iy&hqx*9u<)A(T0 .O,T(24> S/f4ˑOc@fy jT\ުcm _~j[kTU xDHlptt4޽[@;G=߹o W*$#Clͬ.wi>5ꀯBoT1x 7PP4 `lw(8E|zl~=(N0ū|Q; uÑL~ tWى| 7Oրoj*O> 4Sg4«h :$FA_ ^- =ǩ-#M͌Ow٭"C0ggwQ׶j @1ŋnGDRi+oGSAH#Y0=228N|<eRytbF?n1<;@xr N-L[[[9s|tttphpdrlhz~B@ T'G'rݼX$x5 O2)*q|LONN Ma@vlxymgӕ ?@"63YP)ڔm RRϞNN-/@Xhh>]YŗUxd}>/S(ǼB)yg禧Wsk07756::4bFೳ:u[TB_AVj*G{\wp;33==  NO . 5ST@e06$VElFсI5U> X_~{ y4x<٘g_Y=:LwA@Ss]YI2 C! Jj*4ˋ 'LP&D ?{ZV%˚[Z$ Ra;n*]өfޭ(:WVVw9d203YN`&u!^תU0yTh15j_B\M![/2G{L@6 8'4 Ănj6@@fZ7yx $[[[Oz=*` H8<|" j6PNZVktx~`66Vfp ,Mqlv`yT l[\͓'`=]T@!߃/uf / $E.-0;.mװ|\ҍӓ|\> ̮.-Af'9<'X &NmAn8<b5a[[pBd(%!` C@/~v_Z0P*G$&)//ENEs H?cq Kpd&א׍XAn+=Gdsdt(ۉ}6h4b ؇dtX7 =1Ld"VGXt|N.:N$cѠvX&!/xz}GlnʭbnV+֝;Ln.07f'&FI|}w[AÓ]@݃cc Hnxv6Wae-.> $a%+V9{$t(`yye9{߯j~n@:Bm75*OIN>`j!$ 89<݅5jNf23"3 W,f1 o5r|$>y1=\l!0;=t5qB,v:` :*C称KHpv M}}vz8LO71޽_^ㆀvneui fyV/& 8vHK%6xg'a+agmcH@&30`3o< Gb9q!`o]xMt*8#FO L' XL _hl1^0NDbЇ] sx^^L3Jx 0q0!i-N @pvv|dC O1шBDxNYQ@/@8ƀ=88D;kXyjQ |f^[/Mɏ-|;#x $Tflf?}~;?Q./p&14HBۗ?|A3EBP4~vN@_@6@>~ϯc op$_w(93.Nx TV~E#;a0 H<xfπ~qq5B>W::Fq( ǀFiK3_]vowQfx"6 5O6]fݬ뛪4<'<ɜ/x `kdy8ON)^@M=ڲ9<~|ywb'y H?|Hm#5n|S'Tcaw0"mSc@7?j`x0 '5I+^> lpyI@YX'{?/&~f׫V0> '.p N/vv8hsy />0wy?nhVU]Z 7UÏ _}P'R&eG?~DC2ʾD7nܩkoכg<ח%G  |6T?yBioܹ}WTߏx(++;$M^x|v@Y-7H|%>O$Q@Y->>#X`|i1@Y-D&\ե E T㪪'WVU_~=&(ãCK F(drBR*jFޡQ*m6M"i4uU5U+k2u\nWX@$\n[V[iw]n8]٬=== h1F^osxiƞR  #f$&bH  B.`$ X2'4̐T< ϜJ&D$ĢLczp$~@%X">0cx4LӐӽiTo//|.r}t:ۗt&est_o shG <)F(@?af,t&>eHp~`p0OdYK:ZgxpG{{H H #P8 b*Cǟb 2:Bc, yJ pAp{=nY 3r:0N? C z< ]T:ۛf'Ǥl.$ b3P(dI|~آ9٥ttS`5]z^g0- uYvnsN09|>^?臶Щ  Z>!ZjK1L&_WT[W˫TWW=~q]UUmMmM=ϫ74676 [D"P*H$:h&@NSGш[ xݥ7 fdȚfCj@>$WUS YJk++kNp~˔e+Cࡕ5XA9#vX@;oiime @EAaAHng H@ko0Sx!x7Th.w.#xX^%<@Jχа 0bEo5 8mk;jT ̧df@J$h㪁5,9;6>>.#Dc:6 IG}92+1x=YxBɪIT׬n6~~l,=~RT#< dRJ/a Hp! _~N?96HjB$᱀TZO_70G?x+K \GPx64 X EODa1`?'`F!wF3o}x19|z8tY6 &&@&"<<=O <@MltxxvWi"l;Q+'1 z{{;#`! z<дWQ26}Y?o͞v$^*mӹO  eA!LLaB? Z<=jlϗ3PańlyhkkJ  &f`?dA 4LG(~twPkM.#/*, 010ٳ၉i$09<8`0gG+?6??ɰbbJʕWxXJB?鞍?x>lba8 ӣh2X+ԡ?15ɰ WѠjznfjzf뛄83T$C/ax PEj A%GN>ťťUoˋX-SD`o*􂀣Dl]hնkۡd ?K:8-$rjRpp^iR N}DxZ@o"Zl9<<8d֦tzbX|.9$N t:ހژCxa!ٳc\<%$n6e7 ޽>O)$S036l23x1$K#03F8{Y:}T2 d`y6lK)|c lCKEF~;F+\65[V_*=:by!GCCqK-%*#"%0˙sSbqe=3@lv8RH06$otv676VVHEZٵӷGŹ"d>`n"*bƣaRNHK txs)*_ElLqD,Bz޼} #!d2F\VR@q2XZ^Zuba%3p8N uoL 2d"fwK r;"H 0\.F^ +K|\]]~19199:ZHFr :9?{7 R`qq~qs ‡Bp`j5Jhk+ XsSSG|o$ !-9P(, OnlxJ`~cgww=! ^ D3- ?W3/3T4 Gl==]GG_.X2 ;{ݝ͍5DY(jG ƨ]nŤ3zV ؠ>FZD݋n8^y> !M!Biz#N6HU_0fvI| P; >I<֏oNQG@m:rև~]N;A%WQ+^J,wP?lo,}HwnSR GY\ `aza BipO F ݥK>?'Dgv;pn605cYTD좊/J D"t9CTg6dzq|tt{@ߧvѦ F _Uc |bU"|>٠BX7ÀGv|GMR(t|O=x-pXom}ɧ(<u6Xz@ T( 02F?)?>*0PlOJ v;$X?vI !{ie, P=Ll37Mph5=^odG~u#O)3 !ьFK@ {v^>#p)l\Rqx}ipw-}wl~SAt萳訜v\%BZ᝻|xa/+cJ(]h<ۭ+)x듣A-9-ݏ?6:EvSx"f%^qtRop54U!|z{"t:N '. o#\hxRR  [ڛp\{ XOoԨ;=>x“o6tr-7w >p=S{PǧIXXXa*t;woFJ TH5V2=;h|)|no/x|HOK`%W',uZ\9xJ.zIO(苠7+.xÎ%c$ [?|z ?#<0ƻYDpbl7&z]蚍|T&W>[.ޚCE8Lӝ,<{133up1͕Qif>+nzB=F5!"B! O 8/^+['XO{;#= | O pK \ѹy[P6;˳rWO S/Ѡ% x$-#Lӗv9՟cxR::/tG;%Axm(AWՕEVd0\*H<%B{f/.蛚-Gxx,p,^.F@{{IE|=NaAnH1ol+Sx^‚J <~|?8'|jFx_8 E8| T?xFoE{>#ʕ[BGvga'^A5M%'_(|?_|K$ X3 *Mfw6[<O M>[ +t}#h<=mCs6F|E O ((<)p[]bg7aƒ@Ս Rrm[+*7 {#]w(oއp`amG+*Xw?PKK?G% P@004.npygW[֨|˽c'qNظN 6`(H $B(Bb0TR}θ_s9c܉ z˝g_OSyOKujAQ1>[P_ O y5o <| }4`-[Twظ.r=*,,,((xD#7ƕK/xW\pIgr8Ѯ.&:!&XG񉎃{9i~nnޣǏY<'ӥK~1C7oX|+ Q/|p{,,>^F |G VYW2(J@w_#PnGZS4\`񭭆@' _"w >ڞ)Q  \\tfAS^~26840 o}SPTť%eeE#_o޸ . xC €(J\* \R)-&J!5HD^\+ &B(% 2Qx Q䇣)lvj,v]Nt//lVo2 fdt6wf^g!xQQv#i6xC=utttE;2A~yWgG'#amo ᇶG aۀD:;c1c1X'ޗ='zc=]QhgKPOzb8{1'=}C!x048<2<<ú(`r(98O#?y㆞v>vz!hH- n0%cP  pPt|d|_%Q6kaL[Z[4-*uJllԤT :h0j;vpB_s>ui @D|=mǺĆI}e5e⒲b^IqqѣǏ xJKJKyr~yyUumuN("q}Xmnjc460j`z6[[tFd4 *iM̤٬YrrpJÇdz{H ~O]XTRMMD ^ Շwҭ1 Z*j%Vc?_U}ٳgfIb0$HkY*ysgΟ?K5FO";;(/.>+oΜ9sxF a7Z xQ1Dz Ja Ŵ.AE"srJA3 }:?gx(9ONg/XT s2Gu^"a_פt+p4ΖÔ,]ԔJ"򥵥!<8wamm Du5ԀrNX'5D'{{dݻݍW[wG,(ţ@kjhu@.@Y/W2_|HT_WW/ kjZ W{##fW6;<|BAx B T@, Ĺ׮8|\^ºz&IMTј%W~[<6>M#gD ;V(LJZ~@*mK$b^Hjꡚt_'З|2rmxa",Q4l"Nލ .Oɠ(G<+x= D@ ƗrZ 5-p޽r/sxDF՜@EߢQLw<#9*8C,̣ )0_[՚T@,6~D*C|#q@cZ@*6ĵ@M 8٩"޸QV*9d }{[*PLD@B6t4r2L T ^*錦Vߺ_@a'$a''@6 td2V X?ܬ'*lhA7O \gb\ 0G|T2Rpj--oP!1 2<#|` ИD@ۂU`D@ 'ĉ u!+ LjtT@LPz+o]T!RS?c_<#ZTڤnm%ۍYeهc'O}ݏ\#Y) c ^ h Az~eJ |GE@=hdrB+,Z'xF++@sxVkےҼׯfQo~|EU5@4^6=e;w+gzqY kG\~ <(|&X,oFPi;I4Gbߝ:OR<$5BHDx]lhs9L&Ɍ#ttrPR0VFPy5<8kj_'|2r;n v,(08u#n߿} ƿJ>:<<x,8T^D'%{# IQ 98zTPA _ՄGQVFua΁)ÇnGa$2oph' ]hwH&=Dw_>]Z N۶8u w HD`@7zFO{Ǧ`?ăA(ǚJ^*;:y G@췧<_ED@,I@< #OsD|( R|I Yi[ 9ȟEz8wRAH$QH0(p+'##P'OǞ/f@(xg{ `ފ5jMogSsx+R$9s$lCr FB Vyx||xhh`dBSӈgf\ URZXUt/n@RDxhT$?<J&`d _R"reੀn5h4:XZ`VAţ{~]UA"͘67h [vK3_]ϧ& uuȖ\HWc!SeDUՐ?AB F @Td*+0<<ꊆjN@N AUAcDW h%䎢j`^.**(xF-e>5bnnq}ss <d"U(fXl)#D,qIxNRB(נ5oUO`f(C/ib ۛ$tuu(> /y\uz< MEjrsA< "JZ}JS ˀߠK 0 (x*0%]A/8,-:l4< ?/hw6_m)d'TTӗd4K@P{,zF@g1Hln&S@ka!;I*C`jt.F|vf$OW!Ip `lNfh zZ/&xQzɧOXXD tӒo9;67h5LV7z $4 %Kov+<e4(>CF;:@@k6B3/xAlWV`Bd8|!<'@𝝐L m&GjQ` Ӝ@c)x &^M ++/gA g'&Zu;/҅vrFf54lݞDWT> LN,ͦSSYvV' C0 s,x<+eN`rrv!Ŗ?O\M&B ^<N>|F#!G!eksgg/M!~"`L^&|zuV5̥@OW$nb31xxl--0/JfR/^X3[aԸ׽W/‹T`&rqyfVV񚋾gө?Jt|V/9(LFC}}=6[,f"9JMMԿ|jmi ,.R@jaaay[닇~arڌ8h|Z`r|ltd(uv^Q+To;]+^ozssm,傾meV:O ֗f?A3:ztzma^|`?cc5-Ѭ5$ʚz>tt/n0-9퐮(dDVg_< l-XZ Rsk[;[[}=!2eR]?~wk+˗ _M?tt/D"m6ŢתMJrKVX[F˛[{B! ld2HfEʫ)~hwksc}}}mueq搩ѡD:c.lII7ZV 'k F(X_B魈'>Cow^.`4GTer-~}  K.(1C MV* ln2: f6 ~{j}R ˓k. |ln2p)Fc}D@gqE pз-h-hC@j o2+!=uKjZ[H vG;@!<{[qA`c >Njk^ģ7a 3b_7:N0ŧ`r<{ ~sk}ifO # S9<#s7U@^A~Zm(/mlnoS>|A"X`DiSf^B wd :<;|,/ >S]eexVǫ"^$ 9埗BWvyCd^V  q=Ss6wx"PcTǫEo|q7'$ 4> K\Fg*} ]+(x꺲@SS/<Ƅ^Z{`\OCqyPvxP$hX `yn͇+x:\>pX^"  p0h~ EP@w4#7+EIex:]$Հ) =aDcDD"J$3L&d2t"'c0ē)ҩt2a>^|Ǘ#VPZ X2OēIc xL&t  j/T ~BV& ,0Uf$#`XNf;.jY6pؼ^I2<F(YJʤ]$@N**%hMkggg5ٙYܬzzFRMM4 Fj6,8 `];]NaV*5oo̓ӋU@ۭ׋ A?|kUsRn5]ة5 lAa9j鴻+:ܰ/[h3-@ f/J+퇃i)~pOLA g#7VA6gŃ 5zql4f` 0JRN  U*Q0(7`t `y͘_`"x@.##*qe&ʹG9zF2rcGbr?:%u!ãH@Fs#h8 7hg>?`JG2(BZ}F `p8LNSL+F)0eu:Y^@j͟c 1?6Fg}, 'N< {i0~CWnL/5>GP(dWb6}- (rYHfRy码xM>@+c %O(X^c(B@eVUP@!ΦKG|**R W]O"_V*UޮU*=0Zmvcs^ 4 @9pSNrRkhoU*ەzlm) pX5`~ro:LqknFf|JwoT*`noϏp@ϋ x1?|?3dbrj- V nonmzN6aG/_~VKLAѧì9p@i Lg4dT@@S?잟( ZbB1: OWp3RÂLkfGf^ۯZ$` ya<*@ VZ55PjQIJѢxʢB(ˏA@eդUQ5h4JXY*sc_Y0)j $H*Nj,&|dgh5Ӱ9<̦t8CsyqNN{7pFC.dMv0]"?{n 8kDk0s: GB>C@rr| ث!@K`>qAb3.C¢?6mw0 @|.OZ/qq~M.(>&gp/ qxCȎ_Gs%=˯RE?9{GunT/ӈ7Fh$JVa(p6bY y; iF#ru6NB0g؀#np˃_,C~m$[)˲IO A@@ 8:0u}wZۭ6v\.b$. V_6w 8fiN ۵?Rh;nR$" z˅b^^6LSX_?^88>HWɹ<4H@zT'cHqdk\f?k| FRxrZmv 8\y_£ӓccvw66ߖT& NKV3LW& q@' |i7Mj{km9I@`%rL it"gl| o4vۭ!Uä\HҰ3.n[ Kb,( |y}$%~}_PpztxP~[!p|^j2,0|@g0v;x5Z8oo;L vNٰ@Vvy󩌈D>:0<;Crgfyv@|8 J>|xw}Ճk`Zyn3<' f&  u q렱_rW,`/M!MEۡݺ8?9>Q˅_tGaVA #m^]~-Un\ _2.)3 3n` 3w:<3m7Axx h^~@N`X>ƋߤxK^bx^N[>@f^݉  Cy wsX@v1\< G2|߿\^Q)zӿt\A^ !@5NH7+ewxFoԂ26;&sv ^oKxǷ{ݳd͖j3߽E\^j->v{ݿlp60>߯?}y_\ěL./!1oWyr[(%"^PwnzM6x/@++jﮚ%*f3L^ X'_Csݟ?|7 0v Cx2 @sx; h>/Q@ \}w>|wenBppEp.ypuI:˯#U6 ?s_œ 777ӲcL!,g.I#t=)mU'm^ Ɨ/Ǥ[H> ƳJw݇.s"R٦ `yt4QO|yc_?nv`75v[VГ' DwS+ .):A5at{ xaw/H6QS%',/Ǔt..Z-tR t@bs&ˎ Dg$x:'HWD4ٽ< K?g x Kb< >ļ; K7w!"!@?c8'FJw߉0" o7!~z}tԽg00I @y2jtP < oY\S/.5 2ˁ P?˗$s<Dy6 ,EB.1(y/Yy4pgcHtY |dFŒ_?)zp @}<D6@ p^?! Y6@0OO g-X~iy00Й`<d.=N^۱333ܼD?>{?G|.w|?z^ F smG(c.?J|{s|_|?ʳ(k45[eWN/7֒ew+{^ z)Yɤ+;ÓV {P^@(@4<24(z b}Xn n?O<^e}wiH4/cc#a` *JT6P: Ģ<y i  "*OQ;SV-Py@f N@;JF)hW* W*'Q:F*0\>MF. #?9n lVp2SiQy?{np'`QUʨrfb~iRٙGF.y'X0XVhfDT .yJ'O>=%Їk4̣1* `zz^% LLE#7syta4`zZT zב<Q,!3Ҳg>H^L #ugI~zZtW)2P'PP^S!8A)4 y?P@gPbi<Lf X~_+l;T% },3nQ9ٞ`R颡`M@}]|v' ft`ҫ!?1 aAܗRy2Ȥ@&^=;5x~0C€!s.t?^  NjbӿwP/X4?H49Lb u\y|dRo>vEYigorv1Z2"dh\L/;g(a;?< ;#@6ƣ1γ29zQXܼdr蠟"IxVV]T`kk=˥`Pj!_ܮW3 O|1ʏOM,Q,nBs{rvtz.Mc<ҔbtjC/_>%cSӳhM'TF0`w{sk{g hǣQK/@/$cc#p+A30@{NJR٩^Ҁ|>@w~7RJ&$cc#p3%+`K3r{'JyworxV@eiEͼM2dRR\^Au$?o~&2/sP*uL5Rj6y0NM.Cysdb `o^`$mnvp@ Xyyz~aU<Ϛ=[彽=v~+@o YS.*U|/fN8J|7C!TE*^y%@تT*2// y 4Fn  <:b۷%p@y6WN:.i7:‚@_\{H y@nuP;>%v82MzFaZP_~# 8f*+.( P4̥A؄ۈ%Mj;X,[0؂3it'4:z@QzMVG@\8:P*OjP~v8VʸPy P?1cBo[ۇ7ngWp3K[I\f>R&&_Y~u 8fLJ*_T 6goTN~;]J+\* | XZjK<7,_~ 88>¨|zC: *<@i}#P-FNoLpLl[oo(_;?;Ry 3jpgkT, lN~iZ5pss 9:6 y}j^j8eɝ λ8ob N|0h`@ۛ&t];#Rl8A3 {^߶ІuPݯaW $ иl}(;{y4.FۡQ8;9>*SyM884qyN67=켕Tu݀Ѐ/q-߸W67H=&;v`9re` YYy6`+`ڌNzAMu ٬< puE|k r"@ȇNp h(%ɟ[n;ގڱlV+yRpA~9Z|;;=yAƆ[,&pڢ4@v`n/q.j=ju/@|`%k?pWju/c68Ab2u6Z:3w&z) Й7`1;Ýy?o4kEA:*p\yzn~uYttO_~~vGfK[ww7sz.~^Ab !#/hk$/ZMAeoγ}_\Ny8J$'o}sB-bi:XE>d޼y>p4Sj^in76}4onz.^]Y|l;:xvsbhr[ld!-;>w ]\@v?'xpt^+~&7Z(]?]0_n yzG!=Dh@ls( Wӧt+<輝\ybS:y}scs< 0L=9xӟ1f6<|7<@;|By pr]'<Y<@W~NT#&e?&utW^>O"'Z|+ @ӌny`W({QT-O/ 0twsnrp5)PKK?Qv%P@003.npyPKK?L[?P@&%010.npyPKK?:"_C+P@7002.npyPKK?Ke2P@b001.npyPKK?t/C9P@000.npyPKK?{.:P@Y007.npyPKK?P@006.npyPKK?,OP@{005.npyPKK?G% P@004.npyPKK?tP@@009.npyPKK?=VP@T008.npyPK Gjscikit-image-0.9.3/skimage/data/diamond-dilate-matlab-output.npz000066400000000000000000002737141223313777300246500ustar00rootroot00000000000000PKK?y&P@003.npymWW[Yy1Nsr.q6&@ HrP!D9*5ŝs-`o8^&iOHuڥK߸}7Apk[WgOwgG;>r9ZĿx&z 83)&Mx@ &$y&%Qzߊ'?47x Y.JDbX" BaH(K$bi]CN" j555^ [e+*Kr sr2+b@$ 8\^SVXrB2^ \&j2  :hZlO'&`t:%FUi4*Ba0Y&MYP*T:uGexx>Nz|f5o%ЂfoKZZz\N̮?'|y 3 Dk[k{D{{0 wvvutvvvtP[{t044 P5ututCouک@ ,K0 >O?ok UPm1#@pgwO_oxG(O Hkn]0&#F|0P0~lKvc[t8֞޾ޞ.U '`ׅ2? Fx}8ƣ@(Cл@F}>" uS|/DwO7|?8o+@ss1>E|w1c AwQ|o/t@Cv E+ |gHw1x8$x*N?ཞcq3? Gc1<#ЌQv2;; .1(xn.㌃q!8{|8(k{\&jkdeb2ZfVE灵 ]Z` Qk0/EfZ&%Q|hL aOihkJd zX\[ ۍT*446*T 9 Zzgf`2̰`vb.N0$xw9oƶą GQIQqaQE~a~An^a^nA^nnNFnvFnnfNd;99yyEEEEEeJͮpy|_Z#TZE}N-ToUnlPUJZVI(evv OD3ȹ@摊IԴԬ<.+JJU+ |h>*F2uec7kJ Kʓ~|M #ɺ #6!3zGX[ <I]s.>x._x9@&Q|FT_%G$'iY7mJ ]*/AG=ȉ{q%_pmHNRiV퐕$xt 6<\J*𘟓Cn\L3223A 9&L2@$OnA%%puB%e|>#pPTZZX sssr ˅!?'+=# OÃey^f#* S8_sѯO q>VMA~^AnN^n~~n4ñlv)L]OLSZz+/)9=C!bU@I @ /(Ȫ cJKlQy,_'@IYH}0"]UɪU5*@qqi)ϥցAaO>BjyQ˃s_Mڡ <88 |<2Wx H$kʓB.o7oݸWxxT|#G/_̍v(0,DeYD@oU@`0p@«'w޽stG8 UT HN}իW޿q:X ryL _QAM"+MW T 2_H ?~$9cbWJaD2d tw M//o3sTA$0EJ JdR5/ȅ ^kQTZI|G/ F -jQpxBY(Xf7;O~r|z~bi)pLV[P@)n ^p&zE}  ^Nd6XP@bNeYF.G|g[,fp⅟oܺug1 {?_ / v,/D@涡^PA'?%'o2Yr"Ş LscmwO:+H/9PFT,#x"w@S'Ϟ!>ɓŁsn)vg/wėW//RWT&^Nm0@ ?/{VaQxs|8J֝={惤Q,tjl$7LFo6GĈ$2}bu{h@'0JiM^i pLƀנ=xJ/N{Ƀ_A y2Y@6vJ?z[WX F+`14P7tjD|? E}Iɋg}Ddir#>[QG)9%%$`9˃bYEgO? tyڼv4 ^x.^H,C+KT`*OC.={/<ͻ)9|8j5;,ZA  y}x2z0_?|yrmh-%.0xE2R鰫9+ޞ6d55##@oWG ¬%_@Dg^)\pKr֝'P챱کd<^ aEkniwB=2NFz{{ډUBuZVkw kk%طEo+"49TJ7 `5vmdb "x(h'h̫9PUb9tinƫ_ /-x"NO+9A 0=-QP{S:5t --/!xXT8Dqq ?9V adx;0#͡Q* \zW)k|$__R|e%Y"Z bs]CQcB.SaȴOL&FV,YeEeybq=Mch߾{7622ȉٵ%"9 ].OeN,Pn2&9, 0@8eV9UQRUVͫQm=PHDD_#ӓ(0jivQ:sg, ,jo2ZZeCȪ:0$Rds"OE&&''gvl;9Eu[L)C) AZĵ8LN )LM̬, %|I<h +t- Q^IU!BhkRƝ `)Q) @ >uo!~fN&A#'"A@ YL,i3!.t/@. Xf@`;zJDu{}(+ 7*`2hXY2LZ-^$ k`ϯm ,, Ð8"sL)"`]܌ pZMdj* aw_08=9pS<t"ȁ&ȵj9# c(@>-ym:uyv|@0Ddzt@G2/wvR&5ŷ@fИ,z(@&ʨS3g?f}vL w`p̸HdvpG/#< w)JZZ `s8IQihl)3L, ۷O? .x1a0wu. oXL.16YLf^QCj~shqſGѮ)?-%wNhmw~֖`;:A .ZmO:ro1H'7V?EQ S??<:>9>>zN٠U 588:6f[rx#Fc=x)x~~qgcevjma5P< ~&2N[}^zh4*%kc-OS3ve9XхE*ddzfvfÏ|_L10 ~q>TlMZZWT//%]\Dddnq~i xO_|k$Bz;PKT`KQj :'ť*$3c L#9% _WP`ev_pCڂ-fLz*Us O" ?$/.!t87}Lf~f(ƃ0UfXJy-^82k+' ~֡cVVN0kdyqkjrpgrd6B"p8lŪī/eeV' 30~޹9(97v@)>Y\+΀ul,ԇjػΐy|vŠ)uu%zXu *D"SNT`eXi% ~kwks>Y]Y{tx/slB tzϙ[gk_1x"Bnvᔼۗ]@ĻA)&x :zRR(d\|).a˧?:d60F>*@*a:C"s3Lo,Q@ Z&g^tx5x"`1j)Xo.!~WIα |NYeH/WJO]BGl@,jpЙ,4^4Q`]$K\PQqkvɯ ?Qm67֖"h!c<$fX[rWYm>O\8 T $SϩWϟ?}8<%/poY[1lk6HEF;;m"@yb?~ۅ[_uwo1}fX F" @(>m ,fwKkW0*g9MG?~8߅q`WfAo0H+f'^o'-$כAfx*Ɯ٨Q N{jnI<8۱ dg7uZJY za-،IP᭱ s:0bxf(ކi (ubD2I; dĀxN8>V x9~LPmf;;%-,@``'߉|'cүW*q ^k'~p7?7<ޗж`Rn'nAVuY"{.\r:{=K˯VJ:0x#1~*7[fO+LGMX;bxF[:Li5&L'?^'W҈(gRَ(ޠ2{loGX9Q 'W&\]#فsjAE>&VGW(+(,vWGh6X'ÇѧG;wyFo| z逞-z KY}zpj^6WV zȽ2Ji緯_%@ 9Ff^NIF>#@67*9 YbVM£ۣxxF3a?3k//x-H;Z'xlM(TU5*9Pեg<>ˬ9 U)g)!OL3ٝ퀷!`B2 oLQեi ||O6ǛxM5)?9!p@Μ/l.VM42dЬF%Q.WXSPXK|t>DF'*a~:sµt/^ xw6T`d8L]S *Ԋߡ|]#D0*@`-3FLx1(+q !xFZ'k)nCţX|?Ohh:߱N]xQ&:e PF SzpA(^.FCMbZ:!?ǃ P~lӥʋ'_{ZBE%{b.(H"V3+zG#<9XoY3g1N׿nҩۛ#x$. Ƀ9w ɞz~@-17#`.=3_tةV73i'ȵcGK^'SsHl6B|DBlW+G3S nnq @R.WL@+tZnC<l)㮊ݳ-Eٳ:uY6Y5OZX= 'zexaU[:o3g3g` @oOlߡuLdfq}g?!djG*uԩSΞ j3 #;6c3N{\[9]& @ %U\?]?t;S )s> G<wtމ/oޱ{+MDy\H gwi3j >=)_X@<星cxFpwc5ҧ/*Q'x@$BQpu;iy < {o!u8ڇ@&:fcc AP""Oc /-Q>/#vE6O;23G(ͼ r9K4]t5c.sG[S sxV-\бʊ 3SU^qG(kqXjxŻ]$i9onl>=/xdO#^cxgxډ;vhn"ľ@IЂB-_[UܪКm[-5/Uԭ[@_77z~xߠ/~~ϟ?!o=D#8nE0CA=6Ǽp"F_[KSTrmcM$גx<)>)x)@<<0~q0k8~ Y%|2g^/G"a~x>D"Ax!ly6O|y4/ / `\@x,20y0< @GF6M20h O$@ʯeC_< H,$~;`8/ ,|kuPy'Ÿ tJ+ȋԺxP$Ч* s"~hwt8H]T@?_ ?$~rl6vH@z}ݪN/z0m @|,6< qsvn_\ֲ;Vvp< '[-6Ŋjw8v^vG NݮE 4q@2xIJed^6`2ꗌ\F57:!w}[ )f,N&VEh ^EEi|J;;RTJjZQMNMO*R nooKGQټbY`۹VةN`w{^;<,~@x< $L | 43(Lx Py:/@we9x;$/_ xg _9![y[xH^|rTm7 ʟ5 / þbbNvn2l8"\5 )d<0j5^}^3;;I & 3a}^t›0xqss0q:azx)vj5 Zk,;n8^ ~*y&/_yvyVx HƃF!5nXy:+O&B@⹀d<r *TUt`&+O%B8$@"!:`FEF'uoIx>F4YOb5x4p@e d0Wx?*4՘4dVD氄ժhzɣV/Cg^۱ׯ~|F~?=RMO%CJ{{{<``jȫg#c1RgIR5\baր0 `lVWO*&FG(B1TK|8`ZT*YI`[66r d5s$@9VcJ%JE+ /Kx8luyCZVNٙY\e-5:`sŴ,-n0n p&PQ}eYt 3$@/@R)/%=ZK$ (ZM8k$t3L$`F 3JP Z[[]=( Xj5!\Ah?x03]1+QRiWh-lf @$ "P eyo4z7 ! ?%<`7'|@?JIQ- lo5 phi/U?H^8ѣWldэݍ_b]6 :XX.jV<NInH~@xDV^(XYuAF#hZ450_n4 è/yp=NFCd-i-+ <*ptDP|Ȓy(pa!B~nMK7: 1@..PzWf}Dvara`X. z-`_@_?<|Jjcw{?A+$ \B>ˁ^r7޼juWϥG XcxwI A`B[d8yVI[2~|x @Y8N6}K^a]1&GX< h6PǓϫ' ^@ӓcxvsX$p6 LK%͜j|Ty@g0_7u/ | z"].õbԽy3?;5䩀ca&/@|UU\s LkH.ˊb29&x4/ |ݬ_/(8=*u8۬v$ uj6fpT`/~?q߲xnw)  xb~eV໽wg83P.[gXV'Qx~5~߉ ']_śg#ß?}|x`A4߻v;rH( 4|E\Tb"V=6eQB>bՆ]ܽ8~yǟ61aCw7j"~`#1/ p{|l{OHF>O?4oY|߿u{o^yf@NO?n n4`ŝ?|٭u<#E^@#щ]ݽ},eܸ~? xF`Lx8܀8 ļ*w3Itt#;c|K$xw0WmkIk ?$ U[8nayo+MXxvsP8,W 4rYhN<`\0yY@2_QF$/  0 >.< `8ɋ\BCW2< xwX<అxOY<yӷt@߷npdfgrA GpExib)[:@;,`s@{d3''\z=R>O?PKK?,߻+P@002.npyeg_ڷ)yQA슝^C')$H/R ޛ "]3~s+8g4ccsk]^BW s*~:~Oyʊ A/~B_ r:??\?~4>/mP=F%5Py/ϝB`G37orٳ#}9ᝡ`{sLFu^-*Ly ePjO%sOINJLNKçfRI!⯓M*/\+N|>ww᣷sh%0<5|kn`m~NOh,@32sr@M>RS֍7〿˥7eeSuGx*C/_ ,/T}ۘꂜ̴Ԍ,/'3+;7?N'&>OKkqqq=| $#;~S 8W#+++^mipYTzUZT2\V(*N]W[VȫdUUUbiD" |^/+;BW+kkbJ..-|?ÿ"ʊ>\wv86fZp.o/f644Eb4pxiaݜ?kq`% [́cҌZ[C.jP{( /mm[KKkKk}wZ--~ׇمi~%?_;om#` # 6tQݞΎAc}iqo·uPP[tg7>tw)?842<7ſtu@`D@f~_ v1Ըh ۋCK߁LѱAj~|B]Gca0~^224L-IGj@@k+$ QV~,,@e(L/Qcxbt?gx}$nL qTip+|XF1o  r=ݬ㩰10#0_/: b@s3&a 8Ft=}Ca|QI g?,0ojt8ܞF7"Kccr:!n6cnclp3SF]]x6z1(YaH_$<S:um^ѪUu*ᶶVRkz^5b j;vp"!8655yM.7V2mlS[Т臾I*Pk[+JmIFQIQqaQY~a~An^a^nA^n./37'377Wd+*/*.( JB$KD"L.U)\Qk*lzwLZd4M&Q%+iϲ*5==-=9)S%aƲD|~3d$ Ұ0eDJ*+5RHT[_UDKIT-. *~z!Tt1di,YH22ɁI#z̒HLLJ|i3%PNKaxV"5@H__/# R,̃kP\~+ؘ3O_fKS%%59(`B_RA ')f0@_C$99|@ <ĀǢoGU\?sI*&l§s}'`SsssRSĻ9㨜:}6ΆW]1|fϲT.~YS{}:PVPeuT`boS9{ltT7]|fHDR 뀔rJyG$ @cgcΟ=K7cb` s)τM6t x蔔䔰@X$Ԕ|WjHtT04s&&^cwJJe2\sy/,.,¼^N.$?l` BD+*x"()K%%%Ey)+3R|.১ Z{^( oHӊss+$yv7CiĝpTbŢJP(,+V)J&5 < A[nAa!ꙣ2\P,(VY2!KRRݏz zFq< E$!a k _X~3+{`$. W *KA^j+$ /aݒHX46 KK @eouvӅq|uJ"b80RQoPIz _r/@@ ߖcD 8 w|dQ^]R(kyeWKm6@|_9u k ;P\ӑ7Vo gjyeeZ-mTOI{pKx[W>:Em3<&R1w."bx@jY s x|`u6C]sSzkI?s3 tC[k0RxZwML.3'<| ~V*68T*kIb ⢺Zr>~9`m!Pz/q܍+[o0 nWWZ1*qu5愔Լ9r /nA(/#W*T&H R%)JOM@Uލr: co6tt/ШՊf^"ٜ+ ZSCPͪM_/FY*():Y65*YLF#ڢ ^ZF F_R Sx؛퍍7A]FCccp8 h&e0*Nv@-fR>T (KѩuuZ6dR%5R^A+G2^ *!|$|#& Wckkj<# Ȥ+%/-``TJ*DB9:PT$PHQNjP<]̯roSaqq,P`&*k4\ j!,qbZ[|biid8*BIJ^+Yʝ-r~||9tIMP'|۱H4uuz>Qș@z4! 2IuCaIRNDEKrN4SqY䥓744x{f:ۙ@ݍW`ph^. CZNY%e aqvX \Y./7+tla_WxB3daT3%7.D_X_]$h8tPBW|#O|0LVrVNGɑIu$KT$`>>"(x^&kѱH@Y YZN+Uˁ.L?='ņsQןgFCKk5x;( Xz֨1t`?~|=! cǎmv} 1'䉨+ %'"t2.sJ=_^  zze(@F DGǏ <ɯi_|510||<})diĎJ9WWsdv-g( 'VVJQA;o ,2G:gAY㧮NJTб C_;bg)oğNB*4JMvjB)ln+q]>wt<~*×믐KLvQC~hp-L;ie/)y.޾wJ5Qyt*6{.]9{'O=/qFRnDː osaҪZ(z s ںzӧ ׮ŖBT3jvi: 8|\ܕ+L yp|{wSy%%,."ѡW(dRqُ*7[ nhlir}>̀b' 'I%m}d O2JLɨ0b A~ |,H27]b1kԃΖZz OR}n0|'"( [9Eeel#Q Tl ?Ŝ<7tP4U ǰv  뜘ܲQ<%!PVv[\^YE$D*V6IlmA;;Zl z9MzQ9:@ax#]aIt)}vwww67PVW/.NM"w9L1! n N967'՘j4tt {sNww7XYEZY: ӫCrvfZ+wqv#qbBa=E aC:uZPkܻ]}-Jk€.kWA@Nb/?g wׯB8&mopOx |H|.9LZ"~ krV3Nw*_16U΁ޙKS^PCfY:n9!?ݰ@+r8mVd  -f)w""R?X[:3M1^/)1fdWQDOC~v4`O 9m Hpb'HX^Cʇ3dxbllt|rԫn%u;ќ#N_7꠫/&L4i#4[G>+ 0!elhzfvvfvo?n.L y65 b ??7;-/F`3 :G;F??L/&'?P0,Vy,ޭ~9@SKs>"|.b4MKz]tI|^WX  [L0o_}cn*VgSk2 Lno6%wހրPĴRX^QQZJܬT͟Tw'|dj([!77;;;=9Mx&~i;f#b?2 L`u̳M:/>sƶL#ra~v۩/F{;[Z~/’n֫b ܿKs2~vq᷶wI^ -4Nhc^:s&X~ȯ߾yb' MM.[CAWWWd /~q 4M?*z|Ah_ &>`~iv ̇v:}HY;~{{~ ږL/ί뿹+ɢ74U\q:*91?f@+_~yu/xvûN^~cy|` |w. h*Z.W>9{\L; {o_? ܠ s 01jLf»82FV! /,o>?kR ʰTI’n޼y+8={q/(_?Ѫ6\X/moo/OWdU /&v֭۷o3<'ӷ?RGl<\X nŶU[oиk y z9I q\x&|r{ .w+aO[ۯ[ 'wc/pW~8|BO$ܿ믟?~<ۦ7C/xH4 xn51$`;&ՖP vaط9W3P> 8qw1<>}:ikD~96d6Z\6+`{I90< wVz[$p{yr]o|Ɓ[^$G nRbw\[]o"vbrhim C͍>ӱIOxN LX'*yGxd+ @rx-?ox&wͥ$@x~?óDx1\ʬN=ob6νw!7˴.QlVo[΍#Ǐn`)1H)!NX jV3DG.c]FBbv ?q{ᴢc^R''.>(b/~-a<&Nfk tFլɿZ$/aFPaicǎGE?yfgX)sb|ج&:xj &9((F>(fB1'ngOD<󠰆<@ɇS9vXDm6]52:-k˻oۯ_?no4XG\.̥ l%[Z8 }UXÛRŹi`|fï!i,Qoa!d g@6(ő;qёgbKu ZFcu+&Nh7T݊XvrxD@/wxl x(!v;oo~>x紸Gs'""$''|7if @O/5b@ix` 6 ;WW?dk/JeY[Ϗ>""K,x,)3{إ[4:-6,aV m-v:_x!6WJ"翾3ӑQ'I "g=U`ZZ[P+t[+ݫGt&.|._@"M87 8NDݣ"~8vk T=w3fZ`س $jSQѨת}co'FV"|r25"\(]; ;?yu?~:>_o<;k ފVchiv [?D  ^f yU͏/Me\z(X !<'ІNikݴw3n~fzzO_~a<'8zM7Xn zvI`nQ"#OrZ9ӓ!tvٍofKߘ>}_}xFJA61|eeH"T`a䘜7y~ i47cAyE ]_\ ܈픂<{WVJ"\&l(D=qT/ is sRS2.R򀗱 * NϞ|g¸ %0 IFn1VK"zv,N{:(LB ;=ś[\.Jn*|uS/{&(# :4 6 v0)c9V,-YXN+(9q;_Hz?gfc3t)y|dLl-7,*À%<`ύmj+atY_MJHgIfXPO~Zԉ˗c{?<ȶ&,$#[?(JH+(> f>'ty۬^ ^;Y8<ͭ ;4ogw{ϓI #3ҙ@frKOК #8cGa5j>`xn6LLMM.Pm︓U$AO:e$%%g$?{(27&1<ݓO G_[[[V I&=&He +v' hSbO|4>''=Q܍.]PKK?9r3P@001.npyUgW[%Bx[e @B%P$J rc Ƙ D*_WϗW܇;g&Ùs\'82ӳh%7=v/{>W|v%<-5UA>>Pnoڜܼb^\LV U^^^QQVVb%X Zq1TÀ??oޡ5mmzs{Cj?_ᇓW= qt|=333g iEERK!|zNNVB!QLhpHཽ}B3zn2jd"N =#>wxF~(!v12>5:: &ZWjYO |Oo_JNfӋ i4zq 0(a@@A¬gIK}86_bOMؐ{is٩dfRrr)UX(-)c16(&BgЊrrs2SɓO>}SDT$F=o4L՗N ?8:::R2Vi9`2 VYyeuU]M}mm Q\TLҊr2R?B"gh9ٹŴD)쟚˗NNNX}Cv mmֶVJjUrEPZv\7˚fD$ 5*vYy5_j+Um-rD,7d#1ew;C#۬Ngo7ҡnY6bX^r:{zN~bV uFhvgG:ze*AVF7K¦Zp x#x{=n7ᑑI8>2Rccѡagl|dx=8844@vg7 `SQWgpen0% Ll\}m]MmSuM5SUYfUV*+z6S][ǩ64

    $LQ% :ɬurZ3Kb1YLiZrJV򓈈 ~jj_`͎  %q1Օ(9 vu%-HB\1RDEI15Gp(\ےx:e> s++d2YƳ興_?rkjQj8W]WSYfc`o %w^N*\0*[ْz9UǏ322)s +IM{0"YzZN &n]]S6*N%*%x9<(݀ڜ5J rY02ɣ|K+UgggkJ1!aZkjl&ĮNUU-6E*ZGs [o^l,.)!**/4( u^N"p)O4rC?^Dv-w؜VkJ]*F5F!I$ZFfFp`_XTpO`WhmT*E ><<_\\Y\]yvŷ6yICGsمeM|Z7X%< Wf&@Adfd ryLJo!":sDJ?8=e߾~pjyCTVF3\\K˚lC`Z%1Oi Gcͬ*3ZZ1RP(Q@ :A]͕v,A9?;8Xu4+4ZY]ŭk>B(LF /--y] H(BNye9J*Lm002mmJZZ#:?$04g|-`YJVfA^iI.*+`GH6:R*+k̊ Pj]Ym%LVK=K{?utv]xM]#a \%C9+*ՔˉR)_bnkUU աUT \ܨ65rR>D||lAHVf3ĭ| l6gs՛9f|yiH~&BAKB6T@s٢vAjaD5 Flђžx1vV*ocB6zZܩvZ_Jmi!d~ UЧ55:ndvCc=˕j*LkdK߼'l6R$Zy}y~08ꞞKnF@&55Ǔ2r9DXlƯ'ͪ+ yHHOh1PpT%5kXEL[5OŨ͎kkZL <`|/*CRjj4znSP͈@->[|}CP%|@Uk[Zy*y[k.OKʧb;9vS%w wrmmM|CC*=)6BVޢ5p<na=,oomS5P*<'&(!y c!ol''ײ|EP_56KU!QZ1i]Ka+q)bWB1 2]&%EA62.'Hв2BC?hij1`LFE>d]֌D_Ԋf-AL XX,H&SwGB ڊ.жȔHYPG|g\vwoO i6?'ג- ziLTmJ2=$[dw$Bܢu0-/i qY^Xq޹IZ=;OIExL{ YyT^R1Z0+{QF^kVii 1 xݿ*isvY~?>.iuaA~~ABa)/#9SKwwJwobaU!&ܘ,?ԴT/7*@)?? 8,2q|5ޓPF3ux|v%MɇG< !4<2S_@$Z%kP++&22:=;PDZ^>! hadd@PTR]__IR~_ s> :2NE왙v jEԨX *Z^~yzpph Ica*-II|phE?&.<}l.T62<1528rvڬ&Msr=orbrul#>EyOcZ[_-}zzw_{G CB#DD?m5 d*ShhPũ @oOfYz|\xuz>Mn52[UăWWaV/--eyiiCQ¢#ǩ١T$-u//.N\[Y槦{{,M JJ$tr~ O$ EށV =zLsPրx T&%Y.z` + r`kՋun'SzUQN(#b -%K2~ԳEre eR.Sȉ\^]^^.`X{8=?6v:]E.)}wDM]&F5#7SUVTB/r e fUHB)CGŗ Z][[_{rxƛ7o^w\(I ^ΉW_mI4.f6?BIjV^dZyC#|CC>vxhX6JiDW|v-Y]~|vavxtrN9;))%A vNzfJ1CbBP l44Qk6RhveKDd60M@E H_o#:KK S}.%fSRs77s3Ng|f4$QPSf#--dӁLn#v"z{{w{۷oNo@'\]]r+%%슪bu"sskoo0wٺ@4nA7dVZZhthrHZ֦$ 5PּC\[^jUUbgxfucYVsOL]&]AQӊ)4 1|nӐ[P6LpT~~zp'}usqqtzt\ 2R2ձյW{ g2rz~ vլ z}+P)Ȗ&M\ђO@_󯌔`)QQQ>,f9Tɹ1)',SNX}{+ܠҴa;Z&@C"R;H\0K=D__}8?9#@r 7:`ed(;kog;w/F&Ƈ]=.=O2 d;T8MZM8tF(ZN,k#UC8p~~v~zr|t0>h2ӆ;;;뛛 0w...vff~.C@ڪ:L:Q֨)|jTFr[KGިT8sփ͗/ݣ}ѓovw7WVǑ-W''k#̇\:'ڬnk7!Ў7Aѓ C3XE.F,{?ޞߞ黃՗k #nm:r萢F # 0:[l5@fǬ>jӄ##E(;~z0- }-(| 8=>99(j~)ZGQx8<99213;̮QGk^5٬]]&D+69GNlwZ#h< %M\8~fի9gf{k<,\FcɈ*o3vu9LZ>i[FޠiIFQJrH(4_>__\??;ClBؘAЯ\Y8%O 㚲Um0vV620F\cccV0uiwX-fɬӡwhi"_Bd\5r //.ΏO޽B .mmox6r8Օe F?;Wowmϟ?R߿oo@`GJoi;~w|nnjl3H9pm]֮ |>PǭzeyY 0?woP^o;yzskc;$7;?~;C69a18k/_<_-V[\ZWS˩4ԐNbZaF?8;:|kݝͭ-x"`k2 O|zk=ft݇n[ߓ-|ƋK (C}(][ U*vyY9(..)|:?]{vs&!J-m7=vjB }{%CJo6_XvQ6^lx|rZ{Oﭯ;olE?|ȫkkW}}N'rۨkq9^!1_#~޼~bqnzd zk]{;yZ\Q'ͨ@nowwvwuwkB`^瞛:Fӊy./o./ᆳݷk/@{<}<{IO4etlVu|{ywvvy.E1v4f\Jn }=~~G{[^ fgܮ4/H6#cc||vx`Y^?Teeۥs0J0CӼ|#ÂB>~rpLo?yu!te'9wXQ, sSՕ,U;_PPe/.ϐ؆+0]vy 8;=?B+<^W(Z|6_YN V-+> F&''?OJ|AAnnnƳT|t{CՇw ^ol8{FzN 8#t윜_]^^--┇b}Gz   y8,%%%55de _~%Nv]W_yaZyu g/@䝜]\u z96)=-=%]'u 8<}G8ҭ%4e;!Щ7ўE=%4cpA;My}f>O  x  B#{ S'E`9LmF[l첡CJ J+*++"hN2u;,fzɨv{$o}˯_?]a+np~p4FxG#w #BM5PçvQ kSízcDz3#2!_?:^DtZjFDoqG*`//_/IBM}''#r  UB‹hTG2j ׯ_|<"ll |`V[ 4p䒓pNвZT\in':FHo_ WOzَ;_\"]wo AF#0nxQj$+lqn#Tnybcr[[۷_^l_'j&XE.cU=l}P̚r}^J+fAT[ɣ66ޝ_^/W ¡ď&_A>jo?0SLi+R](9444Ld#QLԋ<V2$B)TR7`4u mucm[{0>޼R\|l>p7ʫ_\Kjq7V@Ɠa NK'.-(hfN^V'lVW Fe%P0׸O__~|0cهAa&]nW_?Od%։-}2֢Ȓjg6TeRagB`rrD TMM^>>cr}!TO_?yMawɭNf6 hr ~t_~l&#{pOo̩BA (}/o_|L}ֈ108$ZOxB`td3=HnP wbÓ+/wϮn?wsO|r{'q\\. x']Szۂl{]3A2`d_\VjǖV_omm|_?:Eg- I FA 䡻FL] ۏ,`@0yLD`p>~gwhtp.riSyzS޻[ 1-w>l籞=Ms rrp$2觟#؈ mB+LD6Uǃ້~S_`T:8% Oi=$ɃH"r|^JJz?z\p=DiЫK[!r N\]t8%2NQBR1GD= lp@@HB2 (;AbQ]dwt"y}{ZV>ɪ 5.Jp@(gP&qO= C;{d>w= <81$S{d 76~Kʩ6K +2X  e>5P /"@KHŤD^Sc䰘 zO*Ţf:Jޔ)Ꮲ&$/sׄvEW]6 %Vvv- _^^ `Ǜь6yS,cʺF\yD^tBLSP{(] :n}N+Zmf./>yMYsqf<#'"pJ@9:Ʊ;{{s7(7ҚZQdȾ!(x|IMV#=W߿%)$diԎnn#o19^_?&dReRdeF Re_?tu}Luq \'ګ~dGFeBΪGO2Qos<ف(,PKK?t/C9P@000.npy-W[[k.xmӻj sYD%@!(#I" 66W]U{?}ӿt!&y7CU 5?+*ش(^%Ea;J9O."UBx[!K+.B'<) '"ȠQUhofffS#dxm6>r9l.d87+F)D,"&vzq҃{Q9¨ɧ$xh4 Tȡf2jjkꚘfŬklnnr[ZZyVbf`de&h"KHU:wNz_~JjhoJ$Sɱddn{ ҚZjf7775Kp[y6ᱛ9M5Ey $+-=!>Bht )u(mZ]UJD%׵K8qhxll|b22=86IU c2Ml6'00uu윜dJQ#<437vyVӪbN s#V9QSUSmb56ԃ4ě YfFUmmEYqAvNzzrRBrZJzbRrBBIK д܆>wdaemc+[;[K{G@8^;¢ʪfVcSS#r8ںZdH}mMIQAQA^jRrb'ĥddg0E%JONDf6<}P8 g秂.].hoZx\V+y6agGwWX%sfvCScc]}^^NFBjB8ܱ bwvwvvwX__YD[A<?v@MYCVj!ˠd4BͦAt;3! A0111191:>>5 N͂G͹HdjzlRka&VK, ;:PB@H!uEbX'dJB.T~R=AkAo&hi#9=nf^76A#[UV\ZWX\XTX\RR_\XXTTXRRTR\TPPT<V%5pTVWkj" Es㇣6jivπKH'%4B/eTVUVWUU.(/.@ZVaa^V^AQaaA><x閝 ]?.(,//Jݢܼ*SvzRRZFJf(:/GǥdPt"Eks#<5640++aVTVWV,aVT.,-+,-*+)T_WWͨS +TNYQaΥk3@'`X%h,DqZ8hQP__Ј 02Ls!p9-ZMZskR76$}h&ţ1xT4*C"D2ZֶV)@Wͬ B0 FB8EXL.&x|(BK+[;&h(H$.9\RVSCy )Z[UOƣq8TR~FP-R])loA#(V"<8|@bCx6Z)P]IYYUy\S$ӓHD)MtD%%o|AP hkt.ST' d>E8_GǺMwZSFE_KOU'`Pd*/1X|JK,`tJ^IOoOOSڈ:;DBASyf5VUB,lwttjw*II܌:^_uzE~NravN7he54ZM O0qɴ4zZB|<.+d2io4vEbPK$6IbT0-K$Hz5:62#.E *WB]C: A.;.}l|N:BpܤBPerѡO#%pY,y| &0P ^:`pubWQΫ{x.6'QxJl,X](/WUJJPHe ТO"ӺyǷ_wwl>zqrvͷŪ&VkC8^yr*W'R 4 ]3 !J\*CJ mdՐyi̓߮/{RNfg5&aI9rKyq!$50;6M,%e)Ff@j4~C U">υocZ"~p “An{=8 '"v? L$q*Ks[cTt+E\v;:@4׵pKcIyiY4Z 2P@ȤrJw <M Ez.Uf xBZ:iG1*`` Y[gיT=A@\iBҟLHBG,~Hԡ fbC![N"i2%O91C3KiPQQQI^-@e'W($RuSe5!_%QiDF9 4<Keζن(DCGd'c5d)ְO(Z.“8Խ dU8EQkTA{~ÐRSu]]nJW#b1$F=)6"Q( 9>э{)RK$SH$:=-531\?]Q'2`1(,f_U3H=UaȠ PC&}(dgdш8:a ZxFf_9 F՚,zѢJNs[UzNi51hZBR5RÌUH8":eQk"(XJē8<-LNO)(ʈJ(t<1r|W8Qo6ꑕ!Ūt/~ǪpV;Qh^\OzEeDQx,ITG$ %Qr* (MvQgQL HW<6upHg 6uK05NPH?d7wfC͑ ؘ?=4u8v?i*d&IxZ||M$QHX DơDjB`q2&[gi|; Ab*;#;s#ãc-0dut %99E3 Pظ6mUޟ"ŧ'&$@x4: iq4(*V$([f2@Vi}r x.ժG]#k3?j]$sMf =K\yDMu}hL gf''R)<42lO*f E1bLJکp`j8m֡!FbٟZ LX|EfUŗGjb(幉h ײ Hi 蘘hEs!V*btzsF>*yo#-0? 9Z -1Fe#.W{E r 0JC.% +y\d|l4N<~:866fńIEFOAh廞2v[g/+˳RSS􌔌Z6[ IVd\ءFf݇;Ks++ +ݣg[6@1_K0)Hhk:k{\v7z>Jt;L4K$m|TV%0mT~du=|d{Gw#$& }de.\^/*F #4NyMqIyq(Ԣ(%.##_3gxm{`ѓ';wvGl¼Z2 O bs>-b!(@JQ{b,1? #3FA @xNo Frߠ:Bdɳ'?}zuzry̤!<^ٖ@6d\\xbm︵Gfx\PFͩ4xihzE3b0뚘lNkTaMFIo՛ Ϟ>zȫ/^>_|9=3;1H_Dpeea ^7FAɠm}vI| 7,feITϞ8zƇ7N^>=X[YXqtAzj\UۇgfsZ-ɠWennYz_LڣR!D_g0Z1|&h~_tLJϏO^\{᫳g7mlnG4n,1xxxpt|!/!Wdnyyb,02h4 @l6nY,?Kv_puuq m//F aHUsO}/.o,OZ:p YZCv04ЯTQPkdbǫn/n.޽998;;ۛYՠQQ2=>8zd!dۻs؈k)C9<Ղ\K (csNU!+_~zӵʼnP_2u/O?z<=>ݳT$ <PИ!C YoCs`2;l.rT4ѣKpqw?}wW; v*:`{ifu>46R`u-g"{a] T\C1vylېlDiN4kJ#`^ͯ>^}{s}ۓw{Om/ͱr鳪WGOwgW3&ejSw=6Q%ѺG.P)=p1 ؆&qd:hȺRI7Gw~xwoMG4уO!' +]52}WOiC>Nfv{G<~/043; ٬HA nW?B iWk˿Ϸ߽~}tí㋫k{s"[ܭ2 NU֑0_ N=D8y^ᰛMfHBrA]~d^q{_o?ypgqߞ?͝q@&z`@Z#6휡Ko`zy7;6=47;19>8 Z\^QXl-Y?>ݼts㣝)'w6?y<X-zR hN% L>ġ9&417f '.!{ׅ#^!/A.`0yoS+0o^ߞy}||g{+Nm,D&'g&GCN 0ƁE/2)|LJ/m-,M#Bv{ɤwO&E.߿~t{}G SO@yhçϞ|ӣ'+ ~A#ԗozq~th1;;==w]%nB!iεׯ~{ExyWgͻOO/^]\<9y~㏿gcNS ~ŹX8v{ܞ>O%utvuu:څ|>TW1뗛߾~%@ϟ]} #@o~o,OOV&/.>1yˣ=Z[ZF\X$hA}utD緵MUǯo^xp389|>GDꐺ33ᱠ;86G^9N_^>.-F'FA/0t#|Xcs8 9t{;0*gg"p(r%BX ',V#0=aOvN_<>>>=8ԧa'6۠AoM@ax,BQȤ^8;=9zy$P()e29rW)lg<ًǯϟ[//>~ ;>[&x@&2 ,Oi )tjp۷o/_|׹9pd~h@߻`OO__<7ןx{%alM9a+z*JqT @͇a^^?|Id bp#`63m###þmt7yUUL=utQ)lT 8<@HqtB珷 ޿y}c͍@]d 7LchH`((?v9 j؛sd-ÇwmЇ|VA˷Wj# nbpPk//O#&zfaIQaAI^qeE%D"/J&vm}߾|0|(IȮNǬSzC WWwjyGe:UX’ΑbېGĠjRV^nvafV"s/U.FWn/ 桉qdWipqUX*ˋo.!>^0KOBq(CL KkJZ:U_M/-4NyFrrg uHmNuU~7p`w8tҸXtԽ矯^z}㝧[BGcd2OH-/ɦ0Y - pGgWfƆ=u G>(V̼3PU {=5܏'7|H`%)iqk3GCHXmvA%sO@}x514]? j IYit"#bXzsgL!Si8= _,7a^xߘW.leV4"=@84:y]N+@Ȍ:W@1ˡٳˌX"B萟p<I  rcc^Pe/A|MmM8ZجƉ` qiڽ=7Ƕ}ڞ(mbjj<M'ӨTL ע@g( ml|bo1]n`:o9=Ξʼj&օAG@RI߿|xݫgK;9sG‰82Ƣ2F ('< <<:l }Ah8]vhkY-"!%`h m6:vOo!=|<(qTB$ 9e3CC] Qca_.D GߐR\G.|`LY/,B^폏~t?1 D'`@%bи"n7k)t%dHfdpVf*`+b=Ԛ@Lɯhlɿ~>wz<>db|n? GPhG@cDZ>4 tC,&&'|҄ 0V,V3>^ծ8V!72O18"؍F d.ӥZ!"{*c׾K` L]͏-fà5PRꖩo?^slNz 3qȔ Oh%`QJ 3.NgE"c= md8GC!`Q3LvWY(-;hp2gڝb'h+E>FmR)x"6 p%t@edACB2a/rW >ZZc0{FL+c~Hmu_zw4@cPx*9$O"X,'VwmY?>ߞr;M~uqyN%r'RѧꆠZ#i bQvQ:G"\dj~kxddI 2Ƚv0Ftn@\7ta3YgW/=MH&1^Lj_3 MNNL I煙3 fhgwz'7+Fg-tw_NBް<:!!Q$bX,ONW{|^udzjGTC:b~px0b:q$V٠ F{oW?^[T*5H2@O?4`4А" @cKK s#vԸnۃ  8RqFZiH5o?zQŨz~>6& +B5cxb~~aaqa> LLBC7}]7 FdKWTxv˷~߾ijM@$2L S1x2@ zy5 s807YvdtXfRQdk˃w}oFϮdەˤ2)xC6{B) &Ix/t ٹphvI@]G=jן ߗ/_~JxH+Oȯ4d}J\*eͱcPhdb42HC3|./855=?7;=?AF&Ǒ r;K{O^?߿޾{㐦[JKcW2@4XOYЉNCŐ1j<%{ 0ATcm3 t/΀_HczգYo[QP\U,j.*++2H_ˈAapȦ1 8Lb'uy'&NrOVȝb>h<Y#xh?}|(7'v^Ϊj(,c j LѯPбX4F'cቩHlE@O {02e!魃四;6_>}{{xNQY`443b[_]) RjTT=HN!E%tyWщȿ}07=.\GYŃӳ7׷w`o"Oj,V# AMM)*}2@"QKM aw|/72>&:h47=50ۻŌt[eMB_-Wh$chhlxDDNL H$va+G֦NN_\ӗ`/w^V728.,_TSvU*n.J%P(2 INxFp0|JdA >69O|}tS¨m "on/hv5f*UJ"i]~~C/hb-<.QMDz\BfDOBH`h,LkDXd2h0B0# zۭz[$P|tWTVY]SuMչJzCT*FuS~,r|7N"]l-&0ջwW?>9ѩEUUeuVn;Y_H&3SHĤ*PKK?/s IP@007.npyio[יyo`&i0@"h'i;@qbK}(EHq(jeQ;oIIf˖M><9w9r{*e{l헟g?w߶||lŇ?ύ-ߖ[;⣏|ן%#ZӣT**Z{=݊֦Ɔ=_oP4GD$p8! ï(4`!E#,  `B`0M$ӉxF,K&H&dj"=1OT<D* xzs,Ob4`폐LLx s9&E>;?rLsc{+/, $ j _+`ne$=j8%|ʇx€PXL@ x6 ;`@`֏!hRZ# x. x˷ Ҁ^G0zxҀ8` ?={! W\!  W^4?cT?;.bw:찲r8\̲Y6k(&臵 t%O"ED:>T\ipQ&?XjLe'%8&0 ?1 r`@x6P?ST}}hTA݈nhxt`0Zg2Vd1Yٕqrvuþ =L/E|p`C/qaGQKkssƧMOI}Ó'uѣG?vUO{C}ƖfR҉|t 6vGGt#G[R_3H' $~N [ǥ9_<|X$ K8ls]]Μ];(` v7|S6FgGG{[[{kkkSskK3QxXLEhpDVLHx$ =}:֎@xgҒ/ |g_ j\C@^:yjcȣ/ Ǔp" 0Tr|c_k4<_c^ iLdtvE^a}& fgf ^W p@Eo>Ss<_+ռ0fxbPX lp8LN'a^aLm~c}$:y І}b~+TȫT,Ï7hV ōVÃ7g=,oI/eMgZ]?VaxhhppP ɕrYP(߬OC`1@ٍ<33/x_|T Mm?Dx|vݟd'3x )V&nHi@.O?ŀ.x 9~*A܌sSD2( x7]Q, y_|" \MQ3᧦tbp.,L4x@[;:_Mm~Kхot(,,L>|&EriYvv`|%@Wɧ; //lnmar*`x`ٗ,: Oy|Ġ~/^^XXY€e0-u:[)/XPGOAݽ} >Ӑ9.^u@ iKk\ ^%<4v675wuw):{z`<{Qk+K+h!9e1Èg}Ans$@o*g9~-ytZ+ I^#姑ߓ2MZGѨPB@[;}԰Z x֯Pk ! O `yIeaZףPj1uJh^סNc2vL2 iyL;ҀL:I#ϡ @%J/ytaS*ޢ<_ŀlv< R667%[I?Lt(j5ZM?yu @_[Z@\ vZ-,cDœ[3pr.u"po`L#4@ΏcMk3y\́O<llEZ&knӀAvHʏ,ozqv'Ӏt,XC}4`X7h Fa x NŃ}Xt: & @o aDCU.\]рrX9g&[gCq~NM|oo=ݽ]|A@y!兀x,%+=gO@:c_,Jx&KYw`}r.; ǂ?rLccC,d<pw+dU8tZ*p}xsMp0.n[ !(1xt?lomna<gX>a5u1㝔ǀc!`O%ww _:?==){agsce%,i&`U鴚 [wR<¯evCjpJ.-̿%<@xPww_p|a8?'-X(Olflw2RI9F}uQ9=9Pfggȗ!@ ݅%ú/7eחסT<>$||v?S>=Xw ^}rJ >iM 90 Uu^'ח/V8FKܤ& ({_X\/|.pW02\___W*p us+,/ yHćkY?=!%p|<Mx&ww:B@4 yU8$d<4wDf+U!y|yx .{нP{* ',v_\Vϰd,] }Kγxw:_@N| :jxv?ˇtX:Zfr %sO|<DOpA[-ph!7^:PP|$]~ᓛZExӏw?7Hd)凛򼴝yj48'i-,Ϝ~/? zy4f <X# zkr,?[f\D|_(oۢ+Їǜ^_<.f3Ǜvo uyaxx @[@xbGbǛ ̯Mڽީ7ot7l,m PkýlĤKf o1 yI؆ϿyʪՀ3ٚ'gtNhd?9EGD߾}|O? #4}. zj87Lc>]XVw>;7)/ N'[LN_~ V+?N;N= 3K ,^2o5j %2/峋 x1@WP\K𡼇SWVv 0\/\yyǟ^X^xc^wxnq=-เk9/ I+㹀P ࣾ[Dz["OϫyPJ]a&׿իx>ީYX#᱔˷x'[$U_)L*8}|ri{*.k^>\ XA=tu; B^̓Z|wv)|WҀLp! $ `y?[? B^VgOـL'7#si@|𸾐m?W(Vk/̯?yw;b0YI+r2< 5 |] W@pRpK !.@*FF @>m mĀ˳9+q5pq< C/ `;ܓP\8(?& y@Nfaiie} 񁱮V?}_]#aIMPt}/7Bs;;Gx+񒀺oPKK?rP@006.npyiwWz| ~{N;dxvƝV=-٢H( @$Hľ+Hw nlI>?E[U@ȹTn*;oZ?.-kxTcu?|>~\SXٷ5eYTP ~?#w?#:OG0HfL&C~mKK}㪊xwtgw_~oO}B3m6{4100cxxtN!9kժVMh]GgCۦnmQ(-Mu 5ՕeOJ>,yRZ4VE4;;DLyjfKn9Nr XL^Sc0Xl n2z~'FO` P0 cx$X,ƣh8F~82 EBp'`  ?H, Dx6_|0d3d ~_bF./ < C>M8Nc_ ɉCIeO69_c@ QC,ȏ `1~p|&3^ @X$|;` ]d,@^ < DP@Ǐ#xD"W<P>©"Qsi`ٟ |8K^@?5CCقQyȳ 6Y N_@8L8`oh/H"^p C@xƁ  gƊ0{\6r2a:v!v7'pܠg8SI(J2%ə&'%2ÙnltDSPz? S7:;;:uNmsF-N2{zM&u?l[fx<^p=^]8胝sH4 +m'f|UWWUV>(/RQQUQѣG%%JK<~IeUyeue峚ƆE: tut cժjkZmj>zVӧOCMe˞<)+-?IyY;:N P*YOթST ]}-*|uEeee}C]]-(3qPҤimr"* `|t:UT*;T(-o?𕊆ƆzتQKIZ<>;=<8R < * V'5*,U7+MM u uPUϏcg!RIЁ*~U u4c@CcS=\MԐ-QS蚌3/.QE^CGƳf嗌ohhTZfEMd;Ԑ'DK`sk6..Ā7`F+6>FxPhmmsnRVy;K V f4k`v6h4ɹッ\.veqlx`V+[G>z7? f'`xx  0pzu!.\ih>Bd[Z:ȟ!ċ"v KPaTPںL67Nͬ M/ŵ%`hB0TpϨ8@<:]_;8 q@eWZz`g4^o&^#CoWRnwdF X Fίq1nNM7!ө /g\y.`c|1@ p]]]Zo `4 _P[[a<Ay ӈW>+lld2ubj4B!绣#bnNn*)NN\ P |0f37Rbh,[ z}zR@6;3?{{77wTWՑz 1 0t H Ǐ&C@R?^ͦf/:*OͰnbA(0& ~PqB MLL < Rw$L H,][ |B)~ ::;#éd(?zp?EҾΝ5  _WFtgE~lt L}p1n"ƆSa!k޻Z^EowRM8777N=[ȏd!!&GgI\[[kSj-ߗdOãlP(h\FO؋y0K,byަ Nmjrji#/ ͂S_]!䫫)O*%Ҫ>'!`vdŋ#k$ [٩&O989&b,\G)Bgr^hUkmj8R?B}9bv}c0.8 '_r< Ru{J#oۨfggs 1yaР7$ S<ߖ<[A|#h;}ʿrqq}?'~ۇ{'pSӦXR\uc}EjnmkN9g2(߿0x[Io{. #D"B}텿'O.i.l10d2Tje}Y> >;0]ݦ>R@o/ |[7ONO/]U`޾$_ <$6z^a0^^E>w,`\ċCD-!yV & w߽{U,Lx?GN@rgtV|:'\ֺ빵ߙ x*38>A:(e%zSղ/b;)`Y ON'RSٹ˱h4[&V7حX )[;`y)\p:{9^$Fn{[ @~m ݝuXK /&2CP$´drUPkr\収ObƂŅSCh"|ǀmiPʢ< ]\l NS <^t8m>C_g7y 8ۻCψY~@)83q\v`fyrg<"8;;=!KXS emz('dݻG9f_yu??pս]8$gg' /P;}s\ x @h6{%ƫˋsxDӂl$ae<@sM=Oۻ+j7o޾̟8m[[_Y K|8t'򊧻h(o߾z}KgG;[Yp~/?p||÷}LO-E}ww.ˋbn8W94dV`2:\6҇mx'WW7W/vPz|GlV <\%c1=ODpS~.Onnn.3x~ 4>`87)$`>Ày"VcOE"h<ps.O"y:ocC K. `|2G32 }o~=|q=wDc@"H|xxߗ 8 /y o };@o< K d;*a< O~wFw8Wy;?%<@3E?$|@T<PvV+\)A@'4R>Ly8#J qaN_|~A(c@//y8^qe$7*N݌.woȿ,?|A ^ v8y >Q4^i, BD[Svo2ߙ<yo`Oy+WWהo;]➇X N)v?𸋯Ώ摷w] |?W~?* CO'qGo+l{/w:܄޼~uq0|ؔ[J-\JBB'Tnsc=\>mGMñ. <\ˆp<V}q F__&z3o[{B=E$ލo˄'5]OOᇷ?|sf+O0{2 Kw; r#g4x}ǀk$w|w;=ߤMbN gݔ+.t PC{NV!&f'w_;y^n_n0tyyr>7LJnI ONϮ_ff6nn|a.N67ϋ{1upvsk<)³>8`@_lPxDB6Nͭm 'i ^|/YR'M>byLB@/ w`^ؕxPoxv|Z?[<[\%Ǔ?򚦦<_|/*p? /Oeoy koj\;>T|#~ p'B6sW54fJ=z W]1G`b|U*yVy% _Kdϑ+@ Dxm p7)iEEEyUMc# q ~,ְ ͓mMVgg'GgU׈>)@deALy!G[K]dp>1#`_ƀrnx>'W4w'c{]p_YQb6*DDc駅<dICvP`ot_" hf0(G"$;gWr{{,. ᮹T?zT x@y7SYWdM4>@pEw~.Q7L`wUNxZrPKK?$xPP@005.npy}iW[W~_oVi'*Nu$tRv9UϘ3 Ѐ$@ @.SzK$1+A>x _O =yZPTR\Qx$_۷ᄏo>]'?>>3 B0 Gǰ~ }^yܡ/7"P Wv0 "X Ec޾X/JRT*Lcx/ :xPD2dr"oKG,~(O0EJ/:8$SCx (##N_/ y^㏈ (>ǩ > sx"@?.DF=jJ 9||耳8L^o @8J \S|(.F@g\A 3p$# ? VG|l96XYv'.Vja Y./,jm7%/X"/OfLdyvhp O`|EQHwmm-mju[kM Gs3jRޮv:aFd1fk=$N96qA|nhTG a/tP&E+kJJJˊJ ={RT’ҒzA8 -֮Nwަ黺:UҚj^NIQ @WXRi'O+*,<BRBxEJ0/.nu$B|c%H$:)FaW͟oa}V?|^yYyIi1ؔ jJ.UBUN xMT)|sė׉jkk ྲr*+-../a JY/Q93-:fI-<<ǗE:UQC***+,o9< /x) :Ɇ R_3@~XP_ jjEu(PQ Ac{iONvatn Hh <)BT[^.mA# `7QMjR]9#ğdٽ.TY SB'@cc5xHV.65JqqH=T]YA9^rC `&VcɚA@BH#EWׯ_/OZL.&TLdh <כ7o~53g/側Ga??b?909;M&@ tXڦ-oo a'U= wJ'iI ^ "~&F_x120L 0i_SiK/x* (/?Nj2?rXdo; (^L13iN &9RGB.7< |{R[ ^{frrvri}ff9HM<~e]ۊs 3"PU ؤRJWfrҥT:rjrrKq-~įV&C'0=A@]œՍ5u &Qh Xnmmu\J;N!~;_`xOQ ,:JvjqlmzqUA5䏵4IсD@o*=Bٹ#^`$x㩀#/.D ht%jRB٬i4TEݦb/e dP`ldxp0BԂť%^ L'b^ZtGaV5xĉ:D,c 3%"012<<0 Q@& ͘]Z?DF^KN@@ YF)&W!&0LM\ LD`uik =9#p`G"SUF==ԴiQk-Psӛ-V` d.|1D0bi7[&oߞlm1u!z7kh.xz'GGVg^BRJ ybQONTOSG?,{ ݁u}k(soP1omOt#?3=3[wx<īӓcRT:MDjbx*OPs+xlfL":5:׷_yu=:<Ć؅:X_\Zz ?#pYçRqz -;"ͫ vX[x8< mcl #Yߩj /IoI7_ IA`Lk(?^r b2 u]J!?ǃON/ Dž.ȑ>g:). o7hT>xF pqqqvA?;< >XZö[CMz]P$%x`'LJw9V+u> 7aOHʅ ⥱y? `Nz?;^N`' @o/Wx<x8b2Cvd&l.r5/LOTM&)p/(pǔ<T<8|}ĉw8P~cdϲ,?d!c1u_s~X'naodg3 s'(651vq9O3A'O -0sR߮tvMÊ56@#_p~r?O>kyR:.xaDtǟf2y[+LZtIQ )3oۍF`xtuM???;;_cxSOeiGth n v&^v\ V`;??89-=.xؾwF %b%8,$pNs+0 p݃x;ur< xli;CtW8f<_qxxl4lhϲy8zXB[I@p0dZS 4+}OND`?TP g7n|xƍOkaޝ|`gƦ2ŵcM R1"ʏ>YNd)AK 8f9^\E ލsG.[>C*lQ+( >~h6C;{<%V%GB.lSyhdO( ~xrWv ^JRzCBj릛3g*|7H;W @@ @RrBݼ _iG;; C ]%-Ia :  tKE|®<<x9<F~2im^8Ύ7:'ş(??N{U @<ᗗ KgG[aCUrx"guwޫ>(N{t|H;&O/c<~k2jm-((R>@ 2& ny>t=|%۔,;/GǸ_H|Dr Rƍ>rhx?bx4puMGG{=Uee PZQ]_Oy7xWE|_1ӆYX?r=7'p'4&x:B22cNh?9==`GuwPJJ={VNyÇo玹{]xB(@KD`iPKQ~l?9EEPKK?!P@004.npyugW׶zE1v8vv;vL`@$*HB $$D`)^8_q\k$=1@Bϳ\ox]/y'꿿/.*RY O<'`=`g8F#ڌʢdxǏsrr~L#Eƃ?~G_y _|UX_[,`gWWWbx_o#xC<( .>|8ǃo޼ׯyYnJSXOO೑ՕEsg>}伂§EEgL "o|;PEY9Y n]]]]A|^P(2T*e2RohjoPeZImmH\[SS]S!,//+)+,)(rE}TT#JA*ݾ`(bi5[ͭ&lX[-vf;V>W,fxl6FxAbh[b[6Aմu-`?W yP(۽^z|(;::#`G0|G::vo{MHïuB@];EpgWDWW$x<DD1()th+ E{{!IEʇB*0>(O  |J+:Ѯ(n{ûX ^tVg% DR)x@|th>6CXqx2|?|ßPX$ ģ@⡔QR ,!~޾^xCË0#@V E ?qO Q>2@דx_{R 64@|Rl b0}y~?"ʟ<&)}g?xwpl z@gA ? 3P7Aq@_ZlppYZmVIs; :w Qg$h!3M &%2aax^`_E!A kjSSCS}}ScIШT(`W(5-Vb0`fj-VX`qt\m.fw:{KHM6"@(ACRQ< 4Қī s R&cbHP ? LFNASx_'m%4b[ԫj":Q (r" -&* e/ 4|u]+ X4WTA/hѠ@S )>'KYVj/нޜ;/4%(~\sջObeX4f(`vjA 0*~t 9AB[]X6g}W\!s /.-S 4442: VjߺE7n]^mqO?L%%A~IW`A\MNhjN^H%I_(V oܸ \_URym<< +*HU0'dGu@\ ?UёYM"MFӧ$.DGĕ_ PfIo@@O0s=n[~ (ž5;6^\%RjA//|[[=!-GpO4/۶  |~ŏ? ZW?400lwlj @5YQ( 酕 ^@,mPXY.|E/)x" NTB2@`w3[ L eUSX\Y$}X`uJ:^$Y'+<>"О=y66/Q xxUsrx]CL.jIM|{x Y?L.O>?blljd~e^zzQb{Tįp 'G%̧D)-z)^S<.h?9|bllSS+x _\xk♀0"8OMP PYnNYMEyIUiV,1illDh0 "~fj47 "c^SXe8eEStcTJs V0$xRe3?giv95?Ox]6kժЯ Bk9*<ċ:L Lss'KD`llF`o/8# Xf z"U ZL Lg(XZH|W1ca,f==j QUoOc*&Dҟ!_\f%*08 | rk }T`y;1LL4:*Ras!Z4eM kTb1Duvv33L`y{pv hVLhiȗK'ݽnoorxz"l >E swv*ЬaF `#q|I+{{$L_(O x^  x(`$H@@mA--LJO~2IoQMs0w|:jCè%HzdN }۷("09|; =h:|WG9mu@vZ-&}"Z^k Ŀ}=ctā4@2x<v>N|)6b5z&`Г#ѧ%wM %Ɵy*:cowov{zΎH{7 : .me^,{6) U@ X`&:D8wF'Ɵww~/Tjnp]^,z*뀟!8;51>20LVXDah3VWg@`|i LM'`~1=z|wx뗇kg_^L@a!ow6@F1WzBﯘ",-/S/,/ 뗯߾!0c ǻ::xfi5 y +8w~ X^~YCC@?TPёᡁh8.b2ڥge%:J9mLS<2<o*ߤ|zP7).X#COַh4*t~-qׯ߼:>Æ؂:XzSr*C.[g^/UM*ΠT*\*߹o޼RKl奄;MbK <$x"5c "@qUe\ [9e,gUwIŃ_ONɇA+|o(gfwwD0_F| bp0dQO%q6SN@``N"H<>Y6a8YVqIoP_~A7oR^|yrtxW 2sx&x5>T9OUU^_ vC,%8:xx /~Zւ}H˿o'$BXp(I`-jxbv\~ $U Lsnt<p@CN̋, `4F4l}̈<x&؄ZaxAoLRoKJvpS~"R?"vo;I#ߕHOZO}hQD/{Y;g x,]Fw²K0wR]xͼu[[KoD%ۭ&xW`/ 0sR/b\"qϊ54:!qPJf30 ?\\Ǡ;VCߐӣx(~HjwCRxXw4OELJ+}v;ŷ:ៜݿx@GBYS#LrI˧ r9m&M7Y҉xe,tzzrreG:4pl i;nЂ@Ƈ@;B<֘7.>`QmՃ@͆d(^&;==}y j5)H? W]nON|[-sZde㑈'M|r=0tZ fç gi'xe UHNZ_^_ٛp_Nx@Ϳ&@#KD[IKxE:4l&m V3:K0@_ #\66+UZa/;#xWQ;UZ $v!(Pp~_Oq H\#&k7a%׫Ԛ8$ˣ4Y7ka]2>R"u*q ՘5pxuQ.1)\wM A_ݖa2<_Gǃ3(! pxI'0O_t ܹ XeW=-W.Ԉ{)`xL]mvs xЋ՝C\^qWA;µ9QgyŊuvw 342X=8>>x"U( ᙀUgB3 {p[Zf{G#XA^/ RjosxhrC@ =q{ƻ<>.xSkpxb61[; D OYn1A_\]y xW,@R ߦUbcs kI< 4  PJ5U'@wqSI.r{D{R M xYKkrK*s_(aO'@(6V:XP/TI^" |Čztw@xuFloZ M4H1^ *\MT~?Tpy)q E6{Cl6⧂|rKD  /_RX?W4k&x<0-ܦңr'ǸI+CƊBWȯJ9Xg6O~X@;ZRd}̖;fol,M C و/"T< |x,6GO9wwIoK6"F|pS# m\GC6cV^'ٹC*4 )fwx-y?❜(o>49x&@1Lsc5n*.Ҹ@ N+?)w Cƒ9,vs+۔Tp ՅLtTGn"|B@d$F4~fwO6;F !! ۜ89$u|@ J;P+glrrjve} ^ u2@6w@~^8xsΝ?ws7yIvz-[JU&Yxm PKK?PP@009.npySbY+f"ibz臙ʜ=M@EQAM}ApqC@qAQL5^9..3Ӆϗ s4oWC_y}_W_Wo^?7_櫑GBxaqno`(B~w0D x<>ovFT:c `|~7D&Ch$%d*L&h,ȉ@%X$|*CMCp2<?cqH4X4KN\J/gX< + 0%<xJ,8p8e:Ix5YΤSd*G\@hG1<2z 4E2/ŗd$<(>S is>@\@ HAx&ـL@_xe"Ҁ><xx3P(dD$}yxgh x * "$xaCzD'/P(PP<:ހBI Ѽ /HB_ժ<~!=HVJ<|~ 9%8`eE> ~d? =i?yV<b'mGSAtXM|@_䶷,L>07j@8ؾ\^/ OpJ/?0 x;P Nr;!_]+gJBxK@8LFfC]nj4Zb,fl\0LFռrv(v_–G)fLl53%AZcK( ogSc걉 zb|B39W)J E swN1?`ZX09$m6vqR.p(ژgBwo_yׯ_<{W+ft\melI 3evvrB;;3Q)^<ҍ B ^|ⵄooo+y łE3P+`L»z!@ 0dx. ^O` cc z)à 2<P*I$<0LjG>P8^P,"(# zLgxS@ҀuR ^}*_ xqz#f}3yY F^3bxR>30xasz}V# Vհh4 u:x~Mx+8@L(< 7<$@ FLIs]PCC“OvŅ dy#u:FAa{<0 |?``fgy.h|ހ:v{ ݕjğhO:K/%r;AbgY7^ϋ槦` kqbc2\[  'ʗxA(@+N_bLnWK:$|tՒHx*@Q4#<#ԍL0iG2Z|C,yq / @r\ pN,Ę FU6+<|CJ;az`x= >Rǵt驩ɉ Jf׎Yzͣ׎7.O( =^'0 ~R`s|Y~?@t4{p1x& D|0/*(`kK&`y^~ݳ?1?E3J@noOkLOLhLI?2<8?^[QZ=>dqvqk{e>"@Bfw޽|-\*Ѓ ŜySr 55NOFQ\xxe91JjL~X^& d34 "Q֨S<,bS8@giT.za hI+q,V.@;K4p<Ł#ӇJ;(`%N'bAfq\f &ZˤP 0fI g `B.`= `\f &)h1XHfV3%gfkˋ 6np.-KP.P!?ߡ~ƔGǘDW\ *z2 vV26s0#!9 8>f%rGN˄Ef^0fԤO0i7L@qL w6 GvsKVd:䫓m"F {e:@VC`$X^f}0z=%x @| ;8<P@P"|(R,ldQ낃`1L@l @?+# 63~!ewqΠcx+G8PP>bNݹkqiC8msX&sޯ O7€C>rX^0`Frd2 zGfܜ^o@x\@Ͻ\7޵H@a}m%#DZh a@B  ~zb^0Ww6 Bae%|öh2[,S+`"ã 8axiH zz|tؽݝVqc%'iiɴە2<(fٔoj{ksc%C^̆驱1R!?,/ @|٨Q%+x^n-FvJ+8Tx*;AARX!0\NdOk2<prjYs=?oapP܀=Gt.32< ht ۛ^ s1;ZlGg8 <t:%qyanh8pYw7v=gp j0fnpc͇_l\e6A@Izn< .a'2<h|ex]^`w7V?q$@exp}}v: OFx:ׄ'mQ>pbf#s'ÓIXpZGvJ|ad<߁_߶N.8jy, xR'.EX)oq*ӏ%퇛n=G!м'G]~Mx{g_w.hѣ.㇫ΎdmLDy <ݧ-sUK^4Q@((>r:\ GݫK[M / 8_R%DWL/ zy m?`?; 0N<0o2ܐX@`#  Ie.E<ny ? Y=w4 HxO^iXo_`l'w cr< Ë\.aޠx Ó9^@g|l.N΄< qG`ɵXG%<м)q@n;q@t?c9s HN @?G+?DW.r6'rTRA|/x#ݐ / 0NkL敊ᩭ$὏*s{ rXRy^#}v 0s:vH<Whh0B j H9 F;UMk(p<$@:gxXA7 gw@Bl; "\l@.,|&@k3{,^,:I^x:HljzK8ý7Y0dEG@ N$6|pt| /#`}<\1 ߓ'OS*ex@x2_޵ }3hK_gO<:QG ogɷQs' $|U?IO>~81܇Xގn^ G'`4YN7;V>jkg:XFej$S2.O@vy=n@( KP _(^?x^ϓ)|]d E" pRx)!#ģDKUP|:P|03>I\@*x63G"_A>t4 " y*@^;$ x 3#ϧ;D'xx<s5~@ .1wA@T>3O:Tᩀ5 (gb |@oNG}&9:<|G"{0;:kk<^ ?/{q}sOA|^XQ0?4q1n?x:06*/nGp` =ew/x:)a@yr81u=N]\!  +ٝB]d<.l[\raLdX̰YnXTA7X?K\Q480uw?zƋڵZx ݾ]]Jj< X 3& /of]ú=o`z{^vwuuuwwwuuU%vjh|+6͜bR15xg/_uqBfphhpp~`/twq!uKv /y.@!`8T+|ã0D}uwߗr| !0b|ã` <x*@CK~ ǃ <@PBA{5ǣ PwIK6 o~^jO10S;כ#J S }^>2/,٭RCT01-g`BCxsv^n`L E i<sD|`$@t(?}*@xQR6u[8@TV0B> <ļ,^ dz,]H^S_|.F:=2C!A{jr^/g(~Bv{U^;x.  *M,gvNWlC@H|?bM&E6Q#rw.^VEaaF I`Ch$W,TaKO-0`6 tg"^8iU24TQHx^1@Ea y |N*0j:u4ܖ{033SSSj5ŀXY | +:30 mSs^HrZIF^ gϞ&f㙀f ?>`iOp焛1 y: D}«.t~hM_}?88?04fϧWSx܁p*W  ܷ% ƌ=G6l}e7oП3Q|nVp㸞I.r;b\?<dvKe hHwl@8hoH1Ͱ}[ɮgR K3wk&K7~I ?0V#J%̺lۍayI831hoi^@_˗8 ?P*[l:\n'wX.aL䤲W|~rd~W]p/j` rOor;;ea*`j$l@q2r,w7[C&Fam Q >|,Y/ 63++?_9 gJ4_S #0ZB6 i,|j?CIS.t |,X&F4P@,耳S: YpQ'Z‡BvЙyH@I?o xjgT6}/ p-B/s!`[MfnNM>?;K|uGfw$QU|> H K'O/XAq^G"e|WyLJ!$e_Z E˫+ ul^i|8 9~a^o4Cq/E[h sNY&=]}Ȉ2eۤ:dyiX %p­yިyGGJ9$8>׭fu w^I'Gmw>ݹ`?< 8>}|' 8J'G2p}}"—lz5B>n2z<+`VO~xl`ͳB5S ^T@~sc-#׹h6L?x WS1/yDv|~m-^Ӿhl3ӰH ?lSW/R^@g'p o2x"],YL\y3x. |ެxA׫kKzJK>ۭqX %< Mpj!h~YUq}tvzT&x|Fpج6~N;NKx:R<pvFf@Q`o>v9,FV;;'1v^ Om [XQ$ȻaQh1gf b.Ivzx|û7ǡ^8?=9.Z>I+l~&$7W7%f(}:9>p+}w\g0Hxpss}w+fՊ3"^6(X<9۷^ Oݴ[K8OHxq\[gOba{o>mt~\cоj`[|^P_u%˜Ï@^ v]4oY g,?D(/=Ng_V`xcw0nd>]~8N7^lB zPt7`Q]qO,f>~xڵ[GB^vٽ5TxΊxd'&p?~|ᮽ W~/ o_*"27ǀ->D/|! h>b_K\2<8A 7wl@sKY>@?q8۹LB_?@Y6@ww?n䊕u n.E< dN.W(w\lU2< 08ֶŃj$@g8b xϋ8t|rd^yZt\x*@';jk7~ xr!1@-y Y@ohY_Jx^%Ux8eUZ* ~SW9S5E3gU0{<oJx;%ПW Mo$Ik.fmL|A/ueW(T!r}z+ H qsqqυ_qzn0<%? |}:M<41 U%Hr01zi~`4;~_ǀ`]'7^pK 6&+lXFRzlp?}bnn8 ;HxC! Kx }E//*UC__HAG@0 [_wuqN~E Ǔ?W-A/񧉍ɚe_t|鋓Jyg|pOyyը_x'?Ky*tsfVa@ yߨ簾N6w?1x]Ч{oT+`|qGTNG;Bag\p| ~7-^%Xy|!)ɫ+^*g[APKK?y&P@003.npyPKK?QZBsP@=&010.npyPKK?,߻+P@9002.npyPKK?9r3P@e001.npyPKK?t/C9P@g000.npyPKK?/s IP@007.npyPKK?rP@=006.npyPKK?$xPP@@005.npyPKK?!P@'004.npyPKK?PP@H009.npyPKK?~bP@1^008.npyPK Gouscikit-image-0.9.3/skimage/data/diamond-erode-matlab-output.npz000066400000000000000000002650701223313777300245000ustar00rootroot00000000000000PKK?ƣW&P@003.npy[[gη$ P/ &)]P$$*4I 8%qCl'No?>pnfYz𾻯fSZߠf#I'Fҥ o3v3#MN"QSYT"PBֱx`w:϶? *s@VqYlW5# mew]]g \-.(h:;$^ zzͽ=&CIa2vuͽo>o7wwu흭P-y@eNܡkDN*gigM@(fCӓ`pzLLLMNLp$ >9}>olldugzP`2 N{cuJULgb1,&l끶0[}6kr ya񌌌 ~o_S`.MP;A-<;8w9KzO[k3t憆qꚪ+eeUUeUՕU*U|PU\RWs>_{V)MS?QoRV؆U>b$≄Y`w8܌,2u0j h˥-TJˊJJKa/wˊU`W]V֔J܊bԔ'3+ sS$1׿/+Sa2 AW8Uw WVw!_TbUf~L(MLL<%'4J0 2UT,%"G V8K$"H 1 S*(/eeT,+ ^)Jx| Dp"\iS@rs<ޅ HD@@]=#@TL ENv,7 ./ |6NsycU***_9 ^Hd'x.d +<@8hz ^Z[յ:M j薵UUAبU^SRSQY Us8溺t@2aρ93/M4;:`Q|CVsK+[mmZbIcz-ZJZZ éNP!KPH\޹s)xH*]] h1: W D:4@0,sx9 Xɧ@E"y<Б6$'mߊy(hvk4D򃳳RX<h~`%&Jo4:A[5 MfxPr"@ϖd?:JnZ(2 LX|ww{y,6_̗e.AOxDBY20NG'D/ d S`/ ~`M.C-Hh*X@`l@BB_(0::LR~@dF C )>GN \bK2U ˟30ҲHgGA2nvW~R8O0ɿVa%*"ÓȚDqq/^:O(p@O`-[,0 hp? X `p(E Q 8T" D<n}; zz@? 8 @ OZ/]T5":O }>ď?6x'jæC xH'V?&3ߏݏS؝a3pwJRS.sH$a Of` ٝ1/$"eq+KqIЎG"<K}8Gn+9^kN.CUYa&ks,A\)PXx"9lH0zp0 Egv+!]e 2@1lP< bh ȶ |iRE r %V+ ']>^YY(爩@B)xO<銘L1`{K>;o ?bXAh|7QTU>zs.>Or!P<PvYa&xaNb 0 1p56hATYObր&?!/G L0@<2 x* M:H5;p{4^"vm%>Ctf 2HЌ-LĤS<,!(@a A{pp̌hhȓJibSRpb@̴nF$ԛ'IӳqĨ]^z ~pk=ڎQ{Ƶ[++ 0hh*%$z~* ˒iY(xL&'}x$ExȻ D Dܻqkoyg!VKʢyL*#ȁ,OhDk[׶b33߻wos`ˆo *PRUQ^*mlkEt|)&$OH?ȇ>v͛DCONZʲYȺ)#TL$=>R nK  y2~,~ .1w326@z2:261#@؁Ǐ?*'!= ,e B$LH ގ KQ;;)/l㼰d"I"3.ϸ~ gwXi'D瀿wyNm>9Kb͈GDpj"jP CYPX& <>t7-'OQŋ>9$g~> 'P֩S^&&'QQ@_A׬uv\#~C#[,O#@mEY%$ Tpr"v1ˋKљ,WW:+ѽ!H1F|S4L(=[,'D˗G/>,q9PTP>5pbqe}vgmmeqvv.Fcu{uŀ׺vH)cc~?C!\ШB <9:&OA+bğ# >*:!- P #0bn'@/^֥ӳću8(?-E'44<.Z\#.(i ]tx:Mx'G/_1 |Çׁ? frk-Pt[W,4.Wlivrj2_X`$Gɩ`0C7⻻^~c"Ç Y3ZFW׭Ed>0; g(3[<^pGNOONR3aʧvwuqՋW}xݹD*"&W O(, !x4BI2 D"I]޽};xw޾yQ@ __/)*#u}}}F/-DD{P`moo`c"WD|gY' {u*. !̚L<mj Be*PO>a> 0cSLD`'xBJIu޼wugkcsmuiyii~vGMAo4m4uvui5TW/߿֮~)/x  *)t=M e!|wn^5by) k ⣈Sш͵Td޽ ă/}}>T`l@1<\bEO?8}՝͵B/<xM"xeVVVӋ>In~}ǯ<pMЪt kE"zE E ~tŅy/3G)US[A7o OŋS~c\.EFol;X'1xK2˧=~|;7w6cKK˱X? dh}bO?ł{x]-RZx{O$1wZ̹(Ϟ~ѣC_ہkee9@75EQ'Ϟ?bA>V[͞LrR[X5E|WG]=}{߽scwo{ccuu}30>~g (~|<_.@Z'9W(^(LNyj9&Lxgˣ=쓏?s`owskska~jaj}n֤( ȉ:>G"9T*ObOc~_ų=xtWI_!0*r9B(d_~?r9|Br>V@'2[V@<o^|Got7VVVVV! +_3cx+&||tɫAGЙ$HtR~$%2x᥆}c:=yݻ7n- H\!`C5OTg"%=AK[dW(^p_Jwo^<]olô[`u))ٹ9) /L hdc7V =sļ8@$MF|zR~/ܾwoy=@` aH(ƳZ"pWߚYMS{6 RҤ‚Kht}ܾ\_[ͅY"4 MC$NS<9}g%2 )ɂxxJ~d_[YZ ZO> Db#/ᅛ ޤTi˯_\hĨb8r4iOD@"%j/f?}M*߫ 9*8"śo-Af":0C<^!OHaq8x)Og 5-͑$ < wo!Ȣ/R9r|e"KneoQP|QWQ`=09#T'O |$}$5'\V[<|+4?;7V D"J:9<цӜi `=ěEvO?Gh>27*+Wa|5Wb+k0瀍Ylx֖'㷷vvFcUҧ x ]r/,.N >8|e< 0bRly~|jvzR=<[Ѩ x,~D@ nNB7~mu14fk,$'KEEM)ͅ"KНOVa[3iI]&{SGm]âK$`ýԮgRjzeṹZ|w* 0Hډ;9N Gq"x(2u.2fF<X)~hh@h? Ay|mreX\.ɒ ۼ@ T<qE @Jn>aSSX QA@I|$$ >-ot 3+gXEENt;9v65Uܤ~jjFN*)^5x@trK%Wj}u76̱Њo7>r{J@d* =srAV<$$90Ȉe"1<0?Ÿ(9UYo?~)IEn)@ycvr+ br{"B$I.;a@`k #ࣸzJjls|ڧx(./r X{{@xizJZFa+2Y9XG|,+2t0{{?#+n瀵GJK!NwZ& ܎a f5gE;6c46`27OϙZUZHiLJ6)^@I8M\Mg4tASڻ뭯ojjmiˉ)|'5>ڦJO.t"wʗQ`s3S, L|VuhT**+ ~+9%wuo@`a L׶o}_~{fWp 4ʊ|. @!^#RJQ<6O4-R )sw?7|^w"PSVZZVTx(FHoHx"!6RVcKs5V~?_w_<hlD<0",[Cgvij+HD(`w(~؃u&1ě7o'  R”3xIH&vvw(]_$iD|po~喊m@y9W3x"Fd ^-Iآ9ktqNS_?~_/HJ"TŃM74j>?).ooCwYMR(ɐ}NK/ۯo/ VVUY^x`)^H.$$HRSrmϮM'0okI:7;G_s۟@%EYE45 Ҝ<%ŋ1=Bb޿.RYh)4~6!%3=9?_ jBT*r|:}/_D MJ'xZ/L֋#O_擥T Ȩ + 9 7f(PGW)~<[|_Ͽ"?*h'Vk<9:W^q 0cY WSXOﻘr^%rPKK?(#"P@010.npyO~۷}w@0eC @6 /$8&``@H*9GTJzefyp~G!1g8ѱٿjr馯Gl¢BXF.ç^ᦿaP$|_P'9JNg2I:ʌ &bhwgggր#\N4榦[6`4Ό]x$u,dLxC!@M(1x2t~〇5 Pxꋕ\<~'''?6O%ɡ`"1}L&CI{ޏhHd2> ƣXb E+$,@%% }( C@<:ـ&5@% Fx@&tW.ʧR y9 J_hmN`EV+ph'*Sx!}CXnC%|,Qc hl&%@y@ Ot|__=p= B! 8G؀p8 ||c4xNp0ۭu|C@}^qP*`8|_ Oލ^3<ȼț^/gyA+p2 0 ykc>jluLz^ y<hWFh58ollfl6>/ /~A>^ </D~}[ &ՀQ@xKO4`6XQ?Ӏf:B@vrVͤӣCCS$,31/L?yM`Ь !`~vvff& Hf 鱑TjdѣGQ0<K[nx] Vk~~n1\nzrj:7=&G乒W(l\ަ|~^-@Lv&+k1;; 0lQx^ o-d8<]+f?cx.[o-\|~|4piƒPJ<ꀹ: !ry' .OycԔ#qĿa<1`jJL < YZY[[OMр!xAQݮ xYYO1-qvmVɚ7<d4$@H@Zx7oqC`E+]g& <hnF7צ> m;(`}RJrv<X,$Rl*+ _Z/ErTRy^y%~ ?AS*棷oknW6y^ 9P,Mͤ yXx|# >v4O'Ob4vx%́y|̇wr`|+/l6͛uNJZe3Gy]orwpvM_YYzV^5x^;9MÿK(\2,o6_Ѐe$_hg^cܼY'@@ElT1z^Hy ('}>s455qyr~̋,_&kl@a< (Nyr 5}j}u8`uu @|x ^¼zݒҍU8`u,Ra*r@]^0|'[j@ݕौ/*WaE /8`q8E`[n_ ʱp8KYЅ`GۚK9¿ (T.7+\:,)/u.Ir)y]!!"GSoS:^ HpK[' Px]$oV[z~A%kNgh|`d```px83:wGHR0L(LJgpv+ x%@9ɏIg2C 퍗~(.bv> #& `x-c/77av*>Z9߿_~OHS:0|&鿣n8^~w2O Lx;!ؘ§I<p  Q~{>Biz~w?~.p~wLHiu=o >]ܮ9+ Oޮ_|w 0v{`>ݐ?-Nf^n BX2]]wx48|zGwN_tm}csc{U#>/r~i@tccH(G0[Y^V*O WwuvvNF  ay_ݭ4<*اg| u<﹆?:>P^sy^3=Sa7'kq.ݽ4>FkiၑW1.p y.wßtf8 OD5[M ͷ]''UMyb[]j= pk SYmVpxX9wZn-4`b,</qĞ hIMV%f^aÄt5s"""y. /`CJeR̮ H$&Ly D"(@[ՀG(#Gt< yc/j֏&z/s Bʧ<_,P]gP[Y x%fJ5xbɄWl`4i|?xUmg$bX8fǟ]N#p>]\\;;}xzFߴ 7M w<^yӬ.@~< x~o>1.p@>_X8G)?5^4hyc8B/W1zz PN]|y}8S|@'ɠ{f,n;n; o.7 8咼^`&gv6I@+N^G/yxOo^a~}As ?Ib]n#۱sL4pX4(SxOf{|DLW's +>#pXd03.[g,ڷ)N=m[tT~<Ë4 H: 5 t78+O8JIÓagx%bX`&ۇ{ҫ-֪?_E{)2>65l:X4CwG꫓Z T^dyc/ =[-o `ycl 4Mv~0ߕY^Ћ.vg^4Hqwwwgjzцf/ݷЀvQywr:䉦hiQy?\y}@K9/{wz|:_;m':"΁u1 d.-O}z=훑#`OÚĆ~Џ~0LP@B{W|.޿DgjG'O^&޿C_y< ?˿_<( }=Oܮ_Gƀ?o=\?< ]O_U<|$!vpU^ 0D |9pp뼓;Y^ PKK?{w,P@002.npy[ɶݙwmc9'L9)" A"I$r2ٴ8vrcVZҪGdkOc,/zb˺xa_j>(>Wjonmmmoo.4khu:]iYUeeeiiiEEEUuuh2 uښjX^QUSh4 ᡡ*J&bX;u?A'O *\r_kmq$Y&juťUU'Z_"~IiYiid2D,1o d\$J|ee%G7չ(`xت@P*|ATUWh¼ĘhrD(@ DA$p4eEBBoi)!⢳gehJ&P^+J=/h2bb"BʈƕHT9&{Adw:3ǕSc gj_PF@*JW|0|ffzBtl4beᣩ$D S9u츈?+$p'}g +xп‹H: 2$<*>,2>O_U\/6Wf]¯՟ 5յ?=GE/1h$ ? 46[mh|Ϻ9zWTh7j@hjb|ZRJN^NW[Sr6-T@7 ˜Po66 5:S]hoښZ[[[,uUUho TmuuBP76ZW16I'#cccNkxxtdxxl{aאshhph`oh,M[ss\}^F'u}uug$[[\&>_^^-b|ol7?+>oyii oZ\[[X񭬭c8o.-O@Ip :6j{?ycc0k+~sϟ?a⅋T.]?.^t}};nwg{gwwoo> i w31>66:vƽSS3s3ӳs+-/|+UC+b޹vqޅ.]?\zpp*ʕKm-[dmnZ-fkj47`,ZlMf[k[skGkor:kxc#c#1 ^Мo63?7099?7t] #RLb8m~ܼ̌윜켼&,}d=[/8WTeRW+*+ȯ¢mAvshhhۺ{&':-v{ur|dl4%EBD\C@!oKNVzV&#+3-3==--Q?fi `Ws325i)ZmZRllbr|vvFST<̒"xlqjnV|$Rp2J,dcyEtLKK(Tf;M6srث(>66>>>-2MH)QRVG8\ de1~*L£Sa@aKN}W>I 22R {T, RP(J7¢25?Q|pb+%XtZmQ^9Y YٙP?19iI*x|4 b1 y~j tb -FEAnnVDaU*g+,բմZhHOtxPQVF(#Q#A^$bx/ :j$:ev***M)ԃ2$eXJJW&dW[Ql2VD$aQ"J%LO%H@@"TkjjU&XʐVQ[IxJDJШ\] /&כ #" @x5JBIOKs0d@D2ex1,JG5j+9d2h0֛ l6 0Ւ ZC]Mik K*!DZC-'&~^&ɤl1ObRZ,W*LfZ66 ɳ4Yadj0M,1_X!P=Xh[*M @;1H-exttbuoio$zxX, Ȏ %ŕ5&h757wj8(cTp |XahkhԌb@8<hl6Z҄O%|Frr\r$6#cUB@"dQ=]]{4+YWU6j9V[5ZiS`N D򘸈Pu4ٚ$S> "tp͔4V؆\qON:\e|E%LV$JLEt!E0T*T&/p2ЋM.SO[kmpRs 2`>v@hGSM]DX B0$Ah)_NS{{lvTz.}h4v::Iv :qйh/ZQ‚Omࠁ`o7Բ˪vGdj5Pi3<XhI,02~8eFB !6#*F*a}%GJ}6ptt;g=41չj"JA`n$>a\9ɓ'd|>?.)V_V&C /iQV\T`EF%\IobxL&n /VI#b B*->>ID$ a,7t#LΎ@0Vi Eb@lf mrhfC}:=- &0^.>H&IiEJ>#^LGψ`1_T:ɠxHaDڞ8*J4Tء0L+jJR*l`4yh3ghNHnZfT|C,O-6 b}07bV9/U"_ՊT*$,#M6EJ*܂t SbdkQ76z[!`C&!Xr'O$<,_QZ* ,R!";q A$xS~>8HbwA Ə <Q:dHJOsHED~i@j|7 @V;l v :$P$,8)+P`cp:4x&5?0 _0' "h tq@<44<ӂF1<d5+4Y ff/vRA!UnWR|2Ewrt`۬n71>!'¹d2b1Bm6dKY/cqVAIHSبvw)雠frFF6* 'aQɪ`R! 7kx`!z'(D?I@H7֊7cCgtv!g[Z bɋRQ>32 Q PeRJ% B҅|K14?N w;OOLL`jl# D0Ok4 0!pJٱ+$ F a=kcމqlj\goow׿7fGŁ]?ϰI-14c0O !WB&Kͭ`S_b_O'ź5w `t{accnnbi2d2>N0Nb2D}3 Q);VȤX]= Ӎ}o{mͿ0N@` .,-AݨV*XC$PٻՖYHL Ҽ}QAjBLtT2,<$DPbU2,%+'>" #dnsm[wvy4xu:#e3 yJ[e%s249ErN "\^AJ$5(")zYeoqw67&ܽ WwV!7|MSs3jlϰo6Y+H "B&쩇)! :~0 N xpƍ*n޼y [{KX&4~ckj|Ilezbjm)bcWXuo`#?lm<}{?9zʭ[= >=HglOJQ]hʞ~ `OP[Ȣ?/<伺A'~ ?!Ķݾ{xpg'?íKaLTѝ3g P2"v@ܸwI 2J&:S^wȨȕ5Ȳ 6Ci6эXbGF&;)GOwomѓC<|ɣ'OՃ/HIL : {<ŢTLBxކϷ4799CLC}]MiIi]v{ Rsx܍B '!@K// pn\t&&Ir=0Zi9-V}K3SQ΄[YVXC,NgπkIU*0>6dH{Tn=%'/!pуwo\2EK#c|QƱ IәNנ@M]a'/{{) >|%^?zwoHx.]eOuQB!ΩKn,0=u:V7Ó( PtQX!뗯_={wo>d1]k+E!XiFcqgsշ83=54;^ |u+\5NOt3 zէO_~MGϟ=yj-'o\>_$ h97?aU[=n5Nѱ1x=|vb<}wo߽>zBQڹ09 (n3?’ MgwvrՇlwNY-u?xF'&lΏ){u˻ws.߼y wFw>)) 'T6@I`j4X;;穕ЂƀGlg_6?)~ѹ˗ܹ3v}}n߸D_kIOIOhZ]nCee+Zefj31Ꙝrqwk! TW^ϻ$Źsucggݽsb·vZ\ >e/SӋs3^{1$S]^,]T[ q8GޝK!0pͫx l670|Wb*Vgu#YXY9;7=Nn39U b33/HsܹyuὛXHҵ+{%sxZXknWxW6c+˴DNOO~2a@d3O>O^[ko_:1g{>-j]X@V=w퍵U{fKKKsS|,b3I//||[<|xx_ãwH``vAw[՗U_;}u?B 33f}45ٚ _oSǏ_=~:L=8x= 7~vNl6Wg0̇e혟nR-c7.^X_fg.~l4 &3z4< GHxÇ5L`ehi13鮯׆ fg?uʒovnv 7[D++*IC={?3&pO^y U$_?>2Eٹ0ݾ}Kv6Vss FvH_庂,VWɣW?uΝϟAܭ^z5{qaTb["|@`{;u޹ݭ įfL$w>$sI{y3GY J{_ȞBz_*%O'pxk/ln=`[@ !%%$mu}ܹ[FdЈd`Ґ/|q|pp*:'<{w]taoogksumumvztÊlX, FDD IHH֖[;J Oh.Ċt%?οyG0~֍[W.no`k0r##`cFGg{j,~rrfRO~u$8)!Afi_\HxTTD]o`1^7>~_޾yOxWΟ?[ZF.2Ʈ??K>o}cscuyq'טVȑ6y.Х)WbD$ +E̊K:r"Lg"_Rb}2ETJJrLh0(I@nӇo^Q <tCZ| >|ض {3"xNFbT 4j&UIܻ_޿S> 5Wo޾}*V@w>==7WDxXYG|Goh[#汇NHD $Ri[9|J*j-yy>7ۇ ?]GbY:'i޹k;uyt7 pTyϚD]Q?;B垞T޿|Q}6BȚQsp#yTPsL8<7wyPfhK= |j".#2 fH+5W$@g]^o%p{1Jufgf&r33 *LaO!)ædYLo}t݃#ol̸ =<%nY7?wlbxH -ĞOn/LVՔy4} ةL/*]<|T}=ɥxβ*J0"QqvǨ^vwXmցqTj699KVgVT~qf~~qaf:˽ pų< ̘.xQwKL vTs=LlM[(~ Ir9" ͆³BxO@x*wAd{ÓrT LRbv_F]^^Xz,&KM]#&<&`6,qtVw2ogwI#:urFlQf"ղsǞ&-cU^H"W<_ǰ3u ҙ`ok(Zd5Lӏ7%:TX"=8Hqf˅3C>L`ٷ4|U^oO'h#}l0[ yS6wssfvoIPEz ;NV> O[y(NJ m=$02F+ fݨ{0@@`bޞK!fkl4+Sג=X$K%J%w{x +^tY?iUxOwRF?]eshϏyvK9"-'+ *JbH/aO|SȢRJh0A%؜~` 3sl/WmMM8%iii^=BQ@QO& Q$S\ڣHeuzzF\_9ڞ×/ul C 499-5+<;ۛ-fNR]YHֈ]nț}abI˄Kzw?óNL憚zbhbbZjj*?5T{:?F}<; ̿cw.\}ǯ>?~B ?&113>^6b >6BQLѶwwvv$p~O_n/ۗwI@IIqfF2O4T'fK( YkLA(/SOr'NޏGG/o7sL@/)˧ϐdpxM1:8M%tFIxlQ9z y=K[ʫ~??i?U%ge@VȩHK.)CdM4 2M?RB,\z|?}ǟrm}I ]I@^%KX^+&TD.4ֿ lnmη0ew=>3>_?|DVE OyL<'Q-ip +}%R4,4>L.9 9>Zl1..@ͧO ՚>h#J+9bfƨ% /!pFlA;`9>,m3vɳ_xӧO__!=wWgf8={D/vZeV3gbbFS8 im6}AB ^~ۗ?mGq'tqQ 1q1*Db" 1F~Iyjf2<U$Sy=ӻ |*ϟ>Hم8_gDŽbb"ؾKG1Y:Ư0-'îۏ_2K%*7 VGE5&L_Imo3:XA7=Oo>|FuJ r[YMc7PKK?Tf}e3P@001.npy_[.m]oHoXPADE@{^ǚ^M5=3s;g}8˾|Z/{"r]wgN\U&Q_࿹8ZJc8Bil0MZyӮVCY1BxBZ|Ź啕.Uq ZP(*ryRYS44h0jkT5JrMML\_P(egDGF d2 -av .\r%Zd^, r2DA|$qBQU]}NS( d\Hp8,.L(!eK.%A "]_ZXZYY^ Oz:dW^-H%b"+U*U]Q YyQA^NVvv.ٙ rY,=.LU{ƒ(Z+̤Zif/,.-.M:W BP|TU)00PjEZ&KE䴄Ĥh@xx8;mx|li7Ģ:jI1y /͌89XҒRIիeJ,B^UY <؏!VTIeR. D)I 1Q<~LRrBBB|+7^eE, JfgT66X}sյg KQAM/rWAU+OYiEE,3,ǏKM.V m?_Z\ &mS#BQSWU6hMFEP«;'DfJYGme?"&N?7;;<7=:00 y<^uϋz===]n{j6:Zu-zmQ <nWWelD9QMMM:df&0-/-,dobffzjj o_?-MM@Ipt[mfc^iuf\]<E1676׃:ް{mogg6~%lllmlmnP_׶i5>o}?, @`fj||b|]pyqq xyeAWAonn_ۻ/ão_~hwmg ttw \;8<>>~x|tx?&smg}myqIdgHÅ \m[do޼}!P>HݤS?8~|&]?«7'S>70 }~톻 x}~0r$f=HX^X`6W7760ˋ6VWׂ[[;LJG[ZZAҬ34tZI5h EYjзZ;Z[&iجNn;.6:144>4]}u $ ${dqq¢ܜ*y_ZZ|/ZTFtyYyYIQI\%e2qI&*:}muhhT'&STR&.E-.,$ Gd[T+AY"+*ī9 8+-115=9??K$*xs󸂘8.^*,Kb x, @ /OD\XyYYY'Hw|_P@ %K~gs9ȸH6C3Œ#Kee⊲ry"s_@/?_rnA_Ɔ3<.f3l6N< $ꔨr<ɫd⒲r |B,)++),,Q%2Ujq~բ 1fM\\"F<)[2I _./%4H Ng~h#3NUWCZEUEeĆ\TJ"=dTVUdW LdW,FeH[ *UR!H|X~9d,&g4T@KCaIq&DqX\>Ïx]}m-BAb=Ԛ#' D)@s)k(H Eyn/Ǥe1b|0ZC_fFRaT`<|HZ$-5j(Ds WrŹVւ4@jhh4&(:ia,0>@s0aa|Yu&8 ::vUV<5Ys*qbi122by1|h?AYIE21s % |5LI?!Xj|B``f\ x|,?ωBG,0 VAS7h:U&pkԜ(`)((!_ÖcũP`WcrL&'Dűcbhg%Rl!p:# N^Cij6뚈'kԍz5 iudub ר5xkBwFGFF^ᰩhFѹ~#BB@͊" utln6&&mO5j 8[T*ܠll榆&e g34IIQY٢xNlEE#߅Rlv4ŋdj7v;ڌƶVVkh6` ں&JQiܬ74u(s23ct☤z 0>`8BwZ-d0Lo!x߹FeWRFag\|Qzzz ҾFJINh(D~͊IL٬6 Kd60 $נ:}ٕWV oj5wt w&X(m$Q>OGR $EmLRVBTE~~!!` XnF'`X;AureV wPrN˙򄤸Ha<>%:- 5N[W!G CXb?I@ uQSX SFdP)jI+5vwxnavm?[ՀBXތL8G(lyEQTWOH$&űYTcq $Df#s`6SV>Z~A`}}A]S â¢Ci0p,-#&C]|T ݢ1ԗef$hH$)*pYVňkh#zzS}Ge2Ֆ3R&'9pBTX 8PXXikH,J,*OÄ U8"6e1pib:-f؈4PP֐@#}mխZMrY^J]H V$.OKJ˕6VVJčmJM<'/jRJ H Y.x#9R|)#bAAVIťY pҥ 14-Ij6 tUuSJU$ "%)DcYjAۭXfI255"476~%^݆775[[4QH8YЙ,-z x \jӐ ]:uUqaR"Ο^?1=.;b4Ȫf^cЫFCl "sq%Y84QYfHZL}MmvrӢXyv KgeIDN5o[,0PzH2MF7]0$j 9q%bqKtzSopT6ـ+f[奧&dQII|p:l ~]ހތdh2"mmitv555 $ᅋ7V8+D3`RNF8͗*Y6Ogә$[xx3"ȼr -$r,͎jG)ҷ6zF/ 5 .1Xpdqy0o4^!>DMLJҢx?#>Y~/_wi5h;mݶI AWk{i6&%0 RN0ܰ0 VEEP"ёl΅K](MB `Q4Ҋh{aPQ -FPmkk2lmmlE~0S0yWh4$)/Z~V}}P8< 9 e3/PqDQ+ؼ,;Q6"@![wfmlltn"QQt:I!P!ocXP̤ͣLA"ѧ+¬2b?2xf4Y=d8mH~ yQzl8i iQha_.@AhW I*]w8z."mE581mYYB!4P.?.]q(x!8(Ad$2kN^C6N bZ6"[um7c=lMmB"|Hz ]&]ӵw٠4X6P '( 8&qmV I>C>ݢoi]pLx{1#N%:5<<44N#E',zؑ{1$4|2#`E' h,^PެosٷYu Vr{Nujrb`j[ *1W"Ba4/ҹ<0& ;⳹ &r npw g1YaDt?G)xL06Vj *Z#jB[\LLF}>~pohwkqgllxةiS8h$XŴKG_Plˇᜈ ȼieyiIFJB4? J8)F2:ܸNv륪|><{XǴumn[qqtva~^(D**+LIC~liHD dn۝{ۗonn.-.}[륅q~uwbUj iY ?'C<~$?%Tj cB_b>߼_<8=:ۻ:|x 2_"2O(kjf>4v4 heQ2;:Zj$y11Ay h y.;%)G7n߽577V7SC:hz ;Y!.=Z{pd`*DCX6,N%/D#P;NH.?w#N0wܸuƽ{͝8>>{m|\3r3l> 2ucyAY݂|u9!c줎ZU"QzFr_+Z\T"ʧہt!mmmwo߻sÇsO=ݝ`p¥( 1+W.6vWggguvtScY ueBTժv'Aw=n#է9!;'=99ýNI#ME14O^[ .W럜 L {>t86!hғnD2|wO_AGJYZ[]NNN{ɳGwVWNkLl\BZڪkd_] .Ɔ={.+-j1[ )Xmgon_{}gO>y)=:##5C&L{w&[338359>z0ͥY(fv wc PVœ/_޿:}z{׏]XY ,eG\+Y^o3f4 lΝսiS*v\}ҹ~|yzϻo?^>WN߽|~޽[׏66VVY RLZG&\^rˡS蜈o yIEŨkm{ ٫gnݺq:S+b1A໦m)˔<MNεk[kK ٙN'l3.{go,ϥ]ty}UD@o<47392G*Nc`|C]봺63gLJ&^DYnX>t}_x664Zû_޿;7759\~k` X\Nh4|C}.;<Ftu:5>??1 憱C#H ^OM"0S/|V[[O>}}{z{͛׃H~7m,wZ%E} nIk ):M@p}v? DϋC@mB[ԵU_~| .\?Z]rߺuAbhkomٻzz t]7P(zQPc#ioA6'}#@TU%-~tsggzzjfsΝ[wӆezG%9Uz@p7=6> &%btx ?]>t ziQh׏o?<[YZzp㽣k7=.1dUzZk[{FԄϷX^Y03P-3 M^[/D~|!^=[{[3K_<ݓwn"{]~;E@R Ydu]wt7l3uH#HCcdl -zVS+r*3՛Ƿ0=sq|xѓg>^]Y\YX;TkGb98:,.&'FG |C## mK]BtZEyNNП y&"Kԉ/6>19@.5M ]CZC.**r*#гom.o޺"=髷P1!4 tj ""*j| 05519=iВjؠiPɹ:W%|{wѭ͛7#?{ٽ{N_~7f!59C#CC}^uקiiibeml2$JN+zb6N\va>~/_<zr6+|v*PG~iI3Pochh!g_秦SU>4֌ I)%2Ùdkq|!IǸׯ_}ٓGnlN,t0"$zrljrrrzjQ ޝ9))tSt5W- {qq1Q<&Ҥ/C |߽}s}.fWV!^F >LT @yd%Dޜ=..NU*e:=,a1X,:#e'<=wDTN@d0 ߜxz*pWA'ƦIL{=C9Eȝh|rXXh8`ԕ\ SD%%e(./o?~|#GbFO'xH2zw?hmmxeB'_MMFǤ'g'wd&I'O۵奥yj\jDꚐkDmmO>;}ǏY̢.0CF c.b4|Z0~ -go^WwT̤ ȈHHgo?|x]R.MMx I1)9i<,Zat&'2*137'+/#=!2} {~O޿[XX~j||Kx!d0zG_}Ǐv5p.G %WK ~Arxq&C8/[3!3?7R!*Z$DLaa!aa'޽y&ykl3l6_sjIvVYUoB IEdᳳewX,9>;;33>>'@N,#s''޼ygr(DQXԈh!_e1Bi vDTf\S[Eٟ_\msAo GEE0{g>r]2+CC/޼  7ڢrv|D95:.66VrpuA)_,ޱ鱱N{h 04h9E!"9ux&@h\3~ O!ǦD޿Ӎվ"T:Zc 8 C's` R1nynvny}m08?Li2m IO~A~NK$EUpzÓs6 6 !@zzghldltt Ocann^U)U2a!WKyҭ'߿82 H nddlt$\]!X&uc'WYv~n~qqE&5dn/M-ꊊyd@[2+<hg" Lrx`l:+*ށflt|,E?DG|䓇 ybhUs(sӀA{7 ˟#ȺlB>@%8 =w7Pg ~^t`kK>*!^W*oiWgQgG)AB/?!H<[T\Bc<6Ak\3:Kis:Ό-Γ42sݟЬmq@U 9<G矿~?p/\tfo07@~""i$yu;jmg_OǠJj[L?x d^IknWƚE D!FT˅?[ 𜛎=1119COO{Q;q:\}=d^dY]KKe֏?ޚ!ħpx\ a.@89yqrY4(),pGmmCD.haRyZ~?GA;299EK ίj˭Ȩ.o(r ǹ\53SV6r'jQ!)i􆺺yFxHm~>ɵT69ZȋN*jBK w3?CGt&&!麵ղji5L]N:M+9Rkǟ?-ˎãc㭂+,&M 4Ƅ򖮮Z91D,&&\I#~ߐMDuu'[?kkkRH۽QDI8> !\:Qt֠۰Tx@O$yI&bt-xrvXh5ՒC=LJm%,g ,./.y$ -pȴ~}h).CJ5;F=P^PRY!5u雚5s}M;"Ю)[yE#FfeeLF uS51 2H~KN\D艅&uQv166~ow}pѮoEEG8d4n6I D_,07\BnK%J.e&Y:yx!:XHzLΡсqyi>u4YNFq;Ϟ<{#Y{8a&()DZS#'w)dŒծ[1s،{ʕ41 ԤժϓG{z]['O~}rӐbXP*|S!KH "#Ӕd\>_%F~Ra1ݤ3ҝ$za7?~|{WR*B\QWsx0APKK?t/C9P@000.npy-W[[k.xmӻj sYD%@!(#I" 66W]U{?}ӿt!&y7CU 5?+*ش(^%Ea;J9O."UBx[!K+.B'<) '"ȠQUhofffS#dxm6>r9l.d87+F)D,"&vzq҃{Q9¨ɧ$xh4 Tȡf2jjkꚘfŬklnnr[ZZyVbf`de&h"KHU:wNz_~JjhoJ$Sɱddn{ ҚZjf7775Kp[y6ᱛ9M5Ey $+-=!>Bht )u(mZ]UJD%׵K8qhxll|b22=86IU c2Ml6'00uu윜dJQ#<437vyVӪbN s#V9QSUSmb56ԃ4ě YfFUmmEYqAvNzzrRBrZJzbRrBBIK д܆>wdaemc+[;[K{G@8^;¢ʪfVcSS#r8ںZdH}mMIQAQA^jRrb'ĥddg0E%JONDf6<}P8 g秂.].hoZx\V+y6agGwWX%sfvCScc]}^^NFBjB8ܱ bwvwvvwX__YD[A<?v@MYCVj!ˠd4BͦAt;3! A0111191:>>5 N͂G͹HdjzlRka&VK, ;:PB@H!uEbX'dJB.T~R=AkAo&hi#9=nf^76A#[UV\ZWX\XTX\RR_\XXTTXRRTR\TPPT<V%5pTVWkj" Es㇣6jivπKH'%4B/eTVUVWUU.(/.@ZVaa^V^AQaaA><x閝 ]?.(,//Jݢܼ*SvzRRZFJf(:/GǥdPt"Eks#<5640++aVTVWV,aVT.,-+,-*+)T_WWͨS +TNYQaΥk3@'`X%h,DqZ8hQP__Ј 02Ls!p9-ZMZskR76$}h&ţ1xT4*C"D2ZֶV)@Wͬ B0 FB8EXL.&x|(BK+[;&h(H$.9\RVSCy )Z[UOƣq8TR~FP-R])loA#(V"<8|@bCx6Z)P]IYYUy\S$ӓHD)MtD%%o|AP hkt.ST' d>E8_GǺMwZSFE_KOU'`Pd*/1X|JK,`tJ^IOoOOSڈ:;DBASyf5VUB,lwttjw*II܌:^_uzE~NravN7he54ZM O0qɴ4zZB|<.+d2io4vEbPK$6IbT0-K$Hz5:62#.E *WB]C: A.;.}l|N:BpܤBPerѡO#%pY,y| &0P ^:`pubWQΫ{x.6'QxJl,X](/WUJJPHe ТO"ӺyǷ_wwl>zqrvͷŪ&VkC8^yr*W'R 4 ]3 !J\*CJ mdՐyi̓߮/{RNfg5&aI9rKyq!$50;6M,%e)Ff@j4~C U">υocZ"~p “An{=8 '"v? L$q*Ks[cTt+E\v;:@4׵pKcIyiY4Z 2P@ȤrJw <M Ez.Uf xBZ:iG1*`` Y[gיT=A@\iBҟLHBG,~Hԡ fbC![N"i2%O91C3KiPQQQI^-@e'W($RuSe5!_%QiDF9 4<Keζن(DCGd'c5d)ְO(Z.“8Խ dU8EQkTA{~ÐRSu]]nJW#b1$F=)6"Q( 9>э{)RK$SH$:=-531\?]Q'2`1(,f_U3H=UaȠ PC&}(dgdш8:a ZxFf_9 F՚,zѢJNs[UzNi51hZBR5RÌUH8":eQk"(XJē8<-LNO)(ʈJ(t<1r|W8Qo6ꑕ!Ūt/~ǪpV;Qh^\OzEeDQx,ITG$ %Qr* (MvQgQL HW<6upHg 6uK05NPH?d7wfC͑ ؘ?=4u8v?i*d&IxZ||M$QHX DơDjB`q2&[gi|; Ab*;#;s#ãc-0dut %99E3 Pظ6mUޟ"ŧ'&$@x4: iq4(*V$([f2@Vi}r x.ժG]#k3?j]$sMf =K\yDMu}hL gf''R)<42lO*f E1bLJکp`j8m֡!FbٟZ LX|EfUŗGjb(幉h ײ Hi 蘘hEs!V*btzsF>*yo#-0? 9Z -1Fe#.W{E r 0JC.% +y\d|l4N<~:866fńIEFOAh廞2v[g/+˳RSS􌔌Z6[ IVd\ءFf݇;Ks++ +ݣg[6@1_K0)Hhk:k{\v7z>Jt;L4K$m|TV%0mT~du=|d{Gw#$& }de.\^/*F #4NyMqIyq(Ԣ(%.##_3gxm{`ѓ';wvGl¼Z2 O bs>-b!(@JQ{b,1? #3FA @xNo Frߠ:Bdɳ'?}zuzry̤!<^ٖ@6d\\xbm︵Gfx\PFͩ4xihzE3b0뚘lNkTaMFIo՛ Ϟ>zȫ/^>_|9=3;1H_Dpeea ^7FAɠm}vI| 7,feITϞ8zƇ7N^>=X[YXqtAzj\UۇgfsZ-ɠWennYz_LڣR!D_g0Z1|&h~_tLJϏO^\{᫳g7mlnG4n,1xxxpt|!/!Wdnyyb,02h4 @l6nY,?Kv_puuq m//F aHUsO}/.o,OZ:p YZCv04ЯTQPkdbǫn/n.޽998;;ۛYՠQQ2=>8zd!dۻs؈k)C9<Ղ\K (csNU!+_~zӵʼnP_2u/O?z<=>ݳT$ <PИ!C YoCs`2;l.rT4ѣKpqw?}wW; v*:`{ifu>46R`u-g"{a] T\C1vylېlDiN4kJ#`^ͯ>^}{s}ۓw{Om/ͱr鳪WGOwgW3&ejSw=6Q%ѺG.P)=p1 ؆&qd:hȺRI7Gw~xwoMG4уO!' +]52}WOiC>Nfv{G<~/043; ٬HA nW?B iWk˿Ϸ߽~}tí㋫k{s"[ܭ2 NU֑0_ N=D8y^ᰛMfHBrA]~d^q{_o?ypgqߞ?͝q@&z`@Z#6휡Ko`zy7;6=47;19>8 Z\^QXl-Y?>ݼts㣝)'w6?y<X-zR hN% L>ġ9&417f '.!{ׅ#^!/A.`0yoS+0o^ߞy}||g{+Nm,D&'g&GCN 0ƁE/2)|LJ/m-,M#Bv{ɤwO&E.߿~t{}G SO@yhçϞ|ӣ'+ ~A#ԗozq~th1;;==w]%nB!iεׯ~{ExyWgͻOO/^]\<9y~㏿gcNS ~ŹX8v{ܞ>O%utvuu:څ|>TW1뗛߾~%@ϟ]} #@o~o,OOV&/.>1yˣ=Z[ZF\X$hA}utD緵MUǯo^xp389|>GDꐺ33ᱠ;86G^9N_^>.-F'FA/0t#|Xcs8 9t{;0*gg"p(r%BX ',V#0=aOvN_<>>>=8ԧa'6۠AoM@ax,BQȤ^8;=9zy$P()e29rW)lg<ًǯϟ[//>~ ;>[&x@&2 ,Oi )tjp۷o/_|׹9pd~h@߻`OO__<7ןx{%alM9a+z*JqT @͇a^^?|Id bp#`63m###þmt7yUUL=utQ)lT 8<@HqtB珷 ޿y}c͍@]d 7LchH`((?v9 j؛sd-ÇwmЇ|VA˷Wj# nbpPk//O#&zfaIQaAI^qeE%D"/J&vm}߾|0|(IȮNǬSzC WWwjyGe:UX’ΑbېGĠjRV^nvafV"s/U.FWn/ 桉qdWipqUX*ˋo.!>^0KOBq(CL KkJZ:U_M/-4NyFrrg uHmNuU~7p`w8tҸXtԽ矯^z}㝧[BGcd2OH-/ɦ0Y - pGgWfƆ=u G>(V̼3PU {=5܏'7|H`%)iqk3GCHXmvA%sO@}x514]? j IYit"#bXzsgL!Si8= _,7a^xߘW.leV4"=@84:y]N+@Ȍ:W@1ˡٳˌX"B萟p<I  rcc^Pe/A|MmM8ZجƉ` qiڽ=7Ƕ}ڞ(mbjj<M'ӨTL ע@g( ml|bo1]n`:o9=Ξʼj&օAG@RI߿|xݫgK;9sG‰82Ƣ2F ('< <<:l }Ah8]vhkY-"!%`h m6:vOo!=|<(qTB$ 9e3CC] Qca_.D GߐR\G.|`LY/,B^폏~t?1 D'`@%bи"n7k)t%dHfdpVf*`+b=Ԛ@Lɯhlɿ~>wz<>db|n? GPhG@cDZ>4 tC,&&'|҄ 0V,V3>^ծ8V!72O18"؍F d.ӥZ!"{*c׾K` L]͏-fà5PRꖩo?^slNz 3qȔ Oh%`QJ 3.NgE"c= md8GC!`Q3LvWY(-;hp2gڝb'h+E>FmR)x"6 p%t@edACB2a/rW >ZZc0{FL+c~Hmu_zw4@cPx*9$O"X,'VwmY?>ߞr;M~uqyN%r'RѧꆠZ#i bQvQ:G"\dj~kxddI 2Ƚv0Ftn@\7ta3YgW/=MH&1^Lj_3 MNNL I煙3 fhgwz'7+Fg-tw_NBް<:!!Q$bX,ONW{|^udzjGTC:b~px0b:q$V٠ F{oW?^[T*5H2@O?4`4А" @cKK s#vԸnۃ  8RqFZiH5o?zQŨz~>6& +B5cxb~~aaqa> LLBC7}]7 FdKWTxv˷~߾ijM@$2L S1x2@ zy5 s807YvdtXfRQdk˃w}oFϮdەˤ2)xC6{B) &Ix/t ٹphvI@]G=jן ߗ/_~JxH+Oȯ4d}J\*eͱcPhdb42HC3|./855=?7;=?AF&Ǒ r;K{O^?߿޾{㐦[JKcW2@4XOYЉNCŐ1j<%{ 0ATcm3 t/΀_HczգYo[QP\U,j.*++2H_ˈAapȦ1 8Lb'uy'&NrOVȝb>h<Y#xh?}|(7'v^Ϊj(,c j LѯPбX4F'cቩHlE@O {02e!魃四;6_>}{{xNQY`443b[_]) RjTT=HN!E%tyWщȿ}07=.\GYŃӳ7׷w`o"Oj,V# AMM)*}2@"QKM aw|/72>&:h47=50ۻŌt[eMB_-Wh$chhlxDDNL H$va+G֦NN_\ӗ`/w^V728.,_TSvU*n.J%P(2 INxFp0|JdA >69O|}tS¨m "on/hv5f*UJ"i]~~C/hb-<.QMDz\BfDOBH`h,LkDXd2h0B0# zۭz[$P|tWTVY]SuMչJzCT*FuS~,r|7N"]l-&0ջwW?>9ѩEUUeuVn;Y_H&3SHĤ*PKK?TP@007.npyWٝ}) 4Q$2EA(B4#h73xdvg}6'$r3dMNvv߽)>zΝQ} 9`w?T,=lӘV+vy:<$b˫1rzvb)T>k]!oxnN6ZhmkooJFg?chhhW=6\[]]]Y CffTEC]\\XXX"44y6Il4rl@Ky6h4LD@y<}*xTyT&xf+Lr""~~z}7_ 6py' `yp ?ף% P(pVVVjY-gf)G'èQ+%@|#' tuv;x[66ʍ`p`08 3?8Y (+*](4.ppxI $Vk-k(.!i<#9Y Tj Ԙh`y$Qܜy%%`J h ^Q*`||t8dh^ @m^I8%΀@|Ҿ@vdҨ$>(x^F'¡D4 H$! &لܐ3t,6ljjrj:69FE^ ww'^|(y p KC@qծ0 "L.$ !<z  B&h7: P(^-t*H.- Yw<(̓fxu诤aSO j< 0rK}f1`}ee3 !^!NP(^ X[[T(̇yDWt*P< e>}''Z-8PgQD<42*  N <\ H0|fP$BJJB䓇Q)/oI8|6 &dćtV*$*I㱶FRKbanWJeѧ\PǠF@|"P4TUxO?- ZvJTViy. 803?/SZ5FCx 0<wb@5tF 4,Cl``>NJt  2{YE5 xIN》  |&np( @eNWKKK[ggowg#lXj'_AG8 %`:ićT.x[ں;{w@jzu߫)er9Kp{#9! ^W*%E6jx!Ҟe1Lw_}ϐ誫x1|h1[G;Dw}_|.,O,Mm/حRT6Ɨ76 a#E 'iyP&|Z<Y઩582ln>_X~ǧ@_݌{Le=BFc|SWp$<L/n67^N͉`oݯ޿/!-r2/)IcbWav[৖S_}~[Š./)yL@ x2Non~kVj 4|?[4^(V*aIi&02/-%L!`wk+"{[_bG[Z:M5\ _|(`Zk~ueirѩx|vV 0fA!hc$6ÏF]NuG`lY8Cg"  7omlv v3 C[|6CDt$ЮB2|-C `=YćB3Ng}skI96 .``n)< U&;޾} -`fĘh^vw = s"HdlG£/lf. qV*qnvs. $<|AdLݾz3n43"U*X;?;9>>8fvE:666p"d ?8ExXӓc`"mWeӳÃÃ]?d+ᩀ4דr+_ӼJe/}y}qv~rz||'G~0B!^Qc^י6+w_\_tI@uL P74Dg:CA_CV_|m^? }D@_ 9 v8@E }q}Y_6/.$@,VWןݾ9=;=F']eGv85g JQ* 5Bg^_\^NP]o1G Oh+l*rA(i^]]\^_N  q>/@s>1xo=0$@8E7W{k3yE_^s|Ax[x<_4]hv X''4Wd^M@ @"R9te?Q )/ @`ƋC*@g)R1jF4Z-Aר?9F> d I~1@vx#U*|a^./2jn P. |@(rLJ} wp;]8@Sy.  E~7/@π`05u6֫]T:7T4lnÙ|Ạ˫B^'m-o2ZmcݛON < N&gtr )f?nf2.K GFv( g{E}Z-98C{ůʋ΁<gYIxx8 x wNOOѶ#| l_~o=Sv{)h<`<Oq@~?y!v}=Szx!`ǿ0+n_3> ,/9>_?o*}IkGlo㹀y9w~ᅥ/u< (kx uO}% mΡ=]tA=ZֶIyPKK?m۔P@006.npy{Zםyqb- &B%YkI@І6c[&<ʹ͓&fQ;\NN"Ŗb}s8=3R@01+tk Qc4ǓArbzl>-5*ިXWWWWW7h\:[ZZldtt8].W7aGoOnXj*Lzd2 :NV3J4䅅y(@CQ kt9>:@{lNѰ|2>+?CqFWSgP(|P*sp| yqv@O!7Jx?G~#@$WpR1;yp ON Th^6T* E PUJKK8?-q?-T. PQ%"Ipv4?8I*:VQBZÊٙphf~*45A(x~`B( '{Ƈ5%*G#?'d>8ڬV:?+ah())sL** FKTz-O@OV ſG<TX8xH߿r%\lX0}.@",9^&3q<q@/:fKMX8^r}nDjxԃ}=Nr8YhY?C{ 3԰#ϓ'O@o}f6Xvvvv8)vv>nu=vt92/<xGqwC ,z:xyv%Tſ3;"''5W?wvr< p.xJZBv+BdK&x*O{ K2Ɨ@͓X U)%%J{MmfǓ (0224Lx6!9+xTL)SBT O%a/>ȐghA ݘ?qިUi Rl%QЁy'C*Ʋ2NE^Rv< <Lx 0 NAx8S),^" LOc2 & rBЉr2x ?xxI$Eṹpx%!)ee2 r#?#v?i2g00U 8XZJ<qp<Ô%x>`iq1D|,f (^FSB;xH $H_Lăe_prq wR]=.@"cT*8[ 8LȈ ~Nsq1ߡx<0<h0xͶ: <B.Dۊ./.< ~tvHQ"Qe/&`EIGL|ٗ=:o۲\|f1. a?32: rBn @?࣑y6`j28@ AFyQwp3^8`y! <A*- ?ރZPd,s|$ 4Eorz&v+hf+PJN\@tnn:45%xÃ/**Y>?_*&#\ +u:g߹)!`j~>A<hp^ X($bh($L-/D<Q8W!-DT| 2xHtE!2*udH)˸- а찂LY2xXYYi·*L^ g(az@8^^zlu:]6OWb$< @GN&Y"ϠO++8?;Nz,%\< ȕ 6);f)~.x?7pEfQJmm1|5F67)..Ja‎|1̰[[[;(XjtļN5%*'G8>˧[;0 77!@. ЕV[ZZ=]uw<# 9>nήvpͧć "h7!@*2/ЌX[]=P+ # "> >< x"SDgSJƂKoG?GU='a,w2#7o>#WWH}=h >@x (,=.4*yYckp1 0^ y|9s}}慀b3E8xcwuF} * sO3<⟜OVW1H _~IjS" mU:\C('`vOqOc3H7u_n' Ԛ'pT G/ode|  &/B:t:0jJ'Z BӓpS|K9L&o-TgۉRNu;:rwvk֨G'Fc>n'ǗB_e1匎]mCKomׁC1XeR|u@@`4FGa=,Uj~Hv766(~$ꪪ^О [gw`@hEs,_ypvrr|xp s.~]"<l4|ݴ 4d(``owgw'9':D<<.={s#glկx  kr[e2]^snVl!$mQ+Zn/2G7'''{;:ZEU(TQǷ7C=~9 +D,xFF._vHL&qSj>!]Flks]K/ϏӛkK"^& (9D<KH 0.N3ypx|VT*tف 8?9I/Ne|@g9w<~6_~f2qto\mx2?̀z7_!yps҃y55I ɲ _?C}B#M\*> q<Ch^.7uafX~ssN)/.]b}ÉxєY|.(`wQ@ǣgN]oll.|lJGxxÙ&sGn_g<NMU89ڇFjeyey1 NS*یȔ_ɨVS\m^ǽFjˈ<+Z[)~n!*kUN)kT:?tNR!ځ,fyd2Jo{qMh&G& ekb9O'm^͝N?lԸj4*>myn`Ƿsw+[[.&wO#v;00QQar0e%w.`Fxq<G+8jWhS8|Nls٫4hp[Moj'5+ Tٿ :~D6Рx؁Ta.%r1_P Zmk`wwiy G'b D$m|12p_PtZ}iU"잟|΀P@Jjkk#l%>XU {`]G2 C3ZbV qN0)g7O>x@F&X<0p7jf1O()J"H;Eo>Ç6D0ǖwW5Y` :<Ӈg؛I_Kml_>/-C 8!5(EtSۀ])+7o _q>?/n[[ـՄ wŇ(airWW77I?~׿b^.yP]Zj|PMxVE~DT<Ǚ<H÷"+Gvx5*@<Pޭ DWԄ_=~7xe=PKK??J P@005.npy_#_K* .$!DR$"!D[@^vYeq9K|9yIvdyafgfsG{cS_X]ڡT_ۦf|Hߤ1-+(/:|YNǿdgajw8Vnthkmnmoninimkn,6( /+ägdLAժT*FC $4 5&yvl,E^geVf[Itp>&[1,,4Zq, >||@kϷO7*I@m-<bJ> %p'9$BTمنt=. I1[a_ |NvAU*Sl\"IMIUFFvayp~D`Ջv ?`p 0 s!MNAtr?<aF; =w_[40Vv¤#= DG]MlXmnZm6n,[-~Z uـ"6T_ohlq[I\^65:A,V+0j+|_lՕfKU\YYQQ~\aۡ^?U-eGEI~~qiZŒLЧe_S]6Ԕof 1R] Օf;***UŊF~ 2 ++,9 l&Mf1i-N:NAxvC|grO/D ֿ7< ;U)D6@"!ib |7(3 E#1OH|@f3XJ_V |1; O/J y#zNCxYJ})<`<g\i뀇3.S߿R8@Uhhd(O̖9)/<0W10Y07"p4ڪk,vfm89qTjxy>'KcJot68֟--8654:뜍uZ{C5'z%7Scpu=]t[]ppA .zZې4@^[kJδ47~? P<nwP\:=5ֆfv.,14@I&!C;>G'&k{|CǓ&CglBiҫTHfQ) %3'..! :\]]lyELPbx+B%WMy6. R2.s\N(; ^"24\DkU5JFNx>H,/>v{<^:+K$.K,k^h𒰃. |C>@on y9lt)gdf GИ:8 <#@įId̄ Xxぉmml|B0¥]R.g¥H vg|JT8 ''&& 8gxC '$i@~(@#)Th*4F|J;0@tGE̳KPcAZFy)sc2oqmm1nG+.$e22`-CEss3S s 1$4@0p9jOɑx>^u.@vg:,J*EjjBJx, w̱]!@ _&7u&3`4@%K!^?1<zY6/eɟEA<0)) I $@Iy 4y1`&d=ݔ)Bm"e$Hh+x>5 y2ztv.x _{-.!'g'd~_? 0zp:b@H*M$pGrrBr@ B-s /y8?;KB4@qxcSSޣ~Rx4l |?4GG1`Be$$=!pp`|#q<Oxj*32|ʿӀy<06AQKs @x{HU<.?䃁I>`l#\QK"@ %eQB|@NLa>`l &DJ 8)j*u\CyrWhu<ca00:9 Spȯc %ӓ. ;;<<kY*U,/|;xJQktƄ"l6 |tX[zEZmp!;6~xzp6^=%F6}fs>G=` ayeUUU"-ƓT!` q `x9 xr5*Kg1@ ;>·a𙋍FWӀ!Xx<}yדJ} Yzgy|k6`*p0W\N,=2ve^x4X훝~.gB,746t*P\ jr+ ȷim4L0OyNuzŅY`"3s0//-B`1`<鱨[w66nM1_X^_1t?Ò 0/./ OFYgpo/!&VlLgT'' u| sVX.8g|- #8/5#ϗZB2OMMA.sLO.-4eY,M?,lW~z}[iB:, |XM.}eyyIӀuB &'xbi{OgHHbf?1<`囚\.oֹBG$ǯE ?-Um?o)}uuyIFGn 2sեX~-G Q*m󟯹q|}orp^ XZvx<{CC#CC/kX._5pEF€ͭ͝յյ񸽽}>Xe|^^pq\~\\A@Sh&![g2ZnllooDM_(n7vw7|^^IC?"_s/_B@4`sU*]moF7U r|^nnn O؀K8#рW߼1nt;UbfWnooFx~sRZ/16/>+i_yz}ˏ?c| h0r[eϞ|x`{sw{ntu8,"sO.oGggת؀əI&-{R1'O?:=?9:ل`yw|ZC x_C@Q>8IxJ &KJ˗Ϟ^}&wo~ W* d1&^3?gO?|tzvtAB=7/F^.O_jj :"x?ͫWϟ>z|q~zpx ~~~b>%~å>÷{-\nT}g7}Outtpx|82{ E7o1ytvv||z8?'==\@Q 1wv޼YdiL鸔INN_?_x\v  yM‚\coo\}]QKR$)2 ,?z^?}>z[a'pqv6 MBSCi*ro~=a'kWE4],O^gώNvaV,ͱ<>^z4@*ld MuX$-5G={F H37;I Qkj5eιWGOcy|\}v O D"X;rzrrS><~۟bx'񯿲?'Vf݊x-b vxJ^y>>@̗g_!xX/. &4BHKwtq<_Fx8"KD %='֞VR 1WX9<>:>݊De3T*So0ŗ 5nV@;MMv$_O "w1{Fxe$@^h1^c[/?މ4%.x@ϽL\Q_ZPaDZ:]fel7_htq6 Y{[P*yO\ݽHЏ\o?wq<D3#E3R͈r;-?D!ϴ9~hkfx ZYmxۻïMY00J%F#IcouKS4Ս]XG ഗ1v{oR~~Mx3|d4ai ˷`T8 <Է&,_E*5< Ϩ3̞H$G>\p)߂Sh-X#2|R+| >fQDPiUe-58GAŁ;,vChECr8WRY93-ڎ=,SY]s3!`y" ﷚ Pkiyx k[䝇5_^y8;;HxR[]{\.7 H H(- # v݂h4P0Gx `߀Y`+٪BgT$᧶Y^KKS*v]=# t BSy"z!=# qm:^W~%gC$#6:^-F:0-⛕ lubB97`g+MyG?s+lgyyN,뇇x/6V"~& Go{K!b hHCLJSE,)aƖ.KMc8\&Ҋ㓒JFgh!͍S$L>TZZpA%' Cѥ…vh9:P*/)䃉4TX\^dž}NŪ6!,;;/[ebw¯  `*,|>>_-ʖ~R Jۗ4}K!T`l*Pg.cNyda1=|zi)0;J_ѫRWa@ |)Hy!Lzm G$1|+{'^|_wo :,BxyoE-2> ()ʣED|#߲:R ; _Fq%F' KO7Q^+O4t<l(-{Cꫯ۷o WzFf+јcdNy`H.p"?9O| C@y`@y8x+K<⫯!o]/4&@x+ǃ+1d3_}_Ǣv_~*>УyE.PKK?+c!P@004.npygCWz;ۀP/ Q w$:]PE^WL\b{l';qb'əqsOkW;3.ee‘fU`_@U V͍gRĪo`,ؼ~'wA Mʼ"O)y1}xxxr\ Q[[[WWa0m4: . :MCssC07'; /#-MѨT*\.H$R(>ڵkWk0x3 *N`06A:Z[ۛ[[ZۚjtU\mfzZ:$*BA rA FP ʗ E WTgd#^)WgjA P((1 /1m@{|sr&PHE(0< _Q @LHH T5?ţ@o0IIbQ 1!jK 7f[uv =u=C 2'NQ@Q;Pdf iL2ө@sS9_M&"atc9D "[M|gw_t>xήpZv[OOwLo}_ hj-MK&x};kpdy9/{o__n[l=Gt Gs%*J fsKskhtvk>#v\nנs=p:>~׀k`h54<84:4ހ?  9ݮ~G+00;??k:]y^zF*gx* jPW]W555z}UJz & c ol074c陹P`nv H'$p)|X. 0gb&%JkCuueve2L #O@OH3ht ěͭ _ d2BC'rWI >>=~ r{@g"B|C'M He$'sXx^@NqTm Սq8<t [-4p!S2RLN_ [@[,VnY1 PV#iwOwdJp]JOOWTJ x F^J]N'\}8zmVHu cxxQ<g\iJVe ~=  !܃ f<{pAH @|2ddg\L&_%zFGGG>80tpx*:x(=@PʄgLL5T@(Kx}^( Q1 8@NNRH 0Dz}TG`GaNbm(U~ L,<hFmA@6x x gqI|::,D?wXb. |MNNV qby<@%[#}q< )q.-*  A残x[:+5W BI\?*J2r<(A+8$_xOLP='ltVw8*WqQǓMa)^*qn&Y/OLLM H?'}}}0 #MKx*u6OERiF6luD01A #Ieٺa&쀗9| px8eqWȸK( `|Ds l6C8*[aT@$“Lj 2MP|r=vq8D'~;"U HLOOMLPN?a/F?PV#>1,Q .F@vO抋ӈ׀s2! 訋9D, GJ\il >}l~ Q?s,=`x0Nc + yD`XGA !1L>⋲R& #:)^ l%kb"gxNcLAZLA`qq֬L>ђ}GWyT"@m~ ٙ l(Z)01XRHyU1x%6 ^44:AX^^>"ݝͥYRGRa T Q'UOJNrLC1?Q?8C|00#;PE*uvA`\]NG.IJJ$lJJsPUxK.߾}x ԔԌl| *I6ufJ '@03C?>>^\G|9Q]Ƌ6j*U[\^^^U_X_IT PIȇ!㝃%"GdtwYQ @ZU(Wʫ;QQσx%ǃd xF3<=yO#R|UT5Yp;:P@,x$|xx)*@ 8z %@XȎRfOX 8yZq0'91>9):SshTӧ1c* DiE \I kZPowHIV5 _YT_S$PON98s&ppL9L=P"]ٙɩ xc6# umaQq^&s~$> ϩW_W p 2Z\P\tƒ$oYXYf&lF# 4KVsc ffQw:ׯ&xpAMM10ؘ;H*sln/-LB< @&H]F-,,.)&}w~_ _ݻ'''Rߘ D*׷xp#7əPLw?߾zEߣSp[676b,gVWCΑ9#>'a^Cf>9{*;_iRDrvS >1>8ȌC(1 A`bx{z/߿}>}xG2|ӿ^w3|bbT 8hns ?7O‘p8<7ŷ7^A>jz';88+..ywlz:&E3{>o6D{h~~.'H8<\ݹs{aOo#|7z( ,&d8GFCÏR otkts?Ww0>E& H# 䛬V\7|SX`VF"-]/W`Cŧmcxo?Cl 4"0?4 o@MM6GD Z<>/vyhip0jcݝ͵_^[V;ڲU*)?9) <5))vN`gHUn|r6Lkk+ab%dauww fOCx N>AC_Ľnmmom,quJZ얯F<8=9/n>z/_}O`"!PTnKy|j޼qps׭lfSAAQ{_~쏛ۏ~뗈W1DpAx& QR߿٭7v77V~sJ%οxB1yO}xOi͞ ^DBaJOp[g'7w767Sl.Z։_|j~_[:(ӤeMDdGtAֳ?{Onlnmnm8.?--D/^| |Xɭ͢x,51'/O/’_={g޻}ӛ0~n _j@>F|^8JU*M2]K^(t~͋?{Ӈ8<;8v\=@~!_YY/_c "P"R *JT?-zŋg_|On>;=9:>:X MB?t:v[OWWGA_aį#~;Ro~Ttݛ^'=o:;7MF"P&)?/0 H*UrJ:2֫>yHGG{;kQ<^^@ 2O69 FIRm y''vV#xPD A7[v:#&=T@AJ~wk+< T?7kPgIXR{ >F@Kѫ!頗q.O`/_qtY"Ke*R繿,=39ނ B h͔Jr\B0b*Qã_@C~:CQ bmT x|1rFsx" 侁J&w1J|Z qjڼ y_%&s Jl (KE9)׵B^^^譮|&>omA'iѬ\)7oqь$ӫRy7Rp`F+/K55 ◗#(~'8=k";PhR&K9f؋~"& SF*_W☣J9~;d`xVRQ{<q = GhjzfE(`i'z(%2*CqQ<^acx2*ʼv(8vZmĔ@kŶF+ G5x#<1\)UWX`= m N z&\YʹVF  PXp| ND8тɟ' '!$fX<1%gff`9Ib kx@Zq3Rc c'-x/_Bj[JE{=Efx|\WV˰{Q N 0| wC!F : Augfga<&UXe-G“.NPf%o((['9$enDERxq>4=11@vXL̢@Jd2.I u^˅jurQGpzqqvvyooª. NOMOM@_7@sC\ UP=5~-!U2|Fn$vC+!^`ow 0߮#AZ?7: A@J8T膊N߻8} XpoOU/NL,Oz<`>.ԼdҊmxagryb#W#g ~^Ņ7 zy<V;6D@*cxT\L(ɩrեn_fe1|ZIIgtgţY]JLNn3Lkllii4tL vSS/XƟTY-гo< mR~,, %DTK&@Z^A `9Z!Es8M휞:=;*|@L<#"qa h@Z^ xH8K- R<8Io߸qq'?|՛"x'*l(yyDxFz!X*8<PUaL݁U bpzLdG|/l(O??9r(GD8< ZC0oE"'@(B~g_?ׯ߀?.bG|KFb()?s2i0@??$Kv #!N`vo߾__~Ń@}]e%(f)GnC!Soe Ńb0̄ox} |sb@9 hS}91߲}||UpLk0&Z8|g;K@a}S/PYYxHRvQ)թ)lw$qe?#PHvPhK;/b5F^ 7+_KX< TL8 cV8./ؐZx;wQpDR*FcS hSSS9E = w 6Lso L/@a?W) -gzz (W,єJ^O ( _#{?6?+v}a ['<L ?~wP_ \ͯq PKK?Ƌ+hP@009.npyOiٷn}A @\6!0&` ݝcQKIkfwZi4v{G-VWyz*B?@o쪧\F&=g-OW6֦K"f>?w?H!$22]uݓH$ۛJT@'E}2B~>d4UUUⰠ! y>?Jܜx~WM,dy!를I{&>g(@ P>ܐX8?=95QC]>lqth<Jv|ݺ_@GL:==dO2jSdfj\d(>b< 0!|65)锤*%OKxx`ȫDՇwQU/H5@,\w8P($z>f+P>(_qMxpptܫGpw$򔯸&/2#8 57 0]~;=o@y7VʫVSfo`gyC|pd 8yЁM!y\Xy2;;3͚i@O2!{jHuyyٳlV !pī%cfNLVZ+wYTZ.-/.fb Q00?\N+lr6k08w:Gg6PC6k 1/O>Dv>`scCMox1`k/z^ :x 66H@(c.|e+V<y m[$^(@@v 6c5>p?j l|8ޮ`# !scMj 8?|ʗ\>?92>1޹# ۵_OBarr"mk𺘀[Y&C@"ymo)6ibL^ G|teYn2 P\pڹGsO󘟝`54)o^ 2b| y87|4 `y!@t:,,@ܜ|҄x^vLd3543[L<׼0q1<pIhrn7~3Xwnb%'KlRn0 y`k z=;e,/-i|,-m0soPy L^uM@oi (|sؽ^RU< /=`4,)621ـ5`|uPС>U?g;z4hn(b%PR#8e /7 'O) @ZiAvPv5 DjQ^*OOA^\ĿVjiv*C p) B흝=w^o(BS(WGr{KK#ktCxgOo:m<< Ke䗯_di#CH0K V;4|mm`\}_yu&ߡIn븫U{۫7VK:>]o/MŽJGϤb@$ .g:>9O^;1 (v{|Ha3$/.,,nnS} :#mM#ǝ7 |Tď7ò?S\*-ooj< (rl0#MMWj?v!Xsݐx^Z]xT,Ňz#y!=^%ã}̣ojll>@.p|q8s$πwyt|@$}ᐎ"sC/ȭ( Hd|w8pk~vrr 6@nimmmnNFa?$ ~#{|"O'1Of< þ%y{wq [C?fǙ^ @| % xhoAzw fM!ß2Df,7Z. ]\yH8~4en$U p0]=Y|rgY[u.@U[\;+M /OTe(nmM]ֺ~hB\pȒj:Q>;YE nm2Kwx&@WXĦeȣTW25_ C{jlg/ y5@o<-7od37i@fqdf0TxU.'"xQ[rW ^6]>|e^ ū3&@՛K~dʋʽ$ ?.)m?)8 -\GZ%2E ` $6~u{>/WY 0jYtTDI,<@`|{(L!ME a6B8@i x <dJ?k cm߻A|`Ƨ t*T&ɳ&4V_,᷎<ӣ$DީzTrPfy$Cwv7[ n\3^~.9;;;[9WB@-<:y3_OGW+,jXޥwEsyr;^W9^ (p&3p4)[ '=~OKPiW9BIG&)6ҥj:uLl' d⑈񑈎,=eer%}@S.vi/>R6 #S§)ЭTc~j6܇gKJ@+jeW`0O_\@Ix]- PJ+f'_tFӃmc/.8Muu4@8"O>|qF:! {4s~46ooJ/lmz^ xwI_`q_ >x/ N]t|0uζw/Tpﺀ6t4]Ip bx/X8u~S^>@7PSj ;poڇ^F_ k6omh GJ@d&pQ?y&(N\; jΫ> n6 ]\^^|S"~~8{1=ng\翢R?W<㳼v=X}yyW*^_8{n9y~}}~i&.}=$1 _}+NgԸp{m}o ~^yPKK?5PhP@008.npysg~ۼbC]` I,($$b %`/bb'%78><e9xs[77NGZɈ6577?"=wɣSH(PU^^^V8hx}><|vݒm.u|G.(J|B2_pEQyw>˳Ox>wʻs8#]G xw.<|${{y1;ocQkȼχ'&&&Cc|nMݮL/သ']-9hSS4k57E"Mh$Q[Mݎ(d_q׍7GQ`Bu(4¡Hc8Tjho4EsJ5v2Df2[L@|x ߆fEDa744k0r:ID/7xNQ0C!Gd4yioE )_xtNwN "Z>"<H@F}& <|++6'88<! D̓w@a6H~=! yjԖWI <~((P_H%#VwYM}=~Ky+(++x[ǚ#:! ~x|-mpjx{<-K@˼yyJd#B_*2oWyS^`2Ymti(>?[ϱ<(2w7 aK9Zjex-EEEVM _x9  y%+bK hmOBjx5@vu V8mX ئps$h&4Û9@^&(@f0^x󤫽-5Q; -ͭx<~AhXkto=H*itutuwCM=>_ěO"1Oc< ViyěLgIC@;" WfC@ c"z{sh|5K|;WK{t<ȼɔ%  >?5YMiLL :^ tr6:̷9I86嗍6 /,egfTFҐrx H&S~aQI-Tg`\ax*`ei ''p=o)<Hs޹C`hVV h6Ν< j\]Z"YNC@bvʽWG[x9,8~ 5|z81HȬUVVR;eVBf?$|˭<J<@Y)G> H $SnIijzgא|V Pyx,JӃ憒6@B(|vJ x(F۟Gl*?E2S4wd;?\xg@$`l43*`2:fs'V|_ Q@&C' ⩀C^qL'S3ccƨ y&͉Tg<CC @|̐&@לl'0G0<ÒHe*Ory/8e/N9nV'_sL曣e v ? p"8wOJKtZ*ryPXh'X0n])YA@;L/c{דGȓ4< - 3 _{fcS^!g@|v=j*NgnZh9)L\6e|fajQ&n 3HE^6vwI77[Y5W狢%x)8@⍶_ nV4vwQo` U~eW_\Z E9E5,d}ܪH[`\Ʀx[K=0@~@ypp%_/d!@Oepl1) 7FZÆD"g ^ p{d2ţG[X@8PDdOe{(`>*jjK},fsksc}OjXdݷ}o!Ckxl}[8`}}vvf~n~^G"_}w_{n` oTb^h0x>3;0 섖4v_E㳗%n6 Z< ho6ޅʓ47v n`::v42 \vv}}qucCãt:}2|mEo`Ȅ.@;:0wiw//m[w6d2J?N1|EEKgǙ_*iloooml]'+*j_@6,_~ `r [(`kSb$Y߾˟f_2I7unR:Na!O5rM϶üO%exppO7* CdzԴ/υxIcV+ eowg=5jwD*éq6@_WRJC ; (r[[ގ|_o{DSF<Ǚ혷y/:<8>SQ@9;p+d!<԰uyu}~q~~|t ' xt<LEVM[.Oupxէ$~mDkxrsfdC5l8=9= n]Dw5^d%'viwҧgLjR% G*p@c"'SkG놼^a Px@Wҟ4/./ՆW@(@*o@.#57ǛyKC[Mf5 -؁h @+`0ֻ65tfx8Mj@#8ު/шo1Sx,w\|gt<quuqrbceeqTS14A^`6x*ʘPXP< rhQwlL|O`*4<H_{Zx^>L]Q;uޖ*K>ӡDQ!`Rwvx|BħGGR>!gx <e%CxW`[~owkBIL3l?חf3˓At:V3ڿbڌ7I#؀CN֪Gtz{7HK)6 v+#vw8$\2?;Rج6 PN7<:d>ng8$~v⥀1*_VQK͓WIOi}}wG>#) tz3=U]^.$StW4 ^&ώ?lj! ^ԑQ9KVC/]ZX#Hi 1<ѕUN/4q@-^@@K 78{|E|bxxONO(VL@ Yr(.paS+gxt7 L-6s:յsŸy6@Q@P8=K~*bEhcX)^\K7y6"M~w>yq oh}l-gy1nfP ֻJS۳_R;x 6&'(߯-ܽpfxkQO ~+rN76V/oKw\Mcvr3٫|$ʇd/wյ}zzzFky)`co+5p)߮T]?:=={ x?K> ?<`xwD6^_2ѵW~~eY⃨|z]Nd6yV3 MN{ViVΎ.}{{[c}AWj*JJr2Ti)2yZSeZm[kقdƟ̮бx67:uzzz{:{:Zޮl4u@˷5#þ0/#'#dB"J>iiյ4jz8Qo~*@5>A`-6 Dhb< NXp^Gc~=ёQnY &c__w PxnIWQZRr&;%5gPpoҲ<75 '''C!ąB|4]ZZVWbx]/.ήonlnEgfAև{G]v`4 LOG&'@([Xx(@< |m5yЋm+n/8 0 on~}jaa~AƝ5F 8G0xF`a/п1V 'L'O1 2-?:s* G5cd"<9 Р4h7~Sa`2v }=y`28h9l61r9Αc up|,0 B(gcCҺEEeEgKKJ+**JJciIٳՕgVk QЪꪊ6NiVjJK^|$⌄kjk4Y֖쓙ujMZѨ+*JR\^!tQIYiiI1<).*5 D3jQAIiUUUëegJ 5Sy٥%%J[THKOW֜./NT777CcCCmJ@hjrFK\MNUIԪVVTijJ UQWW]]Q~) P' J3/$Jӓ%)R45X[[`odSH/XkkARDA'OE"@(HD|A"D ٙ\ю%.Ԍ:IC)ҀTkn 4^%Jx|>E"!0EBX$_ @>iZ7` 46R ձG ˣxb?GZZ\D 4TJeVf<;"A!.w06gD8gD@ˡS TQ+>\wv`$ZZ l7$mjj33WJP&qrX2;;::::;hoC-G?#IO̬<P))SR$R/)" =zHߣc$ޤ(" )'O2+Tj!H0݁CzF #r}V*A -OT_%_jنlXA  xF]; srN@KDq/[mvbYP&#j]sSH?VXR]C_ 3\@ pXa0,bSX,T}qnFO$  YBi*"HV Cqbnw`"oN "v55/&&&£CA" |!u l‰P/@b*T~/VRNc(LO>B6 %?[o$^=v;+Ns@2FO/DZ}4dIO0}V- .zV0y r˩DTJB!gfh4G\P"q@:0 twtw$2q<(Cid_A9(*/#x@|O7cڸ"vm͝vsgw@ӉjYrV $+cO\]q|? >]] '7ttaE<#qJAXW!EO|TifQ!|#pOHi0SyyD32Y>V ;pRS|?C?4F#@|bS)^kACI<"&q|I v }cnqaKVٌXbZAׇ,s@Zo} dR /OE"QVOrH`a5P`V3!h)Q|5AH@ Q)T*>B(qD<>{AO`96[@du[k4R< P|ks !*R1DA@PXc\.Gx{^MB0Y]QFh7 >y'x<" Z\1*xH"I͐,sϗ{o,>àcЈ5N.( 8?J`7Ǿ`/R>~qp\.h*c@5CrReV@@9vs%"D$%|'N_O?@>7.t_Sz)$5P" ]ty `>"2C!牉@gyQ>#RF9z$PO?]@ooQ~{ GPX,9Td Ke<;$GQ`t &?I`MS9pi:Mx(RKhad#Lz'?A痢^إx<8Z>_D,1QF I>#o'x0: x){|l&+/0x:T%1# Pe2w$efPqaw]ɅX42 Hx籌^<y>=/CS$eRjpbwI @ÞH_<;5s{eڃ ʼnHڽ{ˬiAB+B N~ HTUUUs @|ٙD@k"a'fo_?EP`xwo뗉Oו@Ha8gp gJΔ` $a!묜Sjqxs׮]nXZ!H.p7mm ٨@e[nC_w0xkxrdaNߺu:ػ}6Q|y{ :.HxD ?3[[WBD@40Y lea=ZP\N.!^Ylp¤%KLluhwܽu&vֈDL%uuД.\LaiMKR&O+@ 7;-n=D`( 'Wo? moeD Zku ~,F=Xq)REIթT \z@>f(U* .',(^ Cwl<0 bx9?O=@ojm[)!_JPt(HgG%CVQ١+@(pɳ}V-*9 R54awIn{me)0 `F߁xFc #Ag^17W?l|k|X};*ՀȭLph"4vvZ">A`~{ۋb|78C VS zMS?"x40<=,??}"?=D) 'Z X `s$N, ;wX`2'x080Y0-0 DvX, P=*y;wܼqak:%Qی@l=6_6ϟ&+`eB{W޷kБ,A ݽ.90 k$gvnvJ^Q߼G~{??}㽽+;1رY,~K_)q?{+wwmnĢs.D`|A;V໻kJ)##wOw?X`jj w(@Za:?D^{ngk#27?7EH L&`M3Wϟ흿yO?<@7Y?.0K݈ύwnݼzZ,:0vwLCF[aoF 0tMM[DIG݇0ۛbt9:׉q|KSDU?{K7 e}C^`- Sp}7][{.]mߠ*)fţ n:K+Je?O=ݍW/loF-A〱KX)=+W?~ ωt[)iyM(À zRyo߼zу;\߽{ܹmȸ׏{`$N /mCf /_ᱚU~F*=rt:<q ḵdׯ߾NMJ%$;~7yy$ABWLw` PBm>|23;+3YP݈ ps8<1/xq@$O[SSAj_Y9.2I!>| 0:/@lf[BA͛8Uaryss6 >=:Pm$qJQs ѥ%<㦡!uQ57wԭIR D`a>vyvKǣ:Z_k "YXKK.l=jQOFggpWO&7< @C"E4Q(J-h`?3ǜeGD~bA]\M>2OF4CxAT"NT޾iRV ~Fzy5`^sj5  hā4I?}D'|gέRr K3aEqx7Px1](;UՎx#23m*"2Oݡ0Bó 86fDMzB }~O90RKi^6s~Dp1f피Fwb, >HŒo`5x}YFZ?ՏWmUnP[JU['vuvA 0 =>r=lRDC?Q (A/Қ܀/6鲱ʲY" h_9]67 tXT0LG(YP@' xXc4LXf^_$'w6ng)>.`1z]3lС Y#K$2DRl1PI@y<@޶~ !l 1 T4fRӮ!JU l(044de2!$4jS,a it{gwXY*.!Jϓ]/ Sui\[tT* AFl(gr@QrOʳ$]` W1q.A) ^v?=zZ\PeňG"Z9B:މ(gMעk:W(~*+;o}O?o_$U|( 4 9l'8KWşߌB2YH&c;~?MlgtF N;>۔sשּׁPW={ v+l<\rXƞ꒒|*pv xZ9*Tb7 ~g)J`d}wX|\] V( wXX;ͭM*@;닋E|p <;]jummCsKSmmuљb!X@(P#(^"OR2L6Áqs;;? .d t}姫t:2A x6XD> '$"8>.}n{aΆ'(~? ySGWTUؚ0x-d&lU#&-,V Re/DX7vQF[uHk㟌xUv^_VcY.5F,2TvTU C K0pxf wTZ 60# C  :+ؗx' eX ̜@`6 ^} ߡ>U"V_ >;W)::$#U<PKޜ|" 0x C~݈@xV0^P u(Y03O:|"qc ~yazOۏ NV|MYJੀ# J>@vM0W3 OJ=xER"9,#xX[$n=[cI>#6_>wX+)LjJUIIt+/PKK?sAP@010.npyOiٷnYl66I0! lBFZӣV~H;Z\UNZMnk:\|N,LoNڞ{~yOvV*}~nn/8NV`vm8 oЂ `yÏOD hRShO~z\ y'H>|p*?9"#q% 0pWG<^  A C'&tt6Gt x^)@tx xݸh0N@ ~t xE^gffg$~juq"cH$~ǯ噀 (n:HLFñHtb"p(2FG!p4^XKLN')$RSSԣG`@8 74`.nә--=',/d\ Ah0~x{ i0 YL/fy9@v-V~@G>'< PxjAޢL(c0>NVy4"@Ԁ"=^j0>N Ytww _>_j0x<"-z]6ߘLR+b>; _xZ@#/cK&)~ғRimu}}0 1-G yzE `lo67ʛ33r২ Y Dk*;;*۠0`f~^ @<Y,R‹8휀K3׆| د‚tz^ r&^~t d0I?`E@:e<@BfFX<@U+pEEρ7th6E/NX>"7+BA*t `x`&Rq XDK$mNВ_[U 4' tt۸ $ @Z(ťEN6fbV2<7@,3QRIⱀUn+OhÀ=n<)m ~}0 |A@g x ( -mtu ߅8 0ը9.À À}[,&6FT*(`0f3{yi2 VG.`0` Jid[[Gg)Cm<ٶq@l-n?h MhC >oF`_Qѷʼ) U-` F\NV`W%vdE$T@xKy3ɾզ|czd0`rS2l Fz^z-(W h L|^ ^\^{( 5}T|\ ^~&gyx)XNDO}^ xmKg jU w84ܦH=AKLNO>8>)@k]A?P3n78:=L$=?K X*,TzãT;|o5%)Ɉ35z[廻!w|RZ@,Bw|.>J|?/(ᩀR(tG 0}yཾdN<9>~%ɀdzdsRğ€-)`-|>iƫ3/k;{/NdK?Xxd }3$RީV/h W>}ګ ȏ_9><,W>}jll,O(L|msy- ">xPS39< MaT4>,`A/_>EVWx@ N5@|^xt9ɗK@V3w~_ K뼀|!x9Yl1A+/)yřƿ iTařʿBPoo~sSO%,* d eyi.L _^Y>}N  'O|H|sgg旖R<'$ߝ*~)G,O$|>@͕%3s# Ǔx5Q䳙t"28}|>s#ʈo=]k2 ]qy-=>:}[>h|up ^&P8M ͻ'N,Ϯ<t>h^]6.؀Y8 ?@2ɀTO7 LC_ dfa"CZ,t"r@gLh;\$v3u7zSМ}hhxhH9z"PAn7ȃ!Ϧxm7 xX%`mX>M^Рnx2O(< XJU^zQؙ[?Tx\"ߎA`2? a|-`v6{-@W@g6S >>&_ SiK">KvtV\&ғ#w޹<. @@"/J`AO׈X, &$߼zχ# t&GGT@0Iy FC0GvkXa{*_\Dr˫wg_\<ߟW2xKmˀ:?- 0~>?R;"_kN@G(`b!xF͛{OtSz}kSx/&.P:s7o޼PL'W?a䕀<0#w߼yK /?'À3hNk;x 7A 3'  xQs-klZʧY<@"ᙀh R#xx〫S#R+~RrS y.ODA)!x-y<y)}48<'!H< `yÃ.|1倈O|G{z8Y'__A y3|.@;_9?zl0j?||Osv PKK?)+P@002.npyCۺ:̝JIozQz B !B BH n;m۽>ޠ{4PJ(Ϫϳw⪢ofkm&@X"3Z}v ^iesgA/%Q *BBWWW}(+k\-uTTPVjjk뚚45566֪jꨔdfs%=51"<\.bs̩S?W4ƆPqNU>7+ll P()6'D ,'>2̷OE[oy@Eeu5UUUյ*ԣ(uuçg?cI@. T۬3ss Y_V_Y]cU__[rj/Կ *kà*kk//.++>--))>.&lظt@LZf\" $hƚgv0#'|qAaAaYѹsE*SEP(*+/CJss3c#RYd|لsiR&h~V|(Z ks־fuk[{[kUXަnih;u=]]ښښ*L 11Qr &7|n߿6x,-+oO;|q/--fg=e߷8;7;j2]ZVӮA37U[ؼ{a=*{~%t?sqw]w ;;6767/뭍UT,\ mN`=_&qu%ݽ xp_?\|} KxuK{w.KW^A։O/^|oIeeO__W~|yYa_.G_b_qstNsj91阰1vۄszzv~vf5ۋY,019(vE76/^x[_~ssn]Avj:t]iSk4-흭XڵڎNmWwgW/Id4&i``ph`x:2bqXFm1 KAwfn)ĈAo]k4*V`NJ[|>\NVffN^NnN^~~~fFV^NNnnN~~n~^nvv9zs\ssEHJJ חϕ׎tgY,Ni6,M^69!*.F(?47+/ܜ,JLLOOKW3Ӳs aWsK32RӒ&'egZbK2$h ^9WFɥZWީ+ J KJ&ťEEyyEqee%JE%KΝ):_XQ\TTDIJeEE ~&39$c)D"$bIxt'Fn %Mu (u UU*U5UU*U%JB_ey9*DL#6V76ԨU(e,B!OP, x"O(Kd,j p_CYEJ6,&XJ1i~j'PX`Q/xP(@6$BKbYDD@Բ>AfWrS&R[[ Bxy\\PxS K'~ YU-Wꘄ*r O"Z0|vFB)CGE £xJBA rJS |㣛PPD*dxB ?/g|5kn657_魾39'1YZ(_N2/ oR1458~KScSInnnGcC= ᫫olOׄoG^]Rrlzza\\+RR)ET{i 62h䶵"kдԌMU@uMuMjhCus,q2TJxeT '@& 1>= \1FWTجم R1)Cqq񑩩d'@ % )#x{DC=>CצVʠV?99]v ťuKx&@x&D"'+08-bDwDbA(P6a"*حASM+wxبlad)"ScbXO!Xejr<..:ZLkG$Bi1HaFëjgMɔ, FS@d"F@'&F$%dkQ*2cxHq2*kiשjYvҶ2sK#*KH ?1###+D /`  Ζ~65uNLo 7B"kM,( J5ʚ,N@JqqS>g9%6AX;8l#fТnc%D'82NKFUV3P&&p@dA`6ԯ"Bʚ&<*e%$D>/'ojjki |^|^Mv $'g&!@HۧŪCb B/imd:Ç 9R.A| 'א)g2\62 F F%6 隩zAlog  |! +Hᓒsr@eؕL*#'|Ftj@ww“N]׫Z`}&:FNXCJBI$ǟab>7 c vh}bLʬ!.רeL x~UUͥ"2/9'ck'#XDg*9j%@>Q@NorZ~ E. 'P!C^ՄIr92"AllLVVP ?>% 13| HV? m: _@OF&IpVwV.<>VsyT hi TU)8<DbqhTTvTL<~ |ZacЩYC򳰂'x1b^rSɃ5Ciljaq@,eЎ10Ŗ~% y!!!|$8XМ _$=+᧟! _4B#M}fFglztc2 Tx< 'x 9}I0!p"=H"AH 93O!+~J7@b%Lxè~&MOG&x?2< JSA V(+~Ke2I)0GFlq0k v;=1 4eES. <dS],=A>]Kg42`Zm6&`u/.@`bF̴d:1OM ^HpHZa p ]7 e4M,8#!]fwLNB~Zr2='YS$pO\.Wâ P˭fd9לb&?ү]ZZzg'&e79mpp0/3A᜜ٺ  hc$<^0{==eaL`>)2N@(QIyF(y,!,>{&sNy̌ȓBھu bS&DGȔ05@&Sdqx*&׽/z=.o_F{ff,'KJ >uH-*(SU@@N:,W@h0 Xo~ҥ͵Uظ 1\#q?{p].4ov Kijjt S<\N/+5ˁA. M={{_۷!@ W.o@ hivP$p:<H^le=":ZJ& )4C4釆8ɨY;8y; M7 qԔ)DLxstwєalca'cj̊$T. LF  ?2z}{ n6)Mff\*8Cy<[.#CHHQ(䔄9O(ŝͩm.rt|"0[pYݻC{{HWep|s 4~57 + omoh0 }|6fu@7}|ͧG$!_%u4gQR%L t]w:cHe%f!nF$еqǏBOA$nFFEGG*[zXI(W=  MI}FC^ׇɎNf%?-F+?} ={u*W77^#ᓪ)W,My1y}Ec1h ,##!X OFY Ƞ> իWGϠ?ٛBslR]$'X |mKl_Ȉu@ m '' ^'Ϟ=!m\(c5F}=H)ImMm=GLJH%pṂhG񟮁57Qyz||O߾}RsZF҅͠=$EaBIͶnsLJ5f8>;c_| >%`fcV޾}{!8X[_[4d+4Z[o-*Jiv;nڲFKL#6£/05 d'G5{G!p͛צJ+Zo^?h- `X܄ ~iin)C:qۨDig/d\yO߽{[ y3V+l iRxqϓWhטvE<1aƎa?=;g6 ޿w9/n[s {u҉.lo{v饥խkjl|@32۸AI9=r"qRcm6&0C|j|d"T }ǷHp*o^߻r+59Ƭ}}]F;~yyvzvaĜr:;m;gfNJkn |޼Ν[7on.y֮޽__Xۿسiݫk>eaxkyNx"ffXv'>QVp? pw{.>K_|kkLk)v/Ռ~o__yܮkfʁSp=:mSY> |z[\l=xD\wo]s9V+meĪ6v޽ymwgs}}uŋj5?ᘚ3:kۛʲcB 1n_:xpу;\GO޹IVoÜ6zw٪>v77VW|,'YgevuCiv4Hk{[wBn>y_q^χ#[{T2S !8]^L- 5 ޞ]7Tdq߿:z|ڵLC{s|"\.gڪA >9<7]?^\yb]vttɏuunR3GO=zt٪27{KKpf@ K_߹{Ÿz݋Mt﫣CIVc^3w~{>y#v*Ԇqκf얖jaJ篞#;׮\-j5--z_UR>_?G^ \5,~ ,#xbH"Wz铧OέW/noo>PKۉhomiR77թʋsb,GH ܿ84T*#!05Z~bji 0W(޼Gǿ޻qƕ[Y:8 o4"[i,L>zGq"B}tdB2 YmXƑKW ֟N>|/?{.\AD27\Ǝ8fftҌ ϟ>;z} k |o8 E{ 2 K/r\<۷>y/Hv҉1m3T޵0&Ekjoݻh{!^\?rA@-jR,ᲠUw|BP}s_1~~+k>1|E|D25{_l*7=19Dx\gmqPH,#”a\*|agݽs:_ |xn&ޫw?9^@.aёJ)try"< ȄܬX </H/ޡͫeV~ѡQ:eS0fꦁ-"MIJ.+$g$E+''%As2k~p޿FYcɡVC6,uٛO~oՍ+_$;󩟃H@YSRcxO?G z}$L}P[+|͛C@ImK  EӧN ʸT K-jk׍\9"؁O$J D{;?,/a B%)_]!/xE25GUT)9+ڻH3SstO)"=)\$iߣ]ei*M:!!'xqrenKt{goA ??/<|{,GequK&:U]n8l()@L( DD(d Wk) @yB$p>=,/dhDA/M;ٶhj%W|*ͱ$1Á`a BHtJSosqs ϸsCLUk s3mєê+-sӿ9[Z PL LΎTPeD=QIQ+5)ly xtbsn?=WWgeHHh3Ë@2 NM5{~L3>5z~;0=E ߤn`'ImYG.Ϊe1,\L$gSP؝. {_2]`meyl 4[Maޱn4&XEu pMD`?3:"\{qg/;Fb }Eę%7c?w<*bfD|"$6~vӡn|@9oԍ^sjډmc YVz.'k.~w Pv+xurrrPo#OaӉ7Uch4?y4CdW7B,I4]GeOC{!`g&&lF-*Xzfz 8d[ټBy|1J5e2ilZngl,=3xKLoC{u[F3>:L&MV۷w~ igV >n6`1->">cpxvR_K Ls3a ]cܚ+nTk;gfJO qGrlO.r-/pn;kfz78b['mMmCmssټ %* SҐ^[[l.ck4nR^m4Yo>weßvk̬{N' tCE"\$ң' OK r.d@HxЇic|h78\?}ڶ&;stnK'Xkb*i\q{Xbp=*/aW6H^nH;!Z]]Z--(NKݵ}=X"?wXՕS-lJ7%7݁-72|jjuifi/Ė ֆv (M&>ѵW~iL 0L$ |4juC+ EX@16n05{Թ浻~'W.j"2-}LfYPcxÇ%ig`߰'Cr['=+޼;O?'4$Ylٮa,|!;-$G.,olnV7si;fiN\ً/ן$'Wp\DJLoDF(cc%|_ljnmkcavvJ ;m x!; 6Z!dlXZpiK\GGꪆfuk]Yqaf =+]Jxv谯Lpfd4|~TW/,x~yq;/{?ǖ梢*bifF=y6-WU$P +^, S J:)Pccyg55??8< μԂʪJ12rU*UÛLcaU˻;!IeIeiV~A`sMo RBP OUّi> @_'ּsn/}'-:wigJKKIPةr> r6t +hz3vQ,L;h}?'w?=qR !9U ]. v1g퓓3C[X{gf^pxT z|~>D =Z |Ir8VOϣHYexc `}o,/at?m?=|1ݸ"X;HY^TN!kkj8$oxN,<\6n~HOmChbyTJaRqPKK?R-3P@001.npy{gW۶o}*9#*,EAE1" ED*IQsɪ{3=o^j{G%  _\%b҄oDijֈJyyy𝗓 0'TXYBpf3pss"=0K+j xq]m@ PPBaff$ferSRɹt 1!$J#L0^^;y6,o* ++qm}}C4ᛛĵ5š:H KxET.͢8i9iE%%UUM\ G;99 `ae-ko:2p].]nuOOY7AHԀe%''%&IV@" k 0P @)t6BM+\)?V֖92q ج6}f.'}68`0[M:Vۣwe]zcpha4[͚na Oc'0T3!)V"lhRw7*Š770|~fA`~nD( |;;; /ʹԬglZVӥRf+^YG+X Z[[_[`᰼/X\Zށ؀߷67WWWV4eeU}f=i o}}58_ׁ0DVavwvvwwv ãÃ]&zmx`owg?<< AuEP"ԑťeHe+k+er8YXߌo`w?R{]]JEgwB٩PȥB.W ɻ::{]=*eOoOOק^7&bZlqfCaϐcR!&0` D եP@A'Tt OZ۠D|~mmljKd4k // i*I2155#== P8> xFšPȉY=ݻ fgC!:;ꐷ # $ڝcc3er 2aKMeɉ\vjFFFZA-Gr' IISkz5*WQtʡ)auu*刃\ eB);;n}dNRNNNff~NN*?7׮h*㦖vU'd$$(Ęx2L#&I(829Io鴚>-> Gh)r$cM^f45*DMRի6#x|Ze'>Frvk&p,%1dyF NF ($#F446XZ>|dI<>RIQ%,eخ9 ?"O`,H_aΠUU^W!VylSP]PFj5FU*EHv55|>B&OC&"RI~ !2c&8( !yEl@+]'SRTTv@~H@H2/`h-2YޥNzad}vֈE"JsSXd T’\ svVz /)cPD[,@o2zV+$-Ĉ%&- FSwf*Dgybf )ͲBJ rJy ~xNTTrr,eB&tve{K{K@y*5882\Yx<J+~&cb(n+h(hIU*U{e 36LLIHH/f"h2TJ;Z{ͮ6C -Ba<.7)CNǠ,j Zhv蛚Z +JKSb4Z" fP#xdNM*komh3!UkG /WU%efd"+ɎKijL%kmeŊ!Ҝ?.`6 Y 쫀'Uv;dM E ުjTu f4G*ϭHΥb~ͨ5[࠶P4Vj & `XEWʿ( )ۺ 6L=GlHIAIlvn.`96*jɤmx0+I"@.HY-` - TӅR@ꐙWlo 4NKja%V~v 6)-6KOdФs$aVW$R S@5V Л] uJ f Gl @ܡj:y4Ar(տKmd3&kk&Q%8[XWV+:x,INN[  ijMG!!*>h7@OJY/_XX(<&v\LF"pɅuY7SxZvFF J!c# Jjo4j.Өnڇ,Ck1N"jɲ:qS`C'BcPTX\$3L&7S~: ?+e,m7j.,`EQG$rFlyE3b2aIj*-;9L0x5\̌B_5U6ح~~]1D\|\xBU Ob2'H_~헒8J+Z@Iou>c(f 2ˈ1.cD;+ql:q7o/ixZs#H$1t X!]pH) <)\[xy?7!%VQnqhcN=h$"f2pXAل s13Xlz "A&DRҁ<-Fuxx7*ԔF 7 y0-;#0q Bm6hR?L0QI/G!![0 njG1N'D|jazz2l Rd1HF0aġ-ظאBI::>ThԸ8"5HwtvC!bWvO?2t:{ /ҁisڬL*Π3cؘ_cʛqhapPM"bƠS`n̤GkD2`rOy&Gv;:Ʈ?p@# gf2.Cx<`J@#h`{f&Q8v{mQ7H#%'gmÎ{_Q݄u@@UkfT^vd{h`gg}1Yy[M$j R=|הN޽TJ54ͽ0ʪU0Bt7Vrn:ooIa*̦~ [-? F;:}tރ;ۑѻώ G" c;@)ƭ{zTiQ8MEIH0 hQbAQ'Y-mB0꙽w~;g@A$"nEAeJ6$AOqݰ>K;d~E:fIL$(i0K&TYC[ ~^c{p!'O?^>=!`}ev6Ť"WW1Ժa3v9!Ռʨ둵fKZ%zISs[dE@c "LzՃO<ɓO̓ݽHdQd$S[2vxu1Wz31CzZ .h;z`7 mGF@cPo1! ,=}z|||rWϏ⢾9\vwpR@8gQ|ЀɬӫZ25V`k[52!uY-?uO}󋓧 ߯$qӹuu>tښFFd8x&U-hj٭Ǩ]v``X=>qo^_\\{lll@TXȳM|xd{wo#!cN;A `2jmؕ }rNt#o/ޜ_|II]X֢y^_gSr:KzF84s A> lwBuHQH菎hD8:8՛o_|եl[n2ٻ`kgW2\M?:l`aEamHp6D`x UT9<ŋ޿zˇw[D¾fpn>؁H$TfFk^_^ [ކZih{l 6hMqŧϟ޼~3XZٌDD¿޾`gc..xפv]`0=.pG768 cF4}Ob߼{8ymn.coe ?[[l\krrf!(r`qx4"D憟#`!9Fl@ӷ?ywջw݈)ԁOnolCa[v^-k[1739Pi?07+R枀AVp\8y0=@ i׽w(޽{wvq{c-ҘO1=zrjdZ UWt{nRS3SnV3{"+sӓq \N^|gQ$lq}Źj8t;zt)hc[6}]OLMLSn(_=619ُ9,Nzo_|͛7η{z ޿;+ {{kJQգr< k㩇f] ANy KsF1 B# 'M@#0tԵ^y|wg}no{;>?9;yr`#a?1 4MPtelzv5tp;{Rh>LON@rONMCצPz{] Wûׯ='/l,{~N`C|M;Ւ' amF g}Sil_Eݝ] *ߍýӳs$݇N/ί^]a b/~^  SƓ{o@[,CsA̔g3=3.ww+;]E{{Ks}My3$7/?_< K{7o0xLOC`zn)LfW^@μwh:r1NxgVt ]A^R/𸍗C"~ţkw/O=8:8ډG‹Akh`l6t0j5mZեh_xd#)jO0_`}XiJxo`hp%3 Dt #0#GP{(&_]|q``6;9Ey; 4N,/ sh/Ϧ3^9W.˪טL~% *Gg0X6N5O~}yv[[kAton>WX^>z0ܿlqy/$ƩCj:!$`ꖕ(Oј(EY߾r~z`k?xOCLL<~ ]+kD"H zODCRK!Hd*3'ͤP N&o~7[H/އ] @'?tS> tA//^A_=+wJ$y8=D"m62`$f'$+ ش&W,͇BA 擓ӳӳ7^ ;U*qQa2Gx"Q9DNBbZYF(]?~˧(ϟKK#06FIx=˫sXiU9i8\ '1X$bWҳ9YY)#?wPԶWgТ-///..a&0f4ǐ^j߿6gcND _MM$gr8?OJLMLg$pҲ3 23d<~|Ӈwo/7_\ĎUfƜM2CHǍo/_~EX8550Co1D:=OथfgqYL͛>B߿VχQksr*YLVbJZj Wq o"|SUj2ɟZR%Sת+`ݼqF,@fSr s sw3#P|Fk !?50x Occ 0x &ѓyl9|<+55 Se5r 8c<s@C-ؠVRcB_WĻI('3%$%&'痖"x )*?JuΩidnwO!hI79*/)EU7  2$QtiRq1q7{ݛ psU&:C2 IɈ@rBF1qx`(j<1eybqks8s.V+:ۋ7x@HWPIFV,b2 ;1NCלbn ha*tMV((`dF.B_BC |R? N),VbB!1p*)N眄nr3 ΅B)4OcjjGsV=}C!CV >`!6H"V St92t7ԭ'&zα ueAU.K3 Oo>?ZKd U&GeJ! " 3 \1:zGhҁ{l=>1n(Dd25q{QwaTuoW&ѷI_= CCɱ D":l@  d04s!@3uq=B_?[xfX6f@G ZߏBm7%H4J" T:8D0z:O/*sh+k-ӕf7wt:2뛘x~: " &k<>$&NucʜyA$/?=j7d4w2[ F\cqʖn_76QqLNѩM<%5Kl:8H~B0YԹAFf{|nZ&ǔIBq{ww.|_׿};[x@a. ؛x"L#gCc%?:\ LLϢawڢ =alr@$ ,w){Z_o_OB؞|tx"rap.P;;e7;9=/o2;1>e҅kh:dݑ㏿a$JTN.LBXmhǤ_X^p9t@j | w%vQ`1o?=q:]HIaTU): wm}=[8"jKGF")عB 2E˨oQxx#{<@~ʉcSG||cl_,+kJ5}VǛ=x =x"7& ]&'e'&BA0UtHMN]0R٭f ̟ˏ?>r5B-"Vw5??[T<. @TNhT&5ΆdYDʬ=V~z =Uh7T^RK&ˏB NnQPXZHۆ<CP'14H5D`u_^Y^ St\}p2`1tWgN>|5H^Mq+77Y = SD5IE]n--GVְ<|R>hwN뻷>yvy/м|xD9NKfe++ʵ)Z}JyG>G BoŢ౎%ӁHduy9.,-.55=~Ͽ}ǯ?@= Z]- 9BaayV.CRFW :YJ] KQ؍Aa/( AxzG~߿8Өd-<^NNqmmmaNY^}z t^G"`SH܎Igr (@8 ˀ<;2?Y3VG?01i]sT(Tg!\^57毈x&+ t"I`ݙ<7=ǪN`fp)bu/P߿ M5CeHT ތܢF%v)& Se0qnf|B3B"d;xhOg_iEeqNH(ml""?=[٧fc5;$tPZi2fn9KKh(ð@q%g?}o?\fedvW" Fլ  FCI$ HfҸb'tE&pdPS[I\q<<;{T/^A].eºhM Ո xM1ϳSsiyc ĥzXA{>]_ C}ºftZ$)C2qѡl|:vvnt,TE J @}gy o}+&TV$H$ I!bb2lt4ݓ2Ocm\7,驱͓@çO}@(W<~au=(ATk -գ#ĐwB 8OCԏ*qǠӋjkʯlllnS E@@$*r^uHˠΣ{+6vE~ʏt8xL3cö'O^}ƴ _a._Q]XW/A7kjDz8;be,C?9c#4t9mS\z "#@~ReeUU--FQUMMMU~jR:7 ^ @b-E޽.V PCBCr[sv}(W0&~G;__7ǧzt \&&3)PKK?t/C9P@000.npy-W[[k.xmӻj sYD%@!(#I" 66W]U{?}ӿt!&y7CU 5?+*ش(^%Ea;J9O."UBx[!K+.B'<) '"ȠQUhofffS#dxm6>r9l.d87+F)D,"&vzq҃{Q9¨ɧ$xh4 Tȡf2jjkꚘfŬklnnr[ZZyVbf`de&h"KHU:wNz_~JjhoJ$Sɱddn{ ҚZjf7775Kp[y6ᱛ9M5Ey $+-=!>Bht )u(mZ]UJD%׵K8qhxll|b22=86IU c2Ml6'00uu윜dJQ#<437vyVӪbN s#V9QSUSmb56ԃ4ě YfFUmmEYqAvNzzrRBrZJzbRrBBIK д܆>wdaemc+[;[K{G@8^;¢ʪfVcSS#r8ںZdH}mMIQAQA^jRrb'ĥddg0E%JONDf6<}P8 g秂.].hoZx\V+y6agGwWX%sfvCScc]}^^NFBjB8ܱ bwvwvvwX__YD[A<?v@MYCVj!ˠd4BͦAt;3! A0111191:>>5 N͂G͹HdjzlRka&VK, ;:PB@H!uEbX'dJB.T~R=AkAo&hi#9=nf^76A#[UV\ZWX\XTX\RR_\XXTTXRRTR\TPPT<V%5pTVWkj" Es㇣6jivπKH'%4B/eTVUVWUU.(/.@ZVaa^V^AQaaA><x閝 ]?.(,//Jݢܼ*SvzRRZFJf(:/GǥdPt"Eks#<5640++aVTVWV,aVT.,-+,-*+)T_WWͨS +TNYQaΥk3@'`X%h,DqZ8hQP__Ј 02Ls!p9-ZMZskR76$}h&ţ1xT4*C"D2ZֶV)@Wͬ B0 FB8EXL.&x|(BK+[;&h(H$.9\RVSCy )Z[UOƣq8TR~FP-R])loA#(V"<8|@bCx6Z)P]IYYUy\S$ӓHD)MtD%%o|AP hkt.ST' d>E8_GǺMwZSFE_KOU'`Pd*/1X|JK,`tJ^IOoOOSڈ:;DBASyf5VUB,lwttjw*II܌:^_uzE~NravN7he54ZM O0qɴ4zZB|<.+d2io4vEbPK$6IbT0-K$Hz5:62#.E *WB]C: A.;.}l|N:BpܤBPerѡO#%pY,y| &0P ^:`pubWQΫ{x.6'QxJl,X](/WUJJPHe ТO"ӺyǷ_wwl>zqrvͷŪ&VkC8^yr*W'R 4 ]3 !J\*CJ mdՐyi̓߮/{RNfg5&aI9rKyq!$50;6M,%e)Ff@j4~C U">υocZ"~p “An{=8 '"v? L$q*Ks[cTt+E\v;:@4׵pKcIyiY4Z 2P@ȤrJw <M Ez.Uf xBZ:iG1*`` Y[gיT=A@\iBҟLHBG,~Hԡ fbC![N"i2%O91C3KiPQQQI^-@e'W($RuSe5!_%QiDF9 4<Keζن(DCGd'c5d)ְO(Z.“8Խ dU8EQkTA{~ÐRSu]]nJW#b1$F=)6"Q( 9>э{)RK$SH$:=-531\?]Q'2`1(,f_U3H=UaȠ PC&}(dgdш8:a ZxFf_9 F՚,zѢJNs[UzNi51hZBR5RÌUH8":eQk"(XJē8<-LNO)(ʈJ(t<1r|W8Qo6ꑕ!Ūt/~ǪpV;Qh^\OzEeDQx,ITG$ %Qr* (MvQgQL HW<6upHg 6uK05NPH?d7wfC͑ ؘ?=4u8v?i*d&IxZ||M$QHX DơDjB`q2&[gi|; Ab*;#;s#ãc-0dut %99E3 Pظ6mUޟ"ŧ'&$@x4: iq4(*V$([f2@Vi}r x.ժG]#k3?j]$sMf =K\yDMu}hL gf''R)<42lO*f E1bLJکp`j8m֡!FbٟZ LX|EfUŗGjb(幉h ײ Hi 蘘hEs!V*btzsF>*yo#-0? 9Z -1Fe#.W{E r 0JC.% +y\d|l4N<~:866fńIEFOAh廞2v[g/+˳RSS􌔌Z6[ IVd\ءFf݇;Ks++ +ݣg[6@1_K0)Hhk:k{\v7z>Jt;L4K$m|TV%0mT~du=|d{Gw#$& }de.\^/*F #4NyMqIyq(Ԣ(%.##_3gxm{`ѓ';wvGl¼Z2 O bs>-b!(@JQ{b,1? #3FA @xNo Frߠ:Bdɳ'?}zuzry̤!<^ٖ@6d\\xbm︵Gfx\PFͩ4xihzE3b0뚘lNkTaMFIo՛ Ϟ>zȫ/^>_|9=3;1H_Dpeea ^7FAɠm}vI| 7,feITϞ8zƇ7N^>=X[YXqtAzj\UۇgfsZ-ɠWennYz_LڣR!D_g0Z1|&h~_tLJϏO^\{᫳g7mlnG4n,1xxxpt|!/!Wdnyyb,02h4 @l6nY,?Kv_puuq m//F aHUsO}/.o,OZ:p YZCv04ЯTQPkdbǫn/n.޽998;;ۛYՠQQ2=>8zd!dۻs؈k)C9<Ղ\K (csNU!+_~zӵʼnP_2u/O?z<=>ݳT$ <PИ!C YoCs`2;l.rT4ѣKpqw?}wW; v*:`{ifu>46R`u-g"{a] T\C1vylېlDiN4kJ#`^ͯ>^}{s}ۓw{Om/ͱr鳪WGOwgW3&ejSw=6Q%ѺG.P)=p1 ؆&qd:hȺRI7Gw~xwoMG4уO!' +]52}WOiC>Nfv{G<~/043; ٬HA nW?B iWk˿Ϸ߽~}tí㋫k{s"[ܭ2 NU֑0_ N=D8y^ᰛMfHBrA]~d^q{_o?ypgqߞ?͝q@&z`@Z#6휡Ko`zy7;6=47;19>8 Z\^QXl-Y?>ݼts㣝)'w6?y<X-zR hN% L>ġ9&417f '.!{ׅ#^!/A.`0yoS+0o^ߞy}||g{+Nm,D&'g&GCN 0ƁE/2)|LJ/m-,M#Bv{ɤwO&E.߿~t{}G SO@yhçϞ|ӣ'+ ~A#ԗozq~th1;;==w]%nB!iεׯ~{ExyWgͻOO/^]\<9y~㏿gcNS ~ŹX8v{ܞ>O%utvuu:څ|>TW1뗛߾~%@ϟ]} #@o~o,OOV&/.>1yˣ=Z[ZF\X$hA}utD緵MUǯo^xp389|>GDꐺ33ᱠ;86G^9N_^>.-F'FA/0t#|Xcs8 9t{;0*gg"p(r%BX ',V#0=aOvN_<>>>=8ԧa'6۠AoM@ax,BQȤ^8;=9zy$P()e29rW)lg<ًǯϟ[//>~ ;>[&x@&2 ,Oi )tjp۷o/_|׹9pd~h@߻`OO__<7ןx{%alM9a+z*JqT @͇a^^?|Id bp#`63m###þmt7yUUL=utQ)lT 8<@HqtB珷 ޿y}c͍@]d 7LchH`((?v9 j؛sd-ÇwmЇ|VA˷Wj# nbpPk//O#&zfaIQaAI^qeE%D"/J&vm}߾|0|(IȮNǬSzC WWwjyGe:UX’ΑbېGĠjRV^nvafV"s/U.FWn/ 桉qdWipqUX*ˋo.!>^0KOBq(CL KkJZ:U_M/-4NyFrrg uHmNuU~7p`w8tҸXtԽ矯^z}㝧[BGcd2OH-/ɦ0Y - pGgWfƆ=u G>(V̼3PU {=5܏'7|H`%)iqk3GCHXmvA%sO@}x514]? j IYit"#bXzsgL!Si8= _,7a^xߘW.leV4"=@84:y]N+@Ȍ:W@1ˡٳˌX"B萟p<I  rcc^Pe/A|MmM8ZجƉ` qiڽ=7Ƕ}ڞ(mbjj<M'ӨTL ע@g( ml|bo1]n`:o9=Ξʼj&օAG@RI߿|xݫgK;9sG‰82Ƣ2F ('< <<:l }Ah8]vhkY-"!%`h m6:vOo!=|<(qTB$ 9e3CC] Qca_.D GߐR\G.|`LY/,B^폏~t?1 D'`@%bи"n7k)t%dHfdpVf*`+b=Ԛ@Lɯhlɿ~>wz<>db|n? GPhG@cDZ>4 tC,&&'|҄ 0V,V3>^ծ8V!72O18"؍F d.ӥZ!"{*c׾K` L]͏-fà5PRꖩo?^slNz 3qȔ Oh%`QJ 3.NgE"c= md8GC!`Q3LvWY(-;hp2gڝb'h+E>FmR)x"6 p%t@edACB2a/rW >ZZc0{FL+c~Hmu_zw4@cPx*9$O"X,'VwmY?>ߞr;M~uqyN%r'RѧꆠZ#i bQvQ:G"\dj~kxddI 2Ƚv0Ftn@\7ta3YgW/=MH&1^Lj_3 MNNL I煙3 fhgwz'7+Fg-tw_NBް<:!!Q$bX,ONW{|^udzjGTC:b~px0b:q$V٠ F{oW?^[T*5H2@O?4`4А" @cKK s#vԸnۃ  8RqFZiH5o?zQŨz~>6& +B5cxb~~aaqa> LLBC7}]7 FdKWTxv˷~߾ijM@$2L S1x2@ zy5 s807YvdtXfRQdk˃w}oFϮdەˤ2)xC6{B) &Ix/t ٹphvI@]G=jן ߗ/_~JxH+Oȯ4d}J\*eͱcPhdb42HC3|./855=?7;=?AF&Ǒ r;K{O^?߿޾{㐦[JKcW2@4XOYЉNCŐ1j<%{ 0ATcm3 t/΀_HczգYo[QP\U,j.*++2H_ˈAapȦ1 8Lb'uy'&NrOVȝb>h<Y#xh?}|(7'v^Ϊj(,c j LѯPбX4F'cቩHlE@O {02e!魃四;6_>}{{xNQY`443b[_]) RjTT=HN!E%tyWщȿ}07=.\GYŃӳ7׷w`o"Oj,V# AMM)*}2@"QKM aw|/72>&:h47=50ۻŌt[eMB_-Wh$chhlxDDNL H$va+G֦NN_\ӗ`/w^V728.,_TSvU*n.J%P(2 INxFp0|JdA >69O|}tS¨m "on/hv5f*UJ"i]~~C/hb-<.QMDz\BfDOBH`h,LkDXd2h0B0# zۭz[$P|tWTVY]SuMչJzCT*FuS~,r|7N"]l-&0ջwW?>9ѩEUUeuVn;Y_H&3SHĤ*PKK?GfP@007.npyW}mߵMĎ d6bb!EX*V^$NtNΙi9ә̤I3':Tg"nxm'UUU%̰l&Ik5:G>(Q6KKKmVm24~L0U"@|iyx2ěhX`XqgooxƏ`B _( K`I_8W〪5U6!?Y*MmT_[%%Okkuκ0PQbdfb"A^q__fԗ]r|l^?Y.|hovwu榖vv\t ̻~3TA,4=Os |ͮ6 Zভjs5 0s ᡡOWOowΖ&k;:[{:ݽ$<=d..-1jMb0ƞ1c A{C( &@GktBh6z^k4j (72sDA,ﰪjxJNhZ^x:@Vj+Q_QpLӎ^ ͆x<)I3* ]^yj x @B$`|l@`l I٬|yyVݪ* ?R(HsD`<0B`p:yഢh[-v{d2$ـpx& OM'B"  pgC[uF KB "ld~G&&aAwW|U(@+`6ó] B<b y!~aQC/+Oxb1|htI0ONr<_6`yi)J%SɼR kس,!|k( %y*P,ySAހ `~|^< ~Cc0rǜ0JP&6Ϳ$@Q(/@q?LãϘgf"·@x4P@Y -UGjY^***|.Qd0al40|A: ˓!WWI@2I#hD0|ZFGLዊ_]Ax8L$P4* y6:AeٙaEQQHK5C*Z6.i%<p<̮Y^DG8a*/_dϧӛ4wKxfpoHpOD\\BR20! y*@ee9>dx7XeU8` `SKKD|/0 y] @|{k9<9^!Tp655uut=0 V;]&2ZxI<_fpYcQ@D7[[\Mm=]}yD_YZYAR !,ǂ@_{?(%E xtzS)䒉GO? ?5Xb!0 oU:ʳJ(r~* hdy3@ULp4nh`t7:,l66Vy_}% !n EP$Hd*5 [Q+q@*բ|z} _GKhy++MQ@6BsVNC榀T濥~ I>q ~_Y^B[T⿥㟣ۉp hh, C@x=`ۛ[R~70?+xrrsÔ(-)d|W^n.JZYC1K:WۆOSR*<9#A^QŘ+`>Mp晀>}rOTEDŽ?C@zw =ȴ}Wǥf 1tewӻmߊ>=k1O撍N$qZ>ߨ?>?;d]@C??|o5=JD@!=^taӳb~6( `wo^ݼby@Oշ9ǣ{^_f2G{$槦_q5ͣ@/q6ws}~q~9:`  eyM\ _|\]~p䢈QkZ¿{;p F)7/_n'G?M$b$ƼA1w^ u 7o^z9=; #E!?mo1'qǃ4UͫW/^岗ggHdnfaex*C!$)QK׾ff(~7q9ex.!.=v:x>:\&B቉`zZR x6;@eZ:DžgnooZ & 깄r *=vt"pr|suu)Kg//s<L_\]f`0|J ;\\K0t$[<gxӈ_pxt, < @<ҀnW<'''4Q[WW34Mx8&^cFop3:"Y[W[Um,#)/ / Q% <A@- (jUu:l^ )|8N7 P5jRUtj-(@D< / |<*Ke =[ n̋4GKӁw,?'QlwEIqIK~6@ 4j]oB | Z1$@̟]vYT~?|4.PwWW?.#M-%p1tpJC>ky^TćKs3A#,466.'??)$@8x_ZRX`y6vgڝ?9> ]n.U j]Bc'|a!A>E8 CjbJ#` x:yL xV 7j ́Cg<@x___yEUޤuw< wcZK( 0 fatycy Q_]8f`ϾmlF'UG NMпTpЙ4mln¿<99>>6f?Ỵ!+L\?HbKc_P?9@Sa@f7Q 4ժ' 'yj^zNon^_]\LF& O''檁oZV7˪3k &l@s}|шyGod3l$1LM"<+![ɈD/^3|'&Gq'f|xʿ )y-6%9<\[O_>156q?8j7-U8B||n28#](n?Ѩw 0<./<e8~~`Q$gxF m!0O{m'y׳>0_\GOҋ9hq%/poggu'I@O?zqٓӓKpgsg_~]R&$ Njv`w@Ѻ`o/ @|GYeM-SOG3O~{\0\55l@wL1/n7߿_=0&Kg}̛uh? ŭ w;,/ h낀Q⛚t‪[B>wAtCxA@[S|.n6|]o~Zu-8\6{v\K |g'p058@sr<,L $!ݰAbgP<ف_yN':99o.Yj`7,Or s\7o}̿>߯h "(az{3(}~_|5k@;{pC!On)g,×UBms<Xgo9f}?~͓6 _\lPKK?ޞP@006.npy_ B-qـ1A8$@@ sJmCl1~5646yuS~cf 'Ob33όisg/bLD EJB4`UFCP==5>4/ J`*dtm͹[ZZh6n:jGy9ddeY,j* EݻwaS߷df'uuM-'O 0tJE,#=~>p:PhtoDì|aQkjoήngI|`1 IVG1y;̣< Y//xYYyeyvWT O(@x M朜Eeť₲,-c8&!W#74ـjK=ckW2W-gg3n-l@2_*d>%|r&eJbeh?&~O>9d8&|~or;6| cA oOiL@$ pTt,p8kY^]G`jk6} fdO@eE8'/jo84477f|\ihJ[EUeYe9̰6[YFyYi J #o1'Otζ憦<&͎X466:Z*lnmlonjͫ u/(DVwWGzWlcjq𨦭E`̗b**QkUZ^qO(@Ot?߬+U* 8-ZZK`8>qv Eex JBDhd5p2zpDra>,5o 49 1dzz OCR0|P$'rn1|ʲZsf$޾gO/sKYYυ[fYc+*Z&#"    \A)< hi)͂QVd zHcϨ32vG=#CCCPf3 Y 997>_~{=2<$ hG' H@lx<  ML>;9Q;>'>e[H\8md* &@(HJBWW-)*M 4^FT$p0;h>"c"Dj4(drbx</\@'Z=;5q@gLT˓<.@E>2Fza䯷Y B( /PWdr @|]N>_Х!^h4&ҼTWdTw^NI@gJ$胉o _0)& L R)֔bi1!@g㉳kpPP' @{(@8>b.kpAiǓI^{hz}N2CfB !ᰈy% O <|b2Ȉqp q0IO445.O Ə`o~xl3aO=LtZ 8u `18 xOPr.ãħ 0t:e%Y,F`q1~4E!RD:|Mx/ P ԟ!aB+ gҤpP{A``_X Iq@#ii8_FZ-/Fs/moxl] W:^/gs?}c8`^g;9AaVG^OwSEN"\.z9h]{J.rF̧ <$V88 V?295U {SCkW'`y|4S(OE&( ?8Z01ZSi6q_QX yF.&s!@cvLF"Q3NE|.@ B$ hi){h]kg&:,+ pzs# s|`4|lfc2<)Yf sKj"0%KO08 I ݱ*vj&,_\RZcQc/,,,-=qӑ`o ?7pB&p<% 9lvF's/.-္Y!777_|pA(Z!@a5 cN!l''Y]_Z^^鈏3x%PZT`x!O7ӓ sOĂOGkݷ3 ֖b>Lp2WOx} B2H<,<l2GLldd ?1ᙜ_ZB2`p/ߋ??h dFL&$''#X⢈O0T$x>wp C5L@&Ljbis~ssy %_ [tFKė~`Dn%F/iib4b[뛫+ϯpp$w|SaG?gGB@3xg\][|ʚ^/bxϹׯ/N>. x<-`Ãյ;q8;>9\O,_#yxo{k{ۡP <uHKGouLw "~- UbdxKV.9jZ8ˋggۛKsGL@qSʿ~N@x(y||˗z셭ŧpޚ ‶6_]{'\ mEB3 ;MO?:888:8\YI,/̊D<w.< @|(@! f?q|" 94sIxV^o4x˙k& |?*nt.Ia+Ъz /fOhiͭWxHZrd[mUI<_S^Ѓ?ptP@ZPi0Ѩ  q|. `zz5h!rJJFnBMn3OL(@7_)|䡀 >c^yj_ Ӄ,IssI|@|d4ի S^ɥο["`w713x?+3>ԍg|gT*Re Ȳ1eMgh%~GF"Y5Fn8kK8@\PaA.ov1nAU僻0?:'up^vz\b^|  ~0]}}}_`V2?#v?B;;.R\Z-p<FMMKMi았Xcmgg|b-7խ]>%]MⓀg~%Ǔ&}a'l8,( M?)@%A[T\)|m]&@ē"o<HyI˳F69=7.I@DBo\JD"j{H( 9$ƽ\y*·"~kb5jSkHePa8\tl΍#Y=И ߊy40"$x=$&Ѩ2{="`s pj,·1l;N/zϯ\ C$CJ; %<@yLT)vtf㣏tjߏxJ4@/hc>;\># `fzJJӀ/b]_dٵ=,𡡶'~B@e೨2TQ<ș5< KKN NBKg?~?|ǟRL=ƃq@F]CUqx+j~cmeq~ۿF  #p54#+Iyا΄_]K÷"4 :\= |[雅53N[8 xvopRkwK ٍ >ϴ* OD̯.^`?&3zcgpG͕x (Q૪ʷhA< {ig6u1t̋ߖ8ax!0)}Gy  )# |a'r*q1|?eS[+E|[uig8?k>jC ϷZ,mzL*9pwK "$<+$y{ퟀ c >Aa>-$''ǥ9fŗ_o?{!?٥|~fA>-PKK?YeP@005.npyCg%DGaH *z6Nl$gf[u~ܓD ig񑥭_~SM{/)jfT3z|Nߍo f3JAgIףq鯯466h [Z+++MHOM5 FTe 뢫W^IqMȻaHIk/kmXBgdFbx*$I dCe|MMm `x[[B VRy- %܌ |Uu$mfk |FᳳIAKW777<uB{; u;;;o$iYYg[X<7͕憚 [6hrt]]v[ښ %yŕՍNkMiKX, m{[, ېlor8zz0,򲢬2lf`q}L@>%88l}[қ lƽn&dKK|f[/QKe2 8L 8~B5 ˛[tBb@),o^*Hȋ1@IxxTr#!N<<m\IA@y17'CL} <w:gBy.@LB32 ^I"& wpػ:;:)l65Q7:5!w" lv8&Z)vX 2'¨ZFDD<` =vpw8{[I3z=0^ ,3dreP^Рg@Go0/ zӁФ\,>Ȉ;:22?8Y[mW0)pkN x dE! Bc`x^ߋCC -m*^f'𰙊T:|NZ|!@B`(h/CPi^h. P((#`'< `yv!VD Ȇ %W /ONـPB@C'aZ#u$ ' 6dU^?_|g # ^9.Hsr2% Īɟ @ 4[Gg"`lRxFP<ύGFxHE tt;<lR 2hpt>\!~,I޾^wit`BL_We< 0)؀3X <#t:N{˅.-ΰk x9L%xqoGrLqa^0<~Twr<4 { {q@>.@3_ddOqÏqx\-[8r+nX+|^,> y7 0|ÕNx3 L2P>>_bcl? #s$Po'OYYY$^&LӀ Aـ^xD>^, J.LzXW r+rI2y4:#?'"x;zG2)H$<^"< P*\^v\E}o @1<>cc\@Tpi WRR*r\ob$'>XwDXpCl (S%0[%tm yL _Oq(Y.QU^ y1My&NOۉF>j c~'&W9TK>>?|?xvwˋ\@_(3 8_pU$! *Q^AK1_^ރ-.@D8_ ,KYq \N'# X37x޿woo :kWULl4@i4'ƂwWրZ^/;233 +z2J>ŘE4d`@#Dx ~7 c&2v>? |9CsyI.yfe]]sC]I8('< w? t4ʪ7M7+mmlCg`B]7 a R޽#H0h*:kkJq8z=6u:7@(1!(3+/^G|&a~#B p9װ4\U9 | XONO^ F9 @ 8!fZ`cS l֬LQOt:T ӥ'0Iϸު< ]1UVrLNM<.]XTnTs{Gxfvvv~ydzr l *Ϯ,F*K;-.@ AD"3gobOH Qo`X~(x~ON@̲> {?[O^@B ZX>!ypI19?<0a矽} xb!_A a4Z}' w;>$26 8 8?|C+$[d!o Fـ9D><-_X.FgxȻBo/|G.P]]Lxwp?iK+<++񻁇vDG%,2b1& E-[GwfY3s %?<+&.Ql Gf4@>2 G<y #x iuȳGd|ĭ_Z][X]_^ZX\Xg_!_O03"ΛLQ) G)[+K@!t< ϦdO|pvijjw8LLwwB@?`>|+@x~_xz*.g  8y#;8=y1ȿ"p8(ó;cG{;,# $=4< O?gO8v;/gw>:lnl~Vm@0 rno2y#s&0%oL[؀Ç܎lnm#3ooo1o'C#i&ի>~~~ٝn-uE<#g^dz!+N X,pR^| ށ jvww,Vi˗< |؍z o1j*ɘv_|GO=9xvrzp?v435t==N ƺ5ɛ7\ӧ\!/pOB@5'Ϟ?E=<<<84?` 8 ~L@MZFf<-9wy<|ɳ_>wNUXkx0XV?/޲~HxMvK tq'yˏ>~6ח`VX )lO7N/y. oT$J@@2K @.Xڪ=s~Obl!kѰdTh B!1O޽:^³$@.1rssҌ]f3 0F1RQچs[eLΝo7^) .mnE\ :TY`ey~}Km:&RiV<\PDW2Ǔ?=XmD~e z~VL/Dzfs /nZx04 'ڲX =/x8,/ϩ6,zz`Y[cC,C^ې݀~uyE% /yWε Eff2vcbvwv"4' ]ax*D^{M&xN<5qpւ%,WI% oUWL+ ON/M/.̬7ֽ]~ X"|$21ZL) P1( ʧVLLcvK(4qc@qm3 v x&x9AJjFK{<001><2}O_`&\y(&;ɕ]@g)PxG}]c,@ d9U:Z] zrjqs<NfXG"A yGQ'u*Z:gvHy7cǛ*It;~aa._&k2o99ń< ؃{y8lm¯]Ho31"B@ulmwb?@y6^_\.O򍌺*-.aƌR,/KS|xQ867V`?LVΎGG] VA%%PY|^|?w]I+()!~^@W]!/ ’Xȟx7G:|#&S14U+)V9qxucmy!7 L h. s$5W)[':㝝>??~Ā:hGM.41fQ^O1J}vlk_%_'׮[/ #@x eK O<P^,`4~tt,䏶02x"_祲 `:^ y&{8-p?{slިEyApg^x&orUn6 V K~{m?s}[?y< 7 F(.@vUs&!w֖z!ߗh͵ |nf~6 V0&@sΑ;vMS J&ߐWZƓY<8]^ ;fY&ef,|ext:nFCZ:`tuu'7:[Z׫VV^\$/'GPHR(ϟ?O(VdDZhZ]Sk+i$@*ؑHIMKI뛯( 5| ; WbXddlfuq~6 Aٕp&_\LyȔC_xΦ<p&_ȴuttuh_^( aVV*2o m[KWյ Z7k]h;:;otw@CoT_UU+ssd+e%+juk92! T`!k08d0 }Fa`d1v8uFO;l~k^]]]U^XZXp)O!\vu4vwuzoq"Wy4&)[]fh4 LF -fn؇Gry=Q=>5b7,Fq`❜ NMD5׫U%yWPB(oxdaZa6l6~ffjjzz:|05OLLi-&FMqt@$?JP(Om4X}~X>)? `$j5y8gp2_dc18WP/F‘h4 ?t؇mvf6 y4d0NV~w:[BW\mC5uMuN]ZSV֪kjUkUR_vZ#|zMLtG \+x]ӢmT[GU3KEp-on;FjUԩVW_VժժR[SUSZS]Y]UUYyWw+Uz߭mZj+/Օ*iBTd\kRWS+>z=Uۨ]5kmh`&த54Ԛk[F۠RKUWWW[[{ 䋊JJJ*/U S$pK299R4==wNvtAM+οZqFZZ #mpOn>cG<p%(#Ed%_$H01,SԄNV\;<) ~꬀8gHx|>"SD8~r.O 302|Ix^FGx AD2\*n<lOVUU\/^6>#C$b1~=I@/ gBt,S>2ge bGˉOz`=HӒ /t99χ,P&<O? 0}C_^o0AG_o)t n?^ *r`ӑ%̒˲rs%R|!.pIl~7! rL||6@ Y##6;\mp8F!1 R#>昗 ?v&@ ? ɝ.9cxl{CBᛵva]A  Hŗ"WxN.~b@f$;̦* `x \0D $lsB4C^sf3(}``T~JHcA,"PHy Ǚnȇ =<zmSgwg"/J$$X2µ K0^  H0 %# 9/PrKKEEB:R?>6vV|B@r*CjH@y9 1|~jxwïVۏK#ʅBop T1? ~o K+<R)nɥ?K3>P: \p?t< <ދagA 0A;B*0.`!Q<@L$~b p;7C2t\<˟T&Ћ i0y x`2 qx.g_sOp"gB 3\ I|XA <^n.y9WiX`Lш80 OO&`*7I HIX>C ^ HK #ۏ?Sq&<& Ădϓtr%?D$!y?aw 0a׳\od'iiKx ,OFp `v > <,ii_p>5] zqT ^*E~0  ݻ$gQ = 8{`er3e2.LC!GD]Q8|ȯG ` = .|Xِ_"32,JȤ\b} u~$`wwcύ=|vx@dY]*B YC@UjigP%Vw76>؃f VF L Ee%$? p x .|D1o.bRϵ8\ӡx?q3RryEIyQ8 B'^goH΋c6`gL9η8B^63th*4W^wvvcwޗ0L7 xh8PihF+KsQJM'PC#.X䏍OC33~8“w%L,#oo 'L-om/υp`J~y6`Oi@,ua0P+͔w3|r y障G138?3`BᣇXdFU(+|b0uÖm-gá8?2>?|tX&fxh4C6wݰop NlE`a `z gYi&f,F-άJ'6ӟP?x%G=aL>իHkb4Kɀ\XHC:Á |d.BV~y=E!{736`K =0d`$B9+3\G O? < `4#|6^!(>fXa4q< - < 3|Y'1Oܻ) ؍**T &MaG# Ks8!ys?qlv =؍U55v2Sc&$M 뫫+Kslxf ϳ<}=2bx6Ǐ!j]4`*8rA}͍\t.<'aɼm 1<7n`~);a+l9 bwvcۛkpX^\aP{o觟={{[?{9 wOzFǀ \<;M^+@\][]]#g KyY\=~vD=zWo>al xl=zpoܫg_O!} ˇ؀ݽ/:wX>Gӓ@gϟ>|x`έ;[hey^;76X6c@o Fzphـ.ʿzᴹfl{ckyey5ln'{:uWc< <`E|^z/£GoWVWV FjvXm6lm,o_}$i\@V[ K ʿ/>~ݽ[j7׭F=~e6[١U)?q<p<w[n~yg< ɻ|; ܽsgRtj"k`ϨŭA0 m-ۣo(rxd(-KY^y%峇|[ˋ0 G¡q#H ɻoHz#/Upw\W'+ǻo?omm^_@`~7olp\]R{RpY9tKOcO %rIdYKUUiZnH$$C]M"J c7o^|g GnS4@'R_cx!D"R/b[CP$ᄃO2a|Q,JOxhǀπ3A  O(I@˓oxɻ>0 ҂$?OX/6m̿Ƕ6"?9 xt'R/\L'x+ʂlAj?IXl~kcu5\s(Gp6`L;'SSRRԔԔ HE**(e_ѶwTۦn @nI ~U0S$ -:T H\Qw4fIeVp&\htf5UU=:OݦdNOFg斀dyPM0|\88P[Lxjww" @^X"Æn-& ǀ:׶"Ex8  ݺn'^"Ĺ0+˫k+kko1Xz'M5yGG?[Z2.ù^V✆E8 5'a}|6!  jOOMD~n}z)UvNNzfymm˜;~2Ю,ax^t7`A~a=,//wqg{rva66slI.Bހ*sO4S/0X,WI:E&5t8$3x@(Hxq20/Ǜ<>6fl#~ E?2r47p)`+dO138.9 p [a'|>1@,NOXMfx~%:htS~c#Ϋj1t:-&gfJ҂EnډwxW}>K 0]F?:lɫ/ï=7ǠSc@MExpCΞ$6ӰK׶yߜ#{g%:Mn>~ջ~?cr?ఘ啖]B\pX #W<+Jۻs'Fv L}>t9l컮RUpqL&CL](Tv 6ַ8~uianf2| '{ چꊫl@/.h[f_۽u듀ݵ-_G~fwr<uk4--7:ZSp|sQ^""ǐ?F_%46⭝幀<}0P"VOCxob _rre1fqJeG82?L۷;S]䗣|=MMMP1.Ҍax.k/Dyـ|ǩB#EFfYד# ktg_|b흄³om,A3N~U¬jF` &| 6s'9ڂ[7'Cbd !a> q|<]S~suV,ӡώͥ[2+|Y&N:WX~ <@yk bh7c/@R%<wۻd0s Q~ss?c/\YJ+PKK?/P@009.npyS#G~ۼKr1 a4zF'!  Yx~~^zU[]+W\ĩsK⺲W.Y^fzZCt/7b=]Ȼ$Z/_/Wb~2~>_WǗS__ړxw=b/~mE¡uuu5UUU>pCaXL<()Q*y<>SFc}?J@ `xz<֎pםx/ N}|u5/{SHMuOj=(Y]'|__OxѮ.ЌjjT (W;>_f #P8 ) [an+<\qx5 XWy.$ox؁ίjy)<[įR+'l@: ߥLoԀO7kErrɠ֧d[J*<)zccX<Xmm u-QxpVT+֡vKP> |~ey0 Z;;j"XoGNaY'_]_['CɇqcOnjPk;+<\$V ,r_ lj/y>I`^ytj[,Wg__~XO# G&XW\Xg[xOފ 7;[x#(M yC=XE"I^Z& ^X. rJ2ڴ|vffbaq9{{:\@>K4zs,lllo< g޿ -A=/W6vv??t :ć# ~iiW} |" oO~oxpY|>ܦ {:OLy~?ܜW>FBNB~C_^=7$#9 <KKo!SYՀz!X`ӯ'6_D7W!!<v~r|pxpO\^0,Mjá axZ|4о8'40 lhll|Ry6nQ zB9>jƆYrT{x[quƀLP@96"nU]n7 >{A,KvdG;[V'Ԏ~(<Q2*V{Y~hGΧ4 HDTTV^f4>&S]`R;q󨪲HD zMLh0[> :_ üpk XKvۭֈ ZQ&׳xw~w<GP2<=h{K?$/ޜ(xޤ >5x§% 0Z|fM J,[l(@ᷨWЗ:;c_\9MZ@1ȲrY]խͭ-6@ـ`09򏏕PLJ@ CW-bh䶩.ⵀ x$^ @v*Zɣx f3q©m]8 `y.@=Rw6?N3vO|kؼ-3:>;)Y>| Or)uxszqvV<`sa秦W55{?{Yv)Ǒ׭x(OM55)by :./ ~qrf8@!*X8 |_0d2J<xCz rOO76/4p/N> 8`a V  h|n敀YR 68u-̟h^sF4$r xyo.M? ?py) G>e`C`_|0Hx|eSmr.E߁X9 C)xj|_WP +Kr>7Q.¿?-j<)ϖ./>Q,o~?~_(zЏ/X>0qtg 1O$Ty$`8^ы ~_OpX H/qG&t@?#H@ΌPYgxD<ox hp5xՏSy5@3Ey: $7"5Ɛ@1O\G<(S \W4 {q^ xw 'b< "/܇Ey&;?.|$=o?~? !@Ox=@zp_ _~  oOʿO~0-hPKK?>޻P@008.npySi~ۼK 0 @dqHF8$0722lMd=;d*SS5[ɦ&d~[qYϷ5p~Mdr咽hFTfiei",M&#K$|{yfb1 t=r6n׷>ޘ}iOO0 g:}mkk].W5zpvbLf{ҒreFUUUx[/  v*0FC_SS7o 8``@@q8VU0lYi:a0%P|$|C਄GYYIx0Ix& ƆJ_WwC`TPygBkpqϳXG$@mBsi|$/(PkpYp8ۇ) h»:]>_Sӧo6kA,a_( |x|?x}^xy;|ގ֎6}[Ǣ|p  5 zz6x}O!(TnS6`GNu|lttDѡ LC!7<Ah|7 a,&1  ?V6u `xh27LYL& s~D{ BxpFhDXĸqW~X[ ˅x<i@ HPcc#"/h< hҋtm3ZX^GǁFF##^ p8̘mƼmfh0aN Px9 &X"<( J6Љ4OɩdɗSI0XTY+acw:X^ XXHLfT![C@=jCȣA` Hg2 }@@wF!fCˏtfq ̋ͧzoOrԼ_3`ey FvptM#/&rRNW(`uee S||8Vt(`u5W8@ďS7O 5Q̃+3< B/i'1XGG“HQ' sJVx\+" Jj%5Y@˗/^ QOA^L k @O*Dy㣑s6z}YːoWT>bx<1$`l-^ 56 Ux# Jzn4"o5C'2OmHr4O^ 0O|XJ`J,0}Hp \OemeE HO͠d %eQ^0F#;[i*`vzW{< Q'ȼd ` 0_//03TH<* [2\͋1@ח[%eJ`w/]6^PY6Q@F3J`8ǨwqCWu6VСR3.i-*@N5:`vy};Zج+þ*.J ߣfxxLx:7I'ziB"?on_3hyExחLF1)Tc&Zt&/Gzyy/J|p@ [:Za߆z/g : =xPKmK$^ X+UQSS#旖E,R< 8>寅Y %O{{{gOOIU3jtfȯ93pp{lS vξP`p \n,+-n =t/9~d<1C!>R͕ť\b¼"/?y/<$I8 Z'8xtMցglz!6[5x%Mj[cKg=G&_0O_ 8Lvt4]SW54xw E'smmomnlZ[_,{.`;JM[{Ptt,>6XU︀tnͪ+mX |2z.eskx%C<lQ>̲<N5Lө lbkk /|.dy6f)o(Jg_\Lg6667l(,+E~~Tx_J s+[s¯,-p< />GhT !r;;;ۛ[j~wOWVI')lV]/5!`{KQJ6=$O?Y -Lj~{gKQRv![xa|8_އ{>M~WAcCSB&Xv@{,NM~ƧojN*|<pY~~~B-zݹGx%PLp@M{{ww|P,(_>x+dݝ:TŇBmq}uv~vvt*>{8 A$bh\_zEOQoR}DPE(!'p]dhQJ"Zey'G?TjGB5 xO|" h4, 8==9=;HLR3S ?24Q\':j^x%31'z5D<@x6tII/6&㉗Ąz moT<@xۭoϓ_-$vzfz hr̻[ 6R0W~;ay*@,2 oɿ<9__W̓;o+uU<<7/ѿ*onF'VN owGl_ ^;?1o4577?n'%ba_d< 6/ |ssy64$-75N|{,O|>zui~.M(\ &3fV'}6ćC7^fьKt ;P5@fj|:@̛rCC8|/v7Gr3 0S4o!uMO{몫_-$@WLF]6]Aث"yXIm/ `3fl5 (t'=-6ָdx,>?ixAo[D^x8Mڽ{( O(l~cj2>666Omkk -5/%AЛP_o uyBk, (י"<fӗѕ| 'O,||^ Ey39< _~WCCaчk2_8@3s?77-s2wwe|H_Axf`-\H󙗣c91"8 /77R欪  uR|zyŀY~l2(w HǷ8橀bϽDbPZ2lBpq %:tȻkŀy06W(U-iQ?h+_]-ݴ!㓓ctAB#@a?go4$> z2[֛_㷿?׏h< Ǜ'Óӷ 7??G̷?Q敀g̍^J $ݍ}Ā=r?CǑlxQQ ?߫:{pptȇ~C x Kԧ(߫:;C00 X\no jT@~ղRDP|~r@9^PLy1^ xRW<|Q“$! {6U0} ߿w[o2y)@䯯a@?i?C??d<`(_Ao$ԩx?nb<չȟ~O_EyWH?G(sWW0lV?*7]PKK?$P@003.npyPKK?sAP@$010.npyPKK?)+P@5002.npyPKK?R-3P@O`001.npyPKK?t/C9P@000.npyPKK?GfP@007.npyPKK?ޞP@006.npyPKK?YeP@005.npyPKK?aP@ 004.npyPKK?/P@7009.npyPKK?>޻P@I008.npyPK G]scikit-image-0.9.3/skimage/data/diamond-tophat-matlab-output.npz000066400000000000000000003234571223313777300247050ustar00rootroot00000000000000PKK?9$P@003.npy{וpC^&' `0D$2HIPTDDJDrݵU. _/; AqrI̛~}=|'~_~ųůZ\._|x /?_ß?w׆6zed4Mð Iڣ-pmZ0 f/nq۶me GI\c%Å4SOO޺~L\Zl᳍fxt3>3yaޞ$ IܰLfBX&7mV\>ǧlX+W'$FMÔ+Eq,öEa׶1f)n`:8m&rSlxܹ|y{R)xHôR1.X-Ŏ%_fi;;-ߺӟ}_/{_<ܙ?K誤0!9 ۲!2CϞ4|6aLRٷ蜺W꛿ۯ/'>uCDbx=2"\勏^}~><~>~iesY9ڿ}xWfkKكG|,YF S-UU ^Ǡs]VEMS(+nڝn0anUx\&^Uu:ea4r2AGkh<8-*1u LjU*|= ` sdLb봪 sÿAS đ5;{xn2??:)t.M8G`4˒bo}❄ŮtRk6fDȕcsJ|Wf8xy:.,6p|3sl뷀>-\e ?qlX}mf$`]˓Յ2lhoA%3c r.Zh Gn# ?p0"]R(|L. vWs7N[6j՚ 4H])n*ۚajqzY5h 6 01GfzO[Nc) [<2wdZxy;ۮT,!W\"Dٞ .-f!\)(%jhG'6预sVFEXEɥ `y }lLf{;Ӳߍ&;hZILY_c^)E~zL$S;f|]TdsZ^qC+'G!C"Ʒ) 6r)`IŌvE]4n(߼zn0HD .3Vr%G 3lq\/-m!Dp#0~қd܇ݍz/>OWq5,i{{ۖ#3d2lo0>?;3Sy|#0W߼; [dI~%EPDaHZmv3wMᧁ[yJ֍m74M'6y^v=HWM>c.ce侴eYWզrl¥N(?{b~IC?l[!3Nw## @oaBi9g.#sYõ5fN_K=_j^KKκK;4Fϝ^;|wR"#FO|]k 'Rݿ֐AVqp4i9YJ#lŜ>ٻ7~t2:;/߻qs3oeѩֶ83h0E6%VTvXox~ۉ2+)7hyo>۫40{w/ Õgw/&n?yꨕۆpD7O|$m - 3NSܬXvaHݻ;n_1xA[⣭M.t-?%c L߉"{1$6E&,NqL  eC17Y;̇Us7Vo^7fU,귙WXrl|"c﮾&11C%(#m4~ r<.&"qvv=8 :@.CC:7.isa/0++S 9t𽫟?N*C̙TCY1\Y>E%@@2EJa$̈j1+bN\&b|}O?h^TVJLIi3?Be][ S^Wr򤀰0 _V,0+b^ʝ4\ۺzG^,#'=Wۻ{nkڣ1QuJ\t% jbx@"|,\D9'n]_ϳSW#{}RiY\>{ {UHߦ b.^FL$X2bD[Xִ,1c]{>[]|?EpA;ݳ/M/دJIJܨ*lY8L*X>'H ˌv# : Af^V0O`10qMmSZIǽ}D8S?l}4J`xڂ|uC5tqcqaydpФL!mqL6YxcQB.- *`+tSHe$/\uЋ m;5ۓ,bIl~$bEK*DISN{[4bØ@d) cJH Z 1 ]YZb/6i6 +|8$iN+P\-VcRS3?LI`v3JWYʏĉ;KԏaOœ oP$92 M NZԛ9VϤ a69NjnTy{0ǡ:\VQk6K4$@K =A4r A !\ih,;Eт2Ѭ15VJllN/e% tj0#m3 ۤd:nFYRy٦ BfE1 hjt;%0'{_J&i > T=c: BkRNDwJ Rap rB3:0<'j1V&7y2n͓:+vוF]~bQ{J)|S;x%M!-d!N8{;7x~+<wx|4plH͕gq(LRAHAy@O @n3ɱG˜QR[G:@96)ۘzDKQIq>mKF!rN=v|kcIHX;eDHm1? vȰ̦k*Jb`$iz& Ԝ*f_efdn%ܲLIćA W]rhA؀0IHlOu\/evI@f~swUfuYE< @!𻣚Ey 1R?iIY 0/nn1!pC?HZv뢬z^c񏢕~{fJ-x*Zq|FsBbNɂb2[g6V6杫ۣ(d+ϋ8 b;)Ѕcv=t9Hk- ݛGئVͦ3JCQTI(z՛7O~էo^>4hW b9 Ğl"&{Io}և?_}տ׿٥;SS^TU~{LjX`~نI`0 }凯^zЕ_<{~wn@]۰SҚ4M3BYb+dL~웦KBZ+'~A$s.tٴ2BpZ0` GJ/BE]~ DB**GF4gz]0I=f.C%n8PIo~OK̤mJ'-\s!u]˦xn 4TFƌ#&+ VakoOp;$0g/K)d95|"ԏ^hN3ޕQ@5)'yXӬ^wÐxt@IRbFZ|A|wBڞ -H[820H~xppyAw<4.l"qz;u 6a4m]*3C0t`k4'k{k8i[޸0`:jơ-: \.m~-i%aRҔE5ʽ )eyjx<7Zgl* l;漓 ‹ӞS"EQ6D68R1K1_:yuZsH W4u(Qy Q9d`Ŗ[&+6 2j4/+۾]ͿQW~O޾N@nx(%H z ;r$S'60fٸ_DHBH닿Yܷxg^rh? ! \(ע)͋UX3`Ghpvx*|]A[qyѓKJ]XLWCa1TE/)Xi%1^[=ༀOҭ:OqƽKfnaL:|}z!s=ePw4E R:$f(WL,(Fi\V=hfL{ǯ>ZТT"wWְn;rJbַ'e-<}*ki0k`ȃ?ؤqX0tm;[[P4ukis ccn{onjw^oᠩ>bLr/zGEZ}%BJ4BSgF5El*/su]iy+θAeB'lL 7Be7y+ckٳѧg,Ca~.yB,ۅ紩ņ腃Ԥ |-'wLI%mR6}Wv.=Ҫ.W 5 p qSz/DǠ/Mwlʗd  3;gU·@ҲV6D`imu Z|?a<%[[yCﺥܩUZnbԙZEA;oERkM7 㹂 EҪt=C@Cbvlh4OVwLffe[ vvD#/1]ku8_I),9uE<@ 3+5+o^ b1&,3FbbI䂣źKOV&/w_}S`2zAG;-]tL]R2gg'(jqRhb:|8!IRͲ,pL4'Qʋaf( )M(K$I<'  ,C2,+$P\ NqVΜ97c }bR)p$0 E4+-5oI$M$q}gO?wkW\| OEde =8ނwwvvv7776667͝ ˼p|U{wܻ}ƍy'?xˏ?|7o9F/|Ѥקffg˫+%;2:Ls}3N.\|ƍ[!_'?z'~oÇ/>~SFʍzzc#ݡ.g&FGzn 'Є]xꥫ>x/xū^/ Ƈ縎?GÑX$ @(p\? a73CP(J% )fg `[{Wnޅtʥ_99^߼\(}ZԢ=X,{!pP5U.Imö`0%HDn^.\]?famw•őBP8I_? ?y`$%@K:ϋZTgE wv|k|-Ec{mR 9?EyT\Q$#)B daUD8Vb.QwW404(ZPCKITAq^z a8Wut놦)knd CstJ? $a)AQEUs"fC4I⁗ 8 ,(\ϲ>uܐvBd2W*Z J:T]ͧgjP=^/g2rc4H%,R=M^( Bnʊl ϶LiYw0DZ R}YKf'dLqN֯)Y2P*'<~p A :lWͲds9mڮ! Aҽ^uf[uŏa7s|K bV"Ð%pL(E qD`K8 Zi$CD4m?0m1N_EeqAmǴKWb 0ENiV6>|xX QN, <nQ4L\W~'glVn;p|f հi)IbrHhD &,)0p$ y@ jEp(h"/K`l?K p (X cr.2-*La]Oizu[} gF') 8.P!@W p}X|Ё~+۲/TyfC,˵`zfm?-۸ K,A#eK i C4ñ5M#Z!H&#>\50:ɎPY,Xb^ll+)  Y'/Ҁr'i2ݰ|0<߭g]JtkFF,^6[VjHL`8T,tTGTDRqPS.N]wïvHE;UL6or=>4s`](+zgT!{#*_ePӠp!j. 'AI)7ܩcpomywoƲisRܝyzpsΈLGQVOMRuuQ6,QV? !0+0e栺2^Pep)Ib|yq}ܵ槏ZN{/ O'y:2o ϪŅ彅 qZY͎oݶ,X %1zXOX H $)cاJQ. ^9&{sn>ɣ1 ˟vhx J$YpHw̜=_}x݆Fp /WU"0 BdiC)gY  8-jT9DMo/^nΏ3Gü4 q4!gx>W"?\dl$XV,17K#NH2ϻ>#81p.H+`@ ֙+w Do}6ܙ~ 9^Z!/ -P&D?N .|i0/NL4%&7{̺ {c\8way0=1Jí3S;{H;T. E΃v4AWqCc{wy<X' Ǩj,x0;du`z޹ +}~^&=;F~~?52ϮSZ.DE?9\$ T c! YA1}w:aSMfq5Ni$ A@\]]>$΅o93rO͛!G~ˡ1J=4N8}ߋEEaDY7U^28cDɈ/`GlgQ^ί̿Iig7alF@.H158,]J#2XpcpD y13K ) P珅\_LcQƅM^e$nƆL3DHr|T}OW] - a$OBF)8D@ELm (x61H5ɠK@Ec$7(*qR/L]!44P$Z 6ٜ"JUE(C$=HC`-@ yY7B!r|9blEf"DBX+y3JB!4P}{ O#Jpp-9YiC~Se~*J ٺOf62TDo$YaEZDahVyE80^H(ʊV+bWT`҉8x0:T~qEVnL۩rVno$8栺Y+.k jN6ghdeE]P*. UKtS&#芡dhN (T|!sK Ub,<VfPtSc6IHP"π+H6hɩ~f@$lx=SHՍ$ l$Yǂ`zߝnb_DQ3TC<@H $)]P^!Cܦt{uVy,nV UH<Lc P—%·a c>S}ѤcX,݀LZ04hyjjԝ]Θ#X7K$>RD@Q t4rRTJi2ja(Q@7GO_J,.Nٮ/lxO&rqH~(#V:08¸\|H&30Zb-] b&dSbןO4϶oP XJ8ʼn&@1h O qZ! |{<2催[SkCu, #VI8}j71,(Mw%Up}'9IY4h aH+tt$,YC-Lt.'}*uF솺Z~ݯy'')DaMyWT^1(鉙ŹI!9E"K"bbZ I` i b!6ʵ0Gg0äJ0;y|%^:dY!Y2Ի.N/L~F#ć p<uB1FeXIлf.(1,AIY[__lmbzRBQ@n[23V~-/gc?n x `@|Ӆj)bHnA?-gX=|,X+,K/鯗[F*JģD<,g *`0).G ߉1M%;N\rATNL)V-ӌQyy?_zcaso{ҙt*NRt5 ],Պ0 Μ|ՅXP,ӹl6E`;`H=/ЇA2yOU[rq^ҁkN ,d +ZFM/_{s^Ld`i}eb;ܩ7*b\b~`XW::> A !)t QtNhɰ_S۔TU5HXtdt߾{\R0\оK4J|,pZ3N?򌍅R|7i+VU1/ё-d9E- ^9yƻ#M&3h"% $T^M;?Ah9ݣiHV ժr!ETAej s؀5h@ѢrÎ@FdB(> [K// |vzOng&&LJ5i5*Z%UDFr3 R5xp(G-=FX@,vr??@4Z`@ar&P<#h)>UsF!+ĤGi)NCZ>N谘n%x@ʦ#N9<D@NP`#|>"P4\-D+H;:69b ?bXBtѩaX6bq_XLuI H/ &]@(*SziQf@rECN@e@2L92:>=51VT"LeX$AK7“Su$ıF`@q e8F*23xto8EB1Rf|7|"M&p(+^MSkCg Z9 m:,܎` 0'ʒHұNOӉj<|q_UYMϮol.M WVaJz^"wODc 522*P#'΢HT^@I &$cj8ڟYZX_xϟܽyx>x'X|û'o[v歾Y 1?=:,mD i"*.{ Ʀy5ePgUA>17HUN>>s`g՗Lhn??P[Y SuH۹N ja1ID":D"vf~EG@"(HR ]h>U v^ 3ox$Y V=Ģ^@[uC#a"/͊D =?qc +LwL-VZTÕ?s_üL49OOt;vv'++PlxB".|d@:TBWPiճɐ^ɷr5<;pr˧׳ p34l"K Hf!z#ÝNR4|B=#Fv`$Q gZHJ?8?g*o|E+-A|S蠏Jrugg'Z'`۶isܠ40/z)lP6Ct>_ *HW?&}@ɇT<"Y c Ue 0??ߟ Fc~eCuYAiQ|Ҩkj#)\mj a4:[FV=YzG"FmH8:5tz6Խm7t)@~MEѢ\\o[@gmncX*UjN{h<%L77F0,7~Y/[P/%Т)g2]`f"-Mh iiianv 2*%Gxi%g2Bݙ>::^^n޸+v;rAѾLӠDǦI@$3 HD"g (7o6p-& )%e90V458֝<8stxWsp8T0j0\p_~o߼}pa QqǿH*O`Zb`okcuynvf $8 :2_=z{w>x#^_ļ4J$JҹZovw=zou3~!Hݝ~v̠_t H1Aw Ͽ}{޽7sWB=gBiv(-CDWNδV|t|6CΦItXZ TAsh%rҤ+ͫ{y{נY$eFI|iPq+O0$8z}xjnvb u{c'1S$KH$# h'߼}㍵&&^zQdԊz(pX? kNKZ;w/sH9O ۀ: mCAMCJ _~gWw1{Yr")m,2%>liTU5}n,6zXughӚ<$;FCA OoxM"g{ۣssCl8WQT݆b4rYI%Qf$n$mhwZv{۩'NL1 ^Yt7:QZn//7Օ]_2`  us ' u(VqPFN=i:TV2uj;t0gQ@ǿ8=jp(77w(ȱhP݄#G|H(tAm7fΑ#Zn4 $fWkƩhP)umPX$[^5dۿهLHW@^HrAf( \8C}p0/ق)ךzJ}ONܬ5ggzyÁ a I(dO{0M,a5?9H(g.A $@ԩerBZq)\c3 dB"H[7TsǁBcY!\pE|6ţLT1Rbtnc}me_b K/Pz1<ÂuXI^iݲЀ.0Ƨ @\St:T1:Yy}I37[[[KdA/- $- NMEcA)e545#+ϴtSQflZfp<wOh2^@bp`AҜ" ((,SWanN\X uIed*+Ha7?1}N)έL_ ʴ& iz?MQhgp*w+E#`IQ@: 4EA%@2\=~+BciꅚݪH66s|t|3fL(˂H<2@7Q0j^5 ++`ZO `xtw&RB}>X={E-A]7`sgϜ>a"1$|8Gg,i| ٢i%҂IcU`:0И I";ы?zp߾|t#x@XĀr%+2ΥЭL 5^bi( 4, eˆi4Ct}w!w4+ 1h>D'qM(W( I(tp^ȟN 1f8":9bv:GN9S>ܑ0P.:qՄnza` $HV`U(t(1"e,:B AhPэ^Ǯ%p/+ :{SǫExO`9)m JGPځ UI6)( 4xv /݈7L==F6Im0N9y0R /k(ċ[e2ʆ TLN1P4'b,8>p/R T3@T!xDAb"n$EBR6}ct,S;`ںJe=KӝEV GGFNE _T9:a72C8u&'  qwgGv('2ȧ:~t(Ҽsi١Đ{萀B G}zFpJDBw ƇKԢFz0 1_⑰eG*Gۉ.7Vb0^\i/]jl48> XFV'9JbZ3"# 0D(Ca6s/V0BG@$] 5ײ C%^VmEA$gpb2lHKq۲Q5Ϩ\13_ [dKt^/PGV΀셩5!3=0"}bSݮL6.<C+4j`Qv+Nb Qs?-S@0O%ɔ؊e9ćaLȆJCI@$@B><@7c^ E%UTY H,z'OXv*9j"Q@{ <N9nz8=t`Q;`;itGDx #hl6NP, % "JεpfP)ZW3#FՃr>ݕqUNXsǪ,0>bU`/Ep`XeJ)NQQiPKK?nnM P@002.npy{isGrv   xJA]ki%KûҮ刵#g_x蛙=Tllb&c03}TUVO>W_6懯߼>]w/w }?_/upxsw_.J8Q I#xRT* AFx^m=5>G|x/:Ee"gFg4HAƁZ YK]+)im1]'V :pQтWI+еXZxFиW ^H0o'[Mx ?˱&DY$؛~ه?~7߹/\8?ȟ(z޵ëG&-G:{jőY!vD.v>>q;M,h,ʠɿĿ0Ŗ^Zmml,ɒ$rMbgQd1+YwG|QhQM,{;DRA "@w%B` B3ӆ%AD~0&H"$i5Xt?|FQ>D+ \3l(YjL)+y0$$+p\-R3yk{`7k{~ʏvV^eH3%4 o,iM{rzbն"؄XBiij;jm {m S{>q%c'䥏bᛙm2R(dh;2ե%l~K{XiydM„;).ZwܗYá 9Qh]dNC:ߟ]l)K~ 2xݶun|qcDql un`K\i?+>}{5?y[Eb6=&7JgQу/Qu#yc'}?;( ϷEǗJ52 @V]WM|n2]o إ_} VӵDD.I/\ҧwBcKkKآctJj{۞1_|vuesp'qRxwCmɰ?[Mrb q:Y?y?Gzn)0:D3pMF!_0A}t{C PT,ㇻHh$p}0qT>8対}o>L׎kkG{;kCÕʤvz!'HF≈7Iݒ zwW:he;[\iNK8DgϿZ/>|wr;Yoh`ׯi9oJ@dRJ KP&_@^Bk5kOK+o0{!~A;x ;ƶ]x Aiy X!|"řCmI+de#A,َ +鰦嗷=M|ud)8x.8;ZV{ N%B9qlf=+8HPo<|zݳ:[J\CnEGO>\?^ 7\ hD5Ca@۹v7Uw e#;r\~0_ 1BǍA> <\'&b%WWRڙxT0ʼv{2#\^i{+;J1f2~:6ڵ$i,sv2McawqyQ!a m8~n%)H&hL$[-I!:V(D,\YH#6Q`0USӦ+~ ].´%EџNVzN7AzѶը%sV \T Gq0R̄Gho 11۳ˣO7!X?5єR/&2RT<4!꬏:mOa m\dy0NVdZ9[Gifch}/]`9 Gs;)i*G2JH! @$E\Mjbq8vl7BV)NwL=o L(*j9!Ǎϧ)(4<$I("MR [ ^:+ xۿ+޹(m & ;h{U4*6q/{v{kӚ`!2+lm Ή)ieq1+4S򓣳kٓngȥ3Gեqkʯb57.pտ~Eu[}˫&@9 ߐy=i+8M= uHcŏ_ϜLfͶy>tF0H@K5gaIHV}T_0߃{~oH Um{ H 7^P-xe?$QD!I$FM:(,goz2WO3'@?dv3c wqP/yh A1zrlhq\1qGjw段,$VwDH Hx Im] C{n]q @; džٟsJR @R݄ BdPzPH%2ư5dW`T0DGHPgBw yB fzKV)8J҉Ъi2bNvJРfN'dLn_]ѯoof #7uАu:w ӝW1~깕) NLLPSN4E~ԃPSh]Ý1 v6m\2ӵVU+gAG쉊D\gHYC\Lm^<:Yԕ.qN9V"Jn8th:+ Wڙ\KFJ]AB) UטFdQuv57e˅?D:[wуܿqpչ[] _{]ҬBo: Ch$\0\0Q%L&k뗯?k^Q# HLz˖ I=|?#ڏLV?_AMb% < CyJk0s6:Bx`n>hsȟ4GHX#r {O`0",uT(v.45vm(=i& Q?y*=r\Y膤GQyB浣Z4kdH2oZ]c6.b+e[;᫧nQFCWbZX@3w"u|E@4+Q][[pB+B븢.E߼BE+(uEH:4%J*Bш\V\<խeg~B Ș*B6hx .e$H"21#iY]C떋TEQUVF -f*|#W%@ `Q,z7کL*2Ide;{$SgҤ(m lܚ {@Y8jZ2/7 &S?nc ڍ^(Gql z\-FӕTވFf\+ktÇV}jlk.oVH&:<7#hmRac<]՗vh|csc 1 W_~rzo{s6~6#8ͬj 4~YؓI7ѹE(/"d>{~OO?~ .[BH}=YZFP((xI ^{t hT;/cߜ>퟾:Euyԓ$K9uQW>Dd }߆A(qCYA*Ð-=X7ϣ/^3&)<)­I]LjZ;K^e7堜實ձ<*DlVV^>ßk3DB2\8ō,qǔk)j22)AYVjU)<.9'-7!-9 HNꉺzgN%au:^)BovX<85<(FzMZ *hɗTB-"dg|h4N F䅙AFlEQ>GЍ ,Y@e5\r_qlU.2['GZpECD3p59_ Yp&2܇R6ni l۝&K^kRρ?J43aZ 0T sYBjwtVF (ɸtD~j s`+•sD=L"w~uS?R0U*I8z!(SC-َ/k&"kXY3^AwbCH$EIv׺et75"M۫\.D^e[ ; hۨ3Q0` XQB,Ary܅C$%%IeWr٥=(,2pHy|*~S&r;܆6N1 mj$^(8ɩ g0j` >}~cqpqR, " Aq:Mj|U!4fq*h J@$yu&*[Hei*cL^$*r6J% `pueȓR:GC wJGE1R4#6TG}>$qO=JsSSLjq\kC}| 2p$^uBurgߦba!~![ϣYDEI]h¿nM]'eʘnis2%s]"T jIZ-i %U(0IE)'*^C""bs*Kx*Ȋ-T]#o rr3LP[IE$GJ|/ː%0)W6:J[Jiwӕ?UxaqzUrdY<;mP+}4O}MB7-.^#nI!&ʕ{jKb 3漴#\[IC-?qte1Kc;ZFCuP"vvU˪U]QQbRUpfzGK6LpA?xŀ"_dP>BuG7ɩp_]TPKK?KϲQP@001.npy[q:{v]`8EeJ6E[ Ҥ!GXJ GxG_yTU2tWWefe~yT}O~_O[ӫo~˿[yvWK8ZRRhPeY h芦JPz9<Fn8ϗ /U62rf2q%ő8zvvwGh8?\޼푺5#zYgzӽ|{4dMg9zso?F[27J%|/DF3: -KFDR]#H)%.^ȝszg:`pDAt*B;$ߛ < u 8 #`$83qh2u? 1P`)-j(J$5IF¢jBgy>nM#I`zSq|Ox~Z; #7/}SM&>&`Dߨ_== 7AWhHEUbqPE&l$2! KtAO(3&a'T1Y88/mMCW=y0")V 9aJ v2ҕc5/&wo49dк\䎡i*HKȡeXfXBpD e q۬0]݋#&[ŝr ќUp'U;ENq$:F*ؚkDOdX`%1goOs2GySeFa rSZ.yHFOŮ.&( nͪ x^ǧanj24VOPpjC,96˺_ dr: E҈o ̈́i٫S<ރ9Tc8{ŹH_.췿tҔ#ԗM"(] 5~SNqqSxt2G5|:!uvEd}lY8n`Bv-p!8Co[-9}qk^ΊLQN=IO}*UZl|_l'L{GssA` #iD.l sʞ,e$O3X"az.}tD"n#ssCheoHGFCpqJ"l -NìtY#Jqw~m8-;Ծ(\ZҠlmMԏʧE.8}ɋӬf  _>\Kj$DbNt=!lCPmfz=K:#!&T tU! ?8IWw|k[~k$%" utmv6a6BmK4?_k1)CGj1pPѥ1_e>'쮫ddv-:Jim`Fsf8V$ ")٪,c/ȾY-^wlx d=;>fjxmz< NbDPO-6 %KΌ3fQVvA. ^)4wYzo>ΪyH qeݮN%}/$=Zo<&Qㅆhfd1؁'t{?%Z_IO4?B}cE7a؂yYN49ӗry E%*PrXɯhܟQO#p]t@|cnxŠ&/QV$ q#C6:T;>A!͋kz#ȇyx0Ue1:*)85@-I_$}0$Nc itoU}Tݓg%t@EbDQ&WÊ:2CISlV߾ (dsCغBS1ֳ:/%DIwfONT9Z—Q7bSCϤL`5r?*ȭ`yFCL8͜%Bq[*Za Py#doEcA$%yUFhix Qe5r<߷3C5t-?X[1zT|er@&W#0U i/IՙzjB=/L5 XC`w5a&2”vv@#F8୧<-ii@g9,A\$@bA2zkHPےsUA+Td )/g+(Tz^u9kbP8)C8d B砗r򝁕'/VݶkgZkAv0S""CЧ7胦Bv1"RIs;YIFZs6帲Ib -"DCaDn5&=$_ݑ 1TQi% Zt+z[X5hh@p:2=0H5?~cTgGq<*F;"B}1ba q;R}⡒dv*CN?\_0zo~^[Sm>+vtyޅ."LMn(h&!I7`"34\a 3bkh4Dg6w!i30 i\ɲcPx-2M.:!(ȁ29/F;Ib˿tՊQq4z$ .5)H̥R}ĩp=8hm-Q׸#NFQ]'9nRBZmqN >9&4p& sτBHXnR50L􀱁n.E o PT%E- J(Pu5gIԢAJ"P%"6+( wM4q1,T[Y^rÜaqAwx<4KgXЛMZG%Up8yzіS%N˥(16~m^GFT eG9)lTF .ܠ>;hL_&' AY j˼]y̐2,Yl42uJfƄ A@sqÔIMI&{U8 %F[=1pC Py6Ie:*X~߾L>Bi;rtVF K(ZՋ},kqQS&aHx< peڙ"pF2CmQg-m5Y_hJ*H{YN} ryoO׷W(,}޴*|\ hؔ Qz 1.BFxȄ9N^_E% y NSc߰vnq26U[ dXզT1R #% UۮEl\$#+P}c%ɲbȗ9PHL(BvD !_u/o`¸I$;hhx xc(K̚WMkM/ϫBclPixƎNmT1"?~|9>g٠nf+!ZB;jThw~o򣧷up{>hYQf>Uq;0A KRǑ7?կ<=&sӖ"^#λױ/II|ӯfgDzZ".,G"Q8J|Ϥ\W͔> ݃yLy}g gP]&F/.!K7JyoIcB4O9g1& {R𴂸aTvpT8l' tqHJB$($50\)u޹:TC4k3غ aM-krJ+}h+]BcS0D+ȸɃi#) +T{Ң1de~&:TUZi Mаov"ITxFRژvcSU`:Yj)hū|!Y! nUH[t'Fyx4>ZIY}K/P@007.npy{s\Yvsݯs@hsD"A$$ 0sf8q'jJ׻kK\\AU~(@Ύ-ow=|߹ŕkk{2O>*>?~VΔ߾)72g/~rt_)S;j#q#ay 7YdE0EHY:Bhf$IY^QYRDDQuMXt نL>Nxsͽ\^(ղ oKY^bA{iE(e0 ?B(yA%UDITTYٰ) 4tcgz8\,n?ZӥvU|O>xO~K 9QWMB; HӄA$CW؏u9M"eJ˹sTHWOϞ\{r|?{鋗/=xp}uanzz{`|j}kkW]]Z][YY_\_X߀׮]ٹs[wa{޽vG?yv1 O>˟|>zCp=zຎʼjES՞ׯ\۹&\Yܼzmk{s Xl]ٹ V>8u|ݻwr=w!C؋>x ѱ񑡡`{ uaɉՍյmt7ܾy{7?xgO_|Ӌ ƳL.$!dt,AԶw$2T6rrmu۝ױI+ K3{ w޸qpt፝Ãљsciȅp 0,1-31njgGˇӋ{ce#_B̆ESfM)xќ5@BȪqB ѣ^գqLHLET"*"JYI_RlӰT1#E~kH48NsDW.WsFW.BQ+:ٕmQ(VW9:r?Е0!"h*lfen %0t73FٓO j V ' EN2 M3R p,#!ͣp8Gp,//H:LR2Mp uDq4<'$K.CAYUzS;)P c(t>ʆ >h#w >*YSeUU44ab DXu>$dܮeu/GSc7+xh,ɉWUD& xO s,8H }@" 2ASd⢹۝آzrO|#N,沤֝R^$3 w$2d+Q wiCūE0燽$\պk 2.Vf-tӶ]KK%M잽f%yEM)%!c(,cdCXd6ǀ E6/ETw̋LT2,IuqZo|ŧ7Jj M3|/=vVbJzF[c=;;!rG5A+n`)V5Z08ݽs̅^}noYԣ|չvKv}):iH \!q6@0H ܛx61^H[ssW<>rųbR$y _#';:ﯖ,th{jWaY0ImnpAώ-@L/XZ\[\:8yzݷUK-vC:L Urzg:;=vk{xVNj^,*e偖HJ ss .p)L Xr%8T?Ne*+[m#f`[&3:]C##WfFzrձB[DtwlB)N%'úL#i \f-\tE%U3] (W(`tuKef2ulE|DRz(kwz sZKV_ӳ~!-)pkF7;R<1dn06ldb8~9"!6fF5d. X_zr-(gUx{> ÃLwwu|aic3N)~Z:D. ψTL!!"{Y kLxGrN#USՂVWg'箟՛vsՃvZS{wEX| m*dŒ)y1U3"R.khX`2wzN߀͗v-Yw߽xo{坹_IXc'31L Td$ D2UJKȆ@d"q,ЎhZ^^NXӝ\+[3/^&.O&'?=ߘ/$bi+b^OE8TBPWCL#=Xs I/Ld}Οzz`sWe^񨅽cZagB-buE yAmאTǗ8/j类 ZZHd!QY\=j~/|{eFY[wf{o)v}ZF h"z"dPamۊ =j*KL*H8'鎡Ee;9"]r:Aɖ+OIXԍ(0uu_J:YI 0s=egU]|שx<j+\4n0$hA6$TMMW<{2txFhLҲeEo+T31_2T R<'<`n<@@h-[v*w=F47fFI<9h@}.b$eNntLল2O~/h`oCnEhIЬ̢De6q@)1 E#<(E-ߎDLۂK tӐ<ϒVqai'oտ]ϤsL 2/h%qX lu3aohZ<_@ZMxr& ppbz)p a^hä;1Q.[ j6NocG@B ē;\T$ ૙7X0h/eN2axB"U,q=QenA!0t3a&E+KG6e@c :0F_:&rUb*ߢRS +f VE#l;R%hN0'lFQE1H"4EpbYJ_rO8uQ3Dp24gYR$QtT&2R8*m*Ory5@Ynܗ b䒹\E״T!Z5)JHd,aHf4u 5p4I8 cUjfWZ?_C鏒I0fBU%I IYT(QbF{Ӂ0[|m~4#YEg'ЉvZ\Z"2{*<*Af_ƣ*ÁDS"od1ēVY$~?R *p XE4MAs OuzQTX'9& I.|Reϋ QIRuKA5P EV_},;H=SvhƗY @dARSK7;c + PHII7q'VYS/zuI)SŁN `.?Z:ٴe _ S6ܸ(y5;teŘ%2i^4$J%l5@q)m`7 )֕6`0O_<~3t1]Umݏeڕ9 Fwr+T`V3Lke;&W,1I%; %o=uOv{XvQKdw\K3͘2eɫ/.,N΍WXawʟ^+^"$癆ꆛzL ]<$g}׿_\jmp N2*+fһ-7:{(L~X=LKg~|CR8_⊫a#DL xc'o [CŔpaQB #I=w).e".,\v1gd< ]RhK5]%qK5`@ViPPOUgvip]Ox& Ab~24xHH B1NVI'_ݚH VoV m+*gh;ExEwfudx]h 8n>1~]GʦK&SE|+3 H`6 Utd8]@{CSx<wx ,+Bڛy0$Z lSM5-q\=E]HOvQFdҽxQiINs@W;ѱ†s,ax4$>.&=ϲ4UEB% MM4T'W!qO[ MU$(;mRDr*DM[??>T  1qǶ5Se?KSٮ iW4`*Ϛd? [fi9XN7$C~ ϸ2Ma>{b!eR %՜),( \M8XU&Nڣy=㊥B-XG;p !Dz?w%Sd6trzJ&=Z.db*K:sS/q5_~0*-kwU1\~g8N<&MѨwubT,C'\. f *R>Y^;uxmsmW/4ZnhV?bp'D. A'z]*@V:w+T2]'[J+޺{ѣGw>Xt{{{.F;\wd(zAm2,U p{b7 Lm5eZ𗭤=|[gSQX/fݡ`gGÃ̠٨7R6 |4#H)`H"Qﮔ*ͮf(T) Mt>8nr)D `g h Y1PNV]@n*\YBFzHo+ܲUG(b0!c{Xb$jw(MݙёN{ppʅ\6*EX%ER=8^@ Kf5DDm6ֻ5_jh4L 4O$ ZZeùlkpӬE3x@^%$0?wtxpcu!龅:M̌|~i0#ƣpDMI$S đyJvQ<ё7<8{ݨ #E@9з66ē+}ÍVktzë +o.-Gl;Nr  䚞@4 ?tёqd_o^ vH~gnxtt56B艝{{^o>981]*#Il6JfR>P5ϵT 616DzFTX'Y"w?Hu-VO>?g?/^l?܁xT!$4 `c:;9޾xJ |)yXhjcW??ˇQD\[뫋չa#(y ')&D iգݙ\ؿJ@c^RiSϥ:?zY[YZi ;4zm*n ,LS(i<¶.@˅Q`ճn.^8#|z+ ł+iH{U*b%]'BqNw9$@FӣMxٜk[%PWg3/^?g/?xxw?+kP 2@S?ŽnQ+֫$x{ṭTu|H$<~tAd ܙlxGO.vm@Sc[6K{ހObWIbl1EcѨzNO U2tMw'l.Oiw}ڈ&R6ǂ\,(x2h;<~|waq=;+|B gDDC&e(a$DL|ЋlrDėT&$‹(5۵T:%ۛ!>UEü(q5BY.N UAI8Kf#x>%˞4/+v$%RMȁ"T6ƣvt9Vr/93Bg5]  y4^ړU4|ah&b&e XyL1*sIg<t/ ٹqxcg‘,pO |`#bx%9 ?,{$QƧu'>{vvt7Y:<{dED6iNLj n::> h,V]W_VeY)8p9r\kxn ޸uw_<MC O8Q`n9>SNApU-Yc)L#gQ`1Qhj:t w7o{Ǜy֢ κLkoa 4@Bg(N3{/N*BZ̮nm>y{;9:4(HIU':6@kr`2އ]"uY,ـc?㋯?piױҋ xA![jA,P9Y3[ru bCzz4wa4Gөl~{GG'`İA$ DcMgJ4lURlNmC1S ~ \0{z|Ɲ{^|eorz(M\ .>R#az4lƧa2 a};jl61v&OoպdH " "XdM[aHl|4LjqX l~ % IJ*?Wyoqe,:T5'p >1> +\%R!gH³4XO(BxA<pT:9rF9kR牟Mb(q m,!r#̏|xšlP~3~`,dўkGJ"\flU ^AXM@fT4mzH1˄Xg*Y-ԏ!vp*xh](*[x"KK`2vVbҋ 9A5T G6ް5 ^;$-5Qv}v-Ci-(G7(,עAK3C!\aUq(=M(bBF+7DdžYAOWYkIyrTSY|I@PXe6FB,4t|:"~`Xe;Pۄ-Nڕxް|W9/I-YP:)WI:>sPXC縰闅K?!Ņ\(Dl{ BS.iN39^.|J0n kLZ+ik2rP1Ee j< {uH(\8>pɳjj: <-d4VW>Oa32.MȮl𼞼, Ʉ! GՉ;cNw Wb$:WLFu"UV(@'5 q%G.xl!Đa[wH ǵcfV{PKK?#b!-P@006.npy{WsUۖ\99+g I@$$I889}C}vCU~u\1snwufa/n9 ~vBˏB>}\<6';*/Y r hz 8Ayc(0 +˪*" fQ\WWyN5l?%Bh:GWҿ(i·r!,|Ha|N(.tm9>8Ҵ $k,ɒʢ$)2 Ήfy뚺Qpk`Y=8paedC5' 0eYQն1ω `X! 8 ɢ"oA%Me^V4raPa A fG{ #0)fZ+G I UuBhl E1@tͥK<|G(FttM7L˱U"Y+^~7_~GჃͻ{sE/*Q؈Ma8e84XaxNEFDh^dQP`*(1Dr[O?oO?/>{}%^2T7lOw&Epڈao[`58:*/HZ MIT3W:x{/{>.ɇi +L9gkkOt,TDDAfy.O/-[sL(Y S^;:_:hcAT C],O jj֨jfhfR.Fި*ri*2Q8;15396:6>:>Ԭq&˥SX) ;;I3 SYG'76VWWLMMO^ssV7VV7ዷvooٹtcy}eqrz&8?3ͻk;vfhhq<<5xdu}k}cummccs{}}}smcmms\?>'NOݿww_z^|o.,,MOÒLӲ BYu805=xν;aֶ66׷a5[[[MxcwܽwٓO.NON=~rvqqGON}7_~rt_އ繖A=11;;0͍ͭ[nܸ}[۷;LWwxrz~œG.//.}痰s}~qg0N/}'g|ɃOQnTZܸ|cyemc}}u <|-l;=8}铳}qSؔx=yŧ}OϿ櫯^<q۔۹l6=317;56:22:>599>2><<<:<42>>1>:965;{m:86x]ܢ]{?7=;>uz],uԒEqn.^Bb4mir'G\rw?Z=>vkx9/(s cL]7OJZq7 ߞ$YJRT7$Ȇ մQ-Ui rwsdeHJ3 CA@)!SBTcʹ+ CsǢʊc"\VmS0};Or;(B[jah_ m@$+dI4=×d)$Nh#ER--<@S9RB(qeCMqkBF`C %8Y@!6Pm2u=0h}kc(ܬEGZ9M$*,"jIeM c.RA'Ţ\1:i>['Zmd5p"Kbewj"tvkt XXO]1vxV1e9 8djP bqSh":dn0@-BFeHpt{8[__-5]JTіd8>l0PB č˲ *%]Vdt%rU:Xy2J4k,dtQ8r?^zUm6zA^<䕢+)ޑdUĒZeH7?w%Jlu|fK ӽldJ!F %UFw5}0`~vatpՒ3z]cQM[o}93`LQaIr+#YaO UenX,*]A@SJc^~~u T7gWE7{SsC xkB.ȖȨ^hT *έ 6ˈ[QrLc@Ki ugO?]$U״pZZvγɡh/ TV' W|BP XZed[JߞVǯ-/97JdmgOtoH4T:sU!ǛJt0ԡybB,N54H{;.!ݚˬxXIpb"C;m=:}\]N\mVJl$X^bAbE Gsh7Whn-+ErxW"$UY[XQ.ksc0mpr61<7۠U8(\4Npãΰ"=p0ATNAG`,M7m~lEgY*g\wrG;B2&nRɠ]}"W뾔J 鬅iWx"!Zps*ThCY$ح2iH*\ n޽37[7Ʈ-Z؜=Va9Hni]'<ܐfTp!+DJκ:ЮB9%i醥IrD'ͭk竕Gb2ygszZɬ+0|UVX}!ax@[ 4DnRrg٨\BnMOܰR;Ko~w?};ǧ]ڿfnlX݌4q;| ++/`邠ɖF uGbቨԸ1ݜel߿;n{?Kd['VvV*َ66rvFY,0}f/GdAˣx@-Ʈ+(%sIgrovB,} ~A*C7HE|z #`YU cDk@@t@=f͉@J d cDՁya,iʊAqU=gWQ Ì%mk&?e<_Bcʠda+xeJMv3&q/oƶ)K|ʚjd{?P) @TER}rammeLJ@;M8@z#;MQLYQ|?Wc 8J^-NX,d`>_׍򾥸NXed(M)a;1 Dvm3N6K^. 4qdЅkĒAHk񒐝Mhy'Vw9PUP5AKUʵT!aR Tog󑍇WKJՔM;qA"h{7G!Ƀ?8qbShꪩ$9d奅֕F~ŁowmII\L*~նm΍$ⶉ,'}wwO~?So񏫗 }+ ߞ^Z\[X)]} &~8j.k碀|9C vHL<$;܁$G?_P]_14@w[BgN飄N"/oqĚ7!Fn6>ۂhɐS[sۿo:?=29l4[DŤ?/r}_h$'1F[3axQꈢXQY6΋?o~ہ١J=$du `UA6gD"Wgw(Tl%CI&gD747iuZ Ͽ}իMd+8 S, 5l/4LBe7i, q4sOKLXpMS3y_t黜A( 5i8=;ۘ~pӁxJxk55հ+d+'x͠ˋXkDmi+`Ir>BVUِh@Zp%yVs;/>7sR&c=l])M!cU Fz \{zv|cM≤ʚDTYJ|&>QS;GϞ>* ՊYϱ-˄p`1LT9%٘a kwz|W=SQT#GA riu/hs&-]p7\E 46ֺ9J &B,ELryh7`|)+bB6F,<2|??n4RUA{Q2I) t?\)vTnÀ0z^l *LgNJ@EpDQTBcC*H A܂օ_[A33/*u LٚmzI{ty/5=0٫R;x9;k@@ҩa|]9MVڐ#E.H1 -Al,F$e qX2~ձ''Q7طNoxU|ޘ0L¼r-f?!F1 # PU! a572EBs6FƆ_.V(ѱ&B? ]>*&p7Al3 vh35W Mr,X0)]ݜVS~?3,14yEg8|194ʒh֤}46)Z0Qpd 7lD^z*>QGaò4ulPx%_-*$jl &/! {#02C_V[{ZީwF"Rɖs$#L" 3P(@(1A5hCfP `ϱCz3Hㅞ!au50تU"q|~#n{V%N,Q+ `|u۵{VVM,cO5$^ӄ (\̓'wLJ[F_`4C͖/hl\ ;vtP ɥDC;dXT&&L((rDl&~6=zxq{/.vn <}ي7<46?10夷'B!&o*Zt[|QLiFbTʄiǕ&MVV6oڈ3>SOB{\ֵuEy7×klmF^!ql+)qyYM Zz9'Sm v}Y'g[j<#B|49بV"q .XIJz\̆dG!fZ-泙|wlld"Fj,rq{i_=-RjсyiV^F\&gw$8dn/-`f fv]>I <ːUN~̍]ʀJxQ LJdDYjZA1\XjȎii5)u3Wۍz v;-'9U]uikf)zy_'YtA%(٘_ZX(15d9 ? 7᱉٩ٙD@]"\rk,Q#N Zo)K6y}vh8lh~yq }.nW%Ђ"ĖIRnZv9KC^1! 8 \EE/e ^wrqyhV\HJmrPfi-e׮BvU8]L#U@ e$ɗ˭f ¯(LMM ia#cI Ţ"x(*AR{hkRқ 4rvdr ) X).Cnq2\L6[ȗrQw(сŒAC3] i&͍)ǵ^TI9D[L[qແ@1- (.(d:-ڙ, (5(vၮ#)V*Fղ3w돿仟PZ+ˎIsa!ʱߴתc%fz ~ʦZ Nc?  /_>>=]QxFPpK؀i0 `.)@"%?ZXS6q{ANxCr[k έ~O??Ɵ`=' ZA'7;==9<x ؆k4Zٜ.pى{Ο,7}SS sK7'H zi7ݙP)w6,PRp\M AJ5ed0i)膧َi JiN=IᑁN%Z5P9~v~-Xyl~"`,( ,:scãcMckK_a.C4wmpB%wrqqLöKr5t KLJ@ ǒ 'f#c615<>SP*diTDK}3)@_Qn%>|Us8#Q\ 􅎏v,61`*cc%PẕW2EXd& ΃~xQ,^!&!! 7H_dkH)v\n"BjmIV8 ngjs۷&].-@S)CvxYYhvmi6f"t#8qӺP4Id|S7UeŁ+` BUON-ھK`aUlL(`eJ,{#؜[ݹ709zQRoZ lYžCX0+XS43DU֑ 45VX&`Ӌ㆛]|vyyxoiB?fQQT@v| XG=$Ѳ8" 163P'wΟ?y>|OWc? ?qʩ1 MPv/#!B&TU EtѢV(=<{ x`rE)l 'EJP`R,`x3SyAIl@%Hj Ņ͵//?Wn7&7rGЅ(lyaŠbUt3vQLl^.D:j޺ >S#HQ EӁ Iv@3q2~aV1 (3-~2/q AC d~HFC,@Lb} CC&A<=疰 r8[DCꯨj:>ʀw`,sxl6ɴJODHp +W(. RK<&gR1$dt4\-AODI<^^P.*36G&pZ71;P@x""|d  plǧ :+(,aA&Q~Fj Dd]Y43}[D+FTQP+ (p0OzKݼQψv&0隺{n#`!e< xC`5%@vk@ݞ7ÂRӓ ?b 3\w7 3ndځgۍR9#4+)HAZp GC;f 43r ؾD,ꛀσK*-Nx } x\+<@ t,[،zB]gAGkpX@vQҰBzrnvx 0I@oN5T F5S ^ gd:@ Ge<סRs4O0=MY0 "줼zi.Hp R,X1ͥ͘`E 8*"!=³9L2682Mbc-%d,0 %)xR?PKK?ռE+P@005.npy{WsdW޹{{_@U{iF4&p!g3 I )b+=<=IM_H6PH*tB=y̼6دO}MsHSj>gog雷/} FF;%|kwJߔ](JȲFdI(qH hȚ,Yah`^+ OgS͇.6pL(xoX_Rt?)u=$Ix#%U%YyRB]Wd]5GijYࢸ4tϟm9:X~|ӛ7wvo<:·ݽË'^<7͛?be nJWz K7v766v6vwnlolonnC[oa?~pzz{ᎏo߹xӷ~'ϏNN0m mL:4>5wppwwo{:?Xuttr|rv-ϟ?;ӓãý[w?~ xO~铋㣽}hD ư˵ f}}cqaiem],.---lllcsG'G'g\>~ѣ'߿w݋SϞ=/x>{ûw>;<<8wb>>?3:22: 􆆆{ O:܍7!4n-V!;gn{[_z%E-S*TIb:lEl=7tt ?HRHXivݡё^jhoV:_=\?8=('3Duœx$JޒH̓b;L=hdhy`dyQi4 ?yqs>7X2*4V"cT?~ὪhmikXc{10zp̳{y|WBJGLba5w ?\uGD*&StjfWJnMXh 3Wɪ˪G0 Y 󄹐耦xGH  H6SU*Fv_R#U}LU=^ (8 }-b؇H:sFUtO\yZXvKxwSR Lw VW8I{meq9 -C0"thۀ@E/+\l'K#űنKu}فLmR,˦*5p=[0 p,Ckpc2'ApOq28 Q@n[^!]ˤ@ّgzFk(pM[b%9 jlFxmK_=X ^q"DG!uXD<]6qS(&׿' [tlWhJT?m,Gq@%H \fYs[zPHs˵fi}a^0r{ &qB5An|iӢl.A)8PK0| Hbtw4\?<ٚ+7Ki!h. ϶b o Z2HAl'\u0wͶ-qƗCt`^T/SSӃt2hWE[ӫ[N7Ym[m\FhR6 F[>X>`©ꐝ.׽JS" <]2]wab['!1DE.4 ]tV˔bNEl|yLM^Ջu\ƒ餝?ZHϞmXe>B3bF;\!HK<{}»d\8xWݷzٗod#05ά..Иҝphf3sK%RMNT Cm+o X-6d.>nIS8{齧ydT rxzyaU ''#ݥrT(O7z9;2{]Z JxI;9P3CRLp֘P ͛{Z98d"m &2T'cu`FrYz] Dfbz[7[;ggT^$N=P! 2$=Y(3ҖrJ0бrjSS7JDlo{o?ӫt/^ؙ{ͣ3;hynٓbCפ"Hunb9U`2I:r:xZ.Nmur~"+U/oó..SMo}tQ"78;QZ}dWtitIlyL<`A/dwƽ~wr εuM56oLi2:Bsdc^ɚB]_6o?*nu[ 1I 2,Z@sU i%ȆTBp@|Ls0#?ٚb\30>oOq4.~m ", fX8"qe_ zxFZ\&^6LXoW av ؁Z৉0D*+K[GJR G,F8˱$ =YB|vЭCM3/ϩzdHTΐx]AETwC$~_ 8zr3q`t޲=5[b6b5hM-GwN/d=# HB% ;NDjhSf2t&\QTH2O`7!=[8blݽ+󈘊bzIԢԍŭ՘ܙ pDIPGf߶50D]] 6q %[;l`g/~a[`iD؍ h~mi}w{RJ9DBR4McaZ3$%8VG>ï*[Қ']CAQܵ{C>N"ؖ@CQBʏvLMg7j|곯~u6zdٳeru+}]䫃)]Q9[7J'2Ka}ElO"n`JV(Jlhx|xR̨&rR%.kkp;Oʮ9*`R YK ]fi; ^4jPr*>x2;)URi! #kHWj>pcÃɌ"ƇN}cLNJ %-_2 0j88ZH"u_u'ޓcR[bMPɈRX/gsE„<I!|ȗ2&,1S7 )4s`Fah.! ]&ZOnXTRQ&(h=_PED%/pDW^rT:ei2ZHHD:$̌V(z):E$JU$8xv% L(25.5 H'L: fnZ3U]89D++IØjU6srVP!rsȲ9~gR!t}doDsy/*[2uӔq>fUK3ZmD-CUKJKFDmlE4fY*_("RMet2R~PmÒr1.QRQgaH\KnvwvOv K*/`:5xp,tU2UX\ 9.T G򬜆?LL`~h6;iVI"fk b@@M}Q dUdTI^4s|G#[^VZ Ind֏ˣJ):F9?=v݆㏯8a֪i/D!<3R͑=g_l,wj. k7GUGk3c@Ѓ #y߷qb tTȰDh(DiO>g/=wsugsH 6,=CG>6kr:SLz`y ŶUSu#ʦs0RK7ZgcKK[{_~B#C @X@""{*GnYjVC8\6X;:o2(2Iߥ\kj׊|ZmwڃS3h n_#(H0keרVsnUKb&x 8Vl:?ʐyLp\Kd75Z: 01խ#y+4>U,< R#~"(Uz)SQX06LCNcl?%JD#`PCUuɩZYFS K_z MKTWt#׵X\ΥSI8M9CwxFvz##).4Ho[FZVSM6@!x(#b+R5,\.IG! - jRX\2!>t^6\4=\F7DfuښӋ'";vJ/HI@*5Vd"P`ITsm}j4ut|`s֏4T,є"P6U4RC6Kcd_gRhg+偑鹅f;qsPy<.,2 M(H01婆TVUJZ`^@ }e Ȳ&BJdEwӅR{zvnycqтLqyA-M2173"xlsdVUrJ6͗˭F^-v;l(#.BL:G4Db3fڶDm::}pD%nԮ5z3'_/~-݋0lhș?12:v *uH%\wtӆQ΁-/<~Js\lVW^Xl'lϏL-ߘ[Y+9|E2t|0;~>?MyzA S翉$ Ԧ_apM)5r\4L*tx\6I~D ,K1hlxB鍴]?$ձŇB E-ӱ`a"G&Kܟ>Ӳ%_Rl*s z*LF~ܦ@\eg'l ]l/"u)fѬ=HKC|_Ɩ W(ؾIKt ,%KrYbHe:aTIfG `/,u KzP(ܒaШ_r{Y"u34|:L8`j: DCAqfhZIVp&>+JHL^~PzIhc#"'&du~0 oxܘi{--&8x$N*D2*atTek!z!] 25&D&Lz1 X|ܓb?Us$!nV^ͮHq-װT<.)Aυ6a9aˆgk q(>{}̅q O$2ѭOk$e5l2zQ*5`y(%ؼf?;[kK 5V@qOZ7߽gI ?rlW>@LS4ݲAj+ ABf z&r͝Ã"= !(jWؒ `}s^(dȣ A ?֌{ps DQʛG3 Q6x5=-SQ{8+9=3 qZ"N3j8a}sl*JZ eB {&]'NuwoUA56߾}S#HqGnP\=]ity Nqg;PnhCkxNS4ur7.}"| Ҟ9i&@}%u,ƙ*֟ec?cH"[>zWO.yoQSՐUig$=jCJ?cU Jw>MM%pG{T]T@hu QEj $M[)b/SN74KU;iRlGJst8)V8j,pƑ&9.1}Q@ 4t-qW * x="(ӁĖ~sC̘SqFQ"0H9t!<S3 LBmQI7A~$] *4v7i`qW* 41b3&$T1 ݦh u3 It&mS+("8?/KQnE;E[}\x|iuyf*L ɳ U=&ۖ% `qW #ei ng[mY \ҿO"TݏxU>T 6uHZ}hMYُ*?d@T"Z{u#e i.xPKK?vV(P@004.npy{gvݭx+ꮮizz:LI9H>Կ'̾>f|57G?7/>|O}я??W׶-5~*.E$EQdYur>jrUMQ),3E5l=Q\pGĸy +.IS; U&Oc|Iѽ()#itsj\TMG0;\nM|^u|p,I7fbٞeaH#ٹއNg.U/ ?ó]?55s kRTURtY$Y4Käd|[<vz9x/lK (XX2纥)Ĩd]aO| E49]p^ef:7-GkUg۟G_|7g뽌v`Y8F {cu^/f8hb/◿O=f|{>wipI*w-0mNf7ǟ|W_~~~saY&e`mƥWOO.?=E]5]"KQכF#,ϲrfRTR\Jqnyx~ߤgӳ>|0۵Ml+˫+++x4.hYtnnV.Ur[m4̙#GUEtWȎec_OK2hi:Ӟ^`[Kܚ\?d3*>)+6 g)$tDZj-v;p^oLV5Δ̨ !qiYtS #ciT,CBϑbD1I)B 4H=M0EW%ï,5vN; v;Ym2t&Iamj50t#Rƚ|g(;ʂ? ~' Kْ``k/}}KNhtx9w Gx/ֹ[)Y|Bi%(l*WdkR 6ùGrΠC CcVУ$d m-VP\,^3֮_,-k4CeAE`!p Q;Z5?k,W"s#7k`;tzmtVLniwRBͨwIAoq05,y=EiBpM=G&uô-@,5o\RG2e/N9EG^_=otq 3S7=XN{)"^iReSv Swvի8kdD,|;8|gO_|G 81`-mvUa28Z_IʴF[K3&g7ZeI IJ>VJAk[81E}5'OO~G>}ƃ>}˟]hegʂmyrxoL6ZI{?iGVYoL[H&L^*$U4<jm.ѝg|?iV[;ZT-mT'oVyHmfv;NU$n^zB@BEKpH2O~w8mً7jml^MUN׏lFu~w`(* =hل+b2 /@sE]I˽jޞ4#4~쳟gOUyٗjfqrpeV?Td(~B)uV"e|L>_%{\" R#zi֪n޼{tL2*P]Û'jӽņcBMXN^1W{HJxH>w.)%h,X^sF%]RS7Zhj~%F[`=Bv g,O;M%KTʐJn˩KHF ΐT"bfRl&PLASRىjiXv8XƤÃႮfGW&뻽v 4n%D"&0E@l|(b2-4%0hswgFt[U6}y,:^Z\c-\ ԵWnYvɬkB<.6EKpzk͒mUIXfZf{uy4X2}W"6>۹i^Yyq|;wVݝ.\z;D JM)SlxeHk`v1+Tl[뽓a»Kn ųx;.<*'2ы/y]I|Z=Y_:g#o!9&P,ij4{'<-q Tx0^Rle6tƳt뺵c$rª7/fQm0pQM0=PrXXcJ IjMtPNJMrItTˮ ⮇Ӿ:]Y1w$|˟y0S~&3P:L Tvc8,fY% N5':+)vK:.L8崙F;3o/T]˖4貦 EePՁ"X41# gg0 FV5aa|*XhbAB ;įF0#i)*`"N[[flsb!,Ԁ'AX}I7 qw?6д0M*z֬Vfi%_#"_-2'[V) 0Ͷ }f1BPlGГ]{ /?|<eXBЋ[kB X")ؓ4Tdpl-L-a>HvT@E,}p&`,g9Į #yk@TV3B( v7eظpVa'5L ØfVm Hն_7Z8{G~M6ޥQ2dōk >*hβ0&/"tƴ*T6EZ(g :j [@75Bዿ߻>V۱ MӰ!5EJۢD xwZqUcds2WЂTQW_p2f,vS%.}q/?/$,-3yI)ƩTXl]z$[ j E8J7j\0G]9^IlQ?O~xjhDK4\I+on]S-]*E-2:dI!){Q\ 'ZKmٍ$FI$[qS=_tv&<Պ@$+s8$ 3KXpZlB{*[Rz{~o^p70(NX7v.]9\0*QQuU<ks g ~QݺBS6|ߤc{5hۦqZ[\[9>9t=2qV?kfrjLQTG4e+kj'@k8[<%Y.*J݋W.uOeyALHnQe,H2 b56_1sS1 :؍k>_VCEwE3UPͫwGk+H~aFes)43Jt?e+Krf} //;i`ȅ:6 ,(+?c#99i\o;p0G*bDy3,SǙ @F>TƖ&ƫ t_ µdx{u8,w7ˮEɈj R4*kskF6qLnwt;9|nf><ơ$B4\jʨeM8BTWտ5! 9貯Ȑn2ZkDdq`܍4@ MvTQGeӊ)kKHt SiiB;ɡCv&[eFq鬠Yyh.n]̀h`#&Asjj*8ʼ TEuHTQՓ-TIS]?"{3=[cxTYJoPIFuOʵJɂn60bUkXB:2eY+f+ v*%YS{ݨ>\%z0j{\aStF4v]E`qƺ9ky) I > ־kȪ6٪;9ZsZhWّ\نԒj)M86.BhwBe§B:R3r}VԀ@@טH'F.g"F'Kn~?d/ˌ: xO`:A&iHM-:2BU@ČDƉ<؀[,p.hi)Ϣnj=xr9,Z%xaR II_cq UV/ يll-qBt[,aUjR2"bXKP/%#HzFbl'REՋ:sQűK"S߆⅋H@5  9fY '!Ko VjՒ&Nr"C2`a29Zb*7&,RpԀmLK-ބm- &N,\B^ *ԍ ꈓ,tM 'iP6))4l)Ǻga+rHIg ,oXYAɃW5׶/zjБB%&rdU](Yf|,H+4vX6u ۮDy?yY +֪e0U|>UԀui DedSE>OJ8.:}Rn= N+gN;'LU,+$IV@w-ӢLDLIu !eYc8MG={rxՀ=;7.v8ヨAhbgj5mKJJeEj)+INXZ<ɳ?^?ыOʸb;:]^caUX 1|V7_H #6uȷaWVo5Ja,:M̠DacqA%\|ʠm~RNFna1lf8~IgV4vesjvSkvJ^J-Y4K)(BzT)y31 O{hi<0ŜI?cյ^ʕڋt{p72$Fi[YN㊄, ʥRT. kӬ%s'.ժF^Vk!\IB Bal]ZoRV*yܖ(x; 0<ڸ,(Y\) Eoh2y %& +nbƵ۷_۟ϿѵqYKΛwU lZӏrzo9 HlhU@U=.UcMr$% Xoܹ2皗5;+{Og/~n~UK}7.wzHkT ;oA9#lĞTإHnhzWg_.n^l].L.v7qU+lxeU9b^h>#F-뜫Zdne곣w䋧/m K;;ڿ Q2=t4'-Pr'UDYa:=7u s Y٤&kV4Ws+Ӆj%-\je%jTа1SUc?4L?8`MymdVcnWb9 ãhT#Xy0J{ŠCkW^x@MRQ?2Xq.EˢU=4Dʹ-PV ShT槽5bv]~֕q"G]m :?'lх ,0Dm\9 vTeEn; ӫt^hzZ3*7,c32#1pb(*}hfRJ-&6<-ץ{xXAčܿ}m+RvčW څgPƶ]&8)UQܣ:/c;W?_}Rd5wݻ:6%<\ d~C90=Ax %$6XeUGA!Y[M.AɟSY|pxɓ'n_ho޶kX6`R-`h*[ͫzW Q9('Q`wnNڸURaw0ANO""jSGorU)YE=ɴ|Դ$o<2:aT9;;qm}qG\&)E|4?xY+ecd^Bѱ,'q' /ߒԞmsG;/ܾ'wodt_4USH?Aq3(q0IO0yґk@kU;0/&,^D\SS&FxO|:e_hHN UIaXA5~p^ٕ+W]zӵPD] #gp_3IGM2LVr|KʅQJOwvvvhTuhi=8"ͬ\x qj="f 5qt `[F|oG7{ <9ϧe1ދUxE[*@ѝ@g"H"OS*M墂.?K :-2ދ޹Sq46J[7DIm-xRE׋c*hlai-qW! aLo] P0׀D!UU)lA5&3(!OPJa1s(EEEY3RNU`H$-iHft⦛s6L=!E=J(̱e͉!{{^v_n!NHᶭs!.n,G_y/q =2'?)WGQ\xOiAuǣaӄL`dzPR]Y^D]AA*[" RxtUMWz0'%))!)6v&UNoP5@81 ȑq>x[yNL'nTQҊ}|rBTTiVhumiH2 &D*Xx8%"gڵ !J<PP:7RV, %t2$5&^&V \ȭ`F<MI%(R|VpgR'e8^ZznJ4Ì :5 ~≲!, <|`+E GwoQ<%+h]%Lu3WȂNJE]1<㨯h'Y+/H*2 ,NG ]PKK?k_M1P@009.npy{\qsίsq{zBON ,EXl.KФHʢ(*LJ%Yh֑'2 3=nݺU_}߽qW]z^ȕ㹫>~x񽇗ww^~t+c.B9*~r U# Gc {ׯݘVRalz_I"`f4 'Ȇ&F0""`4&G4A` ^`C(Ɋ *f;)n08LR?x[׮];ܝ)'36KhzU c(M!Q4 ́A Bp41 N 2%c4Kʵ^~oz/߻׿A`A* Lc L kȀ\Dp qZ!>8ѫp1߹8/ L&Մ R D՜=wέwFk̰w=l[pwt[JP( rRjR,䳅|>\5_*U+jj C٥幅奅S+ST< +(B$,{sg>qhzZ{dbzjzjrzffr }3919511>51=?7ypxp}tϝ;9<:s™ݝÃpj:")ʣ݃ݍS+kkk[k[h._x;7nݸ>s?xɓO{gOݼy/^8>ssıj]Y=8<:8?ނ/ۛ[{koW.]qoݺ~ܾ}?y{O={g?yp}擏1 \=,SV{K6aoo\w mmOI_v"w޼vѣ޿> ァ?}Ȁ~gы_|ի^4uYDyxty渵pK oŀ`Uvv`%w.^x G>͇0<~ ӆy>y|ɳ>޾O~'/_<~OEp>ȷ;I++kKV6͕S M0ssws]q;wn߸~ðO=q={/?|goO~ yP ||g rFcx726 w{Nwt||bj;222:O 0773`իn\|WnܼvrxЗO`|Շ'GQX<'A3vdQQ\P9BE*%`>c s8Ӣ{c%V+f1%hQ&D*W ĘA܅%a*?/OqEW3]4UlgNlJmuWT~T#4qPڠA*%`CjpYa`(qڊGbшz/5K'[NkZWBp:DXDKL,Lj7 E2M8]x'@ARe.Ӷ``8/d2d4ѭj!3VP. XFRx!D D)M_Pǡ# vQ M qNM7 ul˔dAF'ia/J'SbT{7ZmmFLT$ XYNseo *KD(8a oYYR4,i\ XjFsTYʗ 58I"ˍSc=?Z)hdYE-p4DTނfC| 1HV2dOoȷ %ۄTb8;2*-b:H` J(!QϲgXPE’,۰$^(F".y2D  8,I0}Q@.P P]TMVDңʁzhN5b>izEaZT% V`DZJ6E+ $09FJ `LTR X Xޅ,&b#Lr1RVuqXX Rbzg(j X :zXp0 ,!zbJ]ō<;BQ2A>,H"j3YKSftlBx$ ylAs"󲈈P|+v׮9C aL[4b/!QJsCuU-:bJ܈I,8+pA䃛\Ax0 an`}?E3` ƈuVn!1]qouag}ZxRdyRm44tq46(j94]DȉR. 3‘p4'ѭ]ì'aT^57NϜ9b1qAp1KODcムÐV+qj@Bbao޼~/?~}6a8n8⹻8)# 9Z\*cBKKK8QfԨRH"P 4P C{/޿tppŹ7oyt5D~bnbak+s{7GVx]o\p:ӄdI^ĹwA/@iT?shu;^D!g^K,,<|Y?跏l<15蔓/)B}Z P*, pX@4|!4bT|`A8ɚG'W77.޺ro~?OoYo=s;{Qsuԭ'w(hΑ@< SaL wK~ùlF𓾜RLr-^-Z~kw8 ѝgw/=<1S?њAAxEC47#@yU] av:r煸O킁ǰxˣGW.vŸEgNg:"`JkB`L/sV#r0(PH(!:ZܔG;bH beSZ8譈Ȋlxqjzy>)($ $>7E1_8D[h 5L2"B{ ưbX*/FpTdJĜ>KKa֖ތ2'wxI@x3if}rT?]!PI 0"XQ>H^LCxV1 ݍKĥIH&X%hYȡn)4`~Vq$Uuy蚻?yw1 ˇ8.pD wX0~B6doa; @EHge?ZQ$ TJf/, %_ Ëb9` ji Zb(C=HBvh`iZ,˥ә Z\Ox UOdB ].3&XU H>°4V %DT:'l.%# B*s}?12A\fbG$+hÀ$#^183 th%`I2H*%8 "ꩌYJt15I& i7'ȼa?egH!taL^ljū#yk ocHtJ$Z rUAdpHVsT4.͘oUl)W7~?ɭve |Ͱ* %E;b:<o2^! >R(@)0Ј/F\[8pB$f#s!j%uhlsџ~gd %f!hH&s W1YpGC'Bj)x&b!>Rx =-Z+"&AI, ^}SѺGc&wQDh Jwd|qai%<'C <~X٪Ľ VC-8@@ üL'DF#z=}??XG~" &V`Avg&&4"r;8_AXc .hGÆVrH&ֆɣ3_?ӹxGb:l^WME nwauminvrn=8IB9L&h2ךKPr`!27"wé[o>|p>5;[.pTef܎.kgZgRqq897=,}(tkR1[nT 9,ikL+ R*,i!;bWSK͊k ݠ'өt:M-Jw슿x"v@j\ FZ(8l(1޼~m,n ]Ǵ u3l!؊ctTCw.8pB {Zը , ԃGQd,zNBhYMdh·o76, P}zM 6Bhol342+]PpbY0`X,53^nm~|)9cTU-t_!w}:ٙ]`@!Mf^+g(6gZI5ShRb:8%$+i(r ҩ+w>(Bf0vZT@+ÝzLQ p; +r ǢƃA p`'_h隦,[ C1N$tz!Rƅ '5183=5> [24v#Bh<) EChd5쩀&ddβ}j%\#䊉Tog7=w|TufsATiԳ`_  6ihE}ck=p MPaQhҕj2quC)u ۹]L wkjѬL+.KCh!Ĺi~̀ !` "lKs\Ò VQ4"J.EK1,FݡzIx;g[_"ɞP2($j< BDdT$ qt6x9F7 I(#$X !&w1L \OsN?k[餯ҕ , 1+ r#aQ b Zm/[eW蔓xqPM CEOds15WnG\'m'\YGQįPL"3fQ߷-LϢ}=E+_ME7h /Bm?CDp?0Tˑ~+71D4[l38(wR!(R5YyӮusp؞E"X܉ya7ՊX2¢hXN6.=ݰmEf6:bss(6=iv$Q -rn?'DUUEQMK#^4$xTEH\dT.8l*v q>'BT1k7^~4lT *Ŕ"Xr`%ܲ(,:҉c }<J&l^D=s"|RLG]13c6QZˇGգjcN%cBUCuwDQdԃFx^;2&z1Cgi<BAJpܠ^7jNU rD|O(CZ9$zVi]yޣ/_{W/ݺ}ƒN4!JFch! mzwIɒONާ`xRǜjjK>rVgmTj3W; 5ztt|ꃏ?{spkcTKA`3ѡF (Y6!Y 2tEa#4`# #yĺZ3bP BUk^_/tlόzRm0@Pо+ 0n=Ԫ7|6_( ´lD"pv1ҐC*x:zc?xu֝qx:W RQ 9YG?菍A(S<av0Bd\. r1T)Cd Ta}X7[fLͷm,Z2p!MEQGciZ ["X0=59:z>D9dZ"kV퍡6$Po%zj"br{aӗ>,7٨w Qʳ韟 &FQo$D.E#FЂ,KjLv{Qa0H#>r dYSLY><&RT(npLMJ5b">,bԞ>:ٕtoO~ΥRKq.weP&:7H8ˤ9lRHyqX0k[@ZgѴ$!0baa[ҭյՕLiz7Y_~zɚQbP^MA)Cj;mc(4مŅťё6a0v*F İՎvVV&z[7Cg<Ňn.b&);oj&R@|I@QaɥՕYD((@4k@DkpMnܺԽ3GkaVK~۷_|ӏ>~ry{$];xDb|tqogccm HpGƠE+“/Y[Yؼ}AN^pdx̤bs|~ֽ7=gӿu Nho2ұ3 0h~fQC3I B-#B|{_|xtucptM3A= eG r,*3t;ʍs4!V7W׷G{B:9:ޟQ!ɵyr QK5(RtB2<'颍/~u֝@P+9ii )^?!N3uSj5<-Z^ڬKHZ i퓞 y0S7?Ïo_Z]na 0rҤ(t<%_! -(RZTNK Rk:&IhlC'<lwl.R(JXYTo`T #PBJonIJkDyR.Ž"/;T"Ys,tjj).??ϞqOS _alUmU`H M4W1ɨZPܢYJHf](J*+LYt&uމ,G((F__Տ~͂y@j4xxIA=z~4X#"zƐclŢl (HYNI%8c4t/a_'kK[oc$jłR#zFݾ˂aVU腽|XX(rMVONQ!CSQxGa^4j`ng:`B@YrXFh4[piqmx*.|H"cfshbyiqv2{0xȄBul~/_vEDi18>DWcɩlPps۱L۲MF` ^d*g{%ir:4X[!I 'eޚd)@SJ)HPw~W_@Ԡ ²{PhL0t}FTQYh枣ft&Q!U*XڄZsqtKBLrE!1"7pt2wNn(`yb*695 n@~:_ݼyHKCpխ͕a Q2Vx.38Ѕ¢ 45* kkنe醮[mՖ4T@[+ZTe Μ9:}`s1 M2j:t Q;£i&RH Qi).  TvEKI޼վNm\ؔX B,ԽgMA@ PTSUXY@OA} B7T KSH>, p ʨeS d©w^t减nJʧ=}Gc e ;.0mt(d VUn˯+ׯ^zOuGp /]0X 2p$!osiVqLu&'8XC<$:C1P}HL\z>xjY1`f_Y=SQ,A$1 u 4@fjZD8PW{/>Wܿ ~y-j6\g`  ]B7 0>g5[ @ !K9C zkdba+ׯ]to>z[7CIAdI|D@K2: #J CRuPyyv2*C$!"ѹ7ܽy`gwWʚH4I:W:qYQ!:4 ҂ H,.4mR? m 61"jR>KWB- Mxڵ+Ϟx/?zr<M䇋.`,:As;x8%x4!^F-H,H*˲4>xbuCTYs_: ]Q)OHI~6c vgi:Vp 92ȀA$H\(@"OBLA'h]p||aaN*TKֲ+^ )j BJŕQiء4O|#HP r( QDW3qt̹[$TBrrUdJFd=0iЮ,rzP܁}/Bq5qPX]퉽 M#T:`C`"Avg{ӋMt'D xHivzR"BjAQ>*rhԤb<$0hqhd2ABA2tYlCޟ5rqF*1 (:Eg$4e9bd!p'C@%^T?tUkizý@R% TЏU_5R'F ҝ@">nmH<+{8Ȏo*Pef 7Q+5T8NE;438`ЫS`0WP 05Ì* ORNH ɞᨗ)djUЋAZұ`1+)BsP6àR|8$@_!A[::KBpcP@Vu G(mYEӫ6D'C`FVMGѹLA@U<X`|Hd1qȊˈh[@%+v|O4%N8`z38 &N.43,nK'爃rW5'4x E$IYT8$<}Jj_PKK?+]0P@008.npy{gsWv7;nFj4r@̙I"LJiIgeg?^U˵iӞ5UmH{ss]Y؏yxGWGSŗOZZxǏ/?8:~|:~'n]~x,õ|+RR'cH2B YeNN'EhcX&#$IJ$QEc%IheR$t Fh^ia`YYxddz]h )no* BaYY߻~h 軇, Udz0(F K$`$>§x,/p"́DU`(NsLE`Ya <ߺyikmrj״rIS+ͰdF""h$DHX}kGtɄQ$IEbA#tBɅ<9p=x0:X?MPd( #fj9%lCKGW_=zxg/_އOPe?\w-Y%^u Lk;e*2 s⡿豘myl/lЏύU۳;/߹uoS,'HNv;CCCbT.W+RVFV)BTKBVzP)ʙle;=;19=0795=379+gR #q`;^TMV4/Y/-/.--.,,.NwzSS۝?4snogoٽͭ;g7֖zcV5?(ʪ,j@wz{gwgm奅3kgVΜZ__X;wxG\=:\7]q[n^~>'}t|Ν.]L&|n{{uFނ%ln~2/_a߸}[o޼}U{>:~p>{ŋO}'O>ڶ"D;1{{;[[[;g΀1yl={n~t ~'^{?˧/,PdAOU mm0qw-va^{Ǐ?{=xܹwG?zǟ{0^~JXb? qfmyuyy iuy} 5xlm\vk/|߿~ xw޼9)ˏ2ÝH76:ucCÝёѱDo~Bl~yOncw /]p˗n޺~w}}O}'O>{ɧ` )T"{ѤQ-4\v}Ǎ'RD:BWf?8426>66ǻiщ;;p+?To`:Y :XHd- %^cnEwcGx|tupfic33Ɋ QߝB4#vr,Y ` "WE #]$;NU<۲4,C\T>qU-d?)g>xP0[hKmRٶi" o`Ur, D%Hd*S3KmEc>8$1N34E\0 N.SdIQ{:;2u(K),;n,Ùtd|&[5ʎͱ:- _*3dfpW ).|`=* ŋ2dh!lp@948Bcr$xԬU?F$]v}ۙSeثi@!nG}@"lP:UbhC!-+&M3 `z) ;.$E!=$vXKS4D > `\iB%DmKNEmƼbT@]07֎6.*YGoIy7VO`yWEMQAADy^%- s+ƀs6$K2UN!Z/n1bs]UbҘ>lzzPz<&o. ʪ!u: =|BY2Q%YZyTJz~|փgzToH`ӪX@ hJpTCx$4KUZvMs['3vWfel4W_rgv@vp2M @hc*J$-/9Y=hpda%KOͧ?y ` i{'/޸Lo193ЛMvvn,΍ Zf`qlKu"2ݥV EXx 7ji:{`;ܭ&k}+Ww/ZbU!!"R@@6TVv$:P1ȣaxSwzd9417xvo|OּM YTzN_hZNx;p 3|[dUJp8Qe O@8PylyɁTQt'S--l.vV"b0G󖫉^_\:;;Rvdhesp{qc,KL"&5fNEM 'xCp!Ki&Kd i/c&']HgBuh46r8p˸LYHmrh/̍NaCЁD ;>9pB",D686Hs%P=#00Q6RVtpzvvh1]'Gf'H;^"$+@QXL .HҎMG@ xIR7ըZDX9R[ʬL,S13%bxt,VHN5ReX}ꝋgFFӓ3,Ԗ +(fNJ@\9P I"8T>SJ$peOdU+ybʘ,1Ү\~mu\p9?39]*z۾|hkD̄dH BIYq4LmhW(KJVflz*+-,)|fgmi҃gkg항 :-;>+9˝Aj[rO O"~P9Փ%Mt$0v5tH?f %Qߧ[{7t &ܣgieEW:jHDjOrWDyBw$7g:Y&Mxk#i5҃FJq(f(s­_ Kl V v4S]PtC`p`&($)/0@sܘYJ: DB`#h8^M'. }egT"ēZK 9jsj:ƁY<`H/2'Ӑ 144 v.j;'! H I <7LD[tfU#Ńp˔P'slvj>+ cV I4۵j)V<ʆ3)IT,.*Ij .ADE W`+K@@@6E$%JgϦ@aҐw(,z8&mIcb,*%D[h 1mx&SUyEQ)7AUXJjzq?($DIҽv2b%/vTŀM+M ;8I.<$H+gjI('DUu hFޡ# VSz)2hq?dKJR 0xD#[w(x!^d.jvԖ$/ߛ[Y-/ւpTiP䓮EyMЌD̔c* $c`=8eR[VSKTY6UO:ɹʩ#9a1?.k Z:7 |2A04Wp:Swx~To6HڠXӀܮo"x+8Չnwmeqrn,QkV+e]ShUQVë8 {/G^Z^:jV6&s%=H'ȟ.:5O-d:d AT-,W:UYNrʗֿx_zcq{{90uMwmP.fM#6BW N|aO'LTA& UTE Y! CiU8.'Qhp}_ -o&>(r[|Ϥan<9zWx`t> H V;/g3e#iRLUN(bҥ>}t3Z1_&ѨM&b& b_VOIlw>\XDL xcVQDEYV}'ϿI/Ԛ##VVɧRd"O%b&EԬ"bV$vy2(S3`\rjПNq9Zv{蛟_$^U+X4KV|1iFLPD1au 0; DFP &i"K $H@ >J@{O]sQRCLgfnv_- t< BZ\OOf \Yc1'AvŪYȶ=Uex!,d .B]~vg{Iu`&PL Ϗ[;ZAYDBN&p,aROBBD^QU"lM)bP.p{mY]fy UR5x)6+^ 6`Rk5ć@:ZT(||<?@ȃƐD;dl5LeA?YB+9OmQޑׇ̍ۍj)Ij\:i\WwF.5,0d{;p Nn5DzTԀ#U O\_1|3@B-t Hj>_*<_Cs@&KeqQG3@h7/zAQ$ F#f@WLMeΊ;Zpzc@z{{>"KqTGjOš@Lsuw;Y `!r,pxUC4&01EMT|D1? KFQc+D#hVPN:0b wrɓ;&;~hG#~άv_!( 9`/ r >#@RLAL4MCR l rVf\hKbߕ2&wv.\[X(*412T)gөx!n/;pF` C$brӣFH&cb!ުb9UԚvg] r8ѝjf&FmE|36jT!j@ Fާأp/d1ZR֊J>j',D!၁ftx3 {S jj5kRP,q]On1< faHL EXOuFr%ʕrW.7kn;<͕)&|Z/ۃe ( , m”Zf^+WtwKTUN-'h~vl7\S"P0*FbRW^7F'zS޵&Mο2x4NrhѸۚl|566W+@に 4L)*$R\V.Fk^Dx5W;hFɹvgw *>zxUln {xCU)"-3}5<-4۩TtFqS0HUVl7bOΖ`eqB/}idpDxrb`L"|&KDUv&[jtGF 쑄RZj'pCSakܕ@2|wMUD*)g]! T qL asϬ˦*2\eUۍj7i&(A9'h xh9qT3,]K3ӓ`ё!<aXt2b9\ Dᅵ3cCr[WXe6&ii㣎ET7U(l! Z(+ 3tGj5,A"(1޶b:8}p\ Eg'+jt. )4EX< RX<b\(:`2N^ 8 @4/׿aRw900pq gV-qezd庮c[nrY#Ta$Nxg0܀`EWwPAga V=?DIS` {bt4Uض6:04??7;3 S S! PԏW,Mcrq&b;kW^W_}W{ɵ:HՍz OwE؋ Axwr8g?减IT;o,I$ 5vwG={>;Zb~3~7T.lnY5VffHCacF H1qw! ?ⵇo }]>ntr-PX&љwiв yq4 L3.05m?Ѫ%d-SRɸ'k6 )  _LC_=]??{Ń'y-0_ ȎMt &a带x0D" ҵр`h< |&a%'7w//"bm )\p BW5S3tCvS:|?fN,w!wPJ9=CGNapU WE_w/4 >y(bE @麅&SH A:z0r_on[p$#H|?O?Oapi|>"5'}se|DAkD|wب@v5Fg' 'MD؊Ä]Xw//_QFaC$GF0F|WCUϙۡlX#5 *sѲ] :eP(5 +${:@ekM68$TjaD]q707X3],҈G@=sp!˫"M( d K65F$Y4d((` p "+Դ˫W+\8uv{suآqAef\3@ <PwW9A( %$X ë2'ʸ7P'ˈ( :w>8kٕ&(t$±H6,gOwI}Purwacs4oynQq|Pu{'sB(!"Fh ac5 f%AlH;0EE ҇'M7 'ܕ[7o\R~z*?Ұ v{=Ƅ '@T8\!R*belYmUF@ޅK?U|„ "+W]) |*"CT`?4?$NoR)J45,[(BCјɫJ9W&O 鳗oܾsW7!U+"x$" t954'<&ോ4ER8!hdl|P\|OkGvF7U?Q+2'H \Q C"؁,i a,)ߊcw+[:rWwo>årTe`E3ŀ!L2P(j2JW`W8,二k)vuܹ~tcˏo-lF} *n=R{a]9B2A5e* S}"^W6K<,MO.‘Y_y ܺ>6Ȱ˗}- WVq!K6&+FS^ Ƃ[ YZoHLSuTpaH|f7ӍRe.]ra 9dbPPmLW7@fD>YDHD3E`@`IO-p2o2&e.$s,$P@{壣‚<Ǔ=WϹ:YN$疀T)mH v:}0$^A Bh S^ FܵXR9椐N&Vbq⥣rl 19A|% 74RH9:`:&" 4 @`$(ؑFZ"|,qsEs͈'w'a\k?Э~%VI4ؗlPKK?9$P@003.npyPKK?,i2P@%010.npyPKK?nnM P@W002.npyPKK?KϲQP@w001.npyPKK?E sP@d000.npyPKK?6>}K/P@007.npyPKK?#b!-P@l006.npyPKK?ռE+P@R005.npyPKK?vV(P@004.npyPKK?k_M1P@B009.npyPKK?+]0P@Pt008.npyPK GҤscikit-image-0.9.3/skimage/data/disk-bothat-matlab-output.npz000066400000000000000000003221371223313777300242000ustar00rootroot00000000000000PKK?v$P@003.npy{wDZfO49<7'" HT$Jlɖmɲdϖgwުg߮$ptwuW__o擏4r0r?L7>~s_>sx;=(|kY!f&,T-Lt^NM0a%&#܃3K}>O?/>Fo$iNĀMѩmNM73pH']KGf̬ pi/L jJe0z7_׿˟*-3n%quk7YNf6VJu#iQQMS( Rx `u|;O>"l+HtJ4V[i& 59 SggQ%A 8M)LluN#Rrk1Ag²`Y&0-϶Bn~^Ƃ[Ғ(ym8fI,^;ia$䅗v{,:Lb5\o7 ׇs\Ƕ|'ɊhQvH/v9wOfnlZxVQkO 'n-:N+GesA-!,׍n>͎L].ngo_}1L3CvOZ=uhdE 86//?}oO߹{}h|R)}ϲ߱5˲7-W;{GO߹w?R{ i[w&mE}r}?ʲlwhX}IWj?wmW??tv"KJ_PAQJ "j`Jo>*p\}_s}cPU_y 8P{a^Ez(Nt) %eཉm7w[j舐)։2=(}_%QVy<$Fi%QiDq$Y÷Yi4l&a4;}]2+2howwv}kpP=a_q^=qndpSӽM؂kȭCyM^֯;uZVkJ\lhIz8EbՙwGnrz''aL1><+ndw4\n2vm dQ]`'FU*#pC`(S8ܤaI¬t%_d'n<xP%F\[a>wbWxQ !er~2>`ާ}yZA&5r1?zzF{)S l?fz wl*"Y˅k2 R(&}o"YL޻}vI=.|>5nmvH 4R9qĥCGZ)-@̐D_E7%yodC. 8=Bfz>'@2N6/ZX"v: Ty4zPI@uj00$d9ʶ5>ooɐNwf=һʮM2>v6P* 1Xn08I`ҽGGhc4JJrp% FLȻE>lq9֨IԢc:fuO%w-6"(h[S9v>%1'3wDD#3ބ\t]4I(Oq: B'RW e1{hMPEJ!;6{Íw\܇ӯ \R6 : ~A\,ь6<0oLŹ>K̄maKTM47]Y):8'Cc[sgeoksc˼AYah.Ecmd TaN*J 0ݼM[6Ar7tl: v30-6Fde0t@L*k`ĥ`M49`$x6nڤMWq8VOW]o~.WNIpCiQС*Ec3HŹuRIcZ!G$)&DT9b\0QPB;,vAHm[܏|`q&g|(&+%&C6Y0m@ha_K -fo4h`$) BTVJ7AaEE#pѣyJq(wQ(Ӑ~G6375^,;yc{PwX*Gv# 0ע*[e{ r SMFUZ{%YB{ƫT8lB'h?eafd2;j9;wFΰ)\NlI.Ȋ3 GBOlJA 4.lILĉR_A/aCO9L(q6 ofŨ !<{}0+և4R ƷY3x6Z)8S-x`yQDDxs،iW"Ra\\^?k;Ntub h E78HGڄ JADП@4ALnvn8:~lv spyLUGtaRH`myJ"6`B@%x>c͜Ҽͻb`b0AU1A@봒,wUeJDhoHS=􈨘 ȃ}2]%yٲqkWUR,bOiy1+* fS9Ibm /]2+YXF{kvsOW/&)Ա41#Va2Qǫh w@#`&) aJ"j \ !qȇщ $K|E`x&Y VFn4TYut@W G=`TmN7^*0D'(uRx V `#Ӱ0+* ܶfD~t o#< v%WoA85_>RTsY. A$cy Za%lce gCPTE"[Zx0}?pm a㜃'ŠO֒#\V 0/.A[QF JjOɒ8B'p}K²ևֱhYPp@f[OWw^K +nE^V)wIGZr]aI.*I6N -/m?"83_xIf⇮Rׇbh? HG>-:%D/\.cߖF}zrc(Rxoqd DZ):9cAL914 e$\$1$L`1V z1~6\^5(}qvzf~*,~ɜU`<0uO_[nJffMn2v^cs;H0ty{>5! AW6J-Rd$7g?oxzzmr4,gGgOf XV}[p}@UC_qZAJWxn$ҧ7=Gg|9[7 DUYN,s`͔1x"" '\̷GrkqI!܃T<&v7~9zEF}Շ:V{]}YNRA$᧱ H7e~2m,b ? lxAi{T@.@[9;mOVfw62\u:i̲*/£jsk9`i._jZZG̪6>~۷=# ,3~y?O Ifq [Xlꯙ$hUpq#zUQed G}uRqM a[z:7ٺeqW*m ,9FݼA 3HwgwgdQ(I?=s,Hf {_|/?|Nuޕ:oCapFgs웆t6&G0VKXu9y#0g9r{wsgr3.j~믿zf'$Jưe_0aVTmȱeE7QEQ_߿\@ Q6DlG1={Olފ4z]Tn.nmݠ/yce l@xN4.t8,o>#`/myеtԅCzbXYeٙQ=] ]@6d'U} 8I᫩m0PCfޝͯ N-INN11*}I9f/fFe+ɸ90wA7zϱ+)# 8?B,baM_+=H9ڥ{1-Bl X'Fcѱ$ [Sh϶1 ,KQԡXwI*/vZߵ_OqSk AS`Hw.IЀCXOny&jh]Acbh MnV%꠮aك١|A-;XĪ1׫~ku`gW,nމ(R*rH# $!*`1x2T# } |ҶA{kz-l׽l$`zo[~{ͨ:lo0!."UOj{F0\:OF,|jwzL<niTe ?49[EJTM}xW:&ҁ Xt 4M^Ml{}O wذ(,| u=Ь;V:)\U62z:.9$ z@fnSxCp\PUl`/8w^PLZ~ܨ%:IT6v嬄Rh:N|'P G2UvmAZzmZXim5F-XE7 zUyװ,Csw0.chըᚬ`'tؐJW=ەU[)-a׼^gD [.+_g->L8Pz*O˨e{9h%$&|SI m_hkm[2h퍠RU ܮR;UE^Ut=en6zi#O+A \6[j g&`ra]Pöu$ L.Cx AM=o>\yhi0]^߯*JU[?X!N֋rkWՀu8:H덺ֽA'.JfqV>LNcd `ֲ*hGSuHbz(^?:y;'B_'qVWT pf截).WՃJXYůuJT-[ x#]aJ8^P-D0"ɛJ*_[? S=sia:@F֤Y5*s 5"eDaUB> os`iѰȺ^z2XkUrƴ$ 5*h얈KfYEA z Y&j>ZAXuVJͫ%rfGYNiUٳ<G6#Lx6(HȎ00n UAFC z@*)=@<@LvOHU/ 9ނQpOP*؜׈l {SsWdϠHi]RHۀ0d!pfu+vC)]SB|h;zn4`0F5yw6f9x!jfL3͕"1>EVBainQTJbXoj f]i7V/ӓzq#`p1X b 0-ӹs [.̩:X՛袌\?0wg.o.wwVVzspizo20\*HcTBh]ٹL>ds3l1_Tz&7L2J^ ַvwN//_knS5J<~˧Oǻ fjfRk5* x1%cO(ZVn5Y&l6vf:6 f;I? Xncx n< ~B $?@*!I i4!p2H `np0EEo O^s׋>__.z_/.NI 4 :$~V`<  T > Bz:' HP ǹ$!$@m/7w}o$ <.:>#In Ȭ|ȵ_P RF "H]>XCWڑqLqf%2N7uZc&^iJVʕJBP_zV!)JoX)<1z$(\ -I2T*b%Eo}!d*LD&;3ҹl"ǧѩHdzz:Ftb* F)NRB$(GRFY 0)Lj@ "nNL&n ^@(N&jh5ނR6Z]vv76G+:N+@dP/*x[Ŵ!*;^[;R2?-,/, ֠ӂAFV i`,^k2:BX6^ Wv[vcSD"qK(;B'٠?Vm__l/ׇZe8=ۭA]wЭԔJVZVg2iF} d0[V!`6*50zkЭNǢ!O:5)m$buac{icY5; bZ4J-iTZR֨5:`ЏK͞x0:v}dvpQB8^2I'ҲD-n,/}3 L2UdA h6.DLiN4:-h JkMd5TFU#ߠNN4 <j~Nҵ3J2S]bpnnP,T\ x^* F %` \k&3szAhGlTZU J~]sãK<9׊1U|V@(bV@*#%S$$ 6ȭVF33,1hfa\Yh}7*TK^]f륰? h0 PЀ%"R3f3X\Y]_\ gf&IgL_k\VX({+~ebF<=Kv.ނPř*J "Aa`(H}TY[+Ӟ@}2lT P sT2ݔ7>aw+~|ppm6Ĝ>C+j\ *|٩.Kbdq&$'E:D14CRta.my+28Q.'S&D۸MfgR6ɄqQ1hLrt47-{G+;{YGr"[50iS6勮Ja8 +{}xw4>> n@v+mTgA2JF6@ͨkzfWBգӓYL[k^v9mX:35tn>YD۹juMo`A$y\Vs3l6vtPb6*uc|5⋑s݃͡A&=4˸foҬ6zKPBl.1*&f%Ӊh,ZD'HOꣃCwgkyh0bܯ^j3A`ug6yi @ R": ǦP*RpE(1XNrܦTܚ8UXn+-\_ڷV`T~eƶ߈ٲ cxx? OA¬0|6(30R[Y_YoF81 n:.[Mbf?v愫/waݎ^޴[X[XY.P} !"P0 < o "*l FP2J,`hꥅq*^ߦ1Vׄ5+ra4W.MubD Hz?$:CjxNo$.GR άPO8fk,p~ *h Jx>9Nrli.ͥjQ/$OL֠$p̶)YZib +[+a FkWwKOy_W.dTj:R枮gk.]Y,ί,,i? `J/mLL}Aa$0{)HE". h'XӁxd#/n+w#0rZZ\Tnѫ5ʝBhi V @QMʕfNLu21cu"DI b1R Jg-7Fݵ/I0*;SBa&IFc!o2 gґLleP]6 :R/J8=ѠY,zOҏ dbKKXJ05i.thwt/n߅,Siq87VJ#\[@WBͭVRhf ƁFJ(aUj5FQAHbvڪͧ#&1lzk5L87/UʥlmjB/j@Sb"d&3Z4H--eR)&cU#OE @[kӔ.;fζ+N3\^JsJ۬_ivTjx,Cs'0S'4HW/ԑJBd0ӫKk"nV.N6X Iә|T*hXnZ}ae[W rp\tvVX&Lb2 Wyl)N`*ӹͥS"x}9;]T(*r.,{~:d,@C^KY %4zhbD,pSLᲶ^2XjG\"0|y8 n^3W.ҨeTB.EkJ$tR/QR>=0GaFtx˅ҡcbIΠ9Tr`Oy"L&-͂4V5w4J9=bB?^yT$+0*sxJVe1򺲾J5[بbR Cr 8^Ԫsf5YIo")0JS`4_IfiF"eB'9 A@1UpvI(xn YLńWKY"?ݲrxaaK^ l`sct&Y/a`!fAE՞/!\Ҡ QW$(ęL^[UScL!>KٔnZ$#V}X:/򙠎RJNj0>.H{xBJ(KA>.g PQd&1L@djhs.wvx|QB%ʤ&-&FVMa5\?3[Mz]z7]lv }n^?0` ܁ Z81)q|gRbiJ,o.oOsTظ]`(@T*rD~8w; 4uD|H.y&=00 t! 84k"dgecEHKz`orX6F%D*ZE>Z2R59Ъ^Ҁs}U{.?Z HQ +DRAcڨRk">lQoH2%Z)H,TP4pj5 ct'Y'@ "(\މ9Iq 4sGͭi*H[ Rɥr9Cਛ ]xhh>4O6](h0>$-J`$4jBޏ r|Y(kL_eTJh\G9)D\`-$0>_(`hqPm,`$p@0&Ԩk #PIrTh( â˿b?8G=#Nq\p"Pظok7 `L!BrY@ 9HfǭTB{_>?G|cH@d@>98 P}tp$ȟHJEA30*#Ą<'BTf>bЄqT*)4?峫RQMȂ B-&sQB!A>\sp)5ƸB{G͐7Ηh>{;?褈+;\lJ%xJ1dHED&<AoDn YH DEhPHmP\X.v~Oۺ n3@h(<|$bJEB0IBHsp2,1Z`.`(_&Zݭ4Sjub6jBH&a,BK~QA#)ŒBHԑ@'@`C;p9J"PLDYp0Bw;7ń(S*5QՈ@"Ie(V-j+ދ   qy@'|!.qiS"DXc@L.iI7j9eslJM2<7OJ0 /Ati|Ƥ*!PRL(ejI L:uqOOy~L22yzR盖qa\F離utB7i2E .吨 J4GMUJ>ѠU8V{.TNFY)Q6+`@Jhz}5j i1@`}-h@4QWظ +(9%NTr:FZ3 jŀpfV+V%*ԩEM['>pRZ1ntA%)aY7[ DOk oAB%2Fg*yr*[kn3J[=#>)-]B~SO<8-i @"dy^ ?>RKD IW(' #CTJXy_M51gJJ_<y8ځ$AD"ʠD#`hQZZr+SbLq&hF.SɡDp[%aqሷư%U<VT(bT&K=M&r Ug.`]M>$@ZV836[_Df@f„Qk̞gslsfs &R *̈́?'P2SШx!x+Λ@*b~̇<>8V9|x0 &q ΂~JҨHd {H}|HvT\S1BHHIzS%0HpV*TL'Uhz|]h_7ּMltF &8' =/zCAHHʵn6+2J؋9ß?EA^TIA'V9sקD{Y8_p47RBP&R\YZ JS( I"YGG)."n lv&ݥ_nڃ@l| ֩T[Mvmbp:I06HU~BHJADS:.dt(O8^7Ժ??=\;<;x` 52"#Ht ` @dkkBQd &;d[AL }OD~?N,=>==>|~<|z.Ux#פ$^!ZX5CF B./קs^H/wGRj*0IV޿<?="?r&qaV±ff5ɧE4BޟN߽󟾹[$w?Bcy__Oo_on/CxX@) gC-)l9œ }O?l}8^~ݧj7___nNO\ZvKgC Q !xK aFH-vhQp[Xĸ\(G˝/o懟t{mmmus9Z^ k| $;#X  6T'LBF8Uۯ-nn璽ë~/?O^??ݜ\WV燋 卝| ~uTr-jDR\Z9id](W8KmN0ܽy~:99|wzz?;zwups}xzp#_~i>-D% O!/IXf S@8S!A8_- 7o>xxwusz/|_8q(8b㭓PnWF_0=Y/_F~z;ZN :$ϕM:}lgw/{8XD_aI| :Brs{xyzqy~yy{ֲ\M2sG~H/g'+N9*zm=::}x}:\Ϧ<&5-[Rg˟a!!@)kC6a_nr^ۛ㓳ۗrbQRV9cC㓬FgsL8LZ^O$ E((cBTD3rWw^)lB}NǫۋË㳫OgRڣ 0tB$M,zNRT:Y=?^~xS X,EO`"օrՀd ?X|ۧˣ3"} L (R(rzL6 z7p0F,FV.HF; |a0")Z)_ z_q)S g10ϹsZQw..]^]]?^_\ݏrcB4 ]Jr r !n1 8܅z~zj2h_jjyۤJqԡ ?3گX]ŻwUK@I T >g\M}|ЛRct=ٸBr"63`l&0ԫtH4Ey s0hnPU^RcRPcRVouyZy6h"󹝮I/)6א`n.OK{bRдT)zKʥw*Vщ*zNo2ڜ@$J6vKV5۵xdz<=x=W <_e|3 $ 15h%#p.7;&*`4fwc~+ 4+LL~d'=Fmu1d3 @G Q DKWRtz9@3~~ t]&G39Ltc'w75H$P8!S( hB1Cr1u+mbYA;1s2o1>5q&f](wGO^Cհq_DgQT(eeF_ y~Bv2 .FnЪǻӳӫT(Ky75(_*c^A/Z37* ] ֌ h_5(S %IRQI5I)2b񀚏yjrYpw{{c-w6UHqƇxhe-c e2/4eģǛފXzÊuNKK-.w2à*e!AY%EGV:m'@m+U"VaB1|x'-f*vF)FJdqi)1oA9Z\>99<:?m&b p9CpM!9PdQB5Zqh0ZCqq1hh"KuZ(S&%b|"ShFoFk{G;{KKmBS]oQµ`Jm)J&@Gzx %D2G1mnfԈ8 )R E)FA֒(*ibdom{c`o}h{֟)MRߴ Z "YZ.)!<Ђ8A"i6K9*V"RN*&UMF:Up`{s{ ><\n.%B*@~G h@[V>HVc%p.:u'K Ku2`Ba(Vh\TXs낣=劙aT&ZHbAh>J}BxT=},M8v0!P ω R2*Z8v$ͥlhwww]Oʰk|bzgv 6<Ϩەcu)gO1'Ũ #Z.OFhN[ÝÝ#$~1 aO@g1D]^!xb9n/"=OB (tr`%E VgQIUl6cUPKK?m< P@002.npy{ǕfVʬ,OL ш+i%JJVnE.n{eU RV.+gg~|ˀ}o.׿],o} _~?Od\< u2 F0#BwpAgFH)B2^|ן~tU Ua΀ ń0D%]Y) *~_;}=ܟM!L4j3}b9ȅ%a QbuG| |ӓ3 XZ@0bo]ƆȚh oPR8 +is!}Хm=0* pxR'$@utj ũb8D}ݪY* jzudK,+Xfd0քyYUZUyZhX*ͅ+$oY[eiW`#9ʍV'X.ڀhh)MҢjdZ5uQ vt)%̤ˏkP~W=8kGņ _qJWrtu?|~?|?35CMoMg[ݽ'=yz+0L b;E ~޿)%RfV c?do Cx]IȻh`YFhowPzxϡgrv؞ܦҕ5syQr8r4cӝlx= 0iHYeyVVeVWE>ˢ,2-i2+v'YV>)ށoihzyz<'{uwPq+,Kʤ(ڢΫA]MYUQwPfTßaU0ӫw;۫g>ŇWC;5_TfҐR੍2G j(q U ( CW_,/pﰊElxk1m|Vge9h#8"5Wiigju΢W+[ur0ܿ||yr *%hXdE ZpLx[&⻱f+ f@3NvY)XBhG'O{>aYoVEE#1{&* "޿*mX3aqI:D’T q9y=qcɑ65.볣h2[yD]ԑ )a`SI{G`hNA P& @t$~E(#T=dl3WL/qIbLqR*11R`q<8xPR{dՀ%JX vgɤ)ע2*_:P&_=%q{` @J36}D%cho1'EK[8SVEb}k*GW#k>S[ ^<K@)Ad_ұ-dž)p$OOn+P~ O}SA[l)Bq袳 Ҽ t?eIXFg[H.7ʭ uvv2Y=l$YS 4*  74Eo[L:q{V]<~n!1^' O5WE$ D,qg]\ܹ?{XCP[UhD{ S+W ^F>G;mbe(L uik9c>۾OvNA]xF j1l$"!'l(?iֱo8L>q$bE,;EFw"nMGicf]~v~fmkE:<;Zİ_Rne:aOOf[\/vV 2"ʪHmڶ,* >=`f0S8ŭwZvOcZF%dtm~xO\R{yElbq}@˼R.pLc;ҀP ٧p^wY D::F/:83< K$ + P`h)OԈŠE =gxp~W CHh҈E]]-fr'[0 q@ːR(w(˜v[=L;>$zXÖ_ elhnmFs6X{w [rxJRDםFpVb -`۽O>>?9Á;5/0)&챟? ?jY :MFaz(zI8jnT^(N{N9 bϿë"`BrrrҮ8-q\RG>hZP7&||68sr:Z#!~?'*0)aeTyJ'Bd6zCc* ƈcŶ"ݜ2$/oe1!`oO;V7HB`2@8;@ VSØOpT0Zib;q:4HFAw5N[ `x|.(h">n%a;@G1!9]e1vp<ó[ĉ lW}c!o:= ! 0ae܆冾5)7b 6<Ѻ\ A;`2GP!ȍMd@j+:"t>O$[9+<.@V7^8A}-*c  { %wdlIٙ^{m@рKH&m $Sc kF lTp{0uzD 2x_*__ 3(׏و ـJCCǷmg[܋Σ|Tl*FfERQj_^ |܇:@h&(F(+#i`#եcK/hLjDFAim:2| WXF(E$ˬ ` ^LpQ 0xg9I<_.Wq>LKl ̛6x ή!x.k BMAhN9d>H0Vi{7d=]^/%\O<X(0V^0LD E@`0Zx!F_4Mf:9+HF&>hE@ʴp0~~ѣ.gLۧɯAEC-aJnkDL?}5g뚣xh;f!anH9R(7[`aV"uْe>8Băi.$ࠋpJ@¹bRWOAՇu>섭/3vu2yo϶gE<9yiAR]# @?*P/HI~~X]ᶧq5昿iՁ#Rly'_ztdkv-G >8̛ &8+&;*Uf:~ssdK]q۶Mi_WWe/bXј H#)V @O} QGQZ nJ5=}z2g>XD4ϥ',+?jj~.ID본~y+" 0ņab.ZX$hI?b ڸ|B@ߤ8'q*-# Aֶˈ%Q2qdj8 Ck 1[:Zu|6tlr#Eͮ@R|c[ҧ}4]8 :V=*g'{(^yKv Wvy]J,  K:,4l5=z /0A_2ՋGx>oJ/r& F{OPF[(0댹(A*! pQ؉cY={l>Ǥ5/L7ػБP 'xa 恑?>yNbI>ķjFbrBRJ9lXg;$3vqt{v n7)![s?H˲,/)'b x'QDO&"\4BPf/).Hk 8goGl^ꘁ@wMyJ"2E @9⎈C_|эI&xozSga""Po'|M]}TAX%Y4yȱ$G\[ i,EBDj+L[CEn+d*H7I+q ި,"ܗlL+!Y2Id*R߱,;0d o @rO%$"URu-Yt"N mUN,aw(% 8v]p^8H,%[EpG`j*Jn@n)A'^ ֍n* eXB  uڛxxḇf4vLH]Ҿ¿6λvcdKKaJvr#2ѽf'R ?Ƌ*ߥT4kW{7WX) G}03"ms,:6a_~vj!;.CZZMGHWЊEI:h+ RY\ۆO?v3$;D*H>룞_>n獭d_ͽ4/XI,yyx~r|A)Ժ4?st/턜{x|؃À!$vyl&.]Vmޤ&gu&@m{Ld f2,GgdCf%uUzR֧Z%{bDTr>tڅmRUeuASyLn6G%u }ݳ#2g<6 N_|ّ)&aqYk Tot j߁)qSQ\YovN;8?y[æijp&0"7EO&& X4{rˮZXe ~(=YN_/ndG88 LM4sM:IQMdL(ü|_oHٛV@r길نw~}d)Fۻiۦq!S&V?`Qn_>}+^,"NzONfyrzr`ow96sguۼ_NUک%\AJ'MYϿDvȋzWe39ܝitr{ڴ/>g0lڦ.Pik~-MȂ +V=K8]fo]2R V6VP?Mеpp~BvS]~``kC H$wן}xdqiOQM3\BT&iw0bN%!Euˏ+x[$9) WOr&=i4j IdHՃYJpJPx`ͦys 廰a`q"G -tB'EלެN@a% Mo^&cNf;_]id}AiCAuw:N!UͰD}\.|B'yz7tLO!?@mΦ݊ܘ!뵺DkJM=H:aj w Ψ\B|Ė#-IH݈ ToT7!= V&BFJAWt]ʭA@?p|\v=Dұ=k( H Rx^Rwi]K!.;Mr/}'UBwǍ,q2QgM~ _S`ʰQYK/Q,Juָ*'ȭT)4k h3|N*&PNKm̜J)F \ω!2Ov:;ϩ Lv-ڬ3Ib[ܯ_٤.mʒ@Ѷ!EYVM3 RWCeyLᑳ$RB("1 ?dZ7!u\f/LեOJoB0qbCҬc .:!,%%u|ѐ 3 ׺(V2 FkJG YhA5HcڬάQS$Ż\7&ST=4!$Dvbv=z+[80Oدe}y\95UnQ%]2Ȧ a,ryD7:4-uN .SӇy[UdšXbkTt+#3Me@zU>8M_<,[g{")@ DTJt@F<[KSymP?mERWap(w'9 lA(|q9VM"%jwAw·X & I>řc{.x0!ΚAe2K<%m7~--0no'3xkQԩ6E.%ren~ Es'7"S#0d?z~ GΎ 莅ikQ#! {ЀwX+F-2D(\B;Kȟ]R%%aI渥\9V+q*X4F  GVHlp_G7dP7$M\ᆞLJ=$lׄi[6lld%|ۍ ʣ1ꆈ/̾ܣPߎ,I#Lבԃ:2/DA-Bw:3{gUոpzCR K|̗E|il^K+y\ /2;A*3RY=zb9OG?Ǚ+Mt*\NDLMfï/ʬ(|#ͥJO\1 mS .o/W%|2Ux ځ4>&vb,('gߤϥ)Pl5b sW60t>:ʼn\| E;dڔU(Ξ36,˦ݸ8%[~&A!REQ3@a΀Lh$A,S86P/2!DK꽤JN2b2-o ~_jt0-㳳mO7Ƣg0^$ )28}p(p@}?:8Dhԛe%NnU1txy9‘ؗ|7pehA_/35̪v olJ0dFAJ G 0 % NP?fV|9 ܏Ao&  %Eb xP*S/=sdؼg]-k%3@uwGE#O`d\@˖'A)0jU'Nj1H&"Mbndզ{ؽ Hx9m9פ/QH$'̇])N'1`0c:mcvE2nE[0nķf>c@:78Ga堛TOPl| 8Y-%Y&Y'j:o{ϗ&#1OΎa ϟS}!L ̂B!Ĩ <-Ӡdس uc2W/ϏQZ8__5W~@b;Ƥ4'0z;Xf` nhy1(XQ)7 qkφG7zKWGcOU8C_ЂSc Tjt peqm.h]߮Psyk<EidEoB`1|KѫeFe6ƕ],5a?5Z#6^`t6%a]9uy${>cjE:W7/,]8-=.?FMa200{F0ɣX@QZi9IEVL?XXK39 J J^T)Yf@1H>s4LCXrz-Ыyy=%$$U8cڪ"#Mv\7&XwQ EXܽ>?ֵg7d(ٶ~/fnpNi^%/U2FS _ړ39G~K~@~=l=ώ7gG$I[Rpg$KIY L.K"Dsc x$ݯ&޴Lh;.쭜D~yTmj?0)U!R9JZ!χC"~$D@5VY$*Z(\[.F/Fb YYblJ4[Ҋz5C",5*Ɣ,(ʆdM1j"kG`]aLNgIݠğ>C _TFg?E:B~XBAED"lK[AasZլfii&G5kzQ)#E EʢQ2r089ibKuXu`>J*nqG˙xNhلЖ C! ݰ٤na[ߌwt \;t*+{`{)M>ԙRl:*- '&Pq;[!BNb@ ֜F:]NP֠]%DU7btVGph靤,V@taH@ɂWq_\qݥ3H}¡HI MEJNs#>ġh509 ?lWOc4[:ץQNIa<:4최64Uo8$AOp{~&Ȩ!_2Kn1g [=*j}gz2XX؇Ǵ鯱YvkqC!+>+F}|eR8-KSlkSz!5zkZQ\vStum&Lۊ<pᤪ߂aY*j2^r3A6*.ÌhqI_S݈θFX=)lVi@ÕY t*d&{dz#CmčNG4lR֞L*>}&V[hlIH@FL83:ѳ8k39Uv}sH]GI,a^ ?Zmֻ w`[=92I'u'N'ݣ5Te3-9߿8?[( ɾUiMH>uȵQqʑo!#5x} bWqɵ-f3nŲB*Y''x20EG@C%<&3JblꋿxvtBKF ܕ{<Doouۖ$Ѐ w\{o^yJUO}42[;k+ 3JyLƺ4g U}\2x [;~tP2J/ij^P(]BZG,6iY+q%| XiECM Άpu xIulUtKY4O>x؃|f w~R 狚ԉRokLH˅_u/:1KJӡ;*MDşb8Y.+ >1 3zk^J5#o F=j"Ra2K֣mV~<8m~w=PnVVCXX7B RV:*e{ ppƑ^+y>?MQDw^@ē*-Q m9Pi3|NsqI CASz9d _ U,w_࿰&TCN:mh,ă ̢'-"=$}{N@ϸ4T;~gR]rܬ\>)/.kO_v&)Ч٩Ok;V۬|57PL&c*:kSi ָR˦)!`.:C)Fu3Lڡ쵦^=L6g8iq0<tLDŽ;حWI_d~das!2mkܼC/y0YN;;O2LK7;T0i^ҧaQ6A믔xLD)$i ^$XϦx4M+K#2jҡ _?I|ы( NUIN@t7U/BM?:s/W$Xډ_t$ .L2lKoEk\~:彎FCB]oSI$'%r [tJ8}kC݁+[<}e}ʽ]q5rN̅Bx7(ΰe4IΘa: >wmm5 ̳[Ïӑa9Q+-#>ϩ's#9vgUNEz-[G$D"oF?cry:8)9-hO/´<0还TߙV]R1+؆;"@-ś6}'nBvyai3Oc=Y~d" ߭UN)߿Lo~G1 3R AJ<}6i}ۂ~֝U4)"Y̭z!_PKK?E sP@000.npyȱPZ=.IH4zŤr x '9{ԇI.M)Uϡe.ss=vM߾Csinij,82ϴPKK?s=.P@007.npy{gsWK}Vefy}{)xO$%R)u[javvcϽ/ =;[$A]}7yH!}6?$_ܾ|~߽}{o~x~,4[C|)VHX)%I$ z![,sD<Ȥ\:{ځ@umLdIxNH$9P8HVV66ַWUǿ/ӟOGg~/$ͳ,E+b!_*d,H%\&N :'0 [S$N05#"a/M酅6 dn˟oo/NN eiF3qm7JBX3D*N l.J  ck+ ؁p,ţ.T&fgVW+)7N߾Ƿ닇/?1 MA!Ītke{aJ\&H&SL6ϧ,xals횆i"n(J&d"O+C hT6xV,' WIS Hv9ޘl J)Md&2L\!O$"pĶPl˕R6GgfffV6NGa« G xjp"q,CPab`seanXm6LM\"Eh \1Nf3t 6tV4ZF1U'Z&D2хíj2g.3x+ c n==;356<8h4b T8׋W;h[k7HFcd<RRYn4́vVB&:g^{ݷ}뽥B*xnPajH^wqDHlUs/WPzzw?W~d^1YIDl"*2|xP?vBZ.Vjf{p`lbfayiuc}sc<A '08 |Ŋ$˒djXX, B$A,vz~2$?k( ^EQVTxiF]ghehbhݾHW INi;h8 qFh 8/H_*)V`7ͱ$aqӠAz Ig3/C,ۂX5?fJ5-4@9`xA`E4#Ҽȳ"X;9$ے>H @r6$DZp4T\ yAkG"pĬJDg8ߥYֿ# ;CՂJ0Ph2)IE\z"x' gX:S*r|499t''&<Gyхi!M uWk cD">KeiHl1|IdB"LeS|QWZZﮭnllnm,//ʹ:+#Bgmt,(r ͗7:[@nMN[B lhr>I$<׵m7"p(Ӡ\.[,M- 2cDҙrFT^&Ź{͍͝B*/Պ] `1L[-ݲ\e0=7P-KSuC7Mx h O,̕Cz.֨7M-?^V#X (ýH@]2=O̎MAB4YS5݄M4PmPTHri Iz APaƱ4Sl.S=8.wp$K 3SC P.+fʺR$ogK*P k 7DEXAq'nnζ:绫S# )C%QEUPu Bk$N`AIeWUSa?ʂ(.ᄢ`3kB-+sc''[gv.3=^kmgƖݽd*Csp23 X(m6aŲ:};y\[>;[Y "|Q p a-ymjU #NPugx$9r9(`y#L [Hg;V$ᘡxλ`8Ǎ1F?L@DL:r] dDLJ6L5!Nz8f< IHkt ٕ٩bRk;`BfB(%OV"xY.Q8aР9JqH2ԭꀼTv:ZiwۍRSKʕڎR6FVZn #) yċ!9'n%o 3SH\2 ~6;cѳ]%JQ3Q;yMW/+ώp܉7[ VBD`~ںXI ہ%@t$4l@X B X)#-7B!m<6y|ͽGϯVc{3SԚ[H<tc2x\H SM@ AG8@D"b|*S+әyiA1ɱ᙭̓GEWTfn^>l4gz*6Wjgg: @v*OφcUa^`j{2dpmޝmOyŋ`,PQ|x 3!\;$G:](p/~ |D jC$"urT6^9õx+6pJњ ۭվLM__\}NqiC:(%78KӗKe*FQ]p_Sl‹@ݐ6C=X #qZ59F[%-մOnFOWH)mzjힳH4vBX h94X4Arƍ@BɄvh88!K :6+# VXFXBfXh+qIutnhxp ;R؜bU%>Kk;k[ I R\A'r{ hxMQlQpb'W6l=[B֐{ya"M$ NO} !ͶtWVW:k~@)dDt,p30#I*OhcX5 QNTZ2j_gyshFp{$9Sr{e&W&vVf7חWV7*m!@B$"S,+j"%*24371ʹ͍݃GlnNO4(Is2\ZíٵV@08K6`5I,&*1c o$v2cY];9>y_qFl+awIphnkgscz[X[\[vW7g*(f(cM[mتJ"x=i"֠ [xė+ŹRp2YX^;8txX5MdL8N6TQVfovIZZ^YZ,sp7 TލDǦ'ZRg{{Ӯ**xⱀ%QE o2:=YIq .7Tmjfb Jbqfy0 PNj.& {QHȋ%V .$?1x"CJ%X#* JK:@ Dj8],ǫne9!\mOebhnءP(٦D=Li;\Y 5DOa`/c驡J.w# _'ʐp@ 1ƋZ  ߝn&W+}\4Tfu$#U"ǧ; *oP{`40;Ѩ']xjoy IxYpY9 $ F.hv@8v5RYT pydy~jfrU,lS䠔n Ǜpk'V"ML Fb(w%F!C DT\ Pi{wMk댤St!r E Cuôd-&uGb[K=j <, WL>!PED*:(r64:;;k˕1G`d,RT#1>!&AUz#X5^.7:ݓp,98Q/cp?7:-BH~/ZF$ߘI& >DQVa}>D3͈y 9U )߽."ӧB, h!)*AE$d-r3+kKcxaNbǐ-pb y$&"こ׋Ýk§8 pr|L +K2|#,.)b%67[w` E /lSijܟuQgzh}`cHýcH">, |.>X,Vs4kAhw KAD| Xp?6"`F(D'.!ʊ_lF7Qkn~QTjpppWƮ!Ac|L?]E AV,-Py!PV5[ ՛^Zۿ}}6ς"Yw,; {xYl @aQBs(5J9{>M $C ڦ|\o򫍠xwK ,$6 < e@XIggB8R4N!7IBc~@HPp$Ra" . ? @-B eB.ķ?~ӮDH3/fen=eqA,5⎦)lMАiq.a\/ɞ8|𾄠B2䷿O@=FӃ'POUH J9 {& dT@O~ F('hT@+ Kw} jC̈́rzOxNx$&`*(r5 @9"`tWmRXG rHRT]}!+[t6(e_=^f:ͦ2j>֊Tf*JH {BTsMprJX$8%Oi|"Y8ɒ5/ gNk͂2-!Ln퍴Z_MV&=g_o P.NRX;P4b+$ˢ%KEMK4da/tC٥õ၁||80$&XQpEG@XY+yl={ʀyDi&TqFX>4]_,MW Q_}/5^0 Cug-P7 % &s;nX,(w8"TR+J{``l;POzڰdE^tc) ǃMp蓖XvrcZ}QѼ-A Sᰔ3U1@hۊCŅnP9a%d`_"0΁DD~neETӰ,7[n@@Obz<q$duSyd{Ѳ?]@0ـM5n9N<89/AJG=@4uM~0 瀵ݽ,s 1ݐ/Dp򙺮8N4]<ev JpY%2ZH8茦k~! thәStW,|Mn|g븫h^A4I{ђif=6]mԡְdw@ʖxmD1_oL,l^&nrJjDQ5zDmӷb6D 8ATiכz%'0yvOO%U\7d3BZ^"ְJM xXl8\;^:Z^>Eܡ/֪R6,?|AO}v 0{"z0q燑B} o=ow߾zO>:> GseI*}9(Ec&/]w)\yKH`}Q'.ӟWÏݏ>7'''US-R?~?K~P0 `l@dtglT<V{[o_?~?~񻷯_ypcuaԀK |.YǬY@(`fYmYNN8"2\ȡg/'sb*t}jO>}.vB1/lf??1G@}BB征zި6k&]FepH}Ngb2l> ,<|_~OvNwMU7Lqgo>ǟ*4x4VRLb&BЬO..ΏNvP(^Q4}qYif^zӇ7z!pg>}lw~V}L 9Oރ:?{իoQP#qw 3}tZ)7GWgW6g^ 6&lnnJ_dgqAHNh5˯PX"X|ʙѾ/xH?̷o&:~xuhmkpkcco,4#a' n"`TũO|wlR) X`WJ@PPx&WWrhdpowvqv/^~懏o?=M?dӔF|fqkos7.4!F*D5vj2<ux.]8y߾}߿NeXXtx.8 n  ,ܰx,4gE989E Չ_}{kA;9;у7=7W %GUhϩR6p-1 CsaElW?_BCVs-i<5G3D՝7LJ{{ͽ{gg׏n]=y퓃c*0ÿV> #Gxssc GxQ .y D<`Z^u])?<98>x䫋ӥJ$BN1ג9O3 da/ La< s<0 9WƦɓvs\z J'w!1SBǷx:0vr][;>Z[߃(2Al7, Lyd}ӓ+(GgWחݥAWDȖ2 {>c|ǣe^%Z֗V4d /n @W__m&5N]h?}@|=,U"*3*\:8:\YܕEASEYqd,*޽ËNBaXMdƭd'' p^1ʹ>T|]OO6:n ?^a*9Z7}ۗώ/AD R~p?Fs0 ۃvBq Lr\@AFBG{^*A*Xm<>r^xg/|iPw۸w+Y6M FžvfI/Zdcx?~˗/߼y'# ;q!"D |74O ^eOGAGRa<D0OӇ=zSHۍbomOy&;od7J .ہP6x]-Z!3Ϗz*y7{ݝã?yo<5؊qI#x,+.V@T)jdxpzvgL#~rdogwkՋgno?X̂z QeH~v AXt jxװ`!eYЎ gtžz8q{Y7#/;p:gWǧ]Ǐ>9@#(e<- 'W*\Q7bz6@xʝ'*\+I[4?t8rɃ'ۓQme?5 YW5Mq?#hubxP.N$CAv_1GrZDDŽZwv/N\<8ȉfiO`w$Ԑ? aG\!K*ɥj8.;hHCŝntw`r*9G)5u^ôXQ̗jL\X?4J,(yv}}cx{dul:0,wSxR&_Yx$!{ /Z 7d9|rtnKFho`gcwj1_N'p]j)?GRT3qq,#2$/GT5^Ha@TݬW+bm`oupZJ x;yF|4Jkϐdnm a}&Ԁ ]svp2W hlToԳ{ ,ߔ<$[Ul'Pav'?PGާQ  (rx1}Bx z6Kzw޺54 w^Ѻ"Ht~'zoat%$%-0jToXb>8,A'wldM#Hw^4[v~-i27$Ar%WSZ\*Q-xx$+J:k|toxyco֟FӖP9xK/;D*3yW'zXbSyDbd GSS= q40p7+Ǵ gktAݠII U 3p Kɗ+97P(V;cTOM8ëq"ztc8 E+tpp%8AcBP5s( ('@V>e5d5_ܹO@,OIi*(jnD2u? 77D$$K%%xUE̩~$P8I6#N¤SlGgj 1MjyIg4a Rw 8x2!zC fKiKNVN KĒH W7L'q$Ͷ DZ;\oA_kiԈGf{`dn1?$*z|bBdjI$Ac6DVH "(ɰuY(+xEAN"ebc AWgahr,`;`2"d=׋"׀񫠷Hqp(Ei 6rVTPKK?h,P@006.npy{sّ+jh4<  z34c8p[iVH+*"6.~eVJ3$nT{/__kGo*z2|zV>ˇׯ{>V',5eǗLhxeEtKMYbh$YDa(_ cV`&zy˱f'rܜ[i᏿?ӟ~7n??Ӭ{YaDYreIUTcK3ɢ(q<DZ0'EZ%f\PN{uxY??_^߽8ŏo`,F9BNV.ˊ.IϿ/={x}=Wͦ0p /08Z4chB&ePwxnu}w?~}O<]h6 NImi"I ZXmkf39՟_^F{GG{,ShE[PS]h" +Ts ORZbyPf})L۷/op~:p[ry4}9O(G f/6 8 fD ?\~IT4iL@3<81BhBwύ_MUwnHf[}5j?3ֻ_ۨD*ʤT2L DiQI4)lvv{Ғ&'D*шW#ءA$0Nfs\:Nx<$2t:}@X"RV)4jf>kҚ{_\]\y?Ԑhvwvz |X*fRd@5 ٸXbX]d:+[Z,1599<8\]Mm 7Fif}kootpe@vX%^S&a,ӱnY M$AҫwNKj89:^ {lfG;ÙD.v 1;t|N\g47t5%D⸶ jC[Ý[k;!f2C`ulXR _SUF(dMn 7چ.n-\9,7js7'JCLy_M*IGrPpgscLA(JXYʧB[ "ْ*ЊiQkNJ33LFpӽA-KwIzvj)]MJl'$Sz@"tAF`tƪwZRTE* #r7 BNsvhSG+v+WOu*n9 V2 `l4Oc@턑+Ŋ̻@Tr N:9^}Y `-f)=[ՙ&ұj4}~aaPX/v Ey?[3Sɉѭ2jU*AT:MsƳ&5u~k=o֍;z8yzgB=ѺYW&&r,u{f}2_e\kngAKfLTv:ibXl2'cx" lp@-CeT16gu8}:u|ݛv>x|q{jvjK8a6ݝ@m.j%6 119@>rc% WvG4wޛ~k. L$ad/0GM@^cJdY.iNٚ3@?҆`$X8+0ЭI'S G{R@\ڿn^ dKgLy;?X8ux-jDQE-INB"x!vB6R݌I|l<~Zo<OU 'bb4rl+z#se-8ruz 1209A2Zi`dŁ BMf\jqix951-Kblk>]2h;G~h͘Z>>>Ju[U (Z0*0uT̔Sb^"llm,xpw!%3xʳ*yBiR_f֖jń{ǣTQD\QRTSFD'&d0X>s-TYvtO"{^k".E a S =غ2Z4uG Qp=WJlKo,q|15Jʅ1fb  >2`rNK[;ly;E,muJɴH^dwъQ" +ӕ\ʲvW°ހ5~:ÈKE"fh >ύ/cD1ʗ%yTIL/an :1ۇ)h'\rvF KMFs~y&g滖_g _,Eϋu cYղ%.Q04(m`F2ی }8tX;C0k{DLa<}_~Uҫi8o4~F54,8 Sd(?iEDP$ Q^+aE&uo jJѺ:ϫەa2 US&2IQ#P"95βcbH)R]hLgg0T OB -EUdNBߑzH0awf.^t_զ!T`Y% /v"T,C#/`''3Zn7w,Yn&eQJbXPIq"IEYm umZW Ǐpl' F>W.Xhyjb"\4X cK.(&0)KEpA3҉ D5<3{{|ӭW ~hLG%N˿qZ ևE4OPU' pcZoǪ뻃nwnn=Yz+!]bS]p`c1TM@@4,+DivN$֜1%.TaB8:,,,,.uW xڟJR9=GG^ J YP xrЖ7"R,~PE>N&-˕Zcb4[N;t4ɱdV`joq¢]D2rXۋ/;"#溥Aǎ3漠@ SMȺ׆'>쟷cX,DQZ(d&JiG"`XlT K#rd̤ - /g})GLVեe*htMsk=28ݽYvk)1X&IV;I2i(%H)]o;2|3S.o^Abv;bFLj,Xnw]4uWu<7Vήݙ.jnP|,En`>7Rzg[+{UƔ`?'扎V[aՌKD_,ZֽΏݘ c:>FDQ*'Ɗ2grNonymxx~7I0qeI AT\n:`_߭-VR֪>IHۙluJZ}{hLmpa"+Vgf"e8-I2Տ|2'+l"Nl0Uƪkg%ȍhV-ƤKD-]3dǛ-,?ir0=J= J1콽.۪.P~5n߈eRui|ëWOuj!Tjs7Of:V٬BPT[=uiy_E|ۜ5.cň`h"hJC^[s퍛[|ӛK3޵oݼ6өJZn5rQU^~ / gtXt,(6l~y?g_}~Ǐ=ç׎:د*2m)z PR H3)B(:DEo_??~zoxܾw~x{>u6TǶ h)W~^ri"$E9#lб炳FK'׫sO^??{xB6xP $м_If.7KV{'}ׯ|w߿: h(ilpTF` ѧ]ԫ`-m)Q#+*pڹ[$iQ26 ҏ\qʳm*.JSܹuɓ>o^?V]CJ\Vr }pmUovW ~176BE"UT'拫?Ӵet5ncV$>Y,ؠB,U#KRJq,$qGm0Bt~Lv/޾3ډSoU*F!-oZ)\a5S%N,xdR)/eb!yPBc5ɏ_|yxp;X&Tqu3(we*zcihVų))ih?`jro y.0)|g>Ga1Q#h \:;{~eU@ŏ}66\N`r~N΅p0sKՋ=EٱT~>x퓻wO [ʀ @ "6qv҈UK1ױXвǕ'gz'lK'S4`BdH@<'xNRel$Vd9e )K'&2ȸ P"C,S)~gO^ɘ&s,%ʛ#danj^L\W;@%zE[W$ ԇgq1 uun b @(%QQ6IQt# hOO6 >ؠ|7f\%Q1v |U%'ȡa),cQj[$ TI(aٱr\ȂF[Zf+8Vx6)I@KqT1;xp 0Q\^ˢbXd:[6k\+dQkP5Hg_U@ȲX\۩ 2jY59PQP8I[Aܷe \XYjb:8E~9ɖ 8;[gy@N"eE`cQ i;d҈ߊ (%#փk5!h{u쿠aXHX\4ET~L̻]Ƃ hEs ƷMPQ_:ST  --&Zq3 0Tα!Z-`c'X*jT f %Y 3jaexau[6#ً_(S$ڃnhQհd[YtY $E1D98-@04CE&+f5HJW> Ztѵd LDPƙq,tC10Q"=b@r+l83l>qx^ o {1a|Lʆ$(60=>5d"@"`+r!$ i,#msAA$d(YsSI'IBt/:ypX`"1\ǻ3jqloQc .\D MsKCD4 pPa9j@ؕ0V YqEjZU,3nΎrϲi0|&"fHJKbR!a[2e#qQ*  AQmjLxzD<:ҁaQ4MSP :F'̯YV [bR~\QuT5 Ds>[nQCr(}xD7C-IZZ"rGH/l0U,p4ӉthwO2yQU+E ` *1Ǻ%ǑpU_ɥ_C?3Y`2x'yt E&jF[RI/c%:) ZAP\=I(7e< B`" DzNJ(p4QH$2vLTכ*^fPKK?h*P@005.npy{s[W}93@ f0$)RT$KeYl[C3mg;U[S[@IffaK"w=; 7Nn3d|zo?o ʭ_̶?<w_oGr uoK% HI${ɺ% & ,r O K~7~yEˀhQ?AU5g e6 GQ˲@J)ka_lx Y44/*TJlsbeڛdE bj~qf3tYU[A89YUU`Ӓ.*`8fg۶Dc{^$bOίo-̪֔<Q8^]PG~ܤq~7JF`(^J r9װl,2 ݲ0$Wo |ZI=؍nhJA^ncT))9qmˌ\I* Vfs{{}0-*)+:08W*zgSmM ƅi.h-(Ϭ]矾?}{Wڥbġ;TT)IJ=__zZN||;-e=ϯaU#1T5'Gd6t q4)˵Fj7+@ <. B ye`b^tnMrg׾p 2軯o830piW`9BP&'N=.k.S2A <Xl#;/׶ L\H!i. y"(|wk#o 5iQu}w=׏8|X%p$NRri p4"?0IrݩNky{6XZߘZYZZ/tإŅ]}MݪcK~\><+0 \Di\P,i˥J2mvF;hҥMrm;t`{ DZX(d;F=R 7߱A.İ I2EAHA[n5J1spiou]oô ׺A90& Esh{8^)ZR֎d:seoswm_lpB]AtZ^;;[Y_iBkvr_JFgX vJ93l^qzS eQȚPi 9 z컀5AV$oZr-(]+7g3R~/4=QmElS0AQ\yW<4,d*gxx}]H#TtQ-$ZD6 W>oܚr'ôŒFNpkQmt{BWTL]0R2K<6G  {7A4xєRhFn$};52ARwq&l}ڮ^?ɉ{Au8P*$)voHB S=J\,&^)5@)e?YIMs`bNvOv;zɅ\1n}BDy_+$K^!"ɴ> .1xT=hb\WҒ!0=h ! gO{KQ2{򵫻WO#.vLh3'3FJWz uKrfiV6U+sh,͏ & 8q X̃KiOl?ۿgGGWv.]~x//-4z5o-xQjkNwcsӜ Ѕp|q?HrGJ%j+WrTFk/ܸzٕ`f1:Io=oKD_ir\<秄Lseuy}6mӺ.,Bvb C۵my|LR hFyW kV6w檧'W߼stR5ZҊ\nwj8kh`jO,` A$h QZ vS^h*8,EOdn3:m}fҝ<߯jA#rcv6k՞CW1rџޝe9%xtL 6L2,GryÃF!Cd/0\ r~]oϑh%ȧ70.Keѳ̽$)JZK[0|5tRG4_T$T,%Y9^&[\OXWj#uv0 rs{7wNL",6 NVZ£ BUSeٔ˦-+NF+a;!pf'VosⓍm8HӤrQjɤ1CڧC}7GO1ne*刢)#kH!6]*,-u VrT- \uzx;+fI'b"ux;998Z(ల5dɓ%䉬,!Kxٕ%KºQ{Iԩɚ'_Lxw%.T_ {)aGa[խh8ܹ#dU@uXI-#SLe"ⓖmHn0Cҹ`s81G=ziT}?] vf 8Y9[قm)6DT Sy4c%8yHsy[!WTRuazߝn%;3_'B?M+!UΗsfZhNtUZ]::XG+8=D #DKlW\":l!Ŝ9=;]I=l.oVv77n~{JyH$'纶+Y= GSY9̱kV14̣D@а$h X r1N"#謁z,t15]+z͝7޼]4m@+8~9@U/"՝R(:<#?E XODքgxʹBNkjQoݥ*]U$sͣN xFjkBLPJ@lG;''a kBzXJPHD` :-˓RU|4fQLJ›S[e&pU/UJ(]$}yE55t:C1<6<ecd}w8;f9E7gk{u[tU$ʆƅ4_'҂'T"! $cEj_O{ީrpXգyRwo^=9.k:6.M6]a-tk2xqÔZ-C%<:SQ4e|L ᣛr'/2Iۺ\rQ̞%bW+af 2-I@$ 2t>+-W"߿w˥Qh C(xl(a6+TZudUP4ۡc͆u4OH 6FRԷNN`mb89X |\X ,A+27$5;r+5^}j68kqIm-Z~; fvk&@ Ӱu3X+KQEIX!'p1,A|i:-ޫY sL |~Xh40!Bє+?0m*[;  DzT:^l0&V8`:N(ɁGJ2Fpa%^&h"qi*$^Tp,\zMo̖ K VUÑPb,O}d&O$tSW;[L"q ל'^LmG\T/bƦ-?8l1+bѤ;3Q| ppQBHp<8El.J~ju6%#euKL18Ih D)jXG$U钺9Xf5lT3RsGL=/^jYh3H oXEl+E͠W!6[#`ɕ7}/v^*tG 'r/,PlK"`NEl;_8x/ެSxpS5ޏV+i`<eܩDK}0̰4%p D0'1?/^O,TBJvsG'OF-O䲻R,jK2`pVav;(-^ꇕu(&$ 'sM̵b<[Rw>i] U̶Dy`F"o.QPى@+!CU5pOxsh[:adHcRfAh2Vle[qO,bmH& G+DI.1YMN3L ZhuX}>]-l$fLeYb9E⾀c /QA5(#HXkV5CHn(a.-K_FI2 .v!7Q9 &2.8!+NXU|䄢"ʨ./?'Sp&WbQ~{٠&_gxhpoE%z%} h8 N r8B/ q5(=MRNK|"F\OՋIG?<;(J4)d^UŘ*+y ̍atT(] CbxHd-ň!Tcy/7jza 3 ]곣7\Zt|3ЁLjKg!5 gYc9 :h/ 4A`Qw!*y,76晎Vvvt۬4:\)&RD>ė3/#R>ʲbIGNvHx4lnƞe~}ympiq~nzߟV_^p%"!WqIUPA1.0I6/2;䥄\ Ȑ$R{fiu' ou]0/86{1 5a =';}(LIXq莆Q/EM+Fy٬TJ{rrvp^!d H=B̹ Θ ෴InBQIalxacYEp BE6U -8Ĩ-a.34Ɠi}򼢨,*nP)HIK㰮`=c&GwtfegO~9&1;Q[ilfئyvVO"2_P\`K757bV=8+cs]l? !?m4 udbi5 ZzbKUK!msjj86RLS.t1r7;FB/=Il_setHQT\q̲Iuz捹^Y^.x5FifϱV@FRG뀒cWm-,m]}'KZ]i`Jz/wzE2zwV}nT[vg"uTT;+O?~񇟿yG߾~6CՋTOXQ<C:?B$)^V5't,S,3z$PFԃ~SmS~?~⣧Oݽƕӓz'n)ZeyA'}#.K), ܫAZؚOv&h!ga~ZCU+fyq[o?|ѓw?x{׶gr!(I{nnLwH,)7N<$4_}{R4\9j\z/ jΊrk7U{pb/٬+T0pf1S`Hna~g=sFY3_QIǞ 4vWW~ǗwgIYNā2Ƹ u9Vv+7IPu]hAR 4@;?~Oz^;؅Ґ'cSf`b1;k9~&2HaY'R93o]QAh4GS0 ؒWٿ}~>VlòMMLzA{ "&gjIa{9N8% /\j2]c4U҆(+ٕ~.T;NlSU 1s,x.[Ci蕉i؆»W4E5|M]{|G}Ǐ,BtV2h38A |RglzsMeV+ VdvlmnGO{dqe}F)Y SA cj KIl/2ϏidJ͍=z7.K+'x%zDM/&\-W3<`Xo/B Qo=vUM^qB[`X6yGOئcEqH}ZqXc'5UtMZӵ841I69Uam )or N&>zr͇YMx|ւWus<> He`e9ehtUt BQ`;#,b9U5ګ޼Ǐ58!#eM,喙iASy?TTMۍ>ׅ;b h2>]G$I7e]lN_W$`?=txXJ,P*,F՚r)ǿskmQFF+UPR,Ф -)K'ǩl@%JO/X>1XnE5VF'gF <୤I/9 XY1fy:4cy+3tؗ#Qs5 &r}yntpJqO XyHt*o<{Ƒ³x%k/QS񱛬&htF.8:-ɪBulۋ#C S Y?YUlA0 BOö@ߋZ^)MTlb':ݍesP〣` 7x,q,"i*@AZ8NǶyQ@BhˊNf̌R2Y4$Qc),\k)aDMqXZG2AtU WEbȄF 8 m+W *ӝI@XvL#t@{`0Yc>HEMp,!kȂI{v,ROU-}L5f%zsU;Ĵ UWlWiSez(ڸ7<'Ey>^^XbPbiY>IxbRgB=xlI5U%ǯ$,T5lwtɀ߯zq`bWK+:i&Got-]8!JJ2BE8}HܘB@ ۡp~RϬ/•qcTÌ~Y5-pĪ++XVCc8ud&8lɚ)>qw8dxޙ##`϶j9NhVzJ:VB Fv)&0I>YTV62ZYo-[٬l;X$GeqczDZ=VG; "WN-\0#;N {l⚖~֋]C2 R/6e[@'Pp.X :M!Ehiu^p8_B.)7ۓN0Wf^-,Y] 0sYHbyZ(k7Y3VOT ~Jk[LV^/C\QB63%%,I 6rOny~<1<1%L-+ Pz"9!Tޙ,PKK?d'P@004.npy{GfޢPo޳نM6((r#Kiь̎ٽ}s/" )3mШȈ//2߼wK9#vo~3w>yœGɓ/>cx}~Og[:|˗F H| TxN ^@ID* By,G8v*&j_۟׿7ׯg//,pwjݛj/ "ya_9Nj$T/k"KDabBEYUMU\?:O~׿_O p;B5$}X*K2Df*|Dw$JE ()Y54ۮԻ}02Q7>?||{wŃǿhE033d4$IM0$qP*`gLR 5UMOUCUCLdq>NvsA t,zYztqcNp`Q9{g'iH$E{ċ(PFURCV(m[8Acf˜Eo3O^h>5,ܴwOfkP,4"@a /RXmٖiNqYVF7\G5NH,]1f2wT#E;t2^*ZN.`ƠA8uzLg_~?޾~uWT$U~EXQ3E؞c lnܻƇ?oՓo^zpkzsS`R`Y+tuscg[7o]y݂0@k._Rg<]7LJZkz^r̽bz#oG_N2{#">?:*l$?/2hdfGAD?x oyDy~eO7{ (p& +!s`/"޸mA[{ OLڎ hB*&ѫVZBn$Nr=um(4JJ AT*y 'x~ǡQi0J8_wlmwp:]k+O~yު鸶넁lI N'O aD8ɒJV-JZ-4֊p2޹v+g'ǧk峋+W/5Ai}7WMO(w4i [@keXiCfU H80] =݅vg2[{VhIJƗptZofUwjyV*G%",ʰwT/. ),JځYS@؁ FҒlm:L"޿ssШךUntj(ʂЏZ0@$^Q p8dH+R%`%!8}?Bˊ[E&ƍ "tz=0i싾NZ?H/)JQ( Y%4h㙢/mQ$'XYDL"iV\vc$JkJvg @'ˆ#8H!BTB M؟Eh@Fd_i/m/|Bm"jN(e(<5ᇶc9=$AX l5~2]N@y $lBiIK/Ur~3,lf:Mhb*IC@tKU]U#Y x f @T`j".,y@@G z!2յmb{{v~J-V5/|ъ|۴a1'#DJ"aprQpy0+i+x8޸N%r["{]dv8=#X]>k!lb}tA=S1 lN/ k<B4!ƫ۞ ӕK[KAZm7S/1Zi$FaB9p%o% :i&DLHfFٵjKՍFk~ԼvP\?JLMT v&3qs3& fZ9]U| E!AuJ(YrWF;['[&Oc0릷j&n-}8]tV#E1yj:J,ESm fū?xYm&AW6vV*E;shWfcSqZ<圥F≚%dKvyY Q/I40JEե8!J~|iPgDꎸR˛ĵҮɒyB!!d 31Unmµb#넴7n\tj/wCRo:V[4H^hҤ}BIOtq 3c%JdAߐp%i%lz;䐬[؊y?[˞Qm=R;VVH&VjH\{qK' {Y!( 8kH KI&W"۷ZOVn< Hto7!Ttެ |ȸfnK="9uR-" 3DtM׶79ke pjmG~oﭜ\yUW 뵚gĵך gҠݤ[>f})hP R'U"'1^۰JEW${;퍝K;Gg{Y9\7H>iQw8m B 7{kG4x hTRUPejycHaSC͋hޛLュFU?<|p s ;+bZڝ%kcnD/a̪~H}:?<(@ j<n-q$jU$.u|wfފ=9H$&[m)n4W\ku?Pt$ ],D1GQ"_U:w6鐳~EWk-@*SYɭ^ԁdr+<=ߒG]^>6,0SaP;7=sAKx6Y'Kꕷ%EĎ{N,`g[HZMy ,ADuբ,*8NT4x)YjGdF[^DIID0 kqv+ْ79!ݛƱNBՃp#52%u#rQjŵhW&`*>|o,'YW~7%_fsJջ^w,"d|ˀ0>=BDm`j%2H^ɐ)S0][؀Ьw'Hr<^V $( Nkg>aZ-j+}w0vFDUJWzޖpIbuN-//-Ƥ}wc{BUUPN䔻~F~Y!x[|yk/\o@Q;VG+⮱qI Ф%AF+烹r}~`KX"7x`3Ҕ*Zt}lpxys/^D79-iYq=u6pncmjd5,>Z ;lX p_ ) #U$6Ov*5zQ#5]Yj,k7}<V'(sZJ f]d~.VWdM(E2<$)d1X5Ln4 ݕQg]:-Ԭ&aA1MPn 1+O)CslV }I( 5 ̠Y핕`Ft3IFxpdV fٶI$Lj6rEq.D]V sД`<݀p 焲JT$y2xC`Xnm͖]gͽ-T为h ސV+iV  ̏yGQuMRpo9E6=!UP"[D0*"UMi߸q\BON2ޫI"0ZI2GBYd5y51.q41 \whO#m1gNE`* "RUt<;q[V;ӝ1)~vrYh 5f4cR98;r륂xnd2𺁀!7R\x޴{Ϥb;O%U)jLxlTx]@n+Dusptq"% խպ|Timi\+e` r `o@R6W$D?j_A\Tpu~x&hEe D z(go @ ϴ ρf0%52٦Yc9R5r-YeH˃mƇ˰cNc1B$k$-zdؘxGớL{p ,h&SH`1]cjg%ELd!a xȄ@t\ 6$3 䮀X#Y?^?R4IeY +r³!R._(6^.Pxh0@T޲iv47\lwlD$TLoVߜݪ/Zl΄lǠi)2EvV xY  4} @(OkS0|tdbW!e6Â`uAR  9m G `W6A~WdooFUˮ[_r)P X<ҟHBH,8 k<;X_)&5Μu~J=BkfZ$~pˇ/Wj22$= T%nfhX BCUd5` gxV8IQ cp K!ݎ5@f&KgO7g"p0mTÚ 2BX66m{|B:6GX_`H*Uǰ\+ h6v~(a tiVg$Y]7K!6<-ǥ3~N2TK F3&Тx&kǓtoza\Z`aJUO r E*(0Ex߮vۀZpQ3lai ϋ]D8~=]YFzь#ѡzg~zYMi*1WE .լEB1.H;CbXw<8ʪy~ѬAF d$y#\(Z:#UUT֤<O| t@mbU@Uwtg ~?S _1@A6'UkhcUMQTY Nueږ$Bo41?\L xJe_^[r8 lrCRhbU;--D⨪L8ҽze -d k;;;A%<߱t]өQ ]t{{q3UL\iTI4\rnb->\B R(SxOٺ_8#-u J͗2AJX+?|xo ݴJVFg:ٰL>nN|z7t5u!T*%s ~`;#DjDm>u=@ٱCEa/ zTN|D`tݩTQo$^ܳ ܉E< b2?EJֿzfW]oMOFrSQA5bie{͕͟}M%١D,!|CYC17߽{~i`~z;GG{ʂ*ij4F-*ns|oҳ!W]yLFOcW(nƱ"es/ջwl[y2t_lV̫QzZ6 a.\XsC(;$mJL "p2~Y xysw^{Շ/EYlJ:5 w?_/}xH#woݸygWHʋuTTmr|Fs`y<^YڍF% Ў{}txo<6@ $5q3lk|7?D(;$y↶ 7﮴ WDe'iP|l)ҰOҵ뵹!e$>eE_^|7x>2B5CCH.A!aI .Dw_{F8?)Eh(NVJm dlw'@YUoPBpwD wT&T֒<|>ⳏ?廗e d_e k뇑$jV\_6 0 $}22pIm< !)*! [rԱT4UMA+q7@cP)/ ,N">eGc|w 4v!渾F: R EDeI98*c2X[`MQ3j7/*iGgq;(>f'J0S ;c D5GgTuT1KT%YENpA9PXi؞Ifv+}?ze[;N+T>}nO(XX]n5i#ޚ4pzz\ ዕfF⁋DNf"Oa[u[%ɖAYHHjW`沦ǖuP4ek) )uIZ<8 -YFRb(1) U2ύlNp "KۙĘ8|Ҳ P $S)[Dgx1;~.l==x؀ ̬PCNMUW,i E0 e7gG h ņ `g* 8$to h64> : PYpϚ1cEyVK(mT4w&쫥Ԋ|?ouApSC'dțP/02TOG=%y WG?gβy6!AaTA)hBz9 >>(E|FHX!a(P.H=$DMtyJ$PKK?~л1P@009.npys#Y.0 #H Hh@d{X]{ 6B!~R\g)(;/u'?^\l]n㝫5HE8>8 (fI )e)a29llV.JJT.MjB~*?55U*tZkVKV{K++˃ͽ룔Lϟ_q}?q%i3$}ngQi+rT,AV(&' YlmTijommcsѼSO?~O_6!)I?c)蜣 3FUOBYԫj\*A%tQ)Lϴjr}~au1m.o_\<>>\,3r~xs駇n$G3E8I0Lk;lTgf`kR\TiH}\'|^3voye EeH[NW(I[k?4OFlc5SV*bR@j[jUPEmڀ٠Ӑ2YL"!pGN*䕌aql.uN{f۝kJ8]+U R2ݜmͷfa`cumpk`cg4˗g{;GYjJq4F\mwfR+JӋw___^?}z:=N]6Ѡc@>g 48N۬6b1vflf޶vy}>_ "X"L3ىd6[y=n/nַ/_^>|OvBEäDF*B(8Bt22G(6YN x (JJVT*J?ZQ8 Fū@8 x",T3V{ηz h_Fr9xT&IR\HX8/EA>EL*M=T?B*RW*!H~TFR^7cX<, ,HI˲`=.atoHq9.h[dp]]IVq$=LįojɆWOJ:"|F"߿SD.Л4̊r.d<98H M|D [ވ򏆑܈۷??hQT*ib5:VՀσ hd6z/PJ7^7TJEA)"8AT"/Yf4ZM:H|d$:ȏON@ʤလ`FLv,D#,V+8Q:`#q*v[9^ .MdP0Ly^o0#X4 !g꠿ޞk͵jQoooVW!gZZ}\,N`4̻pm@;1L '7esjp8H^'VݭB]XuZ6* N{TQֶ`ѳX+jX+<]h7 X,DFrLτhd_q:6\[]-6P[Ӎfu*R^6HR(z1JjlT蚵R],Aͪs](]^g1 ѬכFhWfRSRޜoϷ Sy*E@ad~rbr۝٢10*s!̭JoyumZ WoU<yʠ3t#Vo[V/FsfjP!1cl3WMRYH¯>9d}xu/,-5KN^ZjJQ!(FF~zPNLʕzl3y<71d2l*5ïR>ߛG04VX:\olggV[3r`U>ߘ_5gylJkkzVo`zN7h4:D3cZ97 ˍGh2fMͩ2s`Z+Va$'KKV1lZjkѬ*S9p@N/uZ-6,ךFYˎ:&rch:dFrgQcW۽n "Fk;~SOf|oi9֜mNMNFy<15@ )BBFjX^oD*3ٹ/Q@: y<{9"cBn(Cyttqt;ˋB 6}L,\dv UAUlW«n[dl<76&'&'Y?d1uY=(T Sx{mZ^lTgƊ]XgiƼd./fggR R+!Ws`W*^TivO:36^՚s~`=pTv4I$2悱('홣@gXioo/T|5R 'KzYWJ4,Fa88n1= Z}nn~~5 rSdb$bD"òb5,nngq9Ycr2m͔륑De*;@;papL4r2: B0;I&P\LԌk{Az6p{Zk;gbV7Lq&0?iʓxiP,v[" `?I7#N[K"V4Fzl/צaţNkvQ/b297X(g*b"̏OVC "e8)8c#j>ŢA'L<,- L>cZ5Mu5& \t;7ӮNJN47Pg .bu8`4),H;%EQl2w=N^E+kӂ; rM4vF SQ;TA7#|kXh!i]?deKd%7Yd@͇>ss*a#yƘT%CsJ[荄f..(t;LfZ)ղsvpnŏ0R%R Mdn CFq,31) o(kd5o:i7^mRxwQĜ:Ot'/H0Y~0tt6*<^Hg#8đ+xqJ9!=TUV >Rqj(ԓ=7rrr|v}zpqѵd: υH,J]FSϖJ 9k'ހlH{ÃO\)JcSAǫ~[*2JUC!W&S]o W;-C uj=;'s`"i._ D *xSZj0L{ZY^- v/_,,4ɕJI+K2#QKnl>'UX+Vǝn'GD AyG q/u@_x:*y@fS(JoQIM \w:s%o4K3.o9f D%.l l5gCDr!J0{0D82h":` _.'C }nNcD|c6lp *T읚1J{E.7-G;_䚃(z,8Kjv?H[rA 0T^;.]Ya >6OgԨٕP{f[߳0J _/oh"1\]>?ɛ`3BVxk֤{s J/2LҘjq86kf 6-:#b*aT OpR4m:3^ou=hEo>UX:p,p`ض4]3a^6 N 8aA՗8#[ :o&0` F4qhx)wg2Vݳ}nw 3`8\n4^](fVa[K+) #̡kԚvV'2 H.Rkj;kkKd *`|pr[R,t X/Ny~ l+K bg&PS$C1d5hTJdT PRP(&XL&t,ښXH)c΍r."c8b 1>w m_C҇TQgTi\ͫ}1jM,QЌPXXk#F=-ܼV(f՜BdPk:15ŕvnAQꕑ!ѪyAbZy`2m䴠QP4px瘧꯵gf7ۀd(Fk'ÁH,ǢH< 9=PdTWEtrQr T]hQZ"NI+SH`rLO-W͕սy]n( ^l4d x8 zu;R'%ԼJ c +(Siu0 ZWb 9F: Jdlbnayyag}sU=\:!!$p03BFCnw)GX }XҀaHJ&yrdEIpF v^0BD9FAZͦ7\ @`P%zr?=ՠ^C!4C+x94(y(D̀ 2 -nl3|7GX#чĤk1*ޮϩ SRTȁN=IBeׂ 5xd!1cr9C /'qN]-lխy Sad3L|$pX:YE$.G"62SLq;uo-{n$+id @V$*Am`R%k.JeppFs =5q<5q:zB9J[Vy,Ajl0a7ObR #RPI#RŢ2MmӇ:5+Π|j {V!h .)-c8%p'i|82K0TR)jv@5kWa9,)QL"mzj'VLjî;KTvKU Z/RS "t8##!M!"v>(%X4, z.ߙ+uW5{t>rԧq\:bQH`I`cFe"2hxD"+$hQp89x(8^RjbgD&ח f5N>%R\̐eK~GcȽhX 2FȡЌ-4$ޮ,\/u'BqS<ZZHGSo4 d%f6RNyQGax@J݂kCK4D,DXl(HxS,FX!<{㷳 u:5O7ֈ42m"!Are82 rur7,6Ȑ̗b'Y`I(&Gu GSjCk>%1&1O2oLPiB)rńNA*`c<@\'IЪL&%x' jhD)$#a0?ϛ8D#6Sk\X BBC<4 (.ZJipI\h R5Z\"$DJX`YtHbV_ط~0jiz}8DN ͨf~hˤ#  Cg{߀u(uHWM0R ! Wzy̮x[a1ުj Ŧ"aìB zJq ~㽐nJ:BF(29QR4'SLr6ϒoڟ;~򄒱t)P&\ {K8%;"_C']a B4$єԣvP$rP\4/ҿ&t 2ɪ ]6qvuPH}hz, LMؕ ?[E $<ÉlX e0,LB0QOʔj-VUj1jyysuo [_:>:F3<ţs:щ\ٚx.}@[Ix)ŋzzcqA4Z^e-~yts06<5>@L4Z&Ѥ5.` }PmvKc|M$Ehiibq97_gqY5j5j7]}|z}yi@}{KЊVu6ןMg&&ʵv:Vy2"02RT*,nw燛ǧH919'(z===֊AM )PAyd޾) /'H2}a?Ҽ}}|puvwtp4?~5(7S7R @VU`GP]1NRUP(Cr虡~R׽X: Gc뛗?ߧDP_#M)-j3N,R2$j7߿|=W:prPHƒ\yGr8o!pCR4B8OXlXUBݿ]|/߿A>m,̔g/w+v^Xfx p,8 (8$(>BڄL%!p6OۛO?~}{?|?|x:>>?:?X/.=~ݴw@a%I(, #HF O(ug7{յfonl<~/8'/ z}kH4Vۢã y4x؊U7IŤ(T&UyGۻw_w|s}wv{[S+R PY(!F0jڞ_]]_^_?`FA@`d?nDC w^>>ݾ>^{KZ>nԪ͢A=+.^=^G}&5-f6;_aւ`x )Py'7wss}y$em$GjwSa+vv-0MzRѿ` V9F֫l?/?e;B dN nnBX@&g9\xa_r.{~lc2 M(Njz54FJPSdyQqGjHBd~~(_܃?>=}|psq h TGcFE7 'p}yNbX ECh#in`S|t뺞>Gq7WΏO?BFPyTH  Ӣ 4)+mv^޿ \@9:ӌ6z0b2-w>>\^AzrQsU BùDJRIɠ7 ؾl?^_]NV#N GR J3b$/pΤn lww7w7P^wNh @Pਿ"I?8%`<`6[Lz7/Owg7wR@ 48Ay01F,lc8V/חjQ_#: (%P_&l[ {>98`E.A)jPCY`O>?_>~xxt1AqynC2Q f2ZV+ 4)H {(Dq Q\GA@ Ma_<=xyq7X 6 NNB 8G'"Nlq?p{KR`yTpt y [?zE֨lv-:X#>aH (Ɣ'v;:rHrtO|rr!T*%ľ0(_P((\=ݳc_=>==|x}zχhwMXt J Br['#ع xq^/7s/S)tphмU|nmmm tB{tD^B+pz|V_#ɽ˓Jt+6 @%b./\]^]_<<[OO;PRhwX|f YQN4ƣ'G'ۭ/K24#ڦRYSRC`ɻӛ+T_/ ._$lQocs0kH,c~K$<|c4}4˝hVc;fofT:Xsy|xpp|rprup|}yu4K-!X[d+/ȍy:3_͍xa5df¥ԆGFGVWdrWG{GǗ'gOϏ~؎Ѫ%HFdqE j0;5OZKy|^fRZ!v| f+kf~pu~?;<w5 RPWHȗ3<TCUi ӅTخQ00U"?JRi%w7wg'{G''WWku*"U)n&΋"K#ʫ7 z#L_ʕ .7tОf!`&sSpãӣw7N/c<#jDrx; bQ 5zju 9.k09 pVQӬRӛlv{k}'┨.d ZRmP)n42C5ۍ(`m}]\X];TJtRl+Tz Ndh5%4zpogA].1^6Ƽ6(jzdڡQ lx%f̔qX&XJOdH8/͘mymy(Xt]{qh6ya\jLj2ۜ4 5š M#hܩ\n2'PKK?g|N0P@008.npy{scI{Ax :Ѓ$'f1;73$]\])$SY@wI EMx$PUY_~_f\-,o)C1ZE?>)_|.e,_|-} f$Ib9#\7õh^**R r.ɦt. \!?Ljۭުޏ_y~_`(ad,ON4#͑FT(JjV+  \:f\aX円 tR&㭉ٹՍպQjn?׿_po#IQAFeH e_i7[Fuh\,kFQKEA>)`R!/ L6<>9=995÷fzk{'''绋q 3Xtalliw??wgN%X&I7adWH}dd^ŗJVk`R/rX+dgff33=95n'n %bC|k~FFq`y'YYmFJ44T֚jCr>\0Bwe][^LlN7C&Ge '5Ti" 5Gldhosm~qr=2>99֪+PRiҰ!l`{fsbbjbj]>X,.w[r4n9΍.UMH4dQe90#أ1:z>l!H$3l*%h4EP.z[;>ݞgR&[%Hn}ݻ\-X6 4a~p;4Eͺi5U3ijn2lVtn_ Bш"լ ,jw~O߽hT(k1NDQd8lX2LSJuxd|jvf~iqyiynq#H FqCHGG4ARDA%x|p,E10@~f4 ?\?$8S4'p JXC$E~VW ^ p)#0Ƞ_~ ?hapKP4 aG3{@Ư?9ΰ .2%)tCl 9-0;|l4]QUES &L,koP%al% Xӧs!',30K!v7$T(E#z7317jB:[,Tš\<ַ{6Jj*zud4`kOdO5ʏ-szgx`myizy.#vs|ܤ,6`E3YMVnXl6뀗v؅d&D"LBh,./t%U5%+(l4 Z_XmLvk|jH{,&k*]U̺MUH,f4xYX,@#HF!_{y`7D%22 & '[ٵXZkfr*WUݬʚ&,Ţf }!Mt6p$ w </;?hH1u'U7g;̓ly~_dj HѕjB3*,Y`A$k&UV.jdžá`$_znxnp".rLsooeu\I "hY[[MUj pB9ZR3uwf`E$R( .#uy}>0SL7;lfdy+\:__Y2볝I=^gӥjبsfYw@UM@?@`Зv~tsDkTJHN዗'{KSCrou k›j  <̈́WtM*$2C%  m ӫj3عwpsedS-ggʭIbg,NeR|1:<f #r (@zY$^%eI6%T}RB@ M\prG>`3\cpowskGX. *T"Rp42,⃥93xH z>YJ8!!1q mWcrpoqq{=wpme xQ@džNM3yH4Q_!h$!E0%_ lcH&A尙D*Q;ƥglc#0R;ͩlgkd3HeQˌCD!g O%pEň!@'H8\%|SC>Pɂa7׽Vws6;wp03ў-Y0,rvx]Z5P.GR@`@ XE}Kر\eLld y] F#Ʌx s5;Fz0ުdXa$%1D;FDl 8, lђIn&Ydh[͟aOa„pD#`C`;M<p<0-zji fӬ;bMdx"Bo&Y+k_HeVݥB%6Rl+ɍ(ǁ"F#I"S$QiSQ$aQ[8km#/7ֶ[͖+092:_뭴&žp3ߨܡ^ d6wF{*M@7Ո|]{"fR]0dy-h͓' wbNpaVeJB0PjygF{iGGi# IDh<*rqY_@B.{̴uskuvdol|w&ՖJD­p,MּVwrryq>3Kf>=n"ma8sp ӡ8|r2H"`ӫ:aFostlqqb.=>>fƊc>ƄR.mz]G wKVZ5Y' }cA<%V|b&o֒e~' rӬ. GFGţózX~q).J=qQ%og@_`Xr2N;K- pvxoF7`s>((p&-ƊN:Y4y$] YY{b+V;:]\>p8> ՛^UΒEfL*DNP CGHh gX"40ŠÈ1YLF ӜAW3Fuk}>:;=< ^aYu[1_MvR/#NLrya88E92uGN8\nxla_(aM9wxdZvQ z՛׽gv7<}NxRļ7 U‡wV6Zc#VWl|{,(cn.hnOp#b)QåX/$"=>]We.acGUlbĒKx6LfʸuъMgڸ4#i{o)i9[uE,P*gr"[csݝhsqeqe9Xw{Մ=԰i* rx:n p^KB$:] FBvYW$ê:M #1f;EЬp Sǀ9GjvƝJ8<~~`e Y`FBt!Zr`tBg]XX\ٮ@ QI1lժ6 l]͂n ܠ9]yY"Lvrcr!}靶pƄdDV,Jlt>4[oa!G$a-NͤXMQy],k +1b8Y90j]_i Vo:we>U> $)6w}k@0Oufzݥl%À1 oj1tYFRdL\X&0S&b5pm{"HFW3SL{wiibgq;=^o0 p݉ޚ]uno: Cʇe ӢI5IIiAF Id9chp9]l&S+݅d f.nj&[*RW2EB>>Ԟ'&'A,/L.6 $~A/N3BjYYE<z"i|`XGO,,Gɠ SYX;> !;L%cpS8=]Aɗ[Jo}e025Qi06IX!.i7S`Zϕ&'WV7ƹYG#<.7ao5;Vp>56:V׻ w!7y IVTJIΡX">UT3[z1rG|Nݢf9>OMLN,-v۱Ux64$0/I@EؙQWhe%#x0Zthx8=5=]ɏdǻG9,L#v6xq6_O9$ ,.63UiOQs)lf ,)yEe1cU1 ^FuF1G3f0*7jBom~D!lYZV&vebkbn3ZͺUעΠ8I * d "h4" 1lE˽Nw2Vi-R0M@8L5݀>6iwmN2iCGL[)D2hEQ f@DI0GN0,fae]hrB<1N7ɄMJ8 ds V{;48dy _0ӒXɁy#1BC{ѹݠ ⫫ 2io~jWۆzIQV-bQ*lC2 n$i|9)jQAR9uop@H;Fh(hn//%Q?sþKϺh" E%QtQb$qiZ_R@V#1ق 7$2"X(*ǘ A 9YZ8Lc,„؜n>ftaˇb[tjPiE,キ٢H?,(~QR)2bh : E'dž[{37sX"K#|4 x+DD7;x9U΍L3b ChH HqV I %Zʌchc{xq[4knM'">@b!D>5Y񹙅Ns8uko16ek0N$-4A4zh,2v76ۧAF4Qg\wZEQ roQ'xR4&gtlr#(*[xk@E F `0#AHO!0ޘ1?m_BT͟Я?$!֎* ``hSL@)2A&ȷVJǃ#Fk_ %ڀH~SFxqyd=w =oGx@DI@ތV˵ف~6Q( P8w)f1 )*,Tr_tĬ01h?H2P#lU (2'F#ѯw8zjD[Ti4x T0)& ;?>pB4iJ?mg%aA  0f`MPz՟`7P MB!K2͈S+ 7kR8$҉JBLN-~PJXXfPCAKzlDAף *rg#yրp#)6 9YUM<^bRYsa~,ܗT)&!"^Ed e/~ƁGD#!iGCF^3m_ Sh^O?br~-G[DHF@ hxT'!E 8F ,r`afaIbLM&4Hz4*\[nRe"@,l0#<"B$ d8FIFS҃@aĘ/G/+PB^Ƞ `RU׽LY$/$< j`._ԧS%d<Z}r2 cn%ETN5E3OXl~a(u͓u9/ˢxɚחoS$fw6v:"ʁa1̚(VO8QO-Կ |֘h1`AYMDGf͐K!eE6u! 4Y:<;2>u_QX@N89RǂiBp+˳~Ưh$%,f GBX<-ZҤH,GbMHQ_ު65҉p0DN~{́W>:x"8bw`EI"N?=ΦB>Z 8PR.N3!R@/\!:H|泺:q8P?RH[S?ae'g'';ۇwhH_6k!n A@NT@Ҁ2D5c2/B6._|ؙ_?-Mͭ}Ӈo~[sgFo̢$jQ+%l06UEGBRV>ߟ/__}w?|7OZoyuw 룵œo(N)0 xFAPY,ȡCTVћ_/ן_駟?zD{fr33396Vo;F~k;+}zۛۻݝ嵥ngjrrgFA@0Ɉ@oFUWVgL>/ֻF*ȱ%>f>4 hO.__^ޞ^o/MOLMLN.noxxw?r<a)p;5}tv~vdG3eífQkW?~ow'+ۂ/.ǀ*1oZxxqpkU6r@ {ihkO/.7{sfn֝6S &v֯޼y8].g:AlR%-4bnچfBE>{FރtW#I{7g{Ǐϗ>aQ 3Z-B~ Z^9X_w%T`BhϛR=6_>?Mb1VЄ{<޿}݋ӛ뻻WO>݋ݵv-fǔ`ht\vosw;9u>($Qe lM󺷰pvITY5>~qyuxvz7޽{Wk0X@\eyw"6^z'6wfn|0>@xYy\ 3fz䇏VO7w77hp0뛗o?||2J"btA ffAt䬮\߾yGBZ #xD)VeU gnϯ^:;{ӫo??JY5IV$Dd"J$"yOcnAT˝+#l/ @$N& cM"iWIln޿{&v1J$jj aKt|4Hɪ|tw{}uv~.*JH=܊Va@2?`>=~~_zf;d6;N/c@ н$4NpTҡh@5|ta? :ŋJu6"ҁe޿y~o^=zbf]gJo[}*HLgd G(`o˓BKRYxpy?|O~ׯ?=gyD(*hT`@FT$RNLnE-Oh++V@HI*plk4h۷}W3I :}2D0,oqy=_w+*$|4@o {zݫwU/q*j:!48750r%Y,V# >pxdo]/V> 7D^߿~|~zx śv)tؘAgۆ(#43;74/6T'z`wxt6fM0mՋ0Wo>=%T#FҨs G@"g{q|8wv:RǼ4bcqEf1vӻuL,$ ކ/(.|-<* XdXyeFeKf~ws~rvtqyu8r&6Q4<  - D9q.FtlaOEV*R7+ᬣX 3,bͼu|`6(ɚ͆3*3H9qE^`FV4YUAZawRT\hAy&GRH4N]^pux}qtrzvxqqp UE]們P&:/ΪjÒ@tx$NU'# N8U?KaON.N^\\]^f$N1)tG2HH^)Zy^5[+>_ LфoP6GH7*/^An1Y]n>]^=8=Z̛$3ap^QD!Հ,fn2[] FUq"'FR% 牌YY㳛ӣcVĿTPJ| 讚6) #JEF DRۓQ;{۽˓ MG;#z)Cdb4ƌooJP Ү\= 7*vps|zsu|y}g @}l@6TMOgjw`ߢ &~N4`#ъefRZ9YH,\^m^ߝ_\޷4`qcrШ Hn:],Ma:X`nͬMUA+YcRڣ!`F;}qyzzaPUJ2QQ,V!?=q|05A,ɺdTZV[ LA$wvֺ+7/-،|Y N[ava%M~l})2_".3lH҂-Y%l2&@2,=8";&YQ7}yot!gU'E$Fc 7K~PKK?v$P@003.npyPKK?gK2P@ %010.npyPKK?m< P@W002.npyPKK?i7P@Xx001.npyPKK?E sP@W000.npyPKK?s=.P@007.npyPKK?h,P@Q006.npyPKK?h*P@005.npyPKK?d'P@004.npyPKK?~л1P@?009.npyPKK?g|N0P@q008.npyPK Gscikit-image-0.9.3/skimage/data/disk-close-matlab-output.npz000066400000000000000000002672371223313777300240350ustar00rootroot00000000000000PKK?e?S&P@003.npygW[Yy;ZsTG$PPN("Ds29{͛W3l 0skCn7gI݅?O.85+N] |*-/Dž'O?Q}-n<> _]VvVV&eY FaaaAAg>Mw_|ڒrfn{NSJҺķwtG|v ~EE-7-7;###wn߸L5>#ޖ3x&++;,pPpg>޹s$IϞ)l≻GN'8Yq)('"gd5p{g{-BRUR Z<>|p$#;qD {@)Q;:c𧻽'LO G"t*-  |Hˌ2ĺbCG6Wi~ (ܬ"FAa D ?V,33ˬ, ^ ,yH$DyT&5JDbD Hd2B+q/lnmmMUyIbL b~5xxCޖo0AJ $lVjffڜtfX& ~٨ozVk96IYM5[Gтp~7mmH$n áy m64 [CA=;|I{>[#'[[áP[[4 b#I^ήXOOO,vutF@NDҽ+tzc}`=r0:ZP+zH; hWtvQa*Ry޼~~Qݝĺ$q::BA/,$P@x~/q\{{;]z,   `,|~Ԯ^Ї>fs]N,˃iYv riwaPC0pk6rh{# aw%$,֏ >^a3224Ԭ9T*rIR+M2YCL7\֨Tzfuk1vb09p8='-P ^[í?VcC]]=e2&UZRR()b`+.f2KY VyUyyu f\SW"H^ߠkhhKMMM >z~`7jkFi. e'{:P9wT*;paq)-GkaB:M=T8Jy[Uʪk2o]wF'{ntJ @Gl6rF<%ҥhOǿˡ)?3pdLn"Jl w -zo6`˞lF"j0yj0ڐsR$''8} fs3x]ƞOgk J@q7hw>x_0s07?=&*Q> B!%.YY EϞb7YRKnQ!y̒"e&`,4Ad:1(hȇz;~%܇i) UUe尺YQVZT\T!)" O>#/cFA T ϺcnKE'|21a{7 #55UUUUՕeLV)a1KY%ť%LfI!P(,f2%ܪ**}Wt}PF [%bϟ#O/pZPR[ 6er&RPX': I \^YzXE ?o'~98leVV[Ĺ #w|qgesw ЙLVDrwғD镸K$߹Oa>l>Col. #G{}ՍXv "oD\.ҹ&5̗ϟ%uƭwE ֠A Ց!@+: Av[.! )̪*N̥MT*)>/tn}Ei@T3Bf`B5\ nyuUIgm(n+dJdy bJAS (Jݻ_EA$ԡq0.Ӏu T`㭡 {4ff&JV|E+*9(xzԇw>_b#By7 -Ih=rX&kqzǠ(nj+Cr{2/>jOPVJR(' q!@mӣY%/{q~=! \ycHQ͹LFbTm:tF%E%%հ9T)/pkEX,c 0|ͮ>lP-?UU~>11ԁz|Nz#NU0QSSvi)PBʂ'$k.*)/TVL3QAc6WtS;S!QD1UMqJЖ__ | * p>VO'U9ϖʊ3aA>߽ &Y,*U#EUXȗJN 0#jy"YJ+h|>7-cRKcX͛0+".ҬUi^{|bV DBQVp"' +.R$ܗ%l2 ~GS*G?z7p{~ d*bj_`Cyaz1,ZJLAA-GL %F>4Y܊/闒&G} н椋III))BE jxt./µ!5O HeI3N)QJBxVv{?]D#OykW%M/Ian:f "U7`+kxR2LOFɞzbfJz^ibd%U*=fk^Qk_R{)- ='pO/%ݸyShϸOk2P Ph_p[f^eZc_yʒrDzJJ5 ʍwSqSR)bV+ãHGBVaT~1xL"̎>MKL,GGՈv_Jx[p݃\@Ȁ[F$V)esEJ ]N'xnT65U>?MKK+U~J{Yo_|门a = >wnی" ja|Wk4ᰟɂ;$a/|H?ϔ4[B?惰e®QZQ]xzVMGJ8_ .:Z$~:$tJ]]'DWQD=ZO@*zEE [F-?4m6+YT  Tb5I%9~fYP]5T޽}jӳJ"/5JX%)~P__/(x@WTֱsPD<>J4441(KI\=q?' r(kk'9ŗ+(06C6 vt=^S {cc^zZfccfP̯*MƏ)o]MJO"x?)"tR`BMbƃgj477቉APFB!V 26@W ^}dhdn[xg?>J}UOkٵ<鰡<wvvt|np@@g~-UȩBeL><<2aӉE|xY㣇_Otp"hPsBa=L>? h;b`b`6CXt4@rK܇NCV`T^Z(h.UAF-P-O=9Sw X,O @ tv]ڊZ*i|lj^ɃֽEp8q/K8bcSq{ʖVA$d@ooWW+;/h*U,6 P ØB#%s*K<~ 995uiYL_PPEbSK~oQAD*sj ^=N]ny/32T :dRj?X{YP>O/Z@o6)allhN+z5M$o( R1og?@@̀>>7r=ɩemVZ?w>i(%|JAuz^uvuXU,4gXLB?1`@F1w^t((Z''g P{e5575Bbͩ<4`$ T!T^[Z\H0*$38:94HXwﱘ`TCҩ፡ eʀ.oR¦N hRȕz% 67?鱡H|K( iXowpXLFPIB(QI$ =ڍ*0N?.mP83994 Lt (Mi zeX :VQ)r"`{ 8@&J-.ln+ `rx&)D@0317k=>7^5!^ *4JqHGC( _z /LN IօщX{hr|+h ZJAm Jѓu~8<; `zz|doOL Op8 {d絙v[E+P(@:<i@n!o(_)|@)mR7[m&ڜvg3I8ʠҨNWp_d` 6 x9D'Gi|f*z;wN(&ԚfqD':N]ol@{`WtD{Cq11`T`sM=U-Пv ߿  LcY;?A)@_󵵵~86Qo!ר)?>kj*k~3yOBz;za p}P(h%=b6 FTufPX^h=++zxpw4;;= &'?@A@rBv(v' \Guz>8édrpww$m+csӣX'bn#vm@3-fEo]ԩKt#[KS4~a~v#06;0qY;\~nq}rqm7fstiqzbJvTu ^o_Ub|?~qowk_[^ʓ9إg6>ooǛg/:Q'|p;Ua "D%fӿq_ LͮsX./a 6ѩ_~m;@m3ӓc=]mq9`05,je~) "-ڸ`e3-\4o\u@WG-y /WXlߏw`G`jfajy(PVVַvquw&E]F~6Q019922?^ NӀ Ա\AubOX,, H_YށfS4fΠR5JŒkh> hK0z3#C}=_ ,Kv+4z1lrpBǏe孽NTK2/>IO2`8? HO7T P aL:B![^4%)͹O[G[^]KJ>Jk^VZg?looCEQC=ݱPik6haM &0E90d:fT&;^,)))~*= 8§xQ5%%'z<ʕYP0n> /WD AN;[|} u?w:݁@#P? 0gz맏HZ^ nl2`uAo/rP B`MJK?@7H뗟(`UYf33L@P `cc}}cߟnUDOS<~iW䠸?: LN ǻ`31a&bMg+(lnlmgAB<z翪0yw~1 *X_Xpحf xXTv>l[8cpTOq/߾# ۛk>退[HxEОYP@*;-/ ~} OdaP8)O]1Voq,Z,7yUVkM04}p& LhΎoavv?ZOmXƐ?nIεAKMK駗y:٪smVaUNM i>TԧcT@j'va}%oXal[__\_IL7D)nwX`kkG- :r :4OxKe4Zu'(@>4wbnH,r /P{|PPDxߎu;QK8>(X'8ο~ @"~j7j)/B~YU'Ơ4T@y P[/]{-._rW!:`bԄFЋEE*EP~ X *C7hDN`>ue>? EtہSF(:,a0"#[Pm!)| nMtke2}ʤ):\>fWxUaQ>Za)ђ]{_} m@1¥>XǛo~?\h+Ǵ p:lP[-f$%_~ilQ])?+vUF˷pujtqa;Uh`.BH$ޙo`c6Uڅ y&'_M-<^/0;UY2^F9#3vLF.qQ_>Mh>{.ᴀ$?/T7}i!gnp(!LPIzB/#|*Hw:}k[S I>O;C P\$Uv5IfP ᪣Hsbq8\uOǿZ6[e~_@=\1]0H@ _ؙS\\<_ 61rW߀ϛ^ć$}tOZ@gl;k[G]xce1#;~Ͽ_ӌsz+zkk8 Oݳ>|,4;;r?o;GRvK^K:1=p$ p]sHD } ʗ/G#.u7֝Ų_W/m?wj.+N?;k%mMpדL MoPϟ?n- gN@$2U6p"ſ~ ZCq #<xX:8| G0[}N!qyq|S>D… <-^~Podzxmfg?|~z`}.(-|ދ' x( h> H~k!aZxdjaqiqimg\XUx( DO}>`'tz3U>ճ[l #`est;:܇{g{_]^^§M O"C:@`F[F#cm i{.n& lHwp@e@=YԳREBH~Νrr~롞S c;3?21Ovqڗ\/cQx:,|X<_~(;~H;p~NB|4xX%/?>>]][OO (e>ϯ4>l]tl҂c Z,/oL,a^e!"ŧzNr1L=$s%ܰpfWN!폇[e,=K*j* xGA&N5*.7wyHDZHpڰt -@ޭlQtt{[+VV. O90,VI #77/J-Qqk ~ro h'>Tuf>`gk8+m((#3ɅB#++ s;w[ޓNZePa s=hwbzvva}|=s^:}>c'y> Hx+C\|ϡYy {<?PKK?P@010.npy͚rYv[?v#j^9 {ᕣ]GUV (APIqbgAR 摓T)|νy2(B"ι73o&?|ݿ=}w_=zO~Ok?=kw~7#W~zD^avw\nF{@ &bZg1^OSr)×iHe0,_*0 s| 0/'0Krwzz0 K T G lK =wͳîH(#H8`P8 AƎrla^.8!C @{Gn$'I/8BAH(D(1\NfXmpحv/@PP\lq2JRD 3Ž'85\8lfNg0 zh4;nj8X 0 /JbCH8x8$@ Nʃ1[<'I6WK͒Fּм\,.X& <p|dCLfrX]x=_aby0?aBfnn̏?@-b8*s$M\ \lmXlsOYQ" h\؀1$W~O*"qix?ȗooq?dz,M ʗ= i:c%_+ __-^bǟ Fl2鴘qm{otz=+ B%a7oR~6m^i)zLJ!( _.w{|*1~f@*NeWtd,D< ].dN!7@'y,&kp&d ʇO'a7K$y"M$`6`Y֟FәӫJd&̐ <$@}m~4@N+ ym7)_~W-n՛t:%l|rr 8U8|pqQbYZ6r?V>=h0?z<{R(˧'\6Ih҆GR#{d k0f,xP(U)Qb#GϏ fxC\.J <cөOfjpVg"+h@o@=|@^z 0O˗+%&jOzUa@`h Q'վ-/#o䒤iQ $ T(;4:X}9 c fF_("jz[B?/2~6߂u@ $U|G ;9b sO_[ŭ࿼B>4 qHr'k~TC;ڵeɪzqYz7W%@pWlW=g1ha}ee6·]!u ^''%!E,^e'贚UW @dؔj H؜j:k_[_]k;D|@?qg]Bvv p:MRiTN rN8˲ 'cA/10@ak:lllBF7oQl>'08pVZ9. ;[-`ۆH|d2Y2n [@Vq?FE1P` &4n*W~^_p45;eB4vspaЂ1g9?xsy~;JA.2wtڭ-o o ]xJhbpA:.?},k|̠Brd4͌-햴|=n dK d!l)A2d" N mfmDkxzC+7e0x& ÀW+7:65 ԯT<;͟2X$wx_mX]]Y du< 5ȵzm'@.* 'Gx9.3KiHZj7+6,pIV` ,f \ |pC# i[m0^]Kg0H>:۬8(yBLz]t #qU8hf3)< .\`eQ,qtHv( Сԡ )F"RI|ۛ>4\׈A$ mY<(EgGb@ pYAnw(3~QnF8yTpx8)DX^HL̀:0 |,oOUOp4SXd}Mˇ+$bfE[!7|,QWo/0poAp7| |Y< c06fXQnQħ6$Ƨtʷ+|ۤ##=P`d#[!kXpww@zO;o,/%> PpO㻕M*o{ ܽԗEwZM/?{-htIxWϿt*qCO?~} ~ݴ/Go@i<0VG$vIOio+HE|ra̾wooy!=~[A>D> ?P㽟+< |VDxN@WTssw~~2 oC{Շx0e}U_~x=J|6~ׯfs-Gݓvyd`>D;iXxbb(beݽMdNv&>djY~i{=/%xOQ qpv={OؘNٙO|xg+fśFs'!UIoɷ|K?c#)  Lv{ pKpU?/ ˷܏0|P$F J}<{Fo(^£ dYZUjuȧV(J|]<_Tow[zV3iU lq0{Jx" /wY P(Cax+F@/SSOBICB\ ۜ.ÏM|W>׀1|,_aS>#JufJ~4 JF O'u|V,^,pJ˧ _PKK?:"_C+P@002.npyg[S|n}-^TTEDQz =B I  Hz REXk| ~s]3XKF=Ӗq'-G~))~_ !/eºa]I)A]C)~,(-ŷ+$4__/\W^oddV~~Fƃ쬬LWXX\\\TTTXXXM&߸q#VJrRÃ/\JRgPK**rR/PIOϸ?zF&=6mcNz:J||\J˗ ;wRA TEp| z3<Ld1|~~jKx>I#W >1dž}C}^Yo4Ztʜ{i]AzW`x"x@p'f n$&Gfg&sk+NW W(8g0ox=}op`h1Vo~|?48Da@ ]n\ o/_?>|CCёQQVЅcS tF'&1GF''gP񱑳?å^ GF'pѱqG8$ffq 0g @1\`L` ?] ^o|@FǨc`W.,.,,MQ[/4p`>3ٹ>ju`"`8i٭v͊1T_?z|]>:щQ47:-:Ij,bh-c&ǧUeee%Ңb^IIyYyYUEyJPUU# u"QX\WWP ʤf9*}腀hԨtFd4 mZԒWEVD G2sf!g C b9͢u19!^"444T*Ix& ::/5fA~FNx*la>#[2D+@fxd,JKhaǫ×63IPK$ڴqa(oܸv5)>:(2444gd= b*&H^𹹙oGGG+WCñ#+/,E:I&|H<H3=ȤFa@~>~%~Ion./щDgxN !?!!A᱔R>Ď.wVrȅ9y,d4? +k5)檪rҌE_JxD Q"#bcy$ s_Bf"H} _PEjm 2rnMCq%?h0t3@Y @GmV F]a9 4ܼy3]'N$&&:: z#F_@{v;,^L^Ua@*̀@2B !4&Qї W^Z╔cRk#NY|JJK ˫>: 99)E5y7R pҥhON*++9W+-)A<.a,A멢ReEIb&P.CQƢ/;+SjAϯTTWWVW@h)@ 7/ 8v_ Nu)_.ݼSR'jQBT@*+U(+*7(d 9|iEee g ގ@6ۥv{9an>Q\/aU%Z&$?+G_~<%yXP#/-r0k vyzGF^&|XX~ezJJScc X\+׉j|tKoOWgggg&y{t:tl/7[R^-jj7A !@x& HaD:U ޝQ]Т1Y]'[ذl?66 aUr!PPP&e>T*BFݘV1snA,yKD GN#`Y+.䗕 $.[w?6yPdY-i& P[Rvtoibn2 \s߽WV  SJR+g i]xC҈dһ>=X^!WνS 7yWJ$7rx)*mFIAo߹s:::xXpaMD~~MG(K7J&!WL@e*uT)EE.eIA׮h@Jn+&.RHwQ+)1N'? q+\0<& )ͥx+CZ!`0$ +E "x)LNAVVo[C Mc [|~:-[e77^MxI@K(͕6* "cKDX|vlxlϗu=MdVwpx>_^+NLl֡(R5j\Uiigo.&<J eJ %hͽ[~4JVábG $% *[Zҟ$@QC" JEbZ /)D2AW$j6}zI%JI:NB¦ˑWb*[r&( 4Qj [MMu bF%9$Py^ZDQvH^Y&5 Usn{rp0'P N h"ĠĔȩƍ@55:๙ hH\NϹ~kx\gK<]gkI0hi_ /hr@P$ |YO֖f4mEXU (iA\/G+O |@xMcK+ooGN*kR *d37H V L /pA7Ze`&2ZNZn&UzKT#-@S󫼴hCCCB#"  ?rO:Eь&Cс۪ꂀJ"[G0|p0:4x%RlZ496'\h_W‡%|[‹CP(WU?Lp1"~=&VT[r|qC>҂FȈ607;;76:|-ݺuK E 0<'pŋ#.{99Uuh$DeTٱi( {#'O 277==6Ӆ.cȔ(,ӋKOww&|LON |%BZX! +-lJX/.>yxW/ |ia~vvr|hqx[n''>{h4ժV9FE@AR|̼Krae`!WB1+WV֗66 Axd[L@h~*@2di6,LkUt@M>zeYPE#P.u={-˓L Uۦ~]1{=.l7tXT>(6jk$H0lWF[6EO)\_{ÝW1?>& nGF5J i_sFǧ'F;LZ-Q/5 [葄h5 4pQ]@Ʃ @`VW!0<Pzxk5L7&ch#W/N=rhLfx^ZAEqP֞,cp :m$0`{rmrt |}7O~`t[鑜mQg1 (Oz3<Hm9<3~/ l0:22ob7T&Y:ݍ (!afQUsxNoh|߀E^ܸ7!0 l-I-&`6:hD;(FZ3V=  xQO|8>z{szjsCF ᇆ0Y]P0@CEсPi0%}~cXF9,niiN'&@ 74 N{d0Z}'N? y%VWg 02MYsu(~+ uz7LnYL&Iex`6כ`7+K!5zr?:re1!1&U˚WOx]]6@3όD^gt"2.Aq24}]\_N? <^Lڋe&6 xcnr;a]~xiӹ1E#`э`4 ;"AMU2`lm"]/VW^Zo\{nx [^1667_xśϧoO?מ|&]EdDDΫ@70s{6LJ#;gg"PvpsDW"~ۧƗo?6&NW$.v{А\`Չ):ዋMmۃݝgty,Lɋm [59oeﱚl֣ `ԙw:Vk!¶7~:A=!u0!`ZNc۠ө;9+ɇ4^<47bRk[9:'7I+FH:ão߾]cLUhju[L^̞>T֞=]Zz\KnN,P$úwW;ۜԳ̓w޽;?kn)V,㣯`tkȯ֟?{4;5|}>4SmoW*ؑVE9B;{6;dk=oiiףΩQ\};.:<$"##i!2 ̡I F#VQ9ήnv.~ZWToZNt­4Dŷb⢣=bsû:ng{k%̇ɉq`L]VfÈfx ew]QQQ}eI]Kyѱ(e%\W6Ǐ޳f@+nm?{DOOxzmH7uZ$`ޣ3J+/*GLii@|˗\ \OI{Nԛ=pD% a"~uy.WG#lݶnh!}o;OW+5?×/Ơ⒓o&$݊OHI?O'hULEJ itDcfw~vQ?\[7 ;ŕӏ>PG`mD@ubcro@/eTߣf}?4z{_8v'&ܹsÓo_>~H-bP/N:ft^.o(.* ~85o*%{M ߾AC,tx0-8ȐFCOL\:&$Y-:Tiutp^:aǃ^໐|szϿCoH;x@Tj.zXAV x\fE;rBlLJAnPX'l7?{wY&?>ZۧEwzޞ|PΟ; #HoVuLFlr2oimW:~fݶ/+Hh4&^eo*8c=,ޝXo@dxEa}zV>M_PR{㏿z$@ؕN3*?4WjoFL+gE=Åwg|ǹssrD\׉ R٤;!90$?cOpxƀYr/_~rs'>r69<=Slcj:ix;(>^T`Ix2߽|eaͻO>ۃ* ;kX{$YXÞjwyPi`jGkzpN/.l?|%ݧVF›I܇cL>3([/Q.6(ov&`v =~r/Gz&(˻yrg|*XXEyę C!{XN0n^i {k 3!_z GN>}JxO-vjtȩ|x54I3hʝg!C gDlq Bꖛީ[Je Kv`{i3>1^EeE1/7+rt:)n74>ݹq@ :L iyt8gkt+TKF 3J#F s/)u]=>)mb =>&b <; Y|^ 4Je?, !E{JCσ ~lmZȝ6>d@N@H|~AA<P- Cd> @/"G8~Oe~dt&@_TSHx +{1%F';YqP—;n}lrx>i$WREJ}:V?BOZ\Zhw\E]#Bdޞ3ɒ zjuxۇネ᬴4䕕Ћ^w\!P_%uw<L%fZc7 e xLdݦv_윌+KyfBc\磮^-Yz 6@ԍk#;l7ܾ 9و.'?b L"&}=\+Ѓf յ7o(?75v*;oԼ PKK?Ke2P@001.npy{W[[ٶek{SL49"$@I $E1&9Nsܯ_WXo B1\s9ksKr7ՃZIAOҠ?=k9-ZzXZ%UaPpO槻?FF5b3YL&(/ǧ .UUUq\NUƋLfY(00N Y?ן':.D$-M2/*(((*cd@EEe%[] JN%"˙x~JRRRJjzrjB\lX|||rU6O~%~~bvM}^!5_\ pV9`(0pbsY%T'%&'''EG|}aC(Ne6*Vnr# ^X]Dwbvqhyyy K,//+iͮl& g%EEyiI?NSمىAj6h,U0`A%"jf9,`Y܂̴ᡑ wBCңJZG4;<3`˪cjOx2ٕU\݌\ >DMMO/ ,SA&!e3zzF7w?Y{ 'x5ռ*n%[9쪚jn_(hjhT FaAQeᕃ@MV%m [zszDǧ' ЩtzFJJШZ^4t:v].EaC_SWS㋕ZJwdrEJ,(H'j ^Bc=Q+zt>g_oos!J515=9191b=zGəɩ٩)4e ?Lϐo'''Ʃ٩1wg4q/^&'pi11{''&&ff1ff橱08?80 :K˫5 kyqanfKW4 >"tX^𙞚[\UŅE,%\ kO6ˋKK,hH-{ux(xauemnnfb|1^G'ŅY@_X,J'[+l]x 8B`ah {Vd}clthG@d 0)yWL_Z^Y^'^[[XVW(7mll,S<6𱽽0cM e0 .Vсkum1#g::9{{ANFcq yGỉqxtthbybtad;UEhMM_.+M V__['VskkjyE5:~]C=A"jiDmX,JeriTT)jYkFiZAԶ~dغv,nEeTK+He//ŧҒ¢ܬ‚|¼ܬ으̼̔ܜܬ⢢¢l)U35rVIJ57}H!1څas #&28</岲 \ "Ǒ  |^#Q?| _[]]B(}J[;B0h`;E"mҢh ?>:-FrX̊ (J6Yj^RVR\J ~aI.WIqq %佹PHJ.W!m1E"VVéf [ʃriw_/o74qj,Q=Q+ĥ>00Y8iІ~a)9Г Ruq 3P$ꗊ V9p;*"N.TfeX,$](6;ݯ 2.i~L_?`hǰRCs*a,Y\JQ—% 2Dy|\(cVr]gai2b+3sEFFUら~D E%TUĭPwBLfA eem/ooga ϧ?ĈʊA&&:"7<<@KIO!WQGOE 2l^̯'qz9Ec;]eeCB\|\,f>3?qpDrTQmRR=(OuG=_[[VWֆ,!08ܚJe{ 2 pT%oe3^AQx\X-"D}|\.epppDQSA~RUS"%+9"8"f?)A(4 (UkuMIn 0YdU!U5nb?EdU)Լg'%E .T&745 [¦&Alu5u|~-%E`s/ d dx\NUu}Zg"0>}{;#;р?0vjREˀdUW!#UVdD'0KS(|xRijy5\d"$jP`o1X FR/mR 9 dt_>>>4.T3 !-Ͳtz My2Ri\."@/ƺ~5yTR+99IIRs'66*)s Q.hkSdfqy>iϏN.,drW#2.||AnCH.EܬQʕRH,<xQZ,]pVjl !jMدw@+U&&vޮ2D*ƅ ^P<(ihF vZ[ZR!WUnII9f8kD𢭗W/g'R`0d.إ&TV |K]+39]&$h1ꚠaM$jni S{UgrQ;i`5T-`{gϔZwR*%(v@Й&0+&d&|j)E"qH"R::@RmB+B9oJc;kcښ{rMg"ij ҢcjJE` (eY($"/RuR-Ž(߰*fUN喕_X,h`]+) Ec8$5k &Um H xD$ÒPЊjudH,(HKU}|Z Zzi;b#J%e37%w1F8F _q(]X2a )h:aB{l[ K ZHH.A 88 aŃ6<%"6N{`xoW*H)DC+D-hi՝y"MS\|Az|XyTR{mjC`G'$< IWGD{ 2餣6;Z b1Lf}lũE)YS3RW/#4z§>::&>.:<)~€ZVmWId2~T;,&K'ڡSKY)EQO "!!ծ&҃A #0$_7ȹO @އ"Ha3vM>:??7>o0-H g_^T:˯*-NM #A &.om77d{|xR:+nm=X_ߘ_|++-$<<5:E~kkkǯrќV~@rܣGaB!?N)`d6U,)z*E'sKd[;57t.18iMCON)ggMhheBCU1A1 KB^U,5!X2]h`ƓյՍ幧ϷAɓՅՙ~pllHR~&=gPϯ>=?S*ERT#fܲG%2vSׄ-V(Uƭ S"86766v׶vvvV׎Owwmo\__\z<NyylcAZb]4hXz|&W*Ɏ5+LT-MKDNO@MZuCMC)v67vv?Y;9y٫' 0339Vyi}y/_گuh jNN)[]^b2*UD ]Ů(ZTu<{٫'G_xjgɓQU=+9榦@UQnhs6KrZFWEe[ ja |̺k]z SQ)2g^a_>| .;O66&4ܚ̔&OR3r&w;Eej2HXiZښ!(C#-`oo5/./OOv1!ˋS^M[E]]`8?h贎L 8fR:d͜f!QG%wQ]^N᫕P[G ˷'GG Ww :&C=1!#!Ak../z@m4ZZĶYI[ml;SoВepg?#pY]Z"F:wrffiggP-NOPK#:KNۡ ,%7TFre"E6ʛ#}4;;ROw)O@[XA B.lJζVg4&0(v9I@::9=>>z)Xq+ ʗ67>}u0p8 o[gWf'GAcQ%j`ԑYF2]?`LfiH$Bf>99}wg½G1g{[;^x{s43Xc!*u:e DMvw̽l1Tr$"5so޼OOv"܏L_`M,z@3D舫ܒuQzBtn69B^Vr[N'PKDo.?wߞ|ؐj=Qs/|onon.o.5t M80T :'Udvojk;;NnOR<.nf.BaǬ#Ϳ&>;W-/̼X=;$ 7dmq \3bhЃ.HX,l<A`g %xk>?{z O -(:jvUƲۻdŰlxԄNw;``Eء,Z[Dz~M]g@Cn~aO=px`$?Fىq`iﶚ A hh~f_[Kˊ Bsbϐ^~o_.|rqtph-aao^ȀrtۺmG]P_T, jjyU첢Oחo߼zzx/v_}s~~L*E_urӗG񏣥I(V$Ğ='++ 33cȅںz^(Cc߿]?{r{{Ký{/_"3=Vkl>pNV\З=݆^BOW) :iz׫7Gv<48|sw ExKo$ ~Ibp܋5񱑡A~C.mhI ]E mdj7/ww_9>4}ۏc,VqcRܮQi;h }w{g!=  %z c5wv"f4N{zo^'GGvNewYВl?__@x }A9xszzzų'KKHiÃa@r[qovOFNȭrFU[Bmmn`Drf>HdbGv@F 25>16Ҍ ;:2jrn:>ۣ7ggo J#3%FL6\|P$=0ĥ_~xxgO6V34t9 <{%%ee%fd /? W77WU0 Ϟn\^dw/$Df{ ~_p߽O??wk@HvaAd +@dbzzzFrZfRrVV^>9Go߾~0/|Kru؉Hٻ{{z<^DA=)AՠSCq1 q i>'8?;5z}G21`=d ̦NXLl.!aH^S!(K  }q7ٖ MHMMO#rrrS㢃}i~[woώ0Ń0|s9{/xCuULB-߯H=ީnʴK-/JMy#a? MIOMINOLLNN|HMV߾~ti,aH7,FFPpxdD8p9Ào٣hดtfdL--viKOlbb9uGj]Ono#=C&u#ܻwN}qs󖂿=nmmq߿7 8&&&*2=-?+/Y=ndB4=#n Qe{ p{ =tb&U+SK/.>wzszH (LHIĠ3 v9pԽ^ԧ^@-G2.H!g$A֗>" _.>^ݛSW|`@pHx!r+5 LmNۦ'' KKJx,OS#wqA_$hѵU>mл˓)߳qw?(*؏HNt;jR-;.-/--%edIzV ]Ia3/?FĿY7g HP~ #{ ?04`[v۵Ҽ2nu!PVFN" tdV4JĀnm.0ޭzѳ;xdGB8 $V* V ɩAF*0YagQ,Myyy &V%wQM)F%,tӵ DŽ@:CBCFQF#~!4W/un+fצK/grk#wg]no&_?^TI&7J,%6cH&'M|gJb]ա.IL-jΏ&)x1Bx_~E\nCi!|RȆwxvxHt.g7C`;*?p@''25[ğ?t#6x˝ݷۯ__qC{CTFr*"^I.lFPA!=$ǷJMKx!!!Y솖o_>;OQ4AJ8?\@R~/@m2,ɠ"uj BuYO}td=B(~7 Ŋt$K{@nwAOn1+qwzf<x'y&! Bac[;,u(&dohh ÷n˘Onׂ%4iuZFM=C@$I s&څz&<$ͮߨjP>b~~u ͯ7{$-wwޟ#àTd02z@ECr~MA&Aoߟ|mhhllx_ze%޷;z@x\wSGQM7g= @@j=ZxhFBɓ ;x; !L6;R.F%mh:W~j~ϷnIk+B{?fksT?-lǜ:zgf&FƐ"` ^r |3t^}$n۷vRZn!D$ji sE͋1 ? ’ z?btCSSS#ɱaI'dGa!Zw O(큜$@T"jiJ6kNG %6PU;11151zHqEQ~֫ͽw_~۷O6A'%2 D%Gz?)u/I| Y؞ѱɻ'|O GN]vLίn==z/h?ߝtiqqqIEFH{U@Ӄ_A"^16C!cv fcէ|%o݊ĸ$43zX,ii+Ěu` U@dp54 32B@p`F+IƦ헇ҏ^}IonnV$X)i9bXDre?D\UHRFDQ!TM&fw=9>~5&n íf1J@ UU!%RH S3R#R34::[)PmlDt>T]|@ I l9]RRXUQƬ'm BSr}>T lhϽTS!((ՊOk>};x6U`*ɳ-mJbLR|OEE@ꥧ(IzsR$Q(]/_>ܼ;-%S*xl|0jE L"uE>9rj& 2D(<&}:xòl,oo?|ӧ/n޽vu]efZއJWD $G {FHkL=D=(K5( }Éέ4JN/> y:W95 N3[R+%75EA>@*CbrDhz(= *( jwّmGG'7@A"2S@zady1t<'L| 3<1JYO!ҰzGIgz5;xD)HId2ؼz.UEK$ ,8ÇH Ʃ".`E@&A*''2&Uɭ`Q&>4vDD45Og䤗2D'<.#Þ>nd^;<qc=&/zSR3s(bJ^BDH,FXXht,<PKK?t/C9P@000.npy-W[[k.xmӻj sYD%@!(#I" 66W]U{?}ӿt!&y7CU 5?+*ش(^%Ea;J9O."UBx[!K+.B'<) '"ȠQUhofffS#dxm6>r9l.d87+F)D,"&vzq҃{Q9¨ɧ$xh4 Tȡf2jjkꚘfŬklnnr[ZZyVbf`de&h"KHU:wNz_~JjhoJ$Sɱddn{ ҚZjf7775Kp[y6ᱛ9M5Ey $+-=!>Bht )u(mZ]UJD%׵K8qhxll|b22=86IU c2Ml6'00uu윜dJQ#<437vyVӪbN s#V9QSUSmb56ԃ4ě YfFUmmEYqAvNzzrRBrZJzbRrBBIK д܆>wdaemc+[;[K{G@8^;¢ʪfVcSS#r8ںZdH}mMIQAQA^jRrb'ĥddg0E%JONDf6<}P8 g秂.].hoZx\V+y6agGwWX%sfvCScc]}^^NFBjB8ܱ bwvwvvwX__YD[A<?v@MYCVj!ˠd4BͦAt;3! A0111191:>>5 N͂G͹HdjzlRka&VK, ;:PB@H!uEbX'dJB.T~R=AkAo&hi#9=nf^76A#[UV\ZWX\XTX\RR_\XXTTXRRTR\TPPT<V%5pTVWkj" Es㇣6jivπKH'%4B/eTVUVWUU.(/.@ZVaa^V^AQaaA><x閝 ]?.(,//Jݢܼ*SvzRRZFJf(:/GǥdPt"Eks#<5640++aVTVWV,aVT.,-+,-*+)T_WWͨS +TNYQaΥk3@'`X%h,DqZ8hQP__Ј 02Ls!p9-ZMZskR76$}h&ţ1xT4*C"D2ZֶV)@Wͬ B0 FB8EXL.&x|(BK+[;&h(H$.9\RVSCy )Z[UOƣq8TR~FP-R])loA#(V"<8|@bCx6Z)P]IYYUy\S$ӓHD)MtD%%o|AP hkt.ST' d>E8_GǺMwZSFE_KOU'`Pd*/1X|JK,`tJ^IOoOOSڈ:;DBASyf5VUB,lwttjw*II܌:^_uzE~NravN7he54ZM O0qɴ4zZB|<.+d2io4vEbPK$6IbT0-K$Hz5:62#.E *WB]C: A.;.}l|N:BpܤBPerѡO#%pY,y| &0P ^:`pubWQΫ{x.6'QxJl,X](/WUJJPHe ТO"ӺyǷ_wwl>zqrvͷŪ&VkC8^yr*W'R 4 ]3 !J\*CJ mdՐyi̓߮/{RNfg5&aI9rKyq!$50;6M,%e)Ff@j4~C U">υocZ"~p “An{=8 '"v? L$q*Ks[cTt+E\v;:@4׵pKcIyiY4Z 2P@ȤrJw <M Ez.Uf xBZ:iG1*`` Y[gיT=A@\iBҟLHBG,~Hԡ fbC![N"i2%O91C3KiPQQQI^-@e'W($RuSe5!_%QiDF9 4<Keζن(DCGd'c5d)ְO(Z.“8Խ dU8EQkTA{~ÐRSu]]nJW#b1$F=)6"Q( 9>э{)RK$SH$:=-531\?]Q'2`1(,f_U3H=UaȠ PC&}(dgdш8:a ZxFf_9 F՚,zѢJNs[UzNi51hZBR5RÌUH8":eQk"(XJē8<-LNO)(ʈJ(t<1r|W8Qo6ꑕ!Ūt/~ǪpV;Qh^\OzEeDQx,ITG$ %Qr* (MvQgQL HW<6upHg 6uK05NPH?d7wfC͑ ؘ?=4u8v?i*d&IxZ||M$QHX DơDjB`q2&[gi|; Ab*;#;s#ãc-0dut %99E3 Pظ6mUޟ"ŧ'&$@x4: iq4(*V$([f2@Vi}r x.ժG]#k3?j]$sMf =K\yDMu}hL gf''R)<42lO*f E1bLJکp`j8m֡!FbٟZ LX|EfUŗGjb(幉h ײ Hi 蘘hEs!V*btzsF>*yo#-0? 9Z -1Fe#.W{E r 0JC.% +y\d|l4N<~:866fńIEFOAh廞2v[g/+˳RSS􌔌Z6[ IVd\ءFf݇;Ks++ +ݣg[6@1_K0)Hhk:k{\v7z>Jt;L4K$m|TV%0mT~du=|d{Gw#$& }de.\^/*F #4NyMqIyq(Ԣ(%.##_3gxm{`ѓ';wvGl¼Z2 O bs>-b!(@JQ{b,1? #3FA @xNo Frߠ:Bdɳ'?}zuzry̤!<^ٖ@6d\\xbm︵Gfx\PFͩ4xihzE3b0뚘lNkTaMFIo՛ Ϟ>zȫ/^>_|9=3;1H_Dpeea ^7FAɠm}vI| 7,feITϞ8zƇ7N^>=X[YXqtAzj\UۇgfsZ-ɠWennYz_LڣR!D_g0Z1|&h~_tLJϏO^\{᫳g7mlnG4n,1xxxpt|!/!Wdnyyb,02h4 @l6nY,?Kv_puuq m//F aHUsO}/.o,OZ:p YZCv04ЯTQPkdbǫn/n.޽998;;ۛYՠQQ2=>8zd!dۻs؈k)C9<Ղ\K (csNU!+_~zӵʼnP_2u/O?z<=>ݳT$ <PИ!C YoCs`2;l.rT4ѣKpqw?}wW; v*:`{ifu>46R`u-g"{a] T\C1vylېlDiN4kJ#`^ͯ>^}{s}ۓw{Om/ͱr鳪WGOwgW3&ejSw=6Q%ѺG.P)=p1 ؆&qd:hȺRI7Gw~xwoMG4уO!' +]52}WOiC>Nfv{G<~/043; ٬HA nW?B iWk˿Ϸ߽~}tí㋫k{s"[ܭ2 NU֑0_ N=D8y^ᰛMfHBrA]~d^q{_o?ypgqߞ?͝q@&z`@Z#6휡Ko`zy7;6=47;19>8 Z\^QXl-Y?>ݼts㣝)'w6?y<X-zR hN% L>ġ9&417f '.!{ׅ#^!/A.`0yoS+0o^ߞy}||g{+Nm,D&'g&GCN 0ƁE/2)|LJ/m-,M#Bv{ɤwO&E.߿~t{}G SO@yhçϞ|ӣ'+ ~A#ԗozq~th1;;==w]%nB!iεׯ~{ExyWgͻOO/^]\<9y~㏿gcNS ~ŹX8v{ܞ>O%utvuu:څ|>TW1뗛߾~%@ϟ]} #@o~o,OOV&/.>1yˣ=Z[ZF\X$hA}utD緵MUǯo^xp389|>GDꐺ33ᱠ;86G^9N_^>.-F'FA/0t#|Xcs8 9t{;0*gg"p(r%BX ',V#0=aOvN_<>>>=8ԧa'6۠AoM@ax,BQȤ^8;=9zy$P()e29rW)lg<ًǯϟ[//>~ ;>[&x@&2 ,Oi )tjp۷o/_|׹9pd~h@߻`OO__<7ןx{%alM9a+z*JqT @͇a^^?|Id bp#`63m###þmt7yUUL=utQ)lT 8<@HqtB珷 ޿y}c͍@]d 7LchH`((?v9 j؛sd-ÇwmЇ|VA˷Wj# nbpPk//O#&zfaIQaAI^qeE%D"/J&vm}߾|0|(IȮNǬSzC WWwjyGe:UX’ΑbېGĠjRV^nvafV"s/U.FWn/ 桉qdWipqUX*ˋo.!>^0KOBq(CL KkJZ:U_M/-4NyFrrg uHmNuU~7p`w8tҸXtԽ矯^z}㝧[BGcd2OH-/ɦ0Y - pGgWfƆ=u G>(V̼3PU {=5܏'7|H`%)iqk3GCHXmvA%sO@}x514]? j IYit"#bXzsgL!Si8= _,7a^xߘW.leV4"=@84:y]N+@Ȍ:W@1ˡٳˌX"B萟p<I  rcc^Pe/A|MmM8ZجƉ` qiڽ=7Ƕ}ڞ(mbjj<M'ӨTL ע@g( ml|bo1]n`:o9=Ξʼj&օAG@RI߿|xݫgK;9sG‰82Ƣ2F ('< <<:l }Ah8]vhkY-"!%`h m6:vOo!=|<(qTB$ 9e3CC] Qca_.D GߐR\G.|`LY/,B^폏~t?1 D'`@%bи"n7k)t%dHfdpVf*`+b=Ԛ@Lɯhlɿ~>wz<>db|n? GPhG@cDZ>4 tC,&&'|҄ 0V,V3>^ծ8V!72O18"؍F d.ӥZ!"{*c׾K` L]͏-fà5PRꖩo?^slNz 3qȔ Oh%`QJ 3.NgE"c= md8GC!`Q3LvWY(-;hp2gڝb'h+E>FmR)x"6 p%t@edACB2a/rW >ZZc0{FL+c~Hmu_zw4@cPx*9$O"X,'VwmY?>ߞr;M~uqyN%r'RѧꆠZ#i bQvQ:G"\dj~kxddI 2Ƚv0Ftn@\7ta3YgW/=MH&1^Lj_3 MNNL I煙3 fhgwz'7+Fg-tw_NBް<:!!Q$bX,ONW{|^udzjGTC:b~px0b:q$V٠ F{oW?^[T*5H2@O?4`4А" @cKK s#vԸnۃ  8RqFZiH5o?zQŨz~>6& +B5cxb~~aaqa> LLBC7}]7 FdKWTxv˷~߾ijM@$2L S1x2@ zy5 s807YvdtXfRQdk˃w}oFϮdەˤ2)xC6{B) &Ix/t ٹphvI@]G=jן ߗ/_~JxH+Oȯ4d}J\*eͱcPhdb42HC3|./855=?7;=?AF&Ǒ r;K{O^?߿޾{㐦[JKcW2@4XOYЉNCŐ1j<%{ 0ATcm3 t/΀_HczգYo[QP\U,j.*++2H_ˈAapȦ1 8Lb'uy'&NrOVȝb>h<Y#xh?}|(7'v^Ϊj(,c j LѯPбX4F'cቩHlE@O {02e!魃四;6_>}{{xNQY`443b[_]) RjTT=HN!E%tyWщȿ}07=.\GYŃӳ7׷w`o"Oj,V# AMM)*}2@"QKM aw|/72>&:h47=50ۻŌt[eMB_-Wh$chhlxDDNL H$va+G֦NN_\ӗ`/w^V728.,_TSvU*n.J%P(2 INxFp0|JdA >69O|}tS¨m "on/hv5f*UJ"i]~~C/hb-<.QMDz\BfDOBH`h,LkDXd2h0B0# zۭz[$P|tWTVY]SuMչJzCT*FuS~,r|7N"]l-&0ջwW?>9ѩEUUeuVn;Y_H&3SHĤ*PKK?FDP@007.npyS皇_T*5'J)W2v2S2 H&־ IX B,b 8bVc3?[yV{w?6>|ϟ~ɧ?5lͭ-{Ë?>g>Go(B|.a %FщiǴx?[۫PfK0Ǔ4,dG~2s"c:;B~4 .ߛoxo0~Ϧ8|f;x|*fE|M>>b;@ @ TQxijF( [u@(tEF?l{ U[AZ)ˇj0ܨ`2 1dYmVnX ?@DZ1%nD?Ӎ kFfߴZalp`|4OM-x~*F0D"'ǓIR$j(e4(pmMy(ӡg =o&tS<hAYU<+092ҧ&741< 46J \G祳ݿݹ{WQR|^ +Bs>IXó ;z߹o((&;|K6_$ ,;Gߠ "àJ6]<)oNW'07goM˗mPx?NYHYQT@Od-O`۔6P \!^< }k2">77wYx~1zS<P@od JrHPN FOcO8.W6^'zo@W((dA.`*;}7 f$s5<M:ګ m<|MbT68+l>|C-'xZG5<' r|< ai\Z px Px<(԰`?x3Þ&)R}:ҭ pK?B3D' :{Uظ>VKnP%,b$^[T;~ldnҶ.$~p)=y\}Gsvl2BStdfP>+ H_W'}*a_@{#>L=^ `b_98V@59,>ܜA඼! 3V ߍWBi^| |䔯ə9wC \(30Q||ÀH)O D3f'W$Z)j|1voo[V׷6'Ġ|e 1?Ku5>+8lz/$?;p_?1טubM<~)<6vYSB/XZ8~MgԬ ^o3刟;闷WFL,SiK$T,Fhu J4-ooz(~[9>*8vaT\3MdҡKE=񉩕Hw _B&dehL)Hv~/OMͮmDF~@W P<p>Pk%~jѨa0gIn6b~ ,YÿlxaJPN`U_ rWوU/ Bd'h4a6xxaځ>+mғO*N6hȯ | T÷@ۡryx"L&@ͦ 3P)9Px!5sJd?;[985>= Hgg233 ~r#'ܫN@͗B|skkөS 3|>?D"ebpp||v}t_ RW({ݪnL<(n_-CHLT~~'g@!jp*ANz ,6( jjpcx|r 0L< @Y耪(Xp8 +70W4u:\⷗,(ub  |8ţja1^/D_"@aPalNZݨFx޿`_ x@;06|^eqY廷o%he^# cVm'_jɮ"~]]ߡ8ݻbF{6 +faQFx xz;NPo緗g|<4>*p/9>8&ӣDߡ^W|<v@  |7o]S*`_8򻔽~EC]2o/@&uVajj_~wI{{Q(#k兩38& ]-rAcoK!~~.!Qpbم*N"V:ohg"7aW W]?"?SG? @^6?shJ(5~@heO \if_P;z@`jm}O.Dq ǽn.NJSq-~_9j/x&WV_ⷞ6$5 pߌVvI'1[X~˅ZiowJ)o5֭map/++ŝ_AG_PKK?4P@006.npyS[g{^[f]IU2.p\v'IONO c@!$}G+ AE;8e9=cK`#}|]dۯn/5㣏m}I*&au  jEuk+#x?~uDF |NB?q~c.oJbDY.".CxLR? #_ ~$8ҿm>@0(r<[C%4s\|0H?WW?@xÆGAoX=&128 R0PL.˻neO_G)uH;::ĒQssSaZ[)Vv\yKS>=>>?Gr^7LfjZVlo'&^!F3V &*5{x h ._P H~ UCa6| G^"~, >6@ Dw}@h(Ex*J&ST2GX(d<x<9sr߅B##Dh<j,N& Rc xWPH$8``)lr<$=id$nӅ ^Lx.CA?)D4~$KPݱcɩ(Rz"=NѤ3`x\LV =fs`7}j;=PT(F 04 %Q$BJvlRQhv|l~SgzzrR;cOS*`)݊ՐjP=L I$)_}M=૊yF,$Bx|?*|_"P{zNC~8xVO˧ R|i L玽޲ & V/˗q<h(Iݮwת woo!?rɗ1%{RPϧqǏ`[[ljT?E` E+x|*AȾPLLAQ !AnYÒX'C33Pae@|; ĢVQEH4?hxUJ˗'{k'rNvBQ"Vk\.moʻ<vIkk$S"$TScY7"^(ײ CQ/jiH;mm@4D4 ܎[,D 4DApīTEKE4?lY$[,T&Wa.!jx\wD E,IA71_07$R BvfΥ򻺠ADi@^/~U#- 0}e%+ | H!/ hsƗGZgP`v0~-a0@DgnܠwI@?(F퐊- x` Ê ]T|j` 0O3~B!oA-/>nTtvHDB?`y! `C76 qpV_.*7J''gV֌*I@ %O;\XL.#.W <82sV z+#|y=xL0/V1's^ :qtn㣱D7 B~!6,;rzEOV p{㱑m=bnK|{ ?zPNMMOm%K7|BEx Bpf1^&wuv/L2tfn.}17=d{3P ?ܽoN:溺aCɝ俞>ER6ccX(|1~~a5|Hz RGPtB!{`W?ƍagvEYcc02I؜JQ|6pUz; >z*lt@e] Gnwv//!Z6]`vHb1ќ_XOI@fkatoA][Kq>FH*Tfyy&Y?́@&L"LfOu֟8ZWF@YV@`gC@O{a36?P>*n/,C0|#FQS V wZڋ)\[q%'ۙ>ǃa*b6pJ6zY> ! >w|sSV 13;;DHE#L:V@Wa,> %Al> ̂4 {ϷCl RQX9pg3a@?? !>xxd''-4' Dqq lm-PH$++'|Vps3CZ7Xiߢ@"tzn9)⯬d@fs7&^ CbP ^,~rY" X̓$va1a Q*D)^,y@ ̃<X <$ Pr݆{x=k t_y( YVV =JD!M$'!4p]A@Ֆ[޼@& NFխt:C64~I͒Seb XįD0loon# z>X,ͤ0^Hɉ h~ms=fWsH̳?g\-|wZ&FShܸLq4:_X,_\pka찐b#f1 0 x\a0ZeJxpy|. ^Xzuw!مT,Nţϋ x`WGO@ כSN9>.e𰯒pmŨ|aq$H`Z25 cAtg]=8<><;{{Da3|tz~p .5zNnH!BD=P;a d&m@3(N/( 8?}/@ 0O  ʱx; t`(>2[S/.N DI ?gg$3V/WU@ƒ#_"Pi #{ḅjF^>@ .WuB!O80*.2ZGC@jg\<L_V*rQi4<@`$6X |tf53XC>ڵw )km`$7B 3h9ѻ<2w' Lm6լ/osӾT=mM7gg|~Nv(rOϜ&eN~}KZ-zw][m9  x"{ߎ/^\^rNtp|px--sB_[\&@_~(#N.GNx2=ӓ9RNW$`9AՏ0i4Pˋ8E|9Ɏx\<6@I5n/_xq~χV z@jŗx+.͝a<7x^ޔ{XzIYcn73p]s7wv/~dׯ/O6[LOhP߉tLJ𺉀|i/<9OO۾$o~s|[|ت8YT0l]\dw||zrg7?]/>@~|0A)|p  .H2"~_߆?/`O64!S2">OJU\ 8OmV ߆|b~^A8tO9,58óg; }kK^PS*^$Qѩl`)n%nik /uvJVQqlx tKO---o읜˳S&7NVTT|^g{>CA]`dV3{ǧ8AnJ򸡮+#?pґ| n2^Z]ۆ!0a+1o^ (,x(p3<>/^_D>kR_og4>,p:YfD9L ~cggτp6:3Rw2A#VWs{zv磃S"+Wwln`Hsp ["6gO>{P6=9W@>vWuz;H\]Z89-x1#mz:~/D_ .Ck2ɕUrV#;| 3 8;W**n ;% :h'QwW+*$8U(O,-?o ?Yk+*_/Ǟ|>ta OG0OX~}|WQAOoq:q)Jng&:{_ۊ_nmq}W<3KK٭-2 0]?PKK?xyȔP@005.npyYW[W}"owz9vݑf$aTN$L$B j@BB}! F41idъcI\5wεԽ#[2xsεךk-7Σo7Mai)O?PyM'226 >~@?CHpgCFEE%%%E ~7T_}eF_}uɓ*Bc"1Q1.> 0Y4g?ܽ{/.k?͏Ä/.M~>y@b_Ga7a8Xѽ/z㏹l:ç~d`bcMcϧFǦ7Sk| $` *.-}ZT\RVQ^Sw,|}1Q:?㓨$P `2D$K$mRD&JRK%VQkk@oh.(-/-.d Th \Ӆxg|}{0|( fh4 bmVa/p/`wuw]Zd-6kF2 @, X<7y=`o0z1Ka8{p  {Wo$@,  !O'a{\Aht`}@c÷G0|T ? x^ۃ~HL@BR|,>&O.bw:03lZ-0VEb =A!(8 F pD 6(!7 5>0ON8T*JP*N68 \ѡtju]0h4[fdXr]vtn]tS|( 11t;00iQYYqi%wՕ5յu&>57 Z:fiQvK,vNE bw OK`+?9ZL_%%E%d?X1˩K]IE 8jX$;tj}_pu9%x",xeZ]c]]BP)BAo߾s˯eQ|\> ԋx-+-\@Y k00^\ƯXWooUU6>{ nEe9(,+-/(#i(zVTHp.&Оfa0acs_WWNh<~cc8i55cT!tQ]B 2q3ÒX)Aes:|-&4f[MFcٳZZV'v/.wWΎ'%, \~ـV%6^"!F>uA;ٟMm3tt(ivKx(??7T`!47bMD߷6A)F;?yXޙƷRi"2?&D: Bs3p@46vrGZoW ܩR@|Ҕ棁` -m@r tBCWg݀OG/~/ߤ <n>ydYGG-c@@1 z3=TvIe3ȱ@Z = Sٯ8g @Ojf-hIl`APfJE %h@ÇTХ+,]&/x qKR\ԋaI ,z{o\΁SpiR(Bٮш~已21 xy.O}O؈&XooWkJf6 G "8=wp$to8lwT*dҨvx)-Jڤ"#Z٦_Ոc[b]s/nܹ qB!jk0զM?y*XPwV[s}}/ ԍ2h 'k@p*§2U^|Rxq+G>c @`l?B7ΰ"eh %fQP"¥k[I|qkcݻѣl\@?Om{ mmZ6_*26R| X(N=F @CcU|4M+/K``ҹaTh6wwi:;;IO }hl$k2 _ | 5ީrF0(rIs#O>xzs7[' & NugF#W*^3/0:Q |NuǗeN ݺ)I9ԀV #n{W#t?ߊ_;{nG V8 TRo3o?}(j+߿j9x)Zx)\xHs: S &ˆgH0LRBW]9PS[[W.t#\p0:2,cohȩ?Ѕ5^6Pty|nްMVϨ{d|dx` {=ono9O\թ$~ԟ) _Zp% {Xv~w~| !Fkji[oVS MPL_yO6MY|W xhl΂p_'b-\\ : 7o)p xghu>@z4~h2=)&&&'W7>J ܼq~ M I  ['slG#,Q<> !L^mYу[د0p*ɺ'&&fW@C \ZM-/LJ#X(34p ,ܺxB,IڤKu[PLή,.fq[QRͼd<ar)XVVk.+*,|’Z.^$/Ie/..VW^鱱X8|qtGcC_Y-:-! b-#ڊ3ê/0ť*XL02H9|ůaF*5J%JXoilo5 [d+('p*ibvvraa~z448677<9 |0fC7t LIZZD I'-2#\@ ID``"H,-%+;Pd 0鏄0J% ^C(}PkTj:5w [Nj,${@H$tggk}? qpl Dqm8{k&bb~vΨ(} {k}} A X+ROPP|7۠1ÙN;;q6Bak]oU1`NMO-`[4:6ŐZPAf*q^؉)࿜) ,jc?A#>20 qngL6s(JWWXP,B $i4coa :+m)>wjaj;sB.$ FC}}\R9}nBZ1~6'_`I&gK|&LsX]xׯ+-w1p̑wh`olp 3K<hzb3B6:!c°4H$/ǿO XS Xp{\6Ũ]>gl{s~rOZ>33ssL gPGzr݁=\c]z.?}A'/G_[Kxanaa|tBdn ƠG.b׳xhrOۍo_Dbq*`ii31_(46V$X  h )?`4lr؀U\ 1 0l& XNe/"}h•l2yf|w[~{wg.cz@uB]ywX; MZ92hlk5@Ov6wvqܙg \SR ;[hai~a~frG4`ZhA}B/S'ۗɕ2 VKSp]bac&Ņ3CHj6h;J<Ү#ߞ: ,?I?K RA,`h:58@bqnzrl(qnni:5 >NQYg(E 0xl9W|^C +ˉř1b y=a§,Vkc]߄bʄN618;9>:<-,/ۇzDpߞb .>͏\y_P/}XK.>=%|0A !LA^>to1 P`[Zv:B*C`H0k`?o_AoOAط`M.ynRlOe|@C :~8F{? X]B8Zjw;{}Ca h(,ߓ>t@,x_KF- oSf|rs8Xr ﶨ \r<1/ .af1&PBN\_} ߼:ٟw 7Ykz P~-/okS oK.ߊn7SG/A6ۼxӛ !vMyʕ, СVu,-[Co?NxR:ǗǮG~FȆWZ@(H>[AӟOIChNX{?].Ag  FJK|ڠ6N`>:9`n2olAի\<1@  Hq{?>P*8zJ F+I {xN27 OIGSR/5|=| ~$ ?C\ jY?;;u~~z3BnkL&nߏb_s OL&OO )++L!M?%WtNŗMt/|{o٫?8aut1IY_tjpYc7^IvNX\δ䋗9NH-~jИ{6E(QjX]n/9~ isErM&խݣ#4pvzhG]uUU. }tWnõEs7,a{z`Nvbwx,Wݥ}ѕtxfr|sAoV >&T4-Q;veWIm+h/~z3n9Gǧ&g%i~]#* w?Fvn{j0r88|w"l" ͅ03Q~}S3 >Tg0͊F rlGpZT13]t(j's2*G7Zi<9b_ 0^m^~xw2Xpx4O&S YӧOGQ%ȩV_gׯ u0^O~>"S.W3i<`?4+?ypq滸"`&~9_'7W>2n\ggó󋉗m|~ߑ+^p?}Sss+ y4/fPKK?gZ!P@004.npygW[綨zE1v8vc;NkUT! $PAHHHBucw0.{3֒sw:11&z9߾z#?$ _ci_?Gq|.P p J篗GGN&^_0h|Oϳ[PPTTTXXX@G.9{浫uBZHoox`>Iss x,﫯Xn?x (|R')IO? x+ R~Vt!NQ%D'BP.B ZbD*mIBR*-2I$llD0<82:22256(  ?C@ ?Vt@r:VfBr\>h 4EЖh$B],؁A b4}h(6 150T*JPme+fn E֦mjtv}1Lb608nw;\No'.ހPu>Z]!ebʪʺrNiYEY)kMIIyYyY%SYSYYq|^ BDV -J^hz|ȡ׫vA׷,g"dFˡ4jڥ7<'_s54BH+z^`7j=_5 M5y5gwݾ}=:C`C-!JwJJJJȺuݻ1>g*rY 1Jk\~#4w0(77o^y36_Hs?@^T SÅBܡ1nRi@/U)+  ׯ@0?|\ I|NN5YLi‹Ưf=MCHYXv4L_#onbi%rsr+]\,oӸ0/_w2x2aH^0&4(ʥ ''*BA@(|hP"l{a-.Rj_WXPM:FAAIAARRZ%(c K5`^VX5:cSA5>#&7pkjkjjkL2ᔗqJKJcP er@PSM{ltf`795b^5|0xu\.VWU>kRIS! @ ]K-:]TF}3| |WEꪪJHCJct͛W'cR^* BĻ-TXܦkomR)D$L|"`QǭB{@˕0c-w)d( h2(1lQWD*+Mh j4x ƢnAfv XV+Yxk$ޖ,Ť!7LR&L@$;`5iz^Uo}]o~Y%tK%t -D t23d".e)FB $ѠDM 8Y¶Wȏ3x!T6l?fBܽG|[ "4R$B0 :'13n6(0x ü\HH 4Ծolmk3t*uK >%<#mZӟ~(*N&(Xxvڰ1[ZZ\B7 o逮bAy!zBi(eeR4: J ^~ڭ;IL_LPUTRn49 `Tj(>,gN=ʺukQ@d#RT&X*2ƕt\Z[?fᳲ*XF*+1[WoIR%ST5:L+/B@oGp !lr fpOdݹsSt_N >UsjI<X` ;{ VUT,<\P6߹L`N~ivve5@)~L;]~?eU&y![ܚ^L ep)]W¡$b쳤VA04 <C_:22lP;vF Nհa݂,#1Ƌ==ja^UxG@EKKe_G`ݝ!mvߍ׎^00Fgj {{{A<8T#ڕB*@ya˼sUͼ_\ {z>o<ROKF\!Fz{{NL ("ϩl6bȼ{ڵ{</]666AvuX'5N~?:6+uuUxx,+ʼsk׮} >/}>lwc{{1>7CAR*,J_\v,Pup5Oɸ{sr6NDJ_n~1>:;33=5M`,T꾾X0sbh AQȯ.-xr}SGsT.m}//F''1ՕٙىTM[E"A,@ dRwrB> xTFvrL͸$NMͭl@_$ Jxؓ["X8뵭*X [`M%EO~*z-2BoUh@YKq~vfjFLWJ_`K~ӏa(^YUHrE:n}mC#"VVLH^Ld<7?7?K @ LLG_`O`$vZ:v aB^R܂l[ӄb P]ZX^>^_[YYZ"#@@di01>5=L "xC;:5)nwVZ@|qߤ"|%@ <%]Ls ?G=jQJRڐd+ mX'IX[Y^^[;>8^(44@$)Awn0SjQ  'WoMQ  s?t:V0puzvdh7h(I6ߞsΏx6% ^^ob"vl2ޚo4'~#v`L LONOӟHOHH47< '#`o4&xC(~y  6buԟϠK`zz{/wpl%pW H)>yI~ ln0"]ŅE@ b? t d./L2 v⿟>@w0 :>;=D`U EX϶߾4 nNg5޾T7fA ⸿{[!aQӫ-24ƍ]P]YY'zB!%^s5Iވ"to;6OXG*З^.&C| I&+6TzrX]YrrlAfiE|o Ň mE˗]]̓MOɭ/I(>D`owwwg{ ;< '}`;F=NJd:86wvvvv6։KPW,Y%;{o&ѓ6 s`0w>i3N70?En6Qi})|g 46l vFnu٨WC1P0?J+47?YC NIWX_q@g|#vL8[6W o%x2aY4G $N_:#p|5쀊< fڵwe׵i;]xb+le U rbM4Zm1Pcט(I/4ŢӘ=@(.¢eګcĭX{T\vnqMԶ, _Mn=V0w@|8"?cO l~}+Wd0񊦙*ƣ_JqsL4>)}vzzp.W?| PՃ=72S>ߝ›;z8xv!?.xr]8s`4C?ö:l_~6YSx A> &#NԙԠoxN5q3wl΃o2?SbsLptHL\0J+|R@l,io)5g,)pgNV\@Qn5^'>*`ӓ)+d &?Ew?yuܓ(###h49= ҽޡf:mwFH7;;. -q#fF=GN[, '>sy_Fҭ˗.A` @^J_#x-N=q08x7aլgM3ݍ?؅6N+4* ?G7^:GYnX7Mn|G(Lm@C~B|`óWa>s2x_"/}˙pB FW./ 3:;52WOwMEI~}}IG2˵p&;~?Йac EGǧvNWTΎwzJ _‹$~Aೇ&Ļ;ܾ$+|ro>UGЋss {'^7@>A昭~rs/?4'g7y{2'KK{ǧqb96G;xU!}R%xV÷y\.f@Mec8?#|8zᓽ)<-@ZpfgUyQ ^`QxJ64#<$'"oe/}zQrފ;Z8<6;.fH S %\~), x/d>Z_/K>|Wl6.ʞV|5˕9C,#}ysoP3H`k)\AOHy"aP$my-'mx-C^>|^jI{H˯l<׎Hg'[0)PW_z3Da2=svSLRfZ?trYx?9>ؙTp(x%0/VIodlK5{O2vSJpbWY\&W)! M%pJKQaSɥ~ɥO> qΠnvBv ,,n1uhogC| yB 9ymI&z2732f34;f$9(&sP@:a﬚;y53L_ddHaµ$ލ,ə9(>A+OG3 %_d` XY_S3P͝8IGۦw^HO:No N GVvx( `yzr PKK?Hު̷P@009.npyśSY~7+my<-}Hj*O-S35 Ht]~k!a@lK~trZbks-O?j=z˱W_|<}GɏC~4B0vA{}^u' ##BS4ƒd2H&D4Q"84Ovy|(P/ XH,t&ea x< bۥxr8]0nuG R.I(cM6$n6668{\BvsBD|~ݵf7mvjlVj^Z,fJ`(O<$d"t:qMlB3ᗃ?ƆŴ~`6ajzfjrrbb~ ZeX /q "p9NG&|7M@`%ui04A2/!W8=m#ꆆF㣣j!/ O,W.Bc[-dtTPy^"`NO6ɐ4x(cEٱ1?4/H*<_>`avbW(G5̟?Kht=}(po|~eߓ/L?,~f/߃qgs\bլɟ3">{{f6ߦkOpNiˬ!p3#ޟ^gWy@.p8,} o>n2\&uTCG"shA]G`, J,!x7H,)XF?& v`09*w0<_%`PP<6ͲvI|LHf%T!0|PBe q&9MM)x[QaW=([,LBI:g h 9O@_~Ƨic0*3{3z#~~?NQjn}7z;M08OB{ 5^ky]nmh09jDwg"7|o`㩀a,o/l|l!@`uul2(+?~r"}яAX7A56Ig4D" <|/Rm<*OSa^" K|5߽j@S0ARa~𻝼h ŗC&øD`DL},"_.QO >st Wl$+fB ,/j-Vn,xC \rg&N',//hF¹M/7=a ݍ+gfbDYƍo˜LJ5_Z# /  ,I =.B`j3s7 H+dvvP E^ˉ|Ԕ/Ͽq\d @?d_n. x\_UL.j#|x  m!nccgoҩXo[ YNU_Haï,&mnlnnu-YAX<&̿)W J @% G; zxi.v6 9,`%EDq4?Bo)ì;>16+^$pfL_&@ۻ/~D| 5d,$x6wţj\B @>QL/|Z2ǏY~F/;ucwwwx"0&9os𜰟~t|bFOwF"1E`j(|Rȧ6qXdJyN(A`03蠃aCIcd 2ϕJQV;6\@(@hvrIrBᾠ腕?^|JJhΈ^ ſQiG#_#pŃ F\z^S9Gū/dhx89Q_dijf%iOH R<_m]5D   =VA,uVρ_2No3' C<~ l?i$UE4Xu0' @F'N}+ asl<ɼNJ| ql? @)6mٴrnnv/_6q RtexY`0WWK&3 QI="STk  fmmfqxR-g#u3@Ox=5s \ؾTD-?Rj!D"ءn5|Tn A*m2R\Ƿ\X^b<ϷZK|^eāLJ \E"֢ bxMu\)@Z~1Ojj YM\: <0 `[x11GKZCvr8b d2󭯣e8oiZZ5.[zv.8wd,z5,i7/Ix870[䇯.aAWC . [l"@ǚÀJ69 4/_-ɤOÝq gǕAq;z/]N#_@*lघ{WW B',mT<_tڭ I8 y'f{^'k{݆NZA*3 t?u;ÁyLLkxM5>Nɻi.\!RJHbP>!"I|#Zӗ/u犴hk#_|e=r<vnmФ5(_7$KDGOH:tu:-Ex}p_?tߒ([qPP/1ZaLNG&xE|?v?k>~f?63%177w@ ZA6#x@ ;3썛;^gUm|U- w|P.|͖߽V82f @mӬf@m_|闟q*#Y(jJ \_V:H4{=J+ۻ[0x H\@gw}tbii7DY)~#x?95>u=gW 0O>]σJQ?tw׏Fw݆XϿ|| ?J#r;ptm_$W2Rh_"y\٣N:= ?tsq[nR$o~_J>C@Ǐ4y4B.1~Ro0v|Q-}#(D> tgV< yY;~E5_%l8n!LHn X*]!WpS}'(O-G\^7~6Wp4EoNNʇD:/.Y5jBjKgOxG?eU/rk={, V6&^-x Wds(ZWy\O.=b䅈}{? &ZÏ'{S;Ztv?;oIV/x](NOy~j>oPKK?P@008.npy[SZΧ軞=WSjԮIuMLw:IӒx@C|>Q! $f>\ϟ?< |~F_/>h+\e%a`Ӿ 0K @8h7_BmUxG}.MR+7'As7jWX '08~Id_/U@wsT:U.B @`fu|:pyxP%aUo2ښAn( VFi4$tth8n& (qt؜nBz(}~=.E^d@D" Nx|QxnB3BLp8 Gx|=cp$H`h, #<[%HY>۝.tq:1/DC "0PF %7RA!|=7l䟴nv Nt9N᰻! `(ęinl3t:NJF*̃H.;5d^3f̨_5 z؆LCu;a^`` @J C=z[528+?gO X2G9sN$ rQ0yWL&PVHL6&S(P𔖌*d\8p8S(^_/3V(>`zTZ <耗Mp*<}:#e.cRGfiG% tYNaC8SZ-n™$J PIJ@!Q8)9PQ>zpYӲg|B>}H'Pp W<䤒8zS*jZ;O@;',?;a[{> :^r%s|US, S|UU \q@if%Q 6 P{4_>e2f+B ç2-ѨV5,C Qղtb -K: l B('J 76 *y@ ㏱|]m33?{?:*ēixi/6r6|@ğܑۇ@@v3r~Y+pM%ϴܙC| @&'ˢpa20@3|POG%'|p%pEND1%k:ZN `WpzZ['_)n?/Wt/}ЏRߓkNGWRkKĺtp++ 0I&Η>/4vtl)lf¬fWĐP|Nj'KD:Ob.nZLMyٗǩuh@}w-ܱϹ K&S z8t6q|TP=;RƏ˝$` 4>[v/0dR5C/=)\$4 OonT 07+J 8 ~כQsR=j-J6ӛp]<|6HNh0p&˼)U*o3F~+Wrs<.dv67sPzz7HD">hzFhbE~O0A΢Q@W_}#rb*1qKk-|" D>~uP,}?#|pJINN+m:/VJ" `D 5htF."˷8W(>l;[ {t#iLK:4=S)3sQNLN!\=j9UB|VWʥR@p3掿T@ BU@W3C`.>PA],izY?>Dܬ Lƕ%2TJk/pfgTfH%8신I`P}W $ Sqb29"`Tʹ,9ϒB>?}WΚ'1p Qbs|QB?8 y5^fsb0pZ0#P>@F |pdGbπ/~G ˇghP]*H'U`-{ PaRtKs\~PwOaWabJR\9: @vU`ZUaV3Y)Jğ<@PZ%? ښSGqyI-/x|⏊lv{AUz| xjdt)OWN ztX% {{ &O҉lYvQ /%}z{9=e8::=#]?AcNf9<^`i{tV>tۧhxBxX @M(꧱(BFo4XC%V<[&NNNOH rn粰XX^Svج`ǃTn@:z~hM AsE l.wP!p+R_׷g P|T83(^^t'݋)Nb?*f / M|x{ tTT^VpN$^|/X<N *G=8g3x$,-H ۇzO(^%^EHZ+U@e=+&/.= P|?R7eq9m0731hMy]Rހ}uR%ڇj*ΦxЃ ,V0Fss>GN&6ԛvUċF*8|MեikO[@R7|KEjU<˃F<uht^(a,T[Ŷ/?AZ'-Fx868eX!<<{tcqW睳i$ Ń7[p:xZ&4|FVS~">[XPD٨ ?hd_2XNqAA|?~C5j }|!x<j-܊`+xǃG`prצ2(ߏ U8E~_X wT$ `:2P7OPߧ~}۸w@DC I.~Bok`u!Wx63*_OLa<>]z Q)/o!,$]r"Ə?+ < 5oOvȧK[>o $*o\ 9c g~OZn(`#@a ^ﮯQe\ A@ؾ"笶3`֯ϯᄍ|;nxSE}_N)]? ^V9,G|AoTF7vA D<O/Jdzu?>ob)_\$/&W߽=odȣ(\/%@7^Ho}rRA_U&~yׯG^@. A?0S8h aZ_yID8s{uŽaľ48zHtDxQl4 EsSHӯ}GM! *6<}_\\~9ή)$SSw]I.C:^- ƀUe^vx"O--Yqn$`NlzNvڹtpOyW|~qv~yUڭJ>b x(pnf_ GvVJ?6+%?x}H Ax8T ;{Yq1HpݬI>z5&;)LфS%䓳GB8Ԁ `vrZ}:n&o6X;i6[N6O =}-|X5 yXP»JNڬ|૔NۿoŧEnF> },xO࡜;< :|n8sGn~oR`)M o멁x\./V MOPKK?e?S&P@003.npyPKK?P@x&010.npyPKK?:"_C+P@e8002.npyPKK?Ke2P@c001.npyPKK?t/C9P@̖000.npyPKK?FDP@4007.npyPKK?4P@006.npyPKK?xyȔP@005.npyPKK?gZ!P@a!004.npyPKK?Hު̷P@C009.npyPKK?P@[V008.npyPK GBlscikit-image-0.9.3/skimage/data/disk-dilate-matlab-output.npz000066400000000000000000002664561223313777300241740ustar00rootroot00000000000000PKK?ڱ%P@003.npygWy;;3kc'ظʼnkMG* PAHHHB&zGTqΛ)f%9)BܿW],? q.9jNNEV%?ܢ|9{Oz@.>{VKPٳ/Q^|2#;;777('''QUSݽ{ǫϟ?7Rl"m@/ԚfX%)O#ŻP<HMKˌL0Y?N}k7.<脏HkwWoOWg71 |‘d @zfFNQ'M^},IFtށoz&VW=npǢegfgJJasr JJJY2 >=ǏLA|,T@ h3tmA,HDP$DT&Ie bNPWWԲUU%ŅVNn!G iW˯* PO].?L m6l2MF`0fY-6bo7f#h4zxN۬kj*lVNV55MbǯzP(L BP8|^/dn_ l B--(+ a4no~ GK$y}>9j`Z<V`(hiFeQTk|E;ڻ:;:;ڣֶ0؉w{{5wvw]li$A:kEmo/m %vu@Wá;:=Ǝnp['F`E$§v@pkk;p"v82 }==b__/:@7z- 1o!7'?wңt KwtP||704CCM}DXF:Qm@N_ tP'NH1<`|@cI|IA^o1F?.XTz}n0u#_8D`4C+>#Mރ=uJXSr\*7MYcDR_ˍT*i75UJt:h0,&l4[`t6Ն rMطбBA%K؊e%%UŅEEV,VaAaAIQaIiQIyIIE%fWsW[S]Һzu}}PԨjlldoh*MFhUB8\-2ӏ5TX|^H#Pddge2rYlTFשPȇI))46i3+*Ӯ\~zDݓ 5nSZHffnAmm1|@3dWR;w'Խԫwn^xY&H'E5@WD DOkW*-JJEE͕|h(N E߂.^z7X,gefP>!7go Axɱ+ytMQ]./-,̄C[,x$L@Vqį|@VH Pᗔ@..y|HI|̰̓PYٙs tpљ0 x*(3(# gQ[~q Ҋ򲊲¢pSTXP*/,ga2\V!WrPA@1ظv!P=&{"/p*T%8Pb1'%|H5^z-/oF~ljb(Nj % eeD$/q6]UIlTUZo7߿\Xۊ YEŔ>t'M1K@-WS]]dLEYi%1:j/~;xA?Qstb#fKj1 >ğUZZeAm :nU%MD9׻:?kdZcTn◉0EUgܺr7o\!0J)=Ä[`/ho7(_V6Q$㧥=|xݾy-z) o ģ&!Iӯ܈EO>۠kfq~=8`1c pyu0J}lp"~uSd9G^≮w!_x dIL#<u],755566S3__,g<|(fKyh$ltÆeiZXЁ4t3fT3i X8-^aYi$Zx& EVAIkv|yذ|<]j(L*,/'\Z_lIx#Q A, @~hIEyQm-hlb 咊 v7#m+(*VQm:EcC7 `HaB: `r.vʊjLcšO{ (%2HX,6= َr/t@LZ-,UU _x|UQ]-ƉM5/jpz-%kYl6$ߊthTUI~7ـh_UMZn `t Hй\  -s0`OFFI>A&~^KZa#RB_AʷX O;:?S F/Ph "@9LcVSS6(WL+j[P _-PzT<6. bv@AO"uP3`!| T?<2,GUtT+2 V٢PPB"BA DJוӾۍ90(ڏrY~ozQQ=#bP:(Jqs`Fjjjh &tې`KBV:?fgn,~̗ >i4ԝoX ^|$MeJ^7&YR6긥 ţGr^Eznwp?_zٔ_3PJe^&SP]8f`h AK3_=yGn] oͮb %m~Py8UTX qܥjBiJ%pCl/, A$d>zJ+F.J; /OMt"_]^UٳR~MK+**> zA+ * 34_ Ey?﾿@SeAyz+{ ^iE#ol)zrO?CGmZd c ?\KS~A:)o`fOƯ1=alRUd:Q{{z{{>fXVm '?Hwvތ6\Rnf`ʰbcÄ/<䬛լӪ:7 zz[Nol>{,5)P\80fvmq?;NsΞ+Wp ܾ~tlHt—ka_n^Z٠Z\ 89/So2s8|_@. VGbF[Tbw{ǮRq*"98B ɃFwͻ) B_wp w$L&n;<( JKW(_EbWG iNYw" KDb!>kONϯ j46|LSUJ2Esd!fYjI +Krȭ,,)`_+(mH CP70222ɩ 8. 1_5#.O9 q{HiT r>Bq}#P(pА _LMLNMOMvv 0^+<+k' XYquW)אkNe-ԏx$'d9Z2QˊGF`L6Y茄pPeML/-,-yΎHi7ufXjjG@bI}D.FNȤr؎Hcٹ=>0 S@OL@B>׏;;B^Qw9D HkKthj<%" lq~nn"|{$zE< Tx hGmMS%%ugVv)g)_+H4'[^>$`mmiii!691P[$ 2^=c*P{g;m0jh*WHeybl|́yءoÚBH8䶉e7Y\vlh!n6SuP@sܬo/ /2uʟ%WO"pgQ 6*\]j;qE-7˿P=eurAkk+Daw0:9$- $ PKb3M IDjtՕՅ1@4:C$0 芄.ہ4Z*']RA)&h>2۷_[hbbd%=.6;CU_jke·J~ͨ3[ zЌ`rhRt_PJarFS dhKok/m쬭 Q喡뉢`U+3r89H v<~暷C'V`ue~~nvfzbrbdh5y\0-YLZ\\'lv5/ B2H0b]ߍǷVMcY;n 2#㛘,?79>2su 8abJ6n'VV=F*sVk<6N?(BTҀ`w^fgߢVg]no26+>#<ڌ c}m}=XS}x~:B[~ף(%-]¿?P:ӻ=B|{ky' fe3x lkbiltat!5i#O޽=< wXW (;(iYl ͒g7Ox4:mIx kSZrJ#[l -ޖH/OO Nwwx7ބo";h^o5B-w@ =Ïm@QxoϮwݛ$z&|bDn='xo:c diCަWvdOOhkjf[@Nna: emotL?Owx?Z&%OmqľtF__-B_\"aJO>; ܡxʿJ@.L6\'S> Gè ux=m]U9X'zrIxӧ??~zKwy&˗ *O,v7iy4x+lkiz5"r_ۃQ:LMƾj?ӧ os(zHKvF'ߓ;gI {N N(;"wVz IUNa2ss?s.^ R fFCv:V47Ӡ̦YSp_l'uPOL? 9w:ʿbqy+ hy;S@ycѨ"X(MZ:׿N?,&t=, 1 F\ iURcxZǖWvǣv?~ ;򡷐+~<~.\!CMm1@e,̈»?JEvS{x[^_'x}DPn]ϬL(5ŋnV(M G~;h24|k2w؜9%o>;S@)_|&zXa!eJب|H>?>p},f5nOsA7:|`ÌH>xdkVnltolZ>`?5/h$gח43gϜE:͹D0s =:?NxotLpzO×p?aE :t̪3 ^v'^3`5·jVBOx݃1@%ig~vN }Hx A3hwI<O9.WK} __Zϟg?n"4[]_< 3j\nk{=>55w o!{xvSVWW{>TϜ9sgϜyR |&#Hd\ln`a?EW_ͭiMԩ3]e,w" 'Zs*X<sN~sw$?iv%7=kkjBgi~!O42܀!]xZz/C_X~"|0pH8xnm^QDEH BP+Nq & @Oo'X K;4p'޾ZعETx[5/ w@} b ΅6 #HsxtfK[ۻ'GnJv}*cR@ԋ_X4n F/A_2 ͭÎw+C~Eiol>WNDnǧ}{&z{I% =VmS'ƶ!{xV 88^Գxޢ+.l`gWo4z9'%s|Tď =toS ='{W@ٳ@?uU=߉&n]df) Cf].lc./ `K+} Y?w=ZcԻ('eˍ5N(XrJ|34&_ F 8¹]u'CV}qfnD;{t=Nr Ыu3'gDxZ}qF Zv; O`({t}`owkM8 $,ď2W6LtۙUr:z_,?9!vغ/XmZ%EsFt), |sJ0#~Z㝜N7[6spdbjff~mqSxqwgs}e'G0QƩS9}2̝g,n( f(ɓ;E/_={J3bg{I֝mt j4yɭ[cY__ff1gLK~wsPKK?#_vP@010.npy[S[vO^)j^NRyK*y:u*gR83c3XF`l %$$nB`.q12"ku{ `[[ܿǿw_wOͽ?|O—?{{zonʊz.ײ|/p0p(|YYH$ CH(o@6  OL/c`DX!HZw{f Y ؐZ:@CP)!S7 aC(Vlpq,1]ŗJ@B |%>x @LJ_@)[^*?2ו Ɨ ݿ ?%0dE᧔&O*eg(7oj ʊ[ׯ.0/|d|$EUIk W:$qC yv0I>* ػ1ڀ8.k@@.虁wk q *bm%aK[qNV'b4!NH tLL[ l-Vamaفݖ%E |&NGV^SحK iaa4?g}g#]NO>8<;Z}a4ڀ@J&f^п0^zØa|s[^Yr\V3i8U6X.8C0:瑑ǏUAz$D9LSi d)<<{&G!^|^) `2=ԩuy& FH~~]>WC5# z/7oǗ &PSf:cZW4`; Yq|l@ D_t9|? J^ Ex&%|qc߲~9u`3T߭2~b. (10Ψ%_/ RAҎD]7x+EPߪo&<x; Oqxq o|<_!MG8_ Qď;Z lH8ހQ[Z|m3r /kUtVWC x䯖,7Or|r47ɍ@x0#1PYJ ')^%(#p,t`ؓC?xx`{nX,hu68LNjGYp }{DnZ``0JO~?Q`,T zV4{51a0>J&72 )3I@'(%X$:D|_.9K+ W!v:h x~ȕ":~+ k; glϗ ł|# f/^ l!fAT I^M±fϬ}k%/j!^ vwSG _"\P֬?툎GbHB!g֠|_#0M6@=<<Yi2MM 5ˤ^e ( g'I]( XXc3O0a#{NրJQH 4aZM)P I~Qoo=5>0Zrqxoa<ҠjZ&YqnP#~]y̖of|0Pc92?ĸ+s[3ȧ$__@&8?Un+4`( ӁssFTV ZШUf(?5xl K &Px3=3#d!(P )M/_Bfр{i ?A 'AZ$fi6;=8vjuxvAyxV,_AˢinooP?\^vP܇a]ZuK2gi.{B/ɪ6^" }O*J&cQbð4/ed\$|çϽrzDž؇Lz+ .ݹK»#M<(Q~\v%|ri0Rvw`2/0ޡn!xB9@NpȓámVٔ@J"|dcNNxf nc_w۔:yj5FFll?w뀯G/лzQퟞ2Yf9x5~[(x_U&Dv6AA'xP)&GϒmfS!/_nPf@D@yW쾶eR/_wm_?__or-{mrVο;i`Whxr3=/p@c^,m{_td8T6]s#?.>᷻owѨs#?ܕgcpJV=c6O&`p|K-$*>k+b tlC6o4Չ 0[G6?[jwIF8>)X}ڟJ (Y;'PKK?,߻+P@002.npyeg_ڷ)yQA슝^C')$H/R ޛ "]3~s+8g4ccsk]^BW s*~:~Oyʊ A/~B_ r:??\?~4>/mP=F%5Py/ϝB`G37orٳ#}9ᝡ`{sLFu^-*Ly ePjO%sOINJLNKçfRI!⯓M*/\+N|>ww᣷sh%0<5|kn`m~NOh,@32sr@M>RS֍7〿˥7eeSuGx*C/_ ,/T}ۘꂜ̴Ԍ,/'3+;7?N'&>OKkqqq=| $#;~S 8W#+++^mipYTzUZT2\V(*N]W[VȫdUUUbiD" |^/+;BW+kkbJ..-|?ÿ"ʊ>\wv86fZp.o/f644Eb4pxiaݜ?kq`% [́cҌZ[C.jP{( /mm[KKkKk}wZ--~ׇمi~%?_;om#` # 6tQݞΎAc}iqo·uPP[tg7>tw)?842<7ſtu@`D@f~_ v1Ըh ۋCK߁LѱAj~|B]Gca0~^224L-IGj@@k+$ QV~,,@e(L/Qcxbt?gx}$nL qTip+|XF1o  r=ݬ㩰10#0_/: b@s3&a 8Ft=}Ca|QI g?,0ojt8ܞF7"Kccr:!n6cnclp3SF]]x6z1(YaH_$<S:um^ѪUu*ᶶVRkz^5b j;vp"!8655yM.7V2mlS[Т臾I*Pk[+JmIFQIQqaQY~a~An^a^nA^n./37'377Wd+*/*.( JB$KD"L.U)\Qk*lzwLZd4M&Q%+iϲ*5==-=9)S%aƲD|~3d$ Ұ0eDJ*+5RHT[_UDKIT-. *~z!Tt1di,YH22ɁI#z̒HLLJ|i3%PNKaxV"5@H__/# R,̃kP\~+ؘ3O_fKS%%59(`B_RA ')f0@_C$99|@ <ĀǢoGU\?sI*&l§s}'`SsssRSĻ9㨜:}6ΆW]1|fϲT.~YS{}:PVPeuT`boS9{ltT7]|fHDR 뀔rJyG$ @cgcΟ=K7cb` s)τM6t x蔔䔰@X$Ԕ|WjHtT04s&&^cwJJe2\sy/,.,¼^N.$?l` BD+*x"()K%%%Ey)+3R|.১ Z{^( oHӊss+$yv7CiĝpTbŢJP(,+V)J&5 < A[nAa!ꙣ2\P,(VY2!KRRݏz zFq< E$!a k _X~3+{`$. W *KA^j+$ /aݒHX46 KK @eouvӅq|uJ"b80RQoPIz _r/@@ ߖcD 8 w|dQ^]R(kyeWKm6@|_9u k ;P\ӑ7Vo gjyeeZ-mTOI{pKx[W>:Em3<&R1w."bx@jY s x|`u6C]sSzkI?s3 tC[k0RxZwML.3'<| ~V*68T*kIb ⢺Zr>~9`m!Pz/q܍+[o0 nWWZ1*qu5愔Լ9r /nA(/#W*T&H R%)JOM@Uލr: co6tt/ШՊf^"ٜ+ ZSCPͪM_/FY*():Y65*YLF#ڢ ^ZF F_R Sx؛퍍7A]FCccp8 h&e0*Nv@-fR>T (KѩuuZ6dR%5R^A+G2^ *!|$|#& Wckkj<# Ȥ+%/-``TJ*DB9:PT$PHQNjP<]̯roSaqq,P`&*k4\ j!,qbZ[|biid8*BIJ^+Yʝ-r~||9tIMP'|۱H4uuz>Qș@z4! 2IuCaIRNDEKrN4SqY䥓744x{f:ۙ@ݍW`ph^. CZNY%e aqvX \Y./7+tla_WxB3daT3%7.D_X_]$h8tPBW|#O|0LVrVNGɑIu$KT$`>>"(x^&kѱH@Y YZN+Uˁ.L?='ņsQןgFCKk5x;( Xz֨1t`?~|=! cǎmv} 1'䉨+ %'"t2.sJ=_^  zze(@F DGǏ <ɯi_|510||<})diĎJ9WWsdv-g( 'VVJQA;o ,2G:gAY㧮NJTб C_;bg)oğNB*4JMvjB)ln+q]>wt<~*×믐KLvQC~hp-L;ie/)y.޾wJ5Qyt*6{.]9{'O=/qFRnDː osaҪZ(z s ںzӧ ׮ŖBT3jvi: 8|\ܕ+L yp|{wSy%%,."ѡW(dRqُ*7[ nhlir}>̀b' 'I%m}d O2JLɨ0b A~ |,H27]b1kԃΖZz OR}n0|'"( [9Eeel#Q Tl ?Ŝ<7tP4U ǰv  뜘ܲQ<%!PVv[\^YE$D*V6IlmA;;Zl z9MzQ9:@ax#]aIt)}vwww67PVW/.NM"w9L1! n N967'՘j4tt {sNww7XYEZY: ӫCrvfZ+wqv#qbBa=E aC:uZPkܻ]}-Jk€.kWA@Nb/?g wׯB8&mopOx |H|.9LZ"~ krV3Nw*_16U΁ޙKS^PCfY:n9!?ݰ@+r8mVd  -f)w""R?X[:3M1^/)1fdWQDOC~v4`O 9m Hpb'HX^Cʇ3dxbllt|rԫn%u;ќ#N_7꠫/&L4i#4[G>+ 0!elhzfvvfvo?n.L y65 b ??7;-/F`3 :G;F??L/&'?P0,Vy,ޭ~9@SKs>"|.b4MKz]tI|^WX  [L0o_}cn*VgSk2 Lno6%wހրPĴRX^QQZJܬT͟Tw'|dj([!77;;;=9Mx&~i;f#b?2 L`u̳M:/>sƶL#ra~v۩/F{;[Z~/’n֫b ܿKs2~vq᷶wI^ -4Nhc^:s&X~ȯ߾yb' MM.[CAWWWd /~q 4M?*z|Ah_ &>`~iv ̇v:}HY;~{{~ ږL/ί뿹+ɢ74U\q:*91?f@+_~yu/xvûN^~cy|` |w. h*Z.W>9{\L; {o_? ܠ s 01jLf»82FV! /,o>?kR ʰTI’n޼y+8={q/(_?Ѫ6\X/moo/OWdU /&v֭۷o3<'ӷ?RGl<\X nŶU[oиk y z9I q\x&|r{ .w+aO[ۯ[ 'wc/pW~8|BO$ܿ믟?~<ۦ7C/xH4 xn51$`;&ՖP vaط9W3P> 8qw1<>}:ikD~96d6Z\6+`{I90< wVz[$p{yr]o|Ɓ[^$G nRbw\[]o"vbrhim C͍>ӱIOxN LX'*yGxd+ @rx-?ox&wͥ$@x~?óDx1\ʬN=ob6νw!7˴.QlVo[΍#Ǐn`)1H)!NX jV3DG.c]FBbv ?q{ᴢc^R''.>(b/~-a<&Nfk tFլɿZ$/aFPaicǎGE?yfgX)sb|ج&:xj &9((F>(fB1'ngOD<󠰆<@ɇS9vXDm6]52:-k˻oۯ_?no4XG\.̥ l%[Z8 }UXÛRŹi`|fï!i,Qoa!d g@6(ő;qёgbKu ZFcu+&Nh7T݊XvrxD@/wxl x(!v;oo~>x紸Gs'""$''|7if @O/5b@ix` 6 ;WW?dk/JeY[Ϗ>""K,x,)3{إ[4:-6,aV m-v:_x!6WJ"翾3ӑQ'I "g=U`ZZ[P+t[+ݫGt&.|._@"M87 8NDݣ"~8vk T=w3fZ`س $jSQѨת}co'FV"|r25"\(]; ;?yu?~:>_o<;k ފVchiv [?D  ^f yU͏/Me\z(X !<'ІNikݴw3n~fzzO_~a<'8zM7Xn zvI`nQ"#OrZ9ӓ!tvٍofKߘ>}_}xFJA61|eeH"T`a䘜7y~ i47cAyE ]_\ ܈픂<{WVJ"\&l(D=qT/ is sRS2.R򀗱 * NϞ|g¸ %0 IFn1VK"zv,N{:(LB ;=ś[\.Jn*|uS/{&(# :4 6 v0)c9V,-YXN+(9q;_Hz?gfc3t)y|dLl-7,*À%<`ύmj+atY_MJHgIfXPO~Zԉ˗c{?<ȶ&,$#[?(JH+(> f>'ty۬^ ^;Y8<ͭ ;4ogw{ϓI #3ҙ@frKOК #8cGa5j>`xn6LLMM.Pm︓U$AO:e$%%g$?{(27&1<ݓO G_[[[V I&=&He +v' hSbO|4>''=Q܍.]PKK?9r3P@001.npyUgW[%Bx[e @B%P$J rc Ƙ D*_WϗW܇;g&Ùs\'82ӳh%7=v/{>W|v%<-5UA>>Pnoڜܼb^\LV U^^^QQVVb%X Zq1TÀ??oޡ5mmzs{Cj?_ᇓW= qt|=333g iEERK!|zNNVB!QLhpHཽ}B3zn2jd"N =#>wxF~(!v12>5:: &ZWjYO |Oo_JNfӋ i4zq 0(a@@A¬gIK}86_bOMؐ{is٩dfRrr)UX(-)c16(&BgЊrrs2SɓO>}SDT$F=o4L՗N ?8:::R2Vi9`2 VYyeuU]M}mm Q\TLҊr2R?B"gh9ٹŴD)쟚˗NNNX}Cv mmֶVJjUrEPZv\7˚fD$ 5*vYy5_j+Um-rD,7d#1ew;C#۬Ngo7ҡnY6bX^r:{zN~bV uFhvgG:ze*AVF7K¦Zp x#x{=n7ᑑI8>2Rccѡagl|dx=8844@vg7 `SQWgpen0% Ll\}m]MmSuM5SUYfUV*+z6S][ǩ64

    $LQ% :ɬurZ3Kb1YLiZrJV򓈈 ~jj_`͎  %q1Օ(9 vu%-HB\1RDEI15Gp(\ےx:e> s++d2YƳ興_?rkjQj8W]WSYfc`o %w^N*\0*[ْz9UǏ322)s +IM{0"YzZN &n]]S6*N%*%x9<(݀ڜ5J rY02ɣ|K+UgggkJ1!aZkjl&ĮNUU-6E*ZGs [o^l,.)!**/4( u^N"p)O4rC?^Dv-w؜VkJ]*F5F!I$ZFfFp`_XTpO`WhmT*E ><<_\\Y\]yvŷ6yICGsمeM|Z7X%< Wf&@Adfd ryLJo!":sDJ?8=e߾~pjyCTVF3\\K˚lC`Z%1Oi Gcͬ*3ZZ1RP(Q@ :A]͕v,A9?;8Xu4+4ZY]ŭk>B(LF /--y] H(BNye9J*Lm002mmJZZ#:?$04g|-`YJVfA^iI.*+`GH6:R*+k̊ Pj]Ym%LVK=K{?utv]xM]#a \%C9+*ՔˉR)_bnkUU աUT \ܨ65rR>D||lAHVf3ĭ| l6gs՛9f|yiH~&BAKB6T@s٢vAjaD5 Flђžx1vV*ocB6zZܩvZ_Jmi!d~ UЧ55:ndvCc=˕j*LkdK߼'l6R$Zy}y~08ꞞKnF@&55Ǔ2r9DXlƯ'ͪ+ yHHOh1PpT%5kXEL[5OŨ͎kkZL <`|/*CRjj4znSP͈@->[|}CP%|@Uk[Zy*y[k.OKʧb;9vS%w wrmmM|CC*=)6BVޢ5p<na=,oomS5P*<'&(!y c!ol''ײ|EP_56KU!QZ1i]Ka+q)bWB1 2]&%EA62.'Hв2BC?hij1`LFE>d]֌D_Ԋf-AL XX,H&SwGB ڊ.жȔHYPG|g\vwoO i6?'ג- ziLTmJ2=$[dw$Bܢu0-/i qY^Xq޹IZ=;OIExL{ YyT^R1Z0+{QF^kVii 1 xݿ*isvY~?>.iuaA~~ABa)/#9SKwwJwobaU!&ܘ,?ԴT/7*@)?? 8,2q|5ޓPF3ux|v%MɇG< !4<2S_@$Z%kP++&22:=;PDZ^>! hadd@PTR]__IR~_ s> :2NE왙v jEԨX *Z^~yzpph Ica*-II|phE?&.<}l.T62<1528rvڬ&Msr=orbrul#>EyOcZ[_-}zzw_{G CB#DD?m5 d*ShhPũ @oOfYz|\xuz>Mn52[UăWWaV/--eyiiCQ¢#ǩ١T$-u//.N\[Y槦{{,M JJ$tr~ O$ EށV =zLsPրx T&%Y.z` + r`kՋun'SzUQN(#b -%K2~ԳEre eR.Sȉ\^]^^.`X{8=?6v:]E.)}wDM]&F5#7SUVTB/r e fUHB)CGŗ Z][[_{rxƛ7o^w\(I ^ΉW_mI4.f6?BIjV^dZyC#|CC>vxhX6JiDW|v-Y]~|vavxtrN9;))%A vNzfJ1CbBP l44Qk6RhveKDd60M@E H_o#:KK S}.%fSRs77s3Ng|f4$QPSf#--dӁLn#v"z{{w{۷oNo@'\]]r+%%슪bu"sskoo0wٺ@4nA7dVZZhthrHZ֦$ 5PּC\[^jUUbgxfucYVsOL]&]AQӊ)4 1|nӐ[P6LpT~~zp'}usqqtzt\ 2R2ձյW{ g2rz~ vլ z}+P)Ȗ&M\ђO@_󯌔`)QQQ>,f9Tɹ1)',SNX}{+ܠҴa;Z&@C"R;H\0K=D__}8?9#@r 7:`ed(;kog;w/F&Ƈ]=.=O2 d;T8MZM8tF(ZN,k#UC8p~~v~zr|t0>h2ӆ;;;뛛 0w...vff~.C@ڪ:L:Q֨)|jTFr[KGިT8sփ͗/ݣ}ѓovw7WVǑ-W''k#̇\:'ڬnk7!Ў7Aѓ C3XE.F,{?ޞߞ黃՗k #nm:r萢F # 0:[l5@fǬ>jӄ##E(;~z0- }-(| 8=>99(j~)ZGQx8<99213;̮QGk^5٬]]&D+69GNlwZ#h< %M\8~fի9gf{k<,\FcɈ*o3vu9LZ>i[FޠiIFQJrH(4_>__\??;ClBؘAЯ\Y8%O 㚲Um0vV620F\cccV0uiwX-fɬӡwhi"_Bd\5r //.ΏO޽B .mmox6r8Օe F?;Wowmϟ?R߿oo@`GJoi;~w|nnjl3H9pm]֮ |>PǭzeyY 0?woP^o;yzskc;$7;?~;C69a18k/_<_-V[\ZWS˩4ԐNbZaF?8;:|kݝͭ-x"`k2 O|zk=ft݇n[ߓ-|ƋK (C}(][ U*vyY9(..)|:?]{vs&!J-m7=vjB }{%CJo6_XvQ6^lx|rZ{Oﭯ;olE?|ȫkkW}}N'rۨkq9^!1_#~޼~bqnzd zk]{;yZ\Q'ͨ@nowwvwuwkB`^瞛:Fӊy./o./ᆳݷk/@{<}<{IO4etlVu|{ywvvy.E1v4f\Jn }=~~G{[^ fgܮ4/H6#cc||vx`Y^?Teeۥs0J0CӼ|#ÂB>~rpLo?yu!te'9wXQ, sSՕ,U;_PPe/.ϐ؆+0]vy 8;=?B+<^W(Z|6_YN V-+> F&''?OJ|AAnnnƳT|t{CՇw ^ol8{FzN 8#t윜_]^^--┇b}Gz   y8,%%%55de _~%Nv]W_yaZyu g/@䝜]\u z96)=-=%]'u 8<}G8ҭ%4e;!Щ7ўE=%4cpA;My}f>O  x  B#{ S'E`9LmF[l첡CJ J+*++"hN2u;,fzɨv{$o}˯_?]a+np~p4FxG#w #BM5PçvQ kSízcDz3#2!_?:^DtZjFDoqG*`//_/IBM}''#r  UB‹hTG2j ׯ_|<"ll |`V[ 4p䒓pNвZT\in':FHo_ WOzَ;_\"]wo AF#0nxQj$+lqn#Tnybcr[[۷_^l_'j&XE.cU=l}P̚r}^J+fAT[ɣ66ޝ_^/W ¡ď&_A>jo?0SLi+R](9444Ld#QLԋ<V2$B)TR7`4u mucm[{0>޼R\|l>p7ʫ_\Kjq7V@Ɠa NK'.-(hfN^V'lVW Fe%P0׸O__~|0cهAa&]nW_?Od%։-}2֢Ȓjg6TeRagB`rrD TMM^>>cr}!TO_?yMawɭNf6 hr ~t_~l&#{pOo̩BA (}/o_|L}ֈ108$ZOxB`td3=HnP wbÓ+/wϮn?wsO|r{'q\\. x']Szۂl{]3A2`d_\VjǖV_omm|_?:Eg- I FA 䡻FL] ۏ,`@0yLD`p>~gwhtp.riSyzS޻[ 1-w>l籞=Ms rrp$2觟#؈ mB+LD6Uǃ້~S_`T:8% Oi=$ɃH"r|^JJz?z\p=DiЫK[!r N\]t8%2NQBR1GD= lp@@HB2 (;AbQ]dwt"y}{ZV>ɪ 5.Jp@(gP&qO= C;{d>w= <81$S{d 76~Kʩ6K +2X  e>5P /"@KHŤD^Sc䰘 zO*Ţf:Jޔ)Ꮲ&$/sׄvEW]6 %Vvv- _^^ `Ǜь6yS,cʺF\yD^tBLSP{(] :n}N+Zmf./>yMYsqf<#'"pJ@9:Ʊ;{{s7(7ҚZQdȾ!(x|IMV#=W߿%)$diԎnn#o19^_?&dReRdeF Re_?tu}Luq \'ګ~dGFeBΪGO2Qos<ف(,PKK?t/C9P@000.npy-W[[k.xmӻj sYD%@!(#I" 66W]U{?}ӿt!&y7CU 5?+*ش(^%Ea;J9O."UBx[!K+.B'<) '"ȠQUhofffS#dxm6>r9l.d87+F)D,"&vzq҃{Q9¨ɧ$xh4 Tȡf2jjkꚘfŬklnnr[ZZyVbf`de&h"KHU:wNz_~JjhoJ$Sɱddn{ ҚZjf7775Kp[y6ᱛ9M5Ey $+-=!>Bht )u(mZ]UJD%׵K8qhxll|b22=86IU c2Ml6'00uu윜dJQ#<437vyVӪbN s#V9QSUSmb56ԃ4ě YfFUmmEYqAvNzzrRBrZJzbRrBBIK д܆>wdaemc+[;[K{G@8^;¢ʪfVcSS#r8ںZdH}mMIQAQA^jRrb'ĥddg0E%JONDf6<}P8 g秂.].hoZx\V+y6agGwWX%sfvCScc]}^^NFBjB8ܱ bwvwvvwX__YD[A<?v@MYCVj!ˠd4BͦAt;3! A0111191:>>5 N͂G͹HdjzlRka&VK, ;:PB@H!uEbX'dJB.T~R=AkAo&hi#9=nf^76A#[UV\ZWX\XTX\RR_\XXTTXRRTR\TPPT<V%5pTVWkj" Es㇣6jivπKH'%4B/eTVUVWUU.(/.@ZVaa^V^AQaaA><x閝 ]?.(,//Jݢܼ*SvzRRZFJf(:/GǥdPt"Eks#<5640++aVTVWV,aVT.,-+,-*+)T_WWͨS +TNYQaΥk3@'`X%h,DqZ8hQP__Ј 02Ls!p9-ZMZskR76$}h&ţ1xT4*C"D2ZֶV)@Wͬ B0 FB8EXL.&x|(BK+[;&h(H$.9\RVSCy )Z[UOƣq8TR~FP-R])loA#(V"<8|@bCx6Z)P]IYYUy\S$ӓHD)MtD%%o|AP hkt.ST' d>E8_GǺMwZSFE_KOU'`Pd*/1X|JK,`tJ^IOoOOSڈ:;DBASyf5VUB,lwttjw*II܌:^_uzE~NravN7he54ZM O0qɴ4zZB|<.+d2io4vEbPK$6IbT0-K$Hz5:62#.E *WB]C: A.;.}l|N:BpܤBPerѡO#%pY,y| &0P ^:`pubWQΫ{x.6'QxJl,X](/WUJJPHe ТO"ӺyǷ_wwl>zqrvͷŪ&VkC8^yr*W'R 4 ]3 !J\*CJ mdՐyi̓߮/{RNfg5&aI9rKyq!$50;6M,%e)Ff@j4~C U">υocZ"~p “An{=8 '"v? L$q*Ks[cTt+E\v;:@4׵pKcIyiY4Z 2P@ȤrJw <M Ez.Uf xBZ:iG1*`` Y[gיT=A@\iBҟLHBG,~Hԡ fbC![N"i2%O91C3KiPQQQI^-@e'W($RuSe5!_%QiDF9 4<Keζن(DCGd'c5d)ְO(Z.“8Խ dU8EQkTA{~ÐRSu]]nJW#b1$F=)6"Q( 9>э{)RK$SH$:=-531\?]Q'2`1(,f_U3H=UaȠ PC&}(dgdш8:a ZxFf_9 F՚,zѢJNs[UzNi51hZBR5RÌUH8":eQk"(XJē8<-LNO)(ʈJ(t<1r|W8Qo6ꑕ!Ūt/~ǪpV;Qh^\OzEeDQx,ITG$ %Qr* (MvQgQL HW<6upHg 6uK05NPH?d7wfC͑ ؘ?=4u8v?i*d&IxZ||M$QHX DơDjB`q2&[gi|; Ab*;#;s#ãc-0dut %99E3 Pظ6mUޟ"ŧ'&$@x4: iq4(*V$([f2@Vi}r x.ժG]#k3?j]$sMf =K\yDMu}hL gf''R)<42lO*f E1bLJکp`j8m֡!FbٟZ LX|EfUŗGjb(幉h ײ Hi 蘘hEs!V*btzsF>*yo#-0? 9Z -1Fe#.W{E r 0JC.% +y\d|l4N<~:866fńIEFOAh廞2v[g/+˳RSS􌔌Z6[ IVd\ءFf݇;Ks++ +ݣg[6@1_K0)Hhk:k{\v7z>Jt;L4K$m|TV%0mT~du=|d{Gw#$& }de.\^/*F #4NyMqIyq(Ԣ(%.##_3gxm{`ѓ';wvGl¼Z2 O bs>-b!(@JQ{b,1? #3FA @xNo Frߠ:Bdɳ'?}zuzry̤!<^ٖ@6d\\xbm︵Gfx\PFͩ4xihzE3b0뚘lNkTaMFIo՛ Ϟ>zȫ/^>_|9=3;1H_Dpeea ^7FAɠm}vI| 7,feITϞ8zƇ7N^>=X[YXqtAzj\UۇgfsZ-ɠWennYz_LڣR!D_g0Z1|&h~_tLJϏO^\{᫳g7mlnG4n,1xxxpt|!/!Wdnyyb,02h4 @l6nY,?Kv_puuq m//F aHUsO}/.o,OZ:p YZCv04ЯTQPkdbǫn/n.޽998;;ۛYՠQQ2=>8zd!dۻs؈k)C9<Ղ\K (csNU!+_~zӵʼnP_2u/O?z<=>ݳT$ <PИ!C YoCs`2;l.rT4ѣKpqw?}wW; v*:`{ifu>46R`u-g"{a] T\C1vylېlDiN4kJ#`^ͯ>^}{s}ۓw{Om/ͱr鳪WGOwgW3&ejSw=6Q%ѺG.P)=p1 ؆&qd:hȺRI7Gw~xwoMG4уO!' +]52}WOiC>Nfv{G<~/043; ٬HA nW?B iWk˿Ϸ߽~}tí㋫k{s"[ܭ2 NU֑0_ N=D8y^ᰛMfHBrA]~d^q{_o?ypgqߞ?͝q@&z`@Z#6휡Ko`zy7;6=47;19>8 Z\^QXl-Y?>ݼts㣝)'w6?y<X-zR hN% L>ġ9&417f '.!{ׅ#^!/A.`0yoS+0o^ߞy}||g{+Nm,D&'g&GCN 0ƁE/2)|LJ/m-,M#Bv{ɤwO&E.߿~t{}G SO@yhçϞ|ӣ'+ ~A#ԗozq~th1;;==w]%nB!iεׯ~{ExyWgͻOO/^]\<9y~㏿gcNS ~ŹX8v{ܞ>O%utvuu:څ|>TW1뗛߾~%@ϟ]} #@o~o,OOV&/.>1yˣ=Z[ZF\X$hA}utD緵MUǯo^xp389|>GDꐺ33ᱠ;86G^9N_^>.-F'FA/0t#|Xcs8 9t{;0*gg"p(r%BX ',V#0=aOvN_<>>>=8ԧa'6۠AoM@ax,BQȤ^8;=9zy$P()e29rW)lg<ًǯϟ[//>~ ;>[&x@&2 ,Oi )tjp۷o/_|׹9pd~h@߻`OO__<7ןx{%alM9a+z*JqT @͇a^^?|Id bp#`63m###þmt7yUUL=utQ)lT 8<@HqtB珷 ޿y}c͍@]d 7LchH`((?v9 j؛sd-ÇwmЇ|VA˷Wj# nbpPk//O#&zfaIQaAI^qeE%D"/J&vm}߾|0|(IȮNǬSzC WWwjyGe:UX’ΑbېGĠjRV^nvafV"s/U.FWn/ 桉qdWipqUX*ˋo.!>^0KOBq(CL KkJZ:U_M/-4NyFrrg uHmNuU~7p`w8tҸXtԽ矯^z}㝧[BGcd2OH-/ɦ0Y - pGgWfƆ=u G>(V̼3PU {=5܏'7|H`%)iqk3GCHXmvA%sO@}x514]? j IYit"#bXzsgL!Si8= _,7a^xߘW.leV4"=@84:y]N+@Ȍ:W@1ˡٳˌX"B萟p<I  rcc^Pe/A|MmM8ZجƉ` qiڽ=7Ƕ}ڞ(mbjj<M'ӨTL ע@g( ml|bo1]n`:o9=Ξʼj&օAG@RI߿|xݫgK;9sG‰82Ƣ2F ('< <<:l }Ah8]vhkY-"!%`h m6:vOo!=|<(qTB$ 9e3CC] Qca_.D GߐR\G.|`LY/,B^폏~t?1 D'`@%bи"n7k)t%dHfdpVf*`+b=Ԛ@Lɯhlɿ~>wz<>db|n? GPhG@cDZ>4 tC,&&'|҄ 0V,V3>^ծ8V!72O18"؍F d.ӥZ!"{*c׾K` L]͏-fà5PRꖩo?^slNz 3qȔ Oh%`QJ 3.NgE"c= md8GC!`Q3LvWY(-;hp2gڝb'h+E>FmR)x"6 p%t@edACB2a/rW >ZZc0{FL+c~Hmu_zw4@cPx*9$O"X,'VwmY?>ߞr;M~uqyN%r'RѧꆠZ#i bQvQ:G"\dj~kxddI 2Ƚv0Ftn@\7ta3YgW/=MH&1^Lj_3 MNNL I煙3 fhgwz'7+Fg-tw_NBް<:!!Q$bX,ONW{|^udzjGTC:b~px0b:q$V٠ F{oW?^[T*5H2@O?4`4А" @cKK s#vԸnۃ  8RqFZiH5o?zQŨz~>6& +B5cxb~~aaqa> LLBC7}]7 FdKWTxv˷~߾ijM@$2L S1x2@ zy5 s807YvdtXfRQdk˃w}oFϮdەˤ2)xC6{B) &Ix/t ٹphvI@]G=jן ߗ/_~JxH+Oȯ4d}J\*eͱcPhdb42HC3|./855=?7;=?AF&Ǒ r;K{O^?߿޾{㐦[JKcW2@4XOYЉNCŐ1j<%{ 0ATcm3 t/΀_HczգYo[QP\U,j.*++2H_ˈAapȦ1 8Lb'uy'&NrOVȝb>h<Y#xh?}|(7'v^Ϊj(,c j LѯPбX4F'cቩHlE@O {02e!魃四;6_>}{{xNQY`443b[_]) RjTT=HN!E%tyWщȿ}07=.\GYŃӳ7׷w`o"Oj,V# AMM)*}2@"QKM aw|/72>&:h47=50ۻŌt[eMB_-Wh$chhlxDDNL H$va+G֦NN_\ӗ`/w^V728.,_TSvU*n.J%P(2 INxFp0|JdA >69O|}tS¨m "on/hv5f*UJ"i]~~C/hb-<.QMDz\BfDOBH`h,LkDXd2h0B0# zۭz[$P|tWTVY]SuMչJzCT*FuS~,r|7N"]l-&0ջwW?>9ѩEUUeuVn;Y_H&3SHĤ*PKK?}P@007.npyS[ٝ3W[T%yJUST6EbhEvbA @,!!xS~ܫ|mV!}>w=˕d׿?g~GM7~/_|jŗ?˿64j>{c#u^<ϿO/G埞l6٩RuwT==꾁>u_oeӋ =_~?4v;zݝ-j`Mhfffvnat@xQi'''u`6MFԔф-ܠMNLLiG#`2/MFfD3Nnvv9.|t|?w7y]NvI2/ͯzB2_P4GX<‘P( +EB )L,Ca5|h(0áH$ pE l*h4D3X,\? M N:~?7pﱘ<# (m2I9z2!S\,^ S864Y$ggQ8 ؕ~%<'p/ bx<Ht$s ]' ">E:g)>z`@&)ح4KO%24><@>QHwYPLF"Lhwi^V ,;?g~0#>CJ>? ()M~ ïW~Zpݢ^!d‰ćL6fG NtٝN|^paeajÙ?J/ ]|7O?+p9S2eԔY&d4` e6ZlNXbz,ypM(,-uF<6+z $&@assaXS C}==ݰT{z4ᑱQV k=zAgߠlVbXmC|^,kCH$ /?i]ݓgO?~\uhl~VWeC@4I3D"`ӌXoNjƺWM_6ri3:ypuU.OrZ^, /@#z, ,24'Ϟ7׵zexФOOTi*iD@>UG_zHD67775&\]*? >][C<$R<8 nok4P& \_M,8V/d9|' B(Юd}|x;!@ ' 5"DZxBu:X]/) iiQ +Yxk r^"􍫥|Q@'|Hzۅp w-{ 7̯VyM&~ q`x>&{_g;@P,@4Ebq1' @P_`iǥ-fWIZ7xFbQyJݟ*Wl68Fhd@@C nZZ~,XFz"ol+@# 9 Dli7,gg1Զ4D@lw[a! GIA!]xgd|* PAVoUo4_<'_9|*SF 0I93h8^o' kNO-l+ԟŋND`RP-ʴëޏ.{zp=4}4T89ᡁuoo 4zsGg\g:@#A@CO `ۈ|=={tF4^5da,/ o<{:8goSn?7Q0;&ғۨ9H$>b3˘KK&}>M_SSK !Ƅ|-h@ sv `ITmpnnqŃKU߇˽'xvL0Ih_YfA@Q!Io{.xxx,ga _ǽLra. )FE[{ǵ@gP!,ZN{g[]XYlllp["t#P\XgPgxsNU[>Azuvfc} Jrv._Y! y"or<1CW/,<.xeV`/,3)w:>-(G0tSK//rY"p>ŭLf} b$Q ~&|&?O: C0 $a6vv)aÇcc:#| x?J3BM=C/0 bO:K)lV"Bl04868<$Ã/g)? sQB˷9Em?= ^Վ񣣔o_*]\\U8=E C2<@S: 0ZWo.ni ?؁pq}-"?ZlvdԎC+IyDLfG6 iӾAӜ_`5 q@}%8'cX,/*T"BlS jūTq߲gg' ` ~qtf5?X h~Y(\J@{{<gy8][d,yzv\ekJT~w]9̲X4n{9~ e4I8n>spzA"\aac703Xq|Xmw?C4e2uzokcw4.}T8>P3өd$ v w6U-<X)qnom^$N&!ðdԏB{'ww,RKΜ)Xy [sm9=ǃ^¨냕IG,;2^ ;>> XOrz6#clV01hkj r JNDa7,Sq%a9 &IVǜ@~_K##Vʥ3(QU(,SI 0.NG2 Tg VZSPg8|0z% @u)E)^OsxPj[e>LED<ĶPI>Yۏp ≄@P"p$շZï'5#P:+?NCd?|+o9fC+ dG N Qpʏ0 xo߼rw *h +(u ۓ˫G>5|~BR|,Cqw4uy h0@~QF{ax__]^Vac V=Po}zv?g\Ǿ׎)Ÿ^^2x퀑 ÉzWכ`) 7kXI%^ ;ƋO1?ۍ֙̈́#t8;P:8wϿܓeDA&Dz*b?GaI% }o;kdo8gI-ѥ*J*U P.ؗjU7ȥNApuu p+J3x|zCs \ew(-O+skg\ ?Ҡ=xUY /d/*b t)xG,V@؈<H.nllUC].QO/:sR|N&MVv;iPHo?v]<(~TE> Px]tP:g(pkM rp( P3ܡ R)w}; `2M&dv"ߧ~ ɍ,Nk(pXz@c{o0W6 ~_:+N~mrkv~qC5[~A !..N w~ sB;=^ǐ QIƃx1_#$q~ ^|Ak3fBC>V[RiP-@XXW(4??y}}CC ੀA%oe-|)w1|T_`=;ɓz䷱|N rےcfm?_B>aӓ OS ,5|o;rqccSz쓞f8|vϓǤ8 v Ȼpx"ez $?@.|?(Ž NV_ nm.襳QT@O\kdQT /;3_Gxtvzk~ OPKK?"B mwP@006.npyScٙ_o[/ڭ׺&T홚=gM "D9"ЀH" $RGk_{΍][_݌z{OW2|_~O?gVTJ5~|(oŇ?M~_XQOcs%<,~_~/?v`\@  nۘB_˃G?~Xz\XR]%I$O5Kf FFT###5hV1)i׫{ZiݓOJMuʊǕUUgaT*Bfhb1z5&F`ڒ2)G퐁5uOk$FiC30y)(VBh!TV<|gWTUi _+"D3<=<,z۹T헟KZMҦƆFF4u45l<}p|zqWTU3x97iLlz{{;d~o_#W455cw6HœzU8r䂦dó~sse< 𿯅Hj%hiimnnJKbBxqǃC_ Tܻx<~R|M i RN^ psj"~᫋Z˅|߁2PhX|+mqWZ-›LZŽ|; @ #6Y"- C~Y * r"^,R RS[gHZZz6bv#5vh^Kw` g#S_E'iF`M~vggˁpfѨәA@?VxFh1 ! rXPxgO dh4XGjrJŷڸШ"|ql6fŨ.0Nk"Jw ̌0mrjApX)ʗ*f&c [a9;R>7 n=9Ϣj"?:'a2d5w i .?t`6Os:]oOS~@[ў^9R '6_(xi~ߥWDtL5=HͭC^ON) 1_Tb: Dgs2)?>=. 0xi{ CJ?B@[?>5J|Nf˯:^؅8fXp?lSb>= _4_.װx/ 0h@KY>϶!i1(s Q@ŌnF񓬀ah @~KV`X,,_g %]z>A$z(5O L _“෶744H># N^FrYLv*Чm FTFfx -B|Y-- _p# mvwHkN)CBvͯ KX^#<^;\F_Zb&&A -v@_> LrH'SY3?*߈{iS?x81[0tKLePp|`͵B=#ș0WSgMM-MFi3e6tP`0D +'&a"@߁$En᷏IPGuuL[Pm$o ՊYܫNM$f&VVV TDA/Sh{T_Z6I?ӗ zBQSN໇Ovy'!0c8Sٹť%m؍T`AU\T#40Q -O׷6͈: V"@ )aP mTGfRF`n[s^`g{kk w2(׀O @MDCNFQF w8-."m(^E|c|~3xh\\gT@oO0|:?OvwwXI$`~rD7Ri.8gv+ `73 ewSΙ (7hӌ fV#C##Z|  1M 7 d^= |D~NN!ÂcZXM `1ۘr%9IOP`XD4AOMA7k J / GH {?wyyy _D<`"ODWh@ ?0x"7jԼ@ sgy('F??@;j٭F^./we(p Ň@g  { z lyzqyq8]΀@X,@(]3,Xtk0@oB7yNXݥa;y84(JP^W``9ŸA  |9 Xw"nvT-RL& n߼)P'LoB.WyuS8âd 4(@qn1`&1/y8V0Lfk+I]}+C+\N) C8*Xӎ 2ٮݛy15ix4DXON'ƻ~FN3uU8sW.ys 0 s^9@ IGD`T29Pn١/ln/pVY!_p0>Jo?_,LL(q0,tA|9i 4=:b+əx<x]VtcC0 2r8|9J9^1HSq!mVj4FT*zXۋC sxh 1l>!sP8>% ;Br:$^Bs:f`ވCF }sh y JA`U I 0.jh0"JwarBW_ȣ YTJ-/.:8No F_0LFP:-[5h?3ӋB>"G"~>8_^Ь0i+ppLqZ`,tyqY8' P̖S(`3M!'̠" kG0oF}us߲yѾo1q=>7MQkЎPY [Ŝ06/n _(`^vՙ8Xs]_R7$-W%78AAwv8qvw B< %( jN |)bP*x.sL,AŃ@i_L BN, +qrBr/^~½)Sb> oeFgŷ?'|"?LIܹͷZXF7 97B< xxlzxQP~u1r7dKeCGּ ?~ F`L}uu |Ee|KAYq} CMoz˰޿{;^w> v)/pmpY8Lm>3)DCwW|hl*NpS'M f8\_]]q|]]q"RzyKcg¡/7t|:Z`Oyq X~ 'W<: %1.2;#\qpG0;C;!^ʟP5w^ſ9enq5?@p.Ci 듎!3}-}+PΎsА,/p$#F 3Xxdy< kP9"?|LtsfJB<35sgt \7o^.<n[Qa/.?%[xF|/-O88޾{bn9{MKw8xؚf }ۍᯮ_\R'[\tKNuՄ sdb]]Y/P8n^>HS,@7a\pA'03Qo{BKgKX...x R~V /ڜq|{嵵WפY| a% oq_[_o1m/O [rWHәYE@vBp;`?">AkPtz'/mXd!HUňB<RW}x( @*4yÈFnY\ 'DӚ&+G4Z8M~(?Hr%p]|yYP^WtveP|_N ] <_ Pw1{IW7ȘE_91c=q9g[<4,,)>?;̎5<~[\=5&#l)C$h4)? w s?xZ+ ^g:M8qv\$0W|y>9>Z\T@v׿, GvvOC3lsȧ.'Ǜ> ,]ħpþ}_[`z/ppjMxA/3+mvFY\Y88fʟxaV;+G)? ɮNț6F[rFaCNP>i~QY6U06s>Z[g9g/rg'䝂J>@'?/PKK?VP@005.npyYW[Wǻ_S-kKիZ餲8I9I3dF@y$4bA @̣lK}{No cϰϹWnݢbwλ҆߿w}X]W_w^u]Q1ou cAb{{ޑC/."? Bס3~SPPXX ݡ[_ݤO?{e EGcTCCC#Css͊|/*zPpaE٣"@A[W?pxHC<-rX"JeRi\ޢhmoUeRII(jjllhTW=,_XR'nQHd-fQ$i5s">/^^ot:^k4lX&3~1zN“4=ݚnUWhfKխU?bNzNOoa|?`_ x>K>z=.?X>k |Zp~fx4X?GBD"P0bx,}  864f8jE 0ysQD&G>0ȉ1 OP(%|Dx####(J~N l Nΰ%7aA _Y1&&OJ#Iǿ dh`xp>|ދGų|^<YC}^* ?(~0z`y<p"8ᗷff~3t\'Zx`q{nv]`VH?̍8 GaY6dKLbC<.hجXYV;.fl2a l7,j~\`8 Co 0ػ o(tBMڮP+;mf(7y{GGWwWJݭh`z`2Fk=var@z=NH7б>e F"Ge5%e%>,..*(~PP\|꽢%KK+J+˫kjkacdRԭ9 ]jjZ#Sw +*)Ʋ~A!)6QEܽK>xjF[V|݌aیEbAnYeU++ʡue((+).zP\Tu.E޽{~?|8:ol[-ZŬ|O?/1ՕU5U=(/)}nJK=,.Gৠ^X,HyX"wՉ QuYM0_*C|yTU+(/AC"Z$ ?!DJ%$<8 _gjrSPP/cL A%UE;;NmIJJI9>^e0XXA$,^,㻗7 εQ5䃨klh1UfKͣ, E["~oBUbD A=<\ :;7n0g|L%_KyG D*jA^Y!KgS9ohT}ׯ}~T35  ¬&~*eMf5aXwn޼q%"| px00kwCUewwH|-B§Ϳ~>?5k49X%=L {|>  B-I9K7baI\0|!ڣ`Y>c@Q(:;ߚob5 A\p*Y"a=^;(|ÖZϒGgg^ TfAoի:=e3<hj1#^Nr95·AiPl%4`D狛 ;344:4\ tD{T2%ER~1߉}`,l7m*6g.gjit ^7PC2b@dg,IG`2y}xb:FL; d2y1v~]}S~ 4{Q,AxJ j>g<[lSxoYvDpGI%J~2úǀ/R8T-,^V,T>^|ikRx% tVP+aࠞsY~s/U*J`,Kvt@Q9xx|eJi㠁.0ڪl~h|g%|@MM |NS1N07@G 7$D $N<7D𱸅\mÊmth@E18]ⴰ_TFFW._2k*kJNS滧f`$x\NI hkVWFF&W6x|bk`,+IYOk ~L"]h5L7##B^ ,IJ~P&{G&66}ėܽ}O>YLfC^j1 N3!ǨPo/<$ƞl?=]^N ʚ:6ԃsDML!<N* ~ e $ 8z\G|DG%?}k7}PYYD\DĴߍ5WH LρcD-ѱ|~P>3xHL.4IĔK0X㨉nkfX$b'tD-|k Ë$04Ȣ/|{Lʧ&RT3MOC]&R`js?ML!O |}.LΛ4jJ<=J 00LCO-!kFzE L5NaU5N6LR!qk8}h|jjjzvp*\H&`] 5VM(65Ki?S ºZ<^ik5Ae6[H[ZSS ̼X|BÉAƀV 4q#L*مTL*56q%j:Dp@*,ΏɅ'8503Cpk&,3斖WӼDjiRhWmR^*t8T6C SO&qHoJ-/'!ӓx%n0P"~4@, - q*%.JH@obJ=<֨|"['''Ax1&A&FGFN#^ڎՓWTg4Y<x8v8ns8fQQtr =|wX>L0E\Z듔`#:H ,:Ut =gI?h/Ul~㡠?6NƆ#}*Jh=@( sv2~ 0 *5xO [0X;E,E+>Egg <Ȏ@ƣ|~4 |v)97 ~MY9~Sx/^f k<LON2癍BFp/ zNS4k% e? !_Zbtzyyi;z2/Kc%xzt֧(!h }Q9x4``s}em-k ɬ{9xl',<N}/^`pr,P8Wy|ZOo\ z")eƆ0Zpx>l0dk߰zuNo7%L#x*8<0> FZ$nޤ_=9c[g#|.w[^/g8'gx`*|Y<4|bٔ xx~rĀ; _( ß_l?sͿA_.پ~~\ȳ`f JxN6@ Fw,#>MpT zz z F鳳c5hc'XXs_Dn m3p LCג}3˗o^g*vh&ɡaX:V iԳ,tOۢSSe3>}eRUav%&7\7-T[1:/xtzsI_&1m/+-.Mh&C3peLV]??f%msNMj\t%67{ڂx\~yG5Z2F_PۡTŲ^@m0mNV| , `pO'?orH^b[m VR-lzgg'*: }OgOMqqxͫ_Ώ&C:j"Af 3&{k>=;{Ju ͛_5@S.}>Pg]@lv3[9xzdn}/C >#W7o6›W8Mt||adFNn@9>>9%<>++tutnv" 0| %gVOϟ=?#)Gg1/s$+W\Y 0x=|lv1dT`?^?gÏ 3[_zZ lhv;  V>aF?ɡۿC_zl6WBA$ߥ'dtjQr%'3*4r>|Ww._ҊzqCH$7^CНl}Lx~usgw /` ;^BX"el PxI~ R?GBށmƘBTNÿf'u?_ZZs1H,m&uU"obrV U"5:3fh?„?OUomoB/3G2dnn| d2mk_֪:=^w|/#/xzI1kc/-|k׾SzO] ,r&E,@aPQmmUE)kE|\&׮}.RC( ,rl9_GGkr,vG 2QUQVVFLއ׮I1ĺ0<>8$i{ؤb= ||c}:ek01Zě56_uw'("' pf |{dut)1vE"j[7 Mm:ԝộ މem=1?d=qksB?,p8XK DE8ՠ\x <$`c 5QÃdIyyiaa!PdWp\Nvp8Аj_XLonrc`g3J+/+~ ȻYewi~N٦3[t(X-u0w7S _F>6_x5P/PKK?aH!P@004.npy}[[W+.>+w{|0 {'@.)+(f/7S7?t~*DU3_G!ޅHN/$"X"iJ$6].ooJ-ǯ,(+.-.,*kbL*4 [|uhM@cX.sd2-.fYՆ_o,fl2"^kZZmxjPkZES^?|4M@0zyݾ@8 zz"1|a' m'܃_?=P~7/yu0k _P X4FzXoo,O&d20؉)tx7 }}d6+o:Yf1`qPBn0y__< ~p?×w !1H:|8Iw!O;'$ЇGFGFF6phxh$YO&Y<ƈ|ׇ(x#54H(5Hc++0cO{O E&C#cVS/a ?3 <8~ o-DM<5' ,m? somsC`dLގ䣃@0Lll >qj*1@<,88al2x[gk`~|BwCrP^^f~"Qp'3hA:asp78ap2ct٬V !vk zb(a"D47s}0`cƏ]0>?6 FF *XSv\P(;mr+jZi udvu-f:XNiwN Ц~O.:V(y[IAIIaq9[eeeU5uohhhj@ ,Tu5Tjv]\NP:NӶzÆ;XGhMC.޽DGo?**mnVs|0ޮSvA! G5u?]Cu⩁lQA}?>䫬Dy/kV(67|{Xn^JJ OFqY IJAA1I?>1*?%5uںaZb ||WTTBVeUOC i).[ #kyialwߛ|ė40QW*?TUTVWWTҒ2Xア2΢X2 De &;Fī>G/[xeeǫGՁZp%vEU%7椲 TP$7$(0@ib@#!B-.;J.Eo _o76xuAUU /7v2cKZPȗ2 S@ԲO޾Y hjlllxLEuU19: s:8 W0|AJ K͵,ϫ&t6p7AQ^0:::: S|->Z[ (xH¿|y~؄cNoy ")Vmm*]fL@3(Vj^ hb x營5pv3jf뎳r9WQ$w@WIboB4 `3x00#hTo~x.ۏ1? H!Y>fyK]M$Vp=*Wq|?N. @S}ϗ`òR)5oxeHo:E|Ģ7(;^.( 'c1M$[\>_<6= R0bgӠppR"d `L~mc ] &'Sk8X\C-Ϡ8Xu^c4"Amm}#MN]|zwrh)8td@GՉ[G3T9|f>@M@offq'JрSdzUutS,? >1jo)mN:ThJB2F.9TO:V5c@ +Ā`"T@+YV?5>``+ KRiM&qP$Q*UJt4t|$M(OI,E ;( ԐWR^hS(lZhnno2/@>,jZ wBрɤ  HdP|Um !OK*.OҽT,6>RވݻO˫d2@*U l8 XJia Ń{n3o`ʕk>U kdƝ~ۭ Xـ&߾+*ʔrn͛ !a7Jk GHu _VP'xGag thGo'x0@7?q5oi&u-QPx=a. :C܃# M@GGSЅJ GOnO?SOTCUR]v=+6~]:,8jp?xPNT PQQ12laMNM>s敫o`դF:cgaT fo#h4 fC|o߬hk < ,OvVV^&W._polF`whID##ÃC8p͚IA#}lln #~'0~w lA&PB qbF4Oz{{ۭQ($b⿺qpr m+ kW.^'Og 4<-B(9Z,aӑi[cרz*<::6 Vj)-wx԰x"r E,bwF)SԳeNCg@Q+$t\PG-V+i[)ܽ 0Jɪ/:~EQijg˨LԀǡV71x^Ns/J~|x&G+|}tg&'g  OW'f~N݁CL@uIjp-8›ER);m cs.10^hr9 :`Щj RPUf^}]cmVf*8Fj0]"oH ̑`ǃ]`M&a]Zַq`ЪոHAB u"z56 N<"5?: ^IxVOM.-H/8`(J $P6G P(v A@O-R (b`i)၁H&oNM@z/GTdA(QJ$" im`)'9c|>ﷲxpX]~jfzr|dhh`fgGZ%πx0^E|?tD봙Xmr% k r6/:jeH8㑈KϞ𩁥ٱx_?9\n vԀZVRۡ|"ԀT:V0mi~$[ &gYnjlvtԀN:`*NZ5~$xX$ 6}6CD$rۃ .*pXי:YI YZZCR%4CH$Rh) ;qÅ 0[=vLt*uXѳ|-Fx$ ?xO c")Ÿ1քͬUt(rZ\JQKr{xviz X,6IZ50$#a ``@gՊBajee5 LOOL@R<X`u>NQ&|1|.e1zhrUJǧtPp Hϳ qO&^~ ^b٤렶V3t=%See*_ 3 XO$Mm%PD@\s:7& m-g_ל~=هrjgqZE禧禟 X, 5¡B]@x s;Džqu307;=p\<Yـ<`f{{ 0"1/P_oVKL ?/H8￞" LyX`XX[?9?:9;h#5,k+ |nfot<|ҐWgPh`~.Z^[I {&7O[\[Kf&Gq`4fc6tog˃]H@zue~m15/ɟ cSk+gcCh'8vX%]vq>P@zrono|&u PI--Z:7|ommש5ыッLfda8G@GxjÓk `ZT":aר^/^3x6У砮}6J`m2H3LərnwIw٠uXʑ~ :{"S,0Yl6ƀj"‡xT5'>'-Бma!WNg.p^퍗13Ӈ@E9!`R&K _pf!ۛ-2@I7zZ$IE*em5޽q#sŃW'Gy pAod2{ɤBRTzWm@_4n ߲/` :fnH@|AΧɰQ}p5Od$gӣ#p䄏qu\1.Zr4*@p8>:>dNeϱ]|TۄdS<tsX>a: C\ ݃c{Ã/^ kʇh^M^{FŸ@wBoew@GC_Ύ 1@߷.&f@O. |p"phr='|Je`2 8Í?^0, ?HZهDdvt[_;׫ɵ#p{:!u#H l9UMn:Aljfg d_ tz戡S<9:xM5P]pHn|~nZplwc&S{'GC _]c" h⯕@υ]ggWO^>@2p T^[aXJCPtƞ/Sk rƟ74 Ir .`G"8>H0cŷ9<?󴼼Mލl{.2>a"dR [ }y!OgSf4&/n`}'zrU.ޞ14"Qn/o^(_*tmIwn'GωpcQK"Q(KЀk'􏮊0whP pC$]\`#NNv6S&^ Er bcKw:f-;&MxF~3e%ɨWZ|&*hxb@t}Ї^\3A1B"t{gsܨ:xq ;]ˤǬڪr|ܡ](q|_tF nD#ɥ'S'};88MyU_^U[m> b rX;FxM:fV;fv;񾐊r>HB..JB \j Y6OIT,$@]|Y3IUO8 doHs?`z{6TWbp&._V=fW0ӽn2ùiYf$<>8>9͙Hǧxpf <ێ`3@N>f/xxv>l۴ 5Vs?x.ߕt7wy_X!|mo*IBG%ɻI>fgPNf%ONCқ4`a*G |p~{^u9{i%,o`Qy  =Qyr}PKK?@ȼP@009.npyśS[Y~'+~<-<$55O&=1-06`I}ߐbB оQS~"9{JX,s{\ͯW㽇x?}/{o?_ݯ/|Aa>~a:6qy]n x^OhNj8. ^e/ D6dT <*<8 ]so 6)Cp$]D"kkP 0k!5CTSxj/4_7H02P( 5 ;]m7! wQu!Z|6C7Bb!ҝH6$H$6t*71$|\ecqƀ"l.?x"0ObrF|^@q@AO66TT\$_7x ,ޥE\@jZۡ6b8]fkgv#b,t< j49P[WMqyh2ˋ KK&rӦi$P < aQYaZǟB܄d2{t01axf2?}6>66:: lHhZOVVVV3nq:T. &qp 2 cÇyh+TxI.tz` g0~dzO?~UxN`gee/S'fQcV|/Xt2 sdx* 5گ#r)B&pnNƟK9, "tR@K' =^1vxQ`eE_@;k KXRUiZOeС/-0xfYv|@{7rC]M#^vL t8tC\ lfxM`1%@*Xl3s_j O _xI1U|'n{Dž|Y&k_?6G `[YۼV-_P_r8b5OS^__W%om: {/aFG::wrq -a,C ^)Ƌ'瀷.%X@  x1e0c/N3QaZԔwKZx5`0eZb{bP  N*@@wMT+^-xrypn  >- 0O`l|w0>cO?}#~*}Vb/NgAA.@Ϟ~Ws\ J@a~~=[d[+`DCT@`3&_jd0' G@U cOF`K0܆=~dTD ~'ݓ=<$\ |8h&_L▏nFFF6LN>7J-NXEgK &@ T[`{ ɱ8;Y ydb5Fǘoց|*;Rv9tR07m x,px* ||I8? >+@E*0x_N=t.|J3&֏Hr'Za"(`2f,=B7%~tFҩg%~RQq wXK~95593ƿ| |!jn6;3A9DY~^d&q?fhx<~@x'(T(pz 1 (J6.늄'˯_ /9ngae8==%< glY]^Fٙ/|aJOGkV>;X7|!}r|]@t'S< 6ClZ^ZGp#!(]'4IdQv2څj=UTfgdMAZB?Q@J˦>_ NtqiaaN7h5"@ot;zՁmeLyJi2{[l}NbY19W?ᗱYc@miKڿir" P;a/3aիy$+~F+ij },ҩxfa* s" ?nd[ g'q0ذX-&'vh']zFpr$ʀ^!3/]u[zV|~䛴h75 ^9 A'V"6^@}¯}*߰\uZX@\@m^ٚUnqV.J6^7M%~Y*<vڭ٭ppv$pETtSW*_WJa(h9ܜ>6zz|&|#{'?s~f-Eq}{{?-A ӲeVKCJ~?#~وW//NZ |ZJnR YrI\Yـ ~eq^A౏~zyu- `|^ /t{WWL1ē:g(onK@~6Dp1VCgn?'yu?+_~_znZM&S+k *_fe XWWVLFW YU_JY6UYI#?OF^zׄķOpj7Mn3hU:k6ߓ|xʝ|* DŲL@“ӏU(m@r^p=/\AF˥tzW0<n__9p^ KG3|)WWt(:{O+)fݬYnzQmnnekM(OZHD^`>͏og2'FVw=x*|k&9fiQy U$szSzq6]Ŷ\L}MGⲲ8x&K'^77Z_{0C?9H>u L+&?,[7?ow?=>/Vv~0C_.j V) E<^&|מ"U*|F~W5@@ŏ:2KC@k3_[cBW%?Bdx5{~xvv.^Gr<M=~TOPW xM?Mr|5odvgIӰćQ} l FuHl5 H[yv^t(+pZ]\s?M?@t`}_~*" X"e¼_JZF64t!->;4ᐎ s;}z.tmY}6V7Jq_!gpOS<Bl^>i֪7?/ |jCDk7 T% tQ(e_&`tŊ}=l_) ೾Y"D~~*mRS_J" PKK?wүP@008.npyYS[vo^)~yJS֭Tnr_.`c ɌЄHLB !@SL?E&]F~ksHh]ϗŗC/~W_|g={}_z?ý?~?/_bsWVޠ8^nZZ\\T/hKN ^Ҩ?ŅxjٙF3uZFZM$2QC |78MWWkkkD$WhLS%|7 xCX8%h@!i@!2^ߌw8'%M7p{۽GZ܇x (8׿{ bX8m6U. c"_*@fb2 .nV .P܈KXx} C`D#p8ĕp lA/4itZ֐z : v.\1% =< p(Xz(o+\[SMOLOM3:22<<26>662:1OT..iHrW]ZR|&IFsN,{B@ {{{~?A>{izMJѼMptL:,-ICс οŋᣗ(`l^A DTgrJ?9-L <񓧽^|UK k- ]./n:4@Rx׏Cy1Ԡ_d`-P&/Z-B R(d!q>@?R>Ex4}}c\6IYd|~LΧcc]!kH$|+Qy;~/H3t'v*;+WM>s*tMJ)B@@R 3#r@{7 /|hXH fff9_zJ||-k|e>Z,/+?SڵDM j"nd-DNL=\a{ha)hLڿmZMz3ZuxXto##3|DGYe=YPptc3O_83iGD`yYO fg&&p 198@|N`fi/m|u u/}i[='5y3i!_7ɵL 蛦}}L%Q- }{1F^b! Y[?Y\qssS׍?>3{_ fiA8 #z4`Cdr\.Kpr)|Xwz7\aD <V 'ߕ  *p%|8 3">*+V+0;I3F21SS85(k4Dq`F#A?8,s}VNP`rЧ%S(Sz,W<6`{_>p5 z ?׸I.S",ŋm@4 8~ah0h4깹9>r[Y7o peYPS>/0A,˰Ԩak۩ɩɹ))C h?-99~rrR>OlT2/ ZBKnHdxb_l4U1m.9E 9?8,߉ ₊3MLa U׉''s fd6t)lY:1 ;?St@,Ѕ{B 0;,݌:fW<]5O RN 䟞r ca>p| <m FT+h5Pā|k! ' y8dj' :р `R c I Tg r9ܯ_Ǜ<e; ]ل8E VN)H"@P?os_NaÙrTȡBj+fIM WhwZMS#E䟓p[[2GGE(DAbE‚za59-H?|:',$9ә(OBvw;X~X ;00} Ӽj`xJY g@d-wTÅd2|b4i8kqJE-rG{0&h lfKjV9E«z ZR. ZZ4:H7]8|pH94jDtr|PJ`0M&NYa%+y|CZ P8XQ2`9 oXh59I%Q}9Q8MVT,vݮQ"_PN[|Bǻ7W&Qk*̈́ h%K@PcNW0qF% 0)K˲N^~Z|Z>GhB(;T@w6Dp,Y8*A` o6Swo fϔsnpV;-X% e?Y]Q@7R<\w.;|BۯDM2cLtYY]*?K;F5hoo%$ B:1O[Z1dpɪiw:^o%/k | w~G__r yW8ɻj-l0q7 ^ƅ(? uI>w$xRZBO4gKEpJ| *4[չC ,*t^ <ĿNQuZ и$;bbl6xU8x2t..Y~g^]_S 㛝ʿ8i awB8_*_"+|yQ&x"@ xӐi5l(^" ;x<]GE}VaP^kt8@܀rN)> ~0Lo)= +%^ OyA rs K; Kʗ5 i*o 3ӯ܋:մA3T;b}k(Gl£rT* B`ރU /[D`E/N!ݸ~F S,CY>܂eU̿f_GU.`SD\˶蘋+ro 4 CǓ/wJ#h@x<!qw..hΩA˧;\}%e{Zobsbw{Y:c|R>{WK|IllgKgVbB< P>|{>d2{Fsy}sAKM# ,:ye ,N ʧŹ"߉|+zSGe~_~woE-S`XzP_Is^_at_e9)d R+yC4dfdWfv|6-tZ=S*;?| ?򗹅ߟsbJl~-?7kfʘ]x+w~Ef-02::V`W3[_O_(/Wn4~yJOm}֓K1Z4p)p)#kyuK19rK}_u3<݀/LhtH#I%Z1Ń@4pWI@ߎB"D,d0  X>[䆈W 4KEf3o JA4&OoKp{yP8?o/泣HT@p ]jFV~& .`VL~ ljϱWs{{bO%qd6 yR=ͺ{ogtn30'l@- Wn fbQ,8v:_,s _]y$ PaOzF* Y^-y@/PKK?ڱ%P@003.npyPKK?#_vP@%010.npyPKK?,߻+P@q7002.npyPKK?9r3P@lc001.npyPKK?t/C9P@000.npyPKK?}P@k007.npyPKK?"B mwP@?006.npyPKK?VP@005.npyPKK?aH!P@V 004.npyPKK?@ȼP@B009.npyPKK?wүP@T008.npyPK Gjscikit-image-0.9.3/skimage/data/disk-erode-matlab-output.npz000066400000000000000000002570051223313777300240160ustar00rootroot00000000000000PKK?%P@003.npy_۽fp`8Q@ 8( " 8 *FkIfhtJjfj:?kˈ+gK\I{dterXmzˈ/z=6ߴK .|*3\jsg{ݽՙ]:0Non16kkkhohkkmjninRUT_\ _eYr\" |>ϗ+9/? h\4m0_ 7U:}C@ͭm4Ԥkh*ˋr DEB8# Ԁ/C[tTWhJ]ݕ+ZnmiN"7jU¼|evfTT"?-M$ 8O"x` n&hJbZ]KKV'JT,J@7ϣ&9QAR]d vܽ >O._W\) 2x0$%$0Q.KOG >!o~!}ʇ2槥IRYz\y(b3t0OoܿŸ(5VPⷖg.uuvwv_' r+sio ض D躺F-Z 6k6uwwJ F׷_)ϐ ލ)b}uw0,VK_g4u{Vfw:VC[[sBA! L C `gʉm;0wwww66@A82 ͆ggBtpfz:4 G驉ɉxÃ6oLS3ppjl<015r4hꊂ̬tgzo-{Fh8/Dg#sP0p84]X-V7͍ͭMXls;{j|g-[^_Yĸo6 <` :>`wm6f1lց>xV{p>tn;󍌌cQ`rjrrbOMAuhf:2A(F&7[leyiu~~eyvZFFUYTikjj*+TMUR]Qk\R_wF#MkjjvzmN30Bёh 'aR^.I# zpHGSkUVTUTGT.*˗+ WjMM] Wj+*՗KuuyyE%uZ JU<;'@PV*]KEjY+**b`MI'}`@G+((T^ShBN0|TP_S&P;|"?/[V'%y co\ؤ5k:(RU1ei4@_Etg_: şs%#[[+Ԓ:^9Aò*0(*izZJM}+JEF+NR1 t0X#;l76pjңCZ X5(?.PȤ2X(y-I($xP"tQ~`hZ piio7Q<-lmz=u?55YlS>m>G bdA *ky$(!^Of]&w=_#\|QHp*5AT@kN[H `x2@˖1Ŗ8!#x"Z*G8e<.g47:eu} X˰H _&ϧ|~/"9@bF==]=Paa_Eta?7ף>ID߅N\1xԋx3Tck1{zFd=]FcWw7 ~}=n!݅R"3S,?p<r im6(9,}PYm`g2=x"Y@e4ïv3&'!yτMg r Bu/(0jҌ: 6[h8 > IYeKadx DEr !``b#0P@,1'K2 LYa dOed0Bha2H  }PE'6.ysʅ], km9% xs|FxPF;``pەCe1u_U\VWìL@q"`[.wt.TsN/y:]ZqUVT3P( 76S=&*ud6CMrqaR/rPlc(!OP, cc {oA>+hmoϕ;nD|an. 6݉:ydɼ@  I kZ,]{ۋrO\d68܋\EBEF|/|?Ng~cm ]}TA@3!H'E0)܅ţONc?Zc;VX 8vxRS< ('C3j Zq]v{N }hVyl1d-L'#4@@4|Ч|NB? ;x+[>H! _a/2 4P^3s9\~QAz4VWg)?>s(n2k4B1~Bcܸ8}c>I݇XyT!"&_".2cTw/ yb ?>/kolaQe'-\H|1tCEDq_ :L ̿ ;|>݆dbDA :.S$0^U#"x@|!̹($u tU@ro| aXjJr d6pp!rBfED0iDXQۅzfwb^/'''vQ \"\yO;)و0tWv۱p><`opmjjj2m0f0 Wd Y>>@Z|0''6=gvƅ$\ϋt4$)mm5 A1 ͡ 7 XZ_ۊXQ Dc%F,'ʈix,CHf~p3FशNΎBp \vmkkynnnبI/9"CV1H|Naidd<=DC(vd]]__^̗'32,\B,]+OBa2 7 0ˏVWgssF?8stsg}yyXY#e<\d0B͓+KqKN[WV͆P$̆ whH x}ȇCCWk[shsY@˃CY9&d8rFU5~v6c%Nٔ/kǨ:koܸqCD޽{9\UV}?SQi4C(m^@r@!lyOL} p߿s8<2VS)?Y&IKKVv9 l$PuDZK8pnߢ\ʢ<. RR :Gp O&>d0<^CjB*H KjGO+D&#.N*A>_YIiPpzjr<0=gn)"K%YrB/: f /mS@|GwnA\"'":!h"KHpzfzr +Jwn_$tIYah6ttu=iQ/`lhP'O|v| G.-$ ^J %S=j҈ -./A6&PS[|IY\\oTjq#^Lp: '`td|ɗ_w>hook(WpXdUphσU אšb㊂k?~p=BN ԪpCy'Ʌ͵u_y z'' lM3ctkzKPC߻c 6z HAgme~& M.v|Hf3lb3Sg‘r {'O_~|y1w} ֖Oy}Ot~fO"84i%| f!A@gЂPDexhmkϞ=yvׯ-d׍?]ZZj{tfjM^[GtS pϰhdW/[/g߾}.,P}tƚ^~:“'>G htGFn[{E~p(φ# ^>}nԨk>GTowF0K S A'n.ʷ 3ss l(tʇuׅ}hЂٛ:o࿹N͍ ?|o㎆ @7nom0 n:ff ++K1&~бʊc[pp76#8ugx{ㄌ:hp]eա  qxhle;iiyq>:b fCvo6"b_RM,~gEE@'[Òll4[~{kW@,G?{w?}\ >{Ý>0.S|BKo޺q 67VVWbR\t>FSMfK (:_|]7{?E>(/`@!lB"]h+b ?H\cEOLd u%_;/w6]M|D'_=~/D{[۠`yiKFftoו$MM'a=X^.n }]rd4czBeE?۷nw,o_?]-Fk]"*W+NK4} =xp|{`}}umcmo:Ui}ǏDk4H!(((1X:yB _̜ΦpGͣ퍍qg/Vf'0@ ;: ?"T1+'';SJʘ9{듓/x࣏nA_y߉/-LJmPVkh6uwv54}SѣGZCMXϗHx=]}o}ܻkO!.;*˃6c x_=:y|t|IJR_<(gH"?Ջoa~)(}KPȕip NO8#>{R[}lj[f0Ῐ$.%K7ݿ}7P:B^xgW<۩|qїk3Gg|~Ť _JŁ/{r}/o{'_<|޽xm{zgKyy|Xohj/̜pr8|$,\)w~(x~3ߍl#]!H D`|>DϾ}nƪ*kY~2THsJS?S]6<}׏|k/_l~%C 8<0TNN}o ^ߺOw>4< zdB :\O t{ï;`0D\> +@U(di IIo ddKޥ[ÕߤVSS0DɫW6Fi.3AX,[2 o/9+3V7A1 t? =tL Z5d{һ>Qa_xl`gO>yq<Ӏ>'Kܳ  _ZFptڷ/-@܂ m)OZ3n$?y5Aܯ%O,3{"z̓'%4mu%y8K5V[J]<,Z| ²35OD{ ř7{#lOAOrQH7](ϣPo͎VIț_߼ 7Ún%j!s˟zl3 Poa7B,UBH[[nߚKO{|f,f67$_sAtOY^w*;FCs0Hvl~'@Uߨi~˟ 9|12=Jsۊ"Y" voZMVH6*sn@Z\ :А 9dkj> ^c2+[ѥU57M&Gd`ʔ+#[,$ g?5|_EM 3 i d(XG'x5san3 ?_'O=%¬<0,mLfX1uww{w3016sjf^׊" ?DrO(?kJ2:2Y`iqMD #C+7Qfx +rT&-iMNME7)~ ф/TJʩަ&6LAPP,P<0 34??ab( k-ۛk+0)?3,oϿ/W%bpN++ o^ݭBruS>2/8iWI]ZYY_>?ϟ}V yb@S~4"|^WZY@@V:4mQS~/^zϿ~v0Z+JY|AA)f1n!/h%c`}TMK+ }T~m믿oWVW *" (|S--sKK[W^eqe_E9˯o/"?+(?C!r򡴖tdt>'|$ ت5$)}6r ⟿ o|O-~Cc jT*TRbG,frKMFF- eq`f\w?9>~" >%+UNOoa?/߿ k0׿R{{ pAܟ&gz_O?#/io\PKK? y+P@010.npySkKHFasۀbA\q` q\)$/Rdm5=#dvH,=ȗ._^تjV6VU/6vssc[Ycc/?C>7;I$  :H2`Nq8T@}u(S'{{?^o_v+"Џgo/vCk++G aoѤzήDwwOOwooOo'y7_X>txWww<wvcߦ~0f]$B P> >a(uHq~9UG|<-  |2'+|ӏq/4PP@Dt ]b y<*` P@ųTsOp٠xEcK |En6j~?`/`,?/V;K{8_@kZ!p:546TZcM|y@AԸ 5<|<d&@qվ P (;Pp U@ ]C\ƅ2/x?P&to?Nx .Ѕb6ݏ BtcGQ0|'0@aw;04Hg+ _ww-_ ;*VB+w8LOM=|bjrr||tdto`( {Dٳg<.@57y4a FGY$_6~Po0(j`#_H?BzKCH_C׍3V4@=ᓜ[}Tz&=JYeE=wf2Le xX[$O&i-p)xR6"]H+|uG9._[[^Yyi66 C/~.[[__&.c.I<.[[x_1r"#^߹*ۢItkfn] __ZJ}/ؑ}Z`R kWOC܀F+R}- 8r~4T |~o*IMMMڷŽ𫫲q z)wy\Y*dp  cMMdG.K寮7I45L.{vܼʲ$< MMUl뮸+/_]ZzM/,d A|&`ZS`' ,3xR_}us8=|$؃J{^1(&!:YpEbMՌ/S (ˏ_bÓuA fY<0~J5u lOlëk 2c3uwħP|j@w a4u9|^.F1, :prhܭNs7㕳*(˴DR,O}Kɫ?+GO/elcrk_*&򋴀`6 dRv> 9xjpGOe%x#?h\^rU[ l<Q᱕m|r4{\o6ר:q 6sWTΞ}л[[>܋G_>oՋ~GڇhZ'  k.dcc}q^п||=m‡Yf}7D݅2)NI]y+tP{ۃgG {rjq|fQP:~ts+APPȞ{j`u&3 [̅y<|GQ9z]|wKA>g!h?:95{sw0?gg3lXof}T28|,X L:6h>o;n<7HskX=Lb>XWrL=?:4 >2w W#[trG|I ^~6շ$>Lo}hx'?>_#\ه]R@73?e O >oךu6Cgէ}:)n꺚״<:MJ?bS,Lt]*`5Դ Щ~ۃߡNOyD $2bk< th/(e# )1ύ ?}-Oiwt9E,ˆ.x캺?7z; W.t EA~443_w 6<@ >X#7n4/B̓C\ʣ)Axt|'V4OyxhW(oH1/ >8?|2|I!n19+ Z<~ a hf .pw[~! સ6_[[.ώ{sq*IjW(o^W.(ΫGg_Z~ΡMW~8??{D?7xG\~-R5y%8[1@n =>T| |5+ǻٸ|J'H|@USm\@w󬀡ೂJG|Uei \d*5ۧ받-MC(>12b<&}T%Riِ{u>,gd5l\\[o*>CPз{fO Xx@'R1M<^S ٥Sٔ/5_NUfלED`[ H^pϭf,:JC8,'>{_,ptЫ;Q@{aWn!::?T z$^ B䫫{_v>Q X=ONJǷG/z} >|k[}r? o?O?C^%峋'O >ϟ_Ia_ŗu}w?,ӿ3SzaPKK?{w,P@002.npy[ɶݙwmc9'L9)" A"I$r2ٴ8vrcVZҪGdkOc,/zb˺xa_j>(>Wjonmmmoo.4khu:]iYUeeeiiiEEEUuuh2 uښjX^QUSh4 ᡡ*J&bX;u?A'O *\r_kmq$Y&juťUU'Z_"~IiYiid2D,1o d\$J|ee%G7չ(`xت@P*|ATUWh¼ĘhrD(@ DA$p4eEBBoi)!⢳gehJ&P^+J=/h2bb"BʈƕHT9&{Adw:3ǕSc gj_PF@*JW|0|ffzBtl4beᣩ$D S9u츈?+$p'}g +xп‹H: 2$<*>,2>O_U\/6Wf]¯՟ 5յ?=GE/1h$ ? 46[mh|Ϻ9zWTh7j@hjb|ZRJN^NW[Sr6-T@7 ˜Po66 5:S]hoښZ[[[,uUUho TmuuBP76ZW16I'#cccNkxxtdxxl{aאshhph`oh,M[ss\}^F'u}uug$[[\&>_^^-b|ol7?+>oyii oZ\[[X񭬭c8o.-O@Ip :6j{?ycc0k+~sϟ?a⅋T.]?.^t}};nwg{gwwoo> i w31>66:vƽSS3s3ӳs+-/|+UC+b޹vqޅ.]?\zpp*ʕKm-[dmnZ-fkj47`,ZlMf[k[skGkor:kxc#c#1 ^Мo63?7099?7t] #RLb8m~ܼ̌윜켼&,}d=[/8WTeRW+*+ȯ¢mAvshhhۺ{&':-v{ur|dl4%EBD\C@!oKNVzV&#+3-3==--Q?fi `Ws325i)ZmZRllbr|vvFST<̒"xlqjnV|$Rp2J,dcyEtLKK(Tf;M6srث(>66>>>-2MH)QRVG8\ de1~*L£Sa@aKN}W>I 22R {T, RP(J7¢25?Q|pb+%XtZmQ^9Y YٙP?19iI*x|4 b1 y~j tb -FEAnnVDaU*g+,բմZhHOtxPQVF(#Q#A^$bx/ :j$:ev***M)ԃ2$eXJJW&dW[Ql2VD$aQ"J%LO%H@@"TkjjU&XʐVQ[IxJDJШ\] /&כ #" @x5JBIOKs0d@D2ex1,JG5j+9d2h0֛ l6 0Ւ ZC]Mik K*!DZC-'&~^&ɤl1ObRZ,W*LfZ66 ɳ4Yadj0M,1_X!P=Xh[*M @;1H-exttbuoio$zxX, Ȏ %ŕ5&h757wj8(cTp |XahkhԌb@8<hl6Z҄O%|Frr\r$6#cUB@"dQ=]]{4+YWU6j9V[5ZiS`N D򘸈Pu4ٚ$S> "tp͔4V؆\qON:\e|E%LV$JLEt!E0T*T&/p2ЋM.SO[kmpRs 2`>v@hGSM]DX B0$Ah)_NS{{lvTz.}h4v::Iv :qйh/ZQ‚Omࠁ`o7Բ˪vGdj5Pi3<XhI,02~8eFB !6#*F*a}%GJ}6ptt;g=41չj"JA`n$>a\9ɓ'd|>?.)V_V&C /iQV\T`EF%\IobxL&n /VI#b B*->>ID$ a,7t#LΎ@0Vi Eb@lf mrhfC}:=- &0^.>H&IiEJ>#^LGψ`1_T:ɠxHaDڞ8*J4Tء0L+jJR*l`4yh3ghNHnZfT|C,O-6 b}07bV9/U"_ՊT*$,#M6EJ*܂t SbdkQ76z[!`C&!Xr'O$<,_QZ* ,R!";q A$xS~>8HbwA Ə <Q:dHJOsHED~i@j|7 @V;l v :$P$,8)+P`cp:4x&5?0 _0' "h tq@<44<ӂF1<d5+4Y ff/vRA!UnWR|2Ewrt`۬n71>!'¹d2b1Bm6dKY/cqVAIHSبvw)雠frFF6* 'aQɪ`R! 7kx`!z'(D?I@H7֊7cCgtv!g[Z bɋRQ>32 Q PeRJ% B҅|K14?N w;OOLL`jl# D0Ok4 0!pJٱ+$ F a=kcމqlj\goow׿7fGŁ]?ϰI-14c0O !WB&Kͭ`S_b_O'ź5w `t{accnnbi2d2>N0Nb2D}3 Q);VȤX]= Ӎ}o{mͿ0N@` .,-AݨV*XC$PٻՖYHL Ҽ}QAjBLtT2,<$DPbU2,%+'>" #dnsm[wvy4xu:#e3 yJ[e%s249ErN "\^AJ$5(")zYeoqw67&ܽ WwV!7|MSs3jlϰo6Y+H "B&쩇)! :~0 N xpƍ*n޼y [{KX&4~ckj|Ilezbjm)bcWXuo`#?lm<}{?9zʭ[= >=HglOJQ]hʞ~ `OP[Ȣ?/<伺A'~ ?!Ķݾ{xpg'?íKaLTѝ3g P2"v@ܸwI 2J&:S^wȨȕ5Ȳ 6Ci6эXbGF&;)GOwomѓC<|ɣ'OՃ/HIL : {<ŢTLBxކϷ4799CLC}]MiIi]v{ Rsx܍B '!@K// pn\t&&Ir=0Zi9-V}K3SQ΄[YVXC,NgπkIU*0>6dH{Tn=%'/!pуwo\2EK#c|QƱ IәNנ@M]a'/{{) >|%^?zwoHx.]eOuQB!ΩKn,0=u:V7Ó( PtQX!뗯_={wo>d1]k+E!XiFcqgsշ83=54;^ |u+\5NOt3 zէO_~MGϟ=yj-'o\>_$ h97?aU[=n5Nѱ1x=|vb<}wo߽>zBQڹ09 (n3?’ MgwvrՇlwNY-u?xF'&lΏ){u˻ws.߼y wFw>)) 'T6@I`j4X;;穕ЂƀGlg_6?)~ѹ˗ܹ3v}}n߸D_kIOIOhZ]nCee+Zefj31Ꙝrqwk! TW^ϻ$Źsucggݽsb·vZ\ >e/SӋs3^{1$S]^,]T[ q8GޝK!0pͫx l670|Wb*Vgu#YXY9;7=Nn39U b33/HsܹyuὛXHҵ+{%sxZXknWxW6c+˴DNOO~2a@d3O>O^[ko_:1g{>-j]X@V=w퍵U{fKKKsS|,b3I//||[<|xx_ãwH``vAw[՗U_;}u?B 33f}45ٚ _oSǏ_=~:L=8x= 7~vNl6Wg0̇e혟nR-c7.^X_fg.~l4 &3z4< GHxÇ5L`ehi13鮯׆ fg?uʒovnv 7[D++*IC={?3&pO^y U$_?>2Eٹ0ݾ}Kv6Vss FvH_庂,VWɣW?uΝϟAܭ^z5{qaTb["|@`{;u޹ݭ įfL$w>$sI{y3GY J{_ȞBz_*%O'pxk/ln=`[@ !%%$mu}ܹ[FdЈd`Ґ/|q|pp*:'<{w]taoogksumumvztÊlX, FDD IHH֖[;J Oh.Ċt%?οyG0~֍[W.no`k0r##`cFGg{j,~rrfRO~u$8)!Afi_\HxTTD]o`1^7>~_޾yOxWΟ?[ZF.2Ʈ??K>o}cscuyq'טVȑ6y.Х)WbD$ +E̊K:r"Lg"_Rb}2ETJJrLh0(I@nӇo^Q <tCZ| >|ض {3"xNFbT 4j&UIܻ_޿S> 5Wo޾}*V@w>==7WDxXYG|Goh[#汇NHD $Ri[9|J*j-yy>7ۇ ?]GbY:'i޹k;uyt7 pTyϚD]Q?;B垞T޿|Q}6BȚQsp#yTPsL8<7wyPfhK= |j".#2 fH+5W$@g]^o%p{1Jufgf&r33 *LaO!)ædYLo}t݃#ol̸ =<%nY7?wlbxH -ĞOn/LVՔy4} ةL/*]<|T}=ɥxβ*J0"QqvǨ^vwXmցqTj699KVgVT~qf~~qaf:˽ pų< ̘.xQwKL vTs=LlM[(~ Ir9" ͆³BxO@x*wAd{ÓrT LRbv_F]^^Xz,&KM]#&<&`6,qtVw2ogwI#:urFlQf"ղsǞ&-cU^H"W<_ǰ3u ҙ`ok(Zd5Lӏ7%:TX"=8Hqf˅3C>L`ٷ4|U^oO'h#}l0[ yS6wssfvoIPEz ;NV> O[y(NJ m=$02F+ fݨ{0@@`bޞK!fkl4+Sג=X$K%J%w{x +^tY?iUxOwRF?]eshϏyvK9"-'+ *JbH/aO|SȢRJh0A%؜~` 3sl/WmMM8%iii^=BQ@QO& Q$S\ڣHeuzzF\_9ڞ×/ul C 499-5+<;ۛ-fNR]YHֈ]nț}abI˄Kzw?óNL憚zbhbbZjj*?5T{:?F}<; ̿cw.\}ǯ>?~B ?&113>^6b >6BQLѶwwvv$p~O_n/ۗwI@IIqfF2O4T'fK( YkLA(/SOr'NޏGG/o7sL@/)˧ϐdpxM1:8M%tFIxlQ9z y=K[ʫ~??i?U%ge@VȩHK.)CdM4 2M?RB,\z|?}ǟrm}I ]I@^%KX^+&TD.4ֿ lnmη0ew=>3>_?|DVE OyL<'Q-ip +}%R4,4>L.9 9>Zl1..@ͧO ՚>h#J+9bfƨ% /!pFlA;`9>,m3vɳ_xӧO__!=wWgf8={D/vZeV3gbbFS8 im6}AB ^~ۗ?mGq'tqQ 1q1*Db" 1F~Iyjf2<U$Sy=ӻ |*ϟ>Hم8_gDŽbb"ؾKG1Y:Ư0-'îۏ_2K%*7 VGE5&L_Imo3:XA7=Oo>|FuJ r[YMc7PKK?Tf}e3P@001.npy_[.m]oHoXPADE@{^ǚ^M5=3s;g}8˾|Z/{"r]wgN\U&Q_࿹8ZJc8Bil0MZyӮVCY1BxBZ|Ź啕.Uq ZP(*ryRYS44h0jkT5JrMML\_P(egDGF d2 -av .\r%Zd^, r2DA|$qBQU]}NS( d\Hp8,.L(!eK.%A "]_ZXZYY^ Oz:dW^-H%b"+U*U]Q YyQA^NVvv.ٙ rY,=.LU{ƒ(Z+̤Zif/,.-.M:W BP|TU)00PjEZ&KE䴄Ĥh@xx8;mx|li7Ģ:jI1y /͌89XҒRIիeJ,B^UY <؏!VTIeR. D)I 1Q<~LRrBBB|+7^eE, JfgT66X}sյg KQAM/rWAU+OYiEE,3,ǏKM.V m?_Z\ &mS#BQSWU6hMFEP«;'DfJYGme?"&N?7;;<7=:00 y<^uϋz===]n{j6:Zu-zmQ <nWWelD9QMMM:df&0-/-,dobffzjj o_?-MM@Ipt[mfc^iuf\]<E1676׃:ް{mogg6~%lllmlmnP_׶i5>o}?, @`fj||b|]pyqq xyeAWAonn_ۻ/ão_~hwmg ttw \;8<>>~x|tx?&smg}myqIdgHÅ \m[do޼}!P>HݤS?8~|&]?«7'S>70 }~톻 x}~0r$f=HX^X`6W7760ˋ6VWׂ[[;LJG[ZZAҬ34tZI5h EYjзZ;Z[&iجNn;.6:144>4]}u $ ${dqq¢ܜ*y_ZZ|/ZTFtyYyYIQI\%e2qI&*:}muhhT'&STR&.E-.,$ Gd[T+AY"+*ī9 8+-115=9??K$*xs󸂘8.^*,Kb x, @ /OD\XyYYY'Hw|_P@ %K~gs9ȸH6C3Œ#Kee⊲ry"s_@/?_rnA_Ɔ3<.f3l6N< $ꔨr<ɫd⒲r |B,)++),,Q%2Ujq~բ 1fM\\"F<)[2I _./%4H Ng~h#3NUWCZEUEeĆ\TJ"=dTVUdW LdW,FeH[ *UR!H|X~9d,&g4T@KCaIq&DqX\>Ïx]}m-BAb=Ԛ#' D)@s)k(H Eyn/Ǥe1b|0ZC_fFRaT`<|HZ$-5j(Ds WrŹVւ4@jhh4&(:ia,0>@s0aa|Yu&8 ::vUV<5Ys*qbi122by1|h?AYIE21s % |5LI?!Xj|B``f\ x|,?ωBG,0 VAS7h:U&pkԜ(`)((!_ÖcũP`WcrL&'Dűcbhg%Rl!p:# N^Cij6뚈'kԍz5 iudub ר5xkBwFGFF^ᰩhFѹ~#BB@͊" utln6&&mO5j 8[T*ܠll榆&e g34IIQY٢xNlEE#߅Rlv4ŋdj7v;ڌƶVVkh6` ں&JQiܬ74u(s23ct☤z 0>`8BwZ-d0Lo!x߹FeWRFag\|Qzzz ҾFJINh(D~͊IL٬6 Kd60 $נ:}ٕWV oj5wt w&X(m$Q>OGR $EmLRVBTE~~!!` XnF'`X;AureV wPrN˙򄤸Ha<>%:- 5N[W!G CXb?I@ uQSX SFdP)jI+5vwxnavm?[ՀBXތL8G(lyEQTWOH$&űYTcq $Df#s`6SV>Z~A`}}A]S â¢Ci0p,-#&C]|T ݢ1ԗef$hH$)*pYVňkh#zzS}Ge2Ֆ3R&'9pBTX 8PXXikH,J,*OÄ U8"6e1pib:-f؈4PP֐@#}mխZMrY^J]H V$.OKJ˕6VVJčmJM<'/jRJ H Y.x#9R|)#bAAVIťY pҥ 14-Ij6 tUuSJU$ "%)DcYjAۭXfI255"476~%^݆775[[4QH8YЙ,-z x \jӐ ]:uUqaR"Ο^?1=.;b4Ȫf^cЫFCl "sq%Y84QYfHZL}MmvrӢXyv KgeIDN5o[,0PzH2MF7]0$j 9q%bqKtzSopT6ـ+f[奧&dQII|p:l ~]ހތdh2"mmitv555 $ᅋ7V8+D3`RNF8͗*Y6Ogә$[xx3"ȼr -$r,͎jG)ҷ6zF/ 5 .1Xpdqy0o4^!>DMLJҢx?#>Y~/_wi5h;mݶI AWk{i6&%0 RN0ܰ0 VEEP"ёl΅K](MB `Q4Ҋh{aPQ -FPmkk2lmmlE~0S0yWh4$)/Z~V}}P8< 9 e3/PqDQ+ؼ,;Q6"@![wfmlltn"QQt:I!P!ocXP̤ͣLA"ѧ+¬2b?2xf4Y=d8mH~ yQzl8i iQha_.@AhW I*]w8z."mE581mYYB!4P.?.]q(x!8(Ad$2kN^C6N bZ6"[um7c=lMmB"|Hz ]&]ӵw٠4X6P '( 8&qmV I>C>ݢoi]pLx{1#N%:5<<44N#E',zؑ{1$4|2#`E' h,^PެosٷYu Vr{Nujrb`j[ *1W"Ba4/ҹ<0& ;⳹ &r npw g1YaDt?G)xL06Vj *Z#jB[\LLF}>~pohwkqgllxةiS8h$XŴKG_Plˇᜈ ȼieyiIFJB4? J8)F2:ܸNv륪|><{XǴumn[qqtva~^(D**+LIC~liHD dn۝{ۗonn.-.}[륅q~uwbUj iY ?'C<~$?%Tj cB_b>߼_<8=:ۻ:|x 2_"2O(kjf>4v4 heQ2;:Zj$y11Ay h y.;%)G7n߽577V7SC:hz ;Y!.=Z{pd`*DCX6,N%/D#P;NH.?w#N0wܸuƽ{͝8>>{m|\3r3l> 2ucyAY݂|u9!c줎ZU"QzFr_+Z\T"ʧہt!mmmwo߻sÇsO=ݝ`p¥( 1+W.6vWggguvtScY ueBTժv'Aw=n#է9!;'=99ýNI#ME14O^[ .W럜 L {>t86!hғnD2|wO_AGJYZ[]NNN{ɳGwVWNkLl\BZڪkd_] .Ɔ={.+-j1[ )Xmgon_{}gO>y)=:##5C&L{w&[338359>z0ͥY(fv wc PVœ/_޿:}z{׏]XY ,eG\+Y^o3f4 lΝսiS*v\}ҹ~|yzϻo?^>WN߽|~޽[׏66VVY RLZG&\^rˡS蜈o yIEŨkm{ ٫gnݺq:S+b1A໦m)˔<MNεk[kK ٙN'l3.{go,ϥ]ty}UD@o<47392G*Nc`|C]봺63gLJ&^DYnX>t}_x664Zû_޿;7759\~k` X\Nh4|C}.;<Ftu:5>??1 憱C#H ^OM"0S/|V[[O>}}{z{͛׃H~7m,wZ%E} nIk ):M@p}v? DϋC@mB[ԵU_~| .\?Z]rߺuAbhkomٻzz t]7P(zQPc#ioA6'}#@TU%-~tsggzzjfsΝ[wӆezG%9Uz@p7=6> &%btx ?]>t ziQh׏o?<[YZzp㽣k7=.1dUzZk[{FԄϷX^Y03P-3 M^[/D~|!^=[{[3K_<ݓwn"{]~;E@R Ydu]wt7l3uH#HCcdl -zVS+r*3՛Ƿ0=sq|xѓg>^]Y\YX;TkGb98:,.&'FG |C## mK]BtZEyNNП y&"Kԉ/6>19@.5M ]CZC.**r*#гom.o޺"=髷P1!4 tj ""*j| 05519=iВjؠiPɹ:W%|{wѭ͛7#?{ٽ{N_~7f!59C#CC}^uקiiibeml2$JN+zb6N\va>~/_<zr6+|v*PG~iI3Pochh!g_秦SU>4֌ I)%2Ùdkq|!IǸׯ_}ٓGnlN,t0"$zrljrrrzjQ ޝ9))tSt5W- {qq1Q<&Ҥ/C |߽}s}.fWV!^F >LT @yd%Dޜ=..NU*e:=,a1X,:#e'<=wDTN@d0 ߜxz*pWA'ƦIL{=C9Eȝh|rXXh8`ԕ\ SD%%e(./o?~|#GbFO'xH2zw?hmmxeB'_MMFǤ'g'wd&I'O۵奥yj\jDꚐkDmmO>;}ǏY̢.0CF c.b4|Z0~ -go^WwT̤ ȈHHgo?|x]R.MMx I1)9i<,Zat&'2*137'+/#=!2} {~O޿[XX~j||Kx!d0zG_}Ǐv5p.G %WK ~Arxq&C8/[3!3?7R!*Z$DLaa!aa'޽y&ykl3l6_sjIvVYUoB IEdᳳewX,9>;;33>>'@N,#s''޼ygr(DQXԈh!_e1Bi vDTf\S[Eٟ_\msAo GEE0{g>r]2+CC/޼  7ڢrv|D95:.66VrpuA)_,ޱ鱱N{h 04h9E!"9ux&@h\3~ O!ǦD޿Ӎվ"T:Zc 8 C's` R1nynvny}m08?Li2m IO~A~NK$EUpzÓs6 6 !@zzghldltt Ocann^U)U2a!WKyҭ'߿82 H nddlt$\]!X&uc'WYv~n~qqE&5dn/M-ꊊyd@[2+<hg" Lrx`l:+*ށflt|,E?DG|䓇 ybhUs(sӀA{7 ˟#ȺlB>@%8 =w7Pg ~^t`kK>*!^W*oiWgQgG)AB/?!H<[T\Bc<6Ak\3:Kis:Ό-Γ42sݟЬmq@U 9<G矿~?p/\tfo07@~""i$yu;jmg_OǠJj[L?x d^IknWƚE D!FT˅?[ 𜛎=1119COO{Q;q:\}=d^dY]KKe֏?ޚ!ħpx\ a.@89yqrY4(),pGmmCD.haRyZ~?GA;299EK ίj˭Ȩ.o(r ǹ\53SV6r'jQ!)i􆺺yFxHm~>ɵT69ZȋN*jBK w3?CGt&&!麵ղji5L]N:M+9Rkǟ?-ˎãc㭂+,&M 4Ƅ򖮮Z91D,&&\I#~ߐMDuu'[?kkkRH۽QDI8> !\:Qt֠۰Tx@O$yI&bt-xrvXh5ՒC=LJm%,g ,./.y$ -pȴ~}h).CJ5;F=P^PRY!5u雚5s}M;"Ю)[yE#FfeeLF uS51 2H~KN\D艅&uQv166~ow}pѮoEEG8d4n6I D_,07\BnK%J.e&Y:yx!:XHzLΡсqyi>u4YNFq;Ϟ<{#Y{8a&()DZS#'w)dŒծ[1s،{ʕ41 ԤժϓG{z]['O~}rӐbXP*|S!KH "#Ӕd\>_%F~Ra1ݤ3ҝ$za7?~|{WR*B\QWsx0APKK?t/C9P@000.npy-W[[k.xmӻj sYD%@!(#I" 66W]U{?}ӿt!&y7CU 5?+*ش(^%Ea;J9O."UBx[!K+.B'<) '"ȠQUhofffS#dxm6>r9l.d87+F)D,"&vzq҃{Q9¨ɧ$xh4 Tȡf2jjkꚘfŬklnnr[ZZyVbf`de&h"KHU:wNz_~JjhoJ$Sɱddn{ ҚZjf7775Kp[y6ᱛ9M5Ey $+-=!>Bht )u(mZ]UJD%׵K8qhxll|b22=86IU c2Ml6'00uu윜dJQ#<437vyVӪbN s#V9QSUSmb56ԃ4ě YfFUmmEYqAvNzzrRBrZJzbRrBBIK д܆>wdaemc+[;[K{G@8^;¢ʪfVcSS#r8ںZdH}mMIQAQA^jRrb'ĥddg0E%JONDf6<}P8 g秂.].hoZx\V+y6agGwWX%sfvCScc]}^^NFBjB8ܱ bwvwvvwX__YD[A<?v@MYCVj!ˠd4BͦAt;3! A0111191:>>5 N͂G͹HdjzlRka&VK, ;:PB@H!uEbX'dJB.T~R=AkAo&hi#9=nf^76A#[UV\ZWX\XTX\RR_\XXTTXRRTR\TPPT<V%5pTVWkj" Es㇣6jivπKH'%4B/eTVUVWUU.(/.@ZVaa^V^AQaaA><x閝 ]?.(,//Jݢܼ*SvzRRZFJf(:/GǥdPt"Eks#<5640++aVTVWV,aVT.,-+,-*+)T_WWͨS +TNYQaΥk3@'`X%h,DqZ8hQP__Ј 02Ls!p9-ZMZskR76$}h&ţ1xT4*C"D2ZֶV)@Wͬ B0 FB8EXL.&x|(BK+[;&h(H$.9\RVSCy )Z[UOƣq8TR~FP-R])loA#(V"<8|@bCx6Z)P]IYYUy\S$ӓHD)MtD%%o|AP hkt.ST' d>E8_GǺMwZSFE_KOU'`Pd*/1X|JK,`tJ^IOoOOSڈ:;DBASyf5VUB,lwttjw*II܌:^_uzE~NravN7he54ZM O0qɴ4zZB|<.+d2io4vEbPK$6IbT0-K$Hz5:62#.E *WB]C: A.;.}l|N:BpܤBPerѡO#%pY,y| &0P ^:`pubWQΫ{x.6'QxJl,X](/WUJJPHe ТO"ӺyǷ_wwl>zqrvͷŪ&VkC8^yr*W'R 4 ]3 !J\*CJ mdՐyi̓߮/{RNfg5&aI9rKyq!$50;6M,%e)Ff@j4~C U">υocZ"~p “An{=8 '"v? L$q*Ks[cTt+E\v;:@4׵pKcIyiY4Z 2P@ȤrJw <M Ez.Uf xBZ:iG1*`` Y[gיT=A@\iBҟLHBG,~Hԡ fbC![N"i2%O91C3KiPQQQI^-@e'W($RuSe5!_%QiDF9 4<Keζن(DCGd'c5d)ְO(Z.“8Խ dU8EQkTA{~ÐRSu]]nJW#b1$F=)6"Q( 9>э{)RK$SH$:=-531\?]Q'2`1(,f_U3H=UaȠ PC&}(dgdш8:a ZxFf_9 F՚,zѢJNs[UzNi51hZBR5RÌUH8":eQk"(XJē8<-LNO)(ʈJ(t<1r|W8Qo6ꑕ!Ūt/~ǪpV;Qh^\OzEeDQx,ITG$ %Qr* (MvQgQL HW<6upHg 6uK05NPH?d7wfC͑ ؘ?=4u8v?i*d&IxZ||M$QHX DơDjB`q2&[gi|; Ab*;#;s#ãc-0dut %99E3 Pظ6mUޟ"ŧ'&$@x4: iq4(*V$([f2@Vi}r x.ժG]#k3?j]$sMf =K\yDMu}hL gf''R)<42lO*f E1bLJکp`j8m֡!FbٟZ LX|EfUŗGjb(幉h ײ Hi 蘘hEs!V*btzsF>*yo#-0? 9Z -1Fe#.W{E r 0JC.% +y\d|l4N<~:866fńIEFOAh廞2v[g/+˳RSS􌔌Z6[ IVd\ءFf݇;Ks++ +ݣg[6@1_K0)Hhk:k{\v7z>Jt;L4K$m|TV%0mT~du=|d{Gw#$& }de.\^/*F #4NyMqIyq(Ԣ(%.##_3gxm{`ѓ';wvGl¼Z2 O bs>-b!(@JQ{b,1? #3FA @xNo Frߠ:Bdɳ'?}zuzry̤!<^ٖ@6d\\xbm︵Gfx\PFͩ4xihzE3b0뚘lNkTaMFIo՛ Ϟ>zȫ/^>_|9=3;1H_Dpeea ^7FAɠm}vI| 7,feITϞ8zƇ7N^>=X[YXqtAzj\UۇgfsZ-ɠWennYz_LڣR!D_g0Z1|&h~_tLJϏO^\{᫳g7mlnG4n,1xxxpt|!/!Wdnyyb,02h4 @l6nY,?Kv_puuq m//F aHUsO}/.o,OZ:p YZCv04ЯTQPkdbǫn/n.޽998;;ۛYՠQQ2=>8zd!dۻs؈k)C9<Ղ\K (csNU!+_~zӵʼnP_2u/O?z<=>ݳT$ <PИ!C YoCs`2;l.rT4ѣKpqw?}wW; v*:`{ifu>46R`u-g"{a] T\C1vylېlDiN4kJ#`^ͯ>^}{s}ۓw{Om/ͱr鳪WGOwgW3&ejSw=6Q%ѺG.P)=p1 ؆&qd:hȺRI7Gw~xwoMG4уO!' +]52}WOiC>Nfv{G<~/043; ٬HA nW?B iWk˿Ϸ߽~}tí㋫k{s"[ܭ2 NU֑0_ N=D8y^ᰛMfHBrA]~d^q{_o?ypgqߞ?͝q@&z`@Z#6휡Ko`zy7;6=47;19>8 Z\^QXl-Y?>ݼts㣝)'w6?y<X-zR hN% L>ġ9&417f '.!{ׅ#^!/A.`0yoS+0o^ߞy}||g{+Nm,D&'g&GCN 0ƁE/2)|LJ/m-,M#Bv{ɤwO&E.߿~t{}G SO@yhçϞ|ӣ'+ ~A#ԗozq~th1;;==w]%nB!iεׯ~{ExyWgͻOO/^]\<9y~㏿gcNS ~ŹX8v{ܞ>O%utvuu:څ|>TW1뗛߾~%@ϟ]} #@o~o,OOV&/.>1yˣ=Z[ZF\X$hA}utD緵MUǯo^xp389|>GDꐺ33ᱠ;86G^9N_^>.-F'FA/0t#|Xcs8 9t{;0*gg"p(r%BX ',V#0=aOvN_<>>>=8ԧa'6۠AoM@ax,BQȤ^8;=9zy$P()e29rW)lg<ًǯϟ[//>~ ;>[&x@&2 ,Oi )tjp۷o/_|׹9pd~h@߻`OO__<7ןx{%alM9a+z*JqT @͇a^^?|Id bp#`63m###þmt7yUUL=utQ)lT 8<@HqtB珷 ޿y}c͍@]d 7LchH`((?v9 j؛sd-ÇwmЇ|VA˷Wj# nbpPk//O#&zfaIQaAI^qeE%D"/J&vm}߾|0|(IȮNǬSzC WWwjyGe:UX’ΑbېGĠjRV^nvafV"s/U.FWn/ 桉qdWipqUX*ˋo.!>^0KOBq(CL KkJZ:U_M/-4NyFrrg uHmNuU~7p`w8tҸXtԽ矯^z}㝧[BGcd2OH-/ɦ0Y - pGgWfƆ=u G>(V̼3PU {=5܏'7|H`%)iqk3GCHXmvA%sO@}x514]? j IYit"#bXzsgL!Si8= _,7a^xߘW.leV4"=@84:y]N+@Ȍ:W@1ˡٳˌX"B萟p<I  rcc^Pe/A|MmM8ZجƉ` qiڽ=7Ƕ}ڞ(mbjj<M'ӨTL ע@g( ml|bo1]n`:o9=Ξʼj&օAG@RI߿|xݫgK;9sG‰82Ƣ2F ('< <<:l }Ah8]vhkY-"!%`h m6:vOo!=|<(qTB$ 9e3CC] Qca_.D GߐR\G.|`LY/,B^폏~t?1 D'`@%bи"n7k)t%dHfdpVf*`+b=Ԛ@Lɯhlɿ~>wz<>db|n? GPhG@cDZ>4 tC,&&'|҄ 0V,V3>^ծ8V!72O18"؍F d.ӥZ!"{*c׾K` L]͏-fà5PRꖩo?^slNz 3qȔ Oh%`QJ 3.NgE"c= md8GC!`Q3LvWY(-;hp2gڝb'h+E>FmR)x"6 p%t@edACB2a/rW >ZZc0{FL+c~Hmu_zw4@cPx*9$O"X,'VwmY?>ߞr;M~uqyN%r'RѧꆠZ#i bQvQ:G"\dj~kxddI 2Ƚv0Ftn@\7ta3YgW/=MH&1^Lj_3 MNNL I煙3 fhgwz'7+Fg-tw_NBް<:!!Q$bX,ONW{|^udzjGTC:b~px0b:q$V٠ F{oW?^[T*5H2@O?4`4А" @cKK s#vԸnۃ  8RqFZiH5o?zQŨz~>6& +B5cxb~~aaqa> LLBC7}]7 FdKWTxv˷~߾ijM@$2L S1x2@ zy5 s807YvdtXfRQdk˃w}oFϮdەˤ2)xC6{B) &Ix/t ٹphvI@]G=jן ߗ/_~JxH+Oȯ4d}J\*eͱcPhdb42HC3|./855=?7;=?AF&Ǒ r;K{O^?߿޾{㐦[JKcW2@4XOYЉNCŐ1j<%{ 0ATcm3 t/΀_HczգYo[QP\U,j.*++2H_ˈAapȦ1 8Lb'uy'&NrOVȝb>h<Y#xh?}|(7'v^Ϊj(,c j LѯPбX4F'cቩHlE@O {02e!魃四;6_>}{{xNQY`443b[_]) RjTT=HN!E%tyWщȿ}07=.\GYŃӳ7׷w`o"Oj,V# AMM)*}2@"QKM aw|/72>&:h47=50ۻŌt[eMB_-Wh$chhlxDDNL H$va+G֦NN_\ӗ`/w^V728.,_TSvU*n.J%P(2 INxFp0|JdA >69O|}tS¨m "on/hv5f*UJ"i]~~C/hb-<.QMDz\BfDOBH`h,LkDXd2h0B0# zۭz[$P|tWTVY]SuMչJzCT*FuS~,r|7N"]l-&0ջwW?>9ѩEUUeuVn;Y_H&3SHĤ*PKK?d!;P@007.npyS#gzͯ-'8A `8t`$BF#aNvR6Tj7Wef\)Un`\,10>}xm`w[Tzir`vn8fTnqyqb>[LW㥙4|목}5[׼c&7HP示{їb 7 Z|2;)t:v )VhUrTyWQygvp8v?M(p&j<,}ȿ'@Wv? \%Gu?]JwO3ͯ5@ȿxspjdl6V"t_qݮי ӳ|_) `e6"TUTTT_tq3;CP8;P0y=PosUPOkk*Ж" P=߷m큖@kkKK[#vWJrwzwwS>.ͤQja ~}Q|Ǐ+ˉ0_r\2ǃ@8P!"PV- !9|@EAqw}C/ ghO 4 4oB纣|I`?6::222oC/{h/ zz:;#^x*U0yD{Z׃?>>6 xKH~+[Hwp II> pf}ey} 0 `<Ј'L>[^|YFF%ΨI-@'0 HRz9O}1T㱱ثX E )y^'Jfqײ<y]29'X_<8pjnq1_@٘Z̏'\ig#`E‚s0POOYXiYyy'`'J^(?*[g<㯬?S۟Uy ~~3ky!Q#RȇѨc }Y^ 3R^&JL&c9'|3>p< Sm%/vU99:Ze_I Q]x0 >tB''!$Hv7<藔>$ey ZP(@"15:6h3~LiZ:9yx)xO%@SMP$ۏyRXzlR:n?@C_ `zzjR'"}_O,>C*7L(}aGO Dl,Xby@MNS)OՈU_Oph"O|+[6>AbvN!Kx_@~G7aKx~xTe".'7hTK-3gk`~iyCfVssFo ٥˳4t00W6ޱG=<k&~iR XZrg>h>jw8%VTPC,9/~ C!Lʖooo/_2߄ eqVݓg5;|p}V%9>>$ [T@CMCXʳLFBom]np/p.,. Pf~'l@t_,%ODQu78T8n|۞80|8N+#_S?oprVzX67ҪU |{K b46ln1C}a`8oxBo[~/CFxEӳ0ށ`CS>Hj?@* ~W!"x s oa7>x3k~o >|^Vo^!@hN/,4mO$S3Sih>A՗ ?Mi ~/Ӑ9WeU2J MPMM$W/_WV DԈaޑ8T,HN HW6@ 3'i2ve<3Lgz_ɇp}n! `A,;3~8`{C{>57PGjurd虙ࡼ'E߇f\2߿{px>_+1wHӀ!{*|WW9<<(8coOk&@#峛iw:q> 莛3|zGC8yt'p  @7Ycgpx͎ zN%초"gɛ~ laf`X_1|s}-D8, FT߿^:OufId9 I9o4f{}mGGj`:$! dr!Ec?Tiq&cy1k_~qssyyc ?ծ s<bkuZ# 8ԣ_0\AbmL-@meEe-+?> N@d: 񀓪g1? xJ >&I/ҿ11&}~qu1!qCxh+LhTY Ct)v-0L<>v %/@b4@g?x`6=3JI>O}S "7*U_Pu+-@!G|a4)O hu>+#lrE.(_xd @7An!8я1/|.BwR81N+@|'b7^ CDQAWBsEsOCCF?>O5V%/$>BF;@9*/C/GFF\nMJgO+Ain#_d~i#FS\QϒXКN Leaqs*% Mݏ`\8,?33=z&OӖwx͛C\D8LYCG\h9O``~p_͎8rWoE` vw67VWqwogrQ;vķW77 -s\jDQlxg[Oet]*J'f5 oxsP (^ߐX[=)t zkDFL|y uprtC<3IOĂ^K~8Y.dUCrR4ģ~`f_e+Uӷh5low B|Ls< PʗVVVյiшxZOONF锟-dxG*oȴ w$ ^̼_t7rT<AXTzsQM~ۜ,oȣo6_ ng0i% 6i[ry Ze> PYڎL:MO6>Yg4.nߡo ~ByOA&>@9%\@4=t>.l޽aFh_ӿۿLP o5Lb̟@9{-J]ğo?OaE|@c%/50'Z҇Eg(_8>]OKR{~=~&oWu7{pt|zWW.|\~~W,Q_cx?;>~7B?T|?'{_?E>&PgRSWW;[q[8xBPKK?%=)SP@006.npySəp/n HBC72H#!H @܇}njcOdj$$ڝu}=}%lR_lSowoz{|Q6䢾AJU- D"4,"鉅PUԢ/Fb[AoQe7pw+)W{GG3R=^|v騯(7:h*7zVQUJaeIg\y: )|-(&EBx<0 ZV_C"#O7vo ~|8܌GG  2טx5?O5R|<WR&rndQiRT TTT.O#}X0hi^ ꧭOffc3 Xt\G @ye9`2h .ˈ|nO'˻]nnwڟ.ٳg]({R[ jˍϣ*T &oy2n7,fQ4_3,1zt4r49h/ho&]%%87x GFF`_9&tY登nI> @Ãe!MJ뵛h_~oK_|}Kx78445 |_--~FxZ[k2x 558^`yΧ CC\i*(D&)P"GKa PFQSrOx抂B:NT*J9WD0P"@}g*mW:^xKT$2" 'PA\;O]Q28b|gAS_:7Ʀa C'TV+*"0 D<_3p:7_.7(^y&@BK/.& (`jL^~BC :Tisx9ϗ./-B%@~x/熎Yg%:m)R_^^\$BߟVk.V>_*18篦R$@o0i{" < ~@N^!?/n K qT`uBD3r^&Ǘ󥜿 )0P`<@ 4/Nn DkgՕ /tL _/E%񅅔/! y?999GG#!?h _TO>க>/ "~ŋ(@(4 vb_PP\A |jyy |B#Gp4r۟|/>T 2IpbAfA .ryt,rih4B39H._@_x>L-a~5C~Xjjd/-0oed# NKTrl-$I"|YwTieާEE4>lI KJ>,Pq\ZJ.bL.B^W^#8@Q'jZZ:W!)]WCTKɄЇx)G>5&}.O0~ZrWT*ңS>5F|*  ̉87t//clh4^ۀ΢s0 $2A gЗu >HG%deH9U|~E(G )777Ŗ sZ .BW"^??D w0< E%@ T{pl|oz ~_~Ӯ}Tf؆#714'rݿe ndy-J1&ݽ-X-,$ t?杤[&VYi`xyT-r|`gx|.Vs߼ZS*F3|p\;;;T-OMcXt6B>ơl9Z38ui"lć llJ"HT POupV;e@|z7toS~:ONVR1psFnAJ#?F 3oTݭm2!Exkm1WkCT+`l6KaX_Aķwӻ~2oeZR|>3[ {<دȜ|z5:VƯe\Aw`Nd=wޮ5SÏa:?3ᡈ洿o-~sURhO0ϬU~*~iGH.kGUx\PɹN*{ݑ o>۫S/~t=Μe2< ?aIJ%rQޠٻj<28 >GxEmШ$sv$3މ_O?ad5P>C|*{nCNG)ē8''>/T@;4c4O>DX\YYJ&<#sv?%>q!a%ttؽ_\<=ZѧJ0} /k?y|;) WQ[8yCR&/Р3Dv'3;8[x@|-s@Mv~z| 9IMD0y7 ľĉ{VIO`>mhK2Q}RT RĻ#O|:Lf%T|v8|xXs/pb^+jL $c>QO}e.hCj#@PLTqO9&*?حAQl}3 6Ϫ2u.zh_=yRWaAl,^^[[[6p<h`\Ati:>J, ƐϬpJe2<?NeoL#5@t 0|X~wƬk2O?L} )'pE :z 2|RI={’_[9>999>5: $NΠ+zdn9ޗ؀C:9>N쥷w֗op~T跷38ĶQ)z>)jjo/;YcXէwv6WVavR|PnkaZ~_YG7670.)v6#&&8@0`<٤8I2jƹJ^jz2F4چгˋLO }|Y B_^});*'U?>f-1 UexZ!R x7y`Lv,| >i/}Or{hj.n</ Ԏ_S|m>Z>Tӵ%VWWVMyhh n~r SiQs/O$jK 2[IlǣV~VG;̂XE;ǝB8=K\)"$ZJ@J=pvWw`/sssoݼ|ǽSRhm3ձw-$8С$ZQ~nqC2y~_*^ny`R}!hGޡBWZ)0ޛow߿)RSVf2|A)*/}]bg՛3PTv6vv~~o-뷵92jGjcGGL |tvv1wﮩ˷y&:̵xtq'⯯3Aaw=0oxsn }i:t}cnޑ|xja9{|wǿ O_t\85>Z`-w<ӻ5j~~%+O<PKK?5eP@005.npyw[Ǖdzo.bA$vb;@ `APD콃 H"ӱED:8;뵓iye@*:{k?H,{̛3p'u?Y1#3Rqu.hQ&gp9=o MFˌb ^2-5?>xDLuƆ&Buvut\:{5/';ӔWm6FNRRe.P?/BWpAkJ iefy~T*b@h@w$kjJ ޠ2?#CkI+}~m|廜_c:C7og0lb x"\|VLKG ^e6LL32s !kz2]&OyYYY& ԁ/]o\j C/$ӤWI|;>h9r,wBVǶb;;uM,|y._ ++3ow? `஦wuz=]^oWo vŕeuNn 0g]xV 55zGtT;uuYc]]:쎆Ɔ&&B g!o[]M'Zg2 ۊ >BxY=©{ 4D\{WTTUUVVè_ j* :guVlWQ\0`-(x8Go% _S ZTU%#9 p++ )tߐa(6hZTw%|T Uz`ЩuN|RJI pc ?MJdp;lb[b_gç§_UZP&N [ <f(?=}_3|!}[>5pS+ߧ|B4@ N'}gHh'`umPb].jt0먩/u"?;/Ϥ}? "u|.xx;\M-fw+ .WKKS}}Uvk;v--FwKCbR6O#b@Cz^5̵kΎfGUٛ{P wy &~ Ho/y𥻫KB8,z`JvM"_ͤӄk=>XohM __$|4&~s+! WkߢҸ2g ?;OV"Bjhd\eT?<:aUkW29 5 4`*~$/%9, }!?AЋ񌁄[ U Bx;TYF|oOk0D>8 "|*B0`1/5tᑑ!pK7'JP9yƜJEGG}O0w' {dg A+9󧧧&024yh_Pxby>©<1?;3 ~},]~].}D,L?U(t7D& t`(ޭ<aan!~^!:; *=qG#[Գ|A\PW*Qȧ 9H޷ܓ( p0nO||IRχ/ - h tNH ( }a復ݓt<SC}}q8f B.SSXF3%~nC ٠yC0CE + ߾'9"?55Q`|Q$įTx0FZ&ON$-!Br%T)s|>yŸDtppCjjxx0P_SYH_ 4pS ### .!)B{Gb$ ?!~eB|b4~X ?`,z—SEK ,.LƆ@CP0| ro n~[т@C؃ ᠳ~=٭%3p^`j ES mXPr~x?h@_Zx,RMNBW P8<99<O}k~*h0jzy*Y.TrxIGyM-`=0;`!]\$|GQ৾K$bC)AθJ"1?3gIQA@[[ɘ~`R{\O.|&<^O ȸMSdtCu,K~vv|7p\bH"2ހ\+!0Ô/иG?cK+++˳ӓ1L_v]X]c Ji!BDh?'8 q!| 3ہ!)crck>)^gz@C=Fp̌ÅǢ44~yJBdIRMYBy>S 74453Fxmno|vCF |ð3fd檍YrrzRTQb-4|1/ϵOS_nosӵh称'x0`ʭwV۫ZZ@^lLssm^ϟQdr9R@6-JKmybv^HMi^N)Bh0LcЕqtw]J H)An_\D92!D$gfa~nɩT,lN_xnyq*R /x~sy}1tŭ,ryKN$ǰ2Lu۱eߘZ|^߃*2p_|/xqss}}q,QELco8X[-y ee驙յu z q/ |ϯޛ2 pW^/v[VngI}\ w2:19 x#=p_~~ k Bo~6ШUZQH?AmNOofr'J$яɹU@555mL@;?ãj4?qQU^._}(XǕ>1Qkxo0tQrqq1DTz.uUIic#XgGǡ"ҫN괇 ry> i{`dT仨"~s G<#^gg=t3*̹k4@D4_6}m666Vf ԡPKpfOS?\UUURR">_'nwc;{۱͍  P_n 8U_]6?^]]]\ VY,fP!XE0|QG; ~+! ª=?:;;= [?wАba@%?"? 6΋ń=j_H3CzOm1ieiC>:  8?ztq~vtx77 ; |4M!v_u}xxXY ϟ6ىQ~ICk+Ebɓלwwb~{'mW[|b,\]3 `3lp3}F3NJgO| N,|ggWs.:!''O~z RJ.O(lζ9>]5u##Yr|a?ޗIhn_HͯϞG..#}`Ao/Zhw9!BBY`@-KKOSH lX(?uWŋg >fiX~  ===YE 58ǯ_I|Q!K+)?C:O>y1Xh2??355;5@YmNKV&``կZ|'5vт_&@mUO>ur5?xB$90GcWsnǷįtO3}Ljo"ߢ'R pE;)^ʿ+~7YZ2ܽ^lo!x4:ب|F&cr*?hok~ܛ _i/֥BNL?)~_~lG{[sA;M"6ۘ$3' ?D5R~uJjf@WUFUx~&&@/<ۤ0 I-%|`0d']ShZZj-.-'Tg\0'`@HK&45KjɈG̿ҟ=_U)-fOO@qJɖ 5 a2kc#6Z#da$ 9E9;;eRs5V1Zm&1c憺J5oE<m0 { nl/.-K 's2x>TC>9WgHO9= ˹#> v^4Azy8|'/txor+}wH{;@56 |o`W%j)_-uWVN%|u{d88Ut- ?֑Y5Dvbct{{\__YZDT.>Cy<{Z2 e-mn}ffF:5Csv`i}p\R |qqQx4~0`I>7K `R\x.s`aiiee/X(P",dϵʳU2|"yVRˇcAw-Wc~{.÷|¨˃Lyz*9mbkX>P60yr||rr~A e*IR--O3-mKk גLCaS` &|ȼ LK+F#!o> [yh0 ۗ`\ىQOߦ*'FƆ[uZIJP33mU\?9?AS6BSsMuQ0&xR'lQ|p 7p=6|@c-,p~͡Liį:WLJlln&ĿB%0Se-Z sx"^0`Xhd1;-3?ſ|^+3Ug[cfP#z*x]=~|z>??Wvyڠ 㯆/c\вFBKZk?񥠫 .{{ܠᷞ|3!p M,ܟCώ% 4 ~knWyfxRHy7P8?>~N^zǞ5[BK7֢YYls2^M,16j H_࿇: |+ux0 7dgY][3%?;Ƿ7諯??W+auG99,_n[[GnoҏXJw-?Z#Q,_o<=үT-5wuޓ[kt쌄Ϝ靿{hPKK? i~$!P@004.npyWgvzItDHtI4I" BD:8ƉdIq)$'rv{z|~‰okyT  Sy P1 OI _rˡ _§LpQH?A'TN':Q- hbdY{ޞ^kOwl4tkˋ JrU*B!J"Xr-P:> _6f=ۻ8swWGWwGgGgWgA۠+-*dg* 5yeR[T*%Pa|VB͌D$@tm =S.EȐdb/~ _Rq|t_7M7uu5KQoOҚ7O$pxbRIsrK:Ǐ^U _VU5h(с* P, )omMƒL𹯷)*& U |O1hֶֶ=KOb1>M@vYIuyeCShi𑿷bkQ:p ;!@?t;\g|lX{L0uqJU ed_y=c=FG\.5pCqǼccc> át0'\s98䞜[^_\\XO<M:$'7 %}`lDvC -ͺ:]ATW[ߨ54蚚akh:~I6֦֖>c]ڦ4FZ¼7 |cntY+J I?n׷AkilD:JuU%|k봵uu55յ0«uZ]SkkjWZj5Օ򢢲Zc]}* Dknj/ɑ2e_ǃWjjP0ͱ"]|5644tTIII~uu&E&(Pddd0:_UTu <~V⫫ATZ\&KER\bo &Q BḠ,' FmRl4o+.*W%|,JοZ]\,))nB:ޚ+~ʫ(%姥qx(?1ښA=Yu &L(zcDF@m0¬7-:}sS[fhH nP:dR , Y nNeƪhd󳁯pS `&Q)j0Zz̐,i!0[:: In֡ 6~(8?߸H9' x0!X:LHh:MDPZJO 0~R+0A]m(']:0cUbD _/Db[>뤻JmmzL,`h@$*3[_ " ߁zBH_.,%n1O",\mM x !1h :l6n'l6 jj C Lۢ%J4 HRK' n J!(#A8m5VRSf,[*JG|NB x^ϼ<13 #cN p:a\H@Mb/Asssrsyy"5K1ق&&&މq/Oc (e>rQ0aPP0'ޱQ(<6|ꠣfqQz"|fEO{W ֒FN&PF{' k6\6ЯǕM%TS @/C)ViD &tր ,?ć608`z# JQ4!O4C 0 T  `2K,$BLOg ` F9fBA;8S[hJe8 Ŭn·pX>00M`2iGt/;Y<HO8Lb4 b~8bik!} tKBj$$7!|A27;;Ca?\.>""1pjrg *cl|_3|C #.:)p6?^({!V?6>akΑ>8H!<n0 '`6? i(8cy, 08Hq}+VB!@,+ƙh` %I(2v"S8 13-哜2xyDmMs|XC'{Ql$<7xā{,Z@|cAC3Po13 Η&W GCAf"vG+ JϨ\p$>H8A3υ&F ѨSJ[4)|15D0e p'a̡_[`WV!`xw8|EJu<1 k;62t` NJ1nQIwhu4 a􍏓!;~znG'Zğ~&C"EZ[[J5yy~~2!ֻwz~w =zXw&|.~&Ckiɭijkf=P$\%@lLNf,rUǏ1GË>[_PF2*ft8ALvO.1e'猁O>x@>H 00 (jPPe({a!;Kq,c\}Ʒw'f~_,)56ǗH\=9yɤg)#ytr盝]& 4:r J>]J_TW??*HG_^z&+++S RL,-D!a+0`w5%*B/YΩ%f!|L8?9]^B|pr~t49QYV#[9` =%]We0~`y}-07=k }%?_)oڬ]k_}$05 &^//sbggGGMMe2)]xr&>'w0Y^_caH5f.zya?8 `ӵ._zţ ۫eV(B,AF^|}=lgvW[uuyuukaM1ť0|88AAы/ @ |x:/tVЬICsKS96|1`iknk>`.4'E4  U,VEŋ^F>|et+Wf:)q+,65L4":X^=@\@G_w_ Ӈ?\ѸT)fECb!w. LO-,-./0E@4Jd#' SW?|o὇!9".GGG RNgo;yhK``!)|ʏEcl o2:l^/>w[+bP15Ok*+K-CI #|ǧKD% X~xԤm!ܣ{L HϜs|O"Z N ,(~)]>_a@ŧޏx<{FX~/KMeNM& /o@bcG=\_[]ck`6`w :}kPL9=<gga?{:V xX+y`w{'YX!t௭n”l5v`Y聏Pxރ?|lvx!WU$/NfJ_]>dgVK 59O>F?~**uh?ogɢ6WW^~p,>:<"o6&/w޻|r@J`LO-/P//?`o "qnϑÛNʿs&/QgTP{IAvUgE8[c D>:ݷo2hx0򷗻e/LΉN.JWQak"\0 a_>|p]wwvw7'߹sq'/_ ,+-- 9p-(L:YeRnzϞ]>|x3tw7:x3JH$s/SW$a ,en!|;/?w>>>88:$svrq>v/ a)ƚ8f p$sW}G=uӓӭͥ ܣns94hs{{͝]9!x\~6-?;ÿRۏ/?۳'?{{{~B|mqv`paS f _.|z ae,>ǝwt ޿wOE Ym/*).tnnBE?{x/|r~?yË?<<>9܈jIT"@oyndO1N RE"SRby, k;_~'OX]rπ!`  eM >yv%R_.C> cPzx03I"NÇw0nS!t5ҠaVdzCa&ᯮZu"c![P%*J%{z(WstE9jZykC5e04% {{&5 ^v<ĻUt e&k W̎`l{{l)Ǘ` u@WI2U@DVƒ ^ŗߏ&?HD >cm3rBomoGdKtzfVHѽ1n$>ǵ 3J Bb0͹ >7ǚ/a@1|B!WdvNob?!p |[7Vq/d^i2Y۴\gn3 /ߺeLE,stLx[Z蠣o&d! {e1X|fVw޽!CѲ Nꗒ>︣BX^U:۴u@:;\=o'S(Wڲx_Yzw܁ZcHOT*GZr737[S|YP<&Pt-{|zr8;.^n?Q:8͍y䖖b? o<ъ ' Ԗh/$W LT tsu<_U>=766bQfψWS5P;MR&O|DC.Ҙ\?&j!pP-{^}?_~_BPRZMV _&΂DȆ6N뇇:{oY?N1ň!Hb \ǃ Tӛ|LIX-/*{?#w2Uo$h'sK_`!Boy3%<]@2X?3#~±(_Bu7PKK?;P@009.npyioGn6M-RWwTV299A2>66a2:^+ {_,[2ތ=4wҤ6|I1|<*l;ᥜѻ|+cK`/G&slv|_.uغ՗|.?3[ s?_(+fFÃƌVVs"_\ |zOm]b I`dSGf"͍u灁a%F S^2ϣNDY_ω (G d˒w:F.'.3; -W`fB|IR`\W ^-c!dk.~-g8>%|sxF߂y3y loW h[f+7~u"LM } E<%-n&h~3\_LdV_F8$ xl^@ݾ3}&MCi6s_+ YL|}}-b:ǏBRfZYGk=|2/<18ePT}/E, LBanND8h X\N&gqU.*e)?]܊DC},~h9{ Raln .<.}\v.|SP"+@>+{^OZR\y(H @ *_ק.ې/Ja~>?P)3T^ fii)>^~4~xXMFoZV l(~AWӏ_ʘz>zuEyxl&+rB^iXr1|?%"<+Ipa9X~a6d=]l"V>:in'j`[X~scs3(Yx-oCqqXhj 02t<9`(ܢ|z W͢؆jK"QP#ّ~1`Z@G_܁/U~@ׯŮFbR@;SRgV G>xtvP6!"sZ[<*OW&6we71 (@J`/w, 5MXMuS>IsUGt+hxa 5< dO[9,/ Y;~/syglhl|2 AT::$C܌P3<]̿w*>{QOC 0̵yۆfx #C~=Q˜=st:KǤ@fO(}$  \\u&PP|7_x4Xa;%6G8'G?}Lx *[ZLToA@e{KKюCxƟ@oq (H D˜}+X}$OU~W @qy" G"W~o16M o%gA>{,GA|N!?,(( ;'z/wU?[,<!~9^{,OyxK}f٧?ci~vq#Ic/ZZΗAX^|Ʉӗ`*K&xr0yC @/ 9Sz $"_ x@oS-jO |#py(Т$`y/whrOMoi$8Uz`6=7}=|3*1nB qpx(Dϟ?~8?>(ΓH852ˎu9C>3$/\`ED/׿6 ؐwߡ}[뻼b#D(O}c{j|^E0ޘן;dELo,O@n-Sugw~QuV{xueofAcfo\/}rsؑ <9Wol3 %:zD]:W  qnGx|S- ! U1GX6tzH36|E)Sٳo`^{q}&Mr,x}Ti1.1O x -lqzU-“χMόW-KG6w7YG>}2f>;>@u"|q C|7{x[ҁ/tZp(o"m|У<@4m6C#r3,݊55|(U^˄cg ZXmV/7YkjjnԷq=ynwtvrrh2gyOlr ،a]O< @⹳WLB.oz 6r{竨*:{{{g77g'VzP>"޽/OJ2F~8^['3T ַ |pװ%Hj#O <V6}Ÿ^MX@,eyA`xϟx^=`|'y4n|<Џto4ԏ|T䉾[Nn>~/*l?ፖ } oh^on1盛 -P石|wfⳟg?_~&>aB ]^?O?/?cߟ_}eOd~t_ ?Gb澑R_}G3?GG5^PKK?z^:FP@008.npySv_[23H[Mf3#"1/IMj*JM%_*՛JMʹKw߾% yasQn͇]|K|P,RktB)8z=XXI;\o˻{zkXxw,m 5Nni#e1t:]5_zTV{ksC@ M~.kГ}w:].|^(v?@ƏσJ>VuvuK{g4muĺcpZ& ;]~ ~(|[IAvRmLwi&p8t6xjZjt+ nAȗce|QWA߾"o2!HJ!V!@;_VFg%hL2pZLU}QUх5Mɤvq>>1NJJ`2}LU"9|H$(SZU@VC18߾qvvn&937L,O)_yWW<=]fԾq!y?K瓤Wz6 e%]\L&w_- h0T1[YZ^p)_z^ӷە z$> @COh35}j0~q_g|(k|` 4} t Y 8@6bpo4+J*^ 0!تtw~L%^/y1l56>,Ӯݾ4|RU'/)6q|~gg$'q<¾Q}qQs˹YF̦RLMM~@K6kayr~᲏)455= @/K0?Ϟ5ijtJY%)WjU@C-.,&K4PEGJWWaLg{|N-XLkVYXLZ .}ӗj_UF//ACD|5< J/K`O$j]˭e=}h+Z> PU%PTw8,N/ra'H'Ȥ3h~@l_l*p9vEZ܊+E$zFW-Ʒ+ + ~ii!b:O*t %#b2rwqC++' iO_uhZ Mt&r+ `_]atTJ]]ظ:DǗrobC kw-+L樈lQQ_U. 6QEK jzB^>2˧EX<=p]eFSzo)y3yⶹkC-IwÐu"8B6_9|eNQˇrᰋQn#;|Bw*1Ni}jCJ3x$u!R>pm:{'>J;;;3;G8T(xm_sʏQIRIq8ܟJϥ}HE?~ﮟ 46Yz͕P(znnө/wP $O<0wݠ Ч+8^hAY^ \ Pvӏu'=_/~ 0yq~vzz|"   @>y 0Qv'3"uuYF%]1?1>L_o˻ac<}kcKݼzU>?;9:iR`(Qh]ط:cJ߮kW$8lC}=A66`48TM(/ ypkOn ^~"&Ů N*8?^px|%+ Fgx /W\|H'KXlyH%/0IɣW^~T>@p%>vw(Z~{{O֛9J!?@t@ ;pW d1 W_C͍d}~8hj^&g\zsyqr _PxN$Fؚ\hrW'3lO>'AҧGTby⤖,!t]USnN?, bog{gsM ELן'& 󚟱Q45{̯$$$el^96\z!>y[ҷxgCHYhxG>&5os6Uķ/Ow+k q~*kc uO#Le_^G VOaurET,حkh>Gd^[y=72)2_ۏX'y!! ?Ҩ׳O/PًZ"i PPCN'|S>4Ǿ `y1/QiIm"\NnYjmPz'xkj3|@_׈xǕ5#gg"➶*8Tb|HDFv...W/W 60 Gf\}Fr_5;mC|ȫ4zjQ-@C]sY =C ~d_/jku~"(G_ߢW={|3Z8>ۭ_%/˗W}K~_<\o_K CT! x߇˗) ]/l?a-_ypVѹc>QO?ן~6ڗ}%@`|Nonee4ދGIhr> P۵{r~{ֿ"|?_Og:?>>;y_? ?oG7>>yonpP?_%axk/PKK?%P@003.npyPKK? y+P@!&010.npyPKK?{w,P@55002.npyPKK?Tf}e3P@la001.npyPKK?t/C9P@000.npyPKK?d!;P@^007.npyPKK?%=)SP@006.npyPKK?5eP@005.npyPKK? i~$!P@004.npyPKK?;P@7009.npyPKK?z^:FP@=H008.npyPK G[scikit-image-0.9.3/skimage/data/disk-matlab-output.npz000066400000000000000000000040251223313777300227120ustar00rootroot00000000000000PKK?+V003.npyPZ\n^Sj_TR_ )*M g$: : "@F12"p9JPKK?~Qv 010.npyPZ\n^Sj_TR_ )*M g$F: F: 0 h! 32b2\b Qav⽉='Lj#PKK?\Ri002.npyPZ\n^Sj_TR_ )*M g$: : Č !bPKK?e@LY001.npyPZ\n^Sj_TR_ )*M g$: ƚ:  PKK?=\GQ000.npyPZ\n^Sj_TR_ wK)Ng$: : pPKK?9"l1007.npyPZ\n^Sj_TR_ )*M g$: : 0 <(Ȉed'dBw3PKK?صf006.npyPZ\n^Sj_TR_ )*M g$: ƚ: 0 0l0Ȉ{P]6PKK?o_005.npyPZ\n^Sj_TR_ )*M g$: : 0 ȈKPKK?2]004.npyPZ\n^Sj_TR_ )*M g$: :  `0Ă1XHj`PKK?5t009.npyPZ\n^Sj_TR_ )*M g$: : 0 (0Ebbb|! lb؈-$ZPKK?_t;nq008.npyPZ\n^Sj_TR_ )*M g$: : 0 Ȁиp!FF4tFF4 3p_0}PKK?+V003.npyPKK?~Qv {010.npyPKK?\Ri002.npyPKK?e@LY001.npyPKK?=\GQ000.npyPKK?9"l1j007.npyPKK?صf006.npyPKK?o_005.npyPKK?2] 004.npyPKK?5t009.npyPKK?_t;nq%008.npyPK Gscikit-image-0.9.3/skimage/data/disk-open-matlab-output.npz000066400000000000000000002642771223313777300236720ustar00rootroot00000000000000PKK?E&P@003.npy[׶:̽'.D3b";H I  5$z5%.Ǝq'Z{83y>lӭwZk{.koloR/nZcSYY)GPvQa56C_4%\oR%iNms{'fiL&[:wtttw3 P]QN… %bX(Ri.Zį4XWrN&_/72/]1|mU ^N|Az.5q +9!lلoJJJΥbYkk~[?i~SR|>G秤2ļf5g`c;RSWmL;;:;{Pwuߎֶfy-_zB9+9/qpP:X^ z(v0F"Ё^vv m]]mm-2B//--,;/ɁSZ#NK~ TUPIl{e~RPVU]'oohnxQA }JE__o8 77VWVWI2SEYK kkryEFk _hV׶6 *C*jhP90Q)jrpHFFn|o;U_()>)Kd-ͭ=r\~8?#x}̴띙t_Z^^^hxa~~emcsmskkc}q~a>5a#ZV@um O ,t0m25b4E&}APVf+lp>^B̤L: UU!|$Lm3O#(?LJw61)h `l qW`M f^Nj4#0o|Ȩ~ĬkuaF7ѨRT vdT7262b4YL&b٬V1>;IuOy@wzy!WvB"mmjj+XU"xb=|&ȴFyc}m}]^Y=U"+!֠oⴅB].7rysKQ.5VSVUUyIyeuUUePQ^YVQ^ % ~|W+/K ssWUK6qVvJ~UŦ 9q*ZXI[ZeyDX_S5E,(7^jX*kllՓH642j 07\iikv E.@gAzVP Bwю=5#-Χ|sαp8 ](f,-uI;ۻ[ThE:/@ 1ssdfy<.""QN2$` ҉`70OKb,9HGc3gff|);fD~)>h8$/7Ksy~oO/DŽuQ-T@lj(U~> /fID"j1~|g*d n"K> ~W)0O%ܜ¬*`% o >)P*JB:zzc񇏑)mE<W"Jdd_2h 媆Sk@bH1g0J>HD;lR&l6Rd}91~^)_=R OP"Ny(==7'xOeffejOg؜M&q86::6f}XӁD oo557D>D<2);':IV}S¢8? (I8KFD~dZR9RJ-HT~2_"L2)?0_TTQA_$:IT d1 k|,GXtjSAok*a+Io|IV!MXiЋGwaHFN` n0Hiр_Q!$6.bv&xe‡gM>/G#(J%PYv*/bLƙr Lh4ڍ4Z'k*P΋g>WNzr E)[ -M&CJBc']t )c:юutDO=IgY0|b uPCzE,*]`aq;6f)Gvl>*Hק\֙3gX8 1>C 3_`ɀH2'`)XM Cf`G$7cvF3&/13 $$xd/Iw9gUUmt'@'PhI\hQ͆y *\(*KH@:/cn>vmm2^jI՘IrN\55XIAᙯ>+ԣ:ҵ|rRKNA lNCXT>6dTQ qE,> 8mt 9>XYNߘЏ>| 0TEbi_٬II0IfpDi BA*OMhɇaYHxnqx<@ ΟtٴKKL.^***"Y\IR(I~" 1٥RT}##ctx&= 3/^|3$Ղb}?{/JQ+91! mAJ*v7%-KB96Rm6lFAꟙtM_# „ozf 'a{"ħ |Q$-3eCae.p3@Er Z/yJ@I޷{^߻zHQS>>nvÝuR0MZ]^u}}c=AS{a ;t:G3lll]X$Aؿ6Wp`la{rLh @慚ʲhzʧ5: B&/߼v*/ݾspykii)0(jD$&kruCaR5| w,Ɍ/cx͛w^ ;D;K@ssUvj'.7DMѩ3Fv 1#e'(:Wh Bɏj1.wo^Pr%$2 ;)l(H1~n~VQm9 dŰxs߽} .9\ iss借Uː)g=9y&$3x9MoGf¢L1EᇇƍhԔ' qr>hR8 p8B ,W JoX- Դ̀8:raLǨoj4vȐfTiȦhtkei1 }>_Wؠ Fj<w  ڿww`u:V|>b{碗v@@d~xmP5 Za7C=រ}3~x3u?Fp (x]jmb旉)j>uDf})w͝fXnX?1؛7(9ὃW(H<ۯAM\^CM㧔TKN (O<ӌ{päO3o7"w^zGm9"x=4PnlLyrvWFn3Yj0ھ@Gρ߽P˗/ܽre{;~ܳ/6!߼EggGHwܸH<3> 3c!<  A@>} _b1^$țKw1l߸ݍ{:mtdfwedD uC#k;;[kpd~an.GooQ1/+w'ܾrww|ݷ5P34Fx# ׮H4 H bv~@s-*_~v!W?|=*}΃'޹! `8Vkj5>07AՕhdjL 4 ,fn2tadXko޼|;>8}Ovv`f2_Fcpz}X^wR\̄ OfhQnX58T(d pO?~|x* P} H~}誰]EۛkK 9/DO g됕bhC/?<ׯ_?>·rc*"Mf xxޝ[7A#R ZBV}ݝME1ӧϞCy  )cx@c2߼ym.եnp@ ۺa-+!%/=;sO}$JdL J&&"֣޹ݍWww6֖W %5 %]^_QP@\O(ݔ8y29 E,P^>?~v||ttx;T bc}ca31VUCE_OOG0Džރ=y9?p/m" s38rbXvh6Fώ<bxJovz~> fL ^7HJ{h'>~?9zpη7]z*V+/)B*ՔyUc[ࣅힽ;1&u>24SR`!TX<뇟~ ݃7^K4+P:!+QhBW +^X-BS2N?T'tm:'%]=F?2E~zB EUvbPq3\<;T$+S*xDJTA?7˟(峺 OGx(HO~вERP'\]dnK-/bi~5Q]$p8xH=rg*&>gJӅ>_⬮Ůٿ/^wJ$q8,[ğOO >_`߄)?L?j"b08RxH/3MktcEZN0~=kjaIq̵UH@GV *߽g{x&˜m0SRDBS")APm2{B'(G:X.xCA1ol75qB)xʇ2Un'A`ؠ/ci~;TSV_JbYH]+om,_&5vEjy~FӇb4D_L / >.~Bbp?zOOn^W*jss{( x[,/-EUrgOOC~|EJn.C#Bxbpd/,Oz`?Ŗrev:kX}gL,p%+6Y)gu)Qpymy0+df-̍.=Nפ=xtyL&}vD.s`ؑ.wA>,aƼW&8tin6?tѢ>ta]]s3+"`LՊɃr_ZŢEE30Kja.8N׸fd~=; |%'\Q[䀕 1_^df,?ūɝ[Fvu| STjU>{Ag9BnWA?RNf|H' !^JhTP&?B崌.  t/?QXtQj@ш ʑ Nc7@ ӊ[\s8U KKX.LPg–=aSM~L@hwRyit>| xt:Syۍik||j5(e{GodBꪍTA?T7vCNVd5e7"LfYv9]q ;T5E%o2eBJ?dӊ%X\ߠƸ zxesw|o~KphliL&#=Ctvq\so<]Zݽ F"`35y~z h`֝p%%D̈́ow69qX^h\t& [ٽDln.Yo%DܪAly 6\&wwiqe}}ˑwҷw?YVYV\F%%q\2'nY|T?Fyӗ|t;dcxAFE/ 4Mlc :'H^c_>}D?>ow+19Ao0q?~3/mloAg?3 WVhs/>Oo~A'@?q14K,6(Y10M9S@hqZjIAW#ss~wosU+.='Yaψ7mm:6\0^T3_O@r2_')ލc AS3,L_~ǧ>} J&ΖKpPKK?NP@010.npy[SI}۝J7$dn#BH4̀ ˀF/cwm{::22_`#v_wl{̪,aFh~s2%UʿLO?֊PB ZveR^ޮS"x"1z~TLcOLt{%S52ПJ&x[HcWP֭ښ:(-x}>Ȥ&`8 AɇT u>!ϫOY$>ڠh2ѧП/͍LFFr e5m[~[> 0O5E&''X* zm dcW`JdPES|W `J0;K:pc?)HXXQ)L p@¤_ >H`@Xa w$Co 5a@VJaQ/yffP]a/`M%\lvT,>*WW cE2|Ljܡ}qR B0AiL5h_}{JENP|s9h@s0S5fǭpӆ.Ȱe(Y73]@(fpD{{F jXmv |K*{Ro2B9 !VU/<*٢y_g `-St~:9Af[6@Ƣ<7gi2%P7lQˊEWD)|ZX2%!`S3UT@%#oFU{,J=_o1~{ss1) ?q787.MTZ RcWuȻX_f0 uNݪi$tM1@qm2_ _>Yu'ja˯z5Ald|}jE1;ѶukX7ч"O7@6(rˀG]'/8* R=}hʳ=I>KſyM :b d-bim>ćjM:[B,:|Ѝh`R$ؤ˜6vm2OMM^bXK< ȶzh~=wK7[%j?5p܆ b]È`P8@㧴yVlOUyyi<oz0LvAfxhx2uڕ>?Otf]rFPMtfxPwGu$QXgo0^y T[]f>Pwy̎F[}E~e}&{F'DHommMA?:>\`j*s 0~\) w(1}l,[/n;ƂIKezh_aŅ/(y)@8]n8ϥc3w6pB/?2-?+;;L*_K:%8cϜC᫗_`o 6W_?-3}~ueq: EȬF㿧SrGTlھdct~~av驨JU(,  ty|@:Q8zQy6j @\期#? F]z _=;>*nllVY 8Gt|‰@@5pz0 6J6֠ElFbƓvWYX)f(aZF)C. gByv[`!%s6~0xHcgs4q+xUpi졟G~?TR|?ԿO5~Ӹⵔ~6{ >˫ynw6{-c80(Ot o<} ao)s\`-oa [ .WͿse {;v.}itѾ_(nv?7ߎ\Z̯Eڻz M|p$> F|B=z#w' vJGb.誠0/v ]qyKbz")?OLdʊJt|q?#3†[7CFKt_ː #tA>@=lqm+LLd-?oxT_NjׁH P*k;]ev'H}}ix'n Mk񖞹D@}!l}H\| ܞY8qm&g>3Kcn0`M"eKj1qw*HPY:sNnpSSrf 8mL݇"]\}^ǖ Uaqٰ%^OdϟK >C") 76?8wKzU6@ysŶ/w/.̣z#U_kH`|7W/._B|$?/4EfI'޼zsO4?^mYV^7B%"_EacZ;o35O<eE_ prA@~7X)||x.ole1 nfwww"~t?rּul/񇍇˟:D]?R,W034vlԉQ@|_\9(_`2h0ⴊeGc ~O# ޼FK|{VyQ/PKK?)+P@002.npyCۺ:̝JIozQz B !B BH n;m۽>ޠ{4PJ(Ϫϳw⪢ofkm&@X"3Z}v ^iesgA/%Q *BBWWW}(+k\-uTTPVjjk뚚45566֪jꨔdfs%=51"<\.bs̩S?W4ƆPqNU>7+ll P()6'D ,'>2̷OE[oy@Eeu5UUUյ*ԣ(uuçg?cI@. T۬3ss Y_V_Y]cU__[rj/Կ *kà*kk//.++>--))>.&lظt@LZf\" $hƚgv0#'|qAaAaYѹsE*SEP(*+/CJss3c#RYd|لsiR&h~V|(Z ks־fuk[{[kUXަnih;u=]]ښښ*L 11Qr &7|n߿6x,-+oO;|q/--fg=e߷8;7;j2]ZVӮA37U[ؼ{a=*{~%t?sqw]w ;;6767/뭍UT,\ mN`=_&qu%ݽ xp_?\|} KxuK{w.KW^A։O/^|oIeeO__W~|yYa_.G_b_qstNsj91阰1vۄszzv~vf5ۋY,019(vE76/^x[_~ssn]Avj:t]iSk4-흭XڵڎNmWwgW/Id4&i``ph`x:2bqXFm1 KAwfn)ĈAo]k4*V`NJ[|>\NVffN^NnN^~~~fFV^NNnnN~~n~^nvv9zs\ssEHJJ חϕ׎tgY,Ni6,M^69!*.F(?47+/ܜ,JLLOOKW3Ӳs aWsK32RӒ&'egZbK2$h ^9WFɥZWީ+ J KJ&ťEEyyEqee%JE%KΝ):_XQ\TTDIJeEE ~&39$c)D"$bIxt'Fn %Mu (u UU*U5UU*U%JB_ey9*DL#6V76ԨU(e,B!OP, x"O(Kd,j p_CYEJ6,&XJ1i~j'PX`Q/xP(@6$BKbYDD@Բ>AfWrS&R[[ Bxy\\PxS K'~ YU-Wꘄ*r O"Z0|vFB)CGE £xJBA rJS |㣛PPD*dxB ?/g|5kn657_魾39'1YZ(_N2/ oR1458~KScSInnnGcC= ᫫olOׄoG^]Rrlzza\\+RR)ET{i 62h䶵"kдԌMU@uMuMjhCus,q2TJxeT '@& 1>= \1FWTجم R1)Cqq񑩩d'@ % )#x{DC=>CצVʠV?99]v ťuKx&@x&D"'+08-bDwDbA(P6a"*حASM+wxبlad)"ScbXO!Xejr<..:ZLkG$Bi1HaFëjgMɔ, FS@d"F@'&F$%dkQ*2cxHq2*kiשjYvҶ2sK#*KH ?1###+D /`  Ζ~65uNLo 7B"kM,( J5ʚ,N@JqqS>g9%6AX;8l#fТnc%D'82NKFUV3P&&p@dA`6ԯ"Bʚ&<*e%$D>/'ojjki |^|^Mv $'g&!@HۧŪCb B/imd:Ç 9R.A| 'א)g2\62 F F%6 隩zAlog  |! +Hᓒsr@eؕL*#'|Ftj@ww“N]׫Z`}&:FNXCJBI$ǟab>7 c vh}bLʬ!.רeL x~UUͥ"2/9'ck'#XDg*9j%@>Q@NorZ~ E. 'P!C^ՄIr92"AllLVVP ?>% 13| HV? m: _@OF&IpVwV.<>VsyT hi TU)8<DbqhTTvTL<~ |ZacЩYC򳰂'x1b^rSɃ5Ciljaq@,eЎ10Ŗ~% y!!!|$8XМ _$=+᧟! _4B#M}fFglztc2 Tx< 'x 9}I0!p"=H"AH 93O!+~J7@b%Lxè~&MOG&x?2< JSA V(+~Ke2I)0GFlq0k v;=1 4eES. <dS],=A>]Kg42`Zm6&`u/.@`bF̴d:1OM ^HpHZa p ]7 e4M,8#!]fwLNB~Zr2='YS$pO\.Wâ P˭fd9לb&?ү]ZZzg'&e79mpp0/3A᜜ٺ  hc$<^0{==eaL`>)2N@(QIyF(y,!,>{&sNy̌ȓBھu bS&DGȔ05@&Sdqx*&׽/z=.o_F{ff,'KJ >uH-*(SU@@N:,W@h0 Xo~ҥ͵Uظ 1\#q?{p].4ov Kijjt S<\N/+5ˁA. M={{_۷!@ W.o@ hivP$p:<H^le=":ZJ& )4C4釆8ɨY;8y; M7 qԔ)DLxstwєalca'cj̊$T. LF  ?2z}{ n6)Mff\*8Cy<[.#CHHQ(䔄9O(ŝͩm.rt|"0[pYݻC{{HWep|s 4~57 + omoh0 }|6fu@7}|ͧG$!_%u4gQR%L t]w:cHe%f!nF$еqǏBOA$nFFEGG*[zXI(W=  MI}FC^ׇɎNf%?-F+?} ={u*W77^#ᓪ)W,My1y}Ec1h ,##!X OFY Ƞ> իWGϠ?ٛBslR]$'X |mKl_Ȉu@ m '' ^'Ϟ=!m\(c5F}=H)ImMm=GLJH%pṂhG񟮁57Qyz||O߾}RsZF҅͠=$EaBIͶnsLJ5f8>;c_| >%`fcV޾}{!8X[_[4d+4Z[o-*Jiv;nڲFKL#6£/05 d'G5{G!p͛צJ+Zo^?h- `X܄ ~iin)C:qۨDig/d\yO߽{[ y3V+l iRxqϓWhטvE<1aƎa?=;g6 ޿w9/n[s {u҉.lo{v饥խkjl|@32۸AI9=r"qRcm6&0C|j|d"T }ǷHp*o^߻r+59Ƭ}}]F;~yyvzvaĜr:;m;gfNJkn |޼Ν[7on.y֮޽__Xۿسiݫk>eaxkyNx"ffXv'>QVp? pw{.>K_|kkLk)v/Ռ~o__yܮkfʁSp=:mSY> |z[\l=xD\wo]s9V+meĪ6v޽ymwgs}}uŋj5?ᘚ3:kۛʲcB 1n_:xpу;\GO޹IVoÜ6zw٪>v77VW|,'YgevuCiv4Hk{[wBn>y_q^χ#[{T2S !8]^L- 5 ޞ]7Tdq߿:z|ڵLC{s|"\.gڪA >9<7]?^\yb]vttɏuunR3GO=zt٪27{KKpf@ K_߹{Ÿz݋Mt﫣CIVc^3w~{>y#v*Ԇqκf얖jaJ篞#;׮\-j5--z_UR>_?G^ \5,~ ,#xbH"Wz铧OέW/noo>PKۉhomiR77թʋsb,GH ܿ84T*#!05Z~bji 0W(޼Gǿ޻qƕ[Y:8 o4"[i,L>zGq"B}tdB2 YmXƑKW ֟N>|/?{.\AD27\Ǝ8fftҌ ϟ>;z} k |o8 E{ 2 K/r\<۷>y/Hv҉1m3T޵0&Ekjoݻh{!^\?rA@-jR,ᲠUw|BP}s_1~~+k>1|E|D25{_l*7=19Dx\gmqPH,#”a\*|agݽs:_ |xn&ޫw?9^@.aёJ)try"< ȄܬX </H/ޡͫeV~ѡQ:eS0fꦁ-"MIJ.+$g$E+''%As2k~p޿FYcɡVC6,uٛO~oՍ+_$;󩟃H@YSRcxO?G z}$L}P[+|͛C@ImK  EӧN ʸT K-jk׍\9"؁O$J D{;?,/a B%)_]!/xE25GUT)9+ڻH3SstO)"=)\$iߣ]ei*M:!!'xqrenKt{goA ??/<|{,GequK&:U]n8l()@L( DD(d Wk) @yB$p>=,/dhDA/M;ٶhj%W|*ͱ$1Á`a BHtJSosqs ϸsCLUk s3mєê+-sӿ9[Z PL LΎTPeD=QIQ+5)ly xtbsn?=WWgeHHh3Ë@2 NM5{~L3>5z~;0=E ߤn`'ImYG.Ϊe1,\L$gSP؝. {_2]`meyl 4[Maޱn4&XEu pMD`?3:"\{qg/;Fb }Eę%7c?w<*bfD|"$6~vӡn|@9oԍ^sjډmc YVz.'k.~w Pv+xurrrPo#OaӉ7Uch4?y4CdW7B,I4]GeOC{!`g&&lF-*Xzfz 8d[ټBy|1J5e2ilZngl,=3xKLoC{u[F3>:L&MV۷w~ igV >n6`1->">cpxvR_K Ls3a ]cܚ+nTk;gfJO qGrlO.r-/pn;kfz78b['mMmCmssټ %* SҐ^[[l.ck4nR^m4Yo>weßvk̬{N' tCE"\$ң' OK r.d@HxЇic|h78\?}ڶ&;stnK'Xkb*i\q{Xbp=*/aW6H^nH;!Z]]Z--(NKݵ}=X"?wXՕS-lJ7%7݁-72|jjuifi/Ė ֆv (M&>ѵW~iL 0L$ |4juC+ EX@16n05{Թ浻~'W.j"2-}LfYPcxÇ%ig`߰'Cr['=+޼;O?'4$Ylٮa,|!;-$G.,olnV7si;fiN\ً/ן$'Wp\DJLoDF(cc%|_ljnmkcavvJ ;m x!; 6Z!dlXZpiK\GGꪆfuk]Yqaf =+]Jxv谯Lpfd4|~TW/,x~yq;/{?ǖ梢*bifF=y6-WU$P +^, S J:)Pccyg55??8< μԂʪJ12rU*UÛLcaU˻;!IeIeiV~A`sMo RBP OUّi> @_'ּsn/}'-:wigJKKIPةr> r6t +hz3vQ,L;h}?'w?=qR !9U ]. v1g퓓3C[X{gf^pxT z|~>D =Z |Ir8VOϣHYexc `}o,/at?m?=|1ݸ"X;HY^TN!kkj8$oxN,<\6n~HOmChbyTJaRqPKK?R-3P@001.npy{gW۶o}*9#*,EAE1" ED*IQsɪ{3=o^j{G%  _\%b҄oDijֈJyyy𝗓 0'TXYBpf3pss"=0K+j xq]m@ PPBaff$ferSRɹt 1!$J#L0^^;y6,o* ++qm}}C4ᛛĵ5š:H KxET.͢8i9iE%%UUM\ G;99 `ae-ko:2p].]nuOOY7AHԀe%''%&IV@" k 0P @)t6BM+\)?V֖92q ج6}f.'}68`0[M:Vۣwe]zcpha4[͚na Oc'0T3!)V"lhRw7*Š770|~fA`~nD( |;;; /ʹԬglZVӥRf+^YG+X Z[[_[`᰼/X\Zށ؀߷67WWWV4eeU}f=i o}}58_ׁ0DVavwvvwwv ãÃ]&zmx`owg?<< AuEP"ԑťeHe+k+er8YXߌo`w?R{]]JEgwB٩PȥB.W ɻ::{]=*eOoOOק^7&bZlqfCaϐcR!&0` D եP@A'Tt OZ۠D|~mmljKd4k // i*I2155#== P8> xFšPȉY=ݻ fgC!:;ꐷ # $ڝcc3er 2aKMeɉ\vjFFFZA-Gr' IISkz5*WQtʡ)auu*刃\ eB);;n}dNRNNNff~NN*?7׮h*㦖vU'd$$(Ęx2L#&I(829Io鴚>-> Gh)r$cM^f45*DMRի6#x|Ze'>Frvk&p,%1dyF NF ($#F446XZ>|dI<>RIQ%,eخ9 ?"O`,H_aΠUU^W!VylSP]PFj5FU*EHv55|>B&OC&"RI~ !2c&8( !yEl@+]'SRTTv@~H@H2/`h-2YޥNzad}vֈE"JsSXd T’\ svVz /)cPD[,@o2zV+$-Ĉ%&- FSwf*Dgybf )ͲBJ rJy ~xNTTrr,eB&tve{K{K@y*5882\Yx<J+~&cb(n+h(hIU*U{e 36LLIHH/f"h2TJ;Z{ͮ6C -Ba<.7)CNǠ,j Zhv蛚Z +JKSb4Z" fP#xdNM*komh3!UkG /WU%efd"+ɎKijL%kmeŊ!Ҝ?.`6 Y 쫀'Uv;dM E ުjTu f4G*ϭHΥb~ͨ5[࠶P4Vj & `XEWʿ( )ۺ 6L=GlHIAIlvn.`96*jɤmx0+I"@.HY-` - TӅR@ꐙWlo 4NKja%V~v 6)-6KOdФs$aVW$R S@5V Л] uJ f Gl @ܡj:y4Ar(տKmd3&kk&Q%8[XWV+:x,INN[  ijMG!!*>h7@OJY/_XX(<&v\LF"pɅuY7SxZvFF J!c# Jjo4j.Өnڇ,Ck1N"jɲ:qS`C'BcPTX\$3L&7S~: ?+e,m7j.,`EQG$rFlyE3b2aIj*-;9L0x5\̌B_5U6ح~~]1D\|\xBU Ob2'H_~헒8J+Z@Iou>c(f 2ˈ1.cD;+ql:q7o/ixZs#H$1t X!]pH) <)\[xy?7!%VQnqhcN=h$"f2pXAل s13Xlz "A&DRҁ<-Fuxx7*ԔF 7 y0-;#0q Bm6hR?L0QI/G!![0 njG1N'D|jazz2l Rd1HF0aġ-ظאBI::>ThԸ8"5HwtvC!bWvO?2t:{ /ҁisڬL*Π3cؘ_cʛqhapPM"bƠS`n̤GkD2`rOy&Gv;:Ʈ?p@# gf2.Cx<`J@#h`{f&Q8v{mQ7H#%'gmÎ{_Q݄u@@UkfT^vd{h`gg}1Yy[M$j R=|הN޽TJ54ͽ0ʪU0Bt7Vrn:ooIa*̦~ [-? F;:}tރ;ۑѻώ G" c;@)ƭ{zTiQ8MEIH0 hQbAQ'Y-mB0꙽w~;g@A$"nEAeJ6$AOqݰ>K;d~E:fIL$(i0K&TYC[ ~^c{p!'O?^>=!`}ev6Ť"WW1Ժa3v9!Ռʨ둵fKZ%zISs[dE@c "LzՃO<ɓO̓ݽHdQd$S[2vxu1Wz31CzZ .h;z`7 mGF@cPo1! ,=}z|||rWϏ⢾9\vwpR@8gQ|ЀɬӫZ25V`k[52!uY-?uO}󋓧 ߯$qӹuu>tښFFd8x&U-hj٭Ǩ]v``X=>qo^_\\{lll@TXȳM|xd{wo#!cN;A `2jmؕ }rNt#o/ޜ_|II]X֢y^_gSr:KzF84s A> lwBuHQH菎hD8:8՛o_|եl[n2ٻ`kgW2\M?:l`aEamHp6D`x UT9<ŋ޿zˇw[D¾fpn>؁H$TfFk^_^ [ކZih{l 6hMqŧϟ޼~3XZٌDD¿޾`gc..xפv]`0=.pG768 cF4}Ob߼{8ymn.coe ?[[l\krrf!(r`qx4"D憟#`!9Fl@ӷ?ywջw݈)ԁOnolCa[v^-k[1739Pi?07+R枀AVp\8y0=@ i׽w(޽{wvq{c-ҘO1=zrjdZ UWt{nRS3SnV3{"+sӓq \N^|gQ$lq}Źj8t;zt)hc[6}]OLMLSn(_=619ُ9,Nzo_|͛7η{z ޿;+ {{kJQգr< k㩇f] ANy KsF1 B# 'M@#0tԵ^y|wg}no{;>?9;yr`#a?1 4MPtelzv5tp;{Rh>LON@rONMCצPz{] Wûׯ='/l,{~N`C|M;Ւ' amF g}Sil_Eݝ] *ߍýӳs$݇N/ί^]a b/~^  SƓ{o@[,CsA̔g3=3.ww+;]E{{Ks}My3$7/?_< K{7o0xLOC`zn)LfW^@μwh:r1NxgVt ]A^R/𸍗C"~ţkw/O=8:8ډG‹Akh`l6t0j5mZեh_xd#)jO0_`}XiJxo`hp%3 Dt #0#GP{(&_]|q``6;9Ey; 4N,/ sh/Ϧ3^9W.˪טL~% *Gg0X6N5O~}yv[[kAton>WX^>z0ܿlqy/$ƩCj:!$`ꖕ(Oј(EY߾r~z`k?xOCLL<~ ]+kD"H zODCRK!Hd*3'ͤP N&o~7[H/އ] @'?tS> tA//^A_=+wJ$y8=D"m62`$f'$+ ش&W,͇BA 擓ӳӳ7^ ;U*qQa2Gx"Q9DNBbZYF(]?~˧(ϟKK#06FIx=˫sXiU9i8\ '1X$bWҳ9YY)#?wPԶWgТ-///..a&0f4ǐ^j߿6gcND _MM$gr8?OJLMLg$pҲ3 23d<~|Ӈwo/7_\ĎUfƜM2CHǍo/_~EX8550Co1D:=OथfgqYL͛>B߿VχQksr*YLVbJZj Wq o"|SUj2ɟZR%Sת+`ݼqF,@fSr s sw3#P|Fk !?50x Occ 0x &ѓyl9|<+55 Se5r 8c<s@C-ؠVRcB_WĻI('3%$%&'痖"x )*?JuΩidnwO!hI79*/)EU7  2$QtiRq1q7{ݛ psU&:C2 IɈ@rBF1qx`(j<1eybqks8s.V+:ۋ7x@HWPIFV,b2 ;1NCלbn ha*tMV((`dF.B_BC |R? N),VbB!1p*)N眄nr3 ΅B)4OcjjGsV=}C!CV >`!6H"V St92t7ԭ'&zα ueAU.K3 Oo>?ZKd U&GeJ! " 3 \1:zGhҁ{l=>1n(Dd25q{QwaTuoW&ѷI_= CCɱ D":l@  d04s!@3uq=B_?[xfX6f@G ZߏBm7%H4J" T:8D0z:O/*sh+k-ӕf7wt:2뛘x~: " &k<>$&NucʜyA$/?=j7d4w2[ F\cqʖn_76QqLNѩM<%5Kl:8H~B0YԹAFf{|nZ&ǔIBq{ww.|_׿};[x@a. ؛x"L#gCc%?:\ LLϢawڢ =alr@$ ,w){Z_o_OB؞|tx"rap.P;;e7;9=/o2;1>e҅kh:dݑ㏿a$JTN.LBXmhǤ_X^p9t@j | w%vQ`1o?=q:]HIaTU): wm}=[8"jKGF")عB 2E˨oQxx#{<@~ʉcSG||cl_,+kJ5}VǛ=x =x"7& ]&'e'&BA0UtHMN]0R٭f ̟ˏ?>r5B-"Vw5??[T<. @TNhT&5ΆdYDʬ=V~z =Uh7T^RK&ˏB NnQPXZHۆ<CP'14H5D`u_^Y^ St\}p2`1tWgN>|5H^Mq+77Y = SD5IE]n--GVְ<|R>hwN뻷>yvy/м|xD9NKfe++ʵ)Z}JyG>G BoŢ౎%ӁHduy9.,-.55=~Ͽ}ǯ?@= Z]- 9BaayV.CRFW :YJ] KQ؍Aa/( AxzG~߿8Өd-<^NNqmmmaNY^}z t^G"`SH܎Igr (@8 ˀ<;2?Y3VG?01i]sT(Tg!\^57毈x&+ t"I`ݙ<7=ǪN`fp)bu/P߿ M5CeHT ތܢF%v)& Se0qnf|B3B"d;xhOg_iEeqNH(ml""?=[٧fc5;$tPZi2fn9KKh(ð@q%g?}o?\fedvW" Fլ  FCI$ HfҸb'tE&pdPS[I\q<<;{T/^A].eºhM Ո xM1ϳSsiyc ĥzXA{>]_ C}ºftZ$)C2qѡl|:vvnt,TE J @}gy o}+&TV$H$ I!bb2lt4ݓ2Ocm\7,驱͓@çO}@(W<~au=(ATk -գ#ĐwB 8OCԏ*qǠӋjkʯlllnS E@@$*r^uHˠΣ{+6vE~ʏt8xL3cö'O^}ƴ _a._Q]XW/A7kjDz8;be,C?9c#4t9mS\z "#@~ReeUU--FQUMMMU~jR:7 ^ @b-E޽.V PCBCr[sv}(W0&~G;__7ǧzt \&&3)PKK?t/C9P@000.npy-W[[k.xmӻj sYD%@!(#I" 66W]U{?}ӿt!&y7CU 5?+*ش(^%Ea;J9O."UBx[!K+.B'<) '"ȠQUhofffS#dxm6>r9l.d87+F)D,"&vzq҃{Q9¨ɧ$xh4 Tȡf2jjkꚘfŬklnnr[ZZyVbf`de&h"KHU:wNz_~JjhoJ$Sɱddn{ ҚZjf7775Kp[y6ᱛ9M5Ey $+-=!>Bht )u(mZ]UJD%׵K8qhxll|b22=86IU c2Ml6'00uu윜dJQ#<437vyVӪbN s#V9QSUSmb56ԃ4ě YfFUmmEYqAvNzzrRBrZJzbRrBBIK д܆>wdaemc+[;[K{G@8^;¢ʪfVcSS#r8ںZdH}mMIQAQA^jRrb'ĥddg0E%JONDf6<}P8 g秂.].hoZx\V+y6agGwWX%sfvCScc]}^^NFBjB8ܱ bwvwvvwX__YD[A<?v@MYCVj!ˠd4BͦAt;3! A0111191:>>5 N͂G͹HdjzlRka&VK, ;:PB@H!uEbX'dJB.T~R=AkAo&hi#9=nf^76A#[UV\ZWX\XTX\RR_\XXTTXRRTR\TPPT<V%5pTVWkj" Es㇣6jivπKH'%4B/eTVUVWUU.(/.@ZVaa^V^AQaaA><x閝 ]?.(,//Jݢܼ*SvzRRZFJf(:/GǥdPt"Eks#<5640++aVTVWV,aVT.,-+,-*+)T_WWͨS +TNYQaΥk3@'`X%h,DqZ8hQP__Ј 02Ls!p9-ZMZskR76$}h&ţ1xT4*C"D2ZֶV)@Wͬ B0 FB8EXL.&x|(BK+[;&h(H$.9\RVSCy )Z[UOƣq8TR~FP-R])loA#(V"<8|@bCx6Z)P]IYYUy\S$ӓHD)MtD%%o|AP hkt.ST' d>E8_GǺMwZSFE_KOU'`Pd*/1X|JK,`tJ^IOoOOSڈ:;DBASyf5VUB,lwttjw*II܌:^_uzE~NravN7he54ZM O0qɴ4zZB|<.+d2io4vEbPK$6IbT0-K$Hz5:62#.E *WB]C: A.;.}l|N:BpܤBPerѡO#%pY,y| &0P ^:`pubWQΫ{x.6'QxJl,X](/WUJJPHe ТO"ӺyǷ_wwl>zqrvͷŪ&VkC8^yr*W'R 4 ]3 !J\*CJ mdՐyi̓߮/{RNfg5&aI9rKyq!$50;6M,%e)Ff@j4~C U">υocZ"~p “An{=8 '"v? L$q*Ks[cTt+E\v;:@4׵pKcIyiY4Z 2P@ȤrJw <M Ez.Uf xBZ:iG1*`` Y[gיT=A@\iBҟLHBG,~Hԡ fbC![N"i2%O91C3KiPQQQI^-@e'W($RuSe5!_%QiDF9 4<Keζن(DCGd'c5d)ְO(Z.“8Խ dU8EQkTA{~ÐRSu]]nJW#b1$F=)6"Q( 9>э{)RK$SH$:=-531\?]Q'2`1(,f_U3H=UaȠ PC&}(dgdш8:a ZxFf_9 F՚,zѢJNs[UzNi51hZBR5RÌUH8":eQk"(XJē8<-LNO)(ʈJ(t<1r|W8Qo6ꑕ!Ūt/~ǪpV;Qh^\OzEeDQx,ITG$ %Qr* (MvQgQL HW<6upHg 6uK05NPH?d7wfC͑ ؘ?=4u8v?i*d&IxZ||M$QHX DơDjB`q2&[gi|; Ab*;#;s#ãc-0dut %99E3 Pظ6mUޟ"ŧ'&$@x4: iq4(*V$([f2@Vi}r x.ժG]#k3?j]$sMf =K\yDMu}hL gf''R)<42lO*f E1bLJکp`j8m֡!FbٟZ LX|EfUŗGjb(幉h ײ Hi 蘘hEs!V*btzsF>*yo#-0? 9Z -1Fe#.W{E r 0JC.% +y\d|l4N<~:866fńIEFOAh廞2v[g/+˳RSS􌔌Z6[ IVd\ءFf݇;Ks++ +ݣg[6@1_K0)Hhk:k{\v7z>Jt;L4K$m|TV%0mT~du=|d{Gw#$& }de.\^/*F #4NyMqIyq(Ԣ(%.##_3gxm{`ѓ';wvGl¼Z2 O bs>-b!(@JQ{b,1? #3FA @xNo Frߠ:Bdɳ'?}zuzry̤!<^ٖ@6d\\xbm︵Gfx\PFͩ4xihzE3b0뚘lNkTaMFIo՛ Ϟ>zȫ/^>_|9=3;1H_Dpeea ^7FAɠm}vI| 7,feITϞ8zƇ7N^>=X[YXqtAzj\UۇgfsZ-ɠWennYz_LڣR!D_g0Z1|&h~_tLJϏO^\{᫳g7mlnG4n,1xxxpt|!/!Wdnyyb,02h4 @l6nY,?Kv_puuq m//F aHUsO}/.o,OZ:p YZCv04ЯTQPkdbǫn/n.޽998;;ۛYՠQQ2=>8zd!dۻs؈k)C9<Ղ\K (csNU!+_~zӵʼnP_2u/O?z<=>ݳT$ <PИ!C YoCs`2;l.rT4ѣKpqw?}wW; v*:`{ifu>46R`u-g"{a] T\C1vylېlDiN4kJ#`^ͯ>^}{s}ۓw{Om/ͱr鳪WGOwgW3&ejSw=6Q%ѺG.P)=p1 ؆&qd:hȺRI7Gw~xwoMG4уO!' +]52}WOiC>Nfv{G<~/043; ٬HA nW?B iWk˿Ϸ߽~}tí㋫k{s"[ܭ2 NU֑0_ N=D8y^ᰛMfHBrA]~d^q{_o?ypgqߞ?͝q@&z`@Z#6휡Ko`zy7;6=47;19>8 Z\^QXl-Y?>ݼts㣝)'w6?y<X-zR hN% L>ġ9&417f '.!{ׅ#^!/A.`0yoS+0o^ߞy}||g{+Nm,D&'g&GCN 0ƁE/2)|LJ/m-,M#Bv{ɤwO&E.߿~t{}G SO@yhçϞ|ӣ'+ ~A#ԗozq~th1;;==w]%nB!iεׯ~{ExyWgͻOO/^]\<9y~㏿gcNS ~ŹX8v{ܞ>O%utvuu:څ|>TW1뗛߾~%@ϟ]} #@o~o,OOV&/.>1yˣ=Z[ZF\X$hA}utD緵MUǯo^xp389|>GDꐺ33ᱠ;86G^9N_^>.-F'FA/0t#|Xcs8 9t{;0*gg"p(r%BX ',V#0=aOvN_<>>>=8ԧa'6۠AoM@ax,BQȤ^8;=9zy$P()e29rW)lg<ًǯϟ[//>~ ;>[&x@&2 ,Oi )tjp۷o/_|׹9pd~h@߻`OO__<7ןx{%alM9a+z*JqT @͇a^^?|Id bp#`63m###þmt7yUUL=utQ)lT 8<@HqtB珷 ޿y}c͍@]d 7LchH`((?v9 j؛sd-ÇwmЇ|VA˷Wj# nbpPk//O#&zfaIQaAI^qeE%D"/J&vm}߾|0|(IȮNǬSzC WWwjyGe:UX’ΑbېGĠjRV^nvafV"s/U.FWn/ 桉qdWipqUX*ˋo.!>^0KOBq(CL KkJZ:U_M/-4NyFrrg uHmNuU~7p`w8tҸXtԽ矯^z}㝧[BGcd2OH-/ɦ0Y - pGgWfƆ=u G>(V̼3PU {=5܏'7|H`%)iqk3GCHXmvA%sO@}x514]? j IYit"#bXzsgL!Si8= _,7a^xߘW.leV4"=@84:y]N+@Ȍ:W@1ˡٳˌX"B萟p<I  rcc^Pe/A|MmM8ZجƉ` qiڽ=7Ƕ}ڞ(mbjj<M'ӨTL ע@g( ml|bo1]n`:o9=Ξʼj&օAG@RI߿|xݫgK;9sG‰82Ƣ2F ('< <<:l }Ah8]vhkY-"!%`h m6:vOo!=|<(qTB$ 9e3CC] Qca_.D GߐR\G.|`LY/,B^폏~t?1 D'`@%bи"n7k)t%dHfdpVf*`+b=Ԛ@Lɯhlɿ~>wz<>db|n? GPhG@cDZ>4 tC,&&'|҄ 0V,V3>^ծ8V!72O18"؍F d.ӥZ!"{*c׾K` L]͏-fà5PRꖩo?^slNz 3qȔ Oh%`QJ 3.NgE"c= md8GC!`Q3LvWY(-;hp2gڝb'h+E>FmR)x"6 p%t@edACB2a/rW >ZZc0{FL+c~Hmu_zw4@cPx*9$O"X,'VwmY?>ߞr;M~uqyN%r'RѧꆠZ#i bQvQ:G"\dj~kxddI 2Ƚv0Ftn@\7ta3YgW/=MH&1^Lj_3 MNNL I煙3 fhgwz'7+Fg-tw_NBް<:!!Q$bX,ONW{|^udzjGTC:b~px0b:q$V٠ F{oW?^[T*5H2@O?4`4А" @cKK s#vԸnۃ  8RqFZiH5o?zQŨz~>6& +B5cxb~~aaqa> LLBC7}]7 FdKWTxv˷~߾ijM@$2L S1x2@ zy5 s807YvdtXfRQdk˃w}oFϮdەˤ2)xC6{B) &Ix/t ٹphvI@]G=jן ߗ/_~JxH+Oȯ4d}J\*eͱcPhdb42HC3|./855=?7;=?AF&Ǒ r;K{O^?߿޾{㐦[JKcW2@4XOYЉNCŐ1j<%{ 0ATcm3 t/΀_HczգYo[QP\U,j.*++2H_ˈAapȦ1 8Lb'uy'&NrOVȝb>h<Y#xh?}|(7'v^Ϊj(,c j LѯPбX4F'cቩHlE@O {02e!魃四;6_>}{{xNQY`443b[_]) RjTT=HN!E%tyWщȿ}07=.\GYŃӳ7׷w`o"Oj,V# AMM)*}2@"QKM aw|/72>&:h47=50ۻŌt[eMB_-Wh$chhlxDDNL H$va+G֦NN_\ӗ`/w^V728.,_TSvU*n.J%P(2 INxFp0|JdA >69O|}tS¨m "on/hv5f*UJ"i]~~C/hb-<.QMDz\BfDOBH`h,LkDXd2h0B0# zۭz[$P|tWTVY]SuMչJzCT*FuS~,r|7N"]l-&0ջwW?>9ѩEUUeuVn;Y_H&3SHĤ*PKK?u#ڬP@007.npyS[ٕ̯d}"l@ص`!H}GMkTWqUOWWuU<Wuzҙ\SUsν=ݷ`wr*csr{ /a.D-ZRLǓD~) 05>oK폟ThᥬBʭOtzW_P>wimm)d4 MQG Vj*/||qZZM"lUUvf{JZ奥&I/S)VYYp;LcMPvѮ&J@'`UӒ!WW7BJkSj!32kee}dzz*>xHy?vTquX@Wy > oHŔ3/i{^|L( z(Ϸ_]H&x?7?`UR+̿tΏYqw}:|D|z.G6Ż}ޞ>]/omu-mЎvhw:_zp?&^1?0nv;ip]Z:pK{[s[f[[8Og냞x<ݝ]^| tupwy=E1!ox+&̥`֛!E#<@.HfCy}~Q ,|հ 3FQecLA Oت\|ZJ`>pFVra)fEbu>D0Pl0ROHPQPo"nxg;<K,ZZT?n2p|6i   AOآ| _$  P cWжB "t"H3Db6CIlxyCT:`:W>0?N%Suf܇Xj,~qa*=7' 0ʏY {$?RbtPl# Co,--AyM@>ⴆļZ' `V19c !!@>8|V+gzž(Qn'dgN ZjifQnp;'/1@ *LS )} @}0T`$_ ~/N4b?@)OW"W^a$aUOQj$+)eaH#\aBP" 5D_X( hz<@^KD> N׀t:#QWdKGlOWm9EX > ?y 1<p u54-#͎*_'"pK#{Yv:jj x_EA~ ʬbou4Up]*?W@*EOMoe2{|; <\[ xi7AOS~c 0;;9#(ߔ9WdRW~\OQ~1[>72 :98"Y:P!J#\%8Lz,@Ipf...nB55vh*LV["|7 -'ORɹE`.niu؍|-YluO||H%jUc1y򥥥W[)_p[X"v Y{y8̄z:aKUJ0bu\痘ZE}8{:ZkʄRgS3%QxnWEE8~at{wo'{p䫯0YޔgSfff^>`MՕ%p?_5 Z_T={R]ZXZ_XZ[Yjῡp 6#¡&=+878<:[ + Or>(WLt֑x0w`>mmۑlG|~aee}}0@_HR_~ 8* [|>V7D<&`Op߃?h|g@~'SssK;?K|o0] [4I"@Rk{$*p&38T= p{J_Zތb6/"?9ķI'cP{p{5h֔ty} HP?omR>#NNa7oL_?2$l8hTG}r>!3O[Q 4੦ ;!á/uF|L&dv6|Fħ|X+[ZEP?QS>wxpvA/.L͎`0 _@}#Yr24+);XIL59O񸈼<;9a]g}?;=9>xK(=>7)F }(|lr<4U}uucHNyL6#\@lf9箌s'/ӛCűsa)WWg9pp˼9?>6:=LPy֗'-rǧxr<'|hltdm#_?s zβ||!_z~rzrzvv6ǧ&'|httdxs<7P[p)fq@E< pM8;<3<2Nyg]+~/-U\^^߮Fpζs=2j}q'! r[azz:6ço!&@]ڝ2+%xjFSk%DXX^^H1 @^{uq")`fdx9^yxd8?>fwW0$ WWb$[whGF @⻞=sy's~?# 08/LovQZ_u~| @Mdr9_o뙧yUUMWuرo!C<L?pʽ|9>o(1O6 NK൲ q_ 8ʭy_kᑓ`!f,2<VE>@bNWr^Uz^%bl<0-+2ow)=9By  _K)~.~W kiq0$|TEEj>32U8(dc]+mԻ\^:~1OZ*Vkl5J^=4:x쿹Q/NRoiܽtj PsWSCC}Uz;444N mS>f7_q5* 'E`\TtlllHi1@ssGwFqf08 zbVe^n֕4 0ûr'>n8 %Kde2ͮEi!B٬@^ nh2OCaB~>3| 3 nc5!R?MI"jGor=+!܏nHq(y:%ȓmM&Lf.';P_ѿ8Jx-~&@W)t7G76v3x1̇ 'vqٓ/[.2_k-m܊K=߽?Ow}h Ll2A#=p1!y)+[OH&`,4x(r>O3"P9 o iq`1"NgCG{x1% `]g6AGߏ؀nݍ| \JUƳ>F8;;m: ~]]9:į'\ك{Ax?9_?L@2Ѥ}ruvvvլ5 i2nO?>/#L@*4<#R/8p B`k<__~TaROCUR˺O'$w}?woX ~%ﲼ,O4TJ6a3uZ%^K߸zU75^8EDٿ)g{ Ï+Qojy'>Rl?Ca!,7?K.×3I>4|RxU˽|'רN~WVQ"PKK?SGP@006.npyS[W_緙n B$lAHX-!}u 83dR]5U]LWˤz2?5=5N\?{{ Of gMj˅RS4cc!مh<i.-{XoB_\J,:Vg+T[}ByZNgʊ"l6d5X:*/W[|骯YaY?eR7,`\>0?'@ _,w1 [濽] I\OS.9}e~sPLǟxox:;ZZ\MԂq\ͭ-6?.ӎR<{@˸H*+z!\h:]p,bluj|lvM𭹩XX]dc3qee5y,bʊ e6ahpٳgm@O:;[Z:;h577a9:vAPC&߈l2ZWCCI}}8ϽJxNlGpSs8)_Y 6>J؅FF20B=xF5ZlmcƁ/DpC2 pħ}08#8)<0@6 p؀Z-*<A|a>.wtHxlꅅUVĭ~*?;K@<tU+\J<*{Fhߐχ kK2@@l4[KxEVis"sh ~a'j.bx h1F Jדx(|16łD&R]U`ZAi~z:<559DxABbCH +}/D(*ZT\@_|h,:D) ._-g:"7r8TiII1F|RDM$(F )vt׿zg-FV|@7>,T" W|N=:i6рrP|X @|}|]1--.>s>BXlF`ia`JqZ?o|CA13"><OqZ1so0%K,Ȍ`VV-x_L& y3!JRx~>/P?.>&A_%_j P K " xW#=dl)%;~_  `D#lh* HU((!CZBm$|V,bs H$|` i =]6 G߀ݒR3}R^< px* <A_G?_[`x $"]8xlb @j۽"%j-ygo:\lZ!_T_>Hdr281u#< @6eAA?:n{ (4r.Bpmy@@yi8#~ye> Ϝx^؀\ENS E|M>17%/"H PHwJ-Ne+aVvGL lH<ǹAk Y>{x`P^ WVɖY4֕K̯~ W$'˫$7R_ WP.sp>!$d2 _Uf:nP~ԇm" _krn?QO$(FL$OIH ѐJ_\1xMq~ |`0|,<9< U£mDP4*k|ÉC?sh ۟ ̬sKi`<@c %!;4P?cv?sh㏶9 򷔗=-Uc;j۟cwTZM^"_51ѐ"o %".΀$ h;->HwKc?5|,tt:wݝMz#9I@8؆hyG.K08M&rzkiieiM*iK }ŗ_@ vBҧg0yy!|:n7e;&V@^" x4`*">fj8xJkNzy.76auckxXfoo 94_I <.Tjk-:_0_>o\x / CSr0OnnlD_џJykh#UA W| g "Y|2N%/7byoeCXcYX^PD^@AJ55]`gbj4![; +҅G^Cs<3cPnpo"@b-3ӡrЀeMr.=ޑǚ ea4FL"ԟßK ^<]xGD>%C?==8?;=:8`di K靴0~4@y:uuxO8y~f:n<svuvv >"<'  D8??;;TrDǑGCέqu-l I35G.Ύ3!;x<&3ȏ z=>9C`r]8 C¿z_:??9?c1?$f?nx~wnnr t[ҘOS@vpxr<<8~|1^Nʿ݀x_ @T՚jן''Gǧǣ@p,8x{6Z9J}/4Sq$˥ШBM]#uVԝ/Zn-8no/.2uwccp#pTܐֿyox]z|Ƿ70 aemq@L4p:Yg;4 `oOnn!'Tjk%>%y@L6[Q`a3r@peM@&@}ZԨJVөŷE7i ,nIƟSD"gD37^dRX&`NصeמG$E^~;9 {0ŹOl-Ntًʐ/vd[ )Ͼ|b:Z)-=?9 X; ufDJJ@Pj* MZW[l~yyyE"Z|)^;*;=z{}$RPO>DqZnP_$~*09HT*>2G|;BP^z=|S/#X5*  G77߇> 1okgy(3lyHD&)~cGZ';g>Cq2?78?Ge|ǹ|*퉮?<\ Iy&w 1ܘl>LS qӗ ί >Y&`F6X!r6v2Ӎյ.|ﯰ=lj1ܠ)R(?HB>V w&`\>r1m'#+ pC60jlX'#Tn:o3L|,kQ:9?#;R߆~Be5sj-}r#`#HXl^&jۨ/YJ|U'镹_$[琏M=<"gxp^>u| Yvbc@DZU5􍄷 &;.~C-3jKKK#ŅT>nz.:,dND0Kѱob/S6MJM?"pR:h Kkj|a{kkx]z%mIk++ˀs@/)!6['276Rgn_7Z$'D$a5 ݷN@SJ$Q&x:_?uEt'}OKUJۭn!pÙb}wө]?N ": rxsq+ǽdyv`簻?}Lή~IZn!o7Xu=Ɍ# y _Ek!-Dǟx ߣn8hUW/e%G;~Ocy8џp{! GRjV;#C%?9燸ɤϾB?N*Q?nknG{Ӧ&nX՜nfFJ^ϿFOâݭg'gMV~h@#lF g\\T xlWS> W 6Mƚ:Ίz}qYn^6 Hw>>1@$S&j@/+8h?"GO`GRE_7Mo}J7]SW__Ƅox4ʦ\p48[ֿO Io=6"f/}yTW_,c`44[Cc F zCss[Ks+|?Y _k[; ,\p e%E=n61V&` FAo Z`֯ ^_[SZsL!p`demrޠ]vsrb2&䰣b1[-榶.v#VZ|TVVPSSX|S%H,QɔlTB,d7,X ؃v.̳@TI~IAAt1aJJ!U@JJZZ1`!V$fsU>/Ј.|z >69ZXTPߍx)hbO3x9 5]u|)x|ӕk\Q 6¨̇)HϤjTd O ^\+4p ن6АaADI\Sfso@'* @ ˜5rs:Gtw mNAI4 hfr645垘sk4 >Ѕ} yxxuc _+/ ?3噞Xp~r2|#p\ES 0 (ff~ǃPNSޮ6]fRoRMJ*Oxx)@ _.ljpnv^j`|zLm*9EKJXZZRU>X`a1@ {Fe\~\ÊI #%{qIlaa^` `mIk" /K/[\D k# -K̫xkg-d|-Ȅy]1 e N_T4H3|Raքx@3$PP):~@J@|~24{8$w*g\cH_?݃=\`mwD 4t MnD` 7<ʁC`fO(g\ݐHT_)6A?GIXF؁p$ߺ%~&g Ssos,I `@n@oo?h4/^,d* ?˱ Tn$"^ i/##4 Lx$H xw:>66~C4~8( 8)q/])fh z ƄI?1$B};M_|s x%et1_,^'jaS>GB>?8"(>#3g~L]L&&&aRVc ~0 e.F-0e̱7O8 YwK&'}>X 8%R />w++HD+ju>X\,@>}?krihm R?3"2Dho`T|x3Y>TY,b("dR `/B͛7#됅+|)׿Y?'P<"Z\Rd0ic C7öoClhiyy9"}ΑJ8>֚\U"t4ȅtF!>4B sA"qppE"zs{SeV tQ "TAkE*~MCpU'`P=>*w["Dg"|r_R+ `@X>ӣ~݇WY{^o) Phi6xݎ ܰlxF|E h #Ngϟ./2Jt*U*>B) 'k4cWFȇMa~e|p1RSq>9 tח0SZ]I @n/,P\}a;P^P\UAK* >|0Lpia~f<<.?^ W k?= SB *kP_o`>0"X>dϞ?ի/^z O`H&<  nBkTZw#nw?յ5j!`nf"N᠏z9h`㪯 `r{Y 3p*Nn"诨Z{<EyLMo5<^je$ /㫯z /w?]USzk+߶riZۦjh5__m$?73E˗/z۷xs45A>X#r35#H$04pY}ssu_aG[`vHXY9> Vf֌>558VQ\Y|c~#x0C$&`E-`ح@2kl#+78~+6Xe__G8h?%kfR֥-l LQ,]Ϟ _c~GrJğ*Y~d\$$> G¡qq;'`_V4k~A-v[?: nmnu/a> 0uYT` ֖[y>ͻ8|+  !F0|Yt5"M X6..>b ;:CC@ |^iK>Z،u? ӓn_?}GG}3x!AǭCgΕzr|tC !QϜGÿx¤Ϩ 0>>DT[9>$`< > Z~3V/.Hgb`cZ8>>:p(M=2l7޲xpp83 4p*p,qt߉f 6|zj·Y;wI_Ç8x0ZMc<|x~v||p c1C%ᓀG~\yq|(L`D,U#i@݃ưvNtVn^~SX$ @|LS'/?}c1AE:YM$ɓ?b7 4|^Թ{4OP}Z80#;mnm(_ROcqyG h"#?1i4] x1>t:9NNK*&@Ex΂Z{Hէ|g?|Ç@r9?n]q:;;c)N' $e ob/_~w)G oB!/,D \TqVkKSSPD\܎BTdu~a~.~gf ܿ.?fp9?V_22ID.Si9?|2v s#4@ Oʗ,C&ȕzŒgRjЀL~ ;eү0~9d qCT:a*8?I<-Vx0Ko-'pTV Ƃ)g"эb71&`k#0VSPRVZ#k{̋+xjfгoQ(] se"IvX~ Vdcޮ3r<!}TՆҒ\:tA__F =O!#e__s>S,=hҫ|%s,=CB'jsuƂv<{1gHx~\!؅Y (O (pHlg+L-`h2/\ҍ ?يRz jSKKSST7ͭ|ggowgg ̔O"cI~tc wz~RJ\ʺCs'@<>*I>%x{V5O+dE;;g @]LJB~ ‡ÜP*yU (Dv}(`jj%|~ߏmG>(t4o!\ȫ aCG%CS..jjjgq(IOCeƁF0ljϿZ9{ oaŶ"#Px>p 89ac;4]q<ʄO~p4)D)ͪ'Gjl5O/𵥥ksړ|BL<>Yz L ]*{fyZ=|Gs`amq y9U-ʏXObM x,rp]>GóCIb㍦9Ɍ}‘"Z|FI!^lvqT>؉1@.;V6Rmȝį3H8~A +<XX,D+3 w((`ldddp6Lb1&2 hta1FGI< >|L 8X,10%J:]Rꢻ(tQص GtOqoE|`rq?ϯ`35\ Z. Vu.o܎?@O%pX}b[x& S W66,V*WWVֽë| z'Pd#p39h4]=ABZYr0juvv/3lm -/pbq}^Neu h0!MٍcN,8 xkkݣG>×8k1 0UTW0|$gR]kPz gdm%^7/$<&nNښʡg5.VEl!j?w/(6n-} `ht8v[90Cx)??qzp#8z;;݃v[w+|I wt`Cۆ#,`Ͼ!'!?jl[E2L9uuuJf+K+Tk$EMhdOY ga#`܅/o˻w>Wz5`W[=yJ 6Cv677c'<>g,tq<ži提85+-,-.,D9@ הO/ON8lX#x3qӏC!?~?(~Cqv:PKK?^!P@004.npyiW[goo}o6yIL1c& 0X!! qlOeIv&RvR}@Rkm <{w>G{vMSZmcQi O:˕*xh=jF}6P_^-RC7ˣh<`c?2?tmlt@tu'EWggYW_[SUQQZZQ%˥RH$zҥORRR._ 3]34o['O\"|t7%5-% 䅅E« Xhv#?=], X: Y\tu}07s7_GO @+QtH̾Ztݸ̓[]u  ho2ttwuN!EtU5 ,($ȯΗ|]XDe7;SUm͚5ڎ6C1̽==֖&`P!U*K*Jku:]u4fG:wwQj65[>lZ-~[z:: ~^]]]Y_w5G.e]vu4vwuFC 8]-OgOb<ւifڬ:.a9t^{1=2lZ}Sӳ3seoWTUE9(WD.D`Fc:1 p8FFFwc cnScaLəљi^4 ڬ6E>S8~h|O t1j08>^%P"'b ?1ag$t /VJ(Z\ C?v؇=!ۀ}tf1l}}!|֦&q u5:uNUժTZ~FFx}zM:NX`5׬ii6U?]eEW ;`,onh[5:VS_HM ,ZVVښʚjUUMuEueeEEU ໵ UժʊrmcEiAAIYZUfRI{Z]MQ$Ҫmn蚠&&@pYIki75oj5S[WK >TCjEE?LBtizV^D+c6Ȍ׷q 6t.ZZZ@#m0'h (^R8\XS/H1S0;;&m'A B"&$q%<>."_(S|,׃\B3ٍ WT0xB+r˅e#V"~ O8 "Ѧ'TwP05L==Tɿ-xAdY1Vl 2H$qڇatLgZ-htc(E d2d\͕E`p/Xv;]0t :0 PKf{_bL$Yld@`et#4J}hl4u -DfgPP DaE!V @dMGL"CgS-90 /@|W/N @럀ɤmJ(DzOߚF1_t &&p%NFq8bt|X PA...AG!?1cFГD/g(Ѡkj@yy12|~j*O|Efn7)^*14ʄBAWĘ<\>ґ/`.g3aBY~Ó)+9}(#`/zۛ,@cX99WU1 2nSF?GrOH\F?C0?#-,b1[C>&\Ώÿr 1<("Qb~?Xa@6vԗOH-+Wx< ԔbK"LN2zF|n9&|_^-N+B[I);8@7 跚q 6lwYBÉ\F:I_Ha P)cd>O(H\dt_X'8_a<%Q,W+Rdء46a:vcq8\ ~M,s.s K\XeHXu B3@a;B`aaafoTC\bMKDd|@,a⧧&``,2>p8i`~HR\/(@KuЭ&IyN')`$0<,/+˓ip9944`gгT H=#\ 鋋Go0̌>s`AROK$)u@?uy&T`d1lmܔr(]G>Wܠohh@H,TdϹBqFR8,:@ soL.Fͅ0ƀ P`%kShiLe93׊I|υꇽ8@?ڏD81om,LyRH1 jt!N]S46wh@KLET!ijGs;~ݣh><;agN-Э,[`Cۀ . `9S(k/?=}{xo*bjSe0,NԲx}6#u:p:) )#ۨo'dz]N>z텁:d_[Zkkk x`'uL`gD.(- L :3)ƣG{3}rwjkV]]P!?iioxs3S0M,+/ʑ_VPwY}S333s''t?WSw?K{GD`eK@onn~i1473;3$m1otwZ]y2̓' ^>_M ߿w.%´vFV }ii}})35;g<3)^>?GT`җ-a*oUk|Hي/-Q,Ɔ@wmbj R:9g'f7` prt\%%%EjnH}c+a}+7{ljl ǃLX'ū7o޿G_>~t gÚIz^4hmx# 0?3uՊ{pVHü?>:2_y_? P_T6o0 @&;]Vk3'ͬc|3s3I ɓ/ϿGC^DoVgm`4]] i4Lqz2\^vjis= q|(b9k?gvzJEiF2z4 O-/_= }.Hf = G  ޽c p`I,S:zOw{f/]$z:D+ @0,їσ3OP":s|ӇwrAA3;MfQ|\bgO`v7 l~o#0S^^rQ`9Fqlu > --/,árop~y ߻w稻*>8JXX^ٜS3NۜN7>,W676VB#Y>In'zF=3޽C{w Y}{PD 1=vOiNxooE6WËpKO=ŏ]^w?X`G[>޽<)vxG'>ܼ8,"]ݔT;gggS;w> CCrOx|O]M3 'h b| ?gO_} ȇ݃6lx,ۃpBwnFwv"0W/˿tCKw*K{V`93s4wb<.X霝8{ǟ~`[\\\Z]]UAߤjck߾ Wo1_= @9q"_ ĠO~~7[u kxewaG`V-Q1޾{/<:|UX]-wQaLm-g@?;yה09y g\R?(Ok_ٽwONlX[ 0'f`G?ko'wFZr(@ y:9l0ܥsIhѣNdmeeek0pǞAsNPHKT(w`mo gR?\᜼ g $S`d@X"*)oqM* ?O,$~kOu'/َlܺ~}goӻKh TtOM~f $ehb@N|>7v_ӕPpjayo-cC{؃7m#=N?S/3wo_)MM&wu{;Tg~*0>'(m$YXY]Y߂]V!x,vrp l{9" 2:Ʀ㑘k+#=;&qjzn0#Gxx*dk+0M g6WLFx 0H444w48?<"chJ EM,~}郛k+ kx?>3x픎AHQދkL"@o M.NLt:FGG}FcbtIhXOsI ^4Xx` llЩ>./'\ufTr1BPP |Ff~.^$D0eV`8 '&Cf+ hkABy8ȼs`X0*K6qk/M?J:ppavnNs6g4܊چZpڭ8?#̅y[+4ehFdu{G/C̹rʮUָ\] xg/\n<Ev䵾 xnz.s//?|˗`?tY,"&v^)ei\Ivia^װaǏ0Vspx=phNrT뻰BDbڄ[hvz7@a` t񆪺cAV╖UL7oJVdmTo ,HZk6v5k˱1ELa^- 8d޷S t@OD>MKK{{WKVU]UU 0|}4>,)xť(?$` 676mB1]kljnI%$b7|BTO-.nƶX[E8!B- -'eRMSSSssKs5(.uqR*;~{D6"@l,"~ޝ 5&Pd5-\o&%@/rmyo/`܇-ch[gᛓ:qZF:^~7 \{56V"/0}~P!&,r|(/VIV`8[~/.psg Ɠ5w?;Ç1oۯ~|+:3/R.5pxik͛{;d_׏?4}FOO@̕˝FIwPpnxe઺AC7+WrQd~L6{tBo.Bs3OoIm.ߠ_U<b$S\<}^hd{%?!zZ:PKK?7eτP@009.npyiSIٷn}!#lс q[ sA`0ئሉ_`cw^n#:bk'2+++%3O?+KTJ=M?-9/6v泳[ѭ f5pQ !牓@6O#fO7l ꪫ|duqTZ,03>E > +Dxo~`CwWO<Ţx,=h$J_c&FGzDۻ#h4"==ݑN8ߺ"hw|A_:7J={liE6d؅pjhzitzzrjjXl|:{<Wve>ss33s|Po x]O ͷZUmf Ш6%|`;[8` `'Dʗݚo5]! qs@B|)H h|`.+4?y@[ $iO }rA.ܲohG',> Q9aZV -6}@+f3; 1>C<\sVG>.|1^ˮc·q͆K$l0藗***ʜ*a/3 <-=T`RQf+\nzaanphR^ _R?"P:ʨoP ?])i }"aI@.][[[^ZA_hvVpqCR4)T $<)-?X_aSf|l|YEeSb})@<'pV݆'_yyai[ d; 2ʋ8#/4`ݭU7pb&^WؐϤ 0o|-kcc]n#*^) l/ʷ<-~O*xF6g|E럝m;4`d1:>^ompz}}>C=,fΑ#O6(766\9zDP p[Α网70@27{xkֶ;R]'x_5쀀utO5dgg~l5`tEbO1cીGY{uOlXPH$6iࡼWoѓ`WZ:j^ "Xx׬PCC'fd5_3*B^Ik,pw$?aLw| pQ} Dj?۷/U<rMG;&F&RGyc mk-/^mjd^߄Dj.CUm2Onoy"~ho䶷rB?G}3Onorvn?|l'| |66)&]y^O^_´@<s*\V3Eٖv[gr9СXSakdak~0d/QE?+xrM$)ϟqy?3+LamzPy G~/{j'I#О'd`|(K?3o||>p=6m&@R{O|̧ zXQߩI`7l.^s\qǔ_\OOLd<b_CTIMM<78Ma4T:51W0M8f`:+G<5oP :S{ėy6Wt:51>5jվzpN W8s&zmH먚~w|}_𻍔OOQ%oCxbOٹ86$[:/?Fț>_O_8^8 2 ><F$>hH$^7!3;h@NDOMZi/|xw: 4`l{l~)` XyTҿ4" ?zH }}UU^ݾT7 @[ZZ7CC3y= lLW&_@Sؼ}hq;Mory`{gm|ks|zawZNȉ/9ڏ/zJ?@pD vx].68hQ"ݷw']T+w'< rY+-cj-kZѾk/ ܯ||j#V +ƦZY65u NH ,@no}mѾXaAM fH-\>&Wɻ\vPB/1l6nS7tӄMȃ=X´A` mР n/}#\l|vKU4;ˑlsn?/|މW=_ `cCᇃ<@1ye~P[,M \US'8Vu:խx'5UqN)x iĆ1|]O?;h&^7`cccFcL, Io\=r v'hzzfޠѿ4*O],{l ڼi8Cӟx┏6NOvb0ak ix|۩SeGŻwQۿ\>`?55 'ՔWGP6KH~γ_ۚEۛ~!|ӀDȃ_W>e#pWcK|;)p_?a 0,{8B^yÇ '+_#Rȳv@5)_~ ?'Ү;54-t'bJHoIf7=@M~1^c":^y <`?aOo84/@HLj Z'ԯÏllcC>:1_I_ps~|Eܵa^s_xS//G_iYkے՟K!>2O@<7=o&^ 32~>T OiO'W놛rAw=w//u\dvRV|gy.\h gy"t.'o3b uPKK?"+]P@008.npyS[W{η  "6 VI]؄%!f @`H`b ]5r=N%N2}9wRV Iy~suoFBwDr+h5:d.cq}s{sa-H'6IF}UF:|'~bxyO0t=hnnnv8Ut'j5*5eMEE{gMMMq ??MNN l6[ N;ke|?/OuuNf3stVUeZϦVױqVՀI//[ dt ^@B|\Mvk>A^]ur~t|e8m2R(^Zz!8|I#Co |.)3P-@@!~wg\@-bЀ U WiR/X|@_*<pB(1}H=>[y<^^I/o>o/3PUxe|(=pz{z*tr}?z#I`P[;9 ` Ho7[Wo W3(>\R{}Ym OBc#ãCAdddxxog`z{t{C+i4ܤn Phbrbb|lؠ x|:n24=@ja<̀A8AqOB%>J1č/2\)b "(+J ]@dp7`H \sx/Q@FU&y|,UOɍm.27T`|Df#3ssJ' PUr5dMJzQ~ |d~!Lj̬P= =C,,55lk2RVeRb2Hc8DP?4]S{lQF <~^^^JL3 /ﮩb{|)lF僁I§kkWaVVB\d300z(lnf2kT pƇNQHFS Z%߼ @ ~&'F >/ ϓ#b430) Y) BfIafKR$-gQ dpD `t2ld'K 69XUvz6jfX@G0(Dh]?)FljJfi VVcFfD%H =?&}iG'n#0;iV`*nTҥ -1X"|eEEQ @xWf ՏAe%V@&cqnRhY|jP J򳦄3Ÿh<WK:kR/ єk>' \2O&>j`::5|t ^'oÕ1ƈ((:U| 0%u?N/*j2u`O2F()4H?! :Z|^^(\`/)x Zf<>-@9!p8D))5X=,\^\^!!~SS#%x# mdG?ԺjQA/g `8L [n @Ѫ◕qu{qoln/k+l`v{ÃÃ* o#XK̲c/ѩ)`[|}ubzoL$6;?JgxPn`5xT`7⹻,?5Usxuf\4yNaC"`0xc7)#GW8vǯ:}dָ[s X|(==--ԧ-/Љ'8sop] O'Oar{{sm} rr/'?jCx[[gxz<<=;]QV?^cC ^Dty|{nNLv7 +,<y 6ג=v7=p6-_(`$oewiC:(㡀=<!X@k+oya!}kw` *[y|0W_C@_؀.?ۛ xM6@U_ Y<؅#63ID~388/θR @gǛO2*-Ul6_?C+?"ǛjRw8 ڬ_=@a* ɁZe2 VmI ,]TJ?|"r=䯮&W/_>7UgswIC:5~!>p`*0>?ၿ\(fYw]]B $~ OQA"..&瞼U=S4> O OCGEP89[4>οRa$w"|"?WWDx: K x?_9?Ei 䏿C8/`@SǛU"oy[U~(O$.dOtSe6(4C[Txӱ~5<,@P}~#"kÍ/-bd; m~3p4ԏoYxq[=c|a24}&C|u~:^LǫX"MƟ OKq&'.~}|!6'G:Ɵ3<*w +' fw5XX 0L'CnwNsySnM3yLSK*0!໛seW}RO\B`ggky (;omteZC< @cc{{7o UhCNCN=aS|N R ;w&FB+ ^n zb|` >]/%[VN\|+(P8!㯹y,A80 c6Z98RMJ:No.N3)PFߨ1 GNfP 6'L-:^§Y|;cY.8F܇E>ZF8hF/'zc gų^lt  B;DJwEoi x++h𽕕 (~T 8>mke/4\ȕG`^]m=יc@{ᅏPnL5oF1&֬5vݭ]]]Ke٨eZ;@4Di -.}cdюy*vqy 7zp]x w4[x&{Go2YL͍q3 (GF.UpWz`ȍۛM `'㧇νegtWOV|j@<"[,p5v6>dS<'pBGQ!/>Gݤ6~(sp LT J|KVg~o40 -/NTf#[}H/>x~:N2n,ɛKDBΏ6;y «ŋ3jǟD<^ɇHɧRg|^O!- ^]Ueby#D|\g41@?)/9l@JYU?P&#t|N N@__Sum p ]蹍ǻG;;\ 3(_KL)'<|,]-vRtfpZÝ1@{^ ߵ:Ï&9azvOOw/. WⳊx>e1,A|d$p4휞/ >)@yb"[?p c9ݕ/0Gsc \xur}}k\#adoKGpxC|GumLN?r{H_#!@CCF/@ SH i8y\.aᑹ4>/ [91~;1[zӟ?=" pG:1?fsGKߗ$ (@ AА\BpxLtix O_`Ѐh PGG/ lFe 4zNE믿}WTx=) QaPAG Ņ,,(Q_(tЀ? ]ɟ Z-R~moxN#щvc[CN`Z{$v$_,"<~K0(x#x=qrr$xҳ`|9 JG. l)d[ӣ7,z)9cTڤ\L'ϋ?;9( k'|.c>gϞO o-'x`tZ>0Gior?2g}-ﮭuWPKK?E&P@003.npyPKK?NP@&010.npyPKK?)+P@E8002.npyPKK?R-3P@c001.npyPKK?t/C9P@Ė000.npyPKK?u#ڬP@,007.npyPKK?SGP@006.npyPKK?kP@i005.npyPKK?^!P@B004.npyPKK?7eτP@7?009.npyPKK?"+]P@P008.npyPK Gbfscikit-image-0.9.3/skimage/data/disk-tophat-matlab-output.npz000066400000000000000000003276461223313777300242300ustar00rootroot00000000000000PKK?bQބ%P@003.npy{iבݭ.ou^t7؈Ef(R Qy,q_&qO>yCx]n޼'OwyN^|ˏ&~1YL~//ŗ/>c'uqcswuK*aYLL4 Ҵٗ%2òM,-ns۶ ۖi,pݦe p!qӿ[m0Z&g6 &lAEb7i|{ Ylta|SRV3̞fqBJi &0:HSU~q?C=A32f?-˰$i[2H3l-?z|s雴_b&e[JpÒRXLӢe.E?n2aS+Gnm|;ꛯŻϞ?5N;izp A zӅmiڤ@c:ž^ы_}xow_ك'Ǐzy` gc6q+MO ,og~O?x 6C3'6o^zx륳?[&1}1(%'&h ~f554Ԙia!P>m\.殯n,Z1#-4".謔vl fj5ٝw-9I.l6n7׶NڶfNG-o|d (;Y[gWqGb{"tZe~C|$7 ldFE1km$iHT2Șm\2fFya~7@dI lC7XD7)RP 70hI.%.a+Ʊ&n2fhpWiUb'hxK 6}{uOK1<^|󽽭K\fI{MሀY mQ뚯fǘLHgwrݻ_0H5;0^Kʗl23w.kL ϗ#(0Օf(4?1Χ_}޻upx|w>&71xm)b>_;pyʍL;+͠3?蝻7t`xv{d@0*TL)Bp=Ryx(ӯQ>yz3ZYZݥ;>/V5hZ5ho/7t=6W6 ^k2g! RM+jG+x/-?e"g‚;E-^wt|/:k-\;L;?z<Z8Y޹{W>VJrjWF[9Xmsa;U3i>͝[{_}q[cMssmdJޓ2f,4k9;s!4ÐO/nS# <˯e*C؂q$_~3"^>xʣD`m\qFrٙ.˙\ƨk51m(Jp*8gly~ͼƒAἆs^Y$.YoĚl]6;kyfD4ONX5a-m d)LViR!`}i~ڵ&|U,»t,~qޅQhemJࡕ$lz܅U1P Q!S' 0-8VbWdFѲFXL/v#G۰Ь\|8(N2ep&̓uָ|k |#[:#"К6H`mt˚0fN_w68m,wzsY޻ҽ0WϾ_yim{7ܽ}st+so?߹i/ɇA#$|LD yHa* XcE`A=j1旃N6mipg!1d/_/ïuqOon6ӡw^?Z$/GLʮml˱~+%`sQ-rz q-mݺ|۴dƇ~?\+vVҵax+;wE/3rH<(-_A&m+/,4N9,HSyaa۱`ח6z7>~`}ъGOD0i+=Ʈ]gi% \Z~wNLV uj~zNޔ}~-0kx#)I,5+~=q Z,#F͉mPK`Qae1\0k˸26Yk)৷ux>BryY_ܟȖU$VU|"nT$ALVhZ\rWi..9>:UDW߻xx13<' FE j'` pA5e+LϖbtI COx*e5L y{W,*e6 0֨R wocMN]/b0>C+=N婂^uanȤǙ*Xg۵cUژ6n@vB:|81!Gyu^V8V MBI¡{ҍ*`(? :9!pαs\K勡nc\Ac@0,;#C2~?s lP N8 66$lGE,e^ĂЃcҨMT#%K_wX|ӧJ3 C ۤuRV55 pG<"Y13+Uʁ5#]{OgJ CbHtHb+5&fNd~n K6X'6SxbA &Vkn pxf֋I3n'lT[:LiAiT :c6bA8J}̆4j [idA|}p/?畭 )ܨ֨!sPTdy'ͨD:ؼ||ZEKSm 1 0]2_xkfs/Wze@cĴϻBs;b]:=^Չ\͒g ay0 5=JX>B\ KR_Ӭ?$^̂i~:\ݿ|z΂$DVBgrqR^\նqu_O7sHv b_ͽãÓK6 вt"VHh*iòcgMA(o]_̓??{aaBa'{W^=:/5'Jld.L$;ȐY/l~fh5/ yBz'>G" 7:7v}`],-ݭS4eieK€peA5%'ƅky/_ Bg6sHbF Wv\&;fZv;,9g{A6rWToZix$^׵Dt&qL)7Q% AaQGM6E@>t%:c2KL aUH㨤f#ͬh>B|' 8uq"@P2,-9Ku8Ӆhp%u 8@h;3XifBUYZd(Z0˪>A/M@dp}t؜/eOk˩?%N`LRBvW~ltrzUw1]ж@@2\mO W4+=| ,K1_vCۡヅROjdh)(!J[e균|2>hϊr}P"ʹwٸw۸Ǟ8k`2Wic|lM8) X*)3 Y" "U+lЮZT`猭25ė(r8b(ي^^ /9#m?eh8 ֍|,p ӭ*iR ~lq n9ͼ#;%QOZן&ZyZi]agviAp8 $"$҂٥̏{վ1K*MT 0p뷺]qՊZZ@乲 Y" r[?pY*V!#[ԋְ.8@Ik-j6^MF{DX$i#Qv5QiM*eA&8؏)2ƶN^[:˧W7s(q籬~=w|}?yGW Ē +$L֩3ɴQ1T/poD`vdG?W/?_q/ [$I+zH\fPqNK)g1զ9\?M/44 a H0ϐPuw'&F]qw%MAtB i7*3&x"Y렊1fϐ6;]f{\96(f385OڎM(KQ]$%e7U- :zGuKF%f2xQFz<<ϮYf?pEJ-pUԓ4C5_ ;be$ޅi}NX0j}\@(He{!Pvf¬h:zPA1'`vz0wcIfh+eWߴ2iw LSFqsڧ\6u,l"XѾ]GO i*и%==A-ڙH Y )_01t**UOx-{Z7NZ̴;O_Ak@p\5T!7zS.-qMNlNC,OѨjJ*SƬZQVlg2֪1M R=kA"o :29~RZDS=ڦ,ZvUʶeܪk4n:;K⧑$1:YzxS.כlrZ;Mݡ<ř=@R9UD#Țu^3J+ -bo KEԥU<-аi,ɢ("e/%'b^i_.z2d0ɯuy\J r%7$L՞Y1e4Ve\ݭ3BQʶXA+o~W%3pc$ (Fvd7ʕ-cVU~U,KS(Y j c`gijxf f܋/_.lPtt1(,FJf"G;zDUÞzoiL5@SmX{`B /}#^ " 3GuQHO3`oTU:6W_+[OeQQRfmaPww+pm;PKK?3P@010.npyuyNy{N7 ,$A`{J$K%ʼnubNjdOd;?I Q|꥓}oTndO*|0  H))X\_ ѸfI 8tCb(*r؆Vҭ[G{[3Rtј|"6'쌀XABl%bvHN8`"ڑA C'Ɋ$r*rlZ^mċq>6uWoߜ}kϭ^<7;XI%-@'iNAeކI܁$$vLJ  vXb(؃"`#!Ntsb:w?ǻWAWgyw?S,nwv؜N4<q`LGA9}^҂. zdO M &˗8wރGgg>/_,275\nG ,h˰LӐE2NG?|vjB!H XRjCn;IF`HJNܹkwn}_w/aZ}=j^rT*N\6_(\:d,ǣT>ZT{VWWgfgh$4,$k$#SJgfCK, LO/LNNOO tCC z  vglrvv~r׮^~pwŽݝ x6ϟX[\x"/ ʷom,//.../-OO.-,,./‹Ņ%u⥋{o];>{>}ۧ=~'O<֍kWK}޾~ׯ߼~F)rMX{cyye_M./&1VVU6Vַ6._9v||=ŋ^|~7^|ٛ>}7>}޼D?tcHgUOƦeg禦gfgfgYAkv.]>88:>>qr _:ݝ٫o?|/_ށ>~xç A1K˗*rvh4QgmU덞Vh;CNgj[\_Z޻{[ܽsέ;<{ ^<{ ^<xŋWݤin a$ *i#pÛp % 8 rIkJtU9NR[wdepIˇˆDywد2O0?m%]qlv'ʚ^ u<^i#X,>,AhmT V-f!l`)E FgY,+@/NSlDq@F/悺l.4^>D\Os370Xmo I&F(#QYMOI`uƉA*K6;5l9Lq,utYs{@t`f%_Ʊ$&Lts)X 'RK%w@Hjs F 6LXA 6p2x=R}S)T3-B,Dz /46Jbuց,%/);|h@(< 2 2sn7y=.I .Dd.Y,f|Ebb*139(+$=a%$lͮ>Z‚O@ɍ (2' .=!+v3U_<!z=  WuK.LCYKyh'dr <-A~ Urtpu [^ Ttp"ƓKyM;$V5ILt! : Z!ЖEY X@0ML:N{bSՖ,d]O {}wgNjGLBquKv) )~ n[XHxCe!sr%St6 gb&co$'QZr<1֛nf MvA@sENٗBX9H,|S {'=9{~!IpV0&ӹD>׳uMba"3_dNlOvfe35ynj:@VM2E'KT G8Y""! [=\۹rt_aDxnqfޔg3#3 kG[Bب4΍Jj|Of˦0gs*t/H;P%)SAﲬȊ5;Ўz{ttbe['G7>UF,-<ϒy-7 ]٨=N ly g* Ń?t0e.v`,o~wկ_tvNj;S`fb {F[r(P@@ieYG4S@Y^ &=D[ߞXEb=M$H WDd.};ӃDX H  惓X5U7tvpMH9XbSK/5X^|?ZF As8F^o<0XvJoUW/ uc-Q3<IJHP?*A`HsvHDF(ZcPcw.KkN3_[^(v'Vdž'9OarR%H:sqWz#)>*@'%b0pL2VV6x36j ꝸ1$ω;@%@H6&e('%`OF&q~תkop"t*^/1xU?ſwY=l_]wr`gim#h vN]ZI@-Hv2@yp ҟJ&xokAZCXR=d\ZQ\o2-';wv޺r`ri"Ȼf}wp:N%xD IITCsCɘ t̄p*\aL-zй[{ͻ: #!yo7j;?-K}Oחvۓz:Ԝ9V5%ɯ&0qB@34!i*mE=Ģ1Jj|jjTޓt\T{|wʧ$]k'~§ ~eaw8Q`8Y XAcd\ {|z$d|XêA f٭wmVVz`#syܶkޜ۹)!)g)ҡ84f#UUh) 6 f[UQ8vW']*ǃ^t a2fAx3!Nh98͋ |-Z)t4 ޠJ&=UyGֈoTx u?fP:pBP %0lp`h1V#& Î$jD &Vތă @^+jH'뮸~*ZK3;WO%K8/^ $TvHve20`'^t*5yZPyZ %릗B$%rɰ xT, ˜!V`xMRyF[s70} %A AE06=7O@QFao UuD+C|!meB`$a $@ʟ%bΕO˿cݯyB1K2 \£K٤7=5ȢpG(v?]o0eBL5Z,B| Opapk^鮦L{՟_8'FCҀ*#4],5VzǦ텩Ņ$|߇USix" dRL*1FHf0)І92p'?Iŕg/ŠF(j ͧ+h8#H<ӰU /Xw &BGLXW'! UZ$HdrU]2tXo;VV/~ݯ+' g%VY r ٹQ+}ACg7l< ZR~]J4eHQ1 Ä\5 D}!*'un"pMyS5p_XX^Ov&i vfT Y͗tF4 cX ٗQ}87Vۓ'}o~9N$? 1H&,:ӝT'=AE5e;Íf C*ӱht=l,uM+/~=)h*DBh$ b1gp4ҹlX'}pPхD8P&<7;hJ4/JNmbIk߼ȍ6|6N$x"2~$2.P:PׁpcCCzZal"1ۅy憘(IQΎ_zxg=Cv_ zx*JA*Yw؁i9Ї.EG6329kViXJ'n$sT#`nXOZ mzZJX0`8q\Yo)'AuaGGwCVhg'Gۍj5` p0C$CC1'+ͻWhofnf38ЂlQ\<x(fM@#KM ̋t+ScÃ͔V)rp6 XJAS" Gq_췋1[nNͯL [=RR-AD@^(qPɯK!]" ε)ʉL[x)IeuUaaX$c g>7,, =3[3vo^.z1M,ƣ;P;= q€ YkS>bCŢ>M. ,&Tnrsw~xtnL|hwI 7]0=>:24ndhT*՚RhLaݶ&8HDq'-P{~d 1sRHgR!W"X\@ׇ^?:yރ`XY=L+OE&&P?Bщ ,'Z=RV\"~I ߽{t+  /-NO V4#MGfPcцQi@uAۨʀӂ(:`RWkrnCĎ9{rrpho}r5fƇ;z`Y׽!Xx($p !8st8p@ @((Kj^b"Sv~p{l& b`rk'/# ‑D0C$XB&ĴpPiN`i޸ړ*I%BkvkN~7wv&'G2TV7/lfRhL %H2"l]C!. X(XjXfBD֎o8ܻs^~峧=~٣ӛV'G;ޭFrh 1t2 | "H" Ih0F42ӝN_ AKeU ޽u|pgo^}gg_޽yͻѭ]y2[åIHIT: |.FiA?NAe*|W׮?~hGO^;H G7n=nm.-LTzoeM!z&Px}􅐰VAT!pyOFz7>>~'96g7f&GƆZÝޞjIc9Mv#-H C= ,/ ǾPWC:d>z~17o>w|zwv4HVU*=n~NQdYm5[J^ehE™?NnuhʉnX=Y<~ʵG׮]{G?7,'(ZOo[s ,r 7<x'B./\uǐIyU t3zٱkWwgN.ܻ~Ǐn>{~A}SLT({GiDn҂jݪ-́'@CÃP^}AcyX F4rI B}nzjN={pp7On޼=YC?zMenlJ,LH A4JkBK"b`Q+26 $Z4_Z#+776'!t8ٹwz;ONn(UO^|xi6BT81G'Ф&Dz"X[^00pbDuw(u*f#bI$ W@U$M4q>0K%R\`t> .H{Ő$g-ٗNfg۫wܾww6iufbaz\3DIW]@ЃL5I.V݆e d|ki u8z٣7_޺<5SIn*FeDC8<I94YA{3( 6MA=w1ۯ^>ٳJlpѻ\Mɾh9p?xVBc>HJD+~٭yq'pBO0>C8h6g>~g^rhA 8rrѭk|ͽZ_6y682s~cse~.@mc[`)qVr 4!>%Qv继?{o?}hVX\ul/xqxagnavm]>0>ŧ369>:`9R[]5A3Po˃; +%rl(fB-T@ЛSWJwlpR41|j|;hA#Ο3,P, 8vǒɷ|ݏ>\8,V~1;BT]. 8%iWsHAo6󸂽cccccCE WBdoj2kuhꅧI (ɪ1?7_[GG ˢʦuK,nkQ rh,Ju:kTGFpfѨ<]4F Ҿpp~?W^7ސEE\.Ԋ g_cpɪc8dT2luhxpxhI4DIvހn4ʕ׿}rx:~3 L`x:UeXH(nSxCy8Te!o@B#% #T/$#!_'vIܼt]׋"/ "àq4|8G-(xX`H4 dȖC~{h@BC?kKAB .ɏc99hc@0i9X'AXBg  ъjX;tZ"D*һw~ 63͓__,o0n7!`ey|Q g¹@Հ޾vȕՁNB^2Z7??YZOO\JJ7 z٦A!t=bp랒K p55O,|uwœ 8\_5oN9<7\ พ+HfJRp^Bgo͕"u`+܀*GvؑEw`lUQnv(4vYVfLuq+vµB,S_.;2%-@* VtJص=5M0DŽAhYuXfPT 4W4AeZ:[+ ݷ_?~a`lHQv/]EE$Ip}[wPE]8MWhV2 XUUSUaQMELP!Q¤zoxŗ/^]ʢw/^}W;nѰ>b&W> (0wE*%Eؼ/ )f89+N; MhTl@Djٽt9Ț;3b#|ЊR}M3/нB$؝D5.UnQ`NQ? 3љLN<:iY/(9rP(Ҕa둍iMMvO/I=wt*Ec5v[ƌ,<R@M+Z+#RG(UT,n*c;40Ϲ;4; Gw4]=Nј"Eڰ2ݢ {vK%UDK3|*/UL6Ic#ZII  ;ۻy}m% :t G}єX^}- \@ftЅ[*Ai`BL-cx: ВLR ;wlD}n A=_o*|WJӁ\SU] ]I"Px8Oz#D6 #F?PKK?nnM P@002.npy{isGrv   xJA]ki%KûҮ刵#g_x蛙=Tllb&c03}TUVO>W_6懯߼>]w/w }?_/upxsw_.J8Q I#xRT* AFx^m=5>G|x/:Ee"gFg4HAƁZ YK]+)im1]'V :pQтWI+еXZxFиW ^H0o'[Mx ?˱&DY$؛~ه?~7߹/\8?ȟ(z޵ëG&-G:{jőY!vD.v>>q;M,h,ʠɿĿ0Ŗ^Zmml,ɒ$rMbgQd1+YwG|QhQM,{;DRA "@w%B` B3ӆ%AD~0&H"$i5Xt?|FQ>D+ \3l(YjL)+y0$$+p\-R3yk{`7k{~ʏvV^eH3%4 o,iM{rzbն"؄XBiij;jm {m S{>q%c'䥏bᛙm2R(dh;2ե%l~K{XiydM„;).ZwܗYá 9Qh]dNC:ߟ]l)K~ 2xݶun|qcDql un`K\i?+>}{5?y[Eb6=&7JgQу/Qu#yc'}?;( ϷEǗJ52 @V]WM|n2]o إ_} VӵDD.I/\ҧwBcKkKآctJj{۞1_|vuesp'qRxwCmɰ?[Mrb q:Y?y?Gzn)0:D3pMF!_0A}t{C PT,ㇻHh$p}0qT>8対}o>L׎kkG{;kCÕʤvz!'HF≈7Iݒ zwW:he;[\iNK8DgϿZ/>|wr;Yoh`ׯi9oJ@dRJ KP&_@^Bk5kOK+o0{!~A;x ;ƶ]x Aiy X!|"řCmI+de#A,َ +鰦嗷=M|ud)8x.8;ZV{ N%B9qlf=+8HPo<|zݳ:[J\CnEGO>\?^ 7\ hD5Ca@۹v7Uw e#;r\~0_ 1BǍA> <\'&b%WWRڙxT0ʼv{2#\^i{+;J1f2~:6ڵ$i,sv2McawqyQ!a m8~n%)H&hL$[-I!:V(D,\YH#6Q`0USӦ+~ ].´%EџNVzN7AzѶը%sV \T Gq0R̄Gho 11۳ˣO7!X?5єR/&2RT<4!꬏:mOa m\dy0NVdZ9[Gifch}/]`9 Gs;)i*G2JH! @$E\Mjbq8vl7BV)NwL=o L(*j9!Ǎϧ)(4<$I("MR [ ^:+ xۿ+޹(m & ;h{U4*6q/{v{kӚ`!2+lm Ή)ieq1+4S򓣳kٓngȥ3Gեqkʯb57.pտ~Eu[}˫&@9 ߐy=i+8M= uHcŏ_ϜLfͶy>tF0H@K5gaIHV}T_0߃{~oH Um{ H 7^P-xe?$QD!I$FM:(,goz2WO3'@?dv3c wqP/yh A1zrlhq\1qGjw段,$VwDH Hx Im] C{n]q @; džٟsJR @R݄ BdPzPH%2ư5dW`T0DGHPgBw yB fzKV)8J҉Ъi2bNvJРfN'dLn_]ѯoof #7uАu:w ӝW1~깕) NLLPSN4E~ԃPSh]Ý1 v6m\2ӵVU+gAG쉊D\gHYC\Lm^<:Yԕ.qN9V"Jn8th:+ Wڙ\KFJ]AB) UטFdQuv57e˅?D:[wуܿqpչ[] _{]ҬBo: Ch$\0\0Q%L&k뗯?k^Q# HLz˖ I=|?#ڏLV?_AMb% < CyJk0s6:Bx`n>hsȟ4GHX#r {O`0",uT(v.45vm(=i& Q?y*=r\Y膤GQyB浣Z4kdH2oZ]c6.b+e[;᫧nQFCWbZX@3w"u|E@4+Q][[pB+B븢.E߼BE+(uEH:4%J*Bш\V\<խeg~B Ș*B6hx .e$H"21#iY]C떋TEQUVF -f*|#W%@ `Q,z7کL*2Ide;{$SgҤ(m lܚ {@Y8jZ2/7 &S?nc ڍ^(Gql z\-FӕTވFf\+ktÇV}jlk.oVH&:<7#hmRac<]՗vh|csc 1 W_~rzo{s6~6#8ͬj 4~YؓI7ѹE(/"d>{~OO?~ .[BH}=YZFP((xI ^{t hT;/cߜ>퟾:Euyԓ$K9uQW>Dd }߆A(qCYA*Ð-=X7ϣ/^3&)<)­I]LjZ;K^e7堜實ձ<*DlVV^>ßk3DB2\8ō,qǔk)j22)AYVjU)<.9'-7!-9 HNꉺzgN%au:^)BovX<85<(FzMZ *hɗTB-"dg|h4N F䅙AFlEQ>GЍ ,Y@e5\r_qlU.2['GZpECD3p59_ Yp&2܇R6ni l۝&K^kRρ?J43aZ 0T sYBjwtVF (ɸtD~j s`+•sD=L"w~uS?R0U*I8z!(SC-َ/k&"kXY3^AwbCH$EIv׺et75"M۫\.D^e[ ; hۨ3Q0` XQB,Ary܅C$%%IeWr٥=(,2pHy|*~S&r;܆6N1 mj$^(8ɩ g0j` >}~cqpqR, " Aq:Mj|U!4fq*h J@$yu&*[Hei*cL^$*r6J% `pueȓR:GC wJGE1R4#6TG}>$qO=JsSSLjq\kC}| 2p$^uBurgߦba!~![ϣYDEI]h¿nM]'eʘnis2%s]"T jIZ-i %U(0IE)'*^C""bs*Kx*Ȋ-T]#o rr3LP[IE$GJ|/ː%0)W6:J[Jiwӕ?UxaqzUrdY<;mP+}4O}MB7-.^#nI!&ʕ{jKb 3漴#\[IC-?qte1Kc;ZFCuP"vvU˪U]QQbRUpfzGK6LpA?xŀ"_dP>BuG7ɩp_]TPKK?KϲQP@001.npy[q:{v]`8EeJ6E[ Ҥ!GXJ GxG_yTU2tWWefe~yT}O~_O[ӫo~˿[yvWK8ZRRhPeY h芦JPz9<Fn8ϗ /U62rf2q%ő8zvvwGh8?\޼푺5#zYgzӽ|{4dMg9zso?F[27J%|/DF3: -KFDR]#H)%.^ȝszg:`pDAt*B;$ߛ < u 8 #`$83qh2u? 1P`)-j(J$5IF¢jBgy>nM#I`zSq|Ox~Z; #7/}SM&>&`Dߨ_== 7AWhHEUbqPE&l$2! KtAO(3&a'T1Y88/mMCW=y0")V 9aJ v2ҕc5/&wo49dк\䎡i*HKȡeXfXBpD e q۬0]݋#&[ŝr ќUp'U;ENq$:F*ؚkDOdX`%1goOs2GySeFa rSZ.yHFOŮ.&( nͪ x^ǧanj24VOPpjC,96˺_ dr: E҈o ̈́i٫S<ރ9Tc8{ŹH_.췿tҔ#ԗM"(] 5~SNqqSxt2G5|:!uvEd}lY8n`Bv-p!8Co[-9}qk^ΊLQN=IO}*UZl|_l'L{GssA` #iD.l sʞ,e$O3X"az.}tD"n#ssCheoHGFCpqJ"l -NìtY#Jqw~m8-;Ծ(\ZҠlmMԏʧE.8}ɋӬf  _>\Kj$DbNt=!lCPmfz=K:#!&T tU! ?8IWw|k[~k$%" utmv6a6BmK4?_k1)CGj1pPѥ1_e>'쮫ddv-:Jim`Fsf8V$ ")٪,c/ȾY-^wlx d=;>fjxmz< NbDPO-6 %KΌ3fQVvA. ^)4wYzo>ΪyH qeݮN%}/$=Zo<&Qㅆhfd1؁'t{?%Z_IO4?B}cE7a؂yYN49ӗry E%*PrXɯhܟQO#p]t@|cnxŠ&/QV$ q#C6:T;>A!͋kz#ȇyx0Ue1:*)85@-I_$}0$Nc itoU}Tݓg%t@EbDQ&WÊ:2CISlV߾ (dsCغBS1ֳ:/%DIwfONT9Z—Q7bSCϤL`5r?*ȭ`yFCL8͜%Bq[*Za Py#doEcA$%yUFhix Qe5r<߷3C5t-?X[1zT|er@&W#0U i/IՙzjB=/L5 XC`w5a&2”vv@#F8୧<-ii@g9,A\$@bA2zkHPےsUA+Td )/g+(Tz^u9kbP8)C8d B砗r򝁕'/VݶkgZkAv0S""CЧ7胦Bv1"RIs;YIFZs6帲Ib -"DCaDn5&=$_ݑ 1TQi% Zt+z[X5hh@p:2=0H5?~cTgGq<*F;"B}1ba q;R}⡒dv*CN?\_0zo~^[Sm>+vtyޅ."LMn(h&!I7`"34\a 3bkh4Dg6w!i30 i\ɲcPx-2M.:!(ȁ29/F;Ib˿tՊQq4z$ .5)H̥R}ĩp=8hm-Q׸#NFQ]'9nRBZmqN >9&4p& sτBHXnR50L􀱁n.E o PT%E- J(Pu5gIԢAJ"P%"6+( wM4q1,T[Y^rÜaqAwx<4KgXЛMZG%Up8yzіS%N˥(16~m^GFT eG9)lTF .ܠ>;hL_&' AY j˼]y̐2,Yl42uJfƄ A@sqÔIMI&{U8 %F[=1pC Py6Ie:*X~߾L>Bi;rtVF K(ZՋ},kqQS&aHx< peڙ"pF2CmQg-m5Y_hJ*H{YN} ryoO׷W(,}޴*|\ hؔ Qz 1.BFxȄ9N^_E% y NSc߰vnq26U[ dXզT1R #% UۮEl\$#+P}c%ɲbȗ9PHL(BvD !_u/o`¸I$;hhx xc(K̚WMkM/ϫBclPixƎNmT1"?~|9>g٠nf+!ZB;jThw~o򣧷up{>hYQf>Uq;0A KRǑ7?կ<=&sӖ"^#λױ/II|ӯfgDzZ".,G"Q8J|Ϥ\W͔> ݃yLy}g gP]&F/.!K7JyoIcB4O9g1& {R𴂸aTvpT8l' tqHJB$($50\)u޹:TC4k3غ aM-krJ+}h+]BcS0D+ȸɃi#) +T{Ң1de~&:TUZi Mаov"ITxFRژvcSU`:Yj)hū|!Y! nUH[t'Fyx4>ZIY}z{rR7`šFFe b vd6NdB O<ka*O`Ox4/Qpel\Va"Ziv?W<8?9zipkSQ`h\>/*񜤩16axyBȱLcUh`&'˲ƒADEd'3 _yO_xxW_Єi%Ըc)&} P$,蕄b`b}(Bѱj%si%b20TH&ݾÇO~߾~'LwCQMQ54TU3mws L ~2/WL&]K3aRjm?/*~XZڿt0< ij|r#XwYj:k6@kYVJj r\h4ZF/loai77Nēdh6FcpBF-/>UC7uy[Z__[]][][337;[؆ksg6/\>tt||pţK{{/mM Fn x9"V"?;txtx v6W7vwwwwvvwwv.ugn:;=yz[7oݹ{~vݻݽ}~v>zѫ^>W.\2 UcF W/_>>tLbgkko/}o%/Lݼs=|xݻ;;;?}G/=ѳO>|p}x}|G\1UgYӍ ._>txFaw/T/1/D._><||V>:9sѓϟw|ɛ0T0 K/^\aŻ;` {{ ?.^r||ٽGϞx^zg>믾wx߼}"lLr:f͹tptz-߻O?{႙yW_}~Ň??+| {;AʏOLLNwGG'ǺSё,Wani&wq\ɕk׮߸qg޻}G?zW`W޼zS˟qwT_hW@`8 %`Y,xbۓa= jٔ '[+[ f#[e Ow#LTE, K(#ÎhF%ß,ꀵ~熻'4jnBPlmz4;RXzx%iץ(A5̦3NPSz0 ؐXLk̝|7'Z#4v+ r;O,gۃk\o&'jĊd./׈\H)ЊT20iJ V@@V: \곏ώ~/yϸLw0Iwl#<4S¥1S!$Ӡ )S#y" ܟte{nf.x|;H\K4?}4;|M/es+wiLڵ)M\k튩ncXU,KM%6;l;0/`_=HL/[]^Xz~~Ql 2rSb㥓Ԋh6zG+3bU_/Lm^>AtxK4g 6HNg rMp`h;3Մ[]˳]B q1YD15Vczt29q`0,|^Φjcm0M.OjNaatתj!WȪ-GGZl0t@ /KLJH1 Z Nbtai孥bkm{EC3UJqsm8H0D`% ZfJ9E=?oazJ!p|M&˙Z?|8ڹrt7{!CRjZTED0},~삘u`0 #&dfXWC3^Tj.UR!^0~ܧ3Ibܺq|kV:9[Vup0(agd,BBP801B^)s g8h45hr񩚩JZaIj[wn<<&7^;83VCXeAŐعD\.¤ޕ;GOKR}g OnuխkDe˝?0o&i`p EVet|bŠ$-1JdT! 5REHͯnZT?ʼnR4QfKУ83F?ag4am7ү#a>Ex@!3$ՑL%Ҧ]Izf %s ,_3-ڥ߽XRe/3ᑻ2tny BI?O!KY"fF6T+sg -)& ՉןmƀIa<,͹owjGr`$ ", sOIs:U9JD1GZ4?]OQ2USĭ/Ж.2VH[dZRI 0 Qh\j) q=$N. B1 WJ]5MJjNnvMলlP0/F GV,z ,JT!&2da AU$$ɋDl͗2f5B<ܘ3AlX0ػvo*1*v0]7Sxd  `ӳYf$;[d[(? ̿2CCFtSIdhֈA| ] & 8ߔd'+ALb>/<As@52ɕrltX,OC^J6 Ŕ-++r,"t@`(wqK _~AA^3^ xataysdmA@ȁOZh8x ^ E|kDhID1P }_o+?_ gQHgD@Pﭭn{>@̶(rSIL#LJe QDl IXQ42ruͻ?hL@L̦r @ UDI%@9 t{˫+k[I<{@އuLKH5ERɶS~|!S%-dƬ|%l7e^5dÔ 7*JP]X6#&<)#\>O &ʥ|I[M$TLp: NV)—'_D;l|mEpǨ ]UAVsasyޟ'_&o\f]ϖk|>$Q-n+Y:h5dX\ ~w_/9 $)E34 P*hϮNoomlL٨x"F"41T7;'gnb\S" s:_?l  6b!nurFwrUE)b1Zkr鸪2j1~ &s>_v匥ᘈGRa?EN,H; rk,eE E3ʔIG[*IX*Rٝ10{7N޿/KR#{py\gSO*<V~t.D2t\ea%O,ւCc 7}cXAkbjrUeзm+k7O*;㰶jM~BBJ7[ @y >H$^RxJ tSb-h񙥅/l/K'>Ի3FH]7?11iS$)q1(2/{Qd CãfYCPgNF٘@@Dalsӳ=66ԶDtozdVrHZFi"':ʎE189P%X-ҍ *H00u"Z!jDoqn9d4shY-  5[NI vG#uXGE~-* Ä[TǴt P)Ed\?ô0XJT깂4rGp^-uE1QhjUo*= S> `XΝb4O!WigmI~62]-[$h坃@QZ\tB1WD F78y,whVxNZx(X`0<,aТnI]hՋ.: rhZ̥DƟD% *>eh6H(x IO%:)Gle:#)Vrq@c $)x~X5Jj9kX-*nό jJ%U)S?sFN,Qxd@Y5=HbF\6Oj\*pC '1RAXJy{J4=;VJZs̑l,:_ "`uBМ8Cݨ ߷--cq+=tx:z),/Lkd(1 { 128ŷZnou hEl b!9z1홚a 1eVRL2텢hXN"x\ 28*/\SG幪5GK#o{@Q380Ȩ~ j"niCUiR㻍l1 agT!I\h Ʉij@dE%gŽVmz~%W |7elFxkOB=`Lsc~Pf 9mڭ"sR^)>51;71.e3 mM<>۾Rm2: i ٲdž??Hy(ʣsVxޝHeG:F-dѨa6D0ZX=Ƀӫa7,Dk$;=\b?SmnK۝ɱ@ MVd6өz108h5Z_=x'Ճ>[q&g'g B5-(†=4n C%/̎R3~/^kBP*HU-U^[tʵZmG&LJL*c`m LXqR8*dgVM@.:VY)Wjr uGZjpF36;3;126T_MuG O6e"uaLIzE@I;3'v-@5&KIt>ZG{Y|ɦb]Ron09K%]^[p국, W{cB;1,u a'$EtK҉x&L +NjLBD3ԛILO!F!QA ϭLNNz "n~u}uE>3 0V/P5|IS]ȓLcX,I$+ 33 TC-TQB /FpVgph+əbK^xۯ k3z)~3lIrlTy)P 7[Z\0 t@8 _4zTglZk~~\"+'j⼞ȗgg>_d9'+~ADZl+ s3],$ Q.x7o_^rt1vM -r=r߾ݯy}]1.4[D{|jvmLתKt}F{/]9r^!6ozjJk<.߿}R]M-/on/veZA:IL Z'wz2 Ion+W޺o HiTIW K"gln̸b3,k l\1όd$@i\t֏@3DತO^y{W~abja[ yXK\#br ?gi^t.J$≼@r?ph i__|+'Z{N) ]MulX#Kd$ υH" ,K'R4?[.t⡈61 bDDwl?~g_~XFxWu˰<πaiA@j QDx#0k%Sb 2=a;lm .ǿg>|`d, %K2(W4<t$4@[ ZNruF7zhTEq7_}nag}?VI@A eFz"EVxW(Vw8v܅xȥZnbȌ9gXĂ2w?~׿ï~L%v<[пݬo$ ,${l306cN3lCQ6 Xc͙KOc7$֨猉1^QYnyk9(Dhx@hؐi nMV́^9 vE>.;o)(Y0~#?0 ˱ Mc⑗$j|> Ѳ]0LtQJr:06eD3R|k[d `NS,st#nlhأ@ x`"E d I.?hW/OxXraPu  ÈD,KT;vE"Pm{pB) 0CUGI֬d}yvvPOKΥÃݍqaPAtMd[SPjadƲ0;"Pߪ$)4Eu3#v{M3LaI-\x` +cfadhfbM_aS@l4'՞ƃ&Z{'W]X˳h#88kRX-B Ep<8|!b+X-oݻ{$6ο^:?\kWՅ 4X_G:)h\_R\D)$Ja誌 o`v(7:ëfNbΝӫ o~xB2lb Dͫ7o^<ݴ`{M\,1'ע ZYEq6MdV ̰5 {q{Ԩ/U]xp{OOj&L Lx[mx'xd.pc+"~ ^Ģ1tE"o"%N6ܺ}/?|;wNJqTWr` m  'k(v倃ca~A?W "'*Pw=}zgOo_]-xjf`` j)Y bsn 0+px7 ?Fdt(2AQZ7n\~w~ɣ::Cͯt+9$; l!Z=+(8ѐ꜄t, ê^UǢL-T=~ƭ~줃iF79o +ȌSĮR0{h{OE `H*~E- HEB $@joWH*Yl" ДXOIbѧ@Bv-T ?]HHb168B;XTTLM%{IAn^:\)T%,0duY}?Ql1L;O-ѩ顪kL"`u|vMÂ=փ\PRxn0 Xۯi Gi0$@YbzY *lxhF`% +&@aNe)$,\AU'i<`0Yh|2S^F!.Da1+'㎢z\]o<$ɲ (P(_/MxGұ  %sF .q$Ew-K庠Bдc}9h}t$8=RA&?9`"F}N@d 70~_@HV:Ӳ%ghb)9ŀϏ8m2A*PDza߫B6Xw IQsxdhz%L,0ȅPKK?.P@006.npy{Ws\Y޹{WU7(l{G Hmtv3=f{vGyPl =(EoQʼvbU @Tsd~}y{[Y$V2ҕ\<g'_>8o^~7ܕgCxh² <ќ@Bq ,ӄaVUEUE ]UdU9QaXA⎩O| ђp= _/9"048BXM-՚\l-J2W`y?bhZDxYdESuMp6o@7Cm?}44ZՐ#Wi"LIķ,ˊ/^"ךng`j(I,a #0H@TI%YC9ӎ9*J1lLJO#P/O6gˡa¨žz UuœBhNDU`(x0 {DbqDX}ѳֶ'D,d]W^5` 0: x=,0Dx0@& KpۙpZoǟ}W_~~ٻw>:X!4M /*S K3bݎaܕNw9Bޛ:#REIr1M5Ӆ'gO_=~ǯ99>5%lrn2&fja㻮+% M0 U\ǔd!~uӒ?^[[[Y]?xDͲt۹ѡᡁv=TzZmFWwW^)Jj~rnJ:PccC#cÃ=#Cm:~7!2(Jф9(m4-iaz^Z$211=355ߓӋK k++ۻ767nl,έm/M,X\lSk;vfh(ډ|kdrv|޸vc}cummcƍ[;[ؾy|ݻwO;=9=8<8s6\{gzׯ?yhezzjbttlt4-YގZ3;oܻܺ#ߺs˫9=W/?'_} >ӏ߾zms-ML7tOnܿuko`s }sogwsڄlmO?zÇܻ|ûw_\^?/ί{sow6wnކm܂7?zɓ'/=գˇ珟=߾w}؜;wUY(JulˎGW6VVWWW1ZV5|onlyvn{pˋgg?y!~Ջ/^|[ VcA"fd,x<cC oHsl!/+zw_O&<048:15;2:2Yܻ4sΝwn,ny_2؀,24mۅruz'?{`vysdkYa?a6$((||HS5rNLJ"$$9#֐5<,I*ҏ#J9T6t]v,V$VfJD'N*cA |Xl'EIZ2c9&5CʕD*LhD,-lY&Z)&'#,$jҩ@K$XzdL`9 ( O J"kx3i;tT*Tw>_h鉥3Hp=E4mg!xBq6;`K8JH^E% U .GS8'U(BޛVFliSH Dϋf-ኊMeVy(l’z,\e(y@hYx Ta1E$HzL3N8ZxWDYSb ˫X c@g8ESL1q)b /V``0,AbԐ8!c|$:M ;Αx0/'ף"it7WTUODa`M&.Rrnjo%w78Rͪ 9weB<[Дհg4#",:|A@ <\.KI2-x?V%cYP^)58bYbb|N\a%Dnp:ՄYX`s ɒ![E{Ɉ[q'd.Ԁ(z ԃ?ї,lMdH>;״Q5:dG@Y\:=:VҗgfS M0R/<o֒AnQh*f.ݩԪ ^ghaSGA,P/@Md.p8p,8UsB+$=iɃZjf+({ňٖckUHQ0 a Q-G&`\Cd%I7,r:aOk>61%TW5´U2Y0S+GE`(D* ~ۇ>z7o":,г>XKõn&MUudjmo 4Dch,3OnoLM3Ӈ.^쎥$bz0Qkw|6xJ,,,;Ycx K 9 R?PBE!EӍX9&TaxōՕw?ݯ^w!Gq8o{"YՉ,d⭮Խe2h%!ۢt&G0ڎ 1o{'nNߺ{dDjX:j`LwWkحx&YYH+e`aatB {Lj,[$`& ;]4jaQ7'뤙0) <2%wab5GG6fG{ҥbOȆ&ƫz$`(݁!ua "AҲ+]*񽠚?w~  Z2YΌtv^oa~tw`?6Ի9t\' /7R})bn"_Px VV3>U)%K4]8DGg2ޝˣs+[C#U^;V{[3`0HTDihV%G!%N@d~#RH鬫Kaf;7Y֊.G,R^Y0_zj3wo ԻsvWL8sx*F|DjSd#,^: hIɹBݶƾ͟~?ʋÕǫ 6wn&3W+LG'Zbe @Fʪo;LN40Vn̎vov/믆]!:!W''Ǐ,n-ú<{/꟝r

    q zIQ-7U,JZB; vQR(%v_R!\^qcjQ3g_H:;׶՗ KdJSrz*&2\*bل*,-0-`$34 {JEuH3]IB-Qo& #SXZR[T:߽{D *A2hn63YPv}" n}+I}?TyRK&q|Œm&F40lZ:(2Lx!~~nP-YĢD>װ~I KCA-r@ 9cI@HDRE+R+ aCTR i xl}x$d#ϳ1+nʄG] ';:@N$c\,Ex*WA1t?>?u7̕<4@,s(K<i -{%HҊAc-=]ƀ+E|ehzyeiGz)WTL>9<~_,H~2 } O ,JuY'_|?/*QjAuR#9!Jch+u Q>zxXK'4X򁡄?2'T-rTtw?9'n<ɰt&\H5rR1t |6Hhk@Hy"u,4/B,RpiQ5lXh φ_P, AT@Uq7ek)(yT H5`F$ 'sd2 TtV,>cP B~`ANzz3 l@315 fB︾c -)Dfy&Q&K3b)aIP;H` 0E# : Lq ₮Pkg 7|aj@8tb ɧ`6D& v Me4` K_Sef BҤPxk$jN*b69ɎdL}ťRTXBߑ$"atj5N·leӦ1$A2XW'0Whc#hպzո3>8!_ͅIߡ.D42#PN)@H B9]'pB焑k]l@$Ŋ'ӹtVdoRJx+kk' ;NRPz˥ h1u{orȂ -(!I]oK!h1Iƪ|:gdBM%{CJ^xNxTl fJlU*gS°PWR.>I^-m/:1`ٖcd=ײTBFܙLTf`|KJqqvVM|J:gt* RBZkʹLv)Fx3,F{Z=2h鱡ЈX {ZɁ Ze~pBUf5?S-&7t>_NEٯl)nzϦޡDdnvWYȌD…Od3 El-W^([MXsV 66t1(BVw-cEHS0T| <~3$\Vit7&VW5CB h+r‹7A ,AƒX6 kɨFz&2L2@I(E@2JS/FGV&|h\ѮW2r\,@^J z8ɂN 6mdP܋#}V/lEck*)rt A1чF'W6 y/|Z@X`bOmBţdުds0K .K iglx`;B(QVE8vpxlbazRbV.b-Kz2NC1UT3_q,%@djH6xLoP+eSX҄%I$!cǛS3!OSf& So/5T-Nc LSrLJ>F &8d(:CF Tr;Ygsz J+Åx}Kp_JL*RZ u|cp{0P/Yc  ZA4ZW{u}}}cbD +}b_!;Ki)>5- d&MBj \ӦHlM  z0& !n;`:E Nu7{[`'8}#S"ao^n?7?ώ'{|;Aʲ#feҩ\-9?ZvtdhQ gݥ#& s𘞞[xϺQ^?;;ow~;Zϭha̎? RGީiHoȡ$!Ed$?ѥم1GOqyLIpf3xѳ?zKL*,$m MN#gȌ Dϰx]Q'0+ S2ZVYJ^} #Is]j=.=4wuhqaihs 3C=@BT;FA y)CAy_bHy R'RjWQbS45/^*frA(589哱1'?lg#}%<[,LNΏM/;B5 Jx>?,qipeĘ9)ߋ75=7;STHke ہLf*$L]N *$E`Jfh뀢lW%rc`7 [簩I{';+1(7a 0RCF2kgD1Q|k SBmFMڈ'sL?vPxr]ě *۵əD|Kc5lXIcJ9&$Y>|EXFlqA/KaqQGB$L~2907;NgU% ^-JQ(,0/e(2XUpy;8YplK5+rXpL0gE<l{0ՕƧ\$K)`)!^`D$'M'EL!PE@öDu(%Diqq3Q:@T??7}cunH3< XaC 2`L-1[%~fF*/WbG` H;9ug?2>D '2c^BuERع`R;kUU E%:q ].cDD S(̋ƭw?J\.%;݌@/+Hb zga<3HzR]^޺2G=,ՅDɌe) M @$UZ"{$iwY˗px ~adYJMx1pcowsu#:J7Z\U hh` zODDUD! Z,f{pX_%jэfQ]Q0N_w=͛NKjvW{`ei@誇>CΑ:72Q`SÛR"}M5gd7ă>ae܇M ʦPòl0΍7goSB]tFB::ӃHkB|ݶ&}==]1t7zq)W`*H\h>sA0i*D~ ;胬&'GC+{K"PNe&vtD9`nJ Yg<̓DSu#L}ACHDFIwN޹{ѓ?k&Db=5[QеD&3MxF%p6*Khՙ\\=ztuu~ÖSJ_<=vZ4@bDK dc"@RL``! ʡXOK^cn{cˇW>89ޙ)`_8v TN#1`eT4 b$e7:*U8H2$bFURxO^??^i.:쥅 ] ]RͲDɊ .5^ѣ#,Dx D DP`:AP<r'_ٙr px%TT_ GXH&(B<8X sc\Ɇ^M=so_~pu#4;;W)#ەi\ .K~ *'2Z~@#qe!HQֵRL5*|25v?8'u, D}$Ft8.bW"h+ҹP0) B`0ǧlD|m&j ƮuQRD^J9͛rTPbTSM`JwxWcHyD{5^"\ y}@cY;% t8 SLQؑ``h.kr$lCT5<1Hf$EH8q,ĚG_< r'NGYNzwH$LKx:iLOR$6:)49+`h Ûap DE9Vͮ:QtRJ Y2k6V@! @UdX8T$ 8Ðź%؈7+|PE=%2Ns:l6xK{ڭ?4POsxA `leRxsXt F7ł9Y;/HĂ5|tU !*nNv皆iԺk87$Uъ3<0.ECQ#FJ5ӹa =,0ndځF!UL`ɲم Aΰ~ "œp/tOG:CD-DKUXq#\"- /hh;&ln{ cq$-Dwa4 ^\^X&. 0,6RQw{Aa ViQ|t;Ї #<.f `g(c^ P<"YAq=Q83\=>uu/QT?#|k@H9q]] PKK?Sxb -P@005.npy{gWK򾪫hFÐZ̐"jvV!iC}7ݛU93+ hWkϹwpg!']}ؘ)6x=7}O^=z_??zgsxdSoNbA I(~itp}(sXBAEDpS,O^545Cqu*'$oMa<H "',/H4 -;$xQDA ò,<'+TשBʢyji(xQE``~xdGM.2,I8yY%D&8@E^y I"z E(l*i{TTy'%{{7O/-bLb| hdY/xȒ'((A@0@q誦.T^9u/ɫWoP hES(,p Ȥ'bxAD4 &PDeuy+gN凟?_}/?wX?rbfW~ee^LXkJf+{W.g{%1h~4iw`߳L݆)KD%*"qx| P"ʛgA6` A\Y޿4q!LInۆ oRX j\b\KRT RZZR4kFrZ @Zoʹ|Ѫ Lu vkuti:&&&'67ff&'Ʀ'ɱёյٙ驑񉩙ͥb๺ n򪢁M]e͍+# +G{k0XZYY]_^^^[\;ػuNOononm::{˛'Onm/M5f۲lIega6׷k}{{[[_[k;;GG}߾u ^uxtrrtxvow͋_vwVVV}߳u<UN666v6vwnlolonn:waK'wn>;{gϟ>}!l݃'Gw99w.^G\]>8>qv<1tE`N\[= 2׶66wuٽO^|ų˫'NP0wO;}~~g/^|]___=sQI`<2!Ucemc}uqiq~iq + [ wO>|3Gh 'A6';飛g^駯_77_[ol/j8lP_?F'ffW@';G{ۛ[ up ֣'w?x_?x[{[8$Qd Ll 2Mͳ-ϤFUǍTHQm:V|:zR6[CXH>zː+! XWFQN^-om.,rѴr!<8Scw h $t] =ȉ)_ NՀSe9SrP , LD.5X<ŦM4o*3\pR8,jU^YU(R\-FHCP5l^ZP?$iu_(v-Kd"v`۵n j|M`g?Ӻئff5k5㡭~3Þ ٹ"!qQ7TBL)m jI  7:&ko{铳g_?~Z zthz~K&[W'3c\+no ]mn{,it0÷5xt]00\w0T%;/ʅgOn>p Jbz0W{DЩ3R%g``Ó<*+hnZ"$`45B jfTD^6?>=}q_~m$dz|?Y697?Fdk7VFg˰EL5)/:HlR8 BIQM8 *N_{x_~~@7c=!e*=\=]ha_[AhaebiU&ǴtMG҂@e큱|Y?8^[! A ȂC%eDmek~/.%Do &ɑ&!x2AF7 x`C0n :NzUy3O)/p;b  l=qy_ܽ}q .5ms5{h!|&4]1 XZiBt|c='"PXe.L&Dܨ.uJB٩3)P Q7%L?Z_X >Z#O*~ؿ.`SŦh% *!դ*L=CI hatf/Nl&'2j 3Gkr_uJ_-]ld43<[359RIǜ+XaE[4H:ˁa1P 5ݷ\vdjg& MQytbSñ~"lܱ6.{bv֙^x~)M?R*DJ!I:u6k%N.0VJչɭN 죁qygW'O^#!;Ooս[.5>$7!XGBT2TxB( 8p$XL' Ç6/>o<֘^nmtb.F=,C /@ JYn/}u"s@'NxKK?nV4s8C;u< ]0<"^7]T4jDx!5x};;KS^,"5f%7^0zl<{ j4MHXA ] `q gRm6,Q=ˈTR "i uN-zulVG?$ C q;_ןi4rEgzp;; (SݍC_3IJ(&T( 6rT6<S^LׯW^ ST' inY  2'CC8^CPэ(\#$P='۴rn YO&j{6W)탇,{T! 1Dη*],sTQ iX2CBɴ->8^)M8Ed (Ko~`~_DFUL>_3aThҦ 0,ؗIz"5Dd‡/x_`cZɲK[;Ƃ{#*Ů.TD=R9)ۨzq;Z|WNJO+IYqF(,xDFe +=nuI"8 W }FH%UXDUDRwȫ}'S!ԋbQiSipXG# :PԨyn)$uA C( rDWug/^^|몪kY+a%o 3㙩鲤 BKʇAV%;q [ d . *b96Uvk`` *VZ6,d7l&Lc("sE yLlVMQiYA&=GxwVj`Aip㙊Dr1q} CeMK0!gt)4295YfR4+:RQ#WV|E[JڇJJp2/C$Fy^9D& 7vD tٴG yaya`u^Є"ʶB p.U,o_bZ*ā1$~ ǰ҈= nGHp+ʂ]I 5˒&d 7-"E,wI%WT (4u׏cOȒMFcC4s3$L=l -55Oj"o 0)4ׯ'J$e@B0pe0 X^c ?f&ӱڄ^-ՓDSSX5u5A@J G>%Flx抖bWAVZ"xi+Aҝ%ot`E4!:@4ASD S@҇Rt#d]Dj*|FнD@PV Z!#2x(ȼBa'` HsV10"rOzv>khD<1tݓën-m8&*H4hf<;Nyp1YǤZi&X SJBԤBXIAS$ s0Tx `fdPȍl*E3"O QPd>y"OxB7Jmj YVyKRK3]C%$J=M I.(?s'F-&b5aoCpL@v2kfB-SF@ EY7puP^ l˦2EKg'=R)S(c[S8 I]˧eP:h f^KlIǙL`K~E!nDž[]=8^lT*~GlU@p3ZU[|۝[M0,ry|y}& G:F)I8Ca&x/<}WgW&?y wdfa{=)3 b7VL%E啅vF h`YQ+Aux9ʒխ[yְ;1 vߥ,-#U@ȅ!DG\O/ ge }N\-FXkrZJv`YbҊ:@GgmjYFĵM׵ /8+57I@)M?r9d S;ʓV;)fԞoS}L,NNCa( ^F|Z를Lʦ~aa1ѧ$Й`3@\" dC6Xz UMQ aqpvaYhO\Xi4&rhq1KX@X1p8Y md^(=ǂ MW#}*b'8i++=J;@l8JF $rkD7}$ sfTZ_%02Ԫ*R!_,0\uL< H S3 {ˋˉH$Vq~hme5S@xhNC|Z$-T*V(f3+pN@Δc { E[l`10#%T%ߴja& k+ 8IiV I^ÝfZ5Ȣ\s ' LP*6 ٹ>1(i~(3G{[W?6%IRAhۖkTI>D; IfjZɃE!{c9 qeU5LxW?{32fT8[䫕j)HbwfՂET`20+aNz/:}EǗ_}?W~'3 mnd3#'?f{Cj#CN_n"' úi#X@!htz.\jW_O>/%S`j P}!a0}a"Q&*&iCЀht88mIL2ҝOoo 2٥~WʆmVh2ղmc!gVF4݂EeFuO4(0~IzVP|VEtkU[6pNIۜR9uub?6o:~;vMg_cw- 1/{Hr) :#6 i(WjB +?TDC,3W_N M34H$p:LF`؁OHz UuY'jX@|%u(B3N{$+|cK# T*@R5Ӵ]W.*=琥2@vh% YRz c8&J8É]݊̕Wߝ28]*$$X- ӴL&Ad7 r(Ȋ&^)1-+ 2Ai%([PB_2ߜ[\[]^oUC% U%eK肪ȫDȝ DŹ)4@ߤeA&GHATBcycgks}ݷ-o0W $p:`diػj0 qA"6ӲۥyS X{+M w)pKpOڙ 8ti) ^ G!ͷ*ErݢVD.-\Id7!U5ң}ݏT kmp*ImFL]dF r BL.0-^8B!P7篿7˄׋ yîK,bG+S0~&\#tߝ۽x3"ېӷHxr-IX`Yt~B崌ݭ*uG2\̤]dك<|ϟ}V,R;E5R xHe9, \2ܛl{]Gë/_xbm HO C.֖yw0H:.Y$"؍#,ʠtl`IElfK+=Vw~ͳg_<~rg[x2 2*m>  KMoSD,4(zSCp?<9z߻~zsssu{ a/+P1V gV@^ 2f ܘiJ{B7d0trAJtfx{ 55,Wkե|{חO֪`}B#ɔ yxNof3 A4\Z2d*QҥyxzO 9bzV V׭{ Y lz7V-UE=%N:RQЀ@T8kDQkĥl{=t 0a ;̜Ch#,eUVc ˀNpW8+{Kg^`0^dtmP6 (g:,(Aluj}0ƈ ^]?gy>ʹ( ;#>1<*ׄMG% H.}s ^آVFPKK?UoI)P@004.npy{$Ǖ^,o쬟uX,b 0 q$AHBB/PUճGٞgt$vß=bx_=˯H>~uvqicďf~Y(d&)"˪fZPjȌ1U74]Q5) cnak&L1M抎/\5Tቸ ;_shYbdq7ƗK8H=)ꚮ1IeCUUMo(Ȋ똠Xeᩪe{'q?/,b}c`Uqg4ed]W $ixG$kn*F38T`~6=|gϞ>uzpܫxX9g1 Q ^UL֦BR CY SZL2R$H"AIBeLRuCBU亡+By2'O>w/>xՍnfC#_fc)%MUCLa>Q1E,teU&~_?w_n}]CdϾWի(nPi_}_|٧>{w^|TW-5܋RoyѕO/N)27r[(Njk7lffČ;xoZqnH["`onXYdY^~Z0߀96 5HO%)j3z'vНOHLK< D vAJ`gaKܶ\ev9yNf$Ӝxa/lƁ^tΥ_ u'h%' ŚDz?Ұ"`li!uzeQXH,VSHӂWxsܠq9IS&F bC̈NSx&thj4-"2V7?/Sb9qT^|1F;k S:ӳ&cY_CS㢏Rܺ0L!MAQ {t_~Ν7zϞ|9&Xhs‚-m|qpʳw6+kvno^؞=_:Y%L'7u|2<8$FE$6Y]6zkG7=~|tdfV>;ԝ[;nauT޿we&=mhhaT\`|&ʚAmNE$IH,+Ln&݂H]{x}mw>.ija*[3WvWl26jjz{ibVW= ۾`("ʅr}Yxn7"0q'~q2kvIۭGL`A9Xj!@N0sB mfON%!| @7<9OԊjJ*ʽa7-6+7v(XHsU,CܓӶS]^[+{ܟf9ik3\"!)y㇢ y5B3m4rhxUQ`{*T3V\.\;ltrMn59sN6Dj'S}?L,[I%(m\xB0֮ZF;-CrҗU&sŅk7Nj[V4YY'-[ԒPjF0BǙ4 hY(Wղ;a}1]2h*n?wk)KoNqxqdQ^rie{wkz!Gd]$P4 ^ z`б3RK{hnkmxa5[y拟<7]9ܼqƽ;,[Otrjr;O>1>;l+te& HCW A;+Gը;_=~N8Gb={Hݹz+,->)TVX3A Y.%]mꙦϜrpd,&XJ`΍oܟ| Վ?<̜;_~G?56;N&{BBsǛ)U8&4C!0)Bp@环FjX S8vR%D̓kWѭ_W/|q-`s5NΎ}ۋDlCƺO0, [}H3){R8 l("૕KI4uW7^Ͷfi':pi[ϝ?a{_1lRXB#WL`8/r#6ڍRȒg1vH*΂GʷC<qB%_?fvbC&%8D#K"QٗʐC=&+WjYBd20 ,YnR|ktedX'νµ|?-1;&kyH0I"g1Dܗst:y" fNbF̬Œbld~7Y߯G)a7w1SʙK"{=+&܈HE}b:9 (FJp=HtVP(( K 6Rr+* c_GL[^&zYm Yd]7YLLcaEr-Alj@ , [(JE6lMv/?\@uZF "wUA;$D^ 0*A5ByfA b;`gLJ,+&sz waPkt &`wP%!ܩf)Gh^%Vr :4ͱ-ǝMyNjrḫƚ`mrzWԍ?U#cأB# K`g.+f\]_h ,,7\;6-EZ(jYƌv\iٖUnm k<ώ@aVo&^{.*rn⩸]ii˂hZDIJ5tM5)2%c<V Ad /?}:@_JsM/,$( A^98t=9V0Y;Q 1*+n+BĂB,-Mww\ GXar`(yd…ӂ4(TP Wx>ˊgՓA+ZgЫoOS%\vῆ;^ rxݧ/^6S}T>-%ry%r6q#aS KY)uNA 0n^\3ehWtfZt GkyyXm*$r8 ku5xJE g7[ۜcFE6n\:޿s y TؔDdi.2 4n)=bQh.̳lm[gE=<:pmoً?o+4I( uQJQMֱ @کJS@x \$A},*pvQl=8~-ޗY2QJ[@+ 4إ련d);a*8xA iD-(kJEo Yѓ z00a~X-,E4zfVYJ[ C߆N!6>ٸʅ YdD JO6pvZ{;1 VO3ֱƾ2*>N<[ iyr8+d-01$nQ6LGe x7ncVs,ivz ƪI&A GClI1U:}IDbܘBHMu􃬎`MkʤZ@ uvwBxK$r4+!aV** EDSMƮk:Us($(l\;&uەr=b[1i,DM~ϏcNn+A?i^Tq$5=ɷ[T1~ aEV*>/k.8m&Ixv.b+>ۑR v>DA4&+mݗ$\4mReã}+|Yk7MfԤJ5J_;1 w( ۡnr5bǚnyc9&l@/"G+8i?e5YQkUR{(G0 HXۍu9hG*pJ ZM3AP`&FL N֚)WLYa|(.;B|,BLJD SV0lvf16p @"hdʫEjWc#>%BL&Q{e25t8pakmV @H'H C7xO/NNX3BSІ"+M5$p!uj IH/:&DQ&`2oWzA2%كkplN(MDB׸I\(b#uv [խTgr1 -(Z~ɣw]86%]|M6h7ϕ~޺A^?֢]-QXB I7u^M^~~>y͋xᶹ:>[GFQ>!LzcM=S2˕ |5Up`IdgqT"yWvsK h&VS]ԛfV zeP_䢒 kUܫA7m`ڲJ!]Y`nA$>2ˍFG|9mVR rþueSy/Ȉ43x1Km9%~9-]w:iZzj? H 3r+N~RN( x:m!`Q 0W.]8=c|pU6wOBїX=%.u)R,K0h9&"tE¾vqΪ4u; m@ocr<{ ¥F\ ȉC>% VY 'qm]uƵKe%Q=u N:j`Xy Fa V1㜫㉢O-֤g Oq7_^ B@N u1\%vrgl)*{ZzN7Kulg~I ԤEGwy@<h+espClJdzFp:2:7WW$"ӂsKpٯ}CLK.kݻsA&^I!o[ gjs`N[:+-t9V5Uսz޽_vW޹q~U@EcV'`1? ۢlܤzzH)I>ShLr^GWOOO//T6QG,*fl0~յ(!P*ǓD<`[f~K_~!߃'y~TֿxѥW`n,_4  kp)-^&bn@g9S~a(j폾|Nth^}T֙m6S'V P aBEbST7fyT A|$%]+WˢNQ3/kD0D>hb<?=<ѣx!Sg9KSĮ>mmWƧL!,-*ogn?R[͢HZ#qC&\}5x>- +6R`-%E\d@dgn bJ`6vh[#11nK !rx,D^A4?E?7]btY۹4O/nm'C5ewՇ[d`$ F| Q{]%4@CrØ&6UQIשEd}huE {[oMЬuxN2jaQ͟řX@D(*N*Gr<#y71<]]Uwrp&4 t%ixJ5@Dd0 gb"/1DkʉТ5 dMhH 'b&t)6 uGE@H7wSd9aX(5R F&H-LLtNI D5!`Y6ΛxɖmQD"CL'PP:I%0T5 ƀw 5#(OA±t]$"VЙ圢ٖyt},MM04e7ƛp3\EN $J(r$34eTCW D#h9#`>u™inE#i?aI7qIƧX#7>7PP]na)$N2ER$!e9dY%^8eyUoV@B~&=-A녝+7.g ño/)Y-A" ai,^ Q p0ۅ X^aiXJPuې5U7 æ1Oz07.޻wN!fzL2A!H+#a8NN (7œLэlDzHiy(F9QZ$NRt&a`97'zg?x0|_p{[p09XGrN.p/`nO׽pJdyTcj85z[>~O_??H^ 0=ۖkX^]PEDI5iy"2$a_Ι!NGL:JZ6eh7N"Kъī}7?|? hAQD vjFPHg2l&/RT,t2Nt2ϤsbP{*r1<434?3>13;?54cWx[4Ùr##Ȓ" Fgvfyqanzzjrrjrjdwph`pdxdxhdtth쇯퍭._wiwskg٭յ3gwl/,̌ }z9p=zgGܻ~ڵkW.˲ ~V?XY[Z+++muye.kcc}kcŃkׯ߼y~ç>}O?~|/^<׳cpS(N=0 Mfu}em~ee}cumei F]CY_]ko^wpVy{>>|x!,'O/ޣ |O?{՛7o_}w W6aek0 Xmڕ͍͍͝=[ >~rL} |GG_|}O޿y[< k4C'z3Ks333s3 s ssɳ Z),:s⅋W^}[wϞv?}zr||O?|-k|?}S7fYC3potfnvY5ZN >;08004244869=|pvlg{6Woܸy۷ߺ~W_?}ū㓗'/xŋW/_9< P8ub8v0bY`ֽ>k[V ;N$erQ7h^S`م{;[]߻r{{WϬLM^^߽\oÍn|H^fy /P8^H0ܳ~ 3K˗mvƦ&&+̊apaɣ@Njz\V4&%HFlmtQ/F{*ibu4c!gx~7?]p` ^"J@glh$m1dեl*U6TE0 0?V13׶a|?O6OJ6D.{DkZN'E^*g iiz p,ͭG~7 aA+i```2 E ( N8} S G[.$$cWSklT Eo1 p=л17w{ 0~prH֊nDwn| 2\5f0  J<pÇoG1,wBƂ{ }~m`d@Jh(ש$ĹAd;Cx'bp:o2 y),Ė"V+.sS4(BeA+`:QhCUsocx(KV&`z, GÓ!u0 ŒnH.c Zr_+\\"(_YB2 r= <(}HE1B@hS~K|g:7d32s0*Ȫ2//_ϛإV޹{V:>scz5cG AHEd n_ʴMŠSB 3v?̍7V'j(?"gՋݣS+SP7׮%x 6l5Cq,Ay8}zXZ85L&R4r~#ie߾}yglXH><ݟq 2-vM,LM f;jֱ-P= ظdC,9TOɠ4JCDhEz2x@LGK {ϲI}k-@4uz|}RX;Ӳ(䁏{pk UHpp@Ypi]E7A!Bh@D1+L.V F!Ck>>}yqˈ?=7aHgڅwtBFq\>G|@ؐz->tGuy(6yȱhswVeqIYYPffu y>27~@{=!ih{)/cd$JÎm+ 1 KPHJ;_d *V00/2a/+ ȇ ${0C8 !Aq ߰% sP9Xo9X'[t(O3iXo!Rf8"PuR]aFMCp0"FR\Cˇ]y{ @)HZQOj*ӱdXVi$,.)50QHrnv?SnbI,Fּf ˎDf#@#7+yo<5- h<0K̥Z ֢TӗWq5 ˚k.-Ld$dA9"2$}Jutl8>K͘!I Uy~;DFIfaۛ ᄊAqk Mk/K[wH34gAs4ҤL(dS4b(cӚ knOSND1w*v40@cNIMK_Pp`A11 DBnaPS RvU]X@萈H2e h82 X2˜ FiN"%±__'1TY\E-Z|M;iovf>РQĂ U {kْ͆L 3x![Ș!)FW l[YiyC3쬻J$: P8J:(sGlIX=&L3Y\L;]b&ig("WOi0 dYOYPt,K,-X1h\ܪc?QlxRZWӿ<iTP:ID/V`Kቩwi pVLSa+4TBVP|%o>56X} шRQ=?= OpNDQ TYdNV8h'&gǕS '`}XPTr^]SE0q"jT' b1$`7镅Zl܅˯|, Ţ % vMuI ۭť7E#k@4˟ RE0,Ղ4'֜3w{h!%^qW\WCfgffDځ2>K!yZ\ 6}l2_)fRX4^'d(,X +|__ KL@=bx1ZfS`I}A}nt =3Jh R"u] 趟7DÀ5hT/8P1L4u;I"F:N,snq-a)0~S)kFB T4h(qލ_|/#v$Q' ئ Ѱ_SP^mխ@~MH;hHThDT28/&^l "?|}\ZgsX<'IE~**dM5:-nQ<"a(Krbj_$v,'JE7ձG_?-X, 5ʕR6HcB2D +la$"ZipH^XHtFN7j\&2T$DxW< 36^ug'?GPDD3VR,X$T"b@P)  D q`l&`5D0ǃL1,MVtgO?9naJMLB.bN^,EǣnT%QA4*d B"T ɋRI+L$G!+ɢ,BZׇgY I'&':=5@>j\'0O*oC 0 u U}5G @X% L,R$% 6"z|+w{Vj.Ύj%BQ+L% l $M3:qq\niRRuPHؙTȫT>f C#k>|TF igNN 6j`qJЭɬ%QU jݲ&N Dug$ >_ ֫D9U3x"Wq&|t.LJo^ܓ ӓc#}f^o3 *ZE/TDQq sI FRH5ZsRC5(>qq z8ݬ/GHoZ\Z7cLu/i%E$\BftBFcv\ȧuP2(  W'On=qAhNS.S\\(6@+B*ꑀ n 7y`xyaSD)=cb3[.3B6ȫ^ՒX?yv7^&PHP6[%AvXi׍D,oARAEǻG\n O%08IJ :[LQVCQ0Xaڋ߾uKW9 B ֮ RŹBpjm >CB$&gY[<2$, tzB9f7ddwykG޽ٳ޼qh/D{?>zǯOܸ<=> ^x ;h+OT< YW7TPk H 8 x?KDwnNQC"6T8;51{'^~g''_>;>y?;wҍwN@pij]HJ`i(3xBhmGR!y'=yw?>9zêֽg{+KsS ,[Tn LFD ꠪BG( 2HCD2X|bT8 2 秦FG=p|߿9yq31QHB\͠s>=6߬Cn'h߶}'\Š|Dme>5=6}tի}Ӈ7'}J##SSccC}8ɪ͏CfjPi&U`۹=@p9մdٙVm|˷_O BZje7WPLa1{frbd`SlTdKٙ|6-mMOLNLOύ`Go>_?ԱԽ;MeRXy-22s4?;`_QdPزtc81RtIRJ4-jޱ[}i-͏O-Lc&ZO>K n jIfHЇh&Jԩɳ*KI4 wz D2Yiu.b_8{vwk~hز,ovqjb KuŊJ_p %V8_dr,D :0?7VO&"!0&@i|O?{ZX]XYZP2ran%ah3!T2a/l.-΃@OM#P4Pt2 (H꽝3gvϞFgV'Aohg,u&PE &(YTdIX2FL2 "^ӓChRP82IJOgd3gwͥՕ`2n6>esCtIAoNvl\43+KU6blS >VhşꙛՅ9B7禖j$uSA'Q[k8QuS@چdpF\\/k"A2J jGŤBP@ ;/>z6'l]rw_;:3&!SR?b2;*a#~,؃ߕ P_6?=:z^̝s?K6[/?~ӻ7o]^%9: sX]]IB\0ߛON?| O\~6ÈJj;7;-R,?P[m\V i*'H.v ul ZEd:xuAD!z.7?O߼ե RER4kh42 cs,<#tUQʹ1 =vۭ _H x߶{@zX۝_/޿?]:/o>ࣂϧ@y[u5U qT:d|jzn2Q ^P%-a7Y;8?_?_;h?Mbr\7yzVl @(F/6Zj'iH&Ex:_Z _C!dt4U@4!) 91 gN^ʢ#\ORQ8Mc*m[5m#;t}pgAsYl>Kd.t||)kp\K' ѣ5MͰwOeWCrzli`tPk, MR 絃و&S8x:S?:Z L`D{rl<4+q e7P1:Fh˹5TӪ*k&jEk$YggZ>vϊ[g=ҹD6*HnvϜ;6&hF)FQU q#(e/:St YIYU4 )YAG!jdz(7.x|~uHQ0gw6u 5$#.KDrѷFm  Wʨ-Rީta#TIV,U19WZ߼y?' ;ӪeH0ƍg\pf?ʻ SS4ȁMd=,2BK , ^m`*I>ax^?.$ %ڍ '!pF <;IG hV{dw ?.PYvh }4/AOxb)V0S< [ۀ}D2C @$ D]8^.{U%]-+S  Ԁ # GIkfȾ]fH;d 9D`L<˜VuC^2u7q.\ bc\)cCȵf!sZpC`R~G+C]a:㑝)tœeSN1ݪ)BbcvzXڑtXJ -g:TPݰ? DzYE )yB:+UDpӂ(0T+"9EQ, ZUW&ܟ$ N! GKt"$C,xDl$`Xd3j,#BFYIò]+aN'hJ5axT8osh4V& Eڵ3E)15S `@qDMW%Ed8pad$f+R<+L$W[<8zCC,i4zaQݦ!a"$+Ϩ7_P.FzzDC:q,m> <(F'h,T2\4KC E0n9lxnbû]:B%S蹬nq^ӇNѐx=ġQO Obn&eG"dR-7`<"F)80.VPKK?e mq1P@008.npy}s$Iv&虡ȈȌZ!54ZkQ ]]=#v$gȣ g[.n]#Kvvv牚*?{!䯟>$?ȿ}W<{rOOx( 4qs[$G9@(D1,͐M4$)"˲ *("Rn^DLM3h*O,1._>lϣ0KG F,&p&a|3KӛkU=f9IAQ ($J, ϋŪvThĶ$eisXz|zjAo_J.l@$ai<^z 8s(D0 &  ߲,/Js< HY+ [hV c oݼzn?T ViOVS6K":DhN xRPE ,al#Y0^`ÂhiHqOk%G޿\|r~haJ,I3lXB4LC!S!f9C} f9-*UY$E% -<|'͵'>/7/>7' oDه ̑^b xfp `L5AȨT˹ $5H_tƍ>~ٛyo?<5?q,1%9YTIVtӈخؚc߽Bv2~&p|-cIg^`'Vn5/^ރ׿  +i"Dd{dx7kw^R(RXV+z^WKB._(B.ɥZVZ*dTԙ_\^Oόv^4uU`v$CrT22'H Trjfzf?3;۟LN&:V7VËOΟ;{GWx^$0iRc|}{9fwgo}gg`wogkF;wppk7{ܼyέ[7O~sx1Ż/`_W^y|߾3M] '^nw&wvmeoon%3Wvv?'No?'Oݽw}`_<gW?~_xo>/|3T7,?)W: kޕՕeUȕU0xmn+sw/\F[w޻/atx=yͫ/?|oW0HNH$jML >G^MNMBS3 kGGGGG'.\zN^}qc^}W/?{޼ׯ^ lˎ^O~"b1׏A,pD,sXd"sRZ< y|bj? [ܝ_]^^ps}ʭ{'.\z򵓓۫Sk6j"B_ DedM"' Q^S3a:ш4xtʅ[sQ@/7ܿhW côȵf@[A_\^R' %M !D}]( @%B #JU7bj54UR[ʫxbOB+ DRBI<Ba (P_04DCeai/B}~cXF`yN17t~"UͰcuc>/g0< sM E0.PD4TtYY%ImD ȒcZnfTZ ߍ帬#h*^;R,M! y![f8$0xD\u.Y{o?vڰJ,D ]H"J ͪ8l˥?@*pdP2+%+ .C#=y s&"Dƨ[XDƒln_kӢ+,oQX5!3Xkؽj"GT|W Z#n4 D2Q?/d+G{>olx4;RX|tC) 'qZ"t*So0VueIUU C!\L@QJRx02 xdQMv5\`UKzN,/^<}%f*_d|ƂFdL b6G'S+KkZќO xytH'LX5 +}h w*(C^Hh$;(z"WꌵJsGK*SG2ZH΃EBKuZV'd9rt;]Bs"*ŧJ~sҭWG&wFF!Xp[N^_6< Ƹ<T%iC40T `iWUQ"yMfѭdwlau(ɗB2VdkXp",7jk[;GBūu/na+w\)N!\W`"AM!02<۴5XoEhgT-95iB*nl>>&+7/\ߛhJK2L|dg*+粐r~p5 _A12e.!;kKIی:VkBkNOԮV$=YG>|ݛ;v/m<֍  {k~nѓ2P 4̠0GE,6a$Q‘ rYKyr2݉"=/ uv&7 ۳걽!e'!Kɓ[W>"k#S/՚,Dz&sS !˳3A`pn*Kt.|!jo^=-^kGO_H*-3ZZKw3{7FAs-I%gPe9ALG3~c'F9=[1ltiz~u!#)cdz#_(dxv_oP\>JK{] bKG! 0yҎ5VyXq]Mbj S$aJ6?u7G3PIXXl_)Կj 6B@v "2$D 4%KSSyN&MEqK0]0҃fBVu% "ϫj.o~t|c&bu <(fI~y#N-shWb.b!< l30$c@4 %Ve'/] Í!X}ÅA{u e|7=AKeE;PVDr!KI+ːġ )[_FU( [⩨륢2 ӘLoς` F`OP`~P(4'*!SMfL27 \X ۑNZ>Pt3Nw/^HTB9xӤUQ!LDk-r|X!dN:49Z\>ez<#el;{.}W?B!E(E0$f4C2ekR.q٥UUkZDeFbDATǒhM Z27D.F %1!NULS(|mAD`M bP`06 *8S_X3 tF 1T,b! 1k堔HR|4TK@HYF/YWAhW!Y4D.I%L(%I9sb2HDE52^Dܹ_zs(: ]u41gegL\qa0Fj;T%=ǦL ,M$FWV 0+__ e \&Nı40 T74li/MĽy0N 0n^լWGҩ&2W'*41R+!()tptG_=x9_V+l.}]7^̧R~D!US9R`X$nhƛ0j31!B GtV) "V_ѦVчׯ%SBo(WJD"WtTFh("Ryf8 thKi>>mSJdz1G…55BBG"u+{/WIx3:5jT|cz*J2 ;GApt8`jNw{T>7yq $%J+[1SW{[.1xU.rdsݡrs#؃ h8[P"?:>Ql-xd0"4"(Gss;{OyCtVǛh452l +1b0P9$nC R1 3\D/e n4f 3! %V#^}N,ɑPZƻΨ:m HcAg:j vuwleBd#g$ɤi_,3%q - f/_nEI9m9ɉX9TVieF(32OYb0` @`bko y?$Sq]u ' ʼnV42V/f7ك.&'f&zP9?]6)Sdߠq PPq0@ !L2R璉l"t15m1O\YRlD7 TQ=>==1TKZ}˘v:SlTO3im?i 3`w$LDSl5Nl"'h,J*<(7Th)aJ2PR]w:ZN%sr!ӵIlb*vۢ;xwF$i8@sN'WJ L&K'?%9,؟+|5@Bjrz@œj>[%"|ceҩ|{b8"8 I[Ľ'x Gw 4Q/˩\>dLWbX2 ?b&B5#.Rî Kf1[[fcRM̬,>Cg[j0 >C#oENuCv =&A qR!@t.$(ݨJ (UnT ]ӹL6ڶT'qWl3zteng{$적}C>`$IEW2i)ƳH"P%D%nΧQ/9\:uXU)g2l6"Ńgor֛۪疗&B>[N$>CX#I,(M#F9+b!r (!i7dP#N,[(UK //ol.JѥqwLiV!d`ol_,(ă1d7+Zea:l4Jx4!:^~xû/_ϡF}txxmxu<5z"gh\))Tx{~t۬Ԁ &=ARbd5ǒPU}~Oë[w=|`5G'Gg@x4qu֢gf@3L4111$mK`ᑱNgZh_3+JB#gfljAi%C@M  D+^dv,C-\j;kꭡfCɩ铓kK4?Sjހ(Gd=E #ý^ Z)߄`UO4ɞsRRo ϭTJ!4:ȗˍ2hvա F:(blb>aK,檜i4޷+NOMtڐet4 tD!蚝Ηѱã剴2N.Pv 1!(tp$DW+IJi|RH,\O`iCrt,,3LPkO.\89\\C\g9 FF!-& Y"^:41 $ +oeavv #]RXF/ʒ b\yh;>⅋3hVZ3<ܞB͡xr2j*`cEKdA,K!-˶myYxҬ abjjbrbtxB 3Pdɘ1'.OXktm%dEGb !.MM0ʧ]fE>fWg3V*42>"˨|5:s 'k 0]w{rj, ]gK"^dŐ3 |/L!σ,-TxAQ&Vgga`1XT`H$`-I:F g6'&[G]\[yR7kX0YPপ骥:,E4یe:S/Nn./,..bCL$yc>h^6 mT?[^[޹G͛xxtq{y,fS}L*ȁ*bO`uc}meq^<biB)dJOo_1*vGv77WFi@|-Pˋ@~#X bb%%ZًގG~a NTQLK"MbK `Ng7RpP|%d'SȠh#t+4 J : }ݗxg5,B'C4}bOQ,;J58iCb@:LgScj rdp;X9!'ە^߾_^?Ye⃷0A^TY44KPA3 !7]-Ad3t2F2gO1sy$Bx(ş͟ͻ^n\_2^ z¶U<ԸO17xA2,j8q RSl:N`x2TJR0tG ޏb9N_p?|̓s݀Y|6 ͟%>IВmeZӁIئr ҩLxHg4ЎKA&ų"4h}Vwow~x `<& 0 Mt0~RxT R9KFd2TϏAO> M*_?~8( -sOR I f0M0ni* $A< 괏Vl,,Ly|<\5#"_g8YPӜ(CH?Ѓ6UQM3 ^p>x=?KjٞZ[Y_A% _E9c_Ɏe;!,ϜAyhpC4E-'b_.W0y~ =KTjͭ8.<Y}-{RA#ZvҀ g]@m4D #"˒+$0H:u4f$Ɇ@knZv=$MA-{ܔHNƽDXє^l8DITU|,YVbϯYh#W~fTn:[k&n,Ed.*jGtvV(Y7,Mt a麬ʼH𞪨2Dg5w_wl}Q!1b<YBэ<~v@趕(Y:Lǩ^GG?ȅE KH`/)Z) "! X$M`6YϞ=xGݼ~\:-&t(TIsל,PP$pA@<,։:XcB1ıā%7xkdur_}|^ߞ<MYSW5W /4R|X (BArA\K2MF`t@F)3)|f:twN/_^xvZ7׫M+$)rrɆE _Jęa!BKj,<.dۭKa+O{ }|ΕhVO@(n"=4OӪLs* ܐdXA$48YEhT,'S>/g}ͫǗ-Y(r#c9 *&?38CC*3D;S[&p6c]q2|&ZaG1 #?|߼<*A6)™j52fiV_5Dd0I\>a4ޢ'Ra`genEg#D(EW˗]I%iR$ /Sj/l(I U`yn#|,!ؽP9|@pz>lfb*+$EGcVUׁ43 -ߛ]Y6UN>(“P;t&<`w)%LG&HgapK˖뽃n:t)Z`{cE^2,eC<<04t]pAepfX(46T`l§ypˈ!q'f%0Y7(4+0$G3TU1T!9K{-Evu6ʈ \&(|8iZtv"p8W D% kD%#@Pˤ]\~Ե 2I9&s2ؚV8Q"i"D#͛,H 7Cx\2hX`/5D`f/sT[])Bc@"^<(dJ|Bܛ]ol<džY| <8g;*-KX;>?pO+(_v0񳐔\Lh"pMc,R)K;=.0 J"#&wˤ;y0 6)O"/K R >@8B~_P :[aQ6"5MQ8(М ?Cb[Hd8>nD x:L%+u 1 1 1 #a@IDATxW%I&fڵ2dR-f8;;, D>avU)"#Jf/XzȬ~1ƍ-L/~V [;w'ncK4y(_~@$.&Yw{ړwݘխur;|d7[{C">#L:Vs:2Cb2gTFFr]wj:m#Q-oOF9(om\jg]4/>'_lbnMN^w;_/!k~Cg|pĶ|FpqH{:[["`6ThntP|ziBF JqG#Y^,+YU9c_.=<ߴjWjfb<5«KdO[vLؿhQU_5셧"̉CrJ5];~g8&kHv9k*V{ؐ,"/4}]Pɨ~9Oa޻$PHwKԍ1ٝrz Sa ,$pdZ?һ&)՞`wfg~$7 13N4U?ޙo$ U׍+a_eb{>׽lqP=z2Yo{EݼIeΘ}p:ZfkG'MGvۉl!BB3̸^uz%h|>(%45tJt~C4E:I @3'CP㠓9XD2fɅ/]7 r?;:~kmKWdfM>̥"&kFܙnWEc}H)qKQ-Vh7cC8c8}!x2N© GRO(<^S1,SFu܊Qk~ɸ,6BC q7 #ܷ[\}Ka)K/*f: IB0FM٣@^Je凰gpӟ4/%|Gy?O9(Yt I34vclX'nV/ =pCf5bMѣP&V^gjFJr<<>Nj eJxط4˧Vqrm&h':]JD7i(ebѩzخ?k.1Et/Y^z&A-mExrG?R1RK hyE[2<ܣL5Ggv6G1 ԸDG+O #*ؔ5 e&ԃ>ݩR4it 0ubyi#wq.FόY7^M oiGIy jP{gA#&4\nn~_Lo}|tX|oJߤa 8iF8X}7lEY||ZUF]m!\'ڋ631s~h$ښ?]?`~«'*W Z1؄w]8VJyG^^]u)jԭv¯l,uh Z¶'c«fQ~2KPf#'U1.{"S9QW1aH7cäHd砨$2bpњa':bzRۘ`׎}IMEj!lzGe,zV^z>LOHcӕN~?NnL56[LY7D\NIsķE[?57hfsK&y9zMĨSAt{0AE7~ rOnlaWV%ŋAU,O%WUĎeI e"j3*jg+1]e3X;#M2n|n @:ԉx̷2,p֍VWW>aΰLmY^#K ZbS 6n 7 9xd1z5Q'l",S`F<{ Ē)cvq$D@kf)`ZP^e*7ƌ:}/m25N;XuC012yvAs4r)!~*$:/ǻS/qqDtٹd6TUQO:)|[?B&8OA?6R#NȌ=3#3SiL**/ƥ˷!꾹YYc1Zx5-&9ѩ.Up8d>\f7?M݊};v( BI㰋ZtDpJc"0rSrR> =**hn&~Uݸjڮ!;RXL*Ym800ސg1hyoZ=v82].܃t1'Цs\)w/,uC\Q=Bd痧] D5&a ?[h|Y(A43BlJ}d1tE9<=f $KLբ:JF,JG 3?鏺@>[E_2ڙg d2鵮w/; OU'_) W'FQ\֓wSs:rʤFX/B8<6=;MRP5޹,䇇o:âʚ2&]("8Nm#ި*5Gj>p6El*ܢ,bPj$ޓA7IkvzM? K}'2@@ T$?Ly-f(=%j>ɽ9:2a#ʲS FSbP(`K;xBgoM%ɁlEd m*sSG[#UI-]^YK?`I/j]FOR-]Dݍ6KSԋ` a_g#7Q. )[!{2=n.~">4☲D`f>sMCwa{txՠoPnt lTg{wa'Ik_Wss4DaVIX*}w+S)UxzMliX<;Ty?-W[kT$4Mb hj& y)YG2I[C.r4'C;G6]@%/9+ F3z|{T_ǹ6:Fc"V4s[pvkz-ol sBdo 7ud\& NՒOMkcP-.ۥ͉hE@@$͐[!%٣NwE83bF iOLTNK\|iZ!xG P ̀n>#mLJT|!.Hu~w~4y)]~&"YmOM0oMr@=X5GI,#򸰑vb$$\T +J1bȨEgA1U871osttփմKbCZTXEdD/aiT\{ِg]F8ؐ| ^cwS.2MCw˵B~- _rQ~N n}g,q7YZmYCkJ3~~POU >̿k乌bV_f1|.~ /È$ Ubng OC3tMBͲtҙ^9kΞY/!ԃ.&̡xгF拹[!C`ft9PzOGxa2ҺxbO 퍛 %a1^a~d_uLm .N֯U\a٢O5^ jyyuTCe֎OpUA_nc@>O9~WT_2m +^0LǩTӔՎOBu24nIC䶄'G*41 5 mYJ\hzGԟ8YqsiY2oB3m"!<ׄ)YF]6BȶL%}ʰ35mA Ӌ%?Ʃo` 4=A/&7*sF4k>xƷb֜չ *f3jP)U`B*@r9- ηA*]Aga:%ujm۝̯}[u)cL p:=AD/\uۍ2To®%9W?m\{?ԛF݄F!ݫPw`4ӓ'qy2Lu58]t Mܛ+ jF$,xfQYl8q. UmR7& P.wI_E#quLJWTd75߽n:뎔嬇# QMlzzu }hfr:QْPO?]og,vWckSqU^{'[V,`<+oSɛ6^0hK^C3̒еR>f|!N5ceߣر_'y{Nsg&U7x <4ѯ>IظGwjM(?T Cs]Vׁ%A?(?wgζa6{\Œ35K 1 Fsh#OrA}]|0kI𐧓Rt.&?u?󏎫sR`<~M4P2zd+K_v]}(<~N. L:"]S=ql꽺jk?/Y Ah Z[s|siiO^Gw}gRd] T385ΪF 2v$#j=984 kHsg#b,A~Xe*l T^6"Ơ@VʅA7_󗆙dM!}-CA Z)9N8}#Q,t4F4썉$pj䥝RrFmUo \ɢT.1sPHbz=~R.&1A]a'_AF Ksa@[Փm 7ݵ#//q(O#]qq#~}Iϝ!gM[pGN* 8__xX d?(+R ƗX4}n`"-|RRIჿGM`;? /JSu6ؗA6[T1͎wB5U7CK. ,9 LCzYm[R+UoR}۔~t߻fzrZt-xנD%02a-wSP~X^lHzwcɇ[Oh*[%M3ͺ{ |-#%Pkb8y\cY*`P@W`^7 C0m}PgvRG >B#Y\fѣJqU:zmAq\ '0R~c\NT8MW^d?w8SIM$ZR$ :NNA :ek?t (K&`4 ۍQdUxqWv׫,oMMt V8pк5Kޠ7![?Hf=[EIj5üa?> a_d!z%g5ؕ]ȒCW2&L[{A0Hoܑg7ؙsxj44-X?5b1Jxh֌Wлjj-[?SĢ1in ~`ZB-VvBDV0,FAMx*kKS֣gMz:Qo.B4K,_ڳmw6~(-8Q  oP"v0b1NeDXERHĽD)x"\De {頪^C6>]XF،dK#Rl6 6KAfK nΗNWjSAn SIX` yCZ/T@Ǝ<~M,|۩xPD$\.P]g@g"l#eHxEJu5`9Wd 3ed"NOP?\nÈd`F$ FzM4RݜFz/tWxX5 W0 R BoDO.@ζ:>?xh`IS^G*,DZ[!@b 'cb;;vBⴎYHY_ɨA&S,m-B1#37]v#'R[;`!V4ɐTxv3-a=aI'A/>JXHUtG쮂"*`:f\`4iH l@n8M0o-x <^}Ko]S$IRm6UY5WPS·G>(-&ZcoM~WdCt+=#/[5]e hmifxw*d 0u& uhq>^;h*D$‡I_rtcHO\b1<#e9 z^bΜ6|FxQۦgSv8YNƧu H{ fH.95)0]] -E=#jfV Z_1BWZ0` ABo_~֘aK>Y`,pz$d^|P{QwrsODb4~ORolAwDDO_(;LZk T@4[A/MBZ4W:$gfP 4|MȽRq~֧+&_At$r=6[.~KVlKHf Фufo_i 1Pf`a ;T%91K][+*k&-AԱ47l FC/xKrK`LƋ3=3s6AHw7~ku<3+}rߴ af!eױ EX޻ ,[Z:_<\BX# z1G#"xYʯr:^b13\LXrIxߤzhios B7CݼU1 Y[)y[`\|!3l4<Lb@WvY4t; u[<^lSӭE>rˊR!W` ϛ杦e6䗟$"d2p-eÁB0؃"Q(9/d7Gɺ .C4 {E(*mհ~>~Ɇg|#M1@ W~_ш6ITr3IS;GPoV3#M(z~!Qb 3JWÏLo l_ %75rȓܪÐx~-vp0~N*_HՕ^Qud*IX`h4֤nH`z@9uֿh̴Y6C0׏=۽+ gV&ݼ>~DЮVK[ sxq:} n&OL0_;ᑝBFH[FSXB"LdڣդV8.M&jOB%;j& G߲49&>?L dm]RD+ @t/%fۓ0!'6೓vD׮\n׸Pɲ6ٙ~W&?F|$5W{C2fp~]K-WH`z+H FT~Sz\6 #|]2dgX]U b{: I,GTa|u/1D-+z _jAlk>sza /w^vzXOOa>AcIJL`"2CA@uALNw¹#wWt٥r8SFq1A0.Ld2ްኔ`ln5΢-J6>"e[6U-`˦0s}=7ҋe?lÑCstc5kw@ &ԏ_5)"%"uJ"$ yWl g׶'Hƶ0!tEEcLJNXː-B֖Z2;+A iI/R=| uǛyVw_F^n$lu="ra,ý|'ݼ j=D;WMwӵF%a%]`:hП0<NF!lp1iW,JCA bKQͪcWfAMo\7l:$*0S!^a1&L x?ULN^ f Wnro4V m؜C WS%aA2a겻yV #vr9c!X%4(L>_O4 &ʾ]b#>~K+0&”8wg< .*' |#_f ;D PY! q{BqvG jiKB1|^[b#Ħf7 SE9_ 실o;?t1pҢoq9Y<@6ROo"[񳷨jw gLuwˋpF"b_|~ ^P@D2CÅZ%gJavh"]-W;SzNQ2fH&?N:by1g5 oSӐv+o'0K@LkΙjp~=U;5~?y\sVσpnNXOO;y˰ʂrû yqJ19*VJUqS` YuƐ Mg]6(zL`RӘݮM]t .} K Į5{&ɯv>^Fu,4 &ņq(:af 2<&¥]Ǥn&?گ*Wgo7%]j /ނ !DO-EXFv[M,VZxAjQ iyF8"񮽴.(?mm &b@6@#59FĎ^/Kp'7v͸(i1qFrqJ#*j,=.}eh(sQX!񆊠8$g ve˓~{onf T9{kzVgyVn7{Vh(aM7pAPɠ]CXoIV:^߹4|>"ϒlhP\O;鵏(ފh.4lj{( t" FN XRޣlN}}C1Hj1⨠5 ֬-WeIvhk[mfĘ= ߕd-Dm_4 wUe1tbYyMJ }s|&u'la@ JEu V_EjkQ6>;J&"s 9`a|Ġ HXlT%+jծٍ{ Նssb( mThT(Fϡ4o׳/qťyE`9R?/3||}1^=M)Ii08@P B 靕&m 89!PvԶqn`]L?hWEƯڦf\2G[oAyK}tޡp6@'Uu_+Ld@Ids㸵F'Վ?>C"nuKa PkJ>GDANl-FG|-*G-#OEGÐVELK=cDBmOY ԰ 3+GX9 +̖{]svt X:eڛYКb (@T+Aʼ^}ތo'/slrܕMidˮ˙e`uzHU p,14,uY$¶pSܐdI2s]:`$'a4O_2nTGC+2D uRƉlK}=w@,PbW8B¾ļN)v6dFwl9uwd$q!=T*U,3syh3@=j-6ַ%֖ekdX+jh󬏪k3NbO!U㺹E=dn[k)qYxIlz"Aٔq3#P>?3n4$3i,&6Gt,~y(Avp ӉhsTt/֟1V)@0/um%}ew<Ёm|AРķS^8fbU_Ke6cyfuo$2:c`9]OQr4(=fxZAO vVy9~ Jk̪6i+ŵWR[M~p4=_"qx T餰ZfKn;"ۘśkU-w:iΛt}^͚p&KI}|L}T\73 %I:\$}:3ad4LR32$ Ja|fcg^-RY(3c6WZ'>}8/QElTYC֘'j_oH%ϩʒ"}R\I&n3dnh"nsn3l1̼s[#eOkqą{1)YCO ,au9R$If&u5GXv?k7}?ņ[QX=Bz"hѹ;"l4יijVS,xwUmDq4ÅVOQi^QQ/8k{F0__mKvH[g)hK@Ɋ=zӃRFl%=HsY٩@{bb}N-'%Mkg! Yw̆$9_Zyumad3b2?R6yՋw4h5MAt1P/i,*GQ*Es܎ӎԈZ:)e3̑W~+b̆;f3K1E6v`HJ ˜=c<5vr͎~+(3c4M:d?j,03jYU ׊$&YE̺ܬ9fV|NԢa{H;r>cZZYͫN\=p&H!2@Z05 w$ձx3C|2؝,Lnd!4UU*giong'чc`tzT }C&RLAڴ6_\P|$13_٫NqstXej[lOs`MCHG@_ڱf@n&5"W )+0n=yڈmN w>Q2&Vu^h>n`Yf_ ^*ZYgX1DU3 gp!P?~#7,f$j8 ^("0Xr[1ku+pQˮV饱e}N/ejkc)]39M2u4K0SAv% PA;~؈(] PKVe ;挦|ԏN…rJ| F=1g/1g3@VGu|'.IN`&70EB\i' `Hm2D1 6}I:c2 yVj }u]f\7s UI7)E~ʦ~V@LJsʪoq;Ri{${{IbŘP"Bc1G}0yXotB-Ø)2Xf.~f+vu:&% $SExSAxApq1zΏXq@7VTn<@ċ"~&@sSSTŠ_@SjX5ѐ.`5}}Ѻjn.=U"c#)cwoJ[kJ;oaJvpG_RnN^;?A>sGAeM$Vz{K2{ bN < e9W:_x@nx$uBzɼ@9foc`#ᩕ'`'2b eX4CO$v.Bٶ?ɶ&a.ԧfWH5V4[٥s9Bˁ:KA!E%4r"Vࡶ5IqjwzQ.pǔ_,q^޼XnκN/8*V鞀wδb u\9׷w!Gp_7LղjmETl!@wTߕ+)f,/۸.hxZ8ќh^YZ8V9zԁV!Yҥ~@6ryzHi7oE0BT+]Ĩ̼2h(G^s nJ2Ӏ@y!SCPYkNK08_85LVJuTAt5Fl ThԭR <%i+$J$^|qڱ_Hϊ)Ja \#583y!xAXW6VeWٰ ]{;cX?yщ/l˲v; ?H$k#P1 :{oӘrd{9a?V/(ҙx.r bFC'Jㄨjp٨QKTbq/CZ@_}Xո}U;V(k&bL{n2xm ({{b2|=R> f@g6o  C7-'1"+s{s^kq "ڀe 0r޸|k´^{@c.ӋiFAigAp8<],A7fǶ:aɏö^vj%`L.|g_\qn Y:=sii)Bqubh-K?ْ֛=bS'$b(q4=Db":ŐoW#RZx5>d&,Eʗ4Ac ؔqDP91̬A/7 kR 8,?zUG !k,kuXX39]UK[ Qu-Vp>_ 3FzMsqV+e$" 5"Cb2CJ@9 ö^$ir^9Ӎ쉶Tgsz^i_?Pk$߼ gK0(~hn,1e۴37[7#nI߸{5ߡ_Q#UK-N񛴞7gBh5Lxyot)jnTB`lj%z>F?F+]YZ;Rl#iy/cCk|U5:EjvFm7$VϦGpzl/UMWd/6a2K9(WA"+jAm*'`A h,>u sѥ*lX; $p6E^^:.8ydgzw+֐/Q_s`4uE'F"IGǏ4iSHwfBUh%?']Wmo/_-3eaX'j_h3b ouU7C1fxjz $/XĹקe3Y#%KUWAn.Aέx8=T G nJDFo7S=f7ܖل7fu՞9'Vy.4w~]1#U3]G Rۭ4|HDԂ >2/_G&gQzn:R/3NN3}ǟ4EDyݤxPߠ= RP)"8s`')DŽaް#f89L8S磸'-@ݨOfQXDX 0U:sUxd~c+ɥP&tOir4z{>n8#_i _w'_ʅyu3,&5 22+B UlZ#T_2ş+;oiab gR˲P|Nh 4]ci2d' *|z#P(\7w(s3O1| F\Y7\~u(V$@|=3s$kK$͉IVQ2Pͼy̱Ʒ5[8Bg#6Az0;9k!v&sz?7se܇`O'/pqys]%agDHԋG (CԠь-#OI tdE[䫯.*ۥg4Xݹa? VB)uVC8C4s.3ee%3݆Q#倊%A2Gd,TI0z4׆03D/ յ5$H½@o ]b"XI%B.R IA/ޒD{d"Els)RʢbMgC +Vk,ۀ%F&QݍSRsyncXn* w$&g]9yJ[VW.o?}~wPE~$>3AwԟrSf#ҩ LYεX%;:Y5=v_L>p;"ȣF&SGE7ZvO[dQ_5kAΡG.]6qG@h>TR:)\=3>~-}%܍ް,nN(<md MGgnJsm91#̶ ElLY`pw6qÑF+M?0YN58R4c-hɘ0zv^ P^~NO(\Ш*I%Z߼aF,KVAeؑ ~L&u?_|*4ab)U-}/$ UA(hSr鳮pʨPH Du┱y]wa؊$~ D e߾~2Ir< [jeo+uO CΔAah8\ @,v'kopmd2.G,w$-ki$wVBn핫a_-^-!y{iݵN{$Шa]էRiIh~nКD [Εt('rUdvaNCNX1@SVSoN8$ird/[GG؝!.g?3ښabr_K < ~6,=apqmH(XM,W [ +b/x|eya@c;juzD}TW).x1uh/]I~L3>~z7mJLE=gPB <8U3HWϩ4~(OU/b)! '͘M˗H5D <%Wݚ#k\,+,w[Е!L ^DH^=Qk~z cJLx<^ZFzaTOU n[db i%uBⰿ? ) 鴙APr@}WOjJcؓTUn<=*gU[ė]ҵ> -zMgNf7gL("·}', QյUI& jNh+p.& )m1%,5ܦs_ W.4}krع)>ㆀwdHƭFX>[8#~/ѰNL2 br6_zoGH+fX ?!OHlelSkьuـ&#ؕ[FY6`C+Eى*drp HOBLM׋~Lx|lsDYf1X}1򂶦fգxdT6vݽSS/h0^"$ԧD$mӄRIKD!Ɇ1ܶ$23UgXrFq`u8)1ܽm.%VxZ+r.\j5E1|n_jw^d =_e4"_>'&݃qElX_Yƞ77O@5Z8'b?~rSteÊXPp &1SPn%_]j^i–e-iOt\l)0 C2y٪ Ӳ窙!lf7xD$(R$!/$l([n*?#*Y` LfЍڱyqs|c40$%4=msB4c]3. 8{ X}:'Bծ[>5$ 56 sBXRH;|8ȸyAQ*dGT+si#cZؘH :Q;80Rrc֭A:vHt×xUIu0L~H9M8ҴiGQſ,CIņ}iׄtdbr-O/8_*҈P0 $@?U"K5|ug/6cZQ^Z.dCnc9EKb@{|ɬ^oKNFw8h[_gq2cfD*)#t-BVH 3f޺|x:Iߵdߔ.U&tE"/sTADh fbp`j[^ a)Fp* 81zmfa4Oi$fO{+#wBMO` ;]-q\sb_,7x;=- Vc )Q Avz˫:y .2^vzֺ<޺Fwb8W@O?* YrE//\pllGu%;$^{ ǭzsQI~YW<̙D# 9/|̿))rZt]E2P$7F@ 6FdYVPY îD\=^@!ϰih5\@/PATpI ]ܷ!U (hB 潳XqCJ,~SMY2452I]^B#|C6]9d rdO4kEBЫ~<;G߯60IT٤4lwfuM$khB9 Kmt j>/0Ĩ{ #% k{+b}{g }oC(|{of_ReۘT?|=XG,g.S]R~#l.)& DneH뛹vEy\kKKPDn= W k[ n=~铆zm#pF \kJc$KBƍy0{C Sa`{> &ܨt .0+[ ި`xTf{Lܙ%?K5_!=2~LQpTY"qcAg isX΅p".0 @($࿄ũ.#Z8fxm_q@ڙa`ߙ5r_ ΄$e"ȳtڧ}l|n^L{]hMƲWަ^ڸ]L`.tJMZ*h3Z{Pk CT-넄 X]K.n_ef+2D5*A'6Fӑ{cM 0Ү:Y[b ہJA=,Py^H*fF/} YE=xv5e7uK2 ߭*8הgzmb66h`N#R V;{O?SN2/fm. |$qBs_ L@49xPۘ%m 7 }P>yypLU 5^^jE&1|loنyL cw*ѺUU[{ʍk+vU,lϤS*l0T1Zgg;.tvnN9 -yhfTpWO:KʉYR,XZR2lq*9!ʻ =cϻWw{A!YTȽ22iU1 6ezﺨLj bq)wU>(ccCsDKܫ;VşU 9KaYz e+Qd͚0t2)}hMcQގn.kt`ύlh m.!!Y9mP/^Wsd/]p[ 2"tG^b%mBžgP0!*$dVgQk5ۖNUvcl aTO ZIҦK[}8֝1RF~K'@PC \ H%x|v7(N/'9(FyS{j]eU0he^CHHՉP!;7֬Kl]Wk.0^Jyٌ@ZHPˮ,JB\@ˑHeH%"8^xf Gv[PtrD]_O~p1ctgr߈r.w*ˁ#3Sĉq`v.5V^$ZSƤN_BZ$i\4aÞ#"'3#34_[`|$ƺd 0dʇ1# %眐'p#2ͫbfe)6X.02}d 18~NvT'؜bu$ʀ' СOVM vS_Gjbf. &ѝEKY,Z8VN'wD Y᎚+yP0cM0cqVo`~P#Ue=)6־$հ dQ5N饔N n"(ڃQۮyQY`8_OLƑUr(i>I_JaGh*5,Ghe3srv L/_>y(q;٣@Z6]6;1%$|W(2VcE^G7ߗ7vлuzLkj[ҺVr KUS<5,ngZ=z1u+Sc5guEԮA>hK]螿$TJh -Y &A|V]x 訮Q I#XE9EZ8dJP#U8`7$*Uբga{{R@-N`]%4`3f[ʿm2\\*V!k}EœOp&e5Qz4t8:bPYY\-XfSK+-EKVU_2uuM9"-\/fQL]'ح_1@оڲOU:azƃTN )g&Pf~<@vU:Vsd\No^Co)6 ?M,&q\>K:V+byh!2H_)fs-{gnB(ȄOh01am['W}E@Vׇ ݨkM1`!M cNɧzOC$cquX.´!llO12j^Q;|)WW:ʑϬ yG"XyL#j^[R~^YVl>?IYlxט*ٮ&&6O6AC3]J?oF$ٚHȞx¯*vN77Z|t<46Y{xOʯ*߱r!=:ۛGe:~+\ї?358XI?, ~rZJXW60+:ݼ7{RQ kCQV ˧zyjMRAwj7Tkӆxd=Loj mh3 vLL2ElxwlS'=Ful R(ԳP8~c&'o{e_ԭ5FM>ݺM;Z}ězo쏈DQ(:6sNFGלn*!8l!i%J~?q/p:IWU}WVNeYy}1#޴Z<-J٨ j~ T4QrnC]TEY{ R%6߳BC Ƿ4REeJ|d{k1KTd̤ RrͰnk[\,"~URUhR_ȄE8 fMeháNI{v8-j#T VANT>#t)G'EN4W#83{`@OX>4ـbqV6ŲJ?,bkTa?}(C68-Ce],*mN9zOKpy33eMEv7.\^Z]f=]9 7$XWs!ފ2,#!~*{Qqo1Y ]s6_c~?,ڇE,_cD%h%v%cB2"z\+0|C<=SRU/>X#BK*D$d5i[:M.qG5Bl'jNJkAGO蠇1:3B<( ϵlDSS39Ik.̬ i˪=C懳t, n\϶\wP?8ariJc5րgu$Udz[VT>ҕe>s)=LLG|Lz P2||K϶D aWxԻe2' k4sQc{O:àK. AH^9_&S80Cs}-=YK4 "cq8{=,#ۻIL(Cqϲ}8fgqBJW#تzuOg9JnNSY)G"b^U@n 4?L4_jd"1 IH a76Nc?5we횸# 0:@GZކGpס} :F[wqUADcySUNhc'(V{I6z[EJχј1No珈}T<8 YT Fdg%iIj0˫zѶL-/?L9G $bҝ#umܬ-UW푦srSpn cS3ۏǛw;ć ԅ=L)e\n%u ) nVJwSg[d(ҧAUy {̚7?Yf}ݒW$O9edӟMUqK˨k2ˉ=OZOF)`+eX 64ǡɔ[kQF#t =\t.a>j[JS˨Pσf{l,蒻QJ~S$L2L3SwWx*5w PӀWBv&;}Υ>]:n:LI$֪~~\`;x R#kߐChE@IDATG~s g~cu}|%(^wrIWх,}kVf}-:$0os rLTP[%/sE/-$W髢A)T7mߋ}R3_I nչo KCK&ZwI;-)4ܪr$m_ͯSCגxKO )IZGE]rkW;F>e O7jt},*y1҇8Pqq/GSxFtWVv:cF@=H uU P9jn?ڙI+ɚم&#}Uu|hFF$ ܍ BCۦ>UXwfxs}_y֒ E3 [u1VJV9nAXwM$9Ɇ41 ,?p%?}f~cD9=Pezs,OoO]{"|leKߧe:Yb7H zipX3CwiHLH9⡝]7jUIT~wR-!wzb|#4ag\' HRWCStԏ!sv!3"5"+Q!-`!7ّcnq$ұAݎ1׆_ #f)RzԞEu~8aэ$9z!.h94$Nn%n%.{^CABVH1 kg0V\d5'Hoוk&>M܋@c8J(;AO(ւ;_ S`V<\ %ꏸ`lDC-fÇqJ* a'D'"{iw[*oU0|`ӎ(-872̪}\O#/(F1\qr&uLFf2yK d|!"- Zf"Bhɉ7F'T0! ^ˎ~"ԡqԭB|P$tޯ-<xQ𻝣YnJgE! kB 6 5mIע)]7O{4(eܥPA3l$,H/XWv4Sft&Y>X9C`=WIS< &anure [ /xr`(\Z+9RCDvO+&CU~{3-3zΞHaD@*}N߼#qlm.RdA/( 逡~!Sѭ}RJ(Ō!& mDM.X}.9-]v%"-8/2 vb(_uky~ʀ=4.XT{%4n~_ C֚Uz/;>1P{צ7샭jwsx q)ʣp8ojCmtXj4Hㆽ `)Njn s!@n#니NTFby;jՊ zN6!o%@ڄ lHο)[K9m1ↇ&=)Y[ 4I9YМv'\}6b\݌Z[>|3`"xgCw;b0NKx8#X߭{mv/rl}OtRsLE -ڴ1kb/B(ha#U Jᡞ}Em1M!)֙Y|e'rbsx]ٌU1w׵\:ܑb.y;kGwnNMA %'sԗNGY?6Qt}Nwާ  W~wD~7MCL+g5GIu͚̯HY "C۫`T)%io^~dxRė8VIՀEC1p[U%F 47I46B֙2;KlPjrbtw+a-H/nRxr[ͽNHz4$M^x _O>Sg_2IQ Ze!%uOhFƝKzpު/!øpb?L$wfGnq<)9?֙FJ?m¼Iʛqu,'z+֛+z$Kt D{;Ҹ춲/byD/%$]Aܴ3x_=WPK⸤VIr'rw.s)]+ ںw@57bg7( a GAS!s3\zUz،Z U&$[r4l @ʨ㔂uhjWp_A?4p9WEjnM0ds4N ĴZ(ܨfū4)^䨶Vo]+e# >PddJ|LОW~욻4_8FA\HƊ>3 C>'ײA2ز$=3=8\! vWR[eX-m F+fKT?(ٓJaIw"Pr\b+:MX W+2y -]Fwiuom8>=nDŴNu6kgA 'ܕ^eƟNXE$|zM3(ʲ8 q\׳L0V5o{/rPbKYŧ?bh?n,<YZ)N'*&j,KȐPBxW0G:]@ aNh nҐ8R`yVݎ91D;O V12Dx6n^=ٵ6;+O>a0-_YLK c-h b=|YʵXYw}DT0W~Ex ݤ/TPt"^fL`Ɉ@ yta4.se/[ 4d7.|8DTv|_U&{X3a ,8;MqoQٮ<[x«>B9*b\_!c% 'yеY@sR"r)M9ƀZ;[^\B*AjԦ¢z<_jb3QɬnT|]xP&SvtPYfwDfz`u6A.y; oSsi|KtTt&a3/ϙG 1yʵ[zQ29`K%>vs=VKfr$XʳĈ>~_nhj1v *s1`+aT+6ytQŲWF.r є|@d3}rFʗH->ܪ%121:hy} y5MBLGxEGbL?{o.9 "{! rp+Tq$?&qH6ԽWc+ӤX\_Z膇 dCɥvgK'>vEARq S$-Ç.?| ojّg%:T`=8eY#!^þ} pj?C5#8NEy9!=㙵:DWXl>Y|rqӉLokWm=BV;o_vv …9h% pc, e 4eAIj_5ŞK'(O:^FA!2UwǍS{W_IR+ uB T)Ґ \@f|>a=k.91HX>[g*Egh±#?1LNhP:z[@89*tG3)ХC9t{8|fH|03EA̿E&]_#•O9G9 Xj"}WV_?pIh#_/VJֺZ/lHéjq/RW(b͓5s{%Z+ k/4M1r琏Ib(8&iryj 0fjܾy<_D+qFӄ H0cKI 7ON߲V>S)!/HiJxz5'Xp1UWgy)#`ׁY#h5˺h\C\$څL9VkxF#}FC'J a4`UF3*Jx9B^(^=>rvnF$_?` EˢC)j 8mUϾ'?~SN!ݻ;`aB=L98I47hcV 5`Tw޻j娞[~W}OQm:#OS!Z?3wSyTg[p$$ X?v%Ӡ -Wn0o [.$)1xrJVY5%Z, K,}3~dsA7KSg[M64@s_(XJtJ]9')d I-,Le4/0[;`RiW"0OA!f{Q:7?!^(hӭF!! EH41VTMu{U&X-(Cgt,PwyžJjgMhy1#ˁia6. n=w. 90(0Col'+ナ S3}Nqq2VDEcaa3j@b[RC9@+#8[\G`)Ե_K};#i(taid(ʛm*d_Vhsh;WxtG>YAGR^u-<=4>J(q߂"X Ũ,NE3><9 騼]oOLT,m\SIe)xw;ҔµۋC}d*B#y֠׍UV$r5$O㩇{ }$N4W8zNPڲݟjx;+Յd1Go{V(ު4Gsڋ6V(B&ɮHًˋVBq (\=Z)uWYrzzH[XU /k0yڈ9n3XZ?yR̴>w5 #xs; q tIFb&^kOXDG:YpD:lz`y9B,a^U e~fm((?ԛy}ej,)P8THqa);J\aJ_}s!$2>%4.|)YSZjyPr+>wn_ڎv閠n@pƅ`ՙ58n0d 9!?uo?i/L.5Eb8S/32F2'e:0s罎j[ڢdjnXxP#]C/Ox\* U92[I;bZp:yKgRK ;4o4&k$jh&XZyw<1(Wb8cUfo%cGx M޸A$ co֒@A+>}vKg@z?E=C$4tń^ʎѫ'JވU2e. ໗h@uMtjD'Kxχ3!FomkIwhDT]gKq]hO8qc]'O~xm{G= 8c2ba- (m_jЁ%Xv#eW@Oœ-KZWEq4zjy?_pK܎P1Ku&L2^Ϣח+Ŵs_Fݏ/,Ȃ<*P׸)ӑyt0R怠av&h8Z,ZKjѼtN YG;4,!vofiM /8o6L>H,!7a;J;-BW/fEk$T?q0oF5N)DG`Bx!;}01xڣ23 ٘5ؗ\,4? k4(|;/O|N͐}E_Ɨr䜖1znn/S&iߜjEh(n?AfG "t1:x,,:ԖoVo:]S٥8+:_s0ͤ| D!_2d]UHPOQZ^6JܕmVm[a"Z}뵩B3EPNUc,!bTv.&k2F{(XA@ѺߵRqàbkcK5ڌEP1qOP*C%%0q-?=h1cޘJMzcTI*o!6&C W5 Hn|m\EeESu[=m';7ׯ'E6CK2[`{q^$6 ݯnO^låt><_~>Qh{3|/oR`D{T-hĕC˽mA/F(VOj.>rMڡYǁhf|K} 6mrg(%˓ kMJmR8zN1xyT>t"r!ǜ]Z,DO*OAp8dFg;!rވúcS5E=0j` xU Dp@GA+zaI)=!0\ A+*s2A{ž֓E[q.4KN*dZDO9q})Q9Y2$x'8n4w(_9tS4,oLrVG9oШ9MUs_ʕ9T_N2Ek<-Z%c-歞6V^1N79SPLH\p% '3RN뫅uSo,)]4XgILP/! !tM۹cY^ɷ|/Y*2B%#&R*zdvgk?YYB,U1EtuU,l$뗘deݾyw6† Oq\LBp_׉`gȇM'T`MW=ۋWBzeOFDw f ^T[H öHT?Μ< [n}w~L;hm8ܾ53#^n;!CuWT;? o/A4D6mЍ"%eZ1.9 &SU!9@&)U=L^hP!*;f5v,IVw_מEL1uo{۫~@&YgV#RFU.TV}A~nvrV_K> 4g|ñl~ !9yuX1F"L0pcTb#Hg2 opeVBn/4Jahi|{`>'v)sgʋ lkf+c*Er_r3^[8i1%on\L%oyo2uhȄ. yBw;ׂ0e\UVк9̈́}@{iT2} VS ,2-~Skȍv5sp<)vr Ϭpvs;A|v) QMz YW܁jLxCԏfTOAa'`$p#Cn/EĪ׳2M"=e# 2KSI\,삗›PU6%R^.!]69^W"RAN`@19δ2ob,ևmUbRך J^L3 뚔jJ ;դY=!K 3.:FzpGh h)apk)<GԎvsw0k{"5UKfҺXI7}hy4^ Dlh .@L$;V怮(=ZNbDxLҮ`h$V?&h !Hϟkv{3 6"4~ϾK h?GƝ=I@9Oq%A-H oiy} a((5cIƄUY#~v[2@O%_OYp$#cw,Es^2T٢3u`IcSvmŢ]36Ku@MfgM$^vP%)O{M+ R'W3n@twr}]VnsQ2{-Jiu*@M4cկ]64Ȱ'uۄEH8<4KƤ즜cxVgg#4U8j/0!ACes7)H^~c`S=CW$/YzGvNYձu*808sh,lmwJi~+#ݽhQ'+ځɷ紁a2&ӻ1% |nf_"QḯP$8+2bӓ4Qf9[a2.Y$dk6vd+́ݱ )Jܯ&A֝*qg22P92H[-#KkTM1b'6M+U?>na)?ҽM]aQW*M_hE҄_.gF` mѪC0Ƅ@B=np]8M2qRGvO󾬬 ncF8sH}"TzG=N 6& Rݰ =R`KkVOP[xn_/2KǽG8d,26;?mdؖ ŒķhgUA-{8T6}9nzRZlGfN1)n_Cj} N\J΀Ѳ8ǟisϼa:nHBR'C=Y~ ~?7 #_m v  ֍erى!:.^״?\|S1K|-gLR޲v5.38x͐M4\/_ "dNJβI 1 Mm#j=I[L.z% yمj;xQY׀yӼVMK?$>BhTe/p$HjNzZ>hyW,)_A D-H~-܏7[[Ipȸ!cM@8r_w_̱eӽfWGL v㮯 Q0bEK#ia M2k--m+bJM峐Kf/'o.Wo&7K_=pnJj!I-k<咎Y/ɧD;aX6Eg>D!iKLo\9uzЍ&_('2QD lS WfBc]֚ǀ@#VѭҔgaPy]XD(q sO8YiGn`2H亏cdFf@aMYdP@9Fj۟[o]' ;c&(cc#&}HG(+$#\}y;%CIjDDb̹M WL%`!;rcvIHE"һ;֚68s>2kz"xó(aքN!~niK\#[#zͬ`5_ieyM IrGʏyDe mzrB1h9Z_?˺\ H&d&m>Hôn)Bʼ|!W$߷咴#vBolҶbBm H&M D-?ZA=qq/sd:ՈmI=y0*CIa v,8 \ݛc4u5"@]I~';0~K_xm{m cFMp!LGB>hޓwض^|iZ%S9Qs#cr 𦋹Q=LhocOpQJtǙ~ĔJTCSEAB<~Bwxİ+g׺nI.jw*@IDAT2,WػπppS=^/q6δJ`̲gҨ40ƛZvaX l{<E yȳyoVoנk.SjKK#^n~?ӠIo͘#c Z0WCޘ\)w(\ (@Y [/ݸ)~^Ha 4r9xY?vj3k ]J6,|:Y_wf@<A1h! 2,KxGO 3]t&z( 8TT8qV4ljL6$xf']wdFFV h]Q4!ra>Bسl#3 ǰ7 H)C_/u 34`'!9\Z"}'\gg[4LIeL=&խL73YvuOEqgSN鄐֯iGZ1n8#$GpKkJ%.38IywI7^z} \L4LJ؀:T9GÌΏJ1ا4iX!,].?Dtդg/ߘ`|}q`o&}1J"uiRLa"X~2Q@ni2LFH/C@D)A"( ˜^Yz*箳^'~::<8AuS_:A=ߐPV(7OB4f<2ř4OgPC4}7U YU!uȔΗ\="na94 JٔS, mdG\$hR ԆӲ&9g$i72 %VEՙ,~7A A_c h$gg30c="]\dQ JBƁ>"Kaw˫74{.ǂ۹'i3Z: >HqaR~b*F"EA9ԫ#P!ؑ9|n'>Zͪ݀DLkJ"|&ۈaV^g>c7x/9zu8w^6 kpeYe䍐zK"ā8+mVGG1T&Up_Wµ\?=.ifB&: (N ů#+, z@(=GOG%y_Kۭ?Bq<(!mhx jԹ#tyI``6+Rg$oS I/CU! ~,Iy-22gpq`Dp ~g1|fWZbas><҇A`;h5VlF}D2 G@%ٸO:Bf!ؾQ=7TnsK`L=)}+!!ze6ct4\I\\ߨJLguCo zc;m/ɤoOFnܔG4D`[#^+9-+FYdU%muZ7CL qoF'},`c z9ߍIxgЄiL̔zdb#GD{ hEqhT:KX m"9K˲9]0ZgrS3a5"f GLΕ-}3af4v_YWR[Fq>0Y8NG`[Tv?YnkZB)ȟ:E ?4툿We륈|h1 "V PhFHVn? 4|$' e⟺VW D"\cmfq>q9i?ڛ3E*Xř 8 "G3+j@a ^nGGy8РF5{mmd(4D3i8 b Z7U?l/vZ4eJ|+ŪDuxt~31_4ι"7 ?\W*CO;ȄD6L GS.=sAVo]_VpbX:wA[PاYXva^<ׇGŮ<Ax0n2۟HM+Ql4Mǚ|};~g੟'lGʼn?|dK6lw[!E\s,s4!5Q8ke4{;)wrb"IKag5Ҩ4S^IJW{J %TÎk !jW >Z hG/2HCby"ar3O{gc\ƾ\vn>EQa A;%$e%V'UwotSi^[F%v-R1"cLD4DmY, 9J< p6TcoIJjmG{\0 ig(鹋l"vQ@0/? |YI}mO?׈˶Fe])QJd3 fҩƍ^^߷@@&{1 |/B"=.2ȧ3ZNq ,?t&Tm r(ɩU\63{5V򷭙>%mkep(O  ЏrMRiMjlM638S`FM3h]d<&]i4Uuс p znOYeD}/ߑ='t$E6yr0=a4^IdU`@FA a{p_^1_46"4od|o?Em^Jt `) L0E.k# _0F *jq_`xyEGU/?}8ݨS|olO?5~j v) O >:=wІ]sQ(X<>Eb[ !eVb˛1#b"_As:.( ohk,2(tX|0gBf Rx6{0gafRu/AfB &Rvߺ8] 6Ꟊj]."T]2T;7k,Iɗ)B]~^wۚ!}-W2*psu)lZ1g?W(#P+hc@c*o?!HĴQ":ۻaH~"]9Hͬ`u1JE ю頀R6s50s$fR'/'bb>W"J#\z-GE"RN\2h}&ˮ4=4P'::Dmn٣2zV˂^5R @W$RNBpS1؝+$ޓvfC;OQuaԙ IJm2#p` bٙ8ֵheBe50%)S0[eeǝ ـ)3=(OB1{gR\Y7bNS(3 m+cgY$Eݹ˅4={#RU%>ڕS-!;>IyoF#9N1]pY @O4232HuÎ!HI)J[u?nylQC:qX!! om) ([L $uT iGƓZp"y$ڢ_KgwFΒz [M ؖf#RuY=EK" N璭Næǁ)P0anM\f.]P[H+ STWcHZ]Ȍv =g~N/k. ˟ 0QKG* ք@ Si`qwOtS=]2`gNx/<(ywW~U#s{Lxt҃`nvf|(!pQ\$K,TJ-6`Si}5\6ϊ`(93!&r W\6 P<`3ㇰ{1Cá̺#`j'VxIYY4,$2MǃЈuUj&P2XkZ",0TCkhs1T>궗ً<&WWzL_53&eN0M& Z,.勅Xk!h8~uf0%O,D&@SxwҪ#á!߄^C!%cK; ŏ"j;b6:Db!ԪThܟ /E]oG~mU,cZ.$LT!ŕ&;aL( VUdI!n6Od3VP [!^ݯ_MTsMbR8?Vqdze 5DW!OJU>rh~ L\8"yXAGLZRv[1oL E9z0OG< +ڍlzxP:E:5ݙkua0R m鿞T]p_ Aqoy׉󗒼G+ ]{,#srvȊ&$&5D9uZX1pAIBj sUwAb6}h\V(0+/ۀ<; K 'ٍz_F[P'P>OhǻY"W r|8tŞ/NlLES[3YL6^HD}fp0ɡA˝eM2@F[Kn 'nFc3^hg jD ΔC*`{xnvG'*Z@څJZo4کzlI'A#_;mY+wA"0-'g;_C ~v],SM7 j(;/mNQZ6'ml$rlK/ 13XNAQJ*DeFkqak1{(7<լ~Ǡ };j*!NN,OHYClG@CȚ>Ryo%6z"j;=+Z[1}/TmvDEvTG?底%ﱼ16]|*7PI%w_eB+xYdoֵGewb3[}3S|ˀ"o.V=ӀI/q<WtߓHHOkúd#By" U<&I!ءZSoi|-*FQ`N8[s#X/eTx6j=LVxz<_ܻDefu*XyYr"5?Ka+LJz S 3ʣ RqZ( [ysp] 9o@MtY:kN)^ο$A=o֊"'Z.1o:F7x2Xz/Wfo3@RӢmo8(鑄4v I|+Ct]'WZ#x&%_wTrF  9 2pW %[_d n I|Q?D,r6sD9`*7|V~i.H^| I4cB1#- } C3`o>Jke_]E,ր ByޥȑL/f A|3{|p;i?3\ѱ<pEj767]NY;[)fYf- Wf5.ă 7"mؖ 1Z~8Ipp׀%wI J6ʢ7|~GL"ljM]ʮloiIOGasv/Za ޮ 4˿Xm,!M=وI8`*)}C75Ky5>ݼI1{!ćst^R{yq,-8K̓;k,W_|?]j GWq# !ӄ\sY\.˜;iqOu8cm$&֫dd * PѸ `_wlaw!Q@P&:O,Y35zXMYvTF.Qx)#J]W',+\fO;ދe}t.~z@yx3;vb 2m럥Cy@'B>p5rd٨CUh-ȋ+doہ8VwFgُOLd^k@՘9pcǑt9 s@ B)_B8hUr](ڋ n2i3U͙ 65T[@"vRglMxJU)"tW\.>6a0hNyCaN9RBPtF߶>&|} ~g f%+'ۛ1\d\AR7)"!X$ڤe @mޛ(dnR׳lYd &sDj0iJy|-yZs,._wɃ#3&r{]$:]Ca1f-D¨q*Nk3 _zG/gFkG"~u$0r>8Fd2[o4!Ii! ^{5)T#m bBʵ3ө e ,cԒU-|ָm+ū>zRā{2º]dTn εO׫s‹y\w˭H>O$#>&]t#""2,l<_/ td5͘}c{QK՟rE(^i K$Cр$CIDϩނG[oϲ :F Ҹky`hX'+Y+FWWФ#c*'3p M>dF}Xvn?g5i=Z $NL!&ۨP ^0;!:<`HQγ`"ȅLfᑻP}_vnBp.PdO0U%1F;ɾhSH5v0n6\afC窖uf|{= ^S{{+KL5xM5}7лgT,D;)wͩڭL-yiJxg͛n2fƕPќdF{]e|ڬ],&{kdjD"5RDPþ[f=7/1g\O5HrxmK< HHS`3y| Ȓ[`RIڐ^6|RƳS }ZCmRE9^G"2G8ڽ>Cr5~&g%cP"b#'!K~5|}%aBi 0l;lt4hG8B]` CfxHǣ6HlBOtPH} TnF0%D'"/Dj[-Y9, ?#b<(yhG4^-S&9 }6a6nz # 8B(EU odŋZchL@W<}LY)\+"j҈SaS٬w8wѿ6Oj\U Jv8)`-E UҎg&&|[/Cd\?ъ6d kPV.C~{).#"Ȕvނ^/kg>C릨@ZtX,*HX\XUƾz8CGA <Т!=U6TIuocYtu,Ut1(9R8T;_Ϋ8Imf-gRJБeB54-$avޡRzsvԁ8J@%JA`YZt?!~c2%\6HmOWȪ#{)\2 x"2,py"t nQPI2>|yhPMW 9 ]=BjSkeF`42YK{J0VBT07 GPzsp%$]RWbFc^ĐbFV&= ;(I(jz١u$Nąa{MEDA>6= yt5HDςi&s_g'uH@ᘔ<OӸtK^55 ŪYG.!Q6zCTV%66uҫW{CŔn=v1wͧ}VJvJh ~'|nW|CrE P̂tQ"?Wt|kkce$Q.?*;4U54:oA 90ғӛofDCL}^_U!4O:}ojHlX#, a2#cxSNZ9c_|f,v;>: 1@]ca>ȋ/ݴ  Ԡ֮:XzX․iWzYhE]+ CV>\%C1r|b6ޒ\ibLݩ_V%zFs4Fb`K? H!gwzWxl9IgeiVO%d)zYd< lZSfV/IIh#+0272LvUe2OCT1f0֪?!,yuN\r̴4Ft̠nD]x=( Pv[GkLIZROϭ(\_ܪ*B"&B_4L(Da4)t kxaYb@?>.8vŻ xЄN Dx døQn6[=ܭc(9YRA% j˯(X\b74(O`8 _+c~n;sF^)ߖ֌,j7h{`\Uaph6C<|܂/@՗qhлϕZ9%$br2mwv=Q-6xJ xOLu) ƩQݗOQ 6)ro0?`tlxc=F-Ht,]V$߁yE`&@ O$T@٩ʒ F&]ԉ+H":%۫ rWC[_ N10TF fI`N^Ф82>!MX,%w.Z ϻЙ/j iijLhH`5+N \dDu}m[4~\J{wZtHXȴ:8=69 PuoyC.a<01Mcx\`ڕ/R'R~HSCM<T Kw-y(i:Ba^r=u"5 L=k,g+Hg ”1rN8|~J4fնgryt!Me`?D,(vMx'0j3E\+r-?Ȉ02Sse5 IAS$A]W1yvM MݼΕ:V«iL.*}6amIA>7.O|Մa(։&k )3hLl@۝v_S5F46'Q,bsgqb%w g_DTC֠3j%t/){eGy2 ʁq3bknKa?H QI}][˩]TOK@ yihG ) ;b[Hp"To?>yD,nrlZ cyo_TKZh YG2<XŠK )e7 jrժU᫩!}:t 5F6 +22pYx:1v#Vkal:#$D22k9.\XA B["IM9^8h >$>4:cBjbԞ"ȇ=\Ag]҃z|n~(B$˾Q*b[o@աʖHF4i-Av蚘nW;΋oBCGGPRnj~*w(tfYL!rcڱW R=j1qUѩf‹Q ZI`.zNrsύ|*qJYSƘgī~ 0)&t*EULM8d^JSeZJvm98|qP!rldؾbV?Uۑ)ќ= 7&ݗORlDť>P0~;  ST_7$$rAT'SGHoތ9&v8]Ѡֶ.\'^80%b8(Q`-Fӝ)jCjfn{fGX3ets M82biʋ_w)NFpZ 9Nws I7T%o{}gcat!Xq`e2U`HIY}}Dt'x+u$2QHGfw:=x#^'Gs`5Ju$8յwkjW?kz >8Λ JTWvn.%CˣUi}hue̓g.#32p`WPAbk.WXE;!`djؖhU⿆ HTlWd Ѿ+N_J?JNҲt0߿уQn;'0هvU3ڡ~[eI ~O:E y躙_OdՇCq-|KDDgGiohR"O:؂9>37R%b-L(޾tHζjLӂ]/~-O'E0Zty@VF5BKF*iDDn~Ԥ 9Jᜳ`If s uUQd'|C<%tC;+&w:}&}r.krڽ4E67PXQlM_r >=R-R{HJ$(}CS]. 2\9m.űkYطwۧ3 zcəFXTpfi ”}@ٙC9[Rޞօ"_XCa8tE.WcOXDB9' &T?hdjE4eH1+0[F:u}U=/G%s<"җ12͸cCU4"^P$5r~N1kOc+Q3wSȺ8ɑ= ^]K3(&ACV\\/fٺ8ը˼K|_Р1]똹{FbȽԀxy ~>5.vnw#qWs`w6$+s]Ꭵ4"㕼?Ĥ6C!|;]ߟpV~u2:dK ca-\:/\6htƁ8I=h3;vO2qa =#c(gU>}ub/sU,Řzu_MEiTC'sܒRmyQPMe 5Jr^:v_2GWZrBp>"zVo^БNjzL~xWF O܏/wh|xa;U&5Tt!?4նkSRK hNcdⴛn@$OXR9ЌJ9!k Wxdt ωd! nˮ^ fb[$DQ^ŠD8"lif$9OJD$o{O=d,m[.à5%m⠁)uͰ9tĩDV;s(ٰ"`p+ U] ޼<} ΜX"xfG;Ut"GjhT 3b?Y>wQ2oIv u~lHf haa=} qJ-!vFgVlp>() 2YAQP /A͕1l-Ūju:o I! 'ΐfr A>a5VAL8EuV*G6xRPV7i:ey|oKK\qۮ2nxw4U5 OBom\"/ w#DgIM-sPC|HW US&yش4 .7d31KNh$}QdN dϓYxlK67K#RMfJIFvۀE̪ƍlm:~,dMr)+I,Ρ,fvh))ʩO[5m#Wv4@1G_I}}oߵyͩoLzu7$]#ӾnCҤ= #(s5UxQ5YoNUF I_T0*A`U#N \#Jlƃ` 8m ]a\%;98fF:Ũ[q`HiqIm% Q5]OmWz.ЂTƳ`V*[f{ hKemvËc?E_gJS;mܛ o)SЮfrV:9LKT&Phw A+%WknGv#':K''T#˝iXزa7]-X1ل#C;B+sR`!~x>&&/I9|ԜaOұZӡ^-w%ʳ;9TR:$)EbheCxC>|P_a>QBuM4}xs7J r[$fC?Ov4A< ⌢)?#эq&B\+zHNf'{Aש!)i~JfdG%P\ާ儱 |YVamkK :e|S\˩^[+zFDBWAV[{6Xr7qHMxYGn: =l${nxxry7O0FnZ@ǚMSIcn|w&5}F/T"iqɫ‘+pI:w`\Ivv ` 3VL0OD_GMh=t0ǐri8*/'%o|.&9oOQ+5FNTSKyB嶈^xI;s_ TY5dI7#>U7vU_y&Sa39r ,vY@^jܚE1q i $mi fp@{"M߭1 %3lSzW9B!"\DMM,_ U I1$4#d (sNs׵z'rO,~ϼ9ٛ? M`AﺛX>tο)Ԫe, wrԬ~ph=#M / OaL3x5tp"3r{Ɨ7N~x~*^GK\jT!NЦױ,LDU4wfʴ2\M뤃Ophƍ0K9;u\+Gl@ʳ R8Ct$lNlt6i޹c4fm)}ޑo-;]u4xw[};^eyd8Egk86W~FǶCwdVNw`Q&p\| 8a2STFpS!>wa7oLPA`rkh*'}^y(6w'ZvBn?+vy1TѹT Z?<_@+} {9fvά.CUJ}+<᜚ ?`Y T{⤚=V׮cHYo1\پ/wL=+`7ӥ0 7i1hBH[;α9~+o$< &w!=h Чۦ2z~6iVxaRqMq ~ez9LWT,)`s>/xC$2+wTTZwփaGvL.9ԫ Clmnkpj V75mE#:$u*_.H0Ⅻy=/!WsA^[ǐ-Ax #U{a?n0?r7ߜҩ6WFH+(]_>E?qg`>bE^*!N/a$|(ګ/.wGa<ʒ|}(݅Sݯ>W (a˭f FFEqsO;c*$=n (h{4S>,}{vho1pPmiȨj Ccw4.؇xA_"!l! ޽B%^[$p?04R6 lғL_O;<D悢= 1U;KxJQ!rt{P We3vh >.g9gi{&J^^[r;{-gj`[pQۦ?8m>9O<{׎))2q"%ROyVr;tkCf ۋ4ODrŞ3i n:oR ν.XC9>ǽf\N\lmQӬڍe,<·=DBeTC5gU˶E!ŀ^ mSY 6IV@:]-x~B\qlzu cG=QV-\ur3Gy 4Ɣ$Lz,YSfn#V{dmղ 1IHڔ`|=Ɗ [bx9AćrMp#S.UB~xKo;ѕ/ucyLE~p?r鐞]5ĄHP G7Ig-P&Ɋ=}T%:h28WĩA|:E17"Wi|͎_OMh,4K53\d;ϼ0+avK\VpNR#Gf.Ϻv`AjP 6IP=7S]?'փ6&ɽC@bzFqg84xP >c'ia2Tc=7j4`w ΐҬEbQK٣ " !tb\'+{";V ͎ދ[2o>(m;5_:ݵ3u<"tQE _+(h%a!)qhwk ń̍'j!66Q0AaP\Mþvd.I萝:Xn$Զ=) ^X )OH|f]@GgBns]Ѐ oX%S}h8׍*#or DG9CΡX0sX}G{ u%_؄$uRh='_x,[s"ld/R=5N[zDesÙ؍BP1)$ v8p@Tbrd;HL@cBf>MVK'(%wqI\"e:% CW9dRxH9 x;"N{-5:,֐\KXiç}>VcsPl R>YĮR ny #͆q^>(ѐW"lTPVtb|ZRk+gLNcSz5\ҷ7{jZʃ,yxjʎtשּׁ"+~,ؚ(7Tw/DR2>2bZvZz{<"+R7_@50e]!S@݃㮌j8Gʹvͳ"+Ⱥv)FJ *1[#1jxo:pitW*IvgcL.df? (!EҐ૶Q4RS\/K'>F\#9a2_z$YLIdUƒMqKπQ eju kNJ̉85(52.i H|'j6QܒPga[K+$k:XL#ILRJ(Jcwx< ,%}̢U=XGEZ^Wg~6U?(vp-ĹhpI& OjzZsMnoLgЫͬާ%kc^AWbgݒoL6 {Ƹ A ", "lݻ~ʓ c'C)0p |uT5!#ķYaȂ֟ب̣nm+m@ijPr/oHGlBHuvx}d} ή0PXE|2sˁG5w2QiA6Wf` 04QDM2S̑I%X-9g21.4h-pOXV?G3_x*=<[!@VA.Þle> wIb:,\/<o48/* 2tji:@#l '6>5Ox}.d{2<fM{_7m[\o/S],XWG&[Osv Ov Ț=DD܅y#;J5OL. ]wd(-W<د>UDEʜQPﱞq~S3lTt &D fJ"T/Tגv~j}|_]L՟H,d[!S^{ӃBvH߲?i+Њϵ茎Ț YP[ #.kO=X .=I,:b~x[bL R^-!IV4)As;6AP4Gʥ>f&'o{e*r? URȼb8ߡzS8x;۶4>T`&4RaU`%aL4FDiI_+J1JԜ"",Aa/u ³ ʾ++RPR6-A0T/oaHikIg1DEP!2,c|_6dxHItrn d10yMzQ~35YH5$G2Jz\R<c>8$L#Dվ;Ml0A6Z0a}>$ E\F>{̨b|!*9DyP=m#{A(IQ+X'5ԊB(3OEHcm"P8P|o_y>(9ׇ9F5:Ih * VNѤIXS 82 &>r{DKi _fr 4e0zu҇KheB Gj^ʖ/ɾt.7K̰BM52R;}enVyMomd%e6ǥ2jw˻P&0u(7^Z8nI&boOZq걌~g #9ݙ =Y{`ҘRa/@fO%#Šw\Ꙏ(/:wR] I2Ȅ]fMGm˘6\4]Xf#ZǘzΨC1@`Г]6W|tZlKZӻe =Y*%busx,{=ua׳mNŝsluxLȌvt%yTq"6{ ?͵)%R|GWw뵹K:^ILXTh5aS2ʽr#av~$>GbWj*m. 0!PE%Y] wTQV-E=Ҥ^rIgha\b.|$NJ4Ua>KΉ[_`R kEE8lx Q*{/%uhP;xMo|fV6ߧA?)(G߀H#[5klgk8b(9q]$Ouy'ɷWF`WB"(|}$0r$QkvV81f*RO؇*ŦĜ#AL4UV~O%44Y^nUˋ/BOgw*0@ޓW,cQ O=m _]g2ޮIT_O#,v;&̌y커D{ QG֭_>Fp3erGvulq9:G;/9 kzSP@D_Ԝ`#å4N55A`YA[4e_muuCPf< 0qbGr~/$kDdTQOXyteLh)96YSו+dTRːXNa 5 P !Arw8aFTfW*nbJ1'b}6+wHqd3e?uPh3z3ڄ6!O$Iv_L .>`uLC@CzL61kk^O(وd9 (^h g]y!߳ A-gpz^a.n'\9Nд04J=U]gBU6z%=ޟB}lvQc-䍪6V%wK@”.'+fZgnl g5sdɁ%?tU$C6/"o?3Opᓝ=&p"eF^%+zH3@(pC d1f)pMzhl/#&vl}=OgVǏ`BFA}ѝ_[,WJ߯TuO /4{=;bۡ6BxBN~X+ ^6x쎹ϩ1m62A@s8m80U!b zI՗n5*>^pĖ#qE 2$l9^D6p+3S{@nߖUx :q͛{e|M6'ptznG4=B*&r3Ez 2SJ(A"Gt,@bcSW_T{Jjj˜J:5I]yVtjfidZx~wfͰþ^!+wC5ݥ%V_\mU(ErhEqМ7e5#m.g=жovd~n˥?M s7 Ad'#t3rW ub7~75-+Dmh5` '*%OfwBxܹ}FPZ|fў¢R>"Ώf XpLp}"/?+ !?4>{$Q<3fV?]C"\oXsvm;h$mGSP<^c+9=f+Csd㻝1.-a<]h X΃ _=`owόMbst.F,m5dZ+ߟ[3 (#HvC?$X< ʭW+,)yh+{vm1{3 B<EV2 TcWW"hP&qr}PHn }!7<>'m {'nb#5/'1F*6MD,U5D$G_4'pC^h9ׄ G^DQkTBnUy1q?ɜgb)Gc+Z#I$hg ǶW`I^%F@9GO cJX1@mNpמb4y9I$|1A&kzCS)O)a_&Sd:^<WiO!o@R@IDAT.3/Sri 1ǯtRŋC7Vkc?S<A1Hr̾90uoXռ(<=Py1rF/yOWq z}'tTYj8Qg}`(B^No;bރiA3&x-NgEtw4˒G#['M?=F6Җ˭1vŒ^ǽ:%NtW9#E.˔-z2~?\G-"'"4' zϥIY?6U`k$m(28qG\ZF 6(r#%aRbXW}MhpѼOnYvgr|>"=U ˃_e\Nͦ b0rXM3,9ZZ5Ieh. XfahpoN:=1HRLwER$ڀt;=n /\;+mjF4P2k| lҊta>:'6UBʊfJYZI0;cy_b/I<d[{ Qh h{>*f(P e0,7ex* ]C[!4i IE&1~Xj{v`CCq9MO:.pqHtf 'B\bT4s'DNkHqOXh<*aH;ӜL IbOhD3a0(.15oxӽHUm-ۧn􀙳n&Sys!>{{} C_z.nlԊ=(YKdrL^_be(Kn3"6EgZv,=si8Oj'5)Ƶ~&+fDWsŒYMuSs٬~bJ@b=귊?3W#-ђd2xQ'o (cȄ<;_q`p['Mۯ<uW38TEprr["`2s"ҥߟh[x_@䴞jD6Q4a/6__gJCPu28v_Z[!fy981Hz]Pߦ/>r`62`wmH;WUn vr_'²\zγEDS Y;}E Tjo49s0R*Jr@5U=i%ej*+CƤ3yfr8?B~29aȇ(5oƽv -#>Xճ$&ק{Lh$x֤֔^6I% H""Ҳ#|~[G~%nDc*c.qؗ6>>a pТ\q]Am,cۄZ& GFO\]\1a F bQzs'HdIyP@M25t{"WR(V?iAd3'v.SƨSIW.04vUOy`"㙓.;$z6<% J64&3-lqLVSef3҄#d_0=Mٸ_h>oa::sU=6`LPCZ(Xۧ-]cǘ94p\ F D;"]*R-(Z2Q㚺xԓXl..O:Xm&>>r AjvüۥNG mz["{{|ve 'U.]E5<. Adyks )iY;S׈Ps '!2S+% %3A,.vy+vqs`RNj֧21xtK,g~G6Vݞr{bV`ȭ]Lf%'}%sʅ1ݑY0-뉟7^ƺe.˃p (|NLBaiϧ.);Dk+&oo&$Ps"-R8O@86 $Ҋ0؂ю59b ɉB"N#,c>jLGb_?)cQf.V|D0D*S^FWw mwimAROX Hmyn @9YEJK#I@T=u%5K k߄dLGkKrFӭW\.pL9:'}S@uIMpO9eNt_̭9)[f/퐀D*@uīq~*O9{A}Y/NB霶y50Y^05[GNbtyvaAoB4wh{:}(D6-4~h?CDҽdٓzM-?ҿ?Ĕ AvĴX Ú%UQ m;lqF'3 c31>ݱԂ:Dw4b$З,Cؔt9(d.\`7"t΢JBa};H؏z-7w#út;##Ͱq~qhmT?ogdu*!pgjҏDN\fa3:!p쪔f_Kis'B!xf^E`Hmrx%عcQisrH3wsEG->z,pN30"f'颜~A%|{NN/Zz464g5e?(D_t i#ʢyOl>Q`6/Wt܋UњndD:f*ɜ-򦹤{Lxv6N]\;Κǔ oRW&H0Uҵ,<4#kPGEzj^΢ y%%l8u{(9z(kV2^?U1X$Dc.ދ cy8W1W}QOANz}V;c/yzasvzߴπY_u zL☏1Hq^FJRܮr))FQ"زïDˡ9oznA7M"/Mp/H37=o*vLվ^ډ|M蘞Z#4md.h"|2$zs^yIŰ]+7偘c,:S0q>recXB_pTsLMRHwJEw/P$1#ҝ?^JX7LjU,h/jl"3,?}d9#v $WœO$.Sh^ze[VS ߃躯 58V2ç8ª &<540 zJX ju,_V''3r= M%A@O(dyԝr.'0{!/C{[V֓Bb8'J}& S8/ù񞳹2VH UMD4b򼌭x!ƺ؁Z;c/)Fa=K/(I-6VWC4֣4E{ZsGV||joAqiLna9uS9E?-1xZZ~_RLMqc;lYϭCꔪS#ۣb]ؐ7Yġ3Z٢m,ɰ/(MQ"Po/n _1. 2G} Ay2 uD?S4A`5"ꜾFt/fWzAҌHQ}BqFa Q/|!)/`V'(4F)m;lL!nM UL`3%bgr|`;0;Tz]$ABYx VU|zQ[wxum,CԠM!Q+l*# l~)&ovmt%Dc*m6:* {S;)'$Mzs`G[\B(j}koLLJ}ξ9A\1Eރ'B”Nd #DaHvGsƳy"M)^fH`Qrܥ K[u2p۫8#]\12}Y;mW٬Djdꐍ¼Z.%SV/ԛ@iTU6k}XD?DdSp8!gS|2#Bg*N:~!տtz1WLFpvWclXxVmש᎒mCȸb`bïa)GrdӬcr &)Ҥh ֤º9_M&7!>B]އύ#՞Qqm E?Sի23אZ@L[ʹJ{ɲ.ѹQZ \id lQ"cF$kTSquWxEe:{t>$dW)_4IuĠP?_mJI&ǽ𛗆4-@9k_[GuNR%m[z5M`u?9Ϟ٣hV4#{ڭzW?G5!**ؗlNo-FE$CM yα49RE\N2&/f'DEl(yW6r](tw`,Q(7tm1+}oC#NͻoLbvuێ,Ԉ.yvܯQeL=ZMwf/h|@q4aL GL "9ΥPª'3^EEs`-aVH 8IE pWG@^ULzBzB2.&gN=#Dhf۱oh\K_wDJn[M-_ZFH_WjX=ú-)A'bEicb6+ s17Wޔl5om,"lEr)QdOf,pgЕs/rGoi_L#>=~ޡc%I,- hO.69m`~QC[jnE̴9TˌTy\S&!TQ6*؂XT"Fg}dT옑';TFF8QkIX2%P?6QP$vɻ'mSv~ioqVERQ_]gUڬlWG섴Q ɟ7_53hlXNA=ɠlбHi:˾G1KX.?1%^_G<„q/|^?AyJͧFaR倔\ZSжLUE O S37<ڇiy'>/I_;W"P~*I"-fgp~aԬsӰ!`B WL3 C%AMbrP`]'yzi*޻͚.1'}"*;wK>%`RI1B=ʻé]uT'oqpoHa*$}1!>`Jz&wdg?߮^,OR=Ty(|"XOE&NDzԂP.&;'Э:>E*[#o k=g)S&gOw2|Ў_5Ch!vlP;jv }fNlk_w-D֤Qؓ=Dt9mdV'ԆychTs?vcK,Gh? u\F[c:ьbR㝧hUۖ\zE1(QgvHJq'Oyિ;<7@kZtqG>fI @ PI2+JS}Yqæ##E Ank}?iH 3܀$n10ÿ 'K_gіOLnrs};g/͡I ($ {75b*l_H>b$cT፩ZQ<'KqLnx'ɴ6kSzAHJ(oZ x ٨FpC/X,Ůn c;yyϰYo <-#!&{X7%9z6]!:&>QfaIòYh$oiTd U'b0-Dg2npD]7[nsJal(zuq2A{+>nB #>b2P=V/LT'ŋ1.[J WFs'= ult$AG:&:Toq^V ѬЊ{TlCL#~D y$'4!zk>]vgӬT|&۠և;o,&JW:X[2ñNOVPՂ'K]%D+C9vx̌## Uv*1MkEaWAux3-k:K8n5lw!BMkh}Fٮ`[lϡ4h_!'XONUy?4.󾅆n7R=^snd׬OsLn_Zx ZqAUmlq"DuZ};?;?ōI Br=9$”B#-hT打ӟ:ʅ |~{s׿qL,Útǒ@H N^ħRL/o8n4KEߢ3onoqqG5)WKazGLs8/\@e0FYEwg(WCv<9La>hSxpR?PD<~\I0|о0J)8!h3_h㵉!]7: '̶u5nWB=ɗRjL.(Yӕ7^h^szF±DUg=j)6y2Mi$BS /p ##=k; C)+ U>lkcڪq8.gX_L;(xx◎/7:'$ĈBy8B=D8rL@ZQQ,**u7db&g^_K8dەd ȳm|t:+;DnG ]wK[tX]QKaNh]&ΪrImr5mԮZ{#Xc_ޝDN| 3=@\3+!k]S+em8W=^]*>UE!QNԅ{G &!*p#N^ivyRFbma2VBۏ@ҿMBtri.#s[tó&oq@dl+FgjhѬJa,;h,"D3ioXL ~fnvyj+{ϞFrіgf7D+65<$kzfݢe!|Ū ox[W%V%xh3["\p4h'Whc, 1OӒ,h=,QdG 1kyI#ȪgҩK Y ?,DM3_0C'#u )FdT}6Q֤7g1cΨv5Mˣz3 viČe\Ep4L?l1W/?n+ g.5e3G:'O5'D#_O 0>H;22'Dc\?)Y%qf H+rBPsxz`* +g&rՋB9Tk?#߭LCֵ?|[hZpUϼp8b_ F=9Pt bhjD=+ q.;o(Nmԇ 6^?ᕤiʓ{ˈ|5z̰ym&Op8̓d>:͆3ïy4^5& Fѹֆ]!vӴ_L}3BGn8E9{bi'Xi9{%fvIa=#ת9W,/liQ ecxAZ/oSt*˯^gMf_mj-,f1Q?v|yZVwdr/p;c]#׊} SkA$* R!=TOg3`@3nhyfp/G_hݥjUM6-sq4ڮgULrԽpqj7[.e-,[THbڹsCA%!? o+OgןХzG u>= R@Vbo='.">Rg/& >bW$4咓H=_V;InR=SPr4"hq.|z2qRӮ]>1Lk]Xw Ee Ӻ_fd"k^6XU챷T=3O`T%pMX$ {/2Ư9OX.}ξ]hxM "0CQOmR 9HCǾ;OE$Qr PbjWe0~q'SsZoo"țH+!(+0hABh0M ם>JI4mvmYϪSǾf ෭Ƨ̳; }8,PmNƘwXV`Yr@]֪"0x)|͂2񾚤 Lv)O#Y<6wjw#MW2XAL+v5[QUzP(bw6AO1-b]EFZ|uּYTD^iB%Ϯ7Sr$N;WڴvjvY\(~g?O†;s_ A%۞uzVZށ'o(UAsH=g8nqX*'s/qTve_(O0رa▼Q#d}(n4:uQھމO 'IRer]*f = #&%}U*,QE"X-ZhreBq5GPQ|q]!:au ^4l⊒r"Ы{1=ƃHQc/nߚxd&?^>^?)@QPYy%˃Y=JBk!1 ?0E,A|ǟ( 0d+n,B˷?wv&|-[0lMIlt+L,oR^Y)l(V"O I.C 6>|^lMdPd9G[YN|.~}کCN2Kk1 ]/;eg>M!$*)dfpؖ%?1*<[f*3r*b) :.NAk=8'dvscv(94^[PZzdcB =rxp#^j&)䉲NWxGɦeݸF }%T 05[RsGW(>U7!o<>8ͻt'B@A:dWxAea\\B。X;mJΓ!'-8cէlW svz8k]ny ՠލ8^ݸ*tI[}*̓[U7 TG} -~D!S pIWfqQ$ڞmPV̯L>vc`]į ꡙϤ;|`!ȹ݆i5킵в-ZDEOږvLb^Hr VP|`5 !0Ɗ39FLJz.\ ͫԖAv֠!pf}j:0K I~Nr*AHn7^F$ =ه?iW+H²6,Rtq+kuA+N7 76&"G >~ƽ|b؄p{P[HKe w [ KONr@%ڸj\=}Jr#rdg j$޾E^RH 2(tRx/bOpp)18%o8H, 3^R4l+TU@z/Q5AGJtr>HchHKR͞+1;|Nٳd)/kthu XHdyͬk.mBx2nbؕvgyG(1.Wɇ,L^#bgwu5HWBtق$As`$ [E?y'렔Fo; @̳Nxz-;9~} 0dfO{ꏱ|h@k esX%e1sxإMI(ߗ3F"t IAΝi.%>_ ?xVNŋ=LxWYFjӋyϻ"r[Z8iECav4=+@DZAa5Q!?Fۜ>iK5Tgh`<ۓmQæbgv|$H=F/Xq|IF~ >K%H Xf-)@XZ]r+ vKG}ەAJfw\ؓox3$Ҁ3b=0:&ܭy^@3fW5N_\ qWo'p-8ΰ_??\AӋ %דX~kLKMTYKs\ {,Fg"Ie)*o,xI2<2Iĺ@7ߓC'9*NcʳBEazcr7(E?&[\i%!$NwݾFPPkaAi"b#4> GIeYH%|-'9ڔ ,Ҍ Yr/lIX .]ŵ!zHcc| c%K])smo~9txOܲ>UB!X->:Ov>d&."YeC]t ނW±\JUNm|{sȪT;9 XQլT]b?[B|Ȑ$p_|Ci/yyyڥ,9rdf\V#90̞5.kWb)WAk(KP2ঝ|;Jq[M*}ȣ"hgXIJpGӮ4NXg!twQ$8Fhmphߌcts8> 60.}\S`Z{90F@qCMx%{τ Ќ ˏiVA3  $\*?E[Q=BۇIBy_"5Pb),i6C5lJ9qͽ"ZrH; =y~"x(1E@IDAT8lV8oW\*\G]3[סz Df_A0г*r[kytu 0E掸uLmڋ74Td22UAH])ضpVamU3X]%쥙s:r{I\ezS"9O{\ȩhKQ#aO y^( M:b#,8r>d½mPAީ /~/%VvsBo5wGw"E8426]+ MIAe$PH"58;3tW]AbEVbM8% fǚ=1k9TU, 2 0oH$+I] ^;?7jɟ <|a~zRD_n"`WPXB ojK!#qȭ~! ]\ UDժ}Q?SVd,LreDM?9ٓc`#oAcaMr^⭤t/zҿkz}'DԽ/߈t\Da֮3F@ٵA6˹݆/1j0,еd<eIC|5JRn/6%_N00?:A=pο.?lmLȕr++O׼=l[ɯ}2DIB*LX/I,6߂x\q5xĖBhXIC R ({MD ZM5PE`#Aʧnczs[#e p^́9\EIbݲ<C=h6|Hgrј."V_<]"K8bZ' ʹr  1oVYMWa7Vӷ-Lo\}i_vkG3;,5iF戱߄z=eH 5hp(mH{KiE'Ԣm~{Nqӕ:RJ _燂goV{U#oj訸~Mʺ%7~:cPv,Kga֟zA"|[m]2NS2ܑG!p"i?y~.:uvwHa%Ho#f: ߴ;YNkVg";[86+2;Gڦy4\o.NJV!bN7DPw (ծӧd.Z>WY0_{B/_S"_1:0y9<ʹIGy{KIWY)6e٬i.Gn fDT2ql(qA:f(KRvjZb.fVݹki\tQha2Ciձ ^*`<8,@c90XL#cpr>o]]y ~U;AGY^P?叫[ 5ݐy&qլ i FI]sכF_k~1AFKgOt,KWPb/k),Q=h-nzެRgᠬ:iBHuU)!砼Ku+vGþONɵ/oR_+a)F6̯rw0l;ash eH ]gF:v2{f¢GSぢ*BA4dL "h p.$^wԏ綳MM}XM3K}4"bi=RV9ze2 Z=t)XW_ oWp\Wqjwn u (' mJrM"ѰCQ pI8L(Ma Q-)% @g @O)(%ud}eqUe۩] lǐF*<X= a9;oɠE/pn^~fi 8{Cv%0)пtnJFog{nͶ2"؝mHT"xan{L qXp?Wu7HlHB."5VQW87v6狝*'u[r%Saܿ"AD4h3F'Xu(<#>ņXB BzE(V?=oBc! 5@ scTgaSr;_KPNb乿L`4kRZcضƒtifdq3WX/)$LY]qJ(Xn RԈOiy< aY9 hۤJ [{xg-j2QG֟_u %;=Ɲ<ܖSjrxL`h}֢uIs qJ](>}|"k*f9m1*xgIUUZQ-ZVoIp#D_S/֦`pٶ*]UTlqQ@}NQJ Uf/xt*I \9haeQnVDɍHY,#˻j8˵N W̥#֏&$7ld!k3Qȍexv01Tbkj8Bn/^  X,d8Tk:4Q<5Yk9ߑ&wui,R>6#.{Ë7ÀJ-|Uڢ '5tlHWؤv:%c6-[:`.o㛮T||])F̕s){\XCH & _4"b,Zp)}JWMV!K0#*,SLtYX2G܉+m~u`AO6W?LSoA)d`afaLod{~2 =IX1UȭMXo5;'85*N7@H\pwJ|R8V6ُÇPj0 Y?oN۩*|'25c5V} 9)t*yM."|qڶM^A~d]LXU/o*tVG7qKVteV-ʞ,9xJfRԝ2E QUӸ߀1)*OmOқDl6|7ꮙ~N+=*̌ww|yX{kձӷC?,;w+'`; "lqVK\ҧ@/74=qgE>Z4Zxٛ/% "2Vk- \ _ u.Ӭ&oh2c~Mø@"Y)c0"UfdHĎ7f .Y7$1XPnd^z`-Qru#;OZK&c|@'N=䜚%AkA%{u8+ؙy Be[/o[wKغꇨoi$LƵSKbpeb܄MjǍCJ5W/5 4g499WbOw f@\.^d[Rj3ncuv"Nj?Tɳs}HXv8_'")(3Kl 毷wBa,` ;ſ~X FG[^AD|j5_#|O_||}3ǧd4wSz_MҾIe-W [8^,-<ιm7{zzq3}63jfg :/=$̊ SsFoL!21T5٩ʔV]?wTvcncrOdQΐ5QC3t"1-؅v_|"sdMWAŷ_ sx"+$6IQV.\M`qy1^xauEJv-y.H1:GTɧ8[tLe!opɗ;t˰i+i$`#?T.M_AEdNd)vG+l&[7e7926'Dm7Ue^~w:D{n%LQ&슠fKj kiCmzcc6ބP5]D+^d`o:ɖNʏ<+'TVɸcg^~]X ʉbT{/@]8t¤+m= 0_@iuqGzЯc|E@ f4EKq2f30Ykw*3_ju8lR׶Fg͟oIʼ_}yקSQ >qrB>w<{<tHDF4 ,]-0'PY8p7u{ -C1򇩠_}msӽ7rڻX6Qڈ2ٲ im#Al3O/C$@ni^m99AUsّY瑎 FPyz};A 76+"@ 1DC.̉j5;/= Iu?0-!d%2Ea~=JxIgwbK:<@V2"}:!,I`I\>V||/US'^lKy,26]?@f+R!W9D7~vfTά3ZAHz7W>1NL_s|՚E?'>(pO֐y5:[eHxţu%_id@K 'ZBٔӯegv 6 xH,2wmU({7N#OA pPɞԱ&=mJkg? [OZ TEv7XUƄ7e=m#~OsG'ޢFX4xiS`jL|.\{Ej)#DۘY2X|쨅Ul xFڹ'RXL"3/n[6ņ?P}&4pBZ1sŎ=ޢђC\=( JُofWRcbM#`:^o].mQi֨Q!4P75IYuĭp!c-U{hP2Gq$QBSxIؑ?/WzXH}tEv9bP Wڗv%H_}:t5m#iN2=POqs(Ŷ`_]k6GVY`dKjʎ{ZEs,qoZC]M I˜YjU25E}%T>Zmy :C+zBKX_N,vY WƠg.}6u f v([E.]b=/v݁W y)?F& +s&Bi~GWiLx! ռ \ez u? n\QYHu5fUƥ݋vpK<6K ZvEȡ9Y[̷7|2s޲Ac]`X_l2\#Mwa/5ȝY{RiL1VqW)a6TuTuxxJ /}'X ٶMpdxLv a&޸u`v?'EMQq~YRX60!$iʜt=Ha/|7rLB}?er|4e= 9bV_ Ĝ㫦V ".*u 5ͨ#(}o[ `\6Cwϥ5s:M=f=$ƫ`)i> VEt6L+0هCкJ)Y{wg#¥cÎˮϷ )؁rKzZv1`#;u&^iUue$\K7Ev#PYpP"fMـJTAz|t>++f&Af'STٷ'V$g4,K}JƟϤlj pINAD|}"R*ay9?HZQ.RJ\g&K[(_N {J.: oV[ GrMAfXɹe2)da4h),}lևV|fz'_ToXIWe-chǚ,RKnReQud%m9u!lL̫F8*[I>C3u[Ǭ; jBA"˥q{>HY-EӆUI9'탪ZQY>[BwLyσG1#vzSw Z ҚvVIU\7cjޤg#- 8绰B L ETՕic:v1E |hP`*Dy|&6GE{V;0ET'"MZSVj?)J-=@1R>"oq>;!&y,#JN}Ѝ9Z=v6|ge'4މOT5gdC@`hXY8@+,: 1b ٓG?;`/]?v6=Oĩ/ T*4Zyd?xй`0ZJZH!2BҺ=g=Qnxs(Y^34hBQ_C3M0焋y^ ɻFM?C@:aADmW<ƛ5Vbi;#*.H=kRLhsNG9>CsVS \RT9?kHzF閍c5ʱR RA⑧%"Il@t g3khRtw~$TN!*&.vOJ%Z .݃IŏH`!Ji#JWq '0Vлxt.BRw:)mm[VS.[ vE_pGw44}W."3rs\0=h:eyc6h#ݠХ L;#fpţAuB=J Q S|loNk{h1#;u{KUAU˛3CI^wMY*MGe#Ăd̾Ϩx0^RNۭmYhͥn-yz7.43K[/~\ j@-GL@9$Ƕ*fBv9c"?IF8$fn4LO:kY|&&e?Qi퓨;9jGht0mmJCv%8H:8 לTGa.`XQ;Afѣ2L~ XNgI"=}B ˖TN7|I G".Ys^v9Np6ɦHkBSe_g7.Lْei8IndsX9gKYbk}~C~qq$4*jM*@H=%y~.6.+Ibrt4/>E1Psyro| [at5,7zCW8yDc1  pH{]bl"|#fk%,>vOޒwimq\Z]bPw+E7ej,Ov,ʌ6Vkwח7: ,$]yL{޳5YÀ\DJ-ty/Kտpk9lfJ{/'o[%%pDKɞj뤄\I˸—sP6 ISw?[Xucc!['ِxgW@=R"3Tg?%gmXQhAFTVd"p%Dڳ1vn]J"dfIIPcH(`58j_qfo3FDU\P̞[ ȄoER%rʤT#]{Xx l]f D)V9GTQ8fs"6tj(HgĖ5&ڛ{ Nkp$%|#Ep59HqELm|m:Q?YSL%穞NDg5씁j'Gʬz4[HG /Yۺ],DtCf, h# TmƤc0AoE+vS~Ь\jZ :b4,)xVͫT8Tc(nc3LQ"G]N17 Os01È.Ɯ#G]x.ɓs/ɘJ7Vj>Ŏqg{lD#2)1j> GFtx6~αġX]*^`)7y;)sG)Xon$ڳ>0z@S8TϦk1fOU}[ޛxmޞsjp&R6ԷHR?@6i4r"a.%cdĹ6%?w|7{$zKNUnDEK0j^F;YY\F89+kpJ So$,Ѩ^ѡ6%Š|HO9GJ3AڶsVԺ6QP+}%QEb:qہZNNL* dR,CxA_X =h2es%NS$rKDTQ %SAP1c *vJd*}E] <*婆rh9UJ,K o K}JK+áq34SHq/%$׬)Qaj nɏ90rkGe'`)bC+S >lXt-Y=4Kٲ|xުüd೪? ʱԳus)inWda\z_ںLHc&m'RZqLzHE֒u ԌY,Ҁ (vDVM.ڳC6W2'y149Y|Ց2<$W/WomnRoG;.R*hI ~C H,bKmvUD]fɮ>́Ε i:]*=C;kf6_@V&K!Yh2.;uڍ::QW6O6ˏ|4L)$pv螺Di jQTfDf(h#I'HimGtl|=t8a%ڒF D/d)O)t ЎL;:cvMqƠjOco^pհ왶npIpB'I'1)"䃢/TܩZh 31b?Ao8N?:0dbqT"F/`"곿1ݢ"48*^OQpd`w{L/Jت>Qj[҈\Uw\>ZgԮ~Cxjf|>q'.n?]l͒WoSIߘH~XhA᫛u5D&1'a,v(`(%4'~GLu9OMMêN˨CiTϵ)ƣX*& +pdNlkG'vlK,Lh?k"g*zmSWfUTTR}f\L,%.bI )+p9w{e8}gK;FT 3ќy:l"tkJC:OvWI(¾A*Y+waN!)1)儤(rE;rń9(\SrdRϽ;Hrd=37O͕ṒkXe`ɹc.06:lRղ3>P&OYFƗӓ86j| EBf\>$6lotGneE6 @:١6_O勒Av*\ $'Ϯ§U}l@> 2ReN{u4f릂N :Â#a<%َe&6n%oMx'jqZf)ڞNb7a;V2ⴅO򎑬^l}Å,r l8r(dĪQs1tQ{LF*aOGfBK?uQM}(ƣ=\NI$},x>@M9HOcՁ$UuK`qE0ު̩]]62 ]6tϤqTpEKG4nFSo,8 \%.Ϟ sB?jEZI :$4: puc;TeiKg+QEƐJIՂr6l$ڰV)ykfaݎa:e&: i z+צCW*uml*/i ]<"{cSa| 83l[W$~t|c䐷+GB6ۻmg{; c5oEx / 5R_u*:'H2facnw)k+K˛uG6Tpc'l?_d b&X_]F0l)k%=A %A_A6@ge3e9[/'B 'V5c3n!kkx&CGlhPLlZI $@?pGhb@x'%;Ebv !>U  BdvOHMCgrQ 银s%WU1};CZe%F IGŠw0ow2nu8;:>o?>BJ2(c@IDATڳ<LRj9w]л7ҁ#=3?e#&ʡZQs6/̈8Kol]&Џn{NP+GRnWo(Nbp/$.rI7od❙F) [w0 lTP?7',j>*˥>^ȓeεi@<#?(Nq)Xes*쏾3/A"٫;Psy}P6!Rf :if}xFp;K8Z4c:Ȉ/$qs"́9CK*|(4j>̟݄$ ?NfOœNTПߛil &k$Whdt~aFK_I$h0zmbUBM' c/آb#m2_6bZVI7Q!jdHq=7k,-핚U^e(@LjRc;'NM^,~5L]J= L>K*n[dhcr9r[u_K$^\vFpXd*R=pC¶swn0}asNpEhX̀l᳘ܞoLUWEVmlkJ2b䨑´ܡ ˜]fj(+uݺX;q[bJR aR=8(0an#!=VwW=3Wy5_@:+f)_ͷ,Ԗ󫥞8σB=_q+oRDSJ?J GUb$>xW&3ύ;|0ӔJLL+CrOK񞩘Y(5q7c͡/?DtOwA5oHϾ"yJX kv;<1z'`U0Bw%tPw|q'X-fm @8Y[{"oSJ5!,-ZV~8<#Ax6A_IwѺ0Yesd)|%SKP?RN)[;Bo ) -iQp13($?yfYa \*Z̭$?OS>ۃXyh+N˯%KT~&P bA*Bk5.PfŠRevj_ocN̹s0;7ާ@vz%N9g*>z}c}͙X 4_)妏A;y) GdxEU,~{.u{1"ңQ85'r[DOfE]mHGC< `TDS5 9 py@!F_Z!5.KƔ!<ݩ8B$w H8.0/Ԥ]hG Q؉k˃V-yS ?!<˭U uFxU776#!m}d_=nRy/Zgvw[ L(ٖHX1elTeǐgg1FS 秐l"Ѧ{ )N}\[gq8~a?3hvM p5߄A+@D;8$ Ds@{aVdW7r!%T:I^N]NeTP2!=ݚqF*9EWozڀb2rq.b:StnWշ jD kWG Ԋd"d3G_ f!Zh2|7zX@T΢WN c"൯@؞{Sڀ/#HB`5.,=QWLݳ bq@ϬŰ%>䭎f?ON-/?(zwՕO qj5 e8G[M#JvG@7u'f3m#PzqcǑm3ٗ!p.떻k_Obw)ܓ+*˔iA/o}tjdR܀y~"GA*͙%kvHf|N+fKTFrN-*5CF b%"H2ujj =7rEkE%8_4s8Vzi/'L&(hMs1ɪ # P}pӜzP1-]v%3B8BN#k:@1\6*xbi $Bj* {)4T.]8]kEQwDߧ{ T幵wy"bA)TmoHlSj@"KnlM9(+P_,nnujٯB1duv"A[: i͔I8I"ZO^Eo]$$kƼ@j JhS҉>اƅ8{iN <`VBcG 9םǟk:C|fNE3MC'1,%jE޴hlT㵵Rw7C Ga<s |hٙfC$rv6A%{70_8Zj,؛\cB fv,bj6R<NDJɢ!|d[ }aG$DLn'Aʓtд?K?,%L,NNf  c. TwԏL*/ov1ϧ+.oQNT<" P}`C̒+c<_dۘwILs@u'fE@V/Y`ڇ h]:rSA  A5Bg3uuOKrPbGd z3MrB$c;;+Gîԁ[a 32]|͎Sà:F_+:wS"XtL=G#CEit72BTFK{Sv {&f8t' 8"n [7{Y`ϼ"1@bp:x N4Dmpj0ܿ>-x!VG1^<K Fd@n_篲g7G JTP{1()V<(c E:ll_N6>f7&&0[퐿{kk\- Q7تh0!ԩ`/ kFs+rfAHU-ÃT-9xK(.&Nl+}yVy >;dA'D3 vDKK*cB=xI ηjD{A\( aJ82j7LA x؆UK23zS(> ׋3 €ctnL 6v`^rRdV?)ɷKm20:W=D­!3ӞzQB dl\zW# հ{l楹ۙZږ\$IN 0csRk #tTeϽmjz+>'D11YG\K*q›͔wFmR!F-H8h;1`M_ާdOdSAӹ(8_4%=٧↻b5n*]/a<-T׫/覜 E>NenXfb|Ь5C:W?C$qv Mz|NlKVHDգ3w{$/u?@ƥ Îtw&?z_G0Y6b4?LL ON! ȀyWQ: ,[My,!^1&5=YOx H&NG",J{0Kxy6zn9lJn7l{eć{{yɩ_*)rruйS#+!^b}Q0+[ s[i?Ӿ{|2 o}6a6dSԇZ%g;`/ONc;Ut ;׽O| 59p-9h/{Y^,P;%S.aEt)*_$ [(fj[/Qϭh1,_gFP =e/-U)7ʰDoqGO)50SH8ЃƳjJwm I"N_|RՁ7suQ9n|fpEpO]T3nzȚ-dz01,}11H @-w! N͏x t#}=3,~+;7>N`}#Ig΅h}rO&ѥI "jK>*l7S͙!'6\vu8/O)U[ nCڀzQ39Nmۡ"KhOtjHLr_{F_忭de(0!Xɍ}/.FVHrӞI%u-+VB$<,,Ba- 8{2L %H/8s/7xL}1Z0~eQe-gD8ALVՃ+К8~1|IiPx>5r rC4 mKCI4I%@ ,yXۭ+؝Qe)h@;->lecL?6ctʍ ujDJH^EQ־ .Q'8 @qN0sLliW4(9fA1DFip4ay5$# ;(ecfK$m xʼnYcLdV*z6g^&s#,Nҡ(s04? H 9mZ^LPO`l6! C0_QLF^/yb"-J% !g(CIHjb–F<I)(ܠIow\ a 0`Сg8{jᢔw@h4}3rwge2Ok)XϞXnJY˵xC2zHZ{dZ{Lo/ܑ͓B!nPn q]5^j$ɍ_n JdXjn;z@;*Hw 9teֵǧQDtKD]&lD`Ŕ&+UeYk+eOw,YP,T˧Nt {0j8="tyV<|z1zF &9עOil?wՉ''әԊ_`H˝ǜAm#5' }O8}mNa)ioW?΋~>3A2u`y?!~><ͳ4P{aJ0npJ(1PxheD} gD JJph=x |sQ^\I$%Rtk%uL&puqw>=1;cPVipx+͛??q^'zWSvbĕE+KE;ʖ0>c>^2Lb&J7GEh'SN3cWHg G4V/.pY1e7Hݠ!.+b&[9Apŗg_i`Y3 !4J9ƹ#q+6WE!aw"Ñ^gEZ V☄C熁%*;azbOI.J9$a Xubd3~Ϊl^~/7_/їbɕߟ)]@jgUHerZ^[K"YfG3]37Z%[]um^A]P}/p+l>W6s[3G_9_,@o-ԎdVɏk6hPFZF@ [幠#;է;BQqӓ>{ӿB[2#gTJ YwUҜIT E]sP2Oyԛu>x6^RE¦bˋj6^rl#ntDQK"d&)}Yu~\NAJ#zxւV\|ʆŔ? hVB駲hI8gz/Wo7^UbbN? }ȘV`OCť͵z䇼,ƋpsZ2/s RfbwE \,h/q6p"4&n^e%2@FLm¿ ]ߩ΀R]=GZŻ|d߽Z!$i9;<|NڱBGy}q$ǮN+=^)P'cZң5_QUt-Sͺz7y M>7Svw*Ͷ.mIt(A>zSdnIw4/48}ecynoڭyz@Ί6U}{Wn<\{\-Yɥn"pquR )T9XׅOsTT]N[ ^QWޜ=c_iYM.1@>pA@UO~ B`L-ps0 ñn6tcۊhl^g< mZ]ވ6kFQ~GIpu#guw&ĥ=׭o'4ƣXdNbn ֊0T5c7C>2.k4=/u6Tg E*64DHyʄONvd_EmHl_"yo4*_ަ d}Z gE ly z,@=_b9\z8$g|F(Mt=ھ#?j>;qՏYV3a$`vBP:'Isg}-glyL?Aqi)63MLIRfln w=j^C X%gcgThZwIvD%aQ![<5:D?xOaMT} Hƴbԏro]d4 hxKyg듛q \L0nLH+Xr(+,FGQrp˰JYYxqF Ylc__PGtTb4-b+J筬s,ج7ݙ} <^nzPs?73G?/1uy]o/i %S׿Ճ,!QWf4Qj?Zɚ-: ϗN=`o|ɏSt "ͧqS3GY\x"+&&qx!Bm3דaICjGy0I= UO3X\K-kUe:f.f5mASS9xҔ'ΙFxsڵiwt̋(Qy\SY_n\ٗAq:Ňĝ&j! r_HDspcdx:u@:2^By!&x88ɈRύ|xTԋ{Srͨ/2T8 0+'/DFj-?-;0ֆYgNO* 9dj.z'N2epK^tWJi! r?{3v_~cIhCjRZ;h rc~^<@'l YAž޲+H#rS]sΖ ~%yNrT]^ڽ}&ѼϪ2+?zLHq~6&kb`#s.%)9CHjZܜs l 'ToSCe Sܧ4ROޏ_Zmz#:Wuw/t>+4ML/e.#u|t~Xk[Ǖ#}Y.{? a{bp{Ŵ2 fQ!z©׀ 0xD|2\U#$GH3*il`Jk§W(F}/kVk$\ֆbHT)-f^u>,??mz2=]|N} kc,5xgOQ sPq%- w+Hŭ 6"zJ}SW;.Lq2*KxӏWOM_P-xk_ ? SXRK~ǚp)Lv$C}4+刼/ixt{io9=>p1GY4uT>Ɲ"O(˨$&@x8ePά>[ ^5@a+Wgh* 6=_ s%;~]SѢ uOlDAU/4pDGQ&M0Kdt9>_~Y)u= 'X+q/q8V孃%5;m߉Kh`?x^Ùd-OpR ~aEۇ BÛ%g8{(lJkSʱ]/)S\P.{ZUhzN)@$Ur{*TD~GHW"h8?H3uӒKRsI@<&yN7O0,S\yt*XDʉTey3g "NBޣod\II~MD~*a$(29hJ* 1JvC`[x&5[mڌAHG ! ~,BhKZ P<3ע$"={[_@͞Dx7v )Y6?əˮL@W]]{OD<.95HY$ f׬tٞ=[JYA=8,Jݾpo{ѭ}@bbȁE%"f҈٪}~N6I79Kki`J}!|R(Hjެ+g_!Yp8ŲUIu`|X zW:3J[r!Xihʁ/4v㉸h(fԉe`cOR@P"ܖia<#K1-ڋ8Xx򨋌yJ*C!f$ݴ3.IoOaHT6W`( yww`>z9B_Ȫsg xQg^C w? z-lhy gҹ;"|m$⩖!'.XƯnC6 yEÌ%$m]6)WpRc 6ID`. O!B9WS*lo:'խpO#bPFAlA$H\ޫYZ_eP"(; F$6-%z([wըA UJƖVpN؄lAfIӞPGzTw22\EW*%D¾2?A~jfsGmR[&&-#3yGޕiJ~ݻ3teL EF|wйI3ښ `I9s&Ym=Qg xfING ~^K_4Z\m?_]N>=@O h󡔇2_x}\J\&'N W%Tx&Ԏw c#@' +I[,s]'p ğ4Bc_;0h,*gI@_qA[H~ZnjD䠰!ք3]Z d-`+NVJFÝxsO$ ~N hսyZ2z^(JnzmJfp&f~+2[ :VMlF/h8 ̈́ù'MbX<%c",}Ϳos1)Joa2Ҫ"ȞˆGe{fs5n̸sZ94 "_M 5>}|pNot~윸)Lag,"+eEJ0rH?y{FkO0:VU(/9Yk92&C3wbqɸQ4nw n 9u)fC>h!w \9 9>TtVX{ gfпt?n !8ܴ ;|ʪe1r$~ zr?4Pfݸ :̮rADq< !Ӡ{VvMv;mt??~Y=, WuϹYYS!v϶}N۞tp`K鞛'[+.);ƒ8 m*Fȅ_WXYikY4ĺjC>1sd-!y~9 d E<5~H_lL#::z'?]þ賟]\'|jD>)[T%\FŨM"Jd$˥G8mQ$S]jZz#Utrt_> gs0`H5^b")Y]Jf f>LF oaz01bjLjt9>ݠ0&r7nF==Qau)¼d{G_Q:W5}9 {] azb>+eCfPŀ4Z^q =ǐR38¢r}B?hـז$YPN~̞f!hڸr~#_TŽ6C?VI:o|h~V *]zy]Zݐr$\l3m R/Q"'c]S rUi k@mljE!K&IOs2.|5XRl#=9;$jʐO=y~Yn;}} .bfpl,ZS2*~;r ګz&آ(nNHfwktNJJxmr~Ւ_EkS)&^(aT'v[m\mPAЦ%o|>ߖ D,k@i„PEꊝufHw'g)zxǁ.Me /_G_!7s,{uN[5!{_Qt=@E?nsQ}K/3엤^%:k_\+\LȷS qVH^ :¦Tf,AzhܤZX4Aɧ8F[ⱗן1ks0/F<ku bޏd:Xhq][m{CNvY̚[(o =U+WOy-q*`sϹl?i,HSW"Y˧KO8r#_bl`VY-DEYXCG:Kc{sϡ5Q!bl[{؃f`%KyGLlFÕ뛭||Fٮ=@gO,w:^FLR~w=>Q@"G$w8=zβXDl?HPnt]>FI xx S 11nk dHYR9Jˮ#P@ /h"y| U^OCU8;py \ћ4q@, J~W}5]~r1fjuouMDmyԶ"v|^txBÈy,e:Ƃ%i.sO|R=&F=W:s$IE%\zl4'-j%^5h~<_T#sTb70("#:r*MIfIཱུyqfmqmel2~/@IDATˇsA8sӧdQ[*ĥUV׫pWN[וhԘ7X?sz5,{,fq6lufvjb(vm>K7-|\fem.Zd7躍$MD}*Uyfp7Sdḃν_ B/aچ^aIMtXzJ~Jqu#`}eH퀞h\2hK%~o6"6z/\E,M"ž+*QO41ao8nbtLõK^P!5:hvn>f^4r<[Y'5*=ۏkS KyUK%|ݺa˽0÷6|.I!8Ѐ2A_ Ɠ=p8J,咟 vļ ywV΁?RLvZ0X߂d! +'[YNu}K%EJ(sX@gҒJtjl\3> z&w?6 0z'caw]؅7FXLH ?|P{bqͻGϼ0{Wn '@<9aL$;;AVt/) Ίm|mlpYsGʊ>t(F-;s[SQ-sf~ -SijEՅ55a u)iU{MLFN,w~lփH;dBT4c:Pؓ4p&/U*K06,ἵ@ 1Gzn@ʶ /fjtNI~~p:[)iݓʕjI]t4qJ_{-h-k- JPRאt"A]Fss^F^1jX5: Z,&k4kD瓃>^,>qQ^PQe_A"ʓ%+S(L1wVI5lH|)e=vRTJxHm1J\@Ol57]*ޠM '8+~Ƚly.c >lF@O,C? ru4wH}缔5%ͥAIl~/N]>*>%y+l a2cة.4˜dt:S5gSޅMLu[; 1!dԉ 'O2UEj'&)ҺJYC@qDZ paq\t!oe=a:S x5o gP){ ͊j|o>߿K}0-L"%czsZ?eplet&3Zc{uDO9ꃻMR)-]7q-7XcԱVmoueTg(B-2T VVC⺓⊛k pվ\J/t\1Fmoy*?é|Zf<4at"D3ui#]=JGPFm<VKy>rJ|P1-&)u3Eh0 BU Ӵ_R!+90QZ佫$day\Vm~;о`X*Ǥ838{Fh!kH2axfm茹Z? _{o7<ރ[]g`_\U9Y8X_7 rSMlFrԦ3'Irm'&/҈':?.o%XŢӧ:Zrǎ c/sp,͵]l=1\wKoޕ]. i [R96zOPfGd.?wd4ӴRs$)۴Yb>U~3nC:͐mh+Ϥ׿R\E^pN9U DE}S'Βp@y7>RRi[oJ)tln 8^{j`;-H5>wmQ6:Q,kpdW /t O7 )PywmCt nV|o4K(Qef3TE8x2\'kI_>jˑ{**y?%WaXZȳpJRQ GWSM╳L3;c7M8a< #fHK-zVNNEJSCVm^5h:yAJZ0mm#1)g $g N [lC(?-> dxYS}ZhV T?aJ;UMHZZ{+&* ~so[Xl[a *nkAVB) y`i=}vE |A|=&#57} ҹlG)c`@=/>ɇ1E9jXPs2A ~\q *ʈ$?4gDZdҭ 8C?h斏𦤷./b DhUZ=2Us?Y}V4i!s'Gm?:-@߽e&G(_U04+C2I . XgR|_lNnd-! yABHu(xct3l ~V>eN]hx{,!LZeN8λhrns #a`Q23kG-vCt!-}3~$nx首'~P3A `|ק?y0V3GZb VIh pHzA;( j*.>*|PuyAC@WfQhHUV je5`k|N`Gۡl'ry5@#i֛!B [{|GK\}׍Ǡ|P&idP;fhgh2`5Do~뽒Ozzb!P)Գ2Ƣ<8#i dBZf H:'F!lx1SX =eġ4;bqP»ٯw'c 8ƶKsP|L@'( !O}u|Mښ >ǟhi J[ŕ&Ju*:w#1j=x{Q*9z_ NwνchD xl_MAOe5Ӟ}{<;%0]}&5V {yƤQWHo 'HJ\Fj'GsSݱDg Tg"$@>7a6Zῳկ',(vqCn5,>v@f.lJKettٮ*P:-#Jgg=&"tT!QC:SAeHmI?-f?g};;~z.HsDGƎ`+ m \2_1:ភARtYd;?ffFYCNlҔۊS 'UU8>ZB-k fq:\tdS\թ ItE&cqЊ%GtNQ<uxIȄ A[NJI., Q(@0=/AM-F׳"ZH\qO:e0^Zͽ[knptkiWv)lNHZjAS-~UD\ǥ.9ѝ 8|+d9Z{+`Zo!X\!NC|+ ~uVb-p-/UFU!Qvw\aj6}ۉwly?eR囫k6!pWuiA׻\0 K׭{*9'ؾG4$Ojq.}80DU"[Hq67-0y3k7%sA"YOy9)n}ެj)f#yXо8U?IV0[ IUNӥKؽ C滏eu<_Ue2WCGFw_ [1Ǹq9kt.T:*FU50`) ڒwCz=&hhrX/=-ty0wNj7"Ȯp)`֒,vIub*>hȀK^]W^׺Eo-K4| L봡fx NiajFT0sO>Q:YTz't<8:W/QX}ڠ,)?ew]+aAr(")A,փ9~f\+Eb(]+Q}{ӻIGX\` ̉7ã[weM'iī*$oռ=^X,TT'/O՜a{fVlH)1&5,o AfdkW4ʢdڲN1:=tkUV4COvcK B>ҧ0 u{5k_%D,:b+kQbd׿[sڅȺnU ǐ`ݚr\d'gUA5|!C`$+ >l45n6`9NR௛eHQM*J SEދn[;Ʃ |ZWOsJ6@#WOH_w1oG6oH?'/(DJ/QWy͈b hTڑ>׸fO$G=dcp=ɷC2p/yTǿo"))z4yB%I 8Ԭe YvFaɺsW4d)C[qߔLsdj\嚅*+={ 07 "$C- b#9mm- sf+?# eɺr;68uAJv̸I7JZ.B2(IE$zy~x/N8e/mxK @ }8@mIpvtjeAxzev&rXcCS(tYf՝N Vشi_$#@&ÃIGc'=Rydžaܿ0u )=S~crP]j9UpdDBK!h%mE"^k8BdI <*_y sMdofU:<>0vh면j*9ىt*#CXO IbAn u(QiCe /Ӟj ?-!O;did$՟0^jzw(n~ĭ/IE X^A LyNUs]V&b2Ra fj"OCPW ͠"LPV-4э0vSVva<]ƃև~Vk* Vz>"FW^YuY%~MPV"QfPճ0lՄee߽&F΅ ĐwCزh8&JXv,pNR?}k )4ʹ9öVo;-[NXu^'k4N|~yh]Q^tA򬭙2$نm *5u+;AT{Io\okre7~˽کAo[ü8!m+|\jw;Ha<^w~'֊FH4ճJL@ɶ\Hv9B7rz ]W]X Qs}}T䴏<BSbޠ\X P;$6k6| ~ovI ~5Guy{jӓ?i&ձVa' I5 yJ3?~^GG#I=nl~Ԑ>"~YV7LI8mS3E1N(3'7_ޖ&3+g(CwۦwE- HR%nu U,J뉼 {JY u.5{&q0|X?:F,a7خmSBc/TMGWe4XLI4!UaѷG%q+c9IE!#7cDZ'oSQ例#K; w„qO6vS!t +<=wk[SiN~* כC*= ?$כK EV4]-\ [EdGʿ}i hE`^qɟQ:;6P..bH4+dNg‰(QV_˃DY ;'ϥ{&e+& nbȾhfMoivP##]/AėH+lx vYf^J$jص/͐ϙhzpj<}+I;?B+[qh4Z*+,k'9bҦ"eu͇WCx /a,Nd@5jk~K#^p/'Ewn'S^ZUkbxti,JK ;Ȩs6R96YM*g h <` ]ξ|N^AT8-+-.㭼[`]BlX߬Y 4"z'JWC6wV?˦޸gv#TlVfzo9! o:Njs#*8Y Ey@ SzCݯ Nn^AD>g_Y.𦪩vE?9uϗ>rP+i h /E\3C(a>+\w60n<;n 0 2lƷHK)m:b%_!#d2VJ-㽽|^y~J#tjiwGf2_)b&ů$ܬYcֲO2ޛI⒈yR=IVL0Ʊ87 0֣`xVN#tix_: ՘:l:1qC|(z2BόRGַO <9앦O=3{gӂЙFgnڒB[(z>JA,F;vǣLK*⬬.$-\*j6]`tvv,Nߞwsqjlaߕ7_R.#. bNjRUv:}DO5PF}WGDi'P?aRU07g֛H{މaztYVA"#(̫hy֩H-|p;+=m}c;h^sN88/^6v^*8j`iү5x~D#`(?$Si1|QDٗ$LGa9FZotKC- dZA7oaA\jBmL_[7^Bv '^E z3~3՜GJSH:`Cfq.}8I!롬ɓp\R$(E$æ2SRkoSӑ\|b}FRPӖ2" )8rl`k-NX0إ=?h>83 ~ 0ľ'.0,jV1Y:U)i%@b&L)^ \&0?A e# uc5D!l[Ɨt@@Em&:@B] c+ s;_{W;0qcUd!oo!''w+N<ᨨ9S_N'^%JjbeKQy#><ϭNOKʹmH [ϝ|^=2R |s+a T߹?m_<߫+jmUtddFD[50č mf-H$7GvRqn :p>!&}<МkX'lYr'o%:P1dg?/\D K 5))WdJ*T rdHYnn0DʇsK0#nK ZtOk"C5 ā/D= RvfzW됖 *rDJ#My5̒jWD:|U-Q%EO4miͮět yg?'V-0I'mm|ۛsUcU@I 1^ՋXPܗK#y2.D*)tAYVIJ8NF@Na!b]#+WF?0+d3+[j+YٺV[o}IXn+DG B-*zgmͣhGI^L!2hoo(FnѴGGP+[>KZF+*HC$rS~=X|/eutbD@|uaa&) _Sm#!,zCz޹e-p[îUr7>ոc&';򕮤*-OSf(!ѹ4RKEK_.M9eұdllS7fC@1'b϶69[th)z?J#ms){SVM5#\MIMNMH>[bSYDKX:r\/',#ݫb F|Fz3}e)PF窔R"2Y{CU6APĎ ʣVMQ}M96;_+8d _V[Z~^/U7u*irhpH`dai]K`;_1&Az Dl"`D~O.$`7v Q8r7ꎌ?VYzn=pzJ0^& QW^*cN"܂eF&7Q]b[hH+EjMnGVܩRc{ w ʀV/?'+֚_Fъ9FXvX(!j]qT)#k4*V~}i K՘'8Y0qHl2`r$ڔc!ܟ h~zv/v|lT5N d-Y+wF7{rpR Y'ekx*}P+gϩ_88}Ir9eKw0Cg#yD?ZŽoIU,gɝr,-a*j{8b8Us-BY0(M)6):ZfZ5Y]_pf, ׭;=Q Vq-8/;PU:o f~oJ{ [Igm&1æ.9,&QX|2ms 00 +Vbb(jSYae׬SMj* S⷟q?@Kf h#<ʲj]=#"%J}9%V%L9ٴIcW5yN/leL:G; *ƒ.iIХzzcaaVX^-$ }otv&MLKWjm#aAk0m7rX*YJݿD *  5653ls%v m9(D<3qfKô eo{Ϗe.VH<Å9,{xm ec!&ܳ~戼(ڡxF:ByKhW*,_=RyK@G9I2Z/Zi5WvpugrTH52Y âoDz/013!{s@w˴/N/fb ,L2P -ֶl]%4[WXOWۧX+ɫ+fɇL5b\~/k.ԌV#!RJpںLӃHٗ$Zoـĭe3ׇ" oѰ0`)Q}Yƈ8`0ӏt[|*&UpIl`gzV ~{䯆ÜGfbFÂh1ﰫ^79+T[3Rs#z a4{79$V~dQ@η[Wwz}]9mfhKus[ŠvXPniݓGƴI~ܦeGTg:jz@| 9WNA "_&?)W.|>?dy&5Q)Ijj)0GR.ko΄ZVjCeoRoGV3q],76yPȦ>g7&˟ OeW$%sF>$bJbHqqtEx"}.Boqָ:+2RzX:i$̉IӺS2gWͰΧ1:w}o .L=PC}y]ʶ[)G4_eQա)PbSU4evO$fA 2hMP  ^-VvPH)}RP_yS>{ld'C|ȟ@XY4P43;3ʅe2.J4]=u+ۑ0yĖAgU^ɣu,@޳G3M;ޛ&mUeY"h{gvgGH } _waAXizw43l2+]9@7fȪ̈syI`*-U(e]t'e>_p sӑk 3.jJTo(3Wn@'8ގ6ȍ+ʼ:Y#1_x|?Z=#`xƞ:B ~(("!G?2)S2Sob.%x(0>qcNK씦7aJJqHfmץk7Y0ǻg!~nJI\Ū{Ms:8Ay5~ִG,Lr#o3hjI5bY1-k5e} `<,q0vJ"NVS'RܛIc̍'b0+fI_nmh}vҺSX=z6mUfw+TR$ȕr#(m>>iw= e;.P%c+,y|ALbqϰOn(T ̱Kٶl;f%4ႎ*۴w*qkϭGy^~P){i 5unNH$SJїV債@M*gH |E*m_wb)}ǀ =Sxj|pQHي#2aBTZkY=ۥZUz#i>T =!m eBɷK8T>1#fG_#\]aOBjUAT cO̟4>˃֮#{{A $xedUuZޖz?tNӛٜadd+W#.2EIتf[0ωOS#Ÿc_&,⛅_Wx3o]o'}쌴*bϸ  ڭ8X_26#i+6`˕OȡR+wk/x[jCbjσ #Vނ(]2C*h#!&G\X+P6Vb9grGJV@It3oCVGv$'R.>~IQ;8O IuM ''=amfL_D9U==,i\x'SB'"&smlGfyAufU 1 |\Dy~Iˊg[>Qa(y5L,q˭pY]zW ?5o=BU$w%ݤ4Ax J+Ȇ DtjFpR0ҦODctB1PHkzp~' mmuD.ǯix96`X*r썆 L<;h0?Am)5Cl}CYl(zp-ϯd6u=c_wN?%Z08*Q4*qyZj$TcҿA|T8|cPֵrݵШjuIxPccԕ89,0?ࢬG,& ԩQ1@sJI+ssm<>jMaCE7!s/dHkY1YXz0gW_&?(|h2 l՚ d^Cm]ei6<4/Q=Pt9HÉHWڤ^k[y/5p7$ўac[I]EPISi8q@6=:Dd]FR"^ A31 -_ֻ̓ ydB) gC{ڍ&9PI%iR("D%yN:dB 2>)NO3gKOQc.k_Kv¢SVd: v9ap[jJ)"ЄmGk>9[ߎ;XkS%3[Q1d~t=(16z9`,RQ}P|CZ::XSpN'on/QZœqM$ӿ_PNX: (W)M&>J"\Iey +Ju~.>0=||:iRG\fB {~ӎŎdkZvLl(;|dㄠ~5Nߟf֟$ֳSH95K)H< J" lds- 9t!e!H~xfj<~W1㫙%2 hWR }5>\L`.oWk[U;Hqǟ/E5}""ݻ#3BZnAI x[ծܳ|{(wAd3ʝ Pc0X6@fgۘ'_IqBR)͉ٙ‘%P~iPnܴycN'5qW‹ZǞ39Y {T*G%oC·V$X|QYRx&Q^bH3g[@3N2` Zr)kK}Tè 8FzW$ _zB ν#PAau(eTjWX"~P ,'N_Qͷr/J۪DMŽ^XNe4yǣ|D#;>)i7:|TemPs(վY͸i7_j*lzn_VՊ8frkTyO6 P:$cח< X@s<]w&ۮNyd.;Ḯ'@^C^۸}Fy:xbywKzr<[YVm*Em |o XҬG)(k&;ÂME5(ZrNfCPckkЅ _iȚ&\ ;YSbI&Kx۩_}k$SMꄶaߎcJqi.&2z9wfY_9k  9&.d*3"M m Mhir(C&lלJ $@qqi_jV|(AfBi!/|v0vLG OLZ@Y"ޓ22Gʳʤ!\/RII3##~G3rsvx؁z~P-Gb.~9}@d~(XK=5`2U4yX_븵r>5$Zb}jX:LNVr$5TQ~/@*lj7PB0i.FZ bIW,T5,*]FNT]ljOUW\oY<Ȋd{% '+]*CL"Dt-#$mQ{- X.+ȃQ8+'1puo|"dFN >li ~RnU0jCz)KMIp$8rd1KbOJ&zP*@uPMy gLx@i:ն3+F >\{9I㕭{c+q0pMx(mqdp)sR剽[k9VI| >sv>j\^:FǏOwqSLoz[sK%}ػ %Ӂ2L%t[yqe6o[}PX%$^!tP9FQ r&O xT0( Ӣb% FM 4~*f3i`=:bߕX,[伷b H >zrA/iϮ$1@CרX466A7s#:ӽ5 䔋e_ȱ-G,T[sͩHP]-!P ܻHIhۈ+fReP\-|$6mbȻBX{~"}r4Ӣ{*P~7ES`ZeP.eo[T1bfkOk!#&-0r8H耷\ kg)&ϑ8 w;_ zpnY85Om?tBʆ!3DLIYxd82)$f!DqҸ_ޠjCH 8%_>;BCN H {^=&9ldme?~(͝.‡%ݴzƚ"/(bmTPB,'f4d诀U7HwDQ3<2vLnf2!f)t♛ 09\.{NZAș&DvCƅ):?(?cWÂo!]v MDsf[\P{SؽoxD)S.S[d :a`.v{7MM#4iDj/t"Vnb22J{ 7 AgZiEZTHFnQS%OE"jrοpv9 j /7.]p ]gu{i/@&,$r &2.WKw]d:x`D0}J-cϼ;DϳMONĎ*+IH.P}PP8X@i xvd:q|({x V_C5kf. bE7I=tYs*Fio GT=g'neȃ&scstӾkyĊ;IF GKYkb5 d\~l Ӄ] &ˑe^ͧߡ┭eߑpq]d^r]Yr]t4(u>&yWc c624gHjڈW lGE0E?5/gMg!A&Cd9Nq*MOKOTټo sYuUwdu,>#oHEF6PO!\0>\Nn\bX04oUˇI bL@AGQ`fWpyӅ#+Bӳ(jl&rVr`LD숌 mH׬E6Ld~ϸ HrF` 缣Ӡ4H2Ekܞ;2*ENxxHڋ됅 e2T\+AoujB-C܆53;B|TZTQq'z -5G{'8Q!y~1[f }ϖ7mc(jok 6 hrjij+F+[r/驵gZ.B2ߵ OM㜘{ѸAYIO}pdP/^5tJu=۱x8O8IyN#Pۮ=TQЋ7O.Sw|fn?ݷ{e>ebBG3 L@J¬mg=lmׄ[ȊV&2ؤO$;qo^LKhNzq4՟:]Ck'~Mg>] 5 7b2}H0?aǢ.<,Ol&:F-J[EN~t?>zRA3ÚI1`}vل_˲k˷-~q)dn~.DT"xD%M&)1ϙR8Z W<+YTh!>oxtT/K9IY{TJBhQwi AhI, l†qx ^"1lOa)ɦ3MO ĭf!]*Pk BV?Zm-Ck4~8{xD[wV!Hl?UpdɬfXQk}ܐ9 T;gŐAu0d^7\+b&j)b0z݌f_0~{[ٻw/Juݹ$&'FA0+Ƹ#~G}NoڐcZ9]4^+o; Sȧ^p^QO\'1Rӓiu}Gz_+/@͚cIܫj'!e/[W1i"E5sWН:Mai缾ؽyujs;1,@ץ9Nŝ6p0"<ݡ X_2\{ۜh E $eOt#+Sp~Ju&]~d Ẕ9H%n'YL'ݮҰZ?oPU5#+mkos&3saq+g\r2kۇ__5§,@p/lsZ_ =aAD*nyS7ݯP-VM(Y\<{[ѓn %W>:ĔPar''oNa(v62/u[i4B` Leఖ]cj[,}Xx# h2 QevŮ5Bx$/٧;o2 % ;||wQg`5 ZFѡg=B]ays( Fq2⮌j0m ~faO{Gvq;!=57fQ5l5zUԽ%zNg J:? lG: qWA:~VslbЧ!QRcj}وfW` jf'&>,vgf /2 Q=R),KeeޠFe,Ϋ̈́NjR.B6/7+uJ>9=G ޺fgsyP6<#oc*rmŐɪ0Ɓtk .S[Uw|e8{WacHfYsJr+]yxM#K ]ʁ< !k,]طe-J yݧU-Vͫu9bWߩP <|4cӃWR, tU5?h&6gK)Exj ?biHy &N #WGNH]%#}oY</leۨ Qs abLb,eZJ#BL&&O1؜{ڷmXFZ`<S[j'jߧ쨌9dƎ0ckP=-4O@.W%E~&^6(d-{LUې7]Cfx(w1I\͝wuaE~6VbwnCɘi6˷PY[}ȺvK(iDGf>PLjHFGclIlzDim 9zԔ+D>B2 Y̑~d-%K7 ;|԰U_dJ5-#O&Fd,D_Ub0<'_Ue:suB# σ\ldW[_j׶,GNTNeƲ[bYtH?7& b3ګ@~DtZQ ֞s/{,"~[f4L37؋Waѡ!{h BHOGnF5gbEWJ{+L8Lɵn+О t)Wf@pG2LER_Nd%ezvCC-!\wt10ZBgXYDP68xَk 3OYU<Ȕg0gLfάEf1} έ )齶jl^抉dm!Cjc[_uFSƗaZ6,:3=`Vb5+ϏU o ;79N{B4M f޿|,̳Sd($1Ol\ݮ,.Ep/QߍO4ƅ`T9{BmJR: rdJ1bi(܇mv$Gz=x|tLjr5?݀/RUV|婬Z;dWMOYK&י0,>`c5h8ߢ E_MtDxsW- uqaUrM>Ș˳;%񝅶Б:[/}KY"tC&O3T׊C!yVa- z{k>+<b.Qu׫fpIeOn$;k+˔#GQk-ZiDIL٭ma,äDQ.k\ 8yiEVL7__Lwŗ?=H}-=MˈgFx^0}Ńg}/^J(8fBmVϣGT/ک"ke^eSѥ?O iB{Is3aŔ.?k9nNCmBDٵ;U MxJMbBn-{$!#qdK*֘ rY~=]8bN JcH>O FLj3N0Χ4A, J zKSqI(*b>&ȳ;/Vbxp8%燍<@ ;#_7!RSz;te=D"fs.9qKs\ @|@Շ<ƥS67@{|W4ߔ;׊9Y>{~IR%'шyMf`\ \,]AMrưuţwzy΃<^SuU`RqaoكwOPu9T7h TtKh6Smx;(X(uy'8ϯ^OLm;tnd,P˧h`]Vd%]q2ZŔMb!df^l:&"ȋ]*651_ "@=ygwFӐ*b_ { uUB&FA mޙ&4W͆9VOXg=;gT/ K:.a9 O-#-6$־U QHD'sbN+;N%DVɍK)R-e#լ-챞5>8#65dSҼbzp dAYmzvitRbCOz5C[ٚڢtմ]K&,grAef,漪ӡ"W̓OTtv[XI#L=n-tOg Kvl'P;Y焂zetTL:?bJ пHtU 'ԃ"}I4;%byjN)y+`H>OUvZC}`8}?]DbRnMH٫{R>PׯӞ|rg4?d;:U\gNVfdݜ#ɚy8u)D) b9vTlfֽbQkG]1z" {ع޾VɵhtZ85Wsu!ޓ~fJ֬K{}9Bi,LCFa8e]IuEIh?Bc\?V&\ f*=6:7&&5L.O 'J7RIVZ^aq?*Kn7]mΆij>ێ0}' AiWqڏ5C@m]dJS?ce p"zp|u_ߍo^W* 2,gk>#$N'ywBp>)}BS3t жMmʅ^CdžHj8GA& Z;oD:K[d(SM\1=ːgeLo]q hZ=?DPlIdv95Vo4WYlE/7CC i ."ϿxGQZ0p`J3,h[[fSj(̷j!91^?\|=B|~h=bJSlWGeȊ^xǒ{YG?j%_Ys8ؼcrpw"0>Ƹe-MEx T@a t.UIS#]x'^hg1Lo4's-_, ME2Aϑ~ZN?,,;`E@ZK3Jq<Un^( k+ }r~BD:E jObHq XsX`rŦ`ͱl4gO5͟r@da)O*mB{{_m RH^}Xn(OFTUa/<}{~ػG}=˽9},6}+Vz.L {2͸L4Ɉxp@-ko\ۺlCHCuVqqOڕo=Nq)JX~@)Cdnfb%tm/L)wMYVDJcXϪ]L)rYņWo{'P$wv"t7.m6x$|˯-BZ.. ԶJ c=aXPcX%@,/Q~ 7Խ6Ǎ2*fELKY87PŠ&P?fi郮xsP`}̷?4j<44Ld bh.H]q~D(o}xr5>tG\s\Ÿ_3+UPE!Ai?um켙s{iWv"~R^bfW'ˡLN-6RhF*b-K['˼ٱPKVйPșd35rϕH862ۃV/kbHJuA?sVzO_<\# Mfa7EFN^VJi \򣵹esuswy5 8LT>8v f Θ(Io!Hw&?+G_[^w Lؕx $KHPȏSK ڶ*bݽ!,.䂟42WRGfD=!K2Z4`8k 9%(~s9U{rE9GKФnc!"O񧝧ҙ/b\9K]x ({Q#n7TK(HHb${y<|ۜ?>g̷E9|'k7{z@r Ys#¢6Z@Bu' tz o@FNKMX ΥE9)nڼWVN͞rzaθV[/;2ՙb!{0R틢6@IDAT&&5+3#&[6ω ^_ c1:̔f6MwPPO!5,B(&"~ 5MCul0Zge)C m(O݈mo5dNrL'=V2iD<椭 j|y}z-!(,kV[qOwX)&аk+d+kuAh^Dg] i 쟍ڻF\k 1m思MU~JC?ܱ#zߐaGݹp! Y()8 8O'R;)3oIylY cM5٤wj[i3ηmvzQ/>cψ(=\YmI_kq$mJU{'gdN@A;Ӭ5m(y⒞ׇWF᪏*z41WuQ+4r|]q'&Y*,BM~Y^#*I8}~w` Q7n|;EX߁ JikNI&3 +{+ګg=c@a& ˉm:sAiC ug:-÷Slq-0e5C䤀 en4D OΧs(C Jjiq{C]>6;Þ-dKgc0>>ak"³\a Fة諅X.d5T! := :41L(&.&VUVRSf{QϷh֝ۗQGdd]\t׼=@ٹ5C[a2vtZ^7d@Ij"v{Z'XdpF\:#3ql~+n%s\@ nuoU'zĶK@ E[KPgw矂ik#m{%,P:d̅rþ١=LN]E<7t6 Г$FN%2m/> lζRҫ {߷^ң M'Mh_Τs`;~Q,=bBש>cqC Ѷ/<^/A2X c#f:̀V38~ET5ΊGU_ܐvbah%4-UV)-8J {g!0uVU},%1JD;Wk/[xYLΕ^+vA4xH@m NA%ޑ(:/!`T;si!72ڦ g_^k- Io'Zq#9טrяwVP5UrPr?i )Q3k2,&}lrb꯵Lt:wFs\Eà,,@Cu!:5'T[`@ssJ(tBpۚ%sO[VH.f~3OI)zsUab[˩S٦HRHG/B$n^,L۫5I<?3y߫_FX 41 ?C5ףjÆ7-z͔,Ȓ2p^4UJZh=Ԍ|rGIx/_2S!fƾ~gE$EXڷmX{'.,sQ8Bؤ̔mM9p8A$qxzGHa}ĺqif~V[}E7NG4tRfeu ӗ 'o85HJ&A+oK&N"^7idIs ҜboJ#VpDxd-Jꎎc;kd:B+e5V50T] o];EYZ4wbNMC_\o?\lHӢLk~wH1hU ygbu-όZG'Mբ}"m3qi uc H#DSz9Ds eo`_B YO2{w?8jU\Djw{)Z0l7Hó~~:[O?ŦCmCR5)TW?D~L/sFN8 ~Vꥦ Q86&_v]I 42{poN-{Fr~*x?;zDg(i0PWlߧDwľ@fCVZcFA54QDĺLѥ@O#q`G4xࢦ:6u8Odon>L]fosn'ԱOf<u,Igd6Ak2\KkwȒ)i6_[|+fF~#ܼK *NukY%M&`O8m]p^uqQjJ"b4 k(ݸۡċ9zzaxvt0텰{ kv9$ N%Գ xu1)*A0.~j"a8pqJ!UKeؓ˃vlɃ 2cH#.) ױ}7{㫉/9!m{BM&%/-UZz߂Y'tx]2,ūƔCf__j52ٶl[1y75ۯcw:YIm((ZSYY&Іg7֙q<6tT2S .' 9Yڅw// T~dȊ@R~?h-G6S0_ \zޟaF j㤢L)!'ίK'(- TR骠rGDv`ӉNVѦ0IK,0 pznհ!ݙd49Cp+ g_a ש˴?~&R逥r;ʹmj<3>02V}.N{:eQi{ .\O=uivgw5醿G Oz_=Ou߾LK2?=q`CkToujB)v3IX%VsՃy~ 2F ,j,y},6'Ҁq"ƻ9EF ^ʞ/𪪸nh=Y#V^JV2RlR d5e[Gj`I־h@ ҺI޺ؖV hJI>' ;4=1(G왹D'+re ܇/="7ѤzA7e:IJޡCx:$D'6u_π>KՔ3 Ҕi1sEg>BWGϏצJM4L,%: {]xt;CeH hv1߼>ϷUV!ݷa3z{&XL g#YsTüfݾe ܡƧԚDr) '4;?n hCxw9#> JX?y _\p ]XG{lþ-k{چ< ;BsEpRhSa)D&Ho(/zFaluĩ=o )4:Y3n%u Od27cEG[m[4juY00Iarٍw4Lܢ{Ud?ggUBd7+ }hW73$1%0Tx;X7k)RbXyJ 3y汱T~sYx\|]xnԴ VHjX|ĎI^ludO chj ŃT}'1N fq<=s{j0ߔ<Nk M^ƒA,pmݻe쓂Uׯ.w'Glzl+#><k: tZ8I~,߽n#m9cO@G+؈}<%`jNkTaz9Ccof5*F evf@m}E;&Gʴl吓e_,ZD?{([9MXdb-rn>Iǝ~=lt"#^@?foau9ݻaCYS$~T&/QުF6ֽ0XEp83Ʌ8 ~{RZ[tEɷNjKQ&F_jW"nDm"%vfvMƏVmj.wx' RC_54́dHKB/%TսhJ(?Gsq3 ]~*aY`JۘԸ6cqi6~6B7vi!6%ݤ3'cRR^[2`H.\gk{dkwF:6VIygҫ2Thz7c4ٮIKˤx!_0d6O1xӏY/5O?Cւ&Zm7̤$̿^?0AWtĿ^ř/ȟ.w"]W4#GmJ&[Ʃ恡/xmi< NC\ dgy9;9߬2s0ܱNg2BZ} o& ~-O476sUCzӊcSfm߸IA7)窓l2#^ejz(PլNr~BCO}l˕"0'_y&&|Y?B.Ra K‡Q4> @RvLzhzb<hv-qWL =fL2 }du앉#OŷZt/d'D-SKh"0WT_k\y@\-!q>}GjH#y[LZics7@߾ÒTr[C]_LT{63֐~PEQex!P@n4+o`ť6W4X>|e/&4g$Z< :AgQlFTv(SBniI.S{qC:_.r‘gLD-A&07>bޗeLļ0Z.Ju3S#T"U0&/Ju) D Q_ @E)b+)Oξ2:X- %b"nzԋsJ1eOSJIXx\:=!S,s[b4i^l$F?z.Rue,JJֹX ʺ{%瓸7.9¢#/hE2 2B|>xIAʧcC]‘YVnG\(\ *!йY|:Fer `T>5^IlftaCH棓b71<~B11JB^C/@ pjvӖ:#XwtR5V ]yPsfe*R>ouB:GCWf正(7I|p~ B'o8JC1:'f`i ft)I3 `q,燊pjnhbAmx31KN"IMߴJ{#LZ )/öuj:e66yq"0H=wCl b}bZqY?tC2 pd̲1Jqjzm9j=ԋz 퍙Lus1RէW4" ttXBS5q`SOe4U~"RZ<b.V^m١x*\PI,X]hdS{@֌ZW.$D]YBYc0H~W$Ĕ!ѵ4Kb<^l}[Lu'M;yAK㭮d fH1vlSby ڀgR"GG5ɔ*M&Ɨ 7J8;q>?Mbf(;h^^[>[1$[O{ʱA2㵜WM(G/*)Uueا󆍷Ȑbea"urQ E:S?~a%<4E <=ח58ĞH;jSCrt֫Y4Pn;ߴ*sqAѸ 1̏U[zFm4x)LL/XEߜZR Nl^qTec{r TB`]n`.ѱޚ` M^z񻦡NeV+ŸUÎp֮p }T ^v"Uۜp#?oD!_ u}~GXix1mk̠Y]/+_cys$#H>e *};jOK3̎N;az^Ѓ>h/An`Ѝ~mjjZ#k܅۝<ٖ$1!cgd~Vo.b#aSD[.!G"8Kٝ#|M@IӦ} {.[up\$E*^#*L|\1Dx>}XX@,CM&n=xvZ"#ǦP_Ĉt|r92Wwy3xAwtDѸnH;K=1Ȯ;q.D}'>&α7j"0t3T2CǶŃNZ1)W$UfVɦJ4S@}Y J0i$d1W:Vt]@pO˓N-zaNj`j8m0L(fU5m@rhe9kF T':BM &[\83}FzQ5!_9za;a?sV-DEߌvaaс>J 0ko` pzw>r8A:`EB5i|翔UgXA=83zͳz@+gAs ~4m%~|n Mg`}FE֝=c O2˾6Ckva) #@5Pɇ7»F,v˱X[oZ/M҉p Pܙ/nM5ԷGBX}Vt$6ȃchg'0DGMpz:Ak؛.R@>E2l~hs_# 79wczLIWG9 Lg&=vAW0b$|HE. ޸$E'+qaf?Ln5tmAC?c)c:3u9^`n v0 "Qɪl{gRܕJ[MPJ6 r֊нw P!0WEt֫ lzL/N} ҇6WEԴ<Ӫpo5` H]!VѾ^d#gr_Ñ mǶ;6N riLf^|Iќ~Ae|LJ^RlK}!I12fcnm2E#OӢT84x[s=zƺ90kֺ@1_~{%B9:\ky GUpIRJPES9m*ش@Nʹ)V}=v>*l[܅_] WHH#5x37c9&VL`Q?Q6? `4lVtJtS3<) oo/^ÕukʾNW:VyD4Q~QGյ T* N/^~ADeDukO- r Lj_JٛےAKShL 0lrM$_͖`G>UΒJf-'_[(Au C#i.C둰f7;ݞ4֨\ Px;"*>Tbjd2q'7cn!pvnN뾡 @V,@4(6*$#D+s/Kv@pWAf$7K5ʹu?+bv3w3+'I;R"bg$)aLےjLV5|Av0mG}U[y~{~7ex:t|Tg֗F/k/%5M`,Ax)Pw@YhV"hNNv}3^L6aȃGInU4([E}wIS;LBoN c63sFo(9⓳뙲[w']Mag~ɧ߷$#ylzWSqYR{yTz?ږlO!HTX\1BYaK>ֲKR񊈍XTaڄ]B ]{k|xi. ڦ^.$hsO{^sk)x).w\(X=Pi,@ D"M NH bţ-d,GͿ&wLQpiP jb.BR5U' `)$$Dj\lA?+~WKS96%˒Xb( YMt,]VI>꒔A܉:jsݟuab@}XmUI3'J 7EXE-Vqn=^ ͓>_4H;P2z5fYlO2,O x7\.lC^ciq Ladɺ>u YzI@bl Z(Z+e~Od8e6}KQ43,e߬Jq 94)@9e_IOYń_T; -qо]g} u;]ϭpRAmd7l`[gO4':,tZRRvS/~`2.zi DbeNWj$/ !z3:trhU)J L@13uk(%cG~h)0R-x&[[tV6JRhv1N'5`QFXN 9T Cj2A0$k~Kc e>j~DqBg7;R$IrzlQI"~>d_P(JROeJA9s=J:EkkJjn(vʅp~w!=t(~J,Od+5*p0~)0'$G'Ggˈ'H _Erm3m;0t&#73o81 um³[w80FeU.a-Ŧ@+7gJJtmQA _dG uX. Z+dribHTeI+Y_Lq\Ap4YM׸ԓ=WW=~trB$y'@@k7$4F/^%> ] &ʯloQY5,p[%fƇ>ntd .a|VA$0g j ;]42wAk0bn5KRHI7ٮCP#1ݎ-عϸaq]>+> ڍv:XL-> ]'+HS dɁT3^Ⱦaֶ.3o4q8R,gmTkǪg`*Nd2Ӓ=i2IƲ_ھ{c 9>ySn)chs$FN1P,΢K@J9[z^t{4OPF^>,]ӯXnơb\ELvat#sbv8*I'eWI'V+i b /:iF|@TwP%d9PT4vvx $l7=AdqLK] 7"˲ \;~(=5Xe&| eɹbKA|Ldad.Q.4u݉Յ?L'LzhV`bpvd›TX`YO61 n̑6MwPI PN`3I:`snF7K]ϘՈ+ugD1F{%.c%{ PXBS!whf27%- ?87@(z]s!}z^_t)xiPUxNgVn@M7vwP_A[lW@VCNm{F%8m.NCB('D8o;3D,JLP1 TuaX"Uy]Y s~v{js602Jv7GㆬIu^x[': Z 2饵yo uO8J,UM&x  1H?/ZV)@Đ5N*АdqO36=K' ܐ8כ50P[I:LRsGd֜Q7@F9|9j?W1),ʮ/ȼn'?1_НS\zv.x[qHu.o썒Mb&ML6a־BoV\k:Y>ԛp^(يۻYԟeB^Di3i) dTŰC2O0Y2;;b_#q8JVi?$J6boϺk8 O͚{_UnZDUL/!6˫ R|}05lqxLԙ5dI& m5lI5JքS s+,ȹ8z#H KFidVB^RAI#zQI㟆oT=X.٨ ע2jR eJOUWH?x~FiJTboH',ѬC [,7z MQD8[ W e*Qnjd?Ij#ߏ [a楠rϬ foh2?5۵-!&vşӵ_g I!Sq.Di6 Gz6oEwO͕Oyε! pW?lͼ0'$2.uj {%ń- z02S;X$eA̘—yPvеs>$1ncbrO *HKV֪jmLs@=|g}j'l+Nr0g/WIP;J+!laV'53i1|oW♔~Ҡ UM0dI&[$S$,A*=0?t) TʴP}ف^k8++AѪT+%NC&ɮ!U)0r?ljūlY;7D>>KbP'-|}6=3@Gaay_}%iKx=*:W^xe eNS7GdCl4Ģh᱐x&O~q g ,[$Czї /mq Aů͊#{mQ¾c^59;W/LRprYr.w{w`i٨qΏ HR+tJJ͐) kYEaiˑw!Sa݄+]'`?KƁ'נ \2/trHl'Hl FgStYa ҩM-Ք:Qv@!(iW/(z}` ey[)qZy[4"u}/`{4BJ ^PW@!&dypg|ddwEZ25ojVMU_A+Ypъgv[:|>j[l!XjDװsitao 8rZXG= e~@cbϽCAfUw4\UԸݑoNWnv'j )Zw;P5USnGϷ ($ܞҚ%U1k\5Z[Įܒ3UU[v^iLiO zUj۴s=Z3Dy#TRY}סּbdϜALѣ0.EqYg~1UJ\Q$FjAQpC$LSzd֠ARqԋv(2,rBh;wp4ٽh:U>m꩚?.=u=[ b?zן̍"c;kO[m{CSD@BѠζڂms*sy:t_5 ΘYڥד& w,A O{^:NUj@=|3)**XEھ{-߯]6  ~ 5XN׵OzYҏ4`j5ݬD|{ .뺝_EwdN\QncJT|&J.u==7GLy@I׊"qzN1wsQAi@IDATBsr =Zm4W OHKO)O(')ʞn $L[N;/z;R>?sƒ8zs uf+pu0MmA\fv(W'O{Q02ˁ\PNTac^iNS&Kx _? f=Z&"}8T755o.{OS 52 ,IQ JȐXz:Nk:bkXi>ǣvTP<7y}pUn {l*z7&oFEḯؚsOař7TvMڱg36?ܾ6Y'K`w)f[>)χyp#&V Lu~cJߜFb$)g)ۖS< H#+#l!̤g":I/>(`\i]`\qc~5匧"QS~Nי/o2r/ PtDֶ*b( ahiy#wU ;&vmSDSҾw!o8::iv ˛/N,-nCiN[Ÿqa)%rFa'fs-9D?0FٞLH>s^ŭKFu$L{qt3#@%slO: w.J^9zNF0/>A]z/v)g_R(֚oOzv0Jcaur:;nQ7!"$zIIrsIM dh!Ȱ Od6GaiOc[4:RD/:4{Hx JM-/dT톫d|.R1^h|`/QLjRS+y$_1UxK"_UI%ʨ\Qw^_me% aBï2oyaPR:OϚk9)%r=oΡR=}V6*/ -9v'ݸ-4p/]|9{zuUngYޖ݆?L`\V{t"6Q7+n\ʜdԾ0!Q~ W rַ`{Ǯ [δXt?h;^vm5zCD4< veo1p<|PsxSr"s}5~Snae9vP 4zC2id3}BC|0L̇Ӱ!HiW#ؾ6ύFs:2٬pOcJ ]LtTTYu\VR|R 8Kl V'7^|=6d%bj?xg/Z&UmFF-P9VxڇN+=j0bfБNTL=by.{U "(ê'G b\EQ|Z!%zDph%Iqnȁ-CR#!_S3hql~Y 2 ֥荵+6K'+xqH,5)/e sSOU_5_u1 X`H'}WL s{oqMr'D1WAD/% FE6'dnl,:w} Fь CdְN+AH1CnXZ $=v3vY|STf5!}08tY/Tܴ_}^2 'J:U?ΚB *z7:<(y_{NUWsDB_-ȸ?\ɠʖLR w1ܡ!9كTӳp#)_cQ>@ukAhEu =hsUU?sR_T $L602WfncJNuL(2ҭ:Bc+|`!4gtSڑ` \Z41>.&-~A7MՊof!yRa=af&ƥ/U5+xuO+Xt0l"\n4f2^ K9EHZGB%A:'nW6ˎFlCxea7;Y&ܒ,l:v/ `z zDWz!0up< b5Xwu5rˀEC\*Gb,QtٚI_y6_&C)k!p"2&*ꊐy5u]yZ`4Ձo_3nǽ*mmm7)2NWI[+1F , gN^?Emq3(]'wLA@)š€#%esYӾ";%jy\[pBt0a8Dx? ? mv0%e+!x%=.&}@~T;C `褏T+G7m3}Xs9MeJ?GdWm'}&\Pڐ8"$R_SPP!R98v{*$o[+y3s1 󜽿}g>[KJ;Uzna> %B4e+5qzAԹ C%$͵0n|(<˛`/!gU1б)g/$Z]pDJwaUp[3]kp30xO _o<=D6)7].S;rC@65EtEH8}rוO,o 8 Q.q]*Gzȝhd5ݏ`E1[r=-Ky?T!^@v 4f9\O%s2<\CE[q꒙O;|X%~;(Q1ШumoϾlQj8/ODlQd-lrHN|6ҵ41<06¬?6ɮǠGAyw-oqDOAz狹JN[*۷]0ڲN1VbGo@֘gq*8`$T G[J~,N|YVUh&`vv* JEس2#7Jv*9$bhGn^h#8i*&Ju NrH  m4 _Gg承lk607Po.%`h7#ӻ".%C4f!1pQ={.IZwG&u.O|ִ\7!I{'U7Q=xvMw$v&\TT1֡$`P .ATd{rxt:`grh].a˪=Xy1nFNE{WhN03bnӥ>`0=Dt[i _ܠ|n= 'aΟTbqGV?ZM "-YЉ/a+"X^4Fw8  2DRAOΘ%CR~^ki?{ \֓@ʱbTiɅx Օm0 H(xjNUoh/\!| b٩ȗؼkycKf];kKkNQsW_=u7Tf t?Ac3^pJA[Pյ cZr&$]U~F҈{SH1콤řBlnׇRv]Ć$$R)Po]peu?%&W]ǫ~8ː\'TĮ $Lo%qiR'ZҺ:N6yQ|)Y*v[ %K k-0$U>S=x <Qbbrq?b,uvNe&YQV'F#EU[Zm&Bb覬r S &|oyw3/Pj}mS8\=r̓2Vͩxg'gO_nڨȆ)e8Y2w,fx1W:TqjXFVK2U@T۽{7ݙ<ܳT-]Tev̍9Dp3?&c8Ϗ< 2` mdũw% zIa2Nm" zW6ƭtۙnaܐshUq!@M;Jb#6X`186u2{ٝS(0JWCO{eK ,Xw7~fNjtҷM|RY&|7BUea`VjׇN>$w﶐}ʚjLIx6F7o6ByD %kO ϭMbr+Bk;obBe$r?>1[٤zkݨ]s?NLuFzn:{qSƊNYa['tbU= xL7;hrWvYh/q]> Zss (QM..)>lXo1s _?'~=N;]+Npّ܃\WXɕr"] rWH)>y$cƊ\-X6?Wk'ULj{0dpcu={T*=@y3'||KG'=C[w CS y7 fU)↲z(UlgE6Փ?  E:W|&!e"lqߴlcYfJ]@z?f\?H4~]6qRO[UFr"z"D%vX`kj%3-Ng(twkm廾56Ǧ3{JKo~A2M1l=mA!+ݣ6}>g__"N\tHT B҉ "1G WH@ws`ꚽTǒSΛ DNoCydoA9Mu>'<Y+h|Q"H;V޶Aڰ$*BvB/>g!&[~s"+%]3e50r[N'Z/=j-mycyc(:-0?_R_V&u@%PXrẖ̌lo/zB^՚VA)++ZsBCҡxP]ƚIڷ.A-us,nT1/SѤBefͨ:a5R7o U(,zu ˎ.EH D`<ˏ=5FH,!LJl@>Rz:,5xs]=tXr;]4i)x <"s-z'Yqs.L!jGk2^ߵzz;˱=5SL}heiEF9GL2r76ӑbN};Q"i/G,z.= @SR_|ni~]_-ꖾW2Tbǫjp*)<ѩj1 Qǂ~'v5MdAC/-K*gK=J Qr#Ak~=*a;L:Pŀch,PDFf@G\3[^34*!aaw1 b)ӦRQn5GMEv<$D< 4ToC/⌔tyYka)k,GqZQl` >Z}ųKff\v s1J ]/x^w*}'5ϸAen?-DI?nU%zogo}^ʙ\8%b@L>D+벉gYV>AȥoQ}6}fy$+$Úrl eV ܑuK͙-. bN콃 kfr]p՜ykR-qV崯7i; ;ֵ)-X5̓-'Z#-LISт]Z"P8Y%uySS1E|Ҵf:5@&hj,x#ʬ%tuZZd-  4QmnW =ӹ1YIbϞu$D:|g'OI6m6W_ pP'QO/ PST<|C t g u N@XѢ'|Mq,o Dگstrdҏ>+ZM4/7`HeW 8sL=?9c<["wQNP_+^4&qyqc"b&*KAk)/o Է- !{<![_'Z?j䞞vx AuC璸.i`0\4`a#&9$?NjStL[՝#cCiFYb8He9)}{;{D_]7V%=bK酕jhOnpmo4a[|4)Kx擞?@P@ݿa5P>GFEjq[J=|[JFOE0 tzi uYޫ UtK:$܊8^eAh?ꇭzGjeWڣ? f5A d D +IUgLkn ^^[USrX}r)u52f|"s0<|+ϴQuř9(IE#^t7N.#K}I^]έ>*g\U%{82b6$wZHQ! ~3niG^U MT'&BƔK:)vH/M6Zu.TfX쬦xvx[v:~*'5 9eonPK2Te?]A 9,?^|X v7_NɋdgQ۞cpc[;uUokY5YYX"E@lu|UbQeKOT"s@]H&B2h/XE= 70gmCe>ps׈ Ǒ;`FZY"pp'>s꽢߼(Qru#KҞ߿}=he2enEM`fsvdPmf?ĦJBbD-x>kkbfͰ|v4')nHY>0jqpANx忣Kԫ`Ei{U$u,RС4bG'E|-]A8r]7]4ߖy~{K*, oHȷE9'mC,gkL.Lhˈ $ףk™Ka ҒF 4HXj2gJ+KL+22V\Jb<f'.Dۧk^}5͑q #^"e_mqQ>vcm8zgjBW`S9ߴH9hy(TD"i6ka0S||h_:0_nGiWN{ !5 ZrnIKPRJWioqyZTA6DkJQ.W`DLGFd6/RP7l!R:UN>Yn@ 6@m* 3߅vX$2ѩwNfCyhaR8 i ;ϗb[[༝}a ?[ilv^מ#qW5!ddZ^eNDFˤQ=И4T()źru:bOQV>fw#YܳP(TicW(XlTƊ2'i|Sj>_IdEğڋd5o/w[qxf4C+ovLBСg6 |yg.%ȓl5q)g6NuO _Z>lY{4d}Jd]t am;NoѤG$dTLBKe{DܻU`Db*86v>Pwp(V/2{;&|+'N 8]L?VM@8GM)]݆h2ۙ:)9<ݏdL\OJRREtK{t{,ܖ7.*@J>l{'5Tt{I*ϋS-ehr[^Q֓_w{xESG$Kɋ kޫ$WQs *P2 L}*J敶`0{DRE !!*O?JU_m3 e=Y Q=IxD9:q0Ǿ~Qh`*3&.]pJ<`۪n>^o<\ &S?Fy΀qj_ <~S=t^ኗu;n ku/EBBc=n%N8C(qwweܘnem,?$"QY=3f(VF'y\ߖN+RD@p+U]o(sa/p"rW ثlGy$&5r{{4VxP39H:߷y\ΓE/]p̿P;4}y3-e)'5+kZJacl}5#Gk3ZOhcWYìLyV+<ʹQܶwx"f,~3qjw~}O8AI*IQÖGF d,eQ\56wázEi}۩ &P=hsboֻV8Īig\lWsA?X^ڮMacCM 7FOlpDSRT,Li}!;b긿Hdّ2 q>>2r*]T\s3 <6 ܪ.5DVDpc埶 OT)L@{un<_nM$@gC4*4+"mwɑPԓcF古R':׼6 kM\N]`d\ۣ`S{xܑU {:r$vT%֝od2-\m)h_>ФݭmD{ᶴH,V]8=A*iCp6h Pk0$SYls M yXF.P7J%Rdu)\emkVihKʌIh[U3gL:&j|p ks' ӏ;hhJD)Ӓd 2%kϮU`-Y2X<1tW4ow֣A>TPnRXTjD ZS@G ,~78q{-7 2 d }48 TQRtUUq$߼ߠkT qx{hݚOe^=y@Eh ׻$OT>gIFNx{'&~כG=C͢9ގ[b C<]3dbSDS1! Q\uHj}ԂTCsfX>QhP߈ҺR-Ӂ@:pWmєOv DtWB?:KVКk3iؔm=j ?}g㓅x}'27tpG/rLH$ī0ܕ'[ fI/t5f ZڟC Dn?TNDMz賏5p@cdOedYcӓoB+FMc2H4}ZY9`\י,'gPaw~ %ak'yc] =>_V|zXJV1?:8yM 4/kgڡ6{RKjY`m) ]+274]rD:~L n =+i`#+Zڡ_$ަ"g+10cf{߹Ni\Q2k|tǮ;=hpyX?S%|3*cs38GVR;H$'OCZL*߳מrUU{LD!8;gPy4`Xc7ogDsqaMMn5ϕ92pwcWњ1; 6ncȉDB3܇K{k#xs눆Ig_Tgƺ. Mg鐉eĦVrw3X)zԝzo -"6dL2;}l ۘILs]2|3} B(R9 _ɢ-OYA¢̤4gګ=<~2Ao!caH桧Ļ2ܩCȴ}^HS |Jս<v8"~’:Q4./5t\}9(Fxi{lP -n-008)֑E?\^~&ouAO(6~;?hQE;a(5>j/B\$ɱc:F^hV H uS :泃fsP+}eIcIJٕ'fP,k/?"l!%p\bW66(pmwtG[R058Ӧ=XSHO<Ktd%E,A!J_&?S/H3VORCDn֐/m^S}lNTż^ FfhRnMY=swu}I)/N&y2 }Ε+# *sn^(ItºP[ݝ8:ݺпz ] :v5D LDXS7lN,zF@- qD/aAc9?=qCgh;2uz 5 9ЏNlqTIJ@dY<+nKHC#RV9p6W| HBȬD>(bCZ㯴e &nI2w% ~r11[>Y}m ~f:[z)éJ:QmCԴ h"q@ @U{ *KiܱcyR}P9H>pX>wd 3[ caoM{ OUz6Ob^ӿ7plOOhT_[RMÉ,(No$7?L^>}ϏKj;nF,Mjo'U~L&ݍ;@wcmf23`gx"עy2`RG_Ig :=o}_T .li&ts^SRccYHr2@p$`VB{r8ޱhвQۈVUZCG7C_s^ D=^Y1gQ*+hcVZ2 L,>{ŋ7p" 暳$m>TuR|%Si?#0BoEصVܱǡلMbE'T 1SE\7ƙmZlNs=Tgl˳Ub"*@ISb%v>ujDY,YFngؽ|eNQ<~Ϛhn y1$T*Z^ @q^_o9aC"uG~mnlyBԙg T3v@ҝke.eײB3knX5vD JR䰀?7|"kBcH>~Kq\vZ: W W#UnqU9x'J&@:gP@'(fCH`i|FIdUNx~T;}@^ 3[E Dş8`u#7 fDhD#7Q`6ƒ2zN6G轥D+8ʢ:j=}D"> KJ<]"WDϪ Rn_h{˩fh;!V!=ewBs._#ٳa&65B@+D//'ͫvk* @i42kYU6,Ͼ8aE& 5Ӹ8 Ol[g AQ5MQaFJ抡8IO40^g3a0eθf+%6eݑ $S~`,IgS[=)U$z3"kNu9_ۅ5xb ~Rn4p$람[kz"BjJLRnWg#&ž .q?@}TkjfkF+i?0 >,- ;{"I/އ"1Y IDATÝܸ(c:TRF#cJBX/^6&ui\4njZ 矢ŴԳt`X%B0/}BcY'gĐr¤Uzߚ󛷄A=TQu}} o??GaۖwtAL &9DQ5| ?l,{#_g3>*e*y7^{T|^{Pb!kB0z{57ƺA84m/7^>銫7tL "?o6ʀ~Zk'b]D66fMe0)$ ?|< ##L/nJ 2zz0g [W.UC4rN%1dL$HWl@A+Zzg[y)e]8֎@U/H`|2ks;lL_OM2)]2z`҂k띞A#3cf]^[01S!Oq_=Lp؝rzxS!*D w2m/0xwcG/3ZOMDz)>8Ovp<d2=wC"Ä{(iQD#&u_ d% UX5[_mFϷm5w} ɇCK%WCX}&vlz2%H[Ey"O =^( m,po9T. 3*2FAW**F/ 5XqY0&nAP+W_Ŀ_\pd RWەnu6hpqzwt[ǰ3o D[Rq!>/)WrOLmvh3@-%b{2s&͟ijm~M*.8(1fVvM5OkHkD1t"?cTV8$D"Kn+4Ck:>nf2ߓxҵol5BS?*!3dyk~aK g4Gi푺XWgf֪1zE8`v.iz{uSE>}(vS^05 9#)t/ PUtt!wjӦTq{@,,5䤟Lx] ']_oqݐCZhV*6gof쳧?s r{O5HM`#ڃvD Qqw[DRA p%S]f'(?,X*B5BxF{F?x_&r|LWM$nÃwFAo[oBYSD*NnȤ/7o7w<&ާv߮m+\eW}T4q2G c5hF?V <1<&z,V"J9u*.}ˀ GVz }1dD$r'[߿g2XUKG;Pz*aJƙ.ڀ:(\ miG  ~TEv<6˃qP 4eƏ8ټ: Zg7<[ـ2|)1E#0$E7XYZR޸ҕ"1#Ê|hlc˴n|ͮT.m 3.v^$k #P`pɶ2%ܦV'R=Oޢlpcv(]SWkj4vl#}j,GעY=Hyop۶@[jޖ鉑ۑ^> 6+/L RCSrd.=p0#M' SAȹ@,?j&JeohcAb7TشyWn9Wퟺtm,[>,NZ{zxUNF,|ɀЄ@1"jӐg>^hqx5cCG>k B!psԧ,Tc}rOslXI Y4fQl:MwqM=d"4;]յ 2s .ĶfL¯ {292`N;KSn-H[gD xuV7@Ozpw*yRAtm텱o|WzfMVVLN.*bػYQblA̦ !#3+1*9gǒTo-nTQB(7q}YA_i% sV.Ǝ.'" 083O-nEcR`|pEugg`HhЂn6dT$؁ۍ 3:VO}L% gݛabbwRe/Pج1t38tzFք eD:0I2KkM`uvf3i;yBE0KKp.J6]'ӛ^_&ajC_V/>\eXR f}т>p{C'Ԏm? jb9͞@hz$ 3~=dіc0eX^7;R#2oIȤ<}8{Ⱥgypۡb&oC$z+/lSB5oθ jۮsoXfd>ҹ=XIIZd^օ!UVp2ȧ5@(Y4^k4ݚ59WFQ\iQTP-1GT9?5K` 3G|]>wA:@yYmH޿,tZ#/9lPQC֏UONfxJoh!ܚm-m‰I2&#i5ÜM;:8oav>?iv 9=&46v6`eciKOf/ASЁy&VU;__1r5w 6L"^4=lwMhݴ)uu{$ IUdw?:LZȑ* 5Ⱦm;'2ETQZ"ˤ\t7I:mc1QzlVMg!mJ,Ox1t?XGjdP }'c pg(tHm2w{x;ї#!GC,l`@w ÇmX7{俩YX`NxZge7VU-G i@{J=htEO-: Z#~O5FL?& ^/˖T!.f|avM0SUHNe|ҩSX-mߪ81:)зs-<aXrޠC?4B1զxo+H@ o9R Jj#^$VIb͚.K)l=>[Ou#;o*|.Uc#Dߟp ?RW̄he `r٪*"P>Uz5g?{ȑ4F跐 EpiE:|$oף~ǞրoOn]mYiZO #М}mOș}{g.G?]Jޑ=V=rPٲ@ 0U<%JnCDUD.3K߼j2Nx'mue3N$}8PБjM:G!: &1%ЋLx2 GR3JR[mmՃ *ZQ[!&=X?]["gKVe0hodQ Z.W*FzwWH;:+-[<*V5q"Fg#(Et8-ZvH0nd}`[R}\wuz?{:Q}>`(fH 94g:V Y[YW*;!Hý^s9ыri pTkI=ENqN2ewh"GIM^dL!g[y8$LI{\TK \‘TȮ録00fUtS AEߘ 3lEKmE^k]y2ʾ0ܻoSPnFfK+ԋ rK Cmr])xskao?䚴nxBײ~}xN؄vk} a )caS.0*u%ʔ#ݺZ3~#ljg 1; VT( BJ q - |̓2'ڛuBE BoƴZ7׀(k/lA`)Ba<~_9iLziBxC89aL* O1'}6dqV-m\ޢ].cekJ K;qKOL#X_9,g;hOYC6S;9-H;";Z>QλɏMhS'NΤóN?LJ;oIENDB`scikit-image-0.9.3/skimage/data/horse.png000066400000000000000000000403711223313777300202650ustar00rootroot00000000000000PNG  IHDRH~Ҩ pHYs  iTXtXML:com.adobe.xmp Pixelmator 1.6.5 1 72 1 5 72 400 65535 328 ?lc  ڶmk{OT !-W^yE\ybb% O[*[2 Ďȑ#E.]Çű+*WUǃ;úvȑ{P2H 6޽{קzTR82d3qҥ}8N{ ) L`РA $34j(T^Z<ʗ/_|έCH&зo,ŐLƍӇ֐VnѣGoCX5!|kРAq%h@/?SmѶi( #y[˔)#Vj{m{(uֵME@tkC$`4BK+{2+ t:S*H80UGBXvhٲZZje˦k!,‘ DA`Νb޽{ž}lC&̘1CL0AߢE l h A$6[NYF|'B [VZ%ԩS|έCHضmX`?XbشiS鬲|dTfMK"Ԥ 7 #U,[LL2Eۖl k2 L$SÇ[q~za#E0Ó:@Bj :Zj׫WO,\PxFT Ĉf$@ASvbM4ӧOr,BKGjD$Z%iwʕZ|sŴHHT8pcK.$Qa|eYUsU{ *i2/ %Nj)q(xN&P;wQF=N@hJA$"rW?Y`-pK<$P$N|T<˾{ 4E $@Lc؊!??4k,P ő F`⦛nL{/+%s`cp+X̝H '|2\zڸi$^"~۷o/  ,;;8C+PH"oݺOR`!/"] XJ$ڵkEÆ <#,N{@"rI AlƍI8qb"r+&$ocǎ>1#U۷oWIHPyq 1,e>&x7}^Op3{H"3fX 9llϚ5+r &pG0եpK;Nٳ'ͧjLC$`K`ݺum۶Tt_BٳgX2G*IPF$Pm۬V3GF8yK1"a@ҥŮ] 8#\ 9Ne˖'ө@T"#֭-4m#F*HY M`ȑbҤIfW"ϛ7OY&R-[&ov% c=Z-9jDؽ{ܕ0M7l T=jf0`qСK fB4hs+bӦM L8b@O<H 2$s$p,$7X{=Yf``$0̘%ł۷0 h @IL=zk׮5SxJ]L{ӯ\\j̏ '&L0?M ȹ΁)Hz[mܸ14ٳh"q+r̐$Ϻ4ߺuy \z{ ay%t$#pԩG4*pC3*L<&xŻロ'S@Td^$` ٳg3Pr\ѨvHbF;vZ.\PtU8.'xJUQEa; ۷0ɃoM4cƌ_"8 C)uO+ٓ0i~5ׄ,reB{WT)Kaa Ԁ@ ӓ  0P_/x㍒72`ɓ'';HGQ,̌'={_Ј$3ghѢt7n Vo޼Y:]G%_bP$`SZC<$rʉoVb 1~xww^/YL2/QZӑ DF`޼ybA*MСC6h@Jh]v_`wze$d$l s]X0'dѨQ<?Osi=-̅ԪUC̈́񄍉HիVCa;|%##6lVoƂU!,/Ԙ uu`œV ֪U+_W%Yf˗[2i1/=/"Lsa˟ ~ 8 `p) J.u,:d߿QVA!#*QLwafxWv'(ּ|gOt%+\#C}6v!viM3}sW)`mQlYbŊB:KTV7|^f:M^Zi& `{Ϟ=|"E1=馛ҥK-zH<裮S/22>C/96lu؄d]xnJQbj/,<y !(}6JVz,bۋR6E):E+W.J5q)+R){^}"ԉAEoEEo=W}RRZ4j~"mݻ{E70!5|`77R2u֧ =` 1B|㒾.\yzW_}%0-@d(剃'5w\k35k$C_P$W\qX֭N䉽!lKR1Pb*^Nj*9R;sReѽTuE$76d@Y`VQIy͜9 ̙`EnZ(Jf\tE1z*:%>pn:k;m pR &޵^k9= &w5w.>`1!yeq _~r>50ė `c#{RYXy؃g=P9 K|`ΕE_*'\jA`jzn\ KxŐzKK`La /,y1(t4 'x"Qom+hGyD`/v6/ #^,BSBòԋm1d1vX*SrIh޼!*&zؠJe)S<)ȡ+b|\ @@˖-Ӈ|vEÇ, fƚ{aiZ!# '۵k5gWseW.Ѧޗ\r db 0^{URP X;g( _t]w :t`yF@஡iӦ4ےLO$ M/ckѣG{MΕwőSoE)ӱHߧEVv"3%w>>|_Kp;Z?*V(eF)?UE1HWT<)E)練K, |u`T|?E./~R~RKE?SRRs_u nD.o꫋~5&4x@'p7(-_2BJ~cHI&$PLd(5\SRnXc93A's0`@$P 4h cXrh .a}vyV,"q@QE%Ctb@ ^zKSfM|r9nvh"dn &ڶɷ^F[(]<s,^^1W(/CXM5w3Yj2e[I*k׮Bf$1 W Kmݦ-Cbbܸqra?,/!0зo߄VjFxJ7KR'?lСi >bڰaxgH@%X 2DK 6 뮻Orcs=GP{W|WbԨQ:aHXÚ?c: g:K<9@Y}bS@MhpYgȭ牄 J t1%0p@QLP %#>}hРA0 =ZԮ]ĤJHX4m4Ր}'7H؛N.\(K$ 8xm:F&ɽ;%|lΜ9ք{~B w-{ `ΞFp [ˏjZ >1ܻw '6zꩧ-`,Ǘ Lo2N0 _X~?V{뮻6Ą;LΝk)#FzQSښ4D@_MRvkժew960׿c#GLƌ#3 =Ec)@A 6m-d7k% "9pEEΌK 7 A fh'|wH ](fÞ  1^޽{Elm?fG7 8=zȨ%u&cPLx1 ,йŲ%#Dq >:~Mi/:׈We `" tMI"țQ *L`pwĭJKUVu"c@T@8-No=N-.@[ *6 oX't~ĉGRR\9#* ?;͛'tKs+4˔EyW]u*;w'N'@ 4?{Vc@@`7?c Z\8XNo@<8jރ2a„ع{)q`tf.T֭[{ _ԴyUzuMIn*{ ZJn\X(?+VX nwС5^H6\े<P ~?y I+ۊ@Pd RLO`zJk"%aow]*Ak *k0% yU TQVypJF@@]~n(?*xš4iuʃos:eq"мysrsP@V`GCJ6h;w󶵡6 @۶mC)C@-֝w^X$giӦӊQ 3LB[υ:$ijCt֐2W ю;VF|EjD;qok7}/xՎ)!ו)(,6o,z-w(QFWn:a<L!+SZ*ʶR^5wG1J'Nڵ飏>:Wy9sA*g^$qKLHT=yccʕ8[XT+#_ցN*U7P@ <Ps 4(Q϶mV⺪ WE2p ZUó0ρ\y+7 *GMΚ5Vy {OE1yla<ļHG(R &;uNiѨQMhѢf~9rD]f>sڵk̅u LDa&|{yͰI&Yxq~n6mOrMYZrJ-2p˖-m k"nj{_ŗ_~|rlٲEeYyq# O4'о}{%x)(z &б#H4{Lld= [5_a1!WxP@@aթSD+L`$&M.mڴq2?ѱ0U&Ǎ*<裮'@ xZjP3_PJWJqj2oau;dW!A!;i)G<*3c  !+z "L 6w M䚏ˋ{j p5&Id$an'x?e Į"%K&w%+4cƌe˖ r~{I4 $G'r"d}e 6܅HG eI׮]= aVn]+JQ@0̓8Kaud߾}ˠbŊbv\] b|)WJFN.(Z-HnkSse ccA7J`*N^NTԇGSX1 (L'{fʼn#W%-Z"b4i5J $`G !^rn:cB@*`7y1mP=AIaÆ`|՛ZQ͛}|79*0"JHn V ۙŪV Clu˜QգA~xD@]%O&T\tEY0rnz8@6*4`¯{sN2x`H18. W1' 1RIt&ƍgT =\`sM+CX.%8z=տ nF-TAnnzj[n_#Ƞ ,܂7@ ==*ܮ];KnC,paTfPGY~ᇬNVZXű@0mf#Wa"t~8p`fvx㍞\bS޽{# ^B=D%5sp<]pGTHO/CXi!䮘ʧy!:e:` 9Zl/uOo߾&̆ ELrx='C Dq~uP{RhBϮ'.p&M Ju!!:'SP ɛ[n$c ~8, Y#G5u$}@/vNcv?pĖ;(^H>}r ﶝ/'H [n<y @=;/RAye\wul aA60/B!`F6PȒb4(_N/ii.HzaÆ)!ގ;`sYN9bw 6y*X`nv,L+ cs t^>\5ҮDʶm۲`*nWɉZ|ڥKjժ%-{ Ҩ1E ;0qA p4XW^ۭNJ~7YT um!uP[7cW6&H@@T d_V~ӛ@ K2-3n$\ꡇ*)"8\ƒ%K!#n0nS} D}&TJ6sYf 4n0Um$U~,[j Kc+E V7f̘Nn@t}~awb"ѫW/ r$CX*YDmL/Z%ke/nud\"1s5W n0\r%nWfe`ZpLv*[!XXȦe<3 @xսŔN!_S|O67=k& [9}dKI3g{`I%g˕5R7*LYxO+f"KI<֬Y|,,nzv lO?t E]i\hD7alVfOիc"p3_fMYf4 )x"Kxl* "裏T˼bJMnO7 iӦ1j"`Dwe(,{2XK.( pce7f2n_[%{ Dć~G7=m&kڵkV}xz x.xa2]vI={사 ܟ(._^btukʳ>[J3gJc4nŗ+V:餓dFOf [Nlٲ%RYYm&%`=zd{{xH@d~|X)CX+V;v,Z?d<Ҫ\\r2x";.;3d= sQ5$K=֜5 @H"@1L0i7CƒiٺuT >){) 䊀 L>aq@f̘!dmeA@vïaCJ V.3- .~0L$ @^z cH.ʕ+$:5%Ë/t;0 }v;X9)S`0kF++T"NVl޼Y,X bYNd{ N= T :z@,Y>J"7 ѣCEB@V88))(7*X[ Ht7?" @pR '|Sc*O?T`{׸ sAL^0in=Ep"`GXb`2>9Nz 2}s @:~j֬>ܴi'ӥi7"BNs,cH?ԩS _B-+de?]=#xێs.opi&n*{ NCXO*f;EHGlРAPҨb믿VV762##]6qaÆ-6Ta9́SET ^z OyP"/=qFtҀbp344d:jS X@Xnn 2><̛) {!4upR p#'OZ!5N`/pޮL쁠ڵI&?1#ċ~ev"L4977 +].?A82uό=zHoqHbΧw|;̄cxgp3W)`婢q Dv~8R5j'Y͛g)OHnV&W^m$+ ퟀq > }w.ƍ總]}'b'Vp N wʂcJ8uLV{m׋6mڸ~~iqu S\W8 @L8 b{Bn {f0NxUXԧOZ'GJ*Yfӧ {QϜ9S4m4sp%ԭkd7 QM,7'`qN">yXL,_{bժU­E|7nLB(sS̙S0ތ'HF|ȑ#E˖-/S?~kC wFgD'*J̞=r5"l!yS >h֬uR7?믿5 #]qutҮk 5kMwi彗S޸ѓ+?#`AwVչsgdb[UCn8hРIa.+p$/Sg%0ğ@iBMu.6֭[IÄ+',qm۶%+z&e[oܱ6"ǩc/ZD `!5].v+t-5nPq_~gnݺE?s+e*qJ_|OC V={LbW?/oC kBޜX~ᇢ}YC nv/X`!~b@qkR8C4k^z {˖y\u$ VqYiaXhHV`Xn8hW'^@nU!_UeJ>0:tE,\4iDԨQup#7:&̻tJݏܶ~G{~k*/+K*%&Nۢ+#ϣ%Pzu_*wX3e)Ox~5<.+s=v˞ϱ\`(,ܵkO6ܗtC PP00`[lZ)o6{=gX)/^lS󐍕svkZ35 Ӏ@Dݏ9on $`"2?\7+W{?tc~ꩧp1G va_~YiK4TZ83#/ĩ(jL0A`̋uWn-S|y)`k׮HdPF0Zb)iKZ۞_z%1x`Oi(ZT @z} 8WT5-;}PY?X]5=7l~gk׮VV W`DT /́䢃{޽{7|39g?O҅0" L`̙Tǚ)R`(0𝅿3Z= =~ P߆ DB fd$@$ T jlVHTQIy @P$YU PI D%ME$@ "@fUIH@%*4 $HU% @Td^$@$ T jlVHTQIy @@lLP}YU  56BJQ\HH 3F?1gEIENDB`scikit-image-0.9.3/skimage/data/ihc.png000066400000000000000000016453341223313777300177230ustar00rootroot00000000000000PNG  IHDR{C pHYs+iTXtXML:com.adobe.xmp 96 96 2 1 PhysicalX=13727589 PhysicalY=-6370654 PhysicalZ=0 PhysicalWidth=750181 PhysicalHeight=378938 Lens=20.000000 ZMin=0 ZMax=0 ZStep=0 Paint.NET v3.5.10 T@IDATxǖdkr%fZLqo k5Gq- =iXUõV ,67+_ض?fs/˵: JrݮVOOO_Yލ;A>Ԫrz<]Krjas^nZ=Nr*UzZ)u:hifXa[ۭoӵ7Xߟ˥kRWJRt+_+\dzrZ!:5kO\M7eaj=hχjޭ/Jw84r-[ns5roj_/&:pvNZf8՛rT*oR|OFh5Qw{_ܞKׯ߾-֫^t.}4[n98|kLf7/j5_R>ϖ폧zZ.USkV+Rz,Р׻z|8x>n]ެjo˴\*av?hm*W+u;NJh4j[tZ+h7p8<~{a^otCo47_?~QzvD&ZZ^*ys8Yn?[u\ѨR)v^w8IBՎjzӴJfgjҰ-_K/_VF֨LW3Snvzq0|$zP9?mVAn5nnojwz֪0_Ԣ@yGIdߖdQ*Fr9Vfy9nV>wH 9ol7NCFR>I7FR;hN O6Ӷ%tvr<eެ/l^:aO|}LiORVJrAډ\m#Fwm\]x:{[j:vҦfa[PUKp\^v7F>`ZVif_7R/O[tχn<OioP0?6f?˽+_IJ1׫}d <]#~7)b;[}Yoj<ҭbc/Nxt;6>xLg횩|xx~uOps;z6_N^WR ?^319ӭrM|0td-CyؑFL<voj媺ٞd:79?{>Z~z0a{(mGz>ݑw,o4uQ-:}j^W NY*]uzw':/&/Afm$\'vDtv_8_ܙLm g+Tȶs7&Xm y>3iWkƥ^Ѻ˩z+/s\m%k8YrcHqyKB?-Z=_JFHaNcL07ikŌ8 h Kl i;F}Z|5éZ!o!v5x:M?|Fr9ҥB,WUYM6/|d]隁-&l\L.+dT/~{>3WRn@W[mﴲAR֭dnHsxWJfyi{h4`8]>ezJzvLR"ΗyFc(&5<)p9H&{6uIx׫@i)ǡPjwn֤E8wֳQosWi~4y6_˯H 9[vO,Uwg]} Z-nʠaۛAT8g.'EwйnW(^?}˦4jm(J#ln_ @1W^VW_&d+ q&'/r7vcԺ0Њ%ךXV vՎNVsGjR1*/QҵoE/$/kզRb`r6 hq.Xk冞4jn / x L^ffuZop6jCG=Ob9_pc?'7l՚~h,8=,jaOd:[хnojTV~]U/*VnB1^ͨ{y"l59dInCYa$zbv[.֬BTpKPi֫qfͭ`Rc}2=G 3KW+0yo+N2jpf $(ȸSx<9&2 rێn)0 -{/JMl@tWk[N[<T80CdCz[K>[Zan]e}./ vAmMXkwn)1+ڟ8Zr-Иlzz!ki;fݬ~Te G5Ku];\f}~6L0Ƭ5cŢIC]jX!-Y u>:}FȒͧ////U@YmD4@${kaj&lx[lm+{:P 6r;0Vx\3Z;fWxqÈ>"@]rҨ;D-9l/7?v2ei*fYw~ MS:W9W'b($O6Y ?qo>1W]uk76ۍ ָ;3a# Hr>L9&!V k~w,g2Pj$F4[fAWk^ ^rO_:/|Y-BVf=™׷5c۝6M5 V|nV{|ù?ءjI_OO_~JBwh8:Fa8]3n lql&>|wٕS"j'XbT̷RY0$ש\'䷃nbyv"h+)|6ٷ.V/]7^,Tzpdxlvp)i2}1;?GiM£Dl-IYk<լϧ?˿M^7E-X3ۭoEL w8(Px9xF [ŷR6_`^|5pp`6J"Njjjn{}iպ&DJ+ sAG;G!VUvmJ-/݊|%1􇃏?noEn@aMb%mZoon9WdճV̘HJ\#r[=o_???O s{BĎDgi0l3`4!'v =fcPcWu; ``9x< G̔ s/?_ujzPL #xs8ZPbnFAC2`1CC>}|sw+{xx}otZ1çKYg n`&["J+Vl&bh PÂ0Gb!No5b4ά#i!V 0 c>|$N'Tb!ܬ}\57{]7m|ŸW?p[+F\v{'Y";|9_*H.)OI2'췌-OLP ؈PZf$dyIS\Q>̞v;6[w6~Z/W:-^m0`Xnm^p<}G\h`8^+M^P/JB숏u{{o2vvgF1w7wv:o..oԨl=?n77XgWs$d?~g(Ao|{ˌT z{#O*`Zi2 Y'oW bx'.1SA'vCX3љeXoOOn cbD/,j2 Ŷ/_~EO_@j@HaVDjCɀeD@jG7Au:CrZud`*dlkpz~N9/IOɿ/nwC:d>= \2ne_^bSˑLڢYL\ju[' ֫$ Eoa;7zUT9]'[>r>%}6=V󺯗(ag\|<]a) zK R$Ċ2G,&@6vY@YԫW4 ,]6ەMGY4ͷ՛q,N ]}s ! 1Xw糺u1"Ks` $\ΚVw`X~vY}f$Fc7+=r[Lu9rDo P'[SX$|}Z%mVk[Z8UqbI8k)Cʵ (e&29uZ`o#*nJ/VA$@LΔ&2]{!qdy@v BGB*ج^OTl⋝n+_oQgͷ_Z^7o@KRejv0Xo~,Ӿ8p;=#홰fͿ3++s):U mwЪ9gWlqXm&/, PcnG@fmʕ˅ժ=GED*! @V#8cΨ`[Sv+:I( /4!':"kWnn r4n~ELÀ~<0pp~ LZ_5}sX 7jb/M.Džo˥iͥ CTFěHN.@KdIeaMª55TA2ȃXkL>D_  lfoo4c7}--'JW2bㄠ S#ĩ.lUwO%ڬvGw6qOzƨf]V!  <ն!k<\`V bGL,YXL/f"q>k#ts0v_=@ݯWOWUZ-zY9]N 9{"boz`=#ć+j1\eex{c{U3SQX0q{p67(A ^hDNѕV؀H+{:oP7KvA`ҁ=!&cBi߇ Ֆv]VMPD\r/=!(sPE`s91 UpA)8Wwe1%DX[r~\bwL%^w_ϘʇR ` ,+ *})4$drEzNd:@JA YpbD jR`CK}=> alp$ ! J)UYY3(mEb(;Ouޒtwڋh}"* ֖5䓉RQ*?λ'|lgfP1<('J- Fh[U(zKl((kIm]AkДCe|9|+3\K'TVJ 4B{G`Y$?yT`?`~`--N=h)̋` _YC鹨vݩwʭk QP^/hnA%vDnvn`(ԱP٨b.A(, Б )Ei_D&gY7MT|.a)̍K ^-yz>zͨYW^V_v+D9?3OgW[r&[mBM!e_T-@E7/&k~0׌4F{) R/C/Gn7M 9}1rǧWE5jF /ͨUa8$^Jylw4ײ vI|i1M9&s^Kn AKk6-Fr;o V #WYTֽJ{` >-b %TM%#Llε4$Q[Wj'f!A9io cUCI1?PwwEDʣJx!Jɭ+,ƗؚW8ބߋ*0L | x b.@5+~DLz d ,~.LJoA*3N5]bZ_ +HܷC& BY4{tV~=tN1-JW,Cv&XUP-#5t.Up{sҽӬl_K{^&PhEuN#\ÆѰvHIXX'G7ѼJ{.(m!%ܕݾ<__0ױ~^?m R P%:zx1 q̶gL-LBc*̂) 1SVد&=.h(xvFǏff@Clnh>Tj*$I:̬))ah %]媛.TpOXU`-%S)'d2& kS"zT$ Hi)|?`E\ " bFm^”Dl3r"Ӭ-y7^Ȼ%2g}wAQ1k14ìr DzbRBWCTEBxjy*UvGŋ oJ JV`TBL} ~6Y/jIy`oޗKL bwH*$ύUx&\?y !ƥu빯8G\Jǭ Yy-Tt%5Ȧ*`Rj#3_gXc"*&gQ*IKEwUq>¯ ߨ:e#H?<5[(]%p p='}èX&O= jK}sBӑ%db^/i-N wk}<`ޣĀ;^ m.)Гd'3MrrH A)j*}VNjNoO/fD-aYp֢vsw8Q4.M|@Z5 bƐ;5%v[f/9ni宄v 5$I*Km679EȰ.ZưB]hl_+X 6͵I4àGϘ&*-gn\Nw:j:%çO8-=Vƹ^g:j#1U2^@ֳ¢ Qnȑ^:Њ`- fW*H۵ 12,TyzMsVgWEܕ hO wk$$"ǥ_.ME]֊WSYm*<+@+cMQyÍZ YAfo_~ae'þ`Py"ƐM.Csh#x:ab6Vi?}f")ꊂy\aB`3M^37fƅQC&Z%`Dl*i!. "䨁G<AMgcIu΋bW:%],j\i6ޚs| #[ɷ\kWeK2vx!b;@1ȎEZY116Cm5RrD!\rQ+3L/5bҜE/b(icIIHlM!g)}THt8+V+e8plٶ&69z7}Oe5l>Iv@:|`GʟF|^t: ΥFJc-ű R-1i9Ic%:pxhXI#mRm>y]0N㥶 P*:CȽI UANB\\ o4_JR]*zQS%.7VXܞ'.\VQBQu5Ccfžhxz!pLUvB;@|nwEEs3;"^dfaUЧڻZC 'kJkC-\٦h; 'C_z'ΌXA>&(gY2$1J9J"ۛj_}~/I Vҋo7=J}r]a>5^bHj3;G9 cU QfWkŘ][uI --WC$Y[y9Ow ~M 2 tR>Km8)qK!!QNJ82qh@~D-:U 8 wނMiŋegW4lΙ**̧h{ XJuZwCj\FFvIXi,92 %ԀFaR!|&NrL$]1~Íj%0Mog-%`WQ-Θ#ezh'oϓ [L?HfϯȀy|+R¬+cnKQS]c l=GDF6șQ 2 wԬ%PK&_ ʪj`ZC!Iq;xGN%U"AP.?})) o!k]ӽȆe4d>8C<K)֢ 8f 99)z; 3Rk&?hecCȨ+R;\VeL"/WL}YQʕ.ȉò";3 MMًIS4h7Cv(?qKQAs5¾at,.']E?I092Dn`D rr cX/y_FΠ -3V_I1%zc*:&?@=CY4^"ucjDX@+-@bg8~6dzb-ϮFjJz7k,*ַ_~pO^ B,.k/I$ɣA՜5k .{Dm)=+:^:jT;6D@rb w͘"|{r|sčn 5/ & ޾}tZh3Rʊҏ. CJ?XmުRk^ͦ̄@Z|ìm4?,y",o>&"\El>hHaeA8FRDs6%N)t}ݟU^<"X(?!8픜rpEUe#7Z}'ăt.34TN ח?=Nc K\ifހ鶓V (4; =\EІY"`o_$`6ǻy uԯ(py^N]͝wh&sJI]Y>Y^1tє@W=PYO7v+CT/aBIG7C.#:=T~Hzꐰ 'GnmB{[4'Q91T6 . = 45k(!!㭅9EhECz*-?J'=MI\3+##2LҺ3Фc")0,PYE2+Ek/_eG+ۻF7?J`זv^pç6 dՐZρ{tYHYr)M,$'"d2uO+~κ,l;t/tdAt{jH!Z$b".;Hn XUw!cBpSht$z>ewƂXqUZeH)t;x豏W  m̵H~n/ag:-֟oT+mҀDZԀM/8dnN,ll4dx{#e2VLwtC4HI&ARnn$ <\@}պ?O4b#zctCvq!﹚DD<㚡q"bj:X+^bb&hYb-ENB4\J?xQԣrvk0.N+p᳃͎D%gp$,vX}8{JJV#,Wgs}'ڀ%M8[Rm&3\w5qB(y*Uaڔ9b5ضvnw+a8h$3nl0 ,1c L^"$pǨ̝)LA{.*¥҂zYo+`$],+?T`UU ;og)!t?۱ b&ʱͻ;2Ձ˸x\,jd) 49p R4j) 2*/ /kQ{ʌA˞NzH7o|3IUiu"$$>Ұ2_l%NFWB is~ Rav7w"P^ͥ2.+L>!ٜ'l "/f#uncgN}n! @_qY=3Hbz/7v UHsj6H?EX[;%ؔ|UoV-#l,òajӳԆ9("quʏk` t|si k,4Q:Hg>oU9vz!n-EI E"4A}%b5P/8Qck7p=udأ%vDyԒgfwazN 1=U\hϕjC˚9m,s,3HX+L?ʔu j(UCzJXzuq lJEtG%bS,deP;YW`%J =UO:Yiu.pIyt qR-{m`ljry}}J˜???+P%Ih{~/¦ c.\t8(TbRbhNs b8E;fI쥯Et kչ)S.9ˡgI}ל>Âу[o1 /wF45&2@R>T`)Of‹hzN)J!~\HE8hU&$ 'UrA!|g`0g`˖KC2S"Ii2.A}v٭f樫6TG8cYXj3'O7BBSDÔK>"9"E˔ܥ^\ tۓ3t2%{ ;g[P={gL\2Iٛ.]{,6p(v#+5OR 6:n_"QYᷲCLO3uYhɴt#ImI˦:a$= DQ*s}'^G)K YU/Ey*R1Y $r땾88=*? 5V#al`dh9jЊ0\CU$ crS tX(ފ|2[Q7hU3xPXkZ Hi-M`$N:c iVr/ԃHa`e;M 'O߾87P΁0R)vbyUwxJihy$&%C>\:]3t|NNqߣ?iG5I(>y I /3.Z\i-V!fX]ȩˉ-RYcXlPQ@ |*70I_&*_śM՞Fp u]\>' Ps@(Y%^K|Sbq ǩ^fy{y{Vtz@ "+oUkȼ~U UAVJWfV5-ZJ>[$O\;FXNNX?_OsӉw'#1l#eZl6?|=~Nqzc:20Ivbl c6,F^E5Ei~Xj%^V } ,DL0ථx򐜳Lb϶(|Ray҆g eݤRX Z0m1Pպ>*oE] ~EY87!0Qw*I VB,q+.B+1#%b&Dgӿ#@ix?'ڬ!(Q5X7Heg]_> lg;d! .T1mREĭ'O4R$&GEb ^ ߅{EA:! y`@*F{=c7H#%|fXş_u31fiEUk _OO Bd+I_-oMYbzy 3Db: k`A+H6^$ZdH/C594eRFJ\ D\sledSN#a)up^!/+wwi+^' *#Sh-2p_- 'a2]״S0[g*3uʊG$ϙQ$ujWR]*Ei!< q&" ݈ Radig3"^umΩ"̼U˓Bb@9Kfsc̴z&NC{&.\#Gv߉|ԁ\/T;7$1<v GR63Zy /fbv#"v&*t#1 1[Tw"V79P;3JuoS`q݅ _#nd=p̙#|a\,}'=1ZiYP4)^ ޣ[e]~0^ 0C܋L;Z6j5O>o\*1*:Qɉ*PMq pcn`0@bØWKZXztxYUWDf*aw۳G[Qj赬aO 0̋/vx -28I~֦ɜOs'nc +9s"!Ms,}=(~t8qsQ2p[iw|.';]aR`s4bF_Yʧ8 ҅лlFGHi|YETЉhcXSjMfR Pyb+IlxxZ蕉\)@6+gXQJcbP_θyxrs-wdTG73pt#3=PaC<ʱTZ8}" z&xTQ faq8VDlzH 'QΠ!¸>)z }(b l ~r?.K XK›{j;//N>9vLJY^ P?T6FPhPPbCF#`Fi4Np؅xsJ2}Ovtϋ8An,kb򞘮 T bӘ3;9Z88= 7B~~/1ފV΋?toTy,6}-fİc~E컹TkPM60|_4ḆQ。=mQS@ raBIOQ7sMΚ/RV4pU AG63(jUv%daSNh.R r0#pjCZoV S\#sQlܠpV޶j!xpWUƦ,ψR{*&yj"_&*c]A43v<1Ky$P<" _m|agK !o$L#Ejz^ƍ4"s_?_9ϟ?3Xu|5jL=Lo lTbQh~jR,n%d*G=P<ԧkGb-s J*/AR@J 'QML;0Z:o?-;aeS11ާ գ@£Ac$!K[ 8MJ.t=vxA G!M- iM{*!LTFIPZQv dd6&Ж/n~qrv)gP@7#W4ja:SFH5we6jF0ʩxLX{QmCk6O@j`C09p bƹ';yP$N ?yK!97返xV*7ceA糥% H9uݗ*VlX<`stP[R04Cy6>mVANY-^n`w<^ч-T`I:R(h@YxAr"3CRsbD Wl,Ubi5BTੲ c(g: `Es"RyAH{ Y:]+ Asb&/E!/2R8R5 ]&? or@SR[̳ >Z%teugzMGJN`5y=Sᐚ#_햷ʶP^JZO ٗHkTҹ ?s&ԋk&OT 9 EZ^e?dV, c >cwl_6$zyӽWb6(E" w6j餏I@ ƊTe"+6iPyrFlig"hidNKT 5x8uDu,Q?/?S>+m//H9#ʍjN7` nkCyp~˗wcGb{0%8 [,;R0ԃ&.`kWv//!}(2p a Eww{A&1"~ke;!~8Yg Np;&oEco00A8"Q$ׇjZ!nu2DOO/2Ċro>?t5wM!r*6X"dȼeQd`*7_ߟfbAP#Mr:w=*g0Зu8Sk$/1㍞N* !t[Mhʪ@Fe)O㘒VsY:t c:GMϟS Ş+SBG|modtfB=%͋n, 픧7)A1C̮*~/hfRŏK _gKzDp+Y!R'A yswh*9<$9g u)s>{@aQUddw8u Q*ڮ)|3Ab_87k9%|&s ֣l3}V뒳r~%;Vۥ%z?_[@FP/fR7#9&^U<<ꜢFpMwd@gǥHRz_;<) p'~%E XHh)j)EK; #U2ԟyѹEoUhFAp l z pn)sՉ) L/xqn~=g6k>u˗'v= ipQ˄$nؑ2;LQ#ZdJ"^˝[ VQj' `2g3 oG=x>^yxĂ찕>aZ4XTEj, ssp>-ҫF&CZbbRx_{A`7ꨖ@!V r .>b91~E+xz A ,&ʪ.ⱷ: sYT%r6;a z2(C 8 )=ͮ$tB<5hجKuEkA#(aaU;1 19;x8m[Vs(ܴ+b;:GzeM`RJh_ * ,-ub`zuKpyTpZD$N+ihɿ"応Wp yv')X8ڊd ~w{N:BJS'ZpdvX3ILjÀ+ғl9Ϫ-^[_#DřHƾ!ђEJ)Xх= .; 1ъuD{Mɶ C~+ՇHtfuit J[Qh>sUCvŔIia]*U `\_4g%:^B-uDZ:5=M[;+l^2rldBfvMp~F]5ٓכztsZ/X񳘊t;|0<5=RXSjHR]ǟs~0ٛ XRS*\rEY d-XqoV~(-+W"+G\ZUrBf)Ԯ9L1B˕R1Or܇UULJZk!?.1Xrq!c+ Ko`c \H.@ku<¤'6, f= Ž_k,K5h@7UU%q.to4mLfDГ Bg kMOgfG-҅)bTȔ,)!J)`O(°bDnX؃KJRۭk+qI:6lXGqG֒onJ=kP/| ;Re%MK11XjiImgd37i&6J(eF岨^l{ܺX>{t?=&kD(Taiyn9@%ızAÎ0Z[j#\G'>@7!=}XSj7k9QgX( fJՃnA!摈ZM WZ.B(C)woUk4/po zq {NѺ<;y#2o>6sm8KM`2KM6J];!W^,ԤsDZRc,#!od@k*ڕ8g}|X1سѱ#ا9)55}/iuX Y;-N@hrQC:McY &[f7ZTR )G+vbQ%SB fd" /[w^v lR'Ko6춀aҴ@W!EA@jW҈Loެa%ʓeMg{A󹀶)]At^ h\ RN6z^NIg7AhzԂũWtX Y-ժ&pdя X(-鬙 MQ#sƳ4`L'dRS, ,;ťFF&ɱbXtd++^a3ѮJPnO5Y<3f2l22Sgc3)zӦ"_3w}A@ *dqG=;]Si>qV9Q%&ʄ"LHD^,T͋l,D s"!jW`q:r/שKb TN&p3ȅM;9-͌}Ny%tESNBrS9pU}6t`L M, 9*#QFzViK4bA4+*!QRQ.4Bܱm[)K{yfHuFnͧ&X=)\.rbL$H_BٻI\Hl,3j d."Jd4S՚x ({@qbDm۵CO*q'|piNN7A_[qO\0&2bmO^";^~옭3SZ/k_Fg[_\GOn1$)VvH ww՗aʌ@] ~#t@`?g^^~RD&2^n0`09#lF>b˨H' I)Dn\_793/(MuXAC1T`iSRVok|x|*T R(}L]kƾhd0RۿҪ{("Bw~.7Blqxr6I%*B;oߐB*nH8RӡBp/Ze_@'~+fݑ3Ud1*F7ZܞUL?KcUE P7ȧ|Kx~a֖bd݃hb0n$!׶O]8 2cX_ZÏ? zW*akJ0$g$6fZM>;9{2,ًRe=J,N¦r`&Q_{!OX%foV@p]8LHL:>3V(j~?}j$}Zf:v^_4U@"7@ASW5㐈e͂9(jBwX,f y!-N2  r~HFA7E+f&LI%(EŲDc&{.aD~ԕ2ђTlm#hb@ǁd3x1 +٣ 'NMtJyp̑ʠa?)s!Tw_:x2F81"|tS}&.E.8L:d^45A[lVFz_7(5} /țvFtr;4̲Xԣm܌54sn1IP%te鶲0~m4|sZ=o'C 'SSQPZNIi;&D 2֊g b wfcYi;黸*@& ƣ ܒ5qg]di:lDWNNCJkFV/w?rع=R I\a\`x>ffAlxWrɈ Ez;QFQd 8hFLuEh ^. BeBRC.Ϩ!(B`Sm.G\c2|7r9 d).:N0,H䙿<ںa] ːN?An}r+"wͷyM@N1gWLM3g$ZK3i88` 3kȯ3M{O+ȍ3U˳tyf\*A }A\~081nv ' (`Qe3нYP+q*:ۜhk¢d5T9L]NDzC|]@aV?}"la{$ I /[(ƛ**ղ/-BҺ%hN}:`+p b)koȇW2ߥȢP"PM'z.m5- | j79靠h)eݓ=&JF$˾ W\RRx8BTҌA%?2d6:N#*dfc#6E7h꼔)-"g}LêxXh)t[^>qt.4YY%bTA aphoG*2xܭ/NO'pLl+;!h?]+`'"ҔG!#q_uKp2kfV-Ԭ&/ҢI1D OR ݖzw?z viSщcoH#MGztv@ > SP$~m:lsRw:*v㐴,z=b*Hc I~26OT *@BOEj-Ib& EVsy3哳ܼ 7UI8BhG@,Yױ#q%3(wB1GJ!rRE#pbEX)'̀g[֔<}D@CEf vu62 O,Z=J 6D@?} N"gymI ?BNZKJC`.rg ۖ$up*BZ-W88ZmrUI/YXɂ.}ʀwՒf>jX|觯;qo|4t|Lsj?3ۺǃ_~uK7ErĪfb m;E쾷4[)7;:tҸ+|<04mnW'Th,Q́`Xy>R<3./?w7RY*&Z%koU4-P4J&lP~7 U ɶoAbݍfGkNT)Qw86!q³r_d:Hbi6Z #菔0W3&eL]lu9]Ö؇liFKb;Vb[>u}˳^ 3%~6zK<$NS:SC#w[qbٰ]\Mo}#'j3e2E` ٨9}MC%_b+/X û4JRct9Eb6%g~ ,m] #ќqW4w-#M>RqXr3t݃nE+MN69^GAw'#%w"wwOm9kBE2Ik.h%vj<tz';gt\^_<|~%6f2$%SC5oc͹r-<7KUYn*br%#l_ ? `cw(`yR\~vv"GR eG -1^`/屉ZN:hx+~Ƹ,lGZ3zR 7|rW<7?<;?>ht>ƻ739-͘`J^mJ:XC 4ccB X0`{v2YtǜEdkGa)R S"8jQxxy(g)q$h;QMҌYIk}yn⹜&KUEt i Rvʄ!R ȱԬZ.*0vni004a$;*aSI1)ɑ黗 ?1 9*飘$:ɞ\\*"Pbq`j#Sm.qx:$P$vryRR V܇mbllSa'_, xG%٦ِ֍f qnU@@,ՏNG^dpEJzs 7ÖH6-&Iz_;H D,F\^F9 FBP :ɥ.#0XÍtGm KVu}N?~CcbS1 : g>Z'BmI:5cI'+γrӗX/*sI4d&&ut8O8}̄1ޜx1x|2E& ^݉jJ'0m!'!itؙS<005q<9 rbϮR*>P&X˔E(KXC3aaFѤvJ.>1P)bݶ"ް0V^x؟õ q?DVnIt{kαqZ  dVWuB^ɋKPnPf][pG)cTz@5PIaCUaRF[)N< [ }3jj`9oO2/;sݖ"`5M4p;QD~&dR&?!*g"#@-TNzÁ5kbqzFrBAl1? '8yEwaE:Ȭ%s~ȖsHn縴U!k zwt7ikJV5$C^h`.v/1 >v%Ply}ьv}ʜfb*U>ڬՍi'3-Bd(;k,ʻ<,"TaFbRetm2Ad4RA xۣdxoPxZ9xs:"BGku[Ua4I4,/Qԛ铢r .PlpF |6uZ~@IDATCQ.9[d^y& `.0@ lHìqLwhh^:Y?p\\/f0&"áJm8<_=ICl 4xRvΎY=eJ.$?6 Ά>~8*;#@0[~/ڍz ͔D zm?>l1MžF)4 lH\fS4TFQmxry$Ȅfm%*kRӄUx§S~s ǝ^ HNcQ~C0QknX3H(Ͷ 6wLAvBzH PH_SdE&VV;f`0JNATv=RղFK2ڡ2cI:#gS)l{f,sxTAH|BGo{z:cf T%lrd%vtx-G4<`dkwz{ \a_dF<ޱ&Z-p4ńHD!Mr"%/"y?IIJM=}dQEQ;Ȏ;!Ƙ2˫Yx7;zH9|yr*xE@coxK|ц;{h&$(cC0 ņ{w {-Y=?)H\K0CM &Ta&i07IJ1H̞$i7QTQ_6}0OD:ɐR$WT78$D +6.=]6;U׏ZA$0nU{ )d\1M|(R[p]8c"K5Qp ĞallQCgjťh33nTL{GaudO鸔$bZqFE߸ۊ%n;E[6?YEHs/Z!5Qitfg_N>+j7]*8FtnP~~y&u N} NFn8V~gOu_.//ջvGL4\K$S='$]SٙCtQ91[o{OOdԲg(^.+@^\;HڝIw (i *Ig"<>y#~|zzk;dQ{qRLh7RwuHnme``=Gjg 3dfԴT3=֧2cyȵغ2щzqTACVRIKB .mBqߊ5ʑmI_t k33dk^'2VHI2yLj1ΚC:BZ„tGKdVS$RMݛ +bQ=#Ya] 4_⸾bhʮ,GNML)F Ɗjǃp'iȪq b%9]"~ Ffs{{g? ǿ}?F\\~1詶q*[y';5Y]K'~O*cϭFKy嗓O?Op !f4ڂ ٦{IrD$l;M: 9^P0mc""3BW {UlF8r ttPqo"6GfNˍLuD; c`^ 1!8|3ڠeW)>Bc?l^w1a$$Mi8FRcdl(dI(jD.w@4Fc ѦI*2;( ½BR˒ \~P9@-gbc;Ow#4<2wN+8/i?(JX(NZu5 9lAu+- {\14H(eF4$&QO;Xc5jk?1B7Ti9=M@huSt/TD@~\1E@ 9ܟZ'1F & h /!]p{>7IԈ`-!2:Ra &_ly N#jGy*X!E\ؒ]˟}aYz8u`">17: ݌TfĆ<|wppTw7߮i?h@fl5)bɜl}Xjmm7RqVM?\\CT,vh_Ȧ:bMLI}4s~LTu{D-'?l[`̔b՟)?M1c࿂.мG&olD1.!=#33]5m۠ii* h:}>#Ye4> Jk(ռKA>} -Bu^ēIVLrSObb~+[{$%1:[{Ɓ~ډի~on*-M5U)΂/'\ny1?i<2:[m´daL*_Iut+ʳC_KDya`qҟmvR47\g_tk6fFgxzT)5<3$I]<.Q2 ]asa6PI9WݥfXFaKaS ^ 99)Ò znpJ^< %d )_ޅ]@X|An*RF]g7"y8HrHΓb<I.(^R8qv Ϧ1av!d<23vfDlEm% D53d6\:i3hH#'umO?!"mA6,ɭ$?c *BWL&8EJ08\y_ư]je(=!/bfQ:Fcy4ݍydQrmMh< [m,T+!}ݮ eRNiU'pnPe{J\`b}O: jkO^r8Ԣ"闥´5/U`8=cXD\3/[,81 hʹby5&* K3qT:%)8%1DI 8 t-'g;2삠"T)"Ǐw4(s{:f 2y@R]2Ԣ5$sPƳ/ůD =3|>\7OHUXA]OBt[O/ni#CI2d/XS:f|3𜈏4|S ?(ӟ0G]~W)]Gb>;YeU ofeɖ/QF[FC?_@t@{ctꫡ3&U)Eb1h>Ԃ9տ jZ)aԾ $2i}'[6LBo# JfHTAeb=T22 Ko+}#+:5?`8}n]ȭiS(؂uўdж/:"e$s<>~ Pz!xx{##x#3;"D,Ah[\jt?aP~ "$)2R5|Hr" \aʛdcbky u( W$Ի;bɪos^0xgEF~S:OΘM})0;LeBk㗱2cT1!uɠ_o`7;]}^ef70$ Dsݟ!ld-d1Xhi5>;=ŧ0AΎS.h/mUmj'yR.[$p5~jhi2!MTX {G"vNB)fg.:VEQ? A[JsCQϑqf!$q,mK2ܘʼ/O E0حU-Fdz {hioj*ʁXS-/=MS-,slU N$D'f{bP,] c`YzƟb Ҡebstj˝R3eYJ"/^sHG/ȒT̐\Nup+o*ɫl N1G %60!%#↙Q`q'œȐI+'39)X /G'=Ez!rfjI" CJNVxZ#ˍ0Oj֔ׄ%zouxb=G1 iSR@yob^yftjqO,^o;pT74LREnq?L?.u΋Gi=H_*t~IY [$TWW潽~Geiz~3c]̱ЅL4I/*TQ..^idHh y]pgLhMwgW,d+&^F9쥢-ׂ{y]u:ڇĽ*jNaE֖R{6&IeP\ݹyBGLfг|TOK]@,c(W|וFc/SZ1mi6\pLjP8)2";L/%w]гy$騶h{ 55յVZ2[֞FwճW ' /q Jj >=($̛R0<9ƗJ=*B%ٔ 9IoRx5<0 Z>O5YԬ1&BAb:/N-!dL=yĪ9cSWb."f-?}[AGRm4K[.5t#Rrl(Hײ9XU]u&aG^K(2t%aQfUgf&#Gv"N`ϓX)DZP橒To(LJ(wTѨ$V %@\r,41 ̓>TH2qWM\9K%W*p QN&fzp .ܓ:%_#,H?)6yHժ%'Ottv~r/|w])*ImC5DRUiYZN<`dX̽D;O6!Jy7$LC_hbtq u 2;AIhKI/L_[=GKQF^q_Ӫ!z07_nÛk앭/Ic6kЩt*U@jM ř4ixۻM/.#$%a1:6-QF'e3HГ.Y*MlD`Y*B'YFgnYuB|YibʺdXӎ CgZ=Px`U.4_;IlK>zg|M$7FY= M&DbUccG=T?d!;Jrxλ*qycṅ2͸v 0Xqdwj;8+ (1`$ikJ: 39co=OZ8_;O^ӆ2HO??0 4gUlh X/ k1hDRC&!3U.96ȃlw'e+CD=36)͐\n;B@B,6!ZS]:,? ā#Hq=题ڀ^g͏hX !tH#"a>vv;]ʉgD-;opw٣$TFo%tFXQn9i69.mZv *|$!Nd[|ewO.ut zu (TH1xDg<;~n9zPG"4B BӞN3IE.|n/?:Vc2U&#U1xvxv΃ʮ_/uOVDr:^Fo!D[zw1%tv~.m0p= 3ro \$mEX$w܌[%Rn+B6*dL@?%]>?j;>D-ۭOOfڣ swj,8B!htF~2v}xR|<~|Iv|v&$Nttx:!1bgqA;7yI ^RdjǴxDޠ܊Mb10|>PXŞ2U]6ƌ4!@ߑRwE+ [DcWtg^)hĞB `z't>T'jTf6Wji(Kȿ| \Ȟӊ,ul\+r+F1K>r Br=Hi?phj1 Gr?(瘚qvcM~Q% Up]pk'}LJ߾KW4P'R?Ꮓ⯪"8ؘTAEIo>%&;QAqap8`f?f0l FFYW™F+CuنrdrHO"sqh=HpKwN2 ٚ"CgavyHފG=1ѪSWf睜<$;◔dc-7a:r}MT6}rJ"B厷 QDe ' Hnv̽=Qd71*Q"*ɬO[e*OtD>˛NWulR!1Se"͝LJf#$t9v~I>Q BĊ~?z$i_ t<Čf- PIa.fsfx܆Sx҈G`{z{_&>P"+'&*:"1tuT+   \7yUNApmKR#/nBjWJ8gtᜱCv9$ H;"~2!8 tq\d$&M {۠Ey,u@@OT}#?%vYI_8g^8_>_3 Rpb2rSΑ0v,v3 (<ūq8JI߾nŮ:x11Y4'Cpw gFuhs oY)7M̶TޒY%m:v+'2s-ȅfhI<0]g؟ۊilTB`m}4Py1_ٌz2a_Q BYm8|3 etgg[-lIAjB"D!XoVg`MP ]cDTe68|r/KE6jgX+%SV2B xL !o78"_VB3;ne%Z=Рm<|(Hn6ʁ%a]mbdZoH͢:y^3ڛhm}aj-ј4cnk3<)v+Zi PjXt&z\}L~[YH#쒡˦XjXiN@UnI碐  H-@e\ ;"Ar壕 OLO3.WKaI/L#*]S6[vNh$ZφTxJըf sqΌ"\svqV-yˋ3 [ؐAQ<3 CA,e%U[ťNCE]t^# eŁieܾ>v;$}G1J" sΝVud/œ'QkZ!AKn=2p5{d[X쇛 ] ^FF$wV@[Eb_h1`xd:q/e,Ē6ƖvCRWdD٥j= xneV,5*)Bqͻl|p;CЪ7V,`/ ȳ^C 7ǂ`ҋS!pPyoQt#i=4W'O,`h<A6SlZ?9SԖ!Ã%3qM}"%8 lFlURG- eK(BB6ͤ 3ꅡ(٬ :e-녀U)=Xw:@41ϐ9U  8y[ʇVve@IEpRxY1 8 eRnhB^+dR+oLbvE(ݒqsa"%^A Vg;s=>4ѢժdfuYaA@(RP. IGSF]^g( =s :ׯ7ĥ@4vф'_3STBTMZit|/s"D)1^#tR>^tuqzOf;F)7pNi<'WJUŰ^{öۦMOyy!E@W%XvȏKra/+l LLr:)(ׂ[AT)PN©=> $,c*e>=mpG=/ww`IoWҫ/"M3ٸ/_3=o ѺW/nЇ8J .)j FK'C~w,г$i,k_IIVs4!ё_8b{|b j=rqwAThZzs9՗uh 2`ԓ^e@eDH=x*j2J-LZ0P@ <2t u`>#2">)lzwk T0Ea"stwi}`G QӼ0Y(T;˒0~TJqĹ97KZ]1}yPgt0Wg!5A*b >iBtBdC ԣKHa)RhVn]g_[1H=I\ Ļ]$;!<o37FXN13e0wwO:ޣZxiSRF_@(s&9r0deвKiedWVӈ@!kIێC% (`nghA6}_"J!&7@^ƏaŪ B n#U> d߹O'ʌIl80 {T 44.R$U/S|Vh.!=5dfm3O>]0;==훴~e:Ӌ%_>#McSC81zHj@.6-ZSDRϗ|>$L,DT@DqgQv4YaHs#tZ% j@C(ȊOe贉8- /5!v v[H8FeM#RU/\&1up1h?zD}NT^07*60ݫJp$/˛g KjA/ю-wv:$rU\91 F$i0BVm7z د|dGŒ.)ύ( TANEOErlGVo~Z7u"`|mEubqA, h,tm$k(\N\C[4dgPՕ/.v⤑BN4Hra 'QwtZ^'\:*qyMJdԾnva7NͤPH |ư+!O6Ve9r(sz)p(77 ] Js 2.*5j<5!0]}sP"T0I:d..p[Jtݑרp(Lݣ_J/7WcI4d3ޗP Xgy*&(D.YŒHSFB|4evQs0JL1-;g.B5q@0zvOmPw"&4ʐk1>s7ℓZee:yVMS33șsr(v8ط_DqxUI]<{BۇNIl_(рИթ~/FWnNG_ q.ueE]͑O{H^ᄔ`LV?IBzLm,Y4䘰"kD8)t3$,͈4M/DqBP:_"E0? ;OXd""{}mdB|'Ōp`4O/I?j^2ARJzWjVCg "VJeORS^vDY "A"JrTEF2N!`XQj[gHM9%q=`azE9tBl #aG@*Q,g\Ev5 Ze3 -yy9myQ^V 8,D`So}sQlAddRH_dJ%ʜϺquW>뱥.պGC݁% 㔯n$Yvb4ZOdh-֣<ӏ///?՛ P ju:ٶ ?2:iHkvĢ2?PŷxGEF6r|07}#q3)\03#$ԈA":?0ּW6MS5Lw6Es/ yF񠅲_K{ A05w& }fn눻D3_a $b9C]ZU#d-hԻVgNDp =_s p AEm +L8e y 4+,>]'9v @ZLg-'3>E#8_5$KyU^&m(&'B(#ޔ_X7pO u1ygmhLHB^ /&= n>_ =Ś/iJ*#{^e2$"('n7YCFDFjXI?bΙLk ~xRZm0S_M$R.<8GS8ڣUk(f ~5pXǴ[&#e@6A.qMkeLF[MWcL [lWřrBKF?aPnV$//sS ݁_A2ȈjKvP#H (ptNh*E _׷ºnL@qP)%@9Pa,0d2B˧pX+ X DKbҥTi]_oZ#=ŧOL-Bz(x0$X1max:8gg冉`xh9bwSbͼ2ؐ-R@${o!K FqΤBVf!ۛ+8Z[@((t z|r?A 컇:MC'cN=U,V#3r & 2N.A _,+^]='LCҌqRoD7H?~vMc,-_ :bWsDD g[H{7W_^~ tK-8@p}|PW!q-9Sw;.j4}N۰+(D80k -Z>U' VWy 5w/0k>jT]% OB_"j7nRKHt.O#xY.ލ]m4P6M IHl>O|<ŕſ_=_~0Q,-5V 3U:r䅝[┤NzAͤp 5׺=0t;nk~#dP{5y=sH[JGk`^, *ᰕ}~˘`7Ȼ}k4Ar{ɭ|ό{COdɹ,揻>:>cnGO񐜷C;'%v2j)-]sP^lsFB<RFhow٭cϢ_f ]7@prX)Dڮ '& HvS:"aH:a (%}@FLk> \wBxXu8Wz}xy*Ww,V&f_a#C'k w"W%`$=R0I܇{\6~_ȆsOCjΒsL-3a:l- dd& jg?IGbnJHA )6O2a[lL]U\.ේE%TY쩊jGha(ۊZD.FklW )uÒ,4ZY41~OU!Gp#Wh?j®@)r kF蘗cb_D,Ǚ(8Ͻjj^ 4o$YZu/I(B+]EЋ//Fd펙lOc]͒F;Z!G\m>X;rs>kCu6B 38^#pd 2JD="p%c 'pڠA#Է3t%66-uƂ5(,][8Ԛ?[|ED|ߦ4{Vn'g+1yխZ"HpW|A7@1M6iݿv})թxS"/\?m[փ x!T;z nkK ~_j3H8b r´igU4R/6rO+ }T@L]/rEh2xg dW4ww`m*{RVzf x%<4NBғ^ٌ|^&*X J1 kW2v>`ڋ:'gon2֓ۑ>;8Z:Wbl0'|i"4ٶ&.8x#6i(iO5拔EƊbm-@-AS̻Jۛӕ &J͋F OMDkN4MY!y}Q̚DdٝXRW <~m.ӹR,S赺:ԘǓ }v$\¼{[:8^0!o8{[ݟ\XK7- HH40NXn"*/ 0MEU ŵkI\:Jnȫ?X' aJ֩zrqW(Qm*XPW99\esSZ(dAj'$uD6 =鈓T9lM;14!3+Oݎpw]U=j߳8T>[Z$]!8~Or[ޟ%`(>#5 l^pphK)`+)*{O:ݫ x۷#\ㄨ 4*0Hb+A0=P+B`+N.n! !HA%s`oTמhMʴٰfܖߛ;v8i.h9N͐'V1_ԡ n[ӷj!?<0; ]9ys@.? I$L=79j7 g 㱢QtdQ&L1H,^4DC C60̙2t^ţ4JC쯘% $fRlKCz)fe]`4s*4>I#1Nس̠3fV Vk^2X %/Խ,R ^i9gIFj!Q9*xދGATtc*XqaVbabR3NQ,<ʼn+1'cY/DBu ҋ"+L`K䴪IJrYKĩܳiyJL|ط_Ga0Y`4h"bt34}($")'^*"R?;h_p;c̟̄48'k$, JxE6d-]SЅ"ׅW=PPzi,YX{k)B0,J/zO%Vuʁqpuzl~\`$#P^VK8T6?D^>d`$gIk*!8+04Qv\)V3dRlI ${GxNBȗ|m& 1 䇅tUtid/ WdXmXKt: O⃼2)id#_WL @"p+IAAHa*K9?_W[云 \t ϸPnNCG*Ayxav6؍D ) ޞ@1ܓSyp53\w4YSie޴l̇XYk>UX'{Ԙ @;Ifef83nHrp.K~wRʔɄf\=ISS/\vR㪦TŽT9B 0z e`q2X;̌/h^iEc3Q~FF^kCVH!h)}l=͜߾8'JTZI⭠.7si/~=}!Wgl}XDf+,4~+ i=\%b8n.[y=O{O 6n\ݱK Yxtsm]}khP* ՟4DZy1\L94>r]kѢ}@8;Jjލ6ɿY@0_HeG`G" ȣ3ǤG%ZL jU5! `Iy3=cŬH7Cmxyf%-n{0GBl 4SE )R|7BWڛm4$P [ ̤Lن嗰A݁"C5GŪ >#\J1yJ-`ۯw<ߩ]ŽngLi(O*GѦ}0Ջ+bBC>S%S w2a>&)Ck{2Ȋ6Dꉺ?(ϟ>&L9G ܌m_2%l& y[}S[Um$DPA^WfR " &+cƺы'Eư ncMjpfo>,iV/^Ȩ9H׋ahW]"LM.x4D"T}/.Sr =zG!G;ZIVq3oӿhveW(z$6d漴xۿLZ.ϵ)CSfwN;l}9Br9)Ҋ>Oa!;ߗn@Xg ؼy_6Ĝ/>1R"n=I]Dqje2[J$ʘξNoۯb!l Yշօ#қD#@Gt(`26? + h0?VRV`,=SrTq XJ3YĪ`A*FGK{rn 0>3۰ ނk,)cN2: 6Ō[yx9ؔDGo42lg1"b, JRE۹~_RM@r1Wnt<#XC1[>̥*S>Fb}K%L['Fe#7&,s >Y4؞rPUSC>|hl/\1KB|O5=eXӖihs c2{/yv LJjjېnU$.+%Jޕ": KV;8'@޹f[V!r5QDH+ mAC͕rBcY[ pA2av '½i,8$5=CVf)hEhn _t!hw򴞪#k'eE77WGʳ=3Q42{- &:&fb+Ƚ0$H0KL-Տb""The|xi3 1\Na_՛z wƯ8ԤFr4+Z!y;H (;kl5z&i EB5BƝw(&*dDdf.7DHXd SEZ 0vR;ƁIi~S@icaƙh!vK}X !{Z@ql+6-7dgDr9n.uue~ Z5= 2イ+oz67!8tvg .J]u#8&,b4kdO:Km2`XNIeɳxR~*򈯘e;IeZi8T c9ktLUu#UTrR H>|ɳW sPs1df% î& c["Ѓ]׫)V IDet~q}AGؾrne膈 !d?bPq}6. !knaRX^QK 0k0 wP ù!sw 0 U8Wo.jI}mp6n< 3k,ÝF4Yǰt&.Z@O\A{O-q(TqpeuC((Int(MmMV"Jj$5D^~%KRL tvW9R0H*ލX=lBy [*bK_Je$i(p \4^+X+x45ZCeC︳Gb`\Iyq4I6ۋ+@+)z|~*P+O6YY' 88*7p ) !q5~4VvS,-P 0RY@-aX.ѕϫ75/ Osy.aBڅ1ܫYRauvA\fhFA/xL|E^G|4<)bۼX'j %$4{WF\sI=nlI9tָatMՓT[#vzCCG˴0GS9V!%5R잞eT2W`7pxR4ZVgxLB7!q1bKp@FHqAA{׉~i,>}3+}DG< 6{3<pHlvUiW9 {k1a&M*䲐l8(U( „%Hy-9?^s/ 9ggn=|}D^1r6V(0)?Oȩp˕4Ų07T>ܾI p.2Bfȥ~>1S6J&`">yR #pc˨౴W8gΦXW8BVOy9"D落ͷ`Gg $@-8QJ:N?'],yؒ-HMeowsI El{Q 1hSǏK9xNI)^FQwhBLΑ%;GXf CƶNX䐸cd+$DU<>`Aoj7[u^ Go, H've,A$RB)k&+=VB8SD.jxAsU01[:E.j)o{ V5eK8CT>1" É!L=>2"8w-q\"XPYLV/Ɍ^kS=i8@tƉL8R"QĒ\pu[d7v܈#b9x,M/Q׀˼T d%_x¬uX}z *XI~>H :8xE>VF|֊ˈKBDMc;mf iz?]dӰ2b%alK$ [2(*3\JCr|{ A'S S~X $m](˯]E8-CU>+u&' { L9tSn\7>7؞GTDP( 16%r\`)DMjtEkdfoՎ(}sʐucuǣc{ gd@vN7>N6w|Ib'5=kIjYkzx5E1N(#& ҃Bϓ8>H:uzn#~~R:HLWƩaϗ/.զ_eX47/!oISvA|7c ..F&/Gakזsd3pm¢7Ԝh!phIqaVoOt;n5 -,̆ə-t{B)~\(Ijc4-Y Zt$VH?HHZ8Lx†@$<qIўGU9[IIgEQi|fDy;D\@SgKWs5=jl %rtZ'`ޣ[ͻQӓ3ށ柮OMbB%깔4SV>dFMXv48B Y:W7)ƍBPөlzqFW[Xśd?|f uIu wy EP؍g\¨^bW7_G@&;$HXO)>-lR3P } y.2A/ɳ;+M@ 7n^sI֒oR5U˖O K__tAں[扌1G 2jyp&#LWz(g``}!phrZJ-/(6O "c2dSjؓ*!lN(&G@x ݤ0wԑD5lS?1Ժ [rp׿ lCa*zN zS ̃ۮ(? z'ʨ4,G]v*HZLa9UEa}lK"x.5}}ioOv6J@ƻX^I6Iݭ||dR$I|-Nĉs-(V O\B6~m6&HRf#UK7@Eʢ5&|$C77n#|J:Y93\nҐ]6j< %aB2ǐ| F`s}2Q/a߾NW!P/@BKd7.I▄qh^Sx4Km@ȂNӊqRtw Z RcLVITzeFI zHvl_s>qAW1V>=O-J+9hV/N i lyA g AiL|P+`g\C:Ϻ PS{þSM(iAL(%;Uf!"1Sg?P !.9H+y;8 :J&/>׹48K5?;N4` %{}\݃@FY$*˛Lˑj(9 H"Sg) 3'">VT87ߠ9:9Tf"Ǚ4&W4(O'?__4GWұE~`b ~͞fB%ZI.(ճtʜ';(Gz:K@/-ضoIYKCK2$Pb&݉=JBr3jϩR)]ET.G3:Z,nFBr0؅bowa]_X\ߥIzkNW9DtS\MDHOn&وT;˴O2c ]Y %1XÝ&=_/fOFHrl 5o#!%.1G"3v & rЂ\ېTp gr|#ۢENܠ;Ξ& 7B-'Kah3~`QrPP -iP.c3Lcv%L(ۭmϱX0E kcgE31$:l;m*%>{ߤ.xsByyxRC+!Ja)5ZCr_Ogu eT0z"Z,}(Y$S̜<"G=(|LuM[},;.B)'stNMyW:=\~Fi|W(VB@􇧨!Uڎl'^ch1Q(p^$g8 hc‚jId>!84Nj Vr39ժ2;-s.oD %(&c/@4jz adO0YQ9[l1;ėo" 7jRֳao%D ZumPOjF+Qz" gAM%o e[c{=Ebk0€qH+ rVq+gHr*J<~UT>&{=#҈p}P)P'"g 씎рiO-"@9@ɵXΈwϠΑ, AO.޴kԝ&3qs͘lSotx-N/j($| ?*-$r$KNmnm'Kh ` E Z+V3i&H`Vʮ&T1}FpxtxcWzUr-|Mj5X0%B!} Ѫ<9Fv62$ z뉚X ouo4KNU,>b;,Q-ˑv;Q5#1B?rPc;Z'|6#~.eQ,R|+nNvl5ر׋ ̊uF-iJwrYJpcwV<ҊOHrcA'ɛí皜%aI4a-Qy0!s֖PV66V"XPXwvPq=PY uiP.x;L,43''QL?k ;^9"*a?RȱsoPwI S| HWɢDTN>+c'5UP77!\9Ϧ jxn9ƃL 3t "tH_ jbchh2=+0,9:X2cMu#2#d+3%hY^6YRRlA2MըC"~\$RKb٥\`JABp2ꉳ'%p, \gh_bL8`D+ N %l - ^Ο_(KSZWT^#Io; 03cJ>TJmVctXFv-sU9ӫ;FpÖz8p2HlK+ !R/: Ax)a8xlbI$d["kyXuIAڣ )ITsȁ츽c-4M _ LzF6v"HN VJ$[EY&쐧Hs을Պ!/| S S`3}r&Bi #ҁh Q$ G]% \h>b-!1%0:bfχdr]5]sН/8EBմTBSdN,;EM.ʀJYXOT3.t01G]+}ÃG83 F*:a%qIp=m蕢h biam;Jo*0h3P$  K.~'u?bbyך 2)l ؿ;'Hv k!i9Bd\D6K,¹  d \fؖD6Gʒ b1}m#0Wf$磺GdZy_kzпV\%(,8  }-UԢ&O{ED nO!ވMK􋴂m KKNԗ%L%A|I}_`Ӭ-dB˧;tl <:z^## NϺ3c]j<鷮!3\p ]rzuu+-bAwq|~M }cuq4.`Li+ ? ̺Ƒ{su9k|yD T k0}IZh_ %Z<8!ͮQGTT` 3GF He 쵪 #줢'ɧSAƔ89H '/bemFOcʄ#ul>Z!c28xzŮ!jI8~$a œ5)FbMR! 6ok@IDAT3%Y-Ƿ+3f2EAm"~l=БO'?S,̳;+uwfT 3bWrŋ} l]B *,b>~ʀ޷Gý@B^ߙ$c•=M!JI؎<_=NmU!9?szLJo?}E!t+VƦkJ*([ޘNg>8H&gycAA/QN*>{ vd(ed"rʷҹ^Y')xK0̌(Ϝ6n>ao>~ok;5{x2&Sm@X{?J4%_a=cp)ҳ嚃(sGs5]o$SbǷ#]Sj8LzhFG p.* RA =)PGV{.Y-5Bw@2ڔR$6#8 Oݕ,Hb]#j,?~Bhmx#- eX0r5WGGK?Km{3TN^+ 4M. `l#p;kEr]/B-  wR_ZA. lmryI{rW)=fKYAtKef"o +J"؈hӝSIZ*ͤclc4sP(9)`O{KE*º$I\j?SIP0;[2d#$Ch/8Yg:zP`q0؋hiC~c%((#rl2jKdU,^J2hZ6=n"*AjĮU`[N,!~ '=զf-T9OeF}f|W|>үxõ)YRgPmK۔Iu-eSu]V1O`RNa^fmY?7%ɉũjUpKGT^gDm=! 6n@k i1Ӷ hP hULfT`@UG WQ9#ڋ_wIx9&MN^|CIL؁v42sȑLUCO$4K2rʢՏ u? x T2L|Iwv򢛍 s8h k< Vә2l=Kv:iڛWkpEkL2~0@($}b> 8?f"ad 4e.Az6DHyMDi:(i%@l%t&\3Ճ1͘(N$癠g1!vXE Aϖ<Sf/"3cBHGWiҝ3V9y]14\`z/rAj2gbfM`NV_xˣZ%ŗl 'ӵ=M.YCy{UC؁g6 U"fl UQIaL;f 1a%UwV'9Z!ջiĞFhM7I%n2P^!n4HԷL >1zzu(/e^.Κu "T=g<{$25#"pDŽ hV [ۮ6t*ڵB*yhYjkr$Svf  (9LV$YnqXzN/b$NV@V4X`52@֕CחoIݤ “_LIPz/qLA% L-vbU˿pκ"4T!gT@ϓ0^kChe@fBI RL x,(q;{Y"4Q;E BB!L!`EjGP@\N]*d.| X´MM4`6 ԩAAit+*RObYOX7ع[0:MP K1Z_֋gDA0# o[5_ﻧǟ:٬O@(%5A6Znۈm9avER;ls=1=ڱ&7L}K@-mN,̍I#R%9Ftq٧ARI  9ksdY7Pg!,DʑbOZ.#Q髆XVC$ydhAہ^w Q[WTt@x  mAEwRko]%o^QjHm_BO1dϢ?Aɤu'+ +p Gppt@GՔ7M]>WX.pnH`B++kC-z(GT̸VIß2ՔsV>x^RYcбWݥ q8#u^(C4),Z縡3;Sfc[OfY%O[R%XHMBl KV#i COTU]o`vCGY`B\y)}K_yC_a.eWȣH o6-Y$"}@!qbR+qldĔ1-R#eL"/')DVǬDZyT%-n~=]˯1֜o@ErshkUQpPlt~Y!Ԉ_ٰA9;?Yr 8Ϥ&ZJE9% bŪ|-/h`lOd 1{H%3 8ֳnj!f$jR;qĖ q, mOrc`dfI%iIY8Mlu-褸g$s8iXAzFP&E-v.N*ilה ˢR :}6h'A%=6 ZEv&-?_LL|YGWD (0^qe3fSPK'`lO`^J5fH^ $e, T}0DUZC(BI:K 9K%A@n # `}M9dm8Pe9_  =~a MBRy,(&_2P`kg'W_ßw8pl F .f6j+CHD {|'upd nçfĕҝO] L\9cֲPѩ>H>Ŀ7c$o!ֹWVXrP|aƀi'6_T,N|jI ×d.>`y':` ̗J4$?yz>$Ǹӵ"K'YS#}B  n0%!z72bl/լ"~;ӜAZf/4/JuN{4$-@ O'$={Ě'{'[QFTx9Cbv~7<6)L\"U9TtAī*/)/jgtCgn+R_<ǂ*&DhfE$1I]}(Ƌ'#:1uϩpVal}!ڔ0pc[IX^͈F[:(O*Ba: *BQ/[r"?";bJ{⇸U{Jy x$xUtN ǽ!-`PbgrwRQAJ]w˵ɍ2\y:e͏2bz1)kB"XKJ|?'"әC8o ^XɈ5) l_/Ȱk'l F' kĉh\a㊔~7wWni)I_ގI%'|M>[ TgPSr0߄mtΚьz[Qt^[[$ Ϳf`Ɠ5ߗkORE<d2EEK4lFbx(O*xc݉hf :GnF$!fvLkRhy4Nm5HQsD8g!BŢG+ og#߈ٍ qЕR%6 +D /%YpF_Pl9҉<#0&9b6W(%JH=nI))š_;Q݊6AN)bͧ8Pˀ1IV˞'F&Ͷ_Yirqwb8#HCEF3%U`]Y.$OdY@4JƒEg:WC0`GH:O_Dqp`?On ڶ"7ޗU@U,|V̱A|dc,ȹ0e_e(JF,8< &15V7$͸ G|ZT?ʅ2j(UuV%/&dd%Zzs#?,nuR'vL` 4n C@Y޿dikE2#%;&5BL˞N,/5S F^WI%jm(AFlmwO<Üh'5JjX.8˙'fx$vdL ĄvR t^ bm ִIb$}?lz_vpH0(MeƑ\6h;Qc zz(!2`'%`[ kvxuHDiBmrVx,o4&Ĺ "&Ʈ5zX| 7ojE4Q+S+OA_h-XSrKˣm|9dqˊ)|̣29HtIvvHxVWG(v5feCD+f6h}l Qd[YGTgЧ(k@*a҃=&KIw1Ȥe(~EWC٥(9:5%#V`:V5ypۄ 8jpl99<Ik)7+`V0̭/y(wCDNϪ[HO 뺟]^gIS ?O]Cq %'!}ƕ>a0M]M mr5.J0#)_T~ZIo>"E."9>#LyXOc>$.zѨ[ݸ< G}MG 1NCۇC|ޜeyg{ _ RY.DDu.3SHm,jS dgbθ8 qUQ^k ˨(?r)%uzdQ :+O4s-#療hW\X.ce @,';t[r\BrT&ϛ.$1 NNy,?*!xW-- \#GmblM~¤b+\f !ڕ:wqy-Lb5_~6:hGY leBGO,U+D +δ)ad^#O:} :R:(m˾E͆/rD=6$w=CZ.?S/};vY|$))fo3KN'#sh w BO'nxpDŽ‚C,׏_ͰHbZq7&0DА9ob̉CT$.8?t"ƴ>ӘcJJOLWo{n>ue݆3Wχ M&YWM`i{뚾lPstX6g"a\,QIsw5vBi-8B x؋"G`,oh5AOFx2+,L4 K_o}Ds;d8Lv;[`Y0Nv @ɆFc\X@Hʵ)h?*cR  4iR3 y/3Ȋ4ntuĠ8KԝNS@rR*ڷ~ `Dwd58gaZ9/ -Z8g;8?RDK])&xD|Ɔ!f~fzceplʽAʘz܃g'1x ,u:y:^i³;,,`CVik`e17-?K")6 {d!$}m{omL~ߦBӧPs"$[DDC,ѐ5Ze5nˑSGK89!if+tIRto]+ԂEnO Kx5^nbeK'/U KJ) ]B9:QaKUOxs8NVޑc8bذg=tg /q߾+]@~ʰYi^m'm< >e|:V,$(NB,TksAr'cWYYpr!mhxWtt fD0)ɧkȑZu[z'YI7'0G$OU3 gO*En'Rr|?~~4)ğRdYD7cpERrxuc\NF8/XvdcR|AÎ@؇9gaM@&[~ft<5 Kok4e$'lH>vަ wcdX80 /.YiUdIZ*en+9tdly"LMI?ztqKI"rQT+17gXidX)߿}!2֢Wt~ݕ͐fA$tgfgT* 3+ѡ*SB e$ %Oj˴C4$zlIT341َ-T\/wN Ձ3^~-̣ f,DwM?#KF 0[.-LF~uȸ6j;rxP|f*mW뽡h3i66{U˚iMf;vX/5x|3w_?/LlA5Sw+[IvEKy(J9+Yvi"}eQ}c2n{ɒSn.-0r٢JcI{QCη.xcuފL_G\Y6D]HM[;%)Nz #r80U0UT*M"x`* 4=h=D0q,7ƊrtdgyZyCi:%R':H=-VwfVD*a2TTI7;Öl3!⎑괈r~|޻$ymD%h)}OX C_"TaU/)w'<1u#_+C!JV0"&CpTQo nI/ks4XaW^#N~d"?ҤԐGkέ迧#'0V)C vI_*6i@:Xכj0J, ֹݠ*{~VBB)5> v`Do%KLߴ^H [@ɱ ;AHx\KX|k (jDxnJ;8I3g/Jbہdja^;:ڐM"B24<{JxbS"m.C ALzEc OIa׳SW~D0Sв[ ciAߡ$1lL !PH/NARE8Ku4+\ 9 v˳د6\~& M̎ŏt[:i$e}!)$H<ɒ(99Fb=NʂoٍqBi@ɡ:lk# [c_$FiǷdg{uQIG^^%\4Ia(=`u[\JkL7#u 2(XV bc2j|W8 т v~) vm1TU|9>3#<b(%dHSE KM!Qb>X\,^86Ƌn~>uiwz~4#20/+jev=&Vk &U`y^1LDY& ㅄ#_<̍&P*DsӧO\o<)x@ @~d-O&& ۛK=#q~*; [$nڑ&|1_ĪIRHIAr\2-!ڛ.aA|YTtZupBSb~"JPۀJC4ۚ;O)8^>

    0n>zuç ,+x }mEā2y/g~KgR&y}vUC\zp.6%pAb Wb!P(j^3+RQI!h7F(_faG|A11 pɢ|ÀMk!AcLdK* F]^m,dΈI+M/ DN%n9s&=y,C$=Op>Z?!hNaLX$؆zY9>f'm2{Hz@ڬA:x{ 39)YҌI t{D,P ]PPDɟsl( ̕lt N\ ‹Jp[Frb0XSrj,? geeW팸!X ">p=Sd[},Ry=J&$L8S)lC56mFv)ЉGm, 2С9@M"DKOԀcIXYc`͡a$T9z'H*hʿA8tJSu4ofpCF}K0lf!=-g}1dKn;MT!Jod[oܟаqًGyBVCT^RfgŚ\'1]0G]j`J#1D/64dĊKZ`zb3C&]@M.Gc.4nP#>^\v͎\Bme؍/;#Q䰤 e:}Sz3))r5$z Zz~D:4ϋ2|1,޴;Xzh,ggTr7ې M(w B.%:SXfmKImD*_*om"c;XjV#ݫ'lY 8hxdead #:ѽ Aif*LdkHtnů4)= 08^0n{"U-~؉3.?~q%CI ބ=_ fj-9VF7c@zG7p*r48Re~7r"IZsz{H6턺"|c:W;Q/#m(Uw5<]&0#U[gGx9}׷A~|Ɍd,sC~R]$ad ]SuegER8")j9tBuuU}nL8Π[6;gXN | I0|b֖JT!JÉA~91X&;iEeh`4<5B^yj:=6Z^'R 4\eRk 7eNG# tq#\Qb\.$V#VSQz<-܄\$D}qy Y={cHaD-"d],h6x~1y iO߾~8tfRB1=huVjgHeJEC1ine8TX,I.ٻ\O'hPIcn_:)/d5eBen:k_(H6w3Ccv(#Exv;RጤK .)1۩ L\I}(BԓU~{w/` #I[k9iqԸztCJͻ[˕ c T*T(djPKzA:06On#zЍOǼT@`R'gľ.n'}DŽ<;#me$3o?Y }w{ Քر`?'3 ݊nR iyW"t5Ax8B\_pP_8z/U4 AAmщfGvWX\#v ;1_)'Sߦ?%)b0IVYL[A (ɸܳIp$ 3%Jћ2+Ai*ܞKjQ9,T\9hQ[,)i3.$-I2BI:$;S.dY FDfeipo44wC^ÏIrXLJU,вc,&P &^fWcobKBeJa,"YV_1mim?ܨ0bzE@Qdr|~~ztu|nφ?~˷~-0t%էG?Nq8KGDH(ŎY?lZ2FĨVe$ LcQ&zpU砺ıRQxt:=.jԄ'eQUgȹy`\^DAV%Tm! :EJ|p:A ,Zc{nڙXutRj?:FtQ}zAL&P\' "f#JΖ%!^Qӡt;Hp|͐\Tmje hVjYS{ jG%HUR~18KOydG& _*{oRJE:0 E>j|(X7 M*O.a<<||dq+[T |k:pΎ;Dzm"Ro_~|y|\ &RF[7l|o7,ؠ6CM9xŠ(bTִ.*Y'fo&:$u\%.ȐQoRV"Xex_~찜@߱<"rc&7368QlpSM[52P$=Rs@:VNJӒv|_zuOUw{*@pR*Et Zpgό^P,&VIGk0kqt48S6VAة%?zHtHfO!, wsODME:A""7Dѐ?G6^fk#`פ] Ax⵸7E0 bETɨQ\^~ox5V"J@zj=YVw"5;V́5YO^x)|UQ~dGIT24f9lF³'t"Ό}D8,`g*$ƴVTzF57O)ЕU"?k1Fw8b[30@ƜVK랾OԘ[rL7~!bS^ Gwv}6KM+JžV~)=.C+PYhdRj{f0x>vI֔sDq6qXq `BxbuxXA` "!}(Kd9 ."<^B``V)ɰ leR&R>LN9; 1;BaSNׇJ3I @-W [Ml1ngi8R\r4R^NE鋙ia1e0&O;g'C^Q2 \qE ^qgAlQK!*ܜ&/t:?,˗/" 16mŽ+www$w5YˣD,_w{KyqH0?Ȩa\X^~iol/!<{tPOvq^A$E@rtaXVK+vF3|atTf;dnu%8zGtUޮY_*W+lL} C^_iSD{v{u>[iԚzPuJ0MFxóg\D)M|%2AGrucXՠs3X-$#W?7JmЫa8nzAF&£)h&S$_UtPQ@X&ITNNuX9zte%K" J.1t%,ls쫴n@x[/U)d&|ad'V.ɩۑuVVJV _ nW7LP2h,f%*iDy*Z2h4@y[ző,/ dW# 2t$%:[y|px+k}jHRo*!>K]ԜD26#“tF0a-Eʜ{\aC3">c!Er%ӫq)狍9鸗m( 󓶂ƨ-c+GD,1HK&& -dwc{MV\_D lыT@ʱ4l'Տ1oĩ;RMN)+L"n`M|BK-R3p4rL5 `G;%?dw"x)TrNZR{BUn[LXњ&+DJt|(TlJI/Mx#fמKMY2p |V */QjId/>+xe]:aB^o!\k?-DeJ” FJ3.re@l4+4'ۗRoΛ.SMo֯SlFļ~>KxyLB]]E:+ īV/۔?F(D$𤋮Z+fڥ$:۴B!(fgZI1G5t 1nw~JH<-jHL/u"ac[CWoC4 v2!iR{9)"ɖWFԕLJQ'HhW3I]GŐbsUBAt*܂d ;i4v_mil`m(憃 1x<~ssL x⠁܂cPzx?gϑ0ݍ' l#7esa^cL14 )HB|XId~{kuDaCXks=v6JWY~/㔁1F3IɄ Okl뎨lqiV$*͔^bJ;_S֥l 4`YF>׏kdӝD6kP4JVw&[Aӷb-6>"P3+!/HaoL֏Bf{7SVT}s54(E&GીmB ˙G qfTHK֒\ei$>J+NU2ϲcN"u|%-*5koTO8M@~/F>ϗW7wwX6 >?CI"35g|02'# Kd-Pdw:R',4UV 5S=ԓ%Yp 6?>ˑPViR_@r{(k&|D,aD޼<-H'7-BvESS-|hJ 6n; p\l?eUM_Ʋ*@QKyhyH>\&Rv@(dVu3{,EY+A:*Flt$P^٢[VqqIv IyHlUnj5o6*=]%4 40QhCc`&#ю!P5dgRq>`"uxEJ\a񖬄V#a{}CcY[{!(-)fՁ(^_έ` eA}!z.GS1z#ar&Io0=OHSJC f=CQ0~r?Py٥rAdY#\,?teTH*1msYoU/4tB/]hѨ5qې^LE'H F_6 xVThv2{oWWW )*peY'@b =֋Xg)ɆI'ɄI)ɑpـ^OtoYZũfF\`D#}r~-S'e"R'Mc?v7&,֛˿"{{'Iji݅h3n8%UW(@f$}V+4pflδiv60]cȞ* u&,*oaQO:C]^gt!FOU{Ǘli%ppT٣S.,+lCL4|#7NkO$JEв>^4 ÐQW;N*) uS_mm?Ya~-0DɷϪyl8/;ck^B6)gAd`UU ] {d^C@)$?Ae1%,j FYdBM0ˇ% ϕ;)e!);soR( <- x%2!݀F1B#O~6P!p|=UՕ7kuo'o\Ich}v=I檫Jazy@"Z"/#E{3vt–*["x@2e/ʳD3u};)gMS? $@Z>iC!i--_(t-LN%d;^'>(8)7bm`o9y]@;Mæ&߿ghZ '¨5FpD9%11 a0 +'{j T(. ı+M\|þģz.2Zg  D:.\\oHWt_ZZrb$O*H#*5;a?ZHgc<~Mg#RAb\{l[t{%$RVh']&+R!pU7O#<=` )LbgƑMD7$LJyNjmP Dȑ$r5k"PfB#hB֬6:>f0Ѐ)JMfAuu  HRŽ9oLHtvvGx$tyLAn9[,>i0I s)4\B PU#猌!| G|yqVGIX  ̫+y&cۧӻ 1@7IT7Փ\4~gȲaH,9+E/hgLoT.e;[KnJxԓUZzGnzvCN zH(B[>lCt"Ǣ*6U4b晊.p'sDj^u*eݧގg5@'DD%FlMv-ja jQ/ĩ!f4mx+b"瓤\h AN?` X[\ɥ)nNp$0ρo4s*PX=~mY>54m ȑ9(XBڲ?r9&e*-0!V.CUt7•T}ߣj $4[H>q~o4Rb|e&kĽe(6GD^Ι#" 7 h3 Q}^s*ϰ6-?it8 XOW3U8xNdD5[U*vr7a+KLjQ? 9;76\_0IIjO5]guٰ0rH$Cm7`Cbq j"s}9QP)6jD帎2K2k1)r^8AKB炛JJ*.P= Su0<$!?p5x_6j!w } 702֮^/$qݠI8qqo0I%]٭G=uZPX'J񮽓}GhLY$ *T@ɲ LYN?pvΈ//YwPXRi;(Ã1BH#%4&P_ 2Uuz%iH{wn/ˆΰy Wh{3NL-nRڈؓ5ɔ({8\q"CPm6'hI_U씚{P#3Z :8p$[3wd-]3eq>R|?㎴xR&:M{ᗇ/8\8+qI+$ Q<j!m(dEV᪻d,ۈo|HbHjf[(.}tS;&)@b m'S,t|  !F :7&a|D_R|*a|Y&xd{|X@!F5%N\N4 fYT.Uu|[y֯oO?}'Cd@GCvD)GLtj#e4b5QJ=0mxc`N%t{$]=M1ܜ r@X]7H$ɬ1'blf֖jiWvq^{jf02?f7M^uΆAtGM 3R,Ħ#=?6o9qC=QGlrBY;I0t͘:(W!Ye*sv?Zksv\[7ڕ~j=sh;IKLwWS&{HR*"IҚΖ%Sж%>WUU- ;".ft d˵<sYU_ko|+@X@~!G!C?V*sӍwntvnsM0֩N43JQ Ei%ҍ]_ aa] E߱7l\f8<2p,L!Vͳ(1Dlԣփla/u L9jRve| 5𲘲/Hs o rO'twMs ]9UUI>=jkQ_%i?2EѬ `Jo?x%GCӓ}.(Zڕh3܊G Ns~3-t%%WU'.m+];V{Ϫm0d-Q;ȷr?wcFQi%W>ʌOkPhbigL*R ^.^)[% -`#Q M ␂&UieAC& |D>FIp3,VU(A OEn#86X ^Oc0]#9?1 6s4WPW~$/Y)ňbpj35btw}wO 98(T+2F/h䰧>Ձ3n P!vkWW!ū13 ߏ@t"C@qb lԑgb@C#BEZnm'Vl!!E^$fD$m`Ǔy8 q@[D7B&Xrt}{PP׻:h=DaRpJ>@/b9 /,ҠZ|"H\(#Ζ`1V+p8. *[!o$쀪qzL6f53j= $ cC{)$|Qb $@B}q GlȂPEF̶+R *}o8 hw$o% [ExA!cKjnj]ӑucy" LaPawC\bew]4O5;en_`o^e<"EwT ༸&-&CD sKN'G[] [e>Y̑(\w5>[̙.Ξsf`#n4WC[2%?Q8 )2us_ItpxIDx@̎z&!A経D!Oq1" r՞M,׿7cA[qm,,ڎ<Jg-_dp/b#ntwgO2#]t[ZN*=|&B. ( &1+U;Eaؽf.V/oЙ,f" U 6 !qϏzAy0v.t& p!+JMtUS7|}u'+ɄnR|vdPT~D2핰$#=lbMb=b(14Ά.|$8T^c7I3aEyb*'尤jT@V].I)UViU`i28a%QNVI4t\/Oΰ-ma29(@%IZˌ"S+by536+%ܥIڥ]kҐYBp&0O5⳯]8v6~l`F:p y'.Q -e۳7V__j\AVk RaiVg'5$!Tz H تX1 eljyq{||4 ,˯s1I1Zb|;v;)Nf1nSpUH4jnoW5G;/cod[BG=u 魉,[xbv W5dzUۇ9t=1}W>6XB(D\&k\d*^)d[7ZY(ɍˆx4'4#ϒFLR󨪃qg (@A^P1otg`Zzsb)[I21aIHrE"=AI"IlQh/+q)gVg۩|̔[+tQs̯[HޯD.hy/BJT׹luy7f;HUTMc$u;Miȅ! ?Gޟ4O։'xrWc?KPUa'>ȇF@) >Kjb Ac-%> oF‰@)Ul`6-iBfC%uyLn#jgBnTvP*A1*;0ӾԯeoeJ8P#AZZmBAJyO4{y&'t`VbrU`*5;^LMKk^bg_Eht-零*KZ+GS' %Pߣz%XfFn~Vƒ~ < &,b|0qB$P%'O>n%4%?m6}Xv>^}ntwrCIyt=k;J~V6xLdtI0A%zKb5!.a/ps.n1ELRt,VH4kQ Ik@C2C.'gl86I|)ɷM¬t f"g0G .DzMz06~, P%\0 6Frk`Y@IDATbaQ BxmA>hл}+x1u I7. VimOwbqu Sd`Ўɧaa{^?ِ$w~Ǚ-92K5. _/L+uwf%WcLX!2o|iE@[ vѪd&⭕{D! gJJ_󇜫w?+yb3e{%yKSA)uەNBdqcD$2ViXG耑?5>q]\ޚON居s@ds/<{3#cYdhhZDW8t-B,&P>,|E9,/"U?&Ƞ¤R($6KPϡ~;htjX3тi5}zM- ]B@*6w"y\#?L ©ژ8.>kStY1eî;j5-CM"n24X9kށck2urd?<=Ь(vqT_RQ򗷗- 2Bw2 -;?)Xf,կ@=6sx@ϻ]p ?IgMa5,yƦchߘLT8#m" "]jdvH4g~|+OiQH)j>^ Cmr\g$Nta0GymK ꌞL?׆h@QiUR<1(c&ܕޢ?O?X I@N D0-¨'pVԵTd0jt0ofA!#]Wb>[EUg(N֊G -F^ܑNG)ܶƣs4q}LE4|\7zHԄA^$Vk,If9&f'SH4Y^pɟxe!`m5X) 1XdtzD`?=<1Gӑ`T+bDlɧyEl(Vk1DNN;:sX|ƭr@hDH*Uf/ 7,Ns5rƼ-](rܩe Fb %nxaG.T795YrK瀶Liփ5H""Ph"ۿ0aߙ^=) 6'l$-8'[K[qD-B_2 .AVV#ΚR^b.FI?תvKb(9 ?4iTnv(p|683|)̱Zσ D]3=l4 ;.װy :i!g,7>6\,o0CGF@`hG\{y .NC'3U֓!}'#4do[[,~Wg^6H *ۗ?bD )]Do8 =q^_$Qa d:/6e `哘,U 'cxy7Z 1ol= 0͝6hQͭ{0 &CWx; ܶϞlǙ6$5x</ 4?pRuSOH[ es<<|wO?6@fnIxܙ ;Q,( % ;tF~ʈ_N[,dU'* Wj:)YBiyLhI "p.J|;":fSiIrs{"z'۵>Ҕ31Z!,.پg鑁 k¼%F:  3r_Xz+ Lq>?e@ݰl:J+M2(Ni\1ƀ\NVȁT nH! P $/?xv9G ޼k=T1zߒh2A,52cˊRsݤG`sؔy9纚XT4jD<UQ `- N ﷽*N@.Z HDgQ>ߕ)_ByO壟%Q7^MB4QJNib:3*01" B4(JX*5dCsK/: 0xhq!'Z?Aq \s¤ ~9 , $G0=Ix:ԏ|9H⿿泴A5]3Be@{T"Z1N{] _|'0?b=4IL[ppiM\?f|ZkƼy4S/*HMhZt65 ]2$ita5Kv$8,$ &C)y7A!E-"` J̉3Bd;h~M$)|:<_ NJO94P_Y8&fbh NpNNaTgUU3`DwkP=Mrx~ɛo19x%cfNj.Yw_.Wh^GgE]FC}I,J(u.mUq"56xPKH6NaGiJ/{o KcuAn ֍1hswєqlΖ-ׇG%h$ RW+Zc-eě6e )hXYD !S{2PA.Y`LDI.Wx..S4adʀd392ޒ*|~{)/43h`51N/̠yqF3Ie?2r%^] (ɲ i0|BA[H˻@I] ]|G-9],3be0<# '$qIG>Փm7 p-6mYX+ ?ښZȾ #x]9ƭ% +&92Ŝo DH$A=`bAA'vjepfc &ZfmG$H2tuSvp/Sxx~:Ah`aZn&;[|y[򤑓+:}{3@}TTJ xKM f> U+!~izx=j+s` xXp2Zߙob"m<Lvs0fۛ@5{10Ji 󧧣έ }u:ZnFoR>m"lJ:{g T{G9%p{eϵXTz(AšJwo+9JpJiqYҍG*͡<獊$0w}i9R!ߑB*+09ƪ,|Si=Kfp&tcI2e֛<I`ltscbSLJPjB|25gC3M0ky6XF|t٘-аW4`xy60ja T ]‘Or ˅[jFg1"U2 b"`b,#ݍ^jtōi~Cu#rwq;(NқDw3X|tq1Zi]"1-ebdi'I0r$CjP?/B I#^Qrz/ 0JpsWcc k; d,J^lT&JJ}#/1Gɣ4Y-|[['%SPw<~Q!ƥ5ª$HHQdpFD7EP^>Q>VxsjGoqvST !TBK?DhTɀrp=V߿\\ PD`9}N8 o[^^@e7_ROK\1BML!J Rt\K[k me @CswvTJI21QܚoIm>f-S4HBzv0n+1i7O-qn/$U5ٮi=)qbw7,\[L#%A2yRY+fV:P&fTYaT, Q'2:Đ[Y hE@#*d?h ΉFGpY?+T 1tM:>S?u"OH촭` s=%3l5yʍɜ)DQf1U(4@*z:A, @Fh>HO8e@nFK`g=j< 9Ex" 䒋niKKU8O{M;Ι|Xs4i^-# Rgku}&4\դcJYhB UBC¹-r4[ FpʉIW4FR,Bķ\nRN/,UX(|akuxo2'f,l6n:Q6 zѓlc)0Sxq L CئT:j?> 6 QaMҷq҂n/ N!vlG4Rv%!\I;!4=eQ7L;[[dVOaiT1g2 Qd&}teƂ85JW:RlDdW(E?_Bm8 RH 45pH[̦`OlXv>2|:dW4BN%hI0=.^G҃ i^X ⾯T}cK0k.5:AZji 2^TA YR!f=Sx (A0B\ q/%ơ{,4bA^AĻH sqɞ^("KSHZ4 N)르+䓪r"}T\Pe#O2Z?LjV8 ]˵Yt۵~_aGλ}k&QFuh44呜Ip0 }*GHW;\ r]\0<&ᛡ<*ř'I*;=+?i)&#$e$Y`]!QWˆdG8it_>(i|4`(g&H}`PbV'{b?F(~1/Iw;T7F~['cplc˖B 6f:zPl_bZ0Mtrd:c ,?WirySFsfDv4 ڠvD@´`nRޓ$b [cWIe Lv#1u\&]H:8chc/Pj@? <'ᤰ3"d_i 6|oS`+URM&+2h/G *6YQ63z>p/ԃ#Gc0!Z?肄5t s;nރFP՛= ^zdyPdE:q}g72<'. Kv>5 \Ȅ?JIJdwTtk32CX 7eXD|9KG(Um!O12^v;~>=9I T@/QǤvxJP Gi$'N]'.q~NV.ӌ%1hГ1rc@1)BJrOНFEp2Ê]r^7’|+Qfnj}Ą-džH-fDWDA[R4f&;%>30bf_.+6Л^ 1$}*G+GOH ךQwM-Os ՞+d95ɋ1K#8hFբ'g$G`Z m U$1ɬz"s9BDenBء TcYM%*J[Il@bIR)Z٨V R~ah#dV21z%@vci #S^1Yj3 :nP\ڮHCGvQ#*[G;mZ2zT/Œ96DR=?wTud'~Bcn[hD(s\Tb H0> FLzs_X-;ʼg_(`?:9ʦWz9ƺxx-֒l(+6839}E<7 ux*bUJ!Zףʸ>uAc(,Wi!Zxš;R0D.ޑ1c.[;-iH,СFXX &FYGZt0^W76m}lV )V@'2 Yٙ=,dT,w-KgI B;n }$I.yfTs(!ߠF5Qp՘C-p {n]"\8E/qyƽ8"nuO"̭^8Os…#=%iRLW,;#o7 Mvc4i; }D??SIj{X4=6v= sl3\EJF\;d2v' c$ϕ;Z_-( z_|DTX?I {0n%Ÿ鰱K{9u˝jP+z8,V@td[SuAL rD d/'J#…z#DCx)bT "tٞ) #[,;S(!MzhuaJ"# ήr8p1M;ɥ@~LWhmâGGH=Et6h3iFInM{ZhPB^|8Y`r7%"-RJK2A0d`K??>285~v,lM#ѕoT{& ɟM{G %(R-DyR%@$;bq)K`F+{$om@no#_7mtBX&Wɶ^.߅ {m'%I=Bb;1OuE@Y=c]Z<ڄͱ1("dtch'ӻÚ@IM|j)dDz)\=l$>,<|RcEQRKsb.%X A6&A-wBz( 0$ '-pdZ8(aX8~xx?xtQ`R^NzOaX4=0o LĔnm)nG> cÑzӸ?!e(Pgg|j'jgp>tv*/r:%Т?iF 9,6oh0"\jc$Ipv:wMT|2 ";/&∣&ǂҘ8 c;}Ku :,3EtC=Fm~StƀVdDOzWY[;l~]v!6Hw ogyE!{)Y}pշ\zl7)Q'\6kꢏZ@] sިMz$caG'\Gxt`mQO&V @jK|{x9IșQ\D=p*]pj 7lh3]pxK)@(ʡyT+੨baؤK;$1pɕb>UѧALj#)JPRTCd3 E;pzdϊ_|Vkh_Eg>?8\rWK)24:+H"+/[n@[śDvr4*M a<#}'(4h ɒAw=hX`t*""n7'/U%^jGI W^K0~2PIbұ;T_}__<4b`Nd#CC}4 %W[rPL$J '<Ǖj cp1$2meF O?hI膵+ߡuql5m"О^NBN<EzIɍݢY+s;$ڋmY w(t::9ɒ.{VVxܨB ~Rz}~Ũࡴ2= p6ch+*8Q,Ű=\{['Qk0iӛ.2AE T- Pr`l6[ўZ̞9+HHPY1VA*!~lq>?NU|_-}̅Iٗe*)],_܀EBXn5,I  jg06ia|-"yOvo 9>7r\v#<]v5ƷSLŊ,r(XOE)BC;9q5JNbo+ hG+VGSvF%t9F45dr!`l©K0VHĄ?(K$.kM_'Qoy@[&.@H5UjX"+%4E7K;qz  !;rv(0h0h[X,Jx`{u*l{* =]O+[ڌ S΃Ju-hBJh4%Cֆ IM@no&Z5%L6/?j h\Nm\6hyZt`&Ut٤tH-5%) N9UaL _$^4m5&]EM]>jO eHQK bI E~[*@_&|}"?4ȠZ PLs|$MRhim."֥MpxG"M) Y-E>Lt:̀ꋄ喹#փ KHR~PAw|ȂjԤmه)L6+zF.#JU,㔪3d Qʼ,NV*'ȍa b ff*̔!?JjB~!ѩ8=:r`b;A?+ٟkF5E}1Ko?ݘcuP4:RE/ϏKAX)d$˔?fS%mnڍ f 5qa+éR]slļ<jȗĢ@<)ހ ɠ֔ ĐԇH6Jz9?]tz+5 0(C%T<{dw9SazcB.D5/O6`u| @NiŌW AAU0lz^bsaM2Ƣ-@GCizGy0Axf)O@U̔q|jAjyAS80vD7vD.㯸WL9Xڿ~vhT :EuzVߋdH.Hl&0/ßo]Hth{eAL vGɵ(abey*0d ;FغfSTV[gwnSpL~At`*! /!|DD389slaKm !Ú6˙\F\Y}gCCCl)t"_ )^kBUG#Js )wy'RfDё_ a!"3J$ib@|K&; T#VnreD)xφB86FZMrvJ Q$;5ՔjLh'Aʆ~ܕ eʐC% z1n'mͦQIX`Y&tstD8Z啯=W~e1o{y)zSl' 닜Y0uOEgMKDz:O~7cxk//aƹulA& w,ۉ*J(DaD#\uܮk=O04s1>$_.n%S1-j ]ߓWhQ,N/( 5-DX&'m)'TKPlC0#n2At .[qP&%6J⋐жۣv8-^cmXZl[򎦪IÐA| E)qNȌg7w뀉b̦+Ԑv橚z5n v#Ehcer;rʿ?Xr-fWwKs$yWOյ#svc}3XB_ s`sA^uȸ3W¶𫟑C䄗wxWJ+Vr\~3~y0PV>yz3lF޿~t:e/5F,|bY@IDATx M?h9%ųC1AkߞD'Qgݻ7-ĥ>%=rhOqĞZ-kcbs1cQ~tpkC Q+YFZ[[6nN!:Ye q^,)riM̆uudŁ! *T̋r# EK 3 R/ ( \S˟87l4EtG`wyjBR价R7Q'iS`="b%kZ6"X"C8>wU/zY|Qj-vZ"֡&"%({\K%h-64ZDSss]AY`6jTĮ2%WNKX.ݎ  D=GbT! R 6H4ƹt/JՎU1gLYeD$<ߊy?M~ۉ|7З{K'{iPMJ+_t-HS|hSghww#~!$1guR`$d(PGXY(B漱ٙqO:f0QvgaYtFCF;揟?HEl1ǔQʽqE0qamUD0=Bq"r};OvړKxFQiIK3^V`H!nh{ԯ&h?8a",wIfxFWAIqDEJ! AS8#OxJ̐m<~B t&J*q);}L>G3kר)BDlP@O$M1?uIIh|<{Ma,@0nLcU(Nb_waK *D_=]0di&3-|aG d}̚NkݒY'шBJl̕Q A͡1YCâ)'s3\.x p,6cqxww>}+ 3eq^~h  TTOG_Z!rMXX>i#(\WXN;ARHV~b DFP$DȀ˄diԸ+=խYG0t2p0^/@Z*)f2pGA.v K=ɟrnGr1sv$-v8֡N Dޅ&*"UHT)&vßC:Cj_%r_>%!Z='uHU$ :y*|Gt+ܴ>E\5w' 072Oiz,g0"FNϦ"K^_no3b\ɳY~n*w܁~HvfR;tcMbv#fX0he%r,4b*; ~yB6/+;%wgt ܅aHg{D+lЉGB dJ6 p| kb@LŎ4t 02:zNJrCrڱΫ"Rd5:EMVY17 u4GPhT?(d`R)c= ٪,N˒9J5LgZL ;D2 oZ>Kf{8ȡQa愎R{%10E4SV/v@%ٞ3!1TdXZb"[0QK[SBICJ"d?}R:JU6Q#ZWJZXdjdLȱ/?j@Tj)Aќۿٝh&3/O.&_&ܳLT?_dC$X(U\)_1"Q_Փ?3 NᄩqصEfykaF#h65IQb5pd-I3A5Z{ђ\] 0O5#@QR w;;\dYP"2Fn3 c@THG(!Wn}J+eeS,bβAqoB}0fg%"ϊk$PV>?2?6BϳHu_ fg3P[tDpd+Cȑ`Zɺ*'= V!يzQLTK~u,]YሟVJݛd8z6a$AU@F?6 vN'mӓSy202A% HO_:Shv/-}kooJ˩aY*=9>'~o~ԋr ɴ.6|Y1l] E:p%c_nS]KoqIBdv6 hsaSJy,uލ?*]*^,NJpc̠L$AS (M!s Tjt%$Ǯѕ &kiVZ2!FMJNWCѳN[i[rПjQsdFc&Kft@IؐZ\m&?T0;-|P0T3 N&&5'dS*F[ F'ؙYg5vpdZZ|ܹt- >IZmWXlL9^ƬO&1|I~OhghJYMT% fd AHmy~k^1GfX8pٛb$aB``YmDrD=1#e>!A ?~;][t .nj,R ]>&L"?z>7;ucHmr }Fw9IvRxNDdO|3<`6iY~#;s0# zcFvMnw3BRƊKid Q7# ŢAе+xy$1y3q 7,u)"J*tg.>; ? uAc= CeI>4TO8z_O6dD m5pEi/:4ha2A 4Z A`\4XKjޒz" wA?tђ |#H~x!'L7N2G&ڴ|ηPUvGF3:lvOѮ`Q4Ȇj4odu:ߨ/ǡ芸&Uڑ_Ґ1|QySJ`֐ P[2h`@ȏs:H j$h990\I05đ4$xdMEIP)[^`%:Uis$֦I2Hm'#攐*j>5L=4N#(l&Kp"rL:pcPLG v6{M]Vh)Ă-t.@M+mMR9BAbĮi BדȆdV$(E%Fϒ֔XI94eI)un@6SYm#DrmV j8{#hC!7:l3O)26>}oAf*F4W"霠vb!`~꡼ih71I(rqkeN6(0p`S goyV i AqL*)jvuJMYq`wR2Ge1+[dzqe"7Q@?Q6*7z܇d>[? 6 /UY2܁V"` }2HL}Z@Q C.:Ζg>$Ыu&i: KCA^Du!J%I0@?4 {;vM0h1nO]x.h+J DxkD2 yR9qWOg=̹HV<( &vnWB:.BR $˖_tB'1N?\9w'~;Iaf+ވX .%s8G]k`g@𺗛zwfĦO{Sc}B)ĤHa~dOFݽFHfֆtM4&3=[* %x&B pglcbMĴ#¬R-Wi :,lm*h%%'qHMx N+K+t1.#&JrI2}mV@4twdN8p~FCNř :<6!\Jp ePC2T〨`0Ʊ_\7+;>~4ev ^F'py&skl?<ܥ=p=Psb1j١` %m~*/b Iqeڕъ6T$2R %C[SN l}-Q[d*/j wCbIZVYrg\ӮMA"Ѩ -lc_K>*HXm @@\>jtxMyש_&. !jD 7 ܞP^zac{yFE' Y] ӕ(B!COFXCq!%Y- V6ZcYc;:?l^M+TBX'uЁ=!znQ6d&l\%7 };S6XW}Q͎LI.]ȅ-o/Z(e+!8_F!kU3+_wBm3T vcP*I"8O4BY~mqA_z"OB`К=P7;i8{z~&J慊@HRx=gtCJ3*HZTvj&aYeaVB HbQȠ0 zf iiAM^Sqy<ޝW i"AnM(++&wD<1NMV̲1EHRpZj?<@_2wvY >X&vr¶f_}NZ4͕ms6]jHe$6SBx(z'Y?Itq~dwq)h@t;+V@Itq~>O A-26)mkRCFdAz&d:J׊no+}HL+5f$hODJjwԢ/%dI g[8Otm4/xh'RC%)DNνiQ0m,G DAA4xNS0^ T9u~Zdm]~yܐHCqԬMkbA}S:}K@P6r<ƥ^}I\KΒ_JcI!3ko|uzCgP/1I QRm^H%3f9ӷ Ý1afa DD\>>H\[9o'9ϰ쭌ƽ,D9>K$ŝlmymB] +:Mqtzh)$mGTRZbkr2'K -Xp]@ƨ]N#L0&g4U'ft18U$jHm_%h-FA26G&J `Z9PvrGcb4I.2^eHR.np|:t"ECBK8y.[PO5쌮޿u>[x?{HQH̒{)IX=i>!H ǻ᤯e6hAr#tSW a׋@m:# "*⒚LxW;_ё&aQ n yi?DoT@sr<'ºi- )HVl0ːm%@4>C:p, ۤ b'=>dc3e[AcR5X͐6](¶Dc o WfzBg LFJYɜNkJDnL6뚶TՑbJE"#lB%<~S,ٚB{O!<'' \j+Qcx!8v+'YO>hA"m'N&WT#!˄ /)"lKH@E$. ⋱P6pdd7 LjvE(RDD/zQM; WR#8Hɔ0S2Ɨm X-l5_$B" 3@뚰 {Rv(Ӆ RJm*0-ojꤒdf`F8~ȿ8mˎ6}eGwF"iL MH΁]=_VJRҜY:\G3'% +RMP4@}MjKaEv:b'FmPW{2ޤA(cl$~coi_]bZb0>N2"%?ǿ~3@%n*mN dFUIUd^,'}*&* fkV4η?&]} JH+gf`S(&vȁauxS k[&̰+?xwoƚ,wv'A59-6N`^$WtRFenWj7 nGdC#(tEi nTvxNɊ<"CuC9؀*~o 0z5jkEkip0U~Dc*_e7 #/ɷ8H ݥr\>gR[.f"R*>C]E9ԹPUd_%CVoݝUpCinPΔyV/l׶Q@P,KL%1~:I%SQ$m/?M].sH0/ɶNT6dti4( Q۽9Q4La\:nNef\l(.Mm.Z"7)֓ĝcdspv%ے.%>Z("Y/se0}!xH14đ_kp5q7!2g`Vћr!N-<)5q%_I?Ԙ\iQޥHK\^bױJ{8*V?˟g }B>a#q/i,)z m-YyG߭g84֥F7搘C[ ITU e.v9gX&M u)#Ofuc}hh6et8pq52))PE {L+rwЂ r? WLVTR9yLA10vF*u/,o]ɿPv'2cRqH*ύRV. G*~$\d`sXt4 ]-BѲlm&U ܞ1AR?l K.NyYun2x$OzyB5oLRjg_Ej4]wwxk{J)ʱ@[vE8 p0.O>E)Df̾=PsXJ `$s6aTzV+QFpymjHsTSD? %1Vɻཊ4eYVu! *&PĈJkWc=ql  j>-6dr)?Bb@1%e ?2$9JmG(*z"=>ឍi, R;6`u/ p ]1OyI$2VmMI R[˯gkg*`"mxG1H'`,ZZ(Vл\2oazyQ(Mƽ@!=k$0ǎUî͢{'K${~d,3Os3.ᨢ11ݦ߮4&U )$>.M3BY44]ZvdqY ͷAZ8SLxTާmlB! @uwۼL'f'(GJ,0Y᱖rU*1e7lK* XsF]=TߕeC_7xJL\0J>m _zh,wG}Hy}%Z"ScJvwt:Dޯ{;F `SXqQ:RD`Pb<0솹*.qY71BΙK3b bNP-Z4wL* dHn1% ^dl*G<480fߨ?T$c/&`Ma:!i$_.hLkE'k.|@;i.\3ƭ+kX3_ w멮#VbKUgQBl-gMݝ;GZIN}9.6$Z[VOJP|,bWS {ilalTRj[P"DZ;_:a<e"uat\";fߘTVͼ:恚̨F~&EM7prbXmHŲu N]# P{zOv<׃?x~gyKKHta-8|EЋulm_P{Y&_XuGES4U8PM6)̞ϖ&A2}i"DF'v)[e $_{STCC֙f EU)͒5a"l95ĭ! /JE?A x0lM~sF@>l!ځ\Jz}|7ڠ`LFm]6i9sZS'uУĊņ>tNs;oA-ݗSx:fqsIe7 fOp=b)(-%-p*A8yd?˂yJij1I:3όԠ$[mm+zKa^;${^VΟ\;[_Bgp-|CAlE&yd):RUp3Oa{i8@IDATz)=?>|5rNI\4TqIT##w3v39"XgL)QTvE&wtrDdk. K0'd nՆu2Z&$JvE^BD"6.f;وfS(VmS +.%/Fߗ/s{N-@a!9#A` 1X9qJ܂ !6?:f>|8%:;̯7xD:*~u*,7Fy% ?KD8m &F HMɏ i˦ zF3_a=8MeEHlYb1ϛxTTXw+Ryq䇣g0k(=ubn?|OPܾsyE \Oe ~5 ;rj( ACOIsG,M^@&lC'6ew>ݤjZӠUX:$kbxiYiWxmK[]C >pC3bǩc$$ ~tp>rM+),:B&Sx<@$7[k RNV&]xb!p!ÀVh | ag> 0#nGĔ 9 $idC3.ZV#NBx)Up q7G#%4α#`JE1.i(+ï@|#1_>)ALG2Q0t^ޖіemYU9PH΀k!f?5xrVAvީ&Ņ?Tɒܣ3wMPQN7Sw]v45jp40z[KX|L$xқ'Fx$D\fso ZQ(Lz=b ifRG~2pnaqG#g&fCi$ Hk[ >,),C+YeiuXWGXDB$]TH[+{Tg[Ըru.-5U${)ySSTZ8hcȷw LB.9&L4?$hr{q*)FRM?z:蜥hˡZ/u(UE);$ct*U[’hS3/%("-y{3dE_⁁=s" 6J MW -hV%0fW Mj|7t4cvq$1OYnӼg+M8dmK(7$SA0`/Ž@cIlԸ#WRthQiU`@ I\˅M ?I8BFcҥND+MC+%TcH}%׍bpqH%uA5d>]y"``5#',ᰖm3b _q*( #o\Ff")#L /!iЗ Ztl2Ii\C'9pwa RO(?JRy* duB{Ux ?F~䀃R?$m}#[\Q|s)v"d*o!kvs20IIf-pYQ:e;3Bg}%,HvE4='l~בZt\U 3aP)@?|w|zz^mF*=g$MZ<. s:- mD(4 :ŧqӤ SjF8vϼvfHq%pT w*TOyI gF4DN&2[FDfÏU.FxR7_x&,*CtOb^+& s&S}TBqeU")I^j=Dzn"ڍ ԣJ*-ԣ+"npv'򎂅 '!'31C20ҵ'm ʪ.Tp:I3`[gR8Q ӈD 5mرވYFbiTFHP\+H1hۭS$ѭ POK ױf\SRLt:z5F(/[+3o̵pLG?P- 1JNSt(C폾:O!?`-F68߰@= ]FތLO΢' s"C>9#]G7satjX8Z!s*X͎$ݑ J£6hOtJXp*ˏ?2jJq98o"D#?C2P+7Nkj_[^Tn=}Rg"ĬgQ.`$)[vҿ?T8վxC@ &#‹d9 *YH OYoT0HD?8OBZO 9`r yڬCbIX9)hOq>ZEXĺ-{5ϱ:{sW w& UbIRe[3,r&wSeJ o#e=hK%k;) 扳7N, {8ԨGY5\Lw[kZI'6#JB*$]\ ݍ(ԩ$)#]z#bBb0|nǯʀ[b䀳VK-}>$;w_p$w89} t! \RoNq%o7@G& mZMnRtVws  q@EC&%b5N0*&Kg#k+ޞY!0;^VAi{,F&˜ IFK !74fxO&jҏDzB!a*y/@0뚚aYRNYZmO]w$guVC ܍4䟨7fE2?h!/6DCVݶlkI_#5={bɔ[1ns 8 hpG%RŖ;(]QX{\Ay@{uGam<-pGf˻"l҅s4-hqHRw +I۪Pރu@`[DEdx< t5@|HЍ͹Պ)j)%ˌ ejpVS\DEn@v'0[ɳ '܈d;} 8{teCZ'ei([7OVf;}Iͱ+Č!!O> @Q:K"E71*aPv`0EZيqǤ[q-d)y^$mOUIE:N CON x@"2$d? #^D0CطpF-\1 r\vi[=̆'g]{۽b'd U1ι8+K!0Bl@ų3#CHFܜ%$(M_"栴MwH&+>'.|3%A/^9o$9e UTQd+Qy v"}x0~R9y+&y9e97 KOLkh(EctrN᠋LAqK\2uez,o+0]9 r0k +ʽ(|/%H;%^ W2YhPi,ob̒} uG/ڙ+^:)SQя!>ߜ&@ФѷzD6hἥa}C+2u'ozKz("sQ);G_vC"Sfbh}jK(t d93XsFW>Gr+֟4޹Xy'Q$ dsB=j^f2SvpUtFyLcȗ \ FӰ`Ůݶ'3`4R sF^ FnHK,vtǼuzs9u7cMR St" 5.ӆAQ $EH "r+b7uD 7ΓNpcjկ)O€vuF]A"td:خE`2VSxZȢѵ:hk%_ HXkk$㻞'DyGN|D'EN82ۑܸ@, Gw%* ͉G>;rZ0-]HEn6,Օ@B bG6]ͷKbEX RǸ0I9DF$j_ބwۆ)BzSQۗ59l19B- U9B_ЛK,}ӣ2.NbWQ~T܋g>ڌ~f~gid\sKo%34/k7F FDSipLwr #B &՝dRowz}%5I{BAr @#^9 -NV:YlIuߥWOąG9C%B $rd% 1a(+4"A%MŹ#ѫG0 z#M T"_X눀=\e՜*=+g*N8'L!Y:'2j=Hti<pԩ~#Sʪ$BPJJwByPz*b?]jd)JɈ5S: &bY쉶MH_ ZY~h(,I ֒+E43@͠ZVybW?ۄzA;B`tq2m!K@_)2i`Mxj>׼/x0ٱ[URMH4.H/W>S4$/duVnz̆blwcg(K kXNcK+oҽsy !)8YDnalpiE= n]! g ;%A92~A+`po#^@z@Tl{dAdK&!aO2L +b 9 aQǒҿ{FӰZf[,a6>}- 'wr%Y} dkD3&6sR}bĥމ=aW $/n(eTm2S;qPT'\,v'[@x=X iKF zșє~׿08T XYߊr-񵏒3/r&)|pdV g2;'Hp_z|-@o=Ḭ%YK6LEÅ"v͊G23U9y;lfz86RU YRFࢎ}IIvU)osR{-HhÝ$ F} D?159|Qk|Ơ{$" AP5.K3!+kr@vCL0Wga-,~s/s+ɰ8!ɿi'r!S븗D+J rW˓Za"Fcfv14aA'%'$i2#*-λRá 8<7"R-l0ךF}`]ViBqĨn _jr=ŁvRdc3J5E{D}0jB:_ B09[I:]Ł |r AZD*͙h%LmA%y(Bq֑E.GBf*JVP:[G(x aEmMX{iK0#r-vf}KicY"(&^rl!R*Bq6J\eH]iMDB<^/_pAk6}F&r (I-ܠ4O8߰SDܠoᗱF^ϤW |_llۜ!e}r'/o? I{Ƽt77Jo#cWras@^RhNN| {f Y}qְH٥Y.| J,K' ߕjڲ#xbr \#~Y9=Bā5e./6`G6# zc p}W 7y){E5Uc^#?D%GvB!s c_4@ B7I3t($vM "8 HKO +z#1{kU|^~,7/2 l6%{EXEx, (@9JLXDTRO9$Sɘ \ζ]KY&R"ٮ%Ds)-Ѥ31%`'$OSQIӥ<̅ O7~ A}F}P4% FJ(/&mhaZVtԆܢ0WlkWlVs8apN:KTL< G%y+ͳ+^5(ur\$K9|@h!zھ2 Dވ4#.{c ,0L?M.-a%1FR{5r %Ҁp[G fJX|hsbPe\"$V )u z[@sX %`@b(^_X5TEwػNPyO3pm 8T7!t1NsP/[Qg,X11 !EWn[a4$ 6jW//;zbl,SvzC3 vghō ӓߪ8 SQ~T/A %67‹20尦R0]c*"Nn.f旋C:/U>kWXKu|LN\3#,KV p/⽵?a؋bL22CkbDj攈H i;zyu#wk@@L(d (5r QU~bc)ejL˙n$Ӆ %g\X}RYu#3WL /P 8n -)}![4Xpb@xrw =IOrI1L%W"\*]lE"*U1 E,QoH @8F=ʣB  # QuϷNLPd|ŀ&}1}PF\ީ<,%Q)@H:f/n23)$if92 ל H Q;v)9/8]?Q cK:(d2'8QY:nz`IjX|+Df2D- 6>Irop'$"/i;Nk\t@]p`>;J 1l{;N}z:=}?FP\?Fz[ }?"X_V欼[*s=KE,cAO6R&Py)_[+^0~ؙ"Ssܐ)h4_Az&Luw,|^FQ :u i`4yaT8pgO륬8A{eqDH}'u Z`|Zf!;}5RDNǀ#Kd#NKK^L[^,,b97h;XBur9aäedA ƖHw ]Fql[wЕ i9f𯷣HHCV 6_p-8ݠ)Zց.Gӱ CwRBaawme7Dȕė.=\ULd?Y`DoGBilv 7s~ !r-aZ[-aA\k?)19Uքs9e"f f|dXca˯m fIgT=жSqUOpiH, 62\)hK {HE jv`唏{Ҳ0"; %SG3a(D9,ÇK;Gd< QBJɛm"!/,(;VjR v*)(k)6ud:B"D_ Uۺ'gw?̈\͗ "H|HW~,QGDv9-6N`>312m1S^4:3'u^' L2jn1?u`Ktւ d`]q\4 EgBoY'؞*j, -jKvh i[(#b:FlD;[Zl(fAɩb JĀ)P|>&$xo_%cAj=JP]hmF.睶&!,W%+~+j4ɶGJ `X E1ٞiSm9-[(=5#*L 9z{[{izo2ӑiw٬ӠK8E'[2vn-B ێh] |ΊW'27҈cw eI!l]oP6K& .T/R(BD~Dz7}pxvV1MxfNm捃T8  |2(-/&p?p| `bC:+V/6&Xxn+kx󛃒@5 Ԕ3Ds3Łx R/J9D@bA^6`AQS-#1 ],(1Հr|E at1)jFwI3sqnULW..rTi&|*8NPmFK9823SoY]oԩcMnM> RȞW驱J0Xl3*m(O?`,odĤSJ.jϨ=4P=Ȍ3٘ıYk sfN=AV.Yl+V=mnp}* .8#7\X(:-NY8~ KQ8nD/OpLRb uem- SKEGqwJ#ʽ1~ғ+$ʜ'ˏ/~q+p(VL  )W3',s܈[3uЬ.$iuZIl8HOmkB:Z}o9YKG*I/ n7YRWJk&IL)q *~r yEP뛦'.BTrHsnJfq֑.t6.,"Y8+Pzfh ޫ2pa&wڴ5%"-E‹m,˃ [PYHxnO*1Cn0|"(*|-r(,: 8o W&? 9)5{$i*}fu{9`0Ld<'49FlmBB$ ܴ"e=$ זyqHJ6sI[l!\OWf=Ch6h()D\LFHz SE7-1iqHǩzK-kTOsz?u|VDm74V fAɢcV;= J4觝:f3jCҤh);{b"FIV|\;VZ?Ͻvv.u}/qs[% #b9fhja( iHF4uJt<|F-H *D)`:N/''G$1X8iD{_H(<.N䤄+BQI/)!LH/HP4HD,,{p@28CB*n8lsSz:A>i}r*z7wR4'a?2D'k%>=glqXZAƨNg9N*C=tEx>E{*ė)@=qʉ; 9ZKlٍh6e'#K? َ?=E?xC9SF\żȁ !) UM_w|U9#BUM$2Ib"C">ijpG^闘VJ*Dž8o@ňIŔQ ^,){-G\,K Co"]GJh}rq/YŲ]m,o}Ϡ;thH8f GzI#ɻ3Շ“n+) ώLmN{K ],`vSTD_lAz(ANW;@uY9z4M8? H$V(C8hODz\Jzž]clX榽j -,CgH]?¤pIhTG@$ 5! s%\w0<@ML$_#z'憈UNݐ F#">6f. 6N1Oq 9DZ< e9;J|a&lÉV?Do{g EX 2gzL?R𑴱POP&ٺ @ۜpaSEnq"D "Z]Wdb>&$km5D:ш5<9=Vﻷlqj7}f*4#kw#Q[Vlhy(׺YC 9ML&)/1bNaF^B̽#zѴ=J>5%%] dŕ'eBƻQQo<~y A PXNwTNyѓ#fm~R+<g: @IDATJVw),%L& {)q^qo&2X]h ϕK97ExNZv]Q Ji,* ]&Ȋ*'[ :_rwXÞ Oc"N{}Y ޙ6?y[u5,ܺ'd۴YQ6owl(qvd}6P*-n`Hk  Π(ԓ4ZL!4ijP`*z{)RM(1!MD^IѷLr˄~qFۥN:ZvCi"-cZ^)nδ8^r(9n c Q te|Z(`[Y,'PgjHasiG2yb'3F3Lw`{QZ /^#!pN1j2bmT!J^@FN9A Ў~>$ۆ15w0|dU;OL-M9n ^LbKV*3ϫ"_^_g7tȑNQ#xLI`ZJY>.IK׳`4C 'lPk:qZ9a): Åp9{s$䢅6e/C}|x$cC_ZoLwtV ;Fd[*Iq ׬G^Z ^LXCZu@r=xyx9n?hpOt=CPS<:`=rd/Hw~;P=VCCg"Eqmgb?K#xnJJPnmzͭyvĴ#MȢN{8pj5|7[[2c ~x,9a1)Z%D2Ny{G,Eo"v&8% =ɘc 2s|)"H8X<-#0R)*4"9̞í8J6!ʽ}ݜ G< ]6dRI\+SRd9Үif_/"\qmVWh; ,h]m׀ِHR|@yz-E  ҰŽ(ZvP3.G/;PJԤGpQB+e-՜*pޢuh:4mj9G9yH'WęcO^ѵq?|nC-.?Vn I^, QN Ǹb?My~ġN>LVA&Q+$k 6ҺJl}& \[hQ+rԃ=ѱBqy]|>pw(Ґ/ϭ()TϛG !D'$C Sq".K,p7t5Ơh\$$cڅk!jA y#4I38:v]JJ3Amj Y)A9JJXo{>).șݫoEL~ 'ŋ 7{Ukn`VTRoVn#|Yc'oHJsYL:DGHM2R89Q7껼ZLL.3 =]Tϥ>9{s*7 D7hCL~ջ{2wt+iV5`zQZ`aO&_?"?x.mDX@JiNlC'CM- JrEfۤxAl6#Y;7l׿Ϳ$8M2U  ,;_;|wDh(ʄqC$9ërN-@TdƐo諥r>Vd05I$FK]ö PfSk,Awz,9iZ<sd `BF&L__8H5o"_t$ FU- !YB 2X6bCfTS@8"7.`2yߕ@s9(-xIYGo [<AR%'M\۳,(i'X2`pkm&Âu/CP#P^(Wz.N8DPfoD _:OfQH$7$39;0ܰi٩X)VO^b{$u.10u:BUΈ}z&TЧZw zDCyqn&ۦ" <} !$M-&Ϳ7+ 0F瀴z|h {ϗڨ}tqn +{ LF5$C dL$9Ӥ!HA퇱0  yoGħZP'ZpCs2A:yUB5yJ*X֦mlFx3ysֹdHn3*Q"mFe!EQE/aHOe("3;MA.%G[1jD rkǷ70DPoB熢|D̻Ft)) }LdOʂ rxa?T7ZUJg ~&vc&!(V,S\.\|e̴p(%YϮrՏL+RbK @є/.O g8bo4z{>>j;,2ȧ HeJOKyJ;VZG&:ӄMzM * 1j)VrdnB:ݓQ[;%ahEbKbB\HЫWz]q\.42NVS9K,(e{xL1*Q;"'¹j6V] Z3"lzYS.\O5?=Gȿ^ͣ<\t ej=H¥x=){]w@p2UL)+1 > $G"J~O+gĠx6ҀB$f$RS8o# x>S?514cI?PU"J.G1IbdJ\*ӭ'YǍ&_\$VY2 lUqik˄׈7%wח"(#)mWjOP1- tW1X3%#xGDũ`vD´*TEIS(M;D :i UH O?ʱ:8T!gPb9"3h2cBXFgRG%IfsB^_ӊJ`CM*z95q]Zy~ʸ2_@&bRp`gYg[ZHG\tbc]{YתzXϸYa*˶\ #dF(3Օ*%&ɕ:=и^DӧMdz?]HgbB'W\+Qr5yeӒa{U{=qdqˢGO;0MD8cRz&ZJBrE2>oZ+)'Т@M9SMr%*I(*A4掲5Nv b΅0)4#-|tFTWS-K[o^oWvKfjse_֏Ők,"K^Uo?A/쪴܇Ǐl %f4;$0 &*D)L ѷIbv$ "rF‹V5Z[ݬ9gp[q#b9":MoW9+Fq")mÄ XMȪ$΂"&>䝌-H>7߶ 2(¯!JwճƂ;da'X^!<1`Jp3!^m~G)bƧu2o}xcȘ2Ѿqh|$?A>!bb2f)HddW:dAbbd*_\:7Gie;p tb#AbWɢxKfpdpE8C>Qۼ /UFeC4w_|Yp@~/ok?31s㣄O/neHIDD-޵_8Uh8JQGq|.DUQjz%% cyߌT Ƀ@:B =g(yo[~e}s0z $Zק:}tvY\{S) NJк* b ^ĪUdC@G/fK8vlFpQ4ۻ̹,ppqXYu&C}[R~gpP*OlyxQ F[c]7yF^d7hY/TC?3}xJa5,WQ=q&`+Q'磡o۸kze7?}ۿM 7AKnŹY~%Uc C*CC*xb3_"a~6eY609 J~+nR=XBsv̕BFn?}וc7H1Dn;Zy20|rQ~N/'AmH$} IPdy-T>vgBjɔU֗݇A$QʌJ."Vh /. V`h=}ޢZ98ۡoI;WNaY"Pf \5Њ͖Z% ^qEYk|~- @lHZzd1Z~-;ϩ/UGYPૢ V ߒJq߿p%֊ -%&MEXx"2EĄUcn9pmɷQb+J#ّ b&%lL5M5nHB>P*j#UU[d,|y E< :QOFPĠ["J|80`A#ԗ~"5كHa0jRQBaX8V_ׇc8pEG*u&c%2bRly*!= `X8dbݎ.W`t 4@5"rg|IpҥC/c]Qd=h|9ak+}A$u1ԯ h^r*ij`^y '0ʼnAА-ΐ^4Q@8R4t6 =H hV'cg6fWPЏ?]* `P.݀c8v'뢋h+a>Ð(02v&c E}j{dabJ|ǾFresA`bEE2BB}A%c(hVᕗ7?L/}X[6?qt@,My Xb8 :fLtn 84ɲ%qz,:BW ARGHq_π#?~& $\4`^qܬ#\^i(bQJAJ&Ä%ǖJOJPC- L}W>Ѧy>%|EFv`J^fi:`23{:gˍ$x"b;xDyp>%'Ԗ84涀RC a  A`fRf>ńs8:Mn$6c>$O|'0SB; [:DH#s12tqJv2_, Dtc$"L $t.^ȶ$-28)AN$(3IUu|5d"H*5k#p)i CrR/?I`>B}A29,!UgThDh ,aˈA L/B;k+U0CAh}kˇ^EULNlta f $2#`,M^h@;,r? S [ 2:lPͿ$R7 |1Jt^P%s /J7am tZ1ӖwcfN@HtdKZZd™ؐgLYNM3_Elw˅wIh#cj nHImzCVQwcR%#+)+3q 1:Wj^wQdszE*2^e:|4 "0 fjUYAlV/u!9=>jÅ+{B`%%+/H(i7#2pǡ!?"ƜA4 DDHl[萴)̢8 #} '{E3o-u=pj1ГTD 倲1!m}dRjpQ1!vRf8R%!8 8{7da30Ua4rzŹ@NibgAEPEſl/9_\7JIO-՛2*k~[-nXUW"Il:9wX]S'+\)s8Dob$>OPc՗7]'}8r$E$C >lDr^jL)V颵W\;ﶤ$H(y}srH0Ib`Mei)PPg;WL|8VoR>Kr: wGW F!z)VD.u8(9ӑD_!cZuY,)75{O}*sY)WjI(lI=J,sj}Dr?"ev.iY22 ~5 y$ͥ$_U}O0ڀ0%ZСiͿܹ'H+zy !~62W|#ٙT%1a`[yCD3T29W!r!\?aEL˻-l>ED޻}& _vlJpnxee {:2O~7~<=k3B@[A? P׽4*WN [4TܯU䕄|qD9;({CHfIL@PClĥTzTB/;W# -yx&y-%y8Vr>Vp]5N-"\i:ಃ)>O\`HVڤgDL&: ɓ,nA:wFi.DOX!P6Ӏ~D=`._9qAzjB]֡A{X&` X`LsOj\C%EQv|"~bpFa+湧#!,O3 /I. a zb!&IHgJ)XfQp݉f0HJ< ifN #R>Dob Q0ҺčRI9UՃMYiE%BС䥈ckCvhD%oa@Sܹ/(5yA6w)]p&T9-N9ins_N[a֐Oc{XoO&h!X@yfH'jm' BT$Q_5Ҝ8mhz:}b1$œ=KÍI}՝uwvhX#i̵!ژP:aV¾q n>C99EFźMYwL9yQ:aѳ@fWː!]I KNW_Q1e]?ݧܸupJ lrL@Ӛ)Jy`b{ G/dHT \a׫ZVRbp+2cs Wq/n a1€IZRԆڕE7B~>Ɉyrt&%6 ]߳YqgXP̡n_-ܷ?|z!%ZY6JK`S4.$7k&Љfzgۊ}ݖ;Rܲ9jJ5Ң&{odFO,-7N6k6*~ҚWmT&rR[¼VxHzgi`͖ !IHԴ~gi$G4ȂatfڲT ߯Ks/ RAf)+K# mmtzˆGcT#levo\B$@݅jފ" dFSv-| jpکϏ?g>%rWRCZW7OXJyiZP k,ϋKSa?~*&JRev7YUn{l4@rum^$!Z~P{bm[(@tz+aq ] [6XIH&>?«y8i;HkKzIox{HGC[.pj`<޴Iq[m{px 0 8vKeS|~fSAtjpt,'qz~yhQ/J(X Bn6'i]c ,ׯ2P&6woG}xm,?\FVԷ:=EZgqǁA(|Tù-mNx 6nƍoxZLy9w Aԣd!w:73;@:HLr0=;F׉!NfN 'J~ト!Z?I57xyyR^Z>vKy(]b*]g|\`R,tYWgV.@`~ٿuVrɆS[;g:LKTP͍gn")RHPP4{r9$rk.bNFɈȊU .!qhXd6<^QQ?db~X͊ʙ}ҮЯCF2濩rq^6Ny l4I ##>)z3 ۧ vrW~9 ' g@-g9*>}VVQSjA))3&WU&3%5VŶ9Y",I٤lPKhsPڽçq7]v;XS 21# H{ai ;7VdMDQӒQr9Ta1'P0C=@ Ie7BE΢vWt5{xU]3PqSB:&POoV/ϗaЏ$ ),mV!x1Pl: #أZ=&uJWZGwo/+I:Lf\6e-jP [YK ۑNxƷ2p6$(fOȼR=D Df\w{yk<6r׫1T)A,(Y|j`e$2*w_6~^](w0Ó2fs(.(ẔLtĵ}ʍid̤ }-wfp[粋o,%O~E>0|,5#0  Yc_9da*#W6a̗K_~.dP _ίXO?dE r:JgItdNlIޏ?S0+!`jsT/u0Ps?^I e!_(;)"u6)f8XyMB_dlsiA׏QO: ֨o&++Y@Jx`b22ke]|H6-pLy'(TXW(EX 80wx[CoOF @N'!MV! 89  Vi(J~rr04yz$?T;$Pࠀ~EHdFtcYU(ii#gں:+B-od"=9ԧ#K,1c[N:8l},D&LXܻ~?#z??4 SR &Qz{Dq r֞J=#==# z ݂:uW+x 1dJ2ևP6 e-IEQ*{#%K/(x|`Y |- @IDAT%de8X3~6g %!"2'c#_u%~++MwXc袊$a6:&L3[RD4<8IuJF%ѣsHNvUvu1b~ܷoʬJUt֖"n@a ;8(Lls˜3{q BH lKCIcTuz򩐊ѫKXzqf}S \ijS;IF n̡FU+) Mb%>ULf7}x .NeIB.^ ͦ%Tt3I ,laM+˂bW1Ga@gXmtUO3=#^y9_*sk;f)Al:JLldžN XfJD3g{ wS)6|8FIW.#B2IWZ?hRyK}ɬ﷛ jz0 o8u,DΔN%]DY@b[ !w?JlUBTr@:8ƄuyIe+>@G؊K 4,SOUE)Aih1"_3#kja{Wׇ2Տ+?+qf2<5 >P&<_|%䷀QB%rd#_NI$SXHęϋ]^;?όX+st;}%Bu'?&4Z#X|I֦,bBt^Gb Vw5Zi%fU nR8˱!b# rlNY+L>+TF([L F$*heXdzwN'Z>h$ ϏZs{PGQZ)T #!aYWr暇0ДkT5&V⷗g$/o@ `ADzCdRMw5>mt]z&D/_ϻ$[ҢA>iH^"]XRZ]|bDs._4M΍bi/-Țxt;F}9P$Ę<>2m'4E.(s7S]Sh2NkEt 偒8D.~h+2S\MvIR*4:&XpyH?&0֤$FT,ˡHgw(v&{Ӈra&%4_&AA>a_[ ˀ'p@Ł( MLo aο, =]])dȟ;3QAYgSE%%zܘu°vyQ1 ɎN%?%!PUQpNܛ&#[4*io=g)A|=u5CY1Aa0m$8TaE01'%f]] jI)۠Q!O42.>r5bjeeY_, 06g @{bľq1+)Gǜ[{H [ MR"("L_I 0U8=tUl!Nyܭ!0_p oFѪ}/aߩ_DQl6 Q4In$K4Z(Qd'@dY*f;r驪HʒPxuS#aroEq`&GSҵxo?l2|CtaJ,)`:@i#FWîh']1 T&ZcT ǃ.%s9mIo2iF 5#-lH2)J/kdY$CwFU"ݺvZz!Ӏd \HD{HBEb^$PvX\FnFWؐiM) y3]Q :6dGԤG%`zf_$9y~J^lv;non,DLJcLIO|I?s4lL~8Fy~o&%e$3s#`$$e,f?A+5I7Pivz.q$G.9,1W;We+·,lɮ8L ꉷB Zn],(Gƻ %nl2drJ\O!-9sl3h,ݩ/I1!agWĉ,/~EAaHfpGTԏG=e>I`ؤ[ oA0XlBP ;X6ɚC.v-yVy7TS=؈Wf>͛TIE*Fq[{<\W3ބ-!h$Wh%N p@j| eEԩcP 1ut q#'5>vL n{h `AsX$hq*1~܆ե =_ji1E$o}rj|9ߵiO= RNxj8p^^Nv:]B,+?](ņ' #&TuwmX'z)a3u`A&vYsd47Mi+gBU넩V>=W,L*.Ro!@pNʅ侙 Ϛ_MtFp7tvAeV[x<,I\yƆ?"a# AD>"@,2"X܈Blw0P8Vi6$fJ$FJ&JMe&)hžhyVD=ܒx)ҵhSa3JM";K~13 9Ξgl>甂 bRKeC>Q6ۡ4<` ?ؒс*@QT^sA'4$4dhу*~;xa1P.ɹ<]Lz“5k-++?b1Bu!TN!O՞:A #-M4?ܴV[s oH_Fb,2Aӂ bڼ8SLJ^@3l%DؤݨMՅoo'pD9 I6,I99moIjO+Mcgy2h.HmٞX.7oJ5Ԣ;#GMCC_lXyɎ]Κf@!a )oZ|cbQ7~-jH$71n H'8pEk:d+}$ H%.{HL!*@uln0+ʸQ!aPv{v =E Lz$,-)Ŋx.Yߺ/X N8p~(G8PG~~F//7B %ݏZWI|ajh45&-{rJ]dF;xxK5{Gu&Y1<% ^)t@ 53u8ʹC} 4 RI\+ ӌagH ZrxYv>CXwzLXKLL}-#* ,!jr>+`4+ªQ|mcuf:MdiSdF'J`< >#8_KluD }ˆ茒 U#-rTqG՞_) ]bb*P/y"NGHeya6f(ʐ+*N" iym20)eQ逢V'LU #GHjĬs3R:0g9Ζ .y1m&TWDGV Qɛ^R%+%C7k G9 jl0&#upR CmHAN н/#8.1c4Jء×c{s~0сՑөrcqbxAoՋsPZBE/:) 0/0ZXmz;vSid @ COE+(b0y%]6SN"we OQJ"c@)9/OQw4ÌLup"_?OJuM"6Kt[E7h8I vMC5<''%/Ai_]ߘ|U흒k 0WDBk\H@߾|ahN+  S cwR?1R#ȌGv ҌnV;U2PH>(76|qT|E5X' j5tՖBXk\GlC"5~~"9 T˦RelQf XQDinPqibAjیަOzCih& pAjKucXȀ4]MK066 I*Ā,14FT?+fͰ9ו5(/׊.=J`pw'~?P?}$M&Gc5gϓz*[g9`,A\_päk*&<:l2o׳҇Y`ub)dRiޤ!+WmgDB(MR[ᫌꓦW`d׹ሓS B#!_ aΧĥ lti`2ߺ󥂊cK*Dx$bӅ m kxmaŅOҝEqMs|>OSQ{'O"VrD!I~J+÷_&"h8r/T0KqT3hͣ2 U"sICIj7'j=:IZÞuRitAW1IZ q0C $2=Ou>FZC홖g$2UJ޸(e_z%/zsHĨ4$8IB{S;Urzzݼ!vG^luZo+vGf=O ~ň~ 4vJA\Kʉ7x E.QwߞfZV){z) ɓbBn%i\OLw'?u}l߼ۯ~™V~P3Qe l:OގŤ%;GkVԃ! D@%U3idDŽ |}Krʋ%`sm[Pre )oWZ4:Tu۱q~-k<_7oT}{x@,S픽XɱX.1zc{9$1^x/8C^[k8\#"T7I5 SܴL~ xRZdJ\˂{rA.==T&yMM.;2f2%fh'2ѶN71c((M lτ;p(%k5|+NP[ǬVX}ɸZz"9UO0"m4U9&@Q{)pwewqO+, ~`y垜`0~?\Kt"eh7#Sg.Z 5 AO@3:[wIpY'9<>l0mʬXp;G`ge%:r&6+YvF+?9CuY ǞLYիAODAZZƮ%t:\,'ϳ7E 5..RI?~4#LaDlGWN(XI PbEȔ]Cyǣv)+/P'H\Z&IZh}^p, OO%Fb9YFWLIX.npeeн ;ê2!/n=K.Lbn jد ثK$x,P񸵓:&H:wbIR" nf~;\-4bʰ]*ۦ;&pq 3cIpϞ+륜^+/F]-;6Cu+&ϒOMF3&(l7;.t5̑wl;X .L6ׯ jwICerZ0ӅK'TcL |IPТsIW 3bV:)" Map#{C_4d+=/Kʴ-4>;@rT:ëG$@B !xQLq#;.j=+A5e:u6T4qEp[HߣhvUː^Y.+^ +Bg;,zUioyp}_<B)t/HpB QT! X$xa j}n7fЬ~ʗ *K$A48MЄ26{xі lهo> #%& FkSQxjJ(~Hx`KbL)I65f$ j~ EV}uE(dh՞+UB ="F&qi9Xg@m]…ҷZ6- <@*֍l6҄K%шF +- V߰W`WDdh ^N<6$0#]"KZXlvfK$ >˵z`2ߍ'RqHU~)Ժ>:h aj7t6w=@bN(1LߞrˈvUBu?g٠B  _}jn>(!8h5=CY6ӔcD:N1=jSg^,gӃwToUCfemoN0HuoC)D$r4aIv`pMKX3znyYdrjnkI0< X%bLWB2%O~埑᧏?ݾ}WkbTA 2r#U{IJp46C[~E逘44>ÇLJ ABK Ar$ +ҝOL~F=O&*2b 5AJ_(摱8D%+#,ϩ9I}/wH$.:'ҭ] V7-6y{QHs W4e2%xGosxʴcل^4`9dqolihq{v3m"-a9- z$x2"z'[mD| {1| ,iօ7|B=Œ9n-6>uaeF Ŭ#1lJB H,5yLWFdOxh!: ,6 "W/iw§q }x| fp %^Č%ܷ܀92/-Pߺ_HVm$$Mu:T/&foRPM)tcE9FhBA J ed%GX(639B:. H-]lIQ<ϷZmI::+,*@nPf]&{@Z@|o?d|Zte0{Ez2\ZR #$[č|,/?L%~FL7 <OT<20A %Z(;&qxbZ,~FX(4wb%|EϷΧřdQ21C9KF 먛\!wmLH7_<=/^V +`3DE9xgSNj,|4ž[ }@~57˶e>1vmrEq jueѬd(6 T̆үܻōxcFe ib%Yef=v宦r/` .Zi/y)~.yHӨw2}] B?7T [oy3E!I Q>Ԑo=V^Y6ޠ&Zm61RaDHKɻw<5t GX_td:gN  ]Z6kTr)¤uCH";S|NHi]G1AKFo&Sm v`)Hg^dąE;%1GHgx9“.SX҅dO˥ ٔ:5h_e\}kђA9|48I⍍dլ[lIٖNVZ3k3+gDƆI:9>}7=O| V%P/uU/~n(lc`2TŌm6e)F3Lt G*~r+"47͑M%Alt[z9 +㦏v<>ѧ[ԅ Sv01|WQ tP4v!"fB9Vڍ\!?n(U bX4r~p[*z =d\0s`29rD SI}-YYr!~@' ¸)+`Uۂ,8Ж3t`WTp̠Pd&`D9GjB2bKXp Xc3ܟ,}]Es1RU7[pnJ]'Ķpyhu 6fOOmB[Ln Wvc7,/JI}iڄ\FȒmcS O/ x`4rp56 woid)~eD QSʢ2cLcxD|*Ф,?('˳'#P.x~(soLދu]&d<~_/2 V]}"MZhbp1(%XbUʀgխ$3M%nqPW64(z[U5 c "$f2Ǥ'BA!*JP֔I$)d_zA k& /XEU+;I +F MAiY \Я Udwkh.ׯg j}yV&:|o13DBt!A:>~hoӱh~L3 ZNz nrfL?|Y)lӚilpyH/Dd@)<Sh>Γ\>OaK#wL`Ƒ:?QJɁ0-uJr<=H49Rz1~Uگ!2iTb2hׇZ{my: Doks;4$" ȴd11" f?mٙx1^ ؾ}s'.e>zs%fsm/+r$qq#)`D\('k4n62fmhTBPnG#>u?>q+aϗ s·xfӪo|Zf K V:Utk`|:'DM)"Ʃ)[$!b5D/]$9|_L'6\8*%<NsoR7E/EhBIq& +qcr(,fb d@Jl0w=xQ}&LJoa 27o?AVFM*O(MC%ef}'OHLȜ?HK{׿: GV0~vb@M3KLr˻! Q kfZ:?dhHTnϦgQ\D)#0k 'ӋO:4b3.qylk%JwrLM۫4./Ԏ?DE04Q\ )2;lfyMLeݦ=8d2ݩUHكv{/-ZF\t3&v! ɖ 81*iv:'N"״%|=UsUWƳF'H[,+{G+USG2e3 |D1xx.lHs(]ɘq/rKRP|+a秧BA`t:u}AҗPK5 ,^AǴ_qWRDbZvԱ\1q|Hqy͒uYf $9i(+Qp,#CL=QUjX<<}3^)^ݐk-~#iB$G8K~ȋ|8Ft0>[`( bKPS8 (_eoD˧%(%eRhNԶr͙U }O~b%B`EݔgdB0&8r`ڥ'IGN+@({./!|.}M聁2 cdl ] xV)>)ZS  ,'szr^P{X9`N60Im3L` ~ˑC;lP ☨ɓ< Nl A:Uf/u2y嫷=#&I[E ]'gn,f". TXHla#Ht˼IkIu,.b#V(5û}ڼ֜ BD or{*@IDAT{} rT׵#fBRkK/9ԏ}I%z[6 rJl5չ:@W|ߦBAs0ʙ("B&΍6#awA a|AX4t xFj*cxX{Q*˱!3"\cZ=!Z)pvS8InyI7i%_Cf.'ZTo]u F,uu U1 yXN|*@$5gG/eg /lw`M%QI. |D!N9MImz+Y삤ndNlz@Ub7"rH?H-s餖@Ϋ1Irm GzjWNc8\DkjWƗQ.pw(4=0 Ac2Ҭ-mJ{*˭=n*+ vCu/$0 (ur,`&A]l,XCrhӜ "rb VSgY2_0/}U=?<<xd:ZLHU6`CxKMH]bFB"9cn6;~ED܌0GbniVjfB\Eo~P%洎s3^CQU^3V½c~¡N;S?dzE}%fc䟔Qlomgx9ꔬ\d՚j3I \tb,Je&oޡHDؼ\7Ft dLj>^K;m$I.A =eTᬆ..ߛ /pHE6+fuF(< ^K*$QVEY<+{^gl~;8"9-dd Rk2ˇ҃<i1:ѯFrД*C|F]9!~KœJ 3%6 T:?j$Mj̷9T!cbuɼp$mEcƲYۤuKxBw攗=Etkzc^J9gTC]B"}7UD6*Z&&r# 6/"5>'xa'aBmwc_}JXH);}68/͜v@UxW!FL"zrC y2niRM4;&2&F7<)n_)X,d2G$8?UR \ @q0Ssgrzy nZ@[J\]Ё%Yij),"MEB}uaJ^`ˤ״I'm瀤 ^_'i3fjS!Uؼ Um,gMFFKNa1w4T!XgQ֮-H+/;˥orR+QR.(GveQ M6FL="x5gzL9s(jeGYx;70g?Zby8eUrHzM7\)8ul0c~Ip-C3)[Z-i4h7+%8 ?E֪_X߰r@PFcd1I)Ne>3sIQVhYI:Z#1c}"3ԧ\ۄӼqxc=Ax6UNtgX^)'${ s(>ϓ,|/*"`biB\vm"C?ԑhm?%v]Rݖ& hB,uMUR*%\FADf$_(>OA]RM 4$5JrX o3ŶP٢*kFah,^}<%_A5=C8:_;5)r6;Ъ:FSk=μ0\vL' b&xdH0}3bg eKr]p }fEg41(Gĝ = ѵrG#p }UTK 8xjۧmNT1@Yfr 8ⲸFWýu&Zf):`!!ug,kE&PcznxbS{`䐉\]$T0(m#%(#YL(=w)Ha)7GR=J1"la*R=I 8Cb4#M؝pLϓ"A%WqѠA`ZKaR ":lubAY={!daCCǭPDq:Bׁ?]Бܤqt?, StmkTi뵢oZ5*<V ЖbtI1u)KO2doO3;ghY48J^,O0Xట@;~~k?)RіözRE~.OLI9zAW_h鐔B~&YVJ6#Io|AB$Fl ׯ>,!3ZjgTR]}|>Hݰ4Kt~yi3:1+4CQ k\S4SmZmQhɠYYdUR50nTXͥ 'kT,DJq\߳^L2 mb0ALci#GԁLf{# =Q^6iOMz&IN/34E4+9=1\l`0Jf ij[Iw>,DO}ew<<˗/P/zf.,-:5P $5v '=kZBگN&T7cVMU39ÒfѥpڃYwQ$.F'U]eEA8'LI䁾XfJzL %(^KH/#PFy@p/fbe89=nvL8]d;AK9$=T>Ŧ,pĤ2TI@` ;+0r$ ^4w{#~<#Rw /biMj Tf|+6A4z`!ɱxLs"*dlXǚmt/^PLGZeް1g3>(t  )QS9-iG}`&|www<aC}Wt~: ]( jkk\ I+%^tRPӉ-D= ®(G(NFz ฐd$9" o E=xUOpO9j)C(9 riH|ywNF%J'Du'2bw>O8<{aPȞZGm:Tj8 4 9=zBtM C01K؄d%&Pmrz h4&9=.IN1Ә PyX(拮~i 3 R/X|M^A3F[ؕ},OA@-*81t&EEy>~\__fހ-LBx/T'Ly2ٍH fR1|q?|*Az Ʈ& MlmwPّmJ#V@S[IeގJPjAm*&%X͞I1M= ,b'yF ^ɯH C*&pZn4 2#/80X):-˄,Iktry$hotvѻN\ VX4eF%?# ҼPk(A=,( *70 C?ɞaOz2[q̻6=ݑ]R_Y \`?IQ&Į=| FI8GT&b> ?I),p; c){X44R*IޡEx8'GR*@В@3RŃF=E='Kڅua*Ѱ R@! &Ԉ;M#h-oj)S.N:F m2Jmg?6'GJk0bi@o^tGv jF7߲&kbu.Cr*RMLWK8z{cb9]ݚ$c$#+f~ŮZ`{ KR4y$@`ߞЍ3d _xgs\Y B :jj ;B& &K"Wg!9;RM%HXr5gbw` Ȃ Yuߨ`HngI=6Psd zb ˿ܕ@;D$~ EIjji>҃s7S)Ar,^W?Uonrmi3XAJ`VYs%;hGf_JD(3{b tAu=R* 66*-& ºCDE@v@oӃ3:o5퇟\e@w֑*"9+Dy~D^!-nǑLAbSS)KY]Gas O=rV@O9Fͭ^Hv( oUp?zu9Fi#+0/pHfד>iɓ}1o6/t5lvrO|鵣D4_a 'Ӟ=lO;JHdƸ(Q)%A)4J>/KyzHiXiT3P%[I&5pq'Ӈ-PΧAu"kFJJSzSrOa=IV+)dH8v.6 \aV/Vf̄Xフa?(i\@ d=ďQ $8 j, TP]3'3ع8z; Cpv1#g'<.f(MR|]bN♉&Ays]5c=)ko$"b` HȐҬD8(>ϫ4|4.=Ns,OEtS3=l8kJ5 -r!./6#쐐BHv(GjvQpw2QaA>=8O up#8NhR„RuN|*o<ɒLQ!P(ۗاL"xdXR IUEbfz#(K.,O}`$t;v$'AG:&"VeڿnƢЂ(nJ_~/_ku'Ϗ?YF&i^Xd"dڃp/橽F.%W!1aՃ`d?H>ޔ52 "Z|O7oܾO7?U[&aTQhHL8Rt" o29@g EDf" Ka)0\:T0d`.HdJdLhqcCt.4:dX'QYI5 bmH)/W ]SȫjS< N$xl:X+lӗUMp8mtek(B_rg\RGkV0%4=.ưB$!FǢcv*dt"'uYti)RB0 a:szɿBKoKm2+uރ҄Ym~@FA7ZyY`t5³rdpIx}pDXH.OY㿼؂.j * V!Ux  FЀOU| rlbdEK`$نunCĤfq|~4$rW¤ WF6#"inP̺eiF$&35bPR VXH4ԡVz)sDoꧦ%+qk^@x ;+aց*`Y'd5a)f 6 Gؗ*v ^-'.m?Y>r-׮]6vʠkd]h}I:0+]  gU 2;q;QOJL@l tFU{Yψc ,Sd`FqP/&U۱CEa>?ܒﮏ2;:E{زÊe ot_<Eߗ_߾Ccߵ{SIZSEM1Xä$wr{O$/a$iӔ"14nDY@JP1޲鋫~+u3!"nOAWڀz7QhcD߰5݁3ql ^eNxᠶk5 Z0څ9ٗWPq[M;) (Ti=Y.RD]bo@xXYq@K5Ɩ_4x%OhW"]VSJ]U0FYT\ldcU+o߿CR-d1Ax|4D^e TѧPnhy,H}I K@S)lok&ꈾ1^U @C4L QYX# ϥ ;b%a JS'IkEUYU|K_`8!Ce5`ˣ2։㓪hl_]0 b0#BI3^X`tK2=DϦ%5%qq Δ& c@F⍑E"QD=; yi ݆& 0)Ⳕ'1 ZB2%!f GFFnL-["͹fFb,vEs1' !>uX[k/ـ}س95` EYղ=P{[&2I20:bM&k؞7}55d9iԇ0b+x}]МQr~[0r>E]Ԍ B'I*"-G */2,Х|m䘰a_"lT."Ҳ:+'$-l5/ЊxKj S)K:]`JuZKOb>>L/Ff U߿IΞ8r"^B`"o]+QB)ηaj/4vOAչOP2M{CT&P~KDx*{@AJFjP1=/Ka'KmG.i1WSC,h^%Nf,cEk u2's(1L\xɦf$O2H-[QQ5lg|maCy8nr:6Ɨ0YLsp , |vK.Ȧ lcϪ3| 5mi"+eĞw.uj9l4gThqZVEf/d|dz a7cmv IlYO:+t^.4@b6P8@[RtE 'Q>a='W-!~s4+X/g3AZ],bӝ6y4ŔUep ƀWm Wu9+3B MDR ?aQE{9~3 >qw-/|L< TT`А`;WS|Q4cֶCkxSty={5hp"F m`fT8`}`q=g>9@{h!a+mr!N͎=~sP *Au]MܐNhV[3fTl:<- S PLh' Yy@&reL%M$W.r&*gZYqF6uh5mR+t'55y^ο?7jZ(&GFInUGHĒG,#$`E;'2>e1R(q^N>iU ! \Lf4xH.NM ًA $\$;<Ғ-^rmJ*YP6;d5$8 Q@ G~X7}h[׫&E\bحQ%w]2W061'_ ]霏CM-#chʒh;)T'(~$ XD^lL/ DrnZ^ q)[RɄ Z^^vl-e<{\V"JIl+Hn<ǵBE:-n8%zar_5|\0/1}},\6*q{gaW nTQX^iF81кv+4jAҼ$`_!27:@'j;W _Sq}XJa)B㛌Bс^|z9NOdY0B;3%XzYLяGjO9 \"A]zlAJ!f؍_D\X\8";^'S͠t*Q?RCQ'ˑש_99_|ȔxfT &PIZ3=> I}l|\ÿ y 'nKFw,{pqxpZV!ANJ"/`7E.[t@v*HX. X>"VqVgͣT%c:Mgfp3ES1l$-~8a#0R x mS0֙$ӂQ`ǖeYnq_hTE0h&feRr4%MI)VDN 7b?Zωa;]z8.i$h+ T*2 s$Pjd%xTхHƒ ¼I?9] >W ٵv/2 w=En0:tG9̇t_)=}:ah_\ r6ט]O4na_xRS Uɘ1ֈI /SA%eo8Yjϓ+%2JXA4v&؅2{%$u/ݭKua($Z߫8pdU8٣y ?_Bx8,`!S" y{H*o '*kH#a| |x %g؇O?ai[ c&>LB#ܺqm}'vxP Avr0`g_wKv"|'Jb-}7 sO,9{$` Ϫ_Ih'$x"(*#͡SGIpF4Žqq^$&l&1$ 4.Ač֧66,zm_'JVAUa {akY9:/C {Yj`Vē0'y+O<10< ޠeUd2Gb|,| XiC P 5]Պ'SoXQЩLv,AH}hOTс3E,F` Sl1ޑ[Phz{n ӶDHK(;N- 8Tph{0$D=&㺜0婹D ϟVr -@(@䱳sE,lR?h41}_$2R϶|_osi윷_e ㆈs^9I+5`_oc8IzcU@LMUSXP8"xgH_Fu=|gʕ2s2x S#$n+۝{;5d\?cF 9SR_knĬK:e6B$CZK  Վ&Lp@]+>O7ǜ8jMI=- hk&xۭZHlі7%,7^Re艼PLab@@~'._0?~v@!20FpmR?N=8ôCn7皬+A"#_>Q! Teau3M1@29ܗl^Ah2)E\!qBr<+b?0ɺoEW\bN> gMnh"j*RNA36Z=Q/ LjJWlatIeDDKK0;<%ݎ%IC 8‹6&ˎfEIweG]9Р"x)*UA9m VJ#>}ĥ;laq T2A{n[m/bHDHB'!BsYSKj6+4S֙eؘmO QpIҢy|~z*){x%E٬N,^]vC 5 Z<8pw5f Wb?:%?i2cP#)b ߔLqL g !"х`ı$}8w!YDHI:"E Qw[;{q/__x b:wlχoB6f)lVԪȐ$n&9*:+==ܾEP[}R|6w,ȔSK5Mv dzÛ(﫵Di\RS7Z*,E2)fܲ <M.kjB4맴%{NF6%-F #*rќP3Aʴf1DV\Vg m^hs_M-;z'Ma"(qw /ˇot_Ƣϧ'; :7lg[Z!`4nr%a@(I#",ŮH/r"+`,l[ lgF-nȅp].^_D 6.$b'g'd@sKhAsgkxʏ&`ꔠs!8e"'S֛ C{#Y- q*mCHymTӛ>d1ȡC$%u8! nU`l7 %PH2I:I\,dNQI'\'^4{PcT, f_T2Z=9/P"FѠ2](-Nf3ݔg_OllsC=•GfqIK" :j>WAmNŪK (/F J*.ˢ1۰ ʬoooA?EmZ&:~O,nY'NjNt(9'XO/.lM9H6F1,m6`Mz" Vx~zqtO4O89˘~eO#Hl0 0$FWٻy `,@qaC} *8.ʅ,G+i`g㉌x80GUV!N4bK,,"hkFhO5Hz5''D2p^V,~s5AjQ-PbOjԫjp0@ː%-2ϟε< y\wZa5*Avs1Q5N8ԥX DH5)[YV' XwMUD`7| j#|aHW5v nNx洹)M(@IDAT}2@+(e`2 2u ;c2@YdEC  yp# Ho?r1RG cr&Үn]6""O"DIU{0 +1$xi$ !MWRł(N @*D.~g\OqjI`␏L澁1!A'Γ\} ,R+IM;1|fX=Uؽ.qCk*VA1P[T\ K;xH71aGYp/tv`SM~ݗabzOQ1aU7%Bnz@֤b 䶰4l C|7r_mKh;I}9q/P,T]bRI+rjX'8M\yJզ?g dأrn 7/ϵ́] .+ *Y8`ovyuEޖ}G!#)OUVT 9QGs _^^%fX7%xUr6mЏ-XΟV3elN19G&nr`bdGqa+=eF1]\]*֏PTN@H\8DNu/%VTaDXg璔 dQw N a&!*BP3_KL*q-_^}=/ -`bt2d g\ɇr/{fpbw/ ,ήIO %{sv?Ě9Pr㨳j{*͆lv(xu Utͬ")x]VHgYx׶њHCR9.ҪJ N&K"$&Db-O e-SiUzZ\T:@|h|\LD ZRߚ!0h97p&Gt`F˚ lӯ&$5T^_}4\q`yCv,+f>ďry-衺ׄmTh(6>3K">P$/4S99 7*'^)a3ԚG4Lz!T@;.9⮞ mK.u*1MY,5_ TZ2zy1{wl! ٜGT:3Y'k|4ACc&dk燱H2OJ&)4m'cbd=ѝ3 8Wf3`tG` eCx|6"#vHC0(K#cKZBY1u@jnW.cN<rMh v}\怯G` 2NJʺ,~~,>g*FіO˙:V BS' mi3 e2)ƣ&I01G"dF%l ?2GOlHZl6ߓݡCOÖd0^M4Vdۑ(d)({\!%7U9Rdq&~) &y;2~y1ѺI=s lf˿gi-I>yZZQ"똿ե6,RlGg2>SMU0n(&Q,O-o/I\˛C)si4L#űcb| 6ƬDx Лh6uZ#IHl>>VZ^Et'( rS?HEN&0qbl`/j5xQϵU>Nfr2x(abJ*rK/df%`>iIVnb\\ 4*N/+ZCr|ՔJQ! tڴyԈ*VIaGR$h&7N$,cܧiްȳ|^QC!nW*I¢dG`o?Hui@y$JՖ*)(Ǩy/l)^eJF:qY9-i9{OQL BbNh@$R6|S{X"̢8y騤v*ɑo"#C)5tp-jP#|&|PQ{k> 6bZ^kO">xl[yQLZ\slOwQ&h=>W9 ,o>|RfB,LQ!WzTmx"t9-X1=m n 7ȟC@rPQ2&Ϣj)-H )~_Gsb3 Y^ǿ㑰mi7q 〉g%Atlt1(z҂N΀z.lTC$x^*"< 5YwRK9XSjP6A}PwC͕@"dh^K[U >Y#-r"髸ޮQ]AUe1i55*6AST!k qR`i'Wn8^fs Qk 9ct:WSLxݡC^ɥj}˯OΧ2^FFR )CgCkJct jZ R[èr_NƮŋhRZn8Upd:O֘&s|8A%l<$YuOqGn.&ĄpuVx̖+#A`u/Ʉ'IWU] \$- Du /1;x<سIPz]kVr /YgƇx»i3G!1 iE3FzB]49h̤`~/cH\L 茯>sY !:#aHfGlJ渤!ZL^>)MH=sgx1Y,)z#-! AzQˢ3YJ$ 9 sP_0 ,czv\/ՅBSPm* TL3h<٨p./~ّ@U$y-Ϥ\׆0SOg 8# poOOO aO}V?~gU(kc $T)l˯7/#j. DtcǃA k&3%s,i`2g`RãuЅz8B^bc֋4=^)Ed1h0%NVA!C`6Qߔk; 89'S?)aR2@uR REOPW?JOx< ? \e6~!Rx#yV\ V% |s=˯Oc b7bvo|KR)Ȋ q$-; hF< uPŅ&:aMهZx !Td!Q̣zk@[k3M]EFvfብ,0^X mG<%YsGG) `Mlagfiin1X́8v#oAn.k_^#0cvkx$)/;m8_c8/g〕c b֋g.o>\^H P"oԙ( SA2cP%%oGUH^ Uu 3і>]0WMR:>HPW7O&V_IE+'^9ci_‘3,c`!̄HpB -ߠT.]Wt+CFڠ7+(dj܄kyi\ 54Qs$PN2TKcyuSGy-u;M߈M+[jDH>'[!9 Iz0qT·%D%F,;Ofp>Τ\L nh}͒.Mu Ŕ@(!8lgAxqCT*I= + #tZs<\\֐r\NyxWR:Z)MixS"sUnEWZt+DYÆvp8q|kFK<-VJ֍ <ڴ*\%!PAyYt#KJ9^͓wV6ɪd%8иB[IIV2 BM+Q8.T9% P6UrenY DDLX!VЁ[XmVh=,3Z)|Pb-1ҔnkJC@Q ˆ 0t ߐ>Gqݟ,d(B# MK?D2d!xC[鎶/?^^+1Q¢rjfֵ+|B'tl6kj۩p"gp8ttgBa з Id%rs&&B,`A!=V~si#FW~^j>4uɣc7G?#Z(͒{8#OE#kO3=<S/.mO!ĆTIxQ~!>@-xVɱ6kq8%=MF%6򒡑Y ^{=Ӓ/&cU^no3245u.jT zDzE2V %қ煑vG~EDC E90owDTwTM\(iw 7 5zX<)DGT2'b1xv<\) `|-ixN/-G~#eFC K!tQSk9WyBAĀ[LKX!f XkoR01\3PB88` 08fyi+Y xD*[9|bSU#1q乀2BH!(!); zIn= V;vY$VR&#/$? d>: S%"鬔 )/һcr4M3YK!( &CW!'gWtY(n ƕ bA޹SφTX=Ym;i@YB'o_9dbmZ 8dٿR#Tᥦ2v&@l\͹Ij*D$dܫR8x.7]:GfX>v,fe@o=q|1-![W&c0I/qU@Qip $vI]Yy@c!t葵0wݖ4[uLMf|h^כQӍ\җ(x~~0X<8G !|h&uM|&i!Va$rZ\Hns8UM$b>58B>fgGi7A$T"bޛh;S1G[Mp 1ѣR#χU-mM@0Pqы(n܌LQ#*g2^`_7 S^B\ـ͇l K,3Բ[T̒ A *%q?*= ٲARf)\nlpJiNG[|^+2bfT4~>sx]αWN~˦8l2B+MQ賽TJLIe'iw?iMon*PĠLژF.. 繀 !ʏn b8OZ8+7r; Ʈ1dQa:F=QQʼnqkG҃WW;P mϭ:o@C/ }s8bEĤPY^%W6D\40v +|}(""egQۯ촓ĉ HTO:excB)֩g}{Lz.n1Mfa`*rVsOg?"KE,Μ虬6&صfp `4sE{T`R6fWT ({`&9'R ^Jio (/m1e'Z[omSŗ=i>/s#T4Sa iȪ~ϪeQufrqajb~m8^WO_\\87Jw.,2JIVK:׫E]vb7c&\.򞛃3џ::):Ǥ:;_MY,tJ9޳զfk(+Q돦؃9"1丽פ_Y85b;G;6TਵeeMI.8xx]M,u}' -W=_Sh14t (ޱEQ-g≤o(Ռ](\|A{ԥKcURrgO%|1=i5'mop \FsRi R}y-H%M :7K%_ώ ( HpRYkG6&Ҕ!!6c w"cRYٶY^w8R5;d!32XJaĘ`ScGR/EblŰ ndƑÿ^aUo^α'")gm&̱k2uG{:'Iaɳi[x o/Ǧfd2RQSY5mm&͓[eXAM5`S8@dPTBT+-"V4t/V\R=ԖN Pϸ =dqmL;n)6q.6N#6<wrR>7 F аDe![5O#ɜk5N;5l8 Jx9\XhE_>Z'_$ /;E4- M k#Ibsy] DQPs5M}t5 ^y QQx"|>kzYLum|Ld>;n9zkR&+cͼdq[{?I}i^a%%K9ԇ>lgfdp]6ٿ.%}ݭ(<#<2O+] #27Bgeqeךd@&AJ8V2 Ww||:^{)gI``2!^6/ :GF"etji^g~jI>С>6ΗDg^|rq^x YOgb+_=nNM쭴ppI^v8D[>/$^R[>,̛daD8R k< .p)TWEOx-d?/Zm}Ʈ"Ϥ rc_8? x5S#,ZʷJec7,7|$)0r\˘_un^4g85d} n0Y@$%Eؠ_^KPMe7~z~Z+}OnxZ!0>)z%sD/fh§bV9vsdzS^mEEFJ:>Q Uۭ:x")󎌦4fS%tS[ 7 MC"l'œoO+2}Jtbd)7)z QEhZ2P;4^]Ō|yu0`2\7zუT;dK.?=?>I11~XaXٰ8>d[ 4/')2ΡO&. tqk bJtS24%a_D0I2yх.:>{Y3ʩ/-/7B@љ}Ch9>0"5c~LeK|* p4xNqPUs3ܮ>#W>.|qNh,4*+S |_z|Noo׳8x8 #/$ i4>ݑM>FO).i[dt3>ħ|Cixj2 N"@̣%d%E:Gz,3Z$ƣ.y}YgH$*'#֖|v XH{ VQUg1]HwI)CGtAwX(6 g$%OUG5oPZA8EAG'RtX}>G{98:G%Lp/ĥ(?.MIHt#BՅl Lg'OtÐ{:LEѥQ1MLMZHn r*JsdcZ#NW38sygTA BJZ{9TJѳxIc&6WiVkp5[gWs7r5(.W4DmL.3T|z"/MV`i2sE>IĻ$nah0y l( Ԯ&괏UdsV c-(UqvL4Γ8ZF2.ߏu0_@1*aTXn;ox\&b o+Ux؃Y6%4Ҡ$.8rL?_[ oRR6fw ӑYc]Hm"[TQ{oR0Mٳ9Q(|mQ'Q^dgI~Aߜ>_X v#R0]4D4@uurSpA(;rI]uL+0) CYCAKDJ6$Y6.R#I|2!zDs|=w2 Șs-)2'j4Y}2.fG/V*gIrbxp&iq[-Lgj3S3}JZ`6p: | T@@DY %}NK6_}^C/G,#Kz"je+!Vt2p4 A, @),[(lKb>61N"*X"}zZLt7 ̂+@m'bkNaϖkwcoY}z4MF'jJqk$X{$苔hk{k`4x9"nG_ݍ<6L󠦳rQ 'B)(.kۋtE@áoi`v_V3D_i0[Τ`fC Y>8D0int9Qz1(E}>,Lzo!WKK[@+`}+ka={EI|v7Za!%5XZ.$wQ^G p$,C#Uϣn-rtwLw=U2WZX+US'p&BJ\qzOd<~;s BA CUiA:G#q_.szpЛ d"<.|N&w89D9y$H87ޮpWp" *X/Vs%"Sx1_c$"|ExZQ۟d~;O뺨 &]2SnId2fhdx\Y%5WV 0ըpJ1%8v3EG'r z"{0q훯/GMs1"*yVJ=J%`pQVL{cu0j1_l椢4\8K*8!p\՚ кu3Ǝ1Se3mo2`jY7Tur4Gx*\"vJ=$C D+ïR4@טOÖ8Z^ QZB6#w6!d]dWdw$"|BiO,pn#>5)Ѭv[f;h@Z%W,!"b5;$X+mYc/ -մy i$7UH#ˣmRMȃRV#>+lB9VLE),q$t+"=tQ(6bkKqjZ^kٺُa3:;x=s]XS G&2nV:q LNGTJFC*&:"* K?AN"'f(LpHVyT%(\Z~V:$ @6|ku ܿ]=+@RJZpq"H#8JQR*aKٝV ؝O1y@IDATl^֣&l]1N*++9l2UF @r9gA@/(asHb" +$-8֛!/Җ;T$p`^j9tĜVY:L%R8$]% //?;jE v'x:VFIkF(@*0 ;di%7iv,e ,*+Ii<xjdtU1g,g#e MM0$!KwpAesf95A2:awWNNȨE0W:=%Z9*iox]і3n@J:ny2,z^_VNu1AU$lU3# w#\qYX4 Err**aU,h&Y0'KIq>?϶GtDL}I$ #+Z?.2_N'Ɇt~quNBV*%.J3FzՍ0!|쭨0p7)"g&;IFݭũp,XkAɛ9K1҈+}|rI>~?wG~5NN 8IIkT՛,ȌHm]ZhyK`_d x M27X<7ve)v>G4455~AJuv;1).!itրS4&R &vAtpV]ZOdj /8 07Eu#]hw =Bf8''_tq,BcR) |\`=6d~^)_ S9̡[*šz,<:sܳҎ:*07sH ?M_7ιz ViЏ6߭+یзj99{uLlܿVoKNgf/IvbLDcv|MC1>pJ ~=Lsܦ:#kO?~ĉJ8jZ9$x+:6t٘ҶR)l Dl \rןŵ&fcdMLMPkjgb Q"u 0qFqjp+XvZT2.4LqSގ:d zIGS DlJ_é=ZKVVul`X݌ohiDKu<]*w.o:v-vULN'TA?3-JH^"`JGbA, q崐c'K}UB ]d ' t 1CU2I VERb_<7P<nR:>JuaˑZiҳ2lB|M {(Ia+'t:zkhSzq&`6aM /P87J=&eaWCŠތ/D,rV;bFl/>6N3 YpdI-.F'r\ʣ8 rXjIbe@Owc3@`51ƣhCa;je!f@ Y1lH&֙B<لcɇ[-/ #a*wB 0iF/pS=Ϩiv9{O՞Q()4: L~;@D&%T;ץRgwzsH;V6r<#'%3GݡkO,RIYLvxh:I;;r: +Gg-YD > `se gi2Jw!JJ.u:p'zTI!'ÍHج["39{RHم7Pgbq[ANpe+NTXeP8 g(b+$3N_ 0t7[^rVgGqj:eeHu7{p7{ԋp|M'39 :!xԜ2HIUЈJh*4Tfy;'G(5E`eH5ԑ+d!rJ`z* *!P@@K$M{jjmoKŌSBoA[AH(y9#;p(2Ԫ0.ɯ8!u(ATBI^x;9YG@xӲ9 .Ԑ7 kH.EJ_Uc"8ݞej⭙OøT}!#`2A)>oU!xD_8CR)^Qh$'gxíІM wvjtKtl-O6-^рYH#2kMϒNG;# \A"Fb %y9z=QװrRʓ]2so衬[E8ژ.wH!\ 0~d2jok-QX.tէ4;83 -L$Bx4( im+9FW)60d|}uqlChʷ(j+Oh[z%%yty ϩ*W)遨l\#֬y~Pb1v}zgz(Н! ݆at__!h~\+Ձ̴`M*2;qbWmX@?VM*e,ckV#M$NQt 4.U?ચ{( k7 =#_n[i85^Kfh&9WzE}iyU.\rl>t0›nd"G1P,5ҁ(E4O<l̂ &ZNCeU#'G_ɲPpVqqHݘiC* ׻/ݞ`\I!YXz%P,IDޞAhӦMW~(WO&ik~֌vCQIEIx:K/[%oo֪e4 pqX$Ezp}c} />&VR'^zq Bd%Ӄdj&HG,EF 352RpQ be.^דB{ZpP,Sht(1K΄G7g?=>e9M HءRef@o"o OuM %2B51ra`Z.Oשkd{Un4T~^w*tkKQ˃J8=")@z)fmthlwliDpyL(Rop%T:# Ȟ130ha75*L8vPA#Z~mvb- 7atBB!>?C"Z_Jn9'$XDtqx::=z24 }:"hE0{p^S] 9~al% ,O(| q:X -=ei,ӡd42=Sb'ȀQ-8He%?l>smef[$HzṯtC v%K\m(Z푬3Ԓagg &=#ˆO?Q\`ᨍ+ "xƲL @lnTVUwK#x1;__˒[]YL.w9bϻ@g!" hJZ$aZag%QX tw w'U.4 +sp:P=O5L'1ީ@D&b.%bIP!pST &P'E몕&zipo2Ke`jjXwIZ(`\(H/J[Uȡ˦RǾeR$h:O׽P9Gw"F;aHX)63o&Or]6w )Æ،oW+x -D:=MEC@C!Y^)BI%N^n"Q1.ɘձ8/&):ӻ) Υ,;Lg}da8+U;?_gOALޞt[mbB{M6<ʮ\D[큁Ҷ۪&շXnUw0nr":=C DOJg@"3X1,)FXﶢ7.)>U}`< :PBibIXK\JKDǷtwntss "i7 }lDHn9X0s̄Ay@Q \XS$OR)65~*5RfN r-'Ep.mAVnGe~&qL(ځ͖ׅ*li1G?9<^ [4Vd(*~]LK+cxd\.k)?+L};Z< B dgDyUjZR@ZO'c8wbcu3 @^J!]psՖ/?˷_4fgG%!bEG~#!Z=)f,gJiM0hҺk2d>/{fHgf]Da>, ZFIנq|sfпu*4bu.-s1"EtgRk&OWY9Ѫ(8J/BMK6u*xvDg@D}/جs+=+ dZl'&7r";Im7 TS++h} dJ ȀaD ir.ڹ =RiI1$/zz,1I(^`q!xC#&edRs lc%fM 䁉 ]p})Gysxiz$^}j} iAOp_ϚF>~V8o(wD#$ԬwޙV!)#D#lJ=Mjl5ÝL̨ʘyƻM HY[ZOGqVӓD-ur@%VUWc!M\~2=eTD&zJ(]28avCpjN72l2̍ߗXӹÔ$qrYl7tߨ(^Nrq\Cb `5ʳD 23ǜ煸Q92tS'n/-/B4=T!Q^8n` s9yb^aO&?]V|w8q?h<vL-dno?qBI+:@)ƳdOq}ݍ'!c?,Qc$z )F->0Б8%.X? Xqn2FO`C$=^WdpfQ66-'" IFKqb ڏI9m|YN9 KPhAhqnR؆SdJ&RfJ1k ;TZs2{%($yӺ_oKk1&Q{X,$VndnvuUY(}}:ŻmlZ00gVulG f|.Sd0,cYX6ʂ$WE!"d(MXt#"^jbs٥1IW_O-yRQ Zo ܡVqN HoIgFbѝL4j =oH~;\9ꦱZ^8l(0go1yJ`,qj& ,l Ipq3|;m/>-Jl/V]N?%MaLv_S )ë&e$T$lvf9 qs,~&̫̙Q=\p"?j!31_GQ(V̵A; 9DI0u #^̌ءH#z$Ob&QHj\}\ۏj?+h~+6HKDMa3GbKGq\nD^b‰]۱$[$kkG08<_#RU;FDE`X:[67K;6Ԁ>xw'|L~hS |=jQ_*/n<Bq]j7s_U4;rJ?mb'OǤ3] ~`KżAcgiv6{4Iwq-"t~yG:RK+g3f83.Ιxi(zQЙ갠T ЗgWx_!f.Ɉ> Z(B] ݞ`#fa:fU\v/_b`Cxf^B,]c$]Aq21IlT!4d>p&3Y'e22tޱ< $qt󌸱O7n=ٟyD▎c9b.a7- {eFW|z k$~;3QL7}|*XսR=DL* ڤ!C'nǣKlm"aq; < /w0Vh)'L]j#tsÐJ_9[j㗌|Oul+ߙ2bRh%֔ IWk-ms(E#d0eR7`* H[(u:y[$M\ֽLCiT6'g V+*ף329'ݬF|kUWeCQD,+GiokB)A x,U.oy^Qњ7 tLwq·i|alCv?}J7# !fL{b>[$!.8,&`y)Xiul6p@Mz3!_'d!>?=wN u8ס$Pn@Ǧ@9?k;%t}T0/n6F5m,=G&A+J:A̗!+Jp7@oE\+y-ؔY,eaT_GjLr9VA,hiyj 3Q3]5^6qJH JqP)K:[!,fl)mpKmX+{T#jhtl5 iכ+0Y*ѦtF2455#Y#׹PH<zIx'#/cvYn'Wrq9:#} exl2z-Qna @(8h˫UY-TS$<5=Cʘӻa8$ΊaSYތBiv;<;R$E$ X2oRR#k X́Ԉ u.I9>EEup+.p_ꚰ (b7d#"q#$]3zM CZA]K5>KD߾w+dhVHR~Un,ꪡRP7pHX9{FEl]fi,S|ym_iQ̶6! А姼)Ê@̮ҎA &$1nrƳ\(IÑ2V1{2gVo9I}#))=֬ \wFN] &Ar2 WrM ❲8˷,}kcAHOȇo?DK@azI+{ŸCSp?aVԛ B-O@0Cx k)g Nగ4Lؾ+ķؘ//oSb"eݎƂ~EcS ^F0 Dխ4EJ|3^y}=|,^/wh t"h3[x!/p'mB!ҫCdNEHݱ qJ+R&폤5cCxWsHI: ]U#cR'قFHm.l`ɖ%|lqax8-7} }.tPU tZP\'* K]/R~d'4xVmfD}+ [j$cmDbvbscҺLd`C0iuC0Өۻ;- .Vbɗ>+CXNȆ9#[ҔBi)r_ =}[u:[@ۍ1Zlqroe!ZFyĽkы5BYߞt@G=dbϻ[y0DH"!#)0԰]2x|返LH";Ӻ$tUGeD8;OD ~f=Ӓltcj;wtaZ7=\r\[핢!@ɬZX _e2 FILZ> ޿~: KK]mvuB4ov,̆3Į|{L4-3ƪMo˝  ÈnLOm'{";CUtTIMZ/իŹf[L/Xzq.D&)~7à6dWfspWVsU뒣lAfK<Ɉׂn#L|]D-=!Da(`A{i-6[QySN%]?N_҉cgU8#DSlkIe|L\RGiNvHQyRΝKN0;os]v㑁0߸ێ2t9_H!C~ݔG'ĭ  * 4u77%Bٓ0r/f2@V7,8t\C*VX:&["*OOZJWi8Ԭ{{$yꤽjRhaF, i{`v6j:M%zQq:u}O@.Vlh">vj\2!(+n {Ctd Z_no:&G@eDI%SgHGvdy/:vJfѫ0,/7 J4#GNRH( qk~o@ř٬.%40Ɖlvt^5?|L ?'Os[Pc*ъfFBZ$M'\6@U>D|PtbR_JE/)"$+c'8 >B$ >> Wbdd&l3Ɗ,LPjIKqwȨ2>G᧬:=}˃j%}.Gϒmvjv}hH&v F5uDb|Y4V\6UF\5pFѮ _ɨ$?'*!Y gAW^}jZjw EDgmaOUgt'?*͏>%#$þac.tLPN`CB%P읇 !1h\lm $OFtq?egD2@+ǦADӤ$==Ä!VŠiuXAp ȕFA,ˮv$MG.$1|vm* 1gB_I;HvDpqף$ ϼ/yB oϿjLzџZ!sLV4$@r5zu{O+a!0DGajaG,R21#ǙYoߺx0V,1{jݮa昊+\ǕZS]= I"LUƊu ه´nҺp 2".BsUh)%m5Qzwz M^fKWb1SCa *s%1tЯE9'ʔ5SO]D0VՎblJpDx.Sޗ[ Wā>q(˸,ˏxJ"W3,2I'rfxO~AN^hG$! @m`S`ː#< "l:nK,2^(uĈ_REEWś0[.>&a=sOzFd&pR,z;vcdJU-9@P34NS^'1#ɠ!JFw쐱gQhiٹY$ųi="z/D\v8q0wޘnEAGo;Wg%#>.0)O_:+,f`;/?#hDzAp<3%BH3/8G{{2tj@t0F*򖇊_ٝ{tlra0`FVZiQDf}aP}M=xQ?鳭iICi*}M*{%J5"":!M #3I97Ko# ֈ yjo`F k5%D?1l T u!I4ad w1F K@W溄cN"xI - ڤ`b(_t"`mXT5)p&&9wG:x&ep?_1izHi aku|*1z\-[(Ffu꒶sdJ:.7$ &>C6?j䀅3YABT7^}R.ZQ#]\='}C6 AP<uH( uϙ,PDE/IPXD,'/+$+achՑly|c[ٜKpBL@m }#PfG$rX+Hn1JZkaIK1F>>oxL?1\d*kuʑŐ3q;P :afmC# ^[l8*`J>V"ؠՋIؒ OQۓ\4% >SHէ耒($[Bu \+ںsu%{Z+I `X zhW2KI3SgNř^@$MsԀ]YhD%ُ-AEЩ<|AhnhVWq-ʹ6XAmbV]K k-^k4\=+>Fņ˨ݛ~~Ǐ_~fhRBtR+:#B._Ibt('(Qyv1 I _N ) kmwA.FvP"Zf@[w&'7b 8P&@GSm7[IjaۭR;Y2MwxDhЦFL1ډݹBP=ֵvކ}YFd w( EX>QjkٍG 9;j*;l3uؗI2\㑻W(2A8ApӷvHTMwe6]ϒXy܋z7qkTc!NEyNm2[2 <;ȯWEic]Ń)o<Ҙ!fjrrdlͭHv-Pߙ# G+@F:A*o (i: J3HsO锠B/:ĺY0c AŴ@IDAT=NckHj%&iGJ1WFY {`tM\u읡 ȓ b33Df,̥]ySL6n?|g q(+c4mˡO__*Ua7RQ?`PC1k {clB:$zv9!(VuO;d.\>Cۑ%KR K1I+vnE[. \Ow/&*zqw׆yӟ)gyb4R[(B"$" ȧįuX馮T*KlJ3vc]wE\)\jw$>Pq\@M{l@p$ۄ J812:rd.ݖ"Qa=9"' `^eF1:Sr)ΒLĔ[C1B\iSQmYa>!M_:0HSդ$fyvW(e,y&I[Z "(twa,SJ_g4w݂2QEVԠv2ԫ h}Wz l58L(һ;Y%Dwwi#c bnCtұ  hDA!m:%L&8X2CKsXRxg--ͤǠ¢1mbRLO\G:*,\ꁎa;Jdai$IHnwI=Ϩ?TC >Ī[]5MK9)q7:Us`mSrR:8tt!fꤶY)R9F1CQvi"G"0v i}&⭸F ?!>^qfA2VSB[/GQ?~?rfotx!6mU$d}PT-#V$#21WP9P€'J\yr!5<(n&<+bzʤ5~ @9M2 -A^_}kV&9 n#H91#oag&x#y-Ubb]z3#A.ş#V%RHG$߬ȝlY(U8#c ⃬Y uy9>-Y^663g)X$>r;L> dJAaG?tݾFO5+1TμSosg ^{bf- ^sAӮ̜l;A{;lL4~PWh?:Թ8H25p|Fa߰rtL }7Alvo~nd b\*mJR.Hi[W0_Kp L?cQ ̳9`UH:GWWLd 5?Ƃ}#/6F%(sԮEpj%sO>\[mbmj7l&P;~yTryiUÜ6`YNA N [΍ sFhx{ 30ěyaJo.ԍ*mBnb'u*6 `ǽcP ڢOt|oҠjN tفRݒ";Z~D9AibZ㰽\,Z;hXN!9Omn =1M3ЊSj E}ˆA+y@!PTOS&|7ZP0yH*EAZa.Vm<}|UrZ RB+Dg[usp7xǠ+E7s 6'IcmHg"}2%{8*K$BہqSAn%`y8q+W;6|ӊ*^A2͑"~!4=u&0lpb9VT$Q3^̔waDE]U8f+YhY8R_gꡲP@Ir퓱ߟ~~,d{ԽJޭDCbPѠK-ݕq* h7IQ.Gj4/Ϻ~܎2J~#EAd*[ o !HY2qPg"tr{<] Y`\Fzf #ud wIHҖU@!12G>$DEqɪ$IMj&Nr<OOŲMMIAku#䙫RtLI }N@ aWicti@g(9!2'1>"@*YSx^9wc%ܒ1V|օgқ\p½~}^^Q)f#xxX|+Hz吀̾}Ul!ޟ^qA2ÏHӬfڽq#fc$]"DaBWp"P.d iwz߳Pq54 $i`J#$l>~ W]ҟKǙll>1+#*2O+?Wfs%s\Ħ[{"cwpTyh:X_z)i2χW⭘fI'Fk\H ".`' }d$a[RծPƬaCN J䧳k1i 9Sh[k{?cT+NJOڻHZ`_d~gO&Rލm4^'o*v8NcDؤ90w x?7M|:usj L+AtIkozK/(K :J)U}Gl|6c^Ei/o gB1Uz4RT qO= #aU"x!sA 5s0D[Y:fKm0Ir"(!8f8 fgn1?a5UY+#l*tGutT"2ulg1G BQ"dKWEhĸ`zҧ>Mc\JMhT"棦&e52vjQhKl=^Wc4L[3'`Q.ީt0E $rRǹw~Xuؘ".9+`ltY%L Jaآh5\ 83oQ rnAQhX)inUF-˛E~uIUBaF8F^od M}頕"/m#0כk%fn,Ϝr\$EY[X3$ֵ(Ăk&.r̬ے̂1@>c5XDMƕТk/es U >Rk\7V#XG25A|o :S]w%VUiA'D^ weP #ṵxn;\\hf3FGٴDiTsW[ [d /\v QDU]3K$g57lZ.UU }8_Yӗd"IA(AGtha~ݹў/4] 7C}S"rcVlOROz:ގېFOC\YE(M`O"dG9f?a传/4ѹJv}{ej{X%fC1vЋ6`f:˕mcC׎(eHok).%+y(YxALH[s+1Xwz8pVg3q~2T։3,j~1yxqs6f7<zQK;fw * :%g6k)@aYcE @v"\(F uչ6H>qmP28.q UK$Y-@0E!<hu2PitQJq,rjxZVc ztJ# J{m-Mv_w3Ʉ9WR%Uiɯ$Wx 3gB fm!?U D@Ӛ=LFxᴎs\.iL}z7: 67H]mצ^2U 0 %dOt+6 WP9^3R w@Jzj]m\i @.Iqg`g{8,pW}Y<OW`fS >$6 WÚS" /Q8vE1ua@qX90SGB I3aJ[vdc6VYfh4z ry$iAW}djWSŇt"?kо`)4s@%NՏW Hg6wly):-5%}, EFYg:mczYq]"3'hH넌m JҪT/%wx"r^ dQD{U1n4Q>Яc YlԻ+L; HX؇e89CiD(4Yl Jr(8 84͡xv HcP:H`=F/×J P1HH|C]/єJ (Ugi&nL_2L}GZjGɵĄ~RK<}~xȮL"]wd s"[c/_śڢ"Ez^7\;vJ)#ZLIdt`"Vu)#E<-P^}Q0n>ބ@Wa3T!?. LN%&&h ٱCl=kUYF$%&ϟ~e܍6Ϥ6B [brg۝RBKwQ2Æ[&v&+LAHP 0u]]PzkHTlоd\$:cӔܪ$:x0)oRhɓrhdR"V5`GAxu1ZشD$]=COnG~qCs{4kA&H%VinMU|a# a0CgN 㧍9f"hx3Ip%Do$}h4L%U˩ˀېȞa҇0@NMXe,@Im~ i$.crpqC89 `,LrnĺwOo_՚jOǏ3[-ϊaʚ/3i:7f$ޚ,}2f:w~0HنR~G]1̱$@J!C^[k^3D8"&JS=$ $iadWoT-n{aGvjM;/R%ⓤ ?pn̵Y8r2;cl Sd F逡LMb v݃yS r'@܄1uD012!db&m4j1;?F)! TϬ8]<_7 -4k,/BW8\__~7z7hP)ot/7[mYD6%(.54j/Dp:Q`dO0qX>lC4W)<3ƍӬM~ jXle ]BS/Dn|YPZ,gDadh&f`Kdi|Nkz7]~i~xi'" rԁEZ &+)6h˖3V'm!9)4oJ ֘v0>;`p8qRӻIȰ ȤǺ$F1A_-Xl!SR6:P:tqPT~ʶbF EÄO Y7=e/asT^ph|lǏ#buS}Ya=7Biort@ov C KRQ*ӟ =Τ%|*"mU+1wH T8A79}K{u҇! BɺQyQ\P9XdSxRuU/T'|U[@X.P42 p{d`2CCȗF\vCF6{YE(3C:euɱᕦcd8r|^h+ G[1 Єw[9퇻o(>U54ϱzcˬT$!#8XQ%̹t بxOZάIxւRBebdvA9(0_Up;d ([ѥf2sOaWKʂ4䭧rH.ɫ(Fq Ul{:Qz>t  (h|VX]he0$Jz#-lB{a2i^NM];LvgX4+*%W*{P@ɭ d F;y' `{}7R`SLO̲ SI*E `beVϽl'z2Ѳ/6zܭM Ѷ8Slf]C߶‡6V$`4+^2t<Kmvo=~B>犵sd'nFyꁑB9v3DO] 8h/my-(3 Oh 좶z|TMN_E^XJub?<]ʗ]op7- x"O.Ld_^"tt%?SAMC{`lWl\LB@Yf$XJ u ]*7ƓĢ, 맓BI{Y oߞ^~8K]ݹ}kCQ/Cry3L%r,zE`Nv&lcYZ qqU/@W9v r̶}ES6enXB%9UFERj s2I8dB0H$Y"]hEI^$ 龙6?qrW4蒉H3^Sۤ)Xd/ @pΙ_o:?@1Ř,Ux8cm \A?!"WFtQf:y֑Y׃2^6K V&!2/tѹD-±.\Le=rFleB"y …݈HcSMm1D^ƃ~@aRU@KK42el$sŌ$,Y8$Ak\UgP%˚hM9ϝZ=Lҥ3XolJ%١ooxP'/_z:x eDTZd *#8fbK]` aBsF2H83'€ F%M$a!Rrµ8 aߤqQ9Uw=>ETUסd[14Ki1 ԄG2O*m4O3 LԺrpv*ۻǻ/'IfOu[Z![q*0h -`錇@Ona_IdU'$yYt*FTtdbNG?Plr_:`&~55ьqf1U} CKg2FB)B璩+y=gpYiCLɆ6FFs}Ǫ竤^9iAzl['AHX xO &]۫Ŵ̛Dw_#@uagdEWh'Iqb%=ԓ{N #IԻ7_&lAL>2aab , ʕ62̣ądQiMM4!kU4l+Kگeg6_/&aV$%6W9$$`Ҩa,'䁒W734S)ºhS@ۯ343p\K.z(KBp jҽ,ZKr`4(HO2RXZn)XZbumO:$ 4"_Bx?DkLx\eȪ(;.sNΧn:?1uOX+ڕiI8-F&M&y׻鯮KN'ľͦo{קW 7a Kq=aBBQ{#.D)їƣ%0,8*2͘BZW@pǑp?&^Sh%]h'#/vL`ǑܺwUX{P ؍qe:0#*q{?ߪY ձFo D:肥p*QFW:="0+\o[=fO8p.Hkek>V-@BK-*я0ˆeE8IƮ춬nev6΃܇"˵v[Vl].B^Z~v4UYm8p['NI!%jI-2!(򳗈1vIBfC뙄eQjVA P)R3E )'S5%C\,*jT[@E(u"PJ7P#FKuaɭq\O^Rn &5h;SV0 X.VJJ)ݏr|Xtç/Nsu/sqdkD%tíP=fcdX<bҠB@:)7Y"_^>]{*Z;ωπ ()pޔoĤhx %qkNR˾#:uVI2Y']MQb4y0 CWz #eBܲҵτ圐_oHDoa D hD(OiDQ?HÀ]N ӈ% pӗ*7Z Ȝʪځ ぐ)X9a4 HG8Ap4ׯ"UĜ:IlӢ6]~Я\eG \u.Ai9XU+]d@Թ|!rɸMW^wѠEBőt J8˥h 9dl}♕RpzJ H_.lXPfG\$-V/͇YtnXH\$ڨazu>*GiRMW /EU.zLyy 4^J?Q pKޥ47]e{KԽ_ϩV uVepu?*x-ZX+ Q`eܜ; Cq#Kкn߽wG˯xE0V9|#:%"`bjԇ[v2\'_3>&=O qOi H^4ҲV0ɿ~NsHEd]o82 cE.b&bS5R\t:52scoU[ad`a>"otaF4B'-M9Sb/|I/Y.{%M ?T:nO4ؑLF>mHS-RZQN8:4=|ѪK_"؁)*Xq3YD6, G|Nv:lTIE.H;Z';>Q+crɢd DZlrn@ 2#O/t;44f fAT{H&R:)i:kJ&mdL<JXZdLc=x1 |9NC\7L贮{tR:$QELKpTc_e6\N˴efMt$pT׾⯤J2pi_uj(BV_T{Mu}l'*WO[krT{%#̩\9&nRawjü.‚"q ^*)]]RJAN_dfX,N]*VҺzoSz6Id{*ٮ/߯WL]m8 NA2R{|d\*sm]毭;U&vLBhs$LV(:WxJ> [[-jiSLź2ej;B{^Iu>~DKU)LU ڐAeA^z_8adbS㟄34=)MUhBhMw]0/ϓL-j^T8l[j oK mpvM?HV~>C( r ̠6|@pF+%^j^bEaH+9~PRAbTl m]<Mqh$7 c{1t$8#Wtkb'&E.3-% @.Sȧ,Z!(´08JBYbb'3w̓~x 8 T!؛xZH?C=}JFApd;uѻP>YSt95=Z/"Q-ڣ)}ٜ-7p̮=Ƶ #=A ͞ Y"i+Vk(dy:iUu@7am0E)w%YbCt2-<^(m2o›RU`ء8A " cx 8Nd3$4fmD)D'd?0FX$2}O6T>ӕ|S9#3El]9{L"AӾͭe4WɨdvZ1<]ԕ\ qz]^g{~}`7~l@&RZev%ɐhmIEF-LjRRdl򓵔#eq[j NJŬihu›H)b0$}x-|%/(JEݣv`TFjt)O_pa3%L#PdgwcR{l77Tڙ/eoBK\҃GM9;@EW.EO2s|zueBA Vt&w/k;yf{0kC%< ȴX&y3&J^NoH.DicZD" !P bK`%$=-RqZEp"u3ɼ`2tR@8!H]ȁ.;Snr:gn^M& q|@ `E#mG (ײE}d>!${#4U37[/A ~ 9()L㉠A{tw{{sc1_4j䪦 jmMon!G/N88G%ȓ1x|5#8XV|㵖``/% FS!W}Ido S1DP syZv;Vw!6t:fvtH%d`rb`54 9MT?;kD Bv*Mr9v*V`$PYC9qwu/[;Ib`eǒx)K;;^Q9O4ab>NLl?tW<#W;i6xy2WPk9+T.fgub;m ZM>UA_,?h;}˵^1-ɅMZ(Sx!˒KzMc_#jmGX?+VIоB2~24pF=65"'QƾSqAM55d9 !!jHJyc,Fox ),-!^%EbJ9KFSt^4>1PbYZ{,iSgB eRO۷BEګSR+nϐbDmsq}q ,5Fr1 78vYG>y \r3=@OˣM x6n!d:#o#f(C-¿]?c]e1[Nǟ)Q휯 ~d:d4: DO<ݖސ]+LͷƌH" +7vdx:BPI8VMA] g›$)|]tL9^F,7$Trz57b6iyY5yctN+ ̹&j#-ִ͋Rk 8;igXTv:O @{bĖZY1{4$JVawƔbpԑΦ}]HN-3~g>EJnsg5 Sia}NVAvۓ`;OB"lXzИ(Uj1~Kb#b-lCdIlGhU4BisMjIŴҴXdRqφIY W"qC"!vЂ)\nqұ@LK=eH>L)D̫ԦYؠ YW\&na44N9x Ä0;9: בPBmV>'d6 XRI9!`7rNi6!nE2ZOgϦ35%ݞʉ vtJv8xLSJ;^M/jtZ3FOBŪ@j-!lny+Z]"0`C͈8zb ;OV˒*T{q3ӏ& !8Q%.כ*%I5OͧAø ZPyisW°|ɳ19!Y/ABC @!Dy,3q>Ai]JNX:0`dVSU}o7xmA(!%琀ԆV,FľF777(#ŞTtLgf>X{k$'5yo {ERi!˖B}J PJjr0R58F,W֮"JFN r\>qbm}HBpީa:=*rcY/ AR>ysEBHIeށCYK J w-*$/L{IH9 kA^~,|l.b!!`x$NwNQ+W8z-Af#愝STrf#|ыC7 9_]<'U++ XoX{|(.C!tJ6IS,! "{&3 G\bAW!I3W(DhOh_DSXt0R?Aa,Y gvR+-hB E-% +!5r[6j%1/V:)ʥSc7}nB/nߺN8 4c/XH"p0 p ytRĖv:R(zբ.#Uƛg|` EiϟN](TvtTxy>1QCZcAd"wbKd;ЗBt/!?Ծn61*h$  Rg__Y,7LxϋCqmN= m8ēMa^ a6.P 3\~SSd(HvP%JJMC8 "VRiMן"N ϣnGlN`0l<^OOo,UQIwq*ZbIKYGvʊwLR:ĕ{PK<'$u"fxyy3%]6~㏫|N1ay̗P?%&毘B}k/®bbЫ EX(qDkNNlxp 36f͋ JNSlTU!< ȓ|$3 WxyP6e7jNNtt&G Ɇ]bFH~i0[%RTwtQ6C9hxo@h(]T|Di{Z#vME a w?zWg2V|bjT8WRpQob AVoŸ4%+8Ue52&e]a7k⹹jXHώk]Ă5CtER"d\*Ք2T46"QǒAgs>up: 'w82=n G_}2񢏲&[{3(t(| nE+Q>,HDE5B"Bnv)o/R{Z˰=hsfnVdYFC4nNܴ1v؏?`gR`LDOLѬ,3LndI<=iDb9@:sļ!\@>SK^r=y Tpek_@ԚZ҅SqN҈aZ(m;X6RD g9+Rr+y(,QcmN;us5DVI{ 5h3Oa`8v %4}(DIޫFb;eW[9ȍc@+: (Ml(3Nbɶs7UZᬽq%oTVOv?˱ԣ hǸ P.fƙuˢ1\ R{ hIZZhDj3UJ(tQ4')U,bs@ŏ=`ciLldUe97#s?-d/M62rn.ń<2zCHb=15ؼN{Ax@ SL-"0%T<(I2ZS!}!b^- R}v'f*6^dKg֖z!б-g8ئ4q(KB[ ^:f ~KL/ևL<_Mgh.qPr/14rGi[,(-PuEY$%޾~-;m=4MxfQ XNk!)7>!3y ]aaD߆/ ֕[3N]n핊6TL:I^w 4ڣ YmFͪ^(9OOO38^_)2#@`ԗxI=.IH0#煰s!%#Ib7I[y?$!wb1ºTP.b`+)7 U"'t44}"bNnצ͍ 6R8ss8߱nTJjg,g&HD5dXӋ#]w|GF[0hEɈ br:m:Y uZ2pBsM'w;FbW_ Rބ-s[k*[?,BD{&›) \ݎX2s5)yV90 $M4\K%C=0!A qa 0X|è 9tj1oL_>njІgЗes-)J,͞Q8)#&S G5qX@SpwsVNc7r[GEʹjħIcwb,] &jFGN[i+)(8Lv[r˼!Wr GQ HH@;euQVEHcD='n-4NG31s0yzg{׉s}j.Jnb1!{f"DM9#ȈذތP9%8*FI c |ŜK t#OGsXE(!xLԘ ^ovZ;{.͡ ;P#r@5dؑ=~G0M -!U i"s^1K|=d]٧ 6rspc)ήWʯo: Zl2~Y>2%|j',RymZ`]hifK9 7ƌ/PcB C'e?f/X5Zw{ Chl̒q,΄#4OOD d5k ɇ|.H>Zvo!7êp߂̗SsIWqYz+RlLVX!}@O5РiZB1>6C0`DQqZkl0bE*T˳Eݠdc :ͧ]$@[ G)R%%5ңl K`%,tfm5i!y0-A43#Mؙ>8Q-`vBx<R k^BÎu˾{e_V Qd N i背ʽZm2=){SC$H Jb@/O`UdޏO1-ӀORb"-`"-2z}iLCL7_w+=gԓ J$p/QpӠ^Ϟa|]sWӒB H)нRX5V> ۍF˦TM!" u:$6i~tA) 4;D bO_j,yNBiHZi \-Dv"cݤ,*-Ӛ8%ژvd׻N LЮ܀CM5ޅ6QָXOϋ?T\0r\y TR oXm}C^(Z1-- pmO/:NH 4(GeC;I}{D1;64}ҜHZjqM(mDDLӑDdDKJ}P`}7uI˱3\.!+SW/O 6:,@Ђ"ˡJiI/q@XcNE6 uTh܈E"5-*y-)QĔy)Ǵ:طij!: ÇeRē#F"oW V zcc:KѕӜ0^< =8Fdp! d 8FgV'Gk- 33ipY2)U eN/y'Iξ9AzjCۂ8C^h2|.DِsœaF*5K_E9>I&QG3UJ_Io >&E P-eaFB)^H?QW qds-"/sεji)(FfqvWWi'VO Kd.ڼVΞv`Pxe\v؊yx:gɴNpTl q#!@Ъc' :n7RI~f2HBY셕#Ij(FNUg7&K].y>䆀b3=>.8V&wݞNMWyY{A၈Kê4`\訑kv8!`>eԹ*O^=%oIñMDBV 9AFEbI B7Z(%VKokFxusNJEǜ_.bP ގ'*^DXAX|AFH۱E>q>p~+m2aŢVLY!r^69D&qL&Ge`\b(3ɵ $K4F3?}iNLrS=Ni1(ځug>ð, uV5?Hlf$m ̲؞ۛ "C x]$(~!Fq9)YwX1qP9Lծ zP(e|ѥ|mBRX6Egpz=V^~4q@0J? \`lkiLVI =zpڞl$sQU%1- D䇞baD4֧G&V7\D`"f(pGBmJ lB PE[$OL@$YJ1-o>@ ^K݇RO-FPH8}Э@ x!~#9˾r~OOhӤ},*\qԝ⡲DVZt %S2]N '!cO"0cbr ~'xٺ4|7`Be-,Om_tf)=dP:Y<p FMP`"숕zrPB:p*G1G[7I{GVLpr5['e.׎̥ӅYE]΅Qİ{g%JZ.ڹUCSzL[iD`L遀Ĥq{!-ZGa3l}iģbuM3H"a"l'E.~`J9mT(%ݗ0{l^];U@@H#?1Cryq[*wMn"2.` KCy t%?0Gq PER6VzY sq%)&N F;ۦ=ӁD4UĶ<7aܔh.ϟ$##x*$$Ɨ=/Q-^Z $[]]# OEaJ^[=I:vXuٱ0X$Rّc%3e*d1 }wiCy/'6m}|=L\*u|~s&I)@53AgI,Kr)tˆJxAܖfI)[S I,5][EěȰ[JT'ec3 R͝\+QWL\Wv=  |Ar"xYW YcVdON0oh%mc_T 0<=F"xɕSK[s}ziPV&VE:OƘ;ƙhBV߭HSTE}f/ 9tSA SN< R.tsyVPBX 6Ϟop5SDXg0MxL|Pc33G+ӬmY^~{85'wi}\4\۹ŐՔцf,$0  ?&`n}3V,XbLw]H7ň *yk3qlq]=GM@n[=; Nnп v oq,f-:5Bt9,s RYį<05i9p iL~" KQ!MNpǴAIK p.lF BL+oYm0 DjxZ*aat- "C(Uy- {ݬw{=ID.V}qȼ<V|س Y=ްZҁCC w{{cc̊Qi&mE60'UQ䨍It-Њ)3L![עfT-JA=+KZݲfeJvw-±9KR[Ωf ,V/%`hP9E CQg3 !\4Rde:B_FK)o7}l١T #3 OCP)+0!*eSgT3$۷oJ@d#?h ؉R/ `rb5mjae<7&ILjnԃ0\iu UxoտnKyBQR^mH4ظa(VL!1 i=` AG)?c%װ_(Rg'8K L!̋ե ʫ$%n Ҝ]#3OzuRf$XiSDAAs]2kImտzn 4,#`U14>V-+F Lp  ]4&~ߒ}RĪ Է;sa`c(Gmbo,8=R HDJ"dfd5Xۍ-s/Oe(&~.W =1*jB&R^p}Re4P)Өćg)!.RNS+`p18'q)10JSyЫĿ>H YzD"7hd|cXmMb7ZI !H,˟Q;|蘆=:vE)mT {Y|Z B7\)ry 9Ŗ4[ iQ 텬v[CV1ccgd%w?12^!GIcec;V+gBLIҖU}mFf @K1l=Po^h a`4tBcNWv z7d9OOknq0b⛰H2lL~YykqܝtQ⯥Xm9t|H !=迺 5H5vB2Tj_Se*vr09 P)VJ2\ky4Ѫ;i ok'SH"x~&b"btjH`WU@E`-݄MVg2a:EЭS$+HsE*dhY~AzWW9U_'wp&Jd!t,q{ b4?m;s9AAE -wB}E^|g1΀W-2Q*3$B9R-Õ'bQĝí8/ t/^뤯6H+Fjd9)yfKf%|<e`ސ6t>ܴ8Ğh% ̭P7 ܴO:|dL2zza$ ZuĴlW/3f䩧ua|䶥s$9GCUlA nHq&<QFrVk(mJ/Nq_2t`K4Sh[d5@IDAT,j-VE Gb(SfA]]_I&GVB|Gh^/#w;he"O1[`eEP)D&\]rHm X 'b5#. "13y֨2,3GwC'~hx X1\|(2wU=>|WXGHI wR#m|緹N^YGƱ½vsJN~"Rmǩ9=E$|DNļ8 Q'^ 耴ųT 6"ƚ or P 'A Kt Ayo K t Qa2zU2z-l! ȶ^h3 =&cF eE{%6qv+{OGlD3b3HGH u#̛&0SI>rܔ/[,.\!0B /:VM"rүs @:q|;@OI:B+_I0~h.O? n'jv}dfI" ^oI"t.J>ML;".dBv(7.xڀy%64lj\[f1R AVL0~E<>kfe7_1qVaHv.0{iY}lOw7I>CBxcQf WP',pbh7<]o-T Aڙe.X+k g|̖jB~//5fzc?ĉ$K${b ؅/ѭ(QBtq-HE-gF5d*h2&NҲ/3H,vDX9ߴ,?'-2~j\0M/v *3`sYfa˦k8%pJ+\x)]d!F(|]%DN< ^ɋ) ="M&c n Vy(ܙZ9P ߾=or?g"X8 ~~ysm]ο)@ǡSRO܈4*!rĺ&XY Emay@ X[{Q p΂WqAlIYSRS! E5#BՆQF*x%ȳ}|`cDMDGcP֗Y{p`5%HE2mad qp9/J7*kU27s\cb8 Z)R!^ܙ;X=k=mcOà@LdƲأN4tv[B 9X5ttՠъn8Y }K"/V:32>I#4m} 4{!WYVWϣzxn!_97#pGfp1iB!Ս|VD2n+*'am*ioja~|/%e8}1gZmVdI)UIm"s ZOܴ̾ f}%eɋ.Yɪc'Y[~nu |s-rʄ56BHKaQ\T&-}oZ`( ёE%zȀW^LF-OF#cfC8C!7).(V^-⊢\bps[Ɩ62EI``%_~gWXI_7'"XcxE,yP̶(B?e+إȗ$h3q &;MB j-/sL/])aV#5!{aikD,P#Y [LJ}h/?Y)`,AJJ|݂)r6!o[*I1L/Yr(S>t~ܗ CKL5r$J.{~=9׸(+d()9 )WjlbEFU[n;|k㳌E%TZE?b ^v[bG~ƇGqVjpLat_⊎NUBͲX (CI܀ zab3TTaO# }Gz]^Nk&1Zŧ\[rx22CdKdУ&o$Yv^cRz?+~6TVՋG~AkBvҀ}k.bUgUVѶ0_ȧ=A~Edr5څu uLg+3qn.[f_>Bج,|'#4PzLiJ"\)?B wSnHOc3P֙ܮiE eT7O3,(0F{Β^eRR?+g¿m.ϲ,/%|ҪaP;M()CE @%#%Jta$ _Hrbōp(-`RIΚKɧ@?@o#c8]N#ߋ}ہtD p 3ezepVK͡##~kU}e=Oo]b//yA(vEB#<)R,_o{XHssŇz"x<\CJF -(KJkt KSIQڀD@Ql8CjIW[}HW9olGITN2`n?N:}@* -G-;].ah۔Bl"|v9:w~0)\ İ& !pz^x~9gsr_( x TKdgp̜F 50AY!\z:^ ItAn^Xű$<·ղkɏ+u#szl.U qAw3JQ4kkvs_*-G5Oy' TTG$bqTa5J4 cvLBeC ,YKď\_4>`IU-T ݑba8?S5,^Hx֧G[Iq`,K.4[1 tNkr8sb6#<#" nSHJ) sY'#7D(mbU6~[nvŒ*]z A"|T@mOuHEã׏FI3` C`ao.IWo6Kؑ/ϕh=[Wkn+zqg͹ ׽3Og{4ٮ_ࢯR*xZ2Lɸ39S!;lYlӌ o j^vu(vݪvzG2T',5DF(Oe-Hސ&H'7tpd!cT'nh^QI-'"?2(07TE$䐨y,Q@)V-mq¹ e*' xq"+ZFY' Łᢲ,&6@gGH1󘰬|G@Xx-Z13 ΛWQ !>EթK h?x?=W뎢y͍g'b$'5 ]~Rv D;cB9q VkC#%JsBGg2ޜZNW3Bx/g),dLuLtnqfT.C ࡝*Rm9RtHUYv*U2f{!7Q{ BaѨyW>)|Ƚ 57OH`Q'AdŶ=,o,E{wr7W zF_! f ajk#Ѷ.9WT_qzr8ܼ<_=.jU#V)rAo6_%QGi&^.leA<;d;J%ܦxU &;acϠn4-Z3)zID& F3\δ(zg"$k5Ʒ,ʳ@TpZ,!]L}T12;RΓp10Cm\Kke [Uy'5"sNֿ]체'K[삟T:(XXA<KIΥv=Q˔^;_ۯ>1+EgPdef-xֈ27`*@Wg >Y4@5Z»T4,ĩ*8GP' ނ蕃rn >a_,M[m1^hJsbp7> :KPYL7z{ /nMV*cfthgp=D#JnesxTyd櫤?-ˎEM޶p\ָb;cŪE0"]t:wQtu/cfNSBEXWo^=zAF_7sG/Yrz+ pbUl<·vX3$ڭ~籨"ӄ&(F>99+7cDzR$lm^߰hIb'_Gly3O a-!F(X0AHR\mI,}m{9 (¶ΰpՑL ָP mݨ,ى%~6#D2Z*.c[D@L6퇋ճ$kOO1bo+&E0nY^į')|w ;',@ΔS9/'盬R4L\ =N;ia~I!'o%m=-k{n8 c@"õ K7'3t(zx||bRI~S(*D,Ip$`v8k}9t c$ F5ۓyS V z<c񗄧yjHT $ TӶLfJDpt,HQS,(u%%5 $nM_8M׌ J!1^( -ՀY}P)TBͤz:Pm%+I쩤L#d#XՋ%)[ifQ*-Νa 4NPW>Ie p/vU-id\u!OBuHìO,lUa%btԗ?Rd̞(`etJ4-хHA5K &PzD ė ?-f%$hElFg`X- ,P,M`TjLMBZ4qwtf&v~y>Kiae&.e4/ö-ZLАI#?QuD 2$b%yn?؁s T/g@AգQ끯+%&g"+dXnqPCܹbjm}bޱ\7b!-GBknT@~)ﰒ]h݇> o 0B聭DY>ɛPvѿsЗoLM0l.4(FhY)Ȍ޳L0פ$-Z[)LL-%(-AFyr &5Qid ]ZzHi'ק|㝚q-iu[:ӱT3 $HγDa(LG` _em">;+%H[ཧx*nfEdնELͽ<WER>,nГO7h=Q@!F`ϒ8D,Sm=WMbl-="d8kC$]205HS܇fMrM'Ĕ~>ݍ%zЋW'pY7~ʍr`Mq7E/K[uvdT'y OU`G<.)RK'R *Zʥ!cԐsxqhVbPZlYJ$p8ZC XVewY1%ŨNnNF}'VnjD!8 E; R\&Igpj쮏!1Ȁ\m v]t%-6"%8V~'nQN JɓJLʔX Cto2! %hn="Fu6l jL]7u[x{KP"ݙxHRx*gD (?QF ~}@(.j"/qP'$n?3ZRm Q_F9M8mAn=:İɠ#b~#j1 (|y >LzVt 10g}gn6HCboJ%}B "~{HWվnL5 D᱗Bq.[ X_3wsqo)j;{me&<2xzZ˚ќݗTA2f\5 \R, I΃Lӽy{5LAQ$3Kf3߬|\o=Ԇ[8K }nAN[OSgPb!P5 O$ۘ z &dv ޺YxqlVX@]ج(4koM4^[e+k.nn0x4c[P"Q(>fg] 9ʖGfZ\m7LHqLV+o<.~ fF:l "!$9bMpVhAn9U?~Dzt,r<'(a[(EȚp'st)lwŪ$+qx[*BL[Z È(;)ɱFu8bO+`EC}[M񟍴_ٳțmK.{0dG,'"[POt ԛ!1'K CϿ{o0糗N uQIgTq *=|(4 P>g\,EIv`"XS|k0."̿?voNa#q-C ,\ד}{۞n0bvX_/ 7u.+43#wh|;1Z,{v">G=` 0fHAR"ԬPs|*Z@{yUc,bV)Ht@$lOqb emSl{.K8 |yy}d+;% >ZPV'2"ߨ-hi3uɝ*1X^[@tO2 Nsߚ5ӼHweRAY& QDH!/~Fb n9U 9]~Z.K NSK L x@ d"hƌ5l+gO \e0WeA SmO/W@; 1wBx()DJV":~9$,R" [,^T+1FZԈ,y#Lg)iWPVC|F0S;Lɞ_n ^G[R:* ;nŘZHX8kkEoerK!c~ Q eM>QƴtghM2T^LO/KK{eJcN$9HXdxf8tl3dOT]q#&PÌpI50X(o|{^(W%VuZz/< z+\ᅰ4Yj&sOQss!AV篺ykTOr16,K =)oegVuC7Dt~AQAUYydY,2ϻצּ9uS%׼^;Y:B e -n+(!C2$C~Ui0bjs0ND qusspz<:>w-'ҩ*4W>*VS"~c4$/R~li_869)K5DC3XpQJYyՠ,[m T9͊z QodZh[q=Wq;l5Hoؖ~;9t|N7@i LO8L* ”>`z_ny&<xp IRR*)F&av/g^XiSWݍ615@sB3<_\4zu-ÿbiL2_yd,5D6 U9"[o+#/q!j~%@j<EHS ]˛'$= ˰oFh?;y{qO.mjy'CΑ@#þQ+Ω;€6$? ;f*$h<,wsZM:}()*@,D5Ur)D̬@$eއZ״`8 qZ P#E-"8&މf8f3+GËF'tLLbJ 8RnI벚p٦{g#al Q+5Wg׬fR0/o=L%x16mj|p*HX(3QX'wY9/),FM<˩J FHD>~q~e@4n2< ͂ ?ıVoߎgΝOO 'O<4w}@Z{biiIUs~a|m 24C ~KvwD]`jnBK A4INT2.zհ6@S9(gFSQkaRR[J i0 oęm ːP~0ޠD2RR=2DMz.*aِ*{ޝNNѪj 82/9zWrD24{G(L>')>FR@_1So驁cmВ3cOZs oJ |0tj|k_jvbEi%g}Bnt7Ɔ lп*+=FÉ9eS[8:k5eȔ<:5Z<_p@Z9j@#i80Yk#.ah\1$+R$w5V ǟ޾g@ bȂ/F=){NHM|sFyݛ'I ?Qv~Csp1ұ[wʻP*gإ CR7@Wj]i^+d]O@Rc,G>:P.iO[mR{;ŗn,$sd@p&4mh7X1].Ȁ} Ɵen#Lr<=OWNT׺[|`;|Uۤ4gE{df3rtғqu Xj }-q9AۄepyL(ɖ}2Dx{iuOs󅘰D2qx?bML:,܏G e0>KP>x<@ߗ'Ȇ, 0Q>aҤ?_E6%-cr fvIr?) eΦZjt_.UdF\Zp3Ҩw6_/!Q4[(' M/CY{{+ʚV#0,쉰E GP$Dl*:#aٕ1i<)Q'e\,=ɥ+KjBS.@ŝz Ax.v)e<`T:>N4qT^ A?1E}:`nj, dw6:h3±̥`I: ZJų.z- ϗȝKSk>|T +fFOR&|"Cȁ^ׁ)U2Ea`KKLTN` ܢ-rȟAٴ[Cg"ЗL_Ǝ\|8ߴfc4V/_>]=MZ^7/kt UY?.Qx)5çOhѝO{ΏGӷxD.ea9cV'mAS#cx vkY(?KONN3\ ~׃N?%Չ;aid{hkL%s8lbdRM`$AFE KR.>HIjH ͎)tcŲQ "h-pR*c|R㚕eVO&߻f^W⩺XF;Xnᷭ ʮQƶ&SFB_7&&cR7`$?D :%zbm:Qx,߬T&}wZd<6SjqCn*7"وVStwء<`/;cJ8՞SU9 %wuܧ iKQZFo&n쏄#@wV(1Nb*X1 ;ȝ(^øt{@7k|.Zx–Oxv|ibKm~2 >U4lg ]5Y7e6~'y vAt @aٽIM}7;Q7wK!7hך:)VZA{r`]5$%iEy0{-3D9msJЦԤeK0^j颱(J>^]G&4R\pF>>U+: \}R 9Ym@fvI:l*}@v.Eۯ!G $qLZ: 6`*^ӑa).YI!n6C87R;;9!̅[PkUΡL:[6_O([lюGSD;02 33]Q(C=hFّ$L-\Es_kB-lA_Pൟ_#b3Rib4+>|ā/l.-QliD=#"mN! )u=nǟp|>=yk ٻ-gqwd' P,|1 iP J* \=%X' dxdp@dFw|ʺT7 +QQ{ SwjHva"iȲ|4$"$Vl{4>x;̆0l)n:HeJJ|lWG0Jwqv`\=Ba(WlR;^-)`tq%;fTH i)'D?B<@+;T^YS-؛Ô{KrzX$;lFP)b<ўۖ WC>>>BlX(0,(N 1>P„$5u:60wP2nJW4jugÌVZc.|:N2ǪiR6qjRŋpN?ꢴBGB1_gMMX^1>, 򵎥Y\-b՟3RىIEm$PߢwW8cExNDvBHlЗ<*1ſy42ݯ|5qGnRftn杀r(IcSd"PCP`$DG;qcḊ<7T,S]Na_{vrG妱&fͷ*gD)Ij4)m*iR9;-pΎtJlW0VmH4›Y^(~`kY5Mx].LipL{G 550/#vώAun$Dirۧ'Sz7 ߢX-(,ݝӮp|∲w%:q7Slqs"[6&&(Z"蚐{uAYfIHxqϙ"l~C>{@N9**  0CstcV5Ƣ@U2E=^`XA& ibP~5*.YeߥNAE8N u2. ~?f)ԗFw\U׋%k%;꿦+eHFsc8cLUEl *?ۋDaJ4KO,:׬$-5Q,еKo֥Yzvk^08TVc3<1$\)D%QM q,nD0JW񢂬}{?bJ ALm31GeBe|F ٍ Kk I1[q99avS-'7tN opn΂S"ѵqo XlIhRK=c=[5l,\.?JΔu0XwߕM5b&#xIr̎  $}dI'8la[@0re~9N'jS࡬B*-մKػM\M͸SU*sIA4V7H`@04 }JdRG8H,1l'ERCYh\=VS ?aCqW1Ǵ,aZhx * :Ef͜?3I ӒѴ#DomฏAC^@OIf时$`;tم‚ ?]N&;eL=S*'sWV/rp Z!.c6/Di*3i^a(=x'uEU!}k$EP`TaGt D?MU}wʸψQxetfpM #)s Ja(JA,sNC-wn\/Jo*5}FzىgK4J$)׬&(Җ/hOUMӶgpğ9}Kg']'p?#6(4NHXb%v.  .BkiLdcnLw?맏?/ZSVcڽrf\?nq|[HtÈ~-U0;L ]Ml&k&<@#$ ջFEh08Axͧg! Hw{…2INN~4 :'ϗ:E 4\=h$p=íDI>VyT"˴YS㨗Z 26. E4)>@<+# ,# ,Dž$y)Wݺ[[(1S˹JBeOWןU?CtJl|SsrS}[8E[f+qDYh2X*S4(CMtPA<`R#%)L~~gꉥH8S4-}897o{m//b@u'wA=[ks:z\dQGjC-/g Bڣ$4/z?=9{bQYr 6ӷdF9ز;8$8D"|CqEy3 dT~AZ4jnA,q-ܴn|h x.X}x21w>FCFqae ea^Lݵν a %? s[ґbpB8@ I;㉾x<1Ε|l<=>kj1Xf&Ʒ)9@(IOyWNW@`槇؅K#  ⠶W9/S7w97I05&w?OU*9bǓNkx<졄lBv[7WͱYiaDɐùkkX\&DAO!JO6JPMs -aA; ۱ U"n w ^XɚZ2=SHPdF@c`I:QsIbX[C@]h@-7IRH#1ZS';+su+* /zt[noSvE4ayoH2StU4!*Ae9:T] BL#E m$Z0Xг].x"zFeK" 6l`É t7'\0 u~pT$'%-A2we,XQa 4x‰*!N; Lus2Egfɘ ˜˥Ky)hx2߿zEV(N~˅0 H7XdjРMcm >*Zh BlXɍ|;@#Wk1ΆaG9v)q}Y@Pmhp\{1+8dXllcG١ݢT<&J&RR+P9W4Ң,3 NQ!OfžHTM+ 17HS@?ù,ގʑG?P;r-޾ՕhFJU* .6⳹5'GY X!/7X u.K5q7]FY>;:"}"}E\m"JIvjz+?cV4Qr|ɻۓ"Eop<j=X? x\^)Em 48+-o~ IP@/k =A35% GfX;rȒ|tLdʒ>N?H#oU^U'tAmaNaX[/JMii c7) /')wOo(́VHksƤIq@(א!ۗc0(%H]dLʹC) M×-KlpA{)W&4q{'2>fDdM9EgbBݳV拈uJ1}eh*g|鯴u[3^"%VmdyMga+Hh1ל9XelΞBo{a[!rw:`ʦp[w>[J^ؑCaE.)6qSBHyN=Ch$̰K#sǟhOFxn5y_ܭ7嗯ÿ_5\FΌƦ Y5yqݿO'ӏ?c_6_y~HZ#8 Sq˂%ͣ)?r<|!_;\89Q7YpNzyW3fdoLf@嵌?gҴmtdS-'lN̠v8.I%)7L3{w =҄i@%U`?0WGὙ`&$%Gh͊>"X!ˆS;a !iա1+ *yso%b(*h~J m2AP\.$o%otpa#Ą$>UǓI+†83;6$ ʓ2,h{;a<wnQT2ĞG -oֶ?#_8*ÈObRt$K1E HʍCFo,&R~K:d(ǽ4bX;5 "ϔ['QH*-9Z29?e> " A@fKyBs?e"]h[O~MI"~h $kJֈ ! 4ArCM j@3<$$Mbrjq&q]r75)s)^/j-I$׷oHD1?cxN/0WPwEh,`fd7Qaw {:Níj펲c fv)(`ҡ:G.TƲ_]FjHb_k|EDJtpc^gyCk@r~.s$Y"F Ԟ)7htO<kAK1Eh)WKN\ܦQ#!rc>>A%5grs8C w)/hi-Q|_ D0 5Ҫʌ!Gu ;{brrV!N0 x0iZ1 D6X0*e&ޕTsmagd Fh8l:*!8IlT>U gl) 8WIpZ2Yj_Hn.2ڊ5yi3a6^V;:-hl8y3ʰr<Z1:'aS +ěP?R,\.e/+#6[~, MKb6T(! '/a/qlaҝp?GQ Ο֗DK$ m3G)\}]"F!nqwl!]Sp`H(*Rh G!+g8EqǷo+aO9@k(.J_bXkp$/Q汈q~uu싫Af@!C#`>5 SLmMO1*y٩<inag,yZĎ!&MU(Ș h-=| b4Y# rע'n\ bmJ\իд\fӬ {CC?|M~CzMk[ /$Z{0 l SF1| ϼ4Yxbh33-m("W$֌OIC;"|3nwYXc^3o2Ӂũj6Ei Q .K&£LB ČP 67HR}vp.%ԅ?(ÆRfA Dz5~7 TдXEU3.t f眔Rmm9h掎#~p~ ɉ  Va22u{r~]<3hN/*6?(e҄xRm<,.A'QUόq:є`ydf7s N}'7,(BAfVW?D/Ű99sg0X"1ݻ_@>Y_zrǏNl^3i|x:ֻ>[}Jc gt̷4-_7˘?`>)ô=w{24  EPщ7h^_`Rcn˻Z)Ĕ3xpX(G 3PkB\m^APs<Z0U"]l,@a h*0O4j/6!o9W;ϰ+#Qۧ  mԣ>.1%sDDFf>tc` `eaa 4\XV#)e?H6coJ~„)"KOKM1 Ce):?+;+{-ߵ˱cK ;߉o}XP\ :dϸh3M05+qH|QБ#z1eH3Q#QeULNv{} wsibh`h,l4KNLLF/yWPׯN yBJ*Hʒ% p]ypUïeBipRKdyvV";iILw*Oy-e9"r#o>N?L'gtvCK~ZE4ՠ}ٳ\Z,FX*4)eSp?w6bӔ}]4 g8=jM2ےuߐ $Kgss$zMERV ~C1P|2[$g0Cwp~؊Lx|1Y8!.Mlbq׽EG l*y;MҀy!?O7ʳ\VɋArgxjddPsÔICbġ6Q}k=BV$ Nrg4m1֐ `& x{$SǺaK(P>o)~S)R'cA$f:_gwRYk591&w7$@ۖ*z==Oz>)-m$+|0Ʉ^Кd;s\߶yka&|&1@JƤᑋ\|Jqػ @ W fzC2UUpx~DZJ !A \Fj-S1zy0fhXMS54xlۈ8x"s/10FtK1!Fm<[a}j xbi4(ϦW-wӄ?k0#M1HF5vǗQG-LIV6aإᴁi)Np5ܡVJ cԛtҤ G|[~ćёUe; W;c\Y5M1G=K95;cQˇrS q?J|E)V,G1V09{# \{C\-O7חHugUm^D˘85HeQfrJ\Ib RMq+jr:X{}Pxòu5Tek͔ =hFfnU5n-i\7Af[K62P6nIwo`-FcO[}&llT ?2< +dRoeL$=,ٙtsچ4Si4Y ;Q+c2%. 2)NfSr$Wx\)ؔLV m4+-GG\v<dzaN@+ѱ}o# >*#Kߋ-oaF.Ue#W@/ۻTM:#${A7 dm+-I2<ޚ?.C"Oɕk.5TB\\#F& >X_`m BZ 07D)Q養!/&&W^EጅzYf/2U+7aoqa7`ub OPXbTHO%DQy+Py)Hٱ.bиDN43^-X>G~ɤJ"{xAxVjXS8  kJvBP>sXaшSIdcCvLf`WsO8@Q:4;^[&f7Tk"LR2/Cl L͐Lߒeqbn 21 ֯?#2LgJ$ 1p)ȉD [YjPKWatμz_kL"%d3k%N6O6g0AwgR( +?:/4`%Upr^S+\EU4FKT0Z#QvoJ۷`z#b@ 9.xVTCWBFhr.9xda Nq0l.v4Hkb&J K3PܓUs"KS\shҐ+H2S9A: X?QONF?CD9e}$P>fIE ސL 7#&a Sbe47ЃFL0>4ŒckRQHļ[˫fp`A\QeD.O#U=~!{dD ?m5LAp)8H uu) Hm`x@+., 'stFᠱlhy{@@027RЃ#*8l12jR2&Ei;LJh=ĎRH<*6rNO?﮿a9=\].\ -ca],\]@>V (Ie)L ,B*x&Jyz\fLa@h-.]hzC@[Y׊1Qwkp #{@q{a(Lf>;o:Pz+?o=r:(ɩU_.o.@Hed6)4tCUj&VM-]@t~C0Y។#Nb[BM$FiRi33svT3(iQ!T~yX;&p&3;vjafyGe-Äy'l*ulbQh8N%7fڬpBL,Y':Lܺœ7pB5}֍i@~rC.NukDYuHEiz6V^IG$ Dij`OT:F0l$19xШ},;G/MENz 2I#"VCw+d,qswv)OOOۙct+}\ F13HKM\v†eR@# c"T4εe?3E#F|\ht1kBtF ꥡ MoR>qh6 U50x>~ΙH@n=tr!/ad1NUXJ%qq9Mka6uHGG5lQ8!tED UZZ P|w8qfZ#}CleB%3֢C Kp64hդY :m2o _ _szJrTp(\|3*LS!|_,l )Κ#MkwGewbl(]?F7yY TTlX % УBDf!Lh|ct?;R3v(.Ŵb%KÛC`NAlW.LЫ$QxQSlG GEBKksd*J]?ݺ]:PERy,fKPemk0}N *mLa7'k"06ʛ;B^^&|9lgU8ų@OcbMYwD1/W$.OiбyK^XP1H=O 09Քa4,g+E"~-w޹UfO!i ~y kT+4bB{& RD1f~? aHaZƶtKCn:lwZċX[#^7%`Փi9ZIK&%%X-f-HyJD6Mʯp?(.@\CDe>i280UW[I2 lJ,ĔO)oI6?7!h+c)?Kh UڑuZd2qFb'sd55$1?t\6L$Y\ꓴ;08PqLɫ95M;,Ӯ/vz遭"ϩrG]r ?^]v2p$ 9O1@3fbp hPX-.p~~M/5N+1NePcaRQS );vgӗ'մ`n:#W6Cpn^).ɿdZ;1~R ӵi-._pxҍL8KΛf,+x!D 0`$RgQ0cy8s x\M/8>fRC~_&C?s1D:H|k[i" Pe(ar8s)gZ_8?SB  =IeZQ} 4!{`NÆ;%tDc ꊳֲaU^kPv?֫E Yz:ٱ\{.,_X-)UI[X?ju:M#Xd'YwArvОj(dp W^Z|h•mC`B-fv -!MDt A{D#DYn"L_4s)(`l" E|>6@t8&NUT5`]'`T*}ri .ͷݑ8їb4^P);nxh׳DiװQ/a`]_rap7Ho8%x#Ȟrg̱ȫ:7IЈOr$bq !3]\AjED(({vgOMݝ3ɰ+g1e ?K͓M>, 0|Č05 Ӆq ezdSwԨDHY@X Ѹ~2pqA|3,FUqba(xݪ?)!Q9L&wS1qGA> )j&3#.eK#= gKfe2 =~j?GGx*fWA;,;Vys(3vr"Z>K~Dِ$#h,}DZ3Jc#Y~lDBuA1_L@zDrpuXBM׫f O୐7iӠ^kӧ ˚\f\2Ƶh`MyiЧ3ެTs+oĩ*lF>,ngl39JQ=%!þ"s 3Ξ]J:墵'uP<"μ;: %/=/S; @spMm`cq+j铁³RMzm"!1k ̨8$JcapmYґ1b֦ⶈY>tm'o7 p-1<KvCCq`z)o 4zUX%Ec!˗~5]j0[QWbxiVSZ^lPSL}!lKL8#`ECB%.yhHFdא"Q,hG˦|gN^L`HR;@3".^eOdQ'2\A*c (RbMht{9 {]Of%oA4XSdS/~[R"AH>QKw'Mڅ 9N19ū@kZht8x&@ "J4~eT +bCV+eov0ܬL>XO2bt t&dUz#2$P۞M}}u-fu󱝂ZDhy$璋hGjNXHTG)Mh~Z*CW"}++e]n Rm#ĕՖ] _Zg7Tf㴖= g,ILj v?(Ϥ~tWr6# '$B"-BE4h?Pn9s^~7QL|id6GUJbWT`]4l8MC@Fv:97ay#Ξ2Ap:_`8 |1[(9ߤ0~56OU9kcup=}I=+, c+.$\p8EIRǢq_ALRެn f (N9C(r~]Nk~~y(Nuθ-psD*^TAw\i},3R_~P8e+^Rw_U;[M a|GCI@b+vX6]v+Q(aV̾ѻ7J*4F>ɮ>Jni Ԁd/HtDY.I){hec 袶WCۀȹ#}2Г$KJV4g!,Uf9SZN̢oBe8!prTG.cS)Nu ?vB}X@ŁC>,Nuڶ'<`&, OcfJFg]ߺ\C,Bv3k؂@;:YkGSжj ڡd['=Ch{U^0IlvN2f9:V} %׺fgỎ/z;(}ã(3Kv֙E(ƀaZ*erPSo4" |ܶ]}aE ž =hh-h;g¤hK+?2l De8bD&uܬ"2OF`\3|WBu!E/zJiJMkħ ƨ#>:t(-*CYʝpK=z>HRۭ4A UH(%dn# :g0h |)*sTK9ηֹHA Mm>J aaJKo{)z˅{'puoM|z*0hӞLOP%w%, [6.CYyja o ^dor _:pAySBI qA\4qG{? |ȼn+G-.Pqc3|=jjM}àFnXKB{UA=50 /GDyqr N Var˱RD /F#Qڇ Hj e@b0= aڨ 27zœ_K|V[V}l2\nri(:UE75hJ -`OZsM7ͧ\ O 6>\5b(>}EZG9=sJӻMB>и=MOYEtIo^=4 lòqT|>Y 57N2 rj^]r8,6jte'L +`J$[a}ws?q`"R:=k:c/E{dr) D™U*@[8Mw\ |`!jF{ f6 hR%^-w @M :;OwwWKag*Cj@M Y+5xH_kR.\g1X9ޖ_:(*>f {4S/vSǝÿ^/J Jyek[ ^SP%9hҘ-ˌ`/oB軡/цN=mΤ AG}Gtq;Djvs{QN?أ*!A2:!dD\g/'w8rReB!Jh7޷c-\ ~Jl|ST1Ď0! )kxe".V،r4śf7?-R2ŋ>2@v:2g .P3KDž&T6* ՌA}w{ma mD@x<%\M.G.,FsiA &Pl ȓ#^ 4r@Zxvb2OsDZ,6\N`s-;T3EjG!{p[f=9N!2Thgr!HWhSyai~a!N#\` 8ыb#"t-&.\ $)W*@WCІS9Ω᭰eK g ևo&Spykb?S(Ja;FԶ]#x^{ʅd,.kDzRI@ D#Fi`b'5AB'd9I&{[HLD82>MwI\ Vv"?~1 p(2"vd7e2vvtOP &S@0$.l3=\NĒdWqrmJ"+~deX4r=59Hέt#8ɍyYD^ }t~,`&.>$pT<B* LGfhu͘o IX\}$(P%u66u- ޮ wNˌϟ)?q ZLOp4*>&a*r}5"*K1l!ψ$$^XA`BQ MUW6Cg N8wɈ' N=GdجllXϘT[^ 4*цyҨ@&YpjaVDԾYaqxy9,%Gh8x` -7_X.NA'Αeׅjui:ᒇKQ}34U y[2n,n))rHDe(=8%1w_a{'7E|ꭷz$)=M`8@PQ%lvNR1F4$༺ú' ӞlAā*@FKdWt!~0NynV0b0ꎧ5XZzN&EZOLo܄/4ɻN|sN xݥ5YDыt>TE$J{z*Kwh}O,ILf2;wRH hf}陆ƩՅ'.geC2-'Edc!bJz#rDzc.pGkHG4uЫ ۊԄiZsz~꥝8[o{.`1LtpxZ*y h؇Շ9fmT OEkVrR*@ |Fp)9HwN'G[tm):2ixpjV ],#NJ@Ou!Qr\8;J7<FAtk -`NP2 є6 Y$^`.Xq<鉫ekJ7&ԎIn~1w e0*a^{nLpҽ #j`K 9ZIk?h;T`F9@4p3g ʌ6ӣ(ߞ;H7b,su?k),@UUDo".4 ڼte8ɫ0?}$X^ !CI%cBLcy'x",U6C[_O@5ľH?Q71|`єqNme Qz1JKhs,@8XwMۀJy㻯"@X$R͝FRbpG%þ g4^zKø фc kPEt1< *K9z~} ac\>raIx*'X 烿Wdt^$Ef!ӌJPso$r^ ]N;0#(xTy)!QjveĖFXh ưl&#_Z'Hbw2 mE'{J41_G;]_0u&!ՠbȂ%~z8kR"xekCR8rE/Z*eb鸧kSAE!xd`3PK.,5AJ) 1F̸P?%<;ӄP&CPӦq9ލngP[MBɓk Ryp-W5P^*GbϲCWZ; x83(hi%[0Zd4^FKJx8P_1ӭ4cjW'B7.쎇Ef6M* >/£H qk`uk(Tc`w|{Q$*7:<ѽ,rU“:F1)D-+#s$+b*b?Zpo-8",Ny@)p`c?V7WYo3#9RfMci]G /X ^b# }5[1])4%9{,C.;s[uCڿVDZSnz'@$}ؽɔ_uKmFғp DUa$DAb[v=n $r|E>f =ٕqxW:R>ZWFljh ^>t;/FEЮ*l51\~rrx˫$Vy j7HX.OջdKS%S~ͽ|*IȸYոn5yXcZԥ&=+4:1c B\D0[φݔ)-s1b/ *C n~j[yI Ȝ8lEɰ ILטT烤|@dc~b8ag7Nv:9ǽVY/eū Ŏ? r#,A?X9m5^ذ~92$?#|)gSg }ѯqrGaLnC+lw +J_ȉ2:  <$q?ZŁR lb PSIEKi`F(%8ZȆc,x#wG9` z-n<${G.&KbX8~{pyt-gI mgW1Dd2…4\rvKJ1EkQɄ'1'S/;Mi#s$>dCV)66cszY3~6W6ԭ$B7e„Eg6,͓_Fz]4DgF[zX G٣8`5 ~0qzlυI]EJ3,#@K#՞Ne8ixR֫ LFň"P*JN_2$o6lJ*̟Ze2" $ߡ! s F*kZF1]ḙjBZ1N48(>ÊKJ"6\m]zJ0aHn pw -0¥s]oeT|S⊚|!@ʟ_s,Ѭrcn2x3%|ՕkXz$sIIc!7klW9/$d9e%,*&WN zT-.<Ǚ' [q"^ ޡR9oEBw6^@$9,ЄheєJG e Euy\Pݬ ہ|d32NM򱆿""YCˎE,YTE6 )u6!Mww `Vr%Sc{o*i)) + ;ԙ™#)8;XPdPgTs='Ў-s?{z~VČVþV&|M SgXFpMJdB-4_o9?tkx\QQyS-#CL4H$*I, ! w` ,ck|P?Q{Rgץr.u~ dNo7|ҷ3o|ʸL"M O|"gGIݖi\b J>@} 7NJA,D=2' ֫?0 UHb#BԚ &>`3j sl?orlr$^Yn}'5ollXm$(ZOXLV?a4eI,ڊa|_&D%pKCr0֛⤌5cG!^4p(# N%dHމIɆ2x"/K(Fxu9-. t\~dC- OWq8$I`SjǺC ty F0 fa9J,_IVOKo8e?KR S /g*jK 2VGU =h/?vYfӑX,Vق`|6 B±qْ?Mcnɭf@0(/[AK e[D&jtlP{7)ג ap7||(Ӑɛs6֩r+-̓^1mBgwW6Gm D.;~B\Hҳ(jv(^g-*N,;=QA"]%ɤ[qp8}Fw ޛ}SA<5ZTE xtv}ijD)$ΰdѦ58#选OԌ(7v]^>A+,qGHz(wlΒSH,'(iALf5s!d$oo22ۤi~_8 d)Vd?jV\r㌓wvDQ,Jx X&juad% q$/%xLpx`yqja$D&BUFr+W􇯟gquVo OܱK7/9oJ|>idR.0rgj[G0@´ê%ϲuvi 4g`ƾ.aj G Td|Ug#ZBtgWMrcĖ*%dľD @q䱬9Dψ z"Y8Ā7}J17f ;7kG0 #Қ G)E*sPR#{9ipMM$y{ء?+|@-26S0}Σ*u[3g[/`>{$f0{^%\j7{Q|y<<<ۍgXO1},}ZyT#;ۭ5h8/Wɨmޢ* M,1Rݙ\`PbDm͜jGK:JDO/B5<g)`ѕaH)PWEZxxՃ[,wn'l$] ȋډJl>_dw "7\%ƚp71 xF[Տ.:=uƘ-ş(ߣ)ĉJB2dP0X$ϖl~M/F];wǩi3`u~/|'K͇l$xcXe:vg"F[cG Uq3H|cq"n^_Ѵ#JVR A^(. IJE JDĐw( ׫$c Xܫxd0 6Vb2M8סX{qGQ=KD~F%NBiΔx+_Mk` 2ń{TYp |kw &Pt{:[ ֦4ɂQU+AgG[V|FS  5Xz#G̐ )7#tpe@SeyNjF2N:&@ ƒ rі i q'pSE>g"Iś0_]:\l$4r++gZ5ʥO{)8(~GQo0{&Pܟ5NBsf3w$G*86k5<ђRӻ2*V">Qm<od0>d`{JѺ&F)N<cN!HFuGl~myhOXV$qV"P—0w“+~b<ӂ2OknSX~~D+o:9b:˶CiƖfEub?Om=uQ-ׂs&WBQ%٨։wyYM"gdl,qE*+T JRSIJU+F5k'jс m(DS ~R@VCެkŢ31fBL:S[z7rWJ@9UX=ϳ%".YwFS\٫|^{~ 뛯Jpk.2aeʥ5dbz5 )E b&c ?P3+d pMПE]sXix[lA"<.XV,DnkBzT"Az(D\Q==X-7 P֓\pD 5&MN^kwGq7)+,+"C+WbpL0Е"&~lxk`=F|8O2p5+PIpbW@9}ߺEю9JI:TkOHc ƂdP XI͠Rl ^FdF[y >nks+V<&pysIpe[şc(76/ف 0]4sA¥X&@9 ԠWwR|Is{EꎢlCG6h,3&kŐ9 i! uHD|@v$LtXJ<}dօb+TX\]Sg}j %2%zqrˢSCY b{e ~Ǚإ\8UbU>%305;o "BWCg~wX)]6F㌩Ԯd WBL1f5#O$<>+W<ĸoDj$EM0(LVľJWCSl-'H_scc7o63zY,`BQaSJwԄ ɎT~~lQ!bxpF|-  6n txXv_9KEɴi֦Eѧ1՛sޏVZ- fNO*TNgoWu0 1PaA!^V.F#R.&-掝[r߂gf-aBѐypl!䨫^Q1ycA<^[ї_ӡ 8L6is U۞9?[A^1? Q0oC _SB7N6{ORxHݖ Eia9;Ec;4{i Un"Goj,).HZ=5'($n\Auj@IDAT@LE!f EO^{j~0쥻k, FD ,], %xA*a2yBDT EX ӛSP)*G)b8 xvȤ>0@ie옢Y26x!IܿpjF}b- G[S{6:n;E櫭͚\qLc7r~}E&p%Du2ha9L*5oՖp >e ^. W:YCC^Q 7 L4>R~@N"pސDX֑cjj?/֟thQtyK'ӫA@˜$ǀ@-~$Q7/d4\:Z[MϦ+ݔNگW䵄|K+=T6!D1uAkY<*j:v3LBKѠ NʬǪ :V $tjx^ h^a(q aث0$%JaQA5GucFĻ"f9wÇwW\ޱ%AQGUNWpr1;u'Q3f.!ԕDn|a- ΄ҧ%zY ˨Ι>KD8S9w=NۗkW|2BX>pb<%68V0 1,Uј/WOzvǎ9|`c9O}?0r<Œ&nmKPWI8 k_$꒫ c'شg;㽍C,4 TQ--"Luh `f< 7tz-AX$^ߠ2MKPI䍏<5(d),fV l-!ytd0Yiǂ6R' \ YDCb3|4iҤUH;Z-~<PLY,T6YfP^h>Vo>^XnOUN栄LF AΐӺNQ ]^dFR@[VbE^2FS VOZz#d]@<#Hu`ߏP2 Kcnr9Q=Y5]}x P9'ńqyN{j/693MwTΧmv۷=÷o/|2vv@:ъ̪%pe<$O&}Sf=אObc|]^ԩEg}y 5eڧ$VH \` SXI߰2H[xuۊҔc1xR  Bd S¨L1:f+(ۊ橥2dWW?Kʴ84*)H(Ej'jnGb^@ D{â'R}xI-t⚐+gϞ6N_(+e FۧbK!ED띡(QY3]ln kG>e!]gjt29WÛ. !N x)m<-A3o t 2ėA6MF?!G}6%+Aiw(X<ܤ  fFK1X($?XMz_](خ ew&/.3Jb3Mlh; "rc•[I1r)t0D, 0s@&[nm{>7\ u1[$A1A $'Evd+]I.V+ڕcfajlq t~uP\%- ft TGPA0> 9M(޿B&)a$Rf W^V?װ(F+GDB SLU%5QmJ8~f=zDVu䛓+4)&WU\D$uA[ ;c!pQ@8<'f%@UI hI9!F#Kډ4a!X#hq1)blh(jT2FUʇvY%ˍ,-7}pOї~w8yО*8? ڬޅk UDH-?oūD';f,DxH\;F<76GUz{qbSSQ(T{T[w Xq/_PQ9X'*xs-A&巒 ?cfa.FD}Sx"mvR?ksZq;)B4 Kf9ٕf4X41v,  Hl!fJWtFpp=ZR+,۝gN#j*`T<(]BU+g_,o:"  6,{"2hzc^55 č}&ENWR4zHeŔOT HܢD$3/ /ƿWN=GtAV ,6SVj[6>%^R+>Y4q'K{L㮅`U{j!^]啎#TSN$%39cH'OǑR֘OJi Chq@90жHu񌙮?z@N ;e1W,Pu,tjdj>T/-Skl'윲,d^xaXL,gH%9O10;OΞQɧTW4u1XqwK4i[:&'A+yumUq0v|,#H #PHP3SPD<sţ,S*B:MG (}O<$XBg+|H_2d36ڒ˅atNgR+{Xت˖7>}bfvA;U|aS9Bd1Si𥅂]2UGO<T5٨~N3bh~SuNQ'th2eJe'JE:P=FX#4 fmI@BU>d Xm jZ,IjMnV-Η'GۇJ+!$3%+>Shvi eQ]Jʖ'(YkZԙ5 *"Mu%Jޠ]3m)neD%m9IG+1s]}8Â],^d; +2qꤩp6M52 O }[?7`Nh֐!*&B2dvKlLFP2%zb@_y:vgk[] fnX,Z~ ԤOMJIW[HJݕ㾱3OWMD۵%GA*m&zBiJlOogA[ W1p=7aƜ~d0.Q[wȢ L%Fd?o^aq__ʙ}ɤRuaKA,tACt`vN2 b0"#àZK$+|pS>/Bgs(0an=rLg#Ik Gkڼ)@HVT# WZwU]T(J0(ew#LC! Z:zNh1~g{$SmQ?=0(/.p!aO֞!t)Įc-5oʝUQBw0ݢ2RDظMKY%Ҁ3U^D!N b*=CԵaӔ1( -ALG`$lIMO$HkCF~Y('̂ uj(!"nF]<1]`197p4a@zmYȌu0e>:TTtjc 5ĴD0Ћ5wa(E@w xAQaȘh0[J(P¹P0Ϥv~s'oTڵ$ ARdLLx#"ALiռ|z5v cKo.YrX;lԂas*0de jֺ1Z~A%T>Hݤ۫{q|t#P-Kp@Ćx,!TvS G 5D]K!`ҴfZ'IrnUsik ;be `Vs %k7m(=.#6huv_Ti;3҂Uyo_ȯx]Ҫxw t;0*IiU%aBLOBYGGîxh)%-9)tox4PC*:q܂sE=J+ZXYQh};%R C56->2߳;wҵ$*O}N 5/"T$(s<[h5YqZېBb'QIĒR|<R֊`hYwԛXxJK)#* J-B{4u'_A oF]1oFሾn^jK8P1 "?WNӢgɰgVK;po191 j kB8 U!L]s\~?n[R &65"3Rv`ttX>9Fn*"|P8gB %i ,9mh#wM!2`ET?yÄfQ[>vZH*/i/b+zJ(JуO\NT9*R2]J'd}\!J0`YRZ3J"cLyG)gc5r.; $^k`/7("{hQv6P uwdpfGi *; $t' wxvfN^'6 jV~}r>eB J*xsQwAX!Y1ҽ#ǏUfx|ʸ/^`m6^Jdi=ܫ{óɘS.DbM5W2$h ڂYʊU,- o3VE"nNXJmqw{R<2ԕLjZ&,XPL(qMfdx58J_<)M"B98̌̋qtIe. lKT=qjlF\@b.8[LIQGD2+:eHȃEqQz Iz>9,W w8 ^L꿇\JZ#O[`o $\@#*kA M}jn@Q{% |LxLT .>}snK 8n&$(˩,6LrLAӗmP!l 8@y҂C!&Ɏ|%!J@܄{c<˼ ?O+ JT\MJ 'M.fJT#ġ|j)1 NGCM)ɑ⍚/AK!n EUD8%DKL!K71\ָa{l:d"B ANW8I1=yk姂aAy*OC[p3pe[3M FZ a8I<HwTYLJ 4L[E\ƀR\!ƀ'gPO$Io݄tS]yp R',d0m4m)D+e˫9uB~ELMpЬ6\=/}H;xKR#|^v>Aށ`E{c%Wݲ 4,Rq؄lܺ`;Uo8BfaY-dsix!*{>щ)$hg| ,_h%Ȱ\OI"4әr7h-Oz$$ #`⻏L) =)@4ֲ.raf/1wmvgl^"3e!h˴2T - egQ8rt f]MOjwO<?ZvG֯ *1TP<=5tDFRih|+j8.Atпy~. 7]ɺcJ0_S@?W8v_]n덢ņ'8ªH_e,!$1abI27PԵ)7iC]^ni&ӚK g7ہx×}cTЮuZoz~cؔٳҩtk11[~'mɐt< 7'CD A ޝK6ɖhjsd$F *tjϘl))c{ɓd><`tTp~ah)J#і>nw΄Q"!"˽E+X !8s_\ȉώ"Fr-0F?1?꘲P:31чQQJE\lv7ps@;$˒2X#uGmOlR8B-_]?X3ƁY~T-i_ adm\Vvlʪ_ Y y z UD' Sr77Qiֱ֚ %HAޛQpTHEݐ/ to2NjZ|\K;*x nћ)t܇0.p wT'hi0>?q$Y rE =!C)Y.(7H?! ԅ<ncBKRug_)dzҭ qAڒ+hWĈl8S? Җ̟. TzA;i!.5kP];]nNr/LFz=/?]D{lL5- 9B<]X^7>cC?gEV5@ʯH5p]7˾?F33j%ryPC㭸6_T=6⁔T,LGYvW}Xlz~q>&TS)5R25bjI+{](b'#;v9@\0oH\c,VԌ!^7ioH 9[z䂋FRO3nǁx/U's?_>, l>Sp<'x"؈{٣-y؜ܽ;;fEbn;>դڂt' V%2]Z6}H٤,9}y{;|"zTpF4͌)B ញbxyDXqJkRX Xz+E㝳jxcyɃ,uͲ+roW/,N~_.Ue':D>nۘ0{np8 bƂZxϒ&\dtGGoJ,CaҢh0:ŒNJB#"X3b ixK!؊Mp)Mj@솿ϿAU.d%G9Pj=WNz3IVq| 8$B4ѡ8"[hDUkM-:y= 7$E$'8fhu)FZdDɓA (/Nq-͓![Zl\ڒlITNhi<[=?r>j&:1~EeT@ {Jk'/!{5I!ASXQ(_jbPM0! S>u'}I[JLu^%MS^!%rNOW`+?i5%1(8iY2dI1J,%B^Gc*r  ypP"&(4~5zk`r%Qc} \A)17_4S$lt{aR% Vzk$t?|IXRd/!0Gݛ-D= az\~GBOlg ˻J}d'8:Üg .m DceYP%o I-- E;٘~"_Iz%p%*4ON/6x8fUV!{8΀*$da%.'[8ؒ7H0K ϣ1'gnIlZ5Rd1DZeͅI}|J/iIP>-bi/]:iQDlL[Lۙ₱3jxYzZ8j619-(r3 Q~P-i$ՠ!2xՉ'NjW,%> ۇK~ѦokYSbzb2,ld#~}?٥"{5k '\f}WWkQHS#&QU\腹' / :^}N2+v2h_SbRn݅DĤ<}^|5 4 4`X):L|o=?VD/!E8f ,ջ0 8Z2heh[ ̮|ZHG;'QuC!R_8A{0q;`ɝ']p4w^nR:%$ӝE,FnBqЂ:l 鰥[}OHaHrc*`w|vdL M7٠tToI'&{iR{Y<̮?w춉Qٹ>;Z~jPNVή[[O63-NzP6A'80I|X` 9vԄݍEnHx5p4'!.z;.`Sx AUy!eB+r&C'Zh_zbɜ抄FM&+b!Po84 /'+ߣ:X%PkXwo D)̐y#?aouFU`+mD}逈җ"3< A{ Lp(m 1g: ^DULȒ}*@A1K_ƿ 'RXer8o?/$? IWŴutvUǰN{m0ˋ=Gu-L:1HeO ȇ 0T` $*E5%sIY9-cBYD D]kr[mո0Q1i CKJCvD*!94O.2aIf Z?8G ?(3bDam/q'LB 2}"upγ `"my/'h{x$0HLK7nĘaF!?Z>=pD͊@E7λ zekOx$-?NYW .7XFh.63)٦+JIUl?$ԋR(ג;  @~) Eѭ+S(D0bVb:,f7{Bl܂=SɊa0"p \9 sqr$A̖򧃢Tَ#2fԶHhb_n9w9,8 8%|G!P)ǘOʊq Vf׍=%&tWiHY ^)THX/لOFͪ`Lykp8>D7ia ŷȮ#:w̗4Z* _dX)2H8=%p#L4ia<[bK%u&.yWY/ zu(ԥNl^-} SAA]& &|p}L9p*++iaT%^W( o9WkOPRbƖ "s @Ac[ "rbnLJ@J{џ(E r6t50B`JMշ#mB6C!K.!3 "*]Rџyf&IЫ֯.[~AjAl쐥v&@EZ|t\DM QM~kR𢖋ZkFoBYo''XmA { Oowbȩz̯'^;ߒ8 ?lW;UUK0^hoN(d>[̟Z${pUUYBg|˸[R+QM6!o2{Xϒd)#d&PT~bDV'֞Y/'Y$7~(p1zUښP?ިHhE,.23r0wUtɤs2P\kK\uC[}SEONec{Y\ nU,W9u}o9Y elFqԽg+ 3wD+HVt{8Exx?1|93OIcBٛjEd(O. 9re_BLӮb׷~ҵN%ȳd5b QM<Ѭy O77[#T+e!](PD 5Bx,02ÐQXV\ ڴ[^PۉW҆P8{DwDIXU@`( Bp/0zil|3ґu%Ro,8޵OY"7 Uc1$%~;H9DگjR;znnAeͤb{aZ^fΨbTp@b2_%)D 0n5_̅Ty|Ė/2| wT^,₂K T0"jk43 nwŕev`. LHJt:=S+O]-fߔ z5xKčufU9nkZ;1=c9G}eP|q;63jl@D cVHbo\2%»`?|u)VT][4:N74ֱsSY\n[VQn$%FYGFD*^E؉dPgdA?ËĦKdrX\4LG0-y- NO!?9w!y a'L8rO =Jӽjl^2-΢20*|0wbrIi!kT f&VB^L|ePRlIuy7P!"2vM2p{#|T I{t}zoxo~~VB l?= uwQIL|^"ۜV 42:  ݀,Q.nQT6?S4Vh)+`80DnB򊶉El"%ڿ"X,ZVű$0%{͠P |Ϗ5Df+S[`0vtSiҸb1䅈Ir"!.|x Q`9 YZFe˥da*M7mOvW1GMqЋi1ΣU^mHէu. 2sd(ŮXkSգ"- 4}_ȶB_bkkwwO6zym.sEq W;`cP2(YIV|jec?| ^O*_{ivWXoJ䗝8i,T,r38K!O1Mk:iC߮nogv'o |`VQv`z$dyMoLTf0h3O؟-_-لZy!Ot5bn3$Rڞ.r7r&KurRi)`D\社J]QVeϣK]ɜ< *i=c 1:߽DFΕDѶ'cE&H:o6Nm 2Q+ NO3̶XZBAHZZɭȜw.~[1,WW@ $Nw>A@Hc^%V3͈IqNgvLIID5JG:Tx-L?S@ e"INJf͗*-<p0Ó@o< + Ź<4D704=W 9LzS5Ld0h7~M(~@I|jC'i,K"fªc[ŐJUE \G~Z2o:㢅QQd*{=<l`Cn"ľR QF`e3,R/VQ,q a/ qX/*O]id[TBQDR$u0{ J+D=@Hg]dĻ #dPE/\I !yd1H>/ R*=p@&V,kY ËZ K.7xGLXT#D2_A_$.Os$ =LY Ii>ڵ>QF&)Cj~:=ÌCl.g2 ݜNl i"4̝.I`h }6O1nïףv'$kˊ+T"!/?~<9Gy/ڙ7eؑh?IY@q4nu^)ǡ{pA^ a+K59X?r\6v:[Hpb0H*OO촌*1HKUiIFT:}.s|맶f|Zʕ}LAt}L=zEz;=_dt(:9 vsyMWQ\v$tJ2&fc3 :Nca} MOJ75Ƌ rb0Dz6k;5r^| \T2re<%A|]Ó`ŬQ:m{dRQS};^Wd'k "'zޑ[AdPªw׸a#sٞmA?}]݇wsbNz>}3 tX@Y!wb$Xc,gIqeE2kO0L"PyE"Aw.O 6^]{=պqCVA_ *WJmZ*L7|.c' ۣnE,>χ⸕,D8o MY,!q~,~86N + *y۩ & &r}'CU a'\ (KD1m>و2 W - qI."iVҦgs7shv&=UU;B!(Vr؉ 4#٦&H=սB4D{͹<ǽ ~7 (O~vt9C)UzF^qH{TBCA3^_cy9ZI?trJj2kWjz4f=!'7U7b,|qbb+:jHǃ6/Ͷ4*-|n%[\$v^M4ʰ\lwQCa!c4n઺zb; KFlied rg _.cH8OI('&+d\ =u4S;㞲;M(J/?)Zlfwd68>s!TQS)n+nv*$&KoˬG&k fJHK?3^buxYW⮴1+@H;$pdrKM 6aԌŢTհE"4*N:F X+PQs Py}?(LgNj~4ѥUN/57l)dVxz==ۖ.PAg =!!ON%F"TC.9` qfR 0V{X_M-οS΄MnߘL*;Rx)n`r1YOpO^GpJ/5QcуsVƙV5cEyYn!6 7!LHe؅v=<ʪrpmŻZL1={tA#{>{6&,>.tJ՛^LP_G3 "9I&!TS%-Gg* {ϵH盟+F2~gEWG/!}V/|ɴ7_UscşG$)KqlJFY8x5AqY qH "' Sh)a$c6ǀEY1e+٩%qȡN̐%+)(ٿ]J͑grؖx' WNJq-KB Ӷ 矾_B1 )T63qF#;0Yafxs,pjۇ>D Y~\&7jUgmpC띆Kit1軓N-0jAzuvaȸtVoZHg=)Rn^U4 &rYP5؝Zc  θ/S%yGdk d3]MiW\48yM8+j|R\$?Y J`!WQNelz݄Z$:|):`Nsj2ʊS?L]iNmcK@gWh(NOzax-IG+Tx+%J.._N)17+P}\҅擓W1&1-ju(v_@W.S=LZX! E-Ǯ㻎ry+'_1v90){b|T&2lieF9ҿ{zg)CdoV9(qAlu{I; xl1ʗ0/ E\H`Zc:VѭZ`ӥWfyK,Kzg2U\+ Z^]7}?>nfJTE!~}tb|HXxGh4;J2  Pˡ;h=wf\aH@s{jTANVkSs:j'Ü?]$S"0?Z}AejDKR%q 3΂c1,1!ЀIa*A"wE: y QP"羦qP"|&G\ Z.e$߯s Yg2uW}}Otq8N?"cTs&DzD݆h[D(5T[nI! & [j}õhuYrylmN hpx1!eWr9i>r/tl3 ,eMyOSYF{`p&Y,ݬVGD%r)ЗH|End/'=JP![#O߼""b~l;`xqwD7GS۱3MD*$@-oȳ`&hѯ)$x{%(i&@xW*Tg ][anN Ev\2AF8NVa^]cYwJ;K>e35CsUE?п(DEً%9 fySQ` N1'RNUO>Ld1<]1pmCj(;6VJ$&8}<Q:\}fP0ČwYҠ¯Ìnnbּ|IsW~I(*oǿ/JsAsz}jU! zT9LL(V>+L' *z]~#bA^vF?(lGхF1x@K,=݅:~u /G Lܳ+Xjxpj::¬K'Z."! GK14D3HxΟZ89z/sR\v4jM8:+*E^z>e -B+т,%%ً|9J^sw$ي!m{Ul=w[LܯKQaJpTo/%p*ځ)~)bW:{ӖA\ePdny1b_DJst5.ڵj+LlqN*!ݟ=mdͤcf4,S^kS"j[~"ڣKkcvh75T_FQZK4\TAǒ?j&ʘb${kr/vëwxfbΖdi~td%eI -q2cwJ?~hsCxrm^_e 6~ժkkS)4ͧ܎e4s[K{pȥAT4{y}gw*|;%dNz<~Zx0]i$v`Aoem[)wvBw[A*Ԉ{t~m O5\G^1QYTm9h ށڔUE0\ʀ =YMރ6X:n[wglzkfX[;6jg,E۶#qB1eB(}} DX,aL:'J 1:$턊i]i[h)vbl,X`lr"$'JK Л@|XNq+ZX/NM$AWu =ר)씉|,˯X5 9FܘgM.t!w"GQC7H֯gop`d~T{; x_:/byT !חtNLlM`L|s 9Vo*@1)҉dXr {ٮAN 1„n cnKQj &/jFMkD>ߐS B@4`,bpsH{C7{|F"tigr5>=4g16a{1FSy%PrV-cg(QTj (87H4n 4|!b4CȑPgMH 2lXGђKl(P !0o1wQ} +%rמ%Y|*~.R 8>`ctx gu9@AӜ@X9O`:$ j}ڏSR8vc4%~HJT(j䷘8R`t`ȱ( nF0焇ȁ*}r\ÒC?܀+$] x`#[u[aMN|RQ62'tǯ>\{WZë;yͩ~QK[^߃se*u7}XV\Ca(Z(m6Hz|dU6f_X%A{$`Kk{7}'is{:$។L9tAo6FDH\w!FCd4*3 r㫞nzБq!L Ķɤd9WS8}0A5*Ś_Jbfsv8_TuO_#qcWS;g@2`1;O9$)1Y #\b ԏ}@0pN`>n[ Γ2)l CSWPxWεMl!.\!9މIp4@Xhk>$ 8 )KEp'i4&avzd 9UNܱI;jlTsh-s9nB'kE@dך0˄“0XԦY~uswЧ_.֧W%C3`ycWCX-\Z$ *gkFh+-||kNċCMCKlcMV3)Lʶd1k"H^%]\a8$Sڬӫ)b3&$+z~J#( Bs!ƀG+ 5X@M4zz"__f.V@٩~9vSݶ`f0hqd(Ӡ;*#1;L%j0*X 5D" <9BI)m8\% IYq5x%tGl4sG%>FO9gK`,˙ g2VKNMxNLI٪}#o>dt4S{~%Od%5h+UMia"Hu|Hjx<Щ{ȹ7 ڪ;d`[RСY=Xxv)G A.26*V*!%D0W' d)6ۺ~k^>:.,jl.۽_TT"u:A۬J(pw9 kօʩl)vOeQ`?ͥ 7WeAy/9\ekLjiw;^&3zSF_f PgQ#ّ~b`}HTSa@JŤ 4jd!eTB9&慳gG'#{H,h>MKXKM۰n|1 hc~78&)ȘCJF13HW`FQUW-$LV 6/L2co=@ Jm{Eߕe>ߢrY5G$_l`iOVhvQ  .]@cgi|[#a_^ށu" *jDLn ƸZWIJsR,/(>}b틫$+iϖ~;jӚhP$%D*0"Ƅ荬sK_\-"JCb*!A7^,Yx'PbV\ |fRw*P:V}j$".V(ƥ]')g8'qmh+0}#+N5it$8|ڎM-Cq:%c VG$;&~O\ŹNŨ \1A0r>>#$<5V)t) MrOp${Z%0孳>Oyvᯬ 6I_7gHD;GjYiR0s1*F:^$6H`VkY!pT >N\<bdP>ޭYV>xf u?Vp$ɓĪW+s"'OD7y<gSUɩ[t0CdsPdv*E~݇aǑXV}F \7O(9}(kt@Gly'zc^/9_}cڱ8tڔom8)EnO%Z\D}2 1ȿ=h/ьx"OncC5t@4.揞RNn"`{[{w{s5*On +tT༦KW8 Jt–ב3}En4}ybԬHa: MRe-MVjۆ~(΃8_M}\e~lS(kt\Th1ݔc lj}Hsym<<š`L#;Ik :+fQM7[ ecl y8F[ҬRس&*!X鋐$|,<|r|.0T%+LSþ%;%A(e+WѨb&ӊ)h;79BɌeh9td8 }g4&T'@x~7_<slైQEbUCn sX0֗XaWbgd! ,KSM?pO$<i%0CĦs*>SzmۇE;s4g+ét"3]eB,d|IuMhݘ  -u9sSyMAN%K sXuѦǺ)g&Rgԓƪ侀+UDi?j(`FHh.D-jWsjOӷXel, \ xz_<~~;;ޙy2W`CϟD`Mܱ4 u ٕeSD@=(fá,J`NNrrͣƊ՗֤M'hx F]`Aَ]zx sTGc2jMLTqMJ ܟ!nl;5 _rh!FTӓhz. RTxŜUujJք&iY<2-WS%s ;x5?{0?Ӽ!~I&2+)ANc,^T>hn.<ՋD=)^TtvqƔ.6k?e^ˁZpnO5 ^^jB 5+DphuW,VdR`=^f=on)޳v6/h&Ŧگ.5gF"M&U-P)j;VB̉s,{ oQ:xr |o;  N.pCH <{CC #l)Qv Џ["͟mּER; ?) '|Yt~WKRmX'QIl__Fb˅Ck>ӳq`m4pE cY|ˑ?YmY1Eq@,7`._ _? ."Uqn>{?};+Q.\__bKD8{EkEVhK}a%-ȇ I]d;W(bY{(&'u7S>g>|d]p10TxpD}}wh|l0*1s~?p5XR45PWh5Tv-ME T(q ִVeL@JE' [[Td 9)5`<wHh|OCl [$5 .9Cg,Dp%ٟd=}\<ݘQX1nQZ Oǟ2zf2m1\ܓ fr؈Y"C_*FzCR6bjC5q ~.5Tu@mb ϤpK~q,-ux pN`+A_4NO2/ÏQ<}n24 cA}>>.fBzÛ:[$%`(Il x`bFp BCj .BxPO|YUfΗ`JQ[H;z:iPYb $ꎥ=-=ޤoa]^)PV IJEI]$- b(?_vH/<&&x:QcdYW"eťIPlWՏpq 7! 2i:f*_Ew&c&1d8Āb.< -ʌzbwD10-HJ͜7i&g_`F{V_hVD-z&XAr΃B\9eܮ[Afx "<E* /P<֬ڴp yQrS2yy}Vh$ }6oUHs;~HQc0ڳJ =kʾ8a|'@Tgtp!X8Ϋ fChGcWRGSGr nYx+ 4U sLH(SI؎E ;B2I.rFoOQQi="k@ 0ABo_MOyw ,lGL&KhI'S,/}1O1HMYS!+Vɖ>"&Rah^xkA{) D !Lй'V><"E{/'m<;Q5,mEתj?+%NvO?`.r5߾-0`3Peo+Lq_P Da[}u#-@CRM0,VE* ɌL$|HeM"Il\1}\")(ہ1#gobsPQy>G8x1ʰΕ<|3wFoHM.d{{xP9\,6z?A 42dh"$l 1alaEy%,{~2CnD~ѮXٯ+8luApiZ$i>o^vj7*qCE!3j:ك[UQtќ‰(h=Jq.R?q"K`4/5(X6^]g7+\]u@?aɊ5f":JeDay=oţФ.c `s(:ѳі.ۋN'q/MN*c;g2I)U> rPA<^sWo\x=ܢFI" + `ihFV]GZ'5)KD/~Xj+,mǣM bLoRm, |56<Dld:KlI<&UcߗF" I!*]{jeܰc[NCПp(: ?G8"nbǭO>uB~|ga\ |mp J+Cn99!ZL\qhF>@WlZ 6=e@S9%7U!2 Otco#ѧ8( BphXz9HR+,LG7_5*lT{JM&G4ފ ˚uuVKi,F(w?IsZ2m%mw 6\G@DCp5d!*"(CpI{&[i[HjJsgPG+m%,-4}Z6>A"aQ :1BoIA|XUH7Lչ PIoGzV;~Yth\Tpjj҉''azs;׎+X| 9o[hq&VJ)(9rBڽa;_=tzuRzqv AS%ARL<)9yJ8~)NՈz7\\qd"{Ce qɾlg+5'%1X@\ _k1[oYu2]uVn?7Dp;('6CJHu_`PujՕ $64Xh7.޶b1rq7_qJH`k&L$w4TҼKqIC{zTb"ƞ&"ƔP|| %NEz?<>8\/bUgjIoRքV {m=vǦe7m{ }AUgr$PE\y>iDH;RQ8/c|Rl=^yh{4,#ڝcQT:z{3}D&5Έx ?<Q4vpVxMđ;rUnZBkT0;&oB\>o7)6w -P"3,<&. \tpYo*>Kİa%Wl"$qQGɔǧ)ӣLTUtHX_2TT*I")!x峀$V&e?Mg#IqV;^KdJ%ypcm,` -|$xN}t:27[(L~Iɑ<6 <4wH8&7X_ZZP`gσIj Ŗbp"30sz>-k,16`n1&n 'g< L;ū"\DUU&,06k"<)jLz򙽹}Q2y"7H7]$ |M=5jwRj?4{dVNbDtZR*&nH }DTn߽k6LruK4[)bU.f}ӽt {-}E+}FNއGa t m#]=Ybۂۖ f^jI_E}Br.*ІcL?ՈMJ06_LR7-ܟcN ع`~ }+ڃGSA;@q6M <7d ermbVQ ܊u'zI $FMv<0ra{RYOMQFMW߳ c9_xA,|Zg%3"zQAy,!0Z$pG|9*' ~7?lW9õBi8QʟZt3L[_iRex"7x3LaE<T˧Hϳ9ఌH bY< ~ALl w#+zd˛57WpFY^Qgt|=<>$mCOpZo,PUosv=Y؞Ygիe0 7J8tmJ*)S.z|]MsRWԚA01'}=U\Sh:OKryQm&܊Z*OG7퇯{D84׾iViV* z'`6 ) ASBjא#FޖG2/?d R. -Pq,bz(1 ,<DO22it ,PLL[8%8z40"J0>ĬpWB@L 2d$S*œ&RСiIE˵ʦt[JvK9AE0`.K$ZgfARd RIj7岐iu|`A 3|lO=TiQ~ḳ }O|s#\MF#ncAG*N.;,\k^8qkt @Yvo JiZK;R>tBɇe3MܦWC7+P1 oGc8ݾ7U7n" BDNpUnggϗC0%,1EAph .OY9t{+?́ =*JV,ąUʼn'g$x>(}c"1ᵦN7ID:5I̥1qA)Y_r2R4 _ĀfdΤ<9 ?<=I%:Q$ѯ~ =1XU T?eQHjh gk( "bx+(p@ b7wCdpDw5SQtJyn#l2вR"=ՕApN]GD{ ,"7ΕqA8~k؄0J\XT5)[$Y~uqrLّ !r"n$D;Q(ʉ#S25f,V~S$$dQc-,-hØ9HrGj [gq@<"%oV<bx@أ=Mrri`zE8( q 39SU̠-qqkS>TonT<,1G~hѕgn~xȞ^2mko0UBƱ/ɠRDWXptAmkf~x珠3 >W[hA"*xy7[CS=%lڄ#^Dہ_X`+[jt<"Fۘ;Sc?9n&k<~]:M;!i@qU"{#"(bڝ3˨"m y WY$|R1%jT"S( ,RM;[]% $i)h70kNu>OA/MqY*_;fw(FuQB1 F7Xy_?W8{Z(JI;lxB UJIAu+i5 ̜m%LE ,c *{M Ǽb7!OpH`cC@P4>k{+}vo˛tUa (R`O =5)|jœyo4:]@(=ۡ\)^m]_oa>Nٗ_7;_܀+Hx욼՚w%gR ~n8'B&wu?AF:J%V1de˶vd-q)I[X &G+O'3dgik<Цe&2wKs6/#H 8u]^Yg|%?DKe1hٞè6gA~QX(ؘL3ac̢h,WpGMk J q* 4d>SMBL's]ȒgK"r+RB\gt>"j=6/^(_60'+Tc*xxS0x.-aNa9di+O~ZkzlH.}VLaQ; a{+R4>=p̚ oh]Te6IBHtSv# o,Kl~f'cX9U!)A{!@4霿P- ET MxM'ryrmPtHC3CqfZE4x]̔hpdYչl:r<.k}AtwBިش.\D.ypbe4`6nA f[4 ٞu |öD0ze&Nm2=zGD"=DQ3 F+DIJ&6+U-EV/aG^T@NFb=,㵃}OO1+7Ѱ?^x4}]4n~E6шYf#6N,?zO<TmjMij(@g$#:UQ6}z$1E_og%.O^c\[l|6,znx:ؕYMkc: [.lӦٴ&ĕwz縛:c[)eCtiJv|0"@U?d@/ [x0ge'hCV?o.۷帕`TCIʒ4ytzڤ_h_1_v`Ҽ\bVTPQ:[;80F`,Z5!rg\G|֜ZZ$;ʉPIKTDEt {kXWݬfO*oʕ.[q ;QӨ &'H-$_>\HPpm1V i<>?T,Ͷ)9`bYa[/;fFΒ c; arPƢ4V~'|XH"*N(2,dHr,]BLV>dF~B$]iL@bZF8ĮHFR/"T^lC`S.ݟXʉ`1 W_ vYw}A=:" KCGtourKts#ހ .n,:3J,LUI{(YOkM@BmmK@hPN 68^:"Xi]0$KBZhZ8,7Z8Y+GS85<΂W 0,C{K(2c$$[BˆtŒzI]tI)%4WB¢f5:sq_4wdTc47uzLOo3@EM }>|ݦ8\Ln_}5:ռ l&Pʩ0ѥYOsFI_0d4h+*HڢFUvaW|SamCAm %ddqFW^{SJR0d:mUXf8*Ad U$h#z=tB99zf͑J @`8elUXT"g|sh k3xD>^Df*R^M[OYbst4eb()<#(@c&J, ;~zݤ/b#mui=6nĦFFe[ѡb6`نL/NHK"~_Z6%3 EļL:vOB8XxmF+FY=C9yi8hXfA,@GIꑽD@bJwNx n4#%Z58:gukGWWObP&"݇?LFY7v&/s{r{t_Ɓ/xXdn/eqe{4N;Z' (U INo^5iU%Xт;w+**&'tϟԓ jtS9-vkibf,i"/ Y:@pdp8%:GsRzLz :|0e62 !1A>:a*. D2i$)ljW@FNPURlDpZAލ>}~tih( K20VC k*퉽k틶?L^tQC{?,!5]K{&QAb+6)[=~1R""om $ KC QmZ*1Zۢz S<Q_x\1&<yշJQy~7P]]^%"R{Nآ"pb?wd*h=?< h GtT.y% i;J#b$|ԭyErn[Y p7kvZ7YrD֡|w\ȶӤAB%%VqVˉZQq7SqSQ!8uRvKLBsɐggNE0jʾJ7TŖx JF^ dá7-2#q̅_g?_Ǒ5f3Qx,%uwn~78bs{d!k$d0pt-ufV@* ts$ RGwRnYg?R;x$TjgE}~u}j,tt3w[*J) eX_Dda} G?u_V]#,e/9YT@!j&}/꙽;6\bZF|جVϔ@<"x܆rjwY5~G7X2$*j^Ac2q`QL$B_ D/du Y&S`Ǫd#rЏ\{>)֛NhةŲu4I!vhЋ?"HY9./ g:u4H;lFEJhR "wAC"a؋@` 2NT{ XPٽ{,j`eݻw!I7Ty^,|RfHO1R#r0b:bP?f0%tP-_FKCazjIBCӎN\M$ ?E 5L fsפ'&) vP7 r:<؂!ɚ,XV@eHUYd% 5D/*o^J?nTi.]U'Qnj(o;j"zͅ`%7<VJaJImNO6ϒGab3]4R:S8J:RԌ#z-\%3pZ)ōdY\TY (F5eX)UA{BdE}4rn2-I9$/'j e8?nX4\/wu5|8 wMSk&WYxR}7ѿID6*3Ii.Ox//mi[#cMç󫈄K(WeYmMЛ*G%RCZj^XH*b@Fj/{"DC/Q/"z vrV,b|,1ʖx;Z5Шb^Lg/^˄ҡ/AXXX>"ޔғxI>FG( ^`0ڋ+7F!VyLǙt# KlFN]@抳![dRvpyg5@U_-Hj(k3;cma bQlYBlsё M,j yATNݧ ѝ$ϐipG%.i8W7PH~H?uuixjAF؆ck,?ZkZG@pf 5TND¦VF9/3e0*,E]稀_0)s=wiJZm{KDf!<[zj 7Ф,IF(*,aΖ;P @TTj0>رUvn52gb _v* 3* = 4Hɘ)aeL)h`p@ S'4PUD$\ ~28Jb:#`/N ndlN=&Iܓ (Ud,0*0rD-x=ydk!>o2ea#mI 4%r1 &h``g:kE-E%om/"ʺ&hŚ0W1Mށb;؃NؘMZ̨CV >P +?=Vlm)BJ%~}f1m!q&bi!Ti%˻twoJG cy<ė0SגԒbS5%g0X#V _ƙiw='s"Q,o<Dj8#9F4cMJOq^RaosiMjA -Q7!0=p pJ niebDS4NlǭU[I2g@@Pg D .Jg=m$Oԕh4]4a"V$c%Ni"Iy(%k/81LԺs;C1U 26+6: cFҪ}ɊYBTeyB93ђ3 +tFG8.!bn*h( z\'p&El: j_HD bmfs^ h򀋍ef[[w \S2ƒ!ݟJH-&:}Pӷ->Zz!&$1-{'x!c6`~"  h $2=>ŧרCaycXBVi1"ǦRdKn;Ggbc]Y Tq +C7@6hk5R | icnTE~͔M0] GvG"vv;½\dO8'K d*LDl@*`gVJس (RR57%D#cj̓/YQ(ݑ^!Q{=v CeDݍ%yؾs`V^nys?d0&#^ Ԣ3dBBD) ]^_E7o?:ơJcH WDTB֡e+5MŹ} 3L@4x:U0S۸dGȕW$2щɘBqŨ`3Ն#S Cpi~CQw$ YPCCR li&)!e Ha\4E2s ͫv˧pm a -\<P ~X4(/KWRsSkSpCq2w94 -]"S%1isg] ,^ZbI+U!)됄J\1xfdB%\֔8ϔ@W? >`O*ϙ CɐI?ġғ6A\g & qxs"Y;N*YN% l4]F47ڊ{=Gp#'Vcr}%.E pG0XcMH \+\H#-6'Z`7Msj/dN SI"OhaјAYxJZUR܉/mEe2YEޏ " vw0<{($VvVi RE== v8,l1a!1Yti[pt 1\1iB̝*ó <&S\%vEll_(aDWMt bmNP(]dCfmrM^Z-UhtX]]GJSk, !%İdƍS$fٛpk3Y,pZD9[KM38TR+`6z˿ڹ1Zlr!qKՙ%@ 4kXF{ jn=>(,DX!xKb7 zzPG]q1fX8o,~@3-4H D"lac P#;ϐz%"`3Lz\x MnNԘ w37kI\9=[S92aN.IDJ I`gvw}8+#E̵AE)w?r5&s ER, :p?k/0-]oQQ8zU.Vlyw?|NdM"(Rڊg;=Bo=?e66bTږ2><ýX beXkPƫn&kD#m3lo@;P>]BԂw.?>* m(c`4%@B1uV3N!y@e@G`@zbkbk]\C \ Ja< =/%-i ̯nj;,~ǣ! 3Fi {}9iZ;?_@fD@/]'r*; ETFl2A!\yP tDs#h_ݒh$."@=D ~|/8c16'/7uc=`uL _/.U/|rͣ7}y%0RϜD˼,ǷYQ];=ue%`m5H'}' MQE8#`"i4Mliӑx( IP<6r%,ջWQK4@kJsW$#uL 0R!כ$pgRMIm~MQ'5@IDAT.C.tRVNre8I @xQUlfFt.GU50|ˁDViKa2aAeH`BPU<9Ϗu (E_-@(‡H`M"?QRI׎I5%t?1%o oAv>r)a@' Lj !f'u6s_Nrh9ρU者3|~#Fx;7Ue%ĮP1#tj{ˆP9DP Do[\melhr#o6?~mVꑍEZB=%AُT=GGH*Ha&~mf kxxvtp # %x&k~HM)%ur4o^^5WOʴR_(.N\J} M{g)v'hP0TKy!>Q6Y/.B_)oo#-.=f\N+yI[s"& !X-3i: g@%0Oa7"nҽůCPT\^=C->@BUeag@ڢ.JHX377'DSKp|:M-}60E 9j EµbҴ"Ȫld{Q#aֳq1E oŬ[xDyc̮=+\g$"*ue@%j =b`E'? j?Q B(wO0M- $Ia4We{jG- )VAO1NAX tP !π Sɧ@4NP(DLW|F~[:P-TdS:K;;.^pU/سO BaG-<GaV `j XxRtDe>. 2R/5-pEv9 Rx`-jbD .h&5O4Wtm U#v>"rtL [P;f h\gͮX.y<ш˚(q}Cgc_jqH{kfd>9Z8!Ϥ1U#a>IptH[PE$xp0-yvskb{C#}d0p$aQxhȯ$37s³;kF9e/#,z_P-;/Jiq"/-$1g2oZo?(P^*(7iUս~ d7O knMnԆ¿ ` Ξ|f r`HTRb@ $޽EىPӋk^ M+Ȏ>(2)pI,G"p9;4DOYK|˝ˇ3}9Zŀ77KRE&͆{}]`p)̓=ԿÓGQc2, P̀dN֗Ɗ3Cӱ\H'bb7mWiVj1XlN$)L'")1$B {}䌠G 6•aEqh#]0$uЩW]j'9J$(C`"t`@f!. L$jnŢ8 t2rߞ'V:)9W|(i18W5Ŭc3̲C~ r0w^_$2Q}q(@ķuCb`|1J޲*QVX0'Rab7MK:FHgnE3DTg% ,:"6Ciil ޿VC=&>^)G4!?pDДOD"B>%&-nO+uL#m8ݔ[+W.D[E\q'.vaJЏԅJ J,NK)3!;=9{!!jMKDs:MpӐBG5:OHk5VZX Ƅ³qr =~0 d H !ZF!q}1 )BU a.Q![WK3Lv&b@n4ڮ39Rv]tA["d>ݜ-o.p>G.0>/˗2{ րyyA<KA .KhkQċ}:j]\0$v|Iv흈o@D#ycJ1񍝋n';2]}}_e%q+M}ₑ q``+T YX.>*Nb4D7 1eي@hN, 7F5qlni18<>~?oL,!h?j.٤yHZ=F'k"TAh%bQj)kjmx]gl@86O`}hI۾ϼ֨ʛ1U!ŞAVhS$م cy+^+6vMBO/z(`BOɴب[LJ]!Lj]LJFKR#QãzU6%'oDė){[Z9%=&/Η* 19tLˋkHrU|r}s&Ӿx;kfYD!Z LFwfDA* ,K)}r#qUX5?ABoο(G6aNG[o&Mp^\w@4 $M86J۬}Jj:Q%jDn+vZ$Z O&@% ,;EztEI^  ɱOjMםb+cFbpe,Z` E8>W[i%!HD@6I[ EI<vĔtV؇.L-z`v-$.(4CP[YFO0Kd`~+ס%VL"As(=5Ah.v̮c8ú'DC0@aWd& grbW_"ÇTz!*Q%5催IyVqi 7NR@O6,|B^?ۣj)[+΂(ޗ>hm gaXJK-&#܉(AZy9=cVě_#z%Ìa\oT>0zc 5_^x 8H&2-nV Og¨[2I*NolkWf/P<$AAiY2: iʷ{ubvw !"xeJ+ߦ.dc6u곫`C`#,ƿ1e[ .ITrUѩMx&c[`Ч 9qIĆ O>>BN! `s7n.~xXVHjF¡bOo*N$T]쪶A2Ž4꽡Q.X~ :=rk ,B%ltJ"QcL jHjق7vT@L% _m݃H2du'9JS U(t @nS,d:&Wx`U,$R|cK@` p+qSe,3(q7q;6"W!cbڐ Ub 87 Lj Ъ0G{ҋJq;8;hU&1ZnO(bTXJ_i>w =Ҝ5R3rè_=?jOl34}PL<muHaaqEM$g^(:.s U'G>ƙB '斶~fuz4{xt %^a{UD}0(`[1eq:Oj J;J2= cS9trw+X%_2{M r\^]T{=D {~HE/q-]Rj4y2Ͽ^_ݰhMdvd¢;9v((ԑP:UyŶqڑⅡ؉O߭9!#Y L*qK L'5$Ҫe-Ng6t`-ٚ|a F߭Kd+,5CoثW_Wspp$ IكQI.:|z4F>y˵klVx$y=H4AP_܍ZQ"bLxֶ ʍ w.WSeMX~Yb*!:!rI^ u14 / Kp%w\s!Z,+ډXWf- %@݉KJC>9Ć0hw|{6ڡ'Pw5%(;u=3fo#EZ$:umhmf2q"mxR/t__^BC`m\\F˃-]B]U`ԙu$wҎs?!Y# Hxd-9^~"wU"KxyY_WV HsgݹXi"8<03)טH'BTugLLk)EbuXIz{,.X*83-F qCĮC-:Pfg!'`HAPc/W=녃8!+d, n`e:M+ֲ2Y̱^c8ny zE?0Au3Dx΢ζ VOt HR7e,ʒN?S/n=?*%ܳ/{: v('4Ѡ`@JZ|I!aeֈ| ^ =U#ygV~%sJh]LNO$ނuY Y)n~Qe,qӪz1dp3{&ݦR"#d `g5S#ۡPΏ8 /oח‹PPF0Etw!A*>Sӳ~w5^x8ؾdt5VcmAE"8, uGx,GgOpzIw ,hE'\tRg0JpM}.lp%s@#ȁ,yY' d bsW#A+p9d $F_Lw;`J87O> ʊ0WLCBO F 0+ҿ@*$EXw "gL1.B)1X|ۀMʯEz%V:_ i$,Q|XNr %ɔ X(Fr||j> $23DL&ҧX_!xT`EuܿZ'\mutx/>޾y/ }\JQ30Eg%eڸ2*}%3oٞL5$I"DRfZ=+1?A{_FZf@;۸T}kdn=C?emO1"@f iEmؠET`iƑ8@)=e.~|z~=/H &0 & 4N$0c^{  T.#fp v8i)2ި;zaGL`Ӽ35^`p<>Hq"g6SˠSmK U[^u2OWH█Y롚k'ki#B,VKXc:?t%+@cR ~< GqPiggg/e_,tH*r"ӳ6Yy ̜Ek͗ѝ: 㝌uq<OjoH-JYa',!>R)y9b*j٘H4TkrzvF_)ٶ݌{(hi] 9W8Ff#CG ҤKpb!O~2* )ݰXscMXށ"xh:-:np?J=[Ip/Vپ`~r;W{aT$qoQ> x<#f98Ӽ(t^=Ժc^N'5<ԯMĩ~{PV1CrZQoCA_E 'r[3q"5*΋ ywxK8,T>wFd*?쿡 ̗xlbJ9V=1].yu gS[P’am,Ug- YSyY+A._+f˻/r|pxvr`du$lTP(0kDpC G0ԓu)-Rix,gZ׏G,Rf+e0*@OJkfԎ>0W3Hf;)f!qSkBȿrx|ppz H{,xk @"Atޟ>zq(JGGG=qܡ" q3=OF%& dL{0no,6dkA"ǹpPXNlwodá^A<R*⥤zj+FJO0LVk\jÌy>d;5l6X& ۉ!HXG},<(x{Guy߽>\L(WrgP?#9ơWw _M;Nj#/.CfV1ӣC~zzo^]G̾ O?`+ =1'zrIE <[cu -0'PKAsMh^ RkKӱr$Ң4^?1P;|D8[,mfo?I$K.lZE3R%6!D](Zb蚯#D-}N\Y`xr/*L|3AR=xju %Fv-2*#@]0\%FIM0T>ȮG #XỲ}qOx!\WAtdR*9d8qQ @'hy/Ů4I"M),&xJJCb O 苠8 ) $:)΋5tr dە<2Il,8,ioUNwA31 d/fv} %u߱r\eC*/͈%+@D" NG7AF(z!-D絋p`J؛YBL^&K0o3e9fRw oDyva$X) \*ͱ%b6]Ð//`uL{1 99\2};ξz7#"*ȌʳcddXKOyt '-t9GH:ꗪG0OmxER'JϑA8x>ܡM/:‰Ȏ$H HK$RK6sZl mL͗ $SnƔQԓLWwC5.+w.O`lTUc>"C[TF2B&B>gf&܄4 Ay>\<tؾ&0b8Fl4 o;ϟ?-~o^u|z="6c.醴 _?~x₶*}׶z͙ [NG!(@dⷘ,[+Q|fdvpxhQH*-%cP@,0lS e. كc {]QC.;] !gCaiuAUlPhkYr ߑZA."\ GV[@Cw-A)V-ёbK:+ -M9IIHvE<ݸ,I /m`6 Vy*P.&|(C&3Ձᡠ7^@,Uo#ֻ~u?[ǿRy?k^rQ{`M,$c5FI*.E_ ߜղsL@숅쿾|edXlrh; =TgZXI2{^Pm!@JH5D^@ ӎ54B+[ uJgE[sy˄ ܎X2JbVɍL$ qsdb%Hg_G1։)+9 \ݝwpYQ6HMDvHbopeώ!蓄`(%=byXB 1u.ǡg@.aINqDv( *BRr:S/ScX+Xns- Mng(Kp#Hb usVMjo]u-h%U9H0׳߃$q[2KRN 6oG͘y5Ɏ!z%g)aVTu 6_$,t\N\c7X~v!}d "Aa`dVntVJNDWZX- dCNvL7.ԃBz?<}t*QhH)Ҙ `xk zɅO;[-a[`0e#q²Paɕq`K˸;m2'LV[ I q-*wŧZF)9 o4~;Z+AHRd~-S.dJ9a~ rE ^W[|O^XiXȘ\ ?_q0&jqU; qqgyBl)<蕅d!a> tb|϶p?:oӣU";2拣@qT6d2Iܭd\1US%wzGCISePu||L#]~9}W1/20ZŸqjҮוpwr}4xl+p+`??t?{V&muDKڮRY,WgTk*wWN'졯  gJ@d{_JЍҽ /DCC){e(%e/mUyg!;`A^  Ŵ+3;k1Iʋ%"44LItPa)=nyW!aq\* ІbK*' VG !L]E15x_@LIJ49L>|Cu"2!^!}4u˰a蛳ŃSs6b?.ONoc_=c, ].08{g찵up}"?76`/wD!$΁}| =2MGC DL0*(V%)H9MU ͽPm .@;[R\hР쌍D(]]@0 @ʫ 6IVUC23+YwIFp#c(5~2p@M5")ZFEC4 ON4 Da lԒ A!@1#/E"mG[hC#>CF b,JAgq?_ "晑sX')*tH0TD Ј_)EG`}ѡ*g$X31 .;|L]6vE.}S.H I*Y/p&[4v7onG,b6 o3EHd@*5j *dO B>1öpPDȦZ0IS0mYe| *oH͜B?  $JJPϊRYl(ְ~AcuaRe'C))],OJ Hc0+GFd@1<ϱLۂ&! qLmCQ ۋ_q~ c~EڷJN|HDk0t_(seF%1_GoHd\[ 98Y0F`UlqB%Kp2t`[d mFW]ݕ:'REGR?X tnGȦ1= Y^1vX7Ϫpxwu[N8T<ܶ3E"ŊPdo t@t}}ϚD"^=6H襤v?~C m_=Tj𫔤!oǖh ̕kOeJ@ ]_֣ILL(~1 .5FK8;F&@ZHi.z cpU!YM\V6GIg)Y"u6%.XCHd%Hh`)w>yCiN&H"$WrqdCg_oݐ*Tӽ` o v5~jM\^9W8R=Ч3Խ`ؕ q.\ƙ`V'3SyUE wn\OL@tBY6lX`C#UgWF yF( <h$8 ԊEU&&L%yOX:;:1-{24 d[O[t"F}"GD(f҉b- Gܵ QHx"xy)Kl;Ƒ&~ Ɛb&Y~[L2GoOOmd>o_ٛ:9 e\͗f@dNƯba~l#ۛ^LGYU#J{avOC P 1bFogKzoSMFHѬ6-ue/7N"tag7OJR?~ܩcÖDKxbbg!z(2񰼽%her2x~*#ZlE& ;$kTFb`5b—1S,B I$d80>Cת/{SXFɝ. MMJgޗ(pG u,̼ʑw@G%E&MS"CF%l #)mZxLH2DzB zeD$ |+xw$Lf.({Lw%+bVŪ{u^mV(FpQs5Ӡz[V)ߌf8> lIOcQX@D=N$+N>d0&2s k"SDx|&9 u9#t*1t. Ϭêa^Wluv@gM%b?ξat We~LbYj|1 G><'xJk݋cCw_lS17#3/5BpeGv.T iV-%ƻC:#-$L9d< [ +'" O.s+*O+P9x2~bX)Y*Uz"en/!en/%SDJAj^",WNPd|xP4 #>˶rd4.aR (UG%RuSTI|7 sfHsVDLR,Ktzswu,-ӧO +Ƞ>$LQf [c|[]O&B9* @ZJ!5YJQO#@huJ O靈[Ş ٶm1զN~OS )+(>l 6H,ڊ ԡfgg/Vq #-lJdA#Ew{} sni~ woj ~huf*J9l8caN2!2'2^H(AH` /֠D{Sy%qp})B9|Zԥ"NH9NPڋR0L"eo\@ BCp E i,B1\C'_w/Ma,PEv aD톓%lPu"Ă̆8 Eʾ;$V⚎Sdb zۆpv_ W_&dz+)XN8|%E}M1<!ùm/oB83$x! GNp#Zr@Fj dl LXL9jHtHGqZ({oJi6 C35/?uh2DXƒ cq81Jʘ6~9@řquڻR.l'K2z)N]ϛr3*Zx&{)tP&?`/`|T_ru9CLCQ2B2R]<=dl1ru ;ntE'%?m}_$1lV %/LTG QQȂ/:F'Z@ԉ'UʑTSG'فR9OBűmO'Ə10d" d<ӊ Ri^CSH?anF7:V3:#NShUŒUa􉀬 oxe{2}w~P8pp4dcr&Wwո^0kQXN[,+H':,4TA6bHD#rQKĐRy&`1jXH pAf t:z_Fe7֘]@11yXbk lC4 PPHgzi ~CĉL0ơYu,˺i{kzzo :дUBhᱥ#bEn!8$] @!z%@&2$6%Si8%8pv,1)nVh̉ů)8< , 3cy; v0@H*U59m6IVS#HTE(Å$`k]ZѩXq0_ dqyxfuqJ =~9yzz1 [@ Lj뫾oE.&OHj\&=Ct]}#xN^ `~ DYqgxLrH:WGҮ=8fewKH ];=M7OT0|]] h~l "vsGBA !rgԦsEsX` GƤS+ʒs{MI^w=88E3f?D/ڢ)hdDL80<F|WPLHԏ>)%@/pFLXgf?̷wNI@ѵ"}A 'A)YDuBUΑÏ-ao7ݨ_\JaNyM[6E@)̈=m+7Av%Xb+=!JmǦS o&Mۤ5 AvxJ:v'wEP< T2Q?^˨N`!7Fב-2s#1+ chvD*'VϗX|1gA\C7OtmPc!7@xIT9mwAZE#?QL/9?fv19O&j~Oy~-\yOQ:H2* D aQbEm׻K"&*>#n퓌pj*٣ECAPE[ ]"$P x3~(x81Uڿщ^E jzBA)Oux@9Nj%)2t]`ᦟ\<\ɺQbRvbVlp?pYAjl[}X_/՟>UU1t0`t Z8mʢVb%Os  d"#cXowu2/j]V&}Y1àv ,BzT+tO2_)<( e)d -(3 yHaESDDcJ]ۛˇV3sexwITG9 2\,7tgRqR.P^ڰ 3^ rn 6׷<$!վ[vg9uA3hCRc%ZoȐB$VTmHP|y!JjBNr,}1 ]5``abW(qJg`K"xd(wL?wT1-(EYc5D8AF956}\2zOg>}Fߌʕ$G`}/ Ȣ Gfz=^Ttp ^Q~ 촒TlRڮRJfҀe(>Ě$AH3' PaE,i$t`8F`H+Tnl>Ǖ(['pbAz~EamWo>}4)Lrp>)~OabІC>Ӧju}_spwWM5<-P"-!5CBBE^JwDkg_fw =)eEgBx (s.AB,8UFZ-//6ݳolIŲN arC fRه' 䱑vtecU&dR͟՗[QCjJYǚa%j`Tq{!Bn O8̠^P m+0O4T|Rc"inRW`E=]EUBrJZ$wY%#pf(HDNע65gxL!a䔧 Ƅ.tF&Euiz0[XͪڲΥV A]DB1O?$E8)A$k pE@+LU@*8pJW@?ҽGIiFgt Xb0Zu 8-Z“j=#uLE9oG8Fa ,_ׇ`-#z6eg4'ƬFN5QQJYAhdFgyWh-͢ Z4(@VzyykoOh6QҢ_~Ϭ}e/ \ti_@hRח, Nw1 d4*eu&JNpo]k&r1?՟Q{U9fssoK?ߛrolRhӪ :|g;6vM+Ьt Z`8' hˌ<,wN9V/fZ]O0v +8o]-PcCV+*߿yd=`Bj ʄ6[LFc67c睼RnDTmw> vKBo%=T%oyYx&+~NZ?X; 8ࢲJM`bl=CFv̦wz+`z}Xv҃6xڦNLC嘉+VLCR?eBgr?3a (@ o* ]=VcwI)屘,2-9. S4pBc Yy5JX"/؎0_db0>.`"K@U8&JJ rK5x S&+:DcOfHs}$Zs iĎF/okFWމHCR\KY\Q(͵ٮM^j۠T i¹HK=/Kj.]&FVm?#˵}fo bݕe  pXwu~ GKu|C'&d3'04 DEauvө5M V,iϫbMWЁQw{ '6ƛaMvP;F( `@>EJW*ťHOeSs'IP9H$Ɲ)ݥ*bfI q=JM@y}9^ z%ZBg#xLcyJ@VƇBS]ERюxLKڒD3ıGD~a~;̋Qg;0,_5U_ rs˜"M->G'g=8S'_(;SDxmPqj%D sON@؆ ҒyQ^?qci s?[?d1&"O]=$zB c5ŭgV]4_$(%LmC.X$=<%IT/2E-CDW:]Jx7 ) ֶ&kV.hV5.8M&?Sh(-}My %V2#AysaelI $@%-ݬ,J= t9:~6PYP)I&c+hh iL!NNڄd7yk,, v @FAI8D*B kPovYbıj<_PRآfI!ʘ2@_9K/J[ Qvjm!'ږ/WL>-ItI+8@^^ǣVd9(ۮt}1MwJDI6[LEBx- G%i騖[pXmc\ T$_sY)8{  rsmQ2W{3Wgs\{=գVRj2WZqdjqzBMѱ e,P 0~ꈙJ"IK'N1%2}:\ί<  wuћ2 PTDFj!|K.{j> T,!_,S,t;3KYZX`N-s^QgGfwP!\3DCBr2 (7!uS8I(R3,%&s+0^MmmGvO*\:rBEdBȰ2_$I kʱR)Qb}jODNɡVca݌ũNv{k;dzӻk ;GT3V8De嗣eਾ `I~ ~:+D]6%ǐ#!j~"qA5<ܟR0D]0xb}.ٍD 'VИm4ET [gI!qY8CzEr;aHH {' 1y'K2\L"Ey uAPGʗ/(cc̆ aDJR dA1e[(sJY~|0Ry(+խ qZht"ww%I3mIM'A+qQw{@əRI{yW< {>^N"7wf7:v6[;ֱַWgDe[dDJ~t_sz"%M(E ජfmT1:8HbTLp ;?|~OC0`G wnF)Atq@3~OY^fX4hXbau2aAegFKM ц;\cFBfzP5m/V!+[ d`SXP!>vyWX yauLXa".{:*w= $VkI3cG쾺tHj%@I,NI8*ɓgyd&|z ]2eA4!!2<[V~Qmm`.bD]l5B}p`iI~ FB}4G#_l6dh'|Y.e{sSg*9 Qr"u$77d^?SAa8-=2њC ķsyר;mɒ[В7G ,މ(M\rAH0^R_>G3s[ؗ[,NujBV-%%!4Xs7AAN6J(tiD D *{x@|@sB7 fCι|QQJҎq6Wz9fL1#D]}fʓ afBa2ؤlZhku_aRsVw!%*J7]MO8].t#g`BgWS{#%$SƼ` 56%Y-A$3$E[38(#[P8D1KxG۾F{Y/ɾEw#LqH"dXi146S݉%H8ʏ:b)mIy@u4ێ- Stg.ì+6XEpY[_`np pm4P32o; |!Z1qRd&A3/' ޴K6XOP#YI= ReCLGY*ٺGWACʙT,r>R34.0_)t3=DTM)NߓN;?D@"qy揿9a[mt X՛<娀֖}ZTϒ.R;7osv1Rԙ'2 ,8͚A{/zC'4R%/ qc|9pCZvwbL\8Wo(aB^;.J6_IN"&6~  ƀ+gEw/9yk >|drwO(°6{X^Oː`!<5UuPXh b 4x.wL\L.V Bx(ۭZ}hڋfɨ328vvu?1",Q$U"ϗhPgV naUg@`pf~^e7(587ɭd1'2KE)1Ü"1:C1 ƀ\ D$_`V)@?5*Èw)B}%ԅ[Z6B󛉁OrVR}9J GF7nq&&8\׼PgvqF %I8O>_|ڧPu8(fFVt5 GG/;O?r ` ;T*_VŻ*KH"vj:̒$e,O#ehcDϭ.zŝ  f{tt(^"p`l.ӐcF495(,.<-PYbEjY%PzE]!'c]>IMM"_a?bT l$zm!6 hy;ld>K3Sݫɿ̼B{c0O.h4?0*V~N8C.Yд=䋗!Zi~J U55w&XSFPuT}!H{@/({ppȈԯ5wbQ7L֊N@}GY0Ps{*Iy:N乐m*5 _LN@;L b~%|'NDxdRx!"W$]g_bIQ0TF1>w ]| 7{#pc 58GD:=.cMR3OB*9fϬX[ lQ)UBwvxp78Npf#[E(;NuHAۙM^IIHLc|Q$xKK $o' {VBZe&زnk!1M$ +%qp_- 4ov7RJ{ (bpdz4p{] žJMB"uꌃ\jUr#+@ ]lqf~LVAk4' $A ;k__^}\Ba`BcR$zx$1&WHt )1lVQCvo3۳e# _$-*dPB"l%ap,pQo[Qo6 0Ud Ezlߌ7[ 7:;*iFnȲښg6fY]O.'F % B1ВSHZc#BZ=鲙8e4 > %NB 1 kOv--^%+؁@zK}F;C7// ojw`1%FaIAxL XI_@^yKRܝx4CZ Xo^+WhMEC#@N?Ҏ*i_mߛ74V_5"lYbqzM1B@PCxfhЋKp!}zQ,V[VKDb!&M )C]+Wr1~E1%8r=HWg8Tz"JVWaqP%0 䝔 *xD}11g-ŌG̭\d1u0i< H?>ެnLC ӈh KY ؙx(9w=`gK¤AUu**dH)$# ?USl /Uhd@CAɊ[S԰g͂&ÀC.n丗n7xAj~+pơr[Cݎx1IR [%Dox!F9 Q+&, Nj.Q>Xv-p'Ea#&q/V,T[[\^P^E4>~ R=\]l6ݞ5rq##28L*!m>hsw}Y%Ӝ7;><ܙ-K{\ /)*K|V<z]^P βG0Kˋ46N3ߐh4.SoM͐ΧNj|>S 9j@eV#;iMxd _Ƨj}zͨ NJ'Ay*aDz=4o\a&}Lz튣D(TUp71(N~j 6٢'zJ|'5RӣYw]^Q>c#1:-(d!$C$!;#C_V@" 14SP) Pl~ '/8]ΐH Ǵ(Gdpf5:&R9MFR7n{߭8q.&W)q؉p n=bk/5%ۨ+мG)pxTKo5ݯzcm+ R૰m(Y|zM~0 n`֐ 3Xc]=#*DD勖a o;JQ7<0Od&U3Ͳc0n =:lRi*R_K[ŽQxՠtEAaM>&{-P[TrzOY_jJT$dobq$pD8d5-v6@ׯ^?brMA^h`4coW ِN[Tו8s.0e›W?[ %>>%udY% Mt?ދsRiGh@Z“\l:m\_(a?~k5^ *d[L?-[]5#v'*4,Yѕ%n[z9lJ-Y /n#3!j\h'h#ތdtLJ>gƢNG!{qn_ @_ `w {W)=0>nzfrqwmkpAKBTdGj97F GR,4n>*C.#K1+wX9: Q6+1SV(+{X RLjX뭝8g'Q\BG̤w ȠM 㻟~O@1 kǩGk.vVUeaNhɤ˙y&PAjW{gDr3=9W3 :´ƮZߵ䭇]sY5LElz~t(J-»6uuv~v#JkWX8E؅n!ȍIW.ۭ;j8!=79$rD&0-U`}")Z]3wtNJ?]2A_6}-C 몗;&V+*pA PbU”"@Z$,B7!T'M#@ T:Ùc_ga":b’z "Td.V5Гς>;p CCdž()&<gt*jFCh+ޑ?aiBJQiT,#;# ¥ _\+,b@ޚMqg 9EPN L43+AS}FB`zItw[FGOTTcWѨ=cWz#w6W;E "Fd]0KygWn+/&ג6 ?\^)w}vr> C^bwAB. GIEĨ~GCjȘQeoJ~QDʤl/n0f|gZ?}?=/}Ky} 󺃨e}`Çw`@SL@A܇Oί,H.dj2{I: #UD@QdtP.WX,CjR"a6`Qwd* TE% t|=RN^ P(@):a!7m$8M8iCZN @ȦFLLm$; UcYMxeB;@Pm]ӟE߾SnvvV\^.(E GFBl킸$:Ѷ5P<>uW$[6p0f!ڀAG\޲<3Ԅ,D>#3Y_ U Q2=(e׏V U񿈏nZh3y)PyL&Ԃƭd("'F";A>x8a0&i9<)w.:Z Xh!iu"y~Hw/5N17AD QlBօ]u^\bi@*Ŭ*Y}2&1N@&H6%rx/ 9 IF>8tfS$aVkA6#: ߿FlckYq1l ):a5<'BX8*sBpp|8*XeAFp۷j58iӗ9'`HT+oHێY>ѥiz쐬;ih?୎J64mC0O1~q!49|>Ŵyl-ߘ&E@IDAT)& HXd:)08;tNKTb QmTAVC:$M<+ f Pkгp! }D4ZY3e;ֲP0(M_&ы2LJxwI('u!{SIpTtiftΖJC2n&0I*s{v4F  *=6wG1XasB,oW}Dөr)N:%AYJAH-xsCķעʺp'PmKʕ"&Zg4a~2r5) ZI[\ztʗtnG0_37AO}O ]5dy1((=RGGS;6782jh< X˹6}g X ^YLN(3!RKڕӥY\G0$0tc>rx@̟.n18|I]ىve&VBOs 3wL +'/ Hj_Q0<t̰7%q%iJ2=i_'H:#AwPf]cGgv|Ď&ѪWK,wmP֌Oc5*iktLڼgۥj To vߗr8_lfG5 ?Z:tUrҢB@aٲ/ˢ&P x(n,MIdqA)3;Kue@L_\ll|oC|`#.ǥϢ3mS(y}ecA84_4iU}fShd=~ ZEI@r0Qf8\9Ȭ.N(kG'C3<U vqbVQN2ȸRϙ︟.GTɮtpZ0,'nk@4?i{b(:N`˥ g_Y{H jї 8rlLF $qLv8Y1Q<G} heGxC=I +u00 3S(sv'6+x7&E :[sm'¾tĂltњ]h>1WdA'C~H4Ad̮IK[K*Kh&QIՕB<c^2Dw{=׷.1 䅘c;&i9)R5fy\*$hɕQVY{B(+Dl*B{ŕTJ1Yc [h4w|dqV(ZHAmH-ՠv#E-%ѩ@+s@`%NCs Np~E0F$Ce6AU2Er;*'p-8| 3*E A /+E[6B*dQ7:kڎ&c4r\ary^_Jm s\@l8z'g\f%| ؁Pigc nvJ!">g߼yttl}P0rj)GHR b͑2]ۃ_,D%!ˆo$5bZxDeGG0a;kMke};=3ԲPk-sAD Ds8";4t:SqK zkp7donм#nOIU(Z  '"ˢRXdЫ(r滑;"?GHr6؎&^Ά,K Eke\eI"|TImQs|6 e*:"q:f1sDZ/1u!*&űI"-:IvEʄevTCD@@N֥;%l7FL`xAG/Vճ@-4= uͷW*it6'ߛ q ̯+-'^ "CPF0+ѓ03?=@5-V Hn܌_=C& 7C늭Xhޭ -J ;3`~t'/,@9)y.5VQ%ڽ˾`V|=TZ'2yɹoYbvlSH1 "ABAvz>:CE5T/1j׉\Vt e鍭DCfw_"D_Ir6Tv1%f1Z1CflI-K5dz6#m,,fT`-y۸rS0h?*Fޱ"y Tpf+,$y5Rh+ FIE@,HЀyk-%ʦ`wG8k;r4ҁ_ncqF;.++ Oj/@\n a}֯i2v@b~]'= ByaT5ʂjf(4NB[[qA›|fii5L*Z0!@VOe9aΞߊ<~ͧy{dr,Ev&*[ܾcWfwxEafhD^+V ̗ed&29r?1ڻ*LهnA6a1 IEՙ&’HBO#r.l>Hkj"]\1-߳|h Uiq<8dL`r>;}Yԧ?~>4K<86x~ ʼn{{{ȶT2z>}mkuL*GV]j{[l[X]keTHb@, ~Q zBl4i Z Թ r%->=h)@'ZAL̆Wp3gz^OF >!^_RՒ(&BI0 H@څl0ڴ_9YC!#Efbg_o93`1?dG;ls~dX+eCXrE5LaX6 '+ Jb/Jn$zK9dfDUYi d۝^_]1eߝ%HJ''|fo<&RUY3V2ܪt/ bq3[-Ch1$l"m`1+V"E!5xbQ[цv< f6_z4WBM_E"@5lX%(гYik8>Hrn$K*J-+w駏6FR Ba-Le8e j~_t68Y uPթ[d 87Ϳ}77_}lmf˚;5';PsiCѷbzR3KDe$ e#>VBM#5U< Ux{ ymct;ð7cRةQT" j!M] 0+~?Fv)3t(GWux'J ӏ*)1T*<=8Jl'c; @Qa J5b9mDhu螖MCZFDܓ ,J“#Qc} ]S!o2fR &ES'0>0T HLpG vD \u4B`‡{t΍*Lz3ǟ#Ad#(w/|/4e@ @gZ+c)J,%-GpURgiU 03V i `{9ݔ~_6}2#-/ā۲eLi#%2tbbM-^nORk4=HuQ4%\ ~hoV&1L.ggXC2'.&dXax4U%Dph@bBI9c!!9JA蜊Frv"*X`jRa? 43CM@^vg7S)e7o߾zmMR" >O1QFUOḱ\_}g(4뗔@B(x0ΗN>``P""^0_1 )>8SЍJP.P"Z>%%yYy67$@Go˗0 <eǴ;"=̵})_|\87{>zC 2r"BXk[UO3Y+fnd0c !nӈ QIe$dv5*m($5(6u<cJZ Jo_Ye  %<­\7܎w]Vɲ+J[&kSmp,v4Qڞ˖QAn[ i͠GlP2i6aYTd4 nʣ6T-l9]% bP/0VEB ۲1xV%FvM8%lBs,.<:qkk% ~8zML˾kTEN'Ե\vy]٘0= . {XRO85W)uH9+TَbΟ4QJrQV M65N"ў2A`H0қ.}-h4aȚ Crk٦= o.]ߺmFj~\~6M jA={4.%G7C2R[;D3eѬ~D0 $Zt (mF40fOfgR;?Sm|JGkxDz'uH I?,%4Wov_W"ƴ 2-;;_./ݏ୅˳u.T-Y-r3"PXDP{ArfG-16r."rbe(mM!aIs^ ITDMd&7qG3=-#IyzetGm;qp7/gW=V,7N!y?,QE!iK++0 T$y̶[fvŚ-:g)o:yzؔ-|}D0BWgl;܆|,}-%0%*B#4Q3Y0 "z%k3h Jcwx~ +sTBŽگ~E ]\j#qt p/!V+"OSQ*֓R^'dQ@xp4*2( J.@4+S$f:i_i'ah 9s'g'' #f!಻w&Z$ePⵑ ֤:u D/-k{G,ݶgj%[akr6A8lYyYFL?'\yB/Xo{ؑ!|:SJu{RyLt~ݍHj7 p_īlUkz< *:A'ܟ آ HZEeSߑѸS:;zD*`h8 ۞ ĂpSq%4SULQi+U(y-5d3fe(gJζҨ&`͗c Xc$} ֕)i5 n6AX5_]tK`n(N ҄U'e'-JHUH 6 ~Tt%FղTQ^zQ7'q_|8=Ir g2CPDLY.XĤHNʱKð.xu{lgr!@1/[o%v=¬[Vã`Z@ ꗔ]7~}L C@#՛HM! 5ds\dD9zڸ0 ETogv*Ey뒻2☺(煩B]ޖkYF>ip>R1QBO 0 Ɠ1-&j9< Z;w,8euB~d1hm #t[PPDo*sJ%I"yU3Ph#RRe54oq:+nd..M54׳;C H{$߾Ç|qgҕR+o8> .Qz]R(vhFq7[372&5#W#yVmY6V1TQ:H/> C"'&${F"m5|F8*QW3(ܖP"[J{O+h)bƼ9)zn:_I\j}~W\@\ĴѹWO^|yܓ }3Ki q3Usg2{Doj,ǟY%we1]qWǢrP2 aԙeDIT=2I1=xf.&F)TbݭLȁJrhA  {+A޹÷Syo.+U3U5YY 0+hJf Dm;j;Z.FwfL Hj}brML19䅜.ODD hrm8fTZTuMEa<R( HTIPXgCr =/wPkvyr3=W釁˗ba8FRH.b)#LV+ʆRر(dKM%ٕ/D^kxgvK~D,\/&4 |xˆNwڙpQ@aL t`Hv1)DPZ-n"n87"W S$&Δ(y@13c9a-<ÚlxMI,[N +>T,ՓĪe95sEBh1Rs C;@L p|5taw'|Ob -?0qS&;8l%-8V,}|BF rп]"5( |<޸d řR6݂cl _ ,3zEWma}b l%!}kj. )qH]2{n:DbPFʒ*OEZLI{U.Gr“]GFU _-S1D~0nbgM5 r;DS"W"e_M.SDB+%-ne1CP 6m F]K;W>F8 Lk:)3@8옳̀~KE *)I斻JX"y~, E`2tAx+u*G:jY& opp[=>$%mHyh;+7 U.[!Ic-dX?qn\;0f:'hpO6$" nR/.O0M_]#|3HaD<_;7Ex0)2S::b;.#'[@>|@]@s ~ӌ M C!nJu$ȓZanwI(Py8 ݶ4tb[>G SY +B#Dr^-¿"`L7R:Q2?low4߅?&S(R8Jd~;|YZ`^yi<7ӏPck~H'ȫ`TD{6#Xp8m7F(SEp@Wc?VgRiRF8̰I134ofNk3L+A,"S(>9hFY g s. %bm$/ $$Ց"RU<7p ANl$_F,c;KջSSSCbܡ˜hnhI'8WEb%`=Ķ#%Ʃl r0+$:F2..o̤8i`Z™_|>|sIW\CНMg@UCB<4~h$pO`}8SŔD4SVfq, _N>~sj}`P\`|OQm4%vPSAk@ѯj{1\64h'S`bDg2Ǒ)cass C 'S᲌-w`i巡_`1kaReun.)dj@ zKC I}ǡkzz/8$9  `)Wr<2mçgfu㚥>N GU 3dѽ ke G"cb Gpvnm1q_{DSpV/wv;)A *(B3S[=5֒w85cL;A\#u@\ (.6銺`IaUh;x& #l..'WiO"+!l@v:<,t6'X2B(MȦ @1[0q`״&jx@dyN "hFCF .4䒭}@VKҍfIKږw[D<%GdB#:x BW舅7j{ܬ7`!ep_IV[T|toPB2s޹<u &Aݴ..~?"\\+ߒ"f,)r .#5)g }/_mɈ decx)#!5g u;#⪂ Z*p>Z}ge@އߝQw6=wͼ9/Jd-iAA^ɼȥy[. Y(݊5olM',(xbPɻ[ނlc[+VEb@hQ,`[Ty'hPAy!Qq= G{n%Q| ^^o]^ ) ߿u"[ID'k|DH/ NsSU&=4|C9mjYm TxÇ?|: IMnٽH"hH![p*&"-l O˼9.ѿH і0ݮ xq6(‘ FVA Y7M"B *kq{r\\ZaqܫK6rtO{Vh2f]+"ZѰG lTT bT;nDMMFd1Tt~^_=H9Zoo U!FfD7/2{yuFrLzBx]g!#!ފ& 3_UZ@ʲ=GLEul#5;;k%L$^,Dm٬}E5ؑhXI|ɒ3wl9S%)"y? `oF^(J/vkV0n<'&Bl)З?1 g ІU"@io*%bR=|AFߛ͚/񯞭~ ê3KRq7м:=c25c&4Dcijihrh<+ѡOqQ/11Mv tLVOQ낑^Ҧq"bfф5!qi$Qnt{c+*43V)0}Dz%e)nTDN.DkឥDP#8ː2ל$iV$ ȷR=4+J$:>z?N^}Nl=|9 ŸZ ."Ѭ,ff$}9@xmFZNИnKGJrz/<tz;8$4Zmkc XSaKXr;Ŷd'I;m W8?j=:'qxAX=P"n]NLL` d7 Tďs i Y\9 V,K {KeBђWӴ17G2] B)bnwʒ?Р1.^]T)$;xvބճAOWȯ gEI b!2Gs$yg0oUt)Œpgb0m;1n,H2I7AEJEKPڪKZmP4! C[e;l]zӧO FGcFƳ4I=*̌K"C^@T=r\{qqXT.DCY(Mk $nJz:([;u zDLe5^Ϲoɼ<:ftaS[ \% ŋrtW-[\DP,#E=R;V[;*;WZm^:h\ꄴV0lBܜ.Vu2L?>D*w677HCJ! ߭vGQJd"(W+nTѻ;"q͏*H mrDɮaJ(\Nn89]AJ>jg\]ˤ.snҖj ݨq#2QV5 *X֦x)0I27 l= 1q{ͤ/_0l3Gnori{Vf#GX+ фn=(`/h휃&gR"|!#*9]vW^Sý4:87J-ч-H{_ :9, 74ix.aFcMtǾ$1N*&S.gC3}KvɆZUKЗx(݄؁W@>[٠[hN /,I 1ui{^M};_yC뼷5c(ܡ>]tOj_j$x6[uD[>: y>CV"{]ch{sJ募2Y Cub@b@$}~cru rsT}V͊F%x) )5 Caw^[HV YA,32WH'4*vKXP5X%K_Ӑ\9r sroVޫi#Qem0LaS* d2`K>ٖuLN]ӻQ!Mo)?zpn1O.ؤ@WLSІ/ZMxXH;P4 j6Z8 =٪X=;;PBW&m 2HUNb+B&@n_߼>zbQV̶|,{۳?ܿ> y՛Y1$4RNl6&d0 fYɄƼѤfxN980T#ݶZ$$HjE4ġW Լ5 !oƓ'W*CH3/ltu0xRk{/r{4fyN>C.JO݈wDd>ݬ i$e`gjQ[ '} hꂁ,'!j@-à7j D:Ӭ-|d~Ep;1] d%U4R$yS"4IbM[&% >{z6ӴȹLIꏰ@LSƛ&F#D\$oˉ TH0_|ovUH@֥N|j`q/Ua-Q̭.@ښmăvsyǫ^#=doHvM31fJM ӉX4XhC Ci'i9bE+}O'G)C !nf p,B?lf# \٤;$ Ń]-j ĐpT!hh)J18K}hR-8vg(Fh(WHjAHs.0;= G+W;Y* [8kB!1 B4ڜPR\RXgh,t"ʬEO-6/h41ĝC8hxc#ј \p;_GP.Y]4".pj=39rf׸PPXyfLc+ WӨZINJcŔ .VD0M^l Ux ux隸Ry=gI8Kp tHh-( 0>L82#4JdI]z~0a0[4rR X2kujdl ,:4IsOZ7#g% m|liܬٟ|>|XBbr܀;.]O/.-|9 NYBN5vYR4NtNA-U(5ދk775kq,ICO&M2陮|t W}s+;  4Ӯ\:z&]Tնt<'7( 9o[qm _Ϻ'(L[$7V )5#2;8YoWzltgSܸXfhJQ4> cڂ 3_gl5vvLI#48IB1Tw≁T@@ܝ-ʔdy{!AaK@fSѝ|,@8)co:^B6[6O>&~XT*Ja6O?x~y ?*g+`$SRl)DÞ{%v;mfJtk,],C+J΄&_cZl|kkxrb#m45^oi/y~p re5fE)"_oSXZҮg ~ DLcV5aBl %d866%?kQeO!WXh2,r^|Ngs9΅WT-"#A)C5 K#' |HXHHu r˟΋ v*a8˝j.o ? zgղzLnP3TUjZbz«~5j Έ D}糺zԞ*o\.:6Edƿ/w e՟|O"J_'@a={dbmhP 㛛^q?v3$!8FsS$xЗg8<*R%7c\qd"fOoPEftilnQNG!'re:MF6Y$~ן!S)QypܩK`o8>H.S8w MUPx;u\o0xyFIGEN01q ӎ7fpq"́ ݻhrS_FBa՞aRc GaeL,=@n I4f>[?4#s gCTw?ܯ?~|[,͋sU8m@p=)䲃lM[Bl#YCf f9`=exsB=P";^V@W|lj; A7>GR{;Mrh@7? ; {\oE=fnHT|U'j_D8]oR;G%z?f*TXK֔)%A~8L-xcHp4XX 3ɏ#ry# Wxa*Ϊنfԉ@5%Z|ӳ튘FN%~R5N猀kcqvŋ(*5ڌgHi^\!`5:D`6Xߤ+p@Mqٲ$"r/fj_x2h1l{aݩ M)Aae"/§6F^VHB6߬=g& _S5Fss΂~^9ŧeƐ^WbKf69 Q|f4 /_6{%Y/ö\GV}> BYﮪk(f~S r%2~RiJIΦ"q[I@Gyjo(fޥg뉎JЕJ&m/–A gAZ/KJ)8fN[ !*OhEd#8:픟tE,Veԣ,"ok ~ܞ%FQ>b ˬςѽ8FL= e4dvP+g> ߏRGg l@vtHA7;>bj #&!hp Bw~0ji"k$"!XÒ2}vAa\DMi)L[ҋجchʇo<^Ӣ /үECd^.M3 l#zBZ*P=%+3dyį8-e4``0\*`gPoRAD 9%Nt6f|a2Hȣ0MT9ٚ6[˹ Llr1Fn 0ʓ9X*LN$`Ws}}Oa y 9'\PI%7!RԬ?j>pA'Gz zNRvH7_B-0Wñ}tW`Stԟ>Wu$%׵\%)Hr8:Z(FE0T 9Fq@ [*Q~uZsD}5#'|h>PP]rtT{LBwe*h 7zKWӷou_ɯi_#oNDtQ=^%2 +՟^YrݳN;t9Х4:+к QSѩ(}V ŗ kG,C⬆D`ȫ:[)d6Ӊ* >{1*и-[+ѕKmClmQY=^HGP!#LMfRdmM;087-*y=b q-mUoHGV|!l}D, N+Mdh^z6_2 %tv1qwD&oL!L#y=0y$eU) n-сyB_ Ή+O/..~-[axXɗo~xH4^HiLؚ >B)@搆iQv;nP 9/s)zJf9#oe@ қ?܃ݱ§ d4pG*0 w|勖|Z7r}S}>S3Oe$D9:F;rׄULaM" yOtfQ A՘B @a0-qR tv'ֺzN;'֟*7:C,'?A1&UStem1hco9ԤYΧ>Рb5K?LdBr(ƹFĶ3*[-dSH:Dg?l',_X+hF\4?$֝%Zką$]ɫW0 RF2x5d"mph?RI9cDr%@?>Nk REJVVoÆL| 50xSRFO.0ZfXi>zZHy"qWRћs15& %!j{e?z˷?x̸L\?Emj7;؈8JT !.S7*7q : "p/#t C`V&`*6"`HCJo lP̕bĀP0RDTǂC$ # Xg9mG9lBTOum7EBLSl1H[b) 6`rkܠ$d " OP a:}°uDi\!JgbC/;g%v5|xY4ođ>C?.8W6 x=we1 /"H#05ɯ!vyXe=5%`ޅw R NIt"U;_I3pc!JԾ}ߝ7莮Yo/߃})߃>5v|;&1M3qWv +M4 JW~ǥg}GM}o(&imBix}LxŢw5(+U~/z ::VH0`VEx@E,3`}3p҃7wſQX ܔIY`>. tmIA/-d8yvl>V%SMo.9AsIo!I'ϧ1Q }];# !pщci&H_3aZ@k,NT4TjI$^IaQhX, 9qQ7s'B8|J^߉E) SЏT,2TE1o"Y~D[Ф$dŠoi e]ę?MP.O l8l: cM &?*efA@" % pcu'k6^@{6(Bi;u}jkDbo`SEԠgdGđsҁ:2VXGTZ*NblpX(7NQ(&Q q4#/1n9WO+<8ApvS-a@0#ߜH1aw\jB߿-E8%&>^()Rm[Hfӻd,}ėP1'H@_8DR!hbƤOFvS+±YmIlaX䜊deE9M}R2Ib0+@ۦd1cFa DaU55w`:K⟜;EY-+n@3mGA񈾻ngz=KgEA+xx$TPn$qdX{6eLyUBHL%Yffq`2#̓c 4w-\~ `("E䝙@fM8\g$8LT$-R?˫Yqt[A _PPcr0;w[ec-"i,"cy[J3Z"7@rK?,d[ 77=XYK럍Qԙ'oH/:ҵYQ[hXTEh }JM\(۪fhJ ]1&JҜRJ0J$DlwgEXV*yfe i0 (!LGH$ gx26ɤ@6|ECEo $JQQ6S&}7c/~,(8>VlH{pP/ `-29zalю!u"7BOQ2H7Hi'Pz>T JxYa DWf5)W'rKu}cNZ$uq'WOK=hS>_nV/rx9C.l"V$a)HYGJO?ٰE^QPGL! @AXϸolU(ЋpfI3Ǽ[ $'UB7F>ҕLy1ԗfA{vkb#\4ΐ /eA ̝fgWpRkZ m8jsshQ- Sz/8{C8\H PB|̑C 2lyQr T Oqcrٷfg W($~tOq3q;yw`yT%v-]b}ϿG'Hg^R0!#s$0>!e%b Y¬btn) 8# ω`c bDgiMӆg9i`oM ?m]e*x짐7h0:/*2 ~:EBL+ 355 xR3l_L%GDR@̎jCC>t;eI$%vё s3M#~bZ8yxeK - Q8"L|oԘ`I!*ҷfbNx$bXG0gw9N C_h&Rpn|iFsd&[G S:8֩ bn2Hihqn>3Y29 ΅qWNaŔqqt|uGٴ{+қ{7k{lq]>ܝsbzlN}] QDG#A<$Š- R c> 9N׭.,`pOAN_v\^˼RD' *RY2 ̸ tb-Tр`n~Cb.Ҍĕ'd=H3>9lF<tBƚ+,ݠK6 1ﮖ0M A Q*@10v5,V?'4gQ0KPS&$"HI 4dE;Pww# ?zm'C->|U̒R-~wD":co5+u^_̧ HUdB^ƻpTrJ֕ C*P0j}k̘%ԥ[3ỻjC{H(Bq,'[Aڠ 3Bf3i1ˌGQ8z4 wvǒ :2[8zy@LN,8*&C ?tL/K%YKl|@"&"LP lNHAx HɷCT CIȋPR dCn?Os(lqY/1Jb`-~J`U$)l }l;,W{o(%X %sX8g ƻ$g@usx>e&593Oe1b`c{CyƤQ-Cj|O[ Nj^vml*zz'A:q%{ﷷ7% Ɵg`cjcv'z4=v","??芔yK!m8Y'H+XSF8ڍ0?|mX+:޾y8H!>:NqfI8I8[ox#qʼ6$gLc+`:B- K& J(!'Ai\F ݁f%¨" SZA澻MMZܞe NJ»iX$x& ~Sm zD[$]eldxJgs+فۡK yhA{ic1!p9iBkwӘb;X[jC!]dpEZw5DQ_KPF!6#ңOlU;n18,B}8 >MgltRtJ@P eN,-Uy["̶c[Oi_4>xd ѭ9@㐡_v?3Dl ^ڬGȜ5H T8P@}ˁew 穾"]p oӵ$nbHS5^P&P|WD29t&-vڭfzQI5RHr66<%ž:=RQ ю_b|RaԖW$[u 4g`@KCx),-` uyŜZ..RPi!#@le899bEK^z [#χ:!_ZO{Xj K^=vZ/@!F!BVb 7 5_#3`,ZL˾MB]8"BW:ΙRy<8 % )hSL2 -A'Yfg1SģZލcf}<ºzlh Qe{ӵ}hG7q<ސ}nMRAb k8kZދԫ*ނ·2H|[lAV/83K+1rZ6+>9FE7K0]tdN {ý⦅ IV*1C14:|=ε*bu 'lƋ3RҨ8ZkûԔ2K$QLaJZ%9^^);$Az"jK Gē ظ %@ٿ h8xx-eh.#C[uԉQG u1!jWjK$^5k̒$9[W}!JK'3WTDF9cUr09M7?~/^a顎ҳ *qFf+rP֑.pMVCVZGM̳/R)e8=^kPD`yWָip.0bd 2,L7>M7qVuea`l7X%3#pSK3jDOeRoU3mMmtUݷx\'_}f(v?`Lxr_c껥ֆ7@ *KudzHȪ'fU=D >[l=x[o%9YN'-}bHp@uktzY򓨥r³pA-pHOrJ$<" @ LWqFrcg5f5~ɜI;ux{Խ2 n[,: W| Ef'%a9TƦŪaZ]TA3:n?ׅn>| ;A8;fFM 'g=_0ZB7{6ΖwL bPl*aFΦbJlg\#0G̞ KU*(t$bbϢFN/r"c[ /]x3o,z ;0ݢ $')mgI# _aCCSc,QN@D@I6d#ѧOwFPk]6SM:'z$[>X׉ :ěgŔ7/>|~V(:bo"XkM ˡ&@Ю:ƉGF4;7pW8&;#Gۛׯ//_ģx ]RA0~+NUuģ~w?Őbkp?9Tp? 2}{?5}Ɗek 7yrHI89>e%NU w)6H%Je̾j]l RF;4FUْrHG;U0eBԧq-(gqRKJֻBŸ !>b~n ߻<-Ӌ f܏h90g+s&eBSsyn,B/b *wC¶qs?evXkÀbuicn$9ٹH:6\=Qz뛯pSA!7W,_E>\@b`#2$&30,},($ҶdTJ/j<+!\nĞ2|IP oڀ)^6{ZPH * Dp/7ߣ5&e29Sm5NbBog7%A2h$ Y0[ ?X" ,Ű.bAp_agTKs-=|mA0DN}e~$WPyN+6OUWw[dnRpnqxLyZLwuT:Ι qC2FdYAH*"nvX~~^FSX!6GO)QK=ǒ$ǝ}J;A$3S؞\Qc|7U#Ւ jf#sÔOf ݱǏGH`.=+@w9Pj4^q[Fy\'5P3= ?E)*K,281vΔih7yzk(`/BO{D1L%T/B^/T !*p*HWSXrSUc)iZC KW@MNKnYMsfy 32'-F#C8`2@!ySy2]>2"+,iy{3HKc3+-* C+jf; `,J>/c#pEh`P/%DW&`pUtUg5.7v3(SOƀ<ŋ<3Esrz0SjV{_+t}!Lę1K iG5%"T25׿ӹEHrJBU<~XKU",Ӭ@hijQ/1ڝ. ȀF[2OcsLok*w]9'7^3<vlQ Imz~>F,k]| B""a/t2iQ,=:>!I21->N\%lM'tJ5@ _eI]$oniUjެ*qttCq~ISe 9|N;ع.O?OysrĠe3MXΩ u#ɎFKӌ.CJfZIedD=^=fM 2(UtK0]5oyvb?%ߚ3R>R&˫+9M2M#wk Zիw-86;|,n =ft f/鐏L۾reaЧl.'*jrݺWHV˳iڂ!nj|w><́:7#f.rҋa j8COЃO.3&oj YY-7'C`O-Pep` άۍ;&*1xbn‡2071&7 dpjb\*$<"ikXT?|`p4J_H){-r7Sg!1bme '`Juh0X#+ 0czI!9 JC{|B~% q̭G"[/ww.fsn fQsU;le *G.#켰%@]X<:MAdIJf⸾{#)T3g9ˡx yx?.ءikT%vJx,0SStY0,)A.F,"/R*Ch`9@D>&~ 8ld)Befld 'T 6C?jYN3| gjʀZ]ϟ?jA\cjf)HS߅ Yfi'.mzME<$ǻ {z_` E|,XO#^ᜎ#U͹BIj]rhqL^T%P\U%t@ch~02ŊP# ~t>UORI`RcmƏao7g`"#p4y\"$P+pz[ JN\^X'vBҫ`$pF63AHnۇۛ:ZoiǙЗǍUN|t}5=>=U<|B8{ӿyR2Pͦ7w/^)qz6%:_RA;֛v5ʳ΀u8*K5e}~ =ۡo7>|5Hnm(7N0z6):%pu-aHDž|y+֙Ů6fO,bfHbADBEƦ-vBS4"BUHR5ShX(rkb K) ~ĭ7 7i N ^]K$C䲘LX *gJ!ڀ]&&^"WX,[N]*P0G劋N8!ӏ/ w'][ ;xzCS^Z哙4髓SE``" Qᰭm: o"&'l0E6r&ׇX!|'h%֩+)l ,Ac%,eJNބз/!N//^?G N# e PEzԴ^2Rh`qVcu7˘~C >e3]gnB5$Ajg}nOa@=l̓@D~'?}I7UW `C ฌBǚ (5C7 Ȁ? H<0|S=:_^Pe$Ք5mS#d^=@t@qlio A+7BҢK f{_3|>CKVU[r1ֲTܷ \5! iSu  h-N8H Ȼ?X/߯Cft t d?Bd/ "%f9O Q$n0-Bi,ƏNpvNmɤw?;wJ ARJlwR;ZS̢0QA0ˇ_y )ɄcHV-)0RdGξvܸ φvHhE `!flhIj5߭#ީ+ QfśhGwTY"I ]EKva|(\Y ѹ'9J;aAVb`idj OFE gb#R ^ҷa%@ōEpf7`Bf{, v {73㜃&+ bU@8T] &jBg*_Ua-v5xg M](= smbNm-{1Nȑ0>  )D"M[_o9BH0kyHRNԚ[jibXP&fwVOs\H ʱڣ ~ _ 2.p>7.^Bs" _.ꅚC}@&빬 4 `;6n_z%@ᣐ_?܀O~ӟ_F5yIۥ4ĖqN"LmRjp<rM9p475ˋXP'ڠ.PPR >Q*X'(OV \c"#1?=);bAWr0 磱89bRiYAk0дF?+P4'K.Ь :\ˡI.kE:a35M?i`p3S4gVcKȆU= LFoEpJ'JWMb$N$AڟL|5 aX.9GK\3 h]v=7|<8XyyK$\8хT>=$?ہ6Юq7!I hIREGcӓO)c4o# ـ8S>2E`ڵY2q=c rC$(v<[Ƌh~Pݯ^{i4K@Q)[0j `ic{+'iCQ9\ZHR"ϛ"&As׹wك~RCՁxZ|BtU$.[(eè18W j8%ϔx'c^6zhU|LK 'Pi]YScϝޚoZ \'M0%xT8n!yVa9OA[8(dfU T27.z~y>?>%mp{{߬/y0ObRu#+Sߔ Iݵ׆Id ų1D@`p+~{9ꛦbiLD AtPL긠F#yFAę  }!;T2P_0j+& `~j@ |Ad%pZ>hIy%=Y83R @%'9_+, -„J#ܫCanQ2a 'RmPO[*N C Ct0@q@Cl5\^`pN76[Om1z;%bV)&<xR 9Q(-~D- Y&KhH?xd`\KdDṫϳEc|ѻz xd:w~/`5&WrWnrÅWW2W^nPjFXR4l/FтhBI!M 0hz>a|l `;+u̞dlg ŠTlM(sZ?:k苓- z0"%qz#zR%b$Y cvCy,_̊.Y lDz6}ϲF[؜q aVJ'%`_@R2&\dzFEɺWU_nw`-^'z\;m[=K ` {5&bp5U˚ a30i460Ka k{_5譤$<0绛/~@ ͢RQLĦr,P͠_1^%&`\"^IVpl hЧ'OO!ј;E>=qH*ď W BPx bADU I\lɲ!B[ 3Bgv9 lpr1' Ham?rB\s cbDSktϦXė־bD4"pQy@W HQ㵅6}StDK LG3j Ib!yx}9Ѯ:kGPi7YQ5(20!yaLf "V0gT} ~~Sv?Rcޜ``&9J1QrD! .W苂egK*ƀ5,%7< sJ{;Mث/;dnK!>Š w7<.]JQoOID az CIs}]Qԋl҅H|L1ƢkHh ԗ--]H#pOu%m@΄b!B5t ofrvM6=m(8"1qL1]zz Si={ա?Kۉ`P'9]uk5TOzXߩ4 g-g\F`y^ !G\L4+#`Wa7ȋt&ZklQűBT;hlŧcF-f($nrZ *lޡk6<*=eܼ\bFiX֑6J( /z[ e_M݋W;6qMm"O0p=x0>=R @L.d*Bv-A5U;Ǻf]gwCAq%A!ij?رUdlt]ì%9KжnˎSGۭޮ]K~͉Er#ly`XHgosrŲ~Ё>cE r$ Sf?(/d; _@VIKa2'A!-ƂvyNIqU!j"r 2^q _E ePJ L]@Ɉ1GIzN,DMaK)VA-`-a ςu"1"4Sf6/g_.2?k )˓+s A+AOz/_i*P(I.!p\26 B5ww?؁f`VK(%F# vv`%J=;jdn"#A'`5dkfݘNȹqnK<dux{&#$޾`xGlI! 7#"x,sn3(x/SDO)r9|uR@p| (O} bǡM[_|bc(1>j[u`oOIk,{۬-**VPvZ!ү W0q3ßQl0;FOcZzG$Kڐ&N^kVm%0C#H6:g&4m(΃@Jŏ]_d1v OFQ VJꕍZ[+&ÏMO%PCC̻/o^( 9Wd|~)< f,48qX [T.R .V6;L&~%<2+N)~%^z%pM@ZXc 7NaSj Yh-("9.,'`T̉ӹS)64hL i g]C٥}62EL?=w[A2@xGX4%M d(m[ؗ2D̢VCث/q/!~tw-Y9;UjF} #f[#D CIm 6[Kj+`blSVGi6bIÈDs{bkpixBj;kL-IːXwg̣#&UWO6|a+ٜgBu-XӲ|*N0?G_AӨC Q!E4[B1!pBivS9oޭxUZY6l;ꈼ%_D.-)4aa T H J-^,ʹ@ݍ)A;lIN%p^V7dCpK$HFV3dD'x&cb>b㰞˕#:?Fj[9vLrR Dv_JcNJCn_^TQATv,(I Ul@^[!-%cӞQHA/[>J+z)loi=;\6;q [,T- :;`vݟP. mu9GC>+Uf"X pf`􀈖᫂bHkhIؽD{w.r?񽎼<@JzVl4BHy*R=oJ+3P. d㲻0br@!!Ha0N2'T0LI*a1’A+0DC*%F_|&59۝R&aǢY5KƆE9 ($Fjvn'w!C!,U`Om!'hYD7~t0tYY*G1#8l^i,]zlVჰ!R ;=%̥rJ!`a1Xo`z$9f/,3v) B)Χt,%qen9$$Q50N-?4re|9bXTZB +@0w`b(S#&=#![[Q=~| Z'B =X;H!ƐYmΎJJz@d; Y؈"+vXΥx2 ̪k< w,^rدqK2ޱ>]M?~y*A ,>8x|] Y'3ed"$x :9FG?A=9}*'N{w r K@Vx;E*eB]wYw Prl1EyaVQX1`1tyǤpPxwi:oWv%a!?kR>L.og$Fa@eF4q™Uw Z cfYŏ ?/1'**ۂIĆFx΢ζW>L Fw8s:sC\_N8^d#zcrRQ`jt!#Qeǡ6c_oW,+ͬi )"F+`dRb"~ǔMߌZϭ'}+}Dz;/a.B>qVJjSwZKBD}^NWvӔ,r6#Tg-f3Py{Xx4RD&1ubMB K /4 | !:Փċ>a%sn_lrHU>V;0n'qhFW⑼q`0Ƥ* "9BHޱ<**:z _ ny#"NN&αgZM1Z1ov '7g d̃%>^`ѐ؂>a向ʻ|*(qdSa%nwF:t.axxXr5‡-`)̺}`^3hWap-a>yQ\yϷm'-cA !^};}尛w_'E>wߴ&ISe<]0qrbemlوܩOKuyzR}kV0(s$8AU4 hQ:|T󩁳̯W0+Sp rh~rщ.o-x9kxd)`YYv`&0imxTVhY )x%H* 1'$rT_12ĽU 64|-fѓo'l0X$wy%>"=d6p N ) +z8X]Muֳϟ~lcIX(F'!,̩s#*@86,CRB'_?a sj0qW#?zkS]v$ίY"p:`ticX']eZsYh]럲`Y"!/t @|J,SֻD̊x4̒r$\gy08SS3b<݄\uw+R4fd~VBh1!^f$󸏇QNc6X)0ȫyFXxV'謐bls:l Tp-y5[Ÿڧi!kEy.x9Y4}ق(d[>i7K2v"_zT0N^8yd$;]b=dE`X 5(<%ld2~t1z'O֙4tSNT]*0F5;Bqr \8dSCBhI3FiQ[-iLE>ث>mb9M_\˝JpPtYU𩁮lz@)XOM=ko ntiocY'vJ)%"r̼+  `q0=n*#B+wR"%ѿƬ(%E]{γe>D<Yx)@t%'G0X ѪZ |D޴4|>l!BD/tP-7,R lpq4˙*5h>bS4 Dխpil1fOp &sV7]/BΩw"ĺ&ui6R LLT 19?x@2OQb[Wk(#R*pN> x= 9ӧOԯ &P)Mb..9\-`1-(ǁ(nyEa83a򭅲Ѣ?K!-Y^>E@$ mcN֡vy9Uy16w]PT +^GT˘2A(!0)M,&c6Ӌ #4'#y_RP!;O&S lyNAC)4GR;9+),5]kY,U (\`Г5IVe-S@)&'̃y5Kwb'%kIw;8g2Ubs#xqߕEs5xYOoY+@WJՇ$~[&nW{6>ks ;..f.?B g8vM`oy`43%z5Qg` {A.'橺 K+#.lb/r-h4lJoowxl(r;\բ3_S5s϶ĸf^_@sQEņ,IcSg2tFy:#O_R<eИB+%B` P8|.W;ԳOPteIv8 !HR%( |>o `0& O^n^e>~~{%X2+F~??|.B?~@$012{1ԅ^\"Ɍ .(o޲ "WyvLE|V I_(':yJ+' T@2-Z|&-\C"KLM%PZR 8qhhv# EEc1] j&?f)/)ݑTEf7[HP:hxnȒJjD WOsTIxzT,΄d=R,TBlse_>sXnnn7Ց/[<](~@䣯@X8V X#d%d W8qy6vKcPۭRVqf3m֝9+H"m{#d7|QǞ8r<\,6GQџUd:WMGً e<82}k #cBxKMfE1gBEE%A>iv"# %NY Ow 0a@q8I"輸ؗV%0NY~T;|3;S`MVu !Z)'Z-٧Xr&ԔjXUG5iB'8E5@N@:7| 왒Y ~daLDm$t/['&!3bd#fc4CY[6N2(Xhu-lPkBżո}?/g{bf|pI#V\24BϬ7@5Da /~__׊KEG^۸O%tLʇ.+Xd\CO2!4RPu>;ʺSK_lgE|fh,?T"Fqf{'J-b .VD|,(B -Kir\"Cw 6|:˄R$HƘ- i6 ޟ)iV1"a>Fh:0֠~ V E򴂋q:69 u0'FjBb=WU L/+>YRXpzuc_oU܏'~'M3@$̂L$D$5vT}C'}U;L.ۍDhiff86|}OX-#`% OŻ+>ƻcG?P?f`~l93]=zd|(|mhޟ*)mGMneCqUb?Jn7"[Ɣtw}7AM->rѐq rrLPZ#Z 5(xr<)7@GQ-R VTŌ//3>B"hFIO"uʍ\RC]ŷ|\㓜SPLvS/rżg YD_xa W1:c%qs >vs;C:۶KguYa[캦 xn0鱦d@IDATS@Sòb@kl'yU$K Z"'0#;wBb]bww3)W% >%3[`S1xV1ḂdⁱheJ)lY쯿Y0y:٩X<8]+a5ssb^8Vs&ςVXfx n"4xO OW_ s7',2J : UB %`)dJA`|yHG7s,~ <+ŅEcջxba 'SH+;bR3_4ɟ }{P]_4\oy}(DŭqI^Hޢz] 9Շ!~mɜy9QȮڋHb\ԋU"Ggsl͇,q@߯?F3ӧz7\xtAc>paB™^^{Rc@|x_~M]Ǝ劤n2D5.c A((cf_2Ԗ"+ɉ|QLffra_@)*)A'Ǣ 4ƞCЉ9 "!9/ǿm4Q켯3SU8" 'Vvr ~gٱ]"[#Ѝ]wB,t,jb@k(kG~baʄsる[ƿ"ӄG=s-*mOE`֎,`DyƈXOD!sQsx8}R"pF;ftZ㠂Sف t}+@p^k8Ors/@xqYIU?'xȲt~fĀU o Β cNZU:6:ieˌG8nǬ#{c`9_5bpSR{d>DSE`pgf âgVnW7%J:RW.G$38cd!ŕ{xm:^En47qNB$ڐK8qϟ9w>xqQnŗӌz>IɈ?;^ S@z/eP KA_Vmz2hv6PE )Rh12J ]2XzSZWnk׈B,n/Ox TeX~~%4\oE_X;Nh|^p+(%Ŗr")gWNKً6SQɈ?ˣ7VXT"&8x 0Yh$0a\q'u)H8KPSP$[ȃ1g=:'+9!,,c˃퍬,±4Fbxe~H锣4u)&Á]$)a>vfl ojeۯ@<Nd #6sIX50ӏ\+pk4*+Cǥ6/]u!D9Æa d{ˋwoZȝ:/C:=[TTazyCĔj&Uo갴Hי5b-sݠ8pp:i;8qyѢT0@(+N*Ca j=')v*7)nf`BGSi:+`2TZ^>gu|d,b\U䔯@H4ުDY C+" X9,-2nl,of;ZV*P(!VWdxغ2{MbnJWs]R7aJ ۃ.D3Q1=)ሊ=$+ƓAxu2^\L?n{Y3%=5_ pu=ልng1;P[)ءpd\[ȑbNnXd<- Hv+ y82j-aX:=Xq|ND~k*󶰌Hs]wbڟv[$'y2 &a*eJzְץ"ْAKd.,DzˆkjB5x.Dj/1T^m?(BP=Rr#|-OvW+rv&X$ H"ri_Aw.Ԫ]𜌜@+c۫=m///LB>ԊV=6Oޜј@(wJWg]Q߮Sl0?qb#ND#ݑ*P~>_\Fx1.؉\j,ڠ!H%Fw-2F?T<+ RǴ#K~Y\ l7YG^'cÆ09)}'&"!ΪZo.>olF8<i>+fȒJ"$lSbS( 3 6cN9т*]]E"(lFCQx }*ɥU(J' ,(2Bb$6# M|ɇYoՃqϭđ!*Ξˣ L C1q CZ E2x:%.'EWbW)Yl Kd@;j:%AҔÈ"у5"r{[D]e)fB<$vK %K:;v#ocZcG?v""|ͻ!:/+r~Ҿn" Ff O3` wU0lf‹qu_9HU Y?S[ RJu!e#r^s ,`6'קl[:ES0T`;MJ>yNo zKzֳÁU+sRϓFa7iU"quL1q9Ӳo\JJs E9<P^iAĻNu/P đ)Dߛl|rYLKI#pd!E| 1?A.7$}&-gEȔQZ9  \ݦ_ɉ$ll6+]}f<ˎFO \#蹗ˎQNR9|b9{b TLWaC0id]OɳHVfd/ܑC#4xm.JչqZyU_х-QVuxK30`HNFO2q:Aluqևم?-s$[/nv䆶s.? v#7NRh OߤtCD D:@g@[SPl/h=k#!fP!1aGMiZ, (573߷ZQAx4!e*Lg T7<֡: !qqPamV)@gV/=f?iZy-R ꪰ򵍈lj0w{CE3"ăSY;?Y!aqYsk\P!`^QpdtJucu!FJ7OdkXNEWp"A. G K*῔1C(wj-uFJD9 p(%b',d;p; $X-/?6:6m>(DKi?}e"V)>swi$z,8 ؏0 'XSgCxX(BÉ*1g6+ "8T@)$׫gC \B(ƺį"]—"4 GN\Ɉ $3[D˷i@ǔH#P.0h_} l_^6RBذN'V,Z ,r!zB6 #AabJvC-!je7u&QWC") <XCqc"Q? bI=V+W-~3_P[%۰OD#`bb*cX+SH+4;ɶL2}BpA1 v b${  ^ޟ,X=24 X 3=>ݖ O@Q%*Cw&-GMXрAQтgBD JJ>- 3G2~3!{@-%d]X&5P8_T*z^zLä3&&.dۆ>j8ppĶҩc'X$GpbQv|ȸ=j;u.P! sH%HnDSe_82΀~XdpK 7~(G!pI#ۆ8X4A P˯IL.gaj9Z^]a1tZFBӔy`@g[ Aat%\jզ0 W6D G LGC3XǻJ"!Od fi餧CnQ94?qvFu.<-${/7c}x^vjX=BKThZWB'qjx,4_n?1BguK Fd0.݅LyRi}% ƥ ]ґ-4_v\-A C):bz<chFp-E(pe:?Pd01iX gi8d8:k׺-$+-A7Фt?ĤX2IB`d)@ˠc %ɜa$;ˡ,qO_t@@<3%,(҇s\Tnk"$5*q2pdrQDab *EEǯScmݼR POIF TCkd̀4qn1]_>fBb#܌N`]fμ?ύpjMn4x"Ȍk/Aׯ?[v"_djv4:5N7ώ5=f3"KpDŽaCɖyj$>0*7wuP.~)f5Io(Nf$;| 5YqݳVo]iBvVut39.&EA1;Y7ݕT$\_pXq=LNW =-LmBAa&aoKJW`OO+Ǚ;'/pj奶m3m 8MsL 9tIpB.4Ʃ¤8 MTRDZd@UunRLi8+,8R!;ؿ;7|{Y1ZըKgyp2$GgB'c{03#"BA1@UF/=²\!K1g(ɸRvPO՟%u u:%eTR`\CDO>B\ rẲO#f9q%U[W!!fp~RGzcFߴOEyp_(!La^pK(&K;W#Ɣfk' 2s Ȓ7nBs% *0x27o'mENsN#o;E2C09| b0FK 0mK,347^ǜӭn)oDjZ sLѳB8$e(Q"{`u$}M]6 D6I\56xJ %G ITs@f;`dc׸ɛI#e(yZs}E(~^o23[c{W"WAItVE[gBtg4}ڊV,BO f0X1ޝ\\?~=68тjK34/\QEƳP9˂r=˖ˆi_%B?EGo}kF(_p. Of[8~n@AD 'TsjŹϻ_ <_IĈX37H"Gx m2$fv5T/C:ɅЁ[-`r(Ey^=m 'Hi]p"wg>cxm޽^'ÝP@{(l K/l+yޮ6xry A el"%\ղ=x ghI\PV:A:ӳ"J]2TC!i7,wB$bsVZH5Ail? g%E|O)j&2õ2!ꚴa*A{|6,x:W2Q2!׽OAͺ@c* vb{ndmױmlMfEk.HJk.bf%i* 5JR™#Ġte=P7 nJq!u˦`J̗9u8f>8v[,D\~2A._ ^ҭuTR;T45sGW 4׎ B4ϰszy>gc$r'G%G9a?Dy X{s.-Ƚf0ns} Ũ7'rudOWQ#{x[msL`@yA26ws" 7'>‚݂V0Շ\^v@X99JRu8XNrG?B-@ܑY1C?Kj\uͺCY[\:QϙnJNl4KAj꽇a<|$Hs Z[S봔4#n{b$*Д܋f?IiI,4Y{*CmR6HR֒v hz6/WDNzP m򒐄&VHfxn/DN vS/IFE8И !C@qQe 't4y0ItFH OEZ2MSdc>^pud"#8hBfC=QX/cD0q<+2nsf.W"|n'I8;>5f۫(mƜ`ž@TЄaP ^e.!Fs=dz&IEGJ1T%H1WŚx- L{L)DECtr(`G*BSi =(#bZO&|)r%R2jWFBbr.?~ [pЇMYY1Ͻ'I&.} FS^!I!Y?Y-EF7?Յ-Ae+uo.$ȹ @^mb8vX^\}eL=X.\hIؾSv0ճ(s~ĸ+ǒ!ʭ(ws\; g肘UZUv\a׿B4Gd!W3AXHD&[2jj҉rYB(b'bzQ a6T8}cᆴxG)rId/Ȋ9^6{OWk+Rb$> R-89%(MQG81"6&`"K]X0H^ ?1# 䀏 ({AdYJ+3F   s%ɳXLK/L 0˖o'J38Eh8tJ[ogsG+pk Օu.x: `tnۏ/FQ:#*R? 5*|QS2h )0՟E} )щO=ќ8ïSVcF߀#Cyzy1r 7[rwvPŁED7j-y%qSj!h;81 DlVzBֱ81S_P"L-/\.`";.l\^%ڦQ+$DeFwیֹI4.%?~AsF8Kt&nո{tN$AH|Jqxn $PV $TD1Q|s9b%MR;*@ _j\;6 jSl\ʱ B$po05q’k8F} إhh~ܮ٭bֵN :b#Khz#0Ŵύ4&$:X y+n1+oqEpOWʿFOv@F@9\|{yߊ/W`Tl$" }/|Ok;;h)g8uX8$m"o y1$@y#Cܰ r#gasc0_N%8e4#s ftVdpIoUAbhFS4 vK1|e2*FN"sjB8Jo0& ˋ fUV[pn*s c[0//+(`xzDVvDAv6$ޱDN jnG^=sR]KRc cJZN:+Fy]K/)}[%L((M9!cIo< :a7{0Av cLyQr ƟL!TfSKwAyEʀ zdLM:!(C*o2iZ0*USEs@%u E'ܘ>i *5Tho@-tYdXO9fXrp(!%ŇU=ƴ!_DgYz4SNN{9Hb廠sl;6rbQ$}K7T]ʊڋ˾~ó+-e$mG=܂Q-k6n;Sd,+o}5⧢NǍV{:,MY=, {6P({&ߍkr$eu]2O)Wx'[hHN$k,bl輝P/3D;j8*rY()%O_^hllM$ZIz}nÜ}*eW"aK>{7Dso^EnTQdep؄ŀt*Hv/#hZvqW3E^0E'OK4tM 'F`UJ:q+QZp,B 7U%KxgSE.+ HneN2JLT:-76ޭ+ʹXB:rN$& ez-݃E._- aP,?0~DjDل PǙ|_8+|\>Ę$/kMEXd&.m12[SbE&S x%帬vG<<ӏl+&W*HM`eJ&!=d򢞸OWݬE)wZ9Q`mF?E=mLwW'u̫Q\2Dɩ8<1fX;4f+UkJ|ҷ٦`Lj T]"'!" 輏@+B5-L0sOު#1$mw9+kH 4)-UFW_ PwFp^K2zu̻dQ м VgNQOvP"h:t ۉ}t}ę.tlڒI~OTƤ?.g@u{dL@6+DV. nSS`3/_><>ρڬښ,>ت_p0V'妼BU\s#̲Gp ݵ|n=:\ KNcj&_tlj@r$t; $@2;E1Iկ@ǀQqULyh * ͒JI{gR3 }OL0k@X "(5\dU'c+3Y[]ΤAH9R^-7 TDW+#mla8|!DFHPI+s[t>mhOgYl5(`!Bu BJ{320ǽOq&¬(i,Z U|.H=Px``]Z4uEcoHq)عɋ""|m%HQdbaݵêެL!=ןq4-ZC!C,WG?qiJ󯟩x6+g߲hIfNG 3 EOdXBlNxb\^^.ELK"91~Pu(JC 9sN`5Sf(&&BYUIQ$|i8(IS(Vxs2S$oJg!f|qf j  >%e4 OJjTo|s$b3EP,,L)+/E ߴV ع @3~Lt8vc"ie=,LaEôOI o ,6wwAg5ūNv]؝p)^,LY<"2{l}'CT"߄j c9%Ln4t?[wg*sm'S?KVf&MeL f 9%EBלkz~9 D19Cw`?CEj{T+[8t 2]V;(ImGnK8e(h6DF{\9U/r'q`x>`2(OScoƩ@i&z.0MVbq:}/l]ԋjodwē 9)ݷE(L2Ù̽*QR 4U5pqؒN quj7n G,by (Q`̢p[.BQ.RXRjaנC bz  0¨ZRXf>X{6 LSfpk* oL 1b%:bbe M h#D}s6 j@JB[eNKՊ/ѕLHMC&̊47QZ4>-dgϡx@Q(+ ~d?+e蔁t[gL"p 1G` bkMJE-؍((vjk#2F|jDNju8{DrfYIHJ`(qڒ4QLZ~E5%yE# H~+7[5AŤ9XX4ej3Қ=i !NV vgJ!YT.1p Y@1nDD8q?bal9< [%H`3r{:kA$v^7MZ( i^tԋtXo2)PgR!4C^|SFǟQ㜻؛^ǃ>\NfB;l y -YHJ3p`|yusy4`-پg3 M~) ιֶ UȁX2qII'" }TbRH$v-[Y;邒--mЃ)qR9._ly7]OEFV4 \xoESQH(PC6~OO(-+! F;v~B}e HmZ/aw_.vѽ\j|>\&fsbVpD!ve3Lr,&.𹗽-&z eݹD6@<=찜d'GOT'Q#bY}/:654e~q7@F f:8zduf;|r؉Lć6-ʈ@`afX/ٙjhf]%p2Aoq^.s1UT1PiA@$BX>~(6Y>)D~nRD|A /!Uΰ2i-G.E_O1Sؚc#S끝:l 8K!x۳-I'PT哘@ @4=E 8ӕ3l7dP 숿"HqF{Y i!Nf B%5.>q=[QWh+ǑIi;!X!y٫gj{7Smꡂ1ВLJ4Q`4GnNJgKА#|P7ւ/_a5'Ws@ǹKc׈ 6\?'W4Fu,~ +CJ$M]Kapa[6eQy9(szQD<<9kG #m=7!4+Uq'5n 8pD-/ԪM?0"ocRrV3$ݜѱ1O/$@[?|kկx2llp:6^ bf:\f{ jEcd,Hp wy~OAơ*v.d j Q"KN:e~5)yD{y |х9,aC9H;\xEj|זpaQpVEfWM["rE\}pYrI1M"P{Hf,!@? 8oҟ5LBku'b'WzbK%,53'MU_qLIE*wKUL`MT/6J @kr137A0m3N.d|)wgsKxq鵺fR{uj%^)Xz/Ύf׳wC_{}u$yc4 vPBhFkX2؀C1>l-eWN6TU_y~2':à"m[M:' @Z GDךT"o(입<"*쑆8 &aDADR[~̓L*.!HGȑV= X%-3R ;[/ۉeJH7U,I *B$>``w WlP<^M8 /S A550LX :nk`aE8dԈ]WCsԽcCe_%zJ5zL/&v2 YI&]P=f6Ov9~?e\@%dt{6<{*\bXUpZM+RVO-lp!V^8kXrnibWHSAГd1:zzmbb*_A|'j( 7dSICh`pD MuM"q@Hrqy-r P'%s&RJLz{Nd FgroQ^L@S!(KH9J#1m 0kڷ,aqY6"Wl& q`,Q1tmKgiz+}e#qz: M5RUAhĘ?@u65WU(.ȍzltw+_kF_\ TpvE?S~y}b)1"M0CI0Xvay$Z/LARӬ9 {Ry\NeڬjE+h]yseY4;L".Y>Lo^"[D|^*h^*?愡axBɢowK;R -tOn =_Cb%<^Ɲ'jkٸex&80-^b+f9Rtp!90JѱٸJ50F?%Gf<Wxv<5e'Nn5S12ށ`A)˒61Qױ'PO_W;ʌw+!rhY-D8 oGqV-޹>%=J7iós&W x`8a<|ebމ $]嶡`r0uܶ> tZDǸjRN)[h8$X+zgKmyFBK:T^E#(OzI 2Bu1[Rq17ID 1U0P&I=ty.aҷA\:BY%W;y|@"@hciFT\=ñ\rZ" &``KnT'Ђ*dShDGAq x/mrsdߋ1Yz db09>=XZͨ neQKE:B! *\L&Hql<%$Nǯ_=>U<ȳǾ%2fGĒweG/()pxC75YŃ%wq4}!?@epx.\NYQPlă`%rߍnIP^3.SV2(ކk=(X)3W"OdYŠA$Qa=I)R &ԆVK&26RCޞjQMGd(PM#ZL2Es[g_66LV{h.BK{n0AD3aL#zԟܝɑ2?ElQ0nOP5WNo#udqR$'P-!uC`둢rS@cuF.ik"ěՓHWr;gӃz 5+)kѩPZEIZwتJJԊL-snwb֯B-TxFE&qOBVLʠrc|fKJoa, N-,(+hq:念WGaf"^lXG\Z1.*5Jooog?jt*7}D$$[oRQL!v|›XqF!&BBFVzZێ IӁ$tHaAfg _(&^lG uʟ7v3Y@- z{":p'N&d@(i0M)ӌ8idK/v@ڌ6:IVL=tYAk 1R l-JvXv&Oϭ"\XE28KPFQ:( sŊLd{IKoZLcEF{Wd"t)}Æ?C?R0-_ 1ub?l˟]$cٲBb `Ixb1WXZUܟGJdqT~ _9RM~Cԁ-y_L&zq;e[s1__Nq :%a[D< J(2V'-5"-:mGR1*71y& I>E/c^=R}a@nyNo7!+:?ɈAmML35|-H2Gc{~M]eb{QK^|d42(pT;⑀GAS""H:") (ߋz@(*0}3= fXSI"*w+hřln5@U*Dǥ+ fDaȘ2| Z!u#NfM"kЀ | ԃI`f$(@1 =A#'{A!z\2F'.Ff&4r)p0t,ir2JW ~QZ SN]rVhYg ͘ 0GKJ(oK gK Uzc!u$zVzeFvb.&q_z88*Έښv* F}E{<+جMs)9,AlT`n]_ϔ'i]d-10͌M'="?6G+Wd IDP C&-g*zqt z/V>XFb# cD4GpMڒUZ|C]D\%Oa{Le",G-KiG TMbf` F/caxa0zɳI'C>F zS_bђ5'=[!S|xњ2@2&"8xͺb'NKBr* 1ve㒈_׉ғ7^h8;յhPRS,XQ+[J#wR+0{2vMLgj4;KmZU͌{v\Oi<ȟ!ϨL>XNaC/!,pGg<`(,:b.x AhNQ<s7^r2HԊ9\TV^ vHGTwTqlo:kִpY"/f4 ņ+Ǐ,PvqWaO˯FI6,WlvR_ ֢ ( ҟGyU1%Sy+SIDZ^EE KYȭMQa*DP%Sv̀ӻ|@(ēd< u12gCq\_\L}噅pE?%>  yq/g% zBUNdFcGJI.2@iUW"˒xi,yxlF~)Aί!8*'A#pIE*ɩ[NOa,>z4RЊE2b"8fw>奆MȮ|^mbO ֟/s˜21k٫JxEv:$?#.lƐ&+'0G> 1kgˎQBgZ0+j]k?x5A@BKv wBxՉY*mas R0qYEM1-y{Y=\&c%@ Kz<)gKkJq_&DžTdC"qJEA_k9nش]eE"/)I#9 բi:4//G?' &.k,cvFYP ]M@ec T.Ni-c4d(Tϋ4ß \Vџc'Q\R/|Lm`NB-&>:=wƮ./ t$zחuMisUra$! ̀$XIUY$6RI #@@榲 zܽz-Cv'44~ыS(ɒ mk[K A[G8sҡ<)7A/U#לj829yDv|[q ˶;l}ʰooN^?wӁr T>g@)@('ty+Ug}%o'8;id[=8ҁgS4`.X)VAh= )oS^&XE]_MNNZU# @zN޼O^6:)>lHG" IŁefYZq,+œ0$oǹldxGvU'RTA;)AD7hfp(݈w0n,wLrC)M򌧓S3o _:"ѕTX"bȰTfdxEtMoB0axb}ðqp0b!6 mAਵ%9 &,`0׊A"=!rNV +bV1A36oxQd"Tlir `xkw, C[W qX>; g6$f܉v*D:wxՀS4.rZYbR1Hja+XjЀaYTGy6p+1+1+hVJ;`Q\ yɁ۱ucIL+! Ah]bF^@nm!eDKMTgWAa1Mpcpڧj#^<N@4Hj, 0= wh}GFTigLj2mo!?{Wg.Ӱ,nzf1<1"?f-䦟xgL3_Ln'-j€$,jH(#I$'&ھ{ݛ=҃[ PfE r!7{;o5 wryQ)||x@f#$xY#=K_Ӳ?2('$w`@Ne}]K>|P@Axئ?jױgFs6NeP ~<絭mZIM21rtPdUGlehM[H@+ dr(x@@Z嫅\`2U2I<7$&|)= 1o:-2ʇzתݜF(U)omu{up&؎Oƅ.y뎕!A60vֻ'E 3>ny8ޗ*|BiguԑGuudM[YUSe6^zi1R0b9`g>F)O>1Y_"ޞo#Ͷ1ϸ!u &$:m!gs%!1J6A*" dV6aN@GǗ\\=.Z^!4/[5MWO?>WϜߝe:ӽ-4T5jZq*iFZG`,ȟ^ .] >t1n7oqҥb g)3LԚf6Ho&Xa//xC'赠u0o<ߦMDP % :mLx{z#̅KqS%/U0x;.t&H,oBP?KMZ- RS oLvE}'o3gCD zҐp˓+e'z)cbcbIJ^ip6xSi { )9V ;6b)stn Amf%-s=Y}HNrq/Ly3 m_e:Iryug'^ujSm\@VZk;,hp~x64mr$:\>gח#Bx&>m96JO~˝% YN:{ƍa9cHqi;,M":9ԮXX͡8fwB9LȈsy9^h 5s&Ɔj4~*5?bJG]%0H;p^ucd"{y@xHC$FʹQ%.ə T4k5Pz,?m9Tqn:aDg $K0x)&p$} kata>H74sxT@_SN  Kxʂ1Z"lVSPY&ޒD$/I$ӠW L$qw7 P}Vw~yh楼YGD#EÓ1E@L,Zhᑵ> &'av@hrߥ:&Xl cpI6fxu*ʎJ}%}1$*a,ٍO~Ԥ/tAĆQǽeKhf^)'e$BC\Y4#(|[7:>}0+>Ésb3$aC~n;4kd L! \B1ť0X].ϗ\s] <~jtaR CK"-r]*"oѐ!_qHi SıL +{ ?K ")Ȁ{{g}/큣ߨ卪9#m-=Z2V.ǝ|E ~fBU \q`զck;vbj~ې\Hq;^-;0.1D0?du,p{lmCD3oG{*ڀf(W<)1^Pjq*d=ޱO_ Ѹ!pb7'&-V:_R1F^!M.H8`1_׿+>@9 (6#"pf) k.\v`B)kSFjd=掸$v XiN2@+gfz_Mu]_oeFF&+܈U-ٮ$"mPaHq )i[U;H1c3xJ7_|Ѧfw-CWO27r(VaTK i ;w>$RqK |`:/a{<*[^${ 922"a4蘒ߣuv"Hz HI!Ei&-mmרlb^/%2 -"9 H:B'oȂ+Fk?V0KB3z$fꋺ1.-ڿۿ~^~[k:a?F1}@} 78iJG 8|=rl۪!@({\fMj:ˎ3<Lxo>Vp 'q( Ztrbo:v; JKA(B=h^qTpUJsڹ[jFTxgZZUCa WJe}ߩJ!>B왣$ wk% t+-IĪQL4,ړewmƓj,^|ݧt!8_ W^ONWcE:])]&y<1 Qy`@OI02K-K'"k\KNPT+co+6<8 8GKRc w֭piC>:>< ϟ˃g!LќC{BMK sa-] &  21򂮰8Ai*|f?P; ($$ -KrQMh͒۲o8\T=RDN(Ybg6.Ha@"j!B&n$n]3 T]UREEw /μ{p$_tZDYQ۔,tA8Z0ګH껨ƙ)Dh*whdAn'L$zq[n~q>[ӏ<ڙZ[cZ0Ϟӗea1yh#l!,Yir߹]|6JI^` 8*yD0G)&#PLCrճOҟ*#؀&j阽)[=‹Jˀvy,db(Ӂy!nå9daoEi&%~T >+M(e83}"ف¬[:=T5/HN9a1*WT͈JC4Qp~?q/}sNv)u! f%*_p<]yѓǦ+Wק?ߝL\Nj*bcJA΂ihEXB?*œT2(3f?cA%}'}rݳ/7.V 3jd6]$.k >b]B+CGEȨ.3 0)0:O^P1J+,%c{^HAnى3CPڠ3#IfaU aWAk-t޺(dw85)ʍex~ %; o;gNSk }1'/_>SIVx˵] ~* <7]$oWXs0> ^RY ;{*Xkf*cYDѝ8l. LUk&P4֜˯u{U7tFaj%`+Mʉ{Xs:" jMƨ'qcZ=z= x}^I[w#5~ TIF?W^2nn?a]!$f '9z˩ٙжJ;G.3W޾ǧp46N6hvZCBb0K;5bM;fY%*n6Ŀ1LˆMjD|nA]VO ""[DFzQOE-Č8<Ѯ8%T6wU,Y:,ZuCkVBm5H`7Yl ;2K1ix( 8gJp̛3qn8潍{OpʁI43t,g|@&dԗ6N豅wnuS2@E[#6 7W0`ry30 bxǎaY~2PdmͶw'`Ns}A$%,y:EI'-{Z(88o H_JT0.`$08FNCēՉDؙ/"! x)dO@| Eh!X\CM,P$eڮtQVL d|]7^/U\_N`}?Pkd:qέ2L̓'z?11YɲbĚ-劝GϞ?y5TO-ڕ;Ԏ9Z5Y'S8 D{zw/A~I+@tHPr6#q+5˗/أjJ~[-s)*8ɌDA=gN&y=_JJS?#s}i@r_mɹLvt"Y2LxEsY#x/AK CI 6U*\#(KxEIS{靕ifpQk6v?]Q+}FU:tl"%}Ze&%(s Yw! S BI XV3a RR" FSa``gBFAb %sW#""b“V3@2kAaAX_(u.}}{a=ځ'x4N BSTMhXpRϔ2LL5;2 |oY&`S׳SMtL ܌( t5]].?Lxcҍ; m[|#'<*jӥFJ!l*mx67>=LeBe5ɣ]I ?@W.iK?;~9?Σ[J; dM11~2Ψ$ :ٴd?PS¸t>irls( OTTګX̼vScO|G^4> c*[ l0YH**.ItrDy0X{G׻\,"{1xzL xTJBi fv\؁Ɔ4d"ʌ`Y $!KuUCx8S44Am~)ȏYrYovmB{^eb䁕n#)MZ pJ10r-rjDِ 曞Nrt-<,0הk7 i캣5k$= ]MZe5 ۰sB~fD~iw1ā2R[$&:탙FW, 2e)N Xw6; grRþ7sۻyjȊp wH>,kV-?m>6 g}m#ዦ+sQϗ̉-~6l l_͍n9[qtnʗ!l~)<~k~KaB:DUvu,?w+y|?s|?,sDۘnQ_ΪaDsZw_?_{~3:ōhs8v_9ީb~e}fV[>doUI " t{|:&n<|tax =xqcixCԃae;j^˟ZXǁg/r ts!-Puܟ/{=ԩ^ꈈ±-J#ӿu}x߾v t.<ٺ,We{ {_.ټ˻]?}{hr^W_+^W_+W_+W_+_dU/a.^Oob2?Ӵ@r͖FlVi;EvSc̪̳XlM_֕ ޯ`jhwu7zjU刴FeN[i [}תseKeRAk\1+mkwĵގn p(-#>G{L46R+3+F8KF]ַ)؍ǴJz"/)P>*a&lf1hӰA7s~ 0ZߘVt8ͪ#[orf3bɵqwG]ui'=jm S5^I.RkU5fT[oZ:OÝ{?LL2x=hUݢ=quʹ']Z-JN߬V:.W;yˊƕ*+gOˎ譽G0̓*4DX^m ٹLjGugv'X.XڇU/?NLJTO[6kvktѾ?7_WIZD]\57e p$V=?9" E[`B =;|< oo `VQeB7܀ DwYgZ;k^]ڏ~N汞uU>VoRwwYNNa.>8%hkZяY{̰B1ԗ(ccg>7kq_/pL΁w,ʫjfP&Zkh@Z8"6q?#tčm$F}8CZ-ArinSI|끼*^s1=E^ԋdxG7\!w,QN[ptınOhimn>,QU&V$T ^eS>֩" hUa^VwX֌۪a]wN# dݙF5>ѫ6eWì*sѽLx[RqyJ4ݯbײvG XGh1ؘ`Ӆ i6vCg7ќ#xyY@q Q7(q\8,T~VN|;M #V ZƔk- ,n = F7fR"U65:35ߝwρ5oWаȧ*5/@zS޾?Ix| z.+6F9j]smm%y#dlKqdi4GAk9XhݹD^a#{{#T1#TUnώh”Y[ifs`U2uQv* cv+vl@+KՎ#WZ30:V`K>Ds4?ޘăs0 V!'0P7i_r?%Hmwdl[X2Imosi*a`y]2 >16ԍmF7Ҩ6*U?\kqvU(_FҜ5 5k@=B:FfsbyTw?~ntp; #MóuXJ{[qd([1fFcU`n^mu5_?o?_ٷb [yo=*wqLJ85̿xfKFh)9ls:^g c>g>eei6l܅ޝ^[v}}wvm|X@1NM/oq=y8 Wu- 1rp턲_Ii:'cftV^}Y8vj|dqG@x7-+4#dus7/}6TW{IeU yƮ*cf$SQüj3i!ډ") U>w5p6 Ǔfd2ЗS=g1[s<=Afܳv7V([6vz֜6;GsJ fԺ=ޢw| ]I[+ `TP/I v.7t m3*RMrhߜ'l DpZk 4߫|~ e7T"H?N4/@[4 D] @v޿5-KU=>1 tGgT6Æ!if`}ް2.4ێedx8c_?˽3e4QڝH6qR5zIio'm E~}[&~1<{I[n7tDGKɋmڸ_M .-S24yw@ `vHwo|ZԪAu[(jt|~6 IUP :Guh0]Ά% QmFJ[fN8$ xZRm_zv(T.sxKb#vovu;c1yn*}4 -N-IܚSct{9o fIa`;lYuO\I 1O~w9 ww Z;[>_ 4 0S7'Ʋ6xМJ$`I0i `Oą^TW&swA-*^gTc@:w@vVof0͡Z.eEe$ݴrܮ|26}_%`i򆆧&v-ɻOA>$h_?.ct<SnW- .伻]eWibX ֱ߲ 5]D: mUdTB#cjHdÎoFu?OVڮ{ܵϲK|pa'1 vNU{)@N>Qi i{FF<\cF.2+G}9;岽tNܵ~'ݽe&S#ߡot{VZ<#lkL\AY[vTٝon W(@x2TU^`’K? i̗Ta3Kvsx/Yo~f1%;+XGxno }u䇇3YnI(֙!귷](G>{]R*Y(U9z]g/)7AxRe(bsݏM/ A%̜CM= MPd<-|,f~|}ty[Xuh"b,.JBk`tmWI6n̼۰{odI󔵷@5n\I[|0K7)`L~a|L0ܚo,:Bnwh(E+IvQl瑹cTE|o#4tX]2G~^J )bo#2mW&xخT) 6uxs^pFuqO?ƺܛAJϿ oUJr蒺(һ7QNGD 2VP9Byfo6<&k`ʶ͵Jc;ClhCF8I3LZK}қ2{͇-J~Xt`FW:Ͳqc{EYȸ.l6}º8_/ =d}N\>?N0XP]4VK~R&^rȭ>"M+~ݩ{e )پ?u]KF!ͽڲDX⤧b]gՅ Gy'-[)SevƵq ˣob/; |{vp`S4@}"vni9T,lNe!kc2GĺIL$oٿW^p9 +DhvCfְiڍPz땹= In9F3*L:fe~/Eϊ!8N>$o^(}5o܆}[Ą,skw#<6kK??}֟|՟'\/h9y%7b6}u|3JOChXxrm HQ7qxejJ[POX Qz@nZ[RILޗí\3֧~ZuymvR.Zoð4L+ dж%̞nu~7k`_f "kzlp_4]e0^ǁ]J?͊S2_$wֲ`ߕz {: _U{1m?^釨< -?`+Xm9UDojI6׏ѝРi>/^i5̒h_^8_ӂ֊|7 ]ݜ2x.PYb ouآ?i>L`M2͠ʍr.m> qKc*Ң~'X{q}DgZ}ԋ8D1/yԾkzAXa0{Z^e`CV"lv:\D`>ս.>>ӿ?ߎCޅL!O@¼ #RFdwȱ})ETm}ד5tkD:nh.Tm:m46ȃdmM ~W=TL0-~Ce!{gK+zsս_lv @7Kػ35u*F)09&q#HKJ,?>XȻybʏ4.j]W?Wvuާx,إ@ˌCT2>?xwY޵ N;Kn |'&}:3n۴,;6I5\fmFENK;2.O۰-{XwC!3iA!_]hD~p'GA%='T.j9,$)?A'$w/p T+x,%p ZH`N{.{袍g }?S&ӪFh5SË `YE 6vӱ_w9 ?~pz>-pux tL=(;&=|w^'"KTS/EMXU$K zrgf鵚vֱ= )ė]nhN0ib|F[Y˚т3egǾ;u?U]f(nc cIaLݯ>GU`QYU1kjpM0c%:ߏOQ&\UTi+1 `ee1<1w\\fX>sj]Up-n:ݩNixUs;cs݊~n(Xbp?O5]W8'=ZOJJGK*d\ov}rLtJ ЀKrKwC@.;v+ftYC!NNlRY(?;'hdr/|v(]t p纤 - Ջn{?c—짾W_&hFb΍q𘶑r8l=~} EH\0W{>,~?|9;wn=R90Rpbv;e_-sgnFizPXz7; ^ԤfhpO64MV)d/}GsS].LR=D5vѹ}aS' Ǐ![z̬7"RsUߣm Oe}J1]8_t1nvy4dg:ӳ[1Ev/v-I8F7K>VGmGX?x^7/fwW6;6k_ꪀi\jW6ߺcy+zY/ i 1gk^E_LK7}`+gt80 >L i=_KYr7ն4H?9CHj|ӻ,ݮeIRxhA2_q٬1T*A p9c D\~~ާ a#T0dK8e]j˥8<_sz])-k<]Wv')uyv~u8-Zwv=wav4}' f;-FӋ#,2e%0frFl04PN`55Ԙ^il ͏u۲E50l_V]>^~{xXm|]L+Kft!)[n| ݥ6Om]B90=Aǧ ;m :n`vn+pp|ɽb[nbiqV^z-!=GesbG1ZV ,8dbN1ws'y33M7V;Fl|g?a'>u 6|0֓.[UVK>&?h>^QITEs'֛Ua":^"0FlڤQZ8#^|`jVʋQ;|Yƨv6w8O N"o}]DV3.W"xNE'ߣӏ=~@TOmHv߯?_)Tl])V5.JY4xL4Hx:f /X(Q*il8l{]fJ'my+]}Ѿ)oqCE.]^kmiw>;1ɉG8|?kt/on^OhL7f(Ǩ볏Z*PrQ I{/莽fEG߫q/5gZzi$۴ m.}CBq]$gk<0x~x83)Fѹm^qp ;tdJ:<?B6>JuKa׫>6()A!U !Y@ TG{LB3vu~U.tBXl Fg47UnI0"OP5 =x{=ɸqX1$Htn||n!;8f-tQ)`zY@f` SH?EJi?:8G5M@о<N0lFG]j#0a-ْd aW€mS{PXo&ruvC3$anj|c]npѻclzqYrCaa$̚ U]Nlz/3uu#4e tec=b-tcveK^Z#:F8|hػFqF_ i=8õh1QM+ӈft3Xֻ:[7z/6¬d{Ů/gp=a20m{{~i?l%Ʈpk*>K1"2ݾ^8 x̆k]4F4UVND޹rd!*a>xc̚2+̨񎝚 n$jαݦ閟^7;7_nByHM;ڌ6]ER韷iot 4*zb+ȡ!U8ZWSk*yɡ&"Ǫ,;\߯>ٍ႕d6fȂ24{CيS޵=E0T~"L[FFMA]_81m4O BQ .Dv9[9NX}~%n\AªK`*c*΍UX#|ts7|z;JOg(0 yB. +5Ѐm+689ۂM0E7i jg.k~*^GsC@{1τi9˿DX6ɪ:߭KM l7}'128q_X8UgDdyTeOwPvy|LDc]j8)_٪v`&kz-!(weQ&'.׮?|8_V[cϣl2 t ݯ śzc~[j<Ƿ7Y;qu;8p8%2ew3o~{+A| Cp[Bѱg࡯~j̗@}IEfM|Dq@R]/_U_1F}f}:e1ݿv`j2@oc9+WK;ʺ?i=մo_쇝 Ymy~3t; oɓp+-2ǃm}J)/\\U}>?`C~zH#=,jўE%>L/^ѽRL۪lG]ط6ܵc3, ؙՆqf}ax㾻h!a,/DQސ؈9Oł}eدq }l?S؝s3ó+m 7!n,G%3Ӓ c' W>0e Nǥ+U\7%#yMhJ-N '_Ob^ R/xXR_.gx|[Kb*lj߯xɵLfi^s~POeuՉ6V} R`-I^Cton5W}}m(qX}_c6 wja;j GbX =vn#ԲfɣZmti|'tHkkx#uYf&fmsC7 {H^Z9PVIP"j(4nP%euh\ Ge$ƻ{>*t91fVCtg+nG9z@^Olw'anyy]_ՆVR&5 MQ6lwTϴA%N-N4̢&&HD8b u n"ʍrm"BTfVBi*+~_8% _v<}/mq1PŨq7c^h/UūoZ}kN׵W) [5K_79[|TOE\u2Ga 34b&l0qˋs[?9;i|Havxj5i ~N^wrTLY}Uj>:~/u|Ǵ9c5fnА{/e;n>w7̻9s8y_# pM>٬p42Uӏثu8|߹`T;W.G̋hXd]\sY&s'KH=jTuӃ֑,@?v]1Rýjn?ȓa0MŘ3?x=RmHz}g9Gw-VIk w;/Tܻ7}(Ѵ;q=mXme靕v`$l?\}w]&}n#]#y^v q,DlA2+l0-wڵm:ڽWXVևan Ӳ9ȥeBB{vYe"NY?*8C;+U֖-o?"w<$G(yf]%[lpqmeBa쎯<15Jݦ0d(.{r{Sl0eȞ(#m?rvbII(<&+Ѱy0]|T7M K煫?~,]Fp!x8G]-ڥp1q~rNua? emoo퇜u0#g#Sqp0/tAxYq+.A% uq6:ŏeаl~{=۵m܃&{cU2@~1'p_>wwm]<ۻq@{m|XW Yj6a&\ ]1$wwcʣf^l[YU Nt,?FHsܙac cM@y>Ǩ~C̓Q'mS9߸xükY_P4m-^ ~t-nXa܌6U1qx-tpCЮ2`#e5?2 <9p_Iaop~@p cM r3M"2bejkη-j;p s6 GM;5f} Id[>]ᱪj J?k` l|_>/?߾qp=ֲc/f2vbm=wm63;0 ۦæ6u͠inl裬9EkTLᎽ3(O!bTBײg.%9> 0W yhq9\{oW}. ufks7; F9ڎFhuy\ǰaf+IȘ1C@h}/>O엲Nj2]'vCaZdn+c/8 JArݘ-jrʫ>+gR|ښmg~/jSfP1h\Nm{S4K15,z$5|E8D@m#)᡼8x]nW:"C [<4p#1~R-V-ɺ8fU|@:3 ֤Gn]e[Y {3o9vVH`%7CAcZ$ƁUඦ 钉Uٰ.,MtFl];|PP; 8#1`y8Zp( NBkszQݚHeyakXnÉ*t^amVC6Df ~ù\ԧ? MRp.yz@qr(YxMj@9pK2Y9{/oQe0 ,^JQmڰ[bmʇc'7<ldL\[o "#{ k$ď5nˆy'0 Y>[iSU ټ _F{7{$)< 8 K(z>\H4 ys`NMI Lv6X=Ĉ#L<ޓ7zRʦ&_-os1hdsyf|w~{wSm}_U{Wu~&h(mqu?`.ZE̲v!'Y 9m0}{*+s1gG,<: a/3Pi{/#΅ V0˭G }_JIvZd@ 4[Fhl?OuV?4?if LvҎe~ە{]Z('b]ϴ>e.mB:3P:>"l~O?ԷG"4rBPvD5: n {?޾>/ʘ01k톥rKhtۨUn?v:17u)Y&URdd?<&l18Ui?xs;F4;ݾnZ̗UٽT^('e`I^qJ;yv^<:") B W[`ҹ&Z4={A}TJ%f ̧V^]/r KfQ:m$;6l5kbã^Ob_ rǁYfu9{U_h-*{zCacm!N /l9y x${}Ff/[<v7;TN ħI0ٳPzW4ϛ&V37[O~<;JK8n5vFzP1On7Ӌko@25j~=n6kGDŽ.\O5s[P&d 2":_}&/ٴ@axۥtgmw;ah3]% ^z 'Vtou/\mdS]5lzc6 :^i ^fw0_5v5֚)IsP(Rp۫ &ƠaLPHF;;h#P6U 6cێ{WG[^lǴ61 ͞ӑ(1 .qWLsOMzYD§؃Wg`@˫%7Ûx/hCLcRKbMU1dExJ,לn6Ѷ=&[vu5u ^}Íx4Qj֘9䇁a0|,? ΏJ0!ʴD}e۵Q?}U2wJ~:Sw=WNL4>V>ŬP#vksu;ƺ'}׳ڝ߾WSY1 +xub+j_5PC[ io<6V$`wWŌ>̦ HՑOM=N>/:/iBER'w}/ݼFf6ʞswV]<~ܽØYm9=P> ;|w.Swhd[aV6ROӐmY1"nM9=Z>XU1sfSꝡ>JׅY7 ITwEXµ!ɫ>\l4ɾ`>E>>UmCOp`zIlߙY] >?Ӷm K=OehZ3mVUa{(Uq2N ~wo7O qmD{B2߂x`lj[pղ6bB;Cvg59|w̅ ϭ]5W5{9aH7pHkf%bKkwa''WwceOX!%3i|""_e!aW/h3Q+nN3gxo.I6g;>"axxe 7z+LK*1N>z!좿XHwEX,o* n3R"uG;kgsHfg3n $MRߩh#2>Ѭ|}<̐` ֢pv385y=_{8Cz#&E:7,Kcx~߿ Wf<|m=up7=WMzY 1򹞛]6x^s*4L[#lJ fEPd"1x|w2h0->.xw$J<͆1y˞?_n!OeN ٷh'-/}CjqA.F>u]YZ03w7yD#j9 >Yu]U-nӫ'Vj<={f~x(ٝ^*߄008|pxt6eLCKfZk0_yv/i4H'F̽W7yz\pX_a/)K =fN6h@>[+z/Ue$mWoK~tY{!iw;|&y~Q6޹yLStwǴxc E]a< T)q;Ĩ[b9ND,|=u|B^\Â6 Ӧ UL}D]Ѐ=WPtOөƨ>>>R`7ϟ7g5_Mt{e1 Zr3} Iu(*]yEs}:NՄ 6/%XI+E 8;zWщ % D fh4M]b9U;2"YAp@sp8-seH !he@ռ3x+1 ֳRvĴo/>NPI4~쬔4e󑐶Zm7Sӣm<;Nq+Klm:@ֲú$|^$~}Ϳ^?=ܻ ~}#8N{cQTGBJ2[:\_uGcHhxpu)n, #e9[}d`~Xwk @Cn~XEnuC[܆ǾD.;ht.&km=罌0)3܏~O<3ìcJ|^%$5Mad69EY^ {oĥ$"K{yy|;oiúzQ#"U|,"$g_''zՓ"N<~_@(d]=1q}T ;}}'-1^m͚5 ܏l̲K@*ƍ$jZ|Tʦ\Z0,ymc;;qB}cJH6UcgXYc~{5r \2$;d<_zﱘj94Mn䢕<GO\m'W{an= q_JW>uyu2O]qԤVOZ]5^ifr Ny}Y=o2k]|X\bёƀM?a[t6uI@eدjjC_A"r}l`Ll^[ [n7 {FaN!ha[[x,w2qͮg+,~Sz7ža_z0?ٸ?KŒ3ox|UOgq[±[do_QH_TWgQWo8/~ǷgW,_z?k)X\eiQK>}8^̓/?Ĉv׳γ܀k_qWf y aE v?^_5&tŠ!e=j %>,noªZ}Q zoU>cSqx^c|NV5WwvD֡ѮZD7\ ܵ8!PI.7Pu\ c `syn6M&{Oijm>:ONl`{HAf|nK>BG? #AA\64;ǘ-kK#^M\~z[ڛUݞ8~݆WgWFOfG??yus\(\P oistOS"!P}j:eFKz-['?#$gMu]QQ{JkQ-Xl8: 9[/[E 3X|ZǗSH]+,6ښfE>_1b*4%;ף^^їև7g13/ 2htIB'DS4A{V;~>ڝю ԂFڼ{^煳ޫګyUs\?}_~9WP鈂V)iI#AF[־El3G然Iy U}ZgwlY"Q1Sӭ!!HX;ȇN #2,bRvT3)u|]g`,M}ddX-}:NѸ0o; l#$"hD@&9V†q~2 ~qm:I`Ez_.sZD́W"TmU$dnI)։03Jmm1OWj]=!,aǰa%[w+s^tYA\O%{\CmVղ!p1z=#]3:&P@oY4L>Dfi8ɨwش{ xs2BFg@("TV{%2u)Y A+TF0-)4^jCa434 R1@kؤI~$+ H])㼛=\0$ 0BFDuT?ICߒ7.q9#! ږir"S<ĩ';V_g0Ur]$'+|~~5[`quku*qGqUOאw~'FZbFSV@/k'Svfft &,e!3l{C쇲_4[\ d|gP}z5`ڥ}wkջBv7[i%\retfAG{Ƹʻjp1}=LvlmZ48aٸ.yvwÃ4<0o0V@iv~z?۠}BvJ>fq/_XV7y8clՍ'@]eWX-qg})RxW,KmІ֩eKB>,̒ː=l @CvmņltܼwyP7g[#r SVam's_~q"SuEg^?t̊81gdF81Ojan&  E a{4ɆFgڍ4Tw;mǡeE׾tuF8ic? x TQ* :"3Z5JD=hhH_M{<Γ*lues}q|~- lE PJ Xa{cRk˰z~ W!1̇u9jܰ)eAb8*Bxͺ;o?_ō=Zt=gw:#cH|h\1+brշi"w'Tv(3Y{Z?- k.!?c};x1C?1nޙ`Hok\vĥ6X&Q-O. 34mΉU+LD׳.r_\+k={?@d6zo~^F@{Σ 9VG* neT#}'WU)b3w"2>fP9 ua1qxn';hqxVUW?"GUa㐔Yf;E0i7 IE:v>^{qL+C '5o_:N;•_B 1d ]>>ȼ8Li ٖLjdžг~Tn[#nwaJ00B6 k /1`EWmkEqZCŴ1\*woOf8 } q ( k{`%'hwF)1*, \w3Y{ڣ;+<_:neڣDkyD_SΨi&^րQ]%B 6pgB? `R]3㕵M@7m+8iE-/4j5`&v3iS8*^>LKYM&ZM|Z_cF24X>pepQ(S*e ^~.Z|gMQZ%onaWK90u?˷f/mejĬyf@࣪<-OvxeS4ch8N?tC~x 4!11^ߴ xw{'i!{'G1VӍ< @NNnrY0UݙV-}핮P}0>߻ =ܴYp8l] rHczn`vƸt3߭Uq. qW5`Y|mw"(.tzZojڮ;ӻƦ> J'|pTUbQypv\^8v:\=@ 7wY)Y 7>1$P#E?NXUY7 d.f^8VǧݗiGu2q-`Ch ndv`ņub{+(fޫ-گ ;fOV_<[<.zIi!h]KLUw퓗y4R̔䍮VIC&er<;'r[fѺʉ+v[ܶY[3 h#b6Ԛ6܁#\Ue>-.vږ޵L1֞ -#EENdN.ìF;QvC ILfb_ev '/`Ugsسg}v},Lg[vc~@dlݽ+ W F8ȃE:Ji)lP[S~Uݸۏ V`{cx5^%CkF՛W^P1ڲ15}Xᛣ)Xm0[ NNdNF$$xx[Ϲ=&?#<*`Zgs-Άp~;n{>:3z=7~Q׃AqC3 O}z70C`U)g_Oyj=7ֶu,Pྀ`n/wc0U 25MhElE># { *VAVnx=$@G!5np gMvKewu`%qd8{Xk޹0f~&ݮ5ς7U{Pi,zU2| 3ȸ11k7P:N4{oRq~d }'k6lS ?qqQK0j/4N">߭ QހRj:-eu쐹MuOͼdGbo3T,8ُamN;gF@Rirߔ %7S=ɺ+-*]YO_\m7ǣ`Fpȟ~7;9_V=ȡ{~L;}jYkqFT*{NU`?(vՈ!,g"|-!;nc=Í( 9o,ksZIx|N;+Ny>`FS_SUsszg޻U*Hf0^_u^UU~;y[D+:;^N[n^Ƽ*mH8(x.Nc!m֣m$K/w{V;=q*g/՛%~}MkVώO[co&!mO^?*V4bw=;G?WϛgYVԻsRF|^c/޼ykK{"BVMk b=/Bz[%J&Jza9h‡:f6bw]^o?ZS=)D0;XW6nNz[{|zykw" %>Қ2t'H;yQΧT8 }YFgw?â|a@B=N=׆_%I擽ɩ}9 XBxü!h<,S~nW[%h,3u..r|.V?Nz Yj3[_u#bxY'>9ua#Q@>h޼}jaASӽcչ_`k`h*&Vѻ}A%X/jO<;9|TnU%_#~;qC&ÏCx3;WKk]0|upx:" 9s[]K`m.ёz9;/1zm~D 18 VFTSl^Imt90 }R;$4Nʝ{Pm0k`5 i2k!%cYT ̼Zz>0s Y^5#a7 czۄ }%]Yy!w1; SվPY2m&Zn-L}ܨN,ޫy{Y=-ÁE~HH9>~3|hAHd>qgVXEc%Ohc-+#r+WQa{{=~׿iܹYљjJ+`ڎauvN#49gGOr?*Z|cU5ۺ͢rl7JN?jrt'R>rJ&6Wsl~0 9@WʬU}[fa? ~DV܊k~Pz|=%‚dbܐрHJ \K5H VE&.wvֈF?}=s6YD~Z.7g?UKi Zou}]rWˀHJ\~&(q <9!}c4HTt nxH?]*APAn#\͛ Q[E<'{FGL-dNuUJ큪>ܮĜ岸[4du{oh Eh8 k * \)B zz CcBWQDͱ^ɗWfz. ;jnh%V4{uiW*w@:.8Sz8lN3o6i6@n,^OQNP1cۆKcl77CG#T?͏773{e,\ \ӆ"BOo4{W_D|QUG۶ڵY} mzs] uJ6>F dp{HH\ʆv{t' od:9yU֜f}E֪I{o߫kK+T{m(b{N6-%49Iǵ[@a,P;nv?yX^qP92afP*uW)MUS8'-jiKE- i277h6!᷏Q7ynW.Důe +V7q;m8.izrDc'dvF-bw,?WKw.0V /sHBe9cY~kݕ00?:^}f/t]xhrZe^[#+XkLl;aUl,ۗc6謶]Ǯq6؅I@6X@({zaW4:)ن߯l/)y;"zQgDwinnYӀH~`mqidwc1ey0<+g }#0np-*`51t ~'Bk\d} rg'@ay߲3.NY1\ 8{phcܭhioDi[>fP҆VzU}2߅1f&ƑtI~=޾}}|>#CQ0n" [l_{~XWBzao%Lzm&LGD:͵\k'IxE?jHMw5~I<5~s6톽ꖋ7dm s6+E;{ +յѥ~jEG._{̌є1g,¸q!|텊,t uǏy rg;ʺ»)s<+-c7m^0k/Vp^@97'CȽ̠6 q p6.2S2'K߄?70۵>h4aoԵp8Jhtm9}30zMqohGA] )J*{GC \&/"H~KZ???7G_^Gs6خyꥢEJlRgyu֓D,{=ܖڃx.\ؼH!rQ ޘL?㦘k5.m4TxznzhjiK8bU{%qP~sNF0c_>-}/ػQf`gWKNs|He Om(͛- _$nlj3C뢕o2׎" A6#mRf%޲IMm9X@MTgd~/x Δ3/c ƽt#;\u7b8 NJ*qܬ8dnѶVXGWN`tmhve7akõea*X҃4f E,yxy0{10r۔ e`GUJ~8.G ]˕n*HX\C#mԦ*vc\ﻍ3_Ӗ#eB}~qחx9wޞ_zqq_1-?W_[ˬ__5_?/?ɋ[TH ޥ8ɋgݴm,{m۶Rkm1|㜳Ϲv!baő((⻀mA$HXr={=c[+t>Fk9jAeZ-XiM[!YZR>lس$=IWO)%RU_^, C*uNK(9 KaXT =ЀbZ;\{cBZ2Cɂ٩b+&wkZYI3#%A(7VZr]ىBvTDZL-v`= v^&1"VpVf*t+/$|bDH f$D9R޳uY{uY#p*-jELJ](B%pfxW׭Jǯu8&BЯY-g_J_nد޵׿?ߑM>83Mo7߬翈/]=.Qۿ~3N <;FX%7h ba)koKsؽJڼIHPt"JCUWc̡ BD&{l*Z; aš LB:vDvͨtC0-%2(Yltm-T٪G]knὁ[!z"y䠧eui}=[jz92d0I1E!6^z֐B,E v8K -qBT-ފ'ak.V3la͒Yj?[E(W]W H"4 j&#x^?/ P"eE3@9D%M`"󥲮ou8Z.ac=leƧ?}9~r3} vLzʵ:;/˲ĶWղQEZ`* tT QFB{Kӵ(깫XFր4oiKY#,իFIu ~S>e#A8| (j6TWhg#R͢ծe UQYQ, O^K2.CtAG(UqEzxOKz,pJTm@c/a+ev#Fe5̥kINHQS!J媈D5yݛ҆$\ !HrK*攬J-tRRifDB1&Le't,v9)n ˂2mF{Z.sz?Kw{<_Yjxɯ.~썄r^\`?ߴ!y՞uꏟ7(?>Wg}coxg//s9=b=I\}|qLҦlꓙRQZ pM&OeֺTd:2KW0R'KL?ʊ0<.iH4" Yv\N!,Yׄ*J)ak0崜iyyx@\*5*I!GyDʔH.',KT`QPYhmCE^^d=Ty+[ LTk E ̈́r8 ekMӳ8bDͧQuXj:t![ Q$B*Eڄ,+is$ 4H@feF&ó2ySqu3kiY_7s]ǏOov*\ά0&b$Dlq2YZߺρlU^Eqc_[P 1YڼsjmmmVr=kZTT/JV_3Ӓ*3)+{d.$/^\Ύ~Li')'5TG̲ɬmz"zcU?%}ɩӥdRG)Ppߵ6ka&j.}/$#j@, 1IjoEZ*5U%XLF[DCKDez5#E2]$Gő Z1u9yd`SuX.>Wk#)"-+h .@U1,7kF[0F([bk-'YreѼBMV/oa#䰰XứmyY.ӘW[Oi>$kגs[uo__z}eY_v߶}o_ۇ!Ο?y^qi𥣷X~zwݖVw~dS=8V‚H?R҉hL*~$FqZՐn8L;k!| MH(U]AȪU)7Hդ`zW5wϖMY!,ٚPŒN]1D=+)bq'P++|E Y%D;P)T%) A3ɚaMeEW-/H̷Y!ND;qNfzuBbU\Ph-`sH;/'(xE5Z+ҩF]T!-q97@+\J9H#y֚{P^s"Ds+ɲQ"Ģט͋rGFU&xkd( Z`k$Ntccm5 "6DkEpLh'i [O]; EXޥ?'bR֥TTxF9!FPa0b)jVn&J@zH.#(bAĄhC3Kr_EƗֶZl(NvZ+DZ(z$E2k51K0}isq0I ]PUzwW'Ob2/~z<>ҖVs[MZ#kKCڞ U?_6 Ͼ]θW1n_d~O"3"z4YrWvij6w@f!+#*މwMiAȾ(vR'PI D SV2gIW ,~x,d͍^۝@,h܁Iob,$VbtJST4RI-\3sT޵M?eGjISRrXIeilͥ1&[_bʡ8 :T#*c)qd 2Y7P٭7!<,ǜcM?g,@l b7Rs_PrZ,+mEH9%㈼qC-$VYxC)tˤMER|u( FcRUKH1SW逮"R@p~Ț1 IFaN>&bV_a E >;(t{vëR$JzKO_wz'kC}/߮Ko5{c 785[jWV$ǛL&j8؟r2qMi*lاqk&t)Seł(*b*f9F! ٞswl8]dFvn =o/g2ʀ^rj O~J;e|`(-6˭;UV ߔ;sVŨ,"٫B|DGrAfXgdv*h02Ju\ d!93pRE8 ZsSgo=nPqD Wz[SQHGUnZo?ӭ2gH˨LBD*VHbY bKkKtbE"UR*RHؒ9@%\L#-̶HȦJ*?fɂ.5UY% _ܷU2l Q^)z}<6 m "~eCM tQri b T=2*sT{"s(«6؎QE](1/,Y]knޞ,vETYfD[iu,7xfTJћ.Si<&%:l*)r3LTQ5g|N]yQbmw orDH)IIc*/I"ZNv, C?JgM$wLaH.Tdhc"ԆF@{pߋ SsFH0( f?{HHe2"+/2܉6^Zz % 'b YK 9QT"@0Kp' zst#M;8"r܎bB5ImFDNVo,|- my W7*u{{?U5䵘8vpD%RtMYE*KtY-4"uD3Y,JhHU#i6>BfI9+13W*!JUTcxy&&'EPQ1c F6h6Aht]JDJ͆O.c@}@S1S|7`T4r9C1BA/97DNF̴E%@SJJ7t*--ҥkكzI)=mwAwzdEZr'U2d鞺} }Nv7%E󾛏:=q^Ya_O_Uk/cw㇣_/Yn/lW]Nd?U˻RwOwߝχq2i^.rh`Csyc=>_|~2ۘFa"hfYttD6F"=cWFk|1gUXKPĢk@}}̑_ZfNhEQG*~pI3neCON'!" rVP~b G6Z*DuXCU;tTIZZuY#DC]ҢDʁH(Iֆ, B$v*Y`J28UhՂc/1{*zAg ,bR XgRY8oJaU6 y3"F4Dn@D* yWeqKk)2Ij hsjf+ l רfufbcw w?h,,MĈ҅91<E5Bw []KTwm1PQYG̓CE>^֥-\l=($ M3,=eV&Ry8.<ɟqòi[e~f>NtS;w5&fJVj{ሔ*UsO&1ݯe\,J+Dw`YeɒȜ зR!}E9X q;jZOV)9CJ6i9;g}˝,Q&G#4;|Q!oY^%g7vq+ yNG.ĉLR"yem k쓬`֔ԛLE cT_ TLOC"”uQYŲ&SU=U82sh@vD*YHHeEv&p(EņJB@DFe|O?o?n<@-Dj){+$ʫTReΪ#Z_5`tz%t`:.n!YH$|Y\uV#d68*ϘTl"D*ҊstͽQ2EJ=TOXԔ*^ ,,9I 0$Lq+mYcZյ"e[s6h&PJ i"Kdw=+} 2Jkj-C2fX̺ŽyCV+R<?= ^JKN-$t'!jAǘTY1f"eY{ Nt40MNWwL?e]Ixwng痘1,TS77?Pkȏ?u?]kYCm)r]O~վ_Ƨm$?qkqbvw~u~u}oNlխ?qs>=jg=90euK#ι=޵>Ñ[ҦEymRߴ_ң GнdCi }hL\V>m2hO,5C1vR(U 4 h[]Κcv̲hVͪf˂c3VE vFȢY(d2bHPh.ȽΊQHm$m8 Y(]:\ pT-wzzWw]~q~=}}[|?,WݾieouqEO?OywwKYwნ.G>OrͯL0~}Z[^VNO\:ZmINzz3QyJVkQrf֢.A<4ÉV#UJcv {'|]SESgT-cY: 8*]ݯM b2˻՘H8p^NlJHT:ge`V.´ۖTz" zm95&ef 7br+B5DiFmZH)Y&iY&13D,vˉ>z!+Ι"ky&UOBp*&ɐHw;4X'< I*H{B#d+aL.z s!qJLQ)Ǩө(Y[ybFlA zp?",6z733ga^@[5ӌ,UN("-uR)V1D/%VzmKy~=8". ].r~!Z%ߠzs9 QJlqR bzVϚlkmW~5#rbkKܕږ_ԲQ1EH3 ffBת[15钖UF"7;T- ΚioSo9@$t:&)! >R4 umD*XGNȱKUW 5X$AEee]@BEr&zrr+QAV?<W*ٟ=;y^_6s`֭5bl-\$3:a)̛>F2jZ/ǧ䔏_,um?z[jO|VKK1{}Z^>\OwqwsO/}{ćwvjxϵI_i5}NϽ;},; T5{;n YDJZTx?K>S[bQ ?@͘YX;{ɢxj:(T~!i죕y8)Bfڝ1[Yb2w tX.-1"<^gyHfvl;(48Ƭ)^#S y+t i3!X\<(yƘ#]Zh?ΫBrY8]JQr' cp(O v2|]5YxVh:u]&̨ށ^Okb8f[;v?(+0X*.z1w_H+A$#uiܰWY,xͶ}ckʉ'MEբ2rʑB–#"œ (ȔIe}Zw6bOzױ1wyUdX3_Zs'R+V. _=qrVwj?EO/;$${OmI~8_q-'U#E9S#?/←ww}m9>ֺz/9_ .3TtX{4:m{+d4f 3f őb+n£)M,'YeXhKGz-CU#)cչr )g=ײtIOS>0A:oId7Oj7+ q`^L,(ד0:!P%DVzPѮ9pBiI@1F *C˄]nYhA^BR7>A@A](TYv~矏sZך3'{wYn%٣"u768,#.Vm1BHLI#KpS'؎r (QCUVD*<&ۢlV= &BhHɀ*݃gFfIVve4ñ6V5YDk{e[W)o!{_* E$+Ͻ9 ,~e=9?;_xuuܮm?b|jryY_odңZ8`KJLf3#~ooQ'ρ}ވmO6Zs߿;x^~tY_~?omy/u 3;vokl|\SQS6*ȩ=_-/Wù}~}=-O'ςG??7!T?uR;Uc64W.Ֆ*MMdi veN}XYL 1":`̌ ]IJԧϽP0}KJ1⯻.#gVt7)<<۝r+)"zfY%@2r{Ũ[ov;^vTUi\jwrdҞ)MM׭n7+揸{`JT-jOV#jsl-֜s^!10Ų`b9} hy9K1BidR"7mk{8V .}6gg#9ume3TN}WD >Am0-X~S<$J.XdJO6 s=s6rH[Ͽ?]^1x|, vp>RV-duVzYwQfz?}c"ϱou9/vw%f~}8$=m~>^Yߟn/OkaOWS-_ώi㲞w}O'_[n]K~y/ݻn=G7nq, ޺_Yӟzg=,?1cYU.˽[_XgibfD%+RL@Ȕ)٨ec6Oì9&BByYĜb9o5ӥҏBI9zZ|B]E) ',JQ%IZ OQDfjvbhK%bbRT-&F)J!'`(Sئ) UC,yT*1ͪ դt1Y68F("[}@&,1SUIumS]kR}UYK M?/ôY_= PinDUK"YQ5 )NϱosWB՞XEUHӚG tEe@%r$"O*x{6Q+dhEl-ؙt$\@@UL1guY; Q#YLj S eRTXùd0fjüAt!.:i2Gr^p;)F!£.@cJ71[wᇚb,z=zb?],}("PR3tkbYY$|Æ*yZԌs6nQ8Z co1ї%ۮkX]4#q: zq;ɱ p ,R-\__jy\?=i:XY_'ˆ>eyw^ꂊה|ZmOyW_vj[ϑ/WyfAk3?ifsV[ᄍ;}mv>纍,.`/M=KH *ViMgX=d!8SKdFY@Yeɪl9GS#D\p-D1ʹ eEQh2 BJA 4ƘDA/:߼1FiԎ)12T_"Zra ||W5  \k ^@!57W[,aܸeGY1`3r [س(~o5Ej@:#l-=!&}ӳaD)YF073ۗߟ)B vZkY֤gԲL%{"E+!\&M\Y@(פGBFUe24[tiHѵS(Kְ}JR$ݑU]O22 ܣ:|T~0l\<$O=Y+@S*U$܌=JPCP\ݯߢJUg%1]7s1shzH/u7mKuzHbzddNMUYdꨌH)#XRXg \iH,kJT*u?Z\0_˥=dK) rGS/7Y܋m>vxvvr[tNQUy¡93SjkpsƭT?~RɬqZ32:ߵcm/y0?ɟ^3znr;Dm$7{a>"8a:*qM _O|[ؒ!>clebE{}zȻ˼ ǁqmEGTUwV(5͐EEԃ-+ωU"=k (+ʃz 즲%f,E= j*NuߗE[CҢ7mh\o+ ud (*r" E+)iЕL_d4;c¥||&brȒ)|f5BMl@2$mJg>ZR)=kJ8AThJX9D)ܥ7Kl,%yx%g*}&R'RW̉%^_ǿ/~o>8`hj:%y4mQrjʩehM:\LnGQI RUMDPs,l1-MM5%5O}Vf7*r02zB 1&S#n1||5<m=\u,ɔ55ǰ-Yy3 VJeFi1nƪL#7 ی -QycHL@ڲ.6<ׄA1,$f@Ii:#Ƭ0Zbd*@ns]:+ fieetONn\{n)|ڥTS7/ 颈1{W8IA]  T!ި"M#x򚽟1gGVAY!clrK:FlydAo?J.(ڹI|Ͻ1u ,=+ŷLYdǵ]G')|2tr.O|8s^>ƾ$Y5z{򇿊ۼ7R̃A>s/ެsG|U;4|y_2*s#^$uk(]d掜nˇSW݂pRKr4T{gѦأđ1TRRQ,rB,)qH#kNKO58Gg-]K]H-swƖv* @vd;CdJ[*ze)0%HBFEgvn1n`9 Df&, c6w;fxo%]9 !FLԥҩ@&CDIJYH㕩J,#ɔ3Q%m5n{]>_\H.%պr:Ȯ STr5PRfsv弪,qDe&9ydYU.$K2~WY!zyLY$I2IF ehqB.QZ93gh)3{8(4/~y(q %K9kLM#^QlGZ8 ʜJhzWp,ᵮo>zj~~jt.<^g`/ԥY@`[دLXY/]N]:5nDZQ3jr~𰱮C #q*'78oy'KO||>Ov;Dw?ϟ_\zLۏQw|9d/<6sƛy_FWj} _e;sY^΅i9cN5K,|<<# Q}H>s4nܮ!{w3|Z]^EY՜u6JNi=k1df\rz @x^f;5wIDХ:CChHjN;;¦{9GɪJÜЬ_B !"pe)tH@ 3%%m]B@en t"ҥXS*V.= 5˜ ];AAƨ+eT7Xīҳ /??W?˜<]8ZZЅPcnvU"<;#rΔ VܼZhk@**S.2krNB(Ȳr TZ1spG}/į"z@/9cM^cĨՏm>_^䟾DE]i_M 30xMB臶QɆ5Yu9wd?|UGHs,'D 1UyZXSlV?~8B~\2a[H49N?7~xw|"!uju{őq0?]]?μO\>r[;1fy7ѶdSA5D̉IN & r3iW+Uzb*48WSNyYZ]gƐ ]3`H FBL`!Me.}$PŷdQ@ daP@T%@NyRRq7]-y c@]Cb\ + ReT`tODQ0B9, 1]nlճve\$w<*d(ZUon5ZB R8>b8?~/σPQ:vJьfBJD6``ȭY*JyPPyx>VS*r2i). I"nzZ˥wmU,]H Jx$5C{ (Hx@z^o|/:)J+Yz3nH5i O9hZё}BX(7;sMkJ`?cΜ>h KMp`QKLjŖz#˥CE(sc3VA' U;#AfUBR۪KA 5K.L$#u83d[\>+J"7P5r@ ~h;7:A&o`,#M2]Z>u)W31ᴸIeu=RY<7eϜ\8FoxຟDS a>lϛ-xz7x>ƧH;udϺHb*d:>}py1~įgA~ӛ^ ^ /?xOrDKe^4vo=>?W~>j=r?6S/M p$Jˮ}7¼.l3_ڱ>p4aA,fs6GQƑڕ%i]Td@"[QKTz>h*?h>H~:86aD")~2]}~vSYvRFJH[Sd Qdbe퀗`ǎBT-Fn LO?n?۰=t! Wu]EwJ] bD+#KȂJ`A=slOHߒ 2\q-G,!p<#IbeRp2fY%rz*eRD XQ,`xO `H2*lYHABce@<=p:1j0qHr R5gpD CpqȊsTRH)Q|Y8rrq|/ptƖs#Y`&(1R)ssZ*]}Ξbƾ"{ńBT[R} ذ8nzXct{Sm}ܢ=NOo/׼LAX3zl}G顮%cg6.ˇʯ|;O?ϿoPTay}_x&IiwxWHQؗiw _^bZs:1,X OYcl :4"v 8-louEq1EP1}D`R) ܉yX,զh5S,A0r:q`&껈&#0&B('.ɒ3FH*QX2yއB#qC:qA"pIP @@vDi}C]LРb>{R^W@g 4 #(̎TJ g%C(ӃJ&ip@Vb1 aZӆk3=-= ZM%358YT$B)'ǥm%,8,`N9-! l*5`B&µ`Q7^(Má0qTA({( DX  &ꨔ &H2ae0) L $Q Oqm3`xsY ,0ç1 bre8SgrQ{Ի,8/'-04LhjY-ӝ2|Ҡח d]Wu֞Nt_G:Z8=ԟOcizWl@0o/˯ǥZxo/AOzz(q[ħHm|}c?qQ3c{S (/9:D9qYR zB|qLs2Is&,U2յ#9,p'b.g8Qp* Ĕ43 QѐLޕErR(MhwDzBK$(--7F0QE<#($)=]B0P1]tg%HsdI_T5h1& L@* @0p`Vs'rt2Bol$2rXb4v>ђēG`< |\%rL%ɦ)aX`J+i&m[yeL(`>hw$yƑHY{Jisw4<lRLXs_ xyͶ~y k@BFB2{G49bZ=n#ǐȜq#b-x$(EtmH)$#Ѻ9$ C"$ S8hI"uyNdr3P[{w>0uwH*\"3`aB#1Q@O(gO´s0a"C}8[TLD(F>h&c"Xo80Cx2&2DER\0!s.7w, ׇ_O[߂Zl1Yԇ۶A8$r"2]$ -9kquɜ0osBy5caѿ}"d}z R_ew'BM>Ʉ|E?3><ZIKUΙ?#VX.~SEZ+>ª&/y'<>pwp*>W=>"ТXP*p=1!F8^T މf$R;@L4?AvTe)06`!LPwTvJ- R)#Ox49B)f4^Y4b78^S"" %i)6>st 0gPdP"Op\ ƻ܄9A8 )UpRh܃VJBL6Q2MOq#D`wR1<4*K $y5U!#) FaR??m$RP`CD AhZUMDN^ܺM$u/J4gD2bwn 2=rF.^j&0kzRD;lx׷>5.?O0`V 6Kv|v=n ȑ,B5XZ.8qc>PJ,"q| hىO~  A (1z4ӜИ20 3{V650/uMPʒG-4hydsPN!4$qBU*# @Z8A)93u,L8A"0 uCRE`:8mD 3$63O@EJ[OQOێC[AߐQo0JqB$A涀r8H-}mԧOΛnTcҧsv"/pwGvq?C >Y~sY@?T 9 nhjy/?ރӸҨ@5ʩ<x2_6w|~@BXىg\sS,ZV *1sVS BN,1GPx'd$ Vn♁`K5 8NES%u/O`"L il$ .Q"̌F($ Ġ- @0q L&H232p:SS#0"VfE84ɖW@g"5tX@ͩ +UtH@ا|BA`Ёj4AHaG(R(EO׽j>? 4FR9noI6j)=rn$5(*æ=͈)j`Ў`1="< }o@E*}P7 ` cxN\!+L f}ƄČR)|0Q"SmČ";$I$p#3C) IDBN\h\ݜ3 w@u&u~3 3\xS@"G*qBa8;,q߀+C5q H&KQwkr0rjOp3b-!BI"Bpd8f D^2R)Qa aF¤QR ]-E;a{g? {"H">0af"5 Raw D_3r7p^}[F'COo&uwܿ_P <ѧ,|^Ӆ7μ~Taˉjw~r?M|O&'[bA8};XAtlx)qzSW& ]#϶$9$<,( A>ɸA#Ay`w|­RN"mL4p" T)f(aTD"9&)0n;'Y{.cZmң GTt-޳Dވ)}K^aE3Ac?B0& @gR̓Cr=3bS)+#aP*1!2~A.GWTØ H>2"D¶!@OŀfdVHb*$XF"vgD"`AR+F؏ǷȜ r)8i-un)TJK| s:$B$<`X WZ@B>2DitYt^#2ZJf}t{2ZӿӉ9<~`ے6m18&\])IN,|-,+QDD4G;%~>F'xz\k&=Jozn/)_aV noƁDR"广b iQ&feP#߾A̘w|Ӻȋoyl,\Q.,]OT$m+uAŷKeIvLΧ)XBl( އfRS7$LtELLP8 2LǛeY$o- )A 7D'dJ #:N(B(0%;r/<'RBBi`;9\/:Gng#7&HdZͥNؐ-ՎJZ AY}qIϽo/_<))"sQxRFy$ D#1:J SQcL6 QpýZE@-V%ҐIlޙg<+遙!%3#.bj2V[ᅴv4Z":SZL^q¤Xί֧t~\?371B^;=z}0_ۼn{~=mBY`ViQL=IAd9Ђ2*D2(لxW CB xG mxxѝfXNpw#i;2ЪN@99NlN$V%mbBx% ! u*9Y(`"E<2{0Xh:DjFucВ@5#*>**CBC“2ErȢ I2LT҄{ԙ ˧N_?Ng5-s-ƱWOW˪ ;{oCՔyט'x5oۘ^Oz~eyKr(cl7SUX`Gs9{]0"#/wnߎX܄7Lg{//sqK?<}1Gp0O?0y$Rss\9o@¿A(0"E]_Ϝ0ǕdD @Pa8bZh4w! `ߐ@{7] 2H$L]|ecv|__ӂ˜CcP]ǕqMHDHXp!&XHf PR,0n}@'ا; {1Т2w/Y[ HkIi,L /wxkؤ3 ğ~~}էvAn?߀tp0眤qϷ b_P019TJpoaV>jeҢH]JCnHugB ?"2@Yxd@TocbZa31)`U'$5I1(_pug>@Ns}z1ݝyL4..suw\CōLgudns*Tpr}0b|r@r9#g`$m$;NW@ 9t]b9qwfD~(,1HWRPeFabxO_ێO{|9:DžN#A*@L$̬BTUY#`6b@{ڤmc|4|N8KD(VYvJvjDVT<-w(G4sx LGIƩ1ʳ 9;aqD !eVflP͈"$-Ht ~iC ـJ >sHzX GOvDM34K- h9u>ԷW ERIMO$>d=3:ωQO VC ,"EX95he~&O|\* q`xSᄒ/j@BzQc*MkHk4:xE<:xag.+.$uި?xŗѷ x[?a|h? Ne}w۝c^rm~#x_u^Tpfa}~E rP *Tb9ɹ*hS.+/\S1_?z02+gZ(h;''a C8 "i!m+u.Ooa !J2՜zኅE!JMFr Ŧĸe<1܈D#5|c^G=&`Ci 61еniЖAQV5,Cz:+~5]x{, =wqݿΗr^O4lߝxe\(^t,@<d-O_>H?~޿[zs2O.z1&ٷ86Ga<58WOw44;= _?V"`\aڼxlo|<>lC~tܕe\ 3< *;pt{:'&`G`@w^!$PxJ+_}#$8@J1 ژCP"&"Ӑ 1{w%2" UUӥLJx$ qWC|:VT!L HRa`p:#s? =Ȏ}nE3qEYJfIQRVB1pDO @dwK `XϤ\peGD((00KcdiQ{Cz 4T4|"D X"//~ &dȺ@4YBJ}Km:LNC 0!Qy (s`P'g8 *+4VmU3n3f9i~'uTδ'ao 49}|}~DX#J|T! midt@JJ4g(Hl5JI7=eB 9}'L5ho #f p̪ȬML H;b&  A<VkG(\= VF"C8[s$6L.B` $PI7. ӝKEY(O B2\U*S01P|9CK-kE0Ѣ1C<xZ<^Rluny\.> YʉGG/@gzKK8\ti&"9;܎c#.uS<|(~m;<,wEU#7@(B8 I"q:1*OKUHa.C#%qaC@GLfD5sG#|0Iy- ժiD`L,2,y3p9ɸZ**iqd] +dJ s١'J)vݡ 6- iOY.PۼXzw(z=r S_OŃ;ᯛC m/uY۷oV뜿38eާ.d˷_揽x|腵j~/<IN(xH2 ^^ohvvxc[w޵.wKɪёT Ѿ#)ڞLDN'!!#c@f,l[}~y{|7D$5 wF^O vQvth儰R Ey]QSۙrCpWk&/nC4`g4+AT#99p8frDltoA!$ؑ0T8C(=sHDc]$ FvGO wp3ar'CNNp CeɗT3b4OQV;削P8v?jq -y(rj]sv"N9[X ӑf$dlsPJ!,U$!p9`&g)mua0}$_K!éL[H9&)h|'x)1"14NRiVA4 .yx'"漴dvclch=n9W)94 ͨFzim?lh^rx+!/K95W:*~c 5H%Z1NkyWpm ]W=Kq\`t#{|}9lJ~Ŷ?t>-`'f/5}Y~- )|e _]-qNo](o;|_'_riUκ;R41q1gR7#'PH,HD 1) 2_Qwn=(-@ up\Fzi&'aG@D6BL.8/@b!; yOwpDL4+22- xGqCcv瘽u7)B+9":Zx9M#/ -L(gDC "'ꑀH;QKL 'wina} "σ s:4}O1Ʒo7翽fggFbyə*M+"fRq Ӵx 0Nj3o1᝸2#= e%8KRZa-}0no䇏򱶶217'KwY(bGbףk mhQL*y8$RMZڹaz`)\14 d%Cʆ>Z2Z`2nT8n8C;NNcX'1+䜘adhaZ h6!#H%X;YUDQ(4 LȌGpνi)ӀDTIA 7)%bG6I\3]8E!Th&\WSn7IG%`xE KI +'Tr$tG°|vƀ["+\z<1 AU=H,:tAu[Ӳ Oen_<-ߓ9%_7sR/wͿqI u=<>ȢE/k~yO腳qP輆 ZyyU b:vXe[K_˧r|HFJ833'" @#|K &qZ#̊T^zݷ>`3Df ABM4:QH#3}E#DL+!fIgDL*8125hcJ&D1d03D > | ýλ۾Խϯ163l8h)5=%%ó2tlw6I##aRff#Nb0 %i#"m`NdɨK#%$s*[ A ސc0,Vz/_˷V֏g Rޝwc 4,+] WCx|\M l]‘Z{'hib/VKyf@b/wgR>XKޮ⒳x>pY?+|k֧'->S\jY@_nNwqiOEۗmsq|˒@oWkOЂgR:1|Q`w~oW{#HH6O>/O\k]" Rƒ{B$F Pqnplc:@R'̄T|Ў%3&p(/wǏo_qlSEI fBξ,4Q$ N]@&b$fWLPeb^h1"B=H='q1ޘ{O pd.ރ d:ն#::m\opZe cJ dJ` V ͕ KP *hL6lsg 3H$v者ZbB+`UPgh1|ŏ/~r4~w@5̏Q gx=#+GdT$,D!=ͮ)+Ab6 Ѷ.S$ Y%pp:Fuv(tzpY$ʺ4#aˉ?L>mul#} DB(.iI;86+s|:d)UDDm-#Vҝ$)JВ阄|H5pkDVrp1p 1 :zv&Lj aiL ӓH:t)  H뻗6)Lu]f&t cB :҄ dg TFH!GGE@>8za@I1I ,;47F* xL@ mr}$y6,jл{ŵ30*Ny4Am ~{M78Fzk^[,\}MܦsUFdO Ұ*c;|`rsuZn?mxIv.Oi1|7%]ﵕ2`~cb^Q2_Y?,g9w9w#_S~wڊ/,ccП$$AA#TqZ vL4=y77"&hR<J8":RL/C ̮ qY[`k1ui9UJ3cLuёy ,Z:B',N# g@]poT)RG?Ñ\ 2^ݠ.?'բx` SpI֊.'\>"tX.ڤU%g#r$ &OW1<~ï_FNI>pb̶LԂ\tYl`$悐Bt$Ai5XMBy#`'F_$0Io>j~Lԕſ> 0s[X&7fWOZ<"D 3ͱyh%Od̉Td򩹥ܧ@p$E & 9ёRN$H"0Ğg6 4f v91fiE&LE'paEQTdi ⌄ A=BnF $V ;ߒK7n078f7yzQ"|| Ci`5qnAkqe:F&z4(,h2$L#η&S2'ږP43!7B⧕`H d_ހIP !09kp22麐1U;JCr` +qФyg##Q*/3/evaGLH-ƍtѡ:;"Uk}UI1h;&ɐm/OarM[2&~t?3c|>o7[>~" CD|]f*If]GAT`dJ+`;xr8R (c<5μf䑩i'xt613-|}Bs@[ u t>JxdcdI4Ia"zbLB3M]1Љ 1a*Q4 5ĪyA5\ ҀJaN( )HpN*X.|7k8^HfS#A8K_R ΍ +oĪe*뽦8eڟAr9{'Q[)W sX˚;Gp_<&(C}ƺ(&82oz̝x b#jܪ>n/_@vZDlx'x!Ï9+TңUm mϯ:/&kH8m~㘟F̼1Oݟ?p9rDJ+saLH L q']sC䎀&J@H;2S8F̹kAw]@Ow-_?[>!Rfކ8#H88&PxIC&p020S##E R0kT ч "H &!! )+gFI<t8^$`di Ul(LVr4nY+0KaT(`aҐ$ґ$Ck%.ϊhIZCȢ,lZ9GJ 6z?{ݿ/׷a*[RDKKwJYBGR*q!H)Tyi~!E.*<҄a18"HGNɉis8 w\JN`>.s{xtqwB 9#{l 8`8Nî!\+̷G"6b^-ħIo#;w \n__vTmt?@\B+6qv ==JvҼ N8_Q/׮wӢ,u,5$J,U)%!m/[^VԐ[DDToݟelʗC#SUWI{\ֿݲhY+تhuD>-gP,'YҡazR&DRil#فΜ@o8K ``tM|xoD8fA$tgy%$Kl;&OMخZdC&FH1h$JSHt'þG+0=gJpc+UMxqN|\mhQ&r03yeLl G<.ވicIs*ݎՕ:Eřܠ4rm|YOEcKnnPǧ3t^nǞq*Q+?:6S|>q۸/['*ӿ.+gA(Ljn}popx9U*҃V/' _d cp8*p9[o-S1[O$&4q@8/,\E@d1"9*Y吶^}7sCT$2Rռ#;Os(JlABn2Z50"L# " @IA nD ZeZ LlqG1+C]Hñ16cm=S"&-jӘܙ(4l 3x)p Ep' Dh ܹ\sOR_GVN$4+`Ezbd2 b.h7IqG`PHKm # d>1Bah e0l؅jb-NLщs,`Yф y#gha+ JF,(f,M2ߍbJY`TĔ~?Heb=OFĨK@@$A(n9vK; I67Q؝Z4gljO/{>ʳVB΃I9ݾ)_"Wg^- E֒'֘Ac [W:/oUӾdy*CЎʹ4/W>]'~Q}uy(|@!@8~}{˯gYNd>@#2 iȕ8O̐3+$ BζR*x'.Q}?s7|= ^v !ªDIIR<*Rg"(\@l %(&i%W&$y; s%J+QH`̄&߁sKԘ# ) 2;/9\[ 7:,MB6A%kщ,QY:vRbL)ɻ/vbefb# }E0: "fL3Ÿt;j,VRHPZ}L݆yyJ⎂s}$| ˃qۺa3q-tk@OKݎn>!>k7m).U e:N2Ky)Zurhxsh:a|>%'<5 U -_|ށ 1}v/.6)P D#a*z RtU |\ށ/֓";c He9Ҩhu!*TM+$@a7VNB)rOLǼ} e<ȾD328D"\JfV b ΌATSS;cwpDw"PfY4Qy UaYbq(4zFD4H"0 0.Ѝ.<P`M߰'%1!/W=LP\ qt# [^~|~wxD Ͷ?~n-l42I1ax0V"=@AU83<q2 B0dd?|#<#TI  RľR,ߎQ*5z⪼^V\Ni, q΄PxPy*וKn9^@p 9]4$ΌJ fTQܡ+wYfX/hUjs>HnN|`9f$]}&'$'yis`9 f'32 @AB-dsl0OfxȄN!sIFC_sP½ϟ˜޷n[R]o~ڜk+h iif[p;T(^ IYCa`2cc~pz!a "T00&K>!y |'9 $HJ1*L?<"҃E ܄42ShPF'GPddh'JE#_ !BMѱF؀aI!wXr~8#fh}{G%Y8]Y +F ! p:R2R"CLD>R"{be05a 9X#O(NI22vۏ}ݧ;*Rw$ŭT`@hm!$ HH-:1Tr">0ӃE .۶cY'.DNXl̐C ."ܰZ`y8=\rZE!8sy013~cYΫ,DzܿMwB^ `  ypČ@F[4VS0!|d'k%'Jn3Н jY3)ݓ r{~UG;qX DgH S%tR X +s$m}` P䓗 j90+Cd\1 ʘDQR;˸>=cE8[ IPf2k@9}Nh'13XhL-dʬ}Hg}n{{n多 ir^fc?t)>A!n}>=NoYr:\zXCNZWw/CyR+b&\] =pf%׈>݆?uh|X?Z4FD C VbZ ]WdcñX9q%kz!{U- D4,uе ^ӊ"ągnXHtx*$rT$"2}$$w85D? Q@i  t׺z`Mԥj(eIL&f$Wפ́kƌ!`q dh-ܶrݱϾ>M! !_/WrAԅlCl! |g&}b2fD@$疱Tɏ( #| $pTqF>DaÏm`bg܄wa0r*xǭJ9xa5\LõVGu. z9?iiK}xX V|136::&RHrϿmx?t69 7Iā9S`!?˜*<4Ӈ.e=!1dGL p!UAH&ߤ06 1b 0?A oRPZ`# b7nlfӏ>q`2Ð}1#QNVIMR<H+`p(.xF)\.¥0U8(-IZrDb,19 0PhwA"*3}omF93ץW9,],hDDdfRhÀxݷΘ$ ][ ^J? W-'.r%€JL @I~xӅuQn'Aͼ%}y0@s%}dB<;:FcɅci V%Ak_V&F7Do%N  $CLpAx ypR~!~`Eʩ,|bJ\D{DF~;S ڷ^ VR# }Ep7 I0vH Z( T.T3eK9)d` ,NT N)b3$ ]A8"RبI^—6XB^ C}z uQiOY!s,֧y2; \Q{i"hBog>N?mƗ<[Cum70wcydtSqcG9KA.r#$&;A![3聤!<*B9ALbʬM|@@m/d)9gYD$SU@Df fL +/x s@Ruie&ayh#iJp,ZJ&Q 6jH[^Y[2riJ\ᱝ*4z'ֆs đ4mf֘SJ*AY:P &"%Q̈PLdRƌ$֨X6%ʸ8@:I A e*ae@e1 &2 i1Oбu?m~@bvr ܺUeDd ` 0C)\&S2-Wั HH h*ĚӍʙBSjF~@\lwjT94 c:Gr4m2{B/uQ^u}"8;Goǰr<;)>wV v-[<Ό#;Icrm@U҇G oFyl/1B?z=^ -"4_cmx#^^^Re_iiq]a/ynm,?7{zgS00銋qgYe}u_o{>ّJȑr0p섷'DdI;r<6Os*ͪ +r9FD&?4T|r Ra%`73LT;b8$!``r/lq}WZJJ}R9$É"D @VD8 )Xq(#vC9Q&߽{G<) Tv=-mAm=6p8%0 G\a*`e ǤIHmZ $@9,8._^jeBb\zȝNqi,_up j^ 2"ě(kDFQ/ƲJ01IwA`B Za:;W@\qt%ĉa63-is&BأOC0JC=]p scQ.`#!\,dx w7S)#lE, 8Eģ81Cf,åfhȵIPRS+?fsL6㜘BĠՇМA+"a`d'YB2ZKjY"d6P؏9^9eT^Nxd~-׺fE_!k _|k|Cjr=ZVpvuURƭH<>~1a11灃a~~{Lÿ$kn|h$H ^%|J 3 X|njh> +IrL`7mH70x"rsre)#Rv4-UƆEOJo3Ad Ğ@ RO]ŝ.)Ea;+iac [t%Jy?`?iO? D\42p1yF!R$ * `!  0Ὥ }"5N YD Xhˬ:6wC _S$G %5"I`FEJ(,P`-YȏW'ɗ3"@U1C@ BCgl)$S8T1N11&@YN"16q m;#,cGds;+,ӡĜUϵj$V% 0%X09d@̈PR% s=C BD>S|?oqL HGtb$gUjM!яnl9O6&4 Yjc* "c҈hgdؘ'ô@ !>ևs&qL\ HYb S9-Ϗt~|~>wPELg&E`EqL3^a`LƬh1 __'3#Ofw"3#X M038vNDHARHE+bY:-L5St-P] aD1؜htvHH0O4't-qbpF@>s`Σ<)=x Y$D+nJTXqyc2Z"'Pd V{hM&i9=8g!LHΥ0}ܐX%7gS]-|]R0'.h};܍ij_h_JYOra"k?lp)}ny;{y'r-o? /7zԦ(YRK=_K?hO'瀳j?z]T_$m#s]gq}Ücm?wOzZ$fJ0;qgC7;QF8 غ@n \\= CecnPg︝> @\<)E&UJCz! 4` $ML@bO,nH9 ^[p%/@!"=j&V*Q0,U2O/ɘLDh{g;sfdhXm 6ǎ yy~Ҍh`&aYcZ:,U /h#GT#2LdL9'g%dF!L}'qz_~~si$LH+UˢFF p$G`a&))fgT˱ X$#GTif`0]ϜڷK$<==,s 唉nPY e9=JKL@ JO1PWP,*&@yPVS(Xݱ8.R\)SEtItqH@h #a~DP\`1 \N%%efLcĴ))Xrf@e)3DܐJL @JGH0;#__YmO{gUK(@SKIVL8T3BrD^<+w:ȽG2E6 10@vD6I ؆,"c}^kghNkMyVqYO8WϗFY*n,|>eV G{;}w,&_s=7O5%d{DklU!>z玾vyy|xv.\>aYbȏ~aUoH߉hBKB}05#ygrWFo?@dq] mg"15W*@p'*S&"K}͹s8$;j#%&e;&bJ@ZAw?~zL@H*5 "/U/gi BoPB(  VDD0v\j9zA}dmtǜGoFCjLN zI󩌾 7I_+ 6RG\p`L9&$3dwJ%"N M, 9$I >o|z/7-T2H2Tӳ>\` 3sN*L9X|9Ab)+W6 b-ddH 0Mj]w]nF. Pͪu5 Y#:뿒$DY+ 81\P,2="T*e]U0P(x&NrB7J8!Qyӧt,6pt7ߠM!3{P(H2-H#Xxd1(}6!BAքA(DW-erHb 0pH$ D`Pu{kՊ j/pl8!b]Nߟp/ iގH HGQw\* =@se ϸX{ra#b?ʥۧӞ0 3c"B6B F1 :$2!H/V S11'"QhIe $ TITQKޮOx~#F8Ð 0J}\+=&BqxPLzn¹lùAė}C÷ֺփ:{ЌP.o>ֳ>٬oyyber?2?].OG]KJqO5-aQ2D [+) f'=Oj1, 儱!;qWcӅׅYkE9 ,"i.*o؞`B&Pj9qGtld>Ȇӂp8\<\$qT-BN` # wZ`>E~4_Jsd*a2P#D ng̡ F|)d2H,$+̀;h%D=aKʊfS{p ,fv{P8qbe۵P!+ ȉUHa䡕ÊY 94d6p CAwΧSfh|>'@r^ sh4)Sdfā`Jb8wsl_>4>12z{IbIMqZmbOْWQA˓^e9^wf_.~Oߝ/eturjovGxI<|0rm =nm &|-s{.JcM/[*]=\jgw5<՟?m)yϸ]߆]ߨ,PT:bBq?!:'HWU' з|aAZ At@<;T H LؽЏ^N%cbq"t=efxbn s@1|! cK*Kda,ò,g0HmS?@. ;' T"JFb%9DF`ØE]2bUN,}Gsz2 R>I]aD&~)e2'[ L -[$(%EqDI̐I@$%_^7??N,}čDD~ZZ{$5ya4CAR~l@f.P*xd8]n )vnpo{l=}c|֎u4^^>Ӳ|GqXrw @N< ͎u]9;%3hN;#{?4v.<ևVoN돧 if?٢`δU4Z3ecOHwLژ 9w'eIߡ961ˍHKEIB ")I+JAX ھzm*' L =b#0G?XX|n4c1fY!D6X[lVa̴'RʬB۝Z3SB΃&&T@"s30A0ͩ*,m^>ο_>ZKaiv`$x.$$C E95mfH:!hAZsʴ{J=oÀYpZs cFd$ؽ\X5qYy=5{:$ȆQr wރe9/ESO' BH $bngωkmX@}$DI@)9 y)"JYB,Z)+2 NJN ,hs"L80I {B19=pr>9Mzt.gaCF,k%@qfޙHhĢy#DZ8҈D 5=$CpgBTDG  U4b#B`3!s ˼<sy^zts"D_*x/,ٻJ Rq\6ڢgG'Zm6/~ev7,q J˅$D'Ge-ss s]yַwg:ʗ>W.a_º k˒2h2pё4A9}շʡJRpaj?msp]u!1R/Q  t!#h:9ؾdi Z &B03w4H)00 ]!"P1"7TLd3{rRA3{]cc*A3I=X/ D5 `P]` (pd``  @i> ڌo.{cy<pܡFĄlaFw/E{0Bk_)I" nZf漳%$101Q$8Op'ĩJjsn㧟fH ,TS<4^WEƌB*soC)2AȋR1;:1Ja5'&óρ\hNT1g>?<*z*b֗ eJ+Լ'&#Qf fdG?kb sʜ_fD%Ik@@Zf+0oW| FoIr_ /8~ulv<x9c>Kq !҃;cmZ nu9,rLW.0:?gts(Ǡ'2B#۴'}b>Fqz%^p%Bœ(QrT r@]|>X6rBf)3]FP (L3`Y<5CAeMDB. *M(v~7s~ Lu)xEۓĖTDTNz X Jc { y=3RhAi>1b Ȍ aD=Z*_|8",܈#%*x9~7cp[p RA@eܕiB"i]s$ *1Nǘ1$VL\9$L=;q-1ϧ&A3]꺿HH~R~<'}nJ*n>l#u X;AV!t;% E?7vtR"K6ᜭ0G`?I*df3!QXI!f]:?;NID687:ĥւp)n{x'u}>H+H+W}C{,9xr {և7ϋ6]O}n}^珏c](8i8|T=0nrt?W~٣ґ%>i 5#ҚlZ Jԯl:ꤋ[A&Ucb^N9?afDjӟ}1Bb"96c&AJ 1l$aeXj@v$< 1(QP/\+{=iSʂ6qyA.E9Q k2r2b*h%\-Rg`S><3Eh&* '%A dp 6wny1q]8R&02R0AЎ="Č3(:/!f瀕AW[ bThx_fF*9hd&l.`|^BZ1)ox8u-EGH$ \jեɃ K' xG'Ee/[zH)(`="FNB`gQWE뒐#H",L 1e4aPrJb&@Z0'g`6OPD0ra+$(d93Y\$Ӌw|}x"Hj"I0aBp ջYpDpExai%2YM.BmE*i-D H\)3+ӇΔ={eO.׿f/^[ndR c85*l~7Ф}z-,0У)VY2ffAX{qn2H1ۆ ;HEFk\+7mv{}ïο 73;zյ ,'!nF>mzA?r9/O_?s~|&<Ļ7xr KS/L9/SX/R;I!Hj#:2&$twgߘ_C/D\ T%p-XYw&LBabBXΎ4'c% RpLP/ P dAj @HD,LzÏ?e8U*gkiVe.H<'AIw$Hi4 BFd ;09^5}2)7?F@\*Œ-dH)ӳp YpBt'Hrw3{#vgGd2BѨ8P_O?_yp@\T'`,8zuǬ BXDFw(|eTaۥH#ngBrDRZߎ@>ͭ+{(bϰݤbUKi.䀉@0oAv!z `tB&oQF:b:P0$Nw%0"BQ݋fp)LѬc`f9nH`h!06""pPIdED0GQ @w@6;({{Dn}聈\H0cL0*&(c"*J0qwJ"QQN3%A0 rUpvQ''Cs t%2IiSƤ C_ߞ~{/˿|q0% +/4H!8-riHh$Аum0: SDGyxT{-ZiqOPr=br jY w*E/( #/X ǚejoooȰ%g_<r|]^_\c2̮ܯ#7 ?|^_4_ƍ~{c]DDW(ƺz 쀝 ׄ1BaRDd`k,;JHXlD%S W_1G@O(ZD &2NHL1r"LöLJIb (-ڨBY*' Bn E3΁e! ̙08uL!cDAF}W>u[,䤔 /$h&N: ԣpko%O~ o#V=Ai9i9o>6P2UtrץUK6t jeab\ٺStn`sSL4/%=7č|7̙RHRJJik0h@I'8vYS~*SjK ,n7VBYIDb,+斩 cFvT'4}p]bL+YR2KF=cihiV`[ulu*U ((3("#Er2/q)ZK $owBx`Gmy&L&Α0<^  jpd>5Q2Gٝp0 H$SY |9DqGctTMfBXj qKnGKCۖm%c1Ş_ӏӧztɥU:[Bc>T je8 ,6={hǗcFևѷXBP:LoE#o_}KS?K-ɒa{# y2Uukf7)$(RcE45)ofs"l|3{mH/l8YvVt̑u!pqzGdvo&9^|Gק( ,I:8ϛM{cGt%LzUGbIS>N`AU#1A)1BD 0 81E0Fǒ: n%N M ZjX$FɌDdD0 Y!"YD䎌c>зP0%٩\)R &RN~㔈hh`fÑIљztR(|Zp06ľ`@ѯxc[\*ܴ+}ЭjnZ@>c]8߻Om?֗D78ֵnN?L7_yU~]ox nHn:@'!v' u4j"Blg>,Ԑ%'F'37%&y!zY5 ש$ Ru`] &Adx?n?{yn?:M13SX`t3l+utSASȅSq!b}Ua bWo(/W fL옼3)[#/CpbgT3C*p…N,9($ C:Β $ b&oc{x-pԛC8yl#1SA5Ys,"5 9h81z#4cGL0\-FVlB{!{st#IAs>|6@'4^04Ԉ(vqzə=+(% n F!)X-MD$9jYxༀ0rܼxqY^1/F Ft݈s+y}x@2ꠎ @Dq _3  p%`\HxnjD v0"<(@ (+4W+y%wVـY`DF )w)|sVĂ1ء; $o zgA<[)t,D $wdmK͂ ٢  AR)=e0Ddo+fFjnOxNXIe ޙ8 s(HmP r|x?oqۿ|r_]˔ X̧bHBqbnC%'J`΂B):8LfUYtx>T6{gtBhdm \@!ࢤ7/mĵkç-;"SE~j[4^@Ò>go罶nH,={?ؔMW"@RhL/#/(Ǘ_[ ͫH?Uf1M R 12ZJj;b€0F"ݰ4`c'[wԴPfL n$4(+V3P ^tUݼE`uFh6C]{<Ʀ6ZʘPRi{p'@ y~?+79Yʇ%աc6P8ض8ȅdgР$4!!\&Ep:Og7Ul%̊ pA$0FJl0c4$1w l}݆Ml{Vs;_])@ H7d!L!ւM=2p ^ [ܯn 4y9+̴vگ ٬eQ_e.Bid!EJ\ o@|KKQ!շ7َ<|BG?H|[!.&}.ԑFsh`BC?,l޾3/S9,Vn`8پ\0`f&ǒ-96^/{\/ͨ^l2i6t%6xQI9('۱_zO9pyցXo^5 i66T('srO|ii}~\6ozuQO T_>۾˗utmͲ~\t,qw4@ a^^bp`mni`[J)͂NJT ā J# 9psхqQ@@P 'DDBRbGDŽPCAn$LIc ȦŻ_ XTq`B[)u>t9PRѐ'+$l9~ATuff֮mX8Vb  m[D-:R {?OTfpm뗿>6}J7w&pF:[T:%N V$z@ y.mWuv*ޔBPbrH:#d" AeD 1#8:$ 2x=-ƪ:m.5ϫT%9D"(t7Dfw+9N<9Z0% BEʌX$ܘH%Ĕ6ϖ\H &" w( wIvqV0:b(9#~u >>ElEp6؁ixS3 qHQ%$Gf.j-q垆G ~1=NTrz|k4;v偱rZ/yl׸+L qA$'{(?EwۻsV6F*/o=}izvBȉgtHjxOSAx1N_}$2EfjKAl$ޟ^ S ;+vsh=aulC0R B )E[;#CeohPȜ "2#g7o(:h$zXP` D*8 @9B~/eJ!eBĒ#p 2gTer 9$HA Sh6y{\a%pO},}p>vNwzr<><sfOaf3%aaa1!O0XJu@7]F>L,9C 3rBrѶhKJHb=Cy ׮1CD1 3$8g ˆ\=|ʞp3VS1vD,VjJXZIL $ BCrtTt,!3IOg ̱@EB #EG Hè 3DbBAYH#-FTCJcĸT4hF `z1F2CpbnB[_Y+jZ[O(_cZn;cFGETx <@:ǐI0 NPf7.B(;@#Ή^ p1J̷wymڗEשׁ6ҡDΑ8|nL \]c0z$ً5VVb2g>כإ>!>Δ!ehsӕyvu qfss.5&5!9elmP>q'{ڙS,?zui-w Bxteɠ+Dۢ'{9>Y\KG/'zq<3SfG:ڻHi] u <>dGXy\7g{G 3,*E1_TM8/TJ%#C Ln(;x *~` \2@`8!@ؕ2bdW#$`D@G 9~۷@TE6%3Tr'p & 3@p#v(h1aJ޹vܛ6j6, l>N2cͯ^տ凙d9폏?ӾϦ׷Ǭ#yʐE L91Z #i!)#ɾg?{I25Rci/yY{W)Af=zLP[ uhzYRDrٮpZ\7sp)7`S wD!1 3{ 9#B6p0$0BJnBFgן&%SoQ ḮPuD\0:`P!\S-,I 180Ɍ F0"H;h]i:+h؞.죇۵ElD2H:Tg pf`>8E$d JP$eqtbGl)ml-` (2kpƂ<I?N6]axyd \} "e"" o S+=Wqۨ1!I6((Zёkןٗ';oe# ؤ6m3/K[]|N so{t8ޥE`~5q-k?_]:ߖ7 ;Q-|CkŻfyAp-怘(I!k[d}̹jcD(|$f@6<%,B#8Df6x:{!hXg $HA@f4‘·p CX( 0§/W붜f־&B|'[^cDoŒ; "m :VAu!r:0Fd,swOu)=<_}~NwRZRJ$8RfC LD#n_<_&p08 >Pz<šKN@+#m$#3 Jt%=Y=cTM=F,󬃶zۇ0N^L쫴U5P ;(= y+cT'Ǩn;11`TvQ`!O%vEȈJ0J5R'܇u@rȕ3%aIrA4%P<'! سׄ 1 &k+Bh6'Сzm۸#Le&& A@YX%\@ )# @! )+q0C(D|tWha=pXg O{#@Ӵa9p { `/il2:IJf4C*YT,)E8&e|8\cnbyjϨݓp FW}ۀq/eWo>{8[in<%ojs79y|F9yD_T`1dx;s׸co\H-›_tהOIMyxrvFge=>Yi\z.7- 2a&2D=A׳):/|,TkE iDh@0˜x%>`ܼG2C$BÙ1J`DM@DD4DGBfDG!& oJ@XHiAH0)[̬ Y0DDdaS1BJ44ؾ#Tqgl>ɺG)úIG,m:QTq{߽Z۾=?_oaSsDDH FxA` Spڞ?pݱ+eBR, &\# 1K=k Ũyjv27Ǽ,><3RqEIwfv'nwu?xo^QjS<|@ϻg." 8:!b`q횀bB2Xw~BDM w6$wS&p%.ێCdrA& cFyJIp ԙUtNH ĎdPY9V s?"vhL]ndv5} j d=j&HI;k9[ćmq0CH @0M^ ;` E(uH @p 39L*h{d/iyUǧޭc_v> P@7)UַkkTHpvWмbyCw8ǎœo_O{қi:85> >P7γcM,1/#hzyw"ݠ`$/cAo6/ʣ%.GEy9f,|<"7\މoDgWIB &ٯ,+|}j>6KyzX)Ykf3qp]@])gʔT" 4phQ@ cH@Ȋ-Qˎ0K.d$@ij#ѠT+q`h )x0TeZm䜖)2kaae\_P3M† Fce(ʕ" =t _ڍ #ŸpkhlDwꔿ{ONʒH/??j ?^*,8Tj0J!)4GߟH%A( )U9 D&S 1s*O߬jXMS Kt,M7HicB䅬{rxP^~4?О¾ڬ2&"( YdG;I: Ks (Opb{oQH9AP&0! DDbqDprH\09$ aaj%Q|bfX)/3MCSE?,Cߞv4.;t; Y+w5< A@`EatD~rЛiZp)_t-|y.gx2r!5ߑ><ں)RE~˳s$a(EO'/Dko3]k3_'pg=z|F?-|3/*la7/+X#/r=DzN|#Us[ϯR oot(r]E#r䎢4l*iKˉP>0BV)m`*r4̨8v!2; "9De7|ؙ9M3 A܆blF!G/!sA@ 镎 TAv;$ C?Ez;ޣN# ׎~aխ3Wr+TJ||?.ڥ鋿~_w{Ywn>ZLIAnL1o9$AQW_n tCX QVauc }1*aB u)Ljjsc"T2X\9da=%)@C=\N_}~~}Z29 A+4'ҳjć|B CIu2 c +A#;)1ΐS1UB F)Kf\4GDG=rjȒ;2vId4PD9;30`&T7 ^519Y|$ζ4vT]Gum`5|;DpQt &# fRHBiDwH "zC@eW{Ý-%H :A!ƆXܻ"s0FbpJᤵG7DͰ\mj;#F C"HǪg2b=3 w4Sc+it2Bl}hlmrGoַL|t:.rB $3QKϭ8#Lfכp4:=Οd~tʭuX}tƾ}nZBz<}e?9>7dbvI%H[3׾qo#`>4 p(lO۶|X2##i!F#t7ƆH)[p)L'{gI>5N] P1" Dj(A Мcf}K 4JI&.Cn&ةˈi% fV K2!FG_6j#z%؛wPFT"sE~oG~CF-J=$zRЯZ5g sG$(WNP݅ RR1@^ՐHTk2H` 1%H3ǘ#\v8uQw2޳K'5ErݕvF6njsF9@r"tpO>rv20TXQ)qs є{T=RN ~61BdG'B4R>4$@F<mۑ;8Q(bH= ]I$<~}:/2fJ #IIH.Dk0P ʷA+60{'u5vՁ KAyђH.oLK¸˾?iߜE!"B- p 뺪 \?5ڶ,jUH0T 8ص;nLPȶA 0 F\i y*V!`K;㤺pÁ_Xl9%% 6 #q- ÑB CXP`X"-RP 743RDZ2vL+,F /8 FGf9 @͉nA0% %KrOsFJR,$0;#!sψu0LІ _`%}(rނsdBS,<4hόwdauf jEXrfMr0B0,gA,){́TR0AVSx$-qzaֆW@>oO7_X_/yusCi+ :"C8,ɬKڿ~]n^&|nܜCp*\C'qK7 q9;fxv{>E| Ѕ.~L&N݅n~0aܿā>a.yy5Dn$GB 7PiQ:-О8 '`"/oށL;(H7/ucޛ]rwg91x *P`Vx8$ܝ*E'ܿ`&洇U0tAq $nP2*$ bƔ<08!9FM)'r` F v@T蘖_'$ijLyvtjHXس q3cpn@jiӡiݮWo_l.-TʒrG?˙ҷm/8'ӗTQ``zD;~ 0ApJ"tm"$r Oo~DDF U@8]r)Gz@D qJ.̣ 5ebaʾmn̽ B qb:8:p3wێd  #T 'D$%!a0A$`K4:`?alml5C Onቅc4`$1F4MKrW[ FH9hpΙ,1: \,Rb ;M3<؟9MBmco;Ry %N`ɈJ١@BDh Y0݂)Z-$5 "x1" *QaIGKUvP}ugC=^?̋4䴶_X}u}~n{T9eU5Um΄@iJێwzcK[NcӅ4g?d[>x 伇)seduF2-eXiܫoNhr^ j~ ' jS?ǯ7]zzIٿˁZ̾)5m$)f>Gyi}fj;sHtD* ?աo2q[]<H,̷52IfcWKZi䤔B;fw0s# zAiAfBʉН `&z4{k8u+}vq1BU2P H*Kx8f@dX(.(F0Q"bg@Fa 6ёGPJѷ(l;öy߼{z+N2):??x: >^ۻoϏV=w~[y<υ8{A`:`D^p! 3T&D@gdW7ncP08d ,rV~5 uDA&pbʩ2ԸJSORVHзؓ[@6B2tat `@TĎ $Z%;lʌ<"̑; `85o 3aAӷnȋTÑYF%D| K,]l+2.?ON4QvZ\ ٜC&PR(dXo 3T T rG7fsػT:tS1R m*ꔪ@pԛxNBT<:`xpPlF0!9̂''p̬r$dd4 6݌vL> ?sp<ϛO%f3$qHT-xZعPΙ~q=w/n`aIRaPvȍg}JG.|7z4`K C^F|LqFL닗&񷚈${-Zg Akñ" G?4^|r8dl)WCkM*A`Sg![|B7vDŎ7%/B8N@40AΎw7ܿ fCJ#P# PFv BGI0$D):ȸC g$K+`İ*%jzqiL$YCC@F@P@LH٘[d,̐h*Ѐ0 3@a=,ޣk}eDwo??}t:2^g?Ra`V<;d 4qJ#.(-57?~"(N>+exq:3h=+98`7C'twAM{T͋ۻ)&yo؍<8L c3d rfJJL`H "(Z(04T` p@;? $֎B)-X&!(A*=OojdTj.4La*H!ӊӝg 5gF>qD%Di Xn|$ q sSP i[dJH[ P,N9rO:"!g : e`s$ 휭K)#!5tJݡi7 vfD 2%xnp؞__엏m].)s*,de2)?~ͽlx4` "+v0r W{IG3mWn9 Nnm;\ _>šl$iߟp&6}y)'weH6!*<"h'e.)"So>{P_G7}][Ƹ|"b )IaeQtEi/VNx=k=#lnÒjʸ#@| RrC$m890 H [eBBAB=EƱ$>TF94$1$cg5Y'D0'"d11% $N/}toEsDnAaE c"wGB=8nOȦ>cyWˋ{:2s6ްe-!2$6ôZF1`8Z( J̀E1L{&!! w5a GJٕ4[eA:!Q,\ !B10'Da);ux2ȓw56ׄg#o4أ9ȄEvp64s ((ɧ Ywp=Ddy8{)ϳ%"wnj,[`$vHT{!G.L1 m5Nn} 7޻Q ]$MUYޜݼ$I8ojJt9%VK:ܥ_Ee}ip'1]KX0@"EN}CPV#qJ SG'o3:On~2;@C ʜB! TW7"^oo%F-RҹkP4F a0AdaoP2*h܇e趏q<ώo^ZC{.{[ۛ=:5}R[)\dҰ10#Ԁlps >33,*h1Dmu L54,# nF$qU43d> c8P$m׆b1FG[NvWo>;,*q7gu M05"׈ 4 2z'B i%@aWgH13 3=Ώ %d$EH"CIaΉ€9!:X%|LyT'zǤ#Ju "4 !Т)<8Bܓ#Mj 5p7J*1e)DLndF "}cȁDB or]Ih=eD3: 7 #AKJ' yqA tT<ί(xڦO◿W b+`nj6]-)1ߙO}a"|udWYJ{̋se}}cߤ;?oT^/E;`I|sSpgBXU]$|oɴ|,ZA@܎1itš9|qq{ܷ_|pW1etE R7@&0Nn9`h ʘ(t*!/fSSIOB5s)2h΅aHЃSa.]uCms9|ۇrG=݋|\S/DX<,yG"sCwr݉MM# 0E $#AȀ f`)k/_ݗʅ]34eL qxֆAEc LN-E @F`.%5k1}w݀`4}aN2cs92h0H(Bn8R ɳT-Z@]zw(AƺtC_}9Uar&蚊tAl59X2y)Ay<Cf1;d#9B'9sReӧ، 3U}{׶ئl=N"C SIP皲Jh9;F2 0X("YC3HפÐp'-V` !ˋTg؊/sGf sl&޹-2N@*>l9ͮ}ʹ35y构N2:]t#X{" Zȉ?h 9q:V¯_^^81.fH>8|\c',8>T|a";=uh]vJ:V߮orL|Ŝ-n003! 1Ip>P;>Hr@ %"F\ŀHH ή[Ue۾Qt˧7[{wt}{y^߄M\?r%sPT#a8t3  92IJ> B@24W)K o,L,nNjFTC',9eH9 )Ad>Lݝ&@:\>zf}}:gN *TH"jp" d=ChHrEB ` Љ*$b&MBFc" @Mua+ wUo톈)K*3B*%C Yܔ @= אj@u)d$.5IQzÉTۺK}k4pT`9L3Y>fWhqqaA~KuD>-wu |[Ot}mwU>b D`ױo~/J5o~mUƒuRxz\׺ؾӼHwJc:Yo S ps8 )!/@H0P= vL &ePd y^./~=&*|"yDJ"1:FQp2qu `;FP;{g>?f3'%d` "@p 6=v2]oi.>|}u~]?}9MyI3PPuc *JHЅQ$CЁ|Ugb&NC22" >=ܜSݑ"P.uaJ P 8k"6 q. a.^^<|T ?ek_4k̬{nH`cMyF%BE))wt췩\MDxrTTUXx=u8{;`6YZXGxP8 춳,n|-h.d{B&UBMU`,??[ȤopW&*G<]FʲJl=珯^)J\~ݴe;,A8%mnQs kܗߟ?8,K\)=nW~B?D*~yqR?f:<|e|F-m^O+~9[٘*M+V%ENQv%ҕR_nOi[~>^p쓧w ih#|49" Ru‡{#́F6W.fμgxcR^~ 4s&3\ىab $Bs =ݶѕ(E+Fn -J,dC1w54\u[V&U'͹>û|xw;yv~iOeve?y*S'`x8QpqD}D{8 9 * V 0@Dlt9??{6Q!ګM(PfԆuFMRYo7Sޫg }P6Pl1Z=z#!Ӣ՗~7cYTwAb r 8n2o]Ej]#H#wBn28܆א R06RV/7a,5@Gg z2 : `дwQIImB@^*iS9ldF@P'`&e2 *cq6,  1u*] ̌98=D wC μl[8l~~+L׵O.טt즅Oj4hڮ(IQ-|+JH!6p"y;?q:>{_W~ʇ8=q5a{C>}^Wm+2ȾIG*Cn"j=eiˇ6 }lҘm꾫\ˣۊ_AkÓՓ8;1uҨr#wS$I֠q1 c@ Dů-dpQ'Ļf!32vU$"$3Fg*çK̏YS{#;`xK%'g!rap)\b9E(y]JhG7g7A#FWTr6UfPh)h$9t"Nu*]p{gwxO%ORt65EkBw۩L&NQkNAG|JPaM{IB)Cnio)N%aBJu@ֺ 57zw%Ad1=MRT`lmD[6V'yfzW?wm\,KELlGaiN)P'@N=d );K8n 8-4# Nu9#[Gp؆v&NTgrۉS\o[2eKEe™%V"NLomC$#d\AF0X9uBİ}Y<<<QRI<#S(#bh6:ˁba&ܶ>Is:JqpHXL6X"M-j-?o/7kMK]f6H by8򞪵zxE6%_㚲]:B# EZz:=,zkBn$zL?K6296)Z^IOuNtodf1VʾJ龜Ʃ|5$uc'^"4&4]7c w͗Wז91/ǫC)zL'cn7oO<Ckq>(1L=&;2GLşc`q<9#*c샲1)(h1u'e(?x_Ww?=<.tLCHAw)|pJA)i8)B6B^8XR{8 pwgu{S;AL_^Ґ}Izz,_u}e9=Ӕem}Z_W;bB>}O9٘!vG x Zc Y4CD%3D;i%2Y;1{x P %Osp1 |t'&%{LW)7Í+6JaAe\#!lxG3SF"NL#\i`Lp8'fbnj;Cy,RAۂ͑(ZXUJ Bֈ2`F hSm P=MsKM߰ߨrˢc/[񾣅錄?{|c.7y6^Z>~og$F`D t2 􈶇 DD<`4CBL4IL/3{B2]R Z˯?ox0)ʜmC)4Md }DS5hFf^cqf7myx;ZG ˔~pz]^RB.o9ʈ#z e)r!.Fk$r<]Ìh[ bo2R/3٦}H``2'[ u8fA9K>P;2fms8% R`DXPO"MK,oi^\ ycHZEwftˁ~ Qƺu7@[``dF7rcVeY͜rDPvV5 LTDeȧyJ6f"Xd#J|me$ǨWM%9QJX3IjmC ~ޙOrx\ԧ(6"'^뎾etLS ^}S:F^Z#Ѫ4]OuM?qvљ=<.)%Rtcگ~2929$A8V/w>ԗǴ8Z<ȏz@؍t%|L;F﹟iY=Ӆwk=oáWiYZGኜSD%#^oO!U!\_gyJӍPrJnIGe %( D3 =e?Mry:F9ixOS2C E@C\I9pn胨2ƪIN>|^;z6$"4pw_}-XAD)RK1Ja-g'{aI0 A)*XJg)L>tÍ߆Uu%ZC)py'haF{xވ~oJ2%2"#dhJ!@ru+74TXjy2ta $1!;͏\7ɲ-h{h$qݷaI6nmx]zCԄ(w2JfS&97ySF2A{@'k<wҹs(MU18 E̐AzYߑ// nx~6@&?lCJn`_.Sn>"zf !^؂eLC& P?>wKY7f*#咓dkx>} dZI!/d#:@BjrLF:R"֣dNVA*z\mLn+JSX3>Hj I"WsAJc1/y4[Oy1ytꇟK|Sg{xxHykQ#E <<c,N;)(D"VE3L2Da>x?o_>D-DugrM(ܔb B[$|ߠ ޣ!#P u"Dip*Idn>ܝ{8r.`u=½I2IDJT:1҈uD ) 끙Ԍ7(=8I͘ cAae_^ QSnʜl*Ț1uHJ#-,lnYL}QF;d,Pp02Xg!'. I/%H]f@d M}no42:ǐVê*B)rB'y#)ڦ)Xf/C^rަ|_uwiˁSup;:tyx>{O`-x=o}.-+/y'Ǖ{<˅- 4X͗{3<,\OcKAti^&0{aOc|z=cqI<< b: 1#+dbes u0;'L)8k?$\Vn¦V޹(>Cߕ/oJp4~?ZCȉBgLTʔB ܆BL H8I IPR1 8(%"fl(A*,Jo7m%ԃBh,jsRmh!D[@yC wI Hu:,9 {V9ܜoۻxw)EN)2Nu9)8DcPR I=DB4A6Pr ޘMi"?+>3Q'褚"Cٮc:J$iPNuLY)LHBĒ9FƦ܍k7;Etg=py [c$6Qbl[wSՉ(zpL#r $r2+IyLL@[cXW7:nDJpx tkI˛>Yȥ *o'ꀄ#П/||V)o>'׃lV޸t[k%Im3 Ǜ_8?5z |`}N:zA Nss|WO7/?nng9N^x6y:Y?8NjaU>2Eq^Rf]׿\r.-?dp<:,I!ydjϢp=M;9v"vVgо8h!!k 9"TBR"w=Ic`{t<|fS{_l,m^ot<2QAv+6z((ĺ9QKBdLLJ 8q@q 37,C߁r 9bNW?V0:ia> ~7bfh UpA.0/B<-fND|LDoIQn^N77qʤnaDF! \ 4Q8̩A޾!֠Gg!UDƨX8 5F"!'f'鈸 +@7?p MA1 ۴XQa4% Vp G]I)A(A);wĜ,<u*cqa)\>w;Ä~ݶom%+ IK#Ng䝌mL3q7hƖH(q3hPD(0!QRý)p4e]ʥ]\J*;]vO~]݌Z.*y}ٶiq]d] *~4 =4'$sdtۂǩ׫gMTj0__/oá Il{Fv[+mZJ׺ۧu lj盕u>h6BSX.~~k}&~i}:M7O|:%'ۤ8W߄R)J{-[G_<ӘoxLt=9p|g1YNazjN=Z!Q$!A Wm+v&ҟ,ul]ܿw܌Zxc! ĔB"57 TtFOc/6H#RrI|}2^;{2տF3Yo= h! wPp DI m 3@L "̪H fR@DI#(clTXa"%SИEtwKV4)\MRX%@.&p:jPw}a)Fr<n2M $Z8#,P-0U@s fF) ݽ8 " $p Bi #rkA`(4\'P!b .jolѴLփe. -Ĝ4+G;ieԘ+W&:E)13uɠ AYpȶ%}\ͼVG7+N[v&|-^3y@IJqboQ{H# c PX49DaIB9羏:5uVލ6]2G?Wx4o}Cq~R'dd.+Y8؂YrlQZ'*yk^Ҭc|Yc9<1}_ZWRT,5@uunrv3A_4=᲏+dMG8~ߴpoO%_WngHR$RGOWʧi@ B~b#}:|_@{?Y\ǁ|yr<4jJz.!vum, yG~o<}%AgHsrQ˟ħEy9~H%ee3j^QT7"u"|Xc\U81 q"7NJF5"B q1J7cYx&:{"E?$[)"}rV:ږW),@$hÙ̳ 9HƆa BH8kGx$yztƠp5AZ47)03"Ĵi\o/8DL!Gu8ٷS }X8RFM&>wv jsf$%ee  qsspsSs@1AwLk#^Ed['Fj*AR"W%OAKgwQ+ $xop -,J4SƎ*jlrx;wS'I5.!|=ǘvBcH0s9ci!|(IFf;s0nFQ,_}^^Pl~lvSɾq;y<Ҿi(%]EէMt%Kpɦg~N&렖-2O6[5q>\# @9h!#qVː`!eX|$FmO:kQ}%jgJ])$eDB ȉwsGMV0i_IR$ JPgEÑ_gIo6"iysg aA6n.UH|T*;T91.OVn'ɯFO5pcvoL}Wr6X B#A#hp#X".ZʨbfzéQH#&7(gPvNZ?[*#1%!omx'~Ծ,[ޕMDm%wP߻OK9֐X!4ut/qm>Jx:?'+;i.cgVѝWViyk̩]Ƕs߼WfQs+I>=]/K)I<>h粿2HبqX~]-'rȱ<#Lg?J~A~jP;)kaZ_'K+S`'q(Ҧ/,Q;'}"ƵCocө8Ou|SyT,#P%x ;3.lNsn-th,Aͽr/J[hcN~zr:jtytb*l0G?"I '}]^趶X3I7RyHiL77I*zGZ>I%%X@yJo^ux|_ SGA0rܷ! !@P0uEeBJ a&rtx&ev2Ek_AS ~X5G;Sg9fJ$5܉>w￰>""HTS倫Izc}~wIwntJ{5>Y(fnITs%rWsATJNau8qK5u51Iz kx};JŇKr o|w-0R!ܕ,p(bb\-F'd9{>DN;QALf07B&DRJ~`=@|(jE'|T).<d-9j}/IѷJ?͡Nu4iDM,Ni@KˎLl=&MfZm[^nIh#Q[Cd@<חjJ2OCX?{YB8)ߤ4?Fj̰lrt}?֬Mҙ+\CR [盲_n!=jj|g;?$h>h+]uU£n-eceT]Qn}?Wz}EY_Gж܉b Mv\zcӰnqP+;gf1f=Y!p׉W؈R1i LDd퍲UD&l'G>o("ym{zDAN&xc^fAw+zhkf\DonC.ߍ˵=]`,w!S;I_7IDAT9{`n1.a\B" cNRș7MbᰀD< P%(væAHA <3Cg8#0_??m$ Rxs&gn]]=l6bKL$b!b.!"PeO*l!! vH'Zؔd?ۼA,BaFqlԇ0qbÂ(x*hHMS2)MmnݣYSuGC Td8d.9֕ 6υ'@LD4ܐXw0=6IhaĘSY{Q7f8ؽaBݻPk~{H$=%}w]VͯQ(\(4fIA˵iC67e{^.r{s[XquCۻr\_Je#uǻD٠r.|Hw'=M`<z/ךnǥ¥֞!Kkvл4]iھMF*"b*j Hr~xXTp Y\=~QhEyJ~Q66'_ʭ4 6uy ^R}dw1^k:я9vGEie~ l#-*%^J&~mZbԌ$3?ZWʞfcV .!pD#L/g0zcOtf*D qt;8v}4}kuüLXczܟ\q4trwSNq6+STE\"(أyKDDXDIA.,lph s 3A) ƒD& 悱l)(F ۘ'H0"é7g/~pckxJ j%LpVCDIqѓʠQٜDNyHD܁(Z_U)ҝQ YfzCfa`Aݰ9'D4HBܡ7̯)'-\nϡme[em4/|ːS7؏BYͧ)ɷʝCB: +% X'"# @p7u7BL SP2HĈɝOק'[w[A2C V#2 剀[$^/o~u-z۠)b0l;9p:w6ƸnI|TFQXni})j%Ӽ<q;RQG`MYA9NFB{Dm9q"RH;1Y dA$ D}GF`oOkApWf/;j(E e738YB 9zkHCՌ{Y< ta, D9GB n»v E6PvE7R[V}(zhv,P!` ph$:#Q2(a4gf- qtSr6zmyhJ^nJcݕk[txSn<{ \{.qM Tu]{tv.hN:őȞx3^G]6:ma{exwi/B̓"ljH=A"BI4l|n{O੎<×7v!@Ҟw~>Z㱻R]nx8/HtWa 4o/~8SK3hm5u ]G^B#p<. tuy kN&m6ES)^I?ؼށ:q"gOKT[a,~r_^K1uz|봔A}iJB^٘||X0.ݼ1@L"b`E07!HL DAYS %D :e;O ъX@IF1vĞTmD_ϗ\cUI::ę'd7:R~ľZ_@=(H>PjB|ey8NI}G49+sJ"lIyq@ !#&\eJ@b=2A =Bˎ̦(ZL4 MUw@6 ~WLB ,}F^Rm2ELD9dyEa4NɣʴȦ(J*=,Yz8 Hp! m&bnՏbFcBTZU(KtS 1$$lraue21ba`!^"i# OEZ9C$bƨ i?ǿi]/w\h"l|e/[eqgn8پ.rRŬ|_빦M+ 7O"2Yloh&M*(oÌ͍;`,bʹ Ri;TTJ>>w2U)E%$iRip@ ԋ"$hWHPcf83̈<;#0=+Dݝmi0Hpaba`o/~}kmo'i$sFgBl]7F5)davzO_!IuP] d *lr#z&$O:INޛsroԪDf\"nng|{ Fow1X9֒Hޖ3tp”B1@=,>40T)xJiqA BISD5t6q& &afI~2H; ` Igڌ$jg6V%IU-) ђeD'4H,NZQb 'HaFpW^ Gk\!%BB8A;$yqsaqKuc0J!*c/A% $ : bV{3!˟Qp{o ՏXq?/{8$* 9Z1M%ti^mꍘp9.c Egqoծ:Py:>v⅝ _.`9r4=U\ =,ts˜G>x[Dm&q۔M׮էth?^u[w}^i_׏&|@ɟ6ow%K+:}bSom8f|A\Odnzq|q/눶oiF4)@ yʰM#75uO?鵭QE,VS|խ3$E Ӑqm[ %]nI`l7 ”H@A  E73oO{sΈ'\swϳQ~HÎ #UpT ђWK;Ѫ'[>Z%Hk>0" 1#f/ߧM+L M5g8O}9,rܞ/s/_^GDH rDanYm$X0S`' Hp Ls <%EQHp Q>>g:$=],/3;`,XZ5q`e͹(uSn(hR XvJ 9Q@F$\uI4* sN};݌gww#嬀)Gtif,F ( 1\R#An3Cm͐adkĤNXrZA 889lP:4 Ha S0Wa0YSEej8C % ϭ9trn=o+JAԓ"0eǬ;BoAF ]Fb}İmKz;0ښ]%GsBDĢaJ"Ӥpݜ)XБ ë(GK (zc@:*l="U 80=ҋo7X^obֿy*nO|i\.n>ACI8@د\L]z-E+ 7sTpD4]PѤ^E/H.wC-_×o~w](dLsWQp!H#Z1Gs*Mwrn_^܄۫j?>+`^ [t{gfܕ̷/i&q4ʹe;ArѐaOnHq ε][̯B h[ R _Y({Q7G:%U>9` HTW]p]f]ַp8jlb&>NRIy{/9J&cq36@S sLήDY G @@wI(#s(R4Jm^0x)8`~%Dp:JBQi]S8e%(3= :"R%'<7  {6Vy[+,]@ 6g lp Xj%I8!6DAn3"[dH ÁZ/DAH[ ry51Y7/Iѝ|"wn)V:w o-W1AΧTgк)g\ z]wq89w @d@TB? 4dtձ&~6TQӘI펫~ዙtOb04ܿ3чӈ >oսJ>а\P/g.0\FRe 4PxlQzCd ])кV)B?aN ᷴ;" tYBd])ϥ>t^{Z1sYLPv0IFh ?ym5P׳dDfHBh-Tࣵ>n(3~li|$uD` !r@'B[_J@ /f9f>}{=i8J0[a__۫%m)w64h05*eISes%բdh' R€ֺbHP~!^v7&rקM @ED J+D@$ k?#a BmGB F s0 {%d cNԜl϶}fč\Dmu"\28toN@P!1 < a)\(Y@99a̓$&N+FL8;,wb6ِ qatLZY`T$񐊁#b(QN ૢ+:S B,nșE+G3 fqPΊHh O pierc mo}>lr@36e]NAmQni2@j0 ~O[bKÀ؞=<~YiWtffRH"xF=nAVKt" KA lʴxyt\OTy%\$ m|n^6z#-LNB=bb@9!/ڐruy ŊȅL|s_Oo8X-ax=~?/{;h~C:+y&^Xu%4d:&Ü|C |%{/cH]V:L(i&ɑ*h5aj5!'hq p$ApL@WP E@NT (e$;`S)\ۯ,<._7# qʰd̈uǒ-P95*OpQwa qnn]@3sp6tnpSxw>3͆p`԰ NvLz-wX X^mw4˒B'7Y %-<= v7!m;9FFbc7kif>zfױgD-G]3p^=7  JBQ)4VsԯmuJi4q1e (8uWjѓP83]k+[J: {L樌yG J l` % ax9߾i9`.< L1Q_˧__*gIsN]<5ؽz:_?ّsk+#;50HÇؚ6)$QZ{GXP2aH$q rq? C Q]Y=FiRO85T݂L0:'h#ܻ, :&jڝ szE1`W/~W Rt5^C8"מ0nbR/ n5"vAqṼM;ėp"!/xàXI1`#y0- )4 ʒ7>ه}Mw m;LzOչUӾLC\V"xvU~a዗GF+0w]L)xM;L1~6Li)H6"7 .W0+ָ-OÃXʈ<>Hݪ 9s{J5nϖwأm*Le9h[qV;C"y[Znz ȴs)mf>L{NWTvii˹(E2d9ƽа g}a̐гãiPlnar ʠ{zΒF{y74N}u<^A;oUsu4ҜFbj衡p45l$TPdD'! >.uHpP2193_J!ЅSwvysFw<"N||!^?aH)W0 B7?>-h1&.Deu [x#>0#@@BOE-z̷Ave0nc#VJwm4ekER) GiTPb됉:8Jagu-с aV `DI@hBv@ԛMGVe(0 UNgLc(i(; B3C9S$D:YjM$(1Qav4or4B$BDHKDdc9c7 P a@nQ:;ZWm^זCȌ4ʀ080" @@q fh̑3;uTxuLAR-0^S6P U9Jˏ_~Che}O_`"-;p󗨏Qt.a\|2&/^|$Zrqixu|ŋcFJ'0.egoWv8x7۰J*RqȻ4z v0.搈ȡ9g Wi챕3͟N@quۮ'w<$BHz›[Z̤{l@Iw/y=GIV^X<8dm4j~-'>7FNjy;#*Ne*޶~z\3Lr6"_E$ګ!kŹ#"?EVFX1f߮Qf4P\[: +բ΢=uen5 Y~"0N/7^>ӫᦌ>^nS>&fcm7 u LF̒R a:z 9D; i8`YW,@H @8/_7(s);(h )yy? 9 0O w__n{LI>J%I(@y=I1,s+#県|p;vAaލR(9#fη=r\FLYxm@HX'p@wȈ] ]!8$`@o` :xF@h΀}„$" @wF3s@A{D F` %ڜgn ;$ 5{`aPRD*DY̐8:YPh+1%fC ,C'AS)5Y 0#VpFh5=&]NԁIa!9J–h};F$ݴ&3N#"9&di C<,ե C(ܚZ ݝi#oa~hpeY؋$t·5)S6Rn}%oRܯ5H4>9|S_ܬ9ewvv%@?kq="ý\V{dy'G_)i%kWwF(;hSJ0G("]bjnof$vn6ew[Z^u7ëD qg A!(");t#jN)3(;zabx!DNB > <<  s#'DLA "h?gFL C栱h#~<<=ag+O{/۟_11 WpBX+`!_!ȶ5XS&' D|4Ș$qRra<|2Os 9t0pW `@Q(7$s`@af" HB#$р0"G V 4T#@A@xEqB)dl8Hؽ _VӾb{.HAaՈ#=;ZN/颞rs4c M<M<0cd@#bBLv@bQ$05!5Gtoڵ׶(^!7wdD)#j**9c5$H1%qpQhA[à`&Capvܝݑ`v$0H#2@pSrb|eaZrꇣܧ5+QZM*vep}fۚP0FjKj`׸n[~y?nø眝\RT"R˫X}~׭߾X~կ|?̻ZZbڑ8NсVIZ^F ]_s\mz< hNʐ!޶ *NW~񹛸3JXKS di̛ _`'bS6ֆA3 Wi0gα- j?^nKlC1=<\$5H| yS)ss`0r;Gd/\6<#߀kD[$C1U\ մw:} V.r. wC߈^Kr/4))' N9dV:C;3EoA4# #43489 T;E2Qpn(H5My0`aAd>`~hwhrғH'x; /~78)dΥKvb(T>=/s$fL6:ifYi(3:?yuqM4 qD[-a!htEGg$C7yDl` VZf{$nH0G! AG8qDF)wOzMP`!5?D#`(-} :ΡJ4@F9ykxr FIPЉ11vt|D]8FO n}sȮɖZW@ޅBb2f*mLD'i_whFA`dQX%dS. հ|Bj772D P 0hb[W?*O("iýuY-͇>[tSM}?4٠xHH0iTN\v&Wߚzs`n8LB!T_[s@ RȊ7݋i(rw?3aJ^np293Vuĝa*޿jNxKB8ENbT0תor=YJ8 C4 ZVhWu[~~~{5q<{N&lYz4 ~tOO7/xRaե^ԗ@aCNi%M[m]}}D#OTN'3^7ld nb77⾠^cyؕqܕ&fl>m[w|w,wqy$b =@@zSrJDA #@"@ , :24r Ub"'w'D44~ɟ}T G}i[VӴ|+h.V 9< w4֧OϾ)ÜvȜ1TZCBNQ|Ӧ (Hj\(< \3ُSB)5#r)@He1` ԭ6EvHԍR6)ƈ 1Q8@B6gֱuu*!As"aЋwSd"pdKPq2v+;rJʜ(k- c 'ND!dk-X@'  8.^ךe/)r/p=RɎ>v39] wUu]Ѱ2fȼ|^[pr5Bkܾ;l߹aKAv71ݖz𑄠EU1퀚g4uX\r`b+i ޚ-uݜoyi < wLcUehYmGIe} ^Ͳm^f(3h׾[,Zcnlڞy+M z:fH(cر 1n>'}=jQE-gݝxJ*T36A7Yj'5HL/j{Y&Cz➰sk,ٺ#Cڬ[WXmͷsQd) `PIG,FY$!:9a PF {D Q##%B8`K<\֯~~zE/)=Z?8 @"oOӵ֞h{? 9BFEo<JA)x[6f¬,<Yȍ@r2V073tː0M^t/< 4s7ʉhJF9999!V#C@vdB0*BA9V L\@EJ@ ! ;@ (d!>8m 11e`^9д&a-)yҭ5<"U1<\PsRP}& LR@;D\%rA딌W`Ub&å7ԴtK۲!fM A"p W,[lj)53L !(;kDc3&ӵC.Ď@@"^@ӿ}z$ƛetotIUd>}OvTG»mn ^?81bXCSV璆T* R[ adj|r4X]3d9-al3 ke!,:w˥`xbV)g(7LoХWO/>@1aP0`@(@aÎIIm;R-5݅ܝqlt0s^]_.>mA"onɆR{[hkKI6M t"_r$iU(-lGi2uIƭg3.W+N;Tt0AFLZ15C}D@v'h_wb֎)3nms%M/[ 8)wb:e@2{""LFH<`FBB5ӟTcf9O?jݼŐ}w]j}/k|7n*njL7n׫?9EBdJHee)H#4$e h9{D] )ROuw/K5 Gnvt13'AꛌMq91"ޯ<Ղgl#2u B֍:+3'$LQ܃A (!8w,# !8$3NHh]i7Q DŽ6B' %PE 8$"eb.2Sqb%1P,=d)t ;(޻_7ŷ>8Gj D3epC |nI0n'qG"0qԗn!f,XFspM%~y/P])boڋGi_/w? %~>лz}P~T{K=e/VتW`cqo!01.= Pq˻wfQ*Ǘwr1`^ᒀr*~}L7@t<AkJM`g{ܮ|e, )0wec~JIͽm^[eEжNToajץm~ݗzM ;~ݧ4 {Tr{ciC4^{:+thЦѺf%Dd3C*Z[3XX1PGcVO{t0+My=B GCwηe o^Gg?Q}Gg>! 蛛ju30Qޒs))I"Mz ΄@|0")09caB7;8%FyD$ ],DѐzwR!9|nszq3%e-~߾l/ׇ˧g ߞ?[ 0Gf 'BJ ;Tp#<=8D!Y1ͱ44D<=ۗ8 7Yt3=Gl!!s@! "ȠÍ);yWP0MLa+P]PR8*~0E)`,#S@0a8D@P9щJȬa@S fuJC. 0.ʔDCd"TN<& OP d@^Hx~9fPzO24Y(1^T!e4U`Sۖ4) U! ((%EFP$Oև sIC) ͦ2'K?ߴ_?o>EnsNz?'痥q %SxY^%d3$meyե*5 a>!~7_|sȂ40+P $9 Kܳ#"L@7A-FJSC^`,`nDaLnDƱ1f6c9c m Ua G#X(D=G@Na@9 n$Ihe4R;q.2δAʄX! & /H`g&\T@#hB`u7>ˆz U 98A.’rF4tŬ@V;d0bꊊ u-D(0Z-@@;Rvdëj;Ͽth`Y~X?o߭ӏ>-_[};4'3et>u 2;p]4LfC{> {JWyzsbk-y|MRa[*'D漝AЍ",gko<\i.9X iYUV];BH_)v #N꧎==._}{}Z{=-mX/viġolmmۖ |0T^X!"GT~^C aoīueu)_tm gS$="l)x}|{* =$»:j;n%eN4af_a{Giϙ@PobՕ9Cr,eǂ I(C {YsfA&#"tL#bt` d'`q6F4œ!*AAFÛ;Cs_N9n^ 7Ͽ?9}Mג'oI8ϯ2X-gPXGk+#ӣ71 4 [nPN7 . a!E~Þ uͅZ\8DA BHq1@gDΆ=u)s7$6DPTD8'`0L EA=*S P4K3[&鱂;@>:u5XeU $a)R.ww@.C00Gg)s) d9 lHRaNX\:19 .*[ л#҈[غ6ojͻTջJN0JpA~)I:Ey`Bs$bjF4XJsU€h]9 "[45K.ӿJ5=[Fa֗?9}r׻דo۟J2ay]]"O\edykvX?f&1Df35]CR "'i~SM<0PxX (T!EM"F&;θ,ׇ9*ZIpLJnJt?œ|nHm~~}_=mr Pf=Oz]ߝ֬_VY"/t[vo>\'S< =‹ ̑(r=uwv~z^3 AkEB0i~&*hz[]~o~:䳄ǘ{=*.lϧە4n?!ga2Bv۟׿*V}ٝ̇O_/^f7~z oo*ٓu [ Ө EamC TAknͻ`J}mq6H݌ŋq݈Nc"Čuޔ ${`fr .Ze ʱO&vTA])6sXzxPCoNѢ3& f9"Ѕ()ݻ)#;0[U@Q&Jf9w`P4QWLTRQZzA9m4)$0gd.{+&۳rJѮͻj*~m_uQe^ eD 1ٵ@JyɎaC05h[3DcDсynA<@QAF n>VߥW_xi'ǟPz/;Zs{H3.Cc3<aGځֵ=Zeoy{o o^ )R}InԾ}~:$tH\\8旣]Uw|{j^ulлoڗiW!^_oǔZIN'<쾸_a(M]v9V6L ࠂRs"E3C#F (3k)cApEBPJ 4QQ R B4L"!8,N,H"sC<y`|t $SB\(ZKI(& CL 7!ᨈI(`Mg&\|s3$kd0UbY,Pj HTKƜ"SARUs3;t S42PC4HoJޫs7GЕ(1'8jp?mGË99/18ة{Z/4Ͽ|pn˛MgzŻ c.]F]m܇{x9Oޮap~k7)v)f6l>joO`vu? i0ź8rvr؞Nj\Ӈ?nPy֡Jq4rvm|Do':{>_ږRvOvӀyY^hy]{vC|y!8g/^w]LJ;n[N,'2J/4na_}ӿq'({|w 4N{wo18&f0 :En0 10(Q .%E '@Df LH bJሡhV32A!0N cd!1Ӳw=:dïo;ɲj9)nG`d78G7O_ oa@\o4Y 0qq.0Hx[-ʠ3Fk.UBG페ruTPiCާq$I@ kfN@怎ĔB- 2qa 5eĬJP"cAO#\ D; 1!.v=)a`@'s'mYdЭs:?#F $ԫ (3E)s]XjSFsDa i .GO2ZLTB8c@B`GPXv]E!%r]uuuh[WS g3{Isɾc$еs[ aU%0a#%ꆹ0:sd!7'dHdn=3T%e2G졽UKoo^gë!]ܾpNGlLp7Z%f7۞O_gɨå^,}]< 4os zL t7!AzY[s>'(n)]MTIk˂Yj0ϙxTߕ{kyB4#|7s9閆0bO9}}ЯyxW_'n`榟|~Ǽ= ?>b)`h{OwW2gW+G&^? c@0 kDCt L( tvb D8\JBF@(;t4"C }l;0!G0#s"PdDaBa~FZ[ϿwfYkPRnB0 Xvķwazb|sizA %Ep2, -+ng"sж DaҘ.ǭiNRJn-<}뢘h]زEV}vU "@. ֗sum#zv7c%(A ??nm7]ڸAږGVʔ[zz|/^ 7e![fû\I!]>,ګ"e[N"ç_wcyFڈQ]{ޯu7,tR:`^C/bnT^샏Sxݻ{~32Ȧ#ϧ>}yjRe,t*ow?u.|W? &.]Can|y?"ݗ2%.؜n_קPU)#A{ׇtRPث;x rr WaĔDBˮk۸ꪐQu0%aDOHE'̄›31 A &5'0J  ' +D tg~!-p ԢLhfƀȋ2y Xf Ge{hJB b$BU`U@\+U)] 0ݹѴ`aX`0Pw5 $*L C씂g4S/QQބ Ohġ.D`JD9MFZ>VÜbXAj"Xi)+Oi3i-;Fs>/v -*X*W>q\e0lY.[&)" @gW^_zfc`_q}_ݕ%-D1Aevwıq""Ȅ0'o?c,w;mQgnzu 9W7=)ñ҅}ndy+lj,X !8Z8}>85!D,%/Ѫ!5KwFZƯ Cº"C0<`y'ƈ,q z(;^AB; `.jH%(i+ܴ6h9%jޣۋwo\q@a.]W*ұಆn\l}׷<||O 2e^|v;:wX]ŕvWrmo!5){^ Nxx'j{ݱ si}˧+`^f=:~|\O%unQ%.دdqu5BDVm]U?0+w݇YS̱ *wA9blh!Wq7ހ;H#yt  h 15HU( Hl\WܿZ^+Rڂ7M}΍<%A0.1 ѹ6iw`=y,gk ;_S+ fX-w;&' 9NNE9tКdib%ԊZZ *ӫxZo6[QCd`E-ـu[70I͆DK bڪŕF׭ĩ64Xѭòkve@oԣ&ސ׌b5$Ý )Ye0#$*&NR-@PA@dN@$͝cv oT؉%&..&,RMŽ JzF'I{ Km 9{7^* "<#꒨mTG(hiU9F(TI.:bPЅ9Pdk;N N':[.M&ت}KɈ+I jkf6 U˶vk3P YެxwF>x zops_?׫=ؼ7iы`_ػؤ4v7fJ'z:xIWlX@haEn8f+z߀境x P( 05.NusŸùug2ώyf'^$J權,Nrkj~]sz[-h)lᶮe2{B'QueKUKñPGa[p{v|v0қ2am*Xynaخbxs xɳw_^Q菍VS`z6<؄|?O#2v͒VY'o˧G=z$u__8\}Ů0x'6!5Gqjsm i(VPgfJA.rD*(7R7q1 4ff9Q+K0%CB )3EHpnjۗtZn|{ܿ9v=,(`l@YJnVn8  z9o͟wZۄ; ua,6L]ܒLgCSƾP+=%Z< Q'O: )cc3sxEx"58ChhBE| D1ZY3jAJ,6j.gw&=!ck꠪#NLN@ኑurxa bH Uд㚡a$-BꎣֱY]gbu@NZZ:7P4 [/J$2D FM P熑Mhr{qh\cB?A1 kr3;zHب46LQlҵ юGvhPZacR]Q5TjXF&ܚz^i4!jf\MiX(գB瘹ȢF/s3? h\}2lƽ~Urfo^~PJ2^Lelŭx`CxҦ-æݖD]1I-԰\ttjz܉ȼ?t&[0zd;hg0\@kZG*Rg+w}fu#\`]"cF۾tKzA|*dmte%6Wfy4nj)u]ޗ~_(a(V Ij6MY1;nkע-Rk4owC piB g2=P}U X6!Ԧ;fԯ#4:vOp1_.ڥsI]~Ws&-/.g 56д8)YC)@plU=jihh0z .BNY(C_B!$04oN! F1bp@Mɩ`倭X;\Lo,15+15+ QNewuz ]BE14XogrU W1-D aPLHQq1 v&q ,]8袅&. cc^m:AWNEz1@[5 [ <J+' ͠7Cظ0Ʈ' ThEݣ9;[m415#'1xꢪ1iSEwLZP:PsBN֢E $ /f*B+w͙_4LЌRxQNձad9bH+B(`M\YGh!AR7jIj]Hz/3f9 )@CtI4I wBHn b>LXr*`!P֔"`UhBP,j&沬c/A&䊑ۄb*B;X}TM_&}O;5]>3ay\|@7oO<1vPa~OVm}usxUMrr 7*m+KXieqw†l c=Ta6n z۶N5o@k]{5]$]`K0!oC\4Di4=vǹRؼ(N4V~t0;&/~iCS1G4\~B8<:7SYnGϥ !Yxߍox4_pD+Q)V^Ƹ9M"C6i,y*YWޗrF#uAtm" ٓ7b_}fscT_7o^(pȆ,葵gAPr2!T1dutwcSͯ3X͜!o0#R}#o ~ۭP>_n7(*vCg\%(yRzt6阯\J2`Fmvyz/VfNw݁kLPQ9_[{jMkq=M#vCGCrv={|+wUNG]ވ{Vߜn=ǻ1i8tͻ _of}1M5׹vxLVvp^azJ!$ޗA] ugC4 e6Wau'۪z7[ 4iix^-s5Ck%5ٜ"]6>ч\>|kfOَgܣj+5rFP@ 4FMɘhLCd:&J= d*UwVM!ZF-h]Dw27dq h08"|צrŷc?Sa[I !rqqY!ئwR; JpXzS˫Kj%m;-1&չi|i\gO/>כN [M}G/_/j\.-z-sS_< 29ʔ]1?`a=mOv=/Hmq"H][8V9B;GUfp:wKe D 9 6TTti`hsDM:VOĀ䔿i!`$[0:@pH֔3fnoܾ\&1$ԯ̊LPpnxQW>~p b@φo~ۿ߼kεAv59nsn@.SA RJ.0[6ʮ$lv J" O:!\ؼ(uɄ9@ EڂI([];1Y !(`դ`@ q* 9E"C(P13:@1#Nk+s6ې MCtQ_}}7C,H̩3ͨ}=Q'LN1,:%Bc{Q3i`VL9O-FH 6 芠ͬi䦖 w$EVGE!f(1z5e9-MqsCdU\jeK]|̌!>Y\Y1:6fͥ[37/59){VUCUղaDV+7K m8<#jyA]+YfR?@Mkk8Zd@&i]B"M݊wXU\_u.T|!h` ~qwQR{L qFc=`, jv霙VԊ'QSRf ͚C}gg#@gH6wWI6qߌlXu-ܦ^on6')R=Oe?cXofgwwO j[_}E73!\oGn_˿{an=oqNwHs.# CjU{o/9>Gӧ>ƿ}5x//0t= g\ܑ6Gw'3 fƂཚ"w !EF&plnN@%F>{@"↊$СGkK46Y;h$>۟}/_M1Ře=+@U'æ3h"@U6] p~YJܣ*+m! ؁0ikxjmHiuθPܵ:E@0s@&t@H%=:OgF(&Uō*ΊY n(^DfJp:TSl qt+V=2ybFauI*QIS8Ubm~]K`z&@#|>>%1-CI|AY|d3Ln}GUto+,CU7k6FdX]bJ2 gZ#Bq#O`yO6\ϰU8jv1oZ v]dz %/-P^W遆!-1df:Lޜ $li}ӻSKUr|Um9qwDX1В^ջ>vYoX[&VW;qxܥnzտo_ϟ_=xԦ0 ?|orRtD5Ʉco/w ]:[Q<p¦淈g潷Z;4#njHHԠwRnH^0!K1 bhY%:6"F!Z5eHfEb )k^?{ yc=.N#WqIDATRA =jWAsZuZA 鶻AdV>͑xZ-n@ لAzY{"j-₦8E/GKN,[4Ā26E`5R r5"8]lVn@>/2;#8l.&6FNV"#n6*{ D`BcgscJ fѠ@jBVy UE2w1 yЛs/ZљX:s =vk#h2&ĎbI&BΎX(4H PC*\tFZ*7nbѝ 5)zՅÙT3:zuX[>-@@Lsּ!\#-kEe.:@J hP4f1lHNͽ8M,'Um 0^q[wNa(8"kV4sOx[׊yt$0 g y_VuavǷww$tLn^A.OxY{ <ٔq9 }~v.hZrri35:>,vJ/-]}c C1W7G>Y**Lg!خcYi\Zz&$9'xЪu!ՃN7a:IGr sߏ{eFͱ߿ʧ㨧 v\%u֡E%dz6&>no\RBiG/.]}r ;ӻ/^F֖?`~(Y[eZ͕-B2& [ dC!`//^oo6*ߓO+rH[fnփYD h٘4*!Yɨh eCN'xtyTߍ|C" Y=I@t,IqTJdիy/_|W?/GЎ9PlE@ZɕCZBM0ptFR߇@p9Z;_j%CŲ7.23 dJ+(#&&5f4%6s"Bs=FNX:3[uWjݼщ]"Z]]>\Ƌv{ϑd |>QOQW0rr5w'=uN(nt+kyJLsk Cr$1K3!7.U{Ӡd^$upƖWT:rCc8D!ͥ6B~GZcwYP9{ #8qI87+71"Dhܭ3i XM(8S̓H]7c6W2ub4TX>9ZM54Z#^7r( hE-dq' P*]EAq Y1S\0uJ]tm;9ظy1wB Ʈ-[*2f VCܝ[<~7r_,?$2zyLM`<8;԰/x'fxoC/y` Wrw y\\L6x85ԭ H H"^3V@Wՠz҄ v#2y\ GKk|;ݴ9?`{U 4CvO_|f00Z!Fb|'>ѳg{o^O3Hm~|uU:R*(Hժ/Ś&Cd"Y֬*+cEsH!KCB nfL@!#"`ENIhv_W>Xk :[Ud!xC44%I\z%G ϻ[?}`Ǜ˔֫^lW\Wï?_֭䆀HL=9tX,d@h+l]IuKDMRj.\B}.^t~9]#Y#F0{$ `=wD5sf QOJ[K-F *DPY'Ը! HDJXV!#o!W Za6S`Cbq@\:|CaoD{;ݑ0`fRV6 U1BT&rR#hQ+kR(znpN̅YVG`0.*`I {# -Sk=xl*`tƎ"X!@p {݌ pB7uFebz$iboEj\ZSP[ŀ`[ؚ1uR˧z :KuC:rJ%MKvjݢ%֛GàQi\=>FXE6x7 Ԡ!m,-݋q~ЩL:s㘠EV VR=,n8s]Gٰ HBKov'?/'n~x߭wz~ݰ{j=[zL,n]l}v?Sf,مɭnVҟOG~}_߾4N2\^>GO7kL@Ⳇ^,[ԈBqؼƅ!fpE$'`b\ZQPb/Dp)#3s qDjB2%f*`4'* ء6OXf#8 ;j::*تj!WyY]l.Ƞa{)\םo?wu} F&Th j I\X)2aҦ@"UI+:Ch]WϮG~6jشEvI\ű#ĸxB9+{5KIEXCmz "t&hѽ"dNh{Y(gXvTtt f@Q5'pu\f5YMSp@pf8TF N\ystlQ󈝚֐] Q=qYnvC t a?&}a wթ̵e셽_XaPj31fXZi,˧)hRם:d`?(VN*fY\N}AqBGT;4꒭a;ͳ.~q%jYzJܗeNyICJJHC~O<~?8͟mO8}ˇb藗7Xl };Nz~G4f#h,I9g~G=ᄐ>=[}ɺh[l¶2U* `v|]Br1q oL] ͨGl؊J̺ɚBEډ ݑ4:!GCxwxAmi/^AHu4`+LZ;#eJq¸L^G _"#$!ު1.[ ǿ\LW7V& tθh- L25NY#nbJ<-H0FP@KiXn:A*>2pTZ$F1)aƑ<9ɤPEh|bG7s''&T(Ќb3\ W#N h )`[dF L` (jbz, Y@RϝwP1g| 5DlxQuA6s=f@(HS4wWĀuBYarM$!԰gb0vM E6 7UK6BP &#=je4jCk9($nU ĔQRAH *S1pЬ]su:*), 6\W+j]Kk_V^Bmy'|a3/_wvM?0}k[6WAvq ;l,}|/x&xBiIN`H.l3n767;[]?*eɥitZ Ș Ů5;6R(X7N[ elaePCשܲسOJܰfʀq ky5h'RtGOj9mMj^LDKd )K FP܅o6?EBWy5}~sM1l>^Zm<_=!6U>ݼuEJZTЬ,h]}tyr߿={0_Ͽ_OK͊/>x󽳔K/ٔ|DP{aA-4f_I 1Bj !gm ĽۘW֊3#*ym$)S`䆌400 o!ЛL\8w2#QcD+**,f:1붐Kv7<<B0v4}A(2qQW+̦ jnXFQP jCT}f*H(j5JP(71CEGcJ==x %ɇW1g0{[7è;'.9.;9;Q+Z]:@ A5MshmVI JỲ(= 49ꊱ#D%Lv0kAr[3Jkm:9{upX8OaP>VG!DU0!danĩ}֜ѳ{H[!֜Pxn Q\7fUlVD%4hO?eMJiWMm&5-yjmR ]ep͹z9_=yvhh~s UDC?5.hf}"Uن+e.%Tw45xhK[h0zLFm9MpWCPIp/nMٯy1EjZq >'H-ڲ[WYðpI"߼~0~*_޿N.O'@£esv?_l|mֻ|qy{{P߾귿q_ >>zzӋr&y~zq{cP6ZcUiXgqqs@3ҜH=Hu&L$2t͠8 ]Bsi47?_.fRdcd::B+M[mw.]]>L5oV ZH R |lؽ~XkHV6lbT}jI|;Wz]m)@  ݎ0 9'赨׌ֱESnh!l`@ &827v)@ߑw6P6Dz,J884>TXNdH F-`t 7o㤄(586D\bÀţ{u5N CCe#Қ: iU}tWjT]Ḧ́Ju$HlS(f+Ki --h.!@4c7qph]E* = 2`.Z* m.I-bsU ""yifSUl9YvG1lwr[G8_/G;eRp# ΀c}zt;pvq坽|u60l` WVX&|+on*Դ&ZND&ϳtkNUvC* ӒρsCf"z)5*^חVxt}?8M~s)mi9K>D T `^L0 asjx+|9n_x j偽܍*Y? O>o8G>[= "J8?e;ld!ƒ~g~li}>m}x 5H8h@4 zMZGNX yF3'wȭ-"'R"HJMxDWF@aн#|(,&}kee^fAʏy!] +Vn`/uyAz97F0:0,n-ƻg]m6 9N{J(ΚNcoKRdS::P }A8 >8+Kxܭw;Ëuw`r"PfƑT- 6=8s%XS $80ͦo<)WZ 0u摽7YP Ms  zBcbܵV9)yqn!"ͱeu3F@8G+C/ZdV=M(-MQBG,Yd'J-G` Su@LRPh}6&~l ldVÚ /mTR`4!hL+ UVy<eB6tCͭȥDP+cϠ"UZe$RS4Vt-R$D DBP. V[$go Yjs'ETp)'[}%\?:?nSN>K/Fx7 f{>Ze.~%͛YJvjZsJ}[cKmv&jynޟjӯFg& n"Vąb7Nj)ڂCX+tr=]VTZS]\A Ni3\N&z CwGφ`<ܽ+B挂miy<>>O(Wzg.L|~]3`08MWQI/_BIkۇ~'}G_Vwߜ^'R>X=SJ5oE* nG +"R#Î{F32EQ a7Д],"CHgEp LXGĂ&M;,two]#_{:m>jx"o][ڀs뫏Vk|{Ono-(v?.krn'`Pmisp(kF h6D@!mNX&eK -'\%U \d0FL ltuTj"B d4TR߿߿70Id s:#"}/.f0t]g5t\%F95Su_YJR9 mf:y?~]3ge:"_/ f 4X7= =dh6$kv\Hzfk(-bbjPZF 12%&FvYHuagK 1# TE&^>Dr zD&%sFZnWw* xΑYpÒBͫBU؃Ʉ@ JE@E[V6.i$XL>ج Pin5sFjdv8z HjXYt@nT; IфN-hrD+ܙ8a>eU0+YsÊ} F!z`YLLPR/"0 Z*b1NC364U0EBЖA @Sl:@h, 5pwWRhUo{8[Qoo<=tY׬Ggv4b}]_6!={Vag<-~q XN{n\Q8!x)\{+4lͫGa7%=>Xyl~|]9UıF"Zwz\h5-M*ASTy;eh&yj*A>;^}o_bLp?VQ˾"Y'ɹ]^P(1m_gzxs{շT/~GE9.7XPV};_~ⲾXSݨ/ji`勗?񃮣]~?dspº is߃^#;.Sx=2dp6XٲGְh\bc=@SaE x澀c {͚qv%@δb3Xhmy}_?Ջ=9Ϫَ{\_PqR{ Z'-y< ě!+i$@&Х gsw~}OjHNf9EDlA=ᘶUJRPE]:1!:% qz\&0NڳbZL=th0%-Q5;[A &e6Lj@2PZ#Bp* bpQ`Lz F Y6$ܓ5&L90+ 晐D[1(4}Xhk⸒TT*j **h-4sDrGDg=^ngI+W`SࡒBLRJ[ݏȃ#bq BaEEp[ UFD ։h HL,B(DCғ0El8 nGOcRM4DU@6n\z 1. *Dg3AbVlC`ٹ՜ao꫹ z;B.ݏڦel-<_nJ1vL``!E5b "?|~6: :a+mR;Ժf_!.e8.wL}O(Q {YQ)4 r49`N7Wu3X"}3}={3_{p7 )BX|2DxW님:7@)lp0ԭ7`oLdBba'g~2NimR4 w߿ѧ?^}}|~uI8oKθ͏8a?{[VكǏ~y8[cr ={O'ϻ ߎةf ݓ竮%VdjS5Alb :IR#*؋}G ^ k[LGt1)J96p=$1V莂\BC7`^^ɫOĶe(߼Z&i6ᡈڸ333y)&CS Bո9b ȋ[$R_ѿׇS# tU(yAWR9P"%6qhV0ct2[b6H" kEju鲓(42eIZw ^X;hj, h^'E DpFyr L !(8{S9­en γvVؔ}Ƙ̙]k XG ` 2xMF-J@S3XDp DB= ܛtDEc_ NX$]s HA\' ]{j@Q 9 [ *Լ6kՎiSL Br20aA3$V."V #kTՐA,)pd r- 0l0X1u@nl ,ˆ(#b%c~ݕ,߶77mL/ۉ4ݕWaчvц߿g R> aބP㢁uynCm*`{kɐWmP!Ay@MnJO@&~/^ܽ1! ɗVQe;p0/n1oVg|lw6v"I\,ha kfSU_IG>n~/i9E@@ C'?tzP-^z}бO\׿?}~'{Ӈo߾*/n\q ;#{t_]f k#҆MѝZ Cm$HրCvRn9 iAo[Y=6]md[(>5ցLvs5Ʈ-}?;!劉ԝ)D CIqPNp?'a sJTPH%jͽ%bTAiŒNRȐ}#n8J a,.Уma,;*K(S`La8()Tj0"A/( )!7lԀ828!0⍀ * Eo93U3Hh9Xn=;Gى)8 N : ak*gHd3[  xEC y@1,:x:0tH"9-j9iӁiF0 ;H 4}x1&*@ej,0'0x2wdJ1UUY1!՜-8Hˈp8jK5V i yR3qQL)'JIH[PZJNa'te?+̍=u} >/<] جt%` ,Ef"$ͥa F41 4.:#` 6:!9bGӟ-۲dy=9jv{aFس璘JxgbswI|:>{zs8ȼaanQBQ&I[D)["t=%YHds]#2hLڡF@$n@L(v!j=;A7ЀF+% Tp !qWƁAPF*~龍a!JK2tк3c(mfR Z&̌M"$α<H4|vpNhI DDHí ms̽ks7[j[K쎌RGND)LI=pI$xsPF!GyHj*AXH\ ȰhQفk#E(D@zI^^9W{GzOo?r6=WFi+qoޞU|([QGJaeX5߼i͓ x[#q[bXWA(?}19/VhqH 6!~7͇~Wz?g0{\~]4Hj?ş^_ w?񯾸vLͽ^>}|3!63s d](JT=(#@)GR@&^)㐤;IrL^@l@@@`Bڢ 7?Wt9^?{~s_xI<˞nkVi]sq*ȻCkyG +%A.МF8.r?Êy<\a42jT5ga uct0p$uBv!QKO.w"cPGbɢ :8_h9aa/>=yy'h щ*m2H$2|!V ʅ#p#`CK}qI[`ʆ1@2P|s* ̅)̱pR ,$O.h : "+h DA=07/>1Jh@LFiP c7goI(zI(Dy`q%F8@ $ь1bw5L R aOqv7-i۪y0׳Kї57qKᦝĽ{x"S ͈0\Ag'I"齐ɽv.U{4 SHY B$HX|}?cǯu''̧_W1y/ruDn}}~xHit7_< n ͵w8a~nbku˄ [F0c^Uƶuj:dIukÔĆ4Cx<(o=;99=<7Xn>^?=PrLӴUe<[oوOj@鋷olC5%@;.O_^x7Sڑքa~?~yW>7w߾{m7~_J~O>/go.o{H&YG/x尳.D#!¥$]69ۣVNf5:2 v Ő 6G,҄uv4 A% סLPB8]jտ'AXo>Cj;rNIs h뱛$LN$ ˉg_  lK(I̡M{Iϯ˿M# @;pN[4Nw ۹!naAZ 3RG p\a`v?^=粒`$I9ݣ:XD4f)G {eVĂ8sgwpv tBT剪O ؃/h51{4}E$dA$9|C,3@pOT(F0 [$!3: ;%?C&D䮔F`db ɻ:8cCLNR*ER<1q`IęX=(gFՠ`JFW%b#0Q;7xMp|1pv^! 0w2r2cR7$@"Xy.䑱d2Ì#ՁUB ؂1,B( 1x4ub5Vѡ2,UEF\ g?g?B`YK%9:mω87_`tbgqKN]3^=9\r̹FYuY v]a_o)ȹzDjD+yCFmU⛒H[ZLS=@Ff7@0<>\N 3\S-8ƫMt~ǎ==Nwoj\`⣟~׿nӓnɋW{wkhK;6/޽{+Siom?xQ/ǟg|ﶿgnq~G~?ͫ7|O??r$A#@jJ >il .uC`H4a`ݔfމX;t IeMΉسcCd .cWoPufArXrü_ǫ\Ez4`v:1xuU~whL.x=[8$|y0;K?_7_^QvoC0R A c )%K ZI3!vAڥdv ֕T$Xz7jʐ$vѠ@ե䒄9`j(Lh*VE)*.C#:4zsQ0IHADHйnK} 5:tpЄhLa @6Cx@ l3P: o$`O<(3;!*u=5#Ra/#-C3rH1L#9 #`$DH 4{(cPjcwLmOi} _֝A=mkxmضXZ'"6o[NѓpXwO\U򲸁Bĩos v O aSUCpGEJօBpˆq`ǀ`DPظ#7õh.s_jS {xYE^m66Ɽ\ø \F'qXz(41dmSjG08Cv P"H|=&sX+q30^ =]qy{wg}xX|mbd? `U/߿NuMp=HJ2{3nR)?^˿˻ N8Hy4_|ۛ.|͵<#囹$zhmjR׿m{M-WO>?{_|Wlu׼gX'O>}@8u:{̈a2t)w0i$B b"S8#wSapg o@N (`z6;o=^#{] Un݇p}qH=>0qf4J>PA-Jpc7_?=~}lr=\M08*xA61 TvVmtU_uvVaO50$J)z)OcBv5BR>i,uACnvy~51 Ӛm\  1- HxϤ2`jF 9b}m\/D CYU`.DHhsAP-\1dA]rBޫ6KfFgc`z8$Jue8 %3_ =bO˜KBkWߩՙe)0YW#WOaK̃/gnr{[ dz__̻=˲%]*2N4J`Q@#0n -?_~/j_ydpw<\. ݉jʙ FC$T!ضp벚(cZZ(9XD1j7im[Boűx300 oԠ{cjD#YcN#v@|9%qfl #"AZ 2 #BgPD$w3ppEt 4:+ $$#M#NJA8 L2U>q2 4UN Zp$Φ"0#8'3cN@E1r"  + ǐ̎AbvJЂB8["?"B ~䭟BVSJ5 A$cf mrG @U<8u@%) H@F1eI z7vB c&Hed;`5#R0wr?77p,3ǵ[Ru %n͵G|A'}Z ,0?.+~}w[@V9e.>KQ2$+?%Ek~}KWu7ӛa\uȴyJR4 8ޜѺFœZ_3!?zɏ>۽ǫoۺySBjړLO$w~wś/0=F4].P7gNś7jݰ<>x_w|?o^<Իo۫w5/C>O^̟0}L+$ S- 0p%ՕR1p@M%1f!:wIXg9:\1ٽF'JS)Q RpĜs0ab.[>xJn`60E__qI z.Ꚇ2O)&ᔠd̉_M/Xz_ӯw)bBr}q=Pt% [0r@\VaF y?ڼ/dY$fА8!djSگ%|tD0n|갃yW`ܬ qGضJ 8J"sU[0@=-Lmu244Fa 2!h`! -h 09#;HW X O@HLݹpZ@,@]itP1!!d= %ܻ򎨁#o3DPETִ䋁 z" ]E\mM$vIBH &bX#93p̞Hpa:J@!,ơPHu4R`3H_h; Dh`=:(Vș}{3$1  0P@30u#)%Bc ΈJtVq hPON#_|.y[ktps_*y汷jđE-4ҺU(JKfL(MkՁjEֻʱmŎ0zk'OF2O}´;Ԛiĺ0zn<*#j㥹{Vٳ:2 /{*PRn^|FൿzǟW_V̩`"m[ݨC)C$z.)|R_mk\ӧ^}1)'<=_3%ޱ-h]M;CF@4 )䬦90QÛ3v[h9G%k! ` ͛fIrVc&46'PZ.,90'a I{|lU֦P sx~f'+VOey-} 05]B Kxx<N~{oۿ+_[n֑GK= Q8z Gރr1Bh *:o5'ՔRRv<óu=f(7xx~S1cE"NR S2@tw &uB,P FFZ:9e D#4^+Rā:a3RJcȡD@49S7j@dDfY(Y3!C>>8wGa%A֫a@sgK&$K H03U#Ss q؇P%k(4wztT]`(TWJU~6a歳z5!W&vs/ľP5 +tf  Sс Gf@CAD05)D_AkpF/έQRTQ{ o?3鯽_wG- ўq+1hI qt;_Oon閷h 0;Jx87{ ӎx3Vqݭ͠2@ZNCS0WvO"{y=n`//Wϗer+OG'u:(//[Co@̒jǦO?~.H_ۻ7GS]J!ַ͈q{zy\:ƔfBآV7,Ǧv7$vt>3i:>ڏ|~>qi{/~G{6_>7"±9 9x$6=VPsM[Q1FW ´f(6@LC!r'4[@ B2H}efྂB /f@v~r=vF?8?w7%]vHC`! )%a$eDiu{8_}q$4hV$$,,8JbIz c˜vIAJ=:DF$^Vrޘ#Ͳޗqh 2y'hf67$)J^{` 1jBmԁENvDxtt0 `'w FsDCX \*jH$-rCψF 3%G PK`se*1 bȄBГD9fh #0pPω[ A>a$JD̅Q2MS)I:Lbd;!]ATĉMR7+dۦ/U'\lURr @(NB`B(fCjTĤPA!V?B9B %1#2Z/Y-h,@, ) A78gOo!WDmÀXǒ/6A>yэ꯿V ӏ>/B{$`lI cބq=T޽p݆OTJPp}~Z=`vomzw_w߽}SȪt^(yAӫ],Dm6c"$fBaDڷAB_êvCmލ,燷;ӭ3~nvJ'f!z ?ݓW_>o빋鏟'\_\?gWO|Le˻7O>}2x2}g#TK 4p0p p$ 樝wksJDL6H…*a4BtLZ9,Y8k`[ 9q$O)] :{.hq V[•-=)]'9_uﱍ77uw;Ƚ<ˡ:eq9~gտwa&LNb ,P`%"j (V[wGwA#&0DNyȄa۶U)3m}wu3Ny(lH !9״99n80aPBĈl A(w'KI#p3 @%J`tvq6Xz@RG0%g@p@ ٍ%|EsHWgR(P'xOq?&nA F-%Br@5 8a7$t0bC!ճPJPDXČ:N0$;$~1hn ۦ &ZkjkDZH iL##B!qN͍k)! {$Z dm9B)88qS@LP=ĻH"0W)aygn=lӧ'tx{1I#٤ijߵ~bE>?[O7v=y [;\q#ar-Ǻ0rqb!R^x}K\坝=st&Sv[<.";-S=]K:)mF<=yjzOSfJ3`grՠ.+*tHLqӏn?{׿ӹbaÇ?o~/(ZM =.Nj]{qzy0?`]pwvϫ?ǻ]/Ο<=?QgOH쮯EM 3c H~馎KX  iΒbF7춪[z޳D52f2;ݢo$Y;Ҥu xlFܤ.PM ຸ7uswmp[m>M_y)7/–N[o[=^zyPS7TL)@9 iTݿ׽nCFc\s@y08z4R0`Fbdh{NI$C `DS`0jz2,i L%ҧW|=dR%A=|x{{aϞ>iq.7W_uSluUU#w21iO{i r<38힤};\Ի]'/WO;U۲ַ|ǟ|HGBp~0Y@n@9%FOj*+ɤ{dJS0a#Gs Y [a ]t*Y OiUK# d# $N$#R0eՕFu,K#p4 |XW)ػ_}yzk߽*vMo`$;q2ny2mF\0sՈ P ANC ke&ĜMpy 1.7c(&!7s^1-ZCv\ƹ0HQBpsV$ SPA I- % &$'bJ #t"\Cpst[sDo/D[D@f{: Wcp 30Dt ,$ѝ3PSa@~S$TAɲ׾s4*;`!p@LE5.+!`t E UHv0SBgFe4D4¤@ >Q@Bl`[@O8t9kb[. 7e$&6Xf MHAhc`͈#<[p@0DX`B! ; H#恂B\@(Fm8qERЂysQN}Ӗշ6uCp{U VLsCi rP)Bt~>X6KJ>=~Pg]92/wΗHtݫe;mmdG)DoZyfқ׿ OQ^0c>mK:ayaQ?۷i9O-O/qMӡ0:eƃ%izhëo_ǻww<,bqf(e3U3d@)1JoucP$@܂JN=dpku]= 0gĂ 1fXl̐ a6<WW{̔:&C6 m%g*qWOS_9X y?Ð1B޹5 8 `GT 6aQL,3; :GD@cubHB"jT qCAA,M9s_0GbHugn$=ZKb#*L4$I*SA] @LAEm\D\ >d`j-[ /ũP% 7IRV T7tqHZsyD늉ZHAB$"ݚ83!FܡC(ݑq&+CA1A;6!4Mt򐥠 . wmo~'0~mGQ{Q[ao LSoK2F"ꩌ \#ZyMCGz*+Qi#*޷/x53vp&fbB<B"̜:u6PDB0y7`fwMyDvb;i~>TpeQ%"JN)D&& (<qt7T<X-Bс SAb!saU&7r@ލ "`B!=)8]08L>:8G[I‚$7G58"t#[v !J$)RrJ)s R H {±Pؘ=1EH- |ajTf`ɡc4flD Ř9Ș$SlJę#gl<$1Ba3/ABKpvՂA#) #*Hb=]q8ՊY!` Gĕux `t`׺3NMJ*r%QٕP©-Hh)e FTvAq,r֍s껯h-.~-qsP(IuAVTڦ_|(ghnnQy3C!@ ؖȓEF9 ywgADd@]Д*Q@Ą qf|%h s9gº0)D.20/vWoIRb]-0@Jaʺ"j A@TB.9!"zEfwT 0Kk`cOє ; bD Aœ"Qa`[) 6[,fP` z8B! Z ipn0aD3#fvAYE Ȃ<$zB8%.9 =A0`!0yYW\=&-ʞ:iߑo fluk۲J .@iiH㐴Yw`- ;Ӑ}3CSB3E3cF-BGd6 n dn:| 77=%1Dtb9'q,aME)ѧvb\.FND{nּ]X[fja@RdHbf8RI7(c$i>HCyGe4e=}HW 8v993)7`D R"H.n zǀ>9eirlE Bcnßa\ /Yi% @Fl!ly @ 0dvE0d2q2J@z3a@D[oVĶFk E4uA))0#E3"Z)e4; DCGixJ02aZdFBY8#w>RA&BtkH;VzPmyELxytCL\m}szÖs5JS&|S5hǥd0O)39y!;לW7udeps66g[WmF#ǾPBL[[Rwe@ehgZ!wsxOdh~&zإw 3 0{4 ;дs]U04< sCۛڌ G/㺻zQ:)_I pHKT !4Qȁ\ :DlnLA(I17i9eFȒ"p@n40'$Pi:źNi7_WMֈ iid$ ).#֠ĀՕTW]c="Oc_(&|O>qZݻY襯qIHR.;o0DHl`40H4ZD9'*#=xiЪ3$.$Ӻ]\.9 a E4Z%JvOʚf ;3vG xFHbQ dbN1ु7*3 vp%Дu,L] #8xps1@h@djbzG ܁j\W|?-;SbJgzag)]$k졯l2hco.:uF-PI P#@22LHI#$J^!(B.̉B.M0;:9BCi[-.:km-Q=EUBy| ,ls*3 a"mnA 4%H c@rr"rxGT;LInF(oaH vL>.\FY}|8Òx;a FQ]C0Aūy۴9OW:>V\i>o =Sn'Kyv>qd8$)y7FDr}y[UXۯUOҢ7u~{ɱ䬏'm8c)AhNvj B2X %Gm [LC%>}r' ZnJ04tK5̅(<'$DUCK N;̢k@AuH#t"OPAgDdAQO@A)C8#Zam5FRuuF36d)0!pu{EnQezfVn^yjf|YIf9h뽏cF@,Ĺ{ )sd~㋷_ν 9 |zYuaA7$ o$g<4RRIpY>&@SpT!m@p~84˽G܌2d#<%$HSwbbda@* Bnmxt3M22]yPJ1k} D %& @Ǿ: Jn 0{Ԡ~r AƎNQSdXj[A' .C9 95Ww;mn3D: )8Тm%VEF2 vqcwτbzl *, ( L KMn@xiL9Qes(`iD椁8>@ۢ'-:@wC9aFE ESgĜDH߭(F–!7D8 AlˑxP0$ l"n4 e&)B6p\W#DZ =64C%4""Ɂ  +`P*hF )\ghyl{uye xV8Z}10Դ[@.Jy2FnK"zZI5nԭ__}w/z;=K> Of@mJ5UߐZ=ng|=`ŻjYQ!wg][FۿmErmSװdźZ Ѱ&>f_~ɋg/U}VݜxrhRՋw@l٪ՈCfqR;a]ї,>jWknHÌ1bS tosqXNfh0G2 5F̎p8Z%LAB(L.g1"¢Xl3D6v%A e߼9Hnk4{B1R?45fIk 9 1#'L`S,VIDATI]?>kh>X}o?g|4ک+\>P\Er G܂Bzeo;5Q`;Anà NA(<]3{QN,0 8!T` S8$L|MBa7ELkh\vCDm7=ݙ@i=%6^4ipy!ZqZج$#ô #JaB67'̽&OSѨskܑ߾0FHyT7G2 BynպrbP&ԑJJyȶ`:Ms)H9t5y`? *DCydѰJ&n\PXz4*d }df,tz65H; X 9]gJRJxKXw v6ĄD\56ܪ![(E݉{ PQvO1=vBpRY;tP D0wdzDG*6n  "ӈ@ Ձ "ȊB+8bHA7#o A׀fiLT$f8 xΦ-E,ٲ,IPU3s#"3"B =D@v|G>;l4э"*23g؃?TJQ]L ̪D<&)Z2fDPtu%#s (%Umz+Qw-L.PQ#G2Wi:%ihF0|{Y_M7&d9?}]^\$gT̰k5#Qڝ9HyOߟ 9i*^z lۍ,~s=k\֬ϫ->?:HYf??;>[z]0"+t»B"A.O|yL g(e Wuw{:?i;Ne٤v|<ٳW"~tHFSTjb ]ů~7?t~w?x#^w_>EwEKtw:,F2H#XYWK? 9G]eH4x̩J0:ڒNoY  " =] E\,,AJL$is#q % 9(-džnѷn{%ȲyјnH+kmo{x{1TjtaRCB8wTʌGۨ[6sNM3G'.Iݝx3a=8A  I( &ʨWv::e= R)t2yGN4=ٛ=!v!nv7ܡG5ȝY HB@BH9V&IJ%0J"#uℲe NU`H&AD)#T=9{RCp"b}[:8kSo`tԊ+%jpv-0, H ͕yeZJA)әxfMPM3* ǮTLҌ$9iQh8̆4:o#}Gi^+#BA az @cAdH2CؽirQѽh`<ՃJMx #AT*Itrpd` SW/0apĠf״WL֩tb >}p-(׋k+48ge[zXoJ\F$[ܭv8R62T/,qc0ENStR ??>;풱f<2vNjV'{e͸-BM[zye~_o ,e^c?ҳ_F~O}8ϫ,|vپ6Hws1i_X>rsx/_Ua yꗕ2ҖFJn0Ī{zJn=/fvQTwtJQ'ޝa]T&ɩ')Rl;q|z*Znyxv` DZMZͰL#HΌiEQfT@׍BVtǑk*[%|CmcˠYUpw1Jmt{ h]ģc,RP&)GNL.;Gv;t]Dɇ$ N (oS&]XQI׌sF!ҳ @F%+B򧦃q|Ni.!% # A5!>(H(9ɒDK-YJ8m&xu┥h2-ʼnlE1[ j JvšTۧbزM= $5D$-H Gn1/;5{={@MVl*4"$LI[Byq¨INY5T,e"!$:"8 J<\2=%tEJ!>TnLد.~B'ʅƷķ!e۶tH[0S2yTq#0єN701O$8ZnoX.DYਣ,u}Yr*Uo?{)/?.i}p)1S؈8lb[J6| F8|Hc*V||g5I\^ʋ|IWO<?{{˵$=?8kk/~/j;fÏWWcn^~?g"X`S>nesz}^2k fxJ}MhfJ\ʼnLٚœR.tCѠ6 [̍`"RaA S#%pSr2 LI(( !1tmS*5YvV&dwN9FMmcl{ɹ"{=5N.4 -m]IJA<@CJ+eJ f åJ`R#;.A9} 4b8XcK_01f^-2p:$4cl3؍#I?DnUbOeΔ$1Sk"Ή#oܠ{8KPΕЉQBDjQ$%gJ0Bܙ%} %#٥2,= s"R+fP`cF:$E%J)(UĺK@["(e T'cu榞hYBff5}0:HsugmLLiT#LIר}Q*ۍ.`RY$~i]7}%fyKւ:*kFPR{J'9dm(j wTILvQ| Du\Sوrum:k%w?g( ;<2dV9+YYZ>.9>3?k쫖Vm}Za^>\N'䃹Gn~tWEȮOMa~Mf&%CEAPaۂ?鵔ߟnod;qHF{BBnnf^<2HR/yQpvnV՗?tp}ǯ?fW~ug|7\JǍv>6?V u{/Gt؞S'=ZN˰i}$A~xv_W/<._[{?>8 DEVέm,QǏtM Ym=[&KhrYٵ " 딢]1OvӱUoܼMD@'/0;Cr$r $p)SB:р-]cd%1x@F TNwh"pb|z&*KxDW&GQڨ21`֘`ʹDʘoF;QpRNɛl ;fy5Mˁ`lc Q%*+{Q(=\fu{7YW摙 IRR$v "$9s#XS 3Js;3BO݃ЄKM2Q2jgNU|rDllI9l2Qx&&ƚ:./ F]s3ä8j*%sw ' cȱz7̢EN- I$$⁒ s,U>H 5N*)r'ep$wutއIW-wik:GoH@W' E!6Z=ĜEI[()Rf̋b7TA5BDR)cnJG:+#UMЍ C`1vTzxv9̟A=f^>o`mƶ6.SOul#ݳpLc4ߟA_{?} [M_mnSyu+wo" \Zen77wlcTѴ"_;L-ėmm3snuӣ~=x?VW汵;yUn*'; eT_տr^?tË_bjŻ &Jjus^lRnDtbxA" (I̕n?e9( #@qI)@#IN)+IA J|"845|S;4]2J'R2I26$1H!--m (p٬g;H2O*_%NSZ" _N}q&:lOd<RUGN؃c<ܓʐ4Fp eWۉ"8g#*BYkHA&gԦ*gQaSwn YKMۍ*%m kjއ(9HN&,*5$ m]Ss8)WUe {f0cKprX)/Hg'"NSqhQyjdgp*5Ea_~; 9qj̶>]*IEu$ szzi@-9dRGY *'IRD lRI<1\R)s$v 9H2iK"Sa9"|]|\Ơ0 MZHfPڑ3MT$~>bRۭ(dHI,Pﻑ([`uߓ-ȗEj/O Z2QZ FwFf@.tz_ /wlSrPtڷ#+xJF7߼|N(t8Eek3c?8_/toblH.RA|l eR jUp4-0sbB~!W ^1;aއp̖ PLYӢAҼܓcB)`) gݵ¶ T4d`B$/gruFQEC@YS[1RZ!c @[`rd/XLO Rpi>aDŽP)8"8CN5CJ#K$i.D:bX"( 酺A E~D>$jcm( KUb1(R j<T#Dt5tD5ڥTLJ;$%FPܾ9->r1H&-XȥJ g; >ζLhi\ ([`}{~/{7}^=>|>Oe}Zqq}#i!L…X/\0qfW Acu_7[]&*(-Se۽\]9Fr׳(-__?_Z?|c޴fX/X eieS/˿{~8_(:stZ~Lu&ƞìY /AE}Ӧ$JXIf[Rq.@Ҥ{3}{TD%=P-,Gzd-~GBl*TCciŶ\}d>6աYH7GXb=LZ$ٌRrWKĠ Ŷ&\` )K_0&}hF$&/Z2.l+~CW7lDN40oO_Wٯ>C3^2F+~SJQtnyxM-E'J8:`I.Lj5gB=&& i1ӦB.\q䑅!cIrlӰɍER% SPVpFD(CY RtB,FP(LS 9I`xe=ŀ Ҷ3|:RmQOMAO)ij&xz>š[0F-T3گ\Ƨ #Ւq1n I{RF^¾γBƨ׳r GRtR0{-ХOr@`Vٸ(Ȳ6A][*&)d8cb#=c3e B<45 $ 供KOZa((s@DuD"Vi,P OͪLt&O/Gr% HRmoB+j\PJpzG%d89(54?)}Zi>\ʹTubY{d$G\?P&eǽo:nfΙc$_tyt$T =+17ogw>.7U/Wy}7$1|nϚݯ^o^⸍c_~ݬԯ^/ڜTZ*o4/@!C.Q_mZK{,kR-Sz:CS$ru~n K9,`JHt{F&Y0qa63d [< 6LF$3u(g&ۧ6 0$vrѤ$Caܵ[a$-x兎oyPxKi:a8Iz|7 NQfqL*-ܩjjp:9<2}j;=*jbZ= 1DJbĀPZo禮\4,t.:б W5N-}pޙ*DZ{^TT Ëv^J7.;iXI;eŢ @w bA{\2o)-U3% Io AS$Xᅐaɒخ H"Kas!7L;.I*}F` 1<"#apԪRXkHQ)e,(]ӃY(e'n e;m9yGs/ubV q)I*DQ5I>|3 _HuI`e9jKC@HgN49>xeߵeVMAFMEtxIk<˯N^}t>}ʖv/wGEH+A `ajV(Y6ZSeʢсZ1e-.wA\4-3^.zz9DqJJTtT(59k ,lMVbInvI g@TkމINj`ہ?3/S`  r䚖+ 6㦎Ğ(XHTC;@{fQ@ukMp2Ҽʅ۰Cy~Q~H𞲏0A1{p3$3(VCܲIK}-Aj#~x?̽Cx*̲T,LJ$N!Ιvbp-= z:]pε{9@$-L6v%Ý (NM@Y&g3`͸j%Yڨ(5%B&f-yk*zGpԶֻ: fF$m(-WkY៿T0<6[~yvw¾f6~x{_qy|@xZu̺)m]Ji޶*Oﺥ'MTv'b&m]oVy=M:boø~X{>^?~l|+u|קxR?ّu}?W?<|?`[zcn_'.a$PmhLsc}\oWVwVF߷5̻M!Tr ]2>KgVa:# k:@4.4^SA;\=@sIW !!0j3+2 Hi H-\.T*s\ehZeژeB}v.Z]trUD|lRO?瀹! -CPdp"E062w1;uXnaQD]{l^ֻS9>9=$ٽ{z,V+rWCҳ9w92O3ɱp ZNЖNlj(PFiaccOZZFqFjJ&d>zڶ;fb-7ƾ']ሎ?$cTX)"v$ōxk"t!Hn !#Cn( 3MJ"aM0'Q8BݸbڲLםͣ.Qq)ļRG'f&ҠsLDyMuqn0 9i!RH=-{g"aMFpL@cjGl۶t 6>kDDmPՓ)Nh`%' EH]@eFC!SkR.Ҿ%vaJX'Nd@I筪7bb^MBiaL2vK/H>EAnO-j@?< 9' =M/^|6~:FRҺ^V#vԦ7_|ųϾmۮI;HR)ԇTv㸿g(H ͣe|\S߅ed~??w \?)IZs勿owӟ^tS]{>ݯc>Qr!ښU Sb!L؍h2fRV}x#5/`L:mqt'\-BkQ4F2e!,Tͤ3>!ȝ@ 38SR X: $OAX@ HI }l!/MkJ*׉ℐ3br2*D@D G~%ϏWBV6M|Q57#6n_=r\LJЅҢhB%_Oe>د!q9y~nIEtws}{볻ۻ7Ns޲2n~sُ_߃07ǫٚa:9O۾l>/- m㗿cy|ZD9P\4EOa*%k ?v*ri"UHkn wx=>}WQxP,MTXv q6Ť|Iԧ:) ĕPPqLDX=8SwN<@Q 5+m<3[K;`0yYRbNLCzȺz7rb:3+N"; * rS*`mYz^?no'zRS>2:Nҷz{USbY|Ozv:r՗˸Ƌ_>L=W~~_o%^}xveTL4S3#H><19F8_~zxY|y%vCQD#3/t{G 5֗6z/7}~1B4m>|v>/f۹ݿ/yg۟SE~=w *EMnsٔ,@8%iD?p`SRޯ1čGa0,o~}vMXf;R9P CjT:Tbρ}'Ihd w Pi{ H4@3#9 aꔹ{Y~ w_sH*'ΡBʴn1*RiT%׎q,>/ZoF70 pBA%ͬxg*a`vOS)4LHӯW9u]/k'3x__Ǐ] Arkܿ?EoکKh 1Jc!7t8r If:>>e\h֑Jksxt-s~ m-`\ Aœ(0%mR)mMYʑ$䃈]`8wp, gf!t D2 $h -zG9fH7x߲˨*Òml-+v|ŋc"^}[LeBFQ:8om̡VG*l_4/\ݓ[eD-ggo- h¡XĞLMK#ib66(j($p0(yPK.xd ىa[ܤL0+j$\;Z&Qj 2bd'6LKbl^$|w%FDQiK2:$8hF0%39I(z 9̢ ?_d' yLI#=#`j֌5b7/"@,MwV%$(=i8,Ltx%lG0 ,bOΖ4ܫ喱$O^#KNHDnz?|\]SOF{ۻq |aFNQ8_>l={خOw^ Wɔc釷Oo}cx~$u_~-77q߲ @J/x2׷S}~kxY˿=Cb$aLtv& `n[:ܛpIݫW.iIc[ .nFdw"%8E i&D!*@&f4iGb0--B:Τpg7r  'OIpȤNp!Bԙ % ̟.Wa|ځ)`nD}"9ׇ)nI|/wsW/裶ӘH!tP)OKU8kH$tL-RjIEp'$V9/n^~]z[9V͇˾e]FhqRReH bGre*CLg@t4T0KDC;8g -K]&4p b.֤[ppR9Cȣu R =nq`$J"W ^ 4hbN*)YaIL"U@ZphmlTX;-;,`CTwBNm\ X#eˠku r\V7nK$Sf !R:d榅0ᦾ*ẻt,kLbLn2:QB3h5**,)d Ԥl<%MT<½0aEED'=YݺÖF>%ᱳޜ$˔t?=[LΙ_Tx{,n:=K SʋCoBFĞ~\Ώi']wNOou\5c;c]w _ͿnCl#sw}|S{wCtWT/ǚ: a.ݎ):VE2q [6I/^oj˻_7+_cZۿC}!< H;H a; ˱c@mʹ<[=-~3]}TicZk0QԨ#= iD1E bP$cFl`C.tE`E,ɑ4Sxu%¼fL@zHѥ,]R@g(P9i%xpLQJ<9{bo`#2FQR˦2'Y]2} 00GwU{( OvTҬNPW>ΰmΈ3eoaEawJezzy=Vיu30Nz0)5x)ժa1"`ɑKP!}c҅TeI=P\J aT,yUǁȢ ]tѯ2єֶSZ]As("ѣLb+4< c8hj&IY@*\FkلKb!Z2kpLc~^g[DK1jBi7% )Zre}KHJ>KQd&YXD'ٯT(H yd)rjize |aiԉ2ŅSU)qj[Wq1hR&MdQA(ҕ0%2k3#xZzܐ5z-2)p61=SFrx.aS+Uekb/oiRPR?yxXLJkGF}hu+T*eۗ?_ֈ@pOOߟׇó_=>?17U/,,*v>kp"7t1tj|.KQ>jm}n9LogukEo'?ioj&82 21pJf%z)WNIY@᥁GK5Gy"YxrsuC&T5"xysrY81U1œ ) SWʾGeƚɅ̩;gʑi{ rPp'd#H$s O@H?=Yͷ$Q[(Pmomf'f_; MSw~YOk:%vKIiP+Ԓ9 S^bZ‘U0rhĸ NAf}(5ە_ybк]-T8i}iԪDYGevϱ>)ϓ^Â}p&=ү4C&٬FAd~hL#:+3ᆬ, [Q!cPt$Ր{]h\0M1) yDFf^bI)A8ïlB&؃`m ͝$öA*}*׋Ld&j-dbl(щǘ"riŀDr* Qeh8+dDRܩ>.$E:I{'MR LwD`~ѳxo3a湉jQ;ޔ̥"^M^ûC.;@uzq<9[rw|}lOTQr,ws;-^ͷ!76 ̴ϯvϗ7ӳ~u]Nw筞BfY>9?Z>Le)GuvhX_g/n^cC}uǯ?t`.NFD!idX޼8ooiׇ͛/?Ӈ K 7? 'Tz+=wVݛRG:qM (te8I=hcZz̾ߊ(#sL̘IX fCtpp”@N3Oc(YfX);0 =P:MLM*&t0""Zy^PئA@ rG8OPB5{&db뛇ɴ擧 vxyWHJ:UJ9U+/I߷MA\hZ'fF죷@$8[2繕e!LUl4#e֬MdY$'6ΖSTSHD2 Ө ' b(5CKiLT"6%v\*YGZ؅0B* F@q1S6"fd*RK8'IOR{T_irȏ :HB 3 AIH' .iUyOI=qQNL\>ULay q?B FI3"t P9pܣ@I8O!YؽCIHhjՌ,%GI:J йΏՋ7_?{1Kyxuo߼ N9~dEnC 2v<{_o?as]?Gt02QBahjIû^On~=ŋ}&_s9~ U;D*;2󠤒4_. n>{Ͳ?|HϿzOm9hˑScٳ/~yw~Wo?m>?,MQ t225JJD'W%1+]'ฎt=DTq}O )2orpL 4ܒؽ2B`dɤ(P 8ƾS*l 1sJ0"2a.!a̤@ 72w1B^&=;]:V/cY%I\EZ{ﳏfެ̬jBH`3/GH3bB#i At5[dUuu+ϹGlVDb}TWޱ$愾(S9wC|VE79CwNvf+ 'r@vN +cy!l6u4䁒9a3M.oI<`ąA}e=J+fD=XV ! iPѕ:)'{t%$;r<`uGFwtr0 D)YMi@tP2eHX7 Zf]e\X yR$r(:ޖk/u]P2] ,cV@F;Bw-8qr5+9q4b Mbb'hKg9Q%Fk0ntq9 H,,J8+V̙tpJHڐP2&MňA'1 `-|eH)VH(;2q IT3ͅp탺8EqƐTuAXk&Ac??g_lviwpz" czg.cdqn~3c&TJP8xOojtQ =zoD!(2\<}q{z >ߴf#]t.qCUW/,:4v Iʠ!ڬ`Ma~1{qQ8oU[~~~ awIc^]M۟O\z//'G{L 0o& "dg1؂q89vCDPiJO??xs+徟V՛{F=(zadj9 M̠ " PAN E hgX '(F1Xb%ԎP U)c?a4X"NqD#F "I[ C``% )b}.Ccnh aKȐf_\\2F Ød}lc- NK.Ѱa\l}.v20(*ǒ|~&n:x!(2FX&O_ζ s%PcBeN huػ UcUNɨdd +m ΁G !4 LEb&6L[S$UGˉ}%RBIw ^C7@)u\Es\{/Խ٨Fá7Z;q:D@(!@30b[A0:cΫnsB ]!x˺uWrdIYHf, AxG T{U@, 658Zu17&G c 3Z%a !^KdӉ SZ@p ⾰#V)+9rF]SrӴ, 8*dǫa>ݘqgy~x_Va=B\IQkznbQ Q{ZM2E^NízQƲᏗ|xa.XP[-'ӫh4^^8eQ;xD淿_t %7WA@vRA9"2noDS ۧ0I]<M"U/]Pf3˸!]s:Kp) 8(kHs_l P$j&^C0l4"{q@` !TJ9"0 Nш`2Aу 03E8x@rFFLBs`U@6Cn:N@ڡ.S?š U)6&_5_\~g'"Yç"ø4kz+փ/mw@{ 7ڔҐƠU UmK.+j-e4 B  "鹥2 M?2uBj֝ mB'w>^"ypfA\ ,\jwyZԄ$St\9b e)GyK6!:iK$%a%qB(s*dg :m&8blHq:Nh $%hw[|8!4u5 HirAetK*An6FdSUY[܉JQ+x9 )DL@}U60FGJ ,4.tdrF:b&_@L SNUd`4-;䫦2吜H]) (jFzt0^ʏ?%[kVi;=y:XG2R'֕n^8 0R˗_㲸T6'.ҦӮ8I\zֲ{<΋4@X81,Nk}ڔGmzzح~uM =I*Fŏ͓w_oӿG7BOMz} -kUdaj3P7H6C^ 3EZ?wa)o,3GPz+g HeHah n&,3́\7j\P6DgH;"{׳'䁝%ْ8U#hT5V낢nnf%Φx_͚=#m*Hj5@!y;n /7 rf~jQ/!M@WNfYn)]({Ei+مvMM 1 -)l5U4C2@I<%a;MiFxlR)P KFJ\ 3Pjĕ܂CIbx 3⼸J$pBu6`w-`xvc!Z_TPZ8lY ج 3 zǬև_rYv$90wW !_$A.\3Jש1`.""7<jjLZc,' :f0a@8).b, {=YEK15𖱙HQ#A H $[ ,ukcr] whXFz\Dܓp4 %bJ6W,(&RN3)T!~StIEG [I)޲\#S (#Ze4%9a[AU"XA&Lƙ um&<hHc`eB2.%Bv'?̾||?ݾ {5{q.cD2u.YI~/+z:s{onNla0_~Qsryi{cdCW)tOz7W aJIcպxjOwi2{Í(E`8M#sۏG Ab{y}lQ9ǒ`xg g,yZQM^?t<{t?Y_w+UM4ژR>6 M4$h<x0Rw 'o/BWAh}4 %HQߝC;ɩ/pwB&9iCAmEH#J0Bt4-ЙHca 4t2E@YzZ%!#0{T"3/ Q#՛nnj?<u$dJ CJ(dfxݹW/{SeOyѩݵizh&Sý>!a!#ztQ2nݴ3 1fXA'ӦR)#K`fJcy;38C$%r18 cnO0>Xs47BP=Ĺy'=Y`HKs#pY«25"Z2vl"UPZ,>,8@()@:+z9k`_;TR뚆lp!Y[3HL=q%5h4q@ bPo> 䚄7EoFMWF6"cr 4HF` @$X7pC Nb`tu psS7< Dv>֎e0Ϲsٹq({]Lr ުm(* yH&1bDa0 `pwE8&9"ܵȲ XpFTf0Co_>=LBI#6$[{\=uv}@ី]}tZgǷ9޷xTDqo>'}!>jaHs)95m D;j7L1>R+aG4\>v*8]>S/q u9mKW:iLuY6~xrerZgg{ͻ*޵ݯө џGŋϞ+I}/>-s{:z޲eR7ݵ"bSbKD`$]#fpwx O>ɉʔ=:/=WLT%>غ,mxr {7y/'g*<3#i[ @!ٺ K&P<   c@FbB!]٤hfWbTP9pK';8ߪz&LJlG`fI"'XY"M ʐv?X24AIC#ũMUW[heqhw$z6/ڴ:3 d)1_ ""Z`1f z2l4Bv*2P@;Wr(555*VrNi@`$T\B )̀!w=NQrCy#+B19S6\EG)t7>0P_IpQ (rvS$d!2qIV}TO$I"-Auݖɐpb`j:o6i~lΆ7Ξeڕ0ZO[h9s%˧뗘ro-?G)DN?.0r7~tiNwcW;xxQtuehfB[s x򓋫g+Shm\>.󄓂ykJ /?H>|7nPG/.<ڙ`$m.'$}=Yo%XSG͆'Lр Nu/[}iʐ0z; O{鴇<43]bw߿T)1͓mzye7^YStB+FBحecH&BM졯EP3ঘ(T(peXrztwŀ``fu6E[`xwز>.kx{sCd[[UCVpDD wդ'jg}}*u2q֡hi&@xkwұȮ5 Sn\!h,<5+br1djlK΄Q1lGSpՕ A)e G)#%FY Gnޑ"{^(z`h/T}uz jHawaVcɊ!͏?'XO*#KۦsHcʲ*ԗFX:͡#Ar(8P[JU#SSDĆx\Q.}ܣ/@偼F<S" ̋&$$ `Qt$$YgW![&Dh 1\@D DS#l\<%PocjCƈ`)l[!wOw`u %h no1fjIvQR>x30+@&Of!]BiS<_Z_\_x ״9\Z5qx a}R ̖L,p^mrҞi V]p<~X6bM3RPj; J-4{J|< FfvARG ˀ8ɘ\~k]2P[S/CT4pVzWHi!]0BM"AL> e%N:gfIJ_!Àq@)5l,Pf^#!7Myîv#2#INYvjTv-Bid\-J' &ҘiX綬"}FvL!)<$5avHfֈU-`!7JŪT-eΐ!62ȎYk;_ށLtj d" cNWK`FV1PPZPRpʔFT\35 LkK) d?ثFꤤkц0W Ζ(<e'yw~쯼C͹X33ra=7KU_?ׯfpԯnR Ǣ/sK>e}8~ݿ'{]$1 err5kG.h{9=ߵBe~~_|+ݿ˟~|}y_.Mi~rG /?lo~wW>ݿgshFȒ~y*3v/[pT8O,GUwi)|gxX޽/wqz7>iaFTΠGTGµa r$C@@93Es4x"h`=4C7n|pg;V7wCܮ6eN4$ԼP{  py}X<qjAGw (cXVr5ؾ|Rr)&uTsN}i=fzؗsIaFPo@-=S*'@ڬnTݚĖdq4̋b g+AyuDeqJ4hkɓ,v@PO&}!&H9"CG=2 (q*)%E@h^z3 D8c/ B ; ,G3r& qz"\K@q`х3D f p+:saC%Gh @_#,3Yu@WP/G4ľF20g@`S Pq$KW(Ԩd jFK8= ^-Bncn-@1ּ:q@" qAaq>%pJ֭dE%t;Apd "MmzaE){iv( XBO$ݛ׫^xB3\q.l_7s.6c󜉢-hi\6=Oď ^_}wH"۹>GO?(w_rOg?>7A{X'׈b<4ˬO_zJRvpQX:%O6u[׫([IBl A%1vM=?K +t * 4l&#RʴٖkMœ}wvv?/'|a-8NV~fD+-.(A&:l##9G)DNals]|z|>Q/+hs{zi꣫):lDŽjo;5_DqHkJi+Ly) gl~s_wC:i{<䨽8Un+{kl1ʑYX&%]]CRæl  f Bhuv)JNkdM !M}$h@1@Ԁ 7=3.,[O( < rcP̀R2=/RوQCL7^DHڝ}F=hM0d 1:g XDsxsj#72s0ج]֎a'sp5ns71S #p*&Y+x‘#HK 97IP$Ĵ\2ډ0xb@!$Ha %ۢFtm}=лb@Ւ09=4RQlD+7{^.aV}zdOۼ:@ZYI3F3cŨh-.SNxzs?ndSRA4lӶ ^{Dq"<6L(fp@k ~ 1V;J5"U^|Xwߟ_77N@._^i㱉AA7S„Xk)(XM">zvg-Pu\OZ=,4R:b/.O9Ћ]M3Ews#fªizm?},3Į v[vrm3 I4nXDZafeZASA$(C dy+[7L !F'0d ؄ê{4V :;"""DP1ٰ0{ՠdfRV4"S0* {8G{ J(=R5Dx8vj)! h$Sz&R qQH64N93bIDAT llB` ,ʅX `& zpD5*(^":[l !P.́0𘐵0 Vs2黎B0̑@`1&&A8j!~) t֜upK7NVvNlY4:3@|><^=9~|uy6>G;]WUw}{lNgӘ˫!O W^X~?nnn_o6S٧r4>,Ǿ:7ke)<n0;l E<>0].<Ɂvcm^%:/d@.Ľw*ps)S",ISp%@̅p F@HAr~1yZ@)2 $Wj;S70׵ 긜ƠWe[D " d` rp@bA a聀WfΞ0So0%jH. 0'@ ep ٱb" ^̓C;9m˗:>yR}ecKW]\fjv"QQz>xt?wa)y;q|dzԎ7z)v2^ϧMwzx#/<^}}( N%W盷B6am}- "_V¾z $,#v#Vk<׆|ntd@./~Gשwol#cdfnϾU. KJ#3Lr߽GN,Dkoa9pZuu9wǩc}ww7P2v|76cxZbze3n̆,Cl`=}FSF?f,CQ$DHʄ)U9oon q.]l4tEr,cNr{=p{eT^]>qs` Ǹ9^|1T[SaiZSP)3 Gh<7S7&A=2Y t XY3pb; yJ SE˴'2"c" EHd)sRPp$fAN]!"GGҪcp V@ "> `Hn #0u с`u0*W #0ڇB4  FDELHܼ ԳpPPF@%Y0 I!$scaapS&eDXP2Mφkk[48׀8y4@pOq]iB0 ]ɻJc{zr }RNhI?}9.1x`eߌ͞f"1Օi|~(r3{I[;[5x3кr=>ϾHGm=zsS]nKקȉӰvy]Qd'G)B@k_pS/.VRK'ꟽ\nxJotuac @4!+txd _/oo/kq`:/}^l;д!XmhN mqfYW-m-\`J?Pܘ:.ȃіs]N3EHlbۮbYO7n~r?8ؗx{9ܵk$` E֨݊^04&f-4V4nwIsp0>{ D=3!k֝$\y}\SxC}0Jhs@WPi%kH=IiU$0ø0"JVSCA]!%<\6 { %D—$wv6/N.lD.3М& _m%ѭzڠUA"}g" f`KUIɫEv$ `+1 bEA pQk87 l@轅Kz[{"`A `P]sV9e$ [^HX<4C(L`(% 98w <( 05# d1d a$ǧ18ɳoN;Ͼ\*}@SˀB 0p.,gkȜ,┘,G9>k2d_4ęb֢Ѻv\8(ܝo^׾_}W;=&?~4@,7ՓݗMPՂ)]l29ZL8_8@D Fΐwݝ6wDDؼ#ܪYArx~m5pw,d|SR-zd%8 yGP`ClC (eH5o嘐j0AHFh7j!KXŮ0Cr@խNM'd(){$s4Odh>G&RHAF(N]mZF5-C]-Iv= F$$N#Y#!X,TZ{j.Ebf,Ln <{!kJCj uu"2⢦Ecɭ[)sEC(fzHZʎ4f[<`=kUT|Pew ,[؅E7- $`欜 Pn>a: 4BT 8:5T3Plipzj{q/zט-@4TJbq6 p]c8@Gf "YgZEz6bKz Ttc$%lkl`t#ٖwE)5h$|XZvkvSh _~7~8v/5PGO>˷/8ryM=_p#'2y{+j\>߶g^^\y*JCE?n\ Xx mpHs[ML;=Ne< (&b?4bk嫿lo!".k Htfm؛tJ&Ie뛁'}T#||ט.nxE<͛,q%c3ZLWҫokaF_>4vq͟oӫ29`s,T@BN#U]HaH44a"0Je`́\hpp*^޼0`Mwx:|׷^ѠbԘ]{QMQiK)wD?5Yc8sIتȳkR.=SkR6R'pJz?e*aHEk TN!̭wI:5z`< T4'A0UM`o,L) "eOnD~ <-KZ̲dn(gIP[Ȼbo’Jo=NʒKwьr b =Z j% s)j(J=VHh^SS N54Whv`pT+G<{VFĨ"cQxK,uT@DC7ܜA873OK1!`;Km%؀݃9QG7]Vzяj 2_T(R;w0|h$%vU, %ɂ3x*=˄RvnJ>yf7l|i.\M]&f&;!]&H-y-`>}~Xv~[/;vq% ,EO>xr=&r)~7]=>y?|V\l7o&AOБi%kݷW~x0ڪDP 7PHn-BO도"hq~:Dx[¡<_WϿx'́uCRy8%5Go@)Jc7/D)dKwGӹWnz߭)ɱB Z k!d_R'0uzah/>= t+ !שc8']%CT0K1@(KF R_{;/8?wwwKtsw!D !8!U˴ riUڻۘe58E_ZZg`rt#6Vq_.oޟ2yr$H҆`CZU(#3[XgX^ )6=ލ i aA_Y8%80 0t\-$dJH~P_kPI4.bW܇1xL69[ԼGffNYcY$hdBkH е&0f1- pe"$_ @QOr`pv 4vǰHEJw/rv1 I!hi )0I9!ZxpɰG9aF\1 5vGs{+g*0nߤx8nyCސwּxOi-Gq" ӻ ?ȷ޾~co5_|~0.>O2n]N\^Xe^3)IQ j]Tf՛/]~?{%)#T,`BA`^_)]o?O?𿙾o~;;uLՇֶ5H ѴMi}}>xU]x_l͓]588k" FR67Fdc_񏏇$tE St?`hZ*BW$4 %y@Iy~Xx\ϯ@Jxvb7^?%OEixP##]^BaS~蝕}cHPYZFȐ@i3~&y9p%NxΪZ6`kða*KL`{'so #(&M[M"cғ( Q>Zi7Vdi0BD.>hh)pfdXځ%Xsz9CN/O,S 1TP`2:棏w]>htOv8? c #{pBPRzyYzkW=OQ} ۷~> f \?/x?wm?/'WWPh}eei#yֶ|7lׄ>FDo_|<˻ij3CX.ۡCSӏ߽xQ*iWWբ j&4k@_|?b||_a|hk Q n}"ƔX:Cu:xw?{lSY{tU9Xr%`v*ዣɒ4elZvW?D|r3>[]ڵȯ=늾~D^cNjs(CxDf0$JOP&j5 p@ mcY+8@?ˆg^w~䵷9hd:v\JźIrBjwPrWUMz2`GVkaƙ)qjwNJ8E?/.>S|F:DJJd#b(We]̻3f=SL8d@T3\:[B#E"!N= uf@"02dnj #jDAj$N%sL8Zvxz1cJv^WB8JBLE ; B1G*f}V J=>eYWsrٻl g USWC0:k X %Xi-#B˚&/ :{^э yS `fcK6pb#Ɇ & K$n" axB7V H :ct0zճ۩ջaS)=tĄ!IKA*3:TwK Bp `/J/w}Zgw?yu٦eC2Q;WLe/_z:J:ϵ{uu ]WYXvVX{dHf10D}z1z{X/F O߼>i&˼<q8Oe4+ KC kkk}co #f(cL|`PLhi49=foUm#rf$"$EHO21!΁f"DR"1CAAѶvyZ1_ȃ;\(ZCBh kC3ָw]Vn"r;n=#~:廟}A}97WoQ߮o{}8/vFWEӋ_?'~yɣzyǿ{x}^nDf%L7oU[#p;+:0Zk-G]8qy7w/Xʡ; 5E$.xv~ǗWώ: P-?`7>,ߢ֕ i0?QS#LF@(DjȚ"4oy6A@2q?ςIE@;0:GkڀeA>џ>~GO{}^lQaӇRj`j,{!6mA:]<Vluгg$c6F^QF w( ]/<|_OVgHZ"hz??n6|xϦ=յjL!L!m6ZsT#z(C9i Rz5Wۓ nJ:r)1h E\ms)Sa{Dz()n}mm<|O.?޾zy{RO:F|7?}u7M#!)n=e> |WǷ{OK_Oo0ͪs8 YhwK^d.'ˏ7EZ1}vniv'pFM c! )D-dt@Њ'oߦ+C^Jmg_Ϸ >NvHC :j=ߟ+^|wC/J`0鎧ul%_0{}'2N_,p9bJڙȳB_yH.Dӈ\`5v:/ *A/GӊHfa8m*/sG7maݝK]W).kޥy `-ѻiB*^8E 3 bݲqE_$l~yz]0jL3ac͉R첏!I90bŋ rgVh7LC=8Le#(aB?a,V"[`A2v&8Tb4@ jhCw@g *6㖴b֥+P kHłDTEKAL`ÎO /JHhPW'Ό[ؼiEW vjdYuf`BmqZYUk襇 TZruf9WqT - &!E' VSvƷ{ 5kws[6TkƏQ@\V}ac#@&6{fdH0[UGJRP6ZLEat-)IDUJM-ZC˩r3Rs!vxksrb?)Zl;L&?\'/} ^|sut_ׇ:z0uA( yL[` ,]b/Y@s iߠ:b`b,ui)r*Woo;i\qL:?4vHzCkL"qľ8Hêܓq%k~i/ ~?}F|pLLcsP00,2쩾.T^7nk 7YtEL2H@x?`NM)^/6}{~wg &m}Vo}DFlO@?2o~~qv>üD؂BPD\]/'rhAq #!B=?_ܗH`}e@P_:D(#f<5Ɗ;8jdvTĘngPߩ9֔ZQE<mozYǫM{8l6|P% H*ֻ@l8yr ^kh\s$D<Ę1߻?Wk Hw6|GtuC21Lfi|;x{t,ޞj_~/0.]csᣫ>l{w!A6ZwQCɗm{y<e!yʸVH>EafG'Z[AD϶?x<|ٍ7T|~l}̰e! ?yr}FIyI6P*"]߼ֳXW]{So'@@f;wC7=noun=KMpү.w7&HϞѬ; = ̻10}=azim}ۻ͋vr'8},}D)IxPczbd'Ef#x eT74 hQ#>g@1(!E qÉFvv;vRQ2z0 ѝ;e1+@vug(4p,+"k֛V  6(at$QSQYP/NhTAٔySuU8t5+]mue fdVsDfC6z8 l)0:/$f t@\܀$Hg[8hFN0Ԋ&l@HU0W-^Ԍ:Ic :Ҋ]U4 hY)7&R!rqޖL { cDkTܾ:yn<Ջ\:>.{zw3+ga5Ar8wK8D:mi>G?ϯޝ,iZh{Gaݫ6SSOB4;־.$wÓnxW^- mY;:;" Ifh]P }9_|?:[='|h eV4ѵteB_μ %GiJuy'u:/'|l_^4׻5rb0(eja`Ֆ@Yr*rt5 ߚSՇxS__loZtd'8yykWg{d@q!ODh/g>}wyԶz9= :OBY%W͚NS Ȟ8wSz^Z5o1狛 8S4 tnõlM9ه vژ7 ꃭFɦsu9V0C`u-N1bXZl P@D )n grȲi#IdH'7כiz0MW޸A(y? ͛3Ӱֵz0a˯~47)R8֋YŵyBZRbEB'fnÚlrۻ_LOvb36%ގCqӀ!`VVx//H!Lb.J:B;SXտ]\kS8z]z:Mۛ|˗b ;,{a~ͳǻ! ) P+<\ln=/|].ݠ0^FM(tDqW)Zb"{Laxy<8M[e*]CkER|nYКsy-X5Tͻ7 k[rZzΝQ8a 63fL0q1Lj/f2šf&~{IŦKXT'4u!Z~LeS&Yot)L%jA2*ق@L{@kVH^JakdSεBè΄Q}N*Jꑰ΂2wv,xC>[ġF th#;8זh=vQQ䱬k5J 1b'Pk %VYdK|h%v;7ؑ4f_ GJ!n2b j8"" lƦ$kI1HZypG1V6K9km*R7DrimBF 3Yu<2=7tf6\B;:̆7'ܜޏFh!\GtGa1E\e L XZb$$YbbYRVXPr<ַo&Sz2Ej^ҹՃp\u>w?~N?jW73|OJw_bY*Teq$}6'!Dl{ Rp\xhd3n`@>Ig۩> bq70а]Ҥ{ۦ fNC6{D9X,&έ^Ûwl=/'`+Bh6G yB lEw w\ 0~^lgjz4?}d~iovv![7B] ;@›o|]8 ,|so|ߴճ]ox{{]7߾~"{ͳ>f읈PYwZ;g91Ǒn\pq9g 3%ip=rdAr Zg:Wϣӎk 0k]|n}E_SBo_9M1Da\_ǃE'?n Fͩh}ʾ[' FlVsB:`6[gHlas j+[Uً +{DHéU%™M@Z87PY(AZM.HXVmfCZ B/rCM1zD`L׊h# 1d#vTlmd,NdPqYj)rpJQSޑ)v 41[CQ:I 5#V"kn5LaxEjawc$֫[S%3c)}4cvm`YٰvEɅ16!ob10  -3!E?auu:e,b: z CB0fkaB+q>tP¥R "o'S&?4MYZHS%Ũ݈"q=8v澭qWnP׹p/A;ч9 X.}xyy>x8!:ݯcXnh}tR݆<ź0$͸>y,px}$??ynCŤJ:X?{Jpu:^oB4+:b y& BFGPFJȋ[cK=eZ\Jq;>zS|3-oڗ/si0ǗOan];SZ7v gVhpGGl ]6aK>j*B=ġ"OP\B&ZMݡq2E'`@12!U>J``^eC qD1*N*f4Tgsncq>콅"$مz;8:IJ ]ы`6AJ 5&S2CĿy V ՌְRMU&RJ-(YCqx`$apqWFWwh,I0FZeKgcf{#c-l-L+0 JfGj(nU5n1>5J)n{ńi3{kr ss1ZJKc jI1bBUA[2z!-Xb{bHشӿzx拧6ߝOb4|3x"<~1oź}A1-zCzbz‡|bJِF;>Fasq{7yFfWdְlv72#t?.t8!\ߝ^. 2 R)M՘ZiW;9z!vTD*yZy=-MA%cא)$36Vs?⺬ ?|K<݈=0cR7E K Hb$poM[ ~?|o` 1NAձ8l0> _n5WG(ӓp9m& hDeΗ~zɓgQXvvExp\}wje kOūp]]␙C$M贂(x(]E4P!f~Őݡ 98<{t}裼jݡ[HX¾ KlXd0 jA#˾ x :xk TsSMV"7$`HLiQh,/˥*Z 0QB+qB_8EUdncUB8y kAhBǨCdh=`m̅JuB *}%!u;^Vl: S@Q{y,#G I ęA@TtjSܠ8!j #Z/hABӦn~fֹG`ś8 G"Cs(b:X'uAqv]}(^^W;~"U D^G #LG QмJ"YN%LrsɩK]\y{}{!.?0?tm}h=1ᣐ'~3//ߴw~y1,GlKuqI[$ {WOӧTx{x|>~y/bͅܤAD_2>VWI;x<汽|\]Zqw~:ZUt=qŊwc;B/ rVkN4Q<wŚv 1b؊1/o?t{Oof.w\cf,/(l"QglVWɿ?$c4ɚo188R]81_9Q=W=znNãkc\l,VA`&Q r 0yS^}.Cs&M|DXB= {"P3 %V@|^;HYlx9^?۞vXOc/.㣧c^N BchԐC]M9r^hڢ54F#5]ÀXXuJ(EF rf㐵Irzt< s4 -hk-X "+aTҋpY.6 +}}k4cHK_{ mu`My aSIKco%- jQlC2bADqG Df$CUtԵ1/R k< Bӳk3U4`9;egQa$ިoN6  aUHZ1T|p rVώ[ȣzr.+:.ϫdOj͎6NB:!x/m+{Z޼/^kPdm("`⫻_?Nۍ\.ߥ6;{^'9ͻ߾/_oOx^޽Oyu.g0|G,mH}绯A|s W?o>z-?z OAd}@q+Λ.pzyɬ^YhC`$/ sצ4ͺD$qxӹ[2ze7lۯ_ 擠p~w߻mXo"6|*lN! K{ ȁ]MՇow30IX@:8qa` ;i,_Ϸ>q'љ_[><[}sg=4i'9kui -dZ ]@Д܀b=8C%ĭ "6 Wt 0lv~>Wm8֮n"]?$+ 2Y8L'҉}>7{-}[P)m]Z+Yv6mz* ! e2u3 @X=^_7˘__nyxz}NC©Ib[88R Ȭa Æ_^ v4!u,Z0{@;ueeQd]#X#t"l4pXD1nhIs3*r$Q ,Qzi(QXn] Ь㮷lxlGE4޹jA$%0lڋ u\U2ۀ=N;rN_8o㼞A|Y4nvaiWj/ȒyzO nV2{y S}."^~݆_Xݑz5` =ČA_KTvYI틇puMAj$ݛs/>.v/ i"aQp{0(@70_/WRd#: 3AL[:3GWʲG2".퇤5I 4'} =!挘lӥ708}?[76|u aKƹ.۪ x;h^,WtRA@`k/ uؓƠWrcWf32,4}-@ZdV&B2h<[i@SͥգHF,<8p٧ ,4 }ūW.earAR7}vs}Yp?~X<}-16zwx=oi%>kDi=h?wv ېr՗ϟ˽*^>o;HSiK#BWq7@M6N5@*6SBnS['Ϟp|*-kq˟sVxY5xZ&Fst,Kת ɐJjWbtQW<ӏs״޻84M{p@[fxLFd<Ԏw/bL,#!^2#@dl,nNF  E=If,%ʐaFksp w_b᧗HLf'mezoDF[' ,C0-4(Eq)/-3taڹ^ FS\\6`sj6X{d=.{84|>xJ#3 kAjܻ3Zz@c&ȁ ώCτC֮u f@vTiuA|j뉫wT jf{6ؖK 67@"7`nzw?_l}̻ =o1@!s7# VkS؇LRWg8xsa:N86mo͛/`;<oonuЗ;sY HpIņ ʀuN]\/@,mgh} JZV,\ozgջl@_]nF7xen刷0toT-ؒq'aLda/b"VحW0 v)n0Xzx0w^Dr@y)ޟJ` /0L˅wyk3JA. Y#F2ŠDM)Qk[XQ\%56iutB7Ml;p_u=[蠴s@"taMjA"y+hʠigN޺*YTtEHՒTPݑ%K% 1mey)2gf BƔψ xhElUbwXXL. {Hq ;@/IVE?tdnTŽ9SAP,X( sQ{3!R\ek4X}ؕvZ"]y_Ec예&^t &pz{}$v !\Ͼsu޳kyW76kR+5s^.>׷˯owt& ϭ.n7mb|]՟'ŷ?wo_8{P6O|_u84`CZP?Uz:׬|U{xg d/^o6W,Vw_]|4w|\]+sĺbPsU造%0R٢L>5b X+F!"~}϶8c޻L?@ʹ%3H@W;cWгǗ (H8*4 ;6t%4T(ZC2ptay귈ԋWosc{omǦm;˧Rn)\_QxڊT`/O}bBkI-A5H[*stI}'vn` LR(aW;E(I*v h6(,tG۔$G y>,=a.vaRztVa2C<{[lS,h$$"$iVW Ї81i#{w7AJ!&ĈcJ$B*vШ]{$3.>BJc`=89 LN01w8@$PmTTD7HH{ 3[h `[o( M8RGv;»!LD0Tn@:m]Xgkg,ͻ \B=jT"/s<0МXc[DC#Jdpe 8d0`u@[3* xC+Zk+8gN)Ҙt5I9:9x݀]%AVMBomKe>N^nfA^꩟+G?n-uzɏӏ^H 4"ki˸}yn u\ǷևqBD6!Rx`{O/>x:\N٧ϟֈ S@.WO?Y:`DD&]: U[i X\XsGSch{Gӏ>δnm {;O}y_=q 8GN2* ?ռ ۸6}0b-;pP 01DL (, ^#aאW!=($q,*LJ4C!ū+w38$7[ .ګB=t9`@3J-KY*HiBp7C!9{JuuZ#ùb2#O&))k볧Hfh}BgEږemX@_ 8Ɖv/G ]i&ě-ɧ)K]~pq#p^ ph.e.i S_Y9m &g~c#I`NSVdWB!`z'D *bB]ю vgqGr @+Yg͠cHU$s Q]I{9i73\Vܣ{stj4ԀZ#=$l8' [cJv7s}x:5]> )˧Uև/?My3m.ݐpCu \U;ڷyw^15gRH8`Y P0X̝4:׃Pf'/q;dC +Ʌ`Eh,QA/_ mlwadzSB@g1@C0 ΨF J3rr//`^Z}JfN٬h9[K0?tSaȈ+ɻBU N dA{`BTWX3{Mk#Ί]zohpc J|˴ ɮ^=w/S}uośAǶV ,9_l"_?O~~87,/Ox7?w>ֈk}|(:E+_}A̾^?9<^덖r| ]|vO>yZs ׳!^<;Z5 ytrN!MDu=--P`A}g'cX^^VG̛a5,+mHHSk}y9 YHg喀#Ђ4b|Ŭ;;7؋0thQ\AN4^,foL$ʈWqC p (mcZu{`(9P  @{*)Bcv%j3uDm@ug04pC7c dj,zhkMx7yUOv1lz'ab͸+yb u&gA @뛗zIm$U5 舃xw?_=2JM@??y^ʃlhx8u;(C҉iFpDFZS(7D5<ƧKXu--jXE%s5:;Z"OꝴS`W*4xi#^T19!uG @W$@1 ;! e l$zD;m xojàM#\\$I}R2;Ł28*29"FB`0C 3OXHr n֛P,28rA{Uhk`48NAb@0p ZA0('*`)*TM*|L*  "UnmYɝ a/9?8^1aNu>KU)nWy)`]>z]5x_ZABko]>]Wmp>N/E^.na 8)xbVPC֥rvkԭvJļt ~%bc#ڴ3X#@ѽ&7vԃh=9dW5b@@&ɬ66iz"b`ɠ1`@5rJ$n!=j|X8Q9^ҡpӨum/J<z,Ivy׿ƔW2\󻺞qX_~~~}(5[Rf- ǺY%T?<]&tr8Ox.$.GO~ׇoʰKW=(\\_\mUϿXq;w &q.\*) 2M.nrU +*n+ӧWG=y/~iN?}@=yڄ13Vow}m苇z/ΤcЂHf!og{y}{w(CuX\ λͰ;m#a;)WfǗtaPJs]?Iz0?Ka\ZOӛv?6@5f7m˛9Ϯ7o8J?h~$׿[|rrXt4SUFWpќ%[#bHd[zvPD0m{?^^;vۛ|qtZv(/$4Lk}?nCCh  ʬ! 6LA1JdDw;PH0'Zx"LNhyjsqECuYLiιzjYf:nYu?gЁaÆe@A- nL *Vڵ<+9G柘cL׸/SЖ@ e68%#3qK3Ӟ8! BFSDvKCxq888! 3qR1<,b 5RE9vD]u-MR/a3t;~߸o0leG@S(VJKZmD1Vm #nk;D_gք3aRr&@ >d#>7;zjէ_0Zۂ+2ŷ߷x]RJʧR|!OV)S߬{\~IyPZjwWƇ{}o_ ~R~+ `7coW#ѳ/?7?_!vLG˛t}+x,q$@[wR3EvejJCy>_Br:ݦ/pه+Y vEjwZ)eRqM)K!(DUib5bS$g ,هL% 52U93 ЄXYFpŌD{-CeE:(bXQu%Ǔ>!`qJd 2ClqC# WfMî-\1wh"^!sfؼC_;xrݔ r ]C[6ǀpɮcEitA.<]Hq|┪E"p'팮H`tu, H!^wIDAT06OXc4 :nySh^1r1e5d.H o5ۭjy;ϟ͛ŷWe?&,ԷWpت}:rq8|wkAR.f'?8/ФO~=˻qhhe?FY/G?79 T~r8_nW?~Zvl{LRԶsk* D` @MnUѳF|L. @ƺagw!2e6'DJD5dHSp@ Cpq˅!=bd] c( T=勐&j0('L}iPy2W"%x@mU^YtI` Ӟw(Ċ@LLCWR+ )0tA S]aڣ%lO{3M0ֵȝ=IP/Gsf)05@3u0C< 4t:N>#: d,kLꍀ \m9dFp,‘ Z #w P#TvT/X߀L+j&ENJCƠ0Ĕ1 ]$bBz9 dv9P* 5,o*a=o 8Qp6,̃`Hh] %cXQt<8< IX`2\`b?;dd]I_Vˆgp27B4C" 3SR"j2x -PZ<雱67:;S[xHH)!i,R+[7Bœx嬡c¼:*7D ;A]* N8 ANcbfd:kK[ʮ8|8{OW0ju 7{tGe><}}з2 mn*ʴi;':GהfzpekrD{ucyr#?LW2wX}~跙؀B_͟_^atw%N՟IM8 ;1b9''5!DEiwL HCFie|ǟ{̖r|;7񛿆g+$rfɣO~ܦL9Lҝ&O1&FDJɗ F,ɂ̓9EhsA_azFܝA#>$'} AwIG) JSFNd)Z[HBo@  B/8kb\'և!ΏF>L @ԉ2XGy3Pxu b$d;SP94B.ti#q@,r$ l~A9D{ޝP?c3"M7LeFMQc `lzS "djtrpGbrEOF.i!cfm f" V C=rKuԥ #&!mFD+9:P'5@ʍL&JC1 QFBDQpuHhؠ͎إv ќ.; @BZ]Ջ#-Չd0(!f@NȴoXCE7!%]N} )` 6p$/"x1ch ;5°1B-H,k%C lfi D:]W]!- I"ᇒ6cW:n:>?'uzaݗ{OOw7;;~ytN8pHjqizr{8j7YaIM'WG?.fzFzȠm8/NyX2z#`@a?ɐdo=۫[}翺a Ӌ~ES4:leǜ4EYO_vc.(Pi͘V/BZ&T&.)a}"00hcS-p L=<J.MiE[(.3`t b _.`@%|ɾ "!Vǘ{qEB~ŽаC|LE)@,ё$R#qH50٪jAzm&mÄQ@QrV&Z`)cmzWF7,8]c'mq=UqZ%%(`m׮ܜZ 8B tl (('ؑcmØFq0 3fڠ)”y.AGgж0tH!Gx1H[[EX"V`#BEL0qqqD`^`+-b8Uxnny9Oy?0Be6'umR_͜_~r[5EXnyF0PskM%#%z!rjw̍Hc3Ty؄2@'d|`"\G "#2u 9P? }Y 䀎Mc8S#Qxo-1EPt݀R:f=0bH0P`7 kXQU[}̼:K{f4BCJ0gboK1DEhnF X棴JR8Arچ#* %Ak̒6vH{T5sN}1@Zz>@4b8A{+6z klUh{D.Y t ĥ6)NHjAN8jB 1O*-:@aKPvhJ:tߥ2kGn5oB'h1XSCGDMVApQCS!JdF-]%Ebq|)!ea?1FҞ}8DN`464qr3.D9{8"ƃ$NAOn}X72t†.(cBکkP`aj o4>J` ci~1'3H@o^{|a^ɼy2M[-WUݼLd6x}9'SnҞ|5]}io>8(+cIUMr#Xlgz=~(9/*, mLTK$L@9ijQ l1Uࣃqcϩ8 >,>+,%5*g1{4My4Fd1tƱ 0^}WphxF;ЈoɗtL&- JR-<8@JYs(9zX!ÆmtW&=[6 f2qtL^ ^ < =qrou@cg3FkL !.djAj<VX=0Qa(h=5(r͏g5*j#3HO?H/@R{_su6y <=6ۄW+y@_*9a7{XnkĞnJuxt*+${KuC`>8rG87ɸk9K,ԡ@DQa Zsh㌭DZ|ʂSֵ̀6,K칷MTi*0,!LR[&1mhkb^yq:Ã3EHhj*c9 5 #ppv %Q<l.c Fd$  xF0fOݙL(o8# & jOဥ3\R&#Yd.5-T#,Yh@&glQVT68z7H܃#djCZ݉N?HR{K;ײ`8/r}xO/>kKdWoz$iŒqvyw׎vZM(tͷ߮oT/o~o^9#f), #3):! O^?~w~Dݗ4>}O_wo-ʎOTBj* ġB>gZC[o @=v5Ơ34~\O/Z2qO}|ǂ B\rx?˯Z t 7)m ;SHbN(v#̻zHSrBt4WJA!I{dZ@B0z  8JPsP`(=:ȈvܣUG IԯLFg4*@9宁Tmأ-@2>:x0B"y n+w hЙ0,a7ܠ6e kd'Ceb)m M#*)]e uޣU,2qE"^7].n ]1#x=Pvd50#]z@v`#RBu KbH}˂DSNBR.P՝i'f.R!)neT2 ND cC7$ wD;Ct i#APE!k+F ljl b UkqUDUmѬ $F 1@\ )@s0Or[&f.#G1IݤOD}7Ljea dА] bC`C LsѮ%~晑qHn ^vp|ڻnGOSKWP.=^o>z7U͓?"߈zmo>Sx|/vC)WWWOr}7馠DSB5jAe)y|Y8j.}y{i3s_~o)X^dw$o.#"p΂^5PJa\S|,,i 6=pD2AiL/^j<3$BIy+$3d!FHɝx U98hmLaC9!48Kȴ3ɱghhkp- 27/tn-qTJǜ wUa -h"X7,q @i$?&R+Mx3,#o،Ybe}0c~Hod{E]n^W]T7닣0v,+1v~͔n90um)1má`a_}~6W- `2u)l[)2`,2 !w1wA;#$q&$}4sIfF {A [V@~0/^/g9>1းuk y!r_Ģms<{c2Շ7o9t?-?fO!•t(ObBk>YdzM F*$%i\8mm "D{@˒ץaӳEn_ gc7e$l{|lRȘlp.%!E2 h)\ s8Jut"`pNNz D aI d7$i`. pt`)Q.s2`m du!BA6 Z:c`KUu 1Zʺi H̀P U Da&`1hl{w _1QXW'yy F];P~So]R¹Q:q떶=Oop*m RVq֥98eoݖda"m {#xp 훱bkq֦ C2A> 1)A`}u/J〠-_=ضD;+LDXt)M٩a|h֡~`G";c1 @XÀ}AVqu:" Ţ@Ps`DL@@x! C8p PO=GfТݐk'ѵvG͙4`!,=2mb'%R19^|B1<1RŃk&HZ)"3S9ǔKD2ypuZ4 1>?gDrhl5%pk7՗\%pH{70r}㌸yw˼@,m8 2잜N'xZIRwl/vȿھz/W/zsI- "ǮG"I `ޖ|_^_?뀺fi >CAe$ZsDl%zW}N) rm漓ްDE;7JLq={߾y^j8b'mklp|>?A.[~ӋTh~nDx<˥14Mųr}/ՕP*OvwWj;q>Pk^3Hµ Q00du˻AnbI@'֋ñ.)ștӨL RWd])2R\η/;_p)ts7n֝\`438P2{o=o۫0G>*0ӔIhدoo~㲭d~8L%,‚ c965@Bb"^@U12L}CpH`A8꺄H52[cqp>W|$tlt/}:qWOxK׾+{p,УCo$41;syˍē{ח˳2%>88dL )_M#AJ81C(Qli [z TܺBo "jȍCƦlt pF: DH Ck4jeºp,Aa;8 . 0jBbX6LXwP`y'h۠xw-6nNLYJX̑xKH! %c:Ҷ mm֌ìsb!䈮P,X38BofjaЙ@*] CӶe;I0LEj'9G)^kv dd#\[\FS&Kb*A5=Ȃ7FЦرO[YRX-(@隑2_k !$M;`)<r2!s`F Zessw 3f  @AЂH0dJD Y.Y4Aȿ700 7ByВ.u&ru1ME,˹F"a䖲1 vfRnԪMM0zx5P4@Ѱܢ6ĞWťvaN [q'qVޚꙆ@ۈ)y7ݣqǺbpAo= uG?N\KGzɯ/}9郧>~n[ebOQty8{bNOm0v'J?}`\޾ݶHMxvKFj@1z^P!T>UqSN<̱N5/kr]#}s{-g8-<lQ;) m #POgf[sl<9-ЯӎSo@ͻ_o~u2 cp?$wD-HFރS88xT~cF ֘-Ԣ=yD]07^pV\=eDFhC 2lc1ra;Qw+^+5:Mv`ih>| Q7@󮑈@A8D;st3pBw@t:M Pa 6W-( 5("Dή Ymޫ5ֶ,J(ҍȅ!AH"&h)W*i䒽Ďx Fh;5kzĉb}0 bhuk}!nk4P!+ f@"$=E\>iHRxM1C„04+8CuIH:`B&cK@U4ESlJ?w:j/)mes1I0+Rp B0=Qel+""$;@aDDL#)b#ČB) v =2MC\`PX]kǝ#a;i9C`T{NB  Zyur8yuVM2zrQw2ŔQi}"S)˺\zAwRN>g~pֿ/}oH7_Ѷ#NyxO/a[/⋟}RU:tsI7x fmϿ8ݯp~(Ɗ22P"{@$S ;X[ ՊHu|Y1#3T߻7G_(1M7I>zq'H[_[[c qᗇK9>M'7/BݽX,"ﯶß_ȩ&"wsV`7d0Hi"(a] @63#"R,)ehh"` OELojlЪ zgtHCmYd{0bA1[`o!jɺB!_GΞ3VSP3rwႤe4т/ٶKPep.iW*AӢ!64H℈g(c 9r7 L)XsߓhZ浻n4y]WKcPȉ\C8[X]`,ZNmjrs;\KxtNѿz JC!C< 'I&#.Ɯx+F4 `)#2FN=C U"ᶅg@#%p1[ugO?޷/N|/,XzHW?7__.woL7MJyVWv CD¡iv4kK_x*LLFFxϮ#OCFWL`T A2.0B"uK.ohC9%1C@Ws>b3R4 |vܗW( '< wQ40r G/7~n1+EKl\FڡWs/ lCg(1Cƭ-\p 04 uG!HCRM⎈foAK@}ņ+҅U>(9CeTQF"btXÉtEI.*pmxf(4Xź8fq Q{j;%CCr)Or Uԗ-P9@fUרkU0mfCb[`tp'Ji^8 +x7UMW l57$ڡӐ0`*=xC!20K~G^Gcu4@ao#(b(t0յ+@k(S.-51_uUئQV1zZ«2yRaHqFcT="hÈ+FP(y 4 $ Dh) #VpBA!`: HeD9d'j#*DmӶ) 4O DKg wL"0(6S1AyuBČ!c qA4vps5k }d_B %-; .;pf1 77xn[cQ0֜m Ұbф4kd0-o>ݗuS-,Mzo~(xuCSdRkD=~TnL/o?xTabJ苺Vp7_i8].p=y)}e# Z͖.u Z`yz\?;~O9u^ݫEKQ,Kz{_n1a;/gǫ_x|wirk7TqX;i ՝Q=4Sh#DEXx9K{íAcS #+:ZHL={hDvF-H{ЂH[s_*d<0F2x#2&R1"GN":rtq2E#cT:Ržغa !!DZi"$10CP yG8z8{E-N= C` `| IQ1h" @L1I&B0(4$o@jRUh{WGʹ99ff# 2qFBrأ`GDQ "C2DNlМ֡VÉuE`3k._{yjwp䄝ZsR=A Wu4e߮=W_?\雟?dyqx<Պ_拮v'?_yYOE'(;tYvS4>(w;eȄ( uR"qj]{ôUUIpׯ^-Rko5t*ARP C%Fz2sy~(>/}|mNխjcw!'ڏ0fr9g$Ev~OJ>.qX i].֫)G]gek4b$UV(C ńؼ"#NCd LL`b@(Q1\$$\<@b{#D[tIh ġnChE }P΀ +il̓ԭc7NL2S@(!G - B.3tDHʼ(D9 i%$d];D:&EMג$\umPJ)8H# !8ȡIlYc&;5*^7tN,Pxm-WWyd|mKO '1LL()Q.<%(=t7EǨ_sث_"1 AB NMUdYF8Oscm BW  #1;#{G/Kv/.Z(Xwf*n4(cځ3傤.`@2:EJ7Px XDC .N;E5B[Č!VD(BJ,0;G{r 8NRr(ai1_17 E7J@`  {QkDhL 5;$Gc`246aMz>8eDcJDK-jj4iN_nGu_}W?y6o?Qg?ߚ_'_/ڕ G[tϯ?W<}˔x돿{8췋ޚna793s4X:%EN#\XTkӸ: EABۤX;j0sTB'vS`vA52R14P / zǦ>?fVǨ7᪸B+CF<аvl Z OsF}[anQ7K0` L7ˬQy*F)i_:9cI7:c%[!lNEa ]#hFg0X/2d7== ʮ`l@Cddqg} ``ew1"wTf)k8D*ڼhQH %α\A2n p4¦`nN;8k{W haVR)e̒@E肂M(Gp֡# pAؑj%@1](P $HAǐbgBp$758N&b_qPcX#4 |zYÕ ڃ[H & DIɑ)b.AӎC!w&L=A@$L`~DŽ hB[bL&,:lD ćU(+pA2qg$劮GLg_Z/7ˬ 笼Axwuݫ şgj[iMC~O~ٻLo?uɜϦ+Ai7}z{:/ Pt>Fٛn}`~Iїeyq )-}c;Oy<;{OVkҘO~Wɓ+hQ <'6S^oo}py~`eGv>~Av}oƘ 7aCp!PwǴϰ!0e"L}XtV)])x}?7[FGJyJ-F0&yw+btEkq9#&ݦ І}+mkB֐0 "€9{ `EooErÅxv.DV#ydva`&ɉj 1LM );(#Bs ,Q$aɌDž@Z]G Kl+' AMM; )yH(>@xU- HǦŨ藷Sq=SxP(ult&)Q"a L+t%!01+O$ pp$Һ.[ 1 4RۂDW h9&9uf i43%Z@#XuIcԍ‚](5p:>P$e Ryec b ]J@ η$oF5H#vᤎf );(3IxgJҟ4풤3{D713+0@nZFw$Eo$Jꖵ%( 1PʬM ZXx}UXݱON7JX 3(A DC8O#ں"C!wn iW3s]c, F 5rh`R.S`:E$RƵ#b!l%X!H@9Ev:I, zPؓŅ%]_=ܣ~}z߼ñF%C4n.|t|wqMtyqSz/x 0/zRX9|~bal~x?՛4*1g`D7L>D6 ) \Oށy1G/\k}>',~2o_'Oe;-g]]4] x8?~nϟ>nњwfC{^?t Z_7d{mB(wwMT1D@rpphM,gN3C(u)Y0f B ϳZEt2S5AQ q,wUXcqG;/f2͏F̘H +dB)؍?}/^ѿ2}HV@.qe.^|Nhǵu{g)50l,'Xoׇ^Rﶟ>sE) UKK@@mY"Gٍ \~r5ܤa4b<] a74sO7Owq!>(_<|}2vcs=#Omo}q'Exݤ{#?w/\9Z:?baPs>hDתɻa9Pc d8<'ShКc1]IiiЏ8m%\<++PЮn1~A=@wL@&肰/QI<>L2L@4pU&NQFjI}Cù2N'I (G?kDGRJ )@N I* u f)!i P!Nu mfbUmJ 2i{F_g烚QDHԻWgS弽ܔmY 4m,,ʌi @v`DX"qBE%=#;B9un-zlE '!"Mڙ f "V5rW]-00 ZÑ"+:vtS4$ހAQC\p dwLn+xDF;I 1MT:D@nX9R"`40 ̑BBV `PS Fu ΤG_jݠRu"j5 {g`8f͊kذV "4AoROPd&KZhX۽~Ep>6[gyKx;9) eҀpͫϫcWmӛfJ鸕1&g;/Dmg es?|wmsaŃ_\&N{?w@` )00@7 oo{۫:`)EMK1gcᔜR2xmY $9p #  :; {S^#4 N209` À=\p"<.D eSGjű3U]™J&"%SsU!FR6)Ty-Ö;#܁<[C&BddMij@50ݛcڍpӫ1ZaJNؙzJ/봜 ԩ-˲oLdLT752$MAݍAanT#g5  !1}PƔ;RJ *o[0{S.So(.^'TtEdYAr #C"b1b4A P9Pv#%Ӗ!# RF?}"bB0z(r$b$E0Bm=HcBԈh$\e mH0̶dWׅ,;0is 6x/:)$ *)iX8 trtȐܚޫ7dq~Z3E_F`$A0Xv~ Ͼa=ٌ1/|}`yb{|()ӓO.ٟ/S_m~w{ ?Q8Xak=Һ\\~՟)wv} o[(ޟ\B, JN|gczGq>S?8JՓ (n EK4Pݘ7Ygc W'O.%qXfO>q\'#pٽ "0UTÐ|d M-uFU.)ޔ5 untc5t1 <%NC Ղ 6Ǿ0ZDwqovB X{ha<@Ы-PѺUiYIZ7ڳALAΑLB 0B wnYu`4n$Le,iRJICBI"@o5B8!!)pt@6@qD\5?1(bt10\$$nބDkTmFHٰ 5Qr֞]cevk[ !3a@6tli6@,V#XRB*hXQp 0ԎH, k ?͎کc:~snaW>|Y A4ȘLSGTC}뷯c}ogWϾ+Btw^lO_80#@RCDr/c}=|b{m%=qnLgb`GT7QT}DӋ˰BYoS§ZEεѳ黋o 02m.`}=u~U&rbC_l?QfK /ˆX6) W^|HAʑufCuuXsdPnU$'BCbo ;P)d ch$P\0@*:+ {|JH~Ht<Iga'ی*fS8)  ⬮Ja09j?R@"yźDu@L0%ʂ@Fh SA#0t3Yu3.~b+ .KXثHdu繡OC oƜ3Hp A`$, f4N!O]l㤣ipi neB Cd9'N.`<(es8[*TYJ'@/3Igd\=rW)+CX yـ5 38ަV=r=v~3J=?C_:kqzFq29_zJ~҅mp<ѻUZ-n;9(d$ Oܬœ3u{XVe~_ǩxǿ/mM+m$OƧ>aW|vd.jH/^naitdYG_?"&I , {4غuML9%`^VG"yeR]S_ܐ8j`cՒ8@[ ;KP89xS3Ay; -Z-p{k]_O˱ &pzWןi{ش.} hn25@%L2r.&~2 %_^~W=ׇ)楮xAw| -1i( &/kf|L~0x4=p܅A ]C#T~CJyrN)p݇[)0nSgeWLiv:Wfx<-2R_sZ)V}g=D j j23K?k0@m#9!FðԀa`L8{(*Y DB 25XEI~7)'5vv +~a Bak: ppƐ,`Nʠ|y̔8WKoJA ڃ38P PFf#. 2# A!"0(!z{!j`8 P,(9| C`f(Hc&Qr<9!|T&< 2y %r'vb @R\rM0'<*= d L =Vfoh(T (7bD` ZX>Ґ=Qc4g9ן_{S/6S39\9lss۝>}_oW=di; bŁxmJ/d85o%/ %K0B%irq~Wew?I~͵\]/ҿ]P2C>{x: gmf?p.kz%mf XgڢہրH`@&7' -#zBIQqZ(^ c8i"9adD @B=#P'I uA8Bw-iB=oŠ S`p8@] 4zCx&. 9"aH-j9 -C]7ΔP(nP"(! QJ@OJ !V8WSʩ?b$%DW侬7S.`w=ܽ7Fop{ێ7iv%V㰣1՚Cufu7=u"6Kıdǂ~!" ha9H ufgexVxp:Ye 7@.0=zI" ┛FF".HǝAPW`Đܿq?>\Ѽ͘@n}t2Š7^ѭ:Aaz^=e-M}ǤHLH+@:`c Z=Z)CUz KR6 ptq$M-w1)ٶS. Fє&)-p qkQ6ݣ4A\!kXRWʡ@^qG6!q`$B8Sn%HJQ$bNtZl^u*dMi z  *` ",(J)0BB$DБSRC(B# ""B,Q!@ fC9' zo^ޝZ}~vL̹35LbJa'xƞ^~P.κܳWDCxofC]c?_~Xn VxWꛇvgz$(O݇]??a=ZX&Ӵ.~my2O~ͧ_.xtoL^ouNT+]Y:4uL%udNf)iiBKn:35p#T2@3),Xp" &ٖhᜀ&nF0@  `fBYa=l!B1Ra뼣hc`Ŕ"c1{Hu4$ JA){.< |F[,fB;1( J8Nͳ9̡5ycAx@nj^A0`H$LၙEXFOgv:tٜ֣nknX.5͆G/`rK^M:8cޅ-8h7fEa!"v@H! Cr' 1U&IH{Cx&u̍zHE(f-+8""#z8Z "kԵ!̨JbR d D8LFniLig/M;! CG||OP @BDC?<C@ N991 A 8$@Gi +*vY7j8rK|Fa {r㉁+8U$q8ځ @vٱVJxJ`WdTjFbkތ܌$tKDLQhtUdV:A|(cF(ͧ؊p/mϧ3G2/Q]LKذ^nYPxغ#m_2u??`W_~.VN/W"'Wey;ywf#w/嗄o>i_Ժ0ۻÙXq߿`mQXYxۦt3: ;\6՟/܎'WI<}xeV6x>tos݀$ a9h+ǿ{ӛ|~8͏Қ%\q4[yݎ:$\gݻ޽Y a, }*,L8@Lg!idfFUsMްv-,:0`H Df.NiX&qz@q8KJQҦwp{0'z*yw!*-B[knTd1){SVgOo jN<.Nei PE7O77R7?{ogW/{6>wo__ovBb;|mS W/o\Zg/6>=^9R>7Wڛ7^7͂E(3 L>]?śzN:w3d܊f3!YB ǁ2-11H(%07Du)Ah ؂X9R(t0quq ̀ɕ)09Bhfԗ1ceB$4%]0.Ntѕ M>&4ֈ6g`B thitz@[D9|@2f ii }a Ȫ1u@,%brŏ+p=,Uc-8"5$)ݸ5n;7Z'q*Q2eW4ɘn-v;h:M[9K,sj6XM  ؝:[C{6`‰A~@dj(3B_ϒ5: RqJI>U =׌ͽC* c %$ HHȄ-#lc4p[ b7 iAP0%*jh(h`kŔ (gpZCdVfB$a|U],Ef G% } e3K6c(Fw$r΂u'XZ^<qsH))鐫Q~LTpN3mbYz9gt%^"yÇ_^=?@î?nj Q9W?t'o/hzj#Sb$Ҏ//(: Sܽ/ˡl0'> UL,DM%X i~ KŒZ=6T)tUdAHHPj"ZdL LPHz>ݾYҲ4(Th>,f짙DkWp{MӘ>5d.=q)>?<嵸#k{[~_Bi i( 0m.Axxd{wgysñ:X\klz~w>Le# Vpdոg]3)#f>ĜD/Sq]_8}wuz|o}Szh^]?Lo/ޚ8lC?>Z6~rӫ; Dfs,mWt7Ϗ~~bK{:a:4W$ib I"^9aH[!@n+ a@hD-0GU+UjBxup)rhEd^ Mr0¢NhdFں?@ wi(!_$QVXrł]( .H q #l*C #`fN PNDN(  ;u]`a4 N+s@'q+$HLP@]8O*3wBX9O'ؑ1x5Ø}^ֈ RܥɄh=r3>@aea,(pCvG0 WvZO PC?mu*[e |hbw}qW_G<TO_c%Lⴾ?gLud9c}'ի?쭌µ.d)qd?q.8{~ 6ex꽴oz4i‡w/̎wyؑ9Qj6#81pǛ쇠w[q!Ή\IDAT޾_[P]#F3 5<;rSҹn,y(E*[(#g@G&8LFUa@h-dFFAxΑ](L`G`YhǾ%̀!ur pn6}itHеN J|{?ŰzW2V>`^<ufiiⴧ2Cy~͉@ksN3 GTRW"H(]v^2 9-Kgc\ l"[.1:H&B )ae6#M34U2!#M|<{a~ϵƼ,]4R` H ݴ q{fpsFeֻ_3s`b[(K.Na@N1&ɢknp{gt,W<8x%YvzPvU6EJҵ,|67*ISeDW.7Y(G_pFR,A 3{Ђ)fSaB$¤1 GꞽuvZe_+5Ai8$ԕ$Ċ6Z9X ',ꀃbnc$B Sj2DsHM]'2[ 2 -sF1 jޑt'BHс\ au=( HxBX#-;Fa>#{1Si؍Qq}X29*"LÊvfb]EJUɽw E2^$Q| dNlQ=':*8b?O 4A#",6kՆ4l?2n6W"&v~N߿w>T IشJ.qk\1Z¸~yI&~ʇKOa?v9 #q$A1{_Ɉyȵ :GwWSՉBsӄAU]n;`RJ&, !o$6>:c-ЂMgA[al c6d  @WZ8U'?0P]a5b@CA|=Ilڟ޿onnF ^ M<n-ڂmķ dR\`EA!J)N!chK9~83H?u`0@Ĥؘ6 {2yYZIIG]8hfg@7mqa\ڡBD#Oy{'*)a;Ų}Ǵ*` |V0twWf-QՑtQ xk^$^,Jjiy>/0`YEs<'j +E&[w`[º81PO(!nN {@@ZS$;@ D K5F`'Z"FL 9W1 HNtҥ#Cڙ8qkE@eD\Z6.EׂyL0A'FM`{X0o B4@+Up--hB0#mSsNM-׍]g=4;>bAX)K0#b,<%Gf˂xOj{tMXK4\>YPba*#囹9 ڲ?~w2mBz~0N/k{Xm~n׻vEf oޫۗM |{DSfGwݻ18=>YФO/?OgiX߯(*3dY60 &'@<%- iW]hةXBcW/~sNi7,H*hh{/P)4XyiͧB0 u?""ډv~\txw׀Dmp$yްsgFQ&=ˆ,EFu DlרqC3 v"3t%1!+d fڸA0zs(=%l$(d)w9yx ZzVDryևXsooN9Mg/{w:ߗ#_^_]o Lo:n҉H\myqJ'抆]]*#f9mϞo;0%B+g4 fW/x?{l.5Yya,u(9[bՅ?=9A2K[O*Y8Tw?_H5)Sw4"'qIFHktUĔ1\6ښS F8FQq@2ea.@@ET @ 2Fu [AK7ԉpFĸ 3Rkm'pA}O&N ɉiE {^Z;POVϞ=js3ʋV[8xXcX"4_jGWNuuEA S9_VP3888DKư,(vDcXϦK%OStcm5ǒ-)0{&AĥYχθ#ˆT1dHkJt9.6iw#7vF5dݠ9g̪hLjL?s! l0*v09zQ&qE0rEjg'-3DS&JLJ LtH"7ZtVLA8Ed1q 3Jp 9R QD (`dDD瀆 Rc /0" (DBH$)y pS*xY B  4iˍB ύ!CB X2zc (d3["dܨ #ub&uE*`:`JWAPI,RjYOR{Zzgu,vefpSs'q,Sryz2-rvqYjp|l4 ol$$n?4omw7ןaX(ϺF"^b1CwW~N=+vmu_j89E/KSVTɰEx_ZԯvL'+_jPFI@ǵ!.Ȕ?_ 1:sՆ2(TP=z]c}ohs`tWI+ LbNSε=8J}A2軃 ,f͵=aaJmHhU9RXc>g767aڼ?>ϟIȧ4Ҳt~YM۫w8'/OLөN8\^_]'^pɠmz0^=|r xө6 X.Bc׹nZ>y:}O>ݡ׵n_.l7÷ >qcqsn` X4bh* i]xQh^f]i-v(oN˨%6T *̘i_ qbBܗMǕ= aJ)Gۃ+-e[Zoilxߟ>>>y P2} D^8|Fuń=H(܇ ՅNwk@!h@)9tެK0w'=gԊ&ǟ:'׉FDs60`lfb“>oVud6'g]:F1q r- 0D@dF9 z4yttaЏ G <)E G ࠈa#`` VEsCcZ-SI*lWM9t̐*}%RJS%12kD\;v+MB8bFцL[wԨdᬎWlѠJ H6;cE!s*3[f$Pi {$F=Ne?c==zX9ş voe.ܺ&$ cwhCI?kmK71Ɯsu9mU (%ŰCm I%MT@՟֚s&3}0"2ƛ>]^ʝ!bp_rcԸ3gaј&99ZL3Sem7fSۮ}Do'Id7Ǣ3/EV%{/.嫹$!4&:{s`t;$d 0\{tk򧂜cT ,IWyxes lQ(Eq7m}rܬ<Ѩ" c,&"~|z A$ J@'VH%n! 4X4# )b""JPFw3h C#zZ@LG2m-hwn&Իk+4!qiOUw䩴4zg sPZס7xilQ7$]hhΈC(99R6@Gf]ÚKdytࠨފM~9g͝&9YbiѧoMdf}fns>xޏ~1z:>c|!|/IrjOW7xYU>c͈#^ȱ?=>27{7Dą,n?`co<}hdeNʶ}{y^_8ӱiͥ^{y>#(+ԋ85 F*yp# ,:ؘRvUQ3Eh̢4`D4x4M9YʾFau$Mtw\A "diћSxnN)zy!a0N_eJ1%s P>,+I婧˯XSYB>rRukȇ8G}1L7FJ|ǟx!]{g?󟡋&af3=,W}+'}Go! XIOp/^/~L?Af ;GY,a\EIoym[?0__?v6l4"O:_爬vi.U]r}7}l:OQ^u9IhLٙa $[ X'N^J ``N"nLbJL_(=Ř])F1h0'Lg}/!3pQ;.yQN4|ųO)YBcT{8e3(2^2!ь6N6(}{nNgb?ȴKm}`YvJ#*C?2>N0ZD^əMyIǶ#cM,Fn꜎9zMD+m*M|ctYJ)l"pnBBd ?SD/8@晫hwLnڇMs!>HEjgMz-j">F )EFt=X3g{:i8$F,fT Q3}RIaF8P\9?D AC ƀZpJ)|9Gx22JY ScL OqP.>Dû DEPF)4SZ$A,sF v'$48`:\Aj^56AM8Pڬnni4;bH3? 4/z<Ç zwf b䷷}y͛޼yi8\߽'_z;}z+<c{ qW?%ncv{˯?ûtX4E^fz~$j9Q+ZWßeu1ywzO'wNWw9eJ@i13sZnC߿CrK9,tx9~@T~?sHDm>&נx KcAe6g:g}O{?yQ[U{`&ٶphqK"L68cV83+;>P8!"3*m'.1,,Iv56ND!*,(ǾNI-zd*^\i9s]uOW:q <, RqEtwגn2_):+;3UET#ek<M.l"N\? Z.kei`*C@Y 5j-dOO_Y9RO]dət@`h#8;gs.!C\ kG5(:v!9Al3Ǩ#ώCv9I002 ДssN @UȘNյ`_z9s"]8;l@#(3)$sF21F5pB$"G`#1؂e * '2x!a42AyF#xZ[dJfkcI^& $Y}j}+,cVȜ5=8QY9Q׼ >{uL2X u^/LJ5:C)oWǗ_ND~#{ɋ.Wy:+H˿U!]Tʔ 06\><+4t$9_A-iࡱ}P¶K9)*Hr+l Fm,Asj Rb=%4݂rD0ҍ FRq2gL '% ,mNgnRۅ&e(#RA_yRЁtvCB =C]ƹɲ{,:l>YD¸šrHK<1R:各Ʀ`Jz>Zw5DQR 3$VX&)G1*j1Q250&jCBcAlW̩Ar IzpQUJzQ!FӕO >2>igD%WFT'eSL`%O" ,A  r P qõEH<"I-S8mJ)r9rDkդmA\.%PA\Da!}`: sɊq<O!, ŠC1&kC MOg~?O>l5eqӵ>|CKo?S><>?oMQC_w:yuJ''>~Lqpu^Zz를8[;xZ~/ޮ_H}z\<^ _=Iۛ/_\M#pM{<|8|~3w;㶥y?JnpN"W|y|2#NI!t0dY͵>lO2A:{)Ϭ1+"/|^lpNerr ) 1}< Q%3z<5Lk67iwg ѾB໇NPL0vV#$ |1%H~v"X=-ɛy]IHg7%G{LN(%Lam%ȸ Y$dJt:V#]iKu ȌpH.98 us-:y>xP*;tD5;v8 SiTibaf0&7. ܶqZ*e79ƐsiEg!߇i k8TdZu_?lHJ6zmW#>T-&co210Z[׿\/_8⫯V<>|w?zut ENӤzLtŻEEnO0HĤA{@} ıh;F89$2CS=T~`^aޗ9D1h]۞YΔs咆 ;?;0g.Y9C$%b fΓB'r fR &4ErOJtei|7]8L}>}j$;{9 41䪜Ջ󋟜y_?fhtH$Qh8-e+x>ǰ>b቟ޗÏ |O4?q;oi?͋W~qZ/&YN7F[-Û7;19 a㖟Ӌ:gosY^L7yO o%a9Zb8+B#;e0f8RKAlXwg%vLbs`D2r~a:"A N"朣,4t ɠ2 Ctsif*S6:)sb;m%WX~%&JZNG^fyљ5$AG!"Q#4!1m(;<3mؠ4Xqa^]^GmNf){9v IG;e:8mp5OE(q*eb>"+ӨbP:H`LLI‚} #"wMJnxc@J8QB Ds iBQYeʣH%9)TZ_}YZpAټUZq!b^T vp1.=ҍƚN2B$X ܅^C[G^\t;(^Nfa8~ɀXD>Mʄi:t7{_y.3q~8÷O咗 )w~f)Oay_pQ커*z.y}Ztt}_$~u:޽-qnok򼐏( D#La\YR )y{ȓ9"P|cf&ՠ'ə 9 F&L4 %.% lUP@NunC⺜!"\9g C>Ӧի}>=So׿~aKͻ]\t\衲\/4vTq?k:Mq#tn뫤LY1pziz5_~yoh}>}<sN^O^x-OizUKK (7?ϻޜf)yɸd}ә~/zX !y]xxz|vli{xo3}߽|͙|>0ֳJ܅/r=oRhBVl+;==BFÛlGTj e–fk}0!;sִWDto!KzJ]@dnԚ1*QG_c "y)1BVI蝈H&!Edv7'߉aͽExPaoLȷQco/>C(8Ív 4ZF'P$mxw\Rx$uQT&J=c{:/|y\ńp5iC:%SʐzOqʴ3v p",0-_vB>-i"$&`f@tGw p )"rdY'BwڭvUdhj8 ^qekʢ ijL"II'aD)9bOAO4* IwuTl D gJXc0F$hMr=KPeX;Wt*cr5_tj3/S0c/Qmy>|? u?oW%yosL1iFhڞ=ƃDzLjkP>mukv~_Uywf%ܧBvn~yX|~}_kBe& K]}zW7L:Gtү |_]N'pxz}(_xľt:$<)AS²4^MDٳe6{|S2|jь:=ny\F Z V".`|d8,Q¤G-Wјp :+{ xIwp23"nՃ*<\5j2fpkF*6$>-Mܖ#-eÂ娄HTB5I' E(P N Z7 DusKaaa{-Ooߜoc Bh!'阃i"2uK>|g%{84"@6-va}Ov{zˑq{{x8厎WݿnضKޮӫ'WC/w6DچD)*ɡ_oz5uP*d^\7/=SH.YT"(5ۇnmT3}&36ڇxDRc+k7yi&)"A+Guhab>wKQE[хnJl=Nك̒!hDRW^y=f^F tn,Z"dAOd m|(, 4ER `f"6,! Վ2prFnOiTlmE_^.mLiaX)q H!ii)<̳O.1=_,KHNaztTG9VMKgZG#hclKy+8Hd3NL+\-BٌDhcKDz]wt QlJs`pioNeư>=GLb8h'ʚ፰{ XHk)-,`#3De8r9rsD18$<)@B:Q!:`A(Y W)`D9B[vOP 1;!|' cYwYY4THz QGwZ0$(*kPjҁ}|^lDĆL ) Ta'#ucP6,mWbXd"rUco6:F۫r{~eԎXRuݻ$RZ7hxW3K~_OQ|(inXä[|Hw%6u<)-m|)ћ/ן̟d|hoνF4|?7ǗnOWWt?<Ϗ>Ջt=z'y7_}ie}@cdO1^_IƔvr;O7<uw-iFv,z8ugrMi:,$+t7!lţG5۞cRx>U23*9<ѪxV9$ S1Hn0A *bWt p#be2m;u^r36"@asf0.Pv 3Xc!hh.H4'ҙx"}_){'Ajhc*dR&2 +F4BM/Z~zz):kjM}Q/;,,FQ!im]RitPosGg p)犺gn+}< g6M^9hufHS0"ߜ"q -AnHMR0Ya)}`|^h3v\8Մ91%8RSq"AO|5#ՒgN2Bz8ʾ4_ߤӧhϻTXJnh+c߮iѧ:\_Eӟ~;N!n V^|{=^9+wg_֋.rYDɆ篿bFo=+S ^ûo/G*ˤʧZj"4OZY<,sQ1qxsa*!es 4cIW/o~Yȡ@ۺn!g+pٷn}_5r(yY|ϿL-ǓkLt˨_Oקrxg>^ڼΖ aw_Accr[OOFۮ>_я^>yՠoޮ}~r[>t=3(R4\tQ̯G>=F  Ώ5:U NCoLD @\svV<Ӝܟ1 sxklLA6XWcT X Gc ,/ښ)9ND6 p1 j{w) /A#D 茶0D٩li4XEh2)9>\o&k8<ў򺎽m)べe6 srwֱ.S.Q[;F=?&M\TEV]G"f|<3Ӥ!96ssX& 2͎DXkt.a(!eh\xэ£wrSBf@ =FDE5.ӫew~ihrtq{,t.J)2/Ee= $)O +pU܆MwHym雧.YuU}u>X慢d E<3sLEI%ei16 ; FLT05c1&w$`l6EB=t.b*AGZ[@XtgH)0 g6,Qv3RW~6nl.ի+wO߽iL'w?n]wJ᫯~˿|֫ӷ~z~ 93Ƙ4<><\(DN4w~%gxaaQRoeuo?OKH7ܿ_蕾?>7#ѭΟ>6֦ iz0NR }s۝>< F_9XjFr NDSDҁ$PF6dt0@hѫdcur6#^h)E΁L|P " p!$$ lp01);8Q*dÉ@L#PD%b+`,נ %q1ٴy6fNOanJ ) _VP|r f9e= 'BZL2f ;;#[ ̡g bCÖf!rVV2/w?w~yifo] 2C_ߟe_^SXF L`^./ey{z 0tOy}~I,)yg|eшA5_f=iMWO|^2['/Oy9?8^Ie}KlÊm[/atL%o_.öB(.c)??yped9qަFS0)4LW//ej4lp,qsFݷN^XM_@z"xw2MiYgk^a $(Ha:iQsZp [,K9EBڳ[*Qf)"**K~r|NGulOG8Uظ5g#1e'JA]IpÏʄ$Hţ/Bl%m_+wN]&AK7Os=!U X(=LdAۃ1฽O@W\n> *Pڃ̓~tPLc l2|QW)~ntI1H!8!GX8⼲Jfm޼ d'Xr?W \n7zPD]|#,utu[Tss`s&Kۆ[x) mm|ܦF^(b''"樮Li[@G!2(6ĝ ޫ9Sb+fXaULmNe`w"Grwl$B "`!2#{-hX%;e3"*@nA4f0@k> H"YvA3"@l(PѰa$.qYt ΈQR0DjZ:!uIMV* >]"G>b公Becj0ӄ}mu&> kJ^^O}vg|xA-8MԙןrjOm;j}W\n>ɏXh9Lƻq.EH ,<6 oqؾy\K[0&؆ֶ?Rr՟.:5'L|:4姯w^Sy_\^<˻c~AVXgtﮞ{眧r-'W_2bkSbE>t;ov9Gs3뼸 )aX.\Utۈ%=X|z: MYN 㳤B!EXK5&ei%FZ"ꀀG q_9;=sXD>Jo0^9@K*. B~nx^exJx~ڟGKX k~v4?vÈ Q7W+Ѡ%g/}$52 asI՜YX)(I l·8d֍[2Ꞧ GqG[[HnU4CԛՎ0 bPH|:Qˇoߪ]y^^ -f|P1aG8\CN !1*:ʍ{ $j}yo$P!̾IyHda)#)B-[r~vSJ΍{8p] tJQ#N6p::eJTBH&033@s.;\#B|0q0Kp2H ;8 Lj!lAJ>܍(Hp# p[!LRe49hj:FŪ9Pdd!{LYt_:̗SP5(CSS>XJظxOYvd!m4\uۆrT_b/4q^nҋoy5RWB,=廉w'umw2o?㾞[{Ѓ(2PgP UB>Җ<ݖ< l#Jy}x:LW̓ 4q~|~̧c}Fˇ}/Qt|~v #8/G~Wq~~}S~WMYIctq8AJk@1@$%~~g˺O:h>4mN'ڥND T="&ZT<D|)ro80seU)=[hkm)zUPHlÖ$$D=|3ՓR" 5ɜrg#Ĝ):y&Ɨ-GDgڟ)#:mJd>xZD>S]# /(Ӕ=.WaF87?y>bނɝ+zy~h9jʡ]Fݣ?a-bf :MxDXҾ7!VgɊj<.S0ЇhH`l0I49f 8$pw7'̓ʆ5ٷ"|lk$:=Z>B|i>^"D%\}/_L<^|z]0Xlj GuZvbyVȡ~_c-\/7qb۟g?J9ߞFogq?l/7y3~z<?].Ꭼ2 !!،Y#4'KrȓoKJύ@]ZmO[u %LՑ]n4آh{,ԪxOF$}Vyhj8vuwË޶zy_ק}.%gI?!ۧKc%u0 ZZ7ߞzk<:ڦ)< vYiZIk9HOoŀK_vyRW)4$Jtz)c5Zl6t1#zY{LGmU,(}O̕T5+va* b!DS@"#B> aw/1@ t5p`<;L%S!spWB䶑HApNcϚ5;4=lMsD"YYU],vKdd24l6dV5W@"qoۇ5"Z< ( s4M͆REH9i4h,nfY/'iqh)Xh̅}8XGw 0w%qdvwIjXnno'y(IU ٕꕖ&r#.lz~Nۇ1/"FT"Tl8&Ljk$hXVkk߿y3T}Ǜ^3+K KQd⠂zimݣTJ` TRwhv}0ݪ6+~yy:hagyλ$>N_{ ,):S提!$>2Է&}y9!4gӡ4ZԪXLOk8veġmr sˎo;_wδ&FXؗ.mf$L즂Y ^3͓wѕєC5 4`%c@/2)6"/fF.&K^)@BH]9uRz'w݌O߾$JÒ4#srh%%iղ؋/_qM8{w3ME=2OàNns%?~~sy<0Zu'rytzOr8ܤ5~>_||~rgOqe+>>}E{ޮ~\On +JFA_o0^r*~@% r~÷|.IL.%;Fɹ:ޜy7?zD&,].+bus,CE+0IgD~Y)2KGG=]23rP XO>` 2"/ ];{t ٢1Zb-pmr7k@u="aJVfD4 O[IuCQ <YRaX3 0ߝçݒ PIDOrXt}L[pU[ ,ݻӶ?[2ULڷ< E2PdFh-dťg)h%O( Sر*K)/x@ʥoj ˴ۼ$BCL4 ]W萊}闱kLԀ9[13bc1.-%B5rҘv>;![ң70m(qmA;ƎA# L2"3ϡYU2c1`8z[{1V0³9̼2L@^Cn1(⠘!08g4q4D5 Z'qÑ #y#tD *b0p#RՈU,9x9V]桩dsRjRk}&R.>) y^vEf@dXW26T5\m}v`B#|DpYUՎSOdY~|N}<9e+3ٜW4.yĔ.}unah+˜r{\~}n?aE撐+< >.T5i'b_$03~>~s.mlx{}d1I_EywxOӋ<ϰO5::q*21>2ɼ{}l|~M#{"Q4˂Cm8̻K\ $Q&w(iBm0@#cΡMc9.A[LCyeHmAN0Rk") .%k+AN@rvOsx;fQxbr-bؑbӔ3Vx6*֧/^= СY[Hy mhƩC-$sfiӎ"6t8@ =P"cn'wl"] ɣ$1$h(s>6l1D5aإ~KRn -+i lkI5ɰqdU1R}{r4}p u} H!`>\>8>.t&$Q҈`D(""D !!%H] rp@B1/CstHEI <6)5ѷxĹB&,5EcCD" r -$8&ls+b$n'pաmʰOD_wv=~ n ¦r9dgb׷>,Pp}u&OqG].R{~3TaCb}$}8Oy3rgbӟӋtT,líW|-lÏy ㄷ7aL?T?;?F_5tH4{\f=Q%jы6L%a-E{" %(#] ]9E:i^G7Fgc5'0Oѓ]S}tZm93|)et*} 1uuJm1Db2]D"3yfE\aRzLIY `uI>i-^D,i]Jb B>zK@}ar7SHS*=+4eÛ EW or#DX{9Bn޽YN a8Nv<'6 u5!D@fkZG]:>_T Q@SAhVK{ vst`s1 40t@p ߂Rǰ1BF HA= w'Ar0:iwIػh%c_<{n9͇ Q9 OlFP#\Cg:o@ 9.(PL.MƍaB}Y;g(@(1ͻ㋟}_}H9{0a|']>m?s) ?Nj 'ڬŅmwqI6(kw$/}]Sttؿ| gJ 3CڼaçUuQ-I?xr~x"Oo'}~ɴ.v&Z:џ2t:ϗ_r8\'.߼8d+DJQ6jJ4g#<3zv_!HOcN 7P|6qOG?_n<OApjKºvC,#[nӲ4#DdDfa@ODu b,Q)NK CJé44/@%kA awXF'p L7U 2Da/6ЪcQWo0f`d'Ni: 'ڈFN4ݹ|:ᲇ&esd*e wwi1rX au>fULK+cZJ7&IDATͫX2^+SLC6#m"d"r $,(ηwټ#r蒐@E0yo40l}xwpB )Yv_ό0|3m * $͐TX㣾8uEd:L%gL=q]oagʚi)"gd=8фm@{66 T&9,xlf 9gؐ90#p{w3pZwA4Jx pdn1#{` ()pwo`yfJS@ 2d>C #!b8R $airm)aj)~D l%<,1s{g#''0j-p&8r0s0HGglL4^eɗQ-nF$ uc"p]/C1ԅG>i@myXfp݄ S }XHW"@l'hjAG /6&d S>h  Ёh )4MRK{v-N3}"ږ7vB^J ]CJ:&3OHKv#m̼~9ζ·da~Α@etNKsEܛ#e<#D>v@5 NS-M$K!eOY`ɜᔡaa hg;‘A 2hdIݬ}ycT4B]V=%4A]r/|Tbf'(VG3EƵƤ2yt9x7!]8sBHΣB.(F=dCS 09yf'E'CBHȦ#}zWr GsծZ} FX,y>E޵Ͽ{_bP* 8"1vKF.|(yG44s_nZC1L Oi",$m=? >g}m"Eל\m[}RleJYX҈HyWSPѧOϗϒ*u \Gv's_}:nK$O }FPJuThR) jAZ!3zu:aT K%*`ƣؼ6֋dl{_ؘhuH{dp.5j]݆Bkytp0Vߑ?Q<6򆴐@"%4r 2@G(bs SlpA6B9XY%!^p_U6zqi̷nߎt|r%dAlW+r2Nzq)~V>ǫZ8ڽPYC`p1N2NCc4c 3urџ.m뽏&1&Aю3h@cOLv?sq2+'$vdFSٰ1pa~U)~E4LbFLptk]WV0:)BV07'5Sd.KhUQ0!JSevO1Z!ˌdlTC$"[D佈)1&uD(14ӎ(GГ`؀ 9,0ua=ja=@ }DX!Ы+'  !,#Ǚ v$P+ZC4=S-M:Ĩ-ҷ+R6mj8dD!5c8p({ PD3gS۠I#($n?N>q8V4 #C*,#&[yei7_=}߿}:HjËvDǧo/'&[ևև֩o@g8u\fUOͪ-LX* OiB\{:%^rCAp"5Ck_Mzz|xȓwt ͻؙ g;>w?CnˆRu*8̳λԶ vS@`PlM1-{xy:"OegL{1kQn WݭֺczG+A~jF#$` M-TB6"5{.fFO^A=R8!Lq6S,^ > Cd άA R+!r^ǫg>IRH)Uv݄ 0ׇO˻ij/w~{soj?Xe#@IF'1aHl²Le'Y VDXE01z$a֜b]G5a7L eĔZ34|a4T5$HrtNn6ЈtɛuU5V ^c`Q1b4Vlh(b@wD=%qA[}2`Fw73Ga<]-3BoEvk =Nc_#S&n}A=G@[ Vз؀ q:l׸VbZd&QN̩`v‰2fH |A+$Nv;ZۇHOR[ô]wzwwo50ͩmtoo̲|gg_n+B_>D$_WN Q4-Lq;|#-mW! y?ᄊxO^G_MoWp#SI7kʁ8d X<.P7njCchqHsƉSz3 z\+hsnufsu"ALYg&u)Wǂ| kk3GF4Mڡ$1  9Ch:|ME%C "Y!1Jق@(9D<9 ki38~߼!Wb?*|Ǔ}Xe o6idBl1߾?7-[%H.Lt\/-`Ja^D-4 3gAC-Ļ[eBIٍvF{<"e9EF2b3Ax($vՑhm B,KjP {/*@&ՒHlKGwX@ !ئϔ 7BH< ̩WI[+ 6(FW@mN !' D 1"AI$lɡ@!#,ȃ "oBWrDpUvF]#B+DA;SrKn1 MmV^6Swa ۠ͩX]>j/16 i`4#P7\mL.H~ B'1Ξč/KH (c~͋?Gݏu:*#XrS?#ꊝ&O7Ǿ^熭?^/'Oy8QN<-w7K9BSޠ gi{Op(_}ŧћ <==Hvay]}Wtl) >y/9=t/8?HPrpm^Z7xgS<{˿Ox?|ou_Wb$   *5בsH#욎x<@ J,Tщ*oJ/;,"onh`ɳ;{Fwm59moo;*}u0,<Q\CCil `H2R0 3O/1-b8Ty=nu1F@E  eG< mHB`8cҸj>pUq0F%.jQ B hdn [F-p2Dɴmma,Sq$+ 0hIӔpi>̉kvFJukC#g 8SgIP4E}qΆI.6.ȼ(`!D9DH O{;ݰo`@MM7D@a)Ax Y9,TpZ$d}|eK$l%wd;G@"Sɂ !}*ĘD!fMA Pʎ)"$jD-;B@z3D \0>(y!dD`144"=T ;;Gc<2!)``OtHV͆dUk )Rg^mqq}ѪF64‚`\abg@p q#@7p0d=T `w\'=H>7q0v]H $H,9՗=7m=:u{v #Z뼟WGkַaր`ogj$ \jX<,ry^'?˷BY[g2S᫯x3=iW篦Ov~$vtT:~*vm_two6r;e[/ oˆ%/"yy>ͥDD93p4l*)S 67?_[@Qrˠzm:fDG32ͅӠ@N<+Sm!+ ~U5#,B1P݆C3:"u Z2nA fa-"xC1c?Ё9E[]M!0`w`p"`%!8 {ZC}Yb}Sb/ߏN>1 :׫}x  af>F*poa|DuKoOc2QcCBef0  L f@n1H"( KFCgs'SEK%,cy>Dۚ+%9#@ XՆN83F:G8$%P4S: l#j6"2mY983v  @$F s Q pZv@9 ٕ"#栙ʼnZt+Fl pÕ]D[P  "0"-@ H@}89 ;A@="cAaFƒ" hlZwf[p!I!m4n(؝ɝXpN%-<8˻ RHn!F7wVU&d \( d` ̉`6b$P'8cl_[zC7UK!̉Zݲ?~y~6 9sTtʒ,Go~䋲̴ ʸQȔE~qg[Vu,qJ K?<ۣ}_kR5|'?ght8~2-ϖ&y}׷3Y*?9˞]p;(O?\:`sfޞNrz/[!>y.;!ӿ؝_o0p8w^ zݴS{@qS6ySJ0H0I;#;YZ#3v%7K O וQs@DarJZM)p]u8}hmּ* ,nڗDh v!qFe2a44|7 8FGgfQ<<, gSɡBع 0lZ$vVB3qm<(X0 jJ61V/2 q|!EdFDU'[k7OOc[9Ak93fzaiGD#g 0!-4<-Lו Ti6GN #1g﨎Ffՙ"ʜw Mx;Rm3!,=YYQss,0`"uF`d(S& u,fR hdphJl&B"Dm @H#( W tѬ_03b&Y` ( "hB"@h@dAP$½z%Pذ{n6N'I;Ȕ8Pv$k#N EulEiL)ѝiFpHX\- {P lp1TsTtQ )%UȴAD4k'#ZL@AM33<%@ p  (A( {PP#0c @txpSv{@ÈGr0k|zFbȌ份<&vuI䌉)]bN> #@#.Ȩ^ D`CBƣ˅^=)`B1M mK51?{yZHcԢ_zp*stibyѫM-imk]OQmۧO^}T E56j᛿zRMKBJ}<8mșGW3TQ\n=: Ծښ@#"iseG'2-!31@Ec`2RC{(j'q1G(>J8O*{3L#458FX&gD ]<I@#D1c vLB=sqˤ\< yfe]F$fM3'6l:|s4q$D#bV=:[=08z@dJ# ń11!0#8A n1^ >`sH2 S& 91 uJeaMz^ػ H@ (z*EfBA`Ea[4n2VdTqĞݧARށJ@hku@11Gv/RaBho>DC Iy6hQ-ک_/ '⣖"A4 l_/.:MW'ԝYl9OeW=zԇGe_9tw0t}Kyz~w?wtoH[Iz/}o/9o]._]7^7=</(===_woή‰/]V*eir uܿýcvqHoWaA4JD>.xėiJiNrePW̮><lO'76l饷#;۶>c[  74]-Bf0tUf# 鳃v 9,rW_w1n1p`0y#70%dz`@>&ZnT9W/Wqp+]Fy]˩jw Y3^jސ;OЍ?߼lZx\5+8yHQWY FKHIZ 2B.`r6bif$A(L)E*U1(!%@<` 1z0B&@DH6 8{P L D@83zf)b& JjܶKcDD"GcLQ++٠ πBh4 [3O3Lnb[bL G<0%` i\$s5=]C;鲻8qz:mS\;&ZfnZM2n9 zB!*Ksէ^w~~Ԁ|a>?n'-/>y~0ln|8wgO<~_׿7uan |v2~\_] zI{c?=VLly>p!R1lcPF̽1.0'b闟J7Xjn ւ[ ru F640Fx̣EW  -p]2$ֵ;+jg4Jal:`4I£+@Pʈ NYa`0 ]2IţQ.V;m`d QK=[M,Ryw #lnᙞϼp{YY^%v/gF>l pZo 7~ bR m r\@Bx :`LRlϗ2I: ʜgexOk;rh^GuU B+]ʇOw:& Gf):ˬ1'Gn  ,4vPVli26 >b&$ V:Er*0s WO!a5 )Oic0L/WRtY hHau 'hEHAIBh%( ! iF@ H>v.vgX@  Adb(P8#*0Dĉ ӄi".j8(Kf^kFʎ0"C f`eE'bɝzuCJe@dE5l9Pܱ|amTRm39N)xBH(S'OJ]7YF2_ߟ'>ٜMԮ_!Df@V+isa2S#3^B߶A{ۿɫ>=mi,FxovϾ|GJ_GLyӧH/߼/}41v~2||.:H"5z@`м+K"nٜW^KX!x TY`F+ 鈄ɲE}RuMp7s^-vyݨ*{T`O{5/ۺzBID*T"zT`c[8Za Ìā--4/=CCkwmhʩVO OGOÈ4@ ٺB2`B6{.c@dT8Z`wD`\P[Y j0/-j-Cm]׍0}Ha;1q p%@ NJၦHZ7><#< hA&F\3R@;#eA@ aK$PA °1AB}4 cZO!@JS7 ,eZ<0I%H )LxylX`^|p]MTpH m8xR9Lt|)Ue̼_&x/ۧv:{&‰A랊YvUT"2D32QfӒ dYvDkX$r#e”ݪ`H$w= t)$JŒ }:T \V/k˻l;bJ e8QCL !ibO.b1?㸢kqxE/D:.2FޮWDBHvhst`bj'̜mub |a'$MɃmZN.D(bjsq s*= fEu?Hah8@œ!Al0& :t1&!5ig$|zx$:t#zTk"5knĐĉ8:>|Q:{?o~p?yS4Ky'ӳeg<|fSKY/߽Gn2nxy^ t/_g/>?XwioF]6qzBlֆ^>hn͵1huԯ4qTzoFo-lspؼ>$Lm[I;Zk37S9Z7<\)z>_zݶfQ^6`m~=W+ jI `ݒ7ԋ(ASGC8M>* 萔SonpDEQA2};S ɼnǻW# `d4aLpUKDB4]zivd60f p(9x1p& (.D0B afZl Jǝ0DAI  B  K lc8)"A4Gfjp!˺ h ̃1Y CP!g9b±p PprlL O6(.e /Ql͂6ra(dqi O-/KY(T6Dl7Bc6pXnwKNj)]燇ՕKI{`(`]9 a{ǯoDB07/0OO FY#\HZ߼7OAo'WdaC/wEne?% mn7!j [h%aNyO w55d *) L&D!kmAn)31"Y ~脬BH2]1@ ֮ #scp( ^ wȫa2=U0SqAHc@ ҇9 dgFA$4s!HŇR/#FC_,YmK.9Z>_[T5d"LY};E_e؆u K0 а!bkwfZshFͿĈH#rBT$Br(#];e|^c(!k:Y./H$X$1 Ex*cJ>EBo~ ey\Nɳ"䓠H 0;'w0t_<9 w*RjY(c^ߖZrF0)Ud5r*V 0 1 x0Af@J8uQGV2L YPpEn|*K 6 Cp36#eZ"An: GpO#%CA9^0fP O')Ap@A8+@1C 8!>*CxΒ &gB JG sz9U[g2pww00EbP RPD@aI L12!)ps² Hr=Y@ݱ sM xk LJz(^ 7$򪮧Sd7,|:3[`69"TJ5gd-YءBÇomn۴8??~Ex}:޿3SE]^xvKi9qrwQ/|j] e<|*KDv|^?bOF#K)Q+\rPɥnJ t hf/"h)ih7S~0#ԼRD)[CJȠ.}pJL81KwA;v~չ[v ] 2Ǿm ahs4FMRMS5s1{$;z8f`yQ3_VQR%d-xvKO<$t b6JWe5s%|b Ű" l B@Hiji.LMxo\#ﮐN^ U8Y j9J0vck%0`@Lq^e͂4(,Paԇ cXܑc39bWj- UIR@bͱxr@0@F)l̘5BbHb  j50p4,4\ SLaô&7$"!_}DpA%<58ZCod=etL09S"T@A0dtFO C!v`BbOH 1bI@dN 8 ":u+ao >?DƜApN3*iZ T\%0 2EPof< @yM9)Png>!/G`L tcSQ#c tBW,)a&rʕ{R|ۆ Z`C&/O[iH.u}vt]GG5#ԃ\(s 6 b<}_{מ#~z7Tl?K "c)E@=\>݇@;G?)qûAͶݾ'b? 3i&9VhF)Dcv6hs01W@aNE 'L "aﷱþojJ \|ڰ|N녩%)81 =Nf'.m>6a 1xXSskh+d$'S6`.N f# X1PAȒ3aAZ+9 Gf$wn`D  B1&aG2QS(n0﯃S@vpNlRnäM t\rz#nԑ]N9TsXIz\5:1$N K4>P6zi*IN"BcZ~̔\1֙9; "'Df,kLCha LLF$BtGh@ \oi`2)H|-Y FpSϢ&\ LH$a`וUЃ 0!`A0i|rݍ-=Ń1 gj D:25@g@ &iGM1滁QU8]00ƒnM *2 -@&4);ݨ^lS40x5v2wH:&D1H@5BƘIF\8l=i?W*KMH1L{WO̘s1ԡ1#ɵHf몤@Sn峟$u>>>#J +YkM5^gW/^m{+|?oN`}TaF@ÜfNP) h\HkuR6䘵̂>C%%0aYʗB צ?=[>ꭇj@ž3TE6 !5 #CU.4';@ ?S]B2C=SedƥbMwʷW(HQ=BqHR@0G=$%l'J$Xyq!0aӧ)5zYJ -s6̩֎QJI(-|r'7C$D0L CG1(T!vC[ Z:65 !f`7@s1f0aUeW8sPƤ8D"np1BҙQ (*Y*`Zv9b4S9J&&`4J,^i&EHuZy13B@֐ ݝ0#'?QD @A t HQR8# ?IwL1ldIX%P4| ׌`V1V`J'1P} @+ԙ?#jy F   *|Ղ @VSCR5s@HGA >|N68-/OO$<d}byYmoAwT Fx d%;؎9-kYO]Qď-ZD/<>\^/>Ͼ|MViN^VʊL決6v=۩@M`&'0/68|_?3q8_P$@Lj+=Ͼ֟&!l:tB*T9ާGt%&qv褘< q;%s%DG3BmԔѓ:9یa!>>vzixq;ʪ1[k胢,T>q(8ݻ!OUb:$`dArbgy G DIiI+C>rH8%0"-@5l|p{ȱCuHX O  ,}Ƿ؇.YÈpt #B]5CRDNsWB.?|d{.rP86d`d\0-RPLכS^3s%(S4\@A(#?j RcJc@xł9L);D Dnbqp4@8S`kBz@pY 5E5A%QLf:D'0[;wdK؇|hʀJR RZLPIlJIJNl(y==ٶ<;E~z?|}T_cOx}F^,uyZR_׻g!:yY%[>ZRr\["4ozX6Fkta@+{9\Aj(ᅣEru':J9US @wT A`>6HՇbڲ|3t:;bJ%93I)RZ(Ƕm̷c{l1i>1>>@y̩J46 *F@ [V`\nPJNÂX"'֪"3 9;a&Zˊ9C8 {ƨA`l'.BZANJbnL(f)|?}rD$]*I:Հ j%ʧ4<MB3鱹Wòht93425AM<4<>!pG| ۶ PJ[W ny f~B4#aP{GqKۂF%RF.q81֣ӧGh;(BD2:YtU4,3-u50%sÔBa,{VRf$$,1 D21N bDH|av$'GH "83 GXMwd!`d Ggc3a6!eO^6Ԛ/Ϗ>^X /z;f 9e62K,%4]DŽvD?&dd]sDaդۛ޿?7_wFit[^N^lkܟ3 yAxUz\R?j[ܮeǛn=SZүy6*.;(gu\M#zZ,3ɼ7z({z$1k$D:UTKeĉZ3 p C-SffPf!KYd5{bL5 >mݺ<Cuұ9nEЧ)ʢz굹6ZLmj3VQSIM LTHk =|7l 7LH`Etj܆1A~wП5Eb)?!bL),K GDrzDDb2*oCuxyyw%iy } Y^ |`@d8c( 5Һ4i\Z`rJ)C %FWX*Jj, =̫(cRKxg:4sr4^8uZ0=-`V! DLC(8M-Ś cGj'b!ff1a+0"$ӣo rD8B1!" P \-uNA| w \3G'v81Ϳj侞 kXJч#>K|;~q7d t|>w'Y?LBJ "<+:QHnS=;F0 ̐ l7pum!\2֋>!Df898a8'm k3TUf[l\w%Ø5AgRa ;=FBt;= [SBz# R>[N6f1 )W49׷~p$(rr~@@8W^Fq9r"G㘘c B&w1h]D'z?׿tw¬>WL +;*`yYz{ ٫oӛ}[=$3v}xӦ#sMNܺ-"sJݘ5rŷϐ@r ̶"~k$J&9Y4%!!r.lp'Xy9$BK<ƉRle?lֻLiI 5ZMxt̹/OE;;abZ|xζu$uX(xtag *"W6 (']OQ J\x.HvӨ N)ק7G.ndc2y, *A8B%bbfr)mp9my9á[豄2e z&=ہ!t+\X`! (+r="&,JˉB# r&*Opv̸D;1?N&QS#~ZpREb:uv Z` bX5K o΂,:)E8-, tTi-"/!̾11! \@ɉ)A|b"@`!nd x2uHq~݅wĆz ?%qkC@A$D8L" 2Zé9uC>%HLYȢ*|6Gp`B7B'% ZTPcC g2X4|AQ{Lc 1 GaC` 篖/Vۻۜ`Mmެʨu-e^]dtCm'rIP'v=1LڏcNB; yK@˯<ݥ u^޾OSf.׷ONPT]Y/kOreOo}&}_t&z~_g_$=}/~atׅ? c9bA}QǴI Q{7Y,$R,fblG#th2UFAh6F70&`F1Eg'ʫ"b:u-1 0g4 w'0n$kK^wlq:6LK6`;bbjsks0b jƘ}@Ȣmy'0iqCD B'h*ppt"bTf8v72$ {z{ %OΗ>8S"%9`!: %bmGZtوdEMX ` ʉhMx#1' [Y81fl#N!ST8j: L>Z. 9sHؑ}zzO@3p;=BMP#<(hZi4b08l$Oo޿usz8VK,~Bk^oe9͟o--|1`ق}ΰėzk {V滳u]OW< +9j=>|>$fb6'#k#r,,9v$hKhNsFW> lL> ̄\BIQpaȵ<\EHQLqyy b"k`纜00NP( J5I;܁dER/kq$ ݧ}uv@t ^qÉ0Ӝ:)R0hޝhu:uO>O9#9CMXW )@-7;m1芌>;9]:e GX1ܦ+E*@va9M#88q t\ӒHl!B 0.L  qcz1gj098ҒMܑh1n1&S64p0GՀ1 }e=UdHa,:j$$:IK H5GNk`fRC+f ml!0 Zwµ ! `H}s2eSTpF 4Kl<%FBr`, h:W8 &AbHB EL@wnH1BPH#桳x6ߵn퇿w~j^O )NfF 6@;pc,T2ɩFDΤtY'd$@iF,CN@( 聰OQMDC=l`Ua34|Tk}cH9UG?*e6nN/0h9/)WUϻyI?Lnx~Gq~CXׁp6/t7 F 8LG'h PSP (MfĆ*Cx$̸͡&ƼhM)=dJNaJ`az|lyT!'8]q1۸޵h:mY9O4 8]GLTW6 g`pwKƁ2zB>B*f}$`u)0 &' g&Cc#$IPB;!D@%h=D"'6ɻhcm֞pfO}P٩>LWN, MLKIHDQOEC1kfJ R`\NEIR ֤%D(RtXBh$GwH1}vk}>u;Ÿ7U t]xU_}=wSG58d"(|0/n2vF\YM]*4NAZTN_taxLucj}R+Mv엏nˋ/F*,K/)=|v}p|"dEj߬om$Xx{nSGcbMs`XDNY23'#D6T2 %LNu2LOD[g`CJI$YsGF 93P[Q1P 5qDSL"/TMK\Ò ;݌"עl)`ֆܺF`@>Ya \$ < τi JpL@ z:-\%B!Pw  괮9RN+Zj9;"O\P%[2߶ݘ3.lC@PJScMRNRRVNi˥l\$t1AI%eԻ#py G ~S  0D`"B=;"Aāa;! 8:a'plL=q:?܎?{oǿ?NFX9 P6T 8T z̸]0>f&{u)n 񅏙&IrHQ#vPGL:pDZO-8ѝ0 >; w}9v}n}㋟}Sy_Jo?}˗ՎخRU^_y/ʷj(pɆ"Hݘȉ\2 UE;8PJhH0%sⴱu#`r,'Ԣ#F$KLi@dpv0O,Yf-yoBj)A ;ͳ2~:zn✟?^^iswHc6aZ:yy,Fjuߒ9DYl|cG$xY",k(C6;bn>QߺK7kFSYVT1(,<75M+Q%Rwu&4$Yg+ u{ZA+MlR9`j̣'![ƅy\Va92ﻍ3@"cD;LX{ llra`=`J,\S;sPpc& r4iJ}SHuǔ'e7!v(#׀S İӸZaw;x:~}s{>?c6`@v0J0/Eg 3%@FaE$ײѣQBr]Vʚ@mJ-:9%%x: BqCo!@'4]3p ;x3+43LtRCi0t#l6_8 |/^~EН/r7$ұל>{"1ћukpjIBa%?߶m[tz8~k#C@0$O{KmĀt!lˢ)4LO koy/>?O/V@&$ᴽogW_ÃL?O׿^»m^|onm+!qN`Bl{`k 0ag/4u;ڈ^1#@K[,k]IĞ0LS4#ro]}9s?TSIa\Э{ Q+)L8hXҪ޷zC*A^TnZj+B$?|ui/\N?*, Z1d6=.r)CY(_Lw'*iP>; Q`a"$;vEg[1ua41m] c}٦>)%'!␴DM՜Rcbu^m{W`b:_% Ke3Bc JcZ ED+JCdt^JXMQB{04H_M Kk74@V>:"#8H sђ8L!1Z"@B<R}4:p/gC6D] r0,P@D#x B od N48c<`;D&gG 1|7MoǸ8w{~:lmNbrIɼL{!u= I@ se|؁`etHX%q7Xg7sc߷J\Ĕ_2k}r>>rB^i{#՜0K-0m3>_~ߐv{p>ɪr3O{o5;a\/Udyz!KVy-Q+޽:6o;]?ʋ;?7r҇NrWMS/K);.?ssb"L}w":EY>M 4 RNB=\' '"L{j昄GCRgH0gG(P:&KX:ء8)f_UKu> k vSvd%܇SEeigW^'XaXxaiEYg"v39L5v_rȂ ="ct@Wn@>cX$$H]AhVQrmc],{=>NE G쳟};v5( .Ji@`V)Ȑ%ВRb_0$@8A#{N,[\*~O/:BBz Ӧ*[lƒHP+&@#aC A OD 3FHfxBl`9c53 1H}0Wk8o~}]o Ep`*!L=rd)8BS13{<}tO r3Ihrn`N"C R^ b- 7ÉŬtWODȎ7%ޒScf;N⻵ާ_ϿI??xS 89q< 4kGŻ~E w/_jer59?e>/8 /!_l ĴSBp>vxۗ/g?{իlhm~HwظuZ"+ӻ,1^Nuo\>/_қӊ󋿸;C?rlhNEyl;e ݤjyRYƚe8LlCV,)9&2MrhVI8s3MH;xUf u'#@ F!!8~8h2_x1 º5S.sɃFK0BiUN|wfD$zn;g"&['  0R Y6Tqs;bZ 4Փ%L7*my)b;(gaH6wh2yܠyYCX洊ʘG;j#K*1ۘ<<1f!eRYO:cN-B[ DjVѦBU4"bTR>t_Ft`qTx"WXe x>i=,.0ڦQhAېp2&Q]VԆɒa-e e "s8Esq8PpֹCDT N%I3fK5K"\!#!;p NĔÈ(``D `X b,7@^  Ɓ-- 6ա̏=O[oΧ}L0)E2-M@" B}?DtIebw}~FwXP*>=V.'O&h˴*4@H9F<BXqb-8ldH+_W7z{Wݏbcc=S>x4ׇף%22/QvRMn!;3Чg^g<@GcU9L rfX̃S{NbEuDLK聒$taʜ90[Pm0Tu;|ҎgI"tx*+8.S>ݽdG9H#i+ %ւz8ᤒtrq}r% 3Zzs m F{#P)W'a~aUP/gG:,EW@}I캁ĥrw]O3 sܞSz9~z.lǵO:M擗s\&gEC`Raf2yb>Р֭.d A)[\^fPt>؟Z;^ GGpbKt I yXy;`BܴC}dB>ѭsWN+R nO\^TrQ|}uZʡmqj46RYG m JU"\|օK!b$L@| <7Ȭ(܌8C( Y`  "TB{{aZcG;xs}{~qCe凇cA꾖;R! L,E&NU}L 04؀ͽc\‰c' ]<$NG8HM%ϧ9(] DG!sqok.luJ/P;cJ2@~㷟yM߼%˷;t߽ퟎ?g/JͿׯu^~%◿G߿vHU$&1:ɂ# aGGN6a,f0j>$3)Ș LHBgv\=+5 L2QrKfxZb鑘ǦJ.%[an@,'2ީbI W::atqGB>ii3$q@ C`/j&4Lqc/҂ t1F B͟X0oc !4oN(>'AHФ֩A ˜^4̖q{~8*M:$l3%"ۀc6wc3񉐇>9 YJ+.7%f1Ņu%`"/늧"1ѥi?6^4a#"5zKFYש1a"hB>Lࣹ$EGpWdkwzn)Q5rb7S<ȜA7脅IS9 =߀+ qt3` 0 )UFtfDsCwԁ)݀g` CN?fp@~#dsMFWy~zGަi݇1I2%cMu$& T)qN$z`9rR`DS$,9«Po }2 甘dF)zb JBBC `C5{pq bOئOK>Ō?'gWyZoOѻ_v(t+/PJE`BQ3zc۵ͦ^ʚ00> DIo~_wK>+Vmo55ac{s}~{{u\^>>|=qxivOq:dO3o{??//S9=ȩ|}xՊK}|<ܥX;$"wQ#ֈvhP]4xk@3j6_Ru"b3 Caf̐XL;E(!3,$c '/wSv8Foߔͫn+at>i)eyDZ0\ c RJ=xoZ9+֚<ٔrXnRC$tE 5qU`:bϊ>mp9A$ ^O_Z˚_|~g/ᄌ? v9KNzQstIDAT &17W`ODwfd*9Ibu^:RXrp~|bq'L/[(zsJeE1M2PsDw\2׿^q }cǏ֭m^[9dž#zB J]6ct.b'ݘB1Ml̕0iL>bC .sŠF4C9*yp V^{5dzb2@$|:'$Ɯ!c(c<"#X')ڡpnwyj޼~wMAM3Q2B>VFN+WL@'"l>Q 4\1YoT&p؛ae?@8 fbP x 2STîLCY0؂T 6}@۱w?W믗?M\/z7\#na.h̦I0~=PER%u]rt"T Hf^tWo+ Ot*eYi(1 [ ƘmڞЦz/xy Gڎ'Uʧu>I0c~f{)vՋeqtD$T#O98,3ScJ%6'Y 3&{3022S@.Θ1aRM]5ð<}NeS8#rrbPkY_ ]PUN<}yq7QV$Y/ i9?,T%ee(ͫ;;˙`@]A0X.c:L4bo5F*ޛD03 F&Mh=zdsJQedR)8׬Z^Zɗ?_|uWFgMs I%@Ğh4VZN+Qoۡ}(Q0tHRktUCQ"B I-.Ɯ5$* UikӺȫ׿Bև3;ڇ玚? MBh aqhA< oVmt C1=+uF4g :݅I}<@m_~vӦm0kfqxHp~/=N1so R~,%'ܞ~ Wtܶ<&Bns?tA;_}_}~߮yyՎg? sP(~EJi1/5/Uy[LBLęn dl޺+/!}&;"8`*2$EH'$4r>[BBICBX:<`@TP@ĜO#ɗsҚ+/e9DGEt1ɦSGXqpoQQ8\'1̙c"BBĨAĤdH`HY d]h۝Phz@`\0[@8??/uW˟}rm:,9 x2 Nw.{Lm6`-uvf!_^eLô-w'V%v`t3}ճ8n^˯\.SXвʹQsjt:{+g^ts"μ 6{"ɐ8FuwO(Iiݽ96 D{/[ŮhU=2i` Wzf.nd.YTJ=.+ab 4 U BC`A'C`wl զ#88}~l_ߍCCw 9ƪTL;We% NV,z,wٔ fJ] =S.@LjjĴ,OvY3=lYUӞτ MBE?9! rwA Apΰ*3ZPQ}_W.iaHEHW&$3#n9N j!6`"oS^$:"50ƱZohg??o}u6w^nSw/|?̝*''7jĔpgp73K$guijh3`I㋜PnmGMؿ|ϓ $f=ua:=RlsM]M]ǫy?~^\JSgjyGS܃ j wnZkhz|-o^aCtDظeMebo y"\~03ҴL7Cype_\;1 2at8DIuvAuH;6pGҍPL{7.p"Ds=}3XJPĸ]-0$$UK(N" եFuP`9,w.3&,(E 4DrjQUh/(d|B/Nl Z `Idn E3[x8g}9Fօ'U(v_ p;BX;,E[wJ4lcY!{vonFj󺺤!RY1.%{>)ki̧8ٰ"i:ǑSDvEjhS!ݑUP406[[TePb5%rZ}c07akp`E'J`U!nnjrBDC9NqذwDSޑBftP@bB~ $2A=@XZ]Sk Vm~oo޿~np2[48p| %I4Mt}q uE$֊ze2Zp6hbB`='AeR1$,D!!-[  cX /ȔC- xlt||_ۗw6i{b_<_Xm1V&q2;pXOYn-kYfO&rˠT݈Z?;!l? m]lD,jv:\>֥6G)v{4`̺{:>Θf}wuw۲QXg9Oç Dhmnーaaܙ4ёف% <(qᖇͯgh' )qpy]z d$o= '^fdn31nĝ4s'àBH8[5RȔH4.*IyUETTPLv)בxD ` ` j$s&ќ#5LHٻ80a)cw8zp_wqxMs՜л& :Į|@Ql JI @ El"N.Fʹyp/. b܍LufX!2N*kYe,lTe֔R0u?I p yD1˜$ғv+þkΟ#7QZu$!7nB2lyP@@! F͚th13/za`= ټ)r2XIFw$+§"Oa.CP=ЖH!-jt$ (H  kUu~w^߿~k7=.] CcշoNn=aԜaJdvUVk"TYOE;楮k[osda> #9rx~n0\^id0p)׮\2$W=zlV-x740 OǾslֶbHGn6^=}0VE?/nᓲ؋_Ze \'4^}NA:ue k@A)yŠfD j4NXxm=d5f%g"l$ (c鋉ڜtqLFvZ=(H #h*^@Jy9 ȆqCX;2zZ5h)v:=~pv2رVLDU bZv``BN Ť.gg`r5oZ;SKY!MƔnn8%f8f3_Wn(J9kHa5!`@P$qh @LDjɢGC+GW{ջ=Gm'DHtȣ,9Úv ijs%Ьud|A |Rb0ꬃwCή E 13dQeW8C;{DQd-8[Ʈܑ5% 9`,fDAxTɉtuF\fs|GvoO_~뷵壋G7zpV~~˯~)@E$I$R!T=noU8_0Bhh=+Ic[WeLNk.D0lx˗ǻ<9$W/.qMxQm9x>߾_"lu=r9RO9m%otw'/g70%l>ʱ߿ UJr<؁%NqZg Qasec7!6y ,Rܻݤ;9 ( 6lf+twn*a%FK A0Dڤɉ 41ld۞ 8‘ YYN#Zٲ R#0H6 A`y [ ZP !!"ùh iLAX@⒮Hx|rV.s۷pn`f $zroN|܂} \Ns-qX'2e5bp;f,Jx]l9Y;g9CpwG6VO%۰*!$Y)|h Pf,䡾Dݢ9x@z^Nks vE%v|9Ր}3o4Fmi>ֈf b V-`E#-a|vo^{=u{< p$^<11dtRBdL%D^R?N1&C&v:Rǚ ;.{f?;MSDWVBё"DTA(v\W4,Aw1B``H'}4Ͼom;޼V9e<-;O!|/|8XhMj t5OKjx}XVF"Yl #ѼS4_owq:w\Oxxo+ggWm}'NgO`M7o%] ,)q~Il^lV6+xz0#@~0~Ymm 8Z'g˜[Nv\Y80uʬqjIQ9u `ֶ"(^c6JEYHE9()kƉYWF1 l [ա^ H8b_>*#WҎN:!ץ4Tp' L@]RrBIZBL"X)TЈ0":9MJl>vpx 3KgrgRV-B]P5g>2^\׻%z'u@zmP$C#c,XO~>|NT!41Q0vMhܲpB ͒O0(zcHpqq-uh4O'aw0 @bk%#T?E㎽r[xk#؝{D#e?.nwx%h2 h]N=M c 1cͧ 0hQrsލɖv/nI;6ҁ"ܽ t*ugvZֻ;A>2p5. K?~Kyr{.jEeFq)Zv.?=|:l>۟}lx}'в% \n19a,fΎ,2w,<L< ZΒm`v:Uk.&}W=7/C1̔hF Lg&1{VՕ3Kl(N9"5Z+x?k?J͈ݤU={G>C~ v7am"% w'|Ջ˯҂a)I@E E )tOp}yw=&f ׃#)'^/.ɰ˷קzhPt~ֽYz>_ſ{պ쩟NoF?B4j$_}6.ؑqYW)qн5!ϛ]lz?/߻R;lQ>{~THİ.ȲQBS`Э&I8Bt7k5d."kXoBTL:w-pO#jIi˙T  T-xP`/E;]9օ'ILdLy%vD8D,BFё҂AR—BVJɛXmGDfAq?+FρCP%Ȝ d@(00fGb`f' Ex|n{ feb;'P]Ӌ붂fk[`-ݕ΄f~@.ӻcxR'v:aɋjf{Hd9^\M|<} 2X(5;ԄD :f1/3#Y ס{ cMt` p `T $sW}ߟws#)tck'pu^P3[GKamm^m!0H- k!2`;u-W7g@Bq8b#a9hy,'v篞ur{bYH0 y;rS"ȒkE,EVzP/JdUQ0E;쪛Bd`/6ΈR'+V4Z S sFE4L:v,"J1pwL"#O>^v#OHK zZmQk]jܯsow}ŧͯՋ_W_>)"S,ŽB\Y:_ n#o- YRv~ܸMgOWPau:~׫4lK;Xr_O؛o~1ϟ? \|(cˣpC&a٧y>s,-<=<x/߽ȓFؼyߌ쳏d9?]GU5DKrtwjwI4*m0m]܄Z"B^[`M>Fϩy l t\{]G%'&ZԎ9z&qCL*b7#i*rRHś3=ONE5po eD̶۪%VG7AŇ6)#$pttHVny9bfꠈŃ Ja5 @Nر L(#8Apa@nD {SAjϒ~l?Nz9(G t hDsi(E=Dˉ0$(a݌Ortw![)p?yxdh{)[V\Ήz3p'r]P1ɘ~E!º4),BV`+0ݛ}^v|{".eDНGkjz9 yΜ72@ }$`+"2s $B k`a`^{C?D=_}m;50@0fFܔ uPvUCs <)$#<"aȝŌS 羬47/*"nH[4t yND39P|G G17 Q4i\dc}}lw=pn6-Z;Xb|Hw?קwk6s )89`+Hr.7t{w;D2KE_xpx:=_ߚ(7Ox KT.dp<۝Qڝ+rxtwq#Ce^$Iwq|[4,' S=n'|9fиzU\y?͛}>&6EobkM%&}s94%zt 313fFHa3i%@?@ :8luYi-#$dCR#DBʉv17173ꄈ֫XAa'5 i;fc<c;akGAucCp:R` t0T0l<{ܮ_BSZkD9Q@kIJH"+:t!tr qd3{gz JcvjRA2`)EkDޜ Wd 5Iאbm)962w ~8xk(A혔; (;8P3)Z]aws_Zcwr.|˷,eeHO,s6VOZhFcaIkG+d%"Ća QZ=HDaЅ(mVA-J\(pR&fgQlekd@*o<i>Y3r=hix-~pl.?gޏ>/N囕<`]j2܁*dW !H%mͫ]B;e"a~E$uI>9#u0fE`3+ݒe(HQw 4 Dkvьè#BGX׀ C)1q`oIޱC5u 3C94pph8/H h@ DL Y (!tPuD(At1 ܉r P@bT;1 &+\\z/Dm ga^xcx8AcJ9q6eAWb cG_w`-BY?P.lm7=a1ū^j@)9͸67s2r0&ڄG0m^po͛<]|֖PlQp];{-lP}ߪ-v|mdֱhK~|hO.|ԛC \u5ƍ|yi1lE^k@aPwHtITw\rɥ#0&LbKuF  Q(a+4GGVHyx!(c&ĺ *I4Rʸ-ʨC NȽGOHnȊȢΓ@7&Mʱ>]T45#hS$P98%` l`#!S8!)zdY($љ`D\;qN HȂ`F!"T@ )vXw >;?+r}s:vgFf@Ն7p#5'{{2/HD=b0KNkqY\uˏ?JI\ h+Zg;:HA¢1]u A]FbT%YbA* EbT,p`4#ںS@3'D]3+82`1|I!UZ5 [HW|D,  8# )2(`4`@%!x4~X9F$!Da}]:Hy[;>|1Jo Vv WIISL6 0=KZGuN(F: ey J3CJZb@-)SsvZV2=2 FwL A>(ɉ[3s@2% `G r" i @1& dݑX/P/2z[!RUlѹ1J o8~otXYĺ6"N k;+,wTA(2 rJY'8z*7^?OAY(CLT@UN P+`.FL@i} lc6W-Y'@G<\O׍R l-T,:*A@t=fı?1f_y8}>~ND>Vɕd<Ř7cۿ~t81Z;;Ֆn}b|w_I׹x݋͗oŋeA(2p8=z,Ǥ;[)[wr!K|S-,';n wN+6oȌEZԑ)0|*( PyqDNnA5j3!Ę(~z@22nUG l7`Ql €t\p2E"%Ă^gtػdXOȌx@o@(L R(`7ͅcH B=( $18` :q tD9P   =U" z Ē<mn<YpR,="^=J59e 4[k(0/S[`fj|rQF- cH9A~ݲSèf9!z[$&10b覠 駠6(8Ed~A\) mS C+A5H1mJNqY*2*-7+oa9v_="?|φk"@0CC=d@4D B#@ գץmm^˗|U͘6g)j?+kfi7LǺoׯ~{8\yi]H Ni01n:y\_<Ǿ?ܼzzw/ЗIq\Z=݀= X7Јh~# ^3j#+Q{L*Kf?i] E NY#hLVs{r|<:w Lfx|v_<9{G}~!q?oʴV->==}M=O'DqZM Ԏ7Ks`ּ/G'! X0%;4'*ǟͷ {)<. ۉҶ;EHX+{w;M`'b=\\dL4.P! ReDGG[U9勍)Q#-+ {ۋOtsq ZFL@7KQyꠄ #R<j]}݋߾\rnq1N.%DݭZp' $BcU{Hq#d1Fh%fр? b;Y<9:"*#FGiQ I`0:䝤 i}"vY$86,S"N c xPU(,n2P+԰X[&ͱ?|ַy1zP<:E4o>@ɖC9uh$hqˡaϷi3A~4=7W۷_<_Qx=*$L}}}GIos`=N6]\yG<,+>.g%Si}oD,c VsOzWuixgo޽nA"1ltu0xtt ؖAё3L›!}R&LSyLzY{=aFp: !/ |; Df m:+k]3sP@SCWIK +%%ȲRJI, 8'ɀF15 B)ZtH #ώ#ڑ m ca"`& Q3Sp@ a1'u ` wDJ(G H!>9#"}p‚$ "R7ENAJi!Yܬ.kRAe3W;Z[gԵ(v7x6Np\Qޯ^!GxEkz\2]UFY|5VbF;VHȱAHa=18F\RcM`ʄ kud}g-``p9@"vʃ@+9^w9 ũ ի xlxsX *Єq*;"n#vpV^ݿ/|zy}'^\rĹYIWgz$T F#?Y8KN7#a'6*e(FPʑK_BȈZ0? #peIM"([ yHE QUaT8LFa3(u)@P;Y;dfLAd( AAAA͈~op߿y-g@`.CVQ7` 7=j.IDO|׿yW_.o[@ӛW~%6ohұ,4nwO>G?|Y׿m(Ů~;Ez/e}h.|Dppa<|IYJzme3.~Zn`h]!&w|wߢVJI~wփOr߼yfQ/|W?k]}zyN9j$J=ЗgRIUSn1:S0Z1ְ1l55&%-)3 m3,3ŘGFM~XۡJ5(i-|cx8#ʄ aPcoMcB 1Kv2NLĔLLHс @HЁ` Hʏ> u`؍- YXe a#k`lB k0(S`D b0{hDD@Vȸ =Χ lưMb-ޯ4eoY`U*aRu1l` CFvG?.p~J2ӊZ`h<9vTfhm5&f@b0Yo]8AT H `4aǎ,fVu儽`@h5z_[*et12& ,4$i \AA؍0V2jP b*>q-!N}g?(ns|Omͻx>/s"B)ކa>Ô` !K*Ӽps?߿?ߜz87w_ͷ7oo߾x^Kci-ZbfI4? ͫZ8ho~rYEb\50|zCLl( ɥN- OSޖYD\^x`q}՛ x _r'^nKZF `^7 2]-K0[ q8T8pV!*=q]2!gQf󋲿U5"\}Sb85!OX=|NXgDNL9g=1z3߭)#P V Bg63H7O؃[+bmhTa[)Ԉ9Q!#pbDBXr#7#b@,@Aa y FA* 9w + %kHNhAP >8w(G(AB5ֹk$=і5c ݝ,*; Y~/_Nuu -PQR)wV!!Dj9bI,q!b 0 h ypV5:&l4ehTDЗJᄝAl΢&ة8ʝuǟÔJQ$ "ȌȈ ?нٽ!׃bˡ/^oa=Imkqӭ<5yAJ3"BȘ%I@mr밺pWI'u*R@:Bs 萄3`a?BFt?V܆q8/2&ib$Tb:rʧI$S7E5eMW39rudze9taYn^׷wK_o1k?O~i1121Don5 sPoD6HLxsī7es.P^U~8oJ{go޿'oB{{|_ת[V SHI,盩/bN>$lФp]2i5JJq^@aZs ,/n, A}HMDv% }\ ]BİNgI oQTWd֙=EW T@-ցS+Of♰ڂ9D!5"1܃Q{c'!+A: yE5 APa 0I!nA l;] voݧ)`JJ# %R=PN)0A⚇t{2_%Q? 15U49$#@XNO7o^V]#rewXm\r?&o#|? R/ݴݺZc9ħt/oշ/{}-=*tǏO|}F㴻@\[PWVwezfBȠ)ol&ǁ&WNner{#;} '?~ş^:,!"Dj) B"2r3u 介lF׉X 9Eq_¨-y쿹n~{##Mm Jfdqan)Q hw)1zLۢd9j\ѰAh?O8Nb ` (9 lŹx,u9ek˸6( @bdF *vf hH ~ Hk4rzc>_̞>y:fwo F*%LQ8Eypm dɁ=º9g4&u>/PP'ٰ2n5kpzYNnZѳtPɒӄ?moySgE5'`p-UNqvHҍdy0a5BGFh͟K+?u0$ó`sG?"n߽=yzۧxo}2<.%(9k$dNֱ xA8p"f$A(8(M=H!$RE'ˋPl) ,R4;u A77t> % jC”{5p]Ҙeew5eRd%̅$ֆP*"9j Zgu '0+afPs`2r TdE`Eu#dFF{p "0BcԽ#EG1/}H<95 d\ CD@eDRls $03zwoD։'fXXSywss} N~HM-k3uJk5زy+"RX yv8 ,,Rrк2qF`|h $< #{G+dm l($@&IAɍU"f`Ḻ&_ IDJ(A CWV@q72۷w}`3&UJDLa* cH儺Y7_Huȼ;֥7Yթ{Z)ODQ(ȉH-8x%#:ja )N ١|4wa5 JFl !rYeKJd)2!3 z8EbP>rݟ꛷;~g" \*,ڤ2qJ䪐4 @4OTMM:mֻ`7c4$ȚkRx{RBlw-H"I de=0V-f묞Fjme;HÇU˴kSť *%ِwvQ[Wr9WեaaN=Arpy Ǐ?_tٓ0=J`>nAF>]QSAxP*t>-K)Dr(aD$tuܴr3ڿևsAtϞ>%˩%7&~w}Uyxh]#gi™Hb Ҙlcm14E֧VڃR*CKe"Rb98Sg4(bF " DělC2R3>_o^o x]k9̝zN 1%˩SKIH6J!<>|b4I4a}~~:}7{eI~\:\/zyD~zY\VaȤ؊/6g[Sߟ܀}.秵<>&qRֹm^GNymnEy=_ï{O/W?|*jje@hnJ 7ʠ}$=UnAOU}y :Z"tz̋|yacOGI9ORY-0sذXN YϚ:уJH((ou_~`sy:V]8"q2[m}QV8pro$ FYΈ<,ֿ?GEyW7_W<o7?Rg{G~s/5YNit{W~n'a a &JcXQΐ`:9Sb.ckkON"|>L%CQ&dD(P?xu6,q9?d+Ùs)$ON$<|at:# wd)6Ѱ A 8BPNdwS3͠t.J['<13s(Wny%BHHfp"D/pvĈ%lR@D#rPPACE}&HN哪?g'(49Ǵ cO}$Ϝ?c1g[7[) -NT yg$1%#&ٍ.8 r x18የFRq.ɐ6bΘ!" u#غ=XH0hm9[S5tD,ei\j&N d.ATd@ P@r*DDs4?>e;|~o[87=b=KPtJF N*TJicO&0ilT .KьmXw6ǘvn SΝZX+?z4dΒitwr }7U"H)-K)IBDɷyr-2@ƴoc,o˃_Wyoqd-12CuEAPJ-ZcӏyTJMqky"rz|$!ujZڲ&Q.T{y\o.,H8ۈY '?c~ܠ޼Y/sܕww_7riR /FԞL]kkTyVm|OHl7OŚ]39Sx+Wzx_Kтp0X0 ]wRcn~TfȘ]Eŧ!,Z*9rފ\7O|&pa2 CG0ܨݎ8=iO :k N!G~DEٖ *zp˫ID֌,wH24e& 7&7d#jII™2ґ;2ƛ8Df!QwvryJpBi!<e$3(I$(E!YdT!C'찣 gXg˾wLrTF6PMdJh]Io1b2&'D%<+{Z02k)Ӝl(S{Fj'А¬n IOA$8gեVRWxIj"SY(+ I;&$z<8h$%FmNX0_^}ure><%i04-=&pe!h檕4-^knǠ%sFqb$1:\ȭW֑&qoo>L8N0$4)֠JR%l*-ɮ$MӢs^VJt"4#$T)odNnh@5H 2h敺0v 8vxSV>?/%*R$XqjӫpΠÏ~06/ݺeau)K6-"]p9?}j3RN،H'ZQQ-Ks/VNW'YX礤>ZnJz#pc5Qr8K _KΫG0~۲rѤUBZ'oI;uo7ͧ?(˩dx[苯.T 3bϜn#y>&'( TH(+Ed`jLj!RgiiGܷW nG9w.T|v^\.SV@j=1}>g#P-}->S[ (#'"@pgrѾe8 =u n9HȔɗ#3N;a ) C(˂f*Tg[6$ +r8(zO*M&ҷ01cnA`%LpOĖ3SGڀ0Td-~E]֓+x1n9`BҏC#@,rY}`$G\rԷ9×9FǸs Dq2~DL8dI8&raXw)JJbN*CDKu MPxLJJL %pBlVy93y] ZA$HQ4I J`Ix"gffnAw4Æ c;jis="pj5+"Yk+J4,쯲*)6q EF'JD,>؎l6űRq&(Tnm@9;92K z 2)¡lQ@̙Ng J )p:<OFZ5#-sS%Bt2(P5S#L,IiDg>=oDQӸczhHL\C|D.k}oRDBmĭk|㚢%4}|'Be^)8K=U^@Fp2}cɦTkp?R]݇}d_ÿy?J_~ՉT8l'0PI4̢+b j)tͦR8t)ESXŒxhSaH螴>_SC==@ RI;Pޟu4!z>*w=SkŽJYE3Mv緗EΧR*Q r7r.Qq" aJ #@O>( &CF0f rOgt'f%r8M9( KTF7"t j82f[Jr L4Ig_v2E6 2`IPAHU~_o^H`H-^*x2<0"ąJR7,(KDTfF&j~j$Xc&mXSkVӤ*>)Uϫrqh nh4oYa:ap0zѼ?=eF˙ M,3'i,gaRRfնJf* *@"Eu3evq*mGXFcaч\А.적TquRZWʧc0Z"UKrz.0 0ͧ~~OLYP0ҰQB\TA "*TU$kőD[]5 ,)AQ9 gip2 fƶyNZ$gQ!A'(v|< v{}mۧo>aEybmL++ rtU&þ9Tm% $=fRx}n k;jIs/ǡQ>p:"qtʨ}?+Q|&fsRf."ݻ}iDz|mRwq쒬˓콇[HLols'"gذyx+sz+GhlNBCLA;B3qɘ-ܲ+%\CDraޛ(쓹2;IܐH}|TR !a@ɬRW#鷘#,ǜcnڏ̥.zy\R +FHhuU V]ii)KѵhJXY;u!N[̙ NF.Y;Z=+xe}G EJEPl~ \Z8vDc&#ʖppyL8&BI'# dt s2sr v7(h?|t>owv3神j: -UA{.Y,z{Qt6W"V9S#*MV&嵈P %u9O?=-+8we]B(^ׯKyϿa\×>}|}vS]Vue~}ïSJrt\_7o_w?W_<<"$d֩Bay[HwH*"le!j)AFe܌Blm;LOhy~no}dCy"Bl(ʱM"ӥ1MZ*&ٱ< 69$6Ӿ)*%/O Scx9Ols2&iPl'Β^T"g##Y~7b"30Y:,@Mpp*qz=<` 8X ܂&K%WɒrqO A 4 %}wL$r"`#hI8W>?~䫥h}jXHO#TV߻1YkЊئͶ &eb3-.5R⼮ b!15f!H1ȽsT!d[x&Ph1tʐF;%^\JxgRkKm$K#@P$YU-Ӥj7j%q'.L EtV)fYjQRp!=%~ߐl__~>^}wzxRzዞސrwߛYX2 S]Ln{64EۚӉ>Esg^Ox7d(k1e)EI0Gd-^Be=J=B2ֳrʬVR6}Ψ$K#f_'3CziHd9ca=mrba]$ׯTK*R}V,ғ=pBb7D [Gnג"Iɖ4BJbFfZK8C̙(%9rBvqK$e$4id -dGxKTBר e9w0 [LfI388. 0wD';\Fj ُO?xKqLyy 9…mS9OcLCRQ86dz SMXd Ր䚍,D4.!pkJu}DgnYtW=Gݠ*,x͔pɺչ_G YGS"m) ȹ'@(@4D#UR`ȃə=[{|CEX^Oe-6C$I!Y( |1TIxVvܯ[Ȱj\N hAU2i-j)n~v-:=-C[P0JI9P.@D(U6QVSLbKP;dI׋=ҙ2\.FΜڍcpM#3ҿ}-/Û?>oiREqkY)V>ӧ}_]߽z! N0N%GMqAe#ɣhmC 9fϽOs2[{Z/w #`Y]"oNoo>gρv\ŷpR)S84[>3?{8?4=ۿy=d͏$/l%劉/=)kXSTVV) y! ;het`~|&!cxץű KK4 Ǖ2*i24)H%gk>a걗}*#s6r W2"$U\8-j8Mb { }/rp(Hx"TN g,IbњgrYn|!;a{;[d1xoGSMĢ !|0A uS:A!ALqjI$"I 93pp$ ;<%;1BAJ||gRs8oOtKܯa(Aٓ4ĺrLU;,3 ]2De}\hxaԷ)(lBbj)gaaByb &3ELѭ0gļNlYe魬_>>_ $fY3Á ar5(=AF zﷹIU*Y\~%s:q6DUTBR>uZ1ʦ(AVE4 1qvC,CqNp~c*)$դ$ei>cRBeLz}}a9.SՇ2o7$%vc1 j>ˉޖfP__w3FR"Ѭp5$ O_1HrԗgnbhQEhOo@+7}XZ[DzZxLeڨd:|._~姟ylX|mMi9̱TVœm~rF19}ߝ"H[d@ʒ*H)R * erFͬHOe?ONogI˖օ˰tMM'OQC('cY90KIDATcʃ'% `)H‚8 B&8S裮U &q6#b5崲p!)2}fg61c#XaYd*r:-/Z~<-fA `e3`!4ݶc~ÂQZi>HT6rRYdi5rيA:1P;M2V)haEFӃ&8~#2?G܌/%`L[Α(BSqٷ3>c*[%YbهZW̺gHM;~J3R\W"f0j" 1>]?YɄzDRkW_vBiK{r\J ' 擄 'ͷPq, 7t,@$z?~R~/?x?r^\yߎ]7c3k;q{ޖDs铗Z.ݷw~z:s\|?!3_ҨUpPsg_-B,ur\iYyd,m=]ڒ}=<0}L"GZ>R/E[F]ێ1r)ؖr1 fɩam+?Z3N/.go TOX}u=Nyj]Κ1>Y{:>Ǿ9h}KM+߾{~.2׿o?uB ]s*tG :D m-{c"qy#GYϗ}-**D=62jdfڃE(I1bNմ1#<]qLTye}$߃]lፚu&f,y|o6;Edr'̕|ӣ~e-燲O=ʃiYN5)->zK\VRBIx&}$6>_sAR[Lei8.22"sza #<VQUsL( >/(D5&ߡ]WⳊP5fQFBHskX.h%Ń."$=cy$i *Y\07gD@D ڣE ex|}7{_(^Sa^]XSw]WZ vtjvy^ M.M=YEϚv+MV :J=oz.zZm|Rʈ=r>w(\sTZEWm|Ct}È5^/m~?zv'[nKδ۫۸v[IN2N#솺Һ<g4yQ&jA6IecYmJ9|ܞ@rUZ xy(/e)1d#u%O¤:MxZ$젳R=$LZ{@%VH. fWt"DG;8Ǫ!%bzB-&w$ohfqdYBp|w|Ͷ &ixɍI3ĢȤlY 4 H _'en.dK2Ϣ|ݮ[Kx" up_98nz),,Džt:# -KaRUM*[QgYhrHF-w6) 4E>saa7ۂR˸͚ӲVz8PNOJ}x*JyKC^Jb  .4FF$lNn# Ocݏ86Yei9rir&QHq bx-LGI T9a]KܺPYl"XiH53rNVh*u>ct+$d}""9A羽2|NZDYr}=LR[9-b{ZDKx PֈߓgƔ'IH"EJ3f%X;),"D/O" Bu@QW@Ǒ }m/EQGb{ô+I<<Taൖ7=/t@,j#h}{1a3WU.ຂf߯OKzF~{>-t[}:חv~#v~}yps6yd'% w[~>e??-O%PJmcsXm-v3T/33p)ϐ`vDN Nt͎8Z}sR O;e y$p)HoZ\ɋ7{ mKmzbSuLc&6ǩм#H,-

    kY.$ZBf& /"Qx9RN4--o;=G= @ҹȗEM3h.d^MsLǘ#ӻ[gQm:v\>Y㤳ul &uRGMp8*bBј)E !J<֊n a;gˢQBFj,-HTH9 b|C6ȏ݋-DA|0ZK&jODǷ{}XE!ptS#dZ4( ke~e7W-Og$|ҊG]`A舸y֧O.E3&xpz(qlySZ.7_}?~7we铇xqn3cm)$]RKt'S^Oy _rqD7{@z;_˱աjVv! ƬyjiMz҄9E|w"I3ՂB%0b*̚bR”*pYa{A(sj K %TRHjd5&Ba.QGXs#KK5Z ch'džWS΃m0UGbeBf3Eb'LEt:94 HrYW+41HUʼnTH< fRZrAPոB$ƣÇ~$mS%&݉Q*mJFD5dq OQ­*{ip^&M~ĪDDǑ3X67Ii9r 1X:}yv7Z'9z8-S.G%5BFA1:2U#ڢ J[G:$mǟ~\|9Rc᳊;9f}&J4@ c$ju]ڲPQqۣ\.'ǸM^*>1=Ink]7L=eiRh"bLJw~F3-7};7u|%q,v-='Ʉyy̛r_^'+G'e=7\?el[߾lz:9h@NҔ[[3=Զxkk&BirGU=F_{!S\}haLiY[2x=;^^.K}Zk>l6ZtIG1q$"fx0C4 9ٖ pNW7"32i*4eu>8[c-.`4|0)g1g@4DIp=JJUj%Hׁ.3Aq')%39F"$DhC@v4Iމ`)B13@T!)`DR9UO~OӎHA%Yj.pi,f K R3)3v"eJΧ:3o:zb&y Еwz15{ "p05N9\Ă4A >R*3*. `ܘE"8P',A.t (Ikx?ގ=gFq3$dl%EKT)OpE42H 0D9^H\W6dR|DM#U4a}?Ƹ}"iyzv$cffApm<`]CO`AnDcOtaX,H -̡ҜiD c ]9yKP O%#t3U\KRMf㳿ÂWw>~`kDžE>y:+6yuCl`6Zz~'|1mfgKVZ-˹)u#Adz㦧Ojkr8sYOf\r8S}xj 8!.o<DZ/|mFp幛}WMOh;];ן<6}É`U_; )1o' _nR.nc!n)hF.mHUzZ,fn!uxѥsђie尠RJhB{ZVJJ9IEġIJID0O"O^jR 1' GI`<=e$YRB xt6N%<F$IB#y!]$9@JZ byAeY33pd ҏ3@H8A$M!| HJ-=;EJJY0q){Ql>>tޏ5;A,T#g#8(z*9\#FGT̥Y9ֺɓ|ボV^WH9!!jjͤH^RQy qPB'Vf69s:P^3T9Y8EyHGQ W)JGn-!X&bL3}ژERjpS(^cE1%b32i'ih̜9Gpe]H% =zRwYpvQzsI4P:d,ȼIԚiS#|p 72Ѣr9s~3GaD~<eH"RZm׬'dVSјp <֪t69|??M0WPs|&}/.?v긽?{ٗ?Zz^ 'Ew?N?omE}̨L"7c;!wӰ1AD3氣kđD 1 kOaTʞ3O!&(]dhl,\[->LJ*}̈)1y6Iqt+gDAغ8uJ(ZQ*xUeUxY=mR;ʤ,ΤJF=z$K$9Iδ; &N8 04gkVI%bєG4IT#y-H$Kg0Jd:=bD II"%$lɁDD$-F3PW~\䲶宓5z*t~J<ɮn7\Hb%)uYp:/>%bc6_BAOjՌN컴vrnRv.1GL&J!;~83;%=#KEݯ9vduYONz9\SU妥X6R%Jdv`~T \3Ɍ;(@ ?(ïLJ[2#Lii\lۉ#Ȋh.F| vJYzRxPF1YJ"DVLe1T4F֏:bN~NC a1(lDN"UU4!iJfGm"/6Ɍ faI|N"A9A)xF0FF*MOFN{*Ac__}܏Y2ki{UmRׇ6囐jct"q1)]YJv~aCIᙕK9=l/r4jX}Y%%^oG ÕD~!,ᄦv:-=q,>ﮏ:$0=h>1dm|~Ĺ ! Գ&A2Kw/^]R45D,Њ݆w~Ci,a2͒{KJ&|x8jsm+Ǒ$ &MO`ET%fJ: Þ!G (= 9 X3$irL+CfT}C& d@3Rr РL.#u9Pz gR<#;N(=B:O4 " AwJIR@NI5pa`Kv0h("f"@,>'/Wq0D$@r!SJ]ˑKs *VIcҒtje) F~:x~R|5 rMΝ.K!L$d)4{$qGlR[-(TZ>Q[/iGjuޞ)aQ2#ax'*Dy$|87Woz"-[Q2E>MFimn䜥ONFL'Kx$L'J]*h N.Hm;a 8a}rELu0d5R")e@DLT}i&&8{Nn$w:f4FJCx !#\H.I䞜GbrH͢qw'?nj(tZeƴ^[-1ΙtF u4T?*YvVEF]P/oʡӓ{;Rr>'f5uU>mv\0|:n1z-tT+ߎyҶחߍ~JV_~拇/ƔvY7?yxsk~o~?6#"eAӏ X֯7c8'9?K]t0g&4.NN̹ iEc}ZΧ8EJrC qфg#s@Ѵbz)[쇗EAIY33e>@DJC)J5 jӈs܃QV,z>&\AE 2;e&OJH(Qx ȐƙD*Hr%0&!c8=[Z')ɜɧ$ُbH`e%zN*La,I(¼/~_o67*:]cTM bp']f=Iү*`{0=m=-0i5hMa00W?XJw>=Hq|MLа6]+/Jy2må,L.|5e zj%]-gj_PmA N2FZw?bϗ|&"D0lhZSacuJV![O4)eIvPt$9rLM|2g%ى[1G$>) z蠁U \+OK1>R0F[)qYJ383Qă˩a#랈ֈ"TY*dFhJU5IL$w>@4-@$h  =׿iHZ"]}툉-BoT S9-.5cEJ맏?_>a)d}q%?A;ox~jcUڣu aaTnuYNUM4$Ht`hXᲐzPt?ưeiE!e.{&.a(,mHvŽlc:zwS쯝[?m+=FLhB~ vJ

    {ɅR4bk6~H &KL9d0$ut=8d`I,[`2Vs}PE˰<(Utєe9Eׇ74G!؃Oӟ5۲dWzؘGZk}ι}DPQ4$L/E҃L&Q$"*{v{lp+c1^}g䣟\m}ꯒgSy/99Kf]%Q۳B-|y= E"S*(M(C`N:1?RSJfnD.@c122,@3S)EBe" =Gމڢ!8D5-6:~%u'="ܐ;avQ I& ;T)Ҏ]y>@y[NcW˗RD>~khEcq0n{lVwGرqJLf\aUnyzw!7 \0.p~0,Y P',8X/ݗޒGu>ǧr;~\n)\bՎIB!pHAL#\-;7RO/_=,*ry"9A خHGK|C¢T e' Lە,A! s`.|d ;23 KdE@wqaTQ\)"9YH$wLp}@ CF=W pO30;"&T@"IS%2'qa!`IfxV[er SZ`;2F__>6xdP"Ho4iOXwDG-SZd'ƍx>gӢ *6SZuZ9bۅ= ?$`0:-n/Ab3KRD AUJ:Aj  ]a9}c0ͤ(!łr7R"~h5Dw>-5A_p1GFI.Sd`$ڃ=OKW#aʇ=oӪk-ZjvԌ6r`8RD1 oI'BZkJ*ѤD3iO?F41cf w<$9Ih6&䈅u2C:u"/Qγq:SYγ5CK<="y}ufR]9i$DI+v)T??3_y_yғA(P3K%{>M*F,:C6@ hQ ]}>mt>?>MU˫϶r7/^tS!xDKiRֆ/_Oxxiz/>{g_E[wWJӋ]O,adrnĐX*¹,N?nOxv=,6’ukuꥸ;g\daK1JGy6n4apLL'o42/8֠}g8M:8!y Z) ql+aPp WB̓2[ϋ\ˆrd=.Sr}_ʪ$*HpHDuEXf=<,b( Ivbh`wpt:7bIDIbx3gfKR7$"B )I)2 z]NOi4EAkk.sF1ƩS(Cig؞NLeM)AͲlŎ.[AxQH%7'j E-GfD- l*$vR%Ju ( ĠHu߼f3/qWNr}>4,%;=9AqEK?GL׿TeDӞg/^ֿ{1OGp*Ἶwֻs<=.,@ױ>S[{0ML{j@t2<8r=N/d\R؜3hve}7F)C#Fyʀ!Hm22#!&]9 +Vdea6 )"pUk.vOtJkXH=Jdf(QxFV~̾Q` Hq,^L):"wI`)N$IP%NB$%aDPHfP!)'?u3); * 4DINȆL"9?]tZH1=PJIX ->n=J1OyGcM%&/ { m;#X0A2$\# $˸a0ÉOsAFraX9OM@!R'3dA. DE5Ccm}t&kyڭlu#J-XsA)F $E"ekȼѓ戕nF3kY!B512l[Fiyir `^o܏@÷C6*: 1ҙk#gWyNԪ&CءI#R(#ߨ,i;r m'>RŚp[j)O`dYx1ʤ2M͋&lϒ8 (CSPh'=v<8M{uOxo~}4-uq/&3\k幆 -O `It>X)g0;={NPQ(=8<'qP'4mǛt]GN壟<|_ N}λ4g@tqo^?o#\>/Gu~خYz|V8?m{7b}{sma'x?溤6tQ49mC\ԏ7Ա/~+#+E#"IMHGWG4TidN  (L# !PIJ6Ѧx g{BcJ#‰('AƤ{JI_G[4#0[Pvq@rz<ܝ3n.lif8f)9x)q1E Dڑ41#29,q1 ,JS82Xxd >a`'(>La ap+ݧ,rNsME<8$a.Tˏ*K*a.)\HIeBRtI?|=}~<+J|q?i:өˤВ2h* E:Q̞2An3 0l$}t)-ط^^>,ӰԹbַ,FP ]M)R}$l'Y2o>H''_go\D8vi(ױq=GZ"[#.-4U\yXl+rç~LloK-v~g_G뻯ã3N3:]i< Q'kqݬ;J첿#/MJ^>]:a܎Cկ~1|yWN>ornfW{iPiYJS:~/"Uu=McmFŎȂB:sdqFQJ'#zRDE1Ȱz&pgNWk`?ZcB J `um$0%*G >4cU8GOV.!2A7#޼L;/TL ̃:AIq}xc(MeƶOױOѢzyRk'gArgYI**7}0F9:$G*%'׷A֦3r,q$BesnqW\:gmQSe"AAJy 7`&HwK_^_4"̠w{Rm' ^#fbO$hV"]pl ER& ;%-šj`_,̝R b$FJ] ƠLRDR~KO Td0Zb?$am/ce}_=t1_irFMDD<}G?4gKpܮv$?BTυa>ݗah^~:8d+`A*c$ԊҤJ9K6 B.th5a7s^mnh扚D\",p\SC^^Set ޶[|AEG?+Y2!@ke$d;RäMa/W~w/ѳˣs2wS{wO=?:⅒r91/sͳM8B$hEy{~3g_=Aq ߿#n~@w1VKRX$7zx|:oIߞ7>Oo~xx/Wuwֻnq'i<~:E~_ܞ]dlI]rw/?ш t<=95#έieΦ2MI Ǽ|;Byv$|_o]f祵HH[,54+N919"8+!ylb%"9Ĝ#Jq( h}wNQFL*& wIAiT4`L z2i 8mJp >۩jԨd Yu \(zFqa9d9MlP怃)$2I?AP4K{d!A2-8 ,225gr)Ï?hZi{Xb Ir̊vn։9(;/$|-7$uHBE8ө:KҎhDO< 6ƪ̔E甖$Œ8힅u C(aD[6F/yw[] p6vCF n&{0k̒Wwe\a$ מv7!UZ%؅8MKiB޳25jdaRv3Ui\uN9Zt2':^{<_T4Eu+nKnbǭ՛xMrpat.ãO2"6a_ʻp+ӝ&]դȨѯ{!x:϶zpRz]_G{/e^|?^ m~xW8?xz?KnZwތ:97O/SoeRfsهqh#Med=xHF<1.$K\lS 1"#(q9 1 e*8VnwTA|AAlY Woa9'8R-Bܢ]h}$C)Ƀi%n0UbJ$btTe9PrκhEH7TV(! I9zLvR 6D!v8!E!ɉpp ^l 8-RL#P&) 2%LQ?.Oӷ=KsT#gQ9SIV5p%jQYO4ƱdzTvWD&q$u.vljh ndfIKY_kHXր Pd??)LgT3v⬜Akomc+bZnEG(@"'J{bF1T)TH gw?*rD #00J:AXfۯRÔ=(F;єLr‹ >6:b| }wZ,Der4MB7+W};uNG;&(rHS$BBs0ca=1VL#[ѾH[ 6VN=CRewr:o_xz2%Asgu%H%"q:kSǻ "e}k{'MnRn5=nlƶ_WCNw}^^e\ %:"n*ҫ+z[JsMw|9}]hZWqL3Lc?M?QhynsX}.Ooppӯxٗ\g]_^ǿ[ _󍺗_OZ+Y4mf/^~#}q?9O"o=?\}tpu^`3T/dj+3=E۩SFI$}#01FqH0:(,c&Giv?&ڍFE1;;49su@iOaݲ+7 =MgQVI(@bЉ|T׈`DPDz =RK`B":lp*@G `N=#ִ*&'(h&w:4u.WML96KflIP4e (#%ID$rdV@J4 aOv$<]~/;:$OM%RrEcH]=3ӳS%QIls91=6:q`c_orVVc H>n_y=qw22y,m#I Iw %襐 ,HI߉3-0_1vj#3)7KcBN'ɶVibpn% 4lnCȈ.6rɺܩr>ϲo0&)K#Pm_P-EU2gU.r].)|$*!B{|{r]ڴׇtj!rY1w,gHI1v* Ό nBXQXGN#E"o'x+޾ζYQ')6̹z*qBD YY0sn]DupAUyq(v4kl9ѯ\:lG!@8# Q0tiЌ!O* ĠdqBiNʞI*D d^,ډr%2R J9TULL4R&D0Q$H8*8 z"ꄚD@7$% i@R((1ȑ(G`p<c^-grpt#r)'  #K92"wx$p-8{-{a6tP+0EF8Rb| =]`v'INB49hU0yYFSaF@RF<9W`[%h%@3Uq76˳y(-eyQXS4dL7)2h8$Gz(Nǎy$IVlۑ%9]v _w|Euz cEiln^+5v)$,nJFڤ>"R4 pAGqxM;3e< F!)>8a(Ijx&LHAp_ 肸jeu:h.%݈)'I8 Y)U]j1@:3c˽SVL7x~p#jiok<!`Ǻ+ˌr *c G/ݙ+eNi|5~}󾮜jJwUB43H߮I~-2} Sb,7PG|jm驜?Ѽu}7}?[?\O?zk?9bv~8W"ۏ?=o91۫B㩲bT\oO{~Xnzx_dJEb: iDEea eMPxN(jp&߀R̔Fc/rY) MuYAД V*-8c:E Og$BH䬄 IFJ K BJJ.%>;ؓAXa&EMYVknԄZ#JrtAdt0X+4RŞliGo<40'120(%s%ZR$>N$d=DT\XLVE5 4ųUFZCՅvՁTuCiمbGd*#&?Ӧbޕ8)}t)VAdي?!Lo1:s *aT| O{.t\@A̗ژh5gJLvRij wk;!8],Pؠ:6IcA0|n.M[8qk F•P LsRoRB䉱'E I0!tt6 g|ZnF /R#@Hc)'| )2;pJ|Fb*^ِ qڒ4sc#gyޟÇH;lq)iYH&:NY 2{!wPtZOv7߽q@kuVLs3 i[u:_N΅U~2Td.e O{&e}]=\'Fu7WџQOOI(E_=Gwn|qw*뭷?~?駟 i܎ç! Lc}R'|jS%uBy gy7"_{9͞ޮ[nfw#ʢܝfCZ̪Cʵ4 . b~яAz[;JcTn@1Q* 2{$K8@TRLBD.IH Q)o'tힰ@͘ҰJarFw!g6\p'3c(3-yLc0B$D Ir)* ~X\LN 6P Jna*Ns8JL,IP K''B)`Bx:ˇ4Ac=qPI)Tj%LgG9|6v$;aATgrP>YJ+"tvL>cɘ>&܍3LmT[fwDA8?D HJd?ջlnN% w#vpv0b!4Fh"--crjGNɺ!AB9$IeLvzEXw/2D'/^xXoѫ?yrv}g?i9}6gۏ~U!IӤm"lo4?|Xh2f?bDA5w?W߽uD~4Tix="7fpcIr8si=95;gN&%LCכYG q% JTa>B*BM6ONziI n +JʈA,&ݝ37D&G ]3 dذP;jNJ5U롰,ِ0VJW)DDT'!$a0Iq nQX)=vE 3sH܏"53K+kHlNyXa1<6N/8  O;-9҆|D@rDWAsnE"3T8nBR't;@*ǁˉOjGNMy.%˳\o+h ÇtV_2T$ڦ(CFqMxUM?>J;8HB`Ms5ɵ:bq^TL4fG.꾽=/Ͼ}g?V7w__>%*A?x|?ů~وbjw7$3sLK9L7V=e^dVQAr3I!lJ#c|컐 WA۹8 S-2l2a tr'µ<-MDe$>`7&zo(VꥌybU#$H@ E 7hPX2Q4cu;wӹ={-_}s/Tz}KdEGYw)KNYr:ŧ/rzt=kNڮ |7c?}'-r]Jȶ̔gk12qq(Pkh(RՍsFՏ>oo~}N>~x>ُK=M/Χ_7zWTe:n}ݷ_|^3o 4]~&/xk[t5oÅe~.b.ۖpz}y]twJp:,Nww6=O5B VҊřv7Q̓kau餾Av}zmS;̭"2ϗ4D wHD h!%ȔH0K(@!NC3IaܜJ3Hطp\88MȖ3E͐=I=d~%K{Eh7jRyuVny,.ReO2ktpG{A;Ks4-myV)$"Tji1c"byQ  ]gauR*OI |:+܃ N(4,!Y!Ė&8cJE3DpIbKl쏩s6أË0AI(Hv{h0[TTMb114ȜHtO{8rzo+-Cx 3"1Oԯ .y1JR Jer.E#:YD9V#GIhd)ES3LBcMA7 qJB„Y t7/uϋ!e. r/QRfÎG߅|O1m.IR)٦f3`Jbyt $5pԸ=GjK':{ GרOV L;,4WW//w}|ׯa?ٹ'eOKUjVhZHIP!4@;L@+ui3 Uc>ϧ˫w?vKS_J?i}:b'䗗?ϟ1o?퇴ˤS>x㟷G=n׿ɏg?fN9s={rՉwƕ`7} PV*sRӝcG#H4*yJ|X- -2D O0I3h-e]P7kȜ4 <( ōQsujR aJČhLžFIZL"d&v0k 89D%=.NY9H `!$(T$"Wb=ڸTRD3!Q: eCH FV8!6*ǣbwxhIS&Kdl{g"1,µzs!ydeU'.!#N$߽S`]ZӓڤYmP0 *wؾwV<keR])ԄQG $4M#$JzL3Xxʏ><(߿oN=Cp)VDR2M*1K29\em;wJۧӥ.ܨ1}'/{9?|:߽y)|]}zqWO޽;utO~Ï_w_ ?T_s|s{v-/5l_R#e7y?B^7;Y@D0eٰ( :|>S-]EU ƌ>JKe. |:UgȝKa ҉BH' {_ ߿^F|IbTI|bm()$/v2PHfN}# Gfd0ld= ^M Vz ,2Rڊ .4W.K3 ᤴ4+ǞʌdJKgάUdi\@CC74 HˤC!  &US IBDKaL$Wp@1fb'L1'((c(۽?\/DY{u~{E"qrl+ǡ=#B_$@ԈӼH8l vXdV1;$œ(\hsnڄH+If*G,:6'23=r};< 3 84L!@s?[=(B=yua5aR6c}D1Ҹf36yf=x @V$!6}1}`)g!i~en9G HfяطaL:Y̧1e/,SWo5ZtY2ŔQeID$VX~ÃfI=ގ_E5W#"I(|g,꣗7_?{\43aETR/X*mlf:6`N{ŋϧi~o5ؓ}|E8;l_W?yv6v,Ozߞuo ?ͯ>Y.N?: '?_Dr~39c!]ף  6rn[? ɜjd{oBy)PLZ'7Z\Oʉ1Uɔ`1H=1gf7OmY&9Iŋr"DiHH:Cg-yJl r'JVH fm"dQ,2 ` gZ25}(1r(A86` u}E r'D=$}X '0S^OpgEd &%q`!. +ɜU@\!&R\ e$b # "Å!J@3fiۿ\s!,}TP!ҏ#'KIgN^#h *,#ebs6?3$C7Ԛ?lYeɮĦ6fѬާMfK$E(H#(B*& @v?D[|XOf6ufcN@lTFI <<#iI."ģVm7 D|֤! Ný5{y׺_={1:Fxw cTBc{5QNQUQ@Ҩ\JX"-AJ<w;Ƹ֬bxbn%R*D!F4ød~} {D%8ì$ѻ$-eZN$JsDˬⵙw2՚O/k]&Js2/K9t&s=h$!gFh5䬬!pT p`sKù]Ҿl_g=sQ?]}2n-pyV<==}P#H(<0;A0EyϞ29N:6e2+'ƀN99'.'a@c'GrHDJ"#nb͝܂ >ZJ%ڀJm;zuT8gdD9̪2BV:;jt$\ȏ.~1T/9jßc Y4p3撼=Oyfǟ~Ӈˎ$&SLє2!*j!A]i2nD.׫$ZZкӬ8*R9\?ZJ>,YEHk{8d)mhP]n)^?_e~G'巿auۚvk?]_禺A?5=?==ޖKx`#"z[1`Hlz{&}׽O9et@_@*eJI u\.&nCe]a a/b9@}-^hd KIwVM"ogE@0歓pᜇKh7-)2{hFG,dW\Bquy<{2؉Q1PÈFXEB7ý܆WpgEHPc >NZ!=PrHLA:_++Qv=m_yuZ]k\Z߶Zm_ZjXaO{סܳG6.Ea xX{_۰j+{H̄fnfO]Zcs5]\E\&c)$(B) G bMbÃ8 s`Vn/?|Ipw w8K1+2m V[ȍ%toCR^ymiFgO_Ӱ1v{N h_^w ׏_k%yrYZ/7kևKD_,緇w/7o]>9=;oݰޞ_:?|_\n-o&*>|9o/ϖ`U"NnNؤE/= n=F.* 6uf=2` Y0Oity^9AE)pqۇyүK tP4$@)00Ic#6#FH,|"NP&+%L"ΈrUInJ4j;.[r <^a 6pA@Cψ@0cD <̒# SL),HX2Q(ظ(;,ΐ'#*H_0 !hc T" PUcz^c_tI% gCm0Нѯd`Jͷm %[ hb8z.D> AӍ= oTr&Q7Eu\ W#oSߊ$߉zvK|nc4r%06XpcL*mb=j>Miətd%fDˠS,͍y39{r"C}~\h\[m~Ƶ1Cn{*ã814Aq IRNy2!ĪeP1[+,ucၣx4~u{aw(SP 'w%t{tJ0JD5,dIg[Dtd2U^2;ݶDU19aղݑhѡ\˴ݿLfzFo>B]#=ncL!iǸ~r# O$2M?~c9MrX |5~q8ow/f-O3S/O?T>ZJ[p!x\AIO؇5(Ke핐"˔6f:o0o> ց3q_N.ĵNl|®fd(%3ح[t*ԙH_#ut.}YajFm;ݝ˗v{XT;)ʜ [}Զ Eo-"ZuCSL,| hga~[y;19uX~]Ç?ӛ/Rc]בOP}3ާC+ǃ7~N;xoʽ׉zmO =1IY:)CtA7Ȏ6]Rg˒%b"MYK3yfV!h$VL&1-xnN_:~Pвқ22J2e.A13$@Bٜ^ Hݨ% g6BJ EG .9(ʬ5x"fwAz`o[sbϔ­7isQ!Mlס;drѬDnhTR#KD2<F##J>0ƣQ.Q49D3[pp#0́,G@(!H"S@!!I&AS|q{y^_>?c`QC˨-D2ѺRuL 7y vk:u0m $bAnpdG]O*ޙ< S 6efL)ܛo7d9Bn)˴Ll&! xg:Z> ?zm y=zyƥ`5AJJ@嶏k{l}:蜎SA+.IE<'fB)Ƚn Z} m@!nfIJVx“AeєU!Ms( 2B/zkSl!rXS rU>"b6'a8QKL!#nfqO~5,G4~c39a|{No9}CU%Fg$ 77UZ4%1ˑd}.4OtL Qe cB)0K {:~]IYq.DAlֆLQ3dUn b;T&=BE&fF)Fш!1>Zx G Op2EDf4ﱜlDuvoV Frl^fI`@$z#- Ēi42́H@C p" @N$D ,ɂ9y%HIN$ Fg֞~Twm(%6ٯO{8a-b3 3ۋ޶a+ FScv}5eI H"! <{F3)֛O]NTBu>s> I 'ʗ|ĸF0F>m{7#eV5;89SVUɅ6po;lN)ecf$K6BhDFÝ/Ѯ4K^9Oc>m}hݠFs;zY7-)( p.E%BHi)yT)<4$V}~{_KG\f I4-HK旷/?i Z{k_a,zx#Uc(uxq*fHjY#ӜR͘zcV!Li}r]7,4r*%LGʢwmf4wWJa T4<'NԯOkc.`d̓m4I1w v"W"C=R_[KC[Nm{^.z|nOoVr~vz{Lo-o|VqP2._>ygOԯjug,o>}NܟyO?Ȇ3K)ԬoU RHcQs XJHeֱєmUYzN nZSC ;#wD߶o~~4<':fs` @(kD=D|i}m!{Ebd@#lU9(E[ \L zd:KDD(qfa`7*'}4h]@5=T72"B\'beσ3Ibg]d`4L A((#A*Ʌ^y"@fD.MN}ԭwcrqƭX-=Nl4y:ƨil`m}ʾg 7܉`ګb`!Hƣ6Tꉘt(8h~ljml{؁X!|*jLʽw}VIB)O<2eDLn6jjJ쭛@cH"Te1ܺ9 Fc9O;q,uXoh|4/A[n<JǐZ PYHcPLvKQ5Ѭ 3R#d2#)}41 Q|rn>cxN@XI$3jN ͒'Op rN7wP-eJ}_fm84 [ՉHơE\GniHfs)Me a%Jp8bu֣I I}HK}qXkn7ݯ=>|{8ᒯ?髯pқ_׸[5^_Okօh.,aZ)R|㗰J CD MէC[24[q1NQ[uHJAAq9 Mav=!S"wS6؟5qq{\|D'$. *ä:cQ%xt B@nea923g cP/ z$Hj)yFeur!.2 2ωWv\]SD,j(fͣSG,!45(Ic+#Gbh2Fp$r pfAq+ DGCّ 6zz;Rc:3C.IS+Lr!V{߶ھc Ũ[ku=][lv۾^//m |p뽮ֻ7q݉ҪmLfcC^xʡ )%Ϡ{1RCY2f % ^S 0d=j˥_լsԽYqŚ[ʝ,,z8W{2|[5^:e,)k%%bCݭwwtSl]PI#R\b#Q2-ԭǸ74!P-X8&bYXשr?+3Q:SxINkw_ncY\|H9q"""%  }A&"ZwfV=Nm2Q wiZiN<^>2]_SܻJ99b> >ČBaՍAф%Mi)Z)laíms SI0sLbm >86Ms@)"icwr~o/O?>t py/.=HݶvEg?-%9t?O,ٻSo/i|?KֽFT@G Ys' coԠLJz1z<|wBALp/ٰJdAq58( Df.|~Dv_9Ppw*}4%8F=Ŗyy2MAzD(VX(1*hL:fn]AD462sh"3<"Bmc*a7Pv&VD$YAFdpKMz @ Zȝ!vC( ~ො|Xhlʊ0AQ(^'PeLB*U`K$D!!5s{É<8ߞTfYz3b8Ь̉59J)ҺQXy4A(@%dսn\|}:|ͪ~$Kl+.=h"W*B=F><|:QLǔcOo˴HΒ'PGakۺ1|^Z:^n ē&)EY"<u2\ҴHdfU'L/nLLbwә %;`n4hmnM7p5TPd&>򒜌$yB=AE\ҍ5F4#3 ;cI'%$#Fp$4S% SXUTl<<ߞ.Mh:tZ$:MS2 ,S-7"S)u𜼑fEC<, z̡&i *b~z`݆hrJ͇O$QtCդL!'/0 T(QhHG>ADJ(Ld}`4((&=7Jv3  hf]<B,W4PbA-;"eB]`W$0=H &sbShb)H,o ae:@8ΩY:J6Nf ]g{ P.|1fQZXd֢Owx <M2 {9F-_)H;5K(}f=82W,s14z'k[lk]GPǵܢh|ȑiPY^>v!,P2$ U|v8W Ia+#bQ9tCIy#dODEźP7CBd/o_(-V7,xxTD8[2Gpޥy~D!]2O3uOE9s  ū+s3So5AȳHéDK`dc ޟƗϏ/ 6ϟ[]ŬVt!rk< C S0(g rm1:^x*)8mks,#YnY.}h.T|@A~eSKV5 Yisww3#eO6_>]r^).(˛H|Hˠ۟ٿxr7ۗ?~O!cG0"Zkm 4w> #'XhĘ[њyuѳ$@!?fyXD8E$TSFNQ1',d~ê[xے۩ޖǂY@E  v.Z4ݥ#I VGEw7x8&B@уč% ӛ[;Z3-G*D>w$A̷g8B& {%9A9LB ADLp _F0JA %q3; drAx2PB9kS36wiDb"(z[N{ Ӭz< !R.2:p/eJ}}!IVYl[A'pJj `_|_G}ۭ߮(n/2"gi1 {:vCIwreN)Q)A7e:gwYrׯGa[oJ~ ^nnf[cS۠B RGuHcI)^;qbL5Hn,*Qk*E(QGJ",m{!9=} vGN {cK@h0I<0/w7u)PODCTFNƃGt幮e9J8ߧ֣f&Yܨ4Aħׇ*EF!9xDg([u￿y=n"j?~~ɧ$yxK84޲B#pav~pXBۮ K]jo޽ ‰x4BqcTDb= "i9CHФEIDŽW r=9aICX[Qak'QC%R"#ʀL$S3#FMuʳv0c#u'k$$HG̈&} 43`Ax);I8u#Ph$3GxTDr-R߉D#b@8(Q"% b! "B ֐1P 'Uxpę<lgG0Ñ( h!r)M럯o M3h!>,ETP;Ҩ|A9Eg[5Ifo7kNTkX{~u~Ds6eci$ڗ H N4Mo f.֙Don8J9rN:d,+mX4Vonm婽Ty Aڛ""kى9S}_Pv 9 tNi",bm֜yA[C@5H9$%B݂J:ٺmv`2HyowDNA)qe{;;Ȝfh$s!G`թLOoutCңt!D_I`B܈=u0I` !HSi!-z(1l~lK;x^/ ;BWr\N]]uRbc03U_pyu m#|V/كm\@fpN鰐ok* )ЬQS.4o|8UkNzn}K޻ !UzS}{)-s<$-9o_~:T%aF~㖠+$A5f=]/[ꨞBZoOQȈ0{IHPFK><Kt/ʼnu0PBl E8Q[O_},go1KmDJzmIDlHVBԂ4)@C (4`wBۋ[L`ʔD:0`u7ZدLa!'\Y$~ w뇏~=R޾%L0NšL%3vѺl4O\&@ 1zuN1FD!c8CtwySaq¹d^ˤmNL w>G۩0 p/z?\jG ݧ /9ӐE H3 WDb4(“MX H X .hFYFE=؀TWDl!wd<gAI/ IѪr̡镽,l{0.-}:X&09Y.3g &vՐI([pv ǀ:! csR+`GZH a.JI"^e S$P' b@!`|k󜉙QP]>/{;x0pn.s'Ϣ9 lʙgaNa2A8BaS8뵅thƦm}^Ʞty{Դ0gpk-4PO%#1K7_~~~%nkݶF6LA0&mK$W-i9-irI)ߝ8Ih=v%,1AFCS +HmmCun$.JTK"ev>NWCAH=C( '0 66@O֚p>C^ g'"!AZYL:\a 2r27!9uˇ~k)}HӺnibi:z9v-* jK:}nֺZe Dg woj)hXrZ׵Yo9nȆyp:7s}u>B]˔^n,$¶BnFK{Kj/Lt8g?*s9-DuáUg~͇RƓhJ֌!IZmFS"bIYcf#&R jΨ(LDETaJ uA j7/ԜfͧYOog4;gB H6`%D f)hN 4Q]&KIN7aDa) ' PX*=9Ѯ)kELuBfb I wLi5)QD-TZj`1bCJ I:UG $ qq }@kD KkAD` vu˗`< , !(SP4x5Ӳ 48P6& #X۱eH$jw d0ԕ Pj=ܸ6yuclWy,oJYMD7AV*A&I9!0Q7el͞x\vҞVhF[#Ms y$N9Z߇nAup2:Ns9]b}""p#ɽshpAi^9\${۬Ljv@v An>"g(T%,%̽CYtJ,0Ax\uݳ[ӤNdk62{p%3d]W;OWy>_zm}F[oTf~k%sQ&FiJǷgֱu'Z|uMzJR(RPOYJcx&$)<^yp7Z g:%/21i%&{`rx|Bu+)mc>~~X} o?x~9xr[?[i^QӢ̰>BDKJt<Ζ{9.WRy;LI3l>y>aNd맒5,MFM^z+G2S PhdДm7?~|lFd7'?q:(%(7E`.0@SiAp&$[hxU7ͅs(KYUB{DA9ښ{NջEd r,*x@ŒdD̖T˜-BȉiaZ]s”yf&M#89J<, v -*["B" Lfda23t?޷$BD\6FdL'%"JA3akn8u3o0p`㼠W~uzuۻN:[Az$iiV)SPC֮cK>K~|[mtɛ:< p>Ml5dֻpc 9 muH2Q D.-`x*!LV#JvG:c;>6 7Ӝ:!DIO?9޽Yf'¢9D8,SYJ0- %H9("X 2?>ۯOyttX^Ͳb:y.q[6 ú:9T << wdd5MQ% q\t\BnDyK$-vfNq=-e9vHT;( /կr*3/-lSo]Hq'KO|+77ov?<+5"Z607]&_2\{cҟ^ƷJ{1gmm2c30zx)M4+1 t>Zѻ[ݝ-.!ӌx:zڶ@IB8Eg:7q>.SI%(4źtO&%Pi:-)9Ou$%D7ڃڭ JkMf%a "5 ͬ`!w8і;:ycwrFx|L)H|r"kݣ]8ORJec^NCI7%lSnZy@ؐVS2{Dǩ̹L,SJ譯7SVUmdC4UR O/fci<;q0%<oW\T B>_~?_4Fn㟓<0cMͯ ?ܽ?D$K  Vzt{/}1 ܶ}0ˬj6MytwOD)Hќh @>b%05/߮[7 Ŕ}~D<"&`PWFr g#sGO 4"$aսh.)0- M2]ICDn٩G.,!AS@9xPX EIu.w՛ɋPjUhv:}OŅu}߼Iimm$#G{8'H1'QcF4I3={_NGN6$!@ 1:FDpeFIX۶|yOC|:yq8.ӥ|zw_~MFa?h=Ow_l~>tooYpsҐzkH=IH)SPJͼu9ː帬Qrŗ7K.%e E&LFaY\imyC~~s:GLNl3GPs؂_=ON&3%Q-:1* !l W݄QȰTy2E`"ߘf!L֐DkH0s3KF' 7ˆB̽NPp%b`'1(a,Ѱ|$Kd 7a193 YakEp[av"wDbQ0 O`-(<:vfb 7(n*(:ThJ%tSA9 ;1)+kZbiyw?{DZ29۶=V=d=}u2JX|ls'ݍco=g9T=eN! +E'w ^GGîyۿ?ii=zo8Mu@TRDǻ]Ƕa4qL| Qg" !EĴ]#'ɔQܘC%s@8V+elWBh1By l:r CpuqrG娴A ƿuYĺD0"pPSNh)&nB$)`]",BD g*QHU'P&w[tt6^or0Gǟ_:9GJn)e rlۍPkm 0]mƪ14 QDžc Eđ9ּV2,ZZrWÑl%K߱G$}h&Ys;=|Umz;~oNe~oGt}#e_Ue2'%k+}[ut][B"4"k mxnk=614im$z"ee9YPX<} Ë/x8|s 剄 c#M$3$! H`HdtI#?K,Kebk%f~Ƚ7"#"2uWu&!~5@׬HVKsw3%{o N3U][)i!!MDw'}8d>&#b6C,O-: U) 24ѧ@SDe ^᳛9DF 6rs!F9$'㖄#̝`1С^ZpdDYA-`au-:gRLԃ68L_aDDHm@Ĕt#jOV;"1 HJnlBy}ZwZ* MOT 3 ZFxzƄHIP"vya̧5"=.ԪkWӜf\8PTda 㶭/~/вcu/RCX#rncz42CY/ESX-B'ą!2Kl}JC>UY*C‰ap)ئ3ͦ^QCo{#D,z8 JByYZK.$K2aG>]b]u(S9 jCV"QdQO 21If0;6d|xioSJqO^Gf=2'0wtr^3GH92' YRD 략vә:!z)K6[rմ5@f+%fΜ5GF  .r:?'=LF"%ƾ\9>h用_1<57?a(.H\yh(WPSIYQfELcvrzCZt/[Zo%,-X??~?ncc*?O5߽-Q}?_Oǧ[K Ӈ3Qv(AƜBU5_s29F0S͒ȚyVꓙ "&_=1M%NZy)0F`iVtr/_?kiX75M2zP"Q"L:yA0@Ns$!vٻ.Uݢ,2-'_T´0lW#%70p'=5!vYA´L-He_!N(N'CfH 4C.M$ECoP2U{p"@pa! AM`B6᳁b 0!L`fdf-6 M  #kA\@YPRhn2RgB#J8le/Qh.X3GDDF#o X5W|&dDq$8H5*|4:l?>_ J~Nb`% Ua[@\jje*)ca0[m>Ƥl9%MG&K58-9,s`9)"soS,+jŅ. r3"IIC;"`a >T1\q.5'$R,e.SFzotϗ!ae͵,SJZj*FBFE", ' # (m;rʶEyzSzUیAe^[$y33z!!tI蓕J]ti1"O!RlXs׹M[z9[3Ps~]E}dWÝX^/z>JV.yRPî5(ݯ_F\'Ao^>}4}kii.?(&0i ʙwY$6cTW=8$7,JHBvf-tʙRRk]i);k.)cfM{?~8y|XU>ۛվ=5q^R) B!o"D>\\L, ۦP@y6BR `6&nf#3BnNO^f< fIS6S iuw'  ;9q4wR82h:7ä.Df f7x9VqayRjGJ xp"ED 11!(u.f(Ӏ+YgQ0MXJ ${;+SV x tو ,0w UB!d>Mp2`dQ:o Qz8T=P=I'")xUDŷsu^xp}_x_~ְ9 @[]Iʽ5ڟ^LID˲yY,pLITdy"eƁ>&iR)a8\,+#\%;6%XQpgxL~Ѽ6*LLţgΩx&7wY (x9(XQ9Jyfzz޻m6/mf9,گO{:oO>_ L0bpUַ)5s3!I)0H6\{?kZIә} HԆ=qιu7QPn6oTzZzL׮pe "AoopJM%+_|9 ,?|i^$qBA%KJPpۮS!S(krVz *7h#Oĭaj91Uκ:fVJrr9!:rłpm9<:z؝ḿ[>SBI9zD;Oh]$W&Kp~a0 )1ɀF19(IkMbEvS4Pi\@]"m :И%LO!=r;R6%똞uwK7 ܼn.u,o| PAVt-&4To6 yѴ&/R{w4ч_?Shk\~)%9oWM0lٶ,_hN훷Owwo_ޥeeM:䛯fYsᬝfk}|Z9: %+Jgi: V%崬y=QQ"X$9m.%,k]̀-$|ꂩ֌Ϗ/Qc_o< -^e/yڄE"پ*B`McB`JQ+3ancjt> =„$jC"r*6ԥV a|z0O5"|IAhu7.9\ԩfn>FlF􆯏VkAL# 81Gx6 @#"b(b3a73k?X FV" 'w#-KWoo:L9C\޶Ωֆo؜!rUaԧcɖdI+I)82R2D*xs{SoNov],% #&D:j)kmx駇yg鳍筟M998C[)usN F0H1%Wpܯ3F CCFI /ꁤuW'gGH"B{)1p}ws%8f2#c_mEK&II)xqH5etD 3[=݆ͽv~/RNKAtYsYϔ =K\CNB+wV"„A`nk>fO_}Sb`Fֹ<~}8pyT7Qҷ3lwx~viebxyr)#*s*[Wn#eHxcrLr)rGKt5P主[)΄ XxL j,1Zz{svzNOy؄A漦c/JHiOz,n??\n_M}NWx|OoS  -7}f{f^wnc 'UPr9®)_8/wwR]PB|{SKʼn%)dr}p6qƯZ~so+oSf]JI)I2fg]ᮬA*H,@ whlj։ 0lzC!J̄PۄeM ) +)E bJ9+LANt1!,]Л7jIFeJ$'fW{6mY AB$@<jT8Z-`)I%ǰ9\ؙd@" w2b D 2"s3L"W8\8@v7LLB)Fk6$T43ɬ'x#"bP),6,J,AN1#bRI4@h"9/|w7፪J"H% H-_y|ڶ>~޿ܰ]bQ2P@5I%/ʓ$uc1ZGF-3$nAFe̋o#&" @_eEz,D\2HnȮfs{>{E4}6)(B̄DHRtm{˘̽(8BHtpZY(!!1ed0SP`A3slckc;[;?h@]tEE%-?Q(/A+l}}P t縺8YoD1gŶKWoN:[lv fԛšpx>DkfLZ=b}a1ږr$Z4} 1 .Y_kR}rz֮nj.KZ4H+8tg<8el>Ew? :D@.÷7|ty5}.:B[vrKۖre;rz{X_o+UɅ\ϥJFֻG{9\y|r9 e=s.7%[Ô)O埶1ۍBf~+4Jɫ Ay ~/JsB8:Ia&L}δNGAܩ_" ^)FdT&6`$4&Kfe-C+xB5P9uZ@YE0gDPT("389A,nNLD`  (Ӻ_x4*d$.'3@<^>P?G8w#ɇpB5QΪu! t3$2]bM=v{5tSB+Q!H"at鱝e8~Og޻]"$}ź3G=(e!oƐ9s9Y$u+0+-!ⲲI %LYZgPNL "&Zlq`gyFmKpZR zͯO9ܔ;|/Į 6EF0tI%T|U^`1}֚GG^VYX'ͅ ɨ"mJcLWpjlAdL :Lp_-ƸZ| =o+I4P==FPOacTjAqkC5#fgșF\^d>ƒʲ_ 1cy'/~roSWf|(EP*k5~뗗?h1{t9?W>|V-Oˇ-;KR߼I¿妼ݯ׏-r>mNJn{8;`<:_^`2P1 h 2T( $A̯Z %NABd$̓9I4O_{<{+wթjm_==$l EPEg9i@=PI% Ә2It{SOHhQNFDƾYҞ^~><ϗ?r>?2y*xij3%Nj$)IdN"G=W 6sI#6e}Duo3)Xޠbs֔SBTs$n`@)na/ :Z)dNw_7ǒ,IE۴^dʻ\RSjӟ?[D\޿&p_̯~ӏz:t̢ϟ5|gtHy4{!$,_5szzxdnnωre'‱eG?'ZcriJo]?#wW___}}&E8-5լ)q@jf` b-WQN]샰[>Ř >%-Gf fP6I=$l6]hC `FTx v%v?SM 0ȤS"ޔZ|os>-g,CѷHYC=FAăEf(+mcomNs?5ܺM<.d,<FFVA2LRB! LȄ1"X # 9CmS/fC1zzy6*U6̚&+ dî@v^D  IlSC4.ۏVRK=RW>0,[`ɇ½{sEOcQ0 ۯ/1r<ea\7ӤPrB&S/Drld$ U IA ;OI싛%gh_xCvF%|suLӊxo܊@2W1Iw?}\nê˒4Uփ݂=AѐN9%I(CEĂ$2ٌ9}oF."6&u?o I*䐰A|A]Y%5F0Y0:OI=x%!TEt`e^vPDAf]MQ-eUY)i0BD+)4QD=PI:qYAB^ $ק6Ys9}5s7Niߟ^^fzicRVWsa×p$?_/PJꁸ_W߱~-72b,w_>(ɘ4ـ5E5s0f pה]9"^(Ě,Bee^?zL1߬髣MN|-$1󢬙(WFI,(oO%OhX&Q2 >5*.r"H@*1*<s}1ȁDj:f$<"q4# gx1(Ex8ŽeEѕ¤PJbc0X+B0pR}\`A e"(!`LJ(HL#Y+) ybP.,.NQ Zy84H™#f1 "6&$ Cw#U) AzYtNLÂ3Iܝv"\+bI\VRk.%\Rj= WʌHգa1"뇟h~ƶ7_Nq}T2!i{x \*-UWQ)'IB%x[C ,DX|*kԯ)&gNlK1\4QbguAwX وi^6ck:?|>ֈ(ad챖5g[t\2jLf7͈Rewdm˧?=7bN"Zߔ,UsOϟƷڗOO痧+ڡ⠷k]PP>=}u_Pfo63PDv:t/̟?>+ʒߌ/y/?|p}_N߶/SדhшTܞ8Щ _?m$KXU~}!y}|:3Mo}\oRZ}rMO7D+t _Dk=T a.r/h󼔛$fyktx-!JlZx[\u[at֯T:ػEno;nw_Vo3+,9iIWE^ &0u*DI%UA@V M7!VnjtyQ.@vu4.!,4hiJΎ"2DSt݃Å9,I9*V.T@ђ#L:<llא,sFČ6Dcse7\ G`JBRU $R@!5v<„fl(R qghH4 \O?ٲ0bHL]Rl$&( ӣ%Q.+(G crcuWoS fVs^1zZ#6qy>xOfJo{LL Cr!QYJBHaafF,kzs.4-d 6~4g LbsBAEJ8)44u,k "/niw8KNFNA> i(Iڮ)][ ÷ Wpƒk}sD.s_ϛ97.&>qEoQV `2)GeHI*s a؈}k <3ú E dBо%z}Xh ۃ{ &:)uLf5 I0btQqfl4ŕDR0a`ͥ)@¨@9Xpa"΢%-4:AIHo@0 0 f%QpfA01Ntp=(*nqdI I/>/ɧj+9'xᰪ|!)=8&((aADs6{97ne~jQqfٮ@sy\4r]rJ'eg>~6>{z0ld5-tdI, c)b+EmǴ2fC0{Β` #򿬿Tݒi7p &t8X081M1q"b$mko3 Ku)`.Mʁ O2"a֢(Hȓ=&36:~yx]?],3k7~ts؟jNT K-T(a&$\(*'5OOOm8;oS%ќPA ku?Sv\ n쏎tw7OmLCy{7_no5/??5z&ݛ#/]۟~=xC^wX\қB7CY.ާh.NY TK)_˲7wL 1Ɖ4 ,IԬxt\)Ӫo8wK~{HK)9LY3qYziYItD[ttoVyd4\jD~9'A4)sR s'n#(]K^&#ЬM$5eevMox\-,)_SQDj#Rv ad;IQ%fñ$v1Յ<$qi1)"Ck),ve3־7׃p\j7! !>t7C*,-[9r,gچtɣnIߧaAͦd 29d'[L\ I]gYS5Q h>r+*K>h.ɢM$'F.}j|!JUJ!O,%,)ybF"e:ufl)<&DumSkM;omߐ&ߛ#Ͼ3{ZRSrYܛdMhhZXuhyI1|_ι|il"t%Ycom'Z$jͧ|I/_ݯ2ӎO޴dk~r:8[;z[ *^y_h?ߞN7_oOaeHʉp;ܾϝ8D#h/_>q<|ȥ.zuTr9&zZd$ RClMQ&P샘5ٍDĆk(oFe[b 9I |1*21;Wc 2Dyn !rJyA h fCF~bOη26V_Qp8?D.~^5CXEx0xh!"p_$Qr~!,2aLh"3.B<'ps7@cD }EZąrN%qf$ ,W^T;sɕHp|$4)MwQ9'ao)*k9"M[x9&%RL֮iss=< gR+Q/M}ۗYb4d^_\>5l&g^s8dN"7qMDH~ҞO?ulD6dˡ7h}|ǛU^~Zj?ϟr~y4"E7kvxOk=y^r5cW}w/$kpPr|.]iUbWPW,H*p+D83riʮIb!bp} 21$fx;3{gȅ#AI撒50Jt84(Pt$64w !37Zo*t"u.D`0O(3qORsb`h֐ D؃@GHfi5s{(y0J@:chp@J IE ,j3;O#G ar AH DVxH)/|iMKf祐kN"8H,-Ha GA' $i&#Y4H=o ә=Yl49t63"ER*fO5>-¼Q: Bj^29۹hSlDSBpyc}?/RHd]WR(<|5IRI=zC@眆>c|yAϽOD8z9!6{w9.rmkq8ݸuIG3p8)e(1SJNRעyU)5/Ir \A)W:C:]*;5iH)5%"b%`5 }]jv? cHdsR&1`l y$}^'"ùoȒΏ0۹C/2SH`iQյ1Cgx3.JBڻ!l 9~(5w~}z֚Pzr|Sjֻoӥ z6kGYވ.Ozݻ.q).S~CqN7o,}Yy@Qs]Kp)׏֞S&^Rr/}z5oӤ KCZnpRi \-/ L1]s] Bj%!RyV͞% ‚E 4)*!wMDyzR10g9H!\shBG#[p9;phg}'+&d;X2;D"+!X] } b &J14& "\OݠDNl`؍1(&*@pR &XԎo).WweCԜ |$Vp"Dj dy*"b@2^ -=(@ R#aMb(4AH`fk(efD0Ӏ?}~fDcɝNAy! EP R* G,#Ea {Nn>2cLee'S9`6ff 1ױA|ReL A8f=%a;!+NuBL9uLuNf} Ds]8ZD bUmkDOa|z Ѽ[r-*$0 <IwFB}İQ|P<EͱS>ޜr5Q. KB >F/]H2j("#iCB@8Q#3f62s\?sy;>t>G${ɒ.Irwt03wCfVVeV%nBX5#"l  t2+{#n?۠\ނ8W;;)- Z #0SYiJӢv$QN%@X,XxݔNϟ~mrۺtxt~˛,qz򌇯 ߽Zf?:Z9?)AJmc\*}3+z7^nXTP[pz|wûym?[iպKǏc}^2횰RK9){\DmBa'Vñ)'>ݗi*{Me$Y2g;ުϤn]5֫ # !]4Zh0!R 9j`c,&+fs|<->?]aIR"ꀐac7 Ÿڧ5|9M򑵋.!A0,޺p{ #%NB>Ψ۟FĴTpE4 ]c.^rjf벻d<:&e^e1OSNPp:Ǵo>Nc۠/x>}~uI.&t;~Xt?֬F;}>S>ֺ^<*<\۸\}Otk9a{|t˿OwEL9E)nNNw~ʒf 2gf12katcMć)y)a͓.'ySVbrL .%{ nX=p_|c9Sn*$,Y #j^{#=>ȫou;F h:DTS#hݕe4I~փ$OJ qoa,ƴ1=|~ecSRBA\$خ/6}͌Ü5%<( sA'K i{ /}Hj2n kUE, r豉Պ4 $uUW!&Tuz8851-#Õ% T/޿/u{Вg>L$O}Ӈmg{<5OSz9Uו2]tw~}mNq5Kۥ7D0mĤ94g'Y5ٽp#]XOF΃/`Ց_tJmtDV@+z2f1qPz l ykDJP:D&A1Au;%*pp8H$1v#es!fP5c8ͳQdd0>xH Rq `DNDc9i =ap^A\DRrep&PSz+?_F*4c(Fomk7حczkXGeUo%QJx+HG[)` Q%HRʹRn.aJ0ԡ̔4gќA"#DFme &z>lIya GK +:-(ҩ}5/eJSFj'H29/`# î6ЪقZ elIs) +(@J,HB@~ig?f UFc!lǷy_viAĉa,jh!֭ڌO?F/3VI sVҦ‘h.=6C yuNZ"Xv Шzs3Ҽ{Wnz폣Umk:×c*"y2q%]nt~7٧?E^o<g__z:{BcYӇT.aaLD"y7ss*8DSI:0@DzǜY2cfW`~J@ypɨ :;hr#&CٙU 3F>Dk;]`SqhUacjAR3NFYBݜNDp= 5Ga aaڍBA爌,t "&Uh Wc4 >2UWdt#gV C< b&+ &E)=1AhCU* PGLq!(i4:2Bwk`&f 7!.J r)y% #K?ϑK 5:K"2֐(K!6֨<:c "仠ƞXSo!HkװPuYraLE2e wdcDBu(+ O%r2g i-8"V\tHTdz6luKJLHҤ$#Y"yk-tmB^^GK7nTu#Inb٥m˲TxIR޲ dAcJm.gr]jF0,%M1/OqGc(S)>ϳ /#/w)3¹7 1$83LĘM ᓲ!m3|nl7iTb&ԍنYS[oZNf}zxk#,TX(FR02QKs1ka‡1{{N߽>ÅhƔʲn/OTX!1$ϣb=ƥ?ǼwNAd#r^~{?7o7?_.~wWoGڸ=a;/O\Jz?׿D|{Cmmk}ir~,,YiVFR1EETrTB36riA &]< wrH&B Wi,hI0q[ffI9 z|DZHvC@ ['L`a&#"L]$wh>%ϳ;/LΦm'X)r[dt%'-&f(θ:mh }(7J!cqֈ BD )xp È&D Bވ `2`$1w.ZP"b &ﴵ0K@jYp""r@A'q۝~pk"p|B$oAR", suPP˷8 U(ۤn ZPf#K>V)C'MZ^CVȄ b:4nF('%.GzuW09'=0f-e/D?~J׾]9&Œ1im,:͔"3*Ibͷ(u}FZؤ(J;]~ur,e%0Uu ``%xx{Zvv{/AJ&')w&FܯX_\H1e9 #HD{R0n =8hdO!`Cz.>y\Z~x_hW\'xnI\la$uמT.04'I8MFO<N8&Y~7_UKb1gH>.J'p<֍o~=(KQ*q{.qӏ~l-8,k1N|4ݕq.¶2Z/ HS]Q^&Q?pW3VIwqaB( irFK04\]yNjT:Ę)E=T!;08qa!މl72DLLn]Ҽ2K{YYvm/~ݪEM\v d){"Ujwǯ~>~avnM?~M:ח[?/4D"g˼r~jD]viwT\pzsLgiO֗ ^ǁYsQ2v}XN6&ӎ8)uIعL)1:9$B9y ݣ=0o-#9B$]ى`hwLƱ4- a#J{0PHHwiL%'fF tω3'FR@uEטx\-C4꒴k֗0cgxwn[Nޯ *)]̈yPD)A6L-I@((O}n mL,Ʌpx_kNEoEҺ9lwfNA.w+q~x`;‰Lpo fyC:C:,s9#[ Gڑ$02rVJ|5  xPdD6n:M8zͯߟde[vz 2S cvSJuNR.A|f# >=Yfre4?[:Ӆ(x+\}|V4Ǐ?,6Y8|_o~wۇV)3$NI4eZf=L!f: bM:<r5d"Kso[Bδ 8'R!܌ WW;&P%"6_ pjQMB evCxd);h y('>{GjY ƒ,LgC0)m֮e{9߮ޚk5}2n@lEķfYyiwY"U K2z/\9k.:-:o߾;X_A*0y7YN.;MXF$MtуT;/ALՇyм^~xռvx':Nz!bX]ò6d6@2v~|gꦅm Z/<sһ:FωQz?/?\6|l[!􋈳o1O_~N?s[e??=}~VDzxǘ+9tJ.U1&?}vy@Yi,u\/uy}ڸE^n5-(6ߝʮ˷N9pwwc~[&aX@Sq$*)8ށgiZƒuD(}A\lXiwSDM2Օ& QA`F3Fh 3A4mǣ_B.& "ۘ:aQ1SS!*Sf[{h݅(4CQrsy `f7w2ؕ9#<$FxD 0Bިӕ,®J0w.$Β1 `fXy~u^Bf%yȠ*A1g2 z쑒p$Sh$WOLJpHH@5>O?_ls(d`Mc]!b$Eẃhۚ:OE=BDuȶIbHE`D0vєN@{dQa!u,}]/5Ē-H;J $M!e!Ct/̻7]DU#i28V"fj멭7۶m6z[8;bdriт|H 0]V<%-)Cɩ OA  7BF^_ΊD륭f$P{WosԩE&.$Ԃ4ӻ/}Tl+5O2b~oNOZ?=&\ec[Oo=/yzo/?qw_Jc"eIzJ>,"nnնa(U JB)( $endQ`ּ̬:BVleҭ">ZD DbUݳw'\W*RU_ v(ed ]̊!@;#!Nܳwsړ (0pmh~ w!C@+46#jø*圓8#bbvu  v=FDL R(e#"qAsr7;Ljs[!a2!8@"X0x8!H,w{:}ܿOeX6FCESr[vfii/W_kJ؉PI.KD"Lgq9 AI !^fQaŕѣA<݆<$nԽo4V{m4k`qvGOuV;<<7.7`p7*N%$W%oÍ.N4NcINsKsy#u#`}xuNvaikk #uuv446.9P.;.ww~o~;o]Zo΅hl48dw}y9'U>޽}?g&꼛꟮ JT_lϷOO][}TdwmQVa}֬_ZWԗwOz?o~і~!׭{&vK9,%BF"ܲùqYC S1 k4谀IR/݁@ vFBf!sdI )Iq "*B!j<$<i4_WЍG0E()l%Δ *x_!;i+ '2)Ҟ=7ݓ@f-6!Ɓ < ^yRAN46ZB &ԼQ=hGJJd`ECOUWY\Y[]adfijonqonsuccelloqqrst|{~{HS\\\ZW_p|ZL_{K$"#).+*%+0%&/C5;vNKONceGGPTXYZ`Z\_dihkmnoqsubafljqnnmovzDPWWYV\n~[2Dpj! (.--").&(7=?C|[INNKbcEDQVV\\][[bbhkipoooveacignlohmtsz߁DOSWUZnb.,Yu+4'(/..(&3''/7CIxjJPROLa~`FHRWXXYZZ^_chjjlnpsjafghmmhciuxyTAKNOZpd-#IhD!#%+,.("0,**.>MrRKPRPK`}~eEEQW[YXY[^^chmimopthjdfinhmnnwzyԅGSVXZXYZ__feZbZ``kgkjrzstk}tmjyT|a.jչu#%+/-(+)).-&RSSSVUN\{cCBGSYY[ZZ[]cejZΘVZ^df`itzqmr~suekļRy}Z"է%),,(&"*1+5TWVXWV_{dGDMTXZZZZ`_cgcdԔY]bZ_jsqoop{~}dp¾þǼַxrDLʭ)2+%%$)+%"cXYZZWT\|dEFNUZ[[`[\ddgdz\V[cgghinqvtrbsĿȅkռ#(*/+'*-->Z\ZYYWa|gEENT[[]ZZZ^beZudY`^ZbnirwlodxɷСŶf%,(+(%&+''q[XXYZWd~fFERTZZZ[Y[_b_S}g`_^^b_olisg¾ɺD+.,*"%*-3SYZ[XZXd}gFDRSWZXYXY\_^Lͮl[a^ccgljug|xͻ"'*-,#*)4F~ZYXXWZc|fECNUWYXXWY[`\Qٲxmc^afcqskux´¶ٷ&'+&%+--gWZXWZV`|jHFPUWZWZYW]^[Xٮuh``bgm`{p¹ɠq!#)+)',)/--449*%**)s_^Z[TRUvsJFSTY\[]\\^mflmnjemezw{`7,R!L06,-,:"B<h6~ϫd7"%WE&.2323+'/%@]\[XZQWxrIDNV[Z_`\\`ekhgfe{dcvxi4>K5' ?J!*<..&S;sлrI" GH+/068.(,+&i\ZYXWRVyrKAMU[Z^]][aejlnmmpzn`+Lb %ES/!*BK=)xZ}B"5Z4<357*-.&7|[[YYYSVwrJEMTZ^\\Z]`fkmm4 Vk`/P2+b+-/!(-51A= _f—MYag|ȧg,!7p-84>6'+-%N{][\[ZTSwuGEMUY^Z\[[`filv{*yLE9UL_3:=.'DK5'7|~U=@imRPA#"0+8:9++)1(h{Z]`\XQSuuIFNW][\[XZ\acv^IrjA.X8J6X#7$-P#$A0§rjrwYi`WPhp[`edM5"1t772:*+.-5z~~Y\[YXPNwvKBJUZ\YYWWWk}* @M_AY%58C!Y1"'Yo¯SF>/-)-"Ctqr|T3'+081 6kH472(*-#F{VVWRRHHqwI?KNV[VVVO_<8Y@\AIs!:.Q$ "i@#%ĽM5'((%6~69|th+/CN$0/'#4`G98+().$[YVUSNFEsuHDNWXXWZSObr{2!L5C*3d]%)$6E"%)'1'mt_E((IA(AǷDWik{ב,.1k7'+''9XPA4*)-%0z|}ZXXTQDBptMEPY]\]^_=*{7)I973O*H8XPa$&&#++ g`~Jhu}ut׵ynh[3'09;g?+!-"R~RRLID69ezOGSX`gyy~x<68SoVg) ,YYQiNC-*$'%00[ls}vqڵ}up`3'181u/*%,%n¾NPFG?74izMFOcwzN6@46MRg5*%$+GTMhq3'(&"mf!@bnu~yuں{usc1+58*(%'&/~HECC@53gyOHR^ailLRRI.]6)^}EBC@;/0fzK?tQj1Jy`1K?Zs_.4/#%(@47{bke"~x$5C`mvz}{{rp|̙yqD$258U!/&x{ECC@7.+d{H?ex~kY;ySJ3SZryg,1+#9d/](FYlB%=A`otw~~wvpoyݔwi6'/=7^ &8~HEBB6)&azKALbmy\@P[BQ`>WC4'()"G?o`AU!(uvx*GD[lux|uo|rnyᖎ~vb$'2>6ns#U|JFD?4*$bzJFujajDIT[G3o*b}DP,5(=qHv=! $zM!-SA^nsv}etysysJ!(1?5U&q~KHD@71.g{[URXalAHgV*aO*fdim#-?-+6[& _h%,TF^lru|l{ePjn{yl&$,0<1%B-&{GDDA:8>r|OAPYb_LK^H$z;Ab`c#*?8$m8*)%"$&-`Makpvzzqjed[myL(&,8;2+,/E~FD@C8?Nz~QBOWjd,IB#i8LEc]{p@'I.K,Vp^s =,"0iKemqvv|uz}t+('0BA3+ >YG@HB;:YQDQXe,G=jA)CF`pV{r1B`12/ycdB,/43(4jQfpsty{W*))8H?24Et~A>>A58YS@KWi7?v26,@>DdDm=d? 1uSwc ('):)%gVdmrux~̩ǿ|-*''8H>7+xV~>=:;6?R{P?Jy_q6[[)>;7JA@P[aT`BQt͵Um#,%.,+33;#LLKamrqv|~|sjektw}0'+(*80GF0E"Zeloquy|rrpr~W"%-"*-3JJ1H$7}x+..0.HV{K;cvd=RL)7BOrka[=pgiu;/-20-+/34?)EF9P`ejqvxzssqt||xx,()*+./7CIIV`grt{h1&&*03,(CDK=D//vo''**?_]xR:[cDMM,P&2s[m|o]CxuPu()--,5(0),&0/2*5391GT^kvz~63$(.431)KGO;H6,vq'+%(BZ[yN'wx()%(4Rb{K8V>*9X,3@(!zi7MdxsbX;/+.*2;'6)0+*,23050B+%2J_ftxl!3310=/,,VKMFGB)~rIJ\$*%%+NXv{EJmH9682'$qI?bhjku%,-,:?#:**,*&-5590;C25;?LWep{}Y'-22.9.,1RROGMA3wq}znu:!+,"!(FInthAo&:=882%"g{iB5^na<~"&)9A9((.)(+204-1CLboz|v=/0-2+.0MQTGL?=jeiousz}vkɵD""(955,&%;?i?2X 1L44D7)Px|S/nM[w_E$-=A&?+,,+)-.52-,HXnwsvz|ȐH,/**5SRPCMEEruljghfimsw{}{ulżY%%2FFiN:.05.Q}DDx2""H5$:S:0YjWmUT`iXYe&59$D()'0))*620)D]oqssv̙>+KPLAJ=J~~wrid_\^dachb`G%,7EJN{_FA3)HyMuo!#"+c)lL:kuRw>hcrlt5w745C(*&21).0<3*<[gpqvv|~v-BNFS~ztmd]XR[n\FN&?BELMNkUA#Eyyp3$!QrFeQH0AKEq=HOttzGi4x0.&F--*/7.+58@.=Zjlttu~Ӟ*/IB;D5dxtkgXf}_N̘<#HHEPWOJ|oH%DyP6&%%8$KB98P[w+<9[[{CnTz6&$A-,,.:+,:B.kyxtkq}ds̽h GRMM]ZPSj_(Dz#0.>0:*C3"1'X?;AO[eu|U7u')D6.-1<0.@>c90^nio|ٖ(';9-{|xss~pƟG;VQR^hZOZ6nt+A|5!$&021'&a7(1?-Y6DA^bvp3*(+:-$:EmF+Ycuzzg"2/"~yy|xѾs>RRV\i_UW^K/8~O%&D&.*,l/,M'GSJ[Cd_pa;8)%)A,+0QmL"Smxzz}%0*~{wvϮMKRU]f_OW^_2+/}rB&"1.&*%1n%<&NO3LcbJUP5c<./)-0/Ijra*[rz|~~}~P>xzsǎURR]hhTQ^`\[h2)yk+3%'$'dNE")@)1%<5vKe{xH2203110),=crpV6\qw~~ےNytoҳq\UTai\RZb][Pi@)wq1*&%*-C'IK'+;$%3(H*3jeXwa?+/@/1'2CjsrN:_u{z~|Uzvv˓n_XZahYR\`ZRJ[@*sx3&)%*+*.-Au<:x4-#2))''>\itqS&*'-./'3,9202$$3,#Kz]V`-"'%" )@Zhjo4*ex~~`Ya^WOC8+# 7ǥϖG3=I=RbYNKUbZD3,RNS}HezmG"-6*',+-80:6&%*)<-!PRw#'$#! $?Jfkp?&Pvz|~؋Rbc`YPG8)3˛дM05B>Ja]JHL\hVG93PUcQdpnC'''(%1-)%5435)-426;9Bb/)%'%&2DYmk8 Kpux~~ԺG\ecZXNC;.=\,.>:G[]LCFUh`RG5=CcmXeno8(+-++1+%.I3BE%)O2B6D[g7G$%& )DW\H"/Whrwz}OX_a_ZXLKMQĉQ51?(1M3@_3%N!QB6R=;)%$%18)'5O_jqryx~~sQ[^a^^V\]VJFQihd<%%,*60+E(0L(AkQ&O8*Z8\fm6$)'#!'1EO\jpsuvux|{~՝GT[bfabjidmoQJKNG?SbXC:8WfoeU>55,15E[tc}82','521H$(R"6SsCfDNBpP= (!&/DRcfkpstuxvu|~|=QZbhiloija]W[_RFM\QDE?Feol`F52.+--7QŌh]2+-'*30:26'i':RqL+a0*`+F_4!$),EWchkjqsusxywy|}ONX`emrokjg``kdTQZVC>?G]qtbO:11.6,.1PĦer6)(.425B0C2^'EKL{V?2FB6Zh6)?P^dgnmpvsuyx{w}~~|wHW]`loqqjhjsr`S[QJMJDZtxiV<,+4;N(*-AgV4%(*2@8=<%;A*D8d0*Sȸ#Q_>^ q;&#rE 0fXtrr:OVg=LN? JFd*NmҨuΠ7u&l2:ޠMU5R#szo|j:%&ch,6>>H}[ɓI1B1R)Òtl<œ[E9,.# F4zQo&Ӈt^5jZԪjب׸Sh$xb";{!ɘT>&rL( ԉx"Λ]Z] uvRL DRJ\ӂMh 9 k*^<7JTJDg ;1bŷn,ttlldL&;P*466X"4?a\.d ,XT1}am:ܺTZ!]zpZ.jOdzzjbzfr<ǣ ~ㅈR:*Iʁ*#3N$ASs ss1gLxdLPL@M:`٨55_k@K(UJL#4JNff&A‘HpR TW{aPl<>>19^K%c.rbX!LhtuHR7Pi dUg Lj:93==>E"pij?>ARkt F#$p?95=he* MJ A:]k \S鸀G'gRS#! sF +'E`up̤MFer@*Id~TJTӡQ}RBRHxb;613 ^vj2E~)4lD''Y``sY :/4AUgZZ%ʕ p'( %B*U`|rzbrjb|r`0V Ɣjc4ĠQ8ȗUGc1ؗ/jE N,$#R *ҩ-elxDT8ƃAs-ECad2Z( {cX1xej|lhRMg_#Ӏ C"@(z8*qPx4/ &Ugffd2X|Q_ʁyNS)zTiҙRSA͐X R&R 'Ћ휸lyb "D<%+7 Jvv.jk2t6380< TKn40wiX"P H|ٓ@<Ebp(qNy@ڙ 4N/Mzl*97hj%`hdl_WM(=]_߻~pC0"[T(,GB!wAB`0u{v>A (CgWS!ݨ5177;744vQt JeR`J)vqb/O^o,ɥâ>g@js<@0^vly?,H4 Y]J8\kbq~vv%CPt6o`xh 10,@=zT:ά.{ɳoOшdldT"q|xp0u<^.Fng>J͙m_w ԑz(T*L!xxHƵL&cj &O?89yO \FxA \px\ Nvƿ{vV6 h X]l"%v}/HdӨ% FZ`љ՝ݝ|՛WoO 6oppP2P8wmV_t{. xDc1PX^ HK sMPCj1T*[ ,JUzHo޿WoOX=,>FX,6U֠{ @X4"A` -<|rίo04:#XU"thhT-kLV&W>}ŋϏ/%.ɢrx"W *]A7vy}X8;Dc`̭||-lhjR H? HGGJO0<<*IaЛKtr'xvO_?}EcQcP, h-lJ Ś!YHE0|m~c&jknoY 1ϡ1|p\KGF$*b8G/?tys}:(j/cĚ>H{\@By'b8Xwښy0f^`!JGG\g5AxjgarJjFlx,60Td <ڻp)n p-٥Tĩo$S@ H(܁AD"Z] ŭwonN>|6wr'e! W*rG3Mϧ&A]]'NY,PA  aNk3nbsg.߿{uz?YFjEbH֏C*v'd!`_QqNϵuvvv̑lJ KB>xxT6ݤ;G'oN߽>}syquu}sגiΝ0sb. ?_؉0 x}f2o$gg1+ OexCC" E#26fnҘ{/=;z~t篿V6d #VAAvVV밺|,(a@lk .̑s49JMud|@yBSA )6dçO_/ϓA3ѰW; oy&lh6mŢ:W柞Mz::;2-`*{htj?/9of`74P6ɡVO=~d?}xէO__R9lhυ{ݼFqXQ<]NMOOwvwܥ).Jo7Lf $Cj \4ڽtgGGNN^;:xvu}}X`4 + ;_98G0\D(uM'kje3 s3ꊆ>@6{@@{Op2\1d6*$Aj/O^<9:{۳W[mшsKW jEHFdWWWoOC[[x5 ]T*F3y1zpD T"3ɕ/^<4?7G*5AebnF&#l{=xoN^~O4h"Zw~|w3D4 4i}2nun!_Xv9t?ȷt0مJ!뗧ͭ黳w߽z6O>|_l ^*$p|4נRPr~u1kә ~mOh#"zxL?|zÓo_yŨ߽޿p @14 CҸ?O tzSg өtv?qfـ\A'bY^XۋѣW./~O,zL6 Wox@ѝFxƼg pJ0:Hx,O*R=֠&ƢkKSK뛛+x|poуݹgNoO޽{ߟ G)) RhClamm}-n(4*ɢ+Nwx1h♚[ ,.ln,nέ>}l{ͻ7o?XX~43 Y fR3 @!OQ{(y|yu}e / jN|ٝn_2C> co}=ZO.έLnn /N"R.Y1 Ԍ`}3qP!`9]L-S̳WoO<:9y{vvcj%<`g!hYnybS3 S4'C J7BP7f~UMiR9,nR9n{84RsəTj>9Ϗ_?]~j`?:\PVU6t5⡤ZL) _STJS6?xu7Mm^mq6 *49gf]0mæӺJXF EcJllXs1 Ul8՝;+[;GN^U253B梡XTIeY\\[M`qz_g.rTZOM+` 3(%R lӊu0XiUj d1<} 7 uhXV#4Q}5l n xM,=9|dzE <WPH6L_ FB @AlMQE׷6V"n*{ KFĂNbȿdǔdՔ$,pV=m/>O.?l :KE*%nj< )OD&%iPpp@Tf(OʦLTߥRrõνW@m|x(Ѱ݈ p &rY&gf s@BD,Oܫ-mnEdխ=tɤslF8?g@𙨚_ˑw4Ź'GxXs'+W_`}f~vaivz"{}KnW:ok 30$DyC|g"9쁵'S/O'[ACrkscѳ.1 ccآ8 msCdz]LOGegԻŕ u=T$hXףni-u=[?喔I ʣ籃Ӡ!4WW6xpVB"X\袒b4Ssi^㱀m3?}]fBySL\+j*.`;neC XwNW^255 P:GGO9~k~VUXH,A39~D1LԾ6uhi{k{u\\CcPcE&FTFU+ /Iɂ߾C~tUWO ݹp4('`ӘWHDn}8 삑;N<`0s!ne3(v W(`-+Q}WYdd@- +o^l͇#S/?ùm+xO,]+NZ݌*Im"jqEdzbfK~-*τ"!uYP$<.Q<[~D /~bp9CB8}< %\$X,H㲚 F@t;I5c{1Ek]`(D!ܲf4e!Ae1޽S#7,>[@gt Ψ^L@ J-2=1Ţx4Aa|)0i:qeGsAm>.*2y-6s>"@QokoFN<8y*T1mYA`7}Bu٦AñXl<=Yyd2-ֽ)M{3oN:|xY[~2,!8S;`ÐPgvlfO7[ *a Uovb| ŸE#X$ =N\3TS& .oߝҵ7v3\;h+iD ABN) (qӱr":u;ͮ xYQ?5dz! ]VͪBr.>~ǢH4f_F#w46] ~>SEgv+o,}\ Fg r6Js(9#Bz.P\;Xfm@vBa|uLnK*(wvu ]}AvҤ)+(Df`NQ>,7csk+kIèzxsc\xNQΖb#6Wr<K\8[/ߜxv0O\t<բk++h%ZQP/Bi.˒ ͬQZ2j?MJ9/_Z#pd OOc@sK'''/ah-mok,hLc p >'6;#cu|K7 Ҥg*mrvo֨x44k1 &jx"A_mŞ򡮺4̭onmLZh~I.(irx]@tgH֟li3˔?NAZցDZV.@ޕڎq@(r~񡮦Omm't͕NלӤ4Wl\>+ ~2i.@k9N֖Wf"F^6fXv9R_'3"w˓n?_C} @+TՔEi19|<3>˟jnA˫9 N%RɠIN=ZԢ8gs+rX >zpsy}suqXWSSqskۛ~QATPyg5Tr{d"7?A5J8T|jf:Qd#O&U?N(H\}똙L78xbB˛˫˦zRe Yޚ5+\1n7!wo$u`˥ ȤYK&5"W`(=Qn#ZyS&"2vOYO'"p$N)HWWUs#07_4Ս(n;j/dc+¢ 谌 o݆bY2 CkX/|N0 !@k-X͗JBA>W'g[W  $RuIQ,25ch[Y]iu?FU݆HPHy? 0,;4Y<>0uRO,l=m )*%1+|;>k?v_Ǐ7Wڢ6]l~iesoYN1wkEE-u<~ ~7'\3w,?)E5 $Rp{>Rg?<\x 4NEg,X+?f^8 nm)7nkJKNIx0 jdm=gW/˩Z=Y wZ Db㑐}6sbSPHdQc%1VQ6//on>~:j_^I)vQaX IW92#GߛR2pd :˗ȔjsCXZ,^n?N, /j(DBo7o,҅9wsJ뺛)PzTЛ̺cHج^\ㆨ [ ֙#ew?3Rm0pe&_t}㧯`.MڬDV+圮RkxQCAE0Xs[d*hwT@06)(&5`4m~T }>Up|ӧO_~G-̫Y$MzZD@VTWy;nNM[qG@ӷOsK[ZTe0y=X0PmphPO*!@h}d/?'νyO.feIQb`g{6aX%C[*hQR 2٘58ix)YPl Ԕ)LK X$}nfO?|Fp\c>?o.daMlK/R__A Uhnm}{gF_i,.("!R~x(jO(^%(Jk-H#%q8LZWKVL@F_ MeɝL4&+Qw?1ޫYzQM>kpyMY0dqbD˅d)t6 W pz,z! WN+Ja1˻Ox q:fbhon;xTYvcc]@=%ig6׷gm).Rˊtyv[WTc1\ SRփ*#cVfcEMTe~E nfՂH|/_ 3ȭLZGnfkcc+9 jsr}tKi *HRSFUU Ѩbm`"9sы7@Kz?x=n  46w dN+/&jCjgkg{&τ8[DZ@fᱲ?eT,NR:j􅧦7<;J,pN_ Dդ{߾|t$ {"vuٷhRo0 1[ ]MZ>{l3w[EH(&tJZ$H%w?PV6^^k39n!:Wh1rp04gZv֞o;yK B8@RFr }D$HZ~jU2˫>Z{ bVavEEC0v_j\dQq;`Sgv)TAJ (UQkڝ,15qѳW/?_napxf~>I},*M?_pX\P:f&6F*G Q!T%e\]3LFv{1Ђ7<=~S/}1u P'oއzdPݙ;_ se!refӮ,5ܜyTmy 's9_c|>i6k;~RFO7W ?, W!ճk)4pt)hD-vA-VU8V,zi2@ }:h?\|Ǔ~j֩T__E|G dFn-dJ>P+#! PX8MFIy!I=(%Uujj7[G'8y{ͷ󼾨 Y4߿< q../mXޒWBRxaa WIw:#60@/iMi6,h<9$D@8pF0vή~^(&2KfLoNuƦw"xfvA ZH+sF)m+'`r(?Ρ*vÚFbD'>9;wW@_lK}mo)m?`Dhhhcwvw2B,бw,noYD0s1Dd7t^/,84+YEGP }NÞNH.l=>~nAP ƵEL4-'Sۚ{i\ ˸0(oo=XI(8кE@EP2lfIVg!ٙʦJX &fs8@{ fqx/yjGCN[ 5M\fSc CPl?Ju;;Fjp8EBA\ b3[]~m?Φ涆ʮڒ":z_ݽ`tOi Y][?j:30<+`6iv.@ ~Lmy'_(L Moet*Ü|"vxVw=`X8*PB,%di K@qLSG RRѪŜf77y@|`0 {.m}D6:$pݝڊT^+r:ެ +{$G̯!YJb}MMXp YHTrVWM&v 07ƓWu#IsJ,Eljm"QoWچ@a=Y .lA(bUQyY8PG&3*(R3~SJTߖm6+Jx~~y Pןz{X|A)#=N*APK̖K?9s+:P@ arr_0.npyPK7:scikit-image-0.9.3/skimage/data/lena_RGB_U8.npy000066400000000000000000001401201223313777300211450ustar00rootroot00000000000000NUMPYF{'descr': '|u1', 'fortran_order': False, 'shape': (128, 128, 3), } x|߅s݈s߂i݁k݁umttyvwxnT_>X@XHYI[LVMXKWMWOZIRQWVZWX\Z`]a\d``bihb^a_e^b^ifc_fddaecgdd_hgechdichfgfjnfaeac_fffaecc]gbibf_ddlhb`d`dbc`eeb`babbac_acb[cZ`V]LWQUf^ulہsވoۉr{hj܀pށqޅuހifih݀f݄j܄l݇q݂l݊mŒϚԠИӍtHYOZY\[`\_\\aeZb[\Z\]__a_`Y\acad^^^^V\W\}ޅowtvj߃l~g߂i݀nށkruzvnqhS\;U=TBWK[HSIUGSJTITIRNTVYXY]Y\Y\[b]b`dbb_b`d_a^eceagcd_eae_d^cbc`fbeafcedhjecd`b]ebeab_c]eae`c^eagfb_a_cc`_cc_`bba``aaa_`Z^ZaT[KWMRc_sk~q݈r݆o~i~l}k܀m݂ngfgހiހeށf܃k܅o݂kځiΗӞӚzKXMYW\XZ[^][_a\`\_]Z^]^_^^[[]`_a__^]W[_aheEU߄llpkmik߀hhmrqlhl`SX9P9NBSCPEPFRIPFOGPKSOVSXX[[]]Y_Z_]`[b^b^b^b]b[c^a_fbd]d`dac`ecdad`cac_abbacaa__\c`ec`Yb]cac_b]a^b^c_b_`\_\a_^^^^``a]_]_]^_W_SZNUHUUZihxp݂t߈sނnkjkkjh߀iih߁jۀiۀli~iqŐЛԛʎxfISPXVZ\][^[][]Y\[]][\_]\][^]_^^]c`caIQgAYAoikjmi߀hhoqtnlgkZQV;P\Amkijjk~kpqppmpgl`SZ:M:M@LBNGPKUFSHREOEMNQRVWXY]]Z]Z_]a]_[d^a\c`d`b]c^c_cbe`geb_d]c_`^feb_edccd`ed``b_e`_^b]hbied`d_d`cac^^[b`ba][^_a`ab__aa`cZ^RVT^NWFXWcolzqރttumroomlnhe݀l}k~l~k{g߆kќՠЗ׏qGTNYV\V\Z[[]_]\^__^`__`^c`d_gb@L\=X?[A];nkjlnmkpqqmnn~fndZ_jomjnopsspoolin^OR8I5I=JFOGPGRJSELDMINLPPTYZXVZW^]`]\[a]a]]\a__ba_`\`[_Zca`]^Xa^dgfda_\Y[W[Y[W]Y^^][^Z_\^[^^`bdcb`cadb^[]Z_\]Z^^]\_]]Y][__\^[a]cNYMVIWUbbhtq݂xzvuopmjjliށmjl}i~l|jxl~eњע֙xIRPVWZ^`[]]][[Z\^b_`dejdW:Z:b;f=omkjonstsqjrkhlZQQ9K6IANEPIRHPIQGQFQIQJORSUUZ\[Y\X^Y^[_\^[]]`_ad_`aaa^a_ba__^]^\cbeddb]]ZXVUYUZ[_][^[Y[\]\`]ab`_cfcacc_^^]_`_`^[\[\Z\^__^^_`W^V\U]NWLXTdekrrv߄vvvtrmhkhpm߁o܃s݀ml|kwhugqʕԠ٦Βq`KPSWWW[^Z][[^_^_cbga8JY;Z?ZA[=aP\EWD]@`@cAf>a>e>qkrotspnjhjolhkZPP4E5G@OBNGOELFNFPGQEPMSQUSWXYVX\\[Y^[[Y`_[XZZ^^^^\]_\\[_a_cbd`^\[_^\\ZZZZ[YXXYX\[ZVUUWXZZ[\_`_abecfbd]^^___]]__ZY\\\[\[[\[_X]T[WaRZHWO]_ilmxr}r݀t߄sޅu݃onm߁nn߀mml߂o~oހmylzlwiqblɐץګԝՐnANPWRWY]^`bced:JZ;V>X@a Kf HdBb?b?^=qplrtrmffkmnjhjXLN3H7K>OGRDOFOGODOCMGMJQOSWXWWXXZ[ZXZY\]]^[ZZZ\^]_]]]]]\]\^^^`_^^_^^]`[[_][ZZWXTSPTPUSTPUVUV^]^`aebe]_^a]`]`acZZ`c^_]X[Y^^Y\W[TZRYQ[MYP[[cklspyq~s݀u݃t߂pjmށnkjmnm~l{hyiwis`q`p]ﲀҝکܨĊ[XKSNVRYZ_ea?L\Z>^BfDb?`A_=^;[=qnpqri~d}`eglpmin]NS5I7K=MDOEOISEPFMEOFNLTRYUTWXXYZW\Z\Z\][\[\_]\]_d^_ZZcc^_be]`[[[\dcZ[XY\`hleklxɋ̏Njȉ~ejSSRTZ[Z^Z]\^]`^aae^a\^\`]Y\[\]Z^Y\S]R\Q\IUP\Yaihrltmyp{r܁v݂qހm~k~nހmhi~j|gxhxitgtftdsbqbiƑף۪֟ݞuJVNWT\``]@cEf!GdDb@^;]<]=qkovm|at]s`{cllqogl]QR6J6HZ>^D`:_;\9lorky]bQUOj_flknofn_LN.F0CM?LCNCKBNFPGOKSPSTTUUWWYZZZXWZW\[\[[]]^]]W[W`hqq|p{]ikwuyx}uy|{ȃ{Ȇnj̖ΕӤСѣԦ֯կܶݻὩϢU_S[Zc^f[bX`[^Y]V\TXQYMWNVLWIWNYY^lkrhulsjtoxryv|p|mvhwewetaudtdqapcobncl]m^o^p`j^lϞڭ߮ۤ~iZ=U?W>Y>cBf?bAdB^B\@`A\=Z:`:qtpem[JLHKj^dplllio\OO2G1I7J=NCQ?KALCKCMGPJTMTSWRTY\UVVUZYXXZ[ZZZ\[[^d]b}{vviq`g[ganlviqgprxx{ʂǃ͐ώΚ˘ԨѦլٮװ۲ݹܶۻxO[PYW\UZX^VZW]U[PVOVLYJUBOLWX_jesjunsitkvoto{ryj}ptepbpbsbueqbpaqenaqan^qcqem^obդ䨮]TL Y?]>fCbAcA[<[>dC]>Y<`9g>splxaYP4DEIl]gkkmmimZML.E-D3GYV4uregY@H)CGKi\djpkmfhVLN+B-E6I>OCSETCOBOEQFQJTLSRWKPRUUYUYTXYZZ\XYYY_\UQMXV]X`[b_hZdfolqfqjroufjrvszʂώҙԣӤӣ׬ըܲܶݲ޹޺ݿۺ۽_jESHQLUOVOXOXMXJZJWESIWV]lfypzlyovnpkmkljkfukwjrfoaqcscrepcpbncrgrfqfrfthvjwmka>U>V=Z=a=a>cB`@\BcBaBX>\=k'IZNCSFUDQAOBOBOHRKTOXRZOUSTVXTTVYYYWUUXyhNYRUNVPZV\ah^deh`ekpnnhoowrrux|ʆ̓Вӟשة۵ܴܷݶ༪ݺܼܺ޺n{KY>LGRMXMVIWIWJVBSFWVappzk}m}ovmrieb`e^]jhxmtfoardvhq`ocnapdrfrevitdxgwjmg]b=V>V=X=b@e@d>`;W:dDaCWC_Bl&Ig!EG6BXsheW9F6J.EKOj\domqiclZLN*D/E4IAOEU@PBPBQDQENHQNWQWRVPTTXUUU[WYUWXZjaURMRHRNWV\TZY^bf\bhmdjiknqknrxqu{y|z̍Кץج۰ٮۯݵݴ߼ݸٳӴ׹ϩ\h:LITKUDPERGWBWHYX`qkznmp{mvk__NVOX]^pjxkqcreugqcodpboeqeocsfujwl~nwfx%DU?W=W<_@f@c>a9ZeAc>c?X=b?hAW@X?aGv2Vh$Jp)Ksvߊuxa]S5G3H8J6IKQiXimnom}bgWMO/G0H8J=M@OANBPJXCRDPGQLTQUPRSWUXUUVWY[[Y][IPIQNUU]S^[cX_X`X_Z`bhfioqlnmnmosvqs}ц՘ۧۧܬ޶שҜӮ;ǵʼʾȺ˿ʷÜ-D9LAQ?QCU>RDWU\ig}o}l{l}ptngbDQy?-FX]kkvkrfqdshncpfpfqeodqguj~mTVUr:AO]`qkwlpdqeoeoepgriqcskzok_i?[&L[?^?gAeBfA\@X?j!C\>Y@aDh&Pq3]6]guz{ttoQM2F9Kd>g?fA_.C5H>NW]kf{n}n}o{pyrkeKTt;UBn@?O\]niujpbncldpiqivj{lUWX;S 9WaCcEg'Po*U`syz΀zuwы{֐~8L:J9J9J9L5HFLh_|epsxtfh]LQ0F-C6H=MBQAOEPCOEQDNGLLROTTVUXTXUXb\PVIRNVOXOWPXQXS]UXYbekafgjornqnopqorjkflptrp{xsx׬໭޸ߺ໬⽮ݼ߼ܼ޾ǽƺǼȾʽ˾ʻʻ~<-D:MTYle}r}p|p{pwgbIQz?W<[8"?HUccthtfnamcoesjyonbo;S 9W;_>i@jCeC_>^>l E\=_BcC_Jg#QTlwzxyzyͅ|֓֐4I;M;L?L;L:MKTh[{goqtm~gj^IP1J,F9L>L>NAOERAOBMDPFNKRNVSXSXQW\]rdBMEPJSQWNTPVRXOYX_\`ekhoqptrhlqrqwppjqdjkl`kȌ٤൥⾮߶޷ٱܷݲݶĻùŵǹƻʽŸ˼ȿJ_"?7GSWibym}n}o{pzsihNUz A\9Y8d 4.DTUgasgm`j_odskzi4HVg@fBdBZ?gC]=]>b?^C^KDe{|xypuzԐՓՑM;K@MBPDRBRKZISMSLUPULQGVHUIWERJSMWNTKSSZV^^aafhmkknpjjjjprbh_hS`kzۢݯ᫗ޭܮܯٞ֨๭ἲ༱ܸĶúûø·ɽŸˮz%CMUhbxmxj|q|o|sheOX{"E\;_:Y6Q 3o%G̥ʵܿۜk=S>ZB]?gBf@eDf!HaBb@\?fCb>Z?i"Niz~yruwyҊԏ{ӋԊzԊ{L@LBN@OAPBOHRFOMRMTAT娆nISBSHTGST[NTSYS^[dde\_^bV^jjgg^_W\TcՊܣঙ׍ؙ٨֜ןܧܭܴܲݳ߹ݷܵد۷¹ĺ߿õǼƽżϣlzJ=K6GDOcYzcoptq~fi]KO,D,C0FMGNbZzdmsumkm^LQ0F-F5H=M@MBNBNAMALHQFNKRNRKQKU͘b@PEQJVBPHXRX\aY^X_YdYdegimhfMVZfݒܒّ֎֑֐ܥߦ؝ۨް۩ثܯڥ֛ܴ޴⽳໲߶߽޶´ݽڵں¹Ǽźǽ̱a`vd|dgjvd[V-Au>`ϺŬΤпͼǸƹɶI @\Cc!Fc>]9_9[;`@e?Z;TAPk҃y|{{Ԍ։}Չ|Ӊ|ъ~҈}ӃzԈ|AMAMBMBM?J;GCJdW{huqrskpcKO-D/E7H>MBNBLBNHPBMDLLRLPOQLTmoȍcTDQ>MDPJUNWNSRWQYWaYc_d]c\`KX_kی؂yՇ|{ՕՌۜݝۤݯ؜ۦڧڧԙԞީܳڨ޴߹޸߽޼޾ݸˑݼú¹ùoY}d{dybm\U]ҽڶҰ;ƵĸĶ˿ɨOA[Ac@aEc>`<`Af@e>J5x+Vzw}ԇ׋}ՉԈ{҆{ӆzӇ{҅zЅ{CQENCMBLAK>MHMdVyekqrrlpaOO-C-D7I=LCOCPEMBLAKAJFMJPMQAPӆx{]XLUBRHTEQAMJRV[Q[Zb_aT^Y_MYdlۅ}ׂ{ywz{|zҀߚۜܣיטڥ٢ۤҕ֝ݭڧۭ۫ݪݯܳ޼ļۯΘڶڹݿݽ޾ݿܿؼټ;ߑ}cv\qb֑̾⿦׮ټοɸ͵ķɽň[oRB^D^@`@`<[<^`zz{zzԉ׊ՊՈ}Ԉ{ֈ{ц{Ѕ|ф{ЂzBNBNDN@KBK?IJJeYgnquyptaNN/B-C;L;H?KCM@J@J?LAMDNGNEK2KƕqqcTTCPJRESKWJXNZT[Q\]dNYgqwuykkzych|zׅ؍Ռٖ҆ڤ٘Ӌӑܣؙڤ۝ڞٝءڰޯפ֤۫ٳԦڵٶٹ۰ׯ׫زծѭҮҭ׹ݩȱ۴۴⿵ǷƷµ߿·ƻĸ߽ƺQ=YB_A`C`CY9b>bAj!L2[k{}}w{τ֋}׊ՊӇ҆~ӈ|фy҆yυzч|CRAO@N@K?KAJKOeZ}drpurnr`MO-B,B6F=K>KAL@N@L?KAJBKGNCK6Jԟuwa`YUSKSEUHSMTJPY][aT]`lywtslm{uckzyyxЀЂ||ؙٗؕՈהݛژܜښ۝ڜ֗ڜ٤ڤڬڧץتٵԯٳ٫ף՜խժЦϤǓԲ߼ګݷ߻ʺɸݻ߽ĸĸỮڭźʽұF:Z<]?c?Y=[>dJHLeV~bmrsxpq]RS0F/F9I=I?KAL?IBLAJ>IEMGNCJ?Mԝs݀kmb]YOOGQGSJWO[U[GWfnnourmqwqZcws{yӄkmtwՈ֏ؔ|ܚݠٓڑ۝ݡْۛםՐܙۤכףܭآٱرעإ֩՟՞էʓɗ޼ܱ֧߽Ķŵó޼޾޾߿ùĹòғ֖ྯ⼮ѻepQ>Y<_?_AZA`:cB\Dw(Rv}}x|҉֌~׍։֌Չԇ}ԉ{҈|ԉ{҇{ԇzAKBO>M@L>I?IHPh]jnuuvnr`PS0G-E;L>MBOBOAMAK@LBLBKCLAK?O̗pgt_k]\YJO;MEPUXIUaiqnhintrpUcvs|yyvtwԀ~}oyԇwxޙܙ׌ڕڕ؍ښ؉ؓՐؗшҏמ؞٠ڮԡ֢֞ԘשԝΊ̓װᷝثܸõ⿮ܶ۷ܼྲ¶źǺע·ףzxܪγ[>XA_E`?^=Z9_;[Cz/][s}|vxρӊ֋ֈ׋Ջӈ~щ~щӉ|ҋ~ӆyӈ}BLJ>J?KJRi]eptuvmuaOP.E-G:K>MAO@L@L?K?K@HCKBJ=JLTŌpf{bj^e[EP@PLSBQbjomdflohiTbqqqowuppwusuՃ|{sxڐՅمݚٌَ؎ևܖيҊ΋ԓהؖڙדٟםԔ֞ѓДɏӟಜפڱ࿳Ƶ࿯ݺ۵ܷ۹߽¸ĻȻἪ˅ءxu͇ݨÞJ8W:`C^?X9d?^JL@L@L?JAK>KBJ?HCL8Fadslfj]i]TUIS@P_fpqhjko_eUcrsqptspphlnr~opwyً؀ׄքՄ|҈ۑݓ΁́ؓ׍ٔ׌ٓؒؐՌӋӗҌɅˎచݤڨṨ俩㺢۲۶۷޺ݻ߿··¶Ĺʾ̽ϏҘ}ԑ́ŰSeR?[@^>[B[@dB\Dr*YjzԀuyЁӉ֌}҉ӆ}Ӈ}Ӊ҉}҈|Ї{ъzц|Ј{҇{>JAP@M>MAJCMMQg\grtvrmwfTV/F+B8J?N?N>LI5Emj‹|qlq]va_W;JW]lk^eip`gZgpqjksrmo_lcoԁnnnsيڂtqÆvm^x`l،ێ֊׋׉ڏՈ׌אӊҏ~ǀڨ߫؛ߵ忨໧ٱׯٳܸܺ޽࿴ö¸ùøǼ˿۳̍˄qjK[όؾN 8T?]DaC[Eg&KcBaK>d~yz{zӈ׊Ԉ~ӈ~Ԇ|х{҇~Ӈ|҆zчxш{Ј}Ї}хzBQAN>LBPANEMLRj[dpruopxfPO/B(A7K@N?L?J>I@J@L=J@H>H5EifǓpe`}am^MW[a_fci_dVcjnqrhkmm]ffmvzgkpw}nwJmhWqJhJiPq΄щ^~ep҅~tЁvHrh}}ʀచܚڦ彩Ṧ۵ڶڷڹܾ߿¶ĸøĸŸʺҔlfi@]Fk!Qgx{uzфӊՉԉ|ӆ|҇~҇}ч}І|ц{І|Іzχ}σ{΅yBOANDQ@NCQDKQRjZgpstsmwaRR-C+B3E=K?N@L@LBM>L@J>G=G1AadɚwkpVubwZLWY^Wb\aSdhlmjhidi[fbhingkmurtu~]{uZtQq=^3Zu0eƍӊmc^u7nNvKr>fn&U^Np1VNDљܠӇ۬⸧㼪ݶ޺ۺ۹ٷݻ³ƸøĹʽ㻢|sHM3G@QXi᯦гU5T;_?]=Y6_;e@WDBd|~y|z|ԊՋՊԊ~Ԋ҅{҇ч~І~Ѕ{Єy΄~υz΄zЄwAOFQCOBOBNGMNNm\dopvtnyfUQ,D+C4I>M@N@M?KCO=I?KAI@H8CCIОd`ReTXWNZS\Z^J]bmjlgheh`iflemfndmqtmvNnp_|TsJj\K~GQmFxh(_k+e~K{k.fp3hVDO=SMU$Xuђϓ彩ศ޹޷޺ݺضڻݼ߾࿲߼ôĸ̼բd_>J=M:IBP^lݥ̯NZTB\?b?\B[?i@YAXEds{|uzӅԍҍԊӊҋӉЈЅ̄~΅~χ}ͅ{΅|΃zфxBPFRDN>IEOELQPj[gosrsoy`ST.D-D5F?M=JBL?JCM?KAN>H=H8B$B͚jWVhgoiV]V_KZ[cklincgZdagioej^fnpfoSqi{^vV]Hvy3\j#Vn"U}:uZLLIys9kc"ZrAqQAG @NKÔooП᳟Ḣߺݸݷܵݹݷطڸܻܼ˻ڰNP;M9L9IDTSe~櫜㸛m#:U :Z=b@`=Z=c>hASCz0Yy~yz|Ս֏ՍӋӋҋЊч·Ї΅~υ}ͅ{̈́|΅}΄|IUFQCPALANEMPNjYfrtrqozbRQ2F*D8JK@I?IBO?JAK=I>H?H+F樆kcUpmunghFXR_ghincjXe\egocl]gosimKhheuLwz5gv3h{4kj QcMs*aWQeT~M>K@L@K@K@L?HAJAI4EjbŔxۂlkdncV_M^imei`hQc`jai_hWgjuhmlrUpfy4bh X@rj(T^H^F\J[QvbKeYMy=t]MG @yPtZDs*Uuz{{uv֓ՑՒՓՎӎьЌЉψ͆ΈΆ~Έ~Ά̅}́{LVHRFQDPDLBIOOhZfnssqny`WT/C+E8K=N=L>KALBK@L@K?ICKDN:FH>JELFKCL4Iڕxʗq{GR`caiafJ[`j_iVeYhalej_l1X.Wu4br1e}9oi*\YEHyQ :\H~?obIfLy6cn(]u9of4kg>q~Orzmyധ亦ݳ֭ժҧԨҡҤѦزٷܴܰ|s|&I|/QNj[uf~]yyz轢᪆n"8R7[8a;g@gCf"C_=]8d<]Ak#NgutxrwאؔՔ֒ՐԑӐҐӋЊωψΊ~·͈̄|˄~̃|KTLWHRFQAL=GGIdWitxttp{dVS-E+D1E;JK?Mg@b=\=^;eAcK=^oufq~}חؔԑӏԎ֏ՑՏҌэЋόьЈ̉ʇͅ|ʂ~JULVEREOAMM>J?J@K@MCNEOIOLRIM8IznŝxlaQ[U^Tcan[pRd[rb|\}T{{,\y+^2b@nx7gaLUEu2ft2_bIk*X`CdKv/at3gx8ok)dJgkΞ߭٪ױԥӢѤҡҢҠѪөޮꮤ볪诡gj7P?\JiFeurޑSRW 8Y>[=a:g=iAgAi?\9^;c<`Aj%PXilsgrю֗ԖՐӒԐ֑ӍӏяьюЌωωˉ}̇̆{ʂ}JTHSGRCOBM;HAIaW}estxxqzgYR,C)B.D:L>L?K@N>M?L@LBMFNKQMUKN?L`dգwY^^fJa\jYhUjdkajPkVgGeu*Xg!RbO{5gv-ai$W]Nl%^Cyw4dX;\=^@]BT<^PFnu1keК֢ժңΙϟСӣџ̟ԡ골쵪볪춭ﶤ~?Lw%Lq0R3\c}zx|7HV;W;]KAMGPNTPVKOBN]_ԥЗkVLTWdZeWeLchodj[hD]}$DiHx3`XAVDk)[r.^?oVGl'[m/ibZAZ=X;R;M a;i>jDk!Dk"E`=];a:`<]FUkuufnŀ~Њԓ֓ՒԒю~ԎӏՑԐӎэьщыЊχ~υỳ}GVIUFQCQCN;HAKbZ}jxuwwv~kYX3H'@2E

    NBOANBQ?MAOFQIOHQQWKPFMFPاÌDKHQQXTaTb_eQ]YhTgHaT >~9d]=[@\AYGy3gq*Ze"Vp2dVJ_x1dl*WK 7F8drVgԑu٫٬ݳҞʑʐҩҙ܌藎꩞봦촦÷³[^-ET>m!G/Y‡ˉg=Z=^=bi@l#Dk D[8\7e;[@s)Qovoquw˅|ȁxʅ~ьӑӓҐԐ}ҍӎՒԍьϋшϋЋ|͈~υỳzFRFSGTENBN=KANa\~hsvzwp|h[Z2K*C0Ef@T@E`yvhpˆ}Ћ~Ƀ}ɂ}Ȁ~ʂ}˄~Έ}э|ҍюҏяόьЊЈ~чzІ|Ѕ~́}IRIRCPCOCO9HCMaX{fuwyut|f\[5P-I4J@QDTCQFSCPANANBO\WMTQVQVRWMSodﻚMOLRU\\c^g`nJ]/R`FZAX?x7bXAh"MdK^F^Hf P_KByG{r/kU?3B\nj|ߟڦ؝Ԛ۵֬Й͕~}{搆斎ꪞ쯥￯MĶŷȸ芁:Go;N 7n%PYx̎{+M_GdBf@k"El"Go'Gc>[;c:_=]FcovvqrӒЏ͉}˅|ǃ}ǂ}~{ǃ|Ȃ{ƀy̆~ϊ}ЍύϊΊψ{Ά|υ}́x~wHSGRBQCOZ?Dfՙ1PZ>fBf Fh!Ej Cl Ca@_;e?X>y-Syzpq{Ԗђё͎~ʌʈ~ȅɅ|Ă||~{~zÀ~ǃ̅̈́|ʄ|̄z͆}Ђw~xEPDQDO@LCM9H?LaYxkzyxtt~kZW2I-I7M?PDTBQGSHSCQCRGSLTRWOTOSNRMReWNLJN]^g}eVuuJl-]K7u;nd#VZBT =q-`|8dX:`Gl+[cKbNZI|DtC4h+Xrv^l۔ډؗڰخԬҚЄႅ⊈甏疍꜒롖쯢LŵǸǷﮟY\1GT>T<3W؟4QdBeChBl$Hm'HcA_=c>b>ZEYpvqnrω~ԒҎАύєѐђ͉}̈}Ã~{{}}|}yy{w|Ɂ{̆|΂z΀wEQBLAQ@J?K:I>Ma^~ozyx|t|fYS4L)F6L=QDRBRFUDREPANIQLQQRSTUTTRRWmen]nXzgWcIY`Pwx:ph-\YFMBgpE]ڞۓאӒڴ֯ѧѡrp}≈⌌搏虑隓雐띒촥﹩ǷŶef)EX :S>r!KЕGak!In+Ng!Fk#Gl&F`>aBd@Y>l%PlvoqsuҎ}ӐёЏЎ}ё~ҔҖѐό~ʉ}„|‚{}{{|||z|y{yz|||ùzCODPBN@MAM;I>J_\{lx|{yr~jZU3L.J6N=PBQFTDSDRBQEQHPMRRUTWTV~{ӄfu R&@)AS_㍅薋瓉ꙍ쨝ﳞﯘڎ{Y]hJsu~aEm&Ip(Ho'G_?_@a=fD\CWlrvjr҉}א{ӊ|Љ|ϊ~Њy·|͊~ˌ΍͊}ʇ}ɇ|Ɉ}Ȉ~ȉƈĄ~z|z}szpvBPESJWEO@I9J;I\Yzivxxyyj^Y1J/K7M@QFTCPCPCO?MBKCLHOJQ_b߁xqiтsMb~8Z_wSa}.LeLHl%as:pe$\}JvUBh%SV?^N?lR 5[9Y?m2Y`MH4pnnuޠܣ߼ԜӘܾ_ZPWZZ``ARvqQYGZ>O7OO]⃂爂鏆짚斊ZbDWJ[OZLQ4Dv @T>hKewu~q$Gk&Jh Ep(H_?b>e@bBl"MivmpssԌ|Ջ~ԉz҈|шyψ|χxΆyΊ{Ќ|ΉẅyɆyʇ|Ɉ}ȊɉLjă|~tzpzAOERCQBM@K8F5F_Zyiuuwwwl^Y4H*D2G>NBOCO@J@J>I>I>IUgzrlq|rkpgiqi=V :d2c{;xOs.lJ{THb%Ri&Wo3aS 9RBJxa OV8a;S 7N?I[Ybߨܚⶥ޼ץܵ>H-@'?w9s7l6q5b 3,E\hV^W`kq}z酁gg?Q{7l5n:r>!>r=U;m#MZoy5Qh"Gn%Ii A`<`>d?U=|4VwwjnɀxԌ{Ӌ}҇wφ{҇wчyхwχ{Ήzϊyχy˅w˅zʈ{Ȇ}ȇɈƄ}}}x}u}?L?MAN:J:I1D0FYUyfuvu{t}e_Y1H'A4G6H>KCM=H=J=J5GG\᧗hpbyiwlnwx)Nt%HE<{Ks.bNo0ey6rgPBg)W_OxBpX?S:UB[n/`]:Q9T@okғߖ~ݤྲݵݷ8F;i8i9i:c;q"Mqr#DU 5!AddY`ejsu脀UZeAcF/W:Tc9l?r>f7Z9j!KNf5Rq&Ln&Ge=]L;L6G/D-B[Vzesyyy|}g\T0F+D5G?M@L?L?KBJ9H6ELW쳏~xpf{h\ifimELEv\>Vr&MFdDžZ>cIisusxuԋ}ӇyӈyͅzЄyςvЃvЃxЃw΂yσẍ́{̈́v˅{Ɂz}ł|~zzx{syqxoypyBPAO@N=M;K-B*AXUziuy{~x~h\U5G-D7HALDKDKEPEQHO']D\DUA@j[?X9_=U 6P>d%LIbǓ̊קfhT^N\7Jw8U`3T}+O_puGRBOO]Xbjp銅϶JXRl>Y8Waۉ,Bf2g4]7X :v.RBdє7X9WgB^x-PvuqsˁyЋ|шyψ|΃w̃x̃ẃxЃxЄy΂w΄zσu͂w~wǁz|}zwzuzpumunv}|ˑCPCOAM_Ev/O9_Ԟ8[:WfE^=\9h=Z;H`vvrsϊχzЇx΄ẅ́vˀx̓xΎ̓v΃y͇y˂x́wʀv~x|wzxvywuovpx|Еۢ⬊FQFUFP:J4G,C(?VUzgt||}yo`V7H3F?JEOLSISdV[ 7RjՆry`m^QVLLMn3eh-]MCt>rg/ak.i}G\eS[GW>W=]?]<`@W7H7?ULVڧڜ߶ŰXZMYamgomtotksgpO`J^dpZhЀݑwyT_[jYaak愂żǾޏu|foYhM]%A'C3Eu;_;cEx/O}3^؝Aa;Vd@_?`;eCp(KcppqxvҌ}ψzυz̓x̂xǂ|́vˊ˃xʁz˅z̃xw|vytvusvrxsy|՗}ݧ䯅将汉ERDPAP8K3E+B$=TQxjwzy}nbV6F/D;HDKKOGNY[vӀs<]l)V};cS@VKUPnpYaQ]!Tj)cOs^@\;_@]>Q 8N:smswؕڪȶ[Y;KV_gst{uzw{suprmrfnowx݄~|YhdlZdWeܚ}fpbkYc?NDN9E{8]8e@s*Ky0\ڟLgy.Nc?[?h!>[;v*Lruim̈́{ъz̄{φz˂źwʄ{̂yɀvɂxʂwȃz~x~vzvywuuqusyΒި洅鵄泇賆籃BP:J:L1F0D!<9RSwgw{~}lcT6E/C:FCLKPHNLZoxVm@bo.cFt`NREq1j}BPg.by?pN ?[Qt7m_(^tHw@u}VV>[@YLNuhvz}y{kbV7F.A;H?IFONicgĈrlk+[e%Vj%\BzbDXXHN?ZPI~IwB{Z{?e}1PdE]AWb>p@v%DjLܝewk>b;Y;c<\<\irrvuь}χ{ͅz̓ỹ}ɂ{ʄz˂yȁxƀw~y}yzwwutrrtuxם趈귃괁籃鳄綉7L;O/F0H(@!?~_Eomv㴡o7Kc=/EMUT]X]bfmpuu针Ꙏ꜖頖界薌琅|utstkm_bZbho馡泩ތޅuveo]j\_@Kr?d=mAx(F` >Ւŀc9Z9k @^9.HtnqpЋ}Ћ{̈́v̇|ˆzˀyɀyȀy~zz~v{x~{yysrjpȅz簁췂췂캃츆鹉꼏šà/H+F,E)E%Cx=|KXtlyxՙшy·z̆{̄y˂xǀy}{~y}y{u{wzwvtmqrr᥁︂~츃컋ÔŜŜğ/J-K.K+J|'Gr>u=NPwks|y|sibW3G&Fa}8NRrwpb L{7oiS_ TnqJn1ky@Rj-exHo3f`$WUB[@\BW?u7_}+L^mHN-JEVS 5T:YR6\lʄcoV9P 8BUxmsnӎ|ЉyΆy̓t˃v́wȅ}ȀvāyŁw}u|wwtuslqՕz츄}Ǚ˝ȚǚȢɣǤ5K0K/H)C|Q(@DLSXX\Z_bckolovswt~|y}yuppIRY`glkm_cW^yz{vums`fZ`4MR>]>j@~+Fs!>W 7B[ώtw[:L 8_g{lzqыy͇z͆xˁvɂwɁsɁwƁyā|ǀv}vxvunovt~︁ĒȜțŖǜȣʧȦ6L2I/F*B!=uCJRSWZY]affjloutvvxw{{|z|xooP\`_LL7DOPRVad줘vtttmr`gUY_>TA]Gp?|(Br)B7Ldh~twxx||ng\8I*B8H?ORhMicJz7js0_TH[h&Yw;tp4rVNocj0aZ@6SЄmF5TN~:]^HD_^tIQ`jϳK5V 8g.Oc?]6gDVe1AJOQVUY[]Z_aeklonostsz{|z{{{ytshoYa_afijwᨫ簢䑊{{rxel]_bBYBTDdE/J.HuCVimuyvy|pj^9I-G:L@PLesdQu6kp*f]m1]TOr1jm6oRcyGofcN|/UJ]cL\#I^Oi~tӧQXOcֲn4M[J_Ge$Hk Ea@h"IXi7IKUU\X\Y[^cfkijjkmruvyz||}{xxwtslm{y箠㈅鷪沦⏆u{ntdkBVVHWEVEm&J5K|,Es>n!CV<Ät|1Mbdyh}nщy͇{ˆyɂŷxƀwǀxz}w~x~w{txtoo{s|}əɛǚǛʝˠ̥̦ͪͮ,C'@'@*A:!?DVkq߂wxvz}|ohZ;H)@3G=SnTsn#Vs,fhd K^'SZPm/cm,cq2nWo3o`{q*^Swx,QQ7hGf|DŽҥÍ=NgqYZU :_MIORUWXZ[\^ddikgkikmlttwwwt|{wuvuvvxv叇ĵ嚒쾱鵤qwlsfkdBZFYBVBq&H4J*B}!?l6S8hp{CYlawaτsЇvʇyʃ{ȁwǀxxÁy{v~w|u}x{sypooˁqz~ȘʜǘțȚʞʡ̨̰ͫͪ(C'A#=%>} ?)A=Qenxvvz~zni[7E(@1LeH^\yo!ZI~My[Lj.ag+^d&Yx9gg+azCse'eVcgCMT>9WKeViȍԳALAV{tK :nAg@f9h<~-Ef<_ 8L\>TGPQVW[Z\]_cgjlfgefgijnpqqqtrrprsyx|暔ʾ堡鷦߅msjuI]T@[EXC]Do%I4J+Ds=k;S :]j}M`paxi͇wΆw̆z˅xɀuȀx~zĀz~x}w~x|wyprolmЇs|ďʙɘɘʞɛţ̦Ϭͫͭί~$A{;%@%B @$@;Pgp݂yz{}}|ph\8H%FRkKbARTvgSru>x>$?};&@>Rjq݄{|}}|peW6I6[]v1KdzSt^Mi(Yk,Zb'Xk.`YUh/kfP}Cxe*cO~OzJ}}>sxmٱ˹ikFTzyATV?Zx>}"?|?2JE\lquy||~}md`Aal.HEamEii&UcMZF_#Qi-al0he0l~y@{KQCxR}k2m|@vrlX\ǻԮ@OYg~QAd>V;iv@}"?w=3JDWin߁vy{}{y捂hm'D-KkJe=em&YO|R?UJy=tp6lf5p^ \{GY|Av_&[Lou{V_ײLUkgԜYC\FbBZ;^8m:]:mV@g=U9d9jl;s:u9s:3HATeh߀sw}~{勅wu3E"DMmazMhs*XxCqy=cZH^']m2gy>yf^R~Le-bcXZy]iɚpk謇j+NZJ\Ff F^ E`CbBfBi!Bn!Bz,Ga@2M4H}$@8GFNJLOUWX\^^dfghkljgd`aXYX[TVV`^ofy]r[nsywtcegAWCXA`@a?i.K5I(C3Kb:m$PϏ}nׂn˅vʊẍvȅxʉzʅwDŽxăzƒx€xy~yyvytpnek槂ΛҤϟ΢ϤѩҫѪѦʛɘƕƔŕbAg=k:k8p<>L9K`ayqw}||}tf]4GHp>\Lf]NW~k)SVHm9l_ S^#`Vaer8qn;x}[Rauܚ𪆄AOVK[GaEk A\?e?^?fCn Bn"@t$Ae?v)I1Is!A+A>GAHHNPUWY[]`fgkkmglbg^_]_\`TYQWS\^iz{owtq,@[@S>\?bAl%Ed=i<0J/H8I|#?2Gl=l#Mѐ}o~oʇwʊxʉ{ɇ|ɇ{ˈ{ˉzLj|}zx}w{xvqklae竁ҥӧТСѨӭҫ͢ɘȖəʝʡˢaAfUAU@[AdCj!Cch@`>g>]:j?o;o@e;r"@p ={%>}7/>;EDKPT\`aceifmmpoqz{}~~揉葊扄x~|vv"Cq@SAUB_Ek"Dj!Cm>d<8O2I;O&A3Iw"BiEД،|znʌyʌzɉ~ƈ~ć|ƅ~Ņ|É}ƒ{}}|vzxtuinbk빐֧֫ҢϡΣ΢ϥϤΠ̢ʝțțŘ]<`?\=]B-FEPDPb_shw{x{|qhY6H%E@YFhj#Oc QNt] MQHu8fULc#_`q;p\!WVzfRqk;cK`Ldl-PXHbF[Eh Eq"C[=k!B[?h>\;b=m>mz!=k4"96>CITY[cbjhnqvuw~}呎劇猉則璏⍈v{nlW :o#CXGVG^Go&Cbf>>S6N>P/E-D~*EbBҙ׉{rʊzɋ~Lj{Â}Å~~}|{}|yzyxwrqjmjqŘڬբ͘͝ϤѦѥ͝əǗŖŗ×^@^@Z?Y>r A=LLVdaulv{|}~rj\3H|"DBZw,L\Fd)\GiYKc"Ro/_SHMMn\d%_s>xVlyf|QxI`i+QT!KWG]GXFjDy'EY@p$A\AeC]Aa>d?k@i!@lAp"Bi@-Ehe"K[$NX#M] Jt,FeAd@g?CU7J:N2G2G/HbDԔ׈{zsuăxÂ{ƒ}}{}{{yxwvuqtekwq̚ڭҡ̙ОПѦΡɜŖĖnybJHX>]A[f>9KCO_]znv|}z~pdW.E7`{\|KB{6`l(Ri$Ph'Ta!OSFPOhxs9oj.iS[^^uhJFUJZIZFx&E~,FT=r(B]@_?d@b=]=e?p"An#Ds&DjA|'C.Dv>x ?&A(E6M@SOaXdcmn{u}㊈}y~nuigBHUB[JZ#N\#M]In(IeA`?jB?U?T=Q4K9K,Fm J֖҃{gg`bmirrxw}|}}~||zyyuwmq`lʏ}П֥Ϟ͛͜͝˝ɗĔ﹉udYz&=U 7R=bAc@W=T:c:2A3GWYvjy|yy{l\ZSwЩ|-UasOFh)Uo,Wj&Rj'Sc!MSERJ[p[p1ed$YPcS{{o*YrKBRDYEz%D.GO;t'C\@]>f@]>`=b?g Bi@o!?gSBV3K8M*Dx*PؑztXZR[W[]_ehcjknqryv}zxz{yzqrip]hߩӣЙʔ˖˛ɗǓ櫆Ѕq0AUv~MkPxt5`zKB\Ez)J.HUCv-J]E_E`@aA`?cCd@m#EmAe>g>3G@QV]_dZa_cceeiillptsxxttsuutۄᛉ䯛鹤h<`UF`F[DXCk#HAS?X>U/J9N1L~2VܓnmagdfZ`W]T^V_U`Yd]cdjhomqpsnrhq]m贈ћȑƏəəɘ鳌ۗGQ]=Z=o@1H2IYm`An$BmAiAe;0IEPW]X]Z]Za^gijgkiloqknmnpovsߋ~❌尚繢꽤꾧Ůe0RO7L:g=8N>T:R-I6I})F7Vڎ|mlqnokmhfgaeWbR\LTIWLXS\Q[S^YbS`P`识˓Éœșəș칎ؑt3C]9i;u#A0F5I:Lun}N_3M-HvS?[JUzB4\J]z;jd+YMC^i{B{me.i[Tg_fxm"Skl%Pt Bo"CO ;~1F^@^@Y?g Dc E\AeBgBv*Gp Bd>{(CEPOUW\X\]c^degefjjkmlonnsr~xߐ㤋尕沚趚뺠ĪʴmF:d?/GN8K8LHQEPP]rwNZf9.Bc`t}zyzo{vÈszD8S;bFaEq-T_Jj*Q]Fr2_a#KQ>^!NSKyKsh/cd+^k1hs@uLW{ipDwi&SjSGQG}2Oj$I`EYHa!Hs*K_ I`F{.J~*LLTx%EkCJZUYQ[X^cigjhkjilijinkwsv{⒄㜆䟊姌誎범칚ĩDz˸Ӻe6c9{'@{%CeEkmqh|vƂvxzs{uzwxvvxsvqumrjsdlc^mV\P؈j˗ΚΛϜےj2Hz'FAPX>] Jb!Jb FUBVHQf&QVG\!Mk/`VRJxa%[o4ij0j}QSiv`k,OcG5M=y,Eo Ac@XAbAq(G_DY;v(A/HUW0Cf?DVIS]baa`bfgjhihhikmomuozqy|~㙅⛆墌稍鯓뵗ŭɵϽٿZmY8t:m>]=vtpd}tss|t}v{uzyxxuvsupsjtjnl^rUeRwРϜΙ̘뷅`S)J>O=PAQGWT[JT@QATJZR7|;\x{k>}#@gcv~}ymma|?XH 9TAW@r4YTAWJZC`N]ZI_CM ?|=hSHr6k{Cvs:pLj3mWObsE AS}¡G7I 9w)Cu%CaUSU^_ab`fddhfkilgljnluqysv{}⑁♅䟊妎篔곔ĭdz̹ε\i9W8~uofƁxs|t{p}uxuvtwwuvtupsmpgjd\z]ֆdҠϜΚɒs7G5J=OAQHVQWIS:NBQIWK`I 6g J{b:s9g^u{yzon__fr1WQCR<^!LaEWAVDT@dPaUAo+SL 9UG|=lz?rb"WuY@^Cp%B[?aBp>DLIM9Cb9BQUW_]X[dcbafekhkhkgurtowq}s߃w|ᑂ㘇䞋䢍欒簕뺟￧İɴ̹ٿjv]8] 4] 8ي{qiȃs~r~r{t}vxuxurqstruorgka`wjzǔҞћ̖ˆvX7J?OׂmxsƂsŃt}pqyq|vvupqrqqqklefid骀͗ӡќʐqJLV@S?K EnNsK@ZEe"L^GYHXHTFk._v?tab']o7qXWqg^S=}*Dz)Ed@g@a?e@_Hl>2GPSYYINjN 8` LUEh,Z^%^js;vXzxnjkJ=JKQTTFR=NETN\K]I_>TH2O 7]wu/Jm6a\r||w{wvn_~b MYGT@W>[B\Nq3^TEw9c{:aTAYGm*QT?RCb"OWJs8dXI^"V]uxVIrxjRtr.Qc=j?x.Jg@j?`;s>-AQPZZY[6Fz&CHR[Xb^`ahdmgdbf_b_gbjdldpltm{t߂x߇}~ᒃᘋ䤐䯘沛꺧¯òǷ˺ξȰ@-ANteŀuw|q{qyoxsxpxrsrqrmqghda鬄ҞȏǐӢӞń݂]XTHLAIDOKPRTCP=MHVM^HZ?V7SF1L :Miät0Hk8\Vr{zꟀnujd}c"KUCYBW=]AZCWC^Jj,Ut4ZYEc&OYD]EXB\JZMHrVKJEzJfnbr4`T8a$Ln&?d(JTr\}^{|4Vg?hA`<&B;JWVZ]]_/F0INW]\dabbhejgfagdb\c]gdnfniwp{s}w߄x|ᒂᓈᣌ㨔沞踥꽬³Ŵɺ;Ͽظh#KORyl}qĄv}q|vyrwowqysusrqjligg`ћĉƑդΗscTTTINBKCLKMGN:I=LM\HZEYU>ZEWFi+SUEf&Re'N_!KUB[Gd&OO=`JTKxBlVTyA{{Dv^bW}^Cn7\a2CDLXX^a^]}"ABSXZ`\edgfieiemffdd`ebicjcmgrmvqwނy݉ᔁ䨑䲗趢껬³ĴǷ˼̾Һ\nSR|pxv{t|uzrztxsxtvsoomonjh\uNjǑբɏgTQQRLRAM?JFN4F=NIWK[CXF[@YG`O8L 9r4XEWr>XWmzz{{lwps}o%OY@N>RAg%R{:]\AQCd'Pa"LYE`!KSKg+WS@]"Qh0\a"W~IxOOsehn3iOdw?kf.\eAbAh@k@`>c@\9y#=5EKQWZ]\TUoCDT\[dcjhifljhdgafbfdfbg_g`ldsmvq{ruޅzᎁᗄ⣍䭕崠缪龮ĴƵʻ˽ͽҢWSzkun{u}vx~t}x|tzuxurrqnqjp_v\fqʕԞņ߄[OPJNCL;JEQ:I-FKXIVEV?SDZE\CZN 8K :e)OTbu=VRoxxy{rohz}~2VZDQBf&Nf&KUDUCTEh'Tf%O^"Mh&Qa"Ma#L[FXMq6dTGvEqi-cVHg3bkg,[e)`l`%Ih?TU?VFZG[3IN 5K 8i(PT`z#?RQlyxzyqo]eq|3UaGP>]DYDUAWFc&Of%OVKn4Y] HU>^FP@g-WZBZOP[c&RNCb/WqUq"?K 4J 5]Dægop;OMlv{{zqu`Xk6Ze"LUAaCU@TEc%NYHf(SSJi(Ng%LZAR>[BWCc1ai7jNwvEzh,[d"Qh#U_j$Mu6X_:X6`>W;Y9W5i<.CBKSRQSVS?IfBGRb]c^cciflgohhdmdj`jde\f]f^iaoepgunyluބvz➋䭖岟绬Ÿʺ˽ͿѽӚ/D9L,D.C4G:H_"Ng&NQCi*TTGj'Pi)Rf$LR=]E_!KUALDo9q[yUN~Zj"GR<^=e@V9Z8W7W6\:u<8ELOTQTUOK`8/G[[c\c^fehhjekfjemflfh`h`f_d]h`jaqiriwmykށvކx|✈㨒䯞纨龯ĶǹʼʿƱ+CBOCP;K7J.Cw'Aq"@m">k!=6HXVm_tےeޗl͖ҕjXM-Bx:1F1E2IDUL[=QAU>SI]J`AWr%?iR?b"K[GPApV7[=T=U7W7g:+ABJNOQPWQ};e?OU_Yg_e`gdhchdhgnhnilejcj_f`e]jag^lendwl|ns߄tމy~㞈ᢎ㬗嶥軪³Ÿɺ˽շN\GROYKTDR;L.Du%Aa=V;P7s$Gښx…cxϔʅ݇X1Bv?'C4F(D>RO_FX;P8PBXPdI^}2Km![;9I^Xa[c]e_kdhcididkglgnhmei_jbh_g_j_h^ngrithoށu߅z|ᖂ䝊㨓泣纫迱Ķǹɽ̿Һ~~?PPYQXNVFU>O5Lr&D^;M;sAy}ݍ^ﺀʈo7@rRCVSgʰ@QMM~mw{zyp\][ow2WXCV?X@ZAW@_!J\GXCUAa%Ma$O`#Nc%PVF\Fb#Pb"Jc&Th+Yh(Xl3aUw] C]?T?W>V:M 7\:s;.BAJUSRO"9T75FWT\Y_Zf`e_ifhbiegcjfohjcpkjalef`hbkdmfjbsguhyn}qއyߌ~ߋ|㚈⤎䭜崥软öƹɽɺͼಠ3CJUSXQWHRFT;O1Fs)Di>(Fq}rgHHi;k<)B$@2JHWJ]9Q0I3KBYWlNhAX5On"Cr,H{2KSd_pzŨHVOR}lyy{zvY[^sn&QVCWF^F[E[Fa F[ESBYJw9f]$Rm2\s5\Q@WI{@g`!Pm3^_'Uo4gL{[f'Qw6^S=UZ5lf`"Pm0]P{a"OTDz>fL>sDim1ea&YzBj-Zf+TN 7Y=TUBX>W7Z2_8t9/@7CBLQTVVZW]Z^Y\X_Xd^b[g`g`e^kcjekcoiqksjokpfnemdkbnamaoguiznt߄z|ᝋ⤒㫚㲢幩ķ˾˿ϼɒ5FDQKUQ\U]P_R_YbVYOWXW\Z=O7J6J9I1C*D@UQbFW0Dx'Bt%DEXUh_qUkD]v,Fo#@o"Aa>a!Ah$Ev5TLi̱gmNUvcx~xj`o&O\#KTB[EWAf$N`"Na Oq9cP?XI{ChOBb%VzCygJ ?p2eXzA ;s3\v?mj3gbvApj.RN;TDJIOKRMQNXTZV\VZT_X`X^Y`YcZd[h_f_g]ibjbjdpinhroskqhtkskrhtkrgxixl{mށr߇wᤏ⫝ᱢ滭迲ķȻʼѷ=T=LHSPYUa^faf\[VTUVQTIRJUUVNU>OSp)Ff ?h >f;v"?[<`?b!F@a׵ñ߿ʞQWwfuw{}x_im$LYCZ@YH`%Lg Oj#Pu1Y_Np3]^!SPxYIu4ctFIKJMLUQTQWP^V[W\U`X^Xb[]Sd[e_e\c\ldiehbkdoirkpfphsirgwmvitjsexl|n}quy}ގᜉ㪚ᰝ䷩羱öǸʻζhr7JGQMXP\]a]`][\XTTQRRR\W\WIR>RH[@Y9S;S8M1HH]cpivZjF^t*EbYC`!Mq/Wl&Rr+Tl+Vl*_^k(Pd!Su3`o8ft4azCm{BwNwi/UREn)Rn1YXGo4aj&VVvv)P.@5A;BGHMKQQVSXRZR^Z\V\T]U^Yb[^V`Xf]f_`Yc[hdkeidpfohqjnhrjriwjvlwjwkzmxotszߏ᧕㯞䵥幭鿲ķƾ̹ЖDeFSBMNXS\`_h]_W\U[Vi\iYWR?L=N3Lz2P>Y@X9Q=RVejuhuObs,Fb>]5c:t+I@SEPscikit-image-0.9.3/skimage/data/lena_RGB_U8.npz000066400000000000000000001327011223313777300211540ustar00rootroot00000000000000PK̖K?EMP arr_0.npy$ux6?n d:BwL;(̯Y23381NbffFɖeŲLLδ{廮z/IVݿ^ CF _ɿ_W)gJyjF/^)Eh)O+w_OS?ӿf%x Rܹ΂hw̙pfzUG1g1o'{8ޑ%qi HzoEA4" 3'X9`@(8!f*ѮPH +SʍueȜbg̕.uf9rGҙsf)E/?&߁6Lo !kym!o 0YpyM>oCnpXHΥ!-& F ̅2pXkl6rFƁV9"3IrW$y0ɤ ZgV ڕv+l'Ã,;CPHݙr{̞ˬiJ.U`~gm([IGpQ c3SLw&41gXE1k ^g^rF ;xeGf>!=̔j^WΪb˔'14cۃ}aI@{q}a(:M$Γh h0& e@Af!@-`BY(C[|@lY⃥ Ƀ6|sMIHчer7 2p@xl0w^ !3BdX=(Z̓GZOAa0O}Nǹ*oēᛂ'C@ ~}wƇީ^^2KS&h83f hΘbgy&sX Z $uDE?]d݄}›%;ʑ{L;MӞN+˵KUKt 4x NG0 HB_v =(T2ZFa@&an [<֖ QE\DX.8\XdA\OD\#m3-2ؔM!72s dq@ Q{C Q[5Iʎx bU"qƛ+ՇROșRZw ~ܪ.p庖R7> Tše0gf8@|*9f )ź@ļ.f,Q(G V8מTNKu'e>)Pj4H^pB}p(<'S&8tH`ɃL|& f,<s,|&mAf>lqY-\o_x %[6gBY"1IL|޺Flbao@ukře fY1芢`5IȊ>,?*?W{ E:߃|aқ:P5t5Eq܋nJ; { 1ğ-ms! tF( ;,jfML&d ƒ S2Ċog`W}CBug7 04':Dҽj@Kj<}?̀Q4Gq'?OJĜ==9BYԮdϿazpQH\'X~0 ?Nd2H_LEh>@@pؐ d :`np #1Yf_oe`ml?h4,M6{]g))24h$Aq8/x&̂cbl(}B_LH5kL:⋵,#9 1ȟ@u3YAe8F&Y,`+l H,k(6NvJ{ޕɍǸsbݹZO AO8 ʕqei٠iZkz/-aMTU7YكaMI \>2!ı.Q? ns nyEtGy"=Ӓ7eץ|7K?R1VMD{0; 'A'9"uF_ЖY5&(cb ',h  o# yA_+`l0`h4f|fPVZgg0h6b0>8A0|3f1ML:FIi*ocA.(U z{ޙ˙dAtg=9jwB* D,+MP$AlW+Vm Vau@]  G0.Q.Ү>E?~ _ b_ 8*НW_WƼ.ӟ^Og`/T ]NAa꿊l?7;!?%D#)i2 @`3 6C- bnlBނf&{?uFZ!VHE2q#AP@4Aulo C ql@4 YYT,1M㙣hXʽh5QHqg=R:']" x :ZԖ(:}Ɵ,u?hŢa& e@bp@sb]\d\ d߄ ބq/1/ +94q*$]tV(9-TiD2Bb7Q!=|@{,0c(WȤe*@,ا # 20Y0Z> H[l~D0g,UM}]*WDeZqzyJqja|ZƌH>O$.H *md@@v6 hʿhoDhóFc8*-1*k֖wd9t. G<8̐zAK{R$-A#9w{`re\aŏ58c^ uĚrk|@{ڥ@Zvۡ+~%r)@: H)koRF]:V^^]azp~vaf׺VR<%UO *€ <*_d&lLfQ@_*ޏV{j0{Ιugh*wʝ*;LSz3$d+IL{z pS~0=/׫~}q϶r3M(Qb R6\|# l} κju%TgcUj2D.sDLymM]MPZbk]TwLG= C |GfФ%%F2eB64B-c\nA䵸In+aJFy9DOXJH6dedgmTl回V0?4>=ofzns;F]m.Tۗd4a"mȘ#2gpI4e"uFk +wū1R'DzվNiWTXU%y8- jM#8PsBzюNP\?:_ _ğn%ˁ0 Ε[~:},]#+5d,y cd Vϋ%bt[JCa~VmTc #FjAU!iE#PgyL_&WHu:`TEorXd86Oi)&#eŚyn\43b>n.:ɐYgyQ5箱xs>Ouq]aāHs༛pmK_E1_~_@~[#|| Igٲ7oJo gibw w1!Ķprg(c{H(~9cK^$(U`:@J6iD)9yC1&)9t-IvEjf5kzRlBJ!/{xz>11nL;-nlk5ۥNn@қQ CQaN Rx6֛8JUjq*^f \ ʥ+F8Kuh6Z9d+A⎗d5,<7EW?b'fz&\Q_EͷpےtMD[ģ&Xu)|[yWz[{/;)_V}VuT3 FƵqp|w(7 3PeG#Vd֩tEce2a M$`31Cg/3,T5#j݂BO)I@_=9謷6Z=Ρ&`{9`؀ku][6>/ԋ$=V8u0 ڦS%U'ZopGlBlVIP"Orl~䫈g_F v%,SL~^~[~Rh)ēV|*p#u:`خ?~AE1i`T02}^2d /} bi OLSt{j^8[>,Yx%1FRSK`rw$mƵdG TI(YWy}pL7PQzbd. -hytg̡X7Ayz x)}G~akAA0`ڕ 'q_R+r>:]{ہ/xUd]Э&xv){WzW[,P'G_DT6.U# tqZg77EfyaH] @] dQ(.`'龂z%I2?nTQXu&~]z[?[8Ĵd_"1p`Kc{#QaG%REuX1LhHiQǚSXcxz?9D.płHfP)7T굘hVRAZ62R 꼥"Lȑq0y8?{ǎ+g3ͷ0\g! j@2P>IVS4'A'~ _c&q}0V厖uR'FI“ٛTMXJnϹOOqƻĺ̹Uaf :x1)En8^T׈M~{H܁z*~Sȯ}Ss^>IY% Nxc@(_ "# b <'H>+4Ϙ$2AM`P <~Ɵy8UvM2hQ]7Kzp^w;?r8;pi9!q9)q#7e*c"QM~~ s?T}4 y,9ל Ti={;ăπ^@,>H<-h$D9_M㩫,8/ 7 ੓XmKqX\Tn藤Mޠ_ErX-)|zvFZ}.gs ʘwy b4wj^<1|@p~T]27QM] @&>>G]O~y2lsOeO|O/(,.g\ |] þ¾, $$$NkcWӓv*2w2w+MF={Qu zEQ@}V} ĤlՁB0WUEԳo^!AcC@ #@pX؝O!ch:LD[,-a, )-JOZ.6 9fόjŕ@u82-8}ѭP/"y.n]  %_dNK\.'ZvʓwvcjwߍxeX+SdA*=+ҟfHr8P߄? iB.'vICQ1yM9v8BSi4uGfH5@DaJERZ>8}JZU`X}젥nu{<α.:kF|8^Yz sYql]Kߓ I'Y I@?wߊcٖ'߬Gח[p[~Zd _ nHnE?݀ 4s&EjBsΔ0]SS]j)H#xvHE?ȁ쎀M.ԝET;˔H(tJ~M@Q].83p,0&H'y?REM$EgI9 iHk)Y6^̗H؜*k$-u4TX[j7Hc}dp~37]*u+)g2?bWu&Ug$)G70?.'p϶}vW/[Jevw3_/oӯ`!`jR)%i>&a37}$ 4KQ(e ?h D _|Џo|K{^Tw&ʠq$Bo ꃡ`_ ?Fb^~p'Gw LHSP$7b!1ST K!-C27! %UeG5k*\m6#XwL揷 }&' ^^}0@|ZR9=k5>u'?sSlKKO&sC]acP=0dW z*mR7e*J7>F]Ts;C!ap87py ՕlhA:?2 ,RxIY:gM*YۉIƔ$KFi0'W֦ZǖU{u]u{GyrMz'=/LOچl fS>Er΀3z09b͎{7ݕ٧oˡU>8Z4w7Z'OM3k V憽#GkSKowݹTٷBپsZZJ2~P NNa R՜ FI lAPaӽib*Ɲ=z Syh ftgT/V!`d_j(=@ǝ5oӦH@e0N-l(Df{j~jk9xQg}k[O~ݮm>a:k 8ztgn{ۻxצN c70A°wi̇덹yB8};wƿD=%@x+Ds#`Iɦ$ YE$osSrYIpL@>#~.y[~W{$G˴1y ;!Ev!#zP| 0#aȗ_"ߞl:DÈH6a, g! ,'t7%i?7h$גg}Ti{Yk}R]]YxQ}PSn{^WmU4>vz_ャw[wlC>z{Z;^wvnuY,]cζ`4uWޙӕAv:m gǻ?6-Cw0ƗB}09 Av}Ncy.}LEȓ I ZcI,WoTcsF9+e/=AMâ݂r"ۓrGmiV[Z_^:l-5ڛC];=mց_v27?|YRUlu8G^'N gkΉn 0 : e ͎NtۺK S]Յ?A\=›pͨW$nJ9!ɔ#⟾]f'/u;?d\ X$jOD9N+S( J:h@|_7݋j 0/TwPT;}QaL_?ם?vf(T|D_]DG ,s.{jn~K[M1{{ɉ9 %&~ k࠺̜xZ|^m*U;ZUV;jʁ/?{)ȥMO}}M^556<٭mi2TU=~lwԹ. yq3 cGcG ½GŞd[OEZG kAj1\/ g] J\%5u#!RW_WWA~*pKA!XfڂQQ]AQ㑸=)t)@a'z45Ѡpñ=0t/ 09Ȏ  7yW Ǯ6X=[ Ƣ <ٞN%mcVq`/. %єgJK5jw\5%eyyU%K -Z?u4>kݫyxN](o|pTڅ>Lc>L? jS~GI Lk0ø7}af|tsُy%$ ]WW_[]UN:v8ds %G@:k>9:] aw"#Ala{ B9,=ч"edU1Gpqq_˷5*PKe$E4XVk]IIތNUXssO+%ֲܽ\ǣkQ(T\SU_]r衭jP_WS]Wlꁹzr_8Y8;CmX7ȮA'ܬƪ؍|gkB}5ߥ>vfg׃@~MiۉI;;;Y 3,ۅTũ[AaJk0% ok ERiR}烸eo`@mdMm@}!}GEvZO?Ld9Xy!>C2H"DA[w:TnPh9iՁ _*j%=mS'Zs22mY +KU̜\ku~IAAEnIvq*KIZnpxh`ntƻ]~رat}j<SYz7("\b^ f_ dނ3}ק<_'I;Ds& y^I*}ۧ~A9?y(i+/\@D; nDwC!e4!aJBQ̻'qs$ʓ/«~h´aQ\8CtYF&lA%|ѝ(:3sC~9*TEv+fH`rvޤrNfAELcL欮`!BUz;<(ɳvS_Xh+/-_Q]Tf)/3edZ;<+w̴z&Z>|: $1|ș yzW&Aղ4sҧt6$s4.An0oI w Y(NO$&_NN^V.:m;~y fܤv8iDq=0Xz EpșB? gſC tAtFu#| l&lV&qrkOEGTCŞFSW MqIRņJ5 b).iM0kR3M_O5 uY3Ng)*,ndu2ܼ٘iK3&sM9i r9{l+ \ڄU7w՚}8}8QBWZگ^[} D!`QwCBlHsW wiF0Uf$s\ٚX*RիBEkèW6Rt BxLˉȪg>W=O GQ2YXr)54i/clV=9Z]#m6xDs=wOv/ /^m*r"ޏjJ[)0HWneaaC䔵ؤܬKi(\|f ͹9i4\S6ؔ. ;ᄞPLG`Tv6 ǹdK?Ҽ}?ha59"硕wB\+ D_o 0L`dw@d]x?x\?TbȖ)(Ӊd,1 L L1A _^ `\  ~#^ I-ݘ[W[]8\i4+?ׇFN)7ՔEw0ah#Ooż} ,@Bs_"}^кd{ 3WzX༠R7᧭ya"cU@ժvci{8m1K2@>ADͼ@ I4[2U/R:!0b_⓾}%MZ!/5ZO}BJf%C) YYzϠt[}{;p9'2QHHP9'r9lLc169g1@wP-UfQj|s5 )Hp3??ɷ>/xT-˭e %o[+Z<}Q5pվTTr eP'bPV)U,kw6p߅~N^G>GI8 >C3b&JfzO3k.0lIN*1;n,J?b3jҴyb;L}!Fg?n`g3,f1~ p VxI3V:D7T;0QKs${1s{D"M$v_Xs,%5BNٽaܸA8=6] Pr(G#(jPqth} ]B֪ϝ+-?-*.)M)ϝ[lxrkrcqZTfKJڢPE.sb=]]6*.=NL[0$q=90sֻ)bi>q.4bID@!Qv̤n´p@ 4-_O_#oh؀nWyʁzy TnpF6AQOvwGk8_O6k5/B#!a)M` S"_25]DC;N=BS> 5KvTe.AL?v`GI=闃igIt&5PWͰ|(rIٚ銜ٺڒwU%?kdT9#5K1AL%9.}!{h6.̣.t[W10% q8z+ƅœ41#ZBy1Co=Y?dx ha>8cƩxdq:BXPzĨm lEaݬCЏE@ȒnJvRKd\wKͻVj=EW:W#EaO|>PmHt=r\?s\Kgv uou _R!bJu-DqhCGn; 0-s%tF;%Iey4^I(\}h|"o,{<ڲٚw5k- J<;_($3<ڝXD.5>{~.}c.' 㠐N$oyPx;WN'_g[,)4\ua6Q?lN`7M'A0hf,P!ՈѪ?ևS 0z(M<IC_Kg3囹t%sq xy^Rs=P~ (ݻ˯ ˻!zS-FO <3=BL,ƃ.5fM50L0M Lbњ j̬i6y6!8K bHt#W-N|S/=z~"ջ4)ի}vyYxU_Ssl Ӆ";qVuśYP9xQ.){ι,A4xC܋73)i~s9W &p[LoTiZ/IKK˘)NKJP\fz;Oײܽ-p]dx4qBg2\p%w ?> q#ٺp"p$t=^ٯNVKM'itͧRtID b*' k=:k{  ᣆ,_ϒlf6d[)үZ>(.""8[ow=ލPX߽ p'~Ar'2Ft c~s:BNrPe g;4~τdm w; ;̗ԹIɛGeoWZe$Ԕ&-'D}NZ)Zohz޴gwӯ'^lUgMEr8;;aC`e'`xkJ&3' b ͆/˳J6۪6;j=~競?lbUtLnGyq*-s҃lbقgOG^BX?#NW10f78ލԯ>aG4SafبkIDf:Q=N2$맓MhS8vܠiE7 S p@4гO*ƏTzl#W#V3B^G510? ΍H? 0m?{y  S6и$[w@Xvv4֝x8v U=T›s5AC&"٣jjqReba^d./mۣuSiI: CE}JZ-hl{vEv}P?Z=xny7/KJV]EZ@vg9_0SeOՍ'iG#1!nآ3{tV٫cݸY=bV@eSZyoܯzCW: P3dG9Gr=G'*o?k9#\d;t9hNG@ `~0(L?mwkFZ4JdjIX'zI"igP.$=-h#j07a?R =ՠ>6ü_NXjZdUeNMFǸo߲ K6ʬRQUgۿ;|]_<ɿl[,.GҏX's1H!֕p z"ڹ4 -S t P#c1^VcTh5/>l@6ƢF^fp(ĨG JG$`gU-[r-K'Woe?{P.@Covmx!zP~~#@(E}>2.Yۍ#$_3.Lt.`y2HqDng@vw*z 䗸.M^HM_jyP=]U6]>&htcc>&$|MI#/G~zafUfÍ֊5;itFe O{Mez9W9g=I6P10+oWt$3It$tv&4=v$Vʬ~eTukTUnRBV(Q:}nUㄬq ~KGWld?kK]7cBX@Dap#V5kfHN9wȃLjCGA!i`K#֍vN9|:G9ߤrx} y)2Ms 3)o=kOP?`v_8>:G^zqZnzvFIc=ܨ+lygW?{c Yp%cs/Xg=spA@GP3G,` u$Lz*A=HPM&&^H׎FG4Ѻ(Khxw*ϔgr3K$O,zO]邪v'|Ps6BVH[Ȕ*X3<|{I)E8)]ZB=[~ $7Q ˞|Əq%uG:=ݥKs؃Hg^ү>[n)7+734RVg*\c./C:>%ZgK]Mܬl,ݨ.햢톜$U;>ٿ'2.`+gHJqɿ&oP0 $<J;™XBj6N="b"Z=M0L$4#њhpf ƁK\R;'"e _Z`ħptBN?(ד[9=;xI4?=GFJޕ-?L]z4W:]Fōc$cTAwydcQ\U[Y[5+@{=^UtYD+8: >r=n vF_Ds x\r&F=QOF'q*#&bec1(_8py0gjmXW>Ի-WE?{ٻWw #|TJ $F싁; v^xǣ]>0fu"]Mȶ@+qA}̜Y>s \~#U$1np*~.9P|Ǟ|)w;]dpZ]WBEr[I+:8"Hf :l=@`skn!i,qGZ>k?,꼝֊a&3:n{?鴫K.2[a4c< ?!rvE}#u#k<3Ѳ(OG+-hDr2N1L9 EcfCNӭ<5M UBW@=G +yBLW }* s|RpDW3 肨w|Ysߣ#CUFkOy'㾊/{#Yeݠ[ta 3wyvGr M I sǙIO^Үn^iYyRcn<>|C~G^'t < }i6'-DfVm?_4.@? w7%:b@#}v=^ތ>]* L9 IrKf4J IMSfY@ &@#(',I+qfՀI=`6=Z 0*42UT*R+A>Ur'T̛`{%}=CU,Pl)AIÜ rϺ /QB7X_5B=UܚQ I aGpCq:g"RhiB<&@ n}!6Sބz:]ERC(P~{~{h A O/^7'^`|oɬUYMu%l0{Aj"1WD=>DH8*Ns Z [3n֣ <'OEр\b.Z1()S&P|ܬ7KG-aNoT?껔Yh|EԷS ~.tʸ͸ dPY.nʿhY!E=+SW+ p퀉E^tfvnh'2OJW,|Y7!'"~>v˹B8bɾ{\CCl{!:0;(hCa?vU g,T|z!vzyڷw1>a߇7{:&ϰO\egyßAW|=665sϽ=vA8Jo'BiF yJM-a~3=MPT3GrwLkQ7MC\QA}8F<ruH(N+P4gVN,\/7'&I1(Q>nZyZ֭?*:e/aVOeޖY>5ջֹ;zȼKZ.Wo=,R|H؇v v7.T d+6vQ]~!)x{e@,hc]:z(zL*d$snk[Re`)0?uproW]s.rZlP]YnUn\`܄:!^^>/g~^#|Cc/3`B>d뭍G>ՖM[Fis(6 =J? sk2NN#!B»^dhոU|ccՈhŐA>i G& ۄ6|=f;vYZ`"yv\'iw,+%;jԠ{@xh"U\͓ȔNL#D$S2" Dl='LQGƓw.ԑȠC`a0 ׭j#OV~%Kki RŘ%M=?[~ԯL2;t_"RwlZCͯ 1 OD&&NOi/u('b,Ql,Z$CHN;?#Gl!CР0N=. K7 <Sw}Yĵ\0SP[2'PY!j֭%EMYO==KV./–oFwԿK42՛pB{2(88y,9 /̌Qt]9ha2~1_!ύlDr,J5fA= 8*@vz5%T۔uJmB fiøD axޛ__W3W /UOE K]q%s?lw]"W|#{#YSe/)P*;^ux1v ,Pt̋zևr% $X}]x "?zנCŁa쀊Ⲟy_Wj|w8 ɻv/ޒYO"g^#F#3Gj쏴)_c4U4H1e2sRƯލwwz݊@9ƚ I= cqdS`!{iAaALF;j%gS1h@l_i}*YFB&y.uH-ɏvvn] ѡxٗ5R9\ћUa-ϨhU g;wY$_Re)6+Mm!wТqbs\bEx&9U´*Tt ,-<vA:}:_<ۓ7e2̧D18j{i\LVַ{޿;.3/^&C^ÖB<Jդ`hk /iCiC(3Y ~1ѷ[rY(Yb_2}5CPQ겻"CtonΒs}~w&V5 NQQ36iPtI]2i _R*\ȯ7M FJ7K6JRnzZ{nxO99{0$ \E#޺qn؀?cv;;wQB^9+#=>0;^W`1?kBP !< A2gFŬfV` V6t: h1Igjoke|٬[V(%J9 _Kθ烺9u>8"E&bQqx$E3ـFң;%6`>S ڝNVqy`hP`PÍ^ɷn".'#سw{Dߓ9\VW-yݿdh`7zRs7,#T>`SNc8 ,.ehy_!+J=d+t(.'x̑%F;($/ Y"R8\'c2g^ըbԽWH#H +vɤ.,#a)wL)WG+ǣ jn_xϠK_i/ur >Hşk?v; [O-}iCCYCGֆ*R n^NH:;u/ekʵlvW{oR#B:@-Hj VFT>H 6ZL $EGab(}ᡶHy87{;1Œ̥yuEЀ ^>G0|k0 8>"J?eW+߫<ބo ) Uc.i9O*e̳$fO >l+f?$H} *B˯{E^!v;c3̢6`0n?E ^ʍX٤ǝٓ;l!e(b]hהOD Q3yB'TIU~+?蔫4EE<{?&%}O^֩oy: Tqpbv`S;%JqXmԄ2bBΞRM)G-R Y=+O#z)?9Kӡy4|s0g `PuUmVnHPy>+XeP57iטB;*_ːoDE.2CiW%:O?NTڱE0{ xOhyE -28A9?cNzkCG:Xk''[z>{ P,6dg_ ]$L~EXIV~ѫ>TUwb2gM^a䷌7lهG>-TB ;FC1n ga\2rUtnZ`&^9-Rce|p>[!~"wx*?vG9\=X9T5\=pcbc Ax]H 3Ϻ>a'#%&Rl~bKlb2G#)>.IpWq)C1><L5G敤1R'7k'٪r{ࣞa'<Sn`dePx+p?A!oD*!y!(~V(?@"|PW2@-՗|xRcr[j!R ? EQ[Y)eRNOXgPpjfy/Pk U {dgb~S8w.Aݦ2PŸy?GwFKػ5pG\%\'] @N1ylY=M,mkk%:2Apkm^2@L<\#P.qn'Y79)_&_},ZhF*<{Ծ6!Sy) a qu1IͲ!O x~K{WjKCobI|b`cE5o)dTPɆ`㮚3 PQI=C,Pjw4c"hjkʾw#EDg_@Zv/:{E-)*Wt_&pDBrPȏgs%`f<>ZBup ?̴ub8N'KpnGT~A X,ޑT{!=L̢طe,}~2~Ve~_Y7q@)0=ϸ;`]$a2z`qT -2p>|آ6)LWzT/=|_/6%<|5O狸? NmnOTlMVm3U5!ғ`eppxA-E(l _ìċ^=K'=ŅqoQTz!H.GLEjP 0 c#P'^@8,: V_v#s\%8c/AÞ~:(O|'{B]->| [c7,I۱IY+kHX  <ǁv؁}Yt|Str3lXb⌒c8Pj"Ȇ,^ ytW'>SH"#[X%ʿ3*9DDdDTTP<+Qrؓ" !:kU/,[+lkKU[%/[x5:)Yٌfa ` ^ T*$e_$QsR iOU1>{]47g1w)w)7Qǡ᧡kC`Bs\i= ͇esecҖI |P2KB}g( W#_K2 δl`A l :} Ŀh^BxUt+] q?ZeDfM,5]3hgtHp@@V&i99dϷuuE8x o/ u"NzX5V-a8G?t )B1BmpZD7T,8)d!g%sH'y.7ؔ௯& HLyi;QfWq17) 'ags-Hzid^4z< ^"G|gp,HberV8LD {6Bp!Jl^,H>rDpϻюq6򌿉GςxppϢS5Y-o$Z??Z= Dhr0FҢyiR]YJ! qp4HC.ox@QyL',DKƕX(0|}QXPjȢR5=FsS|JDլ R_sU-T9`tdh 0~Cag %F:8Sl +Gud5^Zl* tcoXUg =ޑ[D3CL#uP{o}޳g2 ,!݃/wwwww%B"3Z3sͮ x X/p?D k45~by_#k) k7FDyn9VɍEpA"R11 $% el-bI %>}=h&x"<ʟ)/TF˸:Os^侭-__(R\8ypRօ@Ca$>o\RDgU7a2ɹˠ՛v>ASݳ VVfyε+k9W˃ 狂s>QsPk)O <7d׏G}ow~wrp\mFgIXZA+5Js d)mEitdj!!L&R143 _,T[3-EV]P3g.ϔ%ya--D!HGg1`MH0/Sm\2gi`2uȷ([떊]@{ cLBcƜ975o*JU)/}Pd`a^ $Yhy\KbAU z6R5RY ){ άKUe77 cdшߚ/sW = s/^,οPX<_?{x\}VGRm~cŁG}A}j+-|}+a8sAP,Vl%4b50}y_n]_,J 06aMYΐ."cQbMKg=ݬ[-EU%;obQ$/ KDy!s֠sm+`gh0?[ LdK Դa_%A. $AW ۶!#d5w#*7yK 0ca|7.& `M+D$[k3lj|]:x ʘ{RD>$6jmP00R<_w&/L^dw=t1Z{$[A@?윹n珻]v߮4}*Vp}˲?~b<ž͘!Ψm܌掹tmmV6bo/`OG`-Wj'Ǣ4+5l2n9]HBJ~eRK)(wkZ{U]]6\--ECt, QƂ$ѳ/T'b^VgdTnq.e-:]wuna0+,ՔZ#jo8EX" I ٛ!Z*݌O#BxVQ9rxh}laRs@;7?yN}Vۀ%Ԅ<1}V-owfKo<(o2dQfH3K҂떠6FEsrWrfr>y VmYS%:(!Q)R2&g> u{n[-m*?drE-RDZUrׇ׷r;3Z! HI<PI,XW$BƅPehی^c xbRHkxj:=gS1Z7YP燡#o/_ڠɒ0P(~/A5`NYWN*Hk,h2O(Txl^hK)*v {AuždX{fvq~Z폛oqǪF[s;Tl޼l+7b7a,{9B6&Yָ o*2&dCgmgxv-:w. OA)B$%\~%jү`2=DO-ƋVI{n/"VY*y^.? Zs-ER`B1ٚF.5-,݀=\a oswy!'R?ꞨϵfSb~+s^vW9n]/욾zT]rK* ×QA_݆ D^F3V9QsJ>"Uev;., ڨN+kK(Jfn7qoFPͳzGfpn6.ӹZո۔A,4[Iׂ,utF&c)uC7-Pc]+nF?(H _!y `~<A,IX)Vs?+Ev?_glRӖ*qslL K)d9NWfF,̇pAȓ8^sB[aX|r̼ wEJ NLo|b0?5m9p]᫁7xcjxǑFvwZc E8=_r/!R>Sk_̣3JbuCHS5o4=XcSg0{x[/LBRp g2}0];8/x/\ak:mј(x,iHɣ3[置?n}B\I؂ތ܀n"(M>KºM]VdnF:}M{}vTc]iSXv.A|f[ڊ fa^eWp(s0g9ss^kS'XeVlƵHi4 䬖,R,th>Pz(SEW=K^;;Svt]9w].k>e!F"B4i]/VQQMbbZؠ]FocxtpY+IBr0E*8" 0E}vyN]ǬFn}Pa8*]5 (t?׽οw}P5ڠڄ-GB)Yl,(h #*.?;\86c*VC)o+\@ N?u9 lz lNbXQjjj,"KXIy[ ^Ңmp !կ!7ʫ6k+l9yNX(hq";7ӵZsɮWł#X{BSDB~ӼjF5Qql 9au) y^Mջ5NhtW|ys3GyF4GR1$9q͢t\ε_ʵ_8.]s>Y0cv!}q@g:oݵ1(iwgl~̽;mSG$@;)P}߃c@}PFG95)ؕ_\G^_ .|z~ʇ{'I mL:oV]\͵_8.-sc>tr8ZjODṭ3wlx9`oKE7mue;]Q*{?ޖAQ`߷qʳ};/t/eEN@ړ;Uc*F65N5K MBx# XHV0t¿ҙ@R,G1QdͰP]w zZf =9߷MF(((nY:ki̒: _a{L3 B!!z͘^3Wv[A{) Lj+}Sw{?zכǿE\_҄?m3yU{~=v5vtq٬c6!mZT*ֽ}:ẓ?vyۥ;.Nk*nܝEއB:eQ8`/ cUwOI|zSuְYz֞ošA<9KD1bn{sG PQV]!0T`M{9zܽ¯Yt.RIsEx0&Vb9sˡ!,( G09OgBѨZ>ic V> & hK$L{'j & _vT}͡S=__n~n ި=-0^دد:-Wsֳ',S6aJ޼#53#Umq_U~= = I=Lb 1ٻ,v8m7مuєm`ٮ9նr߁ȏ;_ըG͕\|ǥ\ŠJ~er[Yt}Ai=蛹Z?a珋Or;LLaywe`q6lw˧UyY0o9(gX+V۷Is8m=;Dg$BjDKEN{S2utZwgQd6 bIP<&[_&pwٜ8G bx.PJ W0nԅ,1%6GrBo,8QUw7ߞ:ӥC|߿0b&pϮ^_oz1`?q؆cV1e޸_<&< ? =+a$~'3wO=`AѺI}HN/lA 6Z-tl鹸Pis=T6xx~U~2Ȓ84#Ž`DutRF,62iQpY )8qXQ LXU vO]K5a[Geu8u L{n-rǻmC`hO2 t\ ٸJ<*e:ŘA1f1;!#\ '*s& ' {}]S~~ o-0}0Z %q(9//ֳ^rc;a՚a?ܨ^=jx"qCF)hpJW6qObx`VI*_ (&jں.rlXl:ݾyjMNiEpf4;ƎAy pv<\ӭa:edn2p!hR Z*|mڏ;lֽ:aZd9`83Wg~&mO$XsA_AHvJΌAєIE ЊedlB#X ^ߏpj*e쪁h>ܔ*CLKE0U"8Y}~~pù/ )n\"x8Z5UʰQB2SX'fsYCPw<7R7є,}''ϳ-p<nNi7 @;FCqe?l67Ot4w}Ι3^?qu::B `>e 3 m@Kȿn9Xx~G߉"$ۖa-1Nu㟬5-7AR2_APR?C(Ri ,l<0 sr"ھBUi2mun^N\G_!yٝ[l=2iNPtqjܠ k!t\5;_?qdܠ]ְu}܉֢;_h~s|{?? ډ/SsF>t\vz.8=g3>1vj:gݲ/UvY) /)C8A8/BWr-jىeu"Y`z׈TyP$.>X[ː9d_cޔ==^@ufm_0gFTHexf<9f9C,J!jQ)Db?I"Z)QhҪ]+g-7*-5|JIpR&̘eHb31 5 _pVY%b si5!&bTGLЬ KSbL#3Ƭ0*p•9‰}wzs>]>З[g9/j'T^oPzP9e1Fr\gC9 v#`޵?ھ~71ΑGľ N/_`."ũ1&ی%4 `^޾ӭM5 o1*0Lu0Uk f4M & f,<0y0Ü-@Q@kټX/O)(ɗHpz5KgJ#b/lNTl~(*4"HFY:~'ey!j7c /mjT:UĨ "bP1Q-zܢw[nC8h:eH/T0VjzgO#ϳzgK<芭TX3)ꎘLǜP}=`~Xj22Zy _=9#E:;p5HIw#V]6 nDr@Lk -l!v\qKm$d^"'r [\n^F+8G'3*M3 @/%q1tz"N^JBi@x;.(զB4k 3%%D68*6I<ɝy6>|^7TM}/BӞEr|uĬ ""tR0DZYq45TT"@>h3'/xˬ<ty L(${ܭ<گMK 8(;O@pDjE׭di1yq )0Dh jɁ{yLttmSsR WAڶ .Ih[Zc8O|ǔ1=VzֈU0,*@  q&k;&Z ^wW؎wޏrr盳#s99 `ʬS9ID.J-C@%Ӿ:};s-8^-<ʦR!,O2| `z+$ RI%[IvmAE*jw]yU"1c|O z,Cٽ͉b(?;:8q.%J%IV X&b,'_ЬjVp ̼a2\ fD1 VTTAT}Af:!(:~FOI}+X}*PIBZUߢa2jdz dvS35P7\ ({9P@כ|r9핛8 Oewbh(Fu&9o#ʾM@lXu8]zg寄-Tnuc]8ay:5x364P)n[owb._ŁWw8XUa Ƃw^?}ls s{Dv8;%JDdJg?Уa܅8wJf$oP!X?D-YD1n3[)X&Ge3QY_R)?mŤWG`!mA9[ Yd}. cɸVf×~#&PA AϘ^V01vVW;Q;Q_8Urw;0rlʩO7}}ݑoO5dZP"s;Cdb(Vy$TA":\#/# J[9kyˡkHq0fp.2Pmg걒r(ӹ\6/GA5Qޮ uw_߷dSM}Hi޶nA |n_U+J4P$0 %]׮c#$NJB1nP2# qRmӭV3HJΟř&͚[Icf[S`!v~e? _(o,|\ʮ [a>b׆Lj cV՘[;3rDe◝/w4:Į>ݺ΅NUkpډV"nzpPќ{a6\f\pd=d=dV[euVgdj"&i³OkPA~ʮ:VoL||y5VQQz!Kɒxa<ڴMƎEɎl 'cڠVFR,։Vr8qP{$>p~s*De@(^R_2CUȤ3*I2JGi<.E*ݕ/^xuОM_9G?{p+Am3{La;ENreYCd0}Zk&WZұdvQe(vg9̱ь25;v!tAC)Pi3X]Nj MM(ZLfvj@l)-Db~!D%'%2l.Tvcĕ 2Ňo\#I(qhE AYE,&Ȗ1*A =^Bݵj{H(E 8l)J ڷ %tʜ ּ,YL=fs# yFI%=0XlB?nS=ڰʷK5Hw@}Gߞ9~(0&oSٌlBJv2"꤀?b 1Y'#XAP/.2os݊}(%<pIà>`SX& 3gyQ@q a`#X#v¦XTft:6Na.dW{ S$h :'ʼ`&osRGB pHYs  tIME  R IDATx-ou|w%)"%˒,mmM@ڴ耶( hq RUq+5ZDQ.yy/ywNg{^}pzyFى=*arR% DRa'ҠB\ܙ܅̪\nYn0R%;)q,4dг3#W0c%q#`JP2q DsrTl``u5 02x 0s+ r6P%d|9`3C'!cNws+ܜ7Gvr3o79 DD?`w ܈) N0b"L, faՕ(TL|_0Jqgx']ds0!/DnP#e 0E\\1,;˪XAHdn~1?jW#1Sz{`"3+dlYT\M C@^݌n;3 &J#r9{. /!oE60bt.fab.092h.Y(i 29Œ]T8dh3ټ"B፛m׃9I lf LDfd '#"ԝ fLDs(gI`">sPx%03 a+) Sqewz!-VhdrZ@.4Z"ݷ0djE\0N(pWBz#b+DЬfl09{ŮiQ2uw#Fbb7+sUo% ef砹 :[0&/. %9ɭ89Qxۻb/&%=#/pdՋ}\)ٹfe+1$FȵJQTѨ3Xh F p(^@lmZ7;o@R`s! ܂b%ZC|ѡT`p +!8+w߽鹷W7^'ބ/rf9"GGDQL0݅NN5.ՋGb0v( )(˰rR*jE8vp{ a I}3[  @w5\ FuѲYգbkeZjX!Vr&ي•Ȋzqpϔ-g1sjo ln/W3om>Gb߸XfU9f3^\euBV TŹ:t#1Ԭ ebo?\d$+mi:$ rw#׃</p^rW֛_I<bp17'//?E[ fT%ÉouaQ4.y D0vW D\T]T¢˂*TJkO, mz0;\ٛyk rwաWk[hJpDW;q" ̉rEf9Zc#/t~xU d,zv7BPhCkCSqu*rI c+i4$q[W.&oq[ YP"Cր>~+QsUB`(J4 *,H 'm[UU&S[Uq- ]vSI2wͮ{%Zk8t+Jܓ׾U"A"~yFد}ʜS_],hl`yOq*B -^Ե{*-p6Y~-*\|:r.ߧOUduD1}T``%D3dRPP2>?F~v帧W/Ih -vU{ͪ}ߞ1֖Kn!ZR2fRq,xĹrgúmkۧ!êOnU֤,UI,-S'b/|ܑ߬ڋU&-n ̵N(p"'"a*"a 4`x8z qCӦ~F}Մj{}g֛nk# *Z4/nwa GDn$0&bB̥B' .)Jh\nǵ#P2hg_ƋDۈ"gMnlΈ0XV{֘zC\ԥ"4Qy5]hHuJ&\.%JQs*W붎 (Pe'p(²p7ŕzv\[j4s׍ Gnb6O ׮ |W,A`_>QeDApb30sS13"jN `J=ZsDh0q5֗%^˳j,?(W[ϋ B 7K;9i4Z,C^M7ю4_ SZF U>c.9q5y yL\)e&ld NJp) 2ÃJՑVru{+׆]m\W =^<[~?T0+1B$"Njlp&q>! {&cY<5{}6|~=8#Y?2.ᇇ/!VHo>.Hc)=W>} DNz2+0ay+R[.=4 OMԄL3X{ns[f'=ͣoj;EQCp0'MPk;}$w< *{0&@$p"٘QK4y4r:<-Y|py͗~?/YVrh$#nkg=T-2kFbp*PYw.r[Iכgcd9Zsu{1H"W#p̳Qř"K$fp l%8@wpk}T[uP -ק.mN`%8 0LA#d^׎7O`GujۭjǮ/6?Hه/~b\z^x\ggûՠX*>;r ɌdpNqh~|<-&rj{_{/r̅&pX~aovUM{"FGUv dNNyVb\A6ޖezx6p~u||ÖZVgFKLw($VkIJ b"2H & 3værMd>6n}ѓDR*x+g~8&^:GSs\^S^VG5Yw=|ˠmޝb;2yPmܡUdxu%̓{sbΣ L1XAПFfw82ALRM[UQ=ŽSVXY?haB$ 6vщm0 fN;;yM|E[~z=8seտR~qhRuiC#иƒ@bEkjnvAYwg6qDqX(eKwr>Hrqmc'gdxTItk`{׫BcLuf; ;&`wbrR>>FKn5J:H=LN A|xe@"తgG;l,\ɉj(;\$rM?ؒf8)k#]}3wOW+QqbŭQGh`t0}^ͻ0\'L‰OHM efEI߼Laʨۃ;o'^-}0GoiXj6FUCѭ'yT?*&ySr1،491\-m,}OFVkK]_7~e6?ϒFM(LRXb ($hhn%`g !x:\zϫ#}Hv}OyBV7-1kZ2l0DK伱K0vR IRoO B0?k_GW?ڂ{J+4?ݩ+:\c)R=.|t@V}nNnpO*J6q'`L9FhU|a7_ԾĻjo{y6?z[rZih*}wm!e$gCV#(39$8{LAhucƮ䰵]ңc}t<\>M~*m<|푯޾Mu:>7xn-zlwADDQՂ{6xf'qDSV%A||wcg@;}]ԓ;otyJ׍P7oݹ.x[c_,F?s 2"-NA2Z1Hɔ: t_Y}P-_Q}řXoSzl}0#/&oI>VlZeh9 `ul,0* fy+|_~8;Wwiˋqt𳿺ئA]B3d JR1Y\JߵTs=Ϥo}u}>|*݋[ipI^8[[UgN矘>?[ƵFK>3v}1ef9Y.0*2l;ig}<IL 8oo}돚O>u?zq֍.^~GG?Lofᳺpz%||mMQESrfdFFk;ӊ(N`:w9. {TboLg,vquە2H΅fѾh1Y_Z''ȴ|;|n͍Λ .A_y';_bp Ccŀn2Yw{HOeIL2AP)q[RNJzݭv7׮3o\y}@_?}u07Aq<3Re@#@H7ī*v)90/ݳ}b~HɁϾ4~Wnn)U $䂸JlS]~ng'Ac ܔsuf{J盃n!%=x\9FG*t;dVr_{1#!b! ;2H9[>}*HZEKVs*^9Uҧn.&"=sw~2Gt~jqͥoK:@KiO|:9j'Bh.T2+`)y1k4ë~7~6tð|띭 ?z37"ں]AJedc_AY6Lp̸۹)*_mE-E.+lr#"kghأY!yΞAمN%]'wn_t>/_Fġd%mnĎ66 ~;^"f&ٹ18jd<^ǣ#:'^V{[oF e7bG1ll^@y` MIE(I"\han!ܿޠG?_ޭ~G"K^Uw %j*6l.FV"DΥZ΀3-|$ͬ?x+(.w9ՔƕAԜ ,3jG/ Ur4bd&Qت)c&:޲;lnⅯ\]d` U3ιgrSh DX]&Jd0&x#cRQdSwҭF  wҋ;}Zk(Iby~,v:ʱT;̈#{m彁0._pwl{CmJXiRނicRrȈ8W~nS5`<ؼ}3L~o3$O(ALBEv< `;BB. Tą.<(M>0^zӿ[+}񿖋oCB[_ Y lDGMH\oDL1K&3"I򤉙 n T$G΋^N?cO>9=!v32rSt11]1D W=z6moknݽqzsЭj\3=v`3ōWrL=r<&*Dԙ)U$h3$ v5%":zPuX鵟5Jzec̻ѠD[xi<:xfc)H8Y"`NzD 2lPugr~t M'Կ)SbQ 9}^%ĊN`Uue=<~3BF&`kP@ K,. w勷ցn޽ЏvG/lʫӱ:4Vͪe7p1=*VlL\rF!H'YQZZFF+ޟܬ7MWVT1f[ZdϳIT2B!bR%*2q=ȝ p`j쀙2ĶZ wF[4`s6:{qUaFH=?00r  w%~Bu N`9x 'wb๐ [^IbJI'.QomTzo΋Sp48v0,33j%Z} fdD BwkL[{<Onn/ BOl.*v6uǖcS*.ll7 8IDATny( ڔU0bҾ_p3lhFՕV9ס{9/'v4$,u>G,Rꇜq!&NZ))F;ȹFBnu*D\}_X;t Ճq{QpgOM+pr=X?H}?4?y!1.iLILδ@.B)iTTW~PM9HG{(9j>Sҽ.eeԉ9Z;:*Ok17<;Y*_R1R(6)$Vc@^]߻gӺLT1=pЛi!wrS&]2bVla$XUZi-9q9Ιpӻ46/qhmizK/~8YۈA{gZhNl= H%uH,-dPa {R9LqrWo_l6{Y#\2=[rL.n %3\yB^RM ԗaǷ+@ %P4zI!K?)rG7/4eR !JNZr1;|+21S j [* 6m4cA\(Hݯ5}5~|PÛxC ; B;FEE/V9Ș^]%-#[$@yYes> KϯvR1?xC6LKa'Ewͭ|"JT'fT"F +>,SlUS)'K+&W 94 U72J+7̇v_uC$ -P ,2H <79.BfEy*38!-c )UmYڏQz 5qC?EӉ>a3>?W B5esŔ%FǢ Rrvչh燷Z1ƭxP ` I`*x<$>nJ>ڣ`qścBHuUyxvLLr^zٙW¸1y?0gd,&?H€+Ȋ݊qV=V\d ѻ?zt5^6!8?{sIvBm0(~iAi>|Oϖs)N ǒ~<{zܘ]Ytnjp6I^jCZ>JERV?)[QY{] 2Z >/^2ᒦqw?zٍaf\ObY>;YFk}}oڠl㶠 xg-IV{kr'nog於w} fvvb'. JР:)L8_cZ0,?8z#͗\[UUpyx13Oe niõ񬹒}P׋^a&EHՊpc==/PY[$2wxbxxԽx/ W.%!0)q) i1tW͞]aDZc@qsigBKY{ν͇o5Ttjk#F?I\3BL VȲƦiH`$GMY׻:\LjzUw7N\ =6-1{i\OU".L ! dg{wͮ@íY qkZ.gLN~٘ wH 6؋AZ}bԁ%0JNamd9 -O,=Wv:'tG:aO.Ϻ4Ov2YIENDB`scikit-image-0.9.3/skimage/data/moon.png000066400000000000000000001420011223313777300201060ustar00rootroot00000000000000PNG  IHDR& pHYsHHFk> vpAgxNIDATxeu-llkIEMO\]5U]]U=VSUWw( KHF#ccBL0!%_B!p o}kpΆ:>{:5=Y:uSO=;?f8r8qɓNSx9Μ9yrnԩ'css~l8q=9Μ9u'O'N8rdaΣG|unWp^|tw8g|\/:{+乣G>r;rWq^ٳ\߅ gΜ>}guNzΟ;{CnܸtI;N䕜ԩY~%wp g\Ν?}y̅ \Wx~ӬCVx~~yw

    }==####ccmh+@[ZX;}z~ɣG]:fԩGѣ,|D, g`]2P N:wĉcǸ>9~Oy9{rdlln: +6~sk&M_S.\@̪!y*p曃34?3ƈgΜ?"?*qƕ+QRd4332299::8ߏj+@[X{X[QhnÇٚD X2 E.wnB"rs^u _8?k:Tӧϟwj 'N>|(J5s &Wܾ}7n\ȝ|A1##ccmhup-͐𻛦\\Zppcټ$K@*x`S4A 4|c) :c\dM8!)fݳg݀ } źxs FP܅zrlss1?_9M_ ':қo޺u钁)W MO3221VpS8:Es#=džI9rbs iZɣG}MWW\2!?8* YH{`D!]\&]"9À0f к|^bDuyBy5+k㚠|DtPYQhz:IC+KTK._^^6g=:0;:ѱq+N`[Z\`BATw) "~p`۶DLbXΔ&"ckR$yKt"((% *qR # ? %-Gމ{5.us^/fj@O%GqKcR&Dp7 Mq:_\ɵ81\׀4Uy{zzzz{WL@[Z\ 8oԄx.z–j-ᘢq$otsVF!V4WV.&@3gz^!qby\"C=}z1'%cCN 2J묁H]1n|QP$kך_gf qf-Wdyٳׯc~NVK#0??5=SSW`i+@+΂Εo1if5[O J'.-ߢnBRx<:.[\JAy}TEs:q 1EqbhT+O,.W^S8ի.N7gV!(njf/r]XNZJexU2g/:ӧ/_>xG|go:y|[ iIQqQ2DQL%8e&f Iblsx޸nx9K`3Y \s}qWȔr^(7$q }T@,_RcǮ\,84F2_:k,:ʬ\Dڲ>p{<8x]D&''\7 `J#&ݚ(\L7\>(_WySUX)pxAE l ]|BjHJ.(U.7]$?%E5,&H%I05;AuA\4Lj2_:?%qU2u!{ffS*J͍Ycǎ=V0)`#i3,'}),M׉E \;*g6Jŀe<\(!Vٴ9Z¶"ʒBpT"jfK9崪ڨ.,-J9die`R^QA̙.%|F$4&w 8qbb4vVk=|xll``b…>j+@[h+ )aLo?bR]킕c&` P fȒO K$\W P eUԥo+#KK ״3n_  Fg!gYSJi+Ndy]+4J%7+2=;K{!JVVW@PScر繹뻺q_xMFZͤlqV7k lT䋁-$Ek:)PlqP2ܹ[6)6:/Aj8hSɚπSNKCkY]#:>Wn_G|ΉJ a|m#,*y#GXPrBMҾTss;v<$ml#e0RЊlhM3uQ bu)əjxÇI**"[+:sBNL (jZj6JSxI?NPc8n v&B+W\-19}N ;l^ pGN=x!O"x~I_M Gl[4;W4q'-"[vBXиt)U" M jHT I#bKǍWZ\|d)` X7ѦRj$&>PUP UyMT樝A{b^l88R#`Ԇ5kxcp2Oav)IQVaX-iGAjF2I0S?TMQYDUؖK@l_^Tֈ+<{̀R &rdppznZ.%[چz [BjIYA+t@6_cqs^ .k$1H +Ln:!iLT%h~,,-Iej%Hq];#WRU*0js}6AzJ^&q7MZϸVc%Ky>0ѣЬUyUR=\ fᷠ&HP'ٴ%h@RW J51/G\,EZ a\x',Q$c&L:YrL ȸ3i&t6RÒI eh+@[,J' ^PlDiR6f|e XrNwp\/E) a,u< :"'xZu4i'9C?@om8_&\[&et*_j>%)/Tu1IqU'OpVVWi ƖBͱp3 !MxIXFt bm>)\ Szs+S+L~ƤI״ATAꈍ؀MUCQL!RȂcID#INq$=R5+XgM%HU`c5Ji|I2׬cǠP!.R8P75L{' ]j^' T)_IsƸq7vVy!X̕"=HBsjk-^K(k!GkM'tCHTt/ %ĸIs -*NMA~2-"d7;dFAo >)+$CsiE !y +W>P4 AR*_S`&@M̀UCAk˷jp! 4IB, lu6S% ܬtt! aR:+cxƟ$|SAb*V 6:(7Ke UlBLbL I^zh+i;%9@ C`ۨR4;$ MA LN`{u-,ĩMoVVW3/6Jd$ DUTrf)a:43cF15"d63(~TծZ*S2|v5HR$ֵ'Ԟ>}M 'N\K@VImY=Iٸx&KQZE4#ijUK[I[[Z] 5t9Lؑm-TJRj܄N:(x"g5 %xĩ* `) YT:C  V 0 D6h7pihml)*e?jPmst1S*&,l^MASɵ*8l%6/ qrV'$/պ[2TE/2gӀns `g "]|p6onψ<)ؖl) @26q͝=p ÇiXB xJ}R(YC e5ş,4&M'8cd*]q #4RkH7*1\qͪ.¦nOXݼӑsR1'#&9sMݗ.oIK@%o&;Hq"EEʤx\ n㯿rXXPԄb4b9: $ܾ ^o)AW9˻JBR_U:[2 DVJ7%Nr%#9 CZ|| wKNx'HA,Gmhu@I\hr R ٺBCc&17I]6Z!?d[^~o?$ 1 5INi#ҖaqQ9.@f*.n^@i.[`#0,AXϒn/>݇։%Iw|1TCIٳg/_v˿p1Vj$ϝc|[Z]JzE`X@! S BKM(| $p~7ӿG'~kҲ1I@: 488νILŕN9Sm,) jOS)@h] 4`>PIZQqt5qBP8ޙ$\Q ZXx+ХGmu|[Z]YlMEݐ P# Hu 0T;EIK)L ccS+47n?_?Wu)5NaElԩ7V%҄mm0].U5e@?M! "8bkۖ_GRq 1\:+3 *ڜ.LxKP:  g&Pl-)Μo.^$գ1>@P85%m|~?ǿ0@t3 QtjZ@ :I])pYJn'1m*U|idMeuIsxd:nEb|T%Տ-=Ŧ[5 `0<mQʜ!; APS?ܲec2D]W&`롡 h_Lޞ>_?ۿ˿nZ"QT%$/MPVv)T2%DkBTɥR!婘O]`W4q&5t<zG8yޒFU21A&!Pp5~t:x#!=3C{²pj2R`2u 9ztrcpccӘǞ^G_/+_u+[ SJTGt.dYr1iOAVfQĸ_@̹64U36EkGW;jV.]r'[X{IsZXh+@+@R$2?~r59 ja& bs@صk˖;m۽{ppl,;|?3­fX !v <ϧO8Hd]W98#XjRhDmXK(gk)ZY{J^V Clg,/$)U3ERGU::+ó.p"~睶YV-_XN IZ܎RG&:Ν#zuy…cz{׭{Mvسgppxɐ5_뿒/-fkޱP-Ve jӿ|}zNDz\d@_2  j2湷Wr+f$|IM\r>1TF`8?tܹ>xᩩ' #@)!vy--,^ZX&䮭$|TB.NA3e& g˗otȎ?3ϼ `o,_?M$UFL h/edi08WǏ:IJ1RסC0and$1jM/&pE L%x< 0ȑ _gdjTe+fajQ $G"%Qׯ:VVWx( VPҨ(\)B!004qq mokWGGo0 ?N:;o !'=5B`mI UbWfg-n'L@uʍw֍WU]> ̅q,x\U4tr1`tmj:|8F"m:Ę#L^7&-ˤz\ˈ _}`"ۻ!mhqH2}s؝脊b0('5ݰ|ٳYS< /eKGGWW(P/W22נ4ssd}`ƭٱnf -ո*ڥCΟz7zr8M-a1ÁixuDM)G~AE6MRhd8"_tqcP¿EBą wF@4H)]:u q07o93;nO?ċ/>֭;v7::=m M?_PW_Y!JӆSpHZ"NIPxʲ W6.M`w"}mElzq?w֛o޸|Q1>wff&'#n&tRJNCyE`W2%oWǙ3ׯ6tiioi %˗6zwvp[ZZtjTLؖpZM W"./߾Mڵ?OY;vtt=443s!o_O?B+#11i3Xe|F2(:a(PH|6_++Ν7oܸy-g֏sz+A"JH(RDH[ͷ V<ùz/#yT"!WܝVW?VTJ}2!|<[- !l^5@k~~ywymď㧐=fg51,ys 5WʫlU T<꾧q{x4@XΗbիy.&-'jy&i)L F渴d*ܹc:;zꡇ^{m+Ν=/.~gwr^{𷀵R&Z=J(c۽y4W8'5mMSlFZݼyo᧟~GjX 8szzd ޽}}(C04h4&꡾Q]çI t+CP#0Y "!෶ pp۾]6&7&CCo~^~T33k>+رuƍ;vl>:j9Mҥ7>?/i< uBPqjTeǏMUv-$ϳ7nܾo{|ǘQY?1֏߿oΝ;vlذ}{WWo/)bv)8W"5Oˊ-i!ӅB($|RիwG $s#Q(ꥊ2iYX/16Rh\Z9q7Hš57nذgOON5Wo~?HIWrՐ"|TR( ia>FXgZںB.[iTLY9_||ɑ>񮮎]n}W_ݼy{&&(Tgh \YtOm8܌J2>{Dm@~c}( _;|@ɧ;Px %<ɟck׾}ݯA6-6 Ij]4n܈ e]C._&0#VVWOj"I9!'%iP# ! `ƍ/iӶm7wu e2MK(x'|իRFfĻ͏**07RE56Ppc@,Z\4FI%aɓ@\|>w[$^.Z`GGǧz{ۻW֬y챵k׬Yn׮nZ֕S݄I[QW ۯlM`tQKʽO(yRAdА0-¿$y ]jӶ$"U |(J@:vlrrӦ׭E0i~pcVE f9)(ʗ &KW*BR Yh{Ͽ. |n?88::<, /SO=s+SOmܸ}0Pb -}ԡk3>-qyfE!am@r )s]uҥ bwo(RP(SM;Р  ͛&&H%QbADZ5)G&$dcf)W *`^XsU2)NFNu//~>`$d91R0 ./]%fxԐec t^@Wqpբ.\vw>Y9HolQ_9(2kmh+@> HX K4&0Du@dP&h! @ҒeG?¬Piop"g\' "\;Si )Hx6]F I˜㑍Y'|}W$r!" 49)uk=C=3wwO?m[o/PqOFS !`Me+˘6&y,8_-mh+@Z;!A!1@A. VbJ ,e?"*okn$%Qq(aXkSu@8_g}|AAxbghhj~͛7nヌzMz{''LɂpJ@.Q0$1EY4=&CnU6Kҥח1mhu@)V"FlzG$ > HJHHgs0Eαt*pdY2NF@0zTgBR[jAG:&i$|J؜7ΘMM ׏>__~':|Jl[ڽ{rǟx^{wbޅn> {]itN _EXPGÌdzZIQ "Mm(2XNgHu)$+uIe0DŴw=4##0$8*M&e snQHUSЭxCh~a~" )f(\,>?O?}-©kפ!trrppd{ttffjjpַPgxo֮Y \InarWI*X[GA؜k%MaLx‘si_ڔ _FHuN6wI L(Fd(w&IcCUܖvU2;QFAn3 4S$kHt䓯VWZ),>;;6FAh``ddjjt{DY׿:ͱ$C+iD 1d 2ĺVibu4JG\ n6=V-hJlM7.rq,*`H"5?OdH5 ƨMfxDʿE[]<%$6SrHQ,&\b7//{IPܷ![s=K/ollL*5e. ՗1gRr(۝^Mzjkؽ{Ϟ-[Pn޼}]w=0҂|=ȯ94ϸP_Q2¥8IPH2FHj0Yd(* YMP)thK $4R2/q_+ w]+Ǟ= #4*r饁@@/I2 k% -7WfPڵOדF)VVWaAhр$sAD \@fA#& $=C筷~ G&<3[[kv[ѲEQsdjAZ~5S'7_귿{7/]Imfh׫]]P72u$"F9KNM1ʆvU ︕qM|Cg؜V0XW#0I}W8N3ޔčSDhJqREBIDnݰ4{R(.A>)#ޑϪVBt !t Uj4 5K|aC%q V8E>&gC͛y ntFtR<0dϦ rQ-Y24K\ #^ ؊x jN"Ei:au`kv(t#7~O 7>~6Çggz{Im ٶm4R WTy/PP9YMB, i*6F;׊Rf[ $B1 Il@\SׯSQ蕨HAW @iy)tb:LZ gB#9X rRɹ|"KsV35A* effpfgReT7n08U\#nQK\%è#'& J@z믿_~y΍_ƒ92:o߮];wmꫯ}ݝa$͐[ QiFuxUZӒhN ~ MJe[>Af @s~~)H8pc vJRqѩ) 0r1c&bO 9h9*bk>i"BṔ?Q* 7rffllx6|ao'}? ÷zgە+g:D{8bpl&1RQfΦ#uC yiYӁ̺F)K9N_8On8s ϶@Hſ1dU&KmUEZ#4M@ 8|&vi_Ϩ[͟S5#LԨR>9t x|&/TW޹'{_|g #T@ŋ mݺ}u6؁H!xn`$8.mjTGBYW%R mf{MYίTBt|, _~0T'a [)Y*G`B;H #k|S5<& Sq HB)pW33N@V62~6={ 9jRLv&ƾGbiP5k6mdݻi!Ę"+PQ۰0XWi,G\DA.zC6e% @Q-…@ݚn"f6N\ :\*lՂ)0(GjE 1S nl8P Ib{h A~0:Ũ$/G"|(M 85?{% g#݅ n޼kWo/m!q-%)R"3e[$w dr-xL)ׇ&(>Z@dW @=w-6)-ՈR&2Te2cFsHTA,I^8QT'ЋYBJ=:*@WCCF"MWWO 6r oc !_~;@-/] ((s!}}BGF;;P!)7#FF_5S&\&7ipU khxF4@gҥp VqlKZ5 D3.m,?5#ttS%=+$1q9d0IP!ʘwpA3'QJC56uDO 0xrZz:ш]hlI[_{)J @<ԁ7oJOam`- A7찄ɥdc%#FGOz-BE^tkd-:9$B¨Lbh#zICx aaȨ. > @_Lr>FGwػk׮qk`e"ou6I/RMVJLNb޿==\[@0J:Ep ϴAjOZM?:B Ul[ZX5rb:sf`L|$휌!sCt}AT4`; U4T 0$M3H (a㔣g3m^Zw젹NI8yҒcnݺs磏>zqTK331I>) =QKNaPAu'J&=n~Yǽ\\ Wl$LDRdMTjg~UA)ՒH ;/Ɠ>GPf(H; X:AspLB|M$\n*$ &͛ݰaΎG* *1o߾u~??q204084H}"8yPOnJF$N%zxW&7xo- MB6ܞ-@ n6Y(I#ۚ &#j)G1gCCX)1} RB]lPd0- B'Al˪P;r={vܲ3߿i| %Yޅ+Wn?g<q$$t 8 Hˉg1WiO @K'#yʋPr&ޔH!StB>#(!\ZZ^>i #662Fـys$,af<S%;B+xsmh,IN:й#I:aRz f`bD(j4djJ:SHkѲ9/,Cs:I,bvf回>p)eD}ݷg)rˡoQHb (C3:s\<7w*3jXD"V9!>L!eVx uulq%#9qJBnFztK1UȭO)iJcc33HK(ǤرB}H@2h"=dW¢`lڌ~ ޽|304~}͌K),ID{CFφO+( {f5G`J+%I/_8bP[ZZX8YcL%H W1T/[ A±c+T*@ kTR(xC?)aCTl٨@_$/мCwޤ˨͛&^HDv²tpS:M%pw8H|a@3CsP4l YKد^m+@+@F 26%6ghLCQq׮A sK)D|Ŝ*J#6>:uu3BKnDH˅:M Q,<m"E`FFzzz{t&d|._zMYSmKӦ58u H~?/3%\~ę;wO-,|a^hm',@imhuH vZ h Mq8D(+[\aL7n|{R;^5IݘdϡC}}og޹g΄f)Iaۄp}48$mI,Q&1@p{{x=pJ kP7]sN*(P@JvYW4|+q'?s' O[nA/,0>[Z0qI`B0mhuh6 8 ) Y7iu֎@ʄM5d P!pPP!FI)?f."3O=51A),I[ %`UuHQf8n5eKGpy- )6q//g8:JZ"(Zo5朄3ɠQ:vq5%ia)J)vNx-Q ~Bcge`{I@0!a!ڝ< DEB(fAHLr]%LX r0VX:ۂ nS: 8&* *ʧB|~i`yM~ 8twPmuH<u! ZMqyiW%Ц(5Lx])9㗔 6z(m!y% wқoFR +a`[Z\`]<.e X((#7g[@&Cgrԙ(5q,vO9h%s +?*6FZ}B433$ͶOMڅ#1!T3L2:躔S:t7.x@ش/^d3,U[>H 0F?Iyk"QCUh}F0gCR)TSgnٚ%/a[еs HN6UFuP1d1I $U|L ->C1rqu$&xIQ -_Qt#j>B! <~M#`F[F mhu0`,iT[>m^0i-04evt-;wz}B{ȇ^h:.A\E h-ޭԪT xkNəT6$*Tg6p b@bdTPB?Ι)`? c]i` ,XP^&FHZHeqZ*Ǥ=Xʹ7ߤBɓy ]c+K1/4n%jfWg*+UuGxh a|>8{vy A)i|_.̨ ˰=* s8ᇆx@E򬠐?l)ʆh+@+@ EZ#@+|(}eQ>U!PAp֕+ǎryW@Iz7o;gwsvfֱBAsFZ;mS ,Ù `s.~'s4Th tY]}lRg3NiVh o:Wix@@n?3(  d2>mK4'жHJ΁:؎H8]AM33Ǐ55G٢5,9 R#{߹jeXH$ Q?=R":_I(g O\e- L a&%$u!Lc];mYԏ@C qP<+ۀ/Mq9ML-_H@QG 6 Ҙ?qД&Kh8,#z{ N뒊*^T -`ciT /)]vK!'KBT>J)4Gt 5̟NY8 Rȗ4$ \\aBYyҼ"Cz  `(uK7Zy_q Ŧ3& T2$ |ZBvXm 3 wCaf)_DT B@ʇL$3 9UT~uY/;@ cFrH['qֵ@>Q <4|tϜi+@+۳eǽew%~MqxmI,˹Cap1*A@وmv03>0l0RUBh1PUjH,iS5&:r&)T~! i4`NY4*@QW49ݺEWjʩiLWywsߔ}}$n ٪SK4tܐ0o yx>$PƹrَFB51HR4 LLq:Ka̲` ?d)p&Cxu4 tUi, |`8gXv +tpq"Z ִ514]I"J9rdttnƍg!F!\wZ%Z8 kn66S,7]@s0 ED$l ҭ&%nKѳI U-w14P5Մ#!Lô2E GԶf<2))RG|VViذ1АULx7\Xq""9rjDGjO^E1)J* #s [$J(fh5 (Q~+STةY`#wQWW8PrE4]S}s@@&pB?d~ QD-3V[^H J 2%tOP׮ʶbl xt 6%Xśm6qFʐȧ 7 waT0c N + ,J0U% )*A7^!o$Tha02"-!N!T r -eXnqk+@+N! bϥT,c\!+J򚀢Dl@Sr ljcltDooݽlB)q '0Pb1#j&g5Xqh@o+@+@ZL &\QZ4pпq%nk8lU~M 4a] IqD򋂱M,n^AR :ztxxfbA/ =M`s 8҈fG}_8'd[i{׫iK׏g 0d(%s^W@:)y1Ϋb`4mi[J[Z]BX̄("2=j *4QW UZ [9@lI99G1Z"##D I "N1 $PbisjBj:ي?[N.g 0:0jQVC@\clGqdK 7C%md˔W-; -$C"B)đ,P7/*ɦSi)WH.E&`JIhFأ㢭rxO_=:4:903449q 7Fq PDH踁%0ܻ4 Qm9hHVQKQIP+jթM_^SB/i . SptM,4E-p5Mx5D, HURrn==ђN9lm  BvSy(f(tM oN); dNjI*VtUǔPBjN\5LXL 4VW4M:ȵ&\ E ҂Om,ӔUEʂK7[yM [1Y"|}[h4 9==4m[w ۶ogǍ^`,粨BIJ h)SĆ(R9~FI9{m4Z/ 8- & NA*La+E[idt2a}1 ui`RdREVVW 8cLE-L'qq *e\PU&^l-#`pI[yvjk޾ ́##m[9vRl"~bx[@D ; .:) ]$r$B˜jRȥTԶ[(M]gʕ dg C ED%[E{]6mT0E@C(ݎM 9-@M:ƥ \GIӦҔz<͐<LkJ9)&-ػwӦmzzHIIF@ @I L+Mªdg\ g)(hô%AC"); a~,lW[~IN?VVWPAT18!JM.N^PE M6Y C'=!rLGE:,*dS˚Z=2d5t2)Nzᅗ^ڽ0Dp u QA12ej1PLe&<A6EXEo(Hë6g xDC:8'x$m˽֗ h2YTmR2,N6zTK/,)TZ0k,iu$cSVˠg5kz{'VGJH˾\P0 QDNR4,62^Q1*9DƂq?a4 92BVK^phC3~h+@[RЕrٰ$p, 4^)網iKe@(v&xpn5P(ݒK fOB(jfIRM56IPXVxVY%*Sܒ ٰ\H8 `DD1ŤSILc6VVW>1 TnǎΝ>CxR!D*IP5 #Xt rucй *ML)j1 Iw{Ν7o)qA('N$Oe敆: Qj |8 0нIͽ."M8i+@+-0}mYdH"^_QHEe(p0 jhht xT^"8zt||ppnnq1[*#ԡ+ K? +\IXeT `ͫ O96F(kF^ a @y\AFɓH13*&ͭ'A Lg5 !FfpkFi8|xl :p 3jo*Ȯ]F!4;rӳo0z(LMA_-1MO3]\e)4'{&c(֗;=zPXAI").&ĖTԈw钼7o5I+)4 8\TEWMҹf$۹\_V"Z$@3 L`bbp DLѺu u%T$%TzU4j%UE'OLACY u|M қOY@5]mh+"֙pG.^S٨EgKOHOGBRU@U1 ru0G$ tuO@ɐ8&@ 28EEI'ĉZ@ΣEK,N`Mࣁ Gϟ>M@SJeHSRVA(\G**Pnv8?OViV/>=}LsLL|BD%TfJX63116w/Ж}0 {+3 АecAR 3/@V4G`jH6yZ:E[!cFQQX>Ju')ZO<1Cfܚ,!N$* '/"g֊*i!\(vR/) cE#'&FGQ(Rm")2QρMknը^P#Ef'JV#i FUȨ1yu%#tsSm k+@+@N?DmZ+ X:([&"ŽfYr1qn4Vf;VIRj"#hb(?q ʰ44֑ DR$UDD!\/2}IAo)@s%2} vPx[ LGH*!Gu9m5qhm0iP-CJETM~Ҵ$ C16%dtPz \ !?d5,dmln/f[¾*i˹Y{>Mzm|*20O PѶ5NjHIuVTUnW'RLϤֱf LV^ tr^89unݴir2;#,;\`ʨ@Ć$s]BeV¤V56MH:H(C)/hqH #A4B2mhup[Ɉ#<@bA=3Z͆/QD*tsym\!;33?K=fwС_߻wllrD0!tO9P…ĂQb:͡G + :ymxg-[eu( T'2 B-$B[Z]*wƞ: >oepJ 1aD''u^H&7^g <@"(@Iu]{7I !oeN2$ *H,2թFL'LҊ3Ulu+]K1M@(+fi&QN2hdq[Z]LS͕C'6"\hޤ0/mSg΢ĠԙmXJiHz!&Iݔfbb|R8RBsBTK(F"(ƢFSdMQ+#m-:TrʮT`UfOzGJhʭ $.c'~*dRII1尉 P&9d-lֆ@*T.14 +Es`.J.]ɜyt&C0IDAT@88lWIMNMtoZJ`FECseDWJRi5ʗ39/_Δ$ Ť'R3* / *B>[Q z8pr/s6wj *g#iN^ĉ X5]iKaߡ1#?#t ·&7#cHkQIsM,pX]j7bоUt:2TOFC]Â=:1AcfC`zKg<#*8J^ጢ աR"7(7fUvu72) YL$C"…"&!1 5t7C PJ}1U)7JUC7։L>"EZ¸F>gAShԲ[pB?LL  Bݿb☑l0D:Hnxx^P R 5ìM6EuM[J0.qϠ96үG uC'2I< $?˗QFGF iÚE =l.MD0AS̈@:KC48** 6#4q)%Dev>pQ2332׷s}CCHBYw2*cm;E塡-[&'yDBSMDi-MY^5\@5 Q'-ٮ5zQC}A_I-/_ =Ce(JLW@qLE%r%5eFKL5xV)I%U$ٮuRTBl DWמ={ 4VAPqpn>/iJHiMh ѝD6nپRf8;DбcOO9)ॆmҥe>@W2>)Vmd+_tc8dn <^o"K 7<1i )m_)˰c HΌٹgbi?D k>!d;C6L +P+5z"HQ$u),A'O5[VqR0{C#$:DCܷ % Ę@Oj8n$踄" PeI)ߤdJȡ҂0Si N`ܒE( ۻwǎNRI&;OE`*]'O^p6! G)ՖcS*,MJ5{7vF QB!`)etGap V=*AmC>5Հ ALUsuXH08P95}'1)ZWo-mذiSG$RB@D8Y`,͕0fa*Qm69HFnlF Ѧ{zv|{͛!WXEMOgߺ`#)\CRiþ)/'U41v!+""vX@s"xJ:8" L.-$nҘtyEVEEXs-M'dhq)8=hz y $uL ;~{y뇇uRp.G9tƠE>I0XtcbRJZhIT) R-0V&!`u)(z lL8â!omhu(Ε&iD!M7x04f/ I*>"^[2^/A (!-.b.\rhT[B 3LrG''ܛS(9t֤G!8*VeJ+vm(&LgQϸ~4 R)4 +ocǾ}rB$لH TNU^=r>i촞FJ+ ȵӀ6ZC@D'?Fdf1 1%͡ׯmhqH*(cӠ\PM C#E-27!YrRJ6L:DZk@R \1 *|iٷW;:FF!H)4izT$i-6e*i?*wBBde{L*$LX]s@Atq4q *B[ ЄmgQrբ\r330 ͢oŵ,HH+ )y)K"I9pjjrr|!NLl߾n]]o/@&43WW iN/¨45U"ͣi3Z6m]Z8u 5~ϵJ:(fA%I!$n0 pv@E iD)*r/a[>A Tϼ &KMXv 7`4epH:<蘾>H QIYGq]|E`)iO 6e_GE]\P/UȫlkJCp# *!|˗.YD]VVW8o%j^(# u+(L3 b0$ :eJ$3@lYɫ@gRQwA ) ٳg΁[S834H3a$/\fIF)AA)]M>jYc:B;Fo0  w!mhqHOJ-aѨL!^_ʳ3Y#dBn9Ib&NY3j/ Rq"0E*wmbm&wC$+ oTS(YՃ$YqUjz< PR.D \mQB&0[@ J[(J8pi?..c$NFQG*I IiZ~eMAv%*bq䦖0R&8;w -)B#kȈ1EܔQ-;vlx`L[oIBp(M3X1_7/M5YG0a 5 `pIH;xh+@+p{uC\VO(B2&tp@DCmnט 28#%|:ĥ_ -K(2q!huwbؿ0p׮ΞA@5o5vnn`VlE/4UQ [3&[[5͞~KQW~2P TٳΜi+@+seSrb%'Oi b*t ehҘ)J$j+2HvقbP$gOwm۷؁Hc8%}JPu\L7eZ. 8ZYz&#G`łL5Em .z7xS^Xx}DX|ܹ+Wp  `[82cL"itۊ2΢{z!ky(cIBg&&\C(l ٽ{7شiZ1)BO84dx ͭ\:4vX6eufRVR2*جΟ_ȔjD1qE(t ni xqq$H Ď_to 8ĂPҿ C HxӜSQY@fQ%ǣ[W9t$cd'rLp4JIs2Ȧصkp a!˗ P0plW,.&p$ËL8SnEmFƚ$ąI9p M|SJUByMUzooGGwwg[  F1I`z* M=6;i?rk4_ Aԏi K;Fp[ 8 s"u{~pbj2\QiBN$2Eڮj|tAO%t ECBeShR񷢸rCäwعOQ&ۻo֭< @v@&K [>j(PL**n6׬9S&p/N`V@ rR "$I9xq͂ _}y(a|*A,-`&x͸B*B e409^$U Q gRS]H!eV;!{Qڻwpp(c$ Rۧ-e b`--# lЬVӧ_=z ):yVX&Pq)bSB|34- N:rdlljjnTA>)x!%lRHlIhjp 2#Wa4Un*IL9e#GF]]]]A2:9)q֭!)cMpOYS>)OmY tp h! QDc韊0=!Dq1^8f ? h+@*@D$"bn&Uf%(_Aks.7-e#t5l*[نr:Y c.6n9޽s>( 'R5X8M:\Dh@Ǹ+(jc$a!XK hB#MΠ0K /.dl̙[=tқS*$qV0~1"5>5BS>v"0!Z,Rǚ>rD-b@Excޮ i,0U\K*Y!+a6^4 ooI%#bUj\e' A⿴T ή. I7] -WhXYHOdT)&Z HKUTKZ3u0~qhԔGܹf "t W#%иY 8G;4 :&rP#^\WV#ܬF!!Qu OAA촆;4 b( bwAmhiJsi HLLjj3F9A Qi"PV|tPe,e7e mPZƁ~A! m۴i__v>"22tP08eTetMp +8f.+gRH7Pp |?~Uc EY\]) l;[ŋ*BFE\>& CHj3%ȫ58j4ТI{ [kSSohb # 4>>6ۻqضm˖7mE$XVIj%Vҿh1 F!P&f43J!1A^%%bƅ ~%0(fJHu40) S7D5yiÇ'&9w ]Ak`Om6[)_{'z{{x!!3q}-۶ڵm6Z~B"2"iff&&xcy ) <^¾bEQiLM PHa{n5ĄL\ɚ Wq l4t!=0y4 <ńshI"F2 uy$SРa3dSF@B]^~?|{ΦM4"` uvB#};<d~d 3ҐGzT@c&ʸkn b 22NjQUC.sK áQi؉3Hv6xw͵OAm)2) 23a!@!R$vR幆 Ύ)B^\rM;.MO;DV .(PG /`{w~x͚NF t˖[7o4f֎dbiCiuK]F)}YPUHvPju.U9p/^h$/!`R|\q/$5| PPJTJP^PIs&<V:smIKP'LJk׮^Τ@̐"m),޽k>#{wzg6nܽۻ{ oꫯm۞=F0DX'j)'aM }R"ծ3E%Y ; X\lB+zM#VL@[Z^J$T(rM>KǴ~ՠ$lC3Xwq`<;`kנ:&!MEܘeMx{TGygy[og_{^xّ  ,1!LHQH=ʦܼ!qPd\ Hx\rÕZ40QаHPnC7C=@O\\֠c' tEf5(Z%s-}u7ǣ>coX9^}u͚W^YW_]9^~y֝;%QsgXs* b#fIMLgϮ&VN*[GPj^7t^ES_g:lFI VM՘ *䷐VU㍒0=So!XZA:6" q#P\AF"ʁ۟{ַ0~ɗ^ v /K/G/䓏?>oȘiT!u OM#6 Jyql,3V:"Nf7 T@m'11Mxaz[Z]i&1$&6X $^>+%ŋ$+ObRLH#?sk׾"ഁ@$L$mTCY7]_VN"K{LUUq\(kj CązJx|=nj>h7 #zlȐRQ 3>gѣ`[o~T{0? zo'xQ~>,={+ 6񴌅:m>B#XX 8Pϧ &b lONT:d" j̗!2|A(CVVW TБ:;|p@[B  ! #䐨j%mz*Q5|6tnѼkܹzk\=! ;65k׋/> ߽>0&c1>Rz}gw޵kt4垢BlE5:Tq|ŕ f&蔶&1^P$ .6\ ,C]xL0ݔ~$2Οmhu(B"xNlNяFoӔ*  ?%ˈe9@I'ʕeV𾙙m^ziӦ痖P篮(lKws <ڵk=w_GǶm?<<^9 4QvYp/PN*-BA6*ͤ)!.z8)Ciz]P2*P^o+@+@wil3hH$D3XЧezTLIa:A] ܎%lq;:ƞE}-[H0/y~׬aGyy^x啧o^z~;&A:؆j h}ab\**).,Z4eMڻ[P BP V"w ƿ9ݐ2a$BNDW`X` C*1R\3 9ݹ9 .:2FqZ1 $z,ʎ=2C5=țE";f;:>|~8#O=E?ЃCo}G֮}o_xa [V<.aPI`Pt sټ &1>g25|jWA ;(% BPM }J"zq6aٹqӡ)8="<,}JG@iSvb#d+LJŠ$ ])3?/--,\@͛z?ذ?яx'qF|bg}۟}y?$m <C'&oa~LZ 0'-޸̃np0]Ae䬩# R"Zq)/G}:VVʕIHB8Y6 f&hcK@͌`2dqT0q4b" ^)<8:ݽnڵ/fڵe /<SO=?sϭ_OK /|[G.(cP@DR:+U5ª:1\HRBp}=s~XZPd)@$0XA 6"K6ۻcMxԄLPhv_̌. %͛2i䀞V(upt55C6Sn Al'ٻƯ5kn޲מ{}}[Gl<};ڸqSl(Yru3~1pY@U^^PPU3{J-Ո;^%\HB-]tI;\@xq^H |LBfnmvVbSŏ5D TC$KSC.ݱ=s DIgDuu[9ogPTg' _{y'|߾}ppӦ~7QJ,y'IL>mj4&G]3DRq 𻠰FJG u!ҡ*)x@8&-UD$8!5J(S)P`顕 %R>quc(D4Ѭ : udjdȑe@(Ǐ߸q:.. -,mϾ:Gٸ;wi!^z顇|Mk6hmO+OCHk1TBW(gjWW֥ߤQ\r${"PFB"V QLD Xsdqq뉫"] niB ugHPlJQ)dD2R4!`no߾sGq$~FEa|سرfx `$?CCEgJR񗛽1 /"'N$pkzU И *%D E @T k1AGE>U8bf{ƻ*?sEnpFe0& Ė1#wz_|_dċ/B!t|G*w$+iLʸIk5gwT5Uׄ%li8ҫ$6 xU@4)P݃-j> pH ۶ٳyƍEn4~{>*Ð?q\O0'.WPY[BX'f;uJ0ӂ&-P:Q$- 4}:(F548Y {)y ~_qhS>82 tc㞚"2;+RrviH D 0e%Ak83 uA#,p7wuرmvuvvtP:~GF׬Yn{876F8};C9[fMX C٤ss7A^dq -&1͆ JkxF !ƟGP3Iyc+`aV+XbSı}! P/7NS77782=vիHڗfxe &; &Iwa/ꫣc95稨śuJ"&  .T,h!)+q571ڍ0-[0P.qݢkEpfJuz6mb]`PHSP(ngGGq!:L44E%Dfrr||ddǎȢz{HIH~C!s ٸqfs``ՄP Ic-/Cݪmˆ{$ݛ4 ɲ XȯF¹#qp_FF0E/^(jgPT2QSgq)(pQGKǤ]n̊$T+c(tP$(Ծ}2aCGIyllݺؼyzz`kpcÆ^8J4Ê"TS]&M 7mʋ2 rYMi \};vrm76Y4C}( IDns.NHx $]48d$}l7<{R*bȢYKP فT'$?zаNDN00 nE075tu2Rb$eB }+}T Y@R\<@ d|7r I o)T 9 $'Pz&TOmqJSR _y3":R%Vǣ^~dz.%gA? B "|sqB"恕c߾)׭#ىy`tc֯g4po(P7{Y©oty֡> :"vt_[^.I`EQ$ W¡21e71mh+!b@9n6Bۑԡܺc^,:.IÒt2Q:jY&PK"$n}^)D5Hn߾A` }cڵ۶az{'';:lٽ{]Q tG?>[!Uٛ],a /,yoZ kj)\ޝVW*)ne5T<*¢x.:&1.()j1Ih"lÙ4Mq-%ZÖkgH"%ʥUYH ؍ ==;w֭{(پ}Ai@ŌBtI CL'L<Ŷզ4^(<:: %HGN^I 8iALB[ tpLr-KW]<(ǴÔm$5qXUˤiV<o~84g (&BjϞ{'&lY!?Z`bFGrBQ4Wɽ8i,ɗj!aNP ]s- 5LV:$" iO( ]R$QRMdo/Q8zڿL R!P])T'DQW# ؊ԕPQW_фSj,:7zǙKb8D>.h+@+@5{*x hTy8g:1^75"N}5@CN]ufULfP##D/Ö )CHQ KI W oaVg"%:_P gK ?o<)J<2 [bڵʘ͛!u4 NՉaU9% G|UdV , GUHI Bߘ=l 4XV1;)\YsrH=+R xް T# Dul mG$ e2gd) ӽlJUE%唭^K*Pޭx'úr_Zw].xB2G!LM ,cJ `3tu}}ۥ[h@tVj4y'blLQtJ"*$Z$E##FggI0E*)ڠIՐ@b2P_M!Tx A;vZ24)`}0T8tOΙ393J`Q`P]<r%1?J ?u{ʆ#+)`֐3(fGjzdi 5 T@rq벙8 ACscK:"7&{hMB 51]!0$qtM!\k djui.˿'/^TRmn&MTJ)B$5Ch/mvVUF>]V%tEXtdate:create2010-08-17T12:05:30+02:006{!m%tEXtdate:modify2010-08-17T12:05:28+02:00c(IENDB`scikit-image-0.9.3/skimage/data/multi.fits000066400000000000000000010206001223313777300204520ustar00rootroot00000000000000SIMPLE = T / Fits standard BITPIX = 16 / Bits per pixel NAXIS = 0 / Number of axes EXTEND = T / File may contain extensions ORIGIN = 'NOAO-IRAF FITS Image Kernel July 2003' / FITS file originator DATE = '2001-09-10' / Date FITS file was generated IRAF-TLM= '2010-07-02T19:33:03' / Time of last modification COMMENT FITS (Flexible Image Transport System) format defined in Astronomy andCOMMENT Astrophysics Supplement Series v44/p363, v44/p371, v73/p359, v73/p365.COMMENT Contact the NASA Science Office of Standards and Technology for the COMMENT FITS Definition document #100 and other FITS information. INSTRUME= 'GMOS-N ' / Instrument used to acquire data OBJECT = 'NGC1068 ' / Object Name OBSTYPE = 'SCI ' / Observation type GEMPRGID= 'GN-ENG20010910' / Gemini programme ID OBSID = 'GN-ENG20010910-15' / Observation ID / Data label DATALAB = 'GN-ENG20010910-15-001' / DHS data label OBSERVER= 'Jorgensen' / Observer OBSERVAT= 'Gemini-North' / Name of telescope (Gemini-North|Gemini-South) TELESCOP= 'Gemini-North' / Gemini-North PARALLAX= 0. / Parallax of Target RADVEL = 0. / Heliocentric Radial Velocity EPOCH = 2000. / Epoch for Target coordinates EQUINOX = 2000. / Equinox of coordinate system TRKEQUIN= 2000. / Tracking equinox SSA = 'Walther ' / SSA RA = 40.66966667 / Right Ascension DEC = -0.01316667 / Declination of Target ELEVATIO= 0. / Current Elevation AZIMUTH = -135.173831944444 / Current Azimuth CRPA = 0. / Current Cass Rotator Position Angle HA = '+01:14:25.87' / Telescope hour angle LT = '05:00:13.7' / Local time at start of observation TRKFRAME= 'FK5 ' / Tracking co-ordinate DECTRACK= 0. / Differential tracking rate Dec TRKEPOCH= 0. / Differential tracking reference epoch RATRACK = 0. / Differential tracking rate RA FRAME = 'FK5 ' / Target coordinate system PMDEC = 0. / Proper Motion in Declination PMRA = 0. / Proper Motion in RA WAVELENG= 4750. / Effective Target Wavelength RAWIQ = '80-percentile' / Raw Image Quality RAWCC = '50-percentile' / Raw Cloud Cover RAWWV = 'Any ' / Raw Water Vapour/Transparency RAWBG = '80-percentile' / Raw Background RAWPIREQ= 'NO ' / PI Requirements Met RAWGEMQA= 'USABLE ' / Gemini Quality Assessment CGUIDMOD= 'Basic ' / Carousel Mode UT = '15:00:14.2' / UT at observation start CONID = 'GMOS v8.0' / Detector controller ID DETECTOR= 'GMOS + Red1' / Detector name DEWAR = 'Cryostat A' / Dewar name DEW-TEMP= -121.220657276995 / Dewar temperature (Celsius) DETSIZE = '[1:6144,1:4644]' / Detector size NCCDS = 3 / Number of CCD chips NAMPS = 1 / Number of amplifiers SHUTTER = 'OPEN ' / Shutter state during observation AMPINTEG= 5000 / Amplifier integration time TIMESYS = 'UT1 ' / Time system used DATE-OBS= '2001-09-10' / UT Date of observation (YYYY-MM-DD) TIME-OBS= '15:01:11.5' / Time of observation GMOSTHT = 'GOOD ' / Shutter health NSUBEXP = 1 / Number of sub exposures UTSTART = '15:01:11.5' / UT at observation start UTEND = '15:02:11.5' / UT at observation end EXPTIME = 60.0029079914093 / Exposure time in seconds ELAPSED = 60.0029079914093 / Elapsed observation time in seconds DARKTIME= 96.9185329675674 / Dark current integration in seconds INPORT = 1 / Number of ISS port where GMOS was located GMOSCC = 'GMOS-N (V2-8)' / GMOS components controller s/w MASKID = -99 / Mask/IFU barcode MASKNAME= 'IFU ' / Mask name MASKTYP = 0 / Mask/IFU type (0=none/-1=IFU/1=mask) MASKLOC = 1 / Mask/IFU location (-1=unknown/0=FP/1=cassette) FILTER1 = 'open1-6 ' / Filter 1 name FILTID1 = 20000018 / Filter 1 barcode FILTER2 = 'g_G0301 ' / Filter 2 name FILTID2 = 20000018 / Filter 2 barcode GRATING = 'MIRROR ' / Grating name GRATID = 30000008 / Grating barcode GRWLEN = 0. / Grating central wavelength (nm) GRORDER = 0 / Grating order GRTILT = 65. / Grating tilt angle (degrees) DTAX = 103.2 / Detector translation X position (microns) DTAY = 56.64 / Detector translation Y position (microns) DTAZ = 2842. / Detector translation Z position (microns) DTAZST = 0. / Focus at observation start (microns) DTAZEN = 0. / Focus at observation end (microns) DTAZME = 0. / Mean focus during observation (microns) DTMODE = 'FOLLOW-XY' / Detector translation stage mode ADCMODE = ' ' / ADC mode GMOSDC = 'GMOS DC ' / GMOS detector controller s/w DETTYPE = 'SDSU II CCD' / Detector array type DETID = 'EEV9273-16-03EEV9273-20-04EEV9273-20-03' / Chip IDs EXPOSURE= 60. / Requested exposure time in seconds ADCUSED = 1 / ADC used? (1=yes/0=no) DETNROI = 1 / No. regions of interest ADCENPST= 0. / Start entrance prism angle of ADC ADCENPEN= 0. / End entrance prism angle of ADC ADCENPME= 0. / Mean entrance prism angle of ADC ADCEXPST= 0. / Start exit prism angle of ADC ADCEXPEN= 0. / End exit prism angle of ADC ADCEXPME= 0. / Mean exit prism angle of ADC ADCWLEN1= 0. / Lower wavelength for ADC calculation ADCWLEN2= 0. / Upper wavelength for ADC calculation DETRO1X = 1 / ROI 1 X start DETRO1XS= 3072 / ROI 1 X size DETRO1Y = 1 / ROI 1 Y start DETRO1YS= 2304 / ROI 1 Y size AIRMASS = 0. / Airmass averaged throughout the exposure AMSTART = 0. / Airmass at start of exposure AMEND = 0. / Airmass at end of exposure NSCIEXT = 3 / Number of science extensions PIXSCALE= 0.1454 / Pixel scale in Y in arcsec/pixel NEXTEND = 3 / Number of extensions OBSMODE = 'IMAGE ' / Observing mode (IMAGE|IFU|MOS|LONGSLIT) GEM-TLM = '2010-07-02T20:32:41' / UT Last modification with GEMINI GPREPARE= '2010-07-02T20:32:41' / UT Time stamp for GPREPARE END XTENSION= 'IMAGE ' / Image extension BITPIX = 16 / Bits per pixel NAXIS = 2 / Number of axes NAXIS1 = 132 / Axis length NAXIS2 = 288 / Axis length PCOUNT = 0 / No 'random' parameters GCOUNT = 1 / Only one group BSCALE = 1.000000E0 / REAL = TAPE*BSCALE + BZERO BZERO = 3.276800E4 / EXTNAME = 'SCI ' / Extension name EXTVER = 1 / Extension version INHERIT = F / Inherits global header ORIGIN = 'NOAO-IRAF FITS Image Kernel July 2003' / FITS file originator DATE = '2010-07-02T19:55:22' / Date FITS file was generated IRAF-TLM= '2010-07-02T19:59:26' / Time of last modification CTYPE1 = 'RA---TAN' / R.A. in tangent plane projection CRPIX1 = 196.375233233945 / Ref pix of axis 1 CRVAL1 = 306.871725219222 / RA at Ref pix in decimal degrees CTYPE2 = 'DEC--TAN' / DEC. in tangent plane projection CRPIX2 = 143.509119025456 / Ref pix of axis 2 CRVAL2 = 37.3733845984976 / DEC at Ref pix in decimal degrees CD1_1 = -2.9266657155837E-4 / WCS matrix element 1 1 CD1_2 = 1.36727521936194E-4 / WCS matrix element 1 2 CD2_1 = 1.36706238220991E-4 / WCS matrix element 2 1 CD2_2 = 2.93036096725254E-4 / WCS matrix element 2 2 RADECSYS= 'FK5 ' / R.A./DEC. coordinate system reference EQUINOX = 2000. / Equinox of coordinate system MJD-OBS = 52162.6261539214 / MJD of start of obseration CCDNAME = 'EEV 9273-16-03' / CCD chip name(s) AMPNAME = 'EEV 9273-16-03, right' / Amplifier name(s) GAIN = 2.1 / Amplifier gain RDNOISE = 3.5 / Readout noise CCDSIZE = '[1:2048,1:4644]' / CCD chip size CCDSUM = '2 2 ' / CCD sum CCDSEC = '[1:2048,1:4608]' / CCD section(s) DETSEC = '[1:2048,1:4608]' / Detector section(s) DATASEC = '[33:1056,1:2304]' / Data section(s) BIASSEC = '[1:32,1:2304]' / Bias section(s) FRMNAME = 'dhsFrame' / Name assigned to a frame of data. FRAMEID = '0 ' / Frame Id DATATYP = ' ' / Type of data frame WCSDIM = 2 LTV1 = 0.4375 LTV2 = 0.4375 LTM1_1 = 0.125 LTM2_2 = 0.125 WAT0_001= 'system=image' WAT1_001= 'wtype=tan axtype=ra' WAT2_001= 'wtype=tan axtype=dec' END <r7^Ņ߅ .8A; #],/kʅ<]yÆņȆˆΆ҆Ն؆چ߆ !#%())+.0149<=<;=AA: ?b\Ʌ>^z†ĆƆɆ̆Ά҆Ն؆ۆކ ##!#%&)+,+.12249>?@@ADE?#_Ä*><]zĆȆˆ͆φцԆ؆ۆކ !('&'()+./0256559?CDEEGIF 1~Nd:Zw†ƆˆΆІцӆֆچކ $))(*+,.02479;;:?BDGIIKMH F!O)VwÆņƆʆΆ҆Ԇֆچ݆ #&()**-1578::;<=@BDEGHJMNH N8 mĆ Gr†ņdžɆ̆Іӆ׆ۆކ "$')+++-158:;===>BDEFIKMPPJ T˄N')`Ćdžʆ͆Іӆֆۆ߆ "$'*,.//1369;=@BBCEFGILPSSSL Zلd؅@@tÆdžˆ͆φӆֆچ߆  "$'+.0256899;=@DEFHIJKMPTVUSN ^vU QņˆΆφцՆ؆݆ !$'+.0137:<<<;=ADFGJLMORTVWUTN  bfdž]Ædž̆φІӆ؆܆  !!#&),.02469;<;;?BDFHKMPTVXYYXVO f sӆ%eÆƆɆ̆φ҆׆ۆ !$%&')*,.02468;<;=BCEHKLPTVXZ\\]ZP  i|چ,iņɆˆ͆Іֆچކ !#&()*++,.0258;=>?ADEGKNPTWWY\]_`]S !kކ/jÆdž̆ΆІՆچ܆߆ !#%(*+,,-/1259;>@ABDFGJMQTWXY[]_aa_V !k/kÆņʆφцՆچ݆ކ  "$'*-.--/2469<>@@@CGHJMPTWXY[]^`ab`X !k 1l†ĆƆˆцԆ؆܆ކ !"#&)+./.0258;=>ABABEILNQTWXY[]^^`bcbZ !k!3n†ņdžˆцֆنۆކ !&&&()*.0/257;?@ADEEGJNPRUWXXZ]___acee] "k"4oĆɆ͆҆ֆنۆ߆ $*,++*,.0048:=@BEHIILPSTUWYXX\_``acegh_ "k"4oņʆφԆֆ؆ۆކ  &,..--./026:=@BDGJKMOSXYXYZYZ]`aabdgii_ #k"4qÆdž̆цԆ׆ن܆߆  %*.00000036:?DGIJLOPRV\][Z[[\_`bccehig_ #k#6t†ƆɆ͆цՆن܆ކ !$).122102359AHLMMPTUVY]]\\\]^`acddfhhfa #j#8uņɆˆΆ҆ֆچ݆߆ "%'*.12101346;CIPQPRVXZ\^^]]^_`bdeeeghhgd #k#7sƆʆ̆φӆֆن܆߆ "!!"$'*,-.0212446:?DIPRRSWY\^_____`acfiigghijf #k$5qƆɆ̆ІԆ׆ن܆߆ "#$&'*/10/145667:>AEIORTVWZ^`abba`abeillkklmmh #k&7tņȆ̆цԆ׆چ݆ #%&(+0210269999=@CFKOTXZZ]`bdfedcceilmmmnpqok #k';z†ĆȆ͆Іӆ׆چކ #%'),/00137:;<=?BEIMRX^aba`aeikjgfilmmlmpsrql #j'?}ÆƆʆφ҆Ն؆ۆ߆  #&)+...03569<>@ACGKQX`enpg`_cjonjilmlllmqssrn $j'@}Ædž̆цԆ׆چ݆!&*-///24579yĆɆΆ҆׆ۆކ #(,/13447;=?BEHKPUYZ\\]]\]_bfjmopomnqstuvyyr %m*=yņʆΆ҆؆܆ #(,/1346:=?BEILOSWXY[\\[[]`bfilsxvqqstuxz||u %m +=zņɆ͆ӆ׆ۆ !%)+.1579<>ADIMPRTVXZ[\\]]_acdfjs{ytqruw{~y %m ,>|ņʆφԆ׆ۆ  $')*-26:<>@DILPSTUWY[\\]__`cccejqvvsrtx{~~ &m .@~Ædž̆цԆ؆݆ #&()+/48;>@DHLORUVXYZ[\^_abccbchlpstrtw{} &m /AņʆφӆՆچ߆ !%()+.25:=@DHLNPSVXYYY[\_abddcbejnprstw{} &m 0Cdž̆цֆن݆  #&(*-147;?DILNPSTWYYYZ[\`ceggfgimopqsv{~ &m 0EȆ̆ц؆݆߆ !$''(),/36:=BINOORUVXYZ\]\]bfilmmnopqrsvz~ &m 0EɆΆӆنކ !'+--,,/369BDGILOQSVWXZ]acdegjlmoruvwz~ 'l1KƆφԆ׆ۆ  ')(*.114;BFKNPQSVWXYZ]`dggikmnopsttv| &k1KƆІԆ׆ۆ !""&+/26EGIJMSWWUTV[_`_`begilmloruwx{} &j3OʆԆچ #15/,.26:AFHGIMSVTTTX]a`^_beghjlnqsuwz|~ &j3N͆׆݆ =moG1159@DFHKMORTVY]_^`cfggimpt{ %j> _Ɔ؆ #'*.0368:<>ACEFILORTUY\^_behjklorv~ %i@ aȆن $(,/147:;@ABCCEINPRUWZ]`bceiosvyz|~ $i CfɆ܆ #(,/268:=ACCBBBBFLOOQUX[`cedcipvy|}} $h Egˆ݆  $(*.367:>CGHFCBDIMOPRUY^adghgkpuz} $i Fgˆކ "%')-2469CGIJKMPU]a]Z]_aeilpvȈ=ÇȇƂ %i …Kmφ %*/24556:=@CEHJKMPTWZYZ^abdhjnv+ԏˋUVLJˇǂ %i ÅLm҆  '.465568<@CEFHKLNQTVY[\_bdehkow݉k:6ƇLJ‚ %i ÅLnԆ  $*398668ADFINSZ`]YWWXX[^afjmpqrtw|ÇȇӇ݇ۇ҇Ȃ $h ąN!vۆ !&*-257:?CEHJMPUXXVUUVY[_cgknqrtwz‡Ƈ̇ч҇ЇƂ $i ŅO!wކ "%(,1358=BFJKKMQTVUUUWZ]aehknprvy|ÇLJʇχ҇Їł $i ŅO!w߆  $&)-1237CGIIIKMQUWWXZ\`efhlnprv{ÇLJʇ̇ЇӇӇ˂ %i ƅQ$y߆ !&)*+/37<@DGHHIKMQTVX[]^begkoqrux}ÇƇɇ̇χӇԇЂ %i DžS†&zކ "&(*,/39=@CFGHJLNPRTX\^`cehlprtx{‡ćƇʇ·чՇׇӂ %i ȅTĆ'{ "%'+.15;>@CEFHKNPQRTWY\_beilosvy}ćƇɇ·҇ԇևهԂ %i ɅTĆ(| !"%+036;>ACEFGKOPQSTTVZ^bgklouyz}ÇŇLJ̇҇ՇՇׇهՂ %h ȅTĆ(}  #&+036:>BCDEFJNPQSTTVZ^cimnqw{|~‡ćŇɇχՇ؇؇ڇ܇ق %h DžTņ(~ !%)-147:>ACDFHJMOQRSUX\`djnqvz}ÇŇȇ̇҇؇ۇ݇߇܂ %h DžUƆ)~ "',/269;>@BEIKLNPQRTX[_bfjoty|ćLJ̇чՇ؇݇ &h ȅUņ)~ $)-036:=?@CFILNORTTVZ]`cglqw{~ćɇχԇׇهއ &i ȅTņ)}  &*-147:=@DFGJMNPRUWZ]_`chmsxz~ćɇЇՇ؇܇ &i DžTņ*~  &*.147:=BGGHLOOPRTW[]^`dhnswx|ÇƇʇЇԇه߇ &h DžTņ*  %+/136:>DGHJOPPQRSVYY\aeimrvx{Ňȇ̇ЇՇ܇ &h ƅTƆ*  %+/026;?DFHLOPQRSTVWY]bfimrvxz}Ňʇχׇ҇އ  %g ƅTƆ+ !'+./38@CDGKNRWZ]`bejnqsuxz{}ćɇ͇Їԇهއ  %e…QÆ) "&,5:88:=@BDFJLOUZ\^acfjmprtuw{~‡Ƈʇ̇Їԇه߇   %eąSņ+ "%)0579;>BDFJLNQW[^`cehiknrsrtz‡LJɇ͇҇Շڇ  %fȅXɆ.  "$).37:<@BDHLNORVZ_bdehhjnqstv{ÇLJɇ·Ӈ؇އ  &g ΅aц2† !#&*.159<@CEINPRTVY^bdfhhjmoswy|ŇȇˇЇՇۇ   &g Յkۆ:Ɔ  $(+-0368=BEINPRTUY]`cgihikotwy}ćȇ·ԇ؇݇   &g܅vFʆ  %(*-1367;AEIMOQSUX[_cfhijkpuwy}‡ȇчׇڇއ   &hㅁP͆ !$'*.258:>DGILNORUWZ_begiklquwy|‡ʇчևهއ   'i녌XІ  #&*/259=BGJKMNORUX\`cegjknruwy|~ÇʇχӇ؇އ   'j󅘆`ӆ "&,0149?DHKLMNPSWZ]`cfhikosuwy{ćLJˇ҇ڇ  (ki؆ "(-136;AFJLNOPRUZafedfgilosuy{}ÇŇƇˇՇ݇  (ks܆ #).26:>CGJMOPRTYglfgjmoruy|ćŇȇχ؇߇   (i%{ #).49<@DGJLMNPT]ӈ{hfilmqtw{‡Ňʇ҇ه߇   &d-  %*069<@CEIJJLOS]/ׇihjlnrux}Ƈ̇҇ه #\셲4Æ !&-47:=@ADGHILPT[rˇwiiklnsw{LJ͇҇؇ !Sۅ9Ȇ  &/7:<>@ACEGINRVZ`mvqjgijlpty}‡ɇχӇڇ  LڄŅ=͆ !(19<=?@ACEGKOTXZ[^`bcehknrw|~ćˇчׇ܇ !Gʄ@҆ #)18;>??@DFHLPTXYZ]_`adhmqux{}}ҡ҇ه߇  #HÄCֆ !%*069<=?ADFILOSUWZ^abbehntwyz{}Ƈ͇ԇ܇  &L„F؆53!&,1478;>@BFJKMPSVZ^acdfjotwyz{~ȇЇׇ݇ )QDŽG؆/jd."'-3777:=?AEIIKNRW[]_aehlpsvxz|‡ʇЇׇއ  +V΄G؆ *\X-!$(.4877:=?AEGHKOSX[\^aeimpruxz}ćˇЇև݇   -ZքD׆')"$).1468;=@BDEIMPTXY[_bfjmoqtvz}LJׇ̇҇݇   /^܄Bֆ"%)-/269<>@BCFJMPTWY\adgjkmpruy~ćɇχӇׇ܇  0b…@Ն"&*-036:=?@ACGKNQUXZ^acfijlpruy}LJˇЇԇ؇݇ !! 0fх<ӆ  #&*.258<>@AADGKNQVZ\_acfhimpsvy}ŇȇˇЇՇڇއ && /k六9φ "$&+/36:>?@ACEHJMQVZ]_bdfgjmqtxz~Ňȇˇчׇ܇އ߇"+) .o6Ɇ  #$'+/37:=>?AEGIKLOUY\_bdehknqux{͇ЇƇ‡Ƈˇчׇ܇އ߇&,$ -q!0ņ "%(*-269<>?ACFIKMPUX[^cefhlorux|هۇɇćɇχև݇ %( +o") !%(),058<@@ABCFJNRVX[_bdehlnqtw|~ʇ̇Çćȇ·ԇۇ!"  )l"y !&(*,/48>CECABEINSWZ^accegjmqux{}‡Ňȇ̇Їׇ    'ks  &)*,/38@JLFBCGJNRV[bhheefhkoswz}ćƇɇ͇Շއ   &jk݆  &)*-047>JMEBEHJLQV\dllfcdgjlpuz~ÇŇLJ̇ևއ  &jb؆ $(+.1359ADAAFHILQV\affb`cfghmtyÇŇLJ͇Շ݇ &jYԆ !&+.2457:=>@DGJMQVZ^__^^beehmsy~ÇƇʇЇև܇  'kꅅPφ !&*/3457:?BFIMPQRUX[_abcglsz}ƇˇЇԇه܇݇ &jӅdՆ:Ɇ #&),/479;<=>ADGKMPSVXZ]`behlrx|ȇ·҇Շ؇ڇ܇  &i҅bԆ8Ȇ "%(*.2479:<=?BEHKOSVWY[^cfimsy}ˇՇۇ܇ۇڇ݇  &i҅bԆ7Ɇ "&(*-03568:=?AEHLORTWYZ]afkpuz}ɇׇ߇܇  &j҅bՆ9ˆ $')+-/2446:>?BEIMPQSWZ\^agnswz|~ćЇ܇އ   &jхbֆ;̆ !'))+-/0136:=?ADHMPQSXZ\_dipuxyz}ɇ҇ه܇݇  &jхaԆ;͆ (.,*,-...159;=?@FLQQTWZ\`ejouwy{~Ƈ̇҇ևه߇ &jЅ`ӆ:͆ "-40++,,+,059:<=?EKOQSW[_bfjotvx|Ňʇ·҇և߇ &iυ_҆9̆ %-1.*)*++,059:;=AFJMQTX^cfhjnsux{‡Ňʇ·чՇ߇  &iυ^҆8ʆ%(('&')+,-0478:>CGJNQUZ`dgiknqtvzćɇχчՇ߇ %iυ_ц6Ȇ!%$"!"%(+-/0357:?CGKNRW]acfhjmpruy}ɇ·чՇ݇ %hυ_ц5Ȇ! #&)-/0369=@BEIOTY^`cfghknquw{LJ̇χԇ܇ %g υ_І4Ȇ"$(+-037;>?@BHNTY]`cefgjlptvzŇʇ·Ӈۇ $g ΅_І4dž  "'*,/37;>>?BHMSX\_befgiknruyćȇ͇Ӈۇ   $g ΅^φ4dž  #&),/37;=>@DHMRVY]adgiijlptx}Çȇ͇ԇ݇   $g ͅ]φ4ņ !$&(,047;<>BEIMRVWZ_dgiijlnrv{‡Ƈׇ̇  $f ͅ]І5ņ !!#%(-048;=@CEHMQUWY^befhjkmqvzćʇև $f ͅ^ц6ņ !#%)-/27@ADGINRTUV[^_`beimqvz~؈/ $g ͅT*† $)-37:<>@BDEGLQTTVY\^adgilquzԈ   $g ʅO%  &+047:<>@ACEGJNQTUX[^bfgglqty}LJۇއه܇އ߇$ $g ʅQ( !',0358;=?@AEHJKPTVWZ]adegkosw{}ȇ͇чևڇ܇އ8: $g ̅U†, "(,.0258;=>AEIKMQSUWY]`cehlorvy{}ćȇ͇Շڇ܇އ?9 $g ΅Ydž- #(+,-0247:=BFIJMOQTWY]_aeiloqtvxzzyÇƇ̇ԇڇۇ܇އ %  $g҅]Ɇ- #'((+./148CHJMPORXZ[]_adgjkkkmrux{}~LJЇԇԇԇׇ؇ڇ܇߇߂ $fƅS%zކ !$&()*,159>DHIOSQQUWY\^`cehjkmptxz|}Ƈ͇ЇЇ҇ևׇه܇߇܂ $fŅS†&{ކ  &()*+.26;@DFHLONPRV[]^abcegjnswz{|}Ňʇ͇̇ЇӇԇׇڇއق $eŅS†&{߆  %()*,/38?CCDFHKNPS[ggbaa`beiouxz{{|‡LJˇ̇·Ї҇Շ؇܇ق $eŅS†%x݆  $'(),/39@BABDGKOQTe|yg`__`chpuxyzz}‡ȇ͇̇·чԇׇڇއ߇ڂ $eŅT†$x܆  %)''+/39=>?ACGKMNScywf_^^_ciosvwxzŇʇ̇·чԇ؇ۇ݇߇ۂ $eŅT†$yކ !),(',05<=<=@CGIIKPYcd_\\]_dkoruwwz‡Ƈʇ͇ЇՇه܇݇އڂ $fŅS${  )+''+.3:<::@BEFHJLMQTVX^beinprw}‡ȇˇˇʇˇ·ч˂ $g ɅXdž)~߆ !#$'+.0357;=>@CEFHILQSTX]behlosx}ŇLJȇʇ͇·χȂ #g ʅXƆ(} !$)-/0247:=>@BCEEGKOQTY^cgilpuz}‡ćLJ̇χЇχɂ #f ʅYƆ(~  %*-/1258;<>@ABCEHKNQUZ^dgjmrw{ÇLJˇ·Їч˂ "e ̅Ydž)߆ !&),/1369;<>??@BEHJMRVY]beiotw{~ÇLJʇ̇χч̂ "e ͅ[Ȇ*݆ "&),/1479;<==>@BEHJNSVX[_ciptw{~ÇƇɇ͇χʂ "e ΅\Ɇ*~ۆ #&),/1589;==<>@BDGKPUVWY]bjpsv|ҡ·Ȃ "f ΅]ʆ*}ن #&(+.1467;@@??ABDGLRWXYZ]binrv{桷Ȃ !e ΅\Ɇ*}؆  $'),0235;AC@?BDFINSWY[\^afkptx|ćɇˇł !e υ\Ȇ){؆"%'*-.16><=ADIPUX[\`aa`bdhkquvwxyz|‡‡  e ΅]ʆ*|׆ !$')-48:;;=ADGMSVY[^``abfilrvxxxwx{~  eυ]Ɇ){׆ "%(,14689BCDGKPRQQSUX[`cfilnpruy{zz|}~  fЅ]Ȇ'wӆ  #&)-39>ACEHKPSRPQRV[_bfijloqswxxz||}~  fЅ[Ɔ%w҆ "&*.4:>ABDEGLPPOPRVZ]aeggilnqstvxz{||~ fЅ[ņ$vцކ "&*/5;<>@ABDHKMNPTY[]adddfilopqsvxy{z| eЅ\Ɔ$uІކ  #&)-4889;>@BEIKLPY^\\_aabdgjnopruwyyyz} fЅ\Ɔ$tφ݆ !#%'+03568BFGFJPTUVX[_bdgiklmopruvxz{}  gυZĆ"r̆ۆ߆ "#$')+.1347:=ADEEHKORSUY^beijiikmnpruy{|}}  gυZĆ!rˆنކ !##$'(*,/1248ACDEGLPSW]`begggilnprstxz} fυYÆ odžԆچކ  #$&&&()+-/16:=?@ACGJMRY]^`bbbeimprsttux{}~ f΅Xmņцֆۆ #''&')+-/048;=>?CFGJQWYZ^`_`cglprsttuwz|} f΅XlÆІֆۆ߆  $%&')+-./369;<=ADEIOSTX^a``beimprsuwxyz} fͅWk†Іֆچ݆ !$&)+,-/3689:ADFJOWbiga^`dgjlnqvxxxz~ e̅UjΆӆՆن߆  "&)*+,05989;>@CEIP]msi_]`ceiloruvvxz e ʅSj†φӆֆچކ $(***.3789;>@CFIQ_rwi__abcgkostuvx{ e ɅQg†ІՆ؆چކ "'***-2579;=AEIMQZgkd`bbbbfinrsuwz| d ɅReφՆ׆چކ !$(*,034679?CGLRUX`ktupllmmnsxyyz|}~~~ eɅPdʆ҆؆ކ #).23348::;=@CGLQWdwunmlknsxyzz{|}~ eɅOdɆц׆܆ "(,/2224679<>ADHOWgxnkjknrvyyz{||~ e ȅPcȆІՆن݆ $'+/0/02489CLU_rzjfghjmquwxyyxz|}~ eɅOaɆφ҆ֆچކ "$&'')-2788:=BKSZalunedfgilortwyxwwy||}~ f˅Oadž͆цԆ׆ۆ߆  "#%%'+0468:=BHQXYZ_``bdfhjloqtwwwvxz{{|}~ iЅPbƆ̆φ҆Ն؆܆ !##%),/49<>ADKRSSUY\`bdgijlnqsuvuvyzz{{{|}y i҅RbƆʆ͆ІԆ׆ۆކ !#%&(,39=?ABFJKMPUY]`bfghiknpqrsuxyyyxy{zs hυRaņɆ̆Ά҆Նن܆߆  #$$$*29=?@BFGGIMQVZ^adeggilnmnpsuvwwvxzxp g˅P_†Ɔʆ̆φ҆ֆچ݆߆  "##$)08=?@CGIIJKNSX\`bcdfhkkjloqsuutvyyun  gɅN]ĆȆʆ͆ІԆ؆ۆ݆  "#%)/7=?ADGJKKKMQV[^`bdfiiiilopqssruxxtl  gDžL\ÆƆɆ̆φ҆ֆن܆ !$&(.5;@CEEGIJKLOTX[^adfhhhikmopppqsuusl f ÅH YĆȆ̆φӆֆ؆ۆ߆  $&(-39?BCCEHJKKNRUX[_bdeefgikmmlmprqrrk dAW†ƆʆΆӆֆ׆چ݆ "$&+17<>?BEGJJJLPSUY]`bbcdegjkjiloonooh b4SÆdž̆цԆֆن݆  "%*0599;@DFHIIJMPRUY\_`abceijhhkmlllmg `$J†ƆʆΆцԆ׆ۆ߆ "&+0357:>BDFGHIKNPRTWZ]^_adhhgikkjjjjh ]|:~†ƆȆˆφ҆Նن݆ #'+.0259?@BEGJLLLNQUXZ^dgeccdfggfea RӄgL QÆņȆ̆φцԆ؆ކ !$$&*,.0369;<>?AEHJKLMORVZ_dfda``cdefc\ KÄNŅ05jÆdžˆΆцӆ׆܆ !#"$)+,-0357:<>@CFGIKLMQTX\`a`_]]_acec\ C4tΆMuƆɆ͆Іӆֆۆކ  "&()*-02479?AABGJKLMLMOQQQTZ^_``Z \Ʉ=f7Yy†džɆ̆ΆцԆ؆چ܆ !$(+-/0368:=>?BFIJJJIJLOQQRV[\\\U < xޅ:7[{Ædžʆ͆І҆Ն؆ۆކ "%')+.1236:;ADFDCDHNTUTSTUWVN/ze̅V6ZyÆɆ̆Άцֆ؆چ݆  !"%')+.26778;>ABCBCFLTYYUSTVUN =߅!W6XwĆɆ̆ІԆֆن܆ކ !$&)-1455689;=??@BIS[ZTPQSSK F"V 3WxĆȆ͆ІԆ؆چۆ݆  $',/233466579:FMNLKKLMJ J#T 3WxÆɆΆ҆Ն׆ۆކ !%''(+-.///024446>FJKJIKNK J!S 2UsņʆΆ҆Նن݆ """%')*+,-.121028AGIHHLQP J S 0StĆʆІԆ׆ۆ߆  "$&'()*,.//.05>FGGHLRV J!߅Q߆1Vwdžφӆֆن݆  ""#%'(*,--./2;CFEGKQY K"ޅPކ 3Ww͆҆Ԇ׆چކ  "$')*+-//16<@CEINS L#ޅN߆ 2VwņΆ҆Ԇ׆چ܆݆ކ  "$'()-./025;@CFGE M#݅O߆ 2WyĆΆцԆ׆؆ن܆ކ  !"$'+,,-/28>@BCFILOQOJ &`Ȅ7*KiDžхمޅ߅߅߅ XTENSION= 'IMAGE ' / Image extension BITPIX = 16 / Bits per pixel NAXIS = 2 / Number of axes NAXIS1 = 132 / Axis length NAXIS2 = 288 / Axis length PCOUNT = 0 / No 'random' parameters GCOUNT = 1 / Only one group BSCALE = 1.000000E0 / REAL = TAPE*BSCALE + BZERO BZERO = 3.276800E4 / EXTNAME = 'SCI ' / Extension name EXTVER = 2 / Extension version INHERIT = F / Inherits global header ORIGIN = 'NOAO-IRAF FITS Image Kernel July 2003' / FITS file originator DATE = '2010-07-02T19:55:22' / Date FITS file was generated IRAF-TLM= '2010-07-02T19:59:26' / Time of last modification CTYPE1 = 'RA---TAN' / R.A. in tangent plane projection CRPIX1 = 65.7568549170406 / Ref pix of axis 1 CRVAL1 = 306.871725219222 / RA at Ref pix in decimal degrees CTYPE2 = 'DEC--TAN' / DEC. in tangent plane projection CRPIX2 = 143.564898774826 / Ref pix of axis 2 CRVAL2 = 37.3733845984976 / DEC at Ref pix in decimal degrees CD1_1 = -2.9278046959101E-4 / WCS matrix element 1 1 CD1_2 = 1.37000324401069E-4 / WCS matrix element 1 2 CD2_1 = 1.36969765153489E-4 / WCS matrix element 2 1 CD2_2 = 2.93069759666565E-4 / WCS matrix element 2 2 RADECSYS= 'FK5 ' / R.A./DEC. coordinate system reference EQUINOX = 2000. / Equinox of coordinate system MJD-OBS = 52162.6261539214 / MJD of start of obseration CCDNAME = 'EEV 9273-20-04' / CCD chip name(s) AMPNAME = 'EEV 9273-20-04, right' / Amplifier name(s) GAIN = 2.337 / Amplifier gain RDNOISE = 3.3 / Readout noise CCDSIZE = '[1:2048,1:4644]' / CCD chip size CCDSUM = '2 2 ' / CCD sum CCDSEC = '[1:2048,1:4608]' / CCD section(s) DETSEC = '[2049:4096,1:4608]' / Detector section(s) DATASEC = '[33:1056,1:2304]' / Data section(s) BIASSEC = '[1:32,1:2304]' / Bias section(s) FRMNAME = 'dhsFrame' / Name assigned to a frame of data. FRAMEID = '1 ' / Frame Id DATATYP = ' ' / Type of data frame WCSDIM = 2 LTV1 = 0.4375 LTV2 = 0.4375 LTM1_1 = 0.125 LTM2_2 = 0.125 WAT0_001= 'system=image' WAT1_001= 'wtype=tan axtype=ra' WAT2_001= 'wtype=tan axtype=dec' END wybiƅDžDžʅЅ؅߅ׅυŅ}ywxywuuwwutvwurdy{pŅ…………ąƅȅɅ˅ͅ΅ЅӅՅ؅܅݅ۅۅۅۅۅۅممڅ܅݅݅݅ۅՅυʅDžDžȅʅ˅̅ͅυЅЅЅх҅҅Ѕ΅ͅͅͅ˅ʅɅȅDžƅŅąÅÅz|{؅܅߅  ߅߅݅ۅڅمׅօՅԅӅхυ̅˅ʅʅʅɅDžDžɅʅʅDžz|ȅ  !  ""#%()&#!  ߂z|Ն !#(*(&'('')+13.*)*,---.-,,,,+++*+--.142012.*)+,.24321/..//.-+((*)('&%$" z|܆  #$#$$&*,--.-,,-4EL=1-.022343221/---.0457:<:8::633468<==;:86775444101000/.-+)('%%$!  z| !"#%'''''')+.10//./9R[E3/024467776410012479;>?=;<=:89:;>ABA@><<<:87876443443110/.-+*'%$"!z| "%&')*+++*)(*-0//0/07GL>3113568:;:9644567889==>?@CFFDCBAA?=;::987679975543110-*)(&$#!z| !&)++,,----+)*,../00049:6333468:<<<;:99:<<:99<@CB?=?@@@BDFIIGFEDCA?>=<;:98:>?=;:85453/,,.-)&#!!!!"""!  z|  !$)-...../0/.,---./012355555579:<>??ABA>?@?<;;>ACCAABCBBDGIJJJIGFDCBA@?>=;;<:8862.043.*'$$#$&%$$""##"#$#"""!z|  #$$%',//0122243100/./23345678889:;<>ABEINLFCB@???ACEDDEGGEDFILKKKJIGFFEEDCC@>>>@DFDA?><:8425:71-+)''()''&%&)(''('&%$#"z|  "&())+.012356799763224677779;<<===<=@DGJNSQLHEDDCCDGIHHJKKIIJLNNMMLKJJIHHHHECBAACGHEDCB?<977;>:3/.,++++)))*,-+*+,+)(''&"z| #&)*+,-0245689;8679:;<<<>@@AAA@?@CGJLNQROLJIIGGHJLMMOPPNNNOPQQQONMLKJJKJGFEDEGIJIHGDB?===>>;631/.//-,+,/0/--//.-++,+&z|""$'+-...03689::;>BBB@=:;<>?@@ACDDDDDDCCFILNOQRQPPONLKKLOQRSTUSSRRRTUUTROMLKLMLJHGGHJLOOMHEDCCC@>=<:64223210/133101210/..00*z|!%&(,/023347:<<===>ACCCA@??ABCDFFGHGHIHGGILOPRSTSSUUTQPPQSTTUWXWWUUUVWXXWSPMLMONLKJJLNRYWPJFFHGEB?>?=:7676653356666665431143. z|$(*,0356788:=>???@@ACEFFFDCCDEGIJKKKLLKJKMOQRTUVWWXZYVTTUVVWXYYYYXXXYZ[[YWSPNOPPONNNOQX`]SMJJKJFCAAA?=<<<;::989;;;:9998754550%z|'+-035899:;=@AAABCCCFGIIIFDEGIKLMNNMOPNNOQQRSUWYZZ[\\ZYYYYZ[[\[\\\[[[[[ZYXVSQQRTTRQPQSW\ZTQNNOMIFEDCBA@BB@@@???@@?<;;;:976652&z|*/13579::;=?ACDEEEEFIKJIHGGHJLMNOOOPQSSRSTSTUWY[\]^^^^]\\]]^^^^___^]]\[[ZYWUUVW\]YTSTTUUTSRPPPOMJHHGEDDFGFEEDDDEEB@??=<;:8773(z|.3567:<<==>@BEGHHGGJLMKHHIKLLMNPPPPRSTUVVVUVXZ[]_`aabb`^^_``_``abb`_]]]]][XVXZ]bd_YWWVTSSSRPOOOPNLKKHGHKMLKIIIIIHFDDCB?><<;96,z|3679:=?@@??ADFIJJIJLNOMJILNOONOQRQRSTTWXXXWXZ\]_bccdedb``abbaaabccb_^^_`_][Z[^`bda]\[XTQSSRQPOQRPNNMKKMOPONNNMLLKIHGGEB@??=;80z|" 7::;???@BCCCCDEGHIKOPPQTTRQSTSRSTUVWXXXWWY[\ZZ[^aceghhgfdcdeeeedeedca````bbcddeggffdb`_^[XWVWVVWWVTRSSSTVXWUTTSPPOOOPPNKIGECA@>3z|%>CDDDDDDDDEFGHHJMQRRTVWVUUUTUUUVXYZZZYY\^^\[]_bdegjjihgeefghgfffdcbaaabceggfhjkjjgdca_^^][ZXYZZYXWVWWXYZZXWVTQQQPQSTTROLIEDDB8z|&AEFGGGGHGFGHIJKMORTVXYYYXWWWWWVWY[[\\[]_aa`_`beggilmllkigghiihhhffeccddehjjikmoomjgfcbbbb`^\\\\\[ZZ[[[[\[ZYWVUTSRSU[a`XPKGGGE>z|(BEFHIIJKJIIJKMNOPRVZ\[ZZ[[ZZYYXX[\\]^^_`abbcdfhjkklmnopmkiijjjkkjigffghikmmnprsrokjgeddeeda_____^^^__^^^][ZXWXWVUUYdro_SMJIIICz|*AEGHIJMOMLLKLNPQQSX\^]\]^^]\\[ZZ\^^^`abbcdefhjlnnnmopqrqnlkkjknonkjijjkmopqsuvvsoljhffffgfbabbbabbccbba`_^\ZZZYXWW[hvraUOMKLMFz|,AEGIJMPQPNMMNPQRSVZ^``__``^]^]]]]_``bdeefgikmnoqrrssrrrrponmlnqrqnlllmoqrrtuwxxtqmjhhhhhigdccddeghhfedaa`^]]]\[YXX[bhf\UQOOQQJz|-BFHILNPRRPPPPRSTVY\`cbaba_^^__^^^`bbdffghjlopqqstvxxvttsqpppqstsrpnooprssuvwyzyvsoljihijkjgeefhjlmkigdaa`]\___\YXZ[\]]ZVTSTVVOz|-DGHJLNPRSSSRSUVWY\^beeddb``a`````bcdfhiklmorsstuwx{{xvvtsrqsvxwusrqrrsttuwxyzzywuqnkjijmnljihjloqpnlhecaa_^_`a_\\]\[Z[[YWWXYYQz|.GIIKLNRTUUUTUWY[\^adfeeedcddccbbbdefhknppqtuvwxxyz{{zxwvutsvyzywvvvuuvvvvwy{||{yvromklnqqnmmmnruusrolifecba`abb``_]\\\\[ZZ\]]Sz|/IKKLMORTVWVVWZ\]^`bdeefffffeffeddffhkrxyvvxyz{{zz{|}|zxwwwxxz|{zzzyxwyyxvvz}~~|yurpnoqsttrqqrsvyywuromkifdcbcddcba`_`__]\]_dg]z|1IKKMOQSUVWWYZ\^_`bccdefgiigfghgffghjox|z}}}~~}~~|zzz{{{|~}|{zz||{xx|}zvrmlqvwwwvuvvxz{{zxtrpnlifdefggedccccba```bksjz|1HKLOQTVWXXY[]_abddccdhiikkihiiiiijlnsz~}}~}~~}|}}{}}|vnmtyz{{zyzz{}}}|{wtrqpmjhiiihgfeeedddccbdmvlz|2JNOQSVXZ[[\]`bdefeccgjlmmmmmllmmllnrw{|}~~yxz|~}}~~~|yvuutqnnnlkkjiiihgghgfeflpez|3NRRRTWY\]^^_befffeefhjnqqpppppqpooqty}|}}{yyywtssrqqponnmlkllkjijmmaz|4"RUTSUXZ\_`abdgghhhhhikpttsrrrstsqsuw{~~}|||zxwwwzzvttsqpoooomklmk^z|6%UXWWXZ\^acdefghjllkjjlrvvutttuuuuvx{~}{zy|{yxvtrrqqqommlh^z|8'X[[[]_`aceggfgjmoonmmotwvvuuuuvwxy{~~||~}|zwusttsrqonlh^z|9'X^^_accdeghhhiloqrrqqruwvvvvvvwyz{}{wuuvwusqpnlgXz|:(Y_abdfgghhijjkmoruvuttuwvwwwxz{||~{wvvxywtrpmkfOz|:)[acehkkjjjjjjlnpsvwvuuvwwyz{}~}zyyzxvtronmiWz|;+]cehkoolkkklmnprtvuuuuwyz{}}|||yvtqooolbz|=-_dgjnsspmmnopqrsuvuuuvxz|}~}{wsppppofz|>/`egkpturpqrrsttuvxwvwxy{~~|wtrrsrofz|@1bfilqsssssstuvwwxyyxyz{|}zwvvutpez|A3dikmpqqrsstvxz{{zzyyz{|~†}|{yxvrfz|B4fjlnopprstuwy{}}||{{|~~~}zujz|D6glnprqqsuwxxz|~~~~}wmz|G8hmqstsstwzzz{~zpz|H9iortuttvy||{|}~}qz|H:jpsvwwwwy{||||~~pz|Ipuwy{{{{{|}~}jz|L@rwxz{{{}~~~{kQz|NCty{||||~oY=z|PEv{~~~~mY<̂z|RHx}nV8ƅpz|SJ|̆҆~jQ5e8 z|TL~Æ܆̆p[LIP[fv}gJ*䅿`.τz|VO††φԆņtR/2Li|eG#Յ[+ńlDz|YRÆÆÆĆĆĆÆ††††††ÆÆ†ÆÆzX0؅Յ;_yv^A˅sFe@!z|ZT†ņƆdždždžƆƆƆņņņĆĆĆĆņƆƆņÆ†ÆÆÆ}]5ՅrNBJ`}ȅ75;I`}ńz|b^†ĆņņĆÆÆÆĆdžɆɆˆ͆ІӆՆ׆׆ֆԆӆԆԆԆԆԆӆ҆ц҆ӆӆ҆цІІ҆ӆ҆цˆWޅTτ^1 䃻fB+-B_@_oodWOKNWg~Ą<`wz|daƆÆĆņƆdžƆƆƆdžʆ̆͆φ҆Ԇֆن܆܆نֆֆ׆׆׆׆׆ֆԆՆՆՆՆԆԆӆՆ׆׆Ն҆Æf#ۅ<鄙O؃w^E,#5Oy7Q\]_es„:fӅz|ebņɆȆņƆÆņƆdžɆʆɆɆ̆φІ҆Ԇֆ؆چ݆ކ݆چنچۆۆۆۆۆن؆نننن؆؆؆چ܆܆چӆ<셗;܄}!σ[;.**$*Q#IcwƄ6^݅7Dz|fcĆʆ͆̆ɆdžĆÆÆĆdžɆʆ̆Ά͆ΆцԆՆֆ؆ۆ݆߆߆݆܆݆ކކކ߆߆ކކކކ݆݆܆݆ކކކӆnX\ $"!;r%[ 6`օ#BZm{}z|geÆɆ͆φІΆˆȆƆdžʆ̆ΆцӆӆԆ؆ننۆ݆ӆ_(9V܂ȂĂԂ),-+%9qCԅRׅ?\uz|hg†ņȆˆφӆӆцΆ̆͆ΆІ҆Ն׆؆ۆ݆ކ߆ֆW􅄅 !܂Ȃ "-32-$*H̄t̅'}Å>[sz}ih†ĆņƆdžˆІӆՆԆӆ҆ӆԆֆ؆نۆކ܆Z􅁅Ђڂ)13/''7[G sՆ%Wtz}jhĆņdžȆɆˆІԆֆ׆׆ֆ׆نچۆ݆ކ熺iԂς *-+&&=joڅEdz}kiÆĆƆȆʆˆ͆ІՆ؆نچچچ݆߆߆Ն%957Ƃ&)'+G̈́,q؆6~z}ml†ĆƆdžʆ̆͆φцԆ׆نۆކކ߆ 􆲆O߅eee˂؂ (5>KmZ&@z}nmÆƆdždžɆ̆ΆφцԆֆ׆؆ۆ߆  ֆs"ۂ‚‚ւ,Hax:FDz}mm†ĆņdžɆˆ̆̆͆φцӆՆ׆نۆ܆ (>ȄN˃MЂǂɂԂ=fЃC΅n Mz}moĆƆȆɆˆ͆Іццц҆Ն׆؆ن܆߆   #ņVt) -Z9\~ۅ`&_ÆÆz}pq†ƆɆʆ̆ΆІӆՆԆԆֆ؆چۆ݆   (#DτX僈PAOlÃ+[҄CwM{ĆdžƆ†z}rrĆɆˆ̆ΆІӆֆ؆؆نچۆ܆߆   !+0\&[ ׃ƃЃ@rׅ,Qs߆0V{ÆȆʆdžĆz}rtÆņĆņȆˆ͆φцԆ؆ۆ܆݆ކކކ  !$,2"솝E慇-ۄm^czʄ-^օ/Jc{ņʆˆˆɆƆƆz}svĆƆdžɆ̆͆φӆ׆نۆ߆ #&&%$%&&&&%%%%%%$" !#%&'*.)܆?텡]'/X7Umdž̆ΆΆ͆ˆɆȆņÆz}uyÆdžɆʆ͆φІӆ׆ۆ݆߆  ! !##$),,--.///.--,+***)''')***+/3.؆P܅:bʆцӆ҆҆ԆՆԆӆ҆φ̆ˆȆņĆÆz}v{†Ɔʆ̆ΆцӆՆ؆ކ !$&(''(**+,*+034677667766410/00///100005=?/ ކ{S8,&!(@`ц݆߆܆ۆن؆׆Ԇцφ͆ʆdžņÆz}vz††Ædžˆ͆цՆ؆ۆ߆ !$'*,/11124565349>?@@?>=>?@@=9657766788767;AB;+ֆֆކ܆چ؆Ն҆цΆ̆ʆdžÆz}vy†ÆĆņƆʆ͆φӆنކ #%),/2469:<<=>?>=<>DIKLKIGFGIJIFC@??>==>?@@?@CDB=6-"ކۆ؆ֆԆцІΆ͆Ɇņ†z}vyÆĆĆņȆˆ͆Іӆ؆݆ #'*.37;=>@CDGHHGGFFGJNRUVVUSQRSSQOMKJHEEFFEFHIJKHC@<83-&"  ݆ۆنՆӆӆ҆φˆȆƆÆz}x|†ĆņƆȆˆΆцԆ؆܆ "!"'-159=ADEFHLOQQOMNOQSWZ\_`aba_^^\ZXVTSQOPQONOQRRQMIFC@;730.,& ߆܆؆׆׆ՆцΆˆdžÆz}|ÆƆȆʆ͆φ҆Ն׆ۆ߆ "$()(+18<@DILNMMPTXYXUSUX[_dghjklmllkigda_^]\[[[YYZ[ZXWSPMKHC>9531+# ߆ۆچنֆ҆φ̆ȆņÆz}ÆņȆˆφ҆Ԇ׆ن܆ކ $*,-.04:?CHNUXXWWY[_aa^\\`ejnrtvxxwwwurqpmllkifedcdeeca_[WUSNHC>854/(" ߆݆چ׆ԆІ̆ɆȆdžĆz}ƆɆ͆ІӆՆ؆ۆކ "*/246:>AEHMW]`abbbcgijkkjkosv{}{{{z|~|uomklnoomjgc_]YSNHB<861+'" ߆݆چֆцΆ̆ˆɆņz}ÆɆΆ҆Նֆ؆ۆ߆ $+26:=@DGJMQW^adgjllnqqsy}|zzz|xttvxxxvsokgd_ZUOIB<950+&"  ݆نԆцφ͆ʆdžz}ņ̆цֆنچ݆  &-8>@BFINQRV\addfkorvy{{{xuokga\WQIB>;50+'%" ߆ۆ׆Ԇ҆ІΆʆz}ȆφՆن݆߆ !'-5@HJLPTX[]`eijkmqux~}xurjb\WQKFA;61-+(&! ކۆ؆ֆԆ҆Ά‚z}ˆ҆ֆ܆ #(+/5;CLQU[`dgikorstvz|~ukc^ZWQIA=9531-'" ކ܆نֆՆ҆Ȃz}…ΆԆ؆ކ &/469?DLSY`hmrvxxz}~‡·‡yphda\SJEA=;83-($ ܆ن׆ֆ̂z}ÅІ׆܆ #*2:>@CJRZaelsy‡LJƇƇчه̇pje]TNIEB>93.)# ߆܆چ׆΂z}ąՆۆ &/7?DGKPW_gnrw}ćЇׇ݇݇χʇ͇Ӈ҇χ҇և̇ʇˇɇɇɇƇLJ׈4?҇smg`WQMJE?:4.(" ݆نЂz}ƅن߆ &/9AHMQW]cjqx}Ƈ̇χ·ʇȇ͇Շ؇߇ ݇҇·Їч͇̇ˇŇƇч؇ڇهևևׇׇԇчχχ·ˇŇɈBKyc{tqk`YURMG@93-(# ߆܆҂z}ƅ܆%/7@GOV]dintzÇׇ̇'&҇Їڇ߇ևʇÇćˇ҇ه߇߇ڇчƇÇ׈Xs{|ztjc^ZTMF?93-(# ߆Ԃz}Dž݆ &08@GOWbjpw~ȇӇ߇0/'%'#ׇهۇ݇ۇчԈ{|tmhb[TMF@93-'  ӂz}Džކ %/7?GPYdow}Ň̇ԇ߇ .AQZ^K)):;8:=>3'B5  هڇć|vrjb[TNF>82+% ӂz}Dž߆ $.6=EP]it~χۇ߇߇BeֈdKELQUY_c\G53>JJDHS@   ۇ҇ɇ{tkc\TLD>70*" Ղz}Ʌ !-7>EN]n}Çч߇ Bp։"q͊2_ӈi`glq~{icaZWbwY1   ܇χ}skd[RKD<6/& قz}Ʌ*5?FLWgy·݇#3:04ZƈX܊.Fψow}spbP9   ܇ŇzskcZSKC<4,%! z}ʅ '2>HNT]j{χ /Rbhlsx|ԉF+|gوxMY׈ڈڈш#w>!*,#)'؇~wnd[RJB:3,)'" z}̅ %/:FO[hqsżއ.Ga~LjBljKӈr>JΈ&K`XHCN_fW3[:/,,7:& #/1)҇wnd\TKC;51,'! z}̅#-7CNWcvч %FdĈ̈ۈ=zۉʉ6ۈZw-BGEE_܊߉T{I;=?:, 060#чvng_UKB<72,&z}ͅ *4>KV^i}ׇ&CdˈوΈȈ̈وHwWوщ'g}r~!q$߉͉ ^(҈]TF4)  .1* ӇÇzsi_TJC=61+# z}΅‡ &3>FR^fnӇ*Eb}ψ߈ԈˈĈĈۈ11ƈӉ,̉}<"芛Q -:$򉱉k!ӈwX9*%$.,$ۇχʇƇ~sg]SKC<6/'! z}ЅLJ"-;GOWcluχ ,AYm|шΈɈ܈ވΈՉuΊ0- 77{QӊK2@VGa)戦sK1(%!!,51&"$ ݇ˇ}qg]SKD;2*$ z}хˇ )4BOV\gr~Շ):GWgqԈՈEщ,*!,OxGE8T[&ωv;创jF0(%#,96)$+,! ӇŇ{qf[RJ@6.'  z}Ӆχ &2>LX`gq|և '05BYp͈шˉKɉ;qċh8ߊ\U>͉2∦vO4%#/1,1<;/*'Շȇɇ̇ˇŇzodYPF;2+$z}Ӆ҇+8GWdlu͇ *NzՈ݈ɈʈB׉1fڋ-siN퉸p-󈻈P/ &/@OMFD=/͇݇̇Ӈׇԇɇyl`UKB80)! z}ԅՇ$1>Pesz‡އ $Jwڈ و҈'_|rr։Dyދ*cwNJ7ωN!vL2!".CSRQUK:+҇·ׇևȇtg\RI@7.&! z}օه#4BVm{҇ !! *Gi͈҈҈؈߈ۈ׈ 1EGH^DhJn􊉊S/Ή?׈|^C1,2@JIKOF92#ۇчه҇ć~pe[QG>4,(%z}؅܇4EWjyȇ$10'*;PkȈ͈ɈȈψшΈ[iamy}s]LB?ETp.GIRQ<]ibF݉( шqQC@@BCA>4-2- هއχÇyodYND:2-)#z}څĆ'9IXixׇ0L\[Yaq҈݈߈݈3}v[$ É݊SGtmt8hzNE!*ՈwbQB?C>4(#.3؇̇wj_ULA7/*$z}څƆ%2?M\m}̇'KvĈ &9N[mYŠŊwF?FLOYaZK0`يފ4DҊNJL)2*"Ȉz_GBE>6.(,2#އՇ̇~od\TI>3+' z}څƆ)6CP_p؇ "=fՈ؈ĈɈHpЊ=^H=VpS\fLIhm$N3'VagTA$爪fPLICDG@76+ ܇ՇʇwkbZRF90+$ z}څƆ,:FRasˇ&&'4Qyڈ B܉܉؉ ҉ԉ5.'z}څdž1?HTdvه)-+3EaĈA4  ̉ϊ_9Ќbы;Dec)͊}9@5]JcW/xN6׈xiehr{u_J2݇χ~qf\OC90) z}ۅȆ4BKWg|̇ ...?Wr܈KNr:"É͊cԋS*׏X3֌Ӌ_B_e@$^0!m'ӉcS>̈oP- ##! ׇȇznbTH<2*!z}ۅɆ6EO\nه&/3MXfx҇!+B_t(Xz 'ߊ 1976Fo5ߍ؎C'7j<ËYD̊cmFp=Ԋ슟;։ՉQ6=)툸xvvfQ>5 E,!抵fo V̉ъՉtPSJ؈zcE;BC/чʇLJ|l^QE8,z}߅ц@P]l‡"5Qfov{ՉAcN-) RxFʍ+oώЍ׍[ˋD势s@%ӊnɉȊ6ɉzmc>\>@D-؇͇͇ȇscUG9. z}ޅц@O\nɇ#9Qi~# Չĉ݉#! +eŠ̊\4 ]"~\ѓRď`Z\T97B>O#銄+މԊ$DɉpX#ማn_nmME;߇߇܇هˇyhYK=1 z}߅ԆAN[ȯ&&z}؇J\m߇(hщS҉tVٜݏpZJBdЊĊy|`ωN ͈XFLK(ۇ ·reWG2z}؇I[lEV}{pgX;8dO #nیQ'a^2H‘2̫2O;D(̌ƌXc#ъ⊳r)74􉵉ljω^㈤hMYgD҇vhXG4z}هL^oHMhg\LA=<9:EQ_tuknĊ fNtc5 ˙NN.K~UƵ]bOLы^#Њҋ 芴^=R8쉴 ߉}%\[d<߇އևxgUE2z~ڇM_oهE2SU@$$JbeanҊk (L?aWy _7p:ߑHdWŋZߊʊ&*Z3+xv<;׈mN?ڇև‡xeRC1z~هK[k҇EӉ 6@%6NSF8@RWYg~,iԊ!%5ZȌL'4]a Ѻ5.L3Y)o9Ïj= ɋCϊ݋;FŊ`kъ]׈sE' ׇćuaOA1z~ׇGVf|͇C7C?609JX]j:mʊ*=9@qDϛ0 l@}1jd5Y⌊ݍ+{GH͊MƉԊ<劔vÈoI.36'ևÇq\M@0z~ՇCSdyʇ@xɈ݈݈؈݈ %43.'3RbY[;k,UIC+t2şjWvLm-,ƭ2:ΎӍ<@印_ `Z-g{XHs􈪈oWNK8.DYVE5(ԇlYLA.z}ՆBRcwLJ߇8b|ψ*3+%$4PZOS/^ȋNE8W΍@񛺝9Ʀuǵ UݷX<,;dJ ׎tŊRce"ʉ&8, ʉV׈~unxseiiZF=1Ӈ~hVMC.z}Ԇ@Qbu‡ׇ&=DQf|78&+;EEUJ{38+HVǐ̖מנMħ( CgǓVˎ}ԋ!.~҉ 'rhmvd?),+ ӇuaRKA-z}ӆ=N_r·և߇(Lt߉$;8 *39@[ފ 1jĊf@ : X?ަ$鮜sBW!xϒ)+Ŋnˊ:׉Ɋ Љ҉ ۉhꈈWS]paЇjZPK@+z~߅ц:JZnćʇԇHtш42%6:7;ZӉ ]NJ+ދzțȞWϡ졀}5t'ېT Ίt?Vtω֊܉뉟dJKTlڈ` ˇzfZRK@.z~߅І7FVjÇ̇܇Dh| &+0BID=PÉ"eŊъڊ9_Je=2KlͣN'b֗ !񊌊k ՉkӉΉn툉[QTZlڈS Ƈvh`WMA/z~ޅΆ4CSf{ч;Td|Έ(!!-=OTKLm%pҊ݊ tښb Ξ&H斟+ALE ->ԋ%kMϊJ ≥h\ۉOڈgaeinrwq?$ ܇ulcYMA.z}݅̆1AQcv؇ ':L\sÈ$!'>TWQ^Ί[|jUmÊȊ>ԝ(u1;M^k^%N0U‹2`Ut8 쉡haljˆmntrmcUMB1(&҇xodXLA1z}܅Ȇ.?O`qׇ5AFRau-ITR]Š6F0'PӋb唳):󚳚[t旦[Ԛ vl鐓Xw[\W^gx.:A@Dgˉ(c֊ Vk!Ϗԓϖ VSMȔL DŘP󎢍ˌ ފ؊ŊvhmX1󉘉.Èy`rxT)ЇćwiYMB0z}ۅƆ*7BQdv҇/MVTW[iԈ 1:>;>aމB}wj۔uɓJ|̔i Ȓ͎vŒL;Y}w7ىu#Ȉ{{[% ݇̇{obUJ@-z}مÆ&2=K^n{̇:HMMKTo +..1;Xډ+'ˊ}r܋*݌m{Џ]Б$xєh D id.pU;x{ QшtmruM݇ʇrcXOG<+z}؅".8EVeqLJއ*:BB=DZ{ш'3Qt׊c҉҉"[vꋂDm3:@ߋ+8c)ꊜK ߉ƉЉЉnЈ2%,Xz݊K*tOSjrbB߇ʇ{pke_ZVQME:)z}Յև!%)/9ER_l{· 9IJCES`ilk.*&5Pi~3 # 0RreljV ';>;AIVwi.(Y#Έbzk>؇‡qiga\XURMD8&z}Յԇ#*5AO\huՇ&42)+@YjpjqЉ!$/Fiʊ?ߊɊeb%P{k쉬R#2$:#‹>C?vCAQ숎Ȉb/ ˇqkgb[WTQKA4z}ԅӇ )3>JVam{ȇ.Pgne`x&;]zJ܊Ԋ>틈4"A_@lZZ8ЉpJ9',CGYfيۊȋW#}nbщY鈎ɈM" އχ{snic]VRNG=0z}ԅ҇(09CMWbp~ч;Xc]T^ !0E`ijxA􊽊?#׋s8+;'ꊭnȉgv^]-F0쉏)|w\8ЇysplcZRNH@7,z}ӅЇ $+3;DNYguևDZVLKdމ$((;HHXyˉ2{ՊԊvьЋ}Y_}r+؊ɊΊXʼnΉىHC }|zG g,:؈bTQI<*Їwtrk^RLGA91(z}҅̇$,4=GSan{ɇ݇ 4QQH@Hf-'%,=hߊ(OȊЊ͋YB0L~Y NJ?鉸ˉȉ:ۈˆ͉*3ՈiL<51,!|vtpfXMGC=6/$z}хʇ &.7AMYerՇ$݉ƉÉtX=%܈ƈ}z[A5+ }N vi`ZTNJFA8-!z}Ѕ† ")0:DLWgx͇܇#/2$3Ojۈ @lϊW|s=܉։aC)ˈ~rv}rbJ1$ ևƇqe[TOKGC=3(z}υ #+6?GP^l|‡Ӈ%( 4Nbrֈ܈ڈ߈J͊8A"쉺ĉ߉ˉ]*׈ԈֈӈĈxou}xyug]YQ@*  Ƈwk`UMHEA<6,$z}΅ (29AJUcpȇ؇-DRZf~ȈLjĈΈ 9v؉։vs׉ӉÉb$Ԉ̈ˆuggy~}pXF=9. Їwnf[OGB>:4.&z}ͅ %-3;CLYesˇڇ  &=KMN_yψ%Rt}vfRK`jH܈Ljˆticfu}vlfW>)χxohaWLC<73-'! z}ͅ "(.4;DOZfw͇هއ %:A?GZm|҈ڈ$8<:5''CbtseTB&܈Ljyoga_[XUQJ@1 ߇هχ{umd]UK@71-'"z}̅ #(-3HR`p|LJ̇χЇ̇LJ·އڇ·!3>J`{xlmĈɈ̈Έňy`SJ@<=7& ڇՇӇч̇ȇćunie`\XSMF<2)  z}˅ #(08?DPakvȇهۇӇۇ #4BVgkdYUav{\F>80+%ՇЇчЇ͇Ƈrf_[YUQLF?6-$ z}Ʌ !*39=GS]iwʇԇׇԇև 1HVWQHEMZfo}{|uY?0+& ܇ۇۇՇЇ·͇ɇ‡zl`YVUQLGA:2)! ܂z}ȅ $+39AJT^juŇ͇͇̇̇чۇ-=B?:9<@K^xzlmoh^Z[]abZK9)#܇؇ԇӇ҇ч·ɇƇƇŇ|zwoe]XTQLGB;3,%܂z}Dž #)19BKT^iu‡ÇćŇ͇ևه؇݇*010-&,B[f\TXXOE><;974." ؇χȇƇȇˇʇƇ}vroke`[VQJD?:3,&  ۂz}Dž !)08@IS^is|ȇχ҇Їчڇ &'  #'*3>?5,))'# ! އԇ̇ćÇŇÇzuolgb^ZTOIC=61*$ ւz}Dž "(.6@KT]fov}ćƇɇʇȇ·ׇڇ݇   ؇чʇÇ~{vpkgb]XRKEA<5.(# ӂz}ƅކ "(0;DJQZbipx~Çʇˇɇч܇ڇׇчʇć~~}{unic\VQJC>83-'! ҂z}Ņۆ $,5<@HOW^emtx{~̇ۇ܇؇ۇއӇLJʇχ͇·ччӇׇهևч̇Ňzz||xrkd\TNGC>80+&  ߆҂z}Ņ؆݆ '.38@GLS[binps{͇ՇևևڇهӇЇ҇؇ڇՇ͇ćÇƇŇÇ{xwvtojc[SLE?=91)$  ߆тz}ŅՆچچ݆ !&*18>BHOW]adipw}ćɇʇ̇̇Ƈȇ··Ƈ{vsqokgb^YSLE?;82*" ކςz}Ņ҆ֆ׆چކ߆ $+05:?EMSVZ_cfktLJŇ~|xqligea[VSPKE@<83+$ ܆΂z}ąΆӆֆچ܆݆#',26962-&  ۆ͂z}Å̆҆ֆ؆چ݆ $*/5;@CFHHJP[ht~wvxxvslgc^ZVTROKC;50.*& ߆چ΂z}̆ӆՆՆ׆ۆކ߆߆ $).37:<>@@CLXep{~wtrqnkfa\VRONLJE>6/*'$ ߆݆؆˂z}ʆ҆ӆ҆Ԇ؆ۆ܆݆݆܆݆ #&*.137;;81+%! ߆݆ۆֆɂz}džΆΆΆцԆ׆چچننۆކ !%(,1678=DLU^gmqtuvxzzz|~zupje`[XUOJHHEA>;61+%! ݆ۆ؆ӆȂz}ņɆɆˆΆ҆Ն׆ֆՆֆچކ !&+/159>BHPY`eikmopopqrsw{~~|||||{{zvpkgc_XSOKHFEC>:63.(#  ݆چ׆ՆІĂz}†ņdžˆ͆І҆ӆ҆҆Ն؆܆  $',159<@FNTY]abdefgfefjmosxywxzzy{{yvutsqqpqplfa^\XQKGDBBA<72.+&! ߆ۆ׆Ԇ҆͆z}Ćdžʆ̆ΆφφφцԆֆچކ #'+.27:>CHLRVWY\__\Z\^afklmortrpooonljhfeedc`\XVTPJE@==>;60+(# ݆نՆцΆɆz}ÆƆȆʆˆ̆͆φцӆՆ؆܆ކ  #%'+/259=AFJLOSVVTSSVartiehkkifdccba`^\[ZYWUQNMKGC>:99961,($ ߆܆׆ӆΆˆƆz}†ĆņdžȆɆ̆І҆ӆՆ؆ۆ܆ކ  "%(+-/37;>AEILLLLMSgl_``_]\ZYYYXWUSSRPOMIFCA>;855431-(%! ߆܆نՆц͆ɆĆz}†ÆÆņņdžˆІ҆ӆՆنچۆۆކ  #%(+.036:?BDDDFM^z|dWVUSQPPPQRQOMMLJHFEB?;87520/.,*'#  ކ܆چ׆ԆІ̆ȆÆz}†ÆĆƆʆ͆ІӆՆ׆؆؆چ݆ !#%'*-059::;=BJWZSNMMLHGHHIJJHGEDA?>=;85210-*))%"  ܆چچ؆Նӆφ̆ɆÆz}ÆÆÆƆʆ͆ц҆ӆՆֆ؆܆ކ߆  !$'+.01248>DHHGGHGDBA@ABBA?=;9875420-,+(%$$  ݆ن؆׆ՆӆцΆˆȆÆz}†Æ†ĆȆˆΆІц҆ӆՆنۆۆ݆߆  !$')+-27;?AABBA?>=;::99860,./.--+)'$"  ކچ׆ՆԆӆцΆˆȆņz}}††ĆȆˆ̆ΆφІІӆֆ؆نچ݆ !$&).259::;;9998642220-$#''''%"  ݆ۆ؆ՆӆцІΆˆdžņ†z}zĆȆʆ̆͆͆ΆΆІ҆Ն׆چ܆݆݆݆ކ !$(,.1321122110.,,+)(!"""! ۆ؆ֆӆцІΆˆȆņ†z}uyÆņȆˆ̆ʆʆˆ̆φ҆Ն׆؆چچچۆކ !%'(**))**)**)''%$$! چֆӆ҆І͆ˆɆdžÆz}ru†ĆƆdžƆdžȆʆ͆ц҆҆Ԇֆ׆׆ن܆݆ކ  !"#####$$#"  ݆نֆ҆φ͆ʆɆȆņ†z}sv†ÆĆņƆȆ͆φΆΆцӆԆՆ؆چۆކ  ߆݆݆݆ۆن׆ԆІ͆ˆɆdžņÆz}ux†ÆĆdžˆ͆̆͆φІ҆Ԇֆֆن݆߆  ݆چن؆ֆԆӆ҆φ̆ˆȆņ†z}uy†ņȆɆʆ̆ΆφцӆӆԆ׆چ܆ކ    ߆ۆ؆ֆԆ҆цІφ͆̆ʆdžÆz}ux†Æņdžʆ̆ΆφІцԆֆنچچچۆ݆ކ߆߆߆  ކ܆ن׆ԆцІφΆ̆ˆˆɆņz}ux†ÆƆɆˆ͆ΆІ҆Ԇ׆؆׆ֆ׆؆نچۆ݆߆ ݆چ؆ֆԆцΆ͆͆̆ʆɆɆdžĆz}uw†ĆƆȆʆ̆͆ΆІӆՆՆՆՆԆՆֆ؆چۆ݆߆߆چֆԆ҆цφ̆̆ˆɆȆdždžƆÆz}suÆĆƆɆʆʆˆ̆ΆІ҆ӆӆӆԆԆӆԆ׆چ܆ކ߆ކކ݆ۆ׆ӆІΆΆΆ̆ˆɆƆņņƆƆ†z}rs†ĆdžȆȆȆɆʆ̆φІІцццІцӆֆچ݆߆߆݆ۆن׆ӆІΆ̆̆̆ˆɆdžĆ†ÆÆÆz}qs†ÆĆƆdždžȆɆˆˆˆ͆ΆΆΆφ҆Ԇ׆ۆކ߆߆߆݆چ׆Ն҆φ͆ʆʆʆȆƆĆÆ††z}pr†ņņņņƆdždžȆˆˆ̆͆φцӆֆن܆ކކކ߆߆ކކ݆ۆ؆ՆӆцφˆȆȆȆņ†ÆÆÆ†z}npÆÆ††ÆÆņdžȆȆʆˆ͆ΆцԆ؆چ܆܆܆ކކކކ݆݆݆݆ކކ݆܆ۆنՆ҆цφ͆ɆdžƆņƆz}ln†ÆņƆƆȆɆʆ͆І҆ֆنچچۆ܆݆ކ߆ކ܆ۆۆچچۆۆچۆކ݆ۆچچن؆ՆцΆ͆ˆȆĆÆ††z}kkÆÆÆņƆdžɆ̆φІԆ׆ننچچچۆކ߆ކ݆݆݆܆چنننننننچۆ݆݆݆ۆ؆׆ֆֆ׆Նφ̆̆ʆdž†z}ii†Æņdžʆ͆φІӆՆֆ׆؆نچۆ܆݆ކކ݆݆ކ߆ކ݆ۆچچن؆ֆֆ؆ن؆׆نۆ܆܆ۆۆن׆Ԇ҆҆ӆц͆̆ˆɆƆ†z}ig†ÆņȆˆ͆φІц҆ԆԆՆ؆چچچچچچچۆ܆݆߆ކ߆ކކ߆߆܆ن؆׆ֆԆՆ׆׆ֆֆ؆ۆچچن׆ֆԆ҆φΆΆ͆ˆʆɆȆņz}gf†ÆdžɆʆˆΆІІІцІцԆֆֆ׆ֆֆ׆׆؆ن܆߆݆ۆ܆݆ކ߆߆ކކ݆چنچކ܆؆ֆԆӆӆԆՆՆԆՆ׆؆؆؆ֆ҆цІφ̆ʆɆȆdžƆņÆz}fdÆņdžȆȆʆ̆ΆφΆ͆̆͆φцц҆҆ԆֆֆՆֆن݆݆ن؆نچچۆ܆܆ۆۆۆۆنֆՆ׆ކنֆԆ҆цц҆҆ӆӆԆՆֆֆՆ҆φΆ͆ˆɆȆdžņĆƆz}fdÆĆĆņƆdžɆˆ̆̆̆ʆɆˆ͆͆͆͆ΆцՆՆԆՆ׆׆׆ֆֆֆֆֆֆֆ׆׆׆׆ֆՆՆӆԆچ݆نՆӆ҆ІІцццц҆ӆӆԆԆ҆φ͆ˆɆdžƆƆņÆÆ†z}fdņ†ĆȆȆɆʆʆʆɆdždžɆʆʆʆɆˆΆІІ҆ԆՆԆӆԆԆԆӆ҆҆҆ԆԆԆ҆҆ӆӆц҆ԆՆ҆ІІφΆІцццц҆҆ццІφ͆ˆȆdžņƆ†z}dbĆȆφˆɆɆɆɆdžƆņƆdždžȆȆɆɆʆˆΆцццц҆ццІІІІццццццІφІІφΆΆ͆̆͆φІφφІцІφ͆ˆˆˆȆņņņ†z}b`ˆц̆ȆdžȆȆƆņĆĆĆņdždždždždžɆ̆͆ΆΆΆ͆͆ΆφφΆφΆΆІӆ҆ІΆΆ͆̆ˆˆˆˆ̆͆Ά͆͆͆Άφφ͆ʆȆȆdžņ††z|`]†Ȇ̆ɆƆņĆņņņĆĆĆĆņņņņdžɆˆˆˆˆʆʆˆ͆φΆΆ͆ˆˆΆццΆ͆͆ˆʆʆʆʆˆ͆Ά͆͆͆͆͆͆͆ˆɆȆƆÆz|_[ÆņƆƆ†ÆÆ†ÆĆĆĆĆĆĆƆȆɆʆʆɆȆȆɆˆ͆͆̆ˆɆɆˆ͆͆ˆˆ̆ˆˆʆʆʆ̆͆̆̆͆Ά͆ˆʆɆȆȆdžƆz|]YƆ†ÆÆĆĆĆĆƆdžȆɆɆɆȆdždžȆȆȆȆȆdždžɆʆɆdždžɆʆˆʆʆ̆͆̆ˆ̆Ά͆ˆʆɆȆdžņĆƆz|[VÆÆĆņƆƆƆƆƆƆdžņĆņĆ†ÆÆÆņdždžņĆĆņƆȆɆʆ̆̆ˆˆ̆͆ˆɆɆȆdžņ†z|ZT†ÆĆïÆ†ÆÆ†††ņņ††Æņdžʆˆʆˆ̆̆ʆȆƆƆņƆz|ZT†ÆƆȆȆɆˆ̆ˆɆdžņĆÆz|[T†ņƆƆȆɆɆȆȆƆņƆz}[SÆņņƆƆņņņĆÆÆz}ZPÆĆĆÆ††z}YM}††z}UJz~Ć}z|PEuz~Ć҆Նʆyz|L@pw{}}Ć/,Æzz|I/`filnquxzz|~{qz|>._egilosvwxz}}zoz|=-^cehjmrttuwyz{|~}znz|<,]ceghknpqsttuwy{}~}~~||{{zoz|;+\bdfghjmopppruwxyyxyz{}~|zyxwwpz|;+\aceeegjklllnqtvutuvwx{}~~~}zyxvtsmz|<-]`bdccdegghhikoqpqsuuvz|~~~~|{ywvtrpgz|=,\`bbaaaacdeeffikloqrruy|~}zxxwvtrqnbz|<+\_``_^^_abcdedegjmnnptx{}~~~}}~~}zvututrpok`z|;)Y\]]]\\]_`bcdddehjklnquz|}~~}|}}|}|zvtsrrqpnmi^z|9&UYYZZYZ\]_`acccdfhiklnquxz}}{zyz}~{z{|{{yurqpopomlkg[z|7$SWWVVVWY[]^^`abcdfgiklnorvxxwwwwz{|~~{xwxxxwuronmmmljjieZz|5!PTTTTTUXZ\\\^`abccdfiiiknqrrtvwwwwxz}~~~~~~~~{xvuttsrpnmlkkigghhdXz|1MQRRSSTWY[[[]^_`abbcddegiknoqtvvvuvvy|~}~~~~~~~~~}|}}|{|}|{yvtsrqomlkkjihfdeffbWz|/KPPQRSTWXZ[[\\\]`aaaa`acdgklmpstsrstvx{||}~~~}|{z||zz|||}~~}}}}}}~~~}||~|zxxxwxwvsqpoljihhhggededc_Tz|.JOOPQRSUWYZZZZ[\^```_^^_`cgiijnoooprtuvwy{}|zzzzyywuwz||}}{yxyz{|}~~||}~~}}||{{{{{|}~}|||{zzxwvvutuvuronliggffffedeeda\Pz|0KNNNOQRSUXXXXZ[\]^__^]\\\`deefhjklmorstuwyyvtuuuutsrsuvxyz{zyxxxz~|zz{}}}}{zyyyxxxxxy|~}{{||ywutsstsrstspmkhfffededcdddb`\Oz|2KNMMMOQQSUUUVY[\]^]]][ZZZ\^_`bdefhjknprtwwvspoonoppopqqrtwyzywuux~|yxxyyyxwuuvwwuuvvxz{{{||zwutrqqqpoopomkhfeedbbbabbba`^[Pz|0IMLKMOQQRSRSUWY[^^[XXXXXXXYZ\]_``dghjmqsttspmkihilmllnnnoruutttuw}zwwvvuutrqrtvustuuvwxy{|zwutsrponlkklljhfedca__`aa_^^][XNz|-FJJILOPQRQQRTVWYZ[XUUUUUUUVVXZ]]^acegkoqppomlkheeghhikllmopoopstvx{}yuuvvutrpopprttssttttvwyxvutrponmkihhiigeddc`^]^`a`]\\YVTIz|*CGGHJKMOQPQRSSTTUUTTUUSQRTVVVXZ[\_abeilmllklopkeccdefhijlmmlmnqrrsssrqrtsrqpnnnnoqrssssrrsvwusuurmjjigeeggfeba`_^]]^`_][ZXVSODz|(?DFGHHIKOQRRQQPPPQQRTTRPQTUUVVVWY\^_aeghhhgm|vgccccdfghjkkklmopponnmmnoonlllmlkklnqrrqrrsttsrstoigffcbcddcb_\[[\\\]][XVUTSPK@z|% ;ADFGGFHLPQPPOMMMMMOPPPPQQSTTTTTVXZ\]`abbbck|hbbbbceffffghjkmlkjjjjjkkjhfgiiiiiilnoopqqrqponnnjeccca`aa`_^[XVWZZZ[ZVSRQPOLH=z|" 8>BDEDCFJNNMMMLLLKJJJLMNNNOQRQQSTVXZZZ[\]]]bqzoda_^`bddccccegiigfgggggggedefedegghjkllnoponlkihgd`^_``__^][YVTTUVVVWTQOONMLIE;z| 6;>?@ABEHIIJJKLKJJHGHIIJJKMNOOPQSTVWWWXXXXYZ^a`_^\\_bdcaabcdffeefffedccb`bild`bddeghijlmljihfdca^[[\]__][YWTRSSRRRRROMMMLKIFB6z|49:;<>@CDDEFGHJIHHIHHGFEGIKMNOPPQRSRRTTUUVWWXXYZZZ\_cgeaabdeecbcddcb`^]]\^gjb^_``bdfghjigeccb`_\[YXX[]][XURPQRRPONNNMKJJJHEC?2z|16779;>???ACDFFEEGGGGFEEFHIKMOOOOOONNPQRUWWWVUUVWY\^dmkb_`cdc`__`__][YYXXY]^]]]]]`bdeefeca_^]\ZXYXWVXYXVSQOOQQOMMKJKMKHHGDB@=1z|,33468:;;=?@ACCBCDDDEEDFFGGIKMNNNMMLLLMORUVWUSSTVZ\]bmka]]_a`^]\[ZYXVVUVVWWXZ[\\]_`aaaba`^\[ZXVUVVTTUUSQONOQQNKKJHGHKJGFC@?>;0z|(.023568:;<<>@??@A@BCCDFFFGHJKLLLLMLKJJKMPSUUTTTW\]Z[ab]ZZ\]\[ZYWUTSRRRSTVVVWXY[\]^^^^]]\[YXVTSRRPOQRRPNLNPPOKIHGECCEEDB@>>=8/z|%*-/01357899:;;;<=>@ABDDDFHHIJKKKLMKIHGGHKPSTTSTW[YTTXYWVVXYXVUTSRPPQPOOQTTSTUWYZZ[[[ZXWVVVTQOOOMKKMNNNMLMMLIFDB@>;;=?>=<;::6.z|#(*+,-/0234667667:<=?ABCCEGGGIJIIJJIGFDDEGLPQQPQSSQNOQRQQRSTRQONMNNOOMLLOPQQQQTVVVVVVUTRQPONMLKJIGGHIJKJIGC?:41.,)),02100//0.&z|#%&&&'(*,.011113579:<=>?ACCCDFEEEDCB@>>@CGKLMLLLKJKKKLLLMNNMLKIHIKLKJJKLLLLMOQRQONLKKJIHGEDDB@??><;;;:73-#   z| "#$%')**,.//036:977898898653457;?ABCDDEFGFEEFFGGFFGFCBBDDCCEEEECCDEDA=:730.-,+)'%# ܅υƅ…ą…ƅʅĂz|˅    %+/246:>AA?>=<;:98777642110010/.,*(" ۅօх̅ȅƅ…~oc\XSLFCBCIRWVTTUX[Xz|w؅υ҅҅҅҅҅Ӆԅօ؅ۅ݅ޅ$+1442.*&" ߅Ѕytuvqib\VPLGA;6/$݄؄Ԅ΄Ƅ˄Єфτ΄Є҄Մтz|iy………ÅąŅŅƅDžʅ̅ͅЅׅ ׅυȅwfRB81) ބք΄Ƅ~m\MEB>6.)&%'.7;;98:?D@z{YGmnmllnopqsuwz|}}ɅЅօڅۅօυƅtg\PE<4.*&! ل„}naWRRSQG<3,%  σz{Kn>@?>>@BABDFHLNNNPSUVXYYY[\\]_^\[YWUTSSTW\dlu}|rj`SC0 Մʄ{lX?.&؃σ˃˃˃ƃyqeVG8,&$  !)'XTENSION= 'IMAGE ' / Image extension BITPIX = 16 / Bits per pixel NAXIS = 2 / Number of axes NAXIS1 = 132 / Axis length NAXIS2 = 288 / Axis length PCOUNT = 0 / No 'random' parameters GCOUNT = 1 / Only one group BSCALE = 1.000000E0 / REAL = TAPE*BSCALE + BZERO BZERO = 3.276800E4 / EXTNAME = 'SCI ' / Extension name EXTVER = 3 / Extension version INHERIT = F / Inherits global header ORIGIN = 'NOAO-IRAF FITS Image Kernel July 2003' / FITS file originator DATE = '2010-07-02T19:55:23' / Date FITS file was generated IRAF-TLM= '2010-07-02T19:59:26' / Time of last modification CTYPE1 = 'RA---TAN' / R.A. in tangent plane projection CRPIX1 = -66.6459346493144 / Ref pix of axis 1 CRVAL1 = 306.871725219222 / RA at Ref pix in decimal degrees CTYPE2 = 'DEC--TAN' / DEC. in tangent plane projection CRPIX2 = 143.15396209091 / Ref pix of axis 2 CRVAL2 = 37.3733845984976 / DEC at Ref pix in decimal degrees CD1_1 = -2.9402995676385E-4 / WCS matrix element 1 1 CD1_2 = 1.36706049992071E-4 / WCS matrix element 1 2 CD2_1 = 1.37399803289694E-4 / WCS matrix element 2 1 CD2_2 = 2.93132453649777E-4 / WCS matrix element 2 2 RADECSYS= 'FK5 ' / R.A./DEC. coordinate system reference EQUINOX = 2000. / Equinox of coordinate system MJD-OBS = 52162.6261539214 / MJD of start of obseration CCDNAME = 'EEV 9273-20-03' / CCD chip name(s) AMPNAME = 'EEV 9273-20-03, left' / Amplifier name(s) GAIN = 2.3 / Amplifier gain RDNOISE = 3.0 / Readout noise CCDSIZE = '[1:2048,1:4644]' / CCD chip size CCDSUM = '2 2 ' / CCD sum CCDSEC = '[1:2048,1:4608]' / CCD section(s) DETSEC = '[4097:6144,1:4608]' / Detector section(s) DATASEC = '[1:1024,1:2304]' / Data section(s) BIASSEC = '[1025:1056,1:2304]' / Bias section(s) FRMNAME = 'dhsFrame' / Name assigned to a frame of data. FRAMEID = '2 ' / Frame Id DATATYP = ' ' / Type of data frame WCSDIM = 2 LTV1 = 0.4375 LTV2 = 0.4375 LTM1_1 = 0.125 LTM2_2 = 0.125 WAT0_001= 'system=image' WAT1_001= 'wtype=tan axtype=ra' WAT2_001= 'wtype=tan axtype=dec' END q|wvusolkkiededa^[[[YUU\b^UOKD8)ȃiG"ׂ` ā{xuoeWF0݃wR+ւVǁԄބ܄ڄل؄ׄՄф΄̈́̄ʄƄĄÄ„xeM1Ѓ]3قXɁۄׄ؄ل؄քՄ҄Є̈́ʄDŽńĄ}aC$ރb6 ۂYɁ ߄ۄلׄքԄф΄̄Ʉ„lN. 惽d8 ۂYɁ'*&" ބ܄لքԄӄτƄrT3烾e8 ڂY ʁ,.*'%#! ݄ۄلׄԄτȄwW4郿e7 ق[ ˁ./+*('&# ބڄׄՄ҄ʄxX6郾e7 ۂ] ʁ!00-,,+*'#  ݄ۄڄ؄Ԅ̈́ÄyY7ꃿd7 ܂[ ʁ!2310/0.)%#  ߄ބ݄ڄՄτĄzZ8ꃾe8 ܂Z ʁ$4654320,(%#  ߄ۄ؄фĄ{[8郿e8 ۂZ ˁ'7987642.+(&$"  ބڄ҄Ä{[7ꃿe8 ڂ[ ˁ(9<::9641-+)'%#! ߄ۄфÄ{[7郾e7 ڂ\ ˁ*;>>=;8630.-+(&$#"!  لфĄzZ7郾d6 ڂ] ́,=@@?=:84210.,)(&%#! ݄؄фÄzZ7郿d7 ۂ]́/?CB@><964320/-+)'$"! ߄܄؄Є„yY7g9 ܂_΁2CGEBA?<:86541/.,(%$#  ݄؄ЄĄyY7g: ܂_΁7HKIFEC@><987420-)'&%"  ܄ׄфĄxY8h: ۂ_ρ<:9641-+*)'$"  ބۄׄЄ„xZ8g9 ۂaρ@NQPONLIDA><:852/.,*)&$! ބڄՄ̈́zZ7g9 ܂a΁?NRTRPRPJDA><:9631.,*&""!  ܄؄ӄ̄yZ7f9 ۂ_́?PUWUTXXOGC@><;9630-+$ "#"!  ߄ۄׄӄ̄yY6郾a2҂W ȁATYZXWXWPIEB@><:7431.&!$&%$"!  ߄܄؄ӄ˄wX3 ݃}L낼EFX\[ZYWUPKHEB?><86651)#'*)&$$#  ߄܄ׄфʄnF胷T$łd)遷K\_]\ZXUQNKHEB@>;9962-)+.-*('%#!  ݄؄ӄ̄m@߃Oe7́N]__]\ZWSPMKHDB@=<:6310021.,+(&$#" ܄Ԅ˄vO#ǃk=܂|Q(ҁR_aaa^\YVSPMKHECA>;755335420.+(&%%" ܄ӄĄfE ̓tI삺Y.Vceeda^\YUQOMKHFD@=;976665420-*)('$  ؄ʄhI'ヽkA삼W)݁Zikieb`^ZVRPOMKIFB??=;;:86531/-+)'$  ܄˄gH'ჿvP(ׂ}LЁ_ppkfcb`]YUSQONKHDBB@??=;86431/,)&$" ބτcE$݃qL&؂a5 āeuslgeedb]YURQPMJHFEEC@>=;8642/,(%%$! τa@كiDт]7Ёfutokihhd`[XUSRPMKJJIFB@?=;9641.+('&$! ҄~]<Ӄb<ƂzT/ ҁfuurnkjhda^ZWTSQPONMLHDB@?@?;741-)()'# ф}\9σ\4 傽nI%΁Ł́ссāfuvtqnkgda_[WTSSSSQOMJGDBEMMD;50,)((% ЄyX5ǃ}V-܂e?ʁŁԁ灺euxvsplhec`\YVVWWVTSPLHEDM^`N=4.+)(%  ΄rQ/ 僾rK$ӂZ5ځǁǁׁ&5@GH: ȁewzxuroljgb]ZZZ[ZXWVRNIFFO^aN<3/.+&̈́mJ'ރg@ȂwO)ԁāȁׁ1Kcvp+ԁgy|zwusqole`_^^][YXWSOKHHKPPF:42.' DŽhE Ճ^5 傼lE ЁÁɁׁ1LgȂӂׂՂʂHށi{}|zxwvtnifdba_][YVSOMJIHGE?82,!Ąb>̓}U+ق_:΁Łāʁׁ0Khق ς_䁦l{~~}|zyvqmkhedb`\YWTQNKJHE@8/#„[7ÃsJ ͂{S. ܁ρʁ΁؁/Kgۂ0GXac^P6p遧o~~}{yvsplhfec_[YWSOKIF?4%ބyV0 ⃺jAnH$ځҁҁځ-Ieڂ3Qm] {끨r~~{uokhgda^]ZTNHA7'܄tO)ۃ^6䂶b<ہׁ܁0Kdۂ4QnÃ؃ڃŃy쁨ryrmjhd`^]XPF9(քmG!ӃT)ՂX1߁*Gkڂ6TqɃ'-)僽$큨szrmjgc_[VM>*Ԅe>ǃuJȂtN* (D`Ȃ7Ut̓!;SenhX>ă%tyqljfaYN?+Є_6僼h>炻hB!&A^}ڂEbyЃ 'A[srM"ƃ$큩uxqmh_SA)̈́X0܃]1ڂ\9&@\z؂8Wwԃ+Gb{ȄɄzP#ƃ#쁩wtkbVC+ DŽ{R(ԃ|P$͂yS2&?Zxׂ7Wwփ/Lf˄Մڄ݄݄ׄĄ}R$ƃ"쁩yqcS@' „tK ɃrE낿nK. $#ᄻkA샿e8 ߂dD+([vƄۄ  ߄ʄX*Ƀ"|聧fiW;̈́}Oe6ۂpZLIO]r͂4Wyރ @`˄  ߄ʄX+˃$}聨91ƄqG냸X*ӂq_WXcv͂3Ux"Aaӄ #" ̄Y,̓&~遨ㄿi;烸Oʂvieky˂5Xz&Ffք#(*++*'#  ΄[.΃)遨a4փPǂ}vwɂ 0V{ă&Hi„ۄ(.01110/,*'$  Є^/΃(遨>&̃l@ʂʂ /Sw -MmȄ &.3678754331/-,(# ф_0̓$|聨Ճc7̂˂ -Qv -Pq΄#-5;>>===<:875310/-)%  ҄_0̓!z聨lS/ тς*Ot -QtԄ,7>CEGGEB@??@><96300.+(%! ӄ_0̓!z聨قʂɂق +Mr -Quׄ$4AIMNNNNMKHECBBBA>96320.*'%! ׄ`0̃ y灨ނւӂւ0Ru .Rvڄ(:ITZ\[XVTRQPNKIGFEEB>:8520.+(%! ބ_0ʃx灨؂1Sw 1Uxބ/APZaeffd`][XUSQONLJHGFC?<9620.-*'# ᄸ^/ʃ"|聨2Rwà 3Z5JZdkopomkjfba_[WUSRQOMKIGDA>;62/.-,)&! ݄_0˃)ꁩKsƒ7[~Ʉ 7L^ltwyyywtpnkhfea]ZXVTTROLJHFDA<730/.-+'# ل`1̓(ꁩ9`˄ *BSbox~}zwspnkjhd`][XWWUQMJIHEA=9620//,($  لb3Ѓ#z灩*\ӄ.G]oz|yvsqomjfb`^\ZYVSOLJIEA>;7410/-($! ڄc4҃!w恩΄7Ocu~{xurqnkgdba_[XVTQMKIEB>;8520.+'$" ۄc4҃!v恩3Sk~{ywtrolifeb^[XVTQNLJHD@<9531.*&$"  ۄc4҃ u偨Wz|{yvspnljhc^[YWTROLKJGB=9632/+(&$!  ۄd5҃ u偨}{ywtrpqokf`^\XUSPMLKGA=:8530,)(%#"!  ݄d5҃t䁨~{xvusstrmhdb_YVTQPOKFB?<:730-+)'%#!  ݄f6Ӄ t䁨|ywvtssqligfa[WUSQOKFDA=:730.,*)&$" ބf7Ӄ!u䁨~{yxusroljhfb]YVTQNJGEA>:730/-+*'%" ބh9Ӄ!u䁨~{zwuspmigec_\XTPMJGDA=:731/-+)'%! j:ԃ!t䁨~|{xuqmifeca^ZUPMKGCA>;9520.,)(%! „k:փ sと}yvrnjfdca^[WROKGCB?><941/,)(%! l; ׃ rと}yurplhdb`][YUQLGECA@>:630-*'$"  m= ׃rと}yusqnkgda][ZVRMIGDB@=:751.*&$"! m? ׃rと…~ywusqnieb_\ZUPMKIFC@=:853/+'$!  „n?؃q⁨DžÅ|{zwtpkheb]YTPNMKHEB>;8651+(%"  ńp@كpၨɅŅ…}}{wqmjgb^ZURQOMJGD@=9761,)'$  ȄrAڃoၧȅƅÅ|{xsokfa][WTROMKIFB>;972-+'#  ʄsBۃoDžDžą…|zwtplfa_\YUROLKJHD@<:61.+&"! ̄uD܃oʅ˅Dž…{zvsplfb`_[WSPMLKIF@<951.*&$! ΄uDۃo̅υʅÅ~|yvsokfca`\XUROMKIE@<963.*'%" ΄vEۃnͅυ˅ƅÅ}zwtpmieca]YWTQNKHC@=;83.+)&"  ΄wG܃nͅͅʅȅƅą}{yvrpmifc`]ZUQNJFB?><83/-+&$" ΄yH݃n̅̅ͅ˅ɅƅÅ~|{wtrnkhfc`\WSNIEA?>;732/+'%#  τyGރn̅ЅЅ΅˅ɅŅ~{xusoljgeb\WSOIFCA>;7430,(%#"  ЄyGރm҅҅ͅЅ΅˅ȅŅą…~|xvspnkheb]WRNKIFC?<8530,)'&$!҄yH߃mЅӅӅ҅хЅͅ˅ȅŅÅÅ}yvsqnlhe`\WROMJGD@=952/-+*(%! ӄzI߃l߁ą҅҅҅ӅӅԅ҅΅Ʌƅą…zusqnlhaZYXTPMJGDA>:61..,*(%! ӄzI߃k߁ŅӅԅӅԅօׅԅ΅ɅƅŅ…~zvtqokf[RUWTPKHGEA>;71..-*'$"҄zIރkށŅօ؅օօ؅مՅ΅ʅȅŅÅzwurokdWOTURNJHGD@=;9520-*'%! ҄zH߃jށƅم܅څڅڅمՅυ̅ʅDžą|yurokbVSVTPMKIGC@>=;851.*(%! ӄ{H߃jށͅ߅݅܅܅مօх΅˅DžŅ{wsojb[ZYUQNLKHDBA@>:51.,)%! Ԅ|I߃jށԅޅ݅ۅمׅԅЅ̅ȅƅÅ}xsojfb^[WTQNLHECBA?;620-)&" Մ|I߃kށم݅ۅمׅՅӅυ˅ȅŅ~xrnjhd`]YVTRNJGFCA?;741-)&" Մ}Jjށ܅݅م؅օӅυ˅ɅƅÅ|vqmjgca^[XXWSOLHDA?<840,)%!քLボj݁݅߅ۅمօхͅ˅ʅȅą~yuqmifdb_\ZZZWSOIEB@<840,)$ քM䃝i݁ޅ߅܅څՅх΅̅ʅɅƅÅ~yvsnheca_][ZZXTPKGDB>951-($! ׄN僝h݁߅߅܅مՅ҅Ѕ΅̅Ʌȅą}{xsnidb`_^\ZZXUPLHEC?:62.*&$  ؄P僞h܁߅߅ۅ؅Յ҅хυͅʅDžÅ~{wsokeb`_`_^\YUQMIEB?:62/+(&! لP僝g܁݅ۅ؅օԅхυͅʅƅ…|xtplgdbabca^ZVROKGC>:62.+)&" ڄQ䃜f܁߅݅مօԅ҅υ̅ɅŅ…~yuplhfdcccb_[WSPNJD>:51.+(%! ۄR䃛eہ߅ۅօԅ҅ЅͅɅƅązupmjgfdccb_[XTPNKF@;61-+'$! ܄Q䃜dہ܅ׅԅӅхͅʅȅŅÅ~ytqomigecba_[WTPNLGB=82.+'$! ܄Q僝dځۅׅՅԅ҅Ѕͅ˅ȅą…|xtssqmiebaa^ZWTRPMIC?940,(%! ۄP惞eہڅׅׅօԅԅ҅υ̅Džą…}ywuusokgdba^[WUTRPJD?:62.*%! ݄Q烞eہۅممׅׅօԅ҅΅ʅDžƅÅ|yxvsoljhea_\XVTSPIC>;841-'! ߄S烝dځޅ܅څمم؅ԅ҅Ѕͅ˅ȅÅ}zvsolkieb_\YVSQMFA>;842.(# T 胞cځ݅ۅۅ܅څօ҅хυͅɅÅ|wspmkhdba^[WSOJEA?;842.*&# U!郟cځ݅܅݅ޅ܅؅Յ҅ЅͅȅÅ}yurnjgedca]XSOJEB>;741/+'$ ᄶT!ꃠcځ߅݅܅څօӅхͅɅƅ…~{xuplheedb]XTPKFB>:8530,'# ㄷU!ꃟcځ܅ۅڅօӅхЅ΅ʅą~{ywtpkgdc`[VSQLGC?<:852-'# 愻V!郟cځ߅݅܅څօӅ҅҅Ӆ΅Dž~zwwwunhdb^ZVSPKFC@?=:62.*&"  넿Y"ꃠcځޅ݅ۅ؅ԅ҅ӅՅхɅ~zwuutmgca^ZVSOIECA?=:62.,($""" „[$샢cځ߅ޅ݅مԅӅӅӅυʅÅ{wsqnieb`]YVTOHDCA>;:61.+'%##% ]&cځޅ݅څօՅӅυ˅Ʌƅ{vrolhdb_\XWVPHDC@<9852/*&%$%(! ]&cځ߅݅ۅم؅ׅӅ΅ʅʅȅązurokifc_[XVTOIFD@<9641.+(&$&(^(cځ ޅۅ؅؅ׅօ҅υ̅ͅɅŅ}yvrnkjhc_[WUSOKHEA><83/-+)'%#!a-􃦃bځ ߅݅ۅم؅ׅԅххЅͅɅŅ}yvrmjigc`]YWUQMJEA@>:4/-*(%"kC bځ ߅ޅ܅څ؅ԅ҅҅Ѕͅʅƅ…~zwsnkifdb_][XSNJEA?=:50-*&#„\Ճ%cځ ߅܅مՅӅ҅Ѕ΅˅DžÅ{xtpligec`_]YSOJEA=;:50-+'$Ą-dځ ޅڅׅԅӅ҅Ѕ̅ȅŅ…|xspmjheb`_]YTPMGA=:940.,)%!Ą*dځ ߅ۅ؅օԅӅх΅˅ȅą|wsqnlifa_^]ZVTRLD>:730.,)&# Ƅ|c.ƃ%cځ ܅؅ՅՅԅӅЅ̅Ʌƅ…}xtromkgaZ[][XVTNE?:620-*(&$  ɄwK%cځ ޅمօՅՅԅх̅ȅƅ…}yvspmlhaXY\[XVRKE@<731.*)'$! ΄~QÃ'cځ ߅܅څׅՅՅӅυ˅ȅą|yvspnlje^\\YWVQKEA>9420-+(&# Մ^&ʃ)cف  ߅݅مօՅԅх΅ʅą}yvromllid_\XWVSNHC?;852/-*(%"܄l2у,cف  ݅مօՅԅ҅΅ȅ…~{wsommmlf`\YWWTPJEB?;731.+)&$ńw<؃.cف  ޅمׅՅԅх̅ƅ|zuqponmhb]ZXWTOIEDA=731/,*(%΄Eރ/cف  ܅مօԅх˅ƅ}{xtrqnkhc]YVURLGEDA<8420.+(& ׄM0b؁   ߅ۅׅӅЅ˅ƅ…~|yurqmjgb\XTQNJFEB?<9631/,(&  V1a؁##߅ۅׅ҅υ˅ƅ…{wsqoljfa[VROKHFD@><97630,(% ̄_3bف&&  ߅ۅׅӅυ˅ƅzurpnkhd_ZUROKIGC@=;::840-)&!քh5d݁()# ߅܅؅ԅх̅ȅ…{vrpnieb^ZVRONKHC@><<<951.+(" ބp7i䁲)*%  ݅څօӅ΅Ʌą|wsplfb`^ZVTRPMIFCA@?=;741/.)"儷s9n큹)+'"ޅ܅؅Ӆ΅ɅDžŅ~{wrmheb`^ZXVRNMLJHFCA?><99;=92,$t;t)-*% ܅ׅ҅ͅʅȅŅ}zvojfdb`][XUOLLLMLHECBCEGO\bXI;72*DŽv:Ճ+iꁺ&:;4.(! ܅؅Յ҅΅Ʌƅ|yurnkjhfc_\ZYWTQNMKHECA=951.+$ لh/̓&d⁳':;4.'  ۅօӅЅͅʅƅ|xurnkjhfc_^\ZXVSQOKGDA><93.,)"ф[#ă"aށ(<<4-& ߅مՅх΅̅Ʌą|xvsolkigea_]ZYWTQOKGDB?=82.+' ̄|M_ہ)=<4.' ݅؅ӅЅͅʅƅ{yvsqnljheb_\ZYVROMJGEB?;5/-)$˄p?]ځ*<;50( ܅؅ԅхͅȅą|yvsqomkheb`]YVTQNKHED@<72.+'!„c0\ف*:94/(  ܅؅օ҅ͅȅÅ}{vspomkheb`]YVSPLHFDB>952/+& ۄW#냝Z؁,::5.' مօׅօ҅̅DžÅ{wromkjgeb`]ZVSOKGDC@>952/+&!ׄ~Mვ Y؁.=<70' ݅Ѕ҅ͅӅЅ˅ƅ…{wsomjgfeda]ZVRNKGC@?=:51.*'#ՄxFك Xׁ)<<70& ޅӅυхх΅Ʌƅ}yurnjgggeb]YTPMKFA>=<951-*'#քvA ҃ Xׁ%894-$ ߅مօӅυ˅ȅą}xuqmkigda\WSOMJD@><:751-*&"ׄyAσY؁'75/'! ۅ؅ׅ҅̅ȅƅ…~zwtqnjfb_ZVSPMIDA?<9741.+%!؄|B΃Yف,94*$߅ׅׅօхɅŅÅ~{xvtpjfb^ZWTQNIEB?<96320+& ׄx?̓Y؁,83*#݅օՅԅͅƅ…~{xvtpkgc_[WTRNIEA>;85320+& ׄt<΃Xׁ,84+$ ߅؅ӅυɅÅ|xvtpkgc`\XURLHEB>;8642/*%!ׄt<ЃWׁ,83,% م҅̅Dž}yvrokfa^[WUQIDDB?<9752-)% Մu>ЃWց,73,% ޅ؅Ӆͅƅ~|xtpmid`^[XVPEACB@=:752-($Ԅu?ЃWց*51*# ܅؅ӅͅDž~|zwsojea^\[YVQHDDB@?<962-&!Մv?ЃWց%2.'! ߅ۅׅ҅̅ƅ~|{wtqnhb_]\[YVQKHEBA@>:51+%!Մu?уXց-+$ ߅څօхʅą~{zyuqolfa_^\[ZWPKIFCA@=950*%!Մt@ ҃ Xׁ*(" ݅څׅӅʅÅ~{yxspnjda`_\ZYVQMJGC?=:850+%!ԄvB ӃXׁ('  ߅څׅօӅʅÅ|zvsrojeba_\YWURPLHC?;8752,% ԄwB ԃWց)' ܅ׅӅ҅υʅą}zvturlgdb`]ZWUSPLGC?;8543,#ՄvA ԃWց)' ޅمՅхυ˅Dž…|ywuwtnida_]ZWVRNJFB?;8431*$ Ԅu@ ԃWՁ&$܅؅ԅЅͅɅŅ{xuttrlgc`^[YXUPLIFB>:7420+&!҄t@ ԃ WՁ! ܅ׅӅЅ˅Džązvsrpnjfb_\ZZXTOLJGC>:7420,'! ӄu? ӃVՁ ߅ۅׅӅυʅDžązusqnkheb`][[XSMJIGC>:7420+&! ӄu? ӃVՁ  ޅۅׅӅͅȅŅÅyvtqmhedca_^[WRNJHGC>:631.)# Ԅv@ ӃUՁ݅مׅхʅŅÅzvsqnifedb`_[VROLHEA=9410-'" Մu? ԃTԁ ߅ۅׅԅЅɅą…}wsqpmigda`^[VSPLGC?<720/-(" Ԅt? ԃSԁ݅مօ҅ͅȅą…ysqpnkgb``^YUSQLF@=:51/.-)# Ԅt@ ԃRӁޅۅ؅ՅЅ˅DžÅysqomieb``^XSQPKE?;730.-,)$ ԄvB ԃPҁ܅څׅӅ΅Ʌƅąxsqolhfc`^\WQNMID?9531.-,)#ԄxC ӃNс߅ۅ؅Յυ˅ȅDžƅ…|wtrpmjgc_\ZVQNKGC?9542/-+($" ԄxB ҃LЁޅمօх̅ɅȅȅDžŅ…{xuronkfa][YVSQMGB>9752/,+)&# ҄u@ ҃Jρ܅؅Յх΅̅ɅDžDžŅÅ|ytpnmjd_\ZWTSRME@<9752/-,+($ τs? ԃH́߅ۅׅԅӅ҅υ˅ȅƅą}xspnkgb^[XTRRPJC>;97410..,)&!τs@كF́݅مօԅԅԅυ˅ɅƅÅ{uromiea]ZURPPMGA><:7410/.,(%"Єs@܃Eˁ݅؅օօօӅ΅ʅɅŅ…~xsqnkhd_\XTQONKFA><;9520/.*'$ ҄t? ׃Dʁ܅؅ׅׅօ҅΅˅ȅą{vspligb^[XTPNKJFA><;962/.-*%"҄u@ ԃCʁޅ܅م؅ׅԅЅυ̅ȅÅ{wrnjhe`][WSOLIGD@=<;:62/.,)$ ҄u@ ӃBɁׅۅمׅՅ҅Ѕυ̅Dž…|wrmifb^\YVRNJHEB>==<9630.+'" ӄu@ ӃBɁ΅ۅ؅ׅՅ҅Ѕͅʅƅ~{vplifb^ZWTRNKHFB>==<8531-)%! ҄uA ҃BɁ҅܅م؅Յ҅υ˅ȅŅ|xtpmjfb^YVUROLIGC@=<:6320,)$  фuA уBɁԅ߅܅څ؅Յх̅ȅDžązurolieb^ZWURNKHFEA><9520/,)%  Єv@ ЃBʁ҅ޅۅمօ҅ͅɅƅąyspmjgda]ZXUQNJFEEB?=;730.+)%  фu?уCʁ҅ޅۅׅӅυʅƅą~xrnkheb_\ZWTPLGDDCA>=;851,)'#фt>уCʁ҅߅څՅхͅȅŅ…}xrmjgda^\ZWTOJEBCB?==;851+('#Єs>҃Dˁ҅ޅڅԅЅ̅Džą{wsnjgc`_\ZWSOKHFEDA@><840-*'$τs>҃Eˁԅ߅ۅ؅Ӆυ˅DžÅ}wurmifc`_]ZVROMJHEDCB@=720-*(% ΄r> ӃF́Ӆ݅مօхͅʅƅ…}ytrokhfc`^\YVSPNKGECBA@<61.+('$̈́q> ԃǴӅޅڅ؅ՅЅ˅ɅŅ{wrpmihfc`^[YVTRNJGECB@>941.*'%"̄r> ԃǴӅ߅ۅ؅ՅӅυ˅ȅą~{vrnjhhfb_][XWUSNJGFCA?;731.*&# ̈́s> ԃǴ҅݅څׅՅӅ΅ʅŅ|xurnjhgeb_]ZYXURMIHFC?=:52/,)&" ΄s? ԃǴӅ݅مօӅυ˅ƅ…{usqnkigeb`][ZXTQMJHEA><951-+)&! ΄s@ ԃF́Յޅ؅Ӆ΅ʅDžąytrolihgdba^\ZWTQMJGC@>;961-+)%  τs@ ԃǴ҅ޅׅЅɅƅą…~xtqmjgfedcb`]YVTPMIFC@=:840-+'" τs@ ӃH́̅څӅͅDžŅÅ{wuqmigecccc`][XSOKIGD@<:73/-+&! τuA ԃH́ƅׅׅӅ΅ʅDžą{xwtpmjhecbbb`][XSNJHGD@=;72/-*&  ΄uB ԃÍÅ҅ӅЅ̅ʅDžÅ}ywuroljhfeca`^[ZWSOKIHGB<852/,)% ̈́uB ՃÍЅӅЅ΅̅ȅÅ~{xvtspmjigfda_\YWURPLIJJC3+/0.+(# ̈́tA փÍυӅ҅Ѕͅȅą}zxvutrnljhfc`^[XVTQNKHIIA-").,)%#!̈́tA փJ́υ҅хυ˅ƅ…~zwvvuromjgeb`][WVTPLIGEC>3+,-*&$$" ΄s@ փJ΁…Ѕхυ̅DžÅ~zwuutromjgec_\YVTSOKHEA=:61/,)'%%# τs@ փK΁΅υ˅ȅą|zwutsrqmifeb^[XURQMJFB>;840.,)'&%# ΄s@ ՃK΁̅̅ȅŅÅ~{zwuttsqmifda^[XTQNJGC@=962/.,)'%%# ̄r? ԃL΁ȅȅŅą…}zzxvutspmieba_[XTQMHEB@<741/.+(%$$# ʄr? ӃLρŅƅŅ|{zxwuromid``^YVTPLGDB?;74420+'%##! ʄr@ ԃLρ…ƅą~}|yupmkhda^[WURMJGEC@;66640,(&#! Ȅq? ՃMρÅƅą~~~ztnjhfda]ZWUPKIFDCA=9751.+)'# DŽp> ՃMρąƅÅ}}~}zslhgec_[YXTOJHEDDDA=94/,*)(# DŽp= ՃNЁƅƅ…~|zxqkhgeb^ZWWTNIGECCDB>93/,*)(" DŽq> փNρŅŅ~{xsnjhfd`]YVTQLHFEB@@?<62/-)'$ Ƅq? ׃Nρ~zuokigdb^ZXURNJGECA??>:63/+(%! ńp? ؃M΁|xsnjhfc`\XVTQMIGEB@?><974/*&#  ńo? ؃M΁~|zuqnkgda^ZVUROLIGEA?><:853.)%" ńp?كNρ}{wqnljfb_]XUROLJIGEB@>;9741.*&#  ƄqAڃOρ}zxtoljgc`^[WROMJHHHEB?><9632/+'# ƄrCۃOρ~zxvrnkiea_]ZVRNLJHGGDA?><8422/+'# DŽsCۃNρ}ywuqnkhda_\YVRNMLJIFCA?=:6311.*'# ɄtDۃNρ~{xusomjfda_\YUQONLKIFCA>;7420/,)&" ɄuDكPЁ|zxvspmkheca_]YTQPNKJHEC@<8530.-+(%" ȄtD؃Pс{xvtqnljheca`]YTRQMJIGDB>;841.,+*'$! ȄtB؃Pρ|xusqnkigfcb`\WUSOKJIFDA=:841-+*(&"  DŽsBك P΁|xvtqmjihfdb_[XVRLIIHEC@=9620.+*(%! DŽrBك P΁~zxwtpmjihfc`^\YVQLIGFEC@<830/-+*(%  DŽrBكPρ|yxwtqnkihea^_^YTPLIGFED@;620.+*)'$ ƄrBڃPρ~{yxvtspligd`^^\WRNKHFEDB?9410.+*)&#  ńrBۃQЁ|{yvtsrnjihea^\YUPLIGFCA@=8410.,)(%#! ńqAۃ Rс}zyxvtqokihgeb_\YVPKHGFB?=;742/-,)'%$! ƄqAۃ Sс~zxwuusqmigfeca^]\XQKHFD@=;9752.,+)'&# ńpA܃ Sс~{xwtsrqoljhfda^]\ZWPKHEB><:8762.,)''%  ÄoA܃ RЁ|zxvsqpnmlkigda][ZWSOKGC@=;98752/+(('$ ބpAۃ RЁ~}{yvsqpnmmligea]ZWTPMJGC?<:98531.+*)($  ݄p@ۃ RЁ|xtsrponmkifc`\YVSOKIFB>;:96420.-,*'# ܄p? ڃ SЁ|xusqqqpmkida^ZWURMJGC@=;:85430...)%# ܄o> ؃ TЁ~}{yusqqqoljgb^[XVTQMIFB?=;976430/.+&$# ܄m> ك TЁ}{zywutsssrnkiea\YWUSPLIEB@>:76531/.,($#! ܄k= ڃ TЁ~{xvusrstvuqmjfc_ZWVTQMJGDBA>:76420.,)&$" ܄l= ۃ TЁ|yvtsrrrtuuqkgc_\XUTROKGECA@>;97530-*'%#! ڄn?ڃ Uс}zxvusrqqqrspid`\XUSROLIFCA?><:88630,(&#! ؄n@ڃ Uс{yxwvtspoonnlgb^YVTROLJHEB?>=;98763/*'$" ׄm@ڃ Uс}zxwwvtqnlmmkgda\WTSRNLJFCA@>=<:8652/*&#  քnB܃ Vс~{xwwvurokjkkhda^ZVTSPMKIFB@?>><:8753/*$  ׄvL߃ Vс|xvwwvsqmihhgeb_[WTSQNLJHFC@>>=<98752-(" لĄ^&⃐ Uс~{wwwwurolhgfdb`\YWSQOMJHFEDA?=<;87530+&" ߄Єr,߃RЁ{~zxxxvtqmkhfec`]ZXWTQNKIFEEDB@=<:862/+'$! ܄ʄu"ЃyMρ{|zyywuroligedb^[XVVTQMKHFEDCB@=:974/+&#"  ՄRcG΁||{yxvspnlhdba_]ZWUTRPLJGEDCBA>;9751-($"  ԄZփKڂÁ{~}zxvroljfa^]\[YVTRPMKIFEDCA?<9753/+'$! ҄^(탰u2ɂ9ˁx~~|ywupljgc^\[ZYWUTQNLJGFDCB@=;9631-)&$! ӄl7ȃX0ȁw}|zxurnjgc`][ZYWVUSQMKIGEDCA><:852/+&#"  ҄zK߃r=%ā{~|zyvrolhea^\ZXWVUSROLKJGEDC@=:8530-(%"  фY)􃾃T 傋~}~~}zxwtoljfb][YWWVUTRPMKJIFCBA>;8520-)&$" ф^5҃g4ǂn|}|||{xvtpljhd_XVWWWTSRPNMKJIEBA?<851.,)&%$! Ԅ_9xE₥J恬r~}{zzyvtqmigeb^YWWWWSPOMLMKIGDA@>:62/+)'%$" քa;郺S!򂿂{ʁk}}{zyyxtpnjfec`^[XWWVSPMLLLKHEB@><73/-*('&#  ؄c>_-͂D쁳h{}{zywvuqmjfcb`][YWVUTSQNLKJIFB?><950-*(''&%# ؄e@ăf6ׂXÁgz}{yxurrpnkgc`_]ZXXWTSRRQONLJGD?<;852.*)'%%&)'  ؄„gBŃj; ݂`΁gx{ywuqmllkhda_\YXWXVTSRPNNMKIGC=:752/,)(&$"%*)  ل„hCŃl=߂dҁfvywurokihfdb`]ZWVWXWVTRPNMKHGFB=8420-*('%#"#&# ݄ńiDƃk>eӁdtwurpnkifca`_\YVUVXXXVRONKGECA?<730/,)'$""!  ߄ɄjEŃk>ႫeӁ`rsponljgda_][YXWUUUWYVPMKHEC@<==710.*'$#"! ߄ɄlGǃk>ႪdӁ^oomlkifeca^ZXWWVSRQSUSOLIECA>;;:4/-+'$##! ʄnI ȃl>₪bҁ]mmkjgdddb_\YVUTSQQPOONLIFC@=;8740-*(%#"" ߄˄nJ!Ƀn@オbс]klkhdbbb`]ZWUTQOPQOMLJHFCA=9642/-*'&%#! ɄmH!ʃnA䂫bЁYhkjfb``^\ZWVTRONOPMJHFEB@>:631.,)'&&%" ʄnH ˃oA䂬cсTeiiea_][YWUTQNLLLKIGEB@=<:730.+)'&%%#  ̄nH!ʃpBカdсRbfec`\ZYVSRQNKJIGFEEE@;98731.,)'%%$#! ΄oI!̓oA䂫cҁQ_baa^[YWSPOOLKJGDCBDF?96530.-*'%##"  ΄nI"̓rC傭dсM\^^]\ZXUQONMLKJFC@>?@;752/-,+(&$"!  τpJ"̓sE傭eҁHY\[ZYXVSPMLKKJHEB>;97642/-+)(&$"! ЄrM$΃rD悮eӁFWYXWVUTQNLJJIGED@<96321/-+('&%#! фrM&σsE悭eӁDTWVTSRPMLKJIGDCB=9641/.,*(%$$$#  ҄sM%σtF悮dҁ@PTSRQOMJIHHGDA@>9641/.,)'$   ӄtN%΃tF炭dс=<:641/.,)'%" ՄsM%σtF炭dс6EHIJIFB>;:85444320-,+)'%#  ԄtM%ЃuG肮cЁ /35640)#!&))'&$"! ΄rM%уvG邯dЁބ߄ ӄjF ΃vH邯eЁ{yuv{Ԅ܄؄Ԅ҄τʄ„tW6ǃsFꂰeЁ-@Yu„nV<܃kA邱eЁ`mqokc[X\bkwރ4IZht}yrhZJ5ƃ]7傰fЁȂӂւԂ΂ƂĂׂ̂ !=]ԃ(9FQWYWUSQPNI?3$˃pO+߂fЁEMOMG?9:ALYi{ʂ ,KgЃ%(*('%#σcC"߂sӁscikit-image-0.9.3/skimage/data/multipage.tif000066400000000000000000000016541223313777300211330ustar00rootroot00000000000000II* !"$&')+,.023578:<>?ACDFHJKMOPRTVWY[\^`bceghjlnoqstvxz{}   |3(1:jmultipage.tifHHImageMagick 6.4.1 06/19/08 Q16 http://www.imagemagick.orgMPnB538 2LHkㄘWytoRIJabsߧ:aP{ V&b`g7g0nfՈ*:KiCDvdدGUN__ , vDa M<>f   T3bj()1:rmultipage.tifHHImageMagick 6.4.1 06/19/08 Q16 http://www.imagemagick.orgscikit-image-0.9.3/skimage/data/page.png000066400000000000000000001350771223313777300200710ustar00rootroot00000000000000PNG  IHDRTiCCPICC Profilexc``$PPTR~  |@T(dS߮1uAf!fMZ TwRR N//)3"I`v oa``)Iep/,L(Q0TpLOJU,.I-VK/*/J,IM_`d &#ai2tv ^J!+"W4\$q#+rǤ򥥥OȔɪޒwUPIOZU՟jջ4B54?hОk'JZc[ySfӗfwZ,`Ugkghjo`*emP81hi𮐋/Ù"""+bf{ܐ&f:GEff싹y kd*{S_YR֫njF泭rmG;O5ߝh3iS19 sO7_t%ߖe.2d5.kܰm-[Mmasn=gp0#ď8i}ܙ䳿O}īϹis{O<{,d"/+‡O_}]=SZ9 4hE pHYs   IDATx̽$Wu6Z9vggw6jZE$!,#$Dall<`K")rN9M{f:wS=6;UuVs=ar %+b2F< -E1aG~JH+ "lq`3Gd"|aY8\tB Ǣ32cx#` È YQwFq,848Z0>QpkWSY:+w'4n LAą@&1A4 #@ #C4_69@D@'Wb8ax;H`04* E: tL?8`'`ͷ͇7ecA gFDlG>a@ƀ VX9 ) ;xJPw,A + ;!7RVp7`%dӫ>_n􈗅0:o_o!d@s א / 0ƀ" fV|N (=AW 78EZ9xZpH`Ux l7B0F:iD hvz/x3fF<~ ;qp2 ^D "Т4V;@ S,8WRĹO"0rzL 47uitkpԈ _21-bD|DʃXp<1ؘN=f;{L.YF"D$, 2`Ikǥ0!iѓ49:l4 s/w6^9mJBxRBGH+t o$66D 0CP?,]zPZJh'qY:n@X8}"8q%#Y/E!"5T$ϹI y$ˀ/CNp6ur^ " C ౺"AwrbiR4 I! /1qkD1a=Eϡ#bϣ:r{qϿXpDZLd SJ^EօvD"yPrŏ;B4zz?L/JR6`YU! qo7'tebM1Ё!5^] qCֈ d/796^:??WhG͌e-!=@2;rHHB4"%șgk7;21ŃDθ#8Lcz1)G KBB_$wxi\xmq.:#)]HjTXᴄ%$0'l͗c惋:7OלY=A(#I"F6Қ,y>0YD8l+1eVaFJl{zK=(HXt2\#bRWc('ixjc7^(AbA@ξ޺*j6 @ ;V ExڑAĭXh^|B׽WŤbpGr=AZAt AAUFd HY?Ы$ Plۂy%!\ċ0Hj7xrEyh9Zj,4FJP|{6Geނ0w?t%nO/}㛣Wί: Sr_YpBxyIt|Ů٤Q HTRX""&l&:B ҡfI%Un w"&Ipx3I Sr4n3!*tCNvMdIqdAm/ɸQDl3"8Q6BPUOؼ*;Ok$C#kʑ iAU /&\N\!&&(=VX9P+&Џ)ZFCj0</rl79_ I̾Sn2` ʀvv҂S&\5ՙݙ/e~ڥ(Szԩsu.3L%ݵߘ8=Jkr/ξ4R]$,J1Z8P,֍!HzKZ̋SvjwGUY5yufFZ@ô ~*t(%Vo3"*uSZCjuJOB)+t.60~‚Da8"l+,Yq?)S=uxo2L{tLJ+1Gxr$b˯]lºYQ'rN?qQV2_,?xE2 '˖[fۏzLnJ"桋@=/Xn&S)ҟv>ggik^A-om1{h9\>z7uܚ.{y=ރwt^2r m8s]7sݣ>fj͞;{`u$?X+x'(#L GK-۶oRXZy@9U򉇟eY~to@F.\m [b$iϯ0oQN Ow/]=Y?{r%Ï7^ Y}inM?}({eqՒ+w{͛j'k>sF/M;vd-M{a| 9ٜ8y;o]񶪺r+z-g۬T9%_{b";4::s߼7w}z͐ʅ'rު7u}JL˅pc[k/>/n2A?0sQުjVUųEcgbhs--3`kṰn'];Oj-eO8vm!q^p҃ʊgҮMMJ v4L+ Û.^:caZW), 0F(:'tLYOTCco]oLl0y_rA_&vL>ycS`1?1So EAHi۹?+uVr8˷rNT=Zp{fdXR4(/T؜ʁ2yK{NĈdYJ.]*B`jxBW@ z\u.g6znԲ_9 Hۏu/y"z) $P&+szL[ZB2[{HcB5Sr8'_ =U%I䐮֛ /m9=֒, -TCܮVyr}ժ|)5Z~?p]B÷Q}pgRSIn^yE(p!R*dyb2]q j"_Ia9ɉNʜT#fX.e}{]ڡmjs:r#%6|U#-s߷kp(kX2ڲ[mQp\bڝPKze.?.d劗h( d向`=\3tMʖ|#0\}vnI @]OΨ,ȸ9~:sgZZar9Pk_79JRLPO)9(d4ĚX?(S ':2rhs.-\L[l"pC3vqۃ?('xsk'Oݞ"N隡9j%%R=S)9&G ?<'TRv{O:}>uF} .y{Eˬ]^VO6 Ƃ§|/p>^SЄ#pV(ë,U=́a#tL#>B.kemU䨨SkɅ +)gIiWWZa&2TlAX{YJĢXj0a n\YUNHg}sI'H zQ8(PdyIAlMWO{j~y&5EGTZWT2ynXrǹU2^J-JԱo]"0m#Dh (l52ŋ5N"AȱG9,ώ&o"R2Zp^ s铣ɴھlX o(j۔F&-.cYc+]\f命{e'USًGv!A-yW`{*S>M-9j KC=H=ѷn{hי˅+&vx2_% =n6w:0Ib9_|n{6aeup㳷ov]&"~Nj."6\(;%̅g Mu-5>!23^0Eqju־59'@Tl&ig?r})͔:w*2['7gFGtf[J{YwF(Cf8n #ȅG WuËq$/Ɒ&\m,xg j]W^f/^,1KJcj6lܑ/0})WQ}V .TغQ."?gI'[0h+ '(D^ )Nde]DkSf &7B$]PvdtŊz -\fkpi0 &O9K*z9%s`A^/0 &=S{zv ݲȩc03_Uz~nʸK~ .V%D$/v eu[]Q8obOa&Jzлj9[xab& %ޥC9 m ґkهu^lI#I& Hu&GB;y:I?(DQ"&f: Z(-F]Dnc*ݩJ*b>Ǫ?Gr:t1xi(bID%,Hx1+TRVtarEk ޛL(JyǍX=9 ?1rj݁]OݔNPũZvZʯt.]?{Yrckiod?"*L*%E˙jMVBro3&/^ኪMB=+)%# c9H>:XO!qBG\kM+P%"UToG8BYvpYF|!E%9 Ve,%޹zr T7qCb[XSF y/[ 80I4 TّF ȳye6kRې3B~K͈?o|EFER*%cu"ZN,[J>l8F8:S"*ୢOqx5m Pdw%W()8l& CiR@Hx/z%l/IBX޲G7c*% xOe 4!xAAzMuDB߯YbM4chM|qSO=LrkG=RurMLJoM/.#Q`nҔcR4FDub@\F8)08_>qOpM4#ـ'i'35?&!pE1 D -zGF W2WCpM 4OV=-q&dwRR$ OX@GDBhLȢ)+YKgaG=U:GBmU IDAT,~5XKUC%k@8*'^& I`@G+[_Sz"pZ6_tXfc#.桤rx 1Knz 64olN#ynhb/1aRzDv"H m(<'0e=hAdM.l=0<0~fy7 %0 ~攮ǩ!0v%LQB8XC2X qb0Iҿ5A8Xp5 x/$ c@StCQG2C!#p:cü:@7"8 q=@Akk( 4 B mшȨ5y|S6RB5<M6?~X~Mts` $.bZhxl`k>AHeaR ! r# $bBf*1}^`+bL@JΦ@_1C6c҆@ p6Qp$ | e@~(OiF6ȂIk"AkbEbP c ' !aM" ఊ`ӂ22Ȧ _it~-*!%:$ `5 \Lt c$k QA? ;CL!5ț#(H" ނ#`D!Ac# =/ nw[M@~dL9^7&JCS`"mĬ D@_p#Al ~X&&L U(2 aHJo;u PKc0 baqX7 K}OowSe.H\@vDD><^tEx Iƨ xxI^Np⇪ tjzDx 0 `LG%uJ5IZ -8hxT:BNv 4kכ'5? DNH1GLg$bF2ϳ> !DuC-t&# rHiwp<41#?hyh&@K wah5$z6ǘ zAʎ0HO:X\0H51]I$v]g(!%E)-jLacInJu[53-8DH*d &*(>F%ʵ?@jB4|DPD~s<6P| |p H0X\ vU)a JJ l aWdezNXfzI %ʺ,<i(dC)(X  L5x6H<KƸNtakoq6_Pm !C8; &lq>riul69~ Lԉ!eb+'*fmp!FBOH F ĺʌ bKr݉62 kcapJ  n`9|"+>P0]g5ȖDPE&rmP}EZ-h-b8 c#N=^&z`##TA[؜Wʢ^Qr=F!|%bhqDF(o< qnւpuG5bPK c{\9c,RCɡB"$JXn-I9,&4K)_LNԎ@^(c^ςB]){KHb\pzb!ULIQEG3"Uu z  A[C r&]+ ̉6*XpQX0 JP-pYݳF4l CF*1Ns=jhp7p H:(n,IE+B%tjQRUa*Q n}=d,P?i;2nK`'.aѼR6k LQ=8`H. ~3HD^P4\?9W:"/B~]Wk/Փec|X)26e=0$1HldDmCxe&-PUT8Mg]:a5L y`|({V`a,DNJ}􁋄(WUԴ qAa!B1A$kt\:zJ^@{$923Z:& g]tf9=i[de1x~jFk#SLΓUTg~IHx4/Q-V ]l)&dyB=x_Nz8pzӰ6},zε U.U5%U d-Z6A6Do)6W=Ѻ/ݾ) pT 61S!9psOJu߾(QŚ,A `>/o0G+P~P'4g-͊ݦzْe\=,TہjS1CriwUE[SetXcB~w^ Q)0Z| YvVdaQ{50SWӬ<] [CQV ŋ[<ޱ.D[2d8UxjPtz(-3^Q* E/zL(p;^KX\43s6.[Fx3lUTJ=o-Tĺ;3 l @VW;,2I[QU}HTƞ8Vd6mkMt煽}.ON_&NG'2?}rJtʹ̶fs9+Cqw7ay ۅ/'dsnrbJ[c̲Q) , # {V 2~Af!|YazH+v_lT(5UMy<.]Aɴpvud'@ݹ̵ㇺwz"zpF̱2?A{9?hv@2&U+ t|[ 3Ei5wX`\7Vv;8Xm[{ +=/Tw,k/?xޛ[=}cK=3=7=uo5-w<[LYgg?tny-:F95fCR\z^|}& 7x?dW]>mP5ah{H;[IRE jxo_en; \-$P[;}+?x\ d;z\e_]RsXE:=›o5\s"S!L+|Jɺ٩m.L2':%=1D )|+5D yFB0'w|mBg(h<_ % rn`e6)K.vk"@NY3gՆzUMg[$t?]aoZV{du;4[py_j;_Mn[|d8la֌|8W/w _^{0Y#㫛fnSA% z[}׽|oǽOA>$K}W~+/~}l:v?!{G/om3ClyCRf dN~d@:vlӽ*Q@=U29#[Oά> j .&+g =\ݵ@8oy5fQ$ݝV: N:[׻ioec3u“;y_Tj]?4Y}x %{Y]%i2&6,aesw5ZGO*˯YuVqgpj\8)މ5 [} 8^vCUƯSxGՕk݋98\蜹'?zQ~'߼|||FRuFaO=WzLd+>3R4& BTp J=ƏՍD3HT^֞`22ķYIK>fI*3ź3ӶЃcgbAZn9=jzFq˔QȫPhJI0QJ.۔u? gX[a1J!܅iFn5s pݻ;mU8zWZT3ȓ 0rJHr؄ɓf9gGIుBwgrs5SKF;\} ?!ba0eջKAe@6ǼoՖ?|jsH7aE /2K^_J=tཕ WO*8a-N5&8pbzg[񰠭E ̢;s [L(ڛhu`DE`Pp~-HԪVJ1 H6lҁHլEsB_\bAVիe_IKܳM<8XKu7N;}Qnː֎2vYd7죗q뽑-jpb_|AQ7$Ȏ Bl^UIe}9d ahw-{}ӆЪq_oڟY*ޕ%+o?[*EFCx^2>j)8Ľ~G[woYT[wyGv{ O>_7 _\t66.)sᶤ9,ΤMgY۪.s1Z4LZrA\Eo(6rmu`Ah_ZT k -X.\] "&39u'%up%L:8yڒ,t:k7ke)X0grMk;CeiCXA 87/ O1dJvUO?w@+7.Bj(H $Egֳ֯ zF ^wmh-e!kӇ z!@ k]O$6 elp5p:'%XC̳Νֻkֈ]҂5mڛ 6b+gWti+nۚ|ny #9 i%xĚZEj4<2vCY 7Pɰa   R!5^UAӁhȨMgWAJX}Nd)ޅ#&#OdM;KEEgv!S b r>6KY_YAe8 jO yA@-%8i"yn.SQ\Ჵ#׽j֟Kq [lAaBQB`DGlz=PϰuNt2W ɤO>$*UP:U=X؟Eד/ ?> {C<)(AE;Bh5N@c 7Lq~Pa7(% Uo+π-tOAB0> I_x*ƫ>(*(UR&B<:9cX$U).]CDX2> Z@tdt$;bǀ(.a2 pt#~8 ;\LY A b/!"z8v5ۃC12A 6 C0X-ڇ x (o Ozl`qFGXs؏X-O!?C]X`z^G8a!6Q >4sH2AW% 26rSCA*Y!F7o[H rpOr]%׶Dw-Jg%TAR\*;Ti#wY=xmvC.g"'"u* dʦ@H05:(@>.5%N@`IPM#>Oԇ  t%$PXQ'ױc3zYHP>ATX?HMߚ陴. &|L58yz))5xȧYoW%HTt>u%mĎsIa\!!Ѓu}O_򡀒ګv#jԋ[Y:9(G ?yxC-Ft1 1䦃 \<\ V-6`A;R=Epb6C}Tq7z5T<򍉇7~D*jAv/9T5BَD됚CS A`1@qo~9C (υ0:#%p.lR7*P`/%Dj\IP %+3O#Ҳ^b&Qx'clC̆3ܰ69` vD36hǾrX6:~dEn3P3adᩥKPd|%SYAH憑E}):6Q 8'[6G"4UdУW!"IS` v Om8~lmTMaF=\X+ZzB CM"5Z9숮,b.p$r 4@ٮ4kN4 IDATWָa%XR$\ ;j ֖Y|c 7^_ ~!gco݈R9d*ndsIYy퟽dW]T* &B) tOy]M6q~݀;簡DQRC ʉ!G-Iѓ+_pw^޳"y7p|ҫW,C~n[w?(8h;o>zFb1??8֖Z:qt/xmf~Rw=_^XOsw*3ox߾w;6pt|{N "|Qw?m/7OO.Y"cR2m}aoDίo*oe2n)닉G>O}{'\K7vSW\߶=,72sDU<&(Su}IV:+Hj^2N57:ιjhelW> ƊV 5nb:Uy'-&RBl*!])g֡\"xx:*ʳܠZmf%t>!S8nx%0óޜ:r{|OcwlW]z۞:luvxzE8X[r~aFqqhҷ񫢝7vW{>J_[s>vjM-gՊKᤴwU?y?$9o$kl݄Ͻ\ӻlux,$Y/~čaSz:4D84VM9r3D8[ Kw_).gLFjzڔ)@ $rLHdNe׃-pxmpl{(͎TAm^N~g=[ +^fk? cKUU~s7h'2lwKg&Jw~=zϤ?USlg} ߷3!-ڱj!'YJz󗖋 0%#P_^=n zZ>Ξ\MʊCOL Vz|mo -sM 'Sj¾EԫS=m݆/}@ݬ;рT\ǦCV,vx%iK%S5 2?f{,K %pO@e`K C'lUk~vēiIyp"ea/ajuqRy΄׊Ҋ x;vȏz/<5}zVYviT(+`*BYkdسKV("pWtX[gl͝]=ootx Yvƛ+j9˵[-J^?hȋF%E5—>HYAN K|Lrg}LP}ٶd"xK\RY?yÊQ#W;lcM`[}l9-;-|wDkfUOx5aPЪNI9$v*zqrY˝+e nb[=M6r]Nɳl ?fr8%a FVCԻ|S2s#z\s{)Z Bk/Gӗ 2`2[awɜquٙ]9ůgγn}\HJH%6EcJ\o)15}!CZ_ғu,̊Yd2B4[hΓB&ʥ38_fgn NMs ?ݗ/Ia `jp/ѯ h}v{bӟ>x;9hseZsi$?&>澢|s*v..Άpwѷl1<@j1׹t?K +G_[|C KG/]MDQ J_"iey+2C\{Y8, xl|%ddWu[U{{rѠ$$B(#qkg5`0!%!#fg4IgstIUNuw-H]U'k1lb^йq/R N40BZ h`o%EÔ$T??rF+O[X;YG^'enL yDlhd7Jčjbc(FdvctJTl-Mn)>7yQ5RYpO|4憛G#{mNͷ+~" Ǫ ?ogji+ RD|~ki;9[RmVulE1e72"K?h@FC++=~&Qd@`PRPI*Adg{IIޅ pUi+yĢ÷2U,W,]#+t^D#CAzraZO*72z^J,V׵lRCOO\2QV{ VΤ  ,J {ihasO ۉDs`HكduL鰙:ղ?:38_ArKs>)XfFpErY/Ɖ_Jǀ [Osy9E 1"kv ,!zBrb 6ݑ!Ia/!7r<I5sS\ ~dT{]XbM#r-y1DȨ,-N fCW<-k:Jly8JtJ, 2 2Y j{7)`)^ͤhdw%?J皕:Ŧ_w:wc:BnlYo`l.'M,цOLCB^7} ,qK[5%10BPU!/`U*y65}ep%$_l#-['CBP p˺mNI*#@Nn"2~$T)'!f*)o*^t9%L-5ϴkQ(P@np8JI އg׺M| Jӳ5Coi,FZ%HTAh )`D Kzn 4CŜО$e}L*.uNȑ#(b;lY]U$ B g<7!W{͑+ 2ÌK[#u2z1_NfRGtlgbȗ_΀ QwM$aQn,rSMΐK ||S`AdZHN;h ݑX"B}D <(dJ # .Jӳ&` .h4\q`'^B2TPP,,Н ف!ˈiwm/i!ܪ<`pF9xrJ;M  FĒ@4,ʀ aη:`ӡXMY1qVj~LAO >Zc ePb hԘQ#ْrMm#I / 'y5y,dhosSCFegkzRqj A%C cz@_J<`D*h"P9x9X60{G iD!HE|W2;Uל$ǐ9[J'#!d.yAq8FĥfC+Td yr3@YLLOǂ,%tM,Ik#+Q!odɌPxAp&0钁QW<;9DL -U%ҁx_Ln&xN[V>+]3z\靪Lkk3U&F|$bDc(#A0դ0flQ$.=#V`:m3/'nJCWma@tJe]ꁝ"ǔXjΈ͡Q|$.nI ?ifW&_MڦU R V2vqe ], %54 @ŏiKqc8G(8eP31n+ RR诽HMww$i5X^-RcdrtrX;uSNNK/c3߿O3P勇#OXE+E&x/O'H.,X H.85xä4=?9uؚ\ 1X(q3<_W/84a>vdf#ZcbOd,IU6ahe-ldЋE*XfhѿYA3HؒQ" Pá 1a-3T,S˰$} Xl,7V|oto@qDPOb51na׿TYH<}`lښڗXLΨc޵_f<}owk۳u]7D90HfL33|;34ձ{ϐ8WO}-'d]cY%}cGn~d1Êp>i]]c={gzq7SOu:\Bet5;档ꮱٳ !>ޢ= [f:Dt.y<_=1[divn@&=ɲ:$ՃSz}݇W/xʼnJM-O/Ogo_#T*Tߵ:!L$wV)0CrTU@ 3)ke4)UKɥ}A1jRCo-Sab₝_Ov=eO$v M P:Uh(f>@0U$w='=u| Bi 7~'vb'%;;4~{h÷6ްg1_޸}Wvw82{֏}\}s l}獿PgSU޺mN_˄v3Vk/rqי~S{/Oѡ==deS鉽'Zd.;WoZt[(A[Ff`_S PN)5@5r~k!Ihf31p4QЛTp|ʴ鞃1lkL@rN Z~&>//ս2 ;_ח]L?MVmMNv/=zt u߭;n#/反xGڲK˃}o{wj+F>/zR_ܹ#WoWnܙC+?O~0㞹Wۮ>aG>puuG.^CR37-7^[.uʬXGrC}oʉjb_ӣ7zp kv!4V5hU{k ]=ɦw:f:ǫjYGD7n8ؑJfyN*m3\7{[wR!~sh+xP 9ơ>-϶2j͡ЛG͞ygu g.Y놓Yx|OUc=,9_xNdaŌTzm6}g6<6=6=/]%]]֯M|wM$}eCĆ2uoj?N_#^NkL.l6<+,`gŮOYv?]!ͿbEu5u}o99'U;Hi6t#Lr@b]iz|jj[@b[#7~C[5VKOo{lX*So0'@~¸tdy:iO U5P]Zl|HMiyɒȴ j15=9~bk It9w}, -S3w6%ac1s…XHS (3:?4G =&{Xk2h)jKXs bރkE^]0 6G<`9~\)XLyL4׿M)-Yyj3V:Ҍglk>K>C$hKx76UhS<[0.N=<_٘qq IDATo@&ۏL]77_pީx.Á|U2i{"K36 䛩|c\X;w1ՏM @KpՑs;u^>M$ӱӉU5٥-0ddw[mݩAR/,Lͳu՝?s~@]лv.?znGJ.턭_N~ʯfΝWwܹ;[FSFO&o-g=X4,#N;ª٦64b uaoc7`b#e*NLܑ0=mɖCDʭ3ZZtCRQ-͔ͺr@GQ2?@ |OJ^55Եۻ-Wkƛ︭BnF*ѷ[wqbymK,t˱~_U?ᑧ?n?fڞ* $`s?$y'j?gXzǾb4K }Zl` ݤ(肉]:dvؙM6*oZtުMcn{0%φ m(޸1(7٧]/?ϜR}gɻ[>9 *\MdWy{7_` D̓O>01~MܷX}aS[ϻZu_Kdž}$|\‡(PبcqCD-Q:B|Hj(K-x]⤙1>yDte ư` ͂ %r<:0!%!%9Lz@-B˪7NIh ;P1Z,4X; 1Fb[+I,4xHeч KZ_nTuQ8R؟ޜ:BAa(nB/Y֗5Ga$!SIPPf$XsV+)rSͧLS0Oo]0L75UT^o=,BU&&CCv%bPڧ%3a:g)tL ڐ7$Eb iab`'X'8f|;j- $|XYcjn# ).I &pB}"LЩ(34e4}C,7{^Z.c:V93Ә)i|E"$h` bIyFZaؽT֭3_ο| jԘrJm,ĒU'.23S&vp`M TQȺ5t:b~ GfB>'aldG wbZTpx,-X|(h8`jb| =~,Rj7$/.|سI#73m ñ%"LLSU$`bj淧 ˱[*AI`Ih KB`X~1{[ cK e*9pVH*ѝK,75;JăÄ TQx,ȑܳwry3+y,0ְQR4 KUaa Vѩv%L(T[S$(P &D%q!my= ej6a6IM d%S~Qc}HKP܍@11bƍ>YH.x@bqWKUl%Nth3}hQk#,Qā)!5i`T/Hm{8ܐ.HF-T@'.AxbSOyNOkVT#4B7^uU}~,9rjc6ݤi&=V&B&ڏ71>GJkS@<՘Ojx7up3 v(zˋUUF!mdV<1alޭp^)5q\`^ fBˢN@ѯB['kpߐ;"'}J\& bXjTP ՌdF$Y{Y6pI1ju\*Km#DY(&l{a6w8$rPuk ɮijIDv+!t-MC+Cܬěkw>wy oW;(oEt0ٟ9qTy9Gr@L.\ IubIRI斠RSP|9n-"5E-ƈfNͲQ F+;uOih^K G:&OR0"ZX֓vI-P٘t3L&ZHe:aӞdA)'|LYq!UHF^%*-ZHY4;&9f%fy>'=9o 'OM%~M#>?rC8"1n~E)fC}Gt63=ف5F,DX{Jy:7&z{1*O? N.fWXC|KnI/eVW%B çVٽK|+QKn:GTuaeܥ+xckϛWg+C%?2 @{mt/GN='\+,Z@յ*~'OZ:+ZZ.-$3ۉcw֜~|WG&?c%*sykn}eYmW^}CM\]QuYYdj?B!q Tq {AErTOiL1x0^Ҷȴ{LYrNϾKɚ說3ugOoZ|xʾ'ZE/~}TNX{։\|S_Ϣe,qCu'C3 eӖCV]#iՏV/Y_W)ⰰO3}{5kxOWj) :a膙j5͌88Cj@ݶX;E'cҲ70xray|dwwXI,[/}oBx&w_1do_g?j>JD~sڍG֪`ʉ)[5]%"ОPPNć(ʖ[I1+b k4-^xI'b('.xsPtz+zxބbZ}k_g?u7PzUVvg~Ł_1>'?&n*_L4ÿܶn/R5On1{`ۮ`DŽ}Z5׽dzzv|g(ZPv}7cf̓=$XKHWi:]]:ؓqhlDn;}hwӓ걡`~x>yOLstm1)xkA+kGv~ǭt<): 3B͜]&a`RRy^8"4CxS&7[ִ:9o [/Əj[wŋQRě?z\yW 3лF.֗=qwcuhڱ uwoomerwU2s}?5.Ul8B5{JU-8H>W&Q=dMmJz@"!Jԍk?(K dɑ&_) 2Ӳ*+xTnEYuV>?'Qj]e 5|_+XNw"9Y/\~$6 6j4 $%P a ZLr6F3uf_OiW..^9/ ?0rtY[isfu_xݽ6Rd]GW W l djb0I ޕ?TrHu-NU .H2-AUɷRgjoyiot:].HK=_G 6tJgMd3k.͎JIؾZܿ+O "k|"Љ7S&mkueew68A`jA18roUR;/5`ܔ-'Sm `ޤpUcY $J-5QҵP!a,l-\S+ KbXEWl]Y WoH62v_yV l}`Qpzb]|ЃDys6Qs\ sRw[JvwQLs~_}޳kC/Y{_Mkk=&F&ބ;߷z\TF}X&a-5yߎ{l͍|񘿤 9R҇oo\ oyuTջ.PX܈Q+km' P!Gܗ(z;q3 V Q=pf=;YL >QH1 v}cm\V͝-n_UQz.]d漡j8>*3͡lC()|%m%]K|L+.^y^0s(o0Jy׸_nl2 ͡_7'owY0W\oܼ9kFٷ`a/,7oKXGV_jbꟳe(1}/)b )$Xs=B@ +DKp,Heaxj:y:bFWb>$"5‹mgSXA]bA!HHs%̩T6L1P9=X۴kSU}ۭ`Wi;Zݽ#}hp: mvJm.Ùno tO=wl8z"sdwZW<^gn=V>M|Z;w}g~U}]J_ K;񂱅ѱdMLuwɐw[nW;a?3»~v8[Oj X`S?%)B?o9 oo+=@A搉A,Tk@ yj%IiW"@94X)%@Vuc_5O@PW8HĴ%@ĘRO(W'z? 5K $Eѐ9D:->+KHiQt-gR&8-Z3E])T˘0Gꁛ,ɪ9пox]6A3G6[~t>k~r۩vQ.&KPYTW^ Q2BfVi(ʄ0h٘{&Ndh5U2; i `o![b%ѻJO},͐4}HϠLP䢐*`͜\8) s#; }QLLb҄@ z:1?dHX*I bVJk =/k.8Tp!Z/<49L[deit='o[BE iA^j\o^<=nN}cÒ2]/Xr|orN8 ϮA%M)8m4YZzIJXZf35')9a}V,UW.i}NWl~oxF ͖uy0{s!qmkXVݽ9QU5Y3 s37g;V#N]+҃DFݦ`DJCDcW|h:uNKJc~ѮRϦSjKK.C~+f+{a`%p[c^6,67I V}1r-͉U?ko{{=/<Üō}n .߾zKr顣7=|Ն́@ıHQd O!TteDY!$'E'g^-?x;+Or?&T8w3Trʩ? :ՕA=|k;}'C ђFĺܹ:}>s91o% 9{n_3>]U:NZ6g2LOQU"l+31ԏNb~ƱQ,luؘYTb7 *D~CEĴ +C}P֧+?E*){r׭!4`5&N;ҩړAWl"LqrhI n Y/,D+猆܌CG%=Zv |>>3fNkf1hՓcⲱ~=;z;;aӤb0  ŮBYE23x ܘ6/EW fO!9j, B46h;jeHUQ/!d=QF㎱%>/e?) C,`Z6=M$ocuzP"F V]ܺ"}'L:k\ U{Yjb|dt9zoTOc?UrѶ`RAG ܓi=z2K|C%eZ ۤ{8`FDz٥OAVP.#WffHh%a Xd2ӻ3x="qؾ feso6'MǬYE'",d&hרCQEt.?hP{eB\FJy!RI!أ2=P2@{aL R#WY~FЍLh֓zp YjEV&/ ~b\]vWPgXd]/um6\\͟,& cE #D.AhBqMlF?P!ZK lre}$Ξgbp<~azEg C]VQn͔e2eRuk{Dx0l61VHfMgu>q{׀:0 73 g~\Cgwg݇?wи)}߳]C}/3 Ṥn_ $"m+=D_x>}W'a銕d(pL~i>'9>7V"]ȀQIc<ZԆаAz!4RmĂjw bl\զ{Ol΁@Sݪ2vdbKQ+nOՍjjVvո|pqpFP-SF3]QK,Ăi _E'h'.Ilo/!lgSyTk+}LD2F  pnØHP(a(B/iM_4%W2z}4PÖ_&M8m"3e?;hsfXrE3T)ͩr Ϝ2åEʏ-_5&M ᄫC!ΏJ U;pNB ;N_D;S:ŧlר|m|_K7iK7x#y@ } B9aV%:r:y8 ŦKCG 豒W2o)7A4 w6\865b#WVV8ӓ'6kM.vjFOrC#V"gt8.%:Q3NqN۹ah0MhD;g0bb #bTiy:/$ MJ$ 䝶_G^6" +@,v@/t#_:1Ipe a%*J=!FHa(޻E9$#80Ԙ%@Dѕ" z TJWO~%lJmD bA XZL4Kh+ /Kvj_;@xBR *7Јp )Ke YD5&8h /.܇HDya8*R-Q/JV2/W{ahC}~a@#ĨTH-\7xGǹnJ]J9ҷ{ +gW<3?IħK""x_#(%t ޔ:2]"ROv2cUnb`jz. W,T+#=K %|D0h"x$K22=s[u8]8^+~w|d;#@MZK v()yL|N0佅B!J3*!x4IqH.ܛN).s,bAOu&tO)&p?'2Jth-'|DYh. {-:$gxyg4T4R\SP1ezӒ#"󈕄F<Ѡt/ ]PnDEr=5s6&9%O!cq_W s PJ~KD&vdu(pi4=ͣ_2QL;F茠ٯhNepGVl¤Bm/4[bwnY c!8 FL) ( DM .Q3ĊEDHAAuD rCd."^!x|'a~}8n_WcWbSpx*9}@`8!Z8C xI=х tI\ heIUzXb,׊GF ԋDbƗj2>#SR-Y(bTAI#=/*W\V`2e /ZYB@^JOd!:B!X"akw4n3 6aa.9,+qKnH"R5anj J<6|VXj -Ch$PQ6UEwvFc?C>UĜGNN4ܳ=KWq6L8EkdzqU\P^R#>TT)H#6JsZa.^fO(hfmI!) CD+i|$9J,ϳ9N!L<$x N4F   BqČXy%!c[EkT҂[Mؕ~Q@8ip GgDynt :Jnyn|r~tu: `ΟҮ̃'herIa!V R/L# D_(F͓@>e2";Dm5 f:VY8#l@N=PjH;/-HӀO&x]e(Rwa܂!|O"*C #/ڤ:RvF)ԒM,z"3*Dss#@D[1ɬҠs{_佘te'Zy(žKڰR,RshE>UL,TP0[Bwd8#-,&rM54G"fQ`9P~@JIqY,P(VWFg;̛DVȿ +ˣS0iw۠~R\& |t ci "Hdp(1*\"&hjęBv7ȋxB/yA"B CMDeć2Z刚s׷wt:Te6D) -R,d#+m^,D  +EcAI*bOJCF@S9Pf¸܇HDBY"w)!!j`laL^3TfanuS& =#ĉ5O2e hs"y,^ISϵ>MI2IĀE@;NmB\"~g _{\ C Xx mS -ď M .(YN+8Bu9NdE?PN4̀|JM./cxE0Y%Httqϲ4g >⚋ E)d@xi+3݅""+樝z5P- ?M 2j!pqnkй%vvE4 K2b L4=L X dHZXF>%AAr'r稀Qp~5c*B E0Aq"pػ)U C )#)YnkސɑEt842:r Qyǟ!=dHYx9:>R_LCHcDCG*#^LќD@JQID yBޘlt 'PUʕ+ e*-!bd9Ј#^-:DNqJgpndb"h(?yqv@e?@)z3Nx_~K y6{ơVELh5L6ĉ1"(u*e`SEË6C\Cx>㹞>fqB<;єy,@tym쉈̈́ 1{ȧqḈI3=;H ףMލ79: ZEkqN4,dċM?)j"{6e,rgGuXOCAm( 0 9_8R 5ɄAiWB܈PHk+Y5YE` o m$s )]}H1J"3BKFpnRv^-z;X+QJ4BHN`L˳zUSG5ژi-r"0>n긱L*ݼ٢~iBLJKOFpQ2¨Dl"ׄXp4:Tf]nnKn!zhTnɐP.8'E߷_X&-'8}GP}QtGϜ]?FF4t{DZΖ]~M3(] y7izF!8I(5RdXNt/p%cF,p: A@d"#%2yhq $ؕ#\:'$6(:V,zr'r0"GE!dD=Ѿ2K䴗n/=QM~J7)q~lbuVL-ͦGv:]jI0RXLs#Xmj:@Uˀ1#+z "fQuDF a'w7Y u=x/dILp!7dE3=cMh,vxb|G&lyrZW\mpǏf$Mq.FOڞ_( LH7j1ZEU[5ʄ%mwIPSL1(ײusq#FFo2y<-jCԱ/:[xb (-"V]A%3螴)pf>6S~#eR,MϟW]4LzHky FSW#}A" I (cg0%l8G7f$)y0'KkeL,9ƮGʿowuwUw{im!!$!"0 @# HyB 3B ̐ŖCHLI=^]յ׫W7s^ e8$;zP#28 )8P8Jp0 4pXn|7GyF [P Eh.s{w>` xM0X3LWBoe.T֦|pfɕamH vکmmIXG.d}D-T#WTcHK9dhesC@Og?@BL'#J!#K!]G*e >& dG$@dmd|0|rky Y>lBqf,GsZOAOV]Xa6띹 JQPPrWFYn@łfuh[!Rdl܂ 8ajhfJ*HR&T@LQ>%DRRAFDpKr0 UI K aX^hp},$DslS[,GaEcFMwb[՝F"*[J@"LNfd*6kJMo \qrx(\,lΕsv2h:mHm^#} 8xK@ `in#! h/ka h[/zU*ZȅYLY7RA/K916@XmFM1 iEb_Q dO婠w/3~3Gמ>{Bs~"BTE_pcٲS'O$qSb%oH&ρŘ oBEǀzB1S})ɉ e)u$Yvh裔M+\j(0a4Jhol ^jJן;}b0p:NFofZ2Rӫijq({'qV{y|;C맼־X}W͠,ģxʟgk?r7)[Azꁗ(Ʉ`LHl¤#l/Suă[?u@}CPMcYj8czT@-7x ^:k0LGOB[^\Xi!(YĀwQkWNC; VK޼Io=}' CcsNEYWL$X=H-{{/X}/.PVt&52!xp#GH%}R&wI) `@tGCDD&rEC3r Oi` *,>,z@.u :$]򑬈 =A_P[T^7+fS3g܃Ͳ!:){37ޜ6طL/{p0\ 6/m#@dv=ʭerW#Ӗf.s/r02~yR:WA KnQ;n$ a;j!j'}0RљOBV2}$u% qےO4B^%_R C̒섞~sjYp4"ҙ,-)V <P5k :ܢtKhׂY2E2ܱ^wn-6~ly{-TG.[ *os?~z+?4^wnv֫/^ߛ[s8"hO 4 #J /Q/P£NC"vg(C!6Jd|Xd(z|@F0 fqQ6:Ƀ])L "1MFhxCcWb܊rhF 5[@1ữREpNIRJ\4 {Au].W|n27] `Vۍ255/Bm?a^dbYIMf.V\JGƻ;Šə]+<29/YFUpnAD #Mr1ngjnU}xDmuT2!r`Dtb!h}%bέUMlHI:7nU 47Ȭ'&\fˌ-fҠ +Hʆl[3}6nn|͞q"TMZN ZH'k4 /终gs"~ew͗{7XϞ<>C, tA 8SB7hӲ)`Qk E rNbaOE] mQ'et{1hA+ SҨA#x$uT~ 4%fR8ni C$pMZ/WfKQSiN*\<j#XR)M#|ƬfCm ޏ7#*` ;&ݹB*@l܂mSp'bzm.؛LEIENDB`scikit-image-0.9.3/skimage/data/palette_color.png000066400000000000000000000017731223313777300220040ustar00rootroot00000000000000PNG  IHDR ?PLTE3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f̙333f3̙333f3fff̙fff3f̙̙3f̙3f̙3f333f3333f3ffffff3f̙3f3f?IDATxb؟qѿF3bJȈ]c,Vbt*Ĥ>Nbhy\y%bؘ0FbpP;&uc~9bXmbx:a"bX(NxY bMS0b$f,9g,IENDB`scikit-image-0.9.3/skimage/data/palette_gray.png000066400000000000000000000016471223313777300216300ustar00rootroot00000000000000PNG  IHDR ?PLTEȯ}}}dddKKK222bIDATxb``dbfaecb@0BbBbBbBbBbBbBbBb]Ý_IENDB`scikit-image-0.9.3/skimage/data/phantom.png000066400000000000000000000064721223313777300206170ustar00rootroot00000000000000PNG  IHDRݡsRGBbKGD pHYs B(xtIME/2 IDATx[RH@Q<&mॳ F{GG?dIVI|@6,Y7S~~~WC FBQCP`P`8R`Sʅ`T\N)TEN)`!U`!U`I%XH|}}%UUi[&[ETS? -"p.,"R-T6-ZETri`uidKاVR"[%XlZjZ=[%X4OUN(l Mj%UYŚ,`eB V~j%U;fKK*R4KJ4 *dKP+,R+ -,R+B"J"fKK,K,B4K+y*Y4K , ,R+,R+4<P+>LX+ke,B BKu+Y[ЮЄEm&xhw&#fBC@ Ϛ-XE5j?xe+Ly˄Y Xt " 83ʝ{[j\2dzZ=3ឱ"l 3|H&D8-. `awB:5B}+\H?B({'-AaK5e,2W`z|`5k0.0Ljc`Sq GE`^yt*b2d9=WE!+qh \q1Tj߄CeBnyАVE!C@v>ʜb3X0aiV/[LXG0d,4 N`HJ6 K KZf+-!1)* 0,՟` ٚ;Z+2^ M|||T>Mf,%sZ<^+`|? b48AG&/Wo*!r₫uX#U++<]2:SFjq-鏴WJHAϓ`!`ϐ+=xi,› w3 Xt{ bpL@?'`co(UōlѬAzyv XOz h8&, t@DLǂ XNF9 @0,4  ǀ ,Afa+n XPu2 J8&,l氚ay_e5axTŦa&i8 X`d>7#XRş`SE\{B؁i#Aa¾} sv債o!k!kx`ccMf,6Z|[G xQv:C`2d`fwვV,C[BpV0apAEmQƙ@\&389Ll `L @x CGo? }ĖQ bA AuuuY{%Wq_-L/I Y" M Z[X,z$,f%y*<&,b, Y;%SBUA f_OSoa]8>:z$wsVXzĖ@ Y +?Te,,4 ޚ%֫7Te2d,m aSVgtjw&,Al ~Є!ki%+CT+}y;ْ*ْ*l ~p6%+A XN` VO[*,\ѺN`݃ g*h KX҂E >fɱ,c0a&,CLX@Yu`v`9)XQ`隰ǰ,˙ ,Zr6Â,+\9 ,ErB,ٰ˹ ,Qr~,g08{{*<OWje2c ,H[w6- h,sZGW,EZ-afpwOiY21.?)A!kNM)^} x װf*\eu |sJL%'X[#Il DxlO),CVfͭ*^==UaӣAr9ԭ bZeǖp$X667u2AҬR+l ]r3E-afU^H-!6fVY|b1`w2gV+ɷTLX,CJKP+BPŷVC9rWY`Y`ifY`Y`ifY`ѸY#Uj%XZ!XZ VVliVZI`il,B R+KdT`a2X!XF- VflIY`od]J-B4KVJZ %UlɖT 9%[SRVlI *R)*B MҔkbJȐ),fx͊T IDJڸ_ %Ur؋m)BB-\,K,K,2K,B!Xt51Xg>IENDB`scikit-image-0.9.3/skimage/data/rough-wall.png000066400000000000000000006022351223313777300212310ustar00rootroot00000000000000PNG  IHDR& pHYs  iTXtXML:com.adobe.xmp 1 1 1 #a@IDATxDz%ə&2T/[Y=5ܵnLI>QXGv^OU?\%!^*ΐ+{|d)ѺӨn]nYԌ|X|.^嫔ڎIN)qPܖ,.0+fy_.se]w^:K q{Uk.XDLJIӸ9K*+ׇ\$ӔyX`xq%(GUEņȾ{1飘Xh $UTJ62oFSo0x6Y؀)Ȧ5Yy~|1_j&JY7yEHƴ0rF?> ẏ&]3*Zi]'ˆ r>\WPxY݌I~xZy=EE u2Qw4s5Vw+=z>$~;NDgD$pDaT5$ㇾIVkcז8_vP)E&jmtqIH0p%iݓ~ywYt!g eN&JYRdIc,7]S, u{nz O8d3_\3r_Qu4K)T~b6W36Q6?1ֆ/<5bZĝ&*UHŴwB2J[ Fluh^Zy gL1XN! O|~5SQZd>%uu7J|,}j' u3~[JFM1Z 姑-b)q2 ,e'4΢0';j.Y*F@ [s_Ka})#\kS9+(ݾ2W2"|Vy$PyD}JB76G6Ԓ^E>dU@;9!xeM\:(Q4# Q֥WKx*pn68[zm# n4ogtl)&K-b-/ d%;Jfs'(>%V)o+Yq¹Svi%N%tv޾ 2эyC8Kt*(>|e ٙVcS!%c%Mc̝V); .$Wؾd OU:톪F~+${f8>{.Eb`BH1H|,#@If(n/DyNf Xg( &갷;L| d&M+__2 0T6"BF0*n~(O4fZD]f%8bT,K^M;\f!CYn ,߼Y-wuWb.a73 SI#JdSUcx@32A,`1v*M.)86GTv>-|60+獉3n5kgG|<G60wP:EW(߱_"۹!vFg, 1rk6;:=)`9)ЈS4"Gڅ 5TT & g)ϫeКdF};BN#^Z "RklkAQeG5EӝuON"]/A(nWp[ۚjpI_vN Z(Kiؘ1"G`'㦤> _j.P.8} pҁQ:ٗ |5!];ttq*t#ȋPN8nSy\~x|NnB (@>GnnV !LpdA' Txb7Q7 `KoE'NӃ /W#5$6tc:˱.zN|Yå'w7t‘H$aacz'v,hR<4g֣:IE '#{~~^紻Y T'hBl vȮdІRj<⠓BMGšR(0!D%7͗)Q "|\"g̏?r/;ѭnn*bN <Rj%ydJfEE I0 u}|sR)$%jK!qH>X2Y.YNQo8pedYcA&PT<l %9=TѶ3j9,"`i6]˼ôK#7dX(c̩m"@C4<\b0 \2*BE^IL8h͗+YogC!bp *0!mZub1-؞K1&|TZnyקI%_*`(JGB0~ -hM"F{&R.xJ/y!$RnE#7b1vg@- 9r9zxi0/OSP$: z~Y%d'`zn|yMɉQ/G1m@l7MLSιxm}*gq ӱus;&Ii?WkH6b9Z{Zݷ Fs؀ʒ=lGӍp\0qޅ^.8(#VN$@QT<.~˰Z?Qg:ǒU L(D,nvF^*s$#zpݸ$'ÅރdX7<5wߕd!qP7| zȀ:պqs Uԩ{*]ԦrlF{z|Iz'R-D\׻:kj WsCQ= 4Yi cpNOqW\3Kx?\|9RyISb1n{TTR)KS`$HN4 y4_^ɠVʭ^Ȣ4̞ ~i_݁Nnؕ-Ӝj۠:%+lF)m׾v)/ȶ߽^/vޠ"&C%(C!js! mһ[JAh岲owJOVBۣQ,qFL2Zc5ήQfPu]\z%_2R6 ěƇE'sEAZl73Nll؄nYYA#55 N sA4@ۊ5[kqf#۫~1s)z-:OPC,"QBѨptZE&mRKvސ7,J\iK(Zrcf ' Az~MIC 7.% Av?:\ȾIGMCRkCS׳u䗯 3[~Ǘ'ɚl(nM߷N9rքmOR>pAEN8mFv_'WrL~TI ,  _d( UPõ _} B=#NAA@Nlo/<l8A4Uv=*Kd@ HC0 ǴhPךF^9R02yLtm5mǠ )E,4x ` AlbF%D&1P&w=_ͱ`$L6z\ȱ ԡ FE7K&Dw?|_8)o8P`DN5ZJImvftÂBn<{`Vh뾼|f#YEiK~ <&(R2$Dayg]exrQj}`dJ[C3܅J3hLڠupc?𥁯S:D}VG c9|QdGI6m&tdFBDcw;B`} f&s9:abuqYxpJ*P1ˌ]|r#-;(B!,3Or=~3]%t:?5RѐEG 2؍$BZzn/  ,p8iIFC䏛!!' C#~o Eg0 X@upQ?aGrJ OQK2bOpX e\|94Dp10Vi| tC N(:VQ~"]]ڗro-? khX3 ޿|oi@ְ!= ${',>ddus!qfڟ鶬 ̿h'fi!:atsv/ͻ,T>}pXq0rMrv(* [*nz?}{3I8e& `@KqrUۏt s/}r:wfQ|\!4lXђF{r^B7~ R[D੓f@Q,YyI@rP'pT Î5LxMz90nB%C.ͳn|.zXW2 {%l † gVМfDDif<cg4'n =7D!=Z}&S3_v!3@Myb>꤇!4v~Fr5N_!YS᤾E‰#4t1`SpFmI'8B$Bb?лyJ1Gni.7c9 NK ˶}Zɔ(eeP&cR^{V<+6X'Jt/52 /1Ce va&lۿ-D`10AFm%R -9MX/(BSr)&մYwc7ᘂ +QW(K3`>/7ͯn&fn#Q4ñ0S W~Gɂp2%u3g}\{ B\hC-Z`Sw={/4\G1~hoָۋw]X@Do6.$Zˡ7}hXTp7z= z& ԜdRQ4 mn۩4]ps44 Pɠ Gԝ~ dLy'QbĒ>KgG:`tSSCf-1l/B\e&V 9^+/]GK': *E7Qйf 2|7N/]AZcO3xח&GBVG?D:xщBMè{`?П|6!ou{C`'Yn r_ڢV-k }yu'`? {Wu&]E4 ljԟɡ+I a,+ĝ5@=G~!m!TO_ !#ϻW7 4RAR"DL8v@"6Dx#^0c 8ZjA2VYƭ]&f! VA#Z `2`S;fRάtIGgєğmC:`qPku@sfMg<@7V B޵[H%0PJuQ fxkšR/.‚"1F?,rTN6Z|(`J2:T;"(s_}ZzχnMXA4m\i' l:8~SdGſȅ4Ds QGI4l *`lW]މBa|g y@E @2 x=sD*b Tȯ)2M3Td͆\NjY];A`,tR:h~ej= grڄ[ CSehГɞ20&/1iXD "s8 C f]4 6e F2;%(/1;v~}|>yD̍yNw3H婁f-W*-8hWȨQLFy UI!X5nL]}T+jDT%@~Pm\z$(igl@":b!a>|mSݐU@KyL)qO6:*]R8">`C3?ě<㱌>\/rF FE[yE,KX4GV{P~8Ygo$PZJKM~ >b2BٹG`j'9䈡L Bdjfð/4y7 +h,"ηUf0ض{h D+u0MقFOK^.F\,wSVD!sVaIBIx,lˠGBH 0%CJUԅ$8Dby͛hi#/UQ,A Ƕ=8p'4<:i݄r2 H"z#[ɿiЅ̨3~Rw﯅o>CCpq:|}OҥQIHKG Nɥq9^]ni!\5z%HtaHH?|Gӄ0 Q O@:᥄O ;pH&hAnqS0rn/ J~kd2MP"lA|J2}q 4@>DQy:#w ̨;$g!r%5 ½=gfyDG롟MQPC(CCaPB64%" 2$2GBf6^$:ZcCx\AܿS?Є-[ĩ(2; am2=Ҋ]ؿs{M 1ZR?Tnu?λKDK5[!2+H8$O j#}z'wk,[!OcBzꮏ[y-;~Sh*RL)J0S/p6cẇrMFgbFB@h0HjX2x0Q'3?F⫈ @݊֍GA@,h~9m*w2F+հqBH~/0GƷ(9BGuAl :(T+A9 pfķ@=:@C4A$ vGd^Lq41} g'зWHF$yL>/(#|)L,ۊWKTX+ryfpDOWS" |3$#xF;Di֛2|zyϻuE:KL,H:Hi8?#ܶl!$ćv`$7͋L){$.oL$f(#l{B%Ff*/Gy3s:@H&>ma)DԹ0Fwݦ)f?ZׁQHm5j6wIs(qXB(1o똨 X z}["|I-yhS ^,{d:< w{EqtǴCO95zt}iYQ'E_SLй|X%aM=bSeLXgkqv5mUi0|vqH)zx?/Dx@L q!XpΆ=h 3P:!/ I{s !Rd/Aumt9~/jh& #FJvԃiӡOT/8!_ @bA\E@"}ZYC];/n 'l 0#B+m Q =0k *B5k ]гH*yblVwoW\w ܣ_`nC~<_,?uO1x%~z4&iƍ`Z1<<"_@K8˖_X a4>Ayկ%b]7%^* ʾCt {Xx(_ *Ų>`<ϡ_϶ew=|΁"ᷝݼ %&sH Et䞱dЏ[E@LWLE„@/*/:ø  Άz-fyk$4[cT=r7 %a}p Az Q>uNTK!l;|A\d$n|b(/-Bt& bCWD U[woRrD|4d40gu?CO'$mk!XtD-1=mް2Ӈ >.*u %Vxŋ !y8` #p~=nFMωUTɤ)[NQ~vW7]7uU. ޲AV|.8wCDU@ Z\&sϢ'#-鄲L7Z[CT` !6aBk,G%qd*(itaX?i4[StpP#t j6arZvCpMB1c !连JqJzq] ǝ1RDaޗar΢!%j薆}%lqwWp!Mc7/5Hz4;hEHL9;w5T&VqXCz̐`Y6o{g:}5&^.fذ_V.y:CdvmN?$\S^k>e9%vȐQ+ŝ6g~SO?FrZ&Q`9꧗Ӫt/_D_F2&9ߐO0`ٝ։F CgYm=AΎ6!b@y /1ۂ:\ ѹch+'>Au `**dAc{qu")[1(/p 5c qEu)E ;ou.L>|a7'xfb?ߊN(sZeftCUi;2! >zIYqWQ9"|xZ\2 2>tޭ.%b#x>Be6A<_®i.*S$Q^`G~G(,P,ob BKFw <4m3'w0c5孌gPȗ#wt yuZ4VX.$3*{Bru9T3i=qlB#ar;A#n2 %D>\p(Um< L  r Bܰy˶J$6@rxd@w/kDrUZ%vr>! C $$e9 '\b4!|SEr81#~4AzOY <;[T²Ya~8qAd*QbiGptC7!^AeMn69,N~F0\nC0U?!=)= Ɂ|\Ep_htK"YNiY:l--SExl[EyߧB:(kt !r%'7е)"!zug9!8(j =\4A$e ?,7ݻ}PԴ9R@ј3K.=l9&ak| cXa ]bðVWAݙ0CJn;< |1 &5iNP2qT\T fYQ#bB8>Zh!ƓHR̒.Xqh8.a?i7eG'@uvCs51L[-];@K8a%G(G;hwf!JM) BcB <3l9P6- wcP&|pJbXnslKċ~ac&[ݫ $z 1\*( ౐p`{_S2}Spodχaڠ6i.lW G]@K#t߾A//ܦ~7Y1t^m[!S<Ⱥ#}WK>.aw)rr%(eLG oJ/3}G)a_= xM CkuP_Aae)8 P$ z\BЖo?a5/^]$ sԯq \(0!PnѨ9)zlr^߷}S~7ñR\J%njfqp8̋bN$)'K$+. ށipHyO g|eNL+J7, b"$k *S 9 dtB {2BS4`tc0Ӆ8 L[Q0`M(r' J) flK6{sF*Z  Xt3T Rj[yK^?$wW_s%.lQ]KeQLJ ZsIV53d0V';̜ᖫGWߗWUH~.g؜+qS "nLl/g6dYN4O4}L9&!Ta6f2YۏA_2 Ӏ ~?#Y_-\\&.9fk@OSw+d;)Dx1+@l>}\զQYVwg % 7 2lf!!~]➹L?+ a| TWqpv' jZ410$Rw?H%eR.3\`eh|xmչIy,w) W2AGuTᥥe8+~ 3\J g  W)8l0OF+ +V9>v5^Y8x"KQkPqꮹ!T9^0'K{hOOl s(37tloiU@PpY 8 5-%#1\XdzYtPĆvh!ѴmDI AB2rC݅/O"{I&L.RZ7MdLc?X5  ͇ w:>h95%宇CA- 0kA>azD2Lbe &œ|Dh u@o1b\=akBM3yl70pG l01eƩlwt@8o9u;h89m{ X,F\F́tp Jw3eqrMQ%n   2Vq-;\u6'\B1ZP V7׷d(Z45ƟzG}J 󝜿ߧ|zqw.6 A wO-쓋؄H&\O%N$-(*"Y8+&i.-{x̍FGm/Y 4y*A[8_V2U g\#Ix1hE"|:G vPC:CPpAbو^HD]蜁c]@Ts:ב': FQqmq3~ ގׁ1o$[_s!Pe FSb=wmK+s\qǓUERF۰a_ɀGZjj$%6Y,V+ϜI(k}ou&$ؓ1@IDATO6ۥNDE"2xg![eڸ dqѦX6aC3Ro3k,Z|̜ HQSfQ{j]1 ",~n`,BBj?Ղi1.lgh@AL] i$Rַ A)88$'~6O;vR&jdtTt2b9SǵERyxbF.IDQ0[ˉWNhH.QbCPs{L2C:/ wZx別0c(٪BAQ,syFߌG KZ*_|~b*fs>|!F;83|Oȴ`i_~7/#N{UE09UMO}CĽZ}z@5TA@Mf_]ci]ݔb/CDc t ?ș.JG?'|1፥j}yZ+ lTiHO`%y«]LEuNAED EsH4Vc;#͒it JTlԤm1X Ua]e!pVG-QZPRuص WOdDA7]%4SʠoUejQZWySqdc| AQkPYD|D,wVwI{-+&]-fR,4y c|ܯ?CAJtus9-hajC *,/s̈́!VJh-d`,|dvPEitS..7bOumq) ;D>PJ&G Dž)4C)RYSdH?fbD ut-Hp7ػ쒦)ͤ|(<&Hr" lwa-x<,hSn{HLH䳼'Xgk8UɎn .L|Mkl>MB|vXݣ+zq1|zZۃd-7U6l_,oĦRҀSUZ!\=hO+yn`W`Qc<+=WcJ(aԯ'4PZVBL0v`Fƃ]')Emb8*Mlႍ/nTʕ[ +Y^I`;`PÆz%,'ywP3AN@^݇_Yu{Mxirxg>")ryiK_8$ jhҍ>Miamhϱrx &j* ٫NvX ijHv~LK Z6 $VY5v=K^z(Bf{^K`;3Rjc ~o6N`R_外X HkCP_׿sfۚg,:Au_joaB @[UzĽ 1XIv=s9 ^,y۰ez;ɊFk䊗OUb͇(}b "CyS,Y@v풅ԨuÀ d]M?9=(MU/w7W߼YR)ߏڒ t J/ Zfbӂ.̱akh:l+{n2*3A?A zݢ1g#낳>Y` 9c"fm9X!NErmbbĻqRfUUAgj_3k~6Z9Zf/GNWқLS&pW'T s8WYii@ 9OH= 46̙ xݚBV¸=;T!l'J-#=T2qsyZ$=lPOQtFN^3ovS`doʢq hL&|h5 jD@ 6˯ohn={6u ܧCAF#I>5>z~@'T/Jl[+W}q:dN_j,rF['IzU@uO5ͿK`J$}V R֥)0PFzt+Pm0{VfhnhE(^f̣[@?j9pElczTE~5 o ;lNQ}~m4@\l̠;58<j΄K4jf|bO/٫w>n@5Fp0b̔',5 !3\:*P8u)#.@1]V8dVΝ7} DȹGʊf1ogϚzЗsIƟӏKӺ}tWD|œSL%lQX5PTx'ٖ ==|0D1o?o۽ڃ[jхQDQWt6vY850C('|n|PYo1p!ʨ۸pbw-3׭OG4lh^w\ܗ< DXz(xj3c~: &H=+| xj/@!dcJ_47K6!A9s[.:#l >1 ShfԤT!{w`:-"0g4f$9q G _?^[8>84 4)TGtoD EqM:[]a 舩פԚFUܣHdHyMBe_ "]Ƞv, 1qUTIT &vf zD_qDHs V;ۖzWv@nO զЙU./QV[gu0k"L 'ͬVpQ)Iռ)!D#l_fgLXkcǍM'>=oPŜqah/2" ?>N[ *MnP\XLAX\f+N7$U{ N>iy{MOx'a*z 'eCk|Arsu4dIƎ~O QznxLI$cM*'³U;t )g 8lL:^NE^Q_ivƑx֜h[QW_# W̐]qX2U)h0SacQbΤͿRQi3zw`j2MdMj<_ul)vbXF[>fp3ϠR&E$^S+LMHP)?Cv!26.C1Y1 {RB>1S,ͤڡq|D^O M'f8P FcR/0LZw2Hq0# I v6q%pM k!Q)3?Q,oMi{9j&3w@cBvBԨ gHf8$2TW7?XfJbAKg3#7S)XiGJhXCin;Boj_jy-{m=!ߧ3V uA,[00B1-k۞5MB!D~+sBn0X tuw߽=4z<5ns>C?&GѮG 2V/8P}hFQuVȶ5> +>XO:gM IFYdrQ11;4n^20obHUlجıVsCN&Yyri5b{]0A"`~ΰ)Mu$`\lCLbH3O"fL#hɲ;~J]1 *B+?ԍB! mj W]1ӝIW~OC¥8FY@ ~7|}Vvt[ÒRm)Wj6)yZX󥍚fV_ki]'[vk' M*IꄟGŠ޼a>l"v/FȁT6϶ޗ0CEyy3(n, M$x"mkheܨ{Wf1qBPD50I]g8' *Wqp,e0:\M9~o͓F(&C!FsQ2S̋ Sl?~H{cݣdm G@.[]Z"ʼn q[ͫ)ȺC* OAQuHe uỦXI:c,ל9s:4"橥r52 Uvy֊OThkz&̈ĞbKD m9V正- ? q:g>6:TE!]ʿ=uHБeҢ.[6\,M2CwcH 'R?}b.PZغ-#w 589|!S4&V|= 8M] Ǔ<ŋЧFuvc F&al>86.\]I!;2RhL[ىC"س,/OY, 3RSU9{ߵ ^K"E,н1 EX,ә!Ȉ939#^\ygPs1vEyN/mpSܙL.r*[ɨ4Qe؛YpRplyHkB! d@~Hp:"E[RPew3M\!$:M[%WNDy>Ñ\)4w`uR aWn F4к@¶B, '}e5b/}iP7FW^4NHfFwbӺHJHoڂwa>3T%/M.R3,?O Q8EE ,k? Ba'P1W@?4ؼrD>"a5&Aidq2vZbزU%gKknTwOm>%(Sx\$FǬR(~Ƹ7d,׶ɇ <W/< )P mLj䦫3xxE7,tU)j|BB L|.〝Q5F{VSaغ '1`][#+Xwem S<Nb`zFQoJ4Dͧ8@ eb'fm%/v2VIHexsU]?<4 f ̗/ ") OAN#+w,Yd2Ǡ9lQr:7vASS3h$^DO+;xJ_2%S%4Rz,`2i/rBSOX: ])}p#~4l余p+/M%d!.Na"AWO2(D?BP:sH~Ќ73EvHf89Xxg9 oe%1jaXFdJҕ2d Y' \EHt0c+p}-&Ӗ#sZF btutc:}jk69$_hh^ɶ*VeP{Lce+X ӎSYkoQd ZHu6YUI_1@lh]5DwzŦemܕ#hTk'sr0qn慮up"O:Z]h,Ã6 I(+T^ 6C>Tr %8JmM7B8FGJN}ѓH Dw%*+kDZyA=1__͝rT}A]Aͮ~3@@8x\9#9jUN{~=6: ˥ P@@= )Oa:p Fؠ8vk E:^(i0d{Vp#Wt!~o/Qm= /~Wٰ?7S4s&M?DNKm}L>3Pn.JV c"R]<{5a&8"Ɛ <=\FMemw/|߈3XS~$]5^aR~~~ :hڻDw?DGa^c?b5md;k , &y݄s|΅ Z:Y]s" 1vpQL%(fGa [}GژUf̂c`۴(9y@&{ߞU7y`b)`aa,E71$y=R$z uXً;p tf@4u'lzenyנ}0<) 5Y EX,u?;;q&RĶA'SnN. w0}0 z#(mL+2lt80 DDw& ~Λ110 DGm\Fi}O2" ё*'تBxI(D0KU'&Zp5X,hq\8Iz=?ҹ@;*9S89#p"[Ȥ|ъτJs)O[~]! Z zSj]E T&jaxlqOj ~8_LmiɩP3 W8CYµ/&fpFC$5bZ%JxtY<bES|:Ț|'#t`-̿MR'KZOV\L˲OԉC2uG' 5&Y ZܙL *_EO:pjーOԍ 1+9Dj? VÞ4Y~`FofL:9zu_}``aqY{ju1(Z#"=yy\&5F(њÿA+:E}eVJ&1> [n$3 ?dS~;|Phb ;FzM}EbB׾9< ePnAϘj6D9izBjV`kx )>FWIJo?Iչ f# hpa*Kָ`6 Qy- N v2/W'Շ?{DNEaN4Dqf(/ґh9d( ]xrيG5 qwSԶxUwqqZ=.z99Az UN>wRC$3_)XDO3/ŏPz$N'-FnHM<|c#6M'0G/=DZ֖g[ ' ?rx(n1n ) @~GPȈ>gTFD3ĘOn'hwJ#|x1@{b@ \q2 @)劻3uy]$ꦼȾ=/MF? W$j:M^&R&C9>1c³;ܤZ\ %RCظMwa`hFPgm3=xS-@¡ e!ɪMPTS\d&9Y$@b&vWKn5ٷLԌ 闆Ԡ@W,#0sN$XC9Txy*M@Ƈ+d35qwLfJϵ9[ A`*,mlSg )ۮVφ@!ۂ}VFMlHJ8BgJM\'Lm}VPh2"X)*_DŽoN gX,{|75ٚ,!dĵU; [::X0?YY7= }^*{4}L5,TeRpQ.`w/֐|;9t]EJ~yE& 2 Ks>OՓ$̺k·Ä:g)KB~FEM*-to9b'#萖 %#n<~NGf/Dr!{ǹ G䚈iQ_e,.{2 \#MZ&ܐb|@zk b5)" #^/)Ç'T) Ĭ6sJĐ{]d4 ʖL}c 0{CҡLah&}ɺrf;`68Z$[d0=y' ]s#A Fkf #le A$Gd؃|Y>cT ꗙǫV`P"* fQ;šPhOZ!`͌ybs `|\dsӋNI Pޓh@z B6 kp/P El2e6):\(k2@qrsY[!K-y[qM ]LXa^2+cf e5|^˥__x5J'.vm?Lw#19c H6yuJ.!Ҏ.lܷ!}7f:S Y3&SCL9##.II)J72zp'ߛK¥T؟goa%p!B%ryL#2!M0I_ޟSm4AW Ocud<"+ !o=6bjTqOn%vcE5CձF Ζ% qT\P(5 YAr>Jq)l1fXmb#f# 3-IFCf_3c5B>Fޛh;vIayYp] S,7JH7%bA1KIvs ?[6/J`}'uR=ՠ8dyhRO\AS/yhqűТ̃>ɀLVȏ~QZ :]%(zN؂ScUk'k4-,}aZzBcɋ It(h(vbJie m"4>5T󛹏(:bR@'jpըADlaP2D}ԛ6|fDtǀ(S v2} L)1-߃x=QM-Qw N1N+0}{IpdϗGUVd>gmE _rMWH ʇ ogyuC >R+OGt"N^pEאj\>4L>#y;ŖڭQu(JUT T;&@'56dKĉy@ #P o4\9 a|ߜGxA\ZvFE*oXZG*:2:)3SveWh&:;w&!uZV1c$&!`y3-P2f=p ;i:s[W#(|[Y00eЏ}`@8=tXF(1nV:4$/=e2?#"K/6p2Mt1T!,C37w -Nz|~ˉdc-PLh}FmW.oKhHKӶU_jR[*ޛ!9cS,Iy:=Ũ+"䂠>gw#yu/] s0h1"YXwY:/e 2`$~WEa#IfVRX/{bB4ƩWW6?2 8JI؉^Md6e 䜭f^r8DXˣ&\--P-*.G,[svS@m` T4RUXr;93 Zj(¹}Tqc"9ixox?V6ڕfE9L2"8r&ҞQx9!$NwnHvP:`+W ^@Qkv u\T)+[ʙ9%MʵuEA%uf]&=+D ֖v*Hdye>}K6WoQN4X1pv 񚅔vI%[0r}M:[Ipf'~Qxhq%/XU&1C)a |1^R֙Nҷ@Cw?٢vv*zF+;Ku~"MNov|٪Ahaſ`!tMgɠg32 /3n$GZm.O*2^hO6 Φ[N@&/,Gm7Ef6&v7 $ө9bNRfG3R1N܆L_Nl1$Ss0"`;-.cb Z2*K$M𭪤ePRrf?1?ZF0([&Ĕi"\RH="H@>~bd+M} 5Wn E[FsϏ#1ZG\pO!bC)v>|W?R'26%TB$)y%mNJN pXMϲWu9bQ&0</,{9#+V` SrE2T[0Gs̶E zN@,-3Vbf}(t-܁տ)Jiv.Ի6jJ-i\gVУ|#`\a"8N6 Aw&UwB sg_%weBkpfPIe,G(n=Ty1psc^iL$a=6:; U1mOk8݌8mҫ&+\>'Px,hA sWm~HA 9(GWY5 g\"L`aq2 R"b,c͂f!c&<J,\V{2797" cD%gZG\gʉ:1&wuޡ`T 2)rTOk5 ona9 SM+@ro-'1vP._@u_wr [~9aKƋRImCOU&'e9~e i+dDVJ39 [w&DqT6'O|RYT'rj̐#9l`(_ܸU%ёM$Xg"iCoB Rj;H%XXs9`Ek~\eG(W~0EJ3 !6~p"SF7ı0*AK@IDAThS,}#;ל&#AOÅCU%pZ?j<6J RaFdT,D/3~B/D ~A@"OHGVW h1M`-MXEڳvc)HϺX3vqCJ^i߭x|ZfadN#֌a1NFQwr:"_uBz3'us4̝α}%\sLŜaoۖaq3OQr;d"y+H˥%rG9cc{D@8V ہ;D1˓B]i; _"p85I4mz0To-U"XmVtcu]3FrW į!Īf#kM!|ک ә~cs11Th(8$XzOX? $WñWk2'MFB/iLy6Sg "`uſ{+;*fxfEAzkCDPC_./x =onD_59 byc j4]l ,A\j7)^9N|>db)蘇p\XyH?x?nQfޝA!m(! @p( Sk (!*kD0 4gQX^v5e75{&\Hf傝0sB4N941MA_Um>Oe I]p堬#W1 V̯Ş10m94AW=6޴ld\غ䴘0}/=P+NڹѤ^3r BlQMrKł$Xnػf;1bv<*茁~%Z 'n@?/@ /Q۬S%Y3iR9~̎%<7*kaxj~L+"$#JyixcNe뤺?w%1! M&V}s_ @c@3L+Iw}$^bG@Kczˎ>GwDdchGZ}X} 24 q6Y|쐘 .1\jeMWg]ixG"*óft( ¥~q3soq 9)}e?ao1Y?M shȑG/0Wgم9c"ۨ3xL4N 4;{QKYvnCCC}3kD٤g|, @ '^2r],vA?"(@(fW'm;Lq?!#wm@d37Qs25d~▍]MyR A!!Ġfr=epyn =cX/S}'D#qeҢh{Eq/f(76c:ˁ9;|,OJH9i{6unIop:^.8PȭJ}q`4/Sx*5$n! 0nDx/KSV@ y)]tZEڢyrCMrܔe4/MfUpx(8j:H vB^~c916859hձ4:ҏ?9+ R< zݾD%o]NQmesH[Wm'6^tgnl[h;q#xP1A.!P s=6ޯfe/._$.eiAC'P(6j>]!lkϢU]^f7%ZMxݶ>-}fN E C ~U^2~ W@:0SR5:d3 p3vf^ɦ3 y0_80-r@>֩0GMnR_m(YI`D:yA2hU7gH2dqsz˾yYt.ck:yRByufcP6n zd#B⿤ bNXo{_/#'9^ M9W9O!%y@vlSSbS:Z8xSn:- 9"5\DAg@GvVllTo.l75Dd :1N(Mt$L2Kw铷\_1u:8S2(5@$B`ك!t(wQ^ҵZw&66p;p.yzG{ ۓIx #x|l铓 Aw .Hfa㕯t]Oқؑgzۉ$FcX6&+_1lc0HVK^E{5}eI*2-HzgRa'! O^N8>[+,Y$QP㙶Tfbr0/Jʉx8KQ A%@42e.۟/5vndcuw7O7!xЎTfR!& 8G430_xwov3w^Ł W@U4tz >_lnitxW{s.wvp&wujd"2jw c[khZOC/ݮ/nl2L4j W٧ۻ},a#"7_NE@Hr,59$(?C](UtArH08CtEz+",pa󗣨"FFOv!Bs8/# x?jt 24)GBU*u.)~W ]XP-ABqܿ8&хO1paoHLqg$B׻HoOwrF1=Pn_f g1t@ɘc$~=9c`Hd~ToR9" ="v4E|vo("=\rU;l+7NOTK)+@H2.MobJȘxsctכjuw$pi3vhnZlR[5$&I0$!OHfji~$ -+9+JN/LvhUI" FD/4LCVrZ[ T2( rYrgG>ZnQ(@nH74tʭɼ$c w,I("##9b_ˌwk}4ZDV\DFm ]mu55-`A"ZPLx]+7y,IDT*Cb=!̊OÂ-\6nʂ<e?fouaz>!ͻkSpP,tnS[\m(gth2I`OG7'7̅XkSF#2e9)@iD "~B߼d'k,r&Sq My$6ٿUWKbQDҡǺ?l;L.w:\t=,4fǶZ_qГ;kkkwyn7fviunZ5hpr-2qxx>ۥ= u^YJ`(.AK鋞RH$ Np8ؗZV xLV;@pAm>HX]jQoyʨ66}YC5Uا0u0 q%jvP~:|RQn%ը~'Q H2 @8QO]ST7*eɶe샌cp+^!6@ؐ@- yƭa:H@|{snk]QF#*ǫ&rU,`Dv m,Os-_"Ɖܫ:Qp(1-۝u?ˉCRB̎FI(;A/\[Yc PN7|-?fVγirlJ3:?d 9FūljVb1")AYt;d)I#AG;ѭ͑wޅh.k`qU޿#J,"-+AD8B^~=3B]{N0ҟs4YA=rW hg[d*o QUJ2Qz`:CGnP]BUh7_J Gz~XIg)tIL$.eIE㛿DIBYk)>KIBolA5=Oj|&EVKNv}Ӿw^h 0xLd[*le*,C(XDWۅj tHfÊ b֌ \e7!\J1퉦i#/"+ j‹+/XSCz]TC(0$ðGU@OA3i<4\}oq-CqAg.dhJV[벻}/NͻE q5m gPkat*!%nZN%,pg;QxwY3^D*~'ImDS0$n ~gЭvNZcAFD_ VzV?"Y#S`A [{1Hvȳ/h cuݗFP*p6+nְHW-P\Y۟a Ii Ȇ } ' oyuXd,hOj/OsN cZ;WB .ݺML<5 dӺ$рYnWSK`ޥ\݃a٬I : n),ӠchGbWiz\?gRഠKsη1M {I5F+E.Hp9:oe+@$¾b\(]YbXKȒ)H#Юh- ^c_ -wy- %,CD<>/.'4d_@0pΪ JFJ5o냳>FAvWjAJv$ 02[ ⼰1 g%.~RO74 uN0aL֟C-,+- IfL3b~˜i]''q]xD-a0wsL\z9 ڙxd'(cd4in^ I][28S0+ `3Y]5o~|@̀f@ dq ;/',K#d;6Q>*E Yv\21c1q@K5x(ҕwj78@1ƻٖmA]HgBޓJK ,nS|=rJNe rdOՍal{c<`ϓ>*0xfs3ɸ__i@O-㗯#<ڔL񁚨foӝSYO=Bmt ڑ+קΆW󊻊 90|oݏ!&ƆY_EHk'ȃ12^-2o`ֵF0^'`$GEHd{۝JA:;5H4ʈea'5m%sJÐĒ^s5Dy~;.5&ވy$AR: Ye#cuً @fZ;,> J80SpL`!H:c)PȱA~7@ܐ9l[ >LUEIg„aQ  9/k%r]wi4:[ê?(aU`q5/ M^L2`e-EbOt^>;AIX/ +zdZ-PI,7c! Z:_6Dy\b36v8-HM¹ff!: (Y #7(e@R%%^dAG |,*9եBٻX|$,$f2k b2*u•/|݅HdA^0pFp'.SfIsNl#iW.|+'TY#0QuJmsjr^RRΞx^=JSP Kݲ+*z?C4ԟK,]0.1Fx |25к>|=47%۶LMV_bf]e הN*'ǂKXQMDW{lӨqlK0w<E8D(nDȽIwAFYpg5*ˁ#as3&iMrry9u 9s,$:w̗0{Y'`N+=U=3o"\*S63 b97D%".Aڤ{ s}vMp~R0Ӷ.K%Y!֦>\cp-&p5gd}m3Az"oQP r`ZΒDޒĉ4Fb6]P` - qN35+q8PҳfH7';gxyɩ34Z-C4emHf)S gy *) e@Dn4`2Tϵzmaq1Ihn=kLD.};u_KUKhLyMDjr]x˜SV.L Roy*fs3a*Zvƾ%ħ?׶4n"'{ lRy,7{V% k%3Vf(W2E)b q+q:  ydAl~¢HbfY16%.I1- 0 ԤrTyѲIVsgOCi e?7|Cmw嫦!i̒%\T?;9]vO_bJcf.^l6`r{t|E<)ˀgRngҶ`/2A&\B l)>1=jH2*> nl埋7hC^B-Ut[P@wh-;"с"SarDw˞P#ESt4bMd#JSGsG1%[q^?; B%]8~ߛh$fI9i˶alHQsTp%Ϯ?3 "fUMkÀ 4AFd_0AWELpF&J}{n Lr悔2_=;1&ᅴƲMMZ1OKgjgWyTZ^}sէv/fqq)`ɫBFA䛉'IĄ{TJH2R۲H1*H%U$ahm`W_ q#I3x$򬼬$նgGpVP/طxJO2i!Ġe&@aRl,UҗWbQ,?g ] Bu7Gl17|fFs<妨<@$2CKTo8wh!az>/?j]V&HٱqԿfT3j:cZG@E *v!x9Xj;G뮑o77fMkE6/7n T+ &V$!x֎_QkHl ֋=-X. &^?G%ʔ-ͣGv_k?PJYQNo><B!3*6aZfgҙ\|CÅ:&5ɁfLjպmJ56 RT=oIU e'\ٕ[Cr+Q M4/Ϲ؜t%"\h+]=*Up /hpS=x.V}XIw%l/] B YHK )[$XOř"[?쇂(|ep94L17=ds>N,܉E@^hNYяpTE WCw?0%MM kYtbϕ"tpg0vI$ eEb$H!ɓڑCtHt9Kȕ N^GZKa }&v#<]dF{1Ù{t[(a{ʼ5YsiC ugcꕯu0{&=]W p0@3aDx}ݡPWtM7bKf ލ[v%^g,#_Ani%Ҕ|+wwd[8rB BR LˋxJGiH S 0Qfc^,I1['%Wz4b:A]mgatFZy޶*61a5bi\F;,>+ާD;i,L,9߸-=T Ј,j\ -F#O%^iyt-NoTD4[ìhR%7Au,#ܠ56&`|\6WYwzR4G=#9?VHz2+[>=$\|0B>!ƙnÝ(1$#_Zb+1Q9l#dq:)rBp ט{dz_UQI!OǏ"1|UW>S 7Hq~Ec4\ 7 0kW F燄OY}Y!ZHW[G ]3n:bh|4bvTdc监蚡AB_{3x*% }R.56wE%PMM{vuaNJe6#CVAeFNu)qp*q{-.꧘ 8 60A-)+{Ae5 (<>#"9?څc=a8ښ2UttAck6CRqF -A{MgTN/|`8`Z:6 ^g d*ӂs y r΍fq\,NˍfR 0@Q+|2,c ;^"+]>=P:aj^t6W 1*1oX6Mfua]X^9ܠ̐; " c`-C]UmI®qI*0h'ri"`r\]scOwn"I3b"s`MFS;7NO򹃷PIz&γɆAY6ji ! ?,U5r(IGC =*(82 JI[Gɗ$NbފXPg\B;Ra14)** ,A HC2~"]J0 }~Bߣu i%0Lw=/^U2r3?ydoUvd\(e@Iý+r7%5Nijҿ[eL[6g|AaJbv̜<"D#c1Ssc:^0+*&Q-(\&l)$ݼ֍h#=z<.&eYx}Sh) TAaW;zY FDuKV~|II#U7Fm=SkMvK?.ua lXn<5"' u_GnX~Wl,Ӟo  A0M $NDg )@a82+?_Z0-:pYg9)P+muaU ]V>CѺi`aH ѼX@.] E32LcƟ7,cFOyD[AUV? % m1%b]K%P`"}(|~/g% hAzdLD!"+N:!.qfIb'}yh-|)@IDATg xXC@rcIR6'i9< )ٺG<̜fO0ΟwlWQ zә_HsW HWy iPB>a#񙊾~~pقG[5kHj|mۇ.7+{@H9`/a(Ix9deqkFޱ;I/!>cSݟ5N:V8zٕ8pbl$~qhYK'v<&3t@,E=f)m7֎_aSGȠoYqr0f I5%!3\TdKe$o᜾+W'{r:SZ?CQGȞOH968u5G'[8AQ 섐ñ[-l.wC ,J(BOWa;;Rͳlfe"1-B ]QTT0011cc!# A81eϋUiplqNFùl<aL?ʱ!,儊 ٮ-o0qK  MB^ dzQ S,eG].M0sA…TUW됭śL;uoq s!o E,b /?n^giNԑڎ7 ȨH__sJ3 遉2"&A K"0!-pn_Y-X 6H\/ ;SۡɬWWuL**0W#t%8f+h+j/CتAgUYzZZD43yo&:53e/F_r*:4mqp" b<`zzţ8]NK8C&b}6n/XKá+}Ah0B-LbjlǨAN:)M Mqrs (d{þzDc bf? =M.kq<1WTJf3V| 1ll.Ao7<!XMxk>@j osnJ_cT(A(a-$$bE7HlKzSI+y(IyUv!&ʇĠqC[侾]2eENaQ2%<_*2LNYߕIA`k=7 2լgHVc]Qcx& PU 'ܬ7JjNWR\o^` RBdat>TL5A} 1l*O3.y?6W+3k/&tUͯ iv j KDRģiv&|a%vKܝ L N-@óaك;$Zs0F&VҲ> '`lMRj1'՜Ag?@&lL2~k d2SasRP+`oD*\/C.ئ|onnPռQ>b&Ѝ)8K1FYLV5t+&tuyd,`LSR{;!y;YL$oMÁ5'^^:pl8.ǘ̓SG{ە ϢН)A ѯw׾%0}bT^~95Q4q#c2xBTZTepRM2mSuz\yzgXk$,pE-7N*s#O ae|Ib;.5 ɞ%. O~20fTkۯj#+e!Q3 an @*R,6*ؘ>fIZ0x^pSP V0_ZNGn:o0T;3z`P`7oI^eBߒ i1,BK9d:`[D$6Y5 1-[d*=T=Ë`078ujhBCpW-lŤ~ywoBx&СaU1.UJػ0ŽyE[ 晨bzV>-`bHa|j_^'F:}̷-+ KIq$Ҽ r?* 2fVe5hɵ%IeJen"F}~ d[거g;>i?  Xq_oWb)К3rUf\ $$jEu5DŽ( F'BC"Μ$3gloޝ23E߿apլl@Rp,AgH!92?VXwo`lᓒɌ&r$iH_04{{vշOLv#p3=؋(@~=)D{Y5gZWs^Բzx67ル%Ciz"c4|ZsͰ~ 'OH}"Jl, Ȓ%@9KC!HƒvOO.CB \ǒ{z|=(7X6L~I $͐/ DD5LP{CE&MË v7tD}3֤wSI)7\3?~&&4XGSYP5cvl7EL|o#1$0h]\/"x@XI_K IN{M=*dXNmU )(uN"ZFSPKkEiPeP;V̀=<"U7`0!e`]€5@RIW`W<զvϏOoo Tڏ^k=l d#Cmtف_H1$xB7>.%}_pmc#6*У=K!咹#-%c9F޷6K#]~auz'g]H aL~l\e2A0aywhH򯘐Ŀ)|B'i4Q@¦Ul`y`;X8\YF..KɌz8@bn>ա8 h#XxR(^!A1LC76 aCϏoIAu񇣺 Hnp%gXmΨܸ} ŠHd@ء: xx=K'Z޹dpUmQ3]Yٍ6V~}ҎPYB{ 85#U@ҥ΢N3ݟL| j-By:be݋I[P@ݼg_ Gf9J>s!sk@9(hC#-ޥ u^|\t@N!,љ+h-+g*|=K.hu_oȄ9Ơ[mrL¤-@m;zF<%:I.r ExGm2 -.iIޱQ1b[a!l|yuF֌vX٧3y\ڙXps=!g Zm@j3ط ބɏ|m+D9$TqU8 )ȀJ VE"r%})c]ǙΈE \ ).TN'/ C)nE(`~["]0t|nÚduuN8TRR*[2P$Eu\?#c #S.8枸y\Dͥsh :Al|,؛o.9Z./Ɇgm 1\Z_qo5*3`gb.J|ɿY5۝Zqܘ!p:[ۉDc MDT5')A 9:f5تu~ Ua=Ar~%j3F}d?!( تp Te 5؁ӏ´5kJd:>()ʮǴj┅!aZ*n NҀEQ :[9zʗY)>=9mP x6za kf#2n 3">Vy/ѯ+e;sSN,{ֻd/8T[3=:pV9Ėr?{uxUeDִ#YeIw ޝg{~z[%f<{B2+7F_|WpH_q7'$,6hE12s8$+,D-gZf-~kaU5k.?e{WdWx߄BneC5n%R@Q"|)0ȈnN;?1r4 մ_иգc) G3S򀴛*xx }!l'c:q 3*39,? DBi>}XWwwQlVƍ o^#77U~/e}!p</:ʴW$Ro. j_ Tӯ'+EϋvHLUyWF= k{N1x5Ƽ!;ѴMmLtK 8dPhG4J]u]WV '\\PFܿMwo:].ߤva&ZBԮp'nގ[C}quh425DQXݼ([|.ѣ]]`R-O]H@ H.a @O72$%TmKqhX2M!﯅ *5A)tr±QQv7+JmBMc"ڒȕ7$>"8L %>iw\xP˟SM8:h"F9ۮ kp}[z kH69vĨGLUB99$%'%̐1Cq&iv dR%l6`'a#GQj$l3J`0ň枳Z*)h5OCeG.61p0ӸՌ0~4FUgelle?*Qo Hsh@,j3|TL9n2edf\ <Rm70'=tA*"ZGBrᲘEB̻jaa;QmʬA0O.sXj 2X;S$^鄳d=8'l1,bfu_,mܠozkX 6lpKmjgj3+zanh D^ r\G"| Sj|BCp!0Q$(ŴLVIY!m,q?s/A;$™e\HQ/F{ `{KodM}䌁!ZlJp_z!$,RVc/1fT.u !J"+Qp"o?3h^DeNj${RjPt;,nkL,O9ec1H<θ3Cea?.FRLgd˂Dܶ')&tVd"YB^ZhDqSb4!Y#(8~,"jb6$6@4A^͕AI svqc|< A\Ů6.jcd5u(wDVx˹iT|䂲ҷˊHLX6^d]1:Ux FR~>P8!6 nYj0Nr5AZ6<2Wkf/^AXm4BUkBj]΄&T0Fn)r^ly6^;n.泋q2tj:l5/Y~b @ͯyi CSp#G,H_3F_q:/ T⌈ kj6 Bx Ȫ*6:ӄsURT/b((mKsMn*>h0Ĥ,8Qѣ?K"ʸFUނuEVg;aZ|QǤ1fh/{.g{M+aae,ɑ>'}J}!ʺAE-2DoQB8CE#h}'J CI_A7яWY#~3}|A~oŴI~XlǺ2)&Z5%I46ιdX;V9(P˫}.{֚9;lxbcΨYQ$&I85n}=F V@2H!˘T!C(g*?)DP kRۢ BۜH~n;܀+أtxS4i3TG0y9<13vWmV_]][ZGs6c7cCEKȓEFɜ0PCeElspsF(QN, cP% y ^d!_o|`@)UfIqՒt#O>H liGm;.U\JsiM4KX,|zؠ3c 7g~0}S KlI<ǥ^*- g+ XC꾺LJ7ܻ\,hӫu&TDFV 'DŽW iSD{`%Up.Y1p3#Fʡ_z1Iڙ`hʁY`BZ6b@&d]~3~d*YQ|Vߘ&EBvM{C&ډפ5wճS,dtyh1F$*F(}ы*Z Au={lp8[%5L& -t丘'͇Jq8@1m·|}Z+e}ThX0=bŁ.Xc4)O+I(+),mHgfK0ͺRkb?^ߞ}Bs>Q͋*Rvd`ʂbl>txDVE\ c'9-ѻ`oYj I]*v$qY˜Y^%Ġ^\A(G(?y0tLR"uӋp{qqӽLտ`U 48?#I<Z;9CvyZQj~VL63&̷9Dz;A`#]C-Bpkی nK[o;q!i|pšߙQ(Q6ҲA%Zā\ue~Mx]Z  `F0!$Z!g^|3Y s6))h-v̱ C8 aHjMS[_fpVB"&:! nGq#9"R$";̬vYVlj ٬LU'm|96䟱lӸA5fcG*VDYSFbG"ty614'x7)+Y`)IɵĜmIy';罣A( Qa+PE6G%q|`;5}9lXtB:e4!۔mm&F,#|_HJV%v8AZqaח_SeQigwW], ~s愴ǚ \?)˻ɑr虜&yuʣ瑰Ȉ$m k~^pBے0J\:XZ5CNK^2E官Ou~J=D3x5fIp.o3j *dqbgiY61L7a;L7^I*.09ģCC3oiq$R6y9:QoۀTpGKBs(H$ȼSRr "@c7N 9b?w#8qBbt񄂻]xSQݕz]6[.Z .Xo %ѴXjePq7[%@kMPsx٥RA_b9'KMnܙa)y̭5rM0,WeuǤzb %U񜯐Pt ɒv-p3-P]>"#FYV?\aOJ-Y2MJ g!{k#xƋtATܬ?IwKPTnQ8՝?KKYbگ,n` (<5^.8PO)ʹ?hxt{ T.<(\-uFh5b`!',qrBn[hZ7gYPs.TKLo?`V7-mƅ.mn'g(wNXo{//w}}3Rϓi,@ΔT:y↺c6vKCxo"Zފ3lrwaۛ,yp^5NzJ-d $ko?{"Q!K湯O/Tc캱=~༘wt dDŽqo[Nbǰ1h-C!wBe:yF!b0rhO0 Vv lrQZRﬖ2Gp3c;ρp N/~Aa=3z9먨.,rASFg (1⸱ĺ B e/ nonM%53-eT (C713Hn R% ta s~Wt /pY,дy47&Zڑcv\LcJ^{pLp`W3JA$X}16t0 ky} YӰ;e) b`3euJTj?c'@DlY`=uf4FB"KPߴVK./+d ~s,ыH+_{: hZ2|d#BA:p10W؂ees᡹()j3G͚u|g56Cd?KE V`\1\PĚ 7=q{O5Xi<4=|6CvL'fA[V4 ^H&qGֺF}Hڱ5̯ я7%al=]8iW:kHЍ?27>W RB[]{H=q3;_L &*6Ɛ+' #cZҘ-Q7([<J ;b9cILhh򉊹L+HzW@Ev9Z"!V1\^YG-ٔ{ɑ,7IX*ǝ *{w(8`T%o=<0 mfI5W tG Ѥ Wgsk[͸71 +j7+Bf]wZ! LG3oyFTuųמN>O;33= A (˿_n@rő4`ąhĕ2Gx} QҠR!n"mlh q~Q"3EY\ej5onB6|ha:sD\]}#\E1=MH% 4 T*5ɸhJJSwA0PU?,~a? !Dԕ%O+:RH,H"@JO<˙|n{C@ jRGo\/sҤײ_HP,<}^wH`z> 'ZU}sa]f Lxoח r,̚Pߒ0"LN&E6LJ*gC54~NAbE?щu=#oa,A֒߄ VWÚ̴XyēP.!K* @p2^cj 9tHGu+ 4Gy5Cj&ɑ{%F^;V50H&b.gjW({>#ʎޘk8AXSd"u  x#k&$b Z],9-v$0*M1Â; R94-2E۪F{Fc|a0W(]8?s2S7"W}|\}Ӯ3 < XDiӬW P*+ "RH^\zwU5)6lTWI`/ݱb꧞K>gWQ~ocSuu$EG8έQD,-+J~nݙ廉mEАZulw\f,ƾx, ϳ6ĩeg->݂㎍1j&_]51|+x{@q 5G8A@$XϴrE;^Eg>U!IeUq띔!r?| FtyxU|Hn81AON6$958fLOyQXɢxȦ&" r:ʁ.^,0@4sɯëa Thk|dHK"uX0ҥ,Ib\P3FY$U eӎn`NN :eOr"T'^հ,7 ]$ɗYo0\!x|Sv>k% 3z:anLk+;wɹT$QG"؄|[Cə W`ঘ," r\vA^=X]Uxp{LnKufi9.u>xj;%@AbMrbxWf'w+ ?u!u "J# g2?Rs!ͧ0 R@IDAT1po`&\ :TcW9@H9֭{e!Hg?) _M>)D.gêA=3>ԵGfW@2g$/]19STtkWoCVј0jUBhH 9rob(Unc#|8~-OuPF޵EǢ+-skGgY R,%> ѤRmebx n$ ZPPELN<-o|,Dp瑨F$(o p_uDC/PИu&/z00)~bP[W s1JA{/!x8@Q*6R#?]0BsurPi,!uAb%49c8YAqӆMZkNbFYD5 >EjrhYI{IQ?Lȥg1gp|bx^QmX@"𧟬vhwMզ)v|m𘁡Qr\@S]p*|щz48W[=%>l#Nw4!*bc4;6ә^$ֽ ֆ'Ul%icA>u꽫EKN= T>\ل"/\-1C쇻=cH2H$ў׼m9hbZPOhzS*;pXjm/}<ӴZ^{:+Τi#8G#4ϫ+s(x&-<VVu{3qNFFEFt㐶 5#_.by(˧qW?r~{C0o#{Y4&mz~Ky3Tm/70 s0)5Ű0;r0Wة$?;EACv>,y}S@|]hhymx },V%NgkDi<_&gI<:/ڳCn& F!`W] ~󴣵 ҟ;1_]Fw;zT (=#930٨JyoD4[.籡b%!¸6F_IA!C=DL]Q읃.HiVm`)-01O<[B:jMfc]tUt`F#ZeUd.E) V,nkc?U7=Z))=W=DvH7\bAz: 哣,'br9`OZrαKLN;5"v9^ 6Ē ~;J}~GQNbV ci"6/ǟCܜTִM@[iۜgd)^߁Xg (HlAl*H]RȠS[.z}P᳝"Dƒq:̵~*I֌yj`&uO+"cmapN>]^(]ɷ#%xޭ _ UCחoRXhyPwB;H1kP փَwư jPb}^%Bs-X66eh䍙%ʨvi@kn mDžwmhI^${+KQ̿sFrM^<i*ehn5^ ^܎ S%!E !J@(Lb;h(I Hd팉yÎ::T6zTE]-M^[bV..Z8GVD:Jkb%7Ĕ[Aj)Ьe##4S͎r Qo;l K2_.P23$Re۔{V| 3S>UF,o]Axy0& K<-[X'Lk-LU,x8@RZ+*S&a}ĚI!*_[rK [[n"A[lV[ ۫m ߜuzC: 9+@.~`z' NAa'٨g͝n*P܇nmٜ)d딂l^G%xGYQı8Qcbt97 H<ťN#PM[;)NO?>kwub@e?dh&kA(_xt2 %PFE[%QYA7X}4GK~^23+O `1=llY1Wm#./u{e73Ңқ);.RB.i@,$@yYXq A=z=o@P:griyget}cUvYK~BTg}a/ʶ o& Xb(͜Þs#{aO"RL!?J0Q+tE*c0r ]@1qnɺs+l7c%Q~pH.(*h}d(ZP'H&H}J݋(]ol%r/txeKJɼ&s %pLpPݪK8vxy|Բj_NIkrBjfAAǯ/s"t,&L15vAak& ƖŃ]@4*|Gzfp -{D}-`|.f5m8D0{;mߚSFKcS)|/DvtC5هꆞ%.Կ *C*ZTMvH/ "&GucEA[)V\Ԙ(%:'d=鷴BnuVNqʙF7))~-ZQA ȌNώhQ)8]7r1D8ot.rK?hqts.޸'H[MΝ /F 8.琗."N3 8dD-2.tWb3}g6_X,'V ``.2P"g[DB7yGQ8Od K!|dKhZB y 3z00cab<*sbT_X虇Edυ]DIH0qTEGg̈́^ b*U!ɒՀu|zq_00!EKDfLQDDW(dբX%\2(lj~&!̅Ez#,+_sW e$ͲIm~ jlETq!j!vP=#^ kwfѨObWw/g$%h)&@CO)Y-b)rt*Tk( .ȿ,)&),L ͍5 kL{\Xy h9cF5r.KyspަA(=% vՌ,: DUeWiQ߁O_p\tQU-".T!LZ17B2x 43$|P Pbû]Q # * 1!YI-`l$Xꁐ7gMU# Ep,v;C$`n%?ag6㽣fËH6UXN gd`%ݒЛaФIՏ˪ X#  W~d7fz̼0یKsmw XSĉ&Y y /-mrw{6NI&jtzMXpFO*>I=RW잖clTP nvuXT5AC!MkHlU9x;L!LdtF -:PHJݶB'A4FT񦤓IwhrB4j`g9@*9[h0L]kCTtcٱ9ٲlŌWt0ݯ6.TK $_NX)%HZo?Ԑ\ȶǨml_u1x,QlH @){h})5W8|2iʼ mM THONb;*&T~0o.ى4ŀ\Bp'CCDK5c *N N}A3hUւ-$l{ 9'U19ƧN|y+r"`BsQ9 dT cG:]0jE_O.k.>__#{ÑFؿh jYfPm,[[zz78 g8)V膹QKZl`א0 ZQU@(q9MKD3c{hC>MrF!23uT:R& %%p#ۘ89Gz r⋘3t3)my (g0<?N# 갼C0q^%q}Zˆdкgd!r}: \apO'싣X_FۡГh tk*+( (*fn5*9AY<_B⓵Qu3b-3lKG`ĆXx[/EN8+GT $%XgH/dmv:2vЂJgnF.8 |ۅ΅fkXgdC)!~."٣A'\&LG6): kHm腐ҼKl mv5яf/eBL:} 0w%|?_9kuNJ4Wpc-+ClRF {rXUD#rvx'۲ѷ_Dd~QpBK (ejSCBC;< ͵M['|D3,])Mez^iυ WT1RAm5ƯDu`2 mY E7# [sboi O#lzO$2$.Avsi,Q. qK`;LV;2K|XmEڊnp臁#)8[oqXNEC ri?E׳Ӣps#XH0C@ޜؼ.kv f9mfN|άC|{l*8=rߎK(oAhщq"^rx L_LbO~O`!NĎT= Bb+&A Tx}Md=Bg9t/mjfdE%wF<5T/+1F g+pXܮ`sueeM C4ꢮnaNaI0M [ǔJa+MWªޙZe"< \,Vrvpn<6*]ՓA%ꀬ,$u:YDHg HOd :Ƥju"h:*3]ɭ2 ?] "Hـ)T@w3F~co2d]e򽰆jNaS^J1t$FٞX1K0_>bʔBolhss Ïkaä~[i٥ Go<.jkhiv~ngHw51-( aآ:<ʀ`P–ЙqLrǡɦBLb&X+{IE5\ICF9U Kk0~okG)E^GlY`QEH`ߠ c/.*@b?yOTGRԨ8uĮy̮ <WҒ@i83z$S5!]cMSFAbb?F$|3䐂`St4G 2u-99Ɣ$5wD,Ö!^4Vj_oN!0S+ЀmA@J{ݗ߫' 4~vN +>AvQ4izʢD`DW b%zCujLL3vc؎l AHlӨu*٩^_C,0!>A[N?XuW5t#i DX=">F R}b$Wm)^1 tULH8i5D+54,3Q{g|H:kȉPY; 1c \Qnq wʩ;A0 raղ9#}63]?8&h)SvP`/<`V¢?*%+4H>-[ny\BلϔDm[0rH2:}N^r||U} easd?!)`dqPf v?WLvB[x5h^34iH7(L]Gb~BeKsa5>L ӂlu/Dya´p%Ϩ%#@Yf ȶgdwTWC#e1@LIz&Y{_J{1۽CFAɉKx$&8 姥|D q\Dbw槄PYqQE[eg],Zr$\ZzZ^2mEB *ЅiDDM^1e_x z8fvG[68_qɺE;;[1`_=RV4K@UUV‰$4k6u<D 5/t" .oh)Zs #}NeZiHoIiQ[x@N d,f,I7SChOz@sy>"V&Y0Ukj7VRez4PMG6 -4):3چdO͸]_wd' !<r#XvThG?Is7&\<<wOқZZ1;3\UnBCp t$ ElW5F0Rn93^+ u)ahxwwE%HT&qfYO掱na/fj4Uz:JEp/+5eZ) suncgpurWwÕor9vnjX+Og`p/m3}bb} =gG3sXYnY90WYEw> &@@[ JNP,XzHwhc]ICeTpY=FL [r`R[,Q`Z{N3=XJS7KeސNQOAډxRgYk8Bk KH)ׯ l˷H:60,C"v @z:o$:b;[΢$Z@J=u}-l<ޟy ^2`rYs v0ZOhH. YLptH vw~]!DVB4%i xZ Lf"$쵣qxFdc _|3o 0GO A@N<"LXOS3FIIڊzq^\,WL|ԜӴst컹7Ǝ.eRMy#Uv0 0p x[z!S>2Cos7\3TB(qe11T2sUB.F!M;DC?No}P^P-d*E4.gN sr<+G1?O;Q1ZA_ps. b_/NFQ C߇Еh\" ۉvտvE Ql% crHRi4["aCc*31E=V>H:@K0y0.'(= 6gϾ3ig, # MNXZtR]_-@gCdj şN!=pyŌIr+)Sav DL.2dvV,]zrحV'$8} +} \LdMD%/mhҕDE m7O^k vZt>ϨyZ`V)ޱ/+1C[,RBE9Y=,䘈 (G"Քv-dbgZ2[S/^f`YVc*߻05*1/'+"c!LI #[Ĝ35a %=vr+VQIzo*;&`VnD-&~q}Hʂ '_e[HA s2bj" lxs,&gUTX$D2ucҿ9>\v}ezM `:D͜: -qZA#E?!9\qg"m|F:|]Tu`T"zpD))gR.pK]^ e^"fWg?A`}dmC~Pu QQ-sVٲ5VmCI]2O %T"0ʕK E^k5m]o!7M?Ico9)"ųâXZI8\ {-.IALifϜa- c.+rAL=r8W7 a WrQ%ёL^rMGBNIM]礢u I]!3oCg^Nb㨯W%h)$$yfmsT@5J~n80`krnDbOXvQT$9{@ϼ#ɞ!#BT)Fr\?cu>(a|qͲ`z[#0C?%x!CZԑD%Li|by7Kn}&\^̨U֠!@ e:!x"-@3kH9H[~ÆIAM Ŝ6h8s!gnw"6,`jJEѺ_-)3f*cbX$LrU?hUCjw.+Qc:. [l u5`njUwT5;gzب9ib0S63f@LeSZoZ*.r韁J'_n8ҝ7g*^An96%ڢiq&)||cA1$kol_.R8 'C|O̹ɴ S8xLO Z*߉о$<w!u'? %Q2"Y?tL&h& B 29&D1B1_Ǩ zs͉CCOMڡ#^fBJ%>yK\7 l.[Ap ^Fa}ZH֙ѕx2U <>n1! $V͹]}E]Q՝3/`R*APC,=.6CIgd7zn\,}9է,U8|AzBLtVN2I3i{@8v,O)$z{ !_]Hg<0$,GeS5ԓfklR vX>hNv@;^%kuij2.|!2͆ᗩ?b~lPf?c5A96cr.{At&6ZlY^?Lv1ϧO Lw#tNN {Ȅg#`X;Bs, ~(izޚt֒>/jV/tѢVH*xj6&PKz{ͅ~E04`\BU:0fxaG~ՑZ^@ehWu{} l\;!&fMK{:րC9jL\:)).`gE5Wƌl1S%>\od$❴98rLxs3ᒎjjYO_lft) !-c5"QchCv2c0Q BVçldT͔k3{:w_\v[O9; ǓWj|Tt`8Q,g228;CNP/0*[{hNBc9&n?q1)ٹu Hw#m2#gF/[ߚ&-HgN?kjU =ԢNFmB;_A7jL9@IDATh\=CZ(i≯7~1odPѓ`ڷq&vT$8PM4w/d2$Dnbt 3XU>|FOX2O?Q!RL3c|&2y}TRKjϜt0k`kˢx2nŽ?=MYI٨{ nAƽp3y/˔ȐQ'yҕBW'H{4KB \.#^e|ҿSlq r\@+Pmqt0Qi9cP2H ]_v"\yA=5"dTE )6ha_ Y LI7yq6oϱ$[k)uِ"̡l%CmɼLگ1=1:JSnGF]ϋ !RnZESHH -#21r9hFX&GOd䚟@ё!wb_V}cА1'!5h(=bEECUjφc8L1qHU,""~OkĄ8|af͈ غG(O!'wl_8H")o*D 3m*ud\ơKb|sMoIc4S?)4pɐ$1z^SrvLm5 Bm Hu#i-U'K%jCЊN6מ-P:\mzNc\f])L]sVDI ~ς3 VE'ֲ 4ʉ8l:xS=s: j!N.nN{®#F(ammKdI0.KgfGXy?MDJ6Y_\ {E$KLeV6y:ͧd^0L96 LpDmN*S~,G:|(`ŠܒmFF FQG/ ̺ aAd_%CrPLfEm!ǣB6oP5#{<|B aj_yz_٩ZD9FuI$>TĺQM.sG4)dZ [EO7gvj?[eb2l.ԥњdD?oÉ $F aT[(c G9>`ϼb.< H=D=@Vke> 9#gFJ! ep(t6GZclHOC w.Q[*Wi C0'O;Q{w g.XP$L2cM6, ִn 6X- qNOY[( !e?{_z3suPBQrab|# xUeM“i,)MGcr^ZTڑ.UYw Hc{)ۗAeZꡄV>lJD.{nXM$F$_/4jrJx(gyp+b{&+eq8' 1b/:I[D ƳhςɎ^0:,=RDӀх댮v\"Y[H(q5c:Y)*g5#&Т"(0`y:W!9]tc־Y<}XT&n4׶)* gTSq^E:1[7֠5L( _:V$0AXM|4TkrP'Im9W+˦Iy !c){-+]{*8 }dStԵEq̱)ΪWv` (H xGoZ)J邰lƨwW3mr|u`F:'|D=i8X78}&MVTXs;߻BX,6#j{vKE:dH_Fh7;H  [T =MnR61BZZ1׉ 1+'")^:$o#oV:L΋Y8S(*>Uҽ[.TtQtb CmK<2?,&ǒ9&mLq1 `UhR &. !;n3\O d}khl*av" BL\"A25c.&R*]r]#T43E ?Tӥ); &,:F  &I|:=VHmm-CrkZG'k^}7M4#ܾA$(pJWT+źLB [Ӆ\#Mr-lUCJ=`ω˫Š9XR)bZ_\MˁZ^Ǵc^0"Q|K(R>Tf 'P($_oBD3FjF|RBUʺcݵ9UOCN14"*"{إpe06q`Þ}ղՇ-F%$k{'U'+ySs^tkR(;tTV>aԄs.fQd꒭\G:sģ.gMe*-5JM֬H Rd ô`leyLf9g[fZYn +Zpp-׊L-WRyᴓܓ@-(˩rhch ,B˰ '2 &]$lC}&VT'ҰԴRv13{D\L34^D4;Dth%NC֟پd[o.fe؅WP3w 5K/IB#vʲflOf;ڲ}Y#BWz8q9!Kڑ*Ă<@ c$ 1UƗMq]X_| G_W,kn¯p.`8O/=k$l0a_z[AqdodƋ ,`]VpYI]HOD 4̩ lf!2RM+<!ү,f F 1SeRALOlyCwNſڋwts t=fvA+]Gd(p҉\kCm=[Psl]VEÇM5LJ^A<hIIyMl ε)Da632̈:u8#&$iVS,sJ% CY&)c 䞁PCV6 F,IUFZ j Hnp|s7fK>JMP]G:_B $HUG=H[ -rb)1]l)w/R}Wvɒ@w&H2śY%|SQ]RZ BI@v@:WLNFS1=1b3^Rߡfqf暒 ^ .R{>hh9p7FzaxFf@P[SPJ!S}&_eY\ Z.CsԻ"VNMP n8Rfb,J҄oe3J`"UV nk\$xoYZ=YDkXYlaFP0Bq6t0eTqv":Y} vڈCl]Oم9 ]~vF;Q' \&rb,eU A5k6v[SdX%z5(w}$q.R`Sz;Ӕjd F2hjWlsADw>M)&qٞ,!Q,#㦬2 CAk[K}W4&A!z?SI%D}׺~$J+>WzO(R{s*)$BJ1^WFu޸`VRd[xhvh Cp +XTS܁ ,,^HЕ7R*hi6^} T=9zqBTn.!%JK.o\B(tbKf煿>J \F8 i,!_8yiq=>xHdžXCO? e%<SȌffR]X:][) c&ItTMOZocq&*y?Sv;3YA:' oԥ"di` ܆ &ujۛyl ~|eQQl6[G59QʤՓ L k,sJs c.8[+vB> C5f<9OW DOej kl N&Q0"5ݕ}N%z,r Q6tBpuF,5BulZ^5+3W{EyBc㻷DRR`*@d zsV*wD㖎lF) z~LETM cO ". ɂ X얘CFt-b؀g i U"acqm*jgmd`d\Rf+> \n}SzR)ː<-EF, *v}N&N#e1gjsFRf j,zx(iqe6١*NDC aix"*Ob࿭BG‚f-(T pdӫC׽~VrYdu.kEy`%`-} Gճ`] PCcD=( _sio7Brn7ݠ! kxk/TUk_vÇsO旖 9|㎷\C@ڈ(䁣_K)(m1GTN<֐wTDv fKeyɌ#rSBJiis#{p\v@_?UvM_u3"_5kꏫ}}koxiL:q߈ڕ4 ըܢwB úga_#e-qbʶc2(-]Q97jOn}U*:ָ]Ԏ_4P9sj/bHH{f>+%mц KCOz=]AG‚#eɏKrx4<oj_52Fvf'I[%uCp%'t$BK̞V:8}T79;TLdT"J A׀U` -ArgfV]k(.$ݙaC@2t3~5ݯJWh$0C>k!}.]R 96% 2y۰jCDi b00J>x )6DHdN}rdؓg]R/2CKj!4Y;\[X٧s? r u_<) ]kZ Uֻk'*uHblXk*X$Xk Jiù@5ДҒݘ(s~uWM.^?+d=rܗ> 9 !k IsFlu?"mC &N?W6j+'A>A9&}3+KRJ=_̻;w;AH$[(#vƎ=K[g[ =ʘQx{}ڈa+2=(h7_~ϊSMfC>.>%%O8\^hU(/>9G-0SK#>7FPS: )BxNod]5Q"|DVNcH拫蟩*\~xN!$(΂SRO(aD*?[.lio9[7/XPľSNHT&~rkwqD0aS1,h-(.u{>t2kkxqob}9N \F) _莹^C $ďډvR09a5*omÒm>3!~_HxʚΈaOr[w/t 8qQkdX %F )cw)滙Ac3?Br5r*=X5/Nj -)w)])d@T +PA0I%Y`KqEBH_0%Q\9q 3_g%'!%:M`j~2lEm>Y˫σ35/L/o0o) +Lj_6ӷ @xV| bq.aNrҧwBn"2aH/^y+3rHDh"5 #@, hb ̔$[d+"W.*%"I:!t;T|NThKK߰(0mI~YfA[HpU1=0/ _aΊ( $̷* :x+P& z";2pՏ}.H(3Y\nXq(Qw.3U"_ۻBxޒjf4Uu D+ g{c^5ȯކjQs9fI "M}hl+3zAfk?Y^S LB+%FQtwī7seB&kt4خKKJ[klYO;:;NEGYy9ȫWqA;\hlfSDD1 L.˯ |fƓLweڕVف1d@IN $2=[O+(iQD b3tɚ13m;CnxYg/2cx+Ȳ3# _DMNBeozE6 $9;ϩ61Grvũ%Fu-`H0LZJR6v `[{By,buW@Sޅ$(㳹$ ni%F9{H7}HnpcKXvN^OzBܷ`G"6'2)t/bU%g>uE=j^1m<ݸTY-Fi?pdaTT-Ľ-I Imr hpH_IS~璸s\m Sn)\:?3-Oaz~:jLIZ .!TfO#jExT+R;*jcUb%*'9{45!˛?_9nz&?6DgSBu!ܐ".[FF 1OV Y d^ yE#Τ۩+i4jXAP"?$j!6~ֵ~~ $| [-H:)=ӊĉ'bIDaHc4Ow"z4;P~4Dpwc-/=^9 fyve>3%`e]cBmDiZ2BFhYxiyWcL- TH \sat!ƮLfB]:LE3D)sssQ@dāAPS8iN~3kg쓵,^$k`}Vo!6CFڛ^(>{ E MuΙA2H|PCI!3o(XEqV v(xvH\FlJ>1E4|b!H4qN-2 -D[ "n<'{A2ʤ)U̠҆tV#O/I{6w֟P2H@ #)!>|GGGzݥ*[_]!Rg Q,W7e ,DHc]C9Pd\EF^~ [[/?K_oƃ䠤!a OϷ_qT|%i<|W2M *B@u艽 k_d}M$Ut٭Qeb|l;HoU\XvYJ;'mwO:Muu= Wi+c+8eIvX*w+Wf a4Z1?AY`ѠٚTט'ʗAF%qϿ VOitWRA˞:`]wŌK/|`#?  .3tyXϺ ;RQBC1E ~xȍ%Id.]J] 0߳nntWӧMt$*E`W8Q\plP%sJ"NbD@R4ь>ÝzB fp0Y%[VJRi^k3YqWQ,Ef_>9s+谬h?VqKѱ4 ]ƃsKd]{%3T8 f;կO1m $!adT7]_94;ᯰF1hEZGڂ7̑}|" ڿ '֑HV1ɚW}RlYg{|s{bkU//>Gkd$@nD mP"G7sEڞ7)ј`Der$+>D'\2'cΓ|ǐ9]!pIt(e{hچxe{2{{Ʈ'dKFFεf`v5g$X#@H^]J<?f_%Ff#bY-M8B?5sx돘aH5 ,ؑ yHx Wb< n?qZbL"tR(|5}ڭv> !7|j]iGɲp(O#ujKE՜s|&Qej7Jds.#s xȫ2>@ ߮4A7G\UaaK$ݮ WƲ 8@=)r j@<)Ypj.W,`kbiaxPe.6v!/V:Gr]fk5 Mg 4w ~붪A De{ɽܭsm&ڭR_d1 k“<3#=S5^ބj!*W*R,S ҧ).̢.Υ"cEN."9R)ɿ$Η$vN-L3DBGj6m~!.*t0Է,ל5:1*z/kh~Gw%a\j Z jq u8=[!x)*S#ѿ1 WIAdhsh (E مhYNh=AmﮡCI0> M#AY-vH)9zÊPH"+G:WhEd! !dM:[}w.vtiO2^ hߎ $zF \L/: vҼM7OfLRmp1`uB^'|p՜FiȰhȷWe.JŌS&Prތ/:xtqΐ hQ s opr|:V\v1tB QZp*9M5GC(t`> T~&D1`E[dX"Nx"=nH]c6T|/)R Y‹LGZ ۟;%G\]|.Ϭ cyɏ+S kƄ[*˿G<0fPض&2Q]c-,1K"fdž@L3Yl$kg*kj+wohN9e{"."'j%z>K_(|awdϑ-[R#qَ$`7\q0$ E#y{ϒ oxg5#zT+I,`Om4:.n#)}%CUM'2t-X)Cy欜T]r 4)*0gR,];D)#aT- zٛUp3^Jplz26"p)}xoi;IIypAAbVNVt ߇)gɺp |Z$ל61hZ-ȟk XI 1 {i)E\0繱M&6 4i4|tDZ 0&x[!4- m*p>4ZK'aސ8s*Bc0)oK X9W+r(ɍšօVF!WdQfsjlNs;qխ~d4f9Uwk.+W$Sv{1 +{hhi[X3rn&=Kٖ3o2M|CKW7k.I$POGB*+L*Yz$37-Q]y%;0H'x ].e,0O7|o.W6ݻlV}:+X _Bx|0՞zSy֐X'!G%IS3a`bR6?w1B:ΐ(_UBlp@k,z" B^`T#Wx& ;,E򢟺ρzT< O+tpE=ȁky-g8Ez^_]FM6xp H|LH0UD̙!o6ÈmdD?+>u Ajʪijmdi*qػ5qZx7Vt14Jz'ѐnYp3 M:0,?e#5RMMdV}GR|B< D ڿa{t4>X!x9h 7MrbGD@|2ϻ`EHϴKlФ_ .@IDAT KZVШKVHr>Œl+PZEc'i \`Ƥq|GG-W }~FsOξOFBC73n M{W- xSؖ| XO1-%kcq(49!oHx)> ˓Ӿ4J#[kmJ&fR\oUx`%YJPa26Q20")ԗ%z}G%izZB*lƆĊ 1n9+ ;@PZWeUfFҵV|6X:3^{99!{a=.a1r=}ϺEe3Ȓ+_%a&_DaѪg1p]nwUScF?=$lcڞ=mJVѴcC V)BNf{$EKڛXT/Hs9&S/2d٪:{rñ&a|6McS {T^I4!|M`*UCl;/[ ?2EB8w_P.i`924+ע!!#GK`{e1_@,;ORGxfmN^XSkSN=u :ڋL2=1xѵ+s <_c7ێJS<= >P`^t 1Ưy&#, < Ņq֞FKBlh|ʿ`p}R0,oѣIM $R0f6MɹyVbsak+Շ,?(a(Dw`Zs?A"&g,@EiEw*_hLT}87dPtF|ޗ+Ae ΀69(>\h ަEUI K@\1,x-Vx1B9_  " |%W̑[o>uZli/!Li[_~1m1XۤKe-ȤRTº3) M2Ir!t-1$0%RWfzAo1 xchz+ދ87~)v+62k}-!Zxqo(&<@j.]çls ٦8YPwoD/?jer6j \Qcc^:?_/Fb WײO?H? m곧­Q A8M`U1,~W2EkY&5A8U]ܩDG-?L#H,#gX2zɗqi2^ZaTodg`|VHbUh}{Fé$0V X^7"RՄI;b/2!p#XQ-@A S?pgǮP(KpZ]`%S%'.6@?k!f&!Q"L,h \gn5h\8vuq!rN UsXmRjq(rd[ # t/ VUֹQ8֦w^K,e"MLY#b7+7|DgRtfz iC&VⳆV0(N%KWy}15}&ĺg /8iw%ƫ@W8'z ;c%~(t|_rr C,1xN|tG6JQa鞓@VrG }ٸsȒYJ\Od0BA0(7AT[ ~C8&ϒt 8=^RW;dS"w,aɁ9+)d܍!& hA#;d 4ꕘ|/uaRc8^hh",uL>׈k(֓̋$6g7& 蔽3e`E)wcUh&WįQcIt["L*u*MZnL:Tv mH.%oٸv hj3ZHF$ֶQCim?+E)7ǵbN;C J0VPn;RUջNoE,֦`5B)nѝQ !Ǻ b%K:-!@f[WΠɯϏÛm$<䢬eVk$WV rd@}`wR.TA1V?5RqsK4 !xe:(+_ia!Tẹ0sv9P:"bCNo^7R}Emoc0U_d\=IP!o; a[΢RvO?="SN8>;ȵ.$MaXͫCV^rY&1=0Qb1t(z.qBi'ޟ 0wmې4}oO`~޿ϩQ2 9Av9nn=ѤDFLk,_r@n!jk$4o YADcb3+6ߍH@!A+%XoD!uȇ!:P*bmeBjFqZ%TޙaBQOR}=O%*yXXV+ 7(8&4hGي6޽ۜܮyH* C(HYil`RreQzHW';^)Be|錪 g)ܮ]w+fbT,M)`'XL:,]5T0F&{82 [ȗywq3- $0' 7Pinz©U2jMT^rRp.$OPXqޱMC۟4(}{ƥO%rWoБ@ڝkryq`9G.?k;!0`&EI>!HZ%N gmiz}mjP&Iiۿ:om*qy/)vr.׮"ŖJ&B.ŭrY`0}陠jŝδڊ~N+c_ 3ຂRhP:Lpv&$w&Vl:ܬ=D^ r@y~Jf4m ah4>d3  eR'+TbL/X }POo}Vu!^g\!X7)zSj ?i}whN'iqV*8K䉅}-y9sl/pmeY޵*o`wJf{^ug]:z>{똴Fd_on7mFv[ !BIPU9AEO= ko!]^05ח%a"0L3 D!@"}|)?^_lW@^ )((a]L8cX}9~6 f4IDgFݣ aϊ}nz&x~O e8 u4RˍFbDZ(cHtbX(Tl~ Mz@ A{h)mŜvoˁ ҆%;ĩ'ydo6?\Q&9D\ĝ0~* NR\>[JmT[LM `ȵȼ $4lf t58K(C!8^pJ#_CFN(3GE;54f&y1~f~\t\IY]!D$E !}ʠu3 g~[3yɉ0QP%3鰹ZULS V~aW_isO{g UM(xͣJ7Y]qN3S@͐i49|cW$"Ꙇ(30!.y[qs}p|L#H"p_*> Wzʑv*h+l^Jy,Nde^jI1<6(V~IlfIuc/6oﲑ/ 50]"鈧T86[[@ҋ%Ħ|I]"Dr5!+2\힁Hڜφ-jʻUuKL0Gk8&D}S:GwYX|ZFs2*^ؚ㺇OKכQ2XϲH6_EiGP YiO %>}1G~[ UUA"TY!R(Zq irt7oj]waLl{uC@r"D JN\ $lqrjLpW5eoVC S`ԙ/ L:SN{@HH "b@:zj[( T_} ,4kɛVU1K\ʶ_i0d_zz+mЊ<dV,${mSn@iO%Fvkp3;&`ݽcaHyam ޿%TwoC'ΩA0]l,׎ q_y.{_硳T '~¸X^"@9@4h6L&VjM" V7* Cx.M6)}("WOxx\H \C>1Qk?)q$ᡱ00V 2 iz**~B@ln xTW˳fτ# T/3w01Kx][E.,+3@[ഈCX,^2z Ŏ ߭=؞*dD{+ N6hugYm̆nQ$!`r|[i2bXuRâ$90Thw0y7tVGTXIO{B2m}LEng=^VZ'h>je,А5&Yw9 GYB0I!ؓ-%,_}!tjتekd^պۈy1(ƆJj{[s$1nD|Հ`#=D^\ǀ X*U1rqyb7*:В0y 뗸0p=琘QїYX<T3m 5rzPYFQlHaiv3h?]f4z7!):2+:!gIi̹t-ߙ 5lsDlp=,+j(l"5 %E5+4Tbi1#U6#(L:``!D?1W]8n缩Ȅ]ʡ٫K__f!~9TuבӞ0N&ty[ֵ Oi>UcEkbQV]]x ޭ*8 RBDJ? '$4DZ7.Ae^B:tIjrI4Ghy@M U-h Jt*t/}PWNmMDoy.>Bf:@yv{O΃:a)J,h߁팈>06ʤDctn߁6.l>W)6ū)p숝bLτ~Rfʸ̣,|0j5D'$DT3V)WxoKlܻ겲EH-eb ρ տɺѣ 8#eS e U)w*a.[""ݭafU('a)GzBܧ˦F"CBzJC4fS8ɰS֧)]J9 ͱtP$W<Lt뉥^+b$y+׋#B\m(_sMOy~6v@m b.^ĝ3Mn*\9ov,#Q VF8Qg Ĝ1h9Oaz];#װB@~y,Zldذl;TSΎ%>IH볇 'CY*E]=u"8SU;O0觍Ƨ`B1'WpMZӜm$ J|%%n~A;7-n ,;UijD:`73"H!}\ӄa .>А j" a7>Ġ)"rG!M^zX>&A,˳َ rcҘ{G6wp²lًA$O) 1=anr;b z ďDjyVg֍rR.t [a%74.F6{bq SE~ \T% NU0HfmeY\cgG6)5MU}NET f[ijL}]ۄ3Hȴ0Pk~Lq u.;k [Dc %ţ˪)B9Z=epJHc5 HB~@w\Gh\I?8r@Y +.t ZH_5~=O> Q/u ݠCQ`I:/M w&}u>}߼̀V ւSH`>l* 0" V)]oTWtll(H +U80b-pQo5;OTD}z Bp,TZe"H_eMKsn/h=!ߓ֮n5NuvtszD-|$5B<6q=RJ\>?VY,H zMKo0*j"Fa_*#=@I.0k= cR}s߷DoI=F ӥ`Dʦ;+<q"q!B70"9-EK]O@0D;:rbk~q``g,ԕeϗ{ctOPJK(Fkf[AW;. ?9^e΁"^ߑ ϵ;hUkB`(;!2aovW#9aFHkHRܯ3kq;Ozʟ%ĦKIkA+DzY+Nό߯B}D'ͧ-0]Nrt~CpFpOڒ 7ޅ\h[n~odXJ5$JdzىҡXeeA[֥ٞf*8]i7;m]8 `R ŔlQDӿ[id!Re'PK1'2r!JBLL_,T%AQST!f D.~=>%xT“5RПL m]CvOn*sfp|]p[>N!+&Ge ^@0•bhtoq9 ڣqJRX!& |ADP+Aut'؞NzVg#=Mr^1.f\$Axr&] "Q Fc 嚨jԆi~:`#NP9_6vgj=#Js^uOC8DdZp21Yza%lNIIhX8Qт Cwʵ[|oH: :˹ZG/մ&R7,2 8y)<&IŪ1F$,_:S m37!H_(Qv$6h*<ԡƝ$}u{3C Zؘ`fGB Bji7jmFa ?,NFNy O\Ȭpf?]Sɓk5R v X%FpŬLY(E8JM%@ʟr7{YV߫tY+'wm'؝8G!Eê/QԻmF\>xNbJ&-PE8,ڮ^WT}rͩ*Zg/WF,!%2d=&O1ioEv׽[ lPEzC M2YFGM\6e@ id\( /~\sB8QdU4F Uⷐҫ2/ h|-.Ct'$5DHkeײfx.Z),GE1 /56SILI=%B5~-]ZlG{g؀ƃ# t٦gyAȑVn}DR65hY2nQ9\ Gze +FB֏v-UD=1!PJˠ@G7: 0" mc:hǮMx~Py5n`p,cӗ]O=DTDK+u5A#Li1TJl9tk6 tQy`PϚ@- R硉Z8~vcXuhC :!Ti\hHjث[ǵ7ZB>P`\jxήӇ) G1YYTڷ˂P9,)sM3n2#LjEP?zdx1Aڃ"4e Ô!9+R&껉d|)  hKto\5͈@Qyo >r^p 1G>1-`Pc{֫ʎϘ~];\ġɗITgt9G b9׬EGg%9"BXD_7;×cP)@H:CjtS]#U^$< N"R;5= `[@#) jwւ;j{.>N@Ԡ t0(,yuEauD a{@_XPʩW;_礂ggW FQAeP׌ƔQvܷ֯^b{uwBXxpl*g'䤰ek9 |=PbK*!-%C a4Kdҝ\J?]$rȤhe7X 8lC3YxFݖd"VKGh"\R5ZW~TfR "k(NO~ Ǔ i9(HF"׸IәLPڪo⋰6wj]/@AG4^4Vl%C(%5F\} ֦񡈖)Cf4( g#t%:K+tXYbX$*g>[U F8A>7 C!BBU) С#BVk8G}`_y/O1a2b6x"݁TG4[ Pd{Кb3m,Z}UL'Vx+$^m ռSCuMnQ a."ko͟E6釵kԊdTOBs}8TBɘb=U9gLE1q7J(^ij#sHE EAʦZVmul2rdT2Du }{MPwa`0bK_]THyzN_B;_SDD5uH -ܠ :}8fR?m,69x!21qcTةNo1Q0m(|sW=C[\ Z{MNlDi #-%5cabT$lnCX;UD“/)9Ψ=꧞WVa9rj# Z”']Dfڊ@b-v_e9 .U?N}&ئab)ʒ1rE1c%?8ջ8TH<2y~ mb ؀?1ZMŎE9Αם{yY`*ևGUlܑiĜ"O9`5h 54]$i;ԛEcMI@'!1 f"2pe`Ϯ~7 E+WКCQpׯC1Kmk"BS1p~5VEmab!v[Qk8BY⿈WC[#QIqSYd;@迄5 _'ixXcqt\G(/ힺCN St,lTu fdI 4&O*]|nj:%LF㌦%/bcAii|zcoiH3+,DžG#emΉʼUw {y5h-(WSW o,:-y;p2PQQߙ+⎺<*Y*] 1A98/_U2q!oN}8ӫG!akI!`By:i2Q޶_vi٩{sL bԘ,PhQC@D"`&j)h8hCFL 5Yޕ:+h,<{ܱ"@Ga2vU[,<;Lq۷>1 pݬP W#ͭ٣X7Y;"U8iXPێJy~ [lRœ u'jdCݷ=Wt:G  ۜg opd+6kٲH~5[(CvDcȤݹ j VU(}"_O:)`3$=1ffdGzN+"\TH YyہO҅n3}yeV?O??|bA Ĕ5/%_,%I,['n䦑mj(,lcªKJ> IR#4414 [Y=uUiǪdK c-{U_Ou%B{+Qۄ޵i{%bcւ ^5(Fv2:Ǩ<'ؾ Ol((Zh88~|(--O˙ D/$ ]oeK˄Qz@cyHObBqk PeH*@PR f;)IoAY@\ܥe&g }(U^aغ79°Y]I{dyPwwP-†F2/)SN?Z01G%/ 4T'CD[`_r68LcT ~@IDATSʥ!$Z۫ ȴ3j&:NV\2:9rYX5CpuNx;! sK,4/q89QdVI㤥@(_~KEuV~tq@ uQ=hf尠7">r& FPM"v Rv$[VY5fy8%[PϽGvE#N'5`ˊhLr ZFMpǺ̬@s>!"b _eY `udmPXPvTv^#'sFe_S4"m|!0Y_6oaei %Kp7w'IõkF=b˷3a$5..%r6n]IWu'ع p7C y_Db+W` *%hEvϺDedp0H=tΘ_"+o{bq |Q_ ־5?q ̣Æ('rv(7mI n7L>.l]o͘[X?!f;͟ (zq^u o9L;kfB֟D8(iijT pp:"wFtTŸroi>CD72i ܳ|F 5elL9L\wNAiGw2QCs@Y}߇cE.V=k]WD$ò8ݎFB7k&n@sDD6cyKko^!pPBL"RK$ .JJjըZi1F]e]LDxawS JE-hցޮv-#\?OQ})Q@J27v)߂ gnTsiN!`LtJ1{.6%ADJ/aWuCxã=$\ f0*^`HJ\aJxns¾P/4l5vAJ6 6 47LJ]*bR Xșzv4YڿX|[%rIvZiќ?HA@/L=grMyFsQ()qdyllSi+(:T)-<vE=!m>y׮H^=օvj' c$Xy[rP:ր<׏% n?x! X {3]H_UI"BvYӪsWP@G-٫ěȢ zB ^PhA  [%,\3P/Hu PDܗ/dB.O]4HA҂9!fʶDXL ї 3%ev^S̿/!ܓ2ߨWd;>Mڢ*hwcbs h m)rS'g|9u5E2欑[KJDO<ꠝ:u+Dv?_•lz;Hh-G}DZ³f=w-oј|$ r)k!U I` |R;кsC@؜HfxV _2no#8jHYRʹfE'Ċok,\$px}= ۣq`NUl(VB41 ףlKU-ҋВJ cZit?V9iaqdחu!ޤ&IpY3ȇDZ\g9(22r01WԏRZ'1Kʈ9%Weʽo? ɍ t~7 ӓ\fNh'D9;T.Kq UV!s+8/i+iIV;6QZ@@7u$YC3b\GoM-(d߶" nħ5hʥ/@$V9#g#ATVk[;uL/C;:א4-i<I;f[|7{& _~(AB&R[fgQ$͞\`F }?5ʀuBSloK*n7A ;+M8ДM1د@#.p*tJD -jemakM~XLu7p!e?`b9%#1yXƝ|rm.aKآ*V^C-{xXa<$˲b#VŒ Հ;bJGsgPل,&6A!皸?a H~ۦ^!+!Qu9 FFڞ3 v}OǃOBq5`T/ڿkؔd `7_]TQTldTtTD*aR(B2h^y?D58Z,Ldf|mB-$z`C@;T}FBd^ L 8` u,Yg5YD&tpRG6j>7D4:ҍՂ@AOI0FbCB79a*V=g;T'y=T*C Y&Qg(miG%&.yP7J柬s "S Fup5|]QQ*v? ޾J9sÔ_-̈́I6[;T/)AOt%4Z% %K]+_XQ^O\BS1૟lCgkbYhA}1Y)77?D&$08 ",I@XP g89maT@2郻w1ĩ.* T9~/\[&( Kl' H[ \k0gˀ=>B̔k$#Cpmem<hqK:ZFZA˛h_FN%-,u!|LU"/8veNmI~HCcs IU4g* ;Ytps:NAkb R;'Z\nȅʬ\9鐧 8 8~a/?XzR@!b,UtĢ$w LW3їOM+ If&ۧwV~b]+iz*՜Ճ5.0 )ۡXPD 4tAz^]=ƑwUZE;%ށԗ")ϾgYy˦SW%sӌپ1swNz[|h;M &'"o5< c|½;z2r+ ޶X2GcotI;SxEՈe7_UvvEbczYr 00|mO \B 15bPzuIiuKu2\w7e?=|Vz @t=pvb~vAZV(EIvG7M }frG972krF穆 QbdоCܵМKrP9+8}cԮ-~RnKw+qb2ȡh nŷԠ$H|FqH9ع)vY}umĚ0ЪO›V2;9m2+g& UG+]kΰbJ `GGM9Ԏ8e[Ɏ<DmmnGrBDŽȁ.4rPt$\a)WGˎv"w}i,c8BI%iųK*V?/tiDKB2!Q8,%ֲhBg"T}Jn}eھ#OU̯S#Pg\eF *dH |- =GU{pӠ){ @]G :ߖv5H]%;?z+l' ?5G!to ]Xe2RC?v6&#㵜 󎀀#)_sW<=HS/TO3@B[z]Zݲڔ!bsەm+%h26]O N^o"aٽzK:P+M"˵cX V+J?ǑDN6u݅-YdJQ $cdD݁H5]k8u/-]:HH:Y-aBXf"yF$Cł;[XLJЕp[JU{@:S$_|D7Iljxk?wwG 8P3pn*&!yjzi"!Al.>v0̢M+S. WWDd 8 Vg._~L6?w'؅)PSQf!k<=7)U]- SuYƒ6JamDΑ$e[X2C)>Y9l1՞ȭl]X^M v||տ#\Z܁fHx"&{=}x|s- :M!XWQ`Co09G9P6w(tz8p2p1N:q^y&D 5+lsV@;u;(Ҏylcgi9d$ͅTh.1R ttto-g@.'n rPf*mp֋UЇTF|5ԁk^KOmwWuyypC30NZB(:@ ԣZЀp)~:Bphdg~乀ٲɸZ-R51HLq% _@IP`Y`^9#c B$JRqVmi/a/wa|;tV>8C֥X0V9X}MP0 K9E!5 9 k܎jb]8|$6)S˚j?Bj} E?g3>ȱՁ4^eI d1|8 ʭ!ޫ6Dt5X.}ŵ7bȐ%4@i;̭S3tC*i0Uィi~$ElFX\Fxe@<$dYLpxҩƇRU, Yvs@Hso|9YOhGS9]~}Da=#~wmS_^̀LC"iox8\`fD> ՞QXZAFDJaV>V9iq,$d©ȸ$k{^ZI!zpV0WXDv7orh ޗߖ٥Z'iqP'W=X|Y*Aq T&Yr~̈lԺLśq;R(P]%<<*VZ/_"  |E-wP >.f04좫?~{nO{;kWt30@[kwl0 E,RFk[-a\i/zWcB"w$P;/7hߊb荈>`@nU`ICy&`TՃܪ R:)n$*QR&&f)kv ncTY::d$?T^n0k UqPB4O}>.H2!㚐yНt3ŽŐ^.(bOA': ؏L Mq۴V޵dЦ f y%s+}~K`$i; , X\ 4.ҋ}HyٸØۛҺ4;ל7@03gDO YP*n+m@ɈI+ ȭՓ4lt9ӎNޝ]XDRq\gʆެE4!j˗Tr;["|ؤT9Ӌt?bQ*&#JEPHCcXb{>3@T(MxJ1Q6:@Uڠc R%a!}qئtg@30"S\ۈ,B9\߯ vzߤ [$^[#%~+{EhU57BwyN:GD麝ЧY:m ,4n$p0d. N'NX?]f/mrԴUAS:s4aҸo;pu(ʻ1~~S:p2\cF5oofRa0lMyۉ Sq؇xtKvNj~]hOOEà#CvE֯(x 7P/ 9ތ 9ſ}]`鐂ThO"2E-ׯU. o1i1WΰNJ` 3 dJmQɫ/j8j1hrn_<ѡE:)RJ@ޑQ(#d:Ӝ}Ph[YXICdFw њ[n{ .Nv)t8W l 't(NBv~xz ?t \%n8qk^kF7^n6lpfQ'A[0, T’ ͦ hE.܂y:f#W }UE:*4#![(bKzc|<ɟ¸[v tigߢ8s:SaJc8߽+Qp.ܣm6X&8qQvn~OSqLGL`ՐX $^V\Uvf S~R<:WٿZR aҟ54]'H7Ӣ_drhnhpYb  JlEśύWVʱZ}-穌XϪktV Z,u1D'?G6Ň21vɇX%ESrr^# Fs9XPD㵅Y^W2V{9,c5.)ubю7n|FqrE\PO=T@h_+ T*Hg~7,RMj e ȇN=G"$w߆o,ֆAg*ƥ˂n_A*O]_@1UQsϴ-j(ށMZuF~fGuC ]7nJv\EW4Ň4 yQuuFsY6=} gsU|UUrmrtP#\ʋk*τ*ffi3,_e}ϡd~j QiTy`D9K]-SQgngפ Ǚ'"֖k}2TLAƸ$ Q^ 5IJD`+˓H]BD2hX-\x%!{P$&gzJlo3OL_eM!pyqG™񖳪YgQt`BaT-5i|jxڟ>S53m2ׂܧYag2m(Y!=Ck<";F=-N\NV4 ̥ωܢ|( fny6wDʜ^imKQWɡX}dNOǾZ 5^X*M`6c1gCc Np_> AD`eDA``GBK/;SS!Qپ0G2qFGץP(8Lj0-yX"]gͫ%Lf v3 q`+fLfck%ȂV89m3ܶrJI,_xl0 e s&cxCZR۷tM;y(h'PV$Y80`}+?UYG۷ =VrV# .8P!/=,kn6+zL9ur{g޲sڮ[TF)ZQwm [3\87Զu!ɦo=^eSi>t?.Nse|0nn;M%Tc!=,e(寮Ttw2&/g.9BD-bg7^?[ IGDAl/u.h _xpJKMFV@5w&1Y>V*@'-̱P& Yh6WI>ܧ1S6D][%l_eO93 ] D88 Or^,ύ/Ҷj5<-((] .}nnlz:->JH<*R^>'Y!ݗEw֟8pfegɐRa&J ez**8ҞA|g[ hO;26@7.fp_q%(; :ޗݡ[kןrѳjϗ|N؍ >*nf抴ZO/(ؖEr}ݾ681(vo$ҏ5Dx~p@8P;)pMJ0)G^TyiP4-vqSUkhwr`GRÛ}_,0%'/<3o(D`cz'fn!/|%CkCo&W{,cFUQ$w͗AZw5PhQIȫDHB~}E vY;sC5T@'X,߀@d,y=6[KIϘoHe%_l$2G,;<[eﹶ-1k r>AJ$_;S=ǧ Ai,KӽW2 uAQ͔@c[sGNmI|3 V5LK, azh#v{xEu['  ^'u+s7Θ #ꓸa" (K u'[oI%N8LgK rCq.(/M}@36|0V"UHQXo*2,GS)E_HPA \~#:4sO-:;ٟlWxWrJ]"r\-ah0Ww}Ի0hբER 5]e!>Uo2?Og ,Cv icB{r;?o|'ͦCev BmC7'hXczoI %;JΜo&U&#X{GooƠyԁmG9axFԫy ^nmqHYI,֊ j4A"PЯ iF`:RN=N m͉K X!Ga2F"BDv?d}PJ+}'lp%R79847 9˓3a.3jI*k )ׂcu.#)/d0-t!YnOdg+e@s] L!s>"-*{@f\t/(~F|\&HI N]zfӄ\qS~qN7,B ݂a {w֐_J*י\/WS<*w ,0NxՆ=JŃS@p[ lWB" E <6yzַo`$ p ſؾёyĎcߊ _hRk`7 \}C wpkz*H9栮0IZSºCya> u {!uqk~[)cRa$h4:)HS΅9t %w\UXf!@S j"זծnG^#ќ#QSM'+ r% m_DE_QT\ <4-Q- o[%EIץ6圯Ռ*XT]/QPP'"ٳhez$<v9w2~ܖP(QXHMcaEء6wWS4@-5R!Pm5_2Lp-"DRSWKB䜳ʤu`ǢNk 2 vPMSqM(M-1G`=ɗR j5g\ tEDMD^_8}KEQ [[㋹*lRq6ǡ@3c9 MpNpex@XG/y4= v0¼ZϬ,#7"x*7\蝠UHI=x=48")kt ' |XpiGȅU${87Sq =s;-{n22,WweZ{ }$dӨIJm1&|4Yt0}$mG. *ڡ:]H% չ]tyV4}>ox~ed3__J>u#W&` J&LvaЅ%Fx RtͶ6uL xYEfRJLOuV >4Ԟ80Hls!ݹB7HGy6VwOhL\ hq/!N "CtjlMV: XO`oN>˺+'v`^,l݉uirG _Ji2ơKf2 `)KDѰdgy07[A&R,]dn꧎6$dUyʉ<`~VT/vN0Kmmv{^ڎ' ^;)10aljثh^`K$t=|pZ ?A,̻&3%byE-Ǔ=iʤ⫇$Ϗx-!io^_ ERZPsM wT{xk!+<~9 3*m|gX=@ sY&hgK/\ : B{iPϥbӆ$d7nJs%?bArym ˏ/dp93M٘ f_=]SRԙ8T`Y2RǸ$d7=c^kY.Ēe_k@IDATI^T߸ג PCpUcYDDerg%:áTAVrXbNS.aUag(~pֻEХ4_Ⱥ?u7%R-K8!'OHIn0fAA@K.ƺF hd1+(5 izM vM$F+RuVCGv$"D> "g_z9{@a? /WM%߽+*_IR-j>Qg~ RRfABߘM̍+;?yt+L? r @Z2Vd3h[Wk`e6'K<5 JW#Qu4(XÁuTY!c'xl7 щ3(DFbK,l~FS$m&sSm͔]u2&+gյcƧ.7Ƞdz?)_>U& h$@ ̄UlJi` DU0r ! fcw; $q4`_!7nƦҢ:O]x!_݆GJժ~ax r9>29*V^uWo+n*.Ҧ&(ܝ؞wig3}< nM `5~)D<fQЋ3Ƀ˳t҅S,BI޳޿ UGUpn{_y\h̄ YNkS4bD( eMV;"O j\LyW %@hO)dCҕLYݝ^$@/oZr{et0V#*t3kHXbvf1'B6TKsɽЇRDT"ZLpc6s0ݱv%.Cɲ (*OVO|@sM4$U\8V, }4>iĤ@N "K QOne%lt+G=ҳ)ՠʕ#6}GC1>e㺽P%0s`M7$Kʹ#Yaw;zTy&4?4iWngEܐpjϋf8'6cU0 v\~; gYW26<4I<&xFБ4y-vxU#",AeASѱ⌛k'ݲ;QHGgz݌߷`v`K{IVHy3fCiy++'Ò -G "WVsfԞpuo)UDS,VҦ'v$pEb.ƌ6:%ݲ" KUBEmmkB"nddtV~*Co摧J}Cb=6VLۯQYN75eVN5A9⼽'S׸@_0Ä1L?)@:dluk2 iXp,"Q75jA"XAeGR^DK( j9;~, i:Ѿ9E Z k`gC%i["MU77!(|jsqށj~GRu}B"-Ӳ Zg{zy$]c}7@ʙ=@Ž)>Cwonglffzh{'F. $8b떯#QeKKŹ)+0X?@|G?/0)t/#G6$.{N-ǭicku}kٕ:IZ[(vyۧ36KE6j*Nq4ro="S C¬ԧJI!. 7GFd; !Km)YNeNwbguX숪j 8ĩ=A-w IGa|Y^_E1PNJ~ _-_]jΈ3)/ە:P uڞJ X0eѩ]^$as/30<*'C)c/fv_3DG @DKH&d?c3;5ETnmPPӥvߖ|ه@TwPUՅ~oi.qTn2YkqŤgn txGUglak(+ >Ҥ*؛!IOh$\skxyejEŷux`*FM++m`-L/}AY7GEᑧ6R^"5jJsch}$XޓBw]NQ:%>mCz3޺X?RVOu'< =0Ub7/"WtƇ-WKj|P]h{(>PY:\)Η)C aԷʭIws `?ή;cp2==Ti^mB+DƤ4?.}conƋvt!Lė'2c <0 " E, /_l$,wcq>~iӓxG@ kN9.օ VSr Hb/x} $^nTW qcF[ΦITIAcc'X5 O4x0zQtBX}}=Uݭ+IY`V0- JY+粿%@ED]%CzFN5XczH bBj[mFnzC #H8&FGDW$r@",tgY#(_C4#oDEZMz6[?,Y.n뮛GUӻ9+_|59KX?S۵y!L\_Hr-U(zn?{olH 2$RjеcRj'5~,d$& ^LSHvx!ٸ/[ Y!˳tRrihܩ7mU<ÙAXMQ c m"75G8Qκ+ꩴl߉KfOB#`F*ǻs1rgQؕ VJ"k{#Ӱ±0ấ3:Ү5_u,tY?F.:[5$9IO9Uy81sqE [JR$i,u_)D1 mÌpEģMzOsqhIVkh/ rh8~1]mchc ?||67Ex/o&vCgk52~5 ;N4ȏ0uJE+|֘.@MvHҴ"lս 0RPXi!%S2| T OA z"FzCzSR`'aFFIu8QYVgo?dktRG<[]r~DE[]5 7>z-Ll̛uEo-l3Oy~҅ţAUѺ _kA}LuqSB^qdt5~|U0nVfϡuvК c+4bJ`X>J> ĔӠs-6z$Cj_ X52%}9y.qDˇ z*o?S&)ŕ1ճ ia i`W;Zbߠ@o˚]`>JQ`'<>e̷j\C+Abg$GDzm%DÑ9$&8#֩e6^e:Ҋk]0jgVE!TI-'򾉚9fpX |DfCBEOG^ \gJ==`pdm˭{5Dukc!-< Y@CY"fF9_Pi¡r]{/ayTJmaI^Q 2QqY!0!9ʨC\0p#*rVxyF*`Txt˞gV>d5Uk/ynN+Jh@qMnV,{nigeJNV(aCI֯{ TT^Py-bfyܯOVM d;STnIyU%뼊T0C!O "ۮ Yv$ gCዸKY˛PG!'YKmj@DD@^$|\-LSѰEG_qDg{F^蚛jy4?|u?t Pޗk*p_`(&)w2ڧJ"՝kWڍKC&8ʉ,;SU ri/Qܙf%ȌBMA%JZ^[M=)1A1▣*ۻ6^wIzς24me;')\#Ҋ|Ȑyo:]yԣc9ۼV;cBמ"8pIy;rǛ%C3&uXIh:V]4p]9s@> bU '5m<5]CG8Πs2#;NPY Fa4vspӟ߰ )`]IȁTTL C5A_},5#`sW.ƽ9*l}"}vM2R L 'J8l檟gmFRح[A2hM{>+~*d"=fWD oW#b23צF-3D.f蟂_x22r+׸V4Uhn8ke&]?*EK\'7&ء{wNAlTHdEtrJVG ^GX*jy]>&eVۃ!;>ZL.ʚI*טK2HD+G9cKk1>egU;^v`X3ںHSgn{^{ff%>c1X#&tR{w{N*DZ5NlAf_jńO,FZ-NyL͟`2aW-H⽦ zXb9 f=1&JlTJ?%\G <4LG 9nǣo8/h`7"D4Ss=;{3qI!y&|&WR/&v 6/ȬyR2LԦm:CHde"g;˨4G]_#:"5s8:ٰq* /3rHQel/ )Xv.hVռ־Z2}zR 3mžV^̄FnSx)B*DW`UDL*8˴"4#NeE^F;` )".rfB6B?IDDt$KlUC\G<49=sjZ?6T}ƣwO|%ȞbG@47h[}R57b,xHEm({ډ{G.0z¿gjYq{OO6ܼ̤3h9T)YV+bv6Βɑ^Xeue R5Zٚ uBC\*rI_?DD0sF%7;іYW-jî) g~L]sA'2.B:[XUe{]sqx3Uwg {mdi* ȣ3L>ThOGxYq{6)%+I{e><\ՋF|}ϪuQS ۉV ՌV/FA6RQC{*P&LWW,(d q ۬u{BlǺ5 c:(Di0w3mWe1$tVS+pZZ7g!UM)DbeWh <\؞>X%Dt;T{tjT]!M:>2q\*!v킥L1S6-Tr#5#mgRmkr< [:q8t[' ZWHq0C"7!)Y7 Lhx>*vק*@ye<3= =Tj#ZI!M?)묺C#NЕ*`(6q€왚 QZ.'3 AFnrYP"S ^m,ׯr!@-KnRTaL_;$a |J8d)VCd(NduO6EJLj` HOGe>U۩ׂ7bFz Oki /BO}Lh, 0v~gL^@XȞ=KkIēcAPu&f%".6׵TQ sz ǙBNܸN4ҙ8qP!ItR)+71ۡڠ"B sGn :VYLUdVJX#%Y߯ L]\}͛m-3QgP"z놽5dHi"+MFeJ9>\C>QrʝXm_ǜB_w.☓F5 z+5a9`8RG؜%G ʝ]2Ԧo>RK/_` 7JxԬS+]>|< rxiQ?q嬉q{RkM/ggúYw{1qX>mzqQ^{t\"F`ؼ>y1>*}99}1K*a^;<|򬏇 |  ԏc!e"`I-/0EG&0͑'zC N-$_2@VxVuE{x. d> 1]$O@}P>ɲ`*6dhZIo7eE73"Kab^NQM;y÷5Hos]=}.͇Ybb&fn1Gk܋,TH~2vHNx '&d6xJZ5Cm /l=rw ;ǂW,*9?{iCz[M^?b^~c'YB^Woi+県 A>@-S<6j^ }<`r.r+ Bi aI]!H c#Y@ԀQh,*ت DD3~m?kceV@|Uy#X%(b[`%jXrN߲ <rjVMJ0t[FՉ;5ޛT5j$X/&i zUb3.M!-D\W(JB8d$b^C+}}]Je*YY%66P-߷TF_^. ?%%Cx]'KmĭO`϶K1(!!ffpw;]>;K[o!pf U!O t5F i(Ĺ87@Wbx9V3&<{ j\*N= b/.9,kXad1xwE>.OR.W[3Rtnome|.yh>661C}ӻCE25v NKG?qV&~)'N_3N$T5FҚ^OB~s6dm.91%XD;V5#+ԭR`,OI*S Ց?|3< MgQ~6z\ u<T\$"z" 茜m͟粵C/:E~~t8c@I1+=x 1$Zmވ6&ۅAW0h2wp)'," /H"`x۳ikp,yH-2 h_͔uM])Oub7GQ1?0wFDuq%UnYT"Ҟ1ي ;aDy6хH@Z>Yvd{šyD#dGH9>o!6U6te}6/Ӷh$뗥[<&9Whޯ(!]KFƇdH%'PTy0D>-#\3l3b RW -I̽,?z4 <^K$g6)%tmYBkƃֵHH*>Ftrujko -~u6G:RgRkV-dn#t_Uf?P/bؿy,(+@ 5\!Y]:bH% xDИ11 ЁnnhA8SV4NKϻ'ɂCA8Ũ"Y/=4VO]k-=+&T-j`/t[$yJA) .{}«VJ$M:V@kXr{aU2q76Jmw$tʁ[}sp"kHҸEfC]bddZ}4/|^ }˼O``(2ZP \58o`D~,#l]"6R;\+GqՎEFIIZ4۲k vwK)]}j6-3+[ "=_g1 '9b!W< b*§EyD@_4r?_ >JB e߬|na9dmXAX AcSl5".TjWjh0ԙ? nʎQ[ K*Z}ήO8T zdEEQ@ń^p.],oLf>uV7x:.Etjh9 C {Pn#xfH:5=.^o~$O/e8"@vY2>,hr +3>ͩ!1>7~,u'q[QB0sak׾; kD r/ET?,4/̈QTG7.(Y~Ũ1a<IgA}P0NR "DC1v%fAUfN!:k (//Y3S'[8G"I_`x ~L5}j,= q4Wwqgl,mx.&^D%VuYZ&H 5I}]߾[7ŋ޷B~xzRDB.Ŵ.ؘqikr]HKvlrU}*X\t1:Q~;U#.Gːd|*pye]/P%A\_%}\^\BYfjs_ uKy7C?tvxe V$9ZpԹN/4 uC89B8k""/1Qf8 !=Cњ9\/*iP<.8Wf"Mפ V;nYkt 5 R%|N^>a͓mVyab|g3A7|>y1dMM{n8N ~)ko|'oiN8{* 7E\H?KuX!k`K*^>퉙=T+YN&܍{a}4)u;}Rݖa*@F}/(7/*Dl{iؘw[8#[" :نDf8L50h:Pe_sy{MYDdX tatIwo)\Z%Gq,xI\7 EVh zmK춬qab.evy2k/f>[<$d'>iK/ΎfV{$zBc؉l@f]&381İۅbFzTjI]St3f?8vu+$MtPK4},{!%t:69/V޶Oߗa}{&rH`wVhk4GٮNQ$AqXc矁AT`dS"^ u~-5ެFyiMHy={ ꍔj{2 W`/QJSՁoq Fd/+2g%!FmC:rKͫq@IDATt =#*UW]p$jdO2rliOL` "+yհ1!1CT GyGs^j!$ dƓhks(JuKh,"u{x ѣfư[ض,MCKL0-j`_1$e* fEzmal1b$Pt5Z+4 S<[xktHo|b7>+ٴ6%ϘPAyEaZ[#olBmWhBNjՙ;FEz`/S:a"8?ɦ9 S6LL1SH?v.ĖA*`b\Bhq/O O_֑@g@Ж;ΉSd ѝ`rGϺXbXLa>酜0NL;%5X\Mm<JXO`HrI`ٷĶßaOQFqL>uU}scpVL? pF*嗟3GjQܦ!¨BN?-9\ǟD!*j!GT ( "ĎNPQ>Ca/Wk,l })$dN[%{ǖ9~&JBײi "bŌ+Og`qq€-#@ 0IE $Lܦ~g#Lq,FkXq 40|EE`502u%]6ֹ09DmsjFCH$gMOBBrF( 9 ogd4#ք+ (9O<j1!HP&Sȳ\ m`/ܳz6M$l 29iM[zn<ز/bg]XvOLēւ0fpx*AǕ <5Q!?'6-|b} k@8fH,$yvBa/nIY ҥ;]Yp?>ҵK:Mr|inZ΂'1"B@UuխWzcI P ACG-'6\ds2riiv( 7{-pȢd~]A~,I U $ϰ%L½]kNAbvRJdsql&.@mUdMI2SjHRKo"%b=ۤ햓T7[5c(B!D<9o3'2=#?1',U2F >Hh<|s?ҌS5߆Adnfxxg壘lYW)!83Ԥyi6?rغ/ `ZBUK`SE9?N٪ n'L<$48yYWa/ݤ^ǝTr,bb^LGȲ -9H\aO.jP9E]\Ua[*![d1}!Ka#{f5i"j~,smoVl0)٧`L O(WZN mAFe&*/[3J紤:E%"#[ҞVv w qDrhLSP(%#jq)(=BhEb 7+VE%Ψ1 ƣSqde9.=(Tg3j3IGCTb0īZE+ :1 jU%kOhkKkSLh49pYf@6Y-_g=(qxQXbm'-D>7_'4d݊:NHV9SyvKDԞ)g] 0>4 ߮|:BT'~Pt-kxQAtv|vxn7 ib}]GY̮/,S:F(8N?ө-K-L7Fn }[ ҧIX;gg"$'.ASHN< kLR3X\Er,2YVV?Ty@gP>tc OfЁ3$#L%AzJF/A/W#G*HaC*4 1 >'4taev27흁h!֌z"bZq;ͩI<KpuitLXƵ-Uhbֿiad]܄\"ХUP .!r):&f]Ms@e_\G-XKu6Bp1#;'kzxXc:I dX_M P/e[05,]X8{DLQf#ï[BSL=MatArB.52;EtE~$@Ys1̔bkWZUJB<*PVd(F?Vj ˨ GT`+Ռ]s||Eˎ2|x|!َzMD5Cpmdd7 yQ3PsyIN֨97DFOD%bnءͳb*Ie;C9ߒ}aM0¯!Gs IKʍ`ɢ HpP#\ŦGwAA&K &YYI -S6׹{nx7 m/-z;dL%dt [s@\RaAb(b_VbpGj $WER /x2"D9zz@Txy.:  Ǐfke.丱lzcs,8ꪃaxDdoP ),Rs)9۔ïU)?T Ozb*P<p&yT,VO:r=̠8@J CdK[ ޓ%)l'd>!?rtxѝn|IuKCG(9Ãjjd˺8FT|oo-%a!CRO9aUUPbC$ywL3A9b%SEE}J'tjѤKX]VZ&Dm(s*[SE;2y]ű}%`wLp<=*$Bfvp‡Iz7Sļo.W/'3D[57E dmZ S ?iH|# ɹH 0c=:6BcUU<3@CWmE4,M;.)]Rə1Z_hĎI]p"Vx~ >))w@>[s\1#&gP"PCPxZ0(,ϮuC` hsZrL#ﱇwDR\Z($:b_''x=lC~XT% $$|a\V'fۍJEqqݷ3B&߅L}1H y._Sej%GrY+ a9k[P/?.dXK:C )u"P}4Te@;>{3֚`S|FGcR;ttt\,9] 7zt$J9kS^Ѫ!IgewӳV\qd"[3xj%,V% ڭO <ɇ9"JQ?i%rqSA -IVO#xwsD-=RxS.k*Q_&E-6l}AHc[8),}IVq~14 Ъ5<|NMOkZ09)SgbI:E{կ |=c*w n#Q#8jѼ:e|0q!MUġ`!U] [Yxwb6ppS.EK#SI`+Ivџ7ʅzP F}<5.33-Fp$+e(鶨=GݠJz9P%}d{ %S:܆9\VmE3n=Pxn{0 Ȳ-[/F /"oцl!UTY4 zHJi'#[RF 77'=$z%bpA x *t8$hʂ#^\LGnYh Jb-1K"1ejDm,XʪP9Isc!59Nn½%?C}] 25Kڠy)CD7SeþT),żC!5>=UO=V\('Su+QXMR$x&cE`D=+oAsM %M&ߍҥsvʮMm׃P,11a'ԙV@4s15%ueܱ=x-|XCqÞ^n'8Нi,{y: 3L) LAC/yC՞ʒݞɥI}OC.S \\˚a"ၺ.̉!uzuE?[n޾}t7b"cs7GcH}^bOWZ5.\KnNPqRot0X]2QZs)O6oO7abGC V4Oƪbr'&|,K!Wr?he]HݵV!i>/[LNLWCd#bO}^mݱ)(4VF$t^]ݍm˸?ts;|"йV fՄW3,@Wx|4ys *φ74,K[x& n=%Dy|ozĐhe!޻ iT0TP0/ ,(q~*J?drn0/&HSPM-)8kYD 槇.(EYJ!cE8>UuM/kSKX 7VVDrL:V6߿jI0_7j2a3Tτ%qgZa ԡM]\].@b8@BbX E# j BA$OOzvON1Qϳ/EQlJVH>66;@C 90ɸCfUm+EsSjICBGB,{zXw)ah1'g`br ntD./%OoYσ\lywk)yT+ey%mxիo˧۠<=i6mk^Vɍw j2Cbߧ ZR+QB[(m1RP*PB,KpJt^ZXT gM/RcvF#Xfp6Mu/隺ʒbkgLj?U q4Sbv IZ orؐRY1g4X z<[Cmj+Y ]  ݠ7k(< ۍp1x &`. a`qUU)LsCkk49mP ŀ&:w$ݞݘʱI64et'b^Ċ(WKI&MNג& xj&[OȬSg5w ,+A~2-cF:H?ݜʲT:08Q),pY9 uBzZ}Sf8G{8Hm-+}|VkRvGd[BPqЕi"QN 1;WBȌ(oQtB(1kRǭJ P).BP _b\<#?X8AumAy_qsЎfw)u?щbc^12gbSOuE3&$`ew!<(=qKj`#`s+P@:l(Ml1IsIԮI kPG 41qL*ٓK8NU>BiḑzF3ıRI'BSx f˼jY#{NU Ij2O.3u[< >]x!_teRlŇg+=9y$L*0vCc&j;gtB̳-(4$:ڎEBbnB]@|%vtEJz &s):+?U?Kr1pn^\VVӓrjaɋRz 1n;*fd%]ԾpCQ.gk$ 6}JO|\CE4HHC N32ur^h9$LX{4@VZ֣g8ks(@:~+Y;FeNj jF,wpk^4U#LTX?Sncvo&r*LD`YeM[^wC)O&vp}^4u5wza^|qf1e{2CaC&1EIkD͗Il[ÅSi; 4JKn"vFl(n8f<\.3bZbC*]4E{ja+>TCJl€ g4HG0,T/^Ҍ.c3k]F)ЁtH|`K5,G}eZ,oȶAߘǢ'piVzQf4I o050BȓU:+)<MjJ́8 Axm+CgP0JΟ(Ǥ~; PʻU }kаR 6Gz 9H!f2Ln۞=-,b_V~7ij4qk20wcZJ/Z@jaUtxi/PhQfI ~AT&iY yi{&D :F(LZa1 a4;W7??q]7]xٯ27既4@- ǜd3JC"#l2Dd OcGr<:qF`:"(GZ>_z:$Im[ 13P4H~H}I%$(pc$B_CS趗 ~_v˪^iN*K_)IK'*Y[q)-)( 87^3 xTز!nѩ[㰠7v:2g3 ?-{HYAx :Jg7xC~3tt1h'Lߨ ֯DYhr$L ^̤G:+=rn?nf].ÚT &'`jla] adbg 7!RjgkЛH7rӆ*K= F'%,FlnnrşbOpJ/tR?|Gb Y>Hzmw=@d-GMsϐZlQix .]"HxH2C*ސ)^oVuT W0FI!=^*{lb! ]"П|c~-ceɦ.,Ĭ]>/fFI8ͭ/UnTqS[qh?  4 t%+7 L>Dscr Ѭ$'3sIջ۴!I"s;yњC $E'>Z"YJWmBcP8ǥF6O7m`h4tL5_4MEEdT oƤ2&A g|cEQbL@YL.},BГVR B0*|KQ_\yn/m87(Ji>`hf.6C_"u0 VjzrVN7XOtrNې0d:A *l{P@s$*lTS< z.3D''/e8Eۭn|k$*Gx)Nz*C5gVlW3=v(,3:M&u 2=G|1&J5#3onx"y#uYDߔ#:YH;k30o!& ܪ{lo>#n)|9 ?],AʟZtzFQ,f\/ 0Mޘ2nfEӍWR|fJ{ؚa<T^OT{$+=mDDG_ij wSHꓐ͓u &QCl|@ۊ/g)4%W"(*%O{f>-P c)[qwp.[pT^nHIr <*1~+k Dmal>Z3#=tJ׈5DDRq& `>5 NΓ@NWqjjTV[X.R$gX>?wPfg +Szay-1Qž:zEϙ&>f@yvy?&֩a;%:Q]˽K6(Rٿ'rRi*PS<趗 G9Q)Q96 6x8tWmL2˞RZaKPXmI%FȸfxZ89i&UBh)}mp &!-U`Ykuz"#ߟhBYoC_ 4rx$![dWj*E!A&(QH"J:_-d8$mP} aL2aqDvEm%pjq$őBG5F v QDm{!3m,CȠxɜ(mRt@sK$\݌aG IQW_-27vo2ױ-SK҉2h[EzU^Q|fbfs&#a*Ů+6.Q] c!6ulN-f YN;4G`vJ*"GJ>f6 m*;6aBuT| 8!H&vrbG)uyډT͐gDlòJu^}* }"ܮIʔT"1zH p;6EJmٺH:gE'/V{o tMMuCWu -*){D[s~|qB$ęUZLF-j6).$megNe>8fẰwhơ%Ugq @΂/?iIĦ4X6aS;HTG}NR\톦Uھ~6O e2 YFS/Mʸ;_/o<]`BqsKAlTjӷ77. [LbmgEov9J`)+?aLE+`Z{p>矃{9筁j@aN̥>|ŖrPkGȳAʧ꒠,fE4" v`)XGXh> q= n5~17ȫlYhklQݵW!/--M^׋#&XLvM.@r.nRt.'Y.5?yebrO1~~ȍߙƥEVdu1EŜ*ba*P;L%jC ؀E@B:Z }\[D@ErG-st  xm"hYm>8qYc%^I[|;eXyXCY=rD4|C{\V]l/J .o$l&M2ydئ{J ~ ӧ:{P ,qM낿^G&Fy`*ƽ1:䍉oz߂wLu%A%Yl6~KަxMKjfr}nj)wT:*j3[nݣ͠t\e?"bNAidxqPlF@IDATa@.Bm͌O.J(\"hhʸN@1PkIpt)' Sn^4~X+UJe'z^X}naXP=dyL^M9#YgV_ 9ƇԄNO? {ꢉ˳z䕦x {ĎRuW):oh, *(q3Q%?sI!9jx8O,`6CITjdJZed pm#m3?wm`p*sP r bGct`Gb>z:@4 ̠8H.-L`?|%f7X)^K cdKI'*RadhuW vsc (+` D_zRtzFO ?/zQH0 [%_^ȷЧ!*EUu%'Tv IR&0[f<f@dr4EIJ>ukUx\2*q l2/i"9kّ*N,)~ŨԄ=Al2qL=`lj.z@R.L܋46=SΝѽwfDH&iU3a]UN;E앖W ?Nxsc'ɬ$0NGi ^N<`)?K͇J!^bl? wzP"^z  `}AQ#b<CbQ ptvZ7?oP9HcŚ~ 'zDsa™o {a(.u!b]B]V ۚzeb}Zm|blQ&7ՔfeTn95_-1%d \wp~ U8ђ>@E/ .q6rW鈫nHٳ~<#6u8R*p! qL1r%;a Qr 8`!+H՞1O7csopnLH+>= 8QRk')9Tt~KMxQ4/ (CO2|PR8q6<5p S0%Wf~X.݊fy.I{m^2 6[anB8~JY}`^ v_>^>&(rgp9ed iZ:DZ!#UX\ m %:1ԶAam#$'/q?0zV!*ۅ3irs{1o ̳<͙  ~T5vPM , T#)q;Ot;A>h@^9+aҋVerӐ[P LyH%XH1[c|Ц++-Y>/ݭkAb]'7Y@*XvFOjxzNTơ3ag' ?NZxAX_**j2ޢ@tQBhIiO=MEqВd ܅ FGg~Rl"C(q=E IS"x1 x_ W=jc/E{Q DQ\t^`(3Of7[ ;>];{rr co\=3ڸawb5jwK !C87s*)⢝[tj2 FgW8 T澚.9&m#:4" dHXC5lȯ-ʓ/ ўr!m䒳Ro߮hV!]Nstʦ!lLRS{;J+\SP5܂."SAǑRnމAcH:"tTA: )s#_@lR*jwKlj7CFSǒ` ʂng͋EMGZ8ҤFN#ٌ:uC9Y[4=5C +5@8.7;03.[; >k؅s]x[dJ??Yc6/l},a9fNɩ0xעK8 ߆\t%Tigst ktT!mb uw6åЩ‚:y{ګ0Xb{lZVz$}֮3DLc$%kڗY; Nպ8"99,9o_bq bgd㟤;B#=c4:aUqp"ˁIGrvc gx[̟&B"&ɺZT個<948谪1Dݐ1*7 #RҨg<zjkumTX>Ըζl1 zel z HLlWx ZjZFXHw}-hARX@FrJsW:_IoH}Y!Bl2R.͝3sv8)1!sSH\ 1D  =M5bTbZW NA;''ni-3Sqċ)TEiQ`Y`\Fߐ,;XfIn!IWX~F͑%̺U^L7'}4\=  gz}MSiN/W鬥@i:,@QZf *R{ϩ|92%Ci 0sb5`y0 BPh& QmO{|;ZuS~usF1(9vh TJlΚ4q|O wM90`:gb} OMcǻpf6J6m֦9zvtj UW/L^ D4 sN^4s?Kq`133D K%l E7X]{v>bt 6RPM q !A<*%' 4+9=AyR uTF.TgLyI142 *ug] nhj=z ;;=?B|K cpR?!͎/ٸq2[eq7Λ_O7y"6}Ao6yōQ??tЏ\F CvW3Vw뾧jLonKrAR:[\ MǏUe)JUrUG 12v.!gżh(/7kmtShwzDNRaf mU G6 ˉc7/Lങ itJ{IwlLA8Ē`d1NC@c/Kc!S7܌ϐmUvJq;.K Wfy]2p綏~#;/+K }6(8}Fzvk_,F|()L(aHrb+cCg':Xi _%7r:G'N:b^ʟ_-s"$!#Fp _u퐙v:[HKX&^zOLx'ct]!v0ɚn ბ}(?-ro37X+?^ҦM/\QMHIF̢KYŇ?SզfUz a&F?w;T 7R ]ȧZ6Oվ7/١2 +&}ض 8oßwkigH/V:MyG&|o.U Gr^7LrD`w[؆1f/be'y-Py"|k^AvP;-_ ŷ$|Tq/nX)F,ԯ=ZYӬu<њ =4vU|TvlC@a:?rojjJ ,ur%p#B Lya01wy1b ܘ Hx+ `982ݑB,XB&P/Y|NS%D^jIJ<}zjq5x##0en*> M" o-QGHi+7YstG8XǷa WJ撼l7:1vbK=>7ki wtCch9qQ8qJ}IoJq<*:e`<9evq_8w**b༣.*hFQ}{G~SHMdTCdS@:#GPW`^JQ=q/ ̙&|wIrTc|ߐ [C Ei?74XcMbz[z%>nV@fJ{>*]7|ҵYꃶ}^lXHZs NRI3 4$!mbj|V2=xa7`P?RCa\y{, 0ڵ.T<\0 6-|"bu & lmI_?~B'aB5$A >f0:OJ5 3Ay! mbEvDv(d)=ČIܤ `z׋>M FI̼{k61o G6kBRX/|*~i1zȼic8g\m#|vNٞvχ QPE"SeU:Zma xvD^;qŃ|Mq$DOq݁H5|eX Br?["- y_m7꾓z顲cEyr* XʱeN"lC/DF#7=ӯ`6.%5_RWl"i[a+WxeL ﳭ }3 >IYVd`Q F`JNd!GSoýeQ0ۋDx*z /$%󐠚pl5r[E_QOus6;y`Ѿ^*>ZۇQr\] )^@ }Jb܆ jRL*Á1<.Mҏ0c-[1֪y4)t^;LuqE_kݕinRj'zם i>rjqIm6?l|}kgҌ$$PtWbc(p5zlWbs=E$ׅ)Ҹ.Hs8i>R\#^jRK!fmh#7S{;OU@@AcvD)$.\VN # J+YE[SO$Ψ#$p` U úVzD؅v7-VaRsqW2/ J4C/]g1K37KaH/e~T`h6h;B] [HRk>'WTh^v~S4`sjOރ nQͬ` ,ypx(=ڬ Y OJZ`^I_+ȅyL![JnP%#ސoJ>? +s_),MϽ5"%N$J#H(c2@;GsA;pOc%P(P|@]w@^^o's]֍/ţQ\!G}}Eh%N*$L'fg<ӻDR@Y 5^4$=~2L`P mzҼ@$g\u:h1Ġ\&y59[xAnJ ˨U&Oqބ0T T@IX򩻩|DO#%0)t=56$p60,{ >6R[L+F *ϾxPn((t9xzi[!QSAEڿ9 uUquj XPQH⨮ I31,m=xIp`%|hW _`WuL`380,qĩkwK+f8lHIN/_3ܷ%QRrhB҉^7cX6G< ?;<9I ]@q\̩cā2'uhOm|4U8 :9k`ذ/@p2;ksp$a+HbS__Т*x20.Źzw*6)"m:)=$&GHM*9S tXk;=5QW_.ʓvi4OTrO]E>b !#+a_t_m<VKbԌ!#vvjiFM'cm|?4od)ޭ4s~-4W%7 ǧ6[oH3Z)0*X. ԩQdߨ _Hɵ1DwF3t|+u8-^('[Jrq=ȌoGδ"&- gb@9x55qVBLDP]@\Lq%ċ9{HHA,Y@>BH$4AV9#_Dm2ߙ(@B$>m 1gASE`_S}"T2Ptz)Å0D7ܵwAmƫ^N!Cl_D\{ׄ`4u nQ`oXbDLMxQ] =s; V@;#t.m#oj/|/T5OᰔHI{}]ڳۯ,!xKA!" Ұ:_ d05ku=Dx<3J^7]~_Κ9 *t`{JgyH&F#Z f Kt>2K&%2j_0 { +> Td1ⲬjB@*^utJ,.\CDrh8\`J#m l .ViY ]匣_=D!!89G@0y {kKƇ?iԸL-K0pnǘX6tALMך4s:\(̇y֋+ -ez);zn! 5M =yEO X6\>Btzwu/~XTt肄rr5 @zr(\ ^}t4} SlBPkYQ[#[QLW\/':|Z :q߰C/>77XgKNXȗZWJ`xxhn'oɳ5q!ŖpeIٱgy~$'h-r*cALE!mLGIUjp9 .d,#GRfXO@E<(K`ʶ@5SnuH;˷ʢwV}up`< ݄q?!{^yjj7W t#?6Hȷ*OeBl^ڤ.&U?rRW\j˴VAiA&I![a%sWS"K g5:.W5<kpȵ b B)AiϰW s\G$V}?+h@aN Ķ~k3DCp3oF2^b[[BHXS쳁ZpɶH6R)fP}Ɉ}rӅQmhA!LѰ]s)u1vGeLnT#KqXIt2 2Yܪ鮬bru2談KCꢩLɚ/4>bؼD{ %ň6mޕ'Ug~)@7#YX.Jr[qULA&{}3v}u6E|ce"趹ݡQ9`T;XNȺ-ܤHmӸ2d3ȴH ܪQ+E ZEPE5^/=w !mƳ J,Ἅ%;cz@ϒ5" ٩-Z wS68޼f#}T=3T(03w'LbZ+>DQæ\εѥ+;bæn4CnQVlfMsP[!f|)pGT;X=shkd.1U|x)ZfFmjԽwXo>y&hU2& A{=z˓cIvjݑ`~MnPdS,O\0.9RpE|lAGAЌUټSƌQHlI¯x=3Bh&>[gSq&DGW*LW\28ቢ@dn|k,\'`ȥf(a%X:-sovݿ}A 7DU942t:k Gt)M&J;zaǤzکNXO%[acѥbE Nyȥ6Z_B`yXf3H-ݐS{YgL >e$/Yd]ȸ(!^o5+M z]\1( N -\2b^r-;.j "Y;LQt8^ ?-͝^L_ʚ`j{2~S[1M(uS̫L MkQ48_*7gbI/+ʋQd ^<.#4iiͫgJU+$<7MlXnݵ,9g;-Cݿ9Nصzj..UklhSt*MId=PTz^>ːCuĆ Gq6cj T)1U@woSWWrOMJ*aٍiRi&R+ՆSū ja.ӓߋ oJE\ یܔN<&pwk;8{'tԬpލ<#5Q~Sp3Z]狶&,Xu^KYzZTs1#f|^  0*EdGkufnj*3Z+~w*Jq*w_mroq,,3euQ1ǑQJKI1䠭zU9ёRYg!{+?冓ʔ:#Yq<07!;6D{3Ҕ-rU*`aeLZW> jjYlLX w객{atyvqߪ"v:Ge ap,4##.̸L2˓ɽ$' : 2z9aԔtb(bNɵbׂ!%)fًhoL@T!قm͙Yc+/^T>aiR?͙+NRXWD._s 1KiwF\j/>a٫{dR[\7|Z4Dhy<>^9\$*S}[ 68%2N`@IDAT5'%Jj^sB S4vՅRɀwfW7 <ȋdV=N۝*AsrUycm,kIMT PXd)KB*~^P5˜|0.5tdTƼt4t(ogqҺVs<#IEϊ؛ɽD+6f0C|_t? _M:r՗ nz aLK9q] w D`zJ!׭BL&X-mϏ|K)M6n,N,:558\'<@i9B!鱈h9Eh4rb$J(u&yUK fi[gJ/g\.CеX®qʴAw/ו/x`Ζ*_a`ʹ6[\/lMT 3BH Y(aR"ng4>-Z4%E{ꑌHl4cpʖ߳ !ybxD5[)PFn?7˙`tM0ݑO5I7I첚W#@Rә91W3X\ t|P+LF=m JKX (Vu*XOR ٘v^qNsg>gf5 aXtLLRL+ȌS}ӄ1zWL'_0M֧zo!7.b"H9D"WA 9B)7Rz!y^(C[!K.~ Kf A:JSEI5^\LNJy*>&%:)1;H~iD*;k]N.ێ/G X̅Nj3˟\ݭ\UqK>9H۠rǙ[p+4$RO"fOvBjS‡Edc;m>ǫ{n 7UDxbW吆]Ls :b(<M oRx'R30d9!Vy3Q!FWuπFCp>vYtSm JG28ϒs+zJ e(wԧZk+w~Su$%)-,G#.ٰg4"@ jzj\]4 8dz7ȼ'ބ$Ɓ*VzGv(UWf>uRj֊3;DK5 '(nO7`@~+;z7 Y p-_LiMjy}ék4>w@(|"*DL=*%o7X߲mUB8DLFg |l9huL(f4:|uH\(P* #EKXN3Z# ßNj"V"-BiE&Q}5pmaJ=J[JIȊ^wI t"FϘir@-JKX9fBRm@2gWl;]EC6)3omuq"B#gt- 25=15]S*cĕtI3^}}}'nH.ވ\5vh_>U^3.|lXEo6X!4?|2p4ut9a?$}l&E2K}}tz6MdC#bO +^;:6=5kPZƑ-]~2B҆88w:WQMeՃ+1 frPy-Êǘ3 Ϳ[w%6 X|f@DRa5&ؐgO{Uj\XpO:Q[}\e:WeգhgI.2" &jK]BT:O}j123ţ P[-^^%$ 3+Sl#,ٍؓ$z<>Ƃ奲5Bt|j ~uq $`2`αU+VW :N>sގn\%DdI^ aRZ,naelT~VfBרZSc,_JYx0J4Dq" C B%ajjON'I;6j =xuYQ$''R| (@1 PbVF̢I+v+4e{[ 2}3̨fG:;Duy\Ia UIR&]]lVKn^<ۈJJ\v/XuqZ|dnD!s3iBz'uU'XZx0|R,T=!,`a]mr.>;cz 3jpGe%V9W!\ P@_THro]CXooEtEjtCؗB֏_Æi+eOPX:ag7Gfch-3QM#] ,mP}WZs1!_ `K~s(Q09,[{)~s0x}wHԘbe / Ghz]1:LVRt=Mw3:DT-v@ iրw/:ND}Hㆂ\1fEeg<(4qYV¡wK]}PzTD8ȵ=daސ"qjj /~PcQX]rXǜ.g,})XSG1ފBw!)T<2/bH5vMcƌ\Xj{clQ ˋS.) PDzc;TțQq12HYOe'fU;JE׺>3xQ nXB-guv9T#8`-奰ܖ ܪVR;y~l aB3w "b:tzJet51p+"%҅$_dsp0Exaa&ʯ 0kM&7)?{ܱ#迃z{0!ҌV\yB1Wq9͋Ki txE.4~RDeNF^0QLB(liV9^fesY/:f*ˤF0_5g"IhD% E+td/e\E.1>mͽu7 UHCZ'TuaL:Kf*g܅d!^|GcJNo1<ÙaBRZD=|c'a.<]3cܘ|`P RddH=iUl}9Kgrsx%"eeUq6,o̜:@?U<ឮn&ВC`#|^ARQ;$n6>qWKxc&Șg;a?M+2{[8VKs1# 0KYrm)WQ#dg|b$/f!U5ϣ7TE7ǼEyjokR\uBRpQ'cz /@ý"h ιd%_[ePOԌ5MC@ \ߕFJ:81t$v@-6gP̠i^>Fl`Tr}Ii@E͓ObM"7?T1B~ޱR*gM %_ؔZAnEQ5ˏ:.-?1O2 ύojoneH;p/HDrs*Cd\Ҕ.QF> *9pRQ_QJRRљtxR3736 d^ K 'F87Uj}ʒ{۫ڎD%K:ޝ{/k z9}z>cy`{/h25w^- ZNX`N-Bm0 -ĩ_@H @ռFH7ŝ<`CD ~^QY,ӄW ZVk1Y$)3.89]wvgn9d۵a4{T<ᮩNk >9r3d⅑<@Ld닰*[ie0*9Z{x.ށHr-e#qt$h(nie%]!^%-Je6vP+QM :ǪϽFͳr!ax!2TD980djy|b&oYٳfԾfr9_>\?`Jv~D#E,LVRAFz1gCn˘3̿f79)xۗ`nBfPUuȪQ^,P(j-ӦÑ،Y&9|3l -K}@TN6 DlVsdaںcڍ3~ 9z0O>rrFUH*~]k?|b1# =uzaPea!Q||0 ps#b O4iM' X{1ԔK Z8?=3: D'] *dAY=`.(c؜zْ{p0ҡ+ eYlA|ZXLrɍ H9T?nb=9C1#H3wePE4DH N/nˎ(^WI^]- k ρ/  =5RTmmj _5r5cI>m:oڴ+"9^D#'"j~A/|(|dpi#\/^Y|.CAW<xNȏn4aM=bT\b)G?kqn곈  +ᶜ+cw^ )o@6{u;8Jx_y!up܎±\m.s1ՀՐ$84Lj&${χݨlpߕ [BBi2i"\[S4E~V~.q +ǀ)Je!p ,1,!G3!lrC5/-B %pan OY%jZ/?) *.VF\?K6 fXnLUL:/7Z)4\Ui*2g/X.KVQ2ܰi+Wh)k8m!2xlUw>#`⯅ TS! ]QȿX5:PNto%3[Î{]o;S"h19̗97hS2u+ *tiǐVȒAWYQ3I<)'nU1Gojh.4}i&%QB?Ί2y #OodOui0|4p.o E[:?_f [I.yx3ax.ǝ`!Xyz3 yu%k~V*5q:j{Iw G Jqv &0rTS OWh%}הsC9w`?݅0)|nv7 ݁Eޙ[U&}- l1EC*Ԓ:G%XU0Oݭ L!ҭYgyIH0 hw&*ZOέj7`^ޟ+54ϕ"uN66W ~j_;HGSqß@R 7)˲-GJ.Asrl)oϛ w77VrKų{p,JG=HAN ӣpLl{5,SŠ鵳Vo”_[q1O߄ҌRN9KWV jHAzhk]/=|K͇״=5/D28X.4e.?ht3dIv_׊DՂT`aX4X0|hMo?DNC|-Q?I>aꮯo%svL-չj;QΏ\(A:B||!Sn&ՒԎM_Ap1qq(4ڶW :K_ L6 )hps\^iw8qsI6jD+aWj zWjv6|`ؽ~wC>R\°d F]3⫅uiӁϐqBf kH8dq$fmwDSN9$/v'WbHbc4M ,`Y4†x@{+BQId)PKt~j7-.3h2 d9 ;2j<|eG29ҕkZ$X`QO[Xdl~־>ruj6]{:) rriJ]x' jU j`6+1,L@fzǏBr jWm!ޙȩpuS^^*b>m|que<ㆎya_)"|遥һ<%N ŽvMqpD_"t6rIܪPWk0eVɒ,l1O0 ȥd>1o%\;`tgKaR3]^ȵ4 .E07H Xmr+'|r\ٰ7_V2Ј۶)6TY. W=b^ʙ˙ZEZ6֜Rnԓxe v۰}TM*ɼRr񊚐G<%Ld;bP:F !ud`u)Y(@K:kc6][̻A&e3~EfbGvԊNVbĕj;.ğzxQyT짦ڑTaѥjg=Ot%Ol_NҢߘ _ɿazbUѵ"dJi}/\;N&t7WCݨ̏esa9HK8g߀Q T !~vBr6]M閶$Ȥ`Dpx{Nh.Rzp%hVbFQBFVkTwtr6q I %7P%K^ /kŊqV 9Aw55."*7@BM yEE8#ch5wZv dKaя 8[kxVe)o %:N*4*v$OVqcw7| ΣS|7 "1k  à)@v+{_ u\?.!-egA/-1#go4U-]B9Rj#Sytm|Xsh nU=ʅEL p7i7@KעJS\ː CRVb꺧 VnoYa_Oj˅&֬䱒ѝVk[,yt tkA[Wqv R(_$H:|Ծ'vw4?}X͗|}i8aV̗Z5@/0Jm\=aGGth\L$QiER,*"|}Ϛ\HesM#Oh!Sd#IA2%=xiNM(Oozf,TԯB)oWRTkQvx>H̟+X܉*T<|x6+o1~r+VKckGo"._s(!o.=rϑGe_6 Tpe$psCu^Ƚ9u癰>GC{'& mu_kJ;WVMk@1l-1z maER 0Yu5Ǻ< @#S:Z7I/fTRt[_aⵌ ẁ+JcZV2 >~i5ҿxJXBi`Xa~b\Lx$eŞH:tu5\Th1L%K pF8u_3>6BYj 7Կr!\f7Ͳ=8}_l|E֯A?\:~Dga7i0b4QK {//BШLۚSB-juō",5,dU0>)تz='nx2˿*n |1E:%^$w|Z |QlMc'-Ge̋?SBQe-Q&Tպn/ȅޅeU"-w:l&\M<$3/$uΕLUd3DvnQX+zT'q`SƩo j9Z8V` mn!SbQ~!`nsbjʾnүQ!C[xסޘqdTG{Q3=!7gx^cA+>wvm/Hj-榢lUfm]Yb3ϿmY,7|I`,rB\(|:fnLV & Qt.ʈ|I 5fx?38ATZoߙ7jV&*'a-.mD:p:P^yu*%vQQϩ}ؗ%|;dȟf!׺f5 n'^dgC,it<XOc:9S0vܒOB}V'R?dЪ*E=v.(S18ӷ(B;{tԩUNZa=q\n,/_Jyi5tm^CLb̔7b[ QwDz\ۂ98#@!@ʝj|@XhZuemKYVzX_+9NfC$=qMג$Pus'=Kj2sq0 ) )1 _6:*f4eRW=qpJ֒%vjNM8.zEݢ\;[41 Aa0-ү7oK0M!ڱ|zk}['NAZe"nו3K6_syda_ Sv[rbO(]I+X܉.WCT1w"C;o Kt+s0~$Xyp<ȏ_E!&"݁W~T8wlaA|=n݋H=#2;(G1Tz͙CYUM  Bk>bϣh\ ˆ6vBv7/_l@ (imZuӉLʅ?[ƠuWoF 1{;M sI-Y`wu -)?h˯ҶՎf^WYFiX:GCLByq.ZS<MOT^869Dm=htM k&PˎʽLx>hSU'|nj{ˡ*ɇL2al0 DppW%YfMy LV;Q G;Gh2sE&!R A@)BwؗzqQs|N:DtCm$9a#$@c'Se<){ž\zʊet|O.dKM]1j2˔r?`48sIDAT㋭6w4oP mdZEٱ=6㻗B}B˳$^[Պ0](YnYCl @ 6('-yED%t#vD$tM-HtP* ;l(;+)Hp[n0sOiM{>TB>ݾK$r8׉ Cb=!awlڔCULQzl%7|QEѵCgN? LKC`⪻9i:q֤+/sZ~b:w!':ۧ*m4}ܹ4JW˷x[/堠W e? u%:`Z<2QM_[ AzY-3hl!3 N?+4sW4$H$šh'I7x_}{ IENDB`scikit-image-0.9.3/skimage/data/simple.fits000066400000000000000000004160001223313777300206130ustar00rootroot00000000000000SIMPLE = T / Fits standard BITPIX = 16 / Bits per pixel NAXIS = 2 / Number of axes NAXIS1 = 256 / Axis length NAXIS2 = 256 / Axis length EXTEND = F / File may contain extensions ORIGIN = 'NOAO-IRAF FITS Image Kernel July 2003' / FITS file originator DATE = '2010-07-02T15:10:48' / Date FITS file was generated IRAF-TLM= '2010-07-02T15:10:48' / Time of last modification OBJECT = 'm51 B 600s' / Name of the object observed IRAF-MAX= 1.993600E4 / DATA MAX IRAF-MIN= -1.000000E0 / DATA MIN CCDPICNO= 53 / ORIGINAL CCD PICTURE NUMBER ITIME = 600 / REQUESTED INTEGRATION TIME (SECS) TTIME = 600 / TOTAL ELAPSED TIME (SECS) OTIME = 600 / ACTUAL INTEGRATION TIME (SECS) DATA-TYP= 'OBJECT (0)' / OBJECT,DARK,BIAS,ETC. DATE-OBS= '05/04/87' / DATE DD/MM/YY RA = '13:29:24.00' / RIGHT ASCENSION DEC = '47:15:34.00' / DECLINATION EPOCH = 0.00 / EPOCH OF RA AND DEC ZD = '22:14:00.00' / ZENITH DISTANCE UT = ' 9:27:27.00' / UNIVERSAL TIME ST = '14:53:42.00' / SIDEREAL TIME CAM-ID = 1 / CAMERA HEAD ID CAM-TEMP= -106.22 / CAMERA TEMPERATURE, DEG C DEW-TEMP= -180.95 / DEWAR TEMPRATURE, DEG C F1POS = 2 / FILTER BOLT I POSITION F2POS = 0 / FILTER BOLT II POSITION TVFILT = 0 / TV FILTER CMP-LAMP= 0 / COMPARISON LAMP TILT-POS= 0 / TILT POSITION BIAS-PIX= 0 / BI-FLAG = 0 / BIAS SUBTRACT FLAG BP-FLAG = 0 / BAD PIXEL FLAG CR-FLAG = 0 / BAD PIXEL FLAG DK-FLAG = 0 / DARK SUBTRACT FLAG FR-FLAG = 0 / FRINGE FLAG FR-SCALE= 0.00 / FRINGE SCALING PARAMETER TRIM = 'Apr 22 14:11 Trim image section is [3:510,3:510]' BT-FLAG = 'Apr 22 14:11 Overscan correction strip is [515:544,3:510]' FF-FLAG = 'Apr 22 14:11 Flat field image is Flat1.imh with scale=183.9447' CCDPROC = 'Apr 22 14:11 CCD processing done' AIRMASS = 1.08015632629395 / AIRMASS HISTORY 'KPNO-IRAF' HISTORY '24-04-87' HISTORY 'KPNO-IRAF' / HISTORY '08-04-92' / WCSDIM = 2 LTV1 = 0.25 LTV2 = 0.25 LTM1_1 = 0.5 LTM2_2 = 0.5 WAT0_001= 'system=physical' WAT1_001= 'wtype=linear' WAT2_001= 'wtype=linear' END &&&'&&&&&%%&'&&&''''('&&%&')((('''''('()+***)*)))*,,--/221/.///01368877655667655679:::75555554577766689:;<@B?<;999888755788656544469:;BHC<9:;::::;;::;;:::<>>==>@CB>;998877898876789:;<=<<<;:;;:9988888:::<<<<<;:;<;867778:<BHKKLORRPMIGDA@?>=;:75532100/--,+++)&&&&&&&&&&&''&&''''&''''''(((''((((('%#&)*+*))*)*++,,-/46410010113698899876578656789987566666667877789:<==AC@=;:::99987789976666668;<;>A>;;<:9:::<<=<<=<;;=>>>>>>??>;998777788888889:;;<===<<<;::988889::;=====<;:::988778:<BHJKMQUVQMHECA@@?>=;97532211/.-,+**)%&&&'&''''''&'&''''&&''''((('''())(''%$&()*)))***+++,-/7;62221122358889:97669986667889867767787799::9:<>??@A?<:99999::999:888778778::99:99;=<<;:;=>???@@A?===>==<;;<;9888777787887788:;<<===<<;:::98999:;;=>===<;9899865678:AGIKORVVQLHEDBAAA@><;97532210/.,+**)%%%&''&&'()''''&&&'''((''('''''(((('''()))))))*++***+,.36324322222368999988899875556899887779;:99:<<<<>?>=>?=;:888899;<;::8778887788988888;<<=<<=?@AABDGIE?>>===;:9:98888777766887778:;;<==>>=<;::99::::;;<=<<=<;:888643456:?EHKNQSSOKHFDCBBCB><<:8543100/.,,+++%%%&''&&')*(''&&&&'&'('&'''&'''((('((),.+)))***+****+,-.//123211012479:;=>=;:99975579:;;:779<@?<;;<>==>>=<<=<;:8789::<=<=<:778999889998889:;;<<<>?ABCEGIJGCA?===;99::9888767666887788::;;<>>>><;:::;;;;;;;<<<=>><;:97544567;>CGJMNOOMJGFDCBBCB?<;:8543210/.--,++%&&&'''&&'(''&&&&''&'''''''&'''((((()*.1-*)))*******+,----/01210001358<BGGC@=:::9768:;<<:89;=@?=<<<=>=<;;;:;:9988:;;;<<>?=<:99:;;:::::988::;;;;;<=?CGJJIHGFEB?>>=;::;:8898665568888899::;<=?==<;;;;<<<;;;;<<<>??><;;9765798:=@EHLMLMNKHFDCBAAA><<;964320/.---,++%&&&'('&%&'''&&'''&&&'''(''&'''()))))),-+)*****+++++,-.////01100112246<CKJED@;9::9:==<<;:9;=<=>==<=@CA=;;:::98888:;<<<=?@?@A@><;;<;;;;:99:;<<;::9:=CILLIGGGGEB@@?<::;:::;:865457888:999;;<==<;;;;;;;<<<<<;;;<>>>?==<;:879<:9;>BEJMLORNJGFDBA@?==<<;86421/.--,+++%&&&'''%%&'''&&'''&&&'''(''''''()(((())**)*****++,+-../0000011000122358=AAAB?<:;<<?CB=;:89;=<<====?DIF@>>><::99778:;;<=?ABFMPJB>==:::;;:::;=<;:99:<AFJKLJIIHFDBA?=;:99:=>=:75556889::99;;<<<;:;<<<<;<<<=<;;;<==>>?>==<99;=<;;=@CHKKNQNKIHFDBA?=<==<975310/---,++%&&&'''&%&'''&&''''&&&''(('''''()((()))********++**,..//...//000001234589:<=<<==??AFGA=;98:;<==<=?AFJIECCB>;::9889::;<>?@DKXbZJC@><:;;;;::;<<;;;;;=BGIMQOLJIGEB@?=<;:9:=?><976568999:::;;<=<<;;<=>==>==<<<;<<==>>@@??>;:=@CD@>?ADFGJLLKIHFDBBA?>>>>;853110/..-,*%&&''&&&&&'&&'''''('''''(('&&'((((())))*+++****++**+-./..--..////0025447:::99;?@A@ACEB?=<;;;;>???ADGKKIHEB?<;;::99::<>>?AELXc^NFB@=<;;<<;;;<<===<=?DJKOSQNLKJHDA?>=<;9:<==<987778999:;;<<<=>>=<<=>??@?><;;<<==>>?@AAB@>>AFKLGB??ACEHKMMJHFECCCBA??@<863200/.--,+&&''&&&&'''&&&'''('''(''(('&&'((()))((()***++*++++*+-....--.////00124448;;9769=@@@?@ABA@@?=<=AFGDCDFJLLLHC@><<;;::;;=>@BEGKTYWNIEBA?=<<<<<<===>??ABEHKQTRPNNNLGB@?>>><<<<<;988888999:;<====>>>===>?@A?><;;<===>?@BBCCB@AFOVYVI@?@CFHJMNKHFFEDDBA@@@=96420//.--,+%&&''&&'''''&&''''&&&'''((''&((((()(((())******++++,./000/...///01123336886667;>@?===@AAA@?>AFMOHDCEILNQMGC@>>==<<<<>?ADGIKQTROMKHGEB>=>>>>>>>@CDEDDFIOSRRRRQNIDB@?@A@>>?><988889999:;==<<<======?@@@?><;;=>==>>@BCCCBACM_mpgQB>@CEGIKMKHFFEDCBA@??=;7520//..-,+%&&''''(&&''&&'''&&&&''''''''((((((((()))*++***++,-.0112210/////01234446765568;?A?<;;>@AAABCEIMOICADIQWXSMHDA@@@@>>@@@BDGILPQPPPPONOMFA@@@@??AFKMLIFFHMQTUVVSNJFDB@ABA@ABA>;998999:::<==<<<<<<<=>?@@@@?<<;<==>>>>ABBCCCFRknQB>@CFGHJKJHFEDDDDCB@?=;86310//.--,%&&''&&&&&''''''&&&&'&&&''(''(((''())()********++,-/0001440////12234679:876568;?B?<;;=@BDFIKMNNMIEBDKXcbYRMHEEDCCBCCDCDEGKQSQQQQTY]^ZOFCBAAABFOVURMJHKORXZZZVNMLJEBAA??ACC@><;:999::::;<<;;<<<<=>?@@AA@><<<====>?@ABCDEGPcvrQA>AFHHHHIIHGGFEEEDCC@=;964210/...-$&&&&%%%&''&&&&&&&'''&&&'(('((((''())))*******+++,-..//022/.///134457;>=:9:879;>@><=?@BEHMRX[YSOLJFFKXgi^TQNLIGFEEFGGGFGIP[^WRQRZfnk`TKGEDCDEIRXVTOLJMQV^`]ZUQ\ohREA?==>AB@@?><;99:::9:;;;===<<=>?@@ABB@===>===>@@ABDEDDHRaqlP?>CHIHHIIHGHHGFFFDCDA><:74210/...-&&&&&%%%&'&&&&&&&''''''''(''()))(())((())*))*+++,,--./////..///145668=@>;=?<:;=?@??BFFFHOU[die]UPNKJMVbfa[XVRNKKJHINNKJJMUfl`URU^lsj\SNKIGGGIJOSUSPNLMQX_b^YTWgG@=<<<?@ABCA><;::::9:::;=>===>>??@ACDB?======>?@ABDEDCCHP[YH=>CGHHIJJGFHIIGGGEDDA><:864200...,'&&&&&&&''&&'&&&'''&''''''''())(()))(((()*))*+++,-,,.../////001256689;><;=@?==>@BBCGLMLMT\bimmf]TPNMQV]beeda[SQSQLMTUQNOQXfme[WY_ikaWTSQOMKLMLMPRRQQOMQX[][XVYiF?==<<=?ACGE?=<;;;;::::;=>==>>>????ACB?====>???@ACDDDDDEHLIA;<BGIIJLLIGIKKJJIGFEB?<:875310...,''&&&&&&''&&&&&&''&&'&&'''''())((())))(()*))**+,--,,....///01235778;<<=>?ABBA@ACEFGIMOOPV^dhlmjcZSRSTWZ]djmjaWV[YPNRUTSSSU^fga\Z[__ZXZ[[\ZSPONMNPQRSRORVWWVUUUhzVD?>>===>AEGE?<==<<<;;;:;=>>===>>=>>@BB@>>=>?@@@@BCDEEEEDDED>:;@GJKKLMKIJLLLLKIHFD@=;985320/..-''&&%%%&&&&&&&&&'&&&'''''(''()(((((()*)***))*+,,----.//////0246899:>@@ADGIIIGFGHIKMMNNORW]bfjkkh`ZWXXWWY`hkg`ZX[XQNQTVUUTUZdhd^[ZZ[\]afglj\TQONNNOQTSPRTTTSTUSSWUMD@???>>?ADFE@==>=<<<;;;;=>?======>>@BBA@?>>>@@@ABCEFFFECAA?;89<BHJJLLKJKMMMMLJHFDA?<:86320/...''&&%%&&&&&&&&&&&&&&'(((((''()(((((()*******+,---..../////014579::<?@BGLONNNLMPONOQSQNNRY^bfiklkgb`bb]Y[_egda^[ZWTQRSUVWXY\cge`_^`efehpppmbXTRPNNNQUSPRTUUUVXVSQPKEBAB@>>?@BDDA>======<;;<=>???>==>>?@ABBBA>>>@ABBCDFGFFEC@?<9679>CFHIJIILNONNMKIFEC@=;96420////&'&'''''&&&&&&%%&'''(((''''(()(()(()*++****++,---../////01236789;;<>?DKOPOPQPRWUQQSUUPNRY_eilmopmijswkb`cgjjhea^[ZXWWXYZ[\_dhfccfmtuonrqmic\XWSPOORWUQTVYYY\][XTQLGDEFB?>>>?ACB@>=>>?>=<;;<>?@@?>>?@?@BBCDB?>?@ABCCDFGGFFDA>:7559=ADGHIIILPRQOMKIHFCA>;:7531////%&&'(((('''''&&%&&''''''''(()(())((****+**+++,.--....//01245899;<=>?ADIKKMQTSSXXTTUWVRPQW_hnqsutqor|~ofdfjnokiheb__^]_`_^_cgigefku||vsutohc][ZVSRQSWWUWZ\\^`a^ZXTNIGIJGDA>>>?AA@??@@@?>=;;<>@A@?>>>@@ACDDDB?>>@BBCCDEFGGFEB>:6557;?BFGIJJLPSSPNMJHFCA><:85320///%&&'''''('&&&&&&'&'''''((())))())))******++++,-..--../0123569:;=?ABCDEFHILPTTTVXYXYZYVSRU\fntz}xrruwsidcfjmnjimniecaaeigdcfjjhghltyywx{yphc_^]ZWVUVYZZ[\]]_ab`\YVPKJLMKID?>>@ABBA@AA@?>=<;=?BB@????@ABDEDBA>>>ACDDDDEHIIGEB>:8777:>ADGIKLMPSTRQOKJHEB?=;:6420//.%&&''&&''&&&&&'''''(((()))*)))())))**)))*++,+,-..../011345679;=?BEGHHHINSTQSUTUZ^```_[ZZ[^bitxpoqpjdcbcghjijlnmkhcdlrojhikjhiloswxx{}xqjgedb_]ZXXZ\\\\[\^ac`][ZUNLNNLJFA>?BDEFDCCCBA@?>>?ACBA@@@@ABCCDDB@>>@CDDEFEFIJIHGC>:9:98:=@CGJKMNOQRSSPLKIGDB?=;86420/.%&'''&&&&&&&&&'''(((''(()**))))))))+*)))*++,,,-.../012247889:;=@DGILKKMUa`VUWWZafgeedbbfjieer}rkjlmjdb`_`cgjklmmonjmvysnkkljhjmnpuxy|{xtqomljfd_\Z\]\[ZYZ^acca_]XPLMMKJIFCBDGIHFEDDDCA??ABDEDB@@@AABBBCDB@??ACEEFFFGIJIIHD?;;;;::>AEHJLNONOQTTRNKIGEC@><:8642/-%&&'&&&'&&''&&&'''(((''()**))))))))*+****+,-,--./001234689::;<>AEGKMMMNT]_XVXZ`hjgddegjnuxqinwsideikhdb`]]`ejmppprsrxxrnkjjjjklmqtwyz{{{xssqnkfb```^^\Z[_cffda\XQMLMLJKKGEEIJIGEEEDDBAACFIJFBAABBBBBBCDBAAACDEFFFFHJIIIGD@=;;;;;>CFIKKMNNORVVTOLIGECB@=;86431.%&&'''''''''&%&'''(((((()))))))*)))*++++++,,,,-./00134579;;<==>AEHJLLLORVYZZ[^djhcaaejorw|qkje__dhhdaaa_^_aektxuxzx~{rkiijmlllmpsw||wuuvunjihgec`^^aegfda]XSPNNMJKKIGFHJIGEEEEEDCCDIMMHDBCDEDBABDCBBBCDEGGGFGIJIIIHEB?=<;;;>BEHJKNPPRTVVTOKIHFDB@>;854320&'&'''''''''&&''''(((((()))))))*)))*++++++,,,,-./1124568:;<=>??AEIKJIJOTWX\_`adgeb`agmqsv|}rg^XW\bffa]^`_]]]`gsyx||zxokjknonnnnpu||yyyxspoomliecdegihfc_ZVSQONLLLKIHIJIGFFFGGEEEFHKKIGFEFFECBCCCBBBCDEFGHIIJIIIIIHD@?=;;<>@CFJOTURSUWVTOLJIHFDA>;864321''''''''''&&&&'(''((((((())***)******++*+++,,-.012346778:<<>@AABEHIIHIMTXZ]ababffcacglprw}seZTTX[^`\Z\]][Z[^ckprxxw{vplkmopqqqrty~|zvqprrpqpjhkkknnkfa\XUSQPNPPLJJJJIIHGGFFGGFGGIJKJIGFHGEDEDDDCCCDEFHJKKKJJJIIIFBA?<;<=?BFRov]VWXVTPMKIHGFC?;865321'''''''&'&&&'''''''(()+,))***********+**+++,--/23347;;89:<=?BDEEGHHKPLLU^`^ab_afhfbbfjmt~maYWVUUVVVX[\]]_``behlmpu~zrmkmqwzwuuxzupptsqsqklsroqqnjd^ZXVTRSVTOLKKKKJIHFFFHGGGILORPLJHIIGGGFEEFEEFGGHKLLKJJJJJJGDB?<;<=>AHu ]XXVTRNKJIIIEA<976430&&&'''&&''''''''''''()-1,)****++**+++++++++-..12446<FC:9;>?BFIKIHHHPZRPWac^^__afheb`eim|ob]YURRRSVZ^begd]Z]_abgp{}}tllu~wux}xstwupomhkvvqqqnkea^[XWWXYXRONLLLKKJHGGHGGHN[s~lWOKKKKJKJIIIHGHGGHLNNLKKKKJJIEB?=<<==@L*dZYWTRNLKKKKGA=:97531&&&'''''''(((''''''())*,*))*))*+**++,-,,,,-./023446>GE<:=AEGJOPOLJHNTRSW\[X[]]`dda__chn~oh`YUUTSUY^bglh\VVY[]ahostss}{mkvvtv||yzvoliegotsrrokfeda\[\[YWUSRPPONLKIGGHGGKY;zUNMMMLMMLLLKIIHHILNOMLLLLKJIGDA?====@Jc]`]WSOLLLLKGB>;97531&&'''''&&&'''''''(()((()))***)*+++**+,,+,-./12344459>><=AFJLQUVVSNJMPRTVWUTWZZ[^_]]]]`g|ysh^ZZXUUW[_gnl^UTWZ]`babfikvtjlu~uqsy~xtpnlhglsusqmjgijgbaa_ZXWXVUUSPNMKIHIHINi$E]^RQPONONNOOMKJIJKLOPONNNMLJJJGB?>>=<?D^q_fuq_TPMMLKJGC?;87542&&&&''&&&&'''''''(((((())))**+++++**++,,,-.023345568;<=?CIKOUWXZWPMNPRUVVUTUWWXZ\__[XX_otoib^\[ZWVX]hsqaWVX\`bb^\addlrnghs}~topxyrqqrnkpuslhgfhlomjigc^[[[[[YURPONLKKJKPl0aTTUSQONOQQNKIHJLMNPQPPPONKJJHD@==<<>AIYfaZ[keVQONLJIGC?<98532&&&&''&&''''('''((((*))*)))*++,,+,,,,,---./02334568:<=>?BEGNSSSTRONPRTVXXWVUUUUX]dcZUTXbo}od__^]]`daXTXclh]WY[^bfe`^_a`bfecfr|zrlmvssssppxzmb^_bhnrpoomhdba`__\WSQPPONMMNRaGR\VVVTRRQQTSNJHHIKLNQSRQQPNLJIGEA><<<>@BIOQRUarqaYTPNLJIGC?<98641''&&&'''''''))(((((()))*))**++,,,,,-,,--.//13344679<=>>?@ADKONNMMOQRTWYZZYYWTRSW]cb[USUX]djid\USSTV\epn]SSZ]ZUV[^`chhec`__aefecglppoljks|ttssuym^Z[`hnpprusnjhfca_\YUQQQQPOOQU]sf[YXVTUZYUTRNIHGGIKMPSTSSROMKIHFC@>====>CJMNRY^_\YVRPNKIGD@<;9741''&&&'''''((((((()))))))****+++++++,,,-/0111344568:=?>>?AACIMLKKNRUWZ\\[Z[YVSQQUXY\]XSSTUXZYVQNLLLOU^nraSPSUSRV^cccgkkhdcefhjib^^_behikpu{xvwuytfa^`glmpuwuqmjgdb`^\WRPPPQRSU[dkmlke`_]XVZ`aXTQMKIHHHKNPRTUUTPMKIHGFC@><;;<@FKMQW[[ZYWTRPLHFD@><9753&'&&&'((((((''())())))()*++++++++++,,--/1212345678;>???@AACHKKKLOSW[^_^\ZZXTQPPRRQTWTPQRRSTROLJJJJKMS_e[PNPPQRV_febdhkigjomkljbZWX[`cegkntz~x{~yrfbfkmrvxxurnieefda[TPPPQTVY`hljksqifc]XX\\WTQNMKGDDGKNQUXYWRNJIIIHFB><;<<>CIMPVYZZYWUTQKGEDA><9864%&&'''(((((''(()))*))('()*,-,++++,,---./0233446788;>?@@ADGGGHKLNQUY]__^]ZYYVSSSRQONOONNOPPPNLJIJJJJKNRTQMLNOOORZ`_]^acdelrniihb[WY\___cgimqv}zzofhloswxyzzwoijnnjaXSRSSUX^eikkmttolgaZVVVVTSRPMG=:=CKQW^^ZTOLKKKIHD?=<<<=@GLOSVXYYYXUQLHECA?<:974%&''''''(((''())))**)((()*,-++*+,,----./0234556778:<>?@CIPPKKOPRUY\]^^\\[_gh^WVUTRONNNNOONNLKJIJJJJKLLMLKKMNMMPTWWWXZ\^bfiebceb^\]_^]\_cfginrwropz~rijmoswxz}wqrvwsh]Z[\YWZbikmoorttphbZUTUVVWVSOKECDINT_faYTPNMMMKIFB?=;:;>FLPSUWYZZYUPLHFCA@>;975%&&'((''()(((())))**)))****+++++,-..../11234556668:;<=?CJSURRVWXZ]^^][[]_lx^YXWUQPOPPPONNMLJHIKJIIJJKLJJLMMMORSSTUWXZ]`_]\^bda__`_^]]`cegjllmnieehp~rklnov{}}zz||yod`gle\[_einrtvvvqh`YTTVXXXVRNNMLMOQT_e]WSPPOONKIFDA=:99>GNQSUWYZ[YUPKHFEDA?<975&&&''(((()((()))))*)))*+++**+++,--./0/023345555668:::<>AGPWY[\\\_a_\ZY[_cubZYXWUTSRQPPONMLJJLNMJKLLMMLKMNONPQSSSTUVWY[\\\^cfebaaaa__^`cfhjjgcaaaciu|}|tqqqu~}vnhmvpc[Z^dkswyxvpg^VSUXXWUSPNNNNNOPQVXVTRPPPPNLIGFC?<:9=HOSUVWYYYYUOKHILJB>;975'''''''(()(((()))*))))**+++**+,---./10124455666789:;;=@DKT]bdb_]``]ZYZ\^`lt_ZYYYXXXVTSSQPNNNOQTTQPPPPONMOQQRSSUUVVVWWXZ]__`diiedddca`_^afhjjf`_a``elruqnsz|zxwwx~~yqpsof]Y\bjtzzyuog]TRVYXUSRQONMNOOONPRQQPPPOPOLJIGD@=;9<DLSVXXYYYXTOKIJPLB=;975&''''''())()(()**********+++++,---./111244667789:;=>>@DKT]chji`\]]\[Z[]\Z]cfa\ZZ[[ZZZZYXXWSQQTUUY\XUTRQPOOPQRSTSUVWXXXXY[^`abflkgggfdbbb`begiid``bb`cefecbiquwz{}zsqnh_Z]ckw}{xtof\TTXYVTTTSQNMMNNNMNOPPPPOOPOMKIGD@>=;:?GPWZZYZ[YUQLIIKHB>:875&''''((()))*)()*+*)))****+,,,,,,--/01123446789:<=?@ABEIR]eilnne^\[]][Z[[XVX[[[\]^``____^^^[WVWWW[^ZVTRPOOPPNOQRQSUWXXXZZ[\]_chkhfhihdbedaacehhebbddbabbb^^dknrxz}{wska\^huyvocXTV\[VTTUTROKKLLMMNOOOOOPOOONMKIFC@><:=DNX[[YZ[YWSNJHHGC>:965&'''(((())++*(()*))))**+++,,++,,-./0023445679;=?ACEFHLPXcnstsqjb]]``^[Z[YWWZ[]__agkfbcb`bdb_^][YZ\ZVRQPOPQPONPQQRTVWVWXXXXY]adfefhihfeghecccghfcbdfeba`_^^cggkquwyqg_an}{p_URW^^XTSTUSOJJKKLMOOONNNPPOOONMKHFB?<:=EPZ][YZZYWTOLLJHC?<:86('''()(()+,,*((())**)**+,,,++++,-./012334578:<?BEGJLPUW\eq{~zunhdadec`^\[YYY[^`acimgcc`^`ddddb^ZY[ZWTSSSTTTUSSSSTVXYXWWWWVWZ]`adeghjjjmpomjfgiihffgheb`^]^ababhnqxwmedn{}z{n]URV]\XUSSRQLIIJKLNOPOONNOPOOPONMJGD@<;>FS^b]ZZ[[YUPQVUME@=;98((''((())*,,*)(())**++++,++++,-.../02234578:<?BDGJMQW[]_er}vrohgihfc_[YYZ[^``acfeedb`acdedb`\\__\[Z[\]]^_][ZZ[\^`a^[ZYXXYZ[^beghknqvyzwsliilonkigdba____^\^bhmq~|skegloruwtf\XVWY[YXVSQMJHHJKMPPPPONNOONNOPPOLIGC><>FS`d]YY[^\XUYhjUE@=<;:((''((((()**)))))****+++,+++,-..//01234579;=ADFHILPT[adek~|zvlfgiif`[ZZ[]^_``beghgedbabbbbaadhfdbabdfgiigddddegjkiea``_\[[\`dgimrvz}~}xrlkqz|skeaabba_][\_cin||tjcdjnmkg`\\[XWY\\YUOKHHJJLORRPOONNNNMMOQQPNLJE?=?HS\]YWXZ]][X[ihSD?=>@A)(((((((())*))))*******++,++,--.//0123467:=@CGJJLORV\dijqzshbbhkg_[[\]]]]_acgihgedba___acgmpnkifegikmonmlmooqstrlhghgca_^`beinsx{}~zsoouvkdbeeda^\]]afm}D$ujfikgdeb]]\YWX[ZXTNIHIKLMOQQNMNNNNNMNPPOONOLE?=AISYXUVXYYZZWUVSIB>=?EH(('((()))*))))))*+******++,----./11134579<?BEGJLORTW[`eiozzrkffjlg_Z[]]^]]`bcdfefecbb_]]_cgmqpmkfdfhjmpsuwxwwxz{ysomlligededgkorwz|}{wroovskggfeb_]\]_ck}J8~unkg`_dc^[ZXVUVUSPKIHIKLLMNMLLMNNNNMNOOONNOLF@?CJSYXUUWYYYWTQNJFB?>>AC'((((()))*)))*))*,++**+++++--.//02223579;>BDGIMU[XWY[^bhlr{zpkgc]Z\_^]]^`bba`_`baaa^[Z\`dhkllifdgkmnqw}zz|}{wvspnmljkllknqruxzyvtrqrx|smkigfc`^]^`h{{ypf]\df^YXWVTSRPMJIIJKKJKLKJKNONNNNOPOOOOOOMFCGPX[XVUWXYXVSPLIFB@><<<&())()))))))())))*++++++,++--../1223579;=AGMMNUlyh[[^beilo{jc_\]__][]^`b`]ZXXZZZYXWWZ]addfhhffluurrx{zz|{z||zvsrqrsrpqrsvxywusstv|zsqnkkifda_`gwoqzwi^]de^YXXWTRQOKHHIJJJJKLJJKMONNOPPQPPPOPUWNHO[a_YWVWWXWVTPKIGD@><:9&'((('''''('''(((()++*)*+**++,,-/0135679=ALYXRXrn^^adghiktUj_[Z[\ZXWY]^]XTRPPQQOOOQSVZ]^^_acddjssoosz~ywwwvwz~~|zxwxwtsuwxyxurporuyxtspnlihfbagrqfjt~}l^\`_[XWVURPMJGEEFGGHIIJIHHJLLKMMNNNNONR[\ROYdjdZWVUUUWXTNIGFC?<:86#$$##"#$$##$$#$$$$%&('%&&&&&'()*++-023468>IXWPS_gb_bcddefiq}DdZVTUTRPPRTURNJHHHHHFEFILORUUVWZ\^`befikjnsrpnoqrsw}}z{{xvxzzywusojlpt{wuxwsnjihdaems~wf_fozr`Y[YVTRPNLIFCBBBAAACDDEDCCEGGFGIJIIJJKPXWNQ\cf^UTSRRSX[RJECA>;8642%&&&''&'''(((''(('()))())*)*+-..//14689;>CJRUUX^cegkmmllmtc[XVVUTTSSRRPMLKKLLKJIJMPRUWXY[]_begefptlmrsqpsuww|{rptz|xwtnhimmpw{wmdclwoca_[XVSPNKIGHIHFEEHIHHHHHIKLLMNONNNMNRVUNQW\]ZVXXWWX]_VNJGEB?=;86))*,25.*+,,,,++,,,,------../11234468<>?ADHNSW[`gjjlpsssttzpb\YWWYXWVTRQPPQQPPQQQQSUVXYZ]^adffghfhswnlqsstwyyz~{wx}zpllkkprplhlu~lfb_\ZXTRONNOOMJHILNMMMLLMOPPQSSRRSRRTXZUNNRWYZZZZ[[[ZVRNKIFDBA><***,5;/****++++++,---....//012223568<>?AEJOTY^dklhginqtwvyype\WUUVXWUSRQPPQRRQRSTUUVWXXXY[^befebaadlnjjmnpruvuuy||~}ywvwyvqlhiosuror{ldb^ZYXURPOOPOLHFFILMLLLLMMNOQRRRSSSSUZ^WLIMSWYYYZ[YVUTQNJHFDB@><****-/,**)**+++++,,,-----.//02224679;=?CGLRV[_emmfbcglqvwwnc[UQQQSUTRQRRRRSTSSTVXXVWWVVVWY\^acc`^^cikjjkjknqrrstuvz|zwsoq{}vnhiqy|yvxhba^ZYXVSPOPQOKGEEGJKKKKKKLNOPQRSSRRRUXXQKILRVYYZ[[WSQQOLJHEB@?=;)**))***+***++++*+,,,----.//0235789:<>ADHMTY]afnpjefjlpsuuvf[TRPONQSRQSTUUVWYXVVWYYWWWVUTVXY[]aa_^_chjijjjiikmoqpnpvx}~xpox{ohiq{}|e__^ZWWURPPQSPJFFFFHIJKJJJLNOPPQRRQQRSROKIHKRVXYXZZVQONMKIGC@?><:(*******++**+++***+,,,--./00014;A?<<>@CFIOV[`dhqxulkllouuqpvraXRQQOMNPPQVXWXY\a_YVWXXWYYVTTVXYY]``^^`bdffghiighklligkqswxruskimx G6zb]_^ZWUSQQPQRNHFFEEGHJJIIJLNOPOPQQQRRQMJGFFIRVWWVVXUQNMLJGFC?>=;:)****))*+++***+***+++,-..000237EQI@?@CEHLQW\bioyogeejrsmknwre]WRQPOMMMOSY[Z\]_dc[WWXXXZZWTTVYZ\_a_^`abcccdfhhgilmjgdfjmqyzuy}rkis7m(t_\_^[XVTRRQOMIFEEEGIIIIHHJLMNOOOPQRTSPLHEDDHPTUTRTVTPNLKIGFC?><:9*****))*+++**+++++,,,,-///01347COH@@BEHKMPV]fow~medgillgghilkf`[VRPONMMKLQVXZ]^^`_\YWWWXYYUSSVZ]_`_^_bbcdddgnyyropnkgeegims||v{}rjnx *Tr_[]]ZXWUTSQNKIEDDEGHHGGHHIKLNONOPPTXVQMJGEFINRSSQSTROMLJHGFB?=<:8)*********+++++++,,,,,-../01356:@?>ADGJMOQVbnv{{rswxtoiffddddd`ZVRONMKLJIMQTW[]\\]]ZXWVVWWTSSUY]^^]]_bcdffiw|tokiiijklnqu|yw|qmq{H8ve_^\ZXVUTROMKJFDDEEEEFGHIJKLNNONOPUYWSRQLIJLNSUTSTSQNLJJIGDB?=;:9())***++***+,+++,,,-,--./0125678;=?CGJMPSV\iuz}~|y{|pihgdbbbc_ZTQONMKKIGJNQU[^]\^_\ZXWUUUSSUUWY[[[\^`bcfio[3xplkklllmmlmt|{z~z{}tow-6;F>uic`^\XUSRPNNMLHFEDDDEFHIKKLLMNOMMQXYVTUTONPQSVWUUUSPMKIIHFDB?=;;:())****++**+,,+,,,----..0234688:<?BFJMPSW]fr{}~~{ysifgea__aa\VROOOOMLJIKNRVZ][Z\]\\[XVUUSSUVVWY[[[]^adgjqyxyqlklnnopomkqxvsuy}~|}qp|}snhdba^YUSRPOPQNLJFDCCEGIKLMMNPQPMMQYYURRQQZ_YUWWUVURPMJHHHGEB?<<;;()****++***+++,,,,----./12468::;>BEHLORU\enzzv{wjfdb`\[\]\VQPPPQQQPMLNPRTWYXWXZZZZYWVTRRTUVXY[]___`cfiouplkmoqqrpmmqtqnqux{ }{unutmjeccc_ZXVSQRUVQMJFCCCEHKMMMMQWWSONPUUSQOOVin]UVWWUSPNLJHHHGEB><;;;)**++++,+*****++,,---./023578;<=?DGJMQSXdrw|xrt||snmgb]ZYYXVRPOOPRTTSQPSTSSTUVUUVVVXYXVSOOQTVXZ\_a```aegkttpnmlmoqrsqoorsrpqruy{uxxmow~qmjdabb`]\ZVSU\]TMHECCDFILNONMRXXTRPQSTSRPQWddUQUXWSOMLKHGGGFDA>;:;;()**+++++++****+,--../013468:<=?CFIKORT[kzzx{|~}uprvxy}zmc]YXXTPNNMLNPSSQPSYWSQQRTTSTSSUWWVSONPTWYZ\_a```aceglsywqmlllmmnpquwwwxyywuuvz|utzyliowmhgca```^\YTSUZZQJGEDCDHKNOQOMOSTSQQRTTSRPQUWRKNUZYSOLLKHDCDCA?=;::9()***++++*****+,,--../124679<?ACFHIKNQTZfqsruxzxrosw{|h`[ZYSLJKJIJLNNLLPUVSPNPTUSSRSTVVVTQOPSVXY]_a``abbcehlpponllmonnns|}||}{tv{njmtzoijifdcc_[XUSTSPKHECCCEIMNNONMNPQQPQTUUSPNPTRLIMT[[UOKJKIDBBA?=<<;98*****++++*****+,,-//./13589;?DFGGHJLNQTX^flovzytopv{pf_\YRMJJIHHIKKHHKOQQNMPUWUTTUVVVVTSRRUWYZ\_bcccccddcgmrxxutssrps}~xwvqqvxx{|{{vqlhe_ZXWUSQMIFDBBCEILLLMMNOPQPORTUTRNMNRPLJLRZ[UNHHIHEBA@>=<<:87+***+++++**++++,--/0/12369:<@DGGGILNPSUVZbiow{zxuuzria\XSNKJJIIIKJHFGILMLMQUWVVVVVUUUUUUVY\]\]`fhffffgdaeoz~zx}|{}~}~{y|y{{xx}zsmic\YWUTRMIFDBBCFHJJJLNQRSRPPRTUTQMLMPPMLNRXXSKEFHHECA??>=<:87,**+++++***,,,,--./002357:;=?BEFGJLOSXXUW^fnxxzyof_ZWUQNMMKJJLKHEDFIKLORTTUUVUUUUVXYYY]`_]]ailjhhikheiv{xwvtu~x~|xv{}xsph^YWVURMIGDCBDFGHIJLPSUUSQQRUVTOLJMQQNMOSVUPIDEIIFDB?@?=;986++*++++,+*+,,,,--./013568:<>ADFGHIKOTXXTU[cm}uv{xw{yrkb[XWVSPPPNLKKJGEEFHJLOQRRSTUUUVWZ]^^^`a`^^bhlmlkmpolpwsolmu|tv~~~zxw{}ztka[XVTQMIGEDEGHHGIKNQTVUSRRSVVTOLJLOOMLNQSSOJFGIJGGEA?><;976*+++++,,+++++,-../1124679;>BFGIIIJKNPSTTV\etxpqtnimqmg_YXWVTQQQPOKJIGFFGGHJNQRRSSTVZ[[^acddeebaabeinonpsvw}wqmiipw{~yrmntz~~}||~}uld^ZVSPMJHFFGIJHHJMORTVVTSSTVWUQMJJLLLMNPRRPMJJJJIJIB><;:977++++,+,,+++++-.//0234689;=BGKLLLMLKLMORUZbozomlnmf`ehfb]YYWUSRRRRPLIHGGGGGHKOQRSSSUX^``begihhfedcbchnrstwxtsqqvzy|{pighmu}}{}{}vme_ZVRPNKHGFGHHHGKNQSUWWUUVUVVTQNJIJMPQPPSUTQNLKJIJHA=;::987,++++++,,++,,-./024568:<=AEJMNNNOMJIKMQX_gsofgjjga]`b`^\ZZXSQQQRSQNIFFEFFGILORSSSSVY]`acgilljhggebcisz|}{wxz|~{ogfhmr{}||w|#b_ yof]XUSPMKIHFGGFFHKOSWYYXWWXVVUSPLJHJPUVSRUWWSPNLJHGD?<;:::87++***++,,,---..0259:::<>ADHJLNONNKHGIKQY`gq}tc^bdb`^^__]ZXXXVQPQRSTRNIFEEFGIJMQSTSSTVY]``behlmlkjifddkx{vux|}rgeiosw|u{O x}rf[WWURNLJIHGFFGIMQX_caZWWWVVUROKIILQUUTTVWVRPOMKHEA?<;;;:98+*****+,,,--./024;BB?=>ACGKKKMNMLJIHGIPW[`htxl\UVWX[]^^[WUTTUSQRRSTTSOJGFFHJLNQUVVVWX[]adedfhlooonljhho~wqqv}~}}tiehoru~w|W%s}tf]YXVSPMKJIGGGIKOU^kpi^WVWWWVRNKJJNRTTTVXXVSQOLJHEA?=<<;:87++****+,,,-./2348AIHA>?ADIMNLLKKLLLJHHMRUX]gqk\ROOSVYZYWSQQSTSRSTSTUUQLHHKMOQSWZYY[]adefikjkmoqrrssqpqw~woou||zwpjgeimsz=ysi_\YXVRNKKJHHIJLQXalqi]WVX\[XSNLKKOTUTUXZYXTQOKGFEB@>>=;:86*+++**,,--..0468<CGE@>@CEIPQNKJJKLLJHHJNRVZcqp_TONNPTVVTSRRSUTSTTSTVUQMKMQTTVX[]]^acgjijlprsssstuy}}{|xrrx}~}~wqjhfbbfowtskb^\[YUOLKJIIJJMSZ`dd_XUW[a`\UOMKLPTVVX[\[YUQNIEEDB@>=<:986+,++++,,--./1579=ADB??ADFJNOLKJJJIIHGFINU\agqn_VRNMNQSTUVUTSTUUUUTSSQONOSWYYZ]_`acfhikklpuyyxwwxy{vw|}|}tlfdecbdl{|tvtlfc^\ZUQNLJJJIJOU^b`]YUTW[__\WQNLOTWXY[^]\ZUPLJGECA?><<;986,,++,,,,-.01358:<>@@??ACFHJJJJKJIIHHFGJRZdjqri]XVRONPRSVZYVSTVUUUTRPONORVY[[]_`begijijklqy}~}~|}||}|~~|tjdfmmiinxxy|xojf_[XUSPMKJJJKP[ime\USTVYZZYWSONRWXXZ]_^]ZTOLLJGDB@><<:988,,++,-../001369<<<<>?@@ACEFFGIJJJKLKIIMU]emxxlc`^XSPPQSUZ[XUUUSTTSRPPPRSVY[]]_adfgjkjikms{~~}}ztkfly{wtsxuw{toia[XVUSOMLKKNUe|p^USUVXYXVUSONRUVW[_a_^]VQONKHFDC@=;:976,,,,-./01342369;;::<?@??ACDFGGIJLNOPNMOV]dozxoiig]UQPQRTWYXUSRQRSSSRQSTTVXZ[]_acegjnmmmou||}wnir|yxzzz}|mlx|xslb[YWVTROONNR^tbWUVWWYWUTRNMQTUW[`a_^^XSONKIGECB?;:864+,,--.0247754588889;>>>?@ACGJJJKNPRSTSUY_hrwrlilj`VQNOPQSUTQOMMNQQRSSTUVVVXZ]`acfilpsttsw%.~{rnt}~zvrqruz|qqx}{umc\ZXVTRRRPPWicXVWWWYXXVURPQTVX\aa]]\WROMKIGEB@=:8754+---.0247876566778:;<<<=?@CHPQNOQRUXZZ]chlqoieehg`XRMNOOOONLJIIKNPRSSTVVVVX[_abfkorty}~}$'6<"ysuz|}{vqmmnotzxx|}wnf`\YVTSSSRS\po^WVWXXXYZZZWSRUX[_ca][ZWROMKJGC?><98664,--./0369766655668::;;<=>@CJRSRSSUZ__^dnpnmib_`a`]YTONNMLJIGFGHILNPQSTUUUWZ^`adkrwzz  "")+yw{{zxtolmmnsy|}|~~{unhc^ZXVTTTTV]l{|qd[WVXYXXYZ[ZWRPTY]bda]ZYWROMLJGC?<;97664,-//012:@<65566668:::;;=>?CINPRUVZbga[cprmnkc][\\\[VRPNLJHGEEEFILNPRSSSTUX\_acgow   %<9&|x}}zuqnmlmsxy{{zyvrmid^\ZYWVUVY`iooia[WXYZYXYYZYUOMPW]ac`\YXVTQOMKGC?<:86665-.00123<E?6446887888:;;=>@DHLNRV[_fi^VZfllnni`[\]][WTROLIGFFFFHKLNQSSSSSUY]`cgkr|1KE% Br05%}w~xtqmjkqvwy|}{xurplfa][ZYXWX]emokfa[YZ[[YXXXXYVOLNU\__]YWVVURONKGB><:88766/0112237;832268877789:<=?ADHKOSX]`a`ZSSZbgjkjd`_^[XTRQOLJHHGHIKMMPSTTSSSUZ_adint~3Uo`. 2g6$~w~{vsmijnsvvy|~{vtoib][\^_\\bp}zme_[Z\]]ZXWVVXXRNPV[\ZXVUUTTRONKFB>;:87765./011112321235656889::;=@BFINSUX[[ZXUQPT\fighgdb`ZTPOONLKJJIJMOOOQSUUUUUX\`bfkpu{Dgzc*}} }~xsnlkmqtuwz{[r}wpib][busflpb][[^_][WUVVWWSPTXYYXWVUTUWWSNKFB>;:88764,./0111111123445589:99<?ADGLRWWXXWVUSQRU\egfghfeb[RNMOQONMLKLPQQPQRSTUUWZ^`bglqtx|!@YaF}yusv}{yvqmmoqsvxy|gyqjb]\ltuqb\[^b`][XUVWWURSXZZ[\\YUTW_aWOKFA=;989763,.00121111123455679:9:=@BDGKRVWVUTTSRQSW[`cdbbcc`XRNOQSRPPPOOQSSQPPQRSUX[^`dimpsv{ !,) }~{sqtvttx}zxu|~{~}rlllnqtvwzC ]2|tkb][kz{~nb[[`b_]\ZWWXXVSSX\^``]YUTW]^TMJFA<:878754-.01221121123467779::;=@BEGKOSUUTSSRRSVXZ\^]Z[^^YTQPPPQPPSUTRRSSQOOPRSUX[^bgknrv| ~||{vrrvzyy|}xurpuvs}~{qlkklnqtux3zpe][`v}y~{pg^[\_^\\\[ZZ\\YVVX[_a_ZWUTUUSNJHD@<9777655,-/022222113346779:;;<>@CEHKOTWXUSUTTWYXWXYXWY\[TPOQQQPOPTXVUTTTRPPQSUWX[^agmrw}++.(~~zxy||tq}}{wqonmmnoqrt 4Zvi^ZZ^emx}sg_[Y[][YYZZZ\__[YXWW[]ZWVUSRPMKIFB?<8776555+-.02211111335677:<;;=?ACEHJOTYZWWZYVXXTQSVXXY\[UPORTUUTTVXVUUVTRRRTVWXYZ\`gov~6GC<. }wuz}ytqqpppnnoppv`zl`YYZ_itxti_ZWVXZYXYZ[\`cb]YWTSWYWVVVSPMKIGD@>;9876555,-/122111123356789:;;=?ACEGINTXYXZ_\WWUQNQW[[Y[ZVSRTWYYXXXWVVVUTSTWYYYZYZ]ait}#>IF:'{y{{z}{vrpoopqooppnp~nb[Y[_fkmiaZWUTUWY[\]^afie^XSPPUXXWWVTPLJHFB?<;:976544-./1321112334577899:;<?ACDFIMRWXX[^]YZWSRU[]\[[ZYWVWZZZZYXWVWVTSTWYZZZ[]_bhq| !5B>4'|z}{uxytpmlnqsrqppor}ob[Y[]abb_\YVUTUWZ\_`adkmg^WROOSXZYXVSOLJHEB?;::976544-./0111112333567889:<=?ABCFKORUXZ\\]bf`YVY]^^]\[[ZZ[\\[ZZZXXVSRQRUXYY[_cglt|)9;({wyxuz~zupkjnswvrppqv|na[YYYZZ[[[[XVUWX[]`bdhnnf\VQNORVZ[YVROLIGEB?<::976544-./0000123433578889:<=?ABDGLQRTW\]\^iri_[\]]]][ZZ[\]]]\\_`^ZWSPPQSVXZ_flou!-94zuvuty{unlouywroosw{}l`[[YWVXZ\^]ZWWY[]_aehkome\UQOORUXYWURNKIGEC?<;:986432-/0000013444567889:;;=?ACDGKPSUW\]\^gnib]\\\\]\YY\^^]]\^gle]YTQRTTTX\cmvy~ -9F<zzywxxrppswvqopsuy}~nb\[ZXWY[^a_\Z[]`cdfkpssog\UQPQSTTTTTQNJHFEB?<;:875322-/0000024555667889:;;<?ACDGLQUVWZZY\`efb]\\\\]\ZZ]_^]]]`jpg_ZUSTUUVY`ju~$3KiV}{{~{vsrsvwtqsuuw|pd^]]\[\^bdb_^`adgilsxzysh\UTUVUTQQQRPMIFECA><::864322-../0013455667899:;;;<>@BEGLRUVVWWVW[_a`^]]\\^][\^`_^\\^cfb]ZWUUUUW^kz.Q|_|zxutuyyvuwvv{~odabca__aefeccefgjmry~~xi\WZ\[XSPOQQOLIECB@>;::864322,-.//013456789;<;;<<<<>@CEHKPTWWVSSVY\_`_^\\]_]\^cfc_\Z[^_]\ZWWWWX]gv-;~{{{xutuxyzyutyoddgigcaaceedfhijmpx|j\Y]a_ZUQPRRPMIEBA?=;:9854321+,.//01356779;??===<<<>?BEGJNUZ[WRRX\_aa`_]]_`]]`eie_ZXZ\\[YWVWY\_eo}yz{yuqpsy}yrqvqdchmjc`_`bcegjklns~|f[X\`^ZURQSSPMHDA@?<::9864311+,./012356678:=>======>?ADGJOU]a]VTZacfecbaaa`^^_ab`]YWWYYXVUUX]cfkuzyxwvqmpx|wonr~oa`flkc]]^`adhlmnovt`YW[^\XTRRSROMHDB@><:::;96311,-./0113666778:;<=====>@BDGKNS^eaZX\bfklihhhe`]\]]\\ZXVUVVUUUVZ`hnrx|yxyzuopwzvonq}machkic___`bfknpqtz{eYVX\][WRRRRPNLIEC@><::;=<6311,.//01136767789:=?>>==>@BDGLNS\b_ZZ^dimolkkkf_[YYYZ[ZXWVUUUUUX[bn}~||~}vppuxxuuu~ugilligiicacilnqtx}~{wsi\UW\^]YURQQPOMKHFC@>;998874211,.//11235678899:<>>>>>@ABDGLQV\^\Z[`fknpolkid_ZWXZZZYWXXVUVVWZ\ey$*~~|tnpuz}~~qnnkikttjddhknruxzyvqkaWTZab]XTQQQPNLJGEC?<9876643210..//122347899999;==>>?ACCEISdqj`]]^ckqrpoookgc\YZ\ZXVTUVXZ[[[\_h~ }{}|tprx~vpmigjsumhfgkqtvvvtrme[SRW`a]XTRPPOLJHFDA>;987764311110//2333589::999;=>>??ABCFMjqbbcisvpjjlmljf`\]]YURPQU\dfdbaciv $ |yy|~|wuw{tolhdeknkhhksyywurpmg_WRRU[]\ZVSQPOLIGDB@><998753321120/0233358;:9999;=>??@CBBFOC!hfiqwshcbdgjjgb`_^YSONPWdrtlgghjp|  +?HC8$}yvv{}|{||zpmlgb`cffhlu~wrolh`YTRTW[\\ZXUSQPNJFDB@>;:986432211///0123458:9999:<=?@@HTJCFNzunmpwxnb^]^bfgfdcc`YRNPT[kyyojikmr{   +JSA+$.F]hneH"! }zwux}~|~womkgb`abdis}tokibYSQRTY\\[Z[\ZUQOJFDA?=;;;:7421111///0123557889::;==>>?L]NDFJZvstx}l_[Y[^ceffeeaYQPTZbowtmjkmqw 9[fADQZdz|P"@M/~zwuw|~\volifb__aemzyqlhbZRNOQTY[ZY\eohZSPJFDA?=;<>;7431111.///0234578789;<<==>>CIFDFINXfszzxy{l_YWZ^dghgfe`XRRX_hqspmlnrwBj}\smq~hJ?\d>zzzz|dqtmifc`^_cjs~|tnibZQMMORUYZYY^m~r\SOLGCA?=;<=:5432111.../013468888:;<<=>>=>ACFHJMTc}xstrkaYWY_fiiihe_XSSX^fmonoorx  DgnrntrI-|~~x~slhda_]bjt||vqnh]TMKMQSVY[[[^gpeUOPRMFA>=<<;75432200--../1248:989:<<<=>>>?ADHLMOTc{qmmjc\WY`gjilni`YUVZ`gklnpsw~4JiZM_D@:~x~smiecdfmw}vpnmf[QNNOQSVZ\]^_`^VOMSZSGA>=<;975542100--../12479889:;<<<=>>?BEJNOOT`{vnkgc\X[bgijmoh_[Z\bhmnnmqz+;==[($ !cW r]ch{~upllpuz~xqlkh`WRQRQRTVZ\]^^]XPLLPTNFA?>;:86543210/-...012356679::;;<<==>ADHLNPS_zrid`\Y]bejljga^_bgmprqnot4IRFDDQ%48$0OY(}|wvtu~xsnlje\VVVUTTVXZ\]\\ZTOMMMKGDA?=;986531000/--./012345678::::;<==>@BEIMPT_xvic`^^`bflle^\]agmssronqv-HZZB^sp|h~z~~~vqmljhc]\^]ZYZZZYZ[[ZVRONMKGDCB?<;97543100//--./0013456789:::;=>>??@CGLPU`u{ledfffgilj`[[^biosrrqqsy6Zl_7&F% +~|}~}ztnlkjhfbagjd`_``[WWYYXTPNMLJHFDB><;975432100/..//0123356789::;=>>>??@DHNSXbsqjlppnmjid]Z]_cipuvvutuz~ "DbfC83?dNA%n1|y{wrokhilkhdbgxxlgegg^UVXXVRONLJIIFDA=;:8643311100//./011235789:;<>BC@>??AEJRWZaoysvxzwphc]Y[^`chpwxxwtruz~<QQ7#$~'*L}!O1rM~yx{~}sokghknmhcdmz}tmikj]SVZYUQNMKJJIEC@=;:864321110/..../0134679:;=@L`^I??@BFMW\]bnyue\WX\^`chovwvuroqv~:9 (MQ6#d,9@pXsP!F|z|xqokjnssngbfny}xoihbWRY_\UPMKJIIGDB@=;975433210/.-.../0234679:;>MmxN??@BFMX__blnluyeYUVZ^adhmqsrrqpsy6R;[S,hRWf@Y05,w$ ~~-VDxponkmsvqicbgnuwqjd_XQR\b_UOLKJJHECB@=:876432210/..///012356799:>OfjYD?@ACEKTZ[_fhcep{}yx~sd[WUY^adinppppqtx9DHkb, BgQ Q2RF1 d/. Tbyplmlklomhcbdjnolga\WRORY_[SMMMMLIEBA?<9886422110/.///111135689:;=BFEA?>@CEGKPUY_fjigmvzwrnookd^ZYZ^aelppooorv{ 92?^PIt9dv/ cJqS_e6B`@RC~sljjhhhfbaaaekmje^YUSQPQUWUPMMNNMIEB@>;8776422100/.../32123468:<==>????@BEHKNRW]bhmnlnsvsmgeeeec_\\_aekonmnptwz~)4 $c-t)xQ8  j`[/>mN dw@~|OeJ{pjheccc`]^abeiid^XRPOOPQSTSRONNNLHDA?=9766543210/..../00013468:=>>>>@@@BDGJLRX\aeilnpqrqmhb__bffc^\^aeikigjosux|A|] /^$.` afy\?yc@+Q}? }{~vlgea``_^]_cdcda]YSNJKNRSSTUUQOONKGCA?=:765433200/...//00013468:<>???@ACDFIKNSZ^bgknprrspid`\\`efc]Z[_cggdbflpsz [.sHb!+L o  j)s5#jP]L}w~sjfb_\\]`abeda^]ZVPKGIPVYXWVUSOMMJFCA@>;87533210//.--./001134679<>?@CDBDGJKMPV[_cinrttutnfb_\Z]bdaZVY^aca__chnu .q5B@WF]USft[P voq{ske_[Y[`ccabc_\ZXRMIHLU]`_ZVUSOMKIFCA?<97642210///..,./011234579<>@BIIEFIKMOQV[^cjquvvuqg_\[YX[_a]WVZ_a`][]afmw ?d[x7NEFWWe ]1zXi2uljoz{z}zrlb\YZ_fhe`_`]YWTOKIKQ[cda\XWSPLIGDCA=:85442200//...,-/12123457:=?@CIJHIKLNOPSW\cktzyuqh]USTUVXZ\ZWX]``^^^^agnx     !4hB<\dvS`D_4 r@byY(}}smlsytsuyyrlb]_bgmke_\[XVUQKIJNV_cb_][XUPKHEDC@<9754321000/..--./12124568;=?ABDGIKMNOPQSW\clv{zslbVPNPRTVY[[Z\_a``deddipz)")V#u$$MRpP${XP0a,/& yruxsqrxwnkmq|ynffr|vpic\WVTTSNIHKQX]^]\][WSOJGFCA>:8654321110...,-./12135679;>@ABCFIKMOPQSV[_dksvtni_SNMNPSX]``_`a``ckqnlns|| KsM" 1|XA\"_[>( ~wkdglowxleeku##)#slsofbYSQPOMJHHLRXZYWXYXUQLIGEB@=97543321110.-,+,.01223578:<>@BCDFHKMOPQV]dgeiosqle[RONOSW\`deddcbbfr{{xy{ 341tDV@FUhk6A1BC,~}zod_ais{mgeip} xnrja\TONNLHFGKOTXZWTTUURNKHFCA?=96543321110.-,+,./12235799;>@BCDFIKMNPRXbkjdflqpjbZTQRTY^`cgiihgggjt~ H#,.g53 =O2(?h(@<TQ:$|~sgcfnz{qlkmqz%5wllvzpcZTONMKHFFKQWZZYVTTTTQNJHFB?><9653322210/.-,,-./02345799;>@BDDFIKMOPQU\cb`djnmg_ZVTV[afghjklmkklnwFa9i)C C{PG><!xkiovzsqrtuxojiljd\UQNONIEEJQY__]ZVUUTROLIGEA?=:864222110//.--,///1355579:<>@BEFGJMPRRQSW[[]djjhc\YVVY`gmooonoonnory#XJ(Ml0(#8W?'?_8 x2# tjmv{ttwyxvw~nihhfb[TQPOPOIEHOW]aa]ZWVVURMJHGD@=;9653221100//.---//01465689;<>@CFGIKNQRSSSVY[^dihd_YWVW]elqtusppqqrtuyLbn  Tqho~}vvyzwtqppnjggfe`YSOONNONJFJS[]^^\YWWYWQLIGDA><97542221100//.,,-//02466789;<>ADFIKMNPQRRSV[acgiea\XWXY]fmsvvtqqrtvy{{}Gtv 0)shpzvuwxurnjgfdddc_XRMLLLMOMIHNY`_\ZYXVUWTOKIEA>=<97642211100/.-,,,.012467899:<?BDGILNPPPPPRV^fjlkd]ZWWYZ\dmstvusssuw|~|A}kKEp>0FXvlq~}|yurqrsplheedcbb_YRMKLKKNPMILVaeb]ZXVTSRPMKGC?<<;96543100000/-,,,,-/1356789:<=?BEGJLNPPNNORX`hlmkd\XWXZXYakruvvuuuuv{zz|~o=,FFI6:f5yot}yxwtrrrpkgeddecb_[TOMLLKKNPNMSakic\YWUTSROLHDA>;;:75432100///.,,,---.035578:;<>@ADGIKMPQOORV\afjljd]YXXYY[cmtxxxxxywv{|yxz~~yy~B *Y{Y2xou{yywutsqnkgeeeeda\VQNMMMKKMPOQZhoja[WUUUUSOJGC?<:986433210//..--,,++./135668:;;>ABDGHLNPQQTZ_bcdhlic^[YWY]bjqtwx|}{{wuz{xy|}z}&3VYKNu]~}~|sov~xvusrsqomjhgfdcc`XRONNOOMLOQPT]gke`ZVUUUUUOJFB?<98764321100/.---,,*)//245678:;<>BDEFHKMOQTY_eecacgd_]\ZXZbjorstv}zutz|z{~~[L (-&-JiA~xvsstrrv}zsmkjknonljiigec`[TPOOQRSQQPPPU]eeb^ZWUUUVUPIEB?<:8754321100/.-,,++*(-/367778:;<?BDFGIKLLNRW^cdb`_]ZYZYX[^fpttttv}yvy~~}}~}%v`-  zzxutuwz}}{upjcacflpqmjjklkhc[TPQQSSVYVROOU^ba_]ZXWVVTRMHEB@=:8754321100/..-++**)-0477668:<=?BEGHJLKJLQV\cedebYRQTVY\`hsyxwvx~}y|~~{}0Vse ,VY~mca`__aegkqrnkjlqtqi`WRRRQS[b^UPPU_ca`^[YXWUQMIFDB?=:8753333320///.,+***.0256779<=>@CFHIKKJIKOU[adegcXONSWY[_hu||zxz}{xx}~|||~{zyxy{|}+F@F^"|e[[\^afmlkmnlihkrwtkcZSQPPS\c^VSSWckifa\ZYUROKHECA?<9875322379400/.,+**+/013577:=>>@CFHKLLKKLNRX^abc`WQRVWWX\gu}}{z|xw~|wvx{||zsqqtu{ wpnlhfhlkikllihkptqh`XQOOPSZ[WUTUZfqqlb[YXUPMIFCB@=:87643113;?71/.-++**+/012568<@A@@CFHKLLLMMNOSX\]^]WSUWUTU]jw}~|zwvy{z{~snmot}~vpkgdbcfhkmmkilnnib[UPNOPRUVWWWY^fnpj_YWWSOKHEBA?<987642112793/.-,++++*/002469=BCAADGIJJKLMMLKNRUXYXVVXVSRUaqz}xwyyxxvplnt}x|~skfc`_cgjkmmkikkhc\WSQOOPPRTY]]^cgjjd^ZXUQNJGECA>;97654211111/.--,,+***0112469<?@ABEHJJIIIKKJIKMQTUUVZ]YUTZgv{{~zy{yvy}wsmlrz|~pfcbbdjmmkkkjhgfa]XURQQQOMMPW^_`eiiea][XTPLIGEC@=:8754322100/.--,,++*))0113569;=?ACEIKJIIHHHHIJKOSUVY`d`^ahrz||{~|z{zwtoloz~zlb`cglppmjjjhd`_\ZWTRRRQNKJOV[^aehd`\YWUQMKIGEB?<976432110//----,+++*)(/124579;>@ADGJKKLLJGGJKKLPV]`bkqkkw|}sry}|{yz~|yvpjls{{|xruqe__ejorpliigf`ZZYWWUTSRQMKMRW[^bff`[YXUSPLIGFCA><97532210/..--,,++,,+)(/12458:<>@ADHKLMOOLGHLMMOU^hklv~up{zskhnx{vvvy~|vngglppt|~pilu|~qgbadjnopoljhfd`\YXWWVVTROLMRWZ\_beb\YYXVSOLIGEC?=;96432110/.---,,++..+))013468:;=?ADHLNNOOKFHMOPU\dkkkt{sijs~{tokgdgq|tsvz~|ukdchknt{Uj}sjfjq}pgccfkmnoomkifcb^[XXYYWVURNMOUY[\^``]YXWWTQMJGFEB?;975321000/---,,+++-,*()0124678:=?ADGKMOONKGHMPT[bhkjfilgabm} zqnkgfffn}~xvz~~~}zulcbglry~~0}|zsnmpz}icdgmppnnmjgeb`_\YWYZYWVTQNNRX[\\^^]ZYYWSPNKHFDC@>:75432100/.-,,,,+*)*)(()0135679<?ACEHJMPQPNLKNSZbgknmige`_fs.%tsxumjjjp~{{|yxvnedipv~ -~~rgdhlrtrpomjfc_]][YXZ[YXXTPOPU[^^^_^\ZZYWROLJHFDB@=:865432100/.-,-,,+*)))))223578:<?ACFIJMPQQPOLNV_fhkrsmhb^ajx8}t~tmllr~|zwvtmggjpw{oiiknqrponkhfb][[[YYZZXWUROPRX]_```_\[ZZWRNKIGFCA?=;8765311100/---,+++*)))(223578:=@ACEHJLOPPPOLOW]`chpqmhbbemzzwwpsry}zwtplhgjnu}~~~zqmmmmmlkigfea][ZZZYXXWTRONOSZ^_____\ZZ[WQNKIFDA?=<:7654211100/-,++++***)('234579<>@BCEGJLNOOOMLOTX\aglmiddhkq~z{tryz~zwsnjggimqx{qruw{;|~rmlkjjihedc`][[[[XVTSPNMNRW\^^^_^][YYYUPNLIECA><;86443211000/-+++*+*))*)'02368:=?@BCFHJLMNNNNNOQU\diklgcgmpv~yz{~tmqx|{wsniddhkouwqljmqsw~|tqxtmlkkjigdcb_][Z[[XTQPNLLPX_`^^^^^\YXWUQOMLIEB@=;9754321100//.-,+****)))((02478:<?@ACFHJLLMNNPRRQT\eijlhdhnsyyvxzwpkjqz{wsojeehjnt~lgiknsuy~~zqjhkxzokllkigfdca]Z[YYXVSQOMLMR\ed`^_^][YXWUPMKKHEB@=:986321110//..-,+****)((''135899;>@ADFIKMMMMNRUVUV[abcikfgou{sloy|tjhp}zwtojgghjow }|}z{qgksss|zqicaaehighkljhfdcb_[YYXWURQPOMMOT]ccbba^\[ZXWUQMKJGDA><:986431000//..-++***)('''&23678:<>@BDGIJLMNOQTVWWY^_[\fngenuz}oghrunjnz~|zwsojgggjoy{vxyrqu}~yrq~|ynd`_aacddgjjihfdca][YWUSQOMMLLMPV^abbba_^\ZXVTPMKIEB?=;9775321000//--,+****((''''22468;<>@BEGHIKMPRTUVXZ^ca[Zbieenux}rihkkhmy}|zuqnifeegkv|sz~|yxtlc`acddccfijjiecb_\ZXURPNMKIIKMRY`cca```_^[XTQOLJGDA>;976542210000.-,,+*))*((('''11369;=?ADGGHJLNQSUVWY]aedb`bcdjpuw}{vqkghu~zwspmifeddhq}vqmkfbbcefebbehkkhda_]ZXVUROMMLJIKNT]bccb`````]XSOMKGDA?<:86553221110/.-,++*)))))((('12369<>@BEHHIKLNQSTVY\bimnnkfbenruw|~phl|}wtrpmigfdegmxz{ld |smhfdbbdfedddfikjgc`^\YVUTROMMNLKLOW_bbdeb_`a`\XSNKIEB?<;976443212100/.-,+***))))(((&12469=?@BEGHJLLNQSTW]cs|rh`aipvy}rilz}wtsqmihfefhls||xy ~&woieccbadggghijklkhd`]\ZWUSRPMMOONNSZ`abfgc_^`_[WRNKHD@>;986543211210/.--,+***)))((('&13469<?ACCCFJLMPSUUYalxf]^enw}ymlw|xvtrnkifdfhjnsz}xw,xphcabba`bfgjllllmlje_\\ZYUSSQNNQSRSX]_`beeb_]]\WSPMLHD@>;975433211110/.-,,+)))*))(''''23469<>AB?;@HLORVWWZcsyd[]doyplx$.}yvusqmigefhiknrzzuu|y~~w{}vqjd`acccbceghiiijkigb^\\[[WTRQPQUXWX]^_`acca^]\ZTOMLJGD@=:975432211110/.,++*))))((''''(12479;>@B?=AHMPSXYY[cpt`WYalwus~+.|xvtsokhggiklnpu{{uqqx|tz~xu|{vqqy{w|~}ztpmiecdfeedefggfefhhgc`^`^[ZXUSQQVZ[[]bc`_``a_]\YVQNLJGDB>;9875432221110.-,++*))))(('&'''12479<>ABCDFIMPTXYZ]bmw}}{wl\ST\hr}'<;/}yvtqnjghkmmoqvxtnmouxqrtw~|yuwzwsrruy{~zvx{zvuurnmlieeeeefffhhfddgiifc`__^YXWUSQTY]^_adea___`_^\WSOMKGC@?<:765333221111/-,++**))))((''(('22469<?ABDEGJMQTXZZ]bionoomdWPPWdoz,\aYS>}wuspmijnonorwunjjmszwmjkmqw|{{~}ztqsqpqrsttw}~yuuusnlmkiiiecdddegggihfefhiigda_][WVVVUUX]bcdb`___`abba]VQNLJE@><:8653333221111/.,++***))((((*,)'1357:=?ABDFGJNRVX[\^cfggghe]RNPVaow}GwjAyvtspmqtsqoptrlhhkpuxxtoieegmvxxy~xrpy{z|zrllmlmoooqxxrqqmiggfddecceeeefggiifegiihgeb_]ZVUVWXX[_eijd\Z\_aacca\VPMJGC?<;97654343210000/-,++***)(((''*+(&1356;>?ABDFHKOSW[\^`efb__`^WNMQXbovz>tO5{xusqptuusopttojghlprrqnhfghs~utw}{urt~wvxxrkhiiikklpzxpomjihgffhigfggfffhjkjhgiklkigd`\YVVVWXY[^emof[XZ_bcddc\UOJGB@>;987655443210/.--,+*)()))(((('((''1236:>?@BDFHLOTY]^`dfe^YY[ZTNMS[clsx~~$V}rB3*{xtrqqpoqtrqvyupjgimprspjffhp|yqoquwvuw~}{xuvwslhhhijjkqx~tmlllmmlmopqmjihgfgjnppmllnnlheb^\ZYYXWWWY^dkld\[\^bhnnh]RLHD@>;987655544321/.-,++*))(())((('''''&12359<>?ACFIMPU[^_beea[WY\\VQRX^dhnty~'MvuS:8;"}yvqppolimsuuy{xsokjnruurkfdfjoolknqttty|vtwwutvtnjijkllnuzzunklrvtrrtusromljiiilquusqonmid`^\\\\\ZWVWY]becadkjdbhpoi[OIFB?<9876544433321/..,++*)))))(''(''''&%12358;=?ACFHLPU[^_aca^ZX[aaZVX]acfjov~-0+3K_L~~~{yuqppmhfjrvy}|wtvtoptwwupjfefijkklpstsv~urporttrrqnllopqqt{~yqmlntzwtstspnnmlklmlnqttrpmkhd_\\\\\\]ZWWYZ\_``gvpcbca\RJFC@=;98765443322110/.-++*)*)(((''(''''&%02468;=?ACEHLPTZ^`a``^\Y[aa[WW[]^aeks~~KR{yz{|zvrrrnhfjpu|xw{yroswxyuoigffhjjknqrqrwzrmmmmorsqommosuvx{~{qmmmottrqqomlmlmmnmmnpqpnmjfb^ZZ[\ZXX[ZWWYZZ\]anvc\YUPKFB?=;;9876544331100//.-+*))))((((((''&&'&01478;<>@BEILPTZ]___`aa]Z^]WRQSUVZ`go{} b}|xx{{xtstuqjhkptz~}wuwwqnrxyzxqkigefhijlnnnorv{~zqllllmprrolnt{}z||sponnqsqpomkkklmmmllmooljjgd_ZYZ[ZXUVYXTTUXY\]bm|o^XTOKGC@=:99755665543100/...-+*))((('((((''''''12468:;=?CFJMPTY]]\]aegaZ]^VNJJMOU]elv}~|{z~}@Fzzzxusstusnklpsvxxtqqqooswyxvqnlifeegiklmmmoprwuollkjjmpqompy|zzvtsrqrrolkjiijkllklmnnlheeeb]Zbi_ZYWVWURQTX\^_emtxqbYUQLGDA>;987644566532100/.--,+**))(('''(((((('&124678:=@DGJMPSWZ[[^chjcY^c\QIGJMS\cktz~|wttv{}0|vttuvurnmquwvuqnlmoqruxxtrqpmhedegjklklnomnnnmlkighlonms|xsw{{zyvtstrpnifffghjjjklmnomjeaa`]ZZel`[ZYXVTRTW\`ceionjbZVTPJDA?<977654445542110/..-,+*))))((''''(((((('0133589<@CHJMPRTWYZ^ekldY]feZMKLNT[airy}~zuqoq{{<:{yyxxuqoqwwroljjknqruxvstwwrkfedfhjjhimmkkmonmkiffhlmou|~tnmosxxsoprrokgdddegggfilmmmlic^\[YVX\^\[[[YVSTW]cfgjmnic[VTRMFB?<9766654446532110/.,,+*))))('''''''((((('/133589<?CHKNQSSUWY^hopf]bhf\QOPOSY_hrx{~}rjjr}~}x}{zxtprtrkihijjknprsrqu{~xojgfdeghghkljjmpomlkihjnorvz}~xokjnuvnikoonkigeedefecfjkkkkga\YWVTVWXZ[\\ZWVX\cijiikjf_ZVQNHC@=97666555666532210/-++*))))((''''((()(((('0123579<>BGMPSVWY[\`jrtlekndULLMNRV\gptx|~pffnuwv|z|~zx}{zwttsniijkkjiiklmnpsy}|vqmifeghhhjkjimqqqrronostuxxz}yrmhfklfcgklllnkgdceggeehihhgc]YVUTTSSVXYZZZZ[^chlkhffd`\XTNIDA>;86555458:86432110.-++*)))('('')**)(((((('1123579;=AFKPTW\bcackuxrmnl_OFFHLPTYajnsy~vjcfntrpv{}ztrx~}{yxwupooomlkiggghjlnrx}|wrplijjihijkjlrw{}|yvvyyxwuuvuqnjdbb``diklnpmhdcfiifdddcec`][XVVUTTWZZXVX[^aegijhgd`[WSOJFA??=96543458:8642210/-,+**)))('(((*-.*(((((''1123369;=@DHMRW^fhcbjsurnibVKEDCFKOTYahpwzvmcbhpsrruvtpjmv~{z||wtuutromjhfddghjmsy{xutpnonmkijkjmry}~~{wutusrsrjc`_aeiklnomiedfjjfa_^_a`^]\[ZZYXY[]\XVZ_abdfgknkd]WROJFB?>A@954334557643121/-,+**))(((((((*./+(((('''1023369;=?DHLQV[acaagmnmjaWOJHFCBEJOT[dlpple`aiqrswxtpnknv}-5&z||y{}{xtpmkhdbdfhjmruwwvuvwvrnloommqu}|ywvwutyyqhcbcehjjlmkgedehif`\Z[]\\[[[\]\\\\\[Z[`fjgfgkprkbZSNJFB?=;<;633333454432122/,,+**))((((((()*+)(''''''0022357:<?CHLQW[_`_bfhgge]RLJMLFCCGMS[chjigd`bioqsxysonosy})3~z}ztqokgdcdghkorw{|}|tsvxtomqyzxxz{yx{ysqnheefgffhhfdcdeec_][ZZYYYXY[\\\[YXZ]aemtqkjorof]UOJGC?>;975433333343321222/,+*)))))(''(((((((''''('&01223469<?CGKQW]b`_afhgdaYQLIMMIFEGLRZafggfccdinnnponmlpy }}~xvtqmhefhilpuz{x{~{rmot}~vuvz}|{yus|{meedbaacedccedcba`_][[[ZYXWXXYXWX[`dir~~snpplcYQKGC@><9753332222232221110.,+)))))('''(((((('''''('&01223468;?CFKPW]a`_bhmmh`YSLHFGGGHJMRY_deeddfhjmkihghjjp|~{zzwsmiijlnsz}y|~|vrqr{|tqrvyywsnovthcgfa_`abcbdghgggfeca__^[WSRTWXX[^cfkuvpnlg]SLFB@><:864333322223221110.-+**)))((((((('(((''''''''01233568:>BFKPV\`bcekqsl`WQLFBBDFHKMRY`dbaacegikjgedghinw}}ysnllmns|yy~}ywtu|snnpsroliffd`bjidccccbaeillkllkheca`]WSQUZ\]_dgimtyvplhc]VOID@><:864212334322332100/-,***)))((((((((''(''''''''00123578:=BGMQV\adfhknoh\SNHD?>@BEGINV^b_\]`bbejkgcdhhhlsz 1' }~xrolknszxz}zy|umkllkihea^]]bgggiihfcbfkooosspkfca_\WSSY_bdfilllomjgd`[VQMHB><;96431122333332211/.-,*)))(())((''()(''('''(('''001234689=AGMPU\bfikjhf`WPKE@=;=>?AEJQY][YZ\^`ekmhceifekptzC5~}uplkntx{{||qkjhededa__adefjpssoifjnpqtxyuoic`^ZURU[cikklmlkjf`][XTPNNHA=:875432122233332110/-++*))))))))(''(()(((((((('''011234569=@EJNU]dkomid`ZSNJD@=;=>=?CHMTYXVY[\`gorkdgjcagknu  "1<( ~|tonquwy}upnkgccefgghijowtoqsruy|{xtog_]ZTRU[clollmkigaZWVSPMMMG?;975333222232112100/.,+**))))))))('(((((((((((''('001124569<@DJNU]eotnga\VPKHEC?<?@?BFILS_`ZY[\bjstkbbc_]aehpzBknbV<|~wtvxxy{xrpqssmjmrsqpqvzuw}|zxpea^XTV[ajkhikid`ZUSRPMJHGA<986433322222110110/.-,*)))((())))('('''''((((('(('00012357:<?DINV]dmrme`[TMIGED@>@BADHJKTdh\XZ^cjrpe]ZZZ[^bgnv{Spl^4}z~{ywx|~{}{tnjkr}~~~yy~vng_XXZ^acbfif`ZUTSQOLGD@=:86433322111111000/.-,+*)((((((())(''''''''(((''''&000113469<?CHNU\bhmjec^ULFDCC@>?@BEHIKQ^aYUX]bglh`[YYYZ^dhntz 1LMBT\2~|~~xsqtxz||yutwypigmxqf_[[[]]`deb^XTTSOLID@=:754322212111112321/-+**))(''(((((((''('''''''(''''&/01112479;>BGNT[`ejihhcXKDBAA>=>?CGIJKNTWUTWZ^beb\YXZ[[`fjotx}2J.~ywy~yy~rmnqqqokikp{|sjkvrkd`aa`_`cb_[WTROLHD@;9853322211221114;A>60-***))('''(((((((((''''(''(''''&/01123468;?CGMSY_eiijlgYKCA@><<=?CHJJJILPRTWY\]_]ZYX[]^bhlprux{}*?/}wsu}wpntuklmkifbaekuzsr}xolggjjgbaa_[YVSPMHB>:7764222221121014ApS5-**)))((((((((())((((''(((''''''.01233458<?BGLRW]eijkmg\NDA@>==>?BFHHHGILOSV\^\[YWVW\abcgknqrsuy!$#}|xss{~{tlgjzrhjkigd`_chov}~}~{!~pkjijooica`[XXVRNIC>:75542112211111118e3MB/+*)))((((((((((((''(''(''&&''''/00123458=?BGLQV\cjlllibVIC@???>>@DEEFFHJMQU\^[ZXTRTZ_``cgjnqrty} +K3{wrqx|wuqmihn{uhfilifca`befjnsxyuw|~K`Gsjiijjkjfb`]XVURMHC?<9643321121100/001; /M0+*)(((((((((((('''''((('&&&'''&000123458;?BHMQV]cillkkj_NEA??>==?AAADGIJLNPTWXYWSQSWZ\]adioqszJ@|vrru|{uqonnlighigeegifb`_aba_^^_chkqw{~6SB|skikmlifca^\XTQNJFB>;:853222111110////06g[B.+*)(((((((((()(('''''('''&''&'&000123457:<@FKPV\cgjigii^QGA==<<==>=?FIKKJJKMPTVURQRUXY\_dq}vs|~trssu{{somllmmfbcghhgfb^^`cda\XTSVZ`gnv| yplijormfa]ZWUQMJFB?<977643210000100//../1@}S3,*))))(()((((((((''''''''('''''&//01233468;?DIOUZ`ceecdc[QIC>=<<==<<?FJKKJIHILPSRQQQTWZ]_f}ov{~  :~tqrqpxvqnkiklgdfillkhdabegif_XRPRTW\eq|vnjihinng_ZWUQMIFC@=;98653222100000/...-,,-09A=3-+))))*)()))(''''((''''''((''''''///1223468;@EJNRW[]`bbb_ZSLE@=<<==<<@DFIKKJIIKNPPPQSUW[^_cwngmqx{tpomnyxsqnkjkjijlnopoljiijlje`ZVVWXYao{ztkgggeefd]WTQNJFC@><:8665311121000//..-.-,+++-..,*))(())((()((''''(((((((())((('&&0/01123467:?EKNPTXZ]`_^\YUOG@=<<<<;<?BDGKLLLLMNNMORTUX\^_`efacimu|wtqqrvwrrrqrpoonoqsurpnljjllkkhdda]\dpxzpv~ujeegfb__[VQNKHFB?=;98644321222100/.-.---,+***++**))))))((''(((((((''((('())())(&&&0111113467:>CINORUX[\[ZYXWQH@;;;<;;=@BDFIJJKMNOONNQTWY]_`adebdilq{wvvz|tprvy{wrqswyyxtomkjkouxxvvvnd`enu}puztwvkdbdfd_\\XQLHECA?<;:865432223220//.---,,+***)))))**))))(('''((((''(('(((''((''((&&%0121113467:=AGLOQTVYZYXWVVPG@<:;<<<>ABCEGIJKLMMNNMOTWZ]^_`bcbdhiks~}xy|}sns}{sqyzsqompxzldcjqx}klwytnjklje`^``^YUVRLGDA>==;9975432233321////.-,++****)))))****))(('''())(''''(''''''(''''&&%01211245579<@EKOQRTWXXWUUUPIC?<;<=>@BCCFJMPOLJLNNMOSVX[]__^^`cffgn{uvy|zpv~ww~}yyujdiqvz|{{p`\cijgdccba]ZXVRNKKIEB@><;;97764322465310//00.-,++****))))**))))((((''())('''''''''''('''&&''01222234579<?CGKNQTVXWVTTSOKGB=<=@BDEDEILPSRMJLPPOORVY\^`][\]_bdejt{xpms{|uz~zohktxx|~}~~{upnj^TSX_baaaba_[UPLHECCB@><;:986565432246531/.///-,++*)))))))))(((((()((((()(('('''''((''((((''''01222224579;>ADHLORTWXYWTQMJHE@>?ADFFEFJMORQMLNQQPPQTY]^^^]]]]`bcejkgdfox|y}{~}|wrqvxwy{yvuvz~zxricc^SNQUZ^^^_aa^VOIFB??>=<;:9876444553222321///.--,+++*)))))))))(((((()(('(()(((((''''(('''(((''''01222334568;=?BFILNQUY^\VQLIIGDBAADDEFGIKMPPNMNOOPQQRW[\]_`_]^`a``a`^_djou{}?G~xx}|yy|}{xututpmnoqpnmh_YXUPPRTX[\\\]^ZQIEB@>==;:999864333553111110...-,++++++**))((())(((()))(((())((((((''''''''(((&&''01222344568:<>ACGJMPSW^]WRMJIIIECCDEEFHJJKNQPOMLNOPQSUX[\_`__`aa_\[[\^beinuw{'F~x|zxz|{x~wolnlgdda____\WRQRRRSRTVXWWVUQJDA@>=<<;9878854433332110000..-,,+++***+*))((())(((())))((((((((''((''('''''''&&''00223334567:;=?CGKMOQRUWUQNKJJIFDEGFFGJMLILPQPLJLMNQSUVXY[]^`bbb_[XYZ\_cgjoqv#?~{yxtmnwqfbba^[ZWTUUVUSQPSTTRRSTSRPMJGC@>===<;98656543332221100//..--,++,+****))))))))((((((((((((((('''((''((''''''''''/01234345679<>?CHKLMNOPQRPMLKJJHEFGFFFJNLHHNQOKIJKMQSUTVWYZ\`ehie^ZYXX]dihhjp)4zwuogelxvg]ZWTRQPONPQRTTSRUWUSTUSOLIFCA?><<<;:987544322222210///...---,++++****)))))*)((((((''(''(((('&&'('&&&(('''''((('00012344567:=@ADIKKLMOOOPOMLKIIJGFHHGGILKGGLONKHHJLORSRSUWY\blx~td[WTTYcifdfmxC~}sssngbbfcYSQOLKJHHJNQSUVVTVXUSSRNJFDB@>=<;::9876653322221100/......--,++****++**))(()(((((((((('''((('&&'('&&'((''''(*,*(000002455679=@AEHJKMOPOOPONMKHGHGGJLKIJLLGFJNNKHGHIKNPOPRUY^gvjZTRRV`hfcglqv|~{}~~rkoqnf_YUQLIIIHHIGEGMRTVWURSTSQOLHECA@><<;:988754432221211////.../0.-,+**)())*+**))((((''(()+)((''('''''''((''((''''(-=K@//00012356668;=@DGIKMOQPPOONMKGFFFHLONLLLIEEILMLIGGHIKMMNQU[cl~lYRPPSZa``gkklnqrppu|kz~}~{tqtz{wvoedjnib[TMIFEEEEGIHFGMRTUVSONNONKGDCA?>=<;:987654332211110//.-----/0.,+*))(())*)))))(((((((()*)('''('''(''''(('(('''')<I/011123566679<?BFIJKOQQPONLKJGFFFHLOOMMKGCCGKMLJGGHHJKLMQYaej}kXQOOORVX[addccfgjmt}pd_gsxyxywupigkpw|yxrlfa\^dd_ZUOJFEDCCDHJIHILPRSRPMLJIHEBA@?=<<;:8765433332211100/..-------,+**))))))))((()(''(((((((('(''(''''((''((''(('''+Ima/000123456679<>AFJKLNOONNMKIHFGIJIKLKKKIEABFKMLJHGGHJKKLQ[eddpcVPNMMNPTY\]]\[]`cgpvme_`dkpqqlfc_`cfiprlijg`ZY[^^ZUQPMIFEDBBDHJJJKLMOPONLIFDB@?>>=;::98755432112111210//...--,,++******))))))((()(''((((((('''(()('(''(('((''(((((*@L.//0123446789;=AEJLLLMMLMLKJJIINPKIIIHHGDBDGJLKJHFFGIIIKPX_^\`lsfXRNLLKLNRY\YWVVVXZ\bt#}~ztsv|}}tnmkfdcehkib\YXZ]^^__^\\[VSXaa[SNLMLHFEDCCEGHIJJJJKLLKHECA?>=<<;:987654443211100000////.-,,+++*****+****)))))))('()((((((''((()('((('(((''''''''(/G_L2.//1122346899:=?BFIKKLMLLMMNRSNOQMJIHFEEDCEGIKKIGFEDFFGJMRUVVVXXTQONLKJJJNVYTQQQQRSTX`uplkifflpsw}zlegjkkf__`_[VTTUXYXVVVTTUTSY`\UOLIIJIGFEEFFEEFGGFFGHGFDB@?=<<;:9877754433210010//../0120-,++*****)******))()))((()*((''(((((''(('((('((('&&&&&&'(*,.,)./01222347899;=>?CIKKLMMMNOPWZPJMQSPJGFDDDEHIJJJHFDCDEGIJMOQRRRPMMMMKJIJJNUVQLJJLNOQSX_quh`]\Z[^bgnuyuja_acfb\YXXVRPPPQRRRRQQSVWWWVRMLKIGHIHHHHGFDBBCCBCDDCCB@>==<<:98769;64432110010/.--/1452.+**)******)))))))(((('(()))('''(''''''(''((''((''&&&&&'('((''/001123346899:<=?CHKKMNOONNOSTMJVhm`QJGEEEEGIIIJHFDCCDFGHJLNPPPNLMLJIHHJLRZZQJFFHJMOPSTZclpoib[VTRRSW\bhnng^ZYXXWVUUUROLMMMMOPPPQUYZZVPLJKJHGGHIKLJGEB@@AAAABCBA?==<<<;:8755795343210110/.-,-.0220-+*)))*****))))((((((('(()((('''('''('''''()(''((''''''''''('&00001234567889;<?BFIKMNONLLMNNMRp_OIGGFEGHIIIHFDCCDEEFHKLNONMLLKHGGHKNRZZPIEDDGJLLMNQUZ^_\ZWURPOPRVZ\_a^YVTSPNOQRSQNLLMKJLNOPQUY]`ZSNNMJGFGHJKMKHDB@??@AAABA?><;;:::9764333222210000/..----./.-,****))****))))(((()))(())('(('(((''(''(((((('&''''''''''''('%01101224578889:;=AEGIKMOOLLMMLN[rRJGGGFFHIHHGEDCDEDCDFIKNPONMLKHGHIKMOSTNIEBBDGIKJKMNQSTSSSSSRQQQUXVTTTROOOLKMQTTQNLMMJHJLNOPRW`gbYSSRKGFGHIJKJFCA@??@BA@??=<;:9888764322210010000/..---,,,-,+***))**++*)*)))())))*)((((((((''(''('''(((('''&'''''&&&''&&''&12211223578899::=AEGIJLPPLLMMLO\ uRIFFGEFGHGGFDDDEEDCCEGJMOOONNMJHIIJKLNPNJEAADHKKIIJLMMNNOPRSSSQPQSRPNNMKKJHHMUZXURONMKIHJMNONQ\gg]TSRLIFFGHHIHECBA@?@A@>>==<:987665533211100000//..---,,+++,+***)*****)))*))))))**)(((((((('''((''((('''''''''('&&&'''&&&''1222223346789:::=AEGIJNTTNLLMNPYnfOHEFGFFHGGGGFFFEDCCCEFHKMNNOQQLHGGHJKKMNKEAAEIKIGGHIKKJLLORSSRPNMMMOONLKJIFEKU[]][WPMKIHILNNMOW`aYSQPNKGFFGGHFDCCBA@@@?=<<=<:886544432111210/0/..--,,,++++++***++****)))**))*)))*))(((((((((((((((()(''''''''''''&&&'''&&&&11212333457889:;>ADFHJNTTPLKLNPV^hoiXLGFGGEEGGGHHGGGECBCCDFIJLLLNTVPIFFHIJKOQMFCBDGHFEEFGIIHJLNQRQONMKHIMPOLJIGFEHPVZ^^ZPLJIGGJMNMMQVURQPONLHEDEFFDDCCC@???>=<;;;977644443210011////.--,,,+++++++****++***)))*)**)))))))('((((''())((())(((''''''''''''&&'''&&&%012222334568899<>@BEGIKNPNKJKMOTWXXVOJFFFCBBDGHHHHHGECBCDDFHIJJJLQUQIEFGHIJPTPIECDEEFEEFGHGGHJMPOLLLMKGGKNMKIGEEFGJLPSSPLJIHHIKMNLKLNOOOOONKGDCDEDDDCCC@>===<;:9887544333210//00/...---,,,+++++++*********)(())))))))(((('(()((()))(((((((('''''''''''&&&&&&&&&&112222344579999<>@BDFHHJLLKKLMNOQPPNJHFFEB?@CFGGGGGFEDCDDCDEFHHHJLPNGDEGFFHKNMLIECCDFFGGGGFFFGKMLIIKKIGGJKIHGFDEFGGFGJKKJIHGHJLNMLJJLMMMMMLJGEDDEDCCBBA><;;:9976665443222110/./...--,,,,,+++++++,+*******))((()))))))(((((()(((()))('((((((('''''''&&&&&'&&&'''&1122223344678:;<>@BDEFFIKLJJKLLKKMPNJGFHGC@BEFGFFFFEDDDDCBBBDFGGHHIHDCDFFFFFEFJMHCBCDEGHGFDDDEGIHGGHHGGGHGEDEEEDEFFEEHIJJIHGHJLMMKIIIKLKKKKJIHEDECCBA@><:987775544333311111//./...--,,,,+++,,++++++*****)))((()))))))(((((((((())))('(()(((('''('&'&&&&''&&&&''&1122243345678:;<=?BCDDFHKKIIJJIHIOWSJFFHGCACFFFFFEDCBBCCBBBBDFGGHGFGDBCEFGECAAFJGCABCEFGFEDDDDDEEEEEEEEEEDBBDEEEFFFEFGHIJJHGHJJJMLJIIJLKJIIIJJFDCBA@?>=;9876555443222200000////....-,,-,,+++,,+++++*****)))))())*)))))()()((''((())(((((('''''''&&&&&'''&&%&&''&0122343345677:;;<>ACDDFIKJIHHHIHHPZVLFDEDBACDEEFFECAAACCBAABDFHGFGIIFCBCDEDB@@BDC@?@CDFFFEEEDDCBCDDCBBBBA@@ABCCDDDDDFFFFHIIHGHGEILJHIJLLKHGGHGDBAA?=<;:98765444432211100000///....--,,,,,+++,,+**+*******))))))***))())))))(''''(())(((('&&'''''&&&&&'''&&&&''&&01233333556789::;>@BDFHJKJHGGGHGGLROHDA@@@BCDEEFEFDB@ACCBAACDEGFFGGGEB@@ABCBAAAA@?>@BDEEFEEEDDBBBBBA@@@@?>>?@AABCCCCCDCDFHIHFFEEHJIHJKLMLIFDDCA@?>=;99866544444432211100000///..----,++++++++,+**+**+*****))(()))))()+-+)())(''(((()((''''&''''&&&&&'''''&&'('&&111233345456899:;=@BDFGIJJIHGHGFFHHD@?=<=DLHDEFFFEECBBDCBABDEFFFGFEDDBA@@BCB@@AA@??@BBCDEFEDDDCBAA@???@?>>>?@@@@@A@ABBABDFGGFEEEEFGHKKKLJGCA@?=<<;:977644433443322211000000//...-,,,,++++**++++++++*****)))))())))((*183+(((((((''()((''''''''&&&&&&&''''''(('&&111234454446789:;<@CDEFGIIIHGGGFFFE?;:99<J]PEEEFGFFDCCDCBABEFFFFGFDCDCAA@AAA@@A@@??@@BBBDFEDEDCAABEA>>>>>>>>???>>>?@AA@@BDEEFEDCCCDEGFFFDA?=<;:997776554333333322221100000///.---,,,-,+++****+,,++*))*+**))**))**)))+3;4+((((()(''()((((''''''&&&&&&&''''''))(''112334554446789::<?BBDEFGIIHGGGGGGE?:889;CMICDEFHGFEDDDDBBCEFEFFGFDCCCBA@???@A@??????ABBDEDCDCB@@EMF>=<<=>==>>=<==>???>>@CCCDDBCCCCBBAA@>=<;9977755665543333333322221000/////.---,,,-,++,+++++,,,+*******+*)))*****)*-1-)()))())(((('''(''((''&&'''&&''''''(((((112235555556678::;>ABDFGHHIIIIHHHHFA<889:;>?@BEGHGFFFFEDBBCDDDEFFFDCBBBBA????AB@??>>>@ABCDCCCBBAABEB><;;=>===><<<=>>>=<<>@?ADCBDHGCA?===<;:9876665555443233322222112210////...---,,,-,++,,,,+++,,+******)**))*--****)**)((()(((((((''''(((((''&&'&''''''&'''''''112235555556678:;;=@BDEGHHIJKKJHHIJHB;889:;=?AEGGFFGHHHFDBCCCDEDEDDCCBBBBA?>>@A@??>>>>@ABBBBBBBBA@??>=<<=>>===<<;<==<<<<<<=?BCCFIGB@><;;;::987665554433322222222111000//00/...--------,,,,,+++++,,+**)))()**)*./,+*)))))(((((((((('''''((''('''''&&&&'''&'''''&&1122355555666789;<=?BCDGHIJLLKJIIJKKE>8789;=?ADFFEFGHJIGFDCCCCCDCCCDCBABBBA@???>>??????@A@AABBAA@??>>=<<<<<<<;;;;;<=<;<<;:;<>ADEEB?><::;;:9887665554443322111121100000//0/.....----.--,,,,+++++++++***))))****,..,+))(((((((((())((((''''''''''''''&&'''&'''''&&1223454456666789;<<?@BEGHHIJJJIIJKLJE@:668:=?ABDEEEEFHIIIGCBAABBBBCCBBABAAB@?@><=??????A@??@AAAA@>>=<<<<;;<;;;:::;<;;;;;::::;>AA@><;:99;<:97786665443333321111100000000//../.....----,,,,+++,+**++******))***+-12.+)((((''(()))))('(((('''&''''(((('''''''''&'''223345445566789:;;<>@BDEFGHIJJJKLKKIHE?868;=?@ACDDDCDFIJIHEB@?@ACDDDBBBAAAA@@@>==>>=>>?@@???@AAB@>=<<<<<<<;;;;;::;;;;::::::::;<<<;:9889::987776675432233322122100000000////...//..--,,,,,+++++**++**)*******++-13.+)(((((((()(())((()((('''''''(((('''''''''''''333455555667799:<<<>?ACDEFHIJJJLNLKJJIE=88:<>@BDDBBCCDFHGFDB?>?ADFFEDCCBAAA@@@??>><<==>?@@??@@?@?>====<<<<<;;<;:::;;;::::::999:::9977888887777656643223332222221000000000//...//..-,,,-,,++++**++++*)**))*****,./-+*))((((((())))((((((((''(''(((('&&'''&&'''&&'333455555677788:;<=>?@BDEGHIKKKLMMLKKKIB;89;=@BCCAACCCCDEEDA>>@BDFGEDDDCBBBA@@@@?><<<<<>?@?@@@>====<<<<<<<===<;;;;;:::99:::999988877788887777765554433333222222200000000000/.....---,,,,+++++**++++****))***)*++,+**))(((((((()(()('''''(((''''''('&&'&&&&'''&&&334455556667788:;<=>@ABDFGIJKKKKLMMMMLIB<89:=?ABBAACCCBBDEDA@?ABCDEEDCCCBBBBA@@@?>==<;<=?@@????>==<<<<>>>>>>=<<;<=;::999:<;99988887677897655676544443333321222210011000000//......-,,,,,+++++**+++++**)****))****)))))((((((((((((''''''((''&''&'''''&&&&''&&'&&3454566676667789:;<?ABBDFGHKLKJJLOONLKHB<::;=?@ABABCCCBCDEDBA@ACDDEECCCBBBCCBA@@?>>>=<=>>??@??@?>==<<>CHE@?>=<<<;<;;::::;<;998888877667865556665544443332222222111110000////.....-,,,,-,,,+++****++***))***)**))))))))(((((((((((('''''())(''''&&''''''''''''''&2355567776667789:;=@BCDEFFHJKJIILOOMKKJE?<<=>?@AABBBA@BDEDCBA@ACDEEEDDCBBCCCCB@@??>??>>>>>@A??@@?>>=>E`}jJ@>==<;:99:;;;;;:9998887777666766555555544543332223332221110010////////..-,,,,,,,,++++*******))))****)))()))*)(((()))(((((('''(+,)'''''''''''(('&&''('%135555676667888:<<=?ACEFFFGIJIHIKNONMPOIC@>?@@AAABCBA@@CDCBA??@BCDEEEEEDDDDDCBAA@@??@@?>>?@@??@A@?>>?N[B>===;989:;;;;;9999:98777766676666654554454433223333222112111110/0220....-,,,-,++,,++***)**)))))))))))))))*))((((()(((((((('')++('((((('''('''(&&&&&&%134555667777899;<=>?@BDEFFFGJIIJKMQQPTRKEA?>@ABCBDDDC@?@BBA@>>?@BDEEFFFEEEDDDCCBBAA@AA@?@@A@@AABA@???LXB?>==<:889:;;;::99999998887667777676555444555433444323211221221101552....-,,--,++++++**)))*))*)))))))**)))))((((((()(((((((')))('''''''''((''''''&&%%&3344457767889::;<<=>@ABDFGGHIIIJKNSSQRQKFB>=>@ABDEFECA>>@A@>=>>@CEEEGGFEDDEDDDDCCCCBCBBABBBBCCBBA????EXm^HA?>>=<:889::;:::99888999:98777776667666545665544444433211111222101430..---,,,,-,+++*++*)))*+***)))*))**)))))())((())))(((((()*((('&&'''&''((''''''&&&&5554456667889:;;;<<>@AACFGGGIJJKLORRQQPKGB><<?AADEEDC@>=?AA?>>>@DFFFHHFDDDEEEFFDDEECDDDDCBABDEDBBA@@@ADFFB???>=<:89999:;:999888999:97898876666677765554554443343322111222100//./.---,,,,-,+++*++*)()*+***)()****)))((()*))))))(((''&''()(((&&&'''&&'''''(('''''(scikit-image-0.9.3/skimage/data/tests/000077500000000000000000000000001223313777300175745ustar00rootroot00000000000000scikit-image-0.9.3/skimage/data/tests/test_data.py000066400000000000000000000020661223313777300221220ustar00rootroot00000000000000import skimage.data as data from numpy.testing import assert_equal def test_lena(): """ Test that "Lena" image can be loaded. """ lena = data.lena() assert_equal(lena.shape, (512, 512, 3)) def test_camera(): """ Test that "camera" image can be loaded. """ cameraman = data.camera() assert_equal(cameraman.ndim, 2) def test_checkerboard(): """ Test that "checkerboard" image can be loaded. """ data.checkerboard() def test_text(): """ Test that "text" image can be loaded. """ data.text() def test_moon(): """ Test that "moon" image can be loaded. """ data.moon() def test_page(): """ Test that "page" image can be loaded. """ data.page() def test_clock(): """ Test that "clock" image can be loaded. """ data.clock() def test_chelsea(): """ Test that "chelsea" image can be loaded. """ data.chelsea() def test_coffee(): """ Test that "coffee" image can be loaded. """ data.coffee() if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/data/text.png000066400000000000000000001233201223313777300201250ustar00rootroot00000000000000PNG  IHDR#:IDATxuߒ =Q1\[}ſuvf:O>hѠB  sHHH4cۙveUoY1"ƻRX\sy璄8s@`+y0"3pKy@$ewaŮbt2wv0RӘ J bȵaXNn:uvCwظnuaRGeҏmy& (қQAbvuѩ!n%eb?ٸjS.O)܍qAlP"SpĮw݂!B{"")~li9|fE8Qu24Gn,ypB!!e¸I2 (=gk\K@&0e@% 8"N!awev3#Xq8XQM~zO/7v@څH;g3$DrpUdAֳ 9z-Vs)rO&D J +Z[Jȃb EHa` *aN5zb]92_S#+ÜbE.J't"jN<s@%';8l%oZBݭt$y &@޺aw^~9[5*a*y Ub=?hsJ2~A0S[g::n=}PzDD0dG\e$DUVXSHL0:wwgI*fd0&Vw@N{2818V''$"w):\ d'&k >(Yѕ53=pA[vk0oV t K nM.kBҞ NR5GADh!a^ֱxb0/H܈0~&uLnrFGo +x'3g7LI"l:=Kٚo4'mu1KhM>`0SI=V9H"GG 9<+̹s8X=:ؕj>pC<`Uxr *8 3RTBXxU)dK!Fagh6qe + ڬ:°iD\@nDL! 1>:6b7Xjz7^'Jb&o6rG6w_~9}>j?:u :KHU& mh 괏',C^T]AW,k(&0f!D,/]=@PG]SU ZYc+w*ʴ3Z n w_(\u@6gL AA* uXwa{TA;E0p0R/  uim9D-+2yĺb}_0AJ~ozM&W!N\Vޖ_>|WSkcW Amѵg.8`R_fNk^Wb.h•E`9zjXC 2< ]VѭSRbXA^2_̈&bwd3NÅ0Pg0Sksa?p4nRg&#8QY1'_B΁ A4B]TY jM]= p& #%H %uQb(w,C4PVj@=Ʊ׵ gڴ߮޽Z z (|x4j]t,}Xpޤ8SH/qȸMUŃA2P6mX 'vʝ`Zϝ]$)+b '_P[TSH \uXP漙/ OKQƐy Z t%g,}ͬi25Ap#iP GP: {s20={f+RKvׇݏ>sC6`nPi,:aFv6FxVG7,B-cOk2Dш0M3QG : !Ad q JS8-":ŪMJbB%ΰwoP6(u#XNijXwH&T{ G}8/) L2"ȅuRxuCŗkO_w;51|MkcYŊ{_ ي5M@7*`B lSݳH2/sC_M*މzX!ӀZzOR:6>aÙh3/mJѡQs˝r^h& a~ح#Ibl9`} C[x}7l2NZ"q3NdĜ̓kWgS7vHDXkEwr;i?y|t{szQ==.4`eizFZ3 Luۛvճz&D7TBDNaIVem)ε.FBW S$❖ ny]i979nf$@@eu &f&'YIaN;3`' U#c%κWb@DL>!0nZstp\ >}ňݙ ,Likd,Mփ`!f$p;pKޅ$p&ӁZ4/y C#t,\,P 5[FHv傦)z#C-ƕCEDY:C!$_io|joB1(") ^G h56&}aQP 9L,Y vBY$2Ϗp"/T4s+Zhq)V!Z @ ba p ;D|sr|Ѱŀ2F𲈴T+!6KU A#Ûxj[2EVF^3ͩiԟNeUUC([`)2aْ5):@L8 Y6 ^mmʔy{V "0J6y Po CD(!BViĝ(`[-XI R:c )<@*Em9I;h SCG[sFJ3C2IGXP6wҗյ.(9t՜99\GS5 ^MH1(1RH7C݉)l#HzywVv bKʊ *]/QD]6޽>ߓaM5*ePwOC@emh eLnA@CN:F /olbB]mpk@0!qM- ު{=!܌@Y#`b7a'r'5{5azN3!]󆷭Q{Pe($PҒlRy̼ b=]E.!k7l䂅=]Âʪi|M!у("#%V^ޞn߽ƒ_{Hcw)z\RP@iksC[r(eXRޯc%CH]Z2Cޙ-aRc)?h_ڲ}8k_&\@)k7ix~گhDn5 oeXJ~ UleAcj;0γ/\:"WJD˜"CBQh gpIg9պ\"cHFK~vC{ҳ 2pz%5'{ƒ¼R'eRU)=#8B -8"=Y #CD 噱6{cD]n`+#Y  ku%G3!b\M3RAxئ}uOÃZ [&iPP@Hr},:ƾZMf"+CJ @qpC]s̪]"=!yJ0gpjbg~ʙ": z]xzLF/=mjĄ#Fn$4JB.SZAgn@WF5ɺ .$LA8E3m=%w0'(\Z]Wqtа+pQق19L >y @रNԂkVǒڏ>ۏ>湣"̆@7M[0vUH_n|4WƶY׈{UxMM։V:Wȗ]F;#^i'pPVᲀ fApN,݌RA@xpPTlkC|s"w48Xy#o||$Ɋg@pYS0oQ`p#Z/|z{guh Ԃ# wktM "2ֱǴp^.QܹB9  JA`PȽ#qcbh]XKP*J,#GRCLՉ8Y#83Eӱ=a0C9ҘaD@BKb[i~B]*{ n$ Hxm`3mؖCE=~_P$BDfT u]3H|}9>wNQ?q*+"["@(:;(%31f[̽, qXՑQ!XQ& FL q8NϣSnH2Qpiq0h4(J +we J{#+G.mn+9FuK&2#&%vgiCL)͸x<>qFт`2G IgQi^-:-N뀀f= FlXn!,~a;ܺeZ]l3r3 cwB`{t s#[;k3{om`L`YϪ44h=iS}$y\a36D@f6ԍiKj,lp#Iݟt ݵӴi}6[!Dh k9kڕ{yL>lED"޽ + Y]{Ffz }`ֆa]|մiB`xm >W?*Vik@ ;4Smx,CWk rX)kiRT D5<$ove5J\r:vn'Pl+(SƔ4C[a$d=z11y_>&/2x[P~_2ތ98wW[P;^/N˙+<)cZI@<~ VEi,g^%[ϖ# WtT*Scfe\+8˪oxZ4p6K-cla³ ,Ϙvubp9sB;5up.~~B$%d%\@%Xp߀Ze 9)ABnL"A.vlLo.k%h( ۓ;tj tg<[Bmt˾2(^%0eE伿ʼm`sn( Rܽ,w߫\-X ԕ ALVCJDTG+hk!#Es@0%Vn><+ SVA0iD͋buhWM?JۭH) ܌UZޠpb* &J 0ppV*v[̟ +aw!‰̲-xez==-6IPp7TyYψ  1 1A*Oyv`u}9_e߸֐l nyF3gCcFWk+mZlb?9ϛY•pjߝoo^"M Cbǭ\kSUp3k/tܬMu;=8eo Z$ sN/Fp </jD2vyŵ <b I' @N‘*G %0W K@g2O|uwAnOudA8tK.Jl5~"whiGu/^NJD k0K O(gw˥s!x5wm.آ0xMe':%^lX za,&^΅zp^Sqa{(` tg]2/icx+FNjsA0ÍX,1$Z0ZX8\,JhhjE8:g s=:& -L<\)Oӷ si <3K5K`{Yǰ6FڮW|ndN$S e4&HC»󀄼.ǧj3!8kr`9E -Gkۧ-@nkB\johail Q8sdzLlv .^COq2+E!A"J_C0ýULİ@37zZ@ե2^:hmǍᐆ'W{\NmD#u U<Ij@gbG6ڣ~8W~?:+.d sx \)%8Rw+q~pZw\+|6& hm+ڇs-1Cy^=GJR]\>*V8((1l'a|񻇧۾G+'\(̈hT=g^H`H¢d Sus֠4D*Vy'L#H] K`0ew@ UӒӬe i  75qzgacs% BfNܳcre) C^F(Qi\p I܆d̎@nK& EZpS,3fu.Lpu3GL-G'󴙏|t7o߽2 v!xX3*0΄,a !V=y5;1 (kv:<"Ì](qq[ Bt80j: )Ӏ<9y@":!5T6sl~s|WdFK07zV $ mFLg 7,YN֠0$q67\B˳01-U\Cڵ m8ۗO !y } 4vws{Lk ԃ;\#mVч5iR|BQ뤰Vu|EŇ>":6k$^YskkDJ̺ QƪB9/x;]>XZ~[򐨠:,y)fafv{k,=JpqFrR3 $xa[[!'#?_.wb4p# ’J '(Rx8 x#Hѵp<=p>·ED" Xtv[n|n>g&Wpu"f;5$4'VrvTWy7aN-{%gY9":T$mZqe%4yemw\}zI)bv#pXF[[t ų,z@T<!ppEʆV邧xs [y)Z*]\?<pyrt" Qٳ(zT0g| y,B!,&`PŖ5ʻO*LX$;;X uan,%˫15le :D蹧X"$5fx@O=a<AacYxwu#\ϡʦ #(3Aޱe&y4"Q@n+y.im}na;_[G~Zο۟ >.2(:#yZhRqypkfA@z:۩|̉%xhmW#la]R@, K $n "JD]QC9*:, A9L#߮|5?1~6<֍ŋmw'`a#eY;&)y\6;1'd wF.dBgD;Q`̉P \iWSןflh5Cr)3o@rL-B GPo[(XBgk0`St7'G, "Ef^=*aJdB%,Q IKP'撫ke9nAp+FMF|77nv|tG0/%_2uetJ4O`bRD]QGvڙͳ5cd0TPg7ew}x, UoQF#K=>qs*Qj~ [c'G >ӺNMlCacϮ.+9ښ}rOJ&__~SO3lh= dX7j$lC+LhNa Gέf͹Tr`U?{BX ;@aㅎbo&5^l HԖ-=3J`d3<dzyX5j iXs2ĐmRGチ|y{ UWY`xBdHض\qɩ6xұQ0x̛ ;*q|X^ ^ !a3o ?WKͳv= vu.c}겼`iB e_A=ئq]FOde&Lq@awa\~ m0۴.;,3!"IO6a[HIڰx Ud0گ&m)!Ϥuxe.k[\w 9QxG| l\2 ޟ1pZ5F 2Aȩw S2B į߼{5-w@sVbf$~O()H" K/ch.DulWDK͏.O쏁URZ,0 ޒ`ZaHJu=?50k7"hgiG;. vNЃ%H sGXr) `XۜuXp-ɗM8r/%%!X}B<$~ow .Eiz\F0D` w,*=c-@TvwѻՇwOw췉z$-*axtѢI OҀyP!J2(ܬz o>~Oujߴ f9g#lN :&.cڕ9- 2G/>ƾ9LA]q_ J4"#wdfgHS%0DG{@ڤqs3U6xl$&Ppk#b@0ᛲ*5,1<7,3AM@o7onn *YBpwO}xY_L2!Cؼ~}77tV'>XP$MR,3x͸CD,ܛvSk0‚8lW˿WP^ SCҐ+#KPrR2`McmNPӘl-~{9/Wks;W3hI݆+ w{~g?yy}Fh="niֻ"I7JU@@X繇txlSz9sK?/?/Ȳ/ctN ſpݵ˦):s`VIV0 {;?}_RLZs 95LCo|C\Ru4 NָMpJ5H50U& a\{i tvwx)~|ȑix"Ko?>|t?itI ~YJ{O^mJ: ]s"\S{*#HInɝ]Ht|\dSk/Vmx]0.g9p4 zxm)^_œa_Ұz0 1--䏏jfuBPpiPڇn~uqHj\Za,w0!{ YX=+@L+Z=JIտz|Sݟ?Q7{E|ÛW6FD3(7=o OSqAPB`tsPi`$LbH5=d)@ZhuFkeu7_95?o2LnPnMF-=_z{>_]=`B2 )  গvۤ`n(=\5V`PRI`yM_%n$4,#%zmϛ4 0 ̙Ղ8rY"|n/:js՟__l<\ǷPd(;z͇7[|tԵH8 hU?C^4󚴀0Ew"J<"`xе,|(78ѿszK4ȰdW/xW)a [e"EeW(h\Hl^˔N6ۤ"ɼxQ ڑlLԖ}7}Yޘg۠I$Xϭu~zm-qy4u>śvd^d {B #MVx`=8;FarHH @.YO*p"N}#R'C^6}+]7Gɹ{|ӇaquZ]و,fen8]Z0/c[B@AdyYl.H/z >N扦\@ef-&DOsxgT)شe0P "#ϻ߲}Oݨtt6=0n__"O94|2O0\ [ x&rRZaBI$ U`a]E(ЙG.d r$maNOq! {xwuӕO-د[廯|~m~+pi>X;Ff7p,i5lDt= ]yD;8#鄂xD R:e,rJsHɕ puZfnFu27.zx5y|_~O?W/?67?NI8zu̞Kpр:ؒσD88l pd*Bk , F ].zp3 /ןϮF[44C}~hm[O~MېyOmGXN#1斻?ëa%JK鴱jm;$R)\1o^;rِR|Ijֱ)tƩ=n.z$zշwݠ[[O>+_<}zr 8lwܔWe7l,dErTRQH:.AY7E; 7-!´ntiTs8oUQm A?104-_?k˭9fl 'oT@u fB^$hP ׬ܗ^W|{aC=4(1$`pw/heI@2x0{HP3-zOA+!WyN@|8o流[|Z~W۶^y5 vpc{g+RJ&Ԝ sw !m:) 's]"˖05WV|mCEf-y?ߟGC9~~TkG8s1=GrFwG:\ .RH(6vs~zi/OOAiHU=GGW|[Ĩ+kBgP&au77k(a^X' *A fx?tpvIp7f 6 Z,p+X\y ݁^kkO5#*(;u,ȦL4s1ߒSF`Uƒ:BYI"V0t~<Ðz HX]|NQ$@~K`t(s=KdK[KDV=56"{",2 GS8&A& YbE{o\ޙiT"zH gfnzt7eo~_K<}~w;߾~}fv{/+˿zzݟN~W^tǎ hD,k@Y"/n$(dr}~[WĖηLޗ=5)!ƾwh"+˵z\%+?!Ӵ0RTՒC@åxS I12)hbj/Ϙ_)t 3l-^rC[4`VDn/;]}Ԍ3~~#Wwߕzuyu?jNN(1.O= G.~ׯ>nzYbjkB/)9܊;LkApuǺVeGƪrp\T1ۯ/̭2j,|Iz\c !yUEEZ&7dPZAIvRzh6HI$z/e_J!Lr)r3t[[Gzi(P׊ߑܰZ4|zsk#I^WNktz$2-r>'?lu wf:n¦`:%#3^w\j?SZO!%Y;jX=?|͇5(~۽`z7 FƼ$/F];/uT|%e=]ގ h'.9SM#0,Ѩk5HT,1/57"}v}e~S_m4#[6.5"=BFP`FRĻ ^ׯ_gN1͹۽^Nx?~2k'rI 76]2͇@jgr~;tRn+jB<2BL=:~w"nZӥ~iyzrN~|>;N0o{;\(<-hWr\8db@)n~>kax|Z3KpZH ʺ:jtRxc*%FtWՐewxۉ}w]_yλuL7 ҳʹzL1ԔXax=i\p_ܝ8]$吽ƒq1jrdYρVcV>ydJ4 _n9~xY)} J:Lwr>t>[^˴?}ɩ Wūv}7p׶/As1y]DMi#2PAH!4atH~iGMY~,/?ʄ,=-SD`˧H"2¥a=/\n=a):/E^ߡ<9U-dPC5ZPE0{_cNwxsGSSKj >|Hmyhye!$.02#*y,Q1kɐLEv|:eok-CbT]{<<9M,s]];r:,AڟL79n'j~HtQHZ6^t]m],:Cʬ%@F"aAJL1.SkI-W-E-/xz}~/pV{L=d0wݔ`JǂX^f`knwO|zPͷL"uR߿+Ȅ[l*̳e]|WO<.2UR(_ pWFGᨇ,}չ)yE5iHJ(3g`}=?~z뇻a+E|=u¼6܂6@uh؜QmraT1$ݟƧSuxFs"E\ A "H 1I$OW5t2URK['y}~"i'D:<#-qI`w(2WWٿTԮ]fR%y7ǯxr\p sW%5gikLN91!JT`J<K{ ǯK~:  NAsmeneJSd<Qs;sn1w+p0qǵ7_cKwn1TeMo %Q@,mڱ}/o8jqoO'_yR FOq5?u$`)6{NK9VƎH:$F)1e׵xÏ?|soJN#@ r8A*`\v q꿉Gt{\( NA" ~wy_9 :%R sxݯfu8 2Õ+z%ny:w婌xmQq,erXJ@Vn|N.Ua n|eo;|N{z*c"~)7[|yvJ,ݧ>"WF?]}^ϣ^bg1λ3ry0UQ[ bdyǾߎ]B.3W|~Gzsz+B۴E&" Tٌfe9j2eyZ?nWw绵M9vz~9.>K/}g#5[ E2܋,RƸkNCo^D`xPL $5ÇCf2 p_TBm] Șz"dAgSZ׏xWӇv\љ'zw,Ձ\Bw.e0$ sWw3iU\ ۀRH`=/:k-@i$6uI 0!IWR Jk3‹yk+|:QewVMx +Ǐ|WśX$[y(C8f܎Ә2%JGabEh[Mtj,"o'~kskX#w[y로ӟzqzYۿdyTX_n17˒ȺǸ·S5e%Ґ ҧ\ ۧ50(?bw\Tc[.WqJ[GNE`ŠC4wMF1 vxhdEqㄹx?^pJV$i[1I 6qM<jJvζ,aRK@CE!/!%jB?o~kW#BBHH;">aE^wk|?ۣU-dp.3N=1NC0~~a_wޞ>_߿j@*J"Dz$U-/2:ũ+N|>(2md"53vH7^eT E&EfFd HP$%͕?+,# Zd6-O{<] o^ETdHJD{O^~y-2_#Skۡ00}ϟη wo~Lj :*ڿY]>EwGBcqH%Ǘ?ມW9~_uz_op<:'yMv 3H(I3K$3¹(nE}lrcOwwAx"3p*zWa,AaJ@`B&"(}D4 Ms { ^?~9z__JWtxP~ׇ~1^Yw`!k_($O Ja|oE ަ>|.I &-S k=)p*}`15dL% zQo~Qwe fB]2%"  t(Ed hFԾbbƎ/|y<*X #n6 T Q'l2 ֈ1`W~z8罦i뢭 ..(Wݽ5̿~OK[7I$폿:~6=kĢTK EuOCE=sC১}ovK;O݄ȯ?}8:(vE\Ff$/ Dz:Qzq."BF6 La| SdfN =cBwn ZFsD;Ƽ|E|+v(K0+z@@4?O n7?,CDH[n?^o޿c_仺CAڭuT@˸9|/ǾO7xn:LLaS0<D%S%o[^Ze7x߾t9?ǃaH$3j_YœF#oawVam@WuW6q9i?B&S3nӚ2p\50y+Hn'TC dKSzyK{ٟvzmA 2ţbUT䴪 U" Zh%p鲦^ON m-U>5k^%*Q9y`]8`ߞl_tw޴ǀ !iʶ W(׷V_^逡HޅF݇OKE,/K9[A%uj'nv/ e/eE~x^;lq=q1݊ܬ^G<˱)S9[K>¶$]KY 3o+S,pG6}TN'%L#(tO vq|>sk/xuwma4!r:Ja_aP4"zKppu"Gk~^/|P|{)Ip  W!#2zPt91tx 0:)P͟f ; -z'-W)i) 5sd x3U!IP`҃n-! Ys8#e~vm.dD b\2. (UIī|ş^^P-d;v cS5xRAd|W=NQ3rL[dYҋZFf z(UmrA>/{;Md^I2HDg@@C tr CϪԘέJHǮ߮r`N*,Tt&4dA~=/tI˼]}lj6=;u H"9QE`9" ĮJ> ,gy.L$;m8Q>ѬaO㇗=_.> Qd%yfrZkW[ F` t(nHmzC?nƴ.Man 6M 8yDVtLDY w/,|ϧqYg XU{ a3DE@Y̤gEn|o8(Nc|mm)ArlJUVjQI !pҦCG1( I8§$0p'1E?-oz{}:pÝ/"Acfx`zoi;5W̡WMDb(0<^<[zz: $# $3|b "UbIײ{W?^%;D"/X-9q%l^<tLA!h&6b6o;Cdn[&iaLeZZnn_~#Q)0!T H"% Xӧg!-/D) zƄXhf+kHLMC!RJu/ħhgݫZHP *H"E> !Hd:|iEgx~~7y j8LM!U bʄA r+/uiZI]n' ܜ܊ThC7c)J:Hdf QьU[nB4#j` aafa5Iw QoLKpBiY=)2 Ky?7..~}? !A6%ZC}eUϘ ̺RuQ0Zy:d9E(^^Pz7n>-Yr J^.r/Mp .7R=PZ,r"(ntz3߇_}Wug#Bz18LD0>2\^L"hzSuj;,K[>9?Ӎ Xzy>FF9pI@yj9*"_%GuH)]^іq/ovJ1dҳ\0꒾Ev 5$ap8a>{B =uIJDFT`7,}R0e T." F0@0HO]?RL? d:afjJD:DN D$Z8t?Ӈ!GS?*ǟ~I@3j491f$dwuVka5+m>rǽKa"HDx2<43EEBiNs8Qա+5_=ק6EO'x9?’2OcsFF# 3He;z㰜_t>!·ex]\3NkcAVDI*/( )E2)Y{\J4,.b]vx!e%ZWʺV&u1P2>d'K=!tVG=q:.B6-у&@x JQH ?tФdDҠrw}TTnӧNd$Qamv^aIv?*o޵Ӽ"BDT_QEB(B!(=Țc0J*`FU18zys-ˆZL 3*حKd/ Z AUғ6? hC:Ҷ "I 4X)I ɀQDDOH,6`-/:Y5+~ps?J3dR ƭ2H' ͹Ób+\ǧq'zp,o^= z>vk@9,{*`Y4Z(o(6X"FV 0ԑšZjVG R;n,|Xzt"筘{ D7e CA^#E3APieLDfS,[K@"!Tgԡ!UB*! ]KO98tOՂ(0>||;0tDǴ!LKLhv]>XCe`+ni]T@R;j0(F'YHߥCIghRWEDh ALV_l#ao>~‘V:,5R PHMe0o5yz||[$ >Wm[6DCw&2=ϸ/MpkحB${zn7铸Rs[ZRFgpʊ4" [+s?y?</7#]J?-KAUrKUCNd*`Q2|9 b^mcMv>.ڭ 戤(us`$dRJ槗s4/w^?t{b~ލ"idv&%fTEdt&UI_د/X;)U5Gfڶ%(hBvЦ[DV!}x&&d,fY2d_SZ.Մ]ȼ͑( " O{ jni^)*"T04(L " 9)R7IL̸br")TIn^ZGGniFnI*\)[Da])O]|1`"CKo5s@4\+|]%o^v"1V2FI@fM;mXa!2%|{ttCh&b}sr4 h sBnTdMVZKiJQ0֡ITdu 2B0AXf& FT`.͐TǼzE'I&|8C1idJOAFx D業x7->}#N'7&NܥE 3 Ji,}T\7_|/NM F Udj$:)&(%S1J]\@w@ QQdAr^`$)=ؽQSF3c얚v]ӌ󨰄Vq! ,Q2?H"B9} rhcLZ͙4Q’ȑخl q#3u?G—ߺ,s/-{#3ͭRŲ$J0ter23j)3KWu LE $E( bmġ:AAL(eBSQd0iW-k-M`L|A1K4jRD$ ŒC #ʧ}Ѥz$(Z!HSH }f LAXcBFb. ){6 Kd2A`#h/˧cz[bǗi/"hǗ[E$V`ˤ% Ȥi^# 'O &!R C%I ŕ]:]j@>3:C=)2 ݆ QA$R $H ` S-e@j# @P҈L*p㺨w9}ϵϔu,Mp*% evOfLcOWj΂4$;QpE)x^RvOߴՋEMbWTRbV D"#(9RCh&IXmcuAS_Z#t{TMj$Uŝ6"hʄ"!lVt˴Kݍ"2}c`P10IB(HԀyJ өo>BaJL w a(>~y"0[v= nXk#s!S9]Ͼ`:m{ա^/ea}[Fc"*uԑ([Uoxn:vUTI*A;̆5o7_ woҶɻ*Cf2*W/'3 JMSk[̄%EiEJtn7 @h0`(iJjF&jȑ2Ga@ * a:p=q:tKfzz ,K>}pÛp_&qG"Q?/LꙣD6J RՇi7%j?wwwUmDDMԹK^i'n^zSGJ*29j뮭zvphзaJ̪b_O K B&37flm♈!\t°!@IIRE.ز,",i$R!zY.z-,(h@JAz/_INwx|8|sL V һ'B`"v[ˊ+ @P]e/@ ѻA?3{WWnPf(*PǧophŝȖ +]@vSA(ҴL}.<9!'H8ݶ,  Ddv  [ҲA3CM 15,_(IgXB$ZSޮznLۗIړ@L BDW96xj"HԵmpz*_cݏB& wI\pv}+;;Bf&}, ' u Tpܦ:Uw_=#ʹ^ĬHϔ:TWLchqO'Op-R*E$-<SyBm|2{"#( g&m ەEs7|Y&KarvuYׯz*+DbLpgK+FbȺCW> X+#lboCz%av|Qjh+;u|;}sWspz(ҥ6idk| M[qut1U/pp /fұ n$ J i N%V,F[ Ld:1)Q'#N?\.#^-o[y|(>y/mPuք*5KȈ8(3^>ذwZJÊ̮PE4# kcW㒗?.Oqi_Et%: :ӓL 3#tcjW[<)x G,R-ҴY<ݭ_IN9JwTq–ɻցLxR[8&\)SW,U=ۄmDZԥ*(BLi= Q=D CT[v]a?ζm ֯o7Lˀf6R4(PQaxEׅM1GF͑BtR=9&JǵS{*S=`c+bdPA)2f.HϤp( |Bb0,H)u|)/3"L-t$4p:˭O/II`n]2>(#UF)['.t L B5AC%bT]2ͱcصa*=32٘֔"N P r7IbԍD"#ch$<#_ԫ̭u&ֹU=cs$CmjqK W̾ZwO`zU@` P!QJ^0!t>R(A\BS*7~~F,\?|~?_=J\ꢀB7c0V辊q '+\`CPl&3sIkZ$Mt`J[y{+ *b JP5=Gx%D̑7] F1550`db8aA(ma@,KM1ތO>jV, `QI$b _`Ag$$"yaD؃媇UvU'rA2&)ٹ\/uwoև%p9L<L~_oH0Z 9bo|OD|BCDId2[vi J&; Nb o,#Y)J@dܞ_A Xf:oX$T]Nσ\uӹo:/r -ႤGmPF4#3)ė3No>;+ן?T@8hE\g?W3vRO#]=,]:9H¬.XG#S blnUSd$XGz@@5@Hu#f ,esZ- O$*%/a"B4AfcuLW%|EwZ>ݵ๷R br%{uT";fbM< Ob9{q/bM<2tn݊ SھR&W Tn;qjoص2WǨ&2Ė"q(],bϧGB5."/QU<́=fx- M{d(!=-OY$PJcc%Hkm7<([sM>=~o߼{u+P9&<=c}kH2U#%:$4ۖ%$˞zH#kJO%46M yHEedÐKJ9pIbݎw)`! l $dJQ7)"΀ cVH`6a\[ Ѭp)AG)kta@ C5K$"xXA +\CF b?}Twu_ׯ>{?Dx"';HN5Z1!@[MHxoװ?M?kyY0R*qKk/[KV< +Kp]UU"CC8`б宨An@2={!pKA@ml=TMeH*N)͇n;磊+)[z6PL"=ÐA,-Mn!p1F8SŽ(g~<]t%DiELF0CAd$>$SD!oCIĮJoҜyg| WQ+MI"$Uc@D̫b>8_F41GM2|^,\vMt1YB3KF7 D / yg HAq# 4/Hf j!h4) n_&HbAf_\P0y$njk=bzn{os[zvlބ/GhJGه9O|_Z:iaQ*<xSP~Wsl^"` ("l:7 _”L=^_/Wa翅~lNl- L Gs),\D(3 !Vٞ'NiT4 `2&P[zb|&f( %)1$ũd@y(?gSX/3Dh1SܥeQ]zHq%43 7e`L=&"*_x_;鞆eڡ#1`:9d$Ui)#"ePPL`@(sexXθ\?6xkH%6\}^_]W쾿;X5{jժ q[kN#P$L2ҠM=! `20&ly)}IaPzgK186PzF ײ@U<,VfĄN' *p AxK}^١CǍoƸ<~3V̮UKCA9T2ρl{_5}f5͵!@8t/:Jn)ң౯k7S6#*VA2"-n "`{9 U'fg7_.2O2#}8+Uvj.`݀tɞR57v0[]tV;'c3KEː¯[z(:Ҟry朜|>'=ߝ2­] Q!"XWo o!pb&6c!w JHɄB<3l]lpDRB&HF@2r(+K E4)DK4-@ENɼb?G[ūIx-<{߽=<e=E2IGcJgMtaDЧg/{|Nxܡ #3{mj/QU&y~RL8 n6T3)LFOP'F26<#4vpA  ]8"Lr.*)ݾ$WЁbJhQ$!F`"K%Q~'\>l Zptyy>|W;u"wA%9T]ע" ФnHu/Qncm7_l^y_G \,hMt"]8,Dc*\?vc-FVq799iP)'~(z<;t~:w~;0W]3##qq_GZSL-dn$ش>a "yGV̤>  Kg򋁅J#Rm;! C\Z; ҉/! 4b)59hK=["揿vд2e죎{=B n?q/$ L?Jl29~5%F7Aa6y=uXk=Z^b Ʉl`@S膭_Pƨ>%4 GB%`2E@ 1F@(5 9Ip=96oF%/v};uct ޙq kaJ-&"+^rKoDYphy?ɈlEm)~h:@tf/"ȺT>o*@T2l&+  cKwwj,% l4-bd"T 3a 5BC/\2m3Hwn3*NK%{LXbPQ)?~:SM抆h- zY,Wڲ^\N.S3 @t*:*;kݝ6(/6c39֌m)c[øZ|ֆN Ňt7蘄6:^aZ>m-Bj_Z,w@YKvIq(X0``U(chDe͹ နQ3KUR!]]ͺ2\TH4+MVllNꪲΨcoErab't^WdWuT$.~ͧXϏT:7Z|ݔ!wiS!CT|r$dm@wyVh'=Z$a@n".++*|\orj^mU,hAg-N-wVs'|L\i,pXt =CV63RvhB4+z-Jz*LLQlxKlb(BB d W]sw'SaF5@&*!",Mvvtl3遍5ǟ`W#i9 @0JbܞId|ޔp~ӻy"5դ\B"6&Q&]KKѬ9!Tppn@FD)4qvDV Y"2&"Y֣T s'I!-MdSk_Qcep2y2t&V a,S@no{YO1vtT4f]7IǦ'Qpj")4iMDC>_q{7WV*Hd>/tXB9騒znحXT;-:laiϱj|1[mds>5$%1t3rX]\j @v^ݷ ^(C=K׮T3r}-m˹vxLmDFp' hdQvZk[#37Tc7=dQ 6 }+eFH#7/(8~yڧmJD"Esd``vJ737$ |uAV*Mͩkq- i26'& nR!*5|WPn_:xdGnJdm_Nw?xědHtZBH~Z1|t#3#!sWZ-jᓭHP$7%T)"Ј$MGXp]x޹8A8"3ٝ]ȼ)ΌU$^ ?KۮD|q8zxnvԧT}ќc쌔o1FR'e#Tʹ6\kâZ-E- s4{/!#ghcZ1@ɔ>; io?z܎חaT4@;#{u(Kf~h7,P,8f0Qf 9\/şdm?_Jvfc}2+Tn*:qmLyxD` ,b@C< 7 'Z% iC@"0U'MU }R(ن}㗳7>_^[PC\Br 0D=7HviH=#eKy@#nG掶[|rU)KtbK 2~ݹhxUѭT@Nq:Q0BWsa@vv*ɽ>D_.l]|4e [5]#PT191d6| V,ULQ:eo {{0mbxWTDۧTӜ㆏[F>R♦+l63Afi/wg?/&0B#=)| kW0 [JZ7TǶo?O}ǣ^N ĭrD|l5ܐFc jhvàP,86EL"+.A wHSsaI(*4.yN#mm䆓-p/)E9DjJJ{O_KOw|{{}4ƊL1D*8vΉgmޟ4 1AdYɗ+,޾̳1牽/E5/Y4/o=6v:.΢3Z4Bs@sA $6*P`G6aH ÞDee4]*&{Dm\Y @/j#l|R| (?W,Td{$Fs¢ш@hFWnW۳l|5t9@eJE/(Vk۪&=.nHhh Z > ap6On"H4kY5S^nyiZjU5K6M[MD1~xW!P[*e>4"Ka56˓x޽ VS9d$V*DxaCp](8*7u#c'`c!'t-GgyHwҗiC-gtZ>m-`RHiXOGT0+UFZ,6cVTmҰCJ4=5@.VqM}6\,sn_m|vp c9.:k0X֘g#!lFfC" +>6.:ӯ6e,NI44 U6id5L 0DĨntOd~UH*m5kq ZFZep/ôLǿDZ$IENDB`scikit-image-0.9.3/skimage/draw/000077500000000000000000000000001223313777300164565ustar00rootroot00000000000000scikit-image-0.9.3/skimage/draw/__init__.py000066400000000000000000000010761223313777300205730ustar00rootroot00000000000000from .draw import circle, ellipse, set_color from .draw3d import ellipsoid, ellipsoid_stats from ._draw import (line, line_aa, polygon, ellipse_perimeter, circle_perimeter, circle_perimeter_aa, _bezier_segment, bezier_curve) __all__ = ['line', 'line_aa', 'bezier_curve', 'polygon', 'ellipse', 'ellipse_perimeter', 'ellipsoid', 'ellipsoid_stats', 'circle', 'circle_perimeter', 'circle_perimeter_aa', 'set_color'] scikit-image-0.9.3/skimage/draw/_draw.pyx000066400000000000000000000613111223313777300203160ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import math import numpy as np cimport numpy as cnp from libc.math cimport sqrt, sin, cos, floor, ceil from skimage._shared.geometry cimport point_in_polygon def line(Py_ssize_t y, Py_ssize_t x, Py_ssize_t y2, Py_ssize_t x2): """Generate line pixel coordinates. Parameters ---------- y, x : int Starting position (row, column). y2, x2 : int End position (row, column). Returns ------- rr, cc : (N,) ndarray of int Indices of pixels that belong to the line. May be used to directly index into an array, e.g. ``img[rr, cc] = 1``. Notes ----- Anti-aliased line generator is available with `line_aa`. Examples -------- >>> from skimage.draw import line >>> img = np.zeros((10, 10), dtype=np.uint8) >>> rr, cc = line(1, 1, 8, 8) >>> img[rr, cc] = 1 >>> img array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) """ cdef char steep = 0 cdef Py_ssize_t dx = abs(x2 - x) cdef Py_ssize_t dy = abs(y2 - y) cdef Py_ssize_t sx, sy, d, i if (x2 - x) > 0: sx = 1 else: sx = -1 if (y2 - y) > 0: sy = 1 else: sy = -1 if dy > dx: steep = 1 x, y = y, x dx, dy = dy, dx sx, sy = sy, sx d = (2 * dy) - dx cdef Py_ssize_t[::1] rr = np.zeros(int(dx) + 1, dtype=np.intp) cdef Py_ssize_t[::1] cc = np.zeros(int(dx) + 1, dtype=np.intp) for i in range(dx): if steep: rr[i] = x cc[i] = y else: rr[i] = y cc[i] = x while d >= 0: y = y + sy d = d - (2 * dx) x = x + sx d = d + (2 * dy) rr[dx] = y2 cc[dx] = x2 return np.asarray(rr), np.asarray(cc) def line_aa(Py_ssize_t y1, Py_ssize_t x1, Py_ssize_t y2, Py_ssize_t x2): """Generate anti-aliased line pixel coordinates. Parameters ---------- y1, x1 : int Starting position (row, column). y2, x2 : int End position (row, column). Returns ------- rr, cc, val : (N,) ndarray (int, int, float) Indices of pixels (`rr`, `cc`) and intensity values (`val`). ``img[rr, cc] = val``. References ---------- .. [1] A Rasterizing Algorithm for Drawing Curves, A. Zingl, 2012 http://members.chello.at/easyfilter/Bresenham.pdf Examples -------- >>> from skimage.draw import line_aa >>> img = np.zeros((10, 10), dtype=np.uint8) >>> rr, cc, val = line_aa(1, 1, 8, 8) >>> img[rr, cc] = val * 255 >>> img array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 255, 56, 0, 0, 0, 0, 0, 0, 0], [ 0, 56, 255, 56, 0, 0, 0, 0, 0, 0], [ 0, 0, 56, 255, 56, 0, 0, 0, 0, 0], [ 0, 0, 0, 56, 255, 56, 0, 0, 0, 0], [ 0, 0, 0, 0, 56, 255, 56, 0, 0, 0], [ 0, 0, 0, 0, 0, 56, 255, 56, 0, 0], [ 0, 0, 0, 0, 0, 0, 56, 255, 56, 0], [ 0, 0, 0, 0, 0, 0, 0, 56, 255, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) """ cdef list rr = list() cdef list cc = list() cdef list val = list() cdef int dx = abs(x1 - x2) cdef int dy = abs(y1 - y2) cdef int err = dx - dy cdef int x, y, e, ed, sign_x, sign_y if x1 < x2: sign_x = 1 else: sign_x = -1 if y1 < y2: sign_y = 1 else: sign_y = -1 if dx + dy == 0: ed = 1 else: ed = (sqrt(dx*dx + dy*dy)) x, y = x1, y1 while True: cc.append(x) rr.append(y) val.append(1. * abs(err - dx + dy) / (ed)) e = err if 2 * e >= -dx: if x == x2: break if e + dy < ed: cc.append(x) rr.append(y + sign_y) val.append(1. * abs(e + dy) / (ed)) err -= dy x += sign_x if 2 * e <= dy: if y == y2: break if dx - e < ed: cc.append(x) rr.append(y) val.append(abs(dx - e) / (ed)) err += dx y += sign_y return (np.array(rr, dtype=np.intp), np.array(cc, dtype=np.intp), 1. - np.array(val, dtype=np.float)) def polygon(y, x, shape=None): """Generate coordinates of pixels within polygon. Parameters ---------- y : (N,) ndarray Y-coordinates of vertices of polygon. x : (N,) ndarray X-coordinates of vertices of polygon. shape : tuple, optional Image shape which is used to determine maximum extents of output pixel coordinates. This is useful for polygons which exceed the image size. By default the full extents of the polygon are used. Returns ------- rr, cc : ndarray of int Pixel coordinates of polygon. May be used to directly index into an array, e.g. ``img[rr, cc] = 1``. Examples -------- >>> from skimage.draw import polygon >>> img = np.zeros((10, 10), dtype=np.uint8) >>> x = np.array([1, 7, 4, 1]) >>> y = np.array([1, 2, 8, 1]) >>> rr, cc = polygon(y, x) >>> img[rr, cc] = 1 >>> img array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) """ cdef Py_ssize_t nr_verts = x.shape[0] cdef Py_ssize_t minr = int(max(0, y.min())) cdef Py_ssize_t maxr = int(ceil(y.max())) cdef Py_ssize_t minc = int(max(0, x.min())) cdef Py_ssize_t maxc = int(ceil(x.max())) # make sure output coordinates do not exceed image size if shape is not None: maxr = min(shape[0] - 1, maxr) maxc = min(shape[1] - 1, maxc) cdef Py_ssize_t r, c # make contigous arrays for r, c coordinates cdef cnp.ndarray contiguous_rdata, contiguous_cdata contiguous_rdata = np.ascontiguousarray(y, dtype=np.double) contiguous_cdata = np.ascontiguousarray(x, dtype=np.double) cdef cnp.double_t* rptr = contiguous_rdata.data cdef cnp.double_t* cptr = contiguous_cdata.data # output coordinate arrays cdef list rr = list() cdef list cc = list() for r in range(minr, maxr+1): for c in range(minc, maxc+1): if point_in_polygon(nr_verts, cptr, rptr, c, r): rr.append(r) cc.append(c) return np.array(rr, dtype=np.intp), np.array(cc, dtype=np.intp) def circle_perimeter(Py_ssize_t cy, Py_ssize_t cx, Py_ssize_t radius, method='bresenham'): """Generate circle perimeter coordinates. Parameters ---------- cy, cx : int Centre coordinate of circle. radius: int Radius of circle. method : {'bresenham', 'andres'}, optional bresenham : Bresenham method (default) andres : Andres method Returns ------- rr, cc : (N,) ndarray of int Bresenham and Andres' method: Indices of pixels that belong to the circle perimeter. May be used to directly index into an array, e.g. ``img[rr, cc] = 1``. Notes ----- Andres method presents the advantage that concentric circles create a disc whereas Bresenham can make holes. There is also less distortions when Andres circles are rotated. Bresenham method is also known as midpoint circle algorithm. Anti-aliased circle generator is available with `circle_perimeter_aa`. References ---------- .. [1] J.E. Bresenham, "Algorithm for computer control of a digital plotter", IBM Systems journal, 4 (1965) 25-30. .. [2] E. Andres, "Discrete circles, rings and spheres", Computers & Graphics, 18 (1994) 695-706. Examples -------- >>> from skimage.draw import circle_perimeter >>> img = np.zeros((10, 10), dtype=np.uint8) >>> rr, cc = circle_perimeter(4, 4, 3) >>> img[rr, cc] = 1 >>> img array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) """ cdef list rr = list() cdef list cc = list() cdef Py_ssize_t x = 0 cdef Py_ssize_t y = radius cdef Py_ssize_t d = 0 cdef double dceil = 0 cdef double dceil_prev = 0 cdef char cmethod if method == 'bresenham': d = 3 - 2 * radius cmethod = 'b' elif method == 'andres': d = radius - 1 cmethod = 'a' else: raise ValueError('Wrong method') while y >= x: rr.extend([y, -y, y, -y, x, -x, x, -x]) cc.extend([x, x, -x, -x, y, y, -y, -y]) if cmethod == 'b': if d < 0: d += 4 * x + 6 else: d += 4 * (x - y) + 10 y -= 1 x += 1 elif cmethod == 'a': if d >= 2 * (x - 1): d = d - 2 * x x = x + 1 elif d <= 2 * (radius - y): d = d + 2 * y - 1 y = y - 1 else: d = d + 2 * (y - x - 1) y = y - 1 x = x + 1 return (np.array(rr, dtype=np.intp) + cy, np.array(cc, dtype=np.intp) + cx) def circle_perimeter_aa(Py_ssize_t cy, Py_ssize_t cx, Py_ssize_t radius): """Generate anti-aliased circle perimeter coordinates. Parameters ---------- cy, cx : int Centre coordinate of circle. radius: int Radius of circle. Returns ------- rr, cc, val : (N,) ndarray (int, int, float) Indices of pixels (`rr`, `cc`) and intensity values (`val`). ``img[rr, cc] = val``. Notes ----- Wu's method draws anti-aliased circle. This implementation doesn't use lookup table optimization. References ---------- .. [1] X. Wu, "An efficient antialiasing technique", In ACM SIGGRAPH Computer Graphics, 25 (1991) 143-152. Examples -------- >>> from skimage.draw import circle_perimeter_aa >>> img = np.zeros((10, 10), dtype=np.uint8) >>> rr, cc, val = circle_perimeter_aa(4, 4, 3) >>> img[rr, cc] = val * 255 >>> img array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 60, 211, 255, 211, 60, 0, 0, 0], [ 0, 60, 194, 43, 0, 43, 194, 60, 0, 0], [ 0, 211, 43, 0, 0, 0, 43, 211, 0, 0], [ 0, 255, 0, 0, 0, 0, 0, 255, 0, 0], [ 0, 211, 43, 0, 0, 0, 43, 211, 0, 0], [ 0, 60, 194, 43, 0, 43, 194, 60, 0, 0], [ 0, 0, 60, 211, 255, 211, 60, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) """ cdef Py_ssize_t x = 0 cdef Py_ssize_t y = radius cdef Py_ssize_t d = 0 cdef double dceil = 0 cdef double dceil_prev = 0 cdef list rr = [y, x, y, x, -y, -x, -y, -x] cdef list cc = [x, y, -x, -y, x, y, -x, -y] cdef list val = [1] * 8 while y > x + 1: x += 1 dceil = sqrt(radius**2 - x**2) dceil = ceil(dceil) - dceil if dceil < dceil_prev: y -= 1 rr.extend([y, y - 1, x, x, y, y - 1, x, x]) cc.extend([x, x, y, y - 1, -x, -x, -y, 1 - y]) rr.extend([-y, 1 - y, -x, -x, -y, 1 - y, -x, -x]) cc.extend([x, x, y, y - 1, -x, -x, -y, 1 - y]) val.extend([1 - dceil, dceil] * 8) dceil_prev = dceil return (np.array(rr, dtype=np.intp) + cy, np.array(cc, dtype=np.intp) + cx, np.array(val, dtype=np.float)) def ellipse_perimeter(Py_ssize_t cy, Py_ssize_t cx, Py_ssize_t yradius, Py_ssize_t xradius, double orientation=0): """Generate ellipse perimeter coordinates. Parameters ---------- cy, cx : int Centre coordinate of ellipse. yradius, xradius : int Minor and major semi-axes. ``(x/xradius)**2 + (y/yradius)**2 = 1``. orientation : double, optional (default 0) Major axis orientation in clockwise direction as radians. Returns ------- rr, cc : (N,) ndarray of int Indices of pixels that belong to the ellipse perimeter. May be used to directly index into an array, e.g. ``img[rr, cc] = 1``. References ---------- .. [1] A Rasterizing Algorithm for Drawing Curves, A. Zingl, 2012 http://members.chello.at/easyfilter/Bresenham.pdf Examples -------- >>> from skimage.draw import ellipse_perimeter >>> img = np.zeros((10, 10), dtype=np.uint8) >>> rr, cc = ellipse_perimeter(5, 5, 3, 4) >>> img[rr, cc] = 1 >>> img array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 1], [0, 1, 0, 0, 0, 0, 0, 0, 0, 1], [0, 1, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) """ # If both radii == 0, return the center to avoid infinite loop in 2nd set if xradius == 0 and yradius == 0: return np.array(cy), np.array(cx) # Pixels cdef list px = list() cdef list py = list() # Compute useful values cdef Py_ssize_t xd = xradius**2 cdef Py_ssize_t yd = yradius**2 cdef Py_ssize_t x, y, e2, err cdef int ix0, ix1, iy0, iy1, ixd, iyd cdef double sin_angle, xa, ya, za, a, b if orientation == 0: x = -xradius y = 0 e2 = yd err = x*(2 * e2 + x) + e2 while x <= 0: # Quadrant 1 px.append(cx - x) py.append(cy + y) # Quadrant 2 px.append(cx + x) py.append(cy + y) # Quadrant 3 px.append(cx + x) py.append(cy - y) # Quadrant 4 px.append(cx - x) py.append(cy - y) # Adjust x and y e2 = 2 * err if e2 >= (2 * x + 1) * yd: x += 1 err += (2 * x + 1) * yd if e2 <= (2 * y + 1) * xd: y += 1 err += (2 * y + 1) * xd while y < yradius: y += 1 px.append(cx) py.append(cy + y) px.append(cx) py.append(cy - y) else: sin_angle = sin(orientation) za = (xd - yd) * sin_angle xa = sqrt(xd - za * sin_angle) ya = sqrt(yd + za * sin_angle) a = xa + 0.5 b = ya + 0.5 za = za * a * b / (xa * ya) ix0 = int(cx - a) iy0 = int(cy - b) ix1 = int(cx + a) iy1 = int(cy + b) xa = ix1 - ix0 ya = iy1 - iy0 za = 4 * za * cos(orientation) w = xa * ya if w != 0: w = (w - za) / (w + w) ixd = int(floor(xa * w + 0.5)) iyd = int(floor(ya * w + 0.5)) # Draw the 4 quadrants rr, cc = _bezier_segment(iy0 + iyd, ix0, iy0, ix0, iy0, ix0 + ixd, 1-w) py.extend(rr) px.extend(cc) rr, cc = _bezier_segment(iy0 + iyd, ix0, iy1, ix0, iy1, ix1 - ixd, w) py.extend(rr) px.extend(cc) rr, cc = _bezier_segment(iy1 - iyd, ix1, iy1, ix1, iy1, ix1 - ixd, 1-w) py.extend(rr) px.extend(cc) rr, cc = _bezier_segment(iy1 - iyd, ix1, iy0, ix1, iy0, ix0 + ixd, w) py.extend(rr) px.extend(cc) return np.array(py, dtype=np.intp), np.array(px, dtype=np.intp) def _bezier_segment(Py_ssize_t y0, Py_ssize_t x0, Py_ssize_t y1, Py_ssize_t x1, Py_ssize_t y2, Py_ssize_t x2, double weight): """Generate Bezier segment coordinates. Parameters ---------- y0, x0 : int Coordinates of the first control point. y1, x1 : int Coordinates of the middle control point. y2, x2 : int Coordinates of the last control point. weight : double Middle control point weight, it describes the line tension. Returns ------- rr, cc : (N,) ndarray of int Indices of pixels that belong to the Bezier curve. May be used to directly index into an array, e.g. ``img[rr, cc] = 1``. Notes ----- The algorithm is the rational quadratic algorithm presented in reference [1]_. References ---------- .. [1] A Rasterizing Algorithm for Drawing Curves, A. Zingl, 2012 http://members.chello.at/easyfilter/Bresenham.pdf """ # Pixels cdef list px = list() cdef list py = list() # Steps cdef double sx = x2 - x1 cdef double sy = y2 - y1 cdef double dx = x0 - x2 cdef double dy = y0 - y2 cdef double xx = x0 - x1 cdef double yy = y0 - y1 cdef double xy = xx * sy + yy * sx cdef double cur = xx * sy - yy * sx cdef double err cdef bint test1, test2 # if it's not a straight line if cur != 0 and weight > 0: if (sx * sx + sy * sy > xx * xx + yy * yy): # Swap point 0 and point 2 # to start from the longer part x2 = x0 x0 -= (dx) y2 = y0 y0 -= (dy) cur = -cur xx = 2 * (4 * weight * sx * xx + dx * dx) yy = 2 * (4 * weight * sy * yy + dy * dy) # Set steps if x0 < x2: sx = 1 else: sx = -1 if y0 < y2: sy = 1 else: sy = -1 xy = -2 * sx * sy * (2 * weight * xy + dx * dy) if cur * sx * sy < 0: xx = -xx yy = -yy xy = -xy cur = -cur dx = 4 * weight * (x1 - x0) * sy * cur + xx / 2 + xy dy = 4 * weight * (y0 - y1) * sx * cur + yy / 2 + xy # Flat ellipse, algo fails if (weight < 0.5 and (dy > xy or dx < xy)): cur = (weight + 1) / 2 weight = sqrt(weight) xy = 1. / (weight + 1) # subdivide curve in half sx = floor((x0 + 2 * weight * x1 + x2) * xy * 0.5 + 0.5) sy = floor((y0 + 2 * weight * y1 + y2) * xy * 0.5 + 0.5) dx = floor((weight * x1 + x0) * xy + 0.5) dy = floor((y1 * weight + y0) * xy + 0.5) return _bezier_segment(y0, x0, (dy), (dx), (sy), (sx), cur) err = dx + dy - xy while dy <= xy and dx >= xy: px.append(x0) py.append(y0) if x0 == x2 and y0 == y2: # The job is done! return np.array(py, dtype=np.intp), np.array(px, dtype=np.intp) # Save boolean values test1 = 2 * err > dy test2 = 2 * (err + yy) < -dy # Move (x0,y0) to the next position if 2 * err < dx or test2: y0 += (sy) dy += xy dx += xx err += dx if 2 * err > dx or test1: x0 += (sx) dx += xy dy += yy err += dy # Plot line rr, cc = line(x0, y0, x2, y2) px.extend(rr) py.extend(cc) return np.array(py, dtype=np.intp), np.array(px, dtype=np.intp) def bezier_curve(Py_ssize_t y0, Py_ssize_t x0, Py_ssize_t y1, Py_ssize_t x1, Py_ssize_t y2, Py_ssize_t x2, double weight): """Generate Bezier curve coordinates. Parameters ---------- y0, x0 : int Coordinates of the first control point. y1, x1 : int Coordinates of the middle control point. y2, x2 : int Coordinates of the last control point. weight : double Middle control point weight, it describes the line tension. Returns ------- rr, cc : (N,) ndarray of int Indices of pixels that belong to the Bezier curve. May be used to directly index into an array, e.g. ``img[rr, cc] = 1``. Notes ----- The algorithm is the rational quadratic algorithm presented in reference [1]_. References ---------- .. [1] A Rasterizing Algorithm for Drawing Curves, A. Zingl, 2012 http://members.chello.at/easyfilter/Bresenham.pdf Examples -------- >>> import numpy as np >>> from skimage.draw import bezier_curve >>> img = np.zeros((10, 10), dtype=np.uint8) >>> rr, cc = bezier_curve(1, 5, 5, -2, 8, 8, 2) >>> img[rr, cc] = 1 >>> img array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) """ # Pixels cdef list px = list() cdef list py = list() cdef int x, y cdef double xx, yy, ww, t, q x = x0 - 2 * x1 + x2 y = y0 - 2 * y1 + y2 xx = x0 - x1 yy = y0 - y1 if xx * (x2 - x1) > 0: if yy * (y2 - y1): if abs(xx * y) > abs(yy * x): x0 = x2 x2 = (xx + x1) y0 = y2 y2 = (yy + y1) if (x0 == x2) or (weight == 1.): t = (x0 - x1) / x else: q = sqrt(4. * weight * weight * (x0 - x1) * (x2 - x1) + (x2 - x0) * floor(x2 - x0)) if (x1 < x0): q = -q t = (2. * weight * (x0 - x1) - x0 + x2 + q) / (2. * (1. - weight) * (x2 - x0)) q = 1. / (2. * t * (1. - t) * (weight - 1.) + 1.0) xx = (t * t * (x0 - 2. * weight * x1 + x2) + 2. * t * (weight * x1 - x0) + x0) * q yy = (t * t * (y0 - 2. * weight * y1 + y2) + 2. * t * (weight * y1 - y0) + y0) * q ww = t * (weight - 1.) + 1. ww *= ww * q weight = ((1. - t) * (weight - 1.) + 1.) * sqrt(q) x = (xx + 0.5) y = (yy + 0.5) yy = (xx - x0) * (y1 - y0) / (x1 - x0) + y0 rr, cc = _bezier_segment(y0, x0, (yy + 0.5), x, y, x, ww) px.extend(rr) py.extend(cc) yy = (xx - x2) * (y1 - y2) / (x1 - x2) + y2 y1 = (yy + 0.5) x0 = x1 = x y0 = y if (y0 - y1) * floor(y2 - y1) > 0: if (y0 == y2) or (weight == 1): t = (y0 - y1) / (y0 - 2. * y1 + y2) else: q = sqrt(4. * weight * weight * (y0 - y1) * (y2 - y1) + (y2 - y0) * floor(y2 - y0)) if y1 < y0: q = -q t = (2. * weight * (y0 - y1) - y0 + y2 + q) / (2. * (1. - weight) * (y2 - y0)) q = 1. / (2. * t * (1. - t) * (weight - 1.) + 1.) xx = (t * t * (x0 - 2. * weight * x1 + x2) + 2. * t * (weight * x1 - x0) + x0) * q yy = (t * t * (y0 - 2. * weight * y1 + y2) + 2. * t * (weight * y1 - y0) + y0) * q ww = t * (weight - 1.) + 1. ww *= ww * q weight = ((1. - t) * (weight - 1.) + 1.) * sqrt(q) x = (xx + 0.5) y = (yy + 0.5) xx = (x1 - x0) * (yy - y0) / (y1 - y0) + x0 rr, cc = _bezier_segment(y0, x0, y, (xx + 0.5), y, x, ww) px.extend(rr) py.extend(cc) xx = (x1 - x2) * (yy - y2) / (y1 - y2) + x2 x1 = (xx + 0.5) x0 = x y0 = y1 = y rr, cc = _bezier_segment(y0, x0, y1, x1, y2, x2, weight * weight) px.extend(rr) py.extend(cc) return np.array(px, dtype=np.intp), np.array(py, dtype=np.intp) scikit-image-0.9.3/skimage/draw/draw.py000066400000000000000000000107131223313777300177670ustar00rootroot00000000000000# coding: utf-8 import numpy as np def _coords_inside_image(rr, cc, shape): mask = (rr >= 0) & (rr < shape[0]) & (cc >= 0) & (cc < shape[1]) return rr[mask], cc[mask] def ellipse(cy, cx, yradius, xradius, shape=None): """Generate coordinates of pixels within ellipse. Parameters ---------- cy, cx : double Centre coordinate of ellipse. yradius, xradius : double Minor and major semi-axes. ``(x/xradius)**2 + (y/yradius)**2 = 1``. shape : tuple, optional Image shape which is used to determine maximum extents of output pixel coordinates. This is useful for ellipses which exceed the image size. By default the full extents of the ellipse are used. Returns ------- rr, cc : ndarray of int Pixel coordinates of ellipse. May be used to directly index into an array, e.g. ``img[rr, cc] = 1``. Examples -------- >>> from skimage.draw import ellipse >>> img = np.zeros((10, 10), dtype=np.uint8) >>> rr, cc = ellipse(5, 5, 3, 4) >>> img[rr, cc] = 1 >>> img array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) """ dr = 1 / float(yradius) dc = 1 / float(xradius) r, c = np.ogrid[-1:1:dr, -1:1:dc] rr, cc = np.nonzero(r ** 2 + c ** 2 < 1) rr.flags.writeable = True cc.flags.writeable = True rr += cy - yradius cc += cx - xradius if shape is not None: _coords_inside_image(rr, cc, shape) return rr, cc def circle(cy, cx, radius, shape=None): """Generate coordinates of pixels within circle. Parameters ---------- cy, cx : double Centre coordinate of circle. radius: double Radius of circle. shape : tuple, optional Image shape which is used to determine maximum extents of output pixel coordinates. This is useful for circles which exceed the image size. By default the full extents of the circle are used. Returns ------- rr, cc : ndarray of int Pixel coordinates of circle. May be used to directly index into an array, e.g. ``img[rr, cc] = 1``. Notes ----- This function is a wrapper for skimage.draw.ellipse() Examples -------- >>> from skimage.draw import circle >>> img = np.zeros((10, 10), dtype=np.uint8) >>> rr, cc = circle(4, 4, 5) >>> img[rr, cc] = 1 >>> img array([[0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) """ return ellipse(cy, cx, radius, radius, shape) def set_color(img, coords, color): """Set pixel color in the image at the given coordinates. Coordinates that exceed the shape of the image will be ignored. Parameters ---------- img : (M, N, D) ndarray Image coords : ((P,) ndarray, (P,) ndarray) Coordinates of pixels to be colored. color : (D,) ndarray Color to be assigned to coordinates in the image. Returns ------- img : (M, N, D) ndarray The updated image. Examples -------- >>> from skimage.draw import line, set_color >>> img = np.zeros((10, 10), dtype=np.uint8) >>> rr, cc = line(1, 1, 20, 20) >>> set_color(img, (rr, cc), 1) >>> img array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]], dtype=uint8) """ rr, cc = coords rr, cc = _coords_inside_image(rr, cc, img.shape) img[rr, cc] = color scikit-image-0.9.3/skimage/draw/draw3d.py000066400000000000000000000066071223313777300202250ustar00rootroot00000000000000# coding: utf-8 import numpy as np from scipy.special import (ellipkinc as ellip_F, ellipeinc as ellip_E) def ellipsoid(a, b, c, spacing=(1., 1., 1.), levelset=False): """ Generates ellipsoid with semimajor axes aligned with grid dimensions on grid with specified `spacing`. Parameters ---------- a : float Length of semimajor axis aligned with x-axis. b : float Length of semimajor axis aligned with y-axis. c : float Length of semimajor axis aligned with z-axis. spacing : tuple of floats, length 3 Spacing in (x, y, z) spatial dimensions. levelset : bool If True, returns the level set for this ellipsoid (signed level set about zero, with positive denoting interior) as np.float64. False returns a binarized version of said level set. Returns ------- ellip : (N, M, P) array Ellipsoid centered in a correctly sized array for given `spacing`. Boolean dtype unless `levelset=True`, in which case a float array is returned with the level set above 0.0 representing the ellipsoid. """ if (a <= 0) or (b <= 0) or (c <= 0): raise ValueError('Parameters a, b, and c must all be > 0') offset = np.r_[1, 1, 1] * np.r_[spacing] # Calculate limits, and ensure output volume is odd & symmetric low = np.ceil((- np.r_[a, b, c] - offset)) high = np.floor((np.r_[a, b, c] + offset + 1)) for dim in range(3): if (high[dim] - low[dim]) % 2 == 0: low[dim] -= 1 num = np.arange(low[dim], high[dim], spacing[dim]) if 0 not in num: low[dim] -= np.max(num[num < 0]) # Generate (anisotropic) spatial grid x, y, z = np.mgrid[low[0]:high[0]:spacing[0], low[1]:high[1]:spacing[1], low[2]:high[2]:spacing[2]] if not levelset: arr = ((x / float(a)) ** 2 + (y / float(b)) ** 2 + (z / float(c)) ** 2) <= 1 else: arr = ((x / float(a)) ** 2 + (y / float(b)) ** 2 + (z / float(c)) ** 2) - 1 return arr def ellipsoid_stats(a, b, c): """ Calculates analytical surface area and volume for ellipsoid with semimajor axes aligned with grid dimensions of specified `spacing`. Parameters ---------- a : float Length of semimajor axis aligned with x-axis. b : float Length of semimajor axis aligned with y-axis. c : float Length of semimajor axis aligned with z-axis. Returns ------- vol : float Calculated volume of ellipsoid. surf : float Calculated surface area of ellipsoid. """ if (a <= 0) or (b <= 0) or (c <= 0): raise ValueError('Parameters a, b, and c must all be > 0') # Calculate volume & surface area # Surface calculation requires a >= b >= c and a != c. abc = [a, b, c] abc.sort(reverse=True) a = abc[0] b = abc[1] c = abc[2] # Volume vol = 4 / 3. * np.pi * a * b * c # Analytical ellipsoid surface area phi = np.arcsin((1. - (c ** 2 / (a ** 2.))) ** 0.5) d = float((a ** 2 - c ** 2) ** 0.5) m = (a ** 2 * (b ** 2 - c ** 2) / float(b ** 2 * (a ** 2 - c ** 2))) F = ellip_F(phi, m) E = ellip_E(phi, m) surf = 2 * np.pi * (c ** 2 + b * c ** 2 / d * F + b * d * E) return vol, surf scikit-image-0.9.3/skimage/draw/setup.py000066400000000000000000000017321223313777300201730ustar00rootroot00000000000000#!/usr/bin/env python import os from skimage._build import cython base_path = os.path.abspath(os.path.dirname(__file__)) def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs config = Configuration('draw', parent_package, top_path) config.add_data_dir('tests') cython(['_draw.pyx'], working_path=base_path) config.add_extension('_draw', sources=['_draw.c'], include_dirs=[get_numpy_include_dirs(), '../_shared']) return config if __name__ == '__main__': from numpy.distutils.core import setup setup(maintainer='scikit-image developers', author='scikit-image developers', maintainer_email='scikit-image@googlegroups.com', description='Drawing', url='https://github.com/scikit-image/scikit-image', license='SciPy License (BSD Style)', **(configuration(top_path='').todict()) ) scikit-image-0.9.3/skimage/draw/tests/000077500000000000000000000000001223313777300176205ustar00rootroot00000000000000scikit-image-0.9.3/skimage/draw/tests/test_draw.py000066400000000000000000000527051223313777300221770ustar00rootroot00000000000000from numpy.testing import assert_array_equal, assert_equal import numpy as np from skimage.draw import (set_color, line, line_aa, polygon, circle, circle_perimeter, circle_perimeter_aa, ellipse, ellipse_perimeter, _bezier_segment, bezier_curve) def test_set_color(): img = np.zeros((10, 10)) rr, cc = line(0, 0, 0, 30) set_color(img, (rr, cc), 1) img_ = np.zeros((10, 10)) img_[0, :] = 1 assert_array_equal(img, img_) def test_line_horizontal(): img = np.zeros((10, 10)) rr, cc = line(0, 0, 0, 9) img[rr, cc] = 1 img_ = np.zeros((10, 10)) img_[0, :] = 1 assert_array_equal(img, img_) def test_line_vertical(): img = np.zeros((10, 10)) rr, cc = line(0, 0, 9, 0) img[rr, cc] = 1 img_ = np.zeros((10, 10)) img_[:, 0] = 1 assert_array_equal(img, img_) def test_line_reverse(): img = np.zeros((10, 10)) rr, cc = line(0, 9, 0, 0) img[rr, cc] = 1 img_ = np.zeros((10, 10)) img_[0, :] = 1 assert_array_equal(img, img_) def test_line_diag(): img = np.zeros((5, 5)) rr, cc = line(0, 0, 4, 4) img[rr, cc] = 1 img_ = np.eye(5) assert_array_equal(img, img_) def test_line_aa_horizontal(): img = np.zeros((10, 10)) rr, cc, val = line_aa(0, 0, 0, 9) img[rr, cc] = val img_ = np.zeros((10, 10)) img_[0, :] = 1 assert_array_equal(img, img_) def test_line_aa_vertical(): img = np.zeros((10, 10)) rr, cc, val = line_aa(0, 0, 9, 0) img[rr, cc] = val img_ = np.zeros((10, 10)) img_[:, 0] = 1 assert_array_equal(img, img_) def test_line_aa_diagonal(): img = np.zeros((10, 10)) rr, cc, val = line_aa(0, 0, 9, 6) img[rr, cc] = 1 # Check that each pixel belonging to line, # also belongs to line_aa r, c = line(0, 0, 9, 6) for x, y in zip(r, c): assert_equal(img[r, c], 1) def test_polygon_rectangle(): img = np.zeros((10, 10), 'uint8') poly = np.array(((1, 1), (4, 1), (4, 4), (1, 4), (1, 1))) rr, cc = polygon(poly[:, 0], poly[:, 1]) img[rr, cc] = 1 img_ = np.zeros((10, 10)) img_[1:4, 1:4] = 1 assert_array_equal(img, img_) def test_polygon_rectangle_angular(): img = np.zeros((10, 10), 'uint8') poly = np.array(((0, 3), (4, 7), (7, 4), (3, 0), (0, 3))) rr, cc = polygon(poly[:, 0], poly[:, 1]) img[rr, cc] = 1 img_ = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] ) assert_array_equal(img, img_) def test_polygon_parallelogram(): img = np.zeros((10, 10), 'uint8') poly = np.array(((1, 1), (5, 1), (7, 6), (3, 6), (1, 1))) rr, cc = polygon(poly[:, 0], poly[:, 1]) img[rr, cc] = 1 img_ = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] ) assert_array_equal(img, img_) def test_polygon_exceed(): img = np.zeros((10, 10), 'uint8') poly = np.array(((1, -1), (100, -1), (100, 100), (1, 100), (1, 1))) rr, cc = polygon(poly[:, 0], poly[:, 1], img.shape) img[rr, cc] = 1 img_ = np.zeros((10, 10)) img_[1:, :] = 1 assert_array_equal(img, img_) def test_circle(): img = np.zeros((15, 15), 'uint8') rr, cc = circle(7, 7, 6) img[rr, cc] = 1 img_ = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] ) assert_array_equal(img, img_) def test_circle_perimeter_bresenham(): img = np.zeros((15, 15), 'uint8') rr, cc = circle_perimeter(7, 7, 0, method='bresenham') img[rr, cc] = 1 assert(np.sum(img) == 1) assert(img[7][7] == 1) img = np.zeros((17, 15), 'uint8') rr, cc = circle_perimeter(7, 7, 7, method='bresenham') img[rr, cc] = 1 img_ = np.array( [[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] ) assert_array_equal(img, img_) def test_circle_perimeter_andres(): img = np.zeros((15, 15), 'uint8') rr, cc = circle_perimeter(7, 7, 0, method='andres') img[rr, cc] = 1 assert(np.sum(img) == 1) assert(img[7][7] == 1) img = np.zeros((17, 15), 'uint8') rr, cc = circle_perimeter(7, 7, 7, method='andres') img[rr, cc] = 1 img_ = np.array( [[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0], [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] ) assert_array_equal(img, img_) def test_circle_perimeter_aa(): img = np.zeros((15, 15), 'uint8') rr, cc, val = circle_perimeter_aa(7, 7, 0) img[rr, cc] = 1 assert(np.sum(img) == 1) assert(img[7][7] == 1) img = np.zeros((17, 17), 'uint8') rr, cc, val = circle_perimeter_aa(8, 8, 7) img[rr, cc] = val * 255 img_ = np.array( [[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 82, 180, 236, 255, 236, 180, 82, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 189, 172, 74, 18, 0, 18, 74, 172, 189, 0, 0, 0, 0], [ 0, 0, 0, 229, 25, 0, 0, 0, 0, 0, 0, 0, 25, 229, 0, 0, 0], [ 0, 0, 189, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 189, 0, 0], [ 0, 82, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 82, 0], [ 0, 180, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 180, 0], [ 0, 236, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 236, 0], [ 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0], [ 0, 236, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 236, 0], [ 0, 180, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 180, 0], [ 0, 82, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 82, 0], [ 0, 0, 189, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 189, 0, 0], [ 0, 0, 0, 229, 25, 0, 0, 0, 0, 0, 0, 0, 25, 229, 0, 0, 0], [ 0, 0, 0, 0, 189, 172, 74, 18, 0, 18, 74, 172, 189, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 82, 180, 236, 255, 236, 180, 82, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] ) assert_array_equal(img, img_) def test_ellipse(): img = np.zeros((15, 15), 'uint8') rr, cc = ellipse(7, 7, 3, 7) img[rr, cc] = 1 img_ = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] ) assert_array_equal(img, img_) def test_ellipse_perimeter_dot_zeroangle(): # dot, angle == 0 img = np.zeros((30, 15), 'uint8') rr, cc = ellipse_perimeter(15, 7, 0, 0, 0) img[rr, cc] = 1 assert(np.sum(img) == 1) assert(img[15][7] == 1) def test_ellipse_perimeter_dot_nzeroangle(): # dot, angle != 0 img = np.zeros((30, 15), 'uint8') rr, cc = ellipse_perimeter(15, 7, 0, 0, 1) img[rr, cc] = 1 assert(np.sum(img) == 1) assert(img[15][7] == 1) def test_ellipse_perimeter_flat_zeroangle(): # flat ellipse img = np.zeros((20, 18), 'uint8') img_ = np.zeros((20, 18), 'uint8') rr, cc = ellipse_perimeter(6, 7, 0, 5, 0) img[rr, cc] = 1 rr, cc = line(6, 2, 6, 12) img_[rr, cc] = 1 assert_array_equal(img, img_) def test_ellipse_perimeter_zeroangle(): # angle == 0 img = np.zeros((30, 15), 'uint8') rr, cc = ellipse_perimeter(15, 7, 14, 6, 0) img[rr, cc] = 1 img_ = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0]] ) assert_array_equal(img, img_) def test_ellipse_perimeter_nzeroangle(): # angle != 0 img = np.zeros((30, 25), 'uint8') rr, cc = ellipse_perimeter(15, 11, 12, 6, 1.1) img[rr, cc] = 1 img_ = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] ) assert_array_equal(img, img_) def test_bezier_segment_straight(): image = np.zeros((200, 200), dtype=int) x0 = 50 y0 = 50 x1 = 150 y1 = 50 x2 = 150 y2 = 150 rr, cc = _bezier_segment(x0, y0, x1, y1, x2, y2, 0) image[rr, cc] = 1 image2 = np.zeros((200, 200), dtype=int) rr, cc = line(x0, y0, x2, y2) image2[rr, cc] = 1 assert_array_equal(image, image2) def test_bezier_segment_curved(): img = np.zeros((25, 25), 'uint8') x1, y1 = 20, 20 x2, y2 = 20, 2 x3, y3 = 2, 2 rr, cc = _bezier_segment(x1, y1, x2, y2, x3, y3, 1) img[rr, cc] = 1 img_ = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] ) assert_equal(img[x1, y1], 1) assert_equal(img[x3, y3], 1) assert_array_equal(img, img_) def test_bezier_curve_straight(): image = np.zeros((200, 200), dtype=int) x0 = 50 y0 = 50 x1 = 150 y1 = 50 x2 = 150 y2 = 150 rr, cc = bezier_curve(x0, y0, x1, y1, x2, y2, 0) image [rr, cc] = 1 image2 = np.zeros((200, 200), dtype=int) rr, cc = line(x0, y0, x2, y2) image2 [rr, cc] = 1 assert_array_equal(image, image2) def test_bezier_curved_weight_eq_1(): img = np.zeros((23, 8), 'uint8') x1, y1 = (1, 1) x2, y2 = (11, 11) x3, y3 = (21, 1) rr, cc = bezier_curve(x1, y1, x2, y2, x3, y3, 1) img[rr, cc] = 1 assert_equal(img[x1, y1], 1) assert_equal(img[x3, y3], 1) img_ = np.array( [[0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]] ) assert_equal(img, img_) def test_bezier_curved_weight_neq_1(): img = np.zeros((23, 10), 'uint8') x1, y1 = (1, 1) x2, y2 = (11, 11) x3, y3 = (21, 1) rr, cc = bezier_curve(x1, y1, x2, y2, x3, y3, 2) img[rr, cc] = 1 assert_equal(img[x1, y1], 1) assert_equal(img[x3, y3], 1) img_ = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] ) assert_equal(img, img_) if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/draw/tests/test_draw3d.py000066400000000000000000000100361223313777300224150ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal, assert_allclose from skimage.draw import ellipsoid, ellipsoid_stats def test_ellipsoid_bool(): test = ellipsoid(2, 2, 2)[1:-1, 1:-1, 1:-1] test_anisotropic = ellipsoid(2, 2, 4, spacing=(1., 1., 2.)) test_anisotropic = test_anisotropic[1:-1, 1:-1, 1:-1] expected = np.array([[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]], [[0, 0, 1, 0, 0], [0, 1, 1, 1, 0], [1, 1, 1, 1, 1], [0, 1, 1, 1, 0], [0, 0, 1, 0, 0]], [[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]]) assert_array_equal(test, expected.astype(bool)) assert_array_equal(test_anisotropic, expected.astype(bool)) def test_ellipsoid_levelset(): test = ellipsoid(2, 2, 2, levelset=True)[1:-1, 1:-1, 1:-1] test_anisotropic = ellipsoid(2, 2, 4, spacing=(1., 1., 2.), levelset=True) test_anisotropic = test_anisotropic[1:-1, 1:-1, 1:-1] expected = np.array([[[ 2. , 1.25, 1. , 1.25, 2. ], [ 1.25, 0.5 , 0.25, 0.5 , 1.25], [ 1. , 0.25, 0. , 0.25, 1. ], [ 1.25, 0.5 , 0.25, 0.5 , 1.25], [ 2. , 1.25, 1. , 1.25, 2. ]], [[ 1.25, 0.5 , 0.25, 0.5 , 1.25], [ 0.5 , -0.25, -0.5 , -0.25, 0.5 ], [ 0.25, -0.5 , -0.75, -0.5 , 0.25], [ 0.5 , -0.25, -0.5 , -0.25, 0.5 ], [ 1.25, 0.5 , 0.25, 0.5 , 1.25]], [[ 1. , 0.25, 0. , 0.25, 1. ], [ 0.25, -0.5 , -0.75, -0.5 , 0.25], [ 0. , -0.75, -1. , -0.75, 0. ], [ 0.25, -0.5 , -0.75, -0.5 , 0.25], [ 1. , 0.25, 0. , 0.25, 1. ]], [[ 1.25, 0.5 , 0.25, 0.5 , 1.25], [ 0.5 , -0.25, -0.5 , -0.25, 0.5 ], [ 0.25, -0.5 , -0.75, -0.5 , 0.25], [ 0.5 , -0.25, -0.5 , -0.25, 0.5 ], [ 1.25, 0.5 , 0.25, 0.5 , 1.25]], [[ 2. , 1.25, 1. , 1.25, 2. ], [ 1.25, 0.5 , 0.25, 0.5 , 1.25], [ 1. , 0.25, 0. , 0.25, 1. ], [ 1.25, 0.5 , 0.25, 0.5 , 1.25], [ 2. , 1.25, 1. , 1.25, 2. ]]]) assert_allclose(test, expected) assert_allclose(test_anisotropic, expected) def test_ellipsoid_stats(): # Test comparison values generated by Wolfram Alpha vol, surf = ellipsoid_stats(6, 10, 16) assert(round(1280 * np.pi, 4) == round(vol, 4)) assert(1383.28 == round(surf, 2)) # Test when a <= b <= c does not hold vol, surf = ellipsoid_stats(16, 6, 10) assert(round(1280 * np.pi, 4) == round(vol, 4)) assert(1383.28 == round(surf, 2)) # Larger test to ensure reliability over broad range vol, surf = ellipsoid_stats(17, 27, 169) assert(round(103428 * np.pi, 4) == round(vol, 4)) assert(37426.3 == round(surf, 1)) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/exposure/000077500000000000000000000000001223313777300173735ustar00rootroot00000000000000scikit-image-0.9.3/skimage/exposure/__init__.py000066400000000000000000000007571223313777300215150ustar00rootroot00000000000000from .exposure import histogram, equalize, equalize_hist, \ rescale_intensity, cumulative_distribution, \ adjust_gamma, adjust_sigmoid, adjust_log from ._adapthist import equalize_adapthist __all__ = ['histogram', 'equalize', 'equalize_hist', 'equalize_adapthist', 'rescale_intensity', 'cumulative_distribution', 'adjust_gamma', 'adjust_sigmoid', 'adjust_log'] scikit-image-0.9.3/skimage/exposure/_adapthist.py000066400000000000000000000256041223313777300220740ustar00rootroot00000000000000""" Adapted code from "Contrast Limited Adaptive Histogram Equalization" by Karel Zuiderveld , Graphics Gems IV, Academic Press, 1994. http://tog.acm.org/resources/GraphicsGems/gems.html#gemsvi The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code as your own and resell it. Using the code is permitted in any program, product, or library, non-commercial or commercial. Giving credit is not required, though is a nice gesture. The code comes as-is, and if there are any flaws or problems with any Gems code, nobody involved with Gems - authors, editors, publishers, or webmasters - are to be held responsible. Basically, don't be a jerk, and remember that anything free comes with no guarantee. """ import numpy as np import skimage from skimage import color from skimage.exposure import rescale_intensity from skimage.util import view_as_blocks MAX_REG_X = 16 # max. # contextual regions in x-direction */ MAX_REG_Y = 16 # max. # contextual regions in y-direction */ NR_OF_GREY = 16384 # number of grayscale levels to use in CLAHE algorithm def equalize_adapthist(image, ntiles_x=8, ntiles_y=8, clip_limit=0.01, nbins=256): """Contrast Limited Adaptive Histogram Equalization. Parameters ---------- image : array-like Input image. ntiles_x : int, optional Number of tile regions in the X direction. Ranges between 2 and 16. ntiles_y : int, optional Number of tile regions in the Y direction. Ranges between 2 and 16. clip_limit : float: optional Clipping limit, normalized between 0 and 1 (higher values give more contrast). nbins : int, optional Number of gray bins for histogram ("dynamic range"). Returns ------- out : ndarray Equalized image. Notes ----- * The algorithm relies on an image whose rows and columns are even multiples of the number of tiles, so the extra rows and columns are left at their original values, thus preserving the input image shape. * For color images, the following steps are performed: - The image is converted to LAB color space - The CLAHE algorithm is run on the L channel - The image is converted back to RGB space and returned * For RGBA images, the original alpha channel is removed. References ---------- .. [1] http://tog.acm.org/resources/GraphicsGems/gems.html#gemsvi .. [2] https://en.wikipedia.org/wiki/CLAHE#CLAHE """ args = [None, ntiles_x, ntiles_y, clip_limit * nbins, nbins] if image.ndim > 2: lab_img = color.rgb2lab(skimage.img_as_float(image)) l_chan = lab_img[:, :, 0] l_chan /= np.max(np.abs(l_chan)) l_chan = skimage.img_as_uint(l_chan) args[0] = rescale_intensity(l_chan, out_range=(0, NR_OF_GREY - 1)) new_l = _clahe(*args).astype(float) new_l = rescale_intensity(new_l, out_range=(0, 100)) lab_img[:new_l.shape[0], :new_l.shape[1], 0] = new_l image = color.lab2rgb(lab_img) image = rescale_intensity(image, out_range=(0, 1)) else: image = skimage.img_as_uint(image) args[0] = rescale_intensity(image, out_range=(0, NR_OF_GREY - 1)) out = _clahe(*args) image[:out.shape[0], :out.shape[1]] = out image = rescale_intensity(image) return image def _clahe(image, ntiles_x, ntiles_y, clip_limit, nbins=128): """Contrast Limited Adaptive Histogram Equalization. Parameters ---------- image : array-like Input image. ntiles_x : int, optional Number of tile regions in the X direction. Ranges between 2 and 16. ntiles_y : int, optional Number of tile regions in the Y direction. Ranges between 2 and 16. clip_limit : float, optional Normalized clipping limit (higher values give more contrast). nbins : int, optional Number of gray bins for histogram ("dynamic range"). Returns ------- out : ndarray Equalized image. The number of "effective" greylevels in the output image is set by `nbins`; selecting a small value (eg. 128) speeds up processing and still produce an output image of good quality. The output image will have the same minimum and maximum value as the input image. A clip limit smaller than 1 results in standard (non-contrast limited) AHE. """ ntiles_x = min(ntiles_x, MAX_REG_X) ntiles_y = min(ntiles_y, MAX_REG_Y) ntiles_y = max(ntiles_x, 2) ntiles_x = max(ntiles_y, 2) if clip_limit == 1.0: return image # is OK, immediately returns original image. map_array = np.zeros((ntiles_y, ntiles_x, nbins), dtype=int) y_res = image.shape[0] - image.shape[0] % ntiles_y x_res = image.shape[1] - image.shape[1] % ntiles_x image = image[: y_res, : x_res] x_size = image.shape[1] / ntiles_x # Actual size of contextual regions y_size = image.shape[0] / ntiles_y n_pixels = x_size * y_size if clip_limit > 0.0: # Calculate actual cliplimit clip_limit = int(clip_limit * (x_size * y_size) / nbins) if clip_limit < 1: clip_limit = 1 else: clip_limit = NR_OF_GREY # Large value, do not clip (AHE) bin_size = 1 + NR_OF_GREY / nbins aLUT = np.arange(NR_OF_GREY) aLUT /= bin_size img_blocks = view_as_blocks(image, (y_size, x_size)) # Calculate greylevel mappings for each contextual region for y in range(ntiles_y): for x in range(ntiles_x): sub_img = img_blocks[y, x] hist = aLUT[sub_img.ravel()] hist = np.bincount(hist) hist = np.append(hist, np.zeros(nbins - hist.size, dtype=int)) hist = clip_histogram(hist, clip_limit) hist = map_histogram(hist, 0, NR_OF_GREY - 1, n_pixels) map_array[y, x] = hist # Interpolate greylevel mappings to get CLAHE image ystart = 0 for y in range(ntiles_y + 1): xstart = 0 if y == 0: # special case: top row ystep = y_size / 2.0 yU = 0 yB = 0 elif y == ntiles_y: # special case: bottom row ystep = y_size / 2.0 yU = ntiles_y - 1 yB = yU else: # default values ystep = y_size yU = y - 1 yB = yB + 1 for x in range(ntiles_x + 1): if x == 0: # special case: left column xstep = x_size / 2.0 xL = 0 xR = 0 elif x == ntiles_x: # special case: right column xstep = x_size / 2.0 xL = ntiles_x - 1 xR = xL else: # default values xstep = x_size xL = x - 1 xR = xL + 1 mapLU = map_array[yU, xL] mapRU = map_array[yU, xR] mapLB = map_array[yB, xL] mapRB = map_array[yB, xR] xslice = np.arange(xstart, xstart + xstep) yslice = np.arange(ystart, ystart + ystep) interpolate(image, xslice, yslice, mapLU, mapRU, mapLB, mapRB, aLUT) xstart += xstep # set pointer on next matrix */ ystart += ystep return image def clip_histogram(hist, clip_limit): """Perform clipping of the histogram and redistribution of bins. The histogram is clipped and the number of excess pixels is counted. Afterwards the excess pixels are equally redistributed across the whole histogram (providing the bin count is smaller than the cliplimit). Parameters ---------- hist : ndarray Histogram array. clip_limit : int Maximum allowed bin count. Returns ------- hist : ndarray Clipped histogram. """ # calculate total number of excess pixels excess_mask = hist > clip_limit excess = hist[excess_mask] n_excess = excess.sum() - excess.size * clip_limit # Second part: clip histogram and redistribute excess pixels in each bin bin_incr = int(n_excess / hist.size) # average binincrement upper = clip_limit - bin_incr # Bins larger than upper set to cliplimit hist[excess_mask] = clip_limit low_mask = hist < upper n_excess -= hist[low_mask].size * bin_incr hist[low_mask] += bin_incr mid_mask = (hist >= upper) & (hist < clip_limit) mid = hist[mid_mask] n_excess -= mid.size * clip_limit - mid.sum() hist[mid_mask] = clip_limit while n_excess > 0: # Redistribute remaining excess index = 0 while n_excess > 0 and index < hist.size: step_size = int(hist[hist < clip_limit].size / n_excess) step_size = max(step_size, 1) indices = np.arange(index, hist.size, step_size) under = hist[indices] < clip_limit hist[under] += 1 n_excess -= hist[under].size index += 1 return hist def map_histogram(hist, min_val, max_val, n_pixels): """Calculate the equalized lookup table (mapping). It does so by cumulating the input histogram. Parameters ---------- hist : ndarray Clipped histogram. min_val : int Minimum value for mapping. max_val : int Maximum value for mapping. n_pixels : int Number of pixels in the region. Returns ------- out : ndarray Mapped intensity LUT. """ out = np.cumsum(hist).astype(float) scale = ((float)(max_val - min_val)) / n_pixels out *= scale out += min_val out[out > max_val] = max_val return out.astype(int) def interpolate(image, xslice, yslice, mapLU, mapRU, mapLB, mapRB, aLUT): """Find the new grayscale level for a region using bilinear interpolation. Parameters ---------- image : ndarray Full image. xslice, yslice : array-like Indices of the region. map* : ndarray Mappings of greylevels from histograms. aLUT : ndarray Maps grayscale levels in image to histogram levels. Returns ------- out : ndarray Original image with the subregion replaced. Notes ----- This function calculates the new greylevel assignments of pixels within a submatrix of the image. This is done by a bilinear interpolation between four different mappings in order to eliminate boundary artifacts. """ norm = xslice.size * yslice.size # Normalization factor # interpolation weight matrices x_coef, y_coef = np.meshgrid(np.arange(xslice.size), np.arange(yslice.size)) x_inv_coef, y_inv_coef = x_coef[:, ::-1] + 1, y_coef[::-1] + 1 view = image[yslice[0]: yslice[-1] + 1, xslice[0]: xslice[-1] + 1] im_slice = aLUT[view] new = ((y_inv_coef * (x_inv_coef * mapLU[im_slice] + x_coef * mapRU[im_slice]) + y_coef * (x_inv_coef * mapLB[im_slice] + x_coef * mapRB[im_slice])) / norm) view[:, :] = new return image scikit-image-0.9.3/skimage/exposure/exposure.py000066400000000000000000000242751223313777300216310ustar00rootroot00000000000000import warnings import numpy as np from skimage import img_as_float from skimage.util.dtype import dtype_range, dtype_limits from skimage._shared.utils import deprecated __all__ = ['histogram', 'cumulative_distribution', 'equalize', 'rescale_intensity', 'adjust_gamma', 'adjust_log', 'adjust_sigmoid'] def histogram(image, nbins=256): """Return histogram of image. Unlike `numpy.histogram`, this function returns the centers of bins and does not rebin integer arrays. For integer arrays, each integer value has its own bin, which improves speed and intensity-resolution. The histogram is computed on the flattened image: for color images, the function should be used separately on each channel to obtain a histogram for each color channel. Parameters ---------- image : array Input image. nbins : int Number of bins used to calculate histogram. This value is ignored for integer arrays. Returns ------- hist : array The values of the histogram. bin_centers : array The values at the center of the bins. Examples -------- >>> from skimage import data >>> hist = histogram(data.camera()) >>> import matplotlib.pyplot as plt >>> plt.plot(hist[1], hist[0]) # doctest: +ELLIPSIS [...] """ sh = image.shape if len(sh) == 3 and sh[-1] < 4: warnings.warn("This might be a color image. The histogram will be " "computed on the flattened image. You can instead " "apply this function to each color channel.") # For integer types, histogramming with bincount is more efficient. if np.issubdtype(image.dtype, np.integer): offset = 0 if np.min(image) < 0: offset = np.min(image) hist = np.bincount(image.ravel() - offset) bin_centers = np.arange(len(hist)) + offset # clip histogram to start with a non-zero bin idx = np.nonzero(hist)[0][0] return hist[idx:], bin_centers[idx:] else: hist, bin_edges = np.histogram(image.flat, nbins) bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2. return hist, bin_centers def cumulative_distribution(image, nbins=256): """Return cumulative distribution function (cdf) for the given image. Parameters ---------- image : array Image array. nbins : int Number of bins for image histogram. Returns ------- img_cdf : array Values of cumulative distribution function. bin_centers : array Centers of bins. References ---------- .. [1] http://en.wikipedia.org/wiki/Cumulative_distribution_function """ hist, bin_centers = histogram(image, nbins) img_cdf = hist.cumsum() img_cdf = img_cdf / float(img_cdf[-1]) return img_cdf, bin_centers @deprecated('equalize_hist') def equalize(image, nbins=256): return equalize_hist(image, nbins) def equalize_hist(image, nbins=256): """Return image after histogram equalization. Parameters ---------- image : array Image array. nbins : int Number of bins for image histogram. Returns ------- out : float array Image array after histogram equalization. Notes ----- This function is adapted from [1]_ with the author's permission. References ---------- .. [1] http://www.janeriksolem.net/2009/06/histogram-equalization-with-python-and.html .. [2] http://en.wikipedia.org/wiki/Histogram_equalization """ image = img_as_float(image) cdf, bin_centers = cumulative_distribution(image, nbins) out = np.interp(image.flat, bin_centers, cdf) return out.reshape(image.shape) def rescale_intensity(image, in_range=None, out_range=None): """Return image after stretching or shrinking its intensity levels. The image intensities are uniformly rescaled such that the minimum and maximum values given by `in_range` match those given by `out_range`. Parameters ---------- image : array Image array. in_range : 2-tuple (float, float) Min and max *allowed* intensity values of input image. If None, the *allowed* min/max values are set to the *actual* min/max values in the input image. out_range : 2-tuple (float, float) Min and max intensity values of output image. If None, use the min/max intensities of the image data type. See `skimage.util.dtype` for details. Returns ------- out : array Image array after rescaling its intensity. This image is the same dtype as the input image. Examples -------- By default, intensities are stretched to the limits allowed by the dtype: >>> image = np.array([51, 102, 153], dtype=np.uint8) >>> rescale_intensity(image) array([ 0, 127, 255], dtype=uint8) It's easy to accidentally convert an image dtype from uint8 to float: >>> 1.0 * image array([ 51., 102., 153.]) Use `rescale_intensity` to rescale to the proper range for float dtypes: >>> image_float = 1.0 * image >>> rescale_intensity(image_float) array([ 0. , 0.5, 1. ]) To maintain the low contrast of the original, use the `in_range` parameter: >>> rescale_intensity(image_float, in_range=(0, 255)) array([ 0.2, 0.4, 0.6]) If the min/max value of `in_range` is more/less than the min/max image intensity, then the intensity levels are clipped: >>> rescale_intensity(image_float, in_range=(0, 102)) array([ 0.5, 1. , 1. ]) If you have an image with signed integers but want to rescale the image to just the positive range, use the `out_range` parameter: >>> image = np.array([-10, 0, 10], dtype=np.int8) >>> rescale_intensity(image, out_range=(0, 127)) array([ 0, 63, 127], dtype=int8) """ dtype = image.dtype.type if in_range is None: imin = np.min(image) imax = np.max(image) else: imin, imax = in_range if out_range is None: omin, omax = dtype_range[dtype] if imin >= 0: omin = 0 else: omin, omax = out_range image = np.clip(image, imin, imax) image = (image - imin) / float(imax - imin) return dtype(image * (omax - omin) + omin) def _assert_non_negative(image): if np.any(image < 0): raise ValueError('Image Correction methods work correctly only on ' 'images with non-negative values. Use ' 'skimage.exposure.rescale_intensity.') def adjust_gamma(image, gamma=1, gain=1): """Performs Gamma Correction on the input image. Also known as Power Law Transform. This function transforms the input image pixelwise according to the equation ``O = I**gamma`` after scaling each pixel to the range 0 to 1. Parameters ---------- image : ndarray Input image. gamma : float Non negative real number. Default value is 1. gain : float The constant multiplier. Default value is 1. Returns ------- out : ndarray Gamma corrected output image. Notes ----- For gamma greater than 1, the histogram will shift towards left and the output image will be darker than the input image. For gamma less than 1, the histogram will shift towards right and the output image will be brighter than the input image. References ---------- .. [1] http://en.wikipedia.org/wiki/Gamma_correction """ _assert_non_negative(image) dtype = image.dtype.type if gamma < 0: return "Gamma should be a non-negative real number" scale = float(dtype_limits(image, True)[1] - dtype_limits(image, True)[0]) out = ((image / scale) ** gamma) * scale * gain return dtype(out) def adjust_log(image, gain=1, inv=False): """Performs Logarithmic correction on the input image. This function transforms the input image pixelwise according to the equation ``O = gain*log(1 + I)`` after scaling each pixel to the range 0 to 1. For inverse logarithmic correction, the equation is ``O = gain*(2**I - 1)``. Parameters ---------- image : ndarray Input image. gain : float The constant multiplier. Default value is 1. inv : float If True, it performs inverse logarithmic correction, else correction will be logarithmic. Defaults to False. Returns ------- out : ndarray Logarithm corrected output image. References ---------- .. [1] http://www.ece.ucsb.edu/Faculty/Manjunath/courses/ece178W03/EnhancePart1.pdf """ _assert_non_negative(image) dtype = image.dtype.type scale = float(dtype_limits(image, True)[1] - dtype_limits(image, True)[0]) if inv: out = (2 ** (image / scale) - 1) * scale * gain return dtype(out) out = np.log2(1 + image / scale) * scale * gain return dtype(out) def adjust_sigmoid(image, cutoff=0.5, gain=10, inv=False): """Performs Sigmoid Correction on the input image. Also known as Contrast Adjustment. This function transforms the input image pixelwise according to the equation ``O = 1/(1 + exp*(gain*(cutoff - I)))`` after scaling each pixel to the range 0 to 1. Parameters ---------- image : ndarray Input image. cutoff : float Cutoff of the sigmoid function that shifts the characteristic curve in horizontal direction. Default value is 0.5. gain : float The constant multiplier in exponential's power of sigmoid function. Default value is 10. inv : bool If True, returns the negative sigmoid correction. Defaults to False. Returns ------- out : ndarray Sigmoid corrected output image. References ---------- .. [1] Gustav J. Braun, "Image Lightness Rescaling Using Sigmoidal Contrast Enhancement Functions" http://www.cis.rit.edu/fairchild/PDFs/PAP07.pdf """ _assert_non_negative(image) dtype = image.dtype.type scale = float(dtype_limits(image, True)[1] - dtype_limits(image, True)[0]) if inv: out = (1 - 1 / (1 + np.exp(gain * (cutoff - image/scale)))) * scale return dtype(out) out = (1 / (1 + np.exp(gain * (cutoff - image/scale)))) * scale return dtype(out) scikit-image-0.9.3/skimage/exposure/tests/000077500000000000000000000000001223313777300205355ustar00rootroot00000000000000scikit-image-0.9.3/skimage/exposure/tests/test_exposure.py000066400000000000000000000270211223313777300240220ustar00rootroot00000000000000import warnings import numpy as np from numpy.testing import assert_array_almost_equal as assert_close from numpy.testing import assert_array_equal import skimage from skimage import data from skimage import exposure from skimage.color import rgb2gray from skimage.util.dtype import dtype_range # Test histogram equalization # =========================== # squeeze image intensities to lower image contrast test_img = skimage.img_as_float(data.camera()) test_img = exposure.rescale_intensity(test_img / 5. + 100) def test_equalize_ubyte(): img = skimage.img_as_ubyte(test_img) img_eq = exposure.equalize_hist(img) cdf, bin_edges = exposure.cumulative_distribution(img_eq) check_cdf_slope(cdf) def test_equalize_float(): img = skimage.img_as_float(test_img) img_eq = exposure.equalize_hist(img) cdf, bin_edges = exposure.cumulative_distribution(img_eq) check_cdf_slope(cdf) def check_cdf_slope(cdf): """Slope of cdf which should equal 1 for an equalized histogram.""" norm_intensity = np.linspace(0, 1, len(cdf)) slope, intercept = np.polyfit(norm_intensity, cdf, 1) assert 0.9 < slope < 1.1 # Test rescale intensity # ====================== def test_rescale_stretch(): image = np.array([51, 102, 153], dtype=np.uint8) out = exposure.rescale_intensity(image) assert out.dtype == np.uint8 assert_close(out, [0, 127, 255]) def test_rescale_shrink(): image = np.array([51., 102., 153.]) out = exposure.rescale_intensity(image) assert_close(out, [0, 0.5, 1]) def test_rescale_in_range(): image = np.array([51., 102., 153.]) out = exposure.rescale_intensity(image, in_range=(0, 255)) assert_close(out, [0.2, 0.4, 0.6]) def test_rescale_in_range_clip(): image = np.array([51., 102., 153.]) out = exposure.rescale_intensity(image, in_range=(0, 102)) assert_close(out, [0.5, 1, 1]) def test_rescale_out_range(): image = np.array([-10, 0, 10], dtype=np.int8) out = exposure.rescale_intensity(image, out_range=(0, 127)) assert out.dtype == np.int8 assert_close(out, [0, 63, 127]) # Test adaptive histogram equalization # ==================================== def test_adapthist_scalar(): '''Test a scalar uint8 image ''' img = skimage.img_as_ubyte(data.moon()) adapted = exposure.equalize_adapthist(img, clip_limit=0.02) assert adapted.min() == 0 assert adapted.max() == (1 << 16) - 1 assert img.shape == adapted.shape full_scale = skimage.exposure.rescale_intensity(skimage.img_as_uint(img)) assert_almost_equal = np.testing.assert_almost_equal assert_almost_equal(peak_snr(full_scale, adapted), 101.231, 3) assert_almost_equal(norm_brightness_err(full_scale, adapted), 0.041, 3) return img, adapted def test_adapthist_grayscale(): '''Test a grayscale float image ''' img = skimage.img_as_float(data.lena()) img = rgb2gray(img) img = np.dstack((img, img, img)) adapted = exposure.equalize_adapthist(img, 10, 9, clip_limit=0.01, nbins=128) assert_almost_equal = np.testing.assert_almost_equal assert img.shape == adapted.shape assert_almost_equal(peak_snr(img, adapted), 97.531, 3) assert_almost_equal(norm_brightness_err(img, adapted), 0.0313, 3) return data, adapted def test_adapthist_color(): '''Test an RGB color uint16 image ''' img = skimage.img_as_uint(data.lena()) with warnings.catch_warnings(record=True) as w: warnings.simplefilter('always') hist, bin_centers = exposure.histogram(img) assert len(w) > 0 adapted = exposure.equalize_adapthist(img, clip_limit=0.01) assert_almost_equal = np.testing.assert_almost_equal assert adapted.min() == 0 assert adapted.max() == 1.0 assert img.shape == adapted.shape full_scale = skimage.exposure.rescale_intensity(img) assert_almost_equal(peak_snr(full_scale, adapted), 102.940, 3) assert_almost_equal(norm_brightness_err(full_scale, adapted), 0.0110, 3) return data, adapted def peak_snr(img1, img2): '''Peak signal to noise ratio of two images Parameters ---------- img1 : array-like img2 : array-like Returns ------- peak_snr : float Peak signal to noise ratio ''' if img1.ndim == 3: img1, img2 = rgb2gray(img1.copy()), rgb2gray(img2.copy()) img1 = skimage.img_as_float(img1) img2 = skimage.img_as_float(img2) mse = 1. / img1.size * np.square(img1 - img2).sum() _, max_ = dtype_range[img1.dtype.type] return 20 * np.log(max_ / mse) def norm_brightness_err(img1, img2): '''Normalized Absolute Mean Brightness Error between two images Parameters ---------- img1 : array-like img2 : array-like Returns ------- norm_brightness_error : float Normalized absolute mean brightness error ''' if img1.ndim == 3: img1, img2 = rgb2gray(img1), rgb2gray(img2) ambe = np.abs(img1.mean() - img2.mean()) nbe = ambe / dtype_range[img1.dtype.type][1] return nbe if __name__ == '__main__': from numpy import testing testing.run_module_suite() # Test Gamma Correction # ===================== def test_adjust_gamma_one(): """Same image should be returned for gamma equal to one""" image = np.random.uniform(0, 255, (8, 8)) result = exposure.adjust_gamma(image, 1) assert_array_equal(result, image) def test_adjust_gamma_zero(): """White image should be returned for gamma equal to zero""" image = np.random.uniform(0, 255, (8, 8)) result = exposure.adjust_gamma(image, 0) dtype = image.dtype.type assert_array_equal(result, dtype_range[dtype][1]) def test_adjust_gamma_less_one(): """Verifying the output with expected results for gamma correction with gamma equal to half""" image = np.arange(0, 255, 4, np.uint8).reshape(8,8) expected = np.array([[ 0, 31, 45, 55, 63, 71, 78, 84], [ 90, 95, 100, 105, 110, 115, 119, 123], [127, 131, 135, 139, 142, 146, 149, 153], [156, 159, 162, 165, 168, 171, 174, 177], [180, 183, 186, 188, 191, 194, 196, 199], [201, 204, 206, 209, 211, 214, 216, 218], [221, 223, 225, 228, 230, 232, 234, 236], [238, 241, 243, 245, 247, 249, 251, 253]], dtype=np.uint8) result = exposure.adjust_gamma(image, 0.5) assert_array_equal(result, expected) def test_adjust_gamma_greater_one(): """Verifying the output with expected results for gamma correction with gamma equal to two""" image = np.arange(0, 255, 4, np.uint8).reshape(8,8) expected = np.array([[ 0, 0, 0, 0, 1, 1, 2, 3], [ 4, 5, 6, 7, 9, 10, 12, 14], [ 16, 18, 20, 22, 25, 27, 30, 33], [ 36, 39, 42, 45, 49, 52, 56, 60], [ 64, 68, 72, 76, 81, 85, 90, 95], [100, 105, 110, 116, 121, 127, 132, 138], [144, 150, 156, 163, 169, 176, 182, 189], [196, 203, 211, 218, 225, 233, 241, 249]], dtype=np.uint8) result = exposure.adjust_gamma(image, 2) assert_array_equal(result, expected) # Test Logarithmic Correction # =========================== def test_adjust_log(): """Verifying the output with expected results for logarithmic correction with multiplier constant multiplier equal to unity""" image = np.arange(0, 255, 4, np.uint8).reshape(8,8) expected = np.array([[ 0, 5, 11, 16, 22, 27, 33, 38], [ 43, 48, 53, 58, 63, 68, 73, 77], [ 82, 86, 91, 95, 100, 104, 109, 113], [117, 121, 125, 129, 133, 137, 141, 145], [149, 153, 157, 160, 164, 168, 172, 175], [179, 182, 186, 189, 193, 196, 199, 203], [206, 209, 213, 216, 219, 222, 225, 228], [231, 234, 238, 241, 244, 246, 249, 252]], dtype=np.uint8) result = exposure.adjust_log(image, 1) assert_array_equal(result, expected) def test_adjust_inv_log(): """Verifying the output with expected results for inverse logarithmic correction with multiplier constant multiplier equal to unity""" image = np.arange(0, 255, 4, np.uint8).reshape(8,8) expected = np.array([[ 0, 2, 5, 8, 11, 14, 17, 20], [ 23, 26, 29, 32, 35, 38, 41, 45], [ 48, 51, 55, 58, 61, 65, 68, 72], [ 76, 79, 83, 87, 90, 94, 98, 102], [106, 110, 114, 118, 122, 126, 130, 134], [138, 143, 147, 151, 156, 160, 165, 170], [174, 179, 184, 188, 193, 198, 203, 208], [213, 218, 224, 229, 234, 239, 245, 250]], dtype=np.uint8) result = exposure.adjust_log(image, 1, True) assert_array_equal(result, expected) # Test Sigmoid Correction # ======================= def test_adjust_sigmoid_cutoff_one(): """Verifying the output with expected results for sigmoid correction with cutoff equal to one and gain of 5""" image = np.arange(0, 255, 4, np.uint8).reshape(8,8) expected = np.array([[ 1, 1, 1, 2, 2, 2, 2, 2], [ 3, 3, 3, 4, 4, 4, 5, 5], [ 5, 6, 6, 7, 7, 8, 9, 10], [ 10, 11, 12, 13, 14, 15, 16, 18], [ 19, 20, 22, 24, 25, 27, 29, 32], [ 34, 36, 39, 41, 44, 47, 50, 54], [ 57, 61, 64, 68, 72, 76, 80, 85], [ 89, 94, 99, 104, 108, 113, 118, 123]], dtype=np.uint8) result = exposure.adjust_sigmoid(image, 1, 5) assert_array_equal(result, expected) def test_adjust_sigmoid_cutoff_zero(): """Verifying the output with expected results for sigmoid correction with cutoff equal to zero and gain of 10""" image = np.arange(0, 255, 4, np.uint8).reshape(8,8) expected = np.array([[127, 137, 147, 156, 166, 175, 183, 191], [198, 205, 211, 216, 221, 225, 229, 232], [235, 238, 240, 242, 244, 245, 247, 248], [249, 250, 250, 251, 251, 252, 252, 253], [253, 253, 253, 253, 254, 254, 254, 254], [254, 254, 254, 254, 254, 254, 254, 254], [254, 254, 254, 254, 254, 254, 254, 254], [254, 254, 254, 254, 254, 254, 254, 254]], dtype=np.uint8) result = exposure.adjust_sigmoid(image, 0, 10) assert_array_equal(result, expected) def test_adjust_sigmoid_cutoff_half(): """Verifying the output with expected results for sigmoid correction with cutoff equal to half and gain of 10""" image = np.arange(0, 255, 4, np.uint8).reshape(8,8) expected = np.array([[ 1, 1, 2, 2, 3, 3, 4, 5], [ 5, 6, 7, 9, 10, 12, 14, 16], [ 19, 22, 25, 29, 34, 39, 44, 50], [ 57, 64, 72, 80, 89, 99, 108, 118], [128, 138, 148, 158, 167, 176, 184, 192], [199, 205, 211, 217, 221, 226, 229, 233], [236, 238, 240, 242, 244, 246, 247, 248], [249, 250, 250, 251, 251, 252, 252, 253]], dtype=np.uint8) result = exposure.adjust_sigmoid(image, 0.5, 10) assert_array_equal(result, expected) def test_adjust_inv_sigmoid_cutoff_half(): """Verifying the output with expected results for inverse sigmoid correction with cutoff equal to half and gain of 10""" image = np.arange(0, 255, 4, np.uint8).reshape(8,8) expected = np.array([[253, 253, 252, 252, 251, 251, 250, 249], [249, 248, 247, 245, 244, 242, 240, 238], [235, 232, 229, 225, 220, 215, 210, 204], [197, 190, 182, 174, 165, 155, 146, 136], [126, 116, 106, 96, 87, 78, 70, 62], [ 55, 49, 43, 37, 33, 28, 25, 21], [ 18, 16, 14, 12, 10, 8, 7, 6], [ 5, 4, 4, 3, 3, 2, 2, 1]], dtype=np.uint8) result = exposure.adjust_sigmoid(image, 0.5, 10, True) assert_array_equal(result, expected) scikit-image-0.9.3/skimage/feature/000077500000000000000000000000001223313777300171545ustar00rootroot00000000000000scikit-image-0.9.3/skimage/feature/__init__.py000066400000000000000000000014331223313777300212660ustar00rootroot00000000000000from ._daisy import daisy from ._hog import hog from .texture import greycomatrix, greycoprops, local_binary_pattern from .peak import peak_local_max from .corner import (corner_kitchen_rosenfeld, corner_harris, corner_shi_tomasi, corner_foerstner, corner_subpix, corner_peaks) from .corner_cy import corner_moravec from .template import match_template __all__ = ['daisy', 'hog', 'greycomatrix', 'greycoprops', 'local_binary_pattern', 'peak_local_max', 'corner_kitchen_rosenfeld', 'corner_harris', 'corner_shi_tomasi', 'corner_foerstner', 'corner_subpix', 'corner_peaks', 'corner_moravec', 'match_template'] scikit-image-0.9.3/skimage/feature/_brief.py000066400000000000000000000205241223313777300207570ustar00rootroot00000000000000import numpy as np from scipy.ndimage.filters import gaussian_filter from ..util import img_as_float from .util import _mask_border_keypoints, pairwise_hamming_distance from ._brief_cy import _brief_loop def brief(image, keypoints, descriptor_size=256, mode='normal', patch_size=49, sample_seed=1, variance=2): """**Experimental function**. Extract BRIEF Descriptor about given keypoints for a given image. Parameters ---------- image : 2D ndarray Input image. keypoints : (P, 2) ndarray Array of keypoint locations in the format (row, col). descriptor_size : int Size of BRIEF descriptor about each keypoint. Sizes 128, 256 and 512 preferred by the authors. Default is 256. mode : string Probability distribution for sampling location of decision pixel-pairs around keypoints. Default is 'normal' otherwise uniform. patch_size : int Length of the two dimensional square patch sampling region around the keypoints. Default is 49. sample_seed : int Seed for sampling the decision pixel-pairs. From a square window with length patch_size, pixel pairs are sampled using the `mode` parameter to build the descriptors using intensity comparison. The value of `sample_seed` should be the same for the images to be matched while building the descriptors. Default is 1. variance : float Variance of the Gaussian Low Pass filter applied on the image to alleviate noise sensitivity. Default is 2. Returns ------- descriptors : (Q, `descriptor_size`) ndarray of dtype bool 2D ndarray of binary descriptors of size `descriptor_size` about Q keypoints after filtering out border keypoints with value at an index (i, j) either being True or False representing the outcome of Intensity comparison about ith keypoint on jth decision pixel-pair. keypoints : (Q, 2) ndarray Location i.e. (row, col) of keypoints after removing out those that are near border. References ---------- .. [1] Michael Calonder, Vincent Lepetit, Christoph Strecha and Pascal Fua "BRIEF : Binary robust independent elementary features", http://cvlabwww.epfl.ch/~lepetit/papers/calonder_eccv10.pdf Examples -------- >>> import numpy as np >>> from skimage.feature.corner import corner_peaks, corner_harris >>> from skimage.feature import pairwise_hamming_distance, brief, match_keypoints_brief >>> square1 = np.zeros([8, 8], dtype=np.int32) >>> square1[2:6, 2:6] = 1 >>> square1 array([[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32) >>> keypoints1 = corner_peaks(corner_harris(square1), min_distance=1) >>> keypoints1 array([[2, 2], [2, 5], [5, 2], [5, 5]]) >>> descriptors1, keypoints1 = brief(square1, keypoints1, patch_size=5) >>> keypoints1 array([[2, 2], [2, 5], [5, 2], [5, 5]]) >>> square2 = np.zeros([9, 9], dtype=np.int32) >>> square2[2:7, 2:7] = 1 >>> square2 array([[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32) >>> keypoints2 = corner_peaks(corner_harris(square2), min_distance=1) >>> keypoints2 array([[2, 2], [2, 6], [6, 2], [6, 6]]) >>> descriptors2, keypoints2 = brief(square2, keypoints2, patch_size=5) >>> keypoints2 array([[2, 2], [2, 6], [6, 2], [6, 6]]) >>> pairwise_hamming_distance(descriptors1, descriptors2) array([[ 0.03125 , 0.3203125, 0.3671875, 0.6171875], [ 0.3203125, 0.03125 , 0.640625 , 0.375 ], [ 0.375 , 0.6328125, 0.0390625, 0.328125 ], [ 0.625 , 0.3671875, 0.34375 , 0.0234375]]) >>> match_keypoints_brief(keypoints1, descriptors1, keypoints2, descriptors2) array([[[ 2, 2], [ 2, 2]], [[ 2, 5], [ 2, 6]], [[ 5, 2], [ 6, 2]], [[ 5, 5], [ 6, 6]]]) """ np.random.seed(sample_seed) image = np.squeeze(image) if image.ndim != 2: raise ValueError("Only 2-D gray-scale images supported.") image = img_as_float(image) # Gaussian Low pass filtering to alleviate noise # sensitivity image = gaussian_filter(image, variance) image = np.ascontiguousarray(image) keypoints = np.array(keypoints + 0.5, dtype=np.intp, order='C') # Removing keypoints that are within (patch_size / 2) distance from the # image border keypoints = keypoints[_mask_border_keypoints(image, keypoints, patch_size // 2)] keypoints = np.ascontiguousarray(keypoints) descriptors = np.zeros((keypoints.shape[0], descriptor_size), dtype=bool, order='C') # Sampling pairs of decision pixels in patch_size x patch_size window if mode == 'normal': samples = (patch_size / 5.0) * np.random.randn(descriptor_size * 8) samples = np.array(samples, dtype=np.int32) samples = samples[(samples < (patch_size // 2)) & (samples > - (patch_size - 2) // 2)] pos1 = samples[:descriptor_size * 2] pos1 = pos1.reshape(descriptor_size, 2) pos2 = samples[descriptor_size * 2:descriptor_size * 4] pos2 = pos2.reshape(descriptor_size, 2) else: samples = np.random.randint(-(patch_size - 2) // 2, (patch_size // 2) + 1, (descriptor_size * 2, 2)) pos1, pos2 = np.split(samples, 2) pos1 = np.ascontiguousarray(pos1) pos2 = np.ascontiguousarray(pos2) _brief_loop(image, descriptors.view(np.uint8), keypoints, pos1, pos2) return descriptors, keypoints def match_keypoints_brief(keypoints1, descriptors1, keypoints2, descriptors2, threshold=0.15): """**Experimental function**. Match keypoints described using BRIEF descriptors in one image to those in second image. Parameters ---------- keypoints1 : (M, 2) ndarray M Keypoints from the first image described using skimage.feature.brief descriptors1 : (M, P) ndarray BRIEF descriptors of size P about M keypoints in the first image. keypoints2 : (N, 2) ndarray N Keypoints from the second image described using skimage.feature.brief descriptors2 : (N, P) ndarray BRIEF descriptors of size P about N keypoints in the second image. threshold : float in range [0, 1] Maximum allowable hamming distance between descriptors of two keypoints in separate images to be regarded as a match. Default is 0.15. Returns ------- match_keypoints_brief : (Q, 2, 2) ndarray Location of Q matched keypoint pairs from two images. """ if (keypoints1.shape[0] != descriptors1.shape[0] or keypoints2.shape[0] != descriptors2.shape[0]): raise ValueError("The number of keypoints and number of described " "keypoints do not match. Make the optional parameter " "return_keypoints True to get described keypoints.") if descriptors1.shape[1] != descriptors2.shape[1]: raise ValueError("Descriptor sizes for matching keypoints in both " "the images should be equal.") # Get hamming distances between keeypoints1 and keypoints2 distance = pairwise_hamming_distance(descriptors1, descriptors2) temp = distance > threshold row_check = np.any(~temp, axis=1) matched_keypoints2 = keypoints2[np.argmin(distance, axis=1)] matched_keypoint_pairs = np.zeros((np.sum(row_check), 2, 2), dtype=np.intp) matched_keypoint_pairs[:, 0, :] = keypoints1[row_check] matched_keypoint_pairs[:, 1, :] = matched_keypoints2[row_check] return matched_keypoint_pairs scikit-image-0.9.3/skimage/feature/_brief_cy.pyx000066400000000000000000000012741223313777300216430ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False cimport numpy as cnp def _brief_loop(double[:, ::1] image, char[:, ::1] descriptors, Py_ssize_t[:, ::1] keypoints, int[:, ::1] pos0, int[:, ::1] pos1): cdef Py_ssize_t k, d, kr, kc, pr0, pr1, pc0, pc1 for p in range(pos0.shape[0]): pr0 = pos0[p, 0] pc0 = pos0[p, 1] pr1 = pos1[p, 0] pc1 = pos1[p, 1] for k in range(keypoints.shape[0]): kr = keypoints[k, 0] kc = keypoints[k, 1] if image[kr + pr0, kc + pc0] < image[kr + pr1, kc + pc1]: descriptors[k, p] = True scikit-image-0.9.3/skimage/feature/_daisy.py000066400000000000000000000232241223313777300210010ustar00rootroot00000000000000import numpy as np from scipy import sqrt, pi, arctan2, cos, sin, exp from scipy.ndimage import gaussian_filter import skimage.color from skimage import img_as_float, draw def daisy(img, step=4, radius=15, rings=3, histograms=8, orientations=8, normalization='l1', sigmas=None, ring_radii=None, visualize=False): '''Extract DAISY feature descriptors densely for the given image. DAISY is a feature descriptor similar to SIFT formulated in a way that allows for fast dense extraction. Typically, this is practical for bag-of-features image representations. The implementation follows Tola et al. [1]_ but deviate on the following points: * Histogram bin contribution are smoothed with a circular Gaussian window over the tonal range (the angular range). * The sigma values of the spatial Gaussian smoothing in this code do not match the sigma values in the original code by Tola et al. [2]_. In their code, spatial smoothing is applied to both the input image and the center histogram. However, this smoothing is not documented in [1]_ and, therefore, it is omitted. Parameters ---------- img : (M, N) array Input image (greyscale). step : int, optional Distance between descriptor sampling points. radius : int, optional Radius (in pixels) of the outermost ring. rings : int, optional Number of rings. histograms : int, optional Number of histograms sampled per ring. orientations : int, optional Number of orientations (bins) per histogram. normalization : [ 'l1' | 'l2' | 'daisy' | 'off' ], optional How to normalize the descriptors * 'l1': L1-normalization of each descriptor. * 'l2': L2-normalization of each descriptor. * 'daisy': L2-normalization of individual histograms. * 'off': Disable normalization. sigmas : 1D array of float, optional Standard deviation of spatial Gaussian smoothing for the center histogram and for each ring of histograms. The array of sigmas should be sorted from the center and out. I.e. the first sigma value defines the spatial smoothing of the center histogram and the last sigma value defines the spatial smoothing of the outermost ring. Specifying sigmas overrides the following parameter. ``rings = len(sigmas) - 1`` ring_radii : 1D array of int, optional Radius (in pixels) for each ring. Specifying ring_radii overrides the following two parameters. ``rings = len(ring_radii)`` ``radius = ring_radii[-1]`` If both sigmas and ring_radii are given, they must satisfy the following predicate since no radius is needed for the center histogram. ``len(ring_radii) == len(sigmas) + 1`` visualize : bool, optional Generate a visualization of the DAISY descriptors Returns ------- descs : array Grid of DAISY descriptors for the given image as an array dimensionality (P, Q, R) where ``P = ceil((M - radius*2) / step)`` ``Q = ceil((N - radius*2) / step)`` ``R = (rings * histograms + 1) * orientations`` descs_img : (M, N, 3) array (only if visualize==True) Visualization of the DAISY descriptors. References ---------- .. [1] Tola et al. "Daisy: An efficient dense descriptor applied to wide- baseline stereo." Pattern Analysis and Machine Intelligence, IEEE Transactions on 32.5 (2010): 815-830. .. [2] http://cvlab.epfl.ch/alumni/tola/daisy.html ''' # Validate image format. if img.ndim > 2: raise ValueError('Only grey-level images are supported.') if img.dtype.kind != 'f': img = img_as_float(img) # Validate parameters. if sigmas is not None and ring_radii is not None \ and len(sigmas) - 1 != len(ring_radii): raise ValueError('len(sigmas)-1 != len(ring_radii)') if ring_radii is not None: rings = len(ring_radii) radius = ring_radii[-1] if sigmas is not None: rings = len(sigmas) - 1 if sigmas is None: sigmas = [radius * (i + 1) / float(2 * rings) for i in range(rings)] if ring_radii is None: ring_radii = [radius * (i + 1) / float(rings) for i in range(rings)] if normalization not in ['l1', 'l2', 'daisy', 'off']: raise ValueError('Invalid normalization method.') # Compute image derivatives. dx = np.zeros(img.shape) dy = np.zeros(img.shape) dx[:, :-1] = np.diff(img, n=1, axis=1) dy[:-1, :] = np.diff(img, n=1, axis=0) # Compute gradient orientation and magnitude and their contribution # to the histograms. grad_mag = sqrt(dx ** 2 + dy ** 2) grad_ori = arctan2(dy, dx) orientation_kappa = orientations / pi orientation_angles = [2 * o * pi / orientations - pi for o in range(orientations)] hist = np.empty((orientations,) + img.shape, dtype=float) for i, o in enumerate(orientation_angles): # Weigh bin contribution by the circular normal distribution hist[i, :, :] = exp(orientation_kappa * cos(grad_ori - o)) # Weigh bin contribution by the gradient magnitude hist[i, :, :] = np.multiply(hist[i, :, :], grad_mag) # Smooth orientation histograms for the center and all rings. sigmas = [sigmas[0]] + sigmas hist_smooth = np.empty((rings + 1,) + hist.shape, dtype=float) for i in range(rings + 1): for j in range(orientations): hist_smooth[i, j, :, :] = gaussian_filter(hist[j, :, :], sigma=sigmas[i]) # Assemble descriptor grid. theta = [2 * pi * j / histograms for j in range(histograms)] desc_dims = (rings * histograms + 1) * orientations descs = np.empty((desc_dims, img.shape[0] - 2 * radius, img.shape[1] - 2 * radius)) descs[:orientations, :, :] = hist_smooth[0, :, radius:-radius, radius:-radius] idx = orientations for i in range(rings): for j in range(histograms): y_min = radius + int(round(ring_radii[i] * sin(theta[j]))) y_max = descs.shape[1] + y_min x_min = radius + int(round(ring_radii[i] * cos(theta[j]))) x_max = descs.shape[2] + x_min descs[idx:idx + orientations, :, :] = hist_smooth[i + 1, :, y_min:y_max, x_min:x_max] idx += orientations descs = descs[:, ::step, ::step] descs = descs.swapaxes(0, 1).swapaxes(1, 2) # Normalize descriptors. if normalization != 'off': descs += 1e-10 if normalization == 'l1': descs /= np.sum(descs, axis=2)[:, :, np.newaxis] elif normalization == 'l2': descs /= sqrt(np.sum(descs ** 2, axis=2))[:, :, np.newaxis] elif normalization == 'daisy': for i in range(0, desc_dims, orientations): norms = sqrt(np.sum(descs[:, :, i:i + orientations] ** 2, axis=2)) descs[:, :, i:i + orientations] /= norms[:, :, np.newaxis] if visualize: descs_img = skimage.color.gray2rgb(img) for i in range(descs.shape[0]): for j in range(descs.shape[1]): # Draw center histogram sigma color = (1, 0, 0) desc_y = i * step + radius desc_x = j * step + radius coords = draw.circle_perimeter(desc_y, desc_x, int(sigmas[0])) draw.set_color(descs_img, coords, color) max_bin = np.max(descs[i, j, :]) for o_num, o in enumerate(orientation_angles): # Draw center histogram bins bin_size = descs[i, j, o_num] / max_bin dy = sigmas[0] * bin_size * sin(o) dx = sigmas[0] * bin_size * cos(o) coords = draw.line(desc_y, desc_x, int(desc_y + dy), int(desc_x + dx)) draw.set_color(descs_img, coords, color) for r_num, r in enumerate(ring_radii): color_offset = float(1 + r_num) / rings color = (1 - color_offset, 1, color_offset) for t_num, t in enumerate(theta): # Draw ring histogram sigmas hist_y = desc_y + int(round(r * sin(t))) hist_x = desc_x + int(round(r * cos(t))) coords = draw.circle_perimeter(hist_y, hist_x, int(sigmas[r_num + 1])) draw.set_color(descs_img, coords, color) for o_num, o in enumerate(orientation_angles): # Draw histogram bins bin_size = descs[i, j, orientations + r_num * histograms * orientations + t_num * orientations + o_num] bin_size /= max_bin dy = sigmas[r_num + 1] * bin_size * sin(o) dx = sigmas[r_num + 1] * bin_size * cos(o) coords = draw.line(hist_y, hist_x, int(hist_y + dy), int(hist_x + dx)) draw.set_color(descs_img, coords, color) return descs, descs_img else: return descs scikit-image-0.9.3/skimage/feature/_greycomatrix.py000066400000000000000000000175061223313777300224130ustar00rootroot00000000000000""" Compute grey level co-occurrence matrices (GLCMs) and associated properties to characterize image textures. """ import numpy as np from ._texture import _glcm_loop def greycomatrix(image, distances, angles, levels=256, symmetric=False, normed=False): """Calculate the grey-level co-occurrence matrix. A grey level co-occurence matrix is a histogram of co-occuring greyscale values at a given offset over an image. Parameters ---------- image : array_like of uint8 Integer typed input image. The image will be cast to uint8, so the maximum value must be less than 256. distances : array_like List of pixel pair distance offsets. angles : array_like List of pixel pair angles in radians. levels : int, optional The input image should contain integers in [0, levels-1], where levels indicate the number of grey-levels counted (typically 256 for an 8-bit image). The maximum value is 256. symmetric : bool, optional If True, the output matrix `P[:, :, d, theta]` is symmetric. This is accomplished by ignoring the order of value pairs, so both (i, j) and (j, i) are accumulated when (i, j) is encountered for a given offset. The default is False. normed : bool, optional If True, normalize each matrix `P[:, :, d, theta]` by dividing by the total number of accumulated co-occurrences for the given offset. The elements of the resulting matrix sum to 1. The default is False. Returns ------- P : 4-D ndarray The grey-level co-occurrence histogram. The value `P[i,j,d,theta]` is the number of times that grey-level `j` occurs at a distance `d` and at an angle `theta` from grey-level `i`. If `normed` is `False`, the output is of type uint32, otherwise it is float64. References ---------- .. [1] The GLCM Tutorial Home Page, http://www.fp.ucalgary.ca/mhallbey/tutorial.htm .. [2] Pattern Recognition Engineering, Morton Nadler & Eric P. Smith .. [3] Wikipedia, http://en.wikipedia.org/wiki/Co-occurrence_matrix Examples -------- Compute 2 GLCMs: One for a 1-pixel offset to the right, and one for a 1-pixel offset upwards. >>> image = np.array([[0, 0, 1, 1], ... [0, 0, 1, 1], ... [0, 2, 2, 2], ... [2, 2, 3, 3]], dtype=np.uint8) >>> result = greycomatrix(image, [1], [0, np.pi/2], levels=4) >>> result[:, :, 0, 0] array([[2, 2, 1, 0], [0, 2, 0, 0], [0, 0, 3, 1], [0, 0, 0, 1]], dtype=uint32) >>> result[:, :, 0, 1] array([[3, 0, 2, 0], [0, 2, 2, 0], [0, 0, 1, 2], [0, 0, 0, 0]], dtype=uint32) """ assert levels <= 256 image = np.ascontiguousarray(image) assert image.ndim == 2 assert image.min() >= 0 assert image.max() < levels image = image.astype(np.uint8) distances = np.ascontiguousarray(distances, dtype=np.float64) angles = np.ascontiguousarray(angles, dtype=np.float64) assert distances.ndim == 1 assert angles.ndim == 1 P = np.zeros((levels, levels, len(distances), len(angles)), dtype=np.uint32, order='C') # count co-occurences _glcm_loop(image, distances, angles, levels, P) # make each GLMC symmetric if symmetric: Pt = np.transpose(P, (1, 0, 2, 3)) P = P + Pt # normalize each GLMC if normed: P = P.astype(np.float64) glcm_sums = np.apply_over_axes(np.sum, P, axes=(0, 1)) glcm_sums[glcm_sums == 0] = 1 P /= glcm_sums return P def greycoprops(P, prop='contrast'): """Calculate texture properties of a GLCM. Compute a feature of a grey level co-occurrence matrix to serve as a compact summary of the matrix. The properties are computed as follows: - 'contrast': :math:`\\sum_{i,j=0}^{levels-1} P_{i,j}(i-j)^2` - 'dissimilarity': :math:`\\sum_{i,j=0}^{levels-1}P_{i,j}|i-j|` - 'homogeneity': :math:`\\sum_{i,j=0}^{levels-1}\\frac{P_{i,j}}{1+(i-j)^2}` - 'ASM': :math:`\\sum_{i,j=0}^{levels-1} P_{i,j}^2` - 'energy': :math:`\\sqrt{ASM}` - 'correlation': .. math:: \\sum_{i,j=0}^{levels-1} P_{i,j}\\left[\\frac{(i-\\mu_i) \\ (j-\\mu_j)}{\\sqrt{(\\sigma_i^2)(\\sigma_j^2)}}\\right] Parameters ---------- P : ndarray Input array. `P` is the grey-level co-occurrence histogram for which to compute the specified property. The value `P[i,j,d,theta]` is the number of times that grey-level j occurs at a distance d and at an angle theta from grey-level i. prop : {'contrast', 'dissimilarity', 'homogeneity', 'energy', \ 'correlation', 'ASM'}, optional The property of the GLCM to compute. The default is 'contrast'. Returns ------- results : 2-D ndarray 2-dimensional array. `results[d, a]` is the property 'prop' for the d'th distance and the a'th angle. References ---------- .. [1] The GLCM Tutorial Home Page, http://www.fp.ucalgary.ca/mhallbey/tutorial.htm Examples -------- Compute the contrast for GLCMs with distances [1, 2] and angles [0 degrees, 90 degrees] >>> image = np.array([[0, 0, 1, 1], ... [0, 0, 1, 1], ... [0, 2, 2, 2], ... [2, 2, 3, 3]], dtype=np.uint8) >>> g = greycomatrix(image, [1, 2], [0, np.pi/2], levels=4, ... normed=True, symmetric=True) >>> contrast = greycoprops(g, 'contrast') >>> contrast array([[ 0.58333333, 1. ], [ 1.25 , 2.75 ]]) """ assert P.ndim == 4 (num_level, num_level2, num_dist, num_angle) = P.shape assert num_level == num_level2 assert num_dist > 0 assert num_angle > 0 # create weights for specified property I, J = np.ogrid[0:num_level, 0:num_level] if prop == 'contrast': weights = (I - J)**2 elif prop == 'dissimilarity': weights = np.abs(I - J) elif prop == 'homogeneity': weights = 1. / (1. + (I - J)**2) elif prop in ['ASM', 'energy', 'correlation']: pass else: raise ValueError('%s is an invalid property' % (prop)) # compute property for each GLCM if prop == 'energy': asm = np.apply_over_axes(np.sum, (P**2), axes=(0, 1))[0, 0] results = np.sqrt(asm) elif prop == 'ASM': results = np.apply_over_axes(np.sum, (P**2), axes=(0, 1))[0, 0] elif prop == 'correlation': results = np.zeros((num_dist, num_angle), dtype=np.float64) I = np.array(range(num_level)).reshape((num_level, 1, 1, 1)) J = np.array(range(num_level)).reshape((1, num_level, 1, 1)) diff_i = I - np.apply_over_axes(np.sum, (I * P), axes=(0, 1))[0, 0] diff_j = J - np.apply_over_axes(np.sum, (J * P), axes=(0, 1))[0, 0] std_i = np.sqrt(np.apply_over_axes(np.sum, (P * (diff_i)**2), axes=(0, 1))[0, 0]) std_j = np.sqrt(np.apply_over_axes(np.sum, (P * (diff_j)**2), axes=(0, 1))[0, 0]) cov = np.apply_over_axes(np.sum, (P * (diff_i * diff_j)), axes=(0, 1))[0, 0] # handle the special case of standard deviations near zero mask_0 = std_i < 1e-15 mask_0[std_j < 1e-15] = True results[mask_0] = 1 # handle the standard case mask_1 = mask_0 == False results[mask_1] = cov[mask_1] / (std_i[mask_1] * std_j[mask_1]) elif prop in ['contrast', 'dissimilarity', 'homogeneity']: weights = weights.reshape((num_level, num_level, 1, 1)) results = np.apply_over_axes(np.sum, (P * weights), axes=(0, 1))[0, 0] return results scikit-image-0.9.3/skimage/feature/_hog.py000066400000000000000000000165021223313777300204460ustar00rootroot00000000000000import numpy as np from scipy import sqrt, pi, arctan2, cos, sin from scipy.ndimage import uniform_filter def hog(image, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(3, 3), visualise=False, normalise=False): """Extract Histogram of Oriented Gradients (HOG) for a given image. Compute a Histogram of Oriented Gradients (HOG) by 1. (optional) global image normalisation 2. computing the gradient image in x and y 3. computing gradient histograms 4. normalising across blocks 5. flattening into a feature vector Parameters ---------- image : (M, N) ndarray Input image (greyscale). orientations : int Number of orientation bins. pixels_per_cell : 2 tuple (int, int) Size (in pixels) of a cell. cells_per_block : 2 tuple (int,int) Number of cells in each block. visualise : bool, optional Also return an image of the HOG. normalise : bool, optional Apply power law compression to normalise the image before processing. Returns ------- newarr : ndarray HOG for the image as a 1D (flattened) array. hog_image : ndarray (if visualise=True) A visualisation of the HOG image. References ---------- * http://en.wikipedia.org/wiki/Histogram_of_oriented_gradients * Dalal, N and Triggs, B, Histograms of Oriented Gradients for Human Detection, IEEE Computer Society Conference on Computer Vision and Pattern Recognition 2005 San Diego, CA, USA """ image = np.atleast_2d(image) """ The first stage applies an optional global image normalisation equalisation that is designed to reduce the influence of illumination effects. In practice we use gamma (power law) compression, either computing the square root or the log of each colour channel. Image texture strength is typically proportional to the local surface illumination so this compression helps to reduce the effects of local shadowing and illumination variations. """ if image.ndim > 2: raise ValueError("Currently only supports grey-level images") if normalise: image = sqrt(image) """ The second stage computes first order image gradients. These capture contour, silhouette and some texture information, while providing further resistance to illumination variations. The locally dominant colour channel is used, which provides colour invariance to a large extent. Variant methods may also include second order image derivatives, which act as primitive bar detectors - a useful feature for capturing, e.g. bar like structures in bicycles and limbs in humans. """ if image.dtype.kind == 'u': # convert uint image to float # to avoid problems with subtracting unsigned numbers in np.diff() image = image.astype('float') gx = np.zeros(image.shape) gy = np.zeros(image.shape) gx[:, :-1] = np.diff(image, n=1, axis=1) gy[:-1, :] = np.diff(image, n=1, axis=0) """ The third stage aims to produce an encoding that is sensitive to local image content while remaining resistant to small changes in pose or appearance. The adopted method pools gradient orientation information locally in the same way as the SIFT [Lowe 2004] feature. The image window is divided into small spatial regions, called "cells". For each cell we accumulate a local 1-D histogram of gradient or edge orientations over all the pixels in the cell. This combined cell-level 1-D histogram forms the basic "orientation histogram" representation. Each orientation histogram divides the gradient angle range into a fixed number of predetermined bins. The gradient magnitudes of the pixels in the cell are used to vote into the orientation histogram. """ magnitude = sqrt(gx**2 + gy**2) orientation = arctan2(gy, gx) * (180 / pi) % 180 sy, sx = image.shape cx, cy = pixels_per_cell bx, by = cells_per_block n_cellsx = int(np.floor(sx // cx)) # number of cells in x n_cellsy = int(np.floor(sy // cy)) # number of cells in y # compute orientations integral images orientation_histogram = np.zeros((n_cellsy, n_cellsx, orientations)) subsample = np.index_exp[cy / 2:cy * n_cellsy:cy, cx / 2:cx * n_cellsx:cx] for i in range(orientations): #create new integral image for this orientation # isolate orientations in this range temp_ori = np.where(orientation < 180.0 / orientations * (i + 1), orientation, -1) temp_ori = np.where(orientation >= 180.0 / orientations * i, temp_ori, -1) # select magnitudes for those orientations cond2 = temp_ori > -1 temp_mag = np.where(cond2, magnitude, 0) temp_filt = uniform_filter(temp_mag, size=(cy, cx)) orientation_histogram[:, :, i] = temp_filt[subsample] # now for each cell, compute the histogram hog_image = None if visualise: from skimage import draw radius = min(cx, cy) // 2 - 1 hog_image = np.zeros((sy, sx), dtype=float) for x in range(n_cellsx): for y in range(n_cellsy): for o in range(orientations): centre = tuple([y * cy + cy // 2, x * cx + cx // 2]) dx = radius * cos(float(o) / orientations * np.pi) dy = radius * sin(float(o) / orientations * np.pi) rr, cc = draw.line(int(centre[0] - dx), int(centre[1] - dy), int(centre[0] + dx), int(centre[1] + dy)) hog_image[rr, cc] += orientation_histogram[y, x, o] """ The fourth stage computes normalisation, which takes local groups of cells and contrast normalises their overall responses before passing to next stage. Normalisation introduces better invariance to illumination, shadowing, and edge contrast. It is performed by accumulating a measure of local histogram "energy" over local groups of cells that we call "blocks". The result is used to normalise each cell in the block. Typically each individual cell is shared between several blocks, but its normalisations are block dependent and thus different. The cell thus appears several times in the final output vector with different normalisations. This may seem redundant but it improves the performance. We refer to the normalised block descriptors as Histogram of Oriented Gradient (HOG) descriptors. """ n_blocksx = (n_cellsx - bx) + 1 n_blocksy = (n_cellsy - by) + 1 normalised_blocks = np.zeros((n_blocksy, n_blocksx, by, bx, orientations)) for x in range(n_blocksx): for y in range(n_blocksy): block = orientation_histogram[y:y + by, x:x + bx, :] eps = 1e-5 normalised_blocks[y, x, :] = block / sqrt(block.sum()**2 + eps) """ The final step collects the HOG descriptors from all blocks of a dense overlapping grid of blocks covering the detection window into a combined feature vector for use in the window classifier. """ if visualise: return normalised_blocks.ravel(), hog_image else: return normalised_blocks.ravel() scikit-image-0.9.3/skimage/feature/_template.pyx000066400000000000000000000070741223313777300217000ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False """ Template matching using normalized cross-correlation. We use fast normalized cross-correlation algorithm (see [1]_ and [2]_) to compute match probability. This algorithm calculates the normalized cross-correlation of an image, `I`, with a template `T` according to the following equation:: sum{ I(x, y) [T(x, y) - ] } ------------------------------------------------------- sqrt(sum{ [I(x, y) - ]^2 } sum{ [T(x, y) - ]^2 }) where `` is the average of the template, and `` is the average of the image *coincident with the template*, and sums are over the template and the image window coincident with the template. Note that the numerator is simply the cross-correlation of the image and the zero-mean template. To speed up calculations, we use summed-area tables (a.k.a. integral images) to quickly calculate sums of image windows inside the loop. This step relies on the following relation (see Eq. 10 of [1]):: sum{ [I(x, y) - ]^2 } = sum{ I^2(x, y) } - [sum{ I(x, y) }]^2 / N_x N_y (Without this relation, you would need to subtract each image-window mean from the image window *before* squaring.) .. [1] Briechle and Hanebeck, "Template Matching using Fast Normalized Cross Correlation", Proceedings of the SPIE (2001). .. [2] J. P. Lewis, "Fast Normalized Cross-Correlation", Industrial Light and Magic. """ import numpy as np from scipy.signal import fftconvolve cimport numpy as cnp from libc.math cimport sqrt, fabs from skimage._shared.transform cimport integrate from skimage.transform import integral def match_template(cnp.ndarray[float, ndim=2, mode="c"] image, cnp.ndarray[float, ndim=2, mode="c"] template): cdef float[:, ::1] corr cdef float[:, ::1] image_sat cdef float[:, ::1] image_sqr_sat cdef float template_mean = np.mean(template) cdef float template_ssd cdef float inv_area cdef Py_ssize_t r, c, r_end, c_end cdef Py_ssize_t template_rows = template.shape[0] cdef Py_ssize_t template_cols = template.shape[1] cdef float den, window_sqr_sum, window_mean_sqr, window_sum image_sat = integral.integral_image(image) image_sqr_sat = integral.integral_image(image**2) template -= template_mean template_ssd = np.sum(template**2) # use inversed area for accuracy inv_area = 1.0 / (template.shape[0] * template.shape[1]) # when `dtype=float` is used, ascontiguousarray returns ``double``. corr = np.ascontiguousarray(fftconvolve(image, template[::-1, ::-1], mode="valid"), dtype=np.float32) # move window through convolution results, normalizing in the process for r in range(corr.shape[0]): for c in range(corr.shape[1]): # subtract 1 because `i_end` and `c_end` are used for indexing into # summed-area table, instead of slicing windows of the image. r_end = r + template_rows - 1 c_end = c + template_cols - 1 window_sum = integrate(image_sat, r, c, r_end, c_end) window_mean_sqr = window_sum * window_sum * inv_area window_sqr_sum = integrate(image_sqr_sat, r, c, r_end, c_end) if window_sqr_sum <= window_mean_sqr: corr[r, c] = 0 continue den = sqrt((window_sqr_sum - window_mean_sqr) * template_ssd) corr[r, c] /= den return np.asarray(corr) scikit-image-0.9.3/skimage/feature/_texture.pyx000066400000000000000000000224031223313777300215560ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cimport numpy as cnp from libc.math cimport sin, cos, abs from skimage._shared.interpolation cimport bilinear_interpolation def _glcm_loop(cnp.uint8_t[:, ::1] image, double[:] distances, double[:] angles, Py_ssize_t levels, cnp.uint32_t[:, :, :, ::1] out): """Perform co-occurrence matrix accumulation. Parameters ---------- image : ndarray Input image, which is converted to the uint8 data type. distances : ndarray List of pixel pair distance offsets. angles : ndarray List of pixel pair angles in radians. levels : int The input image should contain integers in [0, levels-1], where levels indicate the number of grey-levels counted (typically 256 for an 8-bit image) out : ndarray On input a 4D array of zeros, and on output it contains the results of the GLCM computation. """ cdef: Py_ssize_t a_idx, d_idx, r, c, rows, cols, row, col cnp.uint8_t i, j cnp.float64_t angle, distance rows = image.shape[0] cols = image.shape[1] for a_idx in range(len(angles)): angle = angles[a_idx] for d_idx in range(len(distances)): distance = distances[d_idx] for r in range(rows): for c in range(cols): i = image[r, c] # compute the location of the offset pixel row = r + (sin(angle) * distance + 0.5) col = c + (cos(angle) * distance + 0.5) # make sure the offset is within bounds if row >= 0 and row < rows and \ col >= 0 and col < cols: j = image[row, col] if i >= 0 and i < levels and \ j >= 0 and j < levels: out[i, j, d_idx, a_idx] += 1 cdef inline int _bit_rotate_right(int value, int length): """Cyclic bit shift to the right. Parameters ---------- value : int integer value to shift length : int number of bits of integer """ return (value >> 1) | ((value & 1) << (length - 1)) def _local_binary_pattern(double[:, ::1] image, int P, float R, char method='D'): """Gray scale and rotation invariant LBP (Local Binary Patterns). LBP is an invariant descriptor that can be used for texture classification. Parameters ---------- image : (N, M) double array Graylevel image. P : int Number of circularly symmetric neighbour set points (quantization of the angular space). R : float Radius of circle (spatial resolution of the operator). method : {'D', 'R', 'U', 'N', 'V'} Method to determine the pattern. * 'D': 'default' * 'R': 'ror' * 'U': 'uniform' * 'N': 'nri_uniform' * 'V': 'var' Returns ------- output : (N, M) array LBP image. """ # texture weights cdef int[::1] weights = 2 ** np.arange(P, dtype=np.int32) # local position of texture elements rr = - R * np.sin(2 * np.pi * np.arange(P, dtype=np.double) / P) cc = R * np.cos(2 * np.pi * np.arange(P, dtype=np.double) / P) cdef double[::1] rp = np.round(rr, 5) cdef double[::1] cp = np.round(cc, 5) # pre-allocate arrays for computation cdef double[::1] texture = np.zeros(P, dtype=np.double) cdef char[::1] signed_texture = np.zeros(P, dtype=np.int8) cdef int[::1] rotation_chain = np.zeros(P, dtype=np.int32) output_shape = (image.shape[0], image.shape[1]) cdef double[:, ::1] output = np.zeros(output_shape, dtype=np.double) cdef Py_ssize_t rows = image.shape[0] cdef Py_ssize_t cols = image.shape[1] cdef double lbp cdef Py_ssize_t r, c, changes, i cdef Py_ssize_t rot_index, n_ones cdef cnp.int8_t first_zero, first_one for r in range(image.shape[0]): for c in range(image.shape[1]): for i in range(P): texture[i] = bilinear_interpolation(&image[0, 0], rows, cols, r + rp[i], c + cp[i], 'C', 0) # signed / thresholded texture for i in range(P): if texture[i] - image[r, c] >= 0: signed_texture[i] = 1 else: signed_texture[i] = 0 lbp = 0 # if method == 'uniform' or method == 'var': if method == 'U' or method == 'N' or method == 'V': # determine number of 0 - 1 changes changes = 0 for i in range(P - 1): changes += abs(signed_texture[i] - signed_texture[i + 1]) if method == 'N': # Uniform local binary patterns are defined as patterns # with at most 2 value changes (from 0 to 1 or from 1 to # 0). Uniform patterns can be caraterized by their number # `n_ones` of 1. The possible values for `n_ones` range # from 0 to P. # Here is an example for P = 4: # n_ones=0: 0000 # n_ones=1: 0001, 1000, 0100, 0010 # n_ones=2: 0011, 1001, 1100, 0110 # n_ones=3: 0111, 1011, 1101, 1110 # n_ones=4: 1111 # # For a pattern of size P there are 2 constant patterns # corresponding to n_ones=0 and n_ones=P. For each other # value of `n_ones` , i.e n_ones=[1..P-1], there are P # possible patterns which are related to each other through # circular permutations. The total number of uniform # patterns is thus (2 + P * (P - 1)). # Given any pattern (uniform or not) we must be able to # associate a unique code: # 1. Constant patterns patterns (with n_ones=0 and # n_ones=P) and non uniform patterns are given fixed # code values. # 2. Other uniform patterns are indexed considering the # value of n_ones, and an index called 'rot_index' # reprenting the number of circular right shifts # required to obtain the pattern starting from a # reference position (corresponding to all zeros stacked # on the right). This number of rotations (or circular # right shifts) 'rot_index' is efficiently computed by # considering the positions of the first 1 and the first # 0 found in the pattern. if changes <= 2: # We have a uniform pattern n_ones = 0 # determies the number of ones first_one = -1 # position was the first one first_zero = -1 # position of the first zero for i in range(P): if signed_texture[i]: n_ones += 1 if first_one == -1: first_one = i else: if first_zero == -1: first_zero = i if n_ones == 0: lbp = 0 elif n_ones == P: lbp = P * (P - 1) + 1 else: if first_one == 0: rot_index = n_ones - first_zero else: rot_index = P - first_one lbp = 1 + (n_ones - 1) * P + rot_index else: # changes > 2 lbp = P * (P - 1) + 2 else: # method != 'N' if changes <= 2: for i in range(P): lbp += signed_texture[i] else: lbp = P + 1 if method == 'V': var = np.var(texture) if var != 0: lbp /= var else: lbp = np.nan else: # method == 'default' for i in range(P): lbp += signed_texture[i] * weights[i] # method == 'ror' if method == 'R': # shift LBP P times to the right and get minimum value rotation_chain[0] = lbp for i in range(1, P): rotation_chain[i] = \ _bit_rotate_right(rotation_chain[i - 1], P) lbp = rotation_chain[0] for i in range(1, P): lbp = min(lbp, rotation_chain[i]) output[r, c] = lbp return np.asarray(output) scikit-image-0.9.3/skimage/feature/censure.py000066400000000000000000000236261223313777300212030ustar00rootroot00000000000000import numpy as np from scipy.ndimage.filters import maximum_filter, minimum_filter, convolve from skimage.transform import integral_image from skimage.feature.corner import _compute_auto_correlation from skimage.util import img_as_float from skimage.morphology import octagon, star from skimage.feature.util import _mask_border_keypoints from skimage.feature.censure_cy import _censure_dob_loop # The paper(Reference [1]) mentions the sizes of the Octagon shaped filter # kernel for the first seven scales only. The sizes of the later scales # have been extrapolated based on the following statement in the paper. # "These octagons scale linearly and were experimentally chosen to correspond # to the seven DOBs described in the previous section." OCTAGON_OUTER_SHAPE = [(5, 2), (5, 3), (7, 3), (9, 4), (9, 7), (13, 7), (15, 10), (15, 11), (15, 12), (17, 13), (17, 14)] OCTAGON_INNER_SHAPE = [(3, 0), (3, 1), (3, 2), (5, 2), (5, 3), (5, 4), (5, 5), (7, 5), (7, 6), (9, 6), (9, 7)] # The sizes for the STAR shaped filter kernel for different scales have been # taken from the OpenCV implementation. STAR_SHAPE = [1, 2, 3, 4, 6, 8, 11, 12, 16, 22, 23, 32, 45, 46, 64, 90, 128] STAR_FILTER_SHAPE = [(1, 0), (3, 1), (4, 2), (5, 3), (7, 4), (8, 5), (9, 6), (11, 8), (13, 10), (14, 11), (15, 12), (16, 14)] def _filter_image(image, min_scale, max_scale, mode): response = np.zeros((image.shape[0], image.shape[1], max_scale - min_scale + 1), dtype=np.double) if mode == 'dob': # make response[:, :, i] contiguous memory block item_size = response.itemsize response.strides = (item_size * response.shape[0], item_size, item_size * response.shape[0] * response.shape[1]) integral_img = integral_image(image) for i in range(max_scale - min_scale + 1): n = min_scale + i # Constant multipliers for the outer region and the inner region # of the bi-level filters with the constraint of keeping the # DC bias 0. inner_weight = (1.0 / (2 * n + 1)**2) outer_weight = (1.0 / (12 * n**2 + 4 * n)) _censure_dob_loop(n, integral_img, response[:, :, i], inner_weight, outer_weight) # NOTE : For the Octagon shaped filter, we implemented and evaluated the # slanted integral image based image filtering but the performance was # more or less equal to image filtering using # scipy.ndimage.filters.convolve(). Hence we have decided to use the # later for a much cleaner implementation. elif mode == 'octagon': # TODO : Decide the shapes of Octagon filters for scales > 7 for i in range(max_scale - min_scale + 1): mo, no = OCTAGON_OUTER_SHAPE[min_scale + i - 1] mi, ni = OCTAGON_INNER_SHAPE[min_scale + i - 1] response[:, :, i] = convolve(image, _octagon_filter_kernel(mo, no, mi, ni)) elif mode == 'star': for i in range(max_scale - min_scale + 1): m = STAR_SHAPE[STAR_FILTER_SHAPE[min_scale + i - 1][0]] n = STAR_SHAPE[STAR_FILTER_SHAPE[min_scale + i - 1][1]] response[:, :, i] = convolve(image, _star_filter_kernel(m, n)) return response def _octagon_filter_kernel(mo, no, mi, ni): outer = (mo + 2 * no)**2 - 2 * no * (no + 1) inner = (mi + 2 * ni)**2 - 2 * ni * (ni + 1) outer_weight = 1.0 / (outer - inner) inner_weight = 1.0 / inner c = ((mo + 2 * no) - (mi + 2 * ni)) // 2 outer_oct = octagon(mo, no) inner_oct = np.zeros((mo + 2 * no, mo + 2 * no)) inner_oct[c: -c, c: -c] = octagon(mi, ni) bfilter = (outer_weight * outer_oct - (outer_weight + inner_weight) * inner_oct) return bfilter def _star_filter_kernel(m, n): c = m + m // 2 - n - n // 2 outer_star = star(m) inner_star = np.zeros_like(outer_star) inner_star[c: -c, c: -c] = star(n) outer_weight = 1.0 / (np.sum(outer_star - inner_star)) inner_weight = 1.0 / np.sum(inner_star) bfilter = (outer_weight * outer_star - (outer_weight + inner_weight) * inner_star) return bfilter def _suppress_lines(feature_mask, image, sigma, line_threshold): Axx, Axy, Ayy = _compute_auto_correlation(image, sigma) feature_mask[(Axx + Ayy) * (Axx + Ayy) > line_threshold * (Axx * Ayy - Axy * Axy)] = False def keypoints_censure(image, min_scale=1, max_scale=7, mode='DoB', non_max_threshold=0.15, line_threshold=10): """**Experimental function**. Extracts CenSurE keypoints along with the corresponding scale using either Difference of Boxes, Octagon or STAR bi-level filter. Parameters ---------- image : 2D ndarray Input image. min_scale : int Minimum scale to extract keypoints from. max_scale : int Maximum scale to extract keypoints from. The keypoints will be extracted from all the scales except the first and the last i.e. from the scales in the range [min_scale + 1, max_scale - 1]. mode : {'DoB', 'Octagon', 'STAR'} Type of bi-level filter used to get the scales of the input image. Possible values are 'DoB', 'Octagon' and 'STAR'. The three modes represent the shape of the bi-level filters i.e. box(square), octagon and star respectively. For instance, a bi-level octagon filter consists of a smaller inner octagon and a larger outer octagon with the filter weights being uniformly negative in both the inner octagon while uniformly positive in the difference region. Use STAR and Octagon for better features and DoB for better performance. non_max_threshold : float Threshold value used to suppress maximas and minimas with a weak magnitude response obtained after Non-Maximal Suppression. line_threshold : float Threshold for rejecting interest points which have ratio of principal curvatures greater than this value. Returns ------- keypoints : (N, 2) array Location of the extracted keypoints in the ``(row, col)`` format. scales : (N, 1) array The corresponding scale of the N extracted keypoints. References ---------- .. [1] Motilal Agrawal, Kurt Konolige and Morten Rufus Blas "CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching", http://link.springer.com/content/pdf/10.1007%2F978-3-540-88693-8_8.pdf .. [2] Adam Schmidt, Marek Kraft, Michal Fularz and Zuzanna Domagala "Comparative Assessment of Point Feature Detectors and Descriptors in the Context of Robot Navigation" http://www.jamris.org/01_2013/saveas.php?QUEST=JAMRIS_No01_2013_P_11-20.pdf """ # (1) First we generate the required scales on the input grayscale image # using a bi-level filter and stack them up in `filter_response`. # (2) We then perform Non-Maximal suppression in 3 x 3 x 3 window on the # filter_response to suppress points that are neither minima or maxima in # 3 x 3 x 3 neighbourhood. We obtain a boolean ndarray `feature_mask` # containing all the minimas and maximas in `filter_response` as True. # (3) Then we suppress all the points in the `feature_mask` for which the # corresponding point in the image at a particular scale has the ratio of # principal curvatures greater than `line_threshold`. # (4) Finally, we remove the border keypoints and return the keypoints # along with its corresponding scale. image = np.squeeze(image) if image.ndim != 2: raise ValueError("Only 2-D gray-scale images supported.") mode = mode.lower() if mode not in ('dob', 'octagon', 'star'): raise ValueError('Mode must be one of "DoB", "Octagon", "STAR".') if min_scale < 1 or max_scale < 1 or max_scale - min_scale < 2: raise ValueError('The scales must be >= 1 and the number of scales ' 'should be >= 3.') image = img_as_float(image) image = np.ascontiguousarray(image) # Generating all the scales filter_response = _filter_image(image, min_scale, max_scale, mode) # Suppressing points that are neither minima or maxima in their 3 x 3 x 3 # neighbourhood to zero minimas = minimum_filter(filter_response, (3, 3, 3)) == filter_response maximas = maximum_filter(filter_response, (3, 3, 3)) == filter_response feature_mask = minimas | maximas feature_mask[filter_response < non_max_threshold] = False for i in range(1, max_scale - min_scale): # sigma = (window_size - 1) / 6.0, so the window covers > 99% of the # kernel's distribution # window_size = 7 + 2 * (min_scale - 1 + i) # Hence sigma = 1 + (min_scale - 1 + i)/ 3.0 _suppress_lines(feature_mask[:, :, i], image, (1 + (min_scale + i - 1) / 3.0), line_threshold) rows, cols, scales = np.nonzero(feature_mask[..., 1:max_scale - min_scale]) keypoints = np.column_stack([rows, cols]) scales = scales + min_scale + 1 if mode == 'dob': return keypoints, scales cumulative_mask = np.zeros(keypoints.shape[0], dtype=np.bool) if mode == 'octagon': for i in range(min_scale + 1, max_scale): c = (OCTAGON_OUTER_SHAPE[i - 1][0] - 1) // 2 \ + OCTAGON_OUTER_SHAPE[i - 1][1] cumulative_mask |= _mask_border_keypoints(image, keypoints, c) \ & (scales == i) elif mode == 'star': for i in range(min_scale + 1, max_scale): c = STAR_SHAPE[STAR_FILTER_SHAPE[i - 1][0]] \ + STAR_SHAPE[STAR_FILTER_SHAPE[i - 1][0]] // 2 cumulative_mask |= _mask_border_keypoints(image, keypoints, c) \ & (scales == i) return keypoints[cumulative_mask], scales[cumulative_mask] scikit-image-0.9.3/skimage/feature/censure_cy.pyx000066400000000000000000000053471223313777300220660ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False def _censure_dob_loop(Py_ssize_t n, double[:, ::1] integral_img, double[:, ::1] filtered_image, double inner_weight, double outer_weight): # This function calculates the value in the DoB filtered image using # integral images. If r = right. l = left, u = up, d = down, the sum of # pixel values in the rectangle formed by (u, l), (u, r), (d, r), (d, l) # is calculated as I(d, r) + I(u - 1, l - 1) - I(u - 1, r) - I(d, l - 1). cdef Py_ssize_t i, j cdef double inner, outer cdef Py_ssize_t n2 = 2 * n cdef double total_weight = inner_weight + outer_weight # top-left pixel inner = (integral_img[n2 + n, n2 + n] + integral_img[n2 - n - 1, n2 - n - 1] - integral_img[n2 + n, n2 - n - 1] - integral_img[n2 - n - 1, n2 + n]) outer = integral_img[2 * n2, 2 * n2] filtered_image[n2, n2] = (outer_weight * outer - total_weight * inner) # left column for i in range(n2 + 1, integral_img.shape[0] - n2): inner = (integral_img[i + n, n2 + n] + integral_img[i - n - 1, n2 - n - 1] - integral_img[i + n, n2 - n - 1] - integral_img[i - n - 1, n2 + n]) outer = (integral_img[i + n2, 2 * n2] - integral_img[i - n2 - 1, 2 * n2]) filtered_image[i, n2] = (outer_weight * outer - total_weight * inner) # top row for j in range(n2 + 1, integral_img.shape[1] - n2): inner = (integral_img[n2 + n, j + n] + integral_img[n2 - n - 1, j - n - 1] - integral_img[n2 + n, j - n - 1] - integral_img[n2 - n - 1, j + n]) outer = (integral_img[2 * n2, j + n2] - integral_img[2 * n2, j - n2 - 1]) filtered_image[n2, j] = (outer_weight * outer - total_weight * inner) # remaining block for i in range(n2 + 1, integral_img.shape[0] - n2): for j in range(n2 + 1, integral_img.shape[1] - n2): inner = (integral_img[i + n, j + n] + integral_img[i - n - 1, j - n - 1] - integral_img[i + n, j - n - 1] - integral_img[i - n - 1, j + n]) outer = (integral_img[i + n2, j + n2] + integral_img[i - n2 - 1, j - n2 - 1] - integral_img[i + n2, j - n2 - 1] - integral_img[i - n2 - 1, j + n2]) filtered_image[i, j] = (outer_weight * outer - total_weight * inner) scikit-image-0.9.3/skimage/feature/corner.py000066400000000000000000000365771223313777300210400ustar00rootroot00000000000000import numpy as np from scipy import ndimage from scipy import stats from skimage.color import rgb2grey from skimage.util import img_as_float from skimage.feature import peak_local_max def _compute_derivatives(image): """Compute derivatives in x and y direction using the Sobel operator. Parameters ---------- image : ndarray Input image. Returns ------- imx : ndarray Derivative in x-direction. imy : ndarray Derivative in y-direction. """ imy = ndimage.sobel(image, axis=0, mode='constant', cval=0) imx = ndimage.sobel(image, axis=1, mode='constant', cval=0) return imx, imy def _compute_auto_correlation(image, sigma): """Compute auto-correlation matrix using sum of squared differences. Parameters ---------- image : ndarray Input image. sigma : float Standard deviation used for the Gaussian kernel, which is used as weighting function for the auto-correlation matrix. Returns ------- Axx : ndarray Element of the auto-correlation matrix for each pixel in input image. Axy : ndarray Element of the auto-correlation matrix for each pixel in input image. Ayy : ndarray Element of the auto-correlation matrix for each pixel in input image. """ if image.ndim == 3: image = img_as_float(rgb2grey(image)) imx, imy = _compute_derivatives(image) # structure tensore Axx = ndimage.gaussian_filter(imx * imx, sigma, mode='constant', cval=0) Axy = ndimage.gaussian_filter(imx * imy, sigma, mode='constant', cval=0) Ayy = ndimage.gaussian_filter(imy * imy, sigma, mode='constant', cval=0) return Axx, Axy, Ayy def corner_kitchen_rosenfeld(image): """Compute Kitchen and Rosenfeld corner measure response image. The corner measure is calculated as follows:: (imxx * imy**2 + imyy * imx**2 - 2 * imxy * imx * imy) ------------------------------------------------------ (imx**2 + imy**2) Where imx and imy are the first and imxx, imxy, imyy the second derivatives. Parameters ---------- image : ndarray Input image. Returns ------- response : ndarray Kitchen and Rosenfeld response image. """ imx, imy = _compute_derivatives(image) imxx, imxy = _compute_derivatives(imx) imyx, imyy = _compute_derivatives(imy) numerator = (imxx * imy**2 + imyy * imx**2 - 2 * imxy * imx * imy) denominator = (imx**2 + imy**2) response = np.zeros_like(image, dtype=np.double) mask = denominator != 0 response[mask] = numerator[mask] / denominator[mask] return response def corner_harris(image, method='k', k=0.05, eps=1e-6, sigma=1): """Compute Harris corner measure response image. This corner detector uses information from the auto-correlation matrix A:: A = [(imx**2) (imx*imy)] = [Axx Axy] [(imx*imy) (imy**2)] [Axy Ayy] Where imx and imy are the first derivatives averaged with a gaussian filter. The corner measure is then defined as:: det(A) - k * trace(A)**2 or:: 2 * det(A) / (trace(A) + eps) Parameters ---------- image : ndarray Input image. method : {'k', 'eps'}, optional Method to compute the response image from the auto-correlation matrix. k : float, optional Sensitivity factor to separate corners from edges, typically in range `[0, 0.2]`. Small values of k result in detection of sharp corners. eps : float, optional Normalisation factor (Noble's corner measure). sigma : float, optional Standard deviation used for the Gaussian kernel, which is used as weighting function for the auto-correlation matrix. Returns ------- response : ndarray Harris response image. References ---------- .. [1] http://kiwi.cs.dal.ca/~dparks/CornerDetection/harris.htm .. [2] http://en.wikipedia.org/wiki/Corner_detection Examples -------- >>> from skimage.feature import corner_harris, corner_peaks >>> square = np.zeros([10, 10]) >>> square[2:8, 2:8] = 1 >>> square array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) >>> corner_peaks(corner_harris(square), min_distance=1) array([[2, 2], [2, 7], [7, 2], [7, 7]]) """ Axx, Axy, Ayy = _compute_auto_correlation(image, sigma) # determinant detA = Axx * Ayy - Axy**2 # trace traceA = Axx + Ayy if method == 'k': response = detA - k * traceA**2 else: response = 2 * detA / (traceA + eps) return response def corner_shi_tomasi(image, sigma=1): """Compute Shi-Tomasi (Kanade-Tomasi) corner measure response image. This corner detector uses information from the auto-correlation matrix A:: A = [(imx**2) (imx*imy)] = [Axx Axy] [(imx*imy) (imy**2)] [Axy Ayy] Where imx and imy are the first derivatives averaged with a gaussian filter. The corner measure is then defined as the smaller eigenvalue of A:: ((Axx + Ayy) - sqrt((Axx - Ayy)**2 + 4 * Axy**2)) / 2 Parameters ---------- image : ndarray Input image. sigma : float, optional Standard deviation used for the Gaussian kernel, which is used as weighting function for the auto-correlation matrix. Returns ------- response : ndarray Shi-Tomasi response image. References ---------- .. [1] http://kiwi.cs.dal.ca/~dparks/CornerDetection/harris.htm .. [2] http://en.wikipedia.org/wiki/Corner_detection Examples -------- >>> from skimage.feature import corner_shi_tomasi, corner_peaks >>> square = np.zeros([10, 10]) >>> square[2:8, 2:8] = 1 >>> square array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) >>> corner_peaks(corner_shi_tomasi(square), min_distance=1) array([[2, 2], [2, 7], [7, 2], [7, 7]]) """ Axx, Axy, Ayy = _compute_auto_correlation(image, sigma) # minimum eigenvalue of A response = ((Axx + Ayy) - np.sqrt((Axx - Ayy)**2 + 4 * Axy**2)) / 2 return response def corner_foerstner(image, sigma=1): """Compute Foerstner corner measure response image. This corner detector uses information from the auto-correlation matrix A:: A = [(imx**2) (imx*imy)] = [Axx Axy] [(imx*imy) (imy**2)] [Axy Ayy] Where imx and imy are the first derivatives averaged with a gaussian filter. The corner measure is then defined as:: w = det(A) / trace(A) (size of error ellipse) q = 4 * det(A) / trace(A)**2 (roundness of error ellipse) Parameters ---------- image : ndarray Input image. sigma : float, optional Standard deviation used for the Gaussian kernel, which is used as weighting function for the auto-correlation matrix. Returns ------- w : ndarray Error ellipse sizes. q : ndarray Roundness of error ellipse. References ---------- .. [1] http://www.ipb.uni-bonn.de/uploads/tx_ikgpublication/foerstner87.fast.pdf .. [2] http://en.wikipedia.org/wiki/Corner_detection Examples -------- >>> from skimage.feature import corner_foerstner, corner_peaks >>> square = np.zeros([10, 10]) >>> square[2:8, 2:8] = 1 >>> square array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) >>> w, q = corner_foerstner(square) >>> accuracy_thresh = 0.5 >>> roundness_thresh = 0.3 >>> foerstner = (q > roundness_thresh) * (w > accuracy_thresh) * w >>> corner_peaks(foerstner, min_distance=1) array([[2, 2], [2, 7], [7, 2], [7, 7]]) """ Axx, Axy, Ayy = _compute_auto_correlation(image, sigma) # determinant detA = Axx * Ayy - Axy**2 # trace traceA = Axx + Ayy w = np.zeros_like(image, dtype=np.double) q = np.zeros_like(image, dtype=np.double) mask = traceA != 0 w[mask] = detA[mask] / traceA[mask] q[mask] = 4 * detA[mask] / traceA[mask]**2 return w, q def corner_subpix(image, corners, window_size=11, alpha=0.99): """Determine subpixel position of corners. Parameters ---------- image : ndarray Input image. corners : (N, 2) ndarray Corner coordinates `(row, col)`. window_size : int, optional Search window size for subpixel estimation. alpha : float, optional Significance level for point classification. Returns ------- positions : (N, 2) ndarray Subpixel corner positions. NaN for "not classified" corners. References ---------- .. [1] http://www.ipb.uni-bonn.de/uploads/tx_ikgpublication/\ foerstner87.fast.pdf .. [2] http://en.wikipedia.org/wiki/Corner_detection """ # window extent in one direction wext = (window_size - 1) / 2 # normal equation arrays N_dot = np.zeros((2, 2), dtype=np.double) N_edge = np.zeros((2, 2), dtype=np.double) b_dot = np.zeros((2, ), dtype=np.double) b_edge = np.zeros((2, ), dtype=np.double) # critical statistical test values redundancy = window_size**2 - 2 t_crit_dot = stats.f.isf(1 - alpha, redundancy, redundancy) t_crit_edge = stats.f.isf(alpha, redundancy, redundancy) # coordinates of pixels within window y, x = np.mgrid[- wext:wext + 1, - wext:wext + 1] corners_subpix = np.zeros_like(corners, dtype=np.double) for i, (y0, x0) in enumerate(corners): # crop window around corner + border for sobel operator miny = y0 - wext - 1 maxy = y0 + wext + 2 minx = x0 - wext - 1 maxx = x0 + wext + 2 window = image[miny:maxy, minx:maxx] winx, winy = _compute_derivatives(window) # compute gradient suares and remove border winx_winx = (winx * winx)[1:-1, 1:-1] winx_winy = (winx * winy)[1:-1, 1:-1] winy_winy = (winy * winy)[1:-1, 1:-1] # sum of squared differences (mean instead of gaussian filter) Axx = np.sum(winx_winx) Axy = np.sum(winx_winy) Ayy = np.sum(winy_winy) # sum of squared differences weighted with coordinates # (mean instead of gaussian filter) bxx_x = np.sum(winx_winx * x) bxx_y = np.sum(winx_winx * y) bxy_x = np.sum(winx_winy * x) bxy_y = np.sum(winx_winy * y) byy_x = np.sum(winy_winy * x) byy_y = np.sum(winy_winy * y) # normal equations for subpixel position N_dot[0, 0] = Axx N_dot[0, 1] = N_dot[1, 0] = - Axy N_dot[1, 1] = Ayy N_edge[0, 0] = Ayy N_edge[0, 1] = N_edge[1, 0] = Axy N_edge[1, 1] = Axx b_dot[:] = bxx_y - bxy_x, byy_x - bxy_y b_edge[:] = byy_y + bxy_x, bxx_x + bxy_y # estimated positions est_dot = np.linalg.solve(N_dot, b_dot) est_edge = np.linalg.solve(N_edge, b_edge) # residuals ry_dot = y - est_dot[0] rx_dot = x - est_dot[1] ry_edge = y - est_edge[0] rx_edge = x - est_edge[1] # squared residuals rxx_dot = rx_dot * rx_dot rxy_dot = rx_dot * ry_dot ryy_dot = ry_dot * ry_dot rxx_edge = rx_edge * rx_edge rxy_edge = rx_edge * ry_edge ryy_edge = ry_edge * ry_edge # determine corner class (dot or edge) # variance for different models var_dot = np.sum(winx_winx * ryy_dot - 2 * winx_winy * rxy_dot \ + winy_winy * rxx_dot) var_edge = np.sum(winy_winy * ryy_edge + 2 * winx_winy * rxy_edge \ + winx_winx * rxx_edge) # test value (F-distributed) t = var_edge / var_dot # 1 for edge, -1 for dot, 0 for "not classified" corner_class = (t < t_crit_edge) - (t > t_crit_dot) if corner_class == - 1: corners_subpix[i, :] = y0 + est_dot[0], x0 + est_dot[1] elif corner_class == 0: corners_subpix[i, :] = np.nan, np.nan elif corner_class == 1: corners_subpix[i, :] = y0 + est_edge[0], x0 + est_edge[1] return corners_subpix def corner_peaks(image, min_distance=10, threshold_abs=0, threshold_rel=0.1, exclude_border=True, indices=True, num_peaks=np.inf, footprint=None, labels=None): """Find corners in corner measure response image. This differs from `skimage.feature.peak_local_max` in that it suppresses multiple connected peaks with the same accumulator value. Parameters ---------- See `skimage.feature.peak_local_max`. Returns ------- See `skimage.feature.peak_local_max`. Examples -------- >>> from skimage.feature import peak_local_max, corner_peaks >>> response = np.zeros((5, 5)) >>> response[2:4, 2:4] = 1 >>> response array([[ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 1., 1., 0.], [ 0., 0., 1., 1., 0.], [ 0., 0., 0., 0., 0.]]) >>> peak_local_max(response, exclude_border=False) array([[2, 2], [2, 3], [3, 2], [3, 3]]) >>> corner_peaks(response, exclude_border=False) array([[2, 2]]) >>> corner_peaks(response, exclude_border=False, min_distance=0) array([[2, 2], [2, 3], [3, 2], [3, 3]]) """ peaks = peak_local_max(image, min_distance=min_distance, threshold_abs=threshold_abs, threshold_rel=threshold_rel, exclude_border=exclude_border, indices=False, num_peaks=num_peaks, footprint=footprint, labels=labels) if min_distance > 0: coords = np.transpose(peaks.nonzero()) for r, c in coords: if peaks[r, c]: peaks[r - min_distance:r + min_distance + 1, c - min_distance:c + min_distance + 1] = False peaks[r, c] = True if indices is True: return np.transpose(peaks.nonzero()) else: return peaks scikit-image-0.9.3/skimage/feature/corner_cy.pyx000066400000000000000000000054051223313777300217050ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cimport numpy as cnp from libc.float cimport DBL_MAX from skimage.color import rgb2grey from skimage.util import img_as_float def corner_moravec(image, Py_ssize_t window_size=1): """Compute Moravec corner measure response image. This is one of the simplest corner detectors and is comparatively fast but has several limitations (e.g. not rotation invariant). Parameters ---------- image : ndarray Input image. window_size : int, optional (default 1) Window size. Returns ------- response : ndarray Moravec response image. References ---------- ..[1] http://kiwi.cs.dal.ca/~dparks/CornerDetection/moravec.htm ..[2] http://en.wikipedia.org/wiki/Corner_detection Examples -------- >>> from skimage.feature import moravec, peak_local_max >>> square = np.zeros([7, 7]) >>> square[3, 3] = 1 >>> square array([[ 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 1., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0.]]) >>> moravec(square) array([[ 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 1., 1., 1., 0., 0.], [ 0., 0., 1., 2., 1., 0., 0.], [ 0., 0., 1., 1., 1., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0.]]) """ cdef Py_ssize_t rows = image.shape[0] cdef Py_ssize_t cols = image.shape[1] cdef double[:, ::1] cimage = np.ascontiguousarray(img_as_float(image)) cdef double[:, ::1] out = np.zeros(image.shape, dtype=np.double) cdef double msum, min_msum cdef Py_ssize_t r, c, br, bc, mr, mc, a, b for r in range(2 * window_size, rows - 2 * window_size): for c in range(2 * window_size, cols - 2 * window_size): min_msum = DBL_MAX for br in range(r - window_size, r + window_size + 1): for bc in range(c - window_size, c + window_size + 1): if br != r and bc != c: msum = 0 for mr in range(- window_size, window_size + 1): for mc in range(- window_size, window_size + 1): msum += (cimage[r + mr, c + mc] - cimage[br + mr, bc + mc]) ** 2 min_msum = min(msum, min_msum) out[r, c] = min_msum return np.asarray(out) scikit-image-0.9.3/skimage/feature/peak.py000066400000000000000000000136461223313777300204600ustar00rootroot00000000000000import numpy as np import scipy.ndimage as ndi from ..filter import rank_order def peak_local_max(image, min_distance=10, threshold_abs=0, threshold_rel=0.1, exclude_border=True, indices=True, num_peaks=np.inf, footprint=None, labels=None): """ Find peaks in an image, and return them as coordinates or a boolean array. Peaks are the local maxima in a region of `2 * min_distance + 1` (i.e. peaks are separated by at least `min_distance`). NOTE: If peaks are flat (i.e. multiple adjacent pixels have identical intensities), the coordinates of all such pixels are returned. Parameters ---------- image : ndarray of floats Input image. min_distance : int Minimum number of pixels separating peaks in a region of `2 * min_distance + 1` (i.e. peaks are separated by at least `min_distance`). If `exclude_border` is True, this value also excludes a border `min_distance` from the image boundary. To find the maximum number of peaks, use `min_distance=1`. threshold_abs : float Minimum intensity of peaks. threshold_rel : float Minimum intensity of peaks calculated as `max(image) * threshold_rel`. exclude_border : bool If True, `min_distance` excludes peaks from the border of the image as well as from each other. indices : bool If True, the output will be an array representing peak coordinates. If False, the output will be a boolean array shaped as `image.shape` with peaks present at True elements. num_peaks : int Maximum number of peaks. When the number of peaks exceeds `num_peaks`, return `num_peaks` peaks based on highest peak intensity. footprint : ndarray of bools, optional If provided, `footprint == 1` represents the local region within which to search for peaks at every point in `image`. Overrides `min_distance`, except for border exclusion if `exclude_border=True`. labels : ndarray of ints, optional If provided, each unique region `labels == value` represents a unique region to search for peaks. Zero is reserved for background. Returns ------- output : (N, 2) array or ndarray of bools * If `indices = True` : (row, column) coordinates of peaks. * If `indices = False` : Boolean array shaped like `image`, with peaks represented by True values. Notes ----- The peak local maximum function returns the coordinates of local peaks (maxima) in a image. A maximum filter is used for finding local maxima. This operation dilates the original image. After comparison between dilated and original image, peak_local_max function returns the coordinates of peaks where dilated image = original. Examples -------- >>> im = np.zeros((7, 7)) >>> im[3, 4] = 1 >>> im[3, 2] = 1.5 >>> im array([[ 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 1.5, 0. , 1. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 0. , 0. , 0. ]]) >>> peak_local_max(im, min_distance=1) array([[3, 2], [3, 4]]) >>> peak_local_max(im, min_distance=2) array([[3, 2]]) """ out = np.zeros_like(image, dtype=np.bool) # In the case of labels, recursively build and return an output # operating on each label separately if labels is not None: label_values = np.unique(labels) # Reorder label values to have consecutive integers (no gaps) if np.any(np.diff(label_values) != 1): mask = labels >= 1 labels[mask] = 1 + rank_order(labels[mask])[0].astype(labels.dtype) labels = labels.astype(np.int32) # New values for new ordering label_values = np.unique(labels) for label in label_values[label_values != 0]: maskim = (labels == label) out += peak_local_max(image * maskim, min_distance=min_distance, threshold_abs=threshold_abs, threshold_rel=threshold_rel, exclude_border=exclude_border, indices=False, num_peaks=np.inf, footprint=footprint, labels=None) if indices is True: return np.transpose(out.nonzero()) else: return out.astype(np.bool) if np.all(image == image.flat[0]): if indices is True: return [] else: return out image = image.copy() # Non maximum filter if footprint is not None: image_max = ndi.maximum_filter(image, footprint=footprint, mode='constant') else: size = 2 * min_distance + 1 image_max = ndi.maximum_filter(image, size=size, mode='constant') mask = (image == image_max) image *= mask if exclude_border: # zero out the image borders for i in range(image.ndim): image = image.swapaxes(0, i) image[:min_distance] = 0 image[-min_distance:] = 0 image = image.swapaxes(0, i) # find top peak candidates above a threshold peak_threshold = max(np.max(image.ravel()) * threshold_rel, threshold_abs) # get coordinates of peaks coordinates = np.transpose((image > peak_threshold).nonzero()) if coordinates.shape[0] > num_peaks: intensities = image[coordinates[:, 0], coordinates[:, 1]] idx_maxsort = np.argsort(intensities)[::-1] coordinates = coordinates[idx_maxsort][:num_peaks] if indices is True: return coordinates else: nd_indices = tuple(coordinates.T) out[nd_indices] = True return out scikit-image-0.9.3/skimage/feature/setup.py000066400000000000000000000033241223313777300206700ustar00rootroot00000000000000#!/usr/bin/env python import os from skimage._build import cython base_path = os.path.abspath(os.path.dirname(__file__)) def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs config = Configuration('feature', parent_package, top_path) config.add_data_dir('tests') cython(['corner_cy.pyx'], working_path=base_path) cython(['censure_cy.pyx'], working_path=base_path) cython(['_brief_cy.pyx'], working_path=base_path) cython(['_texture.pyx'], working_path=base_path) cython(['_template.pyx'], working_path=base_path) config.add_extension('corner_cy', sources=['corner_cy.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('censure_cy', sources=['censure_cy.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_brief_cy', sources=['_brief_cy.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_texture', sources=['_texture.c'], include_dirs=[get_numpy_include_dirs(), '../_shared']) config.add_extension('_template', sources=['_template.c'], include_dirs=[get_numpy_include_dirs(), '../_shared']) return config if __name__ == '__main__': from numpy.distutils.core import setup setup(maintainer='scikit-image Developers', author='scikit-image Developers', maintainer_email='scikit-image@googlegroups.com', description='Features', url='https://github.com/scikit-image/scikit-image', license='SciPy License (BSD Style)', **(configuration(top_path='').todict()) ) scikit-image-0.9.3/skimage/feature/template.py000066400000000000000000000054661223313777300213540ustar00rootroot00000000000000"""template.py - Template matching """ import numpy as np from . import _template def match_template(image, template, pad_input=False): """Match a template to an image using normalized correlation. The output is an array with values between -1.0 and 1.0, which correspond to the probability that the template is found at that position. Parameters ---------- image : array_like Image to process. template : array_like Template to locate. pad_input : bool If True, pad `image` with image mean so that output is the same size as the image, and output values correspond to the template center. Otherwise, the output is an array with shape `(M - m + 1, N - n + 1)` for an `(M, N)` image and an `(m, n)` template, and matches correspond to origin (top-left corner) of the template. Returns ------- output : ndarray Correlation results between -1.0 and 1.0. For an `(M, N)` image and an `(m, n)` template, the `output` is `(M - m + 1, N - n + 1)` when `pad_input = False` and `(M, N)` when `pad_input = True`. Examples -------- >>> template = np.zeros((3, 3)) >>> template[1, 1] = 1 >>> print(template) [[ 0. 0. 0.] [ 0. 1. 0.] [ 0. 0. 0.]] >>> image = np.zeros((6, 6)) >>> image[1, 1] = 1 >>> image[4, 4] = -1 >>> print(image) [[ 0. 0. 0. 0. 0. 0.] [ 0. 1. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. -1. 0.] [ 0. 0. 0. 0. 0. 0.]] >>> result = match_template(image, template) >>> print(np.round(result, 3)) [[ 1. -0.125 0. 0. ] [-0.125 -0.125 0. 0. ] [ 0. 0. 0.125 0.125] [ 0. 0. 0.125 -1. ]] >>> result = match_template(image, template, pad_input=True) >>> print(np.round(result, 3)) [[-0.125 -0.125 -0.125 0. 0. 0. ] [-0.125 1. -0.125 0. 0. 0. ] [-0.125 -0.125 -0.125 0. 0. 0. ] [ 0. 0. 0. 0.125 0.125 0.125] [ 0. 0. 0. 0.125 -1. 0.125] [ 0. 0. 0. 0.125 0.125 0.125]] """ if np.any(np.less(image.shape, template.shape)): raise ValueError("Image must be larger than template.") image = np.ascontiguousarray(image, dtype=np.float32) template = np.ascontiguousarray(template, dtype=np.float32) if pad_input: pad_size = tuple(np.array(image.shape) + np.array(template.shape) - 1) pad_image = np.mean(image) * np.ones(pad_size, dtype=np.float32) h, w = image.shape i0, j0 = template.shape i0 /= 2 j0 /= 2 pad_image[i0:i0 + h, j0:j0 + w] = image image = pad_image result = _template.match_template(image, template) return result scikit-image-0.9.3/skimage/feature/tests/000077500000000000000000000000001223313777300203165ustar00rootroot00000000000000scikit-image-0.9.3/skimage/feature/tests/_test_brief.py000066400000000000000000000057101223313777300231600ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal, assert_raises from skimage import data from skimage import transform as tf from skimage.color import rgb2gray from skimage.feature import (brief, match_keypoints_brief, corner_peaks, corner_harris) def test_brief_color_image_unsupported_error(): """Brief descriptors can be evaluated on gray-scale images only.""" img = np.zeros((20, 20, 3)) keypoints = [[7, 5], [11, 13]] assert_raises(ValueError, brief, img, keypoints) def test_match_keypoints_brief_lena_translation(): """Test matched keypoints between lena image and its translated version.""" img = data.lena() img = rgb2gray(img) img.shape tform = tf.SimilarityTransform(scale=1, rotation=0, translation=(15, 20)) translated_img = tf.warp(img, tform) keypoints1 = corner_peaks(corner_harris(img), min_distance=5) descriptors1, keypoints1 = brief(img, keypoints1, descriptor_size=512) keypoints2 = corner_peaks(corner_harris(translated_img), min_distance=5) descriptors2, keypoints2 = brief(translated_img, keypoints2, descriptor_size=512) matched_keypoints = match_keypoints_brief(keypoints1, descriptors1, keypoints2, descriptors2, threshold=0.10) assert_array_equal(matched_keypoints[:, 0, :], matched_keypoints[:, 1, :] + [20, 15]) def test_match_keypoints_brief_lena_rotation(): """Verify matched keypoints result between lena image and its rotated version with the expected keypoint pairs.""" img = data.lena() img = rgb2gray(img) img.shape tform = tf.SimilarityTransform(scale=1, rotation=0.10, translation=(0, 0)) rotated_img = tf.warp(img, tform) keypoints1 = corner_peaks(corner_harris(img), min_distance=5) descriptors1, keypoints1 = brief(img, keypoints1, descriptor_size=512) keypoints2 = corner_peaks(corner_harris(rotated_img), min_distance=5) descriptors2, keypoints2 = brief(rotated_img, keypoints2, descriptor_size=512) matched_keypoints = match_keypoints_brief(keypoints1, descriptors1, keypoints2, descriptors2, threshold=0.07) expected = np.array([[[263, 272], [234, 298]], [[271, 120], [258, 146]], [[323, 164], [305, 195]], [[414, 70], [405, 111]], [[435, 181], [415, 223]], [[454, 176], [435, 221]]]) assert_array_equal(matched_keypoints, expected) if __name__ == '__main__': from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/feature/tests/_test_censure.py000066400000000000000000000065741223313777300235460ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal, assert_raises from skimage.data import moon from skimage.feature import keypoints_censure def test_keypoints_censure_color_image_unsupported_error(): """Censure keypoints can be extracted from gray-scale images only.""" img = np.zeros((20, 20, 3)) assert_raises(ValueError, keypoints_censure, img) def test_keypoints_censure_mode_validity_error(): """Mode argument in keypoints_censure can be either DoB, Octagon or STAR.""" img = np.zeros((20, 20)) assert_raises(ValueError, keypoints_censure, img, mode='dummy') def test_keypoints_censure_scale_range_error(): """Difference between the the max_scale and min_scale parameters in keypoints_censure should be greater than or equal to two.""" img = np.zeros((20, 20)) assert_raises(ValueError, keypoints_censure, img, min_scale=1, max_scale=2) def test_keypoints_censure_moon_image_dob(): """Verify the actual Censure keypoints and their corresponding scale with the expected values for DoB filter.""" img = moon() actual_kp_dob, actual_scale = keypoints_censure(img, 1, 7, 'DoB', 0.15) expected_kp_dob = np.array([[ 21, 497], [ 36, 46], [119, 350], [185, 177], [287, 250], [357, 239], [463, 116], [464, 132], [467, 260]]) expected_scale = np.array([3, 4, 4, 2, 2, 3, 2, 2, 2]) assert_array_equal(expected_kp_dob, actual_kp_dob) assert_array_equal(expected_scale, actual_scale) def test_keypoints_censure_moon_image_octagon(): """Verify the actual Censure keypoints and their corresponding scale with the expected values for Octagon filter.""" img = moon() actual_kp_octagon, actual_scale = keypoints_censure(img, 1, 7, 'Octagon', 0.15) expected_kp_octagon = np.array([[ 21, 496], [ 35, 46], [287, 250], [356, 239], [463, 116]]) expected_scale = np.array([3, 4, 2, 2, 2]) assert_array_equal(expected_kp_octagon, actual_kp_octagon) assert_array_equal(expected_scale, actual_scale) def test_keypoints_censure_moon_image_star(): """Verify the actual Censure keypoints and their corresponding scale with the expected values for STAR filter.""" img = moon() actual_kp_star, actual_scale = keypoints_censure(img, 1, 7, 'STAR', 0.15) expected_kp_star = np.array([[ 21, 497], [ 36, 46], [117, 356], [185, 177], [260, 227], [287, 250], [357, 239], [451, 281], [463, 116], [467, 260]]) expected_scale = np.array([3, 3, 6, 2, 3, 2, 3, 5, 2, 2]) assert_array_equal(expected_kp_star, actual_kp_star) assert_array_equal(expected_scale, actual_scale) if __name__ == '__main__': from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/feature/tests/test_corner.py000066400000000000000000000104051223313777300232170ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal from skimage import data from skimage import img_as_float from skimage.feature import (corner_moravec, corner_harris, corner_shi_tomasi, corner_subpix, peak_local_max, corner_peaks, corner_kitchen_rosenfeld, corner_foerstner) def test_square_image(): im = np.zeros((50, 50)).astype(float) im[:25, :25] = 1. # Moravec results = peak_local_max(corner_moravec(im)) # interest points along edge assert len(results) == 57 # Harris results = peak_local_max(corner_harris(im)) # interest at corner assert len(results) == 1 # Shi-Tomasi results = peak_local_max(corner_shi_tomasi(im)) # interest at corner assert len(results) == 1 def test_noisy_square_image(): im = np.zeros((50, 50)).astype(float) im[:25, :25] = 1. np.random.seed(seed=1234) im = im + np.random.uniform(size=im.shape) * .2 # Moravec results = peak_local_max(corner_moravec(im)) # undefined number of interest points assert results.any() # Harris results = peak_local_max(corner_harris(im, sigma=1.5)) assert len(results) == 1 # Shi-Tomasi results = peak_local_max(corner_shi_tomasi(im, sigma=1.5)) assert len(results) == 1 def test_squared_dot(): im = np.zeros((50, 50)) im[4:8, 4:8] = 1 im = img_as_float(im) # Moravec fails # Harris results = peak_local_max(corner_harris(im)) assert (results == np.array([[6, 6]])).all() # Shi-Tomasi results = peak_local_max(corner_shi_tomasi(im)) assert (results == np.array([[6, 6]])).all() def test_rotated_lena(): """ The harris filter should yield the same results with an image and it's rotation. """ im = img_as_float(data.lena().mean(axis=2)) im_rotated = im.T # Moravec results = peak_local_max(corner_moravec(im)) results_rotated = peak_local_max(corner_moravec(im_rotated)) assert (np.sort(results[:, 0]) == np.sort(results_rotated[:, 1])).all() assert (np.sort(results[:, 1]) == np.sort(results_rotated[:, 0])).all() # Harris results = peak_local_max(corner_harris(im)) results_rotated = peak_local_max(corner_harris(im_rotated)) assert (np.sort(results[:, 0]) == np.sort(results_rotated[:, 1])).all() assert (np.sort(results[:, 1]) == np.sort(results_rotated[:, 0])).all() # Shi-Tomasi results = peak_local_max(corner_shi_tomasi(im)) results_rotated = peak_local_max(corner_shi_tomasi(im_rotated)) assert (np.sort(results[:, 0]) == np.sort(results_rotated[:, 1])).all() assert (np.sort(results[:, 1]) == np.sort(results_rotated[:, 0])).all() def test_subpix(): img = np.zeros((50, 50)) img[:25,:25] = 255 img[25:,25:] = 255 corner = peak_local_max(corner_harris(img), num_peaks=1) subpix = corner_subpix(img, corner) assert_array_equal(subpix[0], (24.5, 24.5)) def test_num_peaks(): """For a bunch of different values of num_peaks, check that peak_local_max returns exactly the right amount of peaks. Test is run on Lena in order to produce a sufficient number of corners""" lena_corners = corner_harris(data.lena()) for i in range(20): n = np.random.random_integers(20) results = peak_local_max(lena_corners, num_peaks=n) assert (results.shape[0] == n) def test_corner_peaks(): response = np.zeros((5, 5)) response[2:4, 2:4] = 1 corners = corner_peaks(response, exclude_border=False) assert len(corners) == 1 corners = corner_peaks(response, exclude_border=False, min_distance=0) assert len(corners) == 4 def test_blank_image_nans(): """Some of the corner detectors had a weakness in terms of returning NaN when presented with regions of constant intensity. This should be fixed by now. We test whether each detector returns something finite in the case of constant input""" detectors = [corner_moravec, corner_harris, corner_shi_tomasi, corner_kitchen_rosenfeld, corner_foerstner] constant_image = np.zeros((20, 20)) for det in detectors: response = det(constant_image) assert np.all(np.isfinite(response)) if __name__ == '__main__': from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/feature/tests/test_daisy.py000066400000000000000000000061011223313777300230360ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_raises, assert_almost_equal from numpy import sqrt, ceil from skimage import data from skimage import img_as_float from skimage.feature import daisy def test_daisy_color_image_unsupported_error(): img = np.zeros((20, 20, 3)) assert_raises(ValueError, daisy, img) def test_daisy_desc_dims(): img = img_as_float(data.lena()[:128, :128].mean(axis=2)) rings = 2 histograms = 4 orientations = 3 descs = daisy(img, rings=rings, histograms=histograms, orientations=orientations) assert(descs.shape[2] == (rings * histograms + 1) * orientations) rings = 4 histograms = 5 orientations = 13 descs = daisy(img, rings=rings, histograms=histograms, orientations=orientations) assert(descs.shape[2] == (rings * histograms + 1) * orientations) def test_descs_shape(): img = img_as_float(data.lena()[:256, :256].mean(axis=2)) radius = 20 step = 8 descs = daisy(img, radius=radius, step=step) assert(descs.shape[0] == ceil((img.shape[0] - radius * 2) / float(step))) assert(descs.shape[1] == ceil((img.shape[1] - radius * 2) / float(step))) img = img[:-1, :-2] radius = 5 step = 3 descs = daisy(img, radius=radius, step=step) assert(descs.shape[0] == ceil((img.shape[0] - radius * 2) / float(step))) assert(descs.shape[1] == ceil((img.shape[1] - radius * 2) / float(step))) def test_daisy_incompatible_sigmas_and_radii(): img = img_as_float(data.lena()[:128, :128].mean(axis=2)) sigmas = [1, 2] radii = [1, 2] assert_raises(ValueError, daisy, img, sigmas=sigmas, ring_radii=radii) def test_daisy_normalization(): img = img_as_float(data.lena()[:64, :64].mean(axis=2)) descs = daisy(img, normalization='l1') for i in range(descs.shape[0]): for j in range(descs.shape[1]): assert_almost_equal(np.sum(descs[i, j, :]), 1) descs_ = daisy(img) assert_almost_equal(descs, descs_) descs = daisy(img, normalization='l2') for i in range(descs.shape[0]): for j in range(descs.shape[1]): assert_almost_equal(sqrt(np.sum(descs[i, j, :] ** 2)), 1) orientations = 8 descs = daisy(img, orientations=orientations, normalization='daisy') desc_dims = descs.shape[2] for i in range(descs.shape[0]): for j in range(descs.shape[1]): for k in range(0, desc_dims, orientations): assert_almost_equal(sqrt(np.sum( descs[i, j, k:k + orientations] ** 2)), 1) img = np.zeros((50, 50)) descs = daisy(img, normalization='off') for i in range(descs.shape[0]): for j in range(descs.shape[1]): assert_almost_equal(np.sum(descs[i, j, :]), 0) assert_raises(ValueError, daisy, img, normalization='does_not_exist') def test_daisy_visualization(): img = img_as_float(data.lena()[:128, :128].mean(axis=2)) descs, descs_img = daisy(img, visualize=True) assert(descs_img.shape == (128, 128, 3)) if __name__ == '__main__': from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/feature/tests/test_hog.py000066400000000000000000000144171223313777300225130ustar00rootroot00000000000000import numpy as np from scipy import ndimage from skimage import data from skimage import feature from skimage import img_as_float from skimage import draw from numpy.testing import (assert_raises, assert_almost_equal, ) def test_histogram_of_oriented_gradients(): img = img_as_float(data.lena()[:256, :].mean(axis=2)) fd = feature.hog(img, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(1, 1)) assert len(fd) == 9 * (256 // 8) * (512 // 8) def test_hog_image_size_cell_size_mismatch(): image = data.camera()[:150, :200] fd = feature.hog(image, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(1, 1)) assert len(fd) == 9 * (150 // 8) * (200 // 8) def test_hog_color_image_unsupported_error(): image = np.zeros((20, 20, 3)) assert_raises(ValueError, feature.hog, image) def test_hog_basic_orientations_and_data_types(): # scenario: # 1) create image (with float values) where upper half is filled by zeros, bottom half by 100 # 2) create unsigned integer version of this image # 3) calculate feature.hog() for both images, both with 'normalise' option enabled and disabled # 4) verify that all results are equal where expected # 5) verify that computed feature vector is as expected # 6) repeat the scenario for 90, 180 and 270 degrees rotated images # size of testing image width = height = 35 image0 = np.zeros((height, width), dtype='float') image0[height / 2:] = 100 for rot in range(4): # rotate by 0, 90, 180 and 270 degrees image_float = np.rot90(image0, rot) # create uint8 image from image_float image_uint8 = image_float.astype('uint8') (hog_float, hog_img_float) = feature.hog(image_float, orientations=4, pixels_per_cell=(8, 8), cells_per_block=(1, 1), visualise=True, normalise=False) (hog_uint8, hog_img_uint8) = feature.hog(image_uint8, orientations=4, pixels_per_cell=(8, 8), cells_per_block=(1, 1), visualise=True, normalise=False) (hog_float_norm, hog_img_float_norm) = feature.hog(image_float, orientations=4, pixels_per_cell=(8, 8), cells_per_block=(1, 1), visualise=True, normalise=True) (hog_uint8_norm, hog_img_uint8_norm) = feature.hog(image_uint8, orientations=4, pixels_per_cell=(8, 8), cells_per_block=(1, 1), visualise=True, normalise=True) # set to True to enable manual debugging with graphical output, # must be False for automatic testing if False: import matplotlib.pyplot as plt plt.figure() plt.subplot(2, 3, 1); plt.imshow(image_float); plt.colorbar(); plt.title('image') plt.subplot(2, 3, 2); plt.imshow(hog_img_float); plt.colorbar(); plt.title('HOG result visualisation (float img)') plt.subplot(2, 3, 5); plt.imshow(hog_img_uint8); plt.colorbar(); plt.title('HOG result visualisation (uint8 img)') plt.subplot(2, 3, 3); plt.imshow(hog_img_float_norm); plt.colorbar(); plt.title('HOG result (normalise) visualisation (float img)') plt.subplot(2, 3, 6); plt.imshow(hog_img_uint8_norm); plt.colorbar(); plt.title('HOG result (normalise) visualisation (uint8 img)') plt.show() # results (features and visualisation) for float and uint8 images must be almost equal assert_almost_equal(hog_float, hog_uint8) assert_almost_equal(hog_img_float, hog_img_uint8) # resulting features should be almost equal when 'normalise' is enabled or disabled (for current simple testing image) assert_almost_equal(hog_float, hog_float_norm, decimal=4) assert_almost_equal(hog_float, hog_uint8_norm, decimal=4) # reshape resulting feature vector to matrix with 4 columns (each corresponding to one of 4 directions), # only one direction should contain nonzero values (this is manually determined for testing image) actual = np.max(hog_float.reshape(-1, 4), axis=0) if rot in [0, 2]: # image is rotated by 0 and 180 degrees desired = [0, 0, 1, 0] elif rot in [1, 3]: # image is rotated by 90 and 270 degrees desired = [1, 0, 0, 0] else: raise Exception('Result is not determined for this rotation.') assert_almost_equal(actual, desired, decimal=2) def test_hog_orientations_circle(): # scenario: # 1) create image with blurred circle in the middle # 2) calculate feature.hog() # 3) verify that the resulting feature vector contains uniformly distributed values for all orientations, # i.e. no orientation is lost or emphasized # 4) repeat the scenario for other 'orientations' option # size of testing image width = height = 100 image = np.zeros((height, width)) rr, cc = draw.circle(int(height / 2), int(width / 2), int(width / 3)) image[rr, cc] = 100 image = ndimage.gaussian_filter(image, 2) for orientations in range(2, 15): (hog, hog_img) = feature.hog(image, orientations=orientations, pixels_per_cell=(8, 8), cells_per_block=(1, 1), visualise=True, normalise=False) # set to True to enable manual debugging with graphical output, # must be False for automatic testing if False: import matplotlib.pyplot as plt plt.figure() plt.subplot(1, 2, 1); plt.imshow(image); plt.colorbar(); plt.title('image_float') plt.subplot(1, 2, 2); plt.imshow(hog_img); plt.colorbar(); plt.title('HOG result visualisation, orientations=%d' % (orientations)) plt.show() # reshape resulting feature vector to matrix with N columns (each column corresponds to one direction), hog_matrix = hog.reshape(-1, orientations) # compute mean values in the resulting feature vector for each direction, # these values should be almost equal to the global mean value (since the image contains a circle), # i.e. all directions have same contribution to the result actual = np.mean(hog_matrix, axis=0) desired = np.mean(hog_matrix) assert_almost_equal(actual, desired, decimal=1) if __name__ == '__main__': from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/feature/tests/test_peak.py000066400000000000000000000226721223313777300226600ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_almost_equal as assert_close import scipy.ndimage from skimage.feature import peak def test_trivial_case(): trivial = np.zeros((25, 25)) peak_indices = peak.peak_local_max(trivial, min_distance=1, indices=True) assert not peak_indices # inherent boolean-ness of empty list peaks = peak.peak_local_max(trivial, min_distance=1, indices=False) assert (peaks.astype(np.bool) == trivial).all() def test_noisy_peaks(): peak_locations = [(7, 7), (7, 13), (13, 7), (13, 13)] # image with noise of amplitude 0.8 and peaks of amplitude 1 image = 0.8 * np.random.random((20, 20)) for r, c in peak_locations: image[r, c] = 1 peaks_detected = peak.peak_local_max(image, min_distance=5) assert len(peaks_detected) == len(peak_locations) for loc in peaks_detected: assert tuple(loc) in peak_locations def test_relative_threshold(): image = np.zeros((5, 5), dtype=np.uint8) image[1, 1] = 10 image[3, 3] = 20 peaks = peak.peak_local_max(image, min_distance=1, threshold_rel=0.5) assert len(peaks) == 1 assert_close(peaks, [(3, 3)]) def test_absolute_threshold(): image = np.zeros((5, 5), dtype=np.uint8) image[1, 1] = 10 image[3, 3] = 20 peaks = peak.peak_local_max(image, min_distance=1, threshold_abs=10) assert len(peaks) == 1 assert_close(peaks, [(3, 3)]) def test_constant_image(): image = 128 * np.ones((20, 20), dtype=np.uint8) peaks = peak.peak_local_max(image, min_distance=1) assert len(peaks) == 0 def test_flat_peak(): image = np.zeros((5, 5), dtype=np.uint8) image[1:3, 1:3] = 10 peaks = peak.peak_local_max(image, min_distance=1) assert len(peaks) == 4 def test_num_peaks(): image = np.zeros((7, 7), dtype=np.uint8) image[1, 1] = 10 image[1, 3] = 11 image[1, 5] = 12 image[3, 5] = 8 image[5, 3] = 7 assert len(peak.peak_local_max(image, min_distance=1)) == 5 peaks_limited = peak.peak_local_max(image, min_distance=1, num_peaks=2) assert len(peaks_limited) == 2 assert (1, 3) in peaks_limited assert (1, 5) in peaks_limited peaks_limited = peak.peak_local_max(image, min_distance=1, num_peaks=4) assert len(peaks_limited) == 4 assert (1, 3) in peaks_limited assert (1, 5) in peaks_limited assert (1, 1) in peaks_limited assert (3, 5) in peaks_limited def test_reorder_labels(): np.random.seed(21) image = np.random.uniform(size=(40, 60)) i, j = np.mgrid[0:40, 0:60] labels = 1 + (i >= 20) + (j >= 30) * 2 labels[labels == 4] = 5 i, j = np.mgrid[-3:4, -3:4] footprint = (i * i + j * j <= 9) expected = np.zeros(image.shape, float) for imin, imax in ((0, 20), (20, 40)): for jmin, jmax in ((0, 30), (30, 60)): expected[imin:imax, jmin:jmax] = scipy.ndimage.maximum_filter( image[imin:imax, jmin:jmax], footprint=footprint) expected = (expected == image) result = peak.peak_local_max(image, labels=labels, min_distance=1, threshold_rel=0, footprint=footprint, indices=False, exclude_border=False) assert (result == expected).all() def test_indices_with_labels(): np.random.seed(21) image = np.random.uniform(size=(40, 60)) i, j = np.mgrid[0:40, 0:60] labels = 1 + (i >= 20) + (j >= 30) * 2 i, j = np.mgrid[-3:4, -3:4] footprint = (i * i + j * j <= 9) expected = np.zeros(image.shape, float) for imin, imax in ((0, 20), (20, 40)): for jmin, jmax in ((0, 30), (30, 60)): expected[imin:imax, jmin:jmax] = scipy.ndimage.maximum_filter( image[imin:imax, jmin:jmax], footprint=footprint) expected = (expected == image) result = peak.peak_local_max(image, labels=labels, min_distance=1, threshold_rel=0, footprint=footprint, indices=True, exclude_border=False) assert (result == np.transpose(expected.nonzero())).all() def test_ndarray_indices_false(): nd_image = np.zeros((5,5,5)) nd_image[2,2,2] = 1 peaks = peak.peak_local_max(nd_image, min_distance=1, indices=False) assert (peaks == nd_image.astype(np.bool)).all() def test_ndarray_exclude_border(): nd_image = np.zeros((5,5,5)) nd_image[[1,0,0],[0,1,0],[0,0,1]] = 1 nd_image[3,0,0] = 1 nd_image[2,2,2] = 1 expected = np.zeros_like(nd_image, dtype=np.bool) expected[2,2,2] = True result = peak.peak_local_max(nd_image, min_distance=2, indices=False) assert (result == expected).all() def test_empty(): image = np.zeros((10, 20)) labels = np.zeros((10, 20), int) result = peak.peak_local_max(image, labels=labels, footprint=np.ones((3, 3), bool), min_distance=1, threshold_rel=0, indices=False, exclude_border=False) assert np.all(~ result) def test_one_point(): image = np.zeros((10, 20)) labels = np.zeros((10, 20), int) image[5, 5] = 1 labels[5, 5] = 1 result = peak.peak_local_max(image, labels=labels, footprint=np.ones((3, 3), bool), min_distance=1, threshold_rel=0, indices=False, exclude_border=False) assert np.all(result == (labels == 1)) def test_adjacent_and_same(): image = np.zeros((10, 20)) labels = np.zeros((10, 20), int) image[5, 5:6] = 1 labels[5, 5:6] = 1 result = peak.peak_local_max(image, labels=labels, footprint=np.ones((3, 3), bool), min_distance=1, threshold_rel=0, indices=False, exclude_border=False) assert np.all(result == (labels == 1)) def test_adjacent_and_different(): image = np.zeros((10, 20)) labels = np.zeros((10, 20), int) image[5, 5] = 1 image[5, 6] = .5 labels[5, 5:6] = 1 expected = (image == 1) result = peak.peak_local_max(image, labels=labels, footprint=np.ones((3, 3), bool), min_distance=1, threshold_rel=0, indices=False, exclude_border=False) assert np.all(result == expected) result = peak.peak_local_max(image, labels=labels, min_distance=1, threshold_rel=0, indices=False, exclude_border=False) assert np.all(result == expected) def test_not_adjacent_and_different(): image = np.zeros((10, 20)) labels = np.zeros((10, 20), int) image[5, 5] = 1 image[5, 8] = .5 labels[image > 0] = 1 expected = (labels == 1) result = peak.peak_local_max(image, labels=labels, footprint=np.ones((3, 3), bool), min_distance=1, threshold_rel=0, indices=False, exclude_border=False) assert np.all(result == expected) def test_two_objects(): image = np.zeros((10, 20)) labels = np.zeros((10, 20), int) image[5, 5] = 1 image[5, 15] = .5 labels[5, 5] = 1 labels[5, 15] = 2 expected = (labels > 0) result = peak.peak_local_max(image, labels=labels, footprint=np.ones((3, 3), bool), min_distance=1, threshold_rel=0, indices=False, exclude_border=False) assert np.all(result == expected) def test_adjacent_different_objects(): image = np.zeros((10, 20)) labels = np.zeros((10, 20), int) image[5, 5] = 1 image[5, 6] = .5 labels[5, 5] = 1 labels[5, 6] = 2 expected = (labels > 0) result = peak.peak_local_max(image, labels=labels, footprint=np.ones((3, 3), bool), min_distance=1, threshold_rel=0, indices=False, exclude_border=False) assert np.all(result == expected) def test_four_quadrants(): np.random.seed(21) image = np.random.uniform(size=(40, 60)) i, j = np.mgrid[0:40, 0:60] labels = 1 + (i >= 20) + (j >= 30) * 2 i, j = np.mgrid[-3:4, -3:4] footprint = (i * i + j * j <= 9) expected = np.zeros(image.shape, float) for imin, imax in ((0, 20), (20, 40)): for jmin, jmax in ((0, 30), (30, 60)): expected[imin:imax, jmin:jmax] = scipy.ndimage.maximum_filter( image[imin:imax, jmin:jmax], footprint=footprint) expected = (expected == image) result = peak.peak_local_max(image, labels=labels, footprint=footprint, min_distance=1, threshold_rel=0, indices=False, exclude_border=False) assert np.all(result == expected) def test_disk(): '''regression test of img-1194, footprint = [1] Test peak.peak_local_max when every point is a local maximum ''' np.random.seed(31) image = np.random.uniform(size=(10, 20)) footprint = np.array([[1]]) result = peak.peak_local_max(image, labels=np.ones((10, 20)), footprint=footprint, min_distance=1, threshold_rel=0, indices=False, exclude_border=False) assert np.all(result) result = peak.peak_local_max(image, footprint=footprint) assert np.all(result) if __name__ == '__main__': from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/feature/tests/test_template.py000066400000000000000000000102461223313777300235450ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_almost_equal as assert_close from skimage.morphology import diamond from skimage.feature import match_template, peak_local_max def test_template(): size = 100 # Float prefactors ensure that image range is between 0 and 1 image = 0.5 * np.ones((400, 400)) target = 0.1 * (np.tri(size) + np.tri(size)[::-1]) target_positions = [(50, 50), (200, 200)] for x, y in target_positions: image[x:x + size, y:y + size] = target np.random.seed(1) image += 0.1 * np.random.uniform(size=(400, 400)) result = match_template(image, target) delta = 5 positions = peak_local_max(result, min_distance=delta) if len(positions) > 2: # Keep the two maximum peaks. intensities = result[tuple(positions.T)] i_maxsort = np.argsort(intensities)[::-1] positions = positions[i_maxsort][:2] # Sort so that order matches `target_positions`. positions = positions[np.argsort(positions[:, 0])] for xy_target, xy in zip(target_positions, positions): yield assert_close, xy, xy_target def test_normalization(): """Test that `match_template` gives the correct normalization. Normalization gives 1 for a perfect match and -1 for an inverted-match. This test adds positive and negative squares to a zero-array and matches the array with a positive template. """ n = 5 N = 20 ipos, jpos = (2, 3) ineg, jneg = (12, 11) image = 0.5 * np.ones((N, N)) image[ipos:ipos + n, jpos:jpos + n] = 1 image[ineg:ineg + n, jneg:jneg + n] = 0 # white square with a black border template = np.zeros((n + 2, n + 2)) template[1:1 + n, 1:1 + n] = 1 result = match_template(image, template) # get the max and min results. sorted_result = np.argsort(result.flat) iflat_min = sorted_result[0] iflat_max = sorted_result[-1] min_result = np.unravel_index(iflat_min, result.shape) max_result = np.unravel_index(iflat_max, result.shape) # shift result by 1 because of template border assert np.all((np.array(min_result) + 1) == (ineg, jneg)) assert np.all((np.array(max_result) + 1) == (ipos, jpos)) assert np.allclose(result.flat[iflat_min], -1) assert np.allclose(result.flat[iflat_max], 1) def test_no_nans(): """Test that `match_template` doesn't return NaN values. When image values are only slightly different, floating-point errors can cause a subtraction inside of a square root to go negative (without an explicit check that was added to `match_template`). """ np.random.seed(1) image = 0.5 + 1e-9 * np.random.normal(size=(20, 20)) template = np.ones((6, 6)) template[:3, :] = 0 result = match_template(image, template) assert not np.any(np.isnan(result)) def test_switched_arguments(): image = np.ones((5, 5)) template = np.ones((3, 3)) np.testing.assert_raises(ValueError, match_template, template, image) def test_pad_input(): """Test `match_template` when `pad_input=True`. This test places two full templates (one with values lower than the image mean, the other higher) and two half templates, which are on the edges of the image. The two full templates should score the top (positive and negative) matches and the centers of the half templates should score 2nd. """ # Float prefactors ensure that image range is between 0 and 1 template = 0.5 * diamond(2) image = 0.5 * np.ones((9, 19)) mid = slice(2, 7) image[mid, :3] -= template[:, -3:] # half min template centered at 0 image[mid, 4:9] += template # full max template centered at 6 image[mid, -9:-4] -= template # full min template centered at 12 image[mid, -3:] += template[:, :3] # half max template centered at 18 result = match_template(image, template, pad_input=True) # get the max and min results. sorted_result = np.argsort(result.flat) i, j = np.unravel_index(sorted_result[:2], result.shape) assert_close(j, (12, 0)) i, j = np.unravel_index(sorted_result[-2:], result.shape) assert_close(j, (18, 6)) if __name__ == "__main__": from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/feature/tests/test_texture.py000066400000000000000000000223231223313777300234310ustar00rootroot00000000000000import numpy as np from skimage.feature import greycomatrix, greycoprops, local_binary_pattern class TestGLCM(): def setup(self): self.image = np.array([[0, 0, 1, 1], [0, 0, 1, 1], [0, 2, 2, 2], [2, 2, 3, 3]], dtype=np.uint8) def test_output_angles(self): result = greycomatrix(self.image, [1], [0, np.pi / 2], 4) assert result.shape == (4, 4, 1, 2) expected1 = np.array([[2, 2, 1, 0], [0, 2, 0, 0], [0, 0, 3, 1], [0, 0, 0, 1]], dtype=np.uint32) np.testing.assert_array_equal(result[:, :, 0, 0], expected1) expected2 = np.array([[3, 0, 2, 0], [0, 2, 2, 0], [0, 0, 1, 2], [0, 0, 0, 0]], dtype=np.uint32) np.testing.assert_array_equal(result[:, :, 0, 1], expected2) def test_output_symmetric_1(self): result = greycomatrix(self.image, [1], [np.pi / 2], 4, symmetric=True) assert result.shape == (4, 4, 1, 1) expected = np.array([[6, 0, 2, 0], [0, 4, 2, 0], [2, 2, 2, 2], [0, 0, 2, 0]], dtype=np.uint32) np.testing.assert_array_equal(result[:, :, 0, 0], expected) def test_output_distance(self): im = np.array([[0, 0, 0, 0], [1, 0, 0, 1], [2, 0, 0, 2], [3, 0, 0, 3]], dtype=np.uint8) result = greycomatrix(im, [3], [0], 4, symmetric=False) expected = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]], dtype=np.uint32) np.testing.assert_array_equal(result[:, :, 0, 0], expected) def test_output_combo(self): im = np.array([[0], [1], [2], [3]], dtype=np.uint8) result = greycomatrix(im, [1, 2], [0, np.pi / 2], 4) assert result.shape == (4, 4, 2, 2) z = np.zeros((4, 4), dtype=np.uint32) e1 = np.array([[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1], [0, 0, 0, 0]], dtype=np.uint32) e2 = np.array([[0, 0, 1, 0], [0, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0]], dtype=np.uint32) np.testing.assert_array_equal(result[:, :, 0, 0], z) np.testing.assert_array_equal(result[:, :, 1, 0], z) np.testing.assert_array_equal(result[:, :, 0, 1], e1) np.testing.assert_array_equal(result[:, :, 1, 1], e2) def test_output_empty(self): result = greycomatrix(self.image, [10], [0], 4) np.testing.assert_array_equal(result[:, :, 0, 0], np.zeros((4, 4), dtype=np.uint32)) result = greycomatrix(self.image, [10], [0], 4, normed=True) np.testing.assert_array_equal(result[:, :, 0, 0], np.zeros((4, 4), dtype=np.uint32)) def test_normed_symmetric(self): result = greycomatrix(self.image, [1, 2, 3], [0, np.pi / 2, np.pi], 4, normed=True, symmetric=True) for d in range(result.shape[2]): for a in range(result.shape[3]): np.testing.assert_almost_equal(result[:, :, d, a].sum(), 1.0) np.testing.assert_array_equal(result[:, :, d, a], result[:, :, d, a].transpose()) def test_contrast(self): result = greycomatrix(self.image, [1, 2], [0], 4, normed=True, symmetric=True) result = np.round(result, 3) contrast = greycoprops(result, 'contrast') np.testing.assert_almost_equal(contrast[0, 0], 0.586) def test_dissimilarity(self): result = greycomatrix(self.image, [1], [0, np.pi / 2], 4, normed=True, symmetric=True) result = np.round(result, 3) dissimilarity = greycoprops(result, 'dissimilarity') np.testing.assert_almost_equal(dissimilarity[0, 0], 0.418) def test_dissimilarity_2(self): result = greycomatrix(self.image, [1, 3], [np.pi / 2], 4, normed=True, symmetric=True) result = np.round(result, 3) dissimilarity = greycoprops(result, 'dissimilarity')[0, 0] np.testing.assert_almost_equal(dissimilarity, 0.664) def test_invalid_property(self): result = greycomatrix(self.image, [1], [0], 4) np.testing.assert_raises(ValueError, greycoprops, result, 'ABC') def test_homogeneity(self): result = greycomatrix(self.image, [1], [0, 6], 4, normed=True, symmetric=True) homogeneity = greycoprops(result, 'homogeneity')[0, 0] np.testing.assert_almost_equal(homogeneity, 0.80833333) def test_energy(self): result = greycomatrix(self.image, [1], [0, 4], 4, normed=True, symmetric=True) energy = greycoprops(result, 'energy')[0, 0] np.testing.assert_almost_equal(energy, 0.38188131) def test_correlation(self): result = greycomatrix(self.image, [1, 2], [0], 4, normed=True, symmetric=True) energy = greycoprops(result, 'correlation') np.testing.assert_almost_equal(energy[0, 0], 0.71953255) np.testing.assert_almost_equal(energy[1, 0], 0.41176470) def test_uniform_properties(self): im = np.ones((4, 4), dtype=np.uint8) result = greycomatrix(im, [1, 2, 8], [0, np.pi / 2], 4, normed=True, symmetric=True) for prop in ['contrast', 'dissimilarity', 'homogeneity', 'energy', 'correlation', 'ASM']: greycoprops(result, prop) class TestLBP(): def setup(self): self.image = np.array([[255, 6, 255, 0, 141, 0], [ 48, 250, 204, 166, 223, 63], [ 8, 0, 159, 50, 255, 30], [167, 255, 63, 40, 128, 255], [ 0, 255, 30, 34, 255, 24], [146, 241, 255, 0, 189, 126]], dtype='double') def test_default(self): lbp = local_binary_pattern(self.image, 8, 1, 'default') ref = np.array([[ 0, 251, 0, 255, 96, 255], [143, 0, 20, 153, 64, 56], [238, 255, 12, 191, 0, 252], [129, 64., 62, 159, 199, 0], [255, 4, 255, 175, 0, 254], [ 3, 5, 0, 255, 4, 24]]) np.testing.assert_array_equal(lbp, ref) def test_ror(self): lbp = local_binary_pattern(self.image, 8, 1, 'ror') ref = np.array([[ 0, 127, 0, 255, 3, 255], [ 31, 0, 5, 51, 1, 7], [119, 255, 3, 127, 0, 63], [ 3, 1, 31, 63, 31, 0], [255, 1, 255, 95, 0, 127], [ 3, 5, 0, 255, 1, 3]]) np.testing.assert_array_equal(lbp, ref) def test_uniform(self): lbp = local_binary_pattern(self.image, 8, 1, 'uniform') ref = np.array([[0, 7, 0, 8, 2, 8], [5, 0, 9, 9, 1, 3], [9, 8, 2, 7, 0, 6], [2, 1, 5, 6, 5, 0], [8, 1, 8, 9, 0, 7], [2, 9, 0, 8, 1, 2]]) np.testing.assert_array_equal(lbp, ref) def test_var(self): lbp = local_binary_pattern(self.image, 8, 1, 'var') ref = np.array([[0. , 0.00072786, 0. , 0.00115377, 0.00032355, 0.00224467], [0.00051758, 0. , 0.0026383 , 0.00163246, 0.00027414, 0.00041124], [0.00192834, 0.00130368, 0.00042095, 0.00171894, 0. , 0.00063726], [0.00023048, 0.00019464 , 0.00082291, 0.00225386, 0.00076696, 0. ], [0.00097253, 0.00013236, 0.0009134 , 0.0014467 , 0. , 0.00082472], [0.00024701, 0.0012277 , 0. , 0.00109869, 0.00015445, 0.00035881]]) np.testing.assert_array_almost_equal(lbp, ref) def test_nri_uniform(self): lbp = local_binary_pattern(self.image, 8, 1, 'nri_uniform') ref = np.array([[ 0, 54, 0, 57, 12, 57], [34, 0, 58, 58, 3, 22], [58, 57, 15, 50, 0, 47], [10, 3, 40, 42, 35, 0], [57, 7, 57, 58, 0, 56], [ 9, 58, 0, 57, 7, 14]]) np.testing.assert_array_almost_equal(lbp, ref) if __name__ == '__main__': np.testing.run_module_suite() scikit-image-0.9.3/skimage/feature/tests/test_util.py000066400000000000000000000021331223313777300227030ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal from skimage.feature.util import pairwise_hamming_distance def test_pairwise_hamming_distance_range(): """Values of all the pairwise hamming distances should be in the range [0, 1].""" a = np.random.random_sample((10, 50)) > 0.5 b = np.random.random_sample((20, 50)) > 0.5 dist = pairwise_hamming_distance(a, b) assert np.all((0 <= dist) & (dist <= 1)) def test_pairwise_hamming_distance_value(): """The result of pairwise_hamming_distance of two fixed sets of boolean vectors should be same as expected.""" np.random.seed(10) a = np.random.random_sample((4, 100)) > 0.5 np.random.seed(20) b = np.random.random_sample((3, 100)) > 0.5 result = pairwise_hamming_distance(a, b) expected = np.array([[0.5 , 0.49, 0.44], [0.44, 0.53, 0.52], [0.4 , 0.55, 0.5 ], [0.47, 0.48, 0.57]]) assert_array_equal(result, expected) if __name__ == '__main__': from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/feature/texture.py000066400000000000000000000236641223313777300212410ustar00rootroot00000000000000""" Methods to characterize image textures. """ import numpy as np from ._texture import _glcm_loop, _local_binary_pattern def greycomatrix(image, distances, angles, levels=256, symmetric=False, normed=False): """Calculate the grey-level co-occurrence matrix. A grey level co-occurence matrix is a histogram of co-occuring greyscale values at a given offset over an image. Parameters ---------- image : array_like of uint8 Integer typed input image. The image will be cast to uint8, so the maximum value must be less than 256. distances : array_like List of pixel pair distance offsets. angles : array_like List of pixel pair angles in radians. levels : int, optional The input image should contain integers in [0, levels-1], where levels indicate the number of grey-levels counted (typically 256 for an 8-bit image). The maximum value is 256. symmetric : bool, optional If True, the output matrix `P[:, :, d, theta]` is symmetric. This is accomplished by ignoring the order of value pairs, so both (i, j) and (j, i) are accumulated when (i, j) is encountered for a given offset. The default is False. normed : bool, optional If True, normalize each matrix `P[:, :, d, theta]` by dividing by the total number of accumulated co-occurrences for the given offset. The elements of the resulting matrix sum to 1. The default is False. Returns ------- P : 4-D ndarray The grey-level co-occurrence histogram. The value `P[i,j,d,theta]` is the number of times that grey-level `j` occurs at a distance `d` and at an angle `theta` from grey-level `i`. If `normed` is `False`, the output is of type uint32, otherwise it is float64. References ---------- .. [1] The GLCM Tutorial Home Page, http://www.fp.ucalgary.ca/mhallbey/tutorial.htm .. [2] Pattern Recognition Engineering, Morton Nadler & Eric P. Smith .. [3] Wikipedia, http://en.wikipedia.org/wiki/Co-occurrence_matrix Examples -------- Compute 2 GLCMs: One for a 1-pixel offset to the right, and one for a 1-pixel offset upwards. >>> image = np.array([[0, 0, 1, 1], ... [0, 0, 1, 1], ... [0, 2, 2, 2], ... [2, 2, 3, 3]], dtype=np.uint8) >>> result = greycomatrix(image, [1], [0, np.pi/2], levels=4) >>> result[:, :, 0, 0] array([[2, 2, 1, 0], [0, 2, 0, 0], [0, 0, 3, 1], [0, 0, 0, 1]], dtype=uint32) >>> result[:, :, 0, 1] array([[3, 0, 2, 0], [0, 2, 2, 0], [0, 0, 1, 2], [0, 0, 0, 0]], dtype=uint32) """ assert levels <= 256 image = np.ascontiguousarray(image) assert image.ndim == 2 assert image.min() >= 0 assert image.max() < levels image = image.astype(np.uint8) distances = np.ascontiguousarray(distances, dtype=np.float64) angles = np.ascontiguousarray(angles, dtype=np.float64) assert distances.ndim == 1 assert angles.ndim == 1 P = np.zeros((levels, levels, len(distances), len(angles)), dtype=np.uint32, order='C') # count co-occurences _glcm_loop(image, distances, angles, levels, P) # make each GLMC symmetric if symmetric: Pt = np.transpose(P, (1, 0, 2, 3)) P = P + Pt # normalize each GLMC if normed: P = P.astype(np.float64) glcm_sums = np.apply_over_axes(np.sum, P, axes=(0, 1)) glcm_sums[glcm_sums == 0] = 1 P /= glcm_sums return P def greycoprops(P, prop='contrast'): """Calculate texture properties of a GLCM. Compute a feature of a grey level co-occurrence matrix to serve as a compact summary of the matrix. The properties are computed as follows: - 'contrast': :math:`\\sum_{i,j=0}^{levels-1} P_{i,j}(i-j)^2` - 'dissimilarity': :math:`\\sum_{i,j=0}^{levels-1}P_{i,j}|i-j|` - 'homogeneity': :math:`\\sum_{i,j=0}^{levels-1}\\frac{P_{i,j}}{1+(i-j)^2}` - 'ASM': :math:`\\sum_{i,j=0}^{levels-1} P_{i,j}^2` - 'energy': :math:`\\sqrt{ASM}` - 'correlation': .. math:: \\sum_{i,j=0}^{levels-1} P_{i,j}\\left[\\frac{(i-\\mu_i) \\ (j-\\mu_j)}{\\sqrt{(\\sigma_i^2)(\\sigma_j^2)}}\\right] Parameters ---------- P : ndarray Input array. `P` is the grey-level co-occurrence histogram for which to compute the specified property. The value `P[i,j,d,theta]` is the number of times that grey-level j occurs at a distance d and at an angle theta from grey-level i. prop : {'contrast', 'dissimilarity', 'homogeneity', 'energy', \ 'correlation', 'ASM'}, optional The property of the GLCM to compute. The default is 'contrast'. Returns ------- results : 2-D ndarray 2-dimensional array. `results[d, a]` is the property 'prop' for the d'th distance and the a'th angle. References ---------- .. [1] The GLCM Tutorial Home Page, http://www.fp.ucalgary.ca/mhallbey/tutorial.htm Examples -------- Compute the contrast for GLCMs with distances [1, 2] and angles [0 degrees, 90 degrees] >>> image = np.array([[0, 0, 1, 1], ... [0, 0, 1, 1], ... [0, 2, 2, 2], ... [2, 2, 3, 3]], dtype=np.uint8) >>> g = greycomatrix(image, [1, 2], [0, np.pi/2], levels=4, ... normed=True, symmetric=True) >>> contrast = greycoprops(g, 'contrast') >>> contrast array([[ 0.58333333, 1. ], [ 1.25 , 2.75 ]]) """ assert P.ndim == 4 (num_level, num_level2, num_dist, num_angle) = P.shape assert num_level == num_level2 assert num_dist > 0 assert num_angle > 0 # create weights for specified property I, J = np.ogrid[0:num_level, 0:num_level] if prop == 'contrast': weights = (I - J) ** 2 elif prop == 'dissimilarity': weights = np.abs(I - J) elif prop == 'homogeneity': weights = 1. / (1. + (I - J) ** 2) elif prop in ['ASM', 'energy', 'correlation']: pass else: raise ValueError('%s is an invalid property' % (prop)) # compute property for each GLCM if prop == 'energy': asm = np.apply_over_axes(np.sum, (P ** 2), axes=(0, 1))[0, 0] results = np.sqrt(asm) elif prop == 'ASM': results = np.apply_over_axes(np.sum, (P ** 2), axes=(0, 1))[0, 0] elif prop == 'correlation': results = np.zeros((num_dist, num_angle), dtype=np.float64) I = np.array(range(num_level)).reshape((num_level, 1, 1, 1)) J = np.array(range(num_level)).reshape((1, num_level, 1, 1)) diff_i = I - np.apply_over_axes(np.sum, (I * P), axes=(0, 1))[0, 0] diff_j = J - np.apply_over_axes(np.sum, (J * P), axes=(0, 1))[0, 0] std_i = np.sqrt(np.apply_over_axes(np.sum, (P * (diff_i) ** 2), axes=(0, 1))[0, 0]) std_j = np.sqrt(np.apply_over_axes(np.sum, (P * (diff_j) ** 2), axes=(0, 1))[0, 0]) cov = np.apply_over_axes(np.sum, (P * (diff_i * diff_j)), axes=(0, 1))[0, 0] # handle the special case of standard deviations near zero mask_0 = std_i < 1e-15 mask_0[std_j < 1e-15] = True results[mask_0] = 1 # handle the standard case mask_1 = mask_0 == False results[mask_1] = cov[mask_1] / (std_i[mask_1] * std_j[mask_1]) elif prop in ['contrast', 'dissimilarity', 'homogeneity']: weights = weights.reshape((num_level, num_level, 1, 1)) results = np.apply_over_axes(np.sum, (P * weights), axes=(0, 1))[0, 0] return results def local_binary_pattern(image, P, R, method='default'): """Gray scale and rotation invariant LBP (Local Binary Patterns). LBP is an invariant descriptor that can be used for texture classification. Parameters ---------- image : (N, M) array Graylevel image. P : int Number of circularly symmetric neighbour set points (quantization of the angular space). R : float Radius of circle (spatial resolution of the operator). method : {'default', 'ror', 'uniform', 'var'} Method to determine the pattern. * 'default': original local binary pattern which is gray scale but not rotation invariant. * 'ror': extension of default implementation which is gray scale and rotation invariant. * 'uniform': improved rotation invariance with uniform patterns and finer quantization of the angular space which is gray scale and rotation invariant. * 'nri_uniform': non rotation-invariant uniform patterns variant which is only gray scale invariant [2]. * 'var': rotation invariant variance measures of the contrast of local image texture which is rotation but not gray scale invariant. Returns ------- output : (N, M) array LBP image. References ---------- .. [1] Multiresolution Gray-Scale and Rotation Invariant Texture Classification with Local Binary Patterns. Timo Ojala, Matti Pietikainen, Topi Maenpaa. http://www.rafbis.it/biplab15/images/stories/docenti/Danielriccio/\ Articoliriferimento/LBP.pdf, 2002. .. [2] Face recognition with local binary patterns. Timo Ahonen, Abdenour Hadid, Matti Pietikainen, http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.214.6851, 2004. """ methods = { 'default': ord('D'), 'ror': ord('R'), 'uniform': ord('U'), 'nri_uniform': ord('N'), 'var': ord('V') } image = np.ascontiguousarray(image, dtype=np.double) output = _local_binary_pattern(image, P, R, methods[method.lower()]) return output scikit-image-0.9.3/skimage/feature/util.py000066400000000000000000000021571223313777300205100ustar00rootroot00000000000000 def _mask_border_keypoints(image, keypoints, dist): """Removes keypoints that are within dist pixels from the image border.""" width = image.shape[0] height = image.shape[1] keypoints_filtering_mask = ((dist - 1 < keypoints[:, 0]) & (keypoints[:, 0] < width - dist + 1) & (dist - 1 < keypoints[:, 1]) & (keypoints[:, 1] < height - dist + 1)) return keypoints_filtering_mask def pairwise_hamming_distance(array1, array2): """**Experimental function**. Calculate hamming dissimilarity measure between two sets of vectors. Parameters ---------- array1 : (P1, D) array P1 vectors of size D. array2 : (P2, D) array P2 vectors of size D. Returns ------- distance : (P1, P2) array of dtype float 2D ndarray with value at an index (i, j) representing the hamming distance in the range [0, 1] between ith vector in array1 and jth vector in array2. """ distance = (array1[:, None] != array2[None]).mean(axis=2) return distance scikit-image-0.9.3/skimage/filter/000077500000000000000000000000001223313777300170065ustar00rootroot00000000000000scikit-image-0.9.3/skimage/filter/__init__.py000066400000000000000000000024561223313777300211260ustar00rootroot00000000000000from .lpi_filter import inverse, wiener, LPIFilter2D from .ctmf import median_filter from ._gaussian import gaussian_filter from ._canny import canny from .edges import (sobel, hsobel, vsobel, scharr, hscharr, vscharr, prewitt, hprewitt, vprewitt, roberts, roberts_positive_diagonal, roberts_negative_diagonal) from ._denoise import denoise_tv_chambolle from ._denoise_cy import denoise_bilateral, denoise_tv_bregman from ._rank_order import rank_order from ._gabor import gabor_kernel, gabor_filter from .thresholding import threshold_otsu, threshold_adaptive from . import rank __all__ = ['inverse', 'wiener', 'LPIFilter2D', 'median_filter', 'gaussian_filter', 'canny', 'sobel', 'hsobel', 'vsobel', 'scharr', 'hscharr', 'vscharr', 'prewitt', 'hprewitt', 'vprewitt', 'roberts', 'roberts_positive_diagonal', 'roberts_negative_diagonal', 'denoise_tv_chambolle', 'denoise_bilateral', 'denoise_tv_bregman', 'rank_order', 'gabor_kernel', 'gabor_filter', 'threshold_otsu', 'threshold_adaptive', 'rank'] scikit-image-0.9.3/skimage/filter/_canny.py000066400000000000000000000242141223313777300206320ustar00rootroot00000000000000""" canny.py - Canny Edge detector Reference: Canny, J., A Computational Approach To Edge Detection, IEEE Trans. Pattern Analysis and Machine Intelligence, 8:679-714, 1986 Originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky """ import numpy as np import scipy.ndimage as ndi from scipy.ndimage import (gaussian_filter, generate_binary_structure, binary_erosion, label) from skimage import dtype_limits def smooth_with_function_and_mask(image, function, mask): """Smooth an image with a linear function, ignoring masked pixels Parameters ---------- image : array Image you want to smooth. function : callable A function that does image smoothing. mask : array Mask with 1's for significant pixels, 0's for masked pixels. Notes ------ This function calculates the fractional contribution of masked pixels by applying the function to the mask (which gets you the fraction of the pixel data that's due to significant points). We then mask the image and apply the function. The resulting values will be lower by the bleed-over fraction, so you can recalibrate by dividing by the function on the mask to recover the effect of smoothing from just the significant pixels. """ bleed_over = function(mask.astype(float)) masked_image = np.zeros(image.shape, image.dtype) masked_image[mask] = image[mask] smoothed_image = function(masked_image) output_image = smoothed_image / (bleed_over + np.finfo(float).eps) return output_image def canny(image, sigma=1., low_threshold=None, high_threshold=None, mask=None): """Edge filter an image using the Canny algorithm. Parameters ----------- image : 2D array Greyscale input image to detect edges on; can be of any dtype. sigma : float Standard deviation of the Gaussian filter. low_threshold : float Lower bound for hysteresis thresholding (linking edges). If None, low_threshold is set to 10% of dtype's max. high_threshold : float Upper bound for hysteresis thresholding (linking edges). If None, high_threshold is set to 20% of dtype's max. mask : array, dtype=bool, optional Mask to limit the application of Canny to a certain area. Returns ------- output : 2D array (image) The binary edge map. See also -------- skimage.sobel Notes ----- The steps of the algorithm are as follows: * Smooth the image using a Gaussian with ``sigma`` width. * Apply the horizontal and vertical Sobel operators to get the gradients within the image. The edge strength is the norm of the gradient. * Thin potential edges to 1-pixel wide curves. First, find the normal to the edge at each point. This is done by looking at the signs and the relative magnitude of the X-Sobel and Y-Sobel to sort the points into 4 categories: horizontal, vertical, diagonal and antidiagonal. Then look in the normal and reverse directions to see if the values in either of those directions are greater than the point in question. Use interpolation to get a mix of points instead of picking the one that's the closest to the normal. * Perform a hysteresis thresholding: first label all points above the high threshold as edges. Then recursively label any point above the low threshold that is 8-connected to a labeled point as an edge. References ----------- Canny, J., A Computational Approach To Edge Detection, IEEE Trans. Pattern Analysis and Machine Intelligence, 8:679-714, 1986 William Green's Canny tutorial http://dasl.mem.drexel.edu/alumni/bGreen/www.pages.drexel.edu/_weg22/can_tut.html Examples -------- >>> from skimage import filter >>> # Generate noisy image of a square >>> im = np.zeros((256, 256)) >>> im[64:-64, 64:-64] = 1 >>> im += 0.2 * np.random.random(im.shape) >>> # First trial with the Canny filter, with the default smoothing >>> edges1 = filter.canny(im) >>> # Increase the smoothing for better results >>> edges2 = filter.canny(im, sigma=3) """ # # The steps involved: # # * Smooth using the Gaussian with sigma above. # # * Apply the horizontal and vertical Sobel operators to get the gradients # within the image. The edge strength is the sum of the magnitudes # of the gradients in each direction. # # * Find the normal to the edge at each point using the arctangent of the # ratio of the Y sobel over the X sobel - pragmatically, we can # look at the signs of X and Y and the relative magnitude of X vs Y # to sort the points into 4 categories: horizontal, vertical, # diagonal and antidiagonal. # # * Look in the normal and reverse directions to see if the values # in either of those directions are greater than the point in question. # Use interpolation to get a mix of points instead of picking the one # that's the closest to the normal. # # * Label all points above the high threshold as edges. # * Recursively label any point above the low threshold that is 8-connected # to a labeled point as an edge. # # Regarding masks, any point touching a masked point will have a gradient # that is "infected" by the masked point, so it's enough to erode the # mask by one and then mask the output. We also mask out the border points # because who knows what lies beyond the edge of the image? # if image.ndim != 2: raise TypeError("The input 'image' must be a two-dimensional array.") if low_threshold is None: low_threshold = 0.1 * dtype_limits(image)[1] if high_threshold is None: high_threshold = 0.2 * dtype_limits(image)[1] if mask is None: mask = np.ones(image.shape, dtype=bool) fsmooth = lambda x: gaussian_filter(x, sigma, mode='constant') smoothed = smooth_with_function_and_mask(image, fsmooth, mask) jsobel = ndi.sobel(smoothed, axis=1) isobel = ndi.sobel(smoothed, axis=0) abs_isobel = np.abs(isobel) abs_jsobel = np.abs(jsobel) magnitude = np.hypot(isobel, jsobel) # # Make the eroded mask. Setting the border value to zero will wipe # out the image edges for us. # s = generate_binary_structure(2, 2) eroded_mask = binary_erosion(mask, s, border_value=0) eroded_mask = eroded_mask & (magnitude > 0) # #--------- Find local maxima -------------- # # Assign each point to have a normal of 0-45 degrees, 45-90 degrees, # 90-135 degrees and 135-180 degrees. # local_maxima = np.zeros(image.shape, bool) #----- 0 to 45 degrees ------ pts_plus = (isobel >= 0) & (jsobel >= 0) & (abs_isobel >= abs_jsobel) pts_minus = (isobel <= 0) & (jsobel <= 0) & (abs_isobel >= abs_jsobel) pts = pts_plus | pts_minus pts = eroded_mask & pts # Get the magnitudes shifted left to make a matrix of the points to the # right of pts. Similarly, shift left and down to get the points to the # top right of pts. c1 = magnitude[1:, :][pts[:-1, :]] c2 = magnitude[1:, 1:][pts[:-1, :-1]] m = magnitude[pts] w = abs_jsobel[pts] / abs_isobel[pts] c_plus = c2 * w + c1 * (1 - w) <= m c1 = magnitude[:-1, :][pts[1:, :]] c2 = magnitude[:-1, :-1][pts[1:, 1:]] c_minus = c2 * w + c1 * (1 - w) <= m local_maxima[pts] = c_plus & c_minus #----- 45 to 90 degrees ------ # Mix diagonal and vertical # pts_plus = (isobel >= 0) & (jsobel >= 0) & (abs_isobel <= abs_jsobel) pts_minus = (isobel <= 0) & (jsobel <= 0) & (abs_isobel <= abs_jsobel) pts = pts_plus | pts_minus pts = eroded_mask & pts c1 = magnitude[:, 1:][pts[:, :-1]] c2 = magnitude[1:, 1:][pts[:-1, :-1]] m = magnitude[pts] w = abs_isobel[pts] / abs_jsobel[pts] c_plus = c2 * w + c1 * (1 - w) <= m c1 = magnitude[:, :-1][pts[:, 1:]] c2 = magnitude[:-1, :-1][pts[1:, 1:]] c_minus = c2 * w + c1 * (1 - w) <= m local_maxima[pts] = c_plus & c_minus #----- 90 to 135 degrees ------ # Mix anti-diagonal and vertical # pts_plus = (isobel <= 0) & (jsobel >= 0) & (abs_isobel <= abs_jsobel) pts_minus = (isobel >= 0) & (jsobel <= 0) & (abs_isobel <= abs_jsobel) pts = pts_plus | pts_minus pts = eroded_mask & pts c1a = magnitude[:, 1:][pts[:, :-1]] c2a = magnitude[:-1, 1:][pts[1:, :-1]] m = magnitude[pts] w = abs_isobel[pts] / abs_jsobel[pts] c_plus = c2a * w + c1a * (1.0 - w) <= m c1 = magnitude[:, :-1][pts[:, 1:]] c2 = magnitude[1:, :-1][pts[:-1, 1:]] c_minus = c2 * w + c1 * (1.0 - w) <= m local_maxima[pts] = c_plus & c_minus #----- 135 to 180 degrees ------ # Mix anti-diagonal and anti-horizontal # pts_plus = (isobel <= 0) & (jsobel >= 0) & (abs_isobel >= abs_jsobel) pts_minus = (isobel >= 0) & (jsobel <= 0) & (abs_isobel >= abs_jsobel) pts = pts_plus | pts_minus pts = eroded_mask & pts c1 = magnitude[:-1, :][pts[1:, :]] c2 = magnitude[:-1, 1:][pts[1:, :-1]] m = magnitude[pts] w = abs_jsobel[pts] / abs_isobel[pts] c_plus = c2 * w + c1 * (1 - w) <= m c1 = magnitude[1:, :][pts[:-1, :]] c2 = magnitude[1:, :-1][pts[:-1, 1:]] c_minus = c2 * w + c1 * (1 - w) <= m local_maxima[pts] = c_plus & c_minus # #---- Create two masks at the two thresholds. # high_mask = local_maxima & (magnitude >= high_threshold) low_mask = local_maxima & (magnitude >= low_threshold) # # Segment the low-mask, then only keep low-segments that have # some high_mask component in them # strel = np.ones((3, 3), bool) labels, count = label(low_mask, strel) if count == 0: return low_mask sums = (np.array(ndi.sum(high_mask, labels, np.arange(count, dtype=np.int32) + 1), copy=False, ndmin=1)) good_label = np.zeros((count + 1,), bool) good_label[1:] = sums > 0 output_mask = good_label[labels] return output_mask scikit-image-0.9.3/skimage/filter/_ctmf.pyx000066400000000000000000000713151223313777300206470ustar00rootroot00000000000000'''_ctmf.pyx - constant time per pixel median filtering Reference: S. Perreault and P. Hebert, "Median Filtering in Constant Time", IEEE Transactions on Image Processing, September 2007. Originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky ''' import numpy as np cimport numpy as cnp cimport cython from libc.stdlib cimport malloc, free from libc.string cimport memset cdef extern from "../_shared/vectorized_ops.h": void add16(cnp.uint16_t *dest, cnp.uint16_t *src) void sub16(cnp.uint16_t *dest, cnp.uint16_t *src) ############################################################################## # # median_filter - implementation of constant-time median filter with # octagonal shape. The algorithm is derived from # Perreault, "Median Filtering in Constant Time", # IEEE TRANSACTIONS ON IMAGE PROCESSING, VOL. 16, NO. 9, # SEPTEMBER 2007. # # Inputs: # a 2d array of uint8's to be median filtered # a similarly shaped uint8 masking array with "1" indicating a significant # pixel and "0" indicating a pixel to be masked. # # Outputs: # a 2d median-filtered array # ############################################################################## DTYPE_UINT32 = np.uint32 DTYPE_BOOL = np.bool ctypedef cnp.uint16_t pixel_count_t ########### # # Histograms # # There are five separate histograms for the octagonal filter and # there are two levels (coarse = 16 values, fine = 256 values) # per histogram. There are four histograms to maintain per position # representing the four diagonals of the histogram plus one histogram # for the straight side (which is used for adding and subtracting) # ########### cdef struct HistogramPiece: cnp.uint16_t coarse[16] cnp.uint16_t fine[256] cdef struct Histogram: HistogramPiece top_left # top-left corner HistogramPiece top_right # top-right corner HistogramPiece edge # leading/trailing edge HistogramPiece bottom_left # bottom-left corner HistogramPiece bottom_right # bottom-right corner # The pixel count has the number of pixels histogrammed in # each of the five compartments for this position. This changes # because of the mask # cdef struct PixelCount: pixel_count_t top_left pixel_count_t top_right pixel_count_t edge pixel_count_t bottom_left pixel_count_t bottom_right # # Stride + coordinates: the info we need when computing # relative offsets from the octagon center # cdef struct SCoord: Py_ssize_t stride # add the stride to the memory location Py_ssize_t x Py_ssize_t y cdef struct Histograms: HistogramPiece accumulator # running histogram (32-byte aligned) void *memory # pointer to the unaligned allocated memory Histogram *histogram # pointer to the histogram memory (aligned) PixelCount *pixel_count # pointer to the pixel count memory cnp.uint8_t *data # pointer to the image data cnp.uint8_t *mask # pointer to the image mask cnp.uint8_t *output # pointer to the output array Py_ssize_t column_count # number of columns represented by this # structure Py_ssize_t stripe_length # number of columns including "radius" before # and after Py_ssize_t row_count # number of rows available in image Py_ssize_t current_column # the column being processed Py_ssize_t current_row # the row being processed Py_ssize_t current_stride # offset in data and mask to current location Py_ssize_t radius # the "radius" of the octagon Py_ssize_t a_2 # 1/2 of the length of a side of the octagon # # # The strides are the offsets in the array to the points that need to # be added or removed from a histogram to shift from the previous row # to the current row. # Listed here going clockwise from the trailing edge's top. # (-) = needs to be removed # (+) = needs to be added # # - - # 1.=========2 # 1. 2 # +. +- Y # |. 3 | # |. 3 | # -. X \|/ # 5. 4 v # 5. 4 # +.=========+ # # x --> # SCoord last_top_left # (-) left side of octagon's top - 1 row SCoord top_left # (+) -1 row from trailing edge top SCoord last_top_right # (-) right side of octagon's top - 1 col - 1 row SCoord top_right # (+) -1 col -1 row from leading edge top SCoord last_leading_edge # (-) leading edge (right) top stride - 1 row SCoord leading_edge # (+) leading edge bottom stride SCoord last_bottom_right # (-) leading edge bottom - 1 col SCoord bottom_right # (+) right side of octagon's bottom - 1 col SCoord last_bottom_left # (-) trailing edge bottom - 1 col SCoord bottom_left # (+) left side of octagon's bottom - 1 col Py_ssize_t row_stride # stride between one row and the next Py_ssize_t col_stride # stride between one column and the next # # The running count of pixels in the accumulator # Py_ssize_t accumulator_count # # The percent of pixels within the octagon whose value is # less than or equal to the median-filtered value (e.g. for # median, this is 50, for lower quartile it's 25) # Py_ssize_t percent # # last_update_column keeps track of the column # of the last update # to the fine histogram accumulator. Short-term, the median # stays in one coarse block so only one fine histogram might # need to be updated # Py_ssize_t last_update_column[16] ############################################################################ # # allocate_histograms - allocates the Histograms structure for the run # ############################################################################ cdef Histograms *allocate_histograms(Py_ssize_t rows, Py_ssize_t columns, Py_ssize_t row_stride, Py_ssize_t col_stride, Py_ssize_t radius, Py_ssize_t percent, cnp.uint8_t *data, cnp.uint8_t *mask, cnp.uint8_t *output): cdef: Py_ssize_t adjusted_stripe_length = columns + 2*radius + 1 Py_ssize_t memory_size void *ptr Histograms *ph Py_ssize_t roundoff Py_ssize_t a SCoord *psc memory_size = (adjusted_stripe_length * (sizeof(Histogram) + sizeof(PixelCount)) + sizeof(Histograms) + 64) ptr = malloc(memory_size) memset(ptr, 0, memory_size) # align ph.accumulator to 32-byte boundary roundoff = ( ptr + 31) % 32 ph = ( ptr + 31 - roundoff) if not ptr: return ph ph.memory = ptr ptr = (ph + 1) ph.pixel_count = ptr ptr = (ph.pixel_count + adjusted_stripe_length) # # Align histogram memory to a 32-byte boundary # roundoff = ( ptr + 31) % 32 ptr = ( ptr + 31 - roundoff) ph.histogram = ptr # # Fill in the statistical things we keep around # ph.column_count = columns ph.row_count = rows ph.current_column = -radius ph.stripe_length = adjusted_stripe_length ph.current_row = 0 ph.radius = radius ph.percent = percent ph.row_stride = row_stride ph.col_stride = col_stride ph.data = data ph.mask = mask ph.output = output # # Compute the coordinates of the significant points # (the SCoords) # # First, the length of a side of an octagon, compared # to what we call the radius is: # 2*r # ----------- = a # (1+sqrt(2)) # # a_2 is the offset from the center to each of the octagon # corners # a = (radius * 2.0 / 2.414213) a_2 = a / 2 if a_2 == 0: a_2 = 1 ph.a_2 = a_2 if radius <= a_2: radius = a_2+1 ph.radius = radius ph.last_top_left.x = -a_2 ph.last_top_left.y = -radius - 1 ph.top_left.x = -radius ph.top_left.y = -a_2 - 1 ph.last_top_right.x = a_2 - 1 ph.last_top_right.y = -radius - 1 ph.top_right.x = radius - 1 ph.top_right.y = -a_2 - 1 ph.last_leading_edge.x = radius ph.last_leading_edge.y = -a_2 - 1 ph.leading_edge.x = radius ph.leading_edge.y = a_2 ph.last_bottom_right.x = radius ph.last_bottom_right.y = a_2 ph.bottom_right.x = a_2 ph.bottom_right.y = radius ph.last_bottom_left.x = -radius-1 ph.last_bottom_left.y = a_2 ph.bottom_left.x = -a_2-1 ph.bottom_left.y = radius # # Set the stride of each SCoord based on its x and y # set_stride(ph, &ph.last_top_left) set_stride(ph, &ph.top_left) set_stride(ph, &ph.last_top_right) set_stride(ph, &ph.top_right) set_stride(ph, &ph.last_leading_edge) set_stride(ph, &ph.leading_edge) set_stride(ph, &ph.last_bottom_left) set_stride(ph, &ph.bottom_left) set_stride(ph, &ph.last_bottom_right) set_stride(ph, &ph.bottom_right) return ph ############################################################################ # # free_histograms - frees the Histograms structure # ############################################################################ cdef void free_histograms(Histograms *ph): free(ph.memory) ############################################################################ # # set_stride - set the stride of a SCoord from its X and Y # ############################################################################ cdef void set_stride(Histograms *ph, SCoord *psc): psc.stride = psc.x * ph.col_stride + psc.y * ph.row_stride ############################################################################ # # _colidx - convert a column index into the histogram # index for a diagonal # # The top-right and bottom left diagonals for one row at one column # become the diagonals for the next column to the right for the next row. # Conversely, the top-left and bottom right become the diagonals for the # previous column. # # These functions use the current row number to find the index of # a particular histogram taking this into account. The indices progress # forward or backward as you go to successive rows. # # The histogram array is, in effect, a circular buffer, so the start # offset is immaterial - we take advantage of this to make sure that # the numbers computed before taking the modulus are all positive, including # those that might be done for columns to the left of 0. We add 3* the radius # here to account for a row of -radius, a column of -radius and a request for # a column that is "radius" to the left. # ############################################################################ cdef inline Py_ssize_t tl_br_colidx(Histograms *ph, Py_ssize_t colidx): return (colidx + 3*ph.radius + ph.current_row) % ph.stripe_length cdef inline Py_ssize_t tr_bl_colidx(Histograms *ph, Py_ssize_t colidx): return (colidx + 3*ph.radius + ph.row_count-ph.current_row) % \ ph.stripe_length cdef inline Py_ssize_t leading_edge_colidx(Histograms *ph, Py_ssize_t colidx): return (colidx + 5*ph.radius) % ph.stripe_length cdef inline Py_ssize_t trailing_edge_colidx(Histograms *ph, Py_ssize_t colidx): return (colidx + 3*ph.radius - 1) % ph.stripe_length ############################################################################ # # accumulate_coarse_histogram - accumulate the coarse histogram # at an index into the accumulator # # ph - the Histograms structure that holds the accumulator # colidx - the index of the column to add # ############################################################################ cdef inline void accumulate_coarse_histogram(Histograms *ph, Py_ssize_t colidx): cdef Py_ssize_t offset offset = tr_bl_colidx(ph, colidx) if ph.pixel_count[offset].top_right > 0: add16(ph.accumulator.coarse, ph.histogram[offset].top_right.coarse) ph.accumulator_count += ph.pixel_count[offset].top_right offset = leading_edge_colidx(ph, colidx) if ph.pixel_count[offset].edge > 0: add16(ph.accumulator.coarse, ph.histogram[offset].edge.coarse) ph.accumulator_count += ph.pixel_count[offset].edge offset = tl_br_colidx(ph, colidx) if ph.pixel_count[offset].bottom_right > 0: add16(ph.accumulator.coarse, ph.histogram[offset].bottom_right.coarse) ph.accumulator_count += ph.pixel_count[offset].bottom_right ############################################################################ # # deaccumulate_coarse_histogram - subtract the coarse histogram # for a given column # ############################################################################ cdef inline void deaccumulate_coarse_histogram(Histograms *ph, Py_ssize_t colidx): cdef Py_ssize_t offset # # The trailing diagonals don't appear until here # if colidx <= ph.a_2: return offset = tl_br_colidx(ph, colidx) if ph.pixel_count[offset].top_left > 0: sub16(ph.accumulator.coarse, ph.histogram[offset].top_left.coarse) ph.accumulator_count -= ph.pixel_count[offset].top_left # # The trailing edge doesn't appear from the border until here # if colidx > ph.radius: offset = trailing_edge_colidx(ph, colidx) if ph.pixel_count[offset].edge > 0: sub16(ph.accumulator.coarse, ph.histogram[offset].edge.coarse) ph.accumulator_count -= ph.pixel_count[offset].edge offset = tr_bl_colidx(ph, colidx) if ph.pixel_count[offset].bottom_left > 0: sub16(ph.accumulator.coarse, ph.histogram[offset].bottom_left.coarse) ph.accumulator_count -= ph.pixel_count[offset].bottom_left ############################################################################ # # accumulate_fine_histogram - accumulate one of the 16 fine histograms # ############################################################################ cdef inline void accumulate_fine_histogram(Histograms *ph, Py_ssize_t colidx, Py_ssize_t fineidx): cdef: Py_ssize_t fineoffset = fineidx * 16 Py_ssize_t offset offset = tr_bl_colidx(ph, colidx) add16(ph.accumulator.fine + fineoffset, ph.histogram[offset].top_right.fine + fineoffset) offset = leading_edge_colidx(ph, colidx) add16(ph.accumulator.fine + fineoffset, ph.histogram[offset].edge.fine + fineoffset) offset = tl_br_colidx(ph, colidx) add16(ph.accumulator.fine + fineoffset, ph.histogram[offset].bottom_right.fine + fineoffset) ############################################################################ # # deaccumulate_fine_histogram - subtract one of the 16 fine histograms # ############################################################################ cdef inline void deaccumulate_fine_histogram(Histograms *ph, Py_ssize_t colidx, Py_ssize_t fineidx): cdef: Py_ssize_t fineoffset = fineidx * 16 Py_ssize_t offset # # The trailing diagonals don't appear until here # if colidx < ph.a_2: return offset = tl_br_colidx(ph, colidx) sub16(ph.accumulator.fine + fineoffset, ph.histogram[offset].top_left.fine + fineoffset) if colidx >= ph.radius: offset = trailing_edge_colidx(ph, colidx) sub16(ph.accumulator.fine+fineoffset, ph.histogram[offset].edge.fine + fineoffset) offset = tr_bl_colidx(ph, colidx) sub16(ph.accumulator.fine + fineoffset, ph.histogram[offset].bottom_left.fine + fineoffset) ############################################################################ # # accumulate - add the leading edge and subtract the trailing edge # ############################################################################ cdef inline void accumulate(Histograms *ph): cdef cnp.int32_t accumulator accumulate_coarse_histogram(ph, ph.current_column) deaccumulate_coarse_histogram(ph, ph.current_column) ############################################################################ # # update_fine - update one of the fine histograms to the current column # # The code has two choices: # redo the fine histogram from scratch - this involves accumulating # the entire histogram from the top_left.x to the top_right.x, # the center (edge) histogram from the trailing edge x to the # top_left.x and then computing a histogram of all points between # the trailing edge top, the point, (top_left.x,trailing edge top.y) # and the top_right and the corresponding triangle in the octagon's # lower half. # # accumulate and deaccumulate within the fine histogram from the last # column computed. # # The code below only implements the accumulate; redo and the code # to choose remains to be done. ############################################################################ cdef inline void update_fine(Histograms *ph, Py_ssize_t fineidx): cdef: Py_ssize_t first_update_column = ph.last_update_column[fineidx]+1 Py_ssize_t update_limit = ph.current_column+1 Py_ssize_t i for i in range(first_update_column, update_limit): accumulate_fine_histogram(ph, i, fineidx) deaccumulate_fine_histogram(ph, i, fineidx) ph.last_update_column[fineidx] = ph.current_column ############################################################################ # # update_histogram - update the coarse and fine levels of a histogram # based on addition of one value and subtraction of another # # ph - Histograms pointer (for access to row_count, column_count) # hist_piece - coarse and fine histogram to update # pixel_count- pointer to pixel counter for histogram # last_coord - coordinate and stride of pixel to remove # coord - coordinate and stride of pixel to add # ############################################################################ cdef inline void update_histogram(Histograms *ph, HistogramPiece *hist_piece, pixel_count_t *pixel_count, SCoord *last_coord, SCoord *coord): cdef: Py_ssize_t current_column = ph.current_column Py_ssize_t current_row = ph.current_row Py_ssize_t current_stride = ph.current_stride Py_ssize_t column_count = ph.column_count Py_ssize_t row_count = ph.row_count cnp.uint8_t value Py_ssize_t stride Py_ssize_t x Py_ssize_t y x = last_coord.x + current_column y = last_coord.y + current_row stride = current_stride+last_coord.stride if (x >= 0 and x < column_count and \ y >= 0 and y < row_count and \ ph.mask[stride]): value = ph.data[stride] pixel_count[0] -= 1 hist_piece.fine[value] -= 1 hist_piece.coarse[value / 16] -= 1 x = coord.x + current_column y = coord.y + current_row stride = current_stride + coord.stride if (x >= 0 and x < column_count and \ y >= 0 and y < row_count and \ ph.mask[stride]): value = ph.data[stride] pixel_count[0] += 1 hist_piece.fine[value] += 1 hist_piece.coarse[value / 16] += 1 ############################################################################ # # update_current_location - update the histograms at the current location # ############################################################################ cdef inline void update_current_location(Histograms *ph): cdef: Py_ssize_t current_column = ph.current_column Py_ssize_t radius = ph.radius Py_ssize_t top_left_off = tl_br_colidx(ph, current_column) Py_ssize_t top_right_off = tr_bl_colidx(ph, current_column) Py_ssize_t bottom_left_off = tr_bl_colidx(ph, current_column) Py_ssize_t bottom_right_off = tl_br_colidx(ph, current_column) Py_ssize_t leading_edge_off = leading_edge_colidx(ph, current_column) cnp.int32_t *coarse_histogram cnp.int32_t *fine_histogram Py_ssize_t last_xoff Py_ssize_t last_yoff Py_ssize_t last_stride Py_ssize_t xoff Py_ssize_t yoff Py_ssize_t stride update_histogram(ph, &ph.histogram[top_left_off].top_left, &ph.pixel_count[top_left_off].top_left, &ph.last_top_left, &ph.top_left) update_histogram(ph, &ph.histogram[top_right_off].top_right, &ph.pixel_count[top_right_off].top_right, &ph.last_top_right, &ph.top_right) update_histogram(ph, &ph.histogram[bottom_left_off].bottom_left, &ph.pixel_count[bottom_left_off].bottom_left, &ph.last_bottom_left, &ph.bottom_left) update_histogram(ph, &ph.histogram[bottom_right_off].bottom_right, &ph.pixel_count[bottom_right_off].bottom_right, &ph.last_bottom_right, &ph.bottom_right) update_histogram(ph, &ph.histogram[leading_edge_off].edge, &ph.pixel_count[leading_edge_off].edge, &ph.last_leading_edge, &ph.leading_edge) ############################################################################ # # find_median - search the current accumulator for the median # ############################################################################ cdef inline cnp.uint8_t find_median(Histograms *ph): cdef: Py_ssize_t pixels_below # of pixels below the median Py_ssize_t i Py_ssize_t j Py_ssize_t k cnp.uint32_t accumulator if ph.accumulator_count == 0: return 0 # +50 for roundoff pixels_below = (ph.accumulator_count * ph.percent + 50) / 100 if pixels_below > 0: pixels_below -= 1 accumulator = 0 for i in range(16): accumulator += ph.accumulator.coarse[i] if accumulator > pixels_below: break accumulator -= ph.accumulator.coarse[i] update_fine(ph, i) for j in range(i*16, (i + 1)*16): accumulator += ph.accumulator.fine[j] if accumulator > pixels_below: return j return 0 ############################################################################ # # c_median_filter - median filter algorithm # # rows - # of rows in each array # columns - # of columns in each array # row_stride - stride from one row to the next in each array # col_stride - stride from one column to the next in each array # radius - radius of circle inscribed into octagon # percent - "median" cutoff: 50 = median, 25 = lower quartile, etc # data - array of image pixels to be filtered # mask - mask of significant pixels # output - array to be filled with filtered pixels # ############################################################################ cdef int c_median_filter(Py_ssize_t rows, Py_ssize_t columns, Py_ssize_t row_stride, Py_ssize_t col_stride, Py_ssize_t radius, Py_ssize_t percent, cnp.uint8_t *data, cnp.uint8_t *mask, cnp.uint8_t *output): cdef: Histograms *ph Histogram *phistogram Py_ssize_t row Py_ssize_t col Py_ssize_t i Py_ssize_t top_left_off Py_ssize_t top_right_off Py_ssize_t bottom_left_off Py_ssize_t bottom_right_off ph = allocate_histograms(rows, columns, row_stride, col_stride, radius, percent, data, mask, output) if not ph: return 1 for row in range(-radius, rows): # # Initialize the starting diagonal histograms to zero. The leading # and trailing histograms descend from above and so are initialized # when memory is initially set to zero. The diagonals move in # from the left (top left and bottom right) and right (top right # and bottom left). One of each needs to be initialized at the # start of each row # tl_br_off = tl_br_colidx(ph, -radius) tr_bl_off = tr_bl_colidx(ph, columns + radius - 1) memset(&ph.histogram[tl_br_off].top_left, 0, sizeof(HistogramPiece)) memset(&ph.histogram[tl_br_off].bottom_right, 0, sizeof(HistogramPiece)) memset(&ph.histogram[tr_bl_off].top_right, 0, sizeof(HistogramPiece)) memset(&ph.histogram[tr_bl_off].bottom_left, 0, sizeof(HistogramPiece)) ph.pixel_count[tl_br_off].top_left = 0 ph.pixel_count[tl_br_off].bottom_right = 0 ph.pixel_count[tr_bl_off].top_right = 0 ph.pixel_count[tr_bl_off].bottom_left = 0 # # Initialize the accumulator (octagon histogram) to zero # memset(&(ph.accumulator), 0, sizeof(ph.accumulator)) ph.accumulator_count = 0 for i in range(16): ph.last_update_column[i] = -radius-1 # # Initialize the current stride to the beginning of the row # ph.current_row = row # # Update locations and coarse accumulator for the octagon # for points before 0 # for col in range(-radius, 0 if row >= 0 else columns+radius): ph.current_column = col ph.current_stride = row * row_stride + col * col_stride update_current_location(ph) accumulate(ph) # # Update locations and coarse accumulator and compute # the median for points between 0 and "columns" # if row >= 0: for col in range(0, columns): ph.current_column = col ph.current_stride = row * row_stride + col * col_stride update_current_location(ph) accumulate(ph) ph.output[ph.current_stride] = find_median(ph) for col in range(columns, columns+radius): ph.current_column = col ph.current_stride = row * row_stride + col * col_stride update_current_location(ph) free_histograms(ph) return 0 def median_filter(cnp.uint8_t[:, ::1] data, cnp.uint8_t[:, ::1] mask, cnp.uint8_t[:, ::1] output, int radius, cnp.int32_t percent): """Median filter with octagon shape and masking. Parameters ---------- data : (M,N) ndarray, dtype uint8 Input image. mask : (M,N) array, dtype uint8 A value of 1 indicates a significant pixel, 0 that a pixel is masked. output : (M,N) array, dtype uint8 Array of same size as the input in which to store the filtered image. radius : int Radius of the inscribed circle to the octagon. percent : int, optional The unmasked pixels within the octagon are sorted, and the value at the `percent`-th index chosen. For example, the default value of 50 chooses the median pixel. """ if percent < 0: raise ValueError('Median filter percent = %d is less than zero' % percent) if percent > 100: raise ValueError('Median filter percent = %d is greater than 100' % percent) if data.shape[0] != mask.shape[0] or data.shape[1] != mask.shape[1]: raise ValueError('Data shape (%d, %d) is not mask shape (%d, %d)' % (data.shape[0], data.shape[1], mask.shape[0], mask.shape[1])) if data.shape[0] != output.shape[0] or data.shape[1] != output.shape[1]: raise ValueError('Data shape (%d, %d) is not output shape (%d, %d)' % (data.shape[0], data.shape[1], output.shape[0], output.shape[1])) if c_median_filter(data.shape[0], data.shape[1], data.strides[0], data.strides[1], radius, percent, &data[0, 0], &mask[0, 0], &output[0, 0]): raise MemoryError('Failed to allocate scratchpad memory') scikit-image-0.9.3/skimage/filter/_denoise.py000066400000000000000000000170631223313777300211540ustar00rootroot00000000000000import numpy as np from skimage import img_as_float def _denoise_tv_chambolle_3d(im, weight=100, eps=2.e-4, n_iter_max=200): """Perform total-variation denoising on 3D images. Parameters ---------- im : ndarray 3-D input data to be denoised. weight : float, optional Denoising weight. The greater `weight`, the more denoising (at the expense of fidelity to `input`). eps : float, optional Relative difference of the value of the cost function that determines the stop criterion. The algorithm stops when: (E_(n-1) - E_n) < eps * E_0 n_iter_max : int, optional Maximal number of iterations used for the optimization. Returns ------- out : ndarray Denoised array of floats. Notes ----- Rudin, Osher and Fatemi algorithm. Examples -------- >>> x, y, z = np.ogrid[0:40, 0:40, 0:40] >>> mask = (x - 22)**2 + (y - 20)**2 + (z - 17)**2 < 8**2 >>> mask = mask.astype(np.float) >>> mask += 0.2 * np.random.randn(*mask.shape) >>> res = denoise_tv_chambolle(mask, weight=100) """ px = np.zeros_like(im) py = np.zeros_like(im) pz = np.zeros_like(im) gx = np.zeros_like(im) gy = np.zeros_like(im) gz = np.zeros_like(im) d = np.zeros_like(im) i = 0 while i < n_iter_max: d = - px - py - pz d[1:] += px[:-1] d[:, 1:] += py[:, :-1] d[:, :, 1:] += pz[:, :, :-1] out = im + d E = (d**2).sum() gx[:-1] = np.diff(out, axis=0) gy[:, :-1] = np.diff(out, axis=1) gz[:, :, :-1] = np.diff(out, axis=2) norm = np.sqrt(gx**2 + gy**2 + gz**2) E += weight * norm.sum() norm *= 0.5 / weight norm += 1. px -= 1. / 6. * gx px /= norm py -= 1. / 6. * gy py /= norm pz -= 1 / 6. * gz pz /= norm E /= float(im.size) if i == 0: E_init = E E_previous = E else: if np.abs(E_previous - E) < eps * E_init: break else: E_previous = E i += 1 return out def _denoise_tv_chambolle_2d(im, weight=50, eps=2.e-4, n_iter_max=200): """Perform total-variation denoising on 2D images. Parameters ---------- im : ndarray Input data to be denoised. weight : float, optional Denoising weight. The greater `weight`, the more denoising (at the expense of fidelity to `input`) eps : float, optional Relative difference of the value of the cost function that determines the stop criterion. The algorithm stops when: (E_(n-1) - E_n) < eps * E_0 n_iter_max : int, optional Maximal number of iterations used for the optimization. Returns ------- out : ndarray Denoised array of floats. Notes ----- The principle of total variation denoising is explained in http://en.wikipedia.org/wiki/Total_variation_denoising. This code is an implementation of the algorithm of Rudin, Fatemi and Osher that was proposed by Chambolle in [1]_. References ---------- .. [1] A. Chambolle, An algorithm for total variation minimization and applications, Journal of Mathematical Imaging and Vision, Springer, 2004, 20, 89-97. Examples -------- >>> from skimage import color, data >>> lena = color.rgb2gray(data.lena()) >>> lena += 0.5 * lena.std() * np.random.randn(*lena.shape) >>> denoised_lena = denoise_tv_chambolle(lena, weight=60) """ px = np.zeros_like(im) py = np.zeros_like(im) gx = np.zeros_like(im) gy = np.zeros_like(im) d = np.zeros_like(im) i = 0 while i < n_iter_max: d = -px - py d[1:] += px[:-1] d[:, 1:] += py[:, :-1] out = im + d E = (d**2).sum() gx[:-1] = np.diff(out, axis=0) gy[:, :-1] = np.diff(out, axis=1) norm = np.sqrt(gx**2 + gy**2) E += weight * norm.sum() norm *= 0.5 / weight norm += 1 px -= 0.25 * gx px /= norm py -= 0.25 * gy py /= norm E /= float(im.size) if i == 0: E_init = E E_previous = E else: if np.abs(E_previous - E) < eps * E_init: break else: E_previous = E i += 1 return out def denoise_tv_chambolle(im, weight=50, eps=2.e-4, n_iter_max=200, multichannel=False): """Perform total-variation denoising on 2D and 3D images. Parameters ---------- im : ndarray (2d or 3d) of ints, uints or floats Input data to be denoised. `im` can be of any numeric type, but it is cast into an ndarray of floats for the computation of the denoised image. weight : float, optional Denoising weight. The greater `weight`, the more denoising (at the expense of fidelity to `input`). eps : float, optional Relative difference of the value of the cost function that determines the stop criterion. The algorithm stops when: (E_(n-1) - E_n) < eps * E_0 n_iter_max : int, optional Maximal number of iterations used for the optimization. multichannel : bool, optional Apply total-variation denoising separately for each channel. This option should be true for color images, otherwise the denoising is also applied in the 3rd dimension. Returns ------- out : ndarray Denoised image. Notes ----- Make sure to set the multichannel parameter appropriately for color images. The principle of total variation denoising is explained in http://en.wikipedia.org/wiki/Total_variation_denoising The principle of total variation denoising is to minimize the total variation of the image, which can be roughly described as the integral of the norm of the image gradient. Total variation denoising tends to produce "cartoon-like" images, that is, piecewise-constant images. This code is an implementation of the algorithm of Rudin, Fatemi and Osher that was proposed by Chambolle in [1]_. References ---------- .. [1] A. Chambolle, An algorithm for total variation minimization and applications, Journal of Mathematical Imaging and Vision, Springer, 2004, 20, 89-97. Examples -------- 2D example on Lena image: >>> from skimage import color, data >>> lena = color.rgb2gray(data.lena()) >>> lena += 0.5 * lena.std() * np.random.randn(*lena.shape) >>> denoised_lena = denoise_tv_chambolle(lena, weight=60) 3D example on synthetic data: >>> x, y, z = np.ogrid[0:40, 0:40, 0:40] >>> mask = (x - 22)**2 + (y - 20)**2 + (z - 17)**2 < 8**2 >>> mask = mask.astype(np.float) >>> mask += 0.2*np.random.randn(*mask.shape) >>> res = denoise_tv_chambolle(mask, weight=100) """ im_type = im.dtype if not im_type.kind == 'f': im = img_as_float(im) if im.ndim == 2: out = _denoise_tv_chambolle_2d(im, weight, eps, n_iter_max) elif im.ndim == 3: if multichannel: out = np.zeros_like(im) for c in range(im.shape[2]): out[..., c] = _denoise_tv_chambolle_2d(im[..., c], weight, eps, n_iter_max) else: out = _denoise_tv_chambolle_3d(im, weight, eps, n_iter_max) else: raise ValueError('only 2-d and 3-d images may be denoised with this ' 'function') return out scikit-image-0.9.3/skimage/filter/_denoise_cy.pyx000066400000000000000000000274561223313777300220460ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False cimport numpy as cnp import numpy as np from libc.math cimport exp, fabs, sqrt from libc.stdlib cimport malloc, free from libc.float cimport DBL_MAX from skimage._shared.interpolation cimport get_pixel3d from skimage.util import img_as_float from skimage._shared.utils import deprecated cdef inline double _gaussian_weight(double sigma, double value): return exp(-0.5 * (value / sigma)**2) cdef double* _compute_color_lut(Py_ssize_t bins, double sigma, double max_value): cdef: double* color_lut = malloc(bins * sizeof(double)) Py_ssize_t b for b in range(bins): color_lut[b] = _gaussian_weight(sigma, b * max_value / bins) return color_lut cdef double* _compute_range_lut(Py_ssize_t win_size, double sigma): cdef: double* range_lut = malloc(win_size**2 * sizeof(double)) Py_ssize_t kr, kc Py_ssize_t window_ext = (win_size - 1) / 2 double dist for kr in range(win_size): for kc in range(win_size): dist = sqrt((kr - window_ext)**2 + (kc - window_ext)**2) range_lut[kr * win_size + kc] = _gaussian_weight(sigma, dist) return range_lut def denoise_bilateral(image, Py_ssize_t win_size=5, sigma_range=None, double sigma_spatial=1, Py_ssize_t bins=10000, mode='constant', double cval=0): """Denoise image using bilateral filter. This is an edge-preserving and noise reducing denoising filter. It averages pixels based on their spatial closeness and radiometric similarity. Spatial closeness is measured by the gaussian function of the euclidian distance between two pixels and a certain standard deviation (`sigma_spatial`). Radiometric similarity is measured by the gaussian function of the euclidian distance between two color values and a certain standard deviation (`sigma_range`). Parameters ---------- image : ndarray Input image. win_size : int Window size for filtering. sigma_range : float Standard deviation for grayvalue/color distance (radiometric similarity). A larger value results in averaging of pixels with larger radiometric differences. Note, that the image will be converted using the `img_as_float` function and thus the standard deviation is in respect to the range `[0, 1]`. sigma_spatial : float Standard deviation for range distance. A larger value results in averaging of pixels with larger spatial differences. bins : int Number of discrete values for gaussian weights of color filtering. A larger value results in improved accuracy. mode : string How to handle values outside the image borders. See `scipy.ndimage.map_coordinates` for detail. cval : string Used in conjunction with mode 'constant', the value outside the image boundaries. Returns ------- denoised : ndarray Denoised image. References ---------- .. [1] http://users.soe.ucsc.edu/~manduchi/Papers/ICCV98.pdf """ image = np.atleast_3d(img_as_float(image)) # if image.max() is 0, then dist_scale can have an unverified value # and color_lut[(dist * dist_scale)] may cause a segmentation fault # so we verify we have a positive image and that the max is not 0.0. if image.min() < 0.0: raise ValueError("Image must contain only positive values") cdef: Py_ssize_t rows = image.shape[0] Py_ssize_t cols = image.shape[1] Py_ssize_t dims = image.shape[2] Py_ssize_t window_ext = (win_size - 1) / 2 double max_value double[:, :, ::1] cimage double[:, :, ::1] out double* color_lut double* range_lut Py_ssize_t r, c, d, wr, wc, kr, kc, rr, cc, pixel_addr double value, weight, dist, total_weight, csigma_range, color_weight, \ range_weight double dist_scale double* values double* centres double* total_values if sigma_range is None: csigma_range = image.std() else: csigma_range = sigma_range max_value = image.max() if max_value == 0.0: raise ValueError("The maximum value found in the image was 0.") cimage = np.ascontiguousarray(image) out = np.zeros((rows, cols, dims), dtype=np.double) color_lut = _compute_color_lut(bins, csigma_range, max_value) range_lut = _compute_range_lut(win_size, sigma_spatial) dist_scale = bins / dims / max_value values = malloc(dims * sizeof(double)) centres = malloc(dims * sizeof(double)) total_values = malloc(dims * sizeof(double)) if mode not in ('constant', 'wrap', 'reflect', 'nearest'): raise ValueError("Invalid mode specified. Please use " "`constant`, `nearest`, `wrap` or `reflect`.") cdef char cmode = ord(mode[0].upper()) for r in range(rows): for c in range(cols): total_weight = 0 for d in range(dims): total_values[d] = 0 centres[d] = cimage[r, c, d] for wr in range(-window_ext, window_ext + 1): rr = wr + r kr = wr + window_ext for wc in range(-window_ext, window_ext + 1): cc = wc + c kc = wc + window_ext # save pixel values for all dims and compute euclidian # distance between centre stack and current position dist = 0 for d in range(dims): value = get_pixel3d(&cimage[0, 0, 0], rows, cols, dims, rr, cc, d, cmode, cval) values[d] = value dist += (centres[d] - value)**2 dist = sqrt(dist) range_weight = range_lut[kr * win_size + kc] color_weight = color_lut[(dist * dist_scale)] weight = range_weight * color_weight for d in range(dims): total_values[d] += values[d] * weight total_weight += weight for d in range(dims): out[r, c, d] = total_values[d] / total_weight free(color_lut) free(range_lut) free(values) free(centres) free(total_values) return np.squeeze(np.asarray(out)) def denoise_tv_bregman(image, double weight, int max_iter=100, double eps=1e-3, char isotropic=True): """Perform total-variation denoising using split-Bregman optimization. Total-variation denoising (also know as total-variation regularization) tries to find an image with less total-variation under the constraint of being similar to the input image, which is controlled by the regularization parameter. Parameters ---------- image : ndarray Input data to be denoised (converted using img_as_float`). weight : float, optional Denoising weight. The smaller the `weight`, the more denoising (at the expense of less similarity to the `input`). The regularization parameter `lambda` is chosen as `2 * weight`. eps : float, optional Relative difference of the value of the cost function that determines the stop criterion. The algorithm stops when:: SUM((u(n) - u(n-1))**2) < eps max_iter : int, optional Maximal number of iterations used for the optimization. isotropic : boolean, optional Switch between isotropic and anisotropic TV denoising. Returns ------- u : ndarray Denoised image. References ---------- .. [1] http://en.wikipedia.org/wiki/Total_variation_denoising .. [2] Tom Goldstein and Stanley Osher, "The Split Bregman Method For L1 Regularized Problems", ftp://ftp.math.ucla.edu/pub/camreport/cam08-29.pdf .. [3] Pascal Getreuer, "Rudin–Osher–Fatemi Total Variation Denoising using Split Bregman" in Image Processing On Line on 2012–05–19, http://www.ipol.im/pub/art/2012/g-tvd/article_lr.pdf .. [4] http://www.math.ucsb.edu/~cgarcia/UGProjects/BregmanAlgorithms_JacquelineBush.pdf """ image = np.atleast_3d(img_as_float(image)) cdef: Py_ssize_t rows = image.shape[0] Py_ssize_t cols = image.shape[1] Py_ssize_t dims = image.shape[2] Py_ssize_t rows2 = rows + 2 Py_ssize_t cols2 = cols + 2 Py_ssize_t r, c, k Py_ssize_t total = rows * cols * dims shape_ext = (rows2, cols2, dims) u = np.zeros(shape_ext, dtype=np.double) cdef: double[:, :, ::1] cimage = np.ascontiguousarray(image) double[:, :, ::1] cu = u double[:, :, ::1] dx = np.zeros(shape_ext, dtype=np.double) double[:, :, ::1] dy = np.zeros(shape_ext, dtype=np.double) double[:, :, ::1] bx = np.zeros(shape_ext, dtype=np.double) double[:, :, ::1] by = np.zeros(shape_ext, dtype=np.double) double ux, uy, uprev, unew, bxx, byy, dxx, dyy, s int i = 0 double lam = 2 * weight double rmse = DBL_MAX double norm = (weight + 4 * lam) u[1:-1, 1:-1] = image # reflect image u[0, 1:-1] = image[1, :] u[1:-1, 0] = image[:, 1] u[-1, 1:-1] = image[-2, :] u[1:-1, -1] = image[:, -2] while i < max_iter and rmse > eps: rmse = 0 for k in range(dims): for r in range(1, rows + 1): for c in range(1, cols + 1): uprev = cu[r, c, k] # forward derivatives ux = cu[r, c + 1, k] - uprev uy = cu[r + 1, c, k] - uprev # Gauss-Seidel method unew = ( lam * ( + cu[r + 1, c, k] + cu[r - 1, c, k] + cu[r, c + 1, k] + cu[r, c - 1, k] + dx[r, c - 1, k] - dx[r, c, k] + dy[r - 1, c, k] - dy[r, c, k] - bx[r, c - 1, k] + bx[r, c, k] - by[r - 1, c, k] + by[r, c, k] ) + weight * cimage[r - 1, c - 1, k] ) / norm cu[r, c, k] = unew # update root mean square error rmse += (unew - uprev)**2 bxx = bx[r, c, k] byy = by[r, c, k] # d_subproblem after reference [4] if isotropic: s = sqrt((ux + bxx)**2 + (uy + byy)**2) dxx = s * lam * (ux + bxx) / (s * lam + 1) dyy = s * lam * (uy + byy) / (s * lam + 1) else: s = ux + bxx if s > 1 / lam: dxx = s - 1/lam elif s < -1 / lam: dxx = s + 1 / lam else: dxx = 0 s = uy + byy if s > 1 / lam: dyy = s - 1 / lam elif s < -1 / lam: dyy = s + 1 / lam else: dyy = 0 dx[r, c, k] = dxx dy[r, c, k] = dyy bx[r, c, k] += ux - dxx by[r, c, k] += uy - dyy rmse = sqrt(rmse / total) i += 1 return np.squeeze(np.asarray(u[1:-1, 1:-1])) scikit-image-0.9.3/skimage/filter/_gabor.py000066400000000000000000000104141223313777300206110ustar00rootroot00000000000000import numpy as np from scipy import ndimage __all__ = ['gabor_kernel', 'gabor_filter'] def _sigma_prefactor(bandwidth): b = bandwidth # See http://www.cs.rug.nl/~imaging/simplecell.html return 1.0 / np.pi * np.sqrt(np.log(2)/2.0) * (2.0**b + 1) / (2.0**b - 1) def gabor_kernel(frequency, theta=0, bandwidth=1, sigma_x=None, sigma_y=None, offset=0): """Return complex 2D Gabor filter kernel. Frequency and orientation representations of the Gabor filter are similar to those of the human visual system. It is especially suitable for texture classification using Gabor filter banks. Parameters ---------- frequency : float Frequency of the harmonic function. theta : float Orientation in radians. If 0, the harmonic is in the x-direction. bandwidth : float The bandwidth captured by the filter. For fixed bandwidth, `sigma_x` and `sigma_y` will decrease with increasing frequency. This value is ignored if `sigma_x` and `sigma_y` are set by the user. sigma_x, sigma_y : float Standard deviation in x- and y-directions. These directions apply to the kernel *before* rotation. If `theta = pi/2`, then the kernel is rotated 90 degrees so that `sigma_x` controls the *vertical* direction. offset : float, optional Phase offset of harmonic function in radians. Returns ------- g : complex array Complex filter kernel. References ---------- .. [1] http://en.wikipedia.org/wiki/Gabor_filter .. [2] http://mplab.ucsd.edu/tutorials/gabor.pdf """ if sigma_x is None: sigma_x = _sigma_prefactor(bandwidth) / frequency if sigma_y is None: sigma_y = _sigma_prefactor(bandwidth) / frequency n_stds = 3 x0 = np.ceil(max(np.abs(n_stds * sigma_x * np.cos(theta)), np.abs(n_stds * sigma_y * np.sin(theta)), 1)) y0 = np.ceil(max(np.abs(n_stds * sigma_y * np.cos(theta)), np.abs(n_stds * sigma_x * np.sin(theta)), 1)) y, x = np.mgrid[-y0:y0+1, -x0:x0+1] rotx = x * np.cos(theta) + y * np.sin(theta) roty = -x * np.sin(theta) + y * np.cos(theta) g = np.zeros(y.shape, dtype=np.complex) g[:] = np.exp(-0.5 * (rotx**2 / sigma_x**2 + roty**2 / sigma_y**2)) g /= 2 * np.pi * sigma_x * sigma_y g *= np.exp(1j * (2 * np.pi * frequency * rotx + offset)) return g def gabor_filter(image, frequency, theta=0, bandwidth=1, sigma_x=None, sigma_y=None, offset=0, mode='reflect', cval=0): """Return real and imaginary responses to Gabor filter. The real and imaginary parts of the Gabor filter kernel are applied to the image and the response is returned as a pair of arrays. Frequency and orientation representations of the Gabor filter are similar to those of the human visual system. It is especially suitable for texture classification using Gabor filter banks. Parameters ---------- image : array Input image. frequency : float Frequency of the harmonic function. theta : float Orientation in radians. If 0, the harmonic is in the x-direction. bandwidth : float The bandwidth captured by the filter. For fixed bandwidth, `sigma_x` and `sigma_y` will decrease with increasing frequency. This value is ignored if `sigma_x` and `sigma_y` are set by the user. sigma_x, sigma_y : float Standard deviation in x- and y-directions. These directions apply to the kernel *before* rotation. If `theta = pi/2`, then the kernel is rotated 90 degrees so that `sigma_x` controls the *vertical* direction. offset : float, optional Phase offset of harmonic function in radians. Returns ------- real, imag : arrays Filtered images using the real and imaginary parts of the Gabor filter kernel. References ---------- .. [1] http://en.wikipedia.org/wiki/Gabor_filter .. [2] http://mplab.ucsd.edu/tutorials/gabor.pdf """ g = gabor_kernel(frequency, theta, bandwidth, sigma_x, sigma_y, offset) filtered_real = ndimage.convolve(image, np.real(g), mode=mode, cval=cval) filtered_imag = ndimage.convolve(image, np.imag(g), mode=mode, cval=cval) return filtered_real, filtered_imag scikit-image-0.9.3/skimage/filter/_gaussian.py000066400000000000000000000076501223313777300213410ustar00rootroot00000000000000import collections as coll import numpy as np from scipy import ndimage import warnings from ..util import img_as_float from ..color import guess_spatial_dimensions __all__ = ['gaussian_filter'] def gaussian_filter(image, sigma, output=None, mode='nearest', cval=0, multichannel=None): """ Multi-dimensional Gaussian filter Parameters ---------- image : array-like input image (grayscale or color) to filter. sigma : scalar or sequence of scalars standard deviation for Gaussian kernel. The standard deviations of the Gaussian filter are given for each axis as a sequence, or as a single number, in which case it is equal for all axes. output : array, optional The ``output`` parameter passes an array in which to store the filter output. mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional The `mode` parameter determines how the array borders are handled, where `cval` is the value when mode is equal to 'constant'. Default is 'nearest'. cval : scalar, optional Value to fill past edges of input if `mode` is 'constant'. Default is 0.0 multichannel : bool, optional (default: None) Whether the last axis of the image is to be interpreted as multiple channels. If True, each channel is filtered separately (channels are not mixed together). Only 3 channels are supported. If `None`, the function will attempt to guess this, and raise a warning if ambiguous, when the array has shape (M, N, 3). Returns ------- filtered_image : ndarray the filtered array Notes ----- This function is a wrapper around :func:`scipy.ndimage.gaussian_filter`. Integer arrays are converted to float. The multi-dimensional filter is implemented as a sequence of one-dimensional convolution filters. The intermediate arrays are stored in the same data type as the output. Therefore, for output types with a limited precision, the results may be imprecise because intermediate results may be stored with insufficient precision. Examples -------- >>> a = np.zeros((3, 3)) >>> a[1, 1] = 1 >>> a array([[ 0., 0., 0.], [ 0., 1., 0.], [ 0., 0., 0.]]) >>> gaussian_filter(a, sigma=0.4) # mild smoothing array([[ 0.00163116, 0.03712502, 0.00163116], [ 0.03712502, 0.84496158, 0.03712502], [ 0.00163116, 0.03712502, 0.00163116]]) >>> gaussian_filter(a, sigma=1) # more smooting array([[ 0.05855018, 0.09653293, 0.05855018], [ 0.09653293, 0.15915589, 0.09653293], [ 0.05855018, 0.09653293, 0.05855018]]) >>> # Several modes are possible for handling boundaries >>> gaussian_filter(a, sigma=1, mode='reflect') array([[ 0.08767308, 0.12075024, 0.08767308], [ 0.12075024, 0.16630671, 0.12075024], [ 0.08767308, 0.12075024, 0.08767308]]) >>> # For RGB images, each is filtered separately >>> from skimage.data import lena >>> image = lena() >>> filtered_lena = gaussian_filter(image, sigma=1, multichannel=True) """ spatial_dims = guess_spatial_dimensions(image) if spatial_dims is None and multichannel is None: msg = ("Images with dimensions (M, N, 3) are interpreted as 2D+RGB" + " by default. Use `multichannel=False` to interpret as " + " 3D image with last dimension of length 3.") warnings.warn(RuntimeWarning(msg)) multichannel = True if multichannel: # do not filter across channels if not isinstance(sigma, coll.Iterable): sigma = [sigma] * (image.ndim - 1) if len(sigma) != image.ndim: sigma = np.concatenate((np.asarray(sigma), [0])) image = img_as_float(image) return ndimage.gaussian_filter(image, sigma, mode=mode, cval=cval) scikit-image-0.9.3/skimage/filter/_rank_order.py000066400000000000000000000040061223313777300216450ustar00rootroot00000000000000"""rankorder.py - convert an image of any type to an image of ints whose pixels have an identical rank order compared to the original image Originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentstky """ import numpy as np def rank_order(image): """Return an image of the same shape where each pixel is the index of the pixel value in the ascending order of the unique values of `image`, aka the rank-order value. Parameters ---------- image: ndarray Returns ------- labels: ndarray of type np.uint32, of shape image.shape New array where each pixel has the rank-order value of the corresponding pixel in `image`. Pixel values are between 0 and n - 1, where n is the number of distinct unique values in `image`. original_values: 1-d ndarray Unique original values of `image` Examples -------- >>> a = np.array([[1, 4, 5], [4, 4, 1], [5, 1, 1]]) >>> a array([[1, 4, 5], [4, 4, 1], [5, 1, 1]]) >>> rank_order(a) (array([[0, 1, 2], [1, 1, 0], [2, 0, 0]], dtype=uint32), array([1, 4, 5])) >>> b = np.array([-1., 2.5, 3.1, 2.5]) >>> rank_order(b) (array([0, 1, 2, 1], dtype=uint32), array([-1. , 2.5, 3.1])) """ flat_image = image.ravel() sort_order = flat_image.argsort().astype(np.uint32) flat_image = flat_image[sort_order] sort_rank = np.zeros_like(sort_order) is_different = flat_image[:-1] != flat_image[1:] np.cumsum(is_different, out=sort_rank[1:]) original_values = np.zeros((sort_rank[-1] + 1,), image.dtype) original_values[0] = flat_image[0] original_values[1:] = flat_image[1:][is_different] int_image = np.zeros_like(sort_order) int_image[sort_order] = sort_rank return (int_image.reshape(image.shape), original_values) scikit-image-0.9.3/skimage/filter/ctmf.py000066400000000000000000000071201223313777300203110ustar00rootroot00000000000000"""ctmf.py - constant time per pixel median filtering with an octagonal shape Reference: S. Perreault and P. Hebert, "Median Filtering in Constant Time", IEEE Transactions on Image Processing, September 2007. Originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky """ import warnings import numpy as np from . import _ctmf from ._rank_order import rank_order from .._shared.utils import deprecated @deprecated('filter.rank.median') def median_filter(image, radius=2, mask=None, percent=50): """Masked median filter with octagon shape. Parameters ---------- image : (M, N) ndarray Input image. radius : int Radius (in pixels) of a circle inscribed into the filtering octagon. Must be at least 2. Default radius is 2. mask : (M, N) ndarray Mask with 1's for significant pixels, 0's for masked pixels. By default, all pixels are considered significant. percent : int The unmasked pixels within the octagon are sorted, and the value at `percent` percent of the index range is chosen. Default value of 50 gives the median pixel. Returns ------- out : (M, N) ndarray Filtered array. In areas where the median filter does not overlap the mask, the filtered result is undefined, but in practice, it will be the lowest value in the valid area. Notes ----- Because of the histogram implementation, the number of unique values for the output is limited to 256. Examples -------- >>> a = np.ones((5, 5)) >>> a[2, 2] = 10 # introduce outlier >>> b = median_filter(a) >>> b[2, 2] # the median filter is good at removing outliers 1.0 """ if image.ndim != 2: raise TypeError("Input 'image' must be a two-dimensional array.") if radius < 2: raise ValueError("Input 'radius' must be >= 2.") if mask is None: mask = np.ones(image.shape, dtype=np.bool) mask = np.ascontiguousarray(mask, dtype=np.bool) if np.all(~ mask): warnings.warn('Mask is all over image! Returning copy of input image.') return image.copy() if (not np.issubdtype(image.dtype, np.int) or np.min(image) < 0 or np.max(image) > 255): ranked_values, translation = rank_order(image[mask]) max_ranked_values = np.max(ranked_values) if max_ranked_values == 0: warnings.warn('Particular case? Returning copy of input image.') return image.copy() if max_ranked_values > 255: ranked_values = ranked_values * 255 // max_ranked_values was_ranked = True else: ranked_values = image[mask] was_ranked = False ranked_image = np.zeros(image.shape, np.uint8) ranked_image[mask] = ranked_values mask.dtype = np.uint8 output = np.zeros(image.shape, np.uint8) _ctmf.median_filter(ranked_image, mask, output, radius, percent) if was_ranked: # # The translation gives the original value at each ranking. # We rescale the output to the original ranking and then # use the translation to look up the original value in the image. # if max_ranked_values > 255: result = translation[output.astype(np.uint32) * max_ranked_values // 255] else: result = translation[output] else: result = output return result scikit-image-0.9.3/skimage/filter/edges.py000066400000000000000000000265531223313777300204620ustar00rootroot00000000000000""" Sobel and Prewitt filters originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky """ import numpy as np from skimage import img_as_float from scipy.ndimage import convolve, binary_erosion, generate_binary_structure EROSION_SELEM = generate_binary_structure(2, 2) HSOBEL_WEIGHTS = np.array([[ 1, 2, 1], [ 0, 0, 0], [-1,-2,-1]]) / 4.0 VSOBEL_WEIGHTS = HSOBEL_WEIGHTS.T HSCHARR_WEIGHTS = np.array([[ 3, 10, 3], [ 0, 0, 0], [-3, -10, -3]]) / 16.0 VSCHARR_WEIGHTS = HSCHARR_WEIGHTS.T HPREWITT_WEIGHTS = np.array([[ 1, 1, 1], [ 0, 0, 0], [-1,-1,-1]]) / 3.0 VPREWITT_WEIGHTS = HPREWITT_WEIGHTS.T ROBERTS_PD_WEIGHTS = np.array([[1, 0], [0, -1]], dtype=np.double) ROBERTS_ND_WEIGHTS = np.array([[0, 1], [-1, 0]], dtype=np.double) def _mask_filter_result(result, mask): """Return result after masking. Input masks are eroded so that mask areas in the original image don't affect values in the result. """ if mask is None: result[0, :] = 0 result[-1, :] = 0 result[:, 0] = 0 result[:, -1] = 0 return result else: mask = binary_erosion(mask, EROSION_SELEM, border_value=0) return result * mask def sobel(image, mask=None): """Find the edge magnitude using the Sobel transform. Parameters ---------- image : 2-D array Image to process. mask : 2-D array, optional An optional mask to limit the application to a certain area. Note that pixels surrounding masked regions are also masked to prevent masked regions from affecting the result. Returns ------- output : 2-D array The Sobel edge map. Notes ----- Take the square root of the sum of the squares of the horizontal and vertical Sobels to get a magnitude that's somewhat insensitive to direction. Note that ``scipy.ndimage.sobel`` returns a directional Sobel which has to be further processed to perform edge detection. """ return np.sqrt(hsobel(image, mask)**2 + vsobel(image, mask)**2) def hsobel(image, mask=None): """Find the horizontal edges of an image using the Sobel transform. Parameters ---------- image : 2-D array Image to process. mask : 2-D array, optional An optional mask to limit the application to a certain area. Note that pixels surrounding masked regions are also masked to prevent masked regions from affecting the result. Returns ------- output : 2-D array The Sobel edge map. Notes ----- We use the following kernel and return the absolute value of the result at each point:: 1 2 1 0 0 0 -1 -2 -1 """ image = img_as_float(image) result = np.abs(convolve(image, HSOBEL_WEIGHTS)) return _mask_filter_result(result, mask) def vsobel(image, mask=None): """Find the vertical edges of an image using the Sobel transform. Parameters ---------- image : 2-D array Image to process mask : 2-D array, optional An optional mask to limit the application to a certain area Note that pixels surrounding masked regions are also masked to prevent masked regions from affecting the result. Returns ------- output : 2-D array The Sobel edge map. Notes ----- We use the following kernel and return the absolute value of the result at each point:: 1 0 -1 2 0 -2 1 0 -1 """ image = img_as_float(image) result = np.abs(convolve(image, VSOBEL_WEIGHTS)) return _mask_filter_result(result, mask) def scharr(image, mask=None): """Find the edge magnitude using the Scharr transform. Parameters ---------- image : 2-D array Image to process. mask : 2-D array, optional An optional mask to limit the application to a certain area. Note that pixels surrounding masked regions are also masked to prevent masked regions from affecting the result. Returns ------- output : 2-D array The Scharr edge map. Notes ----- Take the square root of the sum of the squares of the horizontal and vertical Scharrs to get a magnitude that's somewhat insensitive to direction. References ---------- .. [1] D. Kroon, 2009, Short Paper University Twente, Numerical Optimization of Kernel Based Image Derivatives. """ return np.sqrt(hscharr(image, mask)**2 + vscharr(image, mask)**2) def hscharr(image, mask=None): """Find the horizontal edges of an image using the Scharr transform. Parameters ---------- image : 2-D array Image to process. mask : 2-D array, optional An optional mask to limit the application to a certain area. Note that pixels surrounding masked regions are also masked to prevent masked regions from affecting the result. Returns ------- output : 2-D array The Scharr edge map. Notes ----- We use the following kernel and return the absolute value of the result at each point:: 3 10 3 0 0 0 -3 -10 -3 References ---------- .. [1] D. Kroon, 2009, Short Paper University Twente, Numerical Optimization of Kernel Based Image Derivatives. """ image = img_as_float(image) result = np.abs(convolve(image, HSCHARR_WEIGHTS)) return _mask_filter_result(result, mask) def vscharr(image, mask=None): """Find the vertical edges of an image using the Scharr transform. Parameters ---------- image : 2-D array Image to process mask : 2-D array, optional An optional mask to limit the application to a certain area Note that pixels surrounding masked regions are also masked to prevent masked regions from affecting the result. Returns ------- output : 2-D array The Scharr edge map. Notes ----- We use the following kernel and return the absolute value of the result at each point:: 3 0 -3 10 0 -10 3 0 -3 References ---------- .. [1] D. Kroon, 2009, Short Paper University Twente, Numerical Optimization of Kernel Based Image Derivatives. """ image = img_as_float(image) result = np.abs(convolve(image, VSCHARR_WEIGHTS)) return _mask_filter_result(result, mask) def prewitt(image, mask=None): """Find the edge magnitude using the Prewitt transform. Parameters ---------- image : 2-D array Image to process. mask : 2-D array, optional An optional mask to limit the application to a certain area. Note that pixels surrounding masked regions are also masked to prevent masked regions from affecting the result. Returns ------- output : 2-D array The Prewitt edge map. Notes ----- Return the square root of the sum of squares of the horizontal and vertical Prewitt transforms. """ return np.sqrt(hprewitt(image, mask)**2 + vprewitt(image, mask)**2) def hprewitt(image, mask=None): """Find the horizontal edges of an image using the Prewitt transform. Parameters ---------- image : 2-D array Image to process. mask : 2-D array, optional An optional mask to limit the application to a certain area. Note that pixels surrounding masked regions are also masked to prevent masked regions from affecting the result. Returns ------- output : 2-D array The Prewitt edge map. Notes ----- We use the following kernel and return the absolute value of the result at each point:: 1 1 1 0 0 0 -1 -1 -1 """ image = img_as_float(image) result = np.abs(convolve(image, HPREWITT_WEIGHTS)) return _mask_filter_result(result, mask) def vprewitt(image, mask=None): """Find the vertical edges of an image using the Prewitt transform. Parameters ---------- image : 2-D array Image to process. mask : 2-D array, optional An optional mask to limit the application to a certain area. Note that pixels surrounding masked regions are also masked to prevent masked regions from affecting the result. Returns ------- output : 2-D array The Prewitt edge map. Notes ----- We use the following kernel and return the absolute value of the result at each point:: 1 0 -1 1 0 -1 1 0 -1 """ image = img_as_float(image) result = np.abs(convolve(image, VPREWITT_WEIGHTS)) return _mask_filter_result(result, mask) def roberts(image, mask=None): """Find the edge magnitude using Roberts' cross operator. Parameters ---------- image : 2-D array Image to process. mask : 2-D array, optional An optional mask to limit the application to a certain area. Note that pixels surrounding masked regions are also masked to prevent masked regions from affecting the result. Returns ------- output : 2-D array The Roberts' Cross edge map. """ return np.sqrt(roberts_positive_diagonal(image, mask)**2 + roberts_negative_diagonal(image, mask)**2) def roberts_positive_diagonal(image, mask=None): """Find the cross edges of an image using Roberts' cross operator. The kernel is applied to the input image to produce separate measurements of the gradient component one orientation. Parameters ---------- image : 2-D array Image to process. mask : 2-D array, optional An optional mask to limit the application to a certain area. Note that pixels surrounding masked regions are also masked to prevent masked regions from affecting the result. Returns ------- output : 2-D array The Robert's edge map. Notes ----- We use the following kernel and return the absolute value of the result at each point:: 1 0 0 -1 """ image = img_as_float(image) result = np.abs(convolve(image, ROBERTS_PD_WEIGHTS)) return _mask_filter_result(result, mask) def roberts_negative_diagonal(image, mask=None): """Find the cross edges of an image using the Roberts' Cross operator. The kernel is applied to the input image to produce separate measurements of the gradient component one orientation. Parameters ---------- image : 2-D array Image to process. mask : 2-D array, optional An optional mask to limit the application to a certain area. Note that pixels surrounding masked regions are also masked to prevent masked regions from affecting the result. Returns ------- output : 2-D array The Robert's edge map. Notes ----- We use the following kernel and return the absolute value of the result at each point:: 0 1 -1 0 """ image = img_as_float(image) result = np.abs(convolve(image, ROBERTS_ND_WEIGHTS)) return _mask_filter_result(result, mask) scikit-image-0.9.3/skimage/filter/lpi_filter.py000066400000000000000000000157151223313777300215220ustar00rootroot00000000000000""" :author: Stefan van der Walt, 2008 :license: modified BSD """ import numpy as np from scipy.fftpack import ifftshift eps = np.finfo(float).eps def _min_limit(x, val=eps): mask = np.abs(x) < eps x[mask] = np.sign(x[mask]) * eps def _centre(x, oshape): """Return an array of oshape from the centre of x. """ start = (np.array(x.shape) - np.array(oshape)) / 2. + 1 out = x[[slice(s, s + n) for s, n in zip(start, oshape)]] return out def _pad(data, shape): """Pad the data to the given shape with zeros. Parameters ---------- data : 2-d ndarray Input data shape : (2,) tuple """ out = np.zeros(shape) out[[slice(0, n) for n in data.shape]] = data return out class LPIFilter2D(object): """Linear Position-Invariant Filter (2-dimensional) """ def __init__(self, impulse_response, **filter_params): """ Parameters ---------- impulse_response : callable `f(r, c, **filter_params)` Function that yields the impulse response. `r` and `c` are 1-dimensional vectors that represent row and column positions, in other words coordinates are (r[0],c[0]),(r[0],c[1]) etc. `**filter_params` are passed through. In other words, `impulse_response` would be called like this: >>> def impulse_response(r, c, **filter_params): ... pass >>> >>> r = [0,0,0,1,1,1,2,2,2] >>> c = [0,1,2,0,1,2,0,1,2] >>> filter_params = {'kw1': 1, 'kw2': 2, 'kw3': 3} >>> impulse_response(r, c, **filter_params) Examples -------- Gaussian filter: Use a 1-D gaussian in each direction without normalization coefficients. >>> def filt_func(r, c, sigma = 1): ... return np.exp(-np.hypot(r, c)/sigma) >>> filter = LPIFilter2D(filt_func) """ if not callable(impulse_response): raise ValueError("Impulse response must be a callable.") self.impulse_response = impulse_response self.filter_params = filter_params self._cache = None def _prepare(self, data): """Calculate filter and data FFT in preparation for filtering. """ dshape = np.array(data.shape) dshape += (dshape % 2 == 0) # all filter dimensions must be uneven oshape = np.array(data.shape) * 2 - 1 if self._cache is None or np.any(self._cache.shape != oshape): coords = np.mgrid[[slice(0, float(n)) for n in dshape]] # this steps over two sets of coordinates, # not over the coordinates individually for k, coord in enumerate(coords): coord -= (dshape[k] - 1) / 2. coords = coords.reshape(2, -1).T # coordinate pairs (r,c) f = self.impulse_response(coords[:, 0], coords[:, 1], **self.filter_params).reshape(dshape) f = _pad(f, oshape) F = np.dual.fftn(f) self._cache = F else: F = self._cache data = _pad(data, oshape) G = np.dual.fftn(data) return F, G def __call__(self, data): """Apply the filter to the given data. Parameters ---------- data : (M,N) ndarray """ F, G = self._prepare(data) out = np.dual.ifftn(F * G) out = np.abs(_centre(out, data.shape)) return out def forward(data, impulse_response=None, filter_params={}, predefined_filter=None): """Apply the given filter to data. Parameters ---------- data : (M,N) ndarray Input data. impulse_response : callable `f(r, c, **filter_params)` Impulse response of the filter. See LPIFilter2D.__init__. filter_params : dict Additional keyword parameters to the impulse_response function. Other Parameters ---------------- predefined_filter : LPIFilter2D If you need to apply the same filter multiple times over different images, construct the LPIFilter2D and specify it here. Examples -------- Gaussian filter: >>> def filt_func(r, c): ... return np.exp(-np.hypot(r, c)/1) >>> >>> from skimage import data >>> filtered = forward(data.coins(), filt_func) """ if predefined_filter is None: predefined_filter = LPIFilter2D(impulse_response, **filter_params) return predefined_filter(data) def inverse(data, impulse_response=None, filter_params={}, max_gain=2, predefined_filter=None): """Apply the filter in reverse to the given data. Parameters ---------- data : (M,N) ndarray Input data. impulse_response : callable `f(r, c, **filter_params)` Impulse response of the filter. See LPIFilter2D.__init__. filter_params : dict Additional keyword parameters to the impulse_response function. max_gain : float Limit the filter gain. Often, the filter contains zeros, which would cause the inverse filter to have infinite gain. High gain causes amplification of artefacts, so a conservative limit is recommended. Other Parameters ---------------- predefined_filter : LPIFilter2D If you need to apply the same filter multiple times over different images, construct the LPIFilter2D and specify it here. """ if predefined_filter is None: filt = LPIFilter2D(impulse_response, **filter_params) else: filt = predefined_filter F, G = filt._prepare(data) _min_limit(F) F = 1 / F mask = np.abs(F) > max_gain F[mask] = np.sign(F[mask]) * max_gain return _centre(np.abs(ifftshift(np.dual.ifftn(G * F))), data.shape) def wiener(data, impulse_response=None, filter_params={}, K=0.25, predefined_filter=None): """Minimum Mean Square Error (Wiener) inverse filter. Parameters ---------- data : (M,N) ndarray Input data. K : float or (M,N) ndarray Ratio between power spectrum of noise and undegraded image. impulse_response : callable `f(r, c, **filter_params)` Impulse response of the filter. See LPIFilter2D.__init__. filter_params : dict Additional keyword parameters to the impulse_response function. Other Parameters ---------------- predefined_filter : LPIFilter2D If you need to apply the same filter multiple times over different images, construct the LPIFilter2D and specify it here. """ if predefined_filter is None: filt = LPIFilter2D(impulse_response, **filter_params) else: filt = predefined_filter F, G = filt._prepare(data) _min_limit(F) H_mag_sqr = np.abs(F)**2 F = 1 / F * H_mag_sqr / (H_mag_sqr + K) return _centre(np.abs(ifftshift(np.dual.ifftn(G * F))), data.shape) def constrained_least_squares(data, lam, impulse_response=None, filter_params={}): raise NotImplementedError scikit-image-0.9.3/skimage/filter/rank/000077500000000000000000000000001223313777300177415ustar00rootroot00000000000000scikit-image-0.9.3/skimage/filter/rank/.gitignore000066400000000000000000000000051223313777300217240ustar00rootroot00000000000000demo/scikit-image-0.9.3/skimage/filter/rank/README.rst000066400000000000000000000024371223313777300214360ustar00rootroot00000000000000To do ----- * add simple examples, adapt documentation on existing examples * add/check existing doc * adapting tests for each type of filter General remarks --------------- Basically these filters compute local histogram for each pixel. A histogram is built using a moving window in order to limit redundant computation. The path followed by the moving window is given hereunder ...-----------------------\ /--------------------------/ \-------------------------- ... We compare cmorph.dilate to this histogram based method to show how computational costs increase with respect to image size or structuring element size. This implementation gives better results for large structuring elements. The local histogram is updated at each pixel as the structuring element window moves by, i.e. only those pixels entering and leaving the structuring element update the local histogram. The histogram size is 8-bit (256 bins) for 8-bit images and 2 to 16-bit for 16-bit images depending on the maximum value of the image. The filter is applied up to the image border, the neighboorhood used is adjusted accordingly. The user may provide a mask image (same size as input image) where non zero values are the part of the image participating in the histogram computation. By default the entire image is filtered. scikit-image-0.9.3/skimage/filter/rank/__init__.py000066400000000000000000000047521223313777300220620ustar00rootroot00000000000000from .generic import (autolevel, bottomhat, equalize, gradient, maximum, mean, subtract_mean, median, minimum, modal, enhance_contrast, pop, threshold, tophat, noise_filter, entropy, otsu) from .percentile import (autolevel_percentile, gradient_percentile, mean_percentile, subtract_mean_percentile, enhance_contrast_percentile, percentile, pop_percentile, threshold_percentile) from .bilateral import mean_bilateral, pop_bilateral from skimage._shared.utils import deprecated percentile_autolevel = deprecated('autolevel_percentile')(autolevel_percentile) percentile_gradient = deprecated('gradient_percentile')(gradient_percentile) percentile_mean = deprecated('mean_percentile')(mean_percentile) bilateral_mean = deprecated('mean_bilateral')(mean_bilateral) meansubtraction = deprecated('subtract_mean')(subtract_mean) percentile_mean_subtraction = deprecated('subtract_mean_percentile')\ (subtract_mean_percentile) morph_contr_enh = deprecated('enhance_contrast')(enhance_contrast) percentile_morph_contr_enh = deprecated('enhance_contrast_percentile')\ (enhance_contrast_percentile) percentile_pop = deprecated('pop_percentile')(pop_percentile) bilateral_pop = deprecated('pop_bilateral')(pop_bilateral) percentile_threshold = deprecated('threshold_percentile')(threshold_percentile) __all__ = ['autolevel', 'autolevel_percentile', 'bottomhat', 'equalize', 'gradient', 'gradient_percentile', 'maximum', 'mean', 'mean_percentile', 'mean_bilateral', 'subtract_mean', 'subtract_mean_percentile', 'median', 'minimum', 'modal', 'enhance_contrast', 'enhance_contrast_percentile', 'pop', 'pop_percentile', 'pop_bilateral', 'threshold', 'threshold_percentile', 'tophat', 'noise_filter', 'entropy', 'otsu' 'percentile', # Deprecated 'percentile_autolevel', 'percentile_gradient', 'percentile_mean', 'percentile_mean_subtraction', 'percentile_morph_contr_enh', 'percentile_pop', 'percentile_threshold', 'bilateral_mean', 'bilateral_pop'] scikit-image-0.9.3/skimage/filter/rank/bilateral.py000066400000000000000000000125511223313777300222560ustar00rootroot00000000000000"""Approximate bilateral rank filter for local (custom kernel) mean. The local histogram is computed using a sliding window similar to the method described in [1]_. The pixel neighborhood is defined by: * the given structuring element * an interval [g-s0, g+s1] in greylevel around g the processed pixel greylevel The kernel is flat (i.e. each pixel belonging to the neighborhood contributes equally). Result image is 8-/16-bit or double with respect to the input image and the rank filter operation. References ---------- .. [1] Huang, T. ,Yang, G. ; Tang, G.. "A fast two-dimensional median filtering algorithm", IEEE Transactions on Acoustics, Speech and Signal Processing, Feb 1979. Volume: 27 , Issue: 1, Page(s): 13 - 18. """ import numpy as np from skimage import img_as_ubyte from . import bilateral_cy from .generic import _handle_input __all__ = ['mean_bilateral', 'pop_bilateral'] def _apply(func, image, selem, out, mask, shift_x, shift_y, s0, s1, out_dtype=None): image, selem, out, mask, max_bin = _handle_input(image, selem, out, mask, out_dtype) func(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, out=out, max_bin=max_bin, s0=s0, s1=s1) return out def mean_bilateral(image, selem, out=None, mask=None, shift_x=False, shift_y=False, s0=10, s1=10): """Apply a flat kernel bilateral filter. This is an edge-preserving and noise reducing denoising filter. It averages pixels based on their spatial closeness and radiometric similarity. Spatial closeness is measured by considering only the local pixel neighborhood given by a structuring element (selem). Radiometric similarity is defined by the greylevel interval [g-s0, g+s1] where g is the current pixel greylevel. Only pixels belonging to the structuring element AND having a greylevel inside this interval are averaged. Return greyscale local bilateral_mean of an image. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). s0, s1 : int Define the [s0, s1] interval around the greyvalue of the center pixel to be considered for computing the value. Returns ------- out : ndarray (same dtype as input image) Output image. See also -------- skimage.filter.denoise_bilateral for a gaussian bilateral filter. Examples -------- >>> from skimage import data >>> from skimage.morphology import disk >>> from skimage.filter.rank import bilateral_mean >>> # Load test image / cast to uint16 >>> ima = data.camera().astype(np.uint16) >>> # bilateral filtering of cameraman image using a flat kernel >>> bilat_ima = bilateral_mean(ima, disk(20), s0=10,s1=10) """ return _apply(bilateral_cy._mean, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, s0=s0, s1=s1) def pop_bilateral(image, selem, out=None, mask=None, shift_x=False, shift_y=False, s0=10, s1=10): """Return the number (population) of pixels actually inside the bilateral neighborhood, i.e. being inside the structuring element AND having a gray level inside the interval [g-s0, g+s1]. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). s0, s1 : int Define the [s0, s1] interval around the greyvalue of the center pixel to be considered for computing the value. Returns ------- out : ndarray (same dtype as input image) Output image. Examples -------- >>> # Local mean >>> from skimage.morphology import square >>> import skimage.filter.rank as rank >>> ima16 = 255 * np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) >>> rank.bilateral_pop(ima16, square(3), s0=10,s1=10) array([[3, 4, 3, 4, 3], [4, 4, 6, 4, 4], [3, 6, 9, 6, 3], [4, 4, 6, 4, 4], [3, 4, 3, 4, 3]], dtype=uint16) """ return _apply(bilateral_cy._pop, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, s0=s0, s1=s1) scikit-image-0.9.3/skimage/filter/rank/bilateral_cy.pyx000066400000000000000000000037411223313777300231420ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False cimport numpy as cnp from libc.math cimport log from .core_cy cimport dtype_t, dtype_t_out, _core cdef inline double _kernel_mean(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i cdef Py_ssize_t bilat_pop = 0 cdef Py_ssize_t mean = 0 if pop: for i in range(max_bin): if (g > (i - s0)) and (g < (i + s1)): bilat_pop += histo[i] mean += histo[i] * i if bilat_pop: return mean / bilat_pop else: return 0 else: return 0 cdef inline double _kernel_pop(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i cdef Py_ssize_t bilat_pop = 0 if pop: for i in range(max_bin): if (g > (i - s0)) and (g < (i + s1)): bilat_pop += histo[i] return bilat_pop else: return 0 def _mean(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t s0, Py_ssize_t s1, Py_ssize_t max_bin): _core(_kernel_mean[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, s0, s1, max_bin) def _pop(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t s0, Py_ssize_t s1, Py_ssize_t max_bin): _core(_kernel_pop[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, s0, s1, max_bin) scikit-image-0.9.3/skimage/filter/rank/core_cy.pxd000066400000000000000000000013661223313777300221070ustar00rootroot00000000000000from numpy cimport uint8_t, uint16_t, double_t ctypedef fused dtype_t: uint8_t uint16_t ctypedef fused dtype_t_out: uint8_t uint16_t double_t cdef dtype_t _max(dtype_t a, dtype_t b) cdef dtype_t _min(dtype_t a, dtype_t b) cdef void _core(double kernel(Py_ssize_t*, double, dtype_t, Py_ssize_t, Py_ssize_t, double, double, Py_ssize_t, Py_ssize_t), dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1, Py_ssize_t max_bin) except * scikit-image-0.9.3/skimage/filter/rank/core_cy.pyx000066400000000000000000000205451223313777300221340ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cimport numpy as cnp from libc.stdlib cimport malloc, free cdef inline dtype_t _max(dtype_t a, dtype_t b): return a if a >= b else b cdef inline dtype_t _min(dtype_t a, dtype_t b): return a if a <= b else b cdef inline void histogram_increment(Py_ssize_t* histo, double* pop, dtype_t value): histo[value] += 1 pop[0] += 1 cdef inline void histogram_decrement(Py_ssize_t* histo, double* pop, dtype_t value): histo[value] -= 1 pop[0] -= 1 cdef inline char is_in_mask(Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t r, Py_ssize_t c, char* mask): """Check whether given coordinate is within image and mask is true.""" if r < 0 or r > rows - 1 or c < 0 or c > cols - 1: return 0 else: if mask[r * cols + c]: return 1 else: return 0 cdef void _core(double kernel(Py_ssize_t*, double, dtype_t, Py_ssize_t, Py_ssize_t, double, double, Py_ssize_t, Py_ssize_t), dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1, Py_ssize_t max_bin) except *: """Compute histogram for each pixel neighborhood, apply kernel function and use kernel function return value for output image. """ cdef Py_ssize_t rows = image.shape[0] cdef Py_ssize_t cols = image.shape[1] cdef Py_ssize_t srows = selem.shape[0] cdef Py_ssize_t scols = selem.shape[1] cdef Py_ssize_t centre_r = (selem.shape[0] / 2) + shift_y cdef Py_ssize_t centre_c = (selem.shape[1] / 2) + shift_x # check that structuring element center is inside the element bounding box assert centre_r >= 0 assert centre_c >= 0 assert centre_r < srows assert centre_c < scols # add 1 to ensure maximum value is included in histogram -> range(max_bin) max_bin += 1 cdef Py_ssize_t mid_bin = max_bin / 2 # define pointers to the data cdef char* mask_data = &mask[0, 0] # define local variable types cdef Py_ssize_t r, c, rr, cc, s, value, local_max, i, even_row # number of pixels actually inside the neighborhood (double) cdef double pop = 0 # the current local histogram distribution cdef Py_ssize_t* histo = malloc(max_bin * sizeof(Py_ssize_t)) for i in range(max_bin): histo[i] = 0 # these lists contain the relative pixel row and column for each of the 4 # attack borders east, west, north and south e.g. se_e_r lists the rows of # the east structuring element border cdef Py_ssize_t max_se = srows * scols # number of element in each attack border cdef Py_ssize_t num_se_n, num_se_s, num_se_e, num_se_w num_se_n = num_se_s = num_se_e = num_se_w = 0 cdef Py_ssize_t* se_e_r = malloc(max_se * sizeof(Py_ssize_t)) cdef Py_ssize_t* se_e_c = malloc(max_se * sizeof(Py_ssize_t)) cdef Py_ssize_t* se_w_r = malloc(max_se * sizeof(Py_ssize_t)) cdef Py_ssize_t* se_w_c = malloc(max_se * sizeof(Py_ssize_t)) cdef Py_ssize_t* se_n_r = malloc(max_se * sizeof(Py_ssize_t)) cdef Py_ssize_t* se_n_c = malloc(max_se * sizeof(Py_ssize_t)) cdef Py_ssize_t* se_s_r = malloc(max_se * sizeof(Py_ssize_t)) cdef Py_ssize_t* se_s_c = malloc(max_se * sizeof(Py_ssize_t)) # build attack and release borders by using difference along axis t = np.hstack((selem, np.zeros((selem.shape[0], 1)))) cdef char[:, :] t_e = (np.diff(t, axis=1) < 0).view(np.uint8) t = np.hstack((np.zeros((selem.shape[0], 1)), selem)) cdef char[:, :] t_w = (np.diff(t, axis=1) > 0).view(np.uint8) t = np.vstack((selem, np.zeros((1, selem.shape[1])))) cdef char[:, :] t_s = (np.diff(t, axis=0) < 0).view(np.uint8) t = np.vstack((np.zeros((1, selem.shape[1])), selem)) cdef char[:, :] t_n = (np.diff(t, axis=0) > 0).view(np.uint8) for r in range(srows): for c in range(scols): if t_e[r, c]: se_e_r[num_se_e] = r - centre_r se_e_c[num_se_e] = c - centre_c num_se_e += 1 if t_w[r, c]: se_w_r[num_se_w] = r - centre_r se_w_c[num_se_w] = c - centre_c num_se_w += 1 if t_n[r, c]: se_n_r[num_se_n] = r - centre_r se_n_c[num_se_n] = c - centre_c num_se_n += 1 if t_s[r, c]: se_s_r[num_se_s] = r - centre_r se_s_c[num_se_s] = c - centre_c num_se_s += 1 for r in range(srows): for c in range(scols): rr = r - centre_r cc = c - centre_c if selem[r, c]: if is_in_mask(rows, cols, rr, cc, mask_data): histogram_increment(histo, &pop, image[rr, cc]) r = 0 c = 0 out[r, c] = kernel(histo, pop, image[r, c], max_bin, mid_bin, p0, p1, s0, s1) # main loop r = 0 for even_row in range(0, rows, 2): # ---> west to east for c in range(1, cols): for s in range(num_se_e): rr = r + se_e_r[s] cc = c + se_e_c[s] if is_in_mask(rows, cols, rr, cc, mask_data): histogram_increment(histo, &pop, image[rr, cc]) for s in range(num_se_w): rr = r + se_w_r[s] cc = c + se_w_c[s] - 1 if is_in_mask(rows, cols, rr, cc, mask_data): histogram_decrement(histo, &pop, image[rr, cc]) out[r, c] = kernel(histo, pop, image[r, c], max_bin, mid_bin, p0, p1, s0, s1) r += 1 # pass to the next row if r >= rows: break # ---> north to south for s in range(num_se_s): rr = r + se_s_r[s] cc = c + se_s_c[s] if is_in_mask(rows, cols, rr, cc, mask_data): histogram_increment(histo, &pop, image[rr, cc]) for s in range(num_se_n): rr = r + se_n_r[s] - 1 cc = c + se_n_c[s] if is_in_mask(rows, cols, rr, cc, mask_data): histogram_decrement(histo, &pop, image[rr, cc]) out[r, c] = kernel(histo, pop, image[r, c], max_bin, mid_bin, p0, p1, s0, s1) # ---> east to west for c in range(cols - 2, -1, -1): for s in range(num_se_w): rr = r + se_w_r[s] cc = c + se_w_c[s] if is_in_mask(rows, cols, rr, cc, mask_data): histogram_increment(histo, &pop, image[rr, cc]) for s in range(num_se_e): rr = r + se_e_r[s] cc = c + se_e_c[s] + 1 if is_in_mask(rows, cols, rr, cc, mask_data): histogram_decrement(histo, &pop, image[rr, cc]) out[r, c] = kernel(histo, pop, image[r, c], max_bin, mid_bin, p0, p1, s0, s1) r += 1 # pass to the next row if r >= rows: break # ---> north to south for s in range(num_se_s): rr = r + se_s_r[s] cc = c + se_s_c[s] if is_in_mask(rows, cols, rr, cc, mask_data): histogram_increment(histo, &pop, image[rr, cc]) for s in range(num_se_n): rr = r + se_n_r[s] - 1 cc = c + se_n_c[s] if is_in_mask(rows, cols, rr, cc, mask_data): histogram_decrement(histo, &pop, image[rr, cc]) out[r, c] = kernel(histo, pop, image[r, c], max_bin, mid_bin, p0, p1, s0, s1) # release memory allocated by malloc free(se_e_r) free(se_e_c) free(se_w_r) free(se_w_c) free(se_n_r) free(se_n_c) free(se_s_r) free(se_s_c) free(histo) scikit-image-0.9.3/skimage/filter/rank/generic.py000066400000000000000000000564611223313777300217430ustar00rootroot00000000000000"""The local histogram is computed using a sliding window similar to the method described in [1]_. Input image can be 8-bit or 16-bit, for 16-bit input images, the number of histogram bins is determined from the maximum value present in the image. Result image is 8-/16-bit or double with respect to the input image and the rank filter operation. References ---------- .. [1] Huang, T. ,Yang, G. ; Tang, G.. "A fast two-dimensional median filtering algorithm", IEEE Transactions on Acoustics, Speech and Signal Processing, Feb 1979. Volume: 27 , Issue: 1, Page(s): 13 - 18. """ import warnings import numpy as np from skimage import img_as_ubyte from . import generic_cy __all__ = ['autolevel', 'bottomhat', 'equalize', 'gradient', 'maximum', 'mean', 'subtract_mean', 'median', 'minimum', 'modal', 'enhance_contrast', 'pop', 'threshold', 'tophat', 'noise_filter', 'entropy', 'otsu'] def _handle_input(image, selem, out, mask, out_dtype=None): if image.dtype not in (np.uint8, np.uint16): image = img_as_ubyte(image) selem = np.ascontiguousarray(img_as_ubyte(selem > 0)) image = np.ascontiguousarray(image) if mask is None: mask = np.ones(image.shape, dtype=np.uint8) else: mask = img_as_ubyte(mask) mask = np.ascontiguousarray(mask) if out is None: if out_dtype is None: out_dtype = image.dtype out = np.empty_like(image, dtype=out_dtype) if image is out: raise NotImplementedError("Cannot perform rank operation in place.") is_8bit = image.dtype in (np.uint8, np.int8) if is_8bit: max_bin = 255 else: max_bin = max(4, image.max()) bitdepth = int(np.log2(max_bin)) if bitdepth > 10: warnings.warn("Bitdepth of %d may result in bad rank filter " "performance due to large number of bins." % bitdepth) return image, selem, out, mask, max_bin def _apply(func, image, selem, out, mask, shift_x, shift_y, out_dtype=None): image, selem, out, mask, max_bin = _handle_input(image, selem, out, mask, out_dtype) func(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, out=out, max_bin=max_bin) return out def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Autolevel image using local histogram. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. Examples -------- >>> from skimage import data >>> from skimage.morphology import disk >>> from skimage.filter.rank import autolevel >>> # Load test image >>> ima = data.camera() >>> # Stretch image contrast locally >>> auto = autolevel(ima, disk(20)) """ return _apply(generic_cy._autolevel, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Returns greyscale local bottomhat of an image. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- bottomhat : ndarray (same dtype as input image) The result of the local bottomhat. """ return _apply(generic_cy._bottomhat, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Equalize image using local histogram. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. Examples -------- >>> from skimage import data >>> from skimage.morphology import disk >>> from skimage.filter.rank import equalize >>> # Load test image >>> ima = data.camera() >>> # Local equalization >>> equ = equalize(ima, disk(20)) """ return _apply(generic_cy._equalize, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local gradient of an image (i.e. local maximum - local minimum). Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. """ return _apply(generic_cy._gradient, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local maximum of an image. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. See also -------- skimage.morphology.dilation Note ---- * the lower algorithm complexity makes the rank.maximum() more efficient for larger images and structuring elements """ return _apply(generic_cy._maximum, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local mean of an image. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. Examples -------- >>> from skimage import data >>> from skimage.morphology import disk >>> from skimage.filter.rank import mean >>> # Load test image >>> ima = data.camera() >>> # Local mean >>> avg = mean(ima, disk(20)) """ return _apply(generic_cy._mean, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def subtract_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return image subtracted from its local mean. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. """ return _apply(generic_cy._subtract_mean, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local median of an image. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. Examples -------- >>> from skimage import data >>> from skimage.morphology import disk >>> from skimage.filter.rank import median >>> # Load test image >>> ima = data.camera() >>> # Local mean >>> avg = median(ima, disk(20)) """ return _apply(generic_cy._median, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local minimum of an image. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. See also -------- skimage.morphology.erosion Note ---- * the lower algorithm complexity makes the rank.minimum() more efficient for larger images and structuring elements """ return _apply(generic_cy._minimum, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local mode of an image. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. """ return _apply(generic_cy._modal, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def enhance_contrast(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Enhance an image replacing each pixel by the local maximum if pixel greylevel is closest to maximimum than local minimum OR local minimum otherwise. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns Output image. out : ndarray (same dtype as input image) The result of the local enhance_contrast. Examples -------- >>> from skimage import data >>> from skimage.morphology import disk >>> from skimage.filter.rank import enhance_contrast >>> # Load test image >>> ima = data.camera() >>> # Local mean >>> avg = enhance_contrast(ima, disk(20)) """ return _apply(generic_cy._enhance_contrast, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return the number (population) of pixels actually inside the neighborhood. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. Examples -------- >>> # Local mean >>> from skimage.morphology import square >>> import skimage.filter.rank as rank >>> ima = 255 * np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) >>> rank.pop(ima, square(3)) array([[4, 6, 6, 6, 4], [6, 9, 9, 9, 6], [6, 9, 9, 9, 6], [6, 9, 9, 9, 6], [4, 6, 6, 6, 4]], dtype=uint8) """ return _apply(generic_cy._pop, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local threshold of an image. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. Examples -------- >>> # Local threshold >>> from skimage.morphology import square >>> from skimage.filter.rank import threshold >>> ima = 255 * np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) >>> threshold(ima, square(3)) array([[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 0, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]], dtype=uint8) """ return _apply(generic_cy._threshold, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local tophat of an image. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. """ return _apply(generic_cy._tophat, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Returns the noise feature as described in [Hashimoto12]_ Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). References ---------- .. [Hashimoto12] N. Hashimoto et al. Referenceless image quality evaluation for whole slide imaging. J Pathol Inform 2012;3:9. Returns ------- out : ndarray (same dtype as input image) Output image. """ # ensure that the central pixel in the structuring element is empty centre_r = int(selem.shape[0] / 2) + shift_y centre_c = int(selem.shape[1] / 2) + shift_x # make a local copy selem_cpy = selem.copy() selem_cpy[centre_r, centre_c] = 0 return _apply(generic_cy._noise_filter, image, selem_cpy, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def entropy(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Returns the entropy [1]_ computed locally. Entropy is computed using base 2 logarithm i.e. the filter returns the minimum number of bits needed to encode local greylevel distribution. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (double) Output image. References ---------- .. [1] http://en.wikipedia.org/wiki/Entropy_(information_theory)> Examples -------- >>> # Local entropy >>> from skimage import data >>> from skimage.filter.rank import entropy >>> from skimage.morphology import disk >>> a8 = data.camera() >>> ent8 = entropy(a8, disk(5)) """ return _apply(generic_cy._entropy, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, out_dtype=np.double) def otsu(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Returns the Otsu's threshold value for each pixel. Parameters ---------- image : ndarray Image array (uint8 array). selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). Returns ------- out : ndarray (same dtype as input image) Output image. References ---------- .. [otsu] http://en.wikipedia.org/wiki/Otsu's_method Examples -------- >>> # Local entropy >>> from skimage import data >>> from skimage.filter.rank import otsu >>> from skimage.morphology import disk >>> # defining a 8-bit test images >>> a8 = data.camera() >>> loc_otsu = otsu(a8, disk(5)) >>> thresh_image = a8 >= loc_otsu """ return _apply(generic_cy._otsu, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) scikit-image-0.9.3/skimage/filter/rank/generic_cy.pyx000066400000000000000000000355021223313777300226170ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False cimport numpy as cnp from libc.math cimport log from .core_cy cimport dtype_t, dtype_t_out, _core cdef inline double _kernel_autolevel(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i, imin, imax, delta if pop: for i in range(max_bin - 1, -1, -1): if histo[i]: imax = i break for i in range(max_bin): if histo[i]: imin = i break delta = imax - imin if delta > 0: return (max_bin - 1) * (g - imin) / delta else: return 0 else: return 0 cdef inline double _kernel_bottomhat(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i if pop: for i in range(max_bin): if histo[i]: break return g - i else: return 0 cdef inline double _kernel_equalize(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i cdef Py_ssize_t sum = 0 if pop: for i in range(max_bin): sum += histo[i] if i >= g: break return ((max_bin - 1) * sum) / pop else: return 0 cdef inline double _kernel_gradient(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i, imin, imax if pop: for i in range(max_bin - 1, -1, -1): if histo[i]: imax = i break for i in range(max_bin): if histo[i]: imin = i break return imax - imin else: return 0 cdef inline double _kernel_maximum(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i if pop: for i in range(max_bin - 1, -1, -1): if histo[i]: return i else: return 0 cdef inline double _kernel_mean(Py_ssize_t* histo, double pop,dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i cdef Py_ssize_t mean = 0 if pop: for i in range(max_bin): mean += histo[i] * i return mean / pop else: return 0 cdef inline double _kernel_subtract_mean(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i cdef Py_ssize_t mean = 0 if pop: for i in range(max_bin): mean += histo[i] * i return (g - mean / pop) / 2. + 127 else: return 0 cdef inline double _kernel_median(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i cdef double sum = pop / 2.0 if pop: for i in range(max_bin): if histo[i]: sum -= histo[i] if sum < 0: return i else: return 0 cdef inline double _kernel_minimum(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i if pop: for i in range(max_bin): if histo[i]: return i else: return 0 cdef inline double _kernel_modal(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t hmax = 0, imax = 0 if pop: for i in range(max_bin): if histo[i] > hmax: hmax = histo[i] imax = i return imax else: return 0 cdef inline double _kernel_enhance_contrast(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i, imin, imax if pop: for i in range(max_bin - 1, -1, -1): if histo[i]: imax = i break for i in range(max_bin): if histo[i]: imin = i break if imax - g < g - imin: return imax else: return imin else: return 0 cdef inline double _kernel_pop(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): return pop cdef inline double _kernel_threshold(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i cdef Py_ssize_t mean = 0 if pop: for i in range(max_bin): mean += histo[i] * i return g > (mean / pop) else: return 0 cdef inline double _kernel_tophat(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i if pop: for i in range(max_bin - 1, -1, -1): if histo[i]: break return i - g else: return 0 cdef inline double _kernel_noise_filter(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i cdef Py_ssize_t min_i # early stop if at least one pixel of the neighborhood has the same g if histo[g] > 0: return 0 for i in range(g, -1, -1): if histo[i]: break min_i = g - i for i in range(g, max_bin): if histo[i]: break if i - g < min_i: return i - g else: return min_i cdef inline double _kernel_entropy(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i cdef double e, p if pop: e = 0. for i in range(max_bin): p = histo[i] / pop if p > 0: e -= p * log(p) / 0.6931471805599453 return e else: return 0 cdef inline double _kernel_otsu(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i cdef Py_ssize_t max_i cdef double P, mu1, mu2, q1, new_q1, sigma_b, max_sigma_b cdef double mu = 0. # compute local mean if pop: for i in range(max_bin): mu += histo[i] * i mu = mu / pop else: return 0 # maximizing the between class variance max_i = 0 q1 = histo[0] / pop mu1 = 0. max_sigma_b = 0. for i in range(1, max_bin): P = histo[i] / pop new_q1 = q1 + P if new_q1 > 0: mu1 = (q1 * mu1 + i * P) / new_q1 mu2 = (mu - new_q1 * mu1) / (1. - new_q1) sigma_b = new_q1 * (1. - new_q1) * (mu1 - mu2) ** 2 if sigma_b > max_sigma_b: max_sigma_b = sigma_b max_i = i q1 = new_q1 return max_i def _autolevel(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_autolevel[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _bottomhat(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_bottomhat[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _equalize(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_equalize[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _gradient(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_gradient[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _maximum(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_maximum[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _mean(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_mean[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _subtract_mean(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_subtract_mean[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _median(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_median[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _minimum(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_minimum[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _enhance_contrast(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_enhance_contrast[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _modal(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_modal[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _pop(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_pop[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _threshold(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_threshold[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _tophat(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_tophat[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _noise_filter(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_noise_filter[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _entropy(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_entropy[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) def _otsu(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, Py_ssize_t max_bin): _core(_kernel_otsu[dtype_t], image, selem, mask, out, shift_x, shift_y, 0, 0, 0, 0, max_bin) scikit-image-0.9.3/skimage/filter/rank/percentile.py000066400000000000000000000300621223313777300224460ustar00rootroot00000000000000"""Inferior and superior ranks, provided by the user, are passed to the kernel function to provide a softer version of the rank filters. E.g. ``autolevel_percentile`` will stretch image levels between percentile [p0, p1] instead of using [min, max]. It means that isolated bright or dark pixels will not produce halos. The local histogram is computed using a sliding window similar to the method described in [1]_. Input image can be 8-bit or 16-bit, for 16-bit input images, the number of histogram bins is determined from the maximum value present in the image. Result image is 8-/16-bit or double with respect to the input image and the rank filter operation. References ---------- .. [1] Huang, T. ,Yang, G. ; Tang, G.. "A fast two-dimensional median filtering algorithm", IEEE Transactions on Acoustics, Speech and Signal Processing, Feb 1979. Volume: 27 , Issue: 1, Page(s): 13 - 18. """ import numpy as np from . import percentile_cy from .generic import _handle_input __all__ = ['autolevel_percentile', 'gradient_percentile', 'mean_percentile', 'subtract_mean_percentile', 'enhance_contrast_percentile', 'percentile', 'pop_percentile', 'threshold_percentile'] def _apply(func, image, selem, out, mask, shift_x, shift_y, p0, p1, out_dtype=None): image, selem, out, mask, max_bin = _handle_input(image, selem, out, mask, out_dtype) func(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, out=out, max_bin=max_bin, p0=p0, p1=p1) return out def autolevel_percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=0, p1=1): """Return greyscale local autolevel of an image. Autolevel is computed on the given structuring element. Only levels between percentiles [p0, p1] are used. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). p0, p1 : float in [0, ..., 1] Define the [p0, p1] percentile interval to be considered for computing the value. Returns ------- out : ndarray (same dtype as input image) Output image. """ return _apply(percentile_cy._autolevel, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) def gradient_percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=0, p1=1): """Return greyscale local gradient of an image. gradient is computed on the given structuring element. Only levels between percentiles [p0, p1] are used. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). p0, p1 : float in [0, ..., 1] Define the [p0, p1] percentile interval to be considered for computing the value. Returns ------- out : ndarray (same dtype as input image) Output image. """ return _apply(percentile_cy._gradient, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) def mean_percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=0, p1=1): """Return greyscale local mean of an image. Mean is computed on the given structuring element. Only levels between percentiles [p0, p1] are used. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). p0, p1 : float in [0, ..., 1] Define the [p0, p1] percentile interval to be considered for computing the value. Returns ------- out : ndarray (same dtype as input image) Output image. """ return _apply(percentile_cy._mean, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) def subtract_mean_percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=0, p1=1): """Return greyscale local subtract_mean of an image. subtract_mean is computed on the given structuring element. Only levels between percentiles [p0, p1] are used. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). p0, p1 : float in [0, ..., 1] Define the [p0, p1] percentile interval to be considered for computing the value. Returns ------- out : ndarray (same dtype as input image) Output image. """ return _apply(percentile_cy._subtract_mean, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) def enhance_contrast_percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=0, p1=1): """Return greyscale local enhance_contrast of an image. enhance_contrast is computed on the given structuring element. Only levels between percentiles [p0, p1] are used. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). p0, p1 : float in [0, ..., 1] Define the [p0, p1] percentile interval to be considered for computing the value. Returns ------- out : ndarray (same dtype as input image) Output image. """ return _apply(percentile_cy._enhance_contrast, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=0): """Return greyscale local percentile of an image. percentile is computed on the given structuring element. Returns the value of the p0 lower percentile of the neighborhood value distribution. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). p0 : float in [0, ..., 1] Set the percentile value. Returns ------- out : ndarray (same dtype as input image) Output image. """ return _apply(percentile_cy._percentile, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, p0=p0, p1=0.) def pop_percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=0, p1=1): """Return greyscale local pop of an image. pop is computed on the given structuring element. Only levels between percentiles [p0, p1] are used. Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). p0, p1 : float in [0, ..., 1] Define the [p0, p1] percentile interval to be considered for computing the value. Returns ------- out : ndarray (same dtype as input image) Output image. """ return _apply(percentile_cy._pop, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) def threshold_percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=0): """Return greyscale local threshold of an image. threshold is computed on the given structuring element. Returns thresholded image such that pixels having a higher value than the the p0 percentile of the neighborhood value distribution are set to 2^nbit-1 (e.g. 255 for 8bit image). Parameters ---------- image : ndarray (uint8, uint16) Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray (same dtype as input) If None, a new array will be allocated. mask : ndarray Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). shift_x, shift_y : int Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). p0 : float in [0, ..., 1] Set the percentile value. out : ndarray (same dtype as input image) Output image. local threshold : ndarray (same dtype as input) The result of the local threshold. """ return _apply(percentile_cy._threshold, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, p0=p0, p1=0) scikit-image-0.9.3/skimage/filter/rank/percentile_cy.pyx000066400000000000000000000214701223313777300233340ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False cimport numpy as cnp from .core_cy cimport dtype_t, dtype_t_out, _core, _min, _max cdef inline double _kernel_autolevel(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i, imin, imax, sum, delta if pop: sum = 0 p1 = 1.0 - p1 for i in range(max_bin): sum += histo[i] if sum > p0 * pop: imin = i break sum = 0 for i in range(max_bin - 1, -1, -1): sum += histo[i] if sum > p1 * pop: imax = i break delta = imax - imin if delta > 0: return (max_bin - 1) * (_min(_max(imin, g), imax) - imin) / delta else: return imax - imin else: return 0 cdef inline double _kernel_gradient(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i, imin, imax, sum, delta if pop: sum = 0 p1 = 1.0 - p1 for i in range(max_bin): sum += histo[i] if sum >= p0 * pop: imin = i break sum = 0 for i in range(max_bin - 1, -1, -1): sum += histo[i] if sum >= p1 * pop: imax = i break return imax - imin else: return 0 cdef inline double _kernel_mean(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i, sum, mean, n if pop: sum = 0 mean = 0 n = 0 for i in range(max_bin): sum += histo[i] if (sum >= p0 * pop) and (sum <= p1 * pop): n += histo[i] mean += histo[i] * i if n > 0: return mean / n else: return 0 else: return 0 cdef inline double _kernel_subtract_mean(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i, sum, mean, n if pop: sum = 0 mean = 0 n = 0 for i in range(max_bin): sum += histo[i] if (sum >= p0 * pop) and (sum <= p1 * pop): n += histo[i] mean += histo[i] * i if n > 0: return (g - (mean / n)) * .5 + mid_bin else: return 0 else: return 0 cdef inline double _kernel_enhance_contrast(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i, imin, imax, sum, delta if pop: sum = 0 p1 = 1.0 - p1 for i in range(max_bin): sum += histo[i] if sum > p0 * pop: imin = i break sum = 0 for i in range(max_bin - 1, -1, -1): sum += histo[i] if sum > p1 * pop: imax = i break if g > imax: return imax if g < imin: return imin if imax - g < g - imin: return imax else: return imin else: return 0 cdef inline double _kernel_percentile(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i cdef Py_ssize_t sum = 0 if pop: if p0 == 1: # make sure p0 = 1 returns the maximum filter for i in range(max_bin - 1, -1, -1): if histo[i]: break else: for i in range(max_bin): sum += histo[i] if sum > p0 * pop: break return i else: return 0 cdef inline double _kernel_pop(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef Py_ssize_t i, sum, n if pop: sum = 0 n = 0 for i in range(max_bin): sum += histo[i] if (sum >= p0 * pop) and (sum <= p1 * pop): n += histo[i] return n else: return 0 cdef inline double _kernel_threshold(Py_ssize_t* histo, double pop, dtype_t g, Py_ssize_t max_bin, Py_ssize_t mid_bin, double p0, double p1, Py_ssize_t s0, Py_ssize_t s1): cdef int i cdef Py_ssize_t sum = 0 if pop: for i in range(max_bin): sum += histo[i] if sum >= p0 * pop: break return (max_bin - 1) * (g >= i) else: return 0 def _autolevel(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, double p0, double p1, Py_ssize_t max_bin): _core(_kernel_autolevel[dtype_t], image, selem, mask, out, shift_x, shift_y, p0, p1, 0, 0, max_bin) def _gradient(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, double p0, double p1, Py_ssize_t max_bin): _core(_kernel_gradient[dtype_t], image, selem, mask, out, shift_x, shift_y, p0, p1, 0, 0, max_bin) def _mean(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, double p0, double p1, Py_ssize_t max_bin): _core(_kernel_mean[dtype_t], image, selem, mask, out, shift_x, shift_y, p0, p1, 0, 0, max_bin) def _subtract_mean(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, double p0, double p1, Py_ssize_t max_bin): _core(_kernel_subtract_mean[dtype_t], image, selem, mask, out, shift_x, shift_y, p0, p1, 0, 0, max_bin) def _enhance_contrast(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, double p0, double p1, Py_ssize_t max_bin): _core(_kernel_enhance_contrast[dtype_t], image, selem, mask, out, shift_x, shift_y, p0, p1, 0, 0, max_bin) def _percentile(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, double p0, double p1, Py_ssize_t max_bin): _core(_kernel_percentile[dtype_t], image, selem, mask, out, shift_x, shift_y, p0, 1, 0, 0, max_bin) def _pop(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, double p0, double p1, Py_ssize_t max_bin): _core(_kernel_pop[dtype_t], image, selem, mask, out, shift_x, shift_y, p0, p1, 0, 0, max_bin) def _threshold(dtype_t[:, ::1] image, char[:, ::1] selem, char[:, ::1] mask, dtype_t_out[:, ::1] out, char shift_x, char shift_y, double p0, double p1, Py_ssize_t max_bin): _core(_kernel_threshold[dtype_t], image, selem, mask, out, shift_x, shift_y, p0, 1, 0, 0, max_bin) scikit-image-0.9.3/skimage/filter/rank/tests/000077500000000000000000000000001223313777300211035ustar00rootroot00000000000000scikit-image-0.9.3/skimage/filter/rank/tests/test_rank.py000066400000000000000000000413451223313777300234560ustar00rootroot00000000000000import numpy as np from numpy.testing import run_module_suite, assert_array_equal, assert_raises from skimage import img_as_ubyte, img_as_uint, img_as_float from skimage import data, util from skimage.morphology import cmorph, disk from skimage.filter import rank def test_random_sizes(): # make sure the size is not a problem niter = 10 elem = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]], dtype=np.uint8) for m, n in np.random.random_integers(1, 100, size=(10, 2)): mask = np.ones((m, n), dtype=np.uint8) image8 = np.ones((m, n), dtype=np.uint8) out8 = np.empty_like(image8) rank.mean(image=image8, selem=elem, mask=mask, out=out8, shift_x=0, shift_y=0) assert_array_equal(image8.shape, out8.shape) rank.mean(image=image8, selem=elem, mask=mask, out=out8, shift_x=+1, shift_y=+1) assert_array_equal(image8.shape, out8.shape) image16 = np.ones((m, n), dtype=np.uint16) out16 = np.empty_like(image8, dtype=np.uint16) rank.mean(image=image16, selem=elem, mask=mask, out=out16, shift_x=0, shift_y=0) assert_array_equal(image16.shape, out16.shape) rank.mean(image=image16, selem=elem, mask=mask, out=out16, shift_x=+1, shift_y=+1) assert_array_equal(image16.shape, out16.shape) rank.mean_percentile(image=image16, mask=mask, out=out16, selem=elem, shift_x=0, shift_y=0, p0=.1, p1=.9) assert_array_equal(image16.shape, out16.shape) rank.mean_percentile(image=image16, mask=mask, out=out16, selem=elem, shift_x=+1, shift_y=+1, p0=.1, p1=.9) assert_array_equal(image16.shape, out16.shape) def test_compare_with_cmorph_dilate(): # compare the result of maximum filter with dilate image = (np.random.random((100, 100)) * 256).astype(np.uint8) out = np.empty_like(image) mask = np.ones(image.shape, dtype=np.uint8) for r in range(1, 20, 1): elem = np.ones((r, r), dtype=np.uint8) rank.maximum(image=image, selem=elem, out=out, mask=mask) cm = cmorph._dilate(image=image, selem=elem) assert_array_equal(out, cm) def test_compare_with_cmorph_erode(): # compare the result of maximum filter with erode image = (np.random.random((100, 100)) * 256).astype(np.uint8) out = np.empty_like(image) mask = np.ones(image.shape, dtype=np.uint8) for r in range(1, 20, 1): elem = np.ones((r, r), dtype=np.uint8) rank.minimum(image=image, selem=elem, out=out, mask=mask) cm = cmorph._erode(image=image, selem=elem) assert_array_equal(out, cm) def test_bitdepth(): # test the different bit depth for rank16 elem = np.ones((3, 3), dtype=np.uint8) out = np.empty((100, 100), dtype=np.uint16) mask = np.ones((100, 100), dtype=np.uint8) for i in range(5): image = np.ones((100, 100), dtype=np.uint16) * 255 * 2 ** i r = rank.mean_percentile(image=image, selem=elem, mask=mask, out=out, shift_x=0, shift_y=0, p0=.1, p1=.9) def test_population(): # check the number of valid pixels in the neighborhood image = np.zeros((5, 5), dtype=np.uint8) elem = np.ones((3, 3), dtype=np.uint8) out = np.empty_like(image) mask = np.ones(image.shape, dtype=np.uint8) rank.pop(image=image, selem=elem, out=out, mask=mask) r = np.array([[4, 6, 6, 6, 4], [6, 9, 9, 9, 6], [6, 9, 9, 9, 6], [6, 9, 9, 9, 6], [4, 6, 6, 6, 4]]) assert_array_equal(r, out) def test_structuring_element8(): # check the output for a custom structuring element r = np.array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 255, 0, 0, 0], [0, 0, 255, 255, 255, 0], [0, 0, 0, 255, 255, 0], [0, 0, 0, 0, 0, 0]]) # 8-bit image = np.zeros((6, 6), dtype=np.uint8) image[2, 2] = 255 elem = np.asarray([[1, 1, 0], [1, 1, 1], [0, 0, 1]], dtype=np.uint8) out = np.empty_like(image) mask = np.ones(image.shape, dtype=np.uint8) rank.maximum(image=image, selem=elem, out=out, mask=mask, shift_x=1, shift_y=1) assert_array_equal(r, out) # 16-bit image = np.zeros((6, 6), dtype=np.uint16) image[2, 2] = 255 out = np.empty_like(image) rank.maximum(image=image, selem=elem, out=out, mask=mask, shift_x=1, shift_y=1) assert_array_equal(r, out) def test_pass_on_bitdepth(): # should pass because data bitdepth is not too high for the function image = np.ones((100, 100), dtype=np.uint16) * 2 ** 11 elem = np.ones((3, 3), dtype=np.uint8) out = np.empty_like(image) mask = np.ones(image.shape, dtype=np.uint8) def test_inplace_output(): # rank filters are not supposed to filter inplace selem = disk(20) image = (np.random.random((500, 500)) * 256).astype(np.uint8) out = image assert_raises(NotImplementedError, rank.mean, image, selem, out=out) def test_compare_autolevels(): # compare autolevel and percentile autolevel with p0=0.0 and p1=1.0 # should returns the same arrays image = util.img_as_ubyte(data.camera()) selem = disk(20) loc_autolevel = rank.autolevel(image, selem=selem) loc_perc_autolevel = rank.autolevel_percentile(image, selem=selem, p0=.0, p1=1.) assert_array_equal(loc_autolevel, loc_perc_autolevel) def test_compare_autolevels_16bit(): # compare autolevel(16-bit) and percentile autolevel(16-bit) with p0=0.0 # and p1=1.0 should returns the same arrays image = data.camera().astype(np.uint16) * 4 selem = disk(20) loc_autolevel = rank.autolevel(image, selem=selem) loc_perc_autolevel = rank.autolevel_percentile(image, selem=selem, p0=.0, p1=1.) assert_array_equal(loc_autolevel, loc_perc_autolevel) def test_compare_ubyte_vs_float(): # Create signed int8 image that and convert it to uint8 image_uint = img_as_ubyte(data.camera()[:50, :50]) image_float = img_as_float(image_uint) methods = ['autolevel', 'bottomhat', 'equalize', 'gradient', 'threshold', 'subtract_mean', 'enhance_contrast', 'pop', 'tophat'] for method in methods: func = getattr(rank, method) out_u = func(image_uint, disk(3)) out_f = func(image_float, disk(3)) assert_array_equal(out_u, out_f) def test_compare_8bit_unsigned_vs_signed(): # filters applied on 8-bit image ore 16-bit image (having only real 8-bit # of dynamic) should be identical # Create signed int8 image that and convert it to uint8 image = img_as_ubyte(data.camera()) image[image > 127] = 0 image_s = image.astype(np.int8) image_u = img_as_ubyte(image_s) assert_array_equal(image_u, img_as_ubyte(image_s)) methods = ['autolevel', 'bottomhat', 'equalize', 'gradient', 'maximum', 'mean', 'subtract_mean', 'median', 'minimum', 'modal', 'enhance_contrast', 'pop', 'threshold', 'tophat'] for method in methods: func = getattr(rank, method) out_u = func(image_u, disk(3)) out_s = func(image_s, disk(3)) assert_array_equal(out_u, out_s) def test_compare_8bit_vs_16bit(): # filters applied on 8-bit image ore 16-bit image (having only real 8-bit # of dynamic) should be identical image8 = util.img_as_ubyte(data.camera()) image16 = image8.astype(np.uint16) assert_array_equal(image8, image16) methods = ['autolevel', 'bottomhat', 'equalize', 'gradient', 'maximum', 'mean', 'subtract_mean', 'median', 'minimum', 'modal', 'enhance_contrast', 'pop', 'threshold', 'tophat'] for method in methods: func = getattr(rank, method) f8 = func(image8, disk(3)) f16 = func(image16, disk(3)) assert_array_equal(f8, f16) def test_trivial_selem8(): # check that min, max and mean returns identity if structuring element # contains only central pixel image = np.zeros((5, 5), dtype=np.uint8) out = np.zeros_like(image) mask = np.ones_like(image, dtype=np.uint8) image[2, 2] = 255 image[2, 3] = 128 image[1, 2] = 16 elem = np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]], dtype=np.uint8) rank.mean(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) rank.minimum(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) rank.maximum(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) def test_trivial_selem16(): # check that min, max and mean returns identity if structuring element # contains only central pixel image = np.zeros((5, 5), dtype=np.uint16) out = np.zeros_like(image) mask = np.ones_like(image, dtype=np.uint8) image[2, 2] = 255 image[2, 3] = 128 image[1, 2] = 16 elem = np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]], dtype=np.uint8) rank.mean(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) rank.minimum(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) rank.maximum(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) def test_smallest_selem8(): # check that min, max and mean returns identity if structuring element # contains only central pixel image = np.zeros((5, 5), dtype=np.uint8) out = np.zeros_like(image) mask = np.ones_like(image, dtype=np.uint8) image[2, 2] = 255 image[2, 3] = 128 image[1, 2] = 16 elem = np.array([[1]], dtype=np.uint8) rank.mean(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) rank.minimum(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) rank.maximum(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) def test_smallest_selem16(): # check that min, max and mean returns identity if structuring element # contains only central pixel image = np.zeros((5, 5), dtype=np.uint16) out = np.zeros_like(image) mask = np.ones_like(image, dtype=np.uint8) image[2, 2] = 255 image[2, 3] = 128 image[1, 2] = 16 elem = np.array([[1]], dtype=np.uint8) rank.mean(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) rank.minimum(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) rank.maximum(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) def test_empty_selem(): # check that min, max and mean returns zeros if structuring element is # empty image = np.zeros((5, 5), dtype=np.uint16) out = np.zeros_like(image) mask = np.ones_like(image, dtype=np.uint8) res = np.zeros_like(image) image[2, 2] = 255 image[2, 3] = 128 image[1, 2] = 16 elem = np.array([[0, 0, 0], [0, 0, 0]], dtype=np.uint8) rank.mean(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(res, out) rank.minimum(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(res, out) rank.maximum(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(res, out) def test_otsu(): # test the local Otsu segmentation on a synthetic image # (left to right ramp * sinus) test = np.tile([128, 145, 103, 127, 165, 83, 127, 185, 63, 127, 205, 43, 127, 225, 23, 127], (16, 1)) test = test.astype(np.uint8) res = np.tile([1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1], (16, 1)) selem = np.ones((6, 6), dtype=np.uint8) th = 1 * (test >= rank.otsu(test, selem)) assert_array_equal(th, res) def test_entropy(): # verify that entropy is coherent with bitdepth of the input data selem = np.ones((16, 16), dtype=np.uint8) # 1 bit per pixel data = np.tile(np.asarray([0, 1]), (100, 100)).astype(np.uint8) assert(np.max(rank.entropy(data, selem)) == 1) # 2 bit per pixel data = np.tile(np.asarray([[0, 1], [2, 3]]), (10, 10)).astype(np.uint8) assert(np.max(rank.entropy(data, selem)) == 2) # 3 bit per pixel data = np.tile( np.asarray([[0, 1, 2, 3], [4, 5, 6, 7]]), (10, 10)).astype(np.uint8) assert(np.max(rank.entropy(data, selem)) == 3) # 4 bit per pixel data = np.tile( np.reshape(np.arange(16), (4, 4)), (10, 10)).astype(np.uint8) assert(np.max(rank.entropy(data, selem)) == 4) # 6 bit per pixel data = np.tile( np.reshape(np.arange(64), (8, 8)), (10, 10)).astype(np.uint8) assert(np.max(rank.entropy(data, selem)) == 6) # 8-bit per pixel data = np.tile( np.reshape(np.arange(256), (16, 16)), (10, 10)).astype(np.uint8) assert(np.max(rank.entropy(data, selem)) == 8) # 12 bit per pixel selem = np.ones((64, 64), dtype=np.uint8) data = np.tile( np.reshape(np.arange(4096), (64, 64)), (2, 2)).astype(np.uint16) assert(np.max(rank.entropy(data, selem)) == 12) # make sure output is of dtype double out = rank.entropy(data, np.ones((16, 16), dtype=np.uint8)) assert out.dtype == np.double def test_selem_dtypes(): image = np.zeros((5, 5), dtype=np.uint8) out = np.zeros_like(image) mask = np.ones_like(image, dtype=np.uint8) image[2, 2] = 255 image[2, 3] = 128 image[1, 2] = 16 for dtype in (np.uint8, np.uint16, np.int32, np.int64, np.float32, np.float64): elem = np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]], dtype=dtype) rank.mean(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) rank.mean_percentile(image=image, selem=elem, out=out, mask=mask, shift_x=0, shift_y=0) assert_array_equal(image, out) def test_16bit(): image = np.zeros((21, 21), dtype=np.uint16) selem = np.ones((3, 3), dtype=np.uint8) for bitdepth in range(17): value = 2 ** bitdepth - 1 image[10, 10] = value assert rank.minimum(image, selem)[10, 10] == 0 assert rank.maximum(image, selem)[10, 10] == value assert rank.mean(image, selem)[10, 10] == value / selem.size def test_bilateral(): image = np.zeros((21, 21), dtype=np.uint16) selem = np.ones((3, 3), dtype=np.uint8) image[10, 10] = 1000 image[10, 11] = 1010 image[10, 9] = 900 assert rank.mean_bilateral(image, selem, s0=1, s1=1)[10, 10] == 1000 assert rank.pop_bilateral(image, selem, s0=1, s1=1)[10, 10] == 1 assert rank.mean_bilateral(image, selem, s0=11, s1=11)[10, 10] == 1005 assert rank.pop_bilateral(image, selem, s0=11, s1=11)[10, 10] == 2 def test_percentile_min(): # check that percentile p0 = 0 is identical to local min img = data.camera() img16 = img.astype(np.uint16) selem = disk(15) # check for 8bit img_p0 = rank.percentile(img, selem=selem, p0=0) img_min = rank.minimum(img, selem=selem) assert_array_equal(img_p0, img_min) # check for 16bit img_p0 = rank.percentile(img16, selem=selem, p0=0) img_min = rank.minimum(img16, selem=selem) assert_array_equal(img_p0, img_min) def test_percentile_max(): # check that percentile p0 = 1 is identical to local max img = data.camera() img16 = img.astype(np.uint16) selem = disk(15) # check for 8bit img_p0 = rank.percentile(img, selem=selem, p0=1.) img_max = rank.maximum(img, selem=selem) assert_array_equal(img_p0, img_max) # check for 16bit img_p0 = rank.percentile(img16, selem=selem, p0=1.) img_max = rank.maximum(img16, selem=selem) assert_array_equal(img_p0, img_max) def test_percentile_median(): # check that percentile p0 = 0.5 is identical to local median img = data.camera() img16 = img.astype(np.uint16) selem = disk(15) # check for 8bit img_p0 = rank.percentile(img, selem=selem, p0=.5) img_max = rank.median(img, selem=selem) assert_array_equal(img_p0, img_max) # check for 16bit img_p0 = rank.percentile(img16, selem=selem, p0=.5) img_max = rank.median(img16, selem=selem) assert_array_equal(img_p0, img_max) if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/filter/setup.py000066400000000000000000000036011223313777300205200ustar00rootroot00000000000000#!/usr/bin/env python import os from skimage._build import cython base_path = os.path.abspath(os.path.dirname(__file__)) def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs config = Configuration('filter', parent_package, top_path) config.add_data_dir('tests') cython(['_ctmf.pyx'], working_path=base_path) cython(['_denoise_cy.pyx'], working_path=base_path) cython(['rank/core_cy.pyx'], working_path=base_path) cython(['rank/generic_cy.pyx'], working_path=base_path) cython(['rank/percentile_cy.pyx'], working_path=base_path) cython(['rank/bilateral_cy.pyx'], working_path=base_path) config.add_extension('_ctmf', sources=['_ctmf.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_denoise_cy', sources=['_denoise_cy.c'], include_dirs=[get_numpy_include_dirs(), '../_shared']) config.add_extension('rank.core_cy', sources=['rank/core_cy.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('rank.generic_cy', sources=['rank/generic_cy.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension( 'rank.percentile_cy', sources=['rank/percentile_cy.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension( 'rank.bilateral_cy', sources=['rank/bilateral_cy.c'], include_dirs=[get_numpy_include_dirs()]) return config if __name__ == '__main__': from numpy.distutils.core import setup setup(maintainer='scikit-image Developers', author='scikit-image Developers', maintainer_email='scikit-image@googlegroups.com', description='Filters', url='https://github.com/scikit-image/scikit-image', license='SciPy License (BSD Style)', **(configuration(top_path='').todict()) ) scikit-image-0.9.3/skimage/filter/tests/000077500000000000000000000000001223313777300201505ustar00rootroot00000000000000scikit-image-0.9.3/skimage/filter/tests/test_canny.py000066400000000000000000000054731223313777300227020ustar00rootroot00000000000000import unittest import numpy as np from scipy.ndimage import binary_dilation, binary_erosion import skimage.filter as F class TestCanny(unittest.TestCase): def test_00_00_zeros(self): '''Test that the Canny filter finds no points for a blank field''' result = F.canny(np.zeros((20, 20)), 4, 0, 0, np.ones((20, 20), bool)) self.assertFalse(np.any(result)) def test_00_01_zeros_mask(self): '''Test that the Canny filter finds no points in a masked image''' result = (F.canny(np.random.uniform(size=(20, 20)), 4, 0, 0, np.zeros((20, 20), bool))) self.assertFalse(np.any(result)) def test_01_01_circle(self): '''Test that the Canny filter finds the outlines of a circle''' i, j = np.mgrid[-200:200, -200:200].astype(float) / 200 c = np.abs(np.sqrt(i * i + j * j) - .5) < .02 result = F.canny(c.astype(float), 4, 0, 0, np.ones(c.shape, bool)) # # erode and dilate the circle to get rings that should contain the # outlines # cd = binary_dilation(c, iterations=3) ce = binary_erosion(c, iterations=3) cde = np.logical_and(cd, np.logical_not(ce)) self.assertTrue(np.all(cde[result])) # # The circle has a radius of 100. There are two rings here, one # for the inside edge and one for the outside. So that's # 100 * 2 * 2 * 3 for those places where pi is still 3. # The edge contains both pixels if there's a tie, so we # bump the count a little. point_count = np.sum(result) self.assertTrue(point_count > 1200) self.assertTrue(point_count < 1600) def test_01_02_circle_with_noise(self): '''Test that the Canny filter finds the circle outlines in a noisy image''' np.random.seed(0) i, j = np.mgrid[-200:200, -200:200].astype(float) / 200 c = np.abs(np.sqrt(i * i + j * j) - .5) < .02 cf = c.astype(float) * .5 + np.random.uniform(size=c.shape) * .5 result = F.canny(cf, 4, .1, .2, np.ones(c.shape, bool)) # # erode and dilate the circle to get rings that should contain the # outlines # cd = binary_dilation(c, iterations=4) ce = binary_erosion(c, iterations=4) cde = np.logical_and(cd, np.logical_not(ce)) self.assertTrue(np.all(cde[result])) point_count = np.sum(result) self.assertTrue(point_count > 1200) self.assertTrue(point_count < 1600) def test_image_shape(self): self.assertRaises(TypeError, F.canny, np.zeros((20, 20, 20)), 4, 0, 0) def test_mask_none(self): result1 = F.canny(np.zeros((20, 20)), 4, 0, 0, np.ones((20, 20), bool)) result2 = F.canny(np.zeros((20, 20)), 4, 0, 0) self.assertTrue(np.all(result1 == result2)) scikit-image-0.9.3/skimage/filter/tests/test_ctmf.py000066400000000000000000000074671223313777300225300ustar00rootroot00000000000000import numpy as np from nose.tools import raises from skimage.filter import median_filter def test_00_00_zeros(): '''The median filter on an array of all zeros should be zero''' result = median_filter(np.zeros((10, 10)), 3, np.ones((10, 10), bool)) assert np.all(result == 0) def test_00_01_all_masked(): '''Test a completely masked image Regression test of IMG-1029''' result = median_filter(np.zeros((10, 10)), 3, np.zeros((10, 10), bool)) assert (np.all(result == 0)) def test_00_02_all_but_one_masked(): mask = np.zeros((10, 10), bool) mask[5, 5] = True median_filter(np.zeros((10, 10)), 3, mask) def test_01_01_mask(): '''The median filter, masking a single value''' img = np.zeros((10, 10)) img[5, 5] = 1 mask = np.ones((10, 10), bool) mask[5, 5] = False result = median_filter(img, 3, mask) assert (np.all(result[mask] == 0)) np.testing.assert_equal(result[5, 5], 1) def test_02_01_median(): '''A median filter larger than the image = median of image''' np.random.seed(0) img = np.random.uniform(size=(9, 9)) result = median_filter(img, 20, np.ones((9, 9), bool)) np.testing.assert_equal(result[0, 0], np.median(img)) assert (np.all(result == np.median(img))) def test_02_02_median_bigger(): '''Use an image of more than 255 values to test approximation''' np.random.seed(0) img = np.random.uniform(size=(20, 20)) result = median_filter(img, 40, np.ones((20, 20), bool)) sorted = np.ravel(img) sorted.sort() min_acceptable = sorted[198] max_acceptable = sorted[202] assert (np.all(result >= min_acceptable)) assert (np.all(result <= max_acceptable)) def test_03_01_shape(): '''Make sure the median filter is the expected octagonal shape''' radius = 5 a_2 = int(radius / 2.414213) i, j = np.mgrid[-10:11, -10:11] octagon = np.ones((21, 21), bool) # # constrain the octagon mask to be the points that are on # the correct side of the 8 edges # octagon[i < -radius] = False octagon[i > radius] = False octagon[j < -radius] = False octagon[j > radius] = False octagon[i + j < -radius - a_2] = False octagon[j - i > radius + a_2] = False octagon[i + j > radius + a_2] = False octagon[i - j > radius + a_2] = False np.random.seed(0) img = np.random.uniform(size=(21, 21)) result = median_filter(img, radius, np.ones((21, 21), bool)) sorted = img[octagon] sorted.sort() min_acceptable = sorted[len(sorted) / 2 - 1] max_acceptable = sorted[len(sorted) / 2 + 1] assert (result[10, 10] >= min_acceptable) assert (result[10, 10] <= max_acceptable) def test_04_01_half_masked(): '''Make sure that the median filter can handle large masked areas.''' img = np.ones((20, 20)) mask = np.ones((20, 20), bool) mask[10:, :] = False img[~ mask] = 2 img[1, 1] = 0 # to prevent short circuit for uniform data. result = median_filter(img, 5, mask) # in partial coverage areas, the result should be only # from the masked pixels assert (np.all(result[:14, :] == 1)) # in zero coverage areas, the result should be the lowest # value in the valid area assert (np.all(result[15:, :] == np.min(img[mask]))) def test_default_values(): img = (np.random.random((20, 20)) * 255).astype(np.uint8) mask = np.ones((20, 20), dtype=np.uint8) result1 = median_filter(img, radius=2, mask=mask, percent=50) result2 = median_filter(img) np.testing.assert_array_equal(result1, result2) @raises(ValueError) def test_insufficient_size(): img = (np.random.random((20, 20)) * 255).astype(np.uint8) median_filter(img, radius=1) @raises(TypeError) def test_wrong_shape(): img = np.empty((10, 10, 3)) median_filter(img) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/filter/tests/test_denoise.py000066400000000000000000000106361223313777300232150ustar00rootroot00000000000000import numpy as np from numpy.testing import run_module_suite, assert_raises, assert_equal from skimage import filter, data, color, img_as_float np.random.seed(1234) lena = img_as_float(data.lena()[:256, :256]) lena_gray = color.rgb2gray(lena) def test_denoise_tv_chambolle_2d(): # lena image img = lena_gray # add noise to lena img += 0.5 * img.std() * np.random.random(img.shape) # clip noise so that it does not exceed allowed range for float images. img = np.clip(img, 0, 1) # denoise denoised_lena = filter.denoise_tv_chambolle(img, weight=60.0) # which dtype? assert denoised_lena.dtype in [np.float, np.float32, np.float64] from scipy import ndimage grad = ndimage.morphological_gradient(img, size=((3, 3))) grad_denoised = ndimage.morphological_gradient( denoised_lena, size=((3, 3))) # test if the total variation has decreased assert grad_denoised.dtype == np.float assert (np.sqrt((grad_denoised**2).sum()) < np.sqrt((grad**2).sum()) / 2) def test_denoise_tv_chambolle_multichannel(): denoised0 = filter.denoise_tv_chambolle(lena[..., 0], weight=60.0) denoised = filter.denoise_tv_chambolle(lena, weight=60.0, multichannel=True) assert_equal(denoised[..., 0], denoised0) def test_denoise_tv_chambolle_float_result_range(): # lena image img = lena_gray int_lena = np.multiply(img, 255).astype(np.uint8) assert np.max(int_lena) > 1 denoised_int_lena = filter.denoise_tv_chambolle(int_lena, weight=60.0) # test if the value range of output float data is within [0.0:1.0] assert denoised_int_lena.dtype == np.float assert np.max(denoised_int_lena) <= 1.0 assert np.min(denoised_int_lena) >= 0.0 def test_denoise_tv_chambolle_3d(): """Apply the TV denoising algorithm on a 3D image representing a sphere.""" x, y, z = np.ogrid[0:40, 0:40, 0:40] mask = (x - 22)**2 + (y - 20)**2 + (z - 17)**2 < 8**2 mask = 100 * mask.astype(np.float) mask += 60 mask += 20 * np.random.random(mask.shape) mask[mask < 0] = 0 mask[mask > 255] = 255 res = filter.denoise_tv_chambolle(mask.astype(np.uint8), weight=100) assert res.dtype == np.float assert res.std() * 255 < mask.std() # test wrong number of dimensions assert_raises(ValueError, filter.denoise_tv_chambolle, np.random.random((8, 8, 8, 8))) def test_denoise_tv_bregman_2d(): img = lena_gray # add some random noise img += 0.5 * img.std() * np.random.random(img.shape) img = np.clip(img, 0, 1) out1 = filter.denoise_tv_bregman(img, weight=10) out2 = filter.denoise_tv_bregman(img, weight=5) # make sure noise is reduced assert img.std() > out1.std() assert out1.std() > out2.std() def test_denoise_tv_bregman_float_result_range(): # lena image img = lena_gray int_lena = np.multiply(img, 255).astype(np.uint8) assert np.max(int_lena) > 1 denoised_int_lena = filter.denoise_tv_bregman(int_lena, weight=60.0) # test if the value range of output float data is within [0.0:1.0] assert denoised_int_lena.dtype == np.float assert np.max(denoised_int_lena) <= 1.0 assert np.min(denoised_int_lena) >= 0.0 def test_denoise_tv_bregman_3d(): img = lena # add some random noise img += 0.5 * img.std() * np.random.random(img.shape) img = np.clip(img, 0, 1) out1 = filter.denoise_tv_bregman(img, weight=10) out2 = filter.denoise_tv_bregman(img, weight=5) # make sure noise is reduced assert img.std() > out1.std() assert out1.std() > out2.std() def test_denoise_bilateral_2d(): img = lena_gray # add some random noise img += 0.5 * img.std() * np.random.random(img.shape) img = np.clip(img, 0, 1) out1 = filter.denoise_bilateral(img, sigma_range=0.1, sigma_spatial=20) out2 = filter.denoise_bilateral(img, sigma_range=0.2, sigma_spatial=30) # make sure noise is reduced assert img.std() > out1.std() assert out1.std() > out2.std() def test_denoise_bilateral_3d(): img = lena # add some random noise img += 0.5 * img.std() * np.random.random(img.shape) img = np.clip(img, 0, 1) out1 = filter.denoise_bilateral(img, sigma_range=0.1, sigma_spatial=20) out2 = filter.denoise_bilateral(img, sigma_range=0.2, sigma_spatial=30) # make sure noise is reduced assert img.std() > out1.std() assert out1.std() > out2.std() if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/filter/tests/test_edges.py000066400000000000000000000272711223313777300226610ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_almost_equal as assert_close import skimage.filter as F from skimage.filter.edges import _mask_filter_result def test_roberts_zeros(): """Roberts' filter on an array of all zeros.""" result = F.roberts(np.zeros((10, 10)), np.ones((10, 10), bool)) assert (np.all(result == 0)) def test_roberts_diagonal1(): """Roberts' filter on a diagonal edge should be a diagonal line.""" image = np.tri(10, 10, 0) expected = ~(np.tri(10, 10, -1).astype(bool) | np.tri(10, 10, -2).astype(bool).transpose()) expected = _mask_filter_result(expected, None) result = F.roberts(image).astype(bool) assert_close(result, expected) def test_roberts_diagonal2(): """Roberts' filter on a diagonal edge should be a diagonal line.""" image = np.rot90(np.tri(10, 10, 0), 3) expected = ~np.rot90(np.tri(10, 10, -1).astype(bool) | np.tri(10, 10, -2).astype(bool).transpose()) expected = _mask_filter_result(expected, None) result = F.roberts(image).astype(bool) assert_close(result, expected) def test_sobel_zeros(): """Sobel on an array of all zeros.""" result = F.sobel(np.zeros((10, 10)), np.ones((10, 10), bool)) assert (np.all(result == 0)) def test_sobel_mask(): """Sobel on a masked array should be zero.""" np.random.seed(0) result = F.sobel(np.random.uniform(size=(10, 10)), np.zeros((10, 10), bool)) assert (np.all(result == 0)) def test_sobel_horizontal(): """Sobel on a horizontal edge should be a horizontal line.""" i, j = np.mgrid[-5:6, -5:6] image = (i >= 0).astype(float) result = F.sobel(image) # Fudge the eroded points i[np.abs(j) == 5] = 10000 assert (np.all(result[i == 0] == 1)) assert (np.all(result[np.abs(i) > 1] == 0)) def test_sobel_vertical(): """Sobel on a vertical edge should be a vertical line.""" i, j = np.mgrid[-5:6, -5:6] image = (j >= 0).astype(float) result = F.sobel(image) j[np.abs(i) == 5] = 10000 assert (np.all(result[j == 0] == 1)) assert (np.all(result[np.abs(j) > 1] == 0)) def test_hsobel_zeros(): """Horizontal sobel on an array of all zeros.""" result = F.hsobel(np.zeros((10, 10)), np.ones((10, 10), bool)) assert (np.all(result == 0)) def test_hsobel_mask(): """Horizontal Sobel on a masked array should be zero.""" np.random.seed(0) result = F.hsobel(np.random.uniform(size=(10, 10)), np.zeros((10, 10), bool)) assert (np.all(result == 0)) def test_hsobel_horizontal(): """Horizontal Sobel on an edge should be a horizontal line.""" i, j = np.mgrid[-5:6, -5:6] image = (i >= 0).astype(float) result = F.hsobel(image) # Fudge the eroded points i[np.abs(j) == 5] = 10000 assert (np.all(result[i == 0] == 1)) assert (np.all(result[np.abs(i) > 1] == 0)) def test_hsobel_vertical(): """Horizontal Sobel on a vertical edge should be zero.""" i, j = np.mgrid[-5:6, -5:6] image = (j >= 0).astype(float) result = F.hsobel(image) assert (np.all(result == 0)) def test_vsobel_zeros(): """Vertical sobel on an array of all zeros.""" result = F.vsobel(np.zeros((10, 10)), np.ones((10, 10), bool)) assert (np.all(result == 0)) def test_vsobel_mask(): """Vertical Sobel on a masked array should be zero.""" np.random.seed(0) result = F.vsobel(np.random.uniform(size=(10, 10)), np.zeros((10, 10), bool)) assert (np.all(result == 0)) def test_vsobel_vertical(): """Vertical Sobel on an edge should be a vertical line.""" i, j = np.mgrid[-5:6, -5:6] image = (j >= 0).astype(float) result = F.vsobel(image) # Fudge the eroded points j[np.abs(i) == 5] = 10000 assert (np.all(result[j == 0] == 1)) assert (np.all(result[np.abs(j) > 1] == 0)) def test_vsobel_horizontal(): """vertical Sobel on a horizontal edge should be zero.""" i, j = np.mgrid[-5:6, -5:6] image = (i >= 0).astype(float) result = F.vsobel(image) eps = .000001 assert (np.all(np.abs(result) < eps)) def test_scharr_zeros(): """Scharr on an array of all zeros.""" result = F.scharr(np.zeros((10, 10)), np.ones((10, 10), bool)) assert (np.all(result == 0)) def test_scharr_mask(): """Scharr on a masked array should be zero.""" np.random.seed(0) result = F.scharr(np.random.uniform(size=(10, 10)), np.zeros((10, 10), bool)) assert (np.all(result == 0)) def test_scharr_horizontal(): """Scharr on an edge should be a horizontal line.""" i, j = np.mgrid[-5:6, -5:6] image = (i >= 0).astype(float) result = F.scharr(image) # Fudge the eroded points i[np.abs(j) == 5] = 10000 assert (np.all(result[i == 0] == 1)) assert (np.all(result[np.abs(i) > 1] == 0)) def test_scharr_vertical(): """Scharr on a vertical edge should be a vertical line.""" i, j = np.mgrid[-5:6, -5:6] image = (j >= 0).astype(float) result = F.scharr(image) j[np.abs(i) == 5] = 10000 assert (np.all(result[j == 0] == 1)) assert (np.all(result[np.abs(j) > 1] == 0)) def test_hscharr_zeros(): """Horizontal Scharr on an array of all zeros.""" result = F.hscharr(np.zeros((10, 10)), np.ones((10, 10), bool)) assert (np.all(result == 0)) def test_hscharr_mask(): """Horizontal Scharr on a masked array should be zero.""" np.random.seed(0) result = F.hscharr(np.random.uniform(size=(10, 10)), np.zeros((10, 10), bool)) assert (np.all(result == 0)) def test_hscharr_horizontal(): """Horizontal Scharr on an edge should be a horizontal line.""" i, j = np.mgrid[-5:6, -5:6] image = (i >= 0).astype(float) result = F.hscharr(image) # Fudge the eroded points i[np.abs(j) == 5] = 10000 assert (np.all(result[i == 0] == 1)) assert (np.all(result[np.abs(i) > 1] == 0)) def test_hscharr_vertical(): """Horizontal Scharr on a vertical edge should be zero.""" i, j = np.mgrid[-5:6, -5:6] image = (j >= 0).astype(float) result = F.hscharr(image) assert (np.all(result == 0)) def test_vscharr_zeros(): """Vertical Scharr on an array of all zeros.""" result = F.vscharr(np.zeros((10, 10)), np.ones((10, 10), bool)) assert (np.all(result == 0)) def test_vscharr_mask(): """Vertical Scharr on a masked array should be zero.""" np.random.seed(0) result = F.vscharr(np.random.uniform(size=(10, 10)), np.zeros((10, 10), bool)) assert (np.all(result == 0)) def test_vscharr_vertical(): """Vertical Scharr on an edge should be a vertical line.""" i, j = np.mgrid[-5:6, -5:6] image = (j >= 0).astype(float) result = F.vscharr(image) # Fudge the eroded points j[np.abs(i) == 5] = 10000 assert (np.all(result[j == 0] == 1)) assert (np.all(result[np.abs(j) > 1] == 0)) def test_vscharr_horizontal(): """vertical Scharr on a horizontal edge should be zero.""" i, j = np.mgrid[-5:6, -5:6] image = (i >= 0).astype(float) result = F.vscharr(image) eps = .000001 assert (np.all(np.abs(result) < eps)) def test_prewitt_zeros(): """Prewitt on an array of all zeros.""" result = F.prewitt(np.zeros((10, 10)), np.ones((10, 10), bool)) assert (np.all(result == 0)) def test_prewitt_mask(): """Prewitt on a masked array should be zero.""" np.random.seed(0) result = F.prewitt(np.random.uniform(size=(10, 10)), np.zeros((10, 10), bool)) eps = .000001 assert (np.all(np.abs(result) < eps)) def test_prewitt_horizontal(): """Prewitt on an edge should be a horizontal line.""" i, j = np.mgrid[-5:6, -5:6] image = (i >= 0).astype(float) result = F.prewitt(image) # Fudge the eroded points i[np.abs(j) == 5] = 10000 eps = .000001 assert (np.all(result[i == 0] == 1)) assert (np.all(np.abs(result[np.abs(i) > 1]) < eps)) def test_prewitt_vertical(): """Prewitt on a vertical edge should be a vertical line.""" i, j = np.mgrid[-5:6, -5:6] image = (j >= 0).astype(float) result = F.prewitt(image) eps = .000001 j[np.abs(i) == 5] = 10000 assert (np.all(result[j == 0] == 1)) assert (np.all(np.abs(result[np.abs(j) > 1]) < eps)) def test_hprewitt_zeros(): """Horizontal prewitt on an array of all zeros.""" result = F.hprewitt(np.zeros((10, 10)), np.ones((10, 10), bool)) assert (np.all(result == 0)) def test_hprewitt_mask(): """Horizontal prewitt on a masked array should be zero.""" np.random.seed(0) result = F.hprewitt(np.random.uniform(size=(10, 10)), np.zeros((10, 10), bool)) eps = .000001 assert (np.all(np.abs(result) < eps)) def test_hprewitt_horizontal(): """Horizontal prewitt on an edge should be a horizontal line.""" i, j = np.mgrid[-5:6, -5:6] image = (i >= 0).astype(float) result = F.hprewitt(image) # Fudge the eroded points i[np.abs(j) == 5] = 10000 eps = .000001 assert (np.all(result[i == 0] == 1)) assert (np.all(np.abs(result[np.abs(i) > 1]) < eps)) def test_hprewitt_vertical(): """Horizontal prewitt on a vertical edge should be zero.""" i, j = np.mgrid[-5:6, -5:6] image = (j >= 0).astype(float) result = F.hprewitt(image) eps = .000001 assert (np.all(np.abs(result) < eps)) def test_vprewitt_zeros(): """Vertical prewitt on an array of all zeros.""" result = F.vprewitt(np.zeros((10, 10)), np.ones((10, 10), bool)) assert (np.all(result == 0)) def test_vprewitt_mask(): """Vertical prewitt on a masked array should be zero.""" np.random.seed(0) result = F.vprewitt(np.random.uniform(size=(10, 10)), np.zeros((10, 10), bool)) assert (np.all(result == 0)) def test_vprewitt_vertical(): """Vertical prewitt on an edge should be a vertical line.""" i, j = np.mgrid[-5:6, -5:6] image = (j >= 0).astype(float) result = F.vprewitt(image) # Fudge the eroded points j[np.abs(i) == 5] = 10000 assert (np.all(result[j == 0] == 1)) eps = .000001 assert (np.all(np.abs(result[np.abs(j) > 1]) < eps)) def test_vprewitt_horizontal(): """Vertical prewitt on a horizontal edge should be zero.""" i, j = np.mgrid[-5:6, -5:6] image = (i >= 0).astype(float) result = F.vprewitt(image) eps = .000001 assert (np.all(np.abs(result) < eps)) def test_horizontal_mask_line(): """Horizontal edge filters mask pixels surrounding input mask.""" vgrad, _ = np.mgrid[:1:11j, :1:11j] # vertical gradient with spacing 0.1 vgrad[5, :] = 1 # bad horizontal line mask = np.ones_like(vgrad) mask[5, :] = 0 # mask bad line expected = np.zeros_like(vgrad) expected[1:-1, 1:-1] = 0.2 # constant gradient for most of image, expected[4:7, 1:-1] = 0 # but line and neighbors masked for grad_func in (F.hprewitt, F.hsobel, F.hscharr): result = grad_func(vgrad, mask) yield assert_close, result, expected def test_vertical_mask_line(): """Vertical edge filters mask pixels surrounding input mask.""" _, hgrad = np.mgrid[:1:11j, :1:11j] # horizontal gradient with spacing 0.1 hgrad[:, 5] = 1 # bad vertical line mask = np.ones_like(hgrad) mask[:, 5] = 0 # mask bad line expected = np.zeros_like(hgrad) expected[1:-1, 1:-1] = 0.2 # constant gradient for most of image, expected[1:-1, 4:7] = 0 # but line and neighbors masked for grad_func in (F.vprewitt, F.vsobel, F.vscharr): result = grad_func(hgrad, mask) yield assert_close, result, expected if __name__ == "__main__": from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/filter/tests/test_gabor.py000066400000000000000000000055241223313777300226610ustar00rootroot00000000000000import numpy as np from numpy.testing import (assert_equal, assert_almost_equal, assert_array_almost_equal) from skimage.filter._gabor import gabor_kernel, gabor_filter, _sigma_prefactor def test_gabor_kernel_size(): sigma_x = 5 sigma_y = 10 # Sizes cut off at +/- three sigma + 1 for the center size_x = sigma_x * 6 + 1 size_y = sigma_y * 6 + 1 kernel = gabor_kernel(0, theta=0, sigma_x=sigma_x, sigma_y=sigma_y) assert_equal(kernel.shape, (size_y, size_x)) kernel = gabor_kernel(0, theta=np.pi/2, sigma_x=sigma_x, sigma_y=sigma_y) assert_equal(kernel.shape, (size_x, size_y)) def test_gabor_kernel_bandwidth(): kernel = gabor_kernel(1, bandwidth=1) assert_equal(kernel.shape, (5, 5)) kernel = gabor_kernel(1, bandwidth=0.5) assert_equal(kernel.shape, (9, 9)) kernel = gabor_kernel(0.5, bandwidth=1) assert_equal(kernel.shape, (9, 9)) def test_sigma_prefactor(): assert_almost_equal(_sigma_prefactor(1), 0.56, 2) assert_almost_equal(_sigma_prefactor(0.5), 1.09, 2) def test_gabor_kernel_sum(): for sigma_x in range(1, 10, 2): for sigma_y in range(1, 10, 2): for frequency in range(0, 10, 2): kernel = gabor_kernel(frequency+0.1, theta=0, sigma_x=sigma_x, sigma_y=sigma_y) # make sure gaussian distribution is covered nearly 100% assert_almost_equal(np.abs(kernel).sum(), 1, 2) def test_gabor_kernel_theta(): for sigma_x in range(1, 10, 2): for sigma_y in range(1, 10, 2): for frequency in range(0, 10, 2): for theta in range(0, 10, 2): kernel0 = gabor_kernel(frequency+0.1, theta=theta, sigma_x=sigma_x, sigma_y=sigma_y) kernel180 = gabor_kernel(frequency, theta=theta+np.pi, sigma_x=sigma_x, sigma_y=sigma_y) assert_array_almost_equal(np.abs(kernel0), np.abs(kernel180)) def test_gabor_filter(): Y, X = np.mgrid[:40, :40] frequencies = (0.1, 0.3) wave_images = [np.sin(2 * np.pi * X * f) for f in frequencies] def match_score(image, frequency): gabor_responses = gabor_filter(image, frequency) return np.mean(np.hypot(*gabor_responses)) # Gabor scores: diagonals are frequency-matched, off-diagonals are not. responses = np.array([[match_score(image, f) for f in frequencies] for image in wave_images]) assert responses[0, 0] > responses[0, 1] assert responses[1, 1] > responses[0, 1] assert responses[0, 0] > responses[1, 0] assert responses[1, 1] > responses[1, 0] if __name__ == "__main__": from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/filter/tests/test_gaussian.py000066400000000000000000000027551223313777300234040ustar00rootroot00000000000000import numpy as np from skimage.filter._gaussian import gaussian_filter def test_null_sigma(): a = np.zeros((3, 3)) a[1, 1] = 1. assert np.all(gaussian_filter(a, 0) == a) def test_energy_decrease(): a = np.zeros((3, 3)) a[1, 1] = 1. gaussian_a = gaussian_filter(a, sigma=1, mode='reflect') assert gaussian_a.std() < a.std() def test_multichannel(): a = np.zeros((5, 5, 3)) a[1, 1] = np.arange(1, 4) gaussian_rgb_a = gaussian_filter(a, sigma=1, mode='reflect', multichannel=True) # Check that the mean value is conserved in each channel # (color channels are not mixed together) assert np.allclose([a[..., i].mean() for i in range(3)], [gaussian_rgb_a[..., i].mean() for i in range(3)]) # Test multichannel = None gaussian_rgb_a = gaussian_filter(a, sigma=1, mode='reflect') # Check that the mean value is conserved in each channel # (color channels are not mixed together) assert np.allclose([a[..., i].mean() for i in range(3)], [gaussian_rgb_a[..., i].mean() for i in range(3)]) # Iterable sigma gaussian_rgb_a = gaussian_filter(a, sigma=[1, 2], mode='reflect', multichannel=True) assert np.allclose([a[..., i].mean() for i in range(3)], [gaussian_rgb_a[..., i].mean() for i in range(3)]) if __name__ == "__main__": from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/filter/tests/test_lpi_filter.py000066400000000000000000000033331223313777300237140ustar00rootroot00000000000000import os.path import numpy as np from numpy.testing import * from skimage import data_dir from skimage.io import * from skimage.filter import * class TestLPIFilter2D(object): img = imread(os.path.join(data_dir, 'camera.png'), flatten=True)[:50, :50] def filt_func(self, r, c): return np.exp(-np.hypot(r, c) / 1) def setUp(self): self.f = LPIFilter2D(self.filt_func) def tst_shape(self, x): X = self.f(x) assert_equal(X.shape, x.shape) def test_ip_shape(self): rows, columns = self.img.shape[:2] for c_slice in [slice(0, columns), slice(0, columns - 5), slice(0, columns - 20)]: yield (self.tst_shape, self.img[:, c_slice]) def test_inverse(self): F = self.f(self.img) g = inverse(F, predefined_filter=self.f) assert_equal(g.shape, self.img.shape) g1 = inverse(F[::-1, ::-1], predefined_filter=self.f) assert ((g - g1[::-1, ::-1]).sum() < 55) # test cache g1 = inverse(F[::-1, ::-1], predefined_filter=self.f) assert ((g - g1[::-1, ::-1]).sum() < 55) g1 = inverse(F[::-1, ::-1], self.filt_func) assert ((g - g1[::-1, ::-1]).sum() < 55) def test_wiener(self): F = self.f(self.img) g = wiener(F, predefined_filter=self.f) assert_equal(g.shape, self.img.shape) g1 = wiener(F[::-1, ::-1], predefined_filter=self.f) assert ((g - g1[::-1, ::-1]).sum() < 1) g1 = wiener(F[::-1, ::-1], self.filt_func) assert ((g - g1[::-1, ::-1]).sum() < 1) def test_non_callable(self): assert_raises(ValueError, LPIFilter2D, None) if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/filter/tests/test_thresholding.py000066400000000000000000000077451223313777300242700ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal import skimage from skimage import data from skimage.filter.thresholding import (threshold_adaptive, threshold_otsu, threshold_yen) class TestSimpleImage(): def setup(self): self.image = np.array([[0, 0, 1, 3, 5], [0, 1, 4, 3, 4], [1, 2, 5, 4, 1], [2, 4, 5, 2, 1], [4, 5, 1, 0, 0]], dtype=int) def test_otsu(self): assert threshold_otsu(self.image) == 2 def test_otsu_negative_int(self): image = self.image - 2 assert threshold_otsu(image) == 0 def test_otsu_float_image(self): image = np.float64(self.image) assert 2 <= threshold_otsu(image) < 3 def test_yen(self): assert threshold_yen(self.image) == 2 def test_yen_negative_int(self): image = self.image - 2 assert threshold_yen(image) == 0 def test_yen_float_image(self): image = np.float64(self.image) assert 2 <= threshold_yen(image) < 3 def test_yen_arange(self): image = np.arange(256) assert threshold_yen(image) == 127 def test_yen_binary(self): image = np.zeros([2,256], dtype='uint8') image[0] = 255 assert threshold_yen(image) < 1 def test_threshold_adaptive_generic(self): def func(arr): return arr.sum() / arr.shape[0] ref = np.array( [[False, False, False, False, True], [False, False, True, False, True], [False, False, True, True, False], [False, True, True, False, False], [ True, True, False, False, False]] ) out = threshold_adaptive(self.image, 3, method='generic', param=func) assert_array_equal(ref, out) def test_threshold_adaptive_gaussian(self): ref = np.array( [[False, False, False, False, True], [False, False, True, False, True], [False, False, True, True, False], [False, True, True, False, False], [ True, True, False, False, False]] ) out = threshold_adaptive(self.image, 3, method='gaussian') assert_array_equal(ref, out) def test_threshold_adaptive_mean(self): ref = np.array( [[False, False, False, False, True], [False, False, True, False, True], [False, False, True, True, False], [False, True, True, False, False], [ True, True, False, False, False]] ) out = threshold_adaptive(self.image, 3, method='mean') assert_array_equal(ref, out) def test_threshold_adaptive_median(self): ref = np.array( [[False, False, False, False, True], [False, False, True, False, False], [False, False, True, False, False], [False, False, True, True, False], [False, True, False, False, False]] ) out = threshold_adaptive(self.image, 3, method='median') assert_array_equal(ref, out) def test_otsu_camera_image(): camera = skimage.img_as_ubyte(data.camera()) assert 86 < threshold_otsu(camera) < 88 def test_otsu_coins_image(): coins = skimage.img_as_ubyte(data.coins()) assert 106 < threshold_otsu(coins) < 108 def test_otsu_coins_image_as_float(): coins = skimage.img_as_float(data.coins()) assert 0.41 < threshold_otsu(coins) < 0.42 def test_otsu_lena_image(): lena = skimage.img_as_ubyte(data.lena()) assert 140 < threshold_otsu(lena) < 142 def test_yen_coins_image(): coins = skimage.img_as_ubyte(data.coins()) assert 109 < threshold_yen(coins) < 111 def test_yen_coins_image_as_float(): coins = skimage.img_as_float(data.coins()) assert 0.43 < threshold_yen(coins) < 0.44 if __name__ == '__main__': np.testing.run_module_suite() scikit-image-0.9.3/skimage/filter/thresholding.py000066400000000000000000000155441223313777300220630ustar00rootroot00000000000000__all__ = ['threshold_adaptive', 'threshold_otsu', 'threshold_yen'] import numpy as np import scipy.ndimage from skimage.exposure import histogram def threshold_adaptive(image, block_size, method='gaussian', offset=0, mode='reflect', param=None): """Applies an adaptive threshold to an array. Also known as local or dynamic thresholding where the threshold value is the weighted mean for the local neighborhood of a pixel subtracted by a constant. Alternatively the threshold can be determined dynamically by a a given function using the 'generic' method. Parameters ---------- image : (N, M) ndarray Input image. block_size : int Uneven size of pixel neighborhood which is used to calculate the threshold value (e.g. 3, 5, 7, ..., 21, ...). method : {'generic', 'gaussian', 'mean', 'median'}, optional Method used to determine adaptive threshold for local neighbourhood in weighted mean image. * 'generic': use custom function (see `param` parameter) * 'gaussian': apply gaussian filter (see `param` parameter for custom\ sigma value) * 'mean': apply arithmetic mean filter * 'median': apply median rank filter By default the 'gaussian' method is used. offset : float, optional Constant subtracted from weighted mean of neighborhood to calculate the local threshold value. Default offset is 0. mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional The mode parameter determines how the array borders are handled, where cval is the value when mode is equal to 'constant'. Default is 'reflect'. param : {int, function}, optional Either specify sigma for 'gaussian' method or function object for 'generic' method. This functions takes the flat array of local neighbourhood as a single argument and returns the calculated threshold for the centre pixel. Returns ------- threshold : (N, M) ndarray Thresholded binary image References ---------- .. [1] http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html?highlight=threshold#adaptivethreshold Examples -------- >>> from skimage.data import camera >>> image = camera() >>> binary_image1 = threshold_adaptive(image, 15, 'mean') >>> func = lambda arr: arr.mean() >>> binary_image2 = threshold_adaptive(image, 15, 'generic', param=func) """ thresh_image = np.zeros(image.shape, 'double') if method == 'generic': scipy.ndimage.generic_filter(image, param, block_size, output=thresh_image, mode=mode) elif method == 'gaussian': if param is None: # automatically determine sigma which covers > 99% of distribution sigma = (block_size - 1) / 6.0 else: sigma = param scipy.ndimage.gaussian_filter(image, sigma, output=thresh_image, mode=mode) elif method == 'mean': mask = 1. / block_size * np.ones((block_size,)) # separation of filters to speedup convolution scipy.ndimage.convolve1d(image, mask, axis=0, output=thresh_image, mode=mode) scipy.ndimage.convolve1d(thresh_image, mask, axis=1, output=thresh_image, mode=mode) elif method == 'median': scipy.ndimage.median_filter(image, block_size, output=thresh_image, mode=mode) return image > (thresh_image - offset) def threshold_otsu(image, nbins=256): """Return threshold value based on Otsu's method. Parameters ---------- image : array Input image. nbins : int, optional Number of bins used to calculate histogram. This value is ignored for integer arrays. Returns ------- threshold : float Upper threshold value. All pixels intensities that less or equal of this value assumed as foreground. References ---------- .. [1] Wikipedia, http://en.wikipedia.org/wiki/Otsu's_Method Examples -------- >>> from skimage.data import camera >>> image = camera() >>> thresh = threshold_otsu(image) >>> binary = image <= thresh """ hist, bin_centers = histogram(image, nbins) hist = hist.astype(float) # class probabilities for all possible thresholds weight1 = np.cumsum(hist) weight2 = np.cumsum(hist[::-1])[::-1] # class means for all possible thresholds mean1 = np.cumsum(hist * bin_centers) / weight1 mean2 = (np.cumsum((hist * bin_centers)[::-1]) / weight2[::-1])[::-1] # Clip ends to align class 1 and class 2 variables: # The last value of `weight1`/`mean1` should pair with zero values in # `weight2`/`mean2`, which do not exist. variance12 = weight1[:-1] * weight2[1:] * (mean1[:-1] - mean2[1:])**2 idx = np.argmax(variance12) threshold = bin_centers[:-1][idx] return threshold def threshold_yen(image, nbins=256): """Return threshold value based on Yen's method. Parameters ---------- image : array Input image. nbins : int, optional Number of bins used to calculate histogram. This value is ignored for integer arrays. Returns ------- threshold : float Upper threshold value. All pixels intensities that less or equal of this value assumed as foreground. References ---------- .. [1] Yen J.C., Chang F.J., and Chang S. (1995) "A New Criterion for Automatic Multilevel Thresholding" IEEE Trans. on Image Processing, 4(3): 370-378 .. [2] Sezgin M. and Sankur B. (2004) "Survey over Image Thresholding Techniques and Quantitative Performance Evaluation" Journal of Electronic Imaging, 13(1): 146-165, http://www.busim.ee.boun.edu.tr/~sankur/SankurFolder/Threshold_survey.pdf .. [3] ImageJ AutoThresholder code, http://fiji.sc/wiki/index.php/Auto_Threshold Examples -------- >>> from skimage.data import camera >>> image = camera() >>> thresh = threshold_yen(image) >>> binary = image <= thresh """ hist, bin_centers = histogram(image, nbins) norm_histo = hist.astype(float) / hist.sum() # Probability mass function P1 = np.cumsum(norm_histo) # Cumulative normalized histogram P1_sq = np.cumsum(norm_histo ** 2) # Get cumsum calculated from end of squared array: P2_sq = np.cumsum(norm_histo[::-1] ** 2)[::-1] # P2_sq indexes is shifted +1. I assume, with P1[:-1] it's help avoid '-inf' # in crit. ImageJ Yen implementation replaces those values by zero. crit = np.log(((P1_sq[:-1] * P2_sq[1:]) ** -1) * \ (P1[:-1] * (1.0 - P1[:-1])) ** 2) max_crit = np.argmax(crit) threshold = bin_centers[:-1][max_crit] return threshold scikit-image-0.9.3/skimage/graph/000077500000000000000000000000001223313777300166225ustar00rootroot00000000000000scikit-image-0.9.3/skimage/graph/__init__.py000066400000000000000000000003061223313777300207320ustar00rootroot00000000000000from .spath import shortest_path from .mcp import MCP, MCP_Geometric, route_through_array __all__ = ['shortest_path', 'MCP', 'MCP_Geometric', 'route_through_array']scikit-image-0.9.3/skimage/graph/_mcp.pxd000066400000000000000000000016721223313777300202630ustar00rootroot00000000000000""" This is the definition file for mcp.pyx. It contains the definitions of the mcp class, such that other cython modules can "cimport mcp" and subclass it. """ cimport heap cimport numpy as cnp ctypedef heap.BOOL_T BOOL_T ctypedef unsigned char DIM_T ctypedef cnp.float64_t FLOAT_T cdef class MCP: cdef heap.FastUpdateBinaryHeap costs_heap cdef object costs_shape cdef DIM_T dim cdef object flat_costs cdef object flat_cumulative_costs cdef object traceback_offsets cdef object flat_pos_edge_map cdef object flat_neg_edge_map cdef readonly object offsets cdef object flat_offsets cdef object offset_lengths cdef BOOL_T dirty cdef BOOL_T use_start_cost # if use_start_cost is true, the cost of the starting element is added to # the cost of the path. Set to true by default in the base class... cdef FLOAT_T _travel_cost(self, FLOAT_T old_cost, FLOAT_T new_cost, FLOAT_T offset_length) scikit-image-0.9.3/skimage/graph/_mcp.pyx000066400000000000000000000627721223313777300203200ustar00rootroot00000000000000#cython: cdivision=True #cython: nonecheck=False """Cython implementation of Dijkstra's minimum cost path algorithm, for use with data on a n-dimensional lattice. Original author: Zachary Pincus Inspired by code from Almar Klein License: BSD Copyright 2009 Zachary Pincus Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ import cython import numpy as np import heap cimport numpy as cnp cimport heap ctypedef cnp.int8_t OFFSET_T OFFSET_D = np.int8 ctypedef cnp.int16_t OFFSETS_INDEX_T OFFSETS_INDEX_D = np.int16 ctypedef cnp.int8_t EDGE_T EDGE_D = np.int8 ctypedef cnp.intp_t INDEX_T INDEX_D = np.intp FLOAT_D = np.float64 @cython.boundscheck(False) @cython.wraparound(False) def _get_edge_map(shape): """Return an array with edge points/lines/planes/hyperplanes marked. Given a shape (of length n), return an edge_map array with a shape of original_shape + (n,), where, for each dimension, edge_map[...,dim] will have zeros at indices not along an edge in that dimension, -1s at indices along the lower boundary, and +1s on the upper boundary. This allows one to, given an nd index, calculate not only if the index is at the edge of the array, but if so, which edge(s) it lies along. """ d = len(shape) edges = np.zeros(shape+(d,), order='F', dtype=EDGE_D) for i in range(d): slices = [slice(None)] * (d+1) slices[d] = i slices[i] = 0 edges[tuple(slices)] = -1 slices[i] = -1 edges[tuple(slices)] = 1 return edges @cython.boundscheck(False) @cython.wraparound(False) def _offset_edge_map(shape, offsets): """Return an array with positions marked where offsets will step out of bounds. Given a shape (of length n) and a list of n-d offsets, return a two arrays of (n,) + shape: pos_edge_map and neg_edge_map. For each dimension xxx_edge_map[dim, ...] has zeros at indices at which none of the given offsets (in that dimension) of the given sign (positive or negative, respectively) will step out of bounds. If the value is nonzero, it gives the largest offset (in terms of absolute value) that will step out of bounds in that direction. An example will be explanatory: >>> offsets = [[-2,0], [1,1], [0,2]] >>> pos_edge_map, neg_edge_map = _offset_edge_map((4,4), offsets) >>> neg_edge_map[0] array([[-1, -1, -1, -1], [-2, -2, -2, -2], [ 0, 0, 0, 0], [ 0, 0, 0, 0]], dtype=int8) >>> pos_edge_map[1] array([[0, 0, 2, 1], [0, 0, 2, 1], [0, 0, 2, 1], [0, 0, 2, 1]], dtype=int8) """ indices = np.indices(shape) # indices.shape = (n,)+shape #get the distance from each index to the upper or lower edge in each dim pos_edges = (shape - indices.T).T neg_edges = -1 - indices # now set the distances to zero if none of the given offsets could reach offsets = np.asarray(offsets) maxes = offsets.max(axis=0) mins = offsets.min(axis=0) for pos, neg, mx, mn in zip(pos_edges, neg_edges, maxes, mins): pos[pos > mx] = 0 neg[neg < mn] = 0 return pos_edges.astype(EDGE_D), neg_edges.astype(EDGE_D) @cython.boundscheck(False) @cython.wraparound(False) def make_offsets(d, fully_connected): """Make a list of offsets from a center point defining a n-dim neighborhood. Parameters ---------- d : int dimension of the offsets to produce fully_connected : bool whether the neighborhood should be singly- of fully-connected Returns ------- offsets : list of tuples of length `d` Examples -------- The singly-connected 2-d neighborhood is four offsets: >>> make_offsets(2, False) [(-1,0), (1,0), (0,-1), (0,1)] While the fully-connected 2-d neighborhood is the full cartesian product of {-1, 0, 1} (less the origin (0,0)). """ if fully_connected: mask = np.ones([3]*d, dtype=np.uint8) mask[tuple([1]*d)] = 0 else: mask = np.zeros([3]*d, dtype=np.uint8) for i in range(d): indices = [1]*d indices[i] = (0, -1) mask[tuple(indices)] = 1 offsets = [] for indices, value in np.ndenumerate(mask): if value == 1: indices = np.array(indices) - 1 offsets.append(indices) return offsets @cython.boundscheck(True) @cython.wraparound(True) def _unravel_index_fortran(flat_indices, shape): """_unravel_index_fortran(flat_indices, shape) Given a flat index into an n-d fortran-strided array, return an index tuple. """ strides = np.multiply.accumulate([1] + list(shape[:-1])) indices = [tuple(idx/strides % shape) for idx in flat_indices] return indices @cython.boundscheck(True) @cython.wraparound(True) def _ravel_index_fortran(indices, shape): """_ravel_index_fortran(flat_indices, shape) Given an index tuple into an n-d fortran-strided array, return a flat index. """ strides = np.multiply.accumulate([1] + list(shape[:-1])) flat_indices = [np.sum(strides * idx) for idx in indices] return flat_indices @cython.boundscheck(False) @cython.wraparound(False) def _normalize_indices(indices, shape): """_normalize_indices(indices, shape) Make all indices positive. If an index is out-of-bounds, return None. """ new_indices = [] for index in indices: if len(index) != len(shape): return None new_index = [] for i, s in zip(index, shape): i = int(i) if i < 0: i = s+i if not (0 <= i < s): return None new_index.append(i) new_indices.append(new_index) return new_indices @cython.boundscheck(True) @cython.wraparound(True) def _reverse(arr): """Reverse index an array safely, with bounds/wraparound checks on.""" return arr[::-1] @cython.boundscheck(False) @cython.wraparound(False) cdef class MCP: """MCP(costs, offsets=None, fully_connected=True) A class for finding the minimum cost path through a given n-d costs array. Given an n-d costs array, this class can be used to find the minimum-cost path through that array from any set of points to any other set of points. Basic usage is to initialize the class and call find_costs() with a one or more starting indices (and an optional list of end indices). After that, call traceback() one or more times to find the path from any given end-position to the closest starting index. New paths through the same costs array can be found by calling find_costs() repeatedly. The cost of a path is calculated simply as the sum of the values of the `costs` array at each point on the path. The class MCP_Geometric, on the other hand, accounts for the fact that diagonal vs. axial moves are of different lengths, and weights the path cost accordingly. Array elements with infinite or negative costs will simply be ignored, as will paths whose cumulative cost overflows to infinite. Parameters ---------- costs : ndarray offsets : iterable, optional A list of offset tuples: each offset specifies a valid move from a given n-d position. If not provided, offsets corresponding to a singly- or fully-connected n-d neighborhood will be constructed with make_offsets(), using the `fully_connected` parameter value. fully_connected : bool, optional If no `offsets` are provided, this determines the connectivity of the generated neighborhood. If true, the path may go along diagonals between elements of the `costs` array; otherwise only axial moves are permitted. Attributes ---------- offsets : ndarray Equivalent to the `offsets` provided to the constructor, or if none were so provided, the offsets created for the requested n-d neighborhood. These are useful for interpreting the `traceback` array returned by the find_costs() method. """ def __init__(self, costs, offsets=None, fully_connected=True): """__init__(costs, offsets=None, fully_connected=True) See class documentation. """ costs = np.asarray(costs) if not np.can_cast(costs.dtype, FLOAT_D): raise TypeError('cannot cast costs array to ' + str(FLOAT_D)) # We use flat, fortran-style indexing here (could use C-style, # but this is my code and I like fortran-style! Also, it's # faster when working with image arrays, which are often # already fortran-strided.) self.flat_costs = costs.astype(FLOAT_D).flatten('F') size = self.flat_costs.shape[0] self.flat_cumulative_costs = np.empty(size, dtype=FLOAT_D) self.flat_cumulative_costs.fill(np.inf) self.dim = len(costs.shape) self.costs_shape = costs.shape self.costs_heap = heap.FastUpdateBinaryHeap(initial_capacity=size, max_reference=size-1) # This array stores, for each point, the index into the offset # array (see below) that leads to that point from the # predecessor point. self.traceback_offsets = np.empty(size, dtype=OFFSETS_INDEX_D) self.traceback_offsets.fill(-1) # The offsets are a list of relative offsets from a central # point to each point in the relevant neighborhood. (e.g. (-1, # 0) might be a 2d offset). # These offsets are raveled to provide flat, 1d offsets that can be used # in the same way for flat indices to move to neighboring points. if offsets is None: offsets = make_offsets(self.dim, fully_connected) self.offsets = np.array(offsets, dtype=OFFSET_D) self.flat_offsets = np.array( _ravel_index_fortran(self.offsets, self.costs_shape), dtype=INDEX_D) # Instead of unraveling each index during the pathfinding algorithm, we # will use a pre-computed "edge map" that specifies for each dimension # whether a given index is on a lower or upper boundary (or none at all) # Flatten this map to get something that can be indexed as by the same # flat indices as elsewhere. # The edge map stores more than a boolean "on some edge" flag so as to # allow us to examine the non-out-of-bounds neighbors for a given edge # point while excluding the neighbors which are outside the array. pos, neg = _offset_edge_map(costs.shape, self.offsets) self.flat_pos_edge_map = pos.reshape((self.dim, size), order='F') self.flat_neg_edge_map = neg.reshape((self.dim, size), order='F') # The offset lengths are the distances traveled along each offset self.offset_lengths = np.sqrt( np.sum(self.offsets**2, axis=1)).astype(FLOAT_D) self.dirty = 0 self.use_start_cost = 1 def _reset(self): """_reset() Clears paths found by find_costs(). """ self.costs_heap.reset() self.traceback_offsets.fill(-1) self.flat_cumulative_costs.fill(np.inf) self.dirty = 0 cdef FLOAT_T _travel_cost(self, FLOAT_T old_cost, FLOAT_T new_cost, FLOAT_T offset_length): return new_cost def find_costs(self, starts, ends=None, find_all_ends=True): """ Find the minimum-cost path from the given starting points. This method finds the minimum-cost path to the specified ending indices from any one of the specified starting indices. If no end positions are given, then the minimum-cost path to every position in the costs array will be found. Parameters ---------- starts : iterable A list of n-d starting indices (where n is the dimension of the `costs` array). The minimum cost path to the closest/cheapest starting point will be found. ends : iterable, optional A list of n-d ending indices. find_all_ends : bool, optional If 'True' (default), the minimum-cost-path to every specified end-position will be found; otherwise the algorithm will stop when a a path is found to any end-position. (If no `ends` were specified, then this parameter has no effect.) Returns ------- cumulative_costs : ndarray Same shape as the `costs` array; this array records the minimum cost path from the nearest/cheapest starting index to each index considered. (If `ends` were specified, not all elements in the array will necessarily be considered: positions not evaluated will have a cumulative cost of inf. If `find_all_ends` is 'False', only one of the specified end-positions will have a finite cumulative cost.) traceback : ndarray Same shape as the `costs` array; this array contains the offset to any given index from its predecessor index. The offset indices index into the `offsets` attribute, which is a array of n-d offsets. In the 2-d case, if offsets[traceback[x, y]] is (-1, -1), that means that the predecessor of [x, y] in the minimum cost path to some start position is [x+1, y+1]. Note that if the offset_index is -1, then the given index was not considered. """ # basic variables to use for end-finding; also fix up the start and end # lists cdef BOOL_T use_ends = 0 cdef INDEX_T num_ends cdef BOOL_T all_ends = find_all_ends cdef cnp.ndarray[INDEX_T, ndim=1] flat_ends starts = _normalize_indices(starts, self.costs_shape) if starts is None: raise ValueError('start points must all be within the costs array') if ends is not None: ends = _normalize_indices(ends, self.costs_shape) if ends is None: raise ValueError('end points must all be within ' 'the costs array') use_ends = 1 num_ends = len(ends) flat_ends = np.array(_ravel_index_fortran( ends, self.costs_shape), dtype=INDEX_D) if self.dirty: self._reset() # lookup and array-ify object attributes for fast use cdef heap.FastUpdateBinaryHeap costs_heap = self.costs_heap cdef cnp.ndarray[FLOAT_T, ndim=1] flat_costs = self.flat_costs cdef cnp.ndarray[FLOAT_T, ndim=1] flat_cumulative_costs = \ self.flat_cumulative_costs cdef cnp.ndarray[OFFSETS_INDEX_T, ndim=1] traceback_offsets = \ self.traceback_offsets cdef cnp.ndarray[EDGE_T, ndim=2] flat_pos_edge_map = \ self.flat_pos_edge_map cdef cnp.ndarray[EDGE_T, ndim=2] flat_neg_edge_map = \ self.flat_neg_edge_map cdef cnp.ndarray[OFFSET_T, ndim=2] offsets = self.offsets cdef cnp.ndarray[INDEX_T, ndim=1] flat_offsets = self.flat_offsets cdef cnp.ndarray[FLOAT_T, ndim=1] offset_lengths = self.offset_lengths cdef DIM_T dim = self.dim cdef int num_offsets = len(flat_offsets) # push each start point into the heap. Note that we use flat indexing! for start in _ravel_index_fortran(starts, self.costs_shape): if self.use_start_cost: costs_heap.push_fast(flat_costs[start], start) else: costs_heap.push_fast(0, start) cdef FLOAT_T cost, new_cost cdef INDEX_T index, new_index cdef BOOL_T is_at_edge, use_offset cdef INDEX_T d, i cdef OFFSET_T offset cdef EDGE_T pos_edge_val, neg_edge_val cdef int num_ends_found = 0 cdef FLOAT_T inf = np.inf cdef FLOAT_T travel_cost while 1: # Find the point with the minimum cost in the heap. Once # popped, this point's minimum cost path has been found. if costs_heap.count == 0: # nothing in the heap: we've found paths to every # point in the array break cost = costs_heap.pop_fast() index = costs_heap._popped_ref # Record the cost we found to this point flat_cumulative_costs[index] = cost if use_ends: # If we're only tracing out a path to one or more # endpoints, check to see if this is an endpoint, and # if so, if we're done pathfinding. for i in range(num_ends): if index == flat_ends[i]: num_ends_found += 1 break if (num_ends_found and not all_ends) or \ num_ends_found == num_ends: # if we've found one or all of the end points (as # requested), stop searching break # Look into the edge map to see if this point is at an # edge along any axis is_at_edge = 0 for d in range(dim): if (flat_pos_edge_map[d, index] != 0 or flat_neg_edge_map[d, index] != 0): is_at_edge = 1 break # Now examine the points neighboring the given point for i in range(num_offsets): # First, if we're at some edge, scrutinize the offset # to ensure that it won't put us out-of-bounds. If, # for example, the edge_map at (x, y) is (-1, 0) -- # though of course we use flat indexing below -- that # means that (x, y) is along the lower edge of the # array; thus offsets with -1 or more negative in the # x-dimension should not be used! use_offset = 1 if is_at_edge: for d in range(dim): offset = offsets[i, d] pos_edge_val = flat_pos_edge_map[d, index] neg_edge_val = flat_neg_edge_map[d, index] if (pos_edge_val > 0 and offset >= pos_edge_val) or \ (neg_edge_val < 0 and offset <= neg_edge_val): # the offset puts us out of bounds... use_offset = 0 break # If not at an edge, or the specific offset doesn't # push over the edge, then we go on. if not use_offset: continue # using the flat offsets, calculate the new flat index new_index = index + flat_offsets[i] # If we have already found the best path here then # ignore this point if flat_cumulative_costs[new_index] != inf: continue # If the cost at this point is negative or infinite, ignore it new_cost = flat_costs[new_index] if new_cost < 0 or new_cost == inf: continue # Now we ask the heap to append or update the cost to # this new point, but only if that point isn't already # in the heap, or it is but the new cost is lower. travel_cost = self._travel_cost(flat_costs[index], new_cost, offset_lengths[i]) # don't push infs into the heap though! new_cost = cost + travel_cost if new_cost != inf: costs_heap.push_if_lower_fast(new_cost, new_index) # If we did perform an append or update, we should # record the offset from the predecessor to this new # point if costs_heap._pushed: traceback_offsets[new_index] = i # Un-flatten the costs and traceback arrays for human consumption. cumulative_costs = flat_cumulative_costs.reshape(self.costs_shape, order='F') traceback = traceback_offsets.reshape(self.costs_shape, order='F') self.dirty = 1 return cumulative_costs, traceback def traceback(self, end): """traceback(end) Trace a minimum cost path through the pre-calculated traceback array. This convenience function reconstructs the the minimum cost path to a given end position from one of the starting indices provided to find_costs(), which must have been called previously. This function can be called as many times as desired after find_costs() has been run. Parameters ---------- end : iterable An n-d index into the `costs` array. Returns ------- traceback : list of n-d tuples A list of indices into the `costs` array, starting with one of the start positions passed to find_costs(), and ending with the given `end` index. These indices specify the minimum-cost path from any given start index to the `end` index. (The total cost of that path can be read out from the `cumulative_costs` array returned by find_costs().) """ if not self.dirty: raise Exception('find_costs() must be run before traceback()') ends = _normalize_indices([end], self.costs_shape) if ends is None: raise ValueError('the specified end point must be ' 'within the costs array') traceback = [tuple(ends[0])] cdef INDEX_T flat_position =\ _ravel_index_fortran(ends, self.costs_shape)[0] if self.flat_cumulative_costs[flat_position] == np.inf: raise ValueError('no minimum-cost path was found ' 'to the specified end point') cdef cnp.ndarray[INDEX_T, ndim=1] position = \ np.array(ends[0], dtype=INDEX_D) cdef cnp.ndarray[OFFSETS_INDEX_T, ndim=1] traceback_offsets = \ self.traceback_offsets cdef cnp.ndarray[OFFSET_T, ndim=2] offsets = self.offsets cdef cnp.ndarray[INDEX_T, ndim=1] flat_offsets = self.flat_offsets cdef OFFSETS_INDEX_T offset cdef DIM_T d cdef DIM_T dim = self.dim while 1: offset = traceback_offsets[flat_position] if offset == -1: # At a point where we can go no further: probably a start point break flat_position -= flat_offsets[offset] for d in range(dim): position[d] -= offsets[offset, d] traceback.append(tuple(position)) return _reverse(traceback) @cython.boundscheck(False) @cython.wraparound(False) cdef class MCP_Geometric(MCP): """MCP_Geometric(costs, offsets=None, fully_connected=True) Find distance-weighted minimum cost paths through an n-d costs array. See the documentation for MCP for full details. This class differs from MCP in that the cost of a path is not simply the sum of the costs along that path. This class instead assumes that the costs array contains at each position the "cost" of a unit distance of travel through that position. For example, a move (in 2-d) from (1, 1) to (1, 2) is assumed to originate in the center of the pixel (1, 1) and terminate in the center of (1, 2). The entire move is of distance 1, half through (1, 1) and half through (1, 2); thus the cost of that move is `(1/2)*costs[1,1] + (1/2)*costs[1,2]`. On the other hand, a move from (1, 1) to (2, 2) is along the diagonal and is sqrt(2) in length. Half of this move is within the pixel (1, 1) and the other half in (2, 2), so the cost of this move is calculated as `(sqrt(2)/2)*costs[1,1] + (sqrt(2)/2)*costs[2,2]`. These calculations don't make a lot of sense with offsets of magnitude greater than 1. """ def __init__(self, costs, offsets=None, fully_connected=True): """__init__(costs, offsets=None, fully_connected=True) See class documentation. """ MCP.__init__(self, costs, offsets, fully_connected) if np.absolute(self.offsets).max() > 1: raise ValueError('all offset components must be 0, 1, or -1') self.use_start_cost = 0 cdef FLOAT_T _travel_cost(self, FLOAT_T old_cost, FLOAT_T new_cost, FLOAT_T offset_length): return offset_length * 0.5 * (old_cost + new_cost) scikit-image-0.9.3/skimage/graph/_spath.pyx000066400000000000000000000020601223313777300206400ustar00rootroot00000000000000# -*- python -*- import _mcp cimport _mcp from libc.math cimport fabs cdef class MCP_Diff(_mcp.MCP): """MCP_Diff(costs, offsets=None, fully_connected=True) Find minimum-difference paths through an n-d costs array. See the documentation for MCP for full details. This class differs from MCP in that the cost of a path is not simply the sum of the costs along that path. This class instead assumes that the cost of moving from one point to another is the absolute value of the difference in the costs between the two points. """ def __init__(self, costs, offsets=None, fully_connected=True): """__init__(costs, offsets=None, fully_connected=True) See class documentation. """ _mcp.MCP.__init__(self, costs, offsets, fully_connected) self.use_start_cost = 0 cdef _mcp.FLOAT_T _travel_cost(self, _mcp.FLOAT_T old_cost, _mcp.FLOAT_T new_cost, _mcp.FLOAT_T offset_length): return fabs(old_cost - new_cost) scikit-image-0.9.3/skimage/graph/heap.pxd000066400000000000000000000023511223313777300202550ustar00rootroot00000000000000""" This is the definition file for heap.pyx. It contains the definitions of the heap classes, such that other cython modules can "cimport heap" and thus use the C versions of pop(), push(), and value_of(): pop_fast(), push_fast() and value_of_fast() """ # determine datatypes for heap ctypedef double VALUE_T ctypedef Py_ssize_t REFERENCE_T ctypedef REFERENCE_T INDEX_T ctypedef unsigned char BOOL_T ctypedef unsigned char LEVELS_T cdef class BinaryHeap: cdef readonly INDEX_T count cdef readonly LEVELS_T levels, min_levels cdef VALUE_T *_values cdef REFERENCE_T *_references cdef REFERENCE_T _popped_ref cdef void _add_or_remove_level(self, LEVELS_T add_or_remove) cdef void _update(self) cdef void _update_one(self, INDEX_T i) cdef void _remove(self, INDEX_T i) cdef INDEX_T push_fast(self, VALUE_T value, REFERENCE_T reference) cdef VALUE_T pop_fast(self) cdef class FastUpdateBinaryHeap(BinaryHeap): cdef readonly REFERENCE_T max_reference cdef INDEX_T *_crossref cdef BOOL_T _invalid_ref cdef BOOL_T _pushed cdef VALUE_T value_of_fast(self, REFERENCE_T reference) cdef INDEX_T push_if_lower_fast(self, VALUE_T value, REFERENCE_T reference) scikit-image-0.9.3/skimage/graph/heap.pyx000066400000000000000000000575411223313777300203150ustar00rootroot00000000000000# -*- python -*- """Cython implementation of a binary min heap. Original author: Almar Klein Modified by: Zachary Pincus License: BSD Copyright 2009 Almar Klein Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ from __future__ import division # cython specific imports import cython from libc.stdlib cimport malloc, free cdef extern from "pyport.h": double Py_HUGE_VAL cdef VALUE_T inf = Py_HUGE_VAL # this is handy cdef inline INDEX_T index_min(INDEX_T a, INDEX_T b): return a if a <= b else b cdef class BinaryHeap: """BinaryHeap(initial_capacity=128) A binary heap class that can store values and an integer reference. A binary heap is an object to store values in, optimized in such a way that the minimum (or maximum, but a minimum in this implementation) value can be found in O(log2(N)) time. In this implementation, a reference value (a single integer) can also be stored with each value. Use the methods push() and pop() to put in or extract values. In C, use the corresponding push_fast() and pop_fast(). Parameters ---------- initial_capacity : int Estimate of the size of the heap, if known in advance. (In any case, the heap will dynamically grow and shrink as required, though never below the `initial_capacity`.) Attributes ---------- count : int The number of values in the heap levels : int The number of levels in the binary heap (see Notes below). The values are stored in the last level, so 2**levels is the capacity of the heap before another resize is required. min_levels : int The minimum number of levels in the heap (relates to the `initial_capacity` parameter.) Notes ----- This implementation stores the binary heap in an array twice as long as the number of elements in the heap. The array is structured in levels, starting at level 0 with a single value, doubling the amount of values in each level. The final level contains the actual values, the level before it contains the pairwise minimum values. The level before that contains the pairwise minimum values of that level, etc. Take a look at this illustration: level: 0 11 2222 33333333 4444444444444444 index: 0 12 3456 78901234 5678901234567890 1 2 3 The actual values are stored in level 4. The minimum value of position 15 and 16 is stored in position 7. min(17,18)->8, min(7,8)->3, min(3,4)->1. When adding a value, only the path to the top has to be updated, which takesO(log2(N)) time. The advantage of this implementation relative to more common implementations that swap values when pushing to the array is that data only needs to be swapped once when an element is removed. This means that keeping an array of references along with the values is very inexpensive. Th disadvantage is that if you pop the minimum value, the tree has to be traced from top to bottom and back. So if you only want values and no references, this implementation will probably be slower. If you need references (and maybe cross references to be kept up to date) this implementation will be faster. """ ## Basic methods # The following lines are always "inlined", but documented here for # clarity: # # To calculate the start index of a certain level: # 2**l-1 # LevelStart # Note that in inner loops, this may also be represented as (1<malloc( 2*number * sizeof(VALUE_T)) self._references = malloc(number * sizeof(REFERENCE_T)) def __init__(self, INDEX_T initial_capacity=128): """__init__(initial_capacity=128) Class constructor. Takes an optional parameter 'initial_capacity' so that if the required heap capacity is known or can be estimated in advance, there will need to be fewer resize operations on the heap.""" if self._values is NULL or self._references is NULL: raise MemoryError() self.reset() def reset(self): """reset() Reset the heap to default, empty state. """ cdef INDEX_T number = 2**self.levels cdef INDEX_T i cdef VALUE_T *values = self._values for i in range(number*2): values[i] = inf def __dealloc__(self): if self._values is not NULL: free(self._values) if self._references is not NULL: free(self._references) def __str__(self): s = '' for level in range(1,self.levels+1): i0 = 2**level-1 # LevelStart s+= 'level %i: ' % level for i in range(i0,i0+2**level): s += '%g, ' % self._values[i] s = s[:-1] + '\n' return s ## C Maintanance methods cdef void _add_or_remove_level(self, LEVELS_T add_or_remove): # init indexing ints cdef INDEX_T i, i1, i2, n # new amount of levels cdef LEVELS_T new_levels = self.levels + add_or_remove # allocate new arrays cdef INDEX_T number = 2**new_levels cdef VALUE_T *values cdef REFERENCE_T *references values = malloc(number*2 * sizeof(VALUE_T)) references = malloc(number * sizeof(REFERENCE_T)) # init arrays for i in range(number*2): values[i] = inf for i in range(number): references[i] = -1 # copy data cdef VALUE_T *old_values = self._values cdef REFERENCE_T *old_references = self._references if self.count: i1 = 2**new_levels-1 # LevelStart i2 = 2**self.levels-1 # LevelStart n = index_min(2**new_levels, 2**self.levels) for i in range(n): values[i1+i] = old_values[i2+i] for i in range(n): references[i] = old_references[i] # make current free(self._values) free(self._references) self._values = values self._references = references # we need a full update self.levels = new_levels self._update() cdef void _update(self): """Update the full tree from the bottom up. This should be done after resizing. """ # shorter name for values cdef VALUE_T *values = self._values # Note that i represents an absolute index here cdef INDEX_T i0, i, ii, n cdef LEVELS_T level # track tree for level in range(self.levels,1,-1): i0 = (1 << level) - 1 #2**level-1 = LevelStart n = i0 + 1 #2**level for i in range(i0,i0+n,2): ii = (i-1)//2 # CalcPrevAbs if values[i] < values[i+1]: values[ii] = values[i] else: values[ii] = values[i+1] cdef void _update_one(self, INDEX_T i): """Update the tree for one value.""" # shorter name for values cdef VALUE_T *values = self._values # make index uneven if i % 2==0: i = i-1 # track tree cdef INDEX_T ii cdef LEVELS_T level for level in range(self.levels,1,-1): ii = (i-1)//2 # CalcPrevAbs # test if values[i] < values[i+1]: values[ii] = values[i] else: values[ii] = values[i+1] # next if ii % 2: i = ii else: i = ii-1 cdef void _remove(self, INDEX_T i1): """Remove a value from the heap. By index.""" cdef LEVELS_T levels = self.levels cdef INDEX_T count = self.count # get indices cdef INDEX_T i0 = (1 << levels) - 1 #2**self.levels - 1 # LevelStart cdef INDEX_T i2 = i0 + count - 1 # get relative indices cdef INDEX_T r1 = i1 - i0 cdef INDEX_T r2 = count - 1 cdef VALUE_T *values = self._values cdef REFERENCE_T *references = self._references # swap with last values[i1] = values[i2] references[r1] = references[r2] # make last Null values[i2] = inf # update self.count -= 1 count -= 1 if (levels>self.min_levels) & (count < (1 << (levels-2))): self._add_or_remove_level(-1) else: self._update_one(i1) self._update_one(i2) ## C Public methods cdef INDEX_T push_fast(self, VALUE_T value, REFERENCE_T reference): """The c-method for fast pushing. Returns the index relative to the start of the last level in the heap.""" # We need to resize if currently it just fits. cdef LEVELS_T levels = self.levels cdef INDEX_T count = self.count if count >= (1 << levels):#2**self.levels: self._add_or_remove_level(+1) levels += 1 # insert new value cdef INDEX_T i = ((1 << levels) - 1) + count # LevelStart + n self._values[i] = value self._references[count] = reference # update self.count += 1 self._update_one(i) # return return count cdef VALUE_T pop_fast(self): """The c-method for fast popping. Returns the minimum value. The reference is put in self._popped_ref""" # shorter name for values cdef VALUE_T *values = self._values # init index. start at 1 because we start in level 1 cdef LEVELS_T level cdef INDEX_T i = 1 cdef LEVELS_T levels = self.levels # search tree (using absolute indices) for level in range(1, levels): if values[i] <= values[i+1]: i = i*2+1 # CalcNextAbs else: i = (i+1)*2+1 # CalcNextAbs # select best one in last level if values[i] <= values[i+1]: i = i else: i = i+1 # get values cdef INDEX_T ir = i - ((1 << levels) - 1) #(2**self.levels-1) # LevelStart cdef VALUE_T value = values[i] self._popped_ref = self._references[ir] # remove it if self.count: self._remove(i) # return return value ## Python Public methods (that do not need to be VERY fast) def push(self, VALUE_T value, REFERENCE_T reference=-1): """push(value, reference=-1) Append a value to the heap, with optional reference. Parameters ---------- value : float Value to push onto the heap reference : int, optional Reference to associate with the given value. """ self.push_fast(value, reference) def min_val(self): """min_val() Get the minimum value on the heap. Returns only the value, and does not remove it from the heap. """ # shorter name for values cdef VALUE_T *values = self._values # select best one in last level if values[1] < values[2]: return values[1] else: return values[2] def values(self): """values() Get the values in the heap as a list. """ out = [] cdef INDEX_T i, i0 i0 = 2**self.levels-1 # LevelStart for i in range(self.count): out.append(self._values[i0+i]) return out def references(self): """references() Get the references in the heap as a list. """ out = [] cdef INDEX_T i for i in range(self.count): out.append(self._references[i]) return out def pop(self): """pop() Get the minimum value and remove it from the list. Returns ------- value : float reference : int If no reference was provided, -1 is returned here. Raises ------ IndexError On attempt to pop from an empty heap """ if self.count == 0: raise IndexError('pop from an empty heap') value = self.pop_fast() ref = self._popped_ref return value, ref cdef class FastUpdateBinaryHeap(BinaryHeap): """FastUpdateBinaryHeap(initial_capacity=128, max_reference=None) Binary heap that allows the value of a reference to be updated quickly. This heap class keeps cross-references so that the value associated with a given reference can be quickly queried (O(1) time) or updated (O(log2(N)) time). This is ideal for pathfinding algorithms that implement some variant of Dijkstra's algorithm. Parameters ---------- initial_capacity : int Estimate of the size of the heap, if known in advance. (In any case, the heap will dynamically grow and shrink as required, though never below the `initial_capacity`.) max_reference : int, optional Largest reference value that might be pushed to the heap. (Pushing a larger value will result in an error.) If no value is provided, `1-initial_capacity` will be used. For the cross-reference index to work, all references must be in the range [0, max_reference]; references pushed outside of that range will not be added to the heap. The cross-references are kept as a 1-d array of length `max_reference+1', so memory use of this heap is effectively O(max_reference) Attributes ---------- count : int The number of values in the heap levels : int The number of levels in the binary heap (see Notes below). The values are stored in the last level, so 2**levels is the capacity of the heap before another resize is required. min_levels : int The minimum number of levels in the heap (relates to the `initial_capacity` parameter.) max_reference : int The provided or calculated maximum allowed reference value. Notes ----- The cross-references map data[reference]->internalindex, such that the value corresponding to a given reference can be found efficiently. This can be queried with the value_of() method. A special method, push_if_lower() is provided that will update the heap if the given reference is not in the heap, or if it is and the provided value is lower than the current value in the heap. This is again useful for pathfinding algorithms. """ def __cinit__(self, INDEX_T initial_capacity=128, max_reference=None): if max_reference is None: max_reference = initial_capacity - 1 self.max_reference = max_reference self._crossref = malloc((self.max_reference+1) * \ sizeof(INDEX_T)) def __init__(self, INDEX_T initial_capacity=128, max_reference=None): """__init__(initial_capacity=128, max_reference=None) Class constructor. """ # below will call self.reset BinaryHeap.__init__(self, initial_capacity) def __dealloc__(self): if self._crossref is not NULL: free(self._crossref) def reset(self): """reset() Reset the heap to default, empty state. """ BinaryHeap.reset(self) # set default values of crossrefs cdef INDEX_T i for i in range(self.max_reference+1): self._crossref[i] = -1 cdef void _remove(self, INDEX_T i1): """ Remove a value from the heap. By index. """ cdef LEVELS_T levels = self.levels cdef INDEX_T count = self.count # get indices cdef INDEX_T i0 = (1 << levels) - 1 #2**self.levels - 1 # LevelStart cdef INDEX_T i2 = i0 + count - 1 # get relative indices cdef INDEX_T r1 = i1 - i0 cdef INDEX_T r2 = count - 1 cdef VALUE_T *values = self._values cdef REFERENCE_T *references = self._references cdef INDEX_T *crossref = self._crossref # update cross reference crossref[references[r2]]=r1 crossref[references[r1]]=-1 # disable removed item # swap with last values[i1] = values[i2] references[r1] = references[r2] # make last Null values[i2] = inf # update self.count -= 1 count -= 1 if (levels > self.min_levels) & (count < (1 << (levels-2))): self._add_or_remove_level(-1) else: self._update_one(i1) self._update_one(i2) cdef INDEX_T push_fast(self, VALUE_T value, REFERENCE_T reference): """The c method for fast pushing. If the reference is already present, will update its value, otherwise will append it. If -1 is returned, the provided reference was out-of-bounds and no value was pushed to the heap.""" if not (0 <= reference <= self.max_reference): return -1 # init variable to store the index-in-the-heap cdef INDEX_T i # Reference is the index in the array where MCP is applied to. # Find the index-in-the-heap using the crossref array. cdef INDEX_T ir = self._crossref[reference] if ir != -1: # update i = (1 << self.levels) - 1 + ir self._values[i] = value self._update_one(i) return ir # if not updated: append normally and store reference ir = BinaryHeap.push_fast(self, value, reference) self._crossref[reference] = ir return ir cdef INDEX_T push_if_lower_fast(self, VALUE_T value, REFERENCE_T reference): """If the reference is already present, will update its value ONLY if the new value is lower than the old one. If the reference is not present, this append it. If a value was appended, self._pushed is set to 1. If -1 is returned, the provided reference was out-of-bounds and no value was pushed to the heap. """ if not (0 <= reference <= self.max_reference): return -1 # init variable to store the index-in-the-heap cdef INDEX_T i # Reference is the index in the array where MCP is applied to. # Find the index-in-the-heap using the crossref array. cdef INDEX_T ir = self._crossref[reference] cdef VALUE_T *values = self._values self._pushed = 1 if ir != -1: # update i = (1 << self.levels) - 1 + ir if values[i] > value: values[i] = value self._update_one(i) else: self._pushed = 0 return ir # if not updated: append normally and store reference ir = BinaryHeap.push_fast(self, value, reference) self._crossref[reference] = ir return ir cdef VALUE_T value_of_fast(self, REFERENCE_T reference): """Return the value corresponding to the given reference. If inf is returned, the reference may be invalid: check the _invaild_ref field in this case.""" if not (0 <= reference <= self.max_reference): self.invalid_ref = 1 return inf # init variable to store the index-in-the-heap cdef INDEX_T i # Reference is the index in the array where MCP is applied to. # Find the index-in-the-heap using the crossref array. cdef INDEX_T ir = self._crossref[reference] self._invalid_ref = 0 if ir == -1: self._invalid_ref = 1 return inf i = (1 << self.levels) - 1 + ir return self._values[i] def push(self, double value, int reference): """push(value, reference) Append/update a value in the heap. Parameters ---------- value : float reference : int If the reference is already present in the array, the value for that reference will be updated, otherwise the (value, reference) pair will be added to the heap. Raises ------ ValueError On pushing a reference outside the range [0, max_reference]. """ if self.push_fast(value, reference) == -1: raise ValueError("reference outside of range [0, max_reference]") def push_if_lower(self, double value, int reference): """push_if_lower(value, reference) Append/update a value in the heap if the extant value is lower. If the reference is already in the heap, update only of the new value is lower than the current one. If the reference is not present, the value will always be pushed to the heap. Parameters ---------- value : float reference : int If the reference is already present in the array, the value for that reference will be updated, otherwise the (value, reference) pair will be added to the heap. Returns ------- pushed : bool True if an append/update occured, False if otherwise. Raises ------ ValueError On pushing a reference outside the range [0, max_reference]. """ if self.push_if_lower_fast(value, reference) == -1: raise ValueError("reference outside of range [0, max_reference]") return self._pushed == 1 def value_of(self, int reference): """value_of(reference) Get the value corresponding to a given reference. Parameters ---------- reference : int A reference already pushed to the heap. Returns ------- value : float Raises ------ ValueError On querying a reference outside the range [0, max_reference], or not already pushed to the heap. """ value = self.value_of_fast(reference) if self._invalid_ref: raise ValueError('invalid reference') return value def cross_references(self): """Get the cross references in the heap as a list.""" out = [] cdef INDEX_T i for i in range(self.max_reference+1): out.append( self._crossref[i] ) return out scikit-image-0.9.3/skimage/graph/mcp.py000066400000000000000000000061301223313777300177530ustar00rootroot00000000000000from ._mcp import MCP, MCP_Geometric def route_through_array(array, start, end, fully_connected=True, geometric=True): """Simple example of how to use the MCP and MCP_Geometric classes. See the MCP and MCP_Geometric class documentation for explanation of the path-finding algorithm. Parameters ---------- array : ndarray Array of costs. start : iterable n-d index into `array` defining the starting point end : iterable n-d index into `array` defining the end point fully_connected : bool (optional) If True, diagonal moves are permitted, if False, only axial moves. geometric : bool (optional) If True, the MCP_Geometric class is used to calculate costs, if False, the MCP base class is used. See the class documentation for an explanation of the differences between MCP and MCP_Geometric. Returns ------- path : list List of n-d index tuples defining the path from `start` to `end`. cost : float Cost of the path. If `geometric` is False, the cost of the path is the sum of the values of `array` along the path. If `geometric` is True, a finer computation is made (see the documentation of the MCP_Geometric class). See Also -------- MCP, MCP_Geometric Examples -------- >>> import numpy as np >>> from skimage.graph import route_through_array >>> >>> image = np.array([[1, 3], [10, 12]]) >>> image array([[ 1, 3], [10, 12]]) >>> # Forbid diagonal steps >>> route_through_array(image, [0, 0], [1, 1], fully_connected=False) ([(0, 0), (0, 1), (1, 1)], 9.5) >>> # Now allow diagonal steps: the path goes directly from start to end >>> route_through_array(image, [0, 0], [1, 1]) ([(0, 0), (1, 1)], 9.1923881554251192) >>> # Cost is the sum of array values along the path (16 = 1 + 3 + 12) >>> route_through_array(image, [0, 0], [1, 1], fully_connected=False, ... geometric=False) ([(0, 0), (0, 1), (1, 1)], 16.0) >>> # Larger array where we display the path that is selected >>> image = np.arange((36)).reshape((6, 6)) >>> image array([[ 0, 1, 2, 3, 4, 5], [ 6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23], [24, 25, 26, 27, 28, 29], [30, 31, 32, 33, 34, 35]]) >>> # Find the path with lowest cost >>> indices, weight = route_through_array(image, (0, 0), (5, 5)) >>> indices = np.array(indices).T >>> path = np.zeros_like(image) >>> path[indices[0], indices[1]] = 1 >>> path array([[1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1]]) """ start, end = tuple(start), tuple(end) if geometric: mcp_class = MCP_Geometric else: mcp_class = MCP m = mcp_class(array, fully_connected=fully_connected) costs, traceback_array = m.find_costs([start], [end]) return m.traceback(end), costs[end] scikit-image-0.9.3/skimage/graph/setup.py000066400000000000000000000026211223313777300203350ustar00rootroot00000000000000#!/usr/bin/env python from skimage._build import cython import os.path base_path = os.path.abspath(os.path.dirname(__file__)) def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs config = Configuration('graph', parent_package, top_path) config.add_data_dir('tests') # This function tries to create C files from the given .pyx files. If # it fails, try to build with pre-generated .c files. cython(['_spath.pyx'], working_path=base_path) cython(['_mcp.pyx'], working_path=base_path) cython(['heap.pyx'], working_path=base_path) config.add_extension('_spath', sources=['_spath.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_mcp', sources=['_mcp.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('heap', sources=['heap.c'], include_dirs=[get_numpy_include_dirs()]) return config if __name__ == '__main__': from numpy.distutils.core import setup setup(maintainer='scikit-image Developers', maintainer_email='scikit-image@googlegroups.com', description='Graph-based Image-processing Algorithms', url='https://github.com/scikit-image/scikit-image', license='Modified BSD', **(configuration(top_path='').todict()) ) scikit-image-0.9.3/skimage/graph/spath.py000066400000000000000000000065421223313777300203220ustar00rootroot00000000000000import numpy as np from . import _spath def shortest_path(arr, reach=1, axis=-1, output_indexlist=False): """Find the shortest path through an n-d array from one side to another. Parameters ---------- arr : ndarray of float64 reach : int, optional By default (``reach = 1``), the shortest path can only move one row up or down for every step it moves forward (i.e., the path gradient is limited to 1). `reach` defines the number of elements that can be skipped along each non-axis dimension at each step. axis : int, optional The axis along which the path must always move forward (default -1) output_indexlist: bool, optional See return value `p` for explanation. Returns ------- p : iterable of int For each step along `axis`, the coordinate of the shortest path. If `output_indexlist` is True, then the path is returned as a list of n-d tuples that index into `arr`. If False, then the path is returned as an array listing the coordinates of the path along the non-axis dimensions for each step along the axis dimension. That is, `p.shape == (arr.shape[axis], arr.ndim-1)` except that p is squeezed before returning so if `arr.ndim == 2`, then `p.shape == (arr.shape[axis],)` cost : float Cost of path. This is the absolute sum of all the differences along the path. """ # First: calculate the valid moves from any given position. Basically, # always move +1 along the given axis, and then can move anywhere within # a grid defined by the reach. if axis < 0: axis += arr.ndim offset_ind_shape = (2 * reach + 1,) * (arr.ndim - 1) offset_indices = np.indices(offset_ind_shape) - reach offset_indices = np.insert(offset_indices, axis, np.ones(offset_ind_shape), axis=0) offset_size = np.multiply.reduce(offset_ind_shape) offsets = np.reshape(offset_indices, (arr.ndim, offset_size), order='F').T # Valid starting positions are anywhere on the hyperplane defined by # position 0 on the given axis. Ending positions are anywhere on the # hyperplane at position -1 along the same. non_axis_shape = arr.shape[:axis] + arr.shape[axis + 1:] non_axis_indices = np.indices(non_axis_shape) non_axis_size = np.multiply.reduce(non_axis_shape) start_indices = np.insert(non_axis_indices, axis, np.zeros(non_axis_shape), axis=0) starts = np.reshape(start_indices, (arr.ndim, non_axis_size), order='F').T end_indices = np.insert(non_axis_indices, axis, -np.ones(non_axis_shape), axis=0) ends = np.reshape(end_indices, (arr.ndim, non_axis_size), order='F').T # Find the minimum-cost path to one of the end-points m = _spath.MCP_Diff(arr, offsets=offsets) costs, traceback = m.find_costs(starts, ends, find_all_ends=False) # Figure out which end-point was found for end in ends: cost = costs[tuple(end)] if cost != np.inf: break traceback = m.traceback(end) if not output_indexlist: traceback = np.array(traceback) traceback = np.concatenate([traceback[:, :axis], traceback[:, axis + 1:]], axis=1) traceback = np.squeeze(traceback) return traceback, cost scikit-image-0.9.3/skimage/graph/tests/000077500000000000000000000000001223313777300177645ustar00rootroot00000000000000scikit-image-0.9.3/skimage/graph/tests/test_heap.py000066400000000000000000000021361223313777300223140ustar00rootroot00000000000000import time import random import skimage.graph.heap as heap def test_heap(): _test_heap(100000, True) _test_heap(100000, False) def _test_heap(n, fast_update): # generate random numbers with duplicates random.seed(0) a = [random.uniform(1.0, 100.0) for i in range(n // 2)] a = a + a t0 = time.clock() # insert in heap with random removals if fast_update: h = heap.FastUpdateBinaryHeap(128, n) else: h = heap.BinaryHeap(128) for i in range(len(a)): h.push(a[i], i) if a[i] < 25: # double-push same ref sometimes to test fast update codepaths h.push(2 * a[i], i) if 25 < a[i] < 50: # pop some to test random removal h.pop() # pop from heap b = [] while True: try: b.append(h.pop()[0]) except IndexError: break t1 = time.clock() # verify for i in range(1, len(b)): assert(b[i] >= b[i - 1]) return t1 - t0 if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/graph/tests/test_mcp.py000066400000000000000000000126271223313777300221640ustar00rootroot00000000000000import numpy as np from numpy.testing import (assert_array_equal, assert_almost_equal, ) import skimage.graph.mcp as mcp a = np.ones((8, 8), dtype=np.float32) a[1:-1, 1] = 0 a[1, 1:-1] = 0 def test_basic(): m = mcp.MCP(a, fully_connected=True) costs, traceback = m.find_costs([(1, 6)]) return_path = m.traceback((7, 2)) assert_array_equal(costs, [[1., 1., 1., 1., 1., 1., 1., 1.], [1., 0., 0., 0., 0., 0., 0., 1.], [1., 0., 1., 1., 1., 1., 1., 1.], [1., 0., 1., 2., 2., 2., 2., 2.], [1., 0., 1., 2., 3., 3., 3., 3.], [1., 0., 1., 2., 3., 4., 4., 4.], [1., 0., 1., 2., 3., 4., 5., 5.], [1., 1., 1., 2., 3., 4., 5., 6.]]) assert_array_equal(return_path, [(1, 6), (1, 5), (1, 4), (1, 3), (1, 2), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 2)]) def test_neg_inf(): expected_costs = np.where(a == 1, np.inf, 0) expected_path = [(1, 6), (1, 5), (1, 4), (1, 3), (1, 2), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1)] test_neg = np.where(a == 1, -1, 0) test_inf = np.where(a == 1, np.inf, 0) m = mcp.MCP(test_neg, fully_connected=True) costs, traceback = m.find_costs([(1, 6)]) return_path = m.traceback((6, 1)) assert_array_equal(costs, expected_costs) assert_array_equal(return_path, expected_path) m = mcp.MCP(test_inf, fully_connected=True) costs, traceback = m.find_costs([(1, 6)]) return_path = m.traceback((6, 1)) assert_array_equal(costs, expected_costs) assert_array_equal(return_path, expected_path) def test_route(): return_path, cost = mcp.route_through_array(a, (1, 6), (7, 2), geometric=True) assert_almost_equal(cost, np.sqrt(2) / 2) assert_array_equal(return_path, [(1, 6), (1, 5), (1, 4), (1, 3), (1, 2), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 2)]) def test_no_diagonal(): m = mcp.MCP(a, fully_connected=False) costs, traceback = m.find_costs([(1, 6)]) return_path = m.traceback((7, 2)) assert_array_equal(costs, [[2., 1., 1., 1., 1., 1., 1., 2.], [1., 0., 0., 0., 0., 0., 0., 1.], [1., 0., 1., 1., 1., 1., 1., 2.], [1., 0., 1., 2., 2., 2., 2., 3.], [1., 0., 1., 2., 3., 3., 3., 4.], [1., 0., 1., 2., 3., 4., 4., 5.], [1., 0., 1., 2., 3., 4., 5., 6.], [2., 1., 2., 3., 4., 5., 6., 7.]]) assert_array_equal(return_path, [(1, 6), (1, 5), (1, 4), (1, 3), (1, 2), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (7, 2)]) def test_offsets(): offsets = [(1, i) for i in range(10)] + [(1, -i) for i in range(1, 10)] m = mcp.MCP(a, offsets=offsets) costs, traceback = m.find_costs([(1, 6)]) assert_array_equal(traceback, [[-1, -1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1, -1], [15, 14, 13, 12, 11, 10, 0, 1], [10, 0, 1, 2, 3, 4, 5, 6], [10, 0, 1, 2, 3, 4, 5, 6], [10, 0, 1, 2, 3, 4, 5, 6], [10, 0, 1, 2, 3, 4, 5, 6], [10, 0, 1, 2, 3, 4, 5, 6]]) def test_crashing(): for shape in [(100, 100), (5, 8, 13, 17)] * 5: yield _test_random, shape def _test_random(shape): # Just tests for crashing -- not for correctness. np.random.seed(0) a = np.random.random(shape).astype(np.float32) starts = [[0] * len(shape), [-1] * len(shape), (np.random.random(len(shape)) * shape).astype(int)] ends = [(np.random.random(len(shape)) * shape).astype(int) for i in range(4)] m = mcp.MCP(a, fully_connected=True) costs, offsets = m.find_costs(starts) for point in [(np.random.random(len(shape)) * shape).astype(int) for i in range(4)]: m.traceback(point) m._reset() m.find_costs(starts, ends) for end in ends: m.traceback(end) return a, costs, offsets if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/graph/tests/test_spath.py000066400000000000000000000016441223313777300225210ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_equal, assert_array_equal import skimage.graph.spath as spath def test_basic(): x = np.array([[1, 1, 3], [0, 2, 0], [4, 3, 1]]) path, cost = spath.shortest_path(x) assert_array_equal(path, [0, 0, 1]) assert_equal(cost, 1) def test_reach(): x = np.array([[1, 1, 3], [0, 2, 0], [4, 3, 1]]) path, cost = spath.shortest_path(x, reach=2) assert_array_equal(path, [0, 0, 2]) assert_equal(cost, 0) def test_non_square(): x = np.array([[1, 1, 1, 1, 5, 5, 5], [5, 0, 0, 5, 9, 1, 1], [0, 5, 1, 0, 5, 5, 0], [6, 1, 1, 5, 0, 0, 1]]) path, cost = spath.shortest_path(x, reach=2) assert_array_equal(path, [2, 1, 1, 2, 3, 3, 2]) assert_equal(cost, 0) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/io/000077500000000000000000000000001223313777300161305ustar00rootroot00000000000000scikit-image-0.9.3/skimage/io/__init__.py000066400000000000000000000043171223313777300202460ustar00rootroot00000000000000__doc__ = """Utilities to read and write images in various formats. The following plug-ins are available: """ from ._plugins import use as use_plugin from ._plugins import available as plugins from ._plugins import info as plugin_info from ._plugins import configuration as plugin_order from ._plugins import reset_plugins as _reset_plugins from .sift import * from .collection import * from ._io import * from .video import * available_plugins = plugins() def _load_preferred_plugins(): # Load preferred plugin for each io function. io_funcs = ['imsave', 'imshow', 'imread_collection', 'imread'] preferred_plugins = ['matplotlib', 'pil', 'qt', 'freeimage', 'null'] for func in io_funcs: for plugin in preferred_plugins: if plugin not in available_plugins: continue try: use_plugin(plugin, kind=func) break except (ImportError, RuntimeError, OSError): pass # Use PIL as the default imread plugin, since matplotlib (1.2.x) # is buggy (flips PNGs around, returns bytes as floats, etc.) try: use_plugin('pil', 'imread') except ImportError: pass def reset_plugins(): _reset_plugins() _load_preferred_plugins() def _update_doc(doc): """Add a list of plugins to the module docstring, formatted as a ReStructuredText table. """ from textwrap import wrap info = [(p, plugin_info(p)) for p in plugins() if not p == 'test'] col_1_len = max([len(n) for (n, _) in info]) wrap_len = 73 col_2_len = wrap_len - 1 - col_1_len # Insert table header info.insert(0, ('=' * col_1_len, {'description': '=' * col_2_len})) info.insert(1, ('Plugin', {'description': 'Description'})) info.insert(2, ('-' * col_1_len, {'description': '-' * col_2_len})) info.append(('=' * col_1_len, {'description': '=' * col_2_len})) for (name, meta_data) in info: wrapped_descr = wrap(meta_data.get('description', ''), col_2_len) doc += "%s %s\n" % (name.ljust(col_1_len), '\n'.join(wrapped_descr)) doc = doc.strip() return doc __doc__ = _update_doc(__doc__) reset_plugins() scikit-image-0.9.3/skimage/io/_io.py000066400000000000000000000144331223313777300172550ustar00rootroot00000000000000__all__ = ['Image', 'imread', 'imread_collection', 'imsave', 'imshow', 'show', 'push', 'pop'] try: from urllib.request import urlopen except ImportError: from urllib2 import urlopen import os import re import tempfile from io import BytesIO import numpy as np from skimage.io._plugins import call as call_plugin from skimage.color import rgb2grey from skimage._shared import six # Shared image queue _image_stack = [] URL_REGEX = re.compile(r'http://|https://|ftp://|file://|file:\\') def is_url(filename): """Return True if string is an http or ftp path.""" return (isinstance(filename, six.string_types) and URL_REGEX.match(filename) is not None) class Image(np.ndarray): """Class representing Image data. These objects have tags for image metadata and IPython display protocol methods for image display. Parameters ---------- arr : ndarray Image data. kwargs : Image tags as keywords Specified in the form ``tag0=value``, ``tag1=value``. Attributes ---------- tags : dict Meta-data. """ def __new__(cls, arr, **kwargs): """Set the image data and tags according to given parameters. """ x = np.asarray(arr).view(cls) x.tags = kwargs return x def __array_finalize__(self, obj): self.tags = getattr(obj, 'tags', {}) def _repr_png_(self): return self._repr_image_format('png') def _repr_jpeg_(self): return self._repr_image_format('jpeg') def _repr_image_format(self, format_str): str_buffer = BytesIO() imsave(str_buffer, self, format_str=format_str) return_str = str_buffer.getvalue() str_buffer.close() return return_str def push(img): """Push an image onto the shared image stack. Parameters ---------- img : ndarray Image to push. """ if not isinstance(img, np.ndarray): raise ValueError("Can only push ndarrays to the image stack.") _image_stack.append(img) def pop(): """Pop an image from the shared image stack. Returns ------- img : ndarray Image popped from the stack. """ return _image_stack.pop() def imread(fname, as_grey=False, plugin=None, flatten=None, **plugin_args): """Load an image from file. Parameters ---------- fname : string Image file name, e.g. ``test.jpg`` or URL. as_grey : bool If True, convert color images to grey-scale (32-bit floats). Images that are already in grey-scale format are not converted. plugin : str Name of plugin to use (Python Imaging Library by default). Other Parameters ---------------- flatten : bool Backward compatible keyword, superseded by `as_grey`. Returns ------- img_array : ndarray The different colour bands/channels are stored in the third dimension, such that a grey-image is MxN, an RGB-image MxNx3 and an RGBA-image MxNx4. Other parameters ---------------- plugin_args : keywords Passed to the given plugin. """ # Backward compatibility if flatten is not None: as_grey = flatten if is_url(fname): _, ext = os.path.splitext(fname) with tempfile.NamedTemporaryFile(delete=False, suffix=ext) as f: u = urlopen(fname) f.write(u.read()) img = call_plugin('imread', f.name, plugin=plugin, **plugin_args) os.remove(f.name) else: img = call_plugin('imread', fname, plugin=plugin, **plugin_args) if as_grey and getattr(img, 'ndim', 0) >= 3: img = rgb2grey(img) return img def imread_collection(load_pattern, conserve_memory=True, plugin=None, **plugin_args): """ Load a collection of images. Parameters ---------- load_pattern : str or list List of objects to load. These are usually filenames, but may vary depending on the currently active plugin. See the docstring for ``ImageCollection`` for the default behaviour of this parameter. conserve_memory : bool, optional If True, never keep more than one in memory at a specific time. Otherwise, images will be cached once they are loaded. Returns ------- ic : ImageCollection Collection of images. Other parameters ---------------- plugin_args : keywords Passed to the given plugin. """ return call_plugin('imread_collection', load_pattern, conserve_memory, plugin=plugin, **plugin_args) def imsave(fname, arr, plugin=None, **plugin_args): """Save an image to file. Parameters ---------- fname : str Target filename. arr : ndarray of shape (M,N) or (M,N,3) or (M,N,4) Image data. plugin : str Name of plugin to use. By default, the different plugins are tried (starting with the Python Imaging Library) until a suitable candidate is found. Other parameters ---------------- plugin_args : keywords Passed to the given plugin. """ return call_plugin('imsave', fname, arr, plugin=plugin, **plugin_args) def imshow(arr, plugin=None, **plugin_args): """Display an image. Parameters ---------- arr : ndarray or str Image data or name of image file. plugin : str Name of plugin to use. By default, the different plugins are tried (starting with the Python Imaging Library) until a suitable candidate is found. Other parameters ---------------- plugin_args : keywords Passed to the given plugin. """ if isinstance(arr, six.string_types): arr = call_plugin('imread', arr, plugin=plugin) return call_plugin('imshow', arr, plugin=plugin, **plugin_args) def show(): '''Display pending images. Launch the event loop of the current gui plugin, and display all pending images, queued via `imshow`. This is required when using `imshow` from non-interactive scripts. A call to `show` will block execution of code until all windows have been closed. Examples -------- >>> import skimage.io as io >>> for i in range(4): ... io.imshow(np.random.random((50, 50))) >>> io.show() ''' return call_plugin('_app_show') scikit-image-0.9.3/skimage/io/_plugins/000077500000000000000000000000001223313777300177505ustar00rootroot00000000000000scikit-image-0.9.3/skimage/io/_plugins/__init__.py000066400000000000000000000000261223313777300220570ustar00rootroot00000000000000from .plugin import * scikit-image-0.9.3/skimage/io/_plugins/_colormixer.pyx000066400000000000000000000307261223313777300230440ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False """Colour Mixer NumPy does not do overflow checking when adding or multiplying integers, so currently the only way to clip results efficiently (without making copies of the data) is with an extension such as this one. """ import cython cimport numpy as cnp from libc.math cimport exp, pow def add(cnp.ndarray[cnp.uint8_t, ndim=3] img, cnp.ndarray[cnp.uint8_t, ndim=3] stateimg, Py_ssize_t channel, Py_ssize_t amount): """Add a given amount to a colour channel of `stateimg`, and store the result in `img`. Overflow is clipped. Parameters ---------- img : (M, N, 3) ndarray of uint8 Output image. stateimg : (M, N, 3) ndarray of uint8 Input image. channel : int Channel (0 for "red", 1 for "green", 2 for "blue"). amount : int Value to add. """ cdef Py_ssize_t height = img.shape[0] cdef Py_ssize_t width = img.shape[1] cdef Py_ssize_t k = channel cdef Py_ssize_t n = amount cdef cnp.int16_t op_result cdef cnp.uint8_t lut[256] cdef Py_ssize_t i, j, l with nogil: for l from 0 <= l < 256: op_result = (l + n) if op_result > 255: op_result = 255 elif op_result < 0: op_result = 0 else: pass lut[l] = op_result for i from 0 <= i < height: for j from 0 <= j < width: img[i, j, k] = lut[stateimg[i,j,k]] def multiply(cnp.ndarray[cnp.uint8_t, ndim=3] img, cnp.ndarray[cnp.uint8_t, ndim=3] stateimg, Py_ssize_t channel, float amount): """Multiply a colour channel of `stateimg` by a certain amount, and store the result in `img`. Overflow is clipped. Parameters ---------- img : (M, N, 3) ndarray of uint8 Output image. stateimg : (M, N, 3) ndarray of uint8 Input image. channel : int Channel (0 for "red", 1 for "green", 2 for "blue"). amount : float Multiplication factor. """ cdef Py_ssize_t height = img.shape[0] cdef Py_ssize_t width = img.shape[1] cdef Py_ssize_t k = channel cdef float n = amount cdef float op_result cdef cnp.uint8_t lut[256] cdef Py_ssize_t i, j, l with nogil: for l from 0 <= l < 256: op_result = l * n if op_result > 255: op_result = 255 elif op_result < 0: op_result = 0 else: pass lut[l] = op_result for i from 0 <= i < height: for j from 0 <= j < width: img[i,j,k] = lut[stateimg[i,j,k]] def brightness(cnp.ndarray[cnp.uint8_t, ndim=3] img, cnp.ndarray[cnp.uint8_t, ndim=3] stateimg, float factor, Py_ssize_t offset): """Modify the brightness of an image. 'factor' is multiplied to all channels, which are then added by 'amount'. Overflow is clipped. Parameters ---------- img : (M, N, 3) ndarray of uint8 Output image. stateimg : (M, N, 3) ndarray of uint8 Input image. factor : float Multiplication factor. offset : int Ammount to add to each channel. """ cdef Py_ssize_t height = img.shape[0] cdef Py_ssize_t width = img.shape[1] cdef float op_result cdef cnp.uint8_t lut[256] cdef Py_ssize_t i, j, k with nogil: for k from 0 <= k < 256: op_result = k * factor + offset if op_result > 255: op_result = 255 elif op_result < 0: op_result = 0 else: pass lut[k] = op_result for i from 0 <= i < height: for j from 0 <= j < width: img[i,j,0] = lut[stateimg[i,j,0]] img[i,j,1] = lut[stateimg[i,j,1]] img[i,j,2] = lut[stateimg[i,j,2]] def sigmoid_gamma(cnp.ndarray[cnp.uint8_t, ndim=3] img, cnp.ndarray[cnp.uint8_t, ndim=3] stateimg, float alpha, float beta): cdef Py_ssize_t height = img.shape[0] cdef Py_ssize_t width = img.shape[1] cdef Py_ssize_t i, j, k cdef float c1 = 1 / (1 + exp(beta)) cdef float c2 = 1 / (1 + exp(beta - alpha)) - c1 cdef cnp.uint8_t lut[256] with nogil: # compute the lut for k from 0 <= k < 256: lut[k] = (((1 / (1 + exp(beta - (k / 255.) * alpha))) - c1) * 255 / c2) for i from 0 <= i < height: for j from 0 <= j < width: img[i,j,0] = lut[stateimg[i,j,0]] img[i,j,1] = lut[stateimg[i,j,1]] img[i,j,2] = lut[stateimg[i,j,2]] def gamma(cnp.ndarray[cnp.uint8_t, ndim=3] img, cnp.ndarray[cnp.uint8_t, ndim=3] stateimg, float gamma): cdef Py_ssize_t height = img.shape[0] cdef Py_ssize_t width = img.shape[1] cdef cnp.uint8_t lut[256] cdef Py_ssize_t i, j, k if gamma == 0: gamma = 0.00000000000000000001 gamma = 1./gamma with nogil: # compute the lut for k from 0 <= k < 256: lut[k] = ((pow((k / 255.), gamma) * 255)) for i from 0 <= i < height: for j from 0 <= j < width: img[i,j,0] = lut[stateimg[i,j,0]] img[i,j,1] = lut[stateimg[i,j,1]] img[i,j,2] = lut[stateimg[i,j,2]] cdef void rgb_2_hsv(float* RGB, float* HSV) nogil: cdef float R, G, B, H, S, V, MAX, MIN R = RGB[0] G = RGB[1] B = RGB[2] if R > 255: R = 255 elif R < 0: R = 0 else: pass if G > 255: G = 255 elif G < 0: G = 0 else: pass if B > 255: B = 255 elif B < 0: B = 0 else: pass if R < G: MIN = R MAX = G else: MIN = G MAX = R if B < MIN: MIN = B elif B > MAX: MAX = B else: pass V = MAX / 255. if MAX == MIN: H = 0. elif MAX == R: H = (60 * (G - B) / (MAX - MIN) + 360) % 360 elif MAX == G: H = 60 * (B - R) / (MAX - MIN) + 120 else: H = 60 * (R - G) / (MAX - MIN) + 240 if MAX == 0: S = 0 else: S = 1 - MIN / MAX HSV[0] = H HSV[1] = S HSV[2] = V cdef void hsv_2_rgb(float* HSV, float* RGB) nogil: cdef float H, S, V cdef float f, p, q, t, r, g, b cdef Py_ssize_t hi H = HSV[0] S = HSV[1] V = HSV[2] if H > 360: H = H % 360 elif H < 0: H = 360 - ((-1 * H) % 360) else: pass if S > 1: S = 1 elif S < 0: S = 0 else: pass if V > 1: V = 1 elif V < 0: V = 0 else: pass hi = ((H / 60.)) % 6 f = (H / 60.) - ((H / 60.)) p = V * (1 - S) q = V * (1 - f * S) t = V * (1 - (1 -f) * S) if hi == 0: r = V g = t b = p elif hi == 1: r = q g = V b = p elif hi == 2: r = p g = V b = t elif hi == 3: r = p g = q b = V elif hi == 4: r = t g = p b = V else: r = V g = p b = q RGB[0] = r RGB[1] = g RGB[2] = b def py_hsv_2_rgb(H, S, V): '''Convert an HSV value to RGB. Automatic clipping. Parameters ---------- H : float From 0. - 360. S : float From 0. - 1. V : float From 0. - 1. Returns ------- out : (R, G, B) ints Each from 0 - 255 conversion convention from here: http://en.wikipedia.org/wiki/HSL_and_HSV ''' cdef float HSV[3] cdef float RGB[3] HSV[0] = H HSV[1] = S HSV[2] = V hsv_2_rgb(HSV, RGB) R = int(RGB[0] * 255) G = int(RGB[1] * 255) B = int(RGB[2] * 255) return (R, G, B) def py_rgb_2_hsv(R, G, B): '''Convert an HSV value to RGB. Automatic clipping. Parameters ---------- R : int From 0. - 255. G : int From 0. - 255. B : int From 0. - 255. Returns ------- out : (H, S, V) floats Ranges (0...360), (0...1), (0...1) conversion convention from here: http://en.wikipedia.org/wiki/HSL_and_HSV ''' cdef float HSV[3] cdef float RGB[3] RGB[0] = R RGB[1] = G RGB[2] = B rgb_2_hsv(RGB, HSV) H = HSV[0] S = HSV[1] V = HSV[2] return (H, S, V) def hsv_add(cnp.ndarray[cnp.uint8_t, ndim=3] img, cnp.ndarray[cnp.uint8_t, ndim=3] stateimg, float h_amt, float s_amt, float v_amt): """Modify the image color by specifying additive HSV Values. Since the underlying images are RGB, all three values HSV must be specified at the same time. The RGB triplet in the image is converted to HSV, the operation is applied, and then the HSV triplet is converted back to RGB HSV values are scaled to H(0. - 360.), S(0. - 1.), V(0. - 1.) then the operation is performed and any overflow is clipped, then the reverse transform is performed. Those are the ranges to keep in mind, when passing in values. Parameters ---------- img : (M, N, 3) ndarray of uint8 Output image. stateimg : (M, N, 3) ndarray of uint8 Input image. h_amt : float Ammount to add to H channel. s_amt : float Ammount to add to S channel. v_amt : float Ammount to add to V channel. """ cdef Py_ssize_t height = img.shape[0] cdef Py_ssize_t width = img.shape[1] cdef float HSV[3] cdef float RGB[3] cdef Py_ssize_t i, j with nogil: for i from 0 <= i < height: for j from 0 <= j < width: RGB[0] = stateimg[i, j, 0] RGB[1] = stateimg[i, j, 1] RGB[2] = stateimg[i, j, 2] rgb_2_hsv(RGB, HSV) # Add operation HSV[0] += h_amt HSV[1] += s_amt HSV[2] += v_amt hsv_2_rgb(HSV, RGB) RGB[0] *= 255 RGB[1] *= 255 RGB[2] *= 255 img[i, j, 0] = RGB[0] img[i, j, 1] = RGB[1] img[i, j, 2] = RGB[2] def hsv_multiply(cnp.ndarray[cnp.uint8_t, ndim=3] img, cnp.ndarray[cnp.uint8_t, ndim=3] stateimg, float h_amt, float s_amt, float v_amt): """Modify the image color by specifying multiplicative HSV Values. Since the underlying images are RGB, all three values HSV must be specified at the same time. The RGB triplet in the image is converted to HSV, the operation is applied, and then the HSV triplet is converted back to RGB HSV values are scaled to H(0. - 360.), S(0. - 1.), V(0. - 1.) then the operation is performed and any overflow is clipped, then the reverse transform is performed. Those are the ranges to keep in mind, when passing in values. Note that since hue is in degrees, it makes no sense to multiply that channel, thus an add operation is performed on the hue. And the values given for h_amt, should be the same as for hsv_add Parameters ---------- img : (M, N, 3) ndarray of uint8 Output image. stateimg : (M, N, 3) ndarray of uint8 Input image. h_amt : float Ammount to add to H channel. s_amt : float Ammount by which to multiply S channel. v_amt : float Ammount by which to multiply V channel. """ cdef Py_ssize_t height = img.shape[0] cdef Py_ssize_t width = img.shape[1] cdef float HSV[3] cdef float RGB[3] cdef Py_ssize_t i, j with nogil: for i from 0 <= i < height: for j from 0 <= j < width: RGB[0] = stateimg[i, j, 0] RGB[1] = stateimg[i, j, 1] RGB[2] = stateimg[i, j, 2] rgb_2_hsv(RGB, HSV) # Multiply operation HSV[0] += h_amt HSV[1] *= s_amt HSV[2] *= v_amt hsv_2_rgb(HSV, RGB) RGB[0] *= 255 RGB[1] *= 255 RGB[2] *= 255 img[i, j, 0] = RGB[0] img[i, j, 1] = RGB[1] img[i, j, 2] = RGB[2] scikit-image-0.9.3/skimage/io/_plugins/_histograms.pyx000066400000000000000000000037001223313777300230310ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cimport numpy as cnp cdef inline float tri_max(float a, float b, float c): cdef float MAX if a > b: MAX = a else: MAX = b if MAX > c: return MAX else: return c def histograms(cnp.ndarray[cnp.uint8_t, ndim=3] img, int nbins): '''Calculate the channel histograms of the current image. Parameters ---------- img : ndarray, uint8, ndim=3 The image to calculate the histogram. nbins : int The number of bins. Returns ------- out : (rcounts, gcounts, bcounts, vcounts) The binned histograms of the RGB channels and grayscale intensity. This is a NAIVE histogram routine, meant primarily for fast display. ''' cdef int width = img.shape[1] cdef int height = img.shape[0] cdef cnp.ndarray[cnp.int32_t, ndim=1] r, g, b, v r = np.zeros((nbins,), dtype=np.int32) g = np.zeros((nbins,), dtype=np.int32) b = np.zeros((nbins,), dtype=np.int32) v = np.zeros((nbins,), dtype=np.int32) cdef int i, j, k, rbin, gbin, bbin, vbin cdef float bin_width = 255./ nbins cdef float R, G, B, V for i in range(height): for j in range(width): R = img[i, j, 0] G = img[i, j, 1] B = img[i, j, 2] V = tri_max(R, G, B) rbin = (R / bin_width) gbin = (G / bin_width) bbin = (B / bin_width) vbin = (V / bin_width) # fully open last bin if R == 255: rbin -= 1 if G == 255: gbin -= 1 if B == 255: bbin -= 1 if V == 255: vbin -= 1 r[rbin] += 1 g[gbin] += 1 b[bbin] += 1 v[vbin] += 1 return (r, g, b, v) scikit-image-0.9.3/skimage/io/_plugins/fits_plugin.ini000066400000000000000000000001311223313777300227670ustar00rootroot00000000000000[fits] description = FITS image reading via PyFITS provides = imread, imread_collection scikit-image-0.9.3/skimage/io/_plugins/fits_plugin.py000066400000000000000000000110341223313777300226440ustar00rootroot00000000000000__all__ = ['imread', 'imread_collection'] import skimage.io as io try: import pyfits except ImportError: raise ImportError("PyFITS could not be found. Please refer to\n" "http://www.stsci.edu/resources/software_hardware/pyfits\n" "for further instructions.") def imread(fname, dtype=None): """Load an image from a FITS file. Parameters ---------- fname : string Image file name, e.g. ``test.fits``. dtype : dtype, optional For FITS, this argument is ignored because Stefan is planning on removing the dtype argument from imread anyway. Returns ------- img_array : ndarray Unlike plugins such as PIL, where different colour bands/channels are stored in the third dimension, FITS images are greyscale-only and can be N-dimensional, so an array of the native FITS dimensionality is returned, without colour channels. Currently if no image is found in the file, None will be returned Notes ----- Currently FITS ``imread()`` always returns the first image extension when given a Multi-Extension FITS file; use ``imread_collection()`` (which does lazy loading) to get all the extensions at once. """ hdulist = pyfits.open(fname) # Iterate over FITS image extensions, ignoring any other extension types # such as binary tables, and get the first image data array: img_array = None for hdu in hdulist: if isinstance(hdu, pyfits.ImageHDU) or \ isinstance(hdu, pyfits.PrimaryHDU): if hdu.data is not None: img_array = hdu.data break hdulist.close() return img_array def imread_collection(load_pattern, conserve_memory=True): """Load a collection of images from one or more FITS files Parameters ---------- load_pattern : str or list List of extensions to load. Filename globbing is currently unsupported. converve_memory : bool If True, never keep more than one in memory at a specific time. Otherwise, images will be cached once they are loaded. Returns ------- ic : ImageCollection Collection of images. """ intype = type(load_pattern) if intype is not list and intype is not str: raise TypeError("Input must be a filename or list of filenames") # Ensure we have a list, otherwise we'll end up iterating over the string: if intype is not list: load_pattern = [load_pattern] # Generate a list of filename/extension pairs by opening the list of # files and finding the image extensions in each one: ext_list = [] for filename in load_pattern: hdulist = pyfits.open(filename) for n, hdu in zip(range(len(hdulist)), hdulist): if isinstance(hdu, pyfits.ImageHDU) or \ isinstance(hdu, pyfits.PrimaryHDU): # Ignore (primary) header units with no data (use '.size' # rather than '.data' to avoid actually loading the image): try: data_size = hdu.size() except TypeError: # (size changed to int in PyFITS 3.1) data_size = hdu.size if data_size > 0: ext_list.append((filename, n)) hdulist.close() return io.ImageCollection(ext_list, load_func=FITSFactory, conserve_memory=conserve_memory) def FITSFactory(image_ext): """Load an image extension from a FITS file and return a NumPy array Parameters ---------- image_ext : tuple FITS extension to load, in the format ``(filename, ext_num)``. The FITS ``(extname, extver)`` format is unsupported, since this function is not called directly by the user and ``imread_collection()`` does the work of figuring out which extensions need loading. """ # Expect a length-2 tuple with a filename as the first element: if not isinstance(image_ext, tuple): raise TypeError("Expected a tuple") if len(image_ext) != 2: raise ValueError("Expected a tuple of length 2") filename = image_ext[0] extnum = image_ext[1] if type(filename) is not str or type(extnum) is not int: raise ValueError("Expected a (filename, extension) tuple") hdulist = pyfits.open(filename) data = hdulist[extnum].data hdulist.close() if data is None: raise RuntimeError("Extension %d of %s has no data" % (extnum, filename)) return data scikit-image-0.9.3/skimage/io/_plugins/freeimage_plugin.ini000066400000000000000000000001341223313777300237510ustar00rootroot00000000000000[freeimage] description = Load images using the FreeImage library provides = imread, imsave scikit-image-0.9.3/skimage/io/_plugins/freeimage_plugin.py000066400000000000000000000642431223313777300236350ustar00rootroot00000000000000import ctypes import numpy import sys import os import os.path from numpy.compat import asbytes, asstr def _generate_candidate_libs(): # look for likely library files in the following dirs: lib_dirs = [os.path.dirname(__file__), '/lib', '/usr/lib', '/usr/local/lib', '/opt/local/lib', os.path.join(sys.prefix, 'lib'), os.path.join(sys.prefix, 'DLLs') ] if 'HOME' in os.environ: lib_dirs.append(os.path.join(os.environ['HOME'], 'lib')) lib_dirs = [ld for ld in lib_dirs if os.path.exists(ld)] lib_names = ['libfreeimage', 'freeimage'] # should be lower-case! # Now attempt to find libraries of that name in the given directory # (case-insensitive and without regard for extension) lib_paths = [] for lib_dir in lib_dirs: for lib_name in lib_names: files = os.listdir(lib_dir) lib_paths += [os.path.join(lib_dir, lib) for lib in files if lib.lower().startswith(lib_name) and not os.path.splitext(lib)[1] in ('.py', '.pyc', '.ini')] lib_paths = [lp for lp in lib_paths if os.path.exists(lp)] return lib_dirs, lib_paths def load_freeimage(): if sys.platform == 'win32': loader = ctypes.windll functype = ctypes.WINFUNCTYPE else: loader = ctypes.cdll functype = ctypes.CFUNCTYPE freeimage = None errors = [] # First try a few bare library names that ctypes might be able to find # in the default locations for each platform. Win DLL names don't need the # extension, but other platforms do. bare_libs = ['FreeImage', 'libfreeimage.dylib', 'libfreeimage.so', 'libfreeimage.so.3'] lib_dirs, lib_paths = _generate_candidate_libs() lib_paths = bare_libs + lib_paths for lib in lib_paths: try: freeimage = loader.LoadLibrary(lib) break except Exception: if lib not in bare_libs: # Don't record errors when it couldn't load the library from # a bare name -- this fails often, and doesn't provide any # useful debugging information anyway, beyond "couldn't find # library..." # Get exception instance in Python 2.x/3.x compatible manner e_type, e_value, e_tb = sys.exc_info() del e_tb errors.append((lib, e_value)) if freeimage is None: if errors: # No freeimage library loaded, and load-errors reported for some # candidate libs err_txt = ['%s:\n%s' % (l, str(e.message)) for l, e in errors] raise RuntimeError('One or more FreeImage libraries were found, but ' 'could not be loaded due to the following errors:\n' '\n\n'.join(err_txt)) else: # No errors, because no potential libraries found at all! raise RuntimeError('Could not find a FreeImage library in any of:\n' + '\n'.join(lib_dirs)) # FreeImage found @functype(None, ctypes.c_int, ctypes.c_char_p) def error_handler(fif, message): raise RuntimeError('FreeImage error: %s' % message) freeimage.FreeImage_SetOutputMessage(error_handler) return freeimage _FI = load_freeimage() API = { # All we're doing here is telling ctypes that some of the FreeImage # functions return pointers instead of integers. (On 64-bit systems, # without this information the pointers get truncated and crashes result). # There's no need to list functions that return ints, or the types of the # parameters to these or other functions -- that's fine to do implicitly. # Note that the ctypes immediately converts the returned void_p back to a # python int again! This is really not helpful, because then passing it # back to another library call will cause truncation-to-32-bits on 64-bit # systems. Thanks, ctypes! So after these calls one must immediately # re-wrap the int as a c_void_p if it is to be passed back into FreeImage. 'FreeImage_AllocateT': (ctypes.c_void_p, None), 'FreeImage_FindFirstMetadata': (ctypes.c_void_p, None), 'FreeImage_GetBits': (ctypes.c_void_p, None), 'FreeImage_GetPalette': (ctypes.c_void_p, None), 'FreeImage_GetTagKey': (ctypes.c_char_p, None), 'FreeImage_GetTagValue': (ctypes.c_void_p, None), 'FreeImage_Load': (ctypes.c_void_p, None), 'FreeImage_LockPage': (ctypes.c_void_p, None), 'FreeImage_OpenMultiBitmap': (ctypes.c_void_p, None) } # Albert's ctypes pattern def register_api(lib, api): for f, (restype, argtypes) in api.items(): func = getattr(lib, f) func.restype = restype func.argtypes = argtypes register_api(_FI, API) class FI_TYPES(object): FIT_UNKNOWN = 0 FIT_BITMAP = 1 FIT_UINT16 = 2 FIT_INT16 = 3 FIT_UINT32 = 4 FIT_INT32 = 5 FIT_FLOAT = 6 FIT_DOUBLE = 7 FIT_COMPLEX = 8 FIT_RGB16 = 9 FIT_RGBA16 = 10 FIT_RGBF = 11 FIT_RGBAF = 12 dtypes = { FIT_BITMAP: numpy.uint8, FIT_UINT16: numpy.uint16, FIT_INT16: numpy.int16, FIT_UINT32: numpy.uint32, FIT_INT32: numpy.int32, FIT_FLOAT: numpy.float32, FIT_DOUBLE: numpy.float64, FIT_COMPLEX: numpy.complex128, FIT_RGB16: numpy.uint16, FIT_RGBA16: numpy.uint16, FIT_RGBF: numpy.float32, FIT_RGBAF: numpy.float32 } fi_types = { (numpy.dtype('uint8'), 1): FIT_BITMAP, (numpy.dtype('uint8'), 3): FIT_BITMAP, (numpy.dtype('uint8'), 4): FIT_BITMAP, (numpy.dtype('uint16'), 1): FIT_UINT16, (numpy.dtype('int16'), 1): FIT_INT16, (numpy.dtype('uint32'), 1): FIT_UINT32, (numpy.dtype('int32'), 1): FIT_INT32, (numpy.dtype('float32'), 1): FIT_FLOAT, (numpy.dtype('float64'), 1): FIT_DOUBLE, (numpy.dtype('complex128'), 1): FIT_COMPLEX, (numpy.dtype('uint16'), 3): FIT_RGB16, (numpy.dtype('uint16'), 4): FIT_RGBA16, (numpy.dtype('float32'), 3): FIT_RGBF, (numpy.dtype('float32'), 4): FIT_RGBAF } extra_dims = { FIT_UINT16: [], FIT_INT16: [], FIT_UINT32: [], FIT_INT32: [], FIT_FLOAT: [], FIT_DOUBLE: [], FIT_COMPLEX: [], FIT_RGB16: [3], FIT_RGBA16: [4], FIT_RGBF: [3], FIT_RGBAF: [4] } @classmethod def get_type_and_shape(cls, bitmap): w = _FI.FreeImage_GetWidth(bitmap) h = _FI.FreeImage_GetHeight(bitmap) fi_type = _FI.FreeImage_GetImageType(bitmap) if not fi_type: raise ValueError('Unknown image pixel type') dtype = cls.dtypes[fi_type] if fi_type == cls.FIT_BITMAP: bpp = _FI.FreeImage_GetBPP(bitmap) if bpp == 8: extra_dims = [] elif bpp == 24: extra_dims = [3] elif bpp == 32: extra_dims = [4] else: raise ValueError('Cannot convert %d BPP bitmap' % bpp) else: extra_dims = cls.extra_dims[fi_type] return numpy.dtype(dtype), extra_dims + [w, h] class IO_FLAGS(object): FIF_LOAD_NOPIXELS = 0x8000 # loading: load the image header only # (not supported by all plugins) BMP_DEFAULT = 0 BMP_SAVE_RLE = 1 CUT_DEFAULT = 0 DDS_DEFAULT = 0 EXR_DEFAULT = 0 # save data as half with piz-based wavelet compression EXR_FLOAT = 0x0001 # save data as float instead of as half (not recommended) EXR_NONE = 0x0002 # save with no compression EXR_ZIP = 0x0004 # save with zlib compression, in blocks of 16 scan lines EXR_PIZ = 0x0008 # save with piz-based wavelet compression EXR_PXR24 = 0x0010 # save with lossy 24-bit float compression EXR_B44 = 0x0020 # save with lossy 44% float compression # - goes to 22% when combined with EXR_LC EXR_LC = 0x0040 # save images with one luminance and two chroma channels, # rather than as RGB (lossy compression) FAXG3_DEFAULT = 0 GIF_DEFAULT = 0 GIF_LOAD256 = 1 # Load the image as a 256 color image with ununsed # palette entries, if it's 16 or 2 color GIF_PLAYBACK = 2 # 'Play' the GIF to generate each frame (as 32bpp) # instead of returning raw frame data when loading HDR_DEFAULT = 0 ICO_DEFAULT = 0 ICO_MAKEALPHA = 1 # convert to 32bpp and create an alpha channel from the # AND-mask when loading IFF_DEFAULT = 0 J2K_DEFAULT = 0 # save with a 16:1 rate JP2_DEFAULT = 0 # save with a 16:1 rate JPEG_DEFAULT = 0 # loading (see JPEG_FAST); # saving (see JPEG_QUALITYGOOD|JPEG_SUBSAMPLING_420) JPEG_FAST = 0x0001 # load the file as fast as possible, # sacrificing some quality JPEG_ACCURATE = 0x0002 # load the file with the best quality, # sacrificing some speed JPEG_CMYK = 0x0004 # load separated CMYK "as is" # (use | to combine with other load flags) JPEG_EXIFROTATE = 0x0008 # load and rotate according to # Exif 'Orientation' tag if available JPEG_QUALITYSUPERB = 0x80 # save with superb quality (100:1) JPEG_QUALITYGOOD = 0x0100 # save with good quality (75:1) JPEG_QUALITYNORMAL = 0x0200 # save with normal quality (50:1) JPEG_QUALITYAVERAGE = 0x0400 # save with average quality (25:1) JPEG_QUALITYBAD = 0x0800 # save with bad quality (10:1) JPEG_PROGRESSIVE = 0x2000 # save as a progressive-JPEG # (use | to combine with other save flags) JPEG_SUBSAMPLING_411 = 0x1000 # save with high 4x1 chroma # subsampling (4:1:1) JPEG_SUBSAMPLING_420 = 0x4000 # save with medium 2x2 medium chroma # subsampling (4:2:0) - default value JPEG_SUBSAMPLING_422 = 0x8000 # save with low 2x1 chroma subsampling (4:2:2) JPEG_SUBSAMPLING_444 = 0x10000 # save with no chroma subsampling (4:4:4) JPEG_OPTIMIZE = 0x20000 # on saving, compute optimal Huffman coding tables # (can reduce a few percent of file size) JPEG_BASELINE = 0x40000 # save basic JPEG, without metadata or any markers KOALA_DEFAULT = 0 LBM_DEFAULT = 0 MNG_DEFAULT = 0 PCD_DEFAULT = 0 PCD_BASE = 1 # load the bitmap sized 768 x 512 PCD_BASEDIV4 = 2 # load the bitmap sized 384 x 256 PCD_BASEDIV16 = 3 # load the bitmap sized 192 x 128 PCX_DEFAULT = 0 PFM_DEFAULT = 0 PICT_DEFAULT = 0 PNG_DEFAULT = 0 PNG_IGNOREGAMMA = 1 # loading: avoid gamma correction PNG_Z_BEST_SPEED = 0x0001 # save using ZLib level 1 compression flag # (default value is 6) PNG_Z_DEFAULT_COMPRESSION = 0x0006 # save using ZLib level 6 compression # flag (default recommended value) PNG_Z_BEST_COMPRESSION = 0x0009 # save using ZLib level 9 compression flag # (default value is 6) PNG_Z_NO_COMPRESSION = 0x0100 # save without ZLib compression PNG_INTERLACED = 0x0200 # save using Adam7 interlacing (use | to combine # with other save flags) PNM_DEFAULT = 0 PNM_SAVE_RAW = 0 # Writer saves in RAW format (i.e. P4, P5 or P6) PNM_SAVE_ASCII = 1 # Writer saves in ASCII format (i.e. P1, P2 or P3) PSD_DEFAULT = 0 PSD_CMYK = 1 # reads tags for separated CMYK (default is conversion to RGB) PSD_LAB = 2 # reads tags for CIELab (default is conversion to RGB) RAS_DEFAULT = 0 RAW_DEFAULT = 0 # load the file as linear RGB 48-bit RAW_PREVIEW = 1 # try to load the embedded JPEG preview with included # Exif Data or default to RGB 24-bit RAW_DISPLAY = 2 # load the file as RGB 24-bit SGI_DEFAULT = 0 TARGA_DEFAULT = 0 TARGA_LOAD_RGB888 = 1 # Convert RGB555 and ARGB8888 -> RGB888. TARGA_SAVE_RLE = 2 # Save with RLE compression TIFF_DEFAULT = 0 TIFF_CMYK = 0x0001 # reads/stores tags for separated CMYK # (use | to combine with compression flags) TIFF_PACKBITS = 0x0100 # save using PACKBITS compression TIFF_DEFLATE = 0x0200 # save using DEFLATE (a.k.a. ZLIB) compression TIFF_ADOBE_DEFLATE = 0x0400 # save using ADOBE DEFLATE compression TIFF_NONE = 0x0800 # save without any compression TIFF_CCITTFAX3 = 0x1000 # save using CCITT Group 3 fax encoding TIFF_CCITTFAX4 = 0x2000 # save using CCITT Group 4 fax encoding TIFF_LZW = 0x4000 # save using LZW compression TIFF_JPEG = 0x8000 # save using JPEG compression TIFF_LOGLUV = 0x10000 # save using LogLuv compression WBMP_DEFAULT = 0 XBM_DEFAULT = 0 XPM_DEFAULT = 0 class METADATA_MODELS(object): FIMD_COMMENTS = 0 FIMD_EXIF_MAIN = 1 FIMD_EXIF_EXIF = 2 FIMD_EXIF_GPS = 3 FIMD_EXIF_MAKERNOTE = 4 FIMD_EXIF_INTEROP = 5 FIMD_IPTC = 6 FIMD_XMP = 7 FIMD_GEOTIFF = 8 FIMD_ANIMATION = 9 class METADATA_DATATYPE(object): FIDT_BYTE = 1 # 8-bit unsigned integer FIDT_ASCII = 2 # 8-bit bytes w/ last byte null FIDT_SHORT = 3 # 16-bit unsigned integer FIDT_LONG = 4 # 32-bit unsigned integer FIDT_RATIONAL = 5 # 64-bit unsigned fraction FIDT_SBYTE = 6 # 8-bit signed integer FIDT_UNDEFINED = 7 # 8-bit untyped data FIDT_SSHORT = 8 # 16-bit signed integer FIDT_SLONG = 9 # 32-bit signed integer FIDT_SRATIONAL = 10 # 64-bit signed fraction FIDT_FLOAT = 11 # 32-bit IEEE floating point FIDT_DOUBLE = 12 # 64-bit IEEE floating point FIDT_IFD = 13 # 32-bit unsigned integer (offset) FIDT_PALETTE = 14 # 32-bit RGBQUAD FIDT_LONG8 = 16 # 64-bit unsigned integer FIDT_SLONG8 = 17 # 64-bit signed integer FIDT_IFD8 = 18 # 64-bit unsigned integer (offset) dtypes = { FIDT_BYTE: numpy.uint8, FIDT_SHORT: numpy.uint16, FIDT_LONG: numpy.uint32, FIDT_RATIONAL: [('numerator', numpy.uint32), ('denominator', numpy.uint32)], FIDT_SBYTE: numpy.int8, FIDT_UNDEFINED: numpy.uint8, FIDT_SSHORT: numpy.int16, FIDT_SLONG: numpy.int32, FIDT_SRATIONAL: [('numerator', numpy.int32), ('denominator', numpy.int32)], FIDT_FLOAT: numpy.float32, FIDT_DOUBLE: numpy.float64, FIDT_IFD: numpy.uint32, FIDT_PALETTE: [('R', numpy.uint8), ('G', numpy.uint8), ('B', numpy.uint8), ('A', numpy.uint8)], FIDT_LONG8: numpy.uint64, FIDT_SLONG8: numpy.int64, FIDT_IFD8: numpy.uint64 } def _process_bitmap(filename, flags, process_func): filename = asbytes(filename) ftype = _FI.FreeImage_GetFileType(filename, 0) if ftype == -1: raise ValueError('Cannot determine type of file %s' % filename) bitmap = _FI.FreeImage_Load(ftype, filename, flags) bitmap = ctypes.c_void_p(bitmap) if not bitmap: raise ValueError('Could not load file %s' % filename) try: return process_func(bitmap) finally: _FI.FreeImage_Unload(bitmap) def read(filename, flags=0): """Read an image to a numpy array of shape (height, width) for greyscale images, or shape (height, width, nchannels) for RGB or RGBA images. The `flags` parameter should be one or more values from the IO_FLAGS class defined in this module, or-ed together with | as appropriate. (See the source-code comments for more details.) """ return _process_bitmap(filename, flags, _array_from_bitmap) def read_metadata(filename): """Return a dict containing all image metadata. Returned dict maps (metadata_model, tag_name) keys to tag values, where metadata_model is a string name based on the FreeImage "metadata models" defined in the class METADATA_MODELS. """ flags = IO_FLAGS.FIF_LOAD_NOPIXELS return _process_bitmap(filename, flags, _read_metadata) def _process_multipage(filename, flags, process_func): filename = asbytes(filename) ftype = _FI.FreeImage_GetFileType(filename, 0) if ftype == -1: raise ValueError('Cannot determine type of file %s' % filename) create_new = False read_only = True keep_cache_in_memory = True multibitmap = _FI.FreeImage_OpenMultiBitmap(ftype, filename, create_new, read_only, keep_cache_in_memory, flags) multibitmap = ctypes.c_void_p(multibitmap) if not multibitmap: raise ValueError('Could not open %s as multi-page image.' % filename) try: pages = _FI.FreeImage_GetPageCount(multibitmap) out = [] for i in range(pages): bitmap = _FI.FreeImage_LockPage(multibitmap, i) bitmap = ctypes.c_void_p(bitmap) if not bitmap: raise ValueError('Could not open %s as a multi-page image.' % filename) try: out.append(process_func(bitmap)) finally: _FI.FreeImage_UnlockPage(multibitmap, bitmap, False) return out finally: _FI.FreeImage_CloseMultiBitmap(multibitmap, 0) def read_multipage(filename, flags=0): """Read a multipage image to a list of numpy arrays, where each array is of shape (height, width) for greyscale images, or shape (height, width, nchannels) for RGB or RGBA images. The `flags` parameter should be one or more values from the IO_FLAGS class defined in this module, or-ed together with | as appropriate. (See the source-code comments for more details.) """ return _process_multipage(filename, flags, _array_from_bitmap) def read_multipage_metadata(filename): """Read a multipage image to a list of metadata dicts, one dict for each page. The dict format is as in read_metadata(). """ flags = IO_FLAGS.FIF_LOAD_NOPIXELS return _process_multipage(filename, flags, _read_metadata) def _wrap_bitmap_bits_in_array(bitmap, shape, dtype): """Return an ndarray view on the data in a FreeImage bitmap. Only valid for as long as the bitmap is loaded (if single page) / locked in memory (if multipage). """ pitch = _FI.FreeImage_GetPitch(bitmap) height = shape[-1] byte_size = height * pitch itemsize = dtype.itemsize if len(shape) == 3: strides = (itemsize, shape[0] * itemsize, pitch) else: strides = (itemsize, pitch) bits = _FI.FreeImage_GetBits(bitmap) array = numpy.ndarray(shape, dtype=dtype, buffer=(ctypes.c_char * byte_size).from_address(bits), strides=strides) return array def _array_from_bitmap(bitmap): """Convert a FreeImage bitmap pointer to a numpy array. """ dtype, shape = FI_TYPES.get_type_and_shape(bitmap) array = _wrap_bitmap_bits_in_array(bitmap, shape, dtype) # swizzle the color components and flip the scanlines to go from # FreeImage's BGR[A] and upside-down internal memory format to something # more normal def n(arr): return arr[..., ::-1].T if len(shape) == 3 and _FI.FreeImage_IsLittleEndian() and \ dtype.type == numpy.uint8: b = n(array[0]) g = n(array[1]) r = n(array[2]) if shape[0] == 3: return numpy.dstack((r, g, b)) elif shape[0] == 4: a = n(array[3]) return numpy.dstack((r, g, b, a)) else: raise ValueError('Cannot handle images of shape %s' % shape) # We need to copy because array does *not* own its memory # after bitmap is freed. return n(array).copy() def _read_metadata(bitmap): metadata = {} models = [(name[5:], number) for name, number in METADATA_MODELS.__dict__.items() if name.startswith('FIMD_')] tag = ctypes.c_void_p() for model_name, number in models: mdhandle = _FI.FreeImage_FindFirstMetadata(number, bitmap, ctypes.byref(tag)) mdhandle = ctypes.c_void_p(mdhandle) if mdhandle: more = True while more: tag_name = asstr(_FI.FreeImage_GetTagKey(tag)) tag_type = _FI.FreeImage_GetTagType(tag) byte_size = _FI.FreeImage_GetTagLength(tag) char_ptr = ctypes.c_char * byte_size tag_str = char_ptr.from_address(_FI.FreeImage_GetTagValue(tag)) if tag_type == METADATA_DATATYPE.FIDT_ASCII: tag_val = asstr(tag_str.value) else: tag_val = numpy.fromstring(tag_str, dtype=METADATA_DATATYPE.dtypes[tag_type]) if len(tag_val) == 1: tag_val = tag_val[0] metadata[(model_name, tag_name)] = tag_val more = _FI.FreeImage_FindNextMetadata(mdhandle, ctypes.byref(tag)) _FI.FreeImage_FindCloseMetadata(mdhandle) return metadata def write(array, filename, flags=0): """Write a (height, width) or (height, width, nchannels) array to a greyscale, RGB, or RGBA image, with file type deduced from the filename. The `flags` parameter should be one or more values from the IO_FLAGS class defined in this module, or-ed together with | as appropriate. (See the source-code comments for more details.) """ array = numpy.asarray(array) filename = asbytes(filename) ftype = _FI.FreeImage_GetFIFFromFilename(filename) if ftype == -1: raise ValueError('Cannot determine type for %s' % filename) bitmap, fi_type = _array_to_bitmap(array) try: if fi_type == FI_TYPES.FIT_BITMAP: can_write = _FI.FreeImage_FIFSupportsExportBPP(ftype, _FI.FreeImage_GetBPP(bitmap)) else: can_write = _FI.FreeImage_FIFSupportsExportType(ftype, fi_type) if not can_write: raise TypeError('Cannot save image of this format ' 'to this file type') res = _FI.FreeImage_Save(ftype, bitmap, filename, flags) if not res: raise RuntimeError('Could not save image properly.') finally: _FI.FreeImage_Unload(bitmap) def write_multipage(arrays, filename, flags=0): """Write a list of (height, width) or (height, width, nchannels) arrays to a multipage greyscale, RGB, or RGBA image, with file type deduced from the filename. The `flags` parameter should be one or more values from the IO_FLAGS class defined in this module, or-ed together with | as appropriate. (See the source-code comments for more details.) """ filename = asbytes(filename) ftype = _FI.FreeImage_GetFIFFromFilename(filename) if ftype == -1: raise ValueError('Cannot determine type of file %s' % filename) create_new = True read_only = False keep_cache_in_memory = True multibitmap = _FI.FreeImage_OpenMultiBitmap(ftype, filename, create_new, read_only, keep_cache_in_memory, 0) multibitmap = ctypes.c_void_p(multibitmap) if not multibitmap: raise ValueError('Could not open %s for writing multi-page image.' % filename) try: for array in arrays: array = numpy.asarray(array) bitmap, fi_type = _array_to_bitmap(array) _FI.FreeImage_AppendPage(multibitmap, bitmap) finally: _FI.FreeImage_CloseMultiBitmap(multibitmap, flags) # 4-byte quads of 0,v,v,v from 0,0,0,0 to 0,255,255,255 _GREY_PALETTE = numpy.arange(0, 0x01000000, 0x00010101, dtype=numpy.uint32) def _array_to_bitmap(array): """Allocate a FreeImage bitmap and copy a numpy array into it. """ shape = array.shape dtype = array.dtype r, c = shape[:2] if len(shape) == 2: n_channels = 1 w_shape = (c, r) elif len(shape) == 3: n_channels = shape[2] w_shape = (n_channels, c, r) else: n_channels = shape[0] try: fi_type = FI_TYPES.fi_types[(dtype, n_channels)] except KeyError: raise ValueError('Cannot write arrays of given type and shape.') itemsize = array.dtype.itemsize bpp = 8 * itemsize * n_channels bitmap = _FI.FreeImage_AllocateT(fi_type, c, r, bpp, 0, 0, 0) bitmap = ctypes.c_void_p(bitmap) if not bitmap: raise RuntimeError('Could not allocate image for storage') try: def n(arr): # normalise to freeimage's in-memory format return arr.T[:, ::-1] wrapped_array = _wrap_bitmap_bits_in_array(bitmap, w_shape, dtype) # swizzle the color components and flip the scanlines to go to # FreeImage's BGR[A] and upside-down internal memory format if len(shape) == 3 and _FI.FreeImage_IsLittleEndian() and \ dtype.type == numpy.uint8: wrapped_array[0] = n(array[:, :, 2]) wrapped_array[1] = n(array[:, :, 1]) wrapped_array[2] = n(array[:, :, 0]) if shape[2] == 4: wrapped_array[3] = n(array[:, :, 3]) else: wrapped_array[:] = n(array) if len(shape) == 2 and dtype.type == numpy.uint8: palette = _FI.FreeImage_GetPalette(bitmap) palette = ctypes.c_void_p(palette) if not palette: raise RuntimeError('Could not get image palette') ctypes.memmove(palette, _GREY_PALETTE.ctypes.data, 1024) return bitmap, fi_type except: _FI.FreeImage_Unload(bitmap) raise def imread(filename): """ img = imread(filename) Reads an image from file `filename` Parameters ---------- filename : file name Returns ------- img : ndarray """ img = read(filename) return img def imsave(filename, img): ''' imsave(filename, img) Save image to disk Image type is inferred from filename Parameters ---------- filename : file name img : image to be saved as nd array ''' write(img, filename) scikit-image-0.9.3/skimage/io/_plugins/gdal_plugin.ini000066400000000000000000000001321223313777300227320ustar00rootroot00000000000000[gdal] description = Image reading via the GDAL Library (www.gdal.org) provides = imread scikit-image-0.9.3/skimage/io/_plugins/gdal_plugin.py000066400000000000000000000006131223313777300226070ustar00rootroot00000000000000__all__ = ['imread'] try: import osgeo.gdal as gdal except ImportError: raise ImportError("The GDAL Library could not be found. " "Please refer to http://www.gdal.org/ " "for further instructions.") def imread(fname, dtype=None): """Load an image from file. """ ds = gdal.Open(fname) return ds.ReadAsArray().astype(dtype) scikit-image-0.9.3/skimage/io/_plugins/gtk_plugin.ini000066400000000000000000000001331223313777300226110ustar00rootroot00000000000000[gtk] description = Fast image display using the GTK library provides = imshow, _app_show scikit-image-0.9.3/skimage/io/_plugins/gtk_plugin.py000066400000000000000000000032631223313777300224710ustar00rootroot00000000000000from util import prepare_for_display, window_manager, GuiLockError try: # we try to aquire the gui lock first # or else the gui import might trample another # gui's pyos_inputhook. window_manager.acquire('gtk') except GuiLockError as gle: print(gle) else: try: import gtk except ImportError: print('pygtk libraries not installed.') print('plugin not loaded.') window_manager._release('gtk') else: class ImageWindow(gtk.Window): def __init__(self, arr, mgr): gtk.Window.__init__(self) self.mgr = mgr self.mgr.add_window(self) self.connect("destroy", self.destroy) width = arr.shape[1] height = arr.shape[0] rstride = arr.strides[0] pb = gtk.gdk.pixbuf_new_from_data(arr.data, gtk.gdk.COLORSPACE_RGB, False, 8, width, height, rstride) self.img = gtk.Image() self.img.set_from_pixbuf(pb) self.add(self.img) self.img.show() def destroy(self, widget, data=None): self.mgr.remove_window(self) def imshow(arr): arr = prepare_for_display(arr) iw = ImageWindow(arr, window_manager) iw.show() def _app_show(): if window_manager.has_windows(): window_manager.register_callback(gtk.main_quit) gtk.main() else: print('no images to display') scikit-image-0.9.3/skimage/io/_plugins/imread_plugin.ini000066400000000000000000000001261223313777300232670ustar00rootroot00000000000000[imread] description = Image reading and writing via imread provides = imread, imsave scikit-image-0.9.3/skimage/io/_plugins/imread_plugin.py000066400000000000000000000017151223313777300231450ustar00rootroot00000000000000__all__ = ['imread', 'imsave'] from skimage.utils.dtype import convert try: import imread as _imread except ImportError: raise ImportError("Imread could not be found" "Please refer to http://pypi.python.org/pypi/imread/ " "for further instructions.") def imread(fname, dtype=None): """Load an image from file. Parameters ---------- fname : str Name of input file """ im = _imread.imread(fname) if dtype is not None: im = convert(im, dtype) return im def imsave(fname, arr, format_str=None): """Save an image to disk. Parameters ---------- fname : str Name of destination file. arr : ndarray of uint8 or uint16 Array (image) to save. format_str: str,optional Format to save as. Notes ----- Currently, only 8-bit precision is supported. """ return _imread.imsave(fname, arr, formatstr=format_str) scikit-image-0.9.3/skimage/io/_plugins/matplotlib_plugin.ini000066400000000000000000000001511223313777300241730ustar00rootroot00000000000000[matplotlib] description = Display or save images using Matplotlib provides = imshow, imread, _app_show scikit-image-0.9.3/skimage/io/_plugins/matplotlib_plugin.py000066400000000000000000000003721223313777300240510ustar00rootroot00000000000000import matplotlib.pyplot as plt def imshow(*args, **kwargs): kwargs.setdefault('interpolation', 'nearest') kwargs.setdefault('cmap', 'gray') plt.imshow(*args, **kwargs) imread = plt.imread show = plt.show def _app_show(): show() scikit-image-0.9.3/skimage/io/_plugins/null_plugin.ini000066400000000000000000000001331223313777300227760ustar00rootroot00000000000000[null] description = Default plugin that does nothing provides = imshow, imread, _app_show scikit-image-0.9.3/skimage/io/_plugins/null_plugin.py000066400000000000000000000005341223313777300226540ustar00rootroot00000000000000__all__ = ['imshow', 'imread', '_app_show'] import warnings message = '''\ No plugin has been loaded. Please refer to skimage.io.plugins() for a list of available plugins.''' def imshow(*args, **kwargs): warnings.warn(RuntimeWarning(message)) def imread(*args, **kwargs): warnings.warn(RuntimeWarning(message)) _app_show = imshow scikit-image-0.9.3/skimage/io/_plugins/pil_plugin.ini000066400000000000000000000001561223313777300226150ustar00rootroot00000000000000[pil] description = Image reading via the Python Imaging Library provides = imread, imsave, imshow, _app_show scikit-image-0.9.3/skimage/io/_plugins/pil_plugin.py000066400000000000000000000067241223313777300224750ustar00rootroot00000000000000__all__ = ['imread'] import numpy as np try: from PIL import Image except ImportError: raise ImportError("The Python Image Library could not be found. " "Please refer to http://pypi.python.org/pypi/PIL/ " "for further instructions.") from skimage.util import img_as_ubyte from skimage._shared import six def imread(fname, dtype=None): """Load an image from file. """ im = Image.open(fname) if im.mode == 'P': if _palette_is_grayscale(im): im = im.convert('L') else: im = im.convert('RGB') elif im.mode == '1': im = im.convert('L') elif im.mode.startswith('I;16'): shape = im.size dtype = '>u2' if im.mode.endswith('B') else '>> from skimage.io import use_plugin >>> use_plugin('pil', 'imread') """ if kind is None: kind = plugin_store.keys() else: if not kind in plugin_provides[name]: raise RuntimeError("Plugin %s does not support `%s`." % \ (name, kind)) if kind == 'imshow': kind = [kind, '_app_show'] else: kind = [kind] _load(name) for k in kind: if not k in plugin_store: raise RuntimeError("'%s' is not a known plugin function." % k) funcs = plugin_store[k] # Shuffle the plugins so that the requested plugin stands first # in line funcs = [(n, f) for (n, f) in funcs if n == name] + \ [(n, f) for (n, f) in funcs if n != name] plugin_store[k] = funcs def available(loaded=False): """List available plugins. Parameters ---------- loaded : bool If True, show only those plugins currently loaded. By default, all plugins are shown. Returns ------- p : dict Dictionary with plugin names as keys and exposed functions as values. """ active_plugins = set() for plugin_func in plugin_store.values(): for plugin, func in plugin_func: active_plugins.add(plugin) d = {} for plugin in plugin_provides: if not loaded or plugin in active_plugins: d[plugin] = [f for f in plugin_provides[plugin] \ if not f.startswith('_')] return d def _load(plugin): """Load the given plugin. Parameters ---------- plugin : str Name of plugin to load. See Also -------- plugins : List of available plugins """ if plugin in available(loaded=True): return if not plugin in plugin_module_name: raise ValueError("Plugin %s not found." % plugin) else: modname = plugin_module_name[plugin] plugin_module = __import__('skimage.io._plugins.' + modname, fromlist=[modname]) provides = plugin_provides[plugin] for p in provides: if not hasattr(plugin_module, p): print("Plugin %s does not provide %s as advertised. Ignoring." % \ (plugin, p)) else: store = plugin_store[p] func = getattr(plugin_module, p) if not (plugin, func) in store: store.append((plugin, func)) def info(plugin): """Return plugin meta-data. Parameters ---------- plugin : str Name of plugin. Returns ------- m : dict Meta data as specified in plugin ``.ini``. """ try: return plugin_meta_data[plugin] except KeyError: raise ValueError('No information on plugin "%s"' % plugin) def configuration(): """Return the currently preferred plugin order. Returns ------- p : dict Dictionary of preferred plugin order, with function name as key and plugins (in order of preference) as value. """ p = {} for func in plugin_store: p[func] = [plugin_name for (plugin_name, f) in plugin_store[func]] return p scikit-image-0.9.3/skimage/io/_plugins/q_color_mixer.py000066400000000000000000000273241223313777300231740ustar00rootroot00000000000000# the module for the qt color_mixer plugin from PyQt4 import QtGui, QtCore from PyQt4.QtGui import (QWidget, QStackedWidget, QSlider, QGridLayout, QLabel) from util import ColorMixer class IntelligentSlider(QWidget): ''' A slider that adds a 'name' attribute and calls a callback with 'name' as an argument to the registerd callback. This allows you to create large groups of sliders in a loop, but still keep track of the individual events It also prints a label below the slider. The range of the slider is hardcoded from zero - 1000, but it supports a conversion factor so you can scale the results''' def __init__(self, name, a, b, callback): QWidget.__init__(self) self.name = name self.callback = callback self.a = a self.b = b self.manually_triggered = False self.slider = QSlider() self.slider.setRange(0, 1000) self.slider.setValue(500) self.slider.valueChanged.connect(self.slider_changed) self.name_label = QLabel() self.name_label.setText(self.name) self.name_label.setAlignment(QtCore.Qt.AlignCenter) self.value_label = QLabel() self.value_label.setText('%2.2f' % (self.slider.value() * self.a + self.b)) self.value_label.setAlignment(QtCore.Qt.AlignCenter) self.layout = QGridLayout(self) self.layout.addWidget(self.name_label, 0, 0) self.layout.addWidget(self.slider, 1, 0, QtCore.Qt.AlignHCenter) self.layout.addWidget(self.value_label, 2, 0) # bind this to the valueChanged signal of the slider def slider_changed(self, val): val = self.val() self.value_label.setText(str(val)[:4]) if not self.manually_triggered: self.callback(self.name, val) def set_conv_fac(self, a, b): self.a = a self.b = b def set_value(self, val): self.manually_triggered = True self.slider.setValue(int((val - self.b) / self.a)) self.value_label.setText('%2.2f' % val) self.manually_triggered = False def val(self): return self.slider.value() * self.a + self.b class MixerPanel(QtGui.QFrame): '''A color mixer to hook up to an image. You pass the image you the panel to operate on and it operates on that image in place. You also pass a callback to be called to trigger a refresh. This callback is called every time the mixer modifies your image.''' def __init__(self, img): QtGui.QFrame.__init__(self) #self.setFrameStyle(QtGui.QFrame.Box|QtGui.QFrame.Sunken) self.img = img self.mixer = ColorMixer(self.img) self.callback = None #--------------------------------------------------------------- # ComboBox #--------------------------------------------------------------- self.combo_box_entries = ['RGB Color', 'HSV Color', 'Brightness/Contrast', 'Gamma', 'Gamma (Sigmoidal)'] self.combo_box = QtGui.QComboBox() for entry in self.combo_box_entries: self.combo_box.addItem(entry) self.combo_box.currentIndexChanged.connect(self.combo_box_changed) #--------------------------------------------------------------- # RGB color sliders #--------------------------------------------------------------- # radio buttons self.rgb_add = QtGui.QRadioButton('Additive') self.rgb_mul = QtGui.QRadioButton('Multiplicative') self.rgb_mul.toggled.connect(self.rgb_radio_changed) self.rgb_add.toggled.connect(self.rgb_radio_changed) # sliders rs = IntelligentSlider('R', 0.51, -255, self.rgb_changed) gs = IntelligentSlider('G', 0.51, -255, self.rgb_changed) bs = IntelligentSlider('B', 0.51, -255, self.rgb_changed) self.rs = rs self.gs = gs self.bs = bs self.rgb_widget = QWidget() self.rgb_widget.layout = QGridLayout(self.rgb_widget) self.rgb_widget.layout.addWidget(self.rgb_add, 0, 0, 1, 3) self.rgb_widget.layout.addWidget(self.rgb_mul, 1, 0, 1, 3) self.rgb_widget.layout.addWidget(self.rs, 2, 0) self.rgb_widget.layout.addWidget(self.gs, 2, 1) self.rgb_widget.layout.addWidget(self.bs, 2, 2) #--------------------------------------------------------------- # HSV sliders #--------------------------------------------------------------- # radio buttons self.hsv_add = QtGui.QRadioButton('Additive') self.hsv_mul = QtGui.QRadioButton('Multiplicative') self.hsv_mul.toggled.connect(self.hsv_radio_changed) self.hsv_mul.toggled.connect(self.hsv_radio_changed) # sliders hs = IntelligentSlider('H', 0.36, -180, self.hsv_changed) ss = IntelligentSlider('S', 0.002, 0, self.hsv_changed) vs = IntelligentSlider('V', 0.002, 0, self.hsv_changed) self.hs = hs self.ss = ss self.vs = vs self.hsv_widget = QWidget() self.hsv_widget.layout = QGridLayout(self.hsv_widget) self.hsv_widget.layout.addWidget(self.hsv_add, 0, 0, 1, 3) self.hsv_widget.layout.addWidget(self.hsv_mul, 1, 0, 1, 3) self.hsv_widget.layout.addWidget(self.hs, 2, 0) self.hsv_widget.layout.addWidget(self.ss, 2, 1) self.hsv_widget.layout.addWidget(self.vs, 2, 2) #--------------------------------------------------------------- # Brightness/Contrast sliders #--------------------------------------------------------------- # sliders cont = IntelligentSlider('x', 0.002, 0, self.bright_changed) bright = IntelligentSlider('+', 0.51, -255, self.bright_changed) self.cont = cont self.bright = bright # layout self.bright_widget = QWidget() self.bright_widget.layout = QtGui.QGridLayout(self.bright_widget) self.bright_widget.layout.addWidget(self.cont, 0, 0) self.bright_widget.layout.addWidget(self.bright, 0, 1) #---------------------------------------------------------------------- # Gamma Slider #---------------------------------------------------------------------- gamma = IntelligentSlider('gamma', 0.005, 0, self.gamma_changed) self.gamma = gamma # layout self.gamma_widget = QWidget() self.gamma_widget.layout = QtGui.QGridLayout(self.gamma_widget) self.gamma_widget.layout.addWidget(self.gamma, 0, 0) #--------------------------------------------------------------- # Sigmoid Gamma sliders #--------------------------------------------------------------- # sliders alpha = IntelligentSlider('alpha', 0.011, 1, self.sig_gamma_changed) beta = IntelligentSlider('beta', 0.012, 0, self.sig_gamma_changed) self.a_gamma = alpha self.b_gamma = beta # layout self.sig_gamma_widget = QWidget() self.sig_gamma_widget.layout = QtGui.QGridLayout(self.sig_gamma_widget) self.sig_gamma_widget.layout.addWidget(self.a_gamma, 0, 0) self.sig_gamma_widget.layout.addWidget(self.b_gamma, 0, 1) #--------------------------------------------------------------- # Buttons #--------------------------------------------------------------- self.commit_button = QtGui.QPushButton('Commit') self.commit_button.clicked.connect(self.commit_changes) self.revert_button = QtGui.QPushButton('Revert') self.revert_button.clicked.connect(self.revert_changes) #--------------------------------------------------------------- # Mixer Layout #--------------------------------------------------------------- self.sliders = QStackedWidget() self.sliders.addWidget(self.rgb_widget) self.sliders.addWidget(self.hsv_widget) self.sliders.addWidget(self.bright_widget) self.sliders.addWidget(self.gamma_widget) self.sliders.addWidget(self.sig_gamma_widget) self.layout = QtGui.QGridLayout(self) self.layout.addWidget(self.combo_box, 0, 0) self.layout.addWidget(self.sliders, 1, 0) self.layout.addWidget(self.commit_button, 2, 0) self.layout.addWidget(self.revert_button, 3, 0) #--------------------------------------------------------------- # State Initialization #--------------------------------------------------------------- self.combo_box.setCurrentIndex(0) self.rgb_mul.setChecked(True) self.hsv_mul.setChecked(True) def set_callback(self, callback): self.callback = callback def combo_box_changed(self, index): self.sliders.setCurrentIndex(index) self.reset() def rgb_radio_changed(self): self.reset() def hsv_radio_changed(self): self.reset() def reset(self): self.reset_sliders() self.mixer.set_to_stateimg() if self.callback: self.callback() def reset_sliders(self): # handle changing the conversion factors necessary if self.rgb_add.isChecked(): self.rs.set_conv_fac(0.51, -255) self.rs.set_value(0) self.gs.set_conv_fac(0.51, -255) self.gs.set_value(0) self.bs.set_conv_fac(0.51, -255) self.bs.set_value(0) else: self.rs.set_conv_fac(0.002, 0) self.rs.set_value(1.) self.gs.set_conv_fac(0.002, 0) self.gs.set_value(1.) self.bs.set_conv_fac(0.002, 0) self.bs.set_value(1.) self.hs.set_value(0) if self.hsv_add.isChecked(): self.ss.set_conv_fac(0.002, -1) self.ss.set_value(0) self.vs.set_conv_fac(0.002, -1) self.vs.set_value(0) else: self.ss.set_conv_fac(0.002, 0) self.ss.set_value(1.) self.vs.set_conv_fac(0.002, 0) self.vs.set_value(1.) self.bright.set_value(0) self.cont.set_value(1.) self.gamma.set_value(1) self.a_gamma.set_value(1) self.b_gamma.set_value(0.5) def rgb_changed(self, name, val): if name == 'R': channel = self.mixer.RED elif name == 'G': channel = self.mixer.GREEN else: channel = self.mixer.BLUE if self.rgb_mul.isChecked(): self.mixer.multiply(channel, val) elif self.rgb_add.isChecked(): self.mixer.add(channel, val) else: pass if self.callback: self.callback() def hsv_changed(self, name, val): h = self.hs.val() s = self.ss.val() v = self.vs.val() if self.hsv_mul.isChecked(): self.mixer.hsv_multiply(h, s, v) elif self.hsv_add.isChecked(): self.mixer.hsv_add(h, s, v) else: pass if self.callback: self.callback() def bright_changed(self, name, val): b = self.bright.val() c = self.cont.val() self.mixer.brightness(c, b) if self.callback: self.callback() def gamma_changed(self, name, val): self.mixer.gamma(val) if self.callback: self.callback() def sig_gamma_changed(self, name, val): ag = self.a_gamma.val() bg = self.b_gamma.val() self.mixer.sigmoid_gamma(ag, bg) if self.callback: self.callback() def commit_changes(self): self.mixer.commit_changes() self.reset_sliders() def revert_changes(self): self.mixer.revert() self.reset_sliders() if self.callback: self.callback() scikit-image-0.9.3/skimage/io/_plugins/q_histogram.py000066400000000000000000000113301223313777300226350ustar00rootroot00000000000000import numpy as np from PyQt4.QtGui import QWidget, QPainter, QGridLayout, QColor, QFrame from util import histograms class ColorHistogram(QWidget): '''A Class which draws a scaling histogram in a widget. Where counts are the bin values in the histogram and colormap is a tuple of (R, G, B) tuples the same length as counts. These are the colors to apply to the histogram bars. Colormap can also contain a single tuple (R, G, B), in which case this is the color applied to all bars of that histogram. The histogram assumes the bins were evenly spaced. ''' def __init__(self, counts, colormap): QWidget.__init__(self) self._validate_input(counts, colormap) self.counts = counts self.n = np.sum(self.counts) self.colormap = colormap self.setMinimumSize(100, 50) def _validate_input(self, counts, colormap): if len(counts) != len(colormap): if len(colormap) != 3: msg = '''Colormap must be a list of 3-tuples the same length as counts or a 3-tuple''' raise ValueError(msg) def paintEvent(self, evt): # get the widget dimensions orig_width = self.width() orig_height = self.height() # fill perc % of the widget perc = 1 width = int(orig_width * perc) height = int(orig_height * perc) # get the starting origin x_orig = int((orig_width - width) / 2) # we want to start at the bottom and draw up. y_orig = orig_height - int((orig_height - height) / 2) # a running x-position running_pos = x_orig # calculate to number of bars nbars = len(self.counts) # calculate the bar widths, this compilcation is # necessary because integer trunction severly cripples # the layout. remainder = width % nbars bar_width = [int(width / nbars)] * nbars for i in range(remainder): bar_width[i] += 1 paint = QPainter() paint.begin(self) # determine the scaling factor max_val = np.max(self.counts) scale = 1. * height / max_val # determine if we have a colormap and drop into the appopriate # loop. if hasattr(self.colormap[0], '__iter__'): # assume we have a colormap for i in range(len(self.counts)): bar_height = self.counts[i] r, g, b = self.colormap[i] paint.setPen(QColor(r, g, b)) paint.setBrush(QColor(r, g, b)) paint.drawRect(running_pos, y_orig, bar_width[i], -bar_height) running_pos += bar_width[i] else: # we have a tuple r, g, b = self.colormap paint.setPen(QColor(r, g, b)) paint.setBrush(QColor(r, g, b)) for i in range(len(self.counts)): bar_height = self.counts[i] * scale paint.drawRect(running_pos, y_orig, bar_width[i], -bar_height) running_pos += bar_width[i] paint.end() def update_hist(self, counts, cmap): self._validate_input(counts, cmap) self.counts = counts self.colormap = cmap self.repaint() class QuadHistogram(QFrame): '''A class which uses ColorHistogram to draw the 4 histograms of an image. R, G, B, and Value. The 4 histograms are layout out in a grid, and can be specified horizontal or vertical, and in which order ie. ['R', 'G', 'B', 'V'] ''' def __init__(self, img, layout='vertical', order=['R', 'G', 'B', 'V']): QFrame.__init__(self) r, g, b, v = histograms(img, 100) self.r_hist = ColorHistogram(r, (255, 0, 0)) self.g_hist = ColorHistogram(g, (0, 255, 0)) self.b_hist = ColorHistogram(b, (0, 0, 255)) self.v_hist = ColorHistogram(v, (0, 0, 0)) self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.layout = QGridLayout(self) self.layout.setMargin(0) order_map = {'R': self.r_hist, 'G': self.g_hist, 'B': self.b_hist, 'V': self.v_hist} if layout == 'vertical': for i in range(len(order)): self.layout.addWidget(order_map[order[i]], i, 0) elif layout == 'horizontal': for i in range(len(order)): self.layout.addWidget(order_map[order[i]], 0, i) def update_hists(self, img): r, g, b, v = histograms(img, 100) self.r_hist.update_hist(r, (255, 0, 0)) self.g_hist.update_hist(g, (0, 255, 0)) self.b_hist.update_hist(b, (0, 0, 255)) self.v_hist.update_hist(v, (0, 0, 0)) scikit-image-0.9.3/skimage/io/_plugins/qt_plugin.ini000066400000000000000000000001511223313777300224500ustar00rootroot00000000000000[qt] description = Fast image display using the Qt library provides = imshow, _app_show, imsave, imread scikit-image-0.9.3/skimage/io/_plugins/qt_plugin.py000066400000000000000000000126111223313777300223250ustar00rootroot00000000000000from .util import prepare_for_display, window_manager import numpy as np # We try to aquire the gui lock first or else the gui import might # trample another GUI's PyOS_InputHook. window_manager.acquire('qt') try: from PyQt4.QtGui import (QApplication, QImage, QLabel, QMainWindow, QPixmap, QWidget) from PyQt4 import QtCore, QtGui import sip import warnings except ImportError: window_manager._release('qt') raise ImportError("""\ PyQt4 libraries not installed. Please refer to http://www.riverbankcomputing.co.uk/software/pyqt/intro for more information. PyQt4 is GPL licensed. For an LGPL equivalent, see http://www.pyside.org """) app = None class ImageLabel(QLabel): def __init__(self, parent, arr): QLabel.__init__(self) # we need to hold a reference to # arr because QImage doesn't copy the data # and the buffer must be alive as long # as the image is alive. self.arr = arr # we also need to pass in the row-stride to # the constructor, because we can't guarantee # that every row of the numpy data is # 4-byte aligned. Which Qt would require # if we didnt pass the stride. self.img = QImage(arr.data, arr.shape[1], arr.shape[0], arr.strides[0], QImage.Format_RGB888) self.pm = QPixmap.fromImage(self.img) self.setPixmap(self.pm) self.setAlignment(QtCore.Qt.AlignTop) self.setMinimumSize(100, 100) def resizeEvent(self, evt): width = self.width() pm = QPixmap.fromImage(self.img) self.pm = pm.scaledToWidth(width) self.setPixmap(self.pm) class ImageWindow(QMainWindow): def __init__(self, arr, mgr): QMainWindow.__init__(self) self.setWindowTitle('skimage') self.mgr = mgr self.main_widget = QWidget() self.layout = QtGui.QGridLayout(self.main_widget) self.setCentralWidget(self.main_widget) self.label = ImageLabel(self, arr) self.layout.addWidget(self.label, 0, 0) self.layout.addLayout self.mgr.add_window(self) self.main_widget.show() def closeEvent(self, event): # Allow window to be destroyed by removing any # references to it self.mgr.remove_window(self) def imread_qt(filename): """ Read an image using QT's QImage.load """ qtimg = QImage() if not qtimg.load(filename): # QImage.load() returns false on failure, so raise an exception raise IOError('Unable to load file %s' % filename) if qtimg.depth() == 1: raise IOError('1-bit images currently not supported') # TODO: Warn about other odd formats we don't currently handle properly, # such as the odd 16-bit packed formats QT supports arrayptr = qtimg.bits() # QT may pad the image, so we need to use bytesPerLine, not width for # the conversion to a numpy array bytesPerPixel = qtimg.depth() // 8 pixelsPerLine = qtimg.bytesPerLine() // bytesPerPixel img_size = pixelsPerLine * qtimg.height() * bytesPerPixel arrayptr.setsize(img_size) img = np.array(arrayptr) # Reshape and trim down to correct dimensions if bytesPerPixel > 1: img = img.reshape((qtimg.height(), pixelsPerLine, bytesPerPixel)) img = img[:, :qtimg.width(), :] else: img = img.reshape((qtimg.height(), pixelsPerLine)) img = img[:, :qtimg.width()] # Strip qt's false alpha channel if needed # and reorder color axes as required if bytesPerPixel == 4 and not qtimg.hasAlphaChannel(): img = img[:, :, 2::-1] elif bytesPerPixel == 4: img[:, :, 0:3] = img[:, :, 2::-1] return img if sip.SIP_VERSION >= 0x040c00: # sip.voidptr only acquired a buffer view in 4.12.0, so our imread # doesn't work with earlier versions imread = imread_qt else: warnings.warn(RuntimeWarning( "sip version too old. QT imread disabled")) def imshow(arr, fancy=False): global app if not app: app = QApplication([]) arr = prepare_for_display(arr) if not fancy: iw = ImageWindow(arr, window_manager) else: from .skivi import SkiviImageWindow iw = SkiviImageWindow(arr, window_manager) iw.show() def _app_show(): global app if app and window_manager.has_windows(): app.exec_() else: print('No images to show. See `imshow`.') def imsave(filename, img, format_str=None): # we can add support for other than 3D uint8 here... img = prepare_for_display(img) qimg = QImage(img.data, img.shape[1], img.shape[0], img.strides[0], QImage.Format_RGB888) if _is_filelike(filename): byte_array = QtCore.QByteArray() qbuffer = QtCore.QBuffer(byte_array) qbuffer.open(QtCore.QIODevice.ReadWrite) saved = qimg.save(qbuffer, format_str.upper()) qbuffer.seek(0) filename.write(qbuffer.readAll()) qbuffer.close() else: saved = qimg.save(filename) if not saved: from textwrap import dedent msg = dedent( '''The image was not saved. Allowable file formats for the QT imsave plugin are: BMP, JPG, JPEG, PNG, PPM, TIFF, XBM, XPM''') raise RuntimeError(msg) def _is_filelike(possible_filelike): return callable(getattr(possible_filelike, 'write', None)) scikit-image-0.9.3/skimage/io/_plugins/simpleitk_plugin.ini000066400000000000000000000001341223313777300240260ustar00rootroot00000000000000[simpleitk] description = Image reading and writing via SimpleITK provides = imread, imsave scikit-image-0.9.3/skimage/io/_plugins/simpleitk_plugin.py000066400000000000000000000011131223313777300236750ustar00rootroot00000000000000__all__ = ['imread', 'imsave'] try: import SimpleITK as sitk except ImportError: raise ImportError("SimpleITK could not be found. " "Please try " " easy_install SimpleITK " "or refer to " " http://simpleitk.org/ " "for further instructions.") def imread(fname): sitk_img = sitk.ReadImage(fname) return sitk.GetArrayFromImage(sitk_img) def imsave(fname, arr): sitk_img = sitk.GetImageFromArray(arr, isVector=True) sitk.WriteImage(sitk_img, fname) scikit-image-0.9.3/skimage/io/_plugins/skivi.py000066400000000000000000000173261223313777300214600ustar00rootroot00000000000000''' Skivi is written/maintained/developed by: S. Chris Colbert - sccolbert@gmail.com Skivi is free software and is part of the scikit-image project. Skivi is governed by the licenses of the scikit-image project. Please report any bugs to the author. The skivi module is not meant to be used directly. Use skimage.io.imshow(img, fancy=True)''' from textwrap import dedent from PyQt4 import QtCore, QtGui from PyQt4.QtGui import QMainWindow, QImage, QPixmap, QLabel, QWidget, QFrame from .q_color_mixer import MixerPanel from .q_histogram import QuadHistogram class ImageLabel(QLabel): def __init__(self, parent, arr): QLabel.__init__(self) self.parent = parent # we need to hold a reference to # arr because QImage doesn't copy the data # and the buffer must be alive as long # as the image is alive. self.arr = arr # we also need to pass in the row-stride to # the constructor, because we can't guarantee # that every row of the numpy data is # 4-byte aligned. Which Qt would require # if we didnt pass the stride. self.img = QImage(arr.data, arr.shape[1], arr.shape[0], arr.strides[0], QImage.Format_RGB888) self.pm = QPixmap.fromImage(self.img) self.setPixmap(self.pm) self.setAlignment(QtCore.Qt.AlignTop) self.setMinimumSize(100, 100) self.setMouseTracking(True) def mouseMoveEvent(self, evt): self.parent.label_mouseMoveEvent(evt) def resizeEvent(self, evt): width = self.width() pm = QPixmap.fromImage(self.img) self.pm = pm.scaledToWidth(width) self.setPixmap(self.pm) def update_image(self): width = self.width() pm = QPixmap.fromImage(self.img) pm = pm.scaledToWidth(width) self.setPixmap(pm) class RGBHSVDisplay(QFrame): def __init__(self): QFrame.__init__(self) self.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Sunken) self.posx_label = QLabel('X-pos:') self.posx_value = QLabel() self.posy_label = QLabel('Y-pos:') self.posy_value = QLabel() self.r_label = QLabel('R:') self.r_value = QLabel() self.g_label = QLabel('G:') self.g_value = QLabel() self.b_label = QLabel('B:') self.b_value = QLabel() self.h_label = QLabel('H:') self.h_value = QLabel() self.s_label = QLabel('S:') self.s_value = QLabel() self.v_label = QLabel('V:') self.v_value = QLabel() self.layout = QtGui.QGridLayout(self) self.layout.addWidget(self.posx_label, 0, 0) self.layout.addWidget(self.posx_value, 0, 1) self.layout.addWidget(self.posy_label, 1, 0) self.layout.addWidget(self.posy_value, 1, 1) self.layout.addWidget(self.r_label, 0, 2) self.layout.addWidget(self.r_value, 0, 3) self.layout.addWidget(self.g_label, 1, 2) self.layout.addWidget(self.g_value, 1, 3) self.layout.addWidget(self.b_label, 2, 2) self.layout.addWidget(self.b_value, 2, 3) self.layout.addWidget(self.h_label, 0, 4) self.layout.addWidget(self.h_value, 0, 5) self.layout.addWidget(self.s_label, 1, 4) self.layout.addWidget(self.s_value, 1, 5) self.layout.addWidget(self.v_label, 2, 4) self.layout.addWidget(self.v_value, 2, 5) def update_vals(self, data): xpos, ypos, r, g, b, h, s, v = data self.posx_value.setText(str(xpos)[:5]) self.posy_value.setText(str(ypos)[:5]) self.r_value.setText(str(r)[:5]) self.g_value.setText(str(g)[:5]) self.b_value.setText(str(b)[:5]) self.h_value.setText(str(h)[:5]) self.s_value.setText(str(s)[:5]) self.v_value.setText(str(v)[:5]) class SkiviImageWindow(QMainWindow): def __init__(self, arr, mgr): QMainWindow.__init__(self) self.arr = arr self.mgr = mgr self.main_widget = QWidget() self.layout = QtGui.QGridLayout(self.main_widget) self.setCentralWidget(self.main_widget) self.label = ImageLabel(self, arr) self.label_container = QFrame() self.label_container.setFrameShape( QtGui.QFrame.StyledPanel | QtGui.QFrame.Sunken) self.label_container.setLineWidth(1) self.label_container.layout = QtGui.QGridLayout(self.label_container) self.label_container.layout.setMargin(0) self.label_container.layout.addWidget(self.label, 0, 0) self.layout.addWidget(self.label_container, 0, 0) self.mgr.add_window(self) self.main_widget.show() self.setWindowTitle('Skivi - The skimage viewer.') self.mixer_panel = MixerPanel(self.arr) self.layout.addWidget(self.mixer_panel, 0, 2) self.mixer_panel.show() self.mixer_panel.set_callback(self.refresh_image) self.rgbv_hist = QuadHistogram(self.arr) self.layout.addWidget(self.rgbv_hist, 0, 1) self.rgbv_hist.show() self.rgb_hsv_disp = RGBHSVDisplay() self.layout.addWidget(self.rgb_hsv_disp, 1, 0) self.rgb_hsv_disp.show() self.layout.setColumnStretch(0, 1) self.layout.setRowStretch(0, 1) self.save_file = QtGui.QPushButton('Save to File') self.save_file.clicked.connect(self.save_to_file) self.save_stack = QtGui.QPushButton('Save to Stack') self.save_stack.clicked.connect(self.save_to_stack) self.save_file.show() self.save_stack.show() self.layout.addWidget(self.save_stack, 1, 1) self.layout.addWidget(self.save_file, 1, 2) def closeEvent(self, event): # Allow window to be destroyed by removing any # references to it self.mgr.remove_window(self) def update_histograms(self): self.rgbv_hist.update_hists(self.arr) def refresh_image(self): self.label.update_image() self.update_histograms() def scale_mouse_pos(self, x, y): width = self.label.pm.width() height = self.label.pm.height() x_frac = 1. * x / width y_frac = 1. * y / height width = self.arr.shape[1] height = self.arr.shape[0] new_x = int(width * x_frac) new_y = int(height * y_frac) return(new_x, new_y) def label_mouseMoveEvent(self, evt): x = evt.x() y = evt.y() x, y = self.scale_mouse_pos(x, y) # handle tracking out of array bounds maxw = self.arr.shape[1] maxh = self.arr.shape[0] if x >= maxw or y >= maxh or x < 0 or y < 0: r = g = b = h = s = v = '' else: r = self.arr[y, x, 0] g = self.arr[y, x, 1] b = self.arr[y, x, 2] h, s, v = self.mixer_panel.mixer.rgb_2_hsv_pixel(r, g, b) self.rgb_hsv_disp.update_vals((x, y, r, g, b, h, s, v)) def save_to_stack(self): from skimage import io img = self.arr.copy() io.push(img) msg = dedent(''' The image has been pushed to the io stack. Use io.pop() to retrieve the most recently pushed image.''') msglabel = QLabel(msg) dialog = QtGui.QDialog() ok = QtGui.QPushButton('OK', dialog) ok.clicked.connect(dialog.accept) ok.setDefault(True) dialog.layout = QtGui.QGridLayout(dialog) dialog.layout.addWidget(msglabel, 0, 0, 1, 3) dialog.layout.addWidget(ok, 1, 1) dialog.exec_() def save_to_file(self): from skimage import io filename = str(QtGui.QFileDialog.getSaveFileName()) if len(filename) == 0: return io.imsave(filename, self.arr) scikit-image-0.9.3/skimage/io/_plugins/test_plugin.ini000066400000000000000000000001261223313777300230050ustar00rootroot00000000000000[test] description = Test plugin provides = imsave, imshow, imread, imread_collection scikit-image-0.9.3/skimage/io/_plugins/test_plugin.py000066400000000000000000000007471223313777300226670ustar00rootroot00000000000000# This mock-up is called by ../tests/test_plugin.py # to verify the behaviour of the plugin infrastructure def imread(fname, dtype=None): assert fname == 'test.png' assert dtype == 'i4' def imsave(fname, arr): assert fname == 'test.png' assert arr == [1, 2, 3] def imshow(arr, plugin_arg=None): assert arr == [1, 2, 3] assert plugin_arg == (1, 2) def imread_collection(x, conserve_memory=True): assert conserve_memory == False assert x == '*.png' scikit-image-0.9.3/skimage/io/_plugins/tifffile_plugin.ini000066400000000000000000000001561223313777300236210ustar00rootroot00000000000000[tifffile] description = Load and save TIFF and TIFF-based images using tifffile.py provides = imread, imsave scikit-image-0.9.3/skimage/io/_plugins/tifffile_plugin.py000066400000000000000000000003431223313777300234700ustar00rootroot00000000000000try: from tifffile import imread, imsave except ImportError: raise ImportError("The tifffile module could not be found.\n" "It can be obtained at " "\n") scikit-image-0.9.3/skimage/io/_plugins/util.py000066400000000000000000000313701223313777300213030ustar00rootroot00000000000000import numpy as np from . import _colormixer from . import _histograms import threading from skimage.util import img_as_ubyte # utilities to make life easier for plugin writers. try: import multiprocessing CPU_COUNT = multiprocessing.cpu_count() except: CPU_COUNT = 2 class GuiLockError(Exception): def __init__(self, msg): self.msg = msg def __str__(self): return self.msg class WindowManager(object): ''' A class to keep track of spawned windows, and make any needed callback once all the windows, are closed.''' def __init__(self): self._windows = [] self._callback = None self._callback_args = () self._callback_kwargs = {} self._gui_lock = False self._guikit = '' def _check_locked(self): if not self._gui_lock: raise GuiLockError(\ 'Must first acquire the gui lock before using this image manager') def _exec_callback(self): if self._callback: self._callback(*self._callback_args, **self._callback_kwargs) def acquire(self, kit): if self._gui_lock: raise GuiLockError(\ 'The gui lock can only be acquired by one toolkit per session. \ The lock is already aquired by %s' % self._guikit) else: self._gui_lock = True self._guikit = str(kit) def _release(self, kit): # releaseing the lock will lose all references to currently # tracked images and the callback. # this function is private for reason! self._check_locked() if str(kit) == self._guikit: self._windows = [] self._callback = None self._callback_args = () self._callback_kwargs = {} self._gui_lock = False self._guikit = '' else: raise RuntimeError('Only the toolkit that owns the lock may ' 'release it') def add_window(self, win): self._check_locked() self._windows.append(win) def remove_window(self, win): self._check_locked() try: self._windows.remove(win) except ValueError: print('Unable to find referenced window in tracked windows.') print('Ignoring...') else: if len(self._windows) == 0: self._exec_callback() def register_callback(self, cb, *cbargs, **cbkwargs): self._check_locked() self._callback = cb self._callback_args = cbargs self._callback_kwargs = cbkwargs def has_windows(self): if len(self._windows) > 0: return True else: return False window_manager = WindowManager() def prepare_for_display(npy_img): '''Convert a 2D or 3D numpy array of any dtype into a 3D numpy array with dtype uint8. This array will be suitable for use in passing to gui toolkits for image display purposes. Parameters ---------- npy_img : ndarray, 2D or 3D The image to convert for display Returns ------- out : ndarray, 3D dtype=np.uint8 The converted image. This is guaranteed to be a contiguous array. Notes ----- If the input image is floating point, it is assumed that the data is in the range of 0.0 - 1.0. No check is made to assert this condition. The image is then scaled to be in the range 0 - 255 and then cast to np.uint8 For all other dtypes, the array is simply cast to np.uint8 If a 2D array is passed, the single channel is replicated to the 2nd and 3rd channels. If the array contains an alpha channel, this channel is ignored. ''' if npy_img.ndim < 2: raise ValueError('Image must be 2D or 3D array') height = npy_img.shape[0] width = npy_img.shape[1] out = np.empty((height, width, 3), dtype=np.uint8) npy_img = img_as_ubyte(npy_img) if npy_img.ndim == 2 or \ (npy_img.ndim == 3 and npy_img.shape[2] == 1): npy_plane = npy_img.reshape((height, width)) out[:, :, 0] = npy_plane out[:, :, 1] = npy_plane out[:, :, 2] = npy_plane elif npy_img.ndim == 3: if npy_img.shape[2] == 3 or npy_img.shape[2] == 4: out[:, :, :3] = npy_img[:, :, :3] else: raise ValueError('Image must have 1, 3, or 4 channels') else: raise ValueError('Image must have 2 or 3 dimensions') return out def histograms(img, nbins): '''Calculate the channel histograms of the current image. Parameters ---------- img : ndarray, ndim=3, dtype=np.uint8 nbins : int The number of bins. Returns ------- out : (rcounts, gcounts, bcounts, vcounts) The binned histograms of the RGB channels and intensity values. This is a NAIVE histogram routine, meant primarily for fast display. ''' return _histograms.histograms(img, nbins) class ImgThread(threading.Thread): def __init__(self, func, *args): super(ImgThread, self).__init__() self.func = func self.args = args def run(self): self.func(*self.args) class ThreadDispatch(object): def __init__(self, img, stateimg, func, *args): height = img.shape[0] self.cores = CPU_COUNT self.threads = [] self.chunks = [] if self.cores == 1: self.chunks.append((img, stateimg)) elif self.cores >= 4: self.chunks.append((img[:(height / 4), :, :], stateimg[:(height / 4), :, :])) self.chunks.append((img[(height / 4):(height / 2), :, :], stateimg[(height / 4):(height / 2), :, :])) self.chunks.append((img[(height / 2):(3 * height / 4), :, :], stateimg[(height / 2):(3 * height / 4), :, :])) self.chunks.append((img[(3 * height / 4):, :, :], stateimg[(3 * height / 4):, :, :])) # if they dont have 1, or 4 or more, 2 is good. else: self.chunks.append((img[:(height / 2), :, :], stateimg[:(height / 2), :, :])) self.chunks.append((img[(height / 2):, :, :], stateimg[(height / 2):, :, :])) for i in range(len(self.chunks)): self.threads.append(ImgThread(func, self.chunks[i][0], self.chunks[i][1], *args)) def run(self): for t in self.threads: t.start() for t in self.threads: t.join() class ColorMixer(object): ''' a class to manage mixing colors in an image. The input array must be an RGB uint8 image. The mixer maintains an original copy of the image, and uses this copy to query the pixel data for operations. It also makes a copy for sharing state across operations. That is, if you add to a channel, and multiply to same channel, the two operations are carried separately and the results averaged together. it modifies your array in place. This ensures that if you bust over a threshold, you can always come back down. The passed values to a function are always considered absolute. Thus to threshold a channel completely you can do mixer.add(RED, 255). Or to double the intensity of the blue channel: mixer.multiply(BLUE, 2.) To reverse these operations, respectively: mixer.add(RED, 0), mixer.multiply(BLUE, 1.) The majority of the backend is implemented in Cython, so it should be quite quick. ''' RED = 0 GREEN = 1 BLUE = 2 valid_channels = [RED, GREEN, BLUE] def __init__(self, img): if type(img) != np.ndarray: raise ValueError('Image must be a numpy array') if img.dtype != np.uint8: raise ValueError('Image must have dtype uint8') if img.ndim != 3 or img.shape[2] != 3: raise ValueError('Image must be 3 channel MxNx3') self.img = img self.origimg = img.copy() self.stateimg = img.copy() def get_stateimage(self): return self.stateimg def commit_changes(self): self.stateimg[:] = self.img[:] def revert(self): self.stateimg[:] = self.origimg[:] self.img[:] = self.stateimg[:] def set_to_stateimg(self): self.img[:] = self.stateimg[:] def add(self, channel, ammount): '''Add the specified ammount to the specified channel. Parameters ---------- channel : flag the color channel to operate on RED, GREED, or BLUE ammount : integer the ammount of color to add to the channel, can be positive or negative. ''' assert channel in self.valid_channels pool = ThreadDispatch(self.img, self.stateimg, _colormixer.add, channel, ammount) pool.run() def multiply(self, channel, ammount): '''Mutliply the indicated channel by the specified value. Parameters ---------- channel : flag the color channel to operate on RED, GREED, or BLUE ammount : integer the ammount of color to add to the channel, can be positive or negative. ''' assert channel in self.valid_channels pool = ThreadDispatch(self.img, self.stateimg, _colormixer.multiply, channel, ammount) pool.run() def brightness(self, factor, offset): '''Adjust the brightness off an image with an offset and factor. Parameters ---------- offset : integer The ammount to add to each channel. factor : float The factor to multiply each channel by. result = clip((pixel + offset)*factor) ''' pool = ThreadDispatch(self.img, self.stateimg, _colormixer.brightness, factor, offset) pool.run() def sigmoid_gamma(self, alpha, beta): pool = ThreadDispatch(self.img, self.stateimg, _colormixer.sigmoid_gamma, alpha, beta) pool.run() def gamma(self, gamma): pool = ThreadDispatch(self.img, self.stateimg, _colormixer.gamma, gamma) pool.run() def hsv_add(self, h_amt, s_amt, v_amt): '''Adjust the H, S, V channels of an image by a constant ammount. This is similar to the add() mixer function, but operates over the entire image at once. Thus all three additive values, H, S, V, must be supplied simultaneously. Parameters ---------- h_amt : float The ammount to add to the hue (-180..180) s_amt : float The ammount to add to the saturation (-1..1) v_amt : float The ammount to add to the value (-1..1) ''' pool = ThreadDispatch(self.img, self.stateimg, _colormixer.hsv_add, h_amt, s_amt, v_amt) pool.run() def hsv_multiply(self, h_amt, s_amt, v_amt): '''Adjust the H, S, V channels of an image by a constant ammount. This is similar to the add() mixer function, but operates over the entire image at once. Thus all three additive values, H, S, V, must be supplied simultaneously. Note that since hue is in degrees, it makes no sense to multiply that channel, thus an add operation is performed on the hue. And the values given for h_amt, should be the same as for hsv_add Parameters ---------- h_amt : float The ammount to to add to the hue (-180..180) s_amt : float The ammount to multiply to the saturation (0..1) v_amt : float The ammount to multiply to the value (0..1) ''' pool = ThreadDispatch(self.img, self.stateimg, _colormixer.hsv_multiply, h_amt, s_amt, v_amt) pool.run() def rgb_2_hsv_pixel(self, R, G, B): '''Convert an RGB value to HSV Parameters ---------- R : int Red value G : int Green value B : int Blue value Returns ------- out : (H, S, V) Floats The HSV values ''' H, S, V = _colormixer.py_rgb_2_hsv(R, G, B) return (H, S, V) def hsv_2_rgb_pixel(self, H, S, V): '''Convert an HSV value to RGB Parameters ---------- H : float Hue value S : float Saturation value V : float Intensity value Returns ------- out : (R, G, B) ints The RGB values ''' R, G, B = _colormixer.py_hsv_2_rgb(H, S, V) return (R, G, B) scikit-image-0.9.3/skimage/io/collection.py000066400000000000000000000277411223313777300206500ustar00rootroot00000000000000"""Data structures to hold collections of images, with optional caching.""" from __future__ import with_statement __all__ = ['MultiImage', 'ImageCollection', 'imread', 'concatenate_images'] from glob import glob import re from copy import copy import numpy as np from ._io import imread from .._shared import six def concatenate_images(ic): """Concatenate all images in the image collection into an array. Parameters ---------- ic: an iterable of images (including ImageCollection and MultiImage) The images to be concatenated. Returns ------- ar : np.ndarray An array having one more dimension than the images in `ic`. See Also -------- ImageCollection.concatenate, MultiImage.concatenate Raises ------ ValueError If images in `ic` don't have identical shapes. """ all_images = [img[np.newaxis, ...] for img in ic] try: ar = np.concatenate(all_images) except ValueError: raise ValueError('Image dimensions must agree.') return ar def alphanumeric_key(s): """Convert string to list of strings and ints that gives intuitive sorting. Parameters ---------- s: string Returns ------- k: a list of strings and ints Examples -------- >>> alphanumeric_key('z23a') ['z', 23, 'a'] >>> filenames = ['f9.10.png', 'e10.png', 'f9.9.png', 'f10.10.png', ... 'f10.9.png'] >>> sorted(filenames) ['e10.png', 'f10.10.png', 'f10.9.png', 'f9.10.png', 'f9.9.png'] >>> sorted(filenames, key=alphanumeric_key) ['e10.png', 'f9.9.png', 'f9.10.png', 'f10.9.png', 'f10.10.png'] """ k = [int(c) if c.isdigit() else c for c in re.split('([0-9]+)', s)] return k class MultiImage(object): """A class containing a single multi-frame image. Parameters ---------- filename : str The complete path to the image file. conserve_memory : bool, optional Whether to conserve memory by only caching a single frame. Default is True. Notes ----- If ``conserve_memory=True`` the memory footprint can be reduced, however the performance can be affected because frames have to be read from file more often. The last accessed frame is cached, all other frames will have to be read from file. The current implementation makes use of PIL. Examples -------- >>> from skimage import data_dir >>> img = MultiImage(data_dir + '/multipage.tif') >>> len(img) 2 >>> for frame in img: ... print(frame.shape) (15, 10) (15, 10) The two frames in this image can be shown with matplotlib: .. plot:: show_collection.py """ def __init__(self, filename, conserve_memory=True, dtype=None): """Load a multi-img.""" self._filename = filename self._conserve_memory = conserve_memory self._dtype = dtype self._cached = None from PIL import Image img = Image.open(self._filename) if self._conserve_memory: self._numframes = self._find_numframes(img) else: self._frames = self._getallframes(img) self._numframes = len(self._frames) @property def filename(self): return self._filename @property def conserve_memory(self): return self._conserve_memory def _find_numframes(self, img): """Find the number of frames in the multi-img.""" i = 0 while True: i += 1 try: img.seek(i) except EOFError: break return i def _getframe(self, framenum): """Open the image and extract the frame.""" from PIL import Image img = Image.open(self.filename) img.seek(framenum) return np.asarray(img, dtype=self._dtype) def _getallframes(self, img): """Extract all frames from the multi-img.""" frames = [] try: i = 0 while True: frames.append(np.asarray(img, dtype=self._dtype)) i += 1 img.seek(i) except EOFError: return frames def __getitem__(self, n): """Return the n-th frame as an array. Parameters ---------- n : int Number of the required frame. Returns ------- frame : ndarray The n-th frame. """ numframes = self._numframes if -numframes <= n < numframes: n = n % numframes else: raise IndexError("There are only %s frames in the image" % numframes) if self.conserve_memory: if not self._cached == n: frame = self._getframe(n) self._cached = n self._cachedframe = frame return self._cachedframe else: return self._frames[n] def __iter__(self): """Iterate over the frames.""" for i in range(len(self)): yield self[i] def __len__(self): """Number of images in collection.""" return self._numframes def __str__(self): return str(self.filename) + ' [%s frames]' % self._numframes def concatenate(self): """Concatenate all images in the multi-image into an array. Returns ------- ar : np.ndarray An array having one more dimension than the images in `self`. See Also -------- concatenate_images Raises ------ ValueError If images in the `MultiImage` don't have identical shapes. """ return concatenate_images(self) class ImageCollection(object): """Load and manage a collection of image files. Note that files are always stored in alphabetical order. Also note that slicing returns a new ImageCollection, *not* a view into the data. Parameters ---------- load_pattern : str or list Pattern glob or filenames to load. The path can be absolute or relative. Multiple patterns should be separated by a colon, e.g. '/tmp/work/*.png:/tmp/other/*.jpg'. Also see implementation notes below. conserve_memory : bool, optional If True, never keep more than one in memory at a specific time. Otherwise, images will be cached once they are loaded. Other parameters ---------------- load_func : callable ``imread`` by default. See notes below. Attributes ---------- files : list of str If a glob string is given for `load_pattern`, this attribute stores the expanded file list. Otherwise, this is simply equal to `load_pattern`. Notes ----- ImageCollection can be modified to load images from an arbitrary source by specifying a combination of `load_pattern` and `load_func`. For an ImageCollection ``ic``, ``ic[5]`` uses ``load_func(file_pattern[5])`` to load the image. Imagine, for example, an ImageCollection that loads every tenth frame from a video file:: class AVILoader: video_file = 'myvideo.avi' def __call__(self, frame): return video_read(self.video_file, frame) avi_load = AVILoader() frames = range(0, 1000, 10) # 0, 10, 20, ... ic = ImageCollection(frames, load_func=avi_load) x = ic[5] # calls avi_load(frames[5]) or equivalently avi_load(50) Another use of ``load_func`` would be to convert all images to ``uint8``:: def imread_convert(f): return imread(f).astype(np.uint8) ic = ImageCollection('/tmp/*.png', load_func=imread_convert) Examples -------- >>> import skimage.io as io >>> from skimage import data_dir >>> coll = io.ImageCollection(data_dir + '/lena*.png') >>> len(coll) 2 >>> coll[0].shape (512, 512, 3) >>> ic = io.ImageCollection('/tmp/work/*.png:/tmp/other/*.jpg') """ def __init__(self, load_pattern, conserve_memory=True, load_func=None): """Load and manage a collection of images.""" if isinstance(load_pattern, six.string_types): load_pattern = load_pattern.split(':') self._files = [] for pattern in load_pattern: self._files.extend(glob(pattern)) self._files = sorted(self._files, key=alphanumeric_key) else: self._files = load_pattern if conserve_memory: memory_slots = 1 else: memory_slots = len(self._files) self._conserve_memory = conserve_memory self._cached = None if load_func is None: self.load_func = imread else: self.load_func = load_func self.data = np.empty(memory_slots, dtype=object) @property def files(self): return self._files @property def conserve_memory(self): return self._conserve_memory def __getitem__(self, n): """Return selected image(s) in the collection. Loading is done on demand. Parameters ---------- n : int or slice The image number to be returned, or a slice selecting the images and ordering to be returned in a new ImageCollection. Returns ------- img : ndarray or ImageCollection. The `n`-th image in the collection, or a new ImageCollection with the selected images. """ if hasattr(n, '__index__'): n = n.__index__() if type(n) not in [int, slice]: raise TypeError('slicing must be with an int or slice object') if type(n) is int: n = self._check_imgnum(n) idx = n % len(self.data) if (self.conserve_memory and n != self._cached) or \ (self.data[idx] is None): self.data[idx] = self.load_func(self.files[n]) self._cached = n return self.data[idx] else: # A slice object was provided, so create a new ImageCollection # object. Any loaded image data in the original ImageCollection # will be copied by reference to the new object. Image data # loaded after this creation is not linked. fidx = range(len(self.files))[n] new_ic = copy(self) new_ic._files = [self.files[i] for i in fidx] if self.conserve_memory: if self._cached in fidx: new_ic._cached = fidx.index(self._cached) new_ic.data = np.copy(self.data) else: new_ic.data = np.empty(1, dtype=object) else: new_ic.data = self.data[fidx] return new_ic def _check_imgnum(self, n): """Check that the given image number is valid.""" num = len(self.files) if -num <= n < num: n = n % num else: raise IndexError("There are only %s images in the collection" % num) return n def __iter__(self): """Iterate over the images.""" for i in range(len(self)): yield self[i] def __len__(self): """Number of images in collection.""" return len(self.files) def __str__(self): return str(self.files) def reload(self, n=None): """Clear the image cache. Parameters ---------- n : None or int Clear the cache for this image only. By default, the entire cache is erased. """ self.data = np.empty_like(self.data) def concatenate(self): """Concatenate all images in the collection into an array. Returns ------- ar : np.ndarray An array having one more dimension than the images in `self`. See Also -------- concatenate_images Raises ------ ValueError If images in the `ImageCollection` don't have identical shapes. """ return concatenate_images(self) scikit-image-0.9.3/skimage/io/setup.py000066400000000000000000000025511223313777300176450ustar00rootroot00000000000000#!/usr/bin/env python from skimage._build import cython import os.path base_path = os.path.abspath(os.path.dirname(__file__)) def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs config = Configuration('io', parent_package, top_path) config.add_data_dir('tests') config.add_data_files('_plugins/*.ini') # This function tries to create C files from the given .pyx files. If # it fails, we build the checked-in .c files. cython(['_plugins/_colormixer.pyx', '_plugins/_histograms.pyx'], working_path=base_path) config.add_extension('_plugins._colormixer', sources=['_plugins/_colormixer.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_plugins._histograms', sources=['_plugins/_histograms.c'], include_dirs=[get_numpy_include_dirs()]) return config if __name__ == '__main__': from numpy.distutils.core import setup setup(maintainer='scikit-image Developers', maintainer_email='scikit-image@googlegroups.com', description='Image I/O Routines', url='https://github.com/scikit-image/scikit-image', license='Modified BSD', **(configuration(top_path='').todict()) ) scikit-image-0.9.3/skimage/io/sift.py000066400000000000000000000035241223313777300174530ustar00rootroot00000000000000"""Read SIFT and SURF feature files. See Also -------- http://people.cs.ubc.ca/~lowe/keypoints/ http://www.vision.ee.ethz.ch/~surf/ """ __all__ = ['load_sift', 'load_surf'] import numpy as np def _sift_read(f, mode='SIFT'): """Read SIFT or SURF features from a file. Parameters ---------- f : string or open file Input file generated by the feature detectors from http://people.cs.ubc.ca/~lowe/keypoints/ or http://www.vision.ee.ethz.ch/~surf/ Returns ------- data : record array with fields - row: int row position of feature - column: int column position of feature - scale: float feature scale - orientation: float feature orientation - data: array feature values """ if not hasattr(f, 'readline'): f = file(f, 'r') if mode == 'SIFT': nr_features, feature_len = map(int, f.readline().split()) datatype = np.dtype([('row', float), ('column', float), ('scale', float), ('orientation', float), ('data', (float, feature_len))]) else: mode = 'SURF' feature_len = int(f.readline()) - 1 nr_features = int(f.readline()) datatype = np.dtype([('column', float), ('row', float), ('second_moment', (float, 3)), ('sign', float), ('data', (float, feature_len))]) data = np.fromfile(f, sep=' ') if data.size != nr_features * datatype.itemsize / np.dtype(float).itemsize: raise IOError("Invalid %s feature file." % mode) return data.view(datatype) def load_sift(f): return _sift_read(f, mode='SIFT') def load_surf(f): return _sift_read(f, mode='SURF') load_sift.__doc__ = _sift_read.__doc__ load_surf.__doc__ = _sift_read.__doc__ scikit-image-0.9.3/skimage/io/tests/000077500000000000000000000000001223313777300172725ustar00rootroot00000000000000scikit-image-0.9.3/skimage/io/tests/test_collection.py000066400000000000000000000121561223313777300230430ustar00rootroot00000000000000import sys import os.path import numpy as np from numpy.testing import (assert_raises, assert_equal, assert_array_almost_equal, ) from numpy.testing.decorators import skipif from skimage import data_dir from skimage.io import ImageCollection, MultiImage from skimage.io.collection import alphanumeric_key from skimage.io import Image as ioImage from skimage._shared import six try: from PIL import Image except ImportError: PIL_available = False else: PIL_available = True class TestAlphanumericKey(): def setUp(self): self.test_string = 'z23a' self.test_str_result = ['z', 23, 'a'] self.filenames = ['f9.10.png', 'f9.9.png', 'f10.10.png', 'f10.9.png', 'e9.png', 'e10.png', 'em.png'] self.sorted_filenames = \ ['e9.png', 'e10.png', 'em.png', 'f9.9.png', 'f9.10.png', 'f10.9.png', 'f10.10.png'] def test_string_split(self): assert_equal(alphanumeric_key(self.test_string), self.test_str_result) def test_string_sort(self): sorted_filenames = sorted(self.filenames, key=alphanumeric_key) assert_equal(sorted_filenames, self.sorted_filenames) class TestImageCollection(): pattern = [os.path.join(data_dir, pic) for pic in ['camera.png', 'color.png']] pattern_matched = [os.path.join(data_dir, pic) for pic in ['camera.png', 'moon.png']] def setUp(self): self.collection = ImageCollection(self.pattern) self.collection_matched = ImageCollection(self.pattern_matched) def test_len(self): assert len(self.collection) == 2 def test_getitem(self): num = len(self.collection) for i in range(-num, num): assert type(self.collection[i]) is np.ndarray assert_array_almost_equal(self.collection[0], self.collection[-num]) #assert_raises expects a callable, hence this do-very-little func def return_img(n): return self.collection[n] assert_raises(IndexError, return_img, num) assert_raises(IndexError, return_img, -num - 1) def test_slicing(self): assert type(self.collection[:]) is ImageCollection assert len(self.collection[:]) == 2 assert len(self.collection[:1]) == 1 assert len(self.collection[1:]) == 1 assert_array_almost_equal(self.collection[0], self.collection[:1][0]) assert_array_almost_equal(self.collection[1], self.collection[1:][0]) assert_array_almost_equal(self.collection[1], self.collection[::-1][0]) assert_array_almost_equal(self.collection[0], self.collection[::-1][1]) def test_files_property(self): assert isinstance(self.collection.files, list) def set_files(f): self.collection.files = f assert_raises(AttributeError, set_files, 'newfiles') def test_custom_load(self): load_pattern = [(1, 'one'), (2, 'two')] def load_fn(x): return x ic = ImageCollection(load_pattern, load_func=load_fn) assert_equal(ic[1], (2, 'two')) def test_concatenate(self): ar = self.collection_matched.concatenate() assert_equal(ar.shape, (len(self.collection_matched),) + self.collection[0].shape) assert_raises(ValueError, self.collection.concatenate) class TestMultiImage(): def setUp(self): # This multipage TIF file was created with imagemagick: # convert im1.tif im2.tif -adjoin multipage.tif if PIL_available: self.img = MultiImage(os.path.join(data_dir, 'multipage.tif')) @skipif(not PIL_available) def test_len(self): assert len(self.img) == 2 @skipif(not PIL_available) def test_getitem(self): num = len(self.img) for i in range(-num, num): assert type(self.img[i]) is np.ndarray assert_array_almost_equal(self.img[0], self.img[-num]) #assert_raises expects a callable, hence this do-very-little func def return_img(n): return self.img[n] assert_raises(IndexError, return_img, num) assert_raises(IndexError, return_img, -num - 1) @skipif(not PIL_available) def test_files_property(self): assert isinstance(self.img.filename, six.string_types) def set_filename(f): self.img.filename = f assert_raises(AttributeError, set_filename, 'newfile') @skipif(not PIL_available) def test_conserve_memory_property(self): assert isinstance(self.img.conserve_memory, bool) def set_mem(val): self.img.conserve_memory = val assert_raises(AttributeError, set_mem, True) @skipif(not PIL_available) def test_concatenate(self): ar = self.img.concatenate() assert_equal(ar.shape, (len(self.img),) + self.img[0].shape) if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_colormixer.py000066400000000000000000000110131223313777300230620ustar00rootroot00000000000000from numpy.testing import (assert_array_equal, assert_almost_equal, assert_equal, assert_array_almost_equal, ) import numpy as np import skimage.io._plugins._colormixer as cm class ColorMixerTest(object): def setup(self): self.state = np.ones((18, 33, 3), dtype=np.uint8) * 200 self.img = np.zeros_like(self.state) def test_basic(self): self.op(self.img, self.state, 0, self.positive) assert_array_equal(self.img[..., 0], self.py_op(self.state[..., 0], self.positive)) def test_clip(self): self.op(self.img, self.state, 0, self.positive_clip) assert_array_equal(self.img[..., 0], np.ones_like(self.img[..., 0]) * 255) def test_negative(self): self.op(self.img, self.state, 0, self.negative) assert_array_equal(self.img[..., 0], self.py_op(self.state[..., 0], self.negative)) def test_negative_clip(self): self.op(self.img, self.state, 0, self.negative_clip) assert_array_equal(self.img[..., 0], np.zeros_like(self.img[..., 0])) class TestColorMixerAdd(ColorMixerTest): op = cm.add py_op = np.add positive = 50 positive_clip = 56 negative = -50 negative_clip = -220 class TestColorMixerMul(ColorMixerTest): op = cm.multiply py_op = np.multiply positive = 1.2 positive_clip = 2 negative = 0.5 negative_clip = -0.5 class TestColorMixerBright(object): def setup(self): self.state = np.ones((18, 33, 3), dtype=np.uint8) * 200 self.img = np.zeros_like(self.state) def test_brightness_pos(self): cm.brightness(self.img, self.state, 1.25, 1) assert_array_equal(self.img, np.ones_like(self.img) * 251) def test_brightness_neg(self): cm.brightness(self.img, self.state, 0.5, -50) assert_array_equal(self.img, np.ones_like(self.img) * 50) def test_brightness_pos_clip(self): cm.brightness(self.img, self.state, 2, 0) assert_array_equal(self.img, np.ones_like(self.img) * 255) def test_brightness_neg_clip(self): cm.brightness(self.img, self.state, 0, 0) assert_array_equal(self.img, np.zeros_like(self.img)) class TestColorMixer(object): def setup(self): self.state = np.ones((18, 33, 3), dtype=np.uint8) * 50 self.img = np.zeros_like(self.state) def test_sigmoid(self): import math alpha = 1.5 beta = 1.5 c1 = 1 / (1 + math.exp(beta)) c2 = 1 / (1 + math.exp(beta - alpha)) - c1 state = self.state / 255. cm.sigmoid_gamma(self.img, self.state, alpha, beta) img = 1 / (1 + np.exp(beta - state * alpha)) img = np.asarray((img - c1) / c2 * 255, dtype='uint8') assert_almost_equal(img, self.img) def test_gamma(self): gamma = 1.5 cm.gamma(self.img, self.state, gamma) img = np.asarray(((self.state / 255.)**(1 / gamma)) * 255, dtype='uint8') assert_array_almost_equal(img, self.img) def test_rgb_2_hsv(self): r = 255 g = 0 b = 0 h, s, v = cm.py_rgb_2_hsv(r, g, b) assert_almost_equal(np.array([h]), np.array([0])) assert_almost_equal(np.array([s]), np.array([1])) assert_almost_equal(np.array([v]), np.array([1])) def test_hsv_2_rgb(self): h = 0 s = 1 v = 1 r, g, b = cm.py_hsv_2_rgb(h, s, v) assert_almost_equal(np.array([r]), np.array([255])) assert_almost_equal(np.array([g]), np.array([0])) assert_almost_equal(np.array([b]), np.array([0])) def test_hsv_add(self): cm.hsv_add(self.img, self.state, 360, 0, 0) assert_almost_equal(self.img, self.state) def test_hsv_add_clip_neg(self): cm.hsv_add(self.img, self.state, 0, 0, -1) assert_equal(self.img, np.zeros_like(self.state)) def test_hsv_add_clip_pos(self): cm.hsv_add(self.img, self.state, 0, 0, 1) assert_equal(self.img, np.ones_like(self.state) * 255) def test_hsv_mul(self): cm.hsv_multiply(self.img, self.state, 360, 1, 1) assert_almost_equal(self.img, self.state) def test_hsv_mul_clip_neg(self): cm.hsv_multiply(self.img, self.state, 0, 0, 0) assert_equal(self.img, np.zeros_like(self.state)) if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_fits.py000066400000000000000000000046331223313777300216560ustar00rootroot00000000000000import os.path import numpy as np from numpy.testing import run_module_suite from numpy.testing.decorators import skipif import skimage.io as io from skimage import data_dir pyfits_available = True try: import pyfits except ImportError: pyfits_available = False else: import skimage.io._plugins.fits_plugin as fplug def test_fits_plugin_import(): # Make sure we get an import exception if PyFITS isn't there # (not sure how useful this is, but it ensures there isn't some other # error when trying to load the plugin) try: io.use_plugin('fits') except ImportError: assert pyfits_available == False else: assert pyfits_available == True def teardown(): io.reset_plugins() @skipif(not pyfits_available) def test_imread_MEF(): io.use_plugin('fits') testfile = os.path.join(data_dir, 'multi.fits') img = io.imread(testfile) assert np.all(img == pyfits.getdata(testfile, 1)) @skipif(not pyfits_available) def test_imread_simple(): io.use_plugin('fits') testfile = os.path.join(data_dir, 'simple.fits') img = io.imread(testfile) assert np.all(img == pyfits.getdata(testfile, 0)) @skipif(not pyfits_available) def test_imread_collection_single_MEF(): io.use_plugin('fits') testfile = os.path.join(data_dir, 'multi.fits') ic1 = io.imread_collection(testfile) ic2 = io.ImageCollection([(testfile, 1), (testfile, 2), (testfile, 3)], load_func=fplug.FITSFactory) assert _same_ImageCollection(ic1, ic2) @skipif(not pyfits_available) def test_imread_collection_MEF_and_simple(): io.use_plugin('fits') testfile1 = os.path.join(data_dir, 'multi.fits') testfile2 = os.path.join(data_dir, 'simple.fits') ic1 = io.imread_collection([testfile1, testfile2]) ic2 = io.ImageCollection([(testfile1, 1), (testfile1, 2), (testfile1, 3), (testfile2, 0)], load_func=fplug.FITSFactory) assert _same_ImageCollection(ic1, ic2) def _same_ImageCollection(collection1, collection2): """Ancillary function to compare two ImageCollection objects, checking that their constituent arrays are equal. """ if len(collection1) != len(collection2): return False for ext1, ext2 in zip(collection1, collection2): if not np.all(ext1 == ext2): return False return True if __name__ == '__main__': run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_freeimage.py000066400000000000000000000062751223313777300226410ustar00rootroot00000000000000import os import skimage as si import skimage.io as sio import numpy as np from numpy.testing import * from numpy.testing.decorators import skipif from tempfile import NamedTemporaryFile try: import skimage.io._plugins.freeimage_plugin as fi FI_available = True sio.use_plugin('freeimage') except RuntimeError: FI_available = False def setup_module(self): """The effect of the `plugin.use` call may be overridden by later imports. Call `use_plugin` directly before the tests to ensure that freeimage is used. """ try: sio.use_plugin('freeimage') except RuntimeError: pass def teardown(): sio.reset_plugins() @skipif(not FI_available) def test_imread(): img = sio.imread(os.path.join(si.data_dir, 'color.png')) assert img.shape == (370, 371, 3) assert all(img[274, 135] == [0, 130, 253]) @skipif(not FI_available) def test_imread_uint16(): expected = np.load(os.path.join(si.data_dir, 'chessboard_GRAY_U8.npy')) img = sio.imread(os.path.join(si.data_dir, 'chessboard_GRAY_U16.tif')) assert img.dtype == np.uint16 assert_array_almost_equal(img, expected) @skipif(not FI_available) def test_imread_uint16_big_endian(): expected = np.load(os.path.join(si.data_dir, 'chessboard_GRAY_U8.npy')) img = sio.imread(os.path.join(si.data_dir, 'chessboard_GRAY_U16B.tif')) assert img.dtype == np.uint16 assert_array_almost_equal(img, expected) @skipif(not FI_available) def test_write_multipage(): shape = (64,64,64) x = np.ones(shape, dtype=np.uint8) * np.random.random(shape) * 255 x = x.astype(np.uint8) f = NamedTemporaryFile(suffix='.tif') fname = f.name f.close() fi.write_multipage(x, fname) y = fi.read_multipage(fname) assert_array_equal(x, y) class TestSave: def roundtrip(self, dtype, x, suffix): f = NamedTemporaryFile(suffix='.' + suffix) fname = f.name f.close() sio.imsave(fname, x) y = sio.imread(fname) assert_array_equal(x, y) @skipif(not FI_available) def test_imsave_roundtrip(self): for shape, dtype, format in [ [(10, 10), (np.uint8, np.uint16), ('tif', 'png')], [(10, 10), (np.float32,), ('tif',)], [(10, 10, 3), (np.uint8,), ('png',)], [(10, 10, 4), (np.uint8,), ('png',)] ]: tests = [(d, f) for d in dtype for f in format] for d, f in tests: x = np.ones(shape, dtype=d) * np.random.random(shape) if not np.issubdtype(d, float): x = (x * 255).astype(d) yield self.roundtrip, d, x, f @skipif(not FI_available) def test_metadata(): meta = fi.read_metadata(os.path.join(si.data_dir, 'multipage.tif')) assert meta[('EXIF_MAIN', 'Orientation')] == 1 assert meta[('EXIF_MAIN', 'Software')].startswith('ImageMagick') meta = fi.read_multipage_metadata(os.path.join(si.data_dir, 'multipage.tif')) assert len(meta) == 2 assert meta[0][('EXIF_MAIN', 'Orientation')] == 1 assert meta[1][('EXIF_MAIN', 'Software')].startswith('ImageMagick') if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_histograms.py000066400000000000000000000014231223313777300230630ustar00rootroot00000000000000from numpy.testing import * import numpy as np from skimage.io._plugins._histograms import histograms class TestHistogram: def test_basic(self): img = np.ones((50, 50, 3), dtype=np.uint8) r, g, b, v = histograms(img, 255) for band in (r, g, b, v): yield assert_equal, band.sum(), 50 * 50 def test_counts(self): channel = np.arange(255).reshape(51, 5) img = np.empty((51, 5, 3), dtype='uint8') img[:, :, 0] = channel img[:, :, 1] = channel img[:, :, 2] = channel r, g, b, v = histograms(img, 255) assert_array_equal(r, g) assert_array_equal(r, b) assert_array_equal(r, v) assert_array_equal(r, np.ones(255)) if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_image.py000066400000000000000000000006701223313777300217700ustar00rootroot00000000000000from skimage.io import Image from numpy.testing import assert_equal, assert_array_equal def test_tags(): f = Image([1, 2, 3], foo='bar', sigma='delta') g = Image([3, 2, 1], sun='moon') h = Image([1, 1, 1]) assert_equal(f.tags['foo'], 'bar') assert_array_equal((g + 2).tags['sun'], 'moon') assert_equal(h.tags, {}) if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_imread.py000066400000000000000000000036421223313777300221510ustar00rootroot00000000000000import os.path import numpy as np from numpy.testing import * from numpy.testing.decorators import skipif from tempfile import NamedTemporaryFile from skimage import data_dir from skimage.io import imread, imsave, use_plugin, reset_plugins try: import imread as _imread use_plugin('imread') except ImportError: imread_available = False else: imread_available = True def teardown(): reset_plugins() @skipif(not imread_available) def test_imread_flatten(): # a color image is flattened img = imread(os.path.join(data_dir, 'color.png'), flatten=True) assert img.ndim == 2 assert img.dtype == np.float64 img = imread(os.path.join(data_dir, 'camera.png'), flatten=True) # check that flattening does not occur for an image that is grey already. assert np.sctype2char(img.dtype) in np.typecodes['AllInteger'] @skipif(not imread_available) def test_imread_palette(): img = imread(os.path.join(data_dir, 'palette_color.png')) assert img.ndim == 3 @skipif(not imread_available) def test_bilevel(): expected = np.zeros((10, 10), bool) expected[::2] = 1 img = imread(os.path.join(data_dir, 'checker_bilevel.png')) assert_array_equal(img, expected) class TestSave: def roundtrip(self, x, scaling=1): f = NamedTemporaryFile(suffix='.png') fname = f.name f.close() imsave(fname, x) y = imread(fname) assert_array_almost_equal((x * scaling).astype(np.int32), y) @skipif(not imread_available) def test_imsave_roundtrip(self): dtype = np.uint8 for shape in [(10, 10), (10, 10, 3), (10, 10, 4)]: x = np.ones(shape, dtype=dtype) * np.random.random(shape) if np.issubdtype(dtype, float): yield self.roundtrip, x, 255 else: x = (x * 255).astype(dtype) yield self.roundtrip, x if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_io.py000066400000000000000000000013161223313777300213130ustar00rootroot00000000000000import os from numpy.testing import assert_array_equal, raises, run_module_suite import numpy as np import skimage.io as io from skimage import data_dir def test_stack_basic(): x = np.arange(12).reshape(3, 4) io.push(x) assert_array_equal(io.pop(), x) @raises(ValueError) def test_stack_non_array(): io.push([[1, 2, 3]]) def test_imread_url(): # tweak data path so that file URI works on both unix and windows. data_path = data_dir.lstrip(os.path.sep) data_path = data_path.replace(os.path.sep, '/') image_url = 'file:///{0}/camera.png'.format(data_path) image = io.imread(image_url) assert image.shape == (512, 512) if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_pil.py000066400000000000000000000101201223313777300214610ustar00rootroot00000000000000import os.path import numpy as np from numpy.testing import * from numpy.testing.decorators import skipif from tempfile import NamedTemporaryFile from skimage import data_dir from skimage.io import (imread, imsave, use_plugin, reset_plugins, Image as ioImage) from skimage._shared.six import BytesIO try: from PIL import Image from skimage.io._plugins.pil_plugin import _palette_is_grayscale use_plugin('pil') except ImportError: PIL_available = False else: PIL_available = True def teardown(): reset_plugins() def setup_module(self): """The effect of the `plugin.use` call may be overridden by later imports. Call `use_plugin` directly before the tests to ensure that PIL is used. """ try: use_plugin('pil') except ImportError: pass @skipif(not PIL_available) def test_imread_flatten(): # a color image is flattened img = imread(os.path.join(data_dir, 'color.png'), flatten=True) assert img.ndim == 2 assert img.dtype == np.float64 img = imread(os.path.join(data_dir, 'camera.png'), flatten=True) # check that flattening does not occur for an image that is grey already. assert np.sctype2char(img.dtype) in np.typecodes['AllInteger'] @skipif(not PIL_available) def test_imread_palette(): img = imread(os.path.join(data_dir, 'palette_gray.png')) assert img.ndim == 2 img = imread(os.path.join(data_dir, 'palette_color.png')) assert img.ndim == 3 @skipif(not PIL_available) def test_palette_is_gray(): gray = Image.open(os.path.join(data_dir, 'palette_gray.png')) assert _palette_is_grayscale(gray) color = Image.open(os.path.join(data_dir, 'palette_color.png')) assert not _palette_is_grayscale(color) @skipif(not PIL_available) def test_bilevel(): expected = np.zeros((10, 10)) expected[::2] = 255 img = imread(os.path.join(data_dir, 'checker_bilevel.png')) assert_array_equal(img, expected) @skipif(not PIL_available) def test_imread_uint16(): expected = np.load(os.path.join(data_dir, 'chessboard_GRAY_U8.npy')) img = imread(os.path.join(data_dir, 'chessboard_GRAY_U16.tif')) assert np.issubdtype(img.dtype, np.uint16) assert_array_almost_equal(img, expected) @skipif(not PIL_available) def test_repr_png(): img_path = os.path.join(data_dir, 'camera.png') original_img = ioImage(imread(img_path)) original_img_str = original_img._repr_png_() with NamedTemporaryFile(suffix='.png') as temp_png: temp_png.write(original_img_str) temp_png.seek(0) round_trip = imread(temp_png) assert np.all(original_img == round_trip) # Big endian images not correctly loaded for PIL < 1.1.7 # Renable test when PIL 1.1.7 is more common. @skipif(True) def test_imread_uint16_big_endian(): expected = np.load(os.path.join(data_dir, 'chessboard_GRAY_U8.npy')) img = imread(os.path.join(data_dir, 'chessboard_GRAY_U16B.tif')) assert img.dtype == np.dtype('>u2') assert_array_almost_equal(img, expected) class TestSave: def roundtrip(self, dtype, x, scaling=1): f = NamedTemporaryFile(suffix='.png') fname = f.name f.close() imsave(fname, x) y = imread(fname) assert_array_almost_equal((x * scaling).astype(np.int32), y) @skipif(not PIL_available) def test_imsave_roundtrip(self): for shape in [(10, 10), (10, 10, 3), (10, 10, 4)]: for dtype in (np.uint8, np.uint16, np.float32, np.float64): x = np.ones(shape, dtype=dtype) * np.random.random(shape) if np.issubdtype(dtype, float): yield self.roundtrip, dtype, x, 255 else: x = (x * 255).astype(dtype) yield self.roundtrip, dtype, x @skipif(not PIL_available) def test_imsave_filelike(): shape = (2, 2) image = np.zeros(shape) s = BytesIO() # save to file-like object imsave(s, image) # read from file-like object s.seek(0) out = imread(s) assert out.shape == shape assert_allclose(out, image) if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_plugin.py000066400000000000000000000043271223313777300222070ustar00rootroot00000000000000from numpy.testing import * from skimage import io from skimage.io._plugins import plugin from numpy.testing.decorators import skipif try: io.use_plugin('pil') PIL_available = True priority_plugin = 'pil' except ImportError: PIL_available = False try: io.use_plugin('freeimage') FI_available = True priority_plugin = 'freeimage' except RuntimeError: FI_available = False def setup_module(self): plugin.use('test') # see ../_plugins/test_plugin.py def teardown_module(self): io.reset_plugins() class TestPlugin: def test_read(self): io.imread('test.png', as_grey=True, dtype='i4', plugin='test') def test_save(self): io.imsave('test.png', [1, 2, 3], plugin='test') def test_show(self): io.imshow([1, 2, 3], plugin_arg=(1, 2), plugin='test') def test_collection(self): io.imread_collection('*.png', conserve_memory=False, plugin='test') def test_use(self): plugin.use('test') plugin.use('test', 'imshow') @raises(ValueError) def test_failed_use(self): plugin.use('asd') @skipif(not PIL_available and not FI_available) def test_use_priority(self): plugin.use(priority_plugin) plug, func = plugin.plugin_store['imread'][0] assert_equal(plug, priority_plugin) plugin.use('test') plug, func = plugin.plugin_store['imread'][0] assert_equal(plug, 'test') @skipif(not PIL_available) def test_use_priority_with_func(self): plugin.use('pil') plug, func = plugin.plugin_store['imread'][0] assert_equal(plug, 'pil') plugin.use('test', 'imread') plug, func = plugin.plugin_store['imread'][0] assert_equal(plug, 'test') plug, func = plugin.plugin_store['imsave'][0] assert_equal(plug, 'pil') plugin.use('test') plug, func = plugin.plugin_store['imsave'][0] assert_equal(plug, 'test') def test_plugin_order(self): p = io.plugin_order() assert 'imread' in p assert 'test' in p['imread'] def test_available(self): assert 'qt' in io.plugins() assert 'test' in io.plugins(loaded=True) if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_plugin_util.py000066400000000000000000000033451223313777300232430ustar00rootroot00000000000000from skimage.io._plugins.util import prepare_for_display, WindowManager from numpy.testing import * import numpy as np class TestPrepareForDisplay: def test_basic(self): prepare_for_display(np.random.random((10, 10))) def test_dtype(self): x = prepare_for_display(np.random.random((10, 15))) assert x.dtype == np.dtype(np.uint8) def test_grey(self): x = prepare_for_display(np.arange(12, dtype=float).reshape((4, 3)) / 11) assert_array_equal(x[..., 0], x[..., 2]) assert x[0, 0, 0] == 0 assert x[3, 2, 0] == 255 def test_colour(self): prepare_for_display(np.random.random((10, 10, 3))) def test_alpha(self): prepare_for_display(np.random.random((10, 10, 4))) @raises(ValueError) def test_wrong_dimensionality(self): prepare_for_display(np.random.random((10, 10, 1, 1))) @raises(ValueError) def test_wrong_depth(self): prepare_for_display(np.random.random((10, 10, 5))) class TestWindowManager: callback_called = False def setup(self): self.wm = WindowManager() self.wm.acquire('test') def test_add_window(self): self.wm.add_window('window1') self.wm.remove_window('window1') def callback(self): self.callback_called = True def test_callback(self): self.wm.register_callback(self.callback) self.wm.add_window('window') self.wm.remove_window('window') assert self.callback_called def test_has_images(self): assert not self.wm.has_windows() self.wm.add_window('window') assert self.wm.has_windows() def teardown(self): self.wm._release('test') if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_sift.py000066400000000000000000000062011223313777300216470ustar00rootroot00000000000000from nose.tools import * from numpy.testing import assert_equal, run_module_suite from tempfile import NamedTemporaryFile import os from skimage.io import load_sift, load_surf def test_load_sift(): f = NamedTemporaryFile(delete=False) fname = f.name f.close() f = open(fname, 'wb') f.write(b'''2 128 133.92 135.88 14.38 -2.732 3 12 23 38 10 15 78 20 39 67 42 8 12 8 39 35 118 43 17 0 0 1 12 109 9 2 6 0 0 21 46 22 14 18 51 19 5 9 41 52 65 30 3 21 55 49 26 30 118 118 25 12 8 3 2 60 53 56 72 20 7 10 16 7 88 23 13 15 12 11 11 71 45 7 4 49 82 38 38 91 118 15 2 16 33 3 5 118 98 38 6 19 36 1 0 15 64 22 1 2 6 11 18 61 31 3 0 6 15 23 118 118 13 0 0 35 38 18 40 96 24 1 0 13 17 3 24 98 132.36 99.75 11.45 -2.910 94 32 7 2 13 7 5 23 121 94 13 5 0 0 4 59 13 30 71 32 0 6 32 11 25 32 13 0 0 16 51 5 44 50 0 3 33 55 11 9 121 121 12 9 6 3 0 18 55 60 48 44 44 9 0 2 106 117 13 2 1 0 1 1 37 1 1 25 80 35 15 41 121 3 0 2 14 3 2 121 51 11 0 20 93 6 0 20 109 57 3 4 5 0 0 28 21 2 0 5 13 12 75 119 35 0 0 13 28 14 37 121 12 0 0 21 46 5 11 93 29 0 0 3 14 4 11 99''') f.close() f = open(fname, 'rb') features = load_sift(f) f.close() os.remove(fname) assert_equal(len(features), 2) assert_equal(len(features['data'][0]), 128) assert_equal(features['row'][0], 133.92) assert_equal(features['column'][1], 99.75) def test_load_surf(): f = NamedTemporaryFile(delete=False) fname = f.name f.close() f = open(fname, 'wb') f.write(b'''65 2 38.3727 62.0491 0.0371343 0 0.0371343 -1 -0.0705589 0.0130983 -0.00460534 0.132168 -0.0718833 0.0320583 -0.0134032 0.0988654 -0.0542241 0.0171002 -0.00135754 0.105755 -0.0362088 0.0151748 -0.00694272 0.0610017 -0.247091 0.109605 -0.0337623 0.0813307 -0.24185 0.278548 -0.0494523 0.107804 -0.166312 0.0691584 -0.0288199 0.138476 -0.110956 0.0280772 -0.0752509 0.0736344 -0.22667 0.164226 -0.0544717 0.0388139 -0.30194 0.33065 -0.0537507 0.0596398 -0.245395 0.110925 -0.0603322 0.0239389 -0.18726 0.0374145 -0.0355872 0.0140762 -0.129022 0.135104 -0.0703396 0.0374049 -0.24256 0.222544 -0.0536354 0.0501252 -0.209004 0.0971316 -0.0550094 0.0229767 -0.125547 0.0317879 -0.0291574 0.0124569 68.5773 61.474 0.0313267 0 0.0313267 1 -0.10198 0.130987 -0.0321845 0.0487543 -0.0900435 0.121113 -0.100917 0.0444702 -0.0151742 0.107604 -0.0542035 0.014069 -0.00594097 0.0339933 -0.00994295 0.0127262 -0.125613 0.192551 -0.0174399 0.0433488 -0.272698 0.164641 -0.0676735 0.0467444 -0.0527907 0.258005 -0.0818114 0.0440569 -0.0104433 0.0548934 -0.0323454 0.0145296 -0.112357 0.199223 -0.0532903 0.0332622 -0.342481 0.207469 -0.0526129 0.0741355 -0.256234 0.402708 -0.108296 0.117362 -0.0560274 0.128856 -0.123509 0.0510046 -0.0198793 0.0775934 -0.103863 0.00406679 -0.10264 0.1312 -0.108244 0.0812913 -0.127868 0.182924 -0.0680942 0.071913 -0.0858004 0.144806 -0.0176522 0.0686146''') f.close() f = open(fname, 'rb') features = load_surf(f) f.close() os.remove(fname) assert_equal(len(features), 2) assert_equal(len(features['data'][0]), 64) assert_equal(features['column'][1], 68.5773) assert_equal(features['row'][0], 62.0491) if __name__ == '__main__': run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_simpleitk.py000066400000000000000000000052371223313777300227130ustar00rootroot00000000000000import os.path import numpy as np from numpy.testing.decorators import skipif from tempfile import NamedTemporaryFile from skimage import data_dir from skimage.io import imread, imsave, use_plugin, reset_plugins try: import SimpleITK as sitk use_plugin('simpleitk') except ImportError: sitk_available = False else: sitk_available = True def teardown(): reset_plugins() def setup_module(self): """The effect of the `plugin.use` call may be overridden by later imports. Call `use_plugin` directly before the tests to ensure that sitk is used. """ try: use_plugin('simpleitk') except ImportError: pass @skipif(not sitk_available) def test_imread_flatten(): # a color image is flattened img = imread(os.path.join(data_dir, 'color.png'), flatten=True) assert img.ndim == 2 assert img.dtype == np.float64 img = imread(os.path.join(data_dir, 'camera.png'), flatten=True) # check that flattening does not occur for an image that is grey already. assert np.sctype2char(img.dtype) in np.typecodes['AllInteger'] @skipif(not sitk_available) def test_bilevel(): expected = np.zeros((10, 10)) expected[::2] = 255 img = imread(os.path.join(data_dir, 'checker_bilevel.png')) np.testing.assert_array_equal(img, expected) @skipif(not sitk_available) def test_imread_uint16(): expected = np.load(os.path.join(data_dir, 'chessboard_GRAY_U8.npy')) img = imread(os.path.join(data_dir, 'chessboard_GRAY_U16.tif')) assert np.issubdtype(img.dtype, np.uint16) np.testing.assert_array_almost_equal(img, expected) @skipif(not sitk_available) def test_imread_uint16_big_endian(): expected = np.load(os.path.join(data_dir, 'chessboard_GRAY_U8.npy')) img = imread(os.path.join(data_dir, 'chessboard_GRAY_U16B.tif')) np.testing.assert_array_almost_equal(img, expected) class TestSave: def roundtrip(self, dtype, x): f = NamedTemporaryFile(suffix='.mha') fname = f.name f.close() imsave(fname, x) y = imread(fname) np.testing.assert_array_almost_equal(x, y) @skipif(not sitk_available) def test_imsave_roundtrip(self): for shape in [(10, 10), (10, 10, 3), (10, 10, 4)]: for dtype in (np.uint8, np.uint16, np.float32, np.float64): x = np.ones(shape, dtype=dtype) * np.random.random(shape) if np.issubdtype(dtype, float): yield self.roundtrip, dtype, x else: x = (x * 255).astype(dtype) yield self.roundtrip, dtype, x if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/io/tests/test_tifffile.py000066400000000000000000000032541223313777300224770ustar00rootroot00000000000000import os import skimage as si import skimage.io as sio import numpy as np from numpy.testing import * from numpy.testing.decorators import skipif from tempfile import NamedTemporaryFile try: import skimage.io._plugins.tifffile_plugin as tf _plugins = sio.plugin_order() TF_available = True sio.use_plugin('tifffile') except ImportError: TF_available = False def teardown(): sio.reset_plugins() @skipif(not TF_available) def test_imread_uint16(): expected = np.load(os.path.join(si.data_dir, 'chessboard_GRAY_U8.npy')) img = sio.imread(os.path.join(si.data_dir, 'chessboard_GRAY_U16.tif')) assert img.dtype == np.uint16 assert_array_almost_equal(img, expected) @skipif(not TF_available) def test_imread_uint16_big_endian(): expected = np.load(os.path.join(si.data_dir, 'chessboard_GRAY_U8.npy')) img = sio.imread(os.path.join(si.data_dir, 'chessboard_GRAY_U16B.tif')) assert img.dtype == np.uint16 assert_array_almost_equal(img, expected) class TestSave: def roundtrip(self, dtype, x): f = NamedTemporaryFile(suffix='.tif') fname = f.name f.close() sio.imsave(fname, x) y = sio.imread(fname) assert_array_equal(x, y) @skipif(not TF_available) def test_imsave_roundtrip(self): for shape in [(10, 10), (10, 10, 3), (10, 10, 4)]: for dtype in (np.uint8, np.uint16, np.float32, np.float64): x = np.ones(shape, dtype=dtype) * np.random.random(shape) if not np.issubdtype(dtype, float): x = (x * 255).astype(dtype) yield self.roundtrip, dtype, x if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/io/video.py000066400000000000000000000244301223313777300176130ustar00rootroot00000000000000import numpy as np import os from skimage.io import ImageCollection try: import pygst pygst.require("0.10") import gst import gobject gobject.threads_init() from gst.extend.discoverer import Discoverer gstreamer_available = True except ImportError: gstreamer_available = False try: import cv opencv_available = True except ImportError: opencv_available = False class CvVideo(object): """ Opencv-based video loader. Parameters ---------- source : str Media location URI. Video file path or http address of IP camera. size: tuple, optional Size of returned array. """ def __init__(self, source=None, size=None, backend=None): if not opencv_available: raise ImportError("Opencv 2.0+ required") self.source = source self.capture = cv.CreateFileCapture(self.source) self.size = size def get(self): """ Retrieve a video frame as a numpy array. Returns ------- output : array (image) Retrieved image. """ img = cv.QueryFrame(self.capture) if not self.size: self.size = cv.GetSize(img) img_mat = np.empty((self.size[1], self.size[0], 3), dtype=np.uint8) if cv.GetSize(img) == self.size: cv.Copy(img, cv.fromarray(img_mat)) else: cv.Resize(img, cv.fromarray(img_mat)) # opencv stores images in BGR format cv.CvtColor(cv.fromarray(img_mat), cv.fromarray(img_mat), cv.CV_BGR2RGB) return img_mat def seek_frame(self, frame_number): """ Seek to specified frame in video. Parameters ---------- frame_number : int Frame position """ cv.SetCaptureProperty(self.capture, cv.CV_CAP_PROP_POS_FRAMES, frame_number) def seek_time(self, milliseconds): """ Seek to specified time in video. Parameters ---------- milliseconds : int Time position """ cv.SetCaptureProperty(self.capture, cv.CV_CAP_PROP_POS_MSEC, milliseconds) def frame_count(self): """ Returns frame count of video. Returns ------- output : int Frame count. """ return cv.GetCaptureProperty(self.capture, cv.CV_CAP_PROP_FRAME_COUNT) def duration(self): """ Returns time length of video in milliseconds. Returns ------- output : int Time length [ms]. """ return cv.GetCaptureProperty(self.capture, cv.CV_CAP_PROP_FPS) * \ cv.GetCaptureProperty(self.capture, cv.CV_CAP_PROP_FRAME_COUNT) class GstVideo(object): """ GStreamer-based video loader. Parameters ---------- source : str Media location URI. Video file path or http address of IP camera. size: tuple, optional Size of returned array. sync: bool, optional (default False) Frames are extracted per frame or per time basis. If enabled the video time step continues onward according to the play rate. Useful for ip cameras and other real time video feeds. """ def __init__(self, source=None, size=None, sync=False): if not gstreamer_available: raise ImportError("GStreamer Python bindings 0.10+ required") self.source = source self.size = size self.video_length = 0 self.video_rate = 0 # extract video size if not size: gobject.idle_add(self._discover_one) self.mainloop = gobject.MainLoop() self.mainloop.run() if not self.size: self.size = (640, 480) if os.path.exists(self.source): self.source = "file://" + self.source self._create_main_pipeline(self.source, self.size, sync) def _discover_one(self): """ Callback to start media discovery process, used to retrieve video parameters. """ discoverer = Discoverer(self.source) discoverer.connect('discovered', self._discovered) discoverer.discover() return False def _discovered(self, d, is_media): """ Callback to on media discovery result. """ if is_media: self.size = (d.videowidth, d.videoheight) self.video_length = d.videolength / gst.MSECOND self.video_rate = d.videorate.num self.mainloop.quit() return False def _create_main_pipeline(self, source, size, sync): """ Create the frame extraction pipeline. """ pipeline_string = "uridecodebin name=decoder uri=%s ! ffmpegcolorspace ! videoscale ! appsink name=play_sink" % self.source self.pipeline = gst.parse_launch(pipeline_string) caps = "video/x-raw-rgb, width=%d, height=%d, depth=24, bpp=24" % size self.decoder = self.pipeline.get_by_name("decoder") self.appsink = self.pipeline.get_by_name('play_sink') self.appsink.set_property('emit-signals', True) self.appsink.set_property('sync', sync) self.appsink.set_property('drop', True) self.appsink.set_property('max-buffers', 1) self.appsink.set_property('caps', gst.caps_from_string(caps)) if self.pipeline.set_state(gst.STATE_PLAYING) == gst.STATE_CHANGE_FAILURE: raise NameError("Failed to load video source %s" % self.source) self.appsink.emit('pull-preroll') def get(self): """ Retrieve a video frame as a numpy array. Returns ------- output : array (image) Retrieved image. """ buff = self.appsink.emit('pull-buffer') img_mat = np.ndarray(shape=(self.size[1], self.size[0], 3), dtype=np.uint8, buffer=buff.data) return img_mat def seek_frame(self, frame_number): """ Seek to specified frame in video. Parameters ---------- frame_number : int Frame position """ self.pipeline.seek_simple(gst.FORMAT_DEFAULT, gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_KEY_UNIT, frame_number) def seek_time(self, milliseconds): """ Seek to specified time in video. Parameters ---------- milliseconds : int Time position """ self.pipeline.seek_simple(gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_KEY_UNIT, milliseconds / 1000.0 * gst.SECOND) def frame_count(self): """ Returns frame count of video. Returns ------- output : int Frame count. """ return self.video_length / 1000 * self.video_rate def duration(self): """ Returns time length of video in milliseconds. Returns ------- output : int Time length [ms]. """ return self.video_length class Video(object): """ Video loader. Supports Opencv and Gstreamer backends. Parameters ---------- source : str Media location URI. Video file path or http address of IP camera. size: tuple, optional Size of returned array. sync: bool, optional (default False) Frames are extracted per frame or per time basis. Gstreamer only. If enabled the video time step continues onward according to the play rate. Useful for IP cameras and other real time video feeds. backend: str, 'gstreamer' or 'opencv' Backend to use. """ def __init__(self, source=None, size=None, sync=False, backend=None): if backend is None: # select backend that is available if gstreamer_available: self.video = GstVideo(source, size, sync) elif opencv_available: self.video = CvVideo(source, size) else: # if no backend available, raise exception self.video = GstVideo(source, size, sync) elif backend == "gstreamer": self.video = GstVideo(source, size, sync) elif backend == "opencv": self.video = CvVideo(source, size) else: raise ValueError("Unknown backend: %s", backend) def get(self): """ Retrieve the next video frame as a numpy array. Returns ------- output : array (image) Retrieved image. """ return self.video.get() def seek_frame(self, frame_number): """ Seek to specified frame in video. Parameters ---------- frame_number : int Frame position """ self.video.seek_frame(frame_number) def seek_time(self, milliseconds): """ Seek to specified time in video. Parameters ---------- milliseconds : int Time position """ self.video.seek_time(milliseconds) def frame_count(self): """ Returns frame count of video. Returns ------- output : int Frame count. """ return self.video.frame_count() def duration(self): """ Returns time length of video in milliseconds. Returns ------- output : int Time length [ms]. """ return self.video.duration() def get_index_frame(self, frame_number): """ Retrieve a specified video frame as a numpy array. Parameters ---------- frame_number : int Frame position Returns ------- output : array (image) Retrieved image. """ self.video.seek_frame(frame_number) return self.video.get() def get_collection(self, time_range=None): """ Returns an ImageCollection object. Parameters ---------- time_range: range (int), optional Time steps to extract, defaults to the entire length of video. Returns ------- output: ImageCollection Collection of images iterator. """ if not time_range: time_range = range(int(self.frame_count())) return ImageCollection(time_range, load_func=self.get_index_frame) __all__ = ["Video"] scikit-image-0.9.3/skimage/measure/000077500000000000000000000000001223313777300171625ustar00rootroot00000000000000scikit-image-0.9.3/skimage/measure/__init__.py000077500000000000000000000016641223313777300213050ustar00rootroot00000000000000from .find_contours import find_contours from ._marching_cubes import marching_cubes, mesh_surface_area from ._regionprops import regionprops, perimeter from ._structural_similarity import structural_similarity from ._polygon import approximate_polygon, subdivide_polygon from ._moments import moments, moments_central, moments_normalized, moments_hu from .fit import LineModel, CircleModel, EllipseModel, ransac from .block import block_reduce __all__ = ['find_contours', 'regionprops', 'perimeter', 'structural_similarity', 'approximate_polygon', 'subdivide_polygon', 'LineModel', 'CircleModel', 'EllipseModel', 'ransac', 'block_reduce', 'moments', 'moments_central', 'moments_normalized', 'moments_hu', 'sum_blocks', 'marching_cubes', 'mesh_surface_area'] scikit-image-0.9.3/skimage/measure/_find_contours.pyx000066400000000000000000000157361223313777300227530ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cdef inline double _get_fraction(double from_value, double to_value, double level): if (to_value == from_value): return 0 return ((level - from_value) / (to_value - from_value)) def iterate_and_store(double[:, :] array, double level, Py_ssize_t vertex_connect_high): """Iterate across the given array in a marching-squares fashion, looking for segments that cross 'level'. If such a segment is found, its coordinates are added to a growing list of segments, which is returned by the function. if vertex_connect_high is nonzero, high-values pixels are considered to be face+vertex connected into objects; otherwise low-valued pixels are. """ if array.shape[0] < 2 or array.shape[1] < 2: raise ValueError("Input array must be at least 2x2.") cdef list arc_list = [] cdef Py_ssize_t n # The plan is to iterate a 2x2 square across the input array. This means # that the upper-left corner of the square needs to iterate across a # sub-array that's one-less-large in each direction (so that the square # never steps out of bounds). The square is represented by four pointers: # ul, ur, ll, and lr (for 'upper left', etc.). We also maintain the current # 2D coordinates for the position of the upper-left pointer. Note that we # ensured that the array is of type 'double' and is C-contiguous (last # index varies the fastest). # Current coords start at 0,0. cdef Py_ssize_t[2] coords coords[0] = 0 coords[1] = 0 # Calculate the number of iterations we'll need cdef Py_ssize_t num_square_steps = (array.shape[0] - 1) \ * (array.shape[1] - 1) cdef unsigned char square_case = 0 cdef tuple top, bottom, left, right cdef double ul, ur, ll, lr cdef Py_ssize_t r0, r1, c0, c1 for n in range(num_square_steps): # There are sixteen different possible square types, diagramed below. # A + indicates that the vertex is above the contour value, and a - # indicates that the vertex is below or equal to the contour value. # The vertices of each square are: # ul ur # ll lr # and can be treated as a binary value with the bits in that order. Thus # each square case can be numbered: # 0-- 1+- 2-+ 3++ 4-- 5+- 6-+ 7++ # -- -- -- -- +- +- +- +- # # 8-- 9+- 10-+ 11++ 12-- 13+- 14-+ 15++ # -+ -+ -+ -+ ++ ++ ++ ++ # # The position of the line segment that cuts through (or # doesn't, in case 0 and 15) each square is clear, except in # cases 6 and 9. In this case, where the segments are placed # is determined by vertex_connect_high. If # vertex_connect_high is false, then lines like \\ are drawn # through square 6, and lines like // are drawn through square # 9. Otherwise, the situation is reversed. # Finally, recall that we draw the lines so that (moving from tail to # head) the lower-valued pixels are on the left of the line. So, for # example, case 1 entails a line slanting from the middle of the top of # the square to the middle of the left side of the square. r0, c0 = coords[0], coords[1] r1, c1 = r0 + 1, c0 + 1 ul = array[r0, c0] ur = array[r0, c1] ll = array[r1, c0] lr = array[r1, c1] # now in advance the coords indices if coords[1] < array.shape[1] - 2: coords[1] += 1 else: coords[0] += 1 coords[1] = 0 square_case = 0 if (ul > level): square_case += 1 if (ur > level): square_case += 2 if (ll > level): square_case += 4 if (lr > level): square_case += 8 if (square_case != 0 and square_case != 15): # only do anything if there's a line passing through the # square. Cases 0 and 15 are entirely below/above the contour. top = r0, c0 + _get_fraction(ul, ur, level) bottom = r1, c0 + _get_fraction(ll, lr, level) left = r0 + _get_fraction(ul, ll, level), c0 right = r0 + _get_fraction(ur, lr, level), c1 if (square_case == 1): # top to left arc_list.append(top) arc_list.append(left) elif (square_case == 2): # right to top arc_list.append(right) arc_list.append(top) elif (square_case == 3): # right to left arc_list.append(right) arc_list.append(left) elif (square_case == 4): # left to bottom arc_list.append(left) arc_list.append(bottom) elif (square_case == 5): # top to bottom arc_list.append(top) arc_list.append(bottom) elif (square_case == 6): if vertex_connect_high: arc_list.append(left) arc_list.append(top) arc_list.append(right) arc_list.append(bottom) else: arc_list.append(right) arc_list.append(top) arc_list.append(left) arc_list.append(bottom) elif (square_case == 7): # right to bottom arc_list.append(right) arc_list.append(bottom) elif (square_case == 8): # bottom to right arc_list.append(bottom) arc_list.append(right) elif (square_case == 9): if vertex_connect_high: arc_list.append(top) arc_list.append(right) arc_list.append(bottom) arc_list.append(left) else: arc_list.append(top) arc_list.append(left) arc_list.append(bottom) arc_list.append(right) elif (square_case == 10): # bottom to top arc_list.append(bottom) arc_list.append(top) elif (square_case == 11): # bottom to left arc_list.append(bottom) arc_list.append(left) elif (square_case == 12): # lef to right arc_list.append(left) arc_list.append(right) elif (square_case == 13): # top to right arc_list.append(top) arc_list.append(right) elif (square_case == 14): # left to top arc_list.append(left) arc_list.append(top) return arc_list scikit-image-0.9.3/skimage/measure/_marching_cubes.py000066400000000000000000000142421223313777300226470ustar00rootroot00000000000000import numpy as np from . import _marching_cubes_cy def marching_cubes(volume, level, spacing=(1., 1., 1.)): """ Marching cubes algorithm to find iso-valued surfaces in 3d volumetric data Parameters ---------- volume : (M, N, P) array of doubles Input data volume to find isosurfaces. Will be cast to `np.float64`. level : float Contour value to search for isosurfaces in `volume`. spacing : length-3 tuple of floats Voxel spacing in spatial dimensions corresponding to numpy array indexing dimensions (M, N, P) as in `volume`. Returns ------- verts : (V, 3) array Spatial coordinates for V unique mesh vertices. Coordinate order matches input `volume` (M, N, P). faces : (F, 3) array Define triangular faces via referencing vertex indices from ``verts``. This algorithm specifically outputs triangles, so each face has exactly three indices. Notes ----- The marching cubes algorithm is implemented as described in [1]_. A simple explanation is available here:: http://www.essi.fr/~lingrand/MarchingCubes/algo.html There are several known ambiguous cases in the marching cubes algorithm. Using point labeling as in [1]_, Figure 4, as shown:: v8 ------ v7 / | / | y / | / | ^ z v4 ------ v3 | | / | v5 ----|- v6 |/ (note: NOT right handed!) | / | / ----> x | / | / v1 ------ v2 Most notably, if v4, v8, v2, and v6 are all >= `level` (or any generalization of this case) two parallel planes are generated by this algorithm, separating v4 and v8 from v2 and v6. An equally valid interpretation would be a single connected thin surface enclosing all four points. This is the best known ambiguity, though there are others. This algorithm does not attempt to resolve such ambiguities; it is a naive implementation of marching cubes as in [1]_, but may be a good beginning for work with more recent techniques (Dual Marching Cubes, Extended Marching Cubes, Cubic Marching Squares, etc.). Because of interactions between neighboring cubes, the isosurface(s) generated by this algorithm are NOT guaranteed to be closed, particularly for complicated contours. Furthermore, this algorithm does not guarantee a single contour will be returned. Indeed, ALL isosurfaces which cross `level` will be found, regardless of connectivity. The output is a triangular mesh consisting of a set of unique vertices and connecting triangles. The order of these vertices and triangles in the output list is determined by the position of the smallest ``x,y,z`` (in lexicographical order) coordinate in the contour. This is a side-effect of how the input array is traversed, but can be relied upon. To quantify the area of an isosurface generated by this algorithm, pass the outputs directly into `skimage.measure.mesh_surface_area`. Regarding visualization of algorithm output, the ``mayavi`` package is recommended. To contour a volume named `myvolume` about the level 0.0:: >>> from mayavi import mlab >>> verts, tris = marching_cubes(myvolume, 0.0, (1., 1., 2.)) >>> mlab.triangular_mesh([vert[0] for vert in verts], ... [vert[1] for vert in verts], ... [vert[2] for vert in verts], ... tris) >>> mlab.show() References ---------- .. [1] Lorensen, William and Harvey E. Cline. Marching Cubes: A High Resolution 3D Surface Construction Algorithm. Computer Graphics (SIGGRAPH 87 Proceedings) 21(4) July 1987, p. 163-170). See Also -------- skimage.measure.mesh_surface_area """ # Check inputs and ensure `volume` is C-contiguous for memoryviews if volume.ndim != 3: raise ValueError("Input volume must have 3 dimensions.") if level < volume.min() or level > volume.max(): raise ValueError("Contour level must be within volume data range.") volume = np.array(volume, dtype=np.float64, order="C") # Extract raw triangles using marching cubes in Cython # Returns a list of length-3 lists, each sub-list containing three # tuples. The tuples hold (x, y, z) coordinates for triangle vertices. # Note: this algorithm is fast, but returns degenerate "triangles" which # have repeated vertices - and equivalent vertices are redundantly # placed in every triangle they connect with. raw_tris = _marching_cubes_cy.iterate_and_store_3d(volume, float(level), spacing) # Find and collect unique vertices, storing triangle verts as indices. # Returns a true mesh with no degenerate faces. verts, faces = _marching_cubes_cy.unpack_unique_verts(raw_tris) return np.asarray(verts), np.asarray(faces) def mesh_surface_area(verts, tris): """ Compute surface area, given vertices & triangular faces Parameters ---------- verts : (V, 3) array of floats Array containing (x, y, z) coordinates for V unique mesh vertices. faces : (F, 3) array of ints List of length-3 lists of integers, referencing vertex coordinates as provided in `verts` Returns ------- area : float Surface area of mesh. Units now [coordinate units] ** 2. Notes ----- The arguments expected by this function are the exact outputs from `skimage.measure.marching_cubes`. For unit correct output, ensure correct `spacing` was passed to `skimage.measure.marching_cubes`. This algorithm works properly only if the ``faces`` provided are all triangles. See Also -------- skimage.measure.marching_cubes """ # Fancy indexing to define two vector arrays from triangle vertices actual_verts = verts[tris] a = actual_verts[:, 0, :] - actual_verts[:, 1, :] b = actual_verts[:, 0, :] - actual_verts[:, 2, :] del actual_verts # Area of triangle in 3D = 1/2 * Euclidean norm of cross product return ((np.cross(a, b) ** 2).sum(axis=1) ** 0.5).sum() / 2. scikit-image-0.9.3/skimage/measure/_marching_cubes_cy.pyx000066400000000000000000001220501223313777300235270ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cimport numpy as cnp cdef inline double _get_fraction(double from_value, double to_value, double level): if (to_value == from_value): return 0 return ((level - from_value) / (to_value - from_value)) def unpack_unique_verts(list trilist): """ Convert a list of lists of tuples corresponding to triangle vertices into a unique vertex list, and a list of triangle faces w/indices corresponding to entries of the vertex list. """ cdef Py_ssize_t idx = 0 cdef Py_ssize_t n_tris = len(trilist) cdef Py_ssize_t i, j cdef dict vert_index = {} cdef list vert_list = [] cdef list face_list = [] cdef list templist # Iterate over triangles for i in range(n_tris): templist = [] # Only parse vertices from non-degenerate triangles if not ((trilist[i][0] == trilist[i][1]) or (trilist[i][0] == trilist[i][2]) or (trilist[i][1] == trilist[i][2])): # Iterate over vertices within each triangle for j in range(3): vert = trilist[i][j] # Check if a new unique vertex found if vert not in vert_index: vert_index[vert] = idx templist.append(idx) vert_list.append(vert) idx += 1 else: templist.append(vert_index[vert]) face_list.append(templist) return vert_list, face_list def iterate_and_store_3d(double[:, :, ::1] arr, double level, tuple spacing=(1., 1., 1.)): """Iterate across the given array in a marching-cubes fashion, looking for volumes with edges that cross 'level'. If such a volume is found, appropriate triangulations are added to a growing list of faces to be returned by this function. If `spacing` is not provided, vertices are returned in the indexing coordinate system (assuming all 3 spatial dimensions sampled equally). If `spacing` is provided, vertices will be returned in volume coordinates relative to the origin, regularly spaced as specified in each dimension. """ if arr.shape[0] < 2 or arr.shape[1] < 2 or arr.shape[2] < 2: raise ValueError("Input array must be at least 2x2x2.") if len(spacing) != 3: raise ValueError("`spacing` must be (double, double, double)") cdef list face_list = [] cdef list norm_list = [] cdef Py_ssize_t n cdef bint odd_spacing, plus_z plus_z = False if [float(i) for i in spacing] == [1.0, 1.0, 1.0]: odd_spacing = False else: odd_spacing = True # The plan is to iterate a 2x2x2 cube across the input array. This means # the upper-left corner of the cube needs to iterate across a sub-array # of size one-less-large in each direction (so we can get away with no # bounds checking in Cython). The cube is represented by eight vertices: # v1, v2, ..., v8, oriented thus (see Lorensen, Figure 4): # # v8 ------ v7 # / | / | y # / | / | ^ z # v4 ------ v3 | | / # | v5 ----|- v6 |/ (note: NOT right handed!) # | / | / ----> x # | / | / # v1 ------ v2 # # We also maintain the current 2D coordinates for v1, and ensure the array # is of type 'double' and is C-contiguous (last index varies fastest). # Coords start at (0, 0, 0). cdef Py_ssize_t[3] coords coords[0] = 0 coords[1] = 0 coords[2] = 0 # Extract doubles from `spacing` for speed cdef double[3] spacing2 spacing2[0] = spacing[0] spacing2[1] = spacing[1] spacing2[2] = spacing[2] # Calculate the number of iterations we'll need cdef Py_ssize_t num_cube_steps = ((arr.shape[0] - 1) * (arr.shape[1] - 1) * (arr.shape[2] - 1)) cdef unsigned char cube_case = 0 cdef tuple e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12 cdef double v1, v2, v3, v4, v5, v6, v7, v8, r0, r1, c0, c1, d0, d1 cdef Py_ssize_t x0, y0, z0, x1, y1, z1 e5, e6, e7, e8 = (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0) for n in range(num_cube_steps): # There are 255 unique values for `cube_case`. This algorithm follows # the Lorensen paper in vertex and edge labeling, however, it should # be noted that Lorensen used a left-handed coordinate system while # NumPy uses a proper right handed system. Transforming between these # coordinate systems was handled in the definitions of the cube # vertices v1, v2, ..., v8. # # Refer to the paper, figure 4, for cube edge designations e1, ... e12 # Standard Py_ssize_t coordinates for indexing x0, y0, z0 = coords[0], coords[1], coords[2] x1, y1, z1 = x0 + 1, y0 + 1, z0 + 1 if odd_spacing: # These doubles are the modified world coordinates; they are only # calculated if non-default `spacing` provided. r0 = coords[0] * spacing2[0] c0 = coords[1] * spacing2[1] d0 = coords[2] * spacing2[2] r1 = r0 + spacing2[0] c1 = c0 + spacing2[1] d1 = d0 + spacing2[2] else: r0, c0, d0, r1, c1, d1 = x0, y0, z0, x1, y1, z1 # We use a right-handed coordinate system, UNlike the paper, but want # to index in agreement - the coordinate adjustment takes place here. v1 = arr[x0, y0, z0] v2 = arr[x1, y0, z0] v3 = arr[x1, y1, z0] v4 = arr[x0, y1, z0] v5 = arr[x0, y0, z1] v6 = arr[x1, y0, z1] v7 = arr[x1, y1, z1] v8 = arr[x0, y1, z1] # Unique triangulation cases cube_case = 0 if (v1 > level): cube_case += 1 if (v2 > level): cube_case += 2 if (v3 > level): cube_case += 4 if (v4 > level): cube_case += 8 if (v5 > level): cube_case += 16 if (v6 > level): cube_case += 32 if (v7 > level): cube_case += 64 if (v8 > level): cube_case += 128 if (cube_case != 0 and cube_case != 255): # Only do anything if there's a plane intersecting the cube. # Cases 0 and 255 are entirely below/above the contour. if cube_case > 127: if ((cube_case != 150) and (cube_case != 170) and (cube_case != 195)): cube_case = 255 - cube_case # Calculate cube edges, to become triangulation vertices. # If we moved in a convenient direction, save 1/3 of the effort by # re-assigning prior results. if plus_z: # Reassign prior calculated edges e1 = e5 e2 = e6 e3 = e7 e4 = e8 else: # Calculate edges normally if odd_spacing: e1 = r0 + _get_fraction(v1, v2, level) * spacing2[0], c0, d0 e2 = r1, c0 + _get_fraction(v2, v3, level) * spacing2[1], d0 e3 = r0 + _get_fraction(v4, v3, level) * spacing2[0], c1, d0 e4 = r0, c0 + _get_fraction(v1, v4, level) * spacing2[1], d0 else: e1 = r0 + _get_fraction(v1, v2, level), c0, d0 e2 = r1, c0 + _get_fraction(v2, v3, level), d0 e3 = r0 + _get_fraction(v4, v3, level), c1, d0 e4 = r0, c0 + _get_fraction(v1, v4, level), d0 # These must be calculated at each point unless we implemented a # large, growing lookup table for all adjacent values; could save # ~30% in terms of runtime at the expense of memory usage and # much greater complexity. if odd_spacing: e5 = r0 + _get_fraction(v5, v6, level) * spacing2[0], c0, d1 e6 = r1, c0 + _get_fraction(v6, v7, level) * spacing2[1], d1 e7 = r0 + _get_fraction(v8, v7, level) * spacing2[0], c1, d1 e8 = r0, c0 + _get_fraction(v5, v8, level) * spacing2[1], d1 e9 = r0, c0, d0 + _get_fraction(v1, v5, level) * spacing2[2] e10 = r1, c0, d0 + _get_fraction(v2, v6, level) * spacing2[2] e11 = r0, c1, d0 + _get_fraction(v4, v8, level) * spacing2[2] e12 = r1, c1, d0 + _get_fraction(v3, v7, level) * spacing2[2] else: e5 = r0 + _get_fraction(v5, v6, level), c0, d1 e6 = r1, c0 + _get_fraction(v6, v7, level), d1 e7 = r0 + _get_fraction(v8, v7, level), c1, d1 e8 = r0, c0 + _get_fraction(v5, v8, level), d1 e9 = r0, c0, d0 + _get_fraction(v1, v5, level) e10 = r1, c0, d0 + _get_fraction(v2, v6, level) e11 = r0, c1, d0 + _get_fraction(v4, v8, level) e12 = r1, c1, d0 + _get_fraction(v3, v7, level) # Append appropriate triangles to the growing output `face_list` _append_tris(face_list, cube_case, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) # Advance the coords indices if coords[2] < arr.shape[2] - 2: coords[2] += 1 plus_z = True elif coords[1] < arr.shape[1] - 2: coords[1] += 1 coords[2] = 0 plus_z = False else: coords[0] += 1 coords[1] = 0 coords[2] = 0 plus_z = False return face_list def _append_tris(list face_list, unsigned char case, tuple e1, tuple e2, tuple e3, tuple e4, tuple e5, tuple e6, tuple e7, tuple e8, tuple e9, tuple e10, tuple e11, tuple e12): # Permits recursive use for duplicated planes to conserve code - it's # quite long enough as-is. if (case == 1): # front lower left corner face_list.append([e1, e4, e9]) elif (case == 2): # front lower right corner face_list.append([e10, e2, e1]) elif (case == 3): # front lower plane face_list.append([e2, e4, e9]) face_list.append([e2, e9, e10]) elif (case == 4): # front upper right corner face_list.append([e12, e3, e2]) elif (case == 5): # lower left, upper right corners _append_tris(face_list, 1, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 4, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 6): # front right plane face_list.append([e12, e3, e1]) face_list.append([e12, e1, e10]) elif (case == 7): # Shelf including v1, v2, v3 face_list.append([e3, e4, e12]) face_list.append([e4, e9, e12]) face_list.append([e12, e9, e10]) elif (case == 8): # front upper left corner face_list.append([e3, e11, e4]) elif (case == 9): # front left plane face_list.append([e3, e11, e9]) face_list.append([e3, e9, e1]) elif (case == 10): # upper left, lower right corners _append_tris(face_list, 2, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 11): # Shelf including v4, v1, v2 face_list.append([e3, e11, e2]) face_list.append([e11, e10, e2]) face_list.append([e11, e9, e10]) elif (case == 12): # front upper plane face_list.append([e11, e4, e12]) face_list.append([e2, e4, e12]) elif (case == 13): # Shelf including v1, v4, v3 face_list.append([e11, e9, e12]) face_list.append([e12, e9, e1]) face_list.append([e12, e1, e2]) elif (case == 14): # Shelf including v2, v3, v4 face_list.append([e11, e10, e12]) face_list.append([e11, e4, e10]) face_list.append([e4, e1, e10]) elif (case == 15): # Plane parallel to x-axis through middle face_list.append([e11, e9, e12]) face_list.append([e12, e9, e10]) elif (case == 16): # back lower left corner face_list.append([e8, e9, e5]) elif (case == 17): # lower left plane face_list.append([e4, e1, e8]) face_list.append([e8, e1, e5]) elif (case == 18): # lower left back, lower right front corners _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 2, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 19): # Shelf including v1, v2, v5 face_list.append([e8, e4, e2]) face_list.append([e8, e2, e10]) face_list.append([e8, e10, e5]) elif (case == 20): # lower left back, upper right front corners _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 4, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 21): # lower left plane + upper right front corner, v1, v3, v5 _append_tris(face_list, 17, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 4, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 22): # front right plane + lower left back corner, v2, v3, v5 _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 6, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 23): # Rotated case 14 in the paper face_list.append([e3, e10, e8]) face_list.append([e3, e10, e12]) face_list.append([e8, e10, e5]) face_list.append([e3, e4, e8]) elif (case == 24): # upper front left, lower back left corners _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 25): # Shelf including v1, v4, v5 face_list.append([e1, e5, e3]) face_list.append([e3, e8, e11]) face_list.append([e3, e5, e8]) elif (case == 26): # Three isolated corners _append_tris(face_list, 2, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 27): # Full corner v1, case 9 in paper: (v1, v2, v4, v5) face_list.append([e11, e3, e2]) face_list.append([e11, e2, e10]) face_list.append([e10, e11, e8]) face_list.append([e8, e5, e10]) elif (case == 28): # upper front plane + corner v5 _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 12, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 29): # special case of 11 in the paper: (v1, v3, v4, v5) face_list.append([e11, e5, e2]) face_list.append([e11, e12, e2]) face_list.append([e11, e5, e8]) face_list.append([e2, e1, e5]) elif (case == 30): # Shelf (v2, v3, v4) and lower left back corner _append_tris(face_list, 14, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 31): # Shelf: (v6, v7, v8) by inversion face_list.append([e11, e12, e10]) face_list.append([e11, e8, e10]) face_list.append([e8, e10, e5]) elif (case == 32): # lower right back corner face_list.append([e6, e5, e10]) elif (case == 33): # lower right back, lower left front corners _append_tris(face_list, 1, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 32, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 34): # lower right plane face_list.append([e1, e2, e5]) face_list.append([e2, e6, e5]) elif (case == 35): # Shelf: v1, v2, v6 face_list.append([e4, e2, e6]) face_list.append([e4, e9, e6]) face_list.append([e6, e9, e5]) elif (case == 36): # upper right front, lower right back corners _append_tris(face_list, 32, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 4, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 37): # lower left front, upper right front, lower right back corners _append_tris(face_list, 32, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 4, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 1, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 38): # Shelf: v2, v3, v6 face_list.append([e3, e1, e5]) face_list.append([e3, e5, e12]) face_list.append([e12, e5, e6]) elif (case == 39): # Full corner v2: (v1, v2, v3, v6) face_list.append([e3, e4, e5]) face_list.append([e4, e9, e5]) face_list.append([e3, e5, e6]) face_list.append([e3, e12, e6]) elif (case == 40): # upper left front, lower right back corners _append_tris(face_list, 32, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 41): # front left plane, lower right back corner _append_tris(face_list, 32, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 9, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 42): # lower right plane, upper front left corner _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 34, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 43): # Rotated case 11 in paper face_list.append([e11, e3, e9]) face_list.append([e3, e9, e6]) face_list.append([e3, e2, e6]) face_list.append([e9, e5, e6]) elif (case == 44): # upper front plane, lower right back corner _append_tris(face_list, 12, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 32, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 45): # Shelf: (v1, v3, v4) + lower right back corner _append_tris(face_list, 13, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 32, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 46): # Rotated case 14 in paper face_list.append([e4, e11, e12]) face_list.append([e4, e12, e5]) face_list.append([e12, e5, e6]) face_list.append([e4, e5, e1]) elif (case == 47): # Shelf: (v5, v8, v7) by inversion face_list.append([e11, e9, e12]) face_list.append([e12, e9, e5]) face_list.append([e12, e5, e6]) elif (case == 48): # Back lower plane face_list.append([e9, e10, e6]) face_list.append([e9, e6, e8]) elif (case == 49): # Shelf: (v1, v5, v6) face_list.append([e4, e8, e6]) face_list.append([e4, e6, e1]) face_list.append([e6, e1, e10]) elif (case == 50): # Shelf: (v2, v5, v6) face_list.append([e8, e6, e2]) face_list.append([e8, e2, e1]) face_list.append([e8, e9, e1]) elif (case == 51): # Plane through middle of cube, parallel to x-z axis face_list.append([e4, e8, e2]) face_list.append([e8, e2, e6]) elif (case == 52): # Back lower plane, and front upper right corner _append_tris(face_list, 48, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 4, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 53): # Shelf (v1, v5, v6) and front upper right corner _append_tris(face_list, 49, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 4, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 54): # Rotated case 11 from paper (v2, v3, v5, v6) face_list.append([e1, e9, e3]) face_list.append([e9, e3, e6]) face_list.append([e9, e8, e6]) face_list.append([e12, e3, e6]) elif (case == 55): # Shelf: (v4, v8, v7) by inversion face_list.append([e4, e8, e6]) face_list.append([e4, e6, e3]) face_list.append([e6, e3, e12]) elif (case == 56): # Back lower plane + upper left front corner _append_tris(face_list, 48, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 57): # Rotated case 14 from paper (v4, v1, v5, v6) face_list.append([e3, e11, e8]) face_list.append([e3, e8, e10]) face_list.append([e10, e6, e8]) face_list.append([e3, e1, e10]) elif (case == 58): # Shelf: (v2, v6, v5) + upper left front corner _append_tris(face_list, 50, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 59): # Shelf: (v3, v7, v8) by inversion face_list.append([e2, e6, e8]) face_list.append([e8, e2, e3]) face_list.append([e8, e3, e11]) elif (case == 60): # AMBIGUOUS CASE: parallel planes (front upper, back lower) _append_tris(face_list, 48, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 12, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 61): # Upper back plane + lower right front corner by inversion _append_tris(face_list, 63, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 2, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 62): # Upper back plane + lower left front corner by inversion _append_tris(face_list, 63, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 1, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 63): # Upper back plane face_list.append([e11, e12, e6]) face_list.append([e11, e8, e6]) elif (case == 64): # Upper right back corner face_list.append([e12, e7, e6]) elif (case == 65): # upper right back, lower left front corners _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 1, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 66): # upper right back, lower right front corners _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 2, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 67): # lower front plane + upper right back corner _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 3, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 68): # upper right plane face_list.append([e3, e2, e6]) face_list.append([e3, e7, e6]) elif (case == 69): # Upper right plane, lower left front corner _append_tris(face_list, 68, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 1, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 70): # Shelf: (v2, v3, v7) face_list.append([e1, e3, e7]) face_list.append([e1, e10, e7]) face_list.append([e7, e10, e6]) elif (case == 71): # Rotated version of case 11 in paper (v1, v2, v3, v7) face_list.append([e10, e7, e4]) face_list.append([e4, e3, e7]) face_list.append([e10, e4, e9]) face_list.append([e7, e10, e6]) elif (case == 72): # upper left front, upper right back corners _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 73): # front left plane, upper right back corner _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 9, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 74): # Three isolated corners, exactly case 7 in paper _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 2, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 75): # Shelf: (v1, v2, v4) + upper right back corner _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 11, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 76): # Shelf: (v4, v3, v7) face_list.append([e4, e2, e6]) face_list.append([e4, e11, e7]) face_list.append([e4, e7, e6]) elif (case == 77): # Rotated case 14 in paper (v1, v4, v3, v7) face_list.append([e11, e9, e1]) face_list.append([e11, e1, e6]) face_list.append([e1, e6, e2]) face_list.append([e11, e6, e7]) elif (case == 78): # Full corner v3: (v2, v3, v4, v7) face_list.append([e1, e4, e7]) face_list.append([e1, e7, e6]) face_list.append([e4, e11, e7]) face_list.append([e1, e10, e6]) elif (case == 79): # Shelf: (v6, v5, v8) by inversion face_list.append([e9, e11, e10]) face_list.append([e11, e7, e10]) face_list.append([e7, e10, e6]) elif (case == 80): # lower left back, upper right back corners (v5, v7) _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 81): # lower left plane, upper right back corner _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 17, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 82): # isolated corners (v2, v5, v7) _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 2, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 83): # Shelf: (v1, v2, v5) + upper right back corner _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 19, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 84): # upper right plane, lower left back corner _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 68, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 85): # AMBIGUOUS CASE: upper right and lower left parallel planes _append_tris(face_list, 17, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 68, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 86): # Shelf: (v2, v3, v7) + lower left back corner _append_tris(face_list, 70, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 87): # Upper left plane + lower right back corner, by inversion _append_tris(face_list, 119, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 32, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 88): # Isolated corners v4, v5, v7 _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 89): # Shelf: (v1, v4, v5) + isolated corner v7 _append_tris(face_list, 25, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 90): # Four isolated corners v2, v4, v5, v7 _append_tris(face_list, 2, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 64, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 91): # Three isolated corners, v3, v6, v8 by inversion _append_tris(face_list, 4, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 32, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 127, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 92): # Shelf (v4, v3, v7) + isolated corner v5 _append_tris(face_list, 76, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 16, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 93): # Lower right plane + isolated corner v8 by inversion _append_tris(face_list, 127, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 34, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 94): # Isolated corners v1, v6, v8 by inversion _append_tris(face_list, 1, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 32, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 127, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 95): # Isolated corners v6, v8 by inversion _append_tris(face_list, 32, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 127, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 96): # back right plane face_list.append([e7, e12, e5]) face_list.append([e5, e10, e12]) elif (case == 97): # back right plane + isolated corner v1 _append_tris(face_list, 96, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 1, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 98): # Shelf: (v2, v6, v7) face_list.append([e1, e7, e5]) face_list.append([e7, e1, e12]) face_list.append([e1, e12, e2]) elif (case == 99): # Rotated case 14 in paper: (v1, v2, v6, v7) face_list.append([e9, e2, e7]) face_list.append([e9, e2, e4]) face_list.append([e2, e7, e12]) face_list.append([e7, e9, e5]) elif (case == 100): # Shelf: (v3, v6, v7) face_list.append([e3, e7, e5]) face_list.append([e3, e5, e2]) face_list.append([e2, e5, e10]) elif (case == 101): # Shelf: (v3, v6, v7) + isolated corner v1 _append_tris(face_list, 100, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 1, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 102): # Plane bisecting left-right halves of cube face_list.append([e1, e3, e7]) face_list.append([e1, e7, e5]) elif (case == 103): # Shelf: (v4, v5, v8) by inversion face_list.append([e3, e7, e5]) face_list.append([e3, e5, e4]) face_list.append([e4, e5, e9]) elif (case == 104): # Back right plane + isolated corner v4 _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 96, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 105): # AMBIGUOUS CASE: back right and front left planes _append_tris(face_list, 96, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 9, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 106): # Shelf: (v2, v6, v7) + isolated corner v4 _append_tris(face_list, 98, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 107): # Back left plane + isolated corner v3 by inversion _append_tris(face_list, 4, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 111, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 108): # Rotated case 11 from paper: (v4, v3, v7, v6) face_list.append([e4, e10, e7]) face_list.append([e4, e10, e2]) face_list.append([e4, e11, e7]) face_list.append([e7, e10, e5]) elif (case == 109): # Back left plane + isolated corner v2 by inversion _append_tris(face_list, 111, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 2, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 110): # Shelf: (v1, v5, v8) by inversion face_list.append([e1, e5, e7]) face_list.append([e1, e7, e11]) face_list.append([e1, e11, e4]) elif (case == 111): # Back left plane face_list.append([e11, e9, e7]) face_list.append([e9, e7, e5]) elif (case == 112): # Shelf: (v5, v6, v7) face_list.append([e9, e10, e12]) face_list.append([e9, e12, e7]) face_list.append([e9, e7, e8]) elif (case == 113): # Exactly case 11 from paper: (v1, v5, v6, v7) face_list.append([e1, e8, e12]) face_list.append([e1, e8, e4]) face_list.append([e8, e7, e12]) face_list.append([e12, e1, e10]) elif (case == 114): # Full corner v6: (v2, v6, v7, v5) face_list.append([e1, e9, e7]) face_list.append([e1, e7, e12]) face_list.append([e1, e12, e2]) face_list.append([e9, e8, e7]) elif (case == 115): # Shelf: (v3, v4, v8) face_list.append([e2, e4, e8]) face_list.append([e2, e12, e7]) face_list.append([e2, e8, e7]) elif (case == 116): # Rotated case 14 in paper: (v5, v6, v7, v3) face_list.append([e9, e2, e7]) face_list.append([e9, e2, e10]) face_list.append([e9, e8, e7]) face_list.append([e2, e3, e7]) elif (case == 117): # upper left plane + isolated corner v2 by inversion _append_tris(face_list, 2, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 119, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 118): # Shelf: (v1, v4, v8) face_list.append([e1, e3, e7]) face_list.append([e7, e1, e8]) face_list.append([e1, e8, e9]) elif (case == 119): # Upper left plane face_list.append([e4, e3, e7]) face_list.append([e4, e8, e7]) elif (case == 120): # Shelf: (v5, v6, v7) + isolated corner v4 _append_tris(face_list, 112, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 8, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 121): # Front right plane + isolated corner v8 _append_tris(face_list, 6, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 127, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 122): # Isolated corners v1, v3, v8 _append_tris(face_list, 1, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 4, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 127, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 123): # Isolated corners v3, v8 _append_tris(face_list, 4, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 127, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 124): # Front lower plane + isolated corner v8 _append_tris(face_list, 3, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 127, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 125): # Isolated corners v2, v8 _append_tris(face_list, 2, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 127, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 126): # Isolated corners v1, v8 _append_tris(face_list, 1, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 127, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 127): # Isolated corner v8 face_list.append([e11, e7, e8]) elif (case == 150): # AMBIGUOUS CASE: back right and front left planes # In these cube_case > 127 cases, the vertices are identical BUT # they are connected in the opposite fashion. _append_tris(face_list, 6, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 111, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 170): # AMBIGUOUS CASE: upper left and lower right planes # In these cube_case > 127 cases, the vertices are identical BUT # they are connected in the opposite fashion. _append_tris(face_list, 119, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 34, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) elif (case == 195): # AMBIGUOUS CASE: back upper and front lower planes # In these cube_case > 127 cases, the vertices are identical BUT # they are connected in the opposite fashion. _append_tris(face_list, 63, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) _append_tris(face_list, 3, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) return scikit-image-0.9.3/skimage/measure/_moments.pyx000066400000000000000000000135041223313777300215500ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np def moments(double[:, :] image, Py_ssize_t order=3): """Calculate all raw image moments up to a certain order. The following properties can be calculated from raw image moments: * Area as ``m[0, 0]``. * Centroid as {``m[0, 1] / m[0, 0]``, ``m[1, 0] / m[0, 0]``}. Note that raw moments are whether translation, scale nor rotation invariant. Parameters ---------- image : 2D double array Rasterized shape as image. order : int, optional Maximum order of moments. Default is 3. Returns ------- m : (``order + 1``, ``order + 1``) array Raw image moments. References ---------- .. [1] Wilhelm Burger, Mark Burge. Principles of Digital Image Processing: Core Algorithms. Springer-Verlag, London, 2009. .. [2] B. Jähne. Digital Image Processing. Springer-Verlag, Berlin-Heidelberg, 6. edition, 2005. .. [3] T. H. Reiss. Recognizing Planar Objects Using Invariant Image Features, from Lecture notes in computer science, p. 676. Springer, Berlin, 1993. .. [4] http://en.wikipedia.org/wiki/Image_moment """ return moments_central(image, 0, 0, order) def moments_central(double[:, :] image, double cr, double cc, Py_ssize_t order=3): """Calculate all central image moments up to a certain order. Note that central moments are translation invariant but not scale and rotation invariant. Parameters ---------- image : 2D double array Rasterized shape as image. cr : double Center row coordinate. cc : double Center column coordinate. order : int, optional Maximum order of moments. Default is 3. Returns ------- mu : (``order + 1``, ``order + 1``) array Central image moments. References ---------- .. [1] Wilhelm Burger, Mark Burge. Principles of Digital Image Processing: Core Algorithms. Springer-Verlag, London, 2009. .. [2] B. Jähne. Digital Image Processing. Springer-Verlag, Berlin-Heidelberg, 6. edition, 2005. .. [3] T. H. Reiss. Recognizing Planar Objects Using Invariant Image Features, from Lecture notes in computer science, p. 676. Springer, Berlin, 1993. .. [4] http://en.wikipedia.org/wiki/Image_moment """ cdef Py_ssize_t p, q, r, c cdef double[:, ::1] mu = np.zeros((order + 1, order + 1), dtype=np.double) for p in range(order + 1): for q in range(order + 1): for r in range(image.shape[0]): for c in range(image.shape[1]): mu[p, q] += image[r, c] * (r - cr) ** q * (c - cc) ** p return np.asarray(mu) def moments_normalized(double[:, :] mu, Py_ssize_t order=3): """Calculate all normalized central image moments up to a certain order. Note that normalized central moments are translation and scale invariant but not rotation invariant. Parameters ---------- mu : (M, M) array Central image moments, where M must be > ``order``. order : int, optional Maximum order of moments. Default is 3. Returns ------- nu : (``order + 1``, ``order + 1``) array Normalized central image moments. References ---------- .. [1] Wilhelm Burger, Mark Burge. Principles of Digital Image Processing: Core Algorithms. Springer-Verlag, London, 2009. .. [2] B. Jähne. Digital Image Processing. Springer-Verlag, Berlin-Heidelberg, 6. edition, 2005. .. [3] T. H. Reiss. Recognizing Planar Objects Using Invariant Image Features, from Lecture notes in computer science, p. 676. Springer, Berlin, 1993. .. [4] http://en.wikipedia.org/wiki/Image_moment """ cdef Py_ssize_t p, q cdef double[:, ::1] nu = np.zeros((order + 1, order + 1), dtype=np.double) for p in range(order + 1): for q in range(order + 1): if p + q >= 2: nu[p, q] = mu[p, q] / mu[0, 0] ** ((p + q) / 2 + 1) else: nu[p, q] = np.nan return np.asarray(nu) def moments_hu(double[:, :] nu): """Calculate Hu's set of image moments. Note that this set of moments is proofed to be translation, scale and rotation invariant. Parameters ---------- nu : (M, M) array Normalized central image moments, where M must be > 4. Returns ------- nu : (7, 1) array Hu's set of image moments. References ---------- .. [1] M. K. Hu, "Visual Pattern Recognition by Moment Invariants", IRE Trans. Info. Theory, vol. IT-8, pp. 179-187, 1962 .. [2] Wilhelm Burger, Mark Burge. Principles of Digital Image Processing: Core Algorithms. Springer-Verlag, London, 2009. .. [3] B. Jähne. Digital Image Processing. Springer-Verlag, Berlin-Heidelberg, 6. edition, 2005. .. [4] T. H. Reiss. Recognizing Planar Objects Using Invariant Image Features, from Lecture notes in computer science, p. 676. Springer, Berlin, 1993. .. [5] http://en.wikipedia.org/wiki/Image_moment """ cdef double[::1] hu = np.zeros((7, ), dtype=np.double) cdef double t0 = nu[3, 0] + nu[1, 2] cdef double t1 = nu[2, 1] + nu[0, 3] cdef double q0 = t0 * t0 cdef double q1 = t1 * t1 cdef double n4 = 4 * nu[1, 1] cdef double s = nu[2, 0] + nu[0, 2] cdef double d = nu[2, 0] - nu[0, 2] hu[0] = s hu[1] = d * d + n4 * nu[1, 1] hu[3] = q0 + q1 hu[5] = d * (q0 - q1) + n4 * t0 * t1 t0 *= q0 - 3 * q1 t1 *= 3 * q0 - q1 q0 = nu[3, 0]- 3 * nu[1, 2] q1 = 3 * nu[2, 1] - nu[0, 3] hu[2] = q0 * q0 + q1 * q1 hu[4] = q0 * t0 + q1 * t1 hu[6] = q1 * t0 - q0 * t1 return np.asarray(hu) scikit-image-0.9.3/skimage/measure/_polygon.py000066400000000000000000000123561223313777300213710ustar00rootroot00000000000000import numpy as np from scipy import signal def approximate_polygon(coords, tolerance): """Approximate a polygonal chain with the specified tolerance. It is based on the Douglas-Peucker algorithm. Note that the approximated polygon is always within the convex hull of the original polygon. Parameters ---------- coords : (N, 2) array Coordinate array. tolerance : float Maximum distance from original points of polygon to approximated polygonal chain. If tolerance is 0, the original coordinate array is returned. Returns ------- coords : (M, 2) array Approximated polygonal chain where M <= N. References ---------- .. [1] http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm """ if tolerance <= 0: return coords chain = np.zeros(coords.shape[0], 'bool') # pre-allocate distance array for all points dists = np.zeros(coords.shape[0]) chain[0] = True chain[-1] = True pos_stack = [(0, chain.shape[0] - 1)] end_of_chain = False while not end_of_chain: start, end = pos_stack.pop() # determine properties of current line segment r0, c0 = coords[start, :] r1, c1 = coords[end, :] dr = r1 - r0 dc = c1 - c0 segment_angle = - np.arctan2(dr, dc) segment_dist = c0 * np.sin(segment_angle) + r0 * np.cos(segment_angle) # select points in-between line segment segment_coords = coords[start + 1:end, :] segment_dists = dists[start + 1:end] # check whether to take perpendicular or euclidean distance with # inner product of vectors # vectors from points -> start and end dr0 = segment_coords[:, 0] - r0 dc0 = segment_coords[:, 1] - c0 dr1 = segment_coords[:, 0] - r1 dc1 = segment_coords[:, 1] - c1 # vectors points -> start and end projected on start -> end vector projected_lengths0 = dr0 * dr + dc0 * dc projected_lengths1 = - dr1 * dr - dc1 * dc perp = np.logical_and(projected_lengths0 > 0, projected_lengths1 > 0) eucl = np.logical_not(perp) segment_dists[perp] = np.abs( segment_coords[perp, 0] * np.cos(segment_angle) + segment_coords[perp, 1] * np.sin(segment_angle) - segment_dist ) segment_dists[eucl] = np.minimum( # distance to start point np.sqrt(dc0[eucl] ** 2 + dr0[eucl] ** 2), # distance to end point np.sqrt(dc1[eucl] ** 2 + dr1[eucl] ** 2) ) if np.any(segment_dists > tolerance): # select point with maximum distance to line new_end = start + np.argmax(segment_dists) + 1 pos_stack.append((new_end, end)) pos_stack.append((start, new_end)) chain[new_end] = True if len(pos_stack) == 0: end_of_chain = True return coords[chain, :] # B-Spline subdivision _SUBDIVISION_MASKS = { # degree: (mask_even, mask_odd) # extracted from (degree + 2)th row of Pascal's triangle 1: ([1, 1], [1, 1]), 2: ([3, 1], [1, 3]), 3: ([1, 6, 1], [0, 4, 4]), 4: ([5, 10, 1], [1, 10, 5]), 5: ([1, 15, 15, 1], [0, 6, 20, 6]), 6: ([7, 35, 21, 1], [1, 21, 35, 7]), 7: ([1, 28, 70, 28, 1], [0, 8, 56, 56, 8]), } def subdivide_polygon(coords, degree=2, preserve_ends=False): """Subdivision of polygonal curves using B-Splines. Note that the resulting curve is always within the convex hull of the original polygon. Circular polygons stay closed after subdivision. Parameters ---------- coords : (N, 2) array Coordinate array. degree : {1, 2, 3, 4, 5, 6, 7}, optional Degree of B-Spline. Default is 2. preserve_ends : bool, optional Preserve first and last coordinate of non-circular polygon. Default is False. Returns ------- coords : (M, 2) array Subdivided coordinate array. References ---------- .. [1] http://mrl.nyu.edu/publications/subdiv-course2000/coursenotes00.pdf """ if degree not in _SUBDIVISION_MASKS: raise ValueError("Invalid B-Spline degree. Only degree 1 - 7 is " "supported.") circular = np.all(coords[0, :] == coords[-1, :]) method = 'valid' if circular: # remove last coordinate because of wrapping coords = coords[:-1, :] # circular convolution by wrapping boundaries method = 'same' mask_even, mask_odd = _SUBDIVISION_MASKS[degree] # divide by total weight mask_even = np.array(mask_even, np.float) / (2 ** degree) mask_odd = np.array(mask_odd, np.float) / (2 ** degree) even = signal.convolve2d(coords.T, np.atleast_2d(mask_even), mode=method, boundary='wrap') odd = signal.convolve2d(coords.T, np.atleast_2d(mask_odd), mode=method, boundary='wrap') out = np.zeros((even.shape[1] + odd.shape[1], 2)) out[1::2] = even.T out[::2] = odd.T if circular: # close polygon out = np.vstack([out, out[0, :]]) if preserve_ends and not circular: out = np.vstack([coords[0, :], out, coords[-1, :]]) return out scikit-image-0.9.3/skimage/measure/_regionprops.py000066400000000000000000000440221223313777300222440ustar00rootroot00000000000000# coding: utf-8 import warnings from math import sqrt, atan2, pi as PI import numpy as np from scipy import ndimage from collections import MutableMapping from skimage.morphology import convex_hull_image, label from skimage.measure import _moments __all__ = ['regionprops', 'perimeter'] STREL_4 = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]], dtype=np.uint8) STREL_8 = np.ones((3, 3), dtype=np.uint8) PROPS = { 'Area': 'area', 'BoundingBox': 'bbox', 'CentralMoments': 'moments_central', 'Centroid': 'centroid', 'ConvexArea': 'convex_area', # 'ConvexHull', 'ConvexImage': 'convex_image', 'Coordinates': 'coords', 'Eccentricity': 'eccentricity', 'EquivDiameter': 'equivalent_diameter', 'EulerNumber': 'euler_number', 'Extent': 'extent', # 'Extrema', 'FilledArea': 'filled_area', 'FilledImage': 'filled_image', 'HuMoments': 'moments_hu', 'Image': 'image', 'Label': 'label', 'MajorAxisLength': 'major_axis_length', 'MaxIntensity': 'max_intensity', 'MeanIntensity': 'mean_intensity', 'MinIntensity': 'min_intensity', 'MinorAxisLength': 'minor_axis_length', 'Moments': 'moments', 'NormalizedMoments': 'moments_normalized', 'Orientation': 'orientation', 'Perimeter': 'perimeter', # 'PixelIdxList', # 'PixelList', 'Solidity': 'solidity', # 'SubarrayIdx' 'WeightedCentralMoments': 'weighted_moments_central', 'WeightedCentroid': 'weighted_centroid', 'WeightedHuMoments': 'weighted_moments_hu', 'WeightedMoments': 'weighted_moments', 'WeightedNormalizedMoments': 'weighted_moments_normalized' } class _cached_property(object): """Decorator to use a function as a cached property. The function is only called the first time and each successive call returns the cached result of the first call. class Foo(object): @_cached_property def foo(self): return "Cached" class Foo(object): def __init__(self): self._cache_active = False @_cached_property def foo(self): return "Not cached" Adapted from . """ def __init__(self, func, name=None, doc=None): self.__name__ = name or func.__name__ self.__module__ = func.__module__ self.__doc__ = doc or func.__doc__ self.func = func def __get__(self, obj, type=None): if obj is None: return self # call every time, if cache is not active if not obj.__dict__.get('_cache_active', True): return self.func(obj) # try to retrieve from cache or call and store result in cache try: value = obj.__dict__[self.__name__] except KeyError: value = self.func(obj) obj.__dict__[self.__name__] = value return value class _RegionProperties(MutableMapping): def __init__(self, slice, label, label_image, intensity_image, cache_active, properties=None): self.label = label self._slice = slice self._label_image = label_image self._intensity_image = intensity_image self._cache_active = cache_active self._properties = properties @_cached_property def area(self): return self.moments[0, 0] @_cached_property def bbox(self): return (self._slice[0].start, self._slice[1].start, self._slice[0].stop, self._slice[1].stop) @_cached_property def centroid(self): row, col = self.local_centroid return row + self._slice[0].start, col + self._slice[1].start @_cached_property def convex_area(self): return np.sum(self.convex_image) @_cached_property def convex_image(self): return convex_hull_image(self.image) @_cached_property def coords(self): rr, cc = np.nonzero(self.image) return np.vstack((rr + self._slice[0].start, cc + self._slice[1].start)).T @_cached_property def eccentricity(self): l1, l2 = self.inertia_tensor_eigvals if l1 == 0: return 0 return sqrt(1 - l2 / l1) @_cached_property def equivalent_diameter(self): return sqrt(4 * self.moments[0, 0] / PI) @_cached_property def euler_number(self): euler_array = self.filled_image != self.image _, num = label(euler_array, neighbors=8, return_num=True) return -num + 1 @_cached_property def extent(self): rows, cols = self.image.shape return self.moments[0, 0] / (rows * cols) @_cached_property def filled_area(self): return np.sum(self.filled_image) @_cached_property def filled_image(self): return ndimage.binary_fill_holes(self.image, STREL_8) @_cached_property def image(self): return self._label_image[self._slice] == self.label @_cached_property def _image_double(self): return self.image.astype(np.double) @_cached_property def inertia_tensor(self): mu = self.moments_central a = mu[2, 0] / mu[0, 0] b = -mu[1, 1] / mu[0, 0] c = mu[0, 2] / mu[0, 0] return np.array([[a, b], [b, c]]) @_cached_property def inertia_tensor_eigvals(self): a, b, b, c = self.inertia_tensor.flat # eigen values of inertia tensor l1 = (a + c) / 2 + sqrt(4 * b ** 2 + (a - c) ** 2) / 2 l2 = (a + c) / 2 - sqrt(4 * b ** 2 + (a - c) ** 2) / 2 return l1, l2 @_cached_property def intensity_image(self): if self._intensity_image is None: raise AttributeError('No intensity image specified.') return self._intensity_image[self._slice] * self.image @_cached_property def _intensity_image_double(self): return self.intensity_image.astype(np.double) @_cached_property def local_centroid(self): m = self.moments row = m[0, 1] / m[0, 0] col = m[1, 0] / m[0, 0] return row, col @_cached_property def max_intensity(self): return np.max(self.intensity_image[self.image]) @_cached_property def mean_intensity(self): return np.mean(self.intensity_image[self.image]) @_cached_property def min_intensity(self): return np.min(self.intensity_image[self.image]) @_cached_property def major_axis_length(self): l1, _ = self.inertia_tensor_eigvals return 4 * sqrt(l1) @_cached_property def minor_axis_length(self): _, l2 = self.inertia_tensor_eigvals return 4 * sqrt(l2) @_cached_property def moments(self): return _moments.moments(self._image_double, 3) @_cached_property def moments_central(self): row, col = self.local_centroid return _moments.moments_central(self._image_double, row, col, 3) @_cached_property def moments_hu(self): return _moments.moments_hu(self.moments_normalized) @_cached_property def moments_normalized(self): return _moments.moments_normalized(self.moments_central, 3) @_cached_property def orientation(self): a, b, b, c = self.inertia_tensor.flat b = -b if a - c == 0: if b > 0: return -PI / 4. else: return PI / 4. else: return - 0.5 * atan2(2 * b, (a - c)) @_cached_property def perimeter(self): return perimeter(self.image, 4) @_cached_property def solidity(self): return self.moments[0, 0] / np.sum(self.convex_image) @_cached_property def weighted_centroid(self): row, col = self.weighted_local_centroid return row + self._slice[0].start, col + self._slice[1].start @_cached_property def weighted_local_centroid(self): m = self.weighted_moments row = m[0, 1] / m[0, 0] col = m[1, 0] / m[0, 0] return row, col @_cached_property def weighted_moments(self): return _moments.moments_central(self._intensity_image_double, 0, 0, 3) @_cached_property def weighted_moments_central(self): row, col = self.weighted_local_centroid return _moments.moments_central(self._intensity_image_double, row, col, 3) @_cached_property def weighted_moments_hu(self): return _moments.moments_hu(self.weighted_moments_normalized) @_cached_property def weighted_moments_normalized(self): return _moments.moments_normalized(self.weighted_moments_central, 3) # Preserve dictionary interface def __delitem__(self, key): pass def __len__(self): return len(self._properties or PROPS.values()) def __setitem__(self, key, value): raise RuntimeError("Cannot assign region properties.") def __iter__(self): return iter(self._properties or PROPS.values()) def __getitem__(self, key): value = getattr(self, key, None) if value is not None: return value else: # backwards compatability warnings.warn('Usage of deprecated property name.', category=DeprecationWarning) return getattr(self, PROPS[key]) def regionprops(label_image, properties=None, intensity_image=None, cache=True): """Measure properties of labelled image regions. Parameters ---------- label_image : (N, M) ndarray Labelled input image. properties : {'all', list} **Deprecated parameter** This parameter is not needed any more since all properties are determined dynamically. intensity_image : (N, M) ndarray, optional Intensity image with same size as labelled image. Default is None. cache : bool, optional Determine whether to cache calculated properties. The computation is much faster for cached properties, whereas the memory consumption increases. Returns ------- properties : list List containing a properties for each region. The properties of each region can be accessed as attributes and keys. Notes ----- The following properties can be accessed as attributes or keys: **area** : int Number of pixels of region. **bbox** : tuple Bounding box ``(min_row, min_col, max_row, max_col)`` **centroid** : array Centroid coordinate tuple ``(row, col)``. **convex_area** : int Number of pixels of convex hull image. **convex_image** : (H, J) ndarray Binary convex hull image which has the same size as bounding box. **coords** : (N, 2) ndarray Coordinate list ``(row, col)`` of the region. **eccentricity** : float Eccentricity of the ellipse that has the same second-moments as the region. The eccentricity is the ratio of the distance between its minor and major axis length. The value is between 0 and 1. **equivalent_diameter** : float The diameter of a circle with the same area as the region. **euler_number** : int Euler number of region. Computed as number of objects (= 1) subtracted by number of holes (8-connectivity). **extent** : float Ratio of pixels in the region to pixels in the total bounding box. Computed as ``area / (rows * cols)`` **filled_area** : int Number of pixels of filled region. **filled_image** : (H, J) ndarray Binary region image with filled holes which has the same size as bounding box. **image** : (H, J) ndarray Sliced binary region image which has the same size as bounding box. **inertia_tensor** : (2, 2) ndarray Inertia tensor of the region for the rotation around its mass. **inertia_tensor_eigvals** : tuple The two eigen values of the inertia tensor in decreasing order. **label** : int The label in the labeled input image. **major_axis_length** : float The length of the major axis of the ellipse that has the same normalized second central moments as the region. **min_intensity** : float Value with the greatest intensity in the region. **mean_intensity** : float Value with the mean intensity in the region. **min_intensity** : float Value with the least intensity in the region. **minor_axis_length** : float The length of the minor axis of the ellipse that has the same normalized second central moments as the region. **moments** : (3, 3) ndarray Spatial moments up to 3rd order:: m_ji = sum{ array(x, y) * x^j * y^i } where the sum is over the `x`, `y` coordinates of the region. **moments_central** : (3, 3) ndarray Central moments (translation invariant) up to 3rd order:: mu_ji = sum{ array(x, y) * (x - x_c)^j * (y - y_c)^i } where the sum is over the `x`, `y` coordinates of the region, and `x_c` and `y_c` are the coordinates of the region's centroid. **moments_hu** : tuple Hu moments (translation, scale and rotation invariant). **moments_normalized** : (3, 3) ndarray Normalized moments (translation and scale invariant) up to 3rd order:: nu_ji = mu_ji / m_00^[(i+j)/2 + 1] where `m_00` is the zeroth spatial moment. **orientation** : float Angle between the X-axis and the major axis of the ellipse that has the same second-moments as the region. Ranging from `-pi/2` to `pi/2` in counter-clockwise direction. **perimeter** : float Perimeter of object which approximates the contour as a line through the centers of border pixels using a 4-connectivity. **solidity** : float Ratio of pixels in the region to pixels of the convex hull image. **weighted_centroid** : array Centroid coordinate tuple ``(row, col)`` weighted with intensity image. **weighted_moments** : (3, 3) ndarray Spatial moments of intensity image up to 3rd order:: wm_ji = sum{ array(x, y) * x^j * y^i } where the sum is over the `x`, `y` coordinates of the region. **weighted_moments_central** : (3, 3) ndarray Central moments (translation invariant) of intensity image up to 3rd order:: wmu_ji = sum{ array(x, y) * (x - x_c)^j * (y - y_c)^i } where the sum is over the `x`, `y` coordinates of the region, and `x_c` and `y_c` are the coordinates of the region's centroid. **weighted_moments_hu** : tuple Hu moments (translation, scale and rotation invariant) of intensity image. **weighted_moments_normalized** : (3, 3) ndarray Normalized moments (translation and scale invariant) of intensity image up to 3rd order:: wnu_ji = wmu_ji / wm_00^[(i+j)/2 + 1] where `wm_00` is the zeroth spatial moment (intensity-weighted area). References ---------- .. [1] Wilhelm Burger, Mark Burge. Principles of Digital Image Processing: Core Algorithms. Springer-Verlag, London, 2009. .. [2] B. Jähne. Digital Image Processing. Springer-Verlag, Berlin-Heidelberg, 6. edition, 2005. .. [3] T. H. Reiss. Recognizing Planar Objects Using Invariant Image Features, from Lecture notes in computer science, p. 676. Springer, Berlin, 1993. .. [4] http://en.wikipedia.org/wiki/Image_moment Examples -------- >>> from skimage.data import coins >>> from skimage.morphology import label >>> img = coins() > 110 >>> label_img = label(img) >>> props = regionprops(label_img) >>> props[0].centroid # centroid of first labelled object >>> props[0]['centroid'] # centroid of first labelled object """ label_image = np.squeeze(label_image) if label_image.ndim != 2: raise TypeError('Only 2-D images supported.') if properties is not None: warnings.warn('The ``properties`` argument is deprecated and is ' 'not needed any more as properties are ' 'determined dynamically.', category=DeprecationWarning) regions = [] objects = ndimage.find_objects(label_image) for i, sl in enumerate(objects): label = i + 1 props = _RegionProperties(sl, label, label_image, intensity_image, cache, properties=properties) regions.append(props) return regions def perimeter(image, neighbourhood=4): """Calculate total perimeter of all objects in binary image. Parameters ---------- image : array Binary image. neighbourhood : 4 or 8, optional Neighborhood connectivity for border pixel determination. Returns ------- perimeter : float Total perimeter of all objects in binary image. References ---------- .. [1] K. Benkrid, D. Crookes. Design and FPGA Implementation of a Perimeter Estimator. The Queen's University of Belfast. http://www.cs.qub.ac.uk/~d.crookes/webpubs/papers/perimeter.doc """ if neighbourhood == 4: strel = STREL_4 else: strel = STREL_8 image = image.astype(np.uint8) eroded_image = ndimage.binary_erosion(image, strel, border_value=0) border_image = image - eroded_image perimeter_weights = np.zeros(50, dtype=np.double) perimeter_weights[[5, 7, 15, 17, 25, 27]] = 1 perimeter_weights[[21, 33]] = sqrt(2) perimeter_weights[[13, 23]] = (1 + sqrt(2)) / 2 perimeter_image = ndimage.convolve(border_image, np.array([[10, 2, 10], [ 2, 1, 2], [10, 2, 10]]), mode='constant', cval=0) # You can also write # return perimeter_weights[perimeter_image].sum() # but that was measured as taking much longer than bincount + np.dot (5x # as much time) perimeter_histogram = np.bincount(perimeter_image.ravel(), minlength=50) total_perimeter = np.dot(perimeter_histogram, perimeter_weights) return total_perimeter scikit-image-0.9.3/skimage/measure/_structural_similarity.py000066400000000000000000000057741223313777300243660ustar00rootroot00000000000000from __future__ import division __all__ = ['structural_similarity'] import numpy as np from ..util.dtype import dtype_range from ..util.shape import view_as_windows def structural_similarity(X, Y, win_size=7, gradient=False, dynamic_range=None): """Compute the mean structural similarity index between two images. Parameters ---------- X, Y : (N,N) ndarray Images. win_size : int The side-length of the sliding window used in comparison. Must be an odd value. gradient : bool If True, also return the gradient. dynamic_range : int Dynamic range of the input image (distance between minimum and maximum possible values). By default, this is estimated from the image data-type. Returns ------- s : float Strucutural similarity. grad : (N * N,) ndarray Gradient of the structural similarity index between X and Y. This is only returned if `gradient` is set to True. References ---------- .. [1] Wang, Z., Bovik, A. C., Sheikh, H. R., & Simoncelli, E. P. (2004). Image quality assessment: From error visibility to structural similarity. IEEE Transactions on Image Processing, 13, 600-612. """ if not X.dtype == Y.dtype: raise ValueError('Input images must have the same dtype.') if not X.shape == Y.shape: raise ValueError('Input images must have the same dimensions.') if not (win_size % 2 == 1): raise ValueError('Window size must be odd.') if dynamic_range is None: dmin, dmax = dtype_range[X.dtype.type] dynamic_range = dmax - dmin XW = view_as_windows(X, (win_size, win_size)) YW = view_as_windows(Y, (win_size, win_size)) NS = len(XW) NP = win_size * win_size ux = np.mean(np.mean(XW, axis=2), axis=2) uy = np.mean(np.mean(YW, axis=2), axis=2) # Compute variances var(X), var(Y) and var(X, Y) cov_norm = 1 / (win_size**2 - 1) XWM = XW - ux[..., None, None] YWM = YW - uy[..., None, None] vx = cov_norm * np.sum(np.sum(XWM**2, axis=2), axis=2) vy = cov_norm * np.sum(np.sum(YWM**2, axis=2), axis=2) vxy = cov_norm * np.sum(np.sum(XWM * YWM, axis=2), axis=2) R = dynamic_range K1 = 0.01 K2 = 0.03 C1 = (K1 * R)**2 C2 = (K2 * R)**2 A1, A2, B1, B2 = (v[..., None, None] for v in (2 * ux * uy + C1, 2 * vxy + C2, ux**2 + uy**2 + C1, vx + vy + C2)) S = np.mean((A1 * A2) / (B1 * B2)) if gradient: local_grad = 2 / (NP * B1**2 * B2**2) * \ ( A1 * B1 * (B2 * XW - A2 * YW) - \ B1 * B2 * (A2 - A1) * ux[..., None, None] + \ A1 * A2 * (B1 - B2) * uy[..., None, None] ) grad = np.zeros_like(X, dtype=float) OW = view_as_windows(grad, (win_size, win_size)) OW += local_grad grad /= NS return S, grad else: return S scikit-image-0.9.3/skimage/measure/block.py000066400000000000000000000043021223313777300206250ustar00rootroot00000000000000import numpy as np from skimage.util import view_as_blocks, pad def block_reduce(image, block_size, func=np.sum, cval=0): """Down-sample image by applying function to local blocks. Parameters ---------- image : ndarray N-dimensional input image. block_size : array_like Array containing down-sampling integer factor along each axis. func : callable Function object which is used to calculate the return value for each local block. This function must implement an ``axis`` parameter such as ``numpy.sum`` or ``numpy.min``. cval : float Constant padding value if image is not perfectly divisible by the block size. Returns ------- image : ndarray Down-sampled image with same number of dimensions as input image. Examples -------- >>> from skimage.measure import block_reduce >>> image = np.arange(3*3*4).reshape(3, 3, 4) >>> image array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]], [[24, 25, 26, 27], [28, 29, 30, 31], [32, 33, 34, 35]]]) >>> block_reduce(image, block_size=(3, 3, 1), func=np.mean) array([[[ 16., 17., 18., 19.]]]) >>> block_reduce(image, block_size=(1, 3, 4), func=np.max) array([[[11]], [[23]], [[35]]]) >>> block_reduce(image, block_size=(3, 1, 4), func=np.max) array([[[27], [31], [35]]]) """ if len(block_size) != image.ndim: raise ValueError("`block_size` must have the same length " "as `image.shape`.") pad_width = [] for i in range(len(block_size)): if image.shape[i] % block_size[i] != 0: after_width = block_size[i] - (image.shape[i] % block_size[i]) else: after_width = 0 pad_width.append((0, after_width)) image = pad(image, pad_width=pad_width, mode='constant', constant_values=cval) out = view_as_blocks(image, block_size) for i in range(len(out.shape) // 2): out = func(out, axis=-1) return out scikit-image-0.9.3/skimage/measure/find_contours.py000077500000000000000000000216221223313777300224160ustar00rootroot00000000000000import numpy as np from . import _find_contours from collections import deque _param_options = ('high', 'low') def find_contours(array, level, fully_connected='low', positive_orientation='low'): """Find iso-valued contours in a 2D array for a given level value. Uses the "marching squares" method to compute a the iso-valued contours of the input 2D array for a particular level value. Array values are linearly interpolated to provide better precision for the output contours. Parameters ---------- array : 2D ndarray of double Input data in which to find contours. level : float Value along which to find contours in the array. fully_connected : str, {'low', 'high'} Indicates whether array elements below the given level value are to be considered fully-connected (and hence elements above the value will only be face connected), or vice-versa. (See notes below for details.) positive_orientation : either 'low' or 'high' Indicates whether the output contours will produce positively-oriented polygons around islands of low- or high-valued elements. If 'low' then contours will wind counter- clockwise around elements below the iso-value. Alternately, this means that low-valued elements are always on the left of the contour. (See below for details.) Returns ------- contours : list of (n,2)-ndarrays Each contour is an ndarray of shape ``(n, 2)``, consisting of n ``(x, y)`` coordinates along the contour. Notes ----- The marching squares algorithm is a special case of the marching cubes algorithm [1]_. A simple explanation is available here:: http://www.essi.fr/~lingrand/MarchingCubes/algo.html There is a single ambiguous case in the marching squares algorithm: when a given ``2 x 2``-element square has two high-valued and two low-valued elements, each pair diagonally adjacent. (Where high- and low-valued is with respect to the contour value sought.) In this case, either the high-valued elements can be 'connected together' via a thin isthmus that separates the low-valued elements, or vice-versa. When elements are connected together across a diagonal, they are considered 'fully connected' (also known as 'face+vertex-connected' or '8-connected'). Only high-valued or low-valued elements can be fully-connected, the other set will be considered as 'face-connected' or '4-connected'. By default, low-valued elements are considered fully-connected; this can be altered with the 'fully_connected' parameter. Output contours are not guaranteed to be closed: contours which intersect the array edge will be left open. All other contours will be closed. (The closed-ness of a contours can be tested by checking whether the beginning point is the same as the end point.) Contours are oriented. By default, array values lower than the contour value are to the left of the contour and values greater than the contour value are to the right. This means that contours will wind counter-clockwise (i.e. in 'positive orientation') around islands of low-valued pixels. This behavior can be altered with the 'positive_orientation' parameter. The order of the contours in the output list is determined by the position of the smallest ``x,y`` (in lexicographical order) coordinate in the contour. This is a side-effect of how the input array is traversed, but can be relied upon. .. warning:: Array coordinates/values are assumed to refer to the *center* of the array element. Take a simple example input: ``[0, 1]``. The interpolated position of 0.5 in this array is midway between the 0-element (at ``x=0``) and the 1-element (at ``x=1``), and thus would fall at ``x=0.5``. This means that to find reasonable contours, it is best to find contours midway between the expected "light" and "dark" values. In particular, given a binarized array, *do not* choose to find contours at the low or high value of the array. This will often yield degenerate contours, especially around structures that are a single array element wide. Instead choose a middle value, as above. References ---------- .. [1] Lorensen, William and Harvey E. Cline. Marching Cubes: A High Resolution 3D Surface Construction Algorithm. Computer Graphics (SIGGRAPH 87 Proceedings) 21(4) July 1987, p. 163-170). Examples -------- >>> a = np.zeros((3, 3)) >>> a[0, 0] = 1 >>> a array([[ 1., 0., 0.], [ 0., 0., 0.], [ 0., 0., 0.]]) >>> find_contours(a, 0.5) [array([[ 0. , 0.5], [ 0.5, 0. ]])] """ array = np.asarray(array, dtype=np.double) if array.ndim != 2: raise ValueError('Only 2D arrays are supported.') level = float(level) if (fully_connected not in _param_options or positive_orientation not in _param_options): raise ValueError('Parameters "fully_connected" and' ' "positive_orientation" must be either "high" or "low".') point_list = _find_contours.iterate_and_store(array, level, fully_connected == 'high') contours = _assemble_contours(_take_2(point_list)) if positive_orientation == 'high': contours = [c[::-1] for c in contours] return contours def _take_2(seq): iterator = iter(seq) while(True): n1 = next(iterator) n2 = next(iterator) yield (n1, n2) def _assemble_contours(points_iterator): current_index = 0 contours = {} starts = {} ends = {} for from_point, to_point in points_iterator: # Ignore degenerate segments. # This happens when (and only when) one vertex of the square is # exactly the contour level, and the rest are above or below. # This degnerate vertex will be picked up later by neighboring squares. if from_point == to_point: continue tail_data = starts.get(to_point) head_data = ends.get(from_point) if tail_data is not None and head_data is not None: tail, tail_num = tail_data head, head_num = head_data # We need to connect these two contours. if tail is head: # We need to closed a contour. # Add the end point, and remove the contour from the # 'starts' and 'ends' dicts. head.append(to_point) del starts[to_point] del ends[from_point] else: # tail is not head # We need to join two distinct contours. # We want to keep the first contour segment created, so that # the final contours are ordered left->right, top->bottom. if tail_num > head_num: # tail was created second. Append tail to head. head.extend(tail) # remove all traces of tail: del starts[to_point] del ends[tail[-1]] del contours[tail_num] # remove the old end of head and add the new end. del ends[from_point] ends[head[-1]] = (head, head_num) else: # tail_num <= head_num # head was created second. Prepend head to tail. tail.extendleft(reversed(head)) # remove all traces of head: del starts[head[0]] del ends[from_point] del contours[head_num] # remove the old start of tail and add the new start. del starts[to_point] starts[tail[0]] = (tail, tail_num) elif tail_data is None and head_data is None: # we need to add a new contour current_index += 1 new_num = current_index new_contour = deque((from_point, to_point)) contours[new_num] = new_contour starts[from_point] = (new_contour, new_num) ends[to_point] = (new_contour, new_num) elif tail_data is not None and head_data is None: tail, tail_num = tail_data # We've found a single contour to which the new segment should be # prepended. tail.appendleft(from_point) del starts[to_point] starts[from_point] = (tail, tail_num) elif tail_data is None and head_data is not None: head, head_num = head_data # We've found a single contour to which the new segment should be # appended head.append(to_point) del ends[from_point] ends[to_point] = (head, head_num) # end iteration over from_ and to_ points return [np.array(contour) for (num, contour) in sorted(contours.items())] scikit-image-0.9.3/skimage/measure/fit.py000066400000000000000000000471621223313777300203300ustar00rootroot00000000000000import math import numpy as np from scipy import optimize def _check_data_dim(data, dim): if data.ndim != 2 or data.shape[1] != dim: raise ValueError('Input data must have shape (N, %d).' % dim) class BaseModel(object): def __init__(self): self._params = None class LineModel(BaseModel): """Total least squares estimator for 2D lines. Lines are parameterized using polar coordinates as functional model:: dist = x * cos(theta) + y * sin(theta) This parameterization is able to model vertical lines in contrast to the standard line model ``y = a*x + b``. This estimator minimizes the squared distances from all points to the line:: min{ sum((dist - x_i * cos(theta) + y_i * sin(theta))**2) } The ``_params`` attribute contains the parameters in the following order:: dist, theta A minimum number of 2 points is required to solve for the parameters. """ def estimate(self, data): """Estimate line model from data using total least squares. Parameters ---------- data : (N, 2) array N points with ``(x, y)`` coordinates, respectively. """ _check_data_dim(data, dim=2) X0 = data.mean(axis=0) if data.shape[0] == 2: # well determined theta = np.arctan2(data[1, 1] - data[0, 1], data[1, 0] - data[0, 0]) elif data.shape[0] > 2: # over-determined data = data - X0 # first principal component _, _, v = np.linalg.svd(data) theta = np.arctan2(v[0, 1], v[0, 0]) else: # under-determined raise ValueError('At least 2 input points needed.') # angle perpendicular to line angle theta = (theta + np.pi / 2) % np.pi # line always passes through mean dist = X0[0] * math.cos(theta) + X0[1] * math.sin(theta) self._params = (dist, theta) def residuals(self, data): """Determine residuals of data to model. For each point the shortest distance to the line is returned. Parameters ---------- data : (N, 2) array N points with ``(x, y)`` coordinates, respectively. Returns ------- residuals : (N, ) array Residual for each data point. """ _check_data_dim(data, dim=2) dist, theta = self._params x = data[:, 0] y = data[:, 1] return dist - (x * math.cos(theta) + y * math.sin(theta)) def predict_x(self, y, params=None): """Predict x-coordinates using the estimated model. Parameters ---------- y : array y-coordinates. params : (2, ) array, optional Optional custom parameter set. Returns ------- x : array Predicted x-coordinates. """ if params is None: params = self._params dist, theta = params return (dist - y * math.sin(theta)) / math.cos(theta) def predict_y(self, x, params=None): """Predict y-coordinates using the estimated model. Parameters ---------- x : array x-coordinates. params : (2, ) array, optional Optional custom parameter set. Returns ------- y : array Predicted y-coordinates. """ if params is None: params = self._params dist, theta = params return (dist - x * math.cos(theta)) / math.sin(theta) class CircleModel(BaseModel): """Total least squares estimator for 2D circles. The functional model of the circle is:: r**2 = (x - xc)**2 + (y - yc)**2 This estimator minimizes the squared distances from all points to the circle:: min{ sum((r - sqrt((x_i - xc)**2 + (y_i - yc)**2))**2) } The ``_params`` attribute contains the parameters in the following order:: xc, yc, r A minimum number of 3 points is required to solve for the parameters. """ def estimate(self, data): """Estimate circle model from data using total least squares. Parameters ---------- data : (N, 2) array N points with ``(x, y)`` coordinates, respectively. """ _check_data_dim(data, dim=2) x = data[:, 0] y = data[:, 1] # pre-allocate jacobian for all iterations A = np.zeros((3, data.shape[0]), dtype=np.double) # same for all iterations: r A[2, :] = -1 def dist(xc, yc): return np.sqrt((x - xc)**2 + (y - yc)**2) def fun(params): xc, yc, r = params return dist(xc, yc) - r def Dfun(params): xc, yc, r = params d = dist(xc, yc) A[0, :] = -(x - xc) / d A[1, :] = -(y - yc) / d # same for all iterations, so not changed in each iteration #A[2, :] = -1 return A xc0 = x.mean() yc0 = y.mean() r0 = dist(xc0, yc0).mean() params0 = (xc0, yc0, r0) params, _ = optimize.leastsq(fun, params0, Dfun=Dfun, col_deriv=True) self._params = params def residuals(self, data): """Determine residuals of data to model. For each point the shortest distance to the circle is returned. Parameters ---------- data : (N, 2) array N points with ``(x, y)`` coordinates, respectively. Returns ------- residuals : (N, ) array Residual for each data point. """ _check_data_dim(data, dim=2) xc, yc, r = self._params x = data[:, 0] y = data[:, 1] return r - np.sqrt((x - xc)**2 + (y - yc)**2) def predict_xy(self, t, params=None): """Predict x- and y-coordinates using the estimated model. Parameters ---------- t : array Angles in circle in radians. Angles start to count from positive x-axis to positive y-axis in a right-handed system. params : (3, ) array, optional Optional custom parameter set. Returns ------- xy : (..., 2) array Predicted x- and y-coordinates. """ if params is None: params = self._params xc, yc, r = params x = xc + r * np.cos(t) y = yc + r * np.sin(t) return np.concatenate((x[..., None], y[..., None]), axis=t.ndim) class EllipseModel(BaseModel): """Total least squares estimator for 2D ellipses. The functional model of the ellipse is:: xt = xc + a*cos(theta)*cos(t) - b*sin(theta)*sin(t) yt = yc + a*sin(theta)*cos(t) + b*cos(theta)*sin(t) d = sqrt((x - xt)**2 + (y - yt)**2) where ``(xt, yt)`` is the closest point on the ellipse to ``(x, y)``. Thus d is the shortest distance from the point to the ellipse. This estimator minimizes the squared distances from all points to the ellipse:: min{ sum(d_i**2) } = min{ sum((x_i - xt)**2 + (y_i - yt)**2) } Thus you have ``2 * N`` equations (x_i, y_i) for ``N + 5`` unknowns (t_i, xc, yc, a, b, theta), which gives you an effective redundancy of ``N - 5``. The ``_params`` attribute contains the parameters in the following order:: xc, yc, a, b, theta A minimum number of 5 points is required to solve for the parameters. """ def estimate(self, data): """Estimate circle model from data using total least squares. Parameters ---------- data : (N, 2) array N points with ``(x, y)`` coordinates, respectively. """ _check_data_dim(data, dim=2) x = data[:, 0] y = data[:, 1] N = data.shape[0] # pre-allocate jacobian for all iterations A = np.zeros((N + 5, 2 * N), dtype=np.double) # same for all iterations: xc, yc A[0, :N] = -1 A[1, N:] = -1 diag_idxs = np.diag_indices(N) def fun(params): xyt = self.predict_xy(params[5:], params[:5]) fx = x - xyt[:, 0] fy = y - xyt[:, 1] return np.append(fx, fy) def Dfun(params): xc, yc, a, b, theta = params[:5] t = params[5:] ct = np.cos(t) st = np.sin(t) ctheta = math.cos(theta) stheta = math.sin(theta) # derivatives for fx, fy in the following order: # xc, yc, a, b, theta, t_i # fx A[2, :N] = - ctheta * ct A[3, :N] = stheta * st A[4, :N] = a * stheta * ct + b * ctheta * st A[5:, :N][diag_idxs] = a * ctheta * st + b * stheta * ct # fy A[2, N:] = - stheta * ct A[3, N:] = - ctheta * st A[4, N:] = - a * ctheta * ct + b * stheta * st A[5:, N:][diag_idxs] = a * stheta * st - b * ctheta * ct return A # initial guess of parameters using a circle model params0 = np.empty((N + 5, ), dtype=np.double) xc0 = x.mean() yc0 = y.mean() r0 = np.sqrt((x - xc0)**2 + (y - yc0)**2).mean() params0[:5] = (xc0, yc0, r0, 0, 0) params0[5:] = np.arctan2(y - yc0, x - xc0) params, _ = optimize.leastsq(fun, params0, Dfun=Dfun, col_deriv=True) self._params = params[:5] def residuals(self, data): """Determine residuals of data to model. For each point the shortest distance to the ellipse is returned. Parameters ---------- data : (N, 2) array N points with ``(x, y)`` coordinates, respectively. Returns ------- residuals : (N, ) array Residual for each data point. """ _check_data_dim(data, dim=2) xc, yc, a, b, theta = self._params ctheta = math.cos(theta) stheta = math.sin(theta) x = data[:, 0] y = data[:, 1] N = data.shape[0] def fun(t, xi, yi): ct = math.cos(t) st = math.sin(t) xt = xc + a * ctheta * ct - b * stheta * st yt = yc + a * stheta * ct + b * ctheta * st return (xi - xt)**2 + (yi - yt)**2 # def Dfun(t, xi, yi): # ct = math.cos(t) # st = math.sin(t) # xt = xc + a * ctheta * ct - b * stheta * st # yt = yc + a * stheta * ct + b * ctheta * st # dfx_t = - 2 * (xi - xt) * (- a * ctheta * st # - b * stheta * ct) # dfy_t = - 2 * (yi - yt) * (- a * stheta * st # + b * ctheta * ct) # return [dfx_t + dfy_t] residuals = np.empty((N, ), dtype=np.double) # initial guess for parameter t of closest point on ellipse t0 = np.arctan2(y - yc, x - xc) - theta # determine shortest distance to ellipse for each point for i in range(N): xi = x[i] yi = y[i] # faster without Dfun, because of the python overhead t, _ = optimize.leastsq(fun, t0[i], args=(xi, yi)) residuals[i] = np.sqrt(fun(t, xi, yi)) return residuals def predict_xy(self, t, params=None): """Predict x- and y-coordinates using the estimated model. Parameters ---------- t : array Angles in circle in radians. Angles start to count from positive x-axis to positive y-axis in a right-handed system. params : (5, ) array, optional Optional custom parameter set. Returns ------- xy : (..., 2) array Predicted x- and y-coordinates. """ if params is None: params = self._params xc, yc, a, b, theta = params ct = np.cos(t) st = np.sin(t) ctheta = math.cos(theta) stheta = math.sin(theta) x = xc + a * ctheta * ct - b * stheta * st y = yc + a * stheta * ct + b * ctheta * st return np.concatenate((x[..., None], y[..., None]), axis=t.ndim) def ransac(data, model_class, min_samples, residual_threshold, is_data_valid=None, is_model_valid=None, max_trials=100, stop_sample_num=np.inf, stop_residuals_sum=0): """Fit a model to data with the RANSAC (random sample consensus) algorithm. RANSAC is an iterative algorithm for the robust estimation of parameters from a subset of inliers from the complete data set. Each iteration performs the following tasks: 1. Select `min_samples` random samples from the original data and check whether the set of data is valid (see `is_data_valid`). 2. Estimate a model to the random subset (`model_cls.estimate(*data[random_subset]`) and check whether the estimated model is valid (see `is_model_valid`). 3. Classify all data as inliers or outliers by calculating the residuals to the estimated model (`model_cls.residuals(*data)`) - all data samples with residuals smaller than the `residual_threshold` are considered as inliers. 4. Save estimated model as best model if number of inlier samples is maximal. In case the current estimated model has the same number of inliers, it is only considered as the best model if it has less sum of residuals. These steps are performed either a maximum number of times or until one of the special stop criteria are met. The final model is estimated using all inlier samples of the previously determined best model. Parameters ---------- data : [list, tuple of] (N, D) array Data set to which the model is fitted, where N is the number of data points and D the dimensionality of the data. If the model class requires multiple input data arrays (e.g. source and destination coordinates of ``skimage.transform.AffineTransform``), they can be optionally passed as tuple or list. Note, that in this case the functions ``estimate(*data)``, ``residuals(*data)``, ``is_model_valid(model, *random_data)`` and ``is_data_valid(*random_data)`` must all take each data array as separate arguments. model_class : object Object with the following object methods: * ``estimate(*data)`` * ``residuals(*data)`` min_samples : int The minimum number of data points to fit a model to. residual_threshold : float Maximum distance for a data point to be classified as an inlier. is_data_valid : function, optional This function is called with the randomly selected data before the model is fitted to it: `is_data_valid(*random_data)`. is_model_valid : function, optional This function is called with the estimated model and the randomly selected data: `is_model_valid(model, *random_data)`, . max_trials : int, optional Maximum number of iterations for random sample selection. stop_sample_num : int, optional Stop iteration if at least this number of inliers are found. stop_residuals_sum : float, optional Stop iteration if sum of residuals is less equal than this threshold. Returns ------- model : object Best model with largest consensus set. inliers : (N, ) array Boolean mask of inliers classified as ``True``. References ---------- .. [1] "RANSAC", Wikipedia, http://en.wikipedia.org/wiki/RANSAC Examples -------- Generate ellipse data without tilt and add noise: >>> t = np.linspace(0, 2 * np.pi, 50) >>> a = 5 >>> b = 10 >>> xc = 20 >>> yc = 30 >>> x = xc + a * np.cos(t) >>> y = yc + b * np.sin(t) >>> data = np.column_stack([x, y]) >>> np.random.seed(seed=1234) >>> data += np.random.normal(size=data.shape) Add some faulty data: >>> data[0] = (100, 100) >>> data[1] = (110, 120) >>> data[2] = (120, 130) >>> data[3] = (140, 130) Estimate ellipse model using all available data: >>> model = EllipseModel() >>> model.estimate(data) >>> model._params array([ 4.85808595e+02, 4.51492793e+02, 1.15018491e+03, 5.52428289e+00, 7.32420126e-01]) Estimate ellipse model using RANSAC: >>> ransac_model, inliers = ransac(data, EllipseModel, 5, 3, max_trials=50) >>> # ransac_model._params, inliers Should give the correct result estimated without the faulty data:: [ 20.12762373, 29.73563061, 4.81499637, 10.4743584, 0.05217117] [ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] Robustly estimate geometric transformation: >>> from skimage.transform import SimilarityTransform >>> src = 100 * np.random.random((50, 2)) >>> model0 = SimilarityTransform(scale=0.5, rotation=1, ... translation=(10, 20)) >>> dst = model0(src) >>> dst[0] = (10000, 10000) >>> dst[1] = (-100, 100) >>> dst[2] = (50, 50) >>> model, inliers = ransac((src, dst), SimilarityTransform, 2, 10) >>> inliers array([ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]) """ best_model = None best_inlier_num = 0 best_inlier_residuals_sum = np.inf best_inliers = None if not isinstance(data, list) and not isinstance(data, tuple): data = [data] # make sure data is list and not tuple, so it can be modified below data = list(data) # number of samples N = data[0].shape[0] for _ in range(max_trials): # choose random sample set samples = [] random_idxs = np.random.randint(0, N, min_samples) for d in data: samples.append(d[random_idxs]) # check if random sample set is valid if is_data_valid is not None and not is_data_valid(*samples): continue # estimate model for current random sample set sample_model = model_class() sample_model.estimate(*samples) # check if estimated model is valid if is_model_valid is not None and not is_model_valid(sample_model, *samples): continue sample_model_residuals = np.abs(sample_model.residuals(*data)) # consensus set / inliers sample_model_inliers = sample_model_residuals < residual_threshold sample_model_residuals_sum = np.sum(sample_model_residuals**2) # choose as new best model if number of inliers is maximal sample_inlier_num = np.sum(sample_model_inliers) if ( # more inliers sample_inlier_num > best_inlier_num # same number of inliers but less "error" in terms of residuals or (sample_inlier_num == best_inlier_num and sample_model_residuals_sum < best_inlier_residuals_sum) ): best_model = sample_model best_inlier_num = sample_inlier_num best_inlier_residuals_sum = sample_model_residuals_sum best_inliers = sample_model_inliers if ( best_inlier_num >= stop_sample_num or best_inlier_residuals_sum <= stop_residuals_sum ): break # estimate final model using all inliers if best_inliers is not None: # select inliers for each data array for i in range(len(data)): data[i] = data[i][best_inliers] best_model.estimate(*data) return best_model, best_inliers scikit-image-0.9.3/skimage/measure/setup.py000066400000000000000000000025601223313777300206770ustar00rootroot00000000000000#!/usr/bin/env python from skimage._build import cython import os base_path = os.path.abspath(os.path.dirname(__file__)) def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs config = Configuration('measure', parent_package, top_path) config.add_data_dir('tests') cython(['_find_contours.pyx'], working_path=base_path) cython(['_moments.pyx'], working_path=base_path) cython(['_marching_cubes_cy.pyx'], working_path=base_path) config.add_extension('_find_contours', sources=['_find_contours.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_moments', sources=['_moments.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_marching_cubes_cy', sources=['_marching_cubes_cy.c'], include_dirs=[get_numpy_include_dirs()]) return config if __name__ == '__main__': from numpy.distutils.core import setup setup(maintainer='scikit-image Developers', maintainer_email='scikit-image@googlegroups.com', description='Graph-based Image-processing Algorithms', url='https://github.com/scikit-image/scikit-image', license='Modified BSD', **(configuration(top_path='').todict()) ) scikit-image-0.9.3/skimage/measure/tests/000077500000000000000000000000001223313777300203245ustar00rootroot00000000000000scikit-image-0.9.3/skimage/measure/tests/test_block.py000066400000000000000000000050531223313777300230320ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal from skimage.measure import block_reduce def test_block_reduce_sum(): image1 = np.arange(4 * 6).reshape(4, 6) out1 = block_reduce(image1, (2, 3)) expected1 = np.array([[ 24, 42], [ 96, 114]]) assert_array_equal(expected1, out1) image2 = np.arange(5 * 8).reshape(5, 8) out2 = block_reduce(image2, (3, 3)) expected2 = np.array([[ 81, 108, 87], [174, 192, 138]]) assert_array_equal(expected2, out2) def test_block_reduce_mean(): image1 = np.arange(4 * 6).reshape(4, 6) out1 = block_reduce(image1, (2, 3), func=np.mean) expected1 = np.array([[ 4., 7.], [ 16., 19.]]) assert_array_equal(expected1, out1) image2 = np.arange(5 * 8).reshape(5, 8) out2 = block_reduce(image2, (4, 5), func=np.mean) expected2 = np.array([[14. , 10.8], [ 8.5, 5.7]]) assert_array_equal(expected2, out2) def test_block_reduce_median(): image1 = np.arange(4 * 6).reshape(4, 6) out1 = block_reduce(image1, (2, 3), func=np.median) expected1 = np.array([[ 4., 7.], [ 16., 19.]]) assert_array_equal(expected1, out1) image2 = np.arange(5 * 8).reshape(5, 8) out2 = block_reduce(image2, (4, 5), func=np.median) expected2 = np.array([[ 14., 17.], [ 0., 0.]]) assert_array_equal(expected2, out2) image3 = np.array([[1, 5, 5, 5], [5, 5, 5, 1000]]) out3 = block_reduce(image3, (2, 4), func=np.median) assert_array_equal(5, out3) def test_block_reduce_min(): image1 = np.arange(4 * 6).reshape(4, 6) out1 = block_reduce(image1, (2, 3), func=np.min) expected1 = np.array([[ 0, 3], [12, 15]]) assert_array_equal(expected1, out1) image2 = np.arange(5 * 8).reshape(5, 8) out2 = block_reduce(image2, (4, 5), func=np.min) expected2 = np.array([[0, 0], [0, 0]]) assert_array_equal(expected2, out2) def test_block_reduce_max(): image1 = np.arange(4 * 6).reshape(4, 6) out1 = block_reduce(image1, (2, 3), func=np.max) expected1 = np.array([[ 8, 11], [20, 23]]) assert_array_equal(expected1, out1) image2 = np.arange(5 * 8).reshape(5, 8) out2 = block_reduce(image2, (4, 5), func=np.max) expected2 = np.array([[28, 31], [36, 39]]) assert_array_equal(expected2, out2) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/measure/tests/test_find_contours.py000066400000000000000000000034421223313777300246140ustar00rootroot00000000000000import numpy as np from numpy.testing import (assert_raises, assert_array_equal, ) from skimage.measure import find_contours a = np.ones((8, 8), dtype=np.float32) a[1:-1, 1] = 0 a[1, 1:-1] = 0 x, y = np.mgrid[-1:1:5j, -1:1:5j] r = np.sqrt(x**2 + y**2) def test_binary(): ref = [[6. , 1.5], [5. , 1.5], [4. , 1.5], [3. , 1.5], [2. , 1.5], [1.5, 2. ], [1.5, 3. ], [1.5, 4. ], [1.5, 5. ], [1.5, 6. ], [1. , 6.5], [0.5, 6. ], [0.5, 5. ], [0.5, 4. ], [0.5, 3. ], [0.5, 2. ], [0.5, 1. ], [1. , 0.5], [2. , 0.5], [3. , 0.5], [4. , 0.5], [5. , 0.5], [6. , 0.5], [6.5, 1. ], [6. , 1.5]] contours = find_contours(a, 0.5, positive_orientation='high') assert len(contours) == 1 assert_array_equal(contours[0][::-1], ref) def test_float(): contours = find_contours(r, 0.5) assert len(contours) == 1 assert_array_equal(contours[0], [[ 2., 3.], [ 1., 2.], [ 2., 1.], [ 3., 2.], [ 2., 3.]]) def test_memory_order(): contours = find_contours(np.ascontiguousarray(r), 0.5) assert len(contours) == 1 contours = find_contours(np.asfortranarray(r), 0.5) assert len(contours) == 1 def test_invalid_input(): assert_raises(ValueError, find_contours, r, 0.5, 'foo', 'bar') assert_raises(ValueError, find_contours, r[..., None], 0.5) if __name__ == '__main__': from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/measure/tests/test_fit.py000066400000000000000000000142351223313777300225240ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_equal, assert_raises, assert_almost_equal from skimage.measure import LineModel, CircleModel, EllipseModel, ransac from skimage.transform import AffineTransform def test_line_model_invalid_input(): assert_raises(ValueError, LineModel().estimate, np.empty((5, 3))) def test_line_model_predict(): model = LineModel() model._params = (10, 1) x = np.arange(-10, 10) y = model.predict_y(x) assert_almost_equal(x, model.predict_x(y)) def test_line_model_estimate(): # generate original data without noise model0 = LineModel() model0._params = (10, 1) x0 = np.arange(-100, 100) y0 = model0.predict_y(x0) data0 = np.column_stack([x0, y0]) # add gaussian noise to data np.random.seed(1234) data = data0 + np.random.normal(size=data0.shape) # estimate parameters of noisy data model_est = LineModel() model_est.estimate(data) # test whether estimated parameters almost equal original parameters assert_almost_equal(model0._params, model_est._params, 1) def test_line_model_residuals(): model = LineModel() model._params = (0, 0) assert_equal(abs(model.residuals(np.array([[0, 0]]))), 0) assert_equal(abs(model.residuals(np.array([[0, 10]]))), 0) assert_equal(abs(model.residuals(np.array([[10, 0]]))), 10) model._params = (5, np.pi / 4) assert_equal(abs(model.residuals(np.array([[0, 0]]))), 5) assert_equal(abs(model.residuals(np.array([[np.sqrt(50), 0]]))), 5) def test_line_model_under_determined(): data = np.empty((1, 2)) assert_raises(ValueError, LineModel().estimate, data) def test_circle_model_invalid_input(): assert_raises(ValueError, CircleModel().estimate, np.empty((5, 3))) def test_circle_model_predict(): model = CircleModel() r = 5 model._params = (0, 0, r) t = np.arange(0, 2 * np.pi, np.pi / 2) xy = np.array(((5, 0), (0, 5), (-5, 0), (0, -5))) assert_almost_equal(xy, model.predict_xy(t)) def test_circle_model_estimate(): # generate original data without noise model0 = CircleModel() model0._params = (10, 12, 3) t = np.linspace(0, 2 * np.pi, 1000) data0 = model0.predict_xy(t) # add gaussian noise to data np.random.seed(1234) data = data0 + np.random.normal(size=data0.shape) # estimate parameters of noisy data model_est = CircleModel() model_est.estimate(data) # test whether estimated parameters almost equal original parameters assert_almost_equal(model0._params, model_est._params, 1) def test_circle_model_residuals(): model = CircleModel() model._params = (0, 0, 5) assert_almost_equal(abs(model.residuals(np.array([[5, 0]]))), 0) assert_almost_equal(abs(model.residuals(np.array([[6, 6]]))), np.sqrt(2 * 6**2) - 5) assert_almost_equal(abs(model.residuals(np.array([[10, 0]]))), 5) def test_ellipse_model_invalid_input(): assert_raises(ValueError, EllipseModel().estimate, np.empty((5, 3))) def test_ellipse_model_predict(): model = EllipseModel() r = 5 model._params = (0, 0, 5, 10, 0) t = np.arange(0, 2 * np.pi, np.pi / 2) xy = np.array(((5, 0), (0, 10), (-5, 0), (0, -10))) assert_almost_equal(xy, model.predict_xy(t)) def test_ellipse_model_estimate(): # generate original data without noise model0 = EllipseModel() model0._params = (10, 20, 15, 25, 0) t = np.linspace(0, 2 * np.pi, 100) data0 = model0.predict_xy(t) # add gaussian noise to data np.random.seed(1234) data = data0 + np.random.normal(size=data0.shape) # estimate parameters of noisy data model_est = EllipseModel() model_est.estimate(data) # test whether estimated parameters almost equal original parameters assert_almost_equal(model0._params, model_est._params, 0) def test_line_model_residuals(): model = EllipseModel() # vertical line through origin model._params = (0, 0, 10, 5, 0) assert_almost_equal(abs(model.residuals(np.array([[10, 0]]))), 0) assert_almost_equal(abs(model.residuals(np.array([[0, 5]]))), 0) assert_almost_equal(abs(model.residuals(np.array([[0, 10]]))), 5) def test_ransac_shape(): np.random.seed(1) # generate original data without noise model0 = CircleModel() model0._params = (10, 12, 3) t = np.linspace(0, 2 * np.pi, 1000) data0 = model0.predict_xy(t) # add some faulty data outliers = (10, 30, 200) data0[outliers[0], :] = (1000, 1000) data0[outliers[1], :] = (-50, 50) data0[outliers[2], :] = (-100, -10) # estimate parameters of corrupted data model_est, inliers = ransac(data0, CircleModel, 3, 5) # test whether estimated parameters equal original parameters assert_equal(model0._params, model_est._params) for outlier in outliers: assert outlier not in inliers def test_ransac_geometric(): np.random.seed(1) # generate original data without noise src = 100 * np.random.random((50, 2)) model0 = AffineTransform(scale=(0.5, 0.3), rotation=1, translation=(10, 20)) dst = model0(src) # add some faulty data outliers = (0, 5, 20) dst[outliers[0]] = (10000, 10000) dst[outliers[1]] = (-100, 100) dst[outliers[2]] = (50, 50) # estimate parameters of corrupted data model_est, inliers = ransac((src, dst), AffineTransform, 2, 20) # test whether estimated parameters equal original parameters assert_almost_equal(model0._matrix, model_est._matrix) assert np.all(np.nonzero(inliers == False)[0] == outliers) def test_ransac_is_data_valid(): np.random.seed(1) is_data_valid = lambda data: data.shape[0] > 2 model, inliers = ransac(np.empty((10, 2)), LineModel, 2, np.inf, is_data_valid=is_data_valid) assert_equal(model, None) assert_equal(inliers, None) def test_ransac_is_model_valid(): np.random.seed(1) def is_model_valid(model, data): return False model, inliers = ransac(np.empty((10, 2)), LineModel, 2, np.inf, is_model_valid=is_model_valid) assert_equal(model, None) assert_equal(inliers, None) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/measure/tests/test_marching_cubes.py000066400000000000000000000027211223313777300247100ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_raises from skimage.draw import ellipsoid, ellipsoid_stats from skimage.measure import marching_cubes, mesh_surface_area def test_marching_cubes_isotropic(): ellipsoid_isotropic = ellipsoid(6, 10, 16, levelset=True) _, surf = ellipsoid_stats(6, 10, 16) verts, faces = marching_cubes(ellipsoid_isotropic, 0.) surf_calc = mesh_surface_area(verts, faces) # Test within 1% tolerance for isotropic. Will always underestimate. assert surf > surf_calc and surf_calc > surf * 0.99 def test_marching_cubes_anisotropic(): spacing = (1., 10 / 6., 16 / 6.) ellipsoid_anisotropic = ellipsoid(6, 10, 16, spacing=spacing, levelset=True) _, surf = ellipsoid_stats(6, 10, 16) verts, faces = marching_cubes(ellipsoid_anisotropic, 0., spacing=spacing) surf_calc = mesh_surface_area(verts, faces) # Test within 1.5% tolerance for anisotropic. Will always underestimate. assert surf > surf_calc and surf_calc > surf * 0.985 def test_invalid_input(): assert_raises(ValueError, marching_cubes, np.zeros((2, 2, 1)), 0) assert_raises(ValueError, marching_cubes, np.zeros((2, 2, 1)), 1) assert_raises(ValueError, marching_cubes, np.ones((3, 3, 3)), 1, spacing=(1, 2)) assert_raises(ValueError, marching_cubes, np.zeros((20, 20)), 0) if __name__ == '__main__': np.testing.run_module_suite() scikit-image-0.9.3/skimage/measure/tests/test_moments.py000066400000000000000000000042351223313777300234230ustar00rootroot00000000000000from numpy.testing import assert_equal, assert_almost_equal import numpy as np from skimage.measure import (moments, moments_central, moments_normalized, moments_hu) def test_moments(): image = np.zeros((20, 20), dtype=np.double) image[14, 14] = 1 image[15, 15] = 1 image[14, 15] = 0.5 image[15, 14] = 0.5 m = moments(image) assert_equal(m[0, 0], 3) assert_almost_equal(m[0, 1] / m[0, 0], 14.5) assert_almost_equal(m[1, 0] / m[0, 0], 14.5) def test_moments_central(): image = np.zeros((20, 20), dtype=np.double) image[14, 14] = 1 image[15, 15] = 1 image[14, 15] = 0.5 image[15, 14] = 0.5 mu = moments_central(image, 14.5, 14.5) # shift image by dx=2, dy=2 image2 = np.zeros((20, 20), dtype=np.double) image2[16, 16] = 1 image2[17, 17] = 1 image2[16, 17] = 0.5 image2[17, 16] = 0.5 mu2 = moments_central(image2, 14.5 + 2, 14.5 + 2) # central moments must be translation invariant assert_equal(mu, mu2) def test_moments_normalized(): image = np.zeros((20, 20), dtype=np.double) image[13:17, 13:17] = 1 mu = moments_central(image, 14.5, 14.5) nu = moments_normalized(mu) # shift image by dx=-3, dy=-3 and scale by 0.5 image2 = np.zeros((20, 20), dtype=np.double) image2[11:13, 11:13] = 1 mu2 = moments_central(image2, 11.5, 11.5) nu2 = moments_normalized(mu2) # central moments must be translation and scale invariant assert_almost_equal(nu, nu2, decimal=1) def test_moments_hu(): image = np.zeros((20, 20), dtype=np.double) image[13:15, 13:17] = 1 mu = moments_central(image, 13.5, 14.5) nu = moments_normalized(mu) hu = moments_hu(nu) # shift image by dx=2, dy=3, scale by 0.5 and rotate by 90deg image2 = np.zeros((20, 20), dtype=np.double) image2[11, 11:13] = 1 image2 = image2.T mu2 = moments_central(image2, 11.5, 11) nu2 = moments_normalized(mu2) hu2 = moments_hu(nu2) # central moments must be translation and scale invariant assert_almost_equal(hu, hu2, decimal=1) if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/measure/tests/test_polygon.py000066400000000000000000000045071223313777300234320ustar00rootroot00000000000000import numpy as np from skimage.measure import approximate_polygon, subdivide_polygon from skimage.measure._polygon import _SUBDIVISION_MASKS square = np.array([ [0, 0], [0, 1], [0, 2], [0, 3], [1, 3], [2, 3], [3, 3], [3, 2], [3, 1], [3, 0], [2, 0], [1, 0], [0, 0] ]) def test_approximate_polygon(): out = approximate_polygon(square, 0.1) np.testing.assert_array_equal(out, square[(0, 3, 6, 9, 12), :]) out = approximate_polygon(square, 2.2) np.testing.assert_array_equal(out, square[(0, 6, 12), :]) out = approximate_polygon(square[(0, 1, 3, 4, 5, 6, 7, 9, 11, 12), :], 0.1) np.testing.assert_array_equal(out, square[(0, 3, 6, 9, 12), :]) out = approximate_polygon(square, -1) np.testing.assert_array_equal(out, square) out = approximate_polygon(square, 0) np.testing.assert_array_equal(out, square) def test_subdivide_polygon(): new_square1 = square new_square2 = square[:-1] new_square3 = square[:-1] # test iterative subdvision for _ in range(10): square1, square2, square3 = new_square1, new_square2, new_square3 # test different B-Spline degrees for degree in range(1, 7): mask_len = len(_SUBDIVISION_MASKS[degree][0]) # test circular new_square1 = subdivide_polygon(square1, degree) np.testing.assert_array_equal(new_square1[-1], new_square1[0]) np.testing.assert_equal(new_square1.shape[0], 2 * square1.shape[0] - 1) # test non-circular new_square2 = subdivide_polygon(square2, degree) np.testing.assert_equal(new_square2.shape[0], 2 * (square2.shape[0] - mask_len + 1)) # test non-circular, preserve_ends new_square3 = subdivide_polygon(square3, degree, True) np.testing.assert_equal(new_square3[0], square3[0]) np.testing.assert_equal(new_square3[-1], square3[-1]) np.testing.assert_equal(new_square3.shape[0], 2 * (square3.shape[0] - mask_len + 2)) # not supported B-Spline degree np.testing.assert_raises(ValueError, subdivide_polygon, square, 0) np.testing.assert_raises(ValueError, subdivide_polygon, square, 8) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/measure/tests/test_regionprops.py000066400000000000000000000265751223313777300243230ustar00rootroot00000000000000from numpy.testing import assert_array_equal, assert_almost_equal, \ assert_array_almost_equal, assert_raises, assert_equal import numpy as np import math from skimage.measure._regionprops import regionprops, PROPS, perimeter SAMPLE = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1], [0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]] ) INTENSITY_SAMPLE = SAMPLE.copy() INTENSITY_SAMPLE[1, 9:11] = 2 def test_all_props(): regions = regionprops(SAMPLE, 'all', INTENSITY_SAMPLE)[0] for prop in PROPS: regions[prop] def test_dtype(): regionprops(np.zeros((10, 10), dtype=np.int)) regionprops(np.zeros((10, 10), dtype=np.uint)) assert_raises((TypeError, RuntimeError), regionprops, np.zeros((10, 10), dtype=np.double)) def test_ndim(): regionprops(np.zeros((10, 10), dtype=np.int)) regionprops(np.zeros((10, 10, 1), dtype=np.int)) regionprops(np.zeros((10, 10, 1, 1), dtype=np.int)) assert_raises(TypeError, regionprops, np.zeros((10, 10, 2), dtype=np.int)) def test_area(): area = regionprops(SAMPLE)[0].area assert area == np.sum(SAMPLE) def test_bbox(): bbox = regionprops(SAMPLE)[0].bbox assert_array_almost_equal(bbox, (0, 0, SAMPLE.shape[0], SAMPLE.shape[1])) SAMPLE_mod = SAMPLE.copy() SAMPLE_mod[:, -1] = 0 bbox = regionprops(SAMPLE_mod)[0].bbox assert_array_almost_equal(bbox, (0, 0, SAMPLE.shape[0], SAMPLE.shape[1]-1)) def test_moments_central(): mu = regionprops(SAMPLE)[0].moments_central # determined with OpenCV assert_almost_equal(mu[0,2], 436.00000000000045) # different from OpenCV results, bug in OpenCV assert_almost_equal(mu[0,3], -737.333333333333) assert_almost_equal(mu[1,1], -87.33333333333303) assert_almost_equal(mu[1,2], -127.5555555555593) assert_almost_equal(mu[2,0], 1259.7777777777774) assert_almost_equal(mu[2,1], 2000.296296296291) assert_almost_equal(mu[3,0], -760.0246913580195) def test_centroid(): centroid = regionprops(SAMPLE)[0].centroid # determined with MATLAB assert_array_almost_equal(centroid, (5.66666666666666, 9.444444444444444)) def test_convex_area(): area = regionprops(SAMPLE)[0].convex_area # determined with MATLAB assert area == 124 def test_convex_image(): img = regionprops(SAMPLE)[0].convex_image # determined with MATLAB ref = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] ) assert_array_equal(img, ref) def test_coordinates(): sample = np.zeros((10, 10), dtype=np.int8) coords = np.array([[3, 2], [3, 3], [3, 4]]) sample[coords[:, 0], coords[:, 1]] = 1 prop_coords = regionprops(sample)[0].coords assert_array_equal(prop_coords, coords) def test_eccentricity(): eps = regionprops(SAMPLE)[0].eccentricity assert_almost_equal(eps, 0.814629313427) img = np.zeros((5, 5), dtype=np.int) img[2, 2] = 1 eps = regionprops(img)[0].eccentricity assert_almost_equal(eps, 0) def test_equiv_diameter(): diameter = regionprops(SAMPLE)[0].equivalent_diameter # determined with MATLAB assert_almost_equal(diameter, 9.57461472963) def test_euler_number(): en = regionprops(SAMPLE)[0].euler_number assert en == 0 SAMPLE_mod = SAMPLE.copy() SAMPLE_mod[7, -3] = 0 en = regionprops(SAMPLE_mod)[0].euler_number assert en == -1 def test_extent(): extent = regionprops(SAMPLE)[0].extent assert_almost_equal(extent, 0.4) def test_moments_hu(): hu = regionprops(SAMPLE)[0].moments_hu ref = np.array([ 3.27117627e-01, 2.63869194e-02, 2.35390060e-02, 1.23151193e-03, 1.38882330e-06, -2.72586158e-05, 6.48350653e-06 ]) # bug in OpenCV caused in Central Moments calculation? assert_array_almost_equal(hu, ref) def test_image(): img = regionprops(SAMPLE)[0].image assert_array_equal(img, SAMPLE) def test_label(): label = regionprops(SAMPLE)[0].label assert_array_equal(label, 1) def test_filled_area(): area = regionprops(SAMPLE)[0].filled_area assert area == np.sum(SAMPLE) SAMPLE_mod = SAMPLE.copy() SAMPLE_mod[7, -3] = 0 area = regionprops(SAMPLE_mod)[0].filled_area assert area == np.sum(SAMPLE) def test_filled_image(): img = regionprops(SAMPLE)[0].filled_image assert_array_equal(img, SAMPLE) def test_major_axis_length(): length = regionprops(SAMPLE)[0].major_axis_length # MATLAB has different interpretation of ellipse than found in literature, # here implemented as found in literature assert_almost_equal(length, 16.7924234999) def test_max_intensity(): intensity = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE )[0].max_intensity assert_almost_equal(intensity, 2) def test_mean_intensity(): intensity = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE )[0].mean_intensity assert_almost_equal(intensity, 1.02777777777777) def test_min_intensity(): intensity = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE )[0].min_intensity assert_almost_equal(intensity, 1) def test_minor_axis_length(): length = regionprops(SAMPLE)[0].minor_axis_length # MATLAB has different interpretation of ellipse than found in literature, # here implemented as found in literature assert_almost_equal(length, 9.739302807263) def test_moments(): m = regionprops(SAMPLE)[0].moments # determined with OpenCV assert_almost_equal(m[0,0], 72.0) assert_almost_equal(m[0,1], 408.0) assert_almost_equal(m[0,2], 2748.0) assert_almost_equal(m[0,3], 19776.0) assert_almost_equal(m[1,0], 680.0) assert_almost_equal(m[1,1], 3766.0) assert_almost_equal(m[1,2], 24836.0) assert_almost_equal(m[2,0], 7682.0) assert_almost_equal(m[2,1], 43882.0) assert_almost_equal(m[3,0], 95588.0) def test_moments_normalized(): nu = regionprops(SAMPLE)[0].moments_normalized # determined with OpenCV assert_almost_equal(nu[0,2], 0.08410493827160502) assert_almost_equal(nu[1,1], -0.016846707818929982) assert_almost_equal(nu[1,2], -0.002899800614433943) assert_almost_equal(nu[2,0], 0.24301268861454037) assert_almost_equal(nu[2,1], 0.045473992910668816) assert_almost_equal(nu[3,0], -0.017278118992041805) def test_orientation(): orientation = regionprops(SAMPLE)[0].orientation # determined with MATLAB assert_almost_equal(orientation, 0.10446844651921) # test correct quadrant determination orientation2 = regionprops(SAMPLE.T)[0].orientation assert_almost_equal(orientation2, math.pi / 2 - orientation) # test diagonal regions diag = np.eye(10, dtype=int) orientation_diag = regionprops(diag)[0].orientation assert_almost_equal(orientation_diag, -math.pi / 4) orientation_diag = regionprops(np.flipud(diag))[0].orientation assert_almost_equal(orientation_diag, math.pi / 4) orientation_diag = regionprops(np.fliplr(diag))[0].orientation assert_almost_equal(orientation_diag, math.pi / 4) orientation_diag = regionprops(np.fliplr(np.flipud(diag)))[0].orientation assert_almost_equal(orientation_diag, -math.pi / 4) def test_perimeter(): per = regionprops(SAMPLE)[0].perimeter assert_almost_equal(per, 55.2487373415) per = perimeter(SAMPLE.astype('double'), neighbourhood=8) assert_almost_equal(per, 46.8284271247) def test_solidity(): solidity = regionprops(SAMPLE)[0].solidity # determined with MATLAB assert_almost_equal(solidity, 0.580645161290323) def test_weighted_moments_central(): wmu = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE )[0].weighted_moments_central ref = np.array( [[ 7.4000000000e+01, -2.1316282073e-13, 4.7837837838e+02, -7.5943608473e+02], [ 3.7303493627e-14, -8.7837837838e+01, -1.4801314828e+02, -1.2714707125e+03], [ 1.2602837838e+03, 2.1571526662e+03, 6.6989799420e+03, 1.5304076361e+04], [ -7.6561796932e+02, -4.2385971907e+03, -9.9501164076e+03, -3.3156729271e+04]] ) np.set_printoptions(precision=10) assert_array_almost_equal(wmu, ref) def test_weighted_centroid(): centroid = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE )[0].weighted_centroid assert_array_almost_equal(centroid, (5.540540540540, 9.445945945945)) def test_weighted_moments_hu(): whu = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE )[0].weighted_moments_hu ref = np.array([ 3.1750587329e-01, 2.1417517159e-02, 2.3609322038e-02, 1.2565683360e-03, 8.3014209421e-07, -3.5073773473e-05, 6.7936409056e-06 ]) assert_array_almost_equal(whu, ref) def test_weighted_moments(): wm = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE )[0].weighted_moments ref = np.array( [[ 7.4000000000e+01, 4.1000000000e+02, 2.7500000000e+03, 1.9778000000e+04], [ 6.9900000000e+02, 3.7850000000e+03, 2.4855000000e+04, 1.7500100000e+05], [ 7.8630000000e+03, 4.4063000000e+04, 2.9347700000e+05, 2.0810510000e+06], [ 9.7317000000e+04, 5.7256700000e+05, 3.9007170000e+06, 2.8078871000e+07]] ) assert_array_almost_equal(wm, ref) def test_weighted_moments_normalized(): wnu = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE )[0].weighted_moments_normalized ref = np.array( [[ np.nan, np.nan, 0.0873590903, -0.0161217406], [ np.nan, -0.0160405109, -0.0031421072, -0.0031376984], [ 0.230146783, 0.0457932622, 0.0165315478, 0.0043903193], [-0.0162529732, -0.0104598869, -0.0028544152, -0.0011057191]] ) assert_array_almost_equal(wnu, ref) def test_old_dict_interface(): feats = regionprops(SAMPLE, ['Area', 'Eccentricity', 'EulerNumber', 'Extent', 'MinIntensity', 'MeanIntensity', 'MaxIntensity', 'Solidity'], intensity_image=INTENSITY_SAMPLE) np.array([list(props.values()) for props in feats], np.float) assert_equal(len(feats[0]), 8) if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/measure/tests/test_structural_similarity.py000066400000000000000000000031351223313777300264150ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_equal, assert_raises from skimage.measure import structural_similarity as ssim np.random.seed(1234) def test_ssim_patch_range(): N = 51 X = (np.random.random((N, N)) * 255).astype(np.uint8) Y = (np.random.random((N, N)) * 255).astype(np.uint8) assert(ssim(X, Y, win_size=N) < 0.1) assert_equal(ssim(X, X, win_size=N), 1) def test_ssim_image(): N = 100 X = (np.random.random((N, N)) * 255).astype(np.uint8) Y = (np.random.random((N, N)) * 255).astype(np.uint8) S0 = ssim(X, X, win_size=3) assert_equal(S0, 1) S1 = ssim(X, Y, win_size=3) assert(S1 < 0.3) # NOTE: This test is known to randomly fail on some systems (Mac OS X 10.6) def test_ssim_grad(): N = 30 X = np.random.random((N, N)) * 255 Y = np.random.random((N, N)) * 255 f = ssim(X, Y, dynamic_range=255) g = ssim(X, Y, dynamic_range=255, gradient=True) assert f < 0.05 assert g[0] < 0.05 assert np.all(g[1] < 0.05) def test_ssim_dtype(): N = 30 X = np.random.random((N, N)) Y = np.random.random((N, N)) S1 = ssim(X, Y) X = (X * 255).astype(np.uint8) Y = (X * 255).astype(np.uint8) S2 = ssim(X, Y) assert S1 < 0.1 assert S2 < 0.1 def test_invalid_input(): X = np.zeros((3, 3), dtype=np.double) Y = np.zeros((3, 3), dtype=np.int) assert_raises(ValueError, ssim, X, Y) Y = np.zeros((4, 4), dtype=np.double) assert_raises(ValueError, ssim, X, Y) assert_raises(ValueError, ssim, X, X, win_size=8) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/morphology/000077500000000000000000000000001223313777300177205ustar00rootroot00000000000000scikit-image-0.9.3/skimage/morphology/__init__.py000066400000000000000000000030641223313777300220340ustar00rootroot00000000000000from .binary import (binary_erosion, binary_dilation, binary_opening, binary_closing) from .grey import (erosion, dilation, opening, closing, white_tophat, black_tophat, greyscale_erode, greyscale_dilate, greyscale_open, greyscale_close, greyscale_white_top_hat, greyscale_black_top_hat) from .selem import (square, rectangle, diamond, disk, cube, octahedron, ball, octagon, star) from .ccomp import label from .watershed import watershed from ._skeletonize import skeletonize, medial_axis from .convex_hull import convex_hull_image, convex_hull_object from .greyreconstruct import reconstruction from .misc import remove_small_objects __all__ = ['binary_erosion', 'binary_dilation', 'binary_opening', 'binary_closing', 'erosion', 'dilation', 'opening', 'closing', 'white_tophat', 'black_tophat', 'greyscale_erode', 'greyscale_dilate', 'greyscale_open', 'greyscale_close', 'greyscale_white_top_hat', 'greyscale_black_top_hat', 'square', 'rectangle', 'diamond', 'disk', 'cube', 'octahedron', 'ball', 'octagon', 'label', 'watershed', 'skeletonize', 'medial_axis', 'convex_hull_image', 'convex_hull_object', 'reconstruction', 'remove_small_objects'] scikit-image-0.9.3/skimage/morphology/_convex_hull.pyx000066400000000000000000000037561223313777300231620ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cimport numpy as cnp def possible_hull(cnp.uint8_t[:, ::1] img): """Return positions of pixels that possibly belong to the convex hull. Parameters ---------- img : ndarray of bool Binary input image. Returns ------- coords : ndarray (cols, 2) The ``(row, column)`` coordinates of all pixels that possibly belong to the convex hull. """ cdef Py_ssize_t r, c cdef Py_ssize_t rows = img.shape[0] cdef Py_ssize_t cols = img.shape[1] # Output: rows storage slots for left boundary pixels # cols storage slots for top boundary pixels # rows storage slots for right boundary pixels # cols storage slots for bottom boundary pixels coords = np.ones((2 * (rows + cols), 2), dtype=np.intp) coords *= -1 cdef Py_ssize_t[:, ::1] nonzero = coords cdef Py_ssize_t rows_cols = rows + cols cdef Py_ssize_t rows_2_cols = 2 * rows + cols cdef Py_ssize_t rows_cols_r, rows_c for r in range(rows): rows_cols_r = rows_cols + r for c in range(cols): if img[r, c] != 0: rows_c = rows + c rows_2_cols_c = rows_2_cols + c # Left check if nonzero[r, 1] == -1: nonzero[r, 0] = r nonzero[r, 1] = c # Right check elif nonzero[rows_cols_r, 1] < c: nonzero[rows_cols_r, 0] = r nonzero[rows_cols_r, 1] = c # Top check if nonzero[rows_c, 1] == -1: nonzero[rows_c, 0] = r nonzero[rows_c, 1] = c # Bottom check elif nonzero[rows_2_cols_c, 0] < r: nonzero[rows_2_cols_c, 0] = r nonzero[rows_2_cols_c, 1] = c return coords[coords[:, 0] != -1] scikit-image-0.9.3/skimage/morphology/_greyreconstruct.pyx000066400000000000000000000103121223313777300240600ustar00rootroot00000000000000""" `reconstruction_loop` originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky """ cimport numpy as cnp cimport cython @cython.boundscheck(False) def reconstruction_loop(cnp.ndarray[dtype=cnp.uint32_t, ndim=1, negative_indices=False, mode='c'] aranks, cnp.ndarray[dtype=cnp.int32_t, ndim=1, negative_indices=False, mode='c'] aprev, cnp.ndarray[dtype=cnp.int32_t, ndim=1, negative_indices=False, mode='c'] anext, cnp.ndarray[dtype=cnp.int32_t, ndim=1, negative_indices=False, mode='c'] astrides, Py_ssize_t current_idx, Py_ssize_t image_stride): """The inner loop for reconstruction. This algorithm uses the rank-order of pixels. If low intensity pixels have a low rank and high intensity pixels have a high rank, then this loop performs reconstruction by dilation. If this ranking is reversed, the result is reconstruction by erosion. For each pixel in the seed image, check its neighbors. If its neighbor's rank is below that of the current pixel, replace the neighbor's rank with the rank of the current pixel. This dilation is limited by the mask, i.e. the rank at each pixel cannot exceed the mask as that pixel. Parameters ---------- aranks : array The rank order of the flattened seed and mask images. aprev, anext: arrays Indices of previous and next pixels in rank sorted order. astrides : array Strides to neighbors of the current pixel. current_idx : int Index of highest-ranked pixel used as starting point in loop. image_stride : int Stride between seed image and mask image in `aranks`. """ cdef unsigned int neighbor_rank, current_rank, mask_rank cdef int i, neighbor_idx, current_link, nprev, nnext cdef int nstrides = astrides.shape[0] cdef cnp.uint32_t *ranks = (aranks.data) cdef cnp.int32_t *prev = (aprev.data) cdef cnp.int32_t *next = (anext.data) cdef cnp.int32_t *strides = (astrides.data) while current_idx != -1: if current_idx < image_stride: current_rank = ranks[current_idx] if current_rank == 0: break for i in range(nstrides): neighbor_idx = current_idx + strides[i] neighbor_rank = ranks[neighbor_idx] # Only propagate neighbors ranked below the current rank if neighbor_rank < current_rank: mask_rank = ranks[neighbor_idx + image_stride] # Only propagate neighbors ranked below the mask rank if neighbor_rank < mask_rank: # Raise the neighbor to the mask rank if # the mask ranked below the current rank if mask_rank < current_rank: current_link = neighbor_idx + image_stride ranks[neighbor_idx] = mask_rank else: current_link = current_idx ranks[neighbor_idx] = current_rank # unlink the neighbor nprev = prev[neighbor_idx] nnext = next[neighbor_idx] next[nprev] = nnext if nnext != -1: prev[nnext] = nprev # link to the neighbor after the current link nnext = next[current_link] next[neighbor_idx] = nnext prev[neighbor_idx] = current_link if nnext >= 0: prev[nnext] = neighbor_idx next[current_link] = neighbor_idx current_idx = next[current_idx] scikit-image-0.9.3/skimage/morphology/_pnpoly.pyx000066400000000000000000000045051223313777300221460ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cimport numpy as cnp from skimage._shared.geometry cimport point_in_polygon, points_in_polygon def grid_points_inside_poly(shape, verts): """Test whether points on a specified grid are inside a polygon. For each ``(r, c)`` coordinate on a grid, i.e. ``(0, 0)``, ``(0, 1)`` etc., test whether that point lies inside a polygon. Parameters ---------- shape : tuple (M, N) Shape of the grid. verts : (V, 2) array Specify the V vertices of the polygon, sorted either clockwise or anti-clockwise. The first point may (but does not need to be) duplicated. Returns ------- mask : (M, N) ndarray of bool True where the grid falls inside the polygon. """ cdef double[:] vx, vy verts = np.asarray(verts) vx = verts[:, 0].astype(np.double) vy = verts[:, 1].astype(np.double) cdef Py_ssize_t V = vx.shape[0] cdef Py_ssize_t M = shape[0] cdef Py_ssize_t N = shape[1] cdef Py_ssize_t m, n cdef cnp.ndarray[dtype=cnp.uint8_t, ndim=2, mode="c"] out = \ np.zeros((M, N), dtype=np.uint8) for m in range(M): for n in range(N): out[m, n] = point_in_polygon(V, &vx[0], &vy[0], m, n) return out.view(bool) def points_inside_poly(points, verts): """Test whether points lie inside a polygon. Parameters ---------- points : (N, 2) array Input points, ``(x, y)``. verts : (M, 2) array Vertices of the polygon, sorted either clockwise or anti-clockwise. The first point may (but does not need to be) duplicated. Returns ------- mask : (N,) array of bool True if corresponding point is inside the polygon. """ cdef double[:] x, y, vx, vy points = np.asarray(points) verts = np.asarray(verts) x = points[:, 0].astype(np.double) y = points[:, 1].astype(np.double) vx = verts[:, 0].astype(np.double) vy = verts[:, 1].astype(np.double) cdef cnp.ndarray[cnp.uint8_t, ndim=1] out = \ np.zeros(x.shape[0], dtype=np.uint8) points_in_polygon(vx.shape[0], &vx[0], &vy[0], x.shape[0], &x[0], &y[0], out.data) return out.astype(bool) scikit-image-0.9.3/skimage/morphology/_skeletonize.py000066400000000000000000000316311223313777300227710ustar00rootroot00000000000000""" Algorithms for computing the skeleton of a binary image """ import numpy as np from scipy import ndimage from ._skeletonize_cy import _skeletonize_loop, _table_lookup_index # --------- Skeletonization by morphological thinning --------- def skeletonize(image): """Return the skeleton of a binary image. Thinning is used to reduce each connected component in a binary image to a single-pixel wide skeleton. Parameters ---------- image : numpy.ndarray A binary image containing the objects to be skeletonized. '1' represents foreground, and '0' represents background. It also accepts arrays of boolean values where True is foreground. Returns ------- skeleton : ndarray A matrix containing the thinned image. See also -------- medial_axis Notes ----- The algorithm [1] works by making successive passes of the image, removing pixels on object borders. This continues until no more pixels can be removed. The image is correlated with a mask that assigns each pixel a number in the range [0...255] corresponding to each possible pattern of its 8 neighbouring pixels. A look up table is then used to assign the pixels a value of 0, 1, 2 or 3, which are selectively removed during the iterations. Note that this algorithm will give different results than a medial axis transform, which is also often referred to as "skeletonization". References ---------- .. [1] A fast parallel algorithm for thinning digital patterns, T. Y. ZHANG and C. Y. SUEN, Communications of the ACM, March 1984, Volume 27, Number 3 Examples -------- >>> X, Y = np.ogrid[0:9, 0:9] >>> ellipse = (1./3 * (X - 4)**2 + (Y - 4)**2 < 3**2).astype(np.uint8) >>> ellipse array([[0, 0, 0, 1, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 1, 1, 1, 0, 0, 0]], dtype=uint8) >>> skel = skeletonize(ellipse) >>> skel array([[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) """ # look up table - there is one entry for each of the 2^8=256 possible # combinations of 8 binary neighbours. 1's, 2's and 3's are candidates # for removal at each iteration of the algorithm. lut = [0, 0, 0, 1, 0, 0, 1, 3, 0, 0, 3, 1, 1, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 3, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 2, 0, 0, 0, 3, 1, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 1, 3, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 1, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0, 0] # convert to unsigned int (this should work for boolean values) skeleton = image.astype(np.uint8) # check some properties of the input image: # - 2D # - binary image with only 0's and 1's if skeleton.ndim != 2: raise ValueError('Skeletonize requires a 2D array') if not np.all(np.in1d(skeleton.flat, (0, 1))): raise ValueError('Image contains values other than 0 and 1') # create the mask that will assign a unique value based on the # arrangement of neighbouring pixels mask = np.array([[ 1, 2, 4], [128, 0, 8], [ 64, 32, 16]], np.uint8) pixel_removed = True while pixel_removed: pixel_removed = False # assign each pixel a unique value based on its foreground neighbours neighbours = ndimage.correlate(skeleton, mask, mode='constant') # ignore background neighbours *= skeleton # use LUT to categorize each foreground pixel as a 0, 1, 2 or 3 codes = np.take(lut, neighbours) # pass 1 - remove the 1's and 3's code_mask = (codes == 1) if np.any(code_mask): pixel_removed = True skeleton[code_mask] = 0 code_mask = (codes == 3) if np.any(code_mask): pixel_removed = True skeleton[code_mask] = 0 # pass 2 - remove the 2's and 3's neighbours = ndimage.correlate(skeleton, mask, mode='constant') neighbours *= skeleton codes = np.take(lut, neighbours) code_mask = (codes == 2) if np.any(code_mask): pixel_removed = True skeleton[code_mask] = 0 code_mask = (codes == 3) if np.any(code_mask): pixel_removed = True skeleton[code_mask] = 0 return skeleton.astype(bool) # --------- Skeletonization by medial axis transform -------- _eight_connect = ndimage.generate_binary_structure(2, 2) def medial_axis(image, mask=None, return_distance=False): """ Compute the medial axis transform of a binary image Parameters ---------- image : binary ndarray mask : binary ndarray, optional If a mask is given, only those elements with a true value in `mask` are used for computing the medial axis. return_distance : bool, optional If true, the distance transform is returned as well as the skeleton. Returns ------- out : ndarray of bools Medial axis transform of the image dist : ndarray of ints Distance transform of the image (only returned if `return_distance` is True) See also -------- skeletonize Notes ----- This algorithm computes the medial axis transform of an image as the ridges of its distance transform. The different steps of the algorithm are as follows * A lookup table is used, that assigns 0 or 1 to each configuration of the 3x3 binary square, whether the central pixel should be removed or kept. We want a point to be removed if it has more than one neighbor and if removing it does not change the number of connected components. * The distance transform to the background is computed, as well as the cornerness of the pixel. * The foreground (value of 1) points are ordered by the distance transform, then the cornerness. * A cython function is called to reduce the image to its skeleton. It processes pixels in the order determined at the previous step, and removes or maintains a pixel according to the lookup table. Because of the ordering, it is possible to process all pixels in only one pass. Examples -------- >>> from skimage import morphology >>> square = np.zeros((7, 7), dtype=np.uint8) >>> square[1:-1, 2:-2] = 1 >>> square array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0]], dtype=uint8) >>> morphology.medial_axis(square).astype(np.uint8) array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0]], dtype=uint8) """ global _eight_connect if mask is None: masked_image = image.astype(np.bool) else: masked_image = image.astype(bool).copy() masked_image[~mask] = False # # Build lookup table - three conditions # 1. Keep only positive pixels (center_is_foreground array). # AND # 2. Keep if removing the pixel results in a different connectivity # (if the number of connected components is different with and # without the central pixel) # OR # 3. Keep if # pixels in neighbourhood is 2 or less # Note that table is independent of image center_is_foreground = (np.arange(512) & 2**4).astype(bool) table = (center_is_foreground # condition 1. & (np.array([ndimage.label(_pattern_of(index), _eight_connect)[1] != ndimage.label(_pattern_of(index & ~ 2**4), _eight_connect)[1] for index in range(512)]) # condition 2 | np.array([np.sum(_pattern_of(index)) < 3 for index in range(512)])) # condition 3 ) # Build distance transform distance = ndimage.distance_transform_edt(masked_image) if return_distance: store_distance = distance.copy() # Corners # The processing order along the edge is critical to the shape of the # resulting skeleton: if you process a corner first, that corner will # be eroded and the skeleton will miss the arm from that corner. Pixels # with fewer neighbors are more "cornery" and should be processed last. # We use a cornerness_table lookup table where the score of a # configuration is the number of background (0-value) pixels in the # 3x3 neighbourhood cornerness_table = np.array([9 - np.sum(_pattern_of(index)) for index in range(512)]) corner_score = _table_lookup(masked_image, cornerness_table) # Define arrays for inner loop i, j = np.mgrid[0:image.shape[0], 0:image.shape[1]] result = masked_image.copy() distance = distance[result] i = np.ascontiguousarray(i[result], dtype=np.intp) j = np.ascontiguousarray(j[result], dtype=np.intp) result = np.ascontiguousarray(result, np.uint8) # Determine the order in which pixels are processed. # We use a random # for tiebreaking. Assign each pixel in the image a # predictable, random # so that masking doesn't affect arbitrary choices # of skeletons # generator = np.random.RandomState(0) tiebreaker = generator.permutation(np.arange(masked_image.sum())) order = np.lexsort((tiebreaker, corner_score[masked_image], distance)) order = np.ascontiguousarray(order, dtype=np.int32) table = np.ascontiguousarray(table, dtype=np.uint8) # Remove pixels not belonging to the medial axis _skeletonize_loop(result, i, j, order, table) result = result.astype(bool) if not mask is None: result[~mask] = image[~mask] if return_distance: return result, store_distance else: return result def _pattern_of(index): """ Return the pattern represented by an index value Byte decomposition of index """ return np.array([[index & 2**0, index & 2**1, index & 2**2], [index & 2**3, index & 2**4, index & 2**5], [index & 2**6, index & 2**7, index & 2**8]], bool) def _table_lookup(image, table): """ Perform a morphological transform on an image, directed by its neighbors Parameters ---------- image : ndarray A binary image table : ndarray A 512-element table giving the transform of each pixel given the values of that pixel and its 8-connected neighbors. border_value : bool The value of pixels beyond the border of the image. Returns ------- result : ndarray of same shape as `image` Transformed image Notes ----- The pixels are numbered like this:: 0 1 2 3 4 5 6 7 8 The index at a pixel is the sum of 2** for pixels that evaluate to true. """ # # We accumulate into the indexer to get the index into the table # at each point in the image # if image.shape[0] < 3 or image.shape[1] < 3: image = image.astype(bool) indexer = np.zeros(image.shape, int) indexer[1:, 1:] += image[:-1, :-1] * 2**0 indexer[1:, :] += image[:-1, :] * 2**1 indexer[1:, :-1] += image[:-1, 1:] * 2**2 indexer[:, 1:] += image[:, :-1] * 2**3 indexer[:, :] += image[:, :] * 2**4 indexer[:, :-1] += image[:, 1:] * 2**5 indexer[:-1, 1:] += image[1:, :-1] * 2**6 indexer[:-1, :] += image[1:, :] * 2**7 indexer[:-1, :-1] += image[1:, 1:] * 2**8 else: indexer = _table_lookup_index(np.ascontiguousarray(image, np.uint8)) image = table[indexer] return image scikit-image-0.9.3/skimage/morphology/_skeletonize_cy.pyx000066400000000000000000000150011223313777300236450ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False ''' Originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky ''' import numpy as np cimport numpy as cnp def _skeletonize_loop(cnp.uint8_t[:, ::1] result, Py_ssize_t[::1] i, Py_ssize_t[::1] j, cnp.int32_t[::1] order, cnp.uint8_t[::1] table): """ Inner loop of skeletonize function Parameters ---------- result : ndarray of uint8 On input, the image to be skeletonized, on output the skeletonized image. i, j : ndarrays The coordinates of each foreground pixel in the image order : ndarray The index of each pixel, in the order of processing (order[0] is the first pixel to process, etc.) table : ndarray The 512-element lookup table of values after transformation (whether to keep or not each configuration in a binary 3x3 array) Notes ----- The loop determines whether each pixel in the image can be removed without changing the Euler number of the image. The pixels are ordered by increasing distance from the background which means a point nearer to the quench-line of the brushfire will be evaluated later than a point closer to the edge. Note that the neighbourhood of a pixel may evolve before the loop arrives at this pixel. This is why it is possible to compute the skeleton in only one pass, thanks to an adapted ordering of the pixels. """ cdef: Py_ssize_t accumulator Py_ssize_t index, order_index Py_ssize_t ii, jj Py_ssize_t rows = result.shape[0] Py_ssize_t cols = result.shape[1] for index in range(order.shape[0]): accumulator = 16 order_index = order[index] ii = i[order_index] jj = j[order_index] # Compute the configuration around the pixel if ii > 0: if jj > 0 and result[ii - 1, jj - 1]: accumulator += 1 if result[ii - 1, jj]: accumulator += 2 if jj < cols - 1 and result[ii - 1, jj + 1]: accumulator += 4 if jj > 0 and result[ii, jj - 1]: accumulator += 8 if jj < cols - 1 and result[ii, jj + 1]: accumulator += 32 if ii < rows - 1: if jj > 0 and result[ii + 1, jj - 1]: accumulator += 64 if result[ii + 1, jj]: accumulator += 128 if jj < cols - 1 and result[ii + 1, jj + 1]: accumulator += 256 # Assign the value of table corresponding to the configuration result[ii, jj] = table[accumulator] def _table_lookup_index(cnp.uint8_t[:, ::1] image): """ Return an index into a table per pixel of a binary image Take the sum of true neighborhood pixel values where the neighborhood looks like this:: 1 2 4 8 16 32 64 128 256 This code could be replaced by a convolution with the kernel:: 256 128 64 32 16 8 4 2 1 but this runs about twice as fast because of inlining and the hardwired kernel. """ cdef: Py_ssize_t[:, ::1] indexer Py_ssize_t *p_indexer cnp.uint8_t *p_image Py_ssize_t i_stride Py_ssize_t i_shape Py_ssize_t j_shape Py_ssize_t i Py_ssize_t j Py_ssize_t offset i_shape = image.shape[0] j_shape = image.shape[1] indexer = np.zeros((i_shape, j_shape), dtype=np.intp) p_indexer = &indexer[0, 0] p_image = &image[0, 0] i_stride = image.strides[0] assert i_shape >= 3 and j_shape >= 3, \ "Please use the slow method for arrays < 3x3" for i in range(1, i_shape-1): offset = i_stride* i + 1 for j in range(1, j_shape - 1): if p_image[offset]: p_indexer[offset + i_stride + 1] += 1 p_indexer[offset + i_stride] += 2 p_indexer[offset + i_stride - 1] += 4 p_indexer[offset + 1] += 8 p_indexer[offset] += 16 p_indexer[offset - 1] += 32 p_indexer[offset - i_stride + 1] += 64 p_indexer[offset - i_stride] += 128 p_indexer[offset - i_stride - 1] += 256 offset += 1 # # Do the corner cases (literally) # if image[0, 0]: indexer[0, 0] += 16 indexer[0, 1] += 8 indexer[1, 0] += 2 indexer[1, 1] += 1 if image[0, j_shape - 1]: indexer[0, j_shape - 2] += 32 indexer[0, j_shape - 1] += 16 indexer[1, j_shape - 2] += 4 indexer[1, j_shape - 1] += 2 if image[i_shape - 1, 0]: indexer[i_shape - 2, 0] += 128 indexer[i_shape - 2, 1] += 64 indexer[i_shape - 1, 0] += 16 indexer[i_shape - 1, 1] += 8 if image[i_shape - 1, j_shape - 1]: indexer[i_shape - 2, j_shape - 2] += 256 indexer[i_shape - 2, j_shape - 1] += 128 indexer[i_shape - 1, j_shape - 2] += 32 indexer[i_shape - 1, j_shape - 1] += 16 # # Do the edges # for j in range(1, j_shape - 1): if image[0, j]: indexer[0, j - 1] += 32 indexer[0, j] += 16 indexer[0, j + 1] += 8 indexer[1, j - 1] += 4 indexer[1, j] += 2 indexer[1, j + 1] += 1 if image[i_shape - 1, j]: indexer[i_shape - 2, j - 1] += 256 indexer[i_shape - 2, j] += 128 indexer[i_shape - 2, j + 1] += 64 indexer[i_shape - 1, j - 1] += 32 indexer[i_shape - 1, j] += 16 indexer[i_shape - 1, j + 1] += 8 for i in range(1, i_shape - 1): if image[i, 0]: indexer[i - 1, 0] += 128 indexer[i, 0] += 16 indexer[i + 1, 0] += 2 indexer[i - 1, 1] += 64 indexer[i, 1] += 8 indexer[i + 1, 1] += 1 if image[i, j_shape - 1]: indexer[i - 1, j_shape - 2] += 256 indexer[i, j_shape - 2] += 32 indexer[i + 1, j_shape - 2] += 4 indexer[i - 1, j_shape - 1] += 128 indexer[i, j_shape - 1] += 16 indexer[i + 1, j_shape - 1] += 2 return np.asarray(indexer) scikit-image-0.9.3/skimage/morphology/_watershed.pyx000066400000000000000000000061421223313777300226120ustar00rootroot00000000000000"""watershed.pyx - scithon implementation of guts of watershed Originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky """ import numpy as np cimport numpy as np cimport cython ctypedef np.int32_t DTYPE_INT32_t DTYPE_BOOL = np.bool ctypedef np.int8_t DTYPE_BOOL_t include "heap_watershed.pxi" @cython.boundscheck(False) def watershed(DTYPE_INT32_t[::1] image, DTYPE_INT32_t[:, ::1] pq, Py_ssize_t age, DTYPE_INT32_t[:, ::1] structure, DTYPE_BOOL_t[::1] mask, DTYPE_INT32_t[::1] output): """Do heavy lifting of watershed algorithm Parameters ---------- image - the flattened image pixels, converted to rank-order pq - the priority queue, starts with the marked pixels the first element in each row is the image intensity the second element is the age at entry into the queue the third element is the index into the flattened image or labels the remaining elements are the coordinates of the point age - the next age to assign to a pixel structure - a numpy int32 array containing the structuring elements that define nearest neighbors. For each row, the first element is the stride from the point to its neighbor in a flattened array. The remaining elements are the offsets from the point to its neighbor in the various dimensions mask - numpy boolean (char) array indicating which pixels to consider and which to ignore. Also flattened. output - put the image labels in here """ cdef Heapitem elem cdef Heapitem new_elem cdef Py_ssize_t nneighbors = structure.shape[0] cdef Py_ssize_t i = 0 cdef Py_ssize_t index = 0 cdef Py_ssize_t old_index = 0 cdef Py_ssize_t max_index = image.shape[0] cdef Heap *hp = heap_from_numpy2() for i in range(pq.shape[0]): elem.value = pq[i, 0] elem.age = pq[i, 1] elem.index = pq[i, 2] heappush(hp, &elem) while hp.items > 0: # # Pop off an item to work on # heappop(hp, &elem) #################################################### # loop through each of the structuring elements # old_index = elem.index for i in range(nneighbors): # get the flattened address of the neighbor index = structure[i, 0] + old_index if index < 0 or index >= max_index or output[index] or \ not mask[index]: continue new_elem.value = image[index] new_elem.age = elem.age + 1 new_elem.index = index age += 1 output[index] = output[old_index] # # Push the neighbor onto the heap to work on it later # heappush(hp, &new_elem) heap_done(hp) scikit-image-0.9.3/skimage/morphology/binary.py000066400000000000000000000106671223313777300215700ustar00rootroot00000000000000import warnings import numpy as np from scipy import ndimage def binary_erosion(image, selem, out=None): """Return fast binary morphological erosion of an image. This function returns the same result as greyscale erosion but performs faster for binary images. Morphological erosion sets a pixel at ``(i,j)`` to the minimum over all pixels in the neighborhood centered at ``(i,j)``. Erosion shrinks bright regions and enlarges dark regions. Parameters ---------- image : ndarray Binary input image. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray of bool The array to store the result of the morphology. If None is passed, a new array will be allocated. Returns ------- eroded : ndarray of bool or uint The result of the morphological erosion with values in ``[0, 1]``. """ selem = (selem != 0) selem_sum = np.sum(selem) if selem_sum <= 255: conv = np.empty_like(image, dtype=np.uint8) else: conv = np.empty_like(image, dtype=np.uint) binary = (image > 0).view(np.uint8) ndimage.convolve(binary, selem, mode='constant', cval=1, output=conv) if out is None: out = conv return np.equal(conv, selem_sum, out=out) def binary_dilation(image, selem, out=None): """Return fast binary morphological dilation of an image. This function returns the same result as greyscale dilation but performs faster for binary images. Morphological dilation sets a pixel at ``(i,j)`` to the maximum over all pixels in the neighborhood centered at ``(i,j)``. Dilation enlarges bright regions and shrinks dark regions. Parameters ---------- image : ndarray Binary input image. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray of bool The array to store the result of the morphology. If None, is passed, a new array will be allocated. Returns ------- dilated : ndarray of bool or uint The result of the morphological dilation with values in ``[0, 1]``. """ selem = (selem != 0) if np.sum(selem) <= 255: conv = np.empty_like(image, dtype=np.uint8) else: conv = np.empty_like(image, dtype=np.uint) binary = (image > 0).view(np.uint8) ndimage.convolve(binary, selem, mode='constant', cval=0, output=conv) if out is None: out = conv return np.not_equal(conv, 0, out=out) def binary_opening(image, selem, out=None): """Return fast binary morphological opening of an image. This function returns the same result as greyscale opening but performs faster for binary images. The morphological opening on an image is defined as an erosion followed by a dilation. Opening can remove small bright spots (i.e. "salt") and connect small dark cracks. This tends to "open" up (dark) gaps between (bright) features. Parameters ---------- image : ndarray Binary input image. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray of bool The array to store the result of the morphology. If None is passed, a new array will be allocated. Returns ------- opening : ndarray of bool The result of the morphological opening. """ eroded = binary_erosion(image, selem) out = binary_dilation(eroded, selem, out=out) return out def binary_closing(image, selem, out=None): """Return fast binary morphological closing of an image. This function returns the same result as greyscale closing but performs faster for binary images. The morphological closing on an image is defined as a dilation followed by an erosion. Closing can remove small dark spots (i.e. "pepper") and connect small bright cracks. This tends to "close" up (dark) gaps between (bright) features. Parameters ---------- image : ndarray Binary input image. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray of bool The array to store the result of the morphology. If None, is passed, a new array will be allocated. Returns ------- closing : ndarray of bool The result of the morphological closing. """ dilated = binary_dilation(image, selem) out = binary_erosion(dilated, selem, out=out) return out scikit-image-0.9.3/skimage/morphology/ccomp.pxd000066400000000000000000000005371223313777300215430ustar00rootroot00000000000000"""Export fast union find in Cython""" cimport numpy as cnp DTYPE = cnp.intp ctypedef cnp.intp_t DTYPE_t cdef DTYPE_t find_root(DTYPE_t *forest, DTYPE_t n) cdef void set_root(DTYPE_t *forest, DTYPE_t n, DTYPE_t root) cdef void join_trees(DTYPE_t *forest, DTYPE_t n, DTYPE_t m) cdef void link_bg(DTYPE_t *forest, DTYPE_t n, DTYPE_t *background_node) scikit-image-0.9.3/skimage/morphology/ccomp.pyx000066400000000000000000000136131223313777300215670ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cimport numpy as cnp """ See also: Christophe Fiorio and Jens Gustedt, "Two linear time Union-Find strategies for image processing", Theoretical Computer Science 154 (1996), pp. 165-181. Kensheng Wu, Ekow Otoo and Arie Shoshani, "Optimizing connected component labeling algorithms", Paper LBNL-56864, 2005, Lawrence Berkeley National Laboratory (University of California), http://repositories.cdlib.org/lbnl/LBNL-56864 """ # Tree operations implemented by an array as described in Wu et al. # The term "forest" is used to indicate an array that stores one or more trees DTYPE = np.intp cdef DTYPE_t find_root(DTYPE_t *forest, DTYPE_t n): """Find the root of node n. """ cdef DTYPE_t root = n while (forest[root] < root): root = forest[root] return root cdef inline void set_root(DTYPE_t *forest, DTYPE_t n, DTYPE_t root): """ Set all nodes on a path to point to new_root. """ cdef DTYPE_t j while (forest[n] < n): j = forest[n] forest[n] = root n = j forest[n] = root cdef inline void join_trees(DTYPE_t *forest, DTYPE_t n, DTYPE_t m): """Join two trees containing nodes n and m. """ cdef DTYPE_t root = find_root(forest, n) cdef DTYPE_t root_m if (n != m): root_m = find_root(forest, m) if (root > root_m): root = root_m set_root(forest, n, root) set_root(forest, m, root) cdef inline void link_bg(DTYPE_t *forest, DTYPE_t n, DTYPE_t *background_node): """ Link a node to the background node. """ if background_node[0] == -999: background_node[0] = n join_trees(forest, n, background_node[0]) # Connected components search as described in Fiorio et al. def label(input, DTYPE_t neighbors=8, DTYPE_t background=-1, return_num=False): """Label connected regions of an integer array. Two pixels are connected when they are neighbors and have the same value. They can be neighbors either in a 4- or 8-connected sense:: 4-connectivity 8-connectivity [ ] [ ] [ ] [ ] | \ | / [ ]--[ ]--[ ] [ ]--[ ]--[ ] | / | \\ [ ] [ ] [ ] [ ] Parameters ---------- input : ndarray of dtype int Image to label. neighbors : {4, 8}, int Whether to use 4- or 8-connectivity. background : int Consider all pixels with this value as background pixels, and label them as -1. Returns ------- labels : ndarray of dtype int Labeled array, where all connected regions are assigned the same integer value. num : int, optional Number of labels, which equals the maximum label index and is only returned if return_num is `True`. Examples -------- >>> x = np.eye(3).astype(int) >>> print(x) [[1 0 0] [0 1 0] [0 0 1]] >>> print(m.label(x, neighbors=4)) [[0 1 1] [2 3 1] [2 2 4]] >>> print(m.label(x, neighbors=8)) [[0 1 1] [1 0 1] [1 1 0]] >>> x = np.array([[1, 0, 0], ... [1, 1, 5], ... [0, 0, 0]]) >>> print(m.label(x, background=0)) [[ 0 -1 -1] [ 0 0 1] [-1 -1 -1]] """ cdef DTYPE_t rows = input.shape[0] cdef DTYPE_t cols = input.shape[1] cdef cnp.ndarray[DTYPE_t, ndim=2] data = np.array(input, copy=True, dtype=DTYPE) cdef cnp.ndarray[DTYPE_t, ndim=2] forest forest = np.arange(data.size, dtype=DTYPE).reshape((rows, cols)) cdef DTYPE_t *forest_p = forest.data cdef DTYPE_t *data_p = data.data cdef DTYPE_t i, j cdef DTYPE_t background_node = -999 if neighbors != 4 and neighbors != 8: raise ValueError('Neighbors must be either 4 or 8.') # Initialize the first row if data[0, 0] == background: link_bg(forest_p, 0, &background_node) for j in range(1, cols): if data[0, j] == background: link_bg(forest_p, j, &background_node) if data[0, j] == data[0, j-1]: join_trees(forest_p, j, j-1) for i in range(1, rows): # Handle the first column if data[i, 0] == background: link_bg(forest_p, i * cols, &background_node) if data[i, 0] == data[i-1, 0]: join_trees(forest_p, i*cols, (i-1)*cols) if neighbors == 8: if data[i, 0] == data[i-1, 1]: join_trees(forest_p, i*cols, (i-1)*cols + 1) for j in range(1, cols): if data[i, j] == background: link_bg(forest_p, i * cols + j, &background_node) if neighbors == 8: if data[i, j] == data[i-1, j-1]: join_trees(forest_p, i*cols + j, (i-1)*cols + j - 1) if data[i, j] == data[i-1, j]: join_trees(forest_p, i*cols + j, (i-1)*cols + j) if neighbors == 8: if j < cols - 1: if data[i, j] == data[i - 1, j + 1]: join_trees(forest_p, i*cols + j, (i-1)*cols + j + 1) if data[i, j] == data[i, j-1]: join_trees(forest_p, i*cols + j, i*cols + j - 1) # Label output cdef DTYPE_t ctr = 0 for i in range(rows): for j in range(cols): if (i*cols + j) == background_node: data[i, j] = -1 elif (i*cols + j) == forest[i, j]: data[i, j] = ctr ctr = ctr + 1 else: data[i, j] = data_p[forest[i, j]] # Work around a bug in ndimage's type checking on 32-bit platforms if data.dtype == np.int32: data = data.view(np.int32) if return_num: return data, ctr else: return data scikit-image-0.9.3/skimage/morphology/cmorph.pyx000066400000000000000000000114721223313777300217570ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cimport numpy as np from libc.stdlib cimport malloc, free def _dilate(np.uint8_t[:, :] image, np.uint8_t[:, :] selem, np.uint8_t[:, :] out=None, char shift_x=0, char shift_y=0): """Return greyscale morphological dilation of an image. Morphological dilation sets a pixel at (i,j) to the maximum over all pixels in the neighborhood centered at (i,j). Dilation enlarges bright regions and shrinks dark regions. Parameters ---------- image : ndarray Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray The array to store the result of the morphology. If None, is passed, a new array will be allocated. shift_x, shift_y : bool shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Returns ------- dilated : uint8 array The result of the morphological dilation. """ cdef Py_ssize_t rows = image.shape[0] cdef Py_ssize_t cols = image.shape[1] cdef Py_ssize_t srows = selem.shape[0] cdef Py_ssize_t scols = selem.shape[1] cdef Py_ssize_t centre_r = int(selem.shape[0] / 2) - shift_y cdef Py_ssize_t centre_c = int(selem.shape[1] / 2) - shift_x image = np.ascontiguousarray(image) if out is None: out = np.zeros((rows, cols), dtype=np.uint8) else: out = np.ascontiguousarray(out) cdef Py_ssize_t r, c, rr, cc, s, value, local_max cdef Py_ssize_t selem_num = np.sum(np.asarray(selem) != 0) cdef Py_ssize_t* sr = malloc(selem_num * sizeof(Py_ssize_t)) cdef Py_ssize_t* sc = malloc(selem_num * sizeof(Py_ssize_t)) s = 0 for r in range(srows): for c in range(scols): if selem[r, c] != 0: sr[s] = r - centre_r sc[s] = c - centre_c s += 1 for r in range(rows): for c in range(cols): local_max = 0 for s in range(selem_num): rr = r + sr[s] cc = c + sc[s] if 0 <= rr < rows and 0 <= cc < cols: value = image[rr, cc] if value > local_max: local_max = value out[r, c] = local_max free(sr) free(sc) return np.asarray(out) def _erode(np.uint8_t[:, :] image, np.uint8_t[:, :] selem, np.uint8_t[:, :] out=None, char shift_x=0, char shift_y=0): """Return greyscale morphological erosion of an image. Morphological erosion sets a pixel at (i,j) to the minimum over all pixels in the neighborhood centered at (i,j). Erosion shrinks bright regions and enlarges dark regions. Parameters ---------- image : ndarray Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray The array to store the result of the morphology. If None is passed, a new array will be allocated. shift_x, shift_y : bool shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Returns ------- eroded : uint8 array The result of the morphological erosion. """ cdef Py_ssize_t rows = image.shape[0] cdef Py_ssize_t cols = image.shape[1] cdef Py_ssize_t srows = selem.shape[0] cdef Py_ssize_t scols = selem.shape[1] cdef Py_ssize_t centre_r = int(selem.shape[0] / 2) - shift_y cdef Py_ssize_t centre_c = int(selem.shape[1] / 2) - shift_x image = np.ascontiguousarray(image) if out is None: out = np.zeros((rows, cols), dtype=np.uint8) else: out = np.ascontiguousarray(out) cdef int r, c, rr, cc, s, value, local_min cdef Py_ssize_t selem_num = np.sum(np.asarray(selem) != 0) cdef Py_ssize_t* sr = malloc(selem_num * sizeof(Py_ssize_t)) cdef Py_ssize_t* sc = malloc(selem_num * sizeof(Py_ssize_t)) s = 0 for r in range(srows): for c in range(scols): if selem[r, c] != 0: sr[s] = r - centre_r sc[s] = c - centre_c s += 1 for r in range(rows): for c in range(cols): local_min = 255 for s in range(selem_num): rr = r + sr[s] cc = c + sc[s] if 0 <= rr < rows and 0 <= cc < cols: value = image[rr, cc] if value < local_min: local_min = value out[r, c] = local_min free(sr) free(sc) return np.asarray(out) scikit-image-0.9.3/skimage/morphology/convex_hull.py000066400000000000000000000067711223313777300226330ustar00rootroot00000000000000__all__ = ['convex_hull_image', 'convex_hull_object'] import numpy as np from ._pnpoly import grid_points_inside_poly from ._convex_hull import possible_hull from skimage.morphology import label from skimage.util import unique_rows def convex_hull_image(image): """Compute the convex hull image of a binary image. The convex hull is the set of pixels included in the smallest convex polygon that surround all white pixels in the input image. Parameters ---------- image : ndarray Binary input image. This array is cast to bool before processing. Returns ------- hull : ndarray of bool Binary image with pixels in convex hull set to True. References ---------- .. [1] http://blogs.mathworks.com/steve/2011/10/04/binary-image-convex-hull-algorithm-notes/ """ image = image.astype(bool) # Here we do an optimisation by choosing only pixels that are # the starting or ending pixel of a row or column. This vastly # limits the number of coordinates to examine for the virtual # hull. coords = possible_hull(image.astype(np.uint8)) N = len(coords) # Add a vertex for the middle of each pixel edge coords_corners = np.empty((N * 4, 2)) for i, (x_offset, y_offset) in enumerate(zip((0, 0, -0.5, 0.5), (-0.5, 0.5, 0, 0))): coords_corners[i * N:(i + 1) * N] = coords + [x_offset, y_offset] # repeated coordinates can *sometimes* cause problems in # scipy.spatial.Delaunay, so we remove them. coords = unique_rows(coords_corners) try: from scipy.spatial import Delaunay except ImportError: raise ImportError('Could not import scipy.spatial, only available in ' 'scipy >= 0.9.') # Find the convex hull chull = Delaunay(coords).convex_hull v = coords[np.unique(chull)] # Sort vertices clock-wise v_centred = v - v.mean(axis=0) angles = np.arctan2(v_centred[:, 0], v_centred[:, 1]) v = v[np.argsort(angles)] # For each pixel coordinate, check whether that pixel # lies inside the convex hull mask = grid_points_inside_poly(image.shape[:2], v) return mask def convex_hull_object(image, neighbors=8): """Compute the convex hull image of individual objects in a binary image. The convex hull is the set of pixels included in the smallest convex polygon that surround all white pixels in the input image. Parameters ---------- image : ndarray Binary input image. neighbors : {4, 8}, int Whether to use 4- or 8-connectivity. Returns ------- hull : ndarray of bool Binary image with pixels in convex hull set to True. Note ---- This function uses skimage.morphology.label to define unique objects, finds the convex hull of each using convex_hull_image, and combines these regions with logical OR. Be aware the convex hulls of unconnected objects may overlap in the result. If this is suspected, consider using convex_hull_image separately on each object. """ if neighbors != 4 and neighbors != 8: raise ValueError('Neighbors must be either 4 or 8.') labeled_im = label(image, neighbors, background=0) convex_obj = np.zeros(image.shape, dtype=bool) convex_img = np.zeros(image.shape, dtype=bool) for i in range(0, labeled_im.max() + 1): convex_obj = convex_hull_image(labeled_im == i) convex_img = np.logical_or(convex_img, convex_obj) return convex_img scikit-image-0.9.3/skimage/morphology/grey.py000066400000000000000000000254341223313777300212500ustar00rootroot00000000000000import warnings from skimage import img_as_ubyte from . import cmorph __all__ = ['erosion', 'dilation', 'opening', 'closing', 'white_tophat', 'black_tophat', 'greyscale_erode', 'greyscale_dilate', 'greyscale_open', 'greyscale_close', 'greyscale_white_top_hat', 'greyscale_black_top_hat'] def erosion(image, selem, out=None, shift_x=False, shift_y=False): """Return greyscale morphological erosion of an image. Morphological erosion sets a pixel at (i,j) to the minimum over all pixels in the neighborhood centered at (i,j). Erosion shrinks bright regions and enlarges dark regions. Parameters ---------- image : ndarray Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray The array to store the result of the morphology. If None is passed, a new array will be allocated. shift_x, shift_y : bool shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Returns ------- eroded : uint8 array The result of the morphological erosion. Examples -------- >>> # Erosion shrinks bright regions >>> import numpy as np >>> from skimage.morphology import square >>> bright_square = np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) >>> erosion(bright_square, square(3)) array([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], dtype=uint8) """ if image is out: raise NotImplementedError("In-place erosion not supported!") image = img_as_ubyte(image) selem = img_as_ubyte(selem) return cmorph._erode(image, selem, out=out, shift_x=shift_x, shift_y=shift_y) def dilation(image, selem, out=None, shift_x=False, shift_y=False): """Return greyscale morphological dilation of an image. Morphological dilation sets a pixel at (i,j) to the maximum over all pixels in the neighborhood centered at (i,j). Dilation enlarges bright regions and shrinks dark regions. Parameters ---------- image : ndarray Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray The array to store the result of the morphology. If None, is passed, a new array will be allocated. shift_x, shift_y : bool shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Returns ------- dilated : uint8 array The result of the morphological dilation. Examples -------- >>> # Dilation enlarges bright regions >>> import numpy as np >>> from skimage.morphology import square >>> bright_pixel = np.array([[0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0], ... [0, 0, 1, 0, 0], ... [0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) >>> dilation(bright_pixel, square(3)) array([[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]], dtype=uint8) """ if image is out: raise NotImplementedError("In-place dilation not supported!") image = img_as_ubyte(image) selem = img_as_ubyte(selem) return cmorph._dilate(image, selem, out=out, shift_x=shift_x, shift_y=shift_y) def opening(image, selem, out=None): """Return greyscale morphological opening of an image. The morphological opening on an image is defined as an erosion followed by a dilation. Opening can remove small bright spots (i.e. "salt") and connect small dark cracks. This tends to "open" up (dark) gaps between (bright) features. Parameters ---------- image : ndarray Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray The array to store the result of the morphology. If None is passed, a new array will be allocated. Returns ------- opening : uint8 array The result of the morphological opening. Examples -------- >>> # Open up gap between two bright regions (but also shrink regions) >>> import numpy as np >>> from skimage.morphology import square >>> bad_connection = np.array([[1, 0, 0, 0, 1], ... [1, 1, 0, 1, 1], ... [1, 1, 1, 1, 1], ... [1, 1, 0, 1, 1], ... [1, 0, 0, 0, 1]], dtype=np.uint8) >>> opening(bad_connection, square(3)) array([[0, 0, 0, 0, 0], [1, 1, 0, 1, 1], [1, 1, 0, 1, 1], [1, 1, 0, 1, 1], [0, 0, 0, 0, 0]], dtype=uint8) """ h, w = selem.shape shift_x = True if (w % 2) == 0 else False shift_y = True if (h % 2) == 0 else False eroded = erosion(image, selem) out = dilation(eroded, selem, out=out, shift_x=shift_x, shift_y=shift_y) return out def closing(image, selem, out=None): """Return greyscale morphological closing of an image. The morphological closing on an image is defined as a dilation followed by an erosion. Closing can remove small dark spots (i.e. "pepper") and connect small bright cracks. This tends to "close" up (dark) gaps between (bright) features. Parameters ---------- image : ndarray Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray The array to store the result of the morphology. If None, is passed, a new array will be allocated. Returns ------- closing : uint8 array The result of the morphological closing. Examples -------- >>> # Close a gap between two bright lines >>> import numpy as np >>> from skimage.morphology import square >>> broken_line = np.array([[0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0], ... [1, 1, 0, 1, 1], ... [0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) >>> closing(broken_line, square(3)) array([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 1, 1, 1, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], dtype=uint8) """ h, w = selem.shape shift_x = True if (w % 2) == 0 else False shift_y = True if (h % 2) == 0 else False dilated = dilation(image, selem) out = erosion(dilated, selem, out=out, shift_x=shift_x, shift_y=shift_y) return out def white_tophat(image, selem, out=None): """Return white top hat of an image. The white top hat of an image is defined as the image minus its morphological opening. This operation returns the bright spots of the image that are smaller than the structuring element. Parameters ---------- image : ndarray Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray The array to store the result of the morphology. If None is passed, a new array will be allocated. Returns ------- opening : uint8 array The result of the morphological white top hat. Examples -------- >>> # Subtract grey background from bright peak >>> import numpy as np >>> from skimage.morphology import square >>> bright_on_grey = np.array([[2, 3, 3, 3, 2], ... [3, 4, 5, 4, 3], ... [3, 5, 9, 5, 3], ... [3, 4, 5, 4, 3], ... [2, 3, 3, 3, 2]], dtype=np.uint8) >>> white_tophat(bright_on_grey, square(3)) array([[0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 1, 5, 1, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0]], dtype=uint8) """ if image is out: raise NotImplementedError("Cannot perform white top hat in place.") out = opening(image, selem, out=out) out = image - out return out def black_tophat(image, selem, out=None): """Return black top hat of an image. The black top hat of an image is defined as its morphological closing minus the original image. This operation returns the dark spots of the image that are smaller than the structuring element. Note that dark spots in the original image are bright spots after the black top hat. Parameters ---------- image : ndarray Image array. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray The array to store the result of the morphology. If None is passed, a new array will be allocated. Returns ------- opening : uint8 array The result of the black top filter. Examples -------- >>> # Change dark peak to bright peak and subtract background >>> import numpy as np >>> from skimage.morphology import square >>> dark_on_grey = np.array([[7, 6, 6, 6, 7], ... [6, 5, 4, 5, 6], ... [6, 4, 0, 4, 6], ... [6, 5, 4, 5, 6], ... [7, 6, 6, 6, 7]], dtype=np.uint8) >>> black_tophat(dark_on_grey, square(3)) array([[0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 1, 5, 1, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0]], dtype=uint8) """ if image is out: raise NotImplementedError("Cannot perform white top hat in place.") out = closing(image, selem, out=out) out = out - image return out def greyscale_erode(*args, **kwargs): warnings.warn("`greyscale_erode` renamed `erosion`.") return erosion(*args, **kwargs) def greyscale_dilate(*args, **kwargs): warnings.warn("`greyscale_dilate` renamed `dilation`.") return dilation(*args, **kwargs) def greyscale_open(*args, **kwargs): warnings.warn("`greyscale_open` renamed `opening`.") return opening(*args, **kwargs) def greyscale_close(*args, **kwargs): warnings.warn("`greyscale_close` renamed `closing`.") return closing(*args, **kwargs) def greyscale_white_top_hat(*args, **kwargs): warnings.warn("`greyscale_white_top_hat` renamed `white_tophat`.") return white_tophat(*args, **kwargs) def greyscale_black_top_hat(*args, **kwargs): warnings.warn("`greyscale_black_top_hat` renamed `black_tophat`.") return black_tophat(*args, **kwargs) scikit-image-0.9.3/skimage/morphology/greyreconstruct.py000066400000000000000000000200471223313777300235370ustar00rootroot00000000000000""" This morphological reconstruction routine was adapted from CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky """ import numpy as np from skimage.filter._rank_order import rank_order def reconstruction(seed, mask, method='dilation', selem=None, offset=None): """Perform a morphological reconstruction of an image. Morphological reconstruction by dilation is similar to basic morphological dilation: high-intensity values will replace nearby low-intensity values. The basic dilation operator, however, uses a structuring element to determine how far a value in the input image can spread. In contrast, reconstruction uses two images: a "seed" image, which specifies the values that spread, and a "mask" image, which gives the maximum allowed value at each pixel. The mask image, like the structuring element, limits the spread of high-intensity values. Reconstruction by erosion is simply the inverse: low-intensity values spread from the seed image and are limited by the mask image, which represents the minimum allowed value. Alternatively, you can think of reconstruction as a way to isolate the connected regions of an image. For dilation, reconstruction connects regions marked by local maxima in the seed image: neighboring pixels less-than-or-equal-to those seeds are connected to the seeded region. Local maxima with values larger than the seed image will get truncated to the seed value. Parameters ---------- seed : ndarray The seed image (a.k.a. marker image), which specifies the values that are dilated or eroded. mask : ndarray The maximum (dilation) / minimum (erosion) allowed value at each pixel. method : {'dilation'|'erosion'} Perform reconstruction by dilation or erosion. In dilation (or erosion), the seed image is dilated (or eroded) until limited by the mask image. For dilation, each seed value must be less than or equal to the corresponding mask value; for erosion, the reverse is true. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. Returns ------- reconstructed : ndarray The result of morphological reconstruction. Examples -------- >>> import numpy as np >>> from skimage.morphology import reconstruction First, we create a sinusoidal mask image with peaks at middle and ends. >>> x = np.linspace(0, 4 * np.pi) >>> y_mask = np.cos(x) Then, we create a seed image initialized to the minimum mask value (for reconstruction by dilation, min-intensity values don't spread) and add "seeds" to the left and right peak, but at a fraction of peak value (1). >>> y_seed = y_mask.min() * np.ones_like(x) >>> y_seed[0] = 0.5 >>> y_seed[-1] = 0 >>> y_rec = reconstruction(y_seed, y_mask) The reconstructed image (or curve, in this case) is exactly the same as the mask image, except that the peaks are truncated to 0.5 and 0. The middle peak disappears completely: Since there were no seed values in this peak region, its reconstructed value is truncated to the surrounding value (-1). As a more practical example, we try to extract the bright features of an image by subtracting a background image created by reconstruction. >>> y, x = np.mgrid[:20:0.5, :20:0.5] >>> bumps = np.sin(x) + np.sin(y) To create the background image, set the mask image to the original image, and the seed image to the original image with an intensity offset, `h`. >>> h = 0.3 >>> seed = bumps - h >>> background = reconstruction(seed, bumps) The resulting reconstructed image looks exactly like the original image, but with the peaks of the bumps cut off. Subtracting this reconstructed image from the original image leaves just the peaks of the bumps >>> hdome = bumps - background This operation is known as the h-dome of the image and leaves features of height `h` in the subtracted image. Notes ----- The algorithm is taken from [1]_. Applications for greyscale reconstruction are discussed in [2]_ and [3]_. References ---------- .. [1] Robinson, "Efficient morphological reconstruction: a downhill filter", Pattern Recognition Letters 25 (2004) 1759-1767. .. [2] Vincent, L., "Morphological Grayscale Reconstruction in Image Analysis: Applications and Efficient Algorithms", IEEE Transactions on Image Processing (1993) .. [3] Soille, P., "Morphological Image Analysis: Principles and Applications", Chapter 6, 2nd edition (2003), ISBN 3540429883. """ assert tuple(seed.shape) == tuple(mask.shape) if method == 'dilation' and np.any(seed > mask): raise ValueError("Intensity of seed image must be less than that " "of the mask image for reconstruction by dilation.") elif method == 'erosion' and np.any(seed < mask): raise ValueError("Intensity of seed image must be greater than that " "of the mask image for reconstruction by erosion.") try: from ._greyreconstruct import reconstruction_loop except ImportError: raise ImportError("_greyreconstruct extension not available.") if selem is None: selem = np.ones([3] * seed.ndim, dtype=bool) else: selem = selem.copy() if offset is None: if not all([d % 2 == 1 for d in selem.shape]): ValueError("Footprint dimensions must all be odd") offset = np.array([d // 2 for d in selem.shape]) # Cross out the center of the selem selem[[slice(d, d + 1) for d in offset]] = False # Make padding for edges of reconstructed image so we can ignore boundaries padding = (np.array(selem.shape) / 2).astype(int) dims = np.zeros(seed.ndim + 1, dtype=int) dims[1:] = np.array(seed.shape) + 2 * padding dims[0] = 2 inside_slices = [slice(p, -p) for p in padding] # Set padded region to minimum image intensity and mask along first axis so # we can interleave image and mask pixels when sorting. if method == 'dilation': pad_value = np.min(seed) elif method == 'erosion': pad_value = np.max(seed) images = np.ones(dims) * pad_value images[[0] + inside_slices] = seed images[[1] + inside_slices] = mask # Create a list of strides across the array to get the neighbors within # a flattened array value_stride = np.array(images.strides[1:]) / images.dtype.itemsize image_stride = images.strides[0] // images.dtype.itemsize selem_mgrid = np.mgrid[[slice(-o, d - o) for d, o in zip(selem.shape, offset)]] selem_offsets = selem_mgrid[:, selem].transpose() nb_strides = np.array([np.sum(value_stride * selem_offset) for selem_offset in selem_offsets], np.int32) images = images.flatten() # Erosion goes smallest to largest; dilation goes largest to smallest. index_sorted = np.argsort(images).astype(np.int32) if method == 'dilation': index_sorted = index_sorted[::-1] # Make a linked list of pixels sorted by value. -1 is the list terminator. prev = -np.ones(len(images), np.int32) next = -np.ones(len(images), np.int32) prev[index_sorted[1:]] = index_sorted[:-1] next[index_sorted[:-1]] = index_sorted[1:] # Cython inner-loop compares the rank of pixel values. if method == 'dilation': value_rank, value_map = rank_order(images) elif method == 'erosion': value_rank, value_map = rank_order(-images) value_map = -value_map start = index_sorted[0] reconstruction_loop(value_rank, prev, next, nb_strides, start, image_stride) # Reshape reconstructed image to original image shape and remove padding. rec_img = value_map[value_rank[:image_stride]] rec_img.shape = np.array(seed.shape) + 2 * padding return rec_img[inside_slices] scikit-image-0.9.3/skimage/morphology/heap_general.pxi000066400000000000000000000074711223313777300230650ustar00rootroot00000000000000""" Originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky """ from libc.stdlib cimport free, malloc, realloc cdef struct Heap: Py_ssize_t items Py_ssize_t space Heapitem *data Heapitem **ptrs cdef inline Heap *heap_from_numpy2(): cdef Py_ssize_t k cdef Heap *heap heap = malloc(sizeof (Heap)) heap.items = 0 heap.space = 1000 heap.data = malloc(heap.space * sizeof(Heapitem)) heap.ptrs = malloc(heap.space * sizeof(Heapitem *)) for k in range(heap.space): heap.ptrs[k] = heap.data + k return heap cdef inline void heap_done(Heap *heap): free(heap.data) free(heap.ptrs) free(heap) cdef inline void swap(Py_ssize_t a, Py_ssize_t b, Heap *h): h.ptrs[a], h.ptrs[b] = h.ptrs[b], h.ptrs[a] ###################################################### # heappop - inlined # # pop an element off the heap, maintaining heap invariant # # Note: heap ordering is the same as python heapq, i.e., smallest first. ###################################################### cdef inline void heappop(Heap *heap, Heapitem *dest): cdef Py_ssize_t i, smallest, l, r # heap indices # # Start by copying the first element to the destination # dest[0] = heap.ptrs[0][0] heap.items -= 1 # if the heap is now empty, we can return, no need to fix heap. if heap.items == 0: return # # Move the last element in the heap to the first. # swap(0, heap.items, heap) # # Restore the heap invariant. # i = 0 smallest = i while True: # loop invariant here: smallest == i # find smallest of (i, l, r), and swap it to i's position if necessary l = i * 2 + 1 #__left(i) r = i * 2 + 2 #__right(i) if l < heap.items: if smaller(heap.ptrs[l], heap.ptrs[i]): smallest = l if r < heap.items and smaller(heap.ptrs[r], heap.ptrs[smallest]): smallest = r else: # this is unnecessary, but trims 0.04 out of 0.85 seconds... break # the element at i is smaller than either of its children, heap # invariant restored. if smallest == i: break # swap swap(i, smallest, heap) i = smallest ################################################## # heappush - inlined # # push the element onto the heap, maintaining the heap invariant # # Note: heap ordering is the same as python heapq, i.e., smallest first. ################################################## cdef inline void heappush(Heap *heap, Heapitem *new_elem): cdef Py_ssize_t child = heap.items cdef Py_ssize_t parent cdef Py_ssize_t k cdef Heapitem *new_data # grow if necessary if heap.items == heap.space: heap.space = heap.space * 2 new_data = realloc(heap.data, (heap.space * sizeof(Heapitem))) heap.ptrs = realloc(heap.ptrs, (heap.space * sizeof(Heapitem *))) for k in range(heap.items): heap.ptrs[k] = new_data + (heap.ptrs[k] - heap.data) for k in range(heap.items, heap.space): heap.ptrs[k] = new_data + k heap.data = new_data # insert new data at child heap.ptrs[child][0] = new_elem[0] heap.items += 1 # restore heap invariant, all parents <= children while child > 0: parent = (child + 1) / 2 - 1 # __parent(i) if smaller(heap.ptrs[child], heap.ptrs[parent]): swap(parent, child, heap) child = parent else: break scikit-image-0.9.3/skimage/morphology/heap_watershed.pxi000066400000000000000000000010541223313777300234250ustar00rootroot00000000000000""" Originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky """ cimport numpy as cnp cdef struct Heapitem: cnp.int32_t value cnp.int32_t age Py_ssize_t index cdef inline int smaller(Heapitem *a, Heapitem *b): if a.value <> b.value: return a.value < b.value return a.age < b.age include "heap_general.pxi" scikit-image-0.9.3/skimage/morphology/misc.py000066400000000000000000000056571223313777300212420ustar00rootroot00000000000000import numpy as np import scipy.ndimage as nd def remove_small_objects(ar, min_size=64, connectivity=1, in_place=False): """Remove connected components smaller than the specified size. Parameters ---------- ar : ndarray (arbitrary shape, int or bool type) The array containing the connected components of interest. If the array type is int, it is assumed that it contains already-labeled objects. The ints must be non-negative. min_size : int, optional (default: 64) The smallest allowable connected component size. connectivity : int, {1, 2, ..., ar.ndim}, optional (default: 1) The connectivity defining the neighborhood of a pixel. in_place : bool, optional (default: False) If `True`, remove the connected components in the input array itself. Otherwise, make a copy. Raises ------ TypeError If the input array is of an invalid type, such as float or string. ValueError If the input array contains negative values. Returns ------- out : ndarray, same shape and type as input `ar` The input array with small connected components removed. Examples -------- >>> from skimage import morphology >>> a = np.array([[0, 0, 0, 1, 0], ... [1, 1, 1, 0, 0], ... [1, 1, 1, 0, 1]], bool) >>> b = morphology.remove_small_connected_components(a, 6) >>> b array([[False, False, False, False, False], [ True, True, True, False, False], [ True, True, True, False, False]], dtype=bool) >>> c = morphology.remove_small_connected_components(a, 7, connectivity=2) >>> c array([[False, False, False, True, False], [ True, True, True, False, False], [ True, True, True, False, False]], dtype=bool) >>> d = morphology.remove_small_connected_components(a, 6, in_place=True) >>> d is a True """ # Should use `issubdtype` for bool below, but there's a bug in numpy 1.7 if not (ar.dtype == bool or np.issubdtype(ar.dtype, np.integer)): raise TypeError("Only bool or integer image types are supported. " "Got %s." % ar.dtype) if in_place: out = ar else: out = ar.copy() if min_size == 0: # shortcut for efficiency return out if out.dtype == bool: selem = nd.generate_binary_structure(ar.ndim, connectivity) ccs = np.zeros_like(ar, dtype=np.int32) nd.label(ar, selem, output=ccs) else: ccs = out try: component_sizes = np.bincount(ccs.ravel()) except ValueError: raise ValueError("Negative value labels are not supported. Try " "relabeling the input with `scipy.ndimage.label` or " "`skimage.morphology.label`.") too_small = component_sizes < min_size too_small_mask = too_small[ccs] out[too_small_mask] = 0 return out scikit-image-0.9.3/skimage/morphology/selem.py000066400000000000000000000175251223313777300214110ustar00rootroot00000000000000""" :author: Damian Eads, 2009 :license: modified BSD """ import numpy as np def square(width, dtype=np.uint8): """ Generates a flat, square-shaped structuring element. Every pixel along the perimeter has a chessboard distance no greater than radius (radius=floor(width/2)) pixels. Parameters ---------- width : int The width and height of the square Other Parameters ---------------- dtype : data-type The data type of the structuring element. Returns ------- selem : ndarray A structuring element consisting only of ones, i.e. every pixel belongs to the neighborhood. """ return np.ones((width, width), dtype=dtype) def rectangle(width, height, dtype=np.uint8): """ Generates a flat, rectangular-shaped structuring element of a given width and height. Every pixel in the rectangle belongs to the neighboorhood. Parameters ---------- width : int The width of the rectangle height : int The height of the rectangle Other Parameters ---------------- dtype : data-type The data type of the structuring element. Returns ------- selem : ndarray A structuring element consisting only of ones, i.e. every pixel belongs to the neighborhood. """ return np.ones((width, height), dtype=dtype) def diamond(radius, dtype=np.uint8): """ Generates a flat, diamond-shaped structuring element of a given radius. A pixel is part of the neighborhood (i.e. labeled 1) if the city block/manhattan distance between it and the center of the neighborhood is no greater than radius. Parameters ---------- radius : int The radius of the diamond-shaped structuring element. Other Parameters ---------------- dtype : data-type The data type of the structuring element. Returns ------- selem : ndarray The structuring element where elements of the neighborhood are 1 and 0 otherwise. """ half = radius (I, J) = np.meshgrid(range(0, radius * 2 + 1), range(0, radius * 2 + 1)) s = np.abs(I - half) + np.abs(J - half) return np.array(s <= radius, dtype=dtype) def disk(radius, dtype=np.uint8): """ Generates a flat, disk-shaped structuring element of a given radius. A pixel is within the neighborhood if the euclidean distance between it and the origin is no greater than radius. Parameters ---------- radius : int The radius of the disk-shaped structuring element. Other Parameters ---------------- dtype : data-type The data type of the structuring element. Returns ------- selem : ndarray The structuring element where elements of the neighborhood are 1 and 0 otherwise. """ L = np.linspace(-radius, radius, 2 * radius + 1) (X, Y) = np.meshgrid(L, L) s = X**2 s += Y**2 return np.array(s <= radius * radius, dtype=dtype) def cube(width, dtype=np.uint8): """ Generates a cube-shaped structuring element (the 3D equivalent of a square). Every pixel along the perimeter has a chessboard distance no greater than radius (radius=floor(width/2)) pixels. Parameters ---------- width : int The width, height and depth of the cube Other Parameters ---------------- dtype : data-type The data type of the structuring element. Returns ------- selem : ndarray A structuring element consisting only of ones, i.e. every pixel belongs to the neighborhood. """ return np.ones((width, width, width), dtype=dtype) def octahedron(radius, dtype=np.uint8): """ Generates a octahedron-shaped structuring element of a given radius (the 3D equivalent of a diamond). A pixel is part of the neighborhood (i.e. labeled 1) if the city block/manhattan distance between it and the center of the neighborhood is no greater than radius. Parameters ---------- radius : int The radius of the octahedron-shaped structuring element. Other Parameters ---------------- dtype : data-type The data type of the structuring element. Returns ------- selem : ndarray The structuring element where elements of the neighborhood are 1 and 0 otherwise. """ # note that in contrast to diamond(), this method allows non-integer radii n = 2 * radius + 1 Z, Y, X = np.mgrid[-radius:radius:n*1j, -radius:radius:n*1j, -radius:radius:n*1j] s = np.abs(X) + np.abs(Y) + np.abs(Z) return np.array(s <= radius, dtype=dtype) def ball(radius, dtype=np.uint8): """ Generates a ball-shaped structuring element of a given radius (the 3D equivalent of a disk). A pixel is within the neighborhood if the euclidean distance between it and the origin is no greater than radius. Parameters ---------- radius : int The radius of the ball-shaped structuring element. Other Parameters ---------------- dtype : data-type The data type of the structuring element. Returns ------- selem : ndarray The structuring element where elements of the neighborhood are 1 and 0 otherwise. """ n = 2 * radius + 1 Z, Y, X = np.mgrid[-radius:radius:n*1j, -radius:radius:n*1j, -radius:radius:n*1j] s = X**2 + Y**2 + Z**2 return np.array(s <= radius * radius, dtype=dtype) def octagon(m, n, dtype=np.uint8): """ Generates an octagon shaped structuring element with a given size of horizontal and vertical sides and a given height or width of slanted sides. The slanted sides are 45 or 135 degrees to the horizontal axis and hence the widths and heights are equal. Parameters ---------- m : int The size of the horizontal and vertical sides. n : int The height or width of the slanted sides. Other Parameters ---------------- dtype : data-type The data type of the structuring element. Returns ------- selem : ndarray The structuring element where elements of the neighborhood are 1 and 0 otherwise. """ from . import convex_hull_image selem = np.zeros((m + 2*n, m + 2*n)) selem[0, n] = 1 selem[n, 0] = 1 selem[0, m + n - 1] = 1 selem[m + n - 1, 0] = 1 selem[-1, n] = 1 selem[n, -1] = 1 selem[-1, m + n - 1] = 1 selem[m + n - 1, -1] = 1 selem = convex_hull_image(selem).astype(dtype) return selem def star(a, dtype=np.uint8): """ Generates a star shaped structuring element that has 8 vertices and is an overlap of square of size `2*a + 1` with its 45 degree rotated version. The slanted sides are 45 or 135 degrees to the horizontal axis. Parameters ---------- a : int Parameter deciding the size of the star structural element. The side of the square array returned is `2*a + 1 + 2*floor(a / 2)`. Other Parameters ---------------- dtype : data-type The data type of the structuring element. Returns ------- selem : ndarray The structuring element where elements of the neighborhood are 1 and 0 otherwise. """ from . import convex_hull_image if a == 1: bfilter = np.zeros((3, 3), dtype) bfilter[:] = 1 return bfilter m = 2 * a + 1 n = a // 2 selem_square = np.zeros((m + 2 * n, m + 2 * n)) selem_square[n: m + n, n: m + n] = 1 c = (m + 2 * n - 1) // 2 selem_rotated = np.zeros((m + 2 * n, m + 2 * n)) selem_rotated[0, c] = selem_rotated[-1, c] = selem_rotated[c, 0] = selem_rotated[c, -1] = 1 selem_rotated = convex_hull_image(selem_rotated).astype(int) selem = selem_square + selem_rotated selem[selem > 0] = 1 return selem.astype(dtype) scikit-image-0.9.3/skimage/morphology/setup.py000066400000000000000000000041151223313777300214330ustar00rootroot00000000000000#!/usr/bin/env python import os from skimage._build import cython base_path = os.path.abspath(os.path.dirname(__file__)) def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs config = Configuration('morphology', parent_package, top_path) config.add_data_dir('tests') cython(['ccomp.pyx'], working_path=base_path) cython(['cmorph.pyx'], working_path=base_path) cython(['_watershed.pyx'], working_path=base_path) cython(['_skeletonize_cy.pyx'], working_path=base_path) cython(['_pnpoly.pyx'], working_path=base_path) cython(['_convex_hull.pyx'], working_path=base_path) cython(['_greyreconstruct.pyx'], working_path=base_path) config.add_extension('ccomp', sources=['ccomp.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('cmorph', sources=['cmorph.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_watershed', sources=['_watershed.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_skeletonize_cy', sources=['_skeletonize_cy.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_pnpoly', sources=['_pnpoly.c'], include_dirs=[get_numpy_include_dirs(), '../_shared']) config.add_extension('_convex_hull', sources=['_convex_hull.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_greyreconstruct', sources=['_greyreconstruct.c'], include_dirs=[get_numpy_include_dirs()]) return config if __name__ == '__main__': from numpy.distutils.core import setup setup(maintainer='scikit-image Developers', author='Damian Eads', maintainer_email='scikit-image@googlegroups.com', description='Morphology Wrapper', url='https://github.com/scikit-image/scikit-image', license='SciPy License (BSD Style)', **(configuration(top_path='').todict()) ) scikit-image-0.9.3/skimage/morphology/tests/000077500000000000000000000000001223313777300210625ustar00rootroot00000000000000scikit-image-0.9.3/skimage/morphology/tests/test_binary.py000066400000000000000000000040451223313777300237620ustar00rootroot00000000000000import numpy as np from numpy import testing from skimage import data, color from skimage.util import img_as_bool from skimage.morphology import binary, grey, selem lena = color.rgb2gray(data.lena()) bw_lena = lena > 100 def test_non_square_image(): strel = selem.square(3) binary_res = binary.binary_erosion(bw_lena[:100, :200], strel) grey_res = img_as_bool(grey.erosion(bw_lena[:100, :200], strel)) testing.assert_array_equal(binary_res, grey_res) def test_binary_erosion(): strel = selem.square(3) binary_res = binary.binary_erosion(bw_lena, strel) grey_res = img_as_bool(grey.erosion(bw_lena, strel)) testing.assert_array_equal(binary_res, grey_res) def test_binary_dilation(): strel = selem.square(3) binary_res = binary.binary_dilation(bw_lena, strel) grey_res = img_as_bool(grey.dilation(bw_lena, strel)) testing.assert_array_equal(binary_res, grey_res) def test_binary_closing(): strel = selem.square(3) binary_res = binary.binary_closing(bw_lena, strel) grey_res = img_as_bool(grey.closing(bw_lena, strel)) testing.assert_array_equal(binary_res, grey_res) def test_binary_opening(): strel = selem.square(3) binary_res = binary.binary_opening(bw_lena, strel) grey_res = img_as_bool(grey.opening(bw_lena, strel)) testing.assert_array_equal(binary_res, grey_res) def test_selem_overflow(): strel = np.ones((17, 17), dtype=np.uint8) img = np.zeros((20, 20)) img[2:19, 2:19] = 1 binary_res = binary.binary_erosion(img, strel) grey_res = img_as_bool(grey.erosion(img, strel)) testing.assert_array_equal(binary_res, grey_res) def test_out_argument(): for func in (binary.binary_erosion, binary.binary_dilation): strel = np.ones((3, 3), dtype=np.uint8) img = np.ones((10, 10)) out = np.zeros_like(img) out_saved = out.copy() func(img, strel, out=out) testing.assert_(np.any(out != out_saved)) testing.assert_array_equal(out, func(img, strel)) if __name__ == '__main__': testing.run_module_suite() scikit-image-0.9.3/skimage/morphology/tests/test_ccomp.py000066400000000000000000000055721223313777300236050ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal, run_module_suite from skimage.morphology import label class TestConnectedComponents: def setup(self): self.x = np.array([[0, 0, 3, 2, 1, 9], [0, 1, 1, 9, 2, 9], [0, 0, 1, 9, 9, 9], [3, 1, 1, 5, 3, 0]]) self.labels = np.array([[0, 0, 1, 2, 3, 4], [0, 5, 5, 4, 2, 4], [0, 0, 5, 4, 4, 4], [6, 5, 5, 7, 8, 9]]) def test_basic(self): assert_array_equal(label(self.x), self.labels) # Make sure data wasn't modified assert self.x[0, 2] == 3 def test_random(self): x = (np.random.random((20, 30)) * 5).astype(np.int) labels = label(x) n = labels.max() for i in range(n): values = x[labels == i] assert np.all(values == values[0]) def test_diag(self): x = np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0]]) assert_array_equal(label(x), x) def test_4_vs_8(self): x = np.array([[0, 1], [1, 0]], dtype=int) assert_array_equal(label(x, 4), [[0, 1], [2, 3]]) assert_array_equal(label(x, 8), [[0, 1], [1, 0]]) def test_background(self): x = np.array([[1, 0, 0], [1, 1, 5], [0, 0, 0]]) assert_array_equal(label(x), [[0, 1, 1], [0, 0, 2], [3, 3, 3]]) assert_array_equal(label(x, background=0), [[0, -1, -1], [0, 0, 1], [-1, -1, -1]]) def test_background_two_regions(self): x = np.array([[0, 0, 6], [0, 0, 6], [5, 5, 5]]) assert_array_equal(label(x, background=0), [[-1, -1, 0], [-1, -1, 0], [ 1, 1, 1]]) def test_background_one_region_center(self): x = np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]]) assert_array_equal(label(x, neighbors=4, background=0), [[-1, -1, -1], [-1, 0, -1], [-1, -1, -1]]) def test_return_num(self): x = np.array([[1, 0, 6], [0, 0, 6], [5, 5, 5]]) assert_array_equal(label(x, return_num=True)[1], 4) assert_array_equal(label(x, background=0, return_num=True)[1], 3) if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/morphology/tests/test_convex_hull.py000066400000000000000000000074621223313777300250320ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal, assert_raises from numpy.testing.decorators import skipif from skimage.morphology import convex_hull_image, convex_hull_object from skimage.morphology._convex_hull import possible_hull try: import scipy.spatial scipy_spatial = True except ImportError: scipy_spatial = False @skipif(not scipy_spatial) def test_basic(): image = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool) expected = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool) assert_array_equal(convex_hull_image(image), expected) @skipif(not scipy_spatial) def test_pathological_qhull_example(): image = np.array( [[0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1], [1, 1, 1, 0, 0, 0, 0]], dtype=bool) expected = np.array( [[0, 0, 0, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 0, 0, 0]], dtype=bool) assert_array_equal(convex_hull_image(image), expected) @skipif(not scipy_spatial) def test_possible_hull(): image = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.uint8) expected = np.array([[1, 4], [2, 3], [3, 2], [4, 1], [4, 1], [3, 2], [2, 3], [1, 4], [2, 5], [3, 6], [4, 7], [2, 5], [3, 6], [4, 7], [4, 2], [4, 3], [4, 4], [4, 5], [4, 6]]) ph = possible_hull(image) assert_array_equal(ph, expected) @skipif(not scipy_spatial) def test_object(): image = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 0, 0, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 1, 0], [1, 0, 0, 0, 0, 0, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool) expected4 = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 0, 0, 1, 0, 1], [1, 1, 1, 0, 0, 0, 0, 1, 0], [1, 1, 0, 0, 0, 0, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool) assert_array_equal(convex_hull_object(image, 4), expected4) expected8 = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 1, 0, 0, 0, 1, 1, 1], [1, 1, 0, 0, 0, 0, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool) assert_array_equal(convex_hull_object(image, 8), expected8) assert_raises(ValueError, convex_hull_object, image, 7) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/morphology/tests/test_grey.py000066400000000000000000000122451223313777300234450ustar00rootroot00000000000000import os.path import numpy as np from numpy import testing import skimage from skimage import data_dir from skimage.util import img_as_bool from skimage.morphology import grey, selem lena = np.load(os.path.join(data_dir, 'lena_GRAY_U8.npy')) bw_lena = lena > 100 class TestMorphology(): def morph_worker(self, img, fn, morph_func, strel_func): matlab_results = np.load(os.path.join(data_dir, fn)) k = 0 for arrname in sorted(matlab_results): expected_result = matlab_results[arrname] mask = strel_func(k) actual_result = morph_func(lena, mask) testing.assert_equal(expected_result, actual_result) k = k + 1 def test_erode_diamond(self): self.morph_worker(lena, "diamond-erode-matlab-output.npz", grey.erosion, selem.diamond) def test_dilate_diamond(self): self.morph_worker(lena, "diamond-dilate-matlab-output.npz", grey.dilation, selem.diamond) def test_open_diamond(self): self.morph_worker(lena, "diamond-open-matlab-output.npz", grey.opening, selem.diamond) def test_close_diamond(self): self.morph_worker(lena, "diamond-close-matlab-output.npz", grey.closing, selem.diamond) def test_tophat_diamond(self): self.morph_worker(lena, "diamond-tophat-matlab-output.npz", grey.white_tophat, selem.diamond) def test_bothat_diamond(self): self.morph_worker(lena, "diamond-bothat-matlab-output.npz", grey.black_tophat, selem.diamond) def test_erode_disk(self): self.morph_worker(lena, "disk-erode-matlab-output.npz", grey.erosion, selem.disk) def test_dilate_disk(self): self.morph_worker(lena, "disk-dilate-matlab-output.npz", grey.dilation, selem.disk) def test_open_disk(self): self.morph_worker(lena, "disk-open-matlab-output.npz", grey.opening, selem.disk) def test_close_disk(self): self.morph_worker(lena, "disk-close-matlab-output.npz", grey.closing, selem.disk) class TestEccentricStructuringElements(): def setUp(self): self.black_pixel = 255 * np.ones((4, 4), dtype=np.uint8) self.black_pixel[1, 1] = 0 self.white_pixel = 255 - self.black_pixel self.selems = [selem.square(2), selem.rectangle(2, 2), selem.rectangle(2, 1), selem.rectangle(1, 2)] def test_dilate_erode_symmetry(self): for s in self.selems: c = grey.erosion(self.black_pixel, s) d = grey.dilation(self.white_pixel, s) assert np.all(c == (255 - d)) def test_open_black_pixel(self): for s in self.selems: grey_open = grey.opening(self.black_pixel, s) assert np.all(grey_open == self.black_pixel) def test_close_white_pixel(self): for s in self.selems: grey_close = grey.closing(self.white_pixel, s) assert np.all(grey_close == self.white_pixel) def test_open_white_pixel(self): for s in self.selems: assert np.all(grey.opening(self.white_pixel, s) == 0) def test_close_black_pixel(self): for s in self.selems: assert np.all(grey.closing(self.black_pixel, s) == 255) def test_white_tophat_white_pixel(self): for s in self.selems: tophat = grey.white_tophat(self.white_pixel, s) assert np.all(tophat == self.white_pixel) def test_black_tophat_black_pixel(self): for s in self.selems: tophat = grey.black_tophat(self.black_pixel, s) assert np.all(tophat == (255 - self.black_pixel)) def test_white_tophat_black_pixel(self): for s in self.selems: tophat = grey.white_tophat(self.black_pixel, s) assert np.all(tophat == 0) def test_black_tophat_white_pixel(self): for s in self.selems: tophat = grey.black_tophat(self.white_pixel, s) assert np.all(tophat == 0) class TestDTypes(): def setUp(self): k = 5 arrname = '%03i' % k self.disk = selem.disk(k) fname_opening = os.path.join(data_dir, "disk-open-matlab-output.npz") self.expected_opening = np.load(fname_opening)[arrname] fname_closing = os.path.join(data_dir, "disk-close-matlab-output.npz") self.expected_closing = np.load(fname_closing)[arrname] def _test_image(self, image): result_opening = grey.opening(image, self.disk) testing.assert_equal(result_opening, self.expected_opening) result_closing = grey.closing(image, self.disk) testing.assert_equal(result_closing, self.expected_closing) def test_float(self): image = skimage.img_as_float(lena) self._test_image(image) @testing.decorators.skipif(True) def test_int(self): image = skimage.img_as_int(lena) self._test_image(image) def test_uint(self): image = skimage.img_as_uint(lena) self._test_image(image) if __name__ == '__main__': testing.run_module_suite() scikit-image-0.9.3/skimage/morphology/tests/test_misc.py000066400000000000000000000045441223313777300234350ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal, assert_equal, assert_raises from skimage.morphology import remove_small_objects test_image = np.array([[0, 0, 0, 1, 0], [1, 1, 1, 0, 0], [1, 1, 1, 0, 1]], bool) def test_one_connectivity(): expected = np.array([[0, 0, 0, 0, 0], [1, 1, 1, 0, 0], [1, 1, 1, 0, 0]], bool) observed = remove_small_objects(test_image, min_size=6) assert_array_equal(observed, expected) def test_two_connectivity(): expected = np.array([[0, 0, 0, 1, 0], [1, 1, 1, 0, 0], [1, 1, 1, 0, 0]], bool) observed = remove_small_objects(test_image, min_size=7, connectivity=2) assert_array_equal(observed, expected) def test_in_place(): observed = remove_small_objects(test_image, min_size=6, in_place=True) assert_equal(observed is test_image, True, "remove_small_objects in_place argument failed.") def test_labeled_image(): labeled_image = np.array([[2, 2, 2, 0, 1], [2, 2, 2, 0, 1], [2, 0, 0, 0, 0], [0, 0, 3, 3, 3]], dtype=int) expected = np.array([[2, 2, 2, 0, 0], [2, 2, 2, 0, 0], [2, 0, 0, 0, 0], [0, 0, 3, 3, 3]], dtype=int) observed = remove_small_objects(labeled_image, min_size=3) assert_array_equal(observed, expected) def test_uint_image(): labeled_image = np.array([[2, 2, 2, 0, 1], [2, 2, 2, 0, 1], [2, 0, 0, 0, 0], [0, 0, 3, 3, 3]], dtype=np.uint8) expected = np.array([[2, 2, 2, 0, 0], [2, 2, 2, 0, 0], [2, 0, 0, 0, 0], [0, 0, 3, 3, 3]], dtype=np.uint8) observed = remove_small_objects(labeled_image, min_size=3) assert_array_equal(observed, expected) def test_float_input(): float_test = np.random.rand(5, 5) assert_raises(TypeError, remove_small_objects, float_test) def test_negative_input(): negative_int = np.random.randint(-4, -1, size=(5, 5)) assert_raises(ValueError, remove_small_objects, negative_int) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/morphology/tests/test_pnpoly.py000066400000000000000000000022571223313777300240220ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal from skimage.morphology._pnpoly import points_inside_poly, \ grid_points_inside_poly class test_npnpoly(): def test_square(self): v = np.array([[0, 0], [0, 1], [1, 1], [1, 0]]) assert(points_inside_poly([[0.5, 0.5]], v)[0]) assert(not points_inside_poly([[-0.1, 0.1]], v)[0]) def test_triangle(self): v = np.array([[0, 0], [1, 0], [0.5, 0.75]]) assert(points_inside_poly([[0.5, 0.7]], v)[0]) assert(not points_inside_poly([[0.5, 0.76]], v)[0]) assert(not points_inside_poly([[0.7, 0.5]], v)[0]) def test_type(self): assert(points_inside_poly([[0, 0]], [[0, 0]]).dtype == np.bool) def test_grid_points_inside_poly(): v = np.array([[0, 0], [5, 0], [5, 5]]) expected = np.tril(np.ones((5, 5), dtype=bool)) assert_array_equal(grid_points_inside_poly((5, 5), v), expected) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/morphology/tests/test_reconstruction.py000066400000000000000000000054521223313777300255620ustar00rootroot00000000000000""" These tests are originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky """ import numpy as np from numpy.testing import assert_array_almost_equal as assert_close from skimage.morphology.greyreconstruct import reconstruction def test_zeros(): """Test reconstruction with image and mask of zeros""" assert_close(reconstruction(np.zeros((5, 7)), np.zeros((5, 7))), 0) def test_image_equals_mask(): """Test reconstruction where the image and mask are the same""" assert_close(reconstruction(np.ones((7, 5)), np.ones((7, 5))), 1) def test_image_less_than_mask(): """Test reconstruction where the image is uniform and less than mask""" image = np.ones((5, 5)) mask = np.ones((5, 5)) * 2 assert_close(reconstruction(image, mask), 1) def test_one_image_peak(): """Test reconstruction with one peak pixel""" image = np.ones((5, 5)) image[2, 2] = 2 mask = np.ones((5, 5)) * 3 assert_close(reconstruction(image, mask), 2) def test_two_image_peaks(): """Test reconstruction with two peak pixels isolated by the mask""" image = np.array([[1, 1, 1, 1, 1, 1, 1, 1], [1, 2, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 3, 1], [1, 1, 1, 1, 1, 1, 1, 1]]) mask = np.array([[4, 4, 4, 1, 1, 1, 1, 1], [4, 4, 4, 1, 1, 1, 1, 1], [4, 4, 4, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 4, 4, 4], [1, 1, 1, 1, 1, 4, 4, 4], [1, 1, 1, 1, 1, 4, 4, 4]]) expected = np.array([[2, 2, 2, 1, 1, 1, 1, 1], [2, 2, 2, 1, 1, 1, 1, 1], [2, 2, 2, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 3, 3, 3], [1, 1, 1, 1, 1, 3, 3, 3], [1, 1, 1, 1, 1, 3, 3, 3]]) assert_close(reconstruction(image, mask), expected) def test_zero_image_one_mask(): """Test reconstruction with an image of all zeros and a mask that's not""" result = reconstruction(np.zeros((10, 10)), np.ones((10, 10))) assert_close(result, 0) def test_fill_hole(): """Test reconstruction by erosion, which should fill holes in mask.""" seed = np.array([0, 8, 8, 8, 8, 8, 8, 8, 8, 0]) mask = np.array([0, 3, 6, 2, 1, 1, 1, 4, 2, 0]) result = reconstruction(seed, mask, method='erosion') assert_close(result, np.array([0, 3, 6, 4, 4, 4, 4, 4, 2, 0])) if __name__ == '__main__': from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/morphology/tests/test_selem.py000066400000000000000000000114621223313777300236040ustar00rootroot00000000000000# Author: Damian Eads import os.path import numpy as np from numpy.testing import * from skimage import data_dir from skimage.io import * from skimage import data_dir from skimage.morphology import selem class TestSElem(): def test_square_selem(self): for k in range(0, 5): actual_mask = selem.square(k) expected_mask = np.ones((k, k), dtype='uint8') assert_equal(expected_mask, actual_mask) def test_rectangle_selem(self): for i in range(0, 5): for j in range(0, 5): actual_mask = selem.rectangle(i, j) expected_mask = np.ones((i, j), dtype='uint8') assert_equal(expected_mask, actual_mask) def strel_worker(self, fn, func): matlab_masks = np.load(os.path.join(data_dir, fn)) k = 0 for arrname in sorted(matlab_masks): expected_mask = matlab_masks[arrname] actual_mask = func(k) if (expected_mask.shape == (1,)): expected_mask = expected_mask[:, np.newaxis] assert_equal(expected_mask, actual_mask) k = k + 1 def strel_worker_3d(self, fn, func): matlab_masks = np.load(os.path.join(data_dir, fn)) k = 0 for arrname in sorted(matlab_masks): expected_mask = matlab_masks[arrname] actual_mask = func(k) if (expected_mask.shape == (1,)): expected_mask = expected_mask[:, np.newaxis] # Test center slice for each dimension. This gives a good # indication of validity without the need for a 3D reference # mask. c = int(expected_mask.shape[0]/2) assert_equal(expected_mask, actual_mask[c,:,:]) assert_equal(expected_mask, actual_mask[:,c,:]) assert_equal(expected_mask, actual_mask[:,:,c]) k = k + 1 def test_selem_disk(self): self.strel_worker("disk-matlab-output.npz", selem.disk) def test_selem_diamond(self): self.strel_worker("diamond-matlab-output.npz", selem.diamond) def test_selem_ball(self): self.strel_worker_3d("disk-matlab-output.npz", selem.ball) def test_selem_octahedron(self): self.strel_worker_3d("diamond-matlab-output.npz", selem.octahedron) def test_selem_octagon(self): expected_mask1 = np.array([[0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0]], dtype=np.uint8) actual_mask1 = selem.octagon(5, 3) expected_mask2 = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]], dtype=np.uint8) actual_mask2 = selem.octagon(1, 1) assert_equal(expected_mask1, actual_mask1) assert_equal(expected_mask2, actual_mask2) def test_selem_star(self): expected_mask1 = np.array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]], dtype=np.uint8) actual_mask1 = selem.star(4) expected_mask2 = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]], dtype=np.uint8) actual_mask2 = selem.star(1) assert_equal(expected_mask1, actual_mask1) assert_equal(expected_mask2, actual_mask2) if __name__ == '__main__': np.testing.run_module_suite() scikit-image-0.9.3/skimage/morphology/tests/test_skeletonize.py000066400000000000000000000145671223313777300250440ustar00rootroot00000000000000import numpy as np from skimage.morphology import skeletonize, medial_axis import numpy.testing from skimage import draw from scipy.ndimage import correlate from skimage.io import imread from skimage import data_dir import os.path class TestSkeletonize(): def test_skeletonize_no_foreground(self): im = np.zeros((5, 5)) result = skeletonize(im) numpy.testing.assert_array_equal(result, np.zeros((5, 5))) def test_skeletonize_wrong_dim1(self): im = np.zeros((5)) numpy.testing.assert_raises(ValueError, skeletonize, im) def test_skeletonize_wrong_dim2(self): im = np.zeros((5, 5, 5)) numpy.testing.assert_raises(ValueError, skeletonize, im) def test_skeletonize_not_binary(self): im = np.zeros((5, 5)) im[0, 0] = 1 im[0, 1] = 2 numpy.testing.assert_raises(ValueError, skeletonize, im) def test_skeletonize_unexpected_value(self): im = np.zeros((5, 5)) im[0, 0] = 2 numpy.testing.assert_raises(ValueError, skeletonize, im) def test_skeletonize_all_foreground(self): im = np.ones((3, 4)) skeletonize(im) def test_skeletonize_single_point(self): im = np.zeros((5, 5), np.uint8) im[3, 3] = 1 result = skeletonize(im) numpy.testing.assert_array_equal(result, im) def test_skeletonize_already_thinned(self): im = np.zeros((5, 5), np.uint8) im[3, 1:-1] = 1 im[2, -1] = 1 im[4, 0] = 1 result = skeletonize(im) numpy.testing.assert_array_equal(result, im) def test_skeletonize_output(self): im = imread(os.path.join(data_dir, "bw_text.png"), as_grey=True) # make black the foreground im = (im == 0) result = skeletonize(im) expected = np.load(os.path.join(data_dir, "bw_text_skeleton.npy")) numpy.testing.assert_array_equal(result, expected) def test_skeletonize_num_neighbours(self): # an empty image image = np.zeros((300, 300)) # foreground object 1 image[10:-10, 10:100] = 1 image[-100:-10, 10:-10] = 1 image[10:-10, -100:-10] = 1 # foreground object 2 rs, cs = draw.line(250, 150, 10, 280) for i in range(10): image[rs + i, cs] = 1 rs, cs = draw.line(10, 150, 250, 280) for i in range(20): image[rs + i, cs] = 1 # foreground object 3 ir, ic = np.indices(image.shape) circle1 = (ic - 135)**2 + (ir - 150)**2 < 30**2 circle2 = (ic - 135)**2 + (ir - 150)**2 < 20**2 image[circle1] = 1 image[circle2] = 0 result = skeletonize(image) # there should never be a 2x2 block of foreground pixels in a skeleton mask = np.array([[1, 1], [1, 1]], np.uint8) blocks = correlate(result, mask, mode='constant') assert not numpy.any(blocks == 4) def test_lut_fix(self): im = np.zeros((6, 6), np.uint8) im[1, 2] = 1 im[2, 2] = 1 im[2, 3] = 1 im[3, 3] = 1 im[3, 4] = 1 im[4, 4] = 1 im[4, 5] = 1 result = skeletonize(im) expected = np.array([[0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0]], dtype=np.uint8) assert np.all(result == expected) class TestMedialAxis(): def test_00_00_zeros(self): '''Test skeletonize on an array of all zeros''' result = medial_axis(np.zeros((10, 10), bool)) assert np.all(result == False) def test_00_01_zeros_masked(self): '''Test skeletonize on an array that is completely masked''' result = medial_axis(np.zeros((10, 10), bool), np.zeros((10, 10), bool)) assert np.all(result == False) def test_01_01_rectangle(self): '''Test skeletonize on a rectangle''' image = np.zeros((9, 15), bool) image[1:-1, 1:-1] = True # # The result should be four diagonals from the # corners, meeting in a horizontal line # expected = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], bool) result = medial_axis(image) assert np.all(result == expected) result, distance = medial_axis(image, return_distance=True) assert distance.max() == 4 def test_01_02_hole(self): '''Test skeletonize on a rectangle with a hole in the middle''' image = np.zeros((9, 15), bool) image[1:-1, 1:-1] = True image[4, 4:-4] = False expected = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], bool) result = medial_axis(image) assert np.all(result == expected) def test_narrow_image(self): """Test skeletonize on a 1-pixel thin strip""" image = np.zeros((1, 5), bool) image[:, 1:-1] = True result = medial_axis(image) assert np.all(result == image) if __name__ == '__main__': np.testing.run_module_suite() scikit-image-0.9.3/skimage/morphology/tests/test_watershed.py000066400000000000000000000457771223313777300245050ustar00rootroot00000000000000"""test_watershed.py - tests the watershed function Originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky """ #Portions of this test were taken from scipy's watershed test in test_ndimage.py # # Copyright (C) 2003-2005 Peter J. Verveer # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # # 3. The name of the author may not be used to endorse or promote # products derived from this software without specific prior # written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import math import unittest import numpy as np import scipy.ndimage from skimage.morphology.watershed import watershed, _slow_watershed eps = 1e-12 def diff(a, b): if not isinstance(a, np.ndarray): a = np.asarray(a) if not isinstance(b, np.ndarray): b = np.asarray(b) if (0 in a.shape) and (0 in b.shape): return 0.0 b[a == 0] = 0 if (a.dtype in [np.complex64, np.complex128] or b.dtype in [np.complex64, np.complex128]): a = np.asarray(a, np.complex128) b = np.asarray(b, np.complex128) t = ((a.real - b.real)**2).sum() + ((a.imag - b.imag)**2).sum() else: a = np.asarray(a) a = a.astype(np.float64) b = np.asarray(b) b = b.astype(np.float64) t = ((a - b)**2).sum() return math.sqrt(t) class TestWatershed(unittest.TestCase): eight = np.ones((3, 3), bool) def test_watershed01(self): "watershed 1" data = np.array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 0], [0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0], [0, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]], np.uint8) markers = np.array([[ -1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 1, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0]], np.int8) out = watershed(data, markers, self.eight) expected = np.array([[-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, 1, 1, 1, 1, 1, -1], [-1, 1, 1, 1, 1, 1, -1], [-1, 1, 1, 1, 1, 1, -1], [-1, 1, 1, 1, 1, 1, -1], [-1, 1, 1, 1, 1, 1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1]]) error = diff(expected, out) assert error < eps out = _slow_watershed(data, markers, 8) error = diff(expected, out) assert error < eps def test_watershed02(self): "watershed 2" data = np.array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 0], [0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0], [0, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]], np.uint8) markers = np.array([[-1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]], np.int8) out = watershed(data, markers) error = diff([[-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, 1, 1, 1, -1, -1], [-1, 1, 1, 1, 1, 1, -1], [-1, 1, 1, 1, 1, 1, -1], [-1, 1, 1, 1, 1, 1, -1], [-1, -1, 1, 1, 1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1]], out) self.failUnless(error < eps) def test_watershed03(self): "watershed 3" data = np.array([[0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 0], [0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0], [0, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]], np.uint8) markers = np.array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 2, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, -1]], np.int8) out = watershed(data, markers) error = diff([[-1, -1, -1, -1, -1, -1, -1], [-1, 0, 2, 0, 3, 0, -1], [-1, 2, 2, 0, 3, 3, -1], [-1, 2, 2, 0, 3, 3, -1], [-1, 2, 2, 0, 3, 3, -1], [-1, 0, 2, 0, 3, 0, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1]], out) self.failUnless(error < eps) def test_watershed04(self): "watershed 4" data = np.array([[0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 0], [0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0], [0, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]], np.uint8) markers = np.array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 2, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, -1]], np.int8) out = watershed(data, markers, self.eight) error = diff([[-1, -1, -1, -1, -1, -1, -1], [-1, 2, 2, 0, 3, 3, -1], [-1, 2, 2, 0, 3, 3, -1], [-1, 2, 2, 0, 3, 3, -1], [-1, 2, 2, 0, 3, 3, -1], [-1, 2, 2, 0, 3, 3, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1]], out) self.failUnless(error < eps) def test_watershed05(self): "watershed 5" data = np.array([[0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 0], [0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0], [0, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]], np.uint8) markers = np.array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 0, 2, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, -1]], np.int8) out = watershed(data, markers, self.eight) error = diff([[-1, -1, -1, -1, -1, -1, -1], [-1, 3, 3, 0, 2, 2, -1], [-1, 3, 3, 0, 2, 2, -1], [-1, 3, 3, 0, 2, 2, -1], [-1, 3, 3, 0, 2, 2, -1], [-1, 3, 3, 0, 2, 2, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1]], out) self.failUnless(error < eps) def test_watershed06(self): "watershed 6" data = np.array([[0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0], [0, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]], np.uint8) markers = np.array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [-1, 0, 0, 0, 0, 0, 0]], np.int8) out = watershed(data, markers, self.eight) error = diff([[-1, 1, 1, 1, 1, 1, -1], [-1, 1, 1, 1, 1, 1, -1], [-1, 1, 1, 1, 1, 1, -1], [-1, 1, 1, 1, 1, 1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1]], out) self.failUnless(error < eps) def test_watershed07(self): "A regression test of a competitive case that failed" data = np.array([[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], [255, 255, 255, 255, 255, 204, 204, 204, 204, 204, 204, 255, 255, 255, 255, 255], [255, 255, 255, 204, 204, 183, 153, 153, 153, 153, 183, 204, 204, 255, 255, 255], [255, 255, 204, 183, 153, 141, 111, 103, 103, 111, 141, 153, 183, 204, 255, 255], [255, 255, 204, 153, 111, 94, 72, 52, 52, 72, 94, 111, 153, 204, 255, 255], [255, 255, 204, 153, 111, 72, 39, 1, 1, 39, 72, 111, 153, 204, 255, 255], [255, 255, 204, 183, 141, 111, 72, 39, 39, 72, 111, 141, 183, 204, 255, 255], [255, 255, 255, 204, 183, 141, 111, 72, 72, 111, 141, 183, 204, 255, 255, 255], [255, 255, 255, 255, 204, 183, 141, 94, 94, 141, 183, 204, 255, 255, 255, 255], [255, 255, 255, 255, 255, 204, 153, 103, 103, 153, 204, 255, 255, 255, 255, 255], [255, 255, 255, 255, 204, 183, 141, 94, 94, 141, 183, 204, 255, 255, 255, 255], [255, 255, 255, 204, 183, 141, 111, 72, 72, 111, 141, 183, 204, 255, 255, 255], [255, 255, 204, 183, 141, 111, 72, 39, 39, 72, 111, 141, 183, 204, 255, 255], [255, 255, 204, 153, 111, 72, 39, 1, 1, 39, 72, 111, 153, 204, 255, 255], [255, 255, 204, 153, 111, 94, 72, 52, 52, 72, 94, 111, 153, 204, 255, 255], [255, 255, 204, 183, 153, 141, 111, 103, 103, 111, 141, 153, 183, 204, 255, 255], [255, 255, 255, 204, 204, 183, 153, 153, 153, 153, 183, 204, 204, 255, 255, 255], [255, 255, 255, 255, 255, 204, 204, 204, 204, 204, 204, 255, 255, 255, 255, 255], [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]]) mask = (data != 255) markers = np.zeros(data.shape, int) markers[6, 7] = 1 markers[14, 7] = 2 out = watershed(data, markers, self.eight, mask=mask) # # The two objects should be the same size, except possibly for the # border region # size1 = np.sum(out == 1) size2 = np.sum(out == 2) self.assertTrue(abs(size1 - size2) <= 6) def test_watershed08(self): "The border pixels + an edge are all the same value" data = np.array([[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], [255, 255, 255, 255, 255, 204, 204, 204, 204, 204, 204, 255, 255, 255, 255, 255], [255, 255, 255, 204, 204, 183, 153, 153, 153, 153, 183, 204, 204, 255, 255, 255], [255, 255, 204, 183, 153, 141, 111, 103, 103, 111, 141, 153, 183, 204, 255, 255], [255, 255, 204, 153, 111, 94, 72, 52, 52, 72, 94, 111, 153, 204, 255, 255], [255, 255, 204, 153, 111, 72, 39, 1, 1, 39, 72, 111, 153, 204, 255, 255], [255, 255, 204, 183, 141, 111, 72, 39, 39, 72, 111, 141, 183, 204, 255, 255], [255, 255, 255, 204, 183, 141, 111, 72, 72, 111, 141, 183, 204, 255, 255, 255], [255, 255, 255, 255, 204, 183, 141, 94, 94, 141, 183, 204, 255, 255, 255, 255], [255, 255, 255, 255, 255, 204, 153, 141, 141, 153, 204, 255, 255, 255, 255, 255], [255, 255, 255, 255, 204, 183, 141, 94, 94, 141, 183, 204, 255, 255, 255, 255], [255, 255, 255, 204, 183, 141, 111, 72, 72, 111, 141, 183, 204, 255, 255, 255], [255, 255, 204, 183, 141, 111, 72, 39, 39, 72, 111, 141, 183, 204, 255, 255], [255, 255, 204, 153, 111, 72, 39, 1, 1, 39, 72, 111, 153, 204, 255, 255], [255, 255, 204, 153, 111, 94, 72, 52, 52, 72, 94, 111, 153, 204, 255, 255], [255, 255, 204, 183, 153, 141, 111, 103, 103, 111, 141, 153, 183, 204, 255, 255], [255, 255, 255, 204, 204, 183, 153, 153, 153, 153, 183, 204, 204, 255, 255, 255], [255, 255, 255, 255, 255, 204, 204, 204, 204, 204, 204, 255, 255, 255, 255, 255], [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]]) mask = (data != 255) markers = np.zeros(data.shape, int) markers[6, 7] = 1 markers[14, 7] = 2 out = watershed(data, markers, self.eight, mask=mask) # # The two objects should be the same size, except possibly for the # border region # size1 = np.sum(out == 1) size2 = np.sum(out == 2) self.assertTrue(abs(size1 - size2) <= 6) def test_watershed09(self): """Test on an image of reasonable size This is here both for timing (does it take forever?) and to ensure that the memory constraints are reasonable """ image = np.zeros((1000, 1000)) coords = np.random.uniform(0, 1000, (100, 2)).astype(int) markers = np.zeros((1000, 1000), int) idx = 1 for x, y in coords: image[x, y] = 1 markers[x, y] = idx idx += 1 image = scipy.ndimage.gaussian_filter(image, 4) watershed(image, markers, self.eight) scipy.ndimage.watershed_ift(image.astype(np.uint16), markers, self.eight) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/morphology/watershed.py000066400000000000000000000314541223313777300222670ustar00rootroot00000000000000"""watershed.py - watershed algorithm This module implements a watershed algorithm that apportions pixels into marked basins. The algorithm uses a priority queue to hold the pixels with the metric for the priority queue being pixel value, then the time of entry into the queue - this settles ties in favor of the closest marker. Some ideas taken from Soille, "Automated Basin Delineation from Digital Elevation Models Using Mathematical Morphology", Signal Processing 20 (1990) 171-182. The most important insight in the paper is that entry time onto the queue solves two problems: a pixel should be assigned to the neighbor with the largest gradient or, if there is no gradient, pixels on a plateau should be split between markers on opposite sides. Originally part of CellProfiler, code licensed under both GPL and BSD licenses. Website: http://www.cellprofiler.org Copyright (c) 2003-2009 Massachusetts Institute of Technology Copyright (c) 2009-2011 Broad Institute All rights reserved. Original author: Lee Kamentsky """ from _heapq import heappush, heappop import numpy as np import scipy.ndimage from ..filter import rank_order from .._shared.utils import deprecated from . import _watershed def watershed(image, markers, connectivity=None, offset=None, mask=None): """ Return a matrix labeled using the watershed segmentation algorithm Parameters ---------- image: ndarray (2-D, 3-D, ...) of integers Data array where the lowest value points are labeled first. markers: ndarray of the same shape as `image` An array marking the basins with the values to be assigned in the label matrix. Zero means not a marker. This array should be of an integer type. connectivity: ndarray, optional An array with the same number of dimensions as `image` whose non-zero elements indicate neighbors for connection. Following the scipy convention, default is a one-connected array of the dimension of the image. offset: array_like of shape image.ndim, optional offset of the connectivity (one offset per dimension) mask: ndarray of bools or 0s and 1s, optional Array of same shape as `image`. Only points at which mask == True will be labeled. Returns ------- out: ndarray A labeled matrix of the same type and shape as markers See also -------- skimage.segmentation.random_walker: random walker segmentation A segmentation algorithm based on anisotropic diffusion, usually slower than the watershed but with good results on noisy data and boundaries with holes. Notes ----- This function implements a watershed algorithm [1]_that apportions pixels into marked basins. The algorithm uses a priority queue to hold the pixels with the metric for the priority queue being pixel value, then the time of entry into the queue - this settles ties in favor of the closest marker. Some ideas taken from Soille, "Automated Basin Delineation from Digital Elevation Models Using Mathematical Morphology", Signal Processing 20 (1990) 171-182 The most important insight in the paper is that entry time onto the queue solves two problems: a pixel should be assigned to the neighbor with the largest gradient or, if there is no gradient, pixels on a plateau should be split between markers on opposite sides. This implementation converts all arguments to specific, lowest common denominator types, then passes these to a C algorithm. Markers can be determined manually, or automatically using for example the local minima of the gradient of the image, or the local maxima of the distance function to the background for separating overlapping objects (see example). References ---------- .. [1] http://en.wikipedia.org/wiki/Watershed_%28image_processing%29 .. [2] http://cmm.ensmp.fr/~beucher/wtshed.html Examples -------- The watershed algorithm is very useful to separate overlapping objects >>> # Generate an initial image with two overlapping circles >>> x, y = np.indices((80, 80)) >>> x1, y1, x2, y2 = 28, 28, 44, 52 >>> r1, r2 = 16, 20 >>> mask_circle1 = (x - x1)**2 + (y - y1)**2 < r1**2 >>> mask_circle2 = (x - x2)**2 + (y - y2)**2 < r2**2 >>> image = np.logical_or(mask_circle1, mask_circle2) >>> # Now we want to separate the two objects in image >>> # Generate the markers as local maxima of the distance >>> # to the background >>> from scipy import ndimage >>> distance = ndimage.distance_transform_edt(image) >>> from skimage.feature import peak_local_max >>> local_maxi = peak_local_max(distance, labels=image, ... footprint=np.ones((3, 3))) >>> markers = ndimage.label(local_maxi)[0] >>> labels = watershed(-distance, markers, mask=image) The algorithm works also for 3-D images, and can be used for example to separate overlapping spheres. """ if connectivity is None: c_connectivity = scipy.ndimage.generate_binary_structure(image.ndim, 1) else: c_connectivity = np.array(connectivity, bool) if c_connectivity.ndim != image.ndim: raise ValueError("Connectivity dimension must be same as image") if offset is None: if any([x % 2 == 0 for x in c_connectivity.shape]): raise ValueError("Connectivity array must have an unambiguous " "center") # # offset to center of connectivity array # offset = np.array(c_connectivity.shape) // 2 # pad the image, markers, and mask so that we can use the mask to # keep from running off the edges pads = offset def pad(im): new_im = np.zeros([i + 2 * p for i, p in zip(im.shape, pads)], im.dtype) new_im[[slice(p, -p, None) for p in pads]] = im return new_im if mask is not None: mask = pad(mask) else: mask = pad(np.ones(image.shape, bool)) image = pad(image) markers = pad(markers) c_image = rank_order(image)[0].astype(np.int32) c_markers = np.ascontiguousarray(markers, dtype=np.int32) if c_markers.ndim != c_image.ndim: raise ValueError("markers (ndim=%d) must have same # of dimensions " "as image (ndim=%d)" % (c_markers.ndim, c_image.ndim)) if c_markers.shape != c_image.shape: raise ValueError("image and markers must have the same shape") if mask is not None: c_mask = np.ascontiguousarray(mask, dtype=bool) if c_mask.ndim != c_markers.ndim: raise ValueError("mask must have same # of dimensions as image") if c_markers.shape != c_mask.shape: raise ValueError("mask must have same shape as image") c_markers[np.logical_not(mask)] = 0 else: c_mask = None c_output = c_markers.copy() # # We pass a connectivity array that pre-calculates the stride for each # neighbor. # # The result of this bit of code is an array with one row per # point to be considered. The first column is the pre-computed stride # and the second through last are the x,y...whatever offsets # (to do bounds checking). c = [] image_stride = np.array(image.strides) // image.itemsize for i in range(np.product(c_connectivity.shape)): multiplier = 1 offs = [] indexes = [] ignore = True for j in range(len(c_connectivity.shape)): idx = (i // multiplier) % c_connectivity.shape[j] off = idx - offset[j] if off: ignore = False offs.append(off) indexes.append(idx) multiplier *= c_connectivity.shape[j] if (not ignore) and c_connectivity.__getitem__(tuple(indexes)): stride = np.dot(image_stride, np.array(offs)) offs.insert(0, stride) c.append(offs) c = np.array(c, dtype=np.int32) pq, age = __heapify_markers(c_markers, c_image) pq = np.ascontiguousarray(pq, dtype=np.int32) if np.product(pq.shape) > 0: # If nothing is labeled, the output is empty and we don't have to # do anything c_output = c_output.flatten() if c_mask == None: c_mask = np.ones(c_image.shape, np.int8).flatten() else: c_mask = c_mask.astype(np.int8).flatten() _watershed.watershed(c_image.flatten(), pq, age, c, c_mask, c_output) c_output = c_output.reshape(c_image.shape)[[slice(1, -1, None)] * image.ndim] try: return c_output.astype(markers.dtype) except: return c_output # ---------------------- deprecated ------------------------------ # Deprecate slower pure-Python code, that we keep only for # pedagogical purposes def __heapify_markers(markers, image): """Create a priority queue heap with the markers on it""" stride = np.array(image.strides) // image.itemsize coords = np.argwhere(markers != 0) ncoords = coords.shape[0] if ncoords > 0: pixels = image[markers != 0] age = np.arange(ncoords) offset = np.zeros(coords.shape[0], int) for i in range(image.ndim): offset = offset + stride[i] * coords[:, i] pq = np.column_stack((pixels, age, offset, coords)) # pixels = top priority, age=second ordering = np.lexsort((age, pixels)) pq = pq[ordering, :] else: pq = np.zeros((0, markers.ndim + 3), int) return (pq, ncoords) def _slow_watershed(image, markers, connectivity=8, mask=None): """Return a matrix labeled using the watershed algorithm Use the `watershed` function for a faster execution. This pure Python function is solely for pedagogical purposes. Parameters ---------- image: 2-d ndarray of integers a two-dimensional matrix where the lowest value points are labeled first. markers: 2-d ndarray of integers a two-dimensional matrix marking the basins with the values to be assigned in the label matrix. Zero means not a marker. connectivity: {4, 8}, optional either 4 for four-connected or 8 (default) for eight-connected mask: 2-d ndarray of bools, optional don't label points in the mask Returns ------- out: ndarray A labeled matrix of the same type and shape as markers Notes ----- This function implements a watershed algorithm [1]_that apportions pixels into marked basins. The algorithm uses a priority queue to hold the pixels with the metric for the priority queue being pixel value, then the time of entry into the queue - this settles ties in favor of the closest marker. Some ideas taken from Soille, "Automated Basin Delineation from Digital Elevation Models Using Mathematical Morphology", Signal Processing 20 (1990) 171-182 The most important insight in the paper is that entry time onto the queue solves two problems: a pixel should be assigned to the neighbor with the largest gradient or, if there is no gradient, pixels on a plateau should be split between markers on opposite sides. This implementation converts all arguments to specific, lowest common denominator types, then passes these to a C algorithm. Markers can be determined manually, or automatically using for example the local minima of the gradient of the image, or the local maxima of the distance function to the background for separating overlapping objects. """ if connectivity not in (4, 8): raise ValueError("Connectivity was %d: it should be either \ four or eight" % (connectivity)) image = np.array(image) markers = np.array(markers) labels = markers.copy() max_x = markers.shape[0] max_y = markers.shape[1] if connectivity == 4: connect_increments = ((1, 0), (0, 1), (-1, 0), (0, -1)) else: connect_increments = ((1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)) pq, age = __heapify_markers(markers, image) pq = pq.tolist() # # The second step pops a value off of the queue, then labels and pushes # the neighbors # while len(pq): pix_value, pix_age, ignore, pix_x, pix_y = heappop(pq) pix_label = labels[pix_x, pix_y] for xi, yi in connect_increments: x = pix_x + xi y = pix_y + yi if x < 0 or y < 0 or x >= max_x or y >= max_y: continue if labels[x, y]: continue if mask is not None and not mask[x, y]: continue # label the pixel labels[x, y] = pix_label # put the pixel onto the queue heappush(pq, [image[x, y], age, 0, x, y]) age += 1 return labels scikit-image-0.9.3/skimage/scripts/000077500000000000000000000000001223313777300172105ustar00rootroot00000000000000scikit-image-0.9.3/skimage/scripts/__init__.py000066400000000000000000000000001223313777300213070ustar00rootroot00000000000000scikit-image-0.9.3/skimage/scripts/skivi000077500000000000000000000001511223313777300202600ustar00rootroot00000000000000#!/usr/bin/env python if __name__ == "__main__": from skimage.scripts import skivi skivi.main() scikit-image-0.9.3/skimage/scripts/skivi.py000066400000000000000000000004031223313777300207040ustar00rootroot00000000000000"""skimage viewer""" def main(): import skimage.io as io import sys if len(sys.argv) != 2: print("Usage: skivi ") sys.exit(-1) io.use_plugin('qt') io.imshow(io.imread(sys.argv[1]), fancy=True) io.show() scikit-image-0.9.3/skimage/segmentation/000077500000000000000000000000001223313777300202165ustar00rootroot00000000000000scikit-image-0.9.3/skimage/segmentation/__init__.py000066400000000000000000000012501223313777300223250ustar00rootroot00000000000000from .random_walker_segmentation import random_walker from ._felzenszwalb import felzenszwalb from .slic_superpixels import slic from ._quickshift import quickshift from .boundaries import find_boundaries, visualize_boundaries, mark_boundaries from ._clear_border import clear_border from ._join import join_segmentations, relabel_from_one, relabel_sequential __all__ = ['random_walker', 'felzenszwalb', 'slic', 'quickshift', 'find_boundaries', 'visualize_boundaries', 'mark_boundaries', 'clear_border', 'join_segmentations', 'relabel_from_one', 'relabel_sequential'] scikit-image-0.9.3/skimage/segmentation/_clear_border.py000066400000000000000000000040301223313777300233470ustar00rootroot00000000000000import numpy as np from scipy.ndimage import label def clear_border(image, buffer_size=0, bgval=0): """Clear objects connected to image border. The changes will be applied to the input image. Parameters ---------- image : (N, M) array Binary image. buffer_size : int, optional Define additional buffer around image border. bgval : float or int, optional Value for cleared objects. Returns ------- image : (N, M) array Cleared binary image. Examples -------- >>> import numpy as np >>> from skimage.segmentation import clear_border >>> image = np.array([[0, 0, 0, 0, 0, 0, 0, 1, 0], ... [0, 0, 0, 0, 1, 0, 0, 0, 0], ... [1, 0, 0, 1, 0, 1, 0, 0, 0], ... [0, 0, 1, 1, 1, 1, 1, 0, 0], ... [0, 1, 1, 1, 1, 1, 1, 1, 0], ... [0, 0, 0, 0, 0, 0, 0, 0, 0]]) >>> clear_border(image) array([[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]]) """ rows, cols = image.shape if buffer_size >= rows or buffer_size >= cols: raise ValueError("buffer size may not be greater than image size") # create borders with buffer_size borders = np.zeros_like(image, dtype=np.bool_) ext = buffer_size + 1 borders[:ext] = True borders[- ext:] = True borders[:, :ext] = True borders[:, - ext:] = True labels, number = label(image) # determine all objects that are connected to borders borders_indices = np.unique(labels[borders]) indices = np.arange(number + 1) # mask all label indices that are connected to borders label_mask = np.in1d(indices, borders_indices) # create mask for pixels to clear mask = label_mask[labels.ravel()].reshape(labels.shape) # clear border pixels image[mask] = bgval return image scikit-image-0.9.3/skimage/segmentation/_felzenszwalb.py000066400000000000000000000057261223313777300234470ustar00rootroot00000000000000import warnings import numpy as np from ._felzenszwalb_cy import _felzenszwalb_grey def felzenszwalb(image, scale=1, sigma=0.8, min_size=20): """Computes Felsenszwalb's efficient graph based image segmentation. Produces an oversegmentation of a multichannel (i.e. RGB) image using a fast, minimum spanning tree based clustering on the image grid. The parameter ``scale`` sets an observation level. Higher scale means less and larger segments. ``sigma`` is the diameter of a Gaussian kernel, used for smoothing the image prior to segmentation. The number of produced segments as well as their size can only be controlled indirectly through ``scale``. Segment size within an image can vary greatly depending on local contrast. For RGB images, the algorithm computes a separate segmentation for each channel and then combines these. The combined segmentation is the intersection of the separate segmentations on the color channels. Parameters ---------- image : (width, height, 3) or (width, height) ndarray Input image. scale : float Free parameter. Higher means larger clusters. sigma : float Width of Gaussian kernel used in preprocessing. min_size : int Minimum component size. Enforced using postprocessing. Returns ------- segment_mask : (width, height) ndarray Integer mask indicating segment labels. References ---------- .. [1] Efficient graph-based image segmentation, Felzenszwalb, P.F. and Huttenlocher, D.P. International Journal of Computer Vision, 2004 """ #image = img_as_float(image) if image.ndim == 2: # assume single channel image return _felzenszwalb_grey(image, scale=scale, sigma=sigma) elif image.ndim != 3: raise ValueError("Felzenswalb segmentation can only operate on RGB and" " grey images, but input array of ndim %d given." % image.ndim) # assume we got 2d image with multiple channels n_channels = image.shape[2] if n_channels != 3: warnings.warn("Got image with %d channels. Is that really what you" " wanted?" % image.shape[2]) segmentations = [] # compute quickshift for each channel for c in range(n_channels): channel = np.ascontiguousarray(image[:, :, c]) s = _felzenszwalb_grey(channel, scale=scale, sigma=sigma, min_size=min_size) segmentations.append(s) # put pixels in same segment only if in the same segment in all images # we do this by combining the channels to one number n0 = segmentations[0].max() + 1 n1 = segmentations[1].max() + 1 segmentation = (segmentations[0] + segmentations[1] * n0 + segmentations[2] * n0 * n1) # make segment labels consecutive numbers starting at 0 labels = np.unique(segmentation, return_inverse=True)[1] return labels.reshape(image.shape[:2]) scikit-image-0.9.3/skimage/segmentation/_felzenszwalb_cy.pyx000066400000000000000000000114261223313777300243240ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np import scipy cimport cython cimport numpy as cnp from skimage.morphology.ccomp cimport find_root, join_trees from ..util import img_as_float def _felzenszwalb_grey(image, double scale=1, sigma=0.8, Py_ssize_t min_size=20): """Felzenszwalb's efficient graph based segmentation for a single channel. Produces an oversegmentation of a 2d image using a fast, minimum spanning tree based clustering on the image grid. The number of produced segments as well as their size can only be controlled indirectly through ``scale``. Segment size within an image can vary greatly depending on local contrast. Parameters ---------- image: ndarray Input image. scale: float, optional (default 1) Sets the obervation level. Higher means larger clusters. sigma: float, optional (default 0.8) Width of Gaussian smoothing kernel used in preprocessing. Larger sigma gives smother segment boundaries. min_size: int, optional (default 20) Minimum component size. Enforced using postprocessing. Returns ------- segment_mask: (height, width) ndarray Integer mask indicating segment labels. """ if image.ndim != 2: raise ValueError("This algorithm works only on single-channel 2d" "images. Got image of shape %s" % str(image.shape)) image = img_as_float(image) # rescale scale to behave like in reference implementation scale = float(scale) / 255. image = scipy.ndimage.gaussian_filter(image, sigma=sigma) # compute edge weights in 8 connectivity: right_cost = np.abs((image[1:, :] - image[:-1, :])) down_cost = np.abs((image[:, 1:] - image[:, :-1])) dright_cost = np.abs((image[1:, 1:] - image[:-1, :-1])) uright_cost = np.abs((image[1:, :-1] - image[:-1, 1:])) cdef cnp.ndarray[cnp.float_t, ndim=1] costs = np.hstack([right_cost.ravel(), down_cost.ravel(), dright_cost.ravel(), uright_cost.ravel()]).astype(np.float) # compute edges between pixels: height, width = image.shape[:2] cdef cnp.ndarray[cnp.intp_t, ndim=2] segments \ = np.arange(width * height, dtype=np.intp).reshape(height, width) right_edges = np.c_[segments[1:, :].ravel(), segments[:-1, :].ravel()] down_edges = np.c_[segments[:, 1:].ravel(), segments[:, :-1].ravel()] dright_edges = np.c_[segments[1:, 1:].ravel(), segments[:-1, :-1].ravel()] uright_edges = np.c_[segments[:-1, 1:].ravel(), segments[1:, :-1].ravel()] cdef cnp.ndarray[cnp.intp_t, ndim=2] edges \ = np.vstack([right_edges, down_edges, dright_edges, uright_edges]) # initialize data structures for segment size # and inner cost, then start greedy iteration over edges. edge_queue = np.argsort(costs) edges = np.ascontiguousarray(edges[edge_queue]) costs = np.ascontiguousarray(costs[edge_queue]) cdef cnp.intp_t *segments_p = segments.data cdef cnp.intp_t *edges_p = edges.data cdef cnp.float_t *costs_p = costs.data cdef cnp.ndarray[cnp.intp_t, ndim=1] segment_size \ = np.ones(width * height, dtype=np.intp) # inner cost of segments cdef cnp.ndarray[cnp.float_t, ndim=1] cint = np.zeros(width * height) cdef cnp.intp_t seg0, seg1, seg_new, e cdef float cost, inner_cost0, inner_cost1 # set costs_p back one. we increase it before we use it # since we might continue before that. costs_p -= 1 for e in range(costs.size): seg0 = find_root(segments_p, edges_p[0]) seg1 = find_root(segments_p, edges_p[1]) edges_p += 2 costs_p += 1 if seg0 == seg1: continue inner_cost0 = cint[seg0] + scale / segment_size[seg0] inner_cost1 = cint[seg1] + scale / segment_size[seg1] if costs_p[0] < min(inner_cost0, inner_cost1): # update size and cost join_trees(segments_p, seg0, seg1) seg_new = find_root(segments_p, seg0) segment_size[seg_new] = segment_size[seg0] + segment_size[seg1] cint[seg_new] = costs_p[0] # postprocessing to remove small segments edges_p = edges.data for e in range(costs.size): seg0 = find_root(segments_p, edges_p[0]) seg1 = find_root(segments_p, edges_p[1]) edges_p += 2 if segment_size[seg0] < min_size or segment_size[seg1] < min_size: join_trees(segments_p, seg0, seg1) # unravel the union find tree flat = segments.ravel() old = np.zeros_like(flat) while (old != flat).any(): old = flat flat = flat[flat] flat = np.unique(flat, return_inverse=True)[1] return flat.reshape((height, width)) scikit-image-0.9.3/skimage/segmentation/_join.py000066400000000000000000000110671223313777300216730ustar00rootroot00000000000000import numpy as np from skimage._shared.utils import deprecated def join_segmentations(s1, s2): """Return the join of the two input segmentations. The join J of S1 and S2 is defined as the segmentation in which two voxels are in the same segment if and only if they are in the same segment in *both* S1 and S2. Parameters ---------- s1, s2 : numpy arrays s1 and s2 are label fields of the same shape. Returns ------- j : numpy array The join segmentation of s1 and s2. Examples -------- >>> from skimage.segmentation import join_segmentations >>> s1 = np.array([[0, 0, 1, 1], ... [0, 2, 1, 1], ... [2, 2, 2, 1]]) >>> s2 = np.array([[0, 1, 1, 0], ... [0, 1, 1, 0], ... [0, 1, 1, 1]]) >>> join_segmentations(s1, s2) array([[0, 1, 3, 2], [0, 5, 3, 2], [4, 5, 5, 3]]) """ if s1.shape != s2.shape: raise ValueError("Cannot join segmentations of different shape. " + "s1.shape: %s, s2.shape: %s" % (s1.shape, s2.shape)) s1 = relabel_sequential(s1)[0] s2 = relabel_sequential(s2)[0] j = (s2.max() + 1) * s1 + s2 j = relabel_sequential(j)[0] return j @deprecated('relabel_sequential') def relabel_from_one(label_field): """Convert labels in an arbitrary label field to {1, ... number_of_labels}. This function is deprecated, see ``relabel_sequential`` for more. """ return relabel_sequential(label_field, offset=1) def relabel_sequential(label_field, offset=1): """Relabel arbitrary labels to {`offset`, ... `offset` + number_of_labels}. This function also returns the forward map (mapping the original labels to the reduced labels) and the inverse map (mapping the reduced labels back to the original ones). Parameters ---------- label_field : numpy array of int, arbitrary shape An array of labels. offset : int, optional The return labels will start at `offset`, which should be strictly positive. Returns ------- relabeled : numpy array of int, same shape as `label_field` The input label field with labels mapped to {1, ..., number_of_labels}. forward_map : numpy array of int, shape ``(label_field.max() + 1,)`` The map from the original label space to the returned label space. Can be used to re-apply the same mapping. See examples for usage. inverse_map : 1D numpy array of int, of length offset + number of labels The map from the new label space to the original space. This can be used to reconstruct the original label field from the relabeled one. Notes ----- The label 0 is assumed to denote the background and is never remapped. The forward map can be extremely big for some inputs, since its length is given by the maximum of the label field. However, in most situations, ``label_field.max()`` is much smaller than ``label_field.size``, and in these cases the forward map is guaranteed to be smaller than either the input or output images. Examples -------- >>> from skimage.segmentation import relabel_sequential >>> label_field = np.array([1, 1, 5, 5, 8, 99, 42]) >>> relab, fw, inv = relabel_sequential(label_field) >>> relab array([1, 1, 2, 2, 3, 5, 4]) >>> fw array([0, 1, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5]) >>> inv array([ 0, 1, 5, 8, 42, 99]) >>> (fw[label_field] == relab).all() True >>> (inv[relab] == label_field).all() True >>> relab, fw, inv = relabel_sequential(label_field, offset=5) >>> relab array([5, 5, 6, 6, 7, 9, 8]) """ labels = np.unique(label_field) labels0 = labels[labels != 0] m = labels.max() if m == len(labels0): # nothing to do, already 1...n labels return label_field, labels, labels forward_map = np.zeros(m+1, int) forward_map[labels0] = np.arange(offset, offset + len(labels0) + 1) if not (labels == 0).any(): labels = np.concatenate(([0], labels)) inverse_map = np.zeros(offset - 1 + len(labels), dtype=np.intp) inverse_map[(offset - 1):] = labels relabeled = forward_map[label_field] return relabeled, forward_map, inverse_map scikit-image-0.9.3/skimage/segmentation/_quickshift.pyx000066400000000000000000000143571223313777300233030ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np from scipy import ndimage from itertools import product cimport numpy as cnp from libc.math cimport exp, sqrt from ..util import img_as_float from ..color import rgb2lab def quickshift(image, ratio=1., float kernel_size=5, max_dist=10, return_tree=False, sigma=0, convert2lab=True, random_seed=None): """Segments image using quickshift clustering in Color-(x,y) space. Produces an oversegmentation of the image using the quickshift mode-seeking algorithm. Parameters ---------- image : (width, height, channels) ndarray Input image. ratio : float, optional, between 0 and 1 (default 1). Balances color-space proximity and image-space proximity. Higher values give more weight to color-space. kernel_size : float, optional (default 5) Width of Gaussian kernel used in smoothing the sample density. Higher means fewer clusters. max_dist : float, optional (default 10) Cut-off point for data distances. Higher means fewer clusters. return_tree : bool, optional (default False) Whether to return the full segmentation hierarchy tree and distances. sigma : float, optional (default 0) Width for Gaussian smoothing as preprocessing. Zero means no smoothing. convert2lab : bool, optional (default True) Whether the input should be converted to Lab colorspace prior to segmentation. For this purpose, the input is assumed to be RGB. random_seed : None (default) or int, optional Random seed used for breaking ties. Returns ------- segment_mask : (width, height) ndarray Integer mask indicating segment labels. Notes ----- The authors advocate to convert the image to Lab color space prior to segmentation, though this is not strictly necessary. For this to work, the image must be given in RGB format. References ---------- .. [1] Quick shift and kernel methods for mode seeking, Vedaldi, A. and Soatto, S. European Conference on Computer Vision, 2008 """ image = img_as_float(np.atleast_3d(image)) if convert2lab: if image.shape[2] != 3: ValueError("Only RGB images can be converted to Lab space.") image = rgb2lab(image) image = ndimage.gaussian_filter(img_as_float(image), [sigma, sigma, 0]) cdef cnp.ndarray[dtype=cnp.float_t, ndim=3, mode="c"] image_c \ = np.ascontiguousarray(image) * ratio random_state = np.random.RandomState(random_seed) # TODO join orphaned roots? # Some nodes might not have a point of higher density within the # search window. We could do a global search over these in the end. # Reference implementation doesn't do that, though, and it only has # an effect for very high max_dist. # window size for neighboring pixels to consider if kernel_size < 1: raise ValueError("Sigma should be >= 1") cdef int w = int(3 * kernel_size) cdef Py_ssize_t height = image_c.shape[0] cdef Py_ssize_t width = image_c.shape[1] cdef Py_ssize_t channels = image_c.shape[2] cdef double current_density, closest, dist cdef Py_ssize_t r, c, r_, c_, channel, r_min, c_min cdef cnp.float_t* image_p = image_c.data cdef cnp.float_t* current_pixel_p = image_p cdef cnp.ndarray[dtype=cnp.float_t, ndim=2] densities \ = np.zeros((height, width)) # compute densities for r in range(height): for c in range(width): r_min, r_max = max(r - w, 0), min(r + w + 1, height) c_min, c_max = max(c - w, 0), min(c + w + 1, width) for r_ in range(r_min, r_max): for c_ in range(c_min, c_max): dist = 0 for channel in range(channels): dist += (current_pixel_p[channel] - image_c[r_, c_, channel])**2 dist += (r - r_)**2 + (c - c_)**2 densities[r, c] += exp(-dist / (2 * kernel_size**2)) current_pixel_p += channels # this will break ties that otherwise would give us headache densities += random_state.normal(scale=0.00001, size=(height, width)) # default parent to self: cdef cnp.ndarray[dtype=cnp.int_t, ndim=2] parent \ = np.arange(width * height).reshape(height, width) cdef cnp.ndarray[dtype=cnp.float_t, ndim=2] dist_parent \ = np.zeros((height, width)) # find nearest node with higher density current_pixel_p = image_p for r in range(height): for c in range(width): current_density = densities[r, c] closest = np.inf r_min, r_max = max(r - w, 0), min(r + w + 1, height) c_min, c_max = max(c - w, 0), min(c + w + 1, width) for r_ in range(r_min, r_max): for c_ in range(c_min, c_max): if densities[r_, c_] > current_density: dist = 0 # We compute the distances twice since otherwise # we get crazy memory overhead # (width * height * windowsize**2) for channel in range(channels): dist += (current_pixel_p[channel] - image_c[r_, c_, channel])**2 dist += (r - r_)**2 + (c - c_)**2 if dist < closest: closest = dist parent[r, c] = r_ * width + c_ dist_parent[r, c] = sqrt(closest) current_pixel_p += channels dist_parent_flat = dist_parent.ravel() flat = parent.ravel() # remove parents with distance > max_dist too_far = dist_parent_flat > max_dist flat[too_far] = np.arange(width * height)[too_far] old = np.zeros_like(flat) # flatten forest (mark each pixel with root of corresponding tree) while (old != flat).any(): old = flat flat = flat[flat] flat = np.unique(flat, return_inverse=True)[1] flat = flat.reshape(height, width) if return_tree: return flat, parent, dist_parent return flat scikit-image-0.9.3/skimage/segmentation/_slic.pyx000066400000000000000000000122611223313777300220530ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False from libc.float cimport DBL_MAX import numpy as np cimport numpy as cnp from skimage.util import regular_grid def _slic_cython(double[:, :, :, ::1] image_zyx, double[:, ::1] segments, Py_ssize_t max_iter, double[::1] spacing): """Helper function for SLIC segmentation. Parameters ---------- image_zyx : 4D array of double, shape (Z, Y, X, C) The input image. segments : 2D array of double, shape (N, 3 + C) The initial centroids obtained by SLIC as [Z, Y, X, C...]. max_iter : int The maximum number of k-means iterations. spacing : 1D array of double, shape (3,) The voxel spacing along each image dimension. This parameter controls the weights of the distances along z, y, and x during k-means clustering. Returns ------- nearest_segments : 3D array of int, shape (Z, Y, X) The label field/superpixels found by SLIC. Notes ----- The image is considered to be in (z, y, x) order, which can be surprising. More commonly, the order (x, y, z) is used. However, in 3D image analysis, 'z' is usually the "special" dimension, with, for example, a different effective resolution than the other two axes. Therefore, x and y are often processed together, or viewed as a cut-plane through the volume. So, if the order was (x, y, z) and we wanted to look at the 5th cut plane, we would write:: my_z_plane = img3d[:, :, 5] but, assuming a C-contiguous array, this would grab a discontiguous slice of memory, which is bad for performance. In contrast, if we see the image as (z, y, x) ordered, we would do:: my_z_plane = img3d[5] and get back a contiguous block of memory. This is better both for performance and for readability. """ # initialize on grid cdef Py_ssize_t depth, height, width depth = image_zyx.shape[0] height = image_zyx.shape[1] width = image_zyx.shape[2] cdef Py_ssize_t n_segments = segments.shape[0] # number of features [X, Y, Z, ...] cdef Py_ssize_t n_features = segments.shape[1] # approximate grid size for desired n_segments cdef Py_ssize_t step_z, step_y, step_x slices = regular_grid((depth, height, width), n_segments) step_z, step_y, step_x = [int(s.step) for s in slices] cdef Py_ssize_t[:, :, ::1] nearest_segments \ = np.empty((depth, height, width), dtype=np.intp) cdef double[:, :, ::1] distance \ = np.empty((depth, height, width), dtype=np.double) cdef Py_ssize_t[::1] n_segment_elems = np.zeros(n_segments, dtype=np.intp) cdef Py_ssize_t i, c, k, x, y, z, x_min, x_max, y_min, y_max, z_min, z_max cdef char change cdef double dist_center, cx, cy, cz, dy, dz cdef double sz, sy, sx sz = spacing[0] sy = spacing[1] sx = spacing[2] for i in range(max_iter): change = 0 distance[:, :, :] = DBL_MAX # assign pixels to segments for k in range(n_segments): # segment coordinate centers cz = segments[k, 0] cy = segments[k, 1] cx = segments[k, 2] # compute windows z_min = max(cz - 2 * step_z, 0) z_max = min(cz + 2 * step_z + 1, depth) y_min = max(cy - 2 * step_y, 0) y_max = min(cy + 2 * step_y + 1, height) x_min = max(cx - 2 * step_x, 0) x_max = min(cx + 2 * step_x + 1, width) for z in range(z_min, z_max): dz = (sz * (cz - z)) ** 2 for y in range(y_min, y_max): dy = (sy * (cy - y)) ** 2 for x in range(x_min, x_max): dist_center = dz + dy + (sx * (cx - x)) ** 2 for c in range(3, n_features): dist_center += (image_zyx[z, y, x, c - 3] - segments[k, c]) ** 2 if distance[z, y, x] > dist_center: nearest_segments[z, y, x] = k distance[z, y, x] = dist_center change = 1 # stop if no pixel changed its segment if change == 0: break # recompute segment centers # sum features for all segments n_segment_elems[:] = 0 segments[:, :] = 0 for z in range(depth): for y in range(height): for x in range(width): k = nearest_segments[z, y, x] n_segment_elems[k] += 1 segments[k, 0] += z segments[k, 1] += y segments[k, 2] += x for c in range(3, n_features): segments[k, c] += image_zyx[z, y, x, c - 3] # divide by number of elements per segment to obtain mean for k in range(n_segments): for c in range(n_features): segments[k, c] /= n_segment_elems[k] return np.asarray(nearest_segments) scikit-image-0.9.3/skimage/segmentation/boundaries.py000066400000000000000000000030371223313777300227260ustar00rootroot00000000000000import numpy as np from ..morphology import dilation, square from ..util import img_as_float from ..color import gray2rgb from .._shared.utils import deprecated def find_boundaries(label_img): """Return bool array where boundaries between labeled regions are True.""" boundaries = np.zeros(label_img.shape, dtype=np.bool) boundaries[1:, :] += label_img[1:, :] != label_img[:-1, :] boundaries[:, 1:] += label_img[:, 1:] != label_img[:, :-1] return boundaries def mark_boundaries(image, label_img, color=(1, 1, 0), outline_color=(0, 0, 0)): """Return image with boundaries between labeled regions highlighted. Parameters ---------- image : (M, N[, 3]) array Grayscale or RGB image. label_img : (M, N) array Label array where regions are marked by different integer values. color : length-3 sequence RGB color of boundaries in the output image. outline_color : length-3 sequence RGB color surrounding boundaries in the output image. If None, no outline is drawn. """ if image.ndim == 2: image = gray2rgb(image) image = img_as_float(image, force_copy=True) boundaries = find_boundaries(label_img) if outline_color is not None: outer_boundaries = dilation(boundaries.astype(np.uint8), square(2)) image[outer_boundaries != 0, :] = np.array(outline_color) image[boundaries, :] = np.array(color) return image @deprecated('mark_boundaries') def visualize_boundaries(*args, **kwargs): return mark_boundaries(*args, **kwargs) scikit-image-0.9.3/skimage/segmentation/random_walker_segmentation.py000066400000000000000000000462651223313777300262070ustar00rootroot00000000000000""" Random walker segmentation algorithm from *Random walks for image segmentation*, Leo Grady, IEEE Trans Pattern Anal Mach Intell. 2006 Nov;28(11):1768-83. Installing pyamg and using the 'cg_mg' mode of random_walker improves significantly the performance. """ import warnings import numpy as np from scipy import sparse, ndimage # executive summary for next code block: try to import umfpack from # scipy, but make sure not to raise a fuss if it fails since it's only # needed to speed up a few cases. # See discussions at: # https://groups.google.com/d/msg/scikit-image/FrM5IGP6wh4/1hp-FtVZmfcJ # http://stackoverflow.com/questions/13977970/ignore-exceptions-printed-to-stderr-in-del/13977992?noredirect=1#comment28386412_13977992 try: from scipy.sparse.linalg.dsolve import umfpack old_del = umfpack.UmfpackContext.__del__ def new_del(self): try: old_del(self) except AttributeError: pass umfpack.UmfpackContext.__del__ = new_del UmfpackContext = umfpack.UmfpackContext() except: UmfpackContext = None try: from pyamg import ruge_stuben_solver amg_loaded = True except ImportError: amg_loaded = False from scipy.sparse.linalg import cg from ..util import img_as_float from ..filter import rank_order #-----------Laplacian-------------------- def _make_graph_edges_3d(n_x, n_y, n_z): """Returns a list of edges for a 3D image. Parameters ---------- n_x: integer The size of the grid in the x direction. n_y: integer The size of the grid in the y direction n_z: integer The size of the grid in the z direction Returns ------- edges : (2, N) ndarray with the total number of edges:: N = n_x * n_y * (nz - 1) + n_x * (n_y - 1) * nz + (n_x - 1) * n_y * nz Graph edges with each column describing a node-id pair. """ vertices = np.arange(n_x * n_y * n_z).reshape((n_x, n_y, n_z)) edges_deep = np.vstack((vertices[:, :, :-1].ravel(), vertices[:, :, 1:].ravel())) edges_right = np.vstack((vertices[:, :-1].ravel(), vertices[:, 1:].ravel())) edges_down = np.vstack((vertices[:-1].ravel(), vertices[1:].ravel())) edges = np.hstack((edges_deep, edges_right, edges_down)) return edges def _compute_weights_3d(data, spacing, beta=130, eps=1.e-6, multichannel=False): # Weight calculation is main difference in multispectral version # Original gradient**2 replaced with sum of gradients ** 2 gradients = 0 for channel in range(0, data.shape[-1]): gradients += _compute_gradients_3d(data[..., channel], spacing) ** 2 # All channels considered together in this standard deviation beta /= 10 * data.std() if multichannel: # New final term in beta to give == results in trivial case where # multiple identical spectra are passed. beta /= np.sqrt(data.shape[-1]) gradients *= beta weights = np.exp(- gradients) weights += eps return weights def _compute_gradients_3d(data, spacing): gr_deep = np.abs(data[:, :, :-1] - data[:, :, 1:]).ravel() / spacing[2] gr_right = np.abs(data[:, :-1] - data[:, 1:]).ravel() / spacing[1] gr_down = np.abs(data[:-1] - data[1:]).ravel() / spacing[0] return np.r_[gr_deep, gr_right, gr_down] def _make_laplacian_sparse(edges, weights): """ Sparse implementation """ pixel_nb = edges.max() + 1 diag = np.arange(pixel_nb) i_indices = np.hstack((edges[0], edges[1])) j_indices = np.hstack((edges[1], edges[0])) data = np.hstack((-weights, -weights)) lap = sparse.coo_matrix((data, (i_indices, j_indices)), shape=(pixel_nb, pixel_nb)) connect = - np.ravel(lap.sum(axis=1)) lap = sparse.coo_matrix( (np.hstack((data, connect)), (np.hstack((i_indices, diag)), np.hstack((j_indices, diag)))), shape=(pixel_nb, pixel_nb)) return lap.tocsr() def _clean_labels_ar(X, labels, copy=False): X = X.astype(labels.dtype) if copy: labels = np.copy(labels) labels = np.ravel(labels) labels[labels == 0] = X return labels def _buildAB(lap_sparse, labels): """ Build the matrix A and rhs B of the linear system to solve. A and B are two block of the laplacian of the image graph. """ labels = labels[labels >= 0] indices = np.arange(labels.size) unlabeled_indices = indices[labels == 0] seeds_indices = indices[labels > 0] # The following two lines take most of the time in this function B = lap_sparse[unlabeled_indices][:, seeds_indices] lap_sparse = lap_sparse[unlabeled_indices][:, unlabeled_indices] nlabels = labels.max() rhs = [] for lab in range(1, nlabels + 1): mask = (labels[seeds_indices] == lab) fs = sparse.csr_matrix(mask) fs = fs.transpose() rhs.append(B * fs) return lap_sparse, rhs def _mask_edges_weights(edges, weights, mask): """ Remove edges of the graph connected to masked nodes, as well as corresponding weights of the edges. """ mask0 = np.hstack((mask[:, :, :-1].ravel(), mask[:, :-1].ravel(), mask[:-1].ravel())) mask1 = np.hstack((mask[:, :, 1:].ravel(), mask[:, 1:].ravel(), mask[1:].ravel())) ind_mask = np.logical_and(mask0, mask1) edges, weights = edges[:, ind_mask], weights[ind_mask] max_node_index = edges.max() # Reassign edges labels to 0, 1, ... edges_number - 1 order = np.searchsorted(np.unique(edges.ravel()), np.arange(max_node_index + 1)) edges = order[edges.astype(np.int64)] return edges, weights def _build_laplacian(data, spacing, mask=None, beta=50, multichannel=False): l_x, l_y, l_z = tuple(data.shape[i] for i in range(3)) edges = _make_graph_edges_3d(l_x, l_y, l_z) weights = _compute_weights_3d(data, spacing, beta=beta, eps=1.e-10, multichannel=multichannel) if mask is not None: edges, weights = _mask_edges_weights(edges, weights, mask) lap = _make_laplacian_sparse(edges, weights) del edges, weights return lap #----------- Random walker algorithm -------------------------------- def random_walker(data, labels, beta=130, mode='bf', tol=1.e-3, copy=True, multichannel=False, return_full_prob=False, depth=1., spacing=None): """Random walker algorithm for segmentation from markers. Random walker algorithm is implemented for gray-level or multichannel images. Parameters ---------- data : array_like Image to be segmented in phases. Gray-level `data` can be two- or three-dimensional; multichannel data can be three- or four- dimensional (multichannel=True) with the highest dimension denoting channels. Data spacing is assumed isotropic unless depth keyword argument is used. labels : array of ints, of same shape as `data` without channels dimension Array of seed markers labeled with different positive integers for different phases. Zero-labeled pixels are unlabeled pixels. Negative labels correspond to inactive pixels that are not taken into account (they are removed from the graph). If labels are not consecutive integers, the labels array will be transformed so that labels are consecutive. In the multichannel case, `labels` should have the same shape as a single channel of `data`, i.e. without the final dimension denoting channels. beta : float Penalization coefficient for the random walker motion (the greater `beta`, the more difficult the diffusion). mode : {'bf', 'cg_mg', 'cg'} (default: 'bf') Mode for solving the linear system in the random walker algorithm. - 'bf' (brute force, default): an LU factorization of the Laplacian is computed. This is fast for small images (<1024x1024), but very slow (due to the memory cost) and memory-consuming for big images (in 3-D for example). - 'cg' (conjugate gradient): the linear system is solved iteratively using the Conjugate Gradient method from scipy.sparse.linalg. This is less memory-consuming than the brute force method for large images, but it is quite slow. - 'cg_mg' (conjugate gradient with multigrid preconditioner): a preconditioner is computed using a multigrid solver, then the solution is computed with the Conjugate Gradient method. This mode requires that the pyamg module (http://pyamg.org/) is installed. For images of size > 512x512, this is the recommended (fastest) mode. tol : float tolerance to achieve when solving the linear system, in cg' and 'cg_mg' modes. copy : bool If copy is False, the `labels` array will be overwritten with the result of the segmentation. Use copy=False if you want to save on memory. multichannel : bool, default False If True, input data is parsed as multichannel data (see 'data' above for proper input format in this case) return_full_prob : bool, default False If True, the probability that a pixel belongs to each of the labels will be returned, instead of only the most likely label. depth : float, default 1. [DEPRECATED] Correction for non-isotropic voxel depths in 3D volumes. Default (1.) implies isotropy. This factor is derived as follows: depth = (out-of-plane voxel spacing) / (in-plane voxel spacing), where in-plane voxel spacing represents the first two spatial dimensions and out-of-plane voxel spacing represents the third spatial dimension. `depth` is deprecated as of 0.9, in favor of `spacing`. spacing : iterable of floats Spacing between voxels in each spatial dimension. If `None`, then the spacing between pixels/voxels in each dimension is assumed 1. Returns ------- output : ndarray * If `return_full_prob` is False, array of ints of same shape as `data`, in which each pixel has been labeled according to the marker that reached the pixel first by anisotropic diffusion. * If `return_full_prob` is True, array of floats of shape `(nlabels, data.shape)`. `output[label_nb, i, j]` is the probability that label `label_nb` reaches the pixel `(i, j)` first. See also -------- skimage.morphology.watershed: watershed segmentation A segmentation algorithm based on mathematical morphology and "flooding" of regions from markers. Notes ----- Multichannel inputs are scaled with all channel data combined. Ensure all channels are separately normalized prior to running this algorithm. The `spacing` argument is specifically for anisotropic datasets, where data points are spaced differently in one or more spatial dimensions. Anisotropic data is commonly encountered in medical imaging. The algorithm was first proposed in *Random walks for image segmentation*, Leo Grady, IEEE Trans Pattern Anal Mach Intell. 2006 Nov;28(11):1768-83. The algorithm solves the diffusion equation at infinite times for sources placed on markers of each phase in turn. A pixel is labeled with the phase that has the greatest probability to diffuse first to the pixel. The diffusion equation is solved by minimizing x.T L x for each phase, where L is the Laplacian of the weighted graph of the image, and x is the probability that a marker of the given phase arrives first at a pixel by diffusion (x=1 on markers of the phase, x=0 on the other markers, and the other coefficients are looked for). Each pixel is attributed the label for which it has a maximal value of x. The Laplacian L of the image is defined as: - L_ii = d_i, the number of neighbors of pixel i (the degree of i) - L_ij = -w_ij if i and j are adjacent pixels The weight w_ij is a decreasing function of the norm of the local gradient. This ensures that diffusion is easier between pixels of similar values. When the Laplacian is decomposed into blocks of marked and unmarked pixels:: L = M B.T B A with first indices corresponding to marked pixels, and then to unmarked pixels, minimizing x.T L x for one phase amount to solving:: A x = - B x_m where x_m = 1 on markers of the given phase, and 0 on other markers. This linear system is solved in the algorithm using a direct method for small images, and an iterative method for larger images. Examples -------- >>> a = np.zeros((10, 10)) + 0.2*np.random.random((10, 10)) >>> a[5:8, 5:8] += 1 >>> b = np.zeros_like(a) >>> b[3,3] = 1 #Marker for first phase >>> b[6,6] = 2 #Marker for second phase >>> random_walker(a, b) array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 2, 2, 2, 1, 1], [1, 1, 1, 1, 1, 2, 2, 2, 1, 1], [1, 1, 1, 1, 1, 2, 2, 2, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], dtype=int32) """ if mode is None: mode = 'bf' warnings.warn("Default mode will change in the next release from 'bf' " "to 'cg_mg' if pyamg is installed, else to 'cg' if " "SciPy was built with UMFPACK, or to 'bf' otherwise.") if UmfpackContext is None and mode == 'cg': warnings.warn('SciPy was built without UMFPACK. Consider rebuilding ' 'SciPy with UMFPACK, this will greatly speed up the ' 'random walker functions. You may also install pyamg ' 'and run the random walker function in cg_mg mode ' '(see the docstrings)') if depth != 1.: warnings.warn('`depth` kwarg is deprecated, and will be removed in the' ' next major release. Use `spacing` instead.') # Spacing kwarg checks if spacing is None: spacing = (1., 1.) + (depth, ) elif len(spacing) == 2: spacing = tuple(spacing) + (depth, ) elif len(spacing) == 3: pass else: raise ValueError('Input argument `spacing` incorrect, see docstring.') # Parse input data if not multichannel: # We work with 4-D arrays of floats assert data.ndim > 1 and data.ndim < 4, 'For non-multichannel input, \ data must be of dimension 2 \ or 3.' dims = data.shape data = np.atleast_3d(img_as_float(data))[..., np.newaxis] else: dims = data[..., 0].shape assert multichannel and data.ndim > 2, 'For multichannel input, data \ must have >= 3 dimensions.' data = img_as_float(data) if data.ndim == 3: data = data[..., np.newaxis].transpose((0, 1, 3, 2)) if copy: labels = np.copy(labels) label_values = np.unique(labels) # Reorder label values to have consecutive integers (no gaps) if np.any(np.diff(label_values) != 1): mask = labels >= 0 labels[mask] = rank_order(labels[mask])[0].astype(labels.dtype) labels = labels.astype(np.int32) # If the array has pruned zones, be sure that no isolated pixels # exist between pruned zones (they could not be determined) if np.any(labels < 0): filled = ndimage.binary_propagation(labels > 0, mask=labels >= 0) labels[np.logical_and(np.logical_not(filled), labels == 0)] = -1 del filled labels = np.atleast_3d(labels) if np.any(labels < 0): lap_sparse = _build_laplacian(data, spacing, mask=labels >= 0, beta=beta, multichannel=multichannel) else: lap_sparse = _build_laplacian(data, spacing, beta=beta, multichannel=multichannel) lap_sparse, B = _buildAB(lap_sparse, labels) # We solve the linear system # lap_sparse X = B # where X[i, j] is the probability that a marker of label i arrives # first at pixel j by anisotropic diffusion. if mode == 'cg': X = _solve_cg(lap_sparse, B, tol=tol, return_full_prob=return_full_prob) if mode == 'cg_mg': if not amg_loaded: warnings.warn( """pyamg (http://pyamg.org/)) is needed to use this mode, but is not installed. The 'cg' mode will be used instead.""") X = _solve_cg(lap_sparse, B, tol=tol, return_full_prob=return_full_prob) else: X = _solve_cg_mg(lap_sparse, B, tol=tol, return_full_prob=return_full_prob) if mode == 'bf': X = _solve_bf(lap_sparse, B, return_full_prob=return_full_prob) # Clean up results if return_full_prob: labels = labels.astype(np.float) X = np.array([_clean_labels_ar(Xline, labels, copy=True).reshape(dims) for Xline in X]) for i in range(1, int(labels.max()) + 1): mask_i = np.squeeze(labels == i) X[:, mask_i] = 0 X[i - 1, mask_i] = 1 else: X = _clean_labels_ar(X + 1, labels).reshape(dims) return X def _solve_bf(lap_sparse, B, return_full_prob=False): """ solves lap_sparse X_i = B_i for each phase i. An LU decomposition of lap_sparse is computed first. For each pixel, the label i corresponding to the maximal X_i is returned. """ lap_sparse = lap_sparse.tocsc() solver = sparse.linalg.factorized(lap_sparse.astype(np.double)) X = np.array([solver(np.array((-B[i]).todense()).ravel()) for i in range(len(B))]) if not return_full_prob: X = np.argmax(X, axis=0) return X def _solve_cg(lap_sparse, B, tol, return_full_prob=False): """ solves lap_sparse X_i = B_i for each phase i, using the conjugate gradient method. For each pixel, the label i corresponding to the maximal X_i is returned. """ lap_sparse = lap_sparse.tocsc() X = [] for i in range(len(B)): x0 = cg(lap_sparse, -B[i].todense(), tol=tol)[0] X.append(x0) if not return_full_prob: X = np.array(X) X = np.argmax(X, axis=0) return X def _solve_cg_mg(lap_sparse, B, tol, return_full_prob=False): """ solves lap_sparse X_i = B_i for each phase i, using the conjugate gradient method with a multigrid preconditioner (ruge-stuben from pyamg). For each pixel, the label i corresponding to the maximal X_i is returned. """ X = [] ml = ruge_stuben_solver(lap_sparse) M = ml.aspreconditioner(cycle='V') for i in range(len(B)): x0 = cg(lap_sparse, -B[i].todense(), tol=tol, M=M, maxiter=30)[0] X.append(x0) if not return_full_prob: X = np.array(X) X = np.argmax(X, axis=0) return X scikit-image-0.9.3/skimage/segmentation/setup.py000066400000000000000000000024371223313777300217360ustar00rootroot00000000000000#!/usr/bin/env python import os from skimage._build import cython base_path = os.path.abspath(os.path.dirname(__file__)) def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs config = Configuration('segmentation', parent_package, top_path) cython(['_felzenszwalb_cy.pyx'], working_path=base_path) config.add_extension('_felzenszwalb_cy', sources=['_felzenszwalb_cy.c'], include_dirs=[get_numpy_include_dirs()]) cython(['_quickshift.pyx'], working_path=base_path) config.add_extension('_quickshift', sources=['_quickshift.c'], include_dirs=[get_numpy_include_dirs()]) cython(['_slic.pyx'], working_path=base_path) config.add_extension('_slic', sources=['_slic.c'], include_dirs=[get_numpy_include_dirs()]) return config if __name__ == '__main__': from numpy.distutils.core import setup setup(maintainer='scikit-image Developers', maintainer_email='scikit-image@googlegroups.com', description='Segmentation Algorithms', url='https://github.com/scikit-image/scikit-image', license='SciPy License (BSD Style)', **(configuration(top_path='').todict()) ) scikit-image-0.9.3/skimage/segmentation/slic_superpixels.py000066400000000000000000000144521223313777300241730ustar00rootroot00000000000000# coding=utf-8 import collections as coll import numpy as np from scipy import ndimage import warnings from skimage.util import img_as_float, regular_grid from skimage.segmentation._slic import _slic_cython from skimage.color import rgb2lab def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=None, spacing=None, multichannel=True, convert2lab=True, ratio=None): """Segments image using k-means clustering in Color-(x,y,z) space. Parameters ---------- image : 2D, 3D or 4D ndarray Input image, which can be 2D or 3D, and grayscale or multichannel (see `multichannel` parameter). n_segments : int, optional The (approximate) number of labels in the segmented output image. compactness : float, optional Balances color-space proximity and image-space proximity. Higher values give more weight to image-space. As `compactness` tends to infinity, superpixel shapes become square/cubic. max_iter : int, optional Maximum number of iterations of k-means. sigma : float or (3,) array-like of floats, optional Width of Gaussian smoothing kernel for pre-processing for each dimension of the image. The same sigma is applied to each dimension in case of a scalar value. Zero means no smoothing. Note, that `sigma` is automatically scaled if it is scalar and a manual voxel spacing is provided (see Notes section). spacing : (3,) array-like of floats, optional The voxel spacing along each image dimension. By default, `slic` assumes uniform spacing (same voxel resolution along z, y and x). This parameter controls the weights of the distances along z, y, and x during k-means clustering. multichannel : bool, optional Whether the last axis of the image is to be interpreted as multiple channels or another spatial dimension. convert2lab : bool, optional Whether the input should be converted to Lab colorspace prior to segmentation. For this purpose, the input is assumed to be RGB. Highly recommended. ratio : float, optional Synonym for `compactness`. This keyword is deprecated. Returns ------- labels : 2D or 3D array Integer mask indicating segment labels. Raises ------ ValueError If: - the image dimension is not 2 or 3 and `multichannel == False`, OR - the image dimension is not 3 or 4 and `multichannel == True` Notes ----- * If `sigma > 0`, the image is smoothed using a Gaussian kernel prior to segmentation. * If `sigma` is scalar and `spacing` is provided, the kernel width is divided along each dimension by the spacing. For example, if ``sigma=1`` and ``spacing=[5, 1, 1]``, the effective `sigma` is ``[0.2, 1, 1]``. This ensures sensible smoothing for anisotropic images. * The image is rescaled to be in [0, 1] prior to processing. * Images of shape (M, N, 3) are interpreted as 2D RGB images by default. To interpret them as 3D with the last dimension having length 3, use `multichannel=False`. References ---------- .. [1] Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi, Pascal Fua, and Sabine Süsstrunk, SLIC Superpixels Compared to State-of-the-art Superpixel Methods, TPAMI, May 2012. Examples -------- >>> from skimage.segmentation import slic >>> from skimage.data import lena >>> img = lena() >>> segments = slic(img, n_segments=100, compactness=10) >>> # Increasing the compactness parameter yields more square regions >>> segments = slic(img, n_segments=100, compactness=20) """ if sigma is None: warnings.warn('Default value of keyword `sigma` changed from ``1`` ' 'to ``0``.') sigma = 0 if ratio is not None: warnings.warn('Keyword `ratio` is deprecated. Use `compactness` ' 'instead.') compactness = ratio image = img_as_float(image) is_2d = False if image.ndim == 2: # 2D grayscale image image = image[np.newaxis, ..., np.newaxis] is_2d = True elif image.ndim == 3 and multichannel: # Make 2D multichannel image 3D with depth = 1 image = image[np.newaxis, ...] is_2d = True elif image.ndim == 3 and not multichannel: # Add channel as single last dimension image = image[..., np.newaxis] if spacing is None: spacing = np.ones(3) elif isinstance(spacing, (list, tuple)): spacing = np.array(spacing, dtype=np.double) if not isinstance(sigma, coll.Iterable): sigma = np.array([sigma, sigma, sigma], dtype=np.double) sigma /= spacing.astype(np.double) elif isinstance(sigma, (list, tuple)): sigma = np.array(sigma, dtype=np.double) if (sigma > 0).any(): # add zero smoothing for multichannel dimension sigma = list(sigma) + [0] image = ndimage.gaussian_filter(image, sigma) if convert2lab and multichannel: if image.shape[3] != 3: raise ValueError("Lab colorspace conversion requires a RGB image.") image = rgb2lab(image) depth, height, width = image.shape[:3] # initialize cluster centroids for desired number of segments grid_z, grid_y, grid_x = np.mgrid[:depth, :height, :width] slices = regular_grid(image.shape[:3], n_segments) step_z, step_y, step_x = [int(s.step) for s in slices] segments_z = grid_z[slices] segments_y = grid_y[slices] segments_x = grid_x[slices] segments_color = np.zeros(segments_z.shape + (image.shape[3],)) segments = np.concatenate([segments_z[..., np.newaxis], segments_y[..., np.newaxis], segments_x[..., np.newaxis], segments_color ], axis=-1).reshape(-1, 3 + image.shape[3]) segments = np.ascontiguousarray(segments) # we do the scaling of ratio in the same way as in the SLIC paper # so the values have the same meaning ratio = float(max((step_z, step_y, step_x))) / compactness image = np.ascontiguousarray(image * ratio) labels = _slic_cython(image, segments, max_iter, spacing) if is_2d: labels = labels[0] return labels scikit-image-0.9.3/skimage/segmentation/tests/000077500000000000000000000000001223313777300213605ustar00rootroot00000000000000scikit-image-0.9.3/skimage/segmentation/tests/test_clear_border.py000066400000000000000000000015341223313777300254170ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal from skimage.segmentation import clear_border def test_clear_border(): image = np.array( [[0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0], [1, 0, 0, 1, 0, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]]) # test default case result = clear_border(image.copy()) ref = image.copy() ref[2, 0] = 0 ref[0, -2] = 0 assert_array_equal(result, ref) # test buffer result = clear_border(image.copy(), 1) assert_array_equal(result, np.zeros(result.shape)) # test background value result = clear_border(image.copy(), 1, 2) assert_array_equal(result, 2 * np.ones_like(image)) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/segmentation/tests/test_felzenszwalb.py000066400000000000000000000022321223313777300254760ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_equal, assert_array_equal from skimage._shared.testing import assert_greater from skimage.segmentation import felzenszwalb def test_grey(): # very weak tests. This algorithm is pretty unstable. img = np.zeros((20, 21)) img[:10, 10:] = 0.2 img[10:, :10] = 0.4 img[10:, 10:] = 0.6 seg = felzenszwalb(img, sigma=0) # we expect 4 segments: assert_equal(len(np.unique(seg)), 4) # that mostly respect the 4 regions: for i in range(4): hist = np.histogram(img[seg == i], bins=[0, 0.1, 0.3, 0.5, 1])[0] assert_greater(hist[i], 40) def test_color(): # very weak tests. This algorithm is pretty unstable. img = np.zeros((20, 21, 3)) img[:10, :10, 0] = 1 img[10:, :10, 1] = 1 img[10:, 10:, 2] = 1 seg = felzenszwalb(img, sigma=0) # we expect 4 segments: assert_equal(len(np.unique(seg)), 4) assert_array_equal(seg[:10, :10], 0) assert_array_equal(seg[10:, :10], 2) assert_array_equal(seg[:10, 10:], 1) assert_array_equal(seg[10:, 10:], 3) if __name__ == '__main__': from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/segmentation/tests/test_join.py000066400000000000000000000046641223313777300237420ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_array_equal, assert_raises from skimage.segmentation import join_segmentations, relabel_sequential def test_join_segmentations(): s1 = np.array([[0, 0, 1, 1], [0, 2, 1, 1], [2, 2, 2, 1]]) s2 = np.array([[0, 1, 1, 0], [0, 1, 1, 0], [0, 1, 1, 1]]) # test correct join # NOTE: technically, equality to j_ref is not required, only that there # is a one-to-one mapping between j and j_ref. I don't know of an easy way # to check this (i.e. not as error-prone as the function being tested) j = join_segmentations(s1, s2) j_ref = np.array([[0, 1, 3, 2], [0, 5, 3, 2], [4, 5, 5, 3]]) assert_array_equal(j, j_ref) # test correct exception when arrays are different shapes s3 = np.array([[0, 0, 1, 1], [0, 2, 2, 1]]) assert_raises(ValueError, join_segmentations, s1, s3) def test_relabel_sequential_offset1(): ar = np.array([1, 1, 5, 5, 8, 99, 42]) ar_relab, fw, inv = relabel_sequential(ar) ar_relab_ref = np.array([1, 1, 2, 2, 3, 5, 4]) assert_array_equal(ar_relab, ar_relab_ref) fw_ref = np.zeros(100, int) fw_ref[1] = 1; fw_ref[5] = 2; fw_ref[8] = 3; fw_ref[42] = 4; fw_ref[99] = 5 assert_array_equal(fw, fw_ref) inv_ref = np.array([0, 1, 5, 8, 42, 99]) assert_array_equal(inv, inv_ref) def test_relabel_sequential_offset5(): ar = np.array([1, 1, 5, 5, 8, 99, 42]) ar_relab, fw, inv = relabel_sequential(ar, offset=5) ar_relab_ref = np.array([5, 5, 6, 6, 7, 9, 8]) assert_array_equal(ar_relab, ar_relab_ref) fw_ref = np.zeros(100, int) fw_ref[1] = 5; fw_ref[5] = 6; fw_ref[8] = 7; fw_ref[42] = 8; fw_ref[99] = 9 assert_array_equal(fw, fw_ref) inv_ref = np.array([0, 0, 0, 0, 0, 1, 5, 8, 42, 99]) assert_array_equal(inv, inv_ref) def test_relabel_sequential_offset5_with0(): ar = np.array([1, 1, 5, 5, 8, 99, 42, 0]) ar_relab, fw, inv = relabel_sequential(ar, offset=5) ar_relab_ref = np.array([5, 5, 6, 6, 7, 9, 8, 0]) assert_array_equal(ar_relab, ar_relab_ref) fw_ref = np.zeros(100, int) fw_ref[1] = 5; fw_ref[5] = 6; fw_ref[8] = 7; fw_ref[42] = 8; fw_ref[99] = 9 assert_array_equal(fw, fw_ref) inv_ref = np.array([0, 0, 0, 0, 0, 1, 5, 8, 42, 99]) assert_array_equal(inv, inv_ref) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/segmentation/tests/test_quickshift.py000066400000000000000000000033001223313777300251370ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_equal, assert_array_equal from nose.tools import assert_true from skimage._shared.testing import assert_greater from skimage.segmentation import quickshift def test_grey(): rnd = np.random.RandomState(0) img = np.zeros((20, 21)) img[:10, 10:] = 0.2 img[10:, :10] = 0.4 img[10:, 10:] = 0.6 img += 0.1 * rnd.normal(size=img.shape) seg = quickshift(img, kernel_size=2, max_dist=3, random_seed=0, convert2lab=False, sigma=0) # we expect 4 segments: assert_equal(len(np.unique(seg)), 4) # that mostly respect the 4 regions: for i in range(4): hist = np.histogram(img[seg == i], bins=[0, 0.1, 0.3, 0.5, 1])[0] assert_greater(hist[i], 20) def test_color(): rnd = np.random.RandomState(0) img = np.zeros((20, 21, 3)) img[:10, :10, 0] = 1 img[10:, :10, 1] = 1 img[10:, 10:, 2] = 1 img += 0.01 * rnd.normal(size=img.shape) img[img > 1] = 1 img[img < 0] = 0 seg = quickshift(img, random_seed=0, max_dist=30, kernel_size=10, sigma=0) # we expect 4 segments: assert_equal(len(np.unique(seg)), 4) assert_array_equal(seg[:10, :10], 1) assert_array_equal(seg[10:, :10], 2) assert_array_equal(seg[:10, 10:], 0) assert_array_equal(seg[10:, 10:], 3) seg2 = quickshift(img, kernel_size=1, max_dist=2, random_seed=0, convert2lab=False, sigma=0) # very oversegmented: assert_equal(len(np.unique(seg2)), 7) # still don't cross lines assert_true((seg2[9, :] != seg2[10, :]).all()) assert_true((seg2[:, 9] != seg2[:, 10]).all()) if __name__ == '__main__': from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/segmentation/tests/test_random_walker.py000066400000000000000000000215361223313777300256250ustar00rootroot00000000000000import numpy as np from skimage.segmentation import random_walker from skimage.transform import resize def make_2d_syntheticdata(lx, ly=None): if ly is None: ly = lx np.random.seed(1234) data = np.zeros((lx, ly)) + 0.1 * np.random.randn(lx, ly) small_l = int(lx // 5) data[lx // 2 - small_l:lx // 2 + small_l, ly // 2 - small_l:ly // 2 + small_l] = 1 data[lx // 2 - small_l + 1:lx // 2 + small_l - 1, ly // 2 - small_l + 1:ly // 2 + small_l - 1] = ( 0.1 * np.random.randn(2 * small_l - 2, 2 * small_l - 2)) data[lx // 2 - small_l, ly // 2 - small_l // 8:ly // 2 + small_l // 8] = 0 seeds = np.zeros_like(data) seeds[lx // 5, ly // 5] = 1 seeds[lx // 2 + small_l // 4, ly // 2 - small_l // 4] = 2 return data, seeds def make_3d_syntheticdata(lx, ly=None, lz=None): if ly is None: ly = lx if lz is None: lz = lx np.random.seed(1234) data = np.zeros((lx, ly, lz)) + 0.1 * np.random.randn(lx, ly, lz) small_l = int(lx // 5) data[lx // 2 - small_l:lx // 2 + small_l, ly // 2 - small_l:ly // 2 + small_l, lz // 2 - small_l:lz // 2 + small_l] = 1 data[lx // 2 - small_l + 1:lx // 2 + small_l - 1, ly // 2 - small_l + 1:ly // 2 + small_l - 1, lz // 2 - small_l + 1:lz // 2 + small_l - 1] = 0 # make a hole hole_size = np.max([1, small_l // 8]) data[lx // 2 - small_l, ly // 2 - hole_size:ly // 2 + hole_size, lz // 2 - hole_size:lz // 2 + hole_size] = 0 seeds = np.zeros_like(data) seeds[lx // 5, ly // 5, lz // 5] = 1 seeds[lx // 2 + small_l // 4, ly // 2 - small_l // 4, lz // 2 - small_l // 4] = 2 return data, seeds def test_2d_bf(): lx = 70 ly = 100 data, labels = make_2d_syntheticdata(lx, ly) labels_bf = random_walker(data, labels, beta=90, mode='bf') assert (labels_bf[25:45, 40:60] == 2).all() assert data.shape == labels.shape full_prob_bf = random_walker(data, labels, beta=90, mode='bf', return_full_prob=True) assert (full_prob_bf[1, 25:45, 40:60] >= full_prob_bf[0, 25:45, 40:60]).all() assert data.shape == labels.shape # Now test with more than two labels labels[55, 80] = 3 full_prob_bf = random_walker(data, labels, beta=90, mode='bf', return_full_prob=True) assert (full_prob_bf[1, 25:45, 40:60] >= full_prob_bf[0, 25:45, 40:60]).all() assert len(full_prob_bf) == 3 assert data.shape == labels.shape def test_2d_cg(): lx = 70 ly = 100 data, labels = make_2d_syntheticdata(lx, ly) labels_cg = random_walker(data, labels, beta=90, mode='cg') assert (labels_cg[25:45, 40:60] == 2).all() assert data.shape == labels.shape full_prob = random_walker(data, labels, beta=90, mode='cg', return_full_prob=True) assert (full_prob[1, 25:45, 40:60] >= full_prob[0, 25:45, 40:60]).all() assert data.shape == labels.shape return data, labels_cg def test_2d_cg_mg(): lx = 70 ly = 100 data, labels = make_2d_syntheticdata(lx, ly) labels_cg_mg = random_walker(data, labels, beta=90, mode='cg_mg') assert (labels_cg_mg[25:45, 40:60] == 2).all() assert data.shape == labels.shape full_prob = random_walker(data, labels, beta=90, mode='cg_mg', return_full_prob=True) assert (full_prob[1, 25:45, 40:60] >= full_prob[0, 25:45, 40:60]).all() assert data.shape == labels.shape return data, labels_cg_mg def test_types(): lx = 70 ly = 100 data, labels = make_2d_syntheticdata(lx, ly) data = 255 * (data - data.min()) // (data.max() - data.min()) data = data.astype(np.uint8) labels_cg_mg = random_walker(data, labels, beta=90, mode='cg_mg') assert (labels_cg_mg[25:45, 40:60] == 2).all() assert data.shape == labels.shape return data, labels_cg_mg def test_reorder_labels(): lx = 70 ly = 100 data, labels = make_2d_syntheticdata(lx, ly) labels[labels == 2] = 4 labels_bf = random_walker(data, labels, beta=90, mode='bf') assert (labels_bf[25:45, 40:60] == 2).all() assert data.shape == labels.shape return data, labels_bf def test_2d_inactive(): lx = 70 ly = 100 data, labels = make_2d_syntheticdata(lx, ly) labels[10:20, 10:20] = -1 labels[46:50, 33:38] = -2 labels = random_walker(data, labels, beta=90) assert (labels.reshape((lx, ly))[25:45, 40:60] == 2).all() assert data.shape == labels.shape return data, labels def test_3d(): n = 30 lx, ly, lz = n, n, n data, labels = make_3d_syntheticdata(lx, ly, lz) labels = random_walker(data, labels, mode='cg') assert (labels.reshape(data.shape)[13:17, 13:17, 13:17] == 2).all() assert data.shape == labels.shape return data, labels def test_3d_inactive(): n = 30 lx, ly, lz = n, n, n data, labels = make_3d_syntheticdata(lx, ly, lz) old_labels = np.copy(labels) labels[5:25, 26:29, 26:29] = -1 after_labels = np.copy(labels) labels = random_walker(data, labels, mode='cg') assert (labels.reshape(data.shape)[13:17, 13:17, 13:17] == 2).all() assert data.shape == labels.shape return data, labels, old_labels, after_labels def test_multispectral_2d(): lx, ly = 70, 100 data, labels = make_2d_syntheticdata(lx, ly) data = data[..., np.newaxis].repeat(2, axis=-1) # Expect identical output multi_labels = random_walker(data, labels, mode='cg', multichannel=True) assert data[..., 0].shape == labels.shape single_labels = random_walker(data[..., 0], labels, mode='cg') assert (multi_labels.reshape(labels.shape)[25:45, 40:60] == 2).all() assert data[..., 0].shape == labels.shape return data, multi_labels, single_labels, labels def test_multispectral_3d(): n = 30 lx, ly, lz = n, n, n data, labels = make_3d_syntheticdata(lx, ly, lz) data = data[..., np.newaxis].repeat(2, axis=-1) # Expect identical output multi_labels = random_walker(data, labels, mode='cg', multichannel=True) assert data[..., 0].shape == labels.shape single_labels = random_walker(data[..., 0], labels, mode='cg') assert (multi_labels.reshape(labels.shape)[13:17, 13:17, 13:17] == 2).all() assert (single_labels.reshape(labels.shape)[13:17, 13:17, 13:17] == 2).all() assert data[..., 0].shape == labels.shape return data, multi_labels, single_labels, labels def test_depth(): n = 30 lx, ly, lz = n, n, n data, _ = make_3d_syntheticdata(lx, ly, lz) # Rescale `data` along Z axis data_aniso = np.zeros((n, n, n // 2)) for i, yz in enumerate(data): data_aniso[i, :, :] = resize(yz, (n, n // 2)) # Generate new labels small_l = int(lx // 5) labels_aniso = np.zeros_like(data_aniso) labels_aniso[lx // 5, ly // 5, lz // 5] = 1 labels_aniso[lx // 2 + small_l // 4, ly // 2 - small_l // 4, lz // 4 - small_l // 8] = 2 # Test with `depth` kwarg labels_aniso = random_walker(data_aniso, labels_aniso, mode='cg', depth=0.5) assert (labels_aniso[13:17, 13:17, 7:9] == 2).all() def test_spacing(): n = 30 lx, ly, lz = n, n, n data, _ = make_3d_syntheticdata(lx, ly, lz) # Rescale `data` along Y axis # `resize` is not yet 3D capable, so this must be done by looping in 2D. data_aniso = np.zeros((n, n * 2, n)) for i, yz in enumerate(data): data_aniso[i, :, :] = resize(yz, (n * 2, n)) # Generate new labels small_l = int(lx // 5) labels_aniso = np.zeros_like(data_aniso) labels_aniso[lx // 5, ly // 5, lz // 5] = 1 labels_aniso[lx // 2 + small_l // 4, ly - small_l // 2, lz // 2 - small_l // 4] = 2 # Test with `spacing` kwarg # First, anisotropic along Y labels_aniso = random_walker(data_aniso, labels_aniso, mode='cg', spacing=(1., 2., 1.)) assert (labels_aniso[13:17, 26:34, 13:17] == 2).all() # Rescale `data` along X axis # `resize` is not yet 3D capable, so this must be done by looping in 2D. data_aniso = np.zeros((n, n * 2, n)) for i in range(data.shape[1]): data_aniso[i, :, :] = resize(data[:, 1, :], (n * 2, n)) # Generate new labels small_l = int(lx // 5) labels_aniso2 = np.zeros_like(data_aniso) labels_aniso2[lx // 5, ly // 5, lz // 5] = 1 labels_aniso2[lx - small_l // 2, ly // 2 + small_l // 4, lz // 2 - small_l // 4] = 2 # Anisotropic along X labels_aniso2 = random_walker(data_aniso, labels_aniso2, mode='cg', spacing=(2., 1., 1.)) assert (labels_aniso2[26:34, 13:17, 13:17] == 2).all() if __name__ == '__main__': from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/segmentation/tests/test_slic.py000066400000000000000000000076521223313777300237350ustar00rootroot00000000000000import itertools as it import warnings import numpy as np from numpy.testing import assert_equal, assert_array_equal from skimage.segmentation import slic def test_color_2d(): rnd = np.random.RandomState(0) img = np.zeros((20, 21, 3)) img[:10, :10, 0] = 1 img[10:, :10, 1] = 1 img[10:, 10:, 2] = 1 img += 0.01 * rnd.normal(size=img.shape) img[img > 1] = 1 img[img < 0] = 0 with warnings.catch_warnings(): warnings.simplefilter("ignore") seg = slic(img, n_segments=4, sigma=0) # we expect 4 segments assert_equal(len(np.unique(seg)), 4) assert_equal(seg.shape, img.shape[:-1]) assert_array_equal(seg[:10, :10], 0) assert_array_equal(seg[10:, :10], 2) assert_array_equal(seg[:10, 10:], 1) assert_array_equal(seg[10:, 10:], 3) def test_gray_2d(): rnd = np.random.RandomState(0) img = np.zeros((20, 21)) img[:10, :10] = 0.33 img[10:, :10] = 0.67 img[10:, 10:] = 1.00 img += 0.0033 * rnd.normal(size=img.shape) img[img > 1] = 1 img[img < 0] = 0 seg = slic(img, sigma=0, n_segments=4, compactness=1, multichannel=False, convert2lab=False) assert_equal(len(np.unique(seg)), 4) assert_equal(seg.shape, img.shape) assert_array_equal(seg[:10, :10], 0) assert_array_equal(seg[10:, :10], 2) assert_array_equal(seg[:10, 10:], 1) assert_array_equal(seg[10:, 10:], 3) def test_color_3d(): rnd = np.random.RandomState(0) img = np.zeros((20, 21, 22, 3)) slices = [] for dim_size in img.shape[:-1]: midpoint = dim_size // 2 slices.append((slice(None, midpoint), slice(midpoint, None))) slices = list(it.product(*slices)) colors = list(it.product(*(([0, 1],) * 3))) for s, c in zip(slices, colors): img[s] = c img += 0.01 * rnd.normal(size=img.shape) img[img > 1] = 1 img[img < 0] = 0 seg = slic(img, sigma=0, n_segments=8) assert_equal(len(np.unique(seg)), 8) for s, c in zip(slices, range(8)): assert_array_equal(seg[s], c) def test_gray_3d(): rnd = np.random.RandomState(0) img = np.zeros((20, 21, 22)) slices = [] for dim_size in img.shape: midpoint = dim_size // 2 slices.append((slice(None, midpoint), slice(midpoint, None))) slices = list(it.product(*slices)) shades = np.arange(0, 1.000001, 1.0/7) for s, sh in zip(slices, shades): img[s] = sh img += 0.001 * rnd.normal(size=img.shape) img[img > 1] = 1 img[img < 0] = 0 seg = slic(img, sigma=0, n_segments=8, compactness=1, multichannel=False, convert2lab=False) assert_equal(len(np.unique(seg)), 8) for s, c in zip(slices, range(8)): assert_array_equal(seg[s], c) def test_list_sigma(): rnd = np.random.RandomState(0) img = np.array([[1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 1, 1]], np.float) img += 0.1 * rnd.normal(size=img.shape) result_sigma = np.array([[0, 0, 0, 1, 1, 1], [0, 0, 0, 1, 1, 1]], np.int) seg_sigma = slic(img, n_segments=2, sigma=[1, 50, 1], multichannel=False) assert_equal(seg_sigma, result_sigma) def test_spacing(): rnd = np.random.RandomState(0) img = np.array([[1, 1, 1, 0, 0], [1, 1, 0, 0, 0]], np.float) result_non_spaced = np.array([[0, 0, 0, 1, 1], [0, 0, 1, 1, 1]], np.int) result_spaced = np.array([[0, 0, 0, 0, 0], [1, 1, 1, 1, 1]], np.int) img += 0.1 * rnd.normal(size=img.shape) seg_non_spaced = slic(img, n_segments=2, sigma=0, multichannel=False, compactness=1.0) seg_spaced = slic(img, n_segments=2, sigma=0, spacing=[1, 500, 1], compactness=1.0, multichannel=False) assert_equal(seg_non_spaced, result_non_spaced) assert_equal(seg_spaced, result_spaced) if __name__ == '__main__': from numpy import testing testing.run_module_suite() scikit-image-0.9.3/skimage/setup.py000066400000000000000000000024621223313777300172370ustar00rootroot00000000000000import os def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration config = Configuration('skimage', parent_package, top_path) config.add_subpackage('_shared') config.add_subpackage('color') config.add_subpackage('data') config.add_subpackage('draw') config.add_subpackage('feature') config.add_subpackage('filter') config.add_subpackage('graph') config.add_subpackage('io') config.add_subpackage('measure') config.add_subpackage('morphology') config.add_subpackage('transform') config.add_subpackage('util') config.add_subpackage('segmentation') def add_test_directories(arg, dirname, fnames): if dirname.split(os.path.sep)[-1] == 'tests': config.add_data_dir(dirname) # Add test directories from os.path import isdir, dirname, join rel_isdir = lambda d: isdir(join(curpath, d)) curpath = join(dirname(__file__), './') subdirs = [join(d, 'tests') for d in os.listdir(curpath) if rel_isdir(d)] subdirs = [d for d in subdirs if rel_isdir(d)] for test_dir in subdirs: config.add_data_dir(test_dir) return config if __name__ == "__main__": from numpy.distutils.core import setup config = configuration(top_path='').todict() setup(**config) scikit-image-0.9.3/skimage/transform/000077500000000000000000000000001223313777300175345ustar00rootroot00000000000000scikit-image-0.9.3/skimage/transform/__init__.py000066400000000000000000000031241223313777300216450ustar00rootroot00000000000000from ._hough_transform import (hough_circle, hough_ellipse, hough_line, probabilistic_hough_line) from .hough_transform import hough_line_peaks from .radon_transform import radon, iradon, iradon_sart from .finite_radon_transform import frt2, ifrt2 from .integral import integral_image, integrate from ._geometric import (warp, warp_coords, estimate_transform, SimilarityTransform, AffineTransform, ProjectiveTransform, PolynomialTransform, PiecewiseAffineTransform) from ._warps import swirl, resize, rotate, rescale, downscale_local_mean from .pyramids import (pyramid_reduce, pyramid_expand, pyramid_gaussian, pyramid_laplacian) __all__ = ['hough_circle', 'hough_ellipse', 'hough_line', 'probabilistic_hough_line', 'probabilistic_hough', 'hough_peaks', 'hough_line_peaks', 'radon', 'iradon', 'iradon_sart', 'frt2', 'ifrt2', 'integral_image', 'integrate', 'warp', 'warp_coords', 'estimate_transform', 'SimilarityTransform', 'AffineTransform', 'ProjectiveTransform', 'PolynomialTransform', 'PiecewiseAffineTransform', 'swirl', 'resize', 'rotate', 'rescale', 'downscale_local_mean', 'pyramid_reduce', 'pyramid_expand', 'pyramid_gaussian', 'pyramid_laplacian'] scikit-image-0.9.3/skimage/transform/_geometric.py000066400000000000000000001015461223313777300222320ustar00rootroot00000000000000import math import numpy as np from scipy import ndimage, spatial from skimage.util import img_as_float from ._warps_cy import _warp_fast from skimage._shared.utils import get_bound_method_class from skimage._shared import six class GeometricTransform(object): """Perform geometric transformations on a set of coordinates. """ def __call__(self, coords): """Apply forward transformation. Parameters ---------- coords : (N, 2) array Source coordinates. Returns ------- coords : (N, 2) array Transformed coordinates. """ raise NotImplementedError() def inverse(self, coords): """Apply inverse transformation. Parameters ---------- coords : (N, 2) array Source coordinates. Returns ------- coords : (N, 2) array Transformed coordinates. """ raise NotImplementedError() def residuals(self, src, dst): """Determine residuals of transformed destination coordinates. For each transformed source coordinate the euclidean distance to the respective destination coordinate is determined. Parameters ---------- src : (N, 2) array Source coordinates. dst : (N, 2) array Destination coordinates. Returns ------- residuals : (N, ) array Residual for coordinate. """ return np.sqrt(np.sum((self(src) - dst)**2, axis=1)) def __add__(self, other): """Combine this transformation with another. """ raise NotImplementedError() class ProjectiveTransform(GeometricTransform): """Matrix transformation. Apply a projective transformation (homography) on coordinates. For each homogeneous coordinate :math:`\mathbf{x} = [x, y, 1]^T`, its target position is calculated by multiplying with the given matrix, :math:`H`, to give :math:`H \mathbf{x}`:: [[a0 a1 a2] [b0 b1 b2] [c0 c1 1 ]]. E.g., to rotate by theta degrees clockwise, the matrix should be:: [[cos(theta) -sin(theta) 0] [sin(theta) cos(theta) 0] [0 0 1]] or, to translate x by 10 and y by 20:: [[1 0 10] [0 1 20] [0 0 1 ]]. Parameters ---------- matrix : (3, 3) array, optional Homogeneous transformation matrix. """ _coeffs = range(8) def __init__(self, matrix=None): if matrix is None: # default to an identity transform matrix = np.eye(3) if matrix.shape != (3, 3): raise ValueError("invalid shape of transformation matrix") self._matrix = matrix @property def _inv_matrix(self): return np.linalg.inv(self._matrix) def _apply_mat(self, coords, matrix): coords = np.array(coords, copy=False, ndmin=2) x, y = np.transpose(coords) src = np.vstack((x, y, np.ones_like(x))) dst = np.dot(src.transpose(), matrix.transpose()) # rescale to homogeneous coordinates dst[:, 0] /= dst[:, 2] dst[:, 1] /= dst[:, 2] return dst[:, :2] def __call__(self, coords): return self._apply_mat(coords, self._matrix) def inverse(self, coords): """Apply inverse transformation. Parameters ---------- coords : (N, 2) array Source coordinates. Returns ------- coords : (N, 2) array Transformed coordinates. """ return self._apply_mat(coords, self._inv_matrix) def estimate(self, src, dst): """Set the transformation matrix with the explicit transformation parameters. You can determine the over-, well- and under-determined parameters with the total least-squares method. Number of source and destination coordinates must match. The transformation is defined as:: X = (a0*x + a1*y + a2) / (c0*x + c1*y + 1) Y = (b0*x + b1*y + b2) / (c0*x + c1*y + 1) These equations can be transformed to the following form:: 0 = a0*x + a1*y + a2 - c0*x*X - c1*y*X - X 0 = b0*x + b1*y + b2 - c0*x*Y - c1*y*Y - Y which exist for each set of corresponding points, so we have a set of N * 2 equations. The coefficients appear linearly so we can write A x = 0, where:: A = [[x y 1 0 0 0 -x*X -y*X -X] [0 0 0 x y 1 -x*Y -y*Y -Y] ... ... ] x.T = [a0 a1 a2 b0 b1 b2 c0 c1 c3] In case of total least-squares the solution of this homogeneous system of equations is the right singular vector of A which corresponds to the smallest singular value normed by the coefficient c3. In case of the affine transformation the coefficients c0 and c1 are 0. Thus the system of equations is:: A = [[x y 1 0 0 0 -X] [0 0 0 x y 1 -Y] ... ... ] x.T = [a0 a1 a2 b0 b1 b2 c3] Parameters ---------- src : (N, 2) array Source coordinates. dst : (N, 2) array Destination coordinates. """ xs = src[:, 0] ys = src[:, 1] xd = dst[:, 0] yd = dst[:, 1] rows = src.shape[0] # params: a0, a1, a2, b0, b1, b2, c0, c1 A = np.zeros((rows * 2, 9)) A[:rows, 0] = xs A[:rows, 1] = ys A[:rows, 2] = 1 A[:rows, 6] = - xd * xs A[:rows, 7] = - xd * ys A[rows:, 3] = xs A[rows:, 4] = ys A[rows:, 5] = 1 A[rows:, 6] = - yd * xs A[rows:, 7] = - yd * ys A[:rows, 8] = xd A[rows:, 8] = yd # Select relevant columns, depending on params A = A[:, list(self._coeffs) + [8]] _, _, V = np.linalg.svd(A) H = np.zeros((3, 3)) # solution is right singular vector that corresponds to smallest # singular value H.flat[list(self._coeffs) + [8]] = - V[-1, :-1] / V[-1, -1] H[2, 2] = 1 self._matrix = H def __add__(self, other): """Combine this transformation with another. """ if isinstance(other, ProjectiveTransform): # combination of the same types result in a transformation of this # type again, otherwise use general projective transformation if type(self) == type(other): tform = self.__class__ else: tform = ProjectiveTransform return tform(other._matrix.dot(self._matrix)) else: raise TypeError("Cannot combine transformations of differing " "types.") class AffineTransform(ProjectiveTransform): """2D affine transformation of the form:: X = a0*x + a1*y + a2 = = sx*x*cos(rotation) - sy*y*sin(rotation + shear) + a2 Y = b0*x + b1*y + b2 = = sx*x*sin(rotation) + sy*y*cos(rotation + shear) + b2 where ``sx`` and ``sy`` are zoom factors in the x and y directions, and the homogeneous transformation matrix is:: [[a0 a1 a2] [b0 b1 b2] [0 0 1]] Parameters ---------- matrix : (3, 3) array, optional Homogeneous transformation matrix. scale : (sx, sy) as array, list or tuple, optional Scale factors. rotation : float, optional Rotation angle in counter-clockwise direction as radians. shear : float, optional Shear angle in counter-clockwise direction as radians. translation : (tx, ty) as array, list or tuple, optional Translation parameters. """ _coeffs = range(6) def __init__(self, matrix=None, scale=None, rotation=None, shear=None, translation=None): params = any(param is not None for param in (scale, rotation, shear, translation)) if params and matrix is not None: raise ValueError("You cannot specify the transformation matrix and" " the implicit parameters at the same time.") elif matrix is not None: if matrix.shape != (3, 3): raise ValueError("Invalid shape of transformation matrix.") self._matrix = matrix elif params: if scale is None: scale = (1, 1) if rotation is None: rotation = 0 if shear is None: shear = 0 if translation is None: translation = (0, 0) sx, sy = scale self._matrix = np.array([ [sx * math.cos(rotation), -sy * math.sin(rotation + shear), 0], [sx * math.sin(rotation), sy * math.cos(rotation + shear), 0], [ 0, 0, 1] ]) self._matrix[0:2, 2] = translation else: # default to an identity transform self._matrix = np.eye(3) @property def scale(self): sx = math.sqrt(self._matrix[0, 0] ** 2 + self._matrix[1, 0] ** 2) sy = math.sqrt(self._matrix[0, 1] ** 2 + self._matrix[1, 1] ** 2) return sx, sy @property def rotation(self): return math.atan2(self._matrix[1, 0], self._matrix[0, 0]) @property def shear(self): beta = math.atan2(- self._matrix[0, 1], self._matrix[1, 1]) return beta - self.rotation @property def translation(self): return self._matrix[0:2, 2] class PiecewiseAffineTransform(GeometricTransform): """2D piecewise affine transformation. Control points are used to define the mapping. The transform is based on a Delaunay triangulation of the points to form a mesh. Each triangle is used to find a local affine transform. """ def __init__(self): self._tesselation = None self._inverse_tesselation = None self.affines = [] self.inverse_affines = [] def estimate(self, src, dst): """Set the control points with which to perform the piecewise mapping. Number of source and destination coordinates must match. Parameters ---------- src : (N, 2) array Source coordinates. dst : (N, 2) array Destination coordinates. """ # forward piecewise affine # triangulate input positions into mesh self._tesselation = spatial.Delaunay(src) # find affine mapping from source positions to destination self.affines = [] for tri in self._tesselation.vertices: affine = AffineTransform() affine.estimate(src[tri, :], dst[tri, :]) self.affines.append(affine) # inverse piecewise affine # triangulate input positions into mesh self._inverse_tesselation = spatial.Delaunay(dst) # find affine mapping from source positions to destination self.inverse_affines = [] for tri in self._inverse_tesselation.vertices: affine = AffineTransform() affine.estimate(dst[tri, :], src[tri, :]) self.inverse_affines.append(affine) def __call__(self, coords): """Apply forward transformation. Coordinates outside of the mesh will be set to `- 1`. Parameters ---------- coords : (N, 2) array Source coordinates. Returns ------- coords : (N, 2) array Transformed coordinates. """ out = np.empty_like(coords, np.double) # determine triangle index for each coordinate simplex = self._tesselation.find_simplex(coords) # coordinates outside of mesh out[simplex == -1, :] = -1 for index in range(len(self._tesselation.vertices)): # affine transform for triangle affine = self.affines[index] # all coordinates within triangle index_mask = simplex == index out[index_mask, :] = affine(coords[index_mask, :]) return out def inverse(self, coords): """Apply inverse transformation. Coordinates outside of the mesh will be set to `- 1`. Parameters ---------- coords : (N, 2) array Source coordinates. Returns ------- coords : (N, 2) array Transformed coordinates. """ out = np.empty_like(coords, np.double) # determine triangle index for each coordinate simplex = self._inverse_tesselation.find_simplex(coords) # coordinates outside of mesh out[simplex == -1, :] = -1 for index in range(len(self._inverse_tesselation.vertices)): # affine transform for triangle affine = self.inverse_affines[index] # all coordinates within triangle index_mask = simplex == index out[index_mask, :] = affine(coords[index_mask, :]) return out class SimilarityTransform(ProjectiveTransform): """2D similarity transformation of the form:: X = a0*x - b0*y + a1 = = m*x*cos(rotation) + m*y*sin(rotation) + a1 Y = b0*x + a0*y + b1 = = m*x*sin(rotation) + m*y*cos(rotation) + b1 where ``m`` is a zoom factor and the homogeneous transformation matrix is:: [[a0 b0 a1] [b0 a0 b1] [0 0 1]] Parameters ---------- matrix : (3, 3) array, optional Homogeneous transformation matrix. scale : float, optional Scale factor. rotation : float, optional Rotation angle in counter-clockwise direction as radians. translation : (tx, ty) as array, list or tuple, optional x, y translation parameters. """ def __init__(self, matrix=None, scale=None, rotation=None, translation=None): params = any(param is not None for param in (scale, rotation, translation)) if params and matrix is not None: raise ValueError("You cannot specify the transformation matrix and" " the implicit parameters at the same time.") elif matrix is not None: if matrix.shape != (3, 3): raise ValueError("Invalid shape of transformation matrix.") self._matrix = matrix elif params: if scale is None: scale = 1 if rotation is None: rotation = 0 if translation is None: translation = (0, 0) self._matrix = np.array([ [math.cos(rotation), - math.sin(rotation), 0], [math.sin(rotation), math.cos(rotation), 0], [ 0, 0, 1] ]) self._matrix[0:2, 0:2] *= scale self._matrix[0:2, 2] = translation else: # default to an identity transform self._matrix = np.eye(3) def estimate(self, src, dst): """Set the transformation matrix with the explicit parameters. You can determine the over-, well- and under-determined parameters with the total least-squares method. Number of source and destination coordinates must match. The transformation is defined as:: X = a0*x - b0*y + a1 Y = b0*x + a0*y + b1 These equations can be transformed to the following form:: 0 = a0*x - b0*y + a1 - X 0 = b0*x + a0*y + b1 - Y which exist for each set of corresponding points, so we have a set of N * 2 equations. The coefficients appear linearly so we can write A x = 0, where:: A = [[x 1 -y 0 -X] [y 0 x 1 -Y] ... ... ] x.T = [a0 a1 b0 b1 c3] In case of total least-squares the solution of this homogeneous system of equations is the right singular vector of A which corresponds to the smallest singular value normed by the coefficient c3. Parameters ---------- src : (N, 2) array Source coordinates. dst : (N, 2) array Destination coordinates. """ xs = src[:, 0] ys = src[:, 1] xd = dst[:, 0] yd = dst[:, 1] rows = src.shape[0] # params: a0, a1, b0, b1 A = np.zeros((rows * 2, 5)) A[:rows, 0] = xs A[:rows, 2] = - ys A[:rows, 1] = 1 A[rows:, 2] = xs A[rows:, 0] = ys A[rows:, 3] = 1 A[:rows, 4] = xd A[rows:, 4] = yd _, _, V = np.linalg.svd(A) # solution is right singular vector that corresponds to smallest # singular value a0, a1, b0, b1 = - V[-1, :-1] / V[-1, -1] self._matrix = np.array([[a0, -b0, a1], [b0, a0, b1], [ 0, 0, 1]]) @property def scale(self): if math.cos(self.rotation) == 0: # sin(self.rotation) == 1 scale = self._matrix[0, 1] else: scale = self._matrix[0, 0] / math.cos(self.rotation) return scale @property def rotation(self): return math.atan2(self._matrix[1, 0], self._matrix[1, 1]) @property def translation(self): return self._matrix[0:2, 2] class PolynomialTransform(GeometricTransform): """2D transformation of the form:: X = sum[j=0:order]( sum[i=0:j]( a_ji * x**(j - i) * y**i )) Y = sum[j=0:order]( sum[i=0:j]( b_ji * x**(j - i) * y**i )) Parameters ---------- params : (2, N) array, optional Polynomial coefficients where `N * 2 = (order + 1) * (order + 2)`. So, a_ji is defined in `params[0, :]` and b_ji in `params[1, :]`. """ def __init__(self, params=None): if params is None: # default to transformation which preserves original coordinates params = np.array([[0, 1, 0], [0, 0, 1]]) if params.shape[0] != 2: raise ValueError("invalid shape of transformation parameters") self._params = params def estimate(self, src, dst, order=2): """Set the transformation matrix with the explicit transformation parameters. You can determine the over-, well- and under-determined parameters with the total least-squares method. Number of source and destination coordinates must match. The transformation is defined as:: X = sum[j=0:order]( sum[i=0:j]( a_ji * x**(j - i) * y**i )) Y = sum[j=0:order]( sum[i=0:j]( b_ji * x**(j - i) * y**i )) These equations can be transformed to the following form:: 0 = sum[j=0:order]( sum[i=0:j]( a_ji * x**(j - i) * y**i )) - X 0 = sum[j=0:order]( sum[i=0:j]( b_ji * x**(j - i) * y**i )) - Y which exist for each set of corresponding points, so we have a set of N * 2 equations. The coefficients appear linearly so we can write A x = 0, where:: A = [[1 x y x**2 x*y y**2 ... 0 ... 0 -X] [0 ... 0 1 x y x**2 x*y y**2 -Y] ... ... ] x.T = [a00 a10 a11 a20 a21 a22 ... ann b00 b10 b11 b20 b21 b22 ... bnn c3] In case of total least-squares the solution of this homogeneous system of equations is the right singular vector of A which corresponds to the smallest singular value normed by the coefficient c3. Parameters ---------- src : (N, 2) array Source coordinates. dst : (N, 2) array Destination coordinates. order : int, optional Polynomial order (number of coefficients is order + 1). """ xs = src[:, 0] ys = src[:, 1] xd = dst[:, 0] yd = dst[:, 1] rows = src.shape[0] # number of unknown polynomial coefficients u = (order + 1) * (order + 2) A = np.zeros((rows * 2, u + 1)) pidx = 0 for j in range(order + 1): for i in range(j + 1): A[:rows, pidx] = xs ** (j - i) * ys ** i A[rows:, pidx + u / 2] = xs ** (j - i) * ys ** i pidx += 1 A[:rows, -1] = xd A[rows:, -1] = yd _, _, V = np.linalg.svd(A) # solution is right singular vector that corresponds to smallest # singular value params = - V[-1, :-1] / V[-1, -1] self._params = params.reshape((2, u / 2)) def __call__(self, coords): """Apply forward transformation. Parameters ---------- coords : (N, 2) array source coordinates Returns ------- coords : (N, 2) array Transformed coordinates. """ x = coords[:, 0] y = coords[:, 1] u = len(self._params.ravel()) # number of coefficients -> u = (order + 1) * (order + 2) order = int((- 3 + math.sqrt(9 - 4 * (2 - u))) / 2) dst = np.zeros(coords.shape) pidx = 0 for j in range(order + 1): for i in range(j + 1): dst[:, 0] += self._params[0, pidx] * x ** (j - i) * y ** i dst[:, 1] += self._params[1, pidx] * x ** (j - i) * y ** i pidx += 1 return dst def inverse(self, coords): raise Exception( 'There is no explicit way to do the inverse polynomial ' 'transformation. Instead, estimate the inverse transformation ' 'parameters by exchanging source and destination coordinates,' 'then apply the forward transformation.') TRANSFORMS = { 'similarity': SimilarityTransform, 'affine': AffineTransform, 'piecewise-affine': PiecewiseAffineTransform, 'projective': ProjectiveTransform, 'polynomial': PolynomialTransform, } HOMOGRAPHY_TRANSFORMS = ( SimilarityTransform, AffineTransform, ProjectiveTransform ) def estimate_transform(ttype, src, dst, **kwargs): """Estimate 2D geometric transformation parameters. You can determine the over-, well- and under-determined parameters with the total least-squares method. Number of source and destination coordinates must match. Parameters ---------- ttype : {'similarity', 'affine', 'piecewise-affine', 'projective', \ 'polynomial'} Type of transform. kwargs : array or int Function parameters (src, dst, n, angle):: NAME / TTYPE FUNCTION PARAMETERS 'similarity' `src, `dst` 'affine' `src, `dst` 'piecewise-affine' `src, `dst` 'projective' `src, `dst` 'polynomial' `src, `dst`, `order` (polynomial order, default order is 2) Also see examples below. Returns ------- tform : :class:`GeometricTransform` Transform object containing the transformation parameters and providing access to forward and inverse transformation functions. Examples -------- >>> import numpy as np >>> from skimage import transform as tf >>> # estimate transformation parameters >>> src = np.array([0, 0, 10, 10]).reshape((2, 2)) >>> dst = np.array([12, 14, 1, -20]).reshape((2, 2)) >>> tform = tf.estimate_transform('similarity', src, dst) >>> tform.inverse(tform(src)) # == src >>> # warp image using the estimated transformation >>> from skimage import data >>> image = data.camera() >>> warp(image, inverse_map=tform.inverse) >>> # create transformation with explicit parameters >>> tform2 = tf.SimilarityTransform(scale=1.1, rotation=1, ... translation=(10, 20)) >>> # unite transformations, applied in order from left to right >>> tform3 = tform + tform2 >>> tform3(src) # == tform2(tform(src)) """ ttype = ttype.lower() if ttype not in TRANSFORMS: raise ValueError('the transformation type \'%s\' is not' 'implemented' % ttype) tform = TRANSFORMS[ttype]() tform.estimate(src, dst, **kwargs) return tform def matrix_transform(coords, matrix): """Apply 2D matrix transform. Parameters ---------- coords : (N, 2) array x, y coordinates to transform matrix : (3, 3) array Homogeneous transformation matrix. Returns ------- coords : (N, 2) array Transformed coordinates. """ return ProjectiveTransform(matrix)(coords) def _stackcopy(a, b): """Copy b into each color layer of a, such that:: a[:,:,0] = a[:,:,1] = ... = b Parameters ---------- a : (M, N) or (M, N, P) ndarray Target array. b : (M, N) Source array. Notes ----- Color images are stored as an ``(M, N, 3)`` or ``(M, N, 4)`` arrays. """ if a.ndim == 3: a[:] = b[:, :, np.newaxis] else: a[:] = b def warp_coords(coord_map, shape, dtype=np.float64): """Build the source coordinates for the output pixels of an image warp. Parameters ---------- coord_map : callable like GeometricTransform.inverse Return input coordinates for given output coordinates. Coordinates are in the shape (P, 2), where P is the number of coordinates and each element is a ``(x, y)`` pair. shape : tuple Shape of output image ``(rows, cols[, bands])``. dtype : np.dtype or string dtype for return value (sane choices: float32 or float64). Returns ------- coords : (ndim, rows, cols[, bands]) array of dtype `dtype` Coordinates for `scipy.ndimage.map_coordinates`, that will yield an image of shape (orows, ocols, bands) by drawing from source points according to the `coord_transform_fn`. Notes ----- This is a lower-level routine that produces the source coordinates used by `warp()`. It is provided separately from `warp` to give additional flexibility to users who would like, for example, to re-use a particular coordinate mapping, to use specific dtypes at various points along the the image-warping process, or to implement different post-processing logic than `warp` performs after the call to `ndimage.map_coordinates`. Examples -------- Produce a coordinate map that Shifts an image up and to the right: >>> from skimage import data >>> from scipy.ndimage import map_coordinates >>> >>> def shift_up10_left20(xy): ... return xy - np.array([-20, 10])[None, :] >>> >>> image = data.lena().astype(np.float32) >>> coords = warp_coords(shift_up10_left20, image.shape) >>> warped_image = map_coordinates(image, coords) """ rows, cols = shape[0], shape[1] coords_shape = [len(shape), rows, cols] if len(shape) == 3: coords_shape.append(shape[2]) coords = np.empty(coords_shape, dtype=dtype) # Reshape grid coordinates into a (P, 2) array of (x, y) pairs tf_coords = np.indices((cols, rows), dtype=dtype).reshape(2, -1).T # Map each (x, y) pair to the source image according to # the user-provided mapping tf_coords = coord_map(tf_coords) # Reshape back to a (2, M, N) coordinate grid tf_coords = tf_coords.T.reshape((-1, cols, rows)).swapaxes(1, 2) # Place the y-coordinate mapping _stackcopy(coords[1, ...], tf_coords[0, ...]) # Place the x-coordinate mapping _stackcopy(coords[0, ...], tf_coords[1, ...]) if len(shape) == 3: coords[2, ...] = range(shape[2]) return coords def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, mode='constant', cval=0., reverse_map=None): """Warp an image according to a given coordinate transformation. Parameters ---------- image : 2-D or 3-D array Input image. inverse_map : transformation object, callable ``xy = f(xy, **kwargs)``, (3, 3) array Inverse coordinate map. A function that transforms a (N, 2) array of ``(x, y)`` coordinates in the *output image* into their corresponding coordinates in the *source image* (e.g. a transformation object or its inverse). See example section for usage. map_args : dict, optional Keyword arguments passed to `inverse_map`. output_shape : tuple (rows, cols), optional Shape of the output image generated. By default the shape of the input image is preserved. order : int, optional The order of interpolation. The order has to be in the range 0-5: * 0: Nearest-neighbor * 1: Bi-linear (default) * 2: Bi-quadratic * 3: Bi-cubic * 4: Bi-quartic * 5: Bi-quintic mode : string, optional Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). cval : float, optional Used in conjunction with mode 'constant', the value outside the image boundaries. Notes ----- In case of a `SimilarityTransform`, `AffineTransform` and `ProjectiveTransform` and `order` in [0, 3] this function uses the underlying transformation matrix to warp the image with a much faster routine. Examples -------- >>> from skimage.transform import warp >>> from skimage import data >>> image = data.camera() The following image warps are all equal but differ substantially in execution time. Use a geometric transform to warp an image (fast): >>> from skimage.transform import SimilarityTransform >>> tform = SimilarityTransform(translation=(0, -10)) >>> warp(image, tform) Shift an image to the right with a callable (slow): >>> def shift(xy): ... xy[:, 1] -= 10 ... return xy >>> warp(image, shift_right) Use a transformation matrix to warp an image (fast): >>> matrix = np.array([[1, 0, 0], [0, 1, -10], [0, 0, 1]]) >>> warp(image, matrix) >>> from skimage.transform import ProjectiveTransform >>> warp(image, ProjectiveTransform(matrix=matrix)) You can also use the inverse of a geometric transformation (fast): >>> warp(image, tform.inverse) """ # Backward API compatibility if reverse_map is not None: inverse_map = reverse_map if image.ndim < 2: raise ValueError("Input must have more than 1 dimension.") orig_ndim = image.ndim image = np.atleast_3d(img_as_float(image)) ishape = np.array(image.shape) bands = ishape[2] out = None # use fast Cython version for specific interpolation orders and input if order in range(4) and not map_args: matrix = None # inverse_map is a transformation matrix as numpy array if isinstance(inverse_map, np.ndarray) and inverse_map.shape == (3, 3): matrix = inverse_map # inverse_map is a homography elif isinstance(inverse_map, HOMOGRAPHY_TRANSFORMS): matrix = inverse_map._matrix # inverse_map is the inverse of a homography elif (hasattr(inverse_map, '__name__') and inverse_map.__name__ == 'inverse' and isinstance(get_bound_method_class(inverse_map), HOMOGRAPHY_TRANSFORMS)): matrix = np.linalg.inv(six.get_method_self(inverse_map)._matrix) if matrix is not None: matrix = matrix.astype(np.double) # transform all bands dims = [] for dim in range(image.shape[2]): dims.append(_warp_fast(image[..., dim], matrix, output_shape=output_shape, order=order, mode=mode, cval=cval)) out = np.dstack(dims) if orig_ndim == 2: out = out[..., 0] if out is None: # use ndimage.map_coordinates if output_shape is None: output_shape = ishape rows, cols = output_shape[:2] # inverse_map is a transformation matrix as numpy array if isinstance(inverse_map, np.ndarray) and inverse_map.shape == (3, 3): inverse_map = ProjectiveTransform(matrix=inverse_map) def coord_map(*args): return inverse_map(*args, **map_args) coords = warp_coords(coord_map, (rows, cols, bands)) # Pre-filtering not necessary for order 0, 1 interpolation prefilter = order > 1 out = ndimage.map_coordinates(image, coords, prefilter=prefilter, mode=mode, order=order, cval=cval) # The spline filters sometimes return results outside [0, 1], # so clip to ensure valid data clipped = np.clip(out, 0, 1) if mode == 'constant' and not (0 <= cval <= 1): clipped[out == cval] = cval out = clipped if out.ndim == 3 and orig_ndim == 2: # remove singleton dimension introduced by atleast_3d return out[..., 0] else: return out scikit-image-0.9.3/skimage/transform/_hough_transform.pyx000066400000000000000000000430541223313777300236500ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cimport numpy as cnp cimport cython from libc.math cimport abs, fabs, sqrt, ceil, atan2, M_PI from libc.stdlib cimport rand from skimage.draw import circle_perimeter cdef double PI_2 = 1.5707963267948966 cdef double NEG_PI_2 = -PI_2 cdef inline Py_ssize_t round(double r): return ((r + 0.5) if (r > 0.0) else (r - 0.5)) def hough_circle(cnp.ndarray img, cnp.ndarray[ndim=1, dtype=cnp.intp_t] radius, char normalize=True, char full_output=False): """Perform a circular Hough transform. Parameters ---------- img : (M, N) ndarray Input image with nonzero values representing edges. radius : ndarray Radii at which to compute the Hough transform. normalize : boolean, optional (default True) Normalize the accumulator with the number of pixels used to draw the radius. full_output : boolean, optional (default False) Extend the output size by twice the largest radius in order to detect centers outside the input picture. Returns ------- H : 3D ndarray (radius index, (M + 2R, N + 2R) ndarray) Hough transform accumulator for each radius. R designates the larger radius if full_output is True. Otherwise, R = 0. """ if img.ndim != 2: raise ValueError('The input image must be 2D.') cdef Py_ssize_t xmax = img.shape[0] cdef Py_ssize_t ymax = img.shape[1] # compute the nonzero indexes cdef cnp.ndarray[ndim=1, dtype=cnp.intp_t] x, y x, y = np.nonzero(img) cdef Py_ssize_t num_pixels = x.size cdef Py_ssize_t offset = 0 if full_output: # Offset the image offset = radius.max() x = x + offset y = y + offset cdef Py_ssize_t i, p, c, num_circle_pixels, tx, ty cdef double incr cdef cnp.ndarray[ndim=1, dtype=cnp.intp_t] circle_x, circle_y cdef cnp.ndarray[ndim=3, dtype=cnp.double_t] acc = \ np.zeros((radius.size, img.shape[0] + 2 * offset, img.shape[1] + 2 * offset), dtype=np.double) for i, rad in enumerate(radius): # Store in memory the circle of given radius # centered at (0,0) circle_x, circle_y = circle_perimeter(0, 0, rad) num_circle_pixels = circle_x.size if normalize: incr = 1.0 / num_circle_pixels else: incr = 1 # For each non zero pixel for p in range(num_pixels): # Plug the circle at (px, py), # its coordinates are (tx, ty) for c in range(num_circle_pixels): tx = circle_x[c] + x[p] ty = circle_y[c] + y[p] if offset: acc[i, tx, ty] += incr elif 0 <= tx < xmax and 0 <= ty < ymax: acc[i, tx, ty] += incr return acc def hough_ellipse(cnp.ndarray img, int threshold=4, double accuracy=1, int min_size=4, max_size=None): """Perform an elliptical Hough transform. Parameters ---------- img : (M, N) ndarray Input image with nonzero values representing edges. threshold: int, optional (default 4) Accumulator threshold value. accuracy : double, optional (default 1) Bin size on the minor axis used in the accumulator. min_size : int, optional (default 4) Minimal major axis length. max_size : int, optional Maximal minor axis length. (default None) If None, the value is set to the half of the smaller image dimension. Returns ------- result : ndarray with fields [(accumulator, y0, x0, a, b, orientation)] Where ``(yc, xc)`` is the center, ``(a, b)`` the major and minor axes, respectively. The `orientation` value follows `skimage.draw.ellipse_perimeter` convention. Examples -------- >>> img = np.zeros((25, 25), dtype=np.uint8) >>> rr, cc = ellipse_perimeter(10, 10, 6, 8) >>> img[cc, rr] = 1 >>> result = hough_ellipse(img, threshold=8) [(10, 10.0, 8.0, 6.0, 0.0, 10.0)] Notes ----- The accuracy must be chosen to produce a peak in the accumulator distribution. In other words, a flat accumulator distribution with low values may be caused by a too low bin size. References ---------- .. [1] Xie, Yonghong, and Qiang Ji. "A new efficient ellipse detection method." Pattern Recognition, 2002. Proceedings. 16th International Conference on. Vol. 2. IEEE, 2002 """ if img.ndim != 2: raise ValueError('The input image must be 2D.') cdef Py_ssize_t[:, ::1] pixels = np.row_stack(np.nonzero(img)) cdef Py_ssize_t num_pixels = pixels.shape[1] cdef list acc = list() cdef list results = list() cdef double bin_size = accuracy ** 2 cdef int max_b_squared if max_size is None: if img.shape[0] < img.shape[1]: max_b_squared = np.round(0.5 * img.shape[0]) ** 2 else: max_b_squared = np.round(0.5 * img.shape[1]) ** 2 else: max_b_squared = max_size**2 cdef Py_ssize_t p1, p2, p3, p1x, p1y, p2x, p2y, p3x, p3y cdef double xc, yc, a, b, d, k cdef double cos_tau_squared, b_squared, f_squared, orientation for p1 in range(num_pixels): p1x = pixels[1, p1] p1y = pixels[0, p1] for p2 in range(p1): p2x = pixels[1, p2] p2y = pixels[0, p2] # Candidate: center (xc, yc) and main axis a a = 0.5 * sqrt((p1x - p2x)**2 + (p1y - p2y)**2) if a > 0.5 * min_size: xc = 0.5 * (p1x + p2x) yc = 0.5 * (p1y + p2y) for p3 in range(num_pixels): p3x = pixels[1, p3] p3y = pixels[0, p3] d = sqrt((p3x - xc)**2 + (p3y - yc)**2) if d > min_size: f_squared = (p3x - p1x)**2 + (p3y - p1y)**2 cos_tau_squared = ((a**2 + d**2 - f_squared) / (2 * a * d))**2 # Consider b2 > 0 and avoid division by zero k = a**2 - d**2 * cos_tau_squared if k > 0 and cos_tau_squared < 1: b_squared = a**2 * d**2 * (1 - cos_tau_squared) / k # b2 range is limited to avoid histogram memory # overflow if b_squared <= max_b_squared: acc.append(b_squared) if len(acc) > 0: bins = np.arange(0, np.max(acc) + bin_size, bin_size) hist, bin_edges = np.histogram(acc, bins=bins) hist_max = np.max(hist) if hist_max > threshold: orientation = atan2(p1x - p2x, p1y - p2y) b = sqrt(bin_edges[hist.argmax()]) # to keep ellipse_perimeter() convention if orientation != 0: orientation = M_PI - orientation # When orientation is not in [-pi:pi] # it would mean in ellipse_perimeter() # that a < b. But we keep a > b. if orientation > M_PI: orientation = orientation - M_PI / 2. a, b = b, a results.append((hist_max, # Accumulator yc, xc, a, b, orientation)) acc = [] return np.array(results, dtype=[('accumulator', np.intp), ('yc', np.double), ('xc', np.double), ('a', np.double), ('b', np.double), ('orientation', np.double)]) def hough_line(cnp.ndarray img, cnp.ndarray[ndim=1, dtype=cnp.double_t] theta=None): """Perform a straight line Hough transform. Parameters ---------- img : (M, N) ndarray Input image with nonzero values representing edges. theta : 1D ndarray of double Angles at which to compute the transform, in radians. Defaults to -pi/2 .. pi/2 Returns ------- H : 2-D ndarray of uint64 Hough transform accumulator. theta : ndarray Angles at which the transform was computed, in radians. distances : ndarray Distance values. Notes ----- The origin is the top left corner of the original image. X and Y axis are horizontal and vertical edges respectively. The distance is the minimal algebraic distance from the origin to the detected line. Examples -------- Generate a test image: >>> img = np.zeros((100, 150), dtype=bool) >>> img[30, :] = 1 >>> img[:, 65] = 1 >>> img[35:45, 35:50] = 1 >>> for i in range(90): ... img[i, i] = 1 >>> img += np.random.random(img.shape) > 0.95 Apply the Hough transform: >>> out, angles, d = hough_line(img) .. plot:: hough_tf.py """ if img.ndim != 2: raise ValueError('The input image must be 2D.') # Compute the array of angles and their sine and cosine cdef cnp.ndarray[ndim=1, dtype=cnp.double_t] ctheta cdef cnp.ndarray[ndim=1, dtype=cnp.double_t] stheta if theta is None: theta = np.linspace(NEG_PI_2, PI_2, 180) ctheta = np.cos(theta) stheta = np.sin(theta) # compute the bins and allocate the accumulator array cdef cnp.ndarray[ndim=2, dtype=cnp.uint64_t] accum cdef cnp.ndarray[ndim=1, dtype=cnp.double_t] bins cdef Py_ssize_t max_distance, offset max_distance = 2 * ceil(sqrt(img.shape[0] * img.shape[0] + img.shape[1] * img.shape[1])) accum = np.zeros((max_distance, theta.shape[0]), dtype=np.uint64) bins = np.linspace(-max_distance / 2.0, max_distance / 2.0, max_distance) offset = max_distance / 2 # compute the nonzero indexes cdef cnp.ndarray[ndim=1, dtype=cnp.npy_intp] x_idxs, y_idxs y_idxs, x_idxs = np.nonzero(img) # finally, run the transform cdef Py_ssize_t nidxs, nthetas, i, j, x, y, accum_idx nidxs = y_idxs.shape[0] # x and y are the same shape nthetas = theta.shape[0] for i in range(nidxs): x = x_idxs[i] y = y_idxs[i] for j in range(nthetas): accum_idx = round((ctheta[j] * x + stheta[j] * y)) + offset accum[accum_idx, j] += 1 return accum, theta, bins def probabilistic_hough_line(cnp.ndarray img, int threshold=10, int line_length=50, int line_gap=10, cnp.ndarray[ndim=1, dtype=cnp.double_t] theta=None): """Return lines from a progressive probabilistic line Hough transform. Parameters ---------- img : (M, N) ndarray Input image with nonzero values representing edges. threshold : int, optional (default 10) Threshold line_length : int, optional (default 50) Minimum accepted length of detected lines. Increase the parameter to extract longer lines. line_gap : int, optional, (default 10) Maximum gap between pixels to still form a line. Increase the parameter to merge broken lines more aggresively. theta : 1D ndarray, dtype=double, optional, default (-pi/2 .. pi/2) Angles at which to compute the transform, in radians. Returns ------- lines : list List of lines identified, lines in format ((x0, y0), (x1, y0)), indicating line start and end. References ---------- .. [1] C. Galamhos, J. Matas and J. Kittler, "Progressive probabilistic Hough transform for line detection", in IEEE Computer Society Conference on Computer Vision and Pattern Recognition, 1999. """ if img.ndim != 2: raise ValueError('The input image must be 2D.') if theta is None: theta = PI_2 - np.arange(180) / 180.0 * 2 * PI_2 cdef Py_ssize_t height = img.shape[0] cdef Py_ssize_t width = img.shape[1] # compute the bins and allocate the accumulator array cdef cnp.ndarray[ndim=2, dtype=cnp.int64_t] accum cdef cnp.ndarray[ndim=1, dtype=cnp.double_t] ctheta, stheta cdef cnp.ndarray[ndim=2, dtype=cnp.uint8_t] mask = \ np.zeros((height, width), dtype=np.uint8) cdef cnp.ndarray[ndim=2, dtype=cnp.int32_t] line_end = \ np.zeros((2, 2), dtype=np.int32) cdef Py_ssize_t max_distance, offset, num_indexes, index cdef double a, b cdef Py_ssize_t nidxs, i, j, x, y, px, py, accum_idx cdef int value, max_value, max_theta cdef int shift = 16 # maximum line number cutoff cdef Py_ssize_t lines_max = 2 ** 15 cdef Py_ssize_t xflag, x0, y0, dx0, dy0, dx, dy, gap, x1, y1, \ good_line, count cdef list lines = list() max_distance = 2 * ceil((sqrt(img.shape[0] * img.shape[0] + img.shape[1] * img.shape[1]))) accum = np.zeros((max_distance, theta.shape[0]), dtype=np.int64) offset = max_distance / 2 nthetas = theta.shape[0] # compute sine and cosine of angles ctheta = np.cos(theta) stheta = np.sin(theta) # find the nonzero indexes y_idxs, x_idxs = np.nonzero(img) points = list(zip(x_idxs, y_idxs)) # mask all non-zero indexes mask[y_idxs, x_idxs] = 1 while 1: # quit if no remaining points count = len(points) if count == 0: break # select random non-zero point index = rand() % count x = points[index][0] y = points[index][1] del points[index] # if previously eliminated, skip if not mask[y, x]: continue value = 0 max_value = threshold - 1 max_theta = -1 # apply hough transform on point for j in range(nthetas): accum_idx = round((ctheta[j] * x + stheta[j] * y)) + offset accum[accum_idx, j] += 1 value = accum[accum_idx, j] if value > max_value: max_value = value max_theta = j if max_value < threshold: continue # from the random point walk in opposite directions and find line # beginning and end a = -stheta[max_theta] b = ctheta[max_theta] x0 = x y0 = y # calculate gradient of walks using fixed point math xflag = fabs(a) > fabs(b) if xflag: if a > 0: dx0 = 1 else: dx0 = -1 dy0 = round(b * (1 << shift) / fabs(a)) y0 = (y0 << shift) + (1 << (shift - 1)) else: if b > 0: dy0 = 1 else: dy0 = -1 dx0 = round(a * (1 << shift) / fabs(b)) x0 = (x0 << shift) + (1 << (shift - 1)) # pass 1: walk the line, merging lines less than specified gap length for k in range(2): gap = 0 px = x0 py = y0 dx = dx0 dy = dy0 if k > 0: dx = -dx dy = -dy while 1: if xflag: x1 = px y1 = py >> shift else: x1 = px >> shift y1 = py # check when line exits image boundary if x1 < 0 or x1 >= width or y1 < 0 or y1 >= height: break gap += 1 # if non-zero point found, continue the line if mask[y1, x1]: gap = 0 line_end[k, 1] = y1 line_end[k, 0] = x1 # if gap to this point was too large, end the line elif gap > line_gap: break px += dx py += dy # confirm line length is sufficient good_line = abs(line_end[1, 1] - line_end[0, 1]) >= line_length or \ abs(line_end[1, 0] - line_end[0, 0]) >= line_length # pass 2: walk the line again and reset accumulator and mask for k in range(2): px = x0 py = y0 dx = dx0 dy = dy0 if k > 0: dx = -dx dy = -dy while 1: if xflag: x1 = px y1 = py >> shift else: x1 = px >> shift y1 = py # if non-zero point found, continue the line if mask[y1, x1]: if good_line: accum_idx = round((ctheta[j] * x1 \ + stheta[j] * y1)) + offset accum[accum_idx, max_theta] -= 1 mask[y1, x1] = 0 # exit when the point is the line end if x1 == line_end[k, 0] and y1 == line_end[k, 1]: break px += dx py += dy # add line to the result if good_line: lines.append(((line_end[0, 0], line_end[0, 1]), (line_end[1, 0], line_end[1, 1]))) if len(lines) > lines_max: return lines return lines scikit-image-0.9.3/skimage/transform/_radon_transform.pyx000066400000000000000000000173431223313777300236430ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cimport numpy as cnp cimport cython from libc.math cimport cos, sin, floor, ceil, sqrt, abs, M_PI cpdef bilinear_ray_sum(cnp.double_t[:, :] image, cnp.double_t theta, cnp.double_t ray_position): """ Compute the projection of an image along a ray. Parameters ---------- image : 2D array, dtype=float Image to project. theta : float Angle of the projection ray_position : float Position of the ray within the projection Returns ------- projected_value : float Ray sum along the projection norm_of_weights : A measure of how long the ray's path through the reconstruction circle was """ theta = theta / 180. * M_PI cdef cnp.double_t radius = image.shape[0] // 2 - 1 cdef cnp.double_t projection_center = image.shape[0] // 2 cdef cnp.double_t rotation_center = image.shape[0] // 2 # (s, t) is the (x, y) system rotated by theta cdef cnp.double_t t = ray_position - projection_center # s0 is the half-length of the ray's path in the reconstruction circle cdef cnp.double_t s0 s0 = sqrt(radius**2 - t**2) if radius**2 >= t**2 else 0. cdef Py_ssize_t Ns = 2 * ( ceil(2 * s0)) # number of steps # along the ray cdef cnp.double_t ray_sum = 0. cdef cnp.double_t weight_norm = 0. cdef cnp.double_t ds, dx, dy, x0, y0, x, y, di, dj, cdef cnp.double_t index_i, index_j, weight cdef Py_ssize_t k, i, j if Ns > 0: # step length between samples ds = 2 * s0 / Ns dx = -ds * cos(theta) dy = -ds * sin(theta) # point of entry of the ray into the reconstruction circle x0 = s0 * cos(theta) - t * sin(theta) y0 = s0 * sin(theta) + t * cos(theta) for k in range(Ns+1): x = x0 + k * dx y = y0 + k * dy index_i = x + rotation_center index_j = y + rotation_center i = floor(index_i) j = floor(index_j) di = index_i - floor(index_i) dj = index_j - floor(index_j) # Use linear interpolation between values # Where values fall outside the array, assume zero if i > 0 and j > 0: weight = (1. - di) * (1. - dj) * ds ray_sum += weight * image[i, j] weight_norm += weight**2 if i > 0 and j < image.shape[1] - 1: weight = (1. - di) * dj * ds ray_sum += weight * image[i, j+1] weight_norm += weight**2 if i < image.shape[0] - 1 and j > 0: weight = di * (1 - dj) * ds ray_sum += weight * image[i+1, j] weight_norm += weight**2 if i < image.shape[0] - 1 and j < image.shape[1] - 1: weight = di * dj * ds ray_sum += weight * image[i+1, j+1] weight_norm += weight**2 return ray_sum, weight_norm cpdef bilinear_ray_update(cnp.double_t[:, :] image, cnp.double_t[:, :] image_update, cnp.double_t theta, cnp.double_t ray_position, cnp.double_t projected_value): """ Compute the update along a ray using bilinear interpolation. Parameters ---------- image : 2D array, dtype=float Current reconstruction estimate image_update : 2D array, dtype=float Array of same shape as ``image``. Updates will be added to this array. theta : float Angle of the projection ray_position : float Position of the ray within the projection projected_value : float Projected value (from the sinogram) Returns ------- deviation : Deviation before updating the image """ cdef cnp.double_t ray_sum, weight_norm, deviation ray_sum, weight_norm = bilinear_ray_sum(image, theta, ray_position) if weight_norm > 0.: deviation = -(ray_sum - projected_value) / weight_norm else: deviation = 0. theta = theta / 180. * M_PI cdef cnp.double_t radius = image.shape[0] // 2 - 1 cdef cnp.double_t projection_center = image.shape[0] // 2 cdef cnp.double_t rotation_center = image.shape[0] // 2 # (s, t) is the (x, y) system rotated by theta cdef cnp.double_t t = ray_position - projection_center # s0 is the half-length of the ray's path in the reconstruction circle cdef cnp.double_t s0 s0 = sqrt(radius*radius - t*t) if radius**2 >= t**2 else 0. cdef Py_ssize_t Ns = 2 * ( ceil(2 * s0)) cdef cnp.double_t hamming_beta = 0.46164 # beta for equiripple Hamming window cdef cnp.double_t ds, dx, dy, x0, y0, x, y, di, dj, index_i, index_j cdef cnp.double_t hamming_window cdef Py_ssize_t k, i, j if Ns > 0: # Step length between samples ds = 2 * s0 / Ns dx = -ds * cos(theta) dy = -ds * sin(theta) # Point of entry of the ray into the reconstruction circle x0 = s0 * cos(theta) - t * sin(theta) y0 = s0 * sin(theta) + t * cos(theta) for k in range(Ns+1): x = x0 + k * dx y = y0 + k * dy index_i = x + rotation_center index_j = y + rotation_center i = floor(index_i) j = floor(index_j) di = index_i - floor(index_i) dj = index_j - floor(index_j) hamming_window = ((1 - hamming_beta) - hamming_beta * cos(2 * M_PI * k / (Ns - 1))) if i > 0 and j > 0: image_update[i, j] += (deviation * (1. - di) * (1. - dj) * ds * hamming_window) if i > 0 and j < image.shape[1] - 1: image_update[i, j+1] += (deviation * (1. - di) * dj * ds * hamming_window) if i < image.shape[0] - 1 and j > 0: image_update[i+1, j] += (deviation * di * (1 - dj) * ds * hamming_window) if i < image.shape[0] - 1 and j < image.shape[1] - 1: image_update[i+1, j+1] += (deviation * di * dj * ds * hamming_window) return deviation @cython.boundscheck(True) def sart_projection_update(cnp.double_t[:, :] image not None, cnp.double_t theta, cnp.double_t[:] projection not None, cnp.double_t projection_shift=0.): """ Compute update to a reconstruction estimate from a single projection using bilinear interpolation. Parameters ---------- image : 2D array, dtype=float Current reconstruction estimate theta : float Angle of the projection projection : 1D array, dtype=float Projected values, taken from the sinogram projection_shift : float Shift the position of the projection by this many pixels before using it to compute an update to the reconstruction estimate Returns ------- image_update : 2D array, dtype=float Array of same shape as ``image`` containing updates that should be added to ``image`` to improve the reconstruction estimate """ cdef cnp.ndarray[cnp.double_t, ndim=2] image_update = np.zeros_like(image) cdef cnp.double_t ray_position cdef Py_ssize_t i for i in range(projection.shape[0]): ray_position = i + projection_shift bilinear_ray_update(image, image_update, theta, ray_position, projection[i]) return image_update scikit-image-0.9.3/skimage/transform/_warps.py000066400000000000000000000255411223313777300214100ustar00rootroot00000000000000import numpy as np from scipy import ndimage from skimage.transform._geometric import (warp, SimilarityTransform, AffineTransform) from skimage.measure import block_reduce def resize(image, output_shape, order=1, mode='constant', cval=0.): """Resize image to match a certain size. Performs interpolation to up-size or down-size images. For down-sampling N-dimensional images by applying the arithmetic sum or mean, see `skimage.measure.local_sum` and `skimage.transform.downscale_local_mean`, respectively. Parameters ---------- image : ndarray Input image. output_shape : tuple or ndarray Size of the generated output image `(rows, cols[, dim])`. If `dim` is not provided, the number of channels is preserved. In case the number of input channels does not equal the number of output channels a 3-dimensional interpolation is applied. Returns ------- resized : ndarray Resized version of the input. Other parameters ---------------- order : int, optional The order of the spline interpolation, default is 1. The order has to be in the range 0-5. See `skimage.transform.warp` for detail. mode : string, optional Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). cval : float, optional Used in conjunction with mode 'constant', the value outside the image boundaries. Examples -------- >>> from skimage import data >>> from skimage.transform import resize >>> image = data.camera() >>> resize(image, (100, 100)).shape (100, 100) """ rows, cols = output_shape[0], output_shape[1] orig_rows, orig_cols = image.shape[0], image.shape[1] row_scale = float(orig_rows) / rows col_scale = float(orig_cols) / cols # 3-dimensional interpolation if len(output_shape) == 3 and (image.ndim == 2 or output_shape[2] != image.shape[2]): dim = output_shape[2] orig_dim = 1 if image.ndim == 2 else image.shape[2] dim_scale = float(orig_dim) / dim map_rows, map_cols, map_dims = np.mgrid[:rows, :cols, :dim] map_rows = row_scale * (map_rows + 0.5) - 0.5 map_cols = col_scale * (map_cols + 0.5) - 0.5 map_dims = dim_scale * (map_dims + 0.5) - 0.5 coord_map = np.array([map_rows, map_cols, map_dims]) out = ndimage.map_coordinates(image, coord_map, order=order, mode=mode, cval=cval) else: # 2-dimensional interpolation # 3 control points necessary to estimate exact AffineTransform src_corners = np.array([[1, 1], [1, rows], [cols, rows]]) - 1 dst_corners = np.zeros(src_corners.shape, dtype=np.double) # take into account that 0th pixel is at position (0.5, 0.5) dst_corners[:, 0] = col_scale * (src_corners[:, 0] + 0.5) - 0.5 dst_corners[:, 1] = row_scale * (src_corners[:, 1] + 0.5) - 0.5 tform = AffineTransform() tform.estimate(src_corners, dst_corners) out = warp(image, tform, output_shape=output_shape, order=order, mode=mode, cval=cval) return out def rescale(image, scale, order=1, mode='constant', cval=0.): """Scale image by a certain factor. Performs interpolation to upscale or down-scale images. For down-sampling N-dimensional images with integer factors by applying the arithmetic sum or mean, see `skimage.measure.local_sum` and `skimage.transform.downscale_local_mean`, respectively. Parameters ---------- image : ndarray Input image. scale : {float, tuple of floats} Scale factors. Separate scale factors can be defined as `(row_scale, col_scale)`. Returns ------- scaled : ndarray Scaled version of the input. Other parameters ---------------- order : int, optional The order of the spline interpolation, default is 1. The order has to be in the range 0-5. See `skimage.transform.warp` for detail. mode : string, optional Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). cval : float, optional Used in conjunction with mode 'constant', the value outside the image boundaries. Examples -------- >>> from skimage import data >>> from skimage.transform import rescale >>> image = data.camera() >>> rescale(image, 0.1).shape (51, 51) >>> rescale(image, 0.5).shape (256, 256) """ try: row_scale, col_scale = scale except TypeError: row_scale = col_scale = scale orig_rows, orig_cols = image.shape[0], image.shape[1] rows = np.round(row_scale * orig_rows) cols = np.round(col_scale * orig_cols) output_shape = (rows, cols) return resize(image, output_shape, order=order, mode=mode, cval=cval) def rotate(image, angle, resize=False, order=1, mode='constant', cval=0.): """Rotate image by a certain angle around its center. Parameters ---------- image : ndarray Input image. angle : float Rotation angle in degrees in counter-clockwise direction. resize : bool, optional Determine whether the shape of the output image will be automatically calculated, so the complete rotated image exactly fits. Default is False. Returns ------- rotated : ndarray Rotated version of the input. Other parameters ---------------- order : int, optional The order of the spline interpolation, default is 1. The order has to be in the range 0-5. See `skimage.transform.warp` for detail. mode : string, optional Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). cval : float, optional Used in conjunction with mode 'constant', the value outside the image boundaries. Examples -------- >>> from skimage import data >>> from skimage.transform import rotate >>> image = data.camera() >>> rotate(image, 2).shape (512, 512) >>> rotate(image, 2, resize=True).shape (530, 530) >>> rotate(image, 90, resize=True).shape (512, 512) """ rows, cols = image.shape[0], image.shape[1] # rotation around center translation = np.array((cols, rows)) / 2. - 0.5 tform1 = SimilarityTransform(translation=-translation) tform2 = SimilarityTransform(rotation=np.deg2rad(angle)) tform3 = SimilarityTransform(translation=translation) tform = tform1 + tform2 + tform3 output_shape = None if resize: # determine shape of output image corners = np.array([[1, 1], [1, rows], [cols, rows], [cols, 1]]) corners = tform(corners - 1) minc = corners[:, 0].min() minr = corners[:, 1].min() maxc = corners[:, 0].max() maxr = corners[:, 1].max() out_rows = maxr - minr + 1 out_cols = maxc - minc + 1 output_shape = np.ceil((out_rows, out_cols)) # fit output image in new shape translation = ((cols - out_cols) / 2., (rows - out_rows) / 2.) tform4 = SimilarityTransform(translation=translation) tform = tform4 + tform return warp(image, tform, output_shape=output_shape, order=order, mode=mode, cval=cval) def downscale_local_mean(image, factors, cval=0): """Down-sample N-dimensional image by local averaging. The image is padded with `cval` if it is not perfectly divisible by the integer factors. In contrast to the 2-D interpolation in `skimage.transform.resize` and `skimage.transform.rescale` this function may be applied to N-dimensional images and calculates the local mean of elements in each block of size `factors` in the input image. Parameters ---------- image : ndarray N-dimensional input image. factors : array_like Array containing down-sampling integer factor along each axis. cval : float, optional Constant padding value if image is not perfectly divisible by the integer factors. Returns ------- image : ndarray Down-sampled image with same number of dimensions as input image. Example ------- >>> a = np.arange(15).reshape(3, 5) >>> a array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14]]) >>> downscale_local_mean(a, (2, 3)) array([[3.5, 4.], [5.5, 4.5]]) """ return block_reduce(image, factors, np.mean, cval) def _swirl_mapping(xy, center, rotation, strength, radius): x, y = xy.T x0, y0 = center rho = np.sqrt((x - x0) ** 2 + (y - y0) ** 2) # Ensure that the transformation decays to approximately 1/1000-th # within the specified radius. radius = radius / 5 * np.log(2) theta = rotation + strength * \ np.exp(-rho / radius) + \ np.arctan2(y - y0, x - x0) xy[..., 0] = x0 + rho * np.cos(theta) xy[..., 1] = y0 + rho * np.sin(theta) return xy def swirl(image, center=None, strength=1, radius=100, rotation=0, output_shape=None, order=1, mode='constant', cval=0): """Perform a swirl transformation. Parameters ---------- image : ndarray Input image. center : (x,y) tuple or (2,) ndarray, optional Center coordinate of transformation. strength : float, optional The amount of swirling applied. radius : float, optional The extent of the swirl in pixels. The effect dies out rapidly beyond `radius`. rotation : float, optional Additional rotation applied to the image. Returns ------- swirled : ndarray Swirled version of the input. Other parameters ---------------- output_shape : tuple (rows, cols), optional Shape of the output image generated. By default the shape of the input image is preserved. order : int, optional The order of the spline interpolation, default is 1. The order has to be in the range 0-5. See `skimage.transform.warp` for detail. mode : string, optional Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). cval : float, optional Used in conjunction with mode 'constant', the value outside the image boundaries. """ if center is None: center = np.array(image.shape)[:2] / 2 warp_args = {'center': center, 'rotation': rotation, 'strength': strength, 'radius': radius} return warp(image, _swirl_mapping, map_args=warp_args, output_shape=output_shape, order=order, mode=mode, cval=cval) scikit-image-0.9.3/skimage/transform/_warps_cy.pyx000066400000000000000000000075371223313777300223000ustar00rootroot00000000000000#cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False #cython: wraparound=False import numpy as np cimport numpy as cnp from skimage._shared.interpolation cimport (nearest_neighbour_interpolation, bilinear_interpolation, biquadratic_interpolation, bicubic_interpolation) cdef inline void _matrix_transform(double x, double y, double* H, double *x_, double *y_): """Apply a homography to a coordinate. Parameters ---------- x, y : double Input coordinate. H : (3,3) *double Transformation matrix. x_, y_ : *double Output coordinate. """ cdef double xx, yy, zz xx = H[0] * x + H[1] * y + H[2] yy = H[3] * x + H[4] * y + H[5] zz = H[6] * x + H[7] * y + H[8] x_[0] = xx / zz y_[0] = yy / zz def _warp_fast(cnp.ndarray image, cnp.ndarray H, output_shape=None, int order=1, mode='constant', double cval=0): """Projective transformation (homography). Perform a projective transformation (homography) of a floating point image, using interpolation. For each pixel, given its homogeneous coordinate :math:`\mathbf{x} = [x, y, 1]^T`, its target position is calculated by multiplying with the given matrix, :math:`H`, to give :math:`H \mathbf{x}`. E.g., to rotate by theta degrees clockwise, the matrix should be:: [[cos(theta) -sin(theta) 0] [sin(theta) cos(theta) 0] [0 0 1]] or, to translate x by 10 and y by 20:: [[1 0 10] [0 1 20] [0 0 1 ]]. Parameters ---------- image : 2-D array Input image. H : array of shape ``(3, 3)`` Transformation matrix H that defines the homography. output_shape : tuple (rows, cols), optional Shape of the output image generated (default None). order : {0, 1, 2, 3}, optional Order of interpolation:: * 0: Nearest-neighbor * 1: Bi-linear (default) * 2: Bi-quadratic * 3: Bi-cubic mode : {'constant', 'reflect', 'wrap', 'nearest'}, optional How to handle values outside the image borders (default is constant). cval : string, optional (default 0) Used in conjunction with mode 'C' (constant), the value outside the image boundaries. """ cdef double[:, ::1] img = np.ascontiguousarray(image, dtype=np.double) cdef double[:, ::1] M = np.ascontiguousarray(H) if mode not in ('constant', 'wrap', 'reflect', 'nearest'): raise ValueError("Invalid mode specified. Please use " "`constant`, `nearest`, `wrap` or `reflect`.") cdef char mode_c = ord(mode[0].upper()) cdef Py_ssize_t out_r, out_c if output_shape is None: out_r = int(img.shape[0]) out_c = int(img.shape[1]) else: out_r = int(output_shape[0]) out_c = int(output_shape[1]) cdef double[:, ::1] out = np.zeros((out_r, out_c), dtype=np.double) cdef Py_ssize_t tfr, tfc cdef double r, c cdef Py_ssize_t rows = img.shape[0] cdef Py_ssize_t cols = img.shape[1] cdef double (*interp_func)(double*, Py_ssize_t, Py_ssize_t, double, double, char, double) if order == 0: interp_func = nearest_neighbour_interpolation elif order == 1: interp_func = bilinear_interpolation elif order == 2: interp_func = biquadratic_interpolation elif order == 3: interp_func = bicubic_interpolation for tfr in range(out_r): for tfc in range(out_c): _matrix_transform(tfc, tfr, &M[0, 0], &c, &r) out[tfr, tfc] = interp_func(&img[0, 0], rows, cols, r, c, mode_c, cval) return np.asarray(out) scikit-image-0.9.3/skimage/transform/finite_radon_transform.py000066400000000000000000000062061223313777300246460ustar00rootroot00000000000000""" :author: Gary Ruben, 2009 :license: modified BSD """ __all__ = ["frt2", "ifrt2"] import numpy as np from numpy import roll, newaxis def frt2(a): """Compute the 2-dimensional finite radon transform (FRT) for an n x n integer array. Parameters ---------- a : array_like A 2-D square n x n integer array. Returns ------- FRT : 2-D ndarray Finite Radon Transform array of (n+1) x n integer coefficients. See Also -------- ifrt2 : The two-dimensional inverse FRT. Notes ----- The FRT has a unique inverse iff n is prime. [FRT] The idea for this algorithm is due to Vlad Negnevitski. Examples -------- Generate a test image: Use a prime number for the array dimensions >>> SIZE = 59 >>> img = np.tri(SIZE, dtype=np.int32) Apply the Finite Radon Transform: >>> f = frt2(img) References ---------- .. [FRT] A. Kingston and I. Svalbe, "Projective transforms on periodic discrete image arrays," in P. Hawkes (Ed), Advances in Imaging and Electron Physics, 139 (2006) """ if a.ndim != 2 or a.shape[0] != a.shape[1]: raise ValueError("Input must be a square, 2-D array") ai = a.copy() n = ai.shape[0] f = np.empty((n + 1, n), np.uint32) f[0] = ai.sum(axis=0) for m in range(1, n): # Roll the pth row of ai left by p places for row in range(1, n): ai[row] = roll(ai[row], -row) f[m] = ai.sum(axis=0) f[n] = ai.sum(axis=1) return f def ifrt2(a): """Compute the 2-dimensional inverse finite radon transform (iFRT) for an (n+1) x n integer array. Parameters ---------- a : array_like A 2-D (n+1) row x n column integer array. Returns ------- iFRT : 2-D n x n ndarray Inverse Finite Radon Transform array of n x n integer coefficients. See Also -------- frt2 : The two-dimensional FRT Notes ----- The FRT has a unique inverse iff n is prime. See [1]_ for an overview. The idea for this algorithm is due to Vlad Negnevitski. Examples -------- >>> SIZE = 59 >>> img = np.tri(SIZE, dtype=np.int32) Apply the Finite Radon Transform: >>> f = frt2(img) Apply the Inverse Finite Radon Transform to recover the input >>> fi = ifrt2(f) Check that it's identical to the original >>> assert len(np.nonzero(img-fi)[0]) == 0 References ---------- .. [1] A. Kingston and I. Svalbe, "Projective transforms on periodic discrete image arrays," in P. Hawkes (Ed), Advances in Imaging and Electron Physics, 139 (2006) """ if a.ndim != 2 or a.shape[0] != a.shape[1] + 1: raise ValueError("Input must be an (n+1) row x n column, 2-D array") ai = a.copy()[:-1] n = ai.shape[1] f = np.empty((n, n), np.uint32) f[0] = ai.sum(axis=0) for m in range(1, n): # Rolls the pth row of ai right by p places. for row in range(1, ai.shape[0]): ai[row] = roll(ai[row], row) f[m] = ai.sum(axis=0) f += a[-1][newaxis].T f = (f - ai[0].sum()) / n return f scikit-image-0.9.3/skimage/transform/hough_transform.py000066400000000000000000000110521223313777300233120ustar00rootroot00000000000000import numpy as np from scipy import ndimage from skimage import measure, morphology def hough_line_peaks(hspace, angles, dists, min_distance=9, min_angle=10, threshold=None, num_peaks=np.inf): """Return peaks in hough transform. Identifies most prominent lines separated by a certain angle and distance in a hough transform. Non-maximum suppression with different sizes is applied separately in the first (distances) and second (angles) dimension of the hough space to identify peaks. Parameters ---------- hspace : (N, M) array Hough space returned by the `hough_line` function. angles : (M,) array Angles returned by the `hough_line` function. Assumed to be continuous. (`angles[-1] - angles[0] == PI`). dists : (N, ) array Distances returned by the `hough_line` function. min_distance : int Minimum distance separating lines (maximum filter size for first dimension of hough space). min_angle : int Minimum angle separating lines (maximum filter size for second dimension of hough space). threshold : float Minimum intensity of peaks. Default is `0.5 * max(hspace)`. num_peaks : int Maximum number of peaks. When the number of peaks exceeds `num_peaks`, return `num_peaks` coordinates based on peak intensity. Returns ------- hspace, angles, dists : tuple of array Peak values in hough space, angles and distances. Examples -------- >>> import numpy as np >>> from skimage.transform import hough_line, hough_peaks >>> from skimage.draw import line >>> img = np.zeros((15, 15), dtype=np.bool_) >>> rr, cc = line(0, 0, 14, 14) >>> img[rr, cc] = 1 >>> rr, cc = line(0, 14, 14, 0) >>> img[cc, rr] = 1 >>> hspace, angles, dists = hough_line(img) >>> hspace, angles, dists = hough_peaks(hspace, angles, dists) >>> angles array([ 0.74590887, -0.79856126]) >>> dists array([ 10.74418605, 0.51162791]) """ hspace = hspace.copy() rows, cols = hspace.shape if threshold is None: threshold = 0.5 * np.max(hspace) distance_size = 2 * min_distance + 1 angle_size = 2 * min_angle + 1 hspace_max = ndimage.maximum_filter1d(hspace, size=distance_size, axis=0, mode='constant', cval=0) hspace_max = ndimage.maximum_filter1d(hspace_max, size=angle_size, axis=1, mode='constant', cval=0) mask = (hspace == hspace_max) hspace *= mask hspace_t = hspace > threshold label_hspace = morphology.label(hspace_t) props = measure.regionprops(label_hspace, ['Centroid']) coords = np.array([np.round(p['Centroid']) for p in props], dtype=int) hspace_peaks = [] dist_peaks = [] angle_peaks = [] # relative coordinate grid for local neighbourhood suppression dist_ext, angle_ext = np.mgrid[-min_distance:min_distance + 1, -min_angle:min_angle + 1] for dist_idx, angle_idx in coords: accum = hspace[dist_idx, angle_idx] if accum > threshold: # absolute coordinate grid for local neighbourhood suppression dist_nh = dist_idx + dist_ext angle_nh = angle_idx + angle_ext # no reflection for distance neighbourhood dist_in = np.logical_and(dist_nh > 0, dist_nh < rows) dist_nh = dist_nh[dist_in] angle_nh = angle_nh[dist_in] # reflect angles and assume angles are continuous, e.g. # (..., 88, 89, -90, -89, ..., 89, -90, -89, ...) angle_low = angle_nh < 0 dist_nh[angle_low] = rows - dist_nh[angle_low] angle_nh[angle_low] += cols angle_high = angle_nh >= cols dist_nh[angle_high] = rows - dist_nh[angle_high] angle_nh[angle_high] -= cols # suppress neighbourhood hspace[dist_nh, angle_nh] = 0 # add current line to peaks hspace_peaks.append(accum) dist_peaks.append(dists[dist_idx]) angle_peaks.append(angles[angle_idx]) hspace_peaks = np.array(hspace_peaks) dist_peaks = np.array(dist_peaks) angle_peaks = np.array(angle_peaks) if num_peaks < len(hspace_peaks): idx_maxsort = np.argsort(hspace_peaks)[::-1][:num_peaks] hspace_peaks = hspace_peaks[idx_maxsort] dist_peaks = dist_peaks[idx_maxsort] angle_peaks = angle_peaks[idx_maxsort] return hspace_peaks, angle_peaks, dist_peaks scikit-image-0.9.3/skimage/transform/integral.py000066400000000000000000000027071223313777300217210ustar00rootroot00000000000000import numpy as np def integral_image(x): """Integral image / summed area table. The integral image contains the sum of all elements above and to the left of it, i.e.: .. math:: S[m, n] = \sum_{i \leq m} \sum_{j \leq n} X[i, j] Parameters ---------- x : ndarray Input image. Returns ------- S : ndarray Integral image / summed area table. References ---------- .. [1] F.C. Crow, "Summed-area tables for texture mapping," ACM SIGGRAPH Computer Graphics, vol. 18, 1984, pp. 207-212. """ return x.cumsum(1).cumsum(0) def integrate(ii, r0, c0, r1, c1): """Use an integral image to integrate over a given window. Parameters ---------- ii : ndarray Integral image. r0, c0 : int or ndarray Top-left corner(s) of block to be summed. r1, c1 : int or ndarray Bottom-right corner(s) of block to be summed. Returns ------- S : scalar or ndarray Integral (sum) over the given window(s). """ if np.isscalar(r0): r0, c0, r1, c1 = [np.asarray([x]) for x in (r0, c0, r1, c1)] S = np.zeros(r0.shape, ii.dtype) S += ii[r1, c1] good = (r0 >= 1) & (c0 >= 1) S[good] += ii[r0[good] - 1, c0[good] - 1] good = r0 >= 1 S[good] -= ii[r0[good] - 1, c1[good]] good = c0 >= 1 S[good] -= ii[r1[good], c0[good] - 1] if S.size == 1: return np.asscalar(S) return S scikit-image-0.9.3/skimage/transform/pyramids.py000066400000000000000000000232761223313777300217500ustar00rootroot00000000000000import math import numpy as np from scipy import ndimage from skimage.transform import resize from skimage.util import img_as_float def _smooth(image, sigma, mode, cval): """Return image with each channel smoothed by the Gaussian filter.""" smoothed = np.empty(image.shape, dtype=np.double) if image.ndim == 3: # apply Gaussian filter to all dimensions independently for dim in range(image.shape[2]): ndimage.gaussian_filter(image[..., dim], sigma, output=smoothed[..., dim], mode=mode, cval=cval) else: ndimage.gaussian_filter(image, sigma, output=smoothed, mode=mode, cval=cval) return smoothed def _check_factor(factor): if factor <= 1: raise ValueError('scale factor must be greater than 1') def pyramid_reduce(image, downscale=2, sigma=None, order=1, mode='reflect', cval=0): """Smooth and then downsample image. Parameters ---------- image : array Input image. downscale : float, optional Downscale factor. sigma : float, optional Sigma for Gaussian filter. Default is `2 * downscale / 6.0` which corresponds to a filter mask twice the size of the scale factor that covers more than 99% of the Gaussian distribution. order : int, optional Order of splines used in interpolation of downsampling. See `skimage.transform.warp` for detail. mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional The mode parameter determines how the array borders are handled, where cval is the value when mode is equal to 'constant'. cval : float, optional Value to fill past edges of input if mode is 'constant'. Returns ------- out : array Smoothed and downsampled float image. References ---------- .. [1] http://web.mit.edu/persci/people/adelson/pub_pdfs/pyramid83.pdf """ _check_factor(downscale) image = img_as_float(image) rows = image.shape[0] cols = image.shape[1] out_rows = math.ceil(rows / float(downscale)) out_cols = math.ceil(cols / float(downscale)) if sigma is None: # automatically determine sigma which covers > 99% of distribution sigma = 2 * downscale / 6.0 smoothed = _smooth(image, sigma, mode, cval) out = resize(smoothed, (out_rows, out_cols), order=order, mode=mode, cval=cval) return out def pyramid_expand(image, upscale=2, sigma=None, order=1, mode='reflect', cval=0): """Upsample and then smooth image. Parameters ---------- image : array Input image. upscale : float, optional Upscale factor. sigma : float, optional Sigma for Gaussian filter. Default is `2 * upscale / 6.0` which corresponds to a filter mask twice the size of the scale factor that covers more than 99% of the Gaussian distribution. order : int, optional Order of splines used in interpolation of upsampling. See `skimage.transform.warp` for detail. mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional The mode parameter determines how the array borders are handled, where cval is the value when mode is equal to 'constant'. cval : float, optional Value to fill past edges of input if mode is 'constant'. Returns ------- out : array Upsampled and smoothed float image. References ---------- .. [1] http://web.mit.edu/persci/people/adelson/pub_pdfs/pyramid83.pdf """ _check_factor(upscale) image = img_as_float(image) rows = image.shape[0] cols = image.shape[1] out_rows = math.ceil(upscale * rows) out_cols = math.ceil(upscale * cols) if sigma is None: # automatically determine sigma which covers > 99% of distribution sigma = 2 * upscale / 6.0 resized = resize(image, (out_rows, out_cols), order=order, mode=mode, cval=cval) out = _smooth(resized, sigma, mode, cval) return out def pyramid_gaussian(image, max_layer=-1, downscale=2, sigma=None, order=1, mode='reflect', cval=0): """Yield images of the Gaussian pyramid formed by the input image. Recursively applies the `pyramid_reduce` function to the image, and yields the downscaled images. Note that the first image of the pyramid will be the original, unscaled image. The total number of images is `max_layer + 1`. In case all layers are computed, the last image is either a one-pixel image or the image where the reduction does not change its shape. Parameters ---------- image : array Input image. max_layer : int Number of layers for the pyramid. 0th layer is the original image. Default is -1 which builds all possible layers. downscale : float, optional Downscale factor. sigma : float, optional Sigma for Gaussian filter. Default is `2 * downscale / 6.0` which corresponds to a filter mask twice the size of the scale factor that covers more than 99% of the Gaussian distribution. order : int, optional Order of splines used in interpolation of downsampling. See `skimage.transform.warp` for detail. mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional The mode parameter determines how the array borders are handled, where cval is the value when mode is equal to 'constant'. cval : float, optional Value to fill past edges of input if mode is 'constant'. Returns ------- pyramid : generator Generator yielding pyramid layers as float images. References ---------- .. [1] http://web.mit.edu/persci/people/adelson/pub_pdfs/pyramid83.pdf """ _check_factor(downscale) # cast to float for consistent data type in pyramid image = img_as_float(image) layer = 0 rows = image.shape[0] cols = image.shape[1] prev_layer_image = image yield image # build downsampled images until max_layer is reached or downscale process # does not change image size while layer != max_layer: layer += 1 layer_image = pyramid_reduce(prev_layer_image, downscale, sigma, order, mode, cval) prev_rows = rows prev_cols = cols prev_layer_image = layer_image rows = layer_image.shape[0] cols = layer_image.shape[1] # no change to previous pyramid layer if prev_rows == rows and prev_cols == cols: break yield layer_image def pyramid_laplacian(image, max_layer=-1, downscale=2, sigma=None, order=1, mode='reflect', cval=0): """Yield images of the laplacian pyramid formed by the input image. Each layer contains the difference between the downsampled and the downsampled, smoothed image:: layer = resize(prev_layer) - smooth(resize(prev_layer)) Note that the first image of the pyramid will be the difference between the original, unscaled image and its smoothed version. The total number of images is `max_layer + 1`. In case all layers are computed, the last image is either a one-pixel image or the image where the reduction does not change its shape. Parameters ---------- image : array Input image. max_layer : int Number of layers for the pyramid. 0th layer is the original image. Default is -1 which builds all possible layers. downscale : float, optional Downscale factor. sigma : float, optional Sigma for Gaussian filter. Default is `2 * downscale / 6.0` which corresponds to a filter mask twice the size of the scale factor that covers more than 99% of the Gaussian distribution. order : int, optional Order of splines used in interpolation of downsampling. See `skimage.transform.warp` for detail. mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional The mode parameter determines how the array borders are handled, where cval is the value when mode is equal to 'constant'. cval : float, optional Value to fill past edges of input if mode is 'constant'. Returns ------- pyramid : generator Generator yielding pyramid layers as float images. References ---------- .. [1] http://web.mit.edu/persci/people/adelson/pub_pdfs/pyramid83.pdf .. [2] http://sepwww.stanford.edu/~morgan/texturematch/paper_html/node3.html """ _check_factor(downscale) # cast to float for consistent data type in pyramid image = img_as_float(image) if sigma is None: # automatically determine sigma which covers > 99% of distribution sigma = 2 * downscale / 6.0 layer = 0 rows = image.shape[0] cols = image.shape[1] smoothed_image = _smooth(image, sigma, mode, cval) yield image - smoothed_image # build downsampled images until max_layer is reached or downscale process # does not change image size while layer != max_layer: layer += 1 out_rows = math.ceil(rows / float(downscale)) out_cols = math.ceil(cols / float(downscale)) resized_image = resize(smoothed_image, (out_rows, out_cols), order=order, mode=mode, cval=cval) smoothed_image = _smooth(resized_image, sigma, mode, cval) prev_rows = rows prev_cols = cols rows = resized_image.shape[0] cols = resized_image.shape[1] # no change to previous pyramid layer if prev_rows == rows and prev_cols == cols: break yield resized_image - smoothed_image scikit-image-0.9.3/skimage/transform/radon_transform.py000066400000000000000000000430451223313777300233120ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ radon.py - Radon and inverse radon transforms Based on code of Justin K. Romberg (http://www.clear.rice.edu/elec431/projects96/DSP/bpanalysis.html) J. Gillam and Chris Griffin. References: -B.R. Ramesh, N. Srinivasa, K. Rajgopal, "An Algorithm for Computing the Discrete Radon Transform With Some Applications", Proceedings of the Fourth IEEE Region 10 International Conference, TENCON '89, 1989. -A. C. Kak, Malcolm Slaney, "Principles of Computerized Tomographic Imaging", IEEE Press 1988. """ from __future__ import division import numpy as np from scipy.fftpack import fft, ifft, fftfreq from scipy.interpolate import interp1d from ._warps_cy import _warp_fast from ._radon_transform import sart_projection_update from .. import util __all__ = ["radon", "iradon", "iradon_sart"] def radon(image, theta=None, circle=False): """ Calculates the radon transform of an image given specified projection angles. Parameters ---------- image : array_like, dtype=float Input image. The rotation axis will be located in the pixel with indices ``(image.shape[0] // 2, image.shape[1] // 2)``. theta : array_like, dtype=float, optional (default np.arange(180)) Projection angles (in degrees). circle : boolean, optional Assume image is zero outside the inscribed circle, making the width of each projection (the first dimension of the sinogram) equal to ``min(image.shape)``. Returns ------- radon_image : ndarray Radon transform (sinogram). The tomography rotation axis will lie at the pixel index ``radon_image.shape[0] // 2`` along the 0th dimension of ``radon_image``. Raises ------ ValueError If called with ``circle=True`` and ``image != 0`` outside the inscribed circle """ if image.ndim != 2: raise ValueError('The input image must be 2-D') if theta is None: theta = np.arange(180) if circle: radius = min(image.shape) // 2 c0, c1 = np.ogrid[0:image.shape[0], 0:image.shape[1]] reconstruction_circle = ((c0 - image.shape[0] // 2)**2 + (c1 - image.shape[1] // 2)**2) <= radius**2 if not np.all(reconstruction_circle | (image == 0)): raise ValueError('Image must be zero outside the reconstruction' ' circle') # Crop image to make it square slices = [] for d in (0, 1): if image.shape[d] > min(image.shape): excess = image.shape[d] - min(image.shape) slices.append(slice(int(np.ceil(excess / 2)), int(np.ceil(excess / 2) + min(image.shape)))) else: slices.append(slice(None)) slices = tuple(slices) padded_image = image[slices] else: diagonal = np.sqrt(2) * max(image.shape) pad = [int(np.ceil(diagonal - s)) for s in image.shape] new_center = [(s + p) // 2 for s, p in zip(image.shape, pad)] old_center = [s // 2 for s in image.shape] pad_before = [nc - oc for oc, nc in zip(old_center, new_center)] pad_width = [(pb, p - pb) for pb, p in zip(pad_before, pad)] padded_image = util.pad(image, pad_width, mode='constant', constant_values=0) # padded_image is always square assert padded_image.shape[0] == padded_image.shape[1] radon_image = np.zeros((padded_image.shape[0], len(theta))) center = padded_image.shape[0] // 2 shift0 = np.array([[1, 0, -center], [0, 1, -center], [0, 0, 1]]) shift1 = np.array([[1, 0, center], [0, 1, center], [0, 0, 1]]) def build_rotation(theta): T = np.deg2rad(theta) R = np.array([[np.cos(T), np.sin(T), 0], [-np.sin(T), np.cos(T), 0], [0, 0, 1]]) return shift1.dot(R).dot(shift0) for i in range(len(theta)): rotated = _warp_fast(padded_image, build_rotation(theta[i])) radon_image[:, i] = rotated.sum(0) return radon_image def _sinogram_circle_to_square(sinogram): diagonal = int(np.ceil(np.sqrt(2) * sinogram.shape[0])) pad = diagonal - sinogram.shape[0] old_center = sinogram.shape[0] // 2 new_center = diagonal // 2 pad_before = new_center - old_center pad_width = ((pad_before, pad - pad_before), (0, 0)) return util.pad(sinogram, pad_width, mode='constant', constant_values=0) def iradon(radon_image, theta=None, output_size=None, filter="ramp", interpolation="linear", circle=False): """ Inverse radon transform. Reconstruct an image from the radon transform, using the filtered back projection algorithm. Parameters ---------- radon_image : array_like, dtype=float Image containing radon transform (sinogram). Each column of the image corresponds to a projection along a different angle. The tomography rotation axis should lie at the pixel index ``radon_image.shape[0] // 2`` along the 0th dimension of ``radon_image``. theta : array_like, dtype=float, optional Reconstruction angles (in degrees). Default: m angles evenly spaced between 0 and 180 (if the shape of `radon_image` is (N, M)). output_size : int Number of rows and columns in the reconstruction. filter : str, optional (default ramp) Filter used in frequency domain filtering. Ramp filter used by default. Filters available: ramp, shepp-logan, cosine, hamming, hann. Assign None to use no filter. interpolation : str, optional (default 'linear') Interpolation method used in reconstruction. Methods available: 'linear', 'nearest', and 'cubic' ('cubic' is slow). circle : boolean, optional Assume the reconstructed image is zero outside the inscribed circle. Also changes the default output_size to match the behaviour of ``radon`` called with ``circle=True``. Returns ------- reconstructed : ndarray Reconstructed image. The rotation axis will be located in the pixel with indices ``(reconstructed.shape[0] // 2, reconstructed.shape[1] // 2)``. Notes ----- It applies the Fourier slice theorem to reconstruct an image by multiplying the frequency domain of the filter with the FFT of the projection data. This algorithm is called filtered back projection. """ if radon_image.ndim != 2: raise ValueError('The input image must be 2-D') if theta is None: m, n = radon_image.shape theta = np.linspace(0, 180, n, endpoint=False) else: theta = np.asarray(theta) if len(theta) != radon_image.shape[1]: raise ValueError("The given ``theta`` does not match the number of " "projections in ``radon_image``.") interpolation_types = ('linear', 'nearest', 'cubic') if not interpolation in interpolation_types: raise ValueError("Unknown interpolation: %s" % interpolation) if not output_size: # If output size not specified, estimate from input radon image if circle: output_size = radon_image.shape[0] else: output_size = int(np.floor(np.sqrt((radon_image.shape[0])**2 / 2.0))) if circle: radon_image = _sinogram_circle_to_square(radon_image) th = (np.pi / 180.0) * theta # resize image to next power of two (but no less than 64) for # Fourier analysis; speeds up Fourier and lessens artifacts projection_size_padded = \ max(64, int(2**np.ceil(np.log2(2 * radon_image.shape[0])))) pad_width = ((0, projection_size_padded - radon_image.shape[0]), (0, 0)) img = util.pad(radon_image, pad_width, mode='constant', constant_values=0) # Construct the Fourier filter f = fftfreq(projection_size_padded).reshape(-1, 1) # digital frequency omega = 2 * np.pi * f # angular frequency fourier_filter = 2 * np.abs(f) # ramp filter if filter == "ramp": pass elif filter == "shepp-logan": # Start from first element to avoid divide by zero fourier_filter[1:] = fourier_filter[1:] * np.sin(omega[1:]) / omega[1:] elif filter == "cosine": fourier_filter *= np.cos(omega) elif filter == "hamming": fourier_filter *= (0.54 + 0.46 * np.cos(omega / 2)) elif filter == "hann": fourier_filter *= (1 + np.cos(omega / 2)) / 2 elif filter is None: fourier_filter[:] = 1 else: raise ValueError("Unknown filter: %s" % filter) # Apply filter in Fourier domain projection = fft(img, axis=0) * fourier_filter radon_filtered = np.real(ifft(projection, axis=0)) # Resize filtered image back to original size radon_filtered = radon_filtered[:radon_image.shape[0], :] reconstructed = np.zeros((output_size, output_size)) # Determine the center of the projections (= center of sinogram) mid_index = radon_image.shape[0] // 2 [X, Y] = np.mgrid[0:output_size, 0:output_size] xpr = X - int(output_size) // 2 ypr = Y - int(output_size) // 2 # Reconstruct image by interpolation for i in range(len(theta)): t = ypr * np.cos(th[i]) - xpr * np.sin(th[i]) x = np.arange(radon_filtered.shape[0]) - mid_index if interpolation == 'linear': backprojected = np.interp(t, x, radon_filtered[:, i], left=0, right=0) else: interpolant = interp1d(x, radon_filtered[:, i], kind=interpolation, bounds_error=False, fill_value=0) backprojected = interpolant(t) reconstructed += backprojected if circle: radius = output_size // 2 reconstruction_circle = (xpr**2 + ypr**2) <= radius**2 reconstructed[~reconstruction_circle] = 0. return reconstructed * np.pi / (2 * len(th)) def order_angles_golden_ratio(theta): """ Order angles to reduce the amount of correlated information in subsequent projections. Parameters ---------- theta : 1D array of floats Projection angles in degrees. Duplicate angles are not allowed. Returns ------- indices_generator : generator yielding unsigned integers The returned generator yields indices into ``theta`` such that ``theta[indices]`` gives the approximate golden ratio ordering of the projections. In total, ``len(theta)`` indices are yielded. All non-negative integers < ``len(theta)`` are yielded exactly once. Notes ----- The method used here is that of the golden ratio introduced by T. Kohler. References ---------- .. [1] Kohler, T. "A projection access scheme for iterative reconstruction based on the golden section." Nuclear Science Symposium Conference Record, 2004 IEEE. Vol. 6. IEEE, 2004. .. [2] Winkelmann, Stefanie, et al. "An optimal radial profile order based on the Golden Ratio for time-resolved MRI." Medical Imaging, IEEE Transactions on 26.1 (2007): 68-76. """ interval = 180 def angle_distance(a, b): difference = a - b return min(abs(difference % interval), abs(difference % -interval)) remaining = list(np.argsort(theta)) # indices into theta # yield an arbitrary angle to start things off index = remaining.pop(0) angle = theta[index] yield index # determine subsequent angles using the golden ratio method angle_increment = interval * (1 - (np.sqrt(5) - 1) / 2) while remaining: angle = (angle + angle_increment) % interval insert_point = np.searchsorted(theta[remaining], angle) index_below = insert_point - 1 index_above = 0 if insert_point == len(remaining) else insert_point distance_below = angle_distance(angle, theta[remaining[index_below]]) distance_above = angle_distance(angle, theta[remaining[index_above]]) if distance_below < distance_above: yield remaining.pop(index_below) else: yield remaining.pop(index_above) def iradon_sart(radon_image, theta=None, image=None, projection_shifts=None, clip=None, relaxation=0.15): """ Inverse radon transform Reconstruct an image from the radon transform, using a single iteration of the Simultaneous Algebraic Reconstruction Technique (SART) algorithm. Parameters ---------- radon_image : 2D array, dtype=float Image containing radon transform (sinogram). Each column of the image corresponds to a projection along a different angle. The tomography rotation axis should lie at the pixel index ``radon_image.shape[0] // 2`` along the 0th dimension of ``radon_image``. theta : 1D array, dtype=float, optional Reconstruction angles (in degrees). Default: m angles evenly spaced between 0 and 180 (if the shape of `radon_image` is (N, M)). image : 2D array, dtype=float, optional Image containing an initial reconstruction estimate. Shape of this array should be ``(radon_image.shape[0], radon_image.shape[0])``. The default is an array of zeros. projection_shifts : 1D array, dtype=float Shift the projections contained in ``radon_image`` (the sinogram) by this many pixels before reconstructing the image. The i'th value defines the shift of the i'th column of ``radon_image``. clip : length-2 sequence of floats Force all values in the reconstructed tomogram to lie in the range ``[clip[0], clip[1]]`` relaxation : float Relaxation parameter for the update step. A higher value can improve the convergence rate, but one runs the risk of instabilities. Values close to or higher than 1 are not recommended. Returns ------- reconstructed : ndarray Reconstructed image. The rotation axis will be located in the pixel with indices ``(reconstructed.shape[0] // 2, reconstructed.shape[1] // 2)``. Notes ----- Algebraic Reconstruction Techniques are based on formulating the tomography reconstruction problem as a set of linear equations. Along each ray, the projected value is the sum of all the values of the cross section along the ray. A typical feature of SART (and a few other variants of algebraic techniques) is that it samples the cross section at equidistant points along the ray, using linear interpolation between the pixel values of the cross section. The resulting set of linear equations are then solved using a slightly modified Kaczmarz method. When using SART, a single iteration is usually sufficient to obtain a good reconstruction. Further iterations will tend to enhance high-frequency information, but will also often increase the noise. References ---------- .. [1] AC Kak, M Slaney, "Principles of Computerized Tomographic Imaging", IEEE Press 1988. .. [2] AH Andersen, AC Kak, "Simultaneous algebraic reconstruction technique (SART): a superior implementation of the ART algorithm", Ultrasonic Imaging 6 pp 81--94 (1984) .. [3] S Kaczmarz, "Angenäherte auflösung von systemen linearer gleichungen", Bulletin International de l’Academie Polonaise des Sciences et des Lettres 35 pp 355--357 (1937) .. [4] Kohler, T. "A projection access scheme for iterative reconstruction based on the golden section." Nuclear Science Symposium Conference Record, 2004 IEEE. Vol. 6. IEEE, 2004. .. [5] Kaczmarz' method, Wikipedia, http://en.wikipedia.org/wiki/Kaczmarz_method """ if radon_image.ndim != 2: raise ValueError('radon_image must be two dimensional') reconstructed_shape = (radon_image.shape[0], radon_image.shape[0]) if theta is None: theta = np.linspace(0, 180, radon_image.shape[1], endpoint=False) elif theta.shape != (radon_image.shape[1],): raise ValueError('Shape of theta (%s) does not match the ' 'number of projections (%d)' % (projection_shifts.shape, radon_image.shape[1])) if image is None: image = np.zeros(reconstructed_shape, dtype=np.float) elif image.shape != reconstructed_shape: raise ValueError('Shape of image (%s) does not match first dimension ' 'of radon_image (%s)' % (image.shape, reconstructed_shape)) if projection_shifts is None: projection_shifts = np.zeros((radon_image.shape[1],), dtype=np.float) elif projection_shifts.shape != (radon_image.shape[1],): raise ValueError('Shape of projection_shifts (%s) does not match the ' 'number of projections (%d)' % (projection_shifts.shape, radon_image.shape[1])) if not clip is None: if len(clip) != 2: raise ValueError('clip must be a length-2 sequence') clip = (float(clip[0]), float(clip[1])) relaxation = float(relaxation) for angle_index in order_angles_golden_ratio(theta): image_update = sart_projection_update(image, theta[angle_index], radon_image[:, angle_index], projection_shifts[angle_index]) image += relaxation * image_update if not clip is None: image = np.clip(image, clip[0], clip[1]) return image scikit-image-0.9.3/skimage/transform/setup.py000066400000000000000000000026421223313777300212520ustar00rootroot00000000000000#!/usr/bin/env python import os from skimage._build import cython base_path = os.path.abspath(os.path.dirname(__file__)) def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs config = Configuration('transform', parent_package, top_path) config.add_data_dir('tests') cython(['_hough_transform.pyx'], working_path=base_path) cython(['_warps_cy.pyx'], working_path=base_path) cython(['_radon_transform.pyx'], working_path=base_path) config.add_extension('_hough_transform', sources=['_hough_transform.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_warps_cy', sources=['_warps_cy.c'], include_dirs=[get_numpy_include_dirs(), '../_shared']) config.add_extension('_radon_transform', sources=['_radon_transform.c'], include_dirs=[get_numpy_include_dirs()]) return config if __name__ == '__main__': from numpy.distutils.core import setup setup(maintainer='scikit-image Developers', author='scikit-image Developers', maintainer_email='scikit-image@googlegroups.com', description='Transforms', url='https://github.com/scikit-image/scikit-image', license='SciPy License (BSD Style)', **(configuration(top_path='').todict()) ) scikit-image-0.9.3/skimage/transform/tests/000077500000000000000000000000001223313777300206765ustar00rootroot00000000000000scikit-image-0.9.3/skimage/transform/tests/test_finite_radon_transform.py000066400000000000000000000007561223313777300270530ustar00rootroot00000000000000import numpy as np from skimage.transform import frt2, ifrt2 def test_frt(): SIZE = 59 try: import sympy.ntheory as sn assert sn.isprime(SIZE) == True except ImportError: pass # Generate a test image L = np.tri(SIZE, dtype=np.int32) + np.tri(SIZE, dtype=np.int32)[::-1] f = frt2(L) fi = ifrt2(f) assert len(np.nonzero(L - fi)[0]) == 0 if __name__ == '__main__': from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/transform/tests/test_geometric.py000066400000000000000000000132241223313777300242670ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_equal, assert_array_almost_equal from skimage.transform._geometric import _stackcopy from skimage.transform import (estimate_transform, SimilarityTransform, AffineTransform, ProjectiveTransform, PolynomialTransform, PiecewiseAffineTransform) SRC = np.array([ [-12.3705, -10.5075], [-10.7865, 15.4305], [8.6985, 10.8675], [11.4975, -9.5715], [7.8435, 7.4835], [-5.3325, 6.5025], [6.7905, -6.3765], [-6.1695, -0.8235], ]) DST = np.array([ [0, 0], [0, 5800], [4900, 5800], [4900, 0], [4479, 4580], [1176, 3660], [3754, 790], [1024, 1931], ]) def test_stackcopy(): layers = 4 x = np.empty((3, 3, layers)) y = np.eye(3, 3) _stackcopy(x, y) for i in range(layers): assert_array_almost_equal(x[..., i], y) def test_similarity_estimation(): # exact solution tform = estimate_transform('similarity', SRC[:2, :], DST[:2, :]) assert_array_almost_equal(tform(SRC[:2, :]), DST[:2, :]) assert_equal(tform._matrix[0, 0], tform._matrix[1, 1]) assert_equal(tform._matrix[0, 1], - tform._matrix[1, 0]) # over-determined tform2 = estimate_transform('similarity', SRC, DST) assert_array_almost_equal(tform2.inverse(tform2(SRC)), SRC) assert_equal(tform2._matrix[0, 0], tform2._matrix[1, 1]) assert_equal(tform2._matrix[0, 1], - tform2._matrix[1, 0]) # via estimate method tform3 = SimilarityTransform() tform3.estimate(SRC, DST) assert_array_almost_equal(tform3._matrix, tform2._matrix) def test_similarity_init(): # init with implicit parameters scale = 0.1 rotation = 1 translation = (1, 1) tform = SimilarityTransform(scale=scale, rotation=rotation, translation=translation) assert_array_almost_equal(tform.scale, scale) assert_array_almost_equal(tform.rotation, rotation) assert_array_almost_equal(tform.translation, translation) # init with transformation matrix tform2 = SimilarityTransform(tform._matrix) assert_array_almost_equal(tform2.scale, scale) assert_array_almost_equal(tform2.rotation, rotation) assert_array_almost_equal(tform2.translation, translation) def test_affine_estimation(): # exact solution tform = estimate_transform('affine', SRC[:3, :], DST[:3, :]) assert_array_almost_equal(tform(SRC[:3, :]), DST[:3, :]) # over-determined tform2 = estimate_transform('affine', SRC, DST) assert_array_almost_equal(tform2.inverse(tform2(SRC)), SRC) # via estimate method tform3 = AffineTransform() tform3.estimate(SRC, DST) assert_array_almost_equal(tform3._matrix, tform2._matrix) def test_affine_init(): # init with implicit parameters scale = (0.1, 0.13) rotation = 1 shear = 0.1 translation = (1, 1) tform = AffineTransform(scale=scale, rotation=rotation, shear=shear, translation=translation) assert_array_almost_equal(tform.scale, scale) assert_array_almost_equal(tform.rotation, rotation) assert_array_almost_equal(tform.shear, shear) assert_array_almost_equal(tform.translation, translation) # init with transformation matrix tform2 = AffineTransform(tform._matrix) assert_array_almost_equal(tform2.scale, scale) assert_array_almost_equal(tform2.rotation, rotation) assert_array_almost_equal(tform2.shear, shear) assert_array_almost_equal(tform2.translation, translation) def test_piecewise_affine(): tform = PiecewiseAffineTransform() tform.estimate(SRC, DST) # make sure each single affine transform is exactly estimated assert_array_almost_equal(tform(SRC), DST) assert_array_almost_equal(tform.inverse(DST), SRC) def test_projective_estimation(): # exact solution tform = estimate_transform('projective', SRC[:4, :], DST[:4, :]) assert_array_almost_equal(tform(SRC[:4, :]), DST[:4, :]) # over-determined tform2 = estimate_transform('projective', SRC, DST) assert_array_almost_equal(tform2.inverse(tform2(SRC)), SRC) # via estimate method tform3 = ProjectiveTransform() tform3.estimate(SRC, DST) assert_array_almost_equal(tform3._matrix, tform2._matrix) def test_projective_init(): tform = estimate_transform('projective', SRC, DST) # init with transformation matrix tform2 = ProjectiveTransform(tform._matrix) assert_array_almost_equal(tform2._matrix, tform._matrix) def test_polynomial_estimation(): # over-determined tform = estimate_transform('polynomial', SRC, DST, order=10) assert_array_almost_equal(tform(SRC), DST, 6) # via estimate method tform2 = PolynomialTransform() tform2.estimate(SRC, DST, order=10) assert_array_almost_equal(tform2._params, tform._params) def test_polynomial_init(): tform = estimate_transform('polynomial', SRC, DST, order=10) # init with transformation parameters tform2 = PolynomialTransform(tform._params) assert_array_almost_equal(tform2._params, tform._params) def test_polynomial_default_order(): tform = estimate_transform('polynomial', SRC, DST) tform2 = estimate_transform('polynomial', SRC, DST, order=2) assert_array_almost_equal(tform2._params, tform._params) def test_union(): tform1 = SimilarityTransform(scale=0.1, rotation=0.3) tform2 = SimilarityTransform(scale=0.1, rotation=0.9) tform3 = SimilarityTransform(scale=0.1 ** 2, rotation=0.3 + 0.9) tform = tform1 + tform2 assert_array_almost_equal(tform._matrix, tform3._matrix) if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/transform/tests/test_hough_transform.py000066400000000000000000000272361223313777300255260ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_almost_equal, assert_equal import skimage.transform as tf from skimage.draw import line, circle_perimeter, ellipse_perimeter def append_desc(func, description): """Append the test function ``func`` and append ``description`` to its name. """ func.description = func.__module__ + '.' + func.__name__ + description return func def test_hough_line(): # Generate a test image img = np.zeros((100, 150), dtype=int) rr, cc = line(60, 130, 80, 10) img[rr, cc] = 1 out, angles, d = tf.hough_line(img) y, x = np.where(out == out.max()) dist = d[y[0]] theta = angles[x[0]] assert_almost_equal(dist, 80.723, 1) assert_almost_equal(theta, 1.41, 1) def test_hough_line_angles(): img = np.zeros((10, 10)) img[0, 0] = 1 out, angles, d = tf.hough_line(img, np.linspace(0, 360, 10)) assert_equal(len(angles), 10) def test_probabilistic_hough(): # Generate a test image img = np.zeros((100, 100), dtype=int) for i in range(25, 75): img[100 - i, i] = 100 img[i, i] = 100 # decrease default theta sampling because similar orientations may confuse # as mentioned in article of Galambos et al theta = np.linspace(0, np.pi, 45) lines = tf.probabilistic_hough_line(img, threshold=10, line_length=10, line_gap=1, theta=theta) # sort the lines according to the x-axis sorted_lines = [] for line in lines: line = list(line) line.sort(key=lambda x: x[0]) sorted_lines.append(line) assert([(25, 75), (74, 26)] in sorted_lines) assert([(25, 25), (74, 74)] in sorted_lines) def test_hough_line_peaks(): img = np.zeros((100, 150), dtype=int) rr, cc = line(60, 130, 80, 10) img[rr, cc] = 1 out, angles, d = tf.hough_line(img) out, theta, dist = tf.hough_line_peaks(out, angles, d) assert_equal(len(dist), 1) assert_almost_equal(dist[0], 80.723, 1) assert_almost_equal(theta[0], 1.41, 1) def test_hough_line_peaks_dist(): img = np.zeros((100, 100), dtype=np.bool_) img[:, 30] = True img[:, 40] = True hspace, angles, dists = tf.hough_line(img) assert len(tf.hough_line_peaks(hspace, angles, dists, min_distance=5)[0]) == 2 assert len(tf.hough_line_peaks(hspace, angles, dists, min_distance=15)[0]) == 1 def test_hough_line_peaks_angle(): img = np.zeros((100, 100), dtype=np.bool_) img[:, 0] = True img[0, :] = True hspace, angles, dists = tf.hough_line(img) assert len(tf.hough_line_peaks(hspace, angles, dists, min_angle=45)[0]) == 2 assert len(tf.hough_line_peaks(hspace, angles, dists, min_angle=90)[0]) == 1 theta = np.linspace(0, np.pi, 100) hspace, angles, dists = tf.hough_line(img, theta) assert len(tf.hough_line_peaks(hspace, angles, dists, min_angle=45)[0]) == 2 assert len(tf.hough_line_peaks(hspace, angles, dists, min_angle=90)[0]) == 1 theta = np.linspace(np.pi / 3, 4. / 3 * np.pi, 100) hspace, angles, dists = tf.hough_line(img, theta) assert len(tf.hough_line_peaks(hspace, angles, dists, min_angle=45)[0]) == 2 assert len(tf.hough_line_peaks(hspace, angles, dists, min_angle=90)[0]) == 1 def test_hough_line_peaks_num(): img = np.zeros((100, 100), dtype=np.bool_) img[:, 30] = True img[:, 40] = True hspace, angles, dists = tf.hough_line(img) assert len(tf.hough_line_peaks(hspace, angles, dists, min_distance=0, min_angle=0, num_peaks=1)[0]) == 1 def test_hough_circle(): # Prepare picture img = np.zeros((120, 100), dtype=int) radius = 20 x_0, y_0 = (99, 50) y, x = circle_perimeter(y_0, x_0, radius) img[x, y] = 1 out = tf.hough_circle(img, np.array([radius], dtype=np.intp)) x, y = np.where(out[0] == out[0].max()) assert_equal(x[0], x_0) assert_equal(y[0], y_0) def test_hough_circle_extended(): # Prepare picture # The circle center is outside the image img = np.zeros((100, 100), dtype=int) radius = 20 x_0, y_0 = (-5, 50) y, x = circle_perimeter(y_0, x_0, radius) img[x[np.where(x > 0)], y[np.where(x > 0)]] = 1 out = tf.hough_circle(img, np.array([radius], dtype=np.intp), full_output=True) x, y = np.where(out[0] == out[0].max()) # Offset for x_0, y_0 assert_equal(x[0], x_0 + radius) assert_equal(y[0], y_0 + radius) def test_hough_ellipse_zero_angle(): img = np.zeros((25, 25), dtype=int) rx = 6 ry = 8 x0 = 12 y0 = 15 angle = 0 rr, cc = ellipse_perimeter(y0, x0, ry, rx) img[rr, cc] = 1 result = tf.hough_ellipse(img, threshold=9) best = result[-1] assert_equal(best[1], y0) assert_equal(best[2], x0) assert_almost_equal(best[3], ry, decimal=1) assert_almost_equal(best[4], rx, decimal=1) assert_equal(best[5], angle) # Check if I re-draw the ellipse, points are the same! # ie check API compatibility between hough_ellipse and ellipse_perimeter rr2, cc2 = ellipse_perimeter(y0, x0, int(best[3]), int(best[4]), orientation=best[5]) assert_equal(rr, rr2) assert_equal(cc, cc2) def test_hough_ellipse_non_zero_posangle1(): # ry > rx, angle in [0:pi/2] img = np.zeros((30, 24), dtype=int) rx = 6 ry = 12 x0 = 10 y0 = 15 angle = np.pi / 1.35 rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle) img[rr, cc] = 1 result = tf.hough_ellipse(img, threshold=15, accuracy=3) result.sort(order='accumulator') best = result[-1] assert_almost_equal(best[1] / 100., y0 / 100., decimal=1) assert_almost_equal(best[2] / 100., x0 / 100., decimal=1) assert_almost_equal(best[3] / 10., ry / 10., decimal=1) assert_almost_equal(best[4] / 100., rx / 100., decimal=1) assert_almost_equal(best[5], angle, decimal=1) # Check if I re-draw the ellipse, points are the same! # ie check API compatibility between hough_ellipse and ellipse_perimeter rr2, cc2 = ellipse_perimeter(y0, x0, int(best[3]), int(best[4]), orientation=best[5]) assert_equal(rr, rr2) assert_equal(cc, cc2) def test_hough_ellipse_non_zero_posangle2(): # ry < rx, angle in [0:pi/2] img = np.zeros((30, 24), dtype=int) rx = 12 ry = 6 x0 = 10 y0 = 15 angle = np.pi / 1.35 rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle) img[rr, cc] = 1 result = tf.hough_ellipse(img, threshold=15, accuracy=3) result.sort(order='accumulator') best = result[-1] assert_almost_equal(best[1] / 100., y0 / 100., decimal=1) assert_almost_equal(best[2] / 100., x0 / 100., decimal=1) assert_almost_equal(best[3] / 10., ry / 10., decimal=1) assert_almost_equal(best[4] / 100., rx / 100., decimal=1) assert_almost_equal(best[5], angle, decimal=1) # Check if I re-draw the ellipse, points are the same! # ie check API compatibility between hough_ellipse and ellipse_perimeter rr2, cc2 = ellipse_perimeter(y0, x0, int(best[3]), int(best[4]), orientation=best[5]) assert_equal(rr, rr2) assert_equal(cc, cc2) def test_hough_ellipse_non_zero_posangle3(): # ry < rx, angle in [pi/2:pi] img = np.zeros((30, 24), dtype=int) rx = 12 ry = 6 x0 = 10 y0 = 15 angle = np.pi / 1.35 + np.pi / 2. rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle) img[rr, cc] = 1 result = tf.hough_ellipse(img, threshold=15, accuracy=3) result.sort(order='accumulator') best = result[-1] # Check if I re-draw the ellipse, points are the same! # ie check API compatibility between hough_ellipse and ellipse_perimeter rr2, cc2 = ellipse_perimeter(y0, x0, int(best[3]), int(best[4]), orientation=best[5]) assert_equal(rr, rr2) assert_equal(cc, cc2) def test_hough_ellipse_non_zero_posangle4(): # ry < rx, angle in [pi:3pi/4] img = np.zeros((30, 24), dtype=int) rx = 12 ry = 6 x0 = 10 y0 = 15 angle = np.pi / 1.35 + np.pi rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle) img[rr, cc] = 1 result = tf.hough_ellipse(img, threshold=15, accuracy=3) result.sort(order='accumulator') best = result[-1] # Check if I re-draw the ellipse, points are the same! # ie check API compatibility between hough_ellipse and ellipse_perimeter rr2, cc2 = ellipse_perimeter(y0, x0, int(best[3]), int(best[4]), orientation=best[5]) assert_equal(rr, rr2) assert_equal(cc, cc2) def test_hough_ellipse_non_zero_negangle1(): # ry > rx, angle in [0:-pi/2] img = np.zeros((30, 24), dtype=int) rx = 6 ry = 12 x0 = 10 y0 = 15 angle = - np.pi / 1.35 rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle) img[rr, cc] = 1 result = tf.hough_ellipse(img, threshold=15, accuracy=3) result.sort(order='accumulator') best = result[-1] # Check if I re-draw the ellipse, points are the same! # ie check API compatibility between hough_ellipse and ellipse_perimeter rr2, cc2 = ellipse_perimeter(y0, x0, int(best[3]), int(best[4]), orientation=best[5]) assert_equal(rr, rr2) assert_equal(cc, cc2) def test_hough_ellipse_non_zero_negangle2(): # ry < rx, angle in [0:-pi/2] img = np.zeros((30, 24), dtype=int) rx = 12 ry = 6 x0 = 10 y0 = 15 angle = - np.pi / 1.35 rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle) img[rr, cc] = 1 result = tf.hough_ellipse(img, threshold=15, accuracy=3) result.sort(order='accumulator') best = result[-1] # Check if I re-draw the ellipse, points are the same! # ie check API compatibility between hough_ellipse and ellipse_perimeter rr2, cc2 = ellipse_perimeter(y0, x0, int(best[3]), int(best[4]), orientation=best[5]) assert_equal(rr, rr2) assert_equal(cc, cc2) def test_hough_ellipse_non_zero_negangle3(): # ry < rx, angle in [-pi/2:-pi] img = np.zeros((30, 24), dtype=int) rx = 12 ry = 6 x0 = 10 y0 = 15 angle = - np.pi / 1.35 - np.pi / 2. rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle) img[rr, cc] = 1 result = tf.hough_ellipse(img, threshold=15, accuracy=3) result.sort(order='accumulator') best = result[-1] # Check if I re-draw the ellipse, points are the same! # ie check API compatibility between hough_ellipse and ellipse_perimeter rr2, cc2 = ellipse_perimeter(y0, x0, int(best[3]), int(best[4]), orientation=best[5]) assert_equal(rr, rr2) assert_equal(cc, cc2) def test_hough_ellipse_non_zero_negangle4(): # ry < rx, angle in [-pi:-3pi/4] img = np.zeros((30, 24), dtype=int) rx = 12 ry = 6 x0 = 10 y0 = 15 angle = - np.pi / 1.35 - np.pi rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle) img[rr, cc] = 1 result = tf.hough_ellipse(img, threshold=15, accuracy=3) result.sort(order='accumulator') best = result[-1] # Check if I re-draw the ellipse, points are the same! # ie check API compatibility between hough_ellipse and ellipse_perimeter rr2, cc2 = ellipse_perimeter(y0, x0, int(best[3]), int(best[4]), orientation=best[5]) assert_equal(rr, rr2) assert_equal(cc, cc2) if __name__ == "__main__": np.testing.run_module_suite() scikit-image-0.9.3/skimage/transform/tests/test_integral.py000066400000000000000000000027061223313777300241210ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_equal from skimage.transform import integral_image, integrate x = (np.random.random((50, 50)) * 255).astype(np.uint8) s = integral_image(x) def test_validity(): y = np.arange(12).reshape((4, 3)) y = (np.random.random((50, 50)) * 255).astype(np.uint8) assert_equal(integral_image(y)[-1, -1], y.sum()) def test_basic(): assert_equal(x[12:24, 10:20].sum(), integrate(s, 12, 10, 23, 19)) assert_equal(x[:20, :20].sum(), integrate(s, 0, 0, 19, 19)) assert_equal(x[:20, 10:20].sum(), integrate(s, 0, 10, 19, 19)) assert_equal(x[10:20, :20].sum(), integrate(s, 10, 0, 19, 19)) def test_single(): assert_equal(x[0, 0], integrate(s, 0, 0, 0, 0)) assert_equal(x[10, 10], integrate(s, 10, 10, 10, 10)) def test_vectorized_integrate(): r0 = np.array([12, 0, 0, 10, 0, 10, 30]) c0 = np.array([10, 0, 10, 0, 0, 10, 31]) r1 = np.array([23, 19, 19, 19, 0, 10, 49]) c1 = np.array([19, 19, 19, 19, 0, 10, 49]) expected = np.array([x[12:24, 10:20].sum(), x[:20, :20].sum(), x[:20, 10:20].sum(), x[10:20, :20].sum(), x[0,0], x[10, 10], x[30:, 31:].sum()]) assert_equal(expected, integrate(s, r0, c0, r1, c1)) if __name__ == '__main__': from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/transform/tests/test_pyramids.py000066400000000000000000000043711223313777300241440ustar00rootroot00000000000000from numpy.testing import assert_array_equal, assert_raises, run_module_suite from skimage import data from skimage.transform import pyramids image = data.lena() image_gray = image[..., 0] def test_pyramid_reduce_rgb(): rows, cols, dim = image.shape out = pyramids.pyramid_reduce(image, downscale=2) assert_array_equal(out.shape, (rows / 2, cols / 2, dim)) def test_pyramid_reduce_gray(): rows, cols = image_gray.shape out = pyramids.pyramid_reduce(image_gray, downscale=2) assert_array_equal(out.shape, (rows / 2, cols / 2)) def test_pyramid_expand_rgb(): rows, cols, dim = image.shape out = pyramids.pyramid_expand(image, upscale=2) assert_array_equal(out.shape, (rows * 2, cols * 2, dim)) def test_pyramid_expand_gray(): rows, cols = image_gray.shape out = pyramids.pyramid_expand(image_gray, upscale=2) assert_array_equal(out.shape, (rows * 2, cols * 2)) def test_build_gaussian_pyramid_rgb(): rows, cols, dim = image.shape pyramid = pyramids.pyramid_gaussian(image, downscale=2) for layer, out in enumerate(pyramid): layer_shape = (rows / 2 ** layer, cols / 2 ** layer, dim) assert_array_equal(out.shape, layer_shape) def test_build_gaussian_pyramid_gray(): rows, cols = image_gray.shape pyramid = pyramids.pyramid_gaussian(image_gray, downscale=2) for layer, out in enumerate(pyramid): layer_shape = (rows / 2 ** layer, cols / 2 ** layer) assert_array_equal(out.shape, layer_shape) def test_build_laplacian_pyramid_rgb(): rows, cols, dim = image.shape pyramid = pyramids.pyramid_laplacian(image, downscale=2) for layer, out in enumerate(pyramid): layer_shape = (rows / 2 ** layer, cols / 2 ** layer, dim) assert_array_equal(out.shape, layer_shape) def test_build_laplacian_pyramid_gray(): rows, cols = image_gray.shape pyramid = pyramids.pyramid_laplacian(image_gray, downscale=2) for layer, out in enumerate(pyramid): layer_shape = (rows / 2 ** layer, cols / 2 ** layer) assert_array_equal(out.shape, layer_shape) def test_check_factor(): assert_raises(ValueError, pyramids._check_factor, 0.99) assert_raises(ValueError, pyramids._check_factor, - 2) if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/transform/tests/test_radon_transform.py000066400000000000000000000343371223313777300255170ustar00rootroot00000000000000from __future__ import print_function, division import numpy as np from numpy.testing import assert_raises import itertools import os.path from skimage.transform import radon, iradon from skimage.io import imread from skimage import data_dir __PHANTOM = imread(os.path.join(data_dir, "phantom.png"), as_grey=True)[::2, ::2] def _get_phantom(): return __PHANTOM def _debug_plot(original, result, sinogram=None): from matplotlib import pyplot as plt imkwargs = dict(cmap='gray', interpolation='nearest') if sinogram is None: plt.figure(figsize=(15, 6)) sp = 130 else: plt.figure(figsize=(11, 11)) sp = 221 plt.subplot(sp + 0) plt.imshow(sinogram, aspect='auto', **imkwargs) plt.subplot(sp + 1) plt.imshow(original, **imkwargs) plt.subplot(sp + 2) plt.imshow(result, vmin=original.min(), vmax=original.max(), **imkwargs) plt.subplot(sp + 3) plt.imshow(result - original, **imkwargs) plt.colorbar() plt.show() def rescale(x): x = x.astype(float) x -= x.min() x /= x.max() return x def check_radon_center(shape, circle): # Create a test image with only a single non-zero pixel at the origin image = np.zeros(shape, dtype=np.float) image[(shape[0] // 2, shape[1] // 2)] = 1. # Calculate the sinogram theta = np.linspace(0., 180., max(shape), endpoint=False) sinogram = radon(image, theta=theta, circle=circle) # The sinogram should be a straight, horizontal line sinogram_max = np.argmax(sinogram, axis=0) print(sinogram_max) assert np.std(sinogram_max) < 1e-6 def test_radon_center(): shapes = [(16, 16), (17, 17)] circles = [False, True] for shape, circle in itertools.product(shapes, circles): yield check_radon_center, shape, circle rectangular_shapes = [(32, 16), (33, 17)] for shape in rectangular_shapes: yield check_radon_center, shape, False def check_iradon_center(size, theta, circle): debug = False # Create a test sinogram corresponding to a single projection # with a single non-zero pixel at the rotation center if circle: sinogram = np.zeros((size, 1), dtype=np.float) sinogram[size // 2, 0] = 1. else: diagonal = int(np.ceil(np.sqrt(2) * size)) sinogram = np.zeros((diagonal, 1), dtype=np.float) sinogram[sinogram.shape[0] // 2, 0] = 1. maxpoint = np.unravel_index(np.argmax(sinogram), sinogram.shape) print('shape of generated sinogram', sinogram.shape) print('maximum in generated sinogram', maxpoint) # Compare reconstructions for theta=angle and theta=angle + 180; # these should be exactly equal reconstruction = iradon(sinogram, theta=[theta], circle=circle) reconstruction_opposite = iradon(sinogram, theta=[theta + 180], circle=circle) print('rms deviance:', np.sqrt(np.mean((reconstruction_opposite - reconstruction)**2))) if debug: import matplotlib.pyplot as plt imkwargs = dict(cmap='gray', interpolation='nearest') plt.figure() plt.subplot(221) plt.imshow(sinogram, **imkwargs) plt.subplot(222) plt.imshow(reconstruction_opposite - reconstruction, **imkwargs) plt.subplot(223) plt.imshow(reconstruction, **imkwargs) plt.subplot(224) plt.imshow(reconstruction_opposite, **imkwargs) plt.show() assert np.allclose(reconstruction, reconstruction_opposite) def test_iradon_center(): sizes = [16, 17] thetas = [0, 90] circles = [False, True] for size, theta, circle in itertools.product(sizes, thetas, circles): yield check_iradon_center, size, theta, circle def check_radon_iradon(interpolation_type, filter_type): debug = False image = _get_phantom() reconstructed = iradon(radon(image), filter=filter_type, interpolation=interpolation_type) delta = np.mean(np.abs(image - reconstructed)) print('\n\tmean error:', delta) if debug: _debug_plot(image, reconstructed) if filter_type in ('ramp', 'shepp-logan'): if interpolation_type == 'nearest': allowed_delta = 0.03 else: allowed_delta = 0.02 else: allowed_delta = 0.05 assert delta < allowed_delta def test_radon_iradon(): filter_types = ["ramp", "shepp-logan", "cosine", "hamming", "hann"] interpolation_types = ['linear', 'nearest'] for interpolation_type, filter_type in \ itertools.product(interpolation_types, filter_types): yield check_radon_iradon, interpolation_type, filter_type # cubic interpolation is slow; only run one test for it yield check_radon_iradon, 'cubic', 'shepp-logan' def test_iradon_angles(): """ Test with different number of projections """ size = 100 # Synthetic data image = np.tri(size) + np.tri(size)[::-1] # Large number of projections: a good quality is expected nb_angles = 200 radon_image_200 = radon(image, theta=np.linspace(0, 180, nb_angles, endpoint=False)) reconstructed = iradon(radon_image_200) delta_200 = np.mean(abs(rescale(image) - rescale(reconstructed))) assert delta_200 < 0.03 # Lower number of projections nb_angles = 80 radon_image_80 = radon(image, theta=np.linspace(0, 180, nb_angles, endpoint=False)) # Test whether the sum of all projections is approximately the same s = radon_image_80.sum(axis=0) assert np.allclose(s, s[0], rtol=0.01) reconstructed = iradon(radon_image_80) delta_80 = np.mean(abs(image / np.max(image) - reconstructed / np.max(reconstructed))) # Loss of quality when the number of projections is reduced assert delta_80 > delta_200 def check_radon_iradon_minimal(shape, slices): debug = False theta = np.arange(180) image = np.zeros(shape, dtype=np.float) image[slices] = 1. sinogram = radon(image, theta) reconstructed = iradon(sinogram, theta) print('\n\tMaximum deviation:', np.max(np.abs(image - reconstructed))) if debug: _debug_plot(image, reconstructed, sinogram) if image.sum() == 1: assert (np.unravel_index(np.argmax(reconstructed), image.shape) == np.unravel_index(np.argmax(image), image.shape)) def test_radon_iradon_minimal(): shapes = [(3, 3), (4, 4), (5, 5)] for shape in shapes: c0, c1 = shape[0] // 2, shape[1] // 2 coordinates = itertools.product((c0 - 1, c0, c0 + 1), (c1 - 1, c1, c1 + 1)) for coordinate in coordinates: yield check_radon_iradon_minimal, shape, coordinate def test_reconstruct_with_wrong_angles(): a = np.zeros((3, 3)) p = radon(a, theta=[0, 1, 2]) iradon(p, theta=[0, 1, 2]) assert_raises(ValueError, iradon, p, theta=[0, 1, 2, 3]) def _random_circle(shape): # Synthetic random data, zero outside reconstruction circle np.random.seed(98312871) image = np.random.rand(*shape) c0, c1 = np.ogrid[0:shape[0], 0:shape[1]] r = np.sqrt((c0 - shape[0] // 2)**2 + (c1 - shape[1] // 2)**2) radius = min(shape) // 2 image[r > radius] = 0. return image def test_radon_circle(): a = np.ones((10, 10)) assert_raises(ValueError, radon, a, circle=True) # Synthetic data, circular symmetry shape = (61, 79) c0, c1 = np.ogrid[0:shape[0], 0:shape[1]] r = np.sqrt((c0 - shape[0] // 2)**2 + (c1 - shape[1] // 2)**2) radius = min(shape) // 2 image = np.clip(radius - r, 0, np.inf) image = rescale(image) angles = np.linspace(0, 180, min(shape), endpoint=False) sinogram = radon(image, theta=angles, circle=True) assert np.all(sinogram.std(axis=1) < 1e-2) # Synthetic data, random image = _random_circle(shape) sinogram = radon(image, theta=angles, circle=True) mass = sinogram.sum(axis=0) average_mass = mass.mean() relative_error = np.abs(mass - average_mass) / average_mass print(relative_error.max(), relative_error.mean()) assert np.all(relative_error < 3.2e-3) def check_sinogram_circle_to_square(size): from skimage.transform.radon_transform import _sinogram_circle_to_square image = _random_circle((size, size)) theta = np.linspace(0., 180., size, False) sinogram_circle = radon(image, theta, circle=True) argmax_shape = lambda a: np.unravel_index(np.argmax(a), a.shape) print('\n\targmax of circle:', argmax_shape(sinogram_circle)) sinogram_square = radon(image, theta, circle=False) print('\targmax of square:', argmax_shape(sinogram_square)) sinogram_circle_to_square = _sinogram_circle_to_square(sinogram_circle) print('\targmax of circle to square:', argmax_shape(sinogram_circle_to_square)) error = abs(sinogram_square - sinogram_circle_to_square) print(np.mean(error), np.max(error)) assert (argmax_shape(sinogram_square) == argmax_shape(sinogram_circle_to_square)) def test_sinogram_circle_to_square(): for size in (50, 51): yield check_sinogram_circle_to_square, size def check_radon_iradon_circle(interpolation, shape, output_size): # Forward and inverse radon on synthetic data image = _random_circle(shape) radius = min(shape) // 2 sinogram_rectangle = radon(image, circle=False) reconstruction_rectangle = iradon(sinogram_rectangle, output_size=output_size, interpolation=interpolation, circle=False) sinogram_circle = radon(image, circle=True) reconstruction_circle = iradon(sinogram_circle, output_size=output_size, interpolation=interpolation, circle=True) # Crop rectangular reconstruction to match circle=True reconstruction width = reconstruction_circle.shape[0] excess = int(np.ceil((reconstruction_rectangle.shape[0] - width) / 2)) s = np.s_[excess:width + excess, excess:width + excess] reconstruction_rectangle = reconstruction_rectangle[s] # Find the reconstruction circle, set reconstruction to zero outside c0, c1 = np.ogrid[0:width, 0:width] r = np.sqrt((c0 - width // 2)**2 + (c1 - width // 2)**2) reconstruction_rectangle[r > radius] = 0. print(reconstruction_circle.shape) print(reconstruction_rectangle.shape) np.allclose(reconstruction_rectangle, reconstruction_circle) def test_radon_iradon_circle(): shape = (61, 79) interpolations = ('nearest', 'linear') output_sizes = (None, min(shape), max(shape), 97) for interpolation, output_size in itertools.product(interpolations, output_sizes): yield check_radon_iradon_circle, interpolation, shape, output_size def test_order_angles_golden_ratio(): from skimage.transform.radon_transform import order_angles_golden_ratio np.random.seed(1231) lengths = [1, 4, 10, 180] for l in lengths: theta_ordered = np.linspace(0, 180, l, endpoint=False) theta_random = np.random.uniform(0, 180, l) for theta in (theta_random, theta_ordered): indices = [x for x in order_angles_golden_ratio(theta)] # no duplicate indices allowed assert len(indices) == len(set(indices)) def test_iradon_sart(): from skimage.io import imread from skimage import data_dir from skimage.transform import rescale, radon, iradon_sart debug = False shepp_logan = imread(os.path.join(data_dir, "phantom.png"), as_grey=True) image = rescale(shepp_logan, scale=0.4) theta_ordered = np.linspace(0., 180., image.shape[0], endpoint=False) theta_missing_wedge = np.linspace(0., 150., image.shape[0], endpoint=True) for theta, error_factor in ((theta_ordered, 1.), (theta_missing_wedge, 2.)): sinogram = radon(image, theta, circle=True) reconstructed = iradon_sart(sinogram, theta) if debug: from matplotlib import pyplot as plt plt.figure() plt.subplot(221) plt.imshow(image, interpolation='nearest') plt.subplot(222) plt.imshow(sinogram, interpolation='nearest') plt.subplot(223) plt.imshow(reconstructed, interpolation='nearest') plt.subplot(224) plt.imshow(reconstructed - image, interpolation='nearest') plt.show() delta = np.mean(np.abs(reconstructed - image)) print('delta (1 iteration) =', delta) assert delta < 0.016 * error_factor reconstructed = iradon_sart(sinogram, theta, reconstructed) delta = np.mean(np.abs(reconstructed - image)) print('delta (2 iterations) =', delta) assert delta < 0.013 * error_factor reconstructed = iradon_sart(sinogram, theta, clip=(0, 1)) delta = np.mean(np.abs(reconstructed - image)) print('delta (1 iteration, clip) =', delta) assert delta < 0.015 * error_factor np.random.seed(1239867) shifts = np.random.uniform(-3, 3, sinogram.shape[1]) x = np.arange(sinogram.shape[0]) sinogram_shifted = np.vstack(np.interp(x + shifts[i], x, sinogram[:, i]) for i in range(sinogram.shape[1])).T reconstructed = iradon_sart(sinogram_shifted, theta, projection_shifts=shifts) if debug: from matplotlib import pyplot as plt plt.figure() plt.subplot(221) plt.imshow(image, interpolation='nearest') plt.subplot(222) plt.imshow(sinogram_shifted, interpolation='nearest') plt.subplot(223) plt.imshow(reconstructed, interpolation='nearest') plt.subplot(224) plt.imshow(reconstructed - image, interpolation='nearest') plt.show() delta = np.mean(np.abs(reconstructed - image)) print('delta (1 iteration, shifted sinogram) =', delta) assert delta < 0.018 * error_factor if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() scikit-image-0.9.3/skimage/transform/tests/test_warps.py000066400000000000000000000155721223313777300234550ustar00rootroot00000000000000from numpy.testing import assert_array_almost_equal, run_module_suite, assert_array_equal import numpy as np from scipy.ndimage import map_coordinates from skimage.transform import (warp, warp_coords, rotate, resize, rescale, AffineTransform, ProjectiveTransform, SimilarityTransform, downscale_local_mean) from skimage import transform as tf, data, img_as_float from skimage.color import rgb2gray def test_warp_tform(): x = np.zeros((5, 5), dtype=np.double) x[2, 2] = 1 theta = - np.pi / 2 tform = SimilarityTransform(scale=1, rotation=theta, translation=(0, 4)) x90 = warp(x, tform, order=1) assert_array_almost_equal(x90, np.rot90(x)) x90 = warp(x, tform.inverse, order=1) assert_array_almost_equal(x90, np.rot90(x)) def test_warp_callable(): x = np.zeros((5, 5), dtype=np.double) x[2, 2] = 1 refx = np.zeros((5, 5), dtype=np.double) refx[1, 1] = 1 shift = lambda xy: xy + 1 outx = warp(x, shift, order=1) assert_array_almost_equal(outx, refx) def test_warp_matrix(): x = np.zeros((5, 5), dtype=np.double) x[2, 2] = 1 refx = np.zeros((5, 5), dtype=np.double) refx[1, 1] = 1 matrix = np.array([[1, 0, 1], [0, 1, 1], [0, 0, 1]]) # _warp_fast outx = warp(x, matrix, order=1) assert_array_almost_equal(outx, refx) # check for ndimage.map_coordinates outx = warp(x, matrix, order=5) def test_homography(): x = np.zeros((5, 5), dtype=np.double) x[1, 1] = 1 theta = -np.pi / 2 M = np.array([[np.cos(theta), - np.sin(theta), 0], [np.sin(theta), np.cos(theta), 4], [0, 0, 1]]) x90 = warp(x, inverse_map=ProjectiveTransform(M).inverse, order=1) assert_array_almost_equal(x90, np.rot90(x)) def test_fast_homography(): img = rgb2gray(data.lena()).astype(np.uint8) img = img[:, :100] theta = np.deg2rad(30) scale = 0.5 tx, ty = 50, 50 H = np.eye(3) S = scale * np.sin(theta) C = scale * np.cos(theta) H[:2, :2] = [[C, -S], [S, C]] H[:2, 2] = [tx, ty] tform = ProjectiveTransform(H) coords = warp_coords(tform.inverse, (img.shape[0], img.shape[1])) for order in range(4): for mode in ('constant', 'reflect', 'wrap', 'nearest'): p0 = map_coordinates(img, coords, mode=mode, order=order) p1 = warp(img, tform, mode=mode, order=order) # import matplotlib.pyplot as plt # f, (ax0, ax1, ax2, ax3) = plt.subplots(1, 4) # ax0.imshow(img) # ax1.imshow(p0, cmap=plt.cm.gray) # ax2.imshow(p1, cmap=plt.cm.gray) # ax3.imshow(np.abs(p0 - p1), cmap=plt.cm.gray) # plt.show() d = np.mean(np.abs(p0 - p1)) assert d < 0.001 def test_rotate(): x = np.zeros((5, 5), dtype=np.double) x[1, 1] = 1 x90 = rotate(x, 90) assert_array_almost_equal(x90, np.rot90(x)) def test_rotate_resize(): x = np.zeros((10, 10), dtype=np.double) x45 = rotate(x, 45, resize=False) assert x45.shape == (10, 10) x45 = rotate(x, 45, resize=True) # new dimension should be d = sqrt(2 * (10/2)^2) assert x45.shape == (14, 14) def test_rescale(): # same scale factor x = np.zeros((5, 5), dtype=np.double) x[1, 1] = 1 scaled = rescale(x, 2, order=0) ref = np.zeros((10, 10)) ref[2:4, 2:4] = 1 assert_array_almost_equal(scaled, ref) # different scale factors x = np.zeros((5, 5), dtype=np.double) x[1, 1] = 1 scaled = rescale(x, (2, 1), order=0) ref = np.zeros((10, 5)) ref[2:4, 1] = 1 assert_array_almost_equal(scaled, ref) def test_resize2d(): x = np.zeros((5, 5), dtype=np.double) x[1, 1] = 1 resized = resize(x, (10, 10), order=0) ref = np.zeros((10, 10)) ref[2:4, 2:4] = 1 assert_array_almost_equal(resized, ref) def test_resize3d_keep(): # keep 3rd dimension x = np.zeros((5, 5, 3), dtype=np.double) x[1, 1, :] = 1 resized = resize(x, (10, 10), order=0) ref = np.zeros((10, 10, 3)) ref[2:4, 2:4, :] = 1 assert_array_almost_equal(resized, ref) resized = resize(x, (10, 10, 3), order=0) assert_array_almost_equal(resized, ref) def test_resize3d_resize(): # resize 3rd dimension x = np.zeros((5, 5, 3), dtype=np.double) x[1, 1, :] = 1 resized = resize(x, (10, 10, 1), order=0) ref = np.zeros((10, 10, 1)) ref[2:4, 2:4] = 1 assert_array_almost_equal(resized, ref) def test_resize3d_bilinear(): # bilinear 3rd dimension x = np.zeros((5, 5, 2), dtype=np.double) x[1, 1, 0] = 0 x[1, 1, 1] = 1 resized = resize(x, (10, 10, 1), order=1) ref = np.zeros((10, 10, 1)) ref[1:5, 1:5, :] = 0.03125 ref[1:5, 2:4, :] = 0.09375 ref[2:4, 1:5, :] = 0.09375 ref[2:4, 2:4, :] = 0.28125 assert_array_almost_equal(resized, ref) def test_swirl(): image = img_as_float(data.checkerboard()) swirl_params = {'radius': 80, 'rotation': 0, 'order': 2, 'mode': 'reflect'} swirled = tf.swirl(image, strength=10, **swirl_params) unswirled = tf.swirl(swirled, strength=-10, **swirl_params) assert np.mean(np.abs(image - unswirled)) < 0.01 def test_const_cval_out_of_range(): img = np.random.randn(100, 100) cval = - 10 warped = warp(img, AffineTransform(translation=(10, 10)), cval=cval) assert np.sum(warped == cval) == (2 * 100 * 10 - 10 * 10) def test_warp_identity(): lena = img_as_float(rgb2gray(data.lena())) assert len(lena.shape) == 2 assert np.allclose(lena, warp(lena, AffineTransform(rotation=0))) assert not np.allclose(lena, warp(lena, AffineTransform(rotation=0.1))) rgb_lena = np.transpose(np.asarray([lena, np.zeros_like(lena), lena]), (1, 2, 0)) warped_rgb_lena = warp(rgb_lena, AffineTransform(rotation=0.1)) assert np.allclose(rgb_lena, warp(rgb_lena, AffineTransform(rotation=0))) assert not np.allclose(rgb_lena, warped_rgb_lena) # assert no cross-talk between bands assert np.all(0 == warped_rgb_lena[:, :, 1]) def test_warp_coords_example(): image = data.lena().astype(np.float32) assert 3 == image.shape[2] tform = SimilarityTransform(translation=(0, -10)) coords = warp_coords(tform, (30, 30, 3)) map_coordinates(image[:, :, 0], coords[:2]) def test_downscale_local_mean(): image1 = np.arange(4 * 6).reshape(4, 6) out1 = downscale_local_mean(image1, (2, 3)) expected1 = np.array([[ 4., 7.], [ 16., 19.]]) assert_array_equal(expected1, out1) image2 = np.arange(5 * 8).reshape(5, 8) out2 = downscale_local_mean(image2, (4, 5)) expected2 = np.array([[ 14. , 10.8], [ 8.5, 5.7]]) assert_array_equal(expected2, out2) if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/util/000077500000000000000000000000001223313777300164765ustar00rootroot00000000000000scikit-image-0.9.3/skimage/util/__init__.py000066400000000000000000000014601223313777300206100ustar00rootroot00000000000000from .dtype import (img_as_float, img_as_int, img_as_uint, img_as_ubyte, img_as_bool, dtype_limits) from .shape import view_as_blocks, view_as_windows from .noise import random_noise import numpy ver = numpy.__version__.split('.') chk = int(ver[0] + ver[1]) if chk < 18: # Use internal version for numpy versions < 1.8.x from .arraypad import pad else: from numpy import pad del numpy, ver, chk from ._regular_grid import regular_grid from .unique import unique_rows __all__ = ['img_as_float', 'img_as_int', 'img_as_uint', 'img_as_ubyte', 'img_as_bool', 'dtype_limits', 'view_as_blocks', 'view_as_windows', 'pad', 'random_noise', 'regular_grid', 'unique_rows'] scikit-image-0.9.3/skimage/util/_regular_grid.py000066400000000000000000000046451223313777300216660ustar00rootroot00000000000000import numpy as np def regular_grid(ar_shape, n_points): """Find `n_points` regularly spaced along `ar_shape`. The returned points (as slices) should be as close to cubically-spaced as possible. Essentially, the points are spaced by the Nth root of the input array size, where N is the number of dimensions. However, if an array dimension cannot fit a full step size, it is "discarded", and the computation is done for only the remaining dimensions. Parameters ---------- ar_shape : array-like of ints The shape of the space embedding the grid. ``len(ar_shape)`` is the number of dimensions. n_points : int The (approximate) number of points to embed in the space. Returns ------- slices : list of slice objects A slice along each dimension of `ar_shape`, such that the intersection of all the slices give the coordinates of regularly spaced points. Examples -------- >>> ar = np.zeros((20, 40)) >>> g = regular_grid(ar.shape, 8) >>> g [slice(5.0, None, 10.0), slice(5.0, None, 10.0)] >>> ar[g] = 1 >>> ar.sum() 8.0 >>> ar = np.zeros((20, 40)) >>> g = regular_grid(ar.shape, 32) >>> g [slice(2.0, None, 5.0), slice(2.0, None, 5.0)] >>> ar[g] = 1 >>> ar.sum() 32.0 >>> ar = np.zeros((3, 20, 40)) >>> g = regular_grid(ar.shape, 8) >>> g [slice(1.0, None, 3.0), slice(5.0, None, 10.0), slice(5.0, None, 10.0)] >>> ar[g] = 1 >>> ar.sum() 8.0 """ ar_shape = np.asanyarray(ar_shape) ndim = len(ar_shape) unsort_dim_idxs = np.argsort(np.argsort(ar_shape)) sorted_dims = np.sort(ar_shape) space_size = float(np.prod(ar_shape)) if space_size <= n_points: return [slice(None)] * ndim stepsizes = (space_size / n_points) ** (1.0 / ndim) * np.ones(ndim) if (sorted_dims < stepsizes).any(): for dim in range(ndim): stepsizes[dim] = sorted_dims[dim] space_size = float(np.prod(sorted_dims[dim+1:])) stepsizes[dim+1:] = ((space_size / n_points) ** (1.0 / (ndim - dim - 1))) if (sorted_dims >= stepsizes).all(): break starts = stepsizes // 2 stepsizes = np.round(stepsizes) slices = [slice(start, None, step) for start, step in zip(starts, stepsizes)] slices = [slices[i] for i in unsort_dim_idxs] return slices scikit-image-0.9.3/skimage/util/arraypad.py000066400000000000000000001446041223313777300206640ustar00rootroot00000000000000""" The arraypad module contains a group of functions to pad values onto the edges of an n-dimensional array. """ from __future__ import division, absolute_import, print_function from skimage._shared.six import integer_types import numpy as np try: # Available on 2.x at base, Py3 requires this compatibility import. # Later versions of NumPy have this for 2.x as well. from numpy.compat import long except: pass __all__ = ['pad'] ############################################################################### # Private utility functions. def _arange_ndarray(arr, shape, axis, reverse=False): """ Create an ndarray of `shape` with increments along specified `axis` Parameters ---------- arr : ndarray Input array of arbitrary shape. shape : tuple of ints Shape of desired array. Should be equivalent to `arr.shape` except `shape[axis]` which may have any positive value. axis : int Axis to increment along. reverse : bool If False, increment in a positive fashion from 1 to `shape[axis]`, inclusive. If True, the bounds are the same but the order reversed. Returns ------- padarr : ndarray Output array sized to pad `arr` along `axis`, with linear range from 1 to `shape[axis]` along specified `axis`. Notes ----- The range is deliberately 1-indexed for this specific use case. Think of this algorithm as broadcasting `np.arange` to a single `axis` of an arbitrarily shaped ndarray. """ initshape = tuple(1 if i != axis else shape[axis] for (i, x) in enumerate(arr.shape)) if not reverse: padarr = np.arange(1, shape[axis] + 1) else: padarr = np.arange(shape[axis], 0, -1) padarr = padarr.reshape(initshape) for i, dim in enumerate(shape): if padarr.shape[i] != dim: padarr = padarr.repeat(dim, axis=i) return padarr def _round_ifneeded(arr, dtype): """ Rounds arr inplace if destination dtype is integer. Parameters ---------- arr : ndarray Input array. dtype : dtype The dtype of the destination array. """ if np.issubdtype(dtype, np.integer): arr.round(out=arr) def _prepend_const(arr, pad_amt, val, axis=-1): """ Prepend constant `val` along `axis` of `arr`. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to prepend. val : scalar Constant value to use. For best results should be of type `arr.dtype`; if not `arr.dtype` will be cast to `arr.dtype`. axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt` constant `val` prepended along `axis`. """ if pad_amt == 0: return arr padshape = tuple(x if i != axis else pad_amt for (i, x) in enumerate(arr.shape)) if val == 0: return np.concatenate((np.zeros(padshape, dtype=arr.dtype), arr), axis=axis) else: return np.concatenate(((np.zeros(padshape) + val).astype(arr.dtype), arr), axis=axis) def _append_const(arr, pad_amt, val, axis=-1): """ Append constant `val` along `axis` of `arr`. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to append. val : scalar Constant value to use. For best results should be of type `arr.dtype`; if not `arr.dtype` will be cast to `arr.dtype`. axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt` constant `val` appended along `axis`. """ if pad_amt == 0: return arr padshape = tuple(x if i != axis else pad_amt for (i, x) in enumerate(arr.shape)) if val == 0: return np.concatenate((arr, np.zeros(padshape, dtype=arr.dtype)), axis=axis) else: return np.concatenate( (arr, (np.zeros(padshape) + val).astype(arr.dtype)), axis=axis) def _prepend_edge(arr, pad_amt, axis=-1): """ Prepend `pad_amt` to `arr` along `axis` by extending edge values. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to prepend. axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, extended by `pad_amt` edge values appended along `axis`. """ if pad_amt == 0: return arr edge_slice = tuple(slice(None) if i != axis else 0 for (i, x) in enumerate(arr.shape)) # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) edge_arr = arr[edge_slice].reshape(pad_singleton) return np.concatenate((edge_arr.repeat(pad_amt, axis=axis), arr), axis=axis) def _append_edge(arr, pad_amt, axis=-1): """ Append `pad_amt` to `arr` along `axis` by extending edge values. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to append. axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, extended by `pad_amt` edge values prepended along `axis`. """ if pad_amt == 0: return arr edge_slice = tuple(slice(None) if i != axis else arr.shape[axis] - 1 for (i, x) in enumerate(arr.shape)) # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) edge_arr = arr[edge_slice].reshape(pad_singleton) return np.concatenate((arr, edge_arr.repeat(pad_amt, axis=axis)), axis=axis) def _prepend_ramp(arr, pad_amt, end, axis=-1): """ Prepend linear ramp along `axis`. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to prepend. end : scalar Constal value to use. For best results should be of type `arr.dtype`; if not `arr.dtype` will be cast to `arr.dtype`. axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt` values prepended along `axis`. The prepended region ramps linearly from the edge value to `end`. """ if pad_amt == 0: return arr # Generate shape for final concatenated array padshape = tuple(x if i != axis else pad_amt for (i, x) in enumerate(arr.shape)) # Generate an n-dimensional array incrementing along `axis` ramp_arr = _arange_ndarray(arr, padshape, axis, reverse=True).astype(np.float64) # Appropriate slicing to extract n-dimensional edge along `axis` edge_slice = tuple(slice(None) if i != axis else 0 for (i, x) in enumerate(arr.shape)) # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) # Extract edge, reshape to original rank, and extend along `axis` edge_pad = arr[edge_slice].reshape(pad_singleton).repeat(pad_amt, axis) # Linear ramp slope = (end - edge_pad) / float(pad_amt) ramp_arr = ramp_arr * slope ramp_arr += edge_pad _round_ifneeded(ramp_arr, arr.dtype) # Ramp values will most likely be float, cast them to the same type as arr return np.concatenate((ramp_arr.astype(arr.dtype), arr), axis=axis) def _append_ramp(arr, pad_amt, end, axis=-1): """ Append linear ramp along `axis`. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to append. end : scalar Constal value to use. For best results should be of type `arr.dtype`; if not `arr.dtype` will be cast to `arr.dtype`. axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt` values appended along `axis`. The appended region ramps linearly from the edge value to `end`. """ if pad_amt == 0: return arr # Generate shape for final concatenated array padshape = tuple(x if i != axis else pad_amt for (i, x) in enumerate(arr.shape)) # Generate an n-dimensional array incrementing along `axis` ramp_arr = _arange_ndarray(arr, padshape, axis, reverse=False).astype(np.float64) # Slice a chunk from the edge to calculate stats on edge_slice = tuple(slice(None) if i != axis else -1 for (i, x) in enumerate(arr.shape)) # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) # Extract edge, reshape to original rank, and extend along `axis` edge_pad = arr[edge_slice].reshape(pad_singleton).repeat(pad_amt, axis) # Linear ramp slope = (end - edge_pad) / float(pad_amt) ramp_arr = ramp_arr * slope ramp_arr += edge_pad _round_ifneeded(ramp_arr, arr.dtype) # Ramp values will most likely be float, cast them to the same type as arr return np.concatenate((arr, ramp_arr.astype(arr.dtype)), axis=axis) def _prepend_max(arr, pad_amt, num, axis=-1): """ Prepend `pad_amt` maximum values along `axis`. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to prepend. num : int Depth into `arr` along `axis` to calculate maximum. Range: [1, `arr.shape[axis]`] or None (entire axis) axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt` values appended along `axis`. The prepended region is the maximum of the first `num` values along `axis`. """ if pad_amt == 0: return arr # Equivalent to edge padding for single value, so do that instead if num == 1: return _prepend_edge(arr, pad_amt, axis) # Use entire array if `num` is too large if num is not None: if num >= arr.shape[axis]: num = None # Slice a chunk from the edge to calculate stats on max_slice = tuple(slice(None) if i != axis else slice(num) for (i, x) in enumerate(arr.shape)) # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) # Extract slice, calculate max, reshape to add singleton dimension back max_chunk = arr[max_slice].max(axis=axis).reshape(pad_singleton) # Concatenate `arr` with `max_chunk`, extended along `axis` by `pad_amt` return np.concatenate((max_chunk.repeat(pad_amt, axis=axis), arr), axis=axis) def _append_max(arr, pad_amt, num, axis=-1): """ Pad one `axis` of `arr` with the maximum of the last `num` elements. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to append. num : int Depth into `arr` along `axis` to calculate maximum. Range: [1, `arr.shape[axis]`] or None (entire axis) axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt` values appended along `axis`. The appended region is the maximum of the final `num` values along `axis`. """ if pad_amt == 0: return arr # Equivalent to edge padding for single value, so do that instead if num == 1: return _append_edge(arr, pad_amt, axis) # Use entire array if `num` is too large if num is not None: if num >= arr.shape[axis]: num = None # Slice a chunk from the edge to calculate stats on end = arr.shape[axis] - 1 if num is not None: max_slice = tuple( slice(None) if i != axis else slice(end, end - num, -1) for (i, x) in enumerate(arr.shape)) else: max_slice = tuple(slice(None) for x in arr.shape) # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) # Extract slice, calculate max, reshape to add singleton dimension back max_chunk = arr[max_slice].max(axis=axis).reshape(pad_singleton) # Concatenate `arr` with `max_chunk`, extended along `axis` by `pad_amt` return np.concatenate((arr, max_chunk.repeat(pad_amt, axis=axis)), axis=axis) def _prepend_mean(arr, pad_amt, num, axis=-1): """ Prepend `pad_amt` mean values along `axis`. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to prepend. num : int Depth into `arr` along `axis` to calculate mean. Range: [1, `arr.shape[axis]`] or None (entire axis) axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt` values prepended along `axis`. The prepended region is the mean of the first `num` values along `axis`. """ if pad_amt == 0: return arr # Equivalent to edge padding for single value, so do that instead if num == 1: return _prepend_edge(arr, pad_amt, axis) # Use entire array if `num` is too large if num is not None: if num >= arr.shape[axis]: num = None # Slice a chunk from the edge to calculate stats on mean_slice = tuple(slice(None) if i != axis else slice(num) for (i, x) in enumerate(arr.shape)) # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) # Extract slice, calculate mean, reshape to add singleton dimension back mean_chunk = arr[mean_slice].mean(axis).reshape(pad_singleton) _round_ifneeded(mean_chunk, arr.dtype) # Concatenate `arr` with `mean_chunk`, extended along `axis` by `pad_amt` return np.concatenate((mean_chunk.repeat(pad_amt, axis).astype(arr.dtype), arr), axis=axis) def _append_mean(arr, pad_amt, num, axis=-1): """ Append `pad_amt` mean values along `axis`. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to append. num : int Depth into `arr` along `axis` to calculate mean. Range: [1, `arr.shape[axis]`] or None (entire axis) axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt` values appended along `axis`. The appended region is the maximum of the final `num` values along `axis`. """ if pad_amt == 0: return arr # Equivalent to edge padding for single value, so do that instead if num == 1: return _append_edge(arr, pad_amt, axis) # Use entire array if `num` is too large if num is not None: if num >= arr.shape[axis]: num = None # Slice a chunk from the edge to calculate stats on end = arr.shape[axis] - 1 if num is not None: mean_slice = tuple( slice(None) if i != axis else slice(end, end - num, -1) for (i, x) in enumerate(arr.shape)) else: mean_slice = tuple(slice(None) for x in arr.shape) # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) # Extract slice, calculate mean, reshape to add singleton dimension back mean_chunk = arr[mean_slice].mean(axis=axis).reshape(pad_singleton) _round_ifneeded(mean_chunk, arr.dtype) # Concatenate `arr` with `mean_chunk`, extended along `axis` by `pad_amt` return np.concatenate( (arr, mean_chunk.repeat(pad_amt, axis).astype(arr.dtype)), axis=axis) def _prepend_med(arr, pad_amt, num, axis=-1): """ Prepend `pad_amt` median values along `axis`. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to prepend. num : int Depth into `arr` along `axis` to calculate median. Range: [1, `arr.shape[axis]`] or None (entire axis) axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt` values prepended along `axis`. The prepended region is the median of the first `num` values along `axis`. """ if pad_amt == 0: return arr # Equivalent to edge padding for single value, so do that instead if num == 1: return _prepend_edge(arr, pad_amt, axis) # Use entire array if `num` is too large if num is not None: if num >= arr.shape[axis]: num = None # Slice a chunk from the edge to calculate stats on med_slice = tuple(slice(None) if i != axis else slice(num) for (i, x) in enumerate(arr.shape)) # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) # Extract slice, calculate median, reshape to add singleton dimension back med_chunk = np.median(arr[med_slice], axis=axis).reshape(pad_singleton) _round_ifneeded(med_chunk, arr.dtype) # Concatenate `arr` with `med_chunk`, extended along `axis` by `pad_amt` return np.concatenate( (med_chunk.repeat(pad_amt, axis).astype(arr.dtype), arr), axis=axis) def _append_med(arr, pad_amt, num, axis=-1): """ Append `pad_amt` median values along `axis`. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to append. num : int Depth into `arr` along `axis` to calculate median. Range: [1, `arr.shape[axis]`] or None (entire axis) axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt` values appended along `axis`. The appended region is the median of the final `num` values along `axis`. """ if pad_amt == 0: return arr # Equivalent to edge padding for single value, so do that instead if num == 1: return _append_edge(arr, pad_amt, axis) # Use entire array if `num` is too large if num is not None: if num >= arr.shape[axis]: num = None # Slice a chunk from the edge to calculate stats on end = arr.shape[axis] - 1 if num is not None: med_slice = tuple( slice(None) if i != axis else slice(end, end - num, -1) for (i, x) in enumerate(arr.shape)) else: med_slice = tuple(slice(None) for x in arr.shape) # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) # Extract slice, calculate median, reshape to add singleton dimension back med_chunk = np.median(arr[med_slice], axis=axis).reshape(pad_singleton) _round_ifneeded(med_chunk, arr.dtype) # Concatenate `arr` with `med_chunk`, extended along `axis` by `pad_amt` return np.concatenate( (arr, med_chunk.repeat(pad_amt, axis).astype(arr.dtype)), axis=axis) def _prepend_min(arr, pad_amt, num, axis=-1): """ Prepend `pad_amt` minimum values along `axis`. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to prepend. num : int Depth into `arr` along `axis` to calculate minimum. Range: [1, `arr.shape[axis]`] or None (entire axis) axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt` values prepended along `axis`. The prepended region is the minimum of the first `num` values along `axis`. """ if pad_amt == 0: return arr # Equivalent to edge padding for single value, so do that instead if num == 1: return _prepend_edge(arr, pad_amt, axis) # Use entire array if `num` is too large if num is not None: if num >= arr.shape[axis]: num = None # Slice a chunk from the edge to calculate stats on min_slice = tuple(slice(None) if i != axis else slice(num) for (i, x) in enumerate(arr.shape)) # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) # Extract slice, calculate min, reshape to add singleton dimension back min_chunk = arr[min_slice].min(axis=axis).reshape(pad_singleton) # Concatenate `arr` with `min_chunk`, extended along `axis` by `pad_amt` return np.concatenate((min_chunk.repeat(pad_amt, axis=axis), arr), axis=axis) def _append_min(arr, pad_amt, num, axis=-1): """ Append `pad_amt` median values along `axis`. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : int Amount of padding to append. num : int Depth into `arr` along `axis` to calculate minimum. Range: [1, `arr.shape[axis]`] or None (entire axis) axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt` values appended along `axis`. The appended region is the minimum of the final `num` values along `axis`. """ if pad_amt == 0: return arr # Equivalent to edge padding for single value, so do that instead if num == 1: return _append_edge(arr, pad_amt, axis) # Use entire array if `num` is too large if num is not None: if num >= arr.shape[axis]: num = None # Slice a chunk from the edge to calculate stats on end = arr.shape[axis] - 1 if num is not None: min_slice = tuple( slice(None) if i != axis else slice(end, end - num, -1) for (i, x) in enumerate(arr.shape)) else: min_slice = tuple(slice(None) for x in arr.shape) # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) # Extract slice, calculate min, reshape to add singleton dimension back min_chunk = arr[min_slice].min(axis=axis).reshape(pad_singleton) # Concatenate `arr` with `min_chunk`, extended along `axis` by `pad_amt` return np.concatenate((arr, min_chunk.repeat(pad_amt, axis=axis)), axis=axis) def _pad_ref(arr, pad_amt, method, axis=-1): """ Pad `axis` of `arr` by reflection. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : tuple of ints, length 2 Padding to (prepend, append) along `axis`. method : str Controls method of reflection; options are 'even' or 'odd'. axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt[0]` values prepended and `pad_amt[1]` values appended along `axis`. Both regions are padded with reflected values from the original array. Notes ----- This algorithm does not pad with repetition, i.e. the edges are not repeated in the reflection. For that behavior, use `method='symmetric'`. The modes 'reflect', 'symmetric', and 'wrap' must be padded with a single function, lest the indexing tricks in non-integer multiples of the original shape would violate repetition in the final iteration. """ # Implicit booleanness to test for zero (or None) in any scalar type if pad_amt[0] == 0 and pad_amt[1] == 0: return arr ########################################################################## # Prepended region # Slice off a reverse indexed chunk from near edge to pad `arr` before ref_slice = tuple(slice(None) if i != axis else slice(pad_amt[0], 0, -1) for (i, x) in enumerate(arr.shape)) ref_chunk1 = arr[ref_slice] # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) if pad_amt[0] == 1: ref_chunk1 = ref_chunk1.reshape(pad_singleton) # Memory/computationally more expensive, only do this if `method='odd'` if 'odd' in method and pad_amt[0] > 0: edge_slice1 = tuple(slice(None) if i != axis else 0 for (i, x) in enumerate(arr.shape)) edge_chunk = arr[edge_slice1].reshape(pad_singleton) ref_chunk1 = 2 * edge_chunk - ref_chunk1 del edge_chunk ########################################################################## # Appended region # Slice off a reverse indexed chunk from far edge to pad `arr` after start = arr.shape[axis] - pad_amt[1] - 1 end = arr.shape[axis] - 1 ref_slice = tuple(slice(None) if i != axis else slice(start, end) for (i, x) in enumerate(arr.shape)) rev_idx = tuple(slice(None) if i != axis else slice(None, None, -1) for (i, x) in enumerate(arr.shape)) ref_chunk2 = arr[ref_slice][rev_idx] if pad_amt[1] == 1: ref_chunk2 = ref_chunk2.reshape(pad_singleton) if 'odd' in method: edge_slice2 = tuple(slice(None) if i != axis else -1 for (i, x) in enumerate(arr.shape)) edge_chunk = arr[edge_slice2].reshape(pad_singleton) ref_chunk2 = 2 * edge_chunk - ref_chunk2 del edge_chunk # Concatenate `arr` with both chunks, extending along `axis` return np.concatenate((ref_chunk1, arr, ref_chunk2), axis=axis) def _pad_sym(arr, pad_amt, method, axis=-1): """ Pad `axis` of `arr` by symmetry. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : tuple of ints, length 2 Padding to (prepend, append) along `axis`. method : str Controls method of symmetry; options are 'even' or 'odd'. axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt[0]` values prepended and `pad_amt[1]` values appended along `axis`. Both regions are padded with symmetric values from the original array. Notes ----- This algorithm DOES pad with repetition, i.e. the edges are repeated. For a method that does not repeat edges, use `method='reflect'`. The modes 'reflect', 'symmetric', and 'wrap' must be padded with a single function, lest the indexing tricks in non-integer multiples of the original shape would violate repetition in the final iteration. """ # Implicit booleanness to test for zero (or None) in any scalar type if pad_amt[0] == 0 and pad_amt[1] == 0: return arr ########################################################################## # Prepended region # Slice off a reverse indexed chunk from near edge to pad `arr` before sym_slice = tuple(slice(None) if i != axis else slice(0, pad_amt[0]) for (i, x) in enumerate(arr.shape)) rev_idx = tuple(slice(None) if i != axis else slice(None, None, -1) for (i, x) in enumerate(arr.shape)) sym_chunk1 = arr[sym_slice][rev_idx] # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) if pad_amt[0] == 1: sym_chunk1 = sym_chunk1.reshape(pad_singleton) # Memory/computationally more expensive, only do this if `method='odd'` if 'odd' in method and pad_amt[0] > 0: edge_slice1 = tuple(slice(None) if i != axis else 0 for (i, x) in enumerate(arr.shape)) edge_chunk = arr[edge_slice1].reshape(pad_singleton) sym_chunk1 = 2 * edge_chunk - sym_chunk1 del edge_chunk ########################################################################## # Appended region # Slice off a reverse indexed chunk from far edge to pad `arr` after start = arr.shape[axis] - pad_amt[1] end = arr.shape[axis] sym_slice = tuple(slice(None) if i != axis else slice(start, end) for (i, x) in enumerate(arr.shape)) sym_chunk2 = arr[sym_slice][rev_idx] if pad_amt[1] == 1: sym_chunk2 = sym_chunk2.reshape(pad_singleton) if 'odd' in method: edge_slice2 = tuple(slice(None) if i != axis else -1 for (i, x) in enumerate(arr.shape)) edge_chunk = arr[edge_slice2].reshape(pad_singleton) sym_chunk2 = 2 * edge_chunk - sym_chunk2 del edge_chunk # Concatenate `arr` with both chunks, extending along `axis` return np.concatenate((sym_chunk1, arr, sym_chunk2), axis=axis) def _pad_wrap(arr, pad_amt, axis=-1): """ Pad `axis` of `arr` via wrapping. Parameters ---------- arr : ndarray Input array of arbitrary shape. pad_amt : tuple of ints, length 2 Padding to (prepend, append) along `axis`. axis : int Axis along which to pad `arr`. Returns ------- padarr : ndarray Output array, with `pad_amt[0]` values prepended and `pad_amt[1]` values appended along `axis`. Both regions are padded wrapped values from the opposite end of `axis`. Notes ----- This method of padding is also known as 'tile' or 'tiling'. The modes 'reflect', 'symmetric', and 'wrap' must be padded with a single function, lest the indexing tricks in non-integer multiples of the original shape would violate repetition in the final iteration. """ # Implicit booleanness to test for zero (or None) in any scalar type if pad_amt[0] == 0 and pad_amt[1] == 0: return arr ########################################################################## # Prepended region # Slice off a reverse indexed chunk from near edge to pad `arr` before start = arr.shape[axis] - pad_amt[0] end = arr.shape[axis] wrap_slice = tuple(slice(None) if i != axis else slice(start, end) for (i, x) in enumerate(arr.shape)) wrap_chunk1 = arr[wrap_slice] # Shape to restore singleton dimension after slicing pad_singleton = tuple(x if i != axis else 1 for (i, x) in enumerate(arr.shape)) if pad_amt[0] == 1: wrap_chunk1 = wrap_chunk1.reshape(pad_singleton) ########################################################################## # Appended region # Slice off a reverse indexed chunk from far edge to pad `arr` after wrap_slice = tuple(slice(None) if i != axis else slice(0, pad_amt[1]) for (i, x) in enumerate(arr.shape)) wrap_chunk2 = arr[wrap_slice] if pad_amt[1] == 1: wrap_chunk2 = wrap_chunk2.reshape(pad_singleton) # Concatenate `arr` with both chunks, extending along `axis` return np.concatenate((wrap_chunk1, arr, wrap_chunk2), axis=axis) def _normalize_shape(narray, shape): """ Private function which does some checks and normalizes the possibly much simpler representations of 'pad_width', 'stat_length', 'constant_values', 'end_values'. Parameters ---------- narray : ndarray Input ndarray shape : {sequence, int}, optional The width of padding (pad_width) or the number of elements on the edge of the narray used for statistics (stat_length). ((before_1, after_1), ... (before_N, after_N)) unique number of elements for each axis where `N` is rank of `narray`. ((before, after),) yields same before and after constants for each axis. (constant,) or int is a shortcut for before = after = constant for all axes. Returns ------- _normalize_shape : tuple of tuples int => ((int, int), (int, int), ...) [[int1, int2], [int3, int4], ...] => ((int1, int2), (int3, int4), ...) ((int1, int2), (int3, int4), ...) => no change [[int1, int2], ] => ((int1, int2), (int1, int2), ...) ((int1, int2), ) => ((int1, int2), (int1, int2), ...) [[int , ], ] => ((int, int), (int, int), ...) ((int , ), ) => ((int, int), (int, int), ...) """ normshp = None shapelen = len(np.shape(narray)) if (isinstance(shape, int)) or shape is None: normshp = ((shape, shape), ) * shapelen elif (isinstance(shape, (tuple, list)) and isinstance(shape[0], (tuple, list)) and len(shape) == shapelen): normshp = shape for i in normshp: if len(i) != 2: fmt = "Unable to create correctly shaped tuple from %s" raise ValueError(fmt % (normshp,)) elif (isinstance(shape, (tuple, list)) and isinstance(shape[0], integer_types + (float,)) and len(shape) == 1): normshp = ((shape[0], shape[0]), ) * shapelen elif (isinstance(shape, (tuple, list)) and isinstance(shape[0], integer_types + (float,)) and len(shape) == 2): normshp = (shape, ) * shapelen if normshp is None: fmt = "Unable to create correctly shaped tuple from %s" raise ValueError(fmt % (shape,)) return normshp def _validate_lengths(narray, number_elements): """ Private function which does some checks and reformats pad_width and stat_length using _normalize_shape. Parameters ---------- narray : ndarray Input ndarray number_elements : {sequence, int}, optional The width of padding (pad_width) or the number of elements on the edge of the narray used for statistics (stat_length). ((before_1, after_1), ... (before_N, after_N)) unique number of elements for each axis. ((before, after),) yields same before and after constants for each axis. (constant,) or int is a shortcut for before = after = constant for all axes. Returns ------- _validate_lengths : tuple of tuples int => ((int, int), (int, int), ...) [[int1, int2], [int3, int4], ...] => ((int1, int2), (int3, int4), ...) ((int1, int2), (int3, int4), ...) => no change [[int1, int2], ] => ((int1, int2), (int1, int2), ...) ((int1, int2), ) => ((int1, int2), (int1, int2), ...) [[int , ], ] => ((int, int), (int, int), ...) ((int , ), ) => ((int, int), (int, int), ...) """ normshp = _normalize_shape(narray, number_elements) for i in normshp: chk = [1 if x is None else x for x in i] chk = [1 if x >= 0 else -1 for x in chk] if (chk[0] < 0) or (chk[1] < 0): fmt = "%s cannot contain negative values." raise ValueError(fmt % (number_elements,)) return normshp ############################################################################### # Public functions def pad(array, pad_width, mode=None, **kwargs): """ Pads an array. Parameters ---------- array : array_like of rank N Input array pad_width : {sequence, int} Number of values padded to the edges of each axis. ((before_1, after_1), ... (before_N, after_N)) unique pad widths for each axis. ((before, after),) yields same before and after pad for each axis. (pad,) or int is a shortcut for before = after = pad width for all axes. mode : {str, function} One of the following string values or a user supplied function. 'constant' Pads with a constant value. 'edge' Pads with the edge values of array. 'linear_ramp' Pads with the linear ramp between end_value and the array edge value. 'maximum' Pads with the maximum value of all or part of the vector along each axis. 'mean' Pads with the mean value of all or part of the vector along each axis. 'median' Pads with the median value of all or part of the vector along each axis. 'minimum' Pads with the minimum value of all or part of the vector along each axis. 'reflect' Pads with the reflection of the vector mirrored on the first and last values of the vector along each axis. 'symmetric' Pads with the reflection of the vector mirrored along the edge of the array. 'wrap' Pads with the wrap of the vector along the axis. The first values are used to pad the end and the end values are used to pad the beginning. Padding function, see Notes. stat_length : {sequence, int}, optional Used in 'maximum', 'mean', 'median', and 'minimum'. Number of values at edge of each axis used to calculate the statistic value. ((before_1, after_1), ... (before_N, after_N)) unique statistic lengths for each axis. ((before, after),) yields same before and after statistic lengths for each axis. (stat_length,) or int is a shortcut for before = after = statistic length for all axes. Default is ``None``, to use the entire axis. constant_values : {sequence, int}, optional Used in 'constant'. The values to set the padded values for each axis. ((before_1, after_1), ... (before_N, after_N)) unique pad constants for each axis. ((before, after),) yields same before and after constants for each axis. (constant,) or int is a shortcut for before = after = constant for all axes. Default is 0. end_values : {sequence, int}, optional Used in 'linear_ramp'. The values used for the ending value of the linear_ramp and that will form the edge of the padded array. ((before_1, after_1), ... (before_N, after_N)) unique end values for each axis. ((before, after),) yields same before and after end values for each axis. (constant,) or int is a shortcut for before = after = end value for all axes. Default is 0. reflect_type : str {'even', 'odd'}, optional Used in 'reflect', and 'symmetric'. The 'even' style is the default with an unaltered reflection around the edge value. For the 'odd' style, the extented part of the array is created by subtracting the reflected values from two times the edge value. Returns ------- pad : ndarray Padded array of rank equal to `array` with shape increased according to `pad_width`. Notes ----- For an array with rank greater than 1, some of the padding of later axes is calculated from padding of previous axes. This is easiest to think about with a rank 2 array where the corners of the padded array are calculated by using padded values from the first axis. The padding function, if used, should return a rank 1 array equal in length to the vector argument with padded values replaced. It has the following signature: padding_func(vector, iaxis_pad_width, iaxis, **kwargs) where vector : ndarray A rank 1 array already padded with zeros. Padded values are vector[:pad_tuple[0]] and vector[-pad_tuple[1]:]. iaxis_pad_width : tuple A 2-tuple of ints, iaxis_pad_width[0] represents the number of values padded at the beginning of vector where iaxis_pad_width[1] represents the number of values padded at the end of vector. iaxis : int The axis currently being calculated. kwargs : misc Any keyword arguments the function requires. Examples -------- >>> a = [1, 2, 3, 4, 5] >>> np.lib.pad(a, (2,3), 'constant', constant_values=(4,6)) array([4, 4, 1, 2, 3, 4, 5, 6, 6, 6]) >>> np.lib.pad(a, (2,3), 'edge') array([1, 1, 1, 2, 3, 4, 5, 5, 5, 5]) >>> np.lib.pad(a, (2,3), 'linear_ramp', end_values=(5,-4)) array([ 5, 3, 1, 2, 3, 4, 5, 2, -1, -4]) >>> np.lib.pad(a, (2,), 'maximum') array([5, 5, 1, 2, 3, 4, 5, 5, 5]) >>> np.lib.pad(a, (2,), 'mean') array([3, 3, 1, 2, 3, 4, 5, 3, 3]) >>> np.lib.pad(a, (2,), 'median') array([3, 3, 1, 2, 3, 4, 5, 3, 3]) >>> a = [[1,2], [3,4]] >>> np.lib.pad(a, ((3, 2), (2, 3)), 'minimum') array([[1, 1, 1, 2, 1, 1, 1], [1, 1, 1, 2, 1, 1, 1], [1, 1, 1, 2, 1, 1, 1], [1, 1, 1, 2, 1, 1, 1], [3, 3, 3, 4, 3, 3, 3], [1, 1, 1, 2, 1, 1, 1], [1, 1, 1, 2, 1, 1, 1]]) >>> a = [1, 2, 3, 4, 5] >>> np.lib.pad(a, (2,3), 'reflect') array([3, 2, 1, 2, 3, 4, 5, 4, 3, 2]) >>> np.lib.pad(a, (2,3), 'reflect', reflect_type='odd') array([-1, 0, 1, 2, 3, 4, 5, 6, 7, 8]) >>> np.lib.pad(a, (2,3), 'symmetric') array([2, 1, 1, 2, 3, 4, 5, 5, 4, 3]) >>> np.lib.pad(a, (2,3), 'symmetric', reflect_type='odd') array([0, 1, 1, 2, 3, 4, 5, 5, 6, 7]) >>> np.lib.pad(a, (2,3), 'wrap') array([4, 5, 1, 2, 3, 4, 5, 1, 2, 3]) >>> def padwithtens(vector, pad_width, iaxis, kwargs): ... vector[:pad_width[0]] = 10 ... vector[-pad_width[1]:] = 10 ... return vector >>> a = np.arange(6) >>> a = a.reshape((2,3)) >>> np.lib.pad(a, 2, padwithtens) array([[10, 10, 10, 10, 10, 10, 10], [10, 10, 10, 10, 10, 10, 10], [10, 10, 0, 1, 2, 10, 10], [10, 10, 3, 4, 5, 10, 10], [10, 10, 10, 10, 10, 10, 10], [10, 10, 10, 10, 10, 10, 10]]) """ narray = np.array(array) pad_width = _validate_lengths(narray, pad_width) allowedkwargs = { 'constant': ['constant_values'], 'edge': [], 'linear_ramp': ['end_values'], 'maximum': ['stat_length'], 'mean': ['stat_length'], 'median': ['stat_length'], 'minimum': ['stat_length'], 'reflect': ['reflect_type'], 'symmetric': ['reflect_type'], 'wrap': []} kwdefaults = { 'stat_length': None, 'constant_values': 0, 'end_values': 0, 'reflect_type': 'even'} if isinstance(mode, str): # Make sure have allowed kwargs appropriate for mode for key in kwargs: if key not in allowedkwargs[mode]: raise ValueError('%s keyword not in allowed keywords %s' % (key, allowedkwargs[mode])) # Set kwarg defaults for kw in allowedkwargs[mode]: kwargs.setdefault(kw, kwdefaults[kw]) # Need to only normalize particular keywords. for i in kwargs: if i == 'stat_length': kwargs[i] = _validate_lengths(narray, kwargs[i]) if i in ['end_values', 'constant_values']: kwargs[i] = _normalize_shape(narray, kwargs[i]) elif mode is None: raise ValueError('Keyword "mode" must be a function or one of %s.' % (list(allowedkwargs.keys()),)) else: # Drop back to old, slower np.apply_along_axis mode for user-supplied # vector function function = mode # Create a new padded array rank = list(range(len(narray.shape))) total_dim_increase = [np.sum(pad_width[i]) for i in rank] offset_slices = [slice(pad_width[i][0], pad_width[i][0] + narray.shape[i]) for i in rank] new_shape = np.array(narray.shape) + total_dim_increase newmat = np.zeros(new_shape).astype(narray.dtype) # Insert the original array into the padded array newmat[offset_slices] = narray # This is the core of pad ... for iaxis in rank: np.apply_along_axis(function, iaxis, newmat, pad_width[iaxis], iaxis, kwargs) return newmat # If we get here, use new padding method newmat = narray.copy() # API preserved, but completely new algorithm which pads by building the # entire block to pad before/after `arr` with in one step, for each axis. if mode == 'constant': for axis, ((pad_before, pad_after), (before_val, after_val)) \ in enumerate(zip(pad_width, kwargs['constant_values'])): newmat = _prepend_const(newmat, pad_before, before_val, axis) newmat = _append_const(newmat, pad_after, after_val, axis) elif mode == 'edge': for axis, (pad_before, pad_after) in enumerate(pad_width): newmat = _prepend_edge(newmat, pad_before, axis) newmat = _append_edge(newmat, pad_after, axis) elif mode == 'linear_ramp': for axis, ((pad_before, pad_after), (before_val, after_val)) \ in enumerate(zip(pad_width, kwargs['end_values'])): newmat = _prepend_ramp(newmat, pad_before, before_val, axis) newmat = _append_ramp(newmat, pad_after, after_val, axis) elif mode == 'maximum': for axis, ((pad_before, pad_after), (chunk_before, chunk_after)) \ in enumerate(zip(pad_width, kwargs['stat_length'])): newmat = _prepend_max(newmat, pad_before, chunk_before, axis) newmat = _append_max(newmat, pad_after, chunk_after, axis) elif mode == 'mean': for axis, ((pad_before, pad_after), (chunk_before, chunk_after)) \ in enumerate(zip(pad_width, kwargs['stat_length'])): newmat = _prepend_mean(newmat, pad_before, chunk_before, axis) newmat = _append_mean(newmat, pad_after, chunk_after, axis) elif mode == 'median': for axis, ((pad_before, pad_after), (chunk_before, chunk_after)) \ in enumerate(zip(pad_width, kwargs['stat_length'])): newmat = _prepend_med(newmat, pad_before, chunk_before, axis) newmat = _append_med(newmat, pad_after, chunk_after, axis) elif mode == 'minimum': for axis, ((pad_before, pad_after), (chunk_before, chunk_after)) \ in enumerate(zip(pad_width, kwargs['stat_length'])): newmat = _prepend_min(newmat, pad_before, chunk_before, axis) newmat = _append_min(newmat, pad_after, chunk_after, axis) elif mode == 'reflect': for axis, (pad_before, pad_after) in enumerate(pad_width): # Recursive padding along any axis where `pad_amt` is too large # for indexing tricks. We can only safely pad the original axis # length, to keep the period of the reflections consistent. if ((pad_before > 0) or (pad_after > 0)) and newmat.shape[axis] == 1: # Extending singleton dimension for 'reflect' is legacy # behavior; it really should raise an error. newmat = _prepend_edge(newmat, pad_before, axis) newmat = _append_edge(newmat, pad_after, axis) continue method = kwargs['reflect_type'] safe_pad = newmat.shape[axis] - 1 while ((pad_before > safe_pad) or (pad_after > safe_pad)): offset = 0 pad_iter_b = min(safe_pad, safe_pad * (pad_before // safe_pad)) pad_iter_a = min(safe_pad, safe_pad * (pad_after // safe_pad)) newmat = _pad_ref(newmat, (pad_iter_b, pad_iter_a), method, axis) pad_before -= pad_iter_b pad_after -= pad_iter_a if pad_iter_b > 0: offset += 1 if pad_iter_a > 0: offset += 1 safe_pad += pad_iter_b + pad_iter_a newmat = _pad_ref(newmat, (pad_before, pad_after), method, axis) elif mode == 'symmetric': for axis, (pad_before, pad_after) in enumerate(pad_width): # Recursive padding along any axis where `pad_amt` is too large # for indexing tricks. We can only safely pad the original axis # length, to keep the period of the reflections consistent. method = kwargs['reflect_type'] safe_pad = newmat.shape[axis] while ((pad_before > safe_pad) or (pad_after > safe_pad)): pad_iter_b = min(safe_pad, safe_pad * (pad_before // safe_pad)) pad_iter_a = min(safe_pad, safe_pad * (pad_after // safe_pad)) newmat = _pad_sym(newmat, (pad_iter_b, pad_iter_a), method, axis) pad_before -= pad_iter_b pad_after -= pad_iter_a safe_pad += pad_iter_b + pad_iter_a newmat = _pad_sym(newmat, (pad_before, pad_after), method, axis) elif mode == 'wrap': for axis, (pad_before, pad_after) in enumerate(pad_width): # Recursive padding along any axis where `pad_amt` is too large # for indexing tricks. We can only safely pad the original axis # length, to keep the period of the reflections consistent. safe_pad = newmat.shape[axis] while ((pad_before > safe_pad) or (pad_after > safe_pad)): pad_iter_b = min(safe_pad, safe_pad * (pad_before // safe_pad)) pad_iter_a = min(safe_pad, safe_pad * (pad_after // safe_pad)) newmat = _pad_wrap(newmat, (pad_iter_b, pad_iter_a), axis) pad_before -= pad_iter_b pad_after -= pad_iter_a safe_pad += pad_iter_b + pad_iter_a newmat = _pad_wrap(newmat, (pad_before, pad_after), axis) return newmat scikit-image-0.9.3/skimage/util/dtype.py000066400000000000000000000273311223313777300202030ustar00rootroot00000000000000from __future__ import division import numpy as np from warnings import warn __all__ = ['img_as_float', 'img_as_int', 'img_as_uint', 'img_as_ubyte', 'img_as_bool', 'dtype_limits'] dtype_range = {np.bool_: (False, True), np.bool8: (False, True), np.uint8: (0, 255), np.uint16: (0, 65535), np.int8: (-128, 127), np.int16: (-32768, 32767), np.float32: (-1, 1), np.float64: (-1, 1)} integer_types = (np.uint8, np.uint16, np.int8, np.int16) _supported_types = (np.bool_, np.bool8, np.uint8, np.uint16, np.uint32, np.int8, np.int16, np.int32, np.float32, np.float64) if np.__version__ >= "1.6.0": dtype_range[np.float16] = (-1, 1) _supported_types += (np.float16, ) def dtype_limits(image, clip_negative=True): """Return intensity limits, i.e. (min, max) tuple, of the image's dtype. Parameters ---------- image : ndarray Input image. clip_negative : bool If True, clip the negative range (i.e. return 0 for min intensity) even if the image dtype allows negative values. """ imin, imax = dtype_range[image.dtype.type] if clip_negative: imin = 0 return imin, imax def convert(image, dtype, force_copy=False, uniform=False): """ Convert an image to the requested data-type. Warnings are issued in case of precision loss, or when negative values are clipped during conversion to unsigned integer types (sign loss). Floating point values are expected to be normalized and will be clipped to the range [0.0, 1.0] or [-1.0, 1.0] when converting to unsigned or signed integers respectively. Numbers are not shifted to the negative side when converting from unsigned to signed integer types. Negative values will be clipped when converting to unsigned integers. Parameters ---------- image : ndarray Input image. dtype : dtype Target data-type. force_copy : bool Force a copy of the data, irrespective of its current dtype. uniform : bool Uniformly quantize the floating point range to the integer range. By default (uniform=False) floating point values are scaled and rounded to the nearest integers, which minimizes back and forth conversion errors. References ---------- (1) DirectX data conversion rules. http://msdn.microsoft.com/en-us/library/windows/desktop/dd607323%28v=vs.85%29.aspx (2) Data Conversions. In "OpenGL ES 2.0 Specification v2.0.25", pp 7-8. Khronos Group, 2010. (3) Proper treatment of pixels as integers. A.W. Paeth. In "Graphics Gems I", pp 249-256. Morgan Kaufmann, 1990. (4) Dirty Pixels. J. Blinn. In "Jim Blinn's corner: Dirty Pixels", pp 47-57. Morgan Kaufmann, 1998. """ image = np.asarray(image) dtypeobj = np.dtype(dtype) dtypeobj_in = image.dtype dtype = dtypeobj.type dtype_in = dtypeobj_in.type if dtype_in == dtype: if force_copy: image = image.copy() return image if not (dtype_in in _supported_types and dtype in _supported_types): raise ValueError("can not convert %s to %s." % (dtypeobj_in, dtypeobj)) def sign_loss(): warn("Possible sign loss when converting negative image of type " "%s to positive image of type %s." % (dtypeobj_in, dtypeobj)) def prec_loss(): warn("Possible precision loss when converting from " "%s to %s" % (dtypeobj_in, dtypeobj)) def _dtype(itemsize, *dtypes): # Return first of `dtypes` with itemsize greater than `itemsize` return next(dt for dt in dtypes if itemsize < np.dtype(dt).itemsize) def _dtype2(kind, bits, itemsize=1): # Return dtype of `kind` that can store a `bits` wide unsigned int c = lambda x, y: x <= y if kind == 'u' else x < y s = next(i for i in (itemsize, ) + (2, 4, 8) if c(bits, i * 8)) return np.dtype(kind + str(s)) def _scale(a, n, m, copy=True): # Scale unsigned/positive integers from n to m bits # Numbers can be represented exactly only if m is a multiple of n # Output array is of same kind as input. kind = a.dtype.kind if n == m: return a.copy() if copy else a elif n > m: # downscale with precision loss prec_loss() if copy: b = np.empty(a.shape, _dtype2(kind, m)) np.floor_divide(a, 2**(n - m), out=b, dtype=a.dtype, casting='unsafe') return b else: a //= 2**(n - m) return a elif m % n == 0: # exact upscale to a multiple of n bits if copy: b = np.empty(a.shape, _dtype2(kind, m)) np.multiply(a, (2**m - 1) // (2**n - 1), out=b, dtype=b.dtype) return b else: a = np.array(a, _dtype2(kind, m, a.dtype.itemsize), copy=False) a *= (2**m - 1) // (2**n - 1) return a else: # upscale to a multiple of n bits, # then downscale with precision loss prec_loss() o = (m // n + 1) * n if copy: b = np.empty(a.shape, _dtype2(kind, o)) np.multiply(a, (2**o - 1) // (2**n - 1), out=b, dtype=b.dtype) b //= 2**(o - m) return b else: a = np.array(a, _dtype2(kind, o, a.dtype.itemsize), copy=False) a *= (2**o - 1) // (2**n - 1) a //= 2**(o - m) return a kind = dtypeobj.kind kind_in = dtypeobj_in.kind itemsize = dtypeobj.itemsize itemsize_in = dtypeobj_in.itemsize if kind == 'b': # to binary image if kind_in in "fi": sign_loss() prec_loss() return image > dtype_in(dtype_range[dtype_in][1] / 2) if kind_in == 'b': # from binary image, to float and to integer result = image.astype(dtype) if kind != 'f': result *= dtype(dtype_range[dtype][1]) return result if kind in 'ui': imin = np.iinfo(dtype).min imax = np.iinfo(dtype).max if kind_in in 'ui': imin_in = np.iinfo(dtype_in).min imax_in = np.iinfo(dtype_in).max if kind_in == 'f': if np.min(image) < -1.0 or np.max(image) > 1.0: raise ValueError("Images of type float must be between -1 and 1.") if kind == 'f': # floating point -> floating point if itemsize_in > itemsize: prec_loss() return image.astype(dtype) # floating point -> integer prec_loss() # use float type that can represent output integer type image = np.array(image, _dtype(itemsize, dtype_in, np.float32, np.float64)) if not uniform: if kind == 'u': image *= imax else: image *= imax - imin image -= 1.0 image /= 2.0 np.rint(image, out=image) np.clip(image, imin, imax, out=image) elif kind == 'u': image *= imax + 1 np.clip(image, 0, imax, out=image) else: image *= (imax - imin + 1.0) / 2.0 np.floor(image, out=image) np.clip(image, imin, imax, out=image) return image.astype(dtype) if kind == 'f': # integer -> floating point if itemsize_in >= itemsize: prec_loss() # use float type that can exactly represent input integers image = np.array(image, _dtype(itemsize_in, dtype, np.float32, np.float64)) if kind_in == 'u': image /= imax_in # DirectX uses this conversion also for signed ints #if imin_in: # np.maximum(image, -1.0, out=image) else: image *= 2.0 image += 1.0 image /= imax_in - imin_in return image.astype(dtype) if kind_in == 'u': if kind == 'i': # unsigned integer -> signed integer image = _scale(image, 8 * itemsize_in, 8 * itemsize - 1) return image.view(dtype) else: # unsigned integer -> unsigned integer return _scale(image, 8 * itemsize_in, 8 * itemsize) if kind == 'u': # signed integer -> unsigned integer sign_loss() image = _scale(image, 8 * itemsize_in - 1, 8 * itemsize) result = np.empty(image.shape, dtype) np.maximum(image, 0, out=result, dtype=image.dtype, casting='unsafe') return result # signed integer -> signed integer if itemsize_in > itemsize: return _scale(image, 8 * itemsize_in - 1, 8 * itemsize - 1) image = image.astype(_dtype2('i', itemsize * 8)) image -= imin_in image = _scale(image, 8 * itemsize_in, 8 * itemsize, copy=False) image += imin return image.astype(dtype) def img_as_float(image, force_copy=False): """Convert an image to double-precision floating point format. Parameters ---------- image : ndarray Input image. force_copy : bool Force a copy of the data, irrespective of its current dtype. Returns ------- out : ndarray of float64 Output image. Notes ----- The range of a floating point image is [0.0, 1.0] or [-1.0, 1.0] when converting from unsigned or signed datatypes, respectively. """ return convert(image, np.float64, force_copy) def img_as_uint(image, force_copy=False): """Convert an image to 16-bit unsigned integer format. Parameters ---------- image : ndarray Input image. force_copy : bool Force a copy of the data, irrespective of its current dtype. Returns ------- out : ndarray of uint16 Output image. Notes ----- Negative input values will be shifted to the positive domain. """ return convert(image, np.uint16, force_copy) def img_as_int(image, force_copy=False): """Convert an image to 16-bit signed integer format. Parameters ---------- image : ndarray Input image. force_copy : bool Force a copy of the data, irrespective of its current dtype. Returns ------- out : ndarray of uint16 Output image. Notes ----- If the input data-type is positive-only (e.g., uint8), then the output image will still only have positive values. """ return convert(image, np.int16, force_copy) def img_as_ubyte(image, force_copy=False): """Convert an image to 8-bit unsigned integer format. Parameters ---------- image : ndarray Input image. force_copy : bool Force a copy of the data, irrespective of its current dtype. Returns ------- out : ndarray of ubyte (uint8) Output image. Notes ----- If the input data-type is positive-only (e.g., uint16), then the output image will still only have positive values. """ return convert(image, np.uint8, force_copy) def img_as_bool(image, force_copy=False): """Convert an image to boolean format. Parameters ---------- image : ndarray Input image. force_copy : bool Force a copy of the data, irrespective of its current dtype. Returns ------- out : ndarray of bool (`bool_`) Output image. Notes ----- The upper half of the input dtype's positive range is True, and the lower half is False. All negative values (if present) are False. """ return convert(image, np.bool_, force_copy) scikit-image-0.9.3/skimage/util/montage.py000066400000000000000000000061171223313777300205070ustar00rootroot00000000000000__all__ = ['montage2d'] import numpy as np from .. import exposure EPSILON = 1e-6 def montage2d(arr_in, fill='mean', rescale_intensity=False, grid_shape=None): """Create a 2-dimensional 'montage' from a 3-dimensional input array representing an ensemble of equally shaped 2-dimensional images. For example, ``montage2d(arr_in, fill)`` with the following `arr_in` +---+---+---+ | 1 | 2 | 3 | +---+---+---+ will return: +---+---+ | 1 | 2 | +---+---+ | 3 | * | +---+---+ Where the '*' patch will be determined by the `fill` parameter. Parameters ---------- arr_in: ndarray, shape=[n_images, height, width] 3-dimensional input array representing an ensemble of n_images of equal shape (i.e. [height, width]). fill: float or 'mean', optional How to fill the 2-dimensional output array when sqrt(n_images) is not an integer. If 'mean' is chosen, then fill = arr_in.mean(). rescale_intensity: bool, optional Whether to rescale the intensity of each image to [0, 1]. grid_shape: tuple, optional The desired grid shape for the montage (tiles_y, tiles_x). The default aspect ratio is square. Returns ------- arr_out: ndarray, shape=[alpha * height, alpha * width] Output array where 'alpha' has been determined automatically to fit (at least) the `n_images` in `arr_in`. Examples -------- >>> import numpy as np >>> from skimage.util.montage import montage2d >>> arr_in = np.arange(3 * 2 * 2).reshape(3, 2, 2) >>> print(arr_in) # doctest: +NORMALIZE_WHITESPACE [[[ 0 1] [ 2 3]] [[ 4 5] [ 6 7]] [[ 8 9] [10 11]]] >>> arr_out = montage2d(arr_in) >>> print(arr_out.shape) (4, 4) >>> print(arr_out) [[ 0. 1. 4. 5. ] [ 2. 3. 6. 7. ] [ 8. 9. 5.5 5.5] [ 10. 11. 5.5 5.5]] >>> print(arr_in.mean()) 5.5 >>> arr_out_nonsquare = montage2d(arr_in, grid_shape=(3, 4)) >>> print(arr_out_nonsquare) [[ 0. 1. 4. 5. ] [ 2. 3. 6. 7. ] [ 8. 9. 10. 11. ]] >>> print(arr_out_nonsquare.shape) (3, 4) """ assert arr_in.ndim == 3 n_images, height, width = arr_in.shape arr_in = arr_in.copy() # -- rescale intensity if necessary if rescale_intensity: for i in range(n_images): arr_in[i] = exposure.rescale_intensity(arr_in[i]) # -- determine alpha if grid_shape: alpha_y, alpha_x = grid_shape else: alpha_y = alpha_x = int(np.ceil(np.sqrt(n_images))) # -- fill missing patches if fill == 'mean': fill = arr_in.mean() n_missing = int((alpha_y * alpha_x) - n_images) missing = np.ones((n_missing, height, width), dtype=arr_in.dtype) * fill arr_out = np.vstack((arr_in, missing)) # -- reshape to 2d montage, step by step arr_out = arr_out.reshape(alpha_y, alpha_x, height, width) arr_out = arr_out.swapaxes(1, 2) arr_out = arr_out.reshape(alpha_y * height, alpha_x * width) return arr_out scikit-image-0.9.3/skimage/util/noise.py000066400000000000000000000166721223313777300202010ustar00rootroot00000000000000import numpy as np from .dtype import img_as_float __all__ = ['random_noise'] def random_noise(image, mode='gaussian', seed=None, clip=True, **kwargs): """ Function to add random noise of various types to a floating-point image. Parameters ---------- image : ndarray Input image data. Will be converted to float. mode : str One of the following strings, selecting the type of noise to add: 'gaussian' Gaussian-distributed additive noise. 'localvar' Gaussian-distributed additive noise, with specified local variance at each point of `image` 'poisson' Poisson-distributed noise generated from the data. 'salt' Replaces random pixels with 1. 'pepper' Replaces random pixels with 0. 's&p' Replaces random pixels with 0 or 1. 'speckle' Multiplicative noise using out = image + n*image, where n is uniform noise with specified mean & variance. seed : int If provided, this will set the random seed before generating noise, for valid pseudo-random comparisons. clip : bool If True (default), the output will be clipped after noise applied for modes `'speckle'`, `'poisson'`, and `'gaussian'`. This is needed to maintain the proper image data range. If False, clipping is not applied, and the output may extend beyond the range [-1, 1]. mean : float Mean of random distribution. Used in 'gaussian' and 'speckle'. Default : 0. var : float Variance of random distribution. Used in 'gaussian' and 'speckle'. Note: variance = (standard deviation) ** 2. Default : 0.01 local_vars : ndarray Array of positive floats, same shape as `image`, defining the local variance at every image point. Used in 'localvar'. amount : float Proportion of image pixels to replace with noise on range [0, 1]. Used in 'salt', 'pepper', and 'salt & pepper'. Default : 0.05 salt_vs_pepper : float Proportion of salt vs. pepper noise for 's&p' on range [0, 1]. Higher values represent more salt. Default : 0.5 (equal amounts) Returns ------- out : ndarray Output floating-point image data on range [0, 1] or [-1, 1] if the input `image` was unsigned or signed, respectively. Notes ----- Speckle, Poisson, Localvar, and Gaussian noise may generate noise outside the valid image range. The default is to clip (not alias) these values, but they may be preserved by setting `clip=False`. Note that in this case the output may contain values outside the ranges [0, 1] or [-1, 1]. Use this option with care. Because of the prevalence of exclusively positive floating-point images in intermediate calculations, it is not possible to intuit if an input is signed based on dtype alone. Instead, negative values are explicity searched for. Only if found does this function assume signed input. Unexpected results only occur in rare, poorly exposes cases (e.g. if all values are above 50 percent gray in a signed `image`). In this event, manually scaling the input to the positive domain will solve the problem. The Poisson distribution is only defined for positive integers. To apply this noise type, the number of unique values in the image is found and the next round power of two is used to scale up the floating-point result, after which it is scaled back down to the floating-point image range. To generate Poisson noise against a signed image, the signed image is temporarily converted to an unsigned image in the floating point domain, Poisson noise is generated, then it is returned to the original range. """ mode = mode.lower() # Detect if a signed image was input if image.min() < 0: low_clip = -1. else: low_clip = 0. image = img_as_float(image) if seed is not None: np.random.seed(seed=seed) allowedtypes = { 'gaussian': 'gaussian_values', 'localvar': 'localvar_values', 'poisson': 'poisson_values', 'salt': 'sp_values', 'pepper': 'sp_values', 's&p': 's&p_values', 'speckle': 'gaussian_values'} kwdefaults = { 'mean': 0., 'var': 0.01, 'amount': 0.05, 'salt_vs_pepper': 0.5, 'local_vars': np.zeros_like(image) + 0.01} allowedkwargs = { 'gaussian_values': ['mean', 'var'], 'localvar_values': ['local_vars'], 'sp_values': ['amount'], 's&p_values': ['amount', 'salt_vs_pepper'], 'poisson_values': []} for key in kwargs: if key not in allowedkwargs[allowedtypes[mode]]: raise ValueError('%s keyword not in allowed keywords %s' % (key, allowedkwargs[allowedtypes[mode]])) # Set kwarg defaults for kw in allowedkwargs[allowedtypes[mode]]: kwargs.setdefault(kw, kwdefaults[kw]) if mode == 'gaussian': noise = np.random.normal(kwargs['mean'], kwargs['var'] ** 0.5, image.shape) out = image + noise elif mode == 'localvar': # Ensure local variance input is correct if (kwargs['local_vars'] <= 0).any(): raise ValueError('All values of `local_vars` must be > 0.') # Safe shortcut usage broadcasts kwargs['local_vars'] as a ufunc out = image + np.random.normal(0, kwargs['local_vars'] ** 0.5) elif mode == 'poisson': # Determine unique values in image & calculate the next power of two vals = len(np.unique(image)) vals = 2 ** np.ceil(np.log2(vals)) # Ensure image is exclusively positive if low_clip == -1.: old_max = image.max() image = (image + 1.) / (old_max + 1.) # Generating noise for each unique value in image. out = np.random.poisson(image * vals) / float(vals) # Return image to original range if input was signed if low_clip == -1.: out = out * (old_max + 1.) - 1. elif mode == 'salt': # Re-call function with mode='s&p' and p=1 (all salt noise) out = random_noise(image, mode='s&p', seed=seed, amount=kwargs['amount'], salt_vs_pepper=1.) elif mode == 'pepper': # Re-call function with mode='s&p' and p=1 (all pepper noise) out = random_noise(image, mode='s&p', seed=seed, amount=kwargs['amount'], salt_vs_pepper=0.) elif mode == 's&p': # This mode makes no effort to avoid repeat sampling. Thus, the # exact number of replaced pixels is only approximate. out = image.copy() # Salt mode num_salt = np.ceil( kwargs['amount'] * image.size * kwargs['salt_vs_pepper']) coords = [np.random.randint(0, i - 1, int(num_salt)) for i in image.shape] out[coords] = 1 # Pepper mode num_pepper = np.ceil( kwargs['amount'] * image.size * (1. - kwargs['salt_vs_pepper'])) coords = [np.random.randint(0, i - 1, int(num_pepper)) for i in image.shape] out[coords] = low_clip elif mode == 'speckle': noise = np.random.normal(kwargs['mean'], kwargs['var'] ** 0.5, image.shape) out = image + image * noise # Clip back to original range, if necessary if clip: out = np.clip(out, low_clip, 1.0) return out scikit-image-0.9.3/skimage/util/shape.py000066400000000000000000000163261223313777300201600ustar00rootroot00000000000000__all__ = ['view_as_blocks', 'view_as_windows'] import numpy as np from numpy.lib.stride_tricks import as_strided def view_as_blocks(arr_in, block_shape): """Block view of the input n-dimensional array (using re-striding). Blocks are non-overlapping views of the input array. Parameters ---------- arr_in: ndarray The n-dimensional input array. block_shape: tuple The shape of the block. Each dimension must divide evenly into the corresponding dimensions of `arr_in`. Returns ------- arr_out: ndarray Block view of the input array. Examples -------- >>> import numpy as np >>> from skimage.util.shape import view_as_blocks >>> A = np.arange(4*4).reshape(4,4) >>> A array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15]]) >>> B = view_as_blocks(A, block_shape=(2, 2)) >>> B[0, 0] array([[0, 1], [4, 5]]) >>> B[0, 1] array([[2, 3], [6, 7]]) >>> B[1, 0, 1, 1] 13 >>> A = np.arange(4*4*6).reshape(4,4,6) >>> A # doctest: +NORMALIZE_WHITESPACE array([[[ 0, 1, 2, 3, 4, 5], [ 6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23]], [[24, 25, 26, 27, 28, 29], [30, 31, 32, 33, 34, 35], [36, 37, 38, 39, 40, 41], [42, 43, 44, 45, 46, 47]], [[48, 49, 50, 51, 52, 53], [54, 55, 56, 57, 58, 59], [60, 61, 62, 63, 64, 65], [66, 67, 68, 69, 70, 71]], [[72, 73, 74, 75, 76, 77], [78, 79, 80, 81, 82, 83], [84, 85, 86, 87, 88, 89], [90, 91, 92, 93, 94, 95]]]) >>> B = view_as_blocks(A, block_shape=(1, 2, 2)) >>> B.shape (4, 2, 3, 1, 2, 2) >>> B[2:, 0, 2] # doctest: +NORMALIZE_WHITESPACE array([[[[52, 53], [58, 59]]], [[[76, 77], [82, 83]]]]) """ # -- basic checks on arguments if not isinstance(block_shape, tuple): raise TypeError('block needs to be a tuple') block_shape = np.array(block_shape) if (block_shape <= 0).any(): raise ValueError("'block_shape' elements must be strictly positive") if block_shape.size != arr_in.ndim: raise ValueError("'block_shape' must have the same length " "as 'arr_in.shape'") arr_shape = np.array(arr_in.shape) if (arr_shape % block_shape).sum() != 0: raise ValueError("'block_shape' is not compatible with 'arr_in'") # -- restride the array to build the block view arr_in = np.ascontiguousarray(arr_in) new_shape = tuple(arr_shape / block_shape) + tuple(block_shape) new_strides = tuple(arr_in.strides * block_shape) + arr_in.strides arr_out = as_strided(arr_in, shape=new_shape, strides=new_strides) return arr_out def view_as_windows(arr_in, window_shape, step=1): """Rolling window view of the input n-dimensional array. Windows are overlapping views of the input array, with adjacent windows shifted by a single row or column (or an index of a higher dimension). Parameters ---------- arr_in: ndarray The n-dimensional input array. window_shape: tuple Defines the shape of the elementary n-dimensional orthotope (better know as hyperrectangle [1]_) of the rolling window view. step : int Number of elements to skip when moving the window forward (by default, move forward by one). Returns ------- arr_out: ndarray (rolling) window view of the input array. Notes ----- One should be very careful with rolling views when it comes to memory usage. Indeed, although a 'view' has the same memory footprint as its base array, the actual array that emerges when this 'view' is used in a computation is generally a (much) larger array than the original, especially for 2-dimensional arrays and above. For example, let us consider a 3 dimensional array of size (100, 100, 100) of ``float64``. This array takes about 8*100**3 Bytes for storage which is just 8 MB. If one decides to build a rolling view on this array with a window of (3, 3, 3) the hypothetical size of the rolling view (if one was to reshape the view for example) would be 8*(100-3+1)**3*3**3 which is about 203 MB! The scaling becomes even worse as the dimension of the input array becomes larger. References ---------- .. [1] http://en.wikipedia.org/wiki/Hyperrectangle Examples -------- >>> import numpy as np >>> from skimage.util.shape import view_as_windows >>> A = np.arange(4*4).reshape(4,4) >>> A array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15]]) >>> window_shape = (2, 2) >>> B = view_as_windows(A, window_shape) >>> B[0, 0] array([[0, 1], [4, 5]]) >>> B[0, 1] array([[1, 2], [5, 6]]) >>> A = np.arange(10) >>> A array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> window_shape = (3,) >>> B = view_as_windows(A, window_shape) >>> B.shape (8, 3) >>> B array([[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7, 8], [7, 8, 9]]) >>> A = np.arange(5*4).reshape(5, 4) >>> A array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19]]) >>> window_shape = (4, 3) >>> B = view_as_windows(A, window_shape) >>> B.shape (2, 2, 4, 3) >>> B # doctest: +NORMALIZE_WHITESPACE array([[[[ 0, 1, 2], [ 4, 5, 6], [ 8, 9, 10], [12, 13, 14]], [[ 1, 2, 3], [ 5, 6, 7], [ 9, 10, 11], [13, 14, 15]]], [[[ 4, 5, 6], [ 8, 9, 10], [12, 13, 14], [16, 17, 18]], [[ 5, 6, 7], [ 9, 10, 11], [13, 14, 15], [17, 18, 19]]]]) """ # -- basic checks on arguments if not isinstance(arr_in, np.ndarray): raise TypeError("`arr_in` must be a numpy ndarray") if not isinstance(window_shape, tuple): raise TypeError("`window_shape` must be a tuple") if not (len(window_shape) == arr_in.ndim): raise ValueError("`window_shape` is incompatible with `arr_in.shape`") if step < 1: raise ValueError("`step` must be >= 1") arr_shape = np.array(arr_in.shape) window_shape = np.array(window_shape, dtype=arr_shape.dtype) if ((arr_shape - window_shape) < 0).any(): raise ValueError("`window_shape` is too large") if ((window_shape - 1) < 0).any(): raise ValueError("`window_shape` is too small") # -- build rolling window view arr_in = np.ascontiguousarray(arr_in) new_shape = tuple((arr_shape - window_shape) // step + 1) + \ tuple(window_shape) arr_strides = np.array(arr_in.strides) new_strides = np.concatenate((arr_strides * step, arr_strides)) arr_out = as_strided(arr_in, shape=new_shape, strides=new_strides) return arr_out scikit-image-0.9.3/skimage/util/tests/000077500000000000000000000000001223313777300176405ustar00rootroot00000000000000scikit-image-0.9.3/skimage/util/tests/test_arraypad.py000066400000000000000000000573751223313777300230750ustar00rootroot00000000000000"""Tests for the pad functions. """ from __future__ import division, absolute_import, print_function from numpy.testing import TestCase, run_module_suite, assert_array_equal from numpy.testing import assert_raises, assert_array_almost_equal import numpy as np from skimage.util import pad class TestStatistic(TestCase): def test_check_mean_stat_length(self): a = np.arange(100).astype('f') a = pad(a, ((25, 20), ), 'mean', stat_length=((2, 3), )) b = np.array([ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26., 27., 28., 29., 30., 31., 32., 33., 34., 35., 36., 37., 38., 39., 40., 41., 42., 43., 44., 45., 46., 47., 48., 49., 50., 51., 52., 53., 54., 55., 56., 57., 58., 59., 60., 61., 62., 63., 64., 65., 66., 67., 68., 69., 70., 71., 72., 73., 74., 75., 76., 77., 78., 79., 80., 81., 82., 83., 84., 85., 86., 87., 88., 89., 90., 91., 92., 93., 94., 95., 96., 97., 98., 99., 98., 98., 98., 98., 98., 98., 98., 98., 98., 98., 98., 98., 98., 98., 98., 98., 98., 98., 98., 98.]) assert_array_equal(a, b) def test_check_maximum_1(self): a = np.arange(100) a = pad(a, (25, 20), 'maximum') b = np.array([ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99]) assert_array_equal(a, b) def test_check_maximum_2(self): a = np.arange(100) + 1 a = pad(a, (25, 20), 'maximum') b = np.array([ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100]) assert_array_equal(a, b) def test_check_minimum_1(self): a = np.arange(100) a = pad(a, (25, 20), 'minimum') b = np.array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) assert_array_equal(a, b) def test_check_minimum_2(self): a = np.arange(100) + 2 a = pad(a, (25, 20), 'minimum') b = np.array([ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]) assert_array_equal(a, b) def test_check_median(self): a = np.arange(100).astype('f') a = pad(a, (25, 20), 'median') b = np.array([ 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26., 27., 28., 29., 30., 31., 32., 33., 34., 35., 36., 37., 38., 39., 40., 41., 42., 43., 44., 45., 46., 47., 48., 49., 50., 51., 52., 53., 54., 55., 56., 57., 58., 59., 60., 61., 62., 63., 64., 65., 66., 67., 68., 69., 70., 71., 72., 73., 74., 75., 76., 77., 78., 79., 80., 81., 82., 83., 84., 85., 86., 87., 88., 89., 90., 91., 92., 93., 94., 95., 96., 97., 98., 99., 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5]) assert_array_equal(a, b) def test_check_median_01(self): a = np.array([[3, 1, 4], [4, 5, 9], [9, 8, 2]]) a = pad(a, 1, 'median') b = np.array([ [4, 4, 5, 4, 4], [3, 3, 1, 4, 3], [5, 4, 5, 9, 5], [8, 9, 8, 2, 8], [4, 4, 5, 4, 4]]) assert_array_equal(a, b) def test_check_median_02(self): a = np.array([[3, 1, 4], [4, 5, 9], [9, 8, 2]]) a = pad(a.T, 1, 'median').T b = np.array([ [5, 4, 5, 4, 5], [3, 3, 1, 4, 3], [5, 4, 5, 9, 5], [8, 9, 8, 2, 8], [5, 4, 5, 4, 5]]) assert_array_equal(a, b) def test_check_mean_shape_one(self): a = [[4, 5, 6]] a = pad(a, (5, 7), 'mean', stat_length=2) b = np.array([ [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6], [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6], [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6], [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6], [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6], [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6], [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6], [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6], [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6], [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6], [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6], [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6], [4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6]]) assert_array_equal(a, b) def test_check_mean_2(self): a = np.arange(100).astype('f') a = pad(a, (25, 20), 'mean') b = np.array([ 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26., 27., 28., 29., 30., 31., 32., 33., 34., 35., 36., 37., 38., 39., 40., 41., 42., 43., 44., 45., 46., 47., 48., 49., 50., 51., 52., 53., 54., 55., 56., 57., 58., 59., 60., 61., 62., 63., 64., 65., 66., 67., 68., 69., 70., 71., 72., 73., 74., 75., 76., 77., 78., 79., 80., 81., 82., 83., 84., 85., 86., 87., 88., 89., 90., 91., 92., 93., 94., 95., 96., 97., 98., 99., 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5]) assert_array_equal(a, b) class TestConstant(TestCase): def test_check_constant(self): a = np.arange(100) a = pad(a, (25, 20), 'constant', constant_values=(10, 20)) b = np.array([10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20]) assert_array_equal(a, b) class TestLinearRamp(TestCase): def test_check_simple(self): a = np.arange(100).astype('f') a = pad(a, (25, 20), 'linear_ramp', end_values=(4, 5)) b = np.array([ 4.00, 3.84, 3.68, 3.52, 3.36, 3.20, 3.04, 2.88, 2.72, 2.56, 2.40, 2.24, 2.08, 1.92, 1.76, 1.60, 1.44, 1.28, 1.12, 0.96, 0.80, 0.64, 0.48, 0.32, 0.16, 0.00, 1.00, 2.00, 3.00, 4.00, 5.00, 6.00, 7.00, 8.00, 9.00, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0, 81.0, 82.0, 83.0, 84.0, 85.0, 86.0, 87.0, 88.0, 89.0, 90.0, 91.0, 92.0, 93.0, 94.0, 95.0, 96.0, 97.0, 98.0, 99.0, 94.3, 89.6, 84.9, 80.2, 75.5, 70.8, 66.1, 61.4, 56.7, 52.0, 47.3, 42.6, 37.9, 33.2, 28.5, 23.8, 19.1, 14.4, 9.7, 5.]) assert_array_almost_equal(a, b, decimal=5) class TestReflect(TestCase): def test_check_simple(self): a = np.arange(100) a = pad(a, (25, 20), 'reflect') b = np.array([ 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79]) assert_array_equal(a, b) def test_check_large_pad(self): a = [[4, 5, 6], [6, 7, 8]] a = pad(a, (5, 7), 'reflect') b = np.array([ [7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5]]) assert_array_equal(a, b) def test_check_shape(self): a = [[4, 5, 6]] a = pad(a, (5, 7), 'reflect') b = np.array([ [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5], [5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5]]) assert_array_equal(a, b) def test_check_01(self): a = pad([1, 2, 3], 2, 'reflect') b = np.array([3, 2, 1, 2, 3, 2, 1]) assert_array_equal(a, b) def test_check_02(self): a = pad([1, 2, 3], 3, 'reflect') b = np.array([2, 3, 2, 1, 2, 3, 2, 1, 2]) assert_array_equal(a, b) def test_check_03(self): a = pad([1, 2, 3], 4, 'reflect') b = np.array([1, 2, 3, 2, 1, 2, 3, 2, 1, 2, 3]) assert_array_equal(a, b) class TestWrap(TestCase): def test_check_simple(self): a = np.arange(100) a = pad(a, (25, 20), 'wrap') b = np.array([ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]) assert_array_equal(a, b) def test_check_large_pad(self): a = np.arange(12) a = np.reshape(a, (3, 4)) a = pad(a, (10, 12), 'wrap') b = np.array([ [10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11], [ 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], [ 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7], [10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11], [ 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], [ 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7], [10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11], [ 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], [ 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7], [10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11], [ 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], [ 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7], [10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11], [ 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], [ 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7], [10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11], [ 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], [ 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7], [10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11], [ 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], [ 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7], [10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11], [ 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], [ 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7], [10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11]]) assert_array_equal(a, b) def test_check_01(self): a = pad([1, 2, 3], 3, 'wrap') b = np.array([1, 2, 3, 1, 2, 3, 1, 2, 3]) assert_array_equal(a, b) def test_check_02(self): a = pad([1, 2, 3], 4, 'wrap') b = np.array([3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1]) assert_array_equal(a, b) class TestStatLen(TestCase): def test_check_simple(self): a = np.arange(30) a = np.reshape(a, (6, 5)) a = pad(a, ((2, 3), (3, 2)), mode='mean', stat_length=(3,)) b = np.array([[ 6, 6, 6, 5, 6, 7, 8, 9, 8, 8], [ 6, 6, 6, 5, 6, 7, 8, 9, 8, 8], [ 1, 1, 1, 0, 1, 2, 3, 4, 3, 3], [ 6, 6, 6, 5, 6, 7, 8, 9, 8, 8], [11, 11, 11, 10, 11, 12, 13, 14, 13, 13], [16, 16, 16, 15, 16, 17, 18, 19, 18, 18], [21, 21, 21, 20, 21, 22, 23, 24, 23, 23], [26, 26, 26, 25, 26, 27, 28, 29, 28, 28], [21, 21, 21, 20, 21, 22, 23, 24, 23, 23], [21, 21, 21, 20, 21, 22, 23, 24, 23, 23], [21, 21, 21, 20, 21, 22, 23, 24, 23, 23]]) assert_array_equal(a, b) class TestEdge(TestCase): def test_check_simple(self): a = np.arange(12) a = np.reshape(a, (4, 3)) a = pad(a, ((2, 3), (3, 2)), 'edge') b = np.array([ [0, 0, 0, 0, 1, 2, 2, 2], [0, 0, 0, 0, 1, 2, 2, 2], [0, 0, 0, 0, 1, 2, 2, 2], [3, 3, 3, 3, 4, 5, 5, 5], [6, 6, 6, 6, 7, 8, 8, 8], [9, 9, 9, 9, 10, 11, 11, 11], [9, 9, 9, 9, 10, 11, 11, 11], [9, 9, 9, 9, 10, 11, 11, 11], [9, 9, 9, 9, 10, 11, 11, 11]]) assert_array_equal(a, b) def test_check_too_many_pad_axes(): arr = np.arange(30) arr = np.reshape(arr, (6, 5)) kwargs = dict(mode='mean', stat_length=(3, )) assert_raises(ValueError, pad, arr, ((2, 3), (3, 2), (4, 5)), **kwargs) def test_check_negative_stat_length(): arr = np.arange(30) arr = np.reshape(arr, (6, 5)) kwargs = dict(mode='mean', stat_length=(-3, )) assert_raises(ValueError, pad, arr, ((2, 3), (3, 2)), **kwargs) def test_check_negative_pad_width(): arr = np.arange(30) arr = np.reshape(arr, (6, 5)) kwargs = dict(mode='mean', stat_length=(3, )) assert_raises(ValueError, pad, arr, ((-2, 3), (3, 2)), **kwargs) def test_pad_one_axis_three_ways(): arr = np.arange(30) arr = np.reshape(arr, (6, 5)) kwargs = dict(mode='mean', stat_length=(3, )) assert_raises(ValueError, pad, arr, ((2, 3, 4), (3, 2)), **kwargs) def test_zero_pad_width(): arr = np.arange(30) arr = np.reshape(arr, (6, 5)) for pad_width in (0, (0, 0), ((0, 0), (0, 0))): assert np.all(arr == pad(arr, pad_width, mode='constant')) if __name__ == "__main__": run_module_suite() scikit-image-0.9.3/skimage/util/tests/test_dtype.py000066400000000000000000000062751223313777300224100ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_equal, assert_raises from skimage import img_as_int, img_as_float, \ img_as_uint, img_as_ubyte from skimage.util.dtype import convert dtype_range = {np.uint8: (0, 255), np.uint16: (0, 65535), np.int8: (-128, 127), np.int16: (-32768, 32767), np.float32: (-1.0, 1.0), np.float64: (-1.0, 1.0)} def _verify_range(msg, x, vmin, vmax, dtype): assert_equal(x[0], vmin) assert_equal(x[-1], vmax) assert x.dtype == dtype def test_range(): for dtype in dtype_range: imin, imax = dtype_range[dtype] x = np.linspace(imin, imax, 10).astype(dtype) for (f, dt) in [(img_as_int, np.int16), (img_as_float, np.float64), (img_as_uint, np.uint16), (img_as_ubyte, np.ubyte)]: y = f(x) omin, omax = dtype_range[dt] if imin == 0 or omin == 0: omin = 0 imin = 0 yield (_verify_range, "From %s to %s" % (np.dtype(dtype), np.dtype(dt)), y, omin, omax, np.dtype(dt)) def test_range_extra_dtypes(): """Test code paths that are not skipped by `test_range`""" # Add non-standard data types that are allowed by the `convert` function. dtype_range_extra = dtype_range.copy() dtype_range_extra.update({np.int32: (-2147483648, 2147483647), np.uint32: (0, 4294967295)}) dtype_pairs = [(np.uint8, np.uint32), (np.int8, np.uint32), (np.int8, np.int32), (np.int32, np.int8), (np.float64, np.float32), (np.int32, np.float32)] for dtype_in, dt in dtype_pairs: imin, imax = dtype_range_extra[dtype_in] x = np.linspace(imin, imax, 10).astype(dtype_in) y = convert(x, dt) omin, omax = dtype_range_extra[dt] yield (_verify_range, "From %s to %s" % (np.dtype(dtype_in), np.dtype(dt)), y, omin, omax, np.dtype(dt)) def test_unsupported_dtype(): x = np.arange(10).astype(np.uint64) assert_raises(ValueError, img_as_int, x) def test_float_out_of_range(): too_high = np.array([2], dtype=np.float32) assert_raises(ValueError, img_as_int, too_high) too_low = np.array([-2], dtype=np.float32) assert_raises(ValueError, img_as_int, too_low) def test_copy(): x = np.array([1], dtype=np.float64) y = img_as_float(x) z = img_as_float(x, force_copy=True) assert y is x assert z is not x def test_bool(): img_ = np.zeros((10, 10), np.bool_) img8 = np.zeros((10, 10), np.bool8) img_[1, 1] = True img8[1, 1] = True for (func, dt) in [(img_as_int, np.int16), (img_as_float, np.float64), (img_as_uint, np.uint16), (img_as_ubyte, np.ubyte)]: converted_ = func(img_) assert np.sum(converted_) == dtype_range[dt][1] converted8 = func(img8) assert np.sum(converted8) == dtype_range[dt][1] if __name__ == '__main__': np.testing.run_module_suite() scikit-image-0.9.3/skimage/util/tests/test_montage.py000066400000000000000000000054371223313777300227140ustar00rootroot00000000000000from nose.tools import assert_equal, raises from numpy.testing import assert_array_equal import numpy as np from skimage.util.montage import montage2d def test_simple(): n_images = 3 height, width = 2, 3, arr_in = np.arange(n_images * height * width) arr_in = arr_in.reshape(n_images, height, width) arr_out = montage2d(arr_in) gt = np.array( [[ 0. , 1. , 2. , 6. , 7. , 8. ], [ 3. , 4. , 5. , 9. , 10. , 11. ], [ 12. , 13. , 14. , 8.5, 8.5, 8.5], [ 15. , 16. , 17. , 8.5, 8.5, 8.5]] ) assert_array_equal(arr_out, gt) def test_fill(): n_images = 3 height, width = 2, 3, arr_in = np.arange(n_images * height * width) arr_in = arr_in.reshape(n_images, height, width) arr_out = montage2d(arr_in, fill=0) gt = np.array( [[ 0. , 1. , 2. , 6. , 7. , 8. ], [ 3. , 4. , 5. , 9. , 10. , 11. ], [ 12. , 13. , 14. , 0. , 0. , 0. ], [ 15. , 16. , 17. , 0. , 0. , 0. ]] ) assert_array_equal(arr_out, gt) def test_shape(): n_images = 15 height, width = 11, 7 arr_in = np.arange(n_images * height * width) arr_in = arr_in.reshape(n_images, height, width) alpha = int(np.ceil(np.sqrt(n_images))) arr_out = montage2d(arr_in) assert_equal(arr_out.shape, (alpha * height, alpha * width)) def test_grid_shape(): n_images = 6 height, width = 2, 2 arr_in = np.arange(n_images * height * width, dtype=np.float32) arr_in = arr_in.reshape(n_images, height, width) arr_out = montage2d(arr_in, grid_shape=(3,2)) correct_arr_out = np.array( [[ 0., 1., 4., 5.], [ 2., 3., 6., 7.], [ 8., 9., 12., 13.], [ 10., 11., 14., 15.], [ 16., 17., 20., 21.], [ 18., 19., 22., 23.]] ) assert_array_equal(arr_out, correct_arr_out) def test_rescale_intensity(): n_images = 4 height, width = 3, 3 arr_in = np.arange(n_images * height * width, dtype=np.float32) arr_in = arr_in.reshape(n_images, height, width) arr_out = montage2d(arr_in, rescale_intensity=True) gt = np.array( [[ 0. , 0.125, 0.25 , 0. , 0.125, 0.25 ], [ 0.375, 0.5 , 0.625, 0.375, 0.5 , 0.625], [ 0.75 , 0.875, 1. , 0.75 , 0.875, 1. ], [ 0. , 0.125, 0.25 , 0. , 0.125, 0.25 ], [ 0.375, 0.5 , 0.625, 0.375, 0.5 , 0.625], [ 0.75 , 0.875, 1. , 0.75 , 0.875, 1. ]] ) assert_equal(arr_out.min(), 0.0) assert_equal(arr_out.max(), 1.0) assert_array_equal(arr_out, gt) @raises(AssertionError) def test_error_ndim(): arr_error = np.random.randn(1, 2, 3, 4) montage2d(arr_error) if __name__ == '__main__': np.testing.run_module_suite() scikit-image-0.9.3/skimage/util/tests/test_random_noise.py000066400000000000000000000166611223313777300237400ustar00rootroot00000000000000from numpy.testing import assert_array_equal, assert_allclose, assert_raises import numpy as np from skimage.data import camera from skimage.util import random_noise, img_as_float def test_set_seed(): seed = 42 cam = camera() test = random_noise(cam, seed=seed) assert_array_equal(test, random_noise(cam, seed=seed)) def test_salt(): seed = 42 cam = img_as_float(camera()) cam_noisy = random_noise(cam, seed=seed, mode='salt', amount=0.15) saltmask = cam != cam_noisy # Ensure all changes are to 1.0 assert_allclose(cam_noisy[saltmask], np.ones(saltmask.sum())) # Ensure approximately correct amount of noise was added proportion = float(saltmask.sum()) / (cam.shape[0] * cam.shape[1]) assert 0.11 < proportion <= 0.15 def test_pepper(): seed = 42 cam = img_as_float(camera()) data_signed = cam * 2. - 1. # Same image, on range [-1, 1] cam_noisy = random_noise(cam, seed=seed, mode='pepper', amount=0.15) peppermask = cam != cam_noisy # Ensure all changes are to 1.0 assert_allclose(cam_noisy[peppermask], np.zeros(peppermask.sum())) # Ensure approximately correct amount of noise was added proportion = float(peppermask.sum()) / (cam.shape[0] * cam.shape[1]) assert 0.11 < proportion <= 0.15 # Check to make sure pepper gets added properly to signed images orig_zeros = (data_signed == -1).sum() cam_noisy_signed = random_noise(data_signed, seed=seed, mode='pepper', amount=.15) proportion = (float((cam_noisy_signed == -1).sum() - orig_zeros) / (cam.shape[0] * cam.shape[1])) assert 0.11 < proportion <= 0.15 def test_salt_and_pepper(): seed = 42 cam = img_as_float(camera()) cam_noisy = random_noise(cam, seed=seed, mode='s&p', amount=0.15, salt_vs_pepper=0.25) saltmask = np.logical_and(cam != cam_noisy, cam_noisy == 1.) peppermask = np.logical_and(cam != cam_noisy, cam_noisy == 0.) # Ensure all changes are to 0. or 1. assert_allclose(cam_noisy[saltmask], np.ones(saltmask.sum())) assert_allclose(cam_noisy[peppermask], np.zeros(peppermask.sum())) # Ensure approximately correct amount of noise was added proportion = float( saltmask.sum() + peppermask.sum()) / (cam.shape[0] * cam.shape[1]) assert 0.11 < proportion <= 0.18 # Verify the relative amount of salt vs. pepper is close to expected assert 0.18 < saltmask.sum() / float(peppermask.sum()) < 0.32 def test_gaussian(): seed = 42 data = np.zeros((128, 128)) + 0.5 data_gaussian = random_noise(data, seed=seed, var=0.01) assert 0.008 < data_gaussian.var() < 0.012 data_gaussian = random_noise(data, seed=seed, mean=0.3, var=0.015) assert 0.28 < data_gaussian.mean() - 0.5 < 0.32 assert 0.012 < data_gaussian.var() < 0.018 def test_localvar(): seed = 42 data = np.zeros((128, 128)) + 0.5 local_vars = np.zeros((128, 128)) + 0.001 local_vars[:64, 64:] = 0.1 local_vars[64:, :64] = 0.25 local_vars[64:, 64:] = 0.45 data_gaussian = random_noise(data, mode='localvar', seed=seed, local_vars=local_vars, clip=False) assert 0. < data_gaussian[:64, :64].var() < 0.002 assert 0.095 < data_gaussian[:64, 64:].var() < 0.105 assert 0.245 < data_gaussian[64:, :64].var() < 0.255 assert 0.445 < data_gaussian[64:, 64:].var() < 0.455 # Ensure local variance bounds checking works properly bad_local_vars = np.zeros_like(data) assert_raises(ValueError, random_noise, data, mode='localvar', seed=seed, local_vars=bad_local_vars) bad_local_vars += 0.1 bad_local_vars[0, 0] = -1 assert_raises(ValueError, random_noise, data, mode='localvar', seed=seed, local_vars=bad_local_vars) def test_speckle(): seed = 42 data = np.zeros((128, 128)) + 0.1 np.random.seed(seed=seed) noise = np.random.normal(0.1, 0.02 ** 0.5, (128, 128)) expected = np.clip(data + data * noise, 0, 1) data_speckle = random_noise(data, mode='speckle', seed=seed, mean=0.1, var=0.02) assert_allclose(expected, data_speckle) def test_poisson(): seed = 42 data = camera() # 512x512 grayscale uint8 cam_noisy = random_noise(data, mode='poisson', seed=seed) cam_noisy2 = random_noise(data, mode='poisson', seed=seed, clip=False) np.random.seed(seed=seed) expected = np.random.poisson(img_as_float(data) * 256) / 256. assert_allclose(cam_noisy, np.clip(expected, 0., 1.)) assert_allclose(cam_noisy2, expected) def test_clip_poisson(): seed = 42 data = camera() # 512x512 grayscale uint8 data_signed = img_as_float(data) * 2. - 1. # Same image, on range [-1, 1] # Signed and unsigned, clipped cam_poisson = random_noise(data, mode='poisson', seed=seed, clip=True) cam_poisson2 = random_noise(data_signed, mode='poisson', seed=seed, clip=True) assert (cam_poisson.max() == 1.) and (cam_poisson.min() == 0.) assert (cam_poisson2.max() == 1.) and (cam_poisson2.min() == -1.) # Signed and unsigned, unclipped cam_poisson = random_noise(data, mode='poisson', seed=seed, clip=False) cam_poisson2 = random_noise(data_signed, mode='poisson', seed=seed, clip=False) assert (cam_poisson.max() > 1.15) and (cam_poisson.min() == 0.) assert (cam_poisson2.max() > 1.3) and (cam_poisson2.min() == -1.) def test_clip_gaussian(): seed = 42 data = camera() # 512x512 grayscale uint8 data_signed = img_as_float(data) * 2. - 1. # Same image, on range [-1, 1] # Signed and unsigned, clipped cam_gauss = random_noise(data, mode='gaussian', seed=seed, clip=True) cam_gauss2 = random_noise(data_signed, mode='gaussian', seed=seed, clip=True) assert (cam_gauss.max() == 1.) and (cam_gauss.min() == 0.) assert (cam_gauss2.max() == 1.) and (cam_gauss2.min() == -1.) # Signed and unsigned, unclipped cam_gauss = random_noise(data, mode='gaussian', seed=seed, clip=False) cam_gauss2 = random_noise(data_signed, mode='gaussian', seed=seed, clip=False) assert (cam_gauss.max() > 1.22) and (cam_gauss.min() < -0.36) assert (cam_gauss2.max() > 1.219) and (cam_gauss2.min() < -1.337) def test_clip_speckle(): seed = 42 data = camera() # 512x512 grayscale uint8 data_signed = img_as_float(data) * 2. - 1. # Same image, on range [-1, 1] # Signed and unsigned, clipped cam_speckle = random_noise(data, mode='speckle', seed=seed, clip=True) cam_speckle2 = random_noise(data_signed, mode='speckle', seed=seed, clip=True) assert (cam_speckle.max() == 1.) and (cam_speckle.min() == 0.) assert (cam_speckle2.max() == 1.) and (cam_speckle2.min() == -1.) # Signed and unsigned, unclipped cam_speckle = random_noise(data, mode='speckle', seed=seed, clip=False) cam_speckle2 = random_noise(data_signed, mode='speckle', seed=seed, clip=False) assert (cam_speckle.max() > 1.219) and (cam_speckle.min() == 0.) assert (cam_speckle2.max() > 1.219) and (cam_speckle2.min() < -1.306) def test_bad_mode(): data = np.zeros((64, 64)) assert_raises(KeyError, random_noise, data, 'perlin') if __name__ == '__main__': np.testing.run_module_suite() scikit-image-0.9.3/skimage/util/tests/test_regular_grid.py000066400000000000000000000020201223313777300237110ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_equal from skimage.util import regular_grid def test_regular_grid_full(): ar = np.zeros((2, 2)) g = regular_grid(ar, 25) assert_equal(g, [slice(None, None, None), slice(None, None, None)]) ar[g] = 1 assert_equal(ar.size, ar.sum()) def test_regular_grid_2d_8(): ar = np.zeros((20, 40)) g = regular_grid(ar.shape, 8) assert_equal(g, [slice(5.0, None, 10.0), slice(5.0, None, 10.0)]) ar[g] = 1 assert_equal(ar.sum(), 8) def test_regular_grid_2d_32(): ar = np.zeros((20, 40)) g = regular_grid(ar.shape, 32) assert_equal(g, [slice(2.0, None, 5.0), slice(2.0, None, 5.0)]) ar[g] = 1 assert_equal(ar.sum(), 32) def test_regular_grid_3d_8(): ar = np.zeros((3, 20, 40)) g = regular_grid(ar.shape, 8) assert_equal(g, [slice(1.0, None, 3.0), slice(5.0, None, 10.0), slice(5.0, None, 10.0)]) ar[g] = 1 assert_equal(ar.sum(), 8) if __name__ == '__main__': np.testing.run_module_suite() scikit-image-0.9.3/skimage/util/tests/test_shape.py000066400000000000000000000077361223313777300223660ustar00rootroot00000000000000import numpy as np from nose.tools import raises from numpy.testing import assert_equal from skimage.util.shape import view_as_blocks, view_as_windows @raises(TypeError) def test_view_as_blocks_block_not_a_tuple(): A = np.arange(10) view_as_blocks(A, [5]) @raises(ValueError) def test_view_as_blocks_negative_shape(): A = np.arange(10) view_as_blocks(A, (-2,)) @raises(ValueError) def test_view_as_blocks_block_too_large(): A = np.arange(10) view_as_blocks(A, (11,)) @raises(ValueError) def test_view_as_blocks_wrong_block_dimension(): A = np.arange(10) view_as_blocks(A, (2, 2)) @raises(ValueError) def test_view_as_blocks_1D_array_wrong_block_shape(): A = np.arange(10) view_as_blocks(A, (3,)) def test_view_as_blocks_1D_array(): A = np.arange(10) B = view_as_blocks(A, (5,)) assert_equal(B, np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])) def test_view_as_blocks_2D_array(): A = np.arange(4 * 4).reshape(4, 4) B = view_as_blocks(A, (2, 2)) assert_equal(B[0, 1], np.array([[2, 3], [6, 7]])) assert_equal(B[1, 0, 1, 1], 13) def test_view_as_blocks_3D_array(): A = np.arange(4 * 4 * 6).reshape(4, 4, 6) B = view_as_blocks(A, (1, 2, 2)) assert_equal(B.shape, (4, 2, 3, 1, 2, 2)) assert_equal(B[2:, 0, 2], np.array([[[[52, 53], [58, 59]]], [[[76, 77], [82, 83]]]])) @raises(TypeError) def test_view_as_windows_input_not_array(): A = [1, 2, 3, 4, 5] view_as_windows(A, (2,)) @raises(TypeError) def test_view_as_windows_window_not_tuple(): A = np.arange(10) view_as_windows(A, [2]) @raises(ValueError) def test_view_as_windows_wrong_window_dimension(): A = np.arange(10) view_as_windows(A, (2, 2)) @raises(ValueError) def test_view_as_windows_negative_window_length(): A = np.arange(10) view_as_windows(A, (-1,)) @raises(ValueError) def test_view_as_windows_window_too_large(): A = np.arange(10) view_as_windows(A, (11,)) def test_view_as_windows_1D(): A = np.arange(10) window_shape = (3,) B = view_as_windows(A, window_shape) assert_equal(B, np.array([[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7, 8], [7, 8, 9]])) def test_view_as_windows_2D(): A = np.arange(5 * 4).reshape(5, 4) window_shape = (4, 3) B = view_as_windows(A, window_shape) assert_equal(B.shape, (2, 2, 4, 3)) assert_equal(B, np.array([[[[0, 1, 2], [4, 5, 6], [8, 9, 10], [12, 13, 14]], [[1, 2, 3], [5, 6, 7], [9, 10, 11], [13, 14, 15]]], [[[4, 5, 6], [8, 9, 10], [12, 13, 14], [16, 17, 18]], [[5, 6, 7], [9, 10, 11], [13, 14, 15], [17, 18, 19]]]])) def test_view_as_windows_With_skip(): A = np.arange(20).reshape((5, 4)) B = view_as_windows(A, (2, 2), step=2) assert_equal(B, [[[[0, 1], [4, 5]], [[2, 3], [6, 7]]], [[[8, 9], [12, 13]], [[10, 11], [14, 15]]]]) C = view_as_windows(A, (2, 2), step=4) assert_equal(C.shape, (1, 1, 2, 2)) if __name__ == '__main__': np.testing.run_module_suite() scikit-image-0.9.3/skimage/util/tests/test_unique_rows.py000066400000000000000000000021471223313777300236350ustar00rootroot00000000000000import numpy as np from numpy.testing import assert_equal, assert_raises from skimage.util import unique_rows def test_discontiguous_array(): ar = np.array([[1, 0, 1], [0, 1, 0], [1, 0, 1]], np.uint8) ar = ar[::2] ar_out = unique_rows(ar) desired_ar_out = np.array([[1, 0, 1]], np.uint8) assert_equal(ar_out, desired_ar_out) def test_uint8_array(): ar = np.array([[1, 0, 1], [0, 1, 0], [1, 0, 1]], np.uint8) ar_out = unique_rows(ar) desired_ar_out = np.array([[0, 1, 0], [1, 0, 1]], np.uint8) assert_equal(ar_out, desired_ar_out) def test_float_array(): ar = np.array([[1.1, 0.0, 1.1], [0.0, 1.1, 0.0], [1.1, 0.0, 1.1]], np.float) ar_out = unique_rows(ar) desired_ar_out = np.array([[0.0, 1.1, 0.0], [1.1, 0.0, 1.1]], np.float) assert_equal(ar_out, desired_ar_out) def test_1d_array(): ar = np.array([1, 0, 1, 1], np.uint8) assert_raises(ValueError, unique_rows, ar) def test_3d_array(): ar = np.arange(8).reshape((2, 2, 2)) assert_raises(ValueError, unique_rows, ar) if __name__ == '__main__': np.testing.run_module_suite() scikit-image-0.9.3/skimage/util/unique.py000066400000000000000000000027421223313777300203630ustar00rootroot00000000000000import numpy as np def unique_rows(ar): """Remove repeated rows from a 2D array. In particular, if given an array of coordinates of shape (Npoints, Ndim), it will remove repeated points. Parameters ---------- ar : 2-D ndarray The input array. Returns ------- ar_out : 2-D ndarray A copy of the input array with repeated rows removed. Raises ------ ValueError : if `ar` is not two-dimensional. Notes ----- The function will generate a copy of `ar` if it is not C-contiguous, which will negatively affect performance for large input arrays. Examples -------- >>> ar = np.array([[1, 0, 1], ... [0, 1, 0], ... [1, 0, 1]], np.uint8) >>> unique_rows(ar) array([[0, 1, 0], [1, 0, 1]], dtype=uint8) """ if ar.ndim != 2: raise ValueError("unique_rows() only makes sense for 2D arrays, " "got %dd" % ar.ndim) # the view in the next line only works if the array is C-contiguous ar = np.ascontiguousarray(ar) # np.unique() finds identical items in a raveled array. To make it # see each row as a single item, we create a view of each row as a # byte string of length itemsize times number of columns in `ar` ar_row_view = ar.view('|S%d' % (ar.itemsize * ar.shape[1])) _, unique_row_indices = np.unique(ar_row_view, return_index=True) ar_out = ar[unique_row_indices] return ar_out scikit-image-0.9.3/skimage/viewer/000077500000000000000000000000001223313777300170225ustar00rootroot00000000000000scikit-image-0.9.3/skimage/viewer/__init__.py000066400000000000000000000000631223313777300211320ustar00rootroot00000000000000from .viewers import ImageViewer, CollectionViewer scikit-image-0.9.3/skimage/viewer/canvastools/000077500000000000000000000000001223313777300213565ustar00rootroot00000000000000scikit-image-0.9.3/skimage/viewer/canvastools/__init__.py000066400000000000000000000001631223313777300234670ustar00rootroot00000000000000from .linetool import LineTool, ThickLineTool from .recttool import RectangleTool from .painttool import PaintTool scikit-image-0.9.3/skimage/viewer/canvastools/base.py000066400000000000000000000126611223313777300226500ustar00rootroot00000000000000import numpy as np try: from matplotlib import lines except ImportError: print("Could not import matplotlib -- skimage.viewer not available.") __all__ = ['CanvasToolBase', 'ToolHandles'] def _pass(*args): pass class CanvasToolBase(object): """Base canvas tool for matplotlib axes. Parameters ---------- ax : :class:`matplotlib.axes.Axes` Matplotlib axes where tool is displayed. on_move : function Function called whenever a control handle is moved. This function must accept the end points of line as the only argument. on_release : function Function called whenever the control handle is released. on_enter : function Function called whenever the "enter" key is pressed. useblit : bool If True, update canvas by blitting, which is much faster than normal redrawing (turn off for debugging purposes). """ def __init__(self, ax, on_move=None, on_enter=None, on_release=None, useblit=True): self.ax = ax self.canvas = ax.figure.canvas self.img_background = None self.cids = [] self._artists = [] self.active = True if useblit: self.connect_event('draw_event', self._blit_on_draw_event) self.useblit = useblit self.callback_on_move = _pass if on_move is None else on_move self.callback_on_enter = _pass if on_enter is None else on_enter self.callback_on_release = _pass if on_release is None else on_release self.connect_event('key_press_event', self._on_key_press) def connect_event(self, event, callback): """Connect callback with an event. This should be used in lieu of `figure.canvas.mpl_connect` since this function stores call back ids for later clean up. """ cid = self.canvas.mpl_connect(event, callback) self.cids.append(cid) def disconnect_events(self): """Disconnect all events created by this widget.""" for c in self.cids: self.canvas.mpl_disconnect(c) def ignore(self, event): """Return True if event should be ignored. This method (or a version of it) should be called at the beginning of any event callback. """ return not self.active def set_visible(self, val): for artist in self._artists: artist.set_visible(val) def _blit_on_draw_event(self, event=None): self.img_background = self.canvas.copy_from_bbox(self.ax.bbox) self._draw_artists() def _draw_artists(self): for artist in self._artists: self.ax.draw_artist(artist) def remove(self): """Remove artists and events from axes. Note that the naming here mimics the interface of Matplotlib artists. """ #TODO: For some reason, RectangleTool doesn't get properly removed self.disconnect_events() for a in self._artists: a.remove() def redraw(self): """Redraw image and canvas artists. This method should be called by subclasses when artists are updated. """ if self.useblit and self.img_background is not None: self.canvas.restore_region(self.img_background) self._draw_artists() self.canvas.blit(self.ax.bbox) else: self.canvas.draw_idle() def _on_key_press(self, event): if event.key == 'enter': self.callback_on_enter(self.geometry) self.set_visible(False) self.redraw() @property def geometry(self): """Geometry information that gets passed to callback functions.""" raise NotImplementedError class ToolHandles(object): """Control handles for canvas tools. Parameters ---------- ax : :class:`matplotlib.axes.Axes` Matplotlib axes where tool handles are displayed. x, y : 1D arrays Coordinates of control handles. marker : str Shape of marker used to display handle. See `matplotlib.pyplot.plot`. marker_props : dict Additional marker properties. See :class:`matplotlib.lines.Line2D`. """ def __init__(self, ax, x, y, marker='o', marker_props=None): self.ax = ax props = dict(marker=marker, markersize=7, mfc='w', ls='none', alpha=0.5, visible=False) props.update(marker_props if marker_props is not None else {}) self._markers = lines.Line2D(x, y, animated=True, **props) self.ax.add_line(self._markers) self.artist = self._markers @property def x(self): return self._markers.get_xdata() @property def y(self): return self._markers.get_ydata() def set_data(self, pts, y=None): """Set x and y positions of handles""" if y is not None: x = pts pts = np.array([x, y]) self._markers.set_data(pts) def set_visible(self, val): self._markers.set_visible(val) def set_animated(self, val): self._markers.set_animated(val) def draw(self): self.ax.draw_artist(self._markers) def closest(self, x, y): """Return index and pixel distance to closest index.""" pts = np.transpose((self.x, self.y)) # Transform data coordinates to pixel coordinates. pts = self.ax.transData.transform(pts) diff = pts - ((x, y)) dist = np.sqrt(np.sum(diff**2, axis=1)) return np.argmin(dist), np.min(dist) scikit-image-0.9.3/skimage/viewer/canvastools/linetool.py000066400000000000000000000147711223313777300235670ustar00rootroot00000000000000import numpy as np try: from matplotlib import lines except ImportError: print("Could not import matplotlib -- skimage.viewer not available.") from skimage.viewer.canvastools.base import CanvasToolBase, ToolHandles __all__ = ['LineTool', 'ThickLineTool'] class LineTool(CanvasToolBase): """Widget for line selection in a plot. Parameters ---------- ax : :class:`matplotlib.axes.Axes` Matplotlib axes where tool is displayed. on_move : function Function called whenever a control handle is moved. This function must accept the end points of line as the only argument. on_release : function Function called whenever the control handle is released. on_enter : function Function called whenever the "enter" key is pressed. maxdist : float Maximum pixel distance allowed when selecting control handle. line_props : dict Properties for :class:`matplotlib.lines.Line2D`. Attributes ---------- end_points : 2D array End points of line ((x1, y1), (x2, y2)). """ def __init__(self, ax, on_move=None, on_release=None, on_enter=None, maxdist=10, line_props=None): super(LineTool, self).__init__(ax, on_move=on_move, on_enter=on_enter, on_release=on_release) props = dict(color='r', linewidth=1, alpha=0.4, solid_capstyle='butt') props.update(line_props if line_props is not None else {}) self.linewidth = props['linewidth'] self.maxdist = maxdist self._active_pt = None x = (0, 0) y = (0, 0) self._end_pts = np.transpose([x, y]) self._line = lines.Line2D(x, y, visible=False, animated=True, **props) ax.add_line(self._line) self._handles = ToolHandles(ax, x, y) self._handles.set_visible(False) self._artists = [self._line, self._handles.artist] if on_enter is None: def on_enter(pts): x, y = np.transpose(pts) print("length = %0.2f" % np.sqrt(np.diff(x)**2 + np.diff(y)**2)) self.callback_on_enter = on_enter self.connect_event('button_press_event', self.on_mouse_press) self.connect_event('button_release_event', self.on_mouse_release) self.connect_event('motion_notify_event', self.on_move) @property def end_points(self): return self._end_pts @end_points.setter def end_points(self, pts): self._end_pts = np.asarray(pts) self._line.set_data(np.transpose(pts)) self._handles.set_data(np.transpose(pts)) self._line.set_linewidth(self.linewidth) self.set_visible(True) self.redraw() def on_mouse_press(self, event): if event.button != 1 or not self.ax.in_axes(event): return self.set_visible(True) idx, px_dist = self._handles.closest(event.x, event.y) if px_dist < self.maxdist: self._active_pt = idx else: self._active_pt = 0 x, y = event.xdata, event.ydata self._end_pts = np.array([[x, y], [x, y]]) def on_mouse_release(self, event): if event.button != 1: return self._active_pt = None self.callback_on_release(self.geometry) def on_move(self, event): if event.button != 1 or self._active_pt is None: return if not self.ax.in_axes(event): return self.update(event.xdata, event.ydata) self.callback_on_move(self.geometry) def update(self, x=None, y=None): if x is not None: self._end_pts[self._active_pt, :] = x, y self.end_points = self._end_pts @property def geometry(self): return self.end_points class ThickLineTool(LineTool): """Widget for line selection in a plot. The thickness of the line can be varied using the mouse scroll wheel, or with the '+' and '-' keys. Parameters ---------- ax : :class:`matplotlib.axes.Axes` Matplotlib axes where tool is displayed. on_move : function Function called whenever a control handle is moved. This function must accept the end points of line as the only argument. on_release : function Function called whenever the control handle is released. on_enter : function Function called whenever the "enter" key is pressed. on_change : function Function called whenever the line thickness is changed. maxdist : float Maximum pixel distance allowed when selecting control handle. line_props : dict Properties for :class:`matplotlib.lines.Line2D`. Attributes ---------- end_points : 2D array End points of line ((x1, y1), (x2, y2)). """ def __init__(self, ax, on_move=None, on_enter=None, on_release=None, on_change=None, maxdist=10, line_props=None): super(ThickLineTool, self).__init__(ax, on_move=on_move, on_enter=on_enter, on_release=on_release, maxdist=maxdist, line_props=line_props) if on_change is None: def on_change(*args): pass self.callback_on_change = on_change self.connect_event('scroll_event', self.on_scroll) self.connect_event('key_press_event', self.on_key_press) def on_scroll(self, event): if not event.inaxes: return if event.button == 'up': self._thicken_scan_line() elif event.button == 'down': self._shrink_scan_line() def on_key_press(self, event): if event.key == '+': self._thicken_scan_line() elif event.key == '-': self._shrink_scan_line() def _thicken_scan_line(self): self.linewidth += 1 self.update() self.callback_on_change(self.geometry) def _shrink_scan_line(self): if self.linewidth > 1: self.linewidth -= 1 self.update() self.callback_on_change(self.geometry) if __name__ == '__main__': import matplotlib.pyplot as plt from skimage import data image = data.camera() f, ax = plt.subplots() ax.imshow(image, interpolation='nearest') h, w = image.shape # line_tool = LineTool(ax) line_tool = ThickLineTool(ax) line_tool.end_points = ([w/3, h/2], [2*w/3, h/2]) plt.show() scikit-image-0.9.3/skimage/viewer/canvastools/painttool.py000066400000000000000000000140661223313777300237500ustar00rootroot00000000000000import numpy as np import matplotlib.pyplot as plt import matplotlib.colors as mcolors LABELS_CMAP = mcolors.ListedColormap(['white', 'red', 'dodgerblue', 'gold', 'greenyellow', 'blueviolet']) from skimage.viewer.canvastools.base import CanvasToolBase __all__ = ['PaintTool'] class PaintTool(CanvasToolBase): """Widget for painting on top of a plot. Parameters ---------- ax : :class:`matplotlib.axes.Axes` Matplotlib axes where tool is displayed. overlay_shape : shape tuple 2D shape tuple used to initialize overlay image. alpha : float (between [0, 1]) Opacity of overlay on_move : function Function called whenever a control handle is moved. This function must accept the end points of line as the only argument. on_release : function Function called whenever the control handle is released. on_enter : function Function called whenever the "enter" key is pressed. rect_props : dict Properties for :class:`matplotlib.patches.Rectangle`. This class redefines defaults in :class:`matplotlib.widgets.RectangleSelector`. Attributes ---------- overlay : array Overlay of painted labels displayed on top of image. label : int Current paint color. """ def __init__(self, ax, overlay_shape, radius=5, alpha=0.3, on_move=None, on_release=None, on_enter=None, rect_props=None): super(PaintTool, self).__init__(ax, on_move=on_move, on_enter=on_enter, on_release=on_release) props = dict(edgecolor='r', facecolor='0.7', alpha=0.5, animated=True) props.update(rect_props if rect_props is not None else {}) self.alpha = alpha self.cmap = LABELS_CMAP self._overlay_plot = None self._shape = overlay_shape self.overlay = np.zeros(overlay_shape, dtype='uint8') self._cursor = plt.Rectangle((0, 0), 0, 0, **props) self._cursor.set_visible(False) self.ax.add_patch(self._cursor) # `label` and `radius` can only be set after initializing `_cursor` self.label = 1 self.radius = radius # Note that the order is important: Redraw cursor *after* overlay self._artists = [self._overlay_plot, self._cursor] self.connect_event('button_press_event', self.on_mouse_press) self.connect_event('button_release_event', self.on_mouse_release) self.connect_event('motion_notify_event', self.on_move) @property def label(self): return self._label @label.setter def label(self, value): if value >= self.cmap.N: raise ValueError('Maximum label value = %s' % len(self.cmap - 1)) self._label = value self._cursor.set_edgecolor(self.cmap(value)) @property def radius(self): return self._radius @radius.setter def radius(self, r): self._radius = r self._width = 2 * r + 1 self._cursor.set_width(self._width) self._cursor.set_height(self._width) self.window = CenteredWindow(r, self._shape) @property def overlay(self): return self._overlay @overlay.setter def overlay(self, image): self._overlay = image if image is None: self.ax.images.remove(self._overlay_plot) self._overlay_plot = None elif self._overlay_plot is None: props = dict(cmap=self.cmap, alpha=self.alpha, norm=mcolors.no_norm(), animated=True) self._overlay_plot = self.ax.imshow(image, **props) else: self._overlay_plot.set_data(image) self.redraw() def _on_key_press(self, event): if event.key == 'enter': self.callback_on_enter(self.geometry) self.redraw() def on_mouse_press(self, event): if event.button != 1 or not self.ax.in_axes(event): return self.update_cursor(event.xdata, event.ydata) self.update_overlay(event.xdata, event.ydata) def on_mouse_release(self, event): if event.button != 1: return self.callback_on_release(self.geometry) def on_move(self, event): if not self.ax.in_axes(event): self._cursor.set_visible(False) self.redraw() # make sure cursor is not visible return self._cursor.set_visible(True) self.update_cursor(event.xdata, event.ydata) if event.button != 1: self.redraw() # update cursor position return self.update_overlay(event.xdata, event.ydata) self.callback_on_move(self.geometry) def update_overlay(self, x, y): overlay = self.overlay overlay[self.window.at(y, x)] = self.label # Note that overlay calls `redraw` self.overlay = overlay def update_cursor(self, x, y): x = x - self.radius - 1 y = y - self.radius - 1 self._cursor.set_xy((x, y)) @property def geometry(self): return self.overlay class CenteredWindow(object): """Window that create slices numpy arrays over 2D windows. Example ------- >>> a = np.arange(16).reshape(4, 4) >>> w = CenteredWindow(1, a.shape) >>> a[w.at(1, 1)] array([[ 0, 1, 2], [ 4, 5, 6], [ 8, 9, 10]]) >>> a[w.at(0, 0)] array([[0, 1], [4, 5]]) >>> a[w.at(4, 3)] array([[14, 15]]) """ def __init__(self, radius, array_shape): self.radius = radius self.array_shape = array_shape def at(self, row, col): h, w = self.array_shape r = self.radius xmin = max(0, col - r) xmax = min(w, col + r + 1) ymin = max(0, row - r) ymax = min(h, row + r + 1) return [slice(ymin, ymax), slice(xmin, xmax)] if __name__ == '__main__': np.testing.rundocs() from skimage import data image = data.camera() f, ax = plt.subplots() ax.imshow(image, interpolation='nearest') paint_tool = PaintTool(ax, image.shape) plt.show() scikit-image-0.9.3/skimage/viewer/canvastools/recttool.py000066400000000000000000000166721223313777300235770ustar00rootroot00000000000000try: from matplotlib.widgets import RectangleSelector except ImportError: RectangleSelector = object print("Could not import matplotlib -- skimage.viewer not available.") from skimage.viewer.canvastools.base import CanvasToolBase from skimage.viewer.canvastools.base import ToolHandles __all__ = ['RectangleTool'] class RectangleTool(CanvasToolBase, RectangleSelector): """Widget for selecting a rectangular region in a plot. After making the desired selection, press "Enter" to accept the selection and call the `on_enter` callback function. Parameters ---------- ax : :class:`matplotlib.axes.Axes` Matplotlib axes where tool is displayed. on_move : function Function called whenever a control handle is moved. This function must accept the rectangle extents as the only argument. on_release : function Function called whenever the control handle is released. on_enter : function Function called whenever the "enter" key is pressed. maxdist : float Maximum pixel distance allowed when selecting control handle. rect_props : dict Properties for :class:`matplotlib.patches.Rectangle`. This class redefines defaults in :class:`matplotlib.widgets.RectangleSelector`. Attributes ---------- extents : tuple Rectangle extents: (xmin, xmax, ymin, ymax). """ def __init__(self, ax, on_move=None, on_release=None, on_enter=None, maxdist=10, rect_props=None): CanvasToolBase.__init__(self, ax, on_move=on_move, on_enter=on_enter, on_release=on_release) props = dict(edgecolor=None, facecolor='r', alpha=0.15) props.update(rect_props if rect_props is not None else {}) if props['edgecolor'] is None: props['edgecolor'] = props['facecolor'] RectangleSelector.__init__(self, ax, lambda *args: None, rectprops=props, useblit=self.useblit) # Alias rectangle attribute, which is initialized in RectangleSelector. self._rect = self.to_draw self._rect.set_animated(True) self.maxdist = maxdist self.active_handle = None self._extents_on_press = None if on_enter is None: def on_enter(extents): print("(xmin=%.3g, xmax=%.3g, ymin=%.3g, ymax=%.3g)" % extents) self.callback_on_enter = on_enter props = dict(mec=props['edgecolor']) self._corner_order = ['NW', 'NE', 'SE', 'SW'] xc, yc = self.corners self._corner_handles = ToolHandles(ax, xc, yc, marker_props=props) self._edge_order = ['W', 'N', 'E', 'S'] xe, ye = self.edge_centers self._edge_handles = ToolHandles(ax, xe, ye, marker='s', marker_props=props) self._artists = [self._rect, self._corner_handles.artist, self._edge_handles.artist] @property def _rect_bbox(self): x0 = self._rect.get_x() y0 = self._rect.get_y() width = self._rect.get_width() height = self._rect.get_height() return x0, y0, width, height @property def corners(self): """Corners of rectangle from lower left, moving clockwise.""" x0, y0, width, height = self._rect_bbox xc = x0, x0 + width, x0 + width, x0 yc = y0, y0, y0 + height, y0 + height return xc, yc @property def edge_centers(self): """Midpoint of rectangle edges from left, moving clockwise.""" x0, y0, width, height = self._rect_bbox w = width / 2. h = height / 2. xe = x0, x0 + w, x0 + width, x0 + w ye = y0 + h, y0, y0 + h, y0 + height return xe, ye @property def extents(self): """Return (xmin, xmax, ymin, ymax).""" x0, y0, width, height = self._rect_bbox xmin, xmax = sorted([x0, x0 + width]) ymin, ymax = sorted([y0, y0 + height]) return xmin, xmax, ymin, ymax @extents.setter def extents(self, extents): x1, x2, y1, y2 = extents xmin, xmax = sorted([x1, x2]) ymin, ymax = sorted([y1, y2]) # Update displayed rectangle self._rect.set_x(xmin) self._rect.set_y(ymin) self._rect.set_width(xmax - xmin) self._rect.set_height(ymax - ymin) # Update displayed handles self._corner_handles.set_data(*self.corners) self._edge_handles.set_data(*self.edge_centers) self.set_visible(True) self.redraw() def release(self, event): if event.button != 1: return if not self.ax.in_axes(event): self.eventpress = None return RectangleSelector.release(self, event) self._extents_on_press = None # Undo hiding of rectangle and redraw. self.set_visible(True) self.redraw() self.callback_on_release(self.geometry) def press(self, event): if event.button != 1 or not self.ax.in_axes(event): return self._set_active_handle(event) if self.active_handle is None: # Clear previous rectangle before drawing new rectangle. self.set_visible(False) self.redraw() self.set_visible(True) RectangleSelector.press(self, event) def _set_active_handle(self, event): """Set active handle based on the location of the mouse event""" # Note: event.xdata/ydata in data coordinates, event.x/y in pixels c_idx, c_dist = self._corner_handles.closest(event.x, event.y) e_idx, e_dist = self._edge_handles.closest(event.x, event.y) # Set active handle as closest handle, if mouse click is close enough. if c_dist > self.maxdist and e_dist > self.maxdist: self.active_handle = None return elif c_dist < e_dist: self.active_handle = self._corner_order[c_idx] else: self.active_handle = self._edge_order[e_idx] # Save coordinates of rectangle at the start of handle movement. x1, x2, y1, y2 = self.extents # Switch variables so that only x2 and/or y2 are updated on move. if self.active_handle in ['W', 'SW', 'NW']: x1, x2 = x2, event.xdata if self.active_handle in ['N', 'NW', 'NE']: y1, y2 = y2, event.ydata self._extents_on_press = x1, x2, y1, y2 def onmove(self, event): if self.eventpress is None or not self.ax.in_axes(event): return if self.active_handle is None: # New rectangle x1 = self.eventpress.xdata y1 = self.eventpress.ydata x2, y2 = event.xdata, event.ydata else: x1, x2, y1, y2 = self._extents_on_press if self.active_handle in ['E', 'W'] + self._corner_order: x2 = event.xdata if self.active_handle in ['N', 'S'] + self._corner_order: y2 = event.ydata self.extents = (x1, x2, y1, y2) self.callback_on_move(self.geometry) @property def geometry(self): return self.extents if __name__ == '__main__': import matplotlib.pyplot as plt from skimage import data f, ax = plt.subplots() ax.imshow(data.camera(), interpolation='nearest') rect_tool = RectangleTool(ax) plt.show() print("Final selection:") rect_tool.callback_on_enter(rect_tool.extents) scikit-image-0.9.3/skimage/viewer/plugins/000077500000000000000000000000001223313777300205035ustar00rootroot00000000000000scikit-image-0.9.3/skimage/viewer/plugins/__init__.py000066400000000000000000000000001223313777300226020ustar00rootroot00000000000000scikit-image-0.9.3/skimage/viewer/plugins/base.py000066400000000000000000000203411223313777300217670ustar00rootroot00000000000000""" Base class for Plugins that interact with ImageViewer. """ from warnings import warn import numpy as np from ..qt import QtGui from ..qt.QtCore import Qt, Signal from ..utils import RequiredAttr, init_qtapp class Plugin(QtGui.QDialog): """Base class for plugins that interact with an ImageViewer. A plugin connects an image filter (or another function) to an image viewer. Note that a Plugin is initialized *without* an image viewer and attached in a later step. See example below for details. Parameters ---------- image_viewer : ImageViewer Window containing image used in measurement/manipulation. image_filter : function Function that gets called to update image in image viewer. This value can be `None` if, for example, you have a plugin that extracts information from an image and doesn't manipulate it. Alternatively, this function can be defined as a method in a Plugin subclass. height, width : int Size of plugin window in pixels. Note that Qt will automatically resize a window to fit components. So if you're adding rows of components, you can leave `height = 0` and just let Qt determine the final height. useblit : bool If True, use blitting to speed up animation. Only available on some Matplotlib backends. If None, set to True when using Agg backend. This only has an effect if you draw on top of an image viewer. Attributes ---------- image_viewer : ImageViewer Window containing image used in measurement. name : str Name of plugin. This is displayed as the window title. artist : list List of Matplotlib artists and canvastools. Any artists created by the plugin should be added to this list so that it gets cleaned up on close. Examples -------- >>> from skimage.viewer import ImageViewer >>> from skimage.viewer.widgets import Slider >>> from skimage import data >>> >>> plugin = Plugin(image_filter=lambda img, threshold: img > threshold) >>> plugin += Slider('threshold', 0, 255) >>> >>> image = data.coins() >>> viewer = ImageViewer(image) >>> viewer += plugin >>> # viewer.show() The plugin will automatically delegate parameters to `image_filter` based on its parameter type, i.e., `ptype` (widgets for required arguments must be added in the order they appear in the function). The image attached to the viewer is **automatically passed as the first argument** to the filter function. #TODO: Add flag so image is not passed to filter function by default. `ptype = 'kwarg'` is the default for most widgets so it's unnecessary here. """ name = 'Plugin' image_viewer = RequiredAttr("%s is not attached to ImageViewer" % name) # Signals used when viewers are linked to the Plugin output. image_changed = Signal(np.ndarray) _started = Signal(int) def __init__(self, image_filter=None, height=0, width=400, useblit=True, dock='bottom'): init_qtapp() super(Plugin, self).__init__() self.dock = dock self.image_viewer = None # If subclass defines `image_filter` method ignore input. if not hasattr(self, 'image_filter'): self.image_filter = image_filter elif image_filter is not None: warn("If the Plugin class defines an `image_filter` method, " "then the `image_filter` argument is ignored.") self.setWindowTitle(self.name) self.layout = QtGui.QGridLayout(self) self.resize(width, height) self.row = 0 self.arguments = [] self.keyword_arguments= {} self.useblit = useblit self.cids = [] self.artists = [] def attach(self, image_viewer): """Attach the plugin to an ImageViewer. Note that the ImageViewer will automatically call this method when the plugin is added to the ImageViewer. For example:: viewer += Plugin(...) Also note that `attach` automatically calls the filter function so that the image matches the filtered value specified by attached widgets. """ self.setParent(image_viewer) self.setWindowFlags(Qt.Dialog) self.image_viewer = image_viewer self.image_viewer.plugins.append(self) #TODO: Always passing image as first argument may be bad assumption. self.arguments = [self.image_viewer.original_image] # Call filter so that filtered image matches widget values self.filter_image() def add_widget(self, widget): """Add widget to plugin. Alternatively, Plugin's `__add__` method is overloaded to add widgets:: plugin += Widget(...) Widgets can adjust required or optional arguments of filter function or parameters for the plugin. This is specified by the Widget's `ptype'. """ if widget.ptype == 'kwarg': name = widget.name.replace(' ', '_') self.keyword_arguments[name] = widget widget.callback = self.filter_image elif widget.ptype == 'arg': self.arguments.append(widget) widget.callback = self.filter_image elif widget.ptype == 'plugin': widget.callback = self.update_plugin widget.plugin = self self.layout.addWidget(widget, self.row, 0) self.row += 1 def __add__(self, widget): self.add_widget(widget) return self def filter_image(self, *widget_arg): """Call `image_filter` with widget args and kwargs Note: `display_filtered_image` is automatically called. """ # `widget_arg` is passed by the active widget but is unused since all # filter arguments are pulled directly from attached the widgets. if self.image_filter is None: return arguments = [self._get_value(a) for a in self.arguments] kwargs = dict([(name, self._get_value(a)) for name, a in self.keyword_arguments.items()]) filtered = self.image_filter(*arguments, **kwargs) self.display_filtered_image(filtered) self.image_changed.emit(filtered) def _get_value(self, param): # If param is a widget, return its `val` attribute. return param if not hasattr(param, 'val') else param.val def _update_original_image(self, image): """Update the original image argument passed to the filter function. This method is called by the viewer when the original image is updated. """ self.arguments[0] = image self.filter_image() @property def filtered_image(self): """Return filtered image.""" return self.image_viewer.image def display_filtered_image(self, image): """Display the filtered image on image viewer. If you don't want to simply replace the displayed image with the filtered image (e.g., you want to display a transparent overlay), you can override this method. """ self.image_viewer.image = image def update_plugin(self, name, value): """Update keyword parameters of the plugin itself. These parameters will typically be implemented as class properties so that they update the image or some other component. """ setattr(self, name, value) def show(self, main_window=True): """Show plugin.""" super(Plugin, self).show() self.activateWindow() self.raise_() # Emit signal with x-hint so new windows can be displayed w/o overlap. size = self.frameGeometry() x_hint = size.x() + size.width() self._started.emit(x_hint) def closeEvent(self, event): """On close disconnect all artists and events from ImageViewer. Note that artists must be appended to `self.artists`. """ self.clean_up() self.close() def clean_up(self): self.remove_image_artists() self.image_viewer.plugins.remove(self) self.image_viewer.reset_image() self.image_viewer.redraw() def remove_image_artists(self): """Remove artists that are connected to the image viewer.""" for a in self.artists: a.remove() scikit-image-0.9.3/skimage/viewer/plugins/canny.py000066400000000000000000000023431223313777300221670ustar00rootroot00000000000000import numpy as np import skimage from skimage.filter import canny from .overlayplugin import OverlayPlugin from ..widgets import Slider, ComboBox class CannyPlugin(OverlayPlugin): """Canny filter plugin to show edges of an image.""" name = 'Canny Filter' def __init__(self, *args, **kwargs): super(CannyPlugin, self).__init__(image_filter=canny, **kwargs) def attach(self, image_viewer): image = image_viewer.image imin, imax = skimage.dtype_limits(image) itype = 'float' if np.issubdtype(image.dtype, float) else 'int' self.add_widget(Slider('sigma', 0, 5, update_on='release')) self.add_widget(Slider('low threshold', imin, imax, value_type=itype, update_on='release')) self.add_widget(Slider('high threshold', imin, imax, value_type=itype, update_on='release')) self.add_widget(ComboBox('color', self.color_names, ptype='plugin')) # Call parent method at end b/c it calls `filter_image`, which needs # the values specified by the widgets. Alternatively, move call to # parent method to beginning and add a call to `self.filter_image()` super(CannyPlugin,self).attach(image_viewer) scikit-image-0.9.3/skimage/viewer/plugins/color_histogram.py000066400000000000000000000041761223313777300242600ustar00rootroot00000000000000import numpy as np import matplotlib.pyplot as plt from skimage import color from skimage import exposure from .plotplugin import PlotPlugin from ..canvastools import RectangleTool class ColorHistogram(PlotPlugin): name = 'Color Histogram' def __init__(self, max_pct=0.99, **kwargs): super(ColorHistogram, self).__init__(height=400, **kwargs) self.max_pct = max_pct print(self.help()) def attach(self, image_viewer): super(ColorHistogram, self).attach(image_viewer) self.rect_tool = RectangleTool(self.ax, on_release=self.ab_selected) self.lab_image = color.rgb2lab(image_viewer.image) # Calculate color histogram in the Lab colorspace: L, a, b = self.lab_image.T left, right = -100, 100 ab_extents = [left, right, right, left] bins = np.arange(left, right) hist, x_edges, y_edges = np.histogram2d(a.flatten(), b.flatten(), bins, normed=True) # Clip bin heights that dominate a-b histogram max_val = pct_total_area(hist, percentile=self.max_pct) hist = exposure.rescale_intensity(hist, in_range=(0, max_val)) self.ax.imshow(hist, extent=ab_extents, cmap=plt.cm.gray) self.ax.set_title('Color Histogram') self.ax.set_xlabel('b') self.ax.set_ylabel('a') def help(self): helpstr = ("Color Histogram tool:", "Select region of a-b colorspace to highlight on image.") return '\n'.join(helpstr) def ab_selected(self, extents): x0, x1, y0, y1 = extents lab_masked = self.lab_image.copy() L, a, b = lab_masked.T mask = ((a > y0) & (a < y1)) & ((b > x0) & (b < x1)) lab_masked[..., 1:][~mask.T] = 0 self.image_viewer.image = color.lab2rgb(lab_masked) def pct_total_area(image, percentile=0.80): """Return threshold value based on percentage of total area. The specified percent of pixels less than the given intensity threshold. """ idx = int((image.size - 1) * percentile) sorted_pixels = np.sort(image.flat) return sorted_pixels[idx] scikit-image-0.9.3/skimage/viewer/plugins/crop.py000066400000000000000000000020261223313777300220200ustar00rootroot00000000000000from .base import Plugin from ..canvastools import RectangleTool from skimage.viewer.widgets import SaveButtons __all__ = ['Crop'] class Crop(Plugin): name = 'Crop' def __init__(self, maxdist=10, **kwargs): super(Crop, self).__init__(**kwargs) self.maxdist = maxdist self.add_widget(SaveButtons()) print(self.help()) def attach(self, image_viewer): super(Crop, self).attach(image_viewer) self.rect_tool = RectangleTool(self.image_viewer.ax, maxdist=self.maxdist, on_enter=self.crop) self.artists.append(self.rect_tool) def help(self): helpstr = ("Crop tool", "Select rectangular region and press enter to crop.") return '\n'.join(helpstr) def crop(self, extents): xmin, xmax, ymin, ymax = extents image = self.image_viewer.image[ymin:ymax+1, xmin:xmax+1] self.image_viewer.image = image self.image_viewer.ax.relim() scikit-image-0.9.3/skimage/viewer/plugins/labelplugin.py000066400000000000000000000033371223313777300233610ustar00rootroot00000000000000import numpy as np from .base import Plugin from ..widgets import ComboBox, Slider from ..canvastools import PaintTool __all__ = ['LabelPainter'] rad2deg = 180 / np.pi class LabelPainter(Plugin): name = 'LabelPainter' def __init__(self, max_radius=20, **kwargs): super(LabelPainter, self).__init__(**kwargs) # These widgets adjust plugin properties instead of an image filter. self._radius_widget = Slider('radius', low=1, high=max_radius, value=5, value_type='int', ptype='plugin') labels = [str(i) for i in range(6)] labels[0] = 'Erase' self._label_widget = ComboBox('label', labels, ptype='plugin') self.add_widget(self._radius_widget) self.add_widget(self._label_widget) print(self.help()) def help(self): helpstr = ("Label painter", "Hold left-mouse button and paint on canvas.") return '\n'.join(helpstr) def attach(self, image_viewer): super(LabelPainter, self).attach(image_viewer) image = image_viewer.original_image self.paint_tool = PaintTool(self.image_viewer.ax, image.shape, on_enter=self.on_enter) self.paint_tool.radius = self.radius self.paint_tool.label = self._label_widget.index = 1 self.artists.append(self.paint_tool) def on_enter(self, overlay): pass @property def radius(self): return self._radius_widget.val @radius.setter def radius(self, val): self.paint_tool.radius = val @property def label(self): return self._label_widget.val @label.setter def label(self, val): self.paint_tool.label = val scikit-image-0.9.3/skimage/viewer/plugins/lineprofile.py000066400000000000000000000153061223313777300233720ustar00rootroot00000000000000import warnings import numpy as np import scipy.ndimage as ndi from skimage.util.dtype import dtype_range from .plotplugin import PlotPlugin from ..canvastools import ThickLineTool __all__ = ['LineProfile'] class LineProfile(PlotPlugin): """Plugin to compute interpolated intensity under a scan line on an image. See PlotPlugin and Plugin classes for additional details. Parameters ---------- maxdist : float Maximum pixel distance allowed when selecting end point of scan line. epsilon : float Deprecated. Use `maxdist` instead. limits : tuple or {None, 'image', 'dtype'} (minimum, maximum) intensity limits for plotted profile. The following special values are defined: None : rescale based on min/max intensity along selected scan line. 'image' : fixed scale based on min/max intensity in image. 'dtype' : fixed scale based on min/max intensity of image dtype. """ name = 'Line Profile' def __init__(self, maxdist=10, epsilon='deprecated', limits='image', **kwargs): super(LineProfile, self).__init__(**kwargs) if not epsilon == 'deprecated': warnings.warn("Parameter `epsilon` deprecated; use `maxdist`.") maxdist = epsilon self.maxdist = maxdist self._limit_type = limits print(self.help()) def attach(self, image_viewer): super(LineProfile, self).attach(image_viewer) image = image_viewer.original_image if self._limit_type == 'image': self.limits = (np.min(image), np.max(image)) elif self._limit_type == 'dtype': self._limit_type = dtype_range[image.dtype.type] elif self._limit_type is None or len(self._limit_type) == 2: self.limits = self._limit_type else: raise ValueError("Unrecognized `limits`: %s" % self._limit_type) if not self._limit_type is None: self.ax.set_ylim(self.limits) h, w = image.shape[0:2] x = [w / 3, 2 * w / 3] y = [h / 2] * 2 self.line_tool = ThickLineTool(self.image_viewer.ax, maxdist=self.maxdist, on_move=self.line_changed, on_change=self.line_changed) self.line_tool.end_points = np.transpose([x, y]) scan_data = profile_line(image, self.line_tool.end_points) self.reset_axes(scan_data) self._autoscale_view() def help(self): helpstr = ("Line profile tool", "+ and - keys or mouse scroll changes width of scan line.", "Select and drag ends of the scan line to adjust it.") return '\n'.join(helpstr) def get_profiles(self): """Return intensity profile of the selected line. Returns ------- end_points: (2, 2) array The positions ((x1, y1), (x2, y2)) of the line ends. profile: list of 1d arrays Profile of intensity values. Length 1 (grayscale) or 3 (rgb). """ profiles = [data.get_ydata() for data in self.profile] return self.line_tool.end_points, profiles def _autoscale_view(self): if self.limits is None: self.ax.autoscale_view(tight=True) else: self.ax.autoscale_view(scaley=False, tight=True) def line_changed(self, end_points): x, y = np.transpose(end_points) self.line_tool.end_points = end_points scan = profile_line(self.image_viewer.original_image, end_points, linewidth=self.line_tool.linewidth) if scan.shape[1] != len(self.profile): self.reset_axes(scan) for i in range(len(scan[0])): self.profile[i].set_xdata(np.arange(scan.shape[0])) self.profile[i].set_ydata(scan[:, i]) self.ax.relim() self._autoscale_view() self.redraw() def reset_axes(self, scan_data): # Clear lines out for line in self.ax.lines: self.ax.lines = [] if scan_data.shape[1] == 1: self.profile = self.ax.plot(scan_data, 'k-') else: self.profile = self.ax.plot(scan_data[:, 0], 'r-', scan_data[:, 1], 'g-', scan_data[:, 2], 'b-') def _calc_vert(img, x1, x2, y1, y2, linewidth): # Quick calculation if perfectly horizontal pixels = img[min(y1, y2): max(y1, y2) + 1, x1 - linewidth / 2: x1 + linewidth / 2 + 1] # Reverse index if necessary if y2 > y1: pixels = pixels[::-1, :] return pixels.mean(axis=1)[:, np.newaxis] def profile_line(img, end_points, linewidth=1): """Return the intensity profile of an image measured along a scan line. Parameters ---------- img : 2d or 3d array The image, in grayscale (2d) or RGB (3d) format. end_points: (2, 2) list End points ((x1, y1), (x2, y2)) of scan line. linewidth: int Width of the scan, perpendicular to the line Returns ------- return_value : array The intensity profile along the scan line. The length of the profile is the ceil of the computed length of the scan line. """ point1, point2 = end_points x1, y1 = point1 = np.asarray(point1, dtype=float) x2, y2 = point2 = np.asarray(point2, dtype=float) dx, dy = point2 - point1 channels = 1 if img.ndim == 3: channels = 3 # Quick calculation if perfectly vertical; shortcuts div0 error if x1 == x2: if channels == 1: img = img[:, :, np.newaxis] img = np.rollaxis(img, -1) intensities = np.hstack([_calc_vert(im, x1, x2, y1, y2, linewidth) for im in img]) return intensities theta = np.arctan2(dy, dx) a = dy / dx b = y1 - a * x1 length = np.hypot(dx, dy) line_x = np.linspace(x2, x1, np.ceil(length)) line_y = line_x * a + b y_width = abs(linewidth * np.cos(theta) / 2) perp_ys = np.array([np.linspace(yi - y_width, yi + y_width, linewidth) for yi in line_y]) perp_xs = - a * perp_ys + (line_x + a * line_y)[:, np.newaxis] perp_lines = np.array([perp_ys, perp_xs]) if img.ndim == 3: pixels = [ndi.map_coordinates(img[..., i], perp_lines) for i in range(3)] pixels = np.transpose(np.asarray(pixels), (1, 2, 0)) else: pixels = ndi.map_coordinates(img, perp_lines) pixels = pixels[..., np.newaxis] intensities = pixels.mean(axis=1) if intensities.ndim == 1: return intensities[..., np.newaxis] else: return intensities scikit-image-0.9.3/skimage/viewer/plugins/measure.py000066400000000000000000000024601223313777300225200ustar00rootroot00000000000000# -*- coding: utf-8 -*- import numpy as np from .base import Plugin from ..widgets import Text from ..canvastools import LineTool __all__ = ['Measure'] rad2deg = 180 / np.pi class Measure(Plugin): name = 'Measure' def __init__(self, maxdist=10, **kwargs): super(Measure, self).__init__(**kwargs) self.maxdist = maxdist self._length = Text('Length:') self._angle = Text('Angle:') self.add_widget(self._length) self.add_widget(self._angle) print(self.help()) def attach(self, image_viewer): super(Measure, self).attach(image_viewer) image = image_viewer.original_image h, w = image.shape self.line_tool = LineTool(self.image_viewer.ax, maxdist=self.maxdist, on_move=self.line_changed) self.artists.append(self.line_tool) def help(self): helpstr = ("Measure tool", "Select line to measure distance and angle.") return '\n'.join(helpstr) def line_changed(self, end_points): x, y = np.transpose(end_points) dx = np.diff(x)[0] dy = np.diff(y)[0] self._length.text = '%.1f' % np.hypot(dx, dy) self._angle.text = u'%.1f°' % (180 - np.arctan2(dy, dx) * rad2deg) scikit-image-0.9.3/skimage/viewer/plugins/overlayplugin.py000066400000000000000000000064331223313777300237630ustar00rootroot00000000000000from warnings import warn from skimage.util.dtype import dtype_range from .base import Plugin from ..utils import ClearColormap, update_axes_image from skimage._shared import six __all__ = ['OverlayPlugin'] def recent_mpl_version(): import matplotlib version = matplotlib.__version__.split('.') return int(version[0]) == 1 and int(version[1]) >= 2 class OverlayPlugin(Plugin): """Plugin for ImageViewer that displays an overlay on top of main image. The base Plugin class displays the filtered image directly on the viewer. OverlayPlugin will instead overlay an image with a transparent colormap. See base Plugin class for additional details. Attributes ---------- overlay : array Overlay displayed on top of image. This overlay defaults to a color map with alpha values varying linearly from 0 to 1. color : int Color of overlay. """ colors = {'red': (1, 0, 0), 'yellow': (1, 1, 0), 'green': (0, 1, 0), 'cyan': (0, 1, 1)} def __init__(self, **kwargs): if not recent_mpl_version(): msg = "Matplotlib >= 1.2 required for OverlayPlugin." warn(RuntimeWarning(msg)) super(OverlayPlugin, self).__init__(**kwargs) self._overlay_plot = None self._overlay = None self.cmap = None self.color_names = self.colors.keys() def attach(self, image_viewer): super(OverlayPlugin, self).attach(image_viewer) #TODO: `color` doesn't update GUI widget when set manually. self.color = 0 @property def overlay(self): return self._overlay @overlay.setter def overlay(self, image): self._overlay = image ax = self.image_viewer.ax if image is None: ax.images.remove(self._overlay_plot) self._overlay_plot = None elif self._overlay_plot is None: vmin, vmax = dtype_range[image.dtype.type] self._overlay_plot = ax.imshow(image, cmap=self.cmap, vmin=vmin, vmax=vmax) else: update_axes_image(self._overlay_plot, image) self.image_viewer.redraw() @property def color(self): return self._color @color.setter def color(self, index): # Update colormap whenever color is changed. if isinstance(index, six.string_types) and \ index not in self.color_names: raise ValueError("%s not defined in OverlayPlugin.colors" % index) else: name = self.color_names[index] self._color = name rgb = self.colors[name] self.cmap = ClearColormap(rgb) if self._overlay_plot is not None: self._overlay_plot.set_cmap(self.cmap) self.image_viewer.redraw() @property def filtered_image(self): """Return filtered image. This "filtered image" is used when saving from the plugin. """ return self.overlay def display_filtered_image(self, image): """Display filtered image as an overlay on top of image in viewer.""" self.overlay = image def closeEvent(self, event): # clear overlay from ImageViewer on close self.overlay = None super(OverlayPlugin, self).closeEvent(event) scikit-image-0.9.3/skimage/viewer/plugins/plotplugin.py000066400000000000000000000030061223313777300232510ustar00rootroot00000000000000import numpy as np from ..qt import QtGui from ..utils import new_plot from .base import Plugin __all__ = ['PlotPlugin'] class PlotPlugin(Plugin): """Plugin for ImageViewer that contains a plot canvas. Base class for plugins that contain a Matplotlib plot canvas, which can, for example, display an image histogram. See base Plugin class for additional details. """ def __init__(self, image_filter=None, height=150, width=400, **kwargs): super(PlotPlugin, self).__init__(image_filter=image_filter, height=height, width=width, **kwargs) self._height = height self._width = width def attach(self, image_viewer): super(PlotPlugin, self).attach(image_viewer) # Add plot for displaying intensity profile. self.add_plot() def redraw(self): """Redraw plot.""" self.canvas.draw_idle() def add_plot(self): self.fig, self.ax = new_plot() self.fig.set_figwidth(self._width / float(self.fig.dpi)) self.fig.set_figheight(self._height / float(self.fig.dpi)) self.canvas = self.fig.canvas #TODO: Converted color is slightly different than Qt background. qpalette = QtGui.QPalette() qcolor = qpalette.color(QtGui.QPalette.Window) bgcolor = qcolor.toRgb().value() if np.isscalar(bgcolor): bgcolor = str(bgcolor / 255.) self.fig.patch.set_facecolor(bgcolor) self.layout.addWidget(self.canvas, self.row, 0) scikit-image-0.9.3/skimage/viewer/qt/000077500000000000000000000000001223313777300174465ustar00rootroot00000000000000scikit-image-0.9.3/skimage/viewer/qt/QtCore.py000066400000000000000000000010531223313777300212140ustar00rootroot00000000000000from . import qt_api if qt_api == 'pyside': from PySide.QtCore import * elif qt_api == 'pyqt': from PyQt4.QtCore import * # Use pyside names for signals and slots Signal = pyqtSignal Slot = pyqtSlot else: # Mock objects for buildbot (which doesn't have Qt, but imports viewer). class Qt(object): TopDockWidgetArea = None BottomDockWidgetArea = None LeftDockWidgetArea = None RightDockWidgetArea = None def Signal(*args, **kwargs): pass def Slot(*args, **kwargs): pass scikit-image-0.9.3/skimage/viewer/qt/QtGui.py000066400000000000000000000003351223313777300210520ustar00rootroot00000000000000from . import qt_api if qt_api == 'pyside': from PySide.QtGui import * elif qt_api == 'pyqt': from PyQt4.QtGui import * else: # Mock objects QMainWindow = object QDialog = object QWidget = object scikit-image-0.9.3/skimage/viewer/qt/README.rst000066400000000000000000000005151223313777300211360ustar00rootroot00000000000000This qt subpackage provides a wrapper to allow use of either PySide or PyQt4. In addition, if neither package is available, some mock objects are created to prevent errors in the TravisCI build. Only the objects used in the global namespace need to be mocked (e.g., a Qt object that gets subclassed is used in the global namespace). scikit-image-0.9.3/skimage/viewer/qt/__init__.py000066400000000000000000000010401223313777300215520ustar00rootroot00000000000000import os import warnings qt_api = os.environ.get('QT_API') if qt_api is None: try: import PySide qt_api = 'pyside' except ImportError: try: import PyQt4 qt_api = 'pyqt' except ImportError: qt_api = None # Note that we don't want to raise an error because that would # cause the TravisCI build to fail. warnings.warn("Could not import PyQt4: ImageViewer not available!") if qt_api is not None: os.environ['QT_API'] = qt_api scikit-image-0.9.3/skimage/viewer/utils/000077500000000000000000000000001223313777300201625ustar00rootroot00000000000000scikit-image-0.9.3/skimage/viewer/utils/__init__.py000066400000000000000000000000241223313777300222670ustar00rootroot00000000000000from .core import * scikit-image-0.9.3/skimage/viewer/utils/core.py000066400000000000000000000153621223313777300214730ustar00rootroot00000000000000import warnings import numpy as np from ..qt import qt_api try: import matplotlib as mpl from matplotlib.figure import Figure from matplotlib import _pylab_helpers from matplotlib.colors import LinearSegmentedColormap if qt_api is None: raise ImportError else: from matplotlib.backends.backend_qt4 import FigureManagerQT from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg except ImportError: FigureCanvasQTAgg = object # hack to prevent nosetest and autodoc errors LinearSegmentedColormap = object print("Could not import matplotlib -- skimage.viewer not available.") from ..qt import QtGui __all__ = ['init_qtapp', 'start_qtapp', 'RequiredAttr', 'figimage', 'LinearColormap', 'ClearColormap', 'FigureCanvas', 'new_plot', 'update_axes_image'] QApp = None def init_qtapp(): """Initialize QAppliction. The QApplication needs to be initialized before creating any QWidgets """ global QApp QApp = QtGui.QApplication.instance() if QApp is None: QApp = QtGui.QApplication([]) return QApp def is_event_loop_running(app=None): """Return True if event loop is running.""" if app is None: app = init_qtapp() if hasattr(app, '_in_event_loop'): return app._in_event_loop else: return False def start_qtapp(app=None): """Start Qt mainloop""" if app is None: app = init_qtapp() if not is_event_loop_running(app): app._in_event_loop = True app.exec_() app._in_event_loop = False else: app._in_event_loop = True class RequiredAttr(object): """A class attribute that must be set before use.""" instances = dict() def __init__(self, msg='Required attribute not set', init_val=None): self.instances[self, None] = init_val self.msg = msg def __get__(self, obj, objtype): value = self.instances[self, obj] if value is None: # Should raise an error but that causes issues with the buildbot. warnings.warn(self.msg) self.__set__(obj, self.init_val) return value def __set__(self, obj, value): self.instances[self, obj] = value class LinearColormap(LinearSegmentedColormap): """LinearSegmentedColormap in which color varies smoothly. This class is a simplification of LinearSegmentedColormap, which doesn't support jumps in color intensities. Parameters ---------- name : str Name of colormap. segmented_data : dict Dictionary of 'red', 'green', 'blue', and (optionally) 'alpha' values. Each color key contains a list of `x`, `y` tuples. `x` must increase monotonically from 0 to 1 and corresponds to input values for a mappable object (e.g. an image). `y` corresponds to the color intensity. """ def __init__(self, name, segmented_data, **kwargs): segmented_data = dict((key, [(x, y, y) for x, y in value]) for key, value in segmented_data.items()) LinearSegmentedColormap.__init__(self, name, segmented_data, **kwargs) class ClearColormap(LinearColormap): """Color map that varies linearly from alpha = 0 to 1 """ def __init__(self, rgb, max_alpha=1, name='clear_color'): r, g, b = rgb cg_speq = {'blue': [(0.0, b), (1.0, b)], 'green': [(0.0, g), (1.0, g)], 'red': [(0.0, r), (1.0, r)], 'alpha': [(0.0, 0.0), (1.0, max_alpha)]} LinearColormap.__init__(self, name, cg_speq) class FigureCanvas(FigureCanvasQTAgg): """Canvas for displaying images.""" def __init__(self, figure, **kwargs): self.fig = figure FigureCanvasQTAgg.__init__(self, self.fig) FigureCanvasQTAgg.setSizePolicy(self, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) FigureCanvasQTAgg.updateGeometry(self) def resizeEvent(self, event): FigureCanvasQTAgg.resizeEvent(self, event) # Call to `resize_event` missing in FigureManagerQT. # See https://github.com/matplotlib/matplotlib/pull/1585 self.resize_event() def new_canvas(*args, **kwargs): """Return a new figure canvas.""" allnums = _pylab_helpers.Gcf.figs.keys() num = max(allnums) + 1 if allnums else 1 FigureClass = kwargs.pop('FigureClass', Figure) figure = FigureClass(*args, **kwargs) canvas = FigureCanvas(figure) fig_manager = FigureManagerQT(canvas, num) return fig_manager.canvas def new_plot(parent=None, subplot_kw=None, **fig_kw): """Return new figure and axes. Parameters ---------- parent : QtWidget Qt widget that displays the plot objects. If None, you must manually call ``canvas.setParent`` and pass the parent widget. subplot_kw : dict Keyword arguments passed ``matplotlib.figure.Figure.add_subplot``. fig_kw : dict Keyword arguments passed ``matplotlib.figure.Figure``. """ if subplot_kw is None: subplot_kw = {} canvas = new_canvas(**fig_kw) canvas.setParent(parent) fig = canvas.figure ax = fig.add_subplot(1, 1, 1, **subplot_kw) return fig, ax def figimage(image, scale=1, dpi=None, **kwargs): """Return figure and axes with figure tightly surrounding image. Unlike pyplot.figimage, this actually plots onto an axes object, which fills the figure. Plotting the image onto an axes allows for subsequent overlays of axes artists. Parameters ---------- image : array image to plot scale : float If scale is 1, the figure and axes have the same dimension as the image. Smaller values of `scale` will shrink the figure. dpi : int Dots per inch for figure. If None, use the default rcParam. """ dpi = dpi if dpi is not None else mpl.rcParams['figure.dpi'] kwargs.setdefault('interpolation', 'nearest') kwargs.setdefault('cmap', 'gray') h, w, d = np.atleast_3d(image).shape figsize = np.array((w, h), dtype=float) / dpi * scale fig, ax = new_plot(figsize=figsize, dpi=dpi) fig.subplots_adjust(left=0, bottom=0, right=1, top=1) ax.set_axis_off() ax.imshow(image, **kwargs) return fig, ax def update_axes_image(image_axes, image): """Update the image displayed by an image plot. This sets the image plot's array and updates its shape appropriately Parameters ---------- image_axes : `matplotlib.image.AxesImage` Image axes to update. image : array Image array. """ image_axes.set_array(image) # Adjust size if new image shape doesn't match the original h, w = image.shape[:2] image_axes.set_extent((0, w, h, 0)) scikit-image-0.9.3/skimage/viewer/utils/dialogs.py000066400000000000000000000016341223313777300221620ustar00rootroot00000000000000import os from ..qt import QtGui __all__ = ['open_file_dialog', 'save_file_dialog'] def _format_filename(filename): if isinstance(filename, tuple): # Handle discrepancy between PyQt4 and PySide APIs. filename = filename[0] if len(filename) == 0: return None return str(filename) def open_file_dialog(): """Return user-selected file path.""" filename = QtGui.QFileDialog.getOpenFileName() filename = _format_filename(filename) return filename def save_file_dialog(default_format='png'): """Return user-selected file path.""" filename = QtGui.QFileDialog.getSaveFileName() filename = _format_filename(filename) if filename is None: return None #TODO: io plugins should assign default image formats basename, ext = os.path.splitext(filename) if not ext: filename = '%s.%s' % (filename, default_format) return filename scikit-image-0.9.3/skimage/viewer/viewers/000077500000000000000000000000001223313777300205065ustar00rootroot00000000000000scikit-image-0.9.3/skimage/viewer/viewers/__init__.py000066400000000000000000000000601223313777300226130ustar00rootroot00000000000000from .core import ImageViewer, CollectionViewer scikit-image-0.9.3/skimage/viewer/viewers/core.py000066400000000000000000000267721223313777300220260ustar00rootroot00000000000000""" ImageViewer class for viewing and interacting with images. """ from ..qt import QtGui from ..qt.QtCore import Qt, Signal from skimage import io, img_as_float from skimage.util.dtype import dtype_range from skimage.exposure import rescale_intensity import numpy as np from .. import utils from ..widgets import Slider from ..utils import dialogs from ..plugins.base import Plugin __all__ = ['ImageViewer', 'CollectionViewer'] def mpl_image_to_rgba(mpl_image): """Return RGB image from the given matplotlib image object. Each image in a matplotlib figure has it's own colormap and normalization function. Return RGBA (RGB + alpha channel) image with float dtype. """ input_range = (mpl_image.norm.vmin, mpl_image.norm.vmax) image = rescale_intensity(mpl_image.get_array(), in_range=input_range) image = mpl_image.cmap(img_as_float(image)) # cmap complains on bool arrays return img_as_float(image) class ImageViewer(QtGui.QMainWindow): """Viewer for displaying images. This viewer is a simple container object that holds a Matplotlib axes for showing images. `ImageViewer` doesn't subclass the Matplotlib axes (or figure) because of the high probability of name collisions. Parameters ---------- image : array Image being viewed. Attributes ---------- canvas, fig, ax : Matplotlib canvas, figure, and axes Matplotlib canvas, figure, and axes used to display image. image : array Image being viewed. Setting this value will update the displayed frame. original_image : array Plugins typically operate on (but don't change) the *original* image. plugins : list List of attached plugins. Examples -------- >>> from skimage import data >>> image = data.coins() >>> viewer = ImageViewer(image) >>> # viewer.show() """ dock_areas = {'top': Qt.TopDockWidgetArea, 'bottom': Qt.BottomDockWidgetArea, 'left': Qt.LeftDockWidgetArea, 'right': Qt.RightDockWidgetArea} # Signal that the original image has been changed original_image_changed = Signal(np.ndarray) def __init__(self, image): # Start main loop utils.init_qtapp() super(ImageViewer, self).__init__() #TODO: Add ImageViewer to skimage.io window manager self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowTitle("Image Viewer") self.file_menu = QtGui.QMenu('&File', self) self.file_menu.addAction('Open file', self.open_file, Qt.CTRL + Qt.Key_O) self.file_menu.addAction('Save to file', self.save_to_file, Qt.CTRL + Qt.Key_S) self.file_menu.addAction('Quit', self.close, Qt.CTRL + Qt.Key_Q) self.menuBar().addMenu(self.file_menu) self.main_widget = QtGui.QWidget() self.setCentralWidget(self.main_widget) if isinstance(image, Plugin): plugin = image image = plugin.filtered_image plugin.image_changed.connect(self._update_original_image) # When plugin is started, start plugin._started.connect(self._show) self.fig, self.ax = utils.figimage(image) self.canvas = self.fig.canvas self.canvas.setParent(self) self.ax.autoscale(enable=False) self._image_plot = self.ax.images[0] self._update_original_image(image) self.plugins = [] self.layout = QtGui.QVBoxLayout(self.main_widget) self.layout.addWidget(self.canvas) status_bar = self.statusBar() self.status_message = status_bar.showMessage sb_size = status_bar.sizeHint() cs_size = self.canvas.sizeHint() self.resize(cs_size.width(), cs_size.height() + sb_size.height()) self.connect_event('motion_notify_event', self._update_status_bar) def __add__(self, plugin): """Add plugin to ImageViewer""" plugin.attach(self) self.original_image_changed.connect(plugin._update_original_image) if plugin.dock: location = self.dock_areas[plugin.dock] dock_location = Qt.DockWidgetArea(location) dock = QtGui.QDockWidget() dock.setWidget(plugin) dock.setWindowTitle(plugin.name) self.addDockWidget(dock_location, dock) horiz = (self.dock_areas['left'], self.dock_areas['right']) dimension = 'width' if location in horiz else 'height' self._add_widget_size(plugin, dimension=dimension) return self def _add_widget_size(self, widget, dimension='width'): widget_size = widget.sizeHint() viewer_size = self.frameGeometry() dx = dy = 0 if dimension == 'width': dx = widget_size.width() elif dimension == 'height': dy = widget_size.height() w = viewer_size.width() h = viewer_size.height() self.resize(w + dx, h + dy) def open_file(self): """Open image file and display in viewer.""" filename = dialogs.open_file_dialog() if filename is None: return image = io.imread(filename) self._update_original_image(image) def _update_original_image(self, image): self.original_image = image # update saved image self.image = image.copy() # update displayed image self.original_image_changed.emit(image) def save_to_file(self): """Save current image to file. The current behavior is not ideal: It saves the image displayed on screen, so all images will be converted to RGB, and the image size is not preserved (resizing the viewer window will alter the size of the saved image). """ filename = dialogs.save_file_dialog() if filename is None: return if len(self.ax.images) == 1: io.imsave(filename, self.image) else: underlay = mpl_image_to_rgba(self.ax.images[0]) overlay = mpl_image_to_rgba(self.ax.images[1]) alpha = overlay[:, :, 3] # alpha can be set by channel of array or by a scalar value. # Prefer the alpha channel, but fall back to scalar value. if np.all(alpha == 1): alpha = np.ones_like(alpha) * self.ax.images[1].get_alpha() alpha = alpha[:, :, np.newaxis] composite = (overlay[:, :, :3] * alpha + underlay[:, :, :3] * (1 - alpha)) io.imsave(filename, composite) def closeEvent(self, event): self.close() def _show(self, x=0): self.move(x, 0) for p in self.plugins: p.show() super(ImageViewer, self).show() self.activateWindow() self.raise_() def show(self, main_window=True): """Show ImageViewer and attached plugins. This behaves much like `matplotlib.pyplot.show` and `QWidget.show`. """ self._show() if main_window: utils.start_qtapp() def redraw(self): self.canvas.draw_idle() @property def image(self): return self._img @image.setter def image(self, image): self._img = image utils.update_axes_image(self._image_plot, image) # update display (otherwise image doesn't fill the canvas) h, w = image.shape[:2] self.ax.set_xlim(0, w) self.ax.set_ylim(h, 0) # update color range clim = dtype_range[image.dtype.type] if clim[0] < 0 and image.min() >= 0: clim = (0, clim[1]) self._image_plot.set_clim(clim) self.redraw() def reset_image(self): self.image = self.original_image.copy() def connect_event(self, event, callback): """Connect callback function to matplotlib event and return id.""" cid = self.canvas.mpl_connect(event, callback) return cid def disconnect_event(self, callback_id): """Disconnect callback by its id (returned by `connect_event`).""" self.canvas.mpl_disconnect(callback_id) def _update_status_bar(self, event): if event.inaxes and event.inaxes.get_navigate(): self.status_message(self._format_coord(event.xdata, event.ydata)) else: self.status_message('') def _format_coord(self, x, y): # callback function to format coordinate display in status bar x = int(x + 0.5) y = int(y + 0.5) try: return "%4s @ [%4s, %4s]" % (self.image[y, x], x, y) except IndexError: return "" class CollectionViewer(ImageViewer): """Viewer for displaying image collections. Select the displayed frame of the image collection using the slider or with the following keyboard shortcuts: left/right arrows Previous/next image in collection. number keys, 0--9 0% to 90% of collection. For example, "5" goes to the image in the middle (i.e. 50%) of the collection. home/end keys First/last image in collection. Subclasses and plugins will likely extend the `update_image` method to add custom overlays or filter the displayed image. Parameters ---------- image_collection : list of images List of images to be displayed. update_on : {'move' | 'release'} Control whether image is updated on slide or release of the image slider. Using 'on_release' will give smoother behavior when displaying large images or when writing a plugin/subclass that requires heavy computation. """ def __init__(self, image_collection, update_on='move', **kwargs): self.image_collection = image_collection self.index = 0 self.num_images = len(self.image_collection) first_image = image_collection[0] super(CollectionViewer, self).__init__(first_image) slider_kws = dict(value=0, low=0, high=self.num_images - 1) slider_kws['update_on'] = update_on slider_kws['callback'] = self.update_index slider_kws['value_type'] = 'int' self.slider = Slider('frame', **slider_kws) self.layout.addWidget(self.slider) #TODO: Adjust height to accomodate slider; the following doesn't work # s_size = self.slider.sizeHint() # cs_size = self.canvas.sizeHint() # self.resize(cs_size.width(), cs_size.height() + s_size.height()) def update_index(self, name, index): """Select image on display using index into image collection.""" index = int(round(index)) if index == self.index: return # clip index value to collection limits index = max(index, 0) index = min(index, self.num_images - 1) self.index = index self.slider.val = index self.update_image(self.image_collection[index]) def update_image(self, image): """Update displayed image. This method can be overridden or extended in subclasses and plugins to react to image changes. """ self._update_original_image(image) def keyPressEvent(self, event): if type(event) == QtGui.QKeyEvent: key = event.key() # Number keys (code: 0 = key 48, 9 = key 57) move to deciles if 48 <= key < 58: index = 0.1 * int(key - 48) * self.num_images self.update_index('', index) event.accept() else: event.ignore() else: event.ignore() scikit-image-0.9.3/skimage/viewer/widgets/000077500000000000000000000000001223313777300204705ustar00rootroot00000000000000scikit-image-0.9.3/skimage/viewer/widgets/__init__.py000066400000000000000000000000531223313777300225770ustar00rootroot00000000000000from .core import * from .history import * scikit-image-0.9.3/skimage/viewer/widgets/core.py000066400000000000000000000210151223313777300217710ustar00rootroot00000000000000""" Widgets for interacting with ImageViewer. These widgets should be added to a Plugin subclass using its `add_widget` method or calling:: plugin += Widget(...) on a Plugin instance. The Plugin will delegate action based on the widget's parameter type specified by its `ptype` attribute, which can be: 'arg' : positional argument passed to Plugin's `filter_image` method. 'kwarg' : keyword argument passed to Plugin's `filter_image` method. 'plugin' : attribute of Plugin. You'll probably need to add a class property of the same name that updates the display. """ from ..qt import QtGui from ..qt import QtCore from ..qt.QtCore import Qt from ..utils import RequiredAttr __all__ = ['BaseWidget', 'Slider', 'ComboBox', 'Text'] class BaseWidget(QtGui.QWidget): plugin = RequiredAttr("Widget is not attached to a Plugin.") def __init__(self, name, ptype=None, callback=None): super(BaseWidget, self).__init__() self.name = name self.ptype = ptype self.callback = callback self.plugin = None @property def val(self): msg = "Subclass of BaseWidget requires `val` property" raise NotImplementedError(msg) def _value_changed(self, value): self.callback(self.name, value) class Text(BaseWidget): def __init__(self, name=None, text=''): super(Text, self).__init__(name) self._label = QtGui.QLabel() self.text = text self.layout = QtGui.QHBoxLayout(self) if name is not None: name_label = QtGui.QLabel() name_label.setText(name) self.layout.addWidget(name_label) self.layout.addWidget(self._label) @property def text(self): return self._label.text() @text.setter def text(self, text_str): self._label.setText(text_str) class Slider(BaseWidget): """Slider widget for adjusting numeric parameters. Parameters ---------- name : str Name of slider parameter. If this parameter is passed as a keyword argument, it must match the name of that keyword argument (spaces are replaced with underscores). In addition, this name is displayed as the name of the slider. low, high : float Range of slider values. value : float Default slider value. If None, use midpoint between `low` and `high`. value_type : {'float' | 'int'} Numeric type of slider value. ptype : {'arg' | 'kwarg' | 'plugin'} Parameter type. callback : function Callback function called in response to slider changes. This function is typically set when the widget is added to a plugin. orientation : {'horizontal' | 'vertical'} Slider orientation. update_on : {'release' | 'move'} Control when callback function is called: on slider move or release. """ def __init__(self, name, low=0.0, high=1.0, value=None, value_type='float', ptype='kwarg', callback=None, max_edit_width=60, orientation='horizontal', update_on='release'): super(Slider, self).__init__(name, ptype, callback) if value is None: value = (high - low) / 2. # Set widget orientation #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if orientation == 'vertical': self.slider = QtGui.QSlider(Qt.Vertical) alignment = QtCore.Qt.AlignHCenter align_text = QtCore.Qt.AlignHCenter align_value = QtCore.Qt.AlignHCenter self.layout = QtGui.QVBoxLayout(self) elif orientation == 'horizontal': self.slider = QtGui.QSlider(Qt.Horizontal) alignment = QtCore.Qt.AlignVCenter align_text = QtCore.Qt.AlignLeft align_value = QtCore.Qt.AlignRight self.layout = QtGui.QHBoxLayout(self) else: msg = "Unexpected value %s for 'orientation'" raise ValueError(msg % orientation) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Set slider behavior for float and int values. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if value_type == 'float': # divide slider into 1000 discrete values slider_max = 1000 self._scale = float(high - low) / slider_max self.slider.setRange(0, slider_max) self.value_fmt = '%2.2f' elif value_type == 'int': self.slider.setRange(low, high) self.value_fmt = '%d' else: msg = "Expected `value_type` to be 'float' or 'int'; received: %s" raise ValueError(msg % value_type) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ self.value_type = value_type self._low = low self._high = high # Update slider position to default value self.val = value if update_on == 'move': self.slider.valueChanged.connect(self._on_slider_changed) elif update_on == 'release': self.slider.sliderReleased.connect(self._on_slider_changed) else: raise ValueError("Unexpected value %s for 'update_on'" % update_on) self.slider.setFocusPolicy(QtCore.Qt.StrongFocus) self.name_label = QtGui.QLabel() self.name_label.setText(self.name) self.name_label.setAlignment(align_text) self.editbox = QtGui.QLineEdit() self.editbox.setMaximumWidth(max_edit_width) self.editbox.setText(self.value_fmt % self.val) self.editbox.setAlignment(align_value) self.editbox.editingFinished.connect(self._on_editbox_changed) self.layout.addWidget(self.name_label) self.layout.addWidget(self.slider) self.layout.addWidget(self.editbox) def _on_slider_changed(self): """Call callback function with slider's name and value as parameters""" value = self.val self.editbox.setText(str(value)[:4]) self.callback(self.name, value) def _on_editbox_changed(self): """Validate input and set slider value""" try: value = float(self.editbox.text()) except ValueError: self._bad_editbox_input() return if not self._low <= value <= self._high: self._bad_editbox_input() return self.val = value self._good_editbox_input() self.callback(self.name, value) def _good_editbox_input(self): self.editbox.setStyleSheet("background-color: rgb(255, 255, 255)") def _bad_editbox_input(self): self.editbox.setStyleSheet("background-color: rgb(255, 200, 200)") @property def val(self): value = self.slider.value() if self.value_type == 'float': value = value * self._scale + self._low return value @val.setter def val(self, value): if self.value_type == 'float': value = (value - self._low) / self._scale self.slider.setValue(value) class ComboBox(BaseWidget): """ComboBox widget for selecting among a list of choices. Parameters ---------- name : str Name of slider parameter. If this parameter is passed as a keyword argument, it must match the name of that keyword argument (spaces are replaced with underscores). In addition, this name is displayed as the name of the slider. items: list Allowed parameter values. ptype : {'arg' | 'kwarg' | 'plugin'} Parameter type. callback : function Callback function called in response to slider changes. This function is typically set when the widget is added to a plugin. """ def __init__(self, name, items, ptype='kwarg', callback=None): super(ComboBox, self).__init__(name, ptype, callback) self.name_label = QtGui.QLabel() self.name_label.setText(self.name) self.name_label.setAlignment(QtCore.Qt.AlignLeft) self._combo_box = QtGui.QComboBox() self._combo_box.addItems(items) self.layout = QtGui.QHBoxLayout(self) self.layout.addWidget(self.name_label) self.layout.addWidget(self._combo_box) self._combo_box.currentIndexChanged.connect(self._value_changed) # self.connect(self._combo_box, # SIGNAL("currentIndexChanged(int)"), self.updateUi) @property def val(self): return self._combo_box.value() @property def index(self): return self._combo_box.currentIndex() @index.setter def index(self, i): self._combo_box.setCurrentIndex(i) scikit-image-0.9.3/skimage/viewer/widgets/history.py000066400000000000000000000063611223313777300225510ustar00rootroot00000000000000from textwrap import dedent from ..qt import QtGui from ..qt import QtCore import numpy as np import skimage from skimage import io from .core import BaseWidget from ..utils import dialogs __all__ = ['OKCancelButtons', 'SaveButtons'] class OKCancelButtons(BaseWidget): """Buttons that close the parent plugin. OK will replace the original image with the current (filtered) image. Cancel will just close the plugin. """ def __init__(self, button_width=80): name = 'OK/Cancel' super(OKCancelButtons, self).__init__(name) self.ok = QtGui.QPushButton('OK') self.ok.clicked.connect(self.update_original_image) self.ok.setMaximumWidth(button_width) self.ok.setFocusPolicy(QtCore.Qt.NoFocus) self.cancel = QtGui.QPushButton('Cancel') self.cancel.clicked.connect(self.close_plugin) self.cancel.setMaximumWidth(button_width) self.cancel.setFocusPolicy(QtCore.Qt.NoFocus) self.layout = QtGui.QHBoxLayout(self) self.layout.addStretch() self.layout.addWidget(self.cancel) self.layout.addWidget(self.ok) def update_original_image(self): image = self.plugin.image_viewer.image self.plugin.image_viewer.original_image = image self.plugin.close() def close_plugin(self): # Image viewer will restore original image on close. self.plugin.close() class SaveButtons(BaseWidget): """Buttons to save image to io.stack or to a file.""" def __init__(self, name='Save to:', default_format='png'): super(SaveButtons, self).__init__(name) self.default_format = default_format self.name_label = QtGui.QLabel() self.name_label.setText(name) self.save_file = QtGui.QPushButton('File') self.save_file.clicked.connect(self.save_to_file) self.save_file.setFocusPolicy(QtCore.Qt.NoFocus) self.save_stack = QtGui.QPushButton('Stack') self.save_stack.clicked.connect(self.save_to_stack) self.save_stack.setFocusPolicy(QtCore.Qt.NoFocus) self.layout = QtGui.QHBoxLayout(self) self.layout.addWidget(self.name_label) self.layout.addWidget(self.save_stack) self.layout.addWidget(self.save_file) def save_to_stack(self): image = self.plugin.filtered_image.copy() io.push(image) msg = dedent('''\ The image has been pushed to the io stack. Use io.pop() to retrieve the most recently pushed image. NOTE: The io stack only works in interactive sessions.''') notify(msg) def save_to_file(self): filename = dialogs.save_file_dialog() if filename is None: return image = self.plugin.filtered_image if image.dtype == np.bool: #TODO: This check/conversion should probably be in `imsave`. image = skimage.img_as_ubyte(image) io.imsave(filename, image) def notify(msg): msglabel = QtGui.QLabel(msg) dialog = QtGui.QDialog() ok = QtGui.QPushButton('OK', dialog) ok.clicked.connect(dialog.accept) ok.setDefault(True) dialog.layout = QtGui.QGridLayout(dialog) dialog.layout.addWidget(msglabel, 0, 0, 1, 3) dialog.layout.addWidget(ok, 1, 1) dialog.exec_() scikit-image-0.9.3/tox.ini000066400000000000000000000002521223313777300154130ustar00rootroot00000000000000[testenv] deps = nose coverage cython numpy scipy commands= nosetests {posargs:--with-coverage --cover-package=skimage} coverage xml scikit-image-0.9.3/viewer_examples/000077500000000000000000000000001223313777300173005ustar00rootroot00000000000000scikit-image-0.9.3/viewer_examples/plugins/000077500000000000000000000000001223313777300207615ustar00rootroot00000000000000scikit-image-0.9.3/viewer_examples/plugins/canny.py000066400000000000000000000003171223313777300224440ustar00rootroot00000000000000from skimage import data from skimage.viewer import ImageViewer from skimage.viewer.plugins.canny import CannyPlugin image = data.camera() viewer = ImageViewer(image) viewer += CannyPlugin() viewer.show() scikit-image-0.9.3/viewer_examples/plugins/canny_simple.py000066400000000000000000000014131223313777300240130ustar00rootroot00000000000000from skimage import data from skimage.filter import canny from skimage.viewer import ImageViewer from skimage.viewer.widgets import Slider from skimage.viewer.widgets.history import SaveButtons from skimage.viewer.plugins.overlayplugin import OverlayPlugin image = data.camera() # You can create a UI for a filter just by passing a filter function... plugin = OverlayPlugin(image_filter=canny) # ... and adding widgets to adjust parameter values. plugin += Slider('sigma', 0, 5) plugin += Slider('low threshold', 0, 255) plugin += Slider('high threshold', 0, 255) # ... and we can also add buttons to save the overlay: plugin += SaveButtons(name='Save overlay to:') # Finally, attach the plugin to an image viewer. viewer = ImageViewer(image) viewer += plugin viewer.show() scikit-image-0.9.3/viewer_examples/plugins/collection_overlay.py000066400000000000000000000007671223313777300252410ustar00rootroot00000000000000""" ============================================== ``CollectionViewer`` with an ``OverlayPlugin`` ============================================== Demo of a CollectionViewer for viewing collections of images with an overlay plugin. """ from skimage import data from skimage.viewer import CollectionViewer from skimage.viewer.plugins.canny import CannyPlugin img_collection = [data.camera(), data.coins(), data.text()] viewer = CollectionViewer(img_collection) viewer += CannyPlugin() viewer.show() scikit-image-0.9.3/viewer_examples/plugins/collection_plugin.py000066400000000000000000000015451223313777300250510ustar00rootroot00000000000000""" ================================== ``CollectionViewer`` with a plugin ================================== Demo of a CollectionViewer for viewing collections of images with the `autolevel` rank filter connected as a plugin. """ from skimage import data from skimage.filter import rank from skimage.morphology import disk from skimage.viewer import CollectionViewer from skimage.viewer.widgets import Slider from skimage.viewer.plugins.base import Plugin # Wrap autolevel function to make the disk size a filter argument. def autolevel(image, disk_size): return rank.autolevel(image, disk(disk_size)) img_collection = [data.camera(), data.coins(), data.text()] plugin = Plugin(image_filter=autolevel) plugin += Slider('disk_size', 2, 8, value_type='int') plugin.name = "Autolevel" viewer = CollectionViewer(img_collection) viewer += plugin viewer.show() scikit-image-0.9.3/viewer_examples/plugins/color_histogram.py000066400000000000000000000003641223313777300245310ustar00rootroot00000000000000from skimage.viewer import ImageViewer from skimage.viewer.plugins.color_histogram import ColorHistogram from skimage import data image = data.load('color.png') viewer = ImageViewer(image) viewer += ColorHistogram(dock='right') viewer.show() scikit-image-0.9.3/viewer_examples/plugins/croptool.py000066400000000000000000000003001223313777300231650ustar00rootroot00000000000000from skimage import data from skimage.viewer import ImageViewer from skimage.viewer.plugins.crop import Crop image = data.camera() viewer = ImageViewer(image) viewer += Crop() viewer.show() scikit-image-0.9.3/viewer_examples/plugins/lineprofile.py000066400000000000000000000003251223313777300236430ustar00rootroot00000000000000from skimage import data from skimage.viewer import ImageViewer from skimage.viewer.plugins.lineprofile import LineProfile image = data.camera() viewer = ImageViewer(image) viewer += LineProfile() viewer.show() scikit-image-0.9.3/viewer_examples/plugins/lineprofile_rgb.py000066400000000000000000000003261223313777300244760ustar00rootroot00000000000000from skimage import data from skimage.viewer import ImageViewer from skimage.viewer.plugins.lineprofile import LineProfile image = data.chelsea() viewer = ImageViewer(image) viewer += LineProfile() viewer.show() scikit-image-0.9.3/viewer_examples/plugins/measure.py000066400000000000000000000003111223313777300227670ustar00rootroot00000000000000from skimage import data from skimage.viewer import ImageViewer from skimage.viewer.plugins.measure import Measure image = data.camera() viewer = ImageViewer(image) viewer += Measure() viewer.show() scikit-image-0.9.3/viewer_examples/plugins/median_filter.py000066400000000000000000000007111223313777300241340ustar00rootroot00000000000000from skimage import data from skimage.filter import median_filter from skimage.viewer import ImageViewer from skimage.viewer.widgets import Slider, OKCancelButtons, SaveButtons from skimage.viewer.plugins.base import Plugin image = data.coins() viewer = ImageViewer(image) plugin = Plugin(image_filter=median_filter) plugin += Slider('radius', 2, 10, value_type='int') plugin += SaveButtons() plugin += OKCancelButtons() viewer += plugin viewer.show() scikit-image-0.9.3/viewer_examples/plugins/probabilistic_hough.py000066400000000000000000000026661223313777300253650ustar00rootroot00000000000000import numpy as np from skimage import data from skimage import draw from skimage.transform import probabilistic_hough_line from skimage.viewer import ImageViewer from skimage.viewer.widgets import Slider from skimage.viewer.plugins.overlayplugin import OverlayPlugin from skimage.viewer.plugins.canny import CannyPlugin def line_image(shape, lines): image = np.zeros(shape, dtype=bool) for end_points in lines: # hough lines returns (x, y) points, draw.line wants (row, columns) end_points = np.asarray(end_points)[:, ::-1] image[draw.line(*np.ravel(end_points))] = 1 return image def hough_lines(image, *args, **kwargs): # Set threshold to 0.5 since we're working with a binary image (from canny) lines = probabilistic_hough_line(image, threshold=0.5, *args, **kwargs) image = line_image(image.shape, lines) return image image = data.camera() canny_viewer = ImageViewer(image) canny_plugin = CannyPlugin() canny_viewer += canny_plugin hough_plugin = OverlayPlugin(image_filter=hough_lines) hough_plugin.name = 'Hough Lines' hough_plugin += Slider('line length', 0, 100) hough_plugin += Slider('line gap', 0, 20) # Passing a plugin to a viewer connects the output of the plugin to the viewer. hough_viewer = ImageViewer(canny_plugin) hough_viewer += hough_plugin # Show viewers displays both viewers since `hough_viewer` is connected to # `canny_viewer` through `canny_plugin` canny_viewer.show() scikit-image-0.9.3/viewer_examples/plugins/watershed_demo.py000066400000000000000000000023741223313777300243330ustar00rootroot00000000000000import matplotlib.pyplot as plt from skimage import data from skimage import filter from skimage import morphology from skimage.viewer import ImageViewer from skimage.viewer.widgets import history from skimage.viewer.plugins.labelplugin import LabelPainter class OKCancelButtons(history.OKCancelButtons): def update_original_image(self): # OKCancelButtons updates the original image with the filtered image # by default. Override this method to update the overlay. self.plugin._show_watershed() self.plugin.close() class WatershedPlugin(LabelPainter): def help(self): helpstr = ("Watershed plugin", "----------------", "Use mouse to paint each region with a different label.", "Press OK to display segmented image.") return '\n'.join(helpstr) def _show_watershed(self): viewer = self.image_viewer edge_image = filter.sobel(viewer.image) labels = morphology.watershed(edge_image, self.paint_tool.overlay) viewer.ax.imshow(labels, cmap=plt.cm.jet, alpha=0.5) viewer.redraw() image = data.coins() plugin = WatershedPlugin() plugin += OKCancelButtons() viewer = ImageViewer(image) viewer += plugin viewer.show() scikit-image-0.9.3/viewer_examples/viewers/000077500000000000000000000000001223313777300207645ustar00rootroot00000000000000scikit-image-0.9.3/viewer_examples/viewers/collection_viewer.py000066400000000000000000000014331223313777300250530ustar00rootroot00000000000000""" ===================== CollectionViewer demo ===================== Demo of CollectionViewer for viewing collections of images. This demo uses the different layers of the gaussian pyramid as image collection. You can scroll through images with the slider, or you can interact with the viewer using your keyboard: left/right arrows Previous/next image in collection. number keys, 0--9 0% to 90% of collection. For example, "5" goes to the image in the middle (i.e. 50%) of the collection. home/end keys First/last image in collection. """ from skimage import data from skimage.viewer import CollectionViewer from skimage.transform import pyramid_gaussian img = data.lena() img_collection = tuple(pyramid_gaussian(img)) view = CollectionViewer(img_collection) view.show() scikit-image-0.9.3/viewer_examples/viewers/image_viewer.py000066400000000000000000000002021223313777300237730ustar00rootroot00000000000000from skimage import data from skimage.viewer import ImageViewer image = data.camera() viewer = ImageViewer(image) viewer.show()