wcsaxes-0.6/0000755000077000000240000000000012553237435012763 5ustar tomstaff00000000000000wcsaxes-0.6/ah_bootstrap.py0000644000077000000240000006645712436367710016044 0ustar tomstaff00000000000000""" This bootstrap module contains code for ensuring that the astropy_helpers package will be importable by the time the setup.py script runs. It also includes some workarounds to ensure that a recent-enough version of setuptools is being used for the installation. This module should be the first thing imported in the setup.py of distributions that make use of the utilities in astropy_helpers. If the distribution ships with its own copy of astropy_helpers, this module will first attempt to import from the shipped copy. However, it will also check PyPI to see if there are any bug-fix releases on top of the current version that may be useful to get past platform-specific bugs that have been fixed. When running setup.py, use the ``--offline`` command-line option to disable the auto-upgrade checks. When this module is imported or otherwise executed it automatically calls a main function that attempts to read the project's setup.cfg file, which it checks for a configuration section called ``[ah_bootstrap]`` the presences of that section, and options therein, determine the next step taken: If it contains an option called ``auto_use`` with a value of ``True``, it will automatically call the main function of this module called `use_astropy_helpers` (see that function's docstring for full details). Otherwise no further action is taken (however, ``ah_bootstrap.use_astropy_helpers`` may be called manually from within the setup.py script). Additional options in the ``[ah_boostrap]`` section of setup.cfg have the same names as the arguments to `use_astropy_helpers`, and can be used to configure the bootstrap script when ``auto_use = True``. See https://github.com/astropy/astropy-helpers for more details, and for the latest version of this module. """ import contextlib import errno import imp import io import locale import os import re import subprocess as sp import sys try: from ConfigParser import ConfigParser, RawConfigParser except ImportError: from configparser import ConfigParser, RawConfigParser if sys.version_info[0] < 3: _str_types = (str, unicode) _text_type = unicode PY3 = False else: _str_types = (str, bytes) _text_type = str PY3 = True # Some pre-setuptools checks to ensure that either distribute or setuptools >= # 0.7 is used (over pre-distribute setuptools) if it is available on the path; # otherwise the latest setuptools will be downloaded and bootstrapped with # ``ez_setup.py``. This used to be included in a separate file called # setuptools_bootstrap.py; but it was combined into ah_bootstrap.py try: import pkg_resources _setuptools_req = pkg_resources.Requirement.parse('setuptools>=0.7') # This may raise a DistributionNotFound in which case no version of # setuptools or distribute is properly installed _setuptools = pkg_resources.get_distribution('setuptools') if _setuptools not in _setuptools_req: # Older version of setuptools; check if we have distribute; again if # this results in DistributionNotFound we want to give up _distribute = pkg_resources.get_distribution('distribute') if _setuptools != _distribute: # It's possible on some pathological systems to have an old version # of setuptools and distribute on sys.path simultaneously; make # sure distribute is the one that's used sys.path.insert(1, _distribute.location) _distribute.activate() imp.reload(pkg_resources) except: # There are several types of exceptions that can occur here; if all else # fails bootstrap and use the bootstrapped version from ez_setup import use_setuptools use_setuptools() from distutils import log from distutils.debug import DEBUG # In case it didn't successfully import before the ez_setup checks import pkg_resources from setuptools import Distribution from setuptools.package_index import PackageIndex from setuptools.sandbox import run_setup # Note: The following import is required as a workaround to # https://github.com/astropy/astropy-helpers/issues/89; if we don't import this # module now, it will get cleaned up after `run_setup` is called, but that will # later cause the TemporaryDirectory class defined in it to stop working when # used later on by setuptools try: import setuptools.py31compat except ImportError: pass # TODO: Maybe enable checking for a specific version of astropy_helpers? DIST_NAME = 'astropy-helpers' PACKAGE_NAME = 'astropy_helpers' # Defaults for other options DOWNLOAD_IF_NEEDED = True INDEX_URL = 'https://pypi.python.org/simple' USE_GIT = True AUTO_UPGRADE = True def use_astropy_helpers(path=None, download_if_needed=None, index_url=None, use_git=None, auto_upgrade=None): """ Ensure that the `astropy_helpers` module is available and is importable. This supports automatic submodule initialization if astropy_helpers is included in a project as a git submodule, or will download it from PyPI if necessary. Parameters ---------- path : str or None, optional A filesystem path relative to the root of the project's source code that should be added to `sys.path` so that `astropy_helpers` can be imported from that path. If the path is a git submodule it will automatically be initialzed and/or updated. The path may also be to a ``.tar.gz`` archive of the astropy_helpers source distribution. In this case the archive is automatically unpacked and made temporarily available on `sys.path` as a ``.egg`` archive. If `None` skip straight to downloading. download_if_needed : bool, optional If the provided filesystem path is not found an attempt will be made to download astropy_helpers from PyPI. It will then be made temporarily available on `sys.path` as a ``.egg`` archive (using the ``setup_requires`` feature of setuptools. If the ``--offline`` option is given at the command line the value of this argument is overridden to `False`. index_url : str, optional If provided, use a different URL for the Python package index than the main PyPI server. use_git : bool, optional If `False` no git commands will be used--this effectively disables support for git submodules. If the ``--no-git`` option is given at the command line the value of this argument is overridden to `False`. auto_upgrade : bool, optional By default, when installing a package from a non-development source distribution ah_boostrap will try to automatically check for patch releases to astropy-helpers on PyPI and use the patched version over any bundled versions. Setting this to `False` will disable that functionality. If the ``--offline`` option is given at the command line the value of this argument is overridden to `False`. """ # True by default, unless the --offline option was provided on the command # line if '--offline' in sys.argv: download_if_needed = False auto_upgrade = False offline = True sys.argv.remove('--offline') else: offline = False if '--no-git' in sys.argv: use_git = False sys.argv.remove('--no-git') if path is None: path = PACKAGE_NAME if download_if_needed is None: download_if_needed = DOWNLOAD_IF_NEEDED if index_url is None: index_url = INDEX_URL # If this is a release then the .git directory will not exist so we # should not use git. git_dir_exists = os.path.exists(os.path.join(os.path.dirname(__file__), '.git')) if use_git is None and not git_dir_exists: use_git = False if use_git is None: use_git = USE_GIT if auto_upgrade is None: auto_upgrade = AUTO_UPGRADE # Declared as False by default--later we check if astropy-helpers can be # upgraded from PyPI, but only if not using a source distribution (as in # the case of import from a git submodule) is_submodule = False if not isinstance(path, _str_types): if path is not None: raise TypeError('path must be a string or None') if not download_if_needed: log.debug('a path was not given and download from PyPI was not ' 'allowed so this is effectively a no-op') return elif not os.path.exists(path) or os.path.isdir(path): # Even if the given path does not exist on the filesystem, if it *is* a # submodule, `git submodule init` will create it is_submodule = _check_submodule(path, use_git=use_git, offline=offline) if is_submodule or os.path.isdir(path): log.info( 'Attempting to import astropy_helpers from {0} {1!r}'.format( 'submodule' if is_submodule else 'directory', path)) dist = _directory_import(path) else: dist = None if dist is None: msg = ( 'The requested path {0!r} for importing {1} does not ' 'exist, or does not contain a copy of the {1} package. ' 'Attempting download instead.'.format(path, PACKAGE_NAME)) if download_if_needed: log.warn(msg) else: raise _AHBootstrapSystemExit(msg) elif os.path.isfile(path): # Handle importing from a source archive; this also uses setup_requires # but points easy_install directly to the source archive try: dist = _do_download(find_links=[path]) except Exception as e: if download_if_needed: log.warn('{0}\nWill attempt to download astropy_helpers from ' 'PyPI instead.'.format(str(e))) dist = None else: raise _AHBootstrapSystemExit(e.args[0]) else: msg = ('{0!r} is not a valid file or directory (it could be a ' 'symlink?)'.format(path)) if download_if_needed: log.warn(msg) dist = None else: raise _AHBootstrapSystemExit(msg) if dist is not None and auto_upgrade and not is_submodule: # A version of astropy-helpers was found on the available path, but # check to see if a bugfix release is available on PyPI upgrade = _do_upgrade(dist, index_url) if upgrade is not None: dist = upgrade elif dist is None: # Last resort--go ahead and try to download the latest version from # PyPI try: if download_if_needed: log.warn( "Downloading astropy_helpers; run setup.py with the " "--offline option to force offline installation.") dist = _do_download(index_url=index_url) else: raise _AHBootstrapSystemExit( "No source for the astropy_helpers package; " "astropy_helpers must be available as a prerequisite to " "installing this package.") except Exception as e: if DEBUG: raise else: raise _AHBootstrapSystemExit(e.args[0]) if dist is not None: # Otherwise we found a version of astropy-helpers so we're done # Just activate the found distribibution on sys.path--if we did a # download this usually happens automatically but do it again just to # be sure # Note: Adding the dist to the global working set also activates it by # default pkg_resources.working_set.add(dist) def _do_download(version='', find_links=None, index_url=None): try: if find_links: allow_hosts = '' index_url = None else: allow_hosts = None # Annoyingly, setuptools will not handle other arguments to # Distribution (such as options) before handling setup_requires, so it # is not straightfoward to programmatically augment the arguments which # are passed to easy_install class _Distribution(Distribution): def get_option_dict(self, command_name): opts = Distribution.get_option_dict(self, command_name) if command_name == 'easy_install': if find_links is not None: opts['find_links'] = ('setup script', find_links) if index_url is not None: opts['index_url'] = ('setup script', index_url) if allow_hosts is not None: opts['allow_hosts'] = ('setup script', allow_hosts) return opts if version: req = '{0}=={1}'.format(DIST_NAME, version) else: req = DIST_NAME attrs = {'setup_requires': [req]} if DEBUG: dist = _Distribution(attrs=attrs) else: with _silence(): dist = _Distribution(attrs=attrs) # If the setup_requires succeeded it will have added the new dist to # the main working_set return pkg_resources.working_set.by_key.get(DIST_NAME) except Exception as e: if DEBUG: raise msg = 'Error retrieving astropy helpers from {0}:\n{1}' if find_links: source = find_links[0] elif index_url: source = index_url else: source = 'PyPI' raise Exception(msg.format(source, repr(e))) def _do_upgrade(dist, index_url): # Build up a requirement for a higher bugfix release but a lower minor # release (so API compatibility is guaranteed) # sketchy version parsing--maybe come up with something a bit more # robust for this major, minor = (int(part) for part in dist.parsed_version[:2]) next_minor = '.'.join([str(major), str(minor + 1), '0']) req = pkg_resources.Requirement.parse( '{0}>{1},<{2}'.format(DIST_NAME, dist.version, next_minor)) package_index = PackageIndex(index_url=index_url) upgrade = package_index.obtain(req) if upgrade is not None: return _do_download(version=upgrade.version, index_url=index_url) def _directory_import(path): """ Import astropy_helpers from the given path, which will be added to sys.path. Must return True if the import succeeded, and False otherwise. """ # Return True on success, False on failure but download is allowed, and # otherwise raise SystemExit path = os.path.abspath(path) # Use an empty WorkingSet rather than the man pkg_resources.working_set, # since on older versions of setuptools this will invoke a VersionConflict # when trying to install an upgrade ws = pkg_resources.WorkingSet([]) ws.add_entry(path) dist = ws.by_key.get(DIST_NAME) if dist is None: # We didn't find an egg-info/dist-info in the given path, but if a # setup.py exists we can generate it setup_py = os.path.join(path, 'setup.py') if os.path.isfile(setup_py): with _silence(): run_setup(os.path.join(path, 'setup.py'), ['egg_info']) for dist in pkg_resources.find_distributions(path, True): # There should be only one... return dist return dist def _check_submodule(path, use_git=True, offline=False): """ Check if the given path is a git submodule. See the docstrings for ``_check_submodule_using_git`` and ``_check_submodule_no_git`` for futher details. """ if use_git: return _check_submodule_using_git(path, offline) else: return _check_submodule_no_git(path) def _check_submodule_using_git(path, offline): """ Check if the given path is a git submodule. If so, attempt to initialize and/or update the submodule if needed. This function makes calls to the ``git`` command in subprocesses. The ``_check_submodule_no_git`` option uses pure Python to check if the given path looks like a git submodule, but it cannot perform updates. """ if PY3 and not isinstance(path, _text_type): fs_encoding = sys.getfilesystemencoding() path = path.decode(fs_encoding) try: p = sp.Popen(['git', 'submodule', 'status', '--', path], stdout=sp.PIPE, stderr=sp.PIPE) stdout, stderr = p.communicate() except OSError as e: if DEBUG: raise if e.errno == errno.ENOENT: # The git command simply wasn't found; this is most likely the # case on user systems that don't have git and are simply # trying to install the package from PyPI or a source # distribution. Silently ignore this case and simply don't try # to use submodules return False else: raise _AHBoostrapSystemExit( 'An unexpected error occurred when running the ' '`git submodule status` command:\n{0}'.format(str(e))) # Can fail of the default locale is not configured properly. See # https://github.com/astropy/astropy/issues/2749. For the purposes under # consideration 'latin1' is an acceptable fallback. try: stdio_encoding = locale.getdefaultlocale()[1] or 'latin1' except ValueError: # Due to an OSX oddity locale.getdefaultlocale() can also crash # depending on the user's locale/language settings. See: # http://bugs.python.org/issue18378 stdio_encoding = 'latin1' if p.returncode != 0 or stderr: # Unfortunately the return code alone cannot be relied on, as # earlier versions of git returned 0 even if the requested submodule # does not exist stderr = stderr.decode(stdio_encoding) # This is a warning that occurs in perl (from running git submodule) # which only occurs with a malformatted locale setting which can # happen sometimes on OSX. See again # https://github.com/astropy/astropy/issues/2749 perl_warning = ('perl: warning: Falling back to the standard locale ' '("C").') if not stderr.strip().endswith(perl_warning): # Some other uknown error condition occurred log.warn('git submodule command failed ' 'unexpectedly:\n{0}'.format(stderr)) return False stdout = stdout.decode(stdio_encoding) # The stdout should only contain one line--the status of the # requested submodule m = _git_submodule_status_re.match(stdout) if m: # Yes, the path *is* a git submodule _update_submodule(m.group('submodule'), m.group('status'), offline) return True else: log.warn( 'Unexpected output from `git submodule status`:\n{0}\n' 'Will attempt import from {1!r} regardless.'.format( stdout, path)) return False def _check_submodule_no_git(path): """ Like ``_check_submodule_using_git``, but simply parses the .gitmodules file to determine if the supplied path is a git submodule, and does not exec any subprocesses. This can only determine if a path is a submodule--it does not perform updates, etc. This function may need to be updated if the format of the .gitmodules file is changed between git versions. """ gitmodules_path = os.path.abspath('.gitmodules') if not os.path.isfile(gitmodules_path): return False # This is a minimal reader for gitconfig-style files. It handles a few of # the quirks that make gitconfig files incompatible with ConfigParser-style # files, but does not support the full gitconfig syntaix (just enough # needed to read a .gitmodules file). gitmodules_fileobj = io.StringIO() # Must use io.open for cross-Python-compatible behavior wrt unicode with io.open(gitmodules_path) as f: for line in f: # gitconfig files are more flexible with leading whitespace; just # go ahead and remove it line = line.lstrip() # comments can start with either # or ; if line and line[0] in (':', ';'): continue gitmodules_fileobj.write(line) gitmodules_fileobj.seek(0) cfg = RawConfigParser() try: cfg.readfp(gitmodules_fileobj) except Exception as exc: log.warn('Malformatted .gitmodules file: {0}\n' '{1} cannot be assumed to be a git submodule.'.format( exc, path)) return False for section in cfg.sections(): if not cfg.has_option(section, 'path'): continue submodule_path = cfg.get(section, 'path').rstrip(os.sep) if submodule_path == path.rstrip(os.sep): return True return False def _update_submodule(submodule, status, offline): if status == ' ': # The submodule is up to date; no action necessary return elif status == '-': if offline: raise _AHBootstrapSystemExit( "Cannot initialize the {0} submodule in --offline mode; this " "requires being able to clone the submodule from an online " "repository.".format(submodule)) cmd = ['update', '--init'] action = 'Initializing' elif status == '+': cmd = ['update'] action = 'Updating' if offline: cmd.append('--no-fetch') elif status == 'U': raise _AHBoostrapSystemExit( 'Error: Submodule {0} contains unresolved merge conflicts. ' 'Please complete or abandon any changes in the submodule so that ' 'it is in a usable state, then try again.'.format(submodule)) else: log.warn('Unknown status {0!r} for git submodule {1!r}. Will ' 'attempt to use the submodule as-is, but try to ensure ' 'that the submodule is in a clean state and contains no ' 'conflicts or errors.\n{2}'.format(status, submodule, _err_help_msg)) return err_msg = None cmd = ['git', 'submodule'] + cmd + ['--', submodule] log.warn('{0} {1} submodule with: `{2}`'.format( action, submodule, ' '.join(cmd))) try: p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE) stdout, stderr = p.communicate() except OSError as e: err_msg = str(e) else: if p.returncode != 0: stderr_encoding = locale.getdefaultlocale()[1] err_msg = stderr.decode(stderr_encoding) if err_msg: log.warn('An unexpected error occurred updating the git submodule ' '{0!r}:\n{1}\n{2}'.format(submodule, err_msg, _err_help_msg)) class _DummyFile(object): """A noop writeable object.""" errors = '' # Required for Python 3.x encoding = 'utf-8' def write(self, s): pass def flush(self): pass @contextlib.contextmanager def _silence(): """A context manager that silences sys.stdout and sys.stderr.""" old_stdout = sys.stdout old_stderr = sys.stderr sys.stdout = _DummyFile() sys.stderr = _DummyFile() exception_occurred = False try: yield except: exception_occurred = True # Go ahead and clean up so that exception handling can work normally sys.stdout = old_stdout sys.stderr = old_stderr raise if not exception_occurred: sys.stdout = old_stdout sys.stderr = old_stderr _err_help_msg = """ If the problem persists consider installing astropy_helpers manually using pip (`pip install astropy_helpers`) or by manually downloading the source archive, extracting it, and installing by running `python setup.py install` from the root of the extracted source code. """ class _AHBootstrapSystemExit(SystemExit): def __init__(self, *args): if not args: msg = 'An unknown problem occurred bootstrapping astropy_helpers.' else: msg = args[0] msg += '\n' + _err_help_msg super(_AHBootstrapSystemExit, self).__init__(msg, *args[1:]) if sys.version_info[:2] < (2, 7): # In Python 2.6 the distutils log does not log warnings, errors, etc. to # stderr so we have to wrap it to ensure consistency at least in this # module import distutils class log(object): def __getattr__(self, attr): return getattr(distutils.log, attr) def warn(self, msg, *args): self._log_to_stderr(distutils.log.WARN, msg, *args) def error(self, msg): self._log_to_stderr(distutils.log.ERROR, msg, *args) def fatal(self, msg): self._log_to_stderr(distutils.log.FATAL, msg, *args) def log(self, level, msg, *args): if level in (distutils.log.WARN, distutils.log.ERROR, distutils.log.FATAL): self._log_to_stderr(level, msg, *args) else: distutils.log.log(level, msg, *args) def _log_to_stderr(self, level, msg, *args): # This is the only truly 'public' way to get the current threshold # of the log current_threshold = distutils.log.set_threshold(distutils.log.WARN) distutils.log.set_threshold(current_threshold) if level >= current_threshold: if args: msg = msg % args sys.stderr.write('%s\n' % msg) sys.stderr.flush() log = log() # Output of `git submodule status` is as follows: # # 1: Status indicator: '-' for submodule is uninitialized, '+' if submodule is # initialized but is not at the commit currently indicated in .gitmodules (and # thus needs to be updated), or 'U' if the submodule is in an unstable state # (i.e. has merge conflicts) # # 2. SHA-1 hash of the current commit of the submodule (we don't really need # this information but it's useful for checking that the output is correct) # # 3. The output of `git describe` for the submodule's current commit hash (this # includes for example what branches the commit is on) but only if the # submodule is initialized. We ignore this information for now _git_submodule_status_re = re.compile( '^(?P[+-U ])(?P[0-9a-f]{40}) (?P\S+)( .*)?$') # Implement the auto-use feature; this allows use_astropy_helpers() to be used # at import-time automatically so long as the correct options are specified in # setup.cfg _CFG_OPTIONS = [('auto_use', bool), ('path', str), ('download_if_needed', bool), ('index_url', str), ('use_git', bool), ('auto_upgrade', bool)] def _main(): if not os.path.exists('setup.cfg'): return cfg = ConfigParser() try: cfg.read('setup.cfg') except Exception as e: if DEBUG: raise log.error( "Error reading setup.cfg: {0!r}\nastropy_helpers will not be " "automatically bootstrapped and package installation may fail." "\n{1}".format(e, _err_help_msg)) return if not cfg.has_section('ah_bootstrap'): return kwargs = {} for option, type_ in _CFG_OPTIONS: if not cfg.has_option('ah_bootstrap', option): continue if type_ is bool: value = cfg.getboolean('ah_bootstrap', option) else: value = cfg.get('ah_bootstrap', option) kwargs[option] = value if kwargs.pop('auto_use', False): use_astropy_helpers(**kwargs) _main() wcsaxes-0.6/astropy_helpers/0000755000077000000240000000000012553237435016206 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/.coveragerc0000644000077000000240000000063312346274067020333 0ustar tomstaff00000000000000[run] source = astropy_helpers ah_bootstrap omit = astropy_helpers/tests* [report] exclude_lines = # Have to re-enable the standard pragma pragma: no cover # Don't complain about packages we have installed except ImportError # Don't complain if tests don't hit assertions raise AssertionError raise NotImplementedError # Don't complain about script hooks def main\(.*\): wcsaxes-0.6/astropy_helpers/.travis.yml0000644000077000000240000000343112532571254020315 0ustar tomstaff00000000000000# We set the language to c because python isn't supported on the MacOS X nodes # on Travis. However, the language ends up being irrelevant anyway, since we # install Python ourselves using conda. language: c os: - osx - linux env: matrix: - PYTHON_VERSION=2.6 - PYTHON_VERSION=2.7 - PYTHON_VERSION=3.3 - PYTHON_VERSION=3.4 global: - SETUPTOOLS_VERSION=stable matrix: include: - os: linux env: PYTHON_VERSION=2.7 SETUPTOOLS_VERSION=dev before_install: # Use utf8 encoding. Should be default, but this is insurance against # future changes - export PYTHONIOENCODING=UTF8 # Install conda - source continuous-integration/travis/install_conda_$TRAVIS_OS_NAME.sh # Install graphviz - source continuous-integration/travis/install_graphviz_$TRAVIS_OS_NAME.sh install: - conda create --yes -n test python=$PYTHON_VERSION - source activate test - conda install --yes pip "pytest<2.6" sphinx cython numpy - pip install coveralls pytest-cov # We cannot install the developer version of setuptools using pip because # pip tries to remove the previous version of setuptools before the # installation is complete, which causes issues. Instead, we just install # setuptools manually. - if [[ $SETUPTOOLS_VERSION == dev ]]; then conda install --yes mercurial mock; fi - if [[ $SETUPTOOLS_VERSION == dev ]]; then hg clone https://bitbucket.org/pypa/setuptools; cd setuptools; python setup.py install; cd ..; fi before_script: # Some of the tests use git commands that require a user to be configured - git config --global user.name "A U Thor" - git config --global user.email "author@example.com" script: - py.test --cov astropy_helpers astropy_helpers after_success: - coveralls wcsaxes-0.6/astropy_helpers/ah_bootstrap.py0000644000077000000240000010650312532571254021247 0ustar tomstaff00000000000000""" This bootstrap module contains code for ensuring that the astropy_helpers package will be importable by the time the setup.py script runs. It also includes some workarounds to ensure that a recent-enough version of setuptools is being used for the installation. This module should be the first thing imported in the setup.py of distributions that make use of the utilities in astropy_helpers. If the distribution ships with its own copy of astropy_helpers, this module will first attempt to import from the shipped copy. However, it will also check PyPI to see if there are any bug-fix releases on top of the current version that may be useful to get past platform-specific bugs that have been fixed. When running setup.py, use the ``--offline`` command-line option to disable the auto-upgrade checks. When this module is imported or otherwise executed it automatically calls a main function that attempts to read the project's setup.cfg file, which it checks for a configuration section called ``[ah_bootstrap]`` the presences of that section, and options therein, determine the next step taken: If it contains an option called ``auto_use`` with a value of ``True``, it will automatically call the main function of this module called `use_astropy_helpers` (see that function's docstring for full details). Otherwise no further action is taken (however, ``ah_bootstrap.use_astropy_helpers`` may be called manually from within the setup.py script). Additional options in the ``[ah_boostrap]`` section of setup.cfg have the same names as the arguments to `use_astropy_helpers`, and can be used to configure the bootstrap script when ``auto_use = True``. See https://github.com/astropy/astropy-helpers for more details, and for the latest version of this module. """ import contextlib import errno import imp import io import locale import os import re import subprocess as sp import sys try: from ConfigParser import ConfigParser, RawConfigParser except ImportError: from configparser import ConfigParser, RawConfigParser if sys.version_info[0] < 3: _str_types = (str, unicode) _text_type = unicode PY3 = False else: _str_types = (str, bytes) _text_type = str PY3 = True # What follows are several import statements meant to deal with install-time # issues with either missing or misbehaving pacakges (including making sure # setuptools itself is installed): # Some pre-setuptools checks to ensure that either distribute or setuptools >= # 0.7 is used (over pre-distribute setuptools) if it is available on the path; # otherwise the latest setuptools will be downloaded and bootstrapped with # ``ez_setup.py``. This used to be included in a separate file called # setuptools_bootstrap.py; but it was combined into ah_bootstrap.py try: import pkg_resources _setuptools_req = pkg_resources.Requirement.parse('setuptools>=0.7') # This may raise a DistributionNotFound in which case no version of # setuptools or distribute is properly installed _setuptools = pkg_resources.get_distribution('setuptools') if _setuptools not in _setuptools_req: # Older version of setuptools; check if we have distribute; again if # this results in DistributionNotFound we want to give up _distribute = pkg_resources.get_distribution('distribute') if _setuptools != _distribute: # It's possible on some pathological systems to have an old version # of setuptools and distribute on sys.path simultaneously; make # sure distribute is the one that's used sys.path.insert(1, _distribute.location) _distribute.activate() imp.reload(pkg_resources) except: # There are several types of exceptions that can occur here; if all else # fails bootstrap and use the bootstrapped version from ez_setup import use_setuptools use_setuptools() # Note: The following import is required as a workaround to # https://github.com/astropy/astropy-helpers/issues/89; if we don't import this # module now, it will get cleaned up after `run_setup` is called, but that will # later cause the TemporaryDirectory class defined in it to stop working when # used later on by setuptools try: import setuptools.py31compat except ImportError: pass # matplotlib can cause problems if it is imported from within a call of # run_setup(), because in some circumstances it will try to write to the user's # home directory, resulting in a SandboxViolation. See # https://github.com/matplotlib/matplotlib/pull/4165 # Making sure matplotlib, if it is available, is imported early in the setup # process can mitigate this (note importing matplotlib.pyplot has the same # issue) try: import matplotlib matplotlib.use('Agg') import matplotlib.pyplot except: # Ignore if this fails for *any* reason* pass # End compatibility imports... # In case it didn't successfully import before the ez_setup checks import pkg_resources from setuptools import Distribution from setuptools.package_index import PackageIndex from setuptools.sandbox import run_setup from distutils import log from distutils.debug import DEBUG # TODO: Maybe enable checking for a specific version of astropy_helpers? DIST_NAME = 'astropy-helpers' PACKAGE_NAME = 'astropy_helpers' # Defaults for other options DOWNLOAD_IF_NEEDED = True INDEX_URL = 'https://pypi.python.org/simple' USE_GIT = True OFFLINE = False AUTO_UPGRADE = True # A list of all the configuration options and their required types CFG_OPTIONS = [ ('auto_use', bool), ('path', str), ('download_if_needed', bool), ('index_url', str), ('use_git', bool), ('offline', bool), ('auto_upgrade', bool) ] class _Bootstrapper(object): """ Bootstrapper implementation. See ``use_astropy_helpers`` for parameter documentation. """ def __init__(self, path=None, index_url=None, use_git=None, offline=None, download_if_needed=None, auto_upgrade=None): if path is None: path = PACKAGE_NAME if not (isinstance(path, _str_types) or path is False): raise TypeError('path must be a string or False') if PY3 and not isinstance(path, _text_type): fs_encoding = sys.getfilesystemencoding() path = path.decode(fs_encoding) # path to unicode self.path = path # Set other option attributes, using defaults where necessary self.index_url = index_url if index_url is not None else INDEX_URL self.offline = offline if offline is not None else OFFLINE # If offline=True, override download and auto-upgrade if self.offline: download_if_needed = False auto_upgrade = False self.download = (download_if_needed if download_if_needed is not None else DOWNLOAD_IF_NEEDED) self.auto_upgrade = (auto_upgrade if auto_upgrade is not None else AUTO_UPGRADE) # If this is a release then the .git directory will not exist so we # should not use git. git_dir_exists = os.path.exists(os.path.join(os.path.dirname(__file__), '.git')) if use_git is None and not git_dir_exists: use_git = False self.use_git = use_git if use_git is not None else USE_GIT # Declared as False by default--later we check if astropy-helpers can be # upgraded from PyPI, but only if not using a source distribution (as in # the case of import from a git submodule) self.is_submodule = False @classmethod def main(cls, argv=None): if argv is None: argv = sys.argv config = cls.parse_config() config.update(cls.parse_command_line(argv)) auto_use = config.pop('auto_use', False) bootstrapper = cls(**config) if auto_use: # Run the bootstrapper, otherwise the setup.py is using the old # use_astropy_helpers() interface, in which case it will run the # bootstrapper manually after reconfiguring it. bootstrapper.run() return bootstrapper @classmethod def parse_config(cls): if not os.path.exists('setup.cfg'): return {} cfg = ConfigParser() try: cfg.read('setup.cfg') except Exception as e: if DEBUG: raise log.error( "Error reading setup.cfg: {0!r}\n{1} will not be " "automatically bootstrapped and package installation may fail." "\n{2}".format(e, PACKAGE_NAME, _err_help_msg)) return {} if not cfg.has_section('ah_bootstrap'): return {} config = {} for option, type_ in CFG_OPTIONS: if not cfg.has_option('ah_bootstrap', option): continue if type_ is bool: value = cfg.getboolean('ah_bootstrap', option) else: value = cfg.get('ah_bootstrap', option) config[option] = value return config @classmethod def parse_command_line(cls, argv=None): if argv is None: argv = sys.argv config = {} # For now we just pop recognized ah_bootstrap options out of the # arg list. This is imperfect; in the unlikely case that a setup.py # custom command or even custom Distribution class defines an argument # of the same name then we will break that. However there's a catch22 # here that we can't just do full argument parsing right here, because # we don't yet know *how* to parse all possible command-line arguments. if '--no-git' in argv: config['use_git'] = False argv.remove('--no-git') if '--offline' in argv: config['offline'] = True argv.remove('--offline') return config def run(self): strategies = ['local_directory', 'local_file', 'index'] dist = None # First, remove any previously imported versions of astropy_helpers; # this is necessary for nested installs where one package's installer # is installing another package via setuptools.sandbox.run_setup, as in # the case of setup_requires for key in list(sys.modules): try: if key == PACKAGE_NAME or key.startswith(PACKAGE_NAME + '.'): del sys.modules[key] except AttributeError: # Sometimes mysterious non-string things can turn up in # sys.modules continue # Check to see if the path is a submodule self.is_submodule = self._check_submodule() for strategy in strategies: method = getattr(self, 'get_{0}_dist'.format(strategy)) dist = method() if dist is not None: break else: raise _AHBootstrapSystemExit( "No source found for the {0!r} package; {0} must be " "available and importable as a prerequisite to building " "or installing this package.".format(PACKAGE_NAME)) # This is a bit hacky, but if astropy_helpers was loaded from a # directory/submodule its Distribution object gets a "precedence" of # "DEVELOP_DIST". However, in other cases it gets a precedence of # "EGG_DIST". However, when activing the distribution it will only be # placed early on sys.path if it is treated as an EGG_DIST, so always # do that dist = dist.clone(precedence=pkg_resources.EGG_DIST) # Otherwise we found a version of astropy-helpers, so we're done # Just active the found distribution on sys.path--if we did a # download this usually happens automatically but it doesn't hurt to # do it again # Note: Adding the dist to the global working set also activates it # (makes it importable on sys.path) by default. try: pkg_resources.working_set.add(dist, replace=True) except TypeError: # Some (much) older versions of setuptools do not have the # replace=True option here. These versions are old enough that all # bets may be off anyways, but it's easy enough to work around just # in case... if dist.key in pkg_resources.working_set.by_key: del pkg_resources.working_set.by_key[dist.key] pkg_resources.working_set.add(dist) @property def config(self): """ A `dict` containing the options this `_Bootstrapper` was configured with. """ return dict((optname, getattr(self, optname)) for optname, _ in CFG_OPTIONS if hasattr(self, optname)) def get_local_directory_dist(self): """ Handle importing a vendored package from a subdirectory of the source distribution. """ if not os.path.isdir(self.path): return log.info('Attempting to import astropy_helpers from {0} {1!r}'.format( 'submodule' if self.is_submodule else 'directory', self.path)) dist = self._directory_import() if dist is None: log.warn( 'The requested path {0!r} for importing {1} does not ' 'exist, or does not contain a copy of the {1} ' 'package.'.format(self.path, PACKAGE_NAME)) elif self.auto_upgrade and not self.is_submodule: # A version of astropy-helpers was found on the available path, but # check to see if a bugfix release is available on PyPI upgrade = self._do_upgrade(dist) if upgrade is not None: dist = upgrade return dist def get_local_file_dist(self): """ Handle importing from a source archive; this also uses setup_requires but points easy_install directly to the source archive. """ if not os.path.isfile(self.path): return log.info('Attempting to unpack and import astropy_helpers from ' '{0!r}'.format(self.path)) try: dist = self._do_download(find_links=[self.path]) except Exception as e: if DEBUG: raise log.warn( 'Failed to import {0} from the specified archive {1!r}: ' '{2}'.format(PACKAGE_NAME, self.path, str(e))) dist = None if dist is not None and self.auto_upgrade: # A version of astropy-helpers was found on the available path, but # check to see if a bugfix release is available on PyPI upgrade = self._do_upgrade(dist) if upgrade is not None: dist = upgrade return dist def get_index_dist(self): if not self.download: log.warn('Downloading {0!r} disabled.'.format(DIST_NAME)) return False log.warn( "Downloading {0!r}; run setup.py with the --offline option to " "force offline installation.".format(DIST_NAME)) try: dist = self._do_download() except Exception as e: if DEBUG: raise log.warn( 'Failed to download and/or install {0!r} from {1!r}:\n' '{2}'.format(DIST_NAME, self.index_url, str(e))) dist = None # No need to run auto-upgrade here since we've already presumably # gotten the most up-to-date version from the package index return dist def _directory_import(self): """ Import astropy_helpers from the given path, which will be added to sys.path. Must return True if the import succeeded, and False otherwise. """ # Return True on success, False on failure but download is allowed, and # otherwise raise SystemExit path = os.path.abspath(self.path) # Use an empty WorkingSet rather than the man # pkg_resources.working_set, since on older versions of setuptools this # will invoke a VersionConflict when trying to install an upgrade ws = pkg_resources.WorkingSet([]) ws.add_entry(path) dist = ws.by_key.get(DIST_NAME) if dist is None: # We didn't find an egg-info/dist-info in the given path, but if a # setup.py exists we can generate it setup_py = os.path.join(path, 'setup.py') if os.path.isfile(setup_py): with _silence(): run_setup(os.path.join(path, 'setup.py'), ['egg_info']) for dist in pkg_resources.find_distributions(path, True): # There should be only one... return dist return dist def _do_download(self, version='', find_links=None): if find_links: allow_hosts = '' index_url = None else: allow_hosts = None index_url = self.index_url # Annoyingly, setuptools will not handle other arguments to # Distribution (such as options) before handling setup_requires, so it # is not straightforward to programmatically augment the arguments which # are passed to easy_install class _Distribution(Distribution): def get_option_dict(self, command_name): opts = Distribution.get_option_dict(self, command_name) if command_name == 'easy_install': if find_links is not None: opts['find_links'] = ('setup script', find_links) if index_url is not None: opts['index_url'] = ('setup script', index_url) if allow_hosts is not None: opts['allow_hosts'] = ('setup script', allow_hosts) return opts if version: req = '{0}=={1}'.format(DIST_NAME, version) else: req = DIST_NAME attrs = {'setup_requires': [req]} try: if DEBUG: _Distribution(attrs=attrs) else: with _silence(): _Distribution(attrs=attrs) # If the setup_requires succeeded it will have added the new dist to # the main working_set return pkg_resources.working_set.by_key.get(DIST_NAME) except Exception as e: if DEBUG: raise msg = 'Error retrieving {0} from {1}:\n{2}' if find_links: source = find_links[0] elif index_url != INDEX_URL: source = index_url else: source = 'PyPI' raise Exception(msg.format(DIST_NAME, source, repr(e))) def _do_upgrade(self, dist): # Build up a requirement for a higher bugfix release but a lower minor # release (so API compatibility is guaranteed) next_version = _next_version(dist.parsed_version) req = pkg_resources.Requirement.parse( '{0}>{1},<{2}'.format(DIST_NAME, dist.version, next_version)) package_index = PackageIndex(index_url=self.index_url) upgrade = package_index.obtain(req) if upgrade is not None: return self._do_download(version=upgrade.version) def _check_submodule(self): """ Check if the given path is a git submodule. See the docstrings for ``_check_submodule_using_git`` and ``_check_submodule_no_git`` for further details. """ if (self.path is None or (os.path.exists(self.path) and not os.path.isdir(self.path))): return False if self.use_git: return self._check_submodule_using_git() else: return self._check_submodule_no_git() def _check_submodule_using_git(self): """ Check if the given path is a git submodule. If so, attempt to initialize and/or update the submodule if needed. This function makes calls to the ``git`` command in subprocesses. The ``_check_submodule_no_git`` option uses pure Python to check if the given path looks like a git submodule, but it cannot perform updates. """ cmd = ['git', 'submodule', 'status', '--', self.path] try: log.info('Running `{0}`; use the --no-git option to disable git ' 'commands'.format(' '.join(cmd))) returncode, stdout, stderr = run_cmd(cmd) except _CommandNotFound: # The git command simply wasn't found; this is most likely the # case on user systems that don't have git and are simply # trying to install the package from PyPI or a source # distribution. Silently ignore this case and simply don't try # to use submodules return False stderr = stderr.strip() if returncode != 0 and stderr: # Unfortunately the return code alone cannot be relied on, as # earlier versions of git returned 0 even if the requested submodule # does not exist # This is a warning that occurs in perl (from running git submodule) # which only occurs with a malformatted locale setting which can # happen sometimes on OSX. See again # https://github.com/astropy/astropy/issues/2749 perl_warning = ('perl: warning: Falling back to the standard locale ' '("C").') if not stderr.strip().endswith(perl_warning): # Some other unknown error condition occurred log.warn('git submodule command failed ' 'unexpectedly:\n{0}'.format(stderr)) return False # Output of `git submodule status` is as follows: # # 1: Status indicator: '-' for submodule is uninitialized, '+' if # submodule is initialized but is not at the commit currently indicated # in .gitmodules (and thus needs to be updated), or 'U' if the # submodule is in an unstable state (i.e. has merge conflicts) # # 2. SHA-1 hash of the current commit of the submodule (we don't really # need this information but it's useful for checking that the output is # correct) # # 3. The output of `git describe` for the submodule's current commit # hash (this includes for example what branches the commit is on) but # only if the submodule is initialized. We ignore this information for # now _git_submodule_status_re = re.compile( '^(?P[+-U ])(?P[0-9a-f]{40}) ' '(?P\S+)( .*)?$') # The stdout should only contain one line--the status of the # requested submodule m = _git_submodule_status_re.match(stdout) if m: # Yes, the path *is* a git submodule self._update_submodule(m.group('submodule'), m.group('status')) return True else: log.warn( 'Unexpected output from `git submodule status`:\n{0}\n' 'Will attempt import from {1!r} regardless.'.format( stdout, self.path)) return False def _check_submodule_no_git(self): """ Like ``_check_submodule_using_git``, but simply parses the .gitmodules file to determine if the supplied path is a git submodule, and does not exec any subprocesses. This can only determine if a path is a submodule--it does not perform updates, etc. This function may need to be updated if the format of the .gitmodules file is changed between git versions. """ gitmodules_path = os.path.abspath('.gitmodules') if not os.path.isfile(gitmodules_path): return False # This is a minimal reader for gitconfig-style files. It handles a few of # the quirks that make gitconfig files incompatible with ConfigParser-style # files, but does not support the full gitconfig syntax (just enough # needed to read a .gitmodules file). gitmodules_fileobj = io.StringIO() # Must use io.open for cross-Python-compatible behavior wrt unicode with io.open(gitmodules_path) as f: for line in f: # gitconfig files are more flexible with leading whitespace; just # go ahead and remove it line = line.lstrip() # comments can start with either # or ; if line and line[0] in (':', ';'): continue gitmodules_fileobj.write(line) gitmodules_fileobj.seek(0) cfg = RawConfigParser() try: cfg.readfp(gitmodules_fileobj) except Exception as exc: log.warn('Malformatted .gitmodules file: {0}\n' '{1} cannot be assumed to be a git submodule.'.format( exc, self.path)) return False for section in cfg.sections(): if not cfg.has_option(section, 'path'): continue submodule_path = cfg.get(section, 'path').rstrip(os.sep) if submodule_path == self.path.rstrip(os.sep): return True return False def _update_submodule(self, submodule, status): if status == ' ': # The submodule is up to date; no action necessary return elif status == '-': if self.offline: raise _AHBootstrapSystemExit( "Cannot initialize the {0} submodule in --offline mode; " "this requires being able to clone the submodule from an " "online repository.".format(submodule)) cmd = ['update', '--init'] action = 'Initializing' elif status == '+': cmd = ['update'] action = 'Updating' if self.offline: cmd.append('--no-fetch') elif status == 'U': raise _AHBoostrapSystemExit( 'Error: Submodule {0} contains unresolved merge conflicts. ' 'Please complete or abandon any changes in the submodule so that ' 'it is in a usable state, then try again.'.format(submodule)) else: log.warn('Unknown status {0!r} for git submodule {1!r}. Will ' 'attempt to use the submodule as-is, but try to ensure ' 'that the submodule is in a clean state and contains no ' 'conflicts or errors.\n{2}'.format(status, submodule, _err_help_msg)) return err_msg = None cmd = ['git', 'submodule'] + cmd + ['--', submodule] log.warn('{0} {1} submodule with: `{2}`'.format( action, submodule, ' '.join(cmd))) try: log.info('Running `{0}`; use the --no-git option to disable git ' 'commands'.format(' '.join(cmd))) returncode, stdout, stderr = run_cmd(cmd) except OSError as e: err_msg = str(e) else: if returncode != 0: err_msg = stderr if err_msg is not None: log.warn('An unexpected error occurred updating the git submodule ' '{0!r}:\n{1}\n{2}'.format(submodule, err_msg, _err_help_msg)) class _CommandNotFound(OSError): """ An exception raised when a command run with run_cmd is not found on the system. """ def run_cmd(cmd): """ Run a command in a subprocess, given as a list of command-line arguments. Returns a ``(returncode, stdout, stderr)`` tuple. """ try: p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE) # XXX: May block if either stdout or stderr fill their buffers; # however for the commands this is currently used for that is # unlikely (they should have very brief output) stdout, stderr = p.communicate() except OSError as e: if DEBUG: raise if e.errno == errno.ENOENT: msg = 'Command not found: `{0}`'.format(' '.join(cmd)) raise _CommandNotFound(msg, cmd) else: raise _AHBoostrapSystemExit( 'An unexpected error occurred when running the ' '`{0}` command:\n{1}'.format(' '.join(cmd), str(e))) # Can fail of the default locale is not configured properly. See # https://github.com/astropy/astropy/issues/2749. For the purposes under # consideration 'latin1' is an acceptable fallback. try: stdio_encoding = locale.getdefaultlocale()[1] or 'latin1' except ValueError: # Due to an OSX oddity locale.getdefaultlocale() can also crash # depending on the user's locale/language settings. See: # http://bugs.python.org/issue18378 stdio_encoding = 'latin1' # Unlikely to fail at this point but even then let's be flexible if not isinstance(stdout, _text_type): stdout = stdout.decode(stdio_encoding, 'replace') if not isinstance(stderr, _text_type): stderr = stderr.decode(stdio_encoding, 'replace') return (p.returncode, stdout, stderr) def _next_version(version): """ Given a parsed version from pkg_resources.parse_version, returns a new version string with the next minor version. Examples ======== >>> _next_version(pkg_resources.parse_version('1.2.3')) '1.3.0' """ if hasattr(version, 'base_version'): # New version parsing from setuptools >= 8.0 if version.base_version: parts = version.base_version.split('.') else: parts = [] else: parts = [] for part in version: if part.startswith('*'): break parts.append(part) parts = [int(p) for p in parts] if len(parts) < 3: parts += [0] * (3 - len(parts)) major, minor, micro = parts[:3] return '{0}.{1}.{2}'.format(major, minor + 1, 0) class _DummyFile(object): """A noop writeable object.""" errors = '' # Required for Python 3.x encoding = 'utf-8' def write(self, s): pass def flush(self): pass @contextlib.contextmanager def _silence(): """A context manager that silences sys.stdout and sys.stderr.""" old_stdout = sys.stdout old_stderr = sys.stderr sys.stdout = _DummyFile() sys.stderr = _DummyFile() exception_occurred = False try: yield except: exception_occurred = True # Go ahead and clean up so that exception handling can work normally sys.stdout = old_stdout sys.stderr = old_stderr raise if not exception_occurred: sys.stdout = old_stdout sys.stderr = old_stderr _err_help_msg = """ If the problem persists consider installing astropy_helpers manually using pip (`pip install astropy_helpers`) or by manually downloading the source archive, extracting it, and installing by running `python setup.py install` from the root of the extracted source code. """ class _AHBootstrapSystemExit(SystemExit): def __init__(self, *args): if not args: msg = 'An unknown problem occurred bootstrapping astropy_helpers.' else: msg = args[0] msg += '\n' + _err_help_msg super(_AHBootstrapSystemExit, self).__init__(msg, *args[1:]) if sys.version_info[:2] < (2, 7): # In Python 2.6 the distutils log does not log warnings, errors, etc. to # stderr so we have to wrap it to ensure consistency at least in this # module import distutils class log(object): def __getattr__(self, attr): return getattr(distutils.log, attr) def warn(self, msg, *args): self._log_to_stderr(distutils.log.WARN, msg, *args) def error(self, msg): self._log_to_stderr(distutils.log.ERROR, msg, *args) def fatal(self, msg): self._log_to_stderr(distutils.log.FATAL, msg, *args) def log(self, level, msg, *args): if level in (distutils.log.WARN, distutils.log.ERROR, distutils.log.FATAL): self._log_to_stderr(level, msg, *args) else: distutils.log.log(level, msg, *args) def _log_to_stderr(self, level, msg, *args): # This is the only truly 'public' way to get the current threshold # of the log current_threshold = distutils.log.set_threshold(distutils.log.WARN) distutils.log.set_threshold(current_threshold) if level >= current_threshold: if args: msg = msg % args sys.stderr.write('%s\n' % msg) sys.stderr.flush() log = log() BOOTSTRAPPER = _Bootstrapper.main() def use_astropy_helpers(**kwargs): """ Ensure that the `astropy_helpers` module is available and is importable. This supports automatic submodule initialization if astropy_helpers is included in a project as a git submodule, or will download it from PyPI if necessary. Parameters ---------- path : str or None, optional A filesystem path relative to the root of the project's source code that should be added to `sys.path` so that `astropy_helpers` can be imported from that path. If the path is a git submodule it will automatically be initialized and/or updated. The path may also be to a ``.tar.gz`` archive of the astropy_helpers source distribution. In this case the archive is automatically unpacked and made temporarily available on `sys.path` as a ``.egg`` archive. If `None` skip straight to downloading. download_if_needed : bool, optional If the provided filesystem path is not found an attempt will be made to download astropy_helpers from PyPI. It will then be made temporarily available on `sys.path` as a ``.egg`` archive (using the ``setup_requires`` feature of setuptools. If the ``--offline`` option is given at the command line the value of this argument is overridden to `False`. index_url : str, optional If provided, use a different URL for the Python package index than the main PyPI server. use_git : bool, optional If `False` no git commands will be used--this effectively disables support for git submodules. If the ``--no-git`` option is given at the command line the value of this argument is overridden to `False`. auto_upgrade : bool, optional By default, when installing a package from a non-development source distribution ah_boostrap will try to automatically check for patch releases to astropy-helpers on PyPI and use the patched version over any bundled versions. Setting this to `False` will disable that functionality. If the ``--offline`` option is given at the command line the value of this argument is overridden to `False`. offline : bool, optional If `False` disable all actions that require an internet connection, including downloading packages from the package index and fetching updates to any git submodule. Defaults to `True`. """ global BOOTSTRAPPER config = BOOTSTRAPPER.config config.update(**kwargs) # Create a new bootstrapper with the updated configuration and run it BOOTSTRAPPER = _Bootstrapper(**config) BOOTSTRAPPER.run() wcsaxes-0.6/astropy_helpers/appveyor.yml0000644000077000000240000000301612532571254020573 0ustar tomstaff00000000000000# AppVeyor.com is a Continuous Integration service to build and run tests under # Windows environment: global: PYTHON: "C:\\conda" MINICONDA_VERSION: "3.5.5" CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\continuous-integration\\appveyor\\windows_sdk.cmd" PYTHON_ARCH: "64" # needs to be set for CMD_IN_ENV to succeed. If a mix # of 32 bit and 64 bit builds are needed, move this # to the matrix section. matrix: - PYTHON_VERSION: "2.6" - PYTHON_VERSION: "2.7" - PYTHON_VERSION: "3.4" platform: -x64 install: # Install miniconda using a powershell script. - "powershell continuous-integration/appveyor/install-miniconda.ps1" - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" # Install the build and runtime dependencies of the project. - "conda update --yes conda" # Create a conda environment - "conda create -q --yes -n test python=%PYTHON_VERSION%" - "activate test" # Check that we have the expected version of Python - "python --version" # Install specified version of numpy and dependencies - "conda install -q --yes numpy Cython sphinx pytest" # Some of the tests use git commands that require a user to be configured - git config --global user.name "A U Thor" - git config --global user.email "author@example.com" # Install graphviz - cinst graphviz.portable # Not a .NET project, we build SunPy in the install step instead build: false test_script: - "%CMD_IN_ENV% py.test" wcsaxes-0.6/astropy_helpers/astropy_helpers/0000755000077000000240000000000012553237435021431 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/__init__.py0000644000077000000240000000250212532571254023536 0ustar tomstaff00000000000000try: from .version import version as __version__ from .version import githash as __githash__ except ImportError: __version__ = '' __githash__ = '' # If we've made it as far as importing astropy_helpers, we don't need # ah_bootstrap in sys.modules anymore. Getting rid of it is actually necessary # if the package we're installing has a setup_requires of another package that # uses astropy_helpers (and possibly a different version at that) # See https://github.com/astropy/astropy/issues/3541 import sys if 'ah_bootstrap' in sys.modules: del sys.modules['ah_bootstrap'] # Note, this is repeated from ah_bootstrap.py, but is here too in case this # astropy-helpers was upgraded to from an older version that did not have this # check in its ah_bootstrap. # matplotlib can cause problems if it is imported from within a call of # run_setup(), because in some circumstances it will try to write to the user's # home directory, resulting in a SandboxViolation. See # https://github.com/matplotlib/matplotlib/pull/4165 # Making sure matplotlib, if it is available, is imported early in the setup # process can mitigate this (note importing matplotlib.pyplot has the same # issue) try: import matplotlib matplotlib.use('Agg') import matplotlib.pyplot except: # Ignore if this fails for *any* reason* pass wcsaxes-0.6/astropy_helpers/astropy_helpers/commands/0000755000077000000240000000000012553237435023232 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/commands/__init__.py0000644000077000000240000000000012532571254025326 0ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/commands/build_ext.py0000644000077000000240000001623312532571254025565 0ustar tomstaff00000000000000import errno import os import shutil from distutils.core import Extension from setuptools.command.build_ext import build_ext as SetuptoolsBuildExt from ..utils import get_numpy_include_path, invalidate_caches from ..version_helpers import get_pkg_version_module def should_build_with_cython(package, release=None): """Returns the previously used Cython version (or 'unknown' if not previously built) if Cython should be used to build extension modules from pyx files. If the ``release`` parameter is not specified an attempt is made to determine the release flag from `astropy.version`. """ from ..setup_helpers import _module_state try: version_module = __import__(package + '.cython_version', fromlist=['release', 'cython_version']) except ImportError: version_module = None if release is None and version_module is not None: try: release = version_module.release except AttributeError: pass try: cython_version = version_module.cython_version except AttributeError: cython_version = 'unknown' # Only build with Cython if, of course, Cython is installed, we're in a # development version (i.e. not release) or the Cython-generated source # files haven't been created yet (cython_version == 'unknown'). The latter # case can happen even when release is True if checking out a release tag # from the repository if (_module_state['have_cython'] and (not release or cython_version == 'unknown')): return cython_version else: return False # TODO: I think this can be reworked without having to create the class # programmatically. def generate_build_ext_command(packagename, release): """ Creates a custom 'build_ext' command that allows for manipulating some of the C extension options at build time. We use a function to build the class since the base class for build_ext may be different depending on certain build-time parameters (for example, we may use Cython's build_ext instead of the default version in distutils). Uses the default distutils.command.build_ext by default. """ uses_cython = should_build_with_cython(packagename, release) if uses_cython: from Cython.Distutils import build_ext as basecls else: basecls = SetuptoolsBuildExt attrs = dict(basecls.__dict__) orig_run = getattr(basecls, 'run', None) orig_finalize = getattr(basecls, 'finalize_options', None) def finalize_options(self): # Add a copy of the _compiler.so module as well, but only if there are # in fact C modules to compile (otherwise there's no reason to include # a record of the compiler used) # Note, self.extensions may not be set yet, but # self.distribution.ext_modules is where any extension modules passed # to setup() can be found extensions = self.distribution.ext_modules if extensions: src_path = os.path.relpath( os.path.join(os.path.dirname(__file__), 'src')) shutil.copy2(os.path.join(src_path, 'compiler.c'), os.path.join(self.package_name, '_compiler.c')) ext = Extension(self.package_name + '._compiler', [os.path.join(self.package_name, '_compiler.c')]) extensions.insert(0, ext) if orig_finalize is not None: orig_finalize(self) # Generate if self.uses_cython: try: from Cython import __version__ as cython_version except ImportError: # This shouldn't happen if we made it this far cython_version = None if (cython_version is not None and cython_version != self.uses_cython): self.force_rebuild = True # Update the used cython version self.uses_cython = cython_version # Regardless of the value of the '--force' option, force a rebuild if # the debug flag changed from the last build if self.force_rebuild: self.force = True def run(self): # For extensions that require 'numpy' in their include dirs, replace # 'numpy' with the actual paths np_include = get_numpy_include_path() for extension in self.extensions: if 'numpy' in extension.include_dirs: idx = extension.include_dirs.index('numpy') extension.include_dirs.insert(idx, np_include) extension.include_dirs.remove('numpy') # Replace .pyx with C-equivalents, unless c files are missing for jdx, src in enumerate(extension.sources): if src.endswith('.pyx'): pyxfn = src cfn = src[:-4] + '.c' elif src.endswith('.c'): pyxfn = src[:-2] + '.pyx' cfn = src if not os.path.isfile(pyxfn): continue if self.uses_cython: extension.sources[jdx] = pyxfn else: if os.path.isfile(cfn): extension.sources[jdx] = cfn else: msg = ( 'Could not find C file {0} for Cython file {1} ' 'when building extension {2}. Cython must be ' 'installed to build from a git checkout.'.format( cfn, pyxfn, extension.name)) raise IOError(errno.ENOENT, msg, cfn) if orig_run is not None: # This should always be the case for a correctly implemented # distutils command. orig_run(self) # Update cython_version.py if building with Cython try: cython_version = get_pkg_version_module( packagename, fromlist=['cython_version'])[0] except (AttributeError, ImportError): cython_version = 'unknown' if self.uses_cython and self.uses_cython != cython_version: package_dir = os.path.relpath(packagename) cython_py = os.path.join(package_dir, 'cython_version.py') with open(cython_py, 'w') as f: f.write('# Generated file; do not modify\n') f.write('cython_version = {0!r}\n'.format(self.uses_cython)) if os.path.isdir(self.build_lib): # The build/lib directory may not exist if the build_py command # was not previously run, which may sometimes be the case self.copy_file(cython_py, os.path.join(self.build_lib, cython_py), preserve_mode=False) invalidate_caches() attrs['run'] = run attrs['finalize_options'] = finalize_options attrs['force_rebuild'] = False attrs['uses_cython'] = uses_cython attrs['package_name'] = packagename attrs['user_options'] = basecls.user_options[:] attrs['boolean_options'] = basecls.boolean_options[:] return type('build_ext', (basecls, object), attrs) wcsaxes-0.6/astropy_helpers/astropy_helpers/commands/build_py.py0000644000077000000240000000265612532571254025421 0ustar tomstaff00000000000000from setuptools.command.build_py import build_py as SetuptoolsBuildPy from ..utils import _get_platlib_dir class AstropyBuildPy(SetuptoolsBuildPy): user_options = SetuptoolsBuildPy.user_options[:] boolean_options = SetuptoolsBuildPy.boolean_options[:] def finalize_options(self): # Update build_lib settings from the build command to always put # build files in platform-specific subdirectories of build/, even # for projects with only pure-Python source (this is desirable # specifically for support of multiple Python version). build_cmd = self.get_finalized_command('build') platlib_dir = _get_platlib_dir(build_cmd) build_cmd.build_purelib = platlib_dir build_cmd.build_lib = platlib_dir self.build_lib = platlib_dir SetuptoolsBuildPy.finalize_options(self) def run_2to3(self, files, doctests=False): # Filter the files to exclude things that shouldn't be 2to3'd skip_2to3 = self.distribution.skip_2to3 filtered_files = [] for filename in files: for package in skip_2to3: if filename[len(self.build_lib) + 1:].startswith(package): break else: filtered_files.append(filename) SetuptoolsBuildPy.run_2to3(self, filtered_files, doctests) def run(self): # first run the normal build_py SetuptoolsBuildPy.run(self) wcsaxes-0.6/astropy_helpers/astropy_helpers/commands/build_sphinx.py0000644000077000000240000002214712532571254026277 0ustar tomstaff00000000000000import inspect import os import pkgutil import re import shutil import subprocess import sys import textwrap from distutils import log from distutils.cmd import DistutilsOptionError import sphinx from sphinx.setup_command import BuildDoc as SphinxBuildDoc from ..utils import minversion PY3 = sys.version_info[0] >= 3 class AstropyBuildSphinx(SphinxBuildDoc): """ A version of the ``build_sphinx`` command that uses the version of Astropy that is built by the setup ``build`` command, rather than whatever is installed on the system. To build docs against the installed version, run ``make html`` in the ``astropy/docs`` directory. This also automatically creates the docs/_static directories--this is needed because GitHub won't create the _static dir because it has no tracked files. """ description = 'Build Sphinx documentation for Astropy environment' user_options = SphinxBuildDoc.user_options[:] user_options.append(('warnings-returncode', 'w', 'Parses the sphinx output and sets the return code to 1 if there ' 'are any warnings. Note that this will cause the sphinx log to ' 'only update when it completes, rather than continuously as is ' 'normally the case.')) user_options.append(('clean-docs', 'l', 'Completely clean previous builds, including ' 'automodapi-generated files before building new ones')) user_options.append(('no-intersphinx', 'n', 'Skip intersphinx, even if conf.py says to use it')) user_options.append(('open-docs-in-browser', 'o', 'Open the docs in a browser (using the webbrowser module) if the ' 'build finishes successfully.')) boolean_options = SphinxBuildDoc.boolean_options[:] boolean_options.append('warnings-returncode') boolean_options.append('clean-docs') boolean_options.append('no-intersphinx') boolean_options.append('open-docs-in-browser') _self_iden_rex = re.compile(r"self\.([^\d\W][\w]+)", re.UNICODE) def initialize_options(self): SphinxBuildDoc.initialize_options(self) self.clean_docs = False self.no_intersphinx = False self.open_docs_in_browser = False self.warnings_returncode = False def finalize_options(self): #Clear out previous sphinx builds, if requested if self.clean_docs: dirstorm = [os.path.join(self.source_dir, 'api')] if self.build_dir is None: dirstorm.append('docs/_build') else: dirstorm.append(self.build_dir) for d in dirstorm: if os.path.isdir(d): log.info('Cleaning directory ' + d) shutil.rmtree(d) else: log.info('Not cleaning directory ' + d + ' because ' 'not present or not a directory') SphinxBuildDoc.finalize_options(self) def run(self): # TODO: Break this method up into a few more subroutines and # document them better import webbrowser if PY3: from urllib.request import pathname2url else: from urllib import pathname2url # This is used at the very end of `run` to decide if sys.exit should # be called. If it's None, it won't be. retcode = None # If possible, create the _static dir if self.build_dir is not None: # the _static dir should be in the same place as the _build dir # for Astropy basedir, subdir = os.path.split(self.build_dir) if subdir == '': # the path has a trailing /... basedir, subdir = os.path.split(basedir) staticdir = os.path.join(basedir, '_static') if os.path.isfile(staticdir): raise DistutilsOptionError( 'Attempted to build_sphinx in a location where' + staticdir + 'is a file. Must be a directory.') self.mkpath(staticdir) # Now make sure Astropy is built and determine where it was built build_cmd = self.reinitialize_command('build') build_cmd.inplace = 0 self.run_command('build') build_cmd = self.get_finalized_command('build') build_cmd_path = os.path.abspath(build_cmd.build_lib) ah_importer = pkgutil.get_importer('astropy_helpers') ah_path = os.path.abspath(ah_importer.path) # Now generate the source for and spawn a new process that runs the # command. This is needed to get the correct imports for the built # version runlines, runlineno = inspect.getsourcelines(SphinxBuildDoc.run) subproccode = textwrap.dedent(""" from sphinx.setup_command import * os.chdir({srcdir!r}) sys.path.insert(0, {build_cmd_path!r}) sys.path.insert(0, {ah_path!r}) """).format(build_cmd_path=build_cmd_path, ah_path=ah_path, srcdir=self.source_dir) # runlines[1:] removes 'def run(self)' on the first line subproccode += textwrap.dedent(''.join(runlines[1:])) # All "self.foo" in the subprocess code needs to be replaced by the # values taken from the current self in *this* process subproccode = self._self_iden_rex.split(subproccode) for i in range(1, len(subproccode), 2): iden = subproccode[i] val = getattr(self, iden) if iden.endswith('_dir'): # Directories should be absolute, because the `chdir` call # in the new process moves to a different directory subproccode[i] = repr(os.path.abspath(val)) else: subproccode[i] = repr(val) subproccode = ''.join(subproccode) # This is a quick gross hack, but it ensures that the code grabbed from # SphinxBuildDoc.run will work in Python 2 if it uses the print # function if minversion(sphinx, '1.3'): subproccode = 'from __future__ import print_function' + subproccode if self.no_intersphinx: # the confoverrides variable in sphinx.setup_command.BuildDoc can # be used to override the conf.py ... but this could well break # if future versions of sphinx change the internals of BuildDoc, # so remain vigilant! subproccode = subproccode.replace('confoverrides = {}', 'confoverrides = {\'intersphinx_mapping\':{}}') log.debug('Starting subprocess of {0} with python code:\n{1}\n' '[CODE END])'.format(sys.executable, subproccode)) # To return the number of warnings, we need to capture stdout. This # prevents a continuous updating at the terminal, but there's no # apparent way around this. if self.warnings_returncode: proc = subprocess.Popen([sys.executable], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdo, stde = proc.communicate(subproccode.encode('utf-8')) print(stdo) stdolines = stdo.splitlines() if b'build succeeded.' in stdolines: retcode = 0 else: retcode = 1 if retcode != 0: if os.environ.get('TRAVIS', None) == 'true': #this means we are in the travis build, so customize #the message appropriately. msg = ('The build_sphinx travis build FAILED ' 'because sphinx issued documentation ' 'warnings (scroll up to see the warnings).') else: # standard failure message msg = ('build_sphinx returning a non-zero exit ' 'code because sphinx issued documentation ' 'warnings.') log.warn(msg) else: proc = subprocess.Popen([sys.executable], stdin=subprocess.PIPE) proc.communicate(subproccode.encode('utf-8')) if proc.returncode == 0: if self.open_docs_in_browser: if self.builder == 'html': absdir = os.path.abspath(self.builder_target_dir) index_path = os.path.join(absdir, 'index.html') fileurl = 'file://' + pathname2url(index_path) webbrowser.open(fileurl) else: log.warn('open-docs-in-browser option was given, but ' 'the builder is not html! Ignoring.') else: log.warn('Sphinx Documentation subprocess failed with return ' 'code ' + str(proc.returncode)) if retcode is not None: # this is potentially dangerous in that there might be something # after the call to `setup` in `setup.py`, and exiting here will # prevent that from running. But there's no other apparent way # to signal what the return code should be. sys.exit(retcode) wcsaxes-0.6/astropy_helpers/astropy_helpers/commands/install.py0000644000077000000240000000074612532571254025256 0ustar tomstaff00000000000000from setuptools.command.install import install as SetuptoolsInstall from ..utils import _get_platlib_dir class AstropyInstall(SetuptoolsInstall): user_options = SetuptoolsInstall.user_options[:] boolean_options = SetuptoolsInstall.boolean_options[:] def finalize_options(self): build_cmd = self.get_finalized_command('build') platlib_dir = _get_platlib_dir(build_cmd) self.build_lib = platlib_dir SetuptoolsInstall.finalize_options(self) wcsaxes-0.6/astropy_helpers/astropy_helpers/commands/install_lib.py0000644000077000000240000000100012532571254026064 0ustar tomstaff00000000000000from setuptools.command.install_lib import install_lib as SetuptoolsInstallLib from ..utils import _get_platlib_dir class AstropyInstallLib(SetuptoolsInstallLib): user_options = SetuptoolsInstallLib.user_options[:] boolean_options = SetuptoolsInstallLib.boolean_options[:] def finalize_options(self): build_cmd = self.get_finalized_command('build') platlib_dir = _get_platlib_dir(build_cmd) self.build_dir = platlib_dir SetuptoolsInstallLib.finalize_options(self) wcsaxes-0.6/astropy_helpers/astropy_helpers/commands/register.py0000644000077000000240000000454712532571254025437 0ustar tomstaff00000000000000from setuptools.command.register import register as SetuptoolsRegister class AstropyRegister(SetuptoolsRegister): """Extends the built in 'register' command to support a ``--hidden`` option to make the registered version hidden on PyPI by default. The result of this is that when a version is registered as "hidden" it can still be downloaded from PyPI, but it does not show up in the list of actively supported versions under http://pypi.python.org/pypi/astropy, and is not set as the most recent version. Although this can always be set through the web interface it may be more convenient to be able to specify via the 'register' command. Hidden may also be considered a safer default when running the 'register' command, though this command uses distutils' normal behavior if the ``--hidden`` option is omitted. """ user_options = SetuptoolsRegister.user_options + [ ('hidden', None, 'mark this release as hidden on PyPI by default') ] boolean_options = SetuptoolsRegister.boolean_options + ['hidden'] def initialize_options(self): SetuptoolsRegister.initialize_options(self) self.hidden = False def build_post_data(self, action): data = SetuptoolsRegister.build_post_data(self, action) if action == 'submit' and self.hidden: data['_pypi_hidden'] = '1' return data def _set_config(self): # The original register command is buggy--if you use .pypirc with a # server-login section *at all* the repository you specify with the -r # option will be overwritten with either the repository in .pypirc or # with the default, # If you do not have a .pypirc using the -r option will just crash. # Way to go distutils # If we don't set self.repository back to a default value _set_config # can crash if there was a user-supplied value for this option; don't # worry, we'll get the real value back afterwards self.repository = 'pypi' SetuptoolsRegister._set_config(self) options = self.distribution.get_option_dict('register') if 'repository' in options: source, value = options['repository'] # Really anything that came from setup.cfg or the command line # should override whatever was in .pypirc self.repository = value wcsaxes-0.6/astropy_helpers/astropy_helpers/commands/setup_package.py0000644000077000000240000000016712532571254026420 0ustar tomstaff00000000000000from os.path import join def get_package_data(): return {'astropy_helpers.commands': [join('src', 'compiler.c')]} wcsaxes-0.6/astropy_helpers/astropy_helpers/commands/src/0000755000077000000240000000000012553237435024021 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/commands/src/compiler.c0000644000077000000240000000573112532571254026002 0ustar tomstaff00000000000000#include /*************************************************************************** * Macros for determining the compiler version. * * These are borrowed from boost, and majorly abridged to include only * the compilers we care about. ***************************************************************************/ #ifndef PY3K #if PY_MAJOR_VERSION >= 3 #define PY3K 1 #else #define PY3K 0 #endif #endif #define STRINGIZE(X) DO_STRINGIZE(X) #define DO_STRINGIZE(X) #X #if defined __clang__ /* Clang C++ emulates GCC, so it has to appear early. */ # define COMPILER "Clang version " __clang_version__ #elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) /* Intel */ # if defined(__INTEL_COMPILER) # define INTEL_VERSION __INTEL_COMPILER # elif defined(__ICL) # define INTEL_VERSION __ICL # elif defined(__ICC) # define INTEL_VERSION __ICC # elif defined(__ECC) # define INTEL_VERSION __ECC # endif # define COMPILER "Intel C compiler version " STRINGIZE(INTEL_VERSION) #elif defined(__GNUC__) /* gcc */ # define COMPILER "GCC version " __VERSION__ #elif defined(__SUNPRO_CC) /* Sun Workshop Compiler */ # define COMPILER "Sun compiler version " STRINGIZE(__SUNPRO_CC) #elif defined(_MSC_VER) /* Microsoft Visual C/C++ Must be last since other compilers define _MSC_VER for compatibility as well */ # if _MSC_VER < 1200 # define COMPILER_VERSION 5.0 # elif _MSC_VER < 1300 # define COMPILER_VERSION 6.0 # elif _MSC_VER == 1300 # define COMPILER_VERSION 7.0 # elif _MSC_VER == 1310 # define COMPILER_VERSION 7.1 # elif _MSC_VER == 1400 # define COMPILER_VERSION 8.0 # elif _MSC_VER == 1500 # define COMPILER_VERSION 9.0 # elif _MSC_VER == 1600 # define COMPILER_VERSION 10.0 # else # define COMPILER_VERSION _MSC_VER # endif # define COMPILER "Microsoft Visual C++ version " STRINGIZE(COMPILER_VERSION) #else /* Fallback */ # define COMPILER "Unknown compiler" #endif /*************************************************************************** * Module-level ***************************************************************************/ struct module_state { /* The Sun compiler can't handle empty structs */ #if defined(__SUNPRO_C) || defined(_MSC_VER) int _dummy; #endif }; #if PY3K static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "_compiler", NULL, sizeof(struct module_state), NULL, NULL, NULL, NULL, NULL }; #define INITERROR return NULL PyMODINIT_FUNC PyInit__compiler(void) #else #define INITERROR return PyMODINIT_FUNC init_compiler(void) #endif { PyObject* m; #if PY3K m = PyModule_Create(&moduledef); #else m = Py_InitModule3("_compiler", NULL, NULL); #endif if (m == NULL) INITERROR; PyModule_AddStringConstant(m, "compiler", COMPILER); #if PY3K return m; #endif } wcsaxes-0.6/astropy_helpers/astropy_helpers/compat/0000755000077000000240000000000012553237435022714 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/compat/__init__.py0000644000077000000240000000056012346274067025030 0ustar tomstaff00000000000000def _fix_user_options(options): """ This is for Python 2.x and 3.x compatibility. distutils expects Command options to all be byte strings on Python 2 and Unicode strings on Python 3. """ def to_str_or_none(x): if x is None: return None return str(x) return [tuple(to_str_or_none(x) for x in y) for y in options] wcsaxes-0.6/astropy_helpers/astropy_helpers/compat/_subprocess_py2/0000755000077000000240000000000012553237435026035 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/compat/_subprocess_py2/__init__.py0000644000077000000240000000243212346274067030151 0ustar tomstaff00000000000000from __future__ import absolute_import from subprocess import * def check_output(*popenargs, **kwargs): r"""Run command with arguments and return its output as a byte string. If the exit code was non-zero it raises a CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute and output in the output attribute. The arguments are the same as for the Popen constructor. Example:: >>> check_output(["ls", "-l", "/dev/null"]) 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' The stdout argument is not allowed as it is used internally. To capture standard error in the result, use stderr=STDOUT.:: >>> check_output(["/bin/sh", "-c", ... "ls -l non_existent_file ; exit 0"], ... stderr=STDOUT) 'ls: non_existent_file: No such file or directory\n' """ if 'stdout' in kwargs: raise ValueError('stdout argument not allowed, it will be overridden.') process = Popen(stdout=PIPE, *popenargs, **kwargs) output, unused_err = process.communicate() retcode = process.poll() if retcode: cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] raise CalledProcessError(retcode, cmd) return output wcsaxes-0.6/astropy_helpers/astropy_helpers/compat/subprocess.py0000644000077000000240000000105012346274067025454 0ustar tomstaff00000000000000""" A replacement wrapper around the subprocess module that adds check_output (which was only added to Python in 2.7. Instead of importing subprocess, other modules should use this as follows:: from astropy.utils.compat import subprocess This module is safe to import from anywhere within astropy. """ from __future__ import absolute_import, print_function import subprocess # python2.7 and later provide a check_output method if not hasattr(subprocess, 'check_output'): from ._subprocess_py2 import check_output from subprocess import * wcsaxes-0.6/astropy_helpers/astropy_helpers/distutils_helpers.py0000644000077000000240000001735512532571254025561 0ustar tomstaff00000000000000""" This module contains various utilities for introspecting the distutils module and the setup process. Some of these utilities require the `astropy_helpers.setup_helpers.register_commands` function to be called first, as it will affect introspection of setuptools command-line arguments. Other utilities in this module do not have that restriction. """ import os import sys from distutils import ccompiler from distutils.dist import Distribution from distutils.errors import DistutilsError from .utils import silence # This function, and any functions that call it, require the setup in # `astropy_helpers.setup_helpers.register_commands` to be run first. def get_dummy_distribution(): """ Returns a distutils Distribution object used to instrument the setup environment before calling the actual setup() function. """ from .setup_helpers import _module_state if _module_state['registered_commands'] is None: raise RuntimeError( 'astropy_helpers.setup_helpers.register_commands() must be ' 'called before using ' 'astropy_helpers.setup_helpers.get_dummy_distribution()') # Pre-parse the Distutils command-line options and config files to if # the option is set. dist = Distribution({'script_name': os.path.basename(sys.argv[0]), 'script_args': sys.argv[1:]}) dist.cmdclass.update(_module_state['registered_commands']) with silence(): try: dist.parse_config_files() dist.parse_command_line() except (DistutilsError, AttributeError, SystemExit): # Let distutils handle DistutilsErrors itself AttributeErrors can # get raise for ./setup.py --help SystemExit can be raised if a # display option was used, for example pass return dist def get_distutils_option(option, commands): """ Returns the value of the given distutils option. Parameters ---------- option : str The name of the option commands : list of str The list of commands on which this option is available Returns ------- val : str or None the value of the given distutils option. If the option is not set, returns None. """ dist = get_dummy_distribution() for cmd in commands: cmd_opts = dist.command_options.get(cmd) if cmd_opts is not None and option in cmd_opts: return cmd_opts[option][1] else: return None def get_distutils_build_option(option): """ Returns the value of the given distutils build option. Parameters ---------- option : str The name of the option Returns ------- val : str or None The value of the given distutils build option. If the option is not set, returns None. """ return get_distutils_option(option, ['build', 'build_ext', 'build_clib']) def get_distutils_install_option(option): """ Returns the value of the given distutils install option. Parameters ---------- option : str The name of the option Returns ------- val : str or None The value of the given distutils build option. If the option is not set, returns None. """ return get_distutils_option(option, ['install']) def get_distutils_build_or_install_option(option): """ Returns the value of the given distutils build or install option. Parameters ---------- option : str The name of the option Returns ------- val : str or None The value of the given distutils build or install option. If the option is not set, returns None. """ return get_distutils_option(option, ['build', 'build_ext', 'build_clib', 'install']) def get_compiler_option(): """ Determines the compiler that will be used to build extension modules. Returns ------- compiler : str The compiler option specified for the build, build_ext, or build_clib command; or the default compiler for the platform if none was specified. """ compiler = get_distutils_build_option('compiler') if compiler is None: return ccompiler.get_default_compiler() return compiler def add_command_option(command, name, doc, is_bool=False): """ Add a custom option to a setup command. Issues a warning if the option already exists on that command. Parameters ---------- command : str The name of the command as given on the command line name : str The name of the build option doc : str A short description of the option, for the `--help` message is_bool : bool, optional When `True`, the option is a boolean option and doesn't require an associated value. """ dist = get_dummy_distribution() cmdcls = dist.get_command_class(command) if (hasattr(cmdcls, '_astropy_helpers_options') and name in cmdcls._astropy_helpers_options): return attr = name.replace('-', '_') if hasattr(cmdcls, attr): raise RuntimeError( '{0!r} already has a {1!r} class attribute, barring {2!r} from ' 'being usable as a custom option name.'.format(cmdcls, attr, name)) for idx, cmd in enumerate(cmdcls.user_options): if cmd[0] == name: log.warn('Overriding existing {0!r} option ' '{1!r}'.format(command, name)) del cmdcls.user_options[idx] if name in cmdcls.boolean_options: cmdcls.boolean_options.remove(name) break cmdcls.user_options.append((name, None, doc)) if is_bool: cmdcls.boolean_options.append(name) # Distutils' command parsing requires that a command object have an # attribute with the same name as the option (with '-' replaced with '_') # in order for that option to be recognized as valid setattr(cmdcls, attr, None) # This caches the options added through add_command_option so that if it is # run multiple times in the same interpreter repeated adds are ignored # (this way we can still raise a RuntimeError if a custom option overrides # a built-in option) if not hasattr(cmdcls, '_astropy_helpers_options'): cmdcls._astropy_helpers_options = set([name]) else: cmdcls._astropy_helpers_options.add(name) def get_distutils_display_options(): """ Returns a set of all the distutils display options in their long and short forms. These are the setup.py arguments such as --name or --version which print the project's metadata and then exit. Returns ------- opts : set The long and short form display option arguments, including the - or -- """ short_display_opts = set('-' + o[1] for o in Distribution.display_options if o[1]) long_display_opts = set('--' + o[0] for o in Distribution.display_options) # Include -h and --help which are not explicitly listed in # Distribution.display_options (as they are handled by optparse) short_display_opts.add('-h') long_display_opts.add('--help') # This isn't the greatest approach to hardcode these commands. # However, there doesn't seem to be a good way to determine # whether build *will be* run as part of the command at this # phase. display_commands = set([ 'clean', 'register', 'setopt', 'saveopts', 'egg_info', 'alias']) return short_display_opts.union(long_display_opts.union(display_commands)) def is_distutils_display_option(): """ Returns True if sys.argv contains any of the distutils display options such as --version or --name. """ display_options = get_distutils_display_options() return bool(set(sys.argv[1:]).intersection(display_options)) wcsaxes-0.6/astropy_helpers/astropy_helpers/git_helpers.py0000644000077000000240000001372712532571254024317 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Utilities for retrieving revision information from a project's git repository. """ # Do not remove the following comment; it is used by # astropy_helpers.version_helpers to determine the beginning of the code in # this module # BEGIN import locale import os import subprocess import warnings def _decode_stdio(stream): try: stdio_encoding = locale.getdefaultlocale()[1] or 'utf-8' except ValueError: stdio_encoding = 'utf-8' try: text = stream.decode(stdio_encoding) except UnicodeDecodeError: # Final fallback text = stream.decode('latin1') return text def update_git_devstr(version, path=None): """ Updates the git revision string if and only if the path is being imported directly from a git working copy. This ensures that the revision number in the version string is accurate. """ try: # Quick way to determine if we're in git or not - returns '' if not devstr = get_git_devstr(sha=True, show_warning=False, path=path) except OSError: return version if not devstr: # Probably not in git so just pass silently return version if 'dev' in version: # update to the current git revision version_base = version.split('.dev', 1)[0] devstr = get_git_devstr(sha=False, show_warning=False, path=path) return version_base + '.dev' + devstr else: #otherwise it's already the true/release version return version def get_git_devstr(sha=False, show_warning=True, path=None): """ Determines the number of revisions in this repository. Parameters ---------- sha : bool If True, the full SHA1 hash will be returned. Otherwise, the total count of commits in the repository will be used as a "revision number". show_warning : bool If True, issue a warning if git returns an error code, otherwise errors pass silently. path : str or None If a string, specifies the directory to look in to find the git repository. If `None`, the current working directory is used, and must be the root of the git repository. If given a filename it uses the directory containing that file. Returns ------- devversion : str Either a string with the revision number (if `sha` is False), the SHA1 hash of the current commit (if `sha` is True), or an empty string if git version info could not be identified. """ if path is None: path = os.getcwd() if not _get_repo_path(path, levels=0): return '' if not os.path.isdir(path): path = os.path.abspath(os.path.dirname(path)) if sha: # Faster for getting just the hash of HEAD cmd = ['rev-parse', 'HEAD'] else: cmd = ['rev-list', '--count', 'HEAD'] def run_git(cmd): try: p = subprocess.Popen(['git'] + cmd, cwd=path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) stdout, stderr = p.communicate() except OSError as e: if show_warning: warnings.warn('Error running git: ' + str(e)) return (None, b'', b'') if p.returncode == 128: if show_warning: warnings.warn('No git repository present at {0!r}! Using ' 'default dev version.'.format(path)) return (p.returncode, b'', b'') if p.returncode == 129: if show_warning: warnings.warn('Your git looks old (does it support {0}?); ' 'consider upgrading to v1.7.2 or ' 'later.'.format(cmd[0])) return (p.returncode, stdout, stderr) elif p.returncode != 0: if show_warning: warnings.warn('Git failed while determining revision ' 'count: {0}'.format(_decode_stdio(stderr))) return (p.returncode, stdout, stderr) return p.returncode, stdout, stderr returncode, stdout, stderr = run_git(cmd) if not sha and returncode == 129: # git returns 129 if a command option failed to parse; in # particular this could happen in git versions older than 1.7.2 # where the --count option is not supported # Also use --abbrev-commit and --abbrev=0 to display the minimum # number of characters needed per-commit (rather than the full hash) cmd = ['rev-list', '--abbrev-commit', '--abbrev=0', 'HEAD'] returncode, stdout, stderr = run_git(cmd) # Fall back on the old method of getting all revisions and counting # the lines if returncode == 0: return str(stdout.count(b'\n')) else: return '' elif sha: return _decode_stdio(stdout)[:40] else: return _decode_stdio(stdout).strip() def _get_repo_path(pathname, levels=None): """ Given a file or directory name, determine the root of the git repository this path is under. If given, this won't look any higher than ``levels`` (that is, if ``levels=0`` then the given path must be the root of the git repository and is returned if so. Returns `None` if the given path could not be determined to belong to a git repo. """ if os.path.isfile(pathname): current_dir = os.path.abspath(os.path.dirname(pathname)) elif os.path.isdir(pathname): current_dir = os.path.abspath(pathname) else: return None current_level = 0 while levels is None or current_level <= levels: if os.path.exists(os.path.join(current_dir, '.git')): return current_dir current_level += 1 if current_dir == os.path.dirname(current_dir): break current_dir = os.path.dirname(current_dir) return None wcsaxes-0.6/astropy_helpers/astropy_helpers/setup_helpers.py0000644000077000000240000007367112532571254024700 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module contains a number of utilities for use during setup/build/packaging that are useful to astropy as a whole. """ from __future__ import absolute_import, print_function import collections import os import re import shlex import shutil import subprocess import sys import textwrap import traceback from distutils import log, ccompiler, sysconfig from distutils.dist import Distribution from distutils.errors import DistutilsOptionError, DistutilsModuleError from distutils.core import Extension from distutils.core import Command from distutils.command.sdist import sdist as DistutilsSdist from setuptools import find_packages as _find_packages from .distutils_helpers import * from .version_helpers import get_pkg_version_module from .test_helpers import AstropyTest from .utils import (silence, walk_skip_hidden, import_file, extends_doc, resolve_name) from .commands.build_ext import generate_build_ext_command from .commands.build_py import AstropyBuildPy from .commands.install import AstropyInstall from .commands.install_lib import AstropyInstallLib from .commands.register import AstropyRegister # This import is not used in this module, but it is included for backwards # compat with version 0.4, which included this function in the public API # for this module from .utils import get_numpy_include_path, write_if_different from .commands.build_ext import should_build_with_cython _module_state = { 'adjusted_compiler': False, 'registered_commands': None, 'have_cython': False, 'have_sphinx': False, 'package_cache': None, 'compiler_version_cache': {} } try: import Cython _module_state['have_cython'] = True except ImportError: pass try: import sphinx _module_state['have_sphinx'] = True except ValueError as e: # This can occur deep in the bowels of Sphinx's imports by way of docutils # and an occurrence of this bug: http://bugs.python.org/issue18378 # In this case sphinx is effectively unusable if 'unknown locale' in e.args[0]: log.warn( "Possible misconfiguration of one of the environment variables " "LC_ALL, LC_CTYPES, LANG, or LANGUAGE. For an example of how to " "configure your system's language environment on OSX see " "http://blog.remibergsma.com/2012/07/10/" "setting-locales-correctly-on-mac-osx-terminal-application/") except ImportError: pass except SyntaxError: # occurs if markupsafe is recent version, which doesn't support Python 3.2 pass PY3 = sys.version_info[0] >= 3 # This adds a new keyword to the setup() function Distribution.skip_2to3 = [] def adjust_compiler(package): """ This function detects broken compilers and switches to another. If the environment variable CC is explicitly set, or a compiler is specified on the commandline, no override is performed -- the purpose here is to only override a default compiler. The specific compilers with problems are: * The default compiler in XCode-4.2, llvm-gcc-4.2, segfaults when compiling wcslib. The set of broken compilers can be updated by changing the compiler_mapping variable. It is a list of 2-tuples where the first in the pair is a regular expression matching the version of the broken compiler, and the second is the compiler to change to. """ compiler_mapping = [ (b'i686-apple-darwin[0-9]*-llvm-gcc-4.2', 'clang') ] if _module_state['adjusted_compiler']: return # Whatever the result of this function is, it only needs to be run once _module_state['adjusted_compiler'] = True if 'CC' in os.environ: # Check that CC is not set to llvm-gcc-4.2 c_compiler = os.environ['CC'] try: version = get_compiler_version(c_compiler) except OSError: msg = textwrap.dedent( """ The C compiler set by the CC environment variable: {compiler:s} cannot be found or executed. """.format(compiler=c_compiler)) log.warn(msg) sys.exit(1) for broken, fixed in compiler_mapping: if re.match(broken, version): msg = textwrap.dedent( """Compiler specified by CC environment variable ({compiler:s}:{version:s}) will fail to compile {pkg:s}. Please set CC={fixed:s} and try again. You can do this, for example, by running: CC={fixed:s} python setup.py where is the command you ran. """.format(compiler=c_compiler, version=version, pkg=package, fixed=fixed)) log.warn(msg) sys.exit(1) # If C compiler is set via CC, and isn't broken, we are good to go. We # should definitely not try accessing the compiler specified by # ``sysconfig.get_config_var('CC')`` lower down, because this may fail # if the compiler used to compile Python is missing (and maybe this is # why the user is setting CC). For example, the official Python 2.7.3 # MacOS X binary was compiled with gcc-4.2, which is no longer available # in XCode 4. return if get_distutils_build_option('compiler'): return compiler_type = ccompiler.get_default_compiler() if compiler_type == 'unix': # We have to get the compiler this way, as this is the one that is # used if os.environ['CC'] is not set. It is actually read in from # the Python Makefile. Note that this is not necessarily the same # compiler as returned by ccompiler.new_compiler() c_compiler = sysconfig.get_config_var('CC') try: version = get_compiler_version(c_compiler) except OSError: msg = textwrap.dedent( """ The C compiler used to compile Python {compiler:s}, and which is normally used to compile C extensions, is not available. You can explicitly specify which compiler to use by setting the CC environment variable, for example: CC=gcc python setup.py or if you are using MacOS X, you can try: CC=clang python setup.py """.format(compiler=c_compiler)) log.warn(msg) sys.exit(1) for broken, fixed in compiler_mapping: if re.match(broken, version): os.environ['CC'] = fixed break def get_compiler_version(compiler): if compiler in _module_state['compiler_version_cache']: return _module_state['compiler_version_cache'][compiler] # Different flags to try to get the compiler version # TODO: It might be worth making this configurable to support # arbitrary odd compilers; though all bets may be off in such # cases anyway flags = ['--version', '--Version', '-version', '-Version', '-v', '-V'] def try_get_version(flag): process = subprocess.Popen( shlex.split(compiler) + [flag], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() if process.returncode != 0: return 'unknown' output = stdout.strip() if not output: # Some compilers return their version info on stderr output = stderr.strip() if not output: output = 'unknown' return output for flag in flags: version = try_get_version(flag) if version != 'unknown': break # Cache results to speed up future calls _module_state['compiler_version_cache'][compiler] = version return version def get_debug_option(packagename): """ Determines if the build is in debug mode. Returns ------- debug : bool True if the current build was started with the debug option, False otherwise. """ try: current_debug = get_pkg_version_module(packagename, fromlist=['debug'])[0] except (ImportError, AttributeError): current_debug = None # Only modify the debug flag if one of the build commands was explicitly # run (i.e. not as a sub-command of something else) dist = get_dummy_distribution() if any(cmd in dist.commands for cmd in ['build', 'build_ext']): debug = bool(get_distutils_build_option('debug')) else: debug = bool(current_debug) if current_debug is not None and current_debug != debug: build_ext_cmd = dist.get_command_class('build_ext') build_ext_cmd.force_rebuild = True return debug def register_commands(package, version, release, srcdir='.'): if _module_state['registered_commands'] is not None: return _module_state['registered_commands'] if _module_state['have_sphinx']: from .commands.build_sphinx import AstropyBuildSphinx else: AstropyBuildSphinx = FakeBuildSphinx _module_state['registered_commands'] = registered_commands = { 'test': generate_test_command(package), # Use distutils' sdist because it respects package_data. # setuptools/distributes sdist requires duplication of information in # MANIFEST.in 'sdist': DistutilsSdist, # The exact form of the build_ext command depends on whether or not # we're building a release version 'build_ext': generate_build_ext_command(package, release), # We have a custom build_py to generate the default configuration file 'build_py': AstropyBuildPy, # Since install can (in some circumstances) be run without # first building, we also need to override install and # install_lib. See #2223 'install': AstropyInstall, 'install_lib': AstropyInstallLib, 'register': AstropyRegister, 'build_sphinx': AstropyBuildSphinx } # Need to override the __name__ here so that the commandline options are # presented as being related to the "build" command, for example; normally # this wouldn't be necessary since commands also have a command_name # attribute, but there is a bug in distutils' help display code that it # uses __name__ instead of command_name. Yay distutils! for name, cls in registered_commands.items(): cls.__name__ = name # Add a few custom options; more of these can be added by specific packages # later for option in [ ('use-system-libraries', "Use system libraries whenever possible", True)]: add_command_option('build', *option) add_command_option('install', *option) add_command_hooks(registered_commands, srcdir=srcdir) return registered_commands def add_command_hooks(commands, srcdir='.'): """ Look through setup_package.py modules for functions with names like ``pre__hook`` and ``post__hook`` where ```` is the name of a ``setup.py`` command (e.g. build_ext). If either hook is present this adds a wrapped version of that command to the passed in ``commands`` `dict`. ``commands`` may be pre-populated with other custom distutils command classes that should be wrapped if there are hooks for them (e.g. `AstropyBuildPy`). """ hook_re = re.compile(r'^(pre|post)_(.+)_hook$') # Distutils commands have a method of the same name, but it is not a # *classmethod* (which probably didn't exist when distutils was first # written) def get_command_name(cmdcls): if hasattr(cmdcls, 'command_name'): return cmdcls.command_name else: return cmdcls.__name__ packages = filter_packages(find_packages(srcdir)) dist = get_dummy_distribution() hooks = collections.defaultdict(dict) for setuppkg in iter_setup_packages(srcdir, packages): for name, obj in vars(setuppkg).items(): match = hook_re.match(name) if not match: continue hook_type = match.group(1) cmd_name = match.group(2) cmd_cls = dist.get_command_class(cmd_name) if hook_type not in hooks[cmd_name]: hooks[cmd_name][hook_type] = [] hooks[cmd_name][hook_type].append((setuppkg.__name__, obj)) for cmd_name, cmd_hooks in hooks.items(): commands[cmd_name] = generate_hooked_command( cmd_name, dist.get_command_class(cmd_name), cmd_hooks) def generate_hooked_command(cmd_name, cmd_cls, hooks): """ Returns a generated subclass of ``cmd_cls`` that runs the pre- and post-command hooks for that command before and after the ``cmd_cls.run`` method. """ def run(self, orig_run=cmd_cls.run): self.run_command_hooks('pre_hooks') orig_run(self) self.run_command_hooks('post_hooks') return type(cmd_name, (cmd_cls, object), {'run': run, 'run_command_hooks': run_command_hooks, 'pre_hooks': hooks.get('pre', []), 'post_hooks': hooks.get('post', [])}) def run_command_hooks(cmd_obj, hook_kind): """Run hooks registered for that command and phase. *cmd_obj* is a finalized command object; *hook_kind* is either 'pre_hook' or 'post_hook'. """ hooks = getattr(cmd_obj, hook_kind, None) if not hooks: return for modname, hook in hooks: if isinstance(hook, str): try: hook_obj = resolve_name(hook) except ImportError as exc: raise DistutilsModuleError( 'cannot find hook {0}: {1}'.format(hook, err)) else: hook_obj = hook if not callable(hook_obj): raise DistutilsOptionError('hook {0!r} is not callable' % hook) log.info('running {0} from {1} for {2} command'.format( hook_kind.rstrip('s'), modname, cmd_obj.get_command_name())) try : hook_obj(cmd_obj) except Exception as exc: log.error('{0} command hook {1} raised an exception: %s\n'.format( hook_obj.__name__, cmd_obj.get_command_name())) log.error(traceback.format_exc()) sys.exit(1) def generate_test_command(package_name): """ Creates a custom 'test' command for the given package which sets the command's ``package_name`` class attribute to the name of the package being tested. """ return type(package_name.title() + 'Test', (AstropyTest,), {'package_name': package_name}) def update_package_files(srcdir, extensions, package_data, packagenames, package_dirs): """ This function is deprecated and maintained for backward compatibility with affiliated packages. Affiliated packages should update their setup.py to use `get_package_info` instead. """ info = get_package_info(srcdir) extensions.extend(info['ext_modules']) package_data.update(info['package_data']) packagenames = list(set(packagenames + info['packages'])) package_dirs.update(info['package_dir']) def get_package_info(srcdir='.', exclude=()): """ Collates all of the information for building all subpackages subpackages and returns a dictionary of keyword arguments that can be passed directly to `distutils.setup`. The purpose of this function is to allow subpackages to update the arguments to the package's ``setup()`` function in its setup.py script, rather than having to specify all extensions/package data directly in the ``setup.py``. See Astropy's own ``setup.py`` for example usage and the Astropy development docs for more details. This function obtains that information by iterating through all packages in ``srcdir`` and locating a ``setup_package.py`` module. This module can contain the following functions: ``get_extensions()``, ``get_package_data()``, ``get_build_options()``, ``get_external_libraries()``, and ``requires_2to3()``. Each of those functions take no arguments. - ``get_extensions`` returns a list of `distutils.extension.Extension` objects. - ``get_package_data()`` returns a dict formatted as required by the ``package_data`` argument to ``setup()``. - ``get_build_options()`` returns a list of tuples describing the extra build options to add. - ``get_external_libraries()`` returns a list of libraries that can optionally be built using external dependencies. - ``get_entry_points()`` returns a dict formatted as required by the ``entry_points`` argument to ``setup()``. - ``requires_2to3()`` should return `True` when the source code requires `2to3` processing to run on Python 3.x. If ``requires_2to3()`` is missing, it is assumed to return `True`. """ ext_modules = [] packages = [] package_data = {} package_dir = {} skip_2to3 = [] # Use the find_packages tool to locate all packages and modules packages = filter_packages(find_packages(srcdir, exclude=exclude)) # For each of the setup_package.py modules, extract any # information that is needed to install them. The build options # are extracted first, so that their values will be available in # subsequent calls to `get_extensions`, etc. for setuppkg in iter_setup_packages(srcdir, packages): if hasattr(setuppkg, 'get_build_options'): options = setuppkg.get_build_options() for option in options: add_command_option('build', *option) if hasattr(setuppkg, 'get_external_libraries'): libraries = setuppkg.get_external_libraries() for library in libraries: add_external_library(library) if hasattr(setuppkg, 'requires_2to3'): requires_2to3 = setuppkg.requires_2to3() else: requires_2to3 = True if not requires_2to3: skip_2to3.append( os.path.dirname(setuppkg.__file__)) for setuppkg in iter_setup_packages(srcdir, packages): # get_extensions must include any Cython extensions by their .pyx # filename. if hasattr(setuppkg, 'get_extensions'): ext_modules.extend(setuppkg.get_extensions()) if hasattr(setuppkg, 'get_package_data'): package_data.update(setuppkg.get_package_data()) # Locate any .pyx files not already specified, and add their extensions in. # The default include dirs include numpy to facilitate numerical work. ext_modules.extend(get_cython_extensions(srcdir, packages, ext_modules, ['numpy'])) # Now remove extensions that have the special name 'skip_cython', as they # exist Only to indicate that the cython extensions shouldn't be built for i, ext in reversed(list(enumerate(ext_modules))): if ext.name == 'skip_cython': del ext_modules[i] # On Microsoft compilers, we need to pass the '/MANIFEST' # commandline argument. This was the default on MSVC 9.0, but is # now required on MSVC 10.0, but it doesn't seem to hurt to add # it unconditionally. if get_compiler_option() == 'msvc': for ext in ext_modules: ext.extra_link_args.append('/MANIFEST') return { 'ext_modules': ext_modules, 'packages': packages, 'package_dir': package_dir, 'package_data': package_data, 'skip_2to3': skip_2to3 } def iter_setup_packages(srcdir, packages): """ A generator that finds and imports all of the ``setup_package.py`` modules in the source packages. Returns ------- modgen : generator A generator that yields (modname, mod), where `mod` is the module and `modname` is the module name for the ``setup_package.py`` modules. """ for packagename in packages: package_parts = packagename.split('.') package_path = os.path.join(srcdir, *package_parts) setup_package = os.path.relpath( os.path.join(package_path, 'setup_package.py')) if os.path.isfile(setup_package): module = import_file(setup_package, name=packagename + '.setup_package') yield module def iter_pyx_files(package_dir, package_name): """ A generator that yields Cython source files (ending in '.pyx') in the source packages. Returns ------- pyxgen : generator A generator that yields (extmod, fullfn) where `extmod` is the full name of the module that the .pyx file would live in based on the source directory structure, and `fullfn` is the path to the .pyx file. """ for dirpath, dirnames, filenames in walk_skip_hidden(package_dir): for fn in filenames: if fn.endswith('.pyx'): fullfn = os.path.relpath(os.path.join(dirpath, fn)) # Package must match file name extmod = '.'.join([package_name, fn[:-4]]) yield (extmod, fullfn) break # Don't recurse into subdirectories def get_cython_extensions(srcdir, packages, prevextensions=tuple(), extincludedirs=None): """ Looks for Cython files and generates Extensions if needed. Parameters ---------- srcdir : str Path to the root of the source directory to search. prevextensions : list of `~distutils.core.Extension` objects The extensions that are already defined. Any .pyx files already here will be ignored. extincludedirs : list of str or None Directories to include as the `include_dirs` argument to the generated `~distutils.core.Extension` objects. Returns ------- exts : list of `~distutils.core.Extension` objects The new extensions that are needed to compile all .pyx files (does not include any already in `prevextensions`). """ # Vanilla setuptools and old versions of distribute include Cython files # as .c files in the sources, not .pyx, so we cannot simply look for # existing .pyx sources in the previous sources, but we should also check # for .c files with the same remaining filename. So we look for .pyx and # .c files, and we strip the extension. prevsourcepaths = [] ext_modules = [] for ext in prevextensions: for s in ext.sources: if s.endswith(('.pyx', '.c')): sourcepath = os.path.realpath(os.path.splitext(s)[0]) prevsourcepaths.append(sourcepath) for package_name in packages: package_parts = package_name.split('.') package_path = os.path.join(srcdir, *package_parts) for extmod, pyxfn in iter_pyx_files(package_path, package_name): sourcepath = os.path.realpath(os.path.splitext(pyxfn)[0]) if sourcepath not in prevsourcepaths: ext_modules.append(Extension(extmod, [pyxfn], include_dirs=extincludedirs)) return ext_modules class DistutilsExtensionArgs(collections.defaultdict): """ A special dictionary whose default values are the empty list. This is useful for building up a set of arguments for `distutils.Extension` without worrying whether the entry is already present. """ def __init__(self, *args, **kwargs): def default_factory(): return [] super(DistutilsExtensionArgs, self).__init__( default_factory, *args, **kwargs) def update(self, other): for key, val in other.items(): self[key].extend(val) def pkg_config(packages, default_libraries, executable='pkg-config'): """ Uses pkg-config to update a set of distutils Extension arguments to include the flags necessary to link against the given packages. If the pkg-config lookup fails, default_libraries is applied to libraries. Parameters ---------- packages : list of str A list of pkg-config packages to look up. default_libraries : list of str A list of library names to use if the pkg-config lookup fails. Returns ------- config : dict A dictionary containing keyword arguments to `distutils.Extension`. These entries include: - ``include_dirs``: A list of include directories - ``library_dirs``: A list of library directories - ``libraries``: A list of libraries - ``define_macros``: A list of macro defines - ``undef_macros``: A list of macros to undefine - ``extra_compile_args``: A list of extra arguments to pass to the compiler """ flag_map = {'-I': 'include_dirs', '-L': 'library_dirs', '-l': 'libraries', '-D': 'define_macros', '-U': 'undef_macros'} command = "{0} --libs --cflags {1}".format(executable, ' '.join(packages)), result = DistutilsExtensionArgs() try: pipe = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) output = pipe.communicate()[0].strip() except subprocess.CalledProcessError as e: lines = [ "{0} failed. This may cause the build to fail below.".format(executable), " command: {0}".format(e.cmd), " returncode: {0}".format(e.returncode), " output: {0}".format(e.output) ] log.warn('\n'.join(lines)) result['libraries'].extend(default_libraries) else: if pipe.returncode != 0: lines = [ "pkg-config could not lookup up package(s) {0}.".format( ", ".join(packages)), "This may cause the build to fail below." ] log.warn('\n'.join(lines)) result['libraries'].extend(default_libraries) else: for token in output.split(): # It's not clear what encoding the output of # pkg-config will come to us in. It will probably be # some combination of pure ASCII (for the compiler # flags) and the filesystem encoding (for any argument # that includes directories or filenames), but this is # just conjecture, as the pkg-config documentation # doesn't seem to address it. arg = token[:2].decode('ascii') value = token[2:].decode(sys.getfilesystemencoding()) if arg in flag_map: if arg == '-D': value = tuple(value.split('=', 1)) result[flag_map[arg]].append(value) else: result['extra_compile_args'].append(value) return result def add_external_library(library): """ Add a build option for selecting the internal or system copy of a library. Parameters ---------- library : str The name of the library. If the library is `foo`, the build option will be called `--use-system-foo`. """ for command in ['build', 'build_ext', 'install']: add_command_option(command, str('use-system-' + library), 'Use the system {0} library'.format(library), is_bool=True) def use_system_library(library): """ Returns `True` if the build configuration indicates that the given library should use the system copy of the library rather than the internal one. For the given library `foo`, this will be `True` if `--use-system-foo` or `--use-system-libraries` was provided at the commandline or in `setup.cfg`. Parameters ---------- library : str The name of the library Returns ------- use_system : bool `True` if the build should use the system copy of the library. """ return ( get_distutils_build_or_install_option('use_system_{0}'.format(library)) or get_distutils_build_or_install_option('use_system_libraries')) @extends_doc(_find_packages) def find_packages(where='.', exclude=(), invalidate_cache=False): """ This version of ``find_packages`` caches previous results to speed up subsequent calls. Use ``invalide_cache=True`` to ignore cached results from previous ``find_packages`` calls, and repeat the package search. """ if not invalidate_cache and _module_state['package_cache'] is not None: return _module_state['package_cache'] packages = _find_packages(where=where, exclude=exclude) _module_state['package_cache'] = packages return packages def filter_packages(packagenames): """ Removes some packages from the package list that shouldn't be installed on the current version of Python. """ if PY3: exclude = '_py2' else: exclude = '_py3' return [x for x in packagenames if not x.endswith(exclude)] class FakeBuildSphinx(Command): """ A dummy build_sphinx command that is called if Sphinx is not installed and displays a relevant error message """ #user options inherited from sphinx.setup_command.BuildDoc user_options = [ ('fresh-env', 'E', '' ), ('all-files', 'a', ''), ('source-dir=', 's', ''), ('build-dir=', None, ''), ('config-dir=', 'c', ''), ('builder=', 'b', ''), ('project=', None, ''), ('version=', None, ''), ('release=', None, ''), ('today=', None, ''), ('link-index', 'i', ''), ] #user options appended in astropy.setup_helpers.AstropyBuildSphinx user_options.append(('warnings-returncode', 'w','')) user_options.append(('clean-docs', 'l', '')) user_options.append(('no-intersphinx', 'n', '')) user_options.append(('open-docs-in-browser', 'o','')) def initialize_options(self): try: raise RuntimeError("Sphinx must be installed for build_sphinx") except: log.error('error : Sphinx must be installed for build_sphinx') sys.exit(1) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/0000755000077000000240000000000012553237435022742 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/__init__.py0000644000077000000240000000041412346274067025054 0ustar tomstaff00000000000000""" This package contains utilities and extensions for the Astropy sphinx documentation. In particular, the `astropy.sphinx.conf` should be imported by the sphinx ``conf.py`` file for affiliated packages that wish to make use of the Astropy documentation format. """ wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/conf.py0000644000077000000240000002477212532571254024252 0ustar tomstaff00000000000000# -*- coding: utf-8 -*- # Licensed under a 3-clause BSD style license - see LICENSE.rst # # Astropy shared Sphinx settings. These settings are shared between # astropy itself and affiliated packages. # # Note that not all possible configuration values are present in this file. # # All configuration values have a default; values that are commented out # serve to show the default. import warnings from os import path # -- General configuration ---------------------------------------------------- # The version check in Sphinx itself can only compare the major and # minor parts of the version number, not the micro. To do a more # specific version check, call check_sphinx_version("x.y.z.") from # your project's conf.py needs_sphinx = '1.2' def check_sphinx_version(expected_version): import sphinx from distutils import version sphinx_version = version.LooseVersion(sphinx.__version__) expected_version = version.LooseVersion(expected_version) if sphinx_version < expected_version: raise RuntimeError( "At least Sphinx version {0} is required to build this " "documentation. Found {1}.".format( expected_version, sphinx_version)) # Configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { 'python': ('http://docs.python.org/', None), 'python3': ('http://docs.python.org/3/', path.abspath(path.join(path.dirname(__file__), 'local/python3links.inv'))), 'numpy': ('http://docs.scipy.org/doc/numpy/', None), 'scipy': ('http://docs.scipy.org/doc/scipy/reference/', None), 'matplotlib': ('http://matplotlib.org/', None), 'astropy': ('http://docs.astropy.org/en/stable/', None), 'h5py': ('http://docs.h5py.org/en/latest/', None) } # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # Add any paths that contain templates here, relative to this directory. # templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # The reST default role (used for this markup: `text`) to use for all # documents. Set to the "smart" one. default_role = 'obj' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # This is added to the end of RST files - a good place to put substitutions to # be used globally. rst_epilog = """ .. _Astropy: http://astropy.org """ # -- Project information ------------------------------------------------------ # 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' # 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 = [] # -- Settings for extensions and extension options ---------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.pngmath', 'sphinx.ext.inheritance_diagram', 'astropy_helpers.sphinx.ext.numpydoc', 'astropy_helpers.sphinx.ext.astropyautosummary', 'astropy_helpers.sphinx.ext.autodoc_enhancements', 'astropy_helpers.sphinx.ext.automodsumm', 'astropy_helpers.sphinx.ext.automodapi', 'astropy_helpers.sphinx.ext.tocdepthfix', 'astropy_helpers.sphinx.ext.doctest', 'astropy_helpers.sphinx.ext.changelog_links', 'astropy_helpers.sphinx.ext.viewcode', # Use patched version of viewcode 'astropy_helpers.sphinx.ext.smart_resolver' ] # Above, we use a patched version of viewcode rather than 'sphinx.ext.viewcode' # This can be changed to the sphinx version once the following issue is fixed # in sphinx: # https://bitbucket.org/birkenfeld/sphinx/issue/623/ # extension-viewcode-fails-with-function try: import matplotlib.sphinxext.plot_directive extensions += [matplotlib.sphinxext.plot_directive.__name__] # AttributeError is checked here in case matplotlib is installed but # Sphinx isn't. Note that this module is imported by the config file # generator, even if we're not building the docs. except (ImportError, AttributeError): warnings.warn( "matplotlib's plot_directive could not be imported. " + "Inline plots will not be included in the output") # Don't show summaries of the members in each class along with the # class' docstring numpydoc_show_class_members = False autosummary_generate = True automodapi_toctreedirnm = 'api' # Class documentation should contain *both* the class docstring and # the __init__ docstring autoclass_content = "both" # Render inheritance diagrams in SVG graphviz_output_format = "svg" # -- Options for HTML output ------------------------------------------------- # Add any paths that contain custom themes here, relative to this directory. html_theme_path = [path.abspath(path.join(path.dirname(__file__), 'themes'))] # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'bootstrap-astropy' # Custom sidebar templates, maps document names to template names. html_sidebars = { '**': ['localtoc.html'], 'search': [], 'genindex': [], 'py-modindex': [], } # 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. # included in the bootstrap-astropy theme html_favicon = path.join(html_theme_path[0], html_theme, 'static', 'astropy_logo.ico') # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. html_last_updated_fmt = '%d %b %Y' # 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 = {} # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # -- 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' # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. latex_use_parts = True # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. latex_preamble = r""" % Use a more modern-looking monospace font \usepackage{inconsolata} % The enumitem package provides unlimited nesting of lists and enums. % Sphinx may use this in the future, in which case this can be removed. % See https://bitbucket.org/birkenfeld/sphinx/issue/777/latex-output-too-deeply-nested \usepackage{enumitem} \setlistdepth{15} % In the parameters section, place a newline after the Parameters % header. (This is stolen directly from Numpy's conf.py, since it % affects Numpy-style docstrings). \usepackage{expdlist} \let\latexdescription=\description \def\description{\latexdescription{}{} \breaklabel} % Support the superscript Unicode numbers used by the "unicode" units % formatter \DeclareUnicodeCharacter{2070}{\ensuremath{^0}} \DeclareUnicodeCharacter{00B9}{\ensuremath{^1}} \DeclareUnicodeCharacter{00B2}{\ensuremath{^2}} \DeclareUnicodeCharacter{00B3}{\ensuremath{^3}} \DeclareUnicodeCharacter{2074}{\ensuremath{^4}} \DeclareUnicodeCharacter{2075}{\ensuremath{^5}} \DeclareUnicodeCharacter{2076}{\ensuremath{^6}} \DeclareUnicodeCharacter{2077}{\ensuremath{^7}} \DeclareUnicodeCharacter{2078}{\ensuremath{^8}} \DeclareUnicodeCharacter{2079}{\ensuremath{^9}} \DeclareUnicodeCharacter{207B}{\ensuremath{^-}} \DeclareUnicodeCharacter{00B0}{\ensuremath{^{\circ}}} \DeclareUnicodeCharacter{2032}{\ensuremath{^{\prime}}} \DeclareUnicodeCharacter{2033}{\ensuremath{^{\prime\prime}}} % Make the "warning" and "notes" sections use a sans-serif font to % make them stand out more. \renewenvironment{notice}[2]{ \def\py@noticetype{#1} \csname py@noticestart@#1\endcsname \textsf{\textbf{#2}} }{\csname py@noticeend@\py@noticetype\endcsname} """ # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # -- Options for the linkcheck builder ---------------------------------------- # A timeout value, in seconds, for the linkcheck builder linkcheck_timeout = 60 wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/0000755000077000000240000000000012553237435023542 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/__init__.py0000644000077000000240000000013612346274067025655 0ustar tomstaff00000000000000from __future__ import division, absolute_import, print_function from .numpydoc import setup wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/astropyautosummary.py0000644000077000000240000000761712532571254030134 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This sphinx extension builds off of `sphinx.ext.autosummary` to clean up some issues it presents in the Astropy docs. The main issue this fixes is the summary tables getting cut off before the end of the sentence in some cases. Note: Sphinx 1.2 appears to have fixed the the main issues in the stock autosummary extension that are addressed by this extension. So use of this extension with newer versions of Sphinx is deprecated. """ import re from distutils.version import LooseVersion import sphinx from sphinx.ext.autosummary import Autosummary from ...utils import deprecated # used in AstropyAutosummary.get_items _itemsummrex = re.compile(r'^([A-Z].*?\.(?:\s|$))') @deprecated('1.0', message='AstropyAutosummary is only needed when used ' 'with Sphinx versions less than 1.2') class AstropyAutosummary(Autosummary): def get_items(self, names): """Try to import the given names, and return a list of ``[(name, signature, summary_string, real_name), ...]``. """ from sphinx.ext.autosummary import (get_import_prefixes_from_env, import_by_name, get_documenter, mangle_signature) env = self.state.document.settings.env prefixes = get_import_prefixes_from_env(env) items = [] max_item_chars = 50 for name in names: display_name = name if name.startswith('~'): name = name[1:] display_name = name.split('.')[-1] try: import_by_name_values = import_by_name(name, prefixes=prefixes) except ImportError: self.warn('[astropyautosummary] failed to import %s' % name) items.append((name, '', '', name)) continue # to accommodate Sphinx v1.2.2 and v1.2.3 if len(import_by_name_values) == 3: real_name, obj, parent = import_by_name_values elif len(import_by_name_values) == 4: real_name, obj, parent, module_name = import_by_name_values # NB. using real_name here is important, since Documenters # handle module prefixes slightly differently documenter = get_documenter(obj, parent)(self, real_name) if not documenter.parse_name(): self.warn('[astropyautosummary] failed to parse name %s' % real_name) items.append((display_name, '', '', real_name)) continue if not documenter.import_object(): self.warn('[astropyautosummary] failed to import object %s' % real_name) items.append((display_name, '', '', real_name)) continue # -- Grab the signature sig = documenter.format_signature() if not sig: sig = '' else: max_chars = max(10, max_item_chars - len(display_name)) sig = mangle_signature(sig, max_chars=max_chars) sig = sig.replace('*', r'\*') # -- Grab the summary doc = list(documenter.process_doc(documenter.get_doc())) while doc and not doc[0].strip(): doc.pop(0) m = _itemsummrex.search(" ".join(doc).strip()) if m: summary = m.group(1).strip() elif doc: summary = doc[0].strip() else: summary = '' items.append((display_name, sig, summary, real_name)) return items def setup(app): # need autosummary, of course app.setup_extension('sphinx.ext.autosummary') # Don't make the replacement if Sphinx is at least 1.2 if LooseVersion(sphinx.__version__) < LooseVersion('1.2.0'): # this replaces the default autosummary with the astropy one app.add_directive('autosummary', AstropyAutosummary) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/autodoc_enhancements.py0000644000077000000240000000401412532571254030276 0ustar tomstaff00000000000000""" Miscellaneous enhancements to help autodoc along. """ # See # https://github.com/astropy/astropy-helpers/issues/116#issuecomment-71254836 # for further background on this. def type_object_attrgetter(obj, attr, *defargs): """ This implements an improved attrgetter for type objects (i.e. classes) that can handle class attributes that are implemented as properties on a metaclass. Normally `getattr` on a class with a `property` (say, "foo"), would return the `property` object itself. However, if the class has a metaclass which *also* defines a `property` named "foo", ``getattr(cls, 'foo')`` will find the "foo" property on the metaclass and resolve it. For the purposes of autodoc we just want to document the "foo" property defined on the class, not on the metaclass. For example:: >>> class Meta(type): ... @property ... def foo(cls): ... return 'foo' ... >>> class MyClass(metaclass=Meta): ... @property ... def foo(self): ... \"\"\"Docstring for MyClass.foo property.\"\"\" ... return 'myfoo' ... >>> getattr(MyClass, 'foo') 'foo' >>> type_object_attrgetter(MyClass, 'foo') >>> type_object_attrgetter(MyClass, 'foo').__doc__ 'Docstring for MyClass.foo property.' The last line of the example shows the desired behavior for the purposes of autodoc. """ for base in obj.__mro__: if attr in base.__dict__: if isinstance(base.__dict__[attr], property): # Note, this should only be used for properties--for any other # type of descriptor (classmethod, for example) this can mess # up existing expectations of what getattr(cls, ...) returns return base.__dict__[attr] break return getattr(obj, attr, *defargs) def setup(app): app.add_autodoc_attrgetter(type, type_object_attrgetter) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/automodapi.py0000644000077000000240000003164712532571254026266 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This sphinx extension adds a tools to simplify generating the API documentation for Astropy packages and affiliated packages. .. _automodapi: ======================== automodapi directive ======================== This directive takes a single argument that must be a module or package. It will produce a block of documentation that includes the docstring for the package, an :ref:`automodsumm` directive, and an :ref:`automod-diagram` if there are any classes in the module. If only the main docstring of the module/package is desired in the documentation, use `automodule`_ instead of `automodapi`_. It accepts the following options: * ``:no-inheritance-diagram:`` If present, the inheritance diagram will not be shown even if the module/package has classes. * ``:skip: str`` This option results in the specified object being skipped, that is the object will *not* be included in the generated documentation. This option may appear any number of times to skip multiple objects. * ``:no-main-docstr:`` If present, the docstring for the module/package will not be generated. The function and class tables will still be used, however. * ``:headings: str`` Specifies the characters (in one string) used as the heading levels used for the generated section. This must have at least 2 characters (any after 2 will be ignored). This also *must* match the rest of the documentation on this page for sphinx to be happy. Defaults to "-^", which matches the convention used for Python's documentation, assuming the automodapi call is inside a top-level section (which usually uses '='). * ``:no-heading:`` If specified do not create a top level heading for the section. That is, do not create a title heading with text like "packagename Package". The actual docstring for the package/module will still be shown, though, unless ``:no-main-docstr:`` is given. * ``:allowed-package-names: str`` Specifies the packages that functions/classes documented here are allowed to be from, as comma-separated list of package names. If not given, only objects that are actually in a subpackage of the package currently being documented are included. This extension also adds two sphinx configuration options: * ``automodapi_toctreedirnm`` This must be a string that specifies the name of the directory the automodsumm generated documentation ends up in. This directory path should be relative to the documentation root (e.g., same place as ``index.rst``). Defaults to ``'api'``. * ``automodapi_writereprocessed`` Should be a bool, and if `True`, will cause `automodapi`_ to write files with any `automodapi`_ sections replaced with the content Sphinx processes after `automodapi`_ has run. The output files are not actually used by sphinx, so this option is only for figuring out the cause of sphinx warnings or other debugging. Defaults to `False`. .. _automodule: http://sphinx-doc.org/latest/ext/autodoc.html?highlight=automodule#directive-automodule """ # Implementation note: # The 'automodapi' directive is not actually implemented as a docutils # directive. Instead, this extension searches for the 'automodapi' text in # all sphinx documents, and replaces it where necessary from a template built # into this extension. This is necessary because automodsumm (and autosummary) # use the "builder-inited" event, which comes before the directives are # actually built. import inspect import os import re import sys from .utils import find_mod_objs if sys.version_info[0] == 3: text_type = str else: text_type = unicode automod_templ_modheader = """ {modname} {pkgormod} {modhds}{pkgormodhds} {automoduleline} """ automod_templ_classes = """ Classes {clshds} .. automodsumm:: {modname} :classes-only: {clsfuncoptions} """ automod_templ_funcs = """ Functions {funchds} .. automodsumm:: {modname} :functions-only: {clsfuncoptions} """ automod_templ_inh = """ Class Inheritance Diagram {clsinhsechds} .. automod-diagram:: {modname} :private-bases: :parts: 1 {allowedpkgnms} """ _automodapirex = re.compile(r'^(?:\s*\.\.\s+automodapi::\s*)([A-Za-z0-9_.]+)' r'\s*$((?:\n\s+:[a-zA-Z_\-]+:.*$)*)', flags=re.MULTILINE) # the last group of the above regex is intended to go into finall with the below _automodapiargsrex = re.compile(r':([a-zA-Z_\-]+):(.*)$', flags=re.MULTILINE) def automodapi_replace(sourcestr, app, dotoctree=True, docname=None, warnings=True): """ Replaces `sourcestr`'s entries of ".. automdapi::" with the automodapi template form based on provided options. This is used with the sphinx event 'source-read' to replace `automodapi`_ entries before sphinx actually processes them, as automodsumm needs the code to be present to generate stub documentation. Parameters ---------- sourcestr : str The string with sphinx source to be checked for automodapi replacement. app : `sphinx.application.Application` The sphinx application. dotoctree : bool If `True`, a ":toctree:" option will be added in the ".. automodsumm::" sections of the template, pointing to the appropriate "generated" directory based on the Astropy convention (e.g. in ``docs/api``) docname : str The name of the file for this `sourcestr` (if known - if not, it can be `None`). If not provided and `dotoctree` is `True`, the generated files may end up in the wrong place. warnings : bool If `False`, all warnings that would normally be issued are silenced. Returns ------- newstr :str The string with automodapi entries replaced with the correct sphinx markup. """ spl = _automodapirex.split(sourcestr) if len(spl) > 1: # automodsumm is in this document if dotoctree: toctreestr = ':toctree: ' dirnm = app.config.automodapi_toctreedirnm if not dirnm.endswith("/"): dirnm += "/" if docname is not None: toctreestr += '../' * docname.count('/') + dirnm else: toctreestr += dirnm else: toctreestr = '' newstrs = [spl[0]] for grp in range(len(spl) // 3): modnm = spl[grp * 3 + 1] # find where this is in the document for warnings if docname is None: location = None else: location = (docname, spl[0].count('\n')) # initialize default options toskip = [] inhdiag = maindocstr = top_head = True hds = '-^' allowedpkgnms = [] # look for actual options unknownops = [] for opname, args in _automodapiargsrex.findall(spl[grp * 3 + 2]): if opname == 'skip': toskip.append(args.strip()) elif opname == 'no-inheritance-diagram': inhdiag = False elif opname == 'no-main-docstr': maindocstr = False elif opname == 'headings': hds = args elif opname == 'no-heading': top_head = False elif opname == 'allowed-package-names': allowedpkgnms.append(args.strip()) else: unknownops.append(opname) #join all the allowedpkgnms if len(allowedpkgnms) == 0: allowedpkgnms = '' onlylocals = True else: allowedpkgnms = ':allowed-package-names: ' + ','.join(allowedpkgnms) onlylocals = allowedpkgnms # get the two heading chars if len(hds) < 2: msg = 'Not enough headings (got {0}, need 2), using default -^' if warnings: app.warn(msg.format(len(hds)), location) hds = '-^' h1, h2 = hds.lstrip()[:2] # tell sphinx that the remaining args are invalid. if len(unknownops) > 0 and app is not None: opsstrs = ','.join(unknownops) msg = 'Found additional options ' + opsstrs + ' in automodapi.' if warnings: app.warn(msg, location) ispkg, hascls, hasfuncs = _mod_info(modnm, toskip, onlylocals=onlylocals) # add automodule directive only if no-main-docstr isn't present if maindocstr: automodline = '.. automodule:: {modname}'.format(modname=modnm) else: automodline = '' if top_head: newstrs.append(automod_templ_modheader.format(modname=modnm, modhds=h1 * len(modnm), pkgormod='Package' if ispkg else 'Module', pkgormodhds=h1 * (8 if ispkg else 7), automoduleline=automodline)) else: newstrs.append(automod_templ_modheader.format( modname='', modhds='', pkgormod='', pkgormodhds='', automoduleline=automodline)) #construct the options for the class/function sections #start out indented at 4 spaces, but need to keep the indentation. clsfuncoptions = [] if toctreestr: clsfuncoptions.append(toctreestr) if toskip: clsfuncoptions.append(':skip: ' + ','.join(toskip)) if allowedpkgnms: clsfuncoptions.append(allowedpkgnms) clsfuncoptionstr = '\n '.join(clsfuncoptions) if hasfuncs: newstrs.append(automod_templ_funcs.format( modname=modnm, funchds=h2 * 9, clsfuncoptions=clsfuncoptionstr)) if hascls: newstrs.append(automod_templ_classes.format( modname=modnm, clshds=h2 * 7, clsfuncoptions=clsfuncoptionstr)) if inhdiag and hascls: # add inheritance diagram if any classes are in the module newstrs.append(automod_templ_inh.format( modname=modnm, clsinhsechds=h2 * 25, allowedpkgnms=allowedpkgnms)) newstrs.append(spl[grp * 3 + 3]) newsourcestr = ''.join(newstrs) if app.config.automodapi_writereprocessed: # sometimes they are unicode, sometimes not, depending on how # sphinx has processed things if isinstance(newsourcestr, text_type): ustr = newsourcestr else: ustr = newsourcestr.decode(app.config.source_encoding) if docname is None: with open(os.path.join(app.srcdir, 'unknown.automodapi'), 'a') as f: f.write('\n**NEW DOC**\n\n') f.write(ustr) else: env = app.builder.env # Determine the filename associated with this doc (specifically # the extension) filename = docname + os.path.splitext(env.doc2path(docname))[1] filename += '.automodapi' with open(os.path.join(app.srcdir, filename), 'w') as f: f.write(ustr) return newsourcestr else: return sourcestr def _mod_info(modname, toskip=[], onlylocals=True): """ Determines if a module is a module or a package and whether or not it has classes or functions. """ hascls = hasfunc = False for localnm, fqnm, obj in zip(*find_mod_objs(modname, onlylocals=onlylocals)): if localnm not in toskip: hascls = hascls or inspect.isclass(obj) hasfunc = hasfunc or inspect.isroutine(obj) if hascls and hasfunc: break # find_mod_objs has already imported modname # TODO: There is probably a cleaner way to do this, though this is pretty # reliable for all Python versions for most cases that we care about. pkg = sys.modules[modname] ispkg = (hasattr(pkg, '__file__') and isinstance(pkg.__file__, str) and os.path.split(pkg.__file__)[1].startswith('__init__.py')) return ispkg, hascls, hasfunc def process_automodapi(app, docname, source): source[0] = automodapi_replace(source[0], app, True, docname) def setup(app): # need automodsumm for automodapi app.setup_extension('astropy_helpers.sphinx.ext.automodsumm') app.connect('source-read', process_automodapi) app.add_config_value('automodapi_toctreedirnm', 'api', True) app.add_config_value('automodapi_writereprocessed', False, True) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/automodsumm.py0000644000077000000240000005574712532571254026505 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This sphinx extension adds two directives for summarizing the public members of a module or package. These directives are primarily for use with the `automodapi`_ extension, but can be used independently. .. _automodsumm: ======================= automodsumm directive ======================= This directive will produce an "autosummary"-style table for public attributes of a specified module. See the `sphinx.ext.autosummary`_ extension for details on this process. The main difference from the `autosummary`_ directive is that `autosummary`_ requires manually inputting all attributes that appear in the table, while this captures the entries automatically. This directive requires a single argument that must be a module or package. It also accepts any options supported by the `autosummary`_ directive- see `sphinx.ext.autosummary`_ for details. It also accepts two additional options: * ``:classes-only:`` If present, the autosummary table will only contain entries for classes. This cannot be used at the same time with ``:functions-only:`` . * ``:functions-only:`` If present, the autosummary table will only contain entries for functions. This cannot be used at the same time with ``:classes-only:`` . * ``:skip: obj1, [obj2, obj3, ...]`` If present, specifies that the listed objects should be skipped and not have their documentation generated, nor be included in the summary table. * ``:allowed-package-names: pkgormod1, [pkgormod2, pkgormod3, ...]`` Specifies the packages that functions/classes documented here are allowed to be from, as comma-separated list of package names. If not given, only objects that are actually in a subpackage of the package currently being documented are included. This extension also adds one sphinx configuration option: * ``automodsumm_writereprocessed`` Should be a bool, and if True, will cause `automodsumm`_ to write files with any ``automodsumm`` sections replaced with the content Sphinx processes after ``automodsumm`` has run. The output files are not actually used by sphinx, so this option is only for figuring out the cause of sphinx warnings or other debugging. Defaults to `False`. .. _sphinx.ext.autosummary: http://sphinx-doc.org/latest/ext/autosummary.html .. _autosummary: http://sphinx-doc.org/latest/ext/autosummary.html#directive-autosummary .. _automod-diagram: =========================== automod-diagram directive =========================== This directive will produce an inheritance diagram like that of the `sphinx.ext.inheritance_diagram`_ extension. This directive requires a single argument that must be a module or package. It accepts no options. .. note:: Like 'inheritance-diagram', 'automod-diagram' requires `graphviz `_ to generate the inheritance diagram. .. _sphinx.ext.inheritance_diagram: http://sphinx-doc.org/latest/ext/inheritance.html """ import inspect import os import re from distutils.version import LooseVersion import sphinx from sphinx.ext.autosummary import Autosummary from sphinx.ext.inheritance_diagram import InheritanceDiagram from docutils.parsers.rst.directives import flag from .utils import find_mod_objs from .astropyautosummary import AstropyAutosummary # Don't use AstropyAutosummary with newer versions of Sphinx # See https://github.com/astropy/astropy-helpers/pull/129 if LooseVersion(sphinx.__version__) < LooseVersion('1.2.0'): BaseAutosummary = AstropyAutosummary else: BaseAutosummary = Autosummary def _str_list_converter(argument): """ A directive option conversion function that converts the option into a list of strings. Used for 'skip' option. """ if argument is None: return [] else: return [s.strip() for s in argument.split(',')] class Automodsumm(BaseAutosummary): required_arguments = 1 optional_arguments = 0 final_argument_whitespace = False has_content = False option_spec = dict(Autosummary.option_spec) option_spec['functions-only'] = flag option_spec['classes-only'] = flag option_spec['skip'] = _str_list_converter option_spec['allowed-package-names'] = _str_list_converter def run(self): env = self.state.document.settings.env modname = self.arguments[0] self.warnings = [] nodelist = [] try: localnames, fqns, objs = find_mod_objs(modname) except ImportError: self.warnings = [] self.warn("Couldn't import module " + modname) return self.warnings try: # set self.content to trick the Autosummary internals. # Be sure to respect functions-only and classes-only. funconly = 'functions-only' in self.options clsonly = 'classes-only' in self.options skipnames = [] if 'skip' in self.options: option_skipnames = set(self.options['skip']) for lnm in localnames: if lnm in option_skipnames: option_skipnames.remove(lnm) skipnames.append(lnm) if len(option_skipnames) > 0: self.warn('Tried to skip objects {objs} in module {mod}, ' 'but they were not present. Ignoring.'.format( objs=option_skipnames, mod=modname)) if funconly and not clsonly: cont = [] for nm, obj in zip(localnames, objs): if nm not in skipnames and inspect.isroutine(obj): cont.append(nm) elif clsonly: cont = [] for nm, obj in zip(localnames, objs): if nm not in skipnames and inspect.isclass(obj): cont.append(nm) else: if clsonly and funconly: self.warning('functions-only and classes-only both ' 'defined. Skipping.') cont = [nm for nm in localnames if nm not in skipnames] self.content = cont # for some reason, even though ``currentmodule`` is substituted in, # sphinx doesn't necessarily recognize this fact. So we just force # it internally, and that seems to fix things env.temp_data['py:module'] = modname # can't use super because Sphinx/docutils has trouble return # super(Autosummary,self).run() nodelist.extend(Autosummary.run(self)) return self.warnings + nodelist finally: # has_content = False for the Automodsumm self.content = [] def get_items(self, names): self.genopt['imported-members'] = True return Autosummary.get_items(self, names) #<-------------------automod-diagram stuff------------------------------------> class Automoddiagram(InheritanceDiagram): option_spec = dict(InheritanceDiagram.option_spec) option_spec['allowed-package-names'] = _str_list_converter def run(self): try: ols = self.options.get('allowed-package-names', []) ols = True if len(ols) == 0 else ols # if none are given, assume only local nms, objs = find_mod_objs(self.arguments[0], onlylocals=ols)[1:] except ImportError: self.warnings = [] self.warn("Couldn't import module " + self.arguments[0]) return self.warnings clsnms = [] for n, o in zip(nms, objs): if inspect.isclass(o): clsnms.append(n) oldargs = self.arguments try: if len(clsnms) > 0: self.arguments = [' '.join(clsnms)] return InheritanceDiagram.run(self) finally: self.arguments = oldargs #<---------------------automodsumm generation stuff---------------------------> def process_automodsumm_generation(app): env = app.builder.env filestosearch = [] for docname in env.found_docs: filename = env.doc2path(docname) if os.path.isfile(filename): filestosearch.append(docname + os.path.splitext(filename)[1]) liness = [] for sfn in filestosearch: lines = automodsumm_to_autosummary_lines(sfn, app) liness.append(lines) if app.config.automodsumm_writereprocessed: if lines: # empty list means no automodsumm entry is in the file outfn = os.path.join(app.srcdir, sfn) + '.automodsumm' with open(outfn, 'w') as f: for l in lines: f.write(l) f.write('\n') for sfn, lines in zip(filestosearch, liness): suffix = os.path.splitext(sfn)[1] if len(lines) > 0: generate_automodsumm_docs(lines, sfn, builder=app.builder, warn=app.warn, info=app.info, suffix=suffix, base_path=app.srcdir) #_automodsummrex = re.compile(r'^(\s*)\.\. automodsumm::\s*([A-Za-z0-9_.]+)\s*' # r'\n\1(\s*)(\S|$)', re.MULTILINE) _lineendrex = r'(?:\n|$)' _hdrex = r'^\n?(\s*)\.\. automodsumm::\s*(\S+)\s*' + _lineendrex _oprex1 = r'(?:\1(\s+)\S.*' + _lineendrex + ')' _oprex2 = r'(?:\1\4\S.*' + _lineendrex + ')' _automodsummrex = re.compile(_hdrex + '(' + _oprex1 + '?' + _oprex2 + '*)', re.MULTILINE) def automodsumm_to_autosummary_lines(fn, app): """ Generates lines from a file with an "automodsumm" entry suitable for feeding into "autosummary". Searches the provided file for `automodsumm` directives and returns a list of lines specifying the `autosummary` commands for the modules requested. This does *not* return the whole file contents - just an autosummary section in place of any :automodsumm: entries. Note that any options given for `automodsumm` are also included in the generated `autosummary` section. Parameters ---------- fn : str The name of the file to search for `automodsumm` entries. app : sphinx.application.Application The sphinx Application object Return ------ lines : list of str Lines for all `automodsumm` entries with the entries replaced by `autosummary` and the module's members added. """ fullfn = os.path.join(app.builder.env.srcdir, fn) with open(fullfn) as fr: if 'astropy_helpers.sphinx.ext.automodapi' in app._extensions: from astropy_helpers.sphinx.ext.automodapi import automodapi_replace # Must do the automodapi on the source to get the automodsumm # that might be in there docname = os.path.splitext(fn)[0] filestr = automodapi_replace(fr.read(), app, True, docname, False) else: filestr = fr.read() spl = _automodsummrex.split(filestr) #0th entry is the stuff before the first automodsumm line indent1s = spl[1::5] mods = spl[2::5] opssecs = spl[3::5] indent2s = spl[4::5] remainders = spl[5::5] # only grab automodsumm sections and convert them to autosummary with the # entries for all the public objects newlines = [] #loop over all automodsumms in this document for i, (i1, i2, modnm, ops, rem) in enumerate(zip(indent1s, indent2s, mods, opssecs, remainders)): allindent = i1 + ('' if i2 is None else i2) #filter out functions-only and classes-only options if present oplines = ops.split('\n') toskip = [] allowedpkgnms = [] funcsonly = clssonly = False for i, ln in reversed(list(enumerate(oplines))): if ':functions-only:' in ln: funcsonly = True del oplines[i] if ':classes-only:' in ln: clssonly = True del oplines[i] if ':skip:' in ln: toskip.extend(_str_list_converter(ln.replace(':skip:', ''))) del oplines[i] if ':allowed-package-names:' in ln: allowedpkgnms.extend(_str_list_converter(ln.replace(':allowed-package-names:', ''))) del oplines[i] if funcsonly and clssonly: msg = ('Defined both functions-only and classes-only options. ' 'Skipping this directive.') lnnum = sum([spl[j].count('\n') for j in range(i * 5 + 1)]) app.warn('[automodsumm]' + msg, (fn, lnnum)) continue # Use the currentmodule directive so we can just put the local names # in the autosummary table. Note that this doesn't always seem to # actually "take" in Sphinx's eyes, so in `Automodsumm.run`, we have to # force it internally, as well. newlines.extend([i1 + '.. currentmodule:: ' + modnm, '', '.. autosummary::']) newlines.extend(oplines) ols = True if len(allowedpkgnms) == 0 else allowedpkgnms for nm, fqn, obj in zip(*find_mod_objs(modnm, onlylocals=ols)): if nm in toskip: continue if funcsonly and not inspect.isroutine(obj): continue if clssonly and not inspect.isclass(obj): continue newlines.append(allindent + nm) # add one newline at the end of the autosummary block newlines.append('') return newlines def generate_automodsumm_docs(lines, srcfn, suffix='.rst', warn=None, info=None, base_path=None, builder=None, template_dir=None): """ This function is adapted from `sphinx.ext.autosummary.generate.generate_autosummmary_docs` to generate source for the automodsumm directives that should be autosummarized. Unlike generate_autosummary_docs, this function is called one file at a time. """ from sphinx.jinja2glue import BuiltinTemplateLoader from sphinx.ext.autosummary import import_by_name, get_documenter from sphinx.ext.autosummary.generate import (find_autosummary_in_lines, _simple_info, _simple_warn) from sphinx.util.osutil import ensuredir from sphinx.util.inspect import safe_getattr from jinja2 import FileSystemLoader, TemplateNotFound from jinja2.sandbox import SandboxedEnvironment if info is None: info = _simple_info if warn is None: warn = _simple_warn #info('[automodsumm] generating automodsumm for: ' + srcfn) # Create our own templating environment - here we use Astropy's # templates rather than the default autosummary templates, in order to # allow docstrings to be shown for methods. template_dirs = [os.path.join(os.path.dirname(__file__), 'templates'), os.path.join(base_path, '_templates')] if builder is not None: # allow the user to override the templates template_loader = BuiltinTemplateLoader() template_loader.init(builder, dirs=template_dirs) else: if template_dir: template_dirs.insert(0, template_dir) template_loader = FileSystemLoader(template_dirs) template_env = SandboxedEnvironment(loader=template_loader) # read #items = find_autosummary_in_files(sources) items = find_autosummary_in_lines(lines, filename=srcfn) if len(items) > 0: msg = '[automodsumm] {1}: found {0} automodsumm entries to generate' info(msg.format(len(items), srcfn)) # gennms = [item[0] for item in items] # if len(gennms) > 20: # gennms = gennms[:10] + ['...'] + gennms[-10:] # info('[automodsumm] generating autosummary for: ' + ', '.join(gennms)) # remove possible duplicates items = dict([(item, True) for item in items]).keys() # keep track of new files new_files = [] # write for name, path, template_name in sorted(items): if path is None: # The corresponding autosummary:: directive did not have # a :toctree: option continue path = os.path.abspath(path) ensuredir(path) try: import_by_name_values = import_by_name(name) except ImportError as e: warn('[automodsumm] failed to import %r: %s' % (name, e)) continue # if block to accommodate Sphinx's v1.2.2 and v1.2.3 respectively if len(import_by_name_values) == 3: name, obj, parent = import_by_name_values elif len(import_by_name_values) == 4: name, obj, parent, module_name = import_by_name_values fn = os.path.join(path, name + suffix) # skip it if it exists if os.path.isfile(fn): continue new_files.append(fn) f = open(fn, 'w') try: doc = get_documenter(obj, parent) if template_name is not None: template = template_env.get_template(template_name) else: tmplstr = 'autosummary/%s.rst' try: template = template_env.get_template(tmplstr % doc.objtype) except TemplateNotFound: template = template_env.get_template(tmplstr % 'base') def get_members_mod(obj, typ, include_public=[]): """ typ = None -> all """ items = [] for name in dir(obj): try: documenter = get_documenter(safe_getattr(obj, name), obj) except AttributeError: continue if typ is None or documenter.objtype == typ: items.append(name) public = [x for x in items if x in include_public or not x.startswith('_')] return public, items def get_members_class(obj, typ, include_public=[], include_base=False): """ typ = None -> all include_base -> include attrs that are from a base class """ items = [] # using dir gets all of the attributes, including the elements # from the base class, otherwise use __slots__ or __dict__ if include_base: names = dir(obj) else: if hasattr(obj, '__slots__'): names = tuple(getattr(obj, '__slots__')) else: names = getattr(obj, '__dict__').keys() for name in names: try: documenter = get_documenter(safe_getattr(obj, name), obj) except AttributeError: continue if typ is None or documenter.objtype == typ: items.append(name) public = [x for x in items if x in include_public or not x.startswith('_')] return public, items ns = {} if doc.objtype == 'module': ns['members'] = get_members_mod(obj, None) ns['functions'], ns['all_functions'] = \ get_members_mod(obj, 'function') ns['classes'], ns['all_classes'] = \ get_members_mod(obj, 'class') ns['exceptions'], ns['all_exceptions'] = \ get_members_mod(obj, 'exception') elif doc.objtype == 'class': api_class_methods = ['__init__', '__call__'] ns['members'] = get_members_class(obj, None) ns['methods'], ns['all_methods'] = \ get_members_class(obj, 'method', api_class_methods) ns['attributes'], ns['all_attributes'] = \ get_members_class(obj, 'attribute') ns['methods'].sort() ns['attributes'].sort() parts = name.split('.') if doc.objtype in ('method', 'attribute'): mod_name = '.'.join(parts[:-2]) cls_name = parts[-2] obj_name = '.'.join(parts[-2:]) ns['class'] = cls_name else: mod_name, obj_name = '.'.join(parts[:-1]), parts[-1] ns['fullname'] = name ns['module'] = mod_name ns['objname'] = obj_name ns['name'] = parts[-1] ns['objtype'] = doc.objtype ns['underline'] = len(name) * '=' # We now check whether a file for reference footnotes exists for # the module being documented. We first check if the # current module is a file or a directory, as this will give a # different path for the reference file. For example, if # documenting astropy.wcs then the reference file is at # ../wcs/references.txt, while if we are documenting # astropy.config.logging_helper (which is at # astropy/config/logging_helper.py) then the reference file is set # to ../config/references.txt if '.' in mod_name: mod_name_dir = mod_name.replace('.', '/').split('/', 1)[1] else: mod_name_dir = mod_name if not os.path.isdir(os.path.join(base_path, mod_name_dir)) \ and os.path.isdir(os.path.join(base_path, mod_name_dir.rsplit('/', 1)[0])): mod_name_dir = mod_name_dir.rsplit('/', 1)[0] # We then have to check whether it exists, and if so, we pass it # to the template. if os.path.exists(os.path.join(base_path, mod_name_dir, 'references.txt')): # An important subtlety here is that the path we pass in has # to be relative to the file being generated, so we have to # figure out the right number of '..'s ndirsback = path.replace(base_path, '').count('/') ref_file_rel_segments = ['..'] * ndirsback ref_file_rel_segments.append(mod_name_dir) ref_file_rel_segments.append('references.txt') ns['referencefile'] = os.path.join(*ref_file_rel_segments) rendered = template.render(**ns) f.write(rendered) finally: f.close() def setup(app): # need our autosummary app.setup_extension('astropy_helpers.sphinx.ext.astropyautosummary') # need inheritance-diagram for automod-diagram app.setup_extension('sphinx.ext.inheritance_diagram') app.add_directive('automod-diagram', Automoddiagram) app.add_directive('automodsumm', Automodsumm) app.connect('builder-inited', process_automodsumm_generation) app.add_config_value('automodsumm_writereprocessed', False, True) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/changelog_links.py0000644000077000000240000000542012414703152027232 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This sphinx extension makes the issue numbers in the changelog into links to GitHub issues. """ from __future__ import print_function import re from docutils.nodes import Text, reference BLOCK_PATTERN = re.compile('\[#.+\]', flags=re.DOTALL) ISSUE_PATTERN = re.compile('#[0-9]+') def process_changelog_links(app, doctree, docname): for rex in app.changelog_links_rexes: if rex.match(docname): break else: # if the doc doesn't match any of the changelog regexes, don't process return app.info('[changelog_links] Adding changelog links to "{0}"'.format(docname)) for item in doctree.traverse(): if not isinstance(item, Text): continue # We build a new list of items to replace the current item. If # a link is found, we need to use a 'reference' item. children = [] # First cycle through blocks of issues (delimited by []) then # iterate inside each one to find the individual issues. prev_block_end = 0 for block in BLOCK_PATTERN.finditer(item): block_start, block_end = block.start(), block.end() children.append(Text(item[prev_block_end:block_start])) block = item[block_start:block_end] prev_end = 0 for m in ISSUE_PATTERN.finditer(block): start, end = m.start(), m.end() children.append(Text(block[prev_end:start])) issue_number = block[start:end] refuri = app.config.github_issues_url + issue_number[1:] children.append(reference(text=issue_number, name=issue_number, refuri=refuri)) prev_end = end prev_block_end = block_end # If no issues were found, this adds the whole item, # otherwise it adds the remaining text. children.append(Text(block[prev_end:block_end])) # If no blocks were found, this adds the whole item, otherwise # it adds the remaining text. children.append(Text(item[prev_block_end:])) # Replace item by the new list of items we have generated, # which may contain links. item.parent.replace(item, children) def setup_patterns_rexes(app): app.changelog_links_rexes = [re.compile(pat) for pat in app.config.changelog_links_docpattern] def setup(app): app.connect('doctree-resolved', process_changelog_links) app.connect('builder-inited', setup_patterns_rexes) app.add_config_value('github_issues_url', None, True) app.add_config_value('changelog_links_docpattern', ['.*changelog.*', 'whatsnew/.*'], True) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/comment_eater.py0000644000077000000240000001245112346274067026743 0ustar tomstaff00000000000000from __future__ import division, absolute_import, print_function import sys if sys.version_info[0] >= 3: from io import StringIO else: from io import StringIO import compiler import inspect import textwrap import tokenize from .compiler_unparse import unparse class Comment(object): """ A comment block. """ is_comment = True def __init__(self, start_lineno, end_lineno, text): # int : The first line number in the block. 1-indexed. self.start_lineno = start_lineno # int : The last line number. Inclusive! self.end_lineno = end_lineno # str : The text block including '#' character but not any leading spaces. self.text = text def add(self, string, start, end, line): """ Add a new comment line. """ self.start_lineno = min(self.start_lineno, start[0]) self.end_lineno = max(self.end_lineno, end[0]) self.text += string def __repr__(self): return '%s(%r, %r, %r)' % (self.__class__.__name__, self.start_lineno, self.end_lineno, self.text) class NonComment(object): """ A non-comment block of code. """ is_comment = False def __init__(self, start_lineno, end_lineno): self.start_lineno = start_lineno self.end_lineno = end_lineno def add(self, string, start, end, line): """ Add lines to the block. """ if string.strip(): # Only add if not entirely whitespace. self.start_lineno = min(self.start_lineno, start[0]) self.end_lineno = max(self.end_lineno, end[0]) def __repr__(self): return '%s(%r, %r)' % (self.__class__.__name__, self.start_lineno, self.end_lineno) class CommentBlocker(object): """ Pull out contiguous comment blocks. """ def __init__(self): # Start with a dummy. self.current_block = NonComment(0, 0) # All of the blocks seen so far. self.blocks = [] # The index mapping lines of code to their associated comment blocks. self.index = {} def process_file(self, file): """ Process a file object. """ if sys.version_info[0] >= 3: nxt = file.__next__ else: nxt = file.next for token in tokenize.generate_tokens(nxt): self.process_token(*token) self.make_index() def process_token(self, kind, string, start, end, line): """ Process a single token. """ if self.current_block.is_comment: if kind == tokenize.COMMENT: self.current_block.add(string, start, end, line) else: self.new_noncomment(start[0], end[0]) else: if kind == tokenize.COMMENT: self.new_comment(string, start, end, line) else: self.current_block.add(string, start, end, line) def new_noncomment(self, start_lineno, end_lineno): """ We are transitioning from a noncomment to a comment. """ block = NonComment(start_lineno, end_lineno) self.blocks.append(block) self.current_block = block def new_comment(self, string, start, end, line): """ Possibly add a new comment. Only adds a new comment if this comment is the only thing on the line. Otherwise, it extends the noncomment block. """ prefix = line[:start[1]] if prefix.strip(): # Oops! Trailing comment, not a comment block. self.current_block.add(string, start, end, line) else: # A comment block. block = Comment(start[0], end[0], string) self.blocks.append(block) self.current_block = block def make_index(self): """ Make the index mapping lines of actual code to their associated prefix comments. """ for prev, block in zip(self.blocks[:-1], self.blocks[1:]): if not block.is_comment: self.index[block.start_lineno] = prev def search_for_comment(self, lineno, default=None): """ Find the comment block just before the given line number. Returns None (or the specified default) if there is no such block. """ if not self.index: self.make_index() block = self.index.get(lineno, None) text = getattr(block, 'text', default) return text def strip_comment_marker(text): """ Strip # markers at the front of a block of comment text. """ lines = [] for line in text.splitlines(): lines.append(line.lstrip('#')) text = textwrap.dedent('\n'.join(lines)) return text def get_class_traits(klass): """ Yield all of the documentation for trait definitions on a class object. """ # FIXME: gracefully handle errors here or in the caller? source = inspect.getsource(klass) cb = CommentBlocker() cb.process_file(StringIO(source)) mod_ast = compiler.parse(source) class_ast = mod_ast.node.nodes[0] for node in class_ast.code.nodes: # FIXME: handle other kinds of assignments? if isinstance(node, compiler.ast.Assign): name = node.nodes[0].name rhs = unparse(node.expr).strip() doc = strip_comment_marker(cb.search_for_comment(node.lineno, default='')) yield name, rhs, doc wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/compiler_unparse.py0000644000077000000240000006024412346274067027473 0ustar tomstaff00000000000000""" Turn compiler.ast structures back into executable python code. The unparse method takes a compiler.ast tree and transforms it back into valid python code. It is incomplete and currently only works for import statements, function calls, function definitions, assignments, and basic expressions. Inspired by python-2.5-svn/Demo/parser/unparse.py fixme: We may want to move to using _ast trees because the compiler for them is about 6 times faster than compiler.compile. """ from __future__ import division, absolute_import, print_function import sys from compiler.ast import Const, Name, Tuple, Div, Mul, Sub, Add if sys.version_info[0] >= 3: from io import StringIO else: from StringIO import StringIO def unparse(ast, single_line_functions=False): s = StringIO() UnparseCompilerAst(ast, s, single_line_functions) return s.getvalue().lstrip() op_precedence = { 'compiler.ast.Power':3, 'compiler.ast.Mul':2, 'compiler.ast.Div':2, 'compiler.ast.Add':1, 'compiler.ast.Sub':1 } class UnparseCompilerAst: """ Methods in this class recursively traverse an AST and output source code for the abstract syntax; original formatting is disregarged. """ ######################################################################### # object interface. ######################################################################### def __init__(self, tree, file = sys.stdout, single_line_functions=False): """ Unparser(tree, file=sys.stdout) -> None. Print the source for tree to file. """ self.f = file self._single_func = single_line_functions self._do_indent = True self._indent = 0 self._dispatch(tree) self._write("\n") self.f.flush() ######################################################################### # Unparser private interface. ######################################################################### ### format, output, and dispatch methods ################################ def _fill(self, text = ""): "Indent a piece of text, according to the current indentation level" if self._do_indent: self._write("\n"+" "*self._indent + text) else: self._write(text) def _write(self, text): "Append a piece of text to the current line." self.f.write(text) def _enter(self): "Print ':', and increase the indentation." self._write(": ") self._indent += 1 def _leave(self): "Decrease the indentation level." self._indent -= 1 def _dispatch(self, tree): "_dispatcher function, _dispatching tree type T to method _T." if isinstance(tree, list): for t in tree: self._dispatch(t) return meth = getattr(self, "_"+tree.__class__.__name__) if tree.__class__.__name__ == 'NoneType' and not self._do_indent: return meth(tree) ######################################################################### # compiler.ast unparsing methods. # # There should be one method per concrete grammar type. They are # organized in alphabetical order. ######################################################################### def _Add(self, t): self.__binary_op(t, '+') def _And(self, t): self._write(" (") for i, node in enumerate(t.nodes): self._dispatch(node) if i != len(t.nodes)-1: self._write(") and (") self._write(")") def _AssAttr(self, t): """ Handle assigning an attribute of an object """ self._dispatch(t.expr) self._write('.'+t.attrname) def _Assign(self, t): """ Expression Assignment such as "a = 1". This only handles assignment in expressions. Keyword assignment is handled separately. """ self._fill() for target in t.nodes: self._dispatch(target) self._write(" = ") self._dispatch(t.expr) if not self._do_indent: self._write('; ') def _AssName(self, t): """ Name on left hand side of expression. Treat just like a name on the right side of an expression. """ self._Name(t) def _AssTuple(self, t): """ Tuple on left hand side of an expression. """ # _write each elements, separated by a comma. for element in t.nodes[:-1]: self._dispatch(element) self._write(", ") # Handle the last one without writing comma last_element = t.nodes[-1] self._dispatch(last_element) def _AugAssign(self, t): """ +=,-=,*=,/=,**=, etc. operations """ self._fill() self._dispatch(t.node) self._write(' '+t.op+' ') self._dispatch(t.expr) if not self._do_indent: self._write(';') def _Bitand(self, t): """ Bit and operation. """ for i, node in enumerate(t.nodes): self._write("(") self._dispatch(node) self._write(")") if i != len(t.nodes)-1: self._write(" & ") def _Bitor(self, t): """ Bit or operation """ for i, node in enumerate(t.nodes): self._write("(") self._dispatch(node) self._write(")") if i != len(t.nodes)-1: self._write(" | ") def _CallFunc(self, t): """ Function call. """ self._dispatch(t.node) self._write("(") comma = False for e in t.args: if comma: self._write(", ") else: comma = True self._dispatch(e) if t.star_args: if comma: self._write(", ") else: comma = True self._write("*") self._dispatch(t.star_args) if t.dstar_args: if comma: self._write(", ") else: comma = True self._write("**") self._dispatch(t.dstar_args) self._write(")") def _Compare(self, t): self._dispatch(t.expr) for op, expr in t.ops: self._write(" " + op + " ") self._dispatch(expr) def _Const(self, t): """ A constant value such as an integer value, 3, or a string, "hello". """ self._dispatch(t.value) def _Decorators(self, t): """ Handle function decorators (eg. @has_units) """ for node in t.nodes: self._dispatch(node) def _Dict(self, t): self._write("{") for i, (k, v) in enumerate(t.items): self._dispatch(k) self._write(": ") self._dispatch(v) if i < len(t.items)-1: self._write(", ") self._write("}") def _Discard(self, t): """ Node for when return value is ignored such as in "foo(a)". """ self._fill() self._dispatch(t.expr) def _Div(self, t): self.__binary_op(t, '/') def _Ellipsis(self, t): self._write("...") def _From(self, t): """ Handle "from xyz import foo, bar as baz". """ # fixme: Are From and ImportFrom handled differently? self._fill("from ") self._write(t.modname) self._write(" import ") for i, (name,asname) in enumerate(t.names): if i != 0: self._write(", ") self._write(name) if asname is not None: self._write(" as "+asname) def _Function(self, t): """ Handle function definitions """ if t.decorators is not None: self._fill("@") self._dispatch(t.decorators) self._fill("def "+t.name + "(") defaults = [None] * (len(t.argnames) - len(t.defaults)) + list(t.defaults) for i, arg in enumerate(zip(t.argnames, defaults)): self._write(arg[0]) if arg[1] is not None: self._write('=') self._dispatch(arg[1]) if i < len(t.argnames)-1: self._write(', ') self._write(")") if self._single_func: self._do_indent = False self._enter() self._dispatch(t.code) self._leave() self._do_indent = True def _Getattr(self, t): """ Handle getting an attribute of an object """ if isinstance(t.expr, (Div, Mul, Sub, Add)): self._write('(') self._dispatch(t.expr) self._write(')') else: self._dispatch(t.expr) self._write('.'+t.attrname) def _If(self, t): self._fill() for i, (compare,code) in enumerate(t.tests): if i == 0: self._write("if ") else: self._write("elif ") self._dispatch(compare) self._enter() self._fill() self._dispatch(code) self._leave() self._write("\n") if t.else_ is not None: self._write("else") self._enter() self._fill() self._dispatch(t.else_) self._leave() self._write("\n") def _IfExp(self, t): self._dispatch(t.then) self._write(" if ") self._dispatch(t.test) if t.else_ is not None: self._write(" else (") self._dispatch(t.else_) self._write(")") def _Import(self, t): """ Handle "import xyz.foo". """ self._fill("import ") for i, (name,asname) in enumerate(t.names): if i != 0: self._write(", ") self._write(name) if asname is not None: self._write(" as "+asname) def _Keyword(self, t): """ Keyword value assignment within function calls and definitions. """ self._write(t.name) self._write("=") self._dispatch(t.expr) def _List(self, t): self._write("[") for i,node in enumerate(t.nodes): self._dispatch(node) if i < len(t.nodes)-1: self._write(", ") self._write("]") def _Module(self, t): if t.doc is not None: self._dispatch(t.doc) self._dispatch(t.node) def _Mul(self, t): self.__binary_op(t, '*') def _Name(self, t): self._write(t.name) def _NoneType(self, t): self._write("None") def _Not(self, t): self._write('not (') self._dispatch(t.expr) self._write(')') def _Or(self, t): self._write(" (") for i, node in enumerate(t.nodes): self._dispatch(node) if i != len(t.nodes)-1: self._write(") or (") self._write(")") def _Pass(self, t): self._write("pass\n") def _Printnl(self, t): self._fill("print ") if t.dest: self._write(">> ") self._dispatch(t.dest) self._write(", ") comma = False for node in t.nodes: if comma: self._write(', ') else: comma = True self._dispatch(node) def _Power(self, t): self.__binary_op(t, '**') def _Return(self, t): self._fill("return ") if t.value: if isinstance(t.value, Tuple): text = ', '.join([ name.name for name in t.value.asList() ]) self._write(text) else: self._dispatch(t.value) if not self._do_indent: self._write('; ') def _Slice(self, t): self._dispatch(t.expr) self._write("[") if t.lower: self._dispatch(t.lower) self._write(":") if t.upper: self._dispatch(t.upper) #if t.step: # self._write(":") # self._dispatch(t.step) self._write("]") def _Sliceobj(self, t): for i, node in enumerate(t.nodes): if i != 0: self._write(":") if not (isinstance(node, Const) and node.value is None): self._dispatch(node) def _Stmt(self, tree): for node in tree.nodes: self._dispatch(node) def _Sub(self, t): self.__binary_op(t, '-') def _Subscript(self, t): self._dispatch(t.expr) self._write("[") for i, value in enumerate(t.subs): if i != 0: self._write(",") self._dispatch(value) self._write("]") def _TryExcept(self, t): self._fill("try") self._enter() self._dispatch(t.body) self._leave() for handler in t.handlers: self._fill('except ') self._dispatch(handler[0]) if handler[1] is not None: self._write(', ') self._dispatch(handler[1]) self._enter() self._dispatch(handler[2]) self._leave() if t.else_: self._fill("else") self._enter() self._dispatch(t.else_) self._leave() def _Tuple(self, t): if not t.nodes: # Empty tuple. self._write("()") else: self._write("(") # _write each elements, separated by a comma. for element in t.nodes[:-1]: self._dispatch(element) self._write(", ") # Handle the last one without writing comma last_element = t.nodes[-1] self._dispatch(last_element) self._write(")") def _UnaryAdd(self, t): self._write("+") self._dispatch(t.expr) def _UnarySub(self, t): self._write("-") self._dispatch(t.expr) def _With(self, t): self._fill('with ') self._dispatch(t.expr) if t.vars: self._write(' as ') self._dispatch(t.vars.name) self._enter() self._dispatch(t.body) self._leave() self._write('\n') def _int(self, t): self._write(repr(t)) def __binary_op(self, t, symbol): # Check if parenthesis are needed on left side and then dispatch has_paren = False left_class = str(t.left.__class__) if (left_class in op_precedence.keys() and op_precedence[left_class] < op_precedence[str(t.__class__)]): has_paren = True if has_paren: self._write('(') self._dispatch(t.left) if has_paren: self._write(')') # Write the appropriate symbol for operator self._write(symbol) # Check if parenthesis are needed on the right side and then dispatch has_paren = False right_class = str(t.right.__class__) if (right_class in op_precedence.keys() and op_precedence[right_class] < op_precedence[str(t.__class__)]): has_paren = True if has_paren: self._write('(') self._dispatch(t.right) if has_paren: self._write(')') def _float(self, t): # if t is 0.1, str(t)->'0.1' while repr(t)->'0.1000000000001' # We prefer str here. self._write(str(t)) def _str(self, t): self._write(repr(t)) def _tuple(self, t): self._write(str(t)) ######################################################################### # These are the methods from the _ast modules unparse. # # As our needs to handle more advanced code increase, we may want to # modify some of the methods below so that they work for compiler.ast. ######################################################################### # # stmt # def _Expr(self, tree): # self._fill() # self._dispatch(tree.value) # # def _Import(self, t): # self._fill("import ") # first = True # for a in t.names: # if first: # first = False # else: # self._write(", ") # self._write(a.name) # if a.asname: # self._write(" as "+a.asname) # ## def _ImportFrom(self, t): ## self._fill("from ") ## self._write(t.module) ## self._write(" import ") ## for i, a in enumerate(t.names): ## if i == 0: ## self._write(", ") ## self._write(a.name) ## if a.asname: ## self._write(" as "+a.asname) ## # XXX(jpe) what is level for? ## # # def _Break(self, t): # self._fill("break") # # def _Continue(self, t): # self._fill("continue") # # def _Delete(self, t): # self._fill("del ") # self._dispatch(t.targets) # # def _Assert(self, t): # self._fill("assert ") # self._dispatch(t.test) # if t.msg: # self._write(", ") # self._dispatch(t.msg) # # def _Exec(self, t): # self._fill("exec ") # self._dispatch(t.body) # if t.globals: # self._write(" in ") # self._dispatch(t.globals) # if t.locals: # self._write(", ") # self._dispatch(t.locals) # # def _Print(self, t): # self._fill("print ") # do_comma = False # if t.dest: # self._write(">>") # self._dispatch(t.dest) # do_comma = True # for e in t.values: # if do_comma:self._write(", ") # else:do_comma=True # self._dispatch(e) # if not t.nl: # self._write(",") # # def _Global(self, t): # self._fill("global") # for i, n in enumerate(t.names): # if i != 0: # self._write(",") # self._write(" " + n) # # def _Yield(self, t): # self._fill("yield") # if t.value: # self._write(" (") # self._dispatch(t.value) # self._write(")") # # def _Raise(self, t): # self._fill('raise ') # if t.type: # self._dispatch(t.type) # if t.inst: # self._write(", ") # self._dispatch(t.inst) # if t.tback: # self._write(", ") # self._dispatch(t.tback) # # # def _TryFinally(self, t): # self._fill("try") # self._enter() # self._dispatch(t.body) # self._leave() # # self._fill("finally") # self._enter() # self._dispatch(t.finalbody) # self._leave() # # def _excepthandler(self, t): # self._fill("except ") # if t.type: # self._dispatch(t.type) # if t.name: # self._write(", ") # self._dispatch(t.name) # self._enter() # self._dispatch(t.body) # self._leave() # # def _ClassDef(self, t): # self._write("\n") # self._fill("class "+t.name) # if t.bases: # self._write("(") # for a in t.bases: # self._dispatch(a) # self._write(", ") # self._write(")") # self._enter() # self._dispatch(t.body) # self._leave() # # def _FunctionDef(self, t): # self._write("\n") # for deco in t.decorators: # self._fill("@") # self._dispatch(deco) # self._fill("def "+t.name + "(") # self._dispatch(t.args) # self._write(")") # self._enter() # self._dispatch(t.body) # self._leave() # # def _For(self, t): # self._fill("for ") # self._dispatch(t.target) # self._write(" in ") # self._dispatch(t.iter) # self._enter() # self._dispatch(t.body) # self._leave() # if t.orelse: # self._fill("else") # self._enter() # self._dispatch(t.orelse) # self._leave # # def _While(self, t): # self._fill("while ") # self._dispatch(t.test) # self._enter() # self._dispatch(t.body) # self._leave() # if t.orelse: # self._fill("else") # self._enter() # self._dispatch(t.orelse) # self._leave # # # expr # def _Str(self, tree): # self._write(repr(tree.s)) ## # def _Repr(self, t): # self._write("`") # self._dispatch(t.value) # self._write("`") # # def _Num(self, t): # self._write(repr(t.n)) # # def _ListComp(self, t): # self._write("[") # self._dispatch(t.elt) # for gen in t.generators: # self._dispatch(gen) # self._write("]") # # def _GeneratorExp(self, t): # self._write("(") # self._dispatch(t.elt) # for gen in t.generators: # self._dispatch(gen) # self._write(")") # # def _comprehension(self, t): # self._write(" for ") # self._dispatch(t.target) # self._write(" in ") # self._dispatch(t.iter) # for if_clause in t.ifs: # self._write(" if ") # self._dispatch(if_clause) # # def _IfExp(self, t): # self._dispatch(t.body) # self._write(" if ") # self._dispatch(t.test) # if t.orelse: # self._write(" else ") # self._dispatch(t.orelse) # # unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"} # def _UnaryOp(self, t): # self._write(self.unop[t.op.__class__.__name__]) # self._write("(") # self._dispatch(t.operand) # self._write(")") # # binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%", # "LShift":">>", "RShift":"<<", "BitOr":"|", "BitXor":"^", "BitAnd":"&", # "FloorDiv":"//", "Pow": "**"} # def _BinOp(self, t): # self._write("(") # self._dispatch(t.left) # self._write(")" + self.binop[t.op.__class__.__name__] + "(") # self._dispatch(t.right) # self._write(")") # # boolops = {_ast.And: 'and', _ast.Or: 'or'} # def _BoolOp(self, t): # self._write("(") # self._dispatch(t.values[0]) # for v in t.values[1:]: # self._write(" %s " % self.boolops[t.op.__class__]) # self._dispatch(v) # self._write(")") # # def _Attribute(self,t): # self._dispatch(t.value) # self._write(".") # self._write(t.attr) # ## def _Call(self, t): ## self._dispatch(t.func) ## self._write("(") ## comma = False ## for e in t.args: ## if comma: self._write(", ") ## else: comma = True ## self._dispatch(e) ## for e in t.keywords: ## if comma: self._write(", ") ## else: comma = True ## self._dispatch(e) ## if t.starargs: ## if comma: self._write(", ") ## else: comma = True ## self._write("*") ## self._dispatch(t.starargs) ## if t.kwargs: ## if comma: self._write(", ") ## else: comma = True ## self._write("**") ## self._dispatch(t.kwargs) ## self._write(")") # # # slice # def _Index(self, t): # self._dispatch(t.value) # # def _ExtSlice(self, t): # for i, d in enumerate(t.dims): # if i != 0: # self._write(': ') # self._dispatch(d) # # # others # def _arguments(self, t): # first = True # nonDef = len(t.args)-len(t.defaults) # for a in t.args[0:nonDef]: # if first:first = False # else: self._write(", ") # self._dispatch(a) # for a,d in zip(t.args[nonDef:], t.defaults): # if first:first = False # else: self._write(", ") # self._dispatch(a), # self._write("=") # self._dispatch(d) # if t.vararg: # if first:first = False # else: self._write(", ") # self._write("*"+t.vararg) # if t.kwarg: # if first:first = False # else: self._write(", ") # self._write("**"+t.kwarg) # ## def _keyword(self, t): ## self._write(t.arg) ## self._write("=") ## self._dispatch(t.value) # # def _Lambda(self, t): # self._write("lambda ") # self._dispatch(t.args) # self._write(": ") # self._dispatch(t.body) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/docscrape.py0000644000077000000240000003771312346274067026074 0ustar tomstaff00000000000000"""Extract reference documentation from the NumPy source tree. """ from __future__ import division, absolute_import, print_function import inspect import textwrap import re import pydoc from warnings import warn import collections import sys 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 key not in self._parsed_data: 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(','): if func.strip(): 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 # If several signatures present, take the last one while True: 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(): continue break if summary is not None: 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', 'Returns', 'Raises', 'Warns', 'Other Parameters', 'Attributes', 'Methods'): 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]: if param_type: out += ['%s : %s' % (param, param_type)] else: out += [param] 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', 'Other Parameters', 'Raises', 'Warns'): 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 if sys.version_info[0] >= 3: argspec = inspect.getfullargspec(func) else: argspec = inspect.getargspec(func) argspec = inspect.formatargspec(*argspec) argspec = argspec.replace('*','\*') signature = '%s%s' % (func_name, argspec) except TypeError as 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 self._role not in roles: 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): extra_public_methods = ['__call__'] 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): def splitlines_x(s): if not s: return [] else: return s.splitlines() for field, items in [('Methods', self.methods), ('Attributes', self.properties)]: if not self[field]: doc_list = [] for name in sorted(items): try: doc_item = pydoc.getdoc(getattr(self._cls, name)) doc_list.append((name, '', splitlines_x(doc_item))) except AttributeError: pass # method doesn't exist self[field] = doc_list @property def methods(self): if self._cls is None: return [] return [name for name,func in inspect.getmembers(self._cls) if ((not name.startswith('_') or name in self.extra_public_methods) and isinstance(func, collections.Callable))] @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 or isinstance(func, property) or inspect.isgetsetdescriptor(func))] wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/docscrape_sphinx.py0000644000077000000240000002233512346274067027457 0ustar tomstaff00000000000000from __future__ import division, absolute_import, print_function import sys, re, inspect, textwrap, pydoc import sphinx import collections from .docscrape import NumpyDocString, FunctionDoc, ClassDoc if sys.version_info[0] >= 3: sixu = lambda s: s else: sixu = lambda s: unicode(s, 'unicode_escape') class SphinxDocString(NumpyDocString): def __init__(self, docstring, config={}): NumpyDocString.__init__(self, docstring, config=config) self.load_config(config) def load_config(self, config): self.use_plots = config.get('use_plots', False) self.class_members_toctree = config.get('class_members_toctree', True) # 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_returns(self): out = [] if self['Returns']: out += self._str_field_list('Returns') out += [''] for param, param_type, desc in self['Returns']: if param_type: out += self._str_indent(['**%s** : %s' % (param.strip(), param_type)]) else: out += self._str_indent([param.strip()]) if desc: out += [''] out += self._str_indent(desc, 8) out += [''] return out 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]: if param_type: out += self._str_indent(['**%s** : %s' % (param.strip(), param_type)]) else: out += self._str_indent(['**%s**' % param.strip()]) if desc: 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() # Check if the referenced member can have a docstring or not param_obj = getattr(self._obj, param, None) if not (callable(param_obj) or isinstance(param_obj, property) or inspect.isgetsetdescriptor(param_obj)): param_obj = None if param_obj and (pydoc.getdoc(param_obj) or not desc): # Referenced object has a docstring autosum += [" %s%s" % (prefix, param)] else: others.append((param, param_type, desc)) if autosum: out += ['.. autosummary::'] if self.class_members_toctree: out += [' :toctree:'] out += [''] + autosum if others: maxlen_0 = max(3, max([len(x[0]) for x in others])) hdr = sixu("=")*maxlen_0 + sixu(" ") + sixu("=")*10 fmt = sixu('%%%ds %%s ') % (maxlen_0,) out += ['', hdr] for param, param_type, desc in others: desc = sixu(" ").join(x.strip() for x in desc).strip() if param_type: desc = "(%s) %s" % (param_type, desc) out += [fmt % (param.strip(), desc)] 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() out += self._str_param_list('Parameters') out += self._str_returns() for param_list in ('Other Parameters', 'Raises', 'Warns'): 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.load_config(config) FunctionDoc.__init__(self, obj, doc=doc, config=config) class SphinxClassDoc(SphinxDocString, ClassDoc): def __init__(self, obj, doc=None, func_doc=None, config={}): self.load_config(config) ClassDoc.__init__(self, obj, doc=doc, func_doc=None, config=config) class SphinxObjDoc(SphinxDocString): def __init__(self, obj, doc=None, config={}): self._f = obj self.load_config(config) 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 isinstance(obj, collections.Callable): 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) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/doctest.py0000644000077000000240000000243612417312170025553 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This is a set of three directives that allow us to insert metadata about doctests into the .rst files so the testing framework knows which tests to skip. This is quite different from the doctest extension in Sphinx itself, which actually does something. For astropy, all of the testing is centrally managed from py.test and Sphinx is not used for running tests. """ import re from docutils.nodes import literal_block from sphinx.util.compat import Directive class DoctestSkipDirective(Directive): has_content = True def run(self): # Check if there is any valid argument, and skip it. Currently only # 'win32' is supported in astropy.tests.pytest_plugins. if re.match('win32', self.content[0]): self.content = self.content[2:] code = '\n'.join(self.content) return [literal_block(code, code)] class DoctestRequiresDirective(DoctestSkipDirective): # This is silly, but we really support an unbounded number of # optional arguments optional_arguments = 64 def setup(app): app.add_directive('doctest-requires', DoctestRequiresDirective) app.add_directive('doctest-skip', DoctestSkipDirective) app.add_directive('doctest-skip-all', DoctestSkipDirective) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/edit_on_github.py0000644000077000000240000001340712414703152027072 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This extension makes it easy to edit documentation on github. It adds links associated with each docstring that go to the corresponding view source page on Github. From there, the user can push the "Edit" button, edit the docstring, and submit a pull request. It has the following configuration options (to be set in the project's ``conf.py``): * ``edit_on_github_project`` The name of the github project, in the form "username/projectname". * ``edit_on_github_branch`` The name of the branch to edit. If this is a released version, this should be a git tag referring to that version. For a dev version, it often makes sense for it to be "master". It may also be a git hash. * ``edit_on_github_source_root`` The location within the source tree of the root of the Python package. Defaults to "lib". * ``edit_on_github_doc_root`` The location within the source tree of the root of the documentation source. Defaults to "doc", but it may make sense to set it to "doc/source" if the project uses a separate source directory. * ``edit_on_github_docstring_message`` The phrase displayed in the links to edit a docstring. Defaults to "[edit on github]". * ``edit_on_github_page_message`` The phrase displayed in the links to edit a RST page. Defaults to "[edit this page on github]". * ``edit_on_github_help_message`` The phrase displayed as a tooltip on the edit links. Defaults to "Push the Edit button on the next page" * ``edit_on_github_skip_regex`` When the path to the .rst file matches this regular expression, no "edit this page on github" link will be added. Defaults to ``"_.*"``. """ import inspect import os import re import sys from docutils import nodes from sphinx import addnodes def import_object(modname, name): """ Import the object given by *modname* and *name* and return it. If not found, or the import fails, returns None. """ try: __import__(modname) mod = sys.modules[modname] obj = mod for part in name.split('.'): obj = getattr(obj, part) return obj except: return None def get_url_base(app): return 'http://github.com/%s/tree/%s/' % ( app.config.edit_on_github_project, app.config.edit_on_github_branch) def doctree_read(app, doctree): # Get the configuration parameters if app.config.edit_on_github_project == 'REQUIRED': raise ValueError( "The edit_on_github_project configuration variable must be " "provided in the conf.py") source_root = app.config.edit_on_github_source_root url = get_url_base(app) docstring_message = app.config.edit_on_github_docstring_message # Handle the docstring-editing links for objnode in doctree.traverse(addnodes.desc): if objnode.get('domain') != 'py': continue names = set() for signode in objnode: if not isinstance(signode, addnodes.desc_signature): continue modname = signode.get('module') if not modname: continue fullname = signode.get('fullname') if fullname in names: # only one link per name, please continue names.add(fullname) obj = import_object(modname, fullname) anchor = None if obj is not None: try: lines, lineno = inspect.getsourcelines(obj) except: pass else: anchor = '#L%d' % lineno if anchor: real_modname = inspect.getmodule(obj).__name__ path = '%s%s%s.py%s' % ( url, source_root, real_modname.replace('.', '/'), anchor) onlynode = addnodes.only(expr='html') onlynode += nodes.reference( reftitle=app.config.edit_on_github_help_message, refuri=path) onlynode[0] += nodes.inline( '', '', nodes.raw('', ' ', format='html'), nodes.Text(docstring_message), classes=['edit-on-github', 'viewcode-link']) signode += onlynode def html_page_context(app, pagename, templatename, context, doctree): if (templatename == 'page.html' and not re.match(app.config.edit_on_github_skip_regex, pagename)): doc_root = app.config.edit_on_github_doc_root if doc_root != '' and not doc_root.endswith('/'): doc_root += '/' doc_path = os.path.relpath(doctree.get('source'), app.builder.srcdir) url = get_url_base(app) page_message = app.config.edit_on_github_page_message context['edit_on_github'] = url + doc_root + doc_path context['edit_on_github_page_message'] = ( app.config.edit_on_github_page_message) def setup(app): app.add_config_value('edit_on_github_project', 'REQUIRED', True) app.add_config_value('edit_on_github_branch', 'master', True) app.add_config_value('edit_on_github_source_root', 'lib', True) app.add_config_value('edit_on_github_doc_root', 'doc', True) app.add_config_value('edit_on_github_docstring_message', '[edit on github]', True) app.add_config_value('edit_on_github_page_message', 'Edit This Page on Github', True) app.add_config_value('edit_on_github_help_message', 'Push the Edit button on the next page', True) app.add_config_value('edit_on_github_skip_regex', '_.*', True) app.connect('doctree-read', doctree_read) app.connect('html-page-context', html_page_context) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/numpydoc.py0000644000077000000240000001441412346274067025760 0ustar tomstaff00000000000000""" ======== 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] https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt """ from __future__ import division, absolute_import, print_function import os, sys, re, pydoc import sphinx import inspect import collections if sphinx.__version__ < '1.0.1': raise RuntimeError("Sphinx 1.0.1 or newer is required") from .docscrape_sphinx import get_doc_object, SphinxDocString from sphinx.util.compat import Directive if sys.version_info[0] >= 3: sixu = lambda s: s else: sixu = lambda s: unicode(s, 'unicode_escape') 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, class_members_toctree=app.config.numpydoc_class_members_toctree, ) if what == 'module': # Strip top title title_re = re.compile(sixu('^\\s*[#*=]{4,}\\n[a-z0-9 -]+\\n[#*=]{4,}\\s*'), re.I|re.S) lines[:] = title_re.sub(sixu(''), sixu("\n").join(lines)).split(sixu("\n")) else: doc = get_doc_object(obj, what, sixu("\n").join(lines), config=cfg) if sys.version_info[0] >= 3: doc = str(doc) else: doc = unicode(doc) lines[:] = doc.split(sixu("\n")) if app.config.numpydoc_edit_link and hasattr(obj, '__name__') and \ obj.__name__: if hasattr(obj, '__module__'): v = dict(full_name=sixu("%s.%s") % (obj.__module__, obj.__name__)) else: v = dict(full_name=obj.__name__) lines += [sixu(''), sixu('.. htmlonly::'), sixu('')] lines += [sixu(' %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(sixu('^.. \\[([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(sixu('^\\d+$'), r): new_r = sixu("R%d") % (reference_offset[0] + int(r)) else: new_r = sixu("%s%d") % (r, reference_offset[0]) lines[i] = lines[i].replace(sixu('[%s]_') % r, sixu('[%s]_') % new_r) lines[i] = lines[i].replace(sixu('.. [%s]') % r, sixu('.. [%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 (isinstance(obj, collections.Callable) or hasattr(obj, '__argspec_is_invalid_')): return if not hasattr(obj, '__doc__'): return doc = SphinxDocString(pydoc.getdoc(obj)) if doc['Signature']: sig = re.sub(sixu("^[^(]*"), sixu(""), doc['Signature']) return sig, sixu('') def setup(app, get_doc_object_=get_doc_object): if not hasattr(app, 'add_config_value'): return # probably called by nose, better bail out 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) app.add_config_value('numpydoc_class_members_toctree', 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 list(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', } indices = [] 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 wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/phantom_import.py0000644000077000000240000001333612346274067027164 0ustar tomstaff00000000000000""" ============== phantom_import ============== Sphinx extension to make directives from ``sphinx.ext.autodoc`` and similar extensions to use docstrings loaded from an XML file. This extension loads an XML file in the Pydocweb format [1] and creates a dummy module that contains the specified docstrings. This can be used to get the current docstrings from a Pydocweb instance without needing to rebuild the documented module. .. [1] http://code.google.com/p/pydocweb """ from __future__ import division, absolute_import, print_function import imp, sys, compiler, types, os, inspect, re def setup(app): app.connect('builder-inited', initialize) app.add_config_value('phantom_import_file', None, True) def initialize(app): fn = app.config.phantom_import_file if (fn and os.path.isfile(fn)): print("[numpydoc] Phantom importing modules from", fn, "...") import_phantom_module(fn) #------------------------------------------------------------------------------ # Creating 'phantom' modules from an XML description #------------------------------------------------------------------------------ def import_phantom_module(xml_file): """ Insert a fake Python module to sys.modules, based on a XML file. The XML file is expected to conform to Pydocweb DTD. The fake module will contain dummy objects, which guarantee the following: - Docstrings are correct. - Class inheritance relationships are correct (if present in XML). - Function argspec is *NOT* correct (even if present in XML). Instead, the function signature is prepended to the function docstring. - Class attributes are *NOT* correct; instead, they are dummy objects. Parameters ---------- xml_file : str Name of an XML file to read """ import lxml.etree as etree object_cache = {} tree = etree.parse(xml_file) root = tree.getroot() # Sort items so that # - Base classes come before classes inherited from them # - Modules come before their contents all_nodes = dict([(n.attrib['id'], n) for n in root]) def _get_bases(node, recurse=False): bases = [x.attrib['ref'] for x in node.findall('base')] if recurse: j = 0 while True: try: b = bases[j] except IndexError: break if b in all_nodes: bases.extend(_get_bases(all_nodes[b])) j += 1 return bases type_index = ['module', 'class', 'callable', 'object'] def base_cmp(a, b): x = cmp(type_index.index(a.tag), type_index.index(b.tag)) if x != 0: return x if a.tag == 'class' and b.tag == 'class': a_bases = _get_bases(a, recurse=True) b_bases = _get_bases(b, recurse=True) x = cmp(len(a_bases), len(b_bases)) if x != 0: return x if a.attrib['id'] in b_bases: return -1 if b.attrib['id'] in a_bases: return 1 return cmp(a.attrib['id'].count('.'), b.attrib['id'].count('.')) nodes = root.getchildren() nodes.sort(base_cmp) # Create phantom items for node in nodes: name = node.attrib['id'] doc = (node.text or '').decode('string-escape') + "\n" if doc == "\n": doc = "" # create parent, if missing parent = name while True: parent = '.'.join(parent.split('.')[:-1]) if not parent: break if parent in object_cache: break obj = imp.new_module(parent) object_cache[parent] = obj sys.modules[parent] = obj # create object if node.tag == 'module': obj = imp.new_module(name) obj.__doc__ = doc sys.modules[name] = obj elif node.tag == 'class': bases = [object_cache[b] for b in _get_bases(node) if b in object_cache] bases.append(object) init = lambda self: None init.__doc__ = doc obj = type(name, tuple(bases), {'__doc__': doc, '__init__': init}) obj.__name__ = name.split('.')[-1] elif node.tag == 'callable': funcname = node.attrib['id'].split('.')[-1] argspec = node.attrib.get('argspec') if argspec: argspec = re.sub('^[^(]*', '', argspec) doc = "%s%s\n\n%s" % (funcname, argspec, doc) obj = lambda: 0 obj.__argspec_is_invalid_ = True if sys.version_info[0] >= 3: obj.__name__ = funcname else: obj.func_name = funcname obj.__name__ = name obj.__doc__ = doc if inspect.isclass(object_cache[parent]): obj.__objclass__ = object_cache[parent] else: class Dummy(object): pass obj = Dummy() obj.__name__ = name obj.__doc__ = doc if inspect.isclass(object_cache[parent]): obj.__get__ = lambda: None object_cache[name] = obj if parent: if inspect.ismodule(object_cache[parent]): obj.__module__ = parent setattr(object_cache[parent], name.split('.')[-1], obj) # Populate items for node in root: obj = object_cache.get(node.attrib['id']) if obj is None: continue for ref in node.findall('ref'): if node.tag == 'class': if ref.attrib['ref'].startswith(node.attrib['id'] + '.'): setattr(obj, ref.attrib['name'], object_cache.get(ref.attrib['ref'])) else: setattr(obj, ref.attrib['name'], object_cache.get(ref.attrib['ref'])) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/smart_resolver.py0000644000077000000240000000717612417312170027163 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ The classes in the astropy docs are documented by their API location, which is not necessarily where they are defined in the source. This causes a problem when certain automated features of the doc build, such as the inheritance diagrams or the `Bases` list of a class reference a class by its canonical location rather than its "user" location. In the `autodoc-process-docstring` event, a mapping from the actual name to the API name is maintained. Later, in the `missing-reference` event, unresolved references are looked up in this dictionary and corrected if possible. """ from docutils.nodes import literal, reference def process_docstring(app, what, name, obj, options, lines): if isinstance(obj, type): env = app.env if not hasattr(env, 'class_name_mapping'): env.class_name_mapping = {} mapping = env.class_name_mapping mapping[obj.__module__ + '.' + obj.__name__] = name def missing_reference_handler(app, env, node, contnode): if not hasattr(env, 'class_name_mapping'): env.class_name_mapping = {} mapping = env.class_name_mapping reftype = node['reftype'] reftarget = node['reftarget'] if reftype in ('obj', 'class', 'exc', 'meth'): reftarget = node['reftarget'] suffix = '' if reftarget not in mapping: if '.' in reftarget: front, suffix = reftarget.rsplit('.', 1) else: suffix = reftarget if suffix.startswith('_') and not suffix.startswith('__'): # If this is a reference to a hidden class or method, # we can't link to it, but we don't want to have a # nitpick warning. return node[0].deepcopy() if reftype in ('obj', 'meth') and '.' in reftarget: if front in mapping: reftarget = front suffix = '.' + suffix if (reftype in ('class', ) and '.' in reftarget and reftarget not in mapping): if '.' in front: reftarget, _ = front.rsplit('.', 1) suffix = '.' + suffix reftarget = reftarget + suffix prefix = reftarget.rsplit('.')[0] if (reftarget not in mapping and prefix in env.intersphinx_named_inventory): if reftarget in env.intersphinx_named_inventory[prefix]['py:class']: newtarget = env.intersphinx_named_inventory[prefix]['py:class'][reftarget][2] if not node['refexplicit'] and \ '~' not in node.rawsource: contnode = literal(text=reftarget) newnode = reference('', '', internal=True) newnode['reftitle'] = reftarget newnode['refuri'] = newtarget newnode.append(contnode) return newnode if reftarget in mapping: newtarget = mapping[reftarget] + suffix if not node['refexplicit'] and not '~' in node.rawsource: contnode = literal(text=newtarget) newnode = env.domains['py'].resolve_xref( env, node['refdoc'], app.builder, 'class', newtarget, node, contnode) if newnode is not None: newnode['reftitle'] = reftarget return newnode def setup(app): app.connect('autodoc-process-docstring', process_docstring) app.connect('missing-reference', missing_reference_handler) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/templates/0000755000077000000240000000000012553237435025540 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/templates/autosummary_core/0000755000077000000240000000000012553237435031136 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/templates/autosummary_core/base.rst0000644000077000000240000000025212346274067032603 0ustar tomstaff00000000000000{% if referencefile %} .. include:: {{ referencefile }} {% endif %} {{ objname }} {{ underline }} .. currentmodule:: {{ module }} .. auto{{ objtype }}:: {{ objname }} wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/templates/autosummary_core/class.rst0000644000077000000240000000221112346274067032773 0ustar tomstaff00000000000000{% if referencefile %} .. include:: {{ referencefile }} {% endif %} {{ objname }} {{ underline }} .. currentmodule:: {{ module }} .. autoclass:: {{ objname }} :show-inheritance: {% if '__init__' in methods %} {% set caught_result = methods.remove('__init__') %} {% endif %} {% block attributes_summary %} {% if attributes %} .. rubric:: Attributes Summary .. autosummary:: {% for item in attributes %} ~{{ name }}.{{ item }} {%- endfor %} {% endif %} {% endblock %} {% block methods_summary %} {% if methods %} .. rubric:: Methods Summary .. autosummary:: {% for item in methods %} ~{{ name }}.{{ item }} {%- endfor %} {% endif %} {% endblock %} {% block attributes_documentation %} {% if attributes %} .. rubric:: Attributes Documentation {% for item in attributes %} .. autoattribute:: {{ item }} {%- endfor %} {% endif %} {% endblock %} {% block methods_documentation %} {% if methods %} .. rubric:: Methods Documentation {% for item in methods %} .. automethod:: {{ item }} {%- endfor %} {% endif %} {% endblock %} wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/templates/autosummary_core/module.rst0000644000077000000240000000127712346274067033166 0ustar tomstaff00000000000000{% if referencefile %} .. include:: {{ referencefile }} {% endif %} {{ objname }} {{ underline }} .. automodule:: {{ fullname }} {% block functions %} {% if functions %} .. rubric:: Functions .. autosummary:: {% for item in functions %} {{ item }} {%- endfor %} {% endif %} {% endblock %} {% block classes %} {% if classes %} .. rubric:: Classes .. autosummary:: {% for item in classes %} {{ item }} {%- endfor %} {% endif %} {% endblock %} {% block exceptions %} {% if exceptions %} .. rubric:: Exceptions .. autosummary:: {% for item in exceptions %} {{ item }} {%- endfor %} {% endif %} {% endblock %} wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/tests/0000755000077000000240000000000012553237435024704 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/tests/__init__.py0000644000077000000240000000334112414703152027004 0ustar tomstaff00000000000000import os import subprocess as sp import sys from textwrap import dedent import pytest @pytest.fixture def cython_testpackage(tmpdir, request): """ Creates a trivial Cython package for use with tests. """ test_pkg = tmpdir.mkdir('test_pkg') test_pkg.mkdir('_eva_').ensure('__init__.py') test_pkg.join('_eva_').join('unit02.pyx').write(dedent("""\ def pilot(): \"\"\"Returns the pilot of Eva Unit-02.\"\"\" return True """)) import astropy_helpers test_pkg.join('setup.py').write(dedent("""\ import sys sys.path.insert(0, {0!r}) from os.path import join from setuptools import setup, Extension from astropy_helpers.setup_helpers import register_commands NAME = '_eva_' VERSION = 0.1 RELEASE = True cmdclassd = register_commands(NAME, VERSION, RELEASE) setup( name=NAME, version=VERSION, cmdclass=cmdclassd, ext_modules=[Extension('_eva_.unit02', [join('_eva_', 'unit02.pyx')])] ) """.format(os.path.dirname(astropy_helpers.__path__[0])))) test_pkg.chdir() # Build the Cython module in a subprocess; otherwise strange things can # happen with Cython's global module state sp.call([sys.executable, 'setup.py', 'build_ext', '--inplace']) sys.path.insert(0, str(test_pkg)) import _eva_.unit02 def cleanup(test_pkg=test_pkg): for modname in ['_eva_', '_eva_.unit02']: try: del sys.modules[modname] except KeyError: pass sys.path.remove(str(test_pkg)) request.addfinalizer(cleanup) return test_pkg wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/tests/test_autodoc_enhancements.py0000644000077000000240000000324312532571254032502 0ustar tomstaff00000000000000import sys from textwrap import dedent import pytest from ..autodoc_enhancements import type_object_attrgetter # Define test classes outside the class; otherwise there is flakiness with the # details of how exec works on different Python versions class Meta(type): @property def foo(cls): return 'foo' if sys.version_info[0] < 3: exec(dedent(""" class MyClass(object): __metaclass__ = Meta @property def foo(self): \"\"\"Docstring for MyClass.foo property.\"\"\" return 'myfoo' """)) else: exec(dedent(""" class MyClass(metaclass=Meta): @property def foo(self): \"\"\"Docstring for MyClass.foo property.\"\"\" return 'myfoo' """)) def test_type_attrgetter(): """ This test essentially reproduces the docstring for `type_object_attrgetter`. Sphinx itself tests the custom attrgetter feature; see: https://bitbucket.org/birkenfeld/sphinx/src/40bd03003ac6fe274ccf3c80d7727509e00a69ea/tests/test_autodoc.py?at=default#cl-502 so rather than a full end-to-end functional test it's simple enough to just test that this function does what it needs to do. """ assert getattr(MyClass, 'foo') == 'foo' obj = type_object_attrgetter(MyClass, 'foo') assert isinstance(obj, property) assert obj.__doc__ == 'Docstring for MyClass.foo property.' with pytest.raises(AttributeError): type_object_attrgetter(MyClass, 'susy') assert type_object_attrgetter(MyClass, 'susy', 'default') == 'default' assert type_object_attrgetter(MyClass, '__dict__') == MyClass.__dict__ wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/tests/test_automodapi.py0000644000077000000240000001613612532571254030463 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import os import sys import pytest from . import * from ....utils import iteritems pytest.importorskip('sphinx') # skips these tests if sphinx not present class FakeConfig(object): """ Mocks up a sphinx configuration setting construct for automodapi tests """ def __init__(self, **kwargs): for k, v in iteritems(kwargs): setattr(self, k, v) class FakeApp(object): """ Mocks up a `sphinx.application.Application` object for automodapi tests """ # Some default config values _defaults = { 'automodapi_toctreedirnm': 'api', 'automodapi_writereprocessed': False } def __init__(self, **configs): config = self._defaults.copy() config.update(configs) self.config = FakeConfig(**config) self.info = [] self.warnings = [] def info(self, msg, loc): self.info.append((msg, loc)) def warn(self, msg, loc): self.warnings.append((msg, loc)) am_replacer_str = """ This comes before .. automodapi:: astropy_helpers.sphinx.ext.tests.test_automodapi {options} This comes after """ am_replacer_basic_expected = """ This comes before astropy_helpers.sphinx.ext.tests.test_automodapi Module ------------------------------------------------------- .. automodule:: astropy_helpers.sphinx.ext.tests.test_automodapi Functions ^^^^^^^^^ .. automodsumm:: astropy_helpers.sphinx.ext.tests.test_automodapi :functions-only: :toctree: api/ Classes ^^^^^^^ .. automodsumm:: astropy_helpers.sphinx.ext.tests.test_automodapi :classes-only: :toctree: api/ Class Inheritance Diagram ^^^^^^^^^^^^^^^^^^^^^^^^^ .. automod-diagram:: astropy_helpers.sphinx.ext.tests.test_automodapi :private-bases: :parts: 1 {empty} This comes after """.format(empty='') # the .format is necessary for editors that remove empty-line whitespace def test_am_replacer_basic(): """ Tests replacing an ".. automodapi::" with the automodapi no-option template """ from ..automodapi import automodapi_replace fakeapp = FakeApp() result = automodapi_replace(am_replacer_str.format(options=''), fakeapp) assert result == am_replacer_basic_expected am_replacer_noinh_expected = """ This comes before astropy_helpers.sphinx.ext.tests.test_automodapi Module ------------------------------------------------------- .. automodule:: astropy_helpers.sphinx.ext.tests.test_automodapi Functions ^^^^^^^^^ .. automodsumm:: astropy_helpers.sphinx.ext.tests.test_automodapi :functions-only: :toctree: api/ Classes ^^^^^^^ .. automodsumm:: astropy_helpers.sphinx.ext.tests.test_automodapi :classes-only: :toctree: api/ This comes after """.format(empty='') def test_am_replacer_noinh(): """ Tests replacing an ".. automodapi::" with no-inheritance-diagram option """ from ..automodapi import automodapi_replace fakeapp = FakeApp() ops = ['', ':no-inheritance-diagram:'] ostr = '\n '.join(ops) result = automodapi_replace(am_replacer_str.format(options=ostr), fakeapp) assert result == am_replacer_noinh_expected am_replacer_titleandhdrs_expected = """ This comes before astropy_helpers.sphinx.ext.tests.test_automodapi Module &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& .. automodule:: astropy_helpers.sphinx.ext.tests.test_automodapi Functions ********* .. automodsumm:: astropy_helpers.sphinx.ext.tests.test_automodapi :functions-only: :toctree: api/ Classes ******* .. automodsumm:: astropy_helpers.sphinx.ext.tests.test_automodapi :classes-only: :toctree: api/ Class Inheritance Diagram ************************* .. automod-diagram:: astropy_helpers.sphinx.ext.tests.test_automodapi :private-bases: :parts: 1 {empty} This comes after """.format(empty='') def test_am_replacer_titleandhdrs(): """ Tests replacing an ".. automodapi::" entry with title-setting and header character options. """ from ..automodapi import automodapi_replace fakeapp = FakeApp() ops = ['', ':title: A new title', ':headings: &*'] ostr = '\n '.join(ops) result = automodapi_replace(am_replacer_str.format(options=ostr), fakeapp) assert result == am_replacer_titleandhdrs_expected am_replacer_nomain_str = """ This comes before .. automodapi:: astropy_helpers.sphinx.ext.automodapi :no-main-docstr: This comes after """ am_replacer_nomain_expected = """ This comes before astropy_helpers.sphinx.ext.automodapi Module -------------------------------------------- Functions ^^^^^^^^^ .. automodsumm:: astropy_helpers.sphinx.ext.automodapi :functions-only: :toctree: api/ This comes after """.format(empty='') def test_am_replacer_nomain(): """ Tests replacing an ".. automodapi::" with "no-main-docstring" . """ from ..automodapi import automodapi_replace fakeapp = FakeApp() result = automodapi_replace(am_replacer_nomain_str, fakeapp) assert result == am_replacer_nomain_expected am_replacer_skip_str = """ This comes before .. automodapi:: astropy_helpers.sphinx.ext.automodapi :skip: something1 :skip: something2 This comes after """ am_replacer_skip_expected = """ This comes before astropy_helpers.sphinx.ext.automodapi Module -------------------------------------------- .. automodule:: astropy_helpers.sphinx.ext.automodapi Functions ^^^^^^^^^ .. automodsumm:: astropy_helpers.sphinx.ext.automodapi :functions-only: :toctree: api/ :skip: something1,something2 This comes after """.format(empty='') def test_am_replacer_skip(): """ Tests using the ":skip: option in an ".. automodapi::" . """ from ..automodapi import automodapi_replace fakeapp = FakeApp() result = automodapi_replace(am_replacer_skip_str, fakeapp) assert result == am_replacer_skip_expected am_replacer_invalidop_str = """ This comes before .. automodapi:: astropy_helpers.sphinx.ext.automodapi :invalid-option: This comes after """ def test_am_replacer_invalidop(): """ Tests that a sphinx warning is produced with an invalid option. """ from ..automodapi import automodapi_replace fakeapp = FakeApp() automodapi_replace(am_replacer_invalidop_str, fakeapp) expected_warnings = [('Found additional options invalid-option in ' 'automodapi.', None)] assert fakeapp.warnings == expected_warnings am_replacer_cython_str = """ This comes before .. automodapi:: _eva_.unit02 {options} This comes after """ am_replacer_cython_expected = """ This comes before _eva_.unit02 Module ------------------- .. automodule:: _eva_.unit02 Functions ^^^^^^^^^ .. automodsumm:: _eva_.unit02 :functions-only: :toctree: api/ This comes after """.format(empty='') def test_am_replacer_cython(cython_testpackage): """ Tests replacing an ".. automodapi::" for a Cython module. """ from ..automodapi import automodapi_replace fakeapp = FakeApp() result = automodapi_replace(am_replacer_cython_str.format(options=''), fakeapp) assert result == am_replacer_cython_expected wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/tests/test_automodsumm.py0000644000077000000240000000456412532571254030675 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import sys import pytest from . import * from ....utils import iteritems pytest.importorskip('sphinx') # skips these tests if sphinx not present class FakeEnv(object): """ Mocks up a sphinx env setting construct for automodapi tests """ def __init__(self, **kwargs): for k, v in iteritems(kwargs): setattr(self, k, v) class FakeBuilder(object): """ Mocks up a sphinx builder setting construct for automodapi tests """ def __init__(self, **kwargs): self.env = FakeEnv(**kwargs) class FakeApp(object): """ Mocks up a `sphinx.application.Application` object for automodapi tests """ def __init__(self, srcdir, automodapipresent=True): self.builder = FakeBuilder(srcdir=srcdir) self.info = [] self.warnings = [] self._extensions = [] if automodapipresent: self._extensions.append('astropy_helpers.sphinx.ext.automodapi') def info(self, msg, loc): self.info.append((msg, loc)) def warn(self, msg, loc): self.warnings.append((msg, loc)) ams_to_asmry_str = """ Before .. automodsumm:: astropy_helpers.sphinx.ext.automodsumm :p: And After """ ams_to_asmry_expected = """\ .. currentmodule:: astropy_helpers.sphinx.ext.automodsumm .. autosummary:: :p: Automoddiagram Automodsumm automodsumm_to_autosummary_lines generate_automodsumm_docs process_automodsumm_generation setup """ def test_ams_to_asmry(tmpdir): from ..automodsumm import automodsumm_to_autosummary_lines fi = tmpdir.join('automodsumm.rst') fi.write(ams_to_asmry_str) fakeapp = FakeApp(srcdir='') resultlines = automodsumm_to_autosummary_lines(str(fi), fakeapp) assert '\n'.join(resultlines) == ams_to_asmry_expected ams_cython_str = """ Before .. automodsumm:: _eva_.unit02 :functions-only: :p: And After """ ams_cython_expected = """\ .. currentmodule:: _eva_.unit02 .. autosummary:: :p: pilot """ def test_ams_cython(tmpdir, cython_testpackage): from ..automodsumm import automodsumm_to_autosummary_lines fi = tmpdir.join('automodsumm.rst') fi.write(ams_cython_str) fakeapp = FakeApp(srcdir='') resultlines = automodsumm_to_autosummary_lines(str(fi), fakeapp) assert '\n'.join(resultlines) == ams_cython_expected wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/tests/test_docscrape.py0000644000077000000240000004327112346274067030271 0ustar tomstaff00000000000000# -*- encoding:utf-8 -*- from __future__ import division, absolute_import, print_function import sys, textwrap from ..docscrape import NumpyDocString, FunctionDoc, ClassDoc from ..docscrape_sphinx import SphinxDocString, SphinxClassDoc if sys.version_info[0] >= 3: sixu = lambda s: s else: sixu = lambda s: unicode(s, 'unicode_escape') doc_txt = '''\ numpy.multivariate_normal(mean, cov, shape=None, spam=None) Draw values from a multivariate normal distribution with specified mean and covariance. The multivariate normal or Gaussian distribution is a generalisation of the one-dimensional normal distribution to higher dimensions. Parameters ---------- mean : (N,) ndarray Mean of the N-dimensional distribution. .. math:: (1+2+3)/3 cov : (N, N) ndarray Covariance matrix of the distribution. shape : tuple of ints Given a shape of, for example, (m,n,k), m*n*k samples are generated, and packed in an m-by-n-by-k arrangement. Because each sample is N-dimensional, the output shape is (m,n,k,N). Returns ------- out : ndarray The drawn samples, arranged according to `shape`. If the shape given is (m,n,...), then the shape of `out` is is (m,n,...,N). In other words, each entry ``out[i,j,...,:]`` is an N-dimensional value drawn from the distribution. list of str This is not a real return value. It exists to test anonymous return values. Other Parameters ---------------- spam : parrot A parrot off its mortal coil. Raises ------ RuntimeError Some error Warns ----- RuntimeWarning Some warning Warnings -------- Certain warnings apply. Notes ----- Instead of specifying the full covariance matrix, popular approximations include: - Spherical covariance (`cov` is a multiple of the identity matrix) - Diagonal covariance (`cov` has non-negative elements only on the diagonal) This geometrical property can be seen in two dimensions by plotting generated data-points: >>> mean = [0,0] >>> cov = [[1,0],[0,100]] # diagonal covariance, points lie on x or y-axis >>> x,y = multivariate_normal(mean,cov,5000).T >>> plt.plot(x,y,'x'); plt.axis('equal'); plt.show() Note that the covariance matrix must be symmetric and non-negative definite. References ---------- .. [1] A. Papoulis, "Probability, Random Variables, and Stochastic Processes," 3rd ed., McGraw-Hill Companies, 1991 .. [2] R.O. Duda, P.E. Hart, and D.G. Stork, "Pattern Classification," 2nd ed., Wiley, 2001. See Also -------- some, other, funcs otherfunc : relationship Examples -------- >>> mean = (1,2) >>> cov = [[1,0],[1,0]] >>> x = multivariate_normal(mean,cov,(3,3)) >>> print x.shape (3, 3, 2) The following is probably true, given that 0.6 is roughly twice the standard deviation: >>> print list( (x[0,0,:] - mean) < 0.6 ) [True, True] .. index:: random :refguide: random;distributions, random;gauss ''' doc = NumpyDocString(doc_txt) def test_signature(): assert doc['Signature'].startswith('numpy.multivariate_normal(') assert doc['Signature'].endswith('spam=None)') def test_summary(): assert doc['Summary'][0].startswith('Draw values') assert doc['Summary'][-1].endswith('covariance.') def test_extended_summary(): assert doc['Extended Summary'][0].startswith('The multivariate normal') def test_parameters(): assert len(doc['Parameters']) == 3 assert [n for n,_,_ in doc['Parameters']] == ['mean','cov','shape'] arg, arg_type, desc = doc['Parameters'][1] assert arg_type == '(N, N) ndarray' assert desc[0].startswith('Covariance matrix') assert doc['Parameters'][0][-1][-2] == ' (1+2+3)/3' def test_other_parameters(): assert len(doc['Other Parameters']) == 1 assert [n for n,_,_ in doc['Other Parameters']] == ['spam'] arg, arg_type, desc = doc['Other Parameters'][0] assert arg_type == 'parrot' assert desc[0].startswith('A parrot off its mortal coil') def test_returns(): assert len(doc['Returns']) == 2 arg, arg_type, desc = doc['Returns'][0] assert arg == 'out' assert arg_type == 'ndarray' assert desc[0].startswith('The drawn samples') assert desc[-1].endswith('distribution.') arg, arg_type, desc = doc['Returns'][1] assert arg == 'list of str' assert arg_type == '' assert desc[0].startswith('This is not a real') assert desc[-1].endswith('anonymous return values.') def test_notes(): assert doc['Notes'][0].startswith('Instead') assert doc['Notes'][-1].endswith('definite.') assert len(doc['Notes']) == 17 def test_references(): assert doc['References'][0].startswith('..') assert doc['References'][-1].endswith('2001.') def test_examples(): assert doc['Examples'][0].startswith('>>>') assert doc['Examples'][-1].endswith('True]') def test_index(): assert doc['index']['default'] == 'random' assert len(doc['index']) == 2 assert len(doc['index']['refguide']) == 2 def non_blank_line_by_line_compare(a,b): a = textwrap.dedent(a) b = textwrap.dedent(b) a = [l.rstrip() for l in a.split('\n') if l.strip()] b = [l.rstrip() for l in b.split('\n') if l.strip()] for n,line in enumerate(a): if not line == b[n]: raise AssertionError("Lines %s of a and b differ: " "\n>>> %s\n<<< %s\n" % (n,line,b[n])) def test_str(): non_blank_line_by_line_compare(str(doc), """numpy.multivariate_normal(mean, cov, shape=None, spam=None) Draw values from a multivariate normal distribution with specified mean and covariance. The multivariate normal or Gaussian distribution is a generalisation of the one-dimensional normal distribution to higher dimensions. Parameters ---------- mean : (N,) ndarray Mean of the N-dimensional distribution. .. math:: (1+2+3)/3 cov : (N, N) ndarray Covariance matrix of the distribution. shape : tuple of ints Given a shape of, for example, (m,n,k), m*n*k samples are generated, and packed in an m-by-n-by-k arrangement. Because each sample is N-dimensional, the output shape is (m,n,k,N). Returns ------- out : ndarray The drawn samples, arranged according to `shape`. If the shape given is (m,n,...), then the shape of `out` is is (m,n,...,N). In other words, each entry ``out[i,j,...,:]`` is an N-dimensional value drawn from the distribution. list of str This is not a real return value. It exists to test anonymous return values. Other Parameters ---------------- spam : parrot A parrot off its mortal coil. Raises ------ RuntimeError Some error Warns ----- RuntimeWarning Some warning Warnings -------- Certain warnings apply. See Also -------- `some`_, `other`_, `funcs`_ `otherfunc`_ relationship Notes ----- Instead of specifying the full covariance matrix, popular approximations include: - Spherical covariance (`cov` is a multiple of the identity matrix) - Diagonal covariance (`cov` has non-negative elements only on the diagonal) This geometrical property can be seen in two dimensions by plotting generated data-points: >>> mean = [0,0] >>> cov = [[1,0],[0,100]] # diagonal covariance, points lie on x or y-axis >>> x,y = multivariate_normal(mean,cov,5000).T >>> plt.plot(x,y,'x'); plt.axis('equal'); plt.show() Note that the covariance matrix must be symmetric and non-negative definite. References ---------- .. [1] A. Papoulis, "Probability, Random Variables, and Stochastic Processes," 3rd ed., McGraw-Hill Companies, 1991 .. [2] R.O. Duda, P.E. Hart, and D.G. Stork, "Pattern Classification," 2nd ed., Wiley, 2001. Examples -------- >>> mean = (1,2) >>> cov = [[1,0],[1,0]] >>> x = multivariate_normal(mean,cov,(3,3)) >>> print x.shape (3, 3, 2) The following is probably true, given that 0.6 is roughly twice the standard deviation: >>> print list( (x[0,0,:] - mean) < 0.6 ) [True, True] .. index:: random :refguide: random;distributions, random;gauss""") def test_sphinx_str(): sphinx_doc = SphinxDocString(doc_txt) non_blank_line_by_line_compare(str(sphinx_doc), """ .. index:: random single: random;distributions, random;gauss Draw values from a multivariate normal distribution with specified mean and covariance. The multivariate normal or Gaussian distribution is a generalisation of the one-dimensional normal distribution to higher dimensions. :Parameters: **mean** : (N,) ndarray Mean of the N-dimensional distribution. .. math:: (1+2+3)/3 **cov** : (N, N) ndarray Covariance matrix of the distribution. **shape** : tuple of ints Given a shape of, for example, (m,n,k), m*n*k samples are generated, and packed in an m-by-n-by-k arrangement. Because each sample is N-dimensional, the output shape is (m,n,k,N). :Returns: **out** : ndarray The drawn samples, arranged according to `shape`. If the shape given is (m,n,...), then the shape of `out` is is (m,n,...,N). In other words, each entry ``out[i,j,...,:]`` is an N-dimensional value drawn from the distribution. list of str This is not a real return value. It exists to test anonymous return values. :Other Parameters: **spam** : parrot A parrot off its mortal coil. :Raises: **RuntimeError** Some error :Warns: **RuntimeWarning** Some warning .. warning:: Certain warnings apply. .. seealso:: :obj:`some`, :obj:`other`, :obj:`funcs` :obj:`otherfunc` relationship .. rubric:: Notes Instead of specifying the full covariance matrix, popular approximations include: - Spherical covariance (`cov` is a multiple of the identity matrix) - Diagonal covariance (`cov` has non-negative elements only on the diagonal) This geometrical property can be seen in two dimensions by plotting generated data-points: >>> mean = [0,0] >>> cov = [[1,0],[0,100]] # diagonal covariance, points lie on x or y-axis >>> x,y = multivariate_normal(mean,cov,5000).T >>> plt.plot(x,y,'x'); plt.axis('equal'); plt.show() Note that the covariance matrix must be symmetric and non-negative definite. .. rubric:: References .. [1] A. Papoulis, "Probability, Random Variables, and Stochastic Processes," 3rd ed., McGraw-Hill Companies, 1991 .. [2] R.O. Duda, P.E. Hart, and D.G. Stork, "Pattern Classification," 2nd ed., Wiley, 2001. .. only:: latex [1]_, [2]_ .. rubric:: Examples >>> mean = (1,2) >>> cov = [[1,0],[1,0]] >>> x = multivariate_normal(mean,cov,(3,3)) >>> print x.shape (3, 3, 2) The following is probably true, given that 0.6 is roughly twice the standard deviation: >>> print list( (x[0,0,:] - mean) < 0.6 ) [True, True] """) doc2 = NumpyDocString(""" Returns array of indices of the maximum values of along the given axis. Parameters ---------- a : {array_like} Array to look in. axis : {None, integer} If None, the index is into the flattened array, otherwise along the specified axis""") def test_parameters_without_extended_description(): assert len(doc2['Parameters']) == 2 doc3 = NumpyDocString(""" my_signature(*params, **kwds) Return this and that. """) def test_escape_stars(): signature = str(doc3).split('\n')[0] signature == 'my_signature(\*params, \*\*kwds)' doc4 = NumpyDocString( """a.conj() Return an array with all complex-valued elements conjugated.""") def test_empty_extended_summary(): assert doc4['Extended Summary'] == [] doc5 = NumpyDocString( """ a.something() Raises ------ LinAlgException If array is singular. Warns ----- SomeWarning If needed """) def test_raises(): assert len(doc5['Raises']) == 1 name,_,desc = doc5['Raises'][0] assert name == 'LinAlgException' assert desc == ['If array is singular.'] def test_warns(): assert len(doc5['Warns']) == 1 name,_,desc = doc5['Warns'][0] assert name == 'SomeWarning' assert desc == ['If needed'] def test_see_also(): doc6 = NumpyDocString( """ z(x,theta) See Also -------- func_a, func_b, func_c func_d : some equivalent func foo.func_e : some other func over multiple lines func_f, func_g, :meth:`func_h`, func_j, func_k :obj:`baz.obj_q` :class:`class_j`: fubar foobar """) assert len(doc6['See Also']) == 12 for func, desc, role in doc6['See Also']: if func in ('func_a', 'func_b', 'func_c', 'func_f', 'func_g', 'func_h', 'func_j', 'func_k', 'baz.obj_q'): assert(not desc) else: assert(desc) if func == 'func_h': assert role == 'meth' elif func == 'baz.obj_q': assert role == 'obj' elif func == 'class_j': assert role == 'class' else: assert role is None if func == 'func_d': assert desc == ['some equivalent func'] elif func == 'foo.func_e': assert desc == ['some other func over', 'multiple lines'] elif func == 'class_j': assert desc == ['fubar', 'foobar'] def test_see_also_print(): class Dummy(object): """ See Also -------- func_a, func_b func_c : some relationship goes here func_d """ pass obj = Dummy() s = str(FunctionDoc(obj, role='func')) assert(':func:`func_a`, :func:`func_b`' in s) assert(' some relationship' in s) assert(':func:`func_d`' in s) doc7 = NumpyDocString(""" Doc starts on second line. """) def test_empty_first_line(): assert doc7['Summary'][0].startswith('Doc starts') def test_no_summary(): str(SphinxDocString(""" Parameters ----------""")) def test_unicode(): doc = SphinxDocString(""" öäöäöäöäöåååå öäöäöäööäååå Parameters ---------- ååå : äää ööö Returns ------- ååå : ööö äää """) assert isinstance(doc['Summary'][0], str) assert doc['Summary'][0] == 'öäöäöäöäöåååå' def test_plot_examples(): cfg = dict(use_plots=True) doc = SphinxDocString(""" Examples -------- >>> import matplotlib.pyplot as plt >>> plt.plot([1,2,3],[4,5,6]) >>> plt.show() """, config=cfg) assert 'plot::' in str(doc), str(doc) doc = SphinxDocString(""" Examples -------- .. plot:: import matplotlib.pyplot as plt plt.plot([1,2,3],[4,5,6]) plt.show() """, config=cfg) assert str(doc).count('plot::') == 1, str(doc) def test_class_members(): class Dummy(object): """ Dummy class. """ def spam(self, a, b): """Spam\n\nSpam spam.""" pass def ham(self, c, d): """Cheese\n\nNo cheese.""" pass @property def spammity(self): """Spammity index""" return 0.95 class Ignorable(object): """local class, to be ignored""" pass for cls in (ClassDoc, SphinxClassDoc): doc = cls(Dummy, config=dict(show_class_members=False)) assert 'Methods' not in str(doc), (cls, str(doc)) assert 'spam' not in str(doc), (cls, str(doc)) assert 'ham' not in str(doc), (cls, str(doc)) assert 'spammity' not in str(doc), (cls, str(doc)) assert 'Spammity index' not in str(doc), (cls, str(doc)) doc = cls(Dummy, config=dict(show_class_members=True)) assert 'Methods' in str(doc), (cls, str(doc)) assert 'spam' in str(doc), (cls, str(doc)) assert 'ham' in str(doc), (cls, str(doc)) assert 'spammity' in str(doc), (cls, str(doc)) if cls is SphinxClassDoc: assert '.. autosummary::' in str(doc), str(doc) else: assert 'Spammity index' in str(doc), str(doc) def test_duplicate_signature(): # Duplicate function signatures occur e.g. in ufuncs, when the # automatic mechanism adds one, and a more detailed comes from the # docstring itself. doc = NumpyDocString( """ z(x1, x2) z(a, theta) """) assert doc['Signature'].strip() == 'z(a, theta)' class_doc_txt = """ Foo Parameters ---------- f : callable ``f(t, y, *f_args)`` Aaa. jac : callable ``jac(t, y, *jac_args)`` Bbb. Attributes ---------- t : float Current time. y : ndarray Current variable values. Methods ------- a b c Examples -------- For usage examples, see `ode`. """ def test_class_members_doc(): doc = ClassDoc(None, class_doc_txt) non_blank_line_by_line_compare(str(doc), """ Foo Parameters ---------- f : callable ``f(t, y, *f_args)`` Aaa. jac : callable ``jac(t, y, *jac_args)`` Bbb. Examples -------- For usage examples, see `ode`. Attributes ---------- t : float Current time. y : ndarray Current variable values. Methods ------- a b c .. index:: """) def test_class_members_doc_sphinx(): doc = SphinxClassDoc(None, class_doc_txt) non_blank_line_by_line_compare(str(doc), """ Foo :Parameters: **f** : callable ``f(t, y, *f_args)`` Aaa. **jac** : callable ``jac(t, y, *jac_args)`` Bbb. .. rubric:: Examples For usage examples, see `ode`. .. rubric:: Attributes === ========== t (float) Current time. y (ndarray) Current variable values. === ========== .. rubric:: Methods === ========== a b c === ========== """) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/tests/test_utils.py0000644000077000000240000000174312414703152027450 0ustar tomstaff00000000000000#namedtuple is needed for find_mod_objs so it can have a non-local module import sys from collections import namedtuple import pytest from ..utils import find_mod_objs PY3 = sys.version_info[0] >= 3 pytestmark = pytest.mark.skipif("PY3") def test_find_mod_objs(): lnms, fqns, objs = find_mod_objs('astropy_helpers') # this import is after the above call intentionally to make sure # find_mod_objs properly imports astropy on its own import astropy_helpers # just check for astropy.test ... other things might be added, so we # shouldn't check that it's the only thing assert lnms == [] lnms, fqns, objs = find_mod_objs( 'astropy_helpers.sphinx.ext.tests.test_utils', onlylocals=False) assert namedtuple in objs lnms, fqns, objs = find_mod_objs( 'astropy_helpers.sphinx.ext.tests.test_utils', onlylocals=True) assert 'namedtuple' not in lnms assert 'collections.namedtuple' not in fqns assert namedtuple not in objs wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/tocdepthfix.py0000644000077000000240000000124512346274067026441 0ustar tomstaff00000000000000from sphinx import addnodes def fix_toc_entries(app, doctree): # Get the docname; I don't know why this isn't just passed in to the # callback # This seems a bit unreliable as it's undocumented, but it's not "private" # either: docname = app.builder.env.temp_data['docname'] if app.builder.env.metadata[docname].get('tocdepth', 0) != 0: # We need to reprocess any TOC nodes in the doctree and make sure all # the files listed in any TOCs are noted for treenode in doctree.traverse(addnodes.toctree): app.builder.env.note_toctree(docname, treenode) def setup(app): app.connect('doctree-read', fix_toc_entries) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/traitsdoc.py0000644000077000000240000001026112346274067026112 0ustar tomstaff00000000000000""" ========= traitsdoc ========= Sphinx extension that handles docstrings in the Numpy standard format, [1] and support Traits [2]. This extension can be used as a replacement for ``numpydoc`` when support for Traits is required. .. [1] http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines#docstring-standard .. [2] http://code.enthought.com/projects/traits/ """ from __future__ import division, absolute_import, print_function import inspect import os import pydoc import collections from . import docscrape from . import docscrape_sphinx from .docscrape_sphinx import SphinxClassDoc, SphinxFunctionDoc, SphinxDocString from . import numpydoc from . import comment_eater class SphinxTraitsDoc(SphinxClassDoc): def __init__(self, cls, modulename='', func_doc=SphinxFunctionDoc): if not inspect.isclass(cls): raise ValueError("Initialise using a class. Got %r" % cls) self._cls = cls if modulename and not modulename.endswith('.'): modulename += '.' self._mod = modulename self._name = cls.__name__ self._func_doc = func_doc docstring = pydoc.getdoc(cls) docstring = docstring.split('\n') # De-indent paragraph try: indent = min(len(s) - len(s.lstrip()) for s in docstring if s.strip()) except ValueError: indent = 0 for n,line in enumerate(docstring): docstring[n] = docstring[n][indent:] self._doc = docscrape.Reader(docstring) self._parsed_data = { 'Signature': '', 'Summary': '', 'Description': [], 'Extended Summary': [], 'Parameters': [], 'Returns': [], 'Raises': [], 'Warns': [], 'Other Parameters': [], 'Traits': [], 'Methods': [], 'See Also': [], 'Notes': [], 'References': '', 'Example': '', 'Examples': '', 'index': {} } self._parse() def _str_summary(self): return self['Summary'] + [''] def _str_extended_summary(self): return self['Description'] + self['Extended Summary'] + [''] def __str__(self, indent=0, func_role="func"): out = [] out += self._str_signature() out += self._str_index() + [''] out += self._str_summary() out += self._str_extended_summary() for param_list in ('Parameters', 'Traits', 'Methods', 'Returns','Raises'): out += self._str_param_list(param_list) out += self._str_see_also("obj") out += self._str_section('Notes') out += self._str_references() out += self._str_section('Example') out += self._str_section('Examples') out = self._str_indent(out,indent) return '\n'.join(out) def looks_like_issubclass(obj, classname): """ Return True if the object has a class or superclass with the given class name. Ignores old-style classes. """ t = obj if t.__name__ == classname: return True for klass in t.__mro__: if klass.__name__ == classname: return True return False def get_doc_object(obj, what=None, config=None): if what is None: if inspect.isclass(obj): what = 'class' elif inspect.ismodule(obj): what = 'module' elif isinstance(obj, collections.Callable): what = 'function' else: what = 'object' if what == 'class': doc = SphinxTraitsDoc(obj, '', func_doc=SphinxFunctionDoc, config=config) if looks_like_issubclass(obj, 'HasTraits'): for name, trait, comment in comment_eater.get_class_traits(obj): # Exclude private traits. if not name.startswith('_'): doc['Traits'].append((name, trait, comment.splitlines())) return doc elif what in ('function', 'method'): return SphinxFunctionDoc(obj, '', config=config) else: return SphinxDocString(pydoc.getdoc(obj), config=config) def setup(app): # init numpydoc numpydoc.setup(app, get_doc_object) wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/utils.py0000644000077000000240000000443312417313646025256 0ustar tomstaff00000000000000import inspect import sys def find_mod_objs(modname, onlylocals=False): """ Returns all the public attributes of a module referenced by name. .. note:: The returned list *not* include subpackages or modules of `modname`,nor does it include private attributes (those that beginwith '_' or are not in `__all__`). Parameters ---------- modname : str The name of the module to search. onlylocals : bool If True, only attributes that are either members of `modname` OR one of its modules or subpackages will be included. Returns ------- localnames : list of str A list of the names of the attributes as they are named in the module `modname` . fqnames : list of str A list of the full qualified names of the attributes (e.g., ``astropy.utils.misc.find_mod_objs``). For attributes that are simple variables, this is based on the local name, but for functions or classes it can be different if they are actually defined elsewhere and just referenced in `modname`. objs : list of objects A list of the actual attributes themselves (in the same order as the other arguments) """ __import__(modname) mod = sys.modules[modname] if hasattr(mod, '__all__'): pkgitems = [(k, mod.__dict__[k]) for k in mod.__all__] else: pkgitems = [(k, mod.__dict__[k]) for k in dir(mod) if k[0] != '_'] # filter out modules and pull the names and objs out ismodule = inspect.ismodule localnames = [k for k, v in pkgitems if not ismodule(v)] objs = [v for k, v in pkgitems if not ismodule(v)] # fully qualified names can be determined from the object's module fqnames = [] for obj, lnm in zip(objs, localnames): if hasattr(obj, '__module__') and hasattr(obj, '__name__'): fqnames.append(obj.__module__ + '.' + obj.__name__) else: fqnames.append(modname + '.' + lnm) if onlylocals: valids = [fqn.startswith(modname) for fqn in fqnames] localnames = [e for i, e in enumerate(localnames) if valids[i]] fqnames = [e for i, e in enumerate(fqnames) if valids[i]] objs = [e for i, e in enumerate(objs) if valids[i]] return localnames, fqnames, objs wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/ext/viewcode.py0000644000077000000240000001752512532571254025730 0ustar tomstaff00000000000000# -*- coding: utf-8 -*- """ sphinx.ext.viewcode ~~~~~~~~~~~~~~~~~~~ Add links to module code in Python object descriptions. :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. Patched using patch in https://bitbucket.org/birkenfeld/sphinx/issue/623/extension-viewcode-fails-with-function on 21 Aug 2013 by Kyle H Barbary """ from docutils import nodes from sphinx import addnodes from sphinx.locale import _ from sphinx.pycode import ModuleAnalyzer from sphinx.util.inspect import safe_getattr from sphinx.util.nodes import make_refnode import sys import traceback if sys.version < '3': text_type = unicode else: text_type = str from ...utils import iteritems def doctree_read(app, doctree): env = app.builder.env if not hasattr(env, '_viewcode_modules'): env._viewcode_modules = {} def get_full_modname(modname, attribute): try: __import__(modname) except Exception as error: if not app.quiet: app.info(traceback.format_exc().rstrip()) app.warn('viewcode can\'t import %s, failed with error "%s"' % (modname, error)) return None module = sys.modules[modname] try: # Allow an attribute to have multiple parts and incidentally allow # repeated .s in the attribute. attr = attribute.split('.') value = module for attr in attribute.split('.'): if attr: value = safe_getattr(value, attr) except AttributeError: app.warn('Didn\'t find %s in %s' % (attribute, module.__name__)) return None else: return safe_getattr(value, '__module__', None) def has_tag(modname, fullname, docname, refname): entry = env._viewcode_modules.get(modname, None) if entry is None: try: analyzer = ModuleAnalyzer.for_module(modname) except Exception: env._viewcode_modules[modname] = False return analyzer.find_tags() if not isinstance(analyzer.code, text_type): code = analyzer.code.decode(analyzer.encoding) else: code = analyzer.code entry = code, analyzer.tags, {}, refname env._viewcode_modules[modname] = entry elif entry is False: return _, tags, used, _ = entry if fullname in tags: used[fullname] = docname return True for objnode in doctree.traverse(addnodes.desc): if objnode.get('domain') != 'py': continue names = set() for signode in objnode: if not isinstance(signode, addnodes.desc_signature): continue modname = signode.get('module') fullname = signode.get('fullname') refname = modname if env.config.viewcode_import: modname = get_full_modname(modname, fullname) if not modname: continue if not has_tag(modname, fullname, env.docname, refname): continue if fullname in names: # only one link per name, please continue names.add(fullname) pagename = '_modules/' + modname.replace('.', '/') onlynode = addnodes.only(expr='html') onlynode += addnodes.pending_xref( '', reftype='viewcode', refdomain='std', refexplicit=False, reftarget=pagename, refid=fullname, refdoc=env.docname) onlynode[0] += nodes.inline('', _('[source]'), classes=['viewcode-link']) signode += onlynode def missing_reference(app, env, node, contnode): # resolve our "viewcode" reference nodes -- they need special treatment if node['reftype'] == 'viewcode': return make_refnode(app.builder, node['refdoc'], node['reftarget'], node['refid'], contnode) def collect_pages(app): env = app.builder.env if not hasattr(env, '_viewcode_modules'): return highlighter = app.builder.highlighter urito = app.builder.get_relative_uri modnames = set(env._viewcode_modules) app.builder.info(' (%d module code pages)' % len(env._viewcode_modules), nonl=1) for modname, entry in iteritems(env._viewcode_modules): if not entry: continue code, tags, used, refname = entry # construct a page name for the highlighted source pagename = '_modules/' + modname.replace('.', '/') # highlight the source using the builder's highlighter highlighted = highlighter.highlight_block(code, 'python', linenos=False) # split the code into lines lines = highlighted.splitlines() # split off wrap markup from the first line of the actual code before, after = lines[0].split('
')
        lines[0:1] = [before + '
', after]
        # nothing to do for the last line; it always starts with 
anyway # now that we have code lines (starting at index 1), insert anchors for # the collected tags (HACK: this only works if the tag boundaries are # properly nested!) maxindex = len(lines) - 1 for name, docname in iteritems(used): type, start, end = tags[name] backlink = urito(pagename, docname) + '#' + refname + '.' + name lines[start] = ( '
%s' % (name, backlink, _('[docs]')) + lines[start]) lines[min(end - 1, maxindex)] += '
' # try to find parents (for submodules) parents = [] parent = modname while '.' in parent: parent = parent.rsplit('.', 1)[0] if parent in modnames: parents.append({ 'link': urito(pagename, '_modules/' + parent.replace('.', '/')), 'title': parent}) parents.append({'link': urito(pagename, '_modules/index'), 'title': _('Module code')}) parents.reverse() # putting it all together context = { 'parents': parents, 'title': modname, 'body': _('

Source code for %s

') % modname + \ '\n'.join(lines) } yield (pagename, context, 'page.html') if not modnames: return app.builder.info(' _modules/index') html = ['\n'] # the stack logic is needed for using nested lists for submodules stack = [''] for modname in sorted(modnames): if modname.startswith(stack[-1]): stack.append(modname + '.') html.append('
    ') else: stack.pop() while not modname.startswith(stack[-1]): stack.pop() html.append('
') stack.append(modname + '.') html.append('
  • %s
  • \n' % ( urito('_modules/index', '_modules/' + modname.replace('.', '/')), modname)) html.append('' * (len(stack) - 1)) context = { 'title': _('Overview: module code'), 'body': _('

    All modules for which code is available

    ') + \ ''.join(html), } yield ('_modules/index', context, 'page.html') def setup(app): app.add_config_value('viewcode_import', True, False) app.connect('doctree-read', doctree_read) app.connect('html-collect-pages', collect_pages) app.connect('missing-reference', missing_reference) #app.add_config_value('viewcode_include_modules', [], 'env') #app.add_config_value('viewcode_exclude_modules', [], 'env') wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/local/0000755000077000000240000000000012553237435024034 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/local/python3links.inv0000644000077000000240000000074312532571254027220 0ustar tomstaff00000000000000# Sphinx inventory version 2 # Project: Python # Version: 3.4 # The remainder of this file is compressed using zlib. xœ¥“OSƒ0Åïù;Ó‹ÀñÏ©÷z®¶SωÜl:à§7@­i‡:¨²ï÷–äm°i*eZPf†-u°Grʸ X“}CÉKXw\YVvcu ÷éCøÜV„u¦L¶®”ƒRiWY¯ Ȥ­Bç°ï”y…­òT䣃¦[–ÞHî[&·*”QwóµæÒŠk½µ‰Øª­ç‘¥ÅVbsÎ𠔈Ü+Í*mÞo®·‘:sî‡öeÄjåf‘ƒ.â¸kp7è"nÐ×R(æà±ïÉœPpÑe²Ã¶"ÌŠµµzÕ¢ô<ðŸnމ{õ˜>õÏIÿ±>XÆÒD4¤ _]ÏLvPêSÊÐwcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/local/python3links.txt0000644000077000000240000000233612532571254027243 0ustar tomstaff00000000000000# Sphinx inventory version 2 # Project: Python # Version: 3.4 # The remainder of this file should be compressed using zlib. bytes py:function -1 library/functions.html#bytes - TimeoutError py:exception -1 library/exceptions.html#TimeoutError - builtins.object py:class -1 library/functions.html#object - builtins.list py:class -1 library/functions.html#list - builtins.type py:class -1 library/functions.html#type - builtins.classmethod py:class -1 library/functions.html#classmethod - builtins.SyntaxWarning py:exception -1 library/exceptions.html#SyntaxWarning - builtins.RuntimeWarning py:exception -1 library/exceptions.html#RuntimeWarning - builtins.ValueError py:exception -1 library/exceptions.html#ValueError - object py:function -1 library/functions.html#object - object py:class -1 library/functions.html#object - urllib.request.urlopen py:function -1 library/urllib.request.html#urllib.request.urlopen - concurrent.futures.Future py:class -1 library/concurrent.futures.html#concurrent.futures.Future - concurrent.futures.ThreadPoolExecutor py:class -1 library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor - queue.Queue py:class -1 library/queue.html#queue.Queue - print() py:function -1 library/functions.html#print - wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/setup_package.py0000644000077000000240000000050412346274067026130 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst def get_package_data(): # Install the theme files return { 'astropy_helpers.sphinx': [ 'ext/templates/*/*', 'local/*.inv', 'themes/bootstrap-astropy/*.*', 'themes/bootstrap-astropy/static/*.*']} wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/0000755000077000000240000000000012553237435024227 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/0000755000077000000240000000000012553237435027743 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/globaltoc.html0000644000077000000240000000011112346274067032572 0ustar tomstaff00000000000000

    Table of Contents

    {{ toctree(maxdepth=-1, titles_only=true) }} wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/layout.html0000644000077000000240000000655012346274067032156 0ustar tomstaff00000000000000{% extends "basic/layout.html" %} {# Collapsible sidebar script from default/layout.html in Sphinx #} {% set script_files = script_files + ['_static/sidebar.js'] %} {# Add the google webfonts needed for the logo #} {% block extrahead %} {% if not embedded %}{% endif %} {% endblock %} {% block header %}
    {{ theme_logotext1 }}{{ theme_logotext2 }}{{ theme_logotext3 }}
    • Index
    • Modules
    • {% block sidebarsearch %} {% include "searchbox.html" %} {% endblock %}
    {% endblock %} {% block relbar1 %} {% endblock %} {# Silence the bottom relbar. #} {% block relbar2 %}{% endblock %} {%- block footer %}

    {%- if edit_on_github %} {{ edit_on_github_page_message }}   {%- endif %} {%- if show_source and has_source and sourcename %} {{ _('Page Source') }} {%- endif %}   Back to Top

    {%- if show_copyright %} {%- if hasdoc('copyright') %} {% trans path=pathto('copyright'), copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
    {%- else %} {% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
    {%- endif %} {%- endif %} {%- if show_sphinx %} {% trans sphinx_version=sphinx_version|e %}Created using Sphinx {{ sphinx_version }}.{% endtrans %}   {%- endif %} {%- if last_updated %} {% trans last_updated=last_updated|e %}Last built {{ last_updated }}.{% endtrans %}
    {%- endif %}

    {%- endblock %} wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/localtoc.html0000644000077000000240000000004212346274067032427 0ustar tomstaff00000000000000

    Page Contents

    {{ toc }} wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/searchbox.html0000644000077000000240000000042012346274067032605 0ustar tomstaff00000000000000{%- if pagename != "search" %}
    {%- endif %} wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/0000755000077000000240000000000012553237435031232 5ustar tomstaff00000000000000././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_linkout.svgwcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_linkout.s0000644000077000000240000001212112532571254034656 0ustar tomstaff00000000000000 ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_linkout_20.pngwcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_linkout_20000644000077000000240000000327512346274067034655 0ustar tomstaff00000000000000‰PNG  IHDR[â8A bKGDÿÿÿ ½§“ oFFsvek pHYs × ×B(›x vpAg\@0¢Ð¬IDATXÃå˜iŒ_SÆϘÚ+Új‹fF« BH‘XbOÐέ†ª}‰-Z¤Abû¢$¤Öi…V#¸T•ZCÕ– µIi™ÚU”d¦ª÷ý›;·÷?™)Ó*OrsïyÏsÏûžçžóžs®è!ج’ôLOùÙ`[À–=é`œ3|¼±;»1`{ÛͶﱽÔv]mú«ßØÞX°=˜l¦y’Zjs„á@30ŒlÈ<,éÝ’ÆöÆ @+ð60SÒ϶ûÇG½í‰ñü¡¤mo œ¬‘t—íþÀ%À `¶¤4üÔ pÐX<,’Ô1¦„:`•R~qÂPà` ð.°0kœÐ¨WJéŒs¶@R>)é÷ÎÀ´Ntž$éS`6p6pTØím¢5…—ÿÆHš“s8˜Éã{à@`»¿ ÷J:×v=ð%``/à9`çàœ/iší~À\`ÿbŸ{ƒçœH7KBäÝ€§"Æ“o€f¥´:¡/°hRÊʱ' J™\"ö`ànàÜ*ý[!©ÍöåÀ”ˆÿ `'I­ØÆö¶µ}Ÿí ¶o´Ý9÷#Ûg›Ùþ6ì l²}’í—m¿h[¶›lO·ýeð~ŽòtÛgE;õnÇÛkmϳ=Ëö^ÑÎKQ¿&âš~*¸² Ò NøÑ §ìµNxÊ ×æl30¡L-'ÌwÂ~¥uö ÛOÒ lOŒ˜Ïm)†ÙÞ©`»"×±ÁakÈÙšs\"5äߟ[m,ˆÝfû˜Bý±¹ú 9{ígÃþ[Œþ¼Ø“ªØà„'(Ê8á}'ëðú;aqÑ^{N•:l_q-ãÔHZ"éëx©.„Ü5ÇkŠû×ÀOñ|[ì86—„¤_Y?Ü-éé‚í¸¸ÿB6m‰8×wDqkÚ×… ÚÊ(eY´5$ʯwdz"ðD%¿—iZMh²´1/éѪbÛîmûZÛŸ‘åÒ¸0Çë] ŒV’-Ž_Ù¾9öÕ냲…ª1îK%­)Ôå®AÝðÓBûº08­À9•lî *±íN¶à'’ž M/ÎØÛÛo×;·GcJ=IÏÛ€€þÀeÀ›¶û®§àÕ:T6’܆ò}ÖæÊ³€£œP à„F 7°¸“6J}Kú h,ÌÐa¡S‡ÎŒŠV`¤¤‹%½üXU é[I—»WEÀÿˆÔ°<îM¶‹;¤Á¹çeÝh³1ÏWÊjà% 2úF3;I!±ËF6’Z ¦âÇ¥†ÈcÀrIKªtªÝ›=¢"€¤VIS€rªà·¸°½Y7Å®ï·ÎÈù8/ŠmÀü®4æ„}Õdg‡<¦çÄóhàÁ.4§.p*Úv»ø*žw·}=YJ9ÖÝÙ¼,²=øì”…9ú;À @_`†í¹ÀÊ.þ'IÉöê#{lï |Hv868·Hú¦ðÞÞNRòûï-ÈRãÍ%£öM Þ ûµJÿšQÕÐVCvNé öŒ¶¸&ìk"À“ÉrrÉv$Ä•Ç:ŽŒidi¥8%®WiµU!i­íÑÀcáçÒ\õÀý¹XóÌsÂL²…w7`2°¸o?)8áNàqàÖ.ŠØd{rxS˜yÙ¾ÓÞ¸˜,¡¯î—ôží1À²³ýòàöŽúß‘”æåOtÁ\ V $MSë©A{UÒGeÑFºj&;öö#›IIZg‹dK| ó€=ÉÆJYTM'lE¶»¤”–ÎÔ‹³Äé]ü(¯Hú üMq¨¹h=ÞÛÏ ¯lˆkþ~›<&wmGÿk±pYº™½!üõäÿì%âÿÈ#ÀædëÀX¥·h=…ÿ’ØSß»À3p5™Ø‹óÛĞƟ ½§pÅ%tEXtdate:create2012-10-18T20:57:33+02:00¢p_f%tEXtdate:modify2012-10-18T20:57:33+02:00Ó-çÚtEXtSoftwarewww.inkscape.org›î<IEND®B`‚wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo.ico0000644000077000000240000010033412532571254034445 0ustar tomstaff00000000000000@@ (@F  (n@ ( –P (¾Y(@€ ÿÿ ÿ* ÿVýy ý›¬±ûÕúûüí÷ùüìýýýíýýýí§ªû× ü«ý‹ýoüKÿ ÿ ÿÿîûHýýÌúìýó ûøûü°µÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ˜Ÿÿÿûþ ûúûöýòúéûÇýÿIóÿ¿ÿ!ýyûÏüðüúÿÿÿÿÿÿ ÿÿ>KÿÿÏÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‡ÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿûúÿðûÚü—û?ã ÿÿý|ûÚýöÿÿÿÿÿÿþÿýÿýÿLYþÿÌÏÿÿûüÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿerþÿýÿýÿýÿýÿýÿþÿÿÿÿÿÿÿüûûíú½ÿZÿÿüJûÇýöÿÿÿÿþÿýÿýÿýÿ*<þÿ™¡ÿÿêíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÎÿÿ3Eýÿ ýÿýÿýÿýÿýÿýÿýÿýÿþÿÿÿÿÿÿÿÿðûÄüXÿÿü•üêÿÿÿÿþÿýÿýÿýÿ1ýÿ“þÿäèÿÿûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿrþÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿÿÿÿÿÿÿüïù´ÿ=ÿø$û®ýúÿÿÿÿýÿýÿýÿýÿ.Cþÿ·¿ÿÿùúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ”Ÿþÿ*ýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿÿÿÿÿÿÿúâû†ÿÿ3üÃüþÿÿýÿýÿýÿýÿýÿ^pþÿÓÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷øÿÿ…“þÿ+ýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿÿÿÿÿýöü¸ÿ7 ÿ(øÃ!ÿÿ ÿÿ ýÿ ýÿ ýÿýÿýÿsƒþÿåéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅÍþÿPfýÿ %ýÿýÿýÿ ýÿ ýÿ ýÿ ýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿþÿÿÿ ÿÿûÙ ÿi#ÿ úº#ÿÿ"ÿÿ"ýÿ"ýÿ"ýÿ ýÿ ýÿy‹ÿÿîðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâåþÿu‡ýÿ =ýÿýÿýÿ!ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ!ýÿ!ÿÿ!ÿÿ ûìýƒÿÿ$ý›$ýÿ$ÿÿ$ýÿ$ýÿ$ýÿ"ýÿýÿmþÿëîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýÿÿ¦²þÿ8Týÿ%ýÿýÿ!ýÿ$ýÿ$ýÿ$ýÿ$ýÿ$ýÿ#ýÿ#ýÿ#ýÿ"ýÿ"ýÿ"ýÿ"ýÿ#ýÿ#ýÿ#ýÿ$ýÿ$ýÿ$ýÿ$ýÿ$ýÿ$ýÿ#ýÿ#ýÿ$þÿ$ÿÿ#üõ!ü’'ÿ &ÿj'ûñ(ÿÿ&ýÿ&ýÿ&ýÿ&ýÿ!ýÿNiþÿÞãÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçëþÿmƒýÿ5ýÿ ýÿ ýÿ%ýÿ&ýÿ&ýÿ&ýÿ%ýÿ%ýÿ$ýÿ#ýÿ#ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ#ýÿ#ýÿ$ýÿ$ýÿ%ýÿ&ýÿ&ýÿ&ýÿ&ýÿ&ýÿ&ýÿ&þÿ&ÿÿ%ýø&üš3ÿ)ÿ%(ûØ*ÿÿ)ýÿ)ýÿ)ýÿ(ýÿ%ýÿ'IþÿÇÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙßþÿUqýÿ'ýÿ!ýÿ'ýÿ)ýÿ(ýÿ(ýÿ(ýÿ'ýÿ&ýÿ#ýÿ(ýÿ"DþÿPkþÿp†þÿ‡™þÿ’£þÿ‘¢þÿ„˜þÿm„þÿNjþÿ!Cþÿ&ýÿ"ýÿ%ýÿ&ýÿ'ýÿ(ýÿ(ýÿ(ýÿ(ýÿ(ýÿ(ýÿ(ÿÿ&üú'ü˜9ÿ ÿ+ý”*þÿ+ÿÿ*þÿ+þÿ+þÿ)þÿ*þÿ®ÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàåÿÿQoþÿ%þÿ%þÿ+þÿ+þÿ+þÿ+þÿ*þÿ'þÿ$þÿ"Gþÿt‹ÿÿ¶ÂÿÿÔÛÿÿäèÿÿïñÿÿöøÿÿúûÿÿúûÿÿö÷ÿÿîñÿÿãèÿÿÔÛÿÿ¹Åÿÿ}’ÿÿ/Rþÿ'þÿ&þÿ)þÿ)þÿ*þÿ*þÿ*þÿ*þÿ*þÿ*ÿÿ'ûù'ý‰Uª+ÿ;-üæ.ÿÿ-þÿ-þÿ-þÿ,þÿ)þÿVtÿÿêîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíñÿÿ]zþÿ(þÿ'þÿ-þÿ-þÿ-þÿ-þÿ,þÿ$þÿFþÿ‰ÿÿÒÚÿÿðóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóõÿÿ×Þÿÿ£³ÿÿ?`ÿÿ)þÿ)þÿ,þÿ,þÿ,þÿ,þÿ,þÿ,þÿ.ÿÿ,üñ.ýt@ÿ/ý™/þÿ0ÿÿ0þÿ0þÿ0þÿ-þÿ :þÿ¿Ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿz“þÿ1þÿ(þÿ0þÿ/þÿ.þÿ/þÿ,þÿ+þÿZwÿÿÇÑÿÿøúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜâÿÿ”§ÿÿ#Lþÿ'þÿ.þÿ/þÿ/þÿ/þÿ/þÿ/þÿ0ÿÿ.üâ-ÿI0ÿ%0ýá2ÿÿ1þÿ1þÿ1þÿ0þÿ/þÿbÿÿðóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯¿þÿHþÿ)þÿ1þÿ2þÿ2þÿ1þÿ.þÿ8þÿx’ÿÿæëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿÿÄÏÿÿTsÿÿ+þÿ/þÿ1þÿ0þÿ0þÿ0þÿ1ÿÿ1ÿÿ/üÈ2ÿ$@¿3ýn3üø5ÿÿ3þÿ3þÿ3þÿ1þÿ8þÿÀÌÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿëïÿÿEkþÿ,þÿ2þÿ4þÿ3þÿ4þÿ1þÿ8þÿ€šÿÿñôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôöÿÿÕÞÿÿËÕÿÿËÖÿÿ×ßÿÿõöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâçÿÿqÿÿ1þÿ0þÿ3þÿ2þÿ2þÿ2þÿ3ÿÿ2þÿ0üŸ@ÿã 2ü¶6üþ6ÿÿ6þÿ6þÿ5þÿ5þÿDlþÿèíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ”«þÿ @þÿ/þÿ6þÿ5þÿ5þÿ4þÿ0þÿt‘ÿÿñôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿäéÿÿ—­þÿ\~þÿ?eþÿ1\þÿ,Xþÿ,Xþÿ2]þÿ?fþÿZ}þÿ§þÿÖßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïòÿÿu’ÿÿ3þÿ3þÿ5þÿ5þÿ5þÿ5þÿ6ÿÿ4üð4ÿX8ÿ 5ûå:ÿÿ8þÿ8þÿ8þÿ7þÿ7þÿ–®ÿÿûüÿÿÿÿÿÿÿÿÿÿÿÿÿÿðôÿÿ@jþÿ0þÿ8þÿ8þÿ8þÿ8þÿ.þÿRxÿÿæëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñóÿÿާþÿ:eþÿEþÿ1þÿ*þÿ-þÿ.þÿ.þÿ-þÿ*þÿ0þÿCþÿ3]þÿj‹þÿËÖþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíòÿÿlŒÿÿ1þÿ6þÿ8þÿ7þÿ7þÿ8þÿ8ÿÿ5ýÌ5ÿ:ÿO9üô<ÿÿ:þÿ:þÿ:þÿ8þÿ BþÿÏÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÁþÿMþÿ3þÿ;þÿ:þÿ;þÿ7þÿOþÿ»ËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÕÞþÿ^„þÿ@þÿ/þÿ4þÿ9þÿ:þÿ:þÿ:þÿ9þÿ9þÿ9þÿ8þÿ4þÿ.þÿ6þÿ/]þÿ‹¥þÿóõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàçÿÿMuÿÿ3þÿ9þÿ9þÿ9þÿ9þÿ;ÿÿ8ûý8ÿÿ<ÿ{;ü÷=ÿÿ<þÿ<þÿ<þÿ;þÿ9hþÿæìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿcˆþÿ<þÿ:þÿ<þÿ<þÿ<þÿ2þÿx™ÿÿõøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒÝþÿOyþÿ6þÿ5þÿ<þÿ=þÿ<þÿ<þÿ<þÿ<þÿ<þÿ<þÿ<þÿ<þÿ<þÿ<þÿ9þÿ2þÿ Aþÿf‹þÿàçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅÓÿÿ!Sþÿ9þÿ;þÿ;þÿ;þÿ<þÿ=ÿÿ9üÝ;ÿ'=ý¢?ûý@ÿÿ?þÿ?þÿ=þÿ?þÿkÿÿðôÿÿÿÿÿÿÿÿÿÿÿÿÿÿñôÿÿ7gþÿ5þÿ>þÿ>þÿ>þÿ;þÿMþÿ¾Îÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêïÿÿc‰þÿ8þÿ9þÿ?þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ?þÿ>þÿ7þÿ:þÿ[„þÿàèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿÿ‘¬ÿÿ=þÿ<þÿ>þÿ>þÿ>þÿ@ÿÿ>üþ>ýˆÿAþ¿BÿÿBÿÿAþÿAþÿ?þÿBþÿ•°ÿÿúüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉ×ÿÿ#[þÿ9þÿAþÿAþÿAþÿ:þÿUÿÿäëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ”°þÿ Fþÿ9þÿAþÿ@þÿ@þÿ@þÿ>þÿ:þÿ6þÿ5þÿ5þÿ7þÿ;þÿ?þÿ@þÿ@þÿ@þÿ@þÿAþÿ;þÿ=þÿeþÿñõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãëÿÿ>oþÿ>þÿ@þÿ@þÿ@þÿAþÿBÿÿ?üÝ<ÿBûÒDÿÿCÿÿCþÿCþÿAþÿDþÿ³Çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ºþÿTþÿ>þÿCþÿCþÿCþÿ9þÿŒ«ÿÿûýÿÿÿÿÿÿÿÿÿÿÿÿÿÿâêÿÿEvþÿ7þÿCþÿCþÿCþÿ>þÿ4þÿDþÿBsþÿs˜þÿƒ£ÿÿ„£ÿÿjÿÿ0fþÿ>þÿ:þÿBþÿBþÿBþÿBþÿCþÿ;þÿ Fþÿˆ¦þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿÿ§¾ÿÿCþÿ@þÿBþÿBþÿBþÿDÿÿBûúBýhUÿEûãGÿÿEþÿEþÿEþÿBþÿFþÿÈÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‡¨þÿOþÿAþÿEþÿEþÿDþÿ@þÿ®Äÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©ÁþÿYþÿ?þÿFþÿCþÿ9þÿ&aþÿ¡ÿÿ¨ÀÿÿÔàÿÿöùÿÿÿÿÿÿÿÿÿÿïóÿÿÈÖÿÿ—³ÿÿ?rÿÿ?þÿBþÿEþÿEþÿEþÿEþÿ=þÿ$_þÿÇÖþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâêÿÿ4kþÿCþÿDþÿDþÿDþÿDÿÿEýþBüÄ@ÿ FúêJÿÿHþÿHþÿHþÿEþÿIþÿÕáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿxžþÿMþÿDþÿGþÿGþÿFþÿ Oþÿ¾Ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚¥þÿIþÿEþÿ?þÿHþÿ_Šÿÿ¿ÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒßÿÿbŽÿÿHþÿEþÿGþÿGþÿGþÿEþÿEþÿ\‰þÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿùûÿÿ‰ªÿÿEþÿEþÿGþÿGþÿGþÿIÿÿDûñJÿ4IûåLÿÿJþÿJþÿJþÿGþÿLþÿÙäÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿtœþÿNþÿGþÿJþÿJþÿHþÿZþÿÃÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿp™þÿBþÿ=þÿ ]ÿÿЬÿÿêðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèïÿÿ]ŒÿÿBþÿIþÿIþÿIþÿJþÿAþÿ `þÿÆ×þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÚÿÿ PþÿGþÿIþÿIþÿIþÿKÿÿHüùJÿxLúàNÿÿLÿÿLþÿLþÿIþÿNþÿÖãÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ{¢þÿ RþÿIþÿLþÿLþÿJþÿ\þÿÃÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿrœþÿ;þÿ.hÿÿ¬ÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÛÿÿ+iÿÿGþÿKþÿKþÿKþÿHþÿNþÿo™þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçîÿÿ5pþÿJþÿKþÿKþÿKþÿKÿÿKüþLü¿OûÓPÿÿNÿÿNþÿNþÿLþÿOþÿÈÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°þÿYþÿJþÿNþÿNþÿMþÿRþÿ¼Ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€¦þÿ5nÿÿ®ÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøûÿÿŠ®ÿÿFþÿMþÿNþÿNþÿNþÿFþÿ9uþÿô÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿðõÿÿnšÿÿMþÿKþÿMþÿMþÿMþÿOÿÿLûéPüºQþÿQÿÿQþÿQþÿOþÿRþÿ±Éÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÆÿÿbþÿJþÿPþÿPþÿPþÿHþÿ¨ÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÏÿÿ¹ÐÿÿüýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÕÿÿ\þÿNþÿPþÿPþÿPþÿIþÿ!gþÿÈÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿûýÿÿ™¹ÿÿPþÿNþÿPþÿPþÿPþÿRÿÿPüïRýŸQüüTÿÿSþÿSþÿQþÿTþÿ‘µÿÿùûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚæÿÿ'mþÿJþÿSþÿSþÿSþÿJþÿ}§ÿÿõøÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ùÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûüÿÿüýÿÿÿÿÿÿÿÿÿÿÿÿÿÿØäÿÿAÿÿNþÿRþÿRþÿRþÿMþÿ`þÿ›¼þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÐÿÿTþÿPþÿRþÿRþÿRþÿTÿÿPüíVÿ}UüøVÿÿUþÿUþÿSþÿTþÿf™ÿÿïôÿÿÿÿÿÿÿÿÿÿÿÿÿÿûýÿÿF„þÿOþÿTþÿUþÿUþÿQþÿ9{ÿÿØåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑàÿÿœ½ÿÿéðÿÿÿÿÿÿÿÿÿÿÿÿÿÿæîÿÿ_“ÿÿNþÿTþÿTþÿTþÿPþÿ Zþÿ~¨þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑàÿÿVþÿQþÿTþÿTþÿTþÿVÿÿRüíVÿPWüóYÿÿWþÿWþÿVþÿUþÿ0wþÿåîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿˆ±þÿ _þÿSþÿWþÿWþÿVþÿXþÿ¡ÁÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçïÿÿSÿÿ:}þÿÖäÿÿÿÿÿÿÿÿÿÿÿÿÿÿìóÿÿjÿÿPþÿVþÿVþÿVþÿTþÿYþÿjœþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛçÿÿ ]þÿSþÿVþÿVþÿVþÿXÿÿVüíZÿ"Xúì\ÿÿYþÿYþÿYþÿWþÿ^þÿÃÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜéÿÿ-vþÿQþÿYþÿYþÿYþÿRþÿ;€ÿÿÙæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßêÿÿb™ÿÿQþÿ9þÿÛèÿÿÿÿÿÿÿÿÿÿÿÿÿÿëòÿÿhœÿÿSþÿYþÿYþÿYþÿWþÿZþÿb™þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞéÿÿeþÿWþÿXþÿXþÿXþÿ[ÿÿXüífÿ XüÇ]ýþ\ÿÿ\þÿ\þÿZþÿZþÿ~¬ÿÿ÷úÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿzªþÿ^þÿWþÿ\þÿ[þÿ[þÿWþÿd›ÿÿêòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿×ÿÿOÿÿXþÿKþÿNŽþÿó÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿáìÿÿV’ÿÿVþÿ[þÿ[þÿ[þÿYþÿ\þÿeœþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÝéÿÿ dþÿYþÿ[þÿ[þÿ[þÿ^ÿÿ[üífÿ_ý„]üù_ÿÿ^þÿ^þÿ]þÿ\þÿ*xþÿÜèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàëÿÿ<„þÿXþÿ]þÿ^þÿ^þÿ\þÿ_þÿdÿÿÓäÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑâÿÿ‡³ÿÿ)wÿÿTþÿ[þÿYþÿt§þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒâÿÿ4þÿYþÿ]þÿ]þÿ]þÿZþÿaþÿr¥þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙçÿÿ`þÿZþÿ]þÿ]þÿ]þÿ`ÿÿ]üíÿbÿ<`ûñcÿÿ`þÿ`þÿ`þÿ^þÿ]þÿ˜¿ÿÿûýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÌþÿoþÿYþÿ`þÿ`þÿ`þÿ]þÿ[þÿBˆÿÿ—¾ÿÿÏáÿÿøúÿÿÿÿÿÿüýÿÿäîÿÿ´Ðÿÿ‹·ÿÿ?‡ÿÿZþÿYþÿ`þÿWþÿ"vþÿ½Õþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¹Óÿÿeþÿ]þÿ_þÿ_þÿ_þÿ\þÿhþÿеþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÜÿÿ`þÿ\þÿ_þÿ_þÿ_þÿbÿÿ]üímíbýÌdýþbþÿbþÿbþÿbþÿaþÿ/€þÿÚèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‘»þÿiþÿ[þÿaþÿbþÿbþÿaþÿZþÿ_þÿ;†þÿr¨ÿÿ°ÿÿy¬ÿÿW—þÿoþÿWþÿ[þÿaþÿbþÿ_þÿ]þÿp§þÿøûÿÿÿÿÿÿÿÿÿÿÿÿÿÿùûÿÿ‰·ÿÿYþÿaþÿbþÿbþÿbþÿ]þÿrþÿ¬Ìþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿ­Ìÿÿbþÿ_þÿaþÿaþÿaþÿdÿÿ_üíUªeýwdüùgÿÿeþÿeþÿeþÿdþÿ`þÿy®ÿÿùûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýþÿÿºþÿoþÿ\þÿbþÿdþÿdþÿdþÿcþÿ_þÿZþÿYþÿZþÿ\þÿaþÿdþÿdþÿdþÿaþÿ]þÿGþÿÔäþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØçÿÿ9‡ÿÿ_þÿdþÿdþÿdþÿdþÿ\þÿ(|þÿÜêÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ûÿÿ‰·ÿÿeþÿbþÿdþÿdþÿdþÿgÿÿdüígÿ%füâjÿÿgþÿgþÿgþÿgþÿeþÿpþÿ°Ïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ Æþÿ3…þÿcþÿ_þÿfþÿgþÿgþÿgþÿfþÿfþÿfþÿfþÿfþÿfþÿfþÿ_þÿcþÿG‘þÿÆÝþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿÿ˜Áÿÿcþÿeþÿfþÿfþÿfþÿeþÿ`þÿGþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿìôÿÿZ›þÿeþÿeþÿfþÿfþÿfþÿiÿÿfüíÿiý—hýýkÿÿiþÿiþÿiþÿhþÿeþÿ5‡þÿÍáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËáþÿg¥þÿ'}þÿeþÿ`þÿdþÿfþÿgþÿhþÿhþÿgþÿeþÿaþÿbþÿwþÿj§þÿØèþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐäÿÿ5‡ÿÿcþÿhþÿhþÿhþÿhþÿdþÿ pþÿ‰¹þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàíÿÿ&þÿfþÿgþÿhþÿhþÿhþÿkÿÿhüíjÿ0kúánÿÿkþÿkþÿkþÿkþÿjþÿeþÿN˜ÿÿ×éÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¹Öþÿi¨þÿ=þÿ|þÿ qþÿhþÿdþÿfþÿlþÿvþÿ0…þÿXžþÿ«Îþÿüýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïöÿÿd¦ÿÿdþÿjþÿkþÿkþÿkþÿkþÿdþÿ*„þÿØéÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿ¼ØÿÿkþÿhþÿjþÿjþÿjþÿjþÿmÿÿküínýmüþpÿÿnþÿnþÿnþÿnþÿmþÿgþÿSœÿÿÑåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáîÿÿ«Ïþÿ‡ºþÿmªþÿ_¤þÿe§þÿx±þÿ˜ÃþÿÊáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòøÿÿ|µÿÿnþÿkþÿmþÿmþÿmþÿmþÿjþÿmþÿl«þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôùÿÿq®ÿÿlþÿlþÿmþÿmþÿmþÿmþÿpÿÿküïuÿ%mýÔrÿÿpþÿpþÿpþÿpþÿpþÿoþÿiþÿD•ÿÿ·×ÿÿûýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìôÿÿ~·ÿÿ tþÿkþÿoþÿoþÿnþÿjþÿkþÿiþÿ.‰þÿÒåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙêÿÿ#‚þÿmþÿnþÿoþÿoþÿoþÿoþÿrÿÿoüérÿgpûôuÿÿqþÿrþÿrþÿrþÿrþÿqþÿlþÿþÿÁÿÿáîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÕèÿÿj¬ÿÿsþÿoþÿqþÿqþÿpþÿsþÿ~þÿtþÿtþÿ¿þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿÿ•ÄÿÿnþÿoþÿqþÿqþÿqþÿqþÿqÿÿrýþnüÂ`ÿtü«vÿÿuÿÿtþÿtþÿtþÿtþÿtþÿtþÿqþÿsþÿR ÿÿ²Õÿÿãðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâïÿÿ§Ïÿÿ:“ÿÿoþÿrþÿtþÿtþÿtþÿmþÿ%ˆþÿ—Æþÿn°þÿb©þÿóøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜìÿÿ0þÿrþÿrþÿsþÿsþÿsþÿsþÿuÿÿsüúrýyxÿ1výÓzÿÿwþÿwþÿwþÿwþÿwþÿwþÿvþÿuþÿpþÿ {þÿW¤ÿÿ©ÒÿÿÑæÿÿëôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð÷ÿÿÔèÿÿ«ÑÿÿT¢ÿÿxþÿqþÿuþÿuþÿuþÿvþÿsþÿ vþÿp²þÿÿÿÿÿï÷ÿÿåñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿÿ‰Àÿÿsþÿuþÿvþÿvþÿvþÿvþÿvþÿyÿÿuüéwÿ/xÿ[wûê|ÿÿyþÿxþÿxþÿxþÿxþÿyþÿyþÿxþÿwþÿtþÿvþÿ+þÿh°ÿÿ›Êÿÿ¼ÜÿÿÊãÿÿÒçÿÿÔèÿÿÒèÿÿÍåÿÿÃàÿÿ§Ñÿÿt¶ÿÿ2“þÿwþÿsþÿwþÿxþÿxþÿxþÿxþÿxþÿqþÿ7”þÿÙëÿÿÿÿÿÿÿÿÿÿýÿÿÿýþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÃßÿÿ…þÿvþÿxþÿxþÿwþÿwþÿwþÿyÿÿxÿÿwüª’ÿ|û„xûù~ÿÿ{þÿzþÿzþÿzþÿzþÿzþÿzþÿzþÿzþÿzþÿxþÿwþÿuþÿxþÿ…þÿ)þÿ-’þÿ)þÿŠþÿ|þÿuþÿwþÿxþÿzþÿzþÿzþÿ{þÿ{þÿ{þÿ{þÿvþÿ €þÿ‰ÁþÿþþÿÿÿÿÿÿÿÿÿÿþþÿÿúüÿÿþÿÿÿÿÿÿÿÝíÿÿO¤ÿÿvþÿyþÿyþÿyþÿyþÿyþÿzþÿ|ÿÿwûï|ÿHÿŽÿ {ü—~ýú€ÿÿ}þÿ}þÿ}þÿ}þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ{þÿ{þÿ{þÿzþÿ{þÿ{þÿ{þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿwþÿP¥þÿôùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿýþÿÿõúÿÿ†Áÿÿyþÿ{þÿ}þÿ|þÿ|þÿ|þÿ|þÿ}ÿÿ}ÿÿzû«’ÿ€ÿ€ý¢‚ýýƒÿÿ€þÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿyþÿ!þÿ«ÕþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëõÿÿÀþÿ„þÿ}þÿ~þÿ~þÿ~þÿ~þÿþÿ‚ÿÿ~ûä}ÿ7„ÿú¨ƒüû…ÿÿ‚ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿ}ÿÿb±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüþÿÿ¿ßÿÿ/˜ÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿƒÿÿ€ýùý€ÿ€ÿüž…üù‡ÿÿ„ÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿ‚ÿÿ„ÿÿn¹ÿÿúýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòùÿÿÇäÿÿšÎÿÿ; ÿÿƒÿÿƒÿÿƒÿÿƒÿÿ‚ÿÿ…ÿÿ…ÿÿ€ü²ˆÿ’ÿ…ý’„üòŠÿÿ‡ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿƒÿÿ‚ÿÿÿÿ€ÿÿ‚ÿÿ]±ÿÿåóÿÿùýÿÿÿÿÿÿÿÿÿÿàðÿÿ¼àÿÿƒÄÿÿ“ÿÿƒÿÿ„ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ†ÿÿˆÿÿ‚ýÌ‚ÿ+€ÿ‰ýu‰üáŒÿÿŠÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‰ÿÿ‘ÿÿ•ÿÿ •ÿÿ%–ÿÿg¸ÿÿËçÿÿ³Ûÿÿ¬ØÿÿÕëÿÿ©ÖÿÿL«ÿÿ‰ÿÿ…ÿÿ†ÿÿ†ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‰ÿÿŒÿÿ†ýÔ‡ÿ@‹üMˆüÈüûŽÿÿ‹ÿÿŠÿÿŠÿÿŠÿÿŠÿÿŠÿÿŠÿÿŠÿÿŠÿÿŠÿÿŠÿÿ‰ÿÿ‰ÿÿ‰ÿÿ‰ÿÿ†ÿÿ•ÿÿxÁÿÿ«Øÿÿ¦ÖÿÿÓêÿÿëöÿÿs¾ÿÿ‰ÿÿ’ÿÿ&›ÿÿˆÿÿˆÿÿˆÿÿˆÿÿ‰ÿÿ‰ÿÿ‰ÿÿ‰ÿÿ‰ÿÿ‹ÿÿŽÿÿ‰ýÔˆÿGŠÿ#Šý™‹üìÿÿÿÿÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŠÿÿ•ÿÿV³ÿÿsÀÿÿ]¶ÿÿµÝÿÿ´Ýÿÿ‰ÿÿŠÿÿ‹ÿÿŠÿÿŠÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿŒÿÿÿÿýþ‰üÆŒÿ<€ÿÿTŽüÇýó‘ÿÿ‘ÿÿÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿÿÿÿÿ”ÿÿ‘Îÿÿ–Ñÿÿ†ÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿÿÿ’ÿÿŽýóŽþ­Šÿ%ŒÿÿqŒýÔýõ“ÿÿ”ÿÿ‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‹ÿÿžÿÿ’ÐÿÿsÁÿÿ‹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’ÿÿ”ÿÿ’ýûüÜýs€ê €ÿ™ÿ”ÿw‘ýÒ“ÿð“ÿÿ—ÿÿ–ÿÿ”ÿÿ“ÿÿ“ÿÿ’ÿÿ’ÿÿ’ÿÿ’ÿÿ’ÿÿ’ÿÿÿÿœÿÿP´ÿÿ7ªÿÿÿÿ’ÿÿ’ÿÿ’ÿÿ’ÿÿ“ÿÿ•ÿÿ–ÿÿ”ýûüç‘ýœ•ÿ0€ÿªÿ”ÿ˜ÿW“þµ”üè–ýô”ýþ™ÿÿ™ÿÿ˜ÿÿ—ÿÿ–ÿÿ–ÿÿ–ÿÿ•ÿÿ•ÿÿ•ÿÿ–ÿÿ–ÿÿ–ÿÿ—ÿÿ˜ÿÿ™ÿÿ˜ÿÿ”þÿ•ýó’úâ“ýš”ÿ7™ÿÿÿŽÿ šÿ&—ýi˜ü¯–üà˜ýï•ýõ•ýú–ýþ™ÿÿšÿÿ›ÿÿœÿÿ›ÿÿ™ÿÿ™ÿÿ˜ÿÿ—ýû•ý÷™ÿð—úâ—þ°–ÿd‘ÿªÿªÿ™æ ™ÿ›ÿ8™ÿi—ýŽšþ«—üÇ—ûØ—üá—üê•ýè˜ûÚ™ýΘþ¹™ý˜›ÿu˜ÿE›ÿ™ÿ €ÿ( @ ÿüdýŸüÁþþÿÿÿÿÿÿ¢¦ûíþº ýšüW ÿÿ,þ«úûýÿýÿuþÿÿÿÿÿÿÿÿÿ‰þÿýÿýÿýÿúüüÀüJÿÿý‡úûýÿýÿ>Pýÿ½Ãþÿÿÿÿÿÿÿÿÿúúÿÿ&:ýÿýÿýÿýÿýÿýÿýÿýÍüKÿ þºýÿýÿýÿbsþÿýýÿÿÿÿÿÿÿÿÿÿúûÿÿ\nþÿýÿýÿýÿýÿýÿýÿýÿýÿýÿý¦ ÿ+ÿþ»!ýÿ!ýÿ!ýÿŠ™þÿÿÿÿÿÿÿÿÿôöÿÿÈÏÿÿ0Jýÿ ýÿ ýÿ ýÿ ýÿ ýÿ ýÿ ýÿ ýÿ ýÿ ýÿ ýÿüÛÿ+%ý‹%ýÿ%ýÿ%ýÿp…þÿÿÿÿÿÿÿÿÿúûÿÿs‡þÿ(ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ$ýÿ$ýÿ$úí"ÿ5+ÿ0*úý*ýÿ*ýÿ>^ýÿüüÿÿÿÿÿÿõ÷ÿÿ@_ýÿ)ýÿ)ýÿ)ýÿ)ýÿ$Gýÿyþÿ¥³þÿ»Æþÿ¯¼þÿ¢þÿPlþÿ 1ýÿ)ýÿ)ýÿ)ýÿ)ýÿ)úð'ÿ..þ¶.þÿ.þÿ0þÿÌÕÿÿÿÿÿÿþþÿÿXvþÿ.þÿ.þÿ.þÿCþÿ²Àÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêîÿÿ{’þÿ3þÿ-þÿ-þÿ-þÿ*üÞ$ÿ3ÿ#3ûþ3þÿ3þÿXyþÿÿÿÿÿÿÿÿÿ¤¶ÿÿ2þÿ2þÿ2þÿ8_þÿìðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍ×ÿÿ#Nþÿ2þÿ2þÿ2þÿ2ýž7ÿt7þÿ7þÿ7þÿ·ÇÿÿÿÿÿÿúûÿÿOþÿ7þÿ7þÿOþÿèíÿÿÿÿÿÿÿÿÿÿÓÜÿÿ`‚þÿKþÿ6þÿ =þÿ;eþÿ§ÿÿóöÿÿÿÿÿÿÿÿÿÿàçÿÿJþÿ6þÿ6þÿ6þÿ7ÿO:þ³<þÿ;þÿIþÿúûÿÿÿÿÿÿ¸Èÿÿ;þÿ;þÿ;þÿ¯Âÿÿÿÿÿÿÿÿÿÿ¡·ÿÿ@þÿ;þÿ;þÿ;þÿ;þÿ;þÿ;þÿPþÿÀÏÿÿÿÿÿÿÿÿÿÿÎÙÿÿ@þÿ;þÿ:þÿ:üÛUÿ@üÞ@þÿ@þÿCrþÿÿÿÿÿÿÿÿÿjþÿ@þÿ@þÿ(^þÿýýÿÿÿÿÿÿÇÕÿÿCþÿ?þÿ?þÿ?þÿ?þÿ?þÿ?þÿ?þÿ?þÿ FþÿÅÓÿÿÿÿÿÿÿÿÿÿs–þÿ?þÿ?þÿ?þÿAÿSAûõDþÿDþÿgþÿÿÿÿÿÿÿÿÿAtþÿDþÿDþÿj’þÿÿÿÿÿÿÿÿÿM|þÿDþÿDþÿ7lþÿ­ÂþÿÑÝÿÿÂÒÿÿHyþÿDþÿDþÿDþÿTþÿðôÿÿÿÿÿÿîòÿÿNþÿCþÿCþÿDüÈIûøIþÿIþÿ|¡þÿÿÿÿÿÿÿÿÿ)fþÿIþÿIþÿ°ÿÿÿÿÿÿÿÿÿÿWþÿ Qþÿ¥¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿˆªÿÿHþÿHþÿHþÿxžþÿÿÿÿÿÿÿÿÿ\ŠþÿHþÿHþÿHþÿFÿ!MûçMþÿMþÿošþÿÿÿÿÿÿÿÿÿ6sþÿMþÿMþÿ‰­ÿÿÿÿÿÿÿÿÿÿ#eþÿÁÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýþÿÿ8sþÿLþÿLþÿ^þÿýþÿÿÿÿÿÿªÃÿÿLþÿLþÿLþÿMÿcRýÓRþÿRþÿ\þÿÿÿÿÿÿÿÿÿYŽþÿQþÿQþÿh˜þÿÿÿÿÿÿÿÿÿËÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿþþÿÿÿÿÿÿœ»ÿÿQþÿQþÿQþÿÏÞÿÿÿÿÿÿÛæÿÿQþÿQþÿQþÿOý§Vþ®VþÿVþÿ"mþÿÿÿÿÿÿÿÿÿž¿ÿÿVþÿVþÿcþÿöùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³ÿÿãìÿÿÿÿÿÿÂÖÿÿUþÿUþÿUþÿ­ÈÿÿÿÿÿÿöùÿÿUþÿUþÿUþÿSýÏ\ÿl[þÿ[þÿZþÿÜèÿÿÿÿÿÿó÷ÿÿjþÿZþÿZþÿz©þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’¹ÿÿ[þÿçïÿÿÿÿÿÿ»ÓÿÿZþÿZþÿZþÿŸÁÿÿÿÿÿÿþþÿÿ]þÿYþÿYþÿWúàaÿ*_þÿ_þÿ_þÿr§þÿÿÿÿÿÿÿÿÿžÂÿÿ_þÿ_þÿ_þÿ€¯þÿýþÿÿÿÿÿÿÿÿÿÿßëÿÿG‹þÿ^þÿ*yþÿÿÿÿÿÿÿÿÿ—½ÿÿ^þÿ^þÿ^þÿ²Îÿÿÿÿÿÿðöÿÿ^þÿ^þÿ^þÿ[ûòÿaýÔcþÿcþÿhþÿáíÿÿÿÿÿÿÿÿÿÿn¦þÿcþÿcþÿcþÿeþÿ({þÿlþÿcþÿcþÿdþÿ±ÏÿÿÿÿÿÿÿÿÿÿA‹þÿcþÿcþÿcþÿÛéÿÿÿÿÿÿÖæÿÿbþÿbþÿbþÿ_ûóiÿ_hþÿhþÿhþÿH“þÿüýÿÿÿÿÿÿÿÿÿÿ•Àÿÿqþÿhþÿgþÿgþÿgþÿgþÿ mþÿŸÆÿÿÿÿÿÿÿÿÿÿÌáÿÿhþÿgþÿgþÿ zþÿÿÿÿÿÿÿÿÿšÃÿÿgþÿgþÿgþÿgüÜfÿkúálþÿlþÿlþÿj©þÿþþÿÿÿÿÿÿÿÿÿÿíõÿÿ“ÁÿÿQ›þÿ8ŒþÿG•þÿ€¶þÿâîÿÿÿÿÿÿÿÿÿÿîõÿÿ#€þÿlþÿlþÿkþÿ‡¹ÿÿÿÿÿÿÿÿÿÿVþÿkþÿkþÿkþÿiþ³pÿ]qþÿqþÿqþÿqþÿNœþÿð÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàîÿÿ7þÿpþÿpþÿpþÿ~þÿñ÷ÿÿÿÿÿÿåðÿÿtþÿpþÿpþÿpþÿoÿwtþ­uþÿuþÿuþÿuþÿ€þÿŽÂÿÿñ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñ÷ÿÿ“Åÿÿ~þÿuþÿtþÿ yþÿÇàÿÿÉáÿÿÿÿÿÿÿÿÿÿs³þÿtþÿtþÿtþÿtûþvÿ'yÿ{ûçyþÿyþÿyþÿyþÿyþÿ|þÿ@›þÿl²þÿ€¼þÿq´þÿJ þÿ þÿyþÿyþÿyþÿyþÿŽÃþÿÿÿÿÿêôÿÿÿÿÿÿÌäÿÿ|þÿyþÿyþÿyþÿwþ¼}ÿ5~ûô~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ}þÿ}þÿ}þÿ}þÿ"ŽþÿäñÿÿÿÿÿÿÿÿÿÿèóÿÿP¥þÿ}þÿ}þÿ}þÿ}þÿ{ÿ<ƒÿD‚üó‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿŸÐÿÿÿÿÿÿÿÿÿÿýþÿÿÑéÿÿsºÿÿ‚ÿÿ‚ÿÿÿÿý–‰ÿ6…üå‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ†ÿÿ†ÿÿ†ÿÿ†ÿÿ†ÿÿ†ÿÿŠÿÿœÐÿÿÓêÿÿ¼ßÿÿi¸ÿÿˆÿÿ†ÿÿ†ÿÿ†ÿÿ‡üÇŽÿ ÿ‹þ»‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ%œÿÿ‘ÍÿÿÊæÿÿ3¢ÿÿŽÿÿ‹ÿÿ‹ÿÿ‹ÿÿŠÿÿŠÿÿŠüÇŽÿÿÿ‘ÿaŽüÞÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‹ÌÿÿÿÿÿÿÿÿÿÿÿÿŒüþý˜Žÿ €ÿ”ÿ_’ýÔ”ÿÿ”ÿÿ”ÿÿ”ÿÿ”ÿÿ”ÿÿ$£ÿÿ”ÿÿ“ÿÿ“ÿÿ“ÿÿ“þ½“ÿ;•ÿ$—ÿl˜þ°™ýÑ•üæ˜üû˜üé™ýÑ–þ²˜ÿwšÿ&(0 ÿù\ýš&2üÅùùýîÜÞûì$1üÉý¢ÿeÿ1ÿýiýÐÿÿ9Eÿÿ²¸ÿÿÿÿÿÿ¸¿ÿÿ ÿÿÿÿÿÿüðý ûBÿýÿÿÿÿl{ÿÿìïÿÿÿÿÿÿÚÞÿÿ;Oýÿýÿýÿþÿÿÿÿÿüîûÿÿ "ýŸÿÿ ÿÿƒ“þÿÿÿÿÿÿÿÿÿ¡®þÿ)Cýÿýÿýÿýÿýÿýÿýÿ!ÿÿ"ÿÿ þ¾ø&&ýk'üý ÿÿg~ýÿüüÿÿñóÿÿgþÿ#ýÿýÿ#ýÿ-MýÿTnýÿ[týÿGcýÿ<ýÿýÿ!ÿÿ'ÿÿ'ýÐ&ÿ(1ÿ+ûÙ'ÿÿ&Nþÿèìÿÿÿÿÿÿeþÿþÿ!þÿ5Xþÿ­»þÿéíÿÿÿÿÿÿÿÿÿÿþþÿÿÙàÿÿŽ¡þÿEþÿ$ÿÿ.ÿÿ*üÄÿ3ÿd4ÿÿ1ÿÿˆ þÿÿÿÿÿ£µÿÿ1þÿ&þÿMpþÿçìÿÿÿÿÿÿïóÿÿÇÒÿÿÀÌÿÿÒÜÿÿÿÿÿÿÿÿÿÿÓÜÿÿ@eþÿ*ÿÿ5ÿÿ1ýŒÿ8ý¨7ÿÿFþÿÝåÿÿøúÿÿ;gþÿ&þÿ(Xþÿâêÿÿÿÿÿÿ¤¹ÿÿ4\þÿ2þÿ)þÿ @þÿMsþÿ»Ëþÿÿÿÿÿáèÿÿ1^þÿ1ÿÿ8ýó8ÿD>ûÕ;ÿÿ8iþÿÿÿÿÿÈÖÿÿKþÿ2þÿŒ¨þÿÿÿÿÿ¯Ãÿÿ;þÿ,þÿCþÿ Gþÿ9þÿ,þÿFþÿ¬Àÿÿÿÿÿÿ·ÉÿÿEþÿ=ÿÿ>ú¨UÕBúê@ÿÿ[‡þÿÿÿÿÿ¢»ÿÿ>þÿOþÿÅÕÿÿþþÿÿ3jþÿ@þÿ^‰þÿ»ÍþÿÓßÿÿ…¦þÿSþÿ7þÿWþÿÙãÿÿÿÿÿÿOþÿ=ÿÿDüòCú5KùæFÿÿbþÿÿÿÿÿ›¸ÿÿ@þÿ]þÿ×âÿÿõ÷ÿÿ+iþÿš¸ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢¾ÿÿJþÿ@þÿo™þÿÿÿÿÿžºÿÿKÿÿLÿÿIýpQýÔNÿÿP‡þÿÿÿÿÿ±ÊÿÿPþÿ WþÿÀÓþÿüýÿÿÁÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿó÷ÿÿ?|ÿÿ?þÿ3sþÿùûÿÿ×äÿÿ YþÿOÿÿPþ­Vþ±Uÿÿ#nþÿøúÿÿäíÿÿ"nþÿFþÿv¦þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¦Äÿÿ¾Ôÿÿÿÿÿÿc—ÿÿDþÿ"mþÿâìÿÿôøÿÿbþÿTÿÿQýÑ]ýv_ÿÿ_ÿÿ¶Ñþÿÿÿÿÿ~­ÿÿQþÿdþÿ©Éþÿÿÿÿÿÿÿÿÿûüÿÿ”»þÿeþÿµÐÿÿÿÿÿÿU’ÿÿLþÿ"rþÿàëÿÿôøÿÿhþÿZÿÿYúâaû:büö^ÿÿGþÿÿÿÿÿôøÿÿO”þÿUþÿdþÿFŽþÿR•þÿ1þÿVþÿBŠþÿøûÿÿåïÿÿ!vþÿUþÿ0€þÿúüÿÿÛéÿÿ jþÿaÿÿ_úèqÿ fü¬mÿÿgþÿ½þÿÿÿÿÿñ÷ÿÿw®ÿÿvþÿbþÿ`þÿhþÿQ—þÿßìÿÿÿÿÿÿ‚µÿÿaþÿaþÿb¢þÿÿÿÿÿ¦ÊÿÿjþÿhÿÿgýÔnûHoýômÿÿtþÿ’Âþÿÿÿÿÿÿÿÿÿàîÿÿ«Ïÿÿ¡ÉÿÿÆßÿÿÿÿÿÿÿÿÿÿ¥Ìþÿ rþÿdþÿrþÿÇßÿÿÿÿÿÿ]£þÿhþÿqÿÿmý©ªÿrý“zÿÿqÿÿtþÿX¤þÿÇàÿÿüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿàîÿÿt´ÿÿ xþÿjþÿQžþÿ±ÓÿÿÿÿÿÿÏåÿÿþÿnÿÿyÿÿtýgózüÈ‚ÿÿwÿÿuþÿ ~þÿ3•þÿ^¬þÿe¯þÿFŸþÿ…þÿvþÿqþÿ‰þÿÙëþÿÿÿÿÿóùÿÿV§ÿÿrþÿÿÿwüÞxÿ ‚ù+ûÕˆÿÿ€ÿÿ}þÿ|þÿ{þÿ{þÿ|þÿ|þÿ|þÿ|ÿÿ„ÂÿÿÿÿÿÿÿÿÿÿÍæÿÿ'’þÿ}ÿÿ„ÿÿ~ýs…ÿ,‡üÄÿÿŠÿÿ†ÿÿ†ÿÿ…ÿÿ…ÿÿ…ÿÿ ‰ÿÿ“ÿÿ§ÖÿÿÑéÿÿ‘Ëÿÿ6ŸÿÿŽÿÿŒÿÿ„ý¨™ÿ ÿŠý™ýô•ÿÿŽÿÿŒÿÿ‹ÿÿŒÿÿ>¨ÿÿžÓÿÿ4£ÿÿ ÿÿ‹ÿÿŒÿÿŽÿÿŠý¦ŒÿüL’ý¨’üøšÿÿ—ÿÿ–ÿÿ”ÿÿ;°ÿÿ™ÿÿ“ÿÿ—ÿÿ”ýÙŽýsŽÿ ™ÿ”ÿ9™ÿq–þ²—ýÓ–üç•üä—ýΕý©™ÿf•ÿ$(  ÿÿÿ* ýmîïý“cmýƒüU#ÿÿÿÿ1ÿ üª üû‘šþÿþþþþ4Eüþüÿüîý• ÿÿ1ÿúá6ýÿßãýýô÷ýüG\üûûûûý ûþüÿ ûí'ûHUÿ'þ¶+ýÿÝâýøÆÒýþ#ýÿ!üþl„üþ§³ýþœªýýKiüú!üþ$üý0üPUÿAÿC$ýÿvýýöùýþ 3üþ DþÿåëþÿúûÿÿÁÎþÿÏÙýþÿÿÿÿÅÐýü;þÿ-üñ>ÿ%>ýˆ4ýÿ×àýü”ªýþ$ýÿÏÚþÿÉ×þÿ4ýÿ"ýÿ"ýÿ RýþáêþÿÄÒýú6ýÿ;ý¨Aý¨Jþÿ÷ùýüRýþTþÿÿÿÿÿ0aþÿIxþÿ¼Îþÿœ¸þÿ Býÿ UýþþþþþW‚þÿ7üöUÿ-Mý RþÿôøýüXˆýþ_þÿöøþÿ´Ëþÿÿÿÿÿûüþÿÿÿÿÿœ»þÿ5ýÿ¾Ïýþ°ÉýüAýÿ Tÿt\ÿtOýÿÈÚýü­ÈýþCýÿ»Òþÿÿÿÿÿÿÿÿÿ¶Ïþÿ¡ÂþÿÐàþÿBýÿ—·ýþÏßýüNýÿYý lÿ-XüöNþÿþþþþKŒýþWýÿWšþÿGþÿ\ýÿÔãþÿ¢ÆþÿIýÿ­Êýþ¿ÖýüVýÿdý¨mý¨dýÿ‰ºýúÿÿÿÿ¡Æýþ@ŽþÿN–þÿÔåþÿíõþÿuþÿdýÿïöýþy°ýü_ýÿoýˆuÿ%uýñmýÿQ¡ýüÕéþÿúýýþùýþÿ´Øþÿþÿ{þÿºÙýþêóýþ}üýqýÿvÿCUÿ|ÿP€ýývýþvýú ‚ýýýþtýþoýþ¬Ôþÿþþþþ¼ýøtþÿ€þ¶Uÿ‡ÿHˆþí‰ÿÿ…þþ…þý ŒþûN©þû–ÎýüZ²ýý‹ÿÿ…þá„ÿªÿŠÿý”ýî‘þÿýþ:ªýþ þÿ†þúþª“ÿÿÿ€ÿÿÿ—ÿ–ÿU—ÿ€ÿˆ™ÿl¤ÿ*ÿÿÿwcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo.svg0000644000077000000240000001103212532571254034466 0ustar tomstaff00000000000000 ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo_32.pngwcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo_32.p0000644000077000000240000000353412346274067034447 0ustar tomstaff00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYsÓÇòŽtEXtSoftwarewww.inkscape.org›î<ÙIDATX…Å—PT×Ç?÷ñc‘P° ˆ „FƒUBìȘ&Ådi”I# ±ÒÄJhC2æÇŒ5ÑÔtw:íÛª5ÑÒSÒÆª©é„Ú¡%¨ZÉF2Vk­JFŒ`ÁŠ(JdÙ÷öÝþqaß., É?½3gæ½sÏïýžûΞº®óÿ\Ñ_ÄÉ•ìÎ#šÅHŠl ø2pèZ€Ý8ØãéÔ¯KL”Wš;†AC°È‹h4¥z>ÕÀ$?ñôé—#¹hJ~‹»œ›´`;&y˜#D²ËÂß b0¨Â¤Åu‹»2RìqKàJr'âã7˜<6.´;`Îã2Ò‹@‹†Ž&°Ìa‹$`›+Æâ1ôWB]Ç, w.rÆM¶|»r€Þh?G6B—m"ù‘GêÕïKàƒ…“œ0º#Ñ&¢: WBÅaˆË°mL6¸pÏ€+àΔƒx¥Áti@D1Çä;«áz§ v³ú7zCýrׇóE9ÎÐäš ‹,“é_Gÿ±hbÞˆy•ˆ;¾Ñ Ðñ!,e÷ÙUÄ—¦AÚlˆO†„©ˆ€-^;V€¬…~ï;MçÅðKxUZùK%:Lü剜"¸ë9äžáT½rÝë†3WCúWaá8úè9ô³`p4XW·;KšxBjó«ËwÙÉ¥„Ö÷á“ýÐÚׇ.WêLDå_e5Êw`ÎDîzFíG;ßz9ì¾?@ÈghI^Ž ÄâUˆ¥›Ô³áƒÆMÈl…+çíãÇÄs%bñZˆK„»Ÿ‚Ão@ûÅ`ó!8¹ò—À¬o‚)Ô!ÔÊpu¹4W›;Uü0ˆ0×i'÷Ý@V— ë\Ð}>üÖßôÁž Èu Àôƒˆï¾ ¦übdëÇ‘‰Yáþ>rµ¡z—c0iØI,\1D‹‰ÜX §)‡Ìùׇˆ×üˆ__…Šm cáB3ì߬|f̃¹ÙI.œ²KŸ;ò“NÖ¤AqÐ!~*Üùr8Þg)ã¬BÄß…¬;!*â'#î©DÔôÁürdÓN;Ql’ à|(€Ùá Xôj®€[Ã`aPy÷ã* ÷ר—¦Ô¥h¹bâO½¶Î 9el¢­ïë 0HÆi¦a29HáReÜÝ 5*Ã@ä)}豄 ¢cU5ö»aÙIr mý0›Jú€nARÂPÊør‡j­&5â“+Þðçõ£AL:éµKðAƒÍ\îÿ´ž eà'_Œ໩âlg'ò›Èm/!7|ü¾p7z‘¯T@ß5å—0 KÕÞ¹Àg†öƒ ú@/fHN|ׯ@b bÁÃÈú8X‹lü,yf} ºÚ ®ú•ˆU; )U1·o»bSµ j€~Ú¦‚aS2!&A”8¼/‡‚û ¿Ž7ªhu¯Ž.@ùó0¿D=¿_oo nIøý/© Ió”è70è¦FÞ§¬&%ÀýÁ¶,Ô*}t â—ƒ{Ë#ÿ$'Ï@ütbÅËʾç?ÈuO„Ú j&Á¡DèºÎK î-T㎉E4| )épá,ò;·Ûí³ôˆµ¿…¨!ÊÎ7ÿ¼Èö3ˆiÙ0ý6X°“Ô¾¹ò8önðôB°ÚSjOEÑšÅNi 0ýÈÚ-ˆg<0c&”T@Ãe]· ùßKˆ» .²ó ;©Þzäæç¡³-Tû³™R[åt:iºÝy±è„·‹,, å4âÑçÝEBÛY8{Z5˜öðîFô÷A¬¦¤ƒÐK]àä?‘úÓð»upíjèLñ©,ñ<«÷…" ^?aReÁ ÀAO/¬YŽØü–±áHKCî}K7ÿÙ¼V='N†´ èhß@$.:4Á}žr½säFp"jÊw^ùÆqo?%Š…føä$¢äâþ2HÍ€÷€°O6àƒžËà75E)iנس\o™FÌ„ë*õj¬þ”î{YU†¬¢üI´¿…ܹ㠦!bò¦¦Qà©Ð[Ç¢&âX¾¶Æ])àWHTÿ]º í…ŸAÖ­Ê`Їu×W ëâXq;¤dÍúgõÚ± "20¼Ö¯Ð·k·að:µobÝ3¹u‹2pÄ!}rô¸nÒ,TjÝäN$9Là¿¡k“{rÀâAMP*a¦Öri.©išÜ[ï—ËÊÎ h“Ш™ì÷¼¨7O$éç0 Ë•Lg§$3ó3Çãÿ¼ G®ÿ.Á½8<ßÇIEND®B`‚././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/bootstrap-astropy.csswcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/bootstrap-astropy0000644000077000000240000002673512532571254034703 0ustar tomstaff00000000000000/*! * Bootstrap v1.4.0 * * Copyright 2011 Twitter, Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Heavily modified by Kyle Barbary for the AstroPy Project for use with Sphinx. */ @import url("basic.css"); body { background-color: #ffffff; margin: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; line-height: 18px; color: #404040; } /* Hyperlinks ----------------------------------------------------------------*/ a { color: #0069d6; text-decoration: none; line-height: inherit; font-weight: inherit; } a:hover { color: #00438a; text-decoration: underline; } /* Typography ----------------------------------------------------------------*/ h1,h2,h3,h4,h5,h6 { color: #404040; margin: 0.7em 0 0 0; line-height: 1.5em; } h1 { font-size: 24px; margin: 0; } h2 { font-size: 21px; line-height: 1.2em; margin: 1em 0 0.5em 0; border-bottom: 1px solid #404040; } h3 { font-size: 18px; } h4 { font-size: 16px; } h5 { font-size: 14px; } h6 { font-size: 13px; text-transform: uppercase; } p { font-size: 13px; font-weight: normal; line-height: 18px; margin-top: 0px; margin-bottom: 9px; } ul, ol { margin-left: 0; padding: 0 0 0 25px; } ul ul, ul ol, ol ol, ol ul { margin-bottom: 0; } ul { list-style: disc; } ol { list-style: decimal; } li { line-height: 18px; color: #404040; } ul.unstyled { list-style: none; margin-left: 0; } dl { margin-bottom: 18px; } dl dt, dl dd { line-height: 18px; } dl dd { margin-left: 9px; } hr { margin: 20px 0 19px; border: 0; border-bottom: 1px solid #eee; } strong { font-style: inherit; font-weight: bold; } em { font-style: italic; font-weight: inherit; line-height: inherit; } .muted { color: #bfbfbf; } address { display: block; line-height: 18px; margin-bottom: 18px; } code, pre { padding: 0 3px 2px; font-family: monospace; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } tt { font-family: monospace; } code { color: rgba(0, 0, 0, 0.75); padding: 1px 3px; } pre { display: block; padding: 8.5px; margin: 0 0 18px; line-height: 18px; border: 1px solid #ddd; border: 1px solid rgba(0, 0, 0, 0.12); -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; white-space: pre; white-space: pre-wrap; word-wrap: break-word; } img { margin: 9px 0; } /* format inline code with a rounded box */ tt { margin: 0 2px; padding: 0 5px; border: 1px solid #ddd; border: 1px solid rgba(0, 0, 0, 0.12); border-radius: 3px; } /* all code has same box background color, even in headers */ h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt, pre, code, tt { background-color: #f8f8f8; } /* override box for links & other sphinx-specifc stuff */ tt.xref, a tt, tt.descname, tt.descclassname { padding: 0 1px 0 1px; border: none; } /* override box for related bar at the top of the page */ .related tt { border: none; padding: 0 1px 0 1px; background-color: transparent; font-weight: bold; } th { background-color: #dddddd; } .viewcode-back { font-family: sans-serif; } div.viewcode-block:target { background-color: #f4debf; border-top: 1px solid #ac9; border-bottom: 1px solid #ac9; } table.docutils { border-spacing: 5px; border-collapse: separate; } /* Topbar --------------------------------------------------------------------*/ div.topbar { height: 40px; position: absolute; top: 0; left: 0; right: 0; z-index: 10000; padding: 0px 10px; background-color: #222; background-color: #222222; background-repeat: repeat-x; background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222)); background-image: -moz-linear-gradient(top, #333333, #222222); background-image: -ms-linear-gradient(top, #333333, #222222); background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222)); background-image: -webkit-linear-gradient(top, #333333, #222222); background-image: -o-linear-gradient(top, #333333, #222222); background-image: linear-gradient(top, #333333, #222222); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); } div.topbar a.brand { font-family: 'Source Sans Pro', sans-serif; font-size: 26px; color: #ffffff; font-weight: 600; text-decoration: none; float: left; display: block; height: 32px; padding: 8px 12px 0px 45px; margin-left: -10px; background: transparent url("astropy_logo_32.png") no-repeat 10px 4px; background-image: url("astropy_logo.svg"), none; background-size: 32px 32px; } #logotext1 { } #logotext2 { font-weight:200; color: #ff5000; } #logotext3 { font-weight:200; } div.topbar .brand:hover, div.topbar ul li a.homelink:hover { background-color: #333; background-color: rgba(255, 255, 255, 0.05); } div.topbar ul { font-size: 110%; list-style: none; margin: 0; padding: 0 0 0 10px; float: right; color: #bfbfbf; text-align: center; text-decoration: none; height: 100%; } div.topbar ul li { float: left; display: inline; height: 30px; margin: 5px; padding: 0px; } div.topbar ul li a { color: #bfbfbf; text-decoration: none; padding: 5px; display: block; height: auto; text-align: center; vertical-align: middle; border-radius: 4px; } div.topbar ul li a:hover { color: #ffffff; text-decoration: none; } div.topbar ul li a.homelink { width: 112px; display: block; height: 20px; padding: 5px 0px; background: transparent url("astropy_linkout_20.png") no-repeat 10px 5px; background-image: url("astropy_linkout.svg"), none; background-size: 91px 20px; } div.topbar form { text-align: left; margin: 0 0 0 5px; position: relative; filter: alpha(opacity=100); -khtml-opacity: 1; -moz-opacity: 1; opacity: 1; } div.topbar input { background-color: #444; background-color: rgba(255, 255, 255, 0.3); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: normal; font-weight: 13px; line-height: 1; padding: 4px 9px; color: #ffffff; color: rgba(255, 255, 255, 0.75); border: 1px solid #111; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none; transition: none; } div.topbar input:-moz-placeholder { color: #e6e6e6; } div.topbar input::-webkit-input-placeholder { color: #e6e6e6; } div.topbar input:hover { background-color: #bfbfbf; background-color: rgba(255, 255, 255, 0.5); color: #ffffff; } div.topbar input:focus, div.topbar input.focused { outline: 0; background-color: #ffffff; color: #404040; text-shadow: 0 1px 0 #ffffff; border: 0; padding: 5px 10px; -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); } /* Relation bar (breadcrumbs, prev, next) ------------------------------------*/ div.related { height: 21px; width: auto; margin: 0 10px; position: absolute; top: 42px; clear: both; left: 0; right: 0; z-index: 10000; font-size: 100%; vertical-align: middle; background-color: #fff; border-bottom: 1px solid #bbb; } div.related ul { padding: 0; margin: 0; } /* Footer --------------------------------------------------------------------*/ footer { display: block; margin: 10px 10px 0px; padding: 10px 0 0 0; border-top: 1px solid #bbb; } .pull-right { float: right; width: 30em; text-align: right; } /* Sphinx sidebar ------------------------------------------------------------*/ div.sphinxsidebar { font-size: inherit; border-radius: 3px; background-color: #eee; border: 1px solid #bbb; } div.sphinxsidebarwrapper { padding: 0px 0px 0px 5px; } div.sphinxsidebar h3 { font-family: 'Trebuchet MS', sans-serif; font-size: 1.4em; font-weight: normal; margin: 5px 0px 0px 5px; padding: 0; line-height: 1.6em; } div.sphinxsidebar h4 { font-family: 'Trebuchet MS', sans-serif; font-size: 1.3em; font-weight: normal; margin: 5px 0 0 0; padding: 0; } div.sphinxsidebar p { } div.sphinxsidebar p.topless { margin: 5px 10px 10px 10px; } div.sphinxsidebar ul { margin: 0px 0px 0px 5px; padding: 0; } div.sphinxsidebar ul ul { margin-left: 15px; list-style-type: disc; } /* If showing the global TOC (toctree), color the current page differently */ div.sphinxsidebar a.current { color: #404040; } div.sphinxsidebar a.current:hover { color: #404040; } /* document, documentwrapper, body, bodywrapper ----------------------------- */ div.document { margin-top: 72px; margin-left: 10px; margin-right: 10px; } div.documentwrapper { float: left; width: 100%; } div.body { background-color: #ffffff; padding: 0 0 0px 20px; } div.bodywrapper { margin: 0 0 0 230px; max-width: 55em; } /* Header links ------------------------------------------------------------- */ a.headerlink { font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none; } a.headerlink:hover { background-color: #0069d6; color: white; text-docoration: none; } /* Admonitions and warnings ------------------------------------------------- */ /* Shared by admonitions and warnings */ div.admonition, div.warning { padding: 0px; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; } div.admonition p, div.warning p { margin: 0.5em 1em 0.5em 1em; padding: 0; } div.admonition pre, div.warning pre { margin: 0.4em 1em 0.4em 1em; } div.admonition p.admonition-title, div.warning p.admonition-title { margin: 0; padding: 0.1em 0 0.1em 0.5em; color: white; font-weight: bold; font-size: 1.1em; } div.admonition ul, div.admonition ol, div.warning ul, div.warning ol { margin: 0.1em 0.5em 0.5em 3em; padding: 0; } /* Admonitions only */ div.admonition { border: 1px solid #609060; background-color: #e9ffe9; } div.admonition p.admonition-title { background-color: #70A070; } /* Warnings only */ div.warning { border: 1px solid #900000; background-color: #ffe9e9; } div.warning p.admonition-title { background-color: #b04040; } /* Figures ------------------------------------------------------------------ */ .figure.align-center { clear: none; } /* This is a div for containing multiple figures side-by-side, for use with * .. container:: figures */ div.figures { border: 1px solid #CCCCCC; background-color: #F8F8F8; margin: 1em; text-align: center; } div.figures .figure { clear: none; float: none; display: inline-block; border: none; margin-left: 0.5em; margin-right: 0.5em; } .field-list th { white-space: nowrap; } table.field-list { border-spacing: 0px; margin-left: 1px; border-left: 5px solid rgb(238, 238, 238) !important; } table.field-list th.field-name { display: inline-block; padding: 1px 8px 1px 5px; white-space: nowrap; background-color: rgb(238, 238, 238); border-radius: 0 3px 3px 0; -webkit-border-radius: 0 3px 3px 0; } wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/copybutton.js0000644000077000000240000000467712346274067034016 0ustar tomstaff00000000000000$(document).ready(function() { /* Add a [>>>] button on the top-right corner of code samples to hide * the >>> and ... prompts and the output and thus make the code * copyable. */ var div = $('.highlight-python .highlight,' + '.highlight-python3 .highlight') var pre = div.find('pre'); // get the styles from the current theme pre.parent().parent().css('position', 'relative'); var hide_text = 'Hide the prompts and output'; var show_text = 'Show the prompts and output'; var border_width = pre.css('border-top-width'); var border_style = pre.css('border-top-style'); var border_color = pre.css('border-top-color'); var button_styles = { 'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0', 'border-color': border_color, 'border-style': border_style, 'border-width': border_width, 'color': border_color, 'text-size': '75%', 'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em', 'border-radius': '0 3px 0 0' } // create and add the button to all the code blocks that contain >>> div.each(function(index) { var jthis = $(this); if (jthis.find('.gp').length > 0) { var button = $('>>>'); button.css(button_styles) button.attr('title', hide_text); jthis.prepend(button); } // tracebacks (.gt) contain bare text elements that need to be // wrapped in a span to work with .nextUntil() (see later) jthis.find('pre:has(.gt)').contents().filter(function() { return ((this.nodeType == 3) && (this.data.trim().length > 0)); }).wrap(''); }); // define the behavior of the button when it's clicked $('.copybutton').toggle( function() { var button = $(this); button.parent().find('.go, .gp, .gt').hide(); button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden'); button.css('text-decoration', 'line-through'); button.attr('title', show_text); }, function() { var button = $(this); button.parent().find('.go, .gp, .gt').show(); button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible'); button.css('text-decoration', 'none'); button.attr('title', hide_text); }); }); wcsaxes-0.6/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/sidebar.js0000644000077000000240000001155312346274067033210 0ustar tomstaff00000000000000/* * sidebar.js * ~~~~~~~~~~ * * This script makes the Sphinx sidebar collapsible. * * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton * used to collapse and expand the sidebar. * * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden * and the width of the sidebar and the margin-left of the document * are decreased. When the sidebar is expanded the opposite happens. * This script saves a per-browser/per-session cookie used to * remember the position of the sidebar among the pages. * Once the browser is closed the cookie is deleted and the position * reset to the default (expanded). * * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ $(function() { // global elements used by the functions. // the 'sidebarbutton' element is defined as global after its // creation, in the add_sidebar_button function var bodywrapper = $('.bodywrapper'); var sidebar = $('.sphinxsidebar'); var sidebarwrapper = $('.sphinxsidebarwrapper'); // for some reason, the document has no sidebar; do not run into errors if (!sidebar.length) return; // original margin-left of the bodywrapper and width of the sidebar // with the sidebar expanded var bw_margin_expanded = bodywrapper.css('margin-left'); var ssb_width_expanded = sidebar.width(); // margin-left of the bodywrapper and width of the sidebar // with the sidebar collapsed var bw_margin_collapsed = 12; var ssb_width_collapsed = 12; // custom colors var dark_color = '#404040'; var light_color = '#505050'; function sidebar_is_collapsed() { return sidebarwrapper.is(':not(:visible)'); } function toggle_sidebar() { if (sidebar_is_collapsed()) expand_sidebar(); else collapse_sidebar(); } function collapse_sidebar() { sidebarwrapper.hide(); sidebar.css('width', ssb_width_collapsed); bodywrapper.css('margin-left', bw_margin_collapsed); sidebarbutton.css({ 'margin-left': '-1px', 'height': bodywrapper.height(), 'border-radius': '3px' }); sidebarbutton.find('span').text('»'); sidebarbutton.attr('title', _('Expand sidebar')); document.cookie = 'sidebar=collapsed'; } function expand_sidebar() { bodywrapper.css('margin-left', bw_margin_expanded); sidebar.css('width', ssb_width_expanded); sidebarwrapper.show(); sidebarbutton.css({ 'margin-left': ssb_width_expanded - 12, 'height': bodywrapper.height(), 'border-radius': '0px 3px 3px 0px' }); sidebarbutton.find('span').text('«'); sidebarbutton.attr('title', _('Collapse sidebar')); document.cookie = 'sidebar=expanded'; } function add_sidebar_button() { sidebarwrapper.css({ 'float': 'left', 'margin-right': '0', 'width': ssb_width_expanded - 18 }); // create the button sidebar.append('
    «
    '); var sidebarbutton = $('#sidebarbutton'); // find the height of the viewport to center the '<<' in the page var viewport_height; if (window.innerHeight) viewport_height = window.innerHeight; else viewport_height = $(window).height(); var sidebar_offset = sidebar.offset().top; var sidebar_height = Math.max(bodywrapper.height(), sidebar.height()); sidebarbutton.find('span').css({ 'font-family': '"Lucida Grande",Arial,sans-serif', 'display': 'block', 'top': Math.min(viewport_height/2, sidebar_height/2 + sidebar_offset) - 10, 'width': 12, 'position': 'fixed', 'text-align': 'center' }); sidebarbutton.click(toggle_sidebar); sidebarbutton.attr('title', _('Collapse sidebar')); sidebarbutton.css({ 'color': '#FFFFFF', 'background-color': light_color, 'border': '1px solid ' + light_color, 'border-radius': '0px 3px 3px 0px', 'font-size': '1.2em', 'cursor': 'pointer', 'height': sidebar_height, 'padding-top': '1px', 'margin': '-1px', 'margin-left': ssb_width_expanded - 12 }); sidebarbutton.hover( function () { $(this).css('background-color', dark_color); }, function () { $(this).css('background-color', light_color); } ); } function set_position_from_cookie() { if (!document.cookie) return; var items = document.cookie.split(';'); for(var k=0; k= (3, 3): import importlib importlib.invalidate_caches() @pytest.fixture(scope='function', autouse=True) def reset_setup_helpers(request): """ Saves and restores the global state of the astropy_helpers.setup_helpers module between tests. """ mod = __import__('astropy_helpers.setup_helpers', fromlist=['']) old_state = mod._module_state.copy() def finalizer(old_state=old_state): mod = sys.modules.get('astropy_helpers.setup_helpers') if mod is not None: mod._module_state.update(old_state) request.addfinalizer(finalizer) @pytest.fixture(scope='function', autouse=True) def reset_distutils_log(): """ This is a setup/teardown fixture that ensures the log-level of the distutils log is always set to a default of WARN, since different settings could affect tests that check the contents of stdout. """ from distutils import log log.set_threshold(log.WARN) @pytest.fixture(scope='module', autouse=True) def fix_hide_setuptools(): """ Workaround for https://github.com/astropy/astropy-helpers/issues/124 In setuptools 10.0 run_setup was changed in such a way that it sweeps away the existing setuptools import before running the setup script. In principle this is nice, but in the practice of testing astropy_helpers this is problematic since we're trying to test code that has already been imported during the testing process, and which relies on the setuptools module that was already in use. """ if hasattr(sandbox, 'hide_setuptools'): sandbox.hide_setuptools = lambda: None TEST_PACKAGE_SETUP_PY = """\ #!/usr/bin/env python from setuptools import setup NAME = 'astropy-helpers-test' VERSION = {version!r} setup(name=NAME, version=VERSION, packages=['_astropy_helpers_test_'], zip_safe=False) """ @pytest.fixture def testpackage(tmpdir, version='0.1'): """ This fixture creates a simplified package called _astropy_helpers_test_ used primarily for testing ah_boostrap, but without using the astropy_helpers package directly and getting it confused with the astropy_helpers package already under test. """ source = tmpdir.mkdir('testpkg') with source.as_cwd(): source.mkdir('_astropy_helpers_test_') init = source.join('_astropy_helpers_test_', '__init__.py') init.write('__version__ = {0!r}'.format(version)) setup_py = TEST_PACKAGE_SETUP_PY.format(version=version) source.join('setup.py').write(setup_py) # Make the new test package into a git repo run_cmd('git', ['init']) run_cmd('git', ['add', '--all']) run_cmd('git', ['commit', '-m', 'test package']) return source def cleanup_import(package_name): """Remove all references to package_name from sys.modules""" for k in list(sys.modules): if not isinstance(k, str): # Some things will actually do this =_= continue elif k.startswith('astropy_helpers.tests'): # Don't delete imported test modules or else the tests will break, # badly continue if k == package_name or k.startswith(package_name + '.'): del sys.modules[k] wcsaxes-0.6/astropy_helpers/astropy_helpers/tests/test_ah_bootstrap.py0000644000077000000240000003434012532571254026672 0ustar tomstaff00000000000000# -*- coding: utf-8 -*- import glob import os import textwrap import sys from distutils.version import StrictVersion import setuptools from setuptools.package_index import PackageIndex import pytest from . import * from ..utils import silence TEST_SETUP_PY = """\ #!/usr/bin/env python from __future__ import print_function import os import sys import ah_bootstrap # reset the name of the package installed by ah_boostrap to # _astropy_helpers_test_--this will prevent any confusion by pkg_resources with # any already installed packages named astropy_helpers # We also disable auto-upgrade by default ah_bootstrap.DIST_NAME = 'astropy-helpers-test' ah_bootstrap.PACKAGE_NAME = '_astropy_helpers_test_' ah_bootstrap.AUTO_UPGRADE = False ah_bootstrap.DOWNLOAD_IF_NEEDED = False try: ah_bootstrap.BOOTSTRAPPER = ah_bootstrap._Bootstrapper.main() ah_bootstrap.use_astropy_helpers({args}) finally: ah_bootstrap.DIST_NAME = 'astropy-helpers' ah_bootstrap.PACKAGE_NAME = 'astropy_helpers' ah_bootstrap.AUTO_UPGRADE = True ah_bootstrap.DOWNLOAD_IF_NEEDED = True # Kind of a hacky way to do this, but this assertion is specifically # for test_check_submodule_no_git # TODO: Rework the tests in this module so that it's easier to test specific # behaviors of ah_bootstrap for each test assert '--no-git' not in sys.argv import _astropy_helpers_test_ filename = os.path.abspath(_astropy_helpers_test_.__file__) filename = filename.replace('.pyc', '.py') # More consistent this way print(filename) """ # The behavior checked in some of the tests depends on the version of # setuptools try: SETUPTOOLS_VERSION = StrictVersion(setuptools.__version__).version except: # Broken setuptools? ¯\_(ツ)_/¯ SETUPTOOLS_VERSION = (0, 0, 0) def test_bootstrap_from_submodule(tmpdir, testpackage, capsys): """ Tests importing _astropy_helpers_test_ from a submodule in a git repository. This tests actually performing a fresh clone of the repository without the submodule initialized, and that importing astropy_helpers in that context works transparently after calling `ah_boostrap.use_astropy_helpers`. """ orig_repo = tmpdir.mkdir('orig') # Ensure ah_bootstrap is imported from the local directory import ah_bootstrap with orig_repo.as_cwd(): run_cmd('git', ['init']) # Write a test setup.py that uses ah_bootstrap; it also ensures that # any previous reference to astropy_helpers is first wiped from # sys.modules orig_repo.join('setup.py').write(TEST_SETUP_PY.format(args='')) run_cmd('git', ['add', 'setup.py']) # Add our own clone of the astropy_helpers repo as a submodule named # astropy_helpers run_cmd('git', ['submodule', 'add', str(testpackage), '_astropy_helpers_test_']) run_cmd('git', ['commit', '-m', 'test repository']) os.chdir(str(tmpdir)) # Creates a clone of our test repo in the directory 'clone' run_cmd('git', ['clone', 'orig', 'clone']) os.chdir('clone') run_setup('setup.py', []) stdout, stderr = capsys.readouterr() path = stdout.strip() # Ensure that the astropy_helpers used by the setup.py is the one that # was imported from git submodule a = os.path.normcase(path) b = os.path.normcase(str(tmpdir.join('clone', '_astropy_helpers_test_', '_astropy_helpers_test_', '__init__.py'))) assert a == b def test_bootstrap_from_submodule_no_locale(tmpdir, testpackage, capsys, monkeypatch): """ Regression test for https://github.com/astropy/astropy/issues/2749 Runs test_bootstrap_from_submodule but with missing locale/language settings. """ for varname in ('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE'): monkeypatch.delenv(varname, raising=False) test_bootstrap_from_submodule(tmpdir, testpackage, capsys) def test_bootstrap_from_submodule_bad_locale(tmpdir, testpackage, capsys, monkeypatch): """ Additional regression test for https://github.com/astropy/astropy/issues/2749 """ for varname in ('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE'): monkeypatch.delenv(varname, raising=False) # Test also with bad LC_CTYPE a la http://bugs.python.org/issue18378 monkeypatch.setenv('LC_CTYPE', 'UTF-8') test_bootstrap_from_submodule(tmpdir, testpackage, capsys) def test_check_submodule_no_git(tmpdir, testpackage): """ Tests that when importing astropy_helpers from a submodule, it is still recognized as a submodule even when using the --no-git option. In particular this ensures that the auto-upgrade feature is not activated. """ orig_repo = tmpdir.mkdir('orig') # Ensure ah_bootstrap is imported from the local directory import ah_bootstrap with orig_repo.as_cwd(): run_cmd('git', ['init']) # Write a test setup.py that uses ah_bootstrap; it also ensures that # any previous reference to astropy_helpers is first wiped from # sys.modules args = 'auto_upgrade=True' orig_repo.join('setup.py').write(TEST_SETUP_PY.format(args=args)) run_cmd('git', ['add', 'setup.py']) # Add our own clone of the astropy_helpers repo as a submodule named # astropy_helpers run_cmd('git', ['submodule', 'add', str(testpackage), '_astropy_helpers_test_']) run_cmd('git', ['commit', '-m', 'test repository']) # Temporarily patch _do_upgrade to fail if called class UpgradeError(Exception): pass def _do_upgrade(*args, **kwargs): raise UpgradeError() orig_do_upgrade = ah_bootstrap._Bootstrapper._do_upgrade ah_bootstrap._Bootstrapper._do_upgrade = _do_upgrade try: run_setup('setup.py', ['--no-git']) except UpgradeError: pytest.fail('Attempted to run auto-upgrade despite importing ' '_astropy_helpers_test_ from a git submodule') finally: ah_bootstrap._Bootstrapper._do_upgrade = orig_do_upgrade # Ensure that the no-git option was in fact set assert not ah_bootstrap.BOOTSTRAPPER.use_git def test_bootstrap_from_directory(tmpdir, testpackage, capsys): """ Tests simply bundling a copy of the astropy_helpers source code in its entirety bundled directly in the source package and not in an archive. """ import ah_bootstrap source = tmpdir.mkdir('source') testpackage.copy(source.join('_astropy_helpers_test_')) with source.as_cwd(): source.join('setup.py').write(TEST_SETUP_PY.format(args='')) run_setup('setup.py', []) stdout, stderr = capsys.readouterr() stdout = stdout.splitlines() if stdout: path = stdout[-1].strip() else: path = '' # Ensure that the astropy_helpers used by the setup.py is the one that # was imported from git submodule a = os.path.normcase(path) b = os.path.normcase(str(source.join('_astropy_helpers_test_', '_astropy_helpers_test_', '__init__.py'))) assert a == b def test_bootstrap_from_archive(tmpdir, testpackage, capsys): """ Tests importing _astropy_helpers_test_ from a .tar.gz source archive shipped alongside the package that uses it. """ orig_repo = tmpdir.mkdir('orig') # Ensure ah_bootstrap is imported from the local directory import ah_bootstrap # Make a source distribution of the test package with silence(): run_setup(str(testpackage.join('setup.py')), ['sdist', '--dist-dir=dist', '--formats=gztar']) dist_dir = testpackage.join('dist') for dist_file in dist_dir.visit('*.tar.gz'): dist_file.copy(orig_repo) with orig_repo.as_cwd(): # Write a test setup.py that uses ah_bootstrap; it also ensures that # any previous reference to astropy_helpers is first wiped from # sys.modules args = 'path={0!r}'.format(os.path.basename(str(dist_file))) orig_repo.join('setup.py').write(TEST_SETUP_PY.format(args=args)) run_setup('setup.py', []) stdout, stderr = capsys.readouterr() path = stdout.splitlines()[-1].strip() # Installation from the .tar.gz should have resulted in a .egg # directory that the _astropy_helpers_test_ package was imported from eggs = _get_local_eggs() assert eggs egg = orig_repo.join(eggs[0]) assert os.path.isdir(str(egg)) a = os.path.normcase(path) b = os.path.normcase(str(egg.join('_astropy_helpers_test_', '__init__.py'))) assert a == b def test_download_if_needed(tmpdir, testpackage, capsys): """ Tests the case where astropy_helpers was not actually included in a package, or is otherwise missing, and we need to "download" it. This does not test actually downloading from the internet--this is normally done through setuptools' easy_install command which can also install from a source archive. From the point of view of ah_boostrap the two actions are equivalent, so we can just as easily simulate this by providing a setup.cfg giving the path to a source archive to "download" (as though it were a URL). """ source = tmpdir.mkdir('source') # Ensure ah_bootstrap is imported from the local directory import ah_bootstrap # Make a source distribution of the test package with silence(): run_setup(str(testpackage.join('setup.py')), ['sdist', '--dist-dir=dist', '--formats=gztar']) dist_dir = testpackage.join('dist') with source.as_cwd(): source.join('setup.py').write(TEST_SETUP_PY.format( args='download_if_needed=True')) source.join('setup.cfg').write(textwrap.dedent("""\ [easy_install] find_links = {find_links} """.format(find_links=str(dist_dir)))) run_setup('setup.py', []) stdout, stderr = capsys.readouterr() # Just take the last line--on Python 2.6 distutils logs warning # messages to stdout instead of stderr, causing them to be mixed up # with our expected output path = stdout.splitlines()[-1].strip() # easy_install should have worked by 'installing' astropy_helpers as a # .egg in the current directory eggs = _get_local_eggs() assert eggs egg = source.join(eggs[0]) assert os.path.isdir(str(egg)) a = os.path.normcase(path) b = os.path.normcase(str(egg.join('_astropy_helpers_test_', '__init__.py'))) assert a == b def test_upgrade(tmpdir, capsys): # Run the testpackage fixture manually, since we use it multiple times in # this test to make different versions of _astropy_helpers_test_ orig_dir = testpackage(tmpdir.mkdir('orig')) # Make a test package that uses _astropy_helpers_test_ source = tmpdir.mkdir('source') dist_dir = source.mkdir('dists') orig_dir.copy(source.join('_astropy_helpers_test_')) with source.as_cwd(): setup_py = TEST_SETUP_PY.format(args='auto_upgrade=True') source.join('setup.py').write(setup_py) # This will be used to later to fake downloading the upgrade package source.join('setup.cfg').write(textwrap.dedent("""\ [easy_install] find_links = {find_links} """.format(find_links=str(dist_dir)))) # Make additional "upgrade" versions of the _astropy_helpers_test_ # package--one of them is version 0.2 and the other is version 0.1.1. The # auto-upgrade should ignore version 0.2 but use version 0.1.1. upgrade_dir_1 = testpackage(tmpdir.mkdir('upgrade_1'), version='0.2') upgrade_dir_2 = testpackage(tmpdir.mkdir('upgrade_2'), version='0.1.1') dists = [] # For each upgrade package go ahead and build a source distribution of it # and copy that source distribution to a dist directory we'll use later to # simulate a 'download' for upgrade_dir in [upgrade_dir_1, upgrade_dir_2]: with silence(): run_setup(str(upgrade_dir.join('setup.py')), ['sdist', '--dist-dir=dist', '--formats=gztar']) dists.append(str(upgrade_dir.join('dist'))) for dist_file in upgrade_dir.visit('*.tar.gz'): dist_file.copy(source.join('dists')) # Monkey with the PackageIndex in ah_bootstrap so that it is initialized # with the test upgrade packages, and so that it does not actually go out # to the internet to look for anything import ah_bootstrap class FakePackageIndex(PackageIndex): def __init__(self, *args, **kwargs): PackageIndex.__init__(self, *args, **kwargs) self.to_scan = dists def find_packages(self, requirement): # no-op pass ah_bootstrap.PackageIndex = FakePackageIndex try: with source.as_cwd(): # Now run the source setup.py; this test is similar to # test_download_if_needed, but we explicitly check that the correct # *version* of _astropy_helpers_test_ was used run_setup('setup.py', []) stdout, stderr = capsys.readouterr() path = stdout.splitlines()[-1].strip() eggs = _get_local_eggs() assert eggs egg = source.join(eggs[0]) assert os.path.isdir(str(egg)) a = os.path.normcase(path) b = os.path.normcase(str(egg.join('_astropy_helpers_test_', '__init__.py'))) assert a == b assert 'astropy_helpers_test-0.1.1-' in str(egg) finally: ah_bootstrap.PackageIndex = PackageIndex def _get_local_eggs(path='.'): """ Helper utility used by some tests to get the list of egg archive files in a local directory. """ if SETUPTOOLS_VERSION[0] >= 7: eggs = glob.glob(os.path.join(path, '.eggs', '*.egg')) else: eggs = glob.glob('*.egg') return eggs wcsaxes-0.6/astropy_helpers/astropy_helpers/tests/test_git_helpers.py0000644000077000000240000001627412532571254026520 0ustar tomstaff00000000000000import glob import imp import os import pkgutil import re import sys import tarfile from . import * PY3 = sys.version_info[0] == 3 if PY3: _text_type = str else: _text_type = unicode _DEV_VERSION_RE = re.compile(r'\d+\.\d+(?:\.\d+)?\.dev(\d+)') TEST_VERSION_SETUP_PY = """\ #!/usr/bin/env python from setuptools import setup NAME = '_eva_' VERSION = {version!r} RELEASE = 'dev' not in VERSION from astropy_helpers.git_helpers import get_git_devstr from astropy_helpers.version_helpers import generate_version_py if not RELEASE: VERSION += get_git_devstr(False) generate_version_py(NAME, VERSION, RELEASE, False, uses_git=not RELEASE) setup(name=NAME, version=VERSION, packages=['_eva_']) """ TEST_VERSION_INIT = """\ try: from .version import version as __version__ from .version import githash as __githash__ except ImportError: __version__ = __githash__ = '' """ @pytest.fixture def version_test_package(tmpdir, request): def make_test_package(version='42.42.dev'): test_package = tmpdir.mkdir('test_package') test_package.join('setup.py').write( TEST_VERSION_SETUP_PY.format(version=version)) test_package.mkdir('_eva_').join('__init__.py').write(TEST_VERSION_INIT) with test_package.as_cwd(): run_cmd('git', ['init']) run_cmd('git', ['add', '--all']) run_cmd('git', ['commit', '-m', 'test package']) if '' in sys.path: sys.path.remove('') sys.path.insert(0, '') def finalize(): cleanup_import('_eva_') request.addfinalizer(finalize) return test_package return make_test_package def test_update_git_devstr(version_test_package, capsys): """Tests that the commit number in the package's version string updates after git commits even without re-running setup.py. """ # We have to call version_test_package to actually create the package test_pkg = version_test_package() with test_pkg.as_cwd(): run_setup('setup.py', ['--version']) stdout, stderr = capsys.readouterr() version = stdout.strip() m = _DEV_VERSION_RE.match(version) assert m, ( "Stdout did not match the version string pattern:" "\n\n{0}\n\nStderr:\n\n{1}".format(stdout, stderr)) revcount = int(m.group(1)) import _eva_ assert _eva_.__version__ == version # Make a silly git commit with open('.test', 'w'): pass run_cmd('git', ['add', '.test']) run_cmd('git', ['commit', '-m', 'test']) import _eva_.version imp.reload(_eva_.version) # Previously this checked packagename.__version__, but in order for that to # be updated we also have to re-import _astropy_init which could be tricky. # Checking directly that the packagename.version module was updated is # sufficient: m = _DEV_VERSION_RE.match(_eva_.version.version) assert m assert int(m.group(1)) == revcount + 1 # This doesn't test astropy_helpers.get_helpers.update_git_devstr directly # since a copy of that function is made in packagename.version (so that it # can work without astropy_helpers installed). In order to get test # coverage on the actual astropy_helpers copy of that function just call it # directly and compare to the value in packagename from astropy_helpers.git_helpers import update_git_devstr newversion = update_git_devstr(version, path=str(test_pkg)) assert newversion == _eva_.version.version def test_version_update_in_other_repos(version_test_package, tmpdir): """ Regression test for https://github.com/astropy/astropy-helpers/issues/114 and for https://github.com/astropy/astropy-helpers/issues/107 """ test_pkg = version_test_package() with test_pkg.as_cwd(): run_setup('setup.py', ['build']) # Add the path to the test package to sys.path for now sys.path.insert(0, str(test_pkg)) try: import _eva_ m = _DEV_VERSION_RE.match(_eva_.__version__) assert m correct_revcount = int(m.group(1)) with tmpdir.as_cwd(): testrepo = tmpdir.mkdir('testrepo') testrepo.chdir() # Create an empty git repo run_cmd('git', ['init']) import _eva_.version imp.reload(_eva_.version) m = _DEV_VERSION_RE.match(_eva_.version.version) assert m assert int(m.group(1)) == correct_revcount correct_revcount = int(m.group(1)) # Add several commits--more than the revcount for the _eva_ package for idx in range(correct_revcount + 5): test_filename = '.test' + str(idx) testrepo.ensure(test_filename) run_cmd('git', ['add', test_filename]) run_cmd('git', ['commit', '-m', 'A message']) import _eva_.version imp.reload(_eva_.version) m = _DEV_VERSION_RE.match(_eva_.version.version) assert m assert int(m.group(1)) == correct_revcount correct_revcount = int(m.group(1)) finally: sys.path.remove(str(test_pkg)) @pytest.mark.parametrize('version', ['1.0.dev', '1.0']) def test_installed_git_version(version_test_package, version, tmpdir, capsys): """ Test for https://github.com/astropy/astropy-helpers/issues/87 Ensures that packages installed with astropy_helpers have a correct copy of the git hash of the installed commit. """ # To test this, it should suffice to build a source dist, unpack it # somewhere outside the git repository, and then do a build and import # from the build directory--no need to "install" as such test_pkg = version_test_package(version) with test_pkg.as_cwd(): run_setup('setup.py', ['build']) try: import _eva_ githash = _eva_.__githash__ assert githash and isinstance(githash, _text_type) # Ensure that it does in fact look like a git hash and not some # other arbitrary string assert re.match(r'[0-9a-f]{40}', githash) finally: cleanup_import('_eva_') run_setup('setup.py', ['sdist', '--dist-dir=dist', '--formats=gztar']) tgzs = glob.glob(os.path.join('dist', '*.tar.gz')) assert len(tgzs) == 1 tgz = test_pkg.join(tgzs[0]) build_dir = tmpdir.mkdir('build_dir') tf = tarfile.open(str(tgz), mode='r:gz') tf.extractall(str(build_dir)) with build_dir.as_cwd(): pkg_dir = glob.glob('_eva_-*')[0] os.chdir(pkg_dir) run_setup('setup.py', ['build']) try: import _eva_ loader = pkgutil.get_loader('_eva_') # Ensure we are importing the 'packagename' that was just unpacked # into the build_dir if sys.version_info[:2] != (3, 3): # Skip this test on Python 3.3 wherein the SourceFileLoader # has a bug where get_filename() does not return an absolute # path assert loader.get_filename().startswith(str(build_dir)) assert _eva_.__githash__ == githash finally: cleanup_import('_eva_') wcsaxes-0.6/astropy_helpers/astropy_helpers/tests/test_setup_helpers.py0000644000077000000240000002201412532571254027062 0ustar tomstaff00000000000000import shutil import sys from textwrap import dedent from .. import setup_helpers from ..setup_helpers import get_package_info, register_commands from . import * @pytest.fixture def extension_test_package(tmpdir, request): """Creates a simple test package with an extension module.""" test_pkg = tmpdir.mkdir('test_pkg') test_pkg.mkdir('_eva_').ensure('__init__.py') # TODO: It might be later worth making this particular test package into a # reusable fixture for other build_ext tests # A minimal C extension for testing test_pkg.join('_eva_', 'unit01.c').write(dedent("""\ #include #ifndef PY3K #if PY_MAJOR_VERSION >= 3 #define PY3K 1 #else #define PY3K 0 #endif #endif #if PY3K static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "unit01", NULL, -1, NULL }; PyMODINIT_FUNC PyInit_unit01(void) { return PyModule_Create(&moduledef); } #else PyMODINIT_FUNC initunit01(void) { Py_InitModule3("unit01", NULL, NULL); } #endif """)) test_pkg.join('_eva_', 'setup_package.py').write(dedent("""\ from setuptools import Extension from os.path import join def get_extensions(): return [Extension('_eva_.unit01', [join('_eva_', 'unit01.c')])] """)) test_pkg.join('setup.py').write(dedent("""\ from os.path import join from setuptools import setup from astropy_helpers.setup_helpers import register_commands from astropy_helpers.setup_helpers import get_package_info from astropy_helpers.version_helpers import generate_version_py NAME = '_eva_' VERSION = '0.1' RELEASE = True cmdclassd = register_commands(NAME, VERSION, RELEASE) generate_version_py(NAME, VERSION, RELEASE, False, False) package_info = get_package_info() setup( name=NAME, version=VERSION, cmdclass=cmdclassd, **package_info ) """)) if '' in sys.path: sys.path.remove('') sys.path.insert(0, '') def finalize(): cleanup_import('_eva_') request.addfinalizer(finalize) return test_pkg def test_cython_autoextensions(tmpdir): """ Regression test for https://github.com/astropy/astropy-helpers/pull/19 Ensures that Cython extensions in sub-packages are discovered and built only once. """ # Make a simple test package test_pkg = tmpdir.mkdir('test_pkg') test_pkg.mkdir('yoda').mkdir('luke') test_pkg.ensure('yoda', '__init__.py') test_pkg.ensure('yoda', 'luke', '__init__.py') test_pkg.join('yoda', 'luke', 'dagobah.pyx').write( """def testfunc(): pass""") # Required, currently, for get_package_info to work register_commands('yoda', '0.0', False, srcdir=str(test_pkg)) package_info = get_package_info(str(test_pkg)) assert len(package_info['ext_modules']) == 1 assert package_info['ext_modules'][0].name == 'yoda.luke.dagobah' def test_compiler_module(extension_test_package): """ Test ensuring that the compiler module is built and installed for packages that have extension modules. """ test_pkg = extension_test_package install_temp = test_pkg.mkdir('install_temp') with test_pkg.as_cwd(): # This is one of the simplest ways to install just a package into a # test directory run_setup('setup.py', ['install', '--single-version-externally-managed', '--install-lib={0}'.format(install_temp), '--record={0}'.format(install_temp.join('record.txt'))]) with install_temp.as_cwd(): import _eva_ # Make sure we imported the _eva_ package from the correct place dirname = os.path.abspath(os.path.dirname(_eva_.__file__)) assert dirname == str(install_temp.join('_eva_')) import _eva_._compiler import _eva_.version assert _eva_.version.compiler == _eva_._compiler.compiler assert _eva_.version.compiler != 'unknown' def test_no_cython_buildext(extension_test_package): """ Regression test for https://github.com/astropy/astropy-helpers/pull/35 This tests the custom build_ext command installed by astropy_helpers when used with a project that has no Cython extensions (but does have one or more normal C extensions). """ test_pkg = extension_test_package # In order for this test to test the correct code path we need to fool # setup_helpers into thinking we don't have Cython installed setup_helpers._module_state['have_cython'] = False with test_pkg.as_cwd(): run_setup('setup.py', ['build_ext', '--inplace']) sys.path.insert(0, str(test_pkg)) try: import _eva_.unit01 dirname = os.path.abspath(os.path.dirname(_eva_.unit01.__file__)) assert dirname == str(test_pkg.join('_eva_')) finally: sys.path.remove(str(test_pkg)) @pytest.mark.parametrize('mode', ['cli', 'cli-w', 'direct']) def test_build_sphinx(tmpdir, mode): """ Test for build_sphinx """ import astropy_helpers ah_path = os.path.dirname(astropy_helpers.__file__) test_pkg = tmpdir.mkdir('test_pkg') test_pkg.mkdir('mypackage') test_pkg.join('mypackage').join('__init__.py').write(dedent("""\ def test_function(): pass class A(): pass class B(A): pass """)) docs = test_pkg.mkdir('docs') autosummary = docs.mkdir('_templates').mkdir('autosummary') autosummary.join('base.rst').write('{% extends "autosummary_core/base.rst" %}') autosummary.join('class.rst').write('{% extends "autosummary_core/class.rst" %}') autosummary.join('module.rst').write('{% extends "autosummary_core/module.rst" %}') docs_dir = test_pkg.join('docs') docs_dir.join('conf.py').write(dedent("""\ import sys sys.path.append("../") import warnings with warnings.catch_warnings(): # ignore matplotlib warning warnings.simplefilter("ignore") from astropy_helpers.sphinx.conf import * exclude_patterns.append('_templates') """)) docs_dir.join('index.rst').write(dedent("""\ .. automodapi:: mypackage """)) test_pkg.join('setup.py').write(dedent("""\ from os.path import join from setuptools import setup, Extension from astropy_helpers.setup_helpers import register_commands, get_package_info NAME = 'mypackage' VERSION = 0.1 RELEASE = True cmdclassd = register_commands(NAME, VERSION, RELEASE) setup( name=NAME, version=VERSION, cmdclass=cmdclassd, **get_package_info() ) """)) with test_pkg.as_cwd(): shutil.copytree(ah_path, 'astropy_helpers') if mode == 'cli': run_setup('setup.py', ['build_sphinx']) elif mode == 'cli-w': run_setup('setup.py', ['build_sphinx', '-w']) elif mode == 'direct': # to check coverage with docs_dir.as_cwd(): from sphinx import main try: main(['-b html', '-d _build/doctrees', '.', '_build/html']) except SystemExit as exc: assert exc.code == 0 def test_command_hooks(tmpdir, capsys): """A basic test for pre- and post-command hooks.""" test_pkg = tmpdir.mkdir('test_pkg') test_pkg.mkdir('_welltall_') test_pkg.join('_welltall_', '__init__.py').ensure() # Create a setup_package module with a couple of command hooks in it test_pkg.join('_welltall_', 'setup_package.py').write(dedent("""\ def pre_build_hook(cmd_obj): print('Hello build!') def post_build_hook(cmd_obj): print('Goodbye build!') """)) # A simple setup.py for the test package--running register_commands should # discover and enable the command hooks test_pkg.join('setup.py').write(dedent("""\ from os.path import join from setuptools import setup, Extension from astropy_helpers.setup_helpers import register_commands, get_package_info NAME = '_welltall_' VERSION = 0.1 RELEASE = True cmdclassd = register_commands(NAME, VERSION, RELEASE) setup( name=NAME, version=VERSION, cmdclass=cmdclassd ) """)) with test_pkg.as_cwd(): try: run_setup('setup.py', ['build']) finally: cleanup_import('_welltall_') stdout, stderr = capsys.readouterr() want = dedent("""\ running build running pre_hook from _welltall_.setup_package for build command Hello build! running post_hook from _welltall_.setup_package for build command Goodbye build! """).strip() assert want in stdout wcsaxes-0.6/astropy_helpers/astropy_helpers/utils.py0000644000077000000240000005051712532571254023150 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst from __future__ import absolute_import, unicode_literals import contextlib import functools import imp import inspect import os import sys import textwrap import types import warnings try: from importlib import machinery as import_machinery # Python 3.2 does not have SourceLoader if not hasattr(import_machinery, 'SourceLoader'): import_machinery = None except ImportError: import_machinery = None # Python 3.3's importlib caches filesystem reads for faster imports in the # general case. But sometimes it's necessary to manually invalidate those # caches so that the import system can pick up new generated files. See # https://github.com/astropy/astropy/issues/820 if sys.version_info[:2] >= (3, 3): from importlib import invalidate_caches else: invalidate_caches = lambda: None # Note: The following Warning subclasses are simply copies of the Warnings in # Astropy of the same names. class AstropyWarning(Warning): """ The base warning class from which all Astropy warnings should inherit. Any warning inheriting from this class is handled by the Astropy logger. """ class AstropyDeprecationWarning(AstropyWarning): """ A warning class to indicate a deprecated feature. """ class AstropyPendingDeprecationWarning(PendingDeprecationWarning, AstropyWarning): """ A warning class to indicate a soon-to-be deprecated feature. """ def _get_platlib_dir(cmd): """ Given a build command, return the name of the appropriate platform-specific build subdirectory directory (e.g. build/lib.linux-x86_64-2.7) """ plat_specifier = '.{0}-{1}'.format(cmd.plat_name, sys.version[0:3]) return os.path.join(cmd.build_base, 'lib' + plat_specifier) def get_numpy_include_path(): """ Gets the path to the numpy headers. """ # We need to go through this nonsense in case setuptools # downloaded and installed Numpy for us as part of the build or # install, since Numpy may still think it's in "setup mode", when # in fact we're ready to use it to build astropy now. if sys.version_info[0] >= 3: import builtins if hasattr(builtins, '__NUMPY_SETUP__'): del builtins.__NUMPY_SETUP__ import imp import numpy imp.reload(numpy) else: import __builtin__ if hasattr(__builtin__, '__NUMPY_SETUP__'): del __builtin__.__NUMPY_SETUP__ import numpy reload(numpy) try: numpy_include = numpy.get_include() except AttributeError: numpy_include = numpy.get_numpy_include() return numpy_include class _DummyFile(object): """A noop writeable object.""" errors = '' # Required for Python 3.x def write(self, s): pass def flush(self): pass @contextlib.contextmanager def silence(): """A context manager that silences sys.stdout and sys.stderr.""" old_stdout = sys.stdout old_stderr = sys.stderr sys.stdout = _DummyFile() sys.stderr = _DummyFile() exception_occurred = False try: yield except: exception_occurred = True # Go ahead and clean up so that exception handling can work normally sys.stdout = old_stdout sys.stderr = old_stderr raise if not exception_occurred: sys.stdout = old_stdout sys.stderr = old_stderr if sys.platform == 'win32': import ctypes def _has_hidden_attribute(filepath): """ Returns True if the given filepath has the hidden attribute on MS-Windows. Based on a post here: http://stackoverflow.com/questions/284115/cross-platform-hidden-file-detection """ if isinstance(filepath, bytes): filepath = filepath.decode(sys.getfilesystemencoding()) try: attrs = ctypes.windll.kernel32.GetFileAttributesW(filepath) assert attrs != -1 result = bool(attrs & 2) except (AttributeError, AssertionError): result = False return result else: def _has_hidden_attribute(filepath): return False def is_path_hidden(filepath): """ Determines if a given file or directory is hidden. Parameters ---------- filepath : str The path to a file or directory Returns ------- hidden : bool Returns `True` if the file is hidden """ name = os.path.basename(os.path.abspath(filepath)) if isinstance(name, bytes): is_dotted = name.startswith(b'.') else: is_dotted = name.startswith('.') return is_dotted or _has_hidden_attribute(filepath) def walk_skip_hidden(top, onerror=None, followlinks=False): """ A wrapper for `os.walk` that skips hidden files and directories. This function does not have the parameter `topdown` from `os.walk`: the directories must always be recursed top-down when using this function. See also -------- os.walk : For a description of the parameters """ for root, dirs, files in os.walk( top, topdown=True, onerror=onerror, followlinks=followlinks): # These lists must be updated in-place so os.walk will skip # hidden directories dirs[:] = [d for d in dirs if not is_path_hidden(d)] files[:] = [f for f in files if not is_path_hidden(f)] yield root, dirs, files def write_if_different(filename, data): """Write `data` to `filename`, if the content of the file is different. Parameters ---------- filename : str The file name to be written to. data : bytes The data to be written to `filename`. """ assert isinstance(data, bytes) if os.path.exists(filename): with open(filename, 'rb') as fd: original_data = fd.read() else: original_data = None if original_data != data: with open(filename, 'wb') as fd: fd.write(data) def import_file(filename, name=None): """ Imports a module from a single file as if it doesn't belong to a particular package. The returned module will have the optional ``name`` if given, or else a name generated from the filename. """ # Specifying a traditional dot-separated fully qualified name here # results in a number of "Parent module 'astropy' not found while # handling absolute import" warnings. Using the same name, the # namespaces of the modules get merged together. So, this # generates an underscore-separated name which is more likely to # be unique, and it doesn't really matter because the name isn't # used directly here anyway. mode = 'U' if sys.version_info[0] < 3 else 'r' if name is None: basename = os.path.splitext(filename)[0] name = '_'.join(os.path.relpath(basename).split(os.sep)[1:]) if import_machinery: loader = import_machinery.SourceFileLoader(name, filename) mod = loader.load_module() else: with open(filename, mode) as fd: mod = imp.load_module(name, fd, filename, ('.py', mode, 1)) return mod def resolve_name(name): """Resolve a name like ``module.object`` to an object and return it. Raise `ImportError` if the module or name is not found. """ parts = name.split('.') cursor = len(parts) - 1 module_name = parts[:cursor] attr_name = parts[-1] while cursor > 0: try: ret = __import__('.'.join(module_name), fromlist=[attr_name]) break except ImportError: if cursor == 0: raise cursor -= 1 module_name = parts[:cursor] attr_name = parts[cursor] ret = '' for part in parts[cursor:]: try: ret = getattr(ret, part) except AttributeError: raise ImportError(name) return ret if sys.version_info[0] >= 3: def iteritems(dictionary): return dictionary.items() else: def iteritems(dictionary): return dictionary.iteritems() def extends_doc(extended_func): """ A function decorator for use when wrapping an existing function but adding additional functionality. This copies the docstring from the original function, and appends to it (along with a newline) the docstring of the wrapper function. Example ------- >>> def foo(): ... '''Hello.''' ... >>> @extends_doc(foo) ... def bar(): ... '''Goodbye.''' ... >>> print(bar.__doc__) Hello. Goodbye. """ def decorator(func): func.__doc__ = '\n\n'.join([extended_func.__doc__.rstrip('\n'), func.__doc__.lstrip('\n')]) return func return decorator # Duplicated from astropy.utils.decorators.deprecated # When fixing issues in this function fix them in astropy first, then # port the fixes over to astropy-helpers def deprecated(since, message='', name='', alternative='', pending=False, obj_type=None): """ Used to mark a function or class as deprecated. To mark an attribute as deprecated, use `deprecated_attribute`. Parameters ------------ since : str The release at which this API became deprecated. This is required. message : str, optional Override the default deprecation message. The format specifier ``func`` may be used for the name of the function, and ``alternative`` may be used in the deprecation message to insert the name of an alternative to the deprecated function. ``obj_type`` may be used to insert a friendly name for the type of object being deprecated. name : str, optional The name of the deprecated function or class; if not provided the name is automatically determined from the passed in function or class, though this is useful in the case of renamed functions, where the new function is just assigned to the name of the deprecated function. For example:: def new_function(): ... oldFunction = new_function alternative : str, optional An alternative function or class name that the user may use in place of the deprecated object. The deprecation warning will tell the user about this alternative if provided. pending : bool, optional If True, uses a AstropyPendingDeprecationWarning instead of a AstropyDeprecationWarning. obj_type : str, optional The type of this object, if the automatically determined one needs to be overridden. """ method_types = (classmethod, staticmethod, types.MethodType) def deprecate_doc(old_doc, message): """ Returns a given docstring with a deprecation message prepended to it. """ if not old_doc: old_doc = '' old_doc = textwrap.dedent(old_doc).strip('\n') new_doc = (('\n.. deprecated:: %(since)s' '\n %(message)s\n\n' % {'since': since, 'message': message.strip()}) + old_doc) if not old_doc: # This is to prevent a spurious 'unexpected unindent' warning from # docutils when the original docstring was blank. new_doc += r'\ ' return new_doc def get_function(func): """ Given a function or classmethod (or other function wrapper type), get the function object. """ if isinstance(func, method_types): try: func = func.__func__ except AttributeError: # classmethods in Python2.6 and below lack the __func__ # attribute so we need to hack around to get it method = func.__get__(None, object) if isinstance(method, types.FunctionType): # For staticmethods anyways the wrapped object is just a # plain function (not a bound method or anything like that) func = method elif hasattr(method, '__func__'): func = method.__func__ elif hasattr(method, 'im_func'): func = method.im_func else: # Nothing we can do really... just return the original # classmethod, etc. return func return func def deprecate_function(func, message): """ Returns a wrapped function that displays an ``AstropyDeprecationWarning`` when it is called. """ if isinstance(func, method_types): func_wrapper = type(func) else: func_wrapper = lambda f: f func = get_function(func) def deprecated_func(*args, **kwargs): if pending: category = AstropyPendingDeprecationWarning else: category = AstropyDeprecationWarning warnings.warn(message, category, stacklevel=2) return func(*args, **kwargs) # If this is an extension function, we can't call # functools.wraps on it, but we normally don't care. # This crazy way to get the type of a wrapper descriptor is # straight out of the Python 3.3 inspect module docs. if type(func) != type(str.__dict__['__add__']): deprecated_func = functools.wraps(func)(deprecated_func) deprecated_func.__doc__ = deprecate_doc( deprecated_func.__doc__, message) return func_wrapper(deprecated_func) def deprecate_class(cls, message): """ Returns a wrapper class with the docstrings updated and an __init__ function that will raise an ``AstropyDeprectationWarning`` warning when called. """ # Creates a new class with the same name and bases as the # original class, but updates the dictionary with a new # docstring and a wrapped __init__ method. __module__ needs # to be manually copied over, since otherwise it will be set # to *this* module (astropy.utils.misc). # This approach seems to make Sphinx happy (the new class # looks enough like the original class), and works with # extension classes (which functools.wraps does not, since # it tries to modify the original class). # We need to add a custom pickler or you'll get # Can't pickle : it's not found as ... # errors. Picklability is required for any class that is # documented by Sphinx. members = cls.__dict__.copy() members.update({ '__doc__': deprecate_doc(cls.__doc__, message), '__init__': deprecate_function(get_function(cls.__init__), message), }) return type(cls.__name__, cls.__bases__, members) def deprecate(obj, message=message, name=name, alternative=alternative, pending=pending): if obj_type is None: if isinstance(obj, type): obj_type_name = 'class' elif inspect.isfunction(obj): obj_type_name = 'function' elif inspect.ismethod(obj) or isinstance(obj, method_types): obj_type_name = 'method' else: obj_type_name = 'object' else: obj_type_name = obj_type if not name: name = get_function(obj).__name__ altmessage = '' if not message or type(message) == type(deprecate): if pending: message = ('The %(func)s %(obj_type)s will be deprecated in a ' 'future version.') else: message = ('The %(func)s %(obj_type)s is deprecated and may ' 'be removed in a future version.') if alternative: altmessage = '\n Use %s instead.' % alternative message = ((message % { 'func': name, 'name': name, 'alternative': alternative, 'obj_type': obj_type_name}) + altmessage) if isinstance(obj, type): return deprecate_class(obj, message) else: return deprecate_function(obj, message) if type(message) == type(deprecate): return deprecate(message) return deprecate def deprecated_attribute(name, since, message=None, alternative=None, pending=False): """ Used to mark a public attribute as deprecated. This creates a property that will warn when the given attribute name is accessed. To prevent the warning (i.e. for internal code), use the private name for the attribute by prepending an underscore (i.e. ``self._name``). Parameters ---------- name : str The name of the deprecated attribute. since : str The release at which this API became deprecated. This is required. message : str, optional Override the default deprecation message. The format specifier ``name`` may be used for the name of the attribute, and ``alternative`` may be used in the deprecation message to insert the name of an alternative to the deprecated function. alternative : str, optional An alternative attribute that the user may use in place of the deprecated attribute. The deprecation warning will tell the user about this alternative if provided. pending : bool, optional If True, uses a AstropyPendingDeprecationWarning instead of a AstropyDeprecationWarning. Examples -------- :: class MyClass: # Mark the old_name as deprecated old_name = misc.deprecated_attribute('old_name', '0.1') def method(self): self._old_name = 42 """ private_name = '_' + name @deprecated(since, name=name, obj_type='attribute') def get(self): return getattr(self, private_name) @deprecated(since, name=name, obj_type='attribute') def set(self, val): setattr(self, private_name, val) @deprecated(since, name=name, obj_type='attribute') def delete(self): delattr(self, private_name) return property(get, set, delete) def minversion(module, version, inclusive=True, version_path='__version__'): """ Returns `True` if the specified Python module satisfies a minimum version requirement, and `False` if not. By default this uses `pkg_resources.parse_version` to do the version comparison if available. Otherwise it falls back on `distutils.version.LooseVersion`. Parameters ---------- module : module or `str` An imported module of which to check the version, or the name of that module (in which case an import of that module is attempted-- if this fails `False` is returned). version : `str` The version as a string that this module must have at a minimum (e.g. ``'0.12'``). inclusive : `bool` The specified version meets the requirement inclusively (i.e. ``>=``) as opposed to strictly greater than (default: `True`). version_path : `str` A dotted attribute path to follow in the module for the version. Defaults to just ``'__version__'``, which should work for most Python modules. Examples -------- >>> import astropy >>> minversion(astropy, '0.4.4') True """ if isinstance(module, types.ModuleType): module_name = module.__name__ elif isinstance(module, six.string_types): module_name = module try: module = resolve_name(module_name) except ImportError: return False else: raise ValueError('module argument must be an actual imported ' 'module, or the import name of the module; ' 'got {0!r}'.format(module)) if '.' not in version_path: have_version = getattr(module, version_path) else: have_version = resolve_name('.'.join([module.__name__, version_path])) try: from pkg_resources import parse_version except ImportError: from distutils.version import LooseVersion as parse_version if inclusive: return parse_version(have_version) >= parse_version(version) else: return parse_version(have_version) > parse_version(version) wcsaxes-0.6/astropy_helpers/astropy_helpers/version.py0000644000077000000240000000703612346275264023500 0ustar tomstaff00000000000000# Autogenerated by Astropy-affiliated package astropy_helpers's setup.py on 2014-06-12 12:02:28.641845 import os import subprocess import warnings def update_git_devstr(version, path=None): """ Updates the git revision string if and only if the path is being imported directly from a git working copy. This ensures that the revision number in the version string is accurate. """ try: # Quick way to determine if we're in git or not - returns '' if not devstr = get_git_devstr(sha=True, show_warning=False, path=path) except OSError: return version if not devstr: # Probably not in git so just pass silently return version if 'dev' in version: # update to the current git revision version_base = version.split('.dev', 1)[0] devstr = get_git_devstr(sha=False, show_warning=False, path=path) return version_base + '.dev' + devstr else: #otherwise it's already the true/release version return version def get_git_devstr(sha=False, show_warning=True, path=None): """ Determines the number of revisions in this repository. Parameters ---------- sha : bool If True, the full SHA1 hash will be returned. Otherwise, the total count of commits in the repository will be used as a "revision number". show_warning : bool If True, issue a warning if git returns an error code, otherwise errors pass silently. path : str or None If a string, specifies the directory to look in to find the git repository. If `None`, the current working directory is used. If given a filename it uses the directory containing that file. Returns ------- devversion : str Either a string with the revsion number (if `sha` is False), the SHA1 hash of the current commit (if `sha` is True), or an empty string if git version info could not be identified. """ if path is None: path = os.getcwd() if not os.path.isdir(path): path = os.path.abspath(os.path.dirname(path)) if not os.path.exists(os.path.join(path, '.git')): return '' if sha: cmd = ['rev-parse'] # Faster for getting just the hash of HEAD else: cmd = ['rev-list', '--count'] try: p = subprocess.Popen(['git'] + cmd + ['HEAD'], cwd=path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) stdout, stderr = p.communicate() except OSError as e: if show_warning: warnings.warn('Error running git: ' + str(e)) return '' if p.returncode == 128: if show_warning: warnings.warn('No git repository present at {0!r}! Using default ' 'dev version.'.format(path)) return '' elif p.returncode != 0: if show_warning: warnings.warn('Git failed while determining revision ' 'count: ' + stderr) return '' if sha: return stdout.decode('utf-8')[:40] else: return stdout.decode('utf-8').strip() _last_generated_version = '0.4rc1.dev' version = update_git_devstr(_last_generated_version) githash = get_git_devstr(sha=True, show_warning=False) major = 0 minor = 4 bugfix = 0 release = False debug = False try: from ._compiler import compiler except ImportError: compiler = "unknown" try: from .cython_version import cython_version except ImportError: cython_version = "unknown" wcsaxes-0.6/astropy_helpers/astropy_helpers/version_helpers.py0000644000077000000240000002264412532571254025217 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Utilities for generating the version string for Astropy (or an affiliated package) and the version.py module, which contains version info for the package. Within the generated astropy.version module, the `major`, `minor`, and `bugfix` variables hold the respective parts of the version number (bugfix is '0' if absent). The `release` variable is True if this is a release, and False if this is a development version of astropy. For the actual version string, use:: from astropy.version import version or:: from astropy import __version__ """ from __future__ import division import datetime import imp import os import pkgutil import sys from distutils import log import pkg_resources from . import git_helpers from .distutils_helpers import is_distutils_display_option from .utils import invalidate_caches PY3 = sys.version_info[0] == 3 def _version_split(version): """ Split a version string into major, minor, and bugfix numbers. If any of those numbers are missing the default is zero. Any pre/post release modifiers are ignored. Examples ======== >>> _version_split('1.2.3') (1, 2, 3) >>> _version_split('1.2') (1, 2, 0) >>> _version_split('1.2rc1') (1, 2, 0) >>> _version_split('1') (1, 0, 0) >>> _version_split('') (0, 0, 0) """ parsed_version = pkg_resources.parse_version(version) if hasattr(parsed_version, 'base_version'): # New version parsing for setuptools >= 8.0 if parsed_version.base_version: parts = [int(part) for part in parsed_version.base_version.split('.')] else: parts = [] else: parts = [] for part in parsed_version: if part.startswith('*'): # Ignore any .dev, a, b, rc, etc. break parts.append(int(part)) if len(parts) < 3: parts += [0] * (3 - len(parts)) # In principle a version could have more parts (like 1.2.3.4) but we only # support .. return tuple(parts[:3]) # This is used by setup.py to create a new version.py - see that file for # details. Note that the imports have to be absolute, since this is also used # by affiliated packages. _FROZEN_VERSION_PY_TEMPLATE = """ # Autogenerated by {packagetitle}'s setup.py on {timestamp!s} from __future__ import unicode_literals import datetime {header} major = {major} minor = {minor} bugfix = {bugfix} release = {rel} timestamp = {timestamp!r} debug = {debug} try: from ._compiler import compiler except ImportError: compiler = "unknown" try: from .cython_version import cython_version except ImportError: cython_version = "unknown" """[1:] _FROZEN_VERSION_PY_WITH_GIT_HEADER = """ {git_helpers} _packagename = "{packagename}" _last_generated_version = "{verstr}" _last_githash = "{githash}" # Determine where the source code for this module # lives. If __file__ is not a filesystem path then # it is assumed not to live in a git repo at all. if _get_repo_path(__file__, levels=len(_packagename.split('.'))): version = update_git_devstr(_last_generated_version, path=__file__) githash = get_git_devstr(sha=True, show_warning=False, path=__file__) or _last_githash else: # The file does not appear to live in a git repo so don't bother # invoking git version = _last_generated_version githash = _last_githash """[1:] _FROZEN_VERSION_PY_STATIC_HEADER = """ version = "{verstr}" githash = "{githash}" """[1:] def _get_version_py_str(packagename, version, githash, release, debug, uses_git=True): timestamp = datetime.datetime.now() major, minor, bugfix = _version_split(version) if packagename.lower() == 'astropy': packagetitle = 'Astropy' else: packagetitle = 'Astropy-affiliated package ' + packagename header = '' if uses_git: header = _generate_git_header(packagename, version, githash) elif not githash: # _generate_git_header will already generate a new git has for us, but # for creating a new version.py for a release (even if uses_git=False) # we still need to get the githash to include in the version.py # See https://github.com/astropy/astropy-helpers/issues/141 githash = git_helpers.get_git_devstr(sha=True, show_warning=True) if not header: # If _generate_git_header fails it returns an empty string header = _FROZEN_VERSION_PY_STATIC_HEADER.format(verstr=version, githash=githash) return _FROZEN_VERSION_PY_TEMPLATE.format(packagetitle=packagetitle, timestamp=timestamp, header=header, major=major, minor=minor, bugfix=bugfix, rel=release, debug=debug) def _generate_git_header(packagename, version, githash): """ Generates a header to the version.py module that includes utilities for probing the git repository for updates (to the current git hash, etc.) These utilities should only be available in development versions, and not in release builds. If this fails for any reason an empty string is returned. """ loader = pkgutil.get_loader(git_helpers) source = loader.get_source(git_helpers.__name__) or '' source_lines = source.splitlines() if not source_lines: log.warn('Cannot get source code for astropy_helpers.git_helpers; ' 'git support disabled.') return '' idx = 0 for idx, line in enumerate(source_lines): if line.startswith('# BEGIN'): break git_helpers_py = '\n'.join(source_lines[idx + 1:]) if PY3: verstr = version else: # In Python 2 don't pass in a unicode string; otherwise verstr will # be represented with u'' syntax which breaks on Python 3.x with x # < 3. This is only an issue when developing on multiple Python # versions at once verstr = version.encode('utf8') new_githash = git_helpers.get_git_devstr(sha=True, show_warning=False) if new_githash: githash = new_githash return _FROZEN_VERSION_PY_WITH_GIT_HEADER.format( git_helpers=git_helpers_py, packagename=packagename, verstr=verstr, githash=githash) def generate_version_py(packagename, version, release=None, debug=None, uses_git=True): """Regenerate the version.py module if necessary.""" try: version_module = get_pkg_version_module(packagename) try: last_generated_version = version_module._last_generated_version except AttributeError: last_generated_version = version_module.version try: last_githash = version_module._last_githash except AttributeError: last_githash = version_module.githash current_release = version_module.release current_debug = version_module.debug except ImportError: version_module = None last_generated_version = None last_githash = None current_release = None current_debug = None if release is None: # Keep whatever the current value is, if it exists release = bool(current_release) if debug is None: # Likewise, keep whatever the current value is, if it exists debug = bool(current_debug) version_py = os.path.join(packagename, 'version.py') if (last_generated_version != version or current_release != release or current_debug != debug): if '-q' not in sys.argv and '--quiet' not in sys.argv: log.set_threshold(log.INFO) if is_distutils_display_option(): # Always silence unnecessary log messages when display options are # being used log.set_threshold(log.WARN) log.info('Freezing version number to {0}'.format(version_py)) with open(version_py, 'w') as f: # This overwrites the actual version.py f.write(_get_version_py_str(packagename, version, last_githash, release, debug, uses_git=uses_git)) invalidate_caches() if version_module: imp.reload(version_module) def get_pkg_version_module(packagename, fromlist=None): """Returns the package's .version module generated by `astropy_helpers.version_helpers.generate_version_py`. Raises an ImportError if the version module is not found. If ``fromlist`` is an iterable, return a tuple of the members of the version module corresponding to the member names given in ``fromlist``. Raises an `AttributeError` if any of these module members are not found. """ if not fromlist: # Due to a historical quirk of Python's import implementation, # __import__ will not return submodules of a package if 'fromlist' is # empty. # TODO: For Python 3.1 and up it may be preferable to use importlib # instead of the __import__ builtin return __import__(packagename + '.version', fromlist=['']) else: mod = __import__(packagename + '.version', fromlist=fromlist) return tuple(getattr(mod, member) for member in fromlist) wcsaxes-0.6/astropy_helpers/astropy_helpers.egg-info/0000755000077000000240000000000012553237435023123 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/astropy_helpers.egg-info/dependency_links.txt0000644000077000000240000000000112346275264027173 0ustar tomstaff00000000000000 wcsaxes-0.6/astropy_helpers/astropy_helpers.egg-info/not-zip-safe0000644000077000000240000000000112346275264025353 0ustar tomstaff00000000000000 wcsaxes-0.6/astropy_helpers/astropy_helpers.egg-info/PKG-INFO0000644000077000000240000000546612346275264024235 0ustar tomstaff00000000000000Metadata-Version: 1.1 Name: astropy-helpers Version: 0.4rc1.dev150 Summary: Utilities for building and installing Astropy, Astropy affiliated packages, and their respective documentation. Home-page: http://astropy.org Author: The Astropy Developers Author-email: astropy.team@gmail.com License: BSD Download-URL: http://pypi.python.org/packages/source/a/astropy-helpers/astropy-helpers-0.4rc1.dev150.tar.gz Description: astropy-helpers =============== This project provides a Python package, ``astropy_helpers``, which includes many build, installation, and documentation-related tools used by the Astropy project, but packaged separately for use by other projects that wish to leverage this work. There is a draft Astropy Proposal for Enhancement dubbed `APE 4 `_ describing the motivation behind this package and details of its implementation. Acceptance of APE 4 is pending only on hammering out minor details prior to the release of Astropy v0.4. This also includes a special "bootstrap" module called ``ah_bootstrap.py`` which is intended to be used by a project's setup.py in order to ensure that the ``astropy_helpers`` package is available for build/installation. This is similar to the ``ez_setup.py`` module that is shipped with some projects to bootstrap `setuptools `_. This preview release of astropy-helpers is intended for testing installation via PyPI prior to the final initial release which will be astropy-helpers v0.4. The version of the initial release was chosen, in this case, to parallel Astropy v0.4, which will be the first version of Astropy to use astropy-helpers. As described in APE 4, the major/minor version of astropy-helpers will be kept parallel with the latest version of Astropy, though the micro (bugfix) version will be allowed to diverge. More details will be added to this README before astropy-helpers v0.4 final is released. In the meantime, see the setup.py and setup.cfg files in the `Affiliated package template `_ for examples of its usage. Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Build Tools Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: System :: Archiving :: Packaging wcsaxes-0.6/astropy_helpers/astropy_helpers.egg-info/SOURCES.txt0000644000077000000240000000532212346275264025013 0ustar tomstaff00000000000000CHANGES.rst LICENSE.rst MANIFEST.in README.rst ah_bootstrap.py ez_setup.py setup.cfg setup.py astropy_helpers/__init__.py astropy_helpers/git_helpers.py astropy_helpers/setup_helpers.py astropy_helpers/test_helpers.py astropy_helpers/utils.py astropy_helpers/version.py astropy_helpers/version_helpers.py astropy_helpers.egg-info/PKG-INFO astropy_helpers.egg-info/SOURCES.txt astropy_helpers.egg-info/dependency_links.txt astropy_helpers.egg-info/not-zip-safe astropy_helpers.egg-info/top_level.txt astropy_helpers/compat/__init__.py astropy_helpers/compat/subprocess.py astropy_helpers/sphinx/__init__.py astropy_helpers/sphinx/conf.py astropy_helpers/sphinx/setup_package.py astropy_helpers/sphinx/ext/__init__.py astropy_helpers/sphinx/ext/astropyautosummary.py astropy_helpers/sphinx/ext/automodapi.py astropy_helpers/sphinx/ext/automodsumm.py astropy_helpers/sphinx/ext/changelog_links.py astropy_helpers/sphinx/ext/comment_eater.py astropy_helpers/sphinx/ext/compiler_unparse.py astropy_helpers/sphinx/ext/docscrape.py astropy_helpers/sphinx/ext/docscrape_sphinx.py astropy_helpers/sphinx/ext/doctest.py astropy_helpers/sphinx/ext/edit_on_github.py astropy_helpers/sphinx/ext/numpydoc.py astropy_helpers/sphinx/ext/phantom_import.py astropy_helpers/sphinx/ext/smart_resolver.py astropy_helpers/sphinx/ext/tocdepthfix.py astropy_helpers/sphinx/ext/traitsdoc.py astropy_helpers/sphinx/ext/utils.py astropy_helpers/sphinx/ext/viewcode.py astropy_helpers/sphinx/ext/templates/autosummary_core/base.rst astropy_helpers/sphinx/ext/templates/autosummary_core/class.rst astropy_helpers/sphinx/ext/templates/autosummary_core/module.rst astropy_helpers/sphinx/ext/tests/__init__.py astropy_helpers/sphinx/ext/tests/test_automodapi.py astropy_helpers/sphinx/ext/tests/test_automodsumm.py astropy_helpers/sphinx/ext/tests/test_docscrape.py astropy_helpers/sphinx/ext/tests/test_utils.py astropy_helpers/sphinx/local/python3links.inv astropy_helpers/sphinx/themes/bootstrap-astropy/globaltoc.html astropy_helpers/sphinx/themes/bootstrap-astropy/layout.html astropy_helpers/sphinx/themes/bootstrap-astropy/localtoc.html astropy_helpers/sphinx/themes/bootstrap-astropy/searchbox.html astropy_helpers/sphinx/themes/bootstrap-astropy/theme.conf astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_linkout_20.png astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo.ico astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo_32.png astropy_helpers/sphinx/themes/bootstrap-astropy/static/bootstrap-astropy.css astropy_helpers/sphinx/themes/bootstrap-astropy/static/copybutton.js astropy_helpers/sphinx/themes/bootstrap-astropy/static/sidebar.js astropy_helpers/src/__init__.py astropy_helpers/src/compiler.c astropy_helpers/src/setup_package.pywcsaxes-0.6/astropy_helpers/astropy_helpers.egg-info/top_level.txt0000644000077000000240000000002012346275264025647 0ustar tomstaff00000000000000astropy_helpers wcsaxes-0.6/astropy_helpers/CHANGES.rst0000644000077000000240000002061612532571254020012 0ustar tomstaff00000000000000astropy-helpers Changelog ========================= 1.0.2 (2015-04-02) ------------------ - Various fixes enabling the astropy-helpers Sphinx build command and Sphinx extensions to work with Sphinx 1.3. [#148] - More improvement to the ability to handle multiple versions of astropy-helpers being imported in the same Python interpreter session in the (somewhat rare) case of nested installs. [#147] - To better support high resolution displays, use SVG for the astropy logo and linkout image, falling back to PNGs for browsers that support it. [#150, #151] - Improve ``setup_helpers.get_compiler_version`` to work with more compilers, and to return more info. This will help fix builds of Astropy on less common compilers, like Sun C. [#153] 1.0.1 (2015-03-04) ------------------ - Released in concert with v0.4.8 to address the same issues. - Improved the ``ah_bootstrap`` script's ability to override existing installations of astropy-helpers with new versions in the context of installing multiple packages simultaneously within the same Python interpreter (e.g. when one package has in its ``setup_requires`` another package that uses a different version of astropy-helpers. [#144] - Added a workaround to an issue in matplotlib that can, in rare cases, lead to a crash when installing packages that import matplotlib at build time. [#144] 0.4.8 (2015-03-04) ------------------ - Improved the ``ah_bootstrap`` script's ability to override existing installations of astropy-helpers with new versions in the context of installing multiple packages simultaneously within the same Python interpreter (e.g. when one package has in its ``setup_requires`` another package that uses a different version of astropy-helpers. [#144] - Added a workaround to an issue in matplotlib that can, in rare cases, lead to a crash when installing packages that import matplotlib at build time. [#144] 1.0 (2015-02-17) ---------------- - Added new pre-/post-command hook points for ``setup.py`` commands. Now any package can define code to run before and/or after any ``setup.py`` command without having to manually subclass that command by adding ``pre__hook`` and ``post__hook`` callables to the package's ``setup_package.py`` module. See the PR for more details. [#112] - The following objects in the ``astropy_helpers.setup_helpers`` module have been relocated: - ``get_dummy_distribution``, ``get_distutils_*``, ``get_compiler_option``, ``add_command_option``, ``is_distutils_display_option`` -> ``astropy_helpers.distutils_helpers`` - ``should_build_with_cython``, ``generate_build_ext_command`` -> ``astropy_helpers.commands.build_ext`` - ``AstropyBuildPy`` -> ``astropy_helpers.commands.build_py`` - ``AstropyBuildSphinx`` -> ``astropy_helpers.commands.build_sphinx`` - ``AstropyInstall`` -> ``astropy_helpers.commands.install`` - ``AstropyInstallLib`` -> ``astropy_helpers.commands.install_lib`` - ``AstropyRegister`` -> ``astropy_helpers.commands.register`` - ``get_pkg_version_module`` -> ``astropy_helpers.version_helpers`` - ``write_if_different``, ``import_file``, ``get_numpy_include_path`` -> ``astropy_helpers.utils`` All of these are "soft" deprecations in the sense that they are still importable from ``astropy_helpers.setup_helpers`` for now, and there is no (easy) way to produce deprecation warnings when importing these objects from ``setup_helpers`` rather than directly from the modules they are defined in. But please consider updating any imports to these objects. [#110] - Use of the ``astropy.sphinx.ext.astropyautosummary`` extension is deprecated for use with Sphinx < 1.2. Instead it should suffice to remove this extension for the ``extensions`` list in your ``conf.py`` and add the stock ``sphinx.ext.autosummary`` instead. [#131] 0.4.7 (2015-02-17) ------------------ - Fixed incorrect/missing git hash being added to the generated ``version.py`` when creating a release. [#141] 0.4.6 (2015-02-16) ------------------ - Fixed problems related to the automatically generated _compiler module not being created properly. [#139] 0.4.5 (2015-02-11) ------------------ - Fixed an issue where ah_bootstrap.py could blow up when astropy_helper's version number is 1.0. - Added a workaround for documentation of properties in the rare case where the class's metaclass has a property of the same name. [#130] - Fixed an issue on Python 3 where importing a package using astropy-helper's generated version.py module would crash when the current working directory is an empty git repository. [#114] - Fixed an issue where the "revision count" appended to .dev versions by the generated version.py did not accurately reflect the revision count for the package it belongs to, and could be invalid if the current working directory is an unrelated git repository. [#107] - Likewise, fixed a confusing warning message that could occur in the same circumstances as the above issue. [#121] 0.4.4 (2014-12-31) ------------------ - More improvements for building the documentation using Python 3.x. [#100] - Additional minor fixes to Python 3 support. [#115] - Updates to support new test features in Astropy [#92, #106] 0.4.3 (2014-10-22) ------------------ - The generated ``version.py`` file now preserves the git hash of installed copies of the package as well as when building a source distribution. That is, the git hash of the changeset that was installed/released is preserved. [#87] - In smart resolver add resolution for class links when they exist in the intersphinx inventory, but not the mapping of the current package (e.g. when an affiliated package uses an astropy core class of which "actual" and "documented" location differs) [#88] - Fixed a bug that could occur when running ``setup.py`` for the first time in a repository that uses astropy-helpers as a submodule: ``AttributeError: 'NoneType' object has no attribute 'mkdtemp'`` [#89] - Fixed a bug where optional arguments to the ``doctest-skip`` Sphinx directive were sometimes being left in the generated documentation output. [#90] - Improved support for building the documentation using Python 3.x. [#96] - Avoid error message if .git directory is not present. [#91] 0.4.2 (2014-08-09) ------------------ - Fixed some CSS issues in generated API docs. [#69] - Fixed the warning message that could be displayed when generating a version number with some older versions of git. [#77] - Fixed automodsumm to work with new versions of Sphinx (>= 1.2.2). [#80] 0.4.1 (2014-08-08) ------------------ - Fixed git revision count on systems with git versions older than v1.7.2. [#70] - Fixed display of warning text when running a git command fails (previously the output of stderr was not being decoded properly). [#70] - The ``--offline`` flag to ``setup.py`` understood by ``ah_bootstrap.py`` now also prevents git from going online to fetch submodule updates. [#67] - The Sphinx extension for converting issue numbers to links in the changelog now supports working on arbitrary pages via a new ``conf.py`` setting: ``changelog_links_docpattern``. By default it affects the ``changelog`` and ``whatsnew`` pages in one's Sphinx docs. [#61] - Fixed crash that could result from users with missing/misconfigured locale settings. [#58] - The font used for code examples in the docs is now the system-defined ``monospace`` font, rather than ``Minaco``, which is not available on all platforms. [#50] 0.4 (2014-07-15) ---------------- - Initial release of astropy-helpers. See `APE4 `_ for details of the motivation and design of this package. - The ``astropy_helpers`` package replaces the following modules in the ``astropy`` package: - ``astropy.setup_helpers`` -> ``astropy_helpers.setup_helpers`` - ``astropy.version_helpers`` -> ``astropy_helpers.version_helpers`` - ``astropy.sphinx`` - > ``astropy_helpers.sphinx`` These modules should be considered deprecated in ``astropy``, and any new, non-critical changes to those modules will be made in ``astropy_helpers`` instead. Affiliated packages wishing to make use those modules (as in the Astropy package-template) should use the versions from ``astropy_helpers`` instead, and include the ``ah_bootstrap.py`` script in their project, for bootstrapping the ``astropy_helpers`` package in their setup.py script. wcsaxes-0.6/astropy_helpers/continuous-integration/0000755000077000000240000000000012553237435022735 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/continuous-integration/appveyor/0000755000077000000240000000000012553237435024602 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/continuous-integration/appveyor/install-miniconda.ps10000644000077000000240000000446012532571254030635 0ustar tomstaff00000000000000# Sample script to install anaconda under windows # Authors: Stuart Mumford # Borrwed from: Olivier Grisel and Kyle Kastner # License: BSD 3 clause $MINICONDA_URL = "http://repo.continuum.io/miniconda/" function DownloadMiniconda ($version, $platform_suffix) { $webclient = New-Object System.Net.WebClient $filename = "Miniconda-" + $version + "-Windows-" + $platform_suffix + ".exe" $url = $MINICONDA_URL + $filename $basedir = $pwd.Path + "\" $filepath = $basedir + $filename if (Test-Path $filename) { Write-Host "Reusing" $filepath return $filepath } # Download and retry up to 3 times in case of network transient errors. Write-Host "Downloading" $filename "from" $url $retry_attempts = 2 for($i=0; $i -lt $retry_attempts; $i++){ try { $webclient.DownloadFile($url, $filepath) break } Catch [Exception]{ Start-Sleep 1 } } if (Test-Path $filepath) { Write-Host "File saved at" $filepath } else { # Retry once to get the error message if any at the last try $webclient.DownloadFile($url, $filepath) } return $filepath } function InstallMiniconda ($python_version, $architecture, $python_home) { Write-Host "Installing miniconda" $python_version "for" $architecture "bit architecture to" $python_home if (Test-Path $python_home) { Write-Host $python_home "already exists, skipping." return $false } if ($architecture -eq "x86") { $platform_suffix = "x86" } else { $platform_suffix = "x86_64" } $filepath = DownloadMiniconda $python_version $platform_suffix Write-Host "Installing" $filepath "to" $python_home $args = "/InstallationType=AllUsers /S /AddToPath=1 /RegisterPython=1 /D=" + $python_home Write-Host $filepath $args Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru #Start-Sleep -s 15 if (Test-Path C:\conda) { Write-Host "Miniconda $python_version ($architecture) installation complete" } else { Write-Host "Failed to install Python in $python_home" Exit 1 } } function main () { InstallMiniconda $env:MINICONDA_VERSION $env:PLATFORM $env:PYTHON } main wcsaxes-0.6/astropy_helpers/continuous-integration/appveyor/windows_sdk.cmd0000644000077000000240000000346212532571254027624 0ustar tomstaff00000000000000:: To build extensions for 64 bit Python 3, we need to configure environment :: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of: :: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1) :: :: To build extensions for 64 bit Python 2, we need to configure environment :: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of: :: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0) :: :: 32 bit builds do not require specific environment configurations. :: :: Note: this script needs to be run with the /E:ON and /V:ON flags for the :: cmd interpreter, at least for (SDK v7.0) :: :: More details at: :: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows :: http://stackoverflow.com/a/13751649/163740 :: :: Author: Olivier Grisel :: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ @ECHO OFF SET COMMAND_TO_RUN=%* SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows SET MAJOR_PYTHON_VERSION="%PYTHON_VERSION:~0,1%" IF %MAJOR_PYTHON_VERSION% == "2" ( SET WINDOWS_SDK_VERSION="v7.0" ) ELSE IF %MAJOR_PYTHON_VERSION% == "3" ( SET WINDOWS_SDK_VERSION="v7.1" ) ELSE ( ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%" EXIT 1 ) IF "%PYTHON_ARCH%"=="64" ( ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture SET DISTUTILS_USE_SDK=1 SET MSSdk=1 "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION% "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release ECHO Executing: %COMMAND_TO_RUN% call %COMMAND_TO_RUN% || EXIT 1 ) ELSE ( ECHO Using default MSVC build environment for 32 bit architecture ECHO Executing: %COMMAND_TO_RUN% call %COMMAND_TO_RUN% || EXIT 1 ) wcsaxes-0.6/astropy_helpers/continuous-integration/travis/0000755000077000000240000000000012553237435024245 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/continuous-integration/travis/install_conda_linux.sh0000755000077000000240000000032412532571254030631 0ustar tomstaff00000000000000#!/bin/bash wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh chmod +x miniconda.sh ./miniconda.sh -b export PATH=/home/travis/miniconda/bin:$PATH conda update --yes conda wcsaxes-0.6/astropy_helpers/continuous-integration/travis/install_conda_osx.sh0000755000077000000240000000032512532571254030304 0ustar tomstaff00000000000000#!/bin/bash wget http://repo.continuum.io/miniconda/Miniconda-3.7.3-MacOSX-x86_64.sh -O miniconda.sh chmod +x miniconda.sh ./miniconda.sh -b export PATH=/Users/travis/miniconda/bin:$PATH conda update --yes conda wcsaxes-0.6/astropy_helpers/continuous-integration/travis/install_graphviz_linux.sh0000755000077000000240000000007712532571254031404 0ustar tomstaff00000000000000#!/bin/bash sudo apt-get update sudo apt-get install graphviz wcsaxes-0.6/astropy_helpers/continuous-integration/travis/install_graphviz_osx.sh0000755000077000000240000000005712532571254031054 0ustar tomstaff00000000000000#!/bin/bash brew update brew install graphviz wcsaxes-0.6/astropy_helpers/CONTRIBUTING.md0000644000077000000240000000216512414703152020431 0ustar tomstaff00000000000000Contributing to astropy-helpers =============================== The guidelines for contributing to ``astropy-helpers`` are generally the same as the [contributing guidelines for the astropy core package](http://github.com/astropy/astropy/blob/master/CONTRIBUTING.md). Basically, report relevant issues in the ``astropy-helpers`` issue tracker, and we welcome pull requests that broadly follow the [Astropy coding guidelines](http://docs.astropy.org/en/latest/development/codeguide.html). The key subtlety lies in understanding the relationship between ``astropy`` and ``astropy-helpers``. This package contains the build, installation, and documentation tools used by astropy. It also includes support for the ``setup.py test`` command, though Astropy is still required for this to function (it does not currently include the full Astropy test runner). So issues or improvements to that functionality should be addressed in this package. Any other aspect of the [astropy core package](http://github.com/astropy/astropy) (or any other package that uses ``astropy-helpers``) should be addressed in the github repository for that package. wcsaxes-0.6/astropy_helpers/ez_setup.py0000644000077000000240000002757312346274067020436 0ustar tomstaff00000000000000#!python """Bootstrap setuptools installation If you want to use setuptools in your package's setup.py, just include this file in the same directory with it, and add this to the top of your setup.py:: from ez_setup import use_setuptools use_setuptools() If you want to require a specific version of setuptools, set a download mirror, or use an alternate download directory, you can do so by supplying the appropriate options to ``use_setuptools()``. This file can also be run as a script to install or upgrade setuptools. """ import os import shutil import sys import tempfile import tarfile import optparse import subprocess import platform from distutils import log try: from site import USER_SITE except ImportError: USER_SITE = None DEFAULT_VERSION = "1.4.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): args = (sys.executable,) + args return subprocess.call(args) == 0 def _check_call_py24(cmd, *args, **kwargs): res = subprocess.call(cmd, *args, **kwargs) class CalledProcessError(Exception): pass if not res == 0: msg = "Command '%s' return non-zero exit status %d" % (cmd, res) raise CalledProcessError(msg) vars(subprocess).setdefault('check_call', _check_call_py24) def _install(tarball, install_args=()): # extracting the tarball tmpdir = tempfile.mkdtemp() log.warn('Extracting in %s', tmpdir) old_wd = os.getcwd() try: os.chdir(tmpdir) tar = tarfile.open(tarball) _extractall(tar) tar.close() # going in the directory subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) os.chdir(subdir) log.warn('Now working in %s', subdir) # installing log.warn('Installing Setuptools') if not _python_cmd('setup.py', 'install', *install_args): log.warn('Something went wrong during the installation.') log.warn('See the error message above.') # exitcode will be 2 return 2 finally: os.chdir(old_wd) shutil.rmtree(tmpdir) def _build_egg(egg, tarball, to_dir): # extracting the tarball tmpdir = tempfile.mkdtemp() log.warn('Extracting in %s', tmpdir) old_wd = os.getcwd() try: os.chdir(tmpdir) tar = tarfile.open(tarball) _extractall(tar) tar.close() # going in the directory subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) os.chdir(subdir) log.warn('Now working in %s', subdir) # building an egg log.warn('Building a Setuptools egg in %s', to_dir) _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) finally: os.chdir(old_wd) shutil.rmtree(tmpdir) # returning the result log.warn(egg) if not os.path.exists(egg): raise IOError('Could not build the egg.') def _do_download(version, download_base, to_dir, download_delay): egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg' % (version, sys.version_info[0], sys.version_info[1])) if not os.path.exists(egg): tarball = download_setuptools(version, download_base, to_dir, download_delay) _build_egg(egg, tarball, to_dir) sys.path.insert(0, egg) # Remove previously-imported pkg_resources if present (see # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). if 'pkg_resources' in sys.modules: del sys.modules['pkg_resources'] import setuptools setuptools.bootstrap_install_from = egg def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, download_delay=15): # making sure we use the absolute path to_dir = os.path.abspath(to_dir) was_imported = 'pkg_resources' in sys.modules or \ 'setuptools' in sys.modules try: import pkg_resources except ImportError: return _do_download(version, download_base, to_dir, download_delay) try: pkg_resources.require("setuptools>=" + version) return except pkg_resources.VersionConflict: e = sys.exc_info()[1] if was_imported: sys.stderr.write( "The required version of setuptools (>=%s) is not available,\n" "and can't be installed while this script is running. Please\n" "install a more recent version first, using\n" "'easy_install -U setuptools'." "\n\n(Currently using %r)\n" % (version, e.args[0])) sys.exit(2) else: del pkg_resources, sys.modules['pkg_resources'] # reload ok return _do_download(version, download_base, to_dir, download_delay) except pkg_resources.DistributionNotFound: return _do_download(version, download_base, to_dir, download_delay) def _clean_check(cmd, target): """ Run the command to download target. If the command fails, clean up before re-raising the error. """ try: subprocess.check_call(cmd) except subprocess.CalledProcessError: if os.access(target, os.F_OK): os.unlink(target) raise def download_file_powershell(url, target): """ Download the file at url to target using Powershell (which will validate trust). Raise an exception if the command cannot complete. """ target = os.path.abspath(target) cmd = [ 'powershell', '-Command', "(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)" % vars(), ] _clean_check(cmd, target) def has_powershell(): if platform.system() != 'Windows': return False cmd = ['powershell', '-Command', 'echo test'] devnull = open(os.path.devnull, 'wb') try: try: subprocess.check_call(cmd, stdout=devnull, stderr=devnull) except: return False finally: devnull.close() return True download_file_powershell.viable = has_powershell def download_file_curl(url, target): cmd = ['curl', url, '--silent', '--output', target] _clean_check(cmd, target) def has_curl(): cmd = ['curl', '--version'] devnull = open(os.path.devnull, 'wb') try: try: subprocess.check_call(cmd, stdout=devnull, stderr=devnull) except: return False finally: devnull.close() return True download_file_curl.viable = has_curl def download_file_wget(url, target): cmd = ['wget', url, '--quiet', '--output-document', target] _clean_check(cmd, target) def has_wget(): cmd = ['wget', '--version'] devnull = open(os.path.devnull, 'wb') try: try: subprocess.check_call(cmd, stdout=devnull, stderr=devnull) except: return False finally: devnull.close() return True download_file_wget.viable = has_wget def download_file_insecure(url, target): """ Use Python to download the file, even though it cannot authenticate the connection. """ try: from urllib.request import urlopen except ImportError: from urllib2 import urlopen src = dst = None try: src = urlopen(url) # Read/write all in one block, so we don't create a corrupt file # if the download is interrupted. data = src.read() dst = open(target, "wb") dst.write(data) finally: if src: src.close() if dst: dst.close() download_file_insecure.viable = lambda: True def get_best_downloader(): downloaders = [ download_file_powershell, download_file_curl, download_file_wget, download_file_insecure, ] for dl in downloaders: if dl.viable(): return dl def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader): """Download setuptools from a specified location and return its filename `version` should be a valid setuptools version number that is available as an egg for download under the `download_base` URL (which should end with a '/'). `to_dir` is the directory where the egg will be downloaded. `delay` is the number of seconds to pause before an actual download attempt. ``downloader_factory`` should be a function taking no arguments and returning a function for downloading a URL to a target. """ # making sure we use the absolute path to_dir = os.path.abspath(to_dir) tgz_name = "setuptools-%s.tar.gz" % version url = download_base + tgz_name saveto = os.path.join(to_dir, tgz_name) if not os.path.exists(saveto): # Avoid repeated downloads log.warn("Downloading %s", url) downloader = downloader_factory() downloader(url, saveto) return os.path.realpath(saveto) def _extractall(self, path=".", members=None): """Extract all members from the archive to the current working directory and set owner, modification time and permissions on directories afterwards. `path' specifies a different directory to extract to. `members' is optional and must be a subset of the list returned by getmembers(). """ import copy import operator from tarfile import ExtractError directories = [] if members is None: members = self for tarinfo in members: if tarinfo.isdir(): # Extract directories with a safe mode. directories.append(tarinfo) tarinfo = copy.copy(tarinfo) tarinfo.mode = 448 # decimal for oct 0700 self.extract(tarinfo, path) # Reverse sort directories. if sys.version_info < (2, 4): def sorter(dir1, dir2): return cmp(dir1.name, dir2.name) directories.sort(sorter) directories.reverse() else: directories.sort(key=operator.attrgetter('name'), reverse=True) # Set correct owner, mtime and filemode on directories. for tarinfo in directories: dirpath = os.path.join(path, tarinfo.name) try: self.chown(tarinfo, dirpath) self.utime(tarinfo, dirpath) self.chmod(tarinfo, dirpath) except ExtractError: e = sys.exc_info()[1] if self.errorlevel > 1: raise else: self._dbg(1, "tarfile: %s" % e) def _build_install_args(options): """ Build the arguments to 'python setup.py install' on the setuptools package """ install_args = [] if options.user_install: if sys.version_info < (2, 6): log.warn("--user requires Python 2.6 or later") raise SystemExit(1) install_args.append('--user') return install_args def _parse_args(): """ Parse the command line for options """ parser = optparse.OptionParser() parser.add_option( '--user', dest='user_install', action='store_true', default=False, help='install in user site package (requires Python 2.6 or later)') parser.add_option( '--download-base', dest='download_base', metavar="URL", default=DEFAULT_URL, help='alternative URL from where to download the setuptools package') parser.add_option( '--insecure', dest='downloader_factory', action='store_const', const=lambda: download_file_insecure, default=get_best_downloader, help='Use internal, non-validating downloader' ) options, args = parser.parse_args() # positional arguments are ignored return options def main(version=DEFAULT_VERSION): """Install or upgrade setuptools and EasyInstall""" options = _parse_args() tarball = download_setuptools(download_base=options.download_base, downloader_factory=options.downloader_factory) return _install(tarball, _build_install_args(options)) if __name__ == '__main__': sys.exit(main()) wcsaxes-0.6/astropy_helpers/LICENSE.rst0000644000077000000240000000272312414703152020014 0ustar tomstaff00000000000000Copyright (c) 2014, Astropy Developers All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Astropy Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. wcsaxes-0.6/astropy_helpers/licenses/0000755000077000000240000000000012553237435020013 5ustar tomstaff00000000000000wcsaxes-0.6/astropy_helpers/licenses/LICENSE_COPYBUTTON.rst0000644000077000000240000000471112346274067023422 0ustar tomstaff00000000000000Copyright 2014 Python Software Foundation License: PSF PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 -------------------------------------------- . 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated documentation. . 2. Subject to the terms and conditions of this License Agreement, PSF 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 Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee. . 3. In the event Licensee prepares a derivative work that is based on or incorporates Python 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 Python. . 4. PSF is making Python available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. . 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, 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 PSF and Licensee. This License Agreement does not grant permission to use PSF 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 Python, Licensee agrees to be bound by the terms and conditions of this License Agreement. wcsaxes-0.6/astropy_helpers/licenses/LICENSE_NUMPYDOC.rst0000644000077000000240000001350712346274067023155 0ustar tomstaff00000000000000------------------------------------------------------------------------------- The files - numpydoc.py - docscrape.py - docscrape_sphinx.py - phantom_import.py have the following license: Copyright (C) 2008 Stefan van der Walt , Pauli Virtanen 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. ------------------------------------------------------------------------------- The files - compiler_unparse.py - comment_eater.py - traitsdoc.py have the following license: This software is OSI Certified Open Source Software. OSI Certified is a certification mark of the Open Source Initiative. Copyright (c) 2006, Enthought, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Enthought, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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. ------------------------------------------------------------------------------- The file - plot_directive.py originates from 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. wcsaxes-0.6/astropy_helpers/MANIFEST.in0000644000077000000240000000024312346274067017745 0ustar tomstaff00000000000000include README.rst include CHANGES.rst include LICENSE.rst include ez_setup.py include ah_bootstrap.py exclude *.pyc *.o prune build prune astropy_helpers/tests wcsaxes-0.6/astropy_helpers/README.rst0000644000077000000240000000323112532571254017671 0ustar tomstaff00000000000000astropy-helpers =============== This project provides a Python package, ``astropy_helpers``, which includes many build, installation, and documentation-related tools used by the Astropy project, but packaged separately for use by other projects that wish to leverage this work. The motivation behind this package and details of its implementation are in the accepted `Astropy Proposal for Enhancement (APE) 4 `_. ``astropy_helpers`` includes a special "bootstrap" module called ``ah_bootstrap.py`` which is intended to be used by a project's setup.py in order to ensure that the ``astropy_helpers`` package is available for build/installation. This is similar to the ``ez_setup.py`` module that is shipped with some projects to bootstrap `setuptools `_. As described in APE4, the version numbers for ``astropy_helpers`` follow the corresponding major/minor version of the `astropy core package `_, but with an independent sequence of micro (bugfix) version numbers. Hence, the initial release is 0.4, in parallel with Astropy v0.4, which will be the first version of Astropy to use ``astropy-helpers``. For examples of how to implement ``astropy-helpers`` in a project, see the ``setup.py`` and ``setup.cfg`` files of the `Affiliated package template `_. .. image:: https://travis-ci.org/astropy/astropy-helpers.png :target: https://travis-ci.org/astropy/astropy-helpers .. image:: https://coveralls.io/repos/astropy/astropy-helpers/badge.png :target: https://coveralls.io/r/astropy/astropy-helpers wcsaxes-0.6/astropy_helpers/setup.cfg0000644000077000000240000000014612346274067020032 0ustar tomstaff00000000000000[pytest] norecursedirs = .tox astropy_helpers/tests/package_template python_functions = test_ wcsaxes-0.6/astropy_helpers/setup.py0000755000077000000240000000402312532571254017717 0ustar tomstaff00000000000000#!/usr/bin/env python # Licensed under a 3-clause BSD style license - see LICENSE.rst import ah_bootstrap import pkg_resources from setuptools import setup from astropy_helpers.setup_helpers import register_commands, get_package_info from astropy_helpers.version_helpers import generate_version_py NAME = 'astropy_helpers' VERSION = '1.0.2' RELEASE = 'dev' not in VERSION DOWNLOAD_BASE_URL = 'http://pypi.python.org/packages/source/a/astropy-helpers' generate_version_py(NAME, VERSION, RELEASE, False, uses_git=not RELEASE) # Use the updated version including the git rev count from astropy_helpers.version import version as VERSION cmdclass = register_commands(NAME, VERSION, RELEASE) # This package actually doesn't use the Astropy test command del cmdclass['test'] setup( name=pkg_resources.safe_name(NAME), # astropy_helpers -> astropy-helpers version=VERSION, description='Utilities for building and installing Astropy, Astropy ' 'affiliated packages, and their respective documentation.', author='The Astropy Developers', author_email='astropy.team@gmail.com', license='BSD', url='http://astropy.org', long_description=open('README.rst').read(), download_url='{0}/astropy-helpers-{1}.tar.gz'.format(DOWNLOAD_BASE_URL, VERSION), classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'Framework :: Setuptools Plugin', 'Framework :: Sphinx :: Extension', 'Framework :: Sphinx :: Theme', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Topic :: Software Development :: Build Tools', 'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: System :: Archiving :: Packaging' ], cmdclass=cmdclass, zip_safe=False, **get_package_info(exclude=['astropy_helpers.tests']) ) wcsaxes-0.6/astropy_helpers/tox.ini0000644000077000000240000000045012532571254017515 0ustar tomstaff00000000000000[tox] envlist = py26,py27,py32,py33,py34 [testenv] deps = pytest numpy Cython Sphinx==1.2.3 # Note: Sphinx is required to run the sphinx.ext tests commands = py.test {posargs} sitepackages = False [testenv:py32] deps = pygments<=1.9 Jinja2<2.7 {[testenv]deps} wcsaxes-0.6/CHANGES.md0000644000077000000240000000564012553237416014361 0ustar tomstaff000000000000000.6 (2015-07-20) ---------------- - Fix a bug that caused ticks and labels to be incorrect if a WCS object was used that was not recognized as celestial by WCSlib but had angular units for the axes, when setting the coord_type to longitude/latitude. [#171] - Switch to using pytest-mpl for image testing. [#168] - Show users how to invert axes easily. [#158] 0.4 (2015-06-07) ---------------- - Astropy frame instances to now be passed to ``get_transform`` and ``get_coords_overlay``. [#149] - Fixed bug that caused plotting to crash if there were no ticks on an axis. - Fix compatibility with different versions of Matplotlib. [#153] - Fix bug when plotting overlays on images with 3+ WCS dimensions. - Fixed bug that occurred when hovering over an interactive plot before the axes were drawn the first time. [#152] - Fix bug that occurred in some cases where Matplotlib would try and plot a grid as soon as the axes were initialized. - Fix bug with plotting RGB images. [#15] - Improved error message when passing non-existent frame to ``get_overlay_coords``. [#154] 0.3 (2014-12-07) ---------------- - Fixed a bug that caused axis labels to be incorrectly placed when hiding tick labels using ``set_visible(False)``. [#111] - Fixed a bug that caused tick labels to not always appear. [#110] - Fixed a bug that caused the clip path for images to not be updated when making subsequent changes after drawing the figure. [#117] - Fixed a bug that caused the clip path for images to not be updated after calling reset_wcs. [#120] - Added ``CoordinateHelper.get_axislabel()`` method. [#122] - Improve handling of get/set_xlabel/ylabel. [#94, #126] - Added new feature to display world coordinates in interactive mode. [#112] - When converting celestial coordinates, don't compute a new representation if the old one was already spherical or unit spherical. [#125] - WCS instances from ``wcsaxes.wcs_wrapper`` can now be used to instantiate Matplotlib plots with the ``projection=`` keyword. [#136] - Example datasets are now downloaded from http://data.astropy.org. [#144] - Registering new frame identifiers is now done with the same API as in astropy.wcs.utils, and is handled in wcsaxes.wcs_utils. [#145] 0.2 (2014-08-11) ---------------- ### New features - Added option to specify whether overlapping ticks should be displayed. [#85] - Added minor ticks. [#89] - Added option to set frame linewidth and color. [#88] - Added option to set separators for angle coordinates. [#90] - Added Python ``%`` format to set format for scalar coordinates. [#98] ### Improvements - Improved performance of grid drawing. [#100] - Code is now natively compatible with Python 3. ### Bug Fixes - Fix axis labels overlapping with ticks. [#96] - Fix drawing grids multiple times for multi-dimensional data. [#99] - Fixed bug that occurred when providing a custom ``transData``. 0.1 (2014-07-04) ---------------- - Initial Release. wcsaxes-0.6/docs/0000755000077000000240000000000012553237435013713 5ustar tomstaff00000000000000wcsaxes-0.6/docs/_templates/0000755000077000000240000000000012553237435016050 5ustar tomstaff00000000000000wcsaxes-0.6/docs/_templates/autosummary/0000755000077000000240000000000012553237435020436 5ustar tomstaff00000000000000wcsaxes-0.6/docs/_templates/autosummary/base.rst0000644000077000000240000000037212436367710022104 0ustar tomstaff00000000000000{% extends "autosummary_core/base.rst" %} {# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #}wcsaxes-0.6/docs/_templates/autosummary/class.rst0000644000077000000240000000037312436367710022300 0ustar tomstaff00000000000000{% extends "autosummary_core/class.rst" %} {# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #}wcsaxes-0.6/docs/_templates/autosummary/module.rst0000644000077000000240000000037412436367710022461 0ustar tomstaff00000000000000{% extends "autosummary_core/module.rst" %} {# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #}wcsaxes-0.6/docs/api.rst0000644000077000000240000000021412436367710015213 0ustar tomstaff00000000000000Reference/API ============= .. automodapi:: wcsaxes :no-inheritance-diagram: .. automodapi:: wcsaxes.frame :no-inheritance-diagram: wcsaxes-0.6/docs/conf.py0000644000077000000240000001630712535045247015217 0ustar tomstaff00000000000000# -*- coding: utf-8 -*- # Licensed under a 3-clause BSD style license - see LICENSE.rst # # Astropy documentation build configuration file. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this file. # # All configuration values have a default. Some values are defined in # the global Astropy configuration which is loaded here before anything else. # See astropy.sphinx.conf for which values are set there. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('..')) # IMPORTANT: the above commented section was generated by sphinx-quickstart, but # is *NOT* appropriate for astropy or Astropy affiliated packages. It is left # commented out with this explanation to make it clear why this should not be # done. If the sys.path entry above is added, when the astropy.sphinx.conf # import occurs, it will import the *source* version of astropy instead of the # version installed (if invoked as "make html" or directly with sphinx), or the # version in the build directory (if "python setup.py build_sphinx" is used). # Thus, any C-extensions that are needed to build the documentation will *not* # be accessible, and the documentation will not build correctly. import datetime import os import sys try: import astropy_helpers except ImportError: # Building from inside the docs/ directory? if os.path.basename(os.getcwd()) == 'docs': a_h_path = os.path.abspath(os.path.join('..', 'astropy_helpers')) if os.path.isdir(a_h_path): sys.path.insert(1, a_h_path) # Load all of the global Astropy configuration from astropy_helpers.sphinx.conf import * # Get configuration information from setup.cfg from distutils import config conf = config.ConfigParser() conf.read([os.path.join(os.path.dirname(__file__), '..', 'setup.cfg')]) setup_cfg = dict(conf.items('metadata')) # -- General configuration ---------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.1' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns.append('_templates') # This is added to the end of RST files - a good place to put substitutions to # be used globally. rst_epilog += """ """ # -- Project information ------------------------------------------------------ # This does not *have* to match the package name, but typically does project = setup_cfg['package_name'] author = setup_cfg['author'] copyright = '{0}, {1}'.format( datetime.datetime.now().year, setup_cfg['author']) # 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. __import__(setup_cfg['package_name']) package = sys.modules[setup_cfg['package_name']] # The short X.Y version. version = package.__version__.split('-', 1)[0] # The full version, including alpha/beta/rc tags. release = package.__version__ # -- Options for HTML output --------------------------------------------------- # A NOTE ON HTML THEMES # The global astropy configuration uses a custom theme, 'bootstrap-astropy', # which is installed along with astropy. A different theme can be used or # the options for this theme can be modified by overriding some of the # variables set in the global configuration. The variables set in the # global configuration are listed below, commented out. # Add any paths that contain custom themes here, relative to this directory. # To use a different custom theme, add the directory containing the theme. html_theme_path = [] # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. To override the custom theme, set this to the # name of a builtin theme or the name of a custom theme in html_theme_path. html_theme = 'default' # Custom sidebar templates, maps document names to template names. html_sidebars = {} # 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 = '' # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". html_title = '{0} v{1}'.format(project, release) # Output file base name for HTML help builder. htmlhelp_basename = project + 'doc' # -- Options for LaTeX output -------------------------------------------------- # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [('index', project + '.tex', project + u' Documentation', author, 'manual')] # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [('index', project.lower(), project + u' Documentation', [author], 1)] ## -- Options for the edit_on_github extension ---------------------------------------- if eval(setup_cfg.get('edit_on_github')): extensions += ['astropy_helpers.sphinx.ext.edit_on_github'] versionmod = __import__(setup_cfg['package_name'] + '.version') edit_on_github_project = setup_cfg['github_project'] if versionmod.version.release: edit_on_github_branch = "v" + versionmod.version.version else: edit_on_github_branch = "master" edit_on_github_source_root = "" edit_on_github_doc_root = "docs" # Make sure we have a recent version of matplotlib for the plot directive from distutils.version import LooseVersion import matplotlib if LooseVersion(matplotlib.__version__) < LooseVersion('1.4'): raise ValueError("matplotlib 1.4+ is required to build the docs") plot_rcparams = {'figure.figsize': (6,6), 'savefig.facecolor':'none'} plot_apply_rcparams = True plot_template = """ {{ source_code }} {{ only_html }} {% for img in images %} .. figure:: {{ build_dir }}/{{ img.basename }}.png {%- for option in options %} {{ option }} {% endfor %} {{ caption }} {% endfor %} {{ only_latex }} {% for img in images %} .. image:: {{ build_dir }}/{{ img.basename }}.pdf {% endfor %} """ # on_rtd is whether we are on readthedocs.org import os on_rtd = os.environ.get('READTHEDOCS', None) == 'True' if not on_rtd: # only import and set the theme if we're building docs locally import sphinx_rtd_theme html_theme = 'sphinx_rtd_theme' html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # otherwise, readthedocs.org uses their theme by default, so no need to specify it # Enable nitpicky mode - which ensures that all references in the docs # resolve. nitpicky = True nitpick_ignore = [('py:class', 'matplotlib.axes._subplots.WCSAxesSubplot')] wcsaxes-0.6/docs/controlling_axes.rst0000644000077000000240000000255512553175753020032 0ustar tomstaff00000000000000================== Controlling Axes ================== Changing Axis Units =================== WCSAxes also allows users to change the units of the axes of an image. In the example in :doc:`slicing_datacubes`, the x axis represents velocity in m/s. We can change the unit to an equivalent one by: .. plot:: :context: reset :nofigs: from wcsaxes import datasets, WCS hdu = datasets.fetch_l1448_co_hdu() wcs = WCS(hdu.header) import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=wcs, slices=(50, 'y', 'x')) ax.imshow(hdu.data[:, :, 50].transpose(), cmap=plt.cm.gist_heat) .. plot:: :context: :include-source: :align: center import astropy.units as u ax.coords[2].set_major_formatter('x.x') # Otherwise values round to the nearest whole number ax.coords[2].set_format_unit(u.km / u.s) This feature is only for non-angular coordinate axes. To change the format of angles, refer to :ref:`tick_label_format`. Changing Axis Directions ======================== Sometimes astronomy FITS files don't follow the convention of having the longitude increase to the left, so we want to flip an axis so that it goes in the opposite direction. To do this on our example image: .. plot:: :context: :include-source: :align: center ax.invert_xaxis() wcsaxes-0.6/docs/custom_frames.rst0000644000077000000240000000574712436367710017331 0ustar tomstaff00000000000000==================== Using a custom frame ==================== By default, `~wcsaxes.WCSAxes` will make use of a rectangular frame for a plot, but this can be changed to provide any custom frame. The following example shows how to use the built-in :class:`~wcsaxes.frame.EllipticalFrame` class, which is an ellipse which extends to the same limits as the built-in rectangular frame: .. plot:: :context: reset :include-source: :align: center from wcsaxes import datasets, WCS from wcsaxes.frame import EllipticalFrame hdu = datasets.fetch_msx_hdu() wcs = WCS(hdu.header) import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_axes([0.15, 0.15, 0.7, 0.7], projection=wcs, frame_class=EllipticalFrame) ax.coords.grid(color='white') im = ax.imshow(hdu.data, vmin=-2.e-5, vmax=2.e-4, cmap=plt.cm.gist_heat, origin='lower') # Clip the image to the frame im.set_clip_path(ax.coords.frame.patch) However, you can also write your own frame class. The idea is to set up any number of connecting spines that define the frame. You can define a frame as a spine, but if you define it as multiple spines you will be able to control on which spine the tick labels and ticks should appear. The following example shows how you could for example define a hexagonal frame: .. plot:: :context: reset :include-source: :nofigs: from wcsaxes.frame import BaseFrame class HexagonalFrame(BaseFrame): spine_names = 'abcdef' def update_spines(self): xmin, xmax = self.parent_axes.get_xlim() ymin, ymax = self.parent_axes.get_ylim() ymid = 0.5 * (ymin + ymax) xmid1 = (xmin + xmax) / 4. xmid2 = (xmin + xmax) * 3. / 4. self['a'].data = np.array(([xmid1, ymin], [xmid2, ymin])) self['b'].data = np.array(([xmid2, ymin], [xmax, ymid])) self['c'].data = np.array(([xmax, ymid], [xmid2, ymax])) self['d'].data = np.array(([xmid2, ymax], [xmid1, ymax])) self['e'].data = np.array(([xmid1, ymax], [xmin, ymid])) self['f'].data = np.array(([xmin, ymid], [xmid1, ymin])) which we can then use: .. plot:: :context: :include-source: :align: center from wcsaxes import datasets, WCS hdu = datasets.fetch_msx_hdu() wcs = WCS(hdu.header) import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_axes([0.15, 0.15, 0.7, 0.7], projection=wcs, frame_class=HexagonalFrame) ax.coords.grid(color='white') im = ax.imshow(hdu.data, vmin=-2.e-5, vmax=2.e-4, cmap=plt.cm.gist_heat, origin='lower') # Clip the image to the frame im.set_clip_path(ax.coords.frame.patch) Frame properties ================ The color and linewidth of the frame can also be set by .. plot:: :context: :include-source: :align: center ax.coords.frame.set_color('red') ax.coords.frame.set_linewidth(2) wcsaxes-0.6/docs/getting_started.rst0000644000077000000240000000536612533356400017636 0ustar tomstaff00000000000000=============== Getting started =============== Initialization ============== To make a plot using `~wcsaxes.WCSAxes`, we first read in the data using `astropy.io.fits `_ and parse the WCS information. In this example, we will use a FITS file from the ``wcsaxes.datasets`` module: .. plot:: :context: reset :nofigs: :include-source: :align: center from wcsaxes import datasets, WCS hdu = datasets.fetch_msx_hdu() wcs = WCS(hdu.header) If you have the original FITS file, this is equivalent to doing:: from astropy.io import fits hdu = fits.open('msx.fits')[0] wcs = WCS(hdu.header) We then create a figure using Matplotlib and create the axes using the :class:`~astropy.wcs.WCS` object created above: .. plot:: :context: :include-source: :align: center import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_axes([0.15, 0.1, 0.8, 0.8], projection=wcs) .. note:: If you are using Matplotlib <=1.1 then the ``projection=`` functionality does not exist and one should use the alternative shown in :ref:`initialize_alternative` The ``ax`` object created is an instance of the :class:`~wcsaxes.WCSAxes` class. For more information about the different ways of initializing axes, see :doc:`initializing_axes`. The field of view shown is, as for standard matplotlib axes, 0 to 1 in both directions, in pixel coordinates. The :meth:`~matplotlib.axes.Axes.set_xlim` and :meth:`~matplotlib.axes.Axes.set_ylim` methods can be used to re-set the pixel coordinates. For example, we can set the limits to the edge of the FITS image in pixel coordinates: .. plot:: :context: :include-source: :align: center ax.set_xlim(-0.5, hdu.data.shape[1] - 0.5) ax.set_ylim(-0.5, hdu.data.shape[0] - 0.5) If no WCS transformation is specified, the transformation will default to identity, meaning that the world coordinates will match the pixel coordinates. Plotting images and contours ============================ Plotting images as bitmaps or contours should be done via the usual matplotlib methods such as :meth:`~matplotlib.axes.Axes.imshow` or :meth:`~matplotlib.axes.Axes.contour`. For example, continuing from the example in `Initialization`_, you can do: .. plot:: :context: :include-source: :align: center ax.imshow(hdu.data, vmin=-2.e-5, vmax=2.e-4, cmap=plt.cm.gist_heat, origin='lower') and we can also add contours corresponding to the same image using: .. plot:: :context: :include-source: :align: center import numpy as np ax.contour(hdu.data, levels=np.logspace(-4.7, -3., 10), colors='white', alpha=0.5) To show contours for an image in a different coordinate system, see :doc:`overlays`. wcsaxes-0.6/docs/index.rst0000644000077000000240000000137512553175753015566 0ustar tomstaff00000000000000.. WCSAxes documentation master file, created by sphinx-quickstart on Tue Feb 25 20:57:56 2014. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Welcome to WCSAxes's documentation! =================================== WCSAxes is a framework for making plots of Astronomical data in Matplotlib. It is affiliated with the `Astropy `__ project and is intended for inclusion in the Astropy package once stable. .. toctree:: :maxdepth: 1 installation.rst getting_started.rst ticks_labels_grid.rst overlays.rst overlaying_coordinate_systems.rst slicing_datacubes.rst initializing_axes.rst controlling_axes.rst custom_frames.rst api.rst wcsaxes-0.6/docs/initializing_axes.rst0000644000077000000240000000417312533356400020154 0ustar tomstaff00000000000000================= Initializing axes ================= As in Matplotlib, there are several ways you can initialize the :class:`~wcsaxes.WCSAxes`. As shown in the rest of the documentation, the simplest way is to make use of the :class:`wcsaxes.WCS` class (instead of :class:`astropy.wcs.WCS`) and pass this to the :meth:`~matplotlib.figure.Figure.add_subplot` method:: from wcsaxes import WCS import matplotlib.pyplot as plt wcs = WCS(...) fig = plt.figure() ax = fig.add_subplot(1, 1, 1, projection=wcs) ax.imshow(...) If you normally make plots directly with pyplot directly instead of creating axes and figure instances, you can do:: plt.subplot(1, 1, 1, projection=wcs) plt.imshow(...) Note that this also works with :meth:`~matplotlib.figure.Figure.add_axes` and :func:`~matplotlib.pyplot.axes`, e.g.:: ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=wcs) or:: plt.axes([0.1, 0.1, 0.8, 0.8], projection=wcs) In the above examples, and in the rest of the documentation, we use the :class:`wcsaxes.WCS` class, which is almost identical to :class:`astropy.wcs.WCS` but includes a couple of additional methods that are needed to allow us to use the matplotlib ``projection=`` option. Note that any additional arguments passed to :meth:`~matplotlib.figure.Figure.add_subplot`, :meth:`~matplotlib.figure.Figure.add_axes`, :func:`~matplotlib.pyplot.subplot`, or :func:`~matplotlib.pyplot.axes`, such as ``slices`` or ``frame_class``, will be passed on to the :class:`~wcsaxes.WCSAxes` class. .. _initialize_alternative: Alternative =========== As an alternative to the above methods of initializing :class:`~wcsaxes.WCSAxes`, you can also instantiate :class:`~wcsaxes.WCSAxes` directly and add it to the figure:: from astropy.wcs import WCS from wcsaxes import WCSAxes import matplotlib.pyplot as plt wcs = WCS(...) fig = plt.figure() ax = WCSAxes(fig, [0.1, 0.1, 0.8, 0.8], wcs=wcs) fig.add_axes(ax) # note that the axes have to be explicitly added to the figure Note that in this example, we can use :class:`astropy.wcs.WCS` (but :class:`wcsaxes.WCS` will also work). wcsaxes-0.6/docs/installation.rst0000644000077000000240000000207112436367710017146 0ustar tomstaff00000000000000============ Installation ============ Requirements ============ WCSAxes requires Python 2.6, 2.7, 3.2, 3.3, or 3.4 and the following Python packages to be installed: * `Numpy `_ * `Matplotlib `_ * `Astropy `__ 0.3 or later First-time Python users may want to consider an all-in-one Python installation package, such as the `Anaconda Python Distribution `_ which provides all of the above dependencies. Installation ============ You can install the stable version of WCSAxes with:: pip install wcsaxes Alternatively, you can install the latest developer version of WCSAxes by cloning the git repository:: git clone http://github.com/astrofrog/wcsaxes then installing the package with:: cd wcsaxes python setup.py install Testing ======= If you want to check that all the tests are running correctly with your Python configuration, start up python, and type:: import wcsaxes wcsaxes.test() If there are no errors, you are good to go! wcsaxes-0.6/docs/make.bat0000644000077000000240000001064112436367710015322 0ustar tomstaff00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 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. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages 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 ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Astropy.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Astropy.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end wcsaxes-0.6/docs/Makefile0000644000077000000240000001515612436367710015363 0ustar tomstaff00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/WCSAxes.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/WCSAxes.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/WCSAxes" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/WCSAxes" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." latexpdfja: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." wcsaxes-0.6/docs/overlaying_coordinate_systems.rst0000644000077000000240000000333012436367710022621 0ustar tomstaff00000000000000============================= Overlaying coordinate systems ============================= For the example in the following page we start from the example introduced in :doc:`getting_started`. .. plot:: :context: reset :nofigs: from wcsaxes import datasets, WCS hdu = datasets.fetch_msx_hdu() wcs = WCS(hdu.header) import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_axes([0.25, 0.25, 0.6, 0.6], projection=wcs) ax.imshow(hdu.data, vmin=-2.e-5, vmax=2.e-4, cmap=plt.cm.gist_heat, origin='lower') The coordinates shown by default in a plot will be those derived from the WCS or transformation passed to the `wcsaxes.WCSAxes` class. However, it is possible to overlay different coordinate systems using the :meth:`wcsaxes.WCSAxes.get_coords_overlay` method: .. plot:: :context: :include-source: :align: center overlay = ax.get_coords_overlay('fk5') The object returned is a :class:`~wcsaxes.coordinates_map.CoordinatesMap`, the same type of object as ``ax.coord``. It can therefore be used in the same way as ``ax.coord`` to set the ticks, tick labels, and axis labels properties: .. plot:: :context: :include-source: :align: center ax.coords['glon'].set_ticks(color='white') ax.coords['glat'].set_ticks(color='white') ax.coords['glon'].set_axislabel('Galactic Longitude') ax.coords['glat'].set_axislabel('Galactic Latitude') ax.coords.grid(color='yellow', linestyle='solid', alpha=0.5) overlay['ra'].set_ticks(color='white') overlay['dec'].set_ticks(color='white') overlay['ra'].set_axislabel('Right Ascension') overlay['dec'].set_axislabel('Declination') overlay.grid(color='white', linestyle='solid', alpha=0.5) wcsaxes-0.6/docs/overlays.rst0000644000077000000240000001012312436367710016306 0ustar tomstaff00000000000000==================== Overplotting artists ==================== For the example in the following page we start from the example introduced in :doc:`getting_started`. .. plot:: :context: reset :nofigs: from wcsaxes import datasets, WCS hdu = datasets.fetch_msx_hdu() wcs = WCS(hdu.header) import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=wcs) ax.imshow(hdu.data, vmin=-2.e-5, vmax=2.e-4, cmap=plt.cm.gist_heat, origin='lower') Transforms ========== Apart from the handling of the ticks, tick labels, and grid lines, the `wcsaxes.WCSAxes` class behaves like a normal Matplotlib ``Axes`` instance, and methods such as :meth:`~matplotlib.axes.Axes.imshow`, :meth:`~matplotlib.axes.Axes.contour`, :meth:`~matplotlib.axes.Axes.plot`, :meth:`~matplotlib.axes.Axes.scatter`, and so on will work and plot the data in pixel coordinates. However, all such Matplotlib commands allow a ``transform=`` argument to be passed, and the :meth:`~wcsaxes.WCSAxes.get_transform` method can be used to get the appropriate transformation object. The following example shows how to get the transformation object for the FK5 coordinate system:: tr_fk5 = ax.get_transform("fk5") To plot in the FK5 system one would then do:: ax.method(..., transform=tr_fk5) where ``method`` is whatever Matplotlib command you are running. To plot in the default world coordinates system, you can use:: ax.get_transform("world") By specifying a WCS object, you can also define a transformation from the current WCS system to another file's WCS system, allowing e.g. overplotting of contours in a different system:: ax.get_transform() If the world coordinate system of the plot is a celestial coordinate system, the following built-in sky coordinate systems would be available from the ``get_transform`` method: * ``'fk4'``: B1950 FK4 equatorial coordinates * ``'fk5'``: J2000 FK5 equatorial coordinates * ``'icrs'``: ICRS equatorial coordinates * ``'galactic'``: Galactic coordinates It is also possible to directly pass a frame object from :mod:`astropy.coordinates`. Patches/shapes/lines ==================== As mentioned above, matplotlib methods will by default work in pixel coordinates: .. plot:: :context: :include-source: :align: center from matplotlib.patches import Rectangle r = Rectangle((60., 20.), 10., 12., edgecolor='yellow', facecolor='none') ax.add_patch(r) but we can use the :meth:`~wcsaxes.WCSAxes.get_transform` method above to plot for example in FK5 equatorial coordinates: .. plot:: :context: :include-source: :align: center r = Rectangle((266.0, -28.9), 0.3, 0.15, edgecolor='green', facecolor='none', transform=ax.get_transform('fk5')) ax.add_patch(r) Many Matplotlib methods accept the ``transform=`` option, so :meth:`~wcsaxes.WCSAxes.get_transform` can be used in many cases to plot overlays in various coordinate systems. A few examples are shown below. Contours ======== Overplotting contours is also simple using the :meth:`~wcsaxes.WCSAxes.get_transform` method. For contours, :meth:`~wcsaxes.WCSAxes.get_transform` should be given the WCS of the image to plot the contours for: .. plot:: :context: :include-source: :align: center hdu = datasets.fetch_bolocam_hdu() ax.contour(hdu.data, transform=ax.get_transform(WCS(hdu.header)), levels=[1,2,3,4,5,6], colors='white') ax.set_xlim(-0.5, 148.5) ax.set_ylim(-0.5, 148.5) The calls to ``set_xlim`` and ``set_ylim`` are included here as the contours cover a larger region than the image, so we want to make sure we focus just on the image. Scatter plots ============= Since the ``ax.scatter`` Matplotlib routine can take the ``transform`` option, it can also be used to plot objects in various coordinate systems: .. plot:: :context: :include-source: :align: center l = [0.25, 0.20, 0.30, 0.27] b = [0.20, 0.23, 0.27, 0.30] ax.scatter(l, b, transform=ax.get_transform('galactic'), s=100, edgecolor='white', facecolor='yellow', alpha=0.5) wcsaxes-0.6/docs/rtd-pip-requirements0000644000077000000240000000005712535045247017736 0ustar tomstaff00000000000000numpy matplotlib>=1.4 astropy-helpers astropy wcsaxes-0.6/docs/slicing_datacubes.rst0000644000077000000240000000645012535045247020113 0ustar tomstaff00000000000000============================= Slicing Multidimensional Data ============================= WCSAxes can ultimately only plot two-dimensional data. If we have an n-dimensional dataset, we have to select which dimensions to use for the x and y axis of the image. This example will show how to slice a FITS data cube and plot an image from it. Slicing the WCS object ====================== Like the example introduced in :doc:`getting_started`, we will read in the data using `astropy.io.fits `_ and parse the WCS information. The original FITS file can be downloaded from `here `_. .. plot:: :context: reset :include-source: :align: center :nofigs: from wcsaxes import datasets, WCS hdu = datasets.fetch_l1448_co_hdu() wcs = WCS(hdu.header) image_data = hdu.data This is a three-dimensional dataset which you can check by looking at the header information by:: >>> hdu.header # doctest: +SKIP ... NAXIS = 3 /number of axes CTYPE1 = 'RA---SFL' / CTYPE2 = 'DEC--SFL' / CTYPE3 = 'VELO-LSR' / ... The header keyword 'NAXIS' gives the number of dimensions of the dataset. The keywords 'CTYPE1', 'CTYPE2' and 'CTYPE3' give the data type of these dimensions to be right ascension, declination and velocity respectively. We then instantiate the `~wcsaxes.WCSAxes` using the :class:`~astropy.wcs.WCS` object and select the slices we want to plot: .. plot:: :context: :include-source: :align: center :nofigs: import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=wcs, slices=(50, 'y', 'x')) By setting ``slices=(50, 'y', 'x')``, we have chosen to plot the second dimension on the y-axis and the third dimension on the x-axis. Even though we are not plotting the all the dimensions, we have to specify which slices to select for the dimensions that are not shown. In this example, we are not plotting the first dimension so we have selected the slice 50 to display. You can experiment with this by changing the selected slice and looking at how the plotted image changes. Plotting the image ================== We then add the axes to the image and plot it using the method :meth:`~matplotlib.axes.Axes.imshow`. .. plot:: :context: :include-source: :align: center ax.coords[2].set_ticks(exclude_overlapping=True) ax.imshow(image_data[:, :, 50].transpose(), cmap=plt.cm.gist_heat) Here, ``image_data`` is an :class:`~numpy.ndarray` object. In Numpy, the order of the axes is reversed so the first dimension in the FITS file appears last, the last dimension appears first and so on. Therefore the index passed to :meth:`~matplotlib.axes.Axes.imshow` should be the same as passed to ``slices`` but in reversed order. We also need to :meth:`~numpy.ndarray.transpose` ``image_data`` as we have reversed the dimensions plotted on the x and y axes in the slice. If we don't want to reverse the dimensions plotted, we can simply do: .. plot:: :context: reset :include-source: :align: center fig = plt.figure(figsize=(6,3)) ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=wcs, slices=(50, 'x', 'y')) ax.imshow(image_data[:, :, 50], cmap=plt.cm.gist_heat) wcsaxes-0.6/docs/ticks_labels_grid.rst0000644000077000000240000002063712436367710020121 0ustar tomstaff00000000000000================================== Ticks, tick labels, and grid lines ================================== For the example in the following page we start from the example introduced in :doc:`getting_started`. .. plot:: :context: reset :nofigs: from wcsaxes import datasets, WCS hdu = datasets.fetch_msx_hdu() wcs = WCS(hdu.header) import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_axes([0.25, 0.25, 0.6, 0.6], projection=wcs) ax.imshow(hdu.data, vmin=-2.e-5, vmax=2.e-4, cmap=plt.cm.gist_heat, origin='lower') Coordinate objects ================== While for many images, the coordinate axes are aligned with the pixel axes, this is not always the case, especially if there is any rotation in the world coordinate system, or in coordinate systems with high curvature, where the coupling between x- and y-axis to actual coordinates become less well-defined. Therefore rather than referring to ``x`` and ``y`` ticks as Matplotlib does, we use specialized objects to access the coordinates. The coordinates used in the plot can be accessed using the ``coords`` attribute. The coordinates can either be accessed by index:: lon = ax.coords[0] lat = ax.coords[1] or, in the case of common coordinate systems, by their name: .. plot:: :context: :include-source: :nofigs: lon = ax.coords['glon'] lat = ax.coords['glat'] In this example, the image is in Galactic coordinates, so the coordinates are called ``glon`` and ``glat``. For an image in equatorial coordinates, you would use ``ra`` and ``dec``. The names are only available for specific celestial coordinate systems - for all other systems, you should use the index of the coordinate (``0`` or ``1``). Each coordinate is an instance of the :class:`~wcsaxes.coordinate_helpers.CoordinateHelper` class, which can be used to control the appearance of the ticks, tick labels, grid lines, and axis labels associated with that coordinate. Axis labels =========== Axis labels can be added using the :meth:`~wcsaxes.coordinate_helpers.CoordinateHelper.set_axislabel` method: .. plot:: :context: :include-source: :align: center lon.set_axislabel('Galactic Longitude') lat.set_axislabel('Galactic Latitude') The padding of the axis label with respect to the axes can also be adjusted by using the ``minpad`` option. The default value for ``minpad`` is 1 and is in terms of the font size of the axis label text. Negative values are also allowed. .. plot:: :context: :include-source: :align: center lon.set_axislabel('Galactic Longitude', minpad=0.3) lat.set_axislabel('Galactic Latitude', minpad=-0.4) .. plot:: :context: :nofigs: lon.set_axislabel('Galactic Longitude', minpad=1) lat.set_axislabel('Galactic Latitude', minpad=1) .. _tick_label_format: Tick label format ================= The format of the tick labels can be specified with a string describing the format: .. plot:: :context: :include-source: :align: center lon.set_major_formatter('dd:mm:ss.s') lat.set_major_formatter('dd:mm') The syntax for the format string is the following: ==================== ==================== format result ==================== ==================== ``'dd'`` ``'15d'`` ``'dd:mm'`` ``'15d24m'`` ``'dd:mm:ss'`` ``'15d23m32s'`` ``'dd:mm:ss.s'`` ``'15d23m32.0s'`` ``'dd:mm:ss.ssss'`` ``'15d23m32.0316s'`` ``'hh'`` ``'1h'`` ``'hh:mm'`` ``'1h02m'`` ``'hh:mm:ss'`` ``'1h01m34s'`` ``'hh:mm:ss.s'`` ``'1h01m34.1s'`` ``'hh:mm:ss.ssss'`` ``'1h01m34.1354s'`` ``'d'`` ``'15'`` ``'d.d'`` ``'15.4'`` ``'d.dd'`` ``'15.39'`` ``'d.ddd'`` ``'15.392'`` ``'m'`` ``'924'`` ``'m.m'`` ``'923.5'`` ``'m.mm'`` ``'923.53'`` ``'s'`` ``'55412'`` ``'s.s'`` ``'55412.0'`` ``'s.ss'`` ``'55412.03'`` ``'x.xxxx'`` ``'15.3922'`` ``'%.2f'`` ``'15.39'`` ``'%.3f'`` ``'15.392'`` ``'%d'`` ``'15'`` ==================== ==================== All the ``h...``, ``d...``, ``m...``, and ``s...`` formats can be used for angular coordinate axes, while the ``x...`` format or valid Python formats (see `String Formatting Operations `_) should be used for non-angular coordinate axes. The separators for angular coordinate tick labels can also be set by specifying a string or a tuple. .. plot:: :context: :include-source: :align: center lon.set_separator(('d', "'", '"')) lat.set_separator(':-s') Tick/label spacing and properties ================================= The spacing of ticks/tick labels should have a sensible default, but you may want to be able to manually specify the spacing. This can be done using the :meth:`~wcsaxes.coordinate_helpers.CoordinateHelper.set_ticks` method. There are different options that can be used: * Set the tick positions manually as an Astropy :class:`~astropy.units.quantity.Quantity`:: from astropy import units as u lon.set_ticks([242.2, 242.3, 242.4] * u.degree) * Set the spacing between ticks also as an Astropy :class:`~astropy.units.quantity.Quantity`:: lon.set_ticks(spacing=5. * u.arcmin) * Set the approximate number of ticks:: lon.set_ticks(number=4) In the case of angular axes, specifying the spacing as an Astropy :class:`~astropy.units.quantity.Quantity` avoids roundoff errors. The :meth:`~wcsaxes.coordinate_helpers.CoordinateHelper.set_ticks` method can also be used to set the appearance (color and size) of the ticks, using the ``color=`` and ``size=`` options. There is also the option ``exclude_overlapping=True`` to prevent overlapping tick labels from being displayed. We can apply this to the previous example: .. plot:: :context: :include-source: :align: center from astropy import units as u lon.set_ticks(spacing=10 * u.arcmin, color='white', exclude_overlapping=True) lat.set_ticks(spacing=10 * u.arcmin, color='white', exclude_overlapping=True) Minor ticks =========== WCSAxes does not display minor ticks by default but these can be shown by using the :meth:`~wcsaxes.coordinate_helpers.CoordinateHelper.display_minor_ticks` method. The default frequency of minor ticks is 5 but this can also be specified. .. plot:: :context: :include-source: :align: center lon.display_minor_ticks(True) lat.display_minor_ticks(True) lat.set_minor_frequency(10) Tick, tick label, and axis label position ========================================= By default, the tick and axis labels for the first coordinate are shown on the x-axis, and the tick and axis labels for the second coordinate are shown on the y-axis. In addition, the ticks for both coordintes are shown on all axes. This can be customized using the :meth:`~wcsaxes.coordinate_helpers.CoordinateHelper.set_ticks_position` and :meth:`~wcsaxes.coordinate_helpers.CoordinateHelper.set_ticklabel_position` methods, which each take a string that can contain any or several of ``l``, ``b``, ``r``, or ``t`` (indicating the ticks or tick labels should be shown on the left, bottom, right, or top axes respectively): .. plot:: :context: :include-source: :align: center lon.set_ticks_position('bt') lon.set_ticklabel_position('bt') lon.set_axislabel_position('bt') lat.set_ticks_position('lr') lat.set_ticklabel_position('lr') lat.set_axislabel_position('lr') we can set the defaults back using: .. plot:: :context: :include-source: :align: center lon.set_ticks_position('all') lon.set_ticklabel_position('b') lon.set_axislabel_position('b') lat.set_ticks_position('all') lat.set_ticklabel_position('l') lat.set_axislabel_position('l') Coordinate grid =============== Since the properties of a coordinate grid are linked to the properties of the ticks and labels, grid lines 'belong' to the coordinate objects described above. For example, you can show a grid with yellow lines for RA and orange lines for declination with: .. plot:: :context: :include-source: :align: center lon.grid(color='yellow', alpha=0.5, linestyle='solid') lat.grid(color='orange', alpha=0.5, linestyle='solid') For convenience, you can also simply draw a grid for all the coordinates in one command: .. plot:: :context: :include-source: :align: center ax.coords.grid(color='white', alpha=0.5, linestyle='solid') wcsaxes-0.6/ez_setup.py0000644000077000000240000002757312436367710015211 0ustar tomstaff00000000000000#!python """Bootstrap setuptools installation If you want to use setuptools in your package's setup.py, just include this file in the same directory with it, and add this to the top of your setup.py:: from ez_setup import use_setuptools use_setuptools() If you want to require a specific version of setuptools, set a download mirror, or use an alternate download directory, you can do so by supplying the appropriate options to ``use_setuptools()``. This file can also be run as a script to install or upgrade setuptools. """ import os import shutil import sys import tempfile import tarfile import optparse import subprocess import platform from distutils import log try: from site import USER_SITE except ImportError: USER_SITE = None DEFAULT_VERSION = "1.4.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): args = (sys.executable,) + args return subprocess.call(args) == 0 def _check_call_py24(cmd, *args, **kwargs): res = subprocess.call(cmd, *args, **kwargs) class CalledProcessError(Exception): pass if not res == 0: msg = "Command '%s' return non-zero exit status %d" % (cmd, res) raise CalledProcessError(msg) vars(subprocess).setdefault('check_call', _check_call_py24) def _install(tarball, install_args=()): # extracting the tarball tmpdir = tempfile.mkdtemp() log.warn('Extracting in %s', tmpdir) old_wd = os.getcwd() try: os.chdir(tmpdir) tar = tarfile.open(tarball) _extractall(tar) tar.close() # going in the directory subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) os.chdir(subdir) log.warn('Now working in %s', subdir) # installing log.warn('Installing Setuptools') if not _python_cmd('setup.py', 'install', *install_args): log.warn('Something went wrong during the installation.') log.warn('See the error message above.') # exitcode will be 2 return 2 finally: os.chdir(old_wd) shutil.rmtree(tmpdir) def _build_egg(egg, tarball, to_dir): # extracting the tarball tmpdir = tempfile.mkdtemp() log.warn('Extracting in %s', tmpdir) old_wd = os.getcwd() try: os.chdir(tmpdir) tar = tarfile.open(tarball) _extractall(tar) tar.close() # going in the directory subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) os.chdir(subdir) log.warn('Now working in %s', subdir) # building an egg log.warn('Building a Setuptools egg in %s', to_dir) _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) finally: os.chdir(old_wd) shutil.rmtree(tmpdir) # returning the result log.warn(egg) if not os.path.exists(egg): raise IOError('Could not build the egg.') def _do_download(version, download_base, to_dir, download_delay): egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg' % (version, sys.version_info[0], sys.version_info[1])) if not os.path.exists(egg): tarball = download_setuptools(version, download_base, to_dir, download_delay) _build_egg(egg, tarball, to_dir) sys.path.insert(0, egg) # Remove previously-imported pkg_resources if present (see # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). if 'pkg_resources' in sys.modules: del sys.modules['pkg_resources'] import setuptools setuptools.bootstrap_install_from = egg def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, download_delay=15): # making sure we use the absolute path to_dir = os.path.abspath(to_dir) was_imported = 'pkg_resources' in sys.modules or \ 'setuptools' in sys.modules try: import pkg_resources except ImportError: return _do_download(version, download_base, to_dir, download_delay) try: pkg_resources.require("setuptools>=" + version) return except pkg_resources.VersionConflict: e = sys.exc_info()[1] if was_imported: sys.stderr.write( "The required version of setuptools (>=%s) is not available,\n" "and can't be installed while this script is running. Please\n" "install a more recent version first, using\n" "'easy_install -U setuptools'." "\n\n(Currently using %r)\n" % (version, e.args[0])) sys.exit(2) else: del pkg_resources, sys.modules['pkg_resources'] # reload ok return _do_download(version, download_base, to_dir, download_delay) except pkg_resources.DistributionNotFound: return _do_download(version, download_base, to_dir, download_delay) def _clean_check(cmd, target): """ Run the command to download target. If the command fails, clean up before re-raising the error. """ try: subprocess.check_call(cmd) except subprocess.CalledProcessError: if os.access(target, os.F_OK): os.unlink(target) raise def download_file_powershell(url, target): """ Download the file at url to target using Powershell (which will validate trust). Raise an exception if the command cannot complete. """ target = os.path.abspath(target) cmd = [ 'powershell', '-Command', "(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)" % vars(), ] _clean_check(cmd, target) def has_powershell(): if platform.system() != 'Windows': return False cmd = ['powershell', '-Command', 'echo test'] devnull = open(os.path.devnull, 'wb') try: try: subprocess.check_call(cmd, stdout=devnull, stderr=devnull) except: return False finally: devnull.close() return True download_file_powershell.viable = has_powershell def download_file_curl(url, target): cmd = ['curl', url, '--silent', '--output', target] _clean_check(cmd, target) def has_curl(): cmd = ['curl', '--version'] devnull = open(os.path.devnull, 'wb') try: try: subprocess.check_call(cmd, stdout=devnull, stderr=devnull) except: return False finally: devnull.close() return True download_file_curl.viable = has_curl def download_file_wget(url, target): cmd = ['wget', url, '--quiet', '--output-document', target] _clean_check(cmd, target) def has_wget(): cmd = ['wget', '--version'] devnull = open(os.path.devnull, 'wb') try: try: subprocess.check_call(cmd, stdout=devnull, stderr=devnull) except: return False finally: devnull.close() return True download_file_wget.viable = has_wget def download_file_insecure(url, target): """ Use Python to download the file, even though it cannot authenticate the connection. """ try: from urllib.request import urlopen except ImportError: from urllib2 import urlopen src = dst = None try: src = urlopen(url) # Read/write all in one block, so we don't create a corrupt file # if the download is interrupted. data = src.read() dst = open(target, "wb") dst.write(data) finally: if src: src.close() if dst: dst.close() download_file_insecure.viable = lambda: True def get_best_downloader(): downloaders = [ download_file_powershell, download_file_curl, download_file_wget, download_file_insecure, ] for dl in downloaders: if dl.viable(): return dl def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader): """Download setuptools from a specified location and return its filename `version` should be a valid setuptools version number that is available as an egg for download under the `download_base` URL (which should end with a '/'). `to_dir` is the directory where the egg will be downloaded. `delay` is the number of seconds to pause before an actual download attempt. ``downloader_factory`` should be a function taking no arguments and returning a function for downloading a URL to a target. """ # making sure we use the absolute path to_dir = os.path.abspath(to_dir) tgz_name = "setuptools-%s.tar.gz" % version url = download_base + tgz_name saveto = os.path.join(to_dir, tgz_name) if not os.path.exists(saveto): # Avoid repeated downloads log.warn("Downloading %s", url) downloader = downloader_factory() downloader(url, saveto) return os.path.realpath(saveto) def _extractall(self, path=".", members=None): """Extract all members from the archive to the current working directory and set owner, modification time and permissions on directories afterwards. `path' specifies a different directory to extract to. `members' is optional and must be a subset of the list returned by getmembers(). """ import copy import operator from tarfile import ExtractError directories = [] if members is None: members = self for tarinfo in members: if tarinfo.isdir(): # Extract directories with a safe mode. directories.append(tarinfo) tarinfo = copy.copy(tarinfo) tarinfo.mode = 448 # decimal for oct 0700 self.extract(tarinfo, path) # Reverse sort directories. if sys.version_info < (2, 4): def sorter(dir1, dir2): return cmp(dir1.name, dir2.name) directories.sort(sorter) directories.reverse() else: directories.sort(key=operator.attrgetter('name'), reverse=True) # Set correct owner, mtime and filemode on directories. for tarinfo in directories: dirpath = os.path.join(path, tarinfo.name) try: self.chown(tarinfo, dirpath) self.utime(tarinfo, dirpath) self.chmod(tarinfo, dirpath) except ExtractError: e = sys.exc_info()[1] if self.errorlevel > 1: raise else: self._dbg(1, "tarfile: %s" % e) def _build_install_args(options): """ Build the arguments to 'python setup.py install' on the setuptools package """ install_args = [] if options.user_install: if sys.version_info < (2, 6): log.warn("--user requires Python 2.6 or later") raise SystemExit(1) install_args.append('--user') return install_args def _parse_args(): """ Parse the command line for options """ parser = optparse.OptionParser() parser.add_option( '--user', dest='user_install', action='store_true', default=False, help='install in user site package (requires Python 2.6 or later)') parser.add_option( '--download-base', dest='download_base', metavar="URL", default=DEFAULT_URL, help='alternative URL from where to download the setuptools package') parser.add_option( '--insecure', dest='downloader_factory', action='store_const', const=lambda: download_file_insecure, default=get_best_downloader, help='Use internal, non-validating downloader' ) options, args = parser.parse_args() # positional arguments are ignored return options def main(version=DEFAULT_VERSION): """Install or upgrade setuptools and EasyInstall""" options = _parse_args() tarball = download_setuptools(download_base=options.download_base, downloader_factory=options.downloader_factory) return _install(tarball, _build_install_args(options)) if __name__ == '__main__': sys.exit(main()) wcsaxes-0.6/licenses/0000755000077000000240000000000012553237435014570 5ustar tomstaff00000000000000wcsaxes-0.6/licenses/LICENSE.rst0000644000077000000240000000272512436367710016412 0ustar tomstaff00000000000000Copyright (c) 2014, Thomas P. Robitaille All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Astropy Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. wcsaxes-0.6/licenses/LICENSE_MATPLOTLIB.rst0000644000077000000240000000505012436367710020133 0ustar tomstaff00000000000000*Small portions of the code included in this package was heavily adapted from code present in the mpl_toolkits.axisartist package from Matplotlib, for which the license is given below.* LICENSE AGREEMENT FOR MATPLOTLIB 1.2.0 -------------------------------------- 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 1.2.0 alone or in any derivative version, provided, however, that JDH's License Agreement and JDH's notice of copyright, i.e., "Copyright (c) 2002-2011 John D. Hunter; All Rights Reserved" are retained in matplotlib 1.2.0 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 1.2.0 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 1.2.0. 4. JDH is making matplotlib 1.2.0 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 1.2.0 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. JDH SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF MATPLOTLIB 1.2.0 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING MATPLOTLIB 1.2.0, 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 1.2.0, Licensee agrees to be bound by the terms and conditions of this License Agreement.wcsaxes-0.6/PKG-INFO0000644000077000000240000000050012553237435014053 0ustar tomstaff00000000000000Metadata-Version: 1.0 Name: wcsaxes Version: 0.6 Summary: WCSAxes: a framework for plotting astronomical and geospatial data Home-page: http://wcsaxes.readthedocs.org Author: Thomas Robitaille Author-email: thomas.robitaille@gmail.com License: BSD Description: WCSAxes implementation Platform: UNKNOWN wcsaxes-0.6/README.md0000644000077000000240000000310012535045247014232 0ustar tomstaff00000000000000About ===== WCSAxes is a package that makes it easy to plot images with world coordinate system (WCS) information (which translates pixel to 'world' coordinates and back) using [Matplotlib](http://www.matplotlib.org). Originally intended for use with Astronomical data, WCSAxes can be used with any data provided that an appropriate WCS transformation is supplied. This is an implementation of the API described [here](https://github.com/astropy/astropy-api/blob/master/wcs_axes/wcs_api.md). At the moment the implementation has not be optimized for performance. Once all the functionality is in place, and a test suite has been created, the code will be refactored and optimized. ![Powered by Astropy Badge](http://img.shields.io/badge/powered%20by-AstroPy-orange.svg?style=flat) Developers and Contributors =========================== * Thomas Robitaille * Asra Nizami * Chris Beaumont * Leo Singer * Stuart Mumford * Christoph Deil * Joseph Booker * Matt Craig * Adam Ginsburg * Mathieu Servillat Build and coverage status ========================= [![Build Status](https://travis-ci.org/astrofrog/wcsaxes.png?branch=master)](https://travis-ci.org/astrofrog/wcsaxes) [![Coverage Status](https://coveralls.io/repos/astrofrog/wcsaxes/badge.svg?branch=master)](https://coveralls.io/r/astrofrog/wcsaxes?branch=master) [![Documentation Status](https://readthedocs.org/projects/wcsaxes/badge/?version=latest)](https://readthedocs.org/projects/wcsaxes/?badge=latest) [![asv](http://img.shields.io/badge/benchmarked%20by-asv-green.svg?style=flat)](http://astrofrog.github.io/wcsaxes-benchmarks/) wcsaxes-0.6/setup.cfg0000644000077000000240000000116612553175753014614 0ustar tomstaff00000000000000[build_sphinx] source-dir = docs build-dir = docs/_build all_files = 1 [upload_docs] upload-dir = docs/_build/html show-response = 1 [pytest] minversion = 2.2 norecursedirs = build docs/_build doctest_plus = enabled addopts = --mpl --mpl-baseline-path=wcsaxes/tests/baseline_images [ah_bootstrap] auto_use = True [metadata] package_name = wcsaxes description = WCSAxes: a framework for plotting astronomical and geospatial data long_description = author = Thomas Robitaille author_email = thomas.robitaille@gmail.com license = BSD url = http://wcsaxes.readthedocs.org edit_on_github = False github_project = astrofrog/wcsaxes wcsaxes-0.6/setup.py0000755000077000000240000000664212553237416014507 0ustar tomstaff00000000000000#!/usr/bin/env python # Licensed under a 3-clause BSD style license - see LICENSE.rst import glob import os import sys import ah_bootstrap from setuptools import setup #A dirty hack to get around some early import/configurations ambiguities if sys.version_info[0] >= 3: import builtins else: import __builtin__ as builtins builtins._ASTROPY_SETUP_ = True from astropy_helpers.setup_helpers import ( register_commands, adjust_compiler, get_debug_option, get_package_info) from astropy_helpers.git_helpers import get_git_devstr from astropy_helpers.version_helpers import generate_version_py # Get some values from the setup.cfg from distutils import config conf = config.ConfigParser() conf.read(['setup.cfg']) metadata = dict(conf.items('metadata')) PACKAGENAME = metadata.get('package_name', 'packagename') DESCRIPTION = metadata.get('description', 'Astropy affiliated package') AUTHOR = metadata.get('author', '') AUTHOR_EMAIL = metadata.get('author_email', '') LICENSE = metadata.get('license', 'unknown') URL = metadata.get('url', 'http://astropy.org') # Get the long description from the package's docstring __import__(PACKAGENAME) package = sys.modules[PACKAGENAME] LONG_DESCRIPTION = package.__doc__ # Store the package name in a built-in variable so it's easy # to get from other parts of the setup infrastructure builtins._ASTROPY_PACKAGE_NAME_ = PACKAGENAME # VERSION should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) VERSION = '0.6' # Indicates if this version is a release version RELEASE = 'dev' not in VERSION if not RELEASE: VERSION += get_git_devstr(False) # Populate the dict of setup command overrides; this should be done before # invoking any other functionality from distutils since it can potentially # modify distutils' behavior. cmdclassd = register_commands(PACKAGENAME, VERSION, RELEASE) # Adjust the compiler in case the default on this platform is to use a # broken one. adjust_compiler(PACKAGENAME) # Freeze build information in version.py generate_version_py(PACKAGENAME, VERSION, RELEASE, get_debug_option(PACKAGENAME)) # Treat everything in scripts except README.rst as a script to be installed scripts = [fname for fname in glob.glob(os.path.join('scripts', '*')) if os.path.basename(fname) != 'README.rst'] # Get configuration information from all of the various subpackages. # See the docstring for setup_helpers.update_package_files for more # details. package_info = get_package_info() # Add the project-global data package_info['package_data'].setdefault(PACKAGENAME, []) package_info['package_data'][PACKAGENAME].append('data/*') # Include all .c files, recursively, including those generated by # Cython, since we can not do this in MANIFEST.in with a "dynamic" # directory name. c_files = [] for root, dirs, files in os.walk(PACKAGENAME): for filename in files: if filename.endswith('.c'): c_files.append( os.path.join( os.path.relpath(root, PACKAGENAME), filename)) package_info['package_data'][PACKAGENAME].extend(c_files) setup(name=PACKAGENAME, version=VERSION, description=DESCRIPTION, scripts=scripts, install_requires=['astropy', 'matplotlib'], author=AUTHOR, author_email=AUTHOR_EMAIL, license=LICENSE, url=URL, long_description=LONG_DESCRIPTION, cmdclass=cmdclassd, zip_safe=False, use_2to3=False, **package_info ) wcsaxes-0.6/wcsaxes/0000755000077000000240000000000012553237435014440 5ustar tomstaff00000000000000wcsaxes-0.6/wcsaxes/__init__.py0000644000077000000240000000107512436367710016554 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ WCSAxes implementation """ # Affiliated packages may add whatever they like to this file, but # should keep this content at the top. # ---------------------------------------------------------------------------- from ._astropy_init import * # ---------------------------------------------------------------------------- if not _ASTROPY_SETUP_: from .core import * from .coordinate_helpers import CoordinateHelper from .coordinates_map import CoordinatesMap from .wcs_wrapper import WCS wcsaxes-0.6/wcsaxes/_astropy_init.py0000644000077000000240000001223112553175753017700 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst __all__ = ['__version__', '__githash__', 'test'] # this indicates whether or not we are in the package's setup.py try: _ASTROPY_SETUP_ except NameError: from sys import version_info if version_info[0] >= 3: import builtins else: import __builtin__ as builtins builtins._ASTROPY_SETUP_ = False try: from .version import version as __version__ except ImportError: __version__ = '' try: from .version import githash as __githash__ except ImportError: __githash__ = '' # set up the test command def _get_test_runner(): import os from astropy.tests.helper import TestRunner return TestRunner(os.path.dirname(__file__)) def test(package=None, test_path=None, args=None, plugins=None, verbose=False, pastebin=None, remote_data=False, pep8=False, pdb=False, coverage=False, open_files=False, **kwargs): """ Run the tests using `py.test `__. A proper set of arguments is constructed and passed to `pytest.main`_. .. _py.test: http://pytest.org/latest/ .. _pytest.main: http://pytest.org/latest/builtin.html#pytest.main Parameters ---------- package : str, optional The name of a specific package to test, e.g. 'io.fits' or 'utils'. If nothing is specified all default tests are run. test_path : str, optional Specify location to test by path. May be a single file or directory. Must be specified absolutely or relative to the calling directory. args : str, optional Additional arguments to be passed to pytest.main_ in the ``args`` keyword argument. plugins : list, optional Plugins to be passed to pytest.main_ in the ``plugins`` keyword argument. verbose : bool, optional Convenience option to turn on verbose output from py.test_. Passing True is the same as specifying ``'-v'`` in ``args``. pastebin : {'failed','all',None}, optional Convenience option for turning on py.test_ pastebin output. Set to ``'failed'`` to upload info for failed tests, or ``'all'`` to upload info for all tests. remote_data : bool, optional Controls whether to run tests marked with @remote_data. These tests use online data and are not run by default. Set to True to run these tests. pep8 : bool, optional Turn on PEP8 checking via the `pytest-pep8 plugin `_ and disable normal tests. Same as specifying ``'--pep8 -k pep8'`` in ``args``. pdb : bool, optional Turn on PDB post-mortem analysis for failing tests. Same as specifying ``'--pdb'`` in ``args``. coverage : bool, optional Generate a test coverage report. The result will be placed in the directory htmlcov. open_files : bool, optional Fail when any tests leave files open. Off by default, because this adds extra run time to the test suite. Requires the `psutil `_ package. parallel : int, optional When provided, run the tests in parallel on the specified number of CPUs. If parallel is negative, it will use the all the cores on the machine. Requires the `pytest-xdist `_ plugin installed. Only available when using Astropy 0.3 or later. kwargs Any additional keywords passed into this function will be passed on to the astropy test runner. This allows use of test-related functionality implemented in later versions of astropy without explicitly updating the package template. """ test_runner = _get_test_runner() return test_runner.run_tests( package=package, test_path=test_path, args=args, plugins=plugins, verbose=verbose, pastebin=pastebin, remote_data=remote_data, pep8=pep8, pdb=pdb, coverage=coverage, open_files=open_files, **kwargs) if not _ASTROPY_SETUP_: import os from warnings import warn from astropy import config # add these here so we only need to cleanup the namespace at the end config_dir = None if not os.environ.get('ASTROPY_SKIP_CONFIG_UPDATE', False): config_dir = os.path.dirname(__file__) config_template = os.path.join(config_dir, __package__ + ".cfg") if os.path.isfile(config_template): try: config.configuration.update_default_config( __package__, config_dir, version=__version__) except TypeError as orig_error: try: config.configuration.update_default_config( __package__, config_dir) except config.configuration.ConfigurationDefaultMissingError as e: wmsg = (e.args[0] + " Cannot install default profile. If you are " "importing from source, this is expected.") warn(config.configuration.ConfigurationDefaultMissingWarning(wmsg)) del e except: raise orig_error wcsaxes-0.6/wcsaxes/axislabels.py0000644000077000000240000001054612441052514017134 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import numpy as np from matplotlib.text import Text import matplotlib.transforms as mtransforms from .frame import RectangularFrame class AxisLabels(Text): def __init__(self, frame, minpad=1, *args, **kwargs): self._frame = frame super(AxisLabels, self).__init__(*args, **kwargs) self.set_clip_on(True) self.set_visible_axes('all') self.set_ha('center') self.set_va('center') self._minpad = minpad def get_minpad(self, axis): try: return self._minpad[axis] except TypeError: return self._minpad def set_visible_axes(self, visible_axes): self._visible_axes = visible_axes def get_visible_axes(self): if self._visible_axes == 'all': return self._frame.keys() else: return [x for x in self._visible_axes if x in self._frame] def set_minpad(self, minpad): self._minpad = minpad def draw(self, renderer, bboxes, ticklabels_bbox_list, visible_ticks): if not self.get_visible(): return text_size = renderer.points_to_pixels(self.get_size()) for axis in self.get_visible_axes(): padding = text_size * self.get_minpad(axis) # Find position of the axis label. For now we pick the mid-point # along the path but in future we could allow this to be a # parameter. x_disp, y_disp = self._frame[axis].pixel[:, 0], self._frame[axis].pixel[:, 1] d = np.hstack([0., np.cumsum(np.sqrt(np.diff(x_disp) ** 2 + np.diff(y_disp) ** 2))]) xcen = np.interp(d[-1] / 2., d, x_disp) ycen = np.interp(d[-1] / 2., d, y_disp) # Find segment along which the mid-point lies imin = np.searchsorted(d, d[-1] / 2.) - 1 # Find normal of the axis label facing outwards on that segment normal_angle = self._frame[axis].normal_angle[imin] + 180. label_angle = (normal_angle - 90.) % 360. if label_angle < 225 and label_angle > 135: label_angle += 180 self.set_rotation(label_angle) # Find label position by looking at the bounding box of ticks' # labels and the image. It sets the default padding at 1 times the # axis label font size which can also be changed by setting # the minpad parameter. if isinstance(self._frame, RectangularFrame): if len(ticklabels_bbox_list) > 0: ticklabels_bbox = mtransforms.Bbox.union(ticklabels_bbox_list) else: ticklabels_bbox = None if axis == 'l': if axis in visible_ticks and ticklabels_bbox is not None: left = ticklabels_bbox.xmin else: left = xcen xpos = left - padding self.set_position((xpos, ycen)) elif axis == 'r': if axis in visible_ticks and ticklabels_bbox is not None: right = ticklabels_bbox.x1 else: right = xcen xpos = right + padding self.set_position((xpos, ycen)) elif axis == 'b': if axis in visible_ticks and ticklabels_bbox is not None: bottom = ticklabels_bbox.ymin else: bottom = ycen ypos = bottom - padding self.set_position((xcen, ypos)) elif axis == 't': if axis in visible_ticks and ticklabels_bbox is not None: top = ticklabels_bbox.y1 else: top = ycen ypos = top + padding self.set_position((xcen, ypos)) else: # arbitrary axis dx = np.cos(np.radians(normal_angle)) * (padding + text_size * 1.5) dy = np.sin(np.radians(normal_angle)) * (padding + text_size * 1.5) self.set_position((xcen + dx, ycen + dy)) super(AxisLabels, self).draw(renderer) bb = super(AxisLabels, self).get_window_extent(renderer) bboxes.append(bb) wcsaxes-0.6/wcsaxes/conftest.py0000644000077000000240000000233512553175753016646 0ustar tomstaff00000000000000# this contains imports plugins that configure py.test for astropy tests. # by importing them here in conftest.py they are discoverable by py.test # no matter how it is invoked within the source tree. from astropy.tests.pytest_plugins import * from astropy.tests.pytest_plugins import pytest_addoption as astropy_pytest_addoption # Uncomment the following line to treat all DeprecationWarnings as # exceptions enable_deprecations_as_exceptions() import os from astropy.tests.helper import pytest # Uncomment and customize the following lines to add/remove entries # from the list of packages for which version numbers are displayed # when running the tests try: PYTEST_HEADER_MODULES['Astropy'] = 'astropy' except NameError: # needed to support Astropy < 1.0 pass # Uncomment the following lines to display the version number of the # package rather than the version number of Astropy in the top line when # running the tests. import os # This is to figure out the affiliated package version, rather than # using Astropy's from . import version try: packagename = os.path.basename(os.path.dirname(__file__)) TESTED_VERSIONS[packagename] = version.version except NameError: # Needed to support Astropy <= 1.0.0 pass wcsaxes-0.6/wcsaxes/coordinate_helpers.py0000644000077000000240000006653112553175753020702 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This file defines the classes used to represent a 'coordinate', which includes axes, ticks, tick labels, and grid lines. """ import numpy as np from astropy import units as u from astropy.extern import six from matplotlib.ticker import Formatter from matplotlib.transforms import Affine2D, ScaledTranslation from matplotlib.patches import PathPatch from matplotlib import rcParams from .formatter_locator import AngleFormatterLocator, ScalarFormatterLocator from .ticks import Ticks from .ticklabels import TickLabels from .axislabels import AxisLabels from .grid_paths import get_lon_lat_path, get_gridline_path from . import settings __all__ = ['CoordinateHelper'] def wrap_angle_at(values, coord_wrap): return np.mod(values - coord_wrap, 360.) - (360. - coord_wrap) class CoordinateHelper(object): def __init__(self, parent_axes=None, parent_map=None, transform=None, coord_index=None, coord_type='scalar', coord_unit=None, coord_wrap=None, frame=None): # Keep a reference to the parent axes and the transform self.parent_axes = parent_axes self.parent_map = parent_map self.transform = transform self.coord_index = coord_index self.coord_unit = coord_unit self.frame = frame self.set_coord_type(coord_type, coord_wrap) # Initialize ticks self.dpi_transform = Affine2D() self.offset_transform = ScaledTranslation(0, 0, self.dpi_transform) self.ticks = Ticks(transform=parent_axes.transData + self.offset_transform) # Initialize tick labels self.ticklabels = TickLabels(self.frame, transform=None, # display coordinates figure=parent_axes.get_figure()) self.ticks.display_minor_ticks(False) self.minor_frequency = 5 # Initialize axis labels self.axislabels = AxisLabels(self.frame, transform=None, # display coordinates figure=parent_axes.get_figure()) # Initialize container for the grid lines self.grid_lines = [] # Initialize grid style. Take defaults from matplotlib.rcParams. # Based on matplotlib.axis.YTick._get_gridline. # # Matplotlib's gridlines use Line2D, but ours use PathPatch. # Patches take a slightly different format of linestyle argument. lines_to_patches_linestyle = { '-': 'solid', '--': 'dashed', '-.': 'dashdot', ':': 'dotted', 'none': 'none', 'None': 'none', ' ': 'none', '': 'none' } self.grid_lines_kwargs = {'visible': False, 'facecolor': 'none', 'edgecolor': rcParams['grid.color'], 'linestyle': lines_to_patches_linestyle[rcParams['grid.linestyle']], 'linewidth': rcParams['grid.linewidth'], 'alpha': rcParams.get('grid.alpha', 1.0), 'transform': self.parent_axes.transData} def grid(self, draw_grid=True, grid_type='lines', **kwargs): """ Plot grid lines for this coordinate. Standard matplotlib appearance options (color, alpha, etc.) can be passed as keyword arguments. Parameters ---------- draw_grid : bool Whether to show the gridlines grid_type : { 'lines' | 'contours' } Whether to plot the contours by determining the grid lines in world coordinates and then plotting them in world coordinates (``'lines'``) or by determining the world coordinates at many positions in the image and then drawing contours (``'contours'``). The first is recommended for 2-d images, while for 3-d (or higher dimensional) cubes, the ``'contours'`` option is recommended. """ if grid_type in ('lines', 'contours'): self._grid_type = grid_type else: raise ValueError("grid_type should be 'lines' or 'contours'") if 'color' in kwargs: kwargs['edgecolor'] = kwargs.pop('color') self.grid_lines_kwargs.update(kwargs) if self.grid_lines_kwargs['visible']: if not draw_grid: self.grid_lines_kwargs['visible'] = False else: self.grid_lines_kwargs['visible'] = True def set_coord_type(self, coord_type, coord_wrap=None): """ Set the coordinate type for the axis. Parameters ---------- coord_type : str One of 'longitude', 'latitude' or 'scalar' coord_wrap : float, optional The value to wrap at for angular coordinates """ self.coord_type = coord_type if coord_type == 'longitude' and coord_wrap is None: self.coord_wrap = 360 elif coord_type != 'longitude' and coord_wrap is not None: raise NotImplementedError('coord_wrap is not yet supported for non-longitude coordinates') else: self.coord_wrap = coord_wrap # Initialize tick formatter/locator if coord_type == 'scalar': self._coord_unit_scale = None self._formatter_locator = ScalarFormatterLocator(unit=self.coord_unit) elif coord_type in ['longitude', 'latitude']: if self.coord_unit is u.deg: self._coord_unit_scale = None else: self._coord_unit_scale = self.coord_unit.to(u.deg) self._formatter_locator = AngleFormatterLocator() else: raise ValueError("coord_type should be one of 'scalar', 'longitude', or 'latitude'") def set_major_formatter(self, formatter): """ Set the formatter to use for the major tick labels. Parameters ---------- formatter : str or Formatter The format or formatter to use. """ if isinstance(formatter, Formatter): raise NotImplementedError() # figure out how to swap out formatter elif isinstance(formatter, six.string_types): self._formatter_locator.format = formatter else: raise TypeError("formatter should be a string or a Formatter " "instance") def format_coord(self, value): """ Given the value of a coordinate, will format it according to the format of the formatter_locator. """ if not hasattr(self, "_fl_spacing"): return "" # _update_ticks has not been called yet fl = self._formatter_locator if isinstance(fl, AngleFormatterLocator): # Convert to degrees if needed if self._coord_unit_scale is not None: value *= self._coord_unit_scale if self.coord_type == 'longitude': value = wrap_angle_at(value, self.coord_wrap) value = value * u.degree value = value.to(fl._unit).value spacing = self._fl_spacing string = fl.formatter(values=[value] * fl._unit, spacing=spacing) return string[0] def set_separator(self, separator): """ Set the separator to use for the angle major tick labels. Parameters ---------- separator : The separator between numbers in sexagesimal representation. Can be either a string or a tuple. """ if not (self._formatter_locator.__class__ == AngleFormatterLocator): raise TypeError("Separator can only be specified for angle coordinates") if isinstance(separator, six.string_types) or isinstance(separator, tuple): self._formatter_locator.sep = separator else: raise TypeError("separator should be a string or a tuple") def set_format_unit(self, unit): """ Set the unit for the major tick labels. Parameters ---------- unit : class:`~astropy.units.Unit` The unit to which the tick labels should be converted to. """ if (not issubclass(unit.__class__, u.UnitBase)): raise TypeError("unit should be an astropy UnitBase subclass") self._formatter_locator.format_unit = unit def set_ticks(self, values=None, spacing=None, number=None, size=None, width=None, color=None, alpha=None, exclude_overlapping=False): """ Set the location and properties of the ticks. At most one of the options from ``values``, ``spacing``, or ``number`` can be specified. Parameters ---------- values : iterable, optional The coordinate values at which to show the ticks. spacing : float, optional The spacing between ticks. number : float, optional The approximate number of ticks shown. size : float, optional The length of the ticks in points color : str or tuple A valid Matplotlib color for the ticks exclude_overlapping : bool, optional Whether to exclude tick labels that overlap over each other. """ if sum([values is None, spacing is None, number is None]) < 2: raise ValueError("At most one of values, spacing, or number should " "be specified") if values is not None: self._formatter_locator.values = values elif spacing is not None: self._formatter_locator.spacing = spacing elif number is not None: self._formatter_locator.number = number if size is not None: self.ticks.set_ticksize(size) if width is not None: self.ticks.set_linewidth(width) if color is not None: self.ticks.set_color(color) if alpha is not None: self.ticks.set_alpha(alpha) self.ticklabels.set_exclude_overlapping(exclude_overlapping) def set_ticks_position(self, position): """ Set where ticks should appear Parameters ---------- position : str The axes on which the ticks for this coordinate should appear. Should be a string containing zero or more of ``'b'``, ``'t'``, ``'l'``, ``'r'``. For example, ``'lb'`` will lead the ticks to be shown on the left and bottom axis. """ self.ticks.set_visible_axes(position) def set_ticklabel(self, **kwargs): """ Set the visual properties for the tick labels. Parameters ---------- kwargs Keyword arguments are passed to :class:`matplotlib.text.Text`. These can include keywords to set the ``color``, ``size``, ``weight``, and other text properties. """ self.ticklabels.set(**kwargs) def set_ticklabel_position(self, position): """ Set where tick labels should appear Parameters ---------- position : str The axes on which the tick labels for this coordinate should appear. Should be a string containing zero or more of ``'b'``, ``'t'``, ``'l'``, ``'r'``. For example, ``'lb'`` will lead the tick labels to be shown on the left and bottom axis. """ self.ticklabels.set_visible_axes(position) def set_axislabel(self, text, minpad=1, **kwargs): """ Set the text and optionally visual properties for the axis label. Parameters ---------- text : str The axis label text. minpad : float, optional The padding for the label in terms of axis label font size. kwargs Keywords are passed to :class:`matplotlib.text.Text`. These can include keywords to set the ``color``, ``size``, ``weight``, and other text properties. """ self.axislabels.set_text(text) self.axislabels.set_minpad(minpad) self.axislabels.set(**kwargs) def get_axislabel(self): """ Get the text for the axis label Returns ------- label : str The axis label """ return self.axislabels.get_text() def set_axislabel_position(self, position): """ Set where axis labels should appear Parameters ---------- position : str The axes on which the axis label for this coordinate should appear. Should be a string containing zero or more of ``'b'``, ``'t'``, ``'l'``, ``'r'``. For example, ``'lb'`` will lead the axis label to be shown on the left and bottom axis. """ self.axislabels.set_visible_axes(position) @property def locator(self): return self._formatter_locator.locator @property def formatter(self): return self._formatter_locator.formatter def _draw(self, renderer, bboxes, ticklabels_bbox): renderer.open_group('coordinate_axis') self._update_ticks(renderer) self.ticks.draw(renderer) self.ticklabels.draw(renderer, bboxes=bboxes, ticklabels_bbox=ticklabels_bbox) if self.grid_lines_kwargs['visible']: if self._grid_type == 'lines': self._update_grid_lines() else: self._update_grid_contour() if self._grid_type == 'lines': frame_patch = self.frame.patch for path in self.grid_lines: p = PathPatch(path, **self.grid_lines_kwargs) p.set_clip_path(frame_patch) p.draw(renderer) elif self._grid is not None: for line in self._grid.collections: line.set(**self.grid_lines_kwargs) line.draw(renderer) renderer.close_group('coordinate_axis') def _draw_axislabels(self, renderer, bboxes, ticklabels_bbox, visible_ticks): renderer.open_group('axis labels') self.axislabels.draw(renderer, bboxes=bboxes, ticklabels_bbox_list=ticklabels_bbox, visible_ticks=visible_ticks) renderer.close_group('axis labels') def _update_ticks(self, renderer): # TODO: this method should be optimized for speed # Here we determine the location and rotation of all the ticks. For # each axis, we can check the intersections for the specific # coordinate and once we have the tick positions, we can use the WCS # to determine the rotations. # Find the range of coordinates in all directions coord_range = self.parent_map.get_coord_range() # First find the ticks we want to show tick_world_coordinates, self._fl_spacing = self.locator(*coord_range[self.coord_index]) if self.ticks.get_display_minor_ticks(): minor_ticks_w_coordinates = self._formatter_locator.minor_locator(self._fl_spacing, self.get_minor_frequency(), *coord_range[self.coord_index]) # We want to allow non-standard rectangular frames, so we just rely on # the parent axes to tell us what the bounding frame is. frame = self.frame.sample(settings.FRAME_BOUNDARY_SAMPLES) self.ticks.clear() self.ticklabels.clear() self.lblinfo = [] self.lbl_world = [] # Look up parent axes' transform from data to figure coordinates. # # See: # http://matplotlib.org/users/transforms_tutorial.html#the-transformation-pipeline transData = self.parent_axes.transData invertedTransLimits = transData.inverted() for axis, spine in six.iteritems(frame): # Determine tick rotation in display coordinates and compare to # the normal angle in display coordinates. pixel0 = spine.data world0 = spine.world[:, self.coord_index] world0 = self.transform.transform(pixel0)[:, self.coord_index] axes0 = transData.transform(pixel0) # Advance 2 pixels in figure coordinates pixel1 = axes0.copy() pixel1[:, 0] += 2.0 pixel1 = invertedTransLimits.transform(pixel1) world1 = self.transform.transform(pixel1)[:, self.coord_index] # Advance 2 pixels in figure coordinates pixel2 = axes0.copy() pixel2[:, 1] += 2.0 if self.frame.origin == 'lower' else -2.0 pixel2 = invertedTransLimits.transform(pixel2) world2 = self.transform.transform(pixel2)[:, self.coord_index] dx = (world1 - world0) dy = (world2 - world0) # Rotate by 90 degrees dx, dy = -dy, dx if self._coord_unit_scale is not None: dx *= self._coord_unit_scale dy *= self._coord_unit_scale if self.coord_type == 'longitude': # Here we wrap at 180 not self.coord_wrap since we want to # always ensure abs(dx) < 180 and abs(dy) < 180 dx = wrap_angle_at(dx, 180.) dy = wrap_angle_at(dy, 180.) tick_angle = np.degrees(np.arctan2(dy, dx)) normal_angle_full = np.hstack([spine.normal_angle, spine.normal_angle[-1]]) with np.errstate(invalid='ignore'): reset = (((normal_angle_full - tick_angle) % 360 > 90.) & ((tick_angle - normal_angle_full) % 360 > 90.)) tick_angle[reset] -= 180. # We find for each interval the starting and ending coordinate, # ensuring that we take wrapping into account correctly for # longitudes. w1 = spine.world[:-1, self.coord_index] w2 = spine.world[1:, self.coord_index] if self._coord_unit_scale is not None: w1 = w1 * self._coord_unit_scale w2 = w2 * self._coord_unit_scale if self.coord_type == 'longitude': w1 = wrap_angle_at(w1, self.coord_wrap) w2 = wrap_angle_at(w2, self.coord_wrap) with np.errstate(invalid='ignore'): w1[w2 - w1 > 180.] += 360 w2[w1 - w2 > 180.] += 360 # For longitudes, we need to check ticks as well as ticks + 360, # since the above can produce pairs such as 359 to 361 or 0.5 to # 1.5, both of which would match a tick at 0.75. Otherwise we just # check the ticks determined above. self._compute_ticks(tick_world_coordinates, spine, axis, w1, w2, tick_angle) if self.ticks.get_display_minor_ticks(): self._compute_ticks(minor_ticks_w_coordinates, spine, axis, w1, w2, tick_angle, ticks='minor') # format tick labels, add to scene text = self.formatter(self.lbl_world * tick_world_coordinates.unit, spacing=self._fl_spacing) for kwargs, txt in zip(self.lblinfo, text): self.ticklabels.add(text=txt, **kwargs) def _compute_ticks(self, tick_world_coordinates, spine, axis, w1, w2, tick_angle, ticks='major'): tick_world_coordinates_values = tick_world_coordinates.value if self.coord_type == 'longitude': tick_world_coordinates_values = np.hstack([tick_world_coordinates_values, tick_world_coordinates_values + 360]) for t in tick_world_coordinates_values: # Find steps where a tick is present. We have to check # separately for the case where the tick falls exactly on the # frame points, otherwise we'll get two matches, one for w1 and # one for w2. with np.errstate(invalid='ignore'): intersections = np.hstack([np.nonzero((t - w1) == 0)[0], np.nonzero(((t - w1) * (t - w2)) < 0)[0]]) # But we also need to check for intersection with the last w2 if t - w2[-1] == 0: intersections = np.append(intersections, len(w2) - 1) # Loop over ticks, and find exact pixel coordinates by linear # interpolation for imin in intersections: imax = imin + 1 if np.allclose(w1[imin], w2[imin], rtol=1.e-13, atol=1.e-13): continue # tick is exactly aligned with frame else: frac = (t - w1[imin]) / (w2[imin] - w1[imin]) x_data_i = spine.data[imin, 0] + frac * (spine.data[imax, 0] - spine.data[imin, 0]) y_data_i = spine.data[imin, 1] + frac * (spine.data[imax, 1] - spine.data[imin, 1]) x_pix_i = spine.pixel[imin, 0] + frac * (spine.pixel[imax, 0] - spine.pixel[imin, 0]) y_pix_i = spine.pixel[imin, 1] + frac * (spine.pixel[imax, 1] - spine.pixel[imin, 1]) delta_angle = tick_angle[imax] - tick_angle[imin] if delta_angle > 180.: delta_angle -= 360. elif delta_angle < -180.: delta_angle += 360. angle_i = tick_angle[imin] + frac * delta_angle if self.coord_type == 'longitude': world = wrap_angle_at(t, self.coord_wrap) else: world = t if ticks == 'major': self.ticks.add(axis=axis, pixel=(x_data_i, y_data_i), world=world, angle=angle_i, axis_displacement=imin + frac) # store information to pass to ticklabels.add # it's faster to format many ticklabels at once outside # of the loop self.lblinfo.append(dict(axis=axis, pixel=(x_pix_i, y_pix_i), world=world, angle=spine.normal_angle[imin], axis_displacement=imin + frac)) self.lbl_world.append(world) else: self.ticks.add_minor(minor_axis=axis, minor_pixel=(x_data_i, y_data_i), minor_world=world, minor_angle=angle_i, minor_axis_displacement=imin + frac) def display_minor_ticks(self, display_minor_ticks): """ Display minor ticks for this coordinate. Parameters ---------- display_minor_ticks : bool Whether or not to display minor ticks. """ self.ticks.display_minor_ticks(display_minor_ticks) def get_minor_frequency(self): return self.minor_frequency def set_minor_frequency(self, frequency): """ Set the frequency of minor ticks per major ticks. Parameters ---------- frequency : int The number of minor ticks per major ticks. """ self.minor_frequency = frequency def _update_grid_lines(self): # For 3-d WCS with a correlated third axis, the *proper* way of # drawing a grid should be to find the world coordinates of all pixels # and drawing contours. What we are doing here assumes that we can # define the grid lines with just two of the coordinates (and # therefore assumes that the other coordinates are fixed and set to # the value in the slice). Here we basically assume that if the WCS # had a third axis, it has been abstracted away in the transformation. coord_range = self.parent_map.get_coord_range() tick_world_coordinates, spacing = self.locator(*coord_range[self.coord_index]) tick_world_coordinates_values = tick_world_coordinates.value n_coord = len(tick_world_coordinates_values) n_samples = settings.GRID_SAMPLES xy_world = np.zeros((n_samples * n_coord, 2)) self.grid_lines = [] for iw, w in enumerate(tick_world_coordinates_values): subset = slice(iw * n_samples, (iw + 1) * n_samples) if self.coord_index == 0: xy_world[subset, 0] = np.repeat(w, n_samples) xy_world[subset, 1] = np.linspace(coord_range[1][0], coord_range[1][1], n_samples) else: xy_world[subset, 0] = np.linspace(coord_range[0][0], coord_range[0][1], n_samples) xy_world[subset, 1] = np.repeat(w, n_samples) # We now convert all the world coordinates to pixel coordinates in a # single go rather than doing this in the gridline to path conversion # to fully benefit from vectorized coordinate transformations. # Currently xy_world is in deg, but transform function needs it in # native units if self._coord_unit_scale is not None: xy_world /= self._coord_unit_scale # Transform line to pixel coordinates pixel = self.transform.inverted().transform(xy_world) # Create round-tripped values for checking xy_world_round = self.transform.transform(pixel) for iw in range(n_coord): subset = slice(iw * n_samples, (iw + 1) * n_samples) self.grid_lines.append(self._get_gridline(xy_world[subset], pixel[subset], xy_world_round[subset])) def _get_gridline(self, xy_world, pixel, xy_world_round): if self.coord_type == 'scalar': return get_gridline_path(xy_world, pixel) else: return get_lon_lat_path(xy_world, pixel, xy_world_round) def _update_grid_contour(self): if hasattr(self, '_grid'): for line in self._grid.collections: line.remove() xmin, xmax = self.parent_axes.get_xlim() ymin, ymax = self.parent_axes.get_ylim() X, Y, field = self.transform.get_coord_slices(xmin, xmax, ymin, ymax, 200, 200) coord_range = self.parent_map.get_coord_range() tick_world_coordinates, spacing = self.locator(*coord_range[self.coord_index]) field = field[self.coord_index] # tick_world_coordinates is a Quantities array and we only needs its values tick_world_coordinates_values = tick_world_coordinates.value if self.coord_type == 'longitude': # Find biggest gap in tick_world_coordinates and wrap in middle # For now just assume spacing is equal, so any mid-point will do mid = 0.5 * (tick_world_coordinates_values[0] + tick_world_coordinates_values[1]) field = wrap_angle_at(field, mid) tick_world_coordinates_values = wrap_angle_at(tick_world_coordinates_values, mid) # Replace wraps by NaN reset = (np.abs(np.diff(field[:, :-1], axis=0)) > 180) | (np.abs(np.diff(field[:-1, :], axis=1)) > 180) field[:-1, :-1][reset] = np.nan field[1:, :-1][reset] = np.nan field[:-1, 1:][reset] = np.nan field[1:, 1:][reset] = np.nan if len(tick_world_coordinates_values) > 0: self._grid = self.parent_axes.contour(X, Y, field.transpose(), levels=tick_world_coordinates_values) else: self._grid = None wcsaxes-0.6/wcsaxes/coordinate_range.py0000644000077000000240000001034312553175753020322 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import warnings import numpy as np from astropy import units as u from . import settings # Algorithm inspired by PGSBOX from WCSLIB by M. Calabretta def wrap_180(values): values_new = values % 360. with np.errstate(invalid='ignore'): values_new[values_new > 180.] -= 360 return values_new def find_coordinate_range(transform, extent, coord_types, coord_units): ''' Find the range of coordinates to use for ticks/grids Parameters ---------- pix2world : func Function to transform pixel to world coordinates. Should take two values (the pixel coordinates) and return two values (the world coordinates). extent : iterable The range of the image viewport in pixel coordinates, given as [xmin, xmax, ymin, ymax]. coord_types : list of str Whether each coordinate is a ``'longitude'``, ``'latitude'``, or ``'scalar'`` value. coord_units : list of `astropy.units.Unit` The units for each coordinate ''' # Sample coordinates on a NX x NY grid. NX = NY = settings.COORDINATE_RANGE_SAMPLES x = np.linspace(extent[0], extent[1], NX + 1) y = np.linspace(extent[2], extent[3], NY + 1) xp, yp = np.meshgrid(x, y) world = transform.transform(np.vstack([xp.ravel(), yp.ravel()]).transpose()) ranges = [] for coord_index, coord_type in enumerate(coord_types): xw = world[:, coord_index].reshape(xp.shape) if coord_type in ['longitude', 'latitude']: unit = coord_units[coord_index] xw = xw * unit.to(u.deg) # Iron out coordinates along first row wjump = xw[0, 1:] - xw[0, :-1] with np.errstate(invalid='ignore'): reset = np.abs(wjump) > 180. if np.any(reset): wjump = wjump + np.sign(wjump) * 180. wjump = 360. * (wjump / 360.).astype(int) xw[0, 1:][reset] -= wjump[reset] # Now iron out coordinates along all columns, starting with first row. wjump = xw[1:] - xw[:1] with np.errstate(invalid='ignore'): reset = np.abs(wjump) > 180. if np.any(reset): wjump = wjump + np.sign(wjump) * 180. wjump = 360. * (wjump / 360.).astype(int) xw[1:][reset] -= wjump[reset] with warnings.catch_warnings(): warnings.simplefilter("ignore", RuntimeWarning) xw_min = np.nanmin(xw) xw_max = np.nanmax(xw) # Check if range is smaller when normalizing to the range 0 to 360 if coord_type in ['longitude', 'latitude']: with warnings.catch_warnings(): warnings.simplefilter("ignore", RuntimeWarning) xw_min_check = np.nanmin(xw % 360.) xw_max_check = np.nanmax(xw % 360.) if xw_max - xw_min < 360. and xw_max - xw_min >= xw_max_check - xw_min_check: xw_min = xw_min_check xw_max = xw_max_check # Check if range is smaller when normalizing to the range -180 to 180 if coord_type in ['longitude', 'latitude']: with warnings.catch_warnings(): warnings.simplefilter("ignore", RuntimeWarning) xw_min_check = np.nanmin(wrap_180(xw)) xw_max_check = np.nanmax(wrap_180(xw)) if xw_max_check - xw_min_check < 360. and xw_max - xw_min >= xw_max_check - xw_min_check: xw_min = xw_min_check xw_max = xw_max_check x_range = xw_max - xw_min if coord_type == 'longitude': if x_range > 300.: xw_min = 0. xw_max = 360 - np.spacing(360.) elif xw_min < 0.: xw_min = max(-180., xw_min - 0.1 * x_range) xw_max = min(+180., xw_max + 0.1 * x_range) else: xw_min = max(0., xw_min - 0.1 * x_range) xw_max = min(360., xw_max + 0.1 * x_range) elif coord_type == 'latitude': xw_min = max(-90., xw_min - 0.1 * x_range) xw_max = min(+90., xw_max + 0.1 * x_range) ranges.append((xw_min, xw_max)) return ranges wcsaxes-0.6/wcsaxes/coordinates_map.py0000644000077000000240000001132312553175753020165 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst from astropy.extern import six from .coordinate_helpers import CoordinateHelper from .transforms import WCSPixel2WorldTransform from .utils import coord_type_from_ctype from .frame import RectangularFrame from .coordinate_range import find_coordinate_range class CoordinatesMap(object): def __init__(self, axes, wcs=None, transform=None, coord_meta=None, slice=None, frame_class=RectangularFrame, previous_frame_path=None): # Keep track of parent axes and WCS self._axes = axes if wcs is None: if transform is None: raise ValueError("Either `wcs` or `transform` are required") if coord_meta is None: raise ValueError("`coord_meta` is required when " "`transform` is passed") self._transform = transform naxis = 2 else: if transform is not None: raise ValueError("Cannot specify both `wcs` and `transform`") if coord_meta is not None: raise ValueError("Cannot pass `coord_meta` if passing `wcs`") self._transform = WCSPixel2WorldTransform(wcs, slice=slice) naxis = wcs.wcs.naxis self.frame = frame_class(axes, self._transform, path=previous_frame_path) # Set up coordinates self._coords = [] self._aliases = {} for coord_index in range(naxis): # Extract coordinate metadata from WCS object or transform if wcs is not None: coord_type, coord_wrap = coord_type_from_ctype(wcs.wcs.ctype[coord_index]) coord_unit = wcs.wcs.cunit[coord_index] name = wcs.wcs.ctype[coord_index][:4].replace('-', '') else: try: coord_type = coord_meta['type'][coord_index] coord_wrap = coord_meta['wrap'][coord_index] coord_unit = coord_meta['unit'][coord_index] name = coord_meta['name'][coord_index] except IndexError: raise ValueError("coord_meta items should have a length of {0}".format(len(wcs.wcs.naxis))) self._coords.append(CoordinateHelper(parent_axes=axes, parent_map=self, transform=self._transform, coord_index=coord_index, coord_type=coord_type, coord_wrap=coord_wrap, coord_unit=coord_unit, frame=self.frame)) # Set up aliases for coordinates self._aliases[name.lower()] = coord_index def __getitem__(self, item): if isinstance(item, six.string_types): return self._coords[self._aliases[item.lower()]] else: return self._coords[item] def set_visible(self, visibility): raise NotImplementedError() def enable_offset_mode(self, reference_coordinates): raise NotImplementedError() def disable_offset_mode(self): raise NotImplementedError() def __iter__(self): for coord in self._coords: yield coord def grid(self, draw_grid=True, grid_type='lines', **kwargs): """ Plot gridlines for both coordinates. Standard matplotlib appearance options (color, alpha, etc.) can be passed as keyword arguments. Parameters ---------- draw_grid : bool Whether to show the gridlines grid_type : { 'lines' | 'contours' } Whether to plot the contours by determining the grid lines in world coordinates and then plotting them in world coordinates (``'lines'``) or by determining the world coordinates at many positions in the image and then drawing contours (``'contours'``). The first is recommended for 2-d images, while for 3-d (or higher dimensional) cubes, the ``'contours'`` option is recommended. """ for coord in self: coord.grid(draw_grid=draw_grid, grid_type=grid_type, **kwargs) def get_coord_range(self): xmin, xmax = self._axes.get_xlim() ymin, ymax = self._axes.get_ylim() return find_coordinate_range(self._transform, [xmin, xmax, ymin, ymax], [coord.coord_type for coord in self], [coord.coord_unit for coord in self]) wcsaxes-0.6/wcsaxes/core.py0000644000077000000240000003270712553175753015757 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst from matplotlib.axes import Axes, subplot_class_factory from matplotlib.transforms import Affine2D, Bbox, Transform from astropy.wcs import WCS from astropy.extern import six from .transforms import (WCSPixel2WorldTransform, WCSWorld2PixelTransform, CoordinateTransform) from .coordinates_map import CoordinatesMap from .utils import get_coord_meta from .wcs_utils import wcs_to_celestial_frame from .frame import RectangularFrame import numpy as np __all__ = ['WCSAxes', 'WCSAxesSubplot'] VISUAL_PROPERTIES = ['facecolor', 'edgecolor', 'linewidth', 'alpha', 'linestyle'] IDENTITY = WCS(naxis=2) IDENTITY.wcs.ctype = ["X", "Y"] IDENTITY.wcs.crval = [1., 1.] IDENTITY.wcs.crpix = [1., 1.] IDENTITY.wcs.cdelt = [1., 1.] class WCSAxes(Axes): def __init__(self, fig, rect, wcs=None, transform=None, coord_meta=None, transData=None, slices=None, frame_class=RectangularFrame, **kwargs): super(WCSAxes, self).__init__(fig, rect, **kwargs) self._bboxes = [] self.frame_class = frame_class if not (transData is None): # User wants to override the transform for the final # data->pixel mapping self.transData = transData self.reset_wcs(wcs=wcs, slices=slices, transform=transform, coord_meta=coord_meta) self._hide_parent_artists() self.format_coord = self._display_world_coords self._display_coords_index = 0 fig.canvas.mpl_connect('key_press_event', self._set_cursor_prefs) self.patch = self.coords.frame.patch self._drawn = False def _display_world_coords(self, x, y): if not self._drawn: return "" if self._display_coords_index == -1: return "%s %s (pixel)" % (x, y) pixel = np.array([x, y]) coords = self._all_coords[self._display_coords_index] world = coords._transform.transform(np.array([pixel]))[0] xw = coords[self._x_index].format_coord(world[self._x_index]) yw = coords[self._y_index].format_coord(world[self._y_index]) if self._display_coords_index == 0: system = "world" else: system = "world, overlay {0}".format(self._display_coords_index) coord_string = "%s %s (%s)" % (xw, yw, system) return coord_string def _set_cursor_prefs(self, event, **kwargs): if event.key == 'w': self._display_coords_index += 1 if self._display_coords_index + 1 > len(self._all_coords): self._display_coords_index = -1 def _hide_parent_artists(self): # Turn off spines and current axes for s in self.spines.values(): s.set_visible(False) self.xaxis.set_visible(False) self.yaxis.set_visible(False) # We now overload ``imshow`` because we need to make sure that origin is # set to ``lower`` for all images, which means that we need to flip RGB # images. def imshow(self, X, *args, **kwargs): """ Wrapper to Matplotlib's :meth:`~matplotlib.axes.Axes.imshow`. If an RGB image is passed as a PIL object, it will be flipped vertically and ``origin`` will be set to ``lower``, since WCS transformations - like FITS files - assume that the origin is the lower left pixel of the image (whereas RGB images have the origin in the top left). All arguments are passed to :meth:`~matplotlib.axes.Axes.imshow`. """ origin = kwargs.get('origin', None) if origin == 'upper': raise ValueError("Cannot use images with origin='upper' in WCSAxes.") # To check whether the image is a PIL image we can check if the data # has a 'getpixel' attribute - this is what Matplotlib's AxesImage does try: from PIL.Image import Image, FLIP_TOP_BOTTOM except ImportError: # We don't need to worry since PIL is not installed, so user cannot # have passed RGB image. pass else: if isinstance(X, Image) or hasattr(X, 'getpixel'): X = X.transpose(FLIP_TOP_BOTTOM) kwargs['origin'] = 'lower' return super(WCSAxes, self).imshow(X, *args, **kwargs) def reset_wcs(self, wcs=None, slices=None, transform=None, coord_meta=None): """ Reset the current Axes, to use a new WCS object. """ # Here determine all the coordinate axes that should be shown. if wcs is None and transform is None: self.wcs = IDENTITY else: # We now force call 'set', which ensures the WCS object is # consistent, which will only be important if the WCS has been set # by hand. For example if the user sets a celestial WCS by hand and # forgets to set the units, WCS.wcs.set() will do this. if wcs is not None: wcs.wcs.set() self.wcs = wcs # If we are making a new WCS, we need to preserve the path object since # it may already be used by objects that have been plotted, and we need # to continue updating it. CoordinatesMap will create a new frame # instance, but we can tell that instance to keep using the old path. if hasattr(self, 'coords'): previous_frame_path = self.coords.frame._path else: previous_frame_path = None self.coords = CoordinatesMap(self, wcs=self.wcs, slice=slices, transform=transform, coord_meta=coord_meta, frame_class=self.frame_class, previous_frame_path=previous_frame_path) self._all_coords = [self.coords] if slices is None: self.slices = ('x', 'y') self._x_index = 0 self._y_index = 1 else: self.slices = slices self._x_index = self.slices.index('x') self._y_index = self.slices.index('y') # Common default settings for Rectangular Frame if self.frame_class is RectangularFrame: for coord_index in range(len(self.slices)): if self.slices[coord_index] == 'x': self.coords[coord_index].set_axislabel_position('b') self.coords[coord_index].set_ticklabel_position('b') elif self.slices[coord_index] == 'y': self.coords[coord_index].set_axislabel_position('l') self.coords[coord_index].set_ticklabel_position('l') else: self.coords[coord_index].set_axislabel_position('') self.coords[coord_index].set_ticklabel_position('') self.coords[coord_index].set_ticks_position('') def draw(self, renderer, inframe=False): # We need to make sure that that frame path is up to date self.coords.frame._update_patch_path() super(WCSAxes, self).draw(renderer, inframe) # Here need to find out range of all coordinates, and update range for # each coordinate axis. For now, just assume it covers the whole sky. self._bboxes = [] self._ticklabels_bbox = [] visible_ticks = [] for coords in self._all_coords: coords.frame.update() for coord in coords: coord._draw(renderer, bboxes=self._bboxes, ticklabels_bbox=self._ticklabels_bbox) visible_ticks.extend(coord.ticklabels.get_visible_axes()) for coords in self._all_coords: for coord in coords: coord._draw_axislabels(renderer, bboxes=self._bboxes, ticklabels_bbox=self._ticklabels_bbox, visible_ticks=visible_ticks) self.coords.frame.draw(renderer) self._drawn = True def set_xlabel(self, label): self.coords[self._x_index].set_axislabel(label) def set_ylabel(self, label): self.coords[self._y_index].set_axislabel(label) def get_xlabel(self): return self.coords[self._x_index].get_axislabel() def get_ylabel(self): return self.coords[self._y_index].get_axislabel() def get_coords_overlay(self, frame, coord_meta=None): # Here we can't use get_transform because that deals with # pixel-to-pixel transformations when passing a WCS object. if isinstance(frame, WCS): coords = CoordinatesMap(self, frame, frame_class=self.frame_class) else: if coord_meta is None: coord_meta = get_coord_meta(frame) transform = self._get_transform_no_transdata(frame) coords = CoordinatesMap(self, transform=transform, coord_meta=coord_meta, frame_class=self.frame_class) self._all_coords.append(coords) # Common settings for overlay coords[0].set_axislabel_position('t') coords[1].set_axislabel_position('r') coords[0].set_ticklabel_position('t') coords[1].set_ticklabel_position('r') self.overlay_coords = coords return coords def get_transform(self, frame): """ Return a transform from the specified frame to display coordinates. This does not include the transData transformation Parameters ---------- frame : :class:`~astropy.wcs.WCS` or :class:`~matplotlib.transforms.Transform` or str The ``frame`` parameter can have several possible types: * :class:`~astropy.wcs.WCS` instance: assumed to be a transformation from pixel to world coordinates, where the world coordinates are the same as those in the WCS transformation used for this ``WCSAxes`` instance. This is used for example to show contours, since this involves plotting an array in pixel coordinates that are not the final data coordinate and have to be transformed to the common world coordinate system first. * :class:`~matplotlib.transforms.Transform` instance: it is assumed to be a transform to the world coordinates that are part of the WCS used to instantiate this ``WCSAxes`` instance. * ``'pixel'`` or ``'world'``: return a transformation that allows users to plot in pixel/data coordinates (essentially an identity transform) and ``world`` (the default world-to-pixel transformation used to instantiate the ``WCSAxes`` instance). * ``'fk5'`` or ``'galactic'``: return a transformation from the specified frame to the pixel/data coordinates. * :class:`~astropy.coordinates.BaseCoordinateFrame` instance. """ return self._get_transform_no_transdata(frame).inverted() + self.transData def _get_transform_no_transdata(self, frame): """ Return a transform from data to the specified frame """ if self.wcs is None and frame != 'pixel': raise ValueError('No WCS specified, so only pixel coordinates are available') if isinstance(frame, WCS): coord_in = wcs_to_celestial_frame(self.wcs) coord_out = wcs_to_celestial_frame(frame) if coord_in == coord_out: return (WCSPixel2WorldTransform(self.wcs, slice=self.slices) + WCSWorld2PixelTransform(frame)) else: return (WCSPixel2WorldTransform(self.wcs, slice=self.slices) + CoordinateTransform(self.wcs, frame) + WCSWorld2PixelTransform(frame)) elif frame == 'pixel': return Affine2D() elif isinstance(frame, Transform): pixel2world = WCSPixel2WorldTransform(self.wcs, slice=self.slices) return pixel2world + frame else: pixel2world = WCSPixel2WorldTransform(self.wcs, slice=self.slices) if frame == 'world': return pixel2world else: coordinate_transform = CoordinateTransform(self.wcs, frame) if coordinate_transform.same_frames: return pixel2world else: return pixel2world + CoordinateTransform(self.wcs, frame) def get_tightbbox(self, renderer): if not self.get_visible(): return bb = [b for b in self._bboxes if b and (b.width != 0 or b.height != 0)] if bb: _bbox = Bbox.union(bb) return _bbox else: return self.get_window_extent(renderer) def grid(self, draw_grid=True, **kwargs): """ Plot gridlines for both coordinates. Standard matplotlib appearance options (color, alpha, etc.) can be passed as keyword arguments. Parameters ---------- draw_grid : bool Whether to show the gridlines """ if draw_grid and hasattr(self, 'coords'): self.coords.grid(draw_grid=draw_grid, **kwargs) # In the following, we put the generated subplot class in a temporary class and # we then inherit it - if we don't do this, the generated class appears to # belong in matplotlib, not in WCSAxes, from the API's point of view. class WCSAxesSubplot(subplot_class_factory(WCSAxes)): pass wcsaxes-0.6/wcsaxes/datasets/0000755000077000000240000000000012553237435016250 5ustar tomstaff00000000000000wcsaxes-0.6/wcsaxes/datasets/__init__.py0000644000077000000240000000236412441052514020353 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """Downloads the FITS files that are used in image testing and for building documentation. """ from astropy.utils.data import download_file from astropy.io import fits __all__ = ['fetch_msx_hdu', 'fetch_rosat_hdu', 'fetch_twoMASS_k_hdu', 'fetch_l1448_co_hdu', 'fetch_bolocam_hdu', ] URL = 'http://data.astropy.org/' def fetch_hdu(filename, cache=True): """Download a FITS file to the cache and open HDU 0. """ path = download_file(URL + filename, cache=cache) return fits.open(path)[0] def fetch_msx_hdu(cache=True): """Fetch the MSX example dataset HDU. Returns ------- hdu : `~astropy.io.fits.ImageHDU` Image HDU """ return fetch_hdu('galactic_center/gc_msx_e.fits', cache=cache) def fetch_rosat_hdu(cache=True): return fetch_hdu('allsky/allsky_rosat.fits', cache=cache) def fetch_twoMASS_k_hdu(cache=True): return fetch_hdu('galactic_center/gc_2mass_k.fits', cache=cache) def fetch_l1448_co_hdu(cache=True): return fetch_hdu('l1448/l1448_13co.fits', cache=cache) def fetch_bolocam_hdu(cache=True): return fetch_hdu('galactic_center/gc_bolocam_gps.fits', cache=cache) wcsaxes-0.6/wcsaxes/formatter_locator.py0000644000077000000240000003533612471145036020544 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst # This file defines the AngleFormatterLocator class which is a class that # provides both a method for a formatter and one for a locator, for a given # label spacing. The advantage of keeping the two connected is that we need to # make sure that the formatter can correctly represent the spacing requested and # vice versa. For example, a format of dd:mm cannot work with a tick spacing # that is not a multiple of one arcminute. import re import warnings import numpy as np from matplotlib import rcParams from astropy.extern import six from astropy import units as u from astropy.coordinates import Angle DMS_RE = re.compile('^dd(:mm(:ss(.(s)+)?)?)?$') HMS_RE = re.compile('^hh(:mm(:ss(.(s)+)?)?)?$') DDEC_RE = re.compile('^d(.(d)+)?$') DMIN_RE = re.compile('^m(.(m)+)?$') DSEC_RE = re.compile('^s(.(s)+)?$') SCAL_RE = re.compile('^x(.(x)+)?$') class BaseFormatterLocator(object): """ A joint formatter/locator """ def __init__(self, values=None, number=None, spacing=None, format=None): if (values, number, spacing).count(None) < 2: raise ValueError("At most one of values/number/spacing can be specifed") if values is not None: self.values = values elif number is not None: self.number = number elif spacing is not None: self.spacing = spacing else: self.number = 5 self.format = format @property def values(self): return self._values @values.setter def values(self, values): if not isinstance(values, u.Quantity) or (not values.ndim == 1): raise TypeError("values should be an astropy.units.Quantity array") self._number = None self._spacing = None self._values = values @property def number(self): return self._number @number.setter def number(self, number): self._number = number self._spacing = None self._values = None @property def spacing(self): return self._spacing @spacing.setter def spacing(self, spacing): self._number = None self._spacing = spacing self._values = None def minor_locator(self, spacing, frequency, value_min, value_max): if self.values is not None: return [] * self._unit minor_spacing = spacing.value / frequency values = self._locate_values(value_min, value_max, minor_spacing) index = np.where((values % frequency) == 0) index = index[0][0] values = np.delete(values, np.s_[index::frequency]) return values * minor_spacing * self._unit def _locate_values(self, value_min, value_max, spacing): imin = np.ceil(value_min / spacing) imax = np.floor(value_max / spacing) values = np.arange(imin, imax + 1, dtype=int) return values class AngleFormatterLocator(BaseFormatterLocator): """ A joint formatter/locator """ def __init__(self, values=None, number=None, spacing=None, format=None): self._unit = u.degree self._sep = None super(AngleFormatterLocator, self).__init__(values=values, number=number, spacing=spacing, format=format) @property def spacing(self): return self._spacing @spacing.setter def spacing(self, spacing): if spacing is not None and (not isinstance(spacing, u.Quantity) or spacing.unit.physical_type != 'angle'): raise TypeError("spacing should be an astropy.units.Quantity instance with units of angle") self._number = None self._spacing = spacing self._values = None @property def sep(self): return self._sep @sep.setter def sep(self, separator): self._sep = separator @property def format(self): return self._format @format.setter def format(self, value): self._format = value if value is None: return if DMS_RE.match(value) is not None: self._decimal = False self._unit = u.degree if '.' in value: self._precision = len(value) - value.index('.') - 1 self._fields = 3 else: self._precision = 0 self._fields = value.count(':') + 1 elif HMS_RE.match(value) is not None: self._decimal = False self._unit = u.hourangle if '.' in value: self._precision = len(value) - value.index('.') - 1 self._fields = 3 else: self._precision = 0 self._fields = value.count(':') + 1 elif DDEC_RE.match(value) is not None: self._decimal = True self._unit = u.degree self._fields = 1 if '.' in value: self._precision = len(value) - value.index('.') - 1 else: self._precision = 0 elif DMIN_RE.match(value) is not None: self._decimal = True self._unit = u.arcmin self._fields = 1 if '.' in value: self._precision = len(value) - value.index('.') - 1 else: self._precision = 0 elif DSEC_RE.match(value) is not None: self._decimal = True self._unit = u.arcsec self._fields = 1 if '.' in value: self._precision = len(value) - value.index('.') - 1 else: self._precision = 0 else: raise ValueError("Invalid format: {0}".format(value)) if self.spacing is not None and self.spacing < self.base_spacing: warnings.warn("Spacing is too small - resetting spacing to match format") self.spacing = self.base_spacing if self.spacing is not None: ratio = (self.spacing / self.base_spacing).decompose().value remainder = ratio - np.round(ratio) if abs(remainder) > 1.e-10: warnings.warn("Spacing is not a multiple of base spacing - resetting spacing to match format") self.spacing = self.base_spacing * max(1, round(ratio)) @property def base_spacing(self): if self._decimal: spacing = self._unit / (10. ** self._precision) else: if self._fields == 1: spacing = 1. * u.degree elif self._fields == 2: spacing = 1. * u.arcmin elif self._fields == 3: if self._precision == 0: spacing = 1. * u.arcsec else: spacing = u.arcsec / (10. ** self._precision) if self._unit is u.hourangle: spacing *= 15 return spacing def locator(self, value_min, value_max): if self.values is not None: # values were manually specified return self.values, 1.1 * u.arcsec else: if self.spacing is not None: # spacing was manually specified spacing_deg = self.spacing.to(u.degree).value elif self.number is not None: # number of ticks was specified, work out optimal spacing # first compute the exact spacing dv = abs(float(value_max - value_min)) / self.number * u.degree if self.format is not None and dv < self.base_spacing: # if the spacing is less than the minimum spacing allowed by the format, simply # use the format precision instead. spacing_deg = self.base_spacing.to(u.degree).value else: # otherwise we clip to the nearest 'sensible' spacing if self._unit is u.degree: from .utils import select_step_degree spacing_deg = select_step_degree(dv).to(u.degree).value else: from .utils import select_step_hour spacing_deg = select_step_hour(dv).to(u.degree).value # We now find the interval values as multiples of the spacing and # generate the tick positions from this. values = self._locate_values(value_min, value_max, spacing_deg) return values * spacing_deg * u.degree, spacing_deg * u.degree def formatter(self, values, spacing): if not isinstance(values, u.Quantity) and values is not None: raise TypeError("values should be a Quantities array") if len(values) > 0: if self.format is None: spacing = spacing.to(u.arcsec).value if spacing > 3600: fields = 1 precision = 0 elif spacing > 60: fields = 2 precision = 0 elif spacing > 1: fields = 3 precision = 0 else: fields = 3 precision = -int(np.floor(np.log10(spacing))) decimal = False unit = u.degree else: fields = self._fields precision = self._precision decimal = self._decimal unit = self._unit if decimal: sep = None elif self._sep is not None: sep = self._sep else: if unit == u.degree: if rcParams['text.usetex']: deg = r'$^\circ$' else: deg = six.u('\xb0') sep = (deg, "'", '"') else: sep = ('h', 'm', 's') angles = Angle(values) string = angles.to_string(unit=unit, precision=precision, decimal=decimal, fields=fields, sep=sep).tolist() return string else: return [] class ScalarFormatterLocator(BaseFormatterLocator): """ A joint formatter/locator """ def __init__(self, values=None, number=None, spacing=None, format=None, unit=None): if unit is not None: self._unit = unit self._format_unit = unit elif spacing is not None: self._unit = spacing.unit self._format_unit = spacing.unit elif values is not None: self._unit = values.unit self._format_unit = values.unit super(ScalarFormatterLocator, self).__init__(values=values, number=number, spacing=spacing, format=format) @property def format_unit(self): return self._format_unit @format_unit.setter def format_unit(self, unit): if (not issubclass(unit.__class__, u.UnitBase)): raise TypeError("unit should be an astropy UnitBase subclass") self._format_unit = unit @property def spacing(self): return self._spacing @spacing.setter def spacing(self, spacing): if spacing is not None and not isinstance(spacing, u.Quantity): raise TypeError("spacing should be an astropy.units.Quantity instance") self._number = None self._spacing = spacing self._values = None @property def format(self): return self._format @format.setter def format(self, value): self._format = value if value is None: return if SCAL_RE.match(value) is not None: if '.' in value: self._precision = len(value) - value.index('.') - 1 else: self._precision = 0 if self.spacing is not None and self.spacing < self.base_spacing: warnings.warn("Spacing is too small - resetting spacing to match format") self.spacing = self.base_spacing if self.spacing is not None: ratio = (self.spacing / self.base_spacing).decompose().value remainder = ratio - np.round(ratio) if abs(remainder) > 1.e-10: warnings.warn("Spacing is not a multiple of base spacing - resetting spacing to match format") self.spacing = self.base_spacing * max(1, round(ratio)) elif not value.startswith('%'): raise ValueError("Invalid format: {0}".format(value)) @property def base_spacing(self): return self._unit / (10. ** self._precision) def locator(self, value_min, value_max): if self.values is not None: # values were manually specified return self.values, 1.1 * self._unit else: if self.spacing is not None: # spacing was manually specified spacing = self.spacing.to(self._unit).value elif self.number is not None: # number of ticks was specified, work out optimal spacing # first compute the exact spacing dv = abs(float(value_max - value_min)) / self.number if self.format is not None and (not self.format.startswith('%')) and dv < self.base_spacing.value: # if the spacing is less than the minimum spacing allowed by the format, simply # use the format precision instead. spacing = self.base_spacing.to(self._unit).value else: from .utils import select_step_scalar spacing = select_step_scalar(dv) # We now find the interval values as multiples of the spacing and # generate the tick positions from this values = self._locate_values(value_min, value_max, spacing) return values * spacing * self._unit, spacing * self._unit def formatter(self, values, spacing): if len(values) > 0: if self.format is None: if spacing.value < 1.: precision = -int(np.floor(np.log10(spacing.value))) else: precision = 0 elif self.format.startswith('%'): return [(self.format % x.value) for x in values] else: precision = self._precision return [("{0:." + str(precision) + "f}").format(x.to(self._format_unit).value) for x in values] else: return [] wcsaxes-0.6/wcsaxes/frame.py0000644000077000000240000001327712441052514016103 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import abc import numpy as np from astropy.utils import OrderedDict from astropy.extern import six from matplotlib.lines import Line2D, Path from matplotlib.patches import PathPatch __all__ = ['Spine', 'BaseFrame', 'RectangularFrame', 'EllipticalFrame'] class Spine(object): def __init__(self, parent_axes, transform): self.parent_axes = parent_axes self.transform = transform self.data = None self.pixel = None self.world = None @property def data(self): return self._data @data.setter def data(self, value): if value is None: self._data = None self._pixel = None self._world = None else: self._data = value self._pixel = self.parent_axes.transData.transform(self._data) self._world = self.transform.transform(self._data) self._update_normal() @property def pixel(self): return self._pixel @pixel.setter def pixel(self, value): if value is None: self._data = None self._pixel = None self._world = None else: self._data = self.parent_axes.transData.inverted().transform(self._data) self._pixel = value self._world = self.transform.transform(self._data) self._update_normal() @property def world(self): return self._world @world.setter def world(self, value): if value is None: self._data = None self._pixel = None self._world = None else: self._data = self.transform.transform(value) self._pixel = self.parent_axes.transData.transform(self._data) self._world = value self._update_normal() def _update_normal(self): # Find angle normal to border and inwards, in display coordinate dx = self.pixel[1:, 0] - self.pixel[:-1, 0] dy = self.pixel[1:, 1] - self.pixel[:-1, 1] self.normal_angle = np.degrees(np.arctan2(dx, -dy)) @six.add_metaclass(abc.ABCMeta) class BaseFrame(OrderedDict): def __init__(self, parent_axes, transform, path=None): super(BaseFrame, self).__init__() self.parent_axes = parent_axes self._transform = transform self._linewidth = None self._color = 'black' self._path = path for axis in self.spine_names: self[axis] = Spine(parent_axes, transform) @property def origin(self): ymin, ymax = self.parent_axes.get_ylim() return 'lower' if ymin < ymax else 'upper' @property def transform(self): return self._transform @transform.setter def transform(self, value): self._transform = value for axis in self: self[axis].transform = value def _update_patch_path(self): self.update_spines() x, y = [], [] for axis in self: x.append(self[axis].data[:, 0]) y.append(self[axis].data[:, 1]) vertices = np.vstack([np.hstack(x), np.hstack(y)]).transpose() if self._path is None: self._path = Path(vertices) else: self._path.vertices = vertices @property def patch(self): self._update_patch_path() return PathPatch(self._path, transform=self.parent_axes.transData, facecolor='white', edgecolor='white') def draw(self, renderer): for axis in self: x, y = self[axis].pixel[:, 0], self[axis].pixel[:, 1] line = Line2D(x, y, linewidth=self._linewidth, color=self._color, zorder=1000) line.draw(renderer) def sample(self, n_samples): self.update_spines() spines = OrderedDict() for axis in self: data = self[axis].data p = np.linspace(0., 1., data.shape[0]) p_new = np.linspace(0., 1., n_samples) spines[axis] = Spine(self.parent_axes, self.transform) spines[axis].data = np.array([np.interp(p_new, p, data[:, 0]), np.interp(p_new, p, data[:, 1])]).transpose() return spines def set_color(self, color): """ Sets the color of the frame. Parameters ---------- color : string The color of the frame. """ self._color = color def set_linewidth(self, linewidth): """ Sets the linewidth of the frame. Parameters ---------- linewidth : float The linewidth of the frame in points. """ self._linewidth = linewidth @abc.abstractmethod def update_spines(self): raise NotImplementedError("") class RectangularFrame(BaseFrame): spine_names = 'brtl' def update_spines(self): xmin, xmax = self.parent_axes.get_xlim() ymin, ymax = self.parent_axes.get_ylim() self['b'].data = np.array(([xmin, ymin], [xmax, ymin])) self['r'].data = np.array(([xmax, ymin], [xmax, ymax])) self['t'].data = np.array(([xmax, ymax], [xmin, ymax])) self['l'].data = np.array(([xmin, ymax], [xmin, ymin])) class EllipticalFrame(BaseFrame): spine_names = 'c' def update_spines(self): xmin, xmax = self.parent_axes.get_xlim() ymin, ymax = self.parent_axes.get_ylim() xmid = 0.5 * (xmax + xmin) ymid = 0.5 * (ymax + ymin) dx = xmid - xmin dy = ymid - ymin theta = np.linspace(0., 2 * np.pi, 1000) self['c'].data = np.array([xmid + dx * np.cos(theta), ymid + dy * np.sin(theta)]).transpose() wcsaxes-0.6/wcsaxes/grid_paths.py0000644000077000000240000000745412552423430017137 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import numpy as np from matplotlib.lines import Path from astropy.coordinates.angle_utilities import angular_separation # Tolerance for WCS round-tripping ROUND_TRIP_TOL = 1e-1 # Tolerance for discontinuities relative to the median DISCONT_FACTOR = 10. def get_lon_lat_path(lon_lat, pixel, lon_lat_check): """ Draw a curve, taking into account discontinuities. Parameters ---------- lon_lat : `~numpy.ndarray` The longitude and latitude values along the curve, given as a (n,2) array. pixel : `~numpy.ndarray` The pixel coordinates corresponding to ``lon_lat`` lon_lat : `~numpy.ndarray` The world coordinates derived from converting from ``pixel``, which is used to ensure round-tripping. """ # In some spherical projections, some parts of the curve are 'behind' or # 'in front of' the plane of the image, so we find those by reversing the # transformation and finding points where the result is not consistent. sep = angular_separation(np.radians(lon_lat[:, 0]), np.radians(lon_lat[:, 1]), np.radians(lon_lat_check[:, 0]), np.radians(lon_lat_check[:, 1])) with np.errstate(invalid='ignore'): sep[sep > np.pi] -= 2. * np.pi mask = np.abs(sep > ROUND_TRIP_TOL) # Mask values with invalid pixel positions mask = mask | np.isnan(pixel[:, 0]) | np.isnan(pixel[:, 1]) # We can now start to set up the codes for the Path. codes = np.zeros(lon_lat.shape[0], dtype=np.uint8) codes[:] = Path.LINETO codes[0] = Path.MOVETO codes[mask] = Path.MOVETO # Also need to move to point *after* a hidden value codes[1:][mask[:-1]] = Path.MOVETO # We now go through and search for discontinuities in the curve that would # be due to the curve going outside the field of view, invalid WCS values, # or due to discontinuities in the projection. # We start off by pre-computing the step in pixel coordinates from one # point to the next. The idea is to look for large jumps that might indicate # discontinuities. step = np.sqrt((pixel[1:, 0] - pixel[:-1, 0]) ** 2 + (pixel[1:, 1] - pixel[:-1, 1]) ** 2) # We search for discontinuities by looking for places where the step # is larger by more than a given factor compared to the median # discontinuous = step > DISCONT_FACTOR * np.median(step) discontinuous = step[1:] > DISCONT_FACTOR * step[:-1] # Skip over discontinuities codes[2:][discontinuous] = Path.MOVETO # The above missed the first step, so check that too if step[0] > DISCONT_FACTOR * step[1]: codes[1] = Path.MOVETO # Create the path path = Path(pixel, codes=codes) return path def get_gridline_path(world, pixel): """ Draw a grid line Parameters ---------- lon_lat : `~numpy.ndarray` The longitude and latitude values along the curve, given as a (n,2) array. pixel : `~numpy.ndarray` The pixel coordinates corresponding to ``lon_lat`` """ # Mask values with invalid pixel positions mask = np.isnan(pixel[:, 0]) | np.isnan(pixel[:, 1]) # We can now start to set up the codes for the Path. codes = np.zeros(world.shape[0], dtype=np.uint8) codes[:] = Path.LINETO codes[0] = Path.MOVETO codes[mask] = Path.MOVETO # Also need to move to point *after* a hidden value codes[1:][mask[:-1]] = Path.MOVETO # We now go through and search for discontinuities in the curve that would # be due to the curve going outside the field of view, invalid WCS values, # or due to discontinuities in the projection. # Create the path path = Path(pixel, codes=codes) return path wcsaxes-0.6/wcsaxes/rc_utils.py0000644000077000000240000000102012441052514016614 0ustar tomstaff00000000000000""" This is a backport of the rc_context class from matplotlib 1.2. """ from matplotlib import rcParams try: from matplotlib import rc_context except ImportError: class rc_context(object): def __init__(self, rc=None): self.rcdict = rc self._rcparams = rcParams.copy() if self.rcdict: rcParams.update(self.rcdict) def __enter__(self): return self def __exit__(self, type, value, tb): rcParams.update(self._rcparams) wcsaxes-0.6/wcsaxes/settings.py0000644000077000000240000000022112547635014016643 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst COORDINATE_RANGE_SAMPLES = 50 FRAME_BOUNDARY_SAMPLES = 1000 GRID_SAMPLES = 1000 wcsaxes-0.6/wcsaxes/tests/0000755000077000000240000000000012553237435015602 5ustar tomstaff00000000000000wcsaxes-0.6/wcsaxes/tests/__init__.py0000644000077000000240000000000012436367710017701 0ustar tomstaff00000000000000wcsaxes-0.6/wcsaxes/tests/baseline_images/0000755000077000000240000000000012553237435020711 5ustar tomstaff00000000000000wcsaxes-0.6/wcsaxes/tests/baseline_images/changed_axis_units.png0000644000077000000240000003054512436367710025265 0ustar tomstaff00000000000000‰PNG  IHDR Xšv‚psBIT|dˆ pHYsaa¨?§i IDATxœíÝ{”Wu¡ÿÿ× L@Ü(A"ˆã%Q‚—E%»áJ$:F'Sµ:žååTtñvÔ“æÉ¼$v–ÁÊË /hŠZž $š¨èX i ƒ"|~ôc¾N ïÑ™Çc­Y,ÞŸ÷ÞŸ÷Þkòœ½÷gª*•J%T7÷€ÖC€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å´mî-×Ê•+s÷Ýw§_¿~éСCs/Ø õõõY¶lYŽ9æ˜ôèÑ£¹—´@Øi®¹æšœ{î¹Í½ `;ÜtÓM9餓š{@ $@€æÕW_M’œzê©ùâ¿Ølë˜9sfÎ?ÿüLž<9Ç{¬uXÇ;j ïÄu$I¿~ýšm@Ë&@€¦¦¦&IÒ»wï 4¨ÙÖ±xñâ$Iÿþý­Ã:Þqkx'®#‰Û&ÆCè@1(F€Å`§0`@£?›ËÀ3tèÐ 8Ð:¬ã·†wÚ:šó u¨ªT*•æ^Ð2Í›7/ƒΣ>ê5ð.áûØÙ\Š @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒ‚-Z”Q£FeÀ€騱cjkk3dÈL›6­ÉÜÅ‹gøðáéܹsjkk3vìØ¬\¹²É¼^x!ÇsL:uê”1cƤ¾¾¾ÑëãÆKuuu“¯øÃ›]ãµ×^›øÃéСCöØc\yå•Mæ|ãßHÿþý·ó,­YÛæ^´&Ï<óLÖ¬Y“qãÆ¥wïÞY»vm¦OŸž“O>9Ë–-˹瞛$Y¾|y;ì°tïÞ=S§NÍêÕ«sÑEeáÂ…™3gNjjjöùÅ/~1ëׯÏE]”«¯¾:çž{n.¹ä’FïÛ®]»\{íµÆºvíÚd}?üásê©§æ3ŸùL¾úÕ¯æÁÌgœ‘µk׿ë_ÿz£¹UUU;ê´­ˆ‚FŒ‘#F4;í´Ó2xðà\sÍ5 2eÊ”Ô××gþüùéÓ§O’äàƒÎQG•믿>ãÇO’¬[·.÷ßþô§?¥S§N9òÈ#sä‘G6 ššš|îsŸ{ÓµÕ××çÜsÏÍÈ‘#sË-·$IN9å”lܸ1“'OΗ¾ô¥tëÖ­a~¥Ry{'h•Ü‚ͬºº:}úôitUcÆŒ9rdC|$ɰaòÇ{4ÄA’¬]»6íÚµK§N’$={öÌš5kš¼G¥RÉÆó׿þu‹ë¸ÿþû³jÕª|å+_i4~Úi§å•W^É/~ñ‹í>F€M4ƒµk×fåÊ•yòÉ's饗æî»ïn¸Åé¹çžËŠ+rà6Ùî ƒÊüùóþ¾Ë.»ä}ï{_.¸à‚<õÔSùêW¿šC=t³ï×¥K—tëÖ-µµµ9ýôÓóÊ+¯4š³i¿ÿ¾ƒ Juuu,XÐ0VUUå,`»¸ šÁYg•k®¹&IÒ¶mÛ\~ùåùÒ—¾”$©««K’ôêÕ«Év½zõʪU«²~ýú†+&W]uU>ùÉOæÂ /Ì>ðÌš5«Ñ6½{÷οýÛ¿eРAÙ¸qcî¼óÎüà?Èc=–x mÚ´ixß6mÚ¤G¶Ï{Þ“ÚÚÚ<ÿüó cÿñÿ‘ÿøÿØAghM4ƒ3Ï<3ŸýìgóüóÏgÚ´i9ýôÓÓ¡C‡|þóŸoø«víÚ5Ù®}ûöIþö¼Æ¦9âˆ#òÌ3Ïä‰'žÈ>ûìÓd»)S¦4úûg?ûÙì±Ç9÷Üs3}úôŒ=ºaŸïyÏ{6»ÞvíÚ5ùt-€íá,h{î¹gŽ<òÈŒ3&wÞyg† –I“&eݺuéСC’äÕW_m²Ýºuë’¤aÎ&]»vÍàÁƒ7-›sæ™g¦ºº:÷Ýw_ÃX‡òÚk¯mvþ×ðv¸ï'œpBfÍš•%K–4ÜzµéV¬7ª««Kmmm£Ö·Gûöí³Ë.»dÕªU c½zõʆ ²råÊF·a½öÚkYµjUz÷î½Ýï7sæÌ,^¼¸ÑØÀ³ÿþûo÷>·oÁ‚Y´hQ£±§žzª™V´Þ6ÝÞT]]ÝvÛ-={öÌܹs›Ì›3gÎùGûêÕ«³råÊôìÙ³aì€H’Ì;·ÑGÿö·¿ÍÆßÖûžþùMƆšx`»÷ ¼}“&MÊìÙ³›{@+#@  +V4úG’¬_¿>7Þxcjkk3pàÀ$»"rà 7dùòå Å{ß}÷eéÒ¥9ûì³·úý^}õÕ¼öÚkéܹs£ñÉ“''I†Þ0vä‘Gf—]vÉUW]Õ(@®ºêªtìØ1Çwܶìß½ßßÿæôMÇ 4ŸË.»l³W@6÷C€¥ªâ·‰A1ŸúÔ§²zõêvØaéÝ»w^xá…L›6-?þx®»îºŒ;6Éß~únݺeâĉY½zu¾ÿýï§oß¾™;wîVß‚µlÙ²pÀùÜç>—=÷Ü3Ir÷ÝwçÎ;ï̈#šün«®º*§vZ>ó™Ïäè£ÎC=”Ÿüä'™2eJÎ9çœm>ÞyóæeðàÁyôÑG3hРmÞ(Ï÷-°³¹x≹öÚksÕUWåÅ_L—.]rÈ!‡äÊ+¯Ì°aÃæõéÓ'³gÏÎYg•sÎ9'íÚµËÈ‘#sñÅoÓóÝ»wÏñÇŸY³få†nȆ ²ûî»gêÔ©ùêW¿Údþ©§žšššš\|ñŹýöÛÓ·oß\vÙe9ãŒ3vÈñ¸ì4~’ ï>¾oÍÇðÅ #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1Z¡oûÛ©®®Î¾ûîÛäµÅ‹gøðáéܹsjkk3vìØ¬\¹²ÑœeË–¥ºº:>ø`©%-DÛæ^PÖòåË3eÊ”tìØ1UUUM^;ì°ÃÒ½{÷L:5«W¯ÎE]”… fΜ9©©©i¦U-…Væ«_ýj† ’×_½É•)S¦¤¾¾>óçÏOŸ>}’$|pŽ:ê¨\ýõ?~|s,hAÜ‚­Èƒ>˜3fä²Ë.K¥RirdÆŒ9rdC|$ɰaòÇ{ä–[n)½\  ÐJlذ!&LÈøñã3pàÀ&¯?÷ÜsY±bE<ðÀ&¯tÐA™?~£±¿€­á,h%®¾úê<óÌ3ùå/¹Ù×ëêê’$½zõjòZ¯^½²jÕª¬_¿>555éׯ_6lذS× ´L®€@+ðâ‹/æ‚ .È\ÚÚÚÍΩ¯¯O’´k×®ÉkíÛ·o4`{ hÎ;ï¼ôèÑ#&LØâœ:$I^}õÕ&¯­[·®Ñ€íå,há–.]šÿþïÿÎe—]–åË—7Œ¯[·.¯½öZž~úétéÒ¥áÖ«M·b½Q]]]jkk·ûcxgΜ™Å‹78p`ößÿíÚ°c,X° ‹-j4öÔSO5Ój€ÖB€@ ÷ÜsÏeãÆ9ãŒ3rÆg4y½ÿþ™4iR.¹ä’ôìÙ3sçÎm2gΜ9o+Î?ÿü&cC‡Í<°ÝûÞ¾I“&eöìÙͽ  • ÐÂí»ï¾ùùÏÞèS«*•JÎ;LY³&ÿùŸÿ™$IN8á„Üpà Y¾|yÃGñÞwß}YºtiÎ>ûìí^ÃäɓӿÿFc›û$. ¬Ë.»l³W@6÷C€¥ªR©Tš{@y‡~x^|ñÅ,\¸°alùòå9à€Ò­[·Lœ81«W¯Î÷¿ÿýôíÛ7sçÎÝæ[°æÍ›—ÁƒçÑGÍ Aƒvô!;ï[`gó:´RUUUM~—GŸ>}2{öì 0 çœsN.ºè¢Œ92³fÍÚîç?ÞÈ-XÐJÝÿý›ß{ï½s×]w^ ÐZ¸#@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Åh-Z”Q£FeÀ€騱cjkk3dÈL›6­ÉÜÅ‹gøðáéܹsjkk3vìØ¬\¹²ÑœeË–¥ºº:>ø`©CZˆ¶Í½`ç{æ™g²fÍšŒ7.½{÷ÎÚµk3}úôœ|òÉY¶lYÎ=÷Ü$ÉòåËsØa‡¥{÷î™:ujV¯^‹.º( .Ìœ9sRSSÓÌG¼Û hFŒ‘#F4;í´Ó2xðà\sÍ5 2eÊ”Ô××gþüùéÓ§O’äàƒÎQG•믿>ãÇ/¾v eq ´RÕÕÕéÓ§O£«3fÌÈÈ‘#â#I† –=öØ#·ÜrKs,ha\VdíÚµY»vm^~ùåÜ~ûí¹ûî»så•W&Iž{X±"x`“í:è ÜyçÆªªªŠ¬hY´"guV®¹æš$IÛ¶msùå—çK_úR’¤®®.IÒ«W¯&ÛõêÕ+«V­ÊúõëSSS“~ýúeÆ å´Z‘3Ï<3ŸýìgóüóÏgÚ´i9ýôÓÓ¡C‡|þóŸO}}}’¤]»vM¶kß¾}’¤¾¾ÞƒèÀÛ"@ ÙsÏ=³çž{&IÆŒ“cŽ9&“&MÊèÑ£Ó¡C‡$É«¯¾Úd»uëÖ%IÀí%@ ;á„2kÖ¬,Y²¤áÖ«M·b½Q]]]jkk·ûêÇÌ™3³xñâFcÌþûï¿]ûvŒ dÑ¢EÆžzê©fZ ÐZhÅ6ÝvU]]ÝvÛ-={öÌܹs›Ì›3gÎÛŠ…óÏ?¿ÉØÐ¡CóÀl÷>·oÒ¤I™={vs/he´+V¬HÏž=­_¿>7Þxcjkk3pàÀ$»"rà 7dùòå Å{ß}÷eéÒ¥9ûì³·ûý'Ožœþýû7Ûôž@ó¹ì²Ë6{ds?4ØQª*•J¥¹ì\ŸúÔ§²zõêvØaéÝ»w^xá…L›6-?þx®»îºŒ;6Éß~únݺeâĉY½zu¾ÿýï§oß¾™;wî6ß‚5oÞ¼ <8>úh ´3 ØÁ|ß;›+ Ð œx≹öÚksÕUWåÅ_L—.]rÈ!‡äÊ+¯Ì°aÃæõéÓ'³gÏÎYg•sÎ9'íÚµËÈ‘#sñÅûô+`‡ Ð Œ=:£GÞª¹{ï½wîºë®¼" µªnî­‡Š @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@€bPŒŠ @1(F€Å #@ ˜;wnN?ýô 80:uÊ?øÁŒ=:K—.m2wñâÅ>|x:wîœÚÚÚŒ;6+W®l4gÙ²e©®®Îƒ>Xꀢms/Øù¾ûÝïæ‘GɨQ£²ß~û¥®®.W^ye ”ÿû¿ÿËÀ“$Ë—/Ïa‡–îÝ»gêÔ©Y½zu.ºè¢,\¸0sæÌIMMM3 ðn'@ 8ûì³sÐA¥mÛÿ÷-?zôèì»ï¾ùÎw¾“Ÿüä'I’)S¦¤¾¾>óçÏOŸ>}’$|pŽ:ê¨\ýõ?~|³¬h9Ü‚­ÀG>ò‘Fñ‘$ÿðÿ½÷Þ;K–,i›1cFFŽÙI2lذì±Ç¹å–[Š­h¹´R•J%úÓŸÒ£G$ÉsÏ=—+VäÀl2÷ ƒÊüùóUUUY'в¸ Z©iÓ¦åùçŸÏ…^˜$©««K’ôêÕ«ÉÜ^½zeÕªUY¿~}jjjÒ¯_¿lذ¡èz€–Áh…–,Y’ÓN;-C† Éç?ÿù$I}}}’¤]»vMæ·o߾рí%@ •yá…rÜqÇ¥{÷î™>}zíT:tH’¼úê«M¶Y·n]£9ÛË-XЊ¼üòË1bDþú׿桇Ê®»îÚðÚ¦[¯6ÝŠõFuuu©­­Ýîá9sf/^ÜhlàÀÙÿý·kÀޱ`Á‚,Z´¨ÑØSO=ÕL«Z ­ÄºuërüñÇç‰'žÈ½÷Þ›½öÚ«Ñë»í¶[zö왹sç6ÙvΜ9o+Î?ÿü&cC‡Í<°ÝûÞ¾I“&eöìÙͽ  • Ð lذ!£GÎo~ó›ÜvÛm9äC6;ï„NÈ 7ÜåË—7|ï}÷Ý—¥K—æì³ÏÞî÷Ÿ&Ožœþýû7ëÚµk£¿/X° Æ ËÀs饗æÙgŸÍE]”¥K—fæÌ™;ô˜ÞŽgžy&k֬ɸqãÒ»wï¬]»6Ó§OÏÉ'ŸœeË–mÕ/]lIçã–/_ž)S¦¤cÇŽ©ªªÚêíZÚù˜8qb:è Fc تm[ڹآ Àüú׿®¬_¿¾ÑØÒ¥K+íÛ·¯Œ3æM·½îºë*UUU•G}ô-ßgĈ•ÝvÛ­²zõꆱýèG•ªªªÊ=÷ܳ}‹/dÆ •ý÷߿ҷoß7×ÒÏÇèÑ£+ûØÇ*‡~xeŸ}öyËù-í|Üÿý•ªªªÊŒ3¶yÛ–v.ÞŠ[°€-úÈG>’¶m_(ý‡ø‡ì½÷ÞY²dÉVí£R©dõêÕÙ°aÃf_ÿë_ÿš{ï½7cÃYûIDATÆŒI§NÆÇŽ›N:å–[nÙþ( ºº:}úôIMMÍVÍo‰çãÁÌŒ3rÙe—¥R©lÓ–v>6Ï믿¾ÝÛ¶”s°%Ø&•J%úÓŸÒ£G­šÄG¤k׮騱c>ñ‰Oä‰'žhôúÂ… óúë¯çÀl4^SS“ý÷ß?óçÏßakßQÖ®]›•+WæÉ'ŸÌ¥—^š»ï¾;_ÿú×·jÛ–v>6lØ &düøñ[uKÞßkiçã _øBºvíš:äÈ#Ì£>ºÕÛ¶´s°%ž¶É´iÓòüóÏç /|Óy;v̾ð…qÄéÒ¥K~ûÛßæ’K.É!C2oÞ¼ôéÓ'IRWW—$éÕ«W“}ìºë®yøá‡wüA¼MguV®¹æš$IÛ¶msùå—çK_úÒ›nÓRÏÇÕW_gžy&¿üå/·i»–v>Úµk—Ï|æ39öØcÓ£G,Z´(]tQ=ôÐüú׿Îþûï¿Åm[Ú¹xKÍxûð.³xñâJ—.]*ýèG+7nÜæí~øáJuuuåË_þrÃØ7ÞX©ªªªÌ;·Éü“O>¹Ò­[··µæaÉ’%•ûò“Ÿü¤2|øðJ›6m*×_ý6ïçÝ~>V®\YÙe—]*—\rIÃØÐ¡C+ûî»ïvíïÝ~>þÞO|ø6oÛÒÎÀ¹ Ø*/¼ðBŽ;î¸tïÞ=Ó§Oߦûü7ùèG?šC9$÷Þ{oÃX‡’$¯¾új“ùëÖ­Ë{ßûÞí_ôN²çž{æÈ#̘1crçwfذa™4iRêëë·i?ïöóqÞyç¥G™0aÂÙß»ý|ü½äŸøDî¿ÿþT*•mÚ¶¥ €7 À[zùå—3bĈüõ¯Í]wÝ•]wÝu»÷Õ§OŸüå/iøû¦ÛI6Ý^òFuuuéÝ»÷v¿W)'œpB^~ùåüáØæmß­çcéÒ¥ùïÿþïL˜0!Ë—/ϲe˲lÙ²¬[·.¯½öZž~úéFǵµÞ­çcKúôé“×^{m»~OGK;›àM­[·.Ç|žxâ‰üïÿþoöÚk¯·µ¿?þñéÙ³gÃß÷ÙgŸ´mÛ6sçÎm4ïµ×^Ë‚ ÞôÞùwŠMW>ª«·ý?©ïÖóñÜsÏeãÆ9ãŒ3ò¡}¨ákΜ9yüñÇÓ¿ÿLžú膱Öò½ðfª*Ûzc*ÐjLš4)—_~yŽ?þøÍþãf̘1I’qãÆåÆo̲eËÒ·oß$Éî»ïžAƒeðàÁéÚµkæÍ›—ÿøÇÙm·Ý2wîÜF?Ù?~† ’½÷Þ;ãÇÏòåËsÉ%—dèС¹óÎ;ËìVøÔ§>•Õ«Wç°ÃKïÞ½ó /dÚ´iyüñÇsÝu×eìØ±IZÏùØœÃ?’÷½ï}ùýïŸk®¹&íÚµË#<’=÷Ü3Ië8o©™‚ÞÁ?üðJuuu¥ªªªÉWuuuüqãÆUª««+O?ýtÃØyçW9à€*ݺu«¼ç=ï©ôëׯrÚi§Uþüç?oö½~øáÊG?úÑJ‡*ïÿû+&L¨¬Y³f§ã¶øŸÿùŸÊQGUÙu×]+555•ÚÚÚʱÇ[¹÷Þ{Ík-çcs?üð&Ÿ‚ÕÎÇå—_^9äC*µµµ•šššÊn»íV;vlåÉ'Ÿl4¯5œ €·â PŒg@€bPŒŠ @1(F€Å #@€bPŒŠ ïBÕÕÕùæ7¿¹Sö½lÙ²TWWç†nØ)û£êêêL˜0a§¿ï`'úøÇ?žŽ;fÍš5[œsÒI'¥]»vùË_þ²Mû®ªªz»Ë{Ó}¿qÿ3gÎÜiÁ³3ãï]qÅéÖ­[6lØPì=hL€ìDcÆŒI}}}~þóŸoöõµk׿¶Ûnˈ#Ò½{÷«ۼ~ýú¥¾¾>cÆŒiÛ™RÒ/~ñ‹sÌ1iÓ¦Ms/ Õ ;ÑÇ?þñtîÜ97ß|óf_¿í¶Û²víÚœtÒI…WöæÞóž÷¤ººñÿ"J^©ØÖ®]›|0Çw\s/ U ;QûöíóéO:÷Ýw_V¬XÑäõ›o¾9]ºtÉÇ?þñ$ÉK/½”I“&åø@Ú·oŸÝwß=ßûÞ÷R©TÞò½æÏŸŸ#F¤k×®éܹs>ö±å7¿ùM“y/½ôRÎ<óÌôë×/íÛ·Ï>ð|þóŸÏ‹/¾˜äÿ=rã7&IÆ—üà©T*©®®NuuuÄ~ýú哟üd“÷X·n]ºvíšSO=uëOÖÿï /L›6mò_ÿõ_I’x ÕÕÕ¹å–[rÁ¤wïÞéܹsF•—_~9ë֭ˤI“ò¾÷½/;wÎ)§œ’×^{­É~ï»ï¾¼úê«1bD’dýúõùæ7¿™Ýwß=:tH=r衇æÞ{ïÝæ5°õÚ6÷Zº“N:)7ÜpCn¹å–œvÚi ã«V­ÊÝwßÝð ÈÚµk3tèÐÔÕÕå_ÿõ_Ó·oßüêW¿Ê¿ÿû¿§®®.—^zéßcÑ¢E9ôÐCÓ­[·üÛ¿ý[Ú¶m›þð‡9üðÃ3{öì|ðÁI’5kÖäÐCÍ’%KrÊ)§dРAY±bEî¸ãŽ<÷Üs©­­m²ï/ùË©««Ë¬Y³rÓM75zíä“OÎ÷¾÷½üå/it ÙwܑիW7ºkkœwÞy™:uj®¹æšœrÊ)^›:uj:vì˜sÏ=7K—.ÍW\‘ššš¬_¿>õõõùÖ·¾•Gy$×]w]úõë—óÏ?¿Ñö3gÎ̘ž={&I¾ñoä;ßùNÆŸƒ>8/¿ür~ûÛßfþüùùØÇ>¶Më`TØ©6lØPéÝ»weÈ!Ư¾úêJUUUeÖ¬Y•J¥R™þøã•ªªªÊÕW_ÝhüãÿxåCúÐßãÇ1a„J¥R©œuÖY•6mÚTn¼ñÆFsî¿ÿþJUUUe¿ýö«¼þúë ãŸûÜç*UUU•ãŽ;®Ñü!C†Túõë×ä½úöíÛèœýã?þcåøãË5°c¹ `'«®®Î‰'ž˜Gy$O?ýtÃøÍ7ßœ]wÝ5Æ K’üìg?Ëa‡–nݺeåÊ• _Æ ˆ òàƒnvÿ6lÈ=÷Ü“O~ò“éׯ_Ãø®»îšÏ}îsyøá‡>…kÆŒÙÿýó‰O|b‡Ûî»ïžC9$Ó¦Mk[µjUî¼óέ~®eãÆ9ýôÓsÅWdÚ´i9ùä“7;oìØ±ßtUç_þå_Í;øàƒóì³ÏfãÆ c¿ûÝïòì³Ï6zþ£{÷îùÝï~—'žxb«Ö ÀŽ!@ ØôñM£/_¾<?üpN<ñƇ»—.]š;ï¼3={öÌûÞ÷¾†¯£Ž:*UUU›}†$IV¬X‘úúúì¹çžM^Ûk¯½²qãÆ<ûì³I’'Ÿ|2ûì³Ï=¶±cÇæW¿úUžyæ™$ ©×_}‹!ñ÷n¼ñÆüà?È•W^™Ñ£Goq^ß¾}ý½k×®I’|àMÆ7nܘ—_~¹aì¿øEvÝu× <¸aì[ßúV^zé¥ì±ÇÙo¿ýòõ¯= .ܪ5°ý@ƒ Ê^{핟þô§I’Ÿþô§©T*®T*•}ôѹ÷Þ{›|Íš5+Ÿþô§ßö:vÆ'Yx≩©©i¸ rÓM7å ƒÊî»ï¾UÛô£Íûßÿþ\qÅoú»P¶ôѹ[¯¼áÁý™3gføðá^?ôÐCóä“OæÇ?þqöÙgŸüèG?Ê Aƒríµ×nÕºØ> “N:)¿ûÝï²páÂÜ|óÍÙc=ýD~À€Y½zuŽ<òÈÍ~ýýOú7éÙ³gÞûÞ÷fÉ’%M^[²dIª««¶0`Àvý”ÿÍÂ¥{÷î9î¸ã2mÚ´<ýôÓùõ¯½ÕW?’¿ÝÆuÏ=÷äùçŸÏðáÃßô—6n—^z)<òÈf?~·{÷î7n\n¾ùæ<ûì³Ùo¿ýòo|c‡¾? €B6]í¸à‚ òØc5yFⳟýlyä‘ÜsÏ=M¶}饗¶øÛ»Û´i“£>:·Ýv[£gLþô§?åæ›oΡ‡šN:%IN8á„<öØc¹õÖ[·ií;vL’F·5½ÑÉ'Ÿœßÿþ÷ùÚ×¾–6mÚäÄOܦýï»ï¾™9sf/^œã?>ëÖ­Û¦íß̦óyôÑG7ßô±Ã›tìØ1 ØìGø°ãø^€Búõë—!C†ä¶ÛnKUUU“ùÚ×¾–Ûo¿=#GŽÌ¸qã2hР¼òÊ+Y¸paf̘‘§Ÿ~:»ì²Ëf÷}á…fÖ¬Yùçþç|å+_I›6mòÃþ0ëׯÏ÷¾÷½Fï1}úôŒ5*ÿò/ÿ’AƒeÕªU¹ãŽ;rõÕWg¿ýöÛìþ<ðÀ$Égœ‘£>ºIdwÜq©­­ÍôéÓsì±Ç¦GÛ|~9äÜvÛm9öØcó™Ï|&·ÞzkÚ¶}ûÿ›úÅ/~‘C=4;wn4¾÷Þ{çˆ#ŽÈ Aƒ²Ë.»ä·¿ýmf̘‘ &¼í÷`Ë\(hSt|ðÁùЇ>Ôèµ:döìÙùÚ×¾–x “&MÊw¿ûÝ<ùä“ùÖ·¾•.]ºlq¿{ï½wzè¡ì³Ï>™:uj¾õ­o¥ÿþ¹ÿþûsÐA5ÌëØ±cz衜zê©™9sf&Nœ˜«¯¾:{íµWúôé³Åýúӟ΄ r×]weìØ±M⩦¦¦áòm¹ýêïqĹå–[rÏ=÷dìØ± Ïqlé°ÍWUU5ŒW*•Üu×]9öØc›Ì›8qb–-[–ï|ç;™8qbzè¡|ûÛßÎÅ_¼Ýëà­UU*[ñëuà-œy晹îºëò /¤}ûöͽœ$Éœ9sòOÿôOùýöÚ«¹—@\`X·n]nºé¦œpÂ ï˜øHþv5dêÔ©âàĶۊ+2kÖ¬LŸ>=·ß~{æÍ›·ÅçH ñ:oâE‹2f̘¼ÿýïÏå—_.>xK®€Åx(F€Å #@€bPŒŠ @1ÿp„‘¬8ÓƒIEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/contour_overlay.png0000644000077000000240000012047512436367710024662 0ustar tomstaff00000000000000‰PNG  IHDRXX¾f˜ÜsBIT|dˆ pHYsaa¨?§i IDATxœìÝwx”eöÿñ÷¤w’¡†:Ò¥H•"â ö‚õ»öî϶꺮®}×¾ØYq­»ËbÁÒ«ôÞ;„Hém~Bi“d’IÈçu]s óÌ3óÜ3As¸ïsŸãp:NDDDDÄm¼<=‘s,7S€%"""âf °DDDDÜL–ˆˆˆˆ›)Àq3X""""n¦KDDDÄÍ`‰ˆˆˆ¸™,7S€%"""âf °DDDDÜL–ˆˆˆˆ›)Àq3X""""n¦KDDDÄÍ`‰ˆˆˆ¸™,7S€%"""âf °DDDDÜL–ˆˆˆˆ›)Àq3X""""n¦KDDDÄÍ`‰ˆˆˆ¸™,7S€%"""âf °DDDDÜÌÇÓ¨ ˜6m±±±zz8uB^^^^ú÷ƒˆœûôÿ»’¥§§³{÷n.ºè"¢¢¢ªõÚ °ªÁ´iÓ¸ñÆ== ‘:éóÏ?ç†n¨Ök*Àª±±±€ý€;tèàÙÁÔ#FŒÀét2cÆ OEJ1bÄ~ýõWDJ2|øp¼¼¼˜>}º§‡"¥ÐÏ©d›6mâÆo<ý{¸:)ÀªùË‚:t G͹ÏÏϼ¼<}×5œ¯¯/€~N5˜¯¯/^^^úÕp>>>x{{ëçT O¤çhÑVDD¤–s8ž‚œE–œ“œN§§‡ eÐ/÷Ðÿïj&XrÎÑ/n©KœN§þ¿W)KÎ9þþþÚ²\ øùùé_Þ5œ¯¯/ÞÞÞž†”ÁÏÏOC΢KÎ9»víòôÄ{öìñô¤ ñññž‚¸àÀž‚CÿÌq3X""""n¦KDDDÄÍ`‰ˆˆˆ¸™,7S€%"""âf °DDDDÜL–ˆˆˆˆ›)Àq3X""""n¦KDDDÄÍ`‰ˆˆˆ¸™,7S€%"""âf °Dj“ý?ÂòûaÆ`HÚàéшˆH |<=qÑÁé0÷wÐ2Ž@ú~ïäéQ‰ˆH1<2ƒ5sæLn½õVÚ¶mKpp0­[·æ¶ÛnãСCEÎÍÈÈàå—_¦S§N„„„ШQ#FÍâÅ‹‹œ»uëVúõëGhh(?ü0yyy…žñÅéÛ·/ 4 00Ö­[sÇw°wïÞ"ïåt:yõÕWiÙ²%tíÚ•¯¿þºÈyãÇgèС•ø6D\ÐÀîcFÙ}X{ÏEDDJ呬ǜ¤¤$®¾újâââØ±cï¾û.S§NeõêÕ4lØðô¹·Þz+_ý57Ýt=ô‰‰‰|ðÁ <˜… Ò»woòòò¸êª«hÛ¶-7Þx#¯½ö±±±Üÿý§ßkåÊ•ôèуqãÆÊÆùè£øþûïY¿~=õë×?}î“O>É+¯¼Âí·ßNïÞ½ùöÛo7n‡ƒk¯½¶Ðçq8Uü‰õº@ëÛ`ÇGàAM==")‰ÓæÏŸ_䨼yóœ‡ÃùôÓOŸ>–žžîôòòr^sÍ5…Îݵk—Óáp8xàÓÇ6oÞìlÖ¬™377×ét:Ó¦Ms^pÁeŽeòäÉN‡Ãáœ8qâécñññN___ç}÷ÝWèÜAƒº†ÓétÞrË-ΡC‡–z+V8çŠ+ÊH©òòœÎµÏ9ËîõôHDDj>¾Èò¤Óé,ó:"náp@—?A¯w<=)EÙE˜’’ÂÉ“'‰ŠŠ:}ÌÇLJG}”O?ý”/¿ü’½{÷²víZÆOdd$·ß~ûésÛ·oϾ}ûøàƒؾ};O=õ,öZ :tˆùóçsÿý÷Ó¶m[®¸âŠÓϯZµŠÚ·/œã’¿¹zõêÓLJ–EDD¤³‹ðÍ7ß$;;»H~ÓsÏ=‡ŸŸ7ÝtÓ院V­Z±páBbccOŸÄ»ï¾ËøñãÉÎΦsçÎLš4©Èu:DãÆO?îÑ£sæÌ)4vðàÁBy`ùbbb8pàÀécÿüç?+öEDDäœU#f°æÍ›Ç_þò®½öZ† Rè¹7ÞxƒgŸ}–;3)S¦0aÂrrr;v,ÇŽ+tîõ×_ÏþýûY±b«V­"::ºÈµêׯό3˜:u*Ï=÷;wîdôèÑœaÓ¦MtèÐáôñ%K–ö¹Ê#ÿ½½½½ñññ)ôÃ/n)RDDD\Dff&ÀéI §ÓY¤àxuªÒ+<<¼È XI…Ñ£GsðàAfÏžMëÖ­‹}}=øê«¯9räéã+W®dëÖ­ÜqÇ.%--  P2;ÀäÉ“IJJ*´ãpìØ±<ôÐCL˜0wÞ±íðN§“÷ߟ¦M›Ò¿—¯{¦éÓ§ŸþL"""â;vì(öøÊ•+éÙ³g5Æxdá 7ÜÀ²e˸õÖ[Ù°a64­ eìØ±´nÝšë®»ŽI“&‘œœÌˆ#8xð ï¼óAAA<øàƒ._sëÖ­ >œë®»ŽvíÚáååÅòåËùâ‹/èÒ¥ wÞyçés›4iƒ>Èk¯½Fvv6½zõâÛo¿eÁ‚|ùå—*Ë """¥òH€µfÍ'Ndâĉ…ž‹=`Lš4‰¶mÛòùçŸóÃ?ÂÀyþù牋‹sùšÍš5㪫®bÖ¬YLš4‰œœZ¶lÉ#<“O>Y$qýå—_&""‚>ø€O?ý”¶mÛòÅ_pÝu×UîˈˆÈ9ÏáTò*—?E¹bÅ -ŠˆˆTOþþ­u°DDDDÎ% °DDDDÜL–ˆˆˆˆ›)ÀÉwàgØþqÙ版ˆ”¡Æ4{ñ˜´ý°í=ÈIƒ-o€3âî,ûu"""%Ð –ÈÉ­°ámí€ewÁî¯<=*©Å`IÝâtÚíL ‡B›ÛaõãÐîaˆè‡¦{f|""rNP€%uËþïaæPÈ>Yøøy…œ8ü+ø„€Ósý«DD¤öS€%uGn¬x¼,ˆ:Sên»¯×rÓÁ˯ڇ'""çXRwlú;¤íƒžoÁ™ý$Ol¶ç¼|¡^HÞjùX"""¤]„Rwìý7ÄŽƒ°vöøø Xñ]~‘Ðõ%8<rNB£áž«ˆˆÔj °¤îÈIÀ˜‚Ç»>‡äÍpÁ7Ðt,xûÜK ²DöôÜ8ED¤ÖS€%uC^6¤„€†Dz“ $Z\cü ~‚¾ÿôÌED䜡,9w¬xvYüsIë,y½~{œ› GæCp {œ‹o‚Æ£¡åÍÕ3^9g)À’sDZeÿ}ñÏ]hIìÝíñæ×!utyòr`áuàý>‡þ³‘ÊÑ¡œrÒ ¨[Rô¹„¥°öiˆ>PmyÓŠ‹Öë[Þ…„Å0|>ø×¯þ±‹ˆÈ9G–Ô.¹™°óŸ–O••YÇáÄ&HZÎ\;gZ_?»€”µ¾©×úaÏ™ G å-VÕ}ë;Ðüˆîï¹Ï%""çXR»úÕ¦À žü"!¼3Dõ…mlF*´-_»&A^Dõ‡¡¿€o¨½Çžo ¸%Ôï GæX/Âó?ôèÇ‘s‹,©²OÂ’?@@#«Ä~Ùþ‚b¡'6ÁŒ–_uá ð´ãyÙ²Bb-ÿ*ßÑ3Â^¿ûKƒƒªû‰ˆÈ9L–Ô|;&Âæ7 e§Õ§ Ž-®ò²aÑà ç=«øïÀ'Ú=mï-\„´„Ô}öggŽÍ„YÙ]DD¤’´]Jj¾œT8¹ ÂÚÛÎ?ŸH?dÏmz WC@˜{)žqwBÌE°ú ø¡ì›RøýµŠíGÁ;ÐÊ7ˆˆˆ¸‘f°¤æóö‡¼L ¢WCÚ^˜M!ó°- _þcùW/kÖÜîXõ,¼.?P°tØâ:Xõ(ìŸjIîúw†ˆˆ¸™,©ù¼í>42Éõ›éñ§ž†A?À†àÀÔ‚×…ÆÁÀÿÁ/=`׿ öË¿J‹‡74Ç~SÝ+q;XRó5 Í®€­ïB`#èügËÅJ‡ŒÃP¯,oˆý¿²¤ö¬$øí÷°øfh| l»Zy‡M¯AókmFìÄX""âv °¤æó ƒ“!y‹Gëž¶äö3…u€‹–BXÛ‚cC§ÁŒÁ ©{aÖÐÂïùms«£ÕöÞêù""Rg(À’Ú#¬ôùº¾dÉî8OåPaEE} ŸqžÕ¿Zû´(Í_R«‘ÕúÐò&›Ùq#XRûDÛÍQ}àÂ_íϹ™˜¥îˆn®¿‡ˆˆH9)À’ºÃÛß–Ï\F©Êîq3X""""n¦KDDDÄÍ`‰ˆˆˆ¸™,7S€%"""âf °DDDDÜL–Hm“•Ù'== )… ŠÔ&‰kaz_ÈM‡ÀÆÕ¢BÌHëÇèpxz„""‚f°DjÜLX|#Æ@p¬5¬N\«ƒ;ÁÔöpt‘§G)""hK¤öXõœØ|ª©µ7äìgàŸzpr$,†èþž©ˆH§,‘Ú -¶¾ ¾!à Ù‰Ðì2ˆìiÏçœrÁ?ʣãK¤6H\c÷yÙÞ‚[@ÿ/ ûß ŸçÌ©þ±‰ˆHZ"© ’Ö‚Ã"{AüwvlÙݶ£0Ÿo¤ìôÌøDD¤X"µAÒ:ð€#s ÷84WÁÉíÖ’7Û²a½Îž©ˆˆ %B‘Ú!¬䤀o8,¿p@ý¾Ðè"À¾v,æ"TDD@3X"µC›?ÀŸàøJhq$o´Ù+¿HŠÜTj þ‘ž©ˆˆ ,‘Ú!0†Ï†–ã`÷¿¬$ƒ}8±Þ– ó² ãž¥ˆˆœ¢,‘ÚÂ;úL„–ãáÈÄÝaK­o/oh<v| †À©°ð:[JÌÍ€£‹ Ï'pl Ôï ‡§?ˆH§K¤&pxÁù@öI+×pr´½Ç‚+€îƒæ×@ÂBH? 1£-'kÇÇ6ëÞÙrµ¢úxösˆˆ K¤æ¨ß .Ý}>¶’ ?‹ÇCÚ~‰…ßÀeû¡Û‹qâÿg3[Í.‡ƒmi°Åõžþ""‚,‘šÅËZÿün ôž~‚Ú®Ói9V‹WÀؽV’aÆKl>ßÚꈈˆÇ©–HMäígÁSì8X~?,¾–Ýõ:B½N—i5±²“-wkÐnîéQ‹ˆÈ) °Dj2ß0èûOhy#_iEF“ÖXKvYr|x'ORDD΢K¤¦s8 Ñp»‰ˆH­ K¤*¥îµ67 mi/¬£ÕµÊß(""ç$X"U%+f²Î<È>aǽƒ ËŸ-YÝ¡}&""ç"X"U!7æ]fÕՇυ­,Ÿªá…¶3põãptô›~ž­ˆˆ¸™,‘ª°ù HXÃfÁñ°ý};ž“½Þ…˜¶3ðçž0b5öìxEDÄ­´>!Rþ/†èþÖ+0²'œÿ!l›[Þ†&¿ƒQ+ / æ-hМ›i5¯¦õ»À’Û`Ç'ºÇ³ŸGDDÊE3X"î–“ ‹¡ûëö8q Dö€6·Á‰M°ò¡SMœ[Âàà×0ÿ ƒ½ÿµœ­˜QÞÕú îœh9\ Y¢|p,·°ûú½•Ç%"R)Àq·¬$È˶ö6yÙV»ªÕïí¹¨>°ÅiÛ"»Cÿ/`ÉÿAênhz´»êu(x¿ìdØ7â§XÞÖ®Ï!ç¤=ÖÁ’åcooÿêü”""R X"îæe÷™ ¶´——e•×W? [߆à–à[¯àüf—Ù­$¾aÐ껵ÌÉ>‰«aË›°ä°æÖü¹ÑÈ< );í†Dt³´ˆîÖjGDDªœ,wóößpÈ8¡m¬@èªG­ÿ([:ô ð.Us ‘:N–ˆ»e%Ú½+VF,¿~ìGæÛ’]Ûû`ÿ0½$osÿøVjVüsëžµ]|½þQ4¸r:-øÊ>Ì+_pu|ìûÖê`eŸ€´x8¶Ìfª ‚¡ÓTóÊ“ŽÎ³†ß^þV}?4ÚÞíéQ‰HR€%ân Å·¤É>iG{¼Q|ð´ñØûðokæìªƒ¿ZB¼_=ne÷!m î.hr)ø×¯øg‘ÊËJ²ªþMÆÚìá¡ÖÖHDÎi °DÜ-3êµ/zÜËpZoÁ39ó`Õc°ùïÐùOÖÊÆU¹°èk™3è;5|®‰¼ƒ áPØñ‘=nv%6ôì˜D¤Ê)Àq'§’7C“ß}ÎÛÏò²V?fËvéûáØr8ø‹Íjô|ÛJ5”Çî¯l·aÏw\ÕTÞ~VsìÄ&8¶]èé‰H5P€%âN); ;ÉvgÈO0w üp*ÑÜ;ÐÎðh^e£AÌEÖ Gj.‡„w²›ˆÔ °DÜ)þ;[ l0¨øç ‡ËXÁÏÐÖÖ¼*øŸaÊnHX ý>¯èh=+û$ø†zz""UB–ˆ;íý/4UzààÍ.«üµö|m3`MÇVþ½ªÛÎOá·ßCd/ËIj8ÔŠ®WÚBD¤R€%â. KáØo¶ °*d·"¤'6@ò&ëWØìJð ©šëU•”Ö±ñh ×?kþ>Áw7t{Y…PE¤ÖS€%â.럳Ö6M¯pß{f%Bü÷°ç8ô«µáñ ±¥Å†C-©É²aãk04´êö[Þ²Z`|e;*ó²­Ž×þ`ÃKàðn/zzä""•¢KÄr3áÀÐhx•҃Їç¾ÿÁ‘¹´ÖŽE€žoÚ¬OplÑ"¥5ÕÊG`ÏWPe†¼,ðòƒ g”«ðò…¨¾vó °@µåP¯£gÇ."R °DÜÁÛâîmÿ° ¢Û+ ´Wì ­|áÐþA Ú‚š¸ÌUíèBØ9z¿qwZ ‹ìdÀYrëŽYkŸå÷YiƒâÉ›l‰4m¿•ºÈIµ`-¨4¾‚K¨¢/"R`‰¸K¯w ¬-¬|Èf³"ºAH+›q ޵þ‚¥˜t:-°k¯®Ý ßY'`Ù]Pÿ|h}›s8¬Ê|i¼ýí{œs1,¾Îßr³Àf W?a­fÀfÂÛ†‚ìd ¸œwÙ÷ÖBZÛõ¼ƒ ¨é©ŸC ÆjË  ˆÔZ °DÜÅá€v÷CxWØý9œÜGAz¼UkwxC«[¡ÇߊVsØý]`37ž ®¶ëþý&A£a{£‹¬º|æ11¯ü3yGAÿ/aém¸Òú6æ¤ÀÚ?Á‰Öj(öFktf ”uüd¹j'·Ã‘y6»•›jy^ù¼ á0Û}ÙäRlT±Ï)"RŠ:`½ð üéO¢S§N¬[·îôññãÇóÙgŸ9¿]»vlÚ´éôãÝ»wÓªU+æÌ™Ã A%Ô=’º§á`»åËͲÐû¿‡µÏXÐã ˆèjËZGجLü÷Ö&§¢Mi²OZ"yòf{Üòð ,|Nn¬û3¤´Ö=£–—o¦Çé„M¯Âš§ ~6 BZVl¼±×ÛLÔ‚«aæP;Ö.ZRrW¿zöºØëÏW¤‚Ô=ºÛîþ Ëî„¥wX~[›Ûm)V-lDÄMêl€Ï‹/¾Hpp0Žb~‰øûûóÉ'Ÿ:V¯^Ë"Åñö³¢¢í‚¦—Áâ›`þå§žtN¨× ÎÿÐ’»Ý)u/lyÛ*¾g'Û,Øn½î¯Y@—ÿ÷ßd ®z¼aËœ§Cã‹\»ŽÓ «ͯC§'¡Ë_Ê. šqÄ–ùJÊǪ×.Zf‰þ1ØÄfÜN›ÙŠÿÞv%6¿¢J¾ŽÃ ‚Û-ºŸëô„5å>ð£å‰-¾éÔ5;Cã‹¡ãàéÚg)F °yäú÷ïONN Ež÷õõeܸq™œÓBZÂðypr¤î‚”]Ú^èþ¼ u±S>¡V_*öF³œÕÂÂkaû‡6# »¿´q´{vþ¶¾íZ€å̃¥·ÃŽO ×»ÐöžÒÏ?º6¾bÁM«[¡Ï‡%ŸëQ} 'Íú5šn;,Swƒo¸-®xZ·’þõ]ÿ~¢ Õ-vK?‡gÁ¡™öìúô| š_¥š\"R!u2Àš7o“'OfõêÕÜsÏ=ÅÎ`9NòòòHII!,¬˜|‘ŠrxYïÀªì¸ùMX÷,tz:>^¸iX úÖ•-oé6›” ƒ„Ü +©P¿k×Úú®W}'A«›K?×™¿^Pð¸e1ç]lË©‡,ðI?h»ó²,©½É | ¶:[»>³@2~ t{Í‚­²‚ÕôCp|9äåXcîÀF;Înç=o ú ¯… çYà3J‰ñ"R.u.ÀÊÍÍå¾ûîã¶Ûn£S§’¯¦¥¥FZZ\ýõ¼òÊ+:¯¸àLÄ£veK|‡®Ï—|^³+ì–Ï™gÁß–w 3Á^_–¤ –¯ÕöþD‰Õ IDAT²ƒ+°÷ou«-Ë5 ~>û$Ìm» CZA@#ˆê­~1#lwà™ÿÍDC‡ÿg³s«þ,¹6ü¢Bt{mXG+çppš-{&,¶ÇùÂÚY?Çú½ìqPcüYkŸ²ñ4i›»”ýED¨ƒÖûï¿ÏÞ½{™5kV‰ç4nܘÇœ=z——ÇÏ?ÿÌ„ X³f sæÌÁÛÛòXbccÉÍÍ­®¡‹”íð\øm¼Í u}©|¯uxY)„¯@‹q–7VšœTÛ-Úº|åÏÿbFBƒ!EŸÛþ¡íú»d•VpU`Cèÿ9´¹ÃªÞ',¶œÎ\Û‘™—mŸ¯~Ës‹ìmUæqÛ­8½tý+tx´`I°Á6ÇfÓV= ?wƒŽ<•_VÉb²"rΫSÖ±cÇxæ™gxæ™g¨_¿ä\_,ܦãšk®¡mÛ¶<õÔSü÷¿ÿåÚk¯­ê¡Š”ßî¯,¸ŠhALEfW“·ØìNË›J?/+ æ\);`Äü¢;Kãå -Šùo(7Ã’äco*_pu¦í[fÁVhœíÎô‹(|~p ±ÈJ@¬þ#ì›Ý^²"¯`ßaÓ±s1lz Ö=c¹Z=Þ„¨ó+6F©êTöæÓO?MTT÷Ýw_¹_ûÐCáååÅÌ™3«`d"•²\ ‹ÆA‹ëaÈO¶ÄVaí­­ÍÖwm·^q2ŽÂÌ -/ê™%—M(¬D˜w™ÕÎêøXå߬@iÃ!Ðé–³uvp•ÏÛº¿ÃçØ2éÌ í¶ïÛ‚úYÞ~Ðù)6Û·é}`Õã§l)^™ÁÚ¶m}ôo¾ù&ñññ§gdd••Åž={ #"¢øÿ ÉñãÇË}í¼¼<† †¯¯/N§ç©_^~~~8p ŸH꼬$XÿWØúøGCßOmi°2yÞ~Ðç˜7Ö‚¬vgýc$7掱Y®ásÝ““tb“]/3†Lµœ(Oh0ÈêlÅ _µRþÑ–øÞòfˆènçŒZ [Þ€ÕCÒ:¸àË’KMˆHµˆ‰‰!;ÛþAäp8NçGçääxlLu&ÀÚ¿?yyyÜÿýÜÿýEžoÙ²%>ø ¯¿þz±¯?yò$ DGG—ûÚ^^6QèííO¡¾¿g¤îÊ˵2 kž„Ü4èü'hÿ0ø>/i¬|Øf¸²mv梥V¢4MÇX©†U@psk0íåk3ZKÕ0ìŒàÊé´ŸŒCÖw°á²?CÒz8ð³•j8ºàTÑe%ç}¥ì„ŸZðãtÚµÃϳûÈ^î+êp@³Ëí–¸ÚÊ5ìþ¶¼eK¯|e}!;=zTøõuVV’ýbõ¶a%-õÔ‰kaÉàø2ËUêö²íz;“Ó Û?°„!­ ÙeÖx9q•-ÿ¹¢Û+–»4ï2ð ±™ï@+FÚÿËÂùGÙIpdŽý9uwéïëtZI…u¶÷kx¡õŒ½©p)‰3­xØfŒ|àٕàå'ÖYp–lÁ_»¬$EY½Ë#¢›Ýº½bÁàò»á—^0p²ý=Œiùg?wƒml7£ˆxÄŽ;Š=¾råJzöìYÍ£1u&Àª_¿>cÇŽ-rü7Þ`̘1€µ¿éÞ½;ãÆ£];[ª˜6m?ÿü3_|q±ï!UäØ2ûŵçÈM/8^¯3´½âîðÜØª[nlx6¼h ¥G,´_ògK?d³Lû¿‡¸» ûß­÷Þ éå®/eyû[òwâJ+¾yh†hÝ^)ÚŠÆ/ü×Ê 4-å¿ìÛž/­ÖT‡GËÎËÍ‚­oA›;¡Çß ÏÒ9¶v~_†“ì}ÛÜæÞâ ^>ÐôRk\½à*˜9ú~±×Axghývý6·[ãiêP€U’3—ë"""¸ôÒKùõ×_™4i¹¹¹ÄÅÅñÒK/ñÈ#xp¤uHÒ:ÛÑuàGð¶_àYNËÿñ µ­÷›_¯;Vê^ëÉw|%tzÊ’¶ÏLœN D—ßcípN±™+°ÂÉ› ç›å»®—7Ôï Á±Öæ§´`¨ù•v+I^¶Õ“J\ ý¿²àÄÞ~VR!egÑ%P‡Ãvvù´¾Õz .»Óú-öxÝý…AZRÿ’ÿƒßn¶â¤ ‡ØíÎIöw²ËŸÝ{M©µê|€5{öìBëÕ«Wl£g©9©°ìØ5© g^hkˆÙÃòm\m¹/ñÿ³\¤s½ÑÁ_aÑõ¶L7rqA1Ì3_aÅ>Ï‚æ×X»š€3r7½ ¡m¡a›HÿÔÅ*»ÙYñæÍ+c¿Y]©âfÞJw7üv $o+¹ú}Pè÷©Í2-¿Z¿Awóöƒ¾-ßlÞå0r‘õLlwŸ•qhs§F‹PÇÊ4H –¼~9ß’Šñ¶eÀ°´ÆZ¹že»¸À~ÉçeCz|©oY«e§Àòû`öHKâµ¢hp•uÝhyAéaÐ÷0à›ÂÁUÆË_kwŃѠævÿcg›M+¯]_X_Ão–?¸hqÍbîþWÙç¶½:ÿÖü¶}Pþk¹ÂË×–DƒšÂü+­8k§'­qõºg«æš"Rë(ÀÏ;¾Ê‚„Ì#@ž-E¥î±ãî³s¢/°‚€Ö;,ßè\›e–7¿i š×ý~ê ;&ZP2øÇ¢MŒÓöÃŒA°ª½Öò„ÎæMl–«¢ò—½rÓ-Ÿ«¿+_iA\IœN+¯ÐtLɹS®ª×Þv”æe[ÐX‡zO°Ú_Knµ¿c½Þ-:èªÌc0­à„!?[N ØÏmç?ígØç#›i;ð£,Q€%–'6ÚŸ£úA·W-){Û{6óÑíe+ø¸ýCè5V>h¿¸{WQ~»íü ŽÌ¶^õû@T[²û\¿ýÞêAµص÷Ûþ¾Í¤œÿaáà*i½-&®´%×”í¶lÔÌás¬Mh;;žqÒØî¼M‡içC«[¬ÌAEûž-ó¨ýl»<[ù÷ÊH8µ+¸YZu÷¬DÀa ùátZî^V½Þ‚šXþÚÜK,g­¸Òg léß<öò±àöàtèþê©÷m^P#,ö›ìùfÝî›)RÇ)ÀÏóò†!¿@ÂB+A¼Ùf:Ÿ*-PÑ_ÕíÄF˜}‘Í* þšŒ®ÞëçfY.ÖÖ ´Ö*¿Ÿ]‚Áé´Áý?XñÖŒ#g<éœöÇÖ6;Ù b.‚ˆól®óSÖ qÑV·lÐ÷eÏU´<ßaï7pÁ×å/QšÆ[¢ûš'ìÏeåu5µï)7Ë’ÚÁþÿ]ásŽÎ;UâVºaç$hÿ ûÆ-"µŠ,©|¡Ñp»ÕFy¹°x|AKwíÄsÕÆWaÃK–Û}?-ºt˜“ju¡öþÛÊ ´ºÕòª|Ãl ,û¤½6-Ž/·Ûºgaõchµþƒ5zn~5ø7°r ®Aÿ+šG–¸Öš?çlúL/YîWók*þÅq8lFtÆ©škeU—ÏÿY¦€ØSÇšÙ ]Nª-=6f»_-µ¢Í®´  °Dê,X"î°m‚å+XTýÁUN¬}Æv vü£À<{Ö(uÌc3ƒþ[´1sTŸÂóó‡ò²aÿ–µün ¶ÿ`¹p§À¼K-™ÿ¼¿Z@vl‰VIëlæ±ÓSûLi¬Zÿ¯Üß´¬ˆ-àRÙ‡ÌcEå烥ì¶eÔ†Ãl)q×$û.›Œ=_CV’嶉H£K¤²R÷Áš§¬Ñot¿ê¿~Ò:ÈË´Rç}>+f´:N#[æ*/_hv™ÝÒöÃâ[`ö( ²_d¥ \c;íÀfv¢X|ÌEåÛ!y¦ì$»¯lb{Ir3ìÞ• ñS¬FþìXé ï@ØÿX^Þ¶¡`ÛûÖÞ(¿)vêX"u”*á‰TFÆÛöïWϵJìÅÙóí:LXZ±×ç·ÓIÙYô¹Ü,kHœ™þZ¾àêlAM,°j0æ\bIÞͯ¶’ƒ¾…ËÀe{­˜g“ßU<¸[®[r­ yYvïp¡v^¶í<“_=[ºÜþ±í«‡•d¹mÁùÖn· YDjX"•ßp9ó¨%éWd¦Âé„…×YI…¥·WlÑÜ–èζö)[j4ÅjŽU–O S†YµêqÛÍØt¬%Á»KÖq»÷,ý¼Š =պǕÒ¯‚ êLmn·â·µÇáçY°?Å’ò½lKDê$X"átZ-¥œ4>¯b½úì jc5SññDö‚# ŠÿZßfÛÝÅÛþÏ n}~ì‡fºïý¡`w£¿‹îË+ êu¶Ù¦²„ÆYðê<+a?¿ÒýÆ—í±ÃÍ®°b­8­LFú!·]DjX"ÿ™k5•*33äð‚“áòCй•Ê[\Ç~³v-gÊ8byQîæíŸ†K6XÉ‚Y#,Ñ>/×=ïŸqÄZÿ”Vg«²^‡\°¢Ú,åÙ³]ùUÝÌ#óìXÌÅ6ö›NXÜ>l©`‰”Wn–í¦k4—ц¦,)»í—p`CK”®¨fW@TXùHá '7­h-,w iN·jü^€Yà ýpåß7uwÕ%¸ç‹êkK|YI¥Ÿ3ÒvDîù²èsMÇZÂûúN½gËë:ºÀúBž]üò¢ˆœó`‰”׮Ϭây¿Uî}œN˜9¾kn9X®HÛ¿(ÈûÉçpXŸÆ¤5pð—3/B±¥R÷À–wí}Ê 0Êâð²¤ÃfCò˜Övmc­¨£ lÙ³*9O¢Þ¥Ÿçå ͯƒíZ5û39Ðö^8<ãÔ¬[0Dt‡£ !ö&kŸspzÕŒ_Dj4X"åµãh<ºr;òÀvöåï2ËßÕV–Eãì—wꮢÏåÍOÏ·o²9i½ÕtZõüÐVܳGÂ#`j{+Á°÷¿Es\Õ`ŒZfK’‹®‡o›Âü« vº*ýU¢Y±q¸*;Ù‚'/–!»ƒ†Ã-ÇhÁÕ°å튦 ¦0r¡•lèó±Þ×fü\•ŸGVÕUý³“-ÏË¥†ÏQ–ow`*ìœxÖsÑ=öýχµ‡“Û,hn{·½¦2³y"R+©Ð¨Hyäf@NŠûv·E_`7W7³[q2ŽÚ}Àcëú‚ݲOÂñ¶„×tLAIßvÖΊd‚ÕãZùåV¹Ò¹$1Ðúÿ,/lÞeðKo¸xeAÎÒìÿÁ–ÙÜÙ°Ø16²"¬é‡-®,MÇX» e÷ØÌTý3–0ëu, ë÷±Â¯‰«¡ée°ôHX ͯªšÏ!"5’f°DÊ#3ÁîÏ.×ì2 ÀJrx.¬ù#tz² ô€;u| |Ã`íÓ¥ŸW¯[y9îC‘ku´à/¿{yx@ïw­UÒÀÿÏI‡ÜLð ²Ç^~öXDêX"å‘•>!žEɼýmVe×§Rø¹ ¦¶¬Ug¬|ê÷….ÏUÍØ|C¡Ë_l&­¤eL° 0ó˜µ"ªj/ˆºÀÚ UTƒ–øž/ëà´äv8U©¿æì‰H•R€%RGçYÒrMw‡Í´í;•¼°ÄJ¬yªø¥Ãœ4˜$®î¯V®eOYÚÜͯ>U0uQñçDö„àã¯jQå/†ZšüÖ8ŽSßãÉ­Ö¯QDêX"®Ê:a³*M*Qª:·€ðÎVñ,§jû‡°áE«Ô~¶ewÙÎÃAß•¯&WE8¼ ß$¨>̽R÷sŽZ\g3]g·¦©’1ù´Íq‡ÓÖ©ÿ½žÜ¡qî{©`‰¸êà/¶õ¾é˜ª»Fæq«´¾ü>ˆÿ¾`«y…Ÿɧf«Z·û6ÐþáÂçåfZòNOV®°hyxÀ o-ÙøJñçt|Ü–;×¶Ï#"uF -æ#RÙo÷Ѫ°@æì€ÂÛ¢ú–þÚôC°ãXû'ð«ç=k3aÇWÀŒÁ€pÚìŠ3Ï®5øh0v}fÅ?‹ dR÷Yã>ŸØãàfÖz÷¿,A=´uå>sû‡-èÛñ´èÔ5÷Àþï¡ÏDˆªÂ€lÙ5/‚J°ò²aýóÖ1$¼üË.šuª‡c~¿Ê¸;aÛ{6ó5äG· ]Dj6Í`‰¸âè|+JYRµîÊJÞ‡gØÒ^E6‚ÎOA׿ÚìÒÞÉV uðwÐû=èó1ŒZ WŸ„áó!y,»º¾hÅ?—ÝiÁÆ™ü3‡Úóͯ*8žß&(?¿¨2‚›C츂¥L(˜M+)èq§ŒS ›ÿü¦¿[››n/Ùcg^Ù3wùÕþóóݼ|­b|u숑C3X"®8¶»VÝûo|É~É·¼©rïÓñVÏjá5pä^h{/´¹£ð`t?è5]oE={O°~z“£¬ |X{ÛÁwh†ƒ§ÚRW¾ æ¶0e0¬rãÛ8pfÍ+ÇIâU.ÿ{)æßšû‚µOÙŽÆüµÔÝ\FÊüåÎ3 Òf'þE䜧KÄ ‡Øî±Ìc–;äNYI°ç+èò¬•0¨ ‡ú›{ÙLÖÖ·­¢x½ŽÖ?±Éï¬lC‹k-¨YòÐìJèñº%“§ì²Ù­Œ#Ðï3iký Í´Šå]žµ0Á­àÄf7|x,¡Ý;¨àqæQ»÷‹pÏû—ÆËÏîgsI`áu¶4Øõ…‚ã9'ËþùgŸ°û3ªìdð «üxE¤ÖP€%⊎OX±Î¯XµswÈ>iË®Ïl¶¦åÍîy_/_èø¨Ut?²ŽÌ±™—Œ#P휽ޅ>ÁÆ—­$Ä®IœÎÓ+¾™¸Ê–»ü"-7lë;vN÷W ^‡‚:[®8±Ù–YOl´¥¿–7[>Sê8±¡p Ÿ“Ûì¾:ŠsæïøK;PpìØ2˜s*çªÿ…›^g'Û’ii’ÖÚL oø¯;QÐ:GDêX"®ˆ†vÂæ¿A‡Ç*ž‹åtZ¹‡ÍoXáRgŽ=^‡À÷ŽÙ7 šŒ¶[¾Ã³­rûÏÝmy°Ë³– ŸŸÌ6C•uÜÀ¨¾Õßò¹Ö´íúåuh–•MH\e¿À{¼/®üN¼òh8F¯ƒ]ŸÃúçà§ó ÙUÐh¸Õl nf³/™G¡^§Â³7í†-oæ¿Yy…=_ÁO-àêøÇ¢ELó-»BZÁEËíœÌãV´Õ;Ðf‰‚[XþYÂRøíf›ÕêõÒKG¸‹O0\º öþÛ‚Þ•CÓ±ÐÿËâ© &¶3³$é‡íùv;²’·T]m©‘`‰¸* bo‚­ïBûG¬|‚«’·XeöV0tº4Õ@ÇËZÿZÞh5®6¾ ñÿ+è¡—oÐ÷…Ûçø×· kËÐô2 Ô6¾ ›^±Bš£×ñqæÁѶ“1?ó´ëŸ)óÌ`Ë‘£VA½önÿØ%òö³ï"öû9…Æ•Üð:¼‹õHÌ˱Y½³œf÷1Ù½Ói³u= ïÄô´ì[þ h蹿‡"ç8•i)Ö·Úvû„Å®¿&'\c³#B̈šñKÍË×f¢Ælƒk3aì^±N±_¼Ç–}Mç§­ØêÂk¬øæyÏZù‡´=– _âµÊFý" Æ’Ê«3¸:“Ãa×.)¸ °ò2 òÄÎvxDt·Z³ˆÌ IDATâ¯`}ýfy{Žð¿Û¬D˜%ü'¦ÄÀÂk­‰¹ˆ¸] ø/^¤IÝc÷aåV= '·Âÿ.yÍÓ¼|ly0º4»Ìf\ޝ,æ<_ðo«V¾ìN;V¯4k3{g÷Jtµw¢ÃËf‘öM¶<¬š*m¿Ý{ûÿü‰õÙ£àñŽmƒ@#7”³¨¬„ß,÷îðl+ÍÑû=›qû¥‡•!·R€%RGæÛR` …)Ï–´¶¿g=#Ϋڱ¹C^¬ÿ+ú|‹?'¨‰4ÿ¶`÷]Û{m‡àŽ Ÿ{r‹Ý»’Àßúÿl·ÝÞÿT|üUmû‡–ÇÒªèsNç©%Æv-†5 ¸J? 3†€¸xÄÝeæ/^e»g ¬Ù­H-¤,‘ò8:¢º~þªGmç\Ü=U7¦ŠÊI‡©íl'£ÛQ—qN¬³¤õÎÏ”üÚæ×ÀòûmY°ãct´¹–Þn òÿhï»ä–ÄîÊwÒÊ΋ÿZÝâ¾Ïé.IìçÁ7Å?Ÿ~Àòšòg7On·%¹ú}ªoŒ%qfÛÒf§'íç‘/¤•õ¢Ì·"¢¹pþG–×å*ÿVµ&qæÁoã-XîóIñgNºí® ëP°|˜°BÚØ®IOsxAÃáppzáã©ûì †Wü½Ï…¥wÚß›¤u0÷ës)RÇ)À©*iñ¶ë¬&ì,Iì™`ÕÜË#;ÅÊ/ä—#8SË`èÏ0raÑr e h`3Xùýüj‚•Xͯ ¾´VCgsæÁo¿· îý&ÙÏ;7Ójkw¾§4»W²{­s@VÌcArÌ¨Š½gÊ.Xp¥-3þÁJwøGUO‘X‘N–HUI?PóÛ£Dœ‘=m¶­<ŽÌ±_ÒÅX•3 ð‚9£NÍÖ‡¦Aóë ùÕÅ?¿îYØû ôûWÁrà¾É¸ÆÝYmÃ,Só+¡÷û°ý˜9¦÷µ]±þZñY¶ŸØý€CòVk%•™`½;Eê8X"®Ê¯c”›^ö¹Ngí°ÀvïøÉê{¹êàtŽ…Ð6îKx'¸p†%”ÏQ¾1U•àV¶Zœ=ÿ†õÏÛ.ÑæWßöž%þ‡µ«ž1º*îû~W[@4ä'ï\ñ÷ nnKÌ?v´ªþëþ MÆ”o#ˆÈ9J–ˆ«ApË¢y,ÅÉM·$ÿúU?®Êjq=à°² ®òö·~…U‘/u> ›eËO?ÄÁÚg=»dÚRv=~|•åfµgÍÀóY`˧qwUÛË¥á`³Ë–ó¢úVî½Zއ®/X>t\•ƒ¿+¹Ä‡H¢KÄU‡å±ÄO¼ÜÒÏͯ\ž—Yõãª,¿pëxl©ë¯éð88|Š6mv—Èîp鈻6¾lå$’ÖU͵ÊÔ¬ Àl¾ìd˜…íìóqAž]^,¿ÛªÝ7»²è{ÕÑ6[XYÞ~Vú¡ë 3²ìFØ"uˆ,‘òhvd†£óJ?ÏËÇf¯2Wϸ*+ª$³…ÿäXt£m½?S@”µÙý/›±© ~vK·XÂÅ7{fûZ<6-|lÛ{¶|9à?…gk~³@°ûßjFkñý@¤<¢úB½N°éoeŸSP鼦«ß’7CÊÎÂÇ~ƒÝ_ØÖûܬÂϵú½‘GæTíØ‚[@ßÚ.½-oWíµŠsb}á<¥¼\Ø:b¯‡–…ÏMÞ 8jFí+ñ(X"åáð²*å~²DáÒ5…´}Õ3®Êjv¥-…-½£pÿÀÆüùìÏëð²¦Ð™ U?¾ú½ î^Xû'›QªN¹wFpy`*¤íµö@gKÛgm¼ªo|"R#)À)¯×Úº­J?/8¶hîNMåç‡fX¿½|þ‘pé6kبèëü£¬½Nuèú¼-Ç­{®z®—¯ÅuÖ9ó˜=NZgK–‘=‹žëð\lp-"ç4X"åååcõŸ•~^p‹Ú`4eË~Ëî„éÀÞɶÚ|c[òÏæß úòÌ|àã“V³+ykõ\,ïΙû§Úã æ¶ƒòd1; }‚­¥’ˆÔy °D*¢þùpbcé¿Lƒ›[ý¤Úô ·ÏÇ0è;ðò…WÁ·M`×%ŸÒ R¶»w N'¬xȪ£Ÿ­íݶ·ñ¥Š½÷ÞÉÖ+1e·ë¯ ld¹wùe,š]nŸ{ñME“îYÃçœÔŠïÿ³wßñQ•ÙÇ?3é! $Ô$„zj ذtÕµí®}-««®Ýµ—]Ýu]] ?»¢Ò-ôÞ{¡…ô2÷÷ÇI!…$„LÊ÷ýzÍkÈ{ï<Äœ<ÏyΑjC–HYÔí8y ~ 㓳»,½‚–ÐÊƒË /†sgÀ¨%V(sþï îÓÂÏkÉ;­_yq<°ñMØö‘ýùd>ÐüFØóãéKeœ,3ɶ9WÀÆÀ-­wIEކø_íÏ~¡Ðïckœ¼îÅüçå.£¦V†Õ"R¡`‰”EX[{>u×]®´ƒ°ìëESqã*O=`øo¶l8ÿw°ó«‚焵8´ üÞ×í£—[€WX©ƒ¨Ñ–uxIÉîwpLénãïû\½`M)r¹|üsò«rÔ`µÀÖ<“¹2(Úž7¼GJ~©v`‰”…Ûü꾃.+ÙŠPf'[\·_ů¼¸ÜÐéIûsa ¡Ã»C.0ãØ6®üÞ7¼káIä`%%üêÀŽÏ‹¿GV2,½¦´¤ôQË Å–'Õþa«¶^Xí¯¢îå[+ÿ±Ž³€jé½y;/ÃÚ@çgmöí‡X+ç‘V²÷‘jE–HYÔË °²3`ûç0ûJø¦Z ƒ¾·D÷ªn÷÷V™¾Ç_ó ‚‘ól§Ý‚›`ÉÝg'ý0ìúÎvMzÒ _²;[ƒ¦cañ0}ü<ØÂAߨßMIÕjjËœ¬·e¿u/Y×7uaïDèøDÁeÆì4Xt»}o.ÜÆ["ý°©|o|Ãþ›pùZÒ¾'Ó2©|½=‘*gÛ‡àdAÛûlijûx›á©nýçRöÚÒg·W /—öùli33µšÛŒ^ë;+vœÝ_ƒ”À úÖ¤¢Æ{:a­¬ePÏÁñÍ6—q¨ðÙ+Ÿ@«u9 BšÙ1—Ë–S#GÂÄ9K—Ë_kv½5«nsOõûoED P€%RZ~a6{á8°ãK8¶Æ~(W7[þc@‹B*ªŸà²äðÖ÷@ÏTØÐò j#æ”ýúôö›0q´üÄÞlÅDk·³GqÜ~Ú{0;ôVwXåòö¸q°ñ-[–‘jMK„"¥Õh„µk™1Ê’©£.„úý½=ªòå8–øÝüFð¯]ôy.4Rþír*Êáå0¥‡ÕĪÝ–?ß7†ÅwÁ®o-a¾(žLÈL´[§J\g¯‡åhnËãjùGXû<¤R?MDªX"¥ÒÌòl’¶[`Ñå9o¨ü¥°&Î%É+‹a¥ªZ­§¤8˜>Àv"ŽZ ƒ¾‚1qÐêO–w5ûrø. ¾‹†™c¬\ÅÉ2ŽÚ³_XÁ{ÇÏ\àä´ó©ÓÉž;= 8°þ¥³õ©D¤’P€%Ru:Áð_ ï8ïR¶{x² q³ÍtT6™Çì9 îéÏmt®âŒÿí쎩¼m~Ç–@Ï‘W6¸1t}Ñ­1;-Y¾ù¶~;Ïù³Óí\—í\x‹í4ÌÈùží™h;c.³¦î›¬oå<¶þ¯|û7ŠH¥£K¤¬"ºC‹Ê~ý¦ÁO­áËZ0©3̽Ö¿ž73âMN–=»J¦ÞÝvÉmxý쎩+ªLEÉ]ÚrùXV»¿X1ÎÃËÏî¸ÊKܧÖ0ºÕJv¾Ëmá›\ óáxNƒç FÐãu¸h+´¸É–›Ž…_Z©†„yÖ”:wÖ 4Övn|+¯‡¡ˆT; °D¼%¼+Ôím³½ß±pm¶åÇçÛlHÚAïŒ-÷¿§„yUM®´zYÓúZsåu/'ûì¯,2mÖpJOXt›mNkSòë7¾ Û?¶@íŽù_ ޲^—ì„~å5øÎÝE8¥gþà³íŸáÈ2ˆÿõŒ?–ˆTN °D¼©Ãã°ÿg˜w½%]7†¡“¡÷{VbBX|$m«Øq…µµÝq{'–ì|·/œ;ÓjfFÂÊGaÁ–gVYÌ¿ÁúEàï,¿ª¤¶‡¥wCÛûsꂹ ?/i›í@ü¡̽Öv`l3S{çå©5áÝ,‘jIu°D¼)úBèû¡%EïøZÜ]þ-o…˜KaÓ¿-ïgË!æ h|±5-Iòyie¥ZÂö±56s–qÄ–¼º¾X²ëƒ[Í6÷XÒ¹×Zy‚>ï—½ðgyÉJ…}S¡ëKÐîÒ]›qÔšA7¹º½jAÔÆ®¯­Z|pŒ=2ŽÀîï,0¹Ìf¬v|8¶ ìò5ÏYõy—˾O ~o]ƒ£ÎÊÇïQ€%âM.—åî4¹ 6ÿÖ½`»Ðúj%:ý Ú=[Þµ"•ó®³`¥n_»®åmå7–oZÐ{;6°ouû”í^M®´² ó~µ¡ûëEÏúT„³,±½$=Oµúik¿Óù9˜{5ìüÚÜ›Ý`¹j)»àÈ ûsÏ·mסo°]›qÄf"ÿÑ ¶nû/³ ž,û» (¤Ž–ˆTy °D*ß`K¢n6Ö‚’_G@‡G¡ÓÓàdmyÚÞ){`ßëý·èv›‰½ùÌß?í¬}Áú+öxãÌïÐü:+÷°äN Ö:÷-‹}Smi0·\BI[g3ˆ]ž‡]_Áîï¡×;Ðüû{9ÿpK¤?ºÊ‚«ÀHëGØû»wH¬ÚæˆTSÊÁ©L‚YÓ.ÏÛlÖÌ !ygÞëÁÑ{ ý bo³ü¬CKÊö^ŽcÛž‰°ð6 Ö:>^>Ÿ#Wë; ÓS°ò1ØöqùÞ»4öO³Ù«ÒÌ¢egX[«™•sX÷²ÍîµúCÉ‚«“u{ÙJ^d§å•…HÞ!-Kw©24ƒ%RÙ¸ÜÐá¯Ñæ^cõ•žcãëõÍ;¯ç[pt¥íÚ Š´Ù’ÀFP·D]õzç¿oÜ'6ó•¼ÃvÔe¶€_èñæÙÉíêø¤ì¶ü.OºÕr— üCyI‡ck¡Ãc%¿Æq,©ýÐ">6½mcïXŠ{ä»_6d·¿#Ÿ;–ž` ²E¤ZR€%RYEŽ€1Ûa×7–T=­¿%Fw~üBìõŸ`û§öÃ:ý0¤ì´i›ÿ —ŸTâaí‹°ò¯P`~a–U§£•‹nrör¤\.[Vs²lFhÓÛÐõeˆY1yY sí¹Áà’_³ë[ÛXÐç¶ÛoÆùVr!(²lc8²ÊžkÅÂñœ¾IÛ,p‘jI–HeæjÉìÍ®‡ÿ°æÒ;¿²`!¤%„¶´ZZ¡­l©p÷wÈ´½?ï»°àªÃãÐùï$›»}m·dË?ZCå£,‘>$ÖfqBZ@áÖ8Ú]Îÿ[JX³Ó/ºä×lûê°ü¶„–KÖâÆ²áÈrÛQY« ¤„ÌãÖH:´uÙï)"•š,‘ªÀíkåb.…5Ï[“é³!uOþóBZBûG¬f®°¶–ÿãâÝ|õúÀ¹³ þ80’ãl&'þgXûœÍ¦õýОËK‚üK«§“qÄr¶º½f_§²gÿ2.Ÿ] ^³™ÃÄuÖ»ñøf{M–Hµ¥K¤* i}ÿ—÷uV2$n²’º} vû‚ATXkhõGXûwË ¬_±c>•ËeAF£sóŽ9޵•Y|Lée9hÏßï¬ו®<Ãî VB!ærû:7)=;¥ôïyÜzú†B¯ÿ¤ŽÖV(y‡½¢,‘êJ»Eª2ßZÑÍ–²êt(z†ªã“Öö&n\ÅŽ¯¤\.[’;o±%£¯}ÁjN9ž3¿wvzéJ!Äϰ͹Å?}rjZe/Ùõ©ûaÛ8Xñü:R÷ZÕø=?DôÈ;×ÛXEä¬Ñ¿n‘š °žåUöæÂ>þÐù)ô­Í$­·¡ö@ãK /ÿcÕÖKbËm¦¯Í=yÇëèÅ0çJë'Øåˆ:ß·ÃËàÐBØÿ ì›l»1»ÿš^m×eY—ÙògßmÃX° %o¦-"UŽ,‘š ·4@ØIIÕžl«ŸyÌ’Ê»<ï±%ú" °Òæ?¾æyXóŒÕìêú"ì›nÁOh+6ÅòÔN ‰Oÿ~Ù¶S³ÙõË1„µ‘ `é=°ì>{äò ² ¯ï‡Ð캼Ù)€™c¬×9¿@ƒyÇ}Cì9=ÁvŠHµ£K¤&HŠ³ç“ [˜ ;þÏ“}S¡ó³g7'(ý0¤Å[ƒdÿˆ¼‚›EYó¬G-~ŸÿøŽñP¯¿U³÷­í¶¤_ϵ{§XÙi%«¼¾g‚åK\ââd¾ÁÖ¸ºË‹px‰ÞÍj‰T廦Ôéœ?¸ È|‚aÿt›¡‘jG–HMà*dé,w[Z¼ÍØœÍàÊqàç!p,'‡É¯6\º¯ðÀ'5¶bTLPèi}ürw÷‰Px2{Úþ’ÍL\V„µ8õ jTñç䊹Ì=§%Øu¹|låÞI ŠHµ£$w‘šÀ''9¹Ô@­¦V >¢4Y¶ûf¥Z°“q¬øóެ°àªÇ?,@ ŠÊ y²aÏO¶¤ö}´%·7»bo-x¯º}léäÄõÌÄœÏYH€•²‚Ÿþ³4¹Â–î¶ü÷ôç–TôÅ\îþ¶×.€³à›z0¹̺Ô>w‚ʿADNK3X"5AîlOVRÞ1—Û~ÈG_Pº{¥ì±æÐÇV[ðØ4¾Ä œÖíY𚬜[Þƒã­UŽËeõ¦Ö½hAMÊ.[rëñhz-DþþM¯¶\©)=,oìÐ"Ø>ÞŠ©6*x¾Ë ){Oÿ¹üB¡ù °õ=èôDÑË~¥ÔÐf±V?cùY'Ϻ5¿Ñº¤8«‹•¼¶üÖ>o߇ÖwC³k­ÌÄ®om97ý•åïnjÝ^Þ/+"…R€%RäVsß7ÝŠ‘ž‰õ¯Á¡ÐêOV9>¤¹9Û>€ŸÁ€/màÉ ¶å¾£+-G*·íÌŽ/¬ýOì-ÖF§°àìTuáÜä-¼Õf§Ú>`µÀ K¯?ÈJ/”d&+úBØü/ "Cš•ä»arëu¶ÌÚíø©Õöêò\ÞqŸh6¶à}öMƒMoÁ›aÉÖ(Ú“i­„»ÚÎÅmã¬%R‡ÇòßSD* X"5A`=«L¾ùßÐæî²ç[e¥BÜG{[þ]‡ ‡B›{­VÔìK­Iò©½ûÚÜ]ð~ÇÖX…>ï—nA‘0äGÛÒ¢ðò ¹º¿ û¦X06trñ3>¹KŒNVéÆóÛypp®¯íÉ_V"¤¹Õ¿Zÿ’%Ü·¸èjú.·åwE‚ÄÍÖ1y;ÔËË kxŽÍnxV? F@Ã!¥¯ˆœuÊÁ©)Zß Ç7ÁίË~_Zm§–·|Í'Àf¯ZÜ n²¼¢õ¯Z P”Ä Ö®lcq¹ ¬UñÁ€8ô~×vJîÿ¹øsËR4y—Ý·éÕ͹ ¶œ0v|ÚÿÕ–Bh+=}eø°VÖ»qÇÿYïíŸBÜ'0ÿz›)Œº Ê)µ‘XòñŠH…P€%RSÔh³s¯†@üÌÒ'Soo3(¡±…¿îö±`fȶ\·êoðSk˜Ü ’wZ^ÛþŸ­OI ©ŠH…R€%R“¸Ü–X}þj›m©ÕVüÅJ#̾Ž­/þúfc­òûúWJö~¾µ æË}JÙcïá9)¿©ñ%–øž[õljv=à‚ -`ñ°glûß ;@âz<ÁÃ’î <² Ž,³‚¹\. âjw(úº˜Ël)ué=…·ÇÖX ^ÿ¶Ù±=?Aë» ÉU¶d¸îÛèWÛfæ7”ê[!"gŸ,‘жí#ﲄgoq¹ j´—ÿ²ZU“:ÊG +¹ðëê°„íÕOÀ‘•%¿Úí,Xˆÿ5ÿlKäyà°PKî±Ù™„E6ÃVÞµ ‚£áüUÐúØó#̼Ü»¿‡Ãë ñÅ¥»çúW­ÿ`ôI»&=Ypd¹Õ+NÔ(+›QØ÷úÐ"{nzµZŸ€oXžWHs› ô¯µb,^D*X"-(Êv¾•&Ïçl ˆ€V´£ã¶døSû¢Â;?c‰és®*]ruf¢U”?¹•_( o=÷O³¥°i}`B3XVDËš3ÚÒv?^¼.Ú W%Ã¥{ í½¶$÷mCø*ÜvÆÏÌ+¿P˜ä]6›ÔöÏùg¼@v*Ôí]üX¶· ¬°|¶Üÿ6\nˆÿÙr®V=ë_·Ù¾°¶ÖÇÐ?/‡ÚJý­‘³K–HE‹ mÉ_t²2ð €Nƒ ÖÚý™á%…Ÿ7ðkkA³à÷E!É;l6êøV«ô~x©•18µ=NÌe0ðK¸p\yF-NOÁÆ7a×wåþ1KÆmiý/·;¿†ØÛm†kÿ/–£öC¬íÜ+LÊ. |š\™ÿøÖ÷¬uOýþE¿úaØ;1ÿÒâÉO^{£n¯Bã10V=8VP5q½='ÇY™ ©TTKÄ*sõíÐX2ÑŒYcl×ZptþsÂZAßqVójR'k¾\¯¯ÍÚ$n°2û§¼wó ;™o°5BïnK n¶{žúþå%~&ü6jw„a“-èk|}p.,Ð «6ÿ]Ákk5³åÍ­X`šëð2k=T\­±õ/[ÕôšÂ_ld³X¿Ž€ÎÏÛB°k²’`Ý˖ܾëkm ‘%ì("F–ˆäd?Ô§ö†Y—Àˆ96su²˜K¬—áî VÙ}ëÿ€œ¼©zý ï‡Vy<ý=2—<p¹,ßhB3ËG ¾´×ŽÏ¡Ç[på18w6txÔ¿®)Ù}̆©}l÷cHK8o±µ¢)N­æ–°¾çÇ¢Ïñ µûÄþº½lK£~!öZV2̿іú}£Wä-éYžÓ8ûû¬£WZ9 °Zc+±`pó¿,P;¾Ùr².Žƒö[¿#‹TV^ù×ùðÃsôèQ®¼òJZµjÅÖ­[yûí·ùé§ŸX±b æå%\ýõ|ýõ×ÜrË-ôìÙ“ùóçó·¿ý;wòî»ïž8ÏãñpÅWкuk®¿þz^yåš5kÆ=÷Üsâœ+V0|øp:tèÀo¼Á®]»xõÕWÙ¼y3“&MÊ7ÆG}”—^z‰Ûo¿^½zñý÷ß3vìX\.W_}u¾s]•9aYäL¹\ÖÎ&qSż߾©°÷'ôM^Eõ5ÏÚò[‹ßƒ?4h³K«Ÿ²Põû}¿¤8Xþ›¹Šè Ã+ùL›Ëe³GqãÀóÎéûžÊ“ ž4èò´{ àë¹¥ ²jðá‹ÏᑪÁñ‚Ù³g86kÖ,Çår9?þø‰c‹-r\.—óä“Oæ;÷ÁtÜn·³jÕªÇ6lØàÄÄÄ8ÙÙÙŽã8ÎÔ©Sä»nôèÑNtt´süøñÇÞÿ}Çår9Ó¦M;ql÷îÝŽŸŸŸs÷Ýwç»~ðàÁùÞÃqçÆot† Vìç]ºt©8K—.-ö<‘JkÑŸgR׊y¯£ëç3gëGöuÊ>ÇùÌå8ÿUðܯ"gõóŽ÷™ã$ï*øzVºã|]×q¾vœm;Ž'»à9§s`®gË¥¿ÖqgÎ5ŽóC«ÂßÛãqœo:ΊGËvo)–7þze‰pàÀŽ 4ˆˆˆ6lÈkù0{öl®¹&ÿVæk®¹Çqøâ‹/NKNN&""·Û>RýúõIJJ:ñzbb"?ÿü3×_=!!!'Žßpà „„„ðå—_ž86a²²²¸ãŽ;ò½ïŸþô'vïÞÍüùóówÊ»â´Ô\G×Bv†·GQO0d¥TÌ{Õng»èÖHpp0Ý»wgáÂ…<þøãøúú’šššï>×^{-#FŒ`×®]tîÜŸ¼„ÔÜs Ö» Ìw¯ÔÔÔ"Ï;ù^"åÆå‚K÷‚O5ð­L²3òfæ_o¥}cÁKüo¶ÃnÓ?óΊ„ Æö9ü¬.VÊnÛ—yÌÎ l`ÕÎû~Pt-«æ7ÂÜ«!+\¾°oŠ•Šð ‚c¬lCì-V[*"gfÚåk³l¹ü¬ü'»ô ê§ŠŸa³iQ£óOÚ³/³åʨ ær«t²¦×ÀÊG­ýOŸ÷ò¿ærC£á°û‡3ŸˆT*g5ÀÊÌÌäСüË 48‘'°aÃ.½ôR:wîÌû￟ïÜ€€&NœÈUW]Åå—_XóòË/óÜsÏåË¥ÊU¯^½|ËŒ¹r—s—O–––Fppp¾sÓÒÒ =ïä{‰”« ‚³«^•¼ÓJ $Ì·Ù+° âÜÙäÔí•×B&e·ï n\tÑNÇÇ·XM©c«­ .è÷Qá¹QÑY;˜Íÿ‚æ7ÁÆXôæ7À™P+º½šäõL?hK†¹êt¶ÆËI[òv$–ÕÞ‰V²áäû¤°V;ž,[F]ó¬õ l÷èô„•˜ÛùÔ(¯ÖÕɲRa×·Ðäª3ŸˆT*g5Àš;w.çœsN¾cÛ·o§I“&ìÚµ‹‘#GΤI“¨U«`óÛöíÛ³fÍÖ¯_Ï‘#Ghß¾=Ü{ï½ùf»N'wy/w©ðdûöí#***ß¹3fÌ(ô< ß¹%‘[køðáøùùá8ΉÄxÿ|KŽ"•‚'ÛÇ“w@×l¶(( .XWx[–ÜjëÅq¹!¬µ=êtµœ&ÿÚÐãƒ,ß hs/¬}΂šÞïY ´íCk}ÞˆûØ– °köN„6÷åÝ#·HéÑ5g`¥‚Zy© d¥ÀŒóíýG̵ŽÙi°îXû,ìúZßiË¥‰­ØhÛûóßÓ“iu¹2­–ˆ”Idd$™™V„øäÜ謬¬â.;«Îj’{×®]ùùçŸó=rs›:ÄÈ‘#ÉÌÌdêÔ©…æ<¬]»vôïߟ:uêðÛo¿á8çž{n‰ÇÒ±cG|}}Y¼xq¾ã¬X±‚®]»ž8Ö­[7RRRX¿~}¾s.\xâs•F¾¾øûûH`` färZ÷"œ‘çÁñ­ôûØš1——f×X^Ó¦ÁÌ‹ ãhÁsº<›Ólº‰µ˜É<½ÿ¬…ÀH›-нêæ,:«ržË7§Â{v9,ëûž²“r×·4 dÁØŒU§¿Y1Ñ€z°ô>+š•b…Qc.Ï»ÞñÀü›`ÿTë;Xí…Dj¨ààà?WýýýñõõÅÇÇ'ߊY…«ðÂŽã$%%9½{÷vj×®í,[¶¬Tצ¤¤8Ý»ww¢££¤¤¤R];zôh'**ªÐ:XS§N=ql÷îÝŽ¿¿¿s×]w8æñxœAƒ9111ŽÇã)Õûª–T9?³ÚOŸá8ãÝŽ³ü¯gï½öLrœ/ë8΄XÇ90¯ðs<ÙŽ³ú9Çù¦‘éÿü¬¶ÕWŽ“–wÞ7 ì¼\™)vþ¶OÎ|œÓ‡ZM«\s¯wœÉ=Š>ßã±:\EY÷Š}ow|yæc‘Byóç¯W’ܯ»î:/^ÌÍ7ßÌÚµkY»ví‰×BCC3f̉¯¯ºê*¢££i×®‰‰‰|ðÁlß¾‰'º¤XœçŸžþýû3dÈn»í6vïÞÍ믿ÎyçÇÈ‘#OœÍ}÷ÝÇ+¯¼Bff&={öäûï¿gΜ9Œ?^e¤ú6œ,K@/Kí¨Òˆ £–Xóåéým¹¯ßÇù{ºÜÐñ1›JÜ`5¥̲äñ“wú埭:ñoµjL%oÏßZ'y;„µ+ú|—Ër¯ “«ŸVwæå‰HõRá!ã8Íš5sÜn·ãr¹ <š7ožïÜ—_~Ùi×®äDDD8—\r‰³råÊ2¿÷œ9sœ8AAANÆ »ï¾»Ð™0Çã¼ð N³fÍœ€€§S§NÎøñãËôžšÁ)ì,ÇÙù­ÍR}ÓÐqâg•þSû9άËó¾ÎJË_¾ÌcËtœñ¾Ž³é¼cZ:βËv¿¥÷;ÎW᎓vèÌÆ%"Ūq3Xqqq%>÷¡‡⡇*·÷0`@¾šWEq¹\<òÈ#<òÈ#åöÞ"^å8–¬¾ãÿl–';Ívþ…ÆÚ¶¦×Zuoqû@Ì¥P¯¿•gøm$ þ"G”üÑÛN¾¬TK’wû[þVÂê‚ÒÝ'i›í,lq34*ù.h©z`‰TwÙé°úi«ÁÔæ›Íúy| SûÀì+àÐBˆ¹†ü`ÍçŽ-Y@s6ùÀào¡ë˰í#ø±õég×|,È:’×/”ÐXhö;X|‡Õ¨*mS唽ph‘5 +–ºíCèðWð+Xì¸PŽcIùs®²ò =ŠèK("Õ†,‘ê.i›Ub¹Â¾>8×~Ø7µ;Zpµö{Íí ýÇCÊNXù¸÷ÆœËí퀋6AÃs`Þõpà49”áÝòX`Õâ;üÕ–Iç…ƒóó·Ô)Êñ­0ïZË劺ÀjW-½ÏZý´ücñ×f§CÂB›9œÔÑ‚ÚÌã0àská#"ÕZ¥èE("gQf¢=ç¶°Ùò_‰µ"Ÿ.7¬{ÉÃ=™ÐÔµ¥°ÀFEß³¢Eæ~»`áÍ0zeáåÁ¬_XåÎù_œË ]ž·€rÉ–“åWZý:=]°½OV2l~VýÍ‚©¡“-!}í – >ä§¢ß?e̽ÖWO¸¬íO·¬‘wYʼd¥Øçæwì~ž„è K©0 °Dª»Ü1‰› ¢;] I[­ñ²¸Í ­xÄzÖï»'ØÃæ×ywܧrû@Ÿ`rWXýt{¥ðó"zØø­ðSº.4»ÖêNZ {&À†×mù±þ[ k{~‚íŸYßÀVw@×m)pßt«ßáqˆ.&÷jÛG–dßí5«›U§KÑõ°v|[Þ³6 o…ŸÚCÏ·óÚߤ´ç¸O-àiáñ§v[[ê[÷"´$‘Ñ\Ý,H9´¨`€6«U¿Ÿ=šŽ…ã!a¬zÒv EYÄØ[ ¤™õe\û¬zÂ’î;=Uü÷ü‘£¡Í]§ÿ<ß‚¥÷ØNΣ«`××–¯ØÐ‚2—ŸÍ*6½ÚÞk'Žcmz–Ý;À…ëó÷H‘JA–HMP¯lz˪¦7¹Ò~ /þ“UO+?}ìøöO³À«²ju¬yΖùZßYðußZ¶˜°ZÞ^ü½Â;ÛlI1i›1¹K‹GWÃ’»àÀl è:=e3iEIÝoKƒ…ëTkž·±¶Ø„…·Ú Zh+{ÔéhS¹\ÐärkdýSKºW€%Ré(É]¤&èû!Ôî¿ ·ºRÁÑ0xŒ˜ ƒ¾± +±ŸM®´Ò•U`}h0ÄfŠŠ9ÂfyróÏJÂíkKt¸¬‰óìËaRgHÙ ç΀®/~©Ïq,¡ÝíQçÿ^»'XpÕéièþ*lyâgXrþÆ7-±~R' ðŠ’;óèÉ,ùg‘ £K¤&ð¯æZ¾ÕŒÑ0}lþ7$Ì·Ò“:Y>R·×,™<·ÞSeÕøbˆÿ 2Žþz›{m¹oó;%»ß–ÿÂôð}Sø"¦ô´ZZ}>€ 7@ƒÁÅ_ïɶZ]^ƒÎϾt™+)æß/…޳ië{Ð`[ ‡­^@Ʊ¢ïãòËyoX"•‘,‘šÂ7ØŠwöû|Caé½¶K.=Áf¬F·v÷—m—[E‹¹Üvèíþ¡ð׃ÛgZÿš%¼g×÷°è¶«°ùõVˆuØT ¬bo9PÅñdÛÌß–w ÷»Ðþá¢ÏÍJYc,àíû}¯wO€Ô}P·wÞy~áöìSJ·–íŽLÚZüøDÄ+”ƒ%R“¸}mw`óëlùÌ'èôDemyc;¿€7~N³ßÙÌÔñÍ–¯T˜£k¬r}Ì0ð˲—kÿ»¿³eÖÆî²û-gê¼EdlzÛ6´¹ÒÛf„ˆœäü¬”¢ïåM® oX^ZqË—"Rá4ƒ%RSù…UÍà*WóßÁÞÉV4µ0A9˜Óþú¡%ðÛ(KjïûaÙ‚«ƒsaÍSVºátÁÕ®ï-תǛyÉëÇlü-n¶Ü²ÞïX¾WH¬µ-š76ýÛfÉ ÓáQ+ »ý“Ò]DÎ*X"R5µ¸Åf~æßXx2{`{NÝ—ÿ¸'¶}l9WÁ­ˆhI[Þœ,󸵪×Ïr©Š=7 Ýf¶coË;~h!àä5‘Îå 範&WYaÔ M­ü”^V^ãÇÖ–óårÙ¦„UOZqT©4`‰HÕäö~ã,‡lõ3_÷ ±Yºù×Ã×uáëø<>÷…7B³ëàÜ™U¶÷_õ¤½w¿OóÊ:eË-!¿Ç?óÏ”œg ñ¡­ ^Púü×rã»Bú!«ïÖê‚_[ÀÕúnÇÚËö9Dä¬P–ˆT]Am¶§°dp—ËÊP^©{,!ܧ–%‡×Š†Ã _tÛÉwh‰íê«ÛÛê†D]›þ Ÿ³b¤ÅÉN·Ý…ͯ·÷ëiÿ+ìüêö-~y2(Ú–“âì¼C -x1f^`EWÛ>ë_É+Ž*"^§KDª®=?X[™Ø[ ½¨b§JÙc;*®¶$ôÌœònÛ­Pסà;ÿ ÔjnBOgËm™²Ý_r¾~ßz?¦ì´Ù¨ö)úÚcëà×–+7j1„µµÔ?¶š[=߆Y—@Óœ†ÔÛ?ƒŽ~L"rÖi‰°:Ú7¶þ²R½=‘³kÏÖܹ¨ ÊqŠNÏÿLéû¦Bx+³0ð++ÓpU Œ\-ÿ¸¬nXüÏÖ»ßG%Û¹·o*4:j·³]‚‹ÿhí|F̃ ÖÛÌÔÒû -¡àµkž·šd#@íö6 Ö :=Û?µý:àÀ +®ºwÒéÇ#"B3XÕÍ¡%ÖÖ“+…Ö÷@»Á'ÀÛ#)Góv fµYMoYí+·¿át2­¿`­¦P«™åee¥ä4RN±Y°CaÀç¶“ïTõzÛ£¬R÷æÕ¸r²íáSË‚¬ÕOÚl–O µþ:Érƒ‡{'AáÔ(ÿ=[üÞ‚²ÝìkŸ`ˆêo‰ô释/t*"BVu’³/µßÂûüÏr2V=n¿ážn ¹HUäqãlíðR ¬ZýÉfv<àòµ@+e$ï€äíyÌ ­ºs)w|ÊHŸ.Q½¬R÷Z€Pº¿+¶žé Ðõ%h~ƒ ýy úÖf£\.ˆ¹¶}hÉðõûçÝ3a}>ÿ:–Öú.[nt<6#¦KÄë`U'‹ÿh k}k…_ qÛ$‘ê¨ÏûÐh¸ÕŠjz•KÈѪ Ç–õâ>±\+Ÿ@h{ŸyÙƒX5¿ÎÎþ+̹ fœoË”mÿ Ý_·Jí¿ž ]_OšÍRœÁM`Í 6Ã{«%»û†Ú/X"âu °ª“„yP·$ï´¥’_Ø’H­&Þ™ÈÙáöµ‚£Íçí‘Îå‚./ÚÒÝäîÐïc¨ÛÓf•Ï™šÿ\ßZ0ø{Xõ„Ugßøhs š‹n…¥w[åýˆî¶2q$m†¾ã—åz5Zµ‹ÇŠT#Jr¯N¢ÇXÒïôþ–Ïs èíQ‰Ôl-n€QË,8šÖ¦õ‡•ÁþŸ ¶ÂqûA×`L´¾Ó~Qú>’wÙNÁY¾ÕöO­ôDÿñ¶L8ÿ«ßäJï|F)@3XÕI7m™Äí—S·ÇÇÛ#€:༶d¿o*lyÏzºý¡vˆèÑÚnCßZV…¾ë‹öïyßT+×plýÖúf¿@%̃)=-ϫߧyË"âu °ªß`htŽ·G!"…qûY!ÐØ[,7ëØZˆŸGWÁÁÙ°õ}ËÑŠ mîµÒ~aÐh¤ýÂäòµ²îKlŸ>/ˆž0äGkííO("'Q€%"RÑ\®‚EP7Ù Õ¶à—¡§¿GÃá0t DŽ,[£j9«`‰ˆTa­!ì«`†Õõò« þµ­n–“m¥<VžB3V"•š,‘ÊÄ傆ü=Šª); \~Ê?•JA»ED¤jËNƒï›ÂA0o¬·G#(À©¼2aÏOÖÖGŠ–~ØšgC^["/Ó¡ˆHeå ¡­l¡-8Êt˜ ­îðöhDX""•—Ëeu¯äôš\a‘JBK„""""åL–ˆˆˆH9S€%"""RÎ`‰ˆˆˆ”3X""""åL»ED¤d2CâHÚI[­|DÓk¡VŒ·G&Ré(À‘Ósø!ÒÚ×þVA}Å#ÐåïÐáïŽO¤’Q€%""§—•dÁU·W öVð¯c3ZÓúBâzoN¤ÒQ–ˆˆœ^ÆQ{®ÝÑ‚+'2Ž@@=ïK¤’R€%""§—qÄž׃'ÒÀ/Ãl™°ùÞ›H%¤%B9½ÐVP·,»Ö>>AàÉ‚sgBNÞH¥£KDDNÏ7FÌ…C‹`ïOp|3tyBc½=2‘JI–ˆˆ”ŒÛê÷³‡ˆK9X""""åL–ˆˆˆH9S€%"""RÎ`‰ˆˆˆ”3X""""åL–ˆˆˆH9S€%"""RÎ`‰ˆˆˆ”3X""""åL–ˆˆˆH9S€%"""RÎ`‰ˆˆˆ”3X""""åÌ×Û/:º–Ü ™‰Ú »@.Ðpø{{t"U–,‘šjÏD˜{ Ôj õ@âX728ôý_ìíQŠTIZ"©‰â>ƒYCÃs`èk FÀÐÉpáІ¸½=J‘*K3X""5MV*,"GÛìÕĶàÉŸ Xõ78o1„wƒã½=R‘*K3X""5ÍÖ÷ =2ŽÂöO¡ÍŸa̸<üjÃÞÉÐpZ ©û¼=Z‘*I–ˆHM’ë^‚&W¡…ÐùYèò,5·¯%·Çÿ uû[çí‹TI °DDj’½S u/4»œ,¨Ý!ÿëu{CÂ|8¼Ô¾Žè^ñc©`‰ˆÔ$ç@p 4 ~u`祿ײ3,±½n_HXaíl7¡ˆ”š,‘šÄ훓Ð -o…-ïAÆ1{mÓ[p|ô| æAýþÞ«H¦KD¤&it.¤í·ÜªVwBv2|S&v€UOر½“àè*Ûe("e¢2 ""5I½à€ýÓ¡í}pþj80ެ„Ú¡þ@˜{5t|š\îíÑŠTYšÁ©I|ƒ ¤$m³¯SöÀñ-àòO,º¢Î‡NOzwœ"Uœf°DDjO¤ì¶DwO6,¸ ²S!°!7†7AÇ¿«ÿþ™dË™õú@ôEê™(•’,‘šdó + "G@r¤ì‚!?Bô…ÞYÉŃoÀFÀ7ú}1—x{T"ùTâ_QDD¤\¥‚ÕO@ì-ÞÕÚä¸ýó– «Ç-ïBãK-,+ R÷x{T"hKD¤¦Xý8ÙÐåyûÚíu:Ãáe^V©$n„£«m™så£v¬^?ïŽI¤ °DDjгmæ'°AÞ±:maUQ»­ÍÀ%mƒÌDˆ¹Â‚D‘JF–ˆHMÚÊf~re³¶8áU¬NŸ÷½=‘ÓR–ˆHMÖ7ØŸ7Á´¾ºÚþٻ㩆`‰ˆÔ¤íƒ£k`jo;tÞ"¨Û˻醴D("Rì ë^€Ö÷X¢xæ1 ®ÂZ{{d"Õ’f°DDa³H IDATª»Œc°ðhtt{Õ tÂÙÙ=¸ÿW˜>¦õ‡­”ÿýEªX""ÕÝÊÇ ó8txÌZá¤'@ƒ!°ò ¾ÊCR̸~n-wüêXP·ozùÜ_¤ŠQ€%"RZ ›ÿ Ÿƒäí°íøí<û:ã,¹³|Þgñpd üF·¡?A£0ÿwv |ÞC¤ Q€%"RÅ}µš@뻬Ñ3XÀ³øO¶\¸ý3ØóÓ™½‡ãXñϨÑÐäJp¹¬—a¿Á“ «Ÿ9óÏ!RÅ(À’ò1çj˜Ò ÞnyžLoHD²’Áå nˆ ¾¡Ðä*HÞa» ƒ[ãç²r¹,ˆ;ºÚ‚­\õ¬Z¼_Ø™‘*F–œ¹ÃËaç—àòø°ðV˜>ŽoñöÈD$·¸hZ‚Í`5¾Ì€Úí`ÏÐåE8¶Î(Ÿ‰.Ïá…°ëk ²vO€I -¢Î/—"R•(À’3·å]h‡–@ÒflhE 'u‚Mïx{t"5[ì­ö¼5§úy×!´5Zd9Yþu¬—ßίÏì}³@jÎÕðm}˜u 7†QK¡ÁÀ3»·H¤KÎLZlÿ‚£NÊ÷Ùi–@ëx¼;F‘š,°4»Öþv}gÿV‡ÿž±YçÃK-9½á3¯þã­M«;`ØT8g:DT±6<"åD–œ™_Bv:]e dƒ>ï9yáÝ,ÙUD¼§Ç›y̾ –?Ù©ÐîA¸h‹-çe§BÌågþ>þµ!öfèü DŽ<óû‰Taªä.gæØZK`u¹­»}H¬%Ô:9 ³M¯õîøDüB­|ÂÆX€µþÕü¯‡w…ЖÞ›H5¥KÎLnãØìœÂ‚û§Ûà@Ì¥Þˆär¹ í}V›êÈŠü¯©¡H¹S€%g&qd.ä‚"!4¶Â‡$"ŨÓÁ"rV)9FÎÌ€ÏmGØÒ npùC“k`Ø4¯MDDÄ[4ƒ%g¦Á ¸h#ß {'ƒÛš^ þáÞ™ˆˆˆ×(À’ò mîòö(DDD*-ŠˆHÙìù –ÞG½=‘JG3X""•ÅÁù€õû{{$§·å¿°èö烴cXäšÁ©,üÃaÇÿy{%S»£=wx ¢/òîXD*!Í`‰ˆT¡±Ðý o¢dê÷‡k=V_KD P€%"RY¸ý¼=‚ÒQp%R$-Šˆˆˆ”3X""Rý8Ž·G 5œ,©>ür.|×â>ñöh¤S€%""gÆñx{yöüñ¿@ÚAØñ¹·G#5˜,)›¬TXõ|Y ¦ô„ÍÿÌ$áðœ?8²Ë«C‘šM»ED¤ôâg‚ßCênhu$ÅÁâ; qôxÓ{ãò k³áðÒœô"Þ¡ÿúDD¤ô–ÜuaØk ÙðUÔjîí‘Ë u{y{RÃÕ¨%Âäädž|òIFEDDn·›qãÆ8鍊nÂívx´k×.ßyÛ·oÇív3kÖ¬Šú""ÞçÉ‚ã¡ÅMyÁÕò‡À“nmsD¤fÍ`\êk=ëÓ5|øpüüüpçD’½¿¿?{÷î-×±ŠˆˆÔ$‘‘‘dff–›••åµ1)À*¡ãÇ“@ýúõK}­Ûm…>>>øúúæûË(×qŠˆ”ZV2ìõ¡þ Ðæ©b‚ƒƒIOO81‰‘[ À[`"==ŒŒ BCCóöÙg5jT™ï=mÚ4ºwW>©$Á¦·`÷wd„¶‚F#!ià@ÎÞÅžkwPð%•ÒÖ­[ =¾lÙ2zôèQÁ£15.Àzûí·9zôè‰e¹~ø;wpÏ=÷pøðaºuëÆØ±ciÓ¦ S§NeòäÉŒ=š1cÆxmì""寓 ¿„€úÐþhz-¤ì†­ïÃþiÚR÷Û×9©-ÿ½ßñî¸Eªˆ`½öÚkìØ±°uÚï¾ûŽo¿ý—ËÅ 7Ü@xx8]tÓ§OgܸqdggÓªU+^xá|ðA/^D¤œZ ™Ç`À6+¡±Ðpˆ½ž¼~h Nà‚f¿ƒ-ÿƒ¡Ùµ^ºHUP㬸¸¸ÓžóñÇWÀHDD¼hÿ/àû¦ÀÆ7aðh|qÞë{§XpuY<,½vþ4‹n‡z}!¤¹÷Æ.RÔ¸KDD€ø_ ÁPhÿH‹‡F#ò¿žºÜþàýÆÙlWü ÈN±ÆÎ °DŠ¥:X""5Qæq  ‚"¡ÿg°çGXù8dµ×£/O˜n?hv½W¸,0‘biKD¤¦IÚn%öüh»W?ë_µ×Ì„aS!¢'Ôj Ë„ú a-)ÖéÞ½H• ,‘š"eL ?4‡³¡ÙXpùÁæw¡Í½0r>^s®„ôèô ø†@üo¼²R!úBo ‘*A3X""5ÅÖÿÁ‘ÐïSh<üBìx@„RõúÂàï`æ…ðmŠÿÚ¸Ôƒ&Wz÷3ˆT °DDjн“ j4¿.ÿñ€z6c9.Ú ‡Àáå–ÜÞö~ˆèµÛƒ[?6DJBÿRDDj‚¬T8¼b.-øšÛ?¯˜(@­{h¶J¤Ì”ƒ%"R¸ý!°!$R ððRH˜oíqD¤Ü(À© Ü>Öê&n¤È;¾âk -nòÚÐDª#-ŠˆÔ­ï„õ/ô–Oåû†Áß+·J¤œiKD¤¦¨ ¿FçX³ç#+ æ ˆ¾øô׊H©èW‘š$ê<{ˆÈY¥,‘r¦KDDD¤œ)À‘³'3 æ^ {&y{$"J–ˆˆœ=Ç7ÂŽÏaæ0ç*HÙëí‰TX""röd§Ùs§§áÀL˜ØRã½;&‘  KDDΞìT{n~´¹<yM¦Eª1•i‘³Ç?žh.74¾|kywL"@–ˆˆœ=ÝáÜ™pl-6VQS©`‰ˆÈÙÕ`°=Djå`‰ˆˆˆ”3X""""åL–ˆˆˆH9S€%"""RÎ`‰ˆˆwdgÀ¶àð2p<ÞH¹Ò.BñŽÝßÁ‚ßÛŸý# áPh}·=‹Tq °D¤úÉ<{'îoáè h0Ú? !-¼=29Yü m-n†”=7Ü °¤ZP€%"ÕËž‰0ûrð¤Cx7¨?vO°B—#f{{tr²3­>Öê' vgp2¡nooJ¤\(À‘êeÝ‹V=¼ÿxifÇv_³ÆÀ9Ð` W‡'92“ q=d‚[ûœåBýÞ™H¹P’»ˆT‰›ààh}O^p}!Ôîë^ðÚÐä~!Ðû=[\ý¤W>ÁÞÕÛ#)šÁ‘ê#îcð‡˜Kòw¹¡ý#0ÿwpx)DôðÎø$¿–·Ú#uœg³Xn?oJ¤\hKDªý¿@ä(ð ,øZÓk ´5¬~ºâÇ%Å Š„&—CÔ(oD¤Ü(À‘ê#ý ÇþšÛ:>{~´ºK""g‘,©>²’Á7¤è×›^AQ÷IÅIDj$X"R}d%YOQÜ>Ðx ìú<™7.©q`‰Hõàx,Àò -þ¼–·CÊnØùUÅŒKDj$X"R=d¥Ø³oN€µé_ðó0Xölo%•¨ÛÛ ’Šˆœ%*Ó "ÕCrœ=6°@jí ¶\¸klxÝ^k8†ÿ ½ þïUDª=Í`‰Hõ°ã ›½ª?BêèóŒÙ—'@ƒ¡àdÙ¹Ý!q£U—ò‘ÇÖCZ‚·G"R)(À‘ª/ylxboŸË¯ lõrÚ®Ô…ôP»£}Öpòf½ä̤%ÀÍ`b{˜ÔÑÛ£©`‰HÕ·ò¯àŸǽ?A£‘¶k ;Ýf¬êäüðÏ8jÏþ^nµ“´²ÓÀå“¼Šˆ,©ÚÒÛŒU»‡,Èr¹¬’{Æá¼s/'êt²¯ÓöÛs`ƒŠouT··íÎt@Ó«½=‘JAIî"RµíüÒr«šÍ;ÖôXýŒåíŸKî†à&ÞÝ^?¼©ï]yq¹ ÷»Ðë?ögÑ –ˆTq;¿†Z- ¨QÞ±V²àiBŒ5xŽ:F/ß [Üú>ÔhˉR~\‰œ KDª¶ˆn´’¶çó·•F#`à×0à3Kt[Flù«æ>ëH;è•a‹Hõ¦KDª¶vCH ˜ya^ò:Ø’áЉÐäòüç»ÜÐó-<æÁ”ž ²D¤Ü)À©ŽŽoƒókÆX`=ò#¤ì‚ï"á·QV²aûÿY±Ñ„…_×øbµ²S`ÁïkÆ÷JD*Œ’ÜEª‹Ô}°ñ-Ø3Ž­³caí í}VÊUEŸòdBÊiVô9µÛÃè•°ë[Ø7VüõÿÛ»ÿ¨¨ë|ã¯Aù!  $ „ÚV·.†byM좔vJ‘r1ÜmOž5×Ïš·¬S®n[§Ô“yÒã9efxLi«»•ÚÑíÝ»¤ ™­W6­ÐüøägÌ÷þ1ËܦAÍüÀŒð|œÃÑùÌg¾óf¾ó^ßï÷3߯älv6 r¸”y:X¹^úäné/¹^+0à*ýÄàeO¾ôå*×e`îø“4n§'íž%þÜ×Õý4Ÿ/’ #¥ÿL”jË.Þ·o‚tÃ|iÜviêiiê)íUéÔn©ñØ…›åš«upµÑÒôl, »¨-•"o•Î|!xÁµGkP†ëz|7úººË×Ö"íV âºNõöÿØ€`©w„ëÛƒ6›TÕÁ…o–öÌ—šO»B˜#Ë\íz<дžsMûìߥÓeRM±tö ×EŽc&º.sµ±JÑÿ&5—‡IÇÿëò—4Ðu Âò®Àö}!±Ò?V¸ :›¥3R6H, {8½Ïõoß¡®C\ó‘Â¥Wé¡/›M½ÉõÿÚ=ÒÉÿùiÑS—».“ó¿Ïy¶÷O•Æns¬!³¤à˜+¯þ‰Ip~ç Q#¤€Ë{lÔש N»n7Tº‘ý{±ë[vW«àA®óXÝ-Eùi'²ìÿ¯Ò ¥ýK]‡Omv×áÓS»$g‹ïº "`þâÌçÒÎ±Ò ¿“R^¸¼Çöê#M:$5V¹ööœý»;Ù5éj70]šzJÒœ%ü_ž”šNHçKrJA×H)ˤkƺæ§]­ß°à·X€¿ˆ¼Uº}‹kÞÑOa³¹æ…ĺÎñÔ\iê$¥­5S ü,ÀŸ žêë °_À0´k<&øo_W  `@»^AÒ.—àʰ ]`„4æO¾®@7@À€v6›ë¼Xp…X†° #`FÀ0Œ€` À0€a,ÃX†° #`FÀ0Œ€` ÝVll¬}].àÚk¯U||¼¯ËÀEÄÇÇëÚk¯õu¸€ÄÄD9_— ðu@giii‘eY¾.ÐÒÒ"»m<ÖÒÒ"§Óéë2pÍÍÍjmmõu¸>ÝÐmÙl6_—ŠÏ9ÿEÀ¸8¿“JfK{ÿCjkb°Ÿcýø7º5>€€Ëpx“tpµTõ¡dï#‰=$þŽõã¿Xè¶øà.Sð é†ßIYû$ÆßcÒ¿1ɽ 466J’8àãJz–ÖÖVÙl6•••ùºt€õã"%=(ýs´O fù'ÖÏ¥µÿÝmÿ;Ü•l¸Ó(77××eÐ#½ùæ›úùÏÞ¥ÏIÀê555Ú¾}»ìërèUQQ¡ÌÌL 0 KŸ›€`“Ü #`FÀ0Œ€` À0:UII‰æÌ™£›nºI}ûöU||¼rrrtðàA¯¾N§S«W¯Vrr²BBB4`Àeddhß¾}^}?®Y³f)66VÁÁÁJLLÔ¯~õ+¯~þóŸuÝu×)::Zo¼ñÆEkýë_ÿ*»Ý.»Ý®ÚÚZû^ýu÷}?ü9qâ„Gß„„-^¼øÇ¼<ÝÒþýû•­¤¤$…††***Jééé*((ðê{àÀM˜0AaaaŠŠŠÒC=¤šš>²ÛíúË_þÒU¿B·wþüy=ýôÓš0a‚"##e·Ûµ~ýz¯~3gÎìð=à 7xôc™×Üܬ… Êáp($$D#GŽÔŽ;¼ú1†ügrG§zþùçU\\¬ììlÝrË-ª®®ÖªU«”ššªO?ýT7Ýt“»ï/ùKmܸQyyyš;w®êëëµwï^]³gÏVxx¸fÏž­[n¹EÉÉÉ^u:Nýæ7¿Qhh¨.øû,Y²D‰‰‰m·m6[¾LÏ‘#GT__¯™3gÊáp¨¡¡A………š1c†***´hÑ"I®õ3fÌõïß_üãUWW§_|Q_|ñ…vïÞ­ÀÀ@ÿ&Ý×É“'µdÉÅÇÇ+99YEEE|ÏöéÓG¯¾úªGÛßó0oæÌ™zûí·•ŸŸ¯¡C‡jݺuÊÊÊÒǬѣGKb ù= èDûÛ߬ÖÖV¶ƒZAAAVnn®»í­·Þ²l6›õî»ï^r™'N´’’’¬ÚÚÚ‹ö[³f5}út÷íÇÜZ´hQ‡}W¯^m 0Àš7ože³Ù¬S§NyÜ¿nÝ:Ëf³Y{öì¹d} ÖâÅ‹/Ù¯'ikk³’““­Áƒ»Û~ýë_[¡¡¡Ö·ß~ënÛ±c‡e³Ù¬µk׺۾ùæËf³YŸ|òI—ÖÜ577[Ç·,˲JKK-›Íf­_¿Þ«_^^žvÉ屎ÌÚµk—e³Ù¬eË–¹Ûššš¬!C†Xéééî6Æã!:Õ¨Q£๣tÈ!ºñÆU^^în[¾|¹ÒÒÒtï½÷Êétêüùó.¯¼¼\Û¶mÓ‚ Ô¿555¹¯ÇõC 8p ûöÀU__ïÕ¯¶¶VO=õ”–,YrÉ-s˲TWW§¶¶¶‹ö'»Ý®¸¸8-ê·ß~[÷ÜsâââÜm6l˜6oÞì‹2{ŒÞ½{+::Zҥ߯–eÉétêܹs]Q$* @<òˆ»­OŸ>zøá‡U\\¬ÊÊJIŒ!GÀB—³,KÇw_¶àܹs*))ÑðáÃõÄO(""BaaaJJJÒ–-[<Û>!::Z QHHˆ²²²tøða¾#GŽÔ† TTT¤={öhÕªUºãŽ;¼êyê©§£Y³f]²ö;ï¼S Õ½÷Þ«C‡yõéɇ¿¯¡¡A555úꫯ´bÅ mß¾]=ö˜$©²²R'OžÔðáý7bÄ}öÙgm¼¦¾ÓÐРððpõë×OQQQš3gN‡@¬#s>ûì3 6L}ûöõh1b„$iïÞ½Œ¡«s°Ðå TUU¥¥K—J’¾úê+Y–¥M›6)00P/¾ø¢ÂÃÃõÒK/éPxx¸233%É=9þ‘GÑm·Ý¦Í›7ëðáÃZ¼x±Æ¯}ûö¹¯÷8jÔ(MŸ>]ãÆ“$åäähÊ”)µìÛ·Ok×®ÕÖ­[/úª_üâºóÎ;®ÒÒR-_¾\ééé*++óØ‚üæ›o̽XW±ùóçkíÚµ’¤€€­\¹Ò½E^]]-IЉ‰ñz\LLŒjkkÕÚÚªÀÀ@%$$\t!:ÃáÐÂ… •šš*§Ó©­[·ê•W^Ñ矮¢¢"õêÕK’XG†UWW_plHRUU•®¹æ¶öc ù ]ª¼¼\>ú¨ÒÓÓ•——'IîÃvµµµúôÓOÝ[i“'OVbb¢–.]êXí}cbbôÁ¸—§|P7nÔÃ?ìnùå—5oÞ<µ¶¶êg?û™W=sçÎUVV–ÆѺ³³³•í¾=yòdeffj̘1úÃþ Õ«Wÿ”—£[ËÏÏ×´iÓTUU¥‚‚Í™3GÁÁÁÊËËScc£$×a ’äºH+“t}ëÙgŸõ¸=mÚ4 6L‹-Raa¡rrr|TY÷ÖØØxɱÁò"D—9vì˜î¾ûnõïß_………î=Fí{œÝáJrí5ºçž{´{÷n9N¾Ó¦MóXöÔ©S ââb¯çMJJê0\½õÖ[*..Ö²eË~Òï3zôh¥¥¥uøÕiH×_½Æ§ÜÜ\mݺUš7ožšššÜë±¹¹ÙëqMMM’þ]ÿäççËn·kçξ.¥Û ¾äØ ‘Äòg,t‰³gÏjâĉ:wmÛ¦Aƒ¹ïs8’äÞåý}ÑÑÑjmmuÏù¸Pß^½z)22R§OŸþÑ5-X°@ÙÙÙ TEE…***tæÌI®S TUU]rqqq—õœ=Ù”)StöìY•——»k´*ü¾êêjEEE±åí§‚‚‚éu®8˜ÓáçOûxq8Œ¡«‡Ñéššš4iÒ$:tH;vìðÚ›äp84hÐ ÷7c¾¯ªªJÁÁÁ “$÷„ΣGzôkiiQMMÇ·/åèÑ£Ú¸q£6nÜèu_jjª’““UVVvÑe|ýõ×—õœ=Yû! »Ý®ØØX 8ÐëÜe’´{÷îÏUÿPWWwÙc —'%%EEEEª««söIÒ®]»$IÉÉÉr8Œ!?Ç,tª¶¶6åääh×®]Ú²e‹ÒÒÒ:ì—““£#GŽxn«©©Ñ{ï½çž¤.IcÇŽUtt´ tèP¥¦¦êÖ[oUDD„ÊÊÊôÚk¯)66V%%%lÍÏ}÷ݧºº:3F‡CÇŽSAA¾üòK­[·N=ô$×Ä””õë×O¿ýíoUWW§^xAƒVII ‡7:ÙªU«tæÌUUUiÍš5ºÿþûÝ{=æÎ«ÚÚZ¥¤¤húôéºþúë%IÛ·o×Ö­[5qâD/™À¼œœ½óÎ;ÊÏÏWRR’Ö¯_¯ÒÒRíܹS·ß~»$ÆßóÝ9NÑŒ;Ö²Ûí–Ífóú±Ûí}¿þúkëþûï·"""¬küøñViii‡ËÝ´i“•œœlY111Öܹs­úúú+®÷™gž±ìv»×™ÜŸ|òI+%%ÅêׯŸÕ»wo+!!ÁzôÑG­'N\ñsv7›6m²îºë.kРAV`` eeeeY;vìðê»ÿ~+33Ó µ"##­3fðšv‘„„±Ø>Nív»uøðaëÌ™3ÖŒ3¬¡C‡Z¡¡¡VPPuóÍ7[Ï=÷œõÝwßùºün¯©©ÉZ°`cYiiiÖG}äÕ1ä¿Øƒ`s° #`FÀ0Œ€` À0€a,ÃX†° #`FÀ0Œ€` À0€a,ÃX†° #`FÀ0Œ€` À0€a,ÃX†° #`FÀ0Œ€` À0€a,ÃX†° #`FÀ0Œ€` À0€a,ÃX†° #`FÀžËã*£IDAT0Œ€` À0€a,ÃX†° #`FÀ0Œ€` À0€a,ÃX†° #`FÀ0Œ€` À0€a,ÃX†° #`FÀ0Œ€`Øÿú3ý ÁkõIEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/coords_overlay.png0000644000077000000240000015210312436367710024453 0ustar tomstaff00000000000000‰PNG  IHDR€¿6ÌsBIT|dˆ pHYsaa¨?§i IDATxœì½wx\Õÿÿž¢Þ{—\$Y¶ÜdI¶ 6ÆÁ6YÃÚ'Øüÿ/làa“lɲ$ÀB¶„lYö›pKÖ1l“¡¹H²Š%Û²ºUl•‘FÒH#M;ß?ÞºIV™rgæÊ¾¯ç™GöhtçÌsΧžÏG#„PQQQQQqm  ¢¢¢¢²4QˆŠŠŠŠŠG¨DEEEEÅ#T¢¢¢¢¢âªQQQQQñU€¨¨¨¨¨x„*@TTTTT‰œœ$%%Íxm Æ=×›››QRR‚¼¼<<øàƒ#<÷ÜsX»v-Ö­[‡Ã‡/8Φ¦&”––bÏž=°Z­>ÄSO=…ÂÂBâá‡V̸ ¡¡EEESððpüú׿VÌø¢µµ7ß|3 ±~ýz˜Íæ%1nE!T„B|ðÁâØ±cbß¾}SÏýö·¿BaµZÅÖ­[Å{ï½'„âùçŸ=ö˜Bˆû·>ú¨BˆcÇŽ‰—_~Y´¶¶N=ˆq———‹Ë—/‹ÄÄį Ô¸çãŸþ韊wÞyG!ÄwÜ!Þ~û퀎±¶¶VlÚ´ILLL³Ù,ÊÊÊ„Ñhœwœ>ú¨¸té’øÙÏ~6õœ/èîîË—/‹EØívqã7Š'N|\sa2™Dbb¢UäøfsÓM7‰?þX!Äàà °ÙlKbÜJBµ@&Ùºu+"##g®¹8zô(vìØððpEŽo:õõõÆ7Þˆ…V«Uü¸•†*@\`ddï¼ó¶mÛèîîFFFN<£Ñعs'Þÿ}:t=ôP †;/J·Á`@||üÔÿ322ÐÕÕÐ1®]»|ð†††088ˆ>øóŽóСC8xð >þøcìܹSöñHDGGã‘GAvv6233±sçNÄÄÄ|\sñúë¯ã®»îB¿"Ç7ÆÆFDFFâ‹_ü"Š‹‹ñÔSO-8/•2n¥á5y #„Àý÷ßC‡Mmló¡ÓépäÈ?L>–¸}=ÆÕ«Wãë_ÿ:¶oߎ˜˜”••A§ÓÍûúììl|øá‡>Dss3~ü㣽½¡¡¡¸í¶Û¦,ã@Žk6ÃÃÃ8qâ^ýu Ïûº@o66› }ôjjj””„/|á ÈËË›÷õJ·ÒP-ih4š«ž{üñÇ‘€o|ãSÏ¥§§£³³`4ë·1ÎÅ\ãž‹@Ž{ú0000õÿ®®®)áÈ1>ðÀ¨¬¬Ä{g   ¬^½úªq¦§§ûm<PQQÏ}îsˆEhh(vïÞ'N|\³9zô(n½õVÏùýz|³ÉÌÌDII 222Œ]»v¡­­MñãVª™†bÆÿò“Ÿ ºº?þñg<¿gϼòÊ+€W_}·ß~»ßÆ8³Ç=÷ô1j4”••áwÞ>|xj,coo/f>}·ÞzëUãüâ¿è·ñÀªU«ðé§Ÿbbbv»|ð >®ÙHî+`îï7Ðã›MII z{{a4áp8ðá‡bõêÕŠ·âh_AÜrË-"))I„‡‡‹¬¬,qâÄ ¡×ëE~~¾Ø¸q£Ø¸q£øùÏ.„Âl6‹½{÷ŠÜÜ\±mÛ6Ñß߯¨qÿíßþ­ÈÌÌz½^dffŠù— 踧133SœüðCÜtÓM3žëééAJJŠÛ×2›Íhkkí·ÞŠÄÄD¹†¨h®+ò»ßý÷ÜsO ‡¡¢¢r óꫯâ+_ùJ ‡á®+²lÙ2ü‚W¯^íÑ5l6àŸ¾ûï8ú›ÓˆIÃîÝ¥xà/{eÑø‹G÷ìÁçÿò/ñù½{§žÛ¹s'Þ}÷ÝŽŠŒá‘Ý»ñÓÿý_@a÷ò«ÅÅx¥²2ÐØÁÝÛ·ãç¿øB³²=”)¦Ï¥÷~ùK¼qä^8z4À£Zœ±±1üøÇÿ…ßüæ LÆaìÛ÷9<ú×ÀÅãUSœ?÷ÜsÏÔ>s]è40RYY)ˆÊÊJ·ÿÖh¢¦FˆÓ§…¨«¿¸Wüéš5>¥ï¨øãÅçgXLII Ðh®f}R’0ÖÖzWQª°eb0Ä- BŒz(3˜šKv»Ø/*ËË; w°ÛÅWòòÄ}z·8sfPœ8!Ä… BŒ¹~ oö—¥ŠD_»èèN:;+€ÒR °0?9ú+ã¯öí ô0]¦ø¦››œŒŸy&ÐC™“ì¢"üúg? ô0ÏþçbýªU€Bc /ýÍß99ØTR衸Ìc_øÌIIøù›ÿ…¢¢X”•IIÀ… @e%Ð×çùµF#JKKQTT„ÂÂBüèG? œ’üÞ h¨o6çÏüI PXÌ*z‹—ËËqC^0Ù³b)𯽆ßüð‡Æœìûò—ññ{ïzŠçwo½…›÷ì ô0æÆfÃ;?ûžÿïÿôH\§© %7ߌ7>úhÆÓññ@Q°v-04œ8´¶ÒíÑÑÑøè£PUU…òòrüà?@oo/üq<ñÄhllDOOÏÔ ø_|o½õöíÛ‡ãÇËõ)}‚¢ˆ¿oüÀpæ µŽÔT`Ë + ˜¯¦ž^¯Çþ'Ÿšš“É›ê7ò׭ÛÇ{§Rùˆ»îº ›·oFF=E³oÛ6ÜªÔ mSÞ8sË—/ôH\ãòeÀlÆ]ßú´Ú¹·Ã 7(+BC¹GüñÜzëhoo_ô-´Z-BCC0S+44¡¡¡×DéxEѺño¾ù&çß½{·G7^ »›.ª˜`ÍN—Ñé€9«Š‹à`w?¦ßѯZEó*)iF—À@Š¿øë¿úû¨(Ÿ½tOÚí€Ã1ó!ÄÌd.+ž225š™­ÖùÐéøÐjávÖþ¿ýû´4ß½‡¸óN`dú‚‚@Å5ŒF.|]m o{Z`0Ä 'g6nü ää8ðÒKÿ4¯˜Ò|ÓM7¡©© Ï>û,,Ë‚¥ãï¹çdggãàÁƒÞ}F£høîÆÛlÀ{ï5á[ßúWüÇ<’’øy-E ¡«ºš“q‰¤ôz %èêÂóÏ?èÑÌ$>ž§E4X› ˜˜,–«V+v»s#Ÿ^°göf/=$ €?Ÿû—ÿ‹¡!ç5„p ›ÙHLB̃^QÏ~s I?>V+ÿXaü˃ÙÙ†kH~êÒR¤}B‚?ýé!<ÿü!<ýôìÚõ ê˜÷õ111¨©©Aoo/n¾ùflÞ¼yÞ×.¥ÒñŠ ¾¸ñ¿ýíÜu×?ch¨?~?6nŒõ~ÏŽ–-jki‘(œf¤¥)Jà c˜Ìã˜ÍÀø8Ó7f½ž›­´ñÜW¥‡Ç Ál À y.e³9œ$ðÆÆ¨ [,ŠÓ?gP-âÐPf7‡Y‡ ÅÙ¹££üp ?8€ã¬©6làDò‚àïÿþ.üÍßÜ…gžù¾óû|}rr2¶mÛvÍ”ŽW¼‘ãÆLúÖÿõ_ÿÏ=÷·¸÷ÞWå$Rc#°@sE Õ2ÀÓÞ¾¨¶/7v;oÓè(7ÏÑQnœ’¶2ˆð¶„&G#6Ö¹Ê&ˆ^χ«G]l6L Q³º8³6–Óü½VËk…‡S€FDðß¾t¡ÍÉÅ‹@~¾ŸßÔ„ §`Õ*Þ(™Ðé€/|a¾ó«×ÛÛ‹°°0DEEahh}ô¾þõ¯O•Žß½{7>Œûï¿_¶ñø E ¹o|Ô¤_ý·¿=‚M›6ùfÐË—uu ¬(]£ÈÈ ’•åµ&6 ãá&šÍ\¿:s³‹‹ã0fÄ ÑÀ`/-û˜–z=ÃAS!¡Þ¦M S!x_%Ü×G¡,…KDÿ62’?}"„F4"—™úz®Ë¸8¿½e{{;xà! Ñhðè£bÕªUxæ™gp÷Ýwãá‡ÆŽ;¦êK E %{ã ™<æ×‰ê6 ·´´x¥= A1<ÌÇè(Ÿ rn~II¼.iÆqq“ÊL¤ Ë4) ÑP‘ç=žŽÃÁïbdèíš›iýiµüN¢£éqòZolÖ¯÷ò"~ µ•>'?+v¥¥¥¨ªªºêùÜÜ\THg–(Š KöÆk4ŒƒTTpaÉh*ËNr2ÐÖFsÁ… 2!($††¨xšÍ37¤ìl*¢^¹P¤˜ŒÃ¡¨øLÀ17ZüJßËì„6»Váð0åôØŸˆàåccÝ0&úúø =Ô8Eo/'íRˆO.!-@–4z=ƒtÕÕÌôð‹H6òòèÃ^»öª_™ÍÀà ££ QQÜdòò|X¶*.Žošà£7X‚ô÷2TyÕéhyÄÄÐ{ P1¥Œjks~×ÑÑLŒ‹'ñ«¹Ùå4Ø€1<Ì¥ôq.A¼«]„…«WUUœ¼~lºˆä2È=÷n‹Åé…Ëɹú$¾OILzzT2ÁA`åJŸ\Z£á÷ dfò9‡ƒ{ïà 3«­V·„ •°.Z°JVŽ&&÷(.V­Y àoþ!6–+²®X·.У¹ŠáaVb[ Û›ˆ*Y…„¶zÔ &†V‘ ‘µøqÔj.-)QÏlfņÆÌÙTˆ„Ê{…Qæ=«®æº[|—"ªñiiô ´´0h@Ìfº­ ZQQ\üY7„C3d )#—_Ú,íök#×[©ö˜°0*ÖKÀâ0‘¤…ÁÀ8ºÙÌß'%qNü¬cM -6¿šÎתñ¹¹œÐ==<î' ‹Þ^Nø¸ çPÊòói))ÅWœÀÁ''z$§¿_9åKìvàÊ`Ë„h˜Ô$%6QA©­å–¸8~}nÄþåáüy§$Sñªñ'ëÖ13+4Ô§Zþø8F_HB‚‹1ŒÐP¦ß ʈ=$&Òù® f­ZèQæfú´æˆé…‡s®åä00?8HYÓÐÀ镜Ì}ݧa“ŽÉ’" j¶u­¢ ¢ÕòXEºUµqaL&.Tƒ•))VjÈÍeaH%¨(µ2/@U^¯WF†ÅÂT-Î i4ôºIž·ñqàÕÕüR«^Ëšl0PsòÕAa•¨Äßñlˆ”Þë…hˆÕ¨FZiitùzµÏQx\¾¬ —IPËgT®Y”b^•é uZ'v;­äsçøõ&%qºyˆ7™8¾ÒR/.¢âª Ôફ©)¹±ã³JŠÑÈýôt@öêÙË—§OS= ´Ö›˜È T Â,Pô÷s× 4cc4#d¨® Ó9K£;üˆ ̺MJâ¼vË@·X€³g¹žÔ¤ ¿¡ @Ïyþ<›,ÀØÐÕÅ}4*ŠY0>m¹ ÓñM::_ž;1‘>÷ëY€˜LÊÈ$òQÁD­–±‘äd “¾>. «•:LZÚ"]•±ÂB埈¿ÆPH ÉÌdûÃöö«4L«•^¤+W¸&22žð›A•œ<É7¤Fq=¢÷Ýð°³ Ñj¿KI¡›«§‡É‹ §bròGajkÙJ!Z-¾éoTh xR=<"1 ýýl’f·ÓŒ/.Ðþ­ÑЕÕÚJÉHBCé:‘1é`É Sù¯¹x‘¾Ñéœ) ­ðòrcYY“ò¢±‘j¦^@Pˆ0ç­GÇoê0Äìp¬^­½25•åÞ³³«'&r#•jl\Oô÷¾·ŒÁ@K0€G̓ƒ©Ï,_Nc¨£0µö!5ØŒíËÕ,@¨Åa„4Ï+*€ :$ÜX€²°äf[”!<$rs¦¦ÀŽA ×#Òñî@ÒÔx+tÑÑ@aú J“ÛT˜3gèÅ ôÈ®?#@î¸ãÄÇÇcÿþýSÏ8p7nÄÚµkñ—ù—°OöúÇwÞ‰¼¼À±^(F€lݺ‘³R¥´6› H˜¤¦¦"44Û·otww### £Ñعs'Þÿ}:t=ôPÀÆl·33÷Ä *ÍEEôN¹Üå-'‡šVW—OÇé¶B¤ÂŠ×LáµÛ9ÿ”TOª®Ž‰.VfŒç¹ÂU«èÖ:}š§ßF£Á‰'PUU…?üá€ÇO<ñÑÓÓƒwÞyðâ‹/â­·Þ¾}ûpüøñÀ ØE/@Þ|óM\¾|Büâ¿Xðµ:GŽÁûï¿t?÷=¸ç751ÕP§¶l¡›Ê£²ÖkÖÐ|}œÎÔ°@'(ˆ‡c®}x°µ•g+]‰@¢¥…V‡JÃÃéÞ**¢+ùäIÊF!|0ÎÓÞP'N`×®]fzRt:L&ÆÇÇðšø £(¢™g²aÿþý(//¤§§£³³`4ë¢FÒ××8úŸÿ)ÃhX,ô·VV2ŒQVFEÉ«Þ? «!^¼¨œƒtyyÌ»ÑÑܮ龲Z•U>¦§‡îS/3Á‚‚x‰ÒR*{'OÒSà€»F£Áç>÷9lÞ¼¿üå/a0?­¿KFFº&=‡ÂÁƒññÇcçξœ(#P0Ét m³ÙÐÕÕ…œœØív;v [·nìÙ³¯¼ò ž}öY¼ú꫸ýöÛ]º~RRà7¯½sg'þéèQ¯Æ;1Á*££Œ3Ê^^dz_õ’’Àwè f$?÷4™BŠƒ\'Ž ~÷@Ii»CCÜåeìQ£ÓÑKœMKäÔ)yÊÎö.ÜÓÖÜ<ïï>ù䤥¥áÊ•+رc²p fggãÃ?ô| ~D1dÇŽ¨­­Åèè(²³³ñÚk¯áÑG…ÉdÀøÆŸÿùŸ¾öµ¯áÀÈËËCff&Þ|óM·ÞëG¿ù þéÿüÜ—‡ÿ[Y‰p77$)wt”.*Ÿ6Š £;«ºZ}W®¤.9Ùÿîøxn&vut8¨yÚltñK?çO‡ƒ® I—@w0ÐÆÿK·_«ùÐéøÐë?=®À.ˆDñqNl%Tÿg¼¤Ä'ó^£¡§ #ƒJËË‚ÄÝ·ûÑ3ÏàðOÌûû´Ik.55»víBss3¦¹ƒ»ººâv÷Åßÿþ÷W=÷é§ŸÎùÚÐÐPüêW¿òø½ôz=Þ<}ß~ðAû»¿Ã]ßûžKn«•Çð04¿u‰a0³®ŽG‰NÇUÖÙéÿ«NçÜá58Üc¤ÇÄ Ó}ÜBpS6vi£—’ 6}iÑh„9€§`‘çÄt!$ (é!A£á¿u:r!!ÎGh(!!“ï7<8+ËGÝFêg¾~½Ï-o©ÎVz:É©SüVÖâ €ÃáÀ×þäO0PY‰|ýuìܳçª×ŒÁn·#** &“ ï½÷¾ô¥/¡¬¬ ï¼óvïÞÇãþûï÷Íô!Š àû/¼À§¦†>¨yòkív ­Þ“+|\ w>RS©67Ó $ÙÙÎUæC‹Èá`øgt”?ÇÆsG Ã#@t4´ZhÒ&IÅ9$„{ŽlC‹³Iò\Ênw ¸‰ N¿‘žœ˜˜8#ÐǤ L0Ný&,ÌÇFŸÉÄ›h¡yyn¤.zÏtAÒÑÁIN޳]ïl†‡‡±¿¨+RRðß—.¡º¶vÎ×õôôàŽ;îØív<ðÀ())Á3Ï<ƒ»ï¾?ü0vìØ1P_J\×wžÒRöL‹I„ ¢ÝÙÉ„”-[7LµµÌÎJM Ü8´Z ‘¶6ÝIÓ±X¸‰ŽŒp3›CD7ÐÈHÊ÷°”(h{€¼¥Ñé(<`®¹ û†M› Ð4™vš}_"#™´)“·«¡g,ÍùóŒ±ȦÑpzgdpŠŸ:ÅmaÆpìvýîwñùÛnÃ7ô£¯·|ùrTKm§‘››‹ŠŠ yïgTpEnØÀÔŪ*`ýzô èÐÜÌ}º¬L9ÙŒS}ÕÃÂ|ÚW}Q22¨¢eg»¼{Ig‡‡•–s#ŒŠš iÚa±@ëüÁÊ%ÏdJ.X‡¨à¹«§;¼w&Ï5´´Ð]¦ÕR˜ÄÄðîÆûÒtsë|À¥Kü (œ©ÓQgËÎfòak+½‘:3PSƒ¯~ç;ʈU€Lgùr˜Úúqáåsˆ,ÊCIIh@☠¢Ñ°ŒCE²VÒÊ•Ì&˜Ç§g2±sâà µg©Dt4]fÉ/e·+ç„´œ‹”Ójwz¦­ÃáÐ--´^4 •ØX&ÐÍ[¨³±‘ó)ôõ1û¬¨(°ã˜EPóXÆÆ€†SFu·#÷zÇXØ*¥ms266†Õ«WãK_úž}öY477ã®»îÂÐÐvìØ1U÷ª©© @JJ ~õ«_¹uÇjeüpb"…°‹ÕÀPž25Œ  ZL55ÌP ””KJ¢?1»>F#ÏÜÌ"#¹i­\)³bO©¤„>rÓßÏûêZ­Óúò$«Ïhäü6›9}ââx££M_/%L &šL”z2¦ëÊMxO+ŠbX»g.è`³uâÆ3•ãŠ:H8ßûÞ÷pà 7L4”³@mm-::x05•¥Ââùt‰¤ wöU÷÷‘ZÐèë. §ÿ»UUÎ=½¸˜ñ¢ÂB e÷Š\Ëu±\°@ÜA£¡ÈÎfBÓ–-ô‚FF²ãeùiò·{ÐäX£1 SÉÙÏ|ãFeZ•cv;PT„ø$¶lzèÿÇÊ•_FMMG G0/@ÑÐЀÛn»mê ¡%êêꓳ<ðŸ°Ù¸°f:Mi›“G‰õ¡ã¶›d IDATãéÃ8wÎço%÷¶ÆFÖªª¢f›–…Ò‚”¬En.5[ŸU‰Ž|u<_`·óæùX¥ ¢‘SPlÎ覛"—¤GOÏBTTPoòKñc‡ƒ“iíZeö3w™–`£ÑUUGñðßÅM7ÝžÆÄ„÷£xÖc=†çž{Ÿ|ò ,Zàž{îAvv6<8ï5ÿþïÿ}Ô‡¿þëçðÈ#·.ÜÀ)7—‘ÊòrºÕí fŽrÅ/[&ë¥-Z½½ü·Ô9ôªÞì«& -úËw­ÑÐmg³Î}ç üx¸ܼ;: Û² Z§e³1ÑÚÊ©îLŠ’Ý@¨©a&Ÿ{­{Äà kI&Û<üð!üÅ_Ü‹Ûo¿·Ýö¶Ÿx½úŽ=Šüü|äææâã?0³ÜÉl+088èèˆÆÙ³G•å¢0HNæ*ªª¢Úçú‡ð’+«¯Ïcÿ¹„”2j0poNN¦+jA÷xD_,³ûeA¤ê¼(©â+úû©ø‹öö9]ëõ¼­Ò­¥ÑÞNÙœL…ÜëIC¦—sÖ'ttp!”–.ª¤DFFâý÷ÿ¿üåá+_ùÄOTŠ §NÂk¯½†7Þx&“ V«QQQ—ˆ›Üøÿã?¾áºðˆŒädª®æÊRR™k€îòrZHnjsÃÃô‡R¤¦ò\¥[®¨ü|ºúJKÝ·§$&rG»–Èð°ÿÎaØlÜ ËÊ}iD„³¹ÍFaR_ÏÄ“¤$zQÝ6Ì»ºx±œÏÆï+„ KX§s; _P°ÊGƒR.Š ßÿþ÷ñýïð‹_üõõõø»¿û;ÔÔÔxUà _ØyUŒdÿþýxþùçþC½ž“ê® 5k”s@D«¥ ©²’™‹ø“GFX¶ap!…´4öMð˜ .¬ —ˆŒ¤¹t­`µú·X¦‡ ôz&F¤§ÓÖ×Çå`±ðkOOw!”10@¥¸Ø³±û ‹… bVÖ¢•ˆzè!¼ñÆ3žSzó'_ h2Þ–x÷Ýw±iÓ&ÏPP0™ÂRÎÌ¥ô‹¦¿VªÞ;Ëa=>Nů¿ŸZeF†—Bc6¹¹ŒÀúË%ئKrb0ø/e|b‚I^~ùZ­ÓÕåpÐ29wކEj*÷ૼ?ccŒ—•–*GùhýÕ×Ó_ëB)—çŸþ*…óÌ™3(VšPô1KF€Üwß}SÿVD €´4î••.O:¿é,yRT»•Oº»¹˜33³ôÉÚ•‚&]]þñåKé¼K°ŠéUô÷û¯÷¸ &jµ©© W®0d¨×S¡OL­¬šZÊJJ×íîæœ-.¾6”?²dˆ"‰Žæ¤«©qVaS‰‰ºbÆ¥_·Âœº©©\³~IXZ¶ŒÅƒÒÒ|ŸÏ›˜È¼b¥ÜwoõOáÀÑQnä>Lv•ÌL\ììš.:ß}YŸ]ƒ0¥d2 Á@¾ÝN‹]IÑA ÞÌÉwîÍàU«6¥6Ö—/‘‘YXžv‘©þ økµ|¿K—dO+¾Š°0îPKñqÿðs¹ö°0ÕÍ3×Á°&.ÇÀÞÉ䯤¤îÙ’5”šªˆº[KU€ÈFC7Vg']Z6ø5 *1™h•–N*ÿ¢8s†)Èþ,É’‘A+$+Ë÷® Iˆ²&˜· þ)Ë24ÄïÃß½Ö››ˆ$¬LA¶êèàÓÉÉ&~m¶i2ñäûêÕþK;¿FQˆœdfrqVT,xøH.úû)8ôzºÏ¯*Î+^”Ò{ýÕ[A£á€š›}¯íJq¥¥U»C¿ÌÙ ópñ"ç¥?¹r…δFhÁÁ Ó­XÁÀ{u5§çòå~m==\4.d*ª,ŽâK™,9bc99ëë9YeFº©Nž¤âºneļ•Ýu:¾ ¶–ªŸ¿HIáÁB_¿çµPk|Ü÷úû™fíÏøÃÐMy„–FÃiRZJogK u/ƒÁGãiltT…‡,¨Ä„„p’öôpÒÊ€ÝÎÒ'OÒ}[ZJ¥Õ¥uJ[uµkzåæÊöùçEJå]ªŒù§GS“;YšÍŒ nÜèR #*ŠFʺu<[rêY°ÛéÊ æ›ø¼XÛõƒz'}…VËÉÌÉk·{t›k¿¼œÂ¢¬ŒÚšÛ¡© ÇÙ³Ã#âã©]ùö}–ò¡Âþ~ßÇ?º»±öW Áfc€ÚƒX`HYÓóuò$-n«qñ,[¦¼Sïתñ599œ¼åånm¤’ਨàþXVÆlU¯²VRR(Hšš¼¸ˆ›äOZô%KÙÕßïÛ!XòÅ×qÓ߯ºšß»–•^Oƒ©´”¦G‚¤¿Ÿ®Û ü[¤ò:B þ >ž“¸¶vÑÎngì¹¢‚f}Y™ÌíÏ—/§{áòe/ºQQ”zÃþ{©°âRÄjõíáµK—˜Üᯃ{çÎñ L¶NÇ)»e oÕÉ“.NÝ–Æ_JK—v†žÂQˆ¿›lRÕÙÉÉ= !¸ÖOŸ¦âVVæÃ:k×R3}ô³ðµ"•vH7$/öms»»­¿Î9´µÑeåƒ*Z-¨Í›iÈŸ<ÉXÉUØíÎ&kJ;ñ~ ¢ "eDIfþd\äÊ  ŽEê¸y”Þ{þ¼â……Q*úÒJˆ‰ñ­•ã ßÖ kiá®ëÓz}}TH|œ¶­ÓѵURÂÛW^>ík§éž‘áß„ëõH X¹èëÃÐUh^‡¸Ô”–úYYÒë)DüÕW=7—Å‘|åï—â óæ3+ƒ§è|Ū·yy¾¹þtFF(¬üUÊœ®” ††P Î#¤dÿÎ;©(ǹãŽ;ýû÷_õ»}ûö¡tÚäÇwÞ‰¼¼˜ñœÕjÅSO=…þð‡ø³?û³©ç;†çž{pï½÷¢¬¬ Ï>û,ôz=FGGa6›¡WX¯l£‘›Nz:3J¦Ðë™ô~ñ"Ca¡ÿ5¹ôt&Ý·¶ú¶¤¸NGÿtG‡¬®!¸gމ˜ë‡a‰Åø8•cIVImÔƒƒç âÿõzž=ÐéøÐjùÐhœ y¼–$£¤‡Ý·ÍFËrlŒ?­Vþœ.D´ZjÌ¡¡@Ø#ÂR“î‹Cèþ*˜X[Kw¬¿kkürkj8¦¥)¦§3ùäâEN³5kü{ø~!¾÷½ïá†n˜R†üq<ñÄصkî¼óΩ&y/¾ø"Þzë-üáÀñãDZ{÷î|~”µËÎâŸÿùŸqÿý÷#jV¦Jww72&3=bccaœÌ&Ú¹s'¾üå/ãÈ‘#8|ø°ßÇ;6‡ÃÁ 'ó*jùùTa+*˜òëïR yy\==¾m›•ÅšŒ ·Ý7t·›L|˜ÍÜеZzã‚6Ôäµ± ã½–%~"6!‡ƒŸÁlÌ CHÎAçE§ Ój™kÉ䬨(BS##üéËì.€“:!Á?E g34D3píÚ9?§NÇ:‰##œÒÉÉþË%˜ÆÆF444àöÛoG]]àĉxóÍ7P>vìvïÞ N“É„ñññ«:§* Å ®®.¼ûî»øýï¶¶6—þF§ÓáÈ‘#¾˜ôôÐÅ‘Ÿïbì85•À3g¨:ù; ¼nXX˜ïdi4\Í­­ ¬ÏCC|ŒŽòy©knT7…°°Y›‚ˆÊ€XefàL ºlògZš-“‰.¶ÖV* Z-…JL K­-x¬¡¡V¬/éèà`}•°]]û,^}õUÜ~ûí.]?nrÑfï܉}Ÿù nݾß~ùeèeTKz{õªÕ@PÉùóÜ5V¯öŸý=½¯ºr‹ÇÇþð|ÞîÀxú „„p#ÌÊâæéÕGçF꯾ìžÐßïVy­–ÂtºAêppj 2ˆo³‘-H¸± V•½e怿û™[­^+T¡¡ 5vuQwY»V¾ÐM{{;þìOþ¶yaN:…×^{ o¼ñL&¬V+¢¢¢00-k°«« éK±³¦P·Ür‹HJJááá"33Sœº½ôzºq’“=ȸu8hø;¥éÊ0Š‹eM ¥ßÚêìýævΊݎÝ+Wâ³7â§­­ŽÇ™3gܺÄ3Ï<ƒ»ï¾?ü0vìØ]»v¹9ˆÀ£(‚ƒƒéîHL¤/àÔ)JOL·´Ð óŸIL ß ºúª´EŸ’•Ål›K—\ ˜ŽŒ0¾i4Ò ŸšÊ?›× Íx…É$o*hPÝJÌ`1ä?ŸÑÙɸҴ­ÑÐ…*¹Q-ºWëê(Ã’’ø'.Ƀ³g¯ògRÇÅ‹tI‰ÏÒÚ—/ç²?s†q—½ž@g'Þ­¬„Ö͵xß}÷Mý;77ný½Ò¸îÈRvPF'o{;k%ÌS’Úje||<÷vŸÌÅtîUK´@x¤¾ês˜W&…ÆÀ£´47‡¶j-9o¢T×_‚ÖúûåíKa·S€”•-ø²à`§m·s.pNNfxaN¨©‰‚Þ—©ÝÓ‘z‰$%ùå,KT]êë9eV­ZÀ8àÞ’”•Aȼ`…  Ù1 rt”8-’i ù’ËÊï™¶Z-ÝX—.1SjÃß×°ø>TW##a±0ÙÛËÛ“‘áÅZ§ÿ`ppÎÌ$HL¤B‰Dnk«­ÉÍL§ã˜’Bï”d™8΃x:¨˜Íþë£>:J­¬ @¾¹à:½¨]]ôd_u klŒÒ6$„ŠŽ-Û¡ ùˆˆàdéëãæ™ždeáR‡½½.¥¡ûŽìlnBååœù¾.§ÓAl؈¾?Ô¢3q#„>LƑŻŸO÷ÜæÍ2\ ¼Òá%a±Èëç´ZiJÌ(màZ-ålj*/wù2§{¸mÙ–+ˆÙV$ßx¢¯þ`_¦/BF­3g&eX”Yg££|"'îŽ*@c2>âh»„s¿¬EÐÊl””ùO;š—øx.¶šF§}”¶:1Aƒ§¿?É(©BH©Ì~éà`:ë{{éO‘ƒæ +¥Ž ÷A™ûœQ7ÉN2Ãôéy´'ãÂi ÒÒ<*à:ÍÍ´ÌdÓH<'* (-¨9~I–nd6Û£$’ëÅST2«}9HÜZˆUÑ—é>R‚†ÊE×ÝÍE(#F#‹>ÖÕqo¿á`åÆ(„¬ZF7ƒÜ¬XA T®B‹‰‰ÊëRØß/Ÿ ç¦+wÚßd "ò3ëQ¸A?ÛVÖö1v;'™VK¿Q€…À`€¾òŠ×Z`^½ u=IK®O™?Q-E0™œ5££õÖPx44pÏË ¬OTZ|R™ßõë½R¥ÌÉÈH¯Ê!HN¦OXî‚}z=ï]]òtÐKLäwäÏ“ü‹a6ËwJÜ¥Fg«VMS§sß ˜ÁäñAY€÷¢¦†éO¨§5›ÑQ~¸°°©8Ç*P7«¬d…ÕgUê-Yƒ^‚M›fÕ""ø¤ÁÀÙ•–FÛ?YË—SÕ¢€nlT÷í®.*È›6-²X–-cÚJW—¼tNÓ¨ÓÓ½×FCC©¥+9…‡ÉDí]î ŽúzÞûyØqq|˜Í49Ü6ª þñúõóf9ú «•c1›ç˜OLO祧j{õ™(ÀfT&ÝÝLp))YàQB˜2š$&rQÖÔ¸ä¾q8œG_„` {åJ5­5kq¬/& Z-q{»<× §µ¤äŒ\¼(wk+'º å4ÂÂh‘oØÀÌÖS§¾r‰¶6~¿¥¥Bp••´ª‹‹çMF‰å²ª®^z]“}*@æ µ•ë}Ó&¼A 7½’þQE…³"` çâloçb!è¦:uŠ{vY?‚[J¿ÔW½¡AÞM:#ƒGØm6ï¯%µ¹Uƒ<®£‘Irn¾==ÜÝì`L9V\Ìa:µÀív8;³Z]\X>¤¯ƒÕh¨ºð½„‡ósž?¯¼ÐZ QÈ,˜m¹~½›)½žÙkÖPC¬¯çb :©tÚqZ—¾Ë—ÙŽ àÈÊòÂó¦×S ­©‘÷³®\)OR@B‚rÈÄ„<=^.^”·Uíð0• /Îzèõ ÇlÚäô¢N¶è!|2%Å?mvçÃd¢ÅÑßO…ÏM·³t–·µ•2WEÌ ¾žæùŠ^\$<œ+i`€“5%%pÝlòò8ÓËË1½—B˜èA‰ù… £à¬®v»Ìö¼$%q•z»éNˆOG®Ãƒ½½Œ{ÈÕll|œ“¾¸X– ¨  †&&(çZ[‚T#ÂÚÎS@ê…ÕÊMLp®za½IºYM d%åhÕ™¤¶–óÛ+á1øxªøz=U~—ÄòbŽNA•mºÿpEËX¹ÒÞƒØX¦éLvZ“…ü|.zo‰Šrvé ýýò¸¯ZZä;÷áÃ~æ!!¼l^xêßíÆ…ÈØÃ <&‹L¢²’'%7m’Åõ'µÍéïÞ{¯Ñûq.aT ¸8yKM‘•E•`À¯ñ‡ƒduu@îúp¬½«Á—šXΤ¥Ñii‘çz±±Ô½=o£„8ˆ»ºhÍÊ•KZSC ÕV@}="ÅJ¾ºñ)A8}š‰)~£¯Š›NGENΜ ¡½n_úÒA<õ”2Úg‚ë^€HÂ#+ˇo¢ÓѶ/,dÊ`]->Â``ŒPЧGEþ…âbnÈõõòØ›Nn.ä•+ò\O+D*¬Hl6ïÎ 9ÌzKÃ9žnB™7Uœ×\T€FƒädƪGGù+Ÿ&Æ™L|ƒ“߇ [«Õ¢¶öU<óÌ‹ø÷ÿµÏÞGÉ\×äßÿýÄÆúXxL',ŒåG22x该eF€Û[¤˜ùåË\;Wedj4ÎBu¾bR±Ç¡!ï¯Iáë͵t:Þã@'òþ¼F{;'©'µ/]â<ðŤ¦»hÕª«&ŸVKƒgÍê/ÍÍ2% ³ÆF*j~9ù—žžŽÊÊŸá[ßzo¿}zñ?¸ÆPŒ¹ãŽ;ýû÷O=wÿý÷cåÊ•(**BQQZ&Ý#ããã¸óÎ;‘——‡íÛ·Ã0©aZ,ìÚµ [¶l™zíüï÷-¼øâ¿ºÒæB~â⨒ÓT!¥£·—2!3“{ø‚k'=‹¼²RþÄv­–BòÜ9yòÉa…ÄÄÈ#Ð<ÁÛø‡ÍÆù!Çéüþ~> ¼¿Öl._æIîâbV$œÉ*NŸ–Á£+„³ Cz:瞟Oû­\¹üãóxúéŸúõ}•€bÈ#<‚—_~yÆsÏ?ÿ<ªªªPUU…“î—^z ¹¹¹hllÄÞ½{ñôÓOŽ?ŽàÈ‘#xá…æ}¯üà¿P^~gμé»ä ™™ŒLsô Øk³Ñêèïç¥\vµGGs±_¸ÀÅ/'AAΓWv»w× ¥Λ8F ã Þ–©on–'³Ãdâµ6lðþZÓ‚sh`À)\ +‹C¹pÁ‹°YOãAATÈänÔåEEñúëÿ8çïŒF#JKKQTT„ÂÂBüèG?477£¤¤yyyxðÁ§^ßÔÔ„ÒÒRìÙ³V%d.€bÈÖ­[9G@OÌaç;v _ýêW÷Þ{/Ž;Ðëõ…Ùl†~üí·ßC]Ý/ø¿¡ÓÑX»– üìY—]K’ÜÉÈ kÀíìªà`.úg‘#¹ˆˆp–i÷ÖWáí¹¸8yOÌ»ŠtŸyšö61AËÉÛ Å çÕÆò¦àÙl´b#"è6r3…[j-«Óq»l°ŽŒ8›lÞ,u&ééis>>úUUU(//Ç~ðôööâñÇÇO<ÆÆFôôôàwÞ¼øâ‹xë­·°oß>?~ÜŸÁm#@æã›ßü&6n܈oûÛpLÆ º»»‘1™€ ãä©¥;wâý÷ßÇ¡C‡ðÐC]u­ŽÉ ¤W^ù.b½ªç¸À³²hŽ77/ij¢å^Râe,T£á∠LŽàññÌò¶GyP­OÓx¤ØŒñ&—ðÖúhlôþàÃÁùTX(ßù€My9'¼Œ§ää8-èÍ•as3®U«{¢ÝE´Z-B'Û ˜Íf„††"44'Nœ˜êƒ>]Öét0™LG›W)@ŸŸ§žz ©©©˜˜˜À}÷݇Ÿüä'8tèм¯×ét8räȼ¿Ïšœè™‹×û ±±4Ç»ºY¾|Fg=‹….«¤$º{e#+‹®¢òry}efòx{»wYDË—ó~¤¥yvXqÒ ±F'`|œÚ®Åâ|ØlÎÇt9# 91eDIo­Ó1Τ×S¾Ñ  á#, ÐyÿãÀ¼íÌW[Ë{·@\Âmz{©½\UeÔs"#iLœ;Gƒx2‹8<ÏÑ×G«ÖÝ åbhh7Ýtšššðì³ÏÂb± ~šË-##]]]€C‡áž{îAvv6<¨!»„¢ˆfÖÆ:¹q†„„àÞ{ïÅo¼€™ˆ‡ÑhtÙš0MFìþ϶m¸yçN<üƒ yùr?ŒddPp´´ðìÆªUѾm¥ËM¡ºš§çåꃽjµàðpÏûahµF.¤³ŽÓËa21uÔlÄp pÆ€àü„†:7ú¨(§Ðë)®Rj5£@©ó¿’gJ8V+ôªLLp ¶+°&Z ¼ˆn”Ò{.HCƒ÷åÚ/^äw*W“.€¦ïؘOš?I›»»©ÇlÜ\¡°ÊÎöªó¢?8¹€»)&&555èííÅÍ7ßŒÍ tßÌÎÎÆ‡~è‹!ÊŽ¢ÈìxÇåË—‘––‡Ã£GbíÚµ€={öà•W^Á³Ï>‹W_}·ß~»K×—b,ÿø?ÿƒ£¿ø¾T\ŒôøxüÃK/!ïsŸSž9¬ÓÑ…1>Ž®›qÙŒ’Û³)£+b6!!Üêê¸ çæÊsÝõë}Õ£¢<»Ff&ƒ¦™™SßÕè(7m£ÑyæPz‹ÈHÊÀ°0@ƒH ü<°q™×E£q šyp»p˜jOŠ÷ IDAT ìvî¹££Ô®ÛÛ)p´ZŽ3&†JõÔµ††xqo¬À®.Z0rõ ±Û‡¦Ö¯—çšóžD‰aT¾Ò‰5ƒ#kíyéliÁ?ã¨ÿàŒ»`%''cÛ¶mhkkÃÀÀÀÔó]]]Hw¡²ÒPŒÙ±cjkk1::Šììl¼þúëøÎw¾ƒþþ~8Üpà øú׿øÚ×¾† //™™™xóM÷²©âââðÃÉŒ¯ÿyóMÄEGss‹ˆ ¦#§¹/ÚBáÈ,Dñæ!hê«ôX±ÂwÜ´Znmm²4©À¿/*bе¸Ø£ò ů€áƒ Æ,ƒÝίLª"°ð~;¹ëÛlþé 400•¤ÓQPÌ–›e´ÑÈ0ÑÄoKBW;nȇÇî™YW\ìÕG˜blŒÂ#/Ï7‡§3144 J”|iª/„"³—žKÅ êÿøG|çÞ{16:Š’½{q¤­ -­­(žãž÷öö",, QQQÂG}„¯ýë(++Ã;#ݻwãðáøÿþûýÿY¼D#æJsºF9sæ Š‹‹QYY‰M›6]ý‚‘ºHL&º22Ú†ÌngʼnÄDÌ<¯rù27÷eË|¿²änþ32BG·”~³ããt¹÷õñ~DG‰í•ˆ»itan ¡ÖV~w]såå´ÊÜáüyªÒnú-Ýýh@|>FGiM%'ÓóçÒT”6û’yæn?ÝV¾î¦äpÐ]k0Ðå9é–‚ÆpX˜|ưǘÍt' À Ñ f`Ûo»mê×óí/åååxà „€F£Á7¾ñ Ü{ï½hjjÂÝwß £Ñˆ;và…^¸Ê¯tc(‚¨(f«8ܤ«ª¨fgû=pgµgÎ0ƒõª8lZ7Á–žÆZµÊGAPã —¯ýhT­§ÚÚy³FFœ½ª¤ týúiqƒäå@Ëä‰cwHL¤‚ Wlg!†‡™Zä&ÁÍH½aR'?«ÙLáYSÃi™”DÝf2©g&V+_(WÿÕÖVšG¥¥¾u!I QNÎUR‚5§œîk×ú¹°µL ëìä=ÈÊòó‘`»‹—(--EUUÕUÏçææ¢¢¢BÖáú›ëR€ìܹóªô¸ýû÷ãùçŸç´ZZÔè.]bP39™þw™«—Îf|Ü™y9¯7M«åb›4ù!SWäLÕ” ã&R[ËÝÝÛă¤$Þ׆†©Îzcc\£”1iiô˜Ì¹YÄÇsss·MlT”ŠYZ­žÕ¾º|™BnÚ߆…QÉΦÖ×GãÆj¥LOŸ|¹ÔÏ|õjï-‡ƒ»uD„Ì©~³âˆ_´ÇÀÊ• ëTUQ>úÊ{;Å訳$OJ -°ißËC=4•Ô#¡ôC¾@ua¹Ê\šˆ%ºg16F%rÃ7=FÒbŒ‹£†ï+±©‰‹kÝ:¯W±ýì9t›ãpi ¡lvÙÅ>2B ÌݓՒdvG p×…uå »;iËB0AÀÅ€±ÝÎéØÝ=™ 6|IùqÐÌs˜ÍeÆÇ9—/—7{k:΃«n*=}}4V|ÒÔÐnçw×ÕE/;{Ê•æ ^í/K”ëÒñ†¾ƒÔT.²Žn¦ &súÜÃd¢âWTäÁåbb¸ù\¹B·VNŽKý­Ý&7—A‰òrnÞ|n“‰›Àèèjd œEqitIn–¡"Ò##îeuI] }™ñÒßユvé-^wEŽ!=˜8ß‚ÎÁp4·§!q”_½GFòà 7öõëçíîv;-ÇÝ®IIüìÌ%D9<Ìû?:JÓwÓ¦€Æ>—ê]ò„ÐPúWòò¸Yœ?ÏÅ‘™Is×'­$<¼>›•šJͱµ•ï¦$e#9™LU•³º¯ HÚcHãÿÑÑÀ^Ha¾ÎýM+?Ÿ¥]KJ\ÿ›¤$&øR€ŒŽº÷Yìvšeeî¿×•+±š°ò–õX ÞãÚZz[V¬pC¶^ºÄ?.-õÍæÙÝÍüåeË¼Ž†ÇÇó«—ú<®ÍÆ1]¾Ìô½œÏÓ˯cTâ-‰‰|X,to:Å ;;ÛeÔØ˜LÂCB«¥Ó8+‹e[7z¬¤)""¸ÙÔÔpS^ ¬ñåËÜ;âãi´ÌÐŽu::µ«ª(܉„…ñ1-eÖ¥¿1›]wñ¤ ok+-w¡!nüÓhR&=|V+§Â¼:Ädó§©~1rc4ÒµšÀƒ€2/â⨿9Ãa»ìÎä=³X¨Døà@äõ„*@ä"8˜*ߊœ¤ÎIš–6ï$•\ÎEE>ˆÓ1Hîˆçr«ªâ4œWþJÊ]o/o@^ž<)é*ªñ qq|Hfry9Wtvö 3Ùjåú]¿^^ãà*¢£¹ƒKñ‘ìlúÛåbÕ*^{²þDÿp0šš¨ »œÃqÕÕ¹wÒ98˜;É•+®o‚‰‰Ü´}Qŵ¿*³Ì%ššÜ/˜(õ3Ÿ‘Û<7¡¡”ëãã|«–/Â6D´v­¼®»khˆoäãC¹‰‰\fRöò úû«”ÜË[¶ø9øÚG ¾D¯wæ`SŸ Ô9Ò2PU¥ÃêÕ¾‰WΉik£«MÎÂt©©Eοzk—£¸8ÊýLÖÔTúó$uÙUV¬ `t5þ”˜È¸•/Èø¸ëÚ€ÙÌÏëN )]7?ß­‰JY1: 4|Ô‹cò¿X‚ p«½vuÑ=´|¹|%T\ 5•FÆ… @Á²Éƒn³Õ«}¬]ߨÎ?ÍKen#@æê‰>>>Žûï¿X³f >ùä“©ç½í‰(úú¸o­Xnb«WSk £#·ªÊ¿íW£¢¸áÇÅq'qQ‹—ZéööòøÉŒ3g ƒâÑÑÜ´ÜŒ ÚçÏ»ni4LÅlksíõ¾hs+¹M\áâE÷b%}}Îóîb2ñàD^ތؗFÃy¸nouK‹‹òÞnw&Näæò>®Î0…ÃA˹¼œ‰*))´6V¬‚ƒ±ao­/íTœ(F€ÌÕýÉ'ŸDAA.\¸€³gÏN•s÷¶'z 0›ÍÔf R,)aºíÀ­’¦&߸Zæ"9™ Ñj¥F7­Ôôl¸~33 7Hž‘ÁM«¢Â}m?(ˆ9¿55®wILO§PpE`%$p׋ŵt`€®W³À¤S÷ž”Q¿r…æ¦MóÜ sÖ^,/_dóí줢Ë áç(/ç|(*âü˜ÃÓé(Ïjký߀r>:::°mÛ6bÆ SÕÃÕžè22WOôÇã¯þ꯰Û`Ìäð¶'z ‚“zÑÊèaaô‹oÙÂ__O-¾§ÇûÞâ‹¡Ñ0ZTä,&9m7‚JߥKÜ;\rÃÇÄpóª¯çfæááî÷UwµzP¼í{Ý9ïN«Z‹…š~Q‘ûé×/:ºF›M… ¶vޝj`€Š…ÕJEÃ)ívN¶S§è¾ËÊâºÈÉYðô`D_âm'e¹ ÂøCÔ××ãøñãxä‘G066¦öD÷%F£z½ßüæ7Q\\Œ?ÿó?Ÿê(èiOô@ÒÐàÖÙBnæIIÜ|×­£ê}¾cc>+‚ƒ¹“äåqã¿p–1*+¹¹]ìUjRÕ×ÇMÍâãyަ¾Þµ×'&r3_üµ11ŒÕÈ«ñžjÍ®X*v;…øÚµî¹ˆl6ž° q»f™t>Ô``–¯›ŒstwSˆyràÑ]ŒFJ±ÊJ Í’Þ7âER¿·×GctƒÔÔT¬Ÿ´SRR˜˜ˆk¢'ºbˆÍfCss3víÚ…ÊÊJ¤¥¥M¹ªæCê‰þþûï/ØÝkÌ×ð,¨Hzܺ#8˜šuY]M/Ò”ïîö­ ””`$$•‡/ /´ÙYZAZ-7³nnîhÿ¼®Æ7òó]TR],907É„`²ÄÊ•®]³¶ÖÍz$ rQ^Î’!ö ×jÂU6Äô5¡âVX—å¹/ÄÜÅjå½9y’ÖïÊ• ®¹Ql6«WÓóg±È‰¯lÞŒ/$$à®+pæ÷¿Ÿ÷õ¸ãŽ;ð­o} eeeHHH¸&z¢C(„[n¹E$%%‰ððp‘™™)Nž<)ZZZÄ7Þ(Ö¯_/¾øÅ/ŠÁÁA!„f³YìÝ»WäææŠmÛ¶‰þþ~—Þ£²²R•••3a±qåŠõõBœ<)DE…--B ápxü™„¨©ñøÏÝÇf¢£CˆS§øÆF£Ç—jj¢®n˜L¼OçÎ aµzö&6›UUB47»þ7B|ú©ãã‹¿öìY!&ç̼\¼(„Á°ðkNŸ^ø÷B,6››…èêZø5Bp,®Ï;OîálFG…¨¬än±Ìù«•Óª¯ÏÃ÷p8¸Æ**ø^½½ž×Mìv!Nœ˜÷£¹~‘þ~!„8}ZüòßqÓMâåýW1:2"„˜q8âî»ïßýîwg<çwŠ·ß~[!ľ}û¦þ½”PJÍ…ÍÆÀ…Á@mW«¥Öœ@•Æ-I*s›6ù/E~&3X†‡ýÝ] È56RavéÈÔ3;-Úµ'dK ǹnkî“ÉYÆ}¡×OLÐ5²yóü¯àgXèDøb ¥ÊËi™Í¬¶Ùè²[¬\ûè(U}W ˆ™ÍÞµ¶ÙøeñËž•9)¦Ÿ“ã†gmlŒ¦ìà ÿ(++ b`€!ëRèçÃnç˜ Z˜ “hmÎñ]Ï·¿|üñÇØºu+6lØ0åeyõÕW¢öD¿&Ñ묖NÇÙ휗/Ó7­ÕΜLs|éíí<–áp3X³†’ §‡^ϼÀa·¦& ?—Ï«%&òzRº¥'›ÙŠteIMªsÁDF2ÈZSC =!!ü~z{çï®Çí)RÃB™NMM‹έVgŸxW„ÇÀ]të×»_YVŠstw»õ}ét¼ÝgÎðÿó ‡ÃÙÙ/(ˆŠ…' e$>Þ©OÍ™Ì%­qƒ/’ÖxJ • /6öÏ~ö³°ÏãVV{¢_ètÎF €S;ééá"ž¥XíZ\¹â^…qŸ¡ÕÒ:HK£ÆzéµÎ¤$ÆN¦hkã>¶zµ›ï!ÏÈàµÛÛé×v'š”Ä××ÔpÁ.NLt–²((˜ÿu+WRûŸO€h4¼Gv»gÙ>ƒƒ ¤œ˜ »ÐªökÖ¸V»©½Ë¥Ž§1Ýbô :­VK!RQA}dÆG7™86“‰VoQ‘¢:û8 <ØlüîúûgzÒÒ(ì–˜%(”óí.%t:g#)€Àà µè¦&4·…"7;šÁ8žØUJÚ°0.!8Öº:.”ÌL\¶%axXãÑaç)ôzJic—:7ºšËîlR52²x9;›§Å::hYÍ7¦”jÃó•°§öéNÆ“Dÿ‡ê\)˜XWÇÏâJ ¾®Ž÷ÕÝžÛ££üN¦;÷éBdíj;"‡»iÍ„‡»ö9͆Ð!búFÐû›!êññt¸è–V¹U€ÈVKë#! §Ã‚<#µÄæfnر±|M\\àŠFãtÑMLÀXß…®šß ˜³½o´ÎÆ`àa°ÔT W©ä'il¤KgíÚ…ï×êÕô©„‡ÏïšËÉ¡{mVc/³™Êò¨)æs}ÏHšª‚¢Ñ8“³4çiI á|^£¡\ kœ@ø–D8èY›á²¥¦»Ð†ÚÔDËk± ¶ÿ½7޳¾ÏGŸ™Ñ2£]ÉÚWk±-[‹mÙ¢)Ä@z!m!Z ‰ù……_Ó&¿¥§I{sHR‡6 pCÏåÜóKn†ä¤††Ò„„,˲$K¶µïû2ÒHf}ïÏ|õÎŒf4Û;Òôœ£ck4óλ~žïg}Ø‘_VZ¸ÍÆsi6‡înƒ8“qc¸ôŠÇnNCB |ÔNÃfãý·¸È‹de¡¢y.öUb_Äߨ#…10TV«Ì,9 ãt2·¸(O¬KO— e< qÍR¦O*ã"sN¾ð«üª*†]"Uێ⨯çû´ZßR­†=¿‹DZ”VŠ•¾¬Õ²G/9/ ú…^èŽì÷½0W™9t«Ùó²ëñ* ŒÞØlžOYY ÝÐgK }÷p..ŽÄ!ò#‰‰Ì 2Š®q*èì¤ö§…áÒnµ\èÄø¾cX0¨‘’ÂÝÝ¿ß5å ¤˜²|T‰é¼¡ˆ!-,øÌ½h4@ÖB²n­iwçç9[Ênò26P0{ š“ÇýwIâÔê‚ßnX[ã¹­"¹o,’×ü<>55~C›$éíŠÝ"†Å"Æú: C¯çbXN£ác5?^Úk2öD!ˆÂ¬°ªU*®®ÓÓ]B! E¬üRSeBQ`ÀšÁÀg2`ó« :‡ƒ‰Ò¶6’p“¥"?b0p[¹¹$ªí d|ô!œ={pÓM7aÕ5÷hrr<ðþíßþ ¸ÿþûÑÕÕ…ââbœ={z½V«wÞy'ñãÿb5¿˜š ÎŽ©©ü)+ãïkk¾ %++à°¯ö:ìGj*ǽ‹†±öv¹a,T#V\,çGÆÆèÂm7}¶ HNÆÊï:ÐW‹Ô¼d46zqhy9ðÔÔÖ|f&c¾ôË…Vz0ÆÓŸúàä$‰Ð×ɽz•nˆ+&æL™Lä4õâÜÔäd A׋ҤytÄÇÈÔ6ä!äi &³ýõ¿l÷ù«Wo²XèÉ54(S¥: CC>TL&ž›övÞŸƒƒ¼îBÒ¹®Žçf‡È á iúh—\÷{Aˆ!ñ¥H(099‰ááaÜtÓMbO‘pbÂnwÇ’B ±‘dy9=“«WùÀ^¾ LM¡ç²5:Õ2II 1ÏͱÁWC¡ÝÎ\PRÒo8„“Í*¨T´ïÃŽ…2a?ÉñÀàW,‡,E;4DÒon&Ñ),X¤Ñp³C]&.ïa ó»jky9Âý1T¦4rr¢/:åkqü^P#b(„µΞ=‹»ï¾{ó÷í ï¿ÿ~¼ôÒKx1Àl~%a4îp c0HNæ¾¾ŽÅ%$MB§Y‘Cz½²«>•Š>7—+Üñq®6³²h\ƒ‰ggfÒÈLN--Ê+ÐgÌÅÆ†Wq‘JÅxýØp}½gè(.ޝutl­Jª®¦Av;êtÁ)н;øœ_³ºJãé+ád2‘Øð¨ýà »º€’"'ò-#$âêêíǦxÃhä¹Y_§±>v,zn²ÈÑ È·ÙÐ2”ƒÒ?NB|mí.„ Œ‚¶ØDS¡÷ƒü Þzë­Íß%I»ᄏ©.ÁwÜqÇu¥F\Gòío;àû„"a ¼õÖ[(((@^(7~°¼,WãÆ4’’0¸‘„†?- '-{{=“–z½rIËÄD뫬äʾ§‡†¶¨ˆOl êžÂBسóÐùúö%t¢æ¦r ÎÇ$<Ñ,ÖÚÊPˆ{VT§#»wtx–ʦCïPTR’oï¾ÂWƒƒ[å^-’”¯I½ss$–ÆFŸž”œ(ÅÕÿžÆJQj>ä`5»]nöKI¡;Š¢a°U‚ƒg•à‘#@|<öØå<õ6ݱ¸¸¸­á_ýÕ_¡¤¤Ÿýìgwf‡"@Lˆ¯QÆccc˜˜˜À 7ܰùšP$ÌÊÊ I‘Ðî’Q}ë¹çð›ù¬Ùl08uûíøæw¿Kc£Õ†Ôx53ZåçnaiÉkÔ†NGC.bo¢lRŒ½e“z½"e“›³Ã¬ÖMÏéé4þ~Ê`¬VàR»Õ§J‘•”KR«¹b÷^ÕffÒwvÒ»'y22¸Ôìîöìú®¬d˜Í Dd;á§…O—ÓjÝ¢r8ä.Mï} ÷ÑÔäÛj­®==P¥¥¡ö/`tBƒÎNr£ß[Ó` ·gµ2—àoÛáÀ½Oii‰„!ú”Š‹} dg“Síö˜š§èÙÙ<´Jz>3ëë˜Bwk«‡—.„áõ‚˜º´¾¤IΞ=‹{ï½×ã5¡HxæÌ™ E^äkgÏr^ÿÆ`6Ãi2ñ4›ùšØøxZŽFTüß- `4n?h5V0< ÚD«¥áI^Ѹ58èÙ¸¥×GV÷˜µÖ\L IDAT@_^Nc48Ès^Xè!÷j±Ð¶>,ÐZæ4–—WÏÎæ6ܤVKÃÙÕEƒWY)ÿ­ €ÇáÞíÏí¸ÏµÐëYˆ°xWjõû(îìd©›{^Ïá`È*#ƒ¡5oX­ô¸Ë,-åiko'Gn’ˆÕÊÜÆÜ·YU¥ Ù ÂXXà5rŸ”PR4#””Ó‚j®ÝEˆö ±Ùx¿˜Íž?®±ìO}ë[xã­·`V©éyyHØ&¼è-×ýžP#D ȇ?üa\¾|&“ ÅÅÅxå•WpòäIœ={Ï<óŒÇ{~øaÜwß}¨ªªBQQÑf,1dhµ€V µ¿ o³É7ŽÉÄÊlæ² €Å®AÂT£ò$š‹ùа~H©ŽÄD]qc‹ÑÃÃ<ññ2¡„;æDŒw±ÛåþŽädØ JÐÞ—æ{ôSFó SSôbÊË=]@µšÆyx˜·®N&üÊJv÷:Ó²2&—…œjBÂödÞëë<Áî÷POç´f@ò5—Êéäþ.,°͇G-øíòe ¾ÀÕì'Iô #W"Fë,, adgóü„™7ÉË“/QLA’60›‘b6ÃÔ!æeyñ˜ ?Ó))d·Åãß¿ú*þÞk³—.]Â/Þ|ÓÏWzÊu777ãõ×_ÇwÜ_|>ø`4úØS$ŒSN8Ö-(Î2y®RÜKg=½ñ³ƒã£-R´ëÖßð:½>¢˜»´²Š¶_ÌaÖ2kö‘Àü­xV‰Þw"$ç.Råt’¨•…ÆÆh8Äøø«WšÇá®H8:Êk*H«£ƒÄ$˜n|œçÃ=Äåk?ffH%%Ûw¢šÍÀø8F®˜`KÍBÕyáW09$ ƒçN ÷ÌÎ&y)˜hïíå}ncXp8<ŸGáI¸ZÖj=žÇÎdÔI€VþséϾ¸/޳²²ðÊ+¯@¯×_÷j„@ y ×# Ëj”—ë€äm’΋|//3\²±!—§ÆÅù“)8^X,ˆ2hD…!µÙä8üêêæøìMà Ñ7м¤"³ÀÉsÕÞÎï*)ÙZ¤ÑpE¿±AK¥R‘H„aù÷•¿ZÍPX[›œÀ..fÿJQ‘¬õ²°à›å<ŠP®䱸Èj)÷ÅÉð0¯»·øÓÊ =•ÌLösø2Ú’Doibbs@Ù]Õ¸|˜_ aA cq‘ÿ2aTTD5{\T$á)«u+9˜Íò3¥Ñx>Süÿ6UMYù€a (P¾é¿úÕ¯|¾~½«{‚ƒ˜È‰~»Ýsµ$fÿ¸ÂdP«=WK‚d‚\}®­Ñ¾E}q/—ï²®üä$ë$Å»mtå—–ÈlˆVË9“‰ÄÔÛË€uQ‘g˜P«åêÞh$YdeɆQ§£ñ¾|™F»¼œŸ­«“Ë{5¾>ëê<Ž·¶–Q·ôt?ÑR‡Ã“0Ü3÷ïßQ=šädÞÎBC% ÜÃKîä`±l /%%ñ^ÊÍåïWf&OùušŠØ5ìH˜$…žÃ¸8yL‰¿/r'˜ùy>XV«üTºÇkŃ¥Õj5fgw©JÌ[W^HˆúÑ•— BOŸq0ÉÉ 9‰ùåËòl.÷êP©h¨¶«®B$f3Üìì¦Ko¸šŒòÃ`^·5³“JqqÛêÊLkQœ•Šø5×ô__FO¥’ÃfôJärRadòó¹*âR]ìÊJV,µ¶ÒcÑëyÞ®]c‰Ze%·'žž£{ÿÇÀ‰Çé$ ÕÖòû—–hÙÝ+¦§YæSZêYðzÑëÈÏç6…/dØ ^ƒq~‘\”™Éc®®Þ]Â![·SΜ ó—5È,Ùð ÙêtôöÙ†ƒë0ýØ#0±ººC øã&s:¨u£Ã3f¼´ä;©èìOLŒÞ“å¦+ïp³ç8Y³L«¿_»deùÖ•zëUUü̵k$¥âb®úÕjk÷QM ÿ–”ÄÜÊ|OxI ÃXf³œq?§I`fFž‚ÜÙÉ×ÒÒHh³³r×»·›•ÅJ)q ¢êlzZži¶]á..’p\áÀêf=®Œ—áØñ²~N§GõÒæ¢Å»hDÜ?éé@^2jÑߦNìÌn†‹PfiîØ#0a2mmFŽ5¬®º". •?Æó*kÜ,WöwöNö+Ç›œ K4PeëlW‰«{âwp¯¹W ¹¯ðlD_DK ßSRÂ}­«£á½|™¤TQA#ßÑÁUû$”¤$®àûúèA yž#Ñ®<<ÌPY?Oð¾}ÌwÄÅ1·±Á^•ŠžŽ°HKK$*«UBéëü‰‚„ÅEÏ‚„ÂB°–@ü¬‚Þ°ÈÇy‡—¼óqâúïÛT>NÐ[Ðy]‚˜è¿G Ác@„٬LÏV4a4©ù¤rëcñ÷Ê—ÕU0ÏÊw¢ "L6=í#÷¡VÓhºëÊ‹ÒÓÁAߥ§ $‡Š ëþ~ÙXççÓèÏÌ0¬URÂ/íé‘;ÔÛÚŠ’$YDŸ˜Y3>NC>;K‚--eHLx>ýýžeÅV+ gv–Ÿ¯¬ÜZyá¯$Ú½”ØD³^P³Ø,–­äà](È!)Ik£@x)9™§4f¼vÐéxzv´äø:Ç„‰ëÁÕ]]õ=Y<,ˆ0™?Fò®½7ù4º‡É|ôĘ%-´ZUàÖoB‘$ÙC¦LO—ßãÞ¤89I#/&Ÿ<ÉÏ´´ÐЛͲîzWÿíëãçÅ8ø…þ>0ÀÏ 1|&HgmÄT^Î×èÕˆÙ_îÍ~èy{##ƒ§sk×´(¶p?ÿâÜ‹ñ.!Žî ©©;˜7 :]ðØ÷@Ä ø”úÅ/~Ç*• ¹¹¹øÉO~‚ÌÌ̘”ºÚ/wÔK 5Læ3?âÄ>°ØäÑ1Þ¹_ì"r$¢7Ä}ü†Ð•OOç*º°Æye… ëº:‚ÃA¦íî&Áôôp4Ù¢ˆ†»Ü\’KA¬Ìuí=¡úz’Õð0?xÚb¡›‰ž·ûT÷0“ÔaÖ¬6¤è=Ë[uº˜™Šœ,· Ä*D$xíµ×ðè£Âétâ±ÇÃC=„ŸýìgøêW¿Š~ô£xê©§¢óÅQFÌÈ¿øE<ôÐCøÁ~°ùÚ—¾ô%œ;wUUUxâ‰'ðïÿþïxüñÇ7¥~úÓŸâ{ßû¾ùÍoâÌ™3›‚R7Þx#ž{î9œ9sfh÷átÆPÌÙO˜lÉéêûÐB6’ëë\®ÎÏ{ÌÚìëð&˜„O]yÀsàØ˜<pß>¾g~žÞ†˜B<:Êeòø¸Ü¼`2ñ;EIïü¼\·°ÀÐÎô4Édv–ßWTÄÐÓâ" &=oIòl8u/yÏeKJâþ‰òVYEÀ’H Q[j'¡ÓñTÅ2d‡YIØív|ùË_Æ[o½…ÔÔT=zwÝu^~ùetvv⡇Âêê*R£159ʈñž™¹¹¹XYYFtzÏ;·9Þý“Ÿü$š››qæÌ™”ŠÃ|Ãbq+ñç¿Îu÷0Íú:Ãdf³ï0 ™ü|y̺ ”ñqy¹(½u8äÈØlüœ0â*½»]&D‹…±Â¬,þ;4´UÏ[LnuŸ§æk¿Å>‹ÒÖ ÃKiiäÈXFbbh"•»¸8¹^@I\¸pµµµÈw 4»ýöÛñË_þN§‹V«š•3U1C ¾ðôÓOã¶ÛnƒV«Eee%ž{î9±!(u=„°Þs$§VËBYþà&[ZbHÉ{%Ÿœ,v÷2To`}E¸r®á››Ÿ—$ZF³™OKãÙLdjŠÛÕh<«—„x¸Bá%n«èb¬A£‘É÷ÜíarrŸúÔ§ð|÷ß?’b½"Çb–@œN'|ðAüú׿F}}={ì1<õÔSxòÉ'ý~&XA)%ðž3λÅÏ£0òÁLX6›IJ É@’äRÖùy†µúú˜Ó¨­¥GQXÈ÷ÇÇsç…W"¶£Óm™Üm\/ÆùzXtEþ†$~ä#ÁG>ò‘ÞeSâ~¢çççõ.Ý„»ï¾_ûÚׄ/(%ð‰cÇཆݿ?~üã¿‘«ÉL!}ïŽcoÃá "~ÄÐË¥%¹AqlL&¥ädz =“ÄD9Qî ·î ®&ªØ¾Öªk±¿Ò•àîÇû¢?ÉŸ*((ØT€‰‰ 477G°—±ƒ˜"÷Éò9990AYYþû¿ÿ\ÊMá J ü‡ãÜ% €™ë˜CŒïcÔÏc É­ññ$FÎwèõ ˆ'$0)n³‘(DUWzº<¯Ix<¢ÑØ‘ ËÞP{×Z{<0°å51ÎÝMMMèîîÆÔÔÒÒÒðÆoà«_ýjä;ˆqŸ™_RR‚—_~Ï?ÿ<î¼óNŒŠ -Å¥öp}#ØÉ­Âˆ‹É­b°ãâ"ÿŸ˜(¿?.Ž?"ÈUXqqr¢?)‰a«ÄDþkµÊŸ•`Qš°ì ‹%fªuý"ֻУ‰¸¸8<ýôÓ¸ùæ›7Ëx3·Q/¼ž3âofþwܱå5­V‹ŸýìgÑÞ¥ë×CÌYTÉúœˆ"*£¼ûüâìlcoC,ª¯FGåê+Ñ2=-¿f4ÊC&ERAäGÜwR$Ô†´VVØÿ’›Kk.æi‰òÝÒRÏò]_–½‰Ï½éÏýÇlj JV`—a³Å>ÉE³ìýOÿôOCŽ”\ˆ¹Þð~]M) ‹©’+}ëÈHX—åa}…‚‚Ü*äYÙ¬èpÈzÞÅÅü}|œF>+‹ƒccüÎŒ ò„~Æn§å•X¢ L’X²›—Dz\Ñ_25Åc((`ÒÝnß^W>ЄeA˜^–Ø\žËò\ Ò³›vg',‡€ØŸÜà.õ²‡à°G aâzXÝ yï]Yù¹Onõ/ $&"Û™Œ…ùddâäV¡c4Ü ciIÖó+áAÌÏsr®JE")-¥afuÕð0¿Ûéäg§¦H*çgiµÜ¿¹9n¯¸˜ÛÌÊ¢÷ÒßÏ÷<È÷·µ‘ìJJüëÊ BÉÊÚÚÁÂèì ¥É @· ËÞy˜hNXÞëë±?;Îj}’‹5ìH˜¥“±Üÿ#Dr¢2Î]IÑ BœÜš%€J}ßëtz†ª¨×s‰ûY_§·±´ÄÒÚ#G¸Ä:"••üLG»Äň{µšá¨åe’ËÌ Ãc©ªbuVu5=ÉIfœ˜ ÞzU7®­Ñ»ééáö ÙØèj(Û¢8:*Q„¨+Ù5:Æ®MòMm¾çßC°ìN4QP,ŒÚ}¨ ®/)Ö°G aB4oÅòp¸´4¹I:d¸Ÿ(Nn“AüÚó§ç­×ûÖóv:ee¿øxzÔÈå6úûéI47“XÚÛ9KÙ†Y§H\e^,¸=`³qå=3ÃÕvE…ï•ñÂäùùž"NF#üáÃr>áòen'5•FÜh”ó%¾Ê×ôzCi)‰àâEHa!ãÈãqÕÕÜÏ‹eI[Q%ò#Â#ø÷ÊJþ,.’ ìvn77×§UëëÊ+5Ðäåy®‹ëp0ä5;Ë7ÍA(»aãã1gŽÇ¡ÚTÀW‚Ú;œºÝ„ew¢Q8œj³EuPÀ{1sÊ| J½ùæ›ø»¿û;Øl6ÜvÛmø×ýWˆ A) ÌJ,÷Ä¥ð"66<×ÜWbNnÍɡ؞bÊ„°ž·+nï55õKOw«†IeaPOœðmEÎ!)‰‰»5˜œ¤7rü¸ˆïëcn%'Gþ½ºšÿ÷—Ñ—ãÿ˜œä~ÕÔЛINæ6óòø¡t˜žÎÏ<虓©®öLˆ>›¹ H˜%%›ûd0ð–¹÷Mh4ôn„Ç%òIóó$.÷|’·®|”àtÊ“`|"œ ËSSü¿·ÇíM2!<˜B±8X^^Æ­·Þ »Ý«ÕŠÏþóøë¿þk<øàƒxûí·‘æ’/xõÕWQQQ3ö-Ä x J9N<üðÃøÝï~‡’’|æ3ŸÁ›o¾‰[o½5f¥22x?o†Ê½K'Aø+LI‰úäV†v+j¼6›,Ï**‡DÓ^ˆ9 „ÎV+šòÆ¡Z˜ç º¦ÆyŒÍFão±Ð8{w|_»Æÿ?.“×ä$?'Ãdâï‚ÌÏoͤ¥1ô––FVni¡·£VÓÛhmåê85•?Ç3/’ŸO¢¸Gòœµµ‘ JK·æ?ÊËù³¼ÌðÖÆ6² Ð;“¦æ îµZ&$À³¢MèÊ»JîÁÙY?e(4aÙn—ùëë¾GÇøêêw{ D¥w4––†·ß~Z­ëë먭­Å½÷Þ •J…gžy·ß~»Çûcžƒ˜!oA©……¤¤¤ ¤¤póÍ7ã§?ý)n½õÖÝ”ò /é70{ÙŽìÂ5þݽyK§ãƒ)ªlv±u½°!öÊJ6&zaˆÞ…0ô¼=àJ*§NL Ä¤ÁåñbÔŸªðÞ$‰¡ ™&Û…‘°Ù˜ï(( 7À}Ÿžf®BÀÝûï)ö#ï'ò ii4LÅÅôÊÊø{c#IáèQ^÷øx~WOÃ3ÊÇ$z>&&€óçy|Y±Œ #v‹o, .ýâ®i· ÂvºòCCž=5™™ŠÊ䤫º.šˆ‹“µX|A4µ ’åÊnM­Ë}¨j`rËÅ„ÚÔêjµZWžÈl6C«Õnþ.ùèHŽÁ¼`{á9990™LèîîÆÁƒñŸÿùŸX__ ¼ ”Óé„Z ÄÛnr«{x)) é5èµ%'bö4 Md~8d³XdÂp”0Ìf²›Á@ã\[‹¼ÄDXF+W·æ±ÐC$9¸ç9VWYÝ$BGëë$ woÄh”«YÄßš•EâáƒÂBz!ÅÅÜNBKz;:ää¾JE☜”ûEDØJtÆçç3w#ò#^çÖá.ujPsS.’3syŒ¢I1/ûªQñ¥+/š4GF<»ú³²B&³Y>%» µš^ŸŸVx‡PÛ­P庞ùåe.2üÕ c²ÑhÄM7Ý„œ9sf3lõå/O>ù$n¿ýv|ýë_‡Z­Ž Á¼`³–O¥RáG?ú>÷¹ÏÁn·ãÆoÜ2ߥì.—ö‹÷ݬ¬@cµ"A’pó©SxüñÇ}Onݦ3W ^·‹ãB‚„(ø™õ7÷†Å"‡¤Üç7•—+Wã(ë&'iaJJ<=ŸFF˜³>|Øeï×Öh0SR¶æ9ffhXó¼(6CI žŸëë£ÁXYÙ~U/t@ÄxY•ŠçfpP>†”ÌåËôH ù·‹=“ù÷éÀ°žLu5›©”ª*·(Nj*ÙU4N¶·óx‹‹Ãoù9Êsוõœ+–•ÐxóÔÄ:}~‘à?â>yÁlÆW¿ð¼ó«_A#IHLLDVv6Û„lÓÓÓÑÙÙ‰¹¹9Ü|ó͸í¶Ûðo|yyy°X,8}ú4žþy<òÈ#~·±“‚yÁ"¦Ä[¹ëø~ÿûß~ô£ÑK@ø‚RÂí»÷¾ûðñ{ïEþþý'öí£G\TÑf¢ŽÒR9Üî ™0Ü'ÈVV*ß–+šýVVHÎõõÛv—••‘c.]°¡^Û‡8§•^…¿¡J½½$ŠãÇ=I_’è:äyL ².ºûkþò\¥ kž›Kë¾’å½==$ôt’[G‰Óû‚èt$ƒho‡)%—¥8T«òÍkj5=±‚þØIqß>Þ”‘¬lT*îozºìqùÒ•„âv-m6^îh%¦•Äìláݸ89¯àŸÜ ùØØÚ.^į^x÷Ým7³oß>œ:u ¸û‰‰øä'?¹Y<©`ÞN"¦ªž½ãB•pmm Ï>û,zè!² €°¥þèÏþ ù‡)’UÎÍå 눋£½›33æÞÙÉÐKo/ lUÃA \Å*E‡\M44DC×ÜÌ¥i ÖdIB¡uåÆN´Îc­ªÑ7yØíòðÂÇ·zŒ]]<&o <0 ÷} Û‘EÄUU¬trGI =„‰ Ï×Hróó<ÿ¾•…Ù²“èJBƒõÒ-sÛïÀssà¯cr2ûÒ%~RHKãµ;vŒßS\L¢ìêâýtå 03ƒÁb H( ÄdýH=–””à®} ýÏÿéóïsssX]]ÀPÖÛo¿ºº:LOO`ýç?ÿ9> rû¶“ˆÄ— ÔË/¿Œ7Þxðä“O¢Ú"ˆ%A©øøÀaó]…¨JY\D…É‚‹ÃzäÜìê†Þ®,R\ ‹ñæÇŽ…CŸ›cX¨¸Y·ÇQ #B99^%É&ÿpà€oÃ?8Hcê½ÒŸšâÆÜIÌ=×µ22H>îÈÌ$Az=xF\U¨Õ ‘üêë7o ‡ƒÅc*ÐtÇ>¨%½g~$Pu›J%DÙØ ÊÕqJ^w±*em –©E¬v âÀº˜I&áfeÅdœwqqký…ÒÅg>óH’•J…G}ÕÕÕøÐ‡>„……8NÜpà ø›¿ù±eßA%ù*xBHN¶) iëŽÉI>ô®‚±Ý…É$‡¤¬VyС^$&bxXžç§8ìv¹Ù/%…'$ÄR^¬®rUžšÊ¸‚—1æ‚úÐ! Å.,ß •åÕ’¦Z-÷‰h4$•öö­É}ÈÌÄZU#z_éGRe!N4gùv‚D~DLîX°çZ4Z­$ú–Zù’Å $––äÔ ¹IP<ëë<Ï×®É+¡DÓ#ö»§booøØ# ª{WWC_p‡ŒÕU™0l6­mÃ*¯×®EXŸoµ2427ÇNUUxd§“åVóó\ Ê?8Ðõ\ÆÑº Ò ½SÎñnþÆÇ–¸—ëº}33ô>¼!ô?‚Av6K=½îUUÌx—VK·I”÷ºŒ¾pZ-~¼Iƒ]ÀÈÒÖÜŒ;23¹ÿ‚«‹„¹Iqi‰á­ ’^^ØýN'G÷›-C/¡ÍøÞ^îƒ 1¢'Š˜œ”wí,M IDATµ¾ööD!”•ѺW„*Qõb0xV½q¤0™É€˜æç¹²—$®â}õa‹ÙY† JJ|to˜ÍŒ9¸f[XàËZ-PVdGjo‡ÿ ¯¡!N_Ä¢V,ii 'yCô ø ®§§³®« óõc4ª²R´}¸ºÙ‡‡e’팹0øƒƒ¼&55þ›éüAôØí¼).^”=†·Õ×Çà é¶Ôéx‰2F1Õ·¯„¢Õʊ„2=Á(ü=Ø#ÅšÊû=¢ž÷º{_zÞ féçNÜß (â9t(²pÃÊ Wœéé|‚ƒYñ 1¨ºº-žŽˆÌ¬®HýE/L™‘;—„‚¯c]ô¾¼ ƒ!´þ •Š×ÃWõDUç^²¶Lsa°C??ŠÃ7–úN”—ó\·¶’P¶3œ =· šZÍ‹êM'{++Lî›Llp,(xï‰ù\îËaA§#1Šé¢Ì¼¿ß³Ì\¯¨tja—{oúndØ#QVÆðz°Q-zÞ‡FƺºÈË/N>± ³Ûåt’t:Vý´¼<&žJJ€®fÚçg犯¸8tcê33ÊóT*îok+=a*†äÙßOwÑW£¤/ð¼ 1VYSÚàEo$'3>%<ÓË—×ÖËPP–Ѧ#BB‚¼Zä0åè¨<ìÓ],Zpõìí!B숒p:‘—°Œ–Ž5”ÎÏ!>Î0**b/àêŠuÞ0áâ|)´7EF¶B·„ÑÈÕjffðyåe–‰9x`ãê*ävñ“ÕUìÔThà90³G^6rI(6IÂbq½ZWCeâåwB³Dk³AUëgV~q1ûM }\œ§®úvKøª*nA8ÁôPh4üœÅÂüˆ(Á‹¤ÿB¥bâ>/£½PÏΠp¼XB“b8HHØÜ?²>Íø8°º ƒ):[6´Ö4@bÁÁ¶`@"Ãá’rM7Ý_¯Ç€µkcŒ0¹Úfz𯹴ªÔT4Ú]3þ´ÙµXäñ(uu¡”ñqJwñ§í¾«»›u£Û‘so¯Ÿ±¾.,,@S^î_×hÞ ”ùùlN6¯¿¯zP•ÊË%õ¤$u¡«¾]Xn®,Ruð`ð¡ÀÄD•ÑH²ÊÊŠØž™–ÌZ4üI€2z×®‘q‹ŠÝE ƒMÄÇË]ùúÿ`GcµKWþÚ5žá¡DCWþ¥î¾ûnŒŽŽ¢µµ@ìæƒ˜°pããã8uêjkkQ__¿Ùº?88ˆãÇ£ªª Ÿÿüç7ß¿±±}ìc¨ªªÂ-·Ü‚ÅÅE€ÕjÅí·ßŽ“'ObhhHùu8ÇïéaX ½]V¢ijâOe%²«2a2«áš>XZ¢ñ¸t‰MSªË­‹cD¥« áí·ÓÉØ@g'ÃUþºÃýA’Ø?a2Ñ"‡ƒF÷È‘íƒÙƒ F(úBf& èÊ•Àß'& lC¨zKNæý;5Úç]˜Ÿ§ýõHBçäð:r„ç³¥…ÏI =SS@v^Šö‘€Ožä>§¦rAÕÚÊUÔà „ é‚RíííhmmÅÓO?½9çïÍ7ßD\\œÇ Y!(Õßß;ï¼ßüæ7`SP꥗^Â÷¿ÿ}Eö-RÄÄÇÇã{ßû®\¹‚_þò—øâ¿ˆõõu<öØcøçþgô÷÷cvv¯¿þ:€<Áv;ŸwÂ0é75ñA®¬¤ðZ¹<(‹áí¬V®~ÏŸ—GŽž8ÁŠ{b"£#!>÷ÓÓ4ÉÉÜ~¨q«•nf&ãìÁ¬…žy w©¿ûQ«‘…tt:–—n‡ÊÊ­³³¼QPÀýüB¤Êd"é„jè„^üú:¯›Ko"ÌÏ3½ÐØèç2%$ðº47Ó éï§ažš’gíî÷–ñò ÉïÀÞ»¼E¸ðâE^;‘à Þ‚R‰‰‰Ðjµ°ÙløÆ7¾ø‡ð${îÜ9|âŸ@A©sçÎÀž ”?äåå!ϳÌÍÍEvv6 Þ}÷ÝMoDœÈ;î¸#zŠ]v»<ieEaˬhHî­‡ÌÎÎ+ï™G!4ûét$‘ŽF ¶]˜‹§]9vŒ$RZêò¢V<--‘YB5Vîû- ›š‚÷ì¹ fÒéø8k ãÈ+ÙÙô¢¶#´4ŸµµíÃnj5]@w]õ@HK“Eª„ª¤ÃûžÃ‡yí§§yœZ—¾{„“œN>Š ÇuéÊë››ñÉæf|ÒéŒF¬ŽŒàߟy-®D¸?A©‘‘\½zååå°Û혟ŸÇG?úQ¼öÚk{‚RáÀb±à®»îÂO<ææfèõz †Í¿ONNnzâé'ºÆï½ü2þkqÏ_¸€Ó_ý*Ò¢@z=í£’š>X_g§¥…+¹#Gø„„µÄòøx¦yff€Á?¸ Kj* M¸ä!ÄŸ’“¹b–ûÙÏJN§S’$I2›ÍÒwÞ)UVVJ§N’‚úž¶¶6 €ÔÖÖÍÃñ‰åeIºx1Œ®¬HRw·$?/I##’d³)¾o>±¾.Iíí’tù²$Y,’$IÒ‚$½óŽ$alof†Ç°±ÚçIjiá V+¿'´µñýpáBà÷ÌÌHÒðpà÷Y,<ž`16&IW¯ÿ~¥%^¬ÕÕ?:=ÍS¸¾îzae…ç §G’ìöÐ÷%¬¯KRo¯$½û®$õ÷‡|ßX­<üz\$iwíËn!&r üÇ ‡WýâÅ‹[^ÓjµøÙÏ~íÝRbäÕààöRäÌôtØ£µÃ†ÃÁ4·È§êõ µ_¾,Oc  »…#4ÕÕÅ$L°¥Á¾tÎýÁfSNUK¯—¥ø¶CBcýÁTZôÔ®]cN'¯-#ƒaÍŽ^¨ ¾Ëá ŒŠhÚ¼T©©|av–aÌâbyüz´ Ó1ä'IÌÞ‹råâb†jx——/Ó©‰‘j×÷,b"„õ~AY™<­Ý'–—yç·µñé=~œ Ç"‰ yÆ{S“ÏRË„yzokk€È†ÃÁPD\+}B%îC°uÐÌk–ZYQ¶”TŒv¦ø£¢‚ÅÁŠ<È$Úv ‹¾˜Èë83°Å`à¥ÏÏç`DŸ—*7—ù›ù7·eÔ R‘0Že^hu•ßÝÛë÷æ ŸÇpîù=ƒ=~ÞaÔÕÑðn6GÛl4ܳ³²´^D³DÂÀÒKmrr‚îç‹Ú®.þ[Zêµ(\_'3ŠÜ¦§i B)_ëë ~ä¼’ùôtS o).ŽÆxr2ø•|}½\ÞÊý¡Vó¦ñ)Re·ËqÁLZÍ‹_XÈó=:JOu'taè]îßOòêíåó#„µÔjÌÍq ±7ª}g°G ; †ÏpçïŒ8ž5„8UèÍ~ŠÁlfÅN|”–r%]Pœg&tÕ/] ­oF ¬ŒWkë¦(×ô4y¥ª* .MH w¼¶Æð’HúïTÌH4)Úl›MŠkê4 ¯•¢éƒ TÖí!(ìÈNÂbÆÇ‘´°€êÌltXâØ´;?sÎá`%×Ú­~„Oi)€==€jr5ú$ò ³™1ÿPúC®†ƒ•Ó$Vµ)ÝÀ–™É2Ô`r0j5 Ìç| ?HLd••—®zÐp©ø­¼Ó^g2Ê2 ° 1›knŽä$äiwꦎÊÊ`É/C×ïÖp4kê‹ë²’b H&¼—±G ц$É:â¢Ùoÿ~d©Tؘb(Ps²¢çê~ÿ~ôGe$Æ;Q.,祢Óހ̡m„µüÁng"º¾>´•ìò2WÄÁöt,/G¦áâ`Îà¬ra!{B‘+NK£7!ÊšC€Ù ôõé€Ì£8bí‚6.P[ ûö1::JϪº:4‰à`·»æjÞ‚ÄW“âÔs‰:‰z×KÞÛØ#hÁl¦²Ÿ˜ÖëcjlA,Õ  -÷ ƒ«ôÜ\ö(¹BÜØ á¯¨@FNN@žE'ò#‰D’hjjBoîëë -轸¨xÓå&22HPÁÏýûYõÊ8•}ûäÆÊ r> #Šf3ízZš@ƒ<=ùÈe´jÄøz‘á­D³¦8LíTU¹9ÒB‚¹¸˜^öؽڼ<î›R•w{Ø#EátÊ:âññ\ù0 åå|Ö‚*ï ¢k]Ì&QúáYZâö½&/ Ñû˜“C"ñ»Ð¾r…ŒêCs{[ÌÍÉêN¡ìs´´²³éqK 99 {YüˆRùCy9µP¦¦üvʙͼ¯66xom9µ••rè)ÔñûÛ!>ž¡¶µ5Ö''ÓÂ+œ‘$yÔŽßӒ²2ñlvtÈÏæyHïe숫œ•®rB2Ôb^Öðp½`·s…©PžÃ'ÆÆh,›šü!_=3ÈBj*Ñ#·><,k]‡Š¡¡Ð’íb¤x´Ô!32è„1h1Ôiµµr˜Æ–—å©ð¢7ûöÑÀ‹É™¡øvù‘ùyVÐ+PÀûkaapí4P«eé[•‡EE‘ôc@Â…ˆ³NOËqÖC‡ÂÞÜÁƒ\¬ E¸8–$æ9¦¦Ïsx|Ç•+².E*£Âaus¤96-†ÏÀê›ÜÜÐV¶ƒ²FÒ*•Ã|(#ƒ>Ta+•ŠçíâE8jë0mLÂä$I:¤H`r24¨JW§åäÐ3c~$ÜÒny¸+׆Ž'Hä'»»åüdvvl()^'Øk$ F#3ßmmüýØ1®HÒ:$Ç«ÃÂâ"P§“eÁшó[­ ydg‡5=3“ÇËk8nýººÐG-94HÛŒÐö‰……èå?²²Bo²^Hˆ0šâÐ×€‹/ÁiµãøqÞG!§ââx/›Í4¨ ©ñmB¥âµ:vŒ¡¤¶6fˆp:YÉ,œ‰ˆ÷iß>îSm-Ÿí–^‡hÎþza@‚ÍÆ„`K W½åål€(.V¼LðàA>»!©šL| ggù03H0üžƒÃ\úÉH„U]hþD2õjôö²—dt4È¡“££\)‡Š2£ßÙHæÖRRx/ß*òççÏóv,­ÑâäÇ‹P²Ø:BÃ_SÃýompú§ÄÇ“á +zõjÐÓwÅ çââˆo¿­HLdN¨¹™ÞQOÃnÓÓ+).//£©© ¨­­Å³Ï> ¸ï¾ûÐÐЀÇãÓŸþôæ8§]“ì*IRz©»¸téŽ;†¬¬,Ä{å(î¹ç<óÌ3ž0¸ÊµÙ'ÍÍ^ìÜ ££Œe×ÕmÃv»¼Z:p |]ï`09ɰXˆùŸp8øpÖÖzäfràÌ ÿŸMC±¥Ñnçç››Cû^Q&dØm­­ ñ„‚–z¡`cƒÞ­ï2yn––è]ÐÑñ¸7¦§I\JˆÏ¬®Ò9t(º%°¢é4?Ÿ ?7»ÅÂ4ÍVoQ\¼y¿~á _ÀÙ³g½ÞnƒÁ`@[[Žº 8NX­VhµZ¬¯¯£¶¶.\€V«ÝT#¼÷Þ{qÏ=÷àž{îÁ³Ï>‹±±1üË¿ü ¾÷½ïa||gΜÁk¯½†¥¥%Üxãxî¹çpæÌ™:þÈøø8N:…ÚÚZÔ××oÊØ~ýë_Gii)r¼B‘2ô›o¾‰™™ŸMò°ZYºrþ<ã£55| óówŒ<YÄÉçTnI"Ã\¼(»àÑ"áAκÌÏx%ö5Æ£Gù“”Ä•vK ªóó.yŒÁÁðE‹‹;g}âãC×µÐj™ÀXX€ÕJ¾îìäñOM‘POœ ?äç“m•X¦¦òz÷õqñ-dgËSZZ| 笭1luøðNÅÇ3ÚÐÜÌs;4D7ybÏ|ç;[lÈ›o¾és3þ4ÑyØívX,è]y¡ëI=&ƹOOOK’$IÒÌÌŒTXX(™L&©µµUšžž–²³³=ÞÿÌ3ÏH_ùÊW$I’¤ï~÷»Ò£>*I’$;wNúá( o¾æ¿ã–NIš›ãxï‹%iv–¯ÅÄTn“ÉõÂü8tw‡5Þ<¨qîÞá\ô ±¾.I““’ÔuÉ*¡Kºt‰§is¤z(èèàxy%àtJÒ•+¼nѾßl6~OkëæušŸO j°Û%itTZzã ©óG?òÐ6Ønœûòò²TWW'%%%IÏ=÷ÜæëÿøÇ%½^/Ý{ï½›¯>|XZ\\Üü=77×õÕvéÞ{ï•N:%MNNFãèBFLÐX^^ò\AÍÜÜ\dggcii Çý”gž;wßþö·¡›››qæÌ™ÐÚlÆ~òÔæç#£²’!•+çËÈ`Ô¨ó¼UÎ^è ¹2Œö dmá%Cããü7”±ä.¤¦ò§b½ÒŸbEÃãä$ÆøxîfZßç³¥!œ¬’ÈÎf-­W°^’Øš³ºJ§nu•^•NÇÕuyu<’Ót€ÎG@9"^ŒôÚ©T¼&&˜€¨¯^#^\ók®Þ¥‘…,e”ãøñøØ™H¢Ñ%%ZXÀƒŸû²¾øEÜùáã¡'ŸÜVÀË[ý¶ÛnCee%^yåØl6<ðÀøÁ~€Ó§OoóÕ{šèÑÖÖ§Ó¹)_ë SSS›ÏÈÈÀòò2àÖ[oÅý÷ß—^z /¾ø¢ßϯ á›O=…7ýk¬ggãÿþéOI ±› º¡>4¥XpÙv+ZÊ£}Õff" V“;,,0<‰8õú:`µB••‰txÚF›m8++LllðõøxF÷’â¬Ð­ë [§]f4Òn6¤d˜',0§q·M&…JÅÐ\j*¹¥ªÊǾ”—3œ“Ÿ^1„ZÍR·‹ù¯ ‚EEÜé‹IPQ$bGbº5G‘œµŒF{0žçcÜóîâèÑ£¸<<Œááa<ùÄxᦛPÄ9šè¨tÙœøøxÜsÏ=øío‹Ó§O_Wšè1E ƒ§OŸÆ /¼Öç1ôúú:àóŸúnøó?Çtw£`·õ.ýAä9ff€ª*hôz4‚aØöv>ÃQqBúú˜± GüÉÖÖ˜( 5íÞ^fQ} >žyïö›Æ{}È€å¸lL‘\Ü kT*žKñ£ÑðÐU*—ÍšLôò F§“d`·óÇáð¬z‹£ÍÖ9tÐ97Y¨ERR{j5 öèh`*ˆgFGÏ»Køôt.:;™ðV¼Š×ª«‹)²œœ Íô\ÏŸç‹Au îÊËËñÿþä'€ï|ç;xãK_Úòž¹¹9èt:¤¦¦nj¢?òÈ#Eii)Î;‡~ðƒdÉî3gÎļ&z̈ÅbÁ]wÝ…'žxͪkÂeè$Wqü‹o½åQ%s˜Ÿg¢¸°p˘÷Š †nZ[.±Ûe©A?F:,X­´GFfÄŒF~>Ä•o|<ÀqsÀñ*ÀÏty›M&‡C& Iì€*]&Fþ¤ãii€jHõïMûEQ‘ÑB½r…îž‚÷ÊÔ¹b‹ @q1½±VEFk²B„¸é¦›|¾>::ŠÏ|æ3›Úç>ú(***ð¡}kkk=ùÔ§>€šè÷ÝwªªªPTT´YT‹ˆ ‘$ >ø n¹å<ðÀß.C»bð3ER¢†µ5ÖŸ‹~,SV ¯ººØ˜ñX'“‰äQS£l™‹ÓIã¥Dn©¿Ÿe8áÂlÞV›$>~›Ð~†§q:;›^Ó6áX¿P©Ê ^$˲²C»v-¢I P«é޲<ª®."wØá %$°ÊÌ'ÏÅÅ‘8Ü5lª«C×EÙ455¡½½}Ëëï¼óŽÏ÷_O’Ý1QÆû‡?ü/¿ü2~þóŸ£±±èîîÆ?þã?¢¸¸ËËË(..Æw¾ódèTUUáÕW_Åã?Ô÷»’·?üæç×£vâp0ÝfµÒ1 »°kb‚×·¢‚S»ˆŸüä¸ï¾Û·4¾—ÈNãË_þª«7ðá%*Ó‚ÂÜcÜññlTŠ`õ/¤e­VÉôF>ðbŸÒä15ÅD¼ä1=ÍPP$¥£ Ê럋pÆš¸#+‹Z‰ÙLuu ‰¹âîŠA«%ÁNNrQ½Ž¬,ª‚‹Šxó//“èWW#ØXøx÷Ýkx衯íÊwï&Þ—o¼ñ*NŸ>†K—BoŽ««¼Ñ—– J IDATxã)²Y•Š Àƒé ú™‡g6óû ££‰±´DQbÅ,<´p+‘¬ÖÝë@z§½½‘ï‹ÐUïêR~ΕضJÅʼnk®“;l6F5''É7Š9  ów‡óÆÆñmƒk×&ñ'òEüÓ?Ý·cß+x߈Z­Æg?{?bTÔIDT# ðF¯©‰Š^³˜Ì˜ÈÈÇPXƒ%˜uuÑ™H»¾NC' I¤#ÑEržv²yÐÂiâÔTžO%V׉‰¼ÿÚÛ£“;¨¨à5óJÌ˃£V‚®ÓñÞ+*âñ F=?26¶Œ|àa|ë[÷â–[|Wa½—ñ¾%´4®ÚÛÚ¢´hq:忢"&w ¡[TÄ$ûô4¿ÚÜ;ÆÕ|SSt$FÃÕ3÷¡·F׺v3|%šÊ’×H ”"ö§¢‚×+ÈÉá"¥³ËÃKhiáíqòdt¥X6‘™É/Ój¹Šš™‰Ê×,-9qòäÿÀßþíøÜçŠÊwÄ:Þ÷°—âÐ!V$Z, nxf†7pbâ>=2âãÚƒNTZ® »èI: »…™B[ôàAåÈQÈ3FêÉ,.F$^¤rr¸‘@§#ñ‡ª3²Ý>ee)GJ^0«’Ðׄñ ÓhÌUäR†ŒÂB†‰WV˜t‰”Äݰ´ôõ©ñÓŸ>‰¯~õ Ŷ{½a@\HK£gé’ùÊ•ºð++¼Ã­þ‰ ÐÚŠÔòl4}¼z=“ì## {öÝÝty”¹`µÒà*Ñél·GnX deEN õ*B•ËÝ¥¥™hÎÈIW¥¢û82ÂîQ¥ t¿»»y}Ý07Ƕœ„FÑ"j­Q©¸È™šâ¢§¾~w‡"&&òxF’ˆkBé†MƒŽrL¬DBc {ÊËùY'Z:‰úÜhëªc#9 0„6>ÎUBav6ÖÖ¸0ëé!±äçIÐtv0Ĥ´»ÁàÑP¨ xa!:Í’‘@x!J”0tZR¢,‘çå1¬38kñ~Œ“\ˆT…Љ òdCÃ6i³´4zIii¬¾œœ„3ÈFÄ´´4¼ýöÛhooGkk+ž~úiÌÍÍáôéÓèééA{{;Þyçüæ7¿¼ð ¨¬¬D?î¼óN|ó›ßüò—¿Ä}÷݇—^z ßÿþ÷•8ôˆ2>>ŽS§N¡¶¶õõõ›À;ÊГ“¼1RSå%23å~‘(W$ 0FÜÔ´sn´˜ @3D´&;F2ILd䯥… 6¿%öN'ŸÞÒRe÷{eE™Ràh ''òñîÞ¨©ñë…8t ¯\a¯ÏØ9ìÄ ® ²³Dú’’d]õ*¹ÍÌäʤ»›‹¦(Ánça­¯‡ðXåå'OÂi6㮂|ù¡‡`@®jµZׯÍf3¡Óéð‘|‡††L¹šÎÎ;‡O|â€O~ò“8wîÜæûL&Ìf3âb¥ ^ŠLOOK’$IÒÌÌŒTXX(™L&é7Þ$I’l6›ôÁ~Púõ¯-I’$=óÌ3ÒW¾òI’$é»ßý®ôè£J’$IçΓ~øÃJÃÃÛ¯¹£­­M µµµm¾æXX¤óç%ipP’ްatT’ZZ$i}=ìMø†Ý.I—.IÒЇƒçee%ìM8’´¸(I×®qS—.IÒØ˜Û9”¤ÉIeöWÀj•$·ë«.\Pv{çÏ+»=I’¤®.IZZ’$‰—lhH’Z[¹ë’´ºáö'&$©»;òý ‡$utHR¿â›^\”¤wÞá¿áÂ8?/ýÍÍ7K§ÒÓ¥ÿëé§}Úååe©®®NJJJ’ž{î9¿­¬¬H•••ÒÄÄ„$I’tøðaiÑmÇrss%I’$»Ý.Ý{ï½Ò©S§¤I¥Ÿ›04–——‡<×à¼ÜÜ\dggciii[†þö·¿ € ÝÜÜŒ3g΄ÄÐV£ÿç_ý.´µáÿ‰8[RÂ\ûåËaHËúƒÙÌðAUÕÎO”íìd(!‚ÒJ•Š«]‘ްZ¹îë6ÖìÐ ¯!ëTôJJ–ÇÂôÝ@HHàÉP h@’–2ÄWÁðŸý°Õd 5•žEI‰‚‘ÁÂB†””ø j5ChÃÃly¯«‹ø€œNæÄ­Vz‘,äÓ²³ñÝ_ÿííøê_þ%^xê)¿ïMOOGgg'æææpóÍ7ã¶ÛnCee%$Iƒ>ˆGy…†®j4¼ôÒKáïp!,w´µµÁétzœÌÕÕU¼þúë8uê`jjjóïXv%!n½õVüæ7¿Á#<‚/|á ~¿ãçßý.n/)ÁDb"~>4¤Xõ–µX˜ :à ‹‹²¾ÆNÄÞ^Z}…û(h‡êë“úTÝ”•JNä¶µq¤Øâb!÷XÎD Rh±°h­·—i‚ÖVF_u‰8r4'Ëçpè+äo¯®fÂOÉRä`P^N6ô© ËËŒRgf*'[•x±·_þÚ×¾wß¾}8uê:]Z,=öôz=¾ô¥/m¾§  ®Q/ËËËȈµrt7Ä„"`0púôi¼ð ›¯)ÉÐFW0þ—ヒŸ\¾ŒR¥cï઻²’«ÂÎNV¶„\,5<Ì»½©içGqLNÒzGáÜlbcX]…îÀBžvo·ó°—–¸ÐµÛ™ÇMKãOjjžŠÉ¤|“£ÒÈÎf&{›ñ7’ÄCY]eJgu•«ç„&»ssé˜z4µë÷³³{ß¾èí{] ¹V»³z=ó1axä½^‹…9ºh5½ø£?òùúÜÜt:RSSa4ñöÛoãoÿöoñüóÏ£££ÿõ_ÿåñþ~ô£øÿøÿ¿½3‹ú<÷þw`Td—EYd“Eá€I´ÆÔ¤1ꥩš˜4Ѧ5K¯¤iRmcÓôœ6ûÁó¦ñ½š¦}OmS“\šäÔ¼YZMTPA°QvDQ]†fæ9ÜüØAæ·÷çºæR`˜¹™ùÍó}îå¹oäææb×®]X¹r¥<»ÍˆÕjÅš5k°mÛ6äääô|$…“BûvŸßùÎ;²ˆG_¦O'o¤ªŠv=ÉÉ£XלNJZO›FID¥in¦ÖÞóçËûüðCèt:¼ùæ›xä‘G®y…hã”™Ù;ávÐn¨¥…ê^çÍg—:éê"ñÊÈÿ“VRâ–“Æ’ô;£¿Ì áÕѶZiwoµÒ‚n·Ó"?”Nêt½‡Ø{Ö¥Ò)€'ýŽtë;Jz,ék½ž.ÉF//ò’HÔ<=„Oœ nª¶èût·W>{VÞV ÞÞt!©ã-ÇÆR‰o~>%4ºËd…èÛ‘˜¨Ýj&ä†n€cˆÓA¡ûJyé²2ªÇOL¦5ww«oIˆ«HóÌ“’ä?_ÒÚJ+«\9Šî–:Пb2½ç¥$ ý¢½ºDú¿$,ãî”D[dw ÐÛh1*JÞk*(ˆ\¿3g¨Í‡Ò“ëVP$$ ÑáòrŠÞeg+oÎdDsUXƒ>kI‰%—ãÛ“]èJUq>fq1íX•è.ééI ©Džó"²À"'ííÔZ"6ˆŒó¯ô«YYä8>L‘'—6wBÐÎ0>Þ-ÕJ£Ân§Xœ\§¢%šš´9@j4Èè=W*{àããòsvuѯæçSÍEv6]Bcv˜u:Ú´y{Ó&n˜cŒë°€ÈE}=•ˆÌŸ?îÙÜUefg“=J9é1E?¾ý–âÃJ.´••““3T&ÚÐÊ|„±@»d91™(Ë,·Põeöl:—3†’ÅB™‚rÌrrèH˸/ŸÈHÚ‰;&_ÕÛ$åýÔiœ²2ú4de¹5t#2ž9“6ö'Nк0{öUœŠêjŠÈí ôÅf£ƒƒrûhkSæ ‹\ $€N§¼a¾ØXº`” õ¥¤ÐÎêÔ7QÍÍt‰JÇWdy;ýüh3WXHù¸“(Ìhaq'å Vv?¡¡tkk£VRÝAØh!OO—ÕžA”•Éþ¸¶óþþôÉézxÐëtñ"y¢J ëž«~ìåÝú´Rv8È9¹p#1Ñ3a†ÃË‹6u§NQ…–×ç‡CXƒ‚¶ÑÑò¶B€¯/}FSSILŽ¡ð–ÍÊÀ1Ï\v::(|¡ÄÜö–åæÃË…y€®ÍêjeÊFc¿¹êíí¦:vŒ~œ™IU·²‹‡„^OŸOOòȆh¡ÄŒžkB@:::0kÖ,lݺPQQÌÌLÄÅÅᡇê¹_yy9²²²°bÅŠaûhÉBCÕ¿§¥©–Ìõô¤(Ev6å ‹ÛPð·J4DfÈŠÒR·4L¼*R5ÒŸ»‘<¹1(ŒYS#ÿsõÁá9ç½·» •‘‘tFE©Ø%wÖ,Ôü|eÎÉLP®‰OÞ³Ï>‹… B×Mûå/‰ßýîw(++C}}=>þøcÀ«¯¾Š½{÷bíÚµ8pà€2ÆUVÒA¹¬,·QãÓ!A,Ð qE Ú,ž8r„*8$L¡½^™®ÂÁûz;4*±ŽŠ¢¸‘ÏÕÜLûªãÇáë‡K}‘jø—vRV´é+*R¶À`¡y)++CII n½õVˆn×ûðáÃX¾|9š‰¾oß>4‘°½½ðûœƒÃA 9!(†¤æÀ110y#6¶÷àUEUpUUÉØé¡´T¹ØòDÈHЊ+7:U]TUÉòðíít~ïÈrÌcbhGT`ˆ §<„LÏíÒªóçi3ÈŒ Í ÈÖ­[ñ /ô|ÝÔÔ„€>a¢ˆˆÔÖÖ~ò“ŸàÀ¡C‡°lÙ2ùŒêì¤ nD„r½¤FË™3S°°úûSèWr”N"ヲÆåñMMTq£”'v­W`õesÒÇLh(½WnÚEttôε¯ª¢BŽœŠbêÜG^ªÛ[,Œ© ‹tVŠó"£FÓUX}ôâãã‹C‡@23gÎÄ?ÿùÏ«>î²eËy(ëÖ­ÃŽ;®nTs3m±RSµ7{[:e8Âv½¾·‚Ën§ÏqQýZp0}ß冹ååòÕ°ÛÝ0”CCøøP»¥ˆ‹£÷+)É¥_oo§Rò¦&Ú/„…Ñ^jToǼy´›2E[ŸbbÈm’ªÆF˜óÈ#`Ïž=ý¾§hÞU#hZ@Ž=ŠwÞy{öìA{{;ººº0}út4÷qõkkk>ªÇké>°»¾ ϱ6ß«©¡ L­áO#ÑÔD-µÇ°€äDEDЦëÒ%:oh³‘:†TÆÅ‹ôKJµHin¾öºï^ £‘ÜA%^À ÙX,£ò… ”S}=9~ÞÞt}ŒZ4ú¢×ÓŽÿøqšf(÷ ³±0cF調s‡-ŠÙ±cÇ  ç‰'°`Á%¬Ô ša=÷Üs¨©©AUU¶oߎûï¿¿ùÍo““Ó“8ß½{7V­Z5ªÇóïN¸z{{cÆŒxë­FgˆÓI½}:;©I›ÖÄÃl¦sãhh0Ð.2#ƒôÑϦ¢=Já®úú<{iލœ#T2‘òAAÊÎÔˆ§œÕ0ØlTRP@ý¨édxN ‡èéI^¼CFӦч ªjLkyyå2¥M4¶ŽŽ_|wÞy'}ôQ|÷»ßíI¨–ÜÜÇ`µê°fͯð—¿üŸþ‡Ï[­TÃ>s¦2ƒ—ÆŠÍÖ;—ÚM‰|½ži}6›É;)( ­ð÷§Ÿùúv/ çΑ£d!ÁµÚw$‚‚hÑRê:óñ¡7´ûµt8ȱkl¤4…§'mÈ““eê”?m…ÒNžT.ô9ZŒFÚ,––Òæ19yØrñ¦¦¬X±gÎVØHõ¹fdãÆ=ÿÅ1é$’‹,\˜ººOñÙg…ÈË£²ðA‘°¶6Šé¤¤hs±r:i—œ,k@j—2{6=¥Ê(-ô€sün|„B)‰kqöÇh˜6M¡ZkÂáZç¢é@Ú¢R ×Óæ "‚N†+B` eáOŸVðIÇ@|<%{òóÉÃï“ t:gŸ}¹¹¯aÆtìØñ'dee©h¬ò\3"Ë–¥Ãé¤pp^Šõñùî/ÒQY¥âúc¥¸˜”OÁD¤^OŸy)ýà(©Bó´\¬Ó¡¤”Ä×—"??™^ºkqúàh‘f¥Ë0ú·³“Ä¿¹™’ààï?!áÄÇ4C¨RGã¨(ª¬©±D5BCIÜOœ ¢__ÔÕ·Üò ::¾EAÁ#&&'NœPÛRÅ™ôТK°3§ g+1w¶ ž h·Ê§¬Œ„Cͦp]]0´6aFv,¤\N'…?ZZ(²ÕÕE΂ŸÝ||ÜéjlÔ^ù´»ÊyÇÙøÒf#ZºÙí”+÷ó£=G¿âˆ¨ŠOfÏöñ@ ôÔ©ÚÌmMŸdfâÊ7Å8Ó ߸`ìÙ³ññô:%, }0ºn/Dk| ®Ä °‚Â6Z:#€Nwv*7’v8ÊËÍ9×ë{ÅBÊ©K‹Yc#yzv;y&>>t›>}ŒGG::”›i¢4AAT&>J‚¢^—/Ó­½DÜÃރ€€Q\ÞžtÇúzu7$iiTBk2)ÓÉ` X­@I‰œ>Hñ)Á{ã¨Cn­­­X¶lìv;l6zè!<üðÃxæ™gðÚk¯¡££ =÷ïììÄ]wÝ…ââbDEEaÏž= „ÍfÃêÕ«ÑÔÔ„·ß~sæÌ‘ëÏ5, W®P¹QRü|}‘ Š`å呇íÒ@9hm%Q»\Ðb¡•k¡$)Û·S°ÝÞ»èÕ×Óôðy{ÓmÚ4ºõ[ü:;µUöénL&ú 67›I$ÚÛ)‡¡ÓÑkäãCUtÓ§»ØlΊó«w¡KúNœ ë[y.‡ƒ:8H“ üüt€ÚZ¼ùÓŸ¢möl<òøã#>†<“É„ŽŽ$''cýúõøÞ÷¾‡ÿøÇ˜7`#øç?ÿ±±±Ø»w/^~ùe¼ð ÈÍÍŰaÃ,Z´;wîDnn®ŒùèЄ€œ;w÷Üs`4ñÔSOaíڵذaNŸ> »ÝŽœœ¼úê«0 îWèº:Š¿¸hÃÂhCVSC嬳g«Ç­ž±Á@|þ<í˜ÔÂË‹ŠV Ü>Og,8ô¹¯«#mt©GDàÖGÅ‹áð—_b×Gà Ðëõ0uoz, ¼¼¼0eÊdffyÿ}ûöaûöí¨USNNrssa4a6›a±X`ÔÈQMXááá—_~©©©¨¯¯Ç‚ pÛm·áOú¦wW?­_¿{÷îźuëÜ«Ð%%¨fQÖë©igd$…_ª«)j£xWšgžž®þ9)N"Cò^Ц u~«« °½Kè\ttP2ØbéߊE¯§Çè{óð ›ÑHÿ ô9Ö&‡ƒnv;Ù%ýk³õþkµÒÿ¥¦ :­›&Swô&Ê3 ˜¥løtæLÚ)ED¨Ûáx¬IDATútÚ­)>ÇFÒPIG³³‡ß«ÍˆÅûUUøùM7áº9sðì_þ2ìã¶µµañâÅ(//GnnnϺ6.\@DwÓÏÏ­Ýš—-[†»îº ï¾û.vïÞíúéF4! ¡¡¡í®} APPš››{^D»Ý«ÕŠÀîUÛ- m·ã/?ý)ºüüðàsÏ]ÕF£‘v!6¹´••”ÇU¤{»Ô£gî\MtüEI‰*%—$øÌ¾BIˆþ‹´ôÿööÞ]ºõ-/-b¨Räo§ úYߎ::]ïÏôzºV¤›$^žžä5ô¶a±ùÓÐ ƒÂž€^OöêjÚv«Ip0ÅìJKåŸj zÿ.\ ¯#<œ„c4ª7™ðÒÁƒø?ÿ9]½zØûùúúâäÉ“¸tén¼ñFÜ|ó͈?¼ƒï¾ûî˜~Gn4! }9~ü8Gx¬]»_}õnºé&,]ºÀøÚi6ãñE‹ðÏK—ðÿ“}žž´vÚl”C®¨P@Hþõ/ºªµÐº¼¥…¶Éj$±Íæ«ö“vóî­‚5J–÷{zÊØ.ù*„‡S+ݨ(õcƒÑÑtí×ÖÊ6޹¯p„†Ž^8ú¡×ã¾—^B`BV?øàˆw Æ’%KPXX8¬€„‡‡ãüùó@kk+üF¬6šjeÒÜÜŒ7âµ×^ëùÞûï¿‹/B7ÞxcÄß—úË/¿±?ÖÖÛoÇ…ä••¹üæxzRIxZ%óò¨M–Û©ª¢Õp”ý¾dG©QµC1Û— ÇôéTØ¡11´3ÒIITÍÒÝÇÎ]H9Ž#GÈ3ÍΦ¨Ùx"wQÃ"¼té®t¿—mmm8xð RG˜ºbÅ ¼õÖ[€]»vaåÊ•®%3š«ÕŠ5kÖ`Û¶mÈÉÉé÷3¬[·ùùùzÀ˜Z*•˸ûn¼óá‡Ð»!Î+y$t=J×»[¦†Ö×kkvs}=Õ†ªU3‘DÉöî™1ƒÄkˆj0ő檗”¸er ÃAáç£G顳³ÉÑ‘3åsöìY,^¼éééX²d ¶lÙ‚øøx<õÔSˆŠŠBkk+¢¢¢ðûßÿ°yóf”——#..ûÛßðÄOÈgÜ8ÑDKM›6aéÒ¥¸ûî»PÞ£¶¶³fÍ‚ÃáÀ¾}ûðï|@¯BçææŽI¡gtבþàÞ{Ýþ7xxP¨ÖáèÝÙ„…clçåËÔÍp˜J Å‚¼!5íQªS­  IÉ•}‰'oSí³F@ï\õÂB—;CX­tù¶µQ­@NŽr…ŒYYY(((ôý§Ÿ~O?ýô ï›L&|ðÁJ˜6n4! _ý5Þ{ï=¤¥¥áÃ?„N§Ã믿Ž|ííí(¿qß}÷ …Þ°aâââ‰÷ß_Móûa0Ðg>:šb«ùù´iŽÃñ…ÎNŠý.X yßµµ$V«ìòemÍŽ£‘â,CfõÀ×—* F‘wR„)SÈÕ—Dd”¯ÉåË$]]ô¹LHÙÎI†&ä†n€cˆ–Îß|óÍ÷¿Z§ëµÑÔDz ×ÓE‰`Q›öv ¢†ÌLÌ4Pª¡½>$%%´nFD¨´»*-ÕÆ”–õ½ µ ¢Œ°šb4RkO„D[}ÚÛÉŒyó¤úÀ¯{®zVÖä qj5±Ù(p;~¿‹ßÛ›Ê … øni)9!!”CT¤8Ël¦ÚGµCG…o´Rά4¾¾t¨Mt4¾ Sä½0›I¯š›é%ˆŠ¦Š{Ú4ÊÓÒçHí.Õ“ µp:)ó—’2lã&Ž6 AA´Ž^ºDŒN'‰Ih¨Œ‰B…šØ]•– ÄòTDêÐh·«Û…Y¯§U¼¦†ÄD::¨‹Cc#yÜ£¼è—¿ýHN–Å6fhX@Ô¢¨ˆ…ŒÐÖ¹/mþÂÂh-©¯§‡‚ÜúÐP7z&mmô„Z(žol¤?z2H[ñà`u툈 /$2Òmbf6“h45‘h„…QÕ˜‰ÈHz°³g'_¹·Š°€¨Ai)…†\\ŒÆÞCŠR•í©Sôÿ  “q5Ë--ÕF €Äl² ¢ƒœj ˆNG›žÊÊqy§­­TÛÖF×iX¥¸Æ}š;—¼ú©SUOøOX@”¦¶–r n Ô¨7<œB[ÔfÞb¡˜qp0yø£þp64W¤…ªµÃ6ZAÍμ ¡]¾Í6j—×n§ëòÒ%º.}}i“#˾ 5µw®ú(½{Æu&ifR%ZZÈ_OJ’åáõzŒÔTê:A‘ü|3]S3¸Áê#<Òïkgy¹f*žìõõøãž=j› 6¨m^ÿë_áÔBw\ˆ‹ƒ³¤dзû^KW®Ð¢ü|ÊowvRA_v6 ‡lµA?uJ½™*“…p¶·ã“—^¢ÖÔ UŠøøÐ‡ößþ"RF#•=JŸ¯úzà½÷ööÜ¿îÄ ,^»V3Gx¿xï=üõÀµÍ@…fcìùòKüFƘÂß+o¾—ª«{¾ÕÙ ¼óÎ!Òõuî] Pç…èhKÑ==”|öŸÿ ÑcqP‚®.lY¶ U¾¾X®RHÆÃ£7ÔPM}c#`·'ãèQÀÇÛ‰ïÝ‚¥÷ݯŠ}CñÙàæÛoWÛ MpýªU8ð׿bù~¤¶)€Œ;6âñ5ãoì‡Å"E<Ý= ÒE¦OÇÀÿ|ñþë‹/Ô¶fˆÜßoÚ„¯››ñ·O>QÛš¼½iWèáQ„ìl ýÌçÈ«mÅÊUOáèQêÑuႊ3…¬Vœ<}÷߯AS“û~åEEª={;…@%ãûŸCyÕY8ZòMã: †:mˆG7{¾ú 'ª«ñx@mS&,ìÈÌÞßþÿýÙg8\]í– ˆ²àpà÷¿x[ÿëIde‘f3åOJJHD<<€Â¯påÊ9Üyç­ ‘·µˆåüy4`µ+4Bhh(Ì:š›15 @Ö窨¨ÁÛoŠÀÀXdfÞ§“òÑþþèãaè±ù™ðâîÂ;åå²Úã*z½ûŠŠ°<:3±ög?SÛ¤ Ǥ‹Å8}ú´"ÏW›—‡'·oÇöwßÅ™3gyαÒÕÕ…··oGA{;~žžŽ'N º‡UÒœ=[ˆ½{à?þã°ÛL&¢£ñÌ3ÛàåÖN_¼ú*¦Ìœ9¤=Jc4a‡!2/?ý4n¾ç·=fWÐÜlůý"Ξm„Õê„——³fbݺ[ ÓùÃÃ6/ÒM"ãºëðêo‹Ý;w"qáBtuuiâuÈ/_ÿ~Çðš1‰‰²=´®HëÌd@'„[¦w_ìÞ½?øÁÔ6ƒa˜ Ì®]»zFsOt&•€466âïÿ;¢££1…{?3 ãF, ª««qË-· h’tžTÂ0 øfu†a­ÃÂ0 ø ˆ œ;wK–,Arr2ÒÒÒðþûï÷ûùÚµk‘••Õóugg'n¿ývÄÅÅaéÒ¥hjjØl6,_¾ÙÙÙ¨¬¬TÌÎM›6!&&ÈÈÈèyn%ìΦÎÎNlÚ´ HJJÂ×_-«MÃÙ±hÑ¢ž×%88=ö˜ì¯Íp¶|úé§HKKCzz:n¹å´tÏGWó}úì³Ï‘‘””<þøã=÷WëommEVV222œœŒW^yuÈÌÌD\\zè!Õ휰fÌ\¼xQœþøãA÷WÂÎálzòÉ'ÅóÏ?/„Ân·‹ÖÖVYmé=”¸á†Ä?þñYíγÙ,âããEii©Bˆ'žx¢çõQó}š5k–8{ö¬BˆÍ›7‹(fÓP8a±X„B˜Íf-êëëÅ÷¿ÿýžk|Íš5bÿþýªÚ9QaÄBCC‘šš  APPš››ÑÕՅ矿þõ¯!úÔ&ìÛ·÷t×îß{ï½Ø·oÀh4Âl6Ãb±À(C‹“áìÐÏ>%íΦݻw÷ìö |}}eµi¤×jkkQUU…Å‹ËjÇH¶„††âòåË€¶¶6„w÷¡Që}jll„··7fΜ ¸ñƱwï^Ål ½^Swçh‹Å“É“ɄÇcùòåƒìQËÎ ‹Ú v­sìØ11oÞ,Ο?/nºé&!„UUU£5ì‚ÂBÑÙÙ)î¸ã±sçNÅíìkSCCƒÐétâ“O>Bñ«_ýJ<ù䓊Ø4𵑸îºëÄ7ß|Óóµ¯M_[‡HNN………B!~ñ‹_ˆgžyF1[†²I!:$®¿þz‘-¶lÙ"Ö¬Y£¸MÃQ__/’’’D~~þ˜„q a¹ˆÕjÅš5k°mÛ6äääàäÉ“øöÛo1{öl,Z´ÅÅÅX±b <<çÏŸ@I??Ù†!\ÝN€Âàåå…{ï½ùùùŠÚ9ЦÀÀ@øøøàÖ[o¬^½………²Û4Ôk5558þ<.\Øó=¹_›¶444ÒÒÒPaÆ7ß|£ˆ-ÃÙ×_=:„#GŽ -- qqqŠÚ4ÁÁÁX²d ª««…##""4cçD‚Ąشi–.]ÚÓ²`ùòå¸p᪪ªpèÐ!Ì›7û÷ï¬X±o½õjs°råJÕì€‹Ý œN'>úè#¤¤¤(fçP6ét:Ü|óÍ8rä૯¾BR÷Ð-¹lîµ€={ö`ýúõý¾'çk3”-3fÌ@[[ª»gn|þùçHèá§Öû GØÚÛÛñÊ+¯àGÝíåÕºÆ/]º„+ÝÓÛÚÚpðàAÌ›7999øøãP #ɵ윰¨éþ\«¿?Ò™2²È 3sg˜çuŽ'‡;Ÿ¹÷Ép‡gîÏó|xŒ1B!DF|® „¢™(B‘ %B!r¡B!D.”@!„È…!„¹P!„"J „BäB „Bˆ\(B‘ %B!r¡B!D.”@!„È…!„¹P!„"J „BäB „Bˆ\(B‘ %B!r¡B!D.”@!„È…!„¹P!„"J „BäB „Bˆ\(B‘ %B!r¡B!D.”@!„È…!„¹P!„"J „BäB „Bˆ\(B‘ %B!r¡B!D.”@!„È…!„¹P!„"J d‚‹/âÅ_ÄÒ¥Kajj '''ìÚµ Æ2Æð׿þ+V¬€±±1¬­­‹êêê cïܹƒÿú¯ÿ¢E‹`dd<ûì³Æ}÷Ýwpuu…­­-¾úê«IcüòË/áãã###xxxàÓO?tܽ{÷ðÓŸþ¶¶¶055ELL ***&ŒsqqÁûï¿ÿ¨—†(‰2Î9>Ÿ?é¿?þñö9“sN,??|>:::èîîžð¸6sº\@ÔÏPXXˆøøxøùù¡££D@@Š‹‹áãã#ûãÿ)))øÑ~„—^z ¨¨¨À;w¤öÙÒÒ‚ÐÐPðù|<ÿüóppp@[[JJJ¤Æµ¶¶bÏž=xá…`ff†^xþþþð÷÷—Œùâ‹/ðüóÏ#>>¿øÅ/——‡—_~ƒƒƒøå/)ÇÃÆQ]]}ûöÁÊÊ Ÿ}ö¢¢¢P^^WWW%½‚DVÊ8ç`ݺuøÑ~$µmÅŠR?ÏäœcŒá¥—^‚©©)&}\«Î9FÈC.\¸À„B¡Ô¶††fhhÈžzê)ɶÔÔTÆãñ؉'¹Ï 60WWWÖÓÓ3í¸/¾ø‚íÙ³Gòó[o½ÅÞ~ûmÉσƒƒÌÚÚšmÙ²Eêy{÷îeóæÍc½½½âKOO—lëììd,11QêùÎÎÎì½÷Þ{äÿQeœs<½ôÒK÷¨sn¼¿þõ¯ÌÆÆ†½öÚkŒÏç³»wïJ=®mçÝÂ"CWWúâÔÍÍ ¾¾¾¨©©‘lûÓŸþ„Õ«WcË–-`ŒáÁƒ“®gΜÁ¾}û0þ| ctttÒ±°µµ•ülccƒþþ~ÉÏçÏŸGww7~ö³ŸI=ï…^@?Nž<)Ùöõ×_cá…غu«d›µµ5vî܉'N@(ÎàÕ ª èsn¼¡¡! Oùø£Î9±žž¼óÎ;øÝï~ssóI÷¥mç%2c·o߆µµ5àþýû())ÁªU«ðë_ÿæææ055…««+ÒÒÒ¤ž'Àãñ`ccƒØØXÁÈÈ7nDSS“ÔØàà`|õÕWÈÎÎFYY<ˆ°°0Éãâ{ÉRÏ ŸÏ—º×\QQ€€€ ÿAAAxðàêëë%Ûx<žœ¯ Q&yÏ9±¤¤$˜˜˜ÀÈȾ¾¾HII™0æQçœØÛo¿ ;;;üô§?2^­;績"šá_ÿúãñx,))‰1ÆXEEãñxÌÚÚšÙÙÙ±/¾ø‚¥¤¤°àà`ÆçóÙÙ³g%Ï}å•W$c7nÜÈÒÒÒØÇÌæÍ›ÇÜÝÝÙàà Ô±^zé%ÆãñŸÏg»wï–zìÅ_dzzz“Æhkk+u+ÂÔÔ”=ûì³Æ:uŠñù|vîÜ9¹_¢|³9çc,,,ŒqÎMFWW/¾ø"z{{QVV6áñ©Î¹ÔÔTáã?~dìÚvÎÑ4^2¥¾¾><öØcèëëC~~>.\(yÌÞÞ°`Á‚ ϳµµ…P(ÄÀÀæÍ›7åX>Ÿ+++ôôôÌ8&;;;Œ¡««Kro„B!îÞ½+9–xl{{û„}ˆ·KÔƒ¢Î¹©8::À¤õSÙ·oŸäÃŽø;;ñ9{ëÖ- ÃÎ΀ös”@Ȥ†‡‡ñøããÚµkÈÌÌ„§§§ÔãvvvX¸p!Z[['<·µµ†††’7r`` cÆ …BtuuÁÆÆfÆq-_¾Œ1\¼x=ö˜d{ii)D"–/_.56??Â>ŠŠŠ`ll —(Ÿ"Ϲ©\¿~d:çš››qøða$''Ox, Ë—/Gyy9-<績‡FÔÏØØÛ²e Ó××ggΜ™rÜ«¯¾Êø|¾ä‹EÆ~˜ónnnÎ6oÞ,Ù6<<Ì,XÀÜÜÜØðð°dû_|Áø|>ûúë¯gÛàà ³²²š´ÄÔÔTªÎ$55uÂþÅsòÇÙN¸§ès®³³sÂsûúú˜««+³µµPs2'NLø—Àø|>KNNfÙÙÙ’±ÚvÎñcŒë$FÔË«¯¾ŠO>ù[¶l™ð½$&&ø¡5ÉŠ+000€×^{ ffføâ‹/ÐÒÒ‚¢¢",]ºTòœýë_xúé§±råJ<õÔShjjÂ'Ÿ|‚ÐÐPdeeÉ4¥ñ¯ý+^|ñElß¾ëׯGnn.:„ßÿþ÷xã7$ãD"ÂÂÂpåʼþúë°¶¶ÆgŸ}†ææf”––ÂÝÝ}¯Q$Eœs.\À²eËï½÷Ž?ŽÍ›7cñâÅhkkÃ?þñ477ãСCHHH˜U¼ï½÷Þÿ}tvvÂÒÒR²]ëÎ9®3Q?QQQŒÏçOùo¼›7o²íÛ·³ùóç3ÇÊÊÊ&Ýojj*[±b322bvvvì•W^aýýýrÅø÷¿ÿy{{3CCCæîîÎ>ùä“IÇõöö²çž{ŽÙØØ0SSSÃÊËËå:&QEŸslýúõÌÞÞž0KKK¶aé«…Ù˜jcÚuÎÑ!„¹Ð4^B!r¡B!D.”@!„È…!„¹P!„"­ªDïêêÂÙ³gáì쬒ž4===°°°Púqæ’ššx{{sýî4”<¿7EsƒƒƒhllÄúõë¥ÚìÌeZ•@Ξ=‹½{÷r!d;tè¤ðq®Óªâìì ˆ64ÄGJ=ÖPRR‚´´4ðùšq§pD~›Ëi "‘øÃpòäIlÙ²¯¿þ:tttTv|Ƙd}õ¿ÿýï’íêðÚ¨#uz]ÞyçܸqcÒžUÓ‰Dxï½÷ €_|Q®Åžjjj°wï^Éß­Àq!£J•••1lÛëI(Jss3311™rmuõ_ff\‡ qëÖ-æååÅœYSS“ÊŽ›‘‘ÁLMMÙ½{÷¤¶«Ók£NÔåuihh`ÆÆÆ¬»»[î}\¿~¹¸¸0WWW©žj3%þû2U'†¹H«®@Tå±ÇÃÎ;'][€ÌŒ££#jjjpýúuTWW£²²k×®…±±±ÒŽ9<<ŒŸüä'xçw`ff¦´ãÅ‹‹‹Ãk¯½6«ï­–,Y‚7n ºº§OŸ†££#BBBTz¬i4ãÞŠimmE?þò—¿pÊœàêêŠM›6!00_ý5***À”Ô}'-- æææØ·oŸRöO”£²²:::øàƒ²¿eË–!!!fffHNNÆ­[·²ß¹ˆˆ‚566âÛo¿s+qÍÁÁ‰‰‰ÆáÇqçÎ…½¦¦¦¨®®Vè~‰r1ÆpåÊÉzŠÂãñàçç‡øøxTUUá»ï¾ÃƒzŒ¹@+ˆ¸å³¢Ý»wMMMJÛ¿²s´ø|>‚ƒƒ±yófäåå!##cÊåme!‰ °víÚ)Ǩûkî_—ŠŠ ¸¹¹)í–£‘‘üq,_¾ÇŽCee¥Ò®€5‘V&-›7+e¿çÎC\\œ\38ÔÁÓO?Íu3bff†íÛ·ÃÅÅ)))¨­­ÕþÊÊÊàíí SSÓ)ÇhÊk£j\¾.¸rå V­Z¥ôc9::"11<@JJ ººº”~LM • Dêëëaii)ÓR™dvÜÜܰgÏ´··#-- ½½½2¿uuu TB„D™bccU6M^GG¡¡¡Ø´iΟ?ÔÔT…B•[]QQ¡Pˆ . ""‚ëP´Žžž¢££Ó§O#??ccc3~~FFbcc5öªQ[566B__ööö*?¶¹¹9âããñÁ`É’%ÈËËSy ê‚ˆäææ"$$zzz\‡¢µ¬­­¥fÎ455=ò97nÜ€±±1ìììT!Q”ÑÑQäää ::šÓ8ª««ñÊ+¯`ãÆØ´iîß¿Ïi<\ 2Kèî‡סh=ñÌ™;wâÊ•+øöÛo1000éØÑÑQäåå!**JµA’Y+,,ÄÊ•+ahhÈu(xýõ×ÑÚÚŠû÷ïãñÇç:•£2 Œ1ddd`ݺu\‡BÆ144ÄÆˆôôt”——O˜9SPP€U«VÁÀÀ€£(‰<º»»ÑÖÖ®C‘033Cnn.>ÿüs®CQ9J ³P]] '''˜››s ™„¸vD(âðáø}û6€þutt¨E×_2sŒ1œ;wëÖ­SËהּñ|¢V&rBee¥ÖtÝÔT|>«W¯†222`bb‚ÎÎNlÚ´I-ÿ‘©]½zööö°´´ä:òot"§¬¬,DFFRŸ 1oÞ>>011á:"ƒööv ÃÅÅE²M\;bnnŽC‡ͨv„¨–H$Bff&ââ⸅L‚ˆ úûûQ__€€®C!2˜îÇòe˰k×.\¹r'Nœ˜²v„¨^ii)}`Sc”@d‘‘µk×Òì SVVOOÏiÿ‰kGV®\‰ôôt”••Ñ—ì»ÿ>蛣2C7nÜ€‘‘.\Èu(D²6K׎ŒŽŽ"99YR;BT/##C£»[kú}Äm/¸…ÈHÜ,Q–Ž­׎˜šš"jtúJŒ“H»víLMM±`Á®C!Ó +÷Þ¡¶šåæÍ›022’»Y¢¸vÄÕÕ)……¨©©¡ÛZ*  QPP@}Ê4%GèééQ»Þ;äÑFGG‘››«Ž­®®®H\³HKKCOO"$SÉËËCpp0ôõéšOÝQ™†¸Y"݇Õ<оjÔÕÑAtt4bccqæÌäååÉ´î™™®®.ܽ{žžž\‡Bf€È4jkkakk +++®C!2PfÇV+++$$$`þüù8tè~ m5¾Y"Ñ ”@¦022‚’’„……q ‘Áøûʺj_;rõêUªQªª*8;;Swk B d 999X³f õÞÑ0555X¸p¡J:¶ŠkGV­ZEµ#³488ˆK—.aõêÕ\‡Bd@ dwîÜA__ÜÜܸ…È`xx¥¥¥X³fJkooÄÄDŒQ툜233MýÈ4 }¼~ˆøÈæÍ›¹…È(;;áááœ\5òù|ÁÛÛû?µ#QQ4“hš››ŽŽŽGBdEW ¹té–,Y333®C!2èèèÀƒ°dÉNãªII¡Ú‘GÃùóçËu(D”@ÆDUU݇Õ0Œ1µêØêêêŠÄÄDܾ}›jG¦Q\\ ???q ‘ƒV%ñ›8áàAܹsgÂãâû°²´½ Ü+++ƒ‡‡LMM¹EŠ®®.¢¢¢‹³gÏRíÈCîÝ»‡ÆÆFøûûs ‘“Vý¥´°°ø88ÀÅÅ?ÿùÏ%·ZZZÀ£û°f``555X¹r%סLÉÊÊ »ví‚……ÕŽŒsîÜ9*ÒÕpZ•@ÄÞݶ 5558yò$\\\p÷î]deeÑ}X $dn–ȇ¥K—b×®]¨©©ÑúÚ‘ºº:XZZÂÆÆ†ëPÈ,¨÷»N‰/^Œºº:œ={Ÿ}ö†‡‡iÆŒ†ill„¾¾>ìíí¹eÆ ±aí®AQQ"""¸…Ì’Ö&1{{{8;;#$$ÉÉɸqã×!‘CNNŽBš%rááÚ‘ŽŽ®CR™œœ„††BOOëPÈ,i}ˆ¸íÅ‚ àîîŽììlTVV"..óæÍã:<2…ÂÂBÀÐÐëPä&®¯;bllŒ¨¨¨9½l€¸H×ÝÝëPˆhõÈ7`bb"Y´ÆÀÀëׯǚ5kpâÄ C$q%yXoo/ZZZ°téR®CQSSSlݺîîî8rä®^½:'okïnMæ­M âU'[´fÁ‚HLL„žž:„––ÕH&5¾cë\›½³dÉ$&&¢³³Gsµ#•••puu¥"Ý9Dkˆ——–,Y2å퇀€ìرøþûï188¨â(ÉÃêêê`cc3g[ìëêê"22qqq’Ú‘ÑÑQ®Ãšµ ººAAA\‡BH+È_ÎclF­Ú±yóføûû#-- •••sòö‚&Aqq±V´Ø·´´”ÔŽ$''k|íˆ@ @LLŒÚO·&²ÑÊßæá‚|ÿý÷2ÝqttÄÞ½{188ˆÃ‡OZÉN”KÜb_[fïˆkGPSSƒãÇkdíHSSttt°hÑ"®C! ¦• $ÜÛÞÞÞ2?Ïç#$$›7oF^^222022¢„Éô¹Å¾6lØ€   ¤§§ãâÅ‹s,žnMEºs“V%ššÀïvì˜Õ~ÌḬ̀}ûv¸¸¸PÇU Ù;?׎ˆD"©¹páV¬X¡ÑÓ­ÉÔ´ªD|Õ¡§ õ"ÜÜÜàììŒüü|TUUaݺu’~[Dq*++©Åþ¿=\;bdd„èèhµ¬éííEss³Êø"ª£UW Ê î¸ºvíZœ={¹¹¹sbÖŒºÏÞ¡ûÒĵ#jY;2—§[“ÿ ¢ ⎫VVVÔE233iöÎ4Ôµvd®O·&? w¥ñx<øúú"!! HOOÇýû÷¹Kc577ƒÇãÑìGx¸v„ë«`ñtëððpÎb ªA D Ä-QBCC©%ŠœD"-u*#q툥¥%’““qóæMNâÈÎÎFXX'kÓÕ¢¢D .¤–(r¢¥Nå3¾v¤¶¶ÇG¿ÊŽßÑÑþþ~¸ººªì˜„;”@”l|K”òòrj‰2}}}¸yó&-u: âÚ‘Õ«Wã›o¾QIíˆ:®MO”‹ˆŠcË–-Ôe222°víZš½£vvvHLLc ÉÉÉhooWÚ±ÊËËáîîNË hJ *F-Q¦×ÐÐsssØÚÚrÊœÁçó±jÕ*<ùä“(**™3g0<<¬Ðc àêÕ«Xµj•B÷KÔ%PK”É …BÒR§J¢ÌÚj–¨è·Í!j‰"-??ÁÁÁ´6½’=\;ÒÝÝ=«ý566BOO Šh J jÀÍÍ ‰‰‰¸}û6ÒÒÒÔ¦L•îÞ½‹ÎÎNxzzrŠV_;rîÜ9¹kGÆD"äää &&F QuG DMˆ[¢ÄÆÆªE1˜*o{ATK\;"î  kíHa}½Æ¯MOäG DÍhcK”Ë—/ÃÑÑóçÏç:­4¾ƒB]]ÝŒkGzzzÐÒÝ=gÖ¦'²£¢†n‰òÍ7ßÌÙ–(CCC¨¨¨@HHסh=<öØcX½z5Ž?ŽÒÒÒ);(ˆ[ì¯[¶Œ¦[k1™ÈÈÈÞxã 888ÀØØÁÁÁƽÿþû°µµ…¯¯/ÊËË¥Ào~ólذVVVàóùøê«¯&=Þücðùü ÿ|||¤Æ555Ïç#77W–ÿµ'n‰2g[¢œ?ÐÑÑá:òovvvسgàðáÓ֎ÔÖÖþÐ,‘j>´šLÍjþßÿûHOOÇk¯½777$%%aãÆÈÎÎFhh(àØ±c8xð Þ~ûm\¹rO>ù$êëë%÷H»ººð»ßýNNNX¾|9²³³§=¦¡¡!¾üòK©ÙIæææÆÍåOAâ–(HNNFttôœh0ØÖÖ†‘‘8;;s yˆ¸vÄÛÛ†††’uG†‡‡QRR‚ÄÄD -ëP ‡fœ@JJJššŠ?þ¯½öà©§žÂÒ¥K±oß>äççÒÓÓñûßÿÏ=÷`Íš5(((4ų··GGGlmmQVVöÈÂ#]]]ìÞ½û‘ñÍõé¯â–(^^^¨¬¬Dll¬ÆöЉDÈÊÊÂÖ­[¹…LÃÔÔO>ù$nÞ¼‰#GŽ`åÊ•hnn¦f‰€ ·°Ž;]]]Ib~¸ÅòÌ3ÏàÂ… hmmðÃ-ªñUÄ666R_ÈéééÉ\e,‰æìw²·DñóóÓè–(eeeðòò‚‰‰ סpqqAbb"pîÜ9Zy“!TVVÂÃæ¦¦RÛƒ‚‚ÀCee% $$û÷ïGmm-ÒÓÓ‘••5«ö<€™™ÌÍÍaee…_|ÆÍå[X“Y¼x15²%J?jkkÀu(D:::èïïÇ«¯¾ŠŒŒ äää`tlŒë°‡f| ÚÞÞ;;» ÛÅÛÚÚÚ/½ô¾ýö[øøø@GGÿó?ÿ{{{¹‚³··Ç¾}û‘H„3gÎà³Ï>CUU²³³%mœœœ0¦…'²ŽŽBBBàë닌Œ ˜™™!22Rí+¹Ö®]Km/4Œ¸YââÅ‹áè舚š$9‚ðÐP,Y²„ëðfœ@a``0a»øËqq‹r ºº666“&™Ú¿¿ÔÏ;wî„»»;Þ~ûm;v ;wî”{ßs‰¸%ʵk×’’‚   xyy©åUYcc# fu^Õ7KLLLðÿ\CBp¾¾—.]B\\Ü„;dn›ñG@##£I;x IãñxðóóSʉ×^{ <oÒéÃÚÎÍÍ {öìAGG‡Z¶DCNN¢££¹…ÈH  66vÂU£ž{ì1?²v„Ì=3N vvv“Îo“÷6•¬ aee5ëps•žž¢££Õ²%Jaa!©í…†ijj‚žžÞ´ïññµ#Ê^w„¨ßÂ×lô÷÷K]¦ÇãaùòåJ ðaýýýèêê‚ÜûØÿþû°9p@j[pp0ž~úéYF§>¬ìb W‹‹‘œ’‚//¸üzzˆñõ…žžÊâU•¤¤$ImëÔÂïaÁf¨¸¸˜ñx<öñÇK¶ 3www:ÓÝH¹xñ"ãñxìŸÿüç„dž††Øýû÷'lÿå/Éø|>;qâ„ÌÇ+++cXÙþýrÅ«©†††Ø™3gXzz:ëëë›zàáÃJ‹!55•uuu)mÿJ§Ä×Fåå屪ªª©LóºÜ¸qƒ%%%±êêj&‰”z‘ü})+ã:•™ñHPPâããñæ›oâöíÛ’Jô¦¦&üãÿ)iýå/Aoo¯¤väÛo¿Ess3àå—_ƼyóÐÑÑ+V`÷îÝðòòœ9s§OŸÆÆ±eË™Ž©ÍÄ-Q:::pâÄ xxx`åÊ•*›%i{ae¥’ãÅèííEss3Ö¬Y#×ó]\\àèèˆÂÂB¤¦¦bÝ `æk IDATºu°´´Tp”„S²d›ááa¶oß>fooÏŒŒŒØêÕ«YFF†ÌYËÙÙ™ñùüIÿ5551Æëííe?úј‡‡355eFFFlÙ²eìÀlttTæc2¦½W ã‰D"VVVƾúê+ÖÒÒ"ý >e³¤¤$622¢ð}«”–]ˆD¢™]5Îðu¹{÷.;räËÎÎfB¡Pªºy}}}8púþ@V3YsÀÜÜÿüç?gu2Ñd-Qbbb”Ö%''¡¡¡Ð›ƒ÷Á粺º:…^5ZZZbçÎ?ÔŽ$'#<<œjGæªäÒRâ–(Ë–-CZZ.]º¤ð–(wîÜÁ½{÷àîî®ÐýåAqq1ÂÃú_qíHBBêëëñÍ7ßÌhÝ¢¾(h9qK”.(PXKÆ­2¨²³³±fÍ¥5K¯;Bµ#ŽŽŽBCCñx@rss‘‘‘‘‘‘Yí³ªª ÎÎÎ033SP”Dnß¾û÷ïÃÍÍMéÇ/SÀãñ¨vDCQ!æÆÆØ±cœ‘’’‚ÚÚZ¹nk âÒ¥KX½zµ¢$ÊÂÅU#ÇÃÊ•+±uëVãôéÓ“v¼ ꉙÀÝÝ{öìA{{»\-Q²²²E« j˜ÊÊJ¸ººb« Š×ñòò‘#Gpùòe\¦@ÛP!“z¸%J^^ÞŒZ¢´¶¶bll ‹/VA”DQ°bŠޣ$²Cvv6bbb¸eRãkG¨vDÍP!2O¿ÔÑÑArr2Z[[%« ªã"VdjEEEð÷÷WZ'E÷s›ìà á%"‡ÀÀ@lÛ¶ 'OžDuu5ÌÍ͹‹ÈàÞ½{hjj‚ŸŸ×¡ÌØÃ^ÄKinP!³b``ìÞ½[i-Qˆrddd ..Nã®Çx)--ÅéÓ§%+£Õ¢Bf¥°°+W®„»»»¤%JJJ :;;¹L£¾¾³Z˜k&&&xâ‰'àííÔÔTªá%"·žž´µµÁÇÇÀZ¢lÚ´ 999³n‰BO(âÂ… ˆˆˆà:…pvvÆÞ½{ÑÓÓƒÔÔTܽ{—ë´%"ÆÎ;7é-sssìØ±NNN’–(D}äææ"$$dNµØ×ÑÑAxx8Ö¯_@€ììlªQJ D.µµµX°`Á´ëEŒo‰rôèQôööª0B2™ÎÎNôôôÀÃÃëP”B\;bkk‹ääd\¿~ëæ4J Df###())AXXØ#ÇŽo‰rúôiäååallLQ’‡1Æ$_œÏeãkG®]»†ôôtÜ¿Ÿë°æ$J Df9992¯aee…„„XXXàСC3Z•’(–¸Å¾¶L·׎„††âĉT;¢”@ˆLîܹƒ¾¾>¹Ö‹˜iK¢xÚÜbŸjG”G9KŽ‘9I| dóæÍ³Ú¸%JGGŽ?¬\¹R-ùÍU™™™ZÝb_\;âåå@===ÄÄÄÀÐÐëÐ4½cÉŒ]ºt ... [ep²–(DñZZZÀ£ûøOíˆRSSQ]]Mµ#³@ „ÌÈàà ªªª~ d|UqYYN:…ÁÁA…C›‰[ìÇÆÆrŠZ׎ôööâÈ‘#T;"'º…EfDÙ« š˜˜`Ë–-hjjBZZüýýáçç§qm6ÔMII –.]J-ö'!®éééAFFlmm&ÓämGW ä‘T¹Ê ““µDQ¾¾>\¿~Zì?‚……âãã±`Áª‘%2-.V¤–(ŠA-ögŽÇãÁÛÛ ¸~ý:ÕŽÌ%2­‹/ÂÇLJ“[ ÔE~ׯ_‡©©),XÀu(ÅÀÀëÖ­£Ú‘¢B¦Ôßßúúzp‡¸%J[[µD™ÑÑQäçç#**ŠëP4ÕŽÌ }[D¦”‘‘¡6·@Äóö»ººpúôi,Z´¡¡¡Z[×0üü|A__ŸëP4ÕŽ<]IݼyFFFX¸p!סH±¶¶¦–(Ó¸{÷.nß¾ ///®C™3ĵ#¾¾¾8zô(ÕŽŒC „L066†ÜÜ\DGGsʤÄ-QvíÚ…ÚÚZ?~œZ¢à?Ö­[§Wsx†à½{÷päÈ\¾|™ë8G·°È……… „סLËÐÐ6l@{{;µDpåÊØÛÛÂëPæ,„……¡··àóùpvvæ:4Nhç;L©··---ðõõå:”³³³Cbb"ø|¾Ö~á9<<Œ²²2„††rŠV˜?>®_¿ŽmÛ¶Á××?þñµr¶%"åܹsy „ÇãaåʕضmJKKqêÔ) q–Êœ?TE­B<üãÑÔÔ„ÊÊJµ½å«L”@ˆD][¬­­§]ePÝ=ü…gUUÕœÿ³½½ƒƒƒpqqá:­dmmŠŠ 8p€ëPTŽ…B]»†ððp®CQñž÷ïߟÓ-QcÈÌÌœó« j‚àà`®CP9ºÞ%€ÜÜ\„¸»COOëPFGGkÖ¬ÁÒ¥K‘‘‘ùóç#22rNý?–••ÁÓÓ¦¦¦\‡B´]tvv¢»»vv\‡¢â–(‹/ÆáÇQWWÇuH 100€ššr ÑR”@´c ëÖ­ã:¥óððÀž={ÐÚÚŠ´´4o‰"«µÓ– ÷è––»|ù2annÎu(*ñpKGGG„„„h\K”¦¦&èééÁÞÞžëPˆ£.Zlhhååå á:•·D177Ç¡C‡ÐØØÈuH3666†ììlÄÄÄp Ñr”@´Øùóç©qŸ¾…ÇãaÙ²eصkjjj4¦%Ê… @Mýç(h©ööv km †ñÄ-QV¯^o¾ù¥¥¥j[UÜÛÛ‹ææf,]º”ëP¡¢D"233UºÊ &°³³ÃÞ½{ÁãñÔ¶%JFFâââ4®S™›èKt-T^^NµS·Dñöö–^‚ëÀÔÕÕÁÊÊ ÖÖÖ\‡BºÑ:T;03Z¢ÜºÅiK”‘‘Í™Ndn ¢e233Cµ3$i‰28ˆ””tuuqG^^BBBæT=ù¬¬,<óÌ3ðôô„‰‰ \]]ñÜsÏ¡££cÂØÑÑQ¼÷Þ{puu…¡¡!\]]±ÿ~ŒMÛÐЀÌ›7?ÿùÏ¥> â/ù Ö¯_{{{˜™™! Ÿþù¤ß2ÆðÇ?þK–,‘‘üýý)h“[·nAGG\‡¢Qttt°ÆÓ›6mBvv6233! UvüÎÎNôôôÀÃÃCeÇ$ªõÆo ''Û¶mÃÁƒ±{÷n=z¸sçŽÔØÄÄDüîw¿ÃÚµkñÉ'Ÿ 22ï¼ó^xá©qŒ1ìØ±‹-ÂðÍ7ßàÓO?•<~ãÆ ¼üòË€_üâøøã±dÉüìg?Ã3Ï<3!Æ·Þz ¿úÕ¯°~ýz|úé§prr˜)++cXÙþý\‡¢r£££ìŸÿü'{ðàÁÔƒV]@šfÜkSWWÇ’’’Xmm­Ò+‰Xrr2ëííUú±äB猄äïKY™ÌÏÍËË›°-77—ñx<öÎ;ïH¶•––2Ç~ûÛßJ}ýõ×™ŽŽ«®®–l«««c‹/f"‘ˆ1ÆØÙ³gYXX˜äñ®®.võêÕ ÇýÉO~Âø|>»~ýºd[kk+Ó××g/¿ü²ÔXºÑÅÅÅðó󃑑סh}ùùù“Þƒž¡¡!\ºtI+Û„“@¿Ô¬»ááa˜ðAÐØØÀݙż¼¼pëÖ-|ñŸví~ýë_Oš¨ÖÞÞRÇ­¬¬„‰‰ ¼¼¼¤ÆRÑT; <Êl‰’™™©Õ´ÝŸþô'…B$$$H¶yzz‚1†‚‚©±¹¹¹€ÖÖVÉ6###|úé§xùå—áé鉖–¼ûî»ÓS(âÏþ3–,Y‚U«VI¶···cÁ‚ÆSÈwíÚ5˜™™ÁÖÖ–ëPæ,qKwwwœ?•••X»ví¬êlZ[[166öÕDëäææâý÷ßÇ®]»)Ù¾qãF899áõ×_‡‘‘QTT„·ß~zzz”ÚÏîÝ»‡ææføùù=òÃÈ /¼€ÚÚZœ:uJj¦æàà &Œ§+9lttR' QEµD‰DÈÊÊBll¬¢$\ …¸}û¶Ô¿‡Ï‘ÚÚZlÛ¶ ~~~øÛßþ&õ˜N:+++ìØ±ÎÎÎxúé§ñ›ßü“~h±¶¶ÆŠ+™<>üðCüýïÇ|€õë×K=fdd$¹}6%9¬  «V­‚¾¾>סh;;;$&&ÊÝåâÅ‹ðññ‰‰‰’"$ÊP__ÿÈ1………°³³ƒ½½½ä¿---’Ç›››±nÝ:XXXàäÉ““žÞÞÞ¨®®ÆåË—‘ŸŸ¶¶6<ûì³èêê’{ªwRR~õ«_ág?ûÞ|óÍ ÛÙÙMZ“¢•·°‡ŪÒÝÝŽŽDDDpŠVâóù“·DyDÝþþ~Ô××#11QE‘EÅsÏ=÷ÈqË—/‡@ Ú¶páB?¼g×­[‡ÑÑQdggOúÃxãgP:u "‘qqq2Ç~âÄ <÷Üsرc‡TÈÃqùå—¨­­•þ"]¦ÉÊN 0ÌÙÚšÕ××sŽÒˆD"väÈv÷î]ÙžHsú§6Ëצ±±‘%%%±K—.IæåO&==µ··ÏêX*Eç cŒ±]»v1___¹ë@XPP377g2=÷Áƒ, €988°þþ~™ž›““ÃŒŒŒØÚµkÙÈÈÈ”ãZZZ˜¾¾>{饗¤¶kÕˆ…… ÄÝË—/ÇöíÛñ·¿ýmÒ/‡4Ymm-,XKKK®C!ÿæä䄽{÷¢¨¨GŽA\\Ü„¦ˆ7oÞ„‘‘‘ä)Ñ 555øî»ïpêÔ)DEEɵ={ö ´´Ï<ó ®\¹‚+W®H355ÅOú###Xµj¾ùæî®@†‡‡Ù¾}û˜½½=322b«W¯fÆÕÔÔ°õë×3SSSfiiÉžzê)ÖÙÙ)5¦±±‘ñx<–““3í1ÇW¢ß¾}›ùûû³E‹±Ë—/Oû©P“ ³¤¤$& e2}šœš_›ÞÞ^vôèQ&$Ÿú„B!KJJbCCC ;ŽJÐ9Ã\\\Øo~ó›YU¢;;;3>Ÿ?é?©±~ø!óññaÆÆÆÌÊÊŠmݺ•UUUÉ|Ìììì)ÉçóÙ{ï½7á9øÃ˜‹‹ 344dË–-cœ%„„¦¯¯ÏÞxã ö·¿ý­Y³†éé鱂‚ɘ––fmmÍÜÝÝÙ§Ÿ~Êþû¿ÿ›YZZ²+VHýllld|>_¦"ÖÞÞβ³³YJJ ëêêRüÿ¨Š;wŽ544È÷dúc05%¼6â–(uuu,77Wª …ÆÐòs¦  €¹»»3Æf×ÊDSqr «¤¤©©©øøãñÚk¯žzê),]ºûöíC~~>`ÿþýDee¥¤àªU«‡¤¤$<ûì³’}29¿_¸p!.\ˆžždddÀÆÆaaaÙõôÎ;èë냛›סððð€‹‹ N:…¬¬,üö·¿å:$"¡Pˆ††\¾|™ëP8ÃÉ4ÞcÇŽAWWWjÖ‚žyæ\¸pARM™žžŽÇ\ª{lll,<<<&ܯ›- ìܹvvv8|øðŒ¦ä©Æ­2¨atuu1<<Œ^xAi-Qˆräåå!88X«§És’@*++ááá1¡è%((Œ1TVV¢­­ wîÜÁÊ•+'‚¾®.b|}a¨._ÜjÙ9“UQÈE‹ð¯QTT$õX§ßæVNÈòåË‘þþ~©/Ò‹ŠŠÀãñ°bÅ ØÛÛÃÆÆ/^œðü’’,_¾\îãÿúÝwðÖ[r=w!€=ÿþ¢ÿPu5¢#"àèè(w,³Q~ñ"¼<<`2®oÿ¬íÞ­¸}Í5 zmª.]úaÂCh茟c àIHÍÉAÀÒ¥Xºt©z¬ñ¢%çL[[„ÆÆpzâ <ýòËxú¡ÇËËË‘ÈEhœáäãóŽ;0::Šÿýßÿ•lARR‚ƒƒaooؾ};¾ÿþ{©ER233Q__;wª>o¾ù&nß¾ 777$%%¡©© ÿøÇ?$ãÞzë-;v QQQxå•Wpÿþ}|ôÑGð÷÷Ÿöv“ªáñÇGkk+¾þúkøøø @%Ÿ 333Ãé-4"»¬¬,DEEÍjÂƒŽŽÂÂÂÐÛÛ‹ŒŒ XYY!<<\#‹_5µØŸg}þõ¯áÕW_Å¡C‡ðÊ+¯`ll 'OžÄš5k$c-Z„œœ¸¹¹áÍ7ßÄG}„ÇçÎS«7‹ƒƒ166†äääI¿·Q¤[·nAGGGªÀ’¨?ñ*ƒ‹/VÈþæÏŸøøx888hdñ«¦¸ÿ>êëëÀu(j‡³n¼úúú8pà<ôeöü½½qúôiE%?>Ÿ   øøø@ ÀÀÀÑÑÑ\ÿAVcccÈÎÎF||¼B÷K”K¼Êà¶mÛ¾oOOO,Y²¹¹¹¸téÖ­[G¥ $îð ß7©ºÿ¡`¦¦¦xòÉ'áíí£G¢ªªJ¡ X•””ÀÏÏO%S˜‰â(ûˆžžž¤øõÔ©S(((PëâWMqãÆ S‹ý)PQggg$&&âþýûHIIAggç¬÷Ù×ׇ7nÀßß_U¯2¨Š[ ââ×yóæáСChjjRú1çªÑÑQäååɽƇ6Ъ¥TMGGkÖ¬ÁÒ¥K!`ff†ÈÈH¹›¯Ñ¥´fˆUÙïMÜÅÃÃYYY¨¬¬ÄÚµké ``ÕªUsnÁ9E¢+077ÇöíÛáââ‚””\½zUæÛZׯ_‡©©é#×I&êåæÍ›044œ´§›²o‰’žžŽ‹/RK”êîîFGG‡Ôºãd"J *äææ†ÄÄDܹsGEww÷Œž7::Šüü|DFF*9B¢HcccÈÍÍåüˆ¸% cL%³5Ýøf‰tµ?=º…¥bºººˆŠŠBww7222°`Á„……AWwê_Eaa!V®\I—Ò¦°° Ÿ‰'>ŸU«VÁÛÛ[©³炚š,\¸–––\‡¢öè „#–––عs',X€ääd444L:®§§mmmðññQq„d6z{{ÑÒÒ___®C‘2~–`jj*ª««:KPÓ £´´TªL‡x<¼½½±{÷n455áØ±c¸wïžäqº”Ö\êþ{£–(“ËÎÎFxxø´wÈЫ¤ôõõ±víZtvvâäÉ“prrBpp0®]»kkkXYYq"‘A]]¬¬¬`mmÍu(Óz¸%Š¥¥%"""Ԫ˃*utt```K–,á:AW jÄÆÆ»wïÆ¼yó””„ï¿ÿááá\‡Ed  QTT¤Q¿7qK”E‹imKÆ­2(#J jF<‡ßÞÞffføþûïiYS ’››‹üïéé‰={ö ¹¹yÂíÔ¹®¼¼îîî˜7oסhJ j¨«« ýýýxî¹çŒãÇ£¸¸˜æð«¹®®.twwÃÃÃëPä&n‰‰“'OjEK”\½z«¹®Ž– ¢fÆqü°zcbb"ôôôpèÐ!´´´p!™Œø÷¶nÝ:®CQˆñ·S“““çtKZA~ôŠ©™+W®`Ñ¢E˜?¾dÇC@@vìØŠŠ |÷Ýw*_ÀŠLïòåËpttœS]pÅ·Swî܉+W®àĉà:,…¢¥f‡ˆFYYB§XêÔØØ›7oÆŠ+pìØ1”——Ó~5044„ŠŠ „„„pŠRLÖe.œwâ¥bbb¸EcQQ#â9èZ­nÑ¢EØ»w/„B!’““ÑÑÑ¡¢ÉdΟ?ˆˆˆY­2¨ æZK”¢¢"øûûÓÒ³@ DMtttàÁƒ3žƒÎçó±zõj<ù䓸páΜ9ƒ¡¡!%GIÖÞÞŽááa8;;sŠJˆ[¢<ùä“(..ÆéÊJ<ïîÝ»‡¦¦&øùùqŠF£¢cÈÌÌÄÚµke~®©©)¶nÝ OOOjM¡b³ù½i:qK/{{<ïÔ½S€¦ ¢*++áêê:«9è...’ÖŠZÀŠL¯¬¬ žžž055å:θØÚj\K”úúzXXXÀÆÆ†ëP4%Ž ¢ººAAA³Þ—¸5ŦM›““@€‘‘DI600€ššr çÄç݆ ••…¬¬,…B®Ãš”P(Ä… Áu(s%Žeee!**J¡sÐÍÍͱcÇ899!%%µµµu{APíÀDóçÏÇÎ;áàà ¶-Qrss¬‘ÔýjmmÅØØ/^¬”ý»»»cÏž=èèèi+2=ª˜ž§§'vïÞ[·n©UKq§OOO®C™3¨/GD"²²²°mÛ6¥GOOOj«… bÍš5Ô®ZNâÚøøx®CQkSu˜æjª³¸SÀ† 89þ\EW )++ƒ··7LLLTr<ñV666HNNƵk×Trܹ¦¸¸˜jd .-QÄÆwx ³G „¨««Sù°<>>>ؽ{7nÞ¼‰¯¿þZmn/h‚¾¾>466R퀌¸n‰244„òòò9Û)€K”@8 ÃÙt}}}ÄÅÅ!<<'OžDaaáœï¸ªX»v-ÕÈéá–(eee*™Ü‘••…ÈÈÈ9ß)€ ”@T¬©© zzz°··ç:ØÚÚb÷îÝ055Å¡C‡ÐDµ#SºÖÑ333ØÚÚrŠÆ·DSzK”¶¶6…B­é j”@Thll 999ˆŽŽæ: ñí…]»vájk+Ž?N X=dttõõˆŒŒä:”9ƒÏç#((è?-QNŸVxK‘H¤µT…ˆ •””ÀÏÏO-¿€544Ćå˱zõj?~%%%´€Õ¿ ÈÕúúú\‡2çHZ¢xy!55—/_VØm-UOTÑF”@T¤¯¯7nÜ€¿¿?סLK¼€•ŽŽ’““ÑÚÚÊuHœêîîFGG¼Ôà–ã\&nÅÓÓÓƒ#GŽàîÝ»³Ž‰ö$ IDATÚ_?'U´ %ó,ÇC`` ¶oߎ²²2|ÿý÷ä:,•¿:¤&üÞ4ŽŽÂÃñaÃdffΪ%Š@ @ll,ýÞ”Œˆ ܸq&&&X°`סÈÄØØ[¶l¿¿?ÒÒÒPQQ¡U-Qjkk±`ÁXZZrŠV·D±··ÇáÇÑÐÐ Óóa``;;;%EHÄ((Ùèè(òòòÅu(rsttÄÞ½{1<<ŒÃ‡kÅV###())AXXסh-///ìÞ½MMM3n‰¢ŽUæ2êg¡d.\@`` ¸eVø|>‚ƒƒáëë @cccDEEiüÿ×Trrr¨å‹x¸%г³3V¯^=eMGaa!`hh¨âHµ](Qoo/ZZZàëëËu( 3oÞ>>011••Õœ~¿©#ºQm[õlþüùˆ‡££#>Œºº:®C’Ëàà .]º„Õ«Ws ™$&&bhhúÓŸàîîÎuHZ‡ˆäççcõêÕýI\سgÚÚÚpôèQôôôp’LΟ?OM÷4 ŸÏÇàà žþy\¼xgΜÁðð0×ai J v÷î]tvvÂËË‹ëP8¡§§‡èèhÄÆÆâìÙ³ÈÍÍÅèè(×a=’¸éž““סtvv¢··Ë—/ÇÖ­[áéé9g'w¨#J 4¾rYÛYYYa×®]°²²Brr2®_¿ÎuHS¢¦{ši²÷›‹‹ Ö…L¾DW ššØÙÙÁ‚ëPÔǃ¯¯/ÜÜÜ““ƒÊÊJÄÅÅ©ÝÔåååðòò¢¦{¦ªª NNN077—Ú®««‹ððpôôô ##666 Óº[ʪ@W 222‚ÒÒR¬Y³†ëPÔŽÖ­[‡ððp|÷Ýwjµ€ÕÀÀjjj¨éž†Dee%‚ƒƒ§caaøøxØÙÙÉÕ…<%¡ÊåG³µµÅž={$Å`\­=ž¸éŸOoMrþüyDEE=rÂÇ“«% ™z×(@gg'îÝ»G•Ë30¾Œ‹õ±ÇS§Õ!ÉÌÉ3áAÜ%""‚–qV J ³D_œËÇÈÈHj}ìÒÒR•.`EM÷4Ól'<ˆ—qž®% ™9J ³tùòe,^¼xÂydfÄëcóx<•.`U\\ µ\’LíâÅ‹³^eðQ-QÈÌQ™…¡¡!”——#$$„ëP4ŸÏÇÊ•+±mÛ6”••áäÉ“J]Àª¯¯7oÞ„ŸŸŸÒŽA¯¿¿õõõ ›ð n‰ˆôôt”••Q툌(ÌBvv6"""¨rYALLL°eË,[¶ iii¨¬¬TÊššîi&e­2(n‰266†ääd­XïFQ(È©££ƒƒƒpqqá:”9gñâÅHLLÄàà >ŒÛ·o+lßׯ_Ǽyó`kk«°}åSö*ƒ|>AAAxòÉ'qáÂj‰2C”@äÀ£Êe%ÓÑÑAHH6oÞŒ‚‚œ={vÖoèÑÑQäççkôêÚH•LMMçüz7ŠD D•••puużyó¸eÎ333ömÛàîîŽ#GŽàÊ•+r¿¡ °jÕ*èëë+8J¢L.\Pù*ƒK–,Abb"º»»‘ššJ-Q¦@ DFƒƒƒ¨®®FPPסhñúîÝ»r½¡{zzÐÞÞooo%EH”¡··ÍÍÍœ¬2¨««‹ˆˆ¬_¿™™™8þ<„B¡ÊãPg”@d”••…¨¨(ª\æ€ø ýØc!33YYY3zC¯Õ¡/Î5‹:üÞn‰ríÚ5ÎbQ7ôWPmmmÃâÅ‹¹E«ÍŸ?;wƒÃŒ°ª««ƒ ¬¬¬T!Q„ºº:µYep|K”›7oâØ±cjÝaZU(̸666–ëPÈ¿yzzbÏž=hmmEZZz{{'ŒAqq1ÂÂÂ8ˆÈK(¢¨¨ááá\‡"E__qqqˆˆˆ@LL ¼¼¼ÐÜÜÌuXœ™q¹wï~úÓŸÂÖÖ¦¦¦ˆ‰‰AEEÅ„q£££xñÅaaaܼySêñŽŽüêW¿BLL ÌÌÌÀçó‘››;é1Å·Šþ·qãF©q999àóùJmK@-¿Õ“žžbbbÓ§O#//Oj«ÜÜ\„††R+o “››‹µý½ÙÚÚ¢±±qqqðòòÂsÏ=§ÒV<êbF „1†7âÈ‘#xùå—ñᇢ³³QQQ.ãþüç?ãäɓؿ?°sçN©Çëêêðᇢ­­ ~~~ÓÞÛäñxpttDrr2:$ù·oß¾IÇ* µüVÖÖÖHHH€……’““qãÆ Éju´V¶féêêBww7<<<¸eZ<ĵk×P\\Œ˜˜®CR=6©©©ŒÇã±ôôtɶÎÎNfaaÁ¥Æ†„„°ŒŒ Æc£££lñâÅìÚµk’ÇûûûYOOcŒ±cÇŽ1>ŸÏrrr&=nTT[¶lÙ#ãËÎÎf|>Ÿ555M;®¬¬Œ`eû÷?rŸã8q‚µ´´Èôtø0×(ÄÐÐ;}ú4{õÕWÙ­[·³Ó9òÚ(œ‚_‘HÄ>,ù¡I<øÃß—²2®CQ™]|ýõ×X¸p!¶nÝ*Ùfmm;wâĉR3a`ccà‡b0 ô÷÷K711ÁüùóeJrccclvÆ”TìÓÜÜ >Ÿ¥ìŸ(žÜÜ\\¸pA+o/h¢Ë—/ÃÑÑQæ¿ê 44”ëTnF ¤¢¢¶áÁƒ¨¯¯—l Á[o½…ëׯãóÏ?G[[¼¼¼ä°¾¾&&&˜7oìììðî»ïJÝãSÆ-,‘H„óçÏk祩7¹Ü´iöìÙ###:tˆZw«9jNªyf´|^{{;"##'l÷¥ikkƒ¯¯/àÝwßELL ÜÝÝadd„äädÈœ››bbb°lÙ2 àØ±cøàƒÐÐЀ””ɸÈÈH¥,SZZŠ¥K—ÂØØXáû&Êóp“Ëåÿ¿½;ŠâLÿþín”3 Àa DPäTDШ94 1±vÝTÊd7V*IU6ÙMÌoS{¹Y+»ÙÄlva$(ºj8DQ¼PÅä”ûýýaÍ”ãŒ0 3ÓÓÌó©âzzºŸéyáé~»ß÷ Á´iÓ——‡Ó§O#!!†0AGE\\MN* Z%hL666`Œ©L½íåå…³gÏâìÙ³H$pvvÖ9¸o¾ùFåw™L†×_ÿþ÷¿±qãFƒŽïììÄ•+W “É ¶¢OšäR1u÷íÛ·±gÏbÖ¬Y4°ÐD444 ··‰„ïPÈ(¨taõ÷÷£±±Qåghh¶¶¶'²ëééÇqjEy,--6¦äñ$ï¼ócÈÉÉÑû¶e¨©£‰á(ÚÅp“\*¦îfŒA.—£¾¾ÞˆMMN*X*W %%%ˆÇq`Œã8\»v žžžhhhP{³b™1kJ{{{ZZZ ¶COM £²²#Nr)‰Ž   äääÀÒÒñññT'J¥pppà;2J* $$$DíÌÞÃÃ!!!(**R{sii)ìììŒú¼¶b܉âI/]üaÓ&¸ýéO*Ë"##ñÚk¯aph…EEHŠŒ¹ÏbJJøŽ@gݽ½8wâÒbcÚZ­Þc`€ºæfìÚ¿3}}ìã£ùªSÀÇÆ Æx\ºzzpñäIÈbbM ²mÛ6”––ª,k6À}X“§Í³¾™™™L$±Ý»w+—)Ƥ¦¦êü ñpã@ÚÛÛYoo¯Úòääd&‰Xeeå¨÷§Í8ââbvúôéQo{\ðX‡ýû÷iÌÇÀÀ+..fr¹œ566ª¯ àccPc<.ãiŒ•òÿ‹Ñê&úªU«ð÷¿ÿëÖ­ÃùóçáêêŠ/¿üCCCøøãG´þïÿþÇ)k;l߾ǎüö·¿ðpê””¤¤¤Àßß<Àž={püøq¼þúë õ~G¢¨•ššª÷mùuëcÊîM]ˆÅbDGGcúôéÈÎÎÆ„ 0þ|ªb@7nÜ€X,¦1VB¦m¦¹ÿ>[¿~=sssclÁ‚ìÔ©S:e-Žã˜H$Rû‹ÅÊu®]»Æ’““ÙÓO?Íìì옃ƒ gß|óNûdlä+Ý»w³;wîè¼}ÁàYöàà Û¾};ëêêÒëvkjjضmÛØ¹sçØÐÐ Qèx\Øwß}Ǻ»»õè dNNNغu+¶nÝ:椥ͨ`‰D‚~øaÌûÒVmm-ìííáááa´}’±+//GPPÞÇêL:¾¾¾())Aff&vt€&ƒ×Ÿ'N`æÌ™ôà‚ÀÑtîx8ƒð±cǨV¶ÀtvvâòåËgIЕŠtçÏSE:=Qtó #J xXsyÖ¬Y:˜'ü0ÖXI“&!)2RY‘îÑ©{Èè™B•A¢fŸ@ÚÚÚpëÖ-åT,Dø«£¨HwóæÍ'°"ë©©££#ÜÝÝù…èÙ'ììl$&&ÒÙ€ ¢°°ñññFß·••”¬ŠŠŠ 2Ûx400€ââbóêa2ëråÊLœ8qLƒ‰ñ)nÀÚØØðƒ¢€Õĉ‘žž®Vy“¨+**œ9sèÑèqÄlÈÀÀJJJ0oÞ<¾C!£ÐÞÞŽëׯ›Ä XŽã0}út¬Y³—.]Â?þˆŽŽ¾Ã2I---hllSibzÌ6 €Î†Æ»­­­±xñbDEEaß¾}(--¥V`ŒÑóqÊ,Èß‚••®˜«W¯b„ &{ö©§ž‚L&ƒµµ5ÒÓÓqóæM¾C2 /^ÄSO=eÙ¹ ¿Ì2ì*-ÅþýûélH@PTTdòcu8ŽChh(V­Z…3gÎ`ÿþýèîîæ;,ÞôõõáäÉ“ˆ‰‰á;bf™@â:ƒ0»’’„‡‡ ¦ËÑÎÎ/¼ðBCC±{÷nTTT€1ÆwXFWPP€˜˜XXh=é³J eeeNßmÈz"D¿Z[[Q__ÀÀ@¾Cµ)S¦@&“appr¹\c]ñª©© íííð÷÷ç;b f•@%p}ÝÜàííwß}—爈6„~V$aΜ9X¾|9Nœ8C‡¡§§‡ï° êÑçdü2«¢ðÙš5¨¬¬ÄO?ý??? ðy‚K—.ÁÕÕ..ŸÊÐÁÁË—/G`` vî܉ªªªqÛ­UUU???8::ò 1 ³L •JQ]] ¹\¹\Ž+W®ðyL?JKK1wî\¾CÑ+‰D™L†ŽŽddd ©©‰ïôêÁƒ8sæ """ø…˜Ù&àá3ÑÑÑHIIA]]²²²h~#rìØ1DEEÁÒÒ’ïPôN,#&&Ï?ÿ< ‘¾¾>¾ÃÒ‹¼¼<ÄÅÅA,ó 10³N VVVHLLÄüùóqèÐ!;vŒºµxvïÞ=Ü»woÜ?-çää„U«VÁÏϸpá‚ »µêëë100___¾C!F@ äŠù&Mš¹\ŽÚÚZ¾C2KæxÖßß2™ MMMعs§ ŸBnn.ù… =œýÅüF(((@ee%.\H7èÂ… ðòòÂĉùŨ,,,0þ|´´´ ;;ˆÌŠŠŠ ÂÞÞžïPˆ‘ÐÈX[[cÑ¢E˜;w.8€’’š¶Ûz{{Q^^Žèèh¾Cá³³3’’’àáá!˜<ºººP]]m°êÄ4Q»»;RRRààà¹\ŽëׯóÒ¸VPP ¨³nCá8*x´µµñÖ)ªCŠDô/Åœ˜÷_©–8ŽCpp0¤R)òóóQYY‰ÄÄDL˜0ïÐÆ•¦¦&ttt`êÔ©|‡b2x477ãàÁƒðññATT”I=áTWWKKKxyyñ 12:]š¶Û@cÈÉÉ1«ç£áææ†””899!==Ýd®„‡†PPP€ ð á%(¦í¶±±Azz:nܸÁwH‚WUU‰DB+ ƒã8̘1ÉÉɸxñ"~üñGtvvòÓ‰šÞ«CþPÑÇq ÁêÕ«qöìYìÛ·÷?f¡êéé¡‘Ë£`ccƒ%K– ** {÷îʼn'x¹nooÇõæf“¨IøA dŒlmmñüóÏ#<<?þø#ÊÊʨ[k”Ž=Šyóæ™T¿¾(®„---!—ËqëÖ-£î?;;‰Ó§ v’K2v”@ôÄËË iii‹Å¼ü1 UCCz{{!‘HøE8ŽCXXV®\‰ÊÊJ£°ª©©££#Üœ ¾/bº(èÇq˜5kV®\‰Ó§O›}5º‘0Æh䲞ØÙÙáÅ_Dhh(²²²pêÔ)ƒM‰200€ââbÄÅÅdûD8(€¢]XXvïÞòòrêÖÒ ²²pppà;”qcÊ”)HKKC?är9îܹ£÷} ª:$1J 4yòdÈd20Æ —ËQ__ÏwH&£»»çÎCxx8ß¡Œ;"‘X¾|9Ž?®×V­­­hhhduH¢”@ L$!<<+V¬@yy9<ˆðïòòòO#— ÈÁÁ/¿ü2‘™™‰³gÏŽ©[‹1†Ÿþ‹-¢ç%£±··ÇK/½„àà`ìÚµ •••‚ž¶{,nݺƼ½½ùÅ,H$¤¥¥¡½½hnnÖi;ÕÕÕððð€³³³ž#$BE Äȼ½½‘––†¾¾>ƒõQ›²¡¡!=z |‡bV-`UPP€œœœQ°êëëCYYbcc %J z™=ªG/MAGG®^½Š™3gò …DEEA*•R)gòD”@@ñ襟Ÿ222páÂÁtkÑsáQLr¹páB#)) /^ÄÞ½{©æ QA D@üýý!“Ép÷î]dffâÞ½{|‡4¬k×®ÁÖÖO=õß¡Qx|’KE«ˆˆìÝ»—jÞ%J caayóæañâÅÈËËCnn.úûûùKÍàà Ïw(dº»»qþüy“\zzzB&“QÍ¢D D &NœˆÕ«WÃÛÛ;vì@uuµIuk?~aaa°¶¶æ;2 ¹¹¹ÃNrùhÍ›ÊÊJ8uŠ&5c”@N*•"55 #Ž(6–¶¶6ܸqÓ§Oç;2 Š+Š)S¦Œ¸®¢€ÕL__³ŸÔœQ,--¯Q|ôèQ^»µ#—鯹p !//oÔ“\z»¸ -- ½½½f99¨¹£2Ž(F{zzbÇŽ¸|ù²Ñc¨©©““ÜÜÜŒ¾o¢»“'Obúôé:Mr)‰‰eË–áøñã8|øð¸šE<%q†ã8<óÌ3HMMÅÍ›7±k×.Ü¿ß(û¦ZÙÂÔÙÙ‰+W® 44tLÛ™0a^~ùeL›6mÜÌ¢@†G dœ²´´DBBâããqøðaªM”§o%%%T+[€rrr˜˜¨·.G???å, ?üðîÞ½«—íÓC dœsuuErr2\\\Ô&ÊÓ§ÖÖVÔ××S­l¹~ý:¬­­õ>VG1‹Â’%KpôèQäææ n22J f€ã8<ûì³*åµµµéu999tã\`QPP`б:>nž‘‘ar›“±¡òbfD1Q^ss3<DEEA,i»—/_†³³3\\\ô)1†ÒÒR„††ÂÆÆÆàû’J¥ðóóCQQªªª°páBLš4Éàû%†EW fÈÍÍ )))prrBzz:®]»¦ó¶úûûqüøqÌ›7OCkkkC]]f̘a´}*7OHHÀ‘#G4°"ÂB ÄLq‡3f`Íš5¸|ù2öìÙƒöîîQo§¨¨°´´4@”ÄPø«ãââ‚ääd¸¹¹A.—ãêÕ«Fè%3gmmçž{111ØêJJJ088¨Õ{[ZZÐÔÔ„iÓ¦8J¢O¦0V‡ã8!%%W¯^ÅîÝ»ÑÞÞÎ[>>|‡IsåÊdeei¶Sâãヴ´4H¥R0ưwï^£Ž¦'ªè „hå¹çžÃÚµkUfmµ³³C]]-Z„ÀÀ@¬[·Žžá7!Œ1,[¶ ¿üå/áîîÎw8z#‰PSSƒ5kÖ 22«W¯¦n-ž˜Õˆ¢‘µâÔ©Sÿüs„††òö”ÙÅ‹À¬’Ç̨#Q.—#--ï0!ãXzz:d2ßa…Y%»wïâÈ‘#H$°µµå;BÈ8òàÁ\¿~Ï=÷\]]ùÇ(Ì*BѺ‰N!D'”@!„è„!„P!„¢J „Bt"ˆÒ×ׇ÷ß“'O†"##‘““£¶Þ¦M›àîîŽgŸ}VmpÓ… ””„©S§ÂÞÞ...ˆŽŽ†\.׸Ïêêj,^¼&L€‹‹ Ö®]‹»w窱SWW‘H„ÂÂBý}X=ëêêÂïÿ{,Y²...‰Dؾ}»ÚzëÖ­ƒH$Rûy|>!|fmiÛ®L½-hÛ¶µýŽ ©© ëÖ­ƒ‡‡ììì0kÖ,deeiÜÿþýû1uêT¸»»kl[***‚H$‚X,FKK‹Êkß}÷ÆøÄb1šššTÖõóóæM›´9<Ä€1ýÕW_Åž={°qãFøûûcÛ¶mXºt)òóó ÈÊÊÂ_|?üçÏŸÇòåËqùòeØØØxøÞÙÙ‰×^{ ^^^èîîÆîÝ»ñÊ+¯ ®®|ðr·oܹ߯s1iÒ$üñDGGþò—¿àܹs(++S©ƒaêµîÞ½‹O?ý¾¾¾ A~~þ×µ±±Á·ß~«2I“““Úz¦þ™µ¥M»B[Q4Z nIDATMÛÖæ;îèè@LL š››ñöÛoÃÃÃ;wîDRRvìØ5kÖ(×½}û6RSS±aÃ8::bÆ ˜9s&fΜ©'c o½õÐÕÕ¥ñ³p‡O?ý‰Deùĉu94ÄИ‰;qâã8ŽýíoS.ëééaþþþ,&&F¹,%%…mݺUù{tt4ËÉÉvÛCCC,$$„ùúúª,ã7˜½½=»uë–rYNNã8Ž}óÍ7Êeׯ_gDZ‚‚]?žÁõõõ±ÆÆFÆcåååŒã8öÝwß©­÷Úk¯± &Œ¸=!|fmhÛ®„Ú4µmm¿ã?ÿùÏL$±üü|•íÍ™3‡yyy±þþ~åò¯¿þ𥦦*ÿàƒ؇~¨q»ÿú׿˜››Û¸q#‰DìÞ½{*¯oÛ¶‰D"VQQ1bŒ‰„}òÉ'#®G Ëä»°²²²`aaõë×+—Y[[ã¿øŽ?®,2ÓÕÕ¥2aœ››Ûˆå09Žƒ···Ze½={öà…^ÀäÉ“•Ë •J±sçN}|,£±´´ÕDzCCCèèè0`D¦AÛv%Զ𤶠ŒüÁÍÍ qqq*ÛKJJÂ;wPPP \®íß]kk+>úè#|ú駯j×ÙÙiVõf„ÊäÈéÓ§!•Jáàà ²|Μ9`ŒáôéÓ€¨¨(üá@uu5öìÙƒ¼¼<„‡‡«m¯»»÷îÝCmm->ÿüs9rï¿ÿ¾òõúúz455aöìÙjï3g*++U–—îàá±qtt„““\\\ðæ›ojìjŸY›v%´¶0RÛV¬3ÒwÜÛÛ«qª;;;0ÆPQQ¡\‰íÛ·#??øâ‹/«öÞ?üžžžøÕ¯~5ìg`Œaþüùptt„–-[†ššµõø>Öä!“¿ÒÐÐOOOµåŠeõõõ€·Þz ?ýô‚‚‚ ‹±eËxyy©½ïwÞÁ×_ àáÙù–-[TÎBT¶ÿø>[ZZÐßßKKKøúúŽ›é˽¼¼ðÞ{ï!,, CCC8|ø0¾üòKTUU!??"ÑÃsñò™µiWŠ©ë…ÒFjÛÚ~ÇÓ¦MCnn.nÞ¼ oooåû ÁqœJiÙ¨¨(Èd2,X°Ç!99+W®T‰«ªª [·nÅáLJýÇogg‡uëÖ!>>ŽŽŽ¨¨¨ÀæÍ›ƒS§N©\ÖÖÖŽí`ýà·mdS§NeÏ?ÿ¼ÚòÚÚZÆqÛ²e‹rÙÐÐ;sæ «¯¯âö.]ºÄrssÙ÷ßÏ–,YÂÄb±Ê=cÇŽ1ŽãØ®]»ÔÞû»ßýމD"ÖÖÖ6ÆOÅáîhòÙgŸ1‘HÄ233 ™ñiÓ®„ÖFjÛšhúŽ«ªª˜••‹ˆˆ`%%%ìêÕ«ì³Ï>c666L$±õë׫m§¦¦†]¼xQã>âââØ²eË”¿üñÇïhRTTÄD"{ã7F\—ŸÉwaÙÚÚ¢··WmyOOòuŽã¬ñŒQA*•bÁ‚HKKÃÿþ÷?$$$àí·ßVÛž¶ûÏ¥k5=Ú*tÚ´+¡µ…‘Ú¶&š¾ã3f ##µµµˆ…¿¿?þñ`Ë–-`Œ©uûÀÔ©SñÌ3Ϩ-ÏÌÌDii)6oÞ¬ÓgЉ‰ADDĸlƒãÉ'OOOe·Ò£Ë4uSƪU«ÐÖÖ†êêjåþÝþãûtvv†¥¥å˜ö)666pqqQ{^<Ц] ½-<Þ¶5yÒw¼bÅ Ô××£¬¬ ¥¥¥¨««ƒŸŸ€‡‰J[ï½÷V¯^ ÔÕÕ¡®®­­­€7nh<¶óöö—mp<0ù{ б *g>¥¥¥à8!!!cÚ¾¢z˜¢ÿ×ËË nnn(//W[·¬¬lÌû’ÎÎNܽ{nnn|‡¢w#µ«ÐÐPÁ·…ÇÛ¶&Ã}ǘ5k–ò÷ììlp‡ÄÄD­c¸yó&vìØ¡qÀnXXBBBF¬hX[[;.Ûà¸ÀwÚHÏëoÞ¼Y¹¬··—°èèh­·ÓÔÔ¤¶¬¿¿Ÿ………1WWW600 \>ܳÿŽ5š'Ýéééajë¿ûî»L$±}ûö+D£Ñ¶] ¡-hÓ¶Çú_¾|™9::ªÜËÐÆ¾}ûÔ~Ö¬YÃD"“Ëå*cMš››ÕÞðàAÆqÛ¸qã¨öKŒC¥’““±wï^¼ýöÛÊÃåååÈËËCLLŒVÛX±bÚÛÛ1oÞ>>(++3én MþùÏâþýû¸}û6¾úê+¬X±¡¡¡€_ÿú×hiiAhh(RRR”ý؇Æ¡C‡°téR8p€Ïð F›v%„¶ MÛ®««Õwüì³ÏbõêÕðññAmm-¾úê+899¡¨¨hØ{ŒÚøä“O°iÓ&477ÃÙÙY¹\*•"44³gφ““***ðßÿþ“'OFYY]…˜"¾3˜6z{{Ù{ï½Ç¼¼¼˜­­-‹ˆˆ`ÙÙÙ£ÚFff&[´hóôôdVVVÌÕÕ•-]º”åææj\ÿÂ… lñâÅÌÁÁ9;;³µk×j<Ó‰DÂD"‘ÆŸºº:vÿþ}¶víZ&•J™ƒƒ³µµe3fÌ`úÓŸT®ÌÆmÛ•©·mÚöh¿ãÔÔTæëëËlllØ”)S؆ 4^!èâIOa}ôÑG,,,ŒMš4‰Y[[3‰DÂÞ|óM“:ÖD• ®@!„˜“ ‹Bˆi¢B!D'”@!„è„!„P!„¢J „BtB „BˆN(BÑ %B!:¡B!D'”@!„è„!„P!„¢J „BtB „BˆN(BÑ %B!:¡B!D'”@!„è„!„P!„¢J „BtB „BˆN(BÑ %B!:¡B!D'”@!„è„!„P!„¢J „BtB „BˆN(BÑ %B!:¡B!D'”@!„è„!„P!„¢J „BtòÿËFÇH*Â…IEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/cube_slice_image.png0000644000077000000240000003226012436367710024661 0ustar tomstaff00000000000000‰PNG  IHDR Xšv‚psBIT|dˆ pHYsaa¨?§i IDATxœíÝ{œÖsÞøñ÷5IM3•L%…´4r'‡nÝëPY”LHŠ„ecïEü¸—Ú,·Ã:,9=VÖ!V¹7Úx86»iÑÖÊaˆ’NTªmÔ÷÷‡»k)Kê3s×óùxÌãa>×çú~¾Ÿóêû½®+—eY Ôô [$#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $³UMŸ°ùZ°`ALš4)JKK£°°°¦OøV¬XqðÁGÓ¦Mkút€Í6™I“&Å!Cjú4€ pï½÷ÆàÁƒkú4€Í6™ÒÒÒˆøò™]vÙe£sâĉQtñÅñùȑѻwïrLkYËZÿ\«ââ‹ãŽøçŸ_€M€›ÌÚÛ®vÙe—èÒ¥ËF9æŒ3¢aD,mÝz£ÓZÖ²Ö?×úÇÿþ³Û&MŋЀdŒ’ñàÿ”²²²ø¼¤$v*+³–µ¬µ ÖZPR±pá&_ Ør àÿ”Î;Gtëѹ³µ¬e­M°Öšý(büøM¾°år Œ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@ ¡éÓ§Gÿþý£M›6QTT%%%Ñ­[·;vlµ¹3f̈C9$6l%%%qÜqÇÅ‚ ªÍûøããàƒŽâââ2dH¬X±b½ëWVVFÇŽ£   ®¾úêjÏ™3'N=õÔhݺu4hÐ JKK㤓NŠÙ³gW™÷‹_ü"Z·n½¿À–n«š>Ø’|ðÁ±lÙ²8þøã£eË–±|ùò7n\{ì±QQQ]tQDD|øá‡±ß~ûE“&MâòË/¥K—ÆUW]o¼ñFL™2%êÖ­›?æI'•••qÕUWŘ1c⢋.Šk®¹fëßpà ù˜ÈårU[¹reì»ï¾ñÉ'ŸÄé§ŸíÚµ‹Y³fÅM7Ý“&MŠ3fDqqq~þןðmH¨W¯^Ñ«W¯*c§Ÿ~zì±Çqë­·ædôèѱbÅŠxíµ×b‡vˆˆˆ½÷Þ;~üãÇ]wÝ?ùÉO"âËhxúé§cÞ¼yQ\\=zôˆ=z¬3@>ùä“9rd\pÁqñÅW{üùçŸ÷Þ{/~ó›ßÄ©§žšoß¾}œp ñÔSOEß¾}óãY–}ÿ_`‹ã,¨a±Ã;T¹ªñðÃGŸ>}òñѳgÏh×®]<øàƒù±åË—G½zõòW&š5kË–-[ç:\pAtèÐ!¼ÎÇëׯÍ›7¯2Þ¢E‹ˆˆ(,,Ü€ÝTå Ô€åË—ÇòåËã³Ï>‹ &ĤI“âÆoŒˆˆ>ú(æÏŸ{î¹gµçíµ×^ñøãç¿ßvÛm£yóæqÉ%—İaÃbÔ¨Q±ï¾ûV{Þ”)Sâž{î‰_|q½çô£ý(öÛo¿¸øâ‹cÛm·víÚÅÛo¿çw^ì½÷Þqàæçær9·`Ĩçž{n4oÞ<Ú¶mçŸ~\ýõqòÉ'GDÄܹs#"bûí·¯ö¼í·ß>-Z•••ù±›o¾9®»îºhÓ¦M<ùä“Õ^\žeYœyæ™1hРèÚµëzÏ)—ËÅO<mÛ¶ž={ÆŽ;îÝ»wV­ZÅSO=ÿüÏÅý×Å»ï¾û½~ €-“+ PÎ9çœ0`@Ì™3'ÆŽgœqFÆÐ¡CóïbU¯^½jÏ[{›ÔŠ+ò·luïÞ=>øàƒxûí·c×]w­ö¼»îº+Þ|óÍxä‘G¾ñœÖ¬YG}t<óÌ31zôè(++‹×^{-®¼òÊ6lX•[¿6”о}ûhß¾}DD 2$>øà>|x 80ÿZ‹üãÕž·råʈ¨þzŒÆÇ{ìQmþ’%KbĈqÞyçE«V­¾ñœyä‘?~|<üðÃqÄGDDÄa‡¥¥¥qüñÇÇO<‡rÈwß,ÀW¨úõë“'OŽ™3gæo½Z{+ÖWÍ;7JJJª¼`ý›\uÕUQYY ˆŠŠŠˆøò-~#"-ZѪU«¨[·n¼ð QPP}úô©rŒÃ;,""^zé¥ ‰'ÆŒ3ªŒ•••EçÎ7èxÀÆ1mÚ´˜>}z•±â¯}îÀÆ&@ X{ÛUAAA´jÕ*š5k¯¾újµyS¦LùN?´Ïž=;/^eeeÕ=ztŒ=:¦M›»í¶[TVVF–e±zõê*³öõ&_|ñÅwÝV^ÑÅGï}^RÑ­Û†pÊ”ˆòò >kYËZ_úü¥—¢áÂ…UÆ6üO:À·#@ ¡ùóçG³fͪŒUVVÆ=÷Ü%%%ùPèׯ_Ü}÷Ýñá‡æßŠ÷©§žŠY³fÅÏ~ö³o½ÞYg•¿j­yóæÅ)§œÆ ‹¾}ûFiiiDDtéÒ%²,‹x †šŸÿ»ßý.""vß}÷ï¼ßµ>92–~í“Ów*+‹ØÐ+ åå&lðùXËZÖúRÑ´iQñõ+ ×\1uêF_ `- |òɱtéÒØo¿ý¢eË–ññÇÇØ±cã­·ÞŠ;ï¼3êÔ©^xa<ôÐCѽ{÷8ûì³céÒ¥ñßÿýß±Ûn»Å°aþõz»ï¾{µpX{+VYYY”åoT>úè¸âŠ+â”SN‰×^{-:vìS§N;î¸#vÝu×j!ó]ôîÝ;ºté²ÁÏ6Î;W»ª:õ¡‡°I HhРAqÇwÄÍ7ß .ŒFE×®]ãÆoŒž={æçí°Ãñì³Ïƹçž\pAÔ«W/úôéW_}õ·~ýÇwÕ Aƒxî¹çbĈñÀÄÂ… £yóæqâ‰'ÆèÑ£c«­üçøþüD 80ø­ævìØ1žxâ‰~¥¥¥±fÍšu>Ö¢E‹¸óÎ;7úškù B $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€À`úôéÑ¿ÿhÓ¦MEIIItëÖ-ÆŽ[mîš5kâæ›oŽÎ;Gƒ ¢iӦѳgÏxýõ×ós***¢   ž{î¹”Û6[Õô ›Þ|Ë–-‹ã?>Z¶lË—/qãÆÅ±ÇqÑEåçžp qß}÷ÅСC㬳ΊeË–Å´iÓbþüù5¸`s!@` ЫW¯èÕ«W•±ÓO?=öØc¸õÖ[óòàƒÆ=÷Ü¿ÿýï£oß¾5qªÀfÎ-X°…*((ˆvØ!êÖ­›»æšk¢k׮ѷoßX³fM|þùç5x†ÀæH€Àdùòå±`Á‚xçwâÚk¯I“&ÅyçK–,‰W_}5öÜsϸð £qãÆÑ°aÃhÓ¦M<ôÐCÕŽ•ËåRŸ>°p lAÎ=÷ܸõÖ[#"b«­¶Šë¯¿>N>ù䈈xçw"˲¸ÿþû£nݺqÕUWE£Fâºë®‹AƒE£FâàƒŽˆˆÒÒÒX½zuíø¿K€ÀäœsΉÄœ9sbìØ±qÆgDaaa :4–-[‹-ŠW^y%öÚk¯ˆˆ(//Ö­[ǨQ£ò°¡lAÚ·oíÛ·ˆˆ!C†ÄÁÇDaaaDD´nÝ:EEEѧOŸ;vl¬Y³& ¾û›'NŒ3fT+++‹Î;Ýß×´iÓbúôéUÆŠgÏ®¡³¶¶`ýúõ‹É“'Çßÿþ÷hÙ²eDDl·ÝvÕæ5oÞ<*++ãóÏ?† ~çuŠ.¾8¾þ¬ÏKJ"ºuÛÓŽ˜2%¢¼|Þk-kY+ïó—^І Vûb£¯P•-ØŠ+"âËwÄjÙ²el·ÝvñÑGU›7gΜ(,,Ü øˆˆø|äÈXÚºu•±ÊÊ"6ô HyyÄ„ ö\kYËZyEÓ¦EÅׯ€\sMÄÔ©}-€µlæÏŸÍš5«2VYY÷ÜsO”””DYYYDD 4(®»îºxòÉ'ãÀŒˆˆ Äøñã£G¼~ïÞ½£K—.¾`“èܹsµ[!§>ô6)[€“O>9–.]ûí·_´lÙ2>þøã;vl¼õÖ[qçwF:u""bĈñàƒF¿~ýâÜsÏFŘ1cbõêÕ1zôèÞ°9 °4hPÜqÇqóÍ7ÇÂ… £Q£Fѵk׸ñÆ£gÏžùyÍ›7^x!þó?ÿ3®½öÚ¨¬¬ŒnݺÅ}÷Ý:uªÁ› [€ÆÀ¿ÕÜÖ­[ÇÃ?¼‰ÏØRù$t $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2¶¯¾újœqÆQVVÅÅÅñƒü ³fÍZïs*++£cÇŽQPPW_}u•Ç***¢   ž{î¹M}êÀff«š>`Ó»âŠ+âå—_ŽþýûÇn»ísçÎo¼1ºt鯼òJ”••U{Î 7ܳgÏŽˆˆ\.—ú”€Í”-ÀÏ~ö³Øk¯½b«­þùG~àÀÑ©S§øÕ¯~¿ýío«Ìÿä“ObäÈ‘qÁÄÅ_œút€Í˜[°` °Ï>ûT‰ˆˆþð‡Ñ±cǘ9sfµù\pAtèÐ!œê€-„+ °…ʲ,æÍ›:uª2>eÊ”¸çž{âÅ_üÆç»- Ø®€ÀjìØ±1gΜ8p`~,˲8óÌ3cРAѵk×õ>·´´4V¯^ûí·_ŠS6#®€ÀhæÌ™qúé§G·nÝbèСùñ»îº+Þ|óÍxä‘Gjðì€Í™+ °…ùøããÐC&MšÄ¸qãò·R-Y²$FŒçw^´jÕª†ÏØ\¹[Ï>û,zõêK–,‰çŸ>Z´h‘쪫®ŠÊÊÊ0`@TTTDDć~‹-ŠŠŠŠhÕªUÔ­[÷;¯;qâĘ1cF•±²²²èܹó†oøÞ¦M›Ó§O¯2Vü¿o¿ °©ä²,Ëjú$€MoåÊ•qÐAÅk¯½O>ùdµ×x 6,î¾ûîo<Æ´iÓb·ÝvûÖkN:5öØc¸&"Ú|í±’’’ønݾõ±ª˜2%bï½7ì¹Ö²–µò^|é¥X¸pa•±/"¢_Düå/‰.]ºlô5\-ÀêÕ«càÀñ§?ý)ƿΘŸuÖYqÄGT›7o^œrÊ)1lذèÛ·o”––nÐúŸK[·®2¶SYYĆ^)/˜0aÞk-kY+¯hÚ´¨øúk®‰˜:u£¯°–-ÀÏ~ö³xì±Çâ°Ã‹ Ľ÷Þ[åñ!C†Äî»ï»ï¾{•ñµ·b•••Eyyù¯ß»wo“ µPçÎ«Ý 9õ¡‡°I Øüõ¯\.=öX<öØcUËår1dÈ:3`K#@` ðôÓOoÐóJKKcÍš5ùl€-™·á’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€Éàÿ”iӦŋ/½Ó¦M³–µ¬µ Özþ…6ù:À–M€ÿ§LŸ>=.\Ó§O·–µ¬µ ÖZ°pá&_ز  $#@€d¶ªé6_+V¬ˆˆˆ3fl´c¾÷Þ{QŸ¿÷^L:u£×ZÖ²Ö—kÍýß^ûç`cËeY–ÕôI›§±cÇÆ!Cjú4€ pï½÷ÆàÁƒkú4€Í6™ ĤI“¢´´4 kút€oaÅŠQQQ|p4mÚ´¦OØ  /B’ @2HF€É lr¯¾újœqÆQVVÅÅÅñƒü ³fͪ2/˲3fLtéÒ%7nM›68 &Nœ¸ÎãÞqDZË.»Daaa´k×.n¼ñÆuÎûôÓOãä“OŽfÍšEqqqôèÑ#^{íµï½¯éÓ§Gÿþý£M›6QTT%%%Ñ­[·;vlµ¹kÖ¬‰›o¾9:wî 4ˆ¦M›FÏž=ãõ×_¯uûúº_þò—QPP:uZïœÊÊÊèØ±cÄÕW_½Î95½¯gžy& Öù5eÊ”ˆøò÷à]wÝååå±ÓN;EqqqtêÔ)~ùË_Æ?þñZ¹¯µ¦NåååQRREEEÑ©S§¸á†ªÌ™1cFrÈ!ѰaÃ())‰ãŽ;.,XP«÷l†2€M¬_¿~YË–-³³Ï>;»ãŽ;²Q£Fe-Z´ÈŠ‹‹³7ß|3?oĈY.—Ë;ì°ì–[nÉ~ýë_g;wÎr¹\öÈ#T9æ˜1c²\.—õïß?»ýöÛ³ãŽ;.ËårÙW\QeÞêÕ«³nݺeÅÅÅÙe—]–ýæ7¿ÉÊÊʲFe³fÍú^ûš8qbvÈ!‡d—]vYvûí·g×_}¶ß~ûe¹\.5jT•¹C‡ÍêÖ­›tÒIÙwÜ‘]wÝuÙ°aò'Ÿ|²Öíë«fÏž5hÐ +..Î:uê´ÞyW_}uV\\œår¹ìꫯ®öxmØ×ÓO?år¹løðáÙØ±c«|-X° ˲,[ºti–Ëå²nݺe£GÎn¿ýöì„NÈêÔ©“uïÞ½Vî+˲lÒ¤IÙÖ[oí³Ï>Ù¯ýëìöÛoÏ.¸à‚ìüóÏÏÏ™={vÖ´iÓ¬mÛ¶Ù 7Ü=:ÛvÛm³Î;g«V­ª•û6OØä^z饬²²²ÊجY³²úõëgC† ɵlÙ2ëÚµk•yK–,É6l˜õíÛ7?¶|ùò¬¤¤$;ì°ÃªÌ2dHV\\œ-^¼8?öÀd¹\.{øá‡ócóçÏÏš4i’sÌ1e_µzõê¬sçÎÙN;íTí}ôÑo|nmÜ×À³<0;à€²]wÝusæÍ›—m³Í6Ù¨Q£Ö µe_kä«ÇþºU«Ve/¿ürµñË.»,ËårU‚±¶ìë³Ï>˶Ûn»¬_¿~ß8ïÔSOÍŠŠŠ²Ù³gçÇž|òÉ,—Ëe·Þzk­Û°ù @éÒ¥K¶çž{æ¿oÓ¦MÖ§OŸjóZ´h‘}ôÑùïÿð‡?d¹\.{üñÇ«Ì{ùå—³\.—Ý{ï½ù±þýûgÛo¿}µcžrÊ)YQQQµ¿ùÝúô铵iÓ&ÿ}×®]³ÿ÷ϲìË@Y¶lÙ:ŸWÛöõì³Ïf[mµUöæ›ofûï¿ÿz¡0ßcFIDAT¯€ 6,û÷ÿ÷ì½÷Þ[g€Ô–}­ qãÆeK–,©Åßäõ×_Ïr¹\vã7æÇj˾n¾ùæ,—Ëe3gÎ̲,Ë–-[–­^½ºÚ¼æÍ›g¬6Þ¾}ûìÀ¬uû6_^Ôˆ,ËbÞ¼yÑ´iÓüØ\“&MŠo¼1***bæÌ™qúé§ÇÒ¥Kãì³ÏÎÏ[{ùž{îYå˜]ºt‰‚‚‚˜6mZ•¹]ºt©¶þ^{íË—/·Þzë{ïeùòå±`Á‚xçwâÚk¯I“&ÅyçK–,‰W_}5öÜsϸð £qãÆÑ°aÃhÓ¦M<ôÐCUŽS›öµzõê8óÌ3ã'?ùI”••­wÞ”)Sâž{î‰_ÿú×ëS›ö1lذhܸqF=â/ùË¿|ÎÇQå÷kmÙדO>5ŠÙ³gGûöí£aÆѸqã8í´Óò¯[ùè£bþüùÕÎuí9|õ5µe_ÀæK€5bìØ±1gΜ8p`~줓NŠ[n¹%Î=÷ÜØyç£cÇŽñÐCÅSO=]»vÍÏ›;wnÔ©S§Êƒ[o½u”””Äœ9sªÌÝ~ûí«­¿vì«s7Ô¹çžÍ›7¶mÛÆùçŸ×_}œ|òÉñÎ;ïD–eqÿý÷Ç]wÝW]uUŒ;6š5kƒ ŠI“&ÕÊ}3&>øàƒ9räzçdYgžyf 4¨Ê¿Ÿ¯«-ûªW¯^uÔQqýõ×Ç„ bÔ¨QñÆoľûî[å‡êu¹òÊ+£qãÆÑ«W¯Z·¯Y³fÅ_|‡~xôêÕ+yä‘8á„b̘11lذüú_]ïëç°hÑ¢¨¬¬¬Uû6_[Õô [žµW6ºuëC‡Í?ôÐCqòÉ'Gÿþýã¨£ŽŠ%K–ĵ×^GqD<ÿüóѦM›ˆˆX±bEl½õÖëûìûì³Oþû>}úÄQG»í¶[Œ1"üñu>oôèÑñÔSOÅÍ7ß5Ê×–}-[¶,–/_§žzjþJÔᇫV­Š[n¹%.»ì²üñÿÕ9Ô­[·Öì Ø|¹$õñÇÇ¡‡Mš4‰qãÆE.—‹ˆ/9í´Ó¢wïÞqß}÷Å‘GÇ|<óÌ3±jÕª¸è¢‹òÇ(,,ŒU«V­óø+W®ŒÂÂÂ*s×õö©+W®Ì?þ}µoß>zôèC† ‰Ç}bÊ”)±fÍšZµ¯ÿ÷ÿþ_4mÚ4Î<óÌõÎY²dIŒ1"Î;ï¼hÕªÕ7¯¶ìk]Ú´i}ûö§Ÿ~:²,«öø<_|qœtÒIqÊ)§Ty¬¶ìkís>úè*ãk¿å•Wòs¾Í9Ô–}›/$óÙgŸE¯^½bÉ’%ñÄOD‹-òÍœ93.\åååUžÓ¤I“øÿøxñÅócÛo¿}¬^½ºÚç¬Zµ*-Z-[¶¬2w]·¬½%å«s7–~ýúÅgŸ}ÿûßóÇßn»íªÍkÞ¼yTVVÆçŸž?ךÞ׬Y³â¶Ûn‹3Ï<3>üð訨ˆŠŠŠX¹re¬Zµ*ÞÿýX´hQ\uÕUQYY ÈÏùðÃ#âË«=ù[zjþ¾É;ì«V­Êÿ{XkòäÉqÜqÇEŸ>}b̘1ÕžW[öµ¾ßcÍ›7ˆˆÅ‹çç¬]ïëçPRRuëÖÍŸkmذù @+W®ŒÃ;,Þ~ûíøŸÿùŸèСC•Ç×þ°ºzõêjÏ­¬¬¬2¾ûî»GÄ—pøUþóŸcÍš5ѹsçüXçÎcêÔ©ÕþvûOúSE»ví¾ßÆÖaím'ѲeËØn»íâ£>ª6oΜ9QXX 6ŒˆÚ±¯>ú(Ö¬YguVì¼óÎù¯)S¦Ä[o½­[·Ž‘#GÆìÙ³cñâÅQVV–Ÿ³ß~ûEÄ—·,í¼óÎ1cÆŒü¹Öô¾¾É»ï¾………Q\\\e½#Ž8"öÞ{ïxðÁ£  úÿ.kÿ¯ˆ¾X|m®µ6 š5k-[¶ŒfÍšU;׈/ßHà«çZ[ölÆjìý·€-Æ_|‘•——g[o½uµ·ö\kÙ²eYýúõ«}ØÛìÙ³³âââ¬wïÞù±+V|çÏ)7n\~lþüùÙ6ÛlSå­}7Ä'Ÿ|RmlÕªUY—.]²¦M›f_|ñE–eY6|øð,—Ëe“'O®r5ªò¶Ãµa_ ,È}ôÑlüøñù¯G}4Ûu×]³ÒÒÒlüøñÙo¼‘M:µÊœñãÇg·Þzk–Ëå²N8!?~|öÙgŸÕš}eÙºÿ}M›6-«[·nvøá‡çÇþö·¿e%%%Y§N²O?ýt½Ç«-ûzíµ×²\.— <¸ÊøÑGm½õÖÙܹs³,ûòs@4h°ÎϹå–[jݾ€Í—6¹³Ï>;ËårYyyyöÛßþ¶Ú×Zk? ½GùOjÞa‡²ºuëfÏ?ÿ|•cÞtÓMùOj¾í¶ÛòŸÔ|ùå—W™·zõêlŸ}öÉ6lX哚7nœ½õÖ[ßk_‡~xÖ³gÏìÒK/Ín»í¶läÈ‘Y‡²‚‚‚ìî»ïÎÏ›7o^Ö²eˬQ£FÙ/~ñ‹ìšk®ÉÚµk—e¯¿þz­Û׺ì¿ÿþëý µÖ÷9 YV;öÕ½{÷ìÐCÍF•Ýzë­Ùðáó dMš4Ɇƒ%K²wÜ1«S§NvÅWTû½úõ)¬ ûʲ,;ñij\.— 80ûÍo~“õïß?ËårÙE]”Ÿ³ö“ÐøÃæÿ|5iÒ$û·û·jŸ×Q[ölž°ÉpÀYAAA–Ëåª}T™{Ýu×eeeeY½zõ²† f={öÌžyæ™u÷¶ÛnË:tèÕ«W/kÛ¶mvÝu×­sÞâÅ‹³“N:)kÚ´iVTT”uïÞ=ûË_þò½÷uÿý÷g?þñ³-ZduëÖÍJJJ²Þ½{Wù´ìµÞ}÷ÝìÈ#Ì7nœ5hÐ ;ðÀ³?ÿùϵr_ërÀ¬÷ƒ×ú¦É²šß×õ×_ŸuíÚ5+))ÉêÖ­›µjÕ*;î¸ã²wÞy§ÚÖ÷ûuذaµn_Y–e•••Ù¥—^š•––f[o½uÖ®]»užÇôéÓ³ƒ>8+**ʶÝvÛìØc]ç•¡Ú²/`ó”˲u¼íÀ&àEè@2HF€É $#@€dŒ’ @2HF€É€ÍDAAA\z饛äØQPPwß}÷&9>[XyyyŲeËÖ;gðàÁQ¯^½X¼xñw:v.—û¾§÷Çþêñ'Nœ¸É‚gcxã7¢   þüç?×ô©ð ±!C†ÄŠ+â÷¿ÿý:_¾|yŒ?>zõêMš4I|vëVZZ+V¬ˆ!C†äÇj{€üáˆí¶Û.öÜsÏš>¾B€$V^^ 6Œûî»o?>–/_ƒN|fßlë­·Ž‚‚ªÿÛØ”W\¾¯‰'F¯^½jú4øXýúõãÈ#Œ§žz*æÏŸ_íñûî»/5jåååñé§ŸÆðáÃcÇwŒúõëGÛ¶mãÊ+¯Œ,ËþåZ¯½öZôêÕ+7n 6Œ<0þô§?U›÷é§ŸÆ9眥¥¥Q¿~ýØqÇcèС±páˆøçk@î¹çžˆˆ8þøã㦛nŠ,Ë¢   ¢N:ñåÕ’Ã?¼Ú+W®ŒÆÇ©§žúç\PPgžyf<ðÀѱcÇhРAtëÖ-Þx㈈3fLüð‡?ŒÂÂÂèÑ£G¼ÿþûëÜÏË/¿‡zh~ìþûï=öØ#5j7ŽÝvÛ-®¿þúùkÀƵUMŸÀ–hðàÁq÷Ýwǃ>§Ÿ~z~|Ñ¢E1iÒ¤ük@–/_ûï¿Ì;7N9唨i§âÅ_Œ#FÄܹsãÚk¯]ïÓ§O}÷Ý7¶Ùf›8ÿüóc«­¶Š[n¹%8à€xöÙgcï½÷Žˆˆe˖žûî3gÎŒO<1ºtéóçÏÇ{,>úè£())©vìŸþô§1wîܘºÞó}ï½÷²\.—Ý}÷Ýù±ÓO?=ËårÕæ¾õÖ[Y.—ËÆŒSe¼¼¼<Ûyç×»ÆW÷QXX˜½ÿþûù±[o½5ËårÙöÛoŸ-[¶,?~á…f¹\®ÊÜ,˲c=6ëÞ½{þû³Ï>;Ûf›m²5kÖüËõØ´Ü‚P bРAñòË/W¹…è¾ûî‹-ZDÏž=#"⡇ŠýöÛ/¶Ùf›X°`Aþ«gÏž±zõêxî¹çÖyüÕ«WÇÿøÇ8üðã´´4?Þ¢E‹8æ˜câ…^È¿ ×Ã?;w޾}ûn”½µmÛ6ºvícÇŽÍ-Z´(üñoýº–ž={ÆN;í”ÿ~íÕš£Ž:*ŠŠŠª¿ûî»ù±5kÖÄOûì3fLtèÐ!vØa‡õÿÈ#Œ3Ï<3žxâ‰8î¸ãªÅSݺucàÀßúÅçâ«·‚Mœ81zôèõêÕ«2çØcúõëÇM7ݧŸ~züö·¿£>:üñMv^¬[.˾ÅGéÀ8çœsâÎ;ïŒ?þ8êׯ¿I×úâ‹/¢iÓ¦ñ«_ý*~úÓŸnÒµØp®€°I¬\¹2î½÷Þèׯß&ˆ/ߊ÷ÜsÏ#Ž8b“¯À†s€jþüù1yòä7n\L˜0!¦NºÞב°åñ"t6ªéÓ§Ç!Cb»í¶‹ë¯¿^|P…+ @2^$#@€dŒ’ @2HF€É ™ÿ»\iðLåôIEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/cube_slice_image_lonlat.png0000644000077000000240000003735512443671565026250 0ustar tomstaff00000000000000‰PNG  IHDR Xšv‚psBIT|dˆ pHYsaa¨?§i IDATxœíÝ}u}?üÏ9»›ìfÎ&›P²!L „£Rñ‡ð³Ô$ʘÆxƒíh#ˆñ¡ ·8EZbÕŠ"ZÚHÅN)Ò©T åÁ»¶„(| Ú$BºMv“Íî¹ÿˆYX7d³ßë:×Ù×k&3rö:»ŸÄÞ×çûPªV«ÕÈ@9C2#€™@€Ì @f 3ÈŒdF2#€™@€Ì @f 3ÈŒdF2#€™@€Ì @f 3ÈŒdF2#€™@€Ì @f 3ÈŒdF2#€™@€Ì @f 3ÈŒdF2#€™@€Ì @f 3ÈŒdF2#€™@€Ì @f 3ÈŒdF2Ó˜wL\›7oŽÛo¿=?üðhiiÉ»ŠrÙóÆ—qE*õ>¶úúúâ©§žŠE‹ÅôéÓó.‡ H!7·ß~{,]º4ï2`Búæ7¿ïyÏ{ò.ƒ H!7‡~xDìþ<úè£ó-†dÞýîŸÇ¡‡þm|á Wä] uä _øç¸ë®©ñ/ÿrjÞ¥PgÞýî_Æ¡‡^_øÂ•y—’Ìc=K—.þ= Y@ÈÍžiWG}tÌŸ??çjHeÖ¬)10Pñÿ1ãjÁ‚'ãŽ;ÚŒ+ÆÝa‡µFÿÄøÌ2ý™¼ÔïG &tu5ÅóÏå]uæˆ#¦Eÿ¤¼Ë rȤøßÿõ™) @R¿ó;-ÑÛ룆ñ5gÎïÄÎ y—Aš9³5z{-HÉ, ©Ù³+qüñoÌ» êÌG6ï!…9s:ã¸ã|fAJKIÍœÙË–­È» êLGGGüñy—A:äI±lÙy—uM’ªT"ž>ï*¨GÕjÞP*•ˆžž¼«€ú&€IutD¼ðBÞUìM =Hª£Ã/sÒhlŒÌ» êé @R[·æ]õ¨½]wñ'€@z”)X¤âF‘¬ô )S°HÅØ"…öv][HM’ji‰èëË» êQ¥¢»Æø+—í°© @R¥’_æ¤a @1 @r¥RÞP€b@€ät@HÁ€b@€ät@HÁR)—1) @&tAo©8¿Ò@€äZ[#z{ó®‚zc ©8 Ò@€ä @&ö±áëJ¥R”LÄæeT*: ¤±§»ÖÙ™w%Ô¿Ò`| 5äÌ3ÏŒ3Ïó™˜={v|ÿûßñžîîîøøÇ?óçÏ¡¡¡¸í¶Ûâ+_ùJüä'?‰»ï¾;ÊåòðÏmhhˆéÓ§xSSStuuņ †_»ì²Ëâ²Ë.§ ê‘E褢B* ¿ùõ ¤]tÑEqÎ9çĆ â[ßúV¬X±"¦L™Ë–-‹¾¾¾ˆˆ˜û숛þˆˆ]»vÅ7¾ñ˜6mZ{ì±qöÙgÇõ×_ëׯÞŠ÷Î;ïŒ'žx"V®\¹ß?oÇŽ100mmm#^ÿó?ÿóˆˆg’œvÚi1mÚ´¸æškFk®¹&Z[[ãmo{Ûýe_âäûî‹ùóçùýÓgÞqËwò®‚zÓ󫈫?ñå/ç] õæž¿˜6-âïÈ»’sÜoþ¼ÔŒˆø­]-!KH ù“?ù“xá…âMozSÌš5+ž~úé¸á†â§?ýi¬^½:""â’K.‰›nº)N=õÔ¸ð cëÖ­±jÕª8á„bùòåûýóž~úé8ñÄãÜsÏßû½ß‹ˆˆÛn»-n½õÖxë[ßgõâãéæææ¸üòËcÅŠ±dÉ’X´hQÜ{ï½ñ­o}+þâ/þ":úÔÓdHÅØ‚ñ#€Ôw¿ûÝqÝu×ÅW¿úÕxî¹ç¢££#.\W_}uœvÚiÃ×vØaqÏ=÷ÄG>ò‘¸øâ‹cÒ¤I±xñâXµjÕ­ÿèì쌷¿ýíqÇwÄõ×_ƒƒƒqÔQGÅ•W^¹×NÊ>ð˜4iR|îsŸ‹[n¹%fÏž_øÂâCúиüýV{»C.I£R‰øŸÿÉ» ¨H Y²dÉð¶·¯ä裎[o½õ ~^¥R‰o|ãôžóÎ;/Î;#ú¹Ñظ{!z£O!ÆQ¹az;)è€Àø±  »E"€Àø@€\ ¤R*å]õHñ#€¹pb5P$>³`¼ @.t@H©ZÍ»êÍäÉýýyWõArÑÑa·"Òhi‰øÍù­Ô È…)X¤b®>@m@€\耊B*68€ñ!€¹°„TŒ-€Ú&€¹ð”šTŒ-R™<9bÇŽ¼«€â@€\˜‚E*©[0> ¡“бE*•JDOOÞU@ñ @.ÚÛu@H£R±„4t@`| @.Ì¥&RÑñ!€PWt@HEƇ@]q“H*ÆŒ€º"€Š±ãC ®Lž±sgÞUP›r9bp0ï*¨GÕjÞPLÁ‚ñ!€¹ioèíÍ» êQ©”wÔ#»Eb‹g¿Ì"ijŠØµ+ï* ø 7NC'ÆF7Фa}<È©tt˜ÞP« 7nIE¸¨]„TìVDJ¦aÁÁ@€ÜxJM*Æ©L™±}{ÞU@± @n,B'[<“ŠÃáà @n<¥&S°HÅØ‚ƒ'€¹Ñ!R@àà @nü"'Ý5R1 žäfòäˆ;ò®‚z¤B*œÀÁ@€Ü”JyW@½Ò!•J%¢§'ï* Ø WöÓ'O©IÅØ‚ƒ'€PwÚÚ"z{ó®‚z$€ÀÁ@¨;å²îi pð W¥RÄÐPÞUì»`ÁÁ@€\µµElÛ–wÔ#Rho·Ã,ȕ݊€"ihе…ƒ%€¹r:©”Jº µHreA'©L™bzi¶pp W: ¤â4t€Ú$€¹²„Tt×HÅî}pp W: ¤¢B*v#€¹Ò!c‹TœGrå&‘TLÁ"c ŽäÊ,Réè0‹488+7‰¤â&‘T*•ˆžž¼«€â@€\ ¤bl‘Šp Grå°8Rq“H*ÆÈU©”wÔ+7‰¤ÒÙi  ÈB vX#áŽä®ZÍ»êÑäÉ;wæ]õHƒ#€¹ÓŠÄA„pp &è‚EÑÖÑÛ›wP\»)S"¶oÏ» €ýS*yhCrç4tR1½ ö @îìVD*yWA=Ò±@€Ü逊ÓÐjäN„Tl—J*årÄà`ÞU@1 @ît@HE„T|nÁØ @î*7‰¤¡B*ÆŒäÎ,R1¶HE±@€Ü™Ê@*ºk¤"€ÀØ @î<¥&7‰¤R©Dôôä]“äÎBaRÑ!•ÎNáÆJr'€Šî©è®ÁØ @îZ[#z{ó®‚zä&‘TLÁ‚±@€Ü•ËÕjÞUPLÁ"•ÎNc ÆJ nµ¶Úa4t@`ìêVÙo91½ÆÎG3Àš2%bûö¼«€b@P©”wP\P&OŽØ±#ï*öŸÍ3`l &8¯”Ü(Ô¨ v+"ÖÖˆmÛò®‚zdŒÔR±[©44DìÚ•wP<P::êEÆ©8èÆFj‚›DRÑ!c ÆFj‚)X¤bl‘ŠÓÐal &X„N*¦ÉŠŒÔO©IÅM"©è€ÀØ @M¨Tt@HC„TŒ-¨ : ¤bl‘Jg§±c!€5ÁRñ”šTL@€šÐÞî&‘4t@HŨ CCyWA=ò”šTŒ-€º6iRÄÎyWA=@`l€1hnŽèëË» (` J¥¼+€b@¨{nIÅØ‚'€5£±Ñ\}¨wP3œB*yW@„ÔÆ‘г@H¥©Iç”Ô RnIE¸…'€5££ÃM"i[¤ÒÙ)€À@€šáI"©80ŽTŒ-8pP3ÚÛ=¥& S°HE'€5C„TÜ$’Š)Xpà fX„N*Ö€Šp Nj†©¸I$•J%¢§'ï* X f耊pK*Â-8¨¦ÉŠ›DR1¶àÀ @Íð”šTŒ-R±œÂ(W\qE”Ëå8þøãG}íñÇ3Î8#ÚÛÛ£««+–-[›7oqͺuë¢\.ǽ÷Þ›UÉÔ‰I“"víÊ» êQ[[DooÞUPt@àÀ5æ]µeýúõñ—ù—ÑÖֶׯrÊ)1uêÔ¸òÊ+cëÖ­qÕUWÅ#<kÖ¬‰ÆÆ‡S©TʲlêHµšwÔ£rÙØ"I“"vîÌ» („V®\oxÃb×®]ñÜsÏøÚW\}}}ñÐCŬY³""ⵯ}m¼å-o‰Õ«WÇùçŸ?|mÕozÆHv€úf Ãî½÷Þ¸ùæ›ã _øÂ^¿~óÍ7ÇâÅ‹‡ÃGDÄé§ŸsçÎo¼1«2ÆD¸¨ 144\pA¼ÿýïc=vÔ×7lØ›6mŠ“N:iÔ×.\>øàˆ×LÁ`¢Ðô‡c qÍ5×į~õ«ø÷ÿ÷½~}ãÆ1sæÌQ_›9sflÙ²%¢©©)æÌ™ƒƒƒIë¥~•˃ƒ yWB=ªVuBÆbË–-qÙe—ŧ>õ©˜6mÚ^¯éë니ˆÉ“'úZssóˆkà`´·;Œ4Z[#¶mË» êÑäÉýýyWÅ!€Ÿüä'£««+V¬X±ÏkZZZ""bÇŽ£¾Öÿ›OÝ=×ÀÁp:©T*º$ [ñÂ1k‚ûÙÏ~_ÿú×ã‹_üb¬_¿>"vï`Õßß±nݺèèèžzµg*ÖKmܸ1¦M›MMM™ÖN}Ús`ÜìÙyWB½Ù3¶º»ó®„z³'€üÎïä] ƒ2Á­_¿>ªÕj\pÁñ¡}hÔ×_õªWÅ…^õW3f̈µk׎ºfÍš51oÞ¼1×ðÃ×½.ž-lÆuwwÇqÇ7æïIqý?OFtý15ïJ¨7ç?1ã?ÃØbÜýñ3îˆÎ¼+íᇎ 6ŒxíÉ¡¡œªÝ î5¯yMüó?ÿó¨×?ùÉOFoooüõ_ÿu¼êU¯Šˆˆ³Ï>;®¿þúX¿~ýðV¼wÞyg<ñıråÊ1×pò}÷ÅüùóÇü~êË¿}9⨣"-Ê»êÍí_ŠøÝßøƒ?È»êÍm_Œ8ö؈ÿûó®d´ã~óç¥f<ð@Ä‚y”!€Lx]]]qÖYgzýóŸÿ|”J¥xûÛß>üÚ%—\7ÝtSœzê©qá…ÆÖ­[cÕªUq 'ÄòåË3¬šz¶gš Œ7óôI¥³ÓØ‚a:ûôÛgyvØaqÏ=÷ÄQG_|q¬Zµ*/^ÿöoÿfýãÆ"tRéè°4„[80: ìÕ]wݵ××>úè¸õÖ[3®†‰¤£#âç?Ï» êQ¥ñ‹_ä]õÈØ‚£ÔO©IÅØ"80PSÜ$’Š›DR1¶àÀ @M±TÜ$’J¥ÑÓ“wPPS,B'Ý5R©TŒ-8PSš›#úúò®‚z4yrÄÎyWA=jjŠØµ+ï* 8 ¦üÖîÏ@@€š#„JµšwÔ+c öŸÔê—pJ%]Ø_P“ü"'…ÆÆˆ¼« µ´Dô÷ç]ƒÔœÖÖˆmÛò®‚zd›gRqÎ ì?¨9#$7‰¤â0BØPs<¥&Æ‘Šp ûOjN{»›DÒp“H*Æì?¨9¦`‘бE*¦`Áþ@€šc ©˜‚E*Â-ì/¨9¦2Š©øÜ‚ý'€5§£ÃSjÒÐ!öŸÔS°HE„TØPsÜ$’Š›DR1¶`ÿ @ÍÑ!ÓûHÅØ‚ý'€5G„TÚÛ…[ÒhlŒÌ» (¨9­­Û¶å]õ¨\ލVó®`b@€šS*å]Ànaÿ @f€qP*é‚Àþ@˜pÜ$’”)Û·ç]Ô>¨YnIaÊ”ˆ¾¾¼« uvÚÁö‡Ô¤ææˆþþ¼« Ùæ™T*•ˆžž¼«€Ú'€5Éa„¤âÄjR1¶`ÿ @Mò”šTœXM*ì¨InIÅM"©[° &™‚E*ºk¤"€Àþ@€šä&‘TÜ$’Š]°`ÿ @MÒ!ÓûHE¸…ý#€5I„TÜ$’Šmxaÿ @MÒ!Rnaÿ @MªTÜ$’†±E*ííœÀþ@€šÔÞîI"ixJM* CCyWµOj’)X¤ÒܱcGÞUL\P“ÚÛM“ЧZÍ»¨}P“"ó®oÀ8)•tAà• 㤭-¢·7ï* ¶ @Í*•ò®€zeŠ©Øe ^™À„c“R@à• @ÍjlŒÈ» ê‘›DR1¶à• @Írb5©tt¸I$ÎNc ^‰Ô¬öv‡’†pK*: ðÊ fut¸I$ c‹Tt×à• @Íò‹œT<¥&•ÎΈžž¼«€Ú&€5«£Ã,ÒÐ!á^™Ô,Rq“H*Ƽ2¨YžR“ŠEè¤"€À+@€š%€Š›DR±{¼2¨Y¦`‘бE*årÄÐPÞU@m@€še:©xJ ¨Y¦`‘JCƒ§Ô¤S*å]Ô6¨Y: P fMš10w¦TÒaƒ—#€5Í/qR©Vó®€zÕÖÑÛ›wP»&,!„ló /O`Bji‰èïÏ» ê‘/O`B²Ë© ðò ¦•ËyŸ…WƒIDATƒƒyWA=r“H*•JDOOÞU@í@€šÖÞn1'iè€Jg§p /Gjš³@HE„TŒ-xyPÓ::ü"' c‹TxyPÓ*Ò¨TLÁ" ^žÔ4O©IÅM"©X„/OjZ{»i耊±/OjšŠHÅØ"•¶6»÷ÁË@€šf ©˜‚E*årDµšwP» ¦yJM*Æ@> ¦¹I$•––ˆíÛó®‚z¥û&€5ÍA„¤R*å]õÌø‚}@€šf PD¥RÄÐPÞU@m@€šÖÒÑ×—wÆâ°oPÓLc %óôIÅ.k°oV¹lš i8 öM`Â2M†T:;u@`_ æ™&C*69 S°`ß æ•JBiT*Ι! öMjÞ”)Œ# R@`ß æ9 TÜ$’бû&€5Ïiè¤"Ü’Šû&€5Ï4Rq“H*vÁ‚}@€š§B*¡“Šp û&€5O„TŒ-RimèíÍ» ¨MPót@HE„Tlû&€5ÏBaR1¶H©TÊ»¨MPóL“!óô²'€5Ï,RilŒÌ» €‰EjžPDå²€ {#€5O("kŒ`ï æµµ @ñXc{'€5¯\¶%P<ìÀ„6iRÄÎyWA=@`ï t@HÅ&¤"€ÀÞ LhNC'öN Á‰Â¤b§"Réì@`o &MŠØ±#ï*¨GžR“б{'€…à,RÑ!öN!}ôÑX²dIyä‘ÑÚÚ]]]qòÉ'Ç 7Ü0êÚÇ<Î8ãŒhoo®®®X¶lYlÞ¼yÄ5ëÖ­‹r¹÷Þ{oV&7‰¤â&‘Tlp{טwäoݺuÑÛÛË—/îîîØ¾}{|ûÛߎ?ú£?ŠuëÖÅ%—\ëׯSN9%¦NW^yelݺ5®ºêªxä‘GbÍš5ÑØøâp*™°Ï8@H¥£#â™gò®‚z$ÜÂÞ Ä™gžgžyæˆ×V¬Xóçϯ}íkÃäŠ+®ˆ¾¾¾x衇bÖ¬YñÚ×¾6Þò–·ÄêÕ«ãüóÏ~Õž©Œ3OIÅM"©´¶Fôöæ]ÔS°Ø«R©³gÏÑÕ¸ùæ›cñâÅÃá#"âôÓO¹sçÆ7Þ˜G™L Ö€Šî©˜ {§°íÛ·G___<ÿüóñ/ÿò/qûí·ÇÕW_6lˆM›6ÅI'4ê} .Œ[o½uÄk¦`1ÞÚÛÝ$’†)ùu£ [¹re\{íµÑÔÔ_üâãýïDDlܸ1""fΜ9ê}3gÎŒ-[¶ÄÀÀ@455Åœ9sbpp0»Â™::"~õ«¼« ™Þ-„a]tQœsÎ9±aÆøÖ·¾+V¬ˆ)S¦Ä²eË¢¯¯/""&Ož<ê}ÍÍÍÑ××MMM™ÖÌÄa ©´µElÛ–w‡Â°¹sçÆÜ¹s#"béÒ¥±hÑ¢øð‡?K–,‰–––ˆˆØ±—“àúûû#"†¯*S°H£Tаo©”Ë»vE4ºã‚a¡³Oï|ç;ãùçŸÇ|xêÕž©X/µqãÆ˜6mšîIé€Eä³ F“ÇÙ§=Ó®ÊårtwwÇŒ3bíÚµ£®[³fMÌ›7oÌ?燯{]<[™…»»»ã¸ãŽó÷¤þtD,ÿïˆøeÞ•P.½?"ÎÊ» êÑlj˜|NDLÉçç?üðñaƯ=94”O1ðñì³ÏÆŒ3F¼¶k×®øÆ7¾Ó¦M‹c=6""Î>ûì¸þúëcýúõÃ[ñÞyçñÄOÄÊ•+ÇüóO¾ï¾˜?þØÿL¥ˆËßqóÍyWB=úÌÛ#nùNÞUPnü#Î>;â žÓ”ã~óç¥f<ð@Ä‚y”!€ò'/¼ðB¼éMoŠY³fÅÓO?7ÜpCüô§?Õ«WGCCCDD\rÉ%qÓM7Å©§ž^xalݺ5V­Z'œpB,_¾<ß¿u¯©i÷»àEP(: @U*==yWµA Å ˆ:;=<= P ˆì²/@€B1 ("^$€…ÒÖÑÛ›wÔ«ææˆþþ¼«  ð"(”rÙNE¤£ÃF*¼H §TÊ»êU¥b«TÒ@àEü†³HE ðnIÅØ‚ @ᘂE*: ¤"€À‹ pšš"vîÌ» ê‘›DRii‰èëË» ¨ P8žR“бE*¥RDµšwP pÚÛ=¥& €ô p::"¶nÍ» ê‘@zP8©è€’ 4`7(§U“бEJyWù@€ÂÑ!•)S"¶oÏ» ê•)~°›Ž§Ô¤bŠ )™â» @áè€E$€ÀnP8¦1E$€ÀnP8¦`E$€ÀnP8¦`‘’«IEÝ pLÁ"¥¶¶ˆÞÞ¼« uv !€ÔÔd/}ÒpIEv@€B2E†TÜ$’Šõk°›/¡B*•JDOOÞU@þ G*: ¤blÁn¼„i2¤ÒÒÑ×—w?(¤R)bh(ï*¨G•Š)X¤¡s » @!µ·; „4t@HI((‡’Š@ZPHžR“Š]°Ò@€Br“H*v*"¥ÆF©‚’)X¤ÒÞ.€Ž‡' €e ©Lž±sgÞUP¯tØ@ J("  LcŠH((S°€"@@ Ê, ˆ@€‚2‹”l•J* @Aµ·ë€Ž© €5eJĶmyWA½r“H*•JDOOÞU@¾ J¥ˆj5ï*¨W¦ø‘Šp Œâ&‘T:;-@à·Øæ™Tš›#úûó®ò%€Ào©TLÁ"Ri÷˜È °¬!Rò¹ÅD'€…ÕÒb*i耤#€…ÕÞî)5iØ (,O©IÅ.X¤ÔÐ10w(,§U“Š)_LtPX~‰“J{»±E:Îa¢@€Âr“H* CCyWA½2ʼnN ËV©@ LtPXÖ€E$€0Ñ @a ¤ä´jR@˜è °LÁ"5'V“‚ÂD'€…¥BJÍÍýýyWA=@˜è °t@HÉ6Ϥ"€0Ñ @aµ·ë€N¥"€†ÂD'€…å¬RÒ!2Ñ @¡Y$L*žR“JssD__ÞU@~ Ðl•J*: ¤R*ùìbb@`/t@HI÷–‰L€½Ð!%„‰L ­¡!b` ï*¨G: ¤$€0‘ @¡9ŒTt@H©©)b×®¼«€| @¡¹I$RòÙÅD&€…æ—8©tt ¤S©Dôôä]äC Í,R™2%bûö¼« ^9Œ‰L ÍSjR)•,&Sü˜È Ðt@€"ªTLeâ@€B³("&2(4S°€"²‰L!Ö®]+V¬ˆ×¼æ5ÑÖÖsæÌ‰w½ë]ñä“OŽºöñÇ3Î8#ÚÛÛ£««+–-[›7oqͺuë¢\.ǽ÷Þ›Õ_ ¬½Ý,Ò±„Tt@˜Èó.€ü}ö³Ÿþð‡qÎ9çÄñÇO?ýt|éK_ŠùóçÇ}÷ÝÇsLDD¬_¿>N9唘:uj\y啱uëָꪫâ‘G‰5kÖDcã‹Ã©T*åõ×a‚Ñ!¥¶¶ˆÞÞÝAÆ“ÂD&€+W®Œø‡ –,YÇw\\yå•qýõ×GDÄW\}}}ñÐCŬY³""ⵯ}m¼å-o‰Õ«WÇùçŸ?üþªG†dÄ"tRÚ³ÆHa¼ Ld¦`¯ýëG„ˆˆ£Ž:*Ž=öØxì±Ç†_»ùæ›cñâÅÃá#"âôÓO¹sçÆ7Þ˜Y½ðR)¹I$Ý[&2„}zæ™gbúôé±aÆشiSœtÒI£®[¸pa<øàƒ#^3‹¬LžÑߟwÔ+7‰¤â K&2S°Ø«o~ó›±~ýúøÌg>7nŒˆˆ™3gŽºvæÌ™±eË–ˆ¦¦¦˜3gN fZ/—¬KJÎj •RÉç—£<þøã±bÅŠøýßÿýX¶lYDDôõõEDÄäÉ“G]ßÜÜ<âÈš%G¤¢0þFxæ™gâmo{[L:5þéŸþix*UKKKDDìØ±cÔ{ú3ÿeÏ55OI¥R±Æ`¼ {á…âŒ3Έ^x!n»í¶8ôÐC‡¿¶gêÕž©X/µqãÆ˜6mZ455eV+@t@ÆŸ5 DÄîÎÆâÅ‹ãg?ûYÜyçñ»¿û»#¾ÞÝÝ3f̈µk׎zïš5kbÞ¼ycþÙ?|ÝëâÙòÈ,ÜÝÝÇwܘ¿'Ë¥k"ªgEh„0ÞN|>¢û鈸;ïJ¨G—Þ1ôöˆr¯‡~86lØ0âµ'‡†Òý@Ø144K–,‰ûî»/¾óïÄÂ… ÷zÝÙgŸ×_}¬_¿~x+Þ;ï¼3žxâ‰X¹rå˜þÉ÷ÝóçÏóûáóçF|ý뻃ñ´ùg_ýrÄç?Ÿw%Ô£/¿w÷Øš6-ÝÏ8î7^jÆD,Xî‡Â+@ˆ|ä#qË-·ÄYg›7oŽn¸aÄ×ßóž÷DDÄ%—\7ÝtSœzê©qá…ÆÖ­[cÕªUq 'ÄòåËs¨vÛsXœÂxs)í_)Ô"„øñ¥R)n¹å–¸å–[F}}O9ì°Ãâž{î‰|ä#qñÅǤI“bñâűjÕ*ë?È•ÃIeO¸…\&*„¸ë®»öûÚ£>:n½õÖ„ÕÀ³P˜T&OŽØ¹3ï*¨W•]°€ÂÓŠHa¢@€Â3M("„‰J Ï, ˆ&*(ùÉOÆç>÷¹á¯?øàƒñªW½*þðÿ0¦N¿üå/ãk_ûZ|÷»ßýèGñêW¿zøÚk¯½6>ðÄ9çœ+W®ŒüàqÁD___|ìc¾®T*E©T jÀæÍ›ãòË/9sæÄ¼yóâî»ïÞçµÍÍÍqÝu×ÅKw®¯T*£®3>Øã½ï}oÜ|óÍqÑEÅQG«W¯Ž·¾õ­q÷ÝwÇÉ'ŸëׯSN9%¦NW^yelݺ5®ºêªxä‘GbÍš5ÑØøâmš±E]©$v÷ÝwWK¥RõÛßþöË^·iÓ¦jµZ­VW¬XQ-—Ë{½®¿¿¿:eÊ”joooµZ­VúÓŸVgÍšõŠuüèG?ª–J¥êe—]6üZ___uúôéÕ³Î:kĵK—.­¶··W{zz†_ûô§?]=âˆ#^ñçP ;wî¬>óÌ3ÕjµZ]»vmµT*U¿ñoŒºnùòåÕöööWü~O=õTµT*Uï¹çžq¯•b¹ï¾ûª¥R©úWõWïõ÷÷W:ê¨êïÿþï¿ö| ÚÚÚZýŸÿùŸá×î¸ãŽj©Tª~ýë_~ÍØ¢Þ˜‚dª··7÷úµ3fÄäÉ“_ñ{lß¾=𛛣µµuø}Û¶m{Å÷Í™3'""ššš†_»ë®»bË–-ñÁ~pĵú§½½½ñÝï~÷¿/ÅÔÔÔ‡rÈ~_?44[·nMXõ⦛nŠÆÆÆxÿûß?üÚäÉ“ã¼ó΋ÿüÏÿŒõë×GDÄÍ7ß‹/ŽY³f _wúé§ÇܹsãÆo̼nÈŠdæ}ï{_tttDsssœvÚiñ£ýhLßgêÔ©qÈ!‡Ä§>õ©xê©§â£ýh¼ñoÜëµ[¶l‰gŸ}6Ö®]ï{ßûâÐCåË—ýÁŒˆˆ Œxß‚ ¢\.‰mûöíÑÑÑ•J%ºººbÅŠ{ ½¦ÉñÐCÅܹs£­­mÄë .Œjµ=ôPlذ!6mÚ4jZêžë~û³ÇØ¢žX$7iÒ¤xç;ßo}ë[cúôéñè£ÆªU«âMozSüð‡?ŒN8ဿçW¾ò•xÇ;ÞŸùÌgböìÙñýï¯×Íš5+vìØGydÜ}÷Ý#ž6nܸ1búôé#Þ×ÔÔ]]]±aÆá×.»ì²¸ì²Ë¸VŠ­»»;>þñÇüùóchh(n»í¶øÊW¾?ùÉOâî»ïŽry÷³¼9sæì³»ÇIJqãÆ˜9sæ¨×÷¼¶aÆ8ôÐCG¼öÛ×mÙ²%¢©©ÉØ¢î @roxÃâ oxÃð/^¼8Î>ûì8þøããâ‹/Žï}ï{ü=ßüæ7ǯýëxòÉ'ã5¯yÍ>§nÝvÛmÑßß=öX|îsŸ‹?øƒ?ˆÿøÿ!}}}1iÒ¤½¾·¹¹9úúú¸6êËW\1â¿—,Y¯~õ«ãÒK/›nº)–,Y’SeÔª¾¾¾½~&577}ÏgË+]÷Ò)£P/LÁrqä‘GÆþáÆ]wÝ5bg¡ÑÑÑ ,xÙu#ÿçÿüŸX´hQ|øÃŽ{î¹'6mÚþç>üõ–––عsç^ßÛßß---cªúvÑEE©TÚ붪ÐÒÒ2Üy}©=Û…·´´ ¶¼ÒuP 7³gÏŽ;wî×òñðªW½*N<ñĸï¾û†_›9sf ŽÚw`` ž{î¹èîîΤ6Š¥¹¹9ºººbË–-y—B š9sflܸqÔë{^ëîîžzµ¯ë¦M›¦ûAÝ@€Üüüç?æææQ 5Sêëëž³1oÞ¼¨V«±víÚ×Ýÿý144óæÍˬ6Š£··76oÞ3fÌÈ»jмyóâ‰'žˆÞÞÞ¯ÿ×ýW”J¥8ñÄ£»»;f̘1ê³'"bÍš5>{¨kÜow""~üãÇ-·Ü‹-÷Ÿ788===£^_³fM<üðÃñ¦7½iøµÓN;-¦M›×\s͈k¯¹æšhmm·½ímã^űcÇŽQ7‘1<ïÌ3Ï̺$ àï|gìÚµ+¾öµ¯ ¿¶sçÎX½zu¼þõ¯}öÙñ¯ÿú¯ÃÛòFDÜyçñÄOX[D]³Hî]ïzW´´´ÄÉ'Ÿ‡rHü÷ÿw|ýë_¶¶¶øË¿üËáë~õ«_ÅßÿýßGD ?ܳxΜ9±téÒýúy½½½1{öìx×»ÞÇ{l´¶¶ÆO~ò“X½zuÌœ93þìÏþløÚæææ¸üòËcÅŠ±dÉ’X´hQÜ{ï½ñ­o}+þâ/þ":;;ÇëŸôå/9zzz†o¿óïįý눈¸à‚ bË–-qâ‰'ƹçž¿÷{¿»76¸õÖ[ã­o}kœuÖY¹ÕNíZ¸paœsÎ9qñÅÇ3Ï<3|úºuëâïþî»ä’K⦛nŠSO=5.¼ðÂØºuk¬Zµ*N8á„Û…CÝÉù D`øÒ—¾T}ýë__>}zuÒ¤IÕY³fUßûÞ÷VþóŸ¸nωéåryÔŸ7¿ùÍûýóvîÜY½è¢‹ªóæÍ«vvvV'Ož\=òÈ#«úЇªO?ýô^ßó7ó7Õ£>ºÚÜÜ\}õ«_]ýë¿þëƒú;S ‡~ø^Ç[¹\®®[·®ÚÓÓS]¶lYuîܹն¶¶jKKKõ¸ãŽ«~ö³Ÿ­îÚµ+ïò©a;vì¨~üã¯vwwW[ZZª¯{Ýëªßÿþ÷G]÷è£VÏ8ãŒj[[[uÚ´iÕeË–U7mÚ”CÅRµ:Æíg5 @f 3ÈŒdF2#€™@€Ì @f 3ÈŒdF2#€™@€Ì @f 3ÈŒdF2#€™@€Ì @f 3ÈŒdF2#€™@€Ì @f 3ÈŒdF2óÿ’ÅU±YÖñPIEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/curvlinear_grid_patches_image.png0000644000077000000240000012202512436367710027451 0ustar tomstaff00000000000000‰PNG  IHDR  ÛphsBIT|dˆ pHYsaa¨?§i IDATxœìÝyXUåÂþñAE4œPÄLÅ¡œ%53Í)µ×©Žc8œ´¬s̡ҬL+‡4ÍŽ¢æ˜C6˜ó€N8 Š 2({ÿþð÷ôKq‚µ¾ŸëZ {¯çÞ—ëÞëYϲ±Z­V€lÍ ÿ €0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` ÃP@†À0†¡€0 €a( C` Ã0;@n£M›6©|ùò*T¨ÙqÍnß¾­sçΩeË–*Q¢„Ùqr% ÈSØ´i“zôèav lÉ’%êÞ½»Ù1r% ÈS(_¾¼¤{ÿýüüÌ  GHJJÒõë×uãÆ ÅÆÆ*..N±±±®T©’ ðÀç[­V5hÐ@ ”³³sÆV¤H.\X… VûöíåëëûÀ}ܾ}[·nÝ’£££T°`AÙÚ>ÙŒÛ?üPß|ó*Uª¤ºuë*((HµjÕÒ®]»ôöÛoküøñ*Q¢„öîÝ«={öèôéÓêÞ½»FŒñDã@NwâÄ õèÑ#ã8òþœvåçç§Úµk›œ@vJHHÐ¥K—T¹reÙÙÙ=ðq¯¿þº¾üòËŒ¿ÛÛÛËÝÝ]%K–”»»»¼½½úóâöíÛ²±±É²ìOcÚ´iš1c†J–,ù—Ï_ºtIÒ½Ÿÿýàµk×”žž.OOOCs€Ñ˜~ÿä( ð¿bccµ~ýz]¸p!c»xñ¢.]º¤øøxIÒÅ‹U¦L™îcøðáêÕ«—J•*¥’%KÊÅÅå±ËDv—””íܹSëÖ­SË–-Õ¶mÛ>ÖËË뾟wvv–ƒƒƒœÿòùÿ¿¨ÜÏúõëµiÓ&…„„¨qãÆrppx¼ÈÕ( ò<«Õª˜˜Y,yxx<ðqQQQzíµ×äææ¦²e˪lÙ²jÚ´©¼½½U¦L•)Sæ¡V¯^=«ãg‰˜˜­_¿^aaaÚ¼y³él̃´k×NwîÜy¢ç^¿~]«W¯ÖǬ"EЍE‹j×®BBBäææöDûäyFLLŒ"""tòäI:uJ§OŸÎØ4tèPÍš5ëϯR¥ŠU¸paSg¯ï¾ûNü±~þùgY­VÕ­[Wcƌы/¾¨êÕ«›2Õ«wïÞêÕ«—Ž=ªµk×jíÚµêÝ»·lmmÕ°aC 2D:u2<ÀyÆk¯½¦ 6H’Ê”)£gžyFuêÔÑ«¯¾ªŠ+* ÓçÛÙÙå©ò!IW¯^U‘"Eôé§ŸêÅ_T©R¥ÌŽ$éÞ4³5j¨F?~¼¢¢¢´víZ­^½ZQQQfÇd#«Õj5;DnuàÀjÿþý\„d±»wïêÔ©S ×±cÇtüøq-Y²$ÓëŽ9"U¬XQNNN¦äÿ==΀È®_¿® èÈ‘# ×ü¡»wïJ’<<<äïﯸ¸¸LßÁ¯Q£†QqMwöìY}ûí·ªP¡‚^}õU³ãjùò劌ŒT—.]äããcvÀcz²…á ‹¥¦¦jòäɺpá‚êׯ¯3fhÇŽº~ýº¢¢¢´mÛ¶3}È,ÑÑÑš={¶êÕ«§Š+êý÷ßWDD„Ù± ¡÷ß_+VT½zõ4{ölEGG› ðˆ˜‚õ88p@å˗ט1cøø?å”û_äÉÉÉZ³f-Z¤-[¶ÈÖÖV­ZµR·nÝôâ‹/æ¹kVURR’Ö®]«o¾ùF6lÕjUóæÍõÚk¯©}ûöLÁm8þ{zLÁ%"##µcÇíÝ»W{÷îÕ‘#G”šš*[[[ùûû?ôÆtû[½zµºwï® hΜ9zå•WXªVRáÂ…õꫯêÕW_Õ7´råJ-Y²DݺuÓÒ¥KÕ­[7³#€ K|ýõך4i’|}}U§N½öÚk T@@ïF?…:èôéÓªX±¢ÙQþ",,L;wÖŠ+Ô®];S³¸¹¹iàÀ8p Îœ9Ã]Ø ‡£€ÈTzzºŽ=*//¯Lïr=tèP1BE‹50]ÞçääôÔå#5=U;ÏíÔšˆ5úùÂÏ’¤ÎU;k\ð¸'ÞgBB‚RRR”ðTÙ²ZN+j€¿ã"t‘œœ¬íÛ·kÒ¤IjÑ¢…Š/®ZµjiÕªU™>ÏÕÕ•òñΞ=«±cǪ~ýú²X,Ù2ƹ›ç4ä‡!*9­¤Z,i¡µ'×*È+H~î~¿m¼6Þ”-ãæd‹Eõë×ר±cuöìY³ã@¾Ä’¤>ø@aaaÚ·oŸîÞ½+5hÐ@ãÆSýúõdvÄ\/==]ëÖ­Ó¼yó´iÓ&+VL={öTrr²Š)’eãŠ:¤©¿LÕŠc+T¼Pq ®;Xü;©¦GMÙØØÈjµ*üZ¸–…/SËJ-³lÜÜ 99Yš7ož¦L™¢-Zè7ÞPHHˆìììÌŽù€$éüùó*[¶¬zôè¡àà`U­ZU¶¶œ$Í ×¯_×_|¡O?ýT.\PPP.\¨.]ºdÙõ1V«UÛÏm×”_¦hó™Í*ïR^³ZÍRŸZ}ädÿ×1llläâè"«òß"ˆEŠÑǬ)S¦èÛo¿Õ¼yóÔ¡C•-[VTß¾}åîînvLÈÓ( @—’’¢ß~ûMõë×WÁ‚ø¸yóæ˜*ÿ°Z­zöÙguõêUuíÚUƒ R```–î?,"Lïïz_û®ìS@©-{y™:ùwRÛÿˆOMO•Mþ}ÇßÉÉI}úôQŸ>}´ÿ~Í;W“&MÒüùóuæÌVe€lDò«ÕªððpmÞ¼Y[¶lÑO?ý¤Û·oë§Ÿ~Rpp°Ùñò-]ºT•+WÎòås÷\Þ£Q›Gi×…]jR¾‰6õؤæ>ÍzðœnI×±kÇÔÑ·c–æÉ­µpáBM›6M'Ož¤|@6£€y€ÅbÑ·ß~«M›6iÓ¦MŠŠŠ’£££5j¤wß}WÍ›7W5ÌŽ™o=÷ÜsYº¿È¸HÛ6NË׫zÉêÚØ}ãc]ËñGÌJº›¤º¥ëfi®ÜÎÍÍ-Ëÿ­Gò[[[M˜0A… RÏž=Õ¢E 5lØPŽŽŽfGËó®^½ª›7oÊÏÏ/ÛÇŠ»§ïú·fï™-·BnZÐnzÕì%;ÛÇ›JµçòÙÈF^O>¬jÕªjܸ±ªV­úÄûÈŽ?®âÅ‹s¯“Y,®Qr1¾{<âСC:r䈦NªfÍšQ>²ÙÉ“'Õ¯_?•/_^£GÎÖ±î¦ßÕìßg«ÒÇ•4oß<¯SCNéõZ¯?vù¤mç¶©†G uxòe“´cÇ<ñ>r£·ÞzKåË—W¿~ýtòäI³ãäKÛ·oWõêÕYFÈÅ( @©Ù³g«E‹Š‹‹Ëô±… 6(UþvðàAuîÜY¾¾¾Z·n&Mš¤¥K—fËXV«Uk#ÖªÚ¼j¾i¸:úvÔ©!§4¡ñ.ødÿÞ«E›NoRëJ­³8mþ°téRMš4IëÖ­“¯¯¯:wš+_HKKÓ{ï½§fÍšÉÓÓSÅŠ3;€'Dr«Õªh„ ªY³¦|||4zôhÙÚÚ*&&ÆìxùÚîÝ»¢Úµkkÿþýš7ož"##š-B'®ŸPóÅÍÕny;yõÖÁ5¿Ý|y:?ÝÔŸ ñt=ùº•k”EIó—bÅŠ)44T‘‘‘š7ožöï߯ڵk+$$D»wï6;^žuìØ15lØPï¼óŽÆ¯7fù¢ŒCr«ÕªQ£F©B… ÔǬêÕ«kÅŠЉ‰ÑÆõÌ3ÏQ5?­©óñçµ¶ëZmé¹E5<²fË·.K’Ê+›%û˯5`ÀEDDhñâÅ:{ö¬š6mªØØX³£å) U@@€nÞ¼©]»viÒ¤I*P€KXÜŒï` °±±Ñ•+WÔ¶m[½ôÒKjܸ±ìíí{?ÉÉÉúøãõÕW_iâĉêÛ·o¦÷þÀ£quuÕîÝ»U½zõl½ðu{äv \?P‘q‘ÓpŒÆ“c¬-9—îÒEKgé~ó« ¨GêÖ­›Ž=*WWW³#å111ªV­šnݺ¥ &è­·Þ’ƒƒƒÙ±d΀9Ä7ß|£¹sçªY³fOT>$iøðኈˆP«V­4xð`U©REóçÏWJJJ§ÍjÖ¬™må#&9F½W÷Öó‹žWÉÂ%uhà!Mj:)ˡtï ˆ“½“Š90>+ÙÚÚªfÍšfÇÈSJ”(¡±cÇ*""Bo¿ý6åÈC( @6²X,úùçŸ5xð`9sÆ1½½½õõ×_ëÈ‘# Ò€äã㣩S§êÎ;†dÈ,‹ácZ­V-:¼H¾s|µ&bæ¿8_;{»¶y9á²¼œ½¸Ùž Ìø?–Ûýãÿ···Ù1d1 ŬV«>¬ÐÐP•/_^ÁÁÁZ³fÎ;ghŽjÕªiÅŠ:~ü¸Zµj¥¯¾úê‰Ï¬äeçÏŸWïÞ½Õ¯_?cǽy^Í7W¯Õ½Ô²RKý1èõ­ÝW¶6ÙûcùØõcªìVù©÷«5kÖpÍÃcèÛ·¯z÷î­óçÏ›%ÇHKK3;P@€,rñâE}ðÁªQ£†´`ÁµmÛV;wîÔùóçõ /˜’Ë××W ,ÐáÇeg÷ø÷ŒÈ«bcc5räHU®\Y7nT:u û›£ß¨æ§5u*ö”6vߨ¥—Ê£ˆG¶kµZµçòÕõzú; oذA:tІ ² Yþ¤7ªråÊ9rd¾-o±±±úä“O¤ÿûßfÇ` EBCCõî»ïªjÕªZ»v­®^½ªyóæ©Q£F9⎽;û‘’’¢äädƒÒ˜'%%EÓ§OWÅŠõùçŸküøñ:}ú´Þxãlûæ›êþ}wuÿ¾»ÚVn«Ã«e¥–Ù>îŸÎÆUìíXÕ-ýôï7ÞÐéÓ§5~üx}þùçªX±¢¦OŸž/®ÑJNNÖŠ+ôÒK/ÉÓÓSC‡•§§§êׯov4&0ÿ¨È#¦Nªèèh-_¾\!!!¹nºÓªU«äîî®Î;kùòåŠ7;R–[¹r¥üüü4fÌuíÚU§OŸÖ„ T¤H‘lû§ó?©æ§5µîä:-yi‰–v\*G—l÷¿í¹¼G’T:ÈÐqñŠ)¢ &èôéÓêÚµ«ÆŒ#???­\¹ÒìhÙbÏž=êܹ³ÜÝÝÕ¥K]ºtIS¦LÑåË—¦fÍš™€ ( À#²Z­™~½L™2*Z´¨Ai²^Æ õÏþSgÏžU×®]åîî®-ZhöìÙ:}ú´Ùñ²Ä’%KäïﯣGê“O>‘‡GöO{JMOոǩÉWMT®X9xXÝktÏöqïgÏå=ò)î£N%LÿÇÃÃCŸ|ò‰Ž=*-]ºÔìHÙâÆ:{ö¬þùÏêÔ©SÚ»w¯† fÈ÷€œ‹û€™¸{÷®Ö­[§ùóç«råÊš9s¦Ù‘²MÙ²e5vìX;V.\PXX˜Ö®]«Ñ£Gëÿø‡ºwï®%K–˜ó©|ûí·ÙróÀ‰ˆ‰P÷ï»ëpôa½ÿüû m*;[ó®ÃÙseÓ¯r???­[·.×®PgµZ3]Q­uëÖjݺµ‰äà>"##5þ|}ùå—ŠŠŠRݺuU·nþ9p+[¶¬¬Áƒ+11QÛ¶m3ôÀ=»ù–‡/×ÿ„ýJ;—Ö¯¯ÿjú´§»éwuàêuòëdjÜ_nùþºyó¦~ùåíܹSÛ·oW@@€æÏŸov,¹ ø_iiiZ¿~½>ýôSmÚ´IÎÎÎêÙ³§ú÷ï¯5j˜Ï4EŠQ»víú¸'Nèã?Vƒ T¯^=ùøøäË{M¤[Ò5öDZšöë4u«ÞMŸ‡|®Â ›Ká×Âu'íŽéE¹Ë¥K—´sçNýòË/úå—_tôèQY­Vyyy©I“&jÙÒ¸Eäà:tH:tPPP¾øâ uéÒE… ›à˜[\¹rEÛ¶mÓ¼yó$IîîîgŽêÔ©£:uê¨dÉ’Ù6þõë×õî»ïêÝwß•››[¶“™ØÛ±zõ»Wõcäú°Å‡^oxŽ)a¿_þ]v6vªUª–ÙQð˜nܸ¡‰'jâĉrww7tì%K–hìØ±ªR¥Š4h aÆ)88X+VÌ1ÿ·ä>6Ö‡]Y‹:pà€µÿ~Õ®]Ûì8ÈáááªV­šÙ1rµ7nè÷ß×îÝ»µgÏíÝ»W±±±òôôÔ•+W²|<«Õª… jôèÑ’¤Õ«W«Q£FY>ÎÉ>¢Ë;èVÊ-}Ûé[½àcÎ}_¤ã·­_^ÿ%Kö«]»v)88X®®®Y²OÜßO?ý¤:H’¦M›¦×_ý©þ-‹Î;§Ã‡+ @*Txàcoܸ!I¦•z 'âøïéqø/”§çææ¦6mÚ¨M›6’î„ÈÈÈG*‹-’———ªV­ªR¥J=ô +""Býû÷×O?ý¤ž={júôéÙz–åAV[¡>kú¨²[emëµMå]Êž!3©é©Úrv‹Æ4“eûtuuUûöí³lx°Fé?þШQ£Ô·o_-Z´HŸþ¹ªT©òÐç^½zUÇŽÓñãÇ®£G*<<\‰‰‰’¤O>ù$Ó{àP<d ò…¸¸8ÍŸ?_ P±bÅÌŽ“¯ØØØÈÇÇG>>>™>.--Mƒ Ê80rqq‘¯¯¯|}}U¥JùúúªAƒrww×Ý»w5uêTMš4IÞÞÞÚºu«)wšO·¤kü¶ñšòËu­ÖU_´ûBNöN†çx˜_.ü¢ÄÔDµy¦ÙQð„J–,©E‹©W¯^0`€jÔ¨¡ &è­·ÞÊôžC5ÒéÓ§åàà ___U«VM/½ô’ªW¯®š5kÊÓÓÓÀW÷P@§={V3fÌÐÂ… •žž®š5krÑdU @ÅÅÅéìÙ³:~ü¸Nœ8¡'NèØ±cúþûïuëÖ-ýðê[·®^xá…‡‡käÈ‘zçwT¨P!IRzzºììŒYæ6!%A¿ë¬Íg6kzóéñ܈;'þ‡S?¨T‘R (`v<«Õª›7o*22RqqqêÓ§V®\©·ß~[+W®Ô¶mÛ8 nñâÅruu• àW>€œŸFÈ“öîÝ«iÓ¦iÕªU*^¼¸FŽ©Aƒqó«®@ª\¹²*W®œ1ç]ºw­¢E‹ªP¡Bzþùçµ`Áþåù³fÍÒ¤I“T¾|y•+W.cóööVÙ²eU®\¹,yÇ7:1Zm¿i«S±§´±ûF5¯Øü©÷™~8ýƒZWjc îoóæÍzë­·tîÜ9ÅÇÇg|¾hÑ¢òññQ³fÍTµjU/^üû¨W¯žQà±P@§üúë¯zûí·µmÛ6U¬XQsæÌQ¯^½ää”ó¦ÅàÑÙØØ¨T©Rÿè£îû¸&MšèîÝ»:wîœÎŸ?¯üQçÏŸWRR’$©jÕª Ït¬Ó§OËÅÅE®®®²µµýÛ×ÏÄžQË%-•|7Y?õþI5KÕ|ŠW–ýÎß<¯ã×ëÝ&ïš%ß±X,ŠUTT”®^½ª«W¯êÊ•+ºråŠ._¾¬ªyó—Wwww=÷ÜsêÚµ«*T¨ òåËËÇÇGnnn”I¹yÊÅ‹¯•+W꥗^2l:r†ÚµkÿmE’?§¯\¸pA)))ÝGpp°¢¢¢T @•,YR­NV­³_'÷Êîúõ~Íq›ßÏþøìmíÕÜ'gŸ¥É ,‹âã㣴´4ùùùeúx///EGGÿås...*]º´¼¼¼”žžžéókÕª•±¬5ä%ä)¯¼òŠ:wîÌ»ƒÈ`cc£âÅ‹g:Må¿ýç?ÿÑ•+W¥èèhEGGëÚµk ÿ#\‡ÏVÙeõË뿨„S‰û>ÿ·ß~Óˆ#2Æ,^¼¸\\\þ²µoß>Ó ‡³ÒòðåjýLksdñ«Õª¤¤$ݺuKîîî™þ,Y²Dß|óâââ«7n(..N‹E’¨}ûöe:ÞŒ3äàà R¥JÉÓÓS¥J•ʸ^ ò3 ‰rŒm IDATò”ûM™AîbµZµlÙ2µmÛÖ”Ëî7gþjÂUÕ_X_• TÖ®>»äæôà¥Iœœäç秸¸8]ºtIááኋ‹ÓÍ›7• I=ª­[·ªH‘"*\¸pÆG'''999©V­ZêÖ­[¦ûØ·oŸ®Ý¹¦ßý®™mgêòå˲··WÁ‚eoo/GGǧ:CxèÐ! 6L3gÎT@@Ö^Ü©„„¥¤¤èÎ;ÿܪV­ªZµ|CÅsçΩW¯^JLLTRR’” ÄÄDýyë«ãÇgzÃjµÊÁÁA~~~ruu•«««ÜÜÜ26//¯‡¾Ž®]»>þ‹ÏBñññZ¿~½ºvíÊ›2r r»wïjÕªUzå•W˜Z•GݼyS Њ+4þ|õíÛ×ìHºyç¦Z-m¥4Kš6õØ”iù¤š5kjáÂ…÷ýZzzºnݺ¥‚ fº???ÅÇÇ+11Q‰‰‰e&99YÉÉÉJJJÊ´€X­Veü}ØÜa¦ayÌ·ß~«Î;?paaaêß¿¿ìììdcc#[[ÛŒƒX%''ëúõë:vìØ_ ÈìÙ³5eÊ¥§§Ëb±üåcZZš|||zNûöíuôèÑ~}ìØ±™GGGy{{g7ggç¿lE‹U™2e2ÍгgOõìÙ3ÓÇät+W®T¿~ý´fÍ}öÙgrqq1;H¢€ HOO×Ò¥K5iÒ$9sF^^^¦ÜéÙë·ß~S×®]uóæÍ‡Åbµ¨Ëw]t1þ¢~~ýgyó~ªýÙÙÙ=ÒT°Þ½{«wïÞO5Ö¡C‡ôʲWä]Ø[ãêSjjªRSSu÷î]ݽ{÷¡«#UªTIƒ ’Åb‘ÕjÍøøç„£G*,,ìoÏ«U«–ú÷ï/[[[ÙÚÚÊÎÎî/󣆯nÑ¢EJMM•ƒƒƒ ,(GGÇ¿m™)Uª”–,YòÐqòº¾}ûªhÑ¢êß¿¿´lÙ2=÷ÜsfÇ r.‹Å¢ï¿ÿ^o¿ý¶þøãµoß^«V­RÍš9{Õ!<‹Å¢iÓ¦iüøñª[·®vîÜ©råÊ™K’4ý×éÚ|f³6÷Ø,w³ã<29–vÔ©B§4¥Ó½à÷ø7iô÷÷—¿ÿƒ_óÒ¥Kï[@‚ƒƒüØãý·¬žÒ•ŸuîÜYÏ>û¬ºvíªàà`ýë_ÿÒèÑ£™® ÀTüBŽcµZµyófé•W^Q¹rå´wï^­^½šò‘ÇÄÄÄ($$DcÆŒÑèÑ£sTùØsyÆo¯Ð¡9þ>÷³<|¹œ :«õ3­ÍŽ“•+WN;wîÔèÑ£5fÌ…„„èÆfÇQ@ã,Z´H-[¶”£££vîÜ©7ªN:fÇB6:t¨öìÙ£ 6hòäɆ­ õ0·Rn©ëª®ªíY[ï5}Ïì8-%-EŸîÿT]ªv‘ç+!°··×äÉ“õÃ?hÏž=2dˆÙ‘äcLÁBŽÓ©S'•(QBmÚ´aå–<îÃ?TZZš¼½ŸîÚŠ¬dµZ5pÝ@]Oº®-=·ÈÞ.g”¢Ç±øÈbE'FkTýQfGAÓºukP‘‚EÌŽóD~¹ø‹v_ڭСfGA.–[¾gä^d»¤¤$7NU«VUxx¸¾ûî;MŸ>ÝìXÈfééé5j”‚‚‚ôÛo¿™ç¡&š5ÕÁ·ƒÙQžˆÕjÕ»;ßUU÷ª,½‹'öÛo¿)((H£FRzzºÙqäQLÁB¶±Z­úþûï5lØ0ÅÄÄhܸq U¡B…ÌŽ†l–˜˜¨îÝ»kݺuš5kÖCïºm¶çvjû¹íúO—ÿÈÖ&w¾/³,|™¶žÝªu]×åÚ×óÕ«WO³fÍÒðáÃuêÔ)-]ºTEŠäÎ3‚r. ²…ÅbQ‡´víZ½øâ‹š9s¦||rߊBx|W¯^UHHˆNž<©µkתM›6fGz¨‰;&ªV©Zj_¥½ÙQžHìíX ß4\¯ø¿¢¶•YAOÎÆÆFC‡U¥J•Ô¥K5nÜXëÖ­Ë‘+ÖȽx› ÙÂÖÖV7ÖêÕ«FùÈ'Nœ8¡çž{NÑÑÑÚµkW®(Û#·kçùz§É;¹ö¾3¡[Bu'íŽfµševämÚ´Ñ®]»­çž{N'Nœ0;€<„‚l3räHµoŸ;ßQÆãûùçŸU¿~}9;;k÷îݹf•³I?MR g ^¬ü¢ÙQžÈ®ó»ôÅÁ/ôÁ ÈÓ™w©‘u´{÷n9;;«AƒúùçŸÍŽ  €ÈQQQª]»¶víÚ¥2eʘç‘D'FkǹúìÐ\yö#%-EÖ P½2õ4 Î³ã *S¦ŒvíÚ¥Úµk+::Úì8ò €,Ñ©S'mݺU...fGyd[Ïn•$µ¨ØÂä$OfòÏ“u*ö”>ùÜð ÏÃÂÂäè訰°0CÇ…ñ\\\´e˽üòËfGGP@ðDnݺ¥7ß|SÇ7; rÜvaóÙͪéQS¥Š”2;Êc ‹Ó¤“ôÏ઺GuÃÇOHHPJJŠ ÆËmßÛr6 Û¶mÛT£F -^¼XfÇžˆÕjÕæ3›såÙ#ÑGÔmU7uðí ·¿mv ìöíÛ6l˜^xá•/_^GŽÑK/½dv,à‰œŠ=¥¨Ä(½Pá³£<–kI×ÔnY;=ãöŒ¿´˜{~r~sá‘8p@úì³Ï4cÆ mÛ¶M*T0; fµZovŒ,q!þ‚$é·gLNòèRÒRÔñÛŽº“vGa¯†©pÁÂfG/«Õjv ¹5}útÕ«WOŽŽŽÚ¿¿† &[[þëä7V«UC† Q£F”ššjvœ§vùÖeI’—³—ÉIÕjÕÀõµïÊ>­~uµ¼‹y› Pjjª‚ƒƒ5dÈJ€GÆQ$êÚµk>|¸vïÞ-³ãÀV«UC‡Õܹs5xð`,XÐìHOíÆí*R°ˆ 8š塬V«&¯}¥í¨^™zfG$I Ô!C4wî\ :”à‘0;r¾)S¦°J>fµZ5bÄÍ™3GŸ}ö™úõëgv¤,áXÀQwÒîÈbµäèë(¬V«Fm¥v¤^ø@Ýkt7;ðýúõ“ÕjÕ€T @}ôÑGüÎ) Š_$ù—ÕjÕøñã5sæLÍ;Wýû÷7;R–ñ+á§4KšÂ¯…«†G ³ãÜWº%]o¬CóÌלÖs4¨î ³#e¨Zµª7n¬ªU«š9@ÿþý•––¦Aƒ©P¡Bú÷¿ÿmv$9ÀMžÍÌŽ<’#F(!!AãÆ“···zôèav$9PÎø CX,ýûßÿVÓ¦MóÄÊFÈ:­ZµÒ¬Y³4a³£d›þýu5ñª¾>üµÙQ$I«EŸïÿ\u¿¨+;;íé·‡ò\g„ š5k–Zµjev9$KHHP§N4~üx5iÒDvvvfGBR¢D :4O_T³TMõ¬ÑSomyK×’®™šåpÔa5\ØPÖ PG¿ŽÚÝw·*¹V25ð$lll4tèP•(QÂì(r( H>uúôiÕ«WO[·nÕš5kôÞ{ïQ@/}ØâCÙÚØêµÿ¼¦ÔtãÏ&¦&jÔæQ üóÉ'Ÿ¨U«VzöÙgõûï¿Ë×××ìH€éšWl®e//ÓÊã+Õji+E%FeÛX‰©‰úâÀªûE]u\ÑQ5kúÈwޝæì™£Ë·.?ö¾î¤ÝѾ+û4wÏ\ÍRíÏk+ìd˜†Õ¦ÈDj}·õjóL›\{‘ÿ† Ô¡CmذÁì(ÈE.\¨‘#Gš9HJJŠ~üñG½ûZ­fÇA8 Ígœ%I_~ù¥âââÔ¬Y3U«VM¶¶tÑüèóÏ?׌34oÞ<³£äE<ô]çïtðêA½÷Ó{¾i¸†l¢º¥ëª®W]ù»ûË·„¯ÜœÜä`ç ‹Õ"‹Õ¢·oèàÕƒ:u@¯ÔñëÇ•nM—­­ZVl©Õ]V«må¶*`Ë]ä_©©©úè£T¥Jõïßßì80ÅbQxx¸¶nݪ­[·jçÎJNN–§§§ú÷ï/OOO³#Âü&̧öíÛ§ häÈ‘*Q¢„š4i¢&Mš¨qãÆò÷÷§ä?ÿü³ ¤7ß|S4;NŽS˳–¾ïò½ânÇiý©õZwr~ŒüQŸîÿôS³ìT㆞+óœÞ zSµ=k«º‹· %FHq¥=ý¥´DÉ’&YÓ%»BRAɾ˜ä\Q*ÕL*âcð+Œ3pà@=zTƒ ’¿¿¿6lhv$$..Nýû÷׎;#GGG5lØPï¼óŽZ´h¡5jäÚ3Âx||jîܹúðÃõ믿jûöíÚ¶m›†®»wïÊÕÕU~ø¡z÷îmvLd“Ë—/«S§NjРfΜivœ­x¡âêQ£‡zÔ¸wGçÔôT»yNq·ã”’ž";;ÙÚØª¨CQUq«¬±û¤è¥¸-Ò¾©RRä½Ù9JŪÝ+6$;)应xZJ½)%»WJ W¸WDJ5“<ž—¹—ò–™3gêØ±cêÔ©“öï߯ҥK› (V¬˜4pà@5mÚTõë×—£££Ù±` HtíÚ5•,Yò¡sttÔóÏ?¯çŸ^ï½÷ž’““µ{÷níÚµ‹Õ±ò°ÔÔTuêÔIöööZ±b…ìííÍŽ”«´+¨Ên•ÿúÉ;×¥ÈEÒžW¤['îÑ(^K*ÓAr­uïÏE}¥Ì¦_¥ÆK×vJQ?JÑ[¥3óï}Þ³•ðT¼fö½(À@þì T§N´sçN,È p¹‘ÕjUdd¤~ÿýwÅÄÄhÈ!|¬­­­6nÜh`:ädÍFŽ©è§Ÿ~z¤¢Š°¤KQ[¤3_H—Ã$ÙÜ+³¤R/H69±`1©L»{›$%_‘®n”Ž m¨%Uè)ÕxO*\6Ë_ `´’%Kê»ï¾Spp°F¥Ù³g› aµZuñâEíß¿_û÷ï×¾}û´oß>ݸqC’T³fM <˜ã<&úç!Ë–-ÓË/¿¬6mÚè¹çžËÖ±œeoo¯/¾øB;vT¹råäîî®æÍ›kôèÑZ³fM¶Ž'sìØ1Í;W3fÌгÏ>kvœÜÉ’&œ+…Uv´–nEHS¥—¥†ßJžÍ¿|Ü“—Tñu©í1©Îœ{edmeé`¨”÷ôûLöì³ÏjæÌ™š3gŽŽ?nv<ĪU«T®\9uìØQ_|ñ…ìíí5dÈ­_¿^ׯ_סC‡(xdœÉ#¾úê+½þúëêÙ³§,XíË솄„($$D’tåÊíß¿_ÐÁƒµråJ?~\íÛ·ÏÖ x|U«VÕT³&ÓyžHÔ6iÿ?¤øc÷ÎH<ó¦äVWÊÎ_º¶öRå7ïwbú½-òk©ÉzÉ50ûÆ ðÆo¨~ýúò÷÷7;J¾ôçYððpy{{«zõê|l£F¦ÀÀ@yyy˜y‘•E—ŸØ¨ýû÷«víÚ¦åX°`úõë§~ýúiÞ¼y9b«»wïfzmAJJŠš4i"___ùùùÉÏÏO¾¾¾ªP¡÷(AΓxN:8Rºø½T¢¾Tg¶yÿÉW¤]/IñÇ¥àU’g SbÄÆÆj×®] –«««)<ºÈÈH…‡‡ëĉ:qℎ?®'N(!!A’4zôhM:Õ䔹CN9þËÍ8ÒËå,X ¾}ûê7ÞÐܹssÌéχ]Øœ˜˜¨*Uªèرcúî»ï”˜˜˜ñ¼J•*©J•*š>}º*V¬hD\àþÒ’¤ãS¤ãS%7é¹%RùnÙ{Æãaœ¼¤¶I?w–v´•ê-¼wvÄ`®®®œår‘þýûkëÖ­*R¤ˆüüüäïﯗ_~YþþþªV­šÊ•+gvDä#\,<<\ýúõËqåãQ¸¹¹é«¯¾’tïðåË—uâÄ EDDdl[žïСCºqã†|||äííÍ™d­¨¥Ý}¤;Ñ’ß(ɬd_ÄìT÷(,5Z#í ýöštûŠä÷–¹Å@¶KKKÓÅ‹uöìY9s&c‹ŒŒÔîÝ»3}óoΜ9*\¸°J—.«Ž7qÄ–‹U«VM6lPóæÍsõ•)SFeÊ”QóæÍùysæÌÑ‚ $Ivvv*[¶¬*T¨ òåË«B… ªS§ŽZµj•]±‘WYÒ¥ð÷¤ðI÷îÃÑlGμ9 méÙ/$§ÒÒ¡1RZ²Tã]³SÈûöíSçÎuáÂ¥§§Kº·¬mÙ²eU±bEéöíÛ™*Uªx( H.ײeK³#˜æ“O>Qhh¨Îž=«ÈÈÈŒíÈ‘# SÓ¦M3- V«UëׯWéÒ¥U¦L•(Q"W9dÛQүݥk;¤êïJUÇI¶vf§z0©Æ¤{wT?\©©©š1cF–ì/O;6ùÞô¥²]î­(UÀÉìDOƾ¨Ôp…´éYéÀ)è³OlÆŒò÷÷×ðáõhÑ¢,Ùgjjªnܸ¡˜˜ÅÄÄèúõëº~ýºZ´hñÀ3é’´uëVõìyo¥9—Œ7›¼¼¼T»vmyyyÉjµf:…·OŸ>Yò€¼‚’ ÄÇÇËÑÑQfGÁÿ§OŸ>¿XRRR±]»ví¡ga¤{×ñüùîY±bÅäææ¦%JÈÍÍMnnnêÞ½ûc]L¿yóf-^¼X .”§§ç“½°üâøÔ{å£ÚD©úÄÜ¿ŠTñšRà,iïÀ{Зí”mC:tHÆ ÓÌ™3mã òôôÔG}¤×_]=zôP‹ÿw¿‹Å¢øøxÅÅÅI’||¼H„Õj•¯¯¯¢££ÿ·¯ÛÛÛkÉ’%™víÚéüùóòððà÷0E( 9\jjª:vì¨bÅŠéûï¿7;2áàà ²e˪lÙ²õ¼åË—ëêÕ«ïÊýùÝ7tîÜ9ÅÆÆfúüßÿ]­[·VñâÅU¬X18qB%K–Ô¯¿þª'NÈÅÅEC† ‘³³óÓ¼¼¼çôçÒ¡P©ê?¥ï˜&ëTê/]Ý$í&•ɶ©XÇŽÓÎ;uìØ1 ‹ÅbQRR’âããåååõÀiH½{÷Öäɓվ}{ùùùe”Ž›7oêÏ{(·hÑB›6mzàX666êÞ½» *¤%JdlîîîrwwWÑ¢EºøHÑ¢EU´hÑ'Áþ†’ƒY­V½ùæ›Úµk—¶nÝjvd“:uê<Õó½¼¼ªØØXmÞ¼Y©©©ªT©’:¤›7o*..No¼ñF¦û5j”V®\©¢E‹ªX±b¿p‹-*gggU¯^]½{÷ÎtÉÉÉ*T¨PîXIìü·ÒžRåÁ÷V‘ÊKll¤€)Òz?éÔ<Éw¸Ù‰X­V%''+!!A‰‰‰JHHP©R¥2=ËzìØ1=Z·nÝR|||ÆÇ„„Y,I÷®¯ððð¸ïóÿ,“&ÝûíÔ©“\]]U¼xq/^\®®®*S¦ÌC³O˜0á ^1€ìDÉÁfΜ© 諯¾R£FÌŽƒÊÛÛ[¡¡¡ŠˆˆÐŒ3ôöÛoëwÞy¬}4iÒDŽŽŽ ·nÝÒõë×uæÌ%$$(&&æ¡ÄÝÝ]·oßVáÂ…U¤H‘ŒíÏ¿5JÍš5{àó£¢¢´wï^999ým+T¨œœœäààðôçòÒ¯=¤ò=îMWÊ …éq}Fòé}ïú–ŠýrÎ a˜k×®éêÕ«JNNþÛ–””$õèÑ#Ó}ëôéÓJLLTRRRÆY‡?M›6M£Fzàó ( U¬Xñ/on+V,c{Ø™…‰'Êb±hòäÉZ¶l÷²ò Hµyóf5J£GV¯^½ÌŽƒ\`ãÆ*[¶¬BCCû¹!!! yªñ,X [·n)11ñ/[RR’z§úß~ûM;vÌô1wîÜÉtöÔ©Sõ믿ÊÑÑñ¾[Õ26zÅù©tÛ{œÛü}êÇï¿ÿžqàT°`ÁŒn… zèkɪM"K'gß»Ÿ sùòe%%%)55U)))JMMÍøsJJŠ*W®œéôÅ‹õ¯ýëÿ±wçñ1ÝûÇ_“}KˆXC­‰]*(Ú£mTmõÃí¢ÕZZ[[ÕM¹¥-µV•¶Úº—ºµEQ¡jiQ BDP;Am!dÏÌT6Éd¾g&Ÿçãq'23ç¼G˜œÏùn¤¤¤Ü³%''çìׯ_ŸowÏ™3gæ9m«““­Zµ*° %99ùž xzzâééIÍš5ó}}ýúõ Ë÷9…ñÖ[o±téR6nÜ(ˆ6 ~‹–>'Ožä™gž¡[·n|ôÑGªã+1jÔ(† ‚«««’ó?óÌ3Åzýã?žsÇöÎ;$''çܱÍþº YÂìììHOO'11ñ¾‹·”¤Dº7L ï;íá‘ÿi+‰ÿƒÉd¢uëÖùžcÙ²eù¾×M›61fÌptt¼gËþÞºuëò~ó»ï¾ãСCØÛÛcooƒƒCÎ×öööøûûÓ«W¯|s~»| †Ób·s ö{cpôÀÎ΃Á€mÚ´É·ûÊÅ‹9pà@N«ÓÝ­O¼çùÇçÏ?ÿȹSn2™r6OOÏ×tX¿~=7oÞ$33£ÑˆÉdÊùÚh4˜o—ÅË—/óÙgŸ‘‘‘AfffΖ‘‘‘³}øá‡ùvúꫯX´héé餧§“‘‘‘óuzz:uëÖeûöíù¾Ž;rìØ±<Ÿ4iR¾Ý‚RRRØ»wï=ų‡‡ÞÞÞ¸ººjR’W^y…§Ÿ~WWWÜÝÝïiQ,lýÆoêy%ÍÕÕ•¨¨(<<¤%O[!ˆÎ$%%ñôÓOS¾|y–.]Z¨Y”„ÈfÍ¿ œœ¨û+  IDAT\¹r±Žñúë¯çÞ%$ýlhÎ~Ú:ù Ì>|øð}w­³¿NKK£mÛ¶ùfðññ¡[·n¹^Àf_4÷ÿ¡C‡Ϲx6÷\T?ùä“ù &“‰^xá®ï¼|ßs–/_Nß¾}ó<ÆŽ; \çnK–,É髟›€€¢££ó=Æo¼A\\\®ÙÛÛ3qâÄ| ›7o²dÉìììrж»÷¤¤¤ä›ÁÛÛ›€€€{ H'''prr*ÔÌrß}÷iii9­fÎÎÎ÷lu;ª[·nÓwÄÏÏ??¿bCO¬ù³Mq?ƒéŸ:E¡íß¿Ÿ–-[I‹-ÌrÌ3gÎлwo¾ùæš4ib–c Qêý1Î.‡‡À£–ê4%Îd2å´÷ÇøçטBÏ’‰}Îcnnnù¶(%''çLszw‹F¶Õ«W3jÔ(–,YÂÀ¹u뉉‰À½-&Ù_;::¸ \rr2 µdݽYÅÄBˆR£$®ÿJiÑ™š5k²wï^ù…+„¹œ_'¿V_•Šâ´ ÿìîZÔ{NÌ‚Û{À·k¯Íæêêšow>???œs¦w6ÇT¥ªº !„°,)@tHŠ!Ì$å*ìy ª< QF²Á½&œ_û@HABCC ìÎ$„Bä&ÿŽÈBaÍöc}e›Óí†ÁU{Â…µ =n…Bè€ BX©ìþò"§ÿ§ûœ®¶iÕB!é$,ø¹BX ù ÂzI"„:wîU«VeÛ¶mª£èSR<ì5ú_ñ¦¶ •G/8ÿ£ê$B˜Å¶mÛ¨Zµ*çÎSEQR€a…>þøcìììò’´T‹žxx¾ê$ú`çUB´q BØ€ÀÀ@ìììøøãUGB ½öÚkÌœ9Su aeâããùúë¯;vlÎ Dâ.ÉáäwÐ`,8ç?ík©R¥ÜØi ª“QlžžžŒ3†E‹¯:ŽâI¢È¶mÛøì³ÏpqÉ{A4!r3sæL\\\1b„ê(úttØ9CÝWT'ÑϺÚþε9„0“‘#Gâìì̬Y³TGB< )@HNNfèС´oßžW^‘‹$Qx ,\¸#Fàåå¥:Žþ¤Ý„ã_@ÝaàTVu}q¯©í¥6ÂËË‹ádz`Á¤eOk"ˆ}ôgÏžåË/¿ÄÎN~¢ð.\HZZ¯½öšê(útü ÈL£U'Ѱs2[²víZ\\\X»VÆ•uFEZZ .TEñäê×ÂŽ;Æ'Ÿ|›o¾Iƒ TÇV$--¹sç2hÐ *W®¬:Žþd¦ÀÑÙPëY™v77;p«a¶$11‘ÔÔTÍr`°8„öë´)Ðx ­Xhq< uÕ:VÔDfs&ð>P xE+HÜ‹q!„°,)@l‘É‹Áë¯kkv¬Z¥ ·„S§àÖ-m-!,ÁÎ*¶‡¿¶C€,:v„Ãpéh»T5‹x૬íPxxè”1óù @­¬­OÖ÷2?Ð ŸµÀ7€ Ð!ãI„z'ÓðÚš“'µnV/½¤±±–+>¢¢´}óæ–;§>´…ö2e={ÄÍתP£¯ê$VÌlC»À¯LG+:¶ÿÍzÌÜÅG^ìG€O€#ÀQ`"°hƒÖòò5Z—.!„Ð')@lEf&ÌšiEÈÏ?Ã7ß@¹r–Íqàøø@åÊ–=¯(ݪ> w ~½ê$ú‘|N/…ú¯j­Dfš5klxÆ6°htb€Ùh- `ôщ ðð'°m¬ÈP 0)D„z$ˆ-¸|:u‚q㴖ǵY®TˆŠ’ÖbøðÃÙ½{·êÖÇËÊ? '¾UD?ލ3´D_¾|yzöìi£« ïÚOå­hÈHÀKa®üØ!hãRNƒ€:À ]Y2ÕvïÞ͇~¨:†â.R€˜Á™3g˜9s&wî(¸ÓôûïТ= ۷Ü9j€8 H%''3qâD¢££UG±N=¯­’|Iuõn#Ó¡Þpp²p+¨U;ŽVt´Gk9؈V|<†u«ðæ¢uÏêŒ66ÄS˜IÇ3qâD’““UGBd‘Ä vìØÁ;#ƒƒ…›ã,€ V-Ø¿}Ô²çÿ§+WàÂ)@Š(&&£ÑHSÀ_45€û\uµŒé°{0¸×„Æ“T§±™À,´57b€ïÑfê†uÿT mŒJPxè\QÊâš5k†Ñh$&&Fu!D)@ÌàÀáììl¹“N ÆÁË/ömàëk¹sç%2RÛ7k¦6‡•:|ø0ƒ€€ÕQ¬“SY¨7ŽÎ†”Òuuè)p# ÚüÜT§±ÇÐÆsŒE;q€mýzlü,¶ÀJ¥‰,) ƒÁÀáÇUGBd±¥OXe:Ä#%±¢x^¦O‡wÞÑV5Ÿ;Í?À´H6m‚êÕ¡NÕI¬Rll,~~~¸»Ë|þEæ?0@ìǪ“¨quÄ|ïB…‡U§Ñ90míŽKÀ¯Àlw= ð Z O;´™»ú“ûªì¶ÅÝÝ???bccUGBd‘Ä ®_¿NPPeN¶l¼ù&¼ý¶¶º¹žæöß°zôÐW&+Gƒ TǰnΠÁX­Ö­ãªÓXVF’Öõª\shôŽê4:— ¼¼ ¼waµ`ZkÈ& 5Ú Z¶­AƒÄÅÅ©Ž!„È"ˆ™–üI~ýž{þõ/ÐÛŒþ ÇŽiˆ(’ãÇS¯^=Õ1¬ŸÿàV þxŒ™ªÓXNÔ[tVëzUÓîÚŽKhƒÊ—¡ø ÛmõÈKvkHÚø—VÀ/J•´zõêqüx)»)!„ŽIbåÊ•£J•*%{’'à©§´æ_}¥¿V†ðppr‚ŽU'±J™™™œ:uŠ:Ò}­øÜ¡õwpu7ÄÍTÆ2N.†cŸA³iàe™V´¨¨(:tè@Töâ£V!N¿ƒ”¦Q¯>ZÒ mÀý´®i¶ç¡‡âÔ©SFÕQ„Hb%~ј–@… °r¥v¡¯76@p°Ú)€­ØíÛ·éС7VÅ6Tj§uÅ:ô.\T¦dY/ÀC/jƒð-$&&†_ýÕŠfÚŽ6ؼ °í¢[@Y´êc€ÑÀl±iÒ¤ :t 11Qu!úXÆÕêµiÓ¦dOðÞ{Úú¿ÿ^:\+)I›‰ë£T'±Z^^^lÚ´Iu ÛÒôC¸²~ …nZ·,[sa=ü>j</Ð_˨nlBÑÖ÷XÈì`÷²>E[=} ‚6-±íü{ &88Xu !Di1ƒgŸ}¶ä¾y3L›¦M»û°NgµÙ»RS¡sgÕI„ø›½ <º ö°µ ¤ü¥:‘y[;zCÕ'¡Íb°³WH§¶¢€µHñ‘ŸÑÀ|´®Xã°Å–!„>H¢gÉÉðÒKЩŒ§:MÞΟ×öµk«Í!Ä?¹úBÇ-–¿t€;gT'2?¿‚} ZOxä`'Ù¹Û…¶²y0ÚÌO.jãX…ahÓÏÞSœEa«¤Ñ³O>‹á‹/ÀNÇ?ª ´®a²~…У2u¡óvÈLM­áú~Õ‰ŠÎ˜{GÀž¡Pg(´ýìu8&LN=ѯ,¸P¬Õ|L¾SEa“t|Uk©©©Œ?ž*UªàææFëÖ­ùå—û§œþøc>ùä^|ñE¶nÝJÍš5yóÍ7sž·jÕ*>úè#FÍW_}EõêÕï)P,.* ÂÂ`ÊëèÖ$ˆ°îÐn¥6cÔ©ÿ@xs¸ú‡êTyKü¶v‚ˆ¡úSðx,Tj¯:žžž8;;ãéé©:Ê?LF›éj)ÐHqkçŒ6vÆx P|cNa3lºY¹r% ú÷ÝBggg† ÂîÝ»¹páIIIT¬X1ç9•*UâÎ…wF?þüüàÿþO]†!ˆ°&Ô}B€£üÜv „;gU'û[F2ÄNƒ áöixìghý-8ëçn~hh()))„††ªŽr—]hÈ$´™¯Dñù?ÑÈ t!„¹ØtràÀêÕ«‡Ç?Ç{8k:Ûì|Û´iÃÔ©S‰‹‹cõêÕlÙ²%ç9wü8¬Xãǃƒôï6µò%½¼ àÝwßU£t)Sºþ­¾‚Ë[a]=80’âÕeJЇƒïÂÕáà¨;? ¾]Ôe²IÀó@ð¶â,¶¦9ðo`&ð»â,E÷î»ï :†_ˆðâÅ‹øúúÞ÷ýìïÅÇk¯¾ú*k×®Åßß;;;æÌ™CUÔÓ§C¥JðÜsjÎÿ ®\Œ i)¦ÄÄDìô<Ó™­²³‡:/BÍgàÈ4ˆ›q3¡F_¨? ¼ƒ,“ãê8:Î.×Ö/©ý<Ô{U›ÁKÒ{ÀY´q²&ŠùEëŽõ<¸ªSƒAVBB'lºINNÆÙùþ©]\\rpwwgçÎDGGS±bÅ\‹‹¸s–-Ó »XÉ|õYÝØ¤)žÔÔTœœd:Ue= Édh0N~ Ç>ƒŸ[C™Pí)¨Ö *‚ÁLE¢É×öÀùµpa-ÜŒÚÐ|ºV|8y™ç<¥Æ.´u+¦ g±UöhSò6C+ö>Uš¦(œIMMUC ®®®¹~ؤ¤¤ä<žÍÎÎŽ&MšX,[®Ö¬Û·að`µ9„ f‘žžŽ£££êÂÉ ŒÖZ.ý gWÀ‰¯ öcmQà ­µB¤üÃP¶1¸T*¸(1fBÊ%¸q®ïƒë‘pímevç På húTé!«™I0­ëÕÅYl]´®Xãh]³¬‡££#éééªc!°ñÄ××7§›ÕÝ.^¼`¶nVGŽ´–ÿ|Ÿ›SÝgÞ<|ƒ‚ðÍgEñäääœóå¥aÆ÷WÿtñâÅœ¿ƒÜ<Ðûؽ[[$ñüym,H__ß|[’t÷>ò`©÷‘žžÎÅ‹s]ƒÆšÞ‡­ü<´÷áN#¡æ+ZñpuÄÆà’ü3þ>Y“T´ÂĵŠ6 ÝÎ0{ò)I rÒ®iSé8–2 ñ­ó ¾íú‚w›\‹kùy˜ûxEûùþÄK€ƒºø{±íÿoc€¯·IN^mUïÃÞÞ£ÑxßãÖýóø›¼¿•ôû((Ÿ(“ {ã7L¦[·nÝóý)S¦˜ ƒéüùóÅ:~dd¤ ÈÙìííM>>>&ÓÈ‘#s}¿¿ÿ=¯ùç6ñÉ'ó=gttt¾¯LÑÑÑùcâĉù¾Þßß¿À÷^àû˜8QÞ‡¼Û} GL¦³a&Ó±ù&SÔ»&ÓîçM¦ßú˜L¿ö4™~}ÊäïWÆ:ÞG úyØìÏWÞGïc…ÉdÂýU½éÓ§›¼¼¼î{½õÿ<ä}¨x€)22²ÀãˆÜL¦ì[s¶gÏž=´nÝšéÓ§3nÜ8@ëkߨQ#*V¬Èï¿o6ýû÷Ó²eK–,YBÆ ‹WQ¯Yÿþ7¾11øæs ÝÝøà8u /¾çq[¸Ã–{õë×ç¹çžã¹\&°¦÷a+?yý·€ü˜‡68º: ¿[ùùæý>L@+’“áÈ‘h‹æNOïã“O>á“O>áúõë÷ãòå˪£+gÖë¿Rʦǀüç?ÿá½÷Þã¿ÿý/7nÜ iÓ¦¬_¿¾ØÅ‡Y°e ¼ø¢ê$.>:tPÂêÍ›7 döa=IMMU8­é"àð¾¢ó—v€Ç€éXKÒ³gOêׯ¯:†‚RP€8;;3mÚ4¦M›¦:JÞ¢£µõ4:wVäÁÉ*èfÑ·o_Õ„°"F´V¾€¢iÓðÐ Øèÿ.pãÆiܸ±êBl|%t«±s§¶êyÛ¶ª“<˜äd¸qC !„…mNÃU)垪!]à„J =ˆ…zõ¬gñÁl²ˆB‰ù@S ê ¥œð2°mLŽBŽ z ªS<8)@„wXÖú‘÷ìKÂR^ÒÅ=Q!rH¢±±PÀtpº$ˆÂâVŽÀÕA•Ç媃!¬ˆ ª]¿—/Cƪ“<¸  Lm^!„°ˆµh30yª"rôv©"„°R€¨–ÝŠP³¦ÚE!3` QjL€E»Þ~ž´à9EÁÏÚÿ¤4…ÂzH¢Ú_YwŒ*VT›£(¤1›+W®ðÃ?””¤:Š…Ò¬Y3¶oßN³fÍ,xÖp mö%¡•Ð&X«:Hž’’’øá‡¸råŠê(B¤1‹Ý»wÿ FcñaiR€˜ÍñãÇyæ™g8yò¤ê(BèØZ %ÚÔ¯B_BŸÕAruòäIžyæŽ?®:Š)@ÌbñâbÌþQ§Ž¶ÿóOó„±$)@̦Fœ9sFq!ôl'Úø¡?$à€ê ¹ÊþlÍþ¬B¨%ˆüYœâ¡Z5mý#GÌÈŒFˆ—ÄL|}}qrrâÔ©Sª£¡S— @ ê "W' Ru\V©’ê$6ÃßߟӧOsçÎÕQ„(Ðõë×ùñǹ~ýº…Îx °äš#âÁ5B›&Y_³ùݹs‡Ó§Oãïï¯:Š"‹ fмys"""HMM-Ú*VظѼÁJÒ… P¹²V„³hܸ1^^^œ={Vu! ÎSO=Exx¸…ÎH‹«¾eð¾¨4Å?={///7n¬:Š"‹ƒê¶ 00€€.^¼ˆŸŸ_ÑÒ«|þ9¤¥““Yó•™‚×ìZ¶lÉõë×1¤‹‰÷ºÜ|Uùªœµ/â¤,%¤aÆ\¿~“5³ÂÆI ˆ4hЀ}ûö½øèÓ`Û6³å*QR€˜Á`âCˆ\eßQ—)TõÍm¢}µ€€öù*3` ¡ò¿Q/š6…‡‚•+U')œ[· lYÕ)„¥Bö­´€è_ôX€!ôE ½0´V°0(êXKrt„ôtÕ)„¥ÂÕ¬}E¥)DaT®¨!„Ð9)@ôä¹çàÚ5X¾\u’‚99iãU„¢ÄeßìpVšB†ÿ¼„"wR€èIƒе+Ì™£ÿE ¥Da1Y{™7EÿDQ)@ôfÔ(ˆŒ„?þP$öö‘Qðó„B!„¸‹ zÓ½;Ô©£µ‚èÙíÛàá¡:…ÍJKK#33Su !òš5k ±ÀÙ²[>䦇þeŽªC™™IštB—¤1³+W®°²83YÙÙÁر°bDG›/˜¹%&‚§§ê6)..ŽråʱgÏÕQ„ÈSùòåéÙ³'åË—·ÀÙ²/h­`‚ŽR/ ½ {öì¡\¹rÄÅÅ©Ž"„ø)@ÌlÆ ôíÛ—Ó§Oý C†@­ZðöÛfËevR€”˜:uêàèèÈæÍ›UGB'¼³ö2»’þ]A/³•mÞ¼GGGêÔ©£:Šâ¤1³Þ½{ãááÁ·ß~[ôƒ89Á”)°nìØa¾pæ$H‰qpp S§NlܸQu!t"{ýY_Bÿâшé°Ë IDATËz-7n¤S§N88ÈäBè fæááÁ€øæ›oÈ(Î í¾}¡eKxóM}Έ%H‰êÑ£\½zµà' aó²/h㕦In ‡äêÕ«DDDУGÕQ„¹¤¼òÊ+œ?žõë×ý vv0mš6VqZSJ‚Ѩ B—¤ÄôèÑ£ÑHxx¸ê(Bè€;PiÑ»KYû*JS„‡‡c4¥B§¤)-Z´ ((ˆyóæï@;³ÏjƒÒ/\0O8s¸sGÛKRb|}}iÕªkÖ¬QE¨èèsPä"»…J} Èš5khÕª¾¾ê³!î'H 5j[¶láðáÃÅ;ЬYàæ/¿¬Ÿ®XW²‚–+§6‡ëÕ«7n$))Iu!t £:„ÈW4`ÔVš"))‰7Ò«W/¥9„y“¤„ôéÓ‡jÕª1cÆŒâ¨\9X°~ú þû_ó„+®ìéÔæ°q½{÷&))‰]»v©Ž"Ä}¢¢¢èСQQQ:cK ÐÉ‘‹HÀpSšb×®]$%%Ñ»wo¥9„y“©!Jˆ££#3fÌÀÅÅ¥ø …Áƒaøpm`ºê ÿǵ¨jUµ9l\ݺu9{ö,Õ«WWEˆûÄÄÄð믿C³fÍ,pÆ@´ΧZ8Ÿxp‘h…¢Z]ºt‘ÏN!tN Ô¯_?ólþ|8pzõ‚={ lYóûA:Mš€Á .C)!¿@…È–}a»)@ô(8<§8‡F>;…Ð7é‚e-<< ,L1h6•*ÙˆBXŒP­ú ¤£‡!„þIbMêÔᅦ `Â5’“áØ1hÜXÍù…¥X;`‹ê"W¿ ýh®:ˆ HbmBB`Æ m©S-þ#G´ÖiBX\(Ú8ƒóªƒˆû¬ºf÷(„°y2Ä£-øÎ;Ú½£G[îÜ7‚««´€!A›æu=ðŠâ,âo»Eªƒ!¬„ ÖêÝwµÇŒgg6¬äÏi2ÁâÅл·Vø!„E•Ö!ˆžü”µ\i !„õ.X”‘‘AXX&s,(h0ÀGÁ¨QÚô¼“'—üB…ü¡ÿxî¹’=ÈU||<±±±ªc€§§'ÎÎÎxzzZøÌ¡hã@-|^‘·6@%e bcc‰/ø‰B] Ú¾};O?ý4aaa<õÔSÅ? Á ­”^©’ÖëÐ!mÑBoïâ;7‹CõêðØc%s|‘¯gžy¶nݪ:Š„††’’’¢à̽qÀ2`¨‚ó‹{]BkùTiŠ‘#G’‘‘Áo¿ý¦4‡¢p¤Ä‚:uêD÷îÝ3f ÉÉÉæ9¨Áo¿ +W¶mÚØŒeËÌßrá‚¶ûóσü³QaذalÛ¶èì•è…(•ªOŸ#«¢ëÁ×€#𬲇fÛ¶m ³DWd!„YÈ•¤ æÌ™C||}´AäÚ5ë矡_?èÞ† 1Vñ@^~ùeœœœ˜;w®ê(B(d‡vÑ»¸¨8Ki6h ´P–`Μ9899ñòË/+Ë „xpR€(àêêÊ—_~ÉÎ;Y°`AÉœÄÑQ›¢÷ôim`ú¡CЦ¶šú›oBD¤§çþÚÌLؽºuƒ  øßÿÀÞ¾d²ŠB+[¶,/¿ü2Ÿþ97oÞTG…^<€Éªƒ”R[€mÀÊܼy“ùóçóÊ+¯P¶¬º.`Bˆ'ˆ":t`èС|õÕW%Ó ’ÍņÕV0߸:u‚テ֭µµ<5ÒZG„´Ö“rå´±$'NhÚÃå땎Œ7Ž””>ÿüsÕQ„PÈ ˜|³›©x@&à- è¥,żyóHMMe¬ŒMÂêÈ4¼ ͘1ƒÁ€%f•²·×Z3ºuƒùóaÏ­›Vt4= Ús<=µç<¢!òODo|}}™9s&M›6UEÅFs€÷€ÿ)ÎRš¬ö¡µ€”¥¦lÙ²øúú*Ë „(¹ºTÈÃÃC͉´â¢m[5çÅ6bÄÕD)·víZúõëÇòåË U”˜ Aë ÔRQŽÒ$xètPš¤]»v´k×Ni!DÑH,!„,11‘ÔÔTU¯Hþ/À­5$Sq–Ò`Z—73O%/„(U¤BaÅ€/´‹cQrŽ uw 4WœEaͤBaåÆïf^_IdÉžjÿVœEaí¤Baþ Ô@»H–®Xæ7Ø| ¸*Î"„°v2]gL&sæÌ¡cÇŽ4iÒDu!„2™LF233s¾¾{3™L¸¹¹áää”ç1’““¹q㦻/½ûëk×®Ýóü[·nÝ3Ä`0äì ŽŽŽT¨P!ßÜÉÉÉØÙÙa0°··Ïùº`nhÇíÑÆ'¼Wˆ×ˆÂ9Àß]¯dò!DñI¢3©©©|÷ÝwÌ›7½{÷R®\9Õ‘„HNNfÕªU 8°k"7&“‰˜˜RSSIKKËÙß½µiÓ†š5kæyŒ¨¨(/^Lzzú=[FFééédff–oŽ1cưqãF222ÈÌ̼gËÈÈ 44”E‹å{ ‡¦Ð^¾|9}ûöÍóñuëÖÑ¿ÿ|q·3f0yrÞ‹ï1Z´hA\\î]¨ìììøàƒxï½¼ ‹cÇ*Ò¥KìíßÇÞþ ¼°··ÇÁÁ!g[¶lµjÕÊóaaa¬[·GGÇû6'''|}}:th¾ïã÷ß'-- gggœœœpvvÎùÚÅÅOOOÜÜÜò=†~\zPÙõÊd2±téRúô郋‹‹²BóDg\\\X½z5 8uëÖa/+‹lÛ¶ÁƒãééIÏž=UÇ)’´´4®_¿Î;wHJJ"))‰äää{öƒ Ê·ÀúôÓOÙ¶m)))¤¤¤œœLjjjΟ»wï^à…{ãÆó}|Ù²eù —/_fÓ¦M9­÷\Ä:88`4ó]ÿ§iÓ¦ °··¿gspp aÆùf4 |óÍ7¹¶$dïÛ´i“ï1Ú·oÏO?ýtOKÆÝ¶mÛÆ´iÓrþ>iÒ$Þÿý<?~ü8ýû÷ÇÕÕ\\\îûúÝwßÅÇÇ'Ïcœ>}šË—/ãææ†››îîî9_Tœþ-xHÖ ²ëÕÚµk>}útvíÚ•s¡öÏ­Q£FôéÓ'ßsDDDäÜíξ{½wttÄÍÍMn  µôŒ=šÙ³gÓ¬Y3Õqþá6ÚÀôD`/×/s»páwîÜÉi5»»E-55•zõêQ¿~ý<_îÜ9¦L™’S8ß]Pg½nÝ:jÔ¨‘ç1Þzë->ùä“\stt$((ˆ;väó.LLŸDRÒ~<=Gàဇ‡xzzâá៟+V,ì_K‘%''@½zõ—V^¡\I^ÿ•R€CIÿœ5kcÇŽå»ï¾ãÙgŸ5ûñ…m9zô(7æí·ßæƒ>x ×®_¿ž?þøƒ›7orëÖ-nݺÅÍ›7ILLäÖ­[´nݚŋç{ www’““qwwÇÓÓww÷œ www^ýu:wîœçë/]ºÄ¾}ûpuu͹S›½eÏÙÙY.>D!F[#$mŒHéñ×_qñâÅ{Zïn]ôòòbРAùa>:ž?ÿ,KbbwîÜៗ Ó§Oçõ×_ÏóGå­·Þ¢L™2”)S//¯{öeË–¥C‡Þ0™8q"}ô‡ηpÂR¤)>é‚¥c£G&&&†—^z ???‚ƒƒUG:tîÜ9–.]Ê7`òäÉlÞ¼™´´4nܸABBÇÏw<ÑöíÛY±bEÎ…A™2e¨T©uêÔ¡L™24jÔ¨ÀW®\ÁÕÕµÈBåÊ•yâ‰'ŠôZ!îç‡Öm¨+Ð X äÝzfk*UªD¥J•ŠøêyÀx~ûíàC@keMJJÊiá¼}ûv¾]À222HMMåĉ975²opF@»ñ_2iÒ$þýïÓ¬Y3¾ùæÊ•+GùòåsöÕªU“¢D+$- Å`‰ 8--bbb8yò¤ \…µwï^.]ºÄÕ«Ws¶k×®åì‡ ÆÿýßÿåùúˆˆBBB(_¾iÑ9'''V­ZÅáÇ¥øÐ¹ÔÔT._¾œ³ýõ×_ØÛÛØ}nÀ€œ8qÐÑz{{S¡B*T¨€ŸŸåË—Ï÷õAAA\¿~=çÏ?ÿü3ݺu£mÛ¶<ÿüóÅcBXµŽh­=P´Vù,ÍÝ,´Âc%U|€6¡§§g7E¾ûî;Ž?ΦM›èÚµkÎ÷F#7oÞäÆžËd2ñý÷ßsùòenÞ¼yß㎎Ž,Y²„~ýúåyŒ[·n‘€O¾cЄ…'- Å °øöÛo™6m—.]"!!á¾Ç[´hAddd¾Ç8qâîîîT¨PGGG³äú׿þÅùóçÙ²e‹ÜÝ€íÀhcB€ªJÓèK0m±Á·ÐÖQQû¹a2™èÔ©ÕªUã?ÿùYŽ™žžÎµk׸rå W¯^åÊ•+\¹r…®]»R·nÝ<_·dÉ @Ù²e©\¹2•+WÆ××—Ê•+S¥JÆ'Ÿµ¥ˆ\ÿŸ Å ÿ­›ÑhäòåËœ;wŽóçÏsþüy.\¸³¿páßÿ=?üpžÇøå—_øé§Ÿ¨\¹2>>>9{*V¬h¶‚âA%&&âââ¢ìüBèS$ZKˆ­%¤•Ú8º<üÌ^Cuñ‘-==””åÝG/_¾Ì¸té—/_æÒ¥K9ÛÅ‹IOOÏiÅÎË·ß~Kbb"ÕªU£ZµjT¯^Ÿ|§ãú%×Å']°„ÍÊÌÌÌwºÔ[·nQ¥J•œ?;;;SµjÕœ-00°À… ;wîœïÌNª¨þ…-„>µö¡­mñ(ð0Xi"µŽ¢uK»lôõY–½vŽj>>>tïÞ½XÇX½z5›7o&555ç{T­Z•5j0dÈ™íR”*R€«•––Æ™3g8yò$'OžäôéÓœ:uŠS§Nqúôi:tèÀŠ+ò|½——ëÖ­£jÕªT«V oooiB¢®_¿ÎŽ;hß¾}ã”ô¥2° ü ˆ>ÜU†²0ðð ZW´=@¥‰lݺuë0™L\½z5§Åýܹsœ;w޳gÏâää”ïëããã™3g~~~Ô®]›ÚµkS³fÍ_'„^Ibå®]»F¹råJe3îðáÃsVµ¶··§FÔªU‹&MšÐ³gÏWM6 2í«EΠAƒX²d Tç9‹ÐZDÞ@»ûÿ Z«ˆ­»ŒV|…ýÐZÊ(MTZ *V¬HÅŠiÞ¼ù½6>>ž+VpöìY233°³³£zõê<ôÐCÔ©S‡éÓ§S¦Œü,…uÄŠ¥¤¤ÐºukºtéÂçŸnµwïM&çÏŸ'..Ž£Gælß~û-U«æ=PtäÈ‘ 0€ÚµkS½zu䟳¢° À´uBž‚ÑÆ?LÅ6[CLÀÿ€‘€=°è£4‘(¼ÀÀ@NžO vmv«p´Vy@E¥‰DÑ888P«V-jÕªE§Nèµ#GŽä—_~ÁÃÆ âï5jÔˆ5jXÍ5„°~R€X¹!C†ðÒK/‘‘‘Á‚ tñ’žžžïàAŽ=J@@}úô¡aÆ4hЀZµjIKF ÉÈÈ`öìÙ :Tšé…¸‡=0mšÞqÀ@`:ðÐ ½Ì õàNïß«ÑV…×—[·nñå—_2zôhùü/A_~ù%ÑÑÑ9r„#GŽËêÕ«ILLà7Þ`Ú´iŠSŠÒBþ§Û€!C†`ooÏ /¼@jj*‹-²Ø‡¸Éd">>žýû÷³ÿ~8@TTüôÓOy¾ÎÙٙݻw[$£Ðœ?žÉ“'³oß>–-[&MðBܧ.Z È.´ƒ´®Yïa=…È)´EÞh«›¿¨ŸQêŸL&C‡eÆ ôéÓ???Õ‘lVvËÉ“O>™ó=“ÉĹs爉‰¡Zµjù¾þ¯¿þ"""‚-ZP¥Jù"ŠE ñÜsÏáììÌàÁƒIJJbéÒ¥%:;ÆúõëY°`ûöíãòåËT¨PæÍ›Ó·o_ÚµkWbçEãççÇ¢E‹èׯ>ú(ÇWIzø Ø€Ö-«ÐŽ6s–—ºhyÊ6óÑr{“ÐV5×ïÊï_|ñ?üðË—/—âCƒÁ@5¨Q£FÏýí·ßèÛ·/ MMH`` ­Zµ¢U«Vx{{—t\aC¤±! ÀÝÝ~ýú1iÒ$¦L™RbçJLL$##ƒ_|‘–-[Ò²eKªW¯.wDt®oß¾Œ9’1cÆÐ²eK‚‚‚TGB§ Àã@´1"ó±h-#ƒ€@;Ôÿ=¬B›ÍêÐ<ëëgÐû`úˆˆFÍ«¯¾šsa+ô«wïÞœ9s†ÈÈH"##Ù·oóæÍãÚµk4mÚ”Èu€(ÕŸœÂÌBCCÙºu+5zà×Þ¹s‡?þøƒ;vн{wZ·nçs À€ŠU(2cÆ öíÛGŸ>}ˆŒŒ¤R¥Jª# ¡c CÖ|vÿ%P­@ E+b‰–‘L`7ZW±µh‹ º  ._†¶º»þ/ÿúë/úôéCË–-ùôÓOUÇ…pwkI¯^ÚX"“ÉÄ©S§ˆˆˆàêÕ«R|ˆB“ĵmÛ¶PÏKIIá÷ßgëÖ­lÛ¶½{÷’žžNùòåñóóË·ÖËÉɉ•+WÒ²eKúõëÇæÍ›u±Ú°°.!!!¬Y³†öíÛ«ŽbAUÐÆƒ¼ DëЊ€¥h¿N›hë‹´¡­9RT&´VÈ»¶}@P x˜†¶‚¹~»YýSzz:ýúõ#==•+WÊbzVÌ`0ä,ŒX£ÑH= ¤cÇŽ´mÛ ¤z$H)5bÄ-ZDjj*ÞÞÞtèÐY³fŒ¿¿¿.fÒ%§jÕª¬\¹’Ç{ŒñãÇ3sæLÕ‘„•)_¾<={öTC;àá¬m2pmÜÅ´Ö‰Eh-Ž@ À7k«’µ/›õ˜CÖó2€$àbÖŸµ?ÜÌ:g5´¢f,Э¥Ã:?§ÇŸsó+¿µž„m¹yó&žžž,\¸)S¦àììLûöíéÒ¥ ݺu£I“&Ò‚RŠHRJR§N:uêD£F¤à(…ÚµkÇâÅ‹‹Ô]Oq·šh«‹ËúsÚÚûÓü]TDgíoÞ\€Êü]¤4ª¢µª´Dkñ° Ï>û,2YI)S®\9V¬XÑh$::š-[¶°yóf&MšÄøñãñõõ%22___ÕQ…L&“Iukµÿ~Z¶lIdd$-Z´PG!„Õ0¢µ|Ø£µdÈ_Q:¥¦¦²sçNvîÜÉûï¿o­ rýW|ÒRÊÌ™3‡“'O2cÆ YðI!”±dìƒÎÎÎtêÔéWvÖMúÝ”2NNN|þùç<ñÄ$$$¨Ž#„B!J)@J™aƱqãFöìÙCPPqqqª# !„BˆRD R¨sçÎìÙ³ZµjÅÚµkUGB!„¥„ ¥T:uøã?èܹ3={öä½÷Þ#33Su,¡Œ5 £Ñ¨:ŠÐ©¨¨(:tè@TT”ê(B‡ŒF#£F"""Bu!„IRŠyzz²råJ¦NÊ´iÓ8xð êHB'NŸ>ÍgŸ}Ƹqã‰òDnbbbøõ×_‰‰‰QEèŒÉdbܸq|öÙgœ>}Zu!„É4H¥œ&L`ðàÁT«VMu¡ýû÷çÚµkŒ1‚²eË2qâDÕ‘„VbòäÉÌž=›ùóçÓ¿Õq„:$ˆâCÜgøðá$$$ðÎ;ïàééÉØ±cUGBèÜÌ™3ùàƒ˜:u*Æ +øBˆRI !Dž&L˜ÀíÛ·7n... >\u$!„NÍŸ?ŸqãÆ1aÂ&L˜ :ŽBǤBäÉ`00eÊ’““1b :Tu,!„Î|ùå—Œ1‚Ñ£G3eÊÕq„:'ƒÐEâââxûí·IKKSE(`0˜9s&#GŽd÷îÝ2(]q“ÉÄîÝ»9r$3gÎÄ`0¨Ž$„Ð9iÚ·oŸ~ú)ááá,]ºÕ‘„… æÎ‹Ñh”‹ !Ä= _ý5vvvòù „(i4h¤¦¦Ò¢E fÍš%ëC”Bƒ{{{Õ1„Nxzzâì쌧§§ê(Bìíí¥øBš ¢Pš7oNdd$Æ cìØ±tìØ‘S§N©Ž%„P$44”””BCCUGBae¤…æêêʬY³Øºu+§OŸ¦qãÆ,\¸Pu,!„BaE¤ì±Çãðáà 4ˆcÇŽ©Ž#tÀh4’™™©:†¢effJ÷[!„YÈ tQ$žžž,X°@fDŒ3†øøxþûßÿâââ¢:ŽÂÌRRR4hÕªUcöìÙªã!¬œ´€ˆb‘A‡ cÇŽ¬_¿žTÇB˜QBB!!!üôÓOtìØQu!„ DQl={ödóæÍ 99Yu,QÂ|}}ùõ×_騱#ƒ âæÍ›ª#‰°víZ\\\X»v­ê(ÂÌnÞ¼ÉÀ騱#¿ýö¾¾¾ª# !lŒ ¢Ä z÷îÍ‘#G3f S§N¥aƬZµJfϲq¬^½š;vàåå¥:Ž(‰‰‰¤¦¦’˜˜¨:Š03///vîÜÉêÕ«qwwWGaƒ¤%ÎÝÝ©S§C£FèÓ§]»v%##Cu4Q‚ìíí PCQØÛÛ«Ž!„°Q²ˆ°˜ºuë²~ýzÂÃÃ9pàòÏO!„¢´‘+@aq!!!„„„¨Ž!„B!.XB%bccIKKSCˆR)--#GލŽ!„(¥¤º+ÕmXjj*]»v%88˜sçΩŽ#D©rîÜ9‚ƒƒéÒ¥ ©©©ªã!J!)@„î\ºt‰æÍ›Ó®];~ûí7ÕqD pvvfÕªU\¸pæÍ›®:’¥Bxx8Í›7çÂ… ¬Zµ gggÕ‘„¥ Bw|||X·n)))Ó½{wöîÝ«:–0³   öïßOPP=zô`„ ¤§§«Ž% )^}ü IDAT €àà`™éÌJ¤§§3aÂzôèAPP ((Hu,!D)%ˆÐƒÁ@×®]Ù·o+V¬àìÙ³´jÕŠž={rðàAÕñ„y{{³nÝ:>þøc¦OŸNpp0gΜQKB³fÍØ¾};Íš5SEàÌ™33}út>þøcÖ­[G… TÇB”b2 –Ð-ƒÁ@Ÿ>}èÕ«ßÿ=“&M¢Y³fLž<™÷Þ{Ou‘½½½l6›ìììd³Ù _’® [·nÕÌ™3•——§üüü"ÍÍÍU@@Àu¤oß¾Ú¹sç5¿>räH½ÿþû×üzjjª^{í5U­ZUÕªU“‹‹‹ªU«¦êÕ«ËÅÅEÕ«W×ý÷ß/—bç(üüü4fÌõíÛW®®®V’$[·ºe[¶lQ«V­´yófµlÙÒêq”Û·o×G}¤“'O*33S'OžÔ©S§têÔ)eeeIúã.`ŽŽŽ×ÜÇo¼¡5kÖ¨ZµjªZµj‘WåʕբE =óÌ3ÅÎ/GGG9::ÊÉÉ©ðïäàà ggçRû¤ëƒ*++K999ÊÉÉÑ… мš4iRl`%''«_¿~:{ölá+++KYYY…Ÿà$$$¨Q£F×ÜÇœ9sôÃ?ÈÍÍMîîîrww—‡‡Gá«N: *ñcPúñþïöñ üÉ/¿ü¢””¥¦¦*--Miii:~ü¸ÒÒÒ”žž®÷Þ{Oýë_¯¹ý¹sç´gϹ¹¹ÉÇÇGÁÁÁrss“«««jÔ¨!WW×ëž>4iÒ¤Û>ŽÐÐÐÛÞ‡U4hp[ÛûùùiݺuW,/((Pvv¶Îœ9#//¯b÷a³Ù”““£={ö(33³ð•ŸŸ/IjÕª•âãã‹ÝǼyóäää¤ÚµkËÛÛ[µk×VåÊ•où¸ ¼ @P®œ;wNO>ù¤ú÷ï¯'Ÿ|²Ôþ„æèÔ©S:tèrrrÔºuëb×ïÖ­›RSSU©R%Õ¬YSµjÕR­Zµ¨ûî»OþþþÅnߦMÅÅÅ•ä! „Øl6U«VMÕªU»îº}úô¹âT±üü|>}Z7tǶ#F(--­È2WWWÕ­[WuêÔÑ+¯¼¢‡~øæÊåJzzº.]º¤ž={* @¯¾úªž}öYU©RÅêÑP233õÙgŸiøðáW=…iË–-Zµj•’““•œœ¬ßÿ]‡Rvv¶¤?n»k×®b¿Çúõëåêê*wwwÙÙq£@üvvvrss»î5<—¥¤¤(33S©©©:v옎;¦””¥¤¤èèÑ£×ýÉåëiüüüäçç§ Èßß_…Ÿ¢]¼xQ~ø¡  ww÷Û>F0A¹R¿~}­Y³Fñññš2eІ ¢Ñ£G+**JƒV­Zµ¬·   @iiiZ»v­Þ|óMÅÄÄhÖ¬YjÕªU‘õÖ­[§ &ÈÏÏOõë××C=¤zõê©^½zòõõ½¡‹ÛïÔa”+™™™Z¿~½ÚµkÇßk°³³“§§§<==Õ´iÓ›Þ>==]qqqš7ožNŸ>]¸¼zõêò÷÷————RSS• ÀÀ@=ùä“%9>Ü1\„~¸©ôKJJÒ‡~¨Y³féÒ¥K5j·ð-Årss•””¤„„%$$(11Q‰‰‰Ú»w¯Îœ9£eË–©víÚzî¹ç´k×.½úê«z÷Ýw Ï«ÏËËã´;CbbbÔ§OÍ;W½{÷¶zœrïäÉ“:xð ’’’”˜˜¨ï¾ûN;vìP³fÍôÅ_\ó¢ü_~ùEîîîò÷÷W¥JüÌ( ¼ÿ»}üi„rÍßß_ü±Þ{ï=Íœ9SV„kÈÍÍ•›››Îž=+éså6l¨&Mš¨{÷î RXX˜<==µiÓ&M™2EcÆŒÑ÷߯3f(""‚ø@¹uùÔ¯“'OjöìÙ:räˆÆ§×_]×Ü.22Rû÷ï—“““6l¨¦M›ªY³f VóæÍåííÍ3UG€ BpssÓo¼aõRAA’’’tìØ1µmÛöšëUªTIŸ|ò‰êÖ­«Æ«víÚ×|cäàà 7ß|SÝ»w׋/¾¨|P‘‘‘š9s¦œïÔ¡–¹pႨ9sæèÐÒ¥Koè6À±±±JHHÐîÝ»µk×.íܹS?þøcaèO:Uƒ ºÓã@ð''Ož¼á Lquúå—_ô믿ê·ß~Ó¦M›”™™)ooo¥¤¤»mß¾}oê{iíÚµúâ‹/´zõj999ÝÎè@©åää¤ÜÜ\}þùçzî¹çnøS oooy{{+""¢pY~~¾’““µ}ûv…„„»}FF†$ÉÃÃãÖ‡€ÿA€ÿUPP ¶mÛªJ•*4hž~úiU­ZÕê±ÊŒ5kÖhðàÁÚ»w¯$ÉËËK­[·ÖË/¿¬ÐÐÐ;ö\ ›Í¦çŸ^Ï?ÿüÙ?PØl6}õÕW%²/;;;ùûû_÷–Ò’ôé§ŸjäÈ‘ Ò}÷ݧvíÚ©]»v àÔ-·Œþ«  @&LдiÓ4`À1B‘‘‘8p š5kfõx¥^:uÔ±cG=ZmÚ´Qƒ xƒ”q‘‘‘òõõÕÏ?ÿ¬7jöìÙ*((P:uÔ¾}{uëÖMO=õ”Õc(c¸É=ð_vvvêÚµ«–/_®¤¤$ 2Dßÿ½š7o®Ö­[ëÓO?UNNŽÕcwöìY-Z´H+W®,v½FiêÔ©êÝ»·üýý‰ ¨[·®z÷î­©S§jÛ¶mÊÌÌÔ’%KÔ»woýç?ÿÑŠ+¬@D€Wáçç§ñãÇëСCúá‡äåå¥Q£FY=–1‡Rtt´:uê$=þøãúòË/­ë–>}ZZµj•Õ£WµjÕ*EDDèÌ™3VR,WWW=ú裚µó²*Uª¨gÏžZ°`Ž;¦?þX©©©Ú¸q£Õ£°€­   Àê!ʪ-[¶¨U«VÚ¼y³Z¶liõ8(EvìØ¡˜˜Í›7O‡–FŒQx]…I‰‰‰š2eŠâââ´sçNÙÛÛŸ¡4;räˆêÔ©#;;~ƒ;/??_)))òññ±z”R!77W•*ñD”-¼ÿ»}ü¸š5k¦I“&)99Y6lÐã?nü î®]»Ô³gO5nÜX?ýô“úõëWæN 3ÁÇLJø€1vvvÄÇŸ@ÅÄï|ಳ³Sxx¸ÂÃÃ}ÏÇkÔ¨Qš3gŽêׯ¯3f¨oß¾â4;áòésD nÿ½”¬>úHO>ù¤|}}­@ âOH ”øî»ï¥U«VÝò'|ð‚‚‚ôÓO?)::Z{÷îÕ /¼@|܆yóæ)$$Dß~ûm©¸–¥S~~¾¾ýö[…„„è믿¶zœráĉš0a‚‚‚‚4vìØ ù X ¼"@€RâôéÓZ¶l™:uꤚ5kªOŸ>úöÛooêÖ¾U«VÕСCµÿ~EEEÉÑÑñN\1Ü}÷ݪ]»¶zö쩦M›jîܹÊÍ͵z,ËmÛ¶MíÛ·×¶mÛ¬ÅR¹¹¹š;w®š6mªž={ªvíں뮻¬«\ðôôÔ¾}û4tèP3FÍ›7ç¢u œ @€R¢ÿþ:xð ¶lÙ¢aÆiçÎêÙ³§¼¼¼Ô¹sg-Y²äºûxñÅ5iÒ$¹¸¸˜¸b ÓÊ•+'EFF*((H3fÌÐ… ¬Ï2»wïÖ¿ÿýoíÞ½ÛêQ,qáÂ͘1CAAAŠŒŒ”¿¿¿âââ´råJ………Y=^¹áââ¢I“&iÛ¶mruuU»víôöÛoóC Œ#@€RÄf³©E‹zï½÷´}ûv!±@AAòòò¬7)77W<£·t#>€²ßÁ@9¡Ù³gëèÑ£Ú±c‡Æ/{{{½óÎ;jÙ²¥FŒaõˆÎÏ?ÿ,Mž<™óÕË€ŒŒ Mž>>zþùçµyóf«ÇÂÿˆ×óÏ?/=Z:t§§§Õc@¹E€åœ“““Ú·o¯àààb×[±b…zõꥩS§jÇŽœ²U‚‚‚4{öl9rDo¿ý¶Ö¬Y£ÐÐPµnÝZ_|ñ…Î;gõˆ·ÌÅÅENNNeö–ÏçÎÓ_|¡Ö­[+,,LkÖ¬ÑÛo¿­#GŽhöìÙ ²zD(·’¤‹/êСC>|¸š7o.=öØcš0a‚bccËô›e«yyyiäÈ‘JJJÒ?þ(wwwõïß_cÇŽµz´[ÖµkW]¸pA]»vµz”[2vìXõïß_îîîúñÇ•””¤‘#GÊËËËêѠܳp¥Ý-Û²e‹Zµj¥Í›7«eË–V”ˆsçÎé×_Õ† ´aÃÅÅÅ)++KíÚµSll¬Õã•IIIª\¹²¼½½­¥BJIIÑ… äïïoõ(ÊÞÿÝ>nà  ˆ*Uª¨C‡êСƒ$)//O»víºî' ÊÊÊRõêÕMŒYæñÆ×ZuêÔ±z¨°Ų··WóæÍ¯»Þþýû¤   ………)44T¡¡¡ Q•*U LZþ 2DžžžŠŒŒT@@€Õã” М9stâÄ žÕ¥×€(žžžš5k–:vì¨ÄÄD½þúë —‹‹‹š6mªgŸ}–'ß„ËÏùàƒ¨ððpMŸ>Ûù^EFF†¦OŸ®ððpêƒ>P^^Ïò€RŠP"ÜÜÜÔ¯_?}òÉ'úí·ß”••¥Í›7kúôéjÛ¶­’““U­Z5«Ç,3l6›¦M›¦ÔÔT}õÕWªQ£†† "ooouéÒE_ýµÎŸ?oõ˜–9þ¼¾þúkuéÒEµk×Ö!CT£F }õÕWJMMÕ´iÓd³Ù¬p\„~¸ (Y]ºtQff¦‚ƒƒ¬¦M›ªI“&<“á¿ÒÒÒ4þ|ÅÄÄ(>>^GŽQíÚµ­ËÇŽ“ÂÂÂÔ»woõìÙSµjÕ²z,ïÿn×€(5:w¸8mܸQ³fÍÒ¥K—$I5kÖT“&M4|øð2{Û×’P«V- :TC‡Ujjj…IòööÖÑ£G+ô¯”Uœ‚ Ô2dˆbbb´cÇeggk÷îÝúæ›oôÒK/ÉÃÃCvvÅÿ‘•™™©;vTˆg–ÜÈïeË–)++ëŽ|ÿE‹ÉÙÙY‹-*ñ}geeiÙ²e×]ø€²‰O@”Jjܸ±7n|ÃÛ,[¶L‘‘‘’$ê®»îR@@€ ;5r©røða=úè£rttÔƒ>¨'žx¢ðz‰’••¥œœœ œÔÔT-^¼X .ÔêÕ« Œéëë["û”€r£k×®Ú°aƒöíÛWøŠ×7ß|£3gÎÈËËKÇ/v—.]’ƒƒƒ¡‰ï___œœœtþüù"Ëþñhß¾}JHHмyóîè1J>\áÂ… ŠŠŠÒ_þò}õÕW…ËüqÝu×]zë­·ôõ×_KúãZ‘‹/^s?•+W¾by@@ÀPêñ à ‰‰‰ÊÈÈP×®]‹,wssSxx¸~þùçÂeÞÞÞÊËËÓ‰'Ь{ñâEeffªN:Ff” à —.]’$ååå]õk^Þ¢E IÒ¦M›Š¬¯üüüÂg  €«hܸ±œœœ O³ºìÈ‘#Z¿~}atHRÇŽåîî®iÓ¦YwÚ´iªZµª}ôQ#3Ê®€ (::Z§N*¼CÕ¢E‹tèÐ!IÒ°aÃT½zu1B'NTDD„ºu리¬,M:U9999rdᾜ5vìX *W® @ïÞ½ñðð`øðáìÚµKïüR¥J±mÛ6ÝïÓÓÓ™5k?ÆÑÑ‘;wîðã?òÁ°zõjÝy&L`üøñ¯lKóæÍqss#!!=zäêý¤¦¦2zôh|||عs'ÖÖš‚^^^ôë×O/,_¾œˆˆöìÙCƒ tÇ«W¯Nÿþý9p྾¾¹j‡† °„ÙR©Tlß¾:è’@Ù²eéÑ£ûöíãÉ“'z?Ó¯_?½ß7jÔ•JÅõë׈ˆˆ@¥R1`À½óó&^pôèQâããéß¿¿.yôéÓ‡×^{MïÜU«Váé鉇‡÷îÝÓýÒõݹsg¾´Yˆ—‘ˆ0[ñññ$%%ááá‘áµ7ß|“ôôtnÞ¼‰§§§îøóßàJ–, Àƒt‰ä7ÞÈpžö\cÒÞÿ?ÿùÞqkkkªT©¢wìÒ¥Kœ?— ×Q(ÄÇǯ¡Bdƒ$Q XYYez<;oæesΗÕNT*U¶¯ñâýÓÓÓñööæÇÌôü *d¿B$a¶\\\(Z´(çÏŸÏðÚùóçQ*•9þ­T© ùv¯ý€¿ÿþ›„„„,þe‰BÛ{IHHÐëi{/ÞÿâÅ‹4iÒDw<55•èèh|||tÇÞxã Nž<‰ŸŸ_–í¤"Ì–••-Z´ ,,LïƒøÎ;,_¾œwÞy'Ç£ š7o޵µ5¿þú«ÞñÙ³ggëç‹+–i¢qww`÷îݺc*•ŠyóæéW§N\\\˜;w.©©©ºãÁÁÁ<|øPïÜ.]ºËüùó3Ü/))‰§OŸf«ÍB‹ô@„YX°`›7oÖ;¦P(?~<ááá4jÔˆ`eeÅo¿ýFjj*AAA9¾OéÒ¥;vìÈpÞ„ pqqÁËË‹ãÇçú:`¹±Æ# D8ñññLœ8‘ .P³fM ó½Ìcbbhܸ1W¯^eÊ”) 6ŒM›6áïﯷݬ9êÓ§?ýô½zõbÖ¬YXYYѦMöï߯;'44”Y³f1fÌ6lHûöíIJJÊñuÀ²c%ŒÈ´ûY ax)))ê;wî¨ÕjµúèÑ£j…B¡^¼xq†ó¾øâ u±bÅÔ7oÞÔÛ±c‡Z¡P¨çÍ›§;­V(v4•C‡© …zÆŒºcÉÉÉê7ÞxCÝ Aݱnݺé½___uxxxޝ£V[n¬„qID8¶¶¶”.]@oñ­^½švíÚQ¾|yݱfÍšQµjUBBBŒÞÎÜ ÅÚÚš~ýúéŽÙÙÙñÉ'ŸpàÀbccxúô)...ºsJ—.Mbbb¶¯£;n©±Æ% DJ±±±ÄÇÇS»ví ¯Õ©S‡ÈÈH½c™=3•ÈÈHªV­ŠƒƒƒÞñ:uêpâÄ |}}™}úйsgŠ-jê& ‘‰„…\ûöíY¿~½©›!,Ô±cǨU«–©›!LDH!–€k™2´|öŒ¶¦nŒ‰¬}÷]>ؽÛÔÍ0¹œÆa°ÍÖ–«×®eºS¡(äV!¶lÙ2RSSé 8›º1&òÙ_à$ $Çqp6¦¦²víZ `¼† ³&=BJ­Vã]­%ÏŸgb!þ+ð°ÖÔ0¹‰ÃX…‚‡žžœŒŠB¡P£YÂÌÉ(¬BêСCD;Ç{…8yˆ¼yO­æôÙ³>|ØÔM&" ¤š7o®ÖÖÔ6uC„Ū ¸Z[ëmH% I …PBB+–/§MZZ¡ÿ ÐÄÔ 0Mrñ3V@›´4V,_ÎÇ Ü"a ûçG¡´lÙ2ž={FS7Ä ü²p¡©›`r‡Öh¶Á]¶l™a$,‚$BF­V3wÎPxG^=ïþöí¦n‚YÈmJ¾ÀÜ9sñ8…ŒÂ*d<ˆ¯¯/A@]S7F‡€hþnÕ«WÏÔÍùHz …ŒÏ…¡I1½ð²¸"¦ÜÓÏKJñ\PnŠé‰‰‰Œ7ŽV­Záää„R©dñâÅ™ž{îÜ9Zµj…££#ÎÎÎôîÝ›{÷îésíÚ5”J%{öìÉëÛ1 jµšøøx~ÿýw¢¢¢tÇÌÅ}ŽÈ„¥ÜÓÏKשcꦘâ šº f!¯qÈi1=>>ž‰'ráÂjÖ¬ dþo;&&†ÆsõêU¦L™Â°aÃØ´iþþþ¤¦¦æ©Íæ(99™'N0aÂZ·nMïÞ½™9s&`žŸ}f½”Izz:J¥•JETTÛ¶mC­VS£F ªV­J•*UP*-.šÄóÅóácÇBûö¦n’Y¨0|8g$yŽÃóÅô/¾ø"Ë;777nß¾MéÒ¥9vìu^ò¥fòäÉ$%%Iùòå¨[·.þþþóÙgŸåºÍæBÛÛØ½{7¡¡¡„‡‡“˜˜H³fÍX¶lM›65u_ʬˆ69L™2…3f`kkK||<£GfôèѲ”t6igžŸvëÆrS7ÈLœëÖÍÔM0 †ˆÃ{j5#þ™™žU1ÝÖÖ–Ò¥K¯~4³zõjÚµk§KÍš5£jÕª„„„XtINNæüùó„……±víZN:E¥J•èׯ]ºtÁËË‹"EŠ˜º™¯d¶ D¥RaeeÅîÝ»™}ŠŸŸ#FŒÀÏÏ2eʘº‰ÙföÏfÍšEݺu>|8ÿùÏØ¿?...4oÞ[[[èÚµ+sdúKÉÌs‘ =3=.. Óåâ]]]¹ÿ¾®R¹reT*7Îó}mæÌ™tëÖ¿þú‹Aƒ±ÿ~Ö®]K÷îÝ-*y€'+++RRR¸uëo¼ñ†î/Ño¿ýFÇŽu]ÚØØX¼½½yðàÅ|Éo/Î}ú°yófN:¥;f‰àÍ&\¹r…¿ÿþ@ohîÇLïÞ½9r$ëׯ§bÅŠìÝ»—K—.1|øpBCCùïÿk”6õéÓ‡Ÿ~ú‰^½z1kÖ,¬¬¬hÓ¦ û÷ï×ʬY³3f 6¤}ûözÝêìŽwãŒyÏlæù­Ù³su­‚Hb¡aÈ8jfz¹råpqqáÈ‘#^;|ø°îß“%Wž>}J³fÍØµk½zõ¢G|ÿý÷DDDp÷î]llløê«¯ˆŠŠ"""‚aƱ|ùrNŸ>ÍСCqpp0x›BCC±¶¶¦_¿~ºcvvv|òÉ'8p@÷ýôéS\\\tç”.]šÄÄDÝï³;Þ²óžS²l»0•ìÓgϞͤI“XøÏRòëׯgÒ¤ILš4‰Gèæz5mÚ”Ù³g3eÊ:w·7}ûöÍ·b4ýû÷'--ˆˆºuëFÇŽiذ!S§NåþýûT¬X‘àà`®]»ÆÜ¹sô¾X›³[7$$„¹sç²k×.¼¼¼¨]»6M›6¥^½z¼ñÆæz¨Õj£Œ¾ò÷÷'..N·VDDþþþlذ¶mÛ2uêTÖ¬YÃ’%K8{ö,ü1.\ÀÍÍ-Ã5=Jݺu ¦wïÞz¯ÅÆÆR¡B‚‚‚6l˜Þk½zõbË–-ºo*×®]ÃÝÝ;w¾tØâ«ö<·÷ð éÂ…Ǥ ’Xh#Yí™þúë¯sýúuàßǺÚÏÑÑÑT¬X€³gÏ2tèPöíÛ‡mÛ¶eÆŒz_Ü,ÕãÇéß¿?6l k×®ýôSþ÷¿ÿñäÉ\\\puuåÁƒ’@^F©Tê ç{÷îå­·Þ¢xñ℆†røða.\ˆµµ5ãǧÿþ|óÍ7Ì;WWt7†¤¤¤l?/V¬ûöíãĉܼy“æú~`¸1ï¯Z¶ý²jF–Jb¡aŒ8È2ïY«P¡=¢bÅŠ¤¥¥‘žžN=(Z´(K–,àÈ‘#”)SggóÛÎ,Èóf̘A©R¥˜0a:t FôéÓ‡ƒ̽{÷˜?> --Íhí°··Ïöøs¥R‰··w¦½‡œÜ 3æ=«âyÊÍ›¹ngA#±Ð0FdÏô¬•-[–zõê±mÛ6Nž<‰R©ÄÓÓ“¶mÛ2eÊúöíËŸþÉ'Ÿ|BÉ’%MÝÜ Ì&XYY‘œœÌåË—)Uª€æ•J¥"--Þ½{Ó­[7 ÀÑ£G:íßÕÕU÷˜êyÚGM¹yL•Õýž¿þ‹÷Ìɘw)ž s!{¦gíÇÄÕÕ•Î;óË/¿0jÔ(.^¼Hll,ááá 0€O?ýTw¾9 ç5›’žžŽ­­->>>üõ×_œ?^w\­VëŠçžžž?~œÊ•+µ=>>>\¼x‘Çë?tè€ÁÇ jÌ»ìy.̉왞µ·ß~›víÚáääÄ Aƒøá‡ˆ‹‹cÈ!lÞ¼™éÓ§óÚk¯‘œœÌöíÛQ*•$$$pèÐ!“ï‰b6 D[éС< 00K—.aee¥KIII\¹r…7nàäädÔötêÔ •J¥÷ü6%%…E‹Q¿~}Ê•+gð{bÌû«ŠçZž›ÇRØI,4ŒCÍL/È¢££9~ü8­[·fùòåœ9s†3fàíí­;çÔ©S´jÕŠæÍ›SªT)FŽItt´ [mf˹§¥¥ñᇲpáB†އ‡Íš5£G( Ö®]Kxx8C† 1z[êÖ­KçÎ5jwïÞÅÝÝÅ‹sãÆ -Z”£kÍž=›„„Ý#±õë×s㟥#¾üòKŠ/hƼ¯ZµŠ¦M›2xð`?~Ì´iÓr4æýùeÛ_F){¨èH,4ŒC/ó^õíÛ—wÞy'Ó¥ë}¸rå Ÿþ98p€Aƒe˜'a,K–,᫯¾béÒ¥ <•JÅÆiÔ¨QŽ®3cÆ ¾ýö[æÎ«K„ß~û-ãÆ#!!Aw^ùòåÙ½{7îîîŒ9’éÓ§Ó®];ÂÃóUÿÐÏ+•(ArXƒ*TàÐýº1|8•ÆçúøñºŸ±vv¦ZX>>z×*À™,oQ-,Œ’þþzǜ۷ÇsÅŠ çz,\ˆË oØjaa(_P%(·FÙ{xP-, » ôŽWøç}}ª‰zöìY‚‚‚¨Q£†ÑV&“×@´*W®Ì|ÀôéÓY½z5AAAØØØðÙgŸáääÄ{ï½—é ¡ñª™ç/òøgñ:!±ÐÊ8ÈÌô¬5hЀ””]C­Vë&L[[[£P((Y²$Ïž=c×®]€fA×%K–°oß¾|o¯I{ Ú£´ëàØØØèumOžï¾û.óçÏÏõé…ANŠçZeŒÖK#±ÐÈÏ8H1=k~~~Œ9R÷%ºU«Vz¯?xð€3fðôéS&MšÄ¡C‡¨\¹r¶Wì6“Ñ»té‚‹‹ 3fÌÐíwÃþýû9~ü8gÏžåÑ£GЩS'Š+fŠfšµœϵޘ=[öÁø‡ÄB#¿ã ÅôÜ göìÙºGþåË—çêÕ«lÚ´‰Ö­[ç{{ò-$$$púôiªV­ŠƒƒŽŽŽüúë¯ôéÓkkk”J¥îùvT–­­­n¤–ÈHfž K%3Ó³¦8Àüùóùí·ß¸zõ*nnn4iÒ„6mÚàââÂÇL`` £FâÙ³gØÚÚæ[ó-lÙ²…áÇãàà€½½=gΜaË–-ÔªUKwNjj* …kkktË—ˆŒdæ¹°t23=k©©©|üñǬZµŠºuëâïïOóæÍyûí·±··G­Vóå—_²sçÎ|¯X]Œ+‹ IDATÿÂjnF V«quu%11‘ýû÷õÏ_˜;wîðìÙ3)Q¢VVV(•J’’’fáÂ…tèÐÁØÍ³H‡bÊÔ©  ¿°¼ÆW XOëÖ­)_¾¼©›c–Ž9ÂøñãéСÿ÷ÿÇ{ï½GÅŠ±±±Ñí!_©R%ªV­Ê›o¾™ï+vä˳!…BƒƒcÆŒaÉ’%¤¦¦RµjUÖ­[G@@=zô`üøñìÝ»€;wîðóÏ?놧‰ŒrS<œH1=k+V$))‰V­Zév-ÕΕÓî•T£F Z¶lÉéÓ§M ¿ýÖ”)S L™2$&&R¬X1ÂÃÃñ÷÷çÁƒÌž=›àà`¢££)W®Õ«WçîÝ»\¸p3gÎÈðÝLä¶x®U-,Œ3íÛ¼]–Hb¡aª8H1=ko¿ý6U«Vå—_~ÑÛ=55•£GÁŽ;8}ú4×®]Ë×ÇþFíüõ×_Œ3F7:ÀÎÎÿö/(Y²$ß|ó W®\aÛ¶mÔ«W¨¨(Š-Ê”)S$y¼D^÷<¿•ɾ…•ÄBÃTq™éY›6mîîîº:ÑÝ»wùã?tû$͘1ƒÄÄDú÷ïR©Ì× šFí$$$°sçNÊ•+Gݺu™2e cÆŒá›o¾aàÀº 1/þLZZ¥J•2V³,šÏEA#Åôì;|ø0Ó§Og÷îÝXYYѸqcúöíKË–-MÒž|Êüùó9|ø0>¤yóæ :4Ã$•J%Ë·¿DN–mÂÈ2ïÙsêÔ)ÚµkÇÓ§O4hŸ}öåÊý;„F;I;?÷1êžèéé餧§cmmMrr2:uÂÏÏcÇŽ±sçNÖ¯_O›6m(]º4ýúõ#00I¯=Ï…°$²gzÖÔj56l &&†cÇŽáóÏ–Çϯdžß›I‘k J¥R— ÆGpp0NNNøûûóÝwßÂüùóiذ!3gΤL™24nܘäädc6Ëbi÷|X·Ä `ôzˆÑHrr2qqq( ’““™6m)))¤¤¤ V«±±±ÁËË‹O>ù„_ý•5kÖÈþóÝÒ&B_^‹çZ¥»w7H{ ‰…†©ã Åô¬uêÔ‰Û·oùÏÒûÚÏÉ7n°f͆ F·nÝøúë¯ 0zMÉh5M›6±xñb4h@TT[·nåÏ?ÿ¤jÕª€¦ë¥V«±¶þ÷)šZ­&999ß³R<Ó³öõ×_Æ!CpppàæÍ›„‡‡³wï^¬¬¬èÞ½;¼ýöÛùÒ£Õ@œ¹|ù2¡¡¡ØÙÙñú믳oß>lmm)_¾¼^âxúô)[·n%))‰ž={«IM»l{©"„‘¼§V3âŸeÞ¥’¹¯¿þšG1zôhÝã¾7ß|“™3gòùçŸë>WÓÓÓŒ¾Ž Ñ®^¿~}Ž?Î?þHJJ ÑÑÑ|öÙgtïÞ~ø½{÷rÿþ}@³4ñðáÃu3)EF2ó\t23=kVVVÌŸ?ŸäädHdd$gÏžeàÀX[[“˜˜h‡R©Ô%c1Ú#,íJ’‡bëÖ­tëÖ={ö0gÎN:E™2ehÙ²%o¿ý6§OŸfÑ¢E\¸p*Uª£9-¯3Ï…°23=k6l uëÖºÞFrr2GŽáàÁƒ\»vøøxÊ•+G¿~ýðððÐM.4ÆcA“ìrøðaæÎKHHOŸ>ÅÙÙ™îÝ»3kÖ¬ünŠE0ô²í rA6R$ZæYæ=gýôSÙÎ2Æœy.›(ýKb¡aŽqbzÖ¦OŸÎŸþIjj*UªTáøñã;vŒR¥JѪU+üüü¨W¯U«VÕ[¤6==Ý “ :®Kû‡ìàà@ll¬î÷«W¯¦råÊT¬XÐ<š©_¿> …B’ÇKsæù¹nÝŒpUË$±Ð0Ç8ÈÌô¬}ùå—¬ZµŠ#GŽpøðaÞ|óMÆÏ;#——eʔћžžŽB¡@¡Pl†ºQ–2ñóóãÀxyyP¢D ž>}ªË€W¯^娱c’<^Á˜Ë¶§'%üš–Jb¡aŽqeÞ³vç΢¢¢èÛ·/ï¼óuêÔÁÃÃC7ç#55•Çãääd”Ý 2ŒWû(K»1Ô±cÇð÷÷ÇÝÝæÍ›³sçNΞ=KTT”®W"þ%3υЙéY;uê®®®¸¸¸èŽmذeË–qàÀÜÜܨR¥ ß}÷nk\CÍL7Êàmô=Ž5j0qâDÒÒÒX¶l*•ŠüQ’ÇK«x.„¥‘bzÖ¼½½uÉcÏž=ÔªU‹öíÛ‚··7>>>ìß¿ŸvíÚ±zõjàß¡¾y•¯K™ÄÇdzuëVªU«F­Zµòë¶%?–m¯ÄÕáÃrmK#±Ð0ç8H1=k*•Š´´4ZµjŹsçèß¿?ëׯÇÝÝU«Vqùòe¾þúkΞ=Ë…  vß<õ@RRR¸}ûv–çi'¸888°nÝ:Z´h‘—ÛhÚâù{FÌëÉ7níÚ–Fb¡aÎqxO­æô?Åt‘9+++V®\ÉîÝ»™;w.ãÇ'00 6pÿþ}ÜÝÝ  ::šýû÷d¥Þ\%m§eÆŒ¼þúëŒ3†ãÇ¿t+ZmÅÿèÑ£üõ×_ôèÑ#—Í-øòcæù­Ù³xuË"±Ð0ç8ÈÌô¬©ÕjN:E¹råhݺ5 6¤xñâ£P((Q¢%K–äúõë€aö ÉÕ´ÝÈ·Þz‹–-[2oÞ<|}}ùàƒøã?¸sçŽþM”JT*{öìáÎ; :4Ï /ˆdæ¹ÉÌô¬) >žÝ»wJxx8‰‰‰øùùÀýû÷0`+W®¤S§N†¸e’Ÿ{žÛ{xdÀBš%“XhXB¤˜žµ7ß|“zõê1eÊÜÜܸ}û6}ûöe÷îÝ 4ˆI“&eºµFneVrr2çÏŸ',,Œµk×ræÌT*EŠÑõH„¾ü\¶Ý—­0‰…†%ÄA–yÏÚ‚ ˜:u*5jÔ`Íš5¨T*Μ9ãG¨W¯666ÝШÃxµ½’={ö°|ùrÞyç† b¬ÛY´€€¶.]ʲ|¨ØU¨@ÊÍ›F¾‹eXhXBTÀGÖÖ´îÝ› ˜º9f)%%…uëÖ‘˜˜HÀ?;Lk;[ÈÇy IIIØØØe[EK'3Ï…È™™n^òm°½½½$—â¹Ù#Åôìɯùáù:]d”ŸÅs! )¦›™n`bù1óüEÌtÉ SXhXRr33=%%…#FàææFÑ¢E©_¿~¦›ÙM˜0¼¼¼8~üx®¯pîÜ9Zµj…££#ÎÎÎôîÝ›{÷îésíÚ5”J%{öìÉö{1'’@LÌ{ž+‹ÍÇ»™7‰…†%Å!73ÓûôéÃO?ýD¯^½˜5kVVV´iÓF·¬@hh(³fÍb̘14lØöíÛ“ôÂ2÷Ù¹@LL 7æêÕ«L™2…aƱiÓ&üýýIMMÍÓû7'òË„¤x.Dî䤘~øðaêׯÏôéÓu«`¤¤¤P½zuJ—.­ûðïÞ½;~~~|öÙg4hЀ &èvQÍîu À’%K8þ¼nߣˆˆüýýùí·ßt÷¸víUªTa×®]ºí¿-‰ô@LHŠçBäNNŠé¡¡¡X[[Ó¯_?Ý1;;;>ùä8@ll,OŸ>ÕÛS£téÒ$&&fû:111ºã«W¯¦]»vz›æ5kÖŒªU«êö0/$˜ˆZ­fîœ94œMÝ!,L)À˜;gN–#Ž"##©Zµ*zÇëÔ©À‰'ðõõeòäÉœ?ž5kÖ¡;';×9yò$±±±ÄÇÇS»vÆÓuêÔ!22Rï˜%b"¦(žkY;KÊÒ’XhXb²[L‹‹ÃÕÕ5Ãqí±[·nˆµµ5^^^téÒ…©S§âææ–ãëÄÅÅéñÜû÷ïëê •+WF¥RYäã+(ä $»#*Œ1šÂÅs-… MpWó$±Ð°Ä8d·˜ž””„]†ãEŠѽP¬X1öíÛlj'¸yó&ÌÕu´ÿÍι–®P'쌨0Æh S/Û~}üxÜÕlÐ L­Ð&ìŒÌ0Æh SÏ…(ˆ²*¦wêÔ •J¥W+IIIaÑ¢EÔ¯_ŸråÊeë>9¹Î‡~ÈÆõ†öFDDpéÒ%:wîœÓ·h¶ í#¬ìŒ¨(S¦ŒÞ±ÏÓŽ¦°±±Ñ¦ÈŠ®xž––Çw{e¸mEScXhXrž/¦g¶OHݺuéܹ3£FâîÝ»¸»»³xñbnܸÁ¢E‹²}Ÿœ\gôèѬZµŠ¦M›2xð`?~Ì´iÓðöö¦oß¾y}Ëf£Ðö@²3¢ÂУ)L]<×r¨UË„w7/ KŽCvŠéK–,᫯¾béÒ¥ <•JÅÆiÔ¨QŽî•Ýë”/_žÝ»wãîîÎÈ‘#™>}:íÚµ#<<¼ÀÔ? ÷@²3¢¢è?ëj4…©‹çZ— 2q ̇ÄBÃÒãU1ÝÎÎŽ   ‚‚‚òtŸœ\ÇËË‹­[·æé~æ®Ðö@²3¢Â£)¤x.„ñädfº0œB›@²3¢ÂÍÍÍ`£)¤x.„qåf™w‘7…6dwD…¡FS˜ræ¹…An–yyS¨—sïÚµ+k×®eÈ!ºG%""BW‹‰‰ÁÇLJ%J覨X±"GŽÉÖ#,s[¶½ZXgÚ·7u3Ì‚ÄB£ ÄAöLÏ_…¶ÙQaˆÑæR<׺5{¶©›`6$%²gzþ*Ô D;¢âÖ­[$%%qðàAüýý3œ§MñäÉþþûo–,Y¢·oÀ«h‹çêÖe™¿?€î×üöí±^±"ÃÏx,\ˆK·nzÇŠ7lHµ°0”/Œúª„Û #hì=<¨†]… zÇ+ N¥ñãy®;fíìLµ°0||ôÎ-À™|¨T £ä 1rnßO¼çåö}< K~ÏËÍûx¸oŸE¾™hþ-Mmاaa|ioR­æÛo¾‘bz>(Ô°òÃÁƒñõõ%¨kêÆQF ù·—ÙÄBa8…º’¤x.Dþ’bzþ‘bDæ2óüEΠXj( ‚‡ì.ó.òΜ>× s+žk•îÞÝÔM0 ‚)¦ç©‰Z­Æ»Z5Jž?ÏD ±ùn¬BÁCOONFEYô¾ãæLz F"3Ï…0-™™n|’@ŒDŠçB˜–ÓOa¹Í<¢°’™éÆ%=#0×â¹–‡…nd  ‚)¦—$³„eÛïoßnê&˜ ‰…FAƒ,ón\òËÀdæ¹æEf¦ô@ LŠçB˜)¦ô@ HŠçB˜')¦‡ô@ ÈÜ‹çZÅ64ŭÄB£ ÇAŠéÆ! Ä@,¡x®UaøpS7ÁlH,4 z¤˜nòË@,©x®´·'=)ÉÔÍ0  Â)¦žô@ Ä’Šçýƒ"'$…!RL7<é€Ï…° RL7,逥υ(줘nX’@òÈ’ŠçZU‚‚Lݳ!±Ð(,qbºaIÉ#K\¶=ùÆ S7ÁlH,4 Sd™wÑH°uéR–™Ù¶µBˆÌ©€¬­iÝ»7 ,0us,š$<â¹–IŠé†!_šó@ŠçBX&)¦†$\²Äâ¹–½‡‡©›`6$…-RL7 I ¹d‰Ås­Â2â&;$…1RLÏ;I ¹dI3Ï_tyÐ S7ÁlH,4 cdfzÞI=¤x.DÁ Åô¼‘H.Hñ\ˆ‚AŠéy#=R«ÕxW«FÉóç™(¡ÂâU(xèéÉɨ( …©›cQ¤’C–\<×*è{?ä„ÄB£0ÇAŠé¹' $‡,¹x®¥,ZÔÔM0 Â)¦çž<ÂÊ)ž Q0I1=w¤’R<¢`’bzîH$›¤x.DÁ&Åôœ“H6„â¹–µ³¥-¾b< ‰ƒÓsCH6„â¹–ÇÂ…¦n‚ÙXhH¤˜žò+ ZñÜÁLJ'‘‘¦n†YXhH4–‹­¬¸÷÷ßRLÏédCA+žËÅ¿$Ö@šJ%Åôl’H¤x.DáâTóò’bz6H$ sæÌ!êÜ9ÚJò¢PHNŸ=Ë/¿übꦘ=I ÙT¾‡” 0ŭÄBCâð¯þþ¦n‚Å’…RÃË‹¨+ëP«–©›`6$‡ÅݾM // `ꦘ=©dÜ9sHˆZmqÛ× !²ïÐ Í¿yI Y“’ m¯"sKhþÍË0Þ¬É#¬l(Q¢Ýzô`³µ5é¦nŒÂ(TÀfkk<==%yd“$lêׯqii5uC„FqˆKKcÑ¢E¦nŠÅ’MõêÕ£†— @1½ZX˜©›`6$Ø PPÃË‹ºu뚺)CH6) >0€¿€¿Mݘ<º5{¶©›`6$…=÷€@ÿeò`H=¤˜.DÁ$JåŽô@r@ŠéB<Úây·=$yä$’bº‹¶xÞ¯_?S7ÅâHÉ¡‚PLwnßÞÔM0 Â)žçž$*ÅôÒÝ»›º fCb¡QXã Åó¼‘"z.H1]ˆ‚AŠçy#=\bº–OŠçy' $—¤˜.„e“âyÞÉ#¬\R«Õ¼U½:%Γ …°@c zzÊ΃y =\²äbºÇÂ…¦n‚ÙXh¶8HñÜ0$äAÏž=±µµe³©’C÷·o7ŭÄB£°Åa `ggGÏž=MÝ‹&°ò( €­K—²,-M²±@|dmMëÞ½Y°`©›cÑÌò3/!!~ýúáâ₃ƒ~~~DFFf8/55•AƒQ²dIêׯOtt´Þë·oßfäÈ‘4mÚGGG”J%»wï~é}ÿúë/5jD±bÅpuueðàÁ$&&ê³k×.”J%7nܤ˜.„¥‘â¹á˜]IOO§mÛ¶üñÇ|ùå—q÷î]š4iÂåË—õÎ9s&7näûï¿§\¹rtîÜYïõóçÏD\\ÞÞÞ/}ÞyâÄ š5kFrr2?ýôŸ~ú)óæÍËpÍ„™éB&™Í>ž‰'ráÂjÖ¬ dþe3&&†ÆsõêU¦L™Â°aÃØ´iþþþ¤¦¦æÓ»0f™@Ê–-KÇŽuÇJ•*E—.] ÓûCJLLÄÅÅ+++œœœxòä‰îuJ”(‘å==zÄŽ;øè£pppÐïÝ»7„„„¼òç-­˜^aøpS7ÁlH,4 K^V.ôí[ ÞÇó3SAAl4ˆ€À" Òë¯g˜ynkkKéҥͯ—Y½z5íÚµ£|ùòºcÍš5£jÕªY~Ñ,ˆÌn–ƒƒÝ»wgþüùzÇ7oÞL»víØ¶mþÿüE»uë~~~\¼x{{{~ÿýw>øàƒL¯J—.]صk7Îôµ½{÷Òð…®|—.]Ø·o·nÝze»<ˆ¯¯/A€¬é)„ù9Œ@óoµ^½z/=ïèÑ£Ô­[—àà`z÷î­;K…  bذaz?Ó«W/¶lÙ¢«…\»v wwwvîÜ™áó¦ ±6u^”œœŒ]†ãEŠ ))IwÌÍÍS§NEåÊ•qrrÊÕ=µ×|Ù}Ÿ¿çËèŠéçÎQ×¼r²‚Šçžž¹^¶=..WW× ¯¹ººrÿþ}RSS±±±¡råʨTª<µ×˜ìVjj*·oßÖû¥R©°··'%%%ÃùÉÉÉØ¿ðÈÀÖÖ–Zµjå:y<Í—Ý·hÑ¢Y^ËéB†˜yžÕÍçÏ),L–@öïß›››îW¹r刉‰ÁÕÕ5ÓÇEÚìïææfð¶h¿Qhïñâ}³{OK)¦W 2ŭÄB£ ÇÁ3ϳú¢ùü9……ÉHÍš5Ù±c‡îWxx8eË–¥fÍš?~œí/š‰ÙÑ;uêDýúõéÛ·/gÏžÅÙÙ™_~ùµZÍwß}—ãëMš4 €3gΰdÉÝìбcÇêÎûþûïiРï¾û.Ÿ}ö111üøã´lÙ’-Zdû~RL¼äµxþ¼?üÅ‹£ÊÁ¥K—øïÿ›çë[³Æ šµ°¾þúkÖ­[GRRuëÖeúôé™ÎÉŠR©D¡P V«uÿMÑûÅQû÷ïgĈ?~œâŋӥK¦L™B±bÅrtÏ9sæ080µç·Xa(÷€® ³fÏfÀ€¯ }ûöxzzbgg—§{ì3êâÅ‹üþûï <˜•+WR¹re–/_®ë:yzzâííÍæÍÆþ~mÙ¤˜.„>)žgíúõë8p€÷ߟʕ+P´hQ|||˜2e Ôë•4oÞœ.]º°iÓ¦<Ý×` äĉ+VŒ¶mÛbeeEÿþýY½z57nÜ lÙ²ÄÆÆR²dIÒÓe°êËH1]}R<ÏÚ?þH™2ehܸ1VVV>cË”)C·nÝX»v-¤ÿþ„‡‡sòäI ÷S-òœ@´ ­T©< !!µZMŸ>}xôèû÷ï4°bbb¨Q£J¥<œy™ü(¦oØÐHW¶< sƒϳgùòå4lØ:uê¼ôKº>>>Lš4‰èèh† ä~ª…Ag¢W­Z•êÕ«3mÚ4ÜÝÝéܹ3W¯^åý÷ßç×_ÅÓÓ“­[·bmm•••¡n[à{fzµ°0ÎXÐÚGÆ$±Ð0×8ÈÌóì9~ü8gΜ¡eË–”.]:ßîk’––†µµ5«V­bìØ±<{öŒ¶mÛrãÆ 6nÜÀ[o½ÅÏ?ÿ̻ロçFÆ,¦+ííIÏÇÉFæLb¡aŽqâyöÌŸ?Ÿß~û»wïâìì̧Ÿ~ÊgŸ}†­­­Ñïm¢V«Q(¨Õj._¾Ì¸qãˆŽŽæÖ­[Ô¯_Ÿž={òþûïëοwï·nÝÂÛÛ;¯·.°<ˆ¯¯/A€<ù…Ñ!`š õêÕ3usÌÒ7¨^½:^^^øùù±cÇ.]ºDxx8µk×F¥Raee¥ûŒ64ƒ>Âz¾‘÷ïßÇÑÑ@ÓK¹páGeïÞ½¬X±‚³gÏR±bECݾ@Q«Õ¼U½:%Îc¢¬%& ¡± ==9%õ—1bëÖ­ã?þ V­Z\½z• 0räH¾úê+Μ9CµjÕŒrkC_0==¥R‰““wïÞåÌ™3ìÝ»—Í›7sîÜ9?~LíÚµ)[¶¬¡o_`h‹éƒùp6uƒ„ÈGÚâù,)ž¿R±bŨ]»6îîî€f%{{{>|@xx8:ubíÚµøùùüþy¼®­ø+ ”J%*•ŠsçÎÌ×_M×®]?~Í®]»Ø¶m—/_æÞ½{tëÖQ£FQ½zuÝÏÌœ9“qãÆñúë¯ËÌô—Ð-ó¾t)= XLOþgnŽXh™SdÙöì2dÇŽãáÇL™2…O>ù„°°0<<<¨V­IIIœ={–¸¸8£ ^2H äÉ“',_¾œ}ûö±yófîß¿¯¯/7oÞ¤víÚ,X°@70==kkkâââxÿý÷)W®ëÖ­3Ä{)¤˜. )žgϼyó a÷îݨT*7nLdd$ýúõcÚ´ilÛ¶!C†àááÁÚµkuuC2XÝÑÑ•JÅ_|ÁÀ©R¥ ]ºt¡S§NtéÒE×xíßÛ·oS§NÞy炃ƒóeÈ™%’bº(l¤xž3gΜaÁ‚„……§§' …‚³gÏâííÍ¢E‹ðññ1J1؃½{÷òôéSf̘A•*UˆŒŒdÇŽºgnÿßÞ}‡Eqí ÿî‚t•âª`TĆ\!‚Š öÁk^•kôKôÕx-1&[T¢Æ`MÔXâKŠ\TìÆ *»€bEAiîÎûw'¬¨”,ìÏçyxžpvvæÌÉÊog~ó;GÛqSÓ‚»f+V¬ 55•>}úˆàñ†X3] ETž—^óæÍY²d gÏžåÛo¿ÅÛÛ›Ö­[3sæLvìØ§§'@¹oë}Môüü|”J%&&&4lغuë2oÞ<¼¼¼°¶¶&::š%K–°wï^Þ}÷]V¬X¨L }W¦[6nLöèaO•Ÿ‹Æ2¢ò¼xÙÙÙ$$$‘‘¿¿ÿs¿€çååUÈs½OJU¥JùªcÞ¼y\ºt‰nݺñú믣R©èÕ«ÉÉÉÌž=›eË–Q½zu<Š¡ï5Óí‰CcQÀÆA$ÏKfÚ´iôíÛ—^½zaooψ#ˆ‹‹ÓÙ¦¢îêèý þ,(Ôh4$&&²fÍRSSQ©T8;;Ó¶m[¼½½±°°@­V³sçNz÷î­ï®ümè3™n^·.¹7nè£[•ž‹Æ0"y^¼+W®àææÆˆ#hÑ¢'Nœ`×®]ܺu Þÿ}:uêĦM› ¤uëÖåV…å@´´E…Z?ÆÚÚZþýôéÓ„‡‡Nnn.·oߦFåÕJM$Ó…¿;‘Ç—“êõë×—·qttdĈ´nÝZ§ ¿²X°`GeРAxxxpóæMÂÂÂðòòâ·ß~“'3KII¡cÇŽØÙÙñÙgŸ‘™™É¢E‹8sæ ÇŽ“'Ÿ|}U¦×:•F45b, rJ›<ß¶mGeÛ¶m 0€   ÜÜܘ={6ß}÷¼í?üÀ×_M×®]3f 4àÒ¥KòÜQ_|ñíÛ·×Ù`` :u",,ŒyóæÉí3fÌÀÁÁýû÷ccc€³³3£Fb÷îÝtíÚõ¯ÅK½ÿþûØØØÐ§O<<<¨Y³¦\!Iyyyìß¿_þÛcnnNpp0¶¶¶åÖ§r ÚäÍÀ¹}û6:t¿¡kåææbnnŽ——µjÕbÛ¶m•2€Lž<oooù(@pp0-Z´àóÏ?gÆ |úé§òcx¯½ö>>>tíÚ•ˆˆFõÒãŒ=šuëÖqœ²'Ó•ÿýö"ˆ±Ð2ä8”vÍómÛ¶Q»vm9xÔ¨Qƒ   ¾ýö[òóóå/b?F¥RuööödeeÉï{6xtèÐ{{{å¶G±gÏ&Mš¤ó÷kèСLœ8‘-[¶”kÉÍÍåÒ¥K:tˆˆˆüýýéÑ£mÛ¶¥Q£F˜™™annŽ™™S§NÅÜÜI’Ê}ÂÚr½…¥½—immÍ”)Shݺ5666r´T«Õ˜››óh%''Ó¢E ½OøUÚ¶m«<\]]iÖ¬™ÎqûöíôêÕKo¼ñnnnlÙ²¥Øãh×L_ ô~ eç¸qôÿïïË(x¦¿yTæuëê¼·îÔ©ÔŸ3‡ksæÈm¦4ŠÂæ¿ÅFZµGŽÄ5,¬Èñ›GEa÷Ì?‡¾}iºys‘mó ªÁƒuÚªµkGó¨(”––:í CCq7N§­¸ó(¬¬çQx,*óyV–ó¸±`A…œÇÙ‘#I “?¯ý™@ ‡¯yž€——W‘vooožúè#.]ºÄêÕ«IKK£I“&/ÝVV™™™:ôœ9s†§OŸÒªU+m«T©BË–-‹ä_ôý€¹¹9 ==‰'rôèQFMpp0³gÏf÷îÝÜ»wáÇ3ç¿ÿ/Ôjõ —¶Õ—r} ëYùùù:·iÒÒÒøúë¯ Ã‚_~ùåo³Ð”$IÔ­[—-ZMjj*uëÖ%44T^‹XkÈ!DGG˹«W¯âââ¾}ûèØ±£Î¶_~ù%Æg‹$‰iÞ…Jí.¬P°<,Œ±cÇ–è=666¼õÖ[|ýõ×:í;wî¤W¯^ÄÄÄÈWiiitéÒ…¤¤$,--ùöÛoéß¿ÿK÷ÿÉ'Ÿ0kÖ,öîÝ‹ŸŸPpÕÄ¡C‡h÷ÌúñAAA>|˜´´´’t>>Œ=ºB'§-÷$zaUªT‘ƒGLL ƒ¦U«V¬\¹’Î;³}ûö¿Mðøî»ïHKK#88€›7oùžg9::rÿþ}9È:;;ˤ=K$Ó…¿‹²LÛž““#ß¹(L[W–]hi^'''~ÿýwŽ?Î7Š dîܹËÁ£ð>_tÜìr^øÁƒdddè´Czz:|ð»wï–Ú‰‹‹cÇŽEÞ£o@$IâñãÇÌœ9ÌéÓ§ déÒ¥¬X±222ø÷¿ÿÍÞ½{+ªkå"11‘÷ß___† ÿ!,¼ÍËüÕÊtSqÝ¢%Æ¢€!Æ¡¸äy~~>·nÝÒùQ«ÕXZZ’››[dûœœ,Ÿ¹­hff†———¼ÈÝ‹$&&Ò¿<<<×yM»ÏתsH+V¬ _¿~¸»»3pà@víÚ¥óºJ¥böìÙh4ùÎFHHäÂ… åÖ/¨À¢­L_¹r%VVVLž<™µk×òÕW_ñöÛoS«V-  Ð$''óá‡VT×ôîÖ­[ôìÙ;;;¶mÛ&ß-îCXx›âŒ=š›OŸr¼ ýküÍ7ex×ß“‹†‡â’çGŽÁÉÉIþ©S§)))8::>÷v‘ö ßÉÉ©Ô}¹qãݺuÃÎÎŽ;wê<ßw ´Çxö¸e9fI\¿~éÓ§“““C‹-ˆ'00>þøcäYÕ«WÇßߟo¿ýVç1à 6ðøñãr+&ÌÌÌdâĉrPkß¾=sæÌá»ï¾ã›o¾aÀ€$''S¥J† ¼yóÈÊʪ°'Y+ô),-www:wîÌòåËQ(dggsòäI9²ÆÅÅ1hÐ "##Kõa0$µZÍ€øÏþCTTÏÝnìØ±DFFòÇÈòÆÆÆÒµkWV¯^]âgáAÿÓ¼ BEù+Ó¶k4Ú·oÏÙ³gùðÃqpp`åÊ•¤¤¤O£FJ¼¯~ýúñã?2räH¤9,’×·o_ù÷„„|}}iÖ¬£F"%%…%K–ЩS'¢££Ku%•••ÅÓ§O±µµåéÓ§H’¤ó71!!ÀÀ@ÜÝÝÉÎÎ&33“ÐÐPºwï^.ýyV…mÑàüùóY¹r%‘‘‘ܹs‡;w²ÿ~RSSiРcÆŒaôèÑØÚÚ–ëL’úôÁ°|ùrz÷îýÜo#ï¾û.PP‰îé鉭­-&L 33“… R¯^=âããK0GŽÉ6là;=®™.åI ¼kjJ÷¡CY»vm™ö‘‘‘Á‡~Èÿýßÿ‘‹-zn}ÈË4hЀëׯ?÷»³³3—/_Öi;räÓ¦MãäÉ“T«V   >ûì³"9}ÐNF›——‡‰‰‰|G’$4 OŸ>%""‚þóŸríJrr2îîîåZ}^˜A®@¢££éÙ³'...ܸqI’`ܸqtëÖ­¢»£;wæàÁƒÏý * ‰"ÏŸ?ϤI“8|ø0æææôìٓŋ˳¥Q–iÞkÉ-‘<ÄXhUä8ˆiÛ‹÷äɶnÝÊÚµk©V­Íš5ÃËË‹víÚQ÷¿…œ999L™2…Û·o—¨¹øà‚‚‚˜1c5jÔ`ÕªU4lذR®VXQþê4ï‚PDò¼äÎ;ÇÑ£G9räñññ,X°€ 6)o¯Mš;88Mð# Å)ü¡ôðð {÷î:-õÎ;ï`ffÆÎÿþþtêTƒöǘÔcèo¢sssÞyç½ìïï(::FC¯^½P©Th4Ž9B\\3gÎdܸqøøø°wï^@wÒD#»aTùüy•R½zuÚ·oOFFÛ¶m3p¯Œ×³•éý6t—ŒÆ1€~ÆATž—L\\7–s»yyy|ÿý÷4jÔˆV­ZñäÉš6mÊÅ‹ÉÍÍÕ)²6¶«ºJ@rss9qâ³fÍbþüùÄÇǸWÆ­pezvv¶¡»c44b,ýŒƒ¨Ö¯_Oll,VVV°hÑ"Ú·ooèî5¹2ýÂ0²Ë`áïá'…‚M›ŠÊó—P(Œ;WWWìììÈËËcÏž=ܹs___’’’X¼x1ÇŽ#::ÚÐÝ-–ÑÜÜ\Ο?Ï–-[ؼy3×®]ÃÃÃ3fзo_š4i" •J@›LŸ0~<6†îŒð·£Mž/Éób™ššÒ£G  ö-55€>}ú——‡R©ä£>¢S§NEž@5&F÷¯Ö­[·Ø·o6l 66kkkºvíÊ Aƒèر#*•J|PKI;Í{??>Œ‰1twŒBÃÐP.‹Dú_1m{Ùh4._¾LRRgΜA¡P Wœêƒ/c´W ³fÍ"<<///qµ¡'ÚdzÔÖ­h¨¤ 0=˹~ÝÐ]0 eDò¼ì”J%®®®¸ººÊW%ϾnÌŒî D[~öìY ¤FâjCODeº o¢ò\? ÏUY]Ê—¨LôMTž¿ºŒûúHл’¬™.%%*Ï_m"€¼‚ž­L•Y6nlè.…²Žƒ¨<µ‰ò k¦ÿIjè.…²ŒƒHž "€¼¢ÄšéFŽgè.…²Œƒ¨<DyE‰5Ó ¤Þ¸aè.…²ŒƒXó\ä%’éÂ_!’çˆòJÉt¡¬Dò\#®DÊŸ­­-oµq#Þjõ+ùmbÐС$­_oèn\iÆAD™˜Ð5 À(Öå G¾â"##>|¸¡»!TR'NœÀËËËÐÝ DWÜ“'OHLL4t7„JªI“&XYYº‚ˆ"‚ ”É«xÛ[AÐ@A„2DA(@„J%77—iÓ¦áää„••mÚ´aÏž=E¶ûøãQ©T4kÖŒ“'Oê¼öøñcfÏžM`` ööö(•J"##_xÌ .HÕªUqpp`èСܽ{Wg›«W¯¢T*9xð ~NTOJ:^•ùÃD¨T†ÎÒ¥K2dË—/ÇÄÄ„=zpäÈy›mÛ¶±|ùr>úè#ÚµkGß¾}ÉÎΖ_¿sçóæÍã?þ eË–/¬¦NII¡cÇŽ\¾|™Ï>ûŒ)S¦ðË/¿ÐµkWòóóË÷dõ $ãUÙÏQ0 I*‰¸¸8I¡PH‹/–Ûrrr$WWWÉ××WnGÁ°D*7ß|µZÍš5kä¶ÜÜ\Ö­[G›6m¨S§ŽÞ9pà@~þùgRRRä¶ØØX’““4hÞ§O%¯Ê|Ž‚a‰éÜ…J%88˜;v0qâD\\\ˆŒŒäøñãÄÆÆÒ¾}ûï',,ŒŒŒ ÒÒÒX½z5 ¿mÿë_ÿ¢Zµj@A•¶§§'¶¶¶L˜0ÌÌL.\H½zõˆ7úÛ;%¯Ê~Ž‚¸QJ%''GúðÃ%GGGÉÂÂBjݺµ´k×®RïÇÙÙYR(’B¡”J¥¤T*åÿ¾víšÎ¶çΓ$kkkÉÞÞ^2dˆtûöm}R¹*éxUæs G\‚ e"r ‚ B™ˆ"‚ ”‰ ‚ B™ˆ"‚ ”‰ ‚ B™ˆ"‚ ”‰ ‚ B™ˆ"‚ ”‰ ‚ B™ˆ"‚ ”‰ ‚ B™ˆ"‚ ”‰ ‚ B™ˆ"/°ÿ~”J%¬ãùùùѹsç 9– èƒ ‚AEDD T*9yò¤¡»ò\ …Bç÷7²lÙ²r;Ö³Çcfj肱êÔ©ÙÙÙ:+òmܸ‘sçÎ1a½O’$@„JEAx…B™™ÙsÛA·°„J !!îÝ»S½zuªV­Š¿¿?qqq:Ûho…ýúë¯Lš4 •J…  àîÝ»:Ûj4æÌ™ƒ““ÖÖÖtéÒ…óçÏãìì̈#äížÍøùù±sçN®^½ŠR©D©TÒ Aã_¿~]çX/Ê£¬Y³¬¬¬hݺ5‡zî¹çææ2{öl\]]±°° ^½zL›6¼¼¼² ¦ 葸ŒÚ¹sçèС¶¶¶L›6 SSS¾úê+üüü8pà>>>:Û?{{{æÎË•+Wøâ‹/7n›7o–·™>}: .¤OŸ>pêÔ)ÉÉÉyéÕÅÌ™3™:u*)))|ñÅØØØ”úœÖ®]KHHíÚµcÒ¤I\ºt‰¾}ûbooO½zõäí4 }úôáÈ‘#Œ3†¦M›òû￳téR’’’رcG©-ú$ˆ`ÔfΜ‰Z­æðáÃ8;;0tèP7nÌÔ©SÙ¿¿Îö5jÔ &&Fþ]£Ñ°|ùr233©Zµ*ééé,Y²„þýû³}ûvy»?þ˜9sæ¼´/þþþ899‘‘‘ÁÛo¿]¦óÉÏÏgÆŒxzz²oß>LM þ 6k֌ѣGë7ËÁƒñõõ•ÛÝÝÝ áèÑ£´mÛ¶Lý}·°£¥V«Ùµkýúõ“ƒ@íÚµyûí·9|ø0YYY:ï=z´ÎïíÛ·G­VsíÚ5bccQ«ÕŒ;Vg»ñãÇ—ÏI<ãøñãܹs‡9x >œêÕ«ël»uëVš6mJãÆ¹{÷®ü£}Ôwß¾}ÒgAxq"­;wîMãÆ‹¼Ö¤I4 7nÜ iÓ¦r{áoðvvvž=¾F£ÁÃÃ%K–vvvlÞ¼¹È-,SSS>ùäÆŒC—.] âÊ•+DDDаaCÛXC† aË–-„„„°oß>|}}Q«Õ$&&²uëVvíÚ…——W©Ç@ôFŠˆˆ …¤T*%…B¡ó£T*¥ÔÔT)!!A ”ªV­*Y[[Ko¼ñ†ôÛo¿éìgݺu’R©”Nœ8¡Ó¾oß>I©TJÛÔjµ4kÖ,ÉÑÑQ²²²’ºté"?^ªQ£†4vìØ—¾÷ñãÇÒ;ï¼#ÙÙÙI …BjРüÚåË—¥®]»J’£££4sæLiÏž=Eö!I’´jÕ*©aÆ’………äãã#>|Xòóó“:w]~~¾*¹»»K’½½½äíí-Í›7OzôèQÙ^ô@!I!s(ØÛÛ3þ|¦OŸnèîB¥ r Â+'''§H›¶²¼pb[„—9ᕳyóf"""èÙ³'ÖÖÖ>|˜Í›7 *»¡D^9ÿøÇ?¨R¥ ¡¡¡ùä“€×àíè:NŸ>-­X±B“l6›T]]-õ÷÷û<Ïw¿û]éòåËÒ¿ÿû¿O>æ¶¶6©  @²Ûí’Óé”>÷¹ÏIø¸Ó–æÍ›'Y­VÍ-I’ôùÏ^Ú¿¿$I’Ô××'9]Î3ùùù’ÕjòX°×à/O=õ”ôÕ¯~uò3iôõ†axá–[nA\\Ü”Çâãã‡cccHMMìÞ½÷ÝwàþûïÇîÝ»aaa°Z­°Ùl Ód wÜqÇä±+**ÐÖÖ𼧪ª ×òy‹Å‚ááaŒŽŽ"<<Üë}€ØØXDFFbddcccGzzzÀÇÎûï¿uëÖ!&&Fóc×ÔÔ ""ŸûÜçIII0›ÍšŸG ’$Mù(Ö ”ÚÚZ\¼x_úÒ—&×mäõ† ¡@ü`Ë–-ÈÈÈ@TTÖ®] hkkCVV~9ûûûëׯÇÞ½{±mÛ6<ú裚®chh~ø!n½õÖ ®A‹óôôô %%eò÷¬¬,´¶¶tüÒÒRìÛ·èëëþ}ûpåÊŸçÙ¶m~øaìß¿ëׯ÷¹Ö„„lß¾¹¹¹ÈÎÎÆúõ둘˜ðq§óöÛoã«_ý*º»»5?vmm-âââp×]waåÊ•xæ™gf|Ôžg6L&n¾ùf¬^½ÿùŸÿ’5øÃOéS§––†/~ñ‹(**Òü<³ñûßÿ ,@GGÖ­[‡œœœ ¯A)ï¿ÿ>/^ŒÂÂBìß¿ÀTëi:¡^o(ˆL&“×ÇÃÃÃqÏ=÷àÈ‘#€ÌÌL´´´úûû‘””¤ëž|òI¤¦¦âÛßþöäc®Á×µNGíy<ŸššŠÞÞÞÉß[[['a ×ñÍo~ÇŽÃ'Ÿ|‚ððp_sžÌÌLÅÇ€£Gâæ›oFRR¢¢¢ðå/ø¸ž¼ÿþû¸ãŽ;áõÞrlÈÎÎFUU²²² 6 ©©IóóÌÆ‚ ذaêë냾¥:tÿõ_ÿ…‚‚<ñÄøÙÏ~†—_~Ù°ë %BøÀsÇáp8ÐÜÜ p:ؽ{7*++7nÄ›o¾ رcî¼óN]Ö?ýéOqòäI¼üòËSt 3í®´8çñM&ª««ñá‡Þzë­Éãr˜ÝtøðaÜqÇל箻îR|<X²d þ÷ÿcccp:Ø·o–.]ðq=‘ÝW€÷{ȱƳ:;;Ñßß—Ë…O?ýÅÅÅšŸg&FFF044Æ'Ÿ|‚ÒÒÒ ®Áþîïþ—/_Fcc#^xá|ó›ßÄ÷¿ÿ}î7¤„*zodn¿ýv)--MЉ‰‘rrr¤ßÿþ÷ÒM7Ý$•••IeeeÒw¾óÉårI’$I6›MÚ´i“TXX(Ýzë­Rww·.k8pà€&-^¼Xª¨¨***¤ÿøÿx ÞÎó7ó7Rvv¶&eggK?ùÉOTŸÇóøÙÙÙÒÁƒ¥ÚÚZiåʕҢE‹¤‡~X“{yÓM7IË–-“V¯^-?~\’$ÉçyüáG?ú‘´lÙ2©¤¤Dzì±Ç4;®$IR¿”‘‘!O>¦Õ±=ùÕ¯~%•••I¥¥¥Òã?®Ûy|ÑÐÐ •——KåååRii©ôâ‹/} jùÿøÉ,¬¹°Þ`c’$…ÛO@ <.,@ ¨B(@ ¨â†JãíîîÆo~óäçç#::Z“cöõõ!99Y“c©exxøšb@=°ÙlšÝ7oŒÏ‰B,½×©÷}– Öçf&z{{§ÔWöööÉŒ²éØl6455áŽ;îÀ¼yó‚¼²ÐpC)ßüæ7øú׿êe‚ë˜;vàk_ûZ¨—n(’ŸŸ€opqq±&Ç|úᇑ”˜ˆíÿ÷šÏol6lÛ¸ñóŸO^ŸŒáñ/|ÿ¼o °nÄNî܉øïÿƵ⾕+ñæ±cšóÁ¯~mÝŠòM›4=.ÀáÀŸÝ~;^úøc]­œºº:¼øðÃxñ7¿T´ÚÑ‚ܾýN'ž~饜ßÚëêð·>ˆ­?ü!nžè1óçÏãë_ÿº®ßCÃê4°`rìØ1 €tìØ1ÍŽi³Ù¤u ÒéC‡4;¦¿ülÛ6éK·ÞªûynÉÈ4¼wž =*-ž?_óã®Òá#¾<=]>wNóãJ’$Õ~ú©tSV–.ÇödÃÿù?Ò¿©hò©Ç>ùDº-)I Ù”ÒÕÜ,}))Izóç?ŸñyzÈ£#‚è…‡_|Oýßÿ²5<ø·‹¾ãÇgl…¡Å·Ü‚_üÓ?érì¸ùóápèrl­‰t:;­Õ½Vìzùe”¯[§Ë±ez{{1rö,¾ñôÓºžÇ.‡Oõ«xüßþ !YƒR\##xpåJÜñ½ïáë>êå¡@4`Ë7¾´Å‹Qóë_‡äü攬¿é&|ï»ßÕõ<lߎã{÷êsð˜ÄH\.—>ÇׇÃIbcu9þ‘Ï>ÃÃÛ·ërl™'þüϱnýz˜uº†Ù8õî»ÈX½_Þ¼9$çWÌø8̧OãÿÛ½=ùd¨WcHn¨ˆžüÛ¾}ÀáÃÀØôó?ñÒKëëÓõkª«±iËÀn´Þ9ÆÆbˆ Ô´Ÿ˜Ö cÓ¿DEiðÁAÜyィ¨¨ÐþØüýŸý¢gh¨¨+CC¨\´ÿúÁ¡9¿RœNàøq`Ù2”%$„z5†EX Za2Ë–55!9}|a!æ9€Î¾þío]]Ú82O<ú¨æÊcÑ¢Eš/)) Û{L—Dtvâ¿ø íëÉø8R£¢ã#UW$ 8w() þ¹ýÁå¢ò(*„ò˜¡@´$>ˆ‹&=“ X°@ÿs§§ë£@tâ¿ø…¶”$}”ôöz×D\¾ äæê{_46ò3ª‡õ¦’œ:äåéÿ^\¢5……ü’ÚíÁ?wN0Ñ]7"#é¦Ó³™»?#c³zù9¼~³Ž_II:;/Ó&ugdèé òRÊ™3Ü$¥§‡z%s¡@´Æl–.¥©l, 1‘;Y=IL´?nL ‘±Zõ  ww:evMÒÖ„j†ÅÙ³@iihέ”óç鲚eP›ÀP z”Ä óÄŒŠ RP@Wž¤§ësmsAŒŒpZÓÙ©¿ii²³õ=‡7š›ymAhÏ¢šúznÀn¤"@  D/–,á‡2ص ‘‘¬,ÖïÉÉ€_±±Üá½,›MÅ$ÓÓÃÍ £~uÁf::Œ-˜/_FGÅ‹C½’9‡P za±P‰œ?üs/\¨¯b2ñúÆÇµ=î\P zX ÃÃL¾Ð“ÆÆÐñšf]é•x(íítù=3Ì ¢'))üâôô÷¼ññ tëÈOKÓ>+:š;V#ãrièîìÔ7h;€ÞÕ¥_üÃéd€8˜ÓñÆÇ°7bFÓØ«Ì+*´ïåvƒ"H°§º¶6xç4›)<ôªGIIѾhÑÈ™Xz¤ðê• ­­Á¯û8wŽq?=+êÕ0>œ8”•»eŽa°wù:'#ƒCç¹SÐ3˜.·ÞвÖ%6Ö¸ˆÖ)¼zX4ž»ò¼«‹n¡ääàS rgÝâbãf„ÍQ„ 6%%Ü¥+Û(<œ;.½”VZýøZc\ d|œ÷S+ôLß½z•Ög°,‡¨«£õa$$‰–Ç¢ElÁ#ÐÃ(Í›7#%%÷ÜsÏ5Û²e V­Z5ùûèè(î¾ûnaíڵ虨³°ÛíØ°aÖ¬Yƒ††† ­Ý/"#éV¨¯Þ9 ˜²¨Z·5±X‚Ÿò*zzô‹O47Óú .0îa´¬¦S§ø} fèÂ0 dûöíxã7®yü·¿ý-ÂÂÂ`òH|íµ×PXXˆÚÚZlÚ´ Ï>û,`Ïž=غu+vî܉W^y%hk÷›ìlæ¡ëÙnÄ“ØX e=ÒnçBñŸ8Úfíȳ[ô¸´ä´´–f¢·—É!zf“©áìY®)݇o £@n¹åÄMóOŽã™gžÁ_ÿõ_CòpùìÞ½÷ÝwàþûïÇîÝ»aaa°Z­°Ùl3zŠ^I såƒåÊÒ³Éb\œ¶Ê0""4íðgBëøGo¯~·¡íl‚Ó \¼È,C#qñ"߯œœP¯äºÆ0 Äÿðÿ€xñÓŠ ÚÚÚ5Ñr9)) ýýý€õë×cï޽ضm}ôÑ ¯×/¢£¹3jj ÎùRRÑÃ=¤µˈ©¼ZgKéÿ°Ù¸)Ñ38ïÉ¥KŒ/iÃÖØÈ{,%zcXÒÚÚŠßþö·¸ÿþû§X3a±X°sçNìÝ»™¡š{àyyÌ\ –°ÌÉaçQ­IIѶߗSyµV z5Pll ^Û’þ~ÖViøRK ï­Ñ‚ù×)†R žqŽ“'Oâܹs(((ÀÍ7ߌ3gÎ`ãÆ€ÌÌL´LTX÷÷÷+ž£}åÊ@Ó™3¯<dWV0X°€UÂZ»Í,¶¬Ðʺ1¢¢¥ KÏ©†CCÁI£u¹87’ëêêUnÈŒ>¸ê:ÂP ÄÓÒøò—¿Œ¶¶6466bÿþý(++Ã|ظq#Þ|óMÀŽ;pçw*:~΄?ôùÿ÷ÿÐ~é’Æ«WIl,}ázXÓ1™è6ëèÐþØ©©Ú¥óÑÓn–·^î«+W‚72¶®Žç2JEwO¯¿¼Ü˜ý·®S £@Ö­[‡¯|å+øè£““ƒC‡MþM’¤)ÖÉC=„ºº:á—¿ü%¾÷½ïùu®µÛ¶á¡›nÂp(&z£ €s ôÈ’šŽ^n,-ã F ¢kiµuuiŸV*IÜ#ãhhˆn"£¸‰¨Ð*+Wc˜È×Çìóoùùù8|øðäïQQQxï½÷TŸëÿèi±àÊJìjhþœ„é˜LtÔÔ+Wê{®°06¹ëëÓÖÕaä ò@ÑrˆËÅ­ƒÎííTzï¾%‰…°úžG)ÃÃÚ¶r¥ñjPnnXuýýgžÁo¼Á*U­'ë©!>ž‚½µUÿsé•Ò«¥ëÉH…ZÆ,z{õ™ý,÷UC-Poº¾/gÎÐòVÍ‹` 7¬€5·ßÎþ8ÇCXRèí¾‰ŠâŽZk‹AËî¼F ¤k™¥Gü£·—›½wàV+Ïe„Ú »8y’1#(³”Z`œÂBZ"Álµî “‰ -YYz´7™7O»t^#Òµœ24¤ýœŒ`¥îÖÔ#ÃÉáয´4xõ.¯0ƒ('‡}sB=R51‘ÂÕ«úŸÇfÓÖ}g±ðþiaÍÍÑBPŽj—É%cµò¾k}Üé45Ñr u+t—‹ÊcÉ’àOY\ƒP 2óçÓsöl¨WÂ/GCƒþ±=Z½§¦j3#ÄHˆV1ÎN~Æ´$mKl6®=Ø“ §#wÖ-(0^Ëø¡@<ÉÎfup°ç—OÇl¦9^ß󤧳vCK×Vé¼zÍ\WƒVYXÝÝÚ*»÷Hïѱ55,x 5§O3€¯µ¨F(é0êvð))ZZÎÚðFf¦¶coµj¬h2…Þ¨%’Dß½–ÙBÁhÙÞÒÂݾ^S•RSÃu,XÚu¦ ˆ7–,¡ÿ}¢õIÈ(.æ\=3IJ²($´$:Z›ø…”ˆVq ­ën\.&,èÙ‡jlŒiå¡nJX[ËL«`UÙ #ˆ/JKùÕ£í‡R,fˆééR³XhíhiéhåÆ2¬­RxµNßmmÕ¿¼¦†›˜P¶in¦åVXº5|"ÈL”—sw®·i&ÒÒhôõéwŽü|mÛÊÏ›§Í=3B ]«&ŠÚŽTmmeÌN/ÚÛyÿõޝÌDk+ï[qqèÖ ýýýXµj*++QRR‚þçÔ××£ªª EEExä‘G&Ÿ_WW‡U«VaãÆ7B‘ó 2&«\ëëÙº:TÓ Ñ«N%"‚?CCÚ/,Ìݲ#ŒÊ«…26¦mÓÁ®.f»éÕ÷Énçο¨HŸã+¡³“©ìee¡[ƒF$$$à³Ï>É'päÈüøÇ?Fgg'ž|òIüð‡?Dmm-®^½Š?üðꫯâÝwßÅ–-[°gÏž¯~f„™ ‹X±‚xÛ¶mÃÃ?Œýû÷cýúõ¡Z²" Ó×ðDFrGtò$;†bBI «p׬ÑggVPÀÝí’%+!!p—˜Ùúö2"It iõyilÔ/ ìpÐ]»zµ>ÇŸ «ÕÝ‘ú:묛˜˜ˆS§N¡³³·ÝvVÏpsssñé§Ÿquê¹~T|0ˆŽ¦Oöøq~Ù‚MD[®ÔÕésüÔTëµJŽŠ }U Œ^·Ñ߯Ýn~lŒŸ;½j2Ο/ðe¡`e¥q†Tùƒ$áòÿüϬOKOOÇ­·ÞЦ¦&ôz¸x[[[çÆîiâ/qqô‡ªƒoVÍ|½â199ÚÕ…¤§Ó}‘‘Ú¹ÕüE‹º–é»z6M”›`¦¦êsü™§e¿|¹þ=½ôÀfÃ?Þ{/ÿÁ¼þ¹³³CÖøÀÀ>ûì3”••¡ººz2pþÖ[oá®»î Ú’µB(5$%1è|òdh Ýä9êzœ[ËÊôyóW ¡ ¤k@×Êq:ÿÒc–ˆÓÉP¤Ë:ÜŒ-[újwô?{KJðËK—ðƯ~åõ9ÍÍÍøüç?ŠŠ Üzë­øîw¿‹%K–à¹çžÃ~ð"55u2 >—1µÌ›ÇÓ©SÁŸÎÅ–MMÚïHM&N!Iêc6r ]Á9Vk`£g娇ñª+Wô›Ãqñ"°h‘öSgCî¬[TÚz5¸\Ø÷Ê+xê©§ðÅoÿùôÓ8~ü¸×§®Zµ 'Nœ¸æñÂÂB=zTï•ꊰ@aÁ ¶`Ìï˜Nn.‹õôÈRÊÍÕnnzrr`EsÙÑ*ûJ’XاG¨þ~n„ôl‰â I¢Ÿ—šÍA ŒŒ‡ãROþyï^|ÿé§C½¢!H äæÒ"гFÃ%%ú´Ÿ§àÖ¢x2ÐtÞP¦òŽ6íN«öíW¯rÜ€Ö™w.ë›–-Óö¸J8s†×lÅ(mm\{y9¾ùýïcÅŠ¡^QH D -â—QËv Jˆ‰¡€ÒÊZðdáBmæ¦'&V»nŒ™õj°Ûµ·ÚܬO#ÁÚZZÁ.V;ž.«¬¬àž7œN*ަ9‡z°–A D+–.eÝÃD1PÐÈϧ{CëÙòD‹4ÜPfR©Åé ¬M«ÞWýýœ¼§u|bp®Á`·G¯¯gšp¨‡SùÃð0päc‚¡n.i0„Ñ’ÒRwŸ`a2éçÊÒjnzZZ`n¬°°à×ÝØlei•¾ÛР}¢„$±]I°‡D]¾ÌÎâÅÁ=o ´´ð^UTˆAV^ DKL&vð½|Y›±®J‰‹cª¨ÖÖORw© ï´´ÀÒycb‚Htºó?FFø™ÒÚ]R_ÏN¾Z¸×”ÒÞÎ{b„ɆJp:™a92¬Z57ëS‚€P Zc6³Om­~}«¼±hS=ívm«EFVDãjëVbcƒH¤ˆp|œnš@]Ús¦[LÏVðÓéêbðyùòà3††€Ã‡y/.« Dä¾çÏoçl2Ñ?«uJñüùtÉZ´˜œ¬>«+©¼¤ðj‘¾;>ÎkÖr†üùæýýT„s¥³îåˬ‹Y¹24Uùs ¡@ô"<œ_šÓ§µpû"1‘î-§(šL ´ZH$©¼6›zבíÛ/_Ö¾e{c#ÁÁÊ bšðŠÆoŽèp'NЂ¯ªš›ý¸B€P zŘˆüÁ ‹SPh™úªE¬¤$õHTTð”°L ÕóÎQw¹¨lçÏWŒéØlTlzÎñdd„‰+V¿ÂÝ_˜e•—'Fçú‰P zC—Á‰ÁÉ$2›™R|îœvÇ´XhÝÈ ÷Ô`2qW,E(ÁÁÀÛr´·k?ïüìÙà¹®ÆÆÜ-~Œ¾“oldwë•+ç^E¼ $$$Ð28q"8ó-’“¹ë ´‘¡'ò¬@$+˜³AFGÕ»y´¨>¿rEÛ ÷•+ôç£Yáø8?çeeÆ.¶ŽãÿC5ßç:@(`‘œÌâ©`uð]º”;+­¬žÈH*¥@ÚȉŽ^$ÞÞÞÀv²ÝÝü¬h3eüJ¯6ðžÈu‹‹™ZnTúú€£G™¹Œûr#H0IKcóÌýÏe±°Ëé… Ú3Ðö&‘‘ê]XÁLåU›Âëpð¾RÁÞÔ¤m•vM {]éårÑò(,Ô>sLKêëyW­ ÝØÞëÃ(Í›7#%%÷ÜsÏäc<ð-Z„ÊÊJTVV¢a¢*zttwß}7ŠŠŠ°víZôLøæív;cÔ± IDAT6lØ€5kÖL>×pdfò ¦eŒÂóæñ‹­UQc|<ýÛÄ1ÕÓƒ™Ê«6…·»;°öïÃÃt¥hUà×ÖÆ÷,>^›ãÍÄ©St»5õÕn§ÕÆ©‡FìÏ £@¶oߎ7ÞxcÊc&“ /½ôNœ8'N`áDQÕk¯½†ÂÂBÔÖÖbÓ¦MxöÙg{öìÁÖ­[±sçN¼òÊ+A¿ÅäåQPè5šÖ“âbæµk5=1//°XˆÚ)…ÁLåU«@m_ÒР]á ÝÎTà`d=ë¶®HOã‹/ íÁ0 ä–[nAœ¿©ä%^°{÷nÜwß}€ûï¿»wï„……ÁjµÂf³!Ìè;ŒÂB~É››õ=Ox8…’VíæÓÒhѨ h«¼ùêN§ºD µ#v;´ŠÔÔpóˆ;M /ò½ fe»R$‰Ÿû+WØAw® ­šFøâñÇGEEžzê)¸&„V[[²&ZA'%%¡Â%²~ýzìݻ۶mã>²5+fÙ2ºs´!ë‹ùóLÕªµJV–úº“‰îëTL¦àea©ah(0áߨ¨]ìãêUÖ¡è‹ãaZ·[Ñ‚±1º¬¢£™NlôBÆ9Š¡È3Ï<ƒ .àСChhhÀOúÓŸo±X°sçNìÝ»™ZçÑëÅòåÌû×2åÖ%%l­¢…ÎÊ Lé©•ŒVòZ ¤úÜé¤UHüDÆá +L--ŒÙ,Y¢ïyÔÐÕÅ€~q±~c€ ¦@LÓDÆ„O522÷ß?Ž9ÈÌÌDËĸ¿¿Is9›ÂdbP¯©)°Ñ¯³ÁƈZÄ]Ìf ;µ)¹jã ‘‘ú»±Ôf`õô¨ ·´hç:wŽB]ÏwGß¿²2ýΡIbÖa{;³¬ŒœJ|`(2=ÞÑÞÞp¹\xÿý÷QZZ ظq#Þ|óMÀŽ;pçw*:~ww7`çÓOkÊÙL%ré]!z‘™Éãkq޼<õñµ­I‚‘Ê;2â¿q:¹PoЪò¼»›kг¢º§‡ ¯¼\¿s¨ÁfcÝøxZõÂe £@Ö­[‡¯|å+øè£››‹ƒâë_ÿ:ÊËËQ^^I’ð­o} ðÐC¡®®EEEøå/‰ï}ï{ŠÎ1oÂEð›sçðÇee ´¿“–Èé…gÏê+$KJ¸K ´˜1<œþåÁAu¯OHðÿµÁP jŠ»»Õ[W¯Òš 4Øítr„ÀÒ¥g&hÁVVêœ÷‡«W™F\Z:·Æä^&Uéã?¾æ±ßýîw^Ÿ…÷Þ{Oõ¹þíí·ñ‹7ßÄÆ²2üÃÏ~†Š-[TKS""ð;y’MèôøÅÝ®³& (´**ümz:]`þdÆÄÄèŸp Æ…ÕÙ©þ^67S Ê… ÌìÓ+ûpx˜1´•+³»w¹xÝ.³¬Œ¤ÔnnØ;þüO~‚¿Úµ Žc¶†QšüEGÓ·|â„~n¶œº"-Ì‹å—W;*9ÙÿÇ`X ãã´®üAÛ àŽ>6ÖÿóM§¯Ás½F®ÚlìžPYøZµbd„tSRhyånè»~ûí·ã‘gžaÐñرÀºÍjI\3HŽ×®p:¥¥Ú ŸÊÏW×ÞÄlæNÖŸ^]þ>?2¹P‹yçò.|Ù²ÀŽã »qyypGàÎD{;ÚòåÆ-^¼A¸¡È$ññ4[ZÈF³ÃÙHL¤KB¯¾ÑÑܱZȘ’ÂX†Á>oãFÁéôߤ¶úÜfãç,¹ë?¯úX71¥¥¯S \.Æûúø}5r·ß¡@d,î²bbh{€‘7RSén:uJ¥VPÀ”Ì@ScssYíë/rÄÂÃõsí©  «Mßml Üúà{§Ç.\dIpzi͆ÕÊ,«ôôà4‡(B(édgózò¤þÅ}J˜?Ÿ–ÂÙ³ú¿¤$pWVF‘¿J.:Úå¥gSE{`9¼fƒÊS©““ý{'’Ä ¶C¢$‰Ÿÿ‚‚ÀÖ¨­­üŒVT>*X )Bx#.Ž…Hü’†Ú¥•Í5iÙš]&.Žm­Ii6™ÜJDÍùý©KÑ3îo<£·Wõ¡Å¼óúzZ§z B:}š™zzå•âtr-ÃÃü>2&X  BøÂba6Tb"Mç`5òóEAÏz´©_´ˆ dlLý1rr(ýÅ_7VLŒ~ˆ¿.,5ñIbÝB ó·‡ÙCMš‡šZ hlâ÷.3“n4á²2$BÌFf&É©SêvØZ²x1wßjâ 3a2Ñmˆ++,Œ5þ¦æ¦¦ú÷=]Xccþf‡‡ýo—ÑÞNkM­@”$¾O]4¥¶–™V¹¹ÚÛ._¦µ½b…6ýÁº!ˆbb˜õÑÓÃ/o(»Â––rZ+³„ ç‰ö1ªP37Ýl¦0Uš®¡_ÍŽ?®Ê‘uY@W®& ›šhhíÎijbl&óC|áp0ö26F—•QÒ†> D)f3–©©4­ƒ5ÜÈååt9i[TDA¢6Ë)*Š÷Éß{“šút^Iò¯Mûª·—.Qµ•Ü##LìÐÚBhme*vq±¶Çõ‡f?ææòs(˜â/àgÎèßVÃr߆uãa}a6³—R ãv üÓø±X´/°ô×¢P3¾6Йz¸®:;“ egݦ&ºÏV®Ô·¤@s„QCt4]ZT$zU‹Ï„ÅBñ… ôÅkEr2k-Ô¶jOLdÂ?VŒ¿™UzŒ·õ'…×åâ?E‡V+Ÿ¯Öõtù2-5- úz{YHZQš õø8kM\. ªJŸŒ2påÊÜzë­())Ayy9víÚ¨¯¯GUUŠŠŠðÈ#L>¿®®«V­ÂÆ1n¤®á^ D-&MþŒ šÞZ q¥È|ÏœÑ6Klɦ‰ªm¢¦Õ{l¬ò{¨G*¯?)¼jÒwi[2:ÊØT …‡ž r׿bEhúHõ÷³ÝÂ…Æœh¨!áááxñÅQSSƒ={ö`ûöíÁ“O>‰þð‡¨­­ÅÕ«Wñá‡^}õU¼ûî»Ø²e öìÙâÕÏŒP ’–ÆܹsÕR¨%2ÒÝÁW«à²ÅÂŒ¯óçÕ½>=.’ ü2¥G*¯?)¼þÕHØíTjgr×Ô0þ¦••`µò˜••¡é¬ÛÐÀŸª*Ö ]çddd`ùòå€ùóçcÞ¼yèííŰaÃÀý÷ßÝ»wàdÕááaŒŽŽ"Ü(Í+} ˆDE1kÄjeºo°]Zrßãǵk6(ï°Õ6˜ÌÌô/F”šªü\zX 6›r24äŸ2hnVûhmå¹´š®7:Êâ¼ÊÊ໌ìvZf3-ƒ G=8vì\.¢££‘âïÉÊÊBkk+`Û¶mxøá‡±ÿ~¬_¿>TKU„P Za2Ñõ“Í,-=' z#.Žp-;ø³YŸšãegûg‘Y,Ì„Rr®¨(í ;].e®›Í¿8†ËEŨ¦ªÛngÚ¯V©µv;›s._üªîÞ^v¼.* ,‘ÀÀ=|xÆ¿÷ööâßøþõ_ÿõšé«žäææâÓO?ÅŽ;®óm4„ÑšÔTf“\¸ ®2;’’èO>qB›ö+aa¬R¿xÑÿ×Ê£Uýé'¦´¨Ðd ]{™®.ÿÒw[[ÕWŒ×ÔP‰k!DœN~.JJÔ·ŸWƒ$1ÖÒÜL+=11xç?{ùeܼ`ÞyúiŸÏÃæÍ›ñ—ù—¨®®Fjj*z=>ë­­­ÈÔb¬q D""øe‘w|Áœa1owÿ§Nis¼ôt^‡štáü|ÿ‚éþ¤ój©DFG•ïÈ»ºüKßU«@::èšÔBàº\´L‹ŠÔÇaÔ06F—Ud$]fzMK ‡?|ê)|.%û_z /½þ:žûè#¯Ï•$ <ðÖ®]‹¯}ík“É„êêêÉÀù[o½…»îº+hë× ¡@ô¤°IGŽ0å7Xddp7¯ÅÀ(€mNäÑ¡þÁ¥î¼¸8å™Xj:ùúBi ¯ìbSê»ïêâûào–Óø8kF/öïuÞ;ëæå·Æ¢»›JkéÒзFÑ«Ÿ}†žO?ÅíÛ‡×ÏŸGžàóé¿ÿýïñöÛoãý÷ßGee%*++QSSƒçž{?øÁPXXˆÔÔÔÉ€ú\âúÙ•”º´ÎœáÿµLÅœ‰œfº\º¸ Šˆ ª­eœÇ.dJpy¹²çGG+èr-ˆuJSxûúükoÞÔ¤üº=9ž‚W‹ôÚ3gظ1XmÐ%‰Ÿ¹±1ÖJe~º ð³l6#µª ÿ´¿¢—ýÁüœ>b{GÕr…AGX Á "‚J` 1XÅA ÒjP3rv: PÐú÷º¸8^¯ÒN¿JÝXZ6UTªˆüi_28H·˜¿™N]]ºZÌá8ž.+=ºözct”Öv\õ׋òèîæuµ´0&UQaŒ![@(`RPÀ ôÑ£Ü̓¥KéšH ˆ’uóQ ”+1¥cnµLåUj (I46ú_ çtuu|Ï¥®Ž1‡`e~÷Ýw£¨¨k×®EÏÄîÝn·cÆ X³f ô˜® 3;¢¢èÒ d6ùl„‡ó\§OÓW¯–ü|Z þÔbäå)¯ÎWÒ®D‹¦ŠJèýýʲ¢$‰;svä|™‘>4D FïκV+] سg¶nÝŠ;wâ•W^ ú5LNÝ'Nø×Ä_¢¢9q"°¼¿®¬°0 k%UíJºój‘Ê«ÄQš¾{õ*R @@¯¡E°b…¾•Þmmiµ˹Òà8@W’”ÞyófW Z –Rj(Ißmnö¯êº®ŽÏW›á36Æ–5úe 9´Véjki¬LÅíêb¼¦¬lîºÝ ˆaÈtúûû†Ç+W®Äƒ>ˆá‰6mmmÈšÈ5OJJBÿÄŽvýúõØ»w/¶mÛ†G}4dk‹…Ðøx0iÝyV&>žA|y*œ.äîT©ÛM@³]Sx8…×L T d¶ô\»Ây6«¢¯÷SéÆehˆBYm½ñq*ÿ²2ý„úð0]V °6Åàa'q¹¸©9xŸ•+¹~¥iØÅV8Ô××cÆ 8vì,X0éªò…ÅbÁÎ;±wïÞ™;[3ý3²²èÞ8u*ð_$'3åôäIuÖŽÉDøÙ³Ê_£tnzròÌé¼ááúWõ+;jlTžº+I@¦ÖuåtRéëWwqå ׸b…ºVô¡ÀéäûpèïñêÕ,ܫވ9€¡ˆgïûÔÔT$$$àK_ú`Ó¦M8yò$ 33-³&úûû‘¤pªÙÐDfÏw¿øE¼ÿ“Ÿ·K®ZbcùEèêâZå—–Æ ”Ó§Õ½>>ž?JH%%qg8›ð÷gJ¡”ÌQRÿ12BEªÔhlä®^ÍL—‹–Ga¡>­Ñn&l6ºRç®ÝngPüèQÞÓêjºçbŽa¨;ì9dÅd2á _ø<Ø·o–-[ظq#Þ|óMÀŽ;pçw*:~üDÿš¯ÿýßãÿõ_ñåŒ ìøë¿Ö¿/PÌfÆ+RRèÒÒz@WJR•” ™a¥ô^ææÎž‘•˜8{ÍJX˜ú€’ºÝ>»õ§m‰ÕÊ€®šµ’Dk4;[ŸÌ¡ÁA~¾rrèÚ4ºËÊfcÇ©Sün¬YCÅlôu_Gƶ[·nNŸ> «ÕŠœœìÚµ Ï=÷î»ï> !??¯¿þ:ࡇÂÖ­[QTT„ììlìڵ˯sUTTàÁóçqöìY|pçm·!qþ| #Ø22(TOŸ¦Òº€+/ݺ:ÿ§à™Íô3Ÿ;Ç îlÌŸOWÃÂ…3á##gŽSÈt55³ЕÏÇÇy¥Ö@M 7j¨©q[‹ZÓÜLkoåJã·íbÕ¸ËEÕu8¤j®`òñÇ{}|¿—–ÉQQQxï½÷>gii)>8p€¿ Ð 6™(ÔŒšâM×Â… ÜÉj_XH%ÐÜL…âIIôJÒ^M&*À¶¶™›ï¥¥ñx¾Šó䦊jÞ¯‘‘™cJ®ÃŸûÔÜÌëQ³I¹x‘ךíÿkgÂá`1]Bk"ŒL_cgááìóÌÉŠ¯Ê…R™^TÄ ë£Gï¥f3Gz:³d´j*(³lªÒ˜†'‹sw¨Ä­¤dnzZÚÌq@Š g³@f›ÿár±s°’º›)¥jºãÊ ZÏ’éï§Ë*?Ÿ;y£ÒÙÉÏy{;–/Êà 2ØX~@Ëʘùtè~P’žNwQM6íÚ=)+£Àó7ˆm±°PëüyeÏMLœ¹XDÝD¾2ÄIåµÙ|¾åY3¹×ÚÚ”»kj(üüõÏ_¹BKÉßA^³ÑØHE_U¥Íì­‘$~¦äf¦²’5‰Ý Ä‘‘L“\¹’>׃¹[Ö³W•¢¢èÒblDIËt%˜LTNMMþÏ.IIáë•4ˆT2+$9ÙwõzT”ú–,’ä[ +™}ÞҢ̥ÔÒB÷ž¿)·´pÔÆL¼a·³q ÀÏv ý·ôÀéägîàA*ñU«è0Ú:„™°0ÆV¯æ‡ûàA <­µ˜L `gfÒ%¡tùlÈ|/^ôáÒ¥l8Û}ŠŒ¤p˜iºÝygRÀìñîn*¶ÙÚ}Qøë"êéáë”$$(¥¯Ê£°0x£••2>Îf¢GŽðóP]Mךh§nh„QŠÙÌ`iu5…Þ‘#FJž7ÿÂåM g#,ŒÅd55þ¥ËŠ÷Â…ÙŸ»páÌ……‰‰3÷Ï2›ý¯Ù266óß•Îü8wŽ®\W̄Ӳ³n]×¼j•±²–FGyNœàºª«™T!RqçBø‹ÉÄ~u5w §NQ¸êÕnÄ_"#é×cA˜Å’f§Nù×)8-çŸÍOEìK›L\ƒ¯¿GGûÿg  ΜÕ5<ÌõÌ–îÚÑÁ ¿?bÃÃŒ­X¡ÍîÛngBHx¸{ˆ™¦Ëµ¦†q¤Õ«•Ï›¡@!-;º¬,~éOšÙ,L&ússi)ùë~òFT“ Nœð¯}Ȳe´Bf³òòfž/2S6–šùè3Îæ¾jh˜½pp|œ®NÆÊÚlL©­¬ÔÆçßÓC—ÕâÅþ§dëE?Û°Ô×ó®\iÌ ¾@BhARwŒ‹ñ‹qì˜ÿg=HIáôÒ%ÿ†?ù"6–‰Ç+…‡ÓÕS[;óóÒÒÜc]}ýÝWDM*ïLHo¯o¡66Æ]ýlñsçRZ£c·Ób,/¼}ˆ$ñ=oiáÎÞ5M]]ÜÌ´¶ò3T^>÷ç§ „Ñ”¸8~1JJ˜³~øpðF³ú""‚.-¹_ Í¹«>qByÜ!#ƒ{6K(;Ûw:²<}Ð[œšT^_ˆÃAב/ÁßÔ4{-GW§ÒµÃÁ÷¦´4ðN££Ô11ü,†2-ILu>tˆ*ù»1×Z |"ˆDEÑuSYÉ€èÁƒŒ¡L^´ˆ.ƒ£G• tš‰”V†Ÿ:¥üšJJ¸+Ÿéù™™3/úê¥&âtz®ÝݾÓwN ™Ò{¬•ÖmÈŠ}éRÆ‚¡«‹V̲eÚW¬ûƒËÅ$Žƒi±UUÑfô)¿ DOä– «Vqçð ÛY„*8)‰_æ†eíÔgbþ|Æ ”¶qŒ¤P«¯÷ý³™ÂÙ—Õæ+WM–/fŠ´´Ì>ïü K%;I¢À/(à{£Iây;:øY •kHVž‡ó=©®æµ‰TÜë¡@‚ÅB·Gu5³`ŽáMïYÞwÏÎ>z4°4ä¬, +%©ºHÿ̉yyT²Þ˜© Ðä!QÞ˜©:}¶ÊóÞ^ s¥rOŸ¦Õȼ ›;!ÝB!¬ÇÆø8vŒVTu5ßk‘Š{Ý#H01™(t««ù…?q‚Ù[j+©!?ŸÖѱcõü*( 2šÉ²ðd¶9êááàÞ\U&°7ÅëOEúȈ÷úÐïÝûÕ«´L|ÅFœN\+[CM b •¯^¥±¬LýdÃ@aÖØ™3¼7kÖÌÍyéÕ*ÒÓ™!3>…ÉéÓÚ7EœÄDº<š›i©eñb o%³Ñ££TŸ©}ÉLsÓ}¥óú“ÊkµzVÏ侚mÞù¥Kʧß]ºD…§f&@w]M ã5«WÁÀ7?/Òb¬ªb\LpÃ!H¨‘SmåT×ãÇg¢¤%aa öGDеæO¡ '%%¬;èè˜ý¹yyT¾~L …¤7‹ÂW:¯?©¼¾Rx{{½»Ÿø|_µýý¼oJ áššh­¨í~;2B—Uj*ïy0§îõôÐíyå “*+‘"lp6oÞŒ””ÜsÏ=“Õ××£ªª EEExä‘G&¯««ÃªU«°qãFŒ‡ÂÅí'B…øxö=*.æôÈî0ƒEn.3ŽWÞòrš•¼~6W–¯&‹QQÞ•œ?©¼ÞRxNºÈ¼ ä†ßmK\.úÿ'¦eÎHk+S™•º¹¦ÓÖFwQy¹>C¥|ÑÑÁTÜ®.“j‘n|±}ûv¼ñÆS{òÉ'ñÃþµµµ¸zõ*>üðCÀ«¯¾Šwß}[¶lÁž={B±\¿ ÄhDGó Z^Îß¡C¬) F p|<]"mmtOø{N“‰»Ò††ÙƒÝ±±ÜEûêÙ•œLaë­KBµVš<™P Þ‚è¾Òwm6Þ_³®ŽÊw¶ÕÎNÆ,ÊÊ”­Ñ§“Šc`€ïO0ê(\.nd b^¹’ ‘Šë7·Ür â¼±ZqñÀ¼ûóŸãì‘#èèé5"134¬ôT©©©èõص¶¶"3iØ ¶s‘Œ Z$iiî<|»Ñ*Ål¦ß>)‰Ù?þ´ ‰Žækgëà»h…µ·¢ÆÜ\ïq’yó®uc)‰ƒxKáíêºv‡/IŒYx«k°ZÙÒd¦ªôÑQ¦fûÛYwhˆ÷9+‹Â\«àx IDAT/å14Då~þ<¯cÕªÙ'0Þˆ8´vëêh:45áø©Sh‹Åƒ¯¾ŠßöôààÕ«xa Dò°¢M&ª««'ço½õîºë.Ý/E clÞ¼ÿó?ÿƒÛo¿ï¼óàóŸÿ<†&¦ëµ¶¶âk_û~ò“Ÿ`tt÷Þ{/Μ9ƒœœ¼óÎ;HMM…ÝnǦM›ÐÓÓƒ_üâX8[Ëí¹Nj*é~(ŒõH­\°€ÏéÓÜ•+ÍŠ‹£årâ±Þvâf3ýû55¸žX,¼žÞÞ©µéét yZ&r&ÖL“¬ÖkÛ†tw_[“ÑÞÎc{à553Ãív^ïòåþÍð¾|™Jk&‹-Pz{i=ED°ÔWGâ•ÑQÞ£¾>Z¦ ?/ÉÉSÚ²l-)ÁV…‡\·nNŸ> «ÕŠœœìÚµ Ï=÷þèþ=öÖ­[7PŸkFlß¾ò'‚×_}ò±O?ýtòÿ7ß|36oÞ xíµ×PXXˆwß}/¾ø"ž}öY<ÿüóسg¶nÝŠ›o¾ÿò/ÿ‚çŸ>è×(xGFèŽcÜDë⮘îTÏŸ§K«¸X™<)‰ë‘•ˆ7¡œ˜Haëm×_P@¡íy=Þ(ÆÆÎ>‡}ddª«LîK6]±]¹B×Ótšš¨¼|eB9¼Î’åÂÙá Ïû«W¯2Oå§—‚šKH7_²ÂçûšœÌM’F=Å>þøc¯=zT“ã‡ø°¦§ºyÒÚÚŠÆÆF|þóŸìÞ½÷Ýw€©)paaa°Z­°Ùl»³Fbb(ÊÊø>tHYaŸ?˜ÍŽóæÑÕ¢´öbÞ<ÆoNòýœ%K¸;žî¢€Ÿ~®øø©óß•ŽŽNþ==×ööR¡MW*6﫯vî.ëhŠŠ”[̲ÊËã`-‘$âä}ª¬¤Ò¿Q•‡ÝNEzá?»GŽÐÒŒåwfÍZ99bV‰Bæ„”}çw°eË–ÉßÛÚÚ••HJJBÿDÍÁúõëqï½÷bçÎxë­·B²VCI·‘ÃÁ]çÁƒô©gei—U3>…äéÓüÂ) fdP9œ=ËZ—é˜ÍT"çÏó‹ì‰ÜÞÄóurUºÜ=2röJúé]]]×ʽgWÕÔøÎº’;ëæå)·ü©¬V®Ô¶¾Âé¤;¬£ƒï˪U7fGÜáa·u1:Ê{,÷Ó3¾t1gÈ /¼0ëó, vîÜ9ëóú/_f†Ðõž¢ƘHAw¢‡Qˆçæj#P¢£™¥uñ"ã%%³7'‡JäÒ%öКNJ w…Ó ûhxfY¥¦Ò¥¤´-ˆ$]ûžOÝmZ­¼oÓc-->¾ÜRgθ[ÜÏÆø8or2•‡VŒó~ôôð=®®¾q„¤<«¥¯VÓÉ÷5%…ÊŸX”@1†R Þòž/_¾Œ––ÜtÓM“eff¢¥¥)))èïïG’ÂY c»Óoÿñ#À‚ùóQvÓMøÃ?ýS,¬ªº~M{³™%'‡ÂùèQ ¯üüÀw¾&­ydiiéìæÿÂ…t#ø*Ò[º”.†ää© Inõ.»zÌfžß³¶Cž âms0½U»·–&ÞæQ¬YãýzΟ§‚›°Šg¤¯×^\Ø OFGû²Zy?ý™Ã>W±ÙÜÖ…ÕÊ÷?9™›ŠE‹®ÿÍ¡A0”‘¼´Îxçwð•¯|eÊc7nÄ›o¾‰çŸ;vìÀwÞ©èø‘ âß÷;,_¾}ô>øÅ/pà³Ï°06–‚B6s““)®§œÉD—Ff&þ©S  Þ#-÷ëÔ)ºf¼´t)wí--×NϳX¨$.\˜ê2JOw xY@Ì›GkE¼Ë©¼Þ”ØôÞéÕçv;…ñôÉ€55,xôöY¨«£Å2Û˜[€B~`€Áy-ÚT »‹J.T>Bw®árM v;ü¼¦¤PaŠL²aâ-ÕmÍš5xçwðÒK/MyîC=„­[·¢¨¨ÙÙÙØµk—ßç Ã]wÝumþµÝÎi{;]3&cJ wŒs ?"ÒÒøÓßÏ´ÙÌ[ cU##éo¯­¥")-Ù¥UZʸAxøµ™Wii|¦§ïff²)¡¬ ÒÓ)Då×Ë©¼¾ˆ§°éî¦+S¦¹ùZE Y½ÅåÚ•Ù)ÚítY¥¥1E7Púû©H-¾g×[À×nw+‹¡!~© ssE[a˜wÂWªÛÁƒ¯y,** ï½÷ž> ‰ˆ 0’’$qר×ÇÔNÏT¿””¹¿ûIJ¢Pvg@²›5™Ûè顪¤ÄwF’ÉĦ‘ÇS(Lφ*.¦»MnãÐZ9|Ø­@¦ÆÆNÍÌòddÄWq¹øÞÊÂÈåâš=Ý?v;c Þ\WííüL”—Ïx;ÐÛËÈL÷A)]]tûÅÆòÞ£©¢ÞHÒÔ`·ìHI¡K0>þúò\gF“‰B6)Éí¯·ÙøaojšZl”’â=ýs.Ç̧ÑQ*’ÚZîÆÕö`JMe€XÞyûjó`63½ôèQ sÏ"ÀðpÞóK—èò’ŸŸ’Ba*»ŸbcÝÁð˜ߩ˞1é–MK˵1Œsç¼×ºtu±õÊLÖ„$ѽeµÒ*S»k–$*«Ë—¹ÞŠŠ¹Ý×á˜ì–$w°ûFN1ž£¢†èhþÈ©«N'Ý r•¯œ"[)s)$*Š.9£§¡Á¦ëïN0"‚þþº:ו•y¤rßcÇ® ÂgdP€ ¸•K~>]d²‘»óÆÅy/0”ñ ®wvNÓ´µ1£L¦³“ëŸèîë£PUåû~ŒQqfd¨hËíÔÛÚxœ¹šŠ;2â¶.FFøþ''ó½+,Áî9ŽP Z`±¸ÛŠÈ óKséZx¸[¡Ì…à|x8…ßÂ…dºƒãþ ²ÂBÞ‹#G¨œ¼µ §%rü8wÙžî™’>¾f ï[DÝÐ]©©Œ_ðïJæ˜È¯¨,RSÝÂÌá`\ÅS¡È¯¹x‘Ê×àëêâk•d£yc|œ×ÒÝMwÝ\JÅu¹¨è{{¹¡r8hñ¥¤0V#†P]w¢qqü‘w¹ãã¢î¾U îŒ/£º%,îøóò¸>r„Â6?ß¿„‚äd ÞÓ§ÝÙ3Ó‰ŒdLáäÉ©Åu¼uuî}Auy¹[¡Éé¼²ñ¼ccn÷ˆÍ6Õ*lnžË8žqOE92ÂÈ•+½[Q’Ä÷ÕnWg-ŒÑÚä½Õº*]ÆÆø™îíå†Iv÷Ê­@D°ûºG¼ÃÁ"<œ®9¦ ÷áéë£`¶Û)Ôd+Åh™5&“»š½³“.©¸8Z(J]tááÀtW-_~­Љáî]î›% ¡¬,¾FŽuÄÅq‡++†yóOOçz¦·,ñÌÀòì¾;8ÈçËÊJî¥åiMŽÑeæ+þ`³Q1fg+«ñÄj¥"´Ûy/ÕŽ»ÕI¢&»£ìvÞ÷”*÷@²÷s¡@B…œš˜˜èNå—³¹ÙœOLt§Å.+¾>ÖH„‡Sø)Uz¼¦£GŸžñO àøñ©î¢’ òÕ«yÿò󩌖.¥O]nt(§òN/ôT r«”†·UãtÒåèÙÐp|Ü¿ñ–õtõ*×PVæ_FÞÀÏm2ž>­ããî¸Þà ˆl1gf×b¡@ŒDTã r‹r§ÓBÜØÈßccÝVJ¨Ó8åVCCt/¹\T$J*¬)¨Ïœá®ºËFnŸ}âì&“ûþ46ò<©©<¯œ´ 7Rô6Äje0Z’øüðp*lùžtAyŽou:©ÄŠ‹¯UŽ. ].*4¥Áàîn®?:šŠ/ÔÕê¶.žî›mj °·ãž„…1pÞÜLkdùò©;Û´4wß(9F‘›Ë8LFEv6ƒüùùnÅË{䉜ÂÛÛë¶x<[©ô÷ó\²kËå¢ò*,¼6è?2BÅçÏ\”Ž^gR¯%”;xyc"»=³‹ŠŒ£Ô†G(¹Fl,äör^}g'·$Q ËVJ0Ut4ÝLržœìk0“L^×{ìw»žñ‡ÌL^ã¹sîŠï’´W¯æßä1äî¼99×Z rÆÎN¾Æé¤k¦¸˜Êâüy÷üI¢«,'çÚâF¹&cùòÙ­ËÅú’ÖVîä}àõFvÊÁnC’ d®ænK¸ƒr|BvÊ %¾öˆ*¹­¸ÜN>;Û·…”@…pö¬»"\V:¹¹tUÕÖòñ˜^ïåËüÛüùŒE¤¥ÑjÈÏwŠšŽ¬4Ýr²Å$ôÏžå±<Û«¸\Tbf3]o3Yz×ÖÙÉëö¬¤×oC’¢¢øÞk8$I „¹þ{w%$¸«¿åtË+WÜé–ro¡ädývÅ w¸ùùÜ…>Ìl©ü|ß…ååܵ92u$la!xs3¯+?ŸÇKO§9~Üãp¹¦×áàùFG©L%‰.¥êj [«•-¿Æ5ââ¦6x´Zé²Z¸pæÊ|»V×À×X]ÀÍSˆœ.»wï¶ììë§w›Àr#Iá*ûë傯¾>î”å‚/ÙJѺàËd¢0ËΦà>vŒ ¬ À{ëŠìlºXNždP[¶®–-c<¤­n(Ù•UUE¡ßßÏõ÷ôÐ ²Ûù:9…WNßíèpß‹sçÜsØå¬(Ï•ÖVþTTøNWákGGùZ¹íŠˆ!I!ȈÙì¶>dFF(”êëÝ-'d?yR’v.Y‘õôpWé½J9.Ž®¢sçø\Y8–•ÑMNÅ’”D_PÀ8FQ--9•W¾¶˜*Ï“úz*«ÈH¾fdÄ=ñÐé¤ 0"‚ëð&˜©8$‰Ö‰· û@ðl‘#†$ ˆP ùÎá ðêé¡t¹ÜÂ+99ð¦wrë—ÁAweþt!l±Pa´µÑ]%®+*hÅÈíÌ¢21™¨ø††¨ä@ºÕÊ5óÿññܽ÷÷Ózéèàuʭ݇†hÙzÏ$“{žEFRaiÕ‘y¦!I Š`·Àp"ðNXãžceåàüùóS‡oÉÁy5î“„ºFFhŒÑš˜ž‰•˜Ę̀‚·++©DŠ‹ùSSC!ÛÐ@%c6»ÛºË©½ÉÉ žÓ¶|9ë2ZZÜ£e¯\¡BY±âZ%yõ*³Ë¨ØQ¢ò$¹3­<&@ IÌ!„('>ž?¹¹ü]¾ÕÖFaÈð­˜ e9]W7µÎ"6–YZçÏS軕ˆl™Ølî‚Ááa·2:ÊõÅÇóïW¯ò9v;•VUÝCgÏò<žv%‰.²–*Sµ©¸ò½êíuI’ïUNŽè%˜“ˆO­@=Ó‡oyîªÕߊˆ`Úá`ÆÕîSf3çÌÒ*+£9q‚Ù[§N¹]WÃÃT ²"èï§_°€‰Ë–¹›#Z­´`–,qmÊ)È´€ü©6ÜÖZo¯’$¸n D f³v÷ÂÂß((àîÿÐ!**Ù*IL¤*7—ÈéÓ|~{;ˆÙìîÈërñ<££Tl 2€¿b­‹înw÷_¹²·—ÇVÒN]ŽÉÁn1$Ipƒ ˆ@_¾e6SçäÐ8zÔ­ V¯fÝFw7­‡K—x®ÈH*‘±1·ð§ÃÂÁ’Z‰‰tYÙlü}d„5&‹û¾&9c­·W IÜÐ擾yóf¤¤¤àž{î™|ìW¿úÊËËQQQ;î¸}ýFGGq÷Ýw£¨¨k×®EÏD n»ÝŽ 6`Íš5hhhÉufA¾UXHÁ½f ­ §“ÙX‡±(°±Ñ½›¨,àóSS鮪©¡°Ÿ?Ÿ¯]°Àí¾qgZY­T&²5”Í×ÊùS§[ÉÊbÊ®gæ•ËåNo>vŒë«¯çß-âzV®tÏ‘ÊCà…>øK—.ÅâÅ‹ñóŸÿðÞ{ïaùòåxê©§B¼:õæÓ¾}ûv¼ñÆSûö·¿]»váäÉ“X±b^}õUÀk¯½†ÂÂBÔÖÖbÓ¦MxöÙg{öìÁÖ­[±sçN¼òÊ+A¿JäÁ[ååÈrkôövZ‡ÓÒèìd\eÞ< úœ þ¶6 óŽZ0ããT²Ki`€ Ån§…ÒÕÅç74P,ZDwVRMGëO¦Òèꢥ⹾¬,1aO ‡ÃÇ{÷îÅñãÇñÜsÏ¡··o¿ý6N:…ŽŽ Ƀs ø°n¹åìÛ·oÊcóçÏÇàD{†O ÛÙ½{7^xáÀý÷ßêêj<ÿüó ƒÕj…ÍfC˜Èj™»Ì4|«µuêð-¹Õx}=ÿ£Õ04DÁ?<Ì uX•’ÃÁ¿ww»g¿÷ôЭ%†$ tàðáÃ())Á‚‰1 6lÀž={àr¹066»ÝË­ñ1´”ýñŒ/|á ˆŠŠBaa!þå_þÐÖÖ†¬‰‚·¤¤$ô÷÷Ö¯_{ï½;wîÄ[o½²u 4f¶á[V+]GÑÑT-ŽæfÍ-âkÇÇÝó?äþVññT%%bH’@<ådgg£µµ>ø >÷¹ÏáÞ{ïE̵f «@\.xà|òÉ'(//Ç“O>‰¿û»¿Ã_ýÕ_ù|ÅbÁÎ;ƒ¸JAÈð5|«·— g`€®¨÷Þ|5©©t%'‡nvŠà†Ãä#‹ïŽ;îÀwÜäÕh‹¡ˆçîêê”O Ú²e ž~úi@ff&ZZZ’’‚þþ~$)™€çÁŸßv¦¹¸n¿ýv<ñĬ^RœNº«dWW{;]S‘‘n•ÕJK$!VˆP •<ÿüóøÝï~7å±A‡Ãës333ÑÚÚ:ù{KK ªƒÑ©9JHrÆ €´´4  ©© ùùùøÝï~‡¥]N7n܈7ß|Ï?ÿþå/ùšÇ¢¢¢ðÞ{ïé½$A¨P:$i`€Åƒf3Ój©,>_>–œ%+“‰±sçÜï³ ß’û{‰ì> î¼óN¿=%sñm„žáa·Â¥‚˜iHRw7•Et4[… ÑÉÌdMHx¸{ŒïØަ‹Êf£ª¯gÏ­ðpþßéd1`R’÷á[½½Ìê’‡oÉVÊÍž´@(Ap‘[™ôõñ_¥C’ä1´—/SÈ——Sø_¸@¡.·2‰‰¡¢0›©<¢£ùzY‰Äİ·VI ;þÊ‚6 /]¢kK®FW:|K~Nb¢Î n„è‹Ü>Dv{6S,(˜}H’ËEßÚʶ#UU|ÍÆ.¼¹¹tWÉ3ËÛÛÝVGXØÔfŠN'­•¢"ÆÎç'%Qp··³EJOã'ÇÓªYµŠóAzzØèÑbáñòóiý>L‘Ÿ¯,îkøVkëµ¥’“Ep^0'ŸZr¼ IJNæÝ[°Û¦´¨ù™Dn="wÐu8hA””ðÿ6ÝM±±t'¥¥Ñê E’ÀõK_ú4É¢EnK¤¢‚ÙW²K+2’ה͟«W©°è.óÇ5¥tø–¬PÄH[Á@(wd¿~_…°Ë¥Ï¤ÁÁ©íÑåô[OÚÚ(dËËÝE‚'N0–Ïë+V0®±t)•ƒËE!<0à¬÷õÑ=ÕØèžRUÅk=y’Ó srh­?NKijµ»¬z{©Ì""¸f5ÂÞ×ð­Þ^®oz¼h¦á[Aˆ D@¼ IJJ¢ÛfÑ"í3‹äR‘‘´^¼¥Ã:¬Õçð(9–qò$Ý[)) Zçäð¹•A|<¯AŽIÄÆòwy¨ÔЭ’¤$è³³iœ= ”–òõ«WSÁôô\k]¥¤ðgp-R$‰Ibb`÷$:šy98/g¬õôL¾%[)¾2Ö‚ !Ȉ\Û Ç/¿²rª‚9wŽëÎÌ䮿¦†n-‡ƒ×•”D‹  €n ¹·•läå±n¤¼œÙUì—%§ô.\È¿76ºÝJYY<îÉ“ü»<£Ä“èhZ.v»{H•<»]kââø#çåªýöv*`jp^M"ƒ@ ¡@®7$ij°[îü!Ir*lGñêÕ3»ÂœNZÑÑÌŠòÜM×ÕQÊVESƒæQQÚ¹¹î´Ýéç £ ŠrÏIÏÈ ÐÍÌtO?\°€1”3gÜ®-€_½š ¬»›Ïñvü›ÃÁë>p€×­_q¡¯á[½½¼ùºe…§Ï:7$BÌu·+Jž!Oaª!Ir1^o/~uõ쮕ÁAZ‹OuÙÆv;­€ÖDW…º$1;ªºšÿΛGEâ+àœÀû”›Ël«ÌLãâkÃÃiMœ<ÉÿËYSf3oo§K«¬Ì·«/,ŒÖJ~>…ø¡C2r­p§²MOwÏ8OHà}”3ËÎãyL&þ{ü8ﯧB[°€¯=sfv7•ÙL¥‘“ãN–³®‚©Øg¾ÕØèÎ˱¹ý‹@0 B—ËJÛ×çÇšœÌ]³Q¾èr3C—ËÝP ‡{¬lUÕµïúÿÛ;óè¨Ë{ÿ&3ÙW² $eHH‘šç~šÐPhE_|óËɯ-†‡#Çdz‚¬¹Ú¦à¼÷„Ú]QQ˜‘óæ[öÎy^ß늇ßa­pÕ$)) »Üå’ð57‡Bs-.–gJ†ÉfÓ&×ÛÓÓð,^¤-Ì¡¤Äö»övìØ…9ÙæÅØÒëŒñ‰°àOMÙþ¶v-ù™™ø9;‘V[·ÚÆ ƒ¶#_t\u:˜ãúûaÒ2ÚÅŒãÎÎB³jo·i4þú¬óæ[W9\€¨«&I+V¸o’äÏÌÌ`!„]\L(®+ZZ`þ(.v½+™A}«üü¥f¢ÆF,®Âð}øð IDATñ-a´e;ΈŒÄœ"#a†jk³•lÚÜ~ñ…-tXøÎ† 6!â̱œ€]z]VÁ§ ƒþ¤uë 4+*0NjªÿùÀqÕ|khˆ7ߺBñ›»wÛm·Qll,íÞ½{áwŸ|ò Rnn.}ÿûß_øýÔÔÝ~ûí”™™IÛ¶m£ÁÁA""²X,´cÇ*))¡¶¶6í&k6ÃÌÑØˆÿêjØX˜vJJ`ÆHN^~Âcj Îíêj¼à¥¥òwÁ ¢˜?‚+á17‡E9;{©#úòe{­¥£Ã–PHd+_B„{ã*²) »d"¾>Ûß’“a&HLÄüM¦Åc½Mª«!¬œ 35³×ì¬óϹ# À–C èüyÌi9M*/ï…ÑÛßà„S§ð¼]¾lÓ9Ë¿ >ú(½ñÆ ?[­VºÿþûéðáÃÔÐÐ@ãããôÉ'ŸÑk¯½FÔÜÜL»ví¢çž{ŽˆˆŽ9B{ö졃Ò+¯¼¢ÎÄÃ"ÒÞŽEîäIØ©çæ` .)Áb‘‘âï»DWŒc×ÜØSÕÖ­ÎËvˆep DVÖâÅÞ¡²nFÆRÓÖÌ ®»}>‰ÕŠ­}}¬‰ ›odrÒu4TXþN„{%8Õ‰°ÈÙ "hçÎÙ„Ž@BN]ëóÒé`KMÅâ?:êú³îÐép¬ÒR¯ÚZÜ#³YÞx¾Fh¾••tëVhiÓÓ^6d¸f®„4Ç/ðÖ 7Ü@Ÿ~úéÂÏA©óŽÑ/ùËôÞ{ïÑöíÛ©¼¼œ~ó›ßÑÞ½{©´´”~ýë_“Á` ‰‰ 2›ÍdëÀÓ¢I’?c2Á|£×Ãl¢4š†1[.½ÁÕgkk±€8fŸaAq,ÒÕµ8ÒÉ1ipbµ­]åˆÀ˜:´ƒ?ÇÅag,§  ¿æf˜®ìYµ ®©i±™Ë!` ®ÎÖJ.BT”Ʉ㠦6ŽØƒÐ|KØhX,îöÍ·„Úm¼ù–_á·w"!!&&&¨¡¡²³³éƒ> ÉùÝcOO­ž_DbbbÈ4ofؾ};Ýu×]tðàAzë­·ÜŽ?;;Kýë_©üí·©Ìh¤»¿òõ›$ù3ýý0……Át¤FB›à_µJ\zCDgGýý>Ž9"==¶<"[âŸÀÄ„saD„s·ýè-Á ¼v-æo¯Ý¬Z…‚ÑÑ¥¹%©©ðï47ÛðÎ ‚–ÚÚ -6/OÙF$&Bi|cÎÎBø;˧YŽ-uÎ õ½.\Àùòæ[~ß NG ï~÷»4;;K×_=µ Ä.ÐëõtðàA—Ÿž·±~ëÆ)‘ˆ’“’(ïškèšë¯W·I’¿ÂlÍ.àÅ3Õ îïÇbæ˜pçŠsçð9¡`¡=ssX˜í„E\Übd`þgeLÂÃû=qa¡ ‚ÏJp® ääÀ¬RR²tC‘‘M©³Ó½©ŽÚÂð0üBÙÙâ3ö]{85e NO_,¯ì›o 8k¾%h(11Ü9ï%üJ€è^Îk¯½–>ûì3"":pàÌ?ÉÉÉÔÕÕE±±±d2™(Fä‹"G_ºu*öµ·‚ƒ!è„H-G²³a¢êîöœH¸b®]þ_EVBHÌhBä\k+Ì‚ÉÉW®Í›où~µ‚2‡Y?ÓK/½Dÿú¯ÿJDD;wî¤7ß|“ˆ Xn½õVIljJI¹:„Çì,ÃS§p¾%%X´Õf3ÆŽŠBø­˜q/^Ä"îÊÄ54„—ß±)Óè( {ÓÏà ´Ìm¡£¡=‹ÍZáá¸nŽAkÖ@{˜˜p>v^Ê~Øk8® „ J§C Z‘U¼Åų¢BWÈ“¹’šoefB@—”@#š„ ÎùŽ[ÕjŽbüF¹é¦›¨®®Ž&&&(55•Þyçzçwèoû=õÔS”5¿èÜÿý´gÏÊÌ̤5kÖСC‡|9uÿczªýÈ^¢Œ õÑÛ‹cˆ­EóÙààb-ž¹9¼ìÎ +¶µ-õ3ô÷/γ˜žöl†tÜ‘'$`Ñ·7» ©6n\üÙœt4­ ã@  â[z:>WU›ZeLôzŒ–fë¨gáJ q‡có-!@ÆËÍ·L&mß¾fggÉb±Ð<@=ôíÛ·Ž?NQó¾µwß}—Ö­[GSSSt×]wQ}}=¥¤¤ÐþçR\\Y,Úµk ÒÛo¿MëÔÐ^•®"ªªª±ªª*_OE&&««c¬²’±ÁAmŽ17ÇXCþÍ͉ÿ^?æeµºþÌÙ³Œ]¾¼ô÷f3c§O/ý}EÅ⟇†kn^ü»S§ÿ\WÇØä¤íçÙÙ¥ŸÆž]úûövüsÅì,¾;2âú3ŽÌÌ0væÌÒ¹«ÉåËŒ<ÉXS®'Ï¢ÉÄX[cUU¸o55Œ]¸ÀØØ˜äá\­/sssÌ<Í'&&XZZëííeûöíc}ôÑ’q^|ñEöÃþ1ÆØþð¶ÿ~Æcåååì7Þ`ííí ¿ó5Wç*`têù_`—YT¤MQ¾ÉIìfãâ°kB… ]ÛäGF`s‘eßbVÀY »^û\"›ÙÍÑÌ“’b«eOZ4Wyz=γ±Ñµ¹Ëƒß ÂõÕ"¡nåJhN+W"ú­®Nüü®T„ðàôtT].)&¨×Ãôwò$ZZ 9Ë4PȼÆl6SHHÈÂÏ̉)­¼¼œî¹ç"BšByy9‘:i *ÃÈrfpxg'üÂÂ¥¡¦jqéÌ7ùùÒz}Ã)¾y³k‰ÕŠH¦œœ¥››ƒ€tˆöÙçBYvw„‡/]8ããq-íÂwÙÊsr \„{QW·¸æ–'RSa6;sÑeZ‹ Fz:¢¶Îœ±÷äÀÙžœŒ{\R‚û ÓWu5„Jc#½ýüóôð}÷ÑÑ£GÉê˜hê„‘‘2”ššJ?üð‚Ùê?øГO>¹0Ž»4…cǎу>H?ü°F@þ!Æ8Ò¸|B#:>-íV,–v°R¢zÌfÍ›Ý'µ¶bñtR|á‚ózR‹#¥ˆÜ‡ð „…--O’çª}>‰N‡ÝzoïR)4õºxÑu­«Ûêjç|]‰ëÜС¦UáÍÈHølÌf\ÿóç!Tƒ®v\4ßÚl4RÇéÓô¿û]úÅÀMQ˜àkqBtt4ÕÖÖR__}ùË_¦›o¾™ž}öYJJJ¢ééiº÷Þ{éOú=øàƒn¦â>MÁp d¹`µbÁ:q;è-[°[ÕRxŒ#ÊjåÊÅÅ Å0=:Pîç86 #9yéß„¼ÇÞV+4G¡43ãÙêL‰ˆpnÎIM… vƺuHjtgn ·åH1èõŽáá0iIÑb¤ŠÜ£ëäIך„‡Ó†›n¢'Þ~›47ÓѾ>úèÓOé&ûΙ.HLL¤²²2ª©©¡¤ùIpp0íÝ»—*++‰È–¦@D’Ò| þÎÜü'Oâ¥.)A.‚Ö6Ðîn”Ë((^kv‹f^žû wÆp g¦+"¤¤¥‚K(\)½Þùb.´¼µÇ`ÀN}xxéçu:ä^¸3eÁ¤˜™ S‘SÇ"Ö¬Á1jjq¦%AA0ƒA+©¨€ö'uÎW#—M_ùÎwœþ¹¯¯ÆÆÆˆ¦¬ãÇS~~>]ºt‰ˆP÷ïðáÔ;ßMiš‚7á&,ÅbóØdÂNXI9u)ÌÍÁ|‚|©Ç*ënÜè9#½½Ú…«$¯ œ7žêë[ª±5­ä"TçutÖ§§Ã?ã¬LHd$ÎQè•âŠØX̯¦Æ} 3""pšš`¶Û¸QÛç@¨‰&„Ÿ:ßÚµ¼•L:;;éÛßþ61ÆH§ÓÑþýû)++‹n¼ñF «ÕJ×\s =òÈ#D´¼Òøáo6i³‹—c?-ƒðÈÌ”g g šÇºužËtLLÀdR\ìüïÃÃØ½;[´FGaR³GŒÿC (ÈÖP >sw ¡¡X°]Ÿ‘E6.νŸ#1&6!A z=´¹žËYϵ €'%š`U|nëÖù÷L?£¸¸˜ª««—üþèÑ£N?Bï¿ÿ¾ÖÓR.@ü…±1«&*W]û´âÂ8Œ7o–ïW©­…ÙEŒðil´õ3wF{»ó*·SSÎç'&K@åµ_õz@g¥PÖ­Ã|œ™Ú æ>w¬^ !röìR(†ädæº:hR¢á” 6ıƒƒñŒòƒW=Üâk††°»koÇÎófï Á_!Ô²’+<± ³¨uvÂ,âjšœÄÂìÌ´ÕßïÜ'㮈#ÎéD059†óá~LL`ñwFL ®›˜2&iiV ƒº$, ÷ip×Ü›>Џ8øHRS‘sT]-¿Ï 犀 _Ñ×sDo/v¶ùùÞ/K=2‚(¥åNΟÇb/¦}«Ù “ˆ«BŠDpõwû~öˆI"pL&pìRhÏÚµÐÒ\‘•e+­î‰¬,hRîÆsG@ž™øxßÓã<#]`dĹiËYaEO¸J(ÚܺúΊî5aÊ…‹™ÇæÍ¨6Ÿl&›„¤¦&h¾" À–» ¡vþ¼z}O8~ j2>ŽPÖÆF$–mÝêûö¢ ´a¡Rj6VUX(~×ù2ìåž =vu¹îè'ô«w&€¤„ð ¸r¤ ,®|ii0Gº#!Ú§³ vg ¸7 ÊâBèä$žE_îþu:lJK!x…wÕ‰³ìàD L&øZ[a¢Ù²Åµ­Þ›!™™Xø”21w•u™™ÃUBþ~ø\ë*|—HZ¯€+G:‘­úª3‚ƒ!È<™‰6m‚V!6Ì6(ÚCm­òrî:®÷š5ˆÒò‡PÛ„¶Õ«ñ ÕÖúÎÔÆQ .@”Ðß´»ÑTF£çòÞ€1h .à¥U#¯dj Id……Ò´˜¦&Øç=i+î…œ«ð]"i!¼®4"[—BW¬[s ;m%ÓÅŠˆ¦êj×9'Rˆ‹Ãfæüy×E!½ML 6 ë×ãVU‰×Ô8~ Ra ¶úŠ <øÉÔº´„X¦§a² ÆÜÔ¨_d±`Q3¥%ö÷ãøž´±±1ìÀ]E„1¶´ôˆ=r| î4èh÷»öˆÌÇ“M?) Ç¢DD`3ræŒ:æ§  ø½ffpÅä©xƒˆä>åä ²íÔ)q‰˜¿‚ ±X­ØÅUT`‘..†™ÀŸê `‘ظÑÖZ)³³XÌrr¤íòggÑÉMLˆo[›û¨°‘÷Ž9QX!!îˤ»ÿ{ZLsžÈÉ&%¤5:Žøêjõ2Í320çÊJÿj s_a!æUQž‡/ ¸ñ„°ž:û|i)L¾ Åuc°·÷ô@°EFª3®ÕŠElÃéσ€õt¦§±;vgús¾«Îý"å.œ—ÑZÃÞµ„à`dèK-]Fm­´ï¹cÅ h#--℟7 „¯®¸ÏCE‚x°_È+¦§á쫪‚\ZŠÚ—¡¸Î˜šÂ®22&µc(?ž–&= `hß‹óüYgýÎv­LMÉÏäw'D<'ø­Y#.\võjZHu'%a Ò¾çŽÀ@[‰üª*u|-j¢×ã™+-Å\++áGò·yrˆÈOÈÅ‹©¬¬ŒrrrÈh4.Ô¿omm¥¢¢"ÊÌ̤x`áóSSStûí·Sff&mÛ¶ç3- íØ±ƒJJJ¨Í““ÓÈè­¯G©ˆ’ü×éëÃ"Ÿ“ã:üU.õõ¶L ssÈSmvnf w‚ÆbÁBâJpË áp—uˆEË–’œ,¾„ˆ§>ê®X³¦C±y%bIO‡Yëôiÿtbëtx¦KKaÒ«®†)PËîŒÉø… ¤^xéÈ‘#ôè£Òää$=öØcô³ŸýŒš››©··—>úè#""zíµ×(##ƒš››i×®]ôÜsÏÑ‘#GhÏž=tðàAzå•W¤Mbdis3Ji)«¥%V+^¦¾>䚨]„±© /­»¤>Wœ?/¾câÅ‹X Ýá.úŠH^¯€;G:‘ûp^"ø]ÄÕ …@–c:üCj›¢£a2êè_Ø$&â9_µ B¸®Îý}ãx ¿ III”?ßdgåÊ•OCCCtâÄ Ú±cíÝ»—ÊËˉˆ¨¼¼œî¹çž%¿7 411Af³™ "°³gÏÒ®ë®#ÓßÿŽÅlãFD.Iµ÷{“ÉI¨õ+V ŒˆZ%<ZZક;L&˜þÄø+Cô'!å.ÿƒH^¯€»P^"Ïá¼D¸NbCd×®ÅùÈIܰçªv†¹Á¶ÁmÄŸ³ÅW¬€ùM>sÆ¿®BüB€ØSUUEV«•BCC)ÖNX½z5uwwQOO­ž7ÙÄÄÄi¾ŽÐöíÛ騱côàƒÒÃ?ìòuuu´mÓ&úÁu×Ñ?_{-E]wc ÅuÅåË0-åå¹o¡*—ÎN, rJ»[­pœ;kåŒÞ^O>¥éi÷¡ÃR::âI‰‰ñ¼@b± ™\SžÑþ~m*Þ®]‹ ‡ª*ñÅ }Ed$6zÙÙ¨••Ú÷Œç8ů: ѽ÷ÞK¯½ö1a|z½ž<èòïBcû×ðzø‰'èöG]}ž“U@LjkD°å›LÈõCK B‡Å†5_¸€„2wŒŒxÖ•ôB÷¤á|< ±ôtø( =3<>Ÿ ä…ZØy ₤SQC„Hf¦ÿØ l±À¼×Ö†kš”äßó¾‚ð dzzšn»í6zâ‰'¨´´”âââhÈ®IMww÷‚Ö‘œœL]óª¼Éd¢‘Å#çÃ[Ÿÿøcº}ÿþå!<&&Bœ€Ý½£¿ÚÔ^Ýccø'Ögb2a!õtýµßµ' ÀsžEb¢çÝmXLrbk<¥§Ã|'Ç!AÕÒ¢ùF¯‡ …IKiYo_Q®iE´7»5^¥ø…aŒÑ¾}ûhÛ¶mt÷Ýw‘N§£ÒÒÒÇù[o½E·Þz+íܹ“Þ|óM"":pàÀÂïE£Å"¬ÝÝ0wÚE‚ ÉZP oׯ´#±e݉°[SN~xØ} ƒ«æRj’ Î<’ž.ÞÉ­Óa3 ×”%Æ<{V»zR))0UW/ó^ûPR‚k|ò¤ø.‘YøÅJúùçŸÓ;ï¼C‡¦ÂÂB*,,¤ÆÆFúå/I?þñ)##ƒâââê÷ß?µ´´Pff&½ûî»ôøãûø Tfn‘&cc0Yiå›EÔ””ÊºŽ´µAó[âDØ¥{:§™,’^à`÷»l¡ù”'“ꊸ_b«ÈH˜Œäv Ä}«¯×®ºmDž¿K—àßZ.Ùá€×\ƒç£ª ó_ÚÔ2Ã/l8×]w͹È8=}úô’ß…„„Ðû￯õ´|Ãø8lÐë×k[ ~r;à-[ä›ò&& %‰ÿŽ»~çö x>%tÁ‘îNÆÄÀìæ)¡25¦±Íº22°KŽ—W'8ÚiM î£euôz˜6»»aJÍÏ÷ÿ`{’’ðopÂ68ï–Òç†CD~¢pæ¹xf‰ÂBm…ÇÔJd*[t<õ7wdv‹µŸU_Ÿçk †"Æ‘.ÆB„…ª·WüN]§ƒ™H®)‹óÏÍ…c]KSÍêÕ8Nmíòì{‡ÎÚµx¨®ö2÷Ë.@üÙYì"§¦ðK©x+•™+?_~ "øM¥íF;;ÅGMMy[M Ä11â²µu:„W»ë›îHt4E92Ndµ*øº"<QZð{-G'uT6N6ày<}ÚÿÖý.@|Íè(âØSSµ›œ›Ã"“­lçn6CCÒ¤Š1|GL0Àؘ¸‚žÂkÅ FÑéàs“d—’â¹oº#YY0í)©÷´bLƒ55Úú* uÆÆâ¹UÚAÑW„…!Ÿ*/ÚåÉ“ˆDäH‚ _ÒÙ 'ö–-Ú—M*ëff*o0%ÕtEgñªUâ¤Öá»ö5¯ù„ éì6eš´«Ð.@´fhÂ##C…\,/bËÊR>–Ňf¦ôïzêwîˆÙ,N³P#„W@¬²b…´æKiiâK½Û“ ³‰>…¼<„‹|JÑéœ “–„…ÖF ™ÌL<}š¾à Ô%"`! €BæCæÍf3SHHÍÌÌгÏ>KO?ýô¢â±jµ«ð\€hIK âbå‘OR¸|~©‘R®hjB¤ŠT§µÅ‚b{´»ïnÙ¬^F´X D§ƒ™Il¸mBîƒTAˆÍÆùóÒ¾ç ¦¥ÎNu´±ÄÇc±=wÙùWáá}ýõYZJÿRVFßÊÉ¡º¿ÿÝíWFFFÈh4Rjj*=òÈ#I¿ýíoiß¾} E^”¶«ð&\€hÅç[P­Y·@ēܲìŽôõá©vâšTÚÛ±[—ê_Ck+LbJ€/^”—y/Õÿ¡E¯€”H,"yf,ßSÒ="¾/-ªìæä Â×]##aÒêé_ÎN~ŽG¸qÆø8Tè¤$yý/Ô¦« sÚ¸Qý±ÇÇ“/%kÜư«–£¡KËÚ×"„W@È‹œp^"Z9UzíY¿B[‹È¥ü|,Ür²çÕD¯Ç\"#ñ>z;{žã.@éê‚9§ @Z'­èíÅ‹œ›«Íørú›;"©‚VNE]-MXaaÒ4½ç,Õ)n0`Q”RÞ¡ ­k… ¾ííÊæ¨«Wã­©ñ^YzŽ(¸˜›CtÓä$Tçùúý>ep»L£Q-¨½ ¿RóÜ… Þ1_!GE«†\R5"4ÈÑBÒÓ•'FGãÞ]¾¬lgèõÈÑøâ ÿèéSr_6xܤåø…¹xñ"•••QNNF:tè=óÌ3´víZJpÐToù86†(«5kP<Ð×&+"ø^ZZPßJ‹¨/³šÔŒqG††*'/ClûZo¡×K/9.ÇB„…_§Sž˜•A¤E])ƒB¤¡AÝF¹@_±﫜(8Žªø… ¤^xéÈ‘#ôè£Òää$}å+_¡“'O.ù¼Z-?ûì3úßO> 'Ý–-ò ªÍø8vYjVÖu¤¡A†SrBw‰07'­\ŠÔÏ{©Žw{Ö­S®…À7ÖÔ¤lWÁœU[ë?aµ«V!‘·®Ní‹#¿ III”ŸŸODD+W®¤øøx¦¢¢"Jrâ˜U£åãÓ?NOíkT““•V¹R*ënÞ¬©æâEK¥¾„ÉI89æ¾áaé!¿Z:Ð¥ïæ¥úN¢£ñ=¥ÚʬZ9½CC±`WWûOݰ0¼·CCØ ù¢žÇ?ˆ=UUUdµZZ::CiËÇû¾ñ êzÿ}ú ¶–Jî¾[ÝP‚ÅG¡Ñ¨^e]G¦¦a£Fö¶6ùãÈñhQË9…\3LˆJ#²ˆ …´´h×õ/"Nû3gägÒ«M@Êî$$À¤åíFYÿ CCCtï½÷Ò«¯¾*ëûžZ>Ì'%Ý”Mih (±åýPY77WÛE²±/R?ÏÌ ´%¹½Þå”6×2K@Ž#=>^ž#u¨”ï õz$ž;§lwDGedà9õ§ÿÊ•Øt54h“Ãq‰ßééiºí¶Ûè‰'ž ÒÒR·Ÿ•Ûò1~Þaû/?ù‰væ!9 v²²´ídØÓƒñÕ8†œ’íSSòÌ^Þ rÌQz=¢‚äîÌW­Â½QJ|¼­•°VÄÅ!ؤ¶Ö¿"¡BC¥56߈¿hIW8~!@c´oß>Ú¶mÝ-¤´œZ>zD¨¬›ž[¶VX,·ÍÈP>–ÕŠ]³Ü’ï}}òrl¦§µ¯–ë‹“¿p¯Yƒü#5Ø´ ¡·Z. II¸Zä (A§ƒ)oÕ*$ªÕő㿠Ÿþ9½óÎ;tøða*,,¤ÂÂBjhh û·£””2™L”’’B¿ÿýï‰hyµ|ôH]x­“aÃV#$¸»[Y)ûyçëoP¼ìî„ù~½›5ê> ˆî:^ùXîX³Âö‹/´=Žþ~ö¬²Â•øELäu×]GsNvL¹¹¹ô³ŸýlÉï—SËG·45¡¦‘Ö}Ez{±s—ë¯p¤»æ90T"c¾­‚ì‰ÈHe;Þôtl&ÔÈ‹Y¹µ¬FFÔ»çÎHO‡ikÓ¦F›‚ƒÑñ°¹)¾jüv…ãÇoäNK v»Jù<13ƒ<+Kñúû~+w1–gª›œô^AK½^ž (4T~r[Pþ©evÙ´ ;p­Ý6àÞ¨e‚SÏ}J ¢´FG}=£+.@|Ag'Ì$jø#x§Xã¹s0‘©U;jz»¶ˆùcô÷Ëý5›½'@äj DÐö”äaÄÇãYQ+ 7$šˆÒš[b*øž=ëß!´+V@imõÎu¹‚áÄŒŽÂþªUe]G†‡±Ø«ÜÞ®Ì÷A"wNV«÷¢°BBä;ÕפJIQ×)’Ó’7J}â9¯¯÷ïj¹ð‹UUiÓ˜ë*€ ­™œDFa¡w*ÉZ­Ð>Ôô±ÌÍÁ,¡¤Z1cxIý¥h¥;t:ù&Ÿ¨(åÑ>ÉÉê·”ÍÍõ^â_p0|"55þ¿0§§CS¯ªÒ6ƒÿ … -™šBɇÂBï-œçÏã¥P³TËÅ‹ÊZÞÁÞ,ÇyN$¿ô‰”‘eíWu:hjJú¦;Š1½…¡uæŒÿ;¬££QÙ·³Ó;QkW\€hÅÌ v`ùùÞ[üFF`6ӛ܌a7¬4ÙQ‰ÿÛ!¼Jr:”d¥ ¨Ñ7Ý‘ôtqxË´‰rªàë ƒÁ¶Ñ«¬ôÍÉOàD ææðÒdg{/ô”18/ÕheOo/~¥Žÿáaùˆ7Cx”8Ò”—% ÄÔŽhÊÉñn «+ ¸jjü«ø¢+RS¹XUå¿!É~ j#TÖÍÌÔ¶Œ„#­­p–ªm*»pAy¶¼Å‚Q®òf¯€ÜP^"œëì¬ò3=]½ÄBˆrofŽ'$@ƒ­«óÞ1•‰R=]]0 /Áç#¸QÆàóHMU/yO ããð1¸iÂ% “ »`¥Î%ÑWDЖ“B„÷ð°²9„…á™RÛä´~=Go¶¨]µ ×Äß*øºB¯G @XLZJ|ZW0\€¨I}=Ì=+Wzá¥ÌÍUìövuŠä)ña7ïí^è¡¡ÊÂ^•–5P£oº#:¢ô¼½˜§¦Â¨u¥`5Y³ת¦F»–ÁË.@ÔâÜ9„pª­x¢£»;µõ®W†ÓÓÚµèÕ ½^YFyt´:þ‹˜h˜jG2EEAËR;\Øë×ÃG¨f¶½ÖDD Jëòeø¹Ik.@Ô µInÞn‘;9‰]Qjªúc+-[" ´¤øÌŒu”BP:f¢ÔTø¢Ô&3 ùÌŒúc»#;¹2Ë©ý¬^DÑѨì+Á¬h2™¨¸¸˜ )''‡^zé%""Ú³gPnn.Ýwß} --¦¦¦èöÛo§ÌÌLÚ¶m Î;ó- íØ±ƒJJJ¨MmߘL¸QÊ… °ªU.] Z™®fga¾‘5eO_Ÿ2ó•/Bx‚ƒ•…sª‘•N“ho¯ú;߀,æMMêŽ+†¼<œ“f>o’œŒ¹×ÖÒŸþsjhhðø•¨¨(:~ü8UWWSee%=ÿüóÔßßO¯¾ú*ÕÔÔPCCŽŽÒ{ï½GDD¯½öeddPss3íÚµ‹ž{î9"":räíÙ³‡H?ü°Æ'(.@ä`2ÁGà­ÊºŽ46BëÑàØæÖVP)—äÕ_üBqAÇßÿû¿Ó€‚0Ö={öÈþî ÙL¿þéOeŸˆèõÇÕ)®×Óàì,Y´hÚ¤×Ã{ö¬úc‹9öæÍ0£y£Ø£ÊÄåäÐ45Ñ®õëiïW¿êòsÑÑÑT[[KíííôòË/SË|É”C‡Ñ¥K—ˆ1F¯¿þºÛcéõz:xð ;vŒ’µnƒ-.@$Rsü8"®6oöIåûwì êÖVeeÕÝðâcÑ÷ž^ñ8ôÿ^}U±ùøƒ(F6ÔÚÚ*û»‘IItäý÷eŸˆè7o¼A§N)C໿ü%ýé±ÇTk qqtâÄ zHÀ•M` 6cuut®¦ÆûÇWJh(}ïí·éy›ÄÄD*++£»ó ¤Ý»wSee%%''S×|¢§Éd¢5|‘Áˆ~óóŸÓOwï&kA÷óˆ¨üÝw©÷ôi2Þq‡&ã[ûûéÝ£Géw/¼ x¬_|‘n()QÌó™½7(<œô {ŠoßN‡^{M•ùüî¤÷>ø€¬u,Þ»—Ú?þ˜>=zT“ñÝB³›6Ñþo¤?¿ü²÷¯ŽRo¸ÁéŸúúúhlþžŒŒÐñãÇ);;›:çkÍÍÍQyy9ÑÎ;éÍ7ß$"¢Э·Þê… »Š¨ªªbDĪªª$÷ÿ¼ò Û±bîéÑ`fž™žžfeÑÑì̱cšãÍÿõ¿Ø¶k¯Ue¬ÜÔTÖòÁŠÆa·ÄÅ)£Xá#þ•ØX611!ûûµµµlçêÕŒMO+š‡À—‹ŠØÛO>©ÊXÎøì½÷Øu±±lffF³c¸£çÜ9¶=*Š|ë-Ÿ_ ®Ö—S§N±‚‚f4YAA{ýõ×Ùää$»æškX^^ËËËcßÿþ÷™ÕjeŒ1f6›Ù®]»XFF+++c¾8Qp"‚DZ›£¢X×¹sÍÌ3÷Þr {ìŸÿY»Œ±›X}}½â¡¦§§ÙÖØXÆúûsôðavûÆŠÆP*@þ%+‹ýøcEcä¯XÁ¦ÛÚ!PUUÅv$$¨&œ±ûvv¯–ÏšZNbÛ"#Ù_?üÐgsƒ’ êrÅ?bÁ¼„%qV‚³°ûâEú÷½{éG/¿L½Ô{æŒVÓsIóÙ³Ôzâ=ôÉ'tF£ã׿÷u…„ÅbQ|Œ?üÖ$$ЙŽE p½ÿ>ÄÅ)šÏ‘²ó‰¥òC‡(&>^öÁ©©ôʯM×ßwŸüyØq!(ˆ^ÿÕ¯(oÇUÆsd÷LßûêWéàÛoSæ† šÃ-z=}çW¿¢§vï¦ÙÿøZ­´—ÖwÑXW:Æ®ž¼ü·Þz‹¾ùÍoúzç æÀt÷Ýwûz^᪠ôñÇSZZ…ªQã‰Ãápæ1›ÍÔÑÑA·Ür Å+ÐX—W•áp8Žzð0^‡ÃáÈ‚ ‡ÃáÈ⪠/^¤²²2ÊÉÉ!£ÑH‡""¢»îº‹6nÜHyyyôä“O.|^‹Ë®æ f™gWǸóÎ;©¸¸XÓó{ÞSSS´oß>Ú¸q#mÚ´‰>ÿüsÍæäjÿõ_ÿEF£‘ è–[n¡áù®‚Þ¸.®Ê~·¶¶RQQeffÒ<°ðy9sruŒgžy†Ö®]K •´8oWsðæ»ÇQ _Æû’K—.±ÚÚZÆc—/_f«W¯fìoûcŒ±™™và 7°ÿþïÿfŒ1öâ‹/²þð‡Œ1Æþð‡?°ýû÷3Æ+//go¼ñkoo_ø’9LNN²ÑÑÑ…ÏìÞ½›½óÎ;²çàêŒ1väÈöo|ƒ/|^‹ósÞì©§žbÏ>û,cŒ±ÙÙYf2™4›“«9dee±óçÏ3Æ{üñÇæãë277ÇÌf3cŒ±‰‰ –––Æz{{ÙwÜÁ>úè#Æc·Ývûp>?BΜ\£²²’]ºt‰ÅÇÇ/ú¼çíjÞ|÷8êpÕj III”ŸŸODD+W®¤øøx¦[n¹…ˆP:¹  €zzzˆH›ËÎæ044¤j™gWǘ™™¡gŸ}–ž~úibvqÞ(%íjNo½õ}ï{ß#"Ž‹žoDåÍkŸ””D£ó•aGFFŠÖyãº8–ý ¡:qâí˜Ïù°?¶œ99+-JEEE”””´dNZœ·«9xóÝ㨄¯%˜?púôi–——·èw£££,##ƒuuu1ÆËÍÍeƒƒƒ _¹r%c ;å¯ý묬¬Œuww+šCnnîÂÏwÜq‹‹‹c_ÿú×~§töçùÜsϱ×_utt°¢¢"ÕŽ!aN&“‰edd°‡zˆmÞ¼™}ë[ßbccc^™“ýu©¬¬d±±±,99™}éK_Z(/á­ëb2™X~~> c/¿ü2ëïï_ô\œ:uŠíܹSÑœa£¢Õy»›ƒ·ß=Ž|®z288Èrrr؉'~gµZÙí·ßÎ~ûÛß.üÎÕC¬ÕcÌb±°Ý»w³¿üå/Šç`Œ®®.vã72Ækoo%@´À~NýýýL§Ó±¿þõ¯Œ1Æž|òIöÔSOi>'û9ÌÍͱœœVSSÃcìG?ú{æ™g4Ÿƒ3z{{Ù¦M›Xee¥d"õÍÍÍ ¿+@ÔÂqÞ~÷8ʸjMXDDÓÓÓtÛm·ÑOoaµµµDäÝw£œ«V€0Æhß¾}´mÛ¶Eeþô§?QMM ýñ\ôy-J,;›Ãì쬪ežcÇŽÔÓÓCíííôÙgŸQ^^}øá‡š§˜9ét:ºù曩¢¢‚ˆˆ>ýôSÚ´i“fsr6‡„„¡ŽŽ"":zô(mܸQ³98â¬ìw^^•––ÒG}DD(Ç#[ΜœCð9C‹óvužÞ|÷8*áSýLJ?~œ°ÂÂBVPPÀ Y}}=3 ,++‹°‚‚‚ó‘%–Í¡¶¶VÕ2ÏŽÇ(((XTq·½½}Q–7JI;›SCCkkkc×^{-ËÏÏgÿôOÿƇ‡5›“«ëòá‡2£ÑÈŒF#ûÚ×¾¶p,o\ge¿c¬¹¹™mÙ²…­_¿ž}ç;ßQô<¸:ÆÓO?ÍÖ¬Yà [³f ûÝï~§Ùy»šƒ7ß=Ž:ðR&‡Ã‘ÅUkÂâp8Ž2¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,¸áp8Ž,þ?%¹œ2uIEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/image_plot.png0000644000077000000240000002474712436367710023555 0ustar tomstaff00000000000000‰PNG  IHDRXX¾f˜ÜsBIT|dˆ pHYsaa¨?§i IDATxœíÝyt•õøñϽC›lš¸4Š ¢h@¡¸£–ºÔÖT\êŠG¨8*u¯KqŠZ«xÔªŠÛëXqepƒZ©=("ŠŒaÉóûÃÃýÃ’ÀWÃëuNä{¿÷>ß»$yó<7¹,˲ ™|c/àÿ˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1X“Æ^À†4oÞ¼=ztTTTDIIIc/6 K–,‰éÓ§Çá‡íÚµkìål›U`=:N;í´Æ^l–}ôÑ8õÔS{ÄfXñí¼Ûn»5îbØd½ôÒKqÝu×ÅÍ7ßGuTc/g³ä9`}y mX~øaœvÚi…ŸÃ›ƒÍ*°VÜm·Ý¢{÷î¼6U~øaDDì¸ãŽ^GÄsÀúòj›ÓÛs¼É 1˜ÀHL`$&° vß}÷8øàƒc÷Ýwoì¥l¶<¬/¯!~h›ÕoB •••1~üøÆ^ÆfÍsÀúòâ‡f@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°kP`-[¶,åååѬY³èÕ«WŒ;¶Î¼›nº)Ú·o]ºt‰÷Þ{¯Öe‹-Šn¸!Ž8âˆhÓ¦Mäóù1bÄ*·wæ™gF>Ÿ¯ó±Ûn»Õš7}úôÈçóñꫯ6äîü š4dò™gžO?ýt 4(:uêÇ£Ž:*^~ùåØÿý#"¢ªª*î¾ûî¸öÚkcÊ”)qÌ1ÇÄÔ©S£¤¤$""æÎ7ß|süèG?ŠÊÊÊ?~|är¹Õn³¸¸8þøÇ?ÖkÕªUCï'ÀSïÀzë­·bäÈ‘qûí·Çe—]§Ÿ~zì±Çqå•WÆo¼O?ýtÜzë­qÞyçEDÄ~ûío¼ñFüä'?‰ˆˆòòò˜3gNtèÐ!Þ}÷ÝèѣǷ[TTýû÷_§;Ðê}ˆ°ªª*š4i (ŒÇ9çœ&LˆÏ?ÿ<""/^íÛ·/ÌéСC,Z´¨ðù–[n:tˆˆˆ,ËÖºÝ,Ë¢¦¦&¾úê«ú. QÕ;°&Mš;wŽæÍ›×_¹jòäɱï¾ûÆ!Câ£>Šgžy&Æ·Ö½Tk²xñâhÙ²e´nÝ:Ú¶m]tQ­`[iM‡6¤z"œ={v”••Õ_96kÖ¬ˆˆ8p`¼ð ѥK—Èçóq×]wEyyù:-®¼¼<Ý»wššš5jTÜ{ï½ñ—¿ü%Æ[l±EDDTTTÄŠ+Öi©Õ;°–,YÅÅÅuÆ›6mZ¸<"¢´´4^ýõøàƒ¢}ûö«Œ²ú2dH­Ïûõë;wŽk®¹&ªªªâ¤“NZçÛø¡ÔûaIII,[¶¬ÎøÒ¥K —n4Ÿ=÷Üs½âju ù|>Æ—ü¶R¨w`•••~×ìÙ³#"Öù0`C5mÚ4Ú´ióçÏß Ûh¨z"ìÖ­[Œ?>ª««£E‹…ñ‰'FDDeeeúÕ­BuuuÌ›7¯Öo*6TŸ>}¢¨¨¨ÖXß¾}cذaë»<ج 80žzê©ZcË—/o¤Õ4žzïÁ:ñÄcÅŠñÀÆ–-[Ç^½zŶÛn›taË–-‹êêê:ã7ß|sDDqÄë|ÛcÆŒ‰9sæÔúW°þ† Vçgì˜1c{Y\½÷`õìÙ3úöíW]uU|ñÅѱcÇ1bD̘1#†Þ ÞsÏ=±`Á‚Â!Ç^x!f̘_|q´lÙ2fÏžݺu‹þýûÇ.»ì£GŽQ£FÅ‘GÇsLƒ¶ °¡4è¿Êyøá‡ãºë®‹Gy$¾üòËØk¯½âÅ_Œ8 A½ãŽ;âÓO?ˆoÏ_õì³ÏÆ3Ï<¹\.Î8ãŒhÙ²elµÕVñóŸÿ<ÆŒ#FŒˆ+VD§NâÖ[oË/¿¼AÛØXÅÅÅ1tèÐ:tèzmô“O>YëœV­ZÅÃ?¼^Ûh õ~õ#°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰5Z`-[¶,åååѬY³èÕ«WŒ;¶Î¼?ü0Ž8âˆhÑ¢E´mÛ6Î8㌘7o^­9Ó§O|>¯¾úê†Z>Àj5Z`yæ™qçwÆé§Ÿwß}wl±ÅqÔQGÅo¼Q˜3sæÌ8è ƒâã?Ž[o½5.¿üòøóŸÿ}úô‰åË—7ÖÒÖ¨Iclô­·ÞŠ‘#GÆí·ß—]vYDDœ~úé±Ç{Ä•W^Yˆ¬!C†Ä’%KbÒ¤I±ÝvÛEDDÏž=£OŸ>ñ§?ý)Î;ï¼ÆX>À5ʬªªªhÒ¤I 0 0V\\çœsNL˜0!>ÿüóˆˆxúé§ãè£.ÄUDÄa‡;wŽ'Ÿ|rƒ¯ >eÖ¤I“¢sçÎѼyóZã=zôˆˆˆÉ“'GDÄܹscŸ}ö©sý=zĨQ£jår¹hµ Ó(5{öì(++«3¾rlÖ¬Y±õÖ[×ûþ¼ùóçÇòåË£¨¨(***bÅŠ?ì¢ê©Q.Y²$Š‹‹ëŒ7mÚ´pù’%K""Ö:`cÓ(URRË–-«3¾téÒÂåÍš5‹ˆXë<€M£",++‹Y³fÕŸ={vDD”—— ®ûþ¼¶mÛFQQÑ:m¿OŸ>u®Û·oß6lØ:Ýð­ÆSO=Ukls<µR£V·nÝbüøñQ]]-Z´(ŒOœ81""*++£¼¼<Ú·oo¿ývë¿õÖ[QYY¹ÎÛ3fLtïÞ}¯¬Ú°aÃêì°xï½÷bï½÷n¤5ŽF9Dxâ‰'ÆŠ+â(Œ-[¶,†½zõŠm·Ý6""N8á„xñÅcæÌ™…yãÆ‹¿ÿýïÑ·oß ¾n€úh”=X={öŒ¾}ûÆUW]_|ñEtìØ1FŒ3f̈áÇæ]}õÕñÔSOÅ!‡—\rITWWÇm·Ý{î¹gœuÖY±t€µj”ÀŠˆxøá‡ãºë®‹Gy$¾üòËØk¯½âÅ_Œ8 0g»í¶‹W^y%.»ì²øÕ¯~ÅÅÅqôÑGÇwܱÎï¿ø¡5Z`ÇСCcèСkœ×¥K—øÿø ´*€õ×hÿÙ3ÀÿU 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1X½kÁ‚1`À€hß¾}4oÞ<=ôИ4iRyË—/‹.º(¶Új«èÕ«W|òÉ'µ.Ÿ3gNüêW¿ŠC9$Z´hù|>^yå•Un³wïÞ‘Ïçë|y䑵æ?>òù|̘1£¾wàÓ¤>“jjjâg?ûY¼ÿþûqå•WFÛ¶mãÞ{ïÞ½{Ç»ï¾;ï¼saî]wÝ/¾øbüæ7¿‰qãÆEß¾}ãwÞ)\þÑGÅСC£sçαçž{Æ„ "—Ë­vÛÛo¿}Üzë­µÆÊËËz?6˜zVUUUL˜0!ªªªâøãˆˆ~ýúEçÎã†nˆÇ{¬0÷™gž‰|0úôéçŸ~ì¸ãŽ1mÚ´èØ±cDDì³Ï>1þühݺuávפU«VÑ¿ÿu½\½VUUÅ6ÛlSˆ«ˆˆvíÚE¿~ýâùçŸåË—Æ-ZíÛ·ˆˆ-¶Ø"Ú´i .,\Þ¼yóhݺu½˜eY¬X±¢ÖmlÌêX“&MŠîÝ»×ïÑ£G,^¼8¦NZÛwß}ãšk®‰iÓ¦Åý÷ß³fÍŠ]wÝu8uêÔ(--–-[FYYY\ýõñÍ7ßÔ™·¦ÃŒR½Ξ=;z÷î]g¼¬¬,""fÍš»ï¾{DD\ýõq衇F§N¢¤¤$}ôÑ(..^§Åí¼óÎqØa‡E×®]cÑ¢EñÔSOÅ-·ÜS§N'žx¢0¯wïÞ±bÅŠuÚ@jõ ¬¥K—®2’š6mK–,)Œ•——Çûï¿|ðATTTD›6mÖyq=ôP­ÏO=õÔ8ÿüóãÁŒAƒÅüãu¾m€J­C„Ë—/9sæÔúX±bE”””IJeËê\yéÒ¥QRRRk|Ë-·ŒîÝ»¯W\­Î¿üË¿DDĸqã’ß6@ µö`½ñÆq衇>ÏårññÇGYYYÌš5«Î•gÏžö´ Ûm·]DDÌŸ?o£OŸ>QTTTk¬oß¾1lذõZlîO=õT­±ïþ2Üæ¢V`UVVÆØ±ckMØf›m¢²²2^{íµÈ²¬Ö›É'Nœ¥¥¥Ñ¹sç ³Úˆøøã#" ¿©¸.ÆŒ³Ê7íëgذauvX¼÷Þ{±÷Þ{7ÒŠG­Àjݺu­=X+xâ‰QUUÏ<óLœp 1oÞ¼xê©§âç?ÿy½A)TWWÇ–[nYë½_Y–Å-·Ü¹\.?üðäÛH¡^or?ñÄ£W¯^qÖYgÅßþö·Â™Ü³,‹o¼±Á½å–[""bÊ”)ñðÃÇ«¯¾×^{mDD¼ûî»qÊ)§Dÿþý£cÇŽ±dÉ’xöÙgãÍ7ߌóÏ??*++¼]€ ¡^•Ïç㥗^Š+®¸"î¾ûîX²dIôìÙ3~øáèÔ©Sƒ7zýõ×G.—+rü·û·ˆøö=_+«¢¢":è xöÙgcΜ9‘Ïç£K—.ñ‡?ü!Î;ï¼o`C©W`E|{øðÁŒ|p½7ZSS³Ö91räÈõÞÀ†V¯3¹P 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1 4yòäèÝ»wLž<¹±—²Ùò°¾¼†ø¡ ,h )S¦Ä+¯¼S¦Liì¥l¶<¬/¯!~h 1˜ÀHL`$Ö¤±°!-Y²$"">üðÃF^ ›²O>ù¤ðç{ï½×ȫٟ3f¬v›ƒú>O~øaqÄÑ¢E‹hÛ¶mœqÆ1oÞ¼Zs<¶¿)S¦Dß¾}£cÇŽQZZmÛ¶ýöÛ/{ì±ZóÎ<óÌÈçóu>vÛm·:·ùü#Î:ë¬èСC4kÖ,öÞ{飯ªZåöÿýßÿ=vÚi§èСC<üðÃk\ë믿^Øîüùók]6nܸ8ûì³£sçÎQZZ;vŒóÎ;/æÌ™Sçv***âÆo¬5–eY :4vÜqÇ())‰½öÚ+žxâ‰U®ãóÏ?~ýúÅV[m­ZµŠc=¶pòÓïÊçó…û´ªm²ñÚ¬ÎäΦïÌ3ÏŒ§Ÿ~: :uŠáÇÇQG/¿ürì¿ÿþQUUwß}w\{íµ1eÊ”8æ˜cbêÔ©…sŸÍ;7n¾ùæøÑ~•••1~üøÈåru¶µhÑ¢8ûì³cß}÷ .¸ :tèo¾ùfÜpà 1nܸø¯ÿú¯5®µ¦¦&~ö³ŸÅûï¿W^ye´mÛ6î½÷ÞèÝ»w¼ûî»±óÎ;æNž<9;ì°Ø}÷ÝãÎ;ïŒÏ>û,n¿ýöøûßÿ/½ôRÂGpèÏó4sæÌ8è ƒb«­¶Š[o½5ª««ãöÛo¿þõ¯ñÖ[oEQQÑjos~l7F3f̈… Æ™gžååå±xñ⨪ªŠÓO?=¦OŸ×\sManqqqüñ¬uýV­ZÕúü«¯¾Š8 æÎ—\rIl³Í61räÈèׯ_<öØcqÊ)§æÎœ93ú÷ï^xa´lÙ2.¼ðÂØsÏ=£²²²Î:kjjbàÀQZZ‹/®sùàÁƒcÁ‚Ñ·oßèÔ©SL›6-î¹çžxñÅcòäɱõÖ[æær¹:ß7®¾úêøío ˆ=zÄsÏ=ýû÷\.'tRaÞÂ… ãC‰êêê¸æšk¢I“&qçwÆÁ“'OŽ6mÚ¬òq^Õ6Ùˆe°‰˜8qb–Ëå²;0¶téÒlçwÎöÛo¿ÂØÉ'Ÿœ=ðÀ…Ï÷Ýwßl̘1…Ï—-[–ýãÿȲ,ËÞyç,—Ëe#FŒ¨³½¯¿þ:›0aBñ›nº)ËårÙØ±c cŸ|òI–Ëå²W^y¥06räÈ,—ËeO?ýtalîܹÙV[m•õïß¿Ömyä‘Ù¶Ûn›UWWÆzè¡,—ËeÿùŸÿY{ùå—³\.—}úé§«ÜæÆ ¾ÏÓ\•––fŸ}öYalìØ±Y.—«õüyl7M+V¬È*++³vØ¡0öË_þ2kÑ¢ÅZ¯;tèÐ,—Ëe/¿üra¬¦¦&ëÙ³gVVV–}ýõ×…ñûï¿¿Ös~ÕUWe×\sÍ*o÷¾ûîËÚµk—]zé¥Y.—ËþùÏÖºüµ×^«sW_}5ËårÙµ×^[k¼¢¢"»ñÆ ŸÏœ93+**ÊXkÞA”m¿ýöÙŠ+ c¿ýío³\.—½óÎ;…±>ú(kÒ¤IvõÕW׺þw¿?}›lÜ"d“QUUMš4‰ÆŠ‹‹ãœsΉ &Ä矋/ŽöíÛætèСÖá -·Ü2:tèßîÒ_¢¢¢èÕ«Wñc=6"">ú裵®w›m¶‰ã?¾0Ö®]»èׯ_<ÿüó±|ùòˆøö_ëcÇŽÓN;-š7o^˜{ÆgDóæÍãÉ'Ÿ\ãv66õ}žž~úé8úè£c»í¶+Ì;ì°Ã¢sçÎk½Ï›ëc»)Éçó±ÝvÛÕÙ™eYÔÔÔÄW_}µÚë¾öÚkÑ¡C‡èÝ»wa,—ËEß¾}cΜ9ñÊ+¯Æ¿ÿõÞ¾}ûX¸paÛœ?~\wÝuqóÍ7×Ùc¶ÒPgìÀŒ6mÚÔùzÿþ÷ŽçŸ>¾ù書ð k_pÁ1sæÌ˜0aBa¬ªª*zöì{ï½wal—]v‰Ã;l¯É5}¿bã#°ØdLš4):wî\ëeDD="âÛCAûî»o 2$>úè£xæ™gbܸq…9)¬|?Æ÷ÿ»‡ïﺟ4iRtïÞ½Îõ{ôè‹/Ž©S§FDÄ_ÿú×øæ›obŸ}ö©5¯¨¨(*++뼯è»ÛÙÔçyúüóÏcîܹuîóÊykºÏ+·±9>¶»Å‹ǼyóbÚ´iqçwÆèÑ£ãÊ+¯¬3§e˖ѺuëhÛ¶m\tÑEuÞ·lÙ²UþwfÍš5‹ˆ¨õ¾Ê^½zÅ#<ãÇwß}7î¹çž8ðÀë\÷ºë®‹²²²8ÿüótŸ.\ÕÕÕõúzoÞ¼yìºë®µÆ¿ÿý©¦¦&ÞÿýÕ¾ö§M›VçñXÝ6Ù¸y›ŒÙ³gGYYYñ•c³fÍŠˆˆî(² }IDATÆ /¼]ºt‰|>wÝuW”——'[ÇСC£U«Vqä‘GÆ***bÅŠuÖûݯj½»ï¾{Ìž=»Öøwm³Í6ñúë¯>ïÝ»w­í|›ƒúø Ú·o¿ÊodëjÈ!1nܸ¸ï¾û¢eË–kœ»téÒz­w埫›»òòME}ž§µÝç•óV÷F÷Íõ±ÝØ 4(úõë³fÍŠÇ{,.ºè¢())‰_þò—ñí×Ïwõë×/:wî×\sMTUU"æÜsÏûï¿?úõëwÞygtèÐ!ž|òÉxî¹ç""ê›>‡Ùd”””Ô9=BÄ·?lW^¾R>Ÿ=÷Ü3i\92®»îº8÷Üsëu˜¡¾ë]ùçêæ®<,²©¨Ïý^yŸêû|®Ë6¾ûçÿ•Çvc·Ë.»Ä¡‡§vZŒ5*;ì°¸ôÒK× ƒ Š|>ãÆ+ŒuíÚ5üñ˜6mZì¿ÿþÑ©S§¸çž{â÷¿ÿ}DDÃÏ;v\e\92&L˜wÜqGƒîËG}Çw\ì¹çžñÐC­u~IIIáõ÷] }M~w›6Å&£¬¬¬°›ý»VJyðûÆŒgœqF}ôÑqÿý÷×ë:õ]ïÊ\9þý¹?äýú!Ôç~¯í>·mÛv§iØ\ÛMÍ 'œÿû¿ÿÿó?ÿ³Ú9M›66mÚÔ9'Õ 'œ³fÍŠ·ß~;þû¿ÿ;>ýôÓØqÇ#"¢sçÎõ^ÃW\}ûö¢¢¢˜>}zLŸ>=,Xßž^bU¯£Ï>û,~úÓŸÆV[m/½ôR”––®u;eee«<_Ö÷_“mÚ´‰âââÕ¾&¿;—M›Àb“Ñ­[·˜:ujTWWן8qbDÄ*Ï{“Âĉã¸ãŽ‹ž={Æ“O>ù|ý¾l*++ã½÷Þ«ó›?'NŒÒÒÒ‰=öØ#š4io¿ýv­y_ýuLž<ù»_?”úºÖüþóŸñÓŸþ4–/_£G^åûªV¥[·n±xñâøðÃkÿûS>Ÿ®]»®òµ?qâÄÂÉZù? 1Ï ±òüJ·ß~{alåù•öÝwßuºÍ·ß~{µçÁʲ,ûÛßþ–µmÛ6ëÚµk¶`Á‚ÝöÊs5UUUÆæÎ›µnÝ:;å”SjÍ=òÈ#³òòòUž«iôèÑ Únc«ïótÁdÍš5[åy°þð‡?¬q›ëc»±úâ‹/êŒ}ýõ×Y÷îݳvíÚeß|óM¶téÒ쫯¾ª3ïŠ+®Èr¹\öÜsÏ­qS§NÍZ´h‘ýâ¿hÐÚž{î¹ìù矯õqòÉ'g¹\.{ôÑG³ñãÇæ.\¸0ëÙ³gÖªU«ì½÷ÞkÐvfΜ™m¹å–ÙE]T«©©É<ðÀlûí·Ïjjj ãk:ÖUW]Õ í²ñÊe™k°é8餓âÙgŸAƒEÇŽcĈñÎ;ïĸqãVy›Õ¹çž{bÁ‚1kÖ¬¸ÿþûãøã/ü óâ‹/Ž–-[Fuuuì¾ûî1kÖ¬2dHÝö;ï¼ó*Ï“µRMMMpÀñÁÄW\Q8ÛøÌ™3ãí·ß.ü–PÄ·¿â½ß~ûE—.]â¼ó΋™3gÆï~÷»8øàƒcÔ¨Q |”_}ž§™3gF·nÝ¢uëÖqÉ%—DuuuÜvÛm±Ã;ÄÛo¿½Ö3¹o®íÆè¸ãŽ‹êêê8è ƒ¢¼¼<æÌ™=öXL:5†gœqFLŸ>=ºuëýû÷]vÙ%""F£FŠ#<2þüç?׺Í.]ºD¿~ýbûí·O>ù$î»ï¾hÕªU¼ñÆëýÞÊ_ÿú×qÓM7żyój5ýØc^x!Î>ûì:ojoÑ¢EsÌ1k¼ÝÁƒÇm·Ý ˆ}öÙ'ž{î¹x饗âñÇ“O>¹0oáÂ…Ñ­[·¨®®ŽË/¿<š4i¿ûÝï"˲˜Ëçó…¿úé§Y–ýÿ3ˆ¯¼ìûguÖZ·óå—_fçž{nÖ®]»¬´´4;äC²wß}w•s_ýõlÿý÷ÏJJJ²­·Þ:8p`¶páÂß·A}Ÿ§)S¦d‡~xVZZšµiÓ&;ýôÓW¹7dU6×ÇvcôÄOd}úôɶÙf›¬¨¨(kÛ¶mvÔQGÕúß,X~úéY§N²ÒÒÒ¬iÓ¦Y×®]³ý×;ùæ›:·yÊ)§d;ì°CV\\œm·ÝvÙ…^˜Í;7Ézýë_gù|¾Î™Ü+**Vûõ¾ãŽ;®õvkjj²[o½5«¨¨ÈŠ‹‹³®]»f?þø*çΜ93ëÛ·oÖªU«Âž¹iÓ¦%¹lìÁHÌ›ÜX‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1˜ÀHL`$&°X‰ ,€Ä@b 1Øÿ?0ïÍ£5tIEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/minor_ticks_image.png0000644000077000000240000002742512436367710025114 0ustar tomstaff00000000000000‰PNG  IHDR Xšv‚psBIT|dˆ pHYsaa¨?§i IDATxœíÝŒ]uÿñw‡–éØò£LkNKWQ¤–¬„¶¡RÔ](u±üÊ ‰–Ão•ƒ› E¬È!¢"¨MviÉŠ?Rš"˜ø£ª‹,,ÕÝJJ{Ü–* tJK{¿æë8…ÂýœîÇ#é=sî×=qLŸÜ33£Z­V+èjz0r $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É ™ÑM:ׯcùòåqÀDOOOÓs€× ¿¿?Ö¬Y'Ÿ|rLœ8±é9@ @Û,_¾<,XÐô `|ë[ߊ~ô£MÏ:Úæ€ˆˆ?þCæCyMÉó<ªªú?s®»~îî²ÃæÁfΜ/¼ðÂÀ×/À›M€móêmW‡rHLŸ>ý5=f̘1ÿ§Îµc×ÏÝ]vØ<ØèÑü§Û&vñMèÀneÞ¼ym9·]ìH³ÁŽ7ö¼í¼¯×¨V«ÕjzЙ{챘1cF<ú裯ë¿Ö¶C–eQ×u£ìØ=wìv§½½½±iÓ¦ÝâëèLÞ’ Àˆ°»Ü‚bÇ`»ÃŽÝaCÄî³ã}ï{_Ó€ç, mv§[°€×Æ×-ÐnÞ’ @2HF€m—çydYEQ4=FQ‘eYäyÞô Ã  íªªŠº®£,˦§Ã(Ë2꺎ªªšžt8$#@€dŒ’ @2HF€É $#@€dÐvyžG–eQEÓS€aEY–EžçMO:œÚ®ªª¨ë:ʲlz 0Œ²,£®ë¨ªªé)@‡ @2HF€É $#@€dŒ’ @2h»<Ï#˲(Š¢é)À0Š¢ˆ,Ë"Ïó¦§N€mWUUÔueY6=FY–Q×uTUÕô Ã  $#@€dŒ’ @2HF€É $#@€¶Ëó<²,‹¢(šž £(ŠÈ²,ò9Æ ,ˆþþþA?ï¼ó¢««kÈŸC9d§ï¼óÎ8äC¢§§'¦M›·ÝvÛsþùŸÿ9ÞñŽwìâUF²ÑM€‘ä™gž‰_|1Î;82eJlÞ¼9–.]gŸ}v¬Y³&®¹æšˆˆX»vmœxâ‰1a„¸þú룯¯/nºé¦xüñÇcÅŠ1f̘çüØÇ>Û¶m‹›nº)¾ò•¯Ä5×\ÿò/ÿ2èóvwwÇwÞ9èØ>ûì3dßW¿úÕøøÇ?gœqF\yå•ñÈ#ÄÅ_›7oŽO}êSƒÎ5jÔ›uY€D€@BsæÌ‰9sæ :¶pá˜1cFÜqDzhÑ¢èïïU«VÅÔ©S#"âØc<Ïã®»îŠ .¸ ""¶lÙ=ôPüîw¿‹ñãÇǬY³bÖ¬YCd̘1qÖYgýÅmýýýqÍ5×Äܹsãž{ˆüÇŒ;vÄu×]^xaì»ï¾ç·Z­7v1€É-Xа®®®˜:uê w5î½÷Þ˜;wî@|DDÌž=;¦M›6›7oŽîîî?~|DDLš4)^|ñÅ!Ÿ£ÕjÅŽ;â…^vÇC=›6mŠO|⃎/\¸0^z饸þ÷¿¿Ë¯àU°y󿨏qcüæ7¿‰/~ñ‹±|ùò[œž}öÙØ°aC}ôÑCwÌ1ÇĪU«þ¾ß~ûÅ[ßúÖ¸öÚkãþçâÊ+¯Œ÷¾÷½;ý|{ï½wì»ï¾ÑÛÛ]tQ¼ôÒKƒÎyõyÿüóNŸ>=ºººâ¿øÅÀ±Q£F¹ Ø%nÁ‚\~ùåqÇwDDÄèÑ£ãÖ[o /¼0""Ö¯_“'Oò¸É“'ǦM›bÛ¶mï˜Ü~ûíñá8>÷¹ÏÅßüÍß ùšS¦L‰OúÓ1}úôرcG,[¶,¾üå/Ç/ùËøá{ì±ÇÀçÝc=bâĉƒ¿çž{Fooo¬[·nàØg?ûÙøìg?û&] `$ ЀË.»,Î<óÌX·n],^¼8.ºè¢èéé‰sÏ=wà§XuwwyÜØ±c#â߯ñj€Ìœ93žyæ™øõ¯ïyÏ{†žzê©[¯^½ëO­_¿>z{{}Ãú®;vlì·ß~±iÓ¦c“'OŽíÛ·ù]#[·nM›6Å”)SÞÐçˆp ì^½½©««+ößÿ˜4iR¬\¹rÈy+V¬ˆ#<ò ¾¾¾¾Ø¸qcLš4iàØQG+W®ô£‚þóŸÇŽ;ÞÐçÍó|H4Í›7/ʲÜåçÞ¸¢(bÉ’%ƒŽmÛ¶­¡5ÀHáHhÆ CŽmÛ¶-¾ñoDooovØañÇwD¾÷½ïÅÚµkÎ{ðÁcõêÕ1oÞ¼×üù^~ùåèëërüºë®‹ˆˆSN9eàØ¬Y³b¿ýö‹Ûo¿}й·ß~{Œ7.N=õÔ×üyÿ\UUQ×õ ?âšW–å¯Í?ÿAo6ï€@B^xaôõõʼn'žS¦L‰º®cñâÅñôÓOÇ׿þõŸHuõÕWÇ’%KbæÌ™qÉ%—D___ÜxãqÄGÄùçŸÿš?ßúõëã¨£ŽŠ³Î:+>øàˆˆX¾|y,[¶,æÌ™úЇÎ;vl\wÝu±páÂ8óÌ3ãýïüèG?ŠÅ‹Ç¢E‹ýB€]%@ ¡|ä#qçwÆí·ßÏ=÷\ì½÷ÞqÜqÇÅm·Ý³gÏ8oêÔ©ñðÃÇå—_W]uUtwwÇܹsãæ›o~]ßÿ1a„8í´Ó¢ªª¸ûî»cûöíqÐAÅõ×_W^yåó?þñǘ1câæ›oŽï|ç;ñ¶·½-n¹å–¸øâ‹ß”×0ªÕjµšt¦Ç{,f̘>úhLŸ>½é9Àkàëh7ß$#@€dŒ’ @2HF€m—çydYEQ4=FQ‘eYäyÞô Ã  íªªŠº®£,˦§Ã(Ë2꺎ªªšžt8$#@€dŒ’ @2HF€É $#@€dÐvyžG–eQEÓS€aEY–EžçMO:œÚ®ªª¨ë:ʲlz 0Œ²,£®ë¨ªªé)@‡ @2HF€É $#@€dŒ’ @2HF€m—çydYEQ4=FQ‘eYäyÞô Ã  íªªŠº®£,˦§Ã(Ë2꺎ªªšžt8$#@€dŒ’ @2HF€É $#@€¶Ëó<²,‹¢(šž £(ŠÈ²,òÿùÏGWWW~øáC>öä“OÆ)§œ{íµWôööÆ9çœ7ntΚ5k¢««+yä‘T“€1ºé@Zk×®E‹ŸqãbÔ¨QC>vâ‰'Æ„ âú믾¾¾¸é¦›âñÇ+VĘ1cZ t #Ì•W^'œpB¼òÊ+CÞÙX´hQô÷÷ǪU«bêÔ©qì±ÇFžçq×]wÅ\ÐÄd ƒ¸ FGy$î½÷Þ¸å–[¢Õj yäÞ{ï¹sçÄGDÄìÙ³cÚ´iqÏ=÷¤ž t #ÄöíÛ£(Š¸à‚ â°ÃòñgŸ}66lØG}ôsÌ1±jÕªAÇþ<^^ ·`Áñ•¯|%žyæ™øÁ~°Ó¯_¿>""&Ož<äc“'OŽM›6ŶmÛb̘1qÀÄöíÛÛºèLÞà¹çž‹k¯½6®½öÚèííÝé9ýýýÑÝÝ=äccÇŽtÀ® 0|æ3Ÿ‰‰'þÅßDÞÓÓ/¿üòmÙ²eÐ9»Ê-XÐáV¯^_ûÚ×â–[n‰µk×ß²eKlݺ5~ûÛ߯Þ{ï=pëÕ«·bý©õë×Goo¯à ¼aÞ÷ì³ÏÆŽ;ââ‹/Žw¾óV¬XO?ýt¼ãïˆë®».ößÿ˜4iR¬\¹rÈs¬X±"Ž<òÈ]Þ0cÆŒèêꊷ¼å-‘eYdYößÒ(Šbàkò-oyKtuuÅŒ3šžt8ï€@‡;üðÃãßÿýßýÔªV«ŸùÌgâÅ_Œ/}éKqàFDÄé§Ÿwß}w¬]»vàGñ>øàƒ±zõê¸âŠ+vyã>Ó§Oc/xÓ•eeY:öØc‰ ­t¸ÞÞÞøÐ‡>4äø¿øÅˆˆøà?8pìꫯŽ%K–ÄÌ™3ã’K.‰¾¾¾¸ñÆãˆ#ŽˆóÏ??Ùf s¹ F¨Q£F ù]S§N‡~8<ðÀ¸êª«â¦›nйsçFUU¾ÿxSxF¨‡zh§Ç=ôиÿþû¯F ï€É $#@€dŒ’ @ÛåyY–EQMO†QEdYyž7=èph»ªª¢®ë(˲é)À0ʲŒº®£ªª¦§N€É $#@€dŒ’ @2HF€É ´]žç‘eYEÑô`EQD–e‘çyÓS€'@€¶«ª*꺎²,›ž £,˨ë:ªªjz Ðጒ @2HF€É $#@€dŒ’ @ÛåyY–EQMO†QEdYyž7=èph»ªª¢®ë(˲é)À0ʲŒº®£ªª¦§N€É $#@€dŒ’ @2HF€É íò<,Ë¢(Ц§Ã(Š"²,‹<Ï›žt8´]UUQ×u”eÙô`eYF]×QUUÓS€'@€dŒ’ @2HF€É $#@€dŒÚ.ÏóȲ,Š¢hz 0Œ¢("˲Èó¼é)@‡ @ÛUUu]GY–MO†Q–eÔuUU5=èpHF€É $#@€dŒ’ @2HF€É íò<,Ë¢(Ц§Ã(Š"²,‹<Ï›žt8´]UUQ×u”eÙô`eYF]×QUUÓS€'@€dŒ’ @2HF€É $#@€dŒÚ.ÏóȲ,Š¢hz 0Œ¢("˲Èó¼é)@‡ @ÛUUu]GY–MO†Q–eÔuUU5=èpHF€É $#@€dŒ’ @2HF€m—çydYEQ4=FQ‘eYäyÞô Ã  íªªŠº®£,˦§Ã(Ë2꺎ªªšžt8$#@€dŒ’ @2HF€É $#@€dÐvyžG–eQEÓS€aEY–EžçMO:œÚ®ªª¨ë:ʲlz 0Œ²,£®ë¨ªªé)@‡ @2F€'žx"æÍ›x`Œ7.z{{ã„NˆÅ‹9÷É'ŸŒSN9%öÚk¯èíísÎ9'6nÜ8èœ5kÖDWWW<òÈ#©^Ð!F7=h¿gžy&^|ñÅ8ï¼óbÊ”)±yóæXºtiœ}öÙ±fÍš¸æšk""bíÚµqâ‰'Æ„ âú믾¾¾¸é¦›âñÇ+VĘ1c~%ÀÿuF€9sæÄœ9s[¸pa̘1#î¸ãŽY´hQô÷÷ǪU«bêÔ©qì±ÇFžçq×]wÅ\|;ÐYÜ‚#TWWWL:uл÷Þ{oÌ;w >""fÏžÓ¦M‹{î¹§‰™@‡ñŒ ›7oŽÍ›7ÇóÏ?ßùÎwbùòåqÛm·EDijÏ>6lˆ£>zÈãŽ9æ˜X¶lÙ c£FJ²è,FË/¿<î¸ãŽˆˆ=ztÜzë­qá…FDÄúõë#"bòäÉC7yò䨴iSlÛ¶-ÆŒp@lß¾=Ýp cA.»ì²8óÌ3cݺu±xñâ¸è¢‹¢§§'Î=÷Üèïîîî!;vlDDô÷÷ûFtà  0‚|ðÁqðÁGDÄ‚ âä“OŽK/½4æÏŸ===ñòË/yÜ–-[""ÎØU¾ F°ÓO?=žþùxê©§n½zõV¬?µ~ýúèííõîð†yF°Wo»êêêŠý÷ß?&Mš+W®rÞŠ+âÈ#ÜåÏ“çùx™7o^”e¹ËÏ ¼qEQÄ’%KÛ¶m[Ck€‘B€À°aƘ4iÒ cÛ¶m‹o|ãÑÛÛ‡vXDüñ‘»ï¾;Ö®];ð£x|ðÁX½zu\qÅ»üù«ªŠéÓ§ïú Ú¢,Ë!ÿ!à±Ç‹3f4´ Œ^xaôõõʼn'žS¦L‰º®cñâÅñôÓOÇ׿þõØc=""âꫯŽ%K–ÄÌ™3ã’K.‰¾¾¾¸ñÆãˆ#ŽˆóÏ?¿áWt#ÀG>ò‘¸óÎ;ãöÛoçž{.öÞ{ï8î¸ãâ¶Ûn‹Ù³gœ7uêÔxøá‡ãòË/«®º*º»»cîܹqóÍ7ûþàM!@`˜?~ÌŸ?ÿ5{衇Æý÷ßßæEÀHå§`É $#@€dŒ’ @ÛåyY–EQMO†QEdYyž7=èph»ªª¢®ë(˲é)À0ʲŒº®£ªª¦§N€É $#@€dŒ’ @2HF€É ´]žç‘eYEÑô`EQD–e‘çyÓS€'@€¶«ª*꺎²,›ž £,˨ë:ªªjz Ðጒ @2HF€É $#@€dŒ’ @ÛåyY–EQMO†QEdYyž7=èph»ªª¢®ë(˲é)À0ʲŒº®£ªª¦§N€É $#@€dŒ’ @2HF€É ´]žç‘eYEÑô`EQD–e‘çyÓS€'@€¶«ª*꺎²,›ž £,˨ë:ªªjz Ðጒ @2HF€É $#@€dŒÚ.ÏóȲ,Š¢hz 0Œ¢("˲Èó¼é)@‡ @ÛUUu]GY–MO†Q–eÔuUU5=èpHF€É $#@€dŒ’ @2HF€É íò<,Ë¢(Ц§Ã(Š"²,‹<Ï›žt8´]UUQ×u”eÙô`eYF]×QUUÓS€'@€dŒ’ @2HF€É $#@€dŒÚ.ÏóȲ,Š¢hz 0Œ¢("˲Èó¼é)@‡ @ÛUUu]GY–MO†Q–eÔuUU5=èpHF€É $#@€dŒ’ @2HF€m—çydYEQ4=FQ‘eYäyÞô Ã  íªªŠº®£,˦§Ã(Ë2꺎ªªšžt8$#@€dŒ’ @2HF€É $#@€dÐvyžG–eQEÓS€aEY–EžçMO:œÚ®ªª¨ë:ʲlz 0Œ²,£®ë¨ªªé)@‡ @2F€•+WÆE]‡vXŒ?>Þþö·ÇüùócõêÕCÎ}òÉ'ã”SN‰½öÚ+z{{ãœsΉ7:gÍš5ÑÕÕ<òHª—tˆÑMÚï†nˆŸüä'1oÞ¼8âˆ#býúõqÛm·ÅôéÓã§?ýivØa±víÚ8ñÄc„ qýõ×G___ÜtÓMñ+v¸«IDATøãÇŠ+b̘1 ¿àÿ:#ÀW\ÇsLŒýÿ¿äçÏŸ‡~x|á _ˆo~ó›±hÑ¢èïïU«VÅÔ©S#"âØc<Ïã®»îŠ .¸ ‘ý@çp ŒÇü øˆˆx×»Þ‡zh<õÔSÇî½÷Þ˜;wî@|DDÌž=;¦M›÷ÜsO²½@ç 0BµZ­øÝï~'NŒˆˆgŸ}66lØG}ôs9æ˜XµjÕ c£FJ²è,nÁ‚jñâűnݺøÜç>ëׯˆˆÉ“'9wòäɱiӦضm[Œ3&8à€Ø¾}{Ò½@gðŒ@O=õT,\¸0N8á„8÷Üs#"¢¿¿?""º»»‡œ?vìØAçì*#L]×qê©§Æ„ béÒ¥·RõôôDDÄË/¿<ä1[¶ltÀ®r Œ Ï?ÿ|Ì™3'^xá…øÑ~Y– |ìÕ[¯^½ëO­_¿>z{{ý^à  0BlÙ²%N;í´øõ¯<ð@¼ûÝïôñý÷ß?&Mš+W®òØ+VÄ‘G¹ËŸ;Ïó!ñ2oÞ¼(Ër—Ÿx㊢ˆ%K– :¶mÛ¶†Ö#…`ûöí1þüøÙÏ~÷Ýw_wÜq;=ïôÓO»ï¾;Ö®];ð£x|ðÁX½zu\qÅ»üù«ªŠéÓ§ïòãö(ËrÈxì±ÇbÆŒ -F#ÀW\ßýîwã´ÓN‹7Æ·¾õ­A_°`ADD\}õÕ±dÉ’˜9sf\rÉ%Ñ××7ÞxcqÄqþùç71è0F€_þò—1jÔ¨øîw¿ßýîw}lÔ¨Q2uêÔxøá‡ãòË/«®º*º»»cîܹqóÍ7ûþàM!@`x衇^ó¹‡zhÜÿým\Œd~ /Œ’ @2HF€É ´]žç‘eYEÑô`EQD–e‘çyÓS€'@€¶«ª*꺎²,›ž £,˨ë:ªªjz Ðጒ @2HF€É`DØ]~°ƒí;v‡ »ÏŽn¸¡é @‡ Àˆ°dÉ’¦'D„nwر;lˆØ}v<ðÀMO:œ’ Ànåõ܆Ү[V^ïóÚÑþ v¼±çÝ]nïˆ Ànæõ܆Ү[V^ïóÚÑþ v¼±çÝ]nÝô sõ÷÷GDÄÌ™3côèÑñ¾÷½/>ýéOÿÅÇlÛ¶-{ì±×ôü»Ã¹vìú¹»Ë›ÿè†nˆx 6mÚÿÿëàÍ6ªÕjµšt¦Å‹Ç‚ šžì‚o}ë[ñÑ~´é@ @Ûlܸ1–/_p@ôôô4=x úûûcÍš5qòÉ'Çĉ›žt $ã›Ð€dŒ’ @2HF€ƒ¬\¹2.ºè¢8ì°Ãbüøññö·¿=æÏŸ«W¯tÞyç]]]CþrÈ!;}Þ;ï¼39äèéé‰iÓ¦Åm·Ý¶Óóþð‡?Ä…^“&MŠñãÇǬY³bÕªUoúë|­žx≘7o^xà1nܸèííN8!/^<輑r=þÜç?ÿùèêêŠÃ?|Ðñ‘p=~øÃîô5vuuÅŠ+Î ×àõð›ÐAn¸á†øÉO~óæÍ‹#Ž8"Ö¯_·Ýv[LŸ>=~úÓŸÆa‡6pnwwwÜy烿Ï>û yί~õ«ññ<Î8㌸òÊ+ã‘G‰‹/¾86oÞŸúÔ§ÎÛ±cGœzê©ñÿññ©O}*z{{ãË_þrœtÒIñè£Æ»Þõ®ö½ða<óÌ3ñâ‹/ÆyçS¦L‰Í›7ÇÒ¥Kãì³ÏŽ5kÖÄ5×\3pîH¸jíÚµ±hÑ¢7n\Œ5jÈÇGÊõ¸ä’Kâ˜cŽtìÀô÷‘r-^“ÀŸøñÜÚ¶mÛ c«W¯n;¶µ`Á‚cçž{nk¯½öú«Ï·yóæVoooë´ÓNt|Á‚­ñãÇ·~ÿûßû·û·Ö¨Q£Z÷Þ{ïÀ± 6´&L˜Ð:묳võ%½é¶oßÞ:òÈ#[o{ÛÛŽÄë1þüÖûÞ÷¾ÖI'ÔzÏ{Þ3èc#áz<ôÐCCöìÌH¸¯‡[°€AŽ?þø=zð›£ïz×»âÐC§žzjÐñV«;vìˆ^xaØç{衇bÓ¦Mñ‰O|bÐñ… ÆK/½ßÿþ÷Ž-]º4²,‹¿ÿû¿86qâÄ8óÌ3ã¾ûî‹mÛ¶½‘—ö¦éêꊩS§Æ˜1cI×ã‘G‰{ï½7n¹å–hµZ;}d¤\V«}}}ñÊ+¯üÅsFµx-ðWµZ­øÝï~'Nt|óæÍ±÷Þ{Ǿûî½½½qÑEÅK/½4èœWïI?ú裟>}ztuuÅ/~ñ‹AçNŸ>}Èç?æ˜cbóæÍñôÓO¿Y/éuÛ¼yslܸ1~ó›ßÄ¿øÅX¾|ù [b^=g$\íÛ·GQqÁ º%ïÏ”ëqþùçÇ>ûì===1kÖ¬xôÑG‡œ3R®Àká{@€¿jñâűnݺøÜç>7plÊ”)ñéO:¦OŸ;vìˆeË–Å—¿üåøå/?üác=öˆˆˆõë×Ç{ì1$^öÜsÏèííuëÖ [¿~}œtÒIC>ÿäÉ“#"bݺuñ¼ítùå—ÇwÜ£GŽ[o½5.¼ð¤ëñ•¯|%žyæ™øÁ~0ì9#áztwwÇgœøÀbâĉñÄOÄM7Ýï}ï{ãÇ?þqyä‘12®Àë!@€¿è©§žŠ… Æ 'œçž{îÀñE‹ :ïÌ3ÏŒiÓ¦Å5×\K—.ùóçGDDì¹çž;}îîîîèïïøû–-[¢»»{ÈycÇŽx®¦\vÙeqæ™gƺuëbñâÅqÑEEOOÏÀ5)×ã¹çž‹k¯½6®½öÚèííö¼‘p=Ž?þø8þøãþ>wîÜ8ãŒ3âˆ#Žˆú§ŠeË–EÄȸ¯‡[°€aÕu§žzjL˜0!–.]ºÓûüÿÔe—]]]]ñàƒëé鉭[·îôü-[¶DOOÏ s_~ùåž÷êÇ›rðÁǬY³bÁ‚±lÙ²˜={v\zé¥ñzx=>ó™ÏÄĉ£(Š×ýØN¼îÀŒ}èCñÐCE«Õö¼‘p-†#@€zþùçcΜ9ñ /Äý÷ßY–ýÕÇŒ;6öÛo¿Ø´iÓÀ±É“'ÇöíÛcãÆƒÎݺuklÚ´)¦L™2èÜ?½ÍäUëׯˆtnÓN?ýôxþùçã¿þ뿆=§Ó®ÇêÕ«ãk_ûZEk×®5kÖÄš5kbË–-±uëÖøío¿ÿýï‡}|§]áL:5¶nÝ:ä{<þÔH¹;#@€!¶lÙ§vZüú׿Žï}ï{ñîw¿û5=®¯¯/6nÜ“&M8vÔQGEÄÁáŸúùÏ;vì¸O>"âÈ#ŒÇ{lÈ9þÙÏ~ãÆ‹iÓ¦íêKzÓ½úÎGW×ðÿ7Úi×ãÙgŸ;vÄÅ_ï|ç;þ¬X±"ž~úéxÇ;Þ×]wݰï´ë1œÿþïÿŽžžž?~ü°çŒ”k°SÍüô_`wõÊ+¯´>øÁ¶öÜsÏÖ²eËvzΖ-[Z/¼ðÂãŸüä'[£Fj}ûÛß8Ößßÿº·ÁÒ¥KŽmذ¡µï¾û¶þáþá¾´]ò¿ÿû¿CŽmݺµ5}úôÖĉ[¯¼òʈ¹7nl}ûÛßnÝwß}¾ýío·Þóž÷´8à€Ö}÷Ý×úÕ¯~5b®ÇÎþ·ñ‹_ü¢5f̘և?üáV«5²¾V^«Q­Ö_¸Iq.½ôÒ¸õÖ[ã´ÓN‹yóæ ùø‚ bÍš5qÔQGÅYg|pDD,_¾<–-[sæÌôû ""n¿ýöX¸paœqÆñþ÷¿?~ô£Å7¿ùÍX´hQ\uÕUçíØ±#þöoÿ6~õ«_Å'?ùÉßî¼víÚX¹retÐAí}ñ;ñw÷wÑ××'žxbL™2%꺎ŋÇÓO?_ÿú×ãœsÎQ×cgN:é¤xî¹çâñLj1×cÖ¬Yñ–·¼%Ž?þøxë[ßÿùŸÿwÜqGtwwÇO~ò“8øàƒG̵x]š. `÷rÒI'µºººZ£Fò§«««ÕjµZøÃZgŸ}vë ƒj7®5vìØÖá‡Þú¾Ðzå•Wvú¼_ûÚ×Zï~÷»[ÝÝÝ­ƒ:¨õ¥/}i§çýþ÷¿o}ìckMœ8±5nܸÖÌ™3[>úhÛ^ï_ó¯ÿú¯­<Ï[Y–µÆŒÓêíím}àh=ðÀ猤ë±3'tRëðÃøûH¹·Þzkë¸ãŽkõöö¶ÆŒÓÚÿý[çœsNë7¿ùÍÀ9#åZ¼Þ’ñMè@2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dŒ’ @2HF€É $#@€dþ%ˆ¸DH6IEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/overlay_features_image.png0000644000077000000240000010134012436367710026137 0ustar tomstaff00000000000000‰PNG  IHDRXX¾f˜ÜsBIT|dˆ pHYsaa¨?§i IDATxœìÝ{\”eú?ðÏ3GP-E@QdÌOµj KjÚ¦T¢­KÖîqÅSíZ‘'t%[µÍLÓ4KÝÐ4ýnÚA[×ÒM«¯‹)®yªAt-E@®ß4Ïa€>Àóy¿^óšå~®ç~îû²e.žÃ=ŠˆˆˆˆˆH3:G€ˆˆˆèNˈˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc®Žݼ¼€²2ÀŸûnG†ˆˆí¿ÿªªOOàúuG¦I(""ŽÝa\\€êjG‚ˆˆš®¦Ðr<ƒEÚ3X:àç×$‡,--Å•«WáÛ®ZµjÕ$Çln˜æ`æh†9((¨ù\pqqôHšŽØÙÕ«WeòäÉÒ¡Cñòò’èèhùæ›oÌâ***dÚ´iÒ¶m[¹ï¾ûäÌ™3&Û÷ïß/¿ûÝï$$$DZµj%Ý»w—„„)((°Ø×Â… ¥[·nâáá!Ý»w—ÔÔT©¬¬4‰;pà€(Š"çÏŸ7i7 'mÛ¶•6mÚÈØ±cÍÆ#"R\\,³fÍñððÐÐPY»vm£ò³aÃéÕ«—xzzJHHˆ¬ZµÊb\Có("òå—_Ê!C¤U«VÒ©S'™9s¦”””˜ÅUWWËÒ¥K%((H<==åÞ{ï•÷Þ{Ï,î©§ž’aƉˆHJJŠÙž”¿¿PóÞDÒÒÒ€¤¥¥5Ù1›æ€9aD˜‘f˜|.8š]Ï`UWWãá‡ƱcÇðüóÏ£}ûöX³f † †ŒŒ ôèÑC]¹r%>þøc¼ôÒKøì³Ï‡£GªÛ_xá"..!!!8}ú4V¯^?þYYYèØ±£;wâþç0`À|ýõט?>¾ÿþ{¬[·Îæ˜KJJââbÌ;®®®X±b¢¢¢••___@UUFމŒŒ LŸ>!!!øôÓO‘””„«W¯âÅ_¬7?ëÖ­ÃÔ©S1nÜ8Ìž=_|ñfΜ‰ÒÒR<ÿüó·”Ǭ¬,ÄÄÄ wïÞX±b~øá¼òÊ+8uêöìÙcrü9sæ`éÒ¥HLLÄÀ±k×.Lœ8Š¢`„ &±Š¢XüßDDDd=«·íÛ·‹¢(ò¿ÿû¿jÛåË—¥]»v2qâD“Ø_þò—²oß>©¬¬”ÀÀ@ùî»ïÔí‡2ëÿ‹/¾EQdÞ¼yjÛ¿ÿýoQERRRLbgÏž-:NŽ;¦¶Y:ƒµtéRQEŽ=ª¶åå剫««Ì™3Gm{ÿý÷EQÙ¸q£ÉqÆ'z½^þûßÿÚJ”––Jûöíå‘G1iooo¹zõªÚÖ˜<Ž5Jüýý¥¸¸XmÛ°aƒ(Š¢æW¤æ,›››Ì˜1ÃdÿÈÈH ”ªª*µí©§ž’èèhi¾g°v®Z%)€ì´rÐ0Ìs ˆ4Ã8á,».Ó°sçNtêÔ =ö˜ÚÖ¡CŒ?»wïÆÍ›7Õöëׯ㮻¸À××%%%êö¡C‡šõÿÀÀ××yyyjÛ¡C‡O<ñ„IìO<ÁöíÛëó AƒÐ¿µ­gÏžˆ‰‰Áûï¿ß ã”••a÷îÝ6sàÀ\¹rIII&íÓ¦MÃõë×ñÉ'Ÿ˜Œ©!y,**Âþýûooo5vÒ¤Iðöö6ÿîÝ»QYYivü©S§Â`0à믿6i—fþ,„¾° ~wVÌs0s0Í] ¬ÌÌLôë×Ϭ}àÀ(--Åþóµí—¿ü%æÎ‹Ó§OãÍ7ßÄ… ЫW/›ý—”” ¸¸:tPÛÊËËz½Þ$Öøó7ß|cÒ^ûrWuu5Ž;†XóéÓ§qýçÇKËËËáââww÷§®ÌÌL0;V¿~ý Óé••eÛ<?~•••f}º¹¹!<<\=¦±Oooo³8Lޝ(Šš§Úÿ›ˆˆˆ,³kUPP? O‘Û.\¸ ¶-X°§OŸFHHþô§?aݺuððð°Ùÿk¯½†›7ošÜ/d,>lk<㔟Ÿ¯¶ 6 UUUèÒ¥ àÊ•+¨¨¨hИ{õê…ªª*³3=–ŽcIAA\\\LŠCpwwGûöíMrÓÐ<˜´×Ö©S'³>kß·f­Oظq#>ÿüs@JJ Μ9csnŽlòæ`æ`š»Þä^VVf±HòôôܸqCmëܹ3Ž;†ììl©7“[óÅ_`Ñ¢E˜0a† ¦¶=]»vÅìٳѪU+ôë×GŽÁ¼yóàêêjr̺ŒÛ2æ‰'âÏþ3~ÿûßã7Þ@=°oß>¬]»ÖlnÖŽU÷ì—‘‡‡‡Éþ Íc}ã¯Ýç7üoÓôìÙÓäÝ1ÌÀÌÀ4šX7oÞÄO?ýdÒv×]wA¯×«—ìj+++`~ÏÝÝÝ⥰ºòòòðè£âÞ{ïņ L¶yxxà“O>Áøñãñøã¨)–-[†ÔÔT“{“ê2ާ!cîØ±#>üðC<ùä“1bÀÇÇ«V­ÂSO=eó8Æ~***,n+++3ÉMCóXßøk¯…¢×ëÕýmõy;JKKñÁ–-Ï«WÕ{‚ƒƒÍÿOïé „…Ùî0'§f…xKrsëÐõÇ…†¶æ^PPó²ævçÔ¬fký0kó0¶åæ¶ìyÔÖØyÔÎÐrçQWcæQ7F-mÖ4fÖæÓÒæaM}ól÷a‡ydeeáĉêÏ.h“ŸèâbÜþ§J £ÅòƧñŒ/N'çΓ=z´Y¼ñ©¶ìììFëûï¿—ÀÀ@ –‹/ÚŒÍÉÉ‘/¿üR®^½*¥¥¥¢Óéd„ V㫪ªÄÓÓS¦M›f¶mÞ¼y¢(ŠÙzRUUUòí·ßÊW_}%ׯ_—“'OŠ¢(ò /Ø[jjª(Š"—/_6i///™={¶ÚÖÐ<>|XE‘;v˜Å:T  þœ ^^^fqß}÷(Š"«W¯¶9~›~~Zä@ðó+¨y‚ÄÚ+,¬þ~ÃÂl÷ˆddXß?;»þýëûo2%Åþó¨ó,çÁypœG£ç‘‘Qÿþv˜GTT”ï°ºñNô¡&g°ÂÃñÿ~“¶N:!<<‡‚ˆ˜Ü}äÈxyyá¿øE£ŽóÓO?aĈ¸yó&8`ñ¢ÚBCCÕÿ½gψ|ðA«ñ:}úôAzzºÙ¶#GŽ 88^^^fûÜ{ï½êÏÆ<Ø:DDDÒÓÓ1jÔ(µýèÑ£¨®®Fxx¸ÚÖÐ<ÞsÏ=puuEzz:ƧÆUTT ++Ëä‰Çˆˆ¼ýöÛÈÍÍ5ÉÓ‘#GÔcÞ.ßví¶j€š3X{ê;ƒUŸ;lŸÁŠ·½÷î@FFý1¶L™Œc}ûíΨõ{kó0æ -­eÏ£nŒ-uçQ;¡¡-wu5fus`ÔÒæaMCæ‘–f9µcli.ó¸ÝÀz»Ìãµ×^3;ƒµ'?ÑË—C_TTÿñî$ö¬ÞŒë7íܹSm»|ù²´mÛV~ó›ß4ª¯’’4høøøX]ÁÜšÒÒRéׯŸøûû[\Ѽ6[ë`½øâ‹6÷ýïÿ+]ºt‘ððp³ãçææÊ?þ¨¶Ý¸q£Ñë`5$£F’Î;[\ëÿø‡Úf0ÄÝÝ]¦OŸ®¶UWWË< R]]ms®69b½“'jþÒ:q¢éŽÙÜ0Ìs ˆ4¿8á:Xvý²çêêj :ÙÙÙxî¹çÔÈ ÒÓÓÒà¾bccñá‡â÷¿ÿ½ÉMíкukŒ;Výyüøñð÷÷Ghh(ŠŠŠðÎ;ïàܹsøä“Omó8%%%ˆˆˆ@qq1fÏž WWW¼úê«dee¡}ûöjlTTŒàà`\¼xëׯGii)þõ¯¡wïÞjÜÁƒñ«_ý )))HIIQÛ×®]‹iÓ¦aܸq1b:„wß}K–,Arrò-å133ƒFXX&Ož ƒÁ€W_}QQQØ»w¯É\_xá,_¾‰‰‰0`víÚ…={ö`ëÖ­fë{5J@Ÿøûí÷CDDwgü\°wwõêUIHH0ù½ [÷ÉX$:Îä^/ã«[·n&±Ë–-“ÐÐPÑëõâëë+±±±òí·ß6øXÆï"ôññ‘Ö­[˘1cäôéÓfqüã%88X<==¥cÇŽ/gÏž5‹;pà€èt:Y´h‘Ù¶·ÞzKzõê%"+W®´8¦ÆäñðáÃ2dÈÑëõÒ±cG™1c†Õï"|ùå—%((H<<<¤OŸ>²uëÖz²ÓNø— Ùà„Ÿ v=ƒENÊÿR!""ëœðsÁ® 9#XDDDDcEDDD¤1XDDDDcEDDD¤1XtgÈÉz÷®ywVÌs0s0Í ,º3”•Õÿ¥¤w:æ€9˜€9˜ƒf€‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒÝüü€””šwgÅ0s0sÐ (""ŽÝa€ü|Àß0=""r4'ü\à,""""±À""""Ò ,""""±À""""Ò ,""""±À""""Ò ,º3ܸœ8Qóæ`æ`šXtgÈÍî¹§æÝY1ÌÀÌÀ4,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4æêèi"4ÈκwwôH‡9`æ`æ PDD=ºÃùù€¿?`08z4DDähNø¹ÀK„DDDDcEDDD¤1Xu\¿~)))x衇àëë N‡Í›7›Äˆ6mÚ„1cÆ K—.ðööFŸ>}ðÒK/¡¼¼¼ÁÇúꫯ0tèPxyyÁÏϳfÍÂõë×ÍâDË–-C·nÝ ×ëÑ·o_lÛ¶ÍbŸùùù?~<ÚµkÄÆÆâìÙ³c?üðCôë×z½]»vÅÂ… QUUe³iÓ&èt5ÿ™¦N ƒÁ€¯¿þZmÛ¹s' „þýû«m={öDLLŒIŸ999ÈÍÍEbb¢zù’’’ "عs§Íñ‘m,°4tñâE@‡lÆ?~•••0`€I»››ÂÃÑ™™©¶effÂÛÛ½zõ2‰8p €šKP]]cÇŽ™õiŒ=}ú´z—±ÿº±~~~Pû4ª}‰´îåÒf£ X¸°æÝY1ÌÀÌÀ4,°4´lÙ2øøøÔ{VÁÏÿÁûùù™mëÔ©.\¸`Û±cG³8ã¾ÆØ+W® ¢¢ÂbŸucsü§Ÿ~Z½ñ}ذa¨ªªB—.]lÎÏ! €E‹œû— sÀÌÀÌA3À•Ü5²dÉ|öÙgX»v-Ú´ic3öƳmžžžêvc¬µ¸Ú}Õ×gcbKJJlŽŸˆˆˆlã, lß¾óçÏGBB¦L™Ro¼^¯‹K:”••¡U«V&±eeeãj÷U_Ÿ‰5n'""¢[Ã3X·éŸÿü'&Mš„_ÿú×xóÍ7´ñÒ\…S·èܹ³IìÁƒ-ÆPc}}}áááaµÏÚ±µïïïokéþ[QZZжlx^½ }a! 88={ö4 öôÂÂlw˜“X(6¹¹õèÆúãBC[fAíSî·;ðó«yYcmƶÜÜ–=Ú;Ú9Zî<êjÌ<êæÀ¨¥ÍÚÆÌÃÚ|ZÚ<¬©o€í>ì0¬¬,œ8qBýÙ¥¢mòó]\ §ûÓÝÑ16gééé—i0ú¿ÿû?ñòò’¡C‡JYYYƒû-,,777yþùçMÚËËËÅÛÛ[Ô¶7ÞxCE‘œœ“Ø-[¶ˆ¢(røðaµmàÀ2hÐ ³ã >\zôè¡þœ-Š¢Èš5kLâòóóEQIMMmð\,úùqÜÁϯ æ]k¯°°úû ³Ý ’‘a}ÿììú÷Ïζ=†”ûÏ#%ÅöþœçÁypõÍ##£þýí0¨¨(1þÞ auãh™~Ù³ GÅ Aƒ°iÓ&Lš4Éd[nn.xàtî܇‚Õ~òòòàåå…ÀÀ@µmôèÑøöÛoqòäIu©†·ß~“'OƧŸ~Š#F¨Y™½{÷îHLLĪU«"‚¨¨(œ;wçÏŸWŸì[¶l’““‘žž®.ÕpòäIÜsÏ=xî¹ç°dÉõøaaaððð@FF†ºTÃüùó±dÉää䘟ajŒŸ¿Ô³´];|ðó˜›ä V|<‘ôëg9æNü ½6cÒÒ€Çk¹ó¨íVÎ`sÚrçQWcÏ`ÕÎQK›‡5 ™Çßÿn9F-e·óïñÍ7@ÿþÖs4í¬åË¡/*rª/{feÁêÕ«QXXˆ .àÍ7ßÄc=¦®ê>sæL(Š‚Þ½{ãÂ… X²d‰É%=èÑ£‡Ée6N‡¨¨(8p@mËÌÌÄàÁƒ†É“'Ã`0àÕW_ETTöîÝkÒß /¼€åË—#11 À®]»°gÏlݺO<ñ„WRR‚ˆˆcöìÙpuuÅ«¯¾ AVVÚ·o¯Æ~òÉ'3f ¢££1aÂdggã7Þ@BBBƒ/uZåˆoM7þ2±U`Ýé˜æ`æh~9pÄç‚£9òôYs$Š¢ˆ¢(¢ÓéD§Ó©ÿûüùóröìYõgc\í×ï~÷;“þE‘èèh³ã>|X† "z½^:vì(3fÌ’’³¸êêjyùå—%((H<<<¤OŸ>²uëV‹c7 '>>>Òºuk3fŒœ>}Úbì®]»$""B<==¥K—.²`Á©¬¬¼…ŒÕáˆ{Oœ¨9•}âDÓ³¹a˜æ@„9i~9p•Üy‹´çŒ©‘uNø¹Àeˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹î 99@ïÞ5ïΊ9`æ`æ `Ew†²²ú¿3ëNÇ0s0sÐ °À""""Ò ,""""±À""""Ò ,""""±À""""Ò ,""""±À¢;ƒŸ’Róæ`æ`šEDÄу ;L@Ÿøûƒ£GCDDŽæ„Ÿ <ƒEDDD¤1XDDDDcEDDD¤1XDDDDcEDDD¤1XDDDDcEw†7€'jÞsÀÌÀÌA3À‹î ¹¹À=÷Ô¼;+æ€9˜€9˜ƒf€‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘Æ\="M„†ÙÙ@÷ã0ÌÀÌÀ4Šˆˆ£Aw˜€ ?ð÷ G†ˆˆÍ ?x‰ˆˆˆHc,°ê¸~ý:RRRðÐCÁ××:›7o6‹{úé§¡ÓéÌ^¡¡¡ >ÖW_}…¡C‡ÂËË ~~~˜5k®_¿n'"X¶lºuë½^¾}ûbÛ¶mûÌÏÏÇøñãÑ®];øøø 66gÏžµûᇢ_¿~ÐëõèÚµ+.\ˆªª*“˜M›6A§«ùÏäàÁƒÐétøþûïDDDdŠÖm(--E›6mжm[´oßÓ§O·xU]ÇGee% `Òîææ†ððpdffªm™™™ðööF¯^½Lb æR#TWWãØ±cf}cOŸ>­ŽÍØÝX???¨}Õ¾Djír)ý,°nQçÎñ /`Ó¦MضmÆŒƒ5kÖࡇ2»Q¼®‚‚5M]:uÂ… Lb;vìhgÜ×{åÊTTTXì³nlcŽÿôÓO«ó6lªªªÐ¥K›ósˆ‚`ášwgÅ0s0sÐ °ÀºEK–,Á’%K0nÜ8Œ?7nÄK/½„/¿ü²ÞKl7nÜPs“|]žžžêvc¬µ¸Ú}Õ×gcbk¿Å((-rî_&Ìs0s0Í , =ûì³Ðétøì³ÏlÆéõz@yy¹Ù¶²²2´jÕÊ$¶¬¬Ìb\í¾êë³1±ÆíDDDtk¸Lƒ†<==áëë‹+W®ØŒ3^š+°ð—EAA:wîl{ðàA‹qÔX___xxxXí³vlíãûûû›ÅÞÿý6ÇßP¥¥¥ø`Ë€çիЂƒƒÑ³gOÓ`OO ,Ìv‡99€…b›[ÿ€nܨ?.4°U`Øþ‹ðvç~~5/k¬ÍÃØ–›Û²çQ[cçQ;@ËG]™Gݵ´yXÓ˜yX›OK›‡5õͰ݇摕•…'N¨?»TT M~>¢‹‹átº;ø)Æf-==Ýê2 –‰¢(ò‡?üÁf\aa¡¸¹¹ÉóÏ?oÒ^^^.ÞÞÞ’ ¶½ñÆ¢(Šäää˜ÄnÙ²EE‘Ç«m”Aƒ™oøðáÒ£GõçììlQEÖ¬Yc—ŸŸ/Š¢Hjjjý“µåçÇq?¿R€šGt­½ÂÂêï7,Ìv€HF†õý³³ëß?;ÛöRRì?”ÛûsœçÁyÔ7ŒŒú÷·Ã<¢¢¢Äø{€„Õw¢exëa/ä¬ IDAT”——£¢¢­[·6i_¼x1ࡇ2iÏË˃——Ô,Fúàƒ"-- óçÏW—jx÷ÝwqýúuÄÅÅ©ûŽ;Ï>û,Ö¬YƒU«VDo¾ù&0xð`5vܸqHNNFFF†ºTÃÉ“'qàÀ<÷Üsj\ï޽ѫW/¬_¿S¦LQ—jX»v-EÁ¸qã4É“o»vHûyÌžW¯bO}g°ê³c‡í3Xññ¶÷ïÞÈȨ?Æ–)S€1c¬o¿Ýy¶ÿª¬Ï؃´´–=º1¶ÔG턆¶ÜyÔÕ˜yÔÍQK›‡5 ™GZšåÔŽ±¥¹Ìãvÿ=ë9ì2×^{Íì Öžü|D/_}#—4jñ]á5G«V­’Å‹ËÔ©SEQyüñÇeñâŲxñb¹víšœ={VÚ¶m+III²råJY¹r¥Œ=ZE‘Ñ£G›õ§(Š 6̤í›o¾OOOéׯŸ¬]»VæÎ+z½^zè!³ýŸþyQE¦L™"o½õ–<üðâ(м÷Þ{&qÅÅÅÒ£G騱£,_¾\V¬X! ?þø£IìÇ,:Nbbbdýúõ2sæLqqq‘)S¦Ü~± œñ¯5[g°îtÌs ˆ0"Í/N¸Ð( , ‚‚‚DQQEt:èt:õŸ?^ åÉ'Ÿ”ñòòOOOéÓ§üå/‘ÊÊJ³þE‘èèh³öÇË!CD¯×KÇŽeÆŒRRRbW]]-/¿ü²‰‡‡‡ôéÓG¶nÝjqìƒAâââÄÇÇGZ·n-cÆŒ‘Ó§O[ŒÝµk—DDDˆ§§§téÒE,X`qüÆË1˜æ@„9aDš_œ°Àâ%B ¬}9rmûÛßÜ_uuµÅö!C†àðáÃõî¯( ’““‘œœ\o¬¿¿¿Éªí¶Œ;cÇŽmPl³g¼Y³!§¼ïTÌs0s0Í€""âèAÐ& ÈÏüýƒÁÑ£!""GsÂÏ®ƒEDDD¤1XDDDDcEDDD¤1XDDDDcEDDD¤1XDDDDcEDDD¤1XtgÈÉz÷®ywVÌs0s0Í ,º3”•Õü"±õ¥¤w:æ€9˜€9˜ƒf€‘ÆX`iŒ‘Æì^`UVVâ½÷ÞCbb"}ôQ?~píÚ5üýïÇ¥K—ì="""¢&e׫°°C† Áoû[¼÷Þ{ؽ{7._¾ ðòòÂÌ™3ñÚk¯ÙsDDDDMήVrr2rrrðé§ŸâìÙ³&Û\]]1nÜ8ìݻמC """jrv-°víÚ…éÓ§cĈ·‡„„˜^D·ÄÏHI©ywVÌs0s0Í€«=;¿víºwïnuûÍ›7QYYiÏ!³ðó.tô(‹9`æ`æ °ë¬îÝ»###ÃêöþóŸ ³çˆˆˆˆšœ] ¬É“'ãwÞÁöíÛMÚËÊÊ0wî\ìÝ»S¦L±çˆˆˆˆšœ]/Μ9'NœÀo~óøøø&NœˆŸ~ú UUU˜2e ì9"""¢&g×K§Óá­·ÞÂSO=…;vàÔ©S¨®®Fpp0&L˜€ÈÈH{žˆˆˆÈ!ìZ` :C‡mŠC9¿*‡ˆˆˆHcšžÁêÖ­Eˆ¨mŠ¢X(Š‚3gÎh9 rF7ngÎÝ»z½£GãÌs0s0Í€¦g°¢¢¢‰¨¨(õååå…sçΡU«VGxx8ôz=Î;oooDEEi9rV¹¹À=÷Ô¼;+æ€9˜€9˜ƒf@Ó3X›6m2ùùƒ>ÀîÝ»±oß><øàƒ&ÛþùÏbüøñHMMÕrDDDDg×{°,X€éÓ§›W0|øpLŸ>óæÍ³çˆˆˆˆšœ] ¬ï¾û:t°ºÝ××ß}÷=‡@DDDÔäìZ`ãwÞAqq±Ù¶¢¢"lÜ¸ÑæwµDv]+55?þ8BCCñÔSO!$$ðŸÿü›7oÆ¥K—°cÇ{ˆˆˆ¨ÉÙµÀŠÅÞ½{ñ /àå—_6ÙŽwÞy#GŽ´çˆˆˆˆšœÝWr1bFŒ‚‚œ?еkWøùùÙûÐDDDD¡HíUA‰´äçþþ€ÁÐ4Çä¢zÌÀÌÀÍ/Žø\p0»X›7o¶¹’»Ñ¤I“ì5r'ü?ÙàŒŸ bGŠ¢4èÕœ”””È‚ däȑҮ];QE6mÚdW]]-k×®•ˆˆiÓ¦´oß^¢¢¢ä“O>ið±¾üòK2dˆ´jÕJ:uê$3gΔ’’‹ÇZºt©‰§§§Ü{ï½òÞ{ïYìÓ`0H\\œ´mÛVÚ´i#cÇŽ•3gÎXŒÝ½{·DDDˆ§§§téÒERRR¤²²Ò$fãÆê¿ÑDQ9þ¼í‰ùû‹5ïDDDNø¹`×eΜ9cö:uêöïßÇ{ ýû÷Gvv¶=‡Ðh—/_ÆâÅ‹qòäI„‡‡°ü}ŠsçÎERR°|ùrÌŸ?×®]ïýk|ðÁõ'++ 111(++Ê+€õë×#..Î,vΜ9HNNÆÈ‘#±zõjtéÒ'NÄöíÛMâJJJC‡aîܹX´h233…+W®˜ÄîÝ»±±±ðõõÅêÕ«‹ÔÔT̘1£1é""""KYÝ5J¦NêÈ!˜)//—K—.‰ˆÈÑ£GEQÙ¼y³Y\çÎå¾ûî3i+**’Ö­[ËØ±cë=ΨQ£Äßß_Š‹‹Õ¶ 6ˆ¢(²oß>µÍ`0ˆ›››Ì˜1ÃdÿÈÈH ”ªª*µméÒ¥¢(Š=zTmËËËWWW™3gŽÉþaaaa²ÿ¼yóD§ÓI^^žÚÆ3XDDtÛœðsÁ®g°êóë_ÿï¿ÿ¾#‡`ÆÝÝwß}7@lÜž¦×ëq×]w™´µnÝ^^^hÕª•Ícaÿþýˆ‡···Ú>iÒ$x{{›äd÷îݨ¬¬DRR’IS§N…Á`À×_­¶íܹƒ BÿþýÕ¶ž={"&&ƤϜœäææ"11:ÝÿÿO )) "‚;wÚ?ÙæÐëÌ™3(++sänYrr2þñ`õêÕ8wîòòò0mÚ4cÖ¬Y6÷=~ü8*++1`À“v777„‡‡#33SmËÌÌ„··7zõêe;pà@5— ººÇŽ3ëÓ{úôi\¿~]í€Y¬ŸŸÔ>j_"mÈC DDDÎήë`}ñÅÛ ñ¯ý «V­Âرcí9»IHH€‹‹ ¦L™‚™3g:tè€Ï>û ÷ÝwŸÍ} ÀâZ`:uÂáÇMb;vìhgÜ÷Â… €+W® ¢¢ÂbŸµcCBBê=¾±Oxúé§ñôÓO† †ªª*›s#""";XÆ ³ºÍÅÅqqqXµj•=‡`7;vì@bb"âââ0nÜ8aÅŠxôÑGqèÐ![Ý÷Ƴmžžžêvc¬µ¸Ú}Õ×gcbKJJ¬Ž½Ù*(Ö­¦Lœu[æ€9˜€9˜ƒfÀ®ÖçŸnÖ¦( Úµk‡®]»ÂÇÇÇž‡·›²²2$%%aôèÑØºu«Ú>vìX„„„`îܹضm›Õýõ?/úV^^n±ïÚ÷péõz‹—Qmƾêë³1±úæ°(]c‹cÆ8ï/æ€9˜€9˜ƒfÀag°Z²¼¼<üôÓO3fŒI{»ví0dÈ|ùå—6÷7^š3^ª«­  ;w6‰=xð Å8j¬¯¯/<<<¬öY;¶öñýýýÍbï¿ÿ~›ão¨ÒÒR|°e ÀóêUè ÁÁÁèÙ³§i°§'f»ÃœÀÚ={¹¹õèÆúãBCm¯z\PPó²ævçÔü2´õ ÑÚ<Œm¹¹-{µ5vµs´ÜyÔÕ˜yÔÍQK›‡5™‡µù´´yXSß<Û}ØaYYY8qâ„ú³KEÚäç#º¸-ðO÷ÛcÏGE‘-[¶XÝþÞ{ï‰N§³çnKzzºÅeþýï‹¢(²nÝ:³}F%~~~6û-,,777yþùçMÚËËËÅÛÛ[Ô¶7ÞxCE‘œœ“Ø-[¶ˆ¢(røðaµmàÀ2hÐ ³ã >\zôè¡þœ-Š¢Èš5kLâòóóEQIMMµ9þzýü8î€àçW P󈮵WXXýý†…ÙîÉȰ¾vvýûggÛCJŠýç‘’b{΃óà<8úæ‘‘Qÿþv˜GTT”ï°ºñN´LƒÝ¿ìÙ––zÃtXX<<<°mÛ6$&&ªíƒ‡Bdd¤I|^^¼¼¼ðññÁƒ>ˆ´´4ÌŸ?_]ªáÝwßÅõë×M;v,ž}öY¬Y³F½_MDðæ›o" ƒVcLJäädddd¨K5œ;vØ>ƒo{ÿîÝŒŒúcl™2¥æ”»5·; þÓùÖæaÌAZZËžGÝ[êΣvBC[î<êjÌ<êæÀ¨¥ÍÚ†Ì#-ÍrjÇØÒ\æq»ÿ€õv™Çk¯½fvkO~>¢—/‡¾¨¨þãÝIìY½Ù:ƒUXX(“&M’»ï¾ÛžC¸%«V­’Å‹ËÔ©SEQyüñÇeñâŲxñb¹v횈ˆ¼øâ‹¢(ŠüêW¿’U«VÉ’%K$ @ÜÜÜäСC&ý)Š"Æ 3iûæ›oÄÓÓSúõë'k×®•¹sçŠ^¯—‡zÈl<Ï?ÿ¼(Š"S¦L‘·ÞzK~øaQÅìërŠ‹‹¥GÒ±cGY¾|¹¬X±B% @~üñG“Ø?þXt:ÄÄÄÈúõëeæÌ™âââ"S¦L¹ý:bA9ã_k¶Î`Ýé˜æ@„9aDš_œp¡QÍ ¬… Š¢(¢Óéô=„3gÎÔz·-((HŸN§Sç¢ÓéLV1_¹r¥ôîÝ[<<<¤uëÖ#4ëOQ‰ŽŽ6k?|ø° 2Dôz½tìØQf̘aõ»_~ùe éÓ§lݺÕâØßEèãã#­[·–1cÆÈéÓ§-ÆîÚµËä»,X`ö]„·„–c0Ìs ˆ4¿8a¥ù%ª«Ž¯Y³ÇGHHˆIŒ¢(ðòò€ðØci=„ÛvöìÙÅÍœ9S]Ë–êêj‹íC† 1YóÊEQœœŒäääzcýýý¼:þرc[ì:dDDDÍ™æÖèÑ£1zôh5_>ü‡?üA³§Òˆ¬2> Ó{ îTÌs0s0Í€""âèAÐ& ÈÏüýƒÁÑ£!""GsÂÏMÏ`mÞ¼Š¢ >>:ûÛߴߤI“´‘CizK§ÓAQܸqîîîêãÿõ±vµPNø— Ùà„Ÿ šžÁ:sæ ÀÝÝÝäg""""g¢idóg""""gаkx·¨[·nøðínÿè£Ð½!+ѵ v-°ÎŸ?’’«ÛKJJpîÜ9{ˆˆˆ¨ÉÙµÀªÏÑ£GѶm[GˆˆˆHsšX+W®D·nÝÔKÏ<ó ºwïnöòõõÅŠ+ÔEI‰nKNлwÍ»³b˜€9˜€9h4_Éý®»îBïÞ½çÎC@@:wîlSû«rŒ_«Ct[ÊÊj~‘ØúÖ÷;sÀÌÀÌA3 y5qâDLœ80lØ0Ì›7>ø Ö‡!"""j¶4/°j;xð =»'"""j–ìZ`ݼyyyy¸víšÅUÛ###›bDDDDM®Vuu5’““±fÍ”––ZŒQUUUöQ“²ë2 K–,Á+¯¼‚'Ÿ|ï¾û.`éÒ¥X·núö틾}ûâÓO?µçˆˆˆˆšœ] ¬M›6!..k×®ÅÈ‘#ýû÷ÇäÉ“qäÈ(Š‚Ï?ÿÜžC """jrv-° bbb€²ŸuwwÇ“O>‰´´4{œ…Ÿ’Róæ`æ`š»ÞƒÕ¾}{õ«rZ·n6mÚàôéÓ&1W®\±çÈYøù :zŽÅ0s0sРصÀ Gzzºústt4V®\‰ˆˆTWWãõ×_Gß¾}í9"""¢&g×K„‰‰‰(//W/ ¦¦¦¢°°‘‘‘6lŠŠŠð׿þÕžC """jrŠˆHS°°°„‹‹ † __ߦ<<5…€ ?ð÷ G†ˆˆÍ ?ìzË’¶mÛ"66<òrss±dÉ’¦‘]5yUÛ0þ|GˆˆˆHs-° ‰¯PÙà ,"Mܸœ8Qóæ`æ`šXtgÈÍî¹§æÝY1ÌÀÌÀ4,°ˆˆˆˆ4¦ùB£3fÌ€¢( ŠMOOop,QK¡yõÆohÝ%Q‹¢yU]]­u—DDDD- ïÁ""""Ò ,""""±À""""Ò˜æ÷`9Dh( tïîè‘8sÀÌÀÌA3À3Xu¤§§cúôéèÝ»7¼½½ÑµkWL˜0§N2‰û÷¿ÿ¤¤$ôïßnnnÐéŸÊ¯¾ú C‡…——üüü0kÖ,\¿~Ý,ND°lÙ2tëÖ z½}ûöŶmÛ,ö™ŸŸñãÇ£]»vðññAll,Ξ=k1öÃ?D¿~ý ×ëѵkW,\¸UUU&1›6mRçvðàAèt:|ÿý÷ž«Ýéõ@ïÞ5ïΊ9`æ`æ `UÇÒ¥KñÁ`øðáxýõב˜˜ˆ/¾øýúõÉ'Ô¸={öàí·ß†‹‹ ‚ƒƒ½žWVVbbbPVV†+V !!ëׯG\\œYìœ9sœœŒ‘#GbõêÕèÒ¥ &NœˆíÛ·›Ä•”” ::‡Âܹs±hÑ"dff"** W®\1‰Ý»w/bccáëë‹Õ«W#66©©©˜1cF£æADDDˆUTTȵk׬n¿víšTTTØsöÕW_ÉÍ›7MÚN:%žžž¯¶]ºtIÊÊÊDDdÚ´i¢(J£Ž3jÔ(ñ÷÷—ââbµmÆ ¢(ŠìÛ·Om3 âææ&3fÌ0Ù?22R¥ªªJm[ºt©(Š"GUÛòòòÄÕÕUæÌ™c²XX˜DDD˜ì?oÞ<Ñét’——§¶mܸQÛDQ9þ¼íÉùû‹5ïDDDNø¹`×3X³fÍÂàÁƒ­n2dþô§?ÙsöË_þ®®¦·¦õèÑaaaÈËËSÛî¾ûnxxxÜÒ1ŠŠŠ°ÿ~ÄÇÇÃÛÛ[mŸ4i¼½½ñþûï«m»wïFee%’’’Lú˜:u* ¾þúkµmçÎ4hú÷ﯶõìÙ111&}æää 77‰‰‰&—6“’’ "عsç-Í‹ˆˆˆjصÀúôÓOñøã[Ý>nÜ8ìݻמCЄˆàÒ¥KèСƒ&ý?~•••0`€I»››ÂÃÑ™™©¶effÂÛÛ½zõ2‰8p €šK@ͯǎ3ëÓ{úôiõþ.cÿucýüü öiTûò'¿Úˆˆˆ¨~v-°.\¸€€€«Ûýüü`0ì9MlÙ².\À„ 4鯠 @ÍüëêÔ©.\¸`Û±cG³8ã¾ÆØ+W® ¢¢ÂbŸucsü§Ÿ~Z½ñ}ذa¨ªªB—.]0K"""çe×Ë×××ä²Z]yyyhÓ¦=‡pÛòòò0mÚ4 <O=õ”&}Þ¸q,^bôôôT·c­ÅÕ>[ûøDDDÔxv]kÔ¨QX¿~=~ûÛߢ_¿~&Û222°~ýzŒ7ΞC¸-/^ÄÃ?ŒvíÚaçΚ]ÓÿüØlyy¹Ù¶²²2´jÕÊ$¶¬¬Ìb\í¾êë³1±zë---Å[¶<¯^…¾°Œž={š{zaa¶;ÌÉ,äpù2°o0{6`áÌàÆ 7×ö1BCm?Ö\PPó²ævçÔŒßÚëó¸|øûßÇ"#[‹át FØózƒÁ ;wWWWyôÑGeþüù2þ|‰ñóó“ï¿ÿÞžC¸e……….:tÜÜ\›±}Šððáâ(ŠìرÃlÛСCeÀ€êÏ âååe÷Ýw߉¢(²zõj©ªªOOO™6mšYì¼yóDQ)))‘´´4QEÒÓÓÍbdܸq ž‹E??-ò øù•Ô>K–,AçÎí9„[RVV†Gyß}÷öïßovƒùíºçž{àêêŠôôt“3xÈÊÊÂO<¡¶EDDàí·ßFnn.BCCÕö#GŽÂÃÃ:}úôAzzºÙñŽ9‚àà`xyy™ì“žžnr£û… ŸŸ¯n¿]¾íÚ!mÕ*5g°öÔw«>;vXÿK*7ˆ·½÷î@FFý1¶L™Œc}ûíΰýW-`}Ƥ¥µìyÔ±¥îúè#|ôÑG&ÛEQ §³gϪãVŠ¢`þüùj–3ˆ¯s¹ªn"""°ÿ~¼ð øãÿˆ6mÚ !!/¿ü²Ù˜þò—¿ ]»vX·n6mÚ„_üâزe‹É¥DðööÆÁƒñì³Ï"55ÕÕÕˆŽŽÆŠ+о}{“؇~ÿûß±hÑ"Ìœ9wß}7æÎÛ¬þ-ˆˆˆZ*EDD«ÎŒ«‚—••ÁÝݽÁ_€\]]­Õ¨9òó ©Ö9ûæ ÿš{ê<±ê4˜æ`æh~9pÄ炃iz«n¡Ä‰ˆˆˆœ‘]%j2Æõ\òTÌŠ9`æ`æ Ðôa]:iii˜8q¢ÅíÛ¶mÃoû[õ«Xèá„§‚‰ˆÈ'ü\pè,VDDDt'rXuíÚ5ìÛ·:tpÔˆˆˆˆìBókÑ¢EÐétpqqP³n”N§3{µk×ï¾û®ÙRDDDD-æ 8III€5kÖ`øðá 1‰Q^^^0`{ì1­‡@DDDäPšX£GÆèÑ£%%%øÃþ€ûï¿_ëÃ5[výªœM›6Ù³{"""¢fÉ®7¹¿þúë9r¤Åm"‚‡zkÖ¬±çˆˆˆˆšœ] ¬·ß~¡¡¡·)Š‚°°0¼õÖ[ö9‹œ wïšwgÅ0s0sРصÀ:}ú4¬nïÕ«¾ûî;{œEYYÍ/’²2GÄq˜æ`æ`š»Xîîî¸xñ¢Õí/^lðBµv­nî¿ÿ~lÚ´ EEEfÛ®]»†7ò C"""ºãØõ)””DFF"<<Ï<ó î¹çÀñãÇñÚk¯áÂ… زe‹=‡@DDDÔäìZ`Ýwß}øøã1eÊ<óÌ3&Ûºuë†>úƒ¶çˆˆˆˆšœ] ,>|8N:…ÌÌLœ>Ëü$s IDAT}ŒþýûCQ{žˆˆˆ¨ÉÙ½À 0 hŠÃ9T“X8yò$®]»†êêj³í‘‘‘M1 º“ùù))5ïΊ9`æ`æ PDDìÕyuu5’““±fÍ”––Z€¢ ªªÊ^C GòóÀ`pôhˆˆÈÑœðsÁ®Ë4,Y²¯¼ò ž|òI¼û¥K—bݺuèÛ·/úöí‹O?ýÔžC """jrv-°6mÚ„¸¸8¬]»VýNÂþýûcòäÉ8räEÁçŸnÏ!59»Xƒ111@ÙÏËö»»»ãÉ'ŸDZZš=‡@DDDÔäìZ`µoß%%%€Ö­[£M›6êR FW®\±çˆˆˆˆšœ]Ÿ" Gzzºústt4V®\‰ˆˆTWWãõ×_Gß¾}í9"""¢&g×3X‰‰‰(//W/ ¦¦¦¢°°‘‘‘6lŠŠŠð׿þÕžC """jrv]¦Á’ÂÂB7oÞDXXt:]£Nýꫯ0tèPxyyÁÏϳfÍÂõë×ÍâDË–-C·nÝ ×ëÑ·o_lÛ¶ÍbŸùùù?~<ÚµkÄÆÆâìÙ³c?üðCôë×z½]»vÅÂ… Í8Ø´itºšÿL<NwËO‹9 »XÏ=÷Ž?Ž÷Þ{gΜ|úé§8yò$¦Nо}ûâÂ… öB£-]º|ð†Ž×_‰‰‰øâ‹/Я_?œ8qÂâ>«V­Â?ü æ©È†ÈÊÊBLL ÊÊʰbÅ $$$`ýúõˆ‹‹3‹3g’““1räH¬^½]ºtÁĉ±}ûv“¸’’DGGãСC˜;w.-Z„ÌÌLDEE™}çãÞ½{ ___¬^½±±±HMMÅŒ34þf'4ÈήywVÌs0s0ÍØQ§Nä™gž‘Ë—/‹¢(²ÿ~u{ll¬L˜0ÁžCh´¯¾úJnÞ¼iÒvêÔ)ñôô”øøx³øK—.IÛ¶m%55UE‘¿þõ¯ :ΨQ£Äßß_Š‹‹Õ¶ 6ˆ¢(²oß>µÍ`0ˆ›››Ì˜1ÃdÿÈÈH ”ªª*µméÒ¥¢(Š=zTmËËËWWW™3gŽÉþaaaÿ¯½;«ªÌÿþ9{ᢀl®à¸âž& j¸¤ŽËLæÒ‚¹kŽÆ/m,Ç(—FSÓF›Ô sJÌÌ%­u$Å ÄŒ”Å…1dûþþ@N^.«Y?ï×ë¾®÷9ßóœçù‚ðåœsŸ+:u2ÙÁ‚¢Óé$&&FmÛ¸q£(Š"""‡EQ$>>¾ôÉyxˆÏDDDuð÷Âc=ƒuçδmÛ`4œe)4`À|óÍ7sÖ³gOXZšÞšæíí ÄÄĘ҆†¢M›6xî¹çÊ}ŒÔÔTù+W®¬PçÏŸGnn.ºtébÒnee…Ž;"22Rm‹ŒŒ„ÑhD›6mLb»ví j>óóóqîÜ9³> ccccÕû» û/ëææOOO“¯`zÙ³&|½ˆˆˆªÚc-°úôéƒýû÷«¯ÇŒƒ¥K—bñâÅX´hV¬XÀÀÀÇ9M„‡‡#)) £GVÛDÓ§Oǘ1cн{÷ õ—œœ    )ÊÕÕÕä¾´ääd4jÔÈ,®pßÂØÛ·o#;;»Ø>‹ÆVäø&LPo|@^^?Úˆˆˆ¨ u™†W_}DVVôz=.\ˆ¨¨(uY†>}ú`õêÕs¿YLL ¦NŠ'Ÿ|ãÇWÛ7mÚ„ .`çÎî333`mmm¶M¯×«Û cKŠ{¸¯²ú¬Hì×q‰ˆˆ¨âkÕ¾}{´oß^}Ý AaÂQ¥ÔÇÙ³gKìÿÎ;bee%óæÍ3i¿ÿ¾Fy饗Զ>ø@E‘èèh“ØððpQEŽ=ª¶uíÚUºuëfv¼þýû‹···úúÂ… ¢(Ь]»Ö$.11QE‘Å‹—8öryðvÜk€àÁc!PðÝ’>>e÷ëãSzþþ"II%ïáBéû1¥Y¸ðñÏcáÂÒ÷ç<8΃ó(kII?+yþþþRøs€ø¯CË4(""ZlçÏŸGÇŽñþûïcÚ´i€””¸¸¸˜ÅZXXàôéÓh×®–CøMòòò0bÄìÛ·»wïFpp°YLdd¤º°h¡7n`Ò¤I˜8q"† †€€õhLL lmmѸqc5~РA8{ö,.]º¤.Õð÷¿ÿ/¿ü2öíÛ‡(X™½E‹ QïWøûû#..ñññê¥Ë¥K—"44êR —.]BÛ¶m1wî\„……©Ç÷ññµµ5N:¥.ÕðÆo ,, ÑÑÑæg˜*ÂÓHLD†£#þù`Ìý ÖÅ‹ÀرÀ©S€Ÿ_ñ15ô/B3%Í£0Ÿ~ ŒQsçñ°Š~=ÎÁOÔÜyU‘yÍA¡š6’”g;wŸƒB5e¿åëqú4йsÉ9*÷ Ö²e0¤¦Àƒ+>µžÖÛÔ©S¥yóæ’››«¶.2.W®\‘+W®Èÿû_iܸ±L™2Eë!ü&3gÎEQdèС²e˳GI®\¹RâB£Š¢H@@€IÛéÓ§E¯×‹ŸŸŸ¬[·NæÏŸ/ƒA‚ƒƒÍöŸ7ož(Š"“&M’ 6ÈàÁƒEQùì³ÏLâÒÒÒÄÛÛ[5j$Ë–-“+VHãÆÅÓÓSRRRLb÷ìÙ#:N‚‚‚dýúõ2cÆ ±°°I“&U$]Å«ŠåN*8æ©S•wÌê†9`D˜æ@¤úå .4ªù=X‡ƈ#`aaa¶ÍÕÕÍš5S_ÿñÄ—_~©õ~“³gÏBQ|ùå—fcScÇŽ}¤~‹®Õ©S'‹ÐËË ûÛß|8rjj*ìììàààð¸IDDDT-Tʇ=ÛÛÛ«CDDDTÛi~“;Q]Ç‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°¨vˆŽ|} žë*æ€9˜€9˜ƒj€ÕYY?H²²ªz$U‡9`æ`æ `EDDD¤1XDDDDcEDDD¤1XDDDDcEDDD¤1XDDDDcEµƒ›°paÁs]Å0s0sP (""U=ªe<=ÄDÀÃHH¨êÑQU«ƒ¿x‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹j‡ÌL *ªà¹®b˜€9˜€9¨X`Qípñ"жmÁs]Å0s0sP °À""""Ò ,""""±À""""Ò ,""""±À""""Ò ¬""""0mÚ4øúúÂh4¢iÓ¦=z4._¾l§ÓéJ| 0 \Ç:vìz÷î [[[¸¹¹aæÌ™¸wïžYœˆ`éÒ¥hÞ¼9 :tè€mÛ¶Ûgbb"FGGG888`øðá¸råJ±±ÿú׿àççƒÁ€¦M›âÍ7ßD^^žI̦M› Ó|›9r:W¯^-×üˆˆˆê*˪@u³dÉ?~#GŽDûö표œŒ5kÖÀÏÏ'Nœ€¯¯/àÓO?5Û7""ï¿ÿ>ž~úé2sæÌÁ××+V¬Àµk×°|ùr\¾|{÷î5‰}ýõ×±dÉ„„„ k׮صkþøÇ?BQŒ=ZKOOG`` ÒÒÒ0þ|XZZbÅŠð÷÷Ç™3gРA5ö믿ÆðáÃÑ·o_¬Y³çÎÃâÅ‹qóæM¬]»öQÓGDDD dâØ±c’““cÒvùòeÑëõ2vìØR÷}ñÅE§ÓIbbb™Ç8p xxxHZZšÚöÑG‰¢(²ÿ~µ-!!A¬¬¬dúôé&û÷éÓG7n,yyyjÛ’%KDQùñÇÕ¶˜˜±´´”×_ÝdéÔ©“Éþ ,N'111jÛÆEQ9|ø°(Š"ñññ¥OÎÃC(x®,".<×UÌs ˆ0"Õ/Uñ{¡Šña={ö„¥¥é‰=oooøøø &&¦Äýîß¿;v îîî¥#55ÄØ±ca4ÕöqãÆÁh4âóÏ?WÛvïÞÜÜ\L™2Ťɓ'#!!ÇWÛ¶oߎnݺ¡sçÎj[ëÖ­dÒgtt4.^¼ˆõòL™2"‚íÛ·—:þjÉ`|} žë*æ€9˜€9˜ƒj€V9ˆnܸ''§cöîÝ‹»wïâ¹çž+³¿óçÏ#77]ºt1i·²²BÇŽ©¶EFFÂh4¢M›6&±]»vPp©òóóqîÜ9³> ccccÕû» û/ëææOOOµÏBŠ¢ûo"""* ¬rGRR’ÉýNÅÅèõzüþ÷¿/³¿äädMQ®®®HJJ2‰mÔ¨‘Y\á¾…±·oßFvvv±}­Èñ'L˜ Þø€¼¼<4iÒ¤Ì9Õe,°Êƒ©S§âÉ'ŸÄøñã‹IMMÅW_}…AƒÁÞÞ¾Ì>3|ø¦µµµÙ6½^¯n/Œ-)îá¾Êê³"±™üpP""¢ß„V)®_¿ŽÁƒÃÑÑÛ·o/ñòØŽ;pÿþýr]Ãkâ÷ïß7Û–••“ج¬¬bã>+kà5{""¢ß„Ë4”àîÝ»8p RSSñÃ?ÀÕյĨððpÔ¯_C† )Wß…—æ /Õ=,99Ùä&y7779r¤Ø8jlƒ `mm]bŸÇ>||³Ø=z”keÉÈÈÀ?ÃÃú_~á΀——Z·nm¬×>>¥w SlªÜÜ %ÉÌ,û“åŸx¢ô›B““ %á<~ÅyüŠó(Àyüª–ÎãÌ™3ˆŠŠR_[dgÃ>1ii¨sºWõÛ«£ÌÌLyê©§Äh4ʉ'JMJJN'/½ôR¹û¿sçŽXYYɼyóLÚïß¿/F£Ñ¤¯>ø@E‘èèh“ØððpQEŽ=ª¶uíÚUºuëfv¼þýû‹···úúÂ… ¢(Ь]»Ö$.11QE‘Å‹—{.ÅzðvÜk€àÁc!PðÝ’>>e÷ëãSz –¾ÿ… ¥ïÄ”fáB΃óà<8Σ„yøûûKáÏ}âS4¾-Ó ˆˆTi…WÍäååaĈØ·ovïÞàààRãW¬X9sæàÛo¿E@@@±1111°µµEãÆÕ¶AƒáìÙ³¸té’ºTÃßÿþw¼üòËØ·oŸº|bb"Z´h¬^½ "ð÷÷G\\âããÕK—K—.Ehh("""Ô¥.]º„¶mÛbîܹ Sïããkkkœ:uJ]ªá7Þ@XX¢££ÍÏ0U„§'˜ˆ GGüóÁ˜û¬[·€ýû?ý©ä¿ kè_„fJšÇ­[ÀÎÀˆ@Ÿ>5w«è×ãá8;×ÜyU‘yÍA¡š6’”gß_| Õ”yü–¯Gr2°|90`@ñ9*÷ Ö²e0¤¦@BBéǬ-ª¸À«vfΜ)Š¢ÈСCeË–-f¢:wî,žžž¥ö©(Š˜´>}Zôz½øùùɺuëdþüùb0$88Ølÿy󿉢(2iÒ$Ù°aƒ ûÌ$.--M¼½½¥Q£F²lÙ2Y±b…4nÜX<==%%%Å$vÏž=¢Óé$((HÖ¯_/3fÌ ™4iRySU²ªXPîÔ©‚cž:UyǬn˜æ@„9aDª_êàB£,°ŠN'Š¢˜=t:IlLLŒ(Š"úÓŸJíSQ 4k?zô¨ôêÕK ƒ4jÔH¦OŸ.éééfqùùùòÎ;ïH³fÍÄÚÚZÚµk'[·n-öX 2räHqpp;;;:t¨ÄÆÆ»k×.éÔ©“èõziÒ¤‰üùÏ–ÜÜÜRçR.,°ªsÀˆ0"ÌHõËA,°x“{‡.wlëÖ­‘ŸŸ_f\I1½zõÂÑ£GËÜ_Q„††"44´ÌX“UÛK3lØ0 6¬\±DDDT~\¦ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹j‡Âõ\|îbÄ0s0sP p¡QÒÞƒ…FëÔ‚rDDT²:ø{g°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹j‡èhÀ׷๮b˜€9˜€9¨X`Qí•Uðƒ$+«ªGRu˜æ`æ`ªXDDDDcEDDD¤1XDDDDcEDDD¤1XDDDDcEDDD¤1XT;¸¹ <×UÌs0s0Õ€""RÕƒ ZÆÓHL<<€„„ª Uµ:ø{g°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹ˆˆˆHc,°¨vÈÌ¢¢ žë*æ€9˜€9˜ƒj€Õ/mÛ<×UÌs0s0Õ ,""""±À""""Ò ,""""±À""""Ò ¬"¢¢¢0räHxyyÁÖÖ 6Ä“O>‰ððp³Ø‹/"88vvvhذ!Ƈ”””rëØ±cèÝ»7lmmáææ†™3gâÞ½{fq"‚¥K—¢yóæ0 èС¶mÛVlŸ‰‰‰5jáàà€áÇãÊ•+ÅÆþë_ÿ‚ŸŸ š6mŠ7ß|yyy&1›6m‚NWðmräÈèt:\½zµÜs$""ª‹,«zÕÍÕ«W‘žžŽ &ÀÝÝؾ};žþyÄÅÅaþüù€„„ôéÓŽŽŽxçw––†åË—ãüùó8yò$¬¬¬J=Ι3g___¬X±×®]ÃòåËqùòeìÝ»×$öõ×_Ç’%K‚®]»b×®]øãÿEQ0zôh5.==HKKÃüùóaii‰+VÀßßgΜAƒ ÔØ¯¿þÇGß¾}±fÍœ;w‹/ÆÍ›7±víZ 3JDDT •)//O:vì(Mš4QÛ&Ož,¶¶¶ríÚ5µíàÁƒ¢(Ь_¿¾Ì>(’––¦¶}ôÑG¢(Šìß¿_mKHH+++™>}ºÉþ}úô‘ÆK^^žÚ¶dÉQE~üñGµ-&&F,--åõ×_7ÙßÇÇG:uêd²ÿ‚ D§ÓILLŒÚ¶qãFQEDD>,Š¢H|||é“óð ž+Ë©SÇnÜ8F“ýwïÞÜÜ\L™2Ťɓ'#!!ÇWÛ¶oߎnݺ¡sçÎj[ëÖ­dÒgtt4.^¼ˆõòL™2"‚íÛ·—'-ÕËO.<×UÌs0s0Õ ¬ddd %%±±±X±b¾ùæÌ›7@Á}N·nÝB—.]ÌöëÚµ+"##KíûüùóÈÍÍ5ÛßÊÊ ;v4Ù?22F£mÚ´1;Pp©òóóqîܹÇ«ÞßUØÑX777xzzª}R¥ØW+àë[ð\W1ÌÀÌÀT,°JðꫯÂÅÅ-[¶Äk¯½†U«V!$$œœ    )ÊÍÍ ·oßFNNN‰}—¶¿««+’’’Lb5jTìq¨±·oßFvvv‰cz8¶"ÇŸ0a‚zã{@@òòòФI“çFDDD¼É½D³gÏÆ¨Q£””„ððpL›6 ƒãÇGæƒÏv²¶¶6ÛO¯×233K¼Ñ½¬ý3úì¨ÌÌÌ2Sž>+›žž^츉ˆˆ¨|X`• uëÖhݺ5`ìØ±xúé§1kÖ,Œ=†§\ïß¿o¶_VV¨1Å)k“ØÂ>K;NEÆTVlic'""¢²±À*§gŸ}@LLŒzi­ðRÛÃ’““ѰaÃR—i(kwww“Ø#GŽ@mР¬­­KìóáØ‡ïááaÛ£GÇ^øçƒõÃô¿üÃ;///µxUéõ€OéFGÅ›*7·‚GI23ËþàÓ'ž(ýž…ää‚GI8_q¿â< p¿ª¥ó8sæ ¢¢¢Ô×ÙÙ°OLD`ZêÜŸîUý6ÆšbåÊ•¢(Šœ={VDD\\\dÔ¨Qfq­Zµ’~ýú•Ú×;wÄÊÊJæÍ›gÒ~ÿþ}1òÒK/©m|ð(Š"ÑÑÑ&±ááá¢(Š=zTmëÚµ«tëÖÍìxýû÷oooõõ… DQY»v­I\bb¢(Š"‹/.uüezðvÜk€àÁc!PðÝ’>>e÷ëãSz –¾ÿ… ¥ïÄ”fáB΃óà<8Σ„yøûûKáÏ}âS4¾-Ó ˆˆTi…WÍܺu ÎÎÎ&m999èÑ£®^½ŠëׯÃÂÂS¦LÁæÍ›qéÒ%u©†C‡¡ÿþøðÃÕâ &&¶¶¶hܸ±Ú6hÐ œ={—.]R—jøûßÿŽ—_~ûöíÀ¼c±E‹ ÁêÕ«"ÄÅÅ!>>^}gßÒ¥KŠˆˆu©†K—.¡mÛ¶˜;w.ÂÂÂÔãûøøÀÚÚ§NR—jxã7†èèhó3Láé $&"ÃÑÿ|0fžÁzçQ€óøçñ+Σ@ G‰g°–-ƒ!5ððJ?fmQÅ^µ3|øp ’;H • IDAT·ÞzK6lØ ùË_¤M›6¢ÓédóæÍjܵk×ÄÉÉI¼½½eõêÕ&ŽŽŽÒ¡CÉÎÎ6éSQ 0i;}ú´èõzñóó“uëÖÉüùóÅ`0Hpp°Ù˜æÍ›'Š¢È¤I“dÆ 2xð`QE>ûì3“¸´´4ñöö–FɲeËdÅŠÒ¸qcñôô”””“Ø={öˆN§“   Y¿~½Ì˜1C,,,dÒ¤I¿5…U³ \RRÁ_RII•wÌê†9`D˜æ@¤úå .4Ê«ˆmÛ¶IÿþýÅÕÕU¬¬¬¤aÆ2hÐ 9xð YlTT”<ýôÓbkk+ 4çŸ^nÞ¼i§(Ššµ=zTzõê%ƒA5j$Ó§O—ôôt³¸üü|yçw¤Y³fbmm-íÚµ“­[·;þ„„9r¤888ˆ :Tbcc‹Ýµk—têÔIôz½4iÒDþüç?KnnnY)*Wr¯Ìs ˆ0"Õ/u°ÀâMîEŒ=ÚäóýJãããƒ}ûö•—ŸŸ_l{¯^½pôèÑ2÷W¡¡¡ -3ÖÃã̕ä 6 Æ +W,•%"""Ò ,""""±À""""Ò ,""""±À""""Ò ,ª Ì{ðÁÖusÀÌÀÌA5À•ÜI{Vr¯S+öQÉêàïžÁ""""Ò ,""""±À""""Ò ,""""±À""""Ò ,""""±À""""Ò ,ª¢£_߂纊9`æ`æ `EµCVVÁ’¬¬ªIÕa˜€9˜€9¨X`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`Qíàæ,\Xð\W1ÌÀÌÀTŠˆHU‚jOO 1ððªz4DDTÕêàïžÁ""""Ò ,""""±À¢ZáÌ™3À™3gªz(U†9`æ`æ :`EµBTT¾ûî;DEEUõPª sÀÌÀÌAuÀ‹ˆˆˆHc,°ˆˆˆˆ4Æ‹j‹ìlø>>8}ú´É¶ˆˆL›6 ¾¾¾0hÚ´)FË—/{Ì5kÖà‰'ž€^¯‡§§'æÌ™ƒŒŒ “˜¸¸8èt:|ÿý÷jÛ¦M› ÓéŠ}ܼyÓì8ÙÙÙ C›6m`0àêêŠ!C† ñ¡•‘9N‡«W¯{Ìߢ°ïâ'Ožˆ6mÚ„¡C‡¢I“&0h×®Þ~ûmÜ¿¿Ôœèt:|òÉ'šŒµ²¼ýöÛÐéth×®I»ˆàÃ?„ŸŸàää„€€ìÝ»×$®6çàa999ðññN§Ã{ï½g²­¶çàâÅ‹†6lˆqãÆ!%%Å$¦&æ ** #GŽ„——lmmѰaC<ùä“7‹ÍÏÏǺuëбcGØØØÀÉÉ AAA8wîœSsPÓp,úM&L˜€;v`öìÙhÙ²%6n܈AƒáðáÃèÕ«`ûöíXµj,X€¨¨( 6 ?ýô `É’%8~ü8FމöíÛ#99kÖ¬ŸŸNœ8___õx¯½ö–-[†‘#GböìÙˆŠŠÂêÕ«…}ûö•kÌùË_мys“6“×999pttÄ;#´´4,_¾çÏŸÇÉ“'aeeUE£þí®^½ŠôôtL˜0îîîÈÈÈÀöíÛñüóÏ#..óçÏWc_xálݺãÇÇŒ3žžŽ3gÎàÖ­[U8ƒ:HˆÑþóQEÞ{ï=µ-++K¼½½åÉ'ŸTÛÆŒ#ëׯW_÷ìÙS8 ¾>vì˜äää˜ô}ùòeÑëõ2vìXµ-))I,--eüøñ&±kÖ¬EQäË/¿TÛ®\¹"Š¢Èwß}§¶mܸQE‘S§N•9·%K–H½zõ$""¢Ô¸Ã‡‹¢(_ì1‹Â¾wìØQbLvv¶?~ܬ}Ñ¢E¢(ŠEQdóæÍšŒµ2Œ=Zúõë'Ò¶m[“mîîîÒ½{w“¶ÔÔT±³³“aÆ©mµ9…nܸ!õë×—Å‹›ýÿ©Ý9˜>>ˆ‰‰QÛŽ?޼¼<Œ3Æ$¶ðõ¶mÛÊ5nAZZòJø¸†üü|¼ÿþû1bºté‚ÜÜ\³K•©p¼¹¹¹fÛ¬¬¬Ð£G³öáÇ€Iþj²ï¿ÿ;vìÀÊ•+!"fg. ƒÉ÷ØÙÙÁÖÖ666•9ÔǦ¬ E›6mðÜsÏUò¿²r°cÇ 2žžžj[PPZµj…Ï?ÿ¼²‡ûØét:xzzšœ™ûë_ÿŠîÝ»cذaÈÏÏ7ùYK•‹=²ÈÈH´jÕ F£Ñ¤½ðrÖ™3gPaaaˆ‰‰ÁÎ;qèÐ!³K^E‰nܸ'''µ­ðž¢ÂK‹… _½·«¤_@ppp€­­-† †ŸþÙd{tt4’““Ñ®];„„„ÀÖÖF£:tÀ‘#GÌú{ø8ãrÌĉáààƒÁ€¾}ûâÔ©Seîsýúu0Éßãßã–——‡éÓ§ãå—_6¹\ü°ÐÐP|óÍ7X³f ââ⃩S§"-- 3gÎ4‰­­9€“'Oâ“O>ÁÊ•+Kí¯6æ 11·nÝB—.]̶uíÚ‘‘‘&m51@Á¬)))ˆÅŠ+ðÍ7ß`Þ¼y€ÔÔTDDD K—.xýõ×áàà;;;xyyá‹/¾0ë«¦æ Æ¨ÊÓgT³ùúúJ¿~ýÌÚ£¢¢LNɧ§§KÏž=EQ±°°5kÖ”Ù÷–-[DQÙ¸q£ÚvúôiQE/^l»oß>QEìííKíóóÏ?—^xA¶lÙ"»wï–7ÞxClmmÅÙÙÙä’ÂÎ;EQqrr’Ö­[ËæÍ›eÓ¦MÒªU+±¶¶–sçΕ9~-;vLFŽ)7n”/¿üRÞ}÷]qrrƒÁ ‘‘‘¥îÛ¯_?©_¿¾Ü½{·RÆú8­Y³Fêׯ/)))""âïï/íÚµ3‹ûøãÅÊÊJEEQÄÙÙYNœ8QÙÃ},Ê“ƒüü|éÖ­›<÷Üs"òë% ¢—kª²r!Š¢È§Ÿ~j¶ïܹsEQÉÎή´ñ>.“&MR¿Ç­¬¬dݺuê¶ÂŸ‘NNNâææ&~ø¡lݺUºwï.:NöíÛW…#¯{X`Ñ#kÑ¢… <ج=66VE‘÷ß_mËËË“³gÏJRRR™ý^¼xQìíí¥W¯^’ŸŸo²­Gbgg'7n”+W®ÈÞ½{¥iÓ¦R¯^=±²²ªðŽ=*:N^yåµí“O>EQD¯×KBB‚Ú~õêU©W¯žÉ}a•íçŸ .1æí·ßEQäÃ?¬Ä‘=)))Ò Aùë_ÿª¶W\|þùçbii)øÃdÇŽ²qãFiß¾½¸¹¹ÉÏ?ÿ\ÙÃÖTysðñÇ‹ú=[› ¬òäàûï¿EQä‹/¾0Ûÿ7ÞEQjÅ111rèÐ!Ù²e‹‹………lÚ´ID~ÍN§““'Oªû¤§§‹³³³ôîÝ»ª†]'±À¢GVÞ3X‘œœ,-Z´¦M›Jrr²ÙöÄÄDéÝ»·úœ¥¥¥¼öÚkÒ½{wqtt|¤yôìÙS¼½½Õ×_|ñ…(Š"AAAf±}ûö•-Z<Òq´ò‡?üA¬­­ÍŠO‘mÛ¶‰N§“—_~¹ F¦½W^yEZµjeò&ˆ¢¿X333ÅÉÉI†j²ïíÛ·¥aÆ2zôèJïãPžܽ{W5j$o¾ù¦ÚV› ¬òä ®œÁ*jÀ€R¿~}ÉÈÈPsàååe7qâD©W¯žäååUÁ(ë&.Ó@ÌÍÍ IIIfíÉÉÉww÷ õw÷î] 8©©©øá‡àêêjãîîŽ~ø±±±¸~ý:Z¶l ¸»»£U«V4OOOüôÓO&Ç€F™Å:;;«÷–UOOOdggãÞ½{&÷¿8pãÆÃ!Cðá‡Váµqùòelذ+W®DBB‚Úž••…ììlÄÇÇÃÞÞñññøßÿþ‡¡C‡šìïèèˆ^½záßÿþwe]3åÉV®\‰œœŒ5 qqq Æß¾}qqqððð¨‘Ë”÷ûÀÍÍ À¯?–œœŒ† ÖÈù—åÙgŸÅpéÒ¥Rv¹¸¸ ''÷î݃]e³nªê j®¹s犥¥¥¤¦¦š´^¢zøòZY233å©§ž£ÑXáûf Ϙ͟?¿Bûêܹ³´iÓF}šš*õêճاžzJZ·nýHÇÑʳÏ>+666&m'Nœ[[[éÝ»·deeUÑÈ´U¸LEiÙ³g«µÿío3ëcàÀâææV£×Fyr0kÖ,™0aB™qgÏž­êé<’ò~ˆˆ¸¸¸È¨Q£ÌúhÕªU±gÛkƒ•+Wš|}]]]¥iÓ¦fqÏ?ÿ¼ÙÏ z¼X`Ñ#+\kùòåj[á:X={ö,w?¹¹¹2tèP©W¯ž|ýõ×C^^ž )XËÆÆ¦Øu°Š+Àk’â~dgg‹ŸŸŸ899Inn®ˆˆÌš5KE1YkðÖ­[boo/C† ©´ñ’ˆ""RÕgѨæ=z4þùÏböìÙðòòÂæÍ›ñã?âСCèÝ»w¹ú˜5kV­Z…gžy#GŽ4Û>vìXõß3gÎÄýû÷Ñ¡Cäää`ëÖ­øñDZyóæ2×ýiÙ²%üüüйsg888àôéÓøøãááለ“u”.^¼ˆîÝ»ÃÎÎ3fÌ€ˆ`ÕªUÈÏÏGdd¤z9âqêÛ·/lllгgO¸¸¸ ::ëׯ‡µµ5Ž?ŽÖ­[#-- ¾¾¾HJJBXX˜ÙeYooïb×ɪÉð¿ÿýçÏŸWÛ^ýu¼ûî» Äï~÷;¤¥¥aíÚµ¸qã¾ýöÛr/ÖÅå ¨¸¸8´hÑË—/Ç«¯¾Z‰£«Åå !!:uBýúõ1sæL¤¥¥aÙ²ehÒ¤ """jô%ÂÂïë>}úÀÝÝׯ_Gxx8~úé'lܸãÆܼy:uBzz:^}õUØÛÛãÃ?Dbb"Ž?^êG,‘ƪ¸À£.++KæÎ+nnn¢×ë¥{÷î²ÿþ õ :®ØSÿ:Î$vÓ¦MÒ±cG1boo/ýû÷—#GŽ”ë8 ,N:Iýúõ¥^½zÒ¬Y3™:uj±Š¼å¹ÿþê±~÷»ßUê;ÒV­Z%Ý»w—† Š•••xxxȸqã$66V)¼‘¹¤üMœ8±ÒÆ[YŠ]¦áý÷ß___±¶¶;;; *÷÷FMSRV›nr/NI9ˆŠŠ’§Ÿ~Zlmm¥AƒòüóÏ—ø¼&Ù¶m›ôïß_\]]ÅÊÊJ6l(ƒ 2ù´†BÿýïeĈâàà 666Ò¯_?ùñÇ«`ÔuÏ`iŒ+¹iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒU›6m‚N§ÃÕ«W+ýØ:o½õV¥·*4kÖ 'N¬”cUå×”¨*±À"¢GråÊL›6 ­Zµ‚­­-lmmáëë‹iÓ¦áüùóU=¼bíÝ»·Ô"JQMŽ£Óé0}útMúzE1™ktt4Þ|óMÄÇÇWᨈj˪Õ<{öìÁèÑ£Q¯^=<÷ÜsèСt:.^¼ˆ;wbݺuˆ‹‹CãÆ«z¨&öîÝ‹µk×báÂ…fÛ²²²`aa¡Ù±´*Ö‡Ÿ~úɬÀZ´húö틦M›VáȈjXDT!±±±3f š7oŽC‡¡Q£F&Û—,Y‚uëÖUÛ£¤qÕ«W¯’GRu¬¬¬Šm‘J QíÅK„DT!K—.EFF6nÜhV\€……¦M›OOOµíܹs˜0aZ´hƒÁ777¼øâ‹¸}ûv™ÇÛ½{7 èõzx{{cñâÅÈÏÏ7‹ýÏþƒAƒ¡Aƒ0èСV­Z˜0aÖ®] N§S…Š»+11/¾ø"ÜÝÝ¡×ëÑ¢E L™2999åÎWIîÝ»‡9sæ qãÆÐëõhÓ¦ Þ{ï=³¸ÂË»víBÛ¶m¡×ëѶm[|óÍ7f±GŽA—.]`0àííõë×ãÍ7ß4™'`zÖ¦M›0jÔ(@`` š—ï¿ÿ¾Ä¼í£PTTúöí 4nÜo¿ýv±_'øúë¯ñÔSOÁh4ÂÞÞC† Attt92GT3ð UÈž={вeKtíÚµÜûýôÓbõðÙ­¤¤$tëÖ ©©© A›6m€;v 33³Ä³@å!":t(Ž9‚—^z ;vľ}û0wî\$&&â¯ý«IüÑ£G±sçNL:F£«V­Â³Ï>‹«W¯¢Aƒ€ÈÈHÃÃË-Bnn.-Zggg³³v߃åïï3f`ÕªU˜?>žxâ PŸ‹æ¥¸>àúõë D~~>þïÿþ666X¿~=ôz½Ù¾[¶lÁ„ Œ¥K—âÞ½{X·nz÷îÈÈH^¦¤ÚAˆˆÊéîÝ»¢(ŠŒ1ÂlÛ/¿ü"·nÝR™™™ê¶‡ÿ]hÛ¶m¢(ŠüðÃjÛÆEQ‰/ußW^yElmmåþýû""’››+Í›7—æÍ›ËÝ»wKÿÔ©SEQ”b·)Š"o½õ–úzܸqbii)§N*±¿’(Š"Ó§O/qû®]»DQ 3i9r¤èt:‰5éK¯×Ëÿû_µíܹs¢(ЬY³Fm{æ™gÄh4Jrr²ÚöóÏ?‹¥¥¥èt:“ã4kÖL&Nœ¨¾þâ‹/DQùî»ïŠËÃy)©Y³f‰¢(¡¶ÝºuKD§Ó©_Ó´´4©_¿¾Lš4ɤ¿7nHýúõ%$$ÄìXD5/Q¹¥¦¦ŒF£Ù¶€€¸¸¸¨>ø@ÝöðYŒ¬¬,¤¤¤ {÷î μ”æá}ÓÒÒ’’‚Þ½{###—.]Rûˆ‹‹Ã¬Y³`ooÿè| ??»víÂ3Ï<??¿ßÜ_Q{÷î…¥¥%f̘aÒ>gΈ¾þúk“ö~ýú¡yóæêëvíÚÁÞÞW®\äååáàÁƒ>|8\]]Õ8/// 8PóñgïÞ½èÙ³'ºt颶999aìØ±&÷v8pwïÞŘ1c’’¢>t:ºuë†Ã‡WÊx‰7^"$¢r³³³¤§§›m[¿~=ÒÓÓqýúuŒ;ÖäòÑíÛ·ñÖ[oaÛ¶m¸uë–É~wïÞ-õ˜QQQX°`>¬xE÷´mÛ¶â“*Æ­[·––¦YEÅÇÇÃÝݶ¶¶&ímÚ´³5£š4ibÖ‡££#~ùåÀÍ›7‘••ooo³8ooïJ¹y=>>={ö4koÕª•ÉëË—/úöí[l?Úލ °À"¢rspp€››.\¸`¶­[·n€¸¸8³m£FÂñãÇ1oÞ}ú`éÒ¥ÈÉÉ»»;öïß_ì¥Ä¢zõêGGGŒ?^½!|Ë–-fqŠ¢`ݺuxæ™gбcGLœ8®®®ˆ‰‰Att4öíÛê Ø3fÌÀ€`aa1cÆ{ì°°0ìß¿þþþê2 ÉÉÉØ¾};þýï—y3}DD/^lÖˆgžy˜?>âââо}{ìß¿ÿú׿0{öl“ÚKR´}óÍ7±ÿ~ôêÕ “'OFnn.>øà´mÛçÎ+ußN:ÁÂÂK–,Á;w`mm   8;;㥗^Â+¯¼‚ßÿþ÷èׯΞ=‹ýû÷ÃÉÉɤŸyóæaË–-ÆÌ™3accƒ 6 Y³f&Ç·³³ÃºuëðüóÏÃÏÏcÆŒ““®^½Š¯¾ú ½{÷ÆêÕ«Ëœ?QµWEï^$¢.66V¦L™"-[¶ƒÁ 666âãã#S¦L‘sçΙÄ&&&ʈ#ÄÑÑQêׯ/£G–ääd³%6nÜhò–~‘cÇŽIÏž=ÅÆÆF<==%44Töïß/:ÎlYÿûß2`À±··£Ñ(;v”>ø@Ýž——'3fÌÑét&Ë·ÁÕ«Weüøñâââ"z½^¼½½eúôé’]jnEN'Š¢˜]&ADäÛo¿???±¶¶oooÙ°aƒüéOƒÁPæ¾}ô‘xyy©Ë:æ6??_BCCÅÙÙYlmmeàÀçÏŸ—€€1 Ò¸qcyûí·åã?6ûšŠˆ9rD‚ƒƒ¥~ýúb0¤eË–ò /ÈéÓ§KÍ-QM¡ˆð³ˆˆj«áÇãâÅ‹f÷BÑãÅ{°ˆˆj‰ÌÌL“×—/_ÆÞ½{P5"ªÃx‹ˆ¨–pssÃĉѼysÄÇÇcݺuÈÉÉAdd¤úî="ª¼Éˆ¨–8p >ûì3\¿~ÖÖÖxòÉ'ÆâЍ ð ‘Æx‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`Ù8R}RIDATiŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iŒ‘ÆX`iìÿ©à ây©>IEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/rcparams.png0000644000077000000240000003642712436367710023243 0ustar tomstaff00000000000000‰PNG  IHDRXX¾f˜ÜsBIT|dˆ pHYsaa¨?§i IDATxœíÝlT÷ïÿ×lŒab 7?´€Ú VÄ„Ò4"½R6s…ÐlH“j7©ª(ùö’U¾Z‰HùfÕîUX)¥a•”B‹V·M6 iªåæJë 2fÛ$6ñE´Pbã߯x>ß?N 9 æ=ûœçC²Nûa<~Ÿ×ŒíWŽÏÌñœsN0“Šz€¸¡`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`£`+Šz€+©»»[û÷ï×u×]§ÒÒÒ¨Ç$ÔÈȈŽ;¦;î¸CuuuQƒðœs.ê!®”Ý ÚxøpÔc IúùÏ®ûï¿?ê1P‰:‚uݧåêç’¾œNG;LÜt“äœäyÒ{ïE=ÍôGž¶ÈÓyšú裴qãF]wÝuQ‚ITÁ*õ<É9ýU¨¡¡!êq¦½~ÍV³VêfÔlòÌyÚ"O[äYœ®_‰<É}\ÅQ c*Q«iL%Q äi‹.a‹Uk¯Ö«OÕQ äi‹ÈÓyÚ"O œDÁ($ €±D¬‰‰¨'ˆ‡‰ ÿäiƒÈÓyÚ"O œDÁ($ €±D¬ÁÁ¨'ˆ‡þ~iÿ~.=d…ÈÓyÚ"O œDÁ($ €1 €±D¬®®¨'ˆ‡LFzúi‹ü‘§-ò´Ež@8‰,XQOUURc#—²Bž¶ÈÓyá$òU„¥¥QOeeRCCÔSÄyÚ"O[ä „“È#X…DÁ0–È‚5<õñ08(57sé!+äi‹¹äçþô§?U*•ºàGggç¤gÈgpV_Ÿ´w¯¿EþÈÓyÚ"O œ+~’û~ô#577kýúõúêW¿ªL&£mÛ¶©¡¡Aï¾û®–.]zÉûxæ™gtýõ×Öªªª&=Cmmè±qW]å_:£¸8êIâœsÐÄÄD!FÈË”8–ãœSGG‡êêê&uûÛo¿]UUU*//׺uëÔÚÚZà &oJ¬Ý»w«­­M6l¸èíÊËËõÝï~W/¼ð‚^yå=ùä“úÝï~§U«Véĉ“þz½½ùN Iêî–^zÉß"äi‹xÑÛ®_¿^ëׯ?÷ÿuÇwè¶ÛnÓ³Ï>«ÿøÇ“úšE‘ïu<Ióæ‘§ò´Ež¶È'Òo•öövÝu×]ª©©QSS“<Ï }·Ür‹V®\©·ß~{ÒŸSYúËફ¥ÆÆ¨§ˆò´Ež¶È'²?ž:uJkÖ¬Q¿Þ|óMÕ××_ö}]}õÕê ñw¿žåß’fÌ|´§h05;°6œªP&µ0ç¶]©«ÔŸª¬¥J•I-ÔDª8°Þ³fcΟ$ÇÇ¥LF:}:¸Þ×—{ø=›õo{þ›û \øªöííÒà`pmxØ¿óuuIýýÁµ±1ÿ¶ç¿~ §'÷O«ìûÁ~°±Úuë¤3”M)“Z¨‘Tyàçù@ªJ©ù6¿?nº)w'+‘¬ÑÑQ­]»V­­­úÍo~£/}éKyÝßÑ£G5wîÜIßþ Ýáÿ$øÜÇ÷ ÞwKkGÜmwçÜv»GÍne`í¸[¨íîa ¹ÒÀú¾c_Öoüú½½Òöí¹?pÞyGzå•àÚø¸Û£Gƒëé´´{wî¾íØ!½ÿ~píÈÿ>ηgÔÜ\;~Ü¿íÐPp}ß>±ìûÁ~Ä{?N’²Y»ÚîÖQw]àçyÚݨÝî>›ßÎåî$âÅ]agΜqnæÌ™î7ÞøÂÛe2÷ÑG¹ñññsk9·{ýõ×çyîñÇ¿ä×N§ÓN’Û¯ZçR©ÀGÆ›ï¼ÊÀÚWîÚ¼9·íôæ¹S^U`mÔ›åÚ¼îŒWXï¾ó~wòdpŽÓ§kksnl,¸ÞÛë\WWpmb¿íðpp½¿ß¹öö åæÜÀ@pmhÈ¿óuv:wêTpmtÔ¿í™3Áõîn—³ƒƒÎ:”ûõ¦Û~L•ÇãÄ ç>ü08ÇtÜ©òxüéOþÇçïg:îÇTy<‚yN×ý¸èãÑØè\*å&¼®Í[à†½²ÀÏó~o¶k÷êM~¤=ÏIrét:wg žsW¶F?þøãzþùçµvíÚÀ ëgmܸQ’ôÐCi×®]:v옮¹æIÒâÅ‹ÕÐРåË—«ªªJ---úÉO~¢… êСC—<ŠÕÒÒ¢åË—ëÍ7ÓºãŽË£Rø2ÿ¿¿÷=iþü¨§™þÈÓyÚ"O[g¥Óé¼Þ8S×?Éý÷¿ÿ½<ÏÓk¯½¦×^{-ðožç+Xžçåœôþío[¯¿þºÞzë- kÁ‚úÞ÷¾§-[¶„úaMMþû©®NzôQò´Bž¶ÈÓyá\ñ#XQâ¿S¿âoJ¼Ñ(@œP°Œ%²`ÿ^*¸<½½þK§¹ô ò´Ež¶È'‘+›z‚xÈfý7ú#Oäi‹ùä“I}~__ŸyäÍ;Wúæ7¿©Ã‡‡š¡¢âr&Çùªª¤ÆF.=d…©ÚÚZ½ð Z½zµÒé´Mò:¥¥V{“leeRCCÔSÄyÚ"O[ä „sÅ Ö~ð­X±BEEŸ}é 6è+_ùŠ~øÃêg?ûÙ~nSS“š››ÕÔÔ¤»ï¾[’tï½÷jÉ’%Ú²e‹vïÞ]ðù.åŠÿ‰ðæ›o”+IZ´h‘n¸á9r䢟ÛÔÔ¤úúúsåJ’êêêtï½÷êÕW_Õ8ï ¦€)q’»sNª««»èí>¬† £^±b…†‡‡õñÇOêë _Ö˜8Ïà ÔÜÌ¥‡¬§-ò´Ež@8S¢`íÞ½[mmmÚ°aÃEo—Éd4þüœõ³kmmm“úz,ƒƒÒüÀµBž¶ÈÓyáD~©œ#GŽhÓ¦MZµj•|ðÁ‹ÞvttT%%%9ë³fÍ’$ŒŒLêk^â@&©¾^zꩨ§ˆò´Ež¶È'Ò#Xíííºë®»TSS£¦¦&yžwÑÛ—––jìW=÷ïQ‹¬`:uJkÖ¬Q¿Þ|óMÕ××_òsæÏŸÁ?f>}ç» Lêk÷,ÿ–4cFà£=µ@ƒ©ÙµáT…2©…9·íJ]¥þTu`m,UªLj¡&RÅõž5ÕÛüúããþ›õ>\ï듺»ƒkÙ¬ÛóÎ H¹ûÖÞž{xøÂoØÕ%õ÷ׯÆüÛNLœ—YØöƒý`?â½ëÖI3f(›*R&µP#©òÀÏóT•:Róm~ÜtSîN"V")X£££Z»v­Z[[õ›ßüF_úÒ—&õyË–-SKK‹œsõƒª¼¼\K–,™Ôý¼¡;üŸŸûØáÔûni`íˆ[¢íîáœÛîq÷¨Ù­ ¬w µÝ=¬!WXßwìËúíoƒ_¿·WÚ¾=÷Î;ïH¯¼\÷o{ôhp=–.ô®;vHï¿\;rÄ¿óíÙ㟴úyÇû· ®ïÛ'öƒý`?ØxïÇ©SR6«q7CÛÝÃ:ê® üpîÙgƒ÷3÷cª<ï¿ïÜsÏ÷g:îÇTy<þô§`žÓu?.úx46:—J¹ o†kó¸a¯,ðó¼ß›íÚ½z“ßiÏs’\:ÎÝYÄ‚çÜ•­Ñ?þ¸žþy­]»VëׯÏù÷7J’zè!íÚµKÇŽÓ5×\#É'÷[o½U|ð6oÞ|îÜOœ8¡C‡iñâÅýÚ---Z¾|¹Þy'­o|ƒ·$Î×À€ÿ_¦Ë—K••QO3ý‘§-ò´Ež¶Îþ>J§Ó|û!LWüU„¿ÿýïåyž^{í5½öÚkó<ï\ÁòÈÓyÚ"O œDÁ($ €±D¬ññ¨'ˆ‡Ó§¥ãÇý-òGž¶ÈÓyá$²`q©==ÒË/û[äÈÓyÚ"O ª€1 €±D¬ÞÞ¨'ˆ‡în饗ü-òGž¶ÈÓyá$²`%òÌ3{EEÒ¼yäi…-?îo‘?ò´Ež¶È'‘‹K=Øèé‘^~Ùß"äi‹÷§?ý©R©Ô?:;;'uÕÕùL³jk¥ð·ÈyÚ"O[ä „Éë麺ºôÌ3ÏèÚk¯Õ²eËtàÀyžê>žyæ]ýõµªª*Ë1.K$kÁ‚joo×¼yó”N§µbÅŠÐ÷±fÍ544`:€üDò'™3gjÞ§o¨âœ»¬ûpÎi``@¡?÷2>01á¿`€ªRGj¾Íï›nÊÝIÄJl ÖÑ£G5wîÜIÝö Ýáÿ$øÜÇ÷ ÞwKkGÜmwçÜv»GÍne`í¸[¨íîa ¹ÒÀú¾c_Öoüú½½Òöí¹?pÞyGzå•àÚø¸Û£Gƒëé´´{wî¾íØ!½ÿ~píÈÿ>ηgÔÜ\;~Ü¿íÐPp}ß>åìÇŸþ$mÞ,ÿú‚é¶SåñصKú_ÿ+øKd:îÇTy<^~YÚ¿?˜çtÜ©òx´¶óœ®ûqÑÇãÔ))›Õ¸›¡íîau×~ž§ÝÚíî³ùýq™¯ Ç4â"vèÐ!çyžÛ¹sgοe2÷ÑG¹ñññsk9·{ýõ×çyîñÇ¿è×J§ÓN’Û¯ZçR©ÀGÆ›ï¼ÊÀÚWîÚ¼9·íôæ¹S^U`mÔ›åÚ¼îŒWXï¾ó~wòdpŽÓ§kksnl,¸ÞÛë\WWpmb¿íðpp½¿ß¹ööÜ}Ìdœ® ù÷q¾ÎNçN ®Žú·=s&¸ÞÝíröãÏvîÙg;qbzïÇTy<þã?œûŸÿÓߟé¼Såñøàç¶m æ9÷cª<'Nóœ®ûqÑÇ£±Ñ¹TÊMx3\›·À {eŸçýÞl×îÕ›üþH{ž“äÒétîÎ"<碩ÑÛ¶mS__ŸÚÚÚôâ‹/êî»ïÖ²eË$I=ö˜fÏž­‡zH»víÒ±cÇtÍ5×H’/^¬††-_¾\UUUjiiÑO~ò-\¸P‡ºèQ¬––-_¾\étš7)D†ßGñÙ«Ÿ{î9ýñ”$yž§_ÿú×úÕ¯~%Ïóôï|G³gÏ–çy9—Ðùö·¿­×_]o½õ–†‡‡µ`Á}ï{ßÓ–-[&ý'B€BŠìVø/ÀTÀï£ø‹ÍIîSE" VWWÔÄC&#=ýô…_RðÈÓyÚ"O œD¬ŠŠ¨'ˆ‡ª*©±‘KY!O[äi‹ÈÓyÚ"O œDÁ($ €±D¬ÑѨ'ˆ‡‘éÃý-òGž¶ÈÓyá$²` D=A<ôõI{÷ú[äõñpú´tü¸¿EþÈÓyÚ"O œD,.õ`£§Gzùe‹ü‘§-ò´Ež@8‰<ɽ¦&ê â¡®NzôQò´Bž¶ÈÓyá$²`ñ2cÅÅþ˶aƒ¬†††œõ+VhxxXüñ¤î§(‘§öÛ+*’æÍ#O+äi‹ŸçtÜ©òx9ÌsºîÇES§¤lVãn†¶»‡uÔ]øyžv7j·»Ïæ÷GÈWÑcr:tèó<Ïíܹ3çß2™Œûè£Üøøø¹µ_üâÎó<×ÔÔtn­««ËUWW»ûî»ï’_/N;In¿jK¥o¾ð*kC^¹kóäܶӛçNyUµQo–kó¸3^Q`½ûÎûÝÉ“Á9NŸv®­Í¹±±àzo¯s]]Áµ‰ ÿ¶ÃÃÁõþ~çÚÛs÷1“qn` ¸64äßÇù:;;u*¸6:êßöÌ™àzw·ËÙ¡!çþðç§÷~L•ÇãÏv®µÕŸg:ïÇTy<Žw®£#˜çtÜ©òx óœ®ûqÑÇ£±Ñ¹TÊMx3\›·À {eŸçýÞl×îÕ›üþH{ž“äÒétîÎ"<ç®|Þ¶m›úúúÔÖÖ¦_|Qwß}÷¹wuì±Ç4{öl=ôÐCÚµk—Ž;¦k®¹F’ÿNî·Þz«>øàmÞ¼Yµµµzá…tâÄ :tH‹/¾è×miiÑòåË•N§/øv\ ü>Š¿HÞÑä¹çžÓÿøGIþer~ýë_ëW¿ú•<ÏÓw¾óÍž=[žçå\B'•Jiß¾}Ú¼y³žþyŒŒèk_ûšvíÚuÉrp¥Dr+*ü`*à÷QüM«“Ü­œÿJ\žÞ^ÿÄS.=dƒÈÓyÚ"O œDÁ($ €±D¬ó/«€Ë31á¿`€üÐß"äi‹’ÞøyÔãL{äi‹-:%Í™ãŸrqn?úüÈ>¿Ù:½¢uZ—ýÕ·´LÛý˜*ÇÿÍ^§ºMÿ=ûšj?Ís:îÇTy<2Ùëõ®VjMvÿ¹<§ã~L•Çc";Wo뿞ËsºîÇE'žþÏÿQÖyêÑUjP³>÷ÆÔC®L£š¥Zïdp?.ã÷ÇñO¯(222"ÄS¢NrßÝР‡G=’¤Ÿÿüçºÿþû£¨‚ÕÝÝ­ýßú–®;|X¥žwe¾è7¾!ýã?^™¯¸|ŸÁºFœÓ±oÔo½¥ººº+ò5qe%ª`\ œä`Œ‚`Œ‚`Œ‚`Œ‚`,kllLû·« ¨¬¬L_ÿú×õöÛo_òó~úÓŸ*•J]𣳳ó L>õ iË–-ºóÎ;5gÎ¥R)íܹsÒŸß××§GyDsçÎUEE…¾ùÍoêp‚ß{,Ÿ™Ôçóü Ê'OžŸÀÅÅâÜzè!ýò—¿ÔO<¡Å‹kÇŽúË¿üKýë¿þ«n¹å–K~þ3Ï<£ë¯¿>°VUUU¨q§´®®.=óÌ3ºöÚkµlÙ28p@Þ$ß3,›Íê®»îÒþð=ù䓪­­Õ /¼ Õ«W+NkÑ¢Ež~êÉ'ϳx~~æG?ú‘š››µ~ýz}õ«_U&“ѶmÛÔÐРwß}WK—.ýÂÏåù™+Ÿ<Ïâù |7Í>n:ëtOžgñüüÌÍ7߬¢¢à÷E‹é†nБ#G.ú¹PI+V¬$ýû¿ÿû%ïãöÛoWUU•ÊË˵nÝ:µ¶¶dÖ¸;|ø°rÖW¬X¡ááa}üñÇL5ýñü¼8çœ:::.y¹žŸ“3Ù<Ïâù \Ø´/X™LFóçÏÏY?»ÖÖÖö…Ÿ[^^®ï~÷»zá…ôÊ+¯èÉ'ŸÔï~÷;­ZµJ'Nœ(ØÌq•Ïc\::zîßøå–[´råÊI½Í‚¬ äâùù™öövÝu×]ª©©QSSÓ%_ÉóóâÂæy!çç…]nž_$éÏOà¬i_°î¹çMLLèŸþéŸÎ­iÇŽúú׿®… Jò9rDgΜ9w»®®®œûÛ·oŸZZZtçw~øiìByÞsÏ=êèèЯ~õ«skÝÝÝÚ»w¯Ö®]«âââ(Fx~NÎÄÄ„6lØ ƒjïÞ½Z¹råoÇósròÉ“ç'pqž»Ü7ç™B6lØ _ÿú×zâ‰'ôñÚ¹s§Þ{ï=ýîw¿Ó­·Þ*É·÷]»v騱cºæšk$I‹/VCCƒ–/_®ªª*µ´´è'?ù‰.\¨C‡%ö¿Â¶mÛ¦¾¾>µµµéÅ_ÔÝwß}îHàc=¦Ù³g_0Ïl6«[o½U|ð6oÞ|î²Oœ8¡C‡iñâÅQîVd.7OžŸ¹üq=ÿüóZ»vmàë³6nÜ(éÂßï½µÛ úA½óÎ;xâ‰'Z»[£+,, À·?à>}ú´n3 ÿþ8vìXk·Ñf`úôéúuí <*°êŸöéÓ‘‘‘­Ügà÷ùÇçI/oðEw"R‹ˆ”ÁÀ""e0°èGÐÚ-PÃÀ¢ÍÅ‹[»jcXD¤Œ&«ªª K—.Epp0|}}¬¬¬^dîܹ0™L˜8qb£Ç?ùä 2~~~°Z­X´h®]»æ2NDœœŒž={Âb± _¿~ؾ}û ÷CDjj2°fÍš…””̘1k×®E»ví0~üx>|¸Å =z›7o†4Ms9žŸŸQ£FÁét"%%sæÌAZZâãã]Æ._¾Ë–-ÃØ±c±nÝ:tïÞÓ¦MÃŽ;ZÜ)LÜÈÉÉMÓdÍš5zÍétJxx¸ÄÆÆº;Í ®®NbbbdΜ9&'Nt3nÜ8 ‘òòr½–žž.š¦É¾}ûôZII‰x{{KRR’áüaÆIhh¨ÔÖÖ6ÛϱcÇ€;v¬Eýý”yâõìöVFF¼¼¼˜˜¨×Ìf3fÏžììl”––6†o¿ý6Nœ8+V@D\Ž_¹rYYY˜>}:üýýõúÌ™3áïï;wêµÌÌLÔÔÔ`Á‚†9æÏŸ’’dgg7Û©Ím`ååå!""Â$àÛ§rM)//ÇÒ¥K±|ùrtíÚµÑ1Ÿ}öjjj0`ÀCÝÛÛ6› yyy†~üýýÑ»wïïÕ©Ïm`9X­V—z}­¬¬¬É‰_~ùeøùùá¿ø…Û1‡Ã0gCAAA†5G£Á×Ò~ˆH}nÿñsee%Ìf³KÝÇÇG?îNQQÖ®]‹íÛ·ÃÛÛÛí¸ú9Ü­Óp›é‡ˆÚ·°, ªªª\êN§S?î΢E‹0xð`<üðÃM.^?‡»u|}} cë×¾Ñ~ˆ¨mpûËjµ6ú4«þi\ppp£ç}üñÇØ»w/vïÞS§NéõššTTT ¸¸èСƒþt®~Îï®Óp «ÕŠýû÷ßp?DÔv¸}„e·ÛQTT„òòrC=''`³Ù=ïôéÓ€)S¦àŽ;îÐ?ÊÊÊðñÇ£gϞشiàÞ{ï…——Ž9b˜ãúõëÈÏÏ7¬a·ÛQQQ‚‚‚ê§1£GFPPá#))©ÅçÝjIII.×ìèÑ£[»­[ÏÝ~‡ú}X«W¯Ökõû°bbbôšÃá‚‚©®®‘Ó§OKff¦ácÏž=rûí·ËÀ%33SNž<©Ÿ?nÜ8 ntÖÞ½{õZII‰´oß^ž~úi½VWW'C‡•ÐÐP©««kv‡'î[¡¶Ë¯g·%"’ ÞÞÞ²dÉÙ°aƒÄÆÆJûöíåàÁƒú˜'Ÿ|R4M“âââ&êÑ£G£GsssÅÇÇG"##å7Þçž{N,‹ÄÅŹŒ]²d‰hš&óæÍ“7Ê„ DÓ4Ù¶m[‹¾XOüSÛå‰×s“·HÞ²e ~ýë_ãí·ßÆå˗ѯ_?¼ÿþû2dˆ>FÓ´FÿÉÍw¹c·Û‘••…¥K—â—¿ü%þïÿþsæÌÁÊ•+]Æþîw¿C§N°aüõÖ[ˆˆˆÀ_þò<öØcÍ®ODêÓDÙ‚ÞFåææêoŒÀ{“ê<ñzæíeˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"RF“UUU…¥K—"88¾¾¾ˆŽŽFVVV³“þíoÃSO=…ˆˆøùù¡W¯^˜;w.Ξ=ÛèøO>ùC† ŸŸ¬V+-Z„k×®¹Œ$''£gÏž°X,èׯ¶oßÞÂ/•ˆT×d`Íš5 )))˜1cÖ®]‹víÚaüøñ8|øp““.]ºÀ#<‚ÔÔT<öØcعs'ìv;¾úê+ÃØüü|Œ5 N§)))˜3gÒÒÒï2ïòå˱lÙ2Œ;ëÖ­C÷îÝ1mÚ4ìØ±ã{|éD¤wo ““#š¦Éš5kôšÓé”ððp‰mòí¤¾•}½ˆ¦iòüóÏêãÆ“)//×kééé¢išìÛ·O¯•””ˆ···$%%Î6l˜„††Jmmm“=‰xæ[{SÛå‰×³ÛGXðòòBbb¢^3›Í˜={6²³³QZZê6¾•}½¡C‡" ………zíÊ•+ÈÊÊÂôéÓáïï¯×gΜ ìܹS¯eff¢¦¦ ,0Ì;þ|””” ;;»É`&"õ¹ ¬¼¼øàøùù¹¬ÑpÎï®Óp «ÕÚè>®é‡ˆÔæ6°ìv;ŠŠŠP^^n¨çääl6[“_¼xcÆŒAuu5öîÝÛèëO÷Þ{/¼¼¼päÈCýúõëÈÏÏ7¬a·ÛQQQ‚‚‚ïÕOC£GFPPá#))©ÅçÝjIII.×ìèÑ£[»­[ÏÝ~‡ú}X«W¯Ökõû°bbbôšÃá‚‚©®®ÖkW¯^•JÇŽ%77·É}ãÆ“àààF÷aíÝ»W¯•””Hûöíåé§ŸÖkuuu2tèP •ºººf÷pxâ¾j»<ñzördD||<ž}öYœ;w½zõÂæÍ›qúôilÚ´I·lÙ2lÙ²§NB÷îÝO<ñŽ9‚§žz ÇÇñãÇõñ:tÀC=¤þꫯ"66÷ß?æÎ‹’’üþ÷¿Çرc1fÌ}\HH~þóŸãµ×^Cuu5 €={öàСCغu+4Mûcœˆ~’šJ3§Ó)‹/«Õ*>>>2hÐ Ãîs‘Y³f‰Éd’ââb½&&“I4MsùèÙ³§Ë:‡’Áƒ‹Åb‘®]»JRR’\½zÕe\]]¬\¹RÂÂÂÄl6Kß¾}eëÖ­-NgOü‰Ú.O¼ž5‘ÖÍ[%77ýû÷DZcÇÙÚíÝO¼žy{"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e4XUUUXºt)‚ƒƒáëë‹èèhdeeµh⯿þ‰‰‰èÒ¥ üýý1räHäåå5:ö“O>Á!Càçç«ÕŠE‹áÚµk.ãDÉÉÉèÙ³', úõë‡íÛ··¨"R_“5kÖ,¤¤¤`ÆŒX»v-Úµk‡ñãÇãðáÃMNZWW‡ &`Û¶mX¸p!’““qîÜ9 >Ÿþ¹al~~>F§Ó‰””Ì™3iiiˆw™wùòåX¶lÆŽ‹uëÖ¡{÷î˜6mvìØñ=¾t"RŽ»·„ÎÉÉMÓdÍš5zÍétJxx¸ÄÆÆ6ùvÒ;vìMÓäÝwßÕkçÏŸ—N:É´iÓ cÇ'!!!R^^®×ÒÓÓEÓ4Ù·oŸ^+))oooIJJ2œ?lØ0 •ÚÚÚ&{ñÌ·ö¦¶Ë¯g·°222àåå…ÄÄD½f6›1{öldgg£´´Ômfdd ((S¦LÑkHHH@ff&ª««W®\AVV¦OŸ}ìÌ™3áïï;wêµÌÌLÔÔÔ`Á‚†µæÏŸ’’dgg·8¤‰HMn+//† €¨¨(ß>•kêÜÈÈH—zTT***PTTøì³ÏPSSƒÆy{{Ãf³^óÊË˃¿¿?z÷î}ÃýQÛà6°¬V«K½¾VVVævÒ–žëp8 õ†‚‚‚ k8tíÚõ{õCDmƒÛÀª¬¬„Ùlv©ûøøèÇÝq:-:·þ¿îÆ6\ãfú!¢¶Ám`Y,TUU¹ÔN§~üfÏ­ÿ¯»±¾¾¾†9ëÏ¿Ñ~ˆ¨mðrwÀjµ6ú4«þi\pp°ÛI[znýÓ¹úúwÇ6\Ãjµbÿþýß«Ÿï=z4¼½½ µøøx¤¦¦¶x¢[))) »ví2ÔêyåIÜ>²Ûí(**Byy¹¡ž““°Ùln'µÙlÈÍÍ…ˆ¸œëç燈ˆÀ½÷Þ ///9rÄ0îúõëÈÏÏ7¬a·ÛQQQ‚‚‚îç»>úè#œ={ÖðÁ°¢Ÿ²ÔÔT—kö£>jí¶n9·õ裢¶¶iiiz­ªª ›6mBtt4BBBgÏžEaa!jjj ç~õÕWؽ{·^»pávíÚ…‰'ên:vìˆxï¼ó®^½ª}ûí·qíÚ5ÃæÑ‡zÞÞÞxýõ×õšˆàÍ7ßD·nÝ{3ß"RAS›´ÄÛÛ[–,Y"6lØØXiß¾½Ÿþy³Ï›7ÿýï1sæL¤¦¦"..ëÖ­CLL œN§aì‡~ˆÉ“'# ëÖ­ÃäÉ“±bÅ $%%¹Ì;kÖ,¤¤¤`ÆŒX»v-Úµk‡ñãÇãðáÃßãË'"¥¸{‡Õ;vˆ¦iòî»ïêµóçÏK§NdÚ´i;Cë?þñ—Ú–-[DÓ4IOO7Ôï¾ûn±ÛíR[[«×žþy1™LRXX¨×rrrDÓ4Y³f^s:.±±±Íöä‰ï”Km—'^Ïnaedd ((S¦LÑkHHH@ff&ª««› ÂaƹÔ&Ož (,,Ôk'Nœ@AAa2ý¯ @D‘‘aèÉËË ‰‰‰zÍl6cöìÙÈÎÎFiii“=‘ÚÜV^^^£o…ŠŠ ÝðbgÏžðmð5\ `kµZÑ­[7äççÆFDDÀßßߥ'†±DÔö¸ ,‡Ã«ÕêR¯¯•••Ýðb«V­‚——}ôQÃ: çm(((ȰÎÑ©Ãm`9N˜Íf—º ²²ò†Úºu+þüç?ã™gžA¯^½ôzý<îÖj¸NeeåÚ©Å«ºº/^4»té‹Å‚ªª*—êÃg±XZ¼ÈÁƒ1{ölÄÅÅáÕW_5«ŸÇÝZ ×ù!{""õx>|#GŽÔ š¦á‹/¾€Õjmô)VýS¸ààà-ð¯ý “&MÂ}÷݇ŒŒ à ëÀÿžÎ9„„„¸¬mûCô4zôhx{{jñññHMMmÑùD·ZRRvíÚe¨5÷‹¯¶ÈËf³¹l¼ ‚ÍfÃÁƒ!"Ð4M?–““???DDD4;ùÉ“'‡   |ðÁðõõuc³ÙGŽ1¼ð^VV†ÒÒRý8Øívìß¿åååèСƒ¡§†s5ç£>jô D?U©©©.¡æææ¢ÿþ­ÔQ+q·ß¡~VFF†^;þ¼ÜvÛmòøãÆKAA¡æp8äŽ;înݺIqqq“{+úôé#6›­Åû°V¯^­×ê÷aÅÄÄ4¹†ˆgî[¡¶Ë¯g/wAöè£"::?ûÙÏpâÄ tîܯ¿þ:D/½ô’aìÌ™3qàÀÔÕÕ鵸¸8|ùå—X²d 8`„x@ÿüµ×^äI“0fÌL:ÿùϰ~ýzÌ;wÝu—>nàÀˆÇ³Ï>‹sçΡW¯^ؼy3NŸ>M›6ÝdtÑO^Sivùòe™3gŽŠŸŸŸŒ1¢Ñ4>|¸˜L&CMÓ41™L¢išËLj#\æØ³gØívñññ‘îÝ»Ë /¼ 555.ãœN§,^¼X¬V«øøøÈ Aƒdß¾}-JgOü‰Ú.O¼ž5‘ÖÍ[¥þ9ÿ±cÇø)ϯgÞ^†ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e0°ˆH ,"R‹ˆ”ÁÀ""e4X_ý5Ñ¥KøûûcäÈ‘ÈËËû^ =&“ IIIï½÷ ‹Å‚=zàÅ_Dmm­Ë¸ªª*,]ºÁÁÁðõõEtt4²²²¾WOD¤·UWW‡ &`Û¶mX¸p!’““qîÜ9 >Ÿþù -²{÷nüóŸÿhšærüÃ?ÄäÉ“€uëÖaòäÉX±bE£á6kÖ,¤¤¤`ÆŒX»v-Úµk‡ñãÇãðáÃ7Ô)ÈÝ;¬îرC4M“wß}W¯?^:uê$Ó¦Mkñ;µVVVJXX˜¬X±B4M“¤¤$—1wß}·Øív©­­ÕkÏ?ÿ¼˜L&),,Ôk999¢iš¬Y³F¯9N —ØØØf{ñÄwÊ¥¶Ë¯g·°222„)S¦èµÀÀ@$$$ 33ÕÕÕ- ÄäädÀ3Ï<Óèñ'N   ‰‰‰0™þ×΂ "ÈÈÈ0ôäåå…ÄÄD½f6›1{öldgg£´´´E=‘šÜV^^^£o…ŠŠ 5;ùéÓ§±jÕ*¬Zµ >>>n×€êV«ݺuC~~¾alDDüýý]z`KDmÛÀr8°Z­.õúZYYY³“?óÌ3ˆŒŒDBB‚Û1‡Ã0oCAAA†u~ˆžˆH]^î8N˜Íf—zý#¥ÊÊÊ&'þûßÿŽÝ»wãÓO?mr\ý<îÖºzõªaìÍôDDj󪮮ÆÅ‹ Å.]ºÀb± ªªÊå§Ó °X,n'­©©ÁÂ… 1sæLôïß¿Éêçq·VÃun¦'"RŸ×áÇ1räH½ i¾øâ X­ÖFŸbÕ?… v;é–-[PTT„´´4œ:uÊpìÊ•+(..Æí·ß‹Å¢?s8 qY+::Zÿüfz""õyÙl6——AAA°Ùl8xð Dİw*''~~~ˆˆˆp;é™3gP]]Áƒ»Û²e ¶lÙ‚={ö`Ò¤I°Ùl€#GŽ^x/++Cii©~ìv;öïßòòrtèÐÁÐÃØ¦Œ=ÞÞÞ†Z||Ñ­–””„]»vj-ýM}›ân¿Cý>¬ŒŒ ½vþüy¹í¶ÛäñÇ7Œ-..–‚‚ýóÂÂBÉÌÌ4|ìÙ³G4M“|P233Åápèãûôé#6›­Åû°V¯^­×ê÷aÅÄÄ4»‡Ã÷­PÛå‰×³ÛÀª­­•˜˜éСƒ¼üò˲~ýz¹çž{¤cÇŽRTTd{ÿý÷‹¦iÍ.ænãèûï¿/&“IF%iii²páBi׮̛7ÏelBB‚x{{Ë’%KdÆ +íÛ·—ƒ6»¾'þ€©íòÄëÙm`‰ˆ\¾|YæÌ™#âçç'#FŒhô›3|øp1™LÍ.æ.°DDöìÙ#v»]|||¤{÷îò /HMMË8§Ó)‹/«Õ*>>>2hÐ Ù·o_³k‹xæ˜Ú.O¼ž5‘Ö|Jz+åææ¢ÿþ8vìX£›b‰Tâ‰×3o/CDÊ``‘2XD¤ )ƒEDÊ``‘2Xô£éܹsk·@m ‹~4—.]jí¨a`‘2XD¤ )Ãí-’Û¢ú[(´r'ž#77·µ[h³ê¯cOº5¸GVýÝO§OŸÞºxæn‘M7ïÔ©SÞ,³-ò¨»5\¸p{÷îEXXïÿNÊ«¬¬Ä©S§0vìX¶v;·„G©/º‘2XD¤ )ƒEDÊ``‘2XmÔµk×ð›ßüqqq€ÉdÂæÍ›[PP€¸¸8tèÐ;wÆÌ™3qáÂ…FÇþéOBŸ>}`±XuëÖµ¸'Arr2zöì ‹Å‚~ýúaûöíŽ---EBB:uꄎ;bòäÉøòË/ûÞ{ï!22‹=zôÀ‹/¾ˆÚÚÚ÷E iÅwì¡Ñ—_~)š¦IXX˜Œ1B4M“Í›7»Œ;sæŒÊwÞ)©©©òÛßþVÄf³Éõë× cß|óMÑ4Mâãã%==]fΜ)š¦ÉªU«ZÔÓ²eËDÓ4™7ož¤§§Ëƒ>(š¦ÉöíÛ ãÊËËåÎ;ï”   yíµ×$%%Eºwï.¡¡¡rñâEÃØ>ø@4M“Q£FIzzºþž–óçÏ¿Áï©€ÕFUUUÉW_}%""GuXóçÏ???9sæŒ^ËÊÊMÓ$--M¯UTTHçÎeâĉ†ó§OŸ.þþþrùòå&û)))ooo—÷¥6l˜„††Þõ{ÕªU¢iš=zT¯Š———,_¾ÜpþÝwß-v»½Ùw §¶åŽ9â6°n¿ýv™:uªKý®»î’x@ÿü¯ý«hš&~ø¡a\vv¶hš&ï¼óN“=¬_¿^4M“‚‚C}Û¶m¢iš:tH¯EEEÉ Aƒ\æ;v¬„‡‡ëŸ?~\4M“7ÞxÃ0®¬¬L4M“+V4Ù©‡¯ay°ÒÒRœ? p9…¼¼<ýóú?wldd$L&òóó›\+//þþþèÝ»·Ë:ôóëêêðïÿÛmO'OžÄµkךìÉjµ¢[·nÍöDêa`y0‡ÃàÛÿÁ¿ËjµâÒ¥K¨®®ÖǶk×Îå߬µoß;wFYYY³kuíÚµÑuèç_ºt ׯ_wÛSñMõÔlO¤–«¿-‰Ùlv9æããcSYY‰öíÛ7:Ùlnö'•••-^çFzjj¬'ÝvÅS0°ýôSØl6ýs»Ý.c=Šºº:ÃØÆØívTTT¸Üí5''ôóM&úöíÛhO999èÕ«üüü ç|wlYYJKG›€@\IDATK›í‰ÔÚ¿¦¤_SÛæÏŸ/¾¾¾îÃÚ°aƒ^«¬¬lñ>¬o¾ùF ä›o¾Ñk%%%Ò¾}{yúé§õZ]] :TBCC¥®®N¯7µëÙgŸ5¬ß§O±Ùl܇å!XmXjjª¼òÊ+2þ|Ñ4Myäyå•Wä•W^Ñä~§{xx¸¾Ó½S§NÒ¯_?—þº¾Ó}ãÆúN÷•+WÆmÚ´I4M“·ÞzËP_²d‰¾Ó}ãÆ2aÂÑ4M¶mÛfW^^.áááÒµkW}§{hh¨tëÖM.\¸`ûþûï‹Éd’Q£FIZZš¾Ó}Þ¼y?Ô·‘~BXmXXX˜hš&š¦‰Éd“ɤÿ¹¸¸Xwüøq;v¬øùùI@@€Ì˜1CÎ;×èœ7n”Þ½{‹Ùl–;ï¼SþøÇ?ºŒyë­·Äd2¹<¢«««“•+WJXX˜˜ÍféÛ·¯lݺµÑuJJJ$>>^:vì(:tI“&ÉÉ“'»gϱÛíâãã#Ý»w—^xAjjjZúm"…ðÉD¤ ¾èNDÊ``‘2XD¤ )ƒEDÊ``‘2XD¤ )ƒEDÊ``‘2XD¤ )ƒEDÊ``‘2XD¤ )ƒEDÊ``‘2XD¤ )ƒEDÊ``‘2XD¤ )ƒEDÊ``‘2XD¤ )ƒEDÊ``‘2XD¤ )ƒEDÊ``‘2XD¤ )ƒEDÊ``‘2þÕRÜϵ; IEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/test_axislabels_regression.png0000644000077000000240000001433112436367710027047 0ustar tomstaff00000000000000‰PNG  IHDRÛÜù†ÔøsBIT|dˆ pHYsaa¨?§i{IDATxœíÝ{PT×ðï^®€ˆò¨>>µßp@III|Øå‘””dÕûÒ!lÁÁÁ€¤¤$têÔÉêý 2GޱQ¯OÛõÝ~CmûÂ… ˆ×Þ_µåa3œ:vêÔ VïÇÅÅ¥N¯¯‹úl»¾Ûoèm[ûÑ„$D’0lD’0lD’0lÏ÷‹l»¾ÛwÔ¶!ïïÙ233‰ŒŒŒzd ÇR×÷lD’0lD’0lD’8ä—ÚC† ‹‹‹QY\\6lØPO=¢ÆböìÙØ±c‡QYEEEöÉ " q‚„¨‘`؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$a؈$á’QDfpÉ( qÉ(².EÔH0lD’0lD’Ô*lz½“&MBTTFŒ„„˜ûÈ—””'''›u’ÈX¶ÜÜ\DGG#99ÕÕÕÈÊÊÂïÿ{ôíÛ………&õpÞ…¨N,ÛâÅ‹ááᬬ,dddàÇÄÖ­[‘••…èèhdggÛ³ŸDžÅaûî»ï0kÖ,´oß ( âã㑚š '''ôíÛ©©©vë(QcgqØ~úé'øûû›”¿ð øöÛo„Áƒ㫯¾²i‰…ÅakÛ¶-þûßÿšÝÖªU+¤¤¤ {÷î3fŒÉ7ïDT‹° 0;vì@ee¥ÙíÍ›7Ç×_áÇcÿþýPÅf$r‡mòäɈ‰‰Azzzut:víÚ…9sæ _¿~6é ‘£°øB䨨($''?·ž““Ö®][§N9"^AB$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$‰ESÿ'Nœ°jçü®èÿ, [lll­w¬( ªªªjý:"GeQؾùæ{÷ƒÈáÙíÈFDÆê9«Âöþûï£oß¾8uêþð‡?˜l‰‰ÁÙ³gëÜ9"GbUØÎŸ? &Ô¸ýW¿únݺeu§ˆ‘UasssÃÇkÜ~õêUx{{[Ý)"GdUØ €ÄÄD³«zâ³Ï>ÃСCëÜ9"GbÕ’Q|𢣣…¸¸8ÀáÇqìØ1lÚ´ B¼÷Þ{6í¨5¸dYËKFAXéüùóbРABUU¡(Šö0`€øá‡¬Ý­Mddd"##£^ûAŽ¥®ï+«CìÒ¥ Ž=Š»wïâÒ¥K¨®®FHHüüüê–~"Uç•G[¶l‰=zØ¢/DÍê+Hnß¾  S§NhÚ´)ÜÜÜйsg,X°€ÓþDfX6½^ððp¬Y³^^^ˆ‹‹Ãøñãáéé‰5kÖ <<çÏŸ·u_‰5«N#ßzë-TUU!55QQQFÛÒÒÒ0bÄÌš5 )))¶è#‘C°êÈ–––†¹sçš zôèyóæqE¢§X6___4mÚ´Æí:޳’DO±*lóæÍÃG}„‚‚“mùùùøøã1oÞ¼:wŽÈ‘Xô™mÕªUF«Ò!ЬY3„……aìØ± äää`ïÞ½ å2¿DOQ„©PUë¾!¨®®¶êuu•™™‰ÈÈHddd ""¢^ú@ާ®ï+‹ŽlW®\©õŽ‰È˜Ea ¶s7ˆïˆL$‰Õ×Fž;w6l@ff&Š‹‹>Ÿ ! ( O?‰ž`Õ‘-%%=zôÀ€+W® $$þþþ¸ví<<<п[÷•¨Q³*lK—.EHH²³³µ»h½ûî»øöÛoqúôiäååá·¿ý­-ûIÔèY¶ÌÌLL:Í›7×¾0œFöìÙÓ§OÇ’%Kl×K"`UØœáéé ðòò‚‹‹ nß¾­mo×®ôz½mzHä ¬ [hh(rssÞª¢cǎصk€Ÿ'G<ˆV­ZÙ®—DÀª°5 _|ñ*++ ,ÀîÝ»†°°0ìÛ·Ó§O·iG‰;«¦þ—,Y‚9sæhŸ×&Ož '''$''ÃÉÉ ‹/Æ”)SlÙO¢FϪ°¹¸¸ÀÇÇǨ,>>ñññ€ ??uï!‘ƒ°Ë$ëÖ­CëÖ­í±k¢FË.aBðOlˆžÂk#‰$a؈$a؈$±x6233ÓâÝFˆj¶—_~Ùžý rx‡íóÏ?¯ÕŽ‘KF‘µì±d”E7üilxò‡º¾¯8AB$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$ ÃF$‰Åë³5F\Ÿ¬ÅõÙ,ÄõÙȸ>Q#Á°I°I°I°I°I°=ÃìÙ³‘m×wûŽÚ6Ãö O©ùKi»¾ÛwÔ¶6"I6"I6"IòBä²²2À… ê´ŸŠŠ dffÚ¢Kªíún¿¡¶mx?Þ_µ&PRR’Àvy$%%Yõ¾tÈ«þ‹ŠŠpøða£iÓ¦õÝreee¸ví† ŸZ¿Þ!ÃFÔq‚„H†H†H†H†H†H’¶GaÑ¢E€››¢££qôèQ“zï¿ÿ>|}}ѹsg“oýÓÓÓ1kÖ,téÒhÛ¶-&L˜€ÜÜ\³mnܸ:u‚N§CPP,X€ÒÒR£:×®]ƒªª8qâ„V–UUÍ>nß¾ HIIªªPÅìcĈÚþ.\¸€=z@Q´hÑ¿ùÍo (ŠQ›O÷CUUlݺÕâŸï_þò¨ªŠððp£ò)S¦˜G§Nžùs°Uû†ñ>Íš5ƒ··7^ýuYÕ¾^¯G\\BCCáîîoooôêÕ Û¶m«—q7È˵¦L™‚;wbþüù Ö-[0räH?~½{÷$''cýúõX¼x1ôz=ÆŒƒœœíKì¿ýío8}ú4âââðÒK/¡  7nDDD¾ûî;téÒEkoÑ¢EøðÇùóçC¯×cÆ Ðëõøê«¯,êó²eËЮ];£²æÍ›= Dyy9&L˜ •½ôÒKèØ±#àæÍ›èׯt:àÍ7ßħŸ~ ¨¬¬¬Í°F7oÞÄòåËáîîEQL¶7iÒ›7o~æ8ìÕ¾aü-Z´ÀŠ+PRR‚•+W"++ iii&÷}ž7nàÁƒ˜2e PZZŠäädLš4 ×®]ßþô'­®½Ç îr­ÔÔT¡(ŠXµj•VV^^.Ú·o/zõ꥕Mœ8Q|úé§Úó˜˜qäÈíùþóQQQa´ïÜÜ\¡ÓéD||¼V–ŸŸ/œÅäÉ“ênܸQ(Š"öï߯•]½zU(Š"þýïke[¶lŠ¢ˆŒŒŒÇtüøq¡(Šèܹ³¯±ÞÌ™3…»»»øòË/…¢(âúõëÚ¥gï¼óNýPE$&&Ö¸ß'M˜0A }yyy€ÒÒRøúújuüüüððáCíyLL œÜíÛ·GçΑ­•>}UUU˜8q¢Q]ÃóíÛ·[Ôo!JJJPUUõÌz•••xôè>øà­ì…^œ:u ýû÷×ÊOž< Ú‘‚ƒƒMŽ\îîîxã70`ÀxzzâÌ™3X½z5zõê…ÌÌL¡I“&?~< ѦM¨ªŠ={öàÞ½{X¶lrrrðÎ;ïhãŒ5jgáÂ…X¹r%***àââbÒêêêgŽ>ùäܸqß|óMu°hÑ"DDD ºº‡ÂG}„sçÎ!%%NNNf¶h¿  jü¿¿{÷®Õãûí·µÏ¾ÎÎÎX¿~½Ñ™“=ÇmÄâNIBBBĨQ£LÊ/_¾,EëÖ­ÓʪªªÄ¹sçD~~þs÷{áÂáéé)z÷î-ª««¶EGG‹fÍš‰-[¶ˆ«W¯ŠƒжmÛ WWWáââRë1œ:uJ¨ª*f̘QcK—. 777Ѻuk¡(Šøä“O„¢(bÇŽ&u—,Y"E÷ï߯u_„¢¨¨H´lÙR¬^½Z+ëß¿ÿ3??,_¾\(Š"¶oßnUÛ–¶âÄ »?;;[;vLüãÿÇNNN"!!ᙯ±Å¸ŸÖàÂÖ¥K1xð`“r½^oòAÙR"$$D´mÛV˜lÏËË}úôŠ¢EQ„³³³X´h‘èÙ³§hÑ¢…U㈉‰íÛ·f‰' WWW@Ìœ9S(Šböo¥.\(E?¶ª/3fÌ:t0š0²4leeeÂÉÉIL›6ͪ¶-m?==ÝnãÚСC…———(--­±Ž-Æý´wéïï¯*>Épšñ¼Sŧݿ#FŒ@qq1Nž<‰V­Z™Ô ÀÉ“'qùòe",, ~~~@‡¬GPPrrržY§uëÖÚ2D†ÓÃ8ŸTPPooïZO}@nn.>ûì3¬]»7oÞÔÊËËËñøñc\¿~žžžhÑ¢…Ù×ët:´lÙwïÞ­uÛµißpúhëñ›óꫯâÈ‘#¸xñ"ºuëf¶N]ÇmNƒ› éÞ½;rrrPRRbTžšš 5þpÌ)//ÇèÑ£qéÒ%üë_ÿÒ>ŸÕ$44½{÷†ŸŸ~øábðàÁµ€+W®Í*ÖTG§ÓAQ„„„À××ééé&õÒÒÒj5î'åå塺ºsæÌAHHˆöHKKCNNÚµk‡eË–Õøú’’=w,um?00Ð.ã7Çp[U­ùí_×q›e³c¤¾g[¹r¥Vføž-&&ÆâýTVVŠW^yE¸ººŠC‡ÕªUUUbÔ¨QÂÃÃÃè;snß¾mRvàÀ¡(Š˜7ožV§¸¸X”——ku¾ÿþ{áââ"…ªªâìÙ³bæÌ™ÂÍÍÍì÷L›6mªÕ ŠŠŠÄž={ÄÞ½{µÇž={Ä‹/¾(‚ƒƒÅÞ½{ÅùóçEyy¹(..6y½ánÏž=vm_aóñ›û¿yüø±ˆˆˆ>>>¢²²Ònã6§Aþ¥ö„ °{÷nÌŸ?¡¡¡HLLÄ™3gpìØ1ôéÓÇ¢}Ì›7ëׯÇèÑ£g²=>>^û÷ܹsñèÑ#tíÚøâ‹/pæÌ$&&âw¿ûÝ3Û CDD"##ѼysdffâóÏ?G`` ÒÓÓáëë‹¢¬¬ çÏŸGtt4ªªªpêÔ)!PYY‰3fàã?ÆÍ›7ѽ{wxyyaîܹ())Á‡~ˆ6mÚ ==Ýf§Q‹Ÿ~ú YYY~¾©{÷îxíµ×´+Z>ŒC‡aĈ8pà€ÍÚ6×>›ܸq())A¿~ý€ÂÂBlÛ¶ 999زe ^ýu¹ã¶Ylm¨¼¼\,\¸Pøûû N'zöì)¾þúëZí#66V¨ªªMz<ùPUÕ¨nBB‚èÖ­›ðððžžžbÈ!"%%Å¢v/^,ºwï.¼¼¼„«««o½õ–ÑoÕõë׋nݺi“!„³³³7™ðÑëõbذaÂÝÝ]´lÙRLš4Éìo躊5š ¸w4i’ îîîB§Ó‰ððpñ׿þUTVVÚ½}[ŽûöíbÈ!¢U«VÂÅÅEx{{‹‘#GŠ£GjudŽ»AÙˆQƒ› !rT ‘$ ‘$ ‘$ ‘$ ‘$ ‘$ ‘$ ‘$ ‘$ ‘$ ›3ÜTtÕªU6ۧᆳOÞ4–,ð50†;,ÛrMéºÜÊZ>Ä{gáÇ£eË–PU‰‰‰ÒûÑ0ldwîÜÁ²eËŒn=P¡oHÜ=HÈ1þXÓÏÏϽ§ç/lPEE–.]ŠÈÈHxyyÁÃÃýúõCJJŠÙúB¬Y³mÛ¶…››bcc¡×ëMêeggcüøñðööFÓ¦M…ýû÷[ÕGWWWøùùiílÒýû÷±yóf¼öÚk˜>}:Š‹‹±yóf 6 iiièÚµ«Qý­[·¢¤¤³gÏFYYÖ­[‡"++K „^¯Gï޽Ѻuk¼ûî»pwwÇ?ÿùOŒ;;wîÄØ±cëc¨ŽÅ¦÷MufÉBUUU&‹†Ü»wO´jÕJL:U+3,áîînt#Û´´4¡(Šxûí·µ²Aƒ‰®]»šÜ›±wïÞ¢C‡ÚsÃ"!O..ò<†{BÖf GÄÓÈFHUUmÑêêjíÖÜ‘‘‘fg1ÇŽkt[﨨(ôìÙܽ{ÇG\\îß¿¢¢"í1tèPäææš½Ÿ#ÕO#©ÄÄD¬Zµ /^Ônô !!!&uÃÂÂÌ–íØ±ÀÏ‹v!°dÉ,Y²Ä¤®¢(¸}û¶Ùûð“å¶F()) o¼ñƇE‹ÁÏϪªbÅŠ¸råŠÅû1LňX¸p!† f¶nhhhÝ;þ ǰ5BÉÉÉ ÅÎ;Ê—.]j¶¾¹Û çää 88Àÿ†ÎÎÎ8p m;K~fk„œœœ ~^E+KMMÅéÓ§ÍÖß»w¯Ñú iiiHKKÓÖòöóóCll,6mÚ„ÂÂB“×ß¹sÇÆ#øeâ‘­Ú¼y³6a ( æÎ‹Ñ£Gc÷îÝ7nFމ«W¯bÓ¦MèÒ¥‹ÙMCCCѧOÌœ9åååX»v-|||ŒüûßÿŽ>}ú <<Ó¦MC»vípëÖ-mµWÃ"”µ±qãFÜ»wO ú¾}ûpãÆ Àœ9sàééYë}6jõ<JOIHHÐîÚlîNÎyyyB!V¬X!‚ƒƒ…N§‘‘‘âàÁƒbÊ”)¢]»vÚ¾ Sÿ«V­«W¯mÚ´:Nôïß_dee™´}åÊ1yòdáïï/\]]EëÖ­Å+¯¼"víÚ¥Õ9~ü¸PUÕ¢©ÿàà`£¾Ƥªª¸~ýº ~Z ïˆL$ ?³I°I°I°I°I°I°I°I°I°I°I°Iò?…²»|m˜¯—IEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/test_noncelestial_angular.png0000644000077000000240000002313412553175753026656 0ustar tomstaff00000000000000‰PNG  IHDR2coiKsBIT|dˆ pHYsaa¨?§i IDATxœíÝ{XTÕþ?ð÷`d¸‰¨(*˜â…PQ°§¯zJER±~E$𢙩ñPÚÅDÁ£G“2’N‚—4¡²›×ÔGDKôäOxÌjp´ˆÒÁfýþè09΃š°ìýzžyb>{­µ×b7ïgöž=¢!ˆˆ$¦jî Ý,IAFDÒc‘ôdD$=IAFDÒc‘ôZ7÷šSYY/ÎÆÅ‹NhÝÚ¡¹§sÓzôh‹Ó§Ë›{·×Ò2Ýîµtíê __ ,, íÚµ«¿¡ø[¿~½À|´ðÇúõë|-ÿ©ß‘ùúúþï§ÿ ´—Äòå}1{öÉæžÆ-Áµ´L·{-÷ÜãˆÂÂU×¼VmûS™F£ùßOíx7çTn‰»îêà—æžÆ-Áµ´L·{-®®¿½F­ÚÆ‹ýD$=IAFDÒcÝQ\š{·×Ò2µÌµ0Èî(š{·×Ò2µÌµ0ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é5)Ⱦúê+Œ5 nnnpuuEXXŽ?n³mqq1Fxzz"&&eee6Ûfee¡OŸ>Ðh4ð÷÷GzzºÝsB -- ~~~Ðh4èß¿?6nÜØ”e‘äì²£Gâ¾ûîÃÙ³gñòË/cÁ‚())ÁСCñÍ7ßX´Õét2dΜ9ƒÅ‹cΜ9ؾ};FŒ«W¯Z´ÍÌÌÄSO=…ÀÀ@¤§§ãÞ{ïÅÌ™3‘––f×¼’““‘””„°°0¤§§£k×®ˆŽŽÆ¦M›ì]IÎî³þüùpvvFAA<<<'N„¿¿?’““±eËsÛ”” ÁÇÇ0xð`Œ1ÙÙÙxê©§ƒ/¼ðÆŒƒÍ›7&Ož “É„… bêÔ©pww¯wN¥¥¥X¶lñú믛û:sçÎEdd$T*ž=Ýéì~•ïß¿Ç7‡tìØC† ÁG}„K—.™ë[·nŘ1cÌ!<ðüýýÍ{öìAyy9,ö5}út\ºt Û·oopNùùù¨©©±êN‡‚‚{—GD³;ÈŒF£Í¿dÒ¦MFœ8qÀoï’~úé'[µ AQQ‘ùyÝÏ×·8p T*Ž;ÖàœŠŠŠ ÕjÑ»wo«ýh´?Ýì²^½z¡  &“É\3(,,œ;w ×ëÞÞÖ^ÍÛÛåååæëdz½­Zµ²ú Âðôô4Y½^¬ÿÅʺ}7ÖŸˆî vYBB¾ùæLž<ÅÅÅ8qâbbbpþüy¿]ïºö¿ŽŽŽVc899Yµupp°¹?GGGs»ú »öCDw6»ƒlÚ´iHNNFnn.Я_?|ûí·˜7o@«Õøýi^¹rÅjŒêêj‹6F£Ñæþª««ý£œƉ;áOÚççǸqš{·×Ò2ÝÑÓ®v7u“Õ¦M›ðå—_bÖ¬YõGy}ôt:¹¶k×.””” 22Ò\»ÿþûѶm[¬Y³Æ¢ÿš5kàììŒÑ£G›k•••8uê*++͵qãÆA­VcõêÕæšðññ±\"ºsÙýŽlß¾}xõÕW†¶mÛâСCÈÎÎFxx8žyæ‹¶ÉÉÉxï½÷ð·¿ý Ï<ó ªªª°téRôë×O>ù¤¹““.\ˆéÓ§ã±ÇÃÈ‘#±ÿ~äää %%ÅâfØ÷ßqqqX·nbccüöîoÖ¬YXºt)®^½Šàà`äååáÀÈÍÍ…¢(7ûû!" Ød>>>hݺ5–.]Šªª*tïÞ‹-ÂìÙ³­îž÷ññÁ_|Ù³g#)) ŽŽŽ3f –-[f¾>V'>>jµË–-Ã|€®]»bÅŠ˜9s¦E;EQÌk-Y²ÈÌÌDvv6üýý‘““ƒÇ¼©¿ "’”ÝAÖ½{w|úé§vÜ·o_»ÛO™2S¦Li°Mll¬ùصEARR’’’ìžÝYøED"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’^“ƒìèÑ£ˆˆˆ€§§'œˆU«Vý> JUïcäÈ‘–;¯§]jjª]sB -- ~~~Ðh4èß¿?6nÜØÔ%‘äZ7¥ñçŸޱcÇbРAX°`´Z-NŸ>ÒÒRs›õë×[õ;räV®\‰°°0«m#GŽDLLŒE-((È®ù$''#55S§NEHHòòò EQÕ”¥‘Äì²ÊÊJÄÄÄ`ìØ±Ø²eK½í¢££­j»w(?~¼Õ6›}SZZŠeË–!11¯¿þ:`òäÉ:t(æÎ‹ÈÈH¨T¶®«ÕÕêæKDw>»ß‘uêÔ 'Ož´:kß¾=à—_~±ê“““wwwŒ3Æî ùøøÊËËlçíí½{÷ZÕõz½y¾öZ¾¼/ÇuUÖ§®-ÙàÁ‘ŸoýɰŒ¸––é]ËU•mÛ¶ÙÕÓî ÆÎ;¡ÓéгgOs½îZ”———E{½^={ö ..jµÚÞÝàÌ™36Ç»^PP²²²P\\Œ>}ú˜ë………€ؽÏÙ³O°bÙäçǸqö}XÒÒq--Óí^ˈ=o„&œZ>öØc€¬¬,‹ú[o½µZaÆYÔ7nÜ!D½§•eeeVµªª*¬X±^^^4h¹^YY‰S§N¡²²Ò\7nÔj5V¯^m® !‘‘„††Ú»4"’œÝïÈ €¸¸8¼ýöÛ¨©©Á!C°wï^lÙ²ÉÉÉèØ±£EûœœtîÜÙ*àꤧ§#//èÒ¥ ôz=Þ~ûmèt:¼ûî»hÝú÷©Õ}BºnÝ:ÄÆÆ:wîŒY³faéÒ¥¸zõ*‚ƒƒ‘——‡ 77Š¢ÜÀ¯ƒˆdÔ¤¯(edd k×®X·n¶mÛ___¬X±3gδh÷ŸÿüGÅsÏ=WïX÷Ýw ðÖ[oá矆³³3î¹çdgg[…Ÿ¢(æÇµ–,Ydff";;þþþÈÉÉÁã?Þ”e‘äšd­[·Æ‚ °`Á‚ÛõêÕ«Ñ»þ‡ŽáÃ‡ÛµßØØXó;±k)Š‚¤¤$$%%Ù5Ý™øeD"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ÞMÙ¢E‹ R©hQŸ4iT*•Õ£OŸ>6ÇÉÊÊBŸ>} Ñhàïïôôt»ç „@ZZüüü Ñhпlܸñf–ED’i}£u:RRRàìì EQ¬¶;::"++Ë¢æææfÕ.33ñññxôÑG1gÎìÛ·3gÎÄåË—1oÞ¼F瑜œŒÔÔTL:!!!ÈËËCtt4EATTÔ.ˆ$rÃA6g΄††¢¦¦eeeVÛÕj5¢££Ã`0à…^À˜1c°yófÀäÉ“a2™°páBL:îîîõö/--Ųe˘˜ˆ×_ÝÜèС˜;w."##¡Rñì™èNwC¯ò}ûöaëÖ­X±b„6ß‘ !`2™PYYYï8{öìAyy9,êÓ§OÇ¥K—°}ûö瑟Ÿšš«þñññÐét(((hªˆHVM²ÚÚZ̘1O=õêmwùòe¸ººÂÝÝžžžHLLÄ¥K—,Ú‚ƒƒ-ê„J¥Â±cÇœKQQ´Z-z÷îmQ €Fûѡɧ–øþûï±{÷îzÛtêÔ Ï?ÿ<“É„O>ù«W¯ÆñãDZwï^´jÕ  ×ëѪU+´k×΢¿ƒƒ<==qîܹç¢×ëÑ¡C«º··74ÚŸˆî M ²Ÿþ ,À‚ àééYo»””‹ç=öüýýñ /`Ë–-æ‹ðƒ6Çptt„Á`hp>ƒŽŽŽVu'''óv"ºó5éÔòÅ_D»ví0cÆŒ&ïèÙgŸ…J¥Â®]»Ì5F£Ñh³}uu54Mƒcj4TWWÛì[·ˆî|v¿#+))ÁÚµk±bÅ èt:s½ººF£ß}÷\]]áááa³¿““Ú¶m‹òòrsÍÛÛµµµ(++³8½4(//G§Nœ“··7öîÝkU×ëõÐhÿ:Ë—÷Å]wõ¸®êÀú´µ%<¸3òóÇ7÷4n ®¥eúc×r@•EeÛ¶mvõ´;ÈJKKa2™0sæLÌœ9Ój»ŸŸfÍš…åË—Ûì_UU…²²2xyy™kAAA€#GŽ <<Ü\ÿòË/a2™0`À€ç„¬¬,[Ül[XXö¯3{öI¿ØÕ¶%ËÏqã64÷4n ®¥eºÝk1¢§]íì>µ ĶmÛ——g~lÛ¶ èÖ­òòò0yòd\¹rUUUVý.\5j”¹vÿý÷£mÛ¶X³fEÛ5kÖÀÙÙ£G6×*++qêÔ)‹Û9ƵZÕ«W›kBdddÀÇÇ¡¡¡ö.ˆ$f÷;2OOOŒ7Ϊþü8{ö,‚‚‚^½z>ûì3|òÉ'·ÃÉÉ .ÄôéÓñØcaäȑؿ?rrr’’bq3ìû￸¸8¬[·±±±€Î;cÖ¬YXºt)®^½Šàà`äååáÀÈÍ͵yÝynøÎþ:Š¢X†‡‡ÆŽ‹;vàwÞAmm-zöì‰Å‹cΜ9Výããã¡V«±lÙ2|ðÁèÚµ+V¬XauúZ·ŸëÃiÉ’%ððð@ff&²³³áï<þøã7»4"’ÄMÙž={,ž»¹¹áŸÿüg“Ƙ2e ¦L™Ò`›ØØXó;±k)Š‚¤¤$$%%5iŸDtçà‰Hz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1ȈHzM ²#GŽ 11ÐjµèÖ­¢¢¢PRRbn#„@vv6"""еkWhµZbÑ¢E¸råŠõT*›ÔÔT»æ$„@ZZüüü Ñhпlܸ±)Ë""ɵnJãÔÔT 22ýúõƒ^¯Gzz:ˆC‡! —.]B\\î½÷^ÄÇÇ£}ûö8xð ^zé%ìÚµ »wï¶wäÈ‘ˆ‰‰±¨Ù5§ääd¤¦¦bêÔ© A^^¢££¡( ¢¢¢š²<"’T“‚ì¹çžCHHZ·þ½[TT±dɼûî»pttÄÁƒñ—¿üÅÜfòäÉðõõ5‡Ù<`1®¿¿?¢££›<ùÒÒR,[¶ ‰‰‰xýõ×Íû:t(æÎ‹ÈÈH¨T<{&ºÓ5éU~ï½÷Z„ôèÑ}ûöÅ©S§jµÚ"Äê<ôÐC`nw-! ª««›2äç磦¦ õøøxèt:4i<"’ÓM¿]BàÂ… h×®]ƒíΟ?6ÛeggC«Õ¢M›6À† ìÚwQQ´Z-z÷îmQ ;vÌ®qˆHnM:µ´%''çÎÃk¯½Ö`»´´4¸¹¹!<<Ü¢Ѝ¨(øùù¡´´o¼ñ&L˜€ŠŠ <ýôÓ Ž©×ëÑ¡C«º··7àܹsM\ É覂ìÔ©S˜>}:BCC»””ìÚµ kÖ¬«««Å¶X<‹‹Ã AƒœœŒI“&ÁÉÉ©Þq ­êu} CS–CD’ºáSËóçÏcôèÑðððÀ–-[ (ŠÍv›6mÂüùó1eÊL›6­ÑqÕj5qñâE=z´Á¶ÆæuµºšF£±c%D$»zGVQQððpTVVbÿþýèØ±£Ív;vì@LL ÆŒƒŒŒ »Ç÷ññ”——7ØÎÛÛ{÷ëõz@§NìÚßòå}q×]=®«º°>mmÉîŒüüñÍ=[‚ki™þص\PeQÙ¶m›]=›dÕÕÕ;v,NŸ>;wZ]h¯SXXˆ‡~ƒÆæÍ››tÄ™3g^^^ ¶ BVVŠ‹‹Ñ§O‹}À€ìÚßìÙ'üb÷üZªüüñ7ξJZ:®¥eºÝk1¢§]íštjY[[‹¨¨(â½÷ÞÃ=÷Üc³]qq1FîÝ»ã£>²y ÊÊʬjUUUX±b¼¼¼0hÐ s½²²§NBee¥¹6nÜ8¨Õj¬^½Ú\B ##>>> mÊòˆHRM¾!öÃ?ÄØ±cQVV†õë×[lŸ8q"ªªª†‹/bÞ¼yøðÃ-ÚôèÑÃ|ŸYzz:òòò.]º@¯×ãí·ß†N§Ã»ï¾kqÏÚû￸¸8¬[·ÎüÁBçÎ1kÖ,,]ºW¯^Epp0òòòpàÀäææÖ{ÝŽˆî,M ²ãÇCQ|øá‡V¥( &NœˆŸþ:Š¢ ))ÉjŒI“&™ƒì¾ûîCAAÞzë-üüóÏpvvÆ=÷܃ììl 6ÌjüºÇµ–,Ydff";;þþþÈÉÉÁã?Þ”¥‘Äšd{öìi´¯¯/L&“]ã >Ç·«mll¬Í[<êÓVhÑŸ¿ˆHDÒc‘ôdD$=IAFDÒc‘ôdD$=IAFDÒc‘ôdD$=IAFDÒc‘ôdD$=IAFDÒc‘ôdD$=IAFDÒc‘ôdD$=IAFDÒc‘ôdD$=IAFDÒc‘ôdD$=IAFDÒc‘ôdD$=IAFDÒc‘ôdD$=ÙåBsOàâZZ¦–¹Ù¥ª¹'p q--SË\ ƒŒˆ¤Ç #"é1ȈHz­›{ÍÉ`0üï§²fÇ­òßÿž oîiÜ\KËt»×RYéàÚ×j=ÄŸØúõë>øà£…?Ö¯_ßàkYBüI•••á³Ï>ƒ¯¯/4MsO‡ˆ®c0pöìY„……¡]»võ¶ûSÝx±Ÿˆ¤Ç #"é1ȈHz 2"’ƒŒˆ¤Ç #"é1Èn³#GŽ 11ÐjµèÖ­¢¢¢PRRbn#„@vv6"""еkWhµZbÑ¢E¸råŠÕ˜*•Êæ#55Õ®9 !––???h4ôïß7n¼¡õ-Z´*• õI“&ÙœcŸ>}lŽ“••…>}ú@£ÑÀßßééévÏáf×sôèQDDDÀÓÓÎÎÎ ĪU«ÌÛëû}«T*Œ9Òb¬æ<6_}õF777¸ºº",, Ç·Ù¶¸¸£F‚‹‹ <==ƒ²2ÛßxiÎcSŸ?õW”šCjj* ‰~ýúA¯×#==Ä¡C‡€K—.!..÷Þ{/âããѾ}{ µZmnۜǦAì—€èzW¯^µ¨•””'''1qâD!„F£QXõ}õÕW…¢(bçÎuEQÄŒ3nh>:N¨Õj«þC† ]ºtµµµv%†.† &î¾ûn‹m±±±ÂÅÅ¥Ñ1._¾,<==ÅØ±c-ê'NZ­VüòË/ ö¿™õTTTˆ:ˆGy¤Ñy^oòäÉB¥R‰ÒÒR‹zs›|PxzzŠòòrsM¯× «õÅÇÇ gggñÃ?˜k;wˆ7ß|Ó\kÎcÓY 1pà@Ü`›ýë_BQ‘žžnQWE$&&ŠË—/ ƒÁФý¾ñÆBQQ\\lQß°aƒPE8pÀ®q¾øâ ѺukqâÄ 1tèPh±=66VhµZQ[[+***êgûöíBQñÉ'ŸXÔ „¢(~çîfÖ³fÍ¡(Š8uê”Bˆ_ýÕ®Wuuµpww÷߿նæ:6..."**ʪ>zôháèè(~ýõWs­}ûö6ÛöêÕK >Üü¼9Mcx¬BàÂ… ~— Ο?6ÛeggC«Õ¢M›6À† ìÚwQQ´Z-z÷îmQ ;v¬Ñ1jkk1cÆ <õÔS¨·ÝåË—áêê wwwxzz"11—.]²š[Ô•JÕè|nf=;wî„««+~øáôêÕ ...pssCBB‚Ík“u>þøcTTT`„ 6·7DZ16¿?ܦMFœ8qPZZŠŸ~úÉê÷]·ŸºãQ7 yŽMcx¬ÈÉÉÁ¹sçðÚk¯5Ø.-- nnn·¨‡††"** ~~~(--Åo¼ & ¢¢O?ýtƒcêõztèÐÁªîíí 8wî\£óÏÈÈÀ÷ßoóÚ]N:áùçŸÇÀa2™ðÉ'Ÿ`õêÕ8~ü8öîÝ‹V­Z™çÓªU+«°vpp€§§g£ó¹™õ””” ¦¦=ô¦L™‚ÔÔTìÙ³«V­ÂÅ‹‘››k³_NNœœœðè£Zmk®cÓ«W/Àd2A¥úíýŠÑhDaa¡E_½^o1æõû)//ÇÕ«W¡V«›õØ4ê†ßËÑ-Q\\,\]]Å_ÿúWa2™êm·hÑ"¡(ŠÈÈÈhtL£Ñ(…‡‡G£§3÷ß¿°ª×ÖÖ EQijÏ>Û`ÿ²²2Ѷm[±|ùrsÍÖ©¥-)))BQ±qãFs-..N´iÓÆfû.]ºˆ‡~¸Á1of=Ý»wŠ¢ˆ„„‹út!áMòIDATÓO?-E%%%V}***„“““Ý×Õn×±ÉÈÈŠ¢ˆI“&‰“'OН¿þZDEE ¡(ŠÈÉÉB±oß>¡(Šxï½÷¬Æ˜?¾PÅ|) 9McxjٌΟ?Ñ£GÃÃÃ[¶l±ùIlÚ´ óçÏÇ”)S0mÚ´FÇU«ÕHLLÄÅ‹qôèÑÛj4TWW[ÕëjýóF/¾ø"Úµk‡3f4:¯ë=ûì³P©Tصk—Å|ŒF£ÍöÕÕÕÎçfÖS·müøñõºç‡²ê³uëV\¹r¥ÞÓÊëÝ®c3mÚ4$''#77èׯ¾ýö[ó'‹Z­Öb [§Î×ï§9Mcdͤ¢¢ááᨬ¬Ä§Ÿ~ŠŽ;Úl·cÇÄÄÄ`̘1ÈÈȰ{|@yyyƒí¼½½Í×Þ®UwÊÑ©S§zû–””`íÚµ˜1ct:Ξ=‹³gÏ¢ººF£ß}÷~ùå—zû;99¡mÛ¶sôööFmm­Õ=LF£ååå Îçf×S·íúÓŸöíۀ͵äääÀÝÝcÆŒip^׺Ç^{í5\¸pÀ×_ÂÂBÔÖÖ€ùö‹ºÓºº1¯ß§§§ùö‹æ<6a5ƒêêjŒ;§OŸÆG}duñ³Naa!~øa <›7o6_ë°Ç™3g^^^ ¶ ÂåË—Q\\lµo0`@½}KKKa2™0sæLtïÞÝü8|ø0¾ùæøùùaáÂ…õö¯ªªBYY™Åëî¯:räˆEÛ/¿ü&“©ÁùÜìzê.bët:‹zݵ›ë—z½{öìÁ#šóØ4ê†OJé†ÔÔÔˆˆˆáàà`õ1öµNž<)<==E`` ¸xñb½í~úé'«Zee¥¸ë®»Dûöí-îY«¨¨ÅÅÅ·?èt:áàà Í5“É$þïÿþOtéÒ¥Áëveee"//Oäçç›yyyâî»ï¾¾¾"??_œ8qBTWW‹ÊÊJ«þsçΊ¢ˆ¼¼~üxáàà ôz½E}ùòåBQ±gÏ›ã5ç±±eãÆBQ‹ë™BüvY›6mlÞG–™™i®5ç±i ƒì6{æ™g„¢("""B¼ûî»V!~ûŸ½K—.¢U«V"55ժ͵7˾ôÒK¢ÿþbþüùâÍ7߯¼òŠèÖ­›hÕª•ÈÍ͵Ø÷ºuë„¢(";;Û¢>oÞ<¡(Š˜6mšX»v­=z´PElذá†Ö8tèP‹b¿ýö[áîî.ÄÊ•+ÅÊ•+Ń>(E>ø UÿÕ«W EQDdd¤X»v­ˆ‰‰Š¢ˆÅ‹ÿáë™ø Õ½q?üðƒh×®èÑ£‡Xµj•HII¢ÿþÂh4Z´mÎcÓÙm6lØ0¡R©„¢(V•J%„øí…_÷ÜV»'Ÿ|Ò<ÞŽ;ÄÈ‘#…···pppbÔ¨Q6ß%dgg •J%Þy狺Éd‹/¾¾¾ÂÑÑQZ½ÐšºÆk?µ¼xñ¢xâ‰'DÏž=…³³³prrbÉ’%¢¦¦Ææk×®½{÷ŽŽŽ¢gÏžbåÊ•·e=W¯^¯¼òŠðõõÂßßßæ¾O:%EsæÌ©w¬æ<6ÿýïEXX˜ðòòNNN¢oß¾"55Õê[%uþýï‹°°0áìì,Ú¶m+žxâ ñã?ÚlÛ\Ǧ!ü7û‰Hz¼ØODÒc‘ôdD$=IAFDÒc‘ôdD$=IAFDÒc‘ôdD$=Iïÿ@.´rÏQ IEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/test_ticks_regression_1.png0000644000077000000240000002700012436367710026252 0ustar tomstaff00000000000000‰PNG  IHDR,,y}ŽusBIT|dˆ pHYsaa¨?§i IDATxœíÝ]Pw¾>ðgŒ‚#¢à ¢h|AÈædݬ›)­[{vSuJªNs·WÞl¹{qꔕ‹ãVmlâ&»•dG#ÁM0 o2 "¾ ˆÃË3Ðÿ þÓ3íÌðâLÓÌó©â‚¦{èþÕ|¿4Ýý{F%‚""zÑ;@D4_lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤lXD¤Á/zä`µZqåÊ466b||111Ø»w/’’’æÜv||_ý5ZZZ`µZ‹@¯×;­{ïÞ=|ýõ×èééAhh(222°oß>,Y²D²ž ¨¬¬Duu5FFF Óé——‡ 6x혟Ƨ¿¿uuu¸sçžDff¦äu¿ùæ|÷Ýwذa²²²022‚ï¿ÿQQQˆŽŽ–mÜñ§ñùþûïQWW‡µk×bÓ¦MÐëõhooGee%âãã±|ùrYÇÂG“““øä“O T*òòò¼~ìþnÑ5¬ ¬¬ ùùùؽ{7ôz=233ÑÔÔ„{÷î!++Ëí¶F£UUUøÅ/~Í›7#66¨®®†ÉdBzzº¸î¹sç099‰ßýîwˆGbb""""PUU…øøx¬X±`2™ðÙgŸaË–-xýõס×ëa0p÷î]Fäää@¥RÉ>.6þ6>aaaØ·oÖ¯_½^øøxdff¢®®=¦M›dGþ6>Ž®\¹‚¡¡!$&&¢¿¿? Ö¢»†e4„ììlqYpp0²²²pÿþ}˜L¦Y·ˆˆÀúõëÅeaaaÈÈÈÀ­[·055˜˜˜@GG233%§ï¯¼ò –,Y‚ææfqÙ­[·0==-[¶H~×–-[`2™pïÞ=y!üm|ôz=BBB$¿G£Ñàå—_F¿ÇÇ»Pþ6>6¨ªªBaa!‚‚]ÙÎÛ¢;òžžèt:§ë¶ë!½½½³nëêZÃêÕ«a±X000èëëÃôô´Ó5µZU«VI~GOO–,Y‚¨¨¨ïüm|ÜAXXØœëy›¿ŽÏW_}…ÄÄD$''/ø˜“E×°FFFá´\«Õ†‡‡=Þvdd\®!ù###®ý‘ƒ¿+]]]¸ÿþ ¹)áãÓÖÖ†ŽŽÌó(¯E×°, ‚ƒo~Ú–Y­V·ÛZ­Öymk±X$ËŸ]×ösO÷Gþ6>ÏÅ矎åË—cÇŽ³‰<üm|¦¦¦PVV†Í›7;¥¢E×°BBB\¾©lË\½Il‚ƒƒçµ­íš‹»u¯Éx²?rð·ñq499‰?þ‹ï¼óŽÛõääoãóÃ?Àl6cÏž= 8ŠÅkÑ5,wÿrØ–ÙNÏ]ÑjµóÚÖv*o;µv]Çßáv½¹öGþ6>6SSSøÇ?þGáðáÃX¹rå<ŽÆûüi|ÆÇÇQQQ¬¬,ŒchhCCC˜œœ attt!‡§x‹®aéõz `bbB²üÁƒ€U«V¹ÝvÕªUèéé NÛ†„„@§Ó¢££$¾¦ÍÔÔz{{%¿C¯×Ãb±àñãÇ Þ9øÛø3Ï/={8tèÖ¬YóÜÇç)ŸññqX,\»v §N¿ZZZ`±XpêÔ)\¸pÁãcV’E×°ÒÓÓ!jkkÅeV«uuuˆ‹‹Cdd$€™¿nýýý˜žž–l;::Š––qÙØØš››‘šš µZ Xºt)’’’ÐØØ(þµ€††X,dddˆËRSS„êêjq™ ¨©©Add$âãã½?³ð·ñ€‹/¢¹¹¯¿þ:ÒÒÒd9îùò§ñ ÇÛo¿Ã‡K¾ŒÃ‡cçÎ²Ž‡¿ñÊ”‡â»ï¾ÃÇ1>>ŽeË–Á`0 77WòÿøãÇQVV†îîn¨Õj¤¤¤   Àåíë7n ²²CCCX¶l¶mÛ†­[·:­çj*„^¯Ç7ß|ƒÑÑQ¬X±õõõxúô)¶nÝŠÿýßÿEOOnß¾ «ÕŠÿþïÿÿýHOOG\\Î;‡Ç#,,Ll4¯¾úªä÷îÝ»|ðŠ‹‹‘ “É„~øk×®ÅÚµkÅõ"##‘““ƒÊÊJñVvkk+º»»qèÐ!Ÿ>4 ±±±HOOw9>?ûÙÏÄõÊËËÑÐЀÿ÷Ÿî–c|ªªªPSSƒ¸¸8£±±Qò:ëׯ÷éµ,Ÿ±;ÖØ7`2™°sçNäææJ^×W5æÍéF áñ“î}}}øàƒ`µZ±uëVñ¡¹ªª*?ýéO‘˜˜(®ÓÚÚŠ¾¾>äää`éҥ䟚šôõõÁd2¡µµÕé+;;[üý¾âOã8רÔÔ†††`2™^XykºÑ‚ *//Nœ8!•J%þµ0HII¯3g:N2¡³³f³Ùi*ËÖ­[a±XÐÖÖ&.“s*‘¿`Ùyܰ6mÚ„ððpüßÿýz{{ñôéSܼy555ضmBBB`2™066æ2.dõêÕNSYlËéõz¨T*§u}5U„èEaÙy|Ñ]«Õâ7¿ù þö·¿áÏþ³¸|×®]âÃn³MEÐjµ0›Í˜šš‚Z­ÆÈÈT*•ÓEBµZ Fã4í%!!Áåk3Ï´DGGÏ9¢»»{GMä;¬1;ÖÈÈΜ9xã7†¶¶6TTT <<\<ÍÜOEfn«ÕjX,§‹ŽŽë:>ì‹©"D/kÌáµ<}ŠŠ £¨¨Hìºiiiååå0 sNE¤Ólÿ»Z×q@äž*BäXcv7¬îîn¬ZµÊiÊBJJ êëëÑÛÛ+>áën*‚F£;~DDAÀØØ˜ä”ujj f³Yò{äœ*ò¬þþ~”••!!!Ar+—Èf³(((p;¹9Pjl>žcÃ"¯yÿý÷_ô.ø5Žç<¾KøÅ_ ¡¡ÁíÏÿã?þZ­Öíz:ÇwZ®Äp1"9°ÆììØ±C¼åZRR‚÷Þ{Oòqß½½½øë_ÿŠèèhâéÓ§¨¬¬Äàà ÛöˆükÌÎㆇ¸¸8ɲîînX,§”AµZ=gʦÅbÁåË—‘’’"þÏŸ••AðÝwßI(F#îß¿_þò—âÜxÿý÷qåÊ:tH|Ýo¾ùaaa8vì˜Øí_zé%œ?wîÜñÚs"DÞÆ³“åVSS8 œ ÁéI)9\ŒÈWµÆ¼þ)žSSShnnÆË/¿,†óÛX,œÉ÷Ðét¸|ù2ŒF£8›[ÉábD¾È5æÕkX“““hmmÅÚµk畵}ûv¨T*ܽ{W\¦äp1"¹zyµaÙ&GÎ÷3È‚ƒƒ¡Ñh`6›ÅeŽábŽ”.F$·@¯1¯6¬ÆÆF,Y²©©©óZbbÂ)õÐ1\Ì‘»p±žž§p³ÙÂÅÙÂÅ_s.ùùùXµj•䫨¨hÞÛSà***rzïäçç/è5¡Æf㵆5::ŠŽŽ¬_¿ÞéÿX«Õêò6kEE 99Y\æ.æÈ]¸Øèè(ZZZÄes…‹MNNŠë>O¸Ø×_ÞÞ^ɧ\Ð|¼ÿþûNï…JÍÆkÝ›››!‚ˇÖFFFpúôi 1·º½½íííHNNFZZš}‡.F$'Ö˜VSSÂÃÑ””äô³¥K—"55hhhÀôô4t:öíÛ'‰nµÙ²e Ôj5*++qëÖ-,[¶ ………Náb*• GŽÁ¥K—pýúuqžÓ›o¾)‰’fNƒõ«_¡¼¼eee EVV–Ó"Åc€ß¼1häÀ÷ÕÂ0^†ˆƒ ‹ˆƒ ‹ˆÃg~€ëOô(((pšÓ(3\ŒH¬1;Ÿø™L&C£Ñ`ÿþýâg¦õõõá·¿ý­dn“RÃňäÀ³óY€ßÕ«WaµZñî»ïŠŸJ‹>úõõõÈÎΠìp1"9°Æì|àg4‘’’"$$%%A§ÓI½”.Fä+Zc^oX®ÂÅL&ÆÆÆœÂ½€™ 0Çp¯ù„‹9®ë.\Ìb±```àG‹J ט×–«p±Ù½´Z-Ìf³Ø©.æî5ûŒò¹ÂÅ\ÍF'òW\c^oX®ÂÅæ ÷¤A`J #ò…@®1ŸøÍîHƒÀ”.F$·@¯1¯F$» ›+ÜK£Ñˆß1\Ìñ”Õ_ÂÅòóóÿ­·ÞbÄ Í©¨¨Ÿ~ú©dÙBÏ<¡Æfã“¿ÈÈH„……9…{3A`Žá^þ.Æ<,z^žæaQc³ñI€0“«ÓÖÖ“É$.ëèèÀàà äq%‡‹ɉ5æ£?ÈËËCss3JJJ““#>…ƒ7ÚwHÁábDrby1ëƒ>À“'OðŸÿùŸP©T.×q5ÏéÀwZ÷ÙyN[·nu fæ9]ºtIüß~¶yNÝÝÝ(//®yNÌ-"9,ä}µØkl>à7OlX$¾¯†ñ2D¤lXD¤^»èÞÓÓƒo¿ýÝÝݰZ­X¾|9²³³Åÿ‰Ýeúèt:?~Üi¹³zˆäÄóRúsç>þøc¬^½»wïÆ’%K088èôÀ™Z­ÆÁƒ%ËBCC^O©Y=DraÍð¸aMLLàìÙ³HMMÅ/ùËY×U«ÕnoÉÚ(9«‡H¬1;¯a555att{÷î03×ÉÝGA ‚ËO¨µQrV‘XcvŸautt 44&“ Ÿ|ò ‚W^y’'r- Nž< ‹Å‚¥K—Â`0`ÿþý’œOVmÕlY=µµµ@tt4ó°HÑXcv7¬LOOãïÿ;²²²€»wïâÇÄøø¸xʨÕj±sçNèõz‚€Û·o£ºº½½½8vì‚‚fNöšÕ“à´OŽY=ÑÑÑsfõtww{: D²aÙyܰ&''a±X°yófÒÒÒ055…ÚÚZìÙ³+V¬pú¸êŒŒ èt:\¾|F£6l ì¬"9°Æì<¾†e‹ZyöBŸíûû÷ï»ÝvûöíP©T¸{÷®äõ”šÕC$Ö˜Ç Ëvjøì\%Û÷f³Ùí¶ÁÁÁÐh4’u³z)!«‡H¬1;–í"›c¤`? W“.m&&&œBÄü=«'??«V­’|Í{{ \EEENïüüü9· ´›Ç Ë–sSWW'Y~ãÆ !!!V«ÕåmÖŠŠ @rr²¸Ìß³zàGÏëyü­ÆfãñE÷U«VaÓ¦M¨««Ãôô4Ö¬YƒÎÎNFäåå!""CCC8}ú4 ¢¢¢íííhooGrr2ÒÒÒì;¤à¬"9°Æì¼/3==«W¯¢®®ÃÃÃx饗$Ù:ããã(--Åýû÷1<<Œééièt: 俿з[ù[Vc@Hó}_BÍ󰿉 ‹äÀ÷ÕÂ0^†ˆƒ ‹ˆƒ ‹ˆÃg~€ë€ü‚‚§9M€2ÃňäÄóÒÖ;wð—¿ücccؽ{7^{í5¤¤¤Hž5™L(..Æ“'O°ÿ~äææ¢­­ ~ø¡Ó4ššœ?111øÉO~‚¸¸8”––âÚµk’õlábMMMضmòóó1::Š’’ JÖµ…‹Y­V"++ µµµNŸÄKäXc3|àwõêUX­V¼ûŒŒÄÆÆâ£>B}}=²³³(;\ŒH¬1;ŸøF¤¤¤ˆ IIIÐét’p/%‡‹É5fç“?“É„±±1§p/`fžT{{»ø½’ÃňäÀ³óø Ë1\lݺuxûí·±iÓ&ÔÔÔàܹs0k¸—V«…Ùl;õBÃÅܽ&`Ÿ:W¸˜«ÙèDþ‚5fç“¿¹Â½€™ÌµZ­èp1"9°Æì|à7W¸ Sj¸‘Xcv> ð³­ã.ÜK£Ñˆ_ÉábDr`Ùù$ÀO«Õ",,Ì)Ü ˜ s ÷ò÷p1øÑó’3Ào1ÕØl|àÌäê´µµI½££ƒƒƒ’p/c€=/9ü€ÅSc³ñI€äå塹¹%%%ÈÉÉÁÄÄ*++ƒ7ÚwHÁábDr`Ùù$ÀÏÆÕ<§¸Ì¤ö·p1摼àg£ä›øÍÉï«…a¼ )))†Çw ;;;ñ׿þÕåÏþõ_ÿ±±±€/¾ø Nëèt:?~Üi¹ÃňäÀ³óZâè¶mÛijY¾|¹ä{µZƒJ–…††:½VMM ¾üòK¤§§#77]]](--…ÅbÁŽ;Äõláb}}}رc‡x˵¤¤ï½÷V¬X!®k ‹ŽŽFaa!ž>}ŠÊÊJ âÈ‘#Þ"Y±Æ¼Ø°Ö¬Y#ÉÌqE­V;͇z–’ÃňäÄóâ5,A011éééY×±­çŽ’ÃňäÄóâÖ¹sç099 •J…5kÖ ??ß)ÌËb±àäÉ“°X,Xºt) öïß/9@%‡‹ɉ5æ…†¥V«‘žžŽuëÖ!,, =Bee%Š‹‹ñ›ßüFœô¨Õj±sçNèõz‚€Û·o£ºº½½½8vì˜øQÚ ³Í£rä.=g¸Xww·§Ã@$Ö˜Ç +>>ñññâ÷)))HOOÇÿüÏÿ ¼¼GìÛ·O²]FFt:._¾ £Ñˆ 6€¢ÃňäÀ³“å9¬+V -- .Ãòm¶oß•J…»wïŠË”.Fä+Zc^»†õ¬ÈÈHLMMÁb±¸}#88f³Y\æ.æxÊê/ábùùùNƒÿÖ[o1b†æTTTäô}žœy,Ö›lOº?yòÁÁÁ³>0611á4hþ.Æ<,z^Ï›‡åÎb­±ÙxܰFGG–õööâÖ­[âsV«ÕåmÖŠŠ @rr²¸LÉábDr`Ùyü/ágŸ}†ÄÅÅ!<<?Fmm-–,Y‚ýû÷˜9M<}ú4 ¢¢¢íííhooGrr2ÒÒÒì;¤àp1"9°Æì<Îú~ý:ššš088ˆ‰‰ „‡‡#11¯¾úª8m`||¥¥¥¸ÿ>†‡‡1== NƒÁ€ÜÜ\ñv«# cnÉa>ï«@©±ù`€ß<±a‘ø¾ZÆË‘b°a‘bø, p_PPà4EPfV‘Xcv>ËÃ2™L(..†F£ÁþýûÅ êëëÃoû[ÉT¥fõɉ5æÃ<¬«W¯ÂjµâÝwßEdd$ 66}ôêëë‘ @ÙY=Drbù0Ëh4"%%EHHJJ‚N§“då(9«‡HN¬1åa™L&Œ9eå3¹:íííâ÷JÎê!’kÌ gX¶¬ž×^{ ï¼óöîÝ‹¾¾>‹;9[VŽV«…Ùl;õB³zܽ&`Ÿ 9WV«ÉDþ‚5fç“<¬¹²r€™¹PjµZÑY=Dr`ÙÉ–‡•šš*fõÌ••Hsu”šÕCä+Zc²=8ºlÙ21«g®¬F#v|ǬGJÈê!ò¥@¬1ŸäaEFF",,Ì)+˜ÉÕqÌÊñ÷¬žüü|¬ZµJòUTT4ïí)p9½wòóóŸûõkÍÆ'yXÀLLE[[L&“¸¬££ƒƒƒ’¬Ïêa€=¯ç ð ´›Oò° //ÍÍÍ())ANNŽønLL 6nÜhß!gõÉ5fç“<,Wóœ8€ððp§×õ·¬Æ€¼•‡e£ä›æaÍÉï«…a¼ )))†×?Hµ¢¢W®\ÁÊ•+ñoÿöoâò/¾ø Nëët:?~Üi¹Ãň|%PëÌ« Ëd2áêÕ« J¥rú¹Z­ÆÁƒ%ËBCCÖSj¸‘/ryµa]ºt ñññ˜žžvzì˜HƒÁ0ëk(9\ŒÈ¹Î¼v ««« F£………à²ó ‚ †¹£äp1"¹zyå kzz/^Dvv6¢££Ý®g±XpòäIX,,]ºƒû÷ï—œ’ÃňäÄ:óRê©©ÁÓ§O±gÏ·ëhµZìܹz½‚ àöíÛ¨®®Foo/Ž;&~2íBÃÅ\þ.`f–xttôœábÝÝÝ >f"_cy¡aáÊ•+ؽ{·Ë²Ù·oŸäûŒŒ èt:\¾|F£6lE‡‹É…u6ÃãkX—/_FXX˜Ë9HsÙ¾};T*îÞ½+.Sr¸‘\Xg3òóóþR¼õÖ[ÌÄ¢9áÓO?•,›Ï¿IXgîxÔ°¢££ñöÛoKB\¾|“““xíµ×°|ùrñ/Á³¯UTT’““ÅeŽábŽé.\Ìh4¢¥¥E •úU –IDAT¹ÂÅvïÞ-Þ-yÞ?Ϊ§çñþûï;ýa³¥5Ì&ëÌVXXÒÒÒœ–WUURSSCCC8}ú4 ¢¢¢íííhooGrr²ä5”.F$Ö™×çÚ8þ5Xºt)RSSÑÑц†LOOC§Óaß¾}ÈÍÍuÚvË–-P«Õ¨¬¬Ä­[·°lÙ2:]pT©T8rä.]º„ëׯ‹sœÞ|óMñ4ÕF¯×ãW¿úÊËËQVV†ÐÐPdee9ÝU!R’@«3øÍƒÖH|_- ãeˆH1ذˆH1ذˆH1|à¸þD‚‚—S ”,FäKZg^=Ú-XÌd2¡¸¸Ož<Áþýû‘››‹¶¶6|øá‡NSjjjpþüyÄÄÄà'?ù âââPZZŠk×®IÖ³‹555aÛ¶mÈÏÏÇèè(JJJ088(Y×,fµZQXXˆ¬¬,ÔÖÖ:=ÈGäï¹Î|àwõêUX­V¼ûŒŒÄÆÆâ£>B}}½øðœRƒÅˆ|%ëÌg~F£)))â @RRt:$ØK©ÁbD¾èu敆5W°˜ÉdÂØØ˜S°0æì5Ÿ`1ÇuÝ‹Y, ühQ`y©aÍ,6[°—V«…Ùl»ôBƒÅܽ&`ŸM>W°˜«™èDþ†uæ…†5Ÿ`±¹‚½i˜ƒÅˆäÄ:›á“¿¹‚½i˜ƒÅˆäÄ:ûÿûâÉÆ¶`±ÂÂB˜L&ÉÎÙ‚ÅBCCç öÒh4b·w süKâ/ÁbÌâçõ¼yXXgîø,À/,, }ŠÉÉIlܸZ­‹F£gÏžÅÐÐvíÚ%®«V«qðàAÉöÏ~†03gêË/¿Dzz:rssÑÕÕ…ÒÒRX,ìØ±C\Ï–ÓÓ×ׇ;vˆw/JJJðÞ{ïaÅŠ⺶œžèèhâéÓ§¨¬¬Äàà Ž9âé0Ɇ5fçqÃZ·nä9`&¢âÏþ3jkkÓ`0ÌúzJÍé!’ kÌN–kX*• ‘‘‘N·QA€ ˜˜˜p»­Rszhfê ¹çÍñ ÔóZòX,Ãàà ~øáܹsGrji[çäÉ“øãÿˆ?ýéO¸xñ"&''%ë(5§‡À¸é9x:>¬1/>8ZVV†ÚÚZ@PP^{í5É)­V‹;wB¯×Cܾ}ÕÕÕèííűcÇ4Ó;šÓ“à´/Ž9=ÑÑÑsæôtww{vðD>ÀóbÃÊÉÉAFF†‡‡ÑØØˆ‹/"88Xœðì“®Ðét¸|ù2ŒF£81R©9=Drcyñ_¨¨($&&"33GEbb"¾úê«YwtûöíP©T¸{÷®¸L©9=DrcÉ8—0==DUH~yp04 Ìf³¸Ì_szlûØÒÒ2çºÊb±àÆ/z7ü–«ñ±½Ÿk`¾[͇l ËÖõŸœéhbbÂiÐü5§§³³pôèÑ9× dse;:wãÓÙÙét}.‹­ÆæÃã†5::Šððpɲ©©)444@£Ñ`åÊ•b2â³°UTT’““ÅeþšÓSPP€3gÎ !!f!CDä–ÙlFgg' Ü®(567¬óçÏcrrkÖ¬V«ÅÈÈ100€Ÿýìg ‚ÉdÂéÓ§a0hooG{{;’““%Y?þšÓÅ'âIsYJ͇Çñ27oÞD]]úúú`6›ŠØØXlß¾IIIfæ"•––âþýûÆôô4t: rssÅÛ­Žžç´uëV—üããã¸téZ[[çœçÔÝÝòòrÎ%$EaÙ1‹ˆƒñ2D¤lXD¤lXD¤²=‡õ"Y­V\¹rGLL öîÝ+^ œae‚  ²²ÕÕÕN§C^^ž×žMY(Ÿþþ~ÔÕÕáÎ;xòä –,Y½^W_}Õi"­¯øÓø<«±±gÏžEHH~ÿûß{tœJ¤>qâĉ½ÞöÏþõõõÈÎÎFff&z{{QYY‰ÄÄD,[¶Ìív‚ àÃ?DGG¶oߎ´´4tvvâúõëÈÈÈ<ÕÛÛ‹ââbh4ìÚµ +V¬À?þˆ‡JR ™œ ï¾û6l@VVFFFðý÷ß#** ÑÑѲƒ;þ4>ßÿ=êêê°víZlÚ´ z½ííí¨¬¬D||¼øy{¾äOããhrrŸ|ò‰øg^^ž×Ýß-º†õàÁ”••!??»wï†^¯Gff&šššpïÞ½Y?™Äh4¢ªª ¿øÅ/°yófÄÆÆ"##ÕÕÕ0™L’'xÏ;‡ÉÉIüîw¿C||<ªª*ÄÇÇ‹IŒ&“ Ÿ}ö¶lÙ‚×_z½ƒwïÞ…ÑhDNNάO*{›¿OXXöíÛ‡õë×C¯×#>>™™™¨««Ã£G°iÓ&ÙÇÄ‘¿£+W®`hh‰‰‰èïïȆµè®aFI¦@#++ ÷ï߇Édšu[o‡•ݺu ÓÓÓNai[¶lÉd½{÷<>æ…ð·ñÑëõNc5 ^~ùeô÷÷{|¼ åoãc300€ªª*º|¦*P,º#ïééN§sº`»2[˜ae===X²d‰øôñBöGþ6>Œ8å5ù‚¿ŽÏW_}…ÄÄDÉ›@´èÖÈȈË1ÇÀ1O·+¬ìÙ´gçÍwäàoããJWWîß¿ÿBnJøãø´µµ¡££cÖù†bÑ5,‹Å2¯À1Wä+ódäàoãó¬ÑÑQ|þùçX¾|ù‚Ó ¼Á߯gjj eeeؼy³ÓYz Zt +$$d^c®ÈVæÉþÈÁ߯ÇÑää$>þøcX,¼óÎ;/$XÑ߯ç‡~€ÙlÆž={p‹×¢kXîþåx6pÌ9ÂÊ"""Ü®7×þÈÁ߯Çfjj ÿøÇ?ðèÑ#>|+W®œÇÑxŸ?Ïøø8***••…ññq ahhHüP‰¡¡!ŒŽŽ.äðoÑ5,½^§9zðà¸Mf´ý¬§§ÏΟ-¬Ì‘-¬ÌñwèõzX,<~üxÁû#`æù¥³gÏ¢³³‡š5kžûø<åOã3>>‹Å‚k×®áÔ©SâWKK , N:… .x|ÌJ²èVzz:A?]˜9Í®««C\\"##ÌüuëïïÇôô´dÛÑÑQI ò\aeŽ¡ä*¬,55AAAb†0S 555ˆŒŒD||¼÷aþ6>pñâE477ãõ×_—ä6½þ4>áááxûí·qøðaÉWBB‚ƒƒqøðaìܹSÖñð7‹îÁÑÈÈH<~üÕÕÕ˜œœÄÐÐÊÊÊÐßߟÿüçâ“Ê/^Äùóç‘••%–­\¹wîÜÁ70==ÇãâÅ‹˜˜˜À¡C‡$·ÙW®\‰üQüÐÉÖÖV\¹r‰‰‰’`³ÐÐPLNNâúõëÁÈȾýö[ܽ{ÿò/ÿ‚˜˜ß üo|ªªªpõêUÄÅÅ!>>}}}’¯+V¸ý„—Å>>jµQQQN_èïïÇ›o¾)6Ð@±è0sVcµZÑØØˆ––DDDà§?ý)ÅuZ[[Ñ×ׇœœñ §R©žžŽááa444 ½½:‡ršB£Õj‘€®®.Ô××ãñãÇxå•WðÆo8XRR‚ƒƒqóæM477#((s~¤¸\üi|jjjÐ×דɄÖÖV§/ÇM÷WZ[[öIwø‘b,ºkXD´x±a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘b°a‘bü?c.ÁìûÄIEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/tick_angles.png0000644000077000000240000003607612436367710023716 0ustar tomstaff00000000000000‰PNG  IHDR,,y}ŽusBIT|dˆ pHYsaa¨?§i IDATxœíÝy|\u½ÿñ×™™Ìd&“L23™ìK·¤ÍÒ¢ òƒGQ@(BõªPDA¼ŠòdQÜ*T~TA½/^å§RDðÜ‹RDZh%[›nÙ“É6I&Éì3ç÷G™¡¥[Ú&9s’Ïóñ˜trrÎ'ÉÌ{¾çœï¢¨ªª"„:`к!„˜* ,!„nH` !tCK¡XBÝÀB膖B7$°„º!%„Ð ,!„nH` !tCK¡XBÝÀB膖B7$°„º!%„Ð ,!„nH` !tCK¡XBÝÀB膖B7$°„º!%„Ð ,!„nH` !tCK¡&-:44ÄÿøG*++±Z­Z”0=ÆÇ!;{jÛ¶¶BuõÌÖs¼ÆÆÀáкŠ#¼<­«8´–¨©™Ú¶ÇòšISÁ`öövV­Z…ÛížÝƒ«xâ‰'T@ò‡ŽO<ñĬg‡&-¬ÊÊJžxâ –-[¦E Ó"pé¥ \u•^xÐ×TUeð7¿aìO¢¸®Ž¬›oCúÇ6ndï?þÁ’ýEQ¦m¿»®¹†%>:-ûRU•]·ÝÆÂÅ‹1]ý´ìsºMþìgôþóŸ8jkÉ¿ùf£ñ mÚ_xÏ/‰íÉ'5¨púlß¾+®¸"õ>žU³‘ªª¾õÖ[* ¾õÖ[Z~ú¼òŠº}åJu||ü€§ý ê¿Î?_íY¹RM´µiRÚ”ÄãêÞåËÕ¡-[¦}× gœ1­ûÚ±CÝ[W§ªccÓºßé”ðûÕž5kÔq†êÿå/øÚøø¸º}åJU}ùeª›>Z¾Óï#_O>üaŒŒÐö›ß ª*±H„]7ÝDÏ5װ쓟¤ø¯EÑâShŠ"_û+Và<ùd­K9*gU«V¹ür­K9,%;›âYöÀô<ú(»Î9‡XK ªªÒöä“,³ÏÖºL]Óä”p.±<ü09_ý*;ìvÂ?L¥ÓI‚ͦuiGæ÷Óþ·¿Qñÿþß´ž ÎEQ¨øÆ7h?÷\ª¶n…÷¿_ë’Ë|Ê),}åFzˆ¦ë®ÃR]MNc#– ´.M÷¤…u‚‹“¿kCÿõ_Ô|ç;ä>óLú‡¸újbþ09¥¥Z—2e9¹¹Ä®¿žÀWh]Ê”äÞx#5ü#ƒ¡ù--6oÖº$Ý“À:N‰D‚öûï§íãG¹ðB껺h/.Öº¬©Ù³‡öž|ç;ZWrÌ|æ3´WT€NZ+í½½,ߺÃc±÷Ϧý´ÓHüýïZ—¥[XÇÁ÷æ›4\pYÏ>KÍÆXÿïÿ%×fƒ_dttTëòŽÊÕUd¬YƒU‡ý¬V+wÜÝ:ˆD´.çˆFGGáå—É5›É\³†Úçž#ëk_£áÎ;ñ]x!è൒n$°ŽA8dû—¿ÌÈu×QÉ%ä¿öJEž/>þ8 ðÚÛÛ‰ÇãÚzê+¯Ðž‘AÅW¾¢u)Ç­â´Óh?ÿ|Ô«¯Öº”ÊÇã´··³ðû߇Çö]‡Ë¿ôRê7mbdùr¶ä#„ï¸ m‹Õ ¬)PU•îi=÷\Êz{YôÏb¼æš7Z¾SI ¯¾Êž={´)t †oº‰œ/~³Ù¬u)ÇÍl6“së­ ¿ñ¤éïzÏž=Tüã˜<žƒn32Xtï½”ýþ÷´¶µÑý¾÷¡>÷œF•ê‹ÖQø»»iøô§1Þsõ÷݇ýé§!3óÐ?þ8y÷܃QQšÝB§@ýÙÏè)+£ì⋵.å„•-X@Ï—¾„úÉOj]ÊA1ä}ï{©ÖÕ¡ØËË©ÿÍo0®[GÃà?ã è윽BuHë0b±;×­£ïßþe Rô¯¡œ~ú‘¿iÙ2X¼˜ÏúQ–ýÏÿÐûñ³ëŸ vÍ5‹ÍRÅú"õªªÒÿ÷¿ÓtÁxž{ŽêçžÃ|ï½SßÁ/‰áþû©Z¼˜;w’H“ëñÛo§ÿýï§ðŒ3´.eÚÑÿoÿÊWÒâ:P"‘`çÎTUUaøþ÷á—¿œò÷šÍf–~ýëä¿ðÍŠBm-êÏ>ƒÕê“Ö~~?M_úáë¯gù•W’û÷¿Ã±vUX´jk±þèG³{÷î™)öXLLÐý ”|ûÛÒp<ãñ2 ”œ~:ÝúÜt“Öå°{÷nŠ‹‹±nØ ìkq£Ü¢"êy„ð#ÐôÔSêëabbªÕ§¹óê=ñxœ¶¶6Ún¸%ƒƒ”oÝŠáÊ+‡?<€Ûé$##ƒÞÞÞé+ö8D¯¾š±|÷¢EšÖ1Ün7c7ßLôÉ'ÁëÕ¬ŽÞÞ^222p;°nÝ1µ®ÞË`0P~æ™,ùÃh»ãÚÓúÎólš÷åóùhll$;;›Ú_ÿšÌ§ž‚½ƒV^¾ïÎÐ7¿Iee%£££ÚõÏêè cÏÊï¾[CpŽ•¢(”WWÓñ¥/Á§>¥I É¿oee%Üw,] K–œð~333©½ür²³³illÄçóx±:7o+ÓÒÒÂÈÈõõõÓ?ÙcÁãÄãTWWÓÑÑA ˜ÞcLAè²ËúÓäº\³~ìÙ’››Køâ‹ z½ðò˳zì@ @GGÕÕÕ(ª ë×ïkaO#·ÛM}}=###´´´‡§uÿz2ïKUUºººhmm¥¢¢‚E‹ÍÌ]³âb8í4¸ãŒF#K—.eçγûb{í5Ú…Êÿ÷Ù;¦F*++i¿÷^øìggí˜áp˜;w²lÙ²}¯¡µk¡¾~ßõ«if4Y´h´¶¶ÒÕÕ…ªªÓ~œt7¯Ëï÷ÓÐЀÉd¢¾¾ž¬¬¬™=àããB$‚Åb¡ªªŠ;vFgö¸ï¿á ×_?ó?gÈÊÊÂpÒIŒ/Y³0F2²cǪªªöuÂM$àÇ?>b¿«é••E}}=&“‰††ü~ÿŒ/ÝÌ‹ÀŠF£ìܹ“¾¾>jjj(**šë9n7|èCpË-Øl6.\ÈöíÛ‰Ít?›Ç§£¤„ÊK/Ù㤑ÊÊJ:Ö®…€|#Çb1¶oßÎÂ… ±%gæøÖ·ö]·,/Ÿ±ã&)ŠBQQ555ôõõ±sçÎYûÔÚœ,UUñz½´´´PPP@uu5³[Ä£ÂOÀ;H³³³©¨¨ ¥¥eæîü$øÖ®Åvë­X,–™9F²X,ØŠŠð}ö³0CAÇiii¡¢¢‚ìäàñDzhÆ[Wï•‘‘Auu5´´´àõzçüi✠¬ÉÉIšššˆF£Ô××ãÐjU˜Ü\8ï<Øo°±Ãá ¢¢‚æææii©ßü&]§œBù‡?<íûNwåååt]}5êÖ­ðæ›ÓºïX,Fss3¾žî¸>øÁcï³7MõõõD£Qššš˜œœÔ¤ŽÙ0·+‘ ~óÍì½øb:::X²d eeeÚw–üÏÿ„ßýö»Kèp8¨¬¬¤¹¹yz›ó7âºãL¦ù7¡¬ÉdÂåv3°~ý´¶²¢Ñ(ÍÍÍTVVV±<òȬ·®ÞË`0PVVÆ’%Kèèè`ï—¿L¼¿_ÓšfÂÜ ¬¿ü…áÚZ½^ë×SSSCæá)϶œøØÇàÆßót‹-¢¹¹yÚÆ&®¹†¾U«(®«›–ýéQqq1}uu$ìvxæ™Þ_(¢¹¹™E‹‘““sào½V®ç„3233©©©Á‘—Gã'?Éðí·§Å°¥é¢ÿÀš˜ ôÑÒ|×]Œ­]Ký¯~…+9GU:Ù°zÚn·S]]ÍŽ;˜˜†!=§ŸNÑí·kߪÔÁ` ¨¨ˆžßýNp6‡‰‰ vìØAuu5v»ýà ^}~ñ‹:ÆLp}÷»Ôÿጵ¶Ò²r%¡ÿù­Kšº~U'x€®~]uuT¾ø" /º(}g"°Ù`ëÖC~ÉjµR[[ËÞ½{>îCÄb1|úž’’ãÞÇ\áñxð'tpxx˜½{÷R[[{øÊ·n§ó¸1“Œùù,|æ*¾õ-v­[G×…’к¬¢ÏÀjme줓hÜ´‰Œ'ž î¾ûÈÒát¿ûËÈÈ ®®Ž¡¡!:;;ënOgg'eeesrαR…²²2:c~)UUéììdhhˆºººÙ¿³<ͲÎ;º¿ü…Œ÷¿ŸÆO|‚1Ïrª¯ÀŠÅˆ^s ­Ÿù ý_ø5ÏVûÿ-æEQ(üÞ÷¨yöYúwî¤õŒ3ˆ¾ø¢Öe3Ýü5ÔgŸ¥oùrZ€¢ÿþoªn¼Q÷Ÿ|‡¢( ¥¥¥”””ÐÔÔÄøøø”¾¯½½Štºv÷Áj]´··OiÛññqššš())¡´´tÎ|î/Ãã¡êé§)ºûnZ~ðú.¸upP벦,ýkhˆÉ}ˆÆ$þÀ,ÿ¯ÿ"'MîÈÌ$‡ÃAmm-G7699I"‘x·#c:H“"²³³I$Gì›”_ÚÙÙImm­v}öfQÎG?Êò?ÿ™øÉ'Óø±1©“ÓÄ´¬ø·¿ÍžsΡ㬳¨~ñEJÏ;oN~êNFF555 šššÛõ¡½½}ßÔ&â*++ÛÊ …B455a0¨©©™“­öÃQ…Òï}êgŸ¥c÷nö|ðƒÄ_zI벎(={nÙÂÐ5×Ð]UEùÓOã\¼XëŠ4£( %%%8NvíÚ…Ó餸¸8Ü£££X,–ÃßÅX­V, £££äææûZU½½½ø|>/^<¯–ÂBjžz ß /ÐxÏ=”®_û‰'ö…M3éÕ …]|1Í7ÝÄøm·Q¿q㼫ýY­VêêêP…ÆÆF&&&Rw³ÒêÚUšª¨¨HÝ}˜˜ ±±EQ¨««›×aµ?ç…R¿iã§žJóºóδ;ML›ÀJ<ú(§œÂ®‚¼ø" ®¼2}ûTiDQŠ‹‹Yºt)ÝÝݼùæ›deeͫӘ㕑‘AVVo¾ù&ÝÝÝ,]ºô€–ªØÇh4²à»ßeÁ3ϰk÷n:O9…ĦMZ—•¢}`uv2zÚi4>ù$–G¡î§?ÅöÞáâf³™ªª*b±ãããtvvÊœßGÇéììd||œX,öîVâ°l%%Ô=ù$–ï|‡Æµk=ïö1jÿô'O=•çŸODãÓDmkd€¶ÑQŠžž%·Þ:/g8^ñxœ¡¡! QÇÊ+0444ÐÝÝ=¯[\ñxœîîn0¬X±dz¯óda!óú÷s¬Lf3KÖ®¥ø÷¿gûž= ^v™fµhXyy,ùþ÷É)*Ò¤=ëêꢤ¤ä€Öhò͸bÅ Ìf3MMMìÝ»7½VŸža¡Pˆ½{÷ÒÔÔ„ÙlfÅŠ©POJvÌíêêÒ°R}Ê)/gùoKâÿoÍjдY#§Ç.‰à÷û{g0ÙâÊÏÏÇï÷ÓÖÖF"‘ °°§Ó9ç~窪âóùðz½ Š‹‹Y°`ÁN—ËEoo/‘HD®e#EQ(8õTÍŽ/ça:ÓÑÑAeeåQƒGQ‡ƒH$‚×륻»»ÝŽÇãÁn·ë6¼’]˜˜˜ //%K–L9|EÙ7ÿû;“< ýÀÒ‘`0H4=x¹£0›Í”——SVV–z£ïÝ»»ÝŽËåÂáp¤}x©ªÊØØÃÃÃLLL¤‚wáÂ…ÇU{NNÝÝ݃A釥#X:ÒÖÖvBCpE!;;›ììlTUerr’ááa:;;1äææâp8ÈÊÊÒ<À’õ1::J<ÇápPPPpÜ!õ^•••´µµQSS3 ‹Ù ¥~¿“Éôî²R'HQìv{jÍX,ÆØØýýý©ª³²²°ÛídeeaµZglª•D"A0drr’‰‰‰Ô@e›ÍFnn.ÕÕÕ3rÙf³a2™ðûýÇÜjÚÀÒUUSˡϓɄËåÂõÎ’ö‰D‚@ ÀÄÄ^¯—`0˜š1Âl6c±X0›Íddd`2™0™L  Š¢‰Dƒ$ ‰±XŒX,F4%‰‡‰D"À¾ð´Z­deeáñx°Ùl³6Uee%­­­©aO"½I`é€ÏçÃn·Ïê-ƒÁp@ ,IUÕ' …ˆÇãÄãqTUMݹëééAQŒF#F£“É„ÙlÆn·§OëHÖãóùRa-Ò—VšSU•îînjkkµ.Ø×²X,G] 5 ±X'×ËÊÊhnnž“Ý>æíÇŠ#êïïÇívËH€d2™p»ÝôÏÁuüæ ¬4Çñz½Éh€WTT„×ë•!;iN+õôôP\\-M˜*++ |æ3ŸI=yÏ=÷ Ù¶m¥¥¥œz꩜{î¹<öØc\wÝuÀ¾þB¯¼ò ýýýØívÎ>ûlÎ>ûl~øÃjòÃèUoo/………2'   éííM½„v ¿þõ¯Q…Ë/¿<õäÓO?ÍêÕ«øsÎ9TUU±qãÆÔs@‹Å’ºŸŸŸ/·‚Q,cxx˜‚‚­K‡QPPÀðð0±XLëRæ=ÃÆ9ãŒ3R{{zzä”SN9hã|àlÛ¶-õo§Ó‰Çãáî»ï¦­­[n¹…•+WÎZñsAWWeee2')ŠBYY™¬e˜ >Ÿï€ÓÁä…÷CMiRTT„Ïç;à:Ö† xðÁY´h›6mbýúõ3_õ‡SËT‰ô–——ÇÄÄápXëRæ5ƒÙlæ’K.I=‘¼Ëw¨%“ýƒö¿xÖYgÑÙÙÉ–-[عs'UUU3\òÜ1Õ5…öö_ËPhǰjÕª>á“k´ê“$9 ô½ë¸9N>ùä£N›+ÞˆÇãdggk]Š˜¢ììlâñxjU!1û ûŸ»§‚û÷ÉJêëëÃårI_¡ip¢k m$×2œÏ&4üù ÿøÇx¢¤¤„üü|¶lÙrÐÆ›7o椓N:ñ£¾sñ2¸sç‰ïK‡ÆÆÆ0›Í²â°Y­VÌf3cccZ—¢‰ÉmÛèýÎw4;¾áPãÖ.ºè"žþyº»»SϽüòËìÚµ‹5kÖœøQËÊè\·Žà<»&\c°¢¢BëRÄqª¨¨ ££cÞ Ù vu±ëË_fÁ{ÎÊfÓ!{*ÞyçØl6Î:ë,~úÓŸrï½÷²fÍ–/_Îç>÷¹i;xå¹çÒzÕU„‡‡§mŸénxx‡Ã1«k Šée6›q8 Ï£×mxd„Ö+¯déš5dœ{®fu2°JKKyõÕWY´h·ß~;÷ß?«W¯æ¥—^šÖëW–Ë.£úŒ3ØþéO™2“k Jiý+--¥»»{^´²"Û?ýiªO=•Ì›nÒ´–Ã.vWSSË/¾8ãX﹇%Ÿû-—_NÍo‹yO­Ò×ׇÇãÁh4j]Š8AF£ÇC__ÅÅÅZ—3c"‘-Ÿù UÖûîÓºœô˜^&ë¿`I4Êö/|H$¢u93"300 k Î!EEE ÌÙµ #‘Ûo¸%Ø~õ+­ËÒ$°²ž{ŽÅ;vÐrË-s2´’§‚ÒItîP%uj8×D"Zn¿ÅÿúYü£Ö夤M`a0õ°ä¥—hùþ÷çÔˆH$ÂØØ.—KëRÄ4s¹\ŒÍ©Ùp8LË}÷±äùçÉzýuH£YDÒ§“‰¬7Þ êñÇÙ¾aÜYj©³³“ŠŠ i]ÍAŠ¢PQQ1gÖ2 …BlÿùÏ©úÙÏÈÚ¼Òìnöa/ºk&'Û?þÁÒ“Of‡ÃÁ’K.!++K몎[0$ãp8´.ĖÃAww7Á`P×'''Ùõì³,ýÞ÷È|ã HÃu1Ó«…•T\Læ¦MÔ|ýëì~ñEü~¿Ö·ööv,X ub†é}-C¿ßÏîW^¡æk_#óùç!M;6§g`ÔÖbþÝ悔á:ÞxŸÏ§uEÇl||£ÑˆÍfÓº1ò²²0Œk]Ê1óù|tlÛFí5×`~ì18Ä\xé"} àÌ31ýÇP{ùåx[[ñz½ZW4eªªÒÞÞ.Cpæ‘äZ†zêLêõzñ¶µQ{饘î¹.¸@ë’Ž(ý®a½×%—`èëcÙųçO¢=ÒÅì‘‘ìv»L¹3$§ Áétj]Î%Ç´ÆÂa–]tÊ¿×^«uYG•Þ-¬¤›nB¹â ò“˜…ÖÖÖ´^ÅDUÕÔÔÇb~IN¥œÎ­¬D"Akk+&ƒÅ—\‚rî¹ð­oi]Ö”è#°~ð8õTJ/¾·ÛMssóAKŽ¥‹þþ~\.&Sú7`Åô2™L¸\.úûûµ.å¢Ñ(ÍÍ͸ÝnJ¯½Š‹á‘G´.kÊôXO<99¸¯¾š ÐÜÜÌää¤ÖU ‘Hàõzçôø2qdÅÅÅx½Þ´; ˜œœ¤¹¹™ à¾õV‚^к¬c¢¯Àxé%èìÄ~Ë-ÔÔÔ°gÏžC®H­•žžŠ‹‹eÁyÌ`0PTTDOOÖ¥¤ ±gÏjjj°ßwüõ¯°ysZõbŸ }U û~Áo¾ /¾ˆyÝ:êêêðù|´µµi~Ý âóùÈÏÏ×´¡=ǃÏçÓ|-CUUikkÃçóQWW‡ù¿Øw øöÛ ÃKú ,Ø7\ ¡zãRUUEff¦æ×µ:;;)//Oû;˜bæ)ŠByy¹¦«ì$¯WeffRUU…áùçáÎ;á­·àÅõFŸ“³¯¥õÎJÔEEETTTÐÜܬIÏøP(D0”5EJ^^Á`P“1±~¿Ÿææf***ÞÒèÇ?†W_Ýw¡]§ôX¥¥ð§?¥þ™Mmm-]]]³>drA!ö7Ûk&gµíêꢶ¶öÀeä6m‚ººY«e&è;°!##ƒššZZZfåqrrUU±ë´™-fŽÝnGUÕY¹›FiiiöÍ<—ã›sïN¬V^^Nss3###3z¼öövi]‰Ãšµ GFFhnn¦¼¼|NO9'+);;›úúzسgÏŒô‹%33“C-—&@ff&V«•ÑÑÑißw"‘`Ïž= P__?çWŸÓû ¨®®ÆápÐØØÈÄÄÄ´í[UÕÔA!ޤ¼¼œÎÎÎi½®:11Acc#‡ƒêêêy±¸‰þ:b'·ÛMNN»wïÆf³Q^^~Â;ÉÍÍ“× ÄôÊÈÈ 77—ÁÁA<Ï í+‘HÐÙÙI `Ù²eójË9ßÂÚŸÙlfÙ²eX­VOhî¢D"Aoo/%%%ÓX¡˜ËJJJèíí=¡Kããã466bµZç]XÁ_êZÕ|+˜Ç•är¹¨¯¯gdd„–––)õJ–5ÅñJv¹éêê:ê¶¡Pˆ––FFF¨¯¯—e☇§„‡b4Y´hѾUCví"''‡²²²C^”D"ŒËÔÇâ¸9Nz{{‰D"‡l-% ºººðûý,\¸P׫FM·yßÂÚ_VVuuuX­V<è6tržvi]‰ã•\Ëð½«ì¨ªÊàà X­Vêêê$¬ÞCë=EÁãñP__Ïää$MMM©»‰@€X,FNNŽÆU ½ËÉÉ!‹€}wÿššš˜œœ¤¾¾Ç#Ї §„‡a4©¬¬$ÓÑÑAww7áp˜êêj­KsDee%;wîÄb±`4ÄŒÜNÔIDAT©ªª’EKŽBZXGa±X¨ªª"//áááTp q"Âá0=== “——'a5EÒšUU`åÊ•„B!víÚEff&åååóú³8v‘H„ÎÎNB¡åååTTTÐÚÚJAAœNÖ “““ƒÙlÆl6SWWÇØØ;wî$33“²²2ùtG‡éêê" QVV†ÃáH}-;;›ááaÜn·†êƒÖQ$'D«¯¯?ày‡ÃÃá`llŒÝ»w“‘‘AYYV«U£JE: ƒtuuF)--= ¨’ÊÊÊhjjÂårI+ë($°ŽÂëõ’ŸŸØ!8Éàš˜˜H-S^ZZ*wç9¿ßOww7Š¢PVVvÄÉF#n·¯×ûîtÆâ$°Ž ÓßßÏòå˺­ÝngÙ²e„B!º»»ioo§°°·Û-K~͉D‚¡¡!¼^/6›… Nyž´¢¢"ðx<2>õ$°Ž §§‡’’’c œÌÌL/^L,Ãëõ¦Æ€Ëú9*‰ÐÛÛËØØ.—‹šššc^õÛ`0PRRBOO̯vX‡F¥¬¬ì¸¾ßd2QZZJII ###ìÚµ EQ(,,$//O®U蜪ªŒŒŒàõzQU5µjÓ‰ü]Ýn7Ék‡!uӲƠ¢(8NœN'áp¯×KWW999ÊEz ƒx½^ü~?¹¹¹,Z´hÚîï¿–áâÅ‹§eŸsÖ!„B!Âá0¹¹¹ÓºßäÜ[åååŒÑÙÙI8ÆåráñxäS5ME£QÆb±PPP@ee匴’sssééé! É:‡ ummm3º Ž¢(äææ’››K<gxx˜;w¢ª*.— ·Û-ᥱh4ÊÐÐÃÃÃ(ŠB~~>µµµ³rA¼²²’ööv–.]:ãÇÒ ¬÷Ç`0ÌÚ(y£ÑˆÇãÁãñ‹Å¯¼¼<\.—|ÒÎ’P(Äðð0###(Š‚ÛíféÒ¥Ç|ýDeee¡( ãããs~œc%õ,Y²D“c›L& ((( 322B{{;‘H„ììlœN'999rÁ~š¨ªŠßïÇçó1>>ŽÙlÆív³lÙ2Í»TVV²k×.êt¾Rót“ÀÚÏçÃf³¥Å0›dgB·ÛªªŒãóùèèèÀh4¦N)m6›Ø©ªJ `tt”ÑÑQâñ8999¸\®»&u¼, 6›‘‘òòò´.'mH`½CUUººº¨­­Õº”ƒ(ŠBNNNª÷|,ctt”¾¾>F£‡ÃANNv»]:ª¾#‘H011ßïgllŒx<ŽÍf#77—êêêY?Õ;VÉ•ËsssÓ*Lµ”Þ±Y400€ÓéLû1ì;uL¶¾`_€ùý~†‡‡éèè@UUl6ÙÙÙØíöyÑ K¶ž&&&' ( v»‡ÃAaa¡.þ¶û3™L8NdÁ“wèë/8C‰}}}S‚“Ž’/l§Ó ì{óƒAÆÇÇéëë# ¢ª*f³™¬¬,l66›ÌÌLÝ™ªª„B!@€ÉÉI"‘Š¢`µZÉÎΦ¸¸«Õª»ŸíPJJJhhh ??_ZÎH`ÐÛÛKQQÑœyA(Š’ ¥ä'³ªªD£Q&'' ø|¾Ô AŠ¢`±XÈÌÌÄb±¤f³yÖ'‰D‚H$B8N=’ýâ’óëgffb³Ù°Ûí‘‘1'ÂéP EEEôööRZZªu9š›÷•ìJ ×ÖÕT)Š’šÏë½q‰ÄÁ0::J$!‰´J±ÉdÂh4b2™0 F ƒEQRÁ166F?ªª¢ª*‰D‚D"A<'‘H‹ÅˆÇã­Ïg0RuZ,ìv;n·‹Å2g>PŽ•Çã¡¡¡A—§µÓm~ÿô@gg'eeesöz* V«õ¨Ã„TUM…L<O…O<OSòûBrÿ K†›ÑhL…žÑhœ×¿û©HNQÓÙÙÉÂ… µ.GSó:°Âá0@`Þ¿¦JQL&Ó”>åðx<³PÕü\Ë0§E·­ÌÏ6ö;’k ¡‡ZËp¾™·599I"‘¡B7²³³I$LNNj]Šfæm`µ··Ïèg!fBr`ô|5/ktt‹Å"sQ ݱZ­X,FGGµ.Eó.°TU¥³³S®] ݪ¨¨ ³³3u7v>™w544„Ãáù¦„neddàp8Òº”Y7¯+‘HÐÓÓ#=†…î•––ÒÓÓ3ïZYó*°¼^/šÏu$ĉ2Ð××§u)³jÞV<g``€ÂÂB­KbZ200@<׺”Y3o«««‹ÒÒR"æ EQ(--¥««KëRfͼ¬H$‚ßïÇåri]ŠÓÊårá÷û‰D"Z—2+æE`uttœð"—B¤#EQ¨¨¨ ££CëRfÅœ¬`0H4Åáph]Š3ÂápF ƒZ—2ãæ|`É1TVVÒÖÖ¦u3nN–ßïÇh4b³Ù´.Eˆe³Ù0™Løý~­K™Qs6°TU¥££CZWbÞ¨¬¬L-B2WÍÙÀòù|ØívÌf³Ö¥1+Ìf3v»ŸÏ§u)3fN–ªªtwwSVV¦u)B̪²²2º»»çl+kNV?n·{ÞOØ/æŸäš•ýýýZ—2#æ\`Åãq¼^/EEEZ—"„&ŠŠŠðz½srÈΜ ¬žžŠ‹‹çí’PB Š‹‹éééѺ”i7§ÞÕÑh”‘‘òóóµ.EMåçç3::J4Õº”i5§+9“¨ Áó¢(”——ÓÙÙ©u)ÓjÎV(" ’››«u)B¤…ÜÜ\‚Á ¡PHëR¦Íœ ,‚#ÄÁæÚ*;s"°&&&°ÛíW"DzI¾'’ï½›%­+!o.µ²tX###X­V233µ.Eˆ´”™™‰ÕjeddDëRN˜®+¹Æ`yy¹Ö¥‘Ö’w õ>dG×588ˆÓé”5…8ŠŒŒ œN'ƒƒƒZ—rBtX‰D‚ÞÞ^JJJ´.E]())¡··—D"¡u)ÇM·ÕÛÛKaa¡ ÁbŠ ………ôööj]ÊqÓå»=‹1<ÛÓÓÃàà §œrÊAà`Û¶m©;N<wß}7mmmÜrË-¬\¹rF ûÛßÈøóŸ±Z­3²!æ«ÕŠùObLG¡e¸æškxøá‡ùÜç>@__À!çD/**ÂçópkÆ <øàƒ,Z´ˆM›6±~ýúi/RUU:¾ÿ}*äB»Óª¢¯Žo|C7Cv >ø ×_=¿ýíoÙ½{wê.ŸÅb9hãäãýïžuÖYtvv²eËvîÜIUUÕ´9üÔS8ÆÆ0æ3Ó¾o!æ3óºu8ššÞ¼YëR¦ÄpÙe—ðú믧N¹uË39sá{OË'Ÿ|ò!CîD©ªJ÷† ”þàÓ¾o!æ=ƒÒo¤{íZ]´² Ø7UKqq1ðî©áþúúúp¹\³:ظïð ÏÖÐ0ÞH-ÊÏϧ¸¸˜üü|¶lÙrÐÆ›7o椓N:ñ£ŽÐíµ$¶n=ìfñh”§Ÿ¦hÆ?¦â°ŠÖ­cà¡‡Ž¸–a¢¡î˜½=4‹•ÈðóŸÿœŒŒ >üápÑEñüóÏÓÝÝÚðå—_f×®]¬Y³æÄêp`ºðB¾ö5ú>úQÔCtbë¾ë.J=”¸.&„x—rÞy”D"tÿô§}Míë£ïc£áßÿŒË.c‰– ˆ5k֍Т¨wÝu—šÔÕÕ¥ºÝnuñâÅêO~òõž{îQóòòÔ+V¨‘HD=Qo½õ– ¨o½õ–FÕžµkÕm§Ÿ®z/½TMŒŽªªªª‘ÑQõíÓNSCC'|<1û´.A£Ds³úöé§«‘Phß¿'&Tïg?«n;ýtµç[ßRãѨªª¾g›éí·ßæà+_ùJ*ÄJKKyõÕW¹ù曹ýöÛ±X,¬^½šõë×Oûõ+ƒÉDñ]wQxë­ô~ýë¼}Á¯XÁØÄË—£¸\ÓzõÅÿñÇö&üèGd´·S>6ÆòóÎòaÛ[Zhmme|||f "MÓÚÚÊöíÛ±¼ò Ë?úQÊŸ}–ŒÍ›á€ÜÜcÚ_ñƒâ}ôÑ´¹KŸÕóÍoRìraX¶ìøv`³Áo~ƒÒÒBþoPÿ‘PöÐßßOCC}}}G#%„žÅãqúúúhhh ¿¿Ÿ2¯—úO}ŠüµkQžy^**Žk߆SO¥Èl¦çÞ{§¹êã£y`Å&&ð½ú*ùøÁ>–ç‘Gð½ð±@`*?1š÷ÃêøÚ×(¯©AÉÏŸ¾VWï{F£‘ÂÂB x½^ÚÚÚÈËË£  `Fæðb¦„Ãaúûû!;;›²²²ƒ‘xgöàé¢TTP^QAçm·±ðƒ£g“¦éë#ØØHÞ_þ2+dzÙl,\¸UUñù|ìÝ»—x<ŽÛí&??_:¤Š´Çdhh£ÑˆÇã™õ…„óy„ž|„°×;kÇ<M«÷G?â¼ó΃YX©( .— —ËE,cpp––L&ùùù8N ÍÏ–Å<–H$ðù| ‹Åp»Ý,]ºÓîîÍ»Ê3Ϥý«_…ÛnÓ¦4,µ¿û·¿­e ˜L&ŠŠŠ(**"388HSSf³™üü|òòò$¼Ä¬H$ŒŒŒ088H$Áét²pá´¹la_·õ´ÓîØ¡Y šVñ¿ý[jN:°X,”––RZZJ(bppžž222p»Ý8N9mÓ*ãóù"’——GeeejÁ—´b0Pù¹ÏÑx¬Ý¦‘6ÕØ€åSŸÒäðS‘™™IYYeee„Ãa†††Ø¾};Š¢àt:q¹\˜Íf­Ë:‰DÆçó¡ª*yyyiÕ’:’Ì/~³†3ŽjXõõšöxY,JJJ())!‹áóùسgÑh”œœœN'ÙÙÙ³zT自ªŒãóùðûýdddàr¹¨®®ÖîšÔ (Z¿Î;O“cëï·¥1“É„ÇãÁãñ¤ú ÑÞÞNFFyyyäååéâÓRÌœp8ÌÈÈ###D£Qìv;.—‹ŠŠ ݰ™4œXë(Š‚ÃáÀñ΢‘H„‘‘ÚÚÚ‡ÃØl6òòòp8³º4š˜}Ñh”±±1FFFX,òòòX´h‘\:˜FXÓÈl6SPP@AAªª e×®]Äb1¬V+‡ƒÜÜ\yë\$att”±±1‚Á &“‰ÜÜ\JJJ°Z­ºoE¥+ ¬¢( 6› ›ÍFqqq*ÀÆÆÆØ»w/‘H„ŒŒ rrrÈÉÉ!++KºO¤©D"Áää$~¿¿ßO4Ål6ãp8$ f™Ö,Ù?ÀŠŠŠ€}ŸÒ~¿ŸÁÁAÚÛÛQU«ÕJvv6ÙÙÙØl6y#Ì2UU Œ3>>N0DQ²²²ÈÉÉ‘SŽÄ`0`0P%õHßëõ¦:Ϫªšz$‰£N·k2™RdˆÚl¶T¸ÎÅ–¢˜ ¬yjÿSÍã‘ ŸýÃ(ù€}s‹———fÉG2ä„8VXâ¸(ŠrÄ™+222ÒsÆ¡kÒSQ¡XBÝÀB膖B7$°„º!%„Ð ,!„nH` !tCK¡XBÝÀB膖B7$°„º!%„Ð ,13{Lë Ä$%fÆoh]˜ƒ$°„º!%„Ð ,!„nH` !tCK¡XBÝÀB膖B7$°„º!%„Ð ,!„nH` !tCK¡XBÝÀB膖B7$°„º!%„Ð ,!„nH` !tCK¡XBÝÀB膖B7$°„ºaÒâ Á`€íÛ·kqx1 vMLݺUë2Ä H¾o“ïãÙ¤I`µ··pÅWhqx1[N>Yë Ä jooçŒ3ΘÕc*ªªª³zD`hhˆ?þñTVVbµZgûðBˆ ioogÕªU¸ÝîY=¶&%„ÇC.º !tCK¡XBÝÀB膖B7$°Ä”¼õÖ[œþù8rrrXµjo¿ýö!·Ý¾};çŸ>ÙÙÙ¸\.®ºê*†††ÚÎëõ²jÕ*ìv;W\q…&…¾H·qT[·nåŒ3Π¢¢‚믿žx<ÎC=„ÏçcóæÍTUU¥¶íîîæ}ï{yyy|å+_a||œû￟òòr6oÞLFFFjÛÕ«W¸ä’Kxøá‡9ûì³ùá¨Å(ôBâ(.¸àÕår©>Ÿ/õ\__Ÿš­^tÑElûÅ/~QÍÊÊR»ººRÏmÚ´IUEýÏÿüÏÔsÁ`PµÙlêøø¸ªªªÚÚÚª–””ÌðO"ôNN ÅQýíoã#ùyyy©ç 9óÌ3yþù癜œL=ÿôÓO³zõjJKKSÏsÎ9TUU±qãÆÔs@‹Å‚Ýn ??Ÿ‰‰‰Yøi„žI`‰£ŠD"‡Be³ÙˆD"455ÐÓÓÃàà §œrÊAÛ~à`Û¶m©;N<wß}7mmmÜrË-¬\¹ræ~1'h2øYèKuu5ÿüç?I$ û>ã"‘o¼ñ½½½ôõõPTTtÐ>ŠŠŠðù|D£ÑÔu¬ 6ð‰O|‚µk×RVVÆK/½4?ŽÐ1ia‰£ºñÆÙ¹s'ŸÿüçÙ¾};MMM\uÕUx½^àÝiF’ÿµX,í#33ó€mÎ:ë,:;;Ù²e ;wî<à⽇"%Žêúë¯çÎ;ïä׿þ5µµµ,_¾œ¶¶6n»í6€Ôu¨äic8>h¡Pè€m’'Ÿ|ò!CNˆ÷’ÀS²víZúûûyíµ×hllä7Þ ¤ZFÉSÁä©áþúúúp¹\tkâXÉ5,1e¹¹¹œ~úé©oÚ´‰²²2–.] @II ùùùlÙ²å ïݼy3'tÒ¬Õ*æ&ia‰ãòä“Oòæ›oòÕ¯~õ€ç/ºè"žþyº»»SϽüòËìÚµ‹5kÖÌv™bŽ‘žîâ¨þú׿òÝï~—U«Vát:yýõ×yì±Ç8ï¼óxî¹çRwáÝžî¹¹¹ÜtÓMŒóþÏÿ¡¼¼œ-[¶È)¡8!Xâ¨öîÝË7ÞÈÖ­[gáÂ…|ö³Ÿåæ›oÆd:øªBKK 7ß|3¯½ö‹… /¼õëדŸŸ¯Aõb.‘ÀBè†\ÃB膖B7$°„º!%„Ð ,!„nH` !tCK¡XBÝøÿ îÕbIEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/tick_angles_non_square_axes.png0000644000077000000240000004625212436367710027165 0ustar tomstaff00000000000000‰PNG  IHDRX,=Í–sBIT|dˆ pHYsaa¨?§i IDATxœìÝy|duïÿשԖڗì{º³Vº{ÀmAETDq…aõÎˆŽŒÄ;üGÔ‹àä\eDÛ¡UtfÜÅÇupa®ÝIeO:ûR•µR{ÕùýªLz^ªëT¥>ÏÇ£Iª+ÕŸTRç¼Ï÷|Î÷«¨ªª"„B!rF§uB!„;,!„Bˆ“€%„B‘c°„B!rL–B!DŽIÀB!„È1 XB!„9&K!„"Ç$` !„Bä˜,!„Bˆ“€%„B‘c°„B!rL–B!DŽIÀB!„È1 XB!„9&K!„"Ç$` !„Bä˜,!„Bˆ“€%„B‘c°„B!rL–B!DŽIÀB!„È1 XB!„9&K!„"Ç$` !„Bä˜,!„Bˆ“€%„B‘c°„B!rL¯uùøÁ~@KK åååZ—#fg¡¶6wÏ—L—^š»ç,%““ÐØ¨uÅM^ÃS÷ÝïÂë_úî–r½§,‰0>>Î%—\BEE…Öåä…¢ªªªuùò•¯|…k¯½Vë2„Bˆ’ôå/™k®¹Fë2ò¢¤F°ZZZ€Í_pww·¶Å¿ÿ=“=DËM7a:ï¼þ>ulŒýûY l4bª«Ãùú×ãø³?C§“³Þ'+ý¥/qø™g°ýÝßQ¹w¯Ö弨¡n ý _кŒãZìë#ô©OÑ|Þyèn¹EërŠN:fí·¿eõûß'61%ÅÕÔ„õÊ+QþôOOøyb?ûã?Nãí·c9‰ïgŽßïçÚk¯Íî‡KAI¬ÌiÁîînÎ>ûl«œ}6‘={øàikhÀöÖ·÷¡©ü€•Ï}ŽÀÄQ›Æ½{9룞gŠ¢ä±è%õ¾÷Ñÿÿþ|ë[T¶µi]ÎK2Ølì-ä÷îÙg³xÞy,Üx#]÷ÝGÙþýZWT|Î=n½UUY#øøã¬}ík˜y„ ·×ÛßNÙõ׃ÑxÌo}ó› 8Àå=Fù+_™çâÅK)¥öœ’ X¢ð”¿ò•ôüŸÿƒÿ¶Û¨Dð^}õæ?$“$œà׿Np}´ÇƒûÏþŒ¦ú'Ê«ª´-z‡H¾õ­ôÅb4>õîš­ËÙ1*[[Ñ8@ï-·à{Õ«Ðÿìg¹í+*Š¢àØµ Ç=÷Y_'øÕ¯2óÌ3è¾øE¼é4Þ?ÿs øÔÕü—aúÁéyä g¥eùBHÀÚ3œu{>ÿyßýnV¾û] ã㬦ӔÕÕá}ç;鏿 &“ÖeîÉ$ñóÎÿk­_ü"—KëŠv·×KÙ¾@ï‡?L·Ï‡ñ¹ç@^çÓRn·ÓpóÍ4Ü|3‰D‚¥ŸýŒ¡§ž"uÕU8×ÖHÔÖ’˜ŸgÏ“O¢ëéѺ\!$` m©‡±öàƒÿðÒŠ‚î׿féÊ+Ùóÿˆ^Žús/"ò²—1pÑE´ß{/V«UëŠv,‡ÃAÛ½÷ÒwÿýtîÝKù³ÏÂîÝZ—µ# ª/ºˆê‹."™Lrèþûq~þó¤kk¿öZ¼.Ž¿üK”n8î©D!Î4Ùƒ‰¼K}ç;,?þ8Á©)¢v;Ž?ù*Ÿx[WÊÄÁ‹.¢·¶–ΛoÆl6k]îÎ15ÅÆùç3tÝut}øÃòÚæÕj¥ëC¢¿¦†ö .Àú•¯À…j]ÖŽFxì1{ ï3Ï ¶´Z[#pà‡ücL?Ž7•Â}á…”ýíßBCƒÖ%‹"KäEüÀ‚=ÆR(´ÙOuÁ4?öæ#çCinÆûÓŸbyÕ«H&ix÷»ñz½Ú½“ü÷³ú–·0þÁâ»õVŒrTŸ7f³ß{Þƒ¿¢‚–ë®Ãùÿ×_¯uYE/ 2õä“tÜwå¿ü%45¡v§ûM7ÁM7F üâô}ã设ÏÒÞK/Åxï½Z—/J€,qÆ„Ãa+++èggñ¾ë]t¾óè_jçÞÐ@ùo~ÃÞ³Îb$•båŠ+hmm•)NÕ÷¾ÇÒm·1}Ï=ô\u•œzÕ€Ñh¤çÍoÆïñPË-x††àŸÐº¬¢”N§#ý­o±÷Þ{Ñ=ÿ|¶ÉýHf³™†‹/¦áâ‹7û¶ÆÆ>tˆäþ€Ë墢¢‹Å’çŸ@” ÙÒŠœQU•µµ5¡P‹Å‚×륡¡ݾ}'÷d55è¢}ï^ þÅ_ÐÞÞ.ÓõùÏ3ï½ÿéŸèyÃ$¤jH¯×ÓsÁôõ«$n½•êÁAøú×µ.«¨„Ãa†††¨û᩼ï>8xNðªbƒÁ@uGÕ¤ÓiVVV˜žž&c³Ù¨¨¨ÀápÈ´/"g$`‰Ó’J¥X^^&DZÛíTUU±k×®ÓßPUT@o/•{öàH$¼â <uuu²<wßÍô¿þ+¡'ž ûU¯’׬èt:ºÿôOüÒ—H~èCÔŸ{.üú×2ÃKPU•™™–––èúÎw0}ö³ÐÛ»¹8:ǃÇãAUUB¡Á`Çc4©¨¨ÀívSVV–ãŸD”yW‹“Ç ƒ,--‘N§ñx<´´´œ™¦iúû1ù|ì‰Ç™¾í6:D{{»4i¿õÝïæðÐéýûéðù$\EQèèìdì¿ÿ~šwïFyþùÍ¿uq”h4ÊÐÐn·›=O?òØcà÷çlÚ EQ°ÛíØíöìÿèëëË1¯×+}‹â¤IÀ/IUU"‘H¶ŸÊ`0àõzéììÌO?Ãýý(==4ÄãxþáÄëõÊhÖ‘ÒiÔ×¾–a³óþý%µ,E1Q…]»v1yç 74ÐÖÙ‰òŸÿ ²„WVfÔ* ÒÖÖ†åã‡'ŸÜ WÇûÍf3 444L&YZZbxx˜d2)}[â¤HÀÇt¬~ªŠŠŠÍ~*-úxl¶Í ëž=Xb1ö>ø 333JEE###˜L&ZZZJ·g" uöÙøßñjŠSìMùW[[‹áMo¢Ïë¥ûª«(»ç¸ùf­ËÒD*•b||œX,Fgg'&“ n¿þýß7Õ†#G:·ÛÛíFUU666Ò·%ŽKV‰ÛÚO¥ª*n·ûÌõSå‚Ù¼²öíƒë¯ÇôÅ/âóùXZZâàÁƒÔÕÕQYYY0_††Hœ>þ÷¿Ÿ¦[oÅ%K²ŠŠ ÊÎ?ŸÞ¯}îw½ ÃÐ|úÓZ—•7ªª²¸¸ÈÌÌ MMMx2ýh·Ý?úÑæ{¾€¶IŠ¢`³Ù°½0šF ƒøý~¼^¯ôm X¥FUUÂá0Á`P›~ª\0áÐ!8ë,¸æøÊWðx<¸\.&''9tè---Ù¦Õí¿ vÅøÿñÙýÎw–ÆÏ¼C¹ÝnôçœCß7¾A×_ý¦¡!xúiØáSk¬¯¯3>>ŽÃá`ß¾}lA¸áøÅ/6ÃU³ÙL}}=õõõÙ¾­‘‘‰.— ¯×‹Åb)­?!«¨ªÊêê*@€ íû©rA¯‡?üÎ>Þþvøú×Ñét477‹ÅGUUZ[[7O3ìD¹ýv~˜Ž¿ø i¼Ýìv;í{öàÿÒ—è¼ë.ÊÏ>ž{®àÆ©ˆÅbŒm^UÙѱý}zíµðûßoNÅP,~/8VßÖÌÌ áp«ÕJEEN§SÂV (®¿\qÂR©KKKƒÁl?UMM V«uç¼±uºÍðË_ozÓfŸ`2™èìì$ 144„Åb¡±±ƒÁ qÁ¹úÒ—~â º/¼pç†Èd±Xèöùðò“´}ï{ØÒi­KÊ©D"Áää$áp˜–––ìi¶¬w¼úû7 Š,\éx}[F¼^/Gú¶v¨âþëÛÄb±l?lžrØÑ#8°²ž{nótB4º­OÃf³±gÏ–——ñûý8NvÄÆlee…‰O|‚žîîÅæABOO~ަhWõªT*ÅÔÔ«««466²k×®£o†ªÿþïwjôȾ­X,F ÈömeæÛÚÑÛë#«ˆeú©«««Ù~ª®®®âé§Êžxâ¸ÿìv»q¹\ƒA:” ¾XƒV0dvv–žžž¢ýÄK3 ›!Ëï'•Jí¢ç©T*; {}}=MMMÇE7aÿþü¨“ÉtTßÖèè(‰D§Ó™okÇœq(A%´ÞŽì§²Z­x½Þßh E¡¢¢¯×K àСC¸ÝnêêêŠ*ŒÎÍͱ´´„Ïç+Þþ9qÂÊÊÊðù| H$¨©©Ñº¤–L&™™™ayy™ºº:öíÛ'Û¨ã8VßÖììlv/}[Å©xö,%,™Lfç§ÊÝì¸~ªøAê.½Tú©J„Éd¢©©‰¦¦&B¡ Œa·Û©ªª:©«yÖ××Íé(„(åååtwwÓßßÏ®]»N¸W0sõòÂÂëëëØívjjjdô´dû¶þîïP︃ðò2Áþg&ÀðÀx Ÿ¬+(N™ÉdÂçóá÷ûillÄívóq™¿Ñ@ Àúú:6›ÊÊJZ[[åÀ°D)Š‚ÕãÁúÐôÇ ~ûÛ |ë[¨o|#îHï¹çbþࡳSër‹†¬“L¢~å+l|éKÖjk1¾üåT|êSt·¶J?•8Š¢(8ªª …X\\dllŒòòr***p¹\Ù^–@ ÀÜÜœ¬+(râÈõ +**€Í)?VVVD"ìv»„*q\F£‘Ú+® öŠ+H¥R,?ÿ<ã_þ2ñÛnñ´DEs3Ö›oFyãåTâ‹€u¤µ5Òÿû³òïL¥·´`{ë[©xç;iÎa3³ØùEÁn·gOׄÃa‚Á ÓÓÓèt:R©ªªJó°È©Ìú…dff†²²2Òé4.—K®'­¬¬ŒŠsÏ¥âÜsQU•µÙYæŸx‚Ð#`ùû¿§ÂfÃyÅèn½Ìf­Ë-(°FFH~úÓ,ýêW,’¸î¼“ú7¼A6F"g, ‹…ÆÆFFGGYZZÂf³qðàA¬V+n·—Ë%#Y┤R)VVVX^^fcc“ÉD(ÂëõÒÚÚªuybPg]λî  øÆ7˜üÁÐÿË¿àÇñþùŸ£ÿÀ ©IãjµWºë?þƒèÃbÙëE÷'‚ç±ÇhûÓ?•~*qƨªÊØØ:ŽsÎ9EQ².//3;;K:Æn·ãr¹p8¸Ä1¥R)ÖÖÖXYYa}}N‡ËåÚ6q±ªª>|˜ÑÑQ9(rÎb³ÑôîwÓôîwoömýò— 8@ú]ï½²BEg'æ÷½^ýj­KÕDi¬H€é¿üKÊÚÚ0¿ò•xï¿_S“ìÄħª*ƒƒƒØl6êëë³÷o°¡¡!Û„œYãMUU¬V+N§‡Ã!ð%*‘H°¶¶Æêê*Ù~?¯×{Ü…•E¡¥¥…ééiéèè%ΣÑHí…R{á…›}[££~òIbÿ8ŽÙY6JpࢴÖ s 9{Œ}^(‘7™u3³À¿˜­ò@¶Y~uu•ùùy’É$F£1ûYÜuçÉLŸ°¶¶ÆÚÚñx½^Ãá8¥æôúúzæççñûýtuuIÏŸ8£ÊÊʨho§âcÛìÛZ^æÿ}æ3ðÛßj]Z^•VÀzÝé”’È›d2‰ßï§¾¾ÇsÒßd³6óú™Íf\.WQ†ÐòòòìÒ:­­­Ù‹*„¹!KˆZ^^fjjŠžžž¢l"Þ¾Ž×3–J¥¶h4Êúú:ñxœD"±-ˆdž³¬¬ ½^¿í£N§Ë~ÜzS%û1X23ÿ_f´MUUTU%Ng?n½¥R©ìÇd2¹ícæ92t:ƒ!3§ó2²Xƒã‹1ôôôÐ××÷¢ë !N^ñí„(P‹‹‹,,,àóùväÎ8£¬¬,{ ìD¨ªJ2™Ì›­·t:Ú’2Á)sËXZZbrr À2·­á,Þ2anëM¯×£×ë‹j´éLÒëõôôôÐßßO2™Ì^8!„8=°„È™™ÖÖÖðù|²ã>‚¢(ÙÓ‡§+ÒÞÞžƒªÄV™õ H$ÔÕÕi]’EO.â4d–" ‡ÃtvvJ¸EKQ:;; ‡Ã>|ø¨S¨Bˆ“#KˆS¤ª*###ìÞ½[•(zŠ¢°{÷nFFF$d q$` q TUe``‹ÅBss³„+±c(ŠBss3‹… YBœ" XBœ¤T*E__^¯WzUÄŽUWW‡×륯¯T*¥u9B XBœ„d2I__uuurµ•Øñ*++©««£··—d2©u9B XBœ x~±CeÖL§ÓtttÈììB¼EQèèè`llŒññqYÕ@ˆ-ò°^ùÊWòÊW¾rÛ}?ÿùÏ ‡Ã\sÍ5Ùû>ñ‰O‰Dxþùçihhàå/9¯{Ýëxâ‰'¸é¦›ˆF£üä'?a~~›ÍÆE]ÄE]$Kœ2UUÆl6ÓÒÒ¢u9B EQصk“““ ÓÖÖ&!K4ìÁÚ¿?Š¢põÕWgïûÆ7¾Áe—]– W_|18p {_8Æd2a³Ù€ÍÙ†C¡PþŠ;J:¦¿¿›ÍFcc£ÖåQ”±Ùlô÷÷“N§µ.GÍi°‰à¼óΣ©© Øì{Y\\äÜsÏ=êñ/{ÙËxþùç³_{<ªªª¸ûî»ãŽ;îàüóÏÏ[ýbçȬ+XYY™=U-„85µµµTTTÈú…B§S„GúÁ~ÀÒÒÒ¶Óƒ™F÷cíäjkkYZZ"‘Hdû°yä.¿ür>þñÓØØÈ~ô£ü/vŒD"ßï§±±Q–¾"G*++ÑëõôööÒÝݽ­wVˆR¢IÀÚ¿?F£‘w¼ãÙû2WšL¦£Ÿ™à1‰d߬¯yÍk˜˜˜`xx˜={öóû„8žX,F?»víÂn·k]Ž;ŠÛíF¯×Ó××GWW—lŸEIÊû)ÂP(Ä¿þë¿rÉ%—l5(//6w|GŠF£Û“át:9çœsäÍ+NJ$Áï÷ÓÞÞ.áJˆ3Än·ÓÞÞŽßï—itDIÊ{ÀúÖ·¾E$ÙvzþxjpëœX³³³x½Þœ 5«ªš“çÅ' 100@ww7‹Eër„ØÑ, ÝÝÝ È…H%LUUVž{Në2ò.ïë+_ù v»7¿ùÍÛ¯§²²’ßüæ7G}ÏsÏ=ÇYguúÿù kg ß~;k¿ûÝé?Ÿ(*«««ŒŒŒÐÓÓ#£žBä‰Éd¢§§‡ÑÑQVVV´.GäÙÚï~Ç¡Ë.#üðÃZ—’wy X‹‹‹<óÌ3¼õ­o=æÂ¹o{ÛÛøö·¿ÍÔÔTö¾ÿøÇ qå•Wž~N'-çŸÏü-·ÐwõÕlÈ Ä%! 299Éž={¤éVˆ<3 ôôô055E0Ôº‘ÓÓô]}5ó·ÜBçe—Q÷¥/i]RÞå5`=õÔS¤R©£NfÜu×]X,^óš×ððÃóÉO~’+¯¼’}ûöqýõ×ç¬ÕWÒþÜs´ÖÖ2ñ–·Ðÿ7CT†¯w¬ùùyæççñù|”••i]Ž%©¬¬ ŸÏ—}?Š) Ñÿ¾÷1ñ–·ÐZ[KûsÏa¼í6­ËÒD^Öþýû©®®æµ¯}í1ÿ½¡¡Ÿþô§ìÞ½›;3ûî»Ë.»ŒýèG¹uÐé(¿ÿ~ºŸ}–†…F.¾˜¡{î9f“½(^SSS¬®®Êº‚B€Ìú…«««ÛÎTˆâ‹ÅúÔ§¹øbæçé~öYÊï¿Jx»›×i~ùË_¾äc|>ßÿþ÷óPÍ l6lO=EÏÄk×]ÇÐ÷¿ù†hºæŒFcþê9¥ª*ããã´··ËÒBEQho’v IDATog||œ±±1ZZZäýYÄâñ8ÿò/D?÷9šÇÐܬuYA“y° RSŽgŸeϯ~Åêm·1øÕ¯bþÀhºøb ZEFUU†††°X,Û–]BEQhmmejjŠ¡¡!9*Bñxœ‰gŸ%zÿý4ÎÎâ|ä8ï<­Ë*(¥;vw<¯zÎÿþoö\=•ï{ƒW_Íðý—œ:,™u‡„+! \CC‡CÖ/,"±XŒáçžcðÚk©¼í6ö¼ë]8ÿð WÇ ëxÞùNœìÙ·ª+¯dø¯ÿšÁƒ³“žŠÂ“YW°ªªŠšš­ËBœ€ššªªªdýÂFìíeøöÛ©zûÛÙãóá‚k¯Õº´‚%ëÅètp÷Ý8†‡éI$¨{ãýøÇé÷ûÙØØÐº:±E"‘ ··—††¼^¯Öå!N‚×륡¡ÞÞ^‰„Öåˆ-666è÷ûýÔ§¨»äzB!ƒƒðÑ–tû‰¬a4ÂO`[XÀwõÕ„Ÿ|’É}ˆä…ÒØØˆÃáк’‹Åðûý´µµa³Ù´.Gq \.×¶E¢e2`m­­­199‰þ¿ éŸÀÒÒ¿ý-ÈÙ&ëdTUÁ3Ï`9tˆÎ«®"öàƒL}êSno§¶¶¯×+šy‡¤³³ó¨µ*…ÅÅf³ÑÙÙ‰ßï§££C–³Ê3UU ƒÌÎÎb§íCÂðôÓpöÙZ—Wt$`Š={àÐ!Lßý.»o¹…dM 3=Äôô4UUUTWWËœKy°¾¾Îèè¨í ±ƒ”——ÓÝÝM?»ví’Ùó N3??ÏÂÂîXŒîÛoG?1? o}«Öå-I§ãÒKarýu×Ñô¦7±÷#A …8xð cccÄãq­+ܱVVVÃçóI¸b‡1™Lø|>ÆÆÆdýÂ3(366ÆÁƒQ"ö~ìc4½ñ诸¦§%\& X¹ð7ssèvï¦æG?bß¾}¸\.éïï—Uäs,055EOO¬+(ĵuýÂ@  u9;J(¢¿¿ŸÁÁA\.ûöí£æûßGçõÂü<üÝßi]⎠§sE¯‡@Ün7n·›p8Ìôô4Ñh”êêj***äôái˜eeeŸÏ'¯£;\fý‰µµµZ—T´Òé4@€ùùyÌf3MMMÛ{ÜÞû^íŠÛ¡$`a‹…ööv’É$sssÌèè(­­­²xªª²ººÊÌÌ ªªR[[KSS“¼fy&+ÏEÁãñàñxˆF£ÌÎÎrøða¼^/ÕÕÕÒStUUÄf³Q__¯u9B(ŠBKK ÓÓÓ ÒÑÑ!á‰D‚ùùy‚Á ‡ƒ]»va6›µ.«dIÀÒÙl¦µµ•t:M0d``½^OMMŒjñÇu3áS!êë뙟ŸÇï÷ÓÕÕUò½˜™Ñª¹¹9’É$ÕÕÕìÝ»·ä_—B «èt:*++©¬¬Ü6ªåv»©©©)É^­d2‰ßï§¾¾Ç£u9Bˆ’íÏÌú^Š=Eñxœ¹¹9–——q8´´´ÈhU)½¿Ê—ÕRU•¥¥%†††€Í ŠÇã)‰£’x<Žßï§¥¥§Ó©u9Bˆäñx(++ˆ¬R8M§Ó,--1??l.”ÝØØXòg; •¬¥( ^¯¯×K<gaaƒbµZ©©©Ù±kîE£QúûûiooÇjµj]Ž¢€9NÚÚÚèë룫«kÇŽà„B!æææØØØÀëõÒÞÞ^²ØIÀ*F£‘††X__ϾÑ<UUU;f&ó †††d]A!Ä ³Z­tvvX,ÆÂÂKKKX­Vª««eÙ "#«ÈØívìv;étšååeFFFH§ÓTTTPQQQ´½kkkÙ¥oäÈLq2ÊËËñù|øý~Z[[q8Z—tJ’É$@€@ €N§£ººšúúú’h Ù‰Šso,ÐétÙSˆ™7e?:Žªªª¢ê×Z^^Î.}S¬Q¡-£ÑHOO}}}466âv»µ.é„dúª²Ë]]]²-Üä7¸d¦v¨©©Éök:t£ÑHUU.—«`ÃÖââ" ø|>ÊÊÊ´.GQÄôz====ô÷÷“L&©¬¬Ôº¤cJ§Ó¬¬¬°°°@<ÇãñÐÖÖ&£÷;Œ¬fk¿V4eaa©©)L&•••¶fffX[[ÃçóÉU0Bˆœ(++£»»›ÁÁA‰uuuZ—ü1T-..‹Åp¹\2µÂ'kË,èÙÔÔD$aqq‘©©)ŒF#•••¸ÝnM–ªªLLLH$èìì”p%„È)NGgg'###>|X³eb2½²‹‹‹Äãq\.MMMrO‰€U"ÊË˳a+²¸¸Èôô4ƒŠŠŠìœ2gšªªŒŽŽ¢×ëÙ½{·„+!Ä¡( »wïfbb‚ÑÑQvíÚ•—íM*•bii‰@ @"‘ÀívËHU‰’€U‚Ìf3466Ç øýþì:‰^¯÷Œô¨ªÊÀÀ‡£`†í…;—¢(477333ÃÀÀÀ1ÇãƒA–––PUÇÃîÝ»¥§ªÄIÀ*qF£‘ºº:êêêH&“,--122B"‘ÀétRQQÅb9íR*•¢¿¿ŸÊÊJªªªrT½B¼´ºº:ôz}vBÒÓ­WU•p8L `uuƒÁ€×륳³S®þYò— ²ôz=UUUTUU‘N§Y]]evv– , —ËuÒ'YWP¡µªªªlÈ:•õ S©+++,--‡±Z­x½^ æÂ!QX$`‰cÒét¸Ýîì\2áp˜`0ÈÌÌ Š¢àv»ñxE¡££ƒÑÑQÆÇÇinn–uqZ$`‰S¦ª*###FZZZròœz½Ç“í…PU•P(ÄÚÚZv†yƒÁ \V«UF¹„ØÒé4Ù@µõ½_YYIkkkÎÐÖõ ‡‡‡ikk“%N™,qJÒé4¸\.jkkÏØÿ£( v»»Ýž¶Ç㬯¯GUUÊË˱Ûí8iž¢ÈdšÑ×ÖÖX__'‰ ( 6›-¨ò9zÝÔÔÄìì,ýýýtvvÊAœ8%°ÄIK¥Røý~ª««³½Tùd4ñz½x½^àçõõufffˆD"ÙÐe³Ù¤^ˆ‘iD…BÙ0|¿ÊT™SŽ™¥ud¢Qq²$`‰“’H$ðûý466f—ÑÑÚÖ¹¸ª««íñÙÙY"‘ªªb6›±ÙlØl6¬V«l4…8ƒR©„B!B¡ÑhEQ²aª¶¶¶ ~*++·-­s¢MóB€,qb±ýýýìÚµ »Ý®u9/JQ¬V+V«u[èŠF£„B!–––˜œœ$•J¡×ë³µZ­˜Íæ‚Ýà Qˆ2ï­ì-™LRVV–}_566å{ËívgG²ººº0™LZ—$Š„,qB"‘tttíB§™#çòòòm§6“Édv§°¼¼L4EUUŒFcvç`±X0™LE·s"—TU%‹‡³ï™x<Ž¢(˜Íf¬Vkv©™Ó¹¢¯ÐØívÚÛÛñûýtvv¾ä"÷B€,qB¡ÃÃÃtwwïÈ£7½^Ÿì4CUU‰Dv'ˆÅbÙÇgNI–——c±X¤ Vì(étšp8L$!‡I&“˜L&, 6›êêj CIxX,º»»ñûý´µµa³Ù´.I8 XâE­®®røðazzzJªÿ@QŒF#F£ñ¨^³D"‘Ýé,,,‰DH¥R(Š’ÝùdFÊÌf³„/QÒé4Ñh”H$’ R±X UU)++Ëþ »\.êêêJêý<&“‰žžü~?ÍÍÍÛÊ„8’,q\Á`ÙÙYzzz¤|‹­ËûlµõôIfAÙÌéFؼúÑl6c6›³á«TŽþEþeFa3!*F‰ÇãÙÓz™QØŠŠ 9 ~ C6d%“ÉìÕÌBI–8¦ùùy‚Á >ŸOF`NPf‡e6›ú·ÌÎ.³£Ë„¯ÌÎþÀL&&“ ³ÙŒÑh”p+Ž)•JljF£Äb1b±Øqÿ¦Ìfsvu õ§¯¬¬ ŸÏ—]¿0s![IÀG™šš"¿äº‚âÄm=åx¬Ó ªªdz;ÉP(D0$‹‘N§³Ïa00˜L¦m ƒá"N“H$²[?&‰ìˆ¨N§Ë†q“É„ÛíÎþ=ÈûöÌˬ_844D"‘ ¡¡Aë’D‘€%²TUe||€öövÙHçQ¦Ëd2áp8Žù˜Lۺà …BÙû2;^Ø<Â΄1ƒÁpÌ›ü~ó#3zy¬[&4¥R©ìã·†ñÌÍn·g?—ß[áP…öövÆÇÇ£¥¥E~?"K–6wCCCX,9+P[CØKÍC–9}´uG‰D²_'“Ém 6ÈõzýQ·²²²ìÇ­Ÿëtº¿3QU•t:M*•"™L’J¥¶}žL&ºeF3EA¯×o ·&“ ›Í– Ár¸x)ŠBkk+SSS ÉÁ©È’€%²ë ºÝnjjj´.GäÀÖ«ÀNÔ‘!óu&œm ™Û‹QN—½e¾ÞúñÈÏ3ß·õó­VWW™ŸŸÏ~ ‰ªªõy:>êó­3·#ƒæ±^Ë­·­¡³¼¼<ûùÖ@*JOCCsss²~¡È’€Uâ2ë ÖÔÔPQQ¡u9BC™‘«¹ÎŽ 2Ç 9™´õ–ùÞ­ÁçÈtd;Ö×G¸­ ~BäBMM¬_(²$`•°Ìº‚MMM¸\.­Ë;Œ¢(ÙЖ+ rÅ–(h²~¡@Æ0KT,£··—]»vI¸Bˆr¹\ìÚµ‹ÞÞÞì ¢ôHÀ*Aáp8»¦–,÷ „¹g³ÙèììÄï÷‡µ.Gh@V‰Y__ghhˆîînY°T!Πòòòì\YëëëZ—#òLV YYYall ŸÏ·#mBˆBc2™ðù|Œ±²²¢u9"$`•ˆ@ ÀÔÔTÉ-Ú,„Zˬ_855E к‘'°JÀìì,‹‹‹ø|>¹lX!4Y¿pqq‘ÙÙY­Ëy k‡›œœ$ ÑÕÕ%ß !„†t:]]]„B!&''µ.Gœa²ÇÝ¡TUett”T*E[[›L¦(„@QÚÚÚH¥RŒŽŽ¾äJ¢xIÀÚTUepp“É$‹ !DQ…––L&CCC²v( X;L:Æï÷ãr¹¨¯¯×º!„ÇQ__ÓéÄï÷µH¸(~°vd2Ioo/ÕÕÕ²œˆBÌöº··—d2©u9"‡$`íñxœÞÞ^šššðz½Z—#„ây½^šššèíí%k]ŽÈ X;@4¥¯¯Ý»wãt:µ.G!ÄIr:ìÞ½›¾¾>¢Ñ¨Ö刀UäÂá0ýýý²® B¹Ìú…ýýýlllh]Ž8M°ŠØÚÚCCCø|>YWP!v€òòr|>ÃÃì­­i]Ž8 °ŠÔòò2ãããôôô`4µ.G!DŽFzzzgyyYërÄ)’€U„™™™¡§§½^¯u9B!rL¯×ÓÓÓÃÌÌ ‹‹‹Z—#N¬"333C0”u…b‡+++£»»›`0ÈÌÌŒÖ刓$«H¨ªÊÄÄáp˜ÎÎN™]!J€N§£³³“p8ÌÄÄ„Ìú^D$`̺‚ªª²{÷n WBQBEa÷îÝÛö¢ðIÀ*pªª200@yy9ÍÍÍ®„¢)ŠBss3ååå HÈ*° X*•¢¯¯ÇC]]Öå!„ÐX]]‡¾¾>R©”Öåˆ!«@%“Iúúú¨««£ªªJër„Bˆªª*jkkéëë“õ ˜¬”YW°¹¹·Û­u9B! ŒÇ㡹¹YÖ/,`° Lf]Á¶¶6‡Öå!„(P‡ƒ¶¶6Y¿°@IÀ* ô÷÷ÓÕÕ…ÕjÕº!„ÎjµÒÕÕ%ë Xbmmááa|>f³Yër„B ³Ù,ë X`ii‰Ã‡˺‚B!NIfýÂdz´´¤u9 Xš[XX`nnNÖBqZ2ëÎÎβ°° u9%O–†¦§§Y^^¦»»N~B!NN§Ãçó±¼¼Ìôô´Öå”4Ù«k@UUÆÇljF£tttÈììB!rFQ:::ˆF£ŒË¬ï‘€•gªª222‚N§“u…Bœ™õ u:###²4 +Òé4X­Vššš´.G!Ä×ÔÔ„Õje``€t:­u9%EVždÖôz½ÔÖÖj]ŽBˆQ[[‹×ë•õ ó,¯ë÷¿ÿ=o~ó›ñz½X­VöîÝËg?ûÙmñûý¼á oÀn·ãõz¹îºëG=×ÜÜ—\r 6›k¯½–H$’¯ã¤%“Iz{{©¯¯§²²Rër„B”˜ÊÊJêëëéíí•õ ó$oë‡?ü!¯zÕ«Ü}÷Ý<ôÐC\vÙeÛ®r˜ššâ‚ .`tt”O~ò“ÜqÇ|ç;ßáu¯{‰DbÛóÝxã$ î»ï>:ÄG>ò‘|ý('%‹ÑÛÛKkk«¬+(„B3n·›ÖÖVz{{‰ÅbZ—³ãåe⥵µ5®»î:Þô¦7ñõ¯ý¸ûÄ'>A$áù矧¡¡€—¿üå¼îu¯ã‰'žà¦›n6×ëûÉO~Âüü<6›‹.ºˆ‹.ºˆÏ|æ3ùøqNX$a``€ŽŽ,‹Öå!„(qv»öövü~?”——k]ÒŽ•—¬ýû÷³°°À=÷Ül®¹w¬f»o|ã\vÙeÙppñÅÓÑÑÁ²÷…ÃaL&6› Øú …Bgø§89¡Pˆº»»%\ !„(‹…îîn nß¹“ä%`=óÌ38&''éììÄn·ãt:yï{ß›¦œžžfqq‘sÏ=÷¨ïÙË^ÆóÏ?ŸýÚãñPUUÅÝwßÍØØwÜqçŸ~>~”²ººÊÈÈ===˜L&­ËB!¶1™Lôôô022ÂêêªÖåìHy XCCC$“I.¿ürÞøÆ7òôÓOsà 7ðè£rýõ×0;; pÌ+ìjkkYZZÚÖ‡õÈ#ðàƒ²{÷nžyæî¿ÿþ|ü(/) 299Éž={0 Z—#„B“Á``Ïž=LLL µ.gÇÉKV("sÛm·ñÀpùå—Çù¿ÿ÷ÿò±},{à±F|Ìf3°ÙÓ” -¯yÍk˜˜˜`xx˜={öÄHÑüü<Á`ŸÏ'Kß!„(xeeeôôôÐßßO2™¤ººZë’vŒ¼¤€LÝ;ßùÎm÷g¾þõ¯}̱®lˆF£Ûž'ÃétrÎ9çD¸šššbuuUÖBQTt:ÝÝݬ®®255¥u9;F^’@]]ÀQɸªª €åååìc2§ ·šÅëõæî”[çÌRU•±±1‰ííí²ôBˆ¢£( ííí$ ÆÆÆr»´N4Jò[ßÊÝ󉼬Lãú‘Éxffؼ °®®ŽÊÊJ~ó›ßõýÏ=÷guÖéòB°úÿƒ‘W¼‚¥k®!õ½ïÁ). ª*à Z[[%\ !„(ZŠ¢ÐÚÚŠ^¯gxxøÔCV:Mê?`é]ïbä¯à¯}-¿üen‹-y XïxÇ;xüñÇ·ÝÿùσÁÀ…^ÀÛÞö6¾ýíoo b?þñâÊ+¯<ýB^8ÅØöøãT?ù$­­ø?ûY¾úÕ~õ«Y{ÿûQûûOè©Òé4ý·ßŽý£Ý6­„BQ̱øÃôÿýߟðú…êð0kü ‡/¸€ƒç‡ÿÁÙhn¦úÉ'Ùû³Ÿ±ëÞ{ÏpÕ…'/Mîgu7Üp_øÂH&“\pÁ<ûì³|ýë_箻¦€»îº‹¯}ík¼æ5¯áöÛog}}OúÓìÛ·/{µa.(Š‚­£ÛÇ?N#›aií?ÿ“àSOqø½ïE‰Dp:¸.ºÛM7¡1{*•ÂÿWEÍà Ï>›³º„BˆBPóÄèÏ;¾•º|²²²mÿ®®¯úÜçXyæV——QË˱µ·ã¾ûn/ºHz‘ÉSÀxôÑGijjâ‹_ü"ßüæ7iiiáà}ï{_ö1 üô§?åoÿöo¹óÎ;1™L\vÙeÜÿýgtÊN‡ë q½0’–ŠÅX=p€Åï~—±·¼…²tg}=®·¼ã›ßLÿu×Ñ´±ëç?ù#B±ÓØlTüîwè_ýjzßóº>÷9âßþ6+ßü&«‡“Rlµµ¸Þö6ꮾš2™þ(ŠšÓN¶ÂöûßÿžsÎ9‡ßýîwœ}öÙ'ü}ÉÅEVœågŸe}~½N‡ë¯ÀuõÕØÎ;Oz¯„È“ƒ²wï^­ËbÇSU•Ðï~ÇÊ“O²ò³Ÿ‘l^/îW¿çÍ7£?Æœ•/æT÷¿Å,o#XÅL_YIù»ßÍäH×ùçc¼ùfV?ÿy?üaÆS)·û9çà¼æíí24*„¢¨¤ÓiÖ&&XÝ¿Ÿõÿú/ÔÅE¬Š‚kß>ê{Œøƒ2°°@Ý_ÿ5z¯Wër‹‚¬°>8Èè7Òýú×cúŸÿÏàH§Iÿû¬}ùˬ^s S&jc#Ö /Äyå•8™Ñ]!DAI$¬­­±úïÿNè?þÝè(öpgk+×^‹îmoÛÖSþä“tðƒô¿ýíìzâ ìÍÍV_$`½„•ÿú/&>ð|×_ᦛŽ~€N‡îÒKq]z).€põ‰'ØøíoY}Ó›˜ŸŸ'™Lb2™p:8ÊËËå´¢Bˆ¼PU•H$²¨VW‰ÅbèõzœN'U?þ1­{÷¢<ô¸\/ú<¦ûïÇwß}ø¯¾š¦GÅ%§ë_”¬øÞ÷˜ûèGéùð‡)»üòû&‹å½ïÅØ€úúz`s6úµµ5¦§§‰D"ètºì¢×v»ý¨+4„BˆS‘J¥X__guu•õõuÒé4ååå8Nš››³ËÏðä“'õ܆;î §ºÿ7’ü_ÿ‹Š.G“€us_þ2Ë<€ïнúÕ§ý|f³³Ùœ½>óÈ„®T*…ÙlÆáp`·Û±X,2Ê%„âE©ªJ8ÎîO¢Ñ(eeeÙø†††œÀ—½ë]øª«¸ã’wÝEÍWäôùw XÇ0ùÐCDÿùŸézòIŸïŒüeee¸\.\/ ɪªJ,cmmÙÙYÂá0Š¢`µZ³¡«Ö\B¡X,– S¨ªŠÅbÁápÐÔÔ„ÉdÊËÁ¹îõ¯§ËëeøÆI4Þ|óÿ?‹¬-TUeìþÝ¿ÿ;mÿöo(/œÞËEQŽåJ§Ólll°¾¾Îøø8±XŒ²²2l6v»»Ý. ôB±C% Ö××Y__' ‘J¥0™LØív*++iiiÑôªuåœshûæ79|ù匃´Þy§œyÙBÖ TUeðýïÇö‹_Pÿ“Ÿ€Ã¡uIÙ>-»Ýž½/•J …X__g~~žD"‘Î/ ]BQ\2a*³}O¥R ìv;.ÔNŸß 4IDAT—댜êË¥¥…–ÿø¦/¾˜¡¥%Úï½WBÖ $`ñº‚7Ü€wpê_þŒF­K:®²²2œN'N§3{_2™”tÀJllÐ÷ö·Óâtâ|úi­ËÉ©ct¥Óéì›}nn.ûf7Øl6¬V+6›MN1 !ÄIJ$„B!666…BÄãñìA­Õj¥ºº‹Å²³Gvt:¼?ù ú+® ÷Š+ð=õ«Uëª4S²+:?OÿÕWÓÖÝíᇵ.'/t:]vôj«Ìpõúú:sss$ E¡¼¼<¼,ËÎ8ÊBˆÓJ¥‡ÃÙ ‰DPUƒÁ=H­ªªÂX£7ΧŸf÷­·Òû–·ÐõÕ¯b®¬Ôº$M”dÀŠLNÒÿþ÷ÓyñÅ”ÿÿŸÖåhÎh4âñxðx<Ùû2CÛáp˜@ @8&NgÈ2Ge¼„;ÑÖ •Ù¦ÓiÊÊʲ­µµµÒjq¶G¥ó£¥ÿío§ãÿoï~Bã(ÿ8Žv²»³cÒt›’ ‰ÒC”_A”êÅ¢`Ô¦ÐôWôÔÖƒH5‚JJ‘ÞüsôÏÉâAPìÉ^D{Ñ‚&шXŒ$`ƒ¿Ú¤¶ÖÒmöoföwÏãìnªµ}º“tß/xØ™d²y–dg>ó}žyÿý¸»‹¶ Xÿ;p@ÿ}î9¥Ÿ}6Zæ\7Ýt“ú"gf˜qqq±)xe³Y¾:;;j°êU«U  …‚­Hyžg÷e7n¼ñ‡÷®ƒìÁƒúO_Ÿ¦÷ìÑ¥±±¸»Órí°æç%I›öì!\]¥Ë 3†a¨b±¨B¡  .èôéÓZZZ’´\!3;ªl6«L&ÃŽ @Ë„a¨R©d÷Q…BA•JEÒò‡„Ìþ©¿¿_Ùl–ý“CéçŸ×æþ~9x0î®´\{¬IRrd$æŽÜx<ϳ¯(ó‘dsføçŸªT*©V«Ù‹«šÊW6›mÙUˆÜXÌÝ0Lˆ*‹Mû3´gæH±¯iä®]ÚÔÑ!=þxÜ]i©ö Xh¹D"!ß÷åû¾z{{ë¾=«\\\ÔÙ³gU.—ë~.›ÍÚFå hoÑ}†iårYµZM’äû¾=YëííeŸ±Št ÅÝ…–#`!6Ñ9Â0´g£ÅbQ.\P©TR†’–Ëú&t™Fõ XÛLªT*ÙV,ítÏóìû½³³S¹\N¾ï¢°*°°*yžg+Wjµš–––ìÎ÷âÅ‹úý÷ßmõK’R©”|߯ _¾ïó‰G FA¨\.×…¨r¹¬jµj·‰¾os¹œ2™Œ’É$'OXsXXs‰„R©”½OW£Z­¦jµjwâ‹‹‹úã?T.—m,:tÙØ8þ=Su^©™!<Ïól€ò}_6lïûJ¥R(ÜpX¸á$ ¥Ói¥Óé˜Ô|0¸xñ¢Êå²*•Š aÒ_•°t:mM#ˆ¡„a¨J¥b›yŸ4Vž<ϳïß÷ÕÝÝÍI Ú méï† S ‹TÌ-0*•Š=+—–oM _©Tªî‘ VšÌÿ·y4-»mô„ÅTŸzzzìÿ7•'`e,à2¢–Æë~EÕj5A`NÕjU¥RIù|Þ®G«b’ì§iÉd²i™P†+†¡ªÕª–––T­V›–M‹ò<¯é$ »»Ûþ¿wttœ€kDÀ®Q"‘P2™´,ü'f’~ã°X,ÚƒãÒÒRS(‹þž•ZGGGÝ2mmÃPAØ¿{ty¥­œJËaÉüÝ£¡ÝÜMÁ„vÐZ, Å¢“ôÿ0 ›¶AØp=8AÐÐ ÏóÔÑÑaC˜YŽ®{ž×´]O$¶ÝÈjµšm&…ah[tÝ,A`[týŸþ!9™L*N7i‚3°6°€5ÂL"N§Ó×ôÓí·ß®l6wwh ÅbQsssÕ† âîNK´UÀh&¹8FÀpŒ€à À1€c,±ùî»ï´}ûvõôô¨»»[£££úá‡VÜvzzZÛ·o×Í7߬\.§½{÷êܹsMÛ-,,httT]]]Ú½{w[]ØÀêÁeÄbjjJ[·nÕm·Ý¦}ûö)½ýöÛ:þ¼&&&4<Ÿ×o¼¡¡¡!MLL(•JÙmwîÜ©B¡ 'Ÿ|Rï¾û®FFFôÖ[oÅñ´1€XìØ±CãããšUoo¯¤åêÓðð°¶mÛ¦O>ùÄn;66¦>ø@?ÿü³n½õVIÒ±cÇôè£ê½÷ÞÓ3Ï<#I*•JÊår:s挺ºº433£‘‘:uªõ/@[cˆ@,¾úê+=òÈ#6\IR¿|ðA=zT‹‹‹öëGŽÑÎ;m¸’¤‡~XÃÃÃúøãí× …‚|ßWWW—$©¯¯O—.]jÁ«€z,±¨T*+Þ²ª³³S•JE'Nœ$ýöÛo:{ö¬î½÷Þ¦mï»ï>}ÿý÷v}ýúõÚ¸q£8 “'Oêå—_ÖýôSûÉBé¯+¹¯[·N/¾ø¢òù¼^ýu irr’!B« @,~ùåijjJù|^›6mÒSO=¥ýû÷+™lž½ðÓO?iÿþý:~ü¸|ß׎;ôæ›oª¯¯/†ÞÀß#`8Æ,ÇXް#`8FÀpŒ€à À1€cÿðéºÖ×½ô­IEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/ticks_labels.png0000644000077000000240000004261212436367710024063 0ustar tomstaff00000000000000‰PNG  IHDR/n÷ßôsBIT|dˆ pHYsaa¨?§i IDATxœìÝyxÕáÆñw²@È&Á¶$`!lR¡Ôˆ(auD"P´Ek Z@–R ŠbŪ(P‘Ÿ ‚² FeѰ„°J;„% ÉüþH¹å’Ül÷&aÈ÷ó<<Ü93sι“Ѽœ93c˜¦i À"Ü*º%Ax–Bx–Bx–Bx–Bx–Bx–Bx–Bx–Bx*±9sæÈÍÍMnnn:räHEwŠ…ðüWzzºBCCåææ¦ZµjéìÙ³Eî3bÄÛ/ÿ¹sç–C/ˆaÝ(6 ð_¾¾¾ú÷¿ÿ-I:wîœ^xá…B·ß¼y³f̘!IŠŽŽÖ AƒÊ¼®Fh`E/fì=ù䓚?¾$髯¾R÷îÝóm“••¥6mÚh×®]òññQBB‚BCCË»«P)1òÜà­·ÞR`` $é÷¿ÿ½ÒÓÓóm3eÊíÚµK’ô·¿ýà刑 Ÿ|ò‰(IúÃþ ýë_¶u»wïV«V­”­»ï¾[7n¬¨n@¥ÄÈ P€¨k×®’¤wß}W?üðƒ$)77WC† Qvv¶ªT©¢Y³f•º¬¬,-[¶LÏ=÷œÚ¶m+yzzªfÍšj×®^}õU;wÎáþ]ºt‘›››<==µiÓ&‡Û͘1Ã6©øÕW_µ[Wœ»âââ4dÈ…‡‡ËÇÇG^^^ Q›6môÜsÏiÙ²e¥;PZ&€>|Øôóó3 Ã0›6mjfffšo¾ù¦i†i†9a§ê4h­.Ã0L777ÓÍÍÍ®,00ÐüᇠÜÿäÉ“f`` i†Ù¨Q#3---ß6 ¦———i†Ù¾}{3''ÇnýìÙ³mm>|8ßþo¼ñ†]Ÿ ê£aæ¥K—œ:PŒ¼Ô«WO“'O–$íÝ»WÏ>û¬ÆŽ+IºóÎ;mŸK+''G5Ò¨Q£´páBmܸQ?ýô“>ÿüs=û쳪R¥ŠÎ;§^½zéÌ™3ùö¶üûL_}õ•¤¼¹$/¾ø¢†.IZ»v­Ã1†áðÏ5×î^ÊÉÉQPP¦M›¦¸¸8;wNYYYÊÉÉQNNŽ>üðCÛ>fƒ¤_}õ•’’’l˱±±ÊÈÈ(õ÷—¤Þ½{+))Iï½÷žz÷î­ÚµkË0 ;wNóæÍSTT”ž~úé"û.UÑé ¸;wά]»¶i†b{†JZZšY¯^=ÛèÙ3gJUÿ˜1cLÃ0LOOOsß¾}·›:uj¡##ל:uʬU«–i†Y£F ÛÉsÏ=Wh?Šy)Èž={Ìüãfݺumí¼õÖ[ÅÚ\‘ #FŒÐ™3gd†ÞyçÛ³L|}}5sæLIyožþÓŸþTªú¯½©E‹ w¸ÝÏ?ÿ\¬ú¬³gÏÊÝÝ]_ýµ}ôQIÒ;ï¼£U«V•ªŽ4iÒDcƌѦM›äãã#IZ¸p¡KÛ€Â^€¬^½Zü±$é±ÇÓƒ>h·¾GêÓ§$iþüùZ½zu‰Û¸zõª$éÒ¥K·9yò¤–.]Zd]3gÎÔŠ+$IcÆŒQ‡ôþûï«nݺ’¤§Ÿ~ºÐ× ”ÖwÜa»E»,êG/Àu.]º¤gžyF’ ·ß~»Àíf̘!IÒ³Ï>«Ë—/—¨k£-û÷ï/ðÅŽ—/_Vÿþý‹œ³²oß>ýùÏ–$Ýu×]¶wùûûkΜ92 C§NÒ°aÃJÔ?IúòË/uá‡ë=ª½{÷J’4hPâú ´/ÀuÆŽ«Ã‡K’¦M›¦Úµk¸]íÚµ5uêTIÒ¡C‡ôÊ+¯”¨ko¬ÎÍÍU=4eÊÅÆÆjË–-z÷ÝwÕ²eKmذA:tpXGvv¶  +W®Øžõrýs`î¿ÿ~½ð ’¤/¾øB³gÏ.Q§OŸ®:uê¨oß¾zï½÷´aÃmß¾]ëÖ­ÓÔ©SÕ¡CeddÈ0 =ûì³%ªœRÑ“n€›ÅÆm·';ºúF÷ÝwŸí•[·n-Q{“&Mrx[µ›››ùç?ÿÙœ3gŽ­ìÆ µ/¿ü²mÝ»ï¾[`™™™fóæÍmù?xð Ýúkv ª¿cÇŽ…Þú}í{Ož<¹DßœExLÓÌÎÎ6›7onº¹¹™>>>ù~É;òË/¿˜ÕªU3ÝÜÜÌ6mÚä{ksQ–/_nvéÒŬY³¦éååeÖ«WÏ|ì±ÇÌ5kÖ˜¦iÚÂËwÅÆÆšîî››Ù³gÏBÛˆ7½¼¼L777³C‡v}tT¿iæ½µúƒ>0 `¶nÝÚ¬S§ŽY¥J³zõêfóæÍÍáÇ›;wî,Ñ÷Wà »ÀR˜ó,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,Å£¤;d_ÉÖ÷S¾W‚]8rAÞ5½Õ¨k#uúk'ùÕñ+v=oÖSŽ\p¸þ¹½Ï©fxÍ’vÏ2NÄÐÁoêø–ã:¾å¸ÒN¤I’&äN(U}WR¯hýÄõÚ·dŸÒO¥Ë÷v_5éÕD'v”W /Wvý¦äÊãYÙÏMIʾœ­½KöjÿWû•Ÿ¬ ‡/È4M4 PÓÇšªý‹íUŧJ‰ê¬Ì稫'ç(*»…—«WõŸNÿѱÍÇäWÇOM{5UjRª¶ÏÞ®_¾úEC6 ‘ÿu eLË˫֨Z¢z¬æ»¿~§}K÷I’ ðû»¤.Ÿ½¬Û¨”Ä”¼ÿönªÓ §µù­Í:°â€†l¢jþÕ\Ö÷›‘+ç5•õÜ”¤ówjÙ°e2 CMÖ#L™3uô‡£Z?a½>MP̆ùÔò)V}•ýuõñ¼¦2Ÿ£¨ÜJ^¾ûÛw:¶ù˜B~¢«ÊÓÛS’´qúF­¹ZK/Õ uƒŠ]Ÿazø£‡KÖã[DÈoBÜ2XuÚÖQ»êèÍÐ7•›[ªºVþi¥RStç£wê±Ï“á–÷K{Å +´åí-Zýâj=<ûÖ>ή<žRå>7%ɽлÚ<ÓFíþÔN¶òôSéšßc¾Nn;©UZ¥ÞŸô.V}•ýuõñ”8GQ¹{ÎKNV޶ük‹ ÃP÷wºÛ‚‹$µÑ^A‘A:´áNn=Y&½ÕtÝA'vTxpùù–ºž´“iJø4AU=Ô}fwÛ/IŠž-ï@oÅϋץ3—\Ñí›–«Ž'ò´xª…z¾ÛÓî­$ùûªû;Ý%I{¾Ø£Ü«EDÎQ×O%/G~8¢Ì‹™òoä¯àÁùÖßùØ’¤}Ëö¹®w(Ò•dš¦êÝS/ß³{wE<¡Üœ\ý²ü— ê!n5A‘A’¤œÌ]>w¹Èí9G WÒã  —’w$K’no}{ëƒ[åšÓ;O»qÓ4õÃÔ”š˜*÷ªîªÝ¬¶šöj*ï@ïb×QÙ•ÅÏœ›…I=˜*IrótSµ€¢ç©pŽ®¤ÇóÎQTfÅ/×f¶W¿£z믕_8ìx|AÖŒYc·¼jÄ*u{»›Z=ݪDõTVeõsç¦#›ÞÚ$Ijܵ±Ü=݋ܞs´p%=ž×ãEeUìð’•ž%Ivs]®wí6¿Ì´ÌbÕñp„tj :mêÈ»–·RSµí£mÚüÖf-ºLÞ5½ñPDq»Wi¹úçÎÍÂü²ümûp›Ü«¸ë¾¿ÞW¬}8G+Íñ”8G {H]··º©ÉÃMTýŽêò¨ê¡ZwÖRô´hõx·‡LÓÌ÷/  ¼pnììÞ³Züäb†¡ÎS;+¨yPEwÉÒœ9žœ£¨ìŠ^ªøæýë(ûrvë³.åý몪ŸsÏh5¤•|jùèÜþs:ø¼SuUåõsAå>7/¿¨y]ç)ã|†Ú½ØNw?w±÷åÍÏ™ãY˜Ê|Ž¢r)vx©Q¯†$éⱋ®¿V^#´†S2 Cþüeš¦ÒO¥;UWeP^?TÞsóJÊÍ‹ž§ G.¨ÕàVŠž]¢ý9Gí9{< SYÏQT>Å/Á-óîpô—kå×nûsFFj†$•øñã•‘íçWö?T¾s3+=KŸtûDgöœÑÞ©?x°ÄupŽþ+ŽgQ*Û9ŠÊ©Øá%¤CˆªV¯ª”):µãT¾õ{>ß#Ã0þ`¸S:½ë´Îî;«*>UØ$°è*¹Æ]Ë0 ùþH¾‡|]ͼªýËöËÍÃMaÝÃ*¨‡·ŽÊvn^ͼª/ÐñŸŽ«qׯzôÓGKõÊÎÑ<®:ž…©lç(*¯b‡wOwýúù_K’–_nwýz㕼3Y¡÷†êöVÿ{–ÖmÑ¿šüKkÿ²Ö®®_–ÿ¢¤uIùÚHŽOÖÿ=þ’¤VC[É̓—^_ãèXúûªyÿ溚yUËÿ°\¹9ÿ{Bç7£¿Ñå³—ùd$Ï~¸çfársrµè‰EJZ—¤Ð¨Põ]Ü·ÈïÌ9ê˜+'ç(PÂwE‹RÒš$ýñ¨Þ{[õ~[OçŸ×ñ-ÇåSÛ'ß{6.Ÿ½¬sûÏå»öz|Ëqm˜´A·…Þ¦ È yz{*õ`ªNn=©Üœ\5¸¯øÇλ›Øþ¯÷뻿~g[ÎÍΕiššÕn–­ìÞWîµýkÔѱ”¤.ovѱMÇ´{ÑnjrJ··¹]gvÑé]§U3¼¦º¼Ñ¥ì¿PsÕñäÜ̳å_[´wÉ^I’wMo}õìWù¶1 C§u–wͼÐÁ9ê˜+'ç(PÂðâQÕCƒÖ Rì”X%ÌOо¥ûT- šZ>ÝRþÚI~uüìw0 ~³oã®uñØEøù„ŽþxT™3UµzU…F…ªù€æjùtK—§Þl.Ÿ½¬ã[ŽÛ}OÃ0tâ§vÛüo¥ã·${×ôÖÐ-Cµ~âzí[²Oû¾Ü'Ÿ ÝýÂݺïÕûTµú­‡«Ž'çfžŒóyó& ÃО/öØ­3 C¦iÊ0 u|µ£TóÚ ÎQG\y<9GÉ0MÓ¬èNE€¥^€¥^€¥^€¥^€¥^€¥”è9/¥qöìY­ZµJõë×WµjÕʺ9 tåÊ:tH]ºtQ` ¯O°²2/K—®Ò!O–u3˼yó4`À€ŠîœPæá%(¨¾$éÝwçé׿nZÖÍÝòRS¥¥öí%ÿŠîõq<]‹ãéZO×Ú³gž|òIÕ¯_¿¢»'•yxñòÊ»TÖT­[·.ëænygÏJ'OJ-ZHŒz:ãéZO×âx– ¦0Xv€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥”yxñò²ÿÎñö–š5ËûÎãxºÇÓµ8ž@ÁÊüÅŒ×ÞÅ{°\ÃÛ[jÙ²¢{qëàxºÇÓµ8ž@Á¸l,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,…ð,Å£¢;ÀÍ*;;[6lÐöíÛµ}ûv?~\çÏŸ×ùóçåææ¦€€5iÒD:uÒ£>ªêÕ«—ªüQ?þx±·ß±c‡KÕÖ­€ð€‡Ö Aƒ$IU«VÕO<¡æÍ›+==]‹-R||¼Nœ8¡o¿ýV¯¿þº¦Nªnݺ•iŸ Ã(Óú­€ð@<<<ôÙgŸ©mÛ¶¶²§Ÿ~Z}ûöÕÆ%I©©©6l˜æÏŸ¯{î¹§TíLLÓ,U½· Ex衇삋$¹»»k̘1zä‘Gle¹¹¹š2eJ©ÃË矮víÚ9Õ×Ê€ »8àçç§ž={ªOŸ>®oÕª•ÜÜì•ÆÇÇ+##£<ºWi1ò€AAAzï½÷®÷ððP`` NŸ>mWž––&///§ÚÎÈÈÐÕ«WåããÃ<—^pÂ¥K—ì–}}}K}'Б#Gôå—_jÍš5:qℤ¼ËSêØ±£žzê)…„„8Ýg«ã²¥”˜˜˜/¼<òÈ#¥)9r¤²²²4iÒ$Íž=[C† ‘›››vïÞ­™3gªcÇŽš3gŽ znmŒ¼PJ .´[¾ãŽ;4f̘×S½zuµiÓFÇW—.]låÑÑÑjÙ²¥žþyIy—’ÆŽ+///õë×ϹÎ[#/”Âþýû5kÖ,Ûrƒ ´páBùûû—¸®fÍšiéÒ¥vÁåšÞ½{«Q£Fve“&MÒ•+WJÞé[Dù¼¬]+%%•O[R³fåÓ ô¤}ûʧ­ƒ]VÕÑ£GõÔSOÙî*êÚµ«¦OŸ^ê'ì¥mÛ¶JLL´-_¸pA±±±ŠŽŽ.“önvå^ÆŒ‘Êk¶t÷îÒ²eåÓ ô^~YZ¾¼|ÚrÑÞ¶mÛ¦!C†(99Y·Ýv›&NœX¢Gû—FA€“Êk@à&T~áåµ×¤† ˧­ˆˆòiàœ)S¤˜˜òiëàAiôh§ª˜={¶&Mš¤ììlõìÙS“'O¶ éééºxñ¢‚ƒƒó=ÿÅ=Y·2ß>]~áåþû¥Ö­Ë­9€4kV~—ù·n-õ®§NÒÈ‘#µ~ýzÕ©SG“'O.ð’Í{ï½§7ÞxC[¶lQݺu%å=uwܸqZ¼x±ÂÃÃ5cÆ Õ¯_ßn¿ž={ªwïÞûL+V¬Ðž={”šš*Õ­[WQQQЉ‰Qݺu]ôíÊÖÊ+5jõ(í>³Û®<2(RÿxàêÚ¸k©ë&¼àÀáÇ5hÐ IRÕªUõÄO¨yóæJOO×¢E‹¯'NèÛo¿Õ믿®©S§ª[·n¥j+11Q111:xð $©[·nêÒ¥‹Ž9¢™3g*!!A}ô‘&Nœ¨ºì;džCdÊ,Ö¶Y9Yš¾iºVXeWz[¨&uœ¤'#Ÿ”aNõ‡ð@<<<ôÙgŸ©mÛ¶¶²§Ÿ~Z}ûöÕÆ%I©©©6l˜æÏŸ¯{î¹§Dõ'''«W¯^:wîœ$©]»vš5k–m}pp°F­ŒŒ ½ôÒKòôôT¿~ý\ðÍŠç¾¹÷•z߀júË=Ñs¿~NUÜ«¸¤?<¤€"<ôÐCvÁE’ÜÝÝ5fÌ»²ÜÜ\M™2¥Äõ;Ö\$å½¹qy„ :}út‰Û)­ÒŽ”„ÔѶg¶éÅö/º,¸H„òóóSÏž=Õ§OŸ×·jÕJnnö¿Jããã•‘‘Qì6>¬+Vؕկ_ßn9 Àn>MzzºæÍ›Wì6*ÊÑ Gu×wéíÍo+;'ÛeõrÙ‚‚‚ôÞ{ï9\ïáá¡ÀÀÀ|£ iiiòòò*VË—/ÏWV³fÍË.^¼h[þúë¯õâ‹/« g­´®ØÛf^ÍÔ››ßÔÊ+eš¦Î\:£V¾ ·6¿¥¿uú›úþª/s^¨H—.]²[öõõU```±÷ß±c‡Ý²aòóóË·¯¯¯Ýò”‘‘Qì䌨Шmß¹Qg­N\­‘«Gj×é]’¤ƒ©ÕQMûqš^{à5ÝßðþR÷‡ËF”Rbbb¾ðòÈ#”hdáèÑ£ùÊ<==ó•U©b?g$''GÇ—ì@å)ºQ´v<»CïtGÞÿ s[OnUç;+úãhm;¹­Tu^(¥… Ú-ßqÇù&ñ%---_™»»{‘e¦iÚ]Fº¹nú}ÛßëÀhdû‘ªêQÕ¶nÍÁ5jó~õ_Ô_I©I%«×Õ 2Ø¿¿ÝíÌ 4ÐÂ… åïï_½º9U¯Z]S£§j×v©WÓ^v#S ¨É;MôŠŠ]_ùÍyY»VJ*Y²*µˆ©Y³òi Pz Ò¾}åÓÖþæ GÕSO=e»«¨k×®š>}z©ž°[Ðü–œœœb•9ûDßòÖп¡õY¤ ‡6hĪÚ~j»$);'[ooy[ou{«Xõ”_x3Frrvq±uï.-[V>mJïå—¥î¶)fñž[”mÛ¶iÈ!JNNÖm·Ý¦‰'êñÇ/u}õêÕÓöíÛíʲ³óßVœ••e·ìîî@Ü÷ IDATn™WÜèÞú÷jë3[5{Ûl[7N'ÓN–hÿò /¯½&5lX>mED”O;çL™"ÅÄ”O[J£G;UÅìÙ³5iÒ$egg«gÏžš7oOoýµÓ_5¬Í°bïÄ] ±dÉuêÔI6lРAƒ´nݺƒ‹# .Ôܹs•––¦¸¸85Ên}hhh¾ú’n˜#šššª .Ø–}||4`À€R|››WHboËCêp`ݺu>|¸myîܹš;wn¡ûÜøŒ—øøøB—%éïÿ»~úé'ÛèÊŠ+ô»ßýζ~åÊ•võOœ8QAAAÅÿ"· dff–xó†‰Á‘‘‘vË-Z´È·Opp°¾øâ ÅÄÄ())I›7oÖСCÕ¹sg;vL3gΔ$yyyiüøñêß¿‰ûu+!¼àÀµQ”â>1×4Í|ÛöéÓG;wîÔ¢E‹®iÓ¦¸oãÆµnÝ:-X°@+W®T\\œÖ¬Y#ooo5nÜXQQQЉ‰±ìF®d˜7FDÛºu«Ú´i£¸¸8µfÂ. ‚ðû¨ì:H’TÍ£š‚|Ëþr#/À) ßÊ{Jt£h­|re[;»€SJò"JW ¼K!¼K!¼K!¼K!¼K!¼Ká9/À)÷†Þ+S¦ZåõAY ¼§|;èÛrmËFÀR/ÀR/ÀR/ÀR/ÀR/ÀR/ÀRxÎ (–í§¶kÆæZh½N¤§»§Bk„*ºQ´F´¡!åÒ (Òkß¿¦¿|û™¦i+ËÊÉÒî3»µûÌnýûçëã^ëÑ;µÛo÷™Ýš¾qºL™jØD£~3Êé¾pÙêãëåµ/ÛÃ0d†m9ãj†ú~ÞW[Žo±Û7¢f„Ö$­ÑGÛ>Òøuãu1ó¢Óý!¼‡²s²õÒÚ—lËkÎ#s´û»•ðû½ÿàûº£ú’¤\3W\ñG»ýÝÝÜõTäS’¤Ì«™Zu`•Ó}"¼‡bÄêdÚIIR@µm²QOµxJjZ«©†¶ªÿ ÿjþ’¤-Ç·h×é]vuônÚÛ6Jóm’óïA"¼‡vŸÙmû<¢ÝÕô®™o›!úã¯ÿ7â²þÐz»õ‘A‘òöô–$m;µÍé>^€C—².Ù>GE:Ü®GxÛèÊÎÓ;íÖ†¡°€0IRbj¢Ó}"¼‡‚|ƒlŸ}ªø8Ü.¼f¸ísÊ•”|ëªH’.d\pºO„àPDÍۈʾ³ûnW½juÛçô¬ô|ësÌIR5ÏjN÷‰ðjÒ^õo«/IúOüìn—v$×ÌÍWväÂIRmŸÚN÷‰ð õûÿ!Ã0´ùØfýó‡–xÿ_Îý¢¤Ô$IRËà–N÷‡ð õø¯ׄ{'ÈÍpÓËk_Ö°eÃtúÒébí›y5S×·-÷ ëétx=(ÔÜísZ#T½›öÖç»?׬­³4gûujÐIwÕ¹KÁ¾Áò«âg»¤t<í¸Þ{_‡ÎÒg»>³º4 h¤'š?át/ POùt¾²«¹Wµ:qµV'®Î·n×é]zö«gíʪyVÓ‡}¨*îUœî—@¡®‡Qi„ÔÑŠ+å’þ0ò uoè½ÅÞÖÍpS÷*ªáUCwøÝ¡{BïQ—F]TÕ£ªËúCx…úvóï#r%.K!¼K!¼K!¼€Buû¤›’Ó“]Rס󇜮ƒð µ:qµ"ÿ©¯÷íT=ŸÄ¢ÿnát/ Hg.уŸ>¨ç—?¯Œ«%Ú÷bæE X<@¿¨´Ì4§ûBx…jØÄöùŸÞQÛÚjgòÎbíûý‘ïùn¤>Ýù©ËúCx…Ú:l«^¸û¹y±a×é]úõ¬_kÆæ÷¹š{Uã¾§Žs:êÈ…#’$¿ª~úèáœî᪪GUMï:]«®VHIyo‹þÓÊ?©û'ÝóMæ=r@¿ùð7ú{ìß•kæJ’~[ï·Š6^1-cœîáK§´ó÷;õdä“¶÷­<°R‘ÿŽÔò_–K’>Üú¡Z½×J?ŸøY’TŽЦÜ?Eb6(ô¶P—ôƒ×€b«^µºþÓë?z8âa=ûõ³:wùœÎ\:£žó{ªepKm?µÝ¶í¯jÿJózÍS‹`çï0º#/ Ä½óQíüýNu ëf+»\ ÃÐ w¿ Ÿ÷³Ëƒ‹Dx¥äï寰€°|åUÝ«*¬f˜Kß$}= (±m'·©õû­íî8ªáUC’”q5CÏ-N]çuÕ‰´.o›ðŠ-×ÌÕäï&«Ý‡í´çÌIy“r§vžªS#OiD»¶[ªW'®Vów›ë³„Ï\Ú (–Ä”DÝ3û_7^Ù9Ù’ò`·iè&üÍHUõ¨ª×»¼®•O®T¿:’¤Ô+©zbÑ꿨¿R¯¤º¤„P¤÷ãÞWË÷ZjãѶ²am†)nXœZ·´Ûö†(þ÷ñz¤É#¶² ÔüÝæú&ñ§ûBx…zðÓõìWÏêRÖ%IRMïšú¢ïúwÏ«šgµ÷ ¨ Å}ëýß—OIÒ‰´ê2¯‹Óý!¼€B]{$Ýßð~Å?¯‡›<\¬}‡¶ª­Ã¶ê®:w¹¬?„P¤*îUôÏÎÿÔ7¿Ñí~·—hß°šaÚ8d£^þí˶ɼÎà » P5#ôIïOÔêöV¥®ÃÝÍ]“®»:Ý (ÔÏÃ~–·§·Kêº'ô§ëà²(”«‚‹«^€¥^€¥0çêÕõ¯Ê”©Æõdä“Ý (Ü«^•$E7Š.ux9~ñ¸Ò²Ò$å½RÀ„P(Ã0dš¦Su ]6T«¬’$åNÈuª.æ¼€2gÈpY]„`)„`)Ìy ¹¹¹Z°`¦L™¢””[ùôéÓÕ§O§êþñÇõøã{û;v(00Щ6K+åJŠÖZ_âý :wå\ë6Ú Sÿ›OÓ±~Ç"ë#¼Pˆ¸¸87NñññùÖ†ëæqGy·w£ŸOü¬Ns;¹´ÎûæÞg·\œÉ¼\6À#Fèá‡Ö±cÇÔ¯_¿2mË0ŒBÿܪJóÝyÀÅ‹kðàÁ5j”víÚ¥ ”Y[Ÿþ¹ÚµkWfõ»‚—‡—‚}ƒªãúKD’Z#T¦L2ò­s„ð€k×®UãÆ%ÉéçœÜ î­¯V XáÒ:¾p°ÄûpÙ®—ò–‘‘¡ôôô›.0Ý,ýa䀛À‘#Gôå—_jÍš5:qâ„$ÉÝÝ]êØ±£žzê)…„„Tp/oŒ¼p9r¤²²²4iÒ$Íž=[C† ‘›››vïÞ­™3gªcÇŽš3gNEwó¦ÀÈ ¨zõêjÓ¦†®.]ºØÊ£££Õ²eK=ÿüó’ò.%;V^^^e~çÓÍŽ‘*P³fÍ´téR»àrMïÞ½Õ¨Q#»²I“&éÊ•+åÕ=;7Ë-Ûå7ò²v­””T>mEDHÍš•O[€ÒKHöí+Ÿ¶–ü®–›AÛ¶m•˜˜h[¾pá‚bcc]n}Èy%§ÜÚ*Žò /cÆH啨ºw—–-+Ÿ¶¥÷òËÒòååÓÖMr§LIô*€¤ò ¸I•_xyí5©aÃòi+"¢|Ú8gÊ)&¦|Ú:xP=º|Úr¡‚nO¾Y.ßT”ò /÷ß/µn]nÍ, Y³ò»Ì¿ukù´sÜÜ\7N‹/Vxx¸f̘¡úõëÛmÓ³gOõîÝ[ƒ.°Žäää|e7ÖQÙ0a€2²páBÍ;WiiiŠ‹‹Ó¨Q£òm³mÛ6ÅÆÆ¸¿išÚ´i“]™¿¿¿¢¢¢Ê¤¿VAx ŒÜø&ê‚ÞL-彆  u³gÏÖ±cÇlˆaè•W^‘———k;Z„œÜÏ8oûSÑxÎ lذAû÷ï—$:t(ßúõë×ëüù¼_æ~~~ùž¿i·Ü¢E‹ÛÉÉÉÑ#<¢~ýú©iÓ¦rssSll¬–]wó‰&L˜ >}ú8ó•Jåí-oëÅU/J’ÚÔi£Ÿ~÷“Ãmç™?ÍÔöSÛu5÷ªBj„¨gXO½ôÛ—ää’þ^p`É’%Z¸p¡mùƉ²K–,Ñ’%K$I!!!ùÂKŸ>}´sçN-Z´Háááš6mZ¾6V­Z¥ØØXíØ±C?ÿü³¾ù楤¤È4MÕ®][aaaŠŠŠRß¾}U«V­2ø–E[ºo©íóK^r¸Ý¨Õ£ôÆÆ7ìÊSõÖæ·4oç<­¸F-‚ p%a˜eü–¥­[·ªM›6Š‹‹Sk&ì*¿J'ój¦ü_óWÆÕ T ЩQ§äá–ì#öp¬îs¯]™avwK5ôo¨¿ß©jžÕœês^€CÛOmWfN¦$éÁˆ .’4}ÓtÛçˆÀ-}b©öß«-P°o°$é`êA}šð©Ó}â²phïÙ½¶Ñ“öw´/p›ìœl­J\%)o´eIß%ŠÌ{æZXÍ0T PôÇyOþbïܪàÛ‹‹‘àЙËglŸCk„¸ÍÖ“[•q5C’ô뺿¶—khø€m²îŽS;œîá8t5÷ªísUªn³åøÛèÌ (p›ðšá’¤³—Ï:Ý' p¨FÕ¶ÏÇ.+p›o}kûÜ>¤àKKUÜ«H²C¥Ex…Õ ³}^—´.ßú”+)Zu`•mù®:wXϹËç$I5¼j¸¾$/À¡»ëÞ-/¼'úÎÛ9O §ìÖ];Ö6ߥ¡CÕö©¯Žìœlí=»W’ÔÈ¿‘Ó}ân#à_U?õùUýgÇ”“­uаÖÃÔ8 ±Ö&­Õç»?·mÛ»iïëXh½-à´­ÓÖé>^@¡þñÀ?´ü—å:{ù¬Ò2ÓôúÆ×óms›×mÙ~dû¸íCÛç®»:Ý.€BûkÍSkTÿ¶ú®¯é]S_öû²Àw%§'ëð…ú«Î]Š R—Æ]œî#/ H‘A‘Ú3|>MøTë­ÓéK§åWÅOw×½[O·zZÕ Ü/È7H‡lti_/ XªzTULËÅ´Œ©Ð~pÙX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX áX á€"äææjþüùjÞ¼¹êÖ­kû³páB—µ‘­yóæiÀ€jݺµ4h fÍš©K—.š¬+Vؕկ_ßn9 @Õ«W·-§§§kÞ¼y.ï‹•^p qãÆeZÿòåËó•Õ¬Y³È²¯¿þºÌúd„*ÈŽ;ì– ÃŸŸ_¾í|}}í–8 ŒŒŒ2íÛÍŒð@9zôh¾2OOÏ|eUªT±[ÎÉɩԷN^¨ iiiùÊÜÝÝ‹,3MS/^,³~Ýì/ÀRÊï9/k×JIIåÓVD„Ô¬Yù´(½„iß¾òië¿€»™4¿%''§Xe×ßTÙ”_x3FrÑ“‹Ô½»´lYù´(½—_– ¸ã¦L”Á­ÎΪW¯ž¶oßnW–o»¬¬,»ewwwÕ­[·Lûv3+¿ðòÚkRÆåÓVDDù´pΔ)RLLù´uð 4ztù´UL‘‘‘Zºt©mÙ4ÍçÁ¤§§Û-‡……ÉËË«Ìûw³*¿ðrÿýRëÖåÖÀš5+¿Ëü[·–O;×ÉÍÍÕ¸qã´xñb…‡‡kÆŒv¡ëÞ½»&Ožl÷¼ëŸ¶{MJJŠÝr=ʬÏVÀ„]ÊÈÂ… 5wî\¥¥¥)..N£F²[ªèèh»²¤懦¦¦êÂ… ¶e 0 ì:m„ÊÈo¢.èÍÔÿûß`[¾ñu+W®´}6 C'NTPP‹{j-¼U6lØ ýû÷K’:”oýúõëuþüyIywÝø¶çÈÈH»å-Zä«#88X_|ñ…bbb”””¤Í›7kèСêܹ³Ž;¦™3gJ’¼¼¼4~üxõïßß_ÍÒ/8°dÉ-\¸Ð¶lÜp×ì’%K´dÉIRHHH¾ðÒ§OíܹS‹-Rxx¸¦M›V`;7Öºuë´`Á­\¹RqqqZ³f¼½½Õ¸qcEEE)&&¦Rßat=Ã,‹×d^gëÖ­jÓ¦âââÔš »€ Âï£[s^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥^€¥”yx¹rÅþo8çòeiûö¼¿á<ާkq<]‹ã ¬ÌÃKF†ýßpÎåËRBÿ3sާkq<]‹ã ŒËFÀR<*ºXAvv¶>ûì3­X±B{öìQjjª|||T·n]EEE)&&FuëÖ-UÝ?þø£üñbo¿cÇ–ª­[á€"$&&*&&F”$uëÖM]ºtÑ‘#G4sæL%$$è£>Òĉ5pàÀ2í‹aeZ¿^(Drr²zõê¥sçÎI’Úµk§Y³fÙÖkôèÑÊÈÈÐK/½$OOOõëׯTmLLÓ,U½· …;v¬-¸Hy£.×ëÖ­›Fm[ž0a‚:uê¤Úµk—¸­Ï?ÿ\íÚµ+}g+ &ìàÀáǵbÅ »²úõëÛ-¨zõê¶åôôtÍ›7¯<ºWi^p`ùòåùÊjÖ¬YdÙ×_ítÛJOOçRQ¸l€;vì°[6 C~~~ù¶óõõµ[>pà€222äååU¢öŽ9¢/¿üRk֬щ'$IîîˆPÇŽõÔSO)$$¤„ßâÖÃÈ =z4_™§§g¾²*UªØ-çääèøñã%noäÈ‘ÊÊÊÒ¤I“4{öl 2DnnnÚ½{·fΜ©Ž;jΜ9%®÷VÃÈ ¤¥¥å+sww/²Ì4M]¼x±ØíT¯^]mÚ´ÑðáÃÕ¥K[ytt´Z¶l©çŸ^RÞ¥¤±cÇÊËË«Ôw4Ý y ‚5kÖLK—.µ .×ôîÝ[5²+›4i’®Tâ—–ùÈKFFÞÁ=¸p®ü·®-ëæò„†J—O[å,5U:tHÚ±Cò÷¯èÞXÇÓµ8ž®U)ŽçÒáÃåÒÔžcÇ$©D¿ô šß’““S¬²ëï@rVÛ¶m•˜˜h[¾pá‚bccí²6¬¤ÌÃKrò!IÒ°÷g”uSéСCêСC±¶­W¯ž¶oßnW–o»¬¬,»eww÷R¿*  ½ ))Éeõ[M™‡—‡ê¢yS¦¨~NŽªÝ0¡©ÌÜÂ#/pK)Ç‘—+YY:äî^à¥G"##µtéRÛ²iš΃IOO·[ +ñF…)èvéÊüš€2/ðÒKeÝ ÀŠZ·.׿Š7Þò?Ý»w×äÉ“íÂÃõOÛ½&%%Ån¹G¶Ï¹¹¹7nœ/^¬ððp͘1#߃îzöì©Þ½{kðàÁö#999_ÙuT&LØÀÐÐÐ|óJn¼\“ššª .Ø–}||4`ÀÛòÂ… 5wî\¥¥¥)..N£FÊ×ζmÛ[`LÓÔ¦M›ìÊüýýUâïs« ¼Pˆ¿ÿýï °-ßøº€•+WÚ>†¡‰'*((ÈVo·ýË׬]»¶Àu³gÏÖ±ÿN6¾ÖÆ+¯¼âÒËRVÃs^(Dpp°¾øâ ÅÄÄ())I›7oÖСCÕ¹sg;vL3gΔ$yyyiüøñêß¿¿Ýþ‘‘‘vË-Z´(°œœ=òÈ#êׯŸš6m*777ÅÆÆjÙ²e¶m|||4aÂõéÓÇÅßÒZ “—&P¤ììl-X°@+W®ÔîÝ»•šš*ooo…„„(**J111Þa”››«ñãÇkÑ¢E ×Ûo¿­ÐÐP»m«;vèàÁƒJMMUJJŠLÓT5¦¨¨(õíÛWµjÕ*¯¯|Ó"¼KaÎ ° ° °”ßm”}%[ßOù^ táÈy×ôV£®Ôé¯äW'ÿ; y³þ›ºpä‚ÃõÏí}N5Ãk–´{–q"î„~sPÇ·×ñ-Ç•v"ï‰r'”ª¾+©W´~âzí[²Oé§Òå{»¯šôj¢Ž;ʫƭ;+ge?7%)ûr¶ö.Ù«ý_íWr|².¾ Ó4Ð(@Mkªö/¶WŸ’=1»2Ÿ£®>žœ£¨ìJ^®f\Õ:ýGÇ6“_?5íÕT©I©Ú>{»~ùê Ù4Dþ Jöö°–1- ,¯Z£j‰ê±šïþúö-Ý'éx.í£ž/Ÿ½¬Û¨”Ä”¼ÿönªÓ §µù­Í:°â€†l¢jþÕ\Ö÷›‘+ç5•õÜ”¤ówjÙ°e2 CMÖ#L™3uô‡£Z?a½>MP̆ùÔò)V}•ýuõñ¼¦2Ÿ£¨ÜJ^¾ûÛw:¶ù˜B~¢«ÊÓÛS’´qúF­¹ZK/Õ uƒŠ]Ÿazø£‡KÖã[DÈoBÜ2XuÚÖQ»êèÍÐ7•›[ªºVþi¥RStç£wê±Ï“á–÷K{Å +´åí-Zýâj=<ûÖ>ή<žRå>7%ɽлÚ<ÓFíþÔNÿ{!\ú©tÍï1_'·Ôª?­RïOz«¾Ê~ŽºúxJœ£¨ÜŠ=ç%'+G[þµE†a¨û;ÝmÁE’Úh¯ È ÚpH'·ž,“ŽÞj:Œî Ž;*¼G¸|ƒ|K]OÚÉ4%|š ªê>³»í—‚$EO–w ·âçÅëÒ™K®èöMËUÇyZ<ÕB=ßíi÷‹V’|ƒ}Õýî’¤=_ìQîÕ¢"ç¨k'€„—#?QæÅLù7òWp‹à|ëï|ìNIÒ¾eû\×;éÀÊ2MSõî©—oÈÙ½Š»"ŠPnN®~YþKõ·š È¼Çžçdæèò¹ËEnÏ9Z¸’O%¸l”¼#ï–··¾½ÀõÁ­òÍ駋ݸišúaêJML•{UwÕnV[M{5•w w±ë¨ìÊâçÎͤL•$¹yº©Z@ÑóT8G Wþ)wYIDATÒãy ç(*³b‡—k3Û«ßQ½Àõ×Ê/v<¾ kƬ±[^5b•º½ÝM­žnU¢z*«²ú¹€sÓ‘Moå½Ý¶qׯr÷t/r{ÎÑ•ôx^s•U±ÃKVz–$ÙÍu¹ÞµÛü2Ó2‹U_ÄÃjЩ괩#ïZÞJMLÕ¶¶ió[›µlè2y×ôVÄCÅí^¥åêŸ 87 óËò_´íÃmr¯â®ûþz_±öáu¬4ÇSâ*ì!uÝÞê¦&7Qõ;ªË£ª‡jÝYKÑÓ¢ÕãÝ2M3ß¿(€ò¹Y°³{Ïjñ“‹e†:Oí¬ æAÝ¥ÿoïîbš:ã0€?/-ºªˆ‰4f…H!Ñ€¶„ì‚,ƹĸq±l1Kv±‹e1:/\²Å˜È^âG¢¨›Úgð+jª.Ùkë²Fà`µÁÚBéÙESHW ­§ŠÇ÷ùÝÑ·çpÎÿ<ÿÃἯ®i©'3J²Ë¸y),ŠßM…¦æŸ|¿»2k›_Àþ¥¦•&ŒzFxд/¼­ëBrg3¨ÑÕÚ…p ŒúïêQ··.ãm™ÑTZê9™3Jrɸy)­(‚sŽ'>/µ”j: !–¸ªªbÂ7¡i_2x[×…äÍæ«±Wèj°aGó/ÍYmÏŒ&ÓZÏùÈšQ’OÆÍËj[ü€tó¸$>O¼ö§Ex< YO?.£™ëòàÍ_’/›““8ñÑ Œ¸F°¾}=ÚŽµe½ftV.ê¹Ù2JrʸyY»i- %Œý3ß_¾”q×Y„¨j«Òt@ýÃð»ý(4bEõŠ…7œµÕ !únõ¥LòDá¹èA^~*?®\¤#|È–Íh$ŠÓŸœ†rOµÕŠöSí¯µä3—«zÎG¶Œ’¼2n^–,ÁƽŽoIϯテ¡‡C°4ZPnŸËÁÙéDgu'®þp5i_OOáíñ¦üŽ¡¿‡pæÓ3{‡yù\ô:!]-‹V¡æ³D#Q8¾v 6=;Cç•ï¯ ä¡öóZÎýð?ÌæübÓ1tïì†·Ç Kƒ;ÎíXðœ™ÑôrYOf”(˵~l€÷/úo÷ãhåQTl®@àYŠSi•)e?„QÏhʳWÅ©àúOױ̲ eµe(0`üßq<ÿó9bÓ1¬kZ‡m?oÓ~vï0Ïen¼1ósl*UUq¼þøÌgûgîFÓÕZŽ´`àîw?†¯Ú‡ò åéÁpï0ÌUf´nyó'´ÈrUOf3ÎÙéÄ“ OF³—¾º”ò!¶ÿºFs¼é`FÓËe=™Q¢,›—|C>v÷ìÆÍC7ñèä#¸wcéKaÛcÃÖƒ[Q¼¦8y1÷ʾÖV+‚A ÞDÿí~D‚J °4XP³«¶=¶œÿ9õ]ò‡ 8•¤óB`ðÞ`ÒwfÓ¯’l4ÑáìÀµý×à¾à†û77Le&Ô}[‡¦M0”¼ÿoq䪞Ìf\8ÿ¿ !\ç]IcB¨ª !¶Ø˜Ìh:¹¬'3JUUÕÅ>"""¢Lñ¡(é ›"""Ò6/DDD¤+l^ˆˆˆHWؼ‘®°y!"""]aóBDDDºÂæ…ˆˆˆt…Í é ›"""Ò6/DDD¤+l^ˆˆˆHWؼ‘®ü${‚O:(jIEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/update_clip_path_change_wcs.png0000644000077000000240000001713712436367710027116 0ustar tomstaff00000000000000‰PNG  IHDR Xšv‚psBIT|dˆ pHYsaa¨?§iIDATxœíݰWÿñ×P—Ápä"â­QP[ Æ0t³ÖYÇi u¿¥l³.•¥;­B®¶5S3±°µÍnXÌÄêVJRka–˜«»ZŽýPs±m5'~Ä/(0ù!÷û‡IòKH®ïs?ðxÌ8ƒçóñøšñŽ3Ï{Îù|Z]]]](ЫéÀáC€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€eú4=  k׮ͽ÷Þ›!C†¤oß¾MÏá0³yóæ,Y²$çŸ~Øô€R8,Ý{ï½¹üòË›žÁaîÖ[oÍ_þå_6= ”KC† ùÝŸþ_’îú ôœ$ºé\¯ûNwî[›äÛ/û98|à°ôûÛ®&9¡›ÎÚ»ÏõZ°ïàtÿ>·ÿ‡#¡ePF€e@·Öô€ý°ïàôô}íA€t›±MØûNOßÐPF€ePF€=ÎÆ3uêÔ\pÁ0`@zõê•[n¹e—÷tuuåæ›oÎE]”O<1G}tFŒ‘éÓ§çùçŸoh9°?èqÖ¬Y“iÓ¦åÉ'ŸÌé§Ÿž$iµZ»¼gãÆ¹âŠ+²nݺ|øÃÎ 7Ü3Ï<3S§N͘1cš˜ €>MØ]gggV¯^AƒeÁ‚=zôï9ꨣò“Ÿü$ò'²óØ?øÁ 2$S§NÍý÷ߟóÎ;¯r6p\zœ#<2ƒ Jòâ­V{sÄGì/¹ä’K’$ .|í¯š)«W¯N’ 8°á%ÀÞàòÿø9æ˜c<=”g@€CÆŒ3rÿý÷çK_úRú÷ïßô`/\ ·Ýv[>õ©OåCúPþú¯ÿºé9À> íýçþg&L˜w½ë]™={vÓs€Wà, ­=òÈ#ùó?ÿóœyæ™ùæ7¿™^½þÐß«ÌIÒ{·cÃ’Œíž»“<±Û±íM èж~ñ‹_ä /ÌÉ'Ÿœ»îº+GuÔ«8Ë„$'t÷4x™±Ù3hW%¹±-Í @4kÖ¬¬_¿>+W®L’ÜyçY¶lY’dÒ¤IiµZ9ÿüó³~ýú|ìcËüùówùçO=õÔ½~OЬV×¾¾å  AC‡ÍÒ¥K“$­V+É‹_JØjµ²xñâìØ±#'Ÿ|rZ­Ö^¿¬ðýï¾ò•¯ìóü=öXÎ8ãŒ$WÅê½xdÁ‚5jTÓcJ¹ôH‹/Þï{vìØQ°èN> (#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2èQ6nܘ©S§æ‚ .È€Ò«W¯ÜrË-{}ï/~ñ‹\pÁyÝë^—ŽŽŽL˜0!k×®-^ ü!У¬Y³&Ó¦MË“O>™ÓO?=IÒjµöxßòåËsÎ9çä—¿üeþáþ!ýèGó½ï}/ï|ç;ó /TÏPŸ¦¼\gggV¯^AƒeÁ‚=zô^ß7cÆŒlÞ¼9?ûÙÏò†7¼!Iræ™gæï|gn¾ùæ\yå••³€ä Уyä‘4hP’¤««kŸï»ýöÛó®w½kg|$Éyç—?þã?Î7¿ùÍ×|'ðê í¬X±"kÖ¬É[ßúÖ=^=zt~ö³Ÿ5° 8h;«V­J’œp {¼v 'ä׿þµç@ ‡ @ÛÙ¼ys’䨣ŽÚãµ?ú£?Úå=@Ï"@€¶Ó·oß$ÉóÏ?¿Çk[¶lÙå=@Ï"@€¶óÒ­W/ÝŠõr«V­JGGGŽ8âˆêYÀð1¼@Ûyýë_ŸãŽ;.>úè¯ýô§?Ýùý!fN’Þ»–dìA,„—»;É»ÛÞÄ€A€méÝï~wn¹å–,_¾|çGñÞÿýY´hQ®¿þú?àL’ìù0;tŸ±Ù3hW%¹±-Í @3kÖ¬¬_¿>+W®L’ÜyçY¶lY’dÒ¤Iéß¿>ñ‰Oä[ßúVÎ=÷Ü|ä#ÉoûÛ|îsŸËÈ‘#ó| ÉùÀ+hu½Ò7}4`èСYºti’¤Õj%yñK [­V/^œO<1IòÄOäºë®Ë~ô£uÔQ¹ð óOÿôO9î¸ãöûïxì±ÇrÆg$¹*®€PïÅ+ ,ȨQ£šPÊ ÇY¼xñ½oذa¹çž{^ã5@wò)X@” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @Ûú¯ÿú¯\|ñÅéììL¿~ýòæ7¿9Ó¦MËæÍ››žìCŸ¦¼?þxÞñŽw¤³³3×^{m Ÿüä'™:uj,Xï|ç;MOöB€méßþíß²uëÖ|ï{ßË›ßüæ$ɇ>ô¡ìر#sæÌɆ rÌ1Ç4¼Ø[°€¶Ô·oß$É Aƒv9>xðàôîÝ;Gyd³€ý @[ºâŠ+rüñÇçƒü`~þóŸçW¿úUn»í¶Ìž=;“&MÚ(@Ïâ, -uvvæÇ?þqÆŽ›·¼å-;Ož<9Ÿþô§\¼´¥gžy&cÆŒI’ÜtÓMéèèÈ]wÝ•éÓ§çøãÏÕW_ÝðB`oЖ¦M›–+Vä©§žJggg’ä’K.ÉŽ;òñ<ï}ï{3`À€†W»ó Ж~ô£å-oyËÎøxɸqã²iÓ¦ü÷ÿwCË€Wâ Ж^xá…lß¾}¯Ç“dÛ¶mx¦9IzïvlX’±3^æî$OìvlÏŸ]€Ã…ÚÒ¨Q£ò­o}+‹-ÊßøÆÇ¿ño¤wïÞ9räžiB’^“ð¢±Ù3hW%¹±-Í @[ú»¿û»Ü~ûíùÓ?ýÓ\sÍ50`@îºë®ÜsÏ=¹òÊ+3xðà¦'{!@€¶4räÈ<ðÀ™:uj>÷¹ÏeË–-9ùä“3cÆŒ|ìckz°h[gžyfþýßÿ½éÀÀ§`ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€mí±ÇËE]”ŽŽŽôë×/#FŒÈ¿øÅ¦gûЧé¯ÖüÇdܸq9ãŒ32eÊ”}ôÑyúé§³bÅŠ¦§û @€¶ôì³Ïf„ 7n\æÍ›×ô๠hK_ÿú×óÿ÷™>}z’dãÆÙ±cGë€ý @[ºï¾ûÒ¿ÿüêW¿Êi§–×½îu9æ˜cò7ó7yþù盞ìƒÚÒ¢E‹²mÛ¶\rÉ%3fL¾ýíoçŠ+®ÈìÙ³ó| éyÀ>xhKÏ=÷\6mÚ”øÃ™9sf’ä’K.ÉÖ­[ó/ÿò/ùô§?SO=µá•Àî\ÚRß¾}“$ï}ï{w9þÒß?üðÃ囀ý @[êììL’üñ»4hP’ä7¿ùMù&`ÿÜ‚´¥·¾õ­¹ï¾û²|ùò¼ñoÜy|åÊ•I’ãŽ;îÏ4'IïÝŽ K2¶;fB’»“<±Û±íM èЖ.»ì²|æ3ŸÉ—¿üåœ{î¹;ÿë¿þkŽ8âˆüÙŸýÙžiB’^‹‰ð;c³gЮJrc[š'@€¶túé§çŠ+®ÈW¾ò•lÛ¶-çœsNxàÌ›7/ŸøÄ'2xðà¦'{!@€¶5{öìœxâ‰ùêW¿š;î¸#C† ÉÌ™33iÒ¤¦§û @€¶Õ§OŸL™2%S¦Liz p€| PF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€epȘ>}zzõê•#F4=Ø–/_ž3f¤_¿~iµZMÏö¡OÓºÃG?úÑœ}öÙÙ¶m[Ö®]Ûô`\ÚÞƒ>˜Ûo¿=3gÎLWW—+ Ѓ  ­mß¾='NÌ•W^™áÇ7=Ø·`mmöìÙY¶lY¾ÿýï7=8®€mkݺu™2eJ¦L™’ŽŽŽ¦ç@€mkòäÉ8p`&NœØô๠hK‹-ÊM7Ý”™3gfùòå;oÙ²%[·nÍÒ¥KÓ¿ÿ{ì± ®v'@€¶´bÅŠìØ±#“&MʤI“öx}èС¹öÚkóÏÿüÏû9Óœ$½w;6,ÉØnZ w'yb·cÛ›Ð# -1"wÜqÇ.¹ÛÕÕ•É“'ç¹çžË 7ÜSN9åÎ4!É ¯ÙNx1fwÚUInl` @óЖ:::rñÅïqüóŸÿ|’䢋.ªž¡‡”V«å‹ s8¤üà?hzð \Ê ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÚÖ£>šk®¹&ÇÏÑG“N:)ãÇÏ¢E‹šžìCŸ¦¼ZŸýìgóÐCåÒK/ÍÈ‘#³jժ̚5+£FÊÃ?œáÇ7=ØÚÖõ×_ŸÑ£G§OŸßÿ¯lüøñ1bD>ó™Ïäk_ûZƒë€½ @ÛzÛÛ޶DZSO=5Æ ËÂ… Xìg@€CJWWWžyæ™ 8°é)À^à2wîܬ\¹2ãÇoz °8d,\¸0W_}uÎ>ûì¼ï}ïkz°8$¬^½:^xaŽ=öØÌ›7/­V«éIÀ^xh{6lȘ1còì³Ïæ‡?üaÜô$`ÐÖ¶lÙ’qãÆåé§ŸÎ}÷Ý—7½éMàæ$é½Û±aIÆvÏ@ÈÝIžØíØö&†ôh[Û·oÏøñãóÈ#ä»ßýnÎ:ë¬Wq– INèîið2c³gЮJrc[š'@€¶uýõ×gþüù7n\Ö®]›[o½u—×/¿üò†–û"@€¶õóŸÿ<­V+óçÏÏüùówy­Õj èж~ðƒ4=øù^ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ Œè6w7=`?ì;8=}@{ Ýæ‰¦ì‡}§§ïh(#@€2(Ó§éMؼyóïþ´¶Ϻ=ɪn<_w³ïàtç¾î~ÿspø ÀaiÉ’%¿ûÓ·»ùÌ7vóùº›}§{÷-Y²$oûÛ»õœ=]«««««éÕÖ®]›{ï½7C† Iß¾}›žÃafóæÍY²dIÎ?ÿü 8°é9¥PÆCè@” @” @ð*mܸ1S§NÍ\¤W¯^¹å–[šžµÓ£>šk®¹&ÇÏÑG“N:)ãÇÏ¢E‹šž–$ùßÿýß\zé¥9å”SÒ¯_¿tttäì³ÏÎܹs›ž¶OÓ§OO¯^½2bĈ¦§´-_Dð*­Y³&Ó¦MËI'”ÓO?=<ð@Z­VÓ³vúìg?›‡z(—^ziFŽ™U«VeÖ¬Y5jT~øá >¼Ñ}Ë–-ËsÏ=—÷¿ÿýéìì̦M›2oÞ¼üÕ_ýU–,Y’O~ò“îÛÝòåË3cÆŒôëׯGýwh7¾àUÚºukÖ¯_ŸAƒeÁ‚=ztn¾ùæL˜0¡éiI’‡z(£GNŸ>¿ÿ]ÓÓO?#Fä=ïyO¾öµ¯5¸nïvìØ‘3Î8#¿þõ¯³téÒ¦çìâ/þâ/²nݺlÛ¶-k×®Íã?Þô$€¶ä,€WéÈ#Ì Aƒ’$=ñw9o{ÛÛv‰$9õÔS3lذ,\¸°¡U¯¬W¯^yÃÞ#Ž8¢é)»xðÁsûí·gæÌ™éêêrà ¸ à0ÒÕÕ•gžy¦G=ðiÓ¦lÚ´)6lÈwÞ™{ï½7³fÍjzÖNÛ·oÏĉså•W6~ÛÀ¡@€FæÎ›•+Wæïÿþ²Óu×]—o¼1IÒ§OŸ|á _ÈUW]Õðªß›={v–-[–ïÿûMO8$€ÃÄÂ… sõÕWçì³ÏÎûÞ÷¾¦çìô·û·¹ì²Ë²råÊÌ;7×\sMúöíÛ#6®[·.S¦LÉ”)SÒÑÑÑô€C‚8 ¬^½:^xaŽ=öØÌ›7¯G=ÃpÚi§å´ÓNK’\~ùå9ÿüósíµ×æ²Ë.Kß¾}Ý6yòä 80'NltÀ¡ÄC臸 6d̘1yöÙgsÏ=÷dðàÁMOzEï~÷»³aÆ<ùä“îX´hQnºé¦Lœ81Ë—/Ï’%K²dÉ’lÙ²%[·nÍÒ¥Kó›ßü¦ÑíH€¶lÙ’qãÆåé§ŸÎ]wÝ•7½éMMOگ͛7'yñ±š´bÅŠìØ±#“&MÊÉ'Ÿ¼ó¯Ÿþô§yê©§2tèÐL›6­ÑíÈ-X‡¨íÛ·güøñyä‘GòÝï~7guVÓ“v±fÍšwÜq»{á…2gΜttt4þ‰S#FŒÈwܱËíj]]]™øà^¿$±Õjeûöí ¬ú½Ûn»-_þò—óøãgݺuéß¿Î:ë¬\wÝu9ï¼óÝöJÎ=÷ܬ[·.ÿó?ÿÓô€¶$@€2BÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ Ìÿ¥ æ^$gIEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/update_clip_path_nonrectangular.png0000644000077000000240000004553512436367710030042 0ustar tomstaff00000000000000‰PNG  IHDR Xšv‚psBIT|dˆ pHYsaa¨?§i IDATxœìÝ}t”õÿÿ×uÍLØJ !™TÌz(Qf ?ÝOÕ*uívk÷F»VÛíí¯ëéž_וs–JÏöníÖ~íÚ­ÝÞY»ÖÞìZ[¾nÉÍLh ‚‚d‹¤L&I€\3×õûc€’Û¹>só|œã9ar%¾’ÌÁ¼œëýy[žçyئ(¾¡€ð €o( |Cà ßP@ø†À7¾¡€ð €o( |Cà ßP@ø†À7¾¡€ð €o( |Cà ßP@ø†À7¾¡€ð €o( |Cà ßP@ø†À7¾¡€ð €o( |C€<ÇõÑ~T+V¬Ð¼yó´téR½ç=ïѾ}ûLG“$íÞ½[ï~÷»uÉ%—hîܹZ¸p¡Ö­[§§žzÊt4@MdÆ?ÿó?«©©Iï~÷»uÕUWéСCzä‘GtÍ5ר¹¹Y+V¬0𝣣CýýýzßûÞ§p8¬ÁÁAýð‡?Ô_ÿõ_ëµ×^Ó?üÃ?ÍÈ Ëó<ÏtÀìkjjR$Q08üÿšÚÛÛµjÕ*ýÙŸý™þýßÿÝ`º±¹®«k¯½V½½½:pà€é8€ à,ÈSk×®Q>$©¶¶VW^y¥öìÙc(Õ…Ù¶­7¿ùÍ …B¦£2„[° €xž§Ã‡kÕªU¦£œ588¨ÁÁA;vLÏ>û¬þë¿þK<òˆéX€ ¡€@yê©§ÔÙÙ©Ï|æ3¦£œõÉO~R=ö˜$) ê_ÿõ_õ|Àp*@¦0bÏž=ª¯¯×ªU«ô?ÿó?²,Ët$IÒÞ½{•H$ÔÙÙ©§žzJÏ?ÿ¼¾ñoè®»î2 (]]]Z¿~½R©”š››UUUe:Ò¸Þþö·+‹©³³SÅÅŦãfCèçŽ;¦›nºI}}}úÅ/~‘ÕåC’Þõ®w騱cÚ»w¯é(€ `òØÉ“'uë­·ª½½]¿üå/uùå—›Ž4¡'NHJŸˆÈ?üíy*•Jé=ïyZZZôƒü@õõõ¦#ÐÝÝ=ê1Çqô­o}K .4¾(¼yêïþîïô“ŸüD·Þz«zzzôío{Äûÿê¯þÊP²´|à:~ü¸®»î:…Ãauuué©§žÒ«¯¾ªÇ\@Àh>@f0„yê­o}«^|ñEõ×¼eYJ¥RR ûÞ÷¾§o|ãz饗ôÆo¨¬¬Lõõõúä'?©·½ímF³2‡À7Ì€ð €o( |Cà ßP@ø†À7lB€¶qãFuwwëž{î1Å_ÿú×%I_øÂTRR2êýúÜç>§––Åb1=zT?þ¸îºë®³×xž§'Ÿ|R?úÑ´cÇõööjÙ²eºãŽ;tÿý÷kΜ9¾}=PˆXD9lùòZíßÿ¿¦cønûöíºæškF=þÚk¯iùòåZºt©–-[¦­[·ê‰'žÐwÞyöšþþ~•••iíÚµºå–[TYY©ÆÆF=ù䓺îºëô«_ýÊÏ/ ¯€@ŽÐk¯í—ôÿHºbñ-IwNx•9“É÷Š,k›–,Y2æ{Ãá°ºººTYY©íÛ·+‰ŒºfΜ9jllTCCÃÙÇÞÿþ÷ëâ‹/ÖÆõ /èmo{Û ¾À…P@ GµµµÉó\IWJªšÄG$Ug6ÔŒL.ŸçýöîÝ«E‹z_QQ‘*++O_7ö ü¡PhDù8ã¶ÛnÓÆµgÏ dCè£âñ¸l»HR…é(>ª”m‡Çgý3wuuIÒ˜Å0{( £b±˜,«ZéW E@¶]­X,6ëŸùsŸûœæÏŸ¯›nºiÖ?7`·`@ŽjllQ*5™[¯òK2Y¥ÆÆæYýœ›7oÖ /¼ û·SYYÙ¬~nÀH¼9¨··Wû%ÕLᣮÌTœY2Ù|5:p`¿z{{gåßú½ï}Oÿøÿ¨{î¹GüàgåsÆG€4<žÂGÝœ‰(³h²ùÒ¥«µµuÆÿÆçŸ^wÞy§n¹åmÙ²eÆŸ01 ä x<®@ DR¹é(”+(žñ zKK‹þôOÿTÑhTßÿþ÷eÛü'üÀß¶Ú¸q£n¼ñF•——˶m=ùä“#®ñô¡ÝÈ}fÞx¹=ÏSSS‹\÷R?¾”¬äºÕjjjó}<òˆŽ=ªÎÎNIÒ³Ï>«ŽŽIÒ}÷Ý'˲ôö·¿]GÕ§>õ)ýä'?ññµµµcî ÌËoS`Ú†††tôèѹŸxâ Ýyçð¦oÇq´}ûöQ¿ìnÚ´I7nÔóÏ??æB¼ƒꢋ.’ôI—gø+ÉV¯Hú¾<¨šš‘ƒøË–-Ó$éléósݹÿP> ³( e&ÚȋŠ͗TêcªlS¦`p~F2‹Yf¢Ü--1%“Õ>§Ê>©T•ZZ( kB€,2ÑFn×u·ÊóÖH—]¥Ë~޳XMMͦc¦€E„!çnäÞ²e‹n¿ýv­^½ZÒðFî+V¨³³S›7oV8<ò¶ªó7r;Ž£yóJ54T)©wŒã•’nÎÜdÜÏ$½|ÞcŽl;¥“'O( ™˜" dÈloänkkÓ5×\#énIùñ%ä€I«­­íl¹d7Žá€ Ù¿ÿ„׸®;éÏ‹ÅdY¶<[°†U˲lÅb1 äf@ GÄãqƒU’¸ÕhXHÀbÑ ‡P@ G46¶0€>†d²J-¦c&‰9```@{÷¾,öŒ¥F{ö¼¬ÁÁAÓA“@€ÐÖÖvz^¤Æt”,–ë¦ÔÖÖf:`( âñ¸l»HR…é(Y¨R¶brr@ú¬jIÓQ²P@¶]­X,f:`( [”J1€>žô :Ñ P@ Ëõööª£c¿˜ÿ¸8°_½½cmˆd d¹áÙNÀ_ºœµ¶¶Î˜²\<W P"©Üt”,V®@ ˜AtÈÈr±XLžW-É2%‹Yò¼0ƒè( Å<ÏSSS‹\·Út”¬çºÕjjb#:d; d±D"¡žž×Åúd„ÕÝ}X‰DÂtÀP@ ‹ Ï4P@&–þ1ÙY,‹)š/©Ôt”P¦`p>s å( ÅZZbJ&™ÿ˜¬TªJ--ÈfÈR®ë*o=}&ÃóŠÇãò<ÏtÀ8( ¥ÚÛÛÕßß'æ?¦¢FÇ÷©½½ÝtÀ8( ¥†gØ€>yéïs ½( ¥âñ¸B¡E’ŠMGÉ!Å …qd1 d©¦¦9óSå8Ujnf!!d+ d!Çq´sçqûÕt„ÕÖÖ&ÇqLŒYh×®]:% ÈtÔhhè”vïÞm:` ÈBñx\–eK⬩«’eÙÌ@–¢€@ŠÅb «$…LGÉAE sd) d¡ÆÆ9ÎbÓ1rV2Y¥ÆFÑ Q@ Ë hïÞWÄ™¨Ñž=/kppÐtÀy( eÚÚÚäº)Q@f",×M©­­ÍtÀy( eâñ¸l;$©Ât”V)Û1ˆYˆY&}VXRÀt”mWS@ Q@ ËlÛÖ¬TªÊtŒœ—LViÛ¶&Ó1ç¡€@éííUGÇ~±€p6ÔèÀý:räˆé €sP@ ‹´¶¶ž~‹ô™K‡¿§€l@€,‹Å”H*7%”+(f!!d d‘X,&Ï«–d™Ž’,y^5² ²„çyjjj‘ëV›Ž’7\7¬¦& d d‰D"¡žž×ÅüÇl «»»K‰DÂtÀiÈÃ;+8kö¤Ëû@ {P@ KÄãq…Bó%•™Ž’GJ Χ€@¡€@–hnnQ2ÉüÇì²”JU©¹¹ÅtÀiÈ®ë*o=}f“ç…Çåyžé(Q@ +´··«¿¿O  gBŽïS{{»é Q@ + ïª`}ö¥¿§ì€ì@€,@_$©Øt”+,)`:Jȶ«) ` Ú¶­Y©T•é#™¬Ò¶mM¦c@A£€€!½½½êèØ/ú©Fìב#GL€‚ECZ[[O¿ÅºÒßëáïýhÚ¸q£n¼ñF•——˶m=ùä“c^ûÊ+¯èÆoTii©.\¨;ï¼S===Iù‚†Äb1%’ÊMG) å Š/¸°»»[›6mÒÞ½{µzõjI’eY£®;xð ®»î:ýþ÷¿×g?ûYÝÿýúéOªn¸AŽãdì+€\4 U,“çUKýË-2Å’çU_°€„Ãauuu©²²RÛ·oW$óºÍ›7ëĉjkkÓ›ßüfIR4Õ 7Ü 'žxB÷Þ{oF¾Èu¼xž§¦¦¹nµé(ÇuÃjj¿€©²²RRúç4ž§Ÿ~Z·ÜrËÙò!Io{ÛÛt饗êûßÿþì€1€nRŽïS{{ûô>º¦FcÞÆ‹ÅÎîŒF€ódzöð ÐÍIï/´d"ïz×»ôÜsÏéàÁƒg{á…´oß>½ûÝïžqBÈW,"€óœÙ„½téR­^½Z[·n½à&ì 賟ý¬Ž?®/|á z饗‹Åƽ'=€¾HŽÃŒ€9Å …)ë/ÿò/G½÷‘GÑÑ£GÕÙÙ)IzöÙgÕÑÑ!Iºï¾ûTVV¦OúÓúÁ~ ·¾õ­úøÇ?®ãÇëóŸÿ¼®ºê*ýÍßü¯_ äË›î °§†††tôèÑ›°Ÿxâ Ýyç#®ûð‡?¬o}ë[Ú³gÏÙet/¼ð‚n¸á=úè£ãnÂŽFJº=Ó_ .èiÕ×ÏSssÓ¨÷,[¶L¤³åÓó¡€€b±˜<¯Z’e: F±äyÕð 2Ìó<55µÈu«MGÁ8\7¬¦& ø–H$ÔÓóº˜ÿÈfauww)‘H˜y6¼ä.l4.$]YH™G€ K/%œ/©ÌtŒ«TÁà| ø€ÖÜÜ¢d’ùìf)•ªRss‹é ÷( A®ë*o=}²™ç…ÇÅ~^È, dP{{»úûûÄz.¨Ññã}joo7ò2hx·èÙ/ý3bd2(=€¾HR±é(˜P±B¡E ¢@†Q@ ƒššZä8Ìä Ça2â8ŽvîÜ!n¿Ê%aµµµÉqÓA oQ@ CvíÚ¥¡¡S¢€ä’ ÒîÝ»M€¼E€ ‰Çã²,[·`åŽ*Y–Íd2$‹)¬’2“V¤@`1'a@Q@ C[ä8‹MÇÀ%“Ujld2…000 ½{_ sQöìyYƒƒƒ¦ƒ@^¢€@´µµÉuS¢€ä¢°\7¥¶¶¶IÄC=$Û¶µjÕª æ€ü@€ ˆÇã²í¤ ÓQ0e•²íФÑ<¨Í›7kîܹ²,+ÃÙ ÷M€|”>+,)`: ¦, Û®žt¹ÿþûµnÝ:%“Iõôôd8ä>^€ ض­Y©T•阦d²JÛ¶5MxÝ‹/¾¨§Ÿ~Z?ü°<Ï㘠̲ÞÞ^utì sYد#GŽŒ{E*•ÒÇ>ö1Ý{ï½Z±b…Ù ·Q@`–µ¶¶ž~‹ôÜ•þÙ ÿ,GÛ²e‹:::´iÓ&¿B@^ €À,‹Åb J$•›Ž‚i+W P<îBÂ7ÞxC>ø |ðA-\¸ÐçlÛ( 0Ëb±˜<¯Zó¹Ë’çU[@xà-Z´HûØÇ|ιS°`yž§¦¦¹î¥¦£`†\7¬¦¦Ñdß¾}úÚ×¾¦‡~X<ûøÉ“'544¤¨¬¬L ,ð3.ä Ëó<ÏtÈÔE]$é=’.73òФïëàÁƒª©žçÙºu«þäOþä‚ù‰O|B_úÒ—2œr¯€À8ô¹Ï}N---ŠÅb:zô¨üqÝu×]ã~ÌðîNÀÊ}éÒÇGU«Vé™gžqä®çyzàÔß߯/ù˺ä’K|O ¹‚ãèîîÖ¦M›´téR­^½Z[·npÏC<W(4_ŽSæSJdN©‚ÁùŠÇãºí¶ÛÎ>ºpáB½óïuõ¿üË¿H’6lØà[BÈEG8VWW—*++µ}ûvE"‘ ?¦¹¹EÉdµéy–R©*57·LîjËb!LÆQTT¤ÊÊJIé[l&⺮âñVyÞµ™ŽŸx^Xñx|R[Îýë_û” rÇðÀ,iooWŸX@˜OjtüxŸÚÛÛM€¼A€Y2¼3‚ôü‘þYŽ·0u˜%éôE’ŠMGÁ¬)V(´èœÓÍ3E€YÒÔÔ"Ça=ß8ÎäÑ£€À,pG;wî·_声ÚÚÚä8Žé ( 0 víÚ¥¡¡S¢€ä£ ÒîÝ»M€¼@€YÇeY¶$nÁÊ?U²,›9˜%ì€ xä‘GtôèQuvvJ’ž}öYuttH’î»ï>••¥7žÇb1ƒUrœ±¬È”"‹‹Åtï½÷š9Ïò&³] Ô²eËtàÀI:»ˆîÌRºýû÷kÉ’%’¤+¯\¥W^é’ôSQ‘QϪ¼¼Co¼Ñc:ä< ÌÐÀÀ€ÊÊæËu’þ?ÓqÛ%=§•””˜9˜¡¶¶6¹nJü•šÏÒ‡ ´µµÎ¹ÿZÀ ÅãqÙvHü•šÏ*%‰At˜ü×f(}VX’e: 2& ‰“°`6P@`†¶mkV*Ue:2ÎÖ¶mM¦C@Σ€À ôööª£c¿Ò3WšŽƒŒºHìב#GL€œF€hmm=ýV¤›MFAƽCÒ¹?sÀtP@`b±˜I妣 ãÊ+‹™93‹ÅäyÕb½Xò¼j ̦Éó<55µÈu«MGO\7¬¦& ̦)‘H¨§çu¥ç?PÂêîîR"‘0r¦ix'DØhø)]6ÙÓG€iŠÇã …æK*3¾)U08Ÿ3@€ijnnQ2ÉüGa±”JU©¹¹eÜ+Z[[õÎw¾SápXsçÎÕW\¡M›6éĉ>æ€ìeyžç™¹Æu]ÍŸ¿@ýý×JºÎtøêE•–n×±cGeY#O?{饗‰D‡õ·û·*//Wcc£žxâ mذA?þñ e€ì4rQ{{»úûûÄz!ªÑñã¿V{{»þøÿxÄ{¾ûÝïjhhH?ýéOuÅWH’î¹ç¹®«o}ë[:vì˜æÏŸo"4d nÁ€iÞÁzáIÿÌÇÚR\\,Iª¬¬ñxUU•€ŠŠŠ2²¦!=€¾HR±é(ð]±B¡Ec¢ß}÷ÝZ¼x±Þÿþ÷kçÎúÃþ ï}ï{Ú²e‹î»ï¾³ ·`À445µÈq@/TŽ3ö z8Ö¶mÛtóÍ7«®®îìã<ð€þéŸþÉψµ( 0EŽãhçÎ’®7Æ„ÕÖöå8ŽB¡ÐÙG>¬›nºI’ôµ¯}M .ÔsÏ=§‡zH‹/ÖG>òS kP@`ŠvíÚ¥¡¡Sbþ£Õhhè”vïÞ­Õ«WŸ}tÓ¦MJ$zõÕW§Ÿ·Ýv›\×Õßÿýßë½ï}¯ÊËËM…€¬À LQ<—eÙ’¸«pUɲìQs ¿ùÍoTWWw¶|œqë­·jppP;vìð3$d% LQ,S0X%)4áµÈWE : Ëq¥R©QW;Ž#IJ&“¾¤€lFPЦ³µº±±E޳ØÇ”ÈFÉd•G¢_sÍ5úío«}ûöxü?þã?tÕUWù²›Ð¬él­PYÙ|¹îM’®õ?4²ÈvÙöÏuüxŸJJJ$I¿ûÝïÔÐР²²2}ô£Uyy¹ž{î9ýâ¿Ð½÷Þ«G}Ôpf0!tk:[«ÛÚÚäº)±RX®›R[[›Ö¯_/Iºêª«´uëVmܸQŸÿüçuòäI-_¾\›7oÖ§>õ)Ãy ;P@¬él­ŽÇã²í\·Â—ŒÈf•²íâñøÙ"IÑh£² IDATT?ÿùÏ æ€ìÆ €‚5­Õé°Â’þF– ȶ«Ç܈3 Úïÿ{Ý|óÍzõÕWÏ>v¡­ÕK—.WGG¥¤}Jˆìös-]Ú­×^û½é 3¸ @ÁšêÖêÞÞ^utì—´zŒÏ†ÂT£b:räˆ,X`: ä €‚5Õ­Õ­­­§ßbg¤Ÿ ­­­ºá† g€ÜÀ €‚5Õ­Õ±XL@‰¤riå ŠG-$Œ `Muku,“çUK²üˆ‡œ`Éóª) 0k*[«=ÏSSS‹\·Úï˜Èr®VS&‹S°¬©l­>xð .ºè"Iï‘t¹±ÌÈF¯Hú¾<¨šæƒ`"-‹iãÆjll<»µú®»îÒ§>õ)Ùöð‹ÄÏ<óŒn¿ývIWKjã3])éfŸRìŸIzùœ?»’Nèæ›oÖOúSC™ wp €‚6Ù­Õñx\¡Ð|9Îm>¤Bv»Y#˦§`ðËZ½šã™`2˜€IhnnQ2ÉüÆb)•ªRss‹é ( 0×u·ž> ÍóŠÇãâ®f˜&ÐÞÞ®þþ>±€ã«Ññã}jok>p. L`xÇCø‚ס¥Ÿì€‰Q@`éôE’ŠMGAÖ*V(´HñxÜtÈz˜@SS‹‡ù\˜ã0ˆ“A€ pG;wî·_abaµµµÉqÓA «Q@àvíÚ¥¡¡S¢€`b5:¥Ý»w›YÇeY¶$nÁÂDªdY6s 0 \@,S0X%)d: ²^‘Åœ„ €À46¶Èq›Ž‘LV©±‘At¸ Œc``@{÷¾"bòj´gÏË4²ÆÑÖÖ&×M‰‚É ËuSjkk3²ÆÇeÛ!I¦£ gTʶC ¢ÀP@`é°Â’¦£ gdÛÕ¸ ŒcÛ¶f¥RU¦c Ç$“UÚ¶­Ét ÈZCoo¯::ö‹„˜º8°_GŽ1²ÆÐÚÚzú-Ð1UéçÌðsp. Œ!‹)(‘Tn: rN¹bÀ8( 0†X,&Ï«–d™Ž‚œcÉóª) 0 Œ¡¹9&×­69Êu«ÕÔD€±P@à<‰DBÝ݇Åü¦¯FÝÝ]J$¦ƒ@Ö¡€Ày†oá,LWº¼²F£€Àyâñ¸‚Áù’ÊLGAÎ*U0XF€1P@à<--1¥RÌ`&,¥RÕjiaÎgyžç™ÙÂu]ÍŸ¿@ýý×JºÎtä´UZº]ÇŽ•eqšœÁ+ pŽöövõ÷÷‰tÌ\XÇ÷©½½ÝtÈ*8Çð=û  c¦D€±P@à±XL¡Ð"IŦ£ ç+ZÄBB8ÎÑÔÔ"Ç©2yÂqªÔÜÜb:d œæ8ŽvîÜ!æ?0{ÂÚ±c‡Ç1²NÛµk—††N‰ùÌž:uR»wï6²N‹Çã²,[;@0[ª$Y ¢À9( pZzz•¤é(ÈE «( p œ¶m[³g±éÈ3Éd•¶mk6²$ jïÞWÄ:f_X{ö¼¬ÁÁAÓA +P@@R[[›\7% f_\7¥;v˜YJ/ ´í¤ ÓQw*eÛ!ÀiЙ°ª%LGAÞ È²ªD€Ó( ©±±Y©Çï"3R©*562ˆÔÛÛ«ö‹„Èœ½öÚïuäÈÓAÀ8 €‚×ÚÚzú-Б)ér;ü\€ÂEPðâñ¸I妣 o-T P̈jii‘çUK²LGAÞ²äyÕjii1Œ£€(xÍÍ1¹.èÈ,×­VSGñ@AK$êî>,æ?y5êîîR"‘0Œ¢€(hÃËá8 ™–.¹Ì(t-+œ/©Ìtä½Rƒe  µ´ÄX@ŸXJ¥ªÕÒ€Âfyžç™&¸®«ùó¨¿ÿZI×™Žƒ‚ð¢JK·ëر£²,N]P˜x@ÁjooWŸ@‡Â:~¼Oííí¦ƒ€1kø^|ÐáÑ€ `Åb1…B‹$›Ž‚‚Q¬PhÑ9§¯@á¡€(XMM-rœ*Ó1P`§JÍÍlDP¸( ’ã8Ú¹s‡˜ÿ€ÿÂÚ±c‡Ç1Œ €(H»víÒÐÐ)1ÿÿÕèÔ©“Ú½{·é `@AŠÇã²,[;@à·*Iƒè @Azì±ÇdYs%…LGAÁ)’mÏÓc=f:AÀwžØ  PQ@¤|àò¼I ÃoCrÝ}ðƒ4Œ €(H‘HDžçJ:d: N—$O‘HÄt0‚  ­\¹REEs$ušŽ‚‚“М9¤+V˜FP@¤P(¤«¯^-)a: N§V¯^­Pˆ& €‚µvm½B¡.Ó1P`B¡.54Ô›ŽÆP@¬h4*Çé‘tÂtŒrœE£QÓAÀ €‚5<Ìü’¾åt…Œ `ÕÖÖjÞ¼21ÿtª´´Lµµµ¦ƒ€1˶mE£YGñ–թh4*˲LGc( Z}}T~ðR}=ó @A‹D"J&Iê3y︒É>æ?< €‚6|ƒèÈ´ô¬'`(t­¦¦F‹Å :2/¡ŠŠ*…ÃaÓAÀ( €‚×Еm3‚̲íCZ»–W?€ àÕ×ן> Ë3yË“eR}=Ѐ ¯ýö·¿Õ† ´páBÍ;W«V­ÒW¾ò•×D"¥Rƒ’zÍ„DxC©Ô‰1Ð'ó€|42å¿ÿû¿uë­·êÚk¯Õƒ>¨y󿩽½]‰ÄÈy5kÖœ~+!i¡ï9QÒ‡ ?×Ò&û€|byžÇ=òN__Ÿ.½ôR½å-oÑøÃ ¯¿øâå:p RÒ™‡ôs]|qöïÿß³Lõ9 ù‚[°ä¥ï|ç;zýõ×õÐCI’äºî¸×¯[×ÀBBdL Ð¥uëF<6Õç(ä €¼ôË_þReeeúÃþ Ë.»L¥¥¥š?¾>üáëÔ©S£®OÏ”ôyI_8ùš¹îgùüù¼R©uttŒ¸jªÏQÈÜ‚ /]}õÕúßÿMßîrÏ=÷èúë¯×¯ýk}å+_ÑwÜ¡ï|ç;#®ß¶m›Þò–·Hú ¤*ÿ#’ô˜¶mÛ¦uëÖ}tªÏQÈyé’K.Ñþýûõ¡}H_ýêWÏ>þ¡}H>ú¨^}õUÕÖÖž}|ppP¥¥erÝ›$]k 1òW«lû:~¼O%%%gêsò·`ÈKÅÅÅ’¤÷¾÷½#?óçæææ—””è²Ë®Ñ1û:uùåWŽ(ÒÔŸ£/( òR8–$-^¼xÄã•••’¤#GŽŒú˜õë Î|8”`°Kë×7Œz|:ÏQÈyé̾…ƒŽx¼³3½¡¢¢bÔÇD"%“]’œŒçC¡R2Ù5æÂé&‰Èó\¥‡†ÙÐ%ɳ€Lç9 ù€MèòÒêÕ«u÷Ýwë›ßü¦’ɤ®»î:mݺU?üáõéOZUU£OºZ¹r¥ŠŠæhh¨SÒÿC#%4gÎiÅŠ£Þ3ç(äNÁ·’ɤ6oÞ¬Ç\ºøâ‹õ‘|D÷Ýw߸6(ô.ÿ‚"=­úúyjnnó½ÓyŽ@®£€À9>þñëßþí;rœ˜Ž‚< }Uþð_êá‡6²3 pŽh4*Çé‘tÂtä¼rœE£QÓA «P@àÃÃÂFs ¤wÊŒ5€…Œ稭­Õ¼yeb!!f®S¥¥el3€óP@à¶m+Ȳ8Š3cYŠF£²,ËtÈ*8O}}T3á)8¤úzæ?à|8Oz#ú1I}¦£ gW2ÙÇüŒç>µˆAtLWz†ˆ°`4 œ§¦¦F‹Å :¦/¡ŠŠ*…ÃaÓA ëP@` QÙ6s ˜Û>¤µkyõÆB€1¤O/:$É39Ç“eâö+ÆF•J Jê59§W©Ô ŒƒcX³fÍé·˜ÁT¥Ÿ3ÃÏ!À¹( 0†òòr-Y²Lœ„…©KhéÒeZ°`é •( 0Žõët™Ž viýúµ¦c@Ö¢€À8"‘ˆ<¯SRÊt䌔\÷ à( 0ŽH$"×u$u›Ž‚œñº\ס€ÀP@`uuu²í€DÇäuʶª««3²Æ1wî\]vÙ¢€`òºüò+URRb:d- \Àºuõ …›Ž viݺzÓ1 «Q@à¢Ñ¨’É.IŽé(ÈzCJ¥³€&@€ HŸ„åJ:d: ²^—<Ïe&@€ X¹r¥ŠŠæˆ…„˜XBEEs´bÅ ÓA «Q@àB¡®¾zµ( ˜X§êêê …L€¬F€ ¬][¯Pˆ[°pa¡P—@€‰P@`‘HDŽÓ#é„é(ÈZ'ä8=ÌÀ$P@`çqÆ“~npLŒ¨­­Õ¼yeb!!Æ—Pii™jkkM€¬G€ ض­Hd,‹9ŒÍ²:‰DdY–é(õ( 0 õ ) ‹§@àè0I˜„ô ú1I}¦£ ëW2ÙÇ:L&aø—KÑq¾ôl&‡“PSS£ŠŠÅb£uª¢¢J555¦ƒ@N €À$X–¥††¨l›9ŒdÛZ»–ãw`²( 0IÑhôôIXžé(Èž,ëû?` ( 0IÑhT©Ô ¤^ÓQ5z•J €ÀP@`’Ö¬Ysú-æ@pFú¹0üÜL„“T^^®%K–‰“°0,¡¥K—iÁ‚¦ƒ@Π€À¬_ß @ Ët d‰`°Këׯ5r ¦ ‰Èó:%¥LGq)¹î!öÀQ@` "‘ˆ\בÔm: Œ{]®ëP@`Š( 0uuu²í€D‡Ô)Û¨®®ÎtÈ)˜‚¹sçê²Ë®RB—_~¥JJJL€œB€)Z·®^¡ÐaÓ1`X0Ø¥uëêMÇ€œC€)ŠF£J&»$9¦£À˜!¥R‡Y@Ó@€)JŸ„åJ:d: Œé’ç¹  À4P@`ŠV®\©¢¢9b!a!K¨¨hŽV¬Xa:ä LQ(ÒÕW¯¤uª®®N¡PÈtÈ9˜†µkë q V¡ …ºÔÐÀ:L¦!‰Èqz$0¾;!Çéaþ¦‰Ó0|ú·ažôÏœ°`z( 0 µµµš7¯L,$,D •––©¶¶ÖtÈI˜Û¶‰¬‘e1Rh,«S‘HD–e™Ž9‰ÓÔÐP¯`RX<‡@€ €À4¥ÑIê3¾9®d²t˜ LÓð/¡ ¢Žô̦ÓTSS£ŠŠÅb½tª¢¢J555¦ƒ@΢€À4Y–¥††¨l›9BaÛZ»–ãw`&( 0ÑhôôIXžé(È8O–uˆý0C˜h4ªTjPR¯é(ȸ^¥R'( 0C˜5kÖœ~‹9ü—þÿÌÓA€(//×’%Ë”> ëg¦ã £¶iéÒeZ°`é Ó( 0Cë×7(è’ô²é(Ȩ­_¿ÖtÈyÇÀÀ€6nܨo¼Qååå²m[O>ùä¨ë"‘ˆ<¯S ¢ç³”$wRû?zè!Ù¶­U«Ve>ä Œ£»»[›6mÒÞ½{µzõjIé£wωD于$×ç„ðÏë’&^@xðàAmÞ¼YsçÎ󹂦@¶ ‡ÃêêêRee¥¶oß>î/Ÿuuu²í€\—’¿ÒÛîëêê.xÕý÷߯uëÖ)™Lª§§Ç`sxÆQTT¤ÊÊJI’ç{ÕܹsuÙeWˆW@òYB@P%%%ã^ñâ‹/êé§ŸÖÃ?,ÏóxÆA€Iò¦k®¹F«V­Rkk«é ·P@`>,Iš3gΘÿg;ÊóNHr|N†ÌR*uXŸøÄ'ƽbË–-zíµ×´k×.Í;×Çl{˜€Iøò—¿,Iºøâ‹Ç¼+}–+é¤%þ†C†uÉóÆ?ë7ÞЃ>¨åË—kÑ¢EJ&“ŠÇã>g€ÜÁ+ 0_|Q¿úÕ¯Îþy¬W@V®\©¢¢9:3¬Œ|’PQÑ­X±bÌ÷>ðÀ*))Ñ®]»ÎÎÆÇ+ pgîí¿í¶Ûô£ýhÜëB¡®¾zõéÿóý›1®¸RÒÍ™Š‰Yó3^(yR ,R(uõ¾}ûôØc©ªªJwÜq‡æÎ«“'OÊu] éÀ*++c{:œƒ°eËuttè‹_üâ ˆ$­][¯;þWŽs¿Oé0ûnÖùE1úªî¸ãŽ1¯N$r]Wúö·¿­§žzêì+ ¯¾úª–-[¦O|âúÒ—¾”éà3¸ ÆqæÞþ|PozÓ›&¼>‰Èqz$È|8øä„§gÜùšš•––êî»ïÖþçêÇ?þ±V¬X¡9sæhéÒ¥úñ¬÷¿ÿý>g€ìF€q<ðÀ ƒêëëÓ7¿ùMIROO^ýu}æ3ŸQ__߈ë£Ñèé·˜ÉéŸåðÏv¤/}éKª®®Ö£>ª 6hÆ Z´h‘‚Á æÍ›§ 6Œ;;…Êò˜–€QöíÛ§+®¸BóçÏWoo¯¤ôðù™¿2-ËÒÎ;Gìq]Wóç/Pÿµ’®3³îE•–n×±cGG>pæ9òðÃë–[n9ûøwÜ¡ßýîwZ²d‰ššš˜ÿ€óð Œá̽ýGŽ‘eYgù<÷íÇ|ÄÇØ¶­Hd,ëïy‘–Õ©H$2æÉggž#÷ÝwŸ–/_~öŸX,¦“'OêÕW_Õ¦M› ¤€ìÆ:ŒaÕªUzæ™gFüâéyžxàõ÷÷ëË_þ².¹ä’Q×ÐP¯ßüæÿÈaaðRCûÆ|ïtŸ#Pè¸ ¦àúë¯×o¼¡—^ziÌ÷?óÌ3ºýöÛ%ý¿’Ê|͆ÙÖ'é_ôÌ3Ïè¶Ûn›ôGMô€BÇ-X0çÞ‚5–áÓ’DÏ} I÷¬ñLô€BÇ+ 0‹<ÏÓâÅÕêîþcIo33ò‚**ÚõúëÌôÀlâ˜E–e©¡!*Ûæ—Ö\gÛZ»vìãwÓG€YFOŸ„Š̹˓ewÿ`ú( 0ˢѨR©AI½¦£`Úz•J €@P@`–­Y³æô[ £90éŸÝðÏ0[( 0ËÊË˵dÉ2qV.KhéÒel1€  €@¬_ß @ Ët LS0Ø¥õëךŽy‰‰Däy’R¦£`ÊRrÝCSÞÿ˜ d@$‘ë:’ºMGÁ”½.×u( !È€ºº:Ùv@ ¢ç¢NÙv@uuu¦ƒ@^¢€@Ì;W—]v…( ¹(¡Ë/¿R%%%¦ƒ@^¢€@†¬[W¯Pè°é˜¢`°KëÖÕ›Žy‹F•LvIrLGÁ¤ )•:ÌBÈ dHú$,WÒ!ÓQ0i]ò<—tÈ dÈÊ•+UT4G,$Ì% ÍÑŠ+L€¼E€ …BºúêÕ¢€ä’NÕÕÕ) ™y‹´vm½B!nÁÊ¡P—@€L¢€@E"9N¤¦£`B'ä8=Ì@†Q@ ƒ†OSâ6¬ì—þqd2¨¶¶V󿕉…„¹ ¡ÒÒ2ÕÖÖšydÛ¶"‘5²,æ@²eu*‰È²,ÓQ ¯Q@ Ãê R@²›§@àèà dXzý˜¤>ÓQ0®ãJ&û@P@ Æ©e={¥gt( yȰššUT,ƒèÙ¬SUª©©1ò2̲,54DeÛÌd+ÛîÔÚµ¿ ~ €€¢Ñèé“°<ÓQ0Š'Ë:Äþð |F•J Jê5£ô*•:AŸP@ÀkÖ¬9ýs Ù'ý3þ2‰>(//×’%ËÄIXÙ(¡¥K—iÁ‚¦ƒ@A €€OÖ¯oP Ðe:Î viýúµ¦c@Á €€O"‘ˆ<¯SRÊtœ•’ëbÿøˆ>‰D"r]GR·é(8ëu¹®CQ@À'uuu²í€DÏ&²í€êêêL€‚AŸÌ;W—]v…( Ù$¡Ë/¿R%%%¦ƒ@Á €€Ö­«W(tØt œ viݺzÓ1  P@ÀGÑhTÉd—$ÇthH©Ôa€Ï( à£ôIX®¤C¦£@]ò<—tð|´råJÍ ³ABEEs´bÅ ÓA  P@ÀG¡PHW_½ZlЩºº:…B!ÓA  P@Àgk×Ö+â,ÓB¡.540€~£€€Ï"‘ˆ§GÒ ÓQ Ø 9Nó`|6|ê·a™“þÞsø>«­­Õ¼yeb!¡I •––©¶¶Öt(8ð™mÛŠDÖȲ˜1Ų:‰DdY–é(Pp( `@CC½‚A ˆžC  €!0 =ˆ~LRŸé(踒É>ÐÀ 0üË/ƒèþKÏÞP@À PSS£ŠŠÅbÝ„NUTT©¦¦Æt(H0À²,54DeÛÌøÍ¶;µv-Çï€)0$ž> Ë3¥€x²¬Cìÿƒ( `H4U*5(©×t”Ò«Tê ¢€€!kÖ¬9ýs þI¯‡¿÷¿Q@Àòòr-Y²Lœ„å§„–.]¦ ˜‹­_ß @ ËtŒ‚ viýúµ¦c@A£€€A‘HDž×))e:JHÉu±ÿ £€€A‘HD®ëHê6¥¼.×u( ` ª««“mÄ º:eÛÕÕÕ™ýÿíÝOˆÜwÝð÷ÌMÝ4²¥1¸Ú5›mº53³»yjR% ´aO¥žzОš£×ô*á„R°]xJsÑ€(F+OR‹%µ9TaÿÄÄÀ¦eS:™çÛtMÒlâÎï7³y½NÉofàÍ|a2ïÌïóý 塇¾¤óÛ—­[·–஦€”lf¦™Zí\Ù16½ÁÁ¥ÌÌ4ËŽp×S@JÖh4råÊR’VÙQ6±ÒnŸs!@P@Jvu'¬Õ$‹eGÙÄ–Òé¬@è @Éöïߟ-[î‰ »i>[¶Ü“ñññ²ƒÜõ€’Õjµ8ðHnZÈäädjµZÙAîz @˜žn¦Vs V·ÔjK™š2€Ð €P¯×Ój]Hr¹ì(›Ðå´ZÌô \ÛÉmXïê{j,€Þ €tÑ›o¾™çž{.ãããÙ¶m[öìÙ“ÙÙÙ¼ýöÛkž7::šmÛ¶Ç„Ý0Ÿ{ïÝžÑÑÑ®¬w]Øx•N§Ó);ÀfõÔSOåÔ©S9räH~øá,..æØ±cyï½÷rúôé5»2}å+ç7¿YH§3[bâͧRùß<öØùÕ¯N~tívÖ€5Xv€ÍìèÑ£©×ë¼öq;;;›‰‰‰|ï{ßËË/¿üÑõ©©f~÷»ÿIËy„¨“ÅLM=¹æêí¬ Kè¢ééé뮎Žfß¾}9sæÌšëWÑ—“\J²½˜€›Þ»¹råÒuè·³.l, `N'çÎËÄÄÄšë×¾$ŸÈOEß—äk]N×ï~–ä/ûû•$ÉO~ò“|ãßøÄWÞl]ØX @Áæææ²°°^xaÍõ‘‘‘ìÜù™œ?TN1q çIDAT¿+É—®ï}-kKÚ¯²sçÙ¼ôÒK·|åÍÖ€e,€9s&ßùÎw233“gžyfÍc•J%SST«$Ü(ÕêB¦§o½ýî'­ K(ÈÒÒR¾þõ¯ç¾ûîËñãÇS©T®{N£ÑH¥²˜Ä…ÿ¹N*•Å[žÿ±žu`㸠 ËËËyâ‰'réÒ¥¼þúëÙµk× Ÿ×h4Òn¯$¹˜dG¡7Ÿ‹i·/bYﺰq€.{ÿý÷søðáœ={6'OžÌØØØMŸ{ðàÁýi> Èêꡎ×ÞÓµng]Ø8nÁè¢v»ÙÙÙ¼ñÆyíµ×Òl6?ñùÃÃÃyðÁ½IŠ ¸©ÍgÏž½¹ï¾û®{äv×€ã€.:zôhNœ8‘ÇçÂ… yå•WÖ<þôÓO_÷šC‡¦2?ÿi·‹J¹9 .åСÿºácw².l  ‹þøÇ?¦R©äĉ9qâÄšÇ*•Ê ¿èÖëõ¼úêñ$í$ÅÝtÚY]]¼îÂÝɺ°1€.úõ¯}Û¯©×ëY]m%9ŸÄPôùGVW[7- w².l 3 =frr2Õê@>¢æN,¤ZÈäädÙAø7 @ÊC}1 Èb>ccû²uëÖ²ƒðo€43ÓL­v®ì}kpp)33v¶èE @j4¹re)I«ì(}胴Ûçny:åP@zP½^O§³šd±ì(}h)ÎêMÐ(—Ѓöïߟ-[î‰ ïÄ|¶l¹'ãããeà€T«ÕràÀ#Q@îÄB&''S«ÕÊÀ ( =jzº™ZÍ-X·«V[ÊÔ”t€^¥€ô¨z½žVëB’ËeGé#—Ój]0ÿÐÀum'·a­ßÕ÷ÊX½KèQ£££Ù¶m{Hx;æsï½Û3::ZvnBèQÕj5õúÁT*æ@Ö«RYH½^O¥R); 7¡€ô°f³‘ÁAd½–Òlºý  —) =¬Ñh¤ÕZNr©ì(}àR®\Y6ÿÐã€vm7'ƒè·vuVÆX½Mèa###¹ÿþOÇ úz,dçÎÏddd¤ì | ‡U*•LO7S­š¹•ju1ÓÓ èu @k4ÿÚ «Sv”ÖI¥²`þ ( =®^¯§Ý^Ir±ì(=ìbÚíËæ?ú€Ðã ¢¯ÇÕ™ƒ–œ€[Q@zÜððp|po ¢’ùìÙ³7ÃÃÃeà€>03ÓÌÀÀRÙ1zÖààRff¦ÊŽÀ:( } Ñh¤ÓYLÒ.;JjguuÑ:@ŸP@ú@½^ÏêêIΗ¥ý#««-è}Bè“““©V«1r# ©V299YvÖAèCCCyè¡}±ÖÌgll_¶nÝZvÖAè33ÍÔjÑÿÝÕt' ô  OÔëõ\¹²”¤Uv”ÒJ»}Îü@Q@úÄÕ°V“øäšÅt:«vÀè# @ŸØ¿¶l¹'Ñ?n>[¶Ü“ñññ²ƒ°N @Ÿ¨Õj9pà@ ¢ÜByä‘Ôjµ²ƒ°N @™žž2ˆþ1µÚ¹LO; Ÿ( }¤^¯§Õ:ŸärÙQzÀå´Zç  ô \û²í6¬ß ¿( }äóŸÿ|¶mÛ$Iæsï½Û3::ZvnƒÐGªÕjêõƒ©TJe!õz=ÕªÊú‰Om€>Ól628¸XvŒÒ ,¥Ùtþ@¿Q@úL£ÑH«µœäRÙQJt)W®,;€ ) }Æ zòáaŒÐúÐgFFFrÿýŸÎÝ}"úBvîüLFFFÊÀmR@úL¥RÉôt3ÕêÝ;R­.fzºYv î€ЇF*•Å$²£” “JeÁü@ŸR@úP½^O»½’äbÙQJp1íöeó}JèCw÷ úÕÙ—ƒ–œ€;¡€ô¡ááá<øàÞÜÞ úϺgƒ¬7ß|öìÙ›ááᮦ ;€>53ÓÌÀÀÒm¼â/]˲1Ö—opp)33S]Î@·( }ªÑh¤ÓYLÒ.;JÚY]]4€ÐÇ€>U¯×³ºúA’óeG)Ð?²ºÚ2€ÐÇ€>599™jµš»ë@Â…T«™œœ,;wh°ìÜ™¡¡¡|á c9sæl’ÝëxE;I/^¸ž|góÙÏî-" ]Rét:wã)V›Â·¿ýíüð‡?,;Fáþð‡?äÑG-;w@èc+++9sæLÙ1 766–­[·–€; €…1„F £€…Q@6©7ß|3Ï=÷\ÆÇdzmÛ¶ìÙ³'³³³yûí·ËŽ–$ùóŸÿœ#GŽäsŸû\†††²cÇŽÌÌÌdnn®ìht‘s@6©ïÿû9uêTŽ9’‡~8‹‹‹9vìX}ôÑœ>}:ããã¥æûûßÿž÷Þ{/ßúÖ·²{÷¬äøñãùæ7¿™wÞy'ßýîwKÍ@wØ `“:uêTêõz¯ý_ÓÙ³g311‘§žz*/¿ür‰énluu5_úÒ—rñâÅüío+;]à,€MjzzzMùH’ÑÑÑìÛ·¯gÏ©V«yàR«ÕÊŽ@—¸ à.ÒétrîܹLLL”å#+++YYYÉòòr~úÓŸæ¿øEŽ;Vv,ºD¸‹ÌÍÍeaa!/¼ðBÙQ>òüóÏçG?úQ’dpp0?øÁòì³Ï–œ €n1p—8sæLšÍf&&&òú믧R©”)IòÖ[oe~~> ™››Ë/ù˼øâ‹yæ™gÊŽ@( w¥¥¥:t(ív;§OŸÎ®]»ÊŽtS_ýêWóûßÿ> ùÔ§>Uv6˜!t€Mnyy9O<ñD.]º”Ÿÿüç=]>’äÉ'ŸÌòòrÞzë­²£Ðf@6±÷ß?‡ÎÙ³gsòäÉŒ•é–._¾œäêŽXl>>Ý6©v»ÙÙÙ¼ñÆyíµ×Òl6ËŽ´Æùó篻Öjµòãÿ8;vì(ý DºÃ/ ›ÔÑ£Gsâĉ>|8.\È+¯¼²æñ§Ÿ~º¤dW=ûì³y÷Ýwóå/9»wïÎÒÒRæææò׿þ5/½ôRJÍ@wBؤ{ì±üö·¿Í>æ+•JÚív ©®yõÕWóâ‹/æOúSþùÏfûöíi6›yþùçóøã—š €îQ@€Â˜ £€…Q@€Â( @a 0 P(ŒF £€…Q@€Â( @a 0 P(ŒF £€…Q@€Â( @a 0 P(ŒF £€…Q@€Â( @a 0 P(ŒF £€…Q@€Â( @a 0 P(ŒæÿÌ7-Là¼ìˆIEND®B`‚wcsaxes-0.6/wcsaxes/tests/baseline_images/update_clip_path_rectangular.png0000644000077000000240000001713712436367710027324 0ustar tomstaff00000000000000‰PNG  IHDR Xšv‚psBIT|dˆ pHYsaa¨?§iIDATxœíݰWÿñ×P—Ápä"â­QP[ Æ0t³ÖYÇi u¿¥l³.•¥;­B®¶5S3±°µÍnXÌÄêVJRka–˜«»ZŽýPs±m5'~Ä/(0ù!÷û‡IòKH®ïs?ðxÌ8ƒçóñøšñŽ3Ï{Îù|Z]]]](ЫéÀáC€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€eú4=  k׮ͽ÷Þ›!C†¤oß¾MÏá0³yóæ,Y²$çŸ~Øô€R8,Ý{ï½¹üòË›žÁaîÖ[oÍ_þå_6= ”KC† ùÝŸþ_’îú ôœ$ºé\¯ûNwî[›äÛ/û98|à°ôûÛ®&9¡›ÎÚ»ÏõZ°ïàtÿ>·ÿ‡#¡ePF€e@·Öô€ý°ïàôô}íA€t›±MØûNOßÐPF€ePF€=ÎÆ3uêÔ\pÁ0`@zõê•[n¹e—÷tuuåæ›oÎE]”O<1G}tFŒ‘éÓ§çùçŸoh9°?èqÖ¬Y“iÓ¦åÉ'ŸÌé§Ÿž$iµZ»¼gãÆ¹âŠ+²nݺ|øÃÎ 7Ü3Ï<3S§N͘1cš˜ €>MØ]gggV¯^AƒeÁ‚=zôï9ꨣò“Ÿü$ò'²óØ?øÁ 2$S§NÍý÷ߟóÎ;¯r6p\zœ#<2ƒ Jòâ­V{sÄGì/¹ä’K’$ .|í¯š)«W¯N’ 8°á%ÀÞàòÿø9æ˜c<=”g@€CÆŒ3rÿý÷çK_úRú÷ïßô`/\ ·Ýv[>õ©OåCúPþú¯ÿºé9À> íýçþg&L˜w½ë]™={vÓs€Wà, ­=òÈ#ùó?ÿóœyæ™ùæ7¿™^½þÐß«ÌIÒ{·cÃ’Œíž»“<±Û±íM èж~ñ‹_ä /ÌÉ'Ÿœ»îº+GuÔ«8Ë„$'t÷4x™±Ù3hW%¹±-Í @4kÖ¬¬_¿>+W®L’ÜyçY¶lY’dÒ¤IiµZ9ÿüó³~ýú|ìcËüùówùçO=õÔ½~OЬV×¾¾å  AC‡ÍÒ¥K“$­V+É‹_JØjµ²xñâìØ±#'Ÿ|rZ­Ö^¿¬ðýï¾ò•¯ìóü=öXÎ8ãŒ$WÅê½xdÁ‚5jTÓcJ¹ôH‹/Þï{vìØQ°èN> (#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2(#@€2èQ6nܘ©S§æ‚ .È€Ò«W¯ÜrË-{}ï/~ñ‹\pÁyÝë^—ŽŽŽL˜0!k×®-^ ü!У¬Y³&Ó¦MË“O>™ÓO?=IÒjµöxßòåËsÎ9çä—¿üeþáþ!ýèGó½ï}/ï|ç;ó /TÏPŸ¦¼\gggV¯^AƒeÁ‚=zô^ß7cÆŒlÞ¼9?ûÙÏò†7¼!Iræ™gæï|gn¾ùæ\yå••³€ä Уyä‘4hP’¤««kŸï»ýöÛó®w½kg|$Éyç—?þã?Î7¿ùÍ×|'ðê í¬X±"kÖ¬É[ßúÖ=^=zt~ö³Ÿ5° 8h;«V­J’œp {¼v 'ä׿þµç@ ‡ @ÛÙ¼ys’䨣ŽÚãµ?ú£?Úå=@Ï"@€¶Ó·oß$ÉóÏ?¿Çk[¶lÙå=@Ï"@€¶óÒ­W/ÝŠõr«V­JGGGŽ8âˆêYÀð1¼@Ûyýë_ŸãŽ;.>úè¯ýô§?Ýùý!fN’Þ»–dìA,„—»;É»ÛÞÄ€A€méÝï~wn¹å–,_¾|çGñÞÿýY´hQ®¿þú?àL’ìù0;tŸ±Ù3hW%¹±-Í @3kÖ¬¬_¿>+W®L’ÜyçY¶lY’dÒ¤Iéß¿>ñ‰Oä[ßúVÎ=÷Ü|ä#ÉoûÛ|îsŸËÈ‘#ó| ÉùÀ+hu½Ò7}4`èСYºti’¤Õj%yñK [­V/^œO<1IòÄOäºë®Ë~ô£uÔQ¹ð óOÿôO9î¸ãöûïxì±ÇrÆg$¹*®€PïÅ+ ,ȨQ£šPÊ ÇY¼xñ½oذa¹çž{^ã5@wò)X@” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @” @Ûú¯ÿú¯\|ñÅéììL¿~ýòæ7¿9Ó¦MËæÍ››žìCŸ¦¼?þxÞñŽw¤³³3×^{m Ÿüä'™:uj,Xï|ç;MOöB€méßþíß²uëÖ|ï{ßË›ßüæ$ɇ>ô¡ìر#sæÌɆ rÌ1Ç4¼Ø[°€¶Ô·oß$É Aƒv9>xðàôîÝ;Gyd³€ý @[ºâŠ+rüñÇçƒü`~þóŸçW¿úUn»í¶Ìž=;“&MÚ(@Ïâ, -uvvæÇ?þqÆŽ›·¼å-;Ož<9Ÿþô§\¼´¥gžy&cÆŒI’ÜtÓMéèèÈ]wÝ•éÓ§çøãÏÕW_ÝðB`oЖ¦M›–+Vä©§žJggg’ä’K.ÉŽ;òñ<ï}ï{3`À€†W»ó Ж~ô£å-oyËÎøxɸqã²iÓ¦ü÷ÿwCË€Wâ Ж^xá…lß¾}¯Ç“dÛ¶mx¦9IzïvlX’±3^æî$OìvlÏŸ]€Ã…ÚÒ¨Q£ò­o}+‹-ÊßøÆÇ¿ño¤wïÞ9räžiB’^“ð¢±Ù3hW%¹±-Í @[ú»¿û»Ü~ûíùÓ?ýÓ\sÍ50`@îºë®ÜsÏ=¹òÊ+3xðà¦'{!@€¶4räÈ<ðÀ™:uj>÷¹ÏeË–-9ùä“3cÆŒ|ìckz°h[gžyfþýßÿ½éÀÀ§`ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€mí±ÇËE]”ŽŽŽôë×/#FŒÈ¿øÅ¦gûЧé¯ÖüÇdܸq9ãŒ32eÊ”}ôÑyúé§³bÅŠ¦§û @€¶ôì³Ïf„ 7n\æÍ›×ô๠hK_ÿú×óÿ÷™>}z’dãÆÙ±cGë€ý @[ºï¾ûÒ¿ÿüêW¿Êi§–×½îu9æ˜cò7ó7yþù盞ìƒÚÒ¢E‹²mÛ¶\rÉ%3fL¾ýíoçŠ+®ÈìÙ³ó| éyÀ>xhKÏ=÷\6mÚ”øÃ™9sf’ä’K.ÉÖ­[ó/ÿò/ùô§?SO=µá•Àî\ÚRß¾}“$ï}ï{w9þÒß?üðÃ囀ý @[êììL’üñ»4hP’ä7¿ùMù&`ÿÜ‚´¥·¾õ­¹ï¾û²|ùò¼ñoÜy|åÊ•I’ãŽ;îÏ4'IïÝŽ K2¶;fB’»“<±Û±íM èЖ.»ì²|æ3ŸÉ—¿üåœ{î¹;ÿë¿þkŽ8âˆüÙŸýÙžiB’^‹‰ð;c³gЮJrc[š'@€¶túé§çŠ+®ÈW¾ò•lÛ¶-çœsNxàÌ›7/ŸøÄ'2xðà¦'{!@€¶5{öìœxâ‰ùêW¿š;î¸#C† ÉÌ™33iÒ¤¦§û @€¶Õ§OŸL™2%S¦Liz p€| PF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€ePF€epȘ>}zzõê•#F4=Ø–/_ž3f¤_¿~iµZMÏö¡OÓºÃG?úÑœ}öÙÙ¶m[Ö®]Ûô`\ÚÞƒ>˜Ûo¿=3gÎLWW—+ Ѓ  ­mß¾='NÌ•W^™áÇ7=Ø·`mmöìÙY¶lY¾ÿýï7=8®€mkݺu™2eJ¦L™’ŽŽŽ¦ç@€mkòäÉ8p`&NœØô๠hK‹-ÊM7Ý”™3gfùòå;oÙ²%[·nÍÒ¥KÓ¿ÿ{ì± ®v'@€¶´bÅŠìØ±#“&MʤI“öx}èС¹öÚkóÏÿüÏû9Óœ$½w;6,ÉØnZ w'yb·cÛ›Ð# -1"wÜqÇ.¹ÛÕÕ•É“'ç¹çžË 7ÜSN9åÎ4!É ¯ÙNx1fwÚUInl` @óЖ:::rñÅïqüóŸÿ|’䢋.ªž¡‡”V«å‹ s8¤üà?hzð \Ê ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÚÖ£>šk®¹&ÇÏÑG“N:)ãÇÏ¢E‹šžìCŸ¦¼ZŸýìgóÐCåÒK/ÍÈ‘#³jժ̚5+£FÊÃ?œáÇ7=ØÚÖõ×_ŸÑ£G§OŸßÿ¯lüøñ1bD>ó™Ïäk_ûZƒë€½ @ÛzÛÛ޶DZSO=5Æ ËÂ… Xìg@€CJWWWžyæ™ 8°é)À^à2wîܬ\¹2ãÇoz °8d,\¸0W_}uÎ>ûì¼ï}ïkz°8$¬^½:^xaŽ=öØÌ›7/­V«éIÀ^xh{6lȘ1còì³Ïæ‡?üaÜô$`ÐÖ¶lÙ’qãÆåé§ŸÎ}÷Ý—7½éMàæ$é½Û±aIÆvÏ@ÈÝIžØíØö&†ôh[Û·oÏøñãóÈ#ä»ßýnÎ:ë¬Wq– INèîið2c³gЮJrc[š'@€¶uýõ×gþüù7n\Ö®]›[o½u—×/¿üò†–û"@€¶õóŸÿ<­V+óçÏÏüùówy­Õj èж~ðƒ4=øù^ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ Œè6w7=`?ì;8=}@{ Ýæ‰¦ì‡}§§ïh(#@€2(Ó§éMؼyóïþ´¶Ϻ=ɪn<_w³ïàtç¾î~ÿspø ÀaiÉ’%¿ûÓ·»ùÌ7vóùº›}§{÷-Y²$oûÛ»õœ=]«««««éÕÖ®]›{ï½7C† Iß¾}›žÃafóæÍY²dIÎ?ÿü 8°é9¥PÆCè@” @” @ð*mܸ1S§NÍ\¤W¯^¹å–[šžµÓ£>šk®¹&ÇÏÑG“N:)ãÇÏ¢E‹šž–$ùßÿýß\zé¥9å”SÒ¯_¿tttäì³ÏÎܹs›ž¶OÓ§OO¯^½2bĈ¦§´-_Dð*­Y³&Ó¦MËI'”ÓO?=<ð@Z­VÓ³vúìg?›‡z(—^ziFŽ™U«VeÖ¬Y5jT~øá >¼Ñ}Ë–-ËsÏ=—÷¿ÿýéìì̦M›2oÞ¼üÕ_ýU–,Y’O~ò“îÛÝòåË3cÆŒôëׯGýwh7¾àUÚºukÖ¯_ŸAƒeÁ‚=ztn¾ùæL˜0¡éiI’‡z(£GNŸ>¿ÿ]ÓÓO?#Fä=ïyO¾öµ¯5¸nïvìØ‘3Î8#¿þõ¯³téÒ¦çìâ/þâ/²nݺlÛ¶-k×®Íã?Þô$€¶ä,€WéÈ#Ì Aƒ’$=ñw9o{ÛÛv‰$9õÔS3lذ,\¸°¡U¯¬W¯^yÃÞ#Ž8¢é)»xðÁsûí·gæÌ™éêêrà ¸ à0ÒÕÕ•gžy¦G=ðiÓ¦lÚ´)6lÈwÞ™{ï½7³fÍjzÖNÛ·oÏĉså•W6~ÛÀ¡@€FæÎ›•+Wæïÿþ²Óu×]—o¼1IÒ§OŸ|á _ÈUW]Õðªß›={v–-[–ïÿûMO8$€ÃÄÂ… sõÕWçì³ÏÎûÞ÷¾¦çìô·û·¹ì²Ë²råÊÌ;7×\sMúöíÛ#6®[·.S¦LÉ”)SÒÑÑÑô€C‚8 ¬^½:^xaŽ=öØÌ›7¯G=ÃpÚi§å´ÓNK’\~ùå9ÿüósíµ×æ²Ë.Kß¾}Ý6yòä 80'NltÀ¡ÄC臸 6d̘1yöÙgsÏ=÷dðàÁMOzEï~÷»³aÆ<ùä“îX´hQnºé¦Lœ81Ë—/Ï’%K²dÉ’lÙ²%[·nÍÒ¥Kó›ßü¦ÑíH€¶lÙ’qãÆåé§ŸÎ]wÝ•7½éMMOگ͛7'yñ±š´bÅŠìØ±#“&MÊÉ'Ÿ¼ó¯Ÿþô§yê©§2tèÐL›6­ÑíÈ-X‡¨íÛ·güøñyä‘GòÝï~7guVÓ“v±fÍšwÜq»{á…2gΜttt4þ‰S#FŒÈwܱËíj]]]™øà^¿$±Õjeûöí ¬ú½Ûn»-_þò—óøãgݺuéß¿Î:ë¬\wÝu9ï¼óÝöJÎ=÷ܬ[·.ÿó?ÿÓô€¶$@€2BÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ ŒÊ Ìÿ¥ æ^$gIEND®B`‚wcsaxes-0.6/wcsaxes/tests/coveragerc0000644000077000000240000000143612443671565017655 0ustar tomstaff00000000000000[run] source = {packagename} omit = {packagename}/_astropy_init* {packagename}/conftest* {packagename}/cython_version* {packagename}/setup_package* {packagename}/*/setup_package* {packagename}/*/*/setup_package* {packagename}/tests/* {packagename}/*/tests/* {packagename}/*/*/tests/* {packagename}/version* {packagename}/wcs_utils.py [report] exclude_lines = # Have to re-enable the standard pragma pragma: no cover # Don't complain about packages we have installed except ImportError # Don't complain if tests don't hit assertions raise AssertionError raise NotImplementedError # Don't complain about script hooks def main\(.*\): # Ignore branches that don't pertain to this version of Python pragma: py{ignore_python_version}wcsaxes-0.6/wcsaxes/tests/data/0000755000077000000240000000000012553237435016513 5ustar tomstaff00000000000000wcsaxes-0.6/wcsaxes/tests/data/2MASS_k_header0000644000077000000240000000215512436367710021110 0ustar tomstaff00000000000000WCSAXES = 2 / Number of coordinate axes CRPIX1 = 361.0 / Pixel coordinate of reference point CRPIX2 = 360.5 / Pixel coordinate of reference point CDELT1 = -0.001388889 / [deg] Coordinate increment at reference point CDELT2 = 0.001388889 / [deg] Coordinate increment at reference point CUNIT1 = 'deg' / Units of coordinate increment and value CUNIT2 = 'deg' / Units of coordinate increment and value CTYPE1 = 'RA---TAN' / Right ascension, gnomonic projection CTYPE2 = 'DEC--TAN' / Declination, gnomonic projection CRVAL1 = 266.4 / [deg] Coordinate value at reference point CRVAL2 = -28.93333 / [deg] Coordinate value at reference point LONPOLE = 180.0 / [deg] Native longitude of celestial pole LATPOLE = -28.93333 / [deg] Native latitude of celestial pole EQUINOX = 2000.0 / [yr] Equinox of equatorial coordinates wcsaxes-0.6/wcsaxes/tests/data/cube_header0000644000077000000240000000312312436367710020663 0ustar tomstaff00000000000000WCSAXES = 3 / Number of coordinate axes CRPIX1 = -799.0 / Pixel coordinate of reference point CRPIX2 = -4741.913 / Pixel coordinate of reference point CRPIX3 = -187.0 / Pixel coordinate of reference point CDELT1 = -0.006388889 / [deg] Coordinate increment at reference point CDELT2 = 0.006388889 / [deg] Coordinate increment at reference point CDELT3 = 66.42361 / [m s-1] Coordinate increment at reference point CUNIT1 = 'deg' / Units of coordinate increment and value CUNIT2 = 'deg' / Units of coordinate increment and value CUNIT3 = 'm s-1' / Units of coordinate increment and value CTYPE1 = 'RA---SFL' / Right ascension, Sanson-Flamsteed projection CTYPE2 = 'DEC--SFL' / Declination, Sanson-Flamsteed projection CTYPE3 = 'VOPT' / Optical velocity (linear) CRVAL1 = 57.6599999999 / [deg] Coordinate value at reference point CRVAL2 = 0.0 / [deg] Coordinate value at reference point CRVAL3 = -9959.44378305 / [m s-1] Coordinate value at reference point LONPOLE = 0.0 / [deg] Native longitude of celestial pole LATPOLE = 90.0 / [deg] Native latitude of celestial pole EQUINOX = 0.0 / [yr] Equinox of equatorial coordinates SPECSYS = 'LSRK' / Reference frame of spectral coordinates wcsaxes-0.6/wcsaxes/tests/data/msx_header0000644000077000000240000000203412436367710020554 0ustar tomstaff00000000000000WCSAXES = 2 / Number of coordinate axes CRPIX1 = 75.907 / Pixel coordinate of reference point CRPIX2 = 74.8485 / Pixel coordinate of reference point CDELT1 = -0.006666666828 / [deg] Coordinate increment at reference point CDELT2 = 0.006666666828 / [deg] Coordinate increment at reference point CUNIT1 = 'deg' / Units of coordinate increment and value CUNIT2 = 'deg' / Units of coordinate increment and value CTYPE1 = 'GLON-CAR' / galactic longitude, plate caree projection CTYPE2 = 'GLAT-CAR' / galactic latitude, plate caree projection CRVAL1 = 0.0 / [deg] Coordinate value at reference point CRVAL2 = 0.0 / [deg] Coordinate value at reference point LONPOLE = 0.0 / [deg] Native longitude of celestial pole LATPOLE = 90.0 / [deg] Native latitude of celestial pole wcsaxes-0.6/wcsaxes/tests/data/rosat_header0000644000077000000240000000203412436367710021075 0ustar tomstaff00000000000000WCSAXES = 2 / Number of coordinate axes CRPIX1 = 240.5 / Pixel coordinate of reference point CRPIX2 = 120.5 / Pixel coordinate of reference point CDELT1 = -0.675 / [deg] Coordinate increment at reference point CDELT2 = 0.675 / [deg] Coordinate increment at reference point CUNIT1 = 'deg' / Units of coordinate increment and value CUNIT2 = 'deg' / Units of coordinate increment and value CTYPE1 = 'GLON-AIT' / galactic longitude, Hammer-Aitoff projection CTYPE2 = 'GLAT-AIT' / galactic latitude, Hammer-Aitoff projection CRVAL1 = 0.0 / [deg] Coordinate value at reference point CRVAL2 = 0.0 / [deg] Coordinate value at reference point LONPOLE = 0.0 / [deg] Native longitude of celestial pole LATPOLE = 90.0 / [deg] Native latitude of celestial pole wcsaxes-0.6/wcsaxes/tests/data/slice_header0000644000077000000240000000214312436367710021045 0ustar tomstaff00000000000000WCSAXES = 2 / Number of coordinate axes CRPIX1 = 1.0 / Pixel coordinate of reference point CRPIX2 = 99.0 / Pixel coordinate of reference point CDELT1 = 0.00416666666667 / [deg] Coordinate increment at reference point CDELT2 = 1000.0 / [m s-1] Coordinate increment at reference point CUNIT1 = 'deg' / Units of coordinate increment and value CUNIT2 = 'm s-1' / Units of coordinate increment and value CTYPE1 = 'OFFSET' / Coordinate type code CTYPE2 = 'VRAD' / Radio velocity (linear) CRVAL1 = 0.0 / [deg] Coordinate value at reference point CRVAL2 = 50000.0 / [m s-1] Coordinate value at reference point LONPOLE = 0.0 / [deg] Native longitude of celestial pole LATPOLE = 90.0 / [deg] Native latitude of celestial pole RESTFRQ = 4829659400.0 / [Hz] Line rest frequency EQUINOX = 2000.0 / [yr] Equinox of equatorial coordinates SPECSYS = 'LSRK' / Reference frame of spectral coordinates wcsaxes-0.6/wcsaxes/tests/setup_package.py0000644000077000000240000000015012436367710020763 0ustar tomstaff00000000000000def get_package_data(): return {'wcsaxes.tests': ['coveragerc', 'baseline_images/*.png', 'data/*']} wcsaxes-0.6/wcsaxes/tests/test_coordinate_helpers.py0000644000077000000240000000062112436367710023063 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst from ..core import WCSAxes import matplotlib.pyplot as plt def test_getaxislabel(): fig = plt.figure() ax = WCSAxes(fig, [0.1, 0.1, 0.8, 0.8], aspect='equal') ax.coords[0].set_axislabel("X") ax.coords[1].set_axislabel("Y") assert ax.coords[0].get_axislabel() == "X" assert ax.coords[1].get_axislabel() == "Y" wcsaxes-0.6/wcsaxes/tests/test_display_world_coordinates.py0000644000077000000240000001120612533356270024456 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst from ..core import WCSAxes import matplotlib.pyplot as plt from matplotlib.backend_bases import KeyEvent from astropy.wcs import WCS from astropy.extern import six from astropy.tests.helper import pytest from astropy.coordinates import FK5 from astropy.time import Time from .test_images import BaseImageTests class TestDisplayWorldCoordinate(BaseImageTests): def test_overlay_coords(self, tmpdir): wcs = WCS(self.msx_header) fig = plt.figure(figsize=(4,4)) canvas = fig.canvas ax = WCSAxes(fig, [0.1, 0.1, 0.8, 0.8], wcs=wcs) fig.add_axes(ax) # On some systems, fig.canvas.draw is not enough to force a draw, so we # save to a temporary file. fig.savefig(tmpdir.join('test1.png').strpath) # Testing default displayed world coordinates string_world = ax._display_world_coords(0.523412, 0.518311) assert string_world == six.u('0\xb029\'45" -0\xb029\'20" (world)') # Test pixel coordinates event1 = KeyEvent('test_pixel_coords', canvas, 'w') fig.canvas.key_press_event(event1.key, guiEvent=event1) string_pixel = ax._display_world_coords(0.523412, 0.523412) assert string_pixel == "0.523412 0.523412 (pixel)" event3 = KeyEvent('test_pixel_coords', canvas, 'w') fig.canvas.key_press_event(event3.key, guiEvent=event3) # Test that it still displays world coords when there are no overlay coords string_world2 = ax._display_world_coords(0.523412, 0.518311) assert string_world2 == six.u('0\xb029\'45" -0\xb029\'20" (world)') overlay = ax.get_coords_overlay('fk5') # Regression test for bug that caused format to always be taken from # main world coordinates. overlay[0].set_major_formatter('d.ddd') # On some systems, fig.canvas.draw is not enough to force a draw, so we # save to a temporary file. fig.savefig(tmpdir.join('test2.png').strpath) event4 = KeyEvent('test_pixel_coords', canvas, 'w') fig.canvas.key_press_event(event4.key, guiEvent=event4) # Test that it displays the overlay world coordinates string_world3 = ax._display_world_coords(0.523412, 0.518311) assert string_world3 == six.u('267.176 -28\xb045\'56" (world, overlay 1)') overlay = ax.get_coords_overlay(FK5()) # Regression test for bug that caused format to always be taken from # main world coordinates. overlay[0].set_major_formatter('d.ddd') # On some systems, fig.canvas.draw is not enough to force a draw, so we # save to a temporary file. fig.savefig(tmpdir.join('test3.png').strpath) event5 = KeyEvent('test_pixel_coords', canvas, 'w') fig.canvas.key_press_event(event4.key, guiEvent=event4) # Test that it displays the overlay world coordinates string_world4 = ax._display_world_coords(0.523412, 0.518311) assert string_world4 == six.u('267.176 -28\xb045\'56" (world, overlay 2)') overlay = ax.get_coords_overlay(FK5(equinox=Time("J2030"))) # Regression test for bug that caused format to always be taken from # main world coordinates. overlay[0].set_major_formatter('d.ddd') # On some systems, fig.canvas.draw is not enough to force a draw, so we # save to a temporary file. fig.savefig(tmpdir.join('test4.png').strpath) event6 = KeyEvent('test_pixel_coords', canvas, 'w') fig.canvas.key_press_event(event5.key, guiEvent=event4) # Test that it displays the overlay world coordinates string_world5 = ax._display_world_coords(0.523412, 0.518311) assert string_world5 == six.u('267.652 -28\xb046\'23" (world, overlay 3)') def test_cube_coords(self, tmpdir): wcs = WCS(self.cube_header) fig = plt.figure(figsize=(4,4)) canvas = fig.canvas ax = WCSAxes(fig, [0.1, 0.1, 0.8, 0.8], wcs=wcs, slices=('y', 50, 'x')) fig.add_axes(ax) # On some systems, fig.canvas.draw is not enough to force a draw, so we # save to a temporary file. fig.savefig(tmpdir.join('test.png').strpath) # Testing default displayed world coordinates string_world = ax._display_world_coords(0.523412, 0.518311) assert string_world == six.u('2563 51\xb043\'01" (world)') # Test pixel coordinates event1 = KeyEvent('test_pixel_coords', canvas, 'w') fig.canvas.key_press_event(event1.key, guiEvent=event1) string_pixel = ax._display_world_coords(0.523412, 0.523412) assert string_pixel == "0.523412 0.523412 (pixel)" wcsaxes-0.6/wcsaxes/tests/test_formatter_locator.py0000644000077000000240000003640312471145036022741 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import numpy as np from numpy.testing import assert_almost_equal from astropy import units as u from astropy.extern import six from astropy.tests.helper import pytest from ..formatter_locator import AngleFormatterLocator, ScalarFormatterLocator class TestAngleFormatterLocator(object): def test_no_options(self): fl = AngleFormatterLocator() assert fl.values is None assert fl.number == 5 assert fl.spacing is None def test_too_many_options(self): with pytest.raises(ValueError) as exc: AngleFormatterLocator(values=[1.,2.], number=5) assert exc.value.args[0] == "At most one of values/number/spacing can be specifed" with pytest.raises(ValueError) as exc: AngleFormatterLocator(values=[1.,2.], spacing=5. * u.deg) assert exc.value.args[0] == "At most one of values/number/spacing can be specifed" with pytest.raises(ValueError) as exc: AngleFormatterLocator(number=5, spacing=5. * u.deg) assert exc.value.args[0] == "At most one of values/number/spacing can be specifed" with pytest.raises(ValueError) as exc: AngleFormatterLocator(values=[1.,2.], number=5, spacing=5. * u.deg) assert exc.value.args[0] == "At most one of values/number/spacing can be specifed" def test_values(self): fl = AngleFormatterLocator(values=[0.1, 1., 14.] * u.degree) assert fl.values.to(u.degree).value.tolist() == [0.1, 1., 14.] assert fl.number is None assert fl.spacing is None values, spacing = fl.locator(34.3, 55.4) assert_almost_equal(values.to(u.degree).value, [0.1, 1., 14.]) def test_number(self): fl = AngleFormatterLocator(number=7) assert fl.values is None assert fl.number == 7 assert fl.spacing is None values, spacing = fl.locator(34.3, 55.4) assert_almost_equal(values.to(u.degree).value, [35., 40., 45., 50., 55.]) values, spacing = fl.locator(34.3, 36.1) assert_almost_equal(values.to(u.degree).value, [34.5, 34.75, 35., 35.25, 35.5, 35.75, 36.]) fl.format = 'dd' values, spacing = fl.locator(34.3, 36.1) assert_almost_equal(values.to(u.degree).value, [35., 36.]) def test_spacing(self): with pytest.raises(TypeError) as exc: AngleFormatterLocator(spacing=3.) assert exc.value.args[0] == "spacing should be an astropy.units.Quantity instance with units of angle" fl = AngleFormatterLocator(spacing=3. * u.degree) assert fl.values is None assert fl.number is None assert fl.spacing == 3. * u.degree values, spacing = fl.locator(34.3, 55.4) assert_almost_equal(values.to(u.degree).value, [36., 39., 42., 45., 48., 51., 54.]) fl.spacing = 30. * u.arcmin values, spacing = fl.locator(34.3, 36.1) assert_almost_equal(values.to(u.degree).value, [34.5, 35., 35.5, 36.]) fl.format = 'dd' values, spacing = fl.locator(34.3, 36.1) assert_almost_equal(values.to(u.degree).value, [35., 36.]) def test_minor_locator(self): fl = AngleFormatterLocator() values, spacing = fl.locator(34.3, 55.4) minor_values = fl.minor_locator(spacing, 5, 34.3, 55.4) assert_almost_equal(minor_values.to(u.degree).value, [36., 37., 38., 39., 41., 42., 43., 44., 46., 47., 48., 49., 51., 52., 53., 54.]) minor_values = fl.minor_locator(spacing, 2, 34.3, 55.4) assert_almost_equal(minor_values.to(u.degree).value, [37.5, 42.5, 47.5, 52.5]) fl.values = [0.1, 1., 14.] * u.degree values, spacing = fl.locator(34.3, 36.1) minor_values = fl.minor_locator(spacing, 2, 34.3, 55.4) assert_almost_equal(minor_values.to(u.degree).value, []) @pytest.mark.parametrize(('format', 'string'), [('dd', six.u('15\xb0')), ('dd:mm', six.u('15\xb024\'')), ('dd:mm:ss', six.u('15\xb023\'32"')), ('dd:mm:ss.s', six.u('15\xb023\'32.0"')), ('dd:mm:ss.ssss', six.u('15\xb023\'32.0316"')), ('hh', '1h'), ('hh:mm', '1h02m'), ('hh:mm:ss', '1h01m34s'), ('hh:mm:ss.s', '1h01m34.1s'), ('hh:mm:ss.ssss', '1h01m34.1354s'), ('d', '15'), ('d.d', '15.4'), ('d.dd', '15.39'), ('d.ddd', '15.392'), ('m', '924'), ('m.m', '923.5'), ('m.mm', '923.53'), ('s', '55412'), ('s.s', '55412.0'), ('s.ss', '55412.03'), ]) def test_format(self, format, string): fl = AngleFormatterLocator(number=5, format=format) assert fl.formatter([15.392231] * u.degree, None)[0] == string @pytest.mark.parametrize(('separator', 'format', 'string'), [(('deg', "'", '"'), 'dd', '15deg'), (('deg', "'", '"'), 'dd:mm', '15deg24\''), (('deg', "'", '"'), 'dd:mm:ss', '15deg23\'32"'), ((':', "-", 's'), 'dd:mm:ss.s', '15:23-32.0s'), (':', 'dd:mm:ss.s', '15:23:32.0'), ((':', ":", 's'), 'hh', '1:'), (('-', "-", 's'), 'hh:mm:ss.ssss', '1-01-34.1354s'), (('d', ":", '"'), 'd', '15'), (('d', ":", '"'), 'd.d', '15.4'), ]) def test_separator(self, separator, format, string): fl = AngleFormatterLocator(number=5, format=format) fl.sep = separator assert fl.formatter([15.392231] * u.degree, None)[0] == string def test_latex_format(self): fl = AngleFormatterLocator(number=5, format="dd:mm:ss") assert fl.formatter([15.392231] * u.degree, None)[0] == six.u('15\xb023\'32"') from ..rc_utils import rc_context with rc_context(rc={'text.usetex': True}): assert fl.formatter([15.392231] * u.degree, None)[0] == "15$^\circ$23'32\"" @pytest.mark.parametrize(('format'), ['x.xxx', 'dd.ss', 'dd:ss', 'mdd:mm:ss']) def test_invalid_formats(self, format): fl = AngleFormatterLocator(number=5) with pytest.raises(ValueError) as exc: fl.format = format assert exc.value.args[0] == "Invalid format: " + format @pytest.mark.parametrize(('format', 'base_spacing'), [('dd', 1. * u.deg), ('dd:mm', 1. * u.arcmin), ('dd:mm:ss', 1. * u.arcsec), ('dd:mm:ss.ss', 0.01 * u.arcsec), ('hh', 15. * u.deg), ('hh:mm', 15. * u.arcmin), ('hh:mm:ss', 15. * u.arcsec), ('hh:mm:ss.ss', 0.15 * u.arcsec), ('d', 1. * u.deg), ('d.d', 0.1 * u.deg), ('d.dd', 0.01 * u.deg), ('d.ddd', 0.001 * u.deg), ('m', 1. * u.arcmin), ('m.m', 0.1 * u.arcmin), ('m.mm', 0.01 * u.arcmin), ('s', 1. * u.arcsec), ('s.s', 0.1 * u.arcsec), ('s.ss', 0.01 * u.arcsec), ]) def test_base_spacing(self, format, base_spacing): fl = AngleFormatterLocator(number=5, format=format) assert fl.base_spacing == base_spacing def test_incorrect_spacing(self): fl = AngleFormatterLocator() fl.spacing = 0.032 * u.deg fl.format = 'dd:mm:ss' assert_almost_equal(fl.spacing.to(u.arcsec).value, 115.) @pytest.mark.parametrize(('spacing', 'string'), [(2 * u.deg, six.u('15\xb0')), (2 * u.arcmin, six.u('15\xb024\'')), (2 * u.arcsec, six.u('15\xb023\'32"')), (0.1 * u.arcsec, six.u('15\xb023\'32.0"'))]) def test_formatter_no_format(self, spacing, string): fl = AngleFormatterLocator() assert fl.formatter([15.392231] * u.degree, spacing)[0] == string class TestScalarFormatterLocator(object): def test_no_options(self): fl = ScalarFormatterLocator(unit=u.m) assert fl.values is None assert fl.number == 5 assert fl.spacing is None def test_too_many_options(self): with pytest.raises(ValueError) as exc: ScalarFormatterLocator(values=[1.,2.] * u.m, number=5) assert exc.value.args[0] == "At most one of values/number/spacing can be specifed" with pytest.raises(ValueError) as exc: ScalarFormatterLocator(values=[1.,2.] * u.m, spacing=5. * u.m) assert exc.value.args[0] == "At most one of values/number/spacing can be specifed" with pytest.raises(ValueError) as exc: ScalarFormatterLocator(number=5, spacing=5. * u.m) assert exc.value.args[0] == "At most one of values/number/spacing can be specifed" with pytest.raises(ValueError) as exc: ScalarFormatterLocator(values=[1.,2.] * u.m, number=5, spacing=5. * u.m) assert exc.value.args[0] == "At most one of values/number/spacing can be specifed" def test_values(self): fl = ScalarFormatterLocator(values=[0.1, 1., 14.] * u.m, unit=u.m) assert fl.values.value.tolist() == [0.1, 1., 14.] assert fl.number is None assert fl.spacing is None values, spacing = fl.locator(34.3, 55.4) assert_almost_equal(values.value, [0.1, 1., 14.]) def test_number(self): fl = ScalarFormatterLocator(number=7, unit=u.m) assert fl.values is None assert fl.number == 7 assert fl.spacing is None values, spacing = fl.locator(34.3, 55.4) assert_almost_equal(values.value, np.linspace(36., 54., 10)) values, spacing = fl.locator(34.3, 36.1) assert_almost_equal(values.value, np.linspace(34.4, 36, 9)) fl.format = 'x' values, spacing = fl.locator(34.3, 36.1) assert_almost_equal(values.value, [35., 36.]) def test_spacing(self): fl = ScalarFormatterLocator(spacing=3. * u.m) assert fl.values is None assert fl.number is None assert fl.spacing == 3. * u.m values, spacing = fl.locator(34.3, 55.4) assert_almost_equal(values.value, [36., 39., 42., 45., 48., 51., 54.]) fl.spacing = 0.5 * u.m values, spacing = fl.locator(34.3, 36.1) assert_almost_equal(values.value, [34.5, 35., 35.5, 36.]) fl.format = 'x' values, spacing = fl.locator(34.3, 36.1) assert_almost_equal(values.value, [35., 36.]) def test_minor_locator(self): fl = ScalarFormatterLocator(unit=u.m) values, spacing = fl.locator(34.3, 55.4) minor_values = fl.minor_locator(spacing, 5, 34.3, 55.4) assert_almost_equal(minor_values.value, [36., 37., 38., 39., 41., 42., 43., 44., 46., 47., 48., 49., 51., 52., 53., 54.]) print('minor_values: ' + str(minor_values)) minor_values = fl.minor_locator(spacing, 2, 34.3, 55.4) assert_almost_equal(minor_values.value, [37.5, 42.5, 47.5, 52.5]) fl.values = [0.1, 1., 14.] * u.m values, spacing = fl.locator(34.3, 36.1) minor_values = fl.minor_locator(spacing, 2, 34.3, 55.4) assert_almost_equal(minor_values.value, []) @pytest.mark.parametrize(('format', 'string'), [('x', '15'), ('x.x', '15.4'), ('x.xx', '15.39'), ('x.xxx', '15.392'), ('%g', '15.3922'), ('%f', '15.392231'), ('%.2f', '15.39'), ('%.3f', '15.392')]) def test_format(self, format, string): fl = ScalarFormatterLocator(number=5, format=format, unit=u.m) assert fl.formatter([15.392231] * u.m, None)[0] == string @pytest.mark.parametrize(('format', 'string'), [('x', '1539'), ('x.x', '1539.2'), ('x.xx', '1539.22'), ('x.xxx', '1539.223')]) def test_format_unit(self, format, string): fl = ScalarFormatterLocator(number=5, format=format, unit=u.m) fl.format_unit = u.cm assert fl.formatter([15.392231] * u.m, None)[0] == string @pytest.mark.parametrize(('format'), ['dd', 'dd:mm', 'xx:mm', 'mx.xxx']) def test_invalid_formats(self, format): fl = ScalarFormatterLocator(number=5, unit=u.m) with pytest.raises(ValueError) as exc: fl.format = format assert exc.value.args[0] == "Invalid format: " + format @pytest.mark.parametrize(('format', 'base_spacing'), [('x', 1. * u.m), ('x.x', 0.1 * u.m), ('x.xxx', 0.001 * u.m)]) def test_base_spacing(self, format, base_spacing): fl = ScalarFormatterLocator(number=5, format=format, unit=u.m) assert fl.base_spacing == base_spacing def test_incorrect_spacing(self): fl = ScalarFormatterLocator(unit=u.m) fl.spacing = 0.032 * u.m fl.format = 'x.xx' assert_almost_equal(fl.spacing.to(u.m).value, 0.03) wcsaxes-0.6/wcsaxes/tests/test_frame.py0000644000077000000240000001016312553175753020312 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import numpy as np import matplotlib.pyplot as plt from astropy.wcs import WCS from astropy.tests.helper import pytest from .. import WCSAxes from .. import datasets from ..frame import BaseFrame from .test_images import BaseImageTests class HexagonalFrame(BaseFrame): spine_names = 'abcdef' def update_spines(self): xmin, xmax = self.parent_axes.get_xlim() ymin, ymax = self.parent_axes.get_ylim() ymid = 0.5 * (ymin + ymax) xmid1 = (xmin + xmax) / 4. xmid2 = (xmin + xmax) * 3. / 4. self['a'].data = np.array(([xmid1, ymin], [xmid2, ymin])) self['b'].data = np.array(([xmid2, ymin], [xmax, ymid])) self['c'].data = np.array(([xmax, ymid], [xmid2, ymax])) self['d'].data = np.array(([xmid2, ymax], [xmid1, ymax])) self['e'].data = np.array(([xmid1, ymax], [xmin, ymid])) self['f'].data = np.array(([xmin, ymid], [xmid1, ymin])) class TestFrame(BaseImageTests): @pytest.mark.mpl_image_compare(filename='custom_frame.png', tolerance=1.5) def test_custom_frame(self): wcs = WCS(self.msx_header) fig = plt.figure(figsize=(4, 4)) ax = WCSAxes(fig, [0.15, 0.15, 0.7, 0.7], wcs=wcs, frame_class=HexagonalFrame) fig.add_axes(ax) ax.coords.grid(color='white') im = ax.imshow(np.ones((149, 149)), vmin=0., vmax=2., cmap=plt.cm.gist_heat, origin='lower') minpad = {} minpad['a'] = minpad['d'] = 1 minpad['b'] = minpad['c'] = minpad['e'] = minpad['f'] = 2.75 ax.coords['glon'].set_axislabel("Longitude", minpad=minpad) ax.coords['glon'].set_axislabel_position('ad') ax.coords['glat'].set_axislabel("Latitude", minpad=minpad) ax.coords['glat'].set_axislabel_position('bcef') ax.coords['glon'].set_ticklabel_position('ad') ax.coords['glat'].set_ticklabel_position('bcef') # Set limits so that no labels overlap ax.set_xlim(5.5, 100.5) ax.set_ylim(5.5, 110.5) # Clip the image to the frame im.set_clip_path(ax.coords.frame.patch) return fig @pytest.mark.mpl_image_compare(filename='update_clip_path_rectangular.png', tolerance=1.5) def test_update_clip_path_rectangular(self, tmpdir): fig = plt.figure() ax = WCSAxes(fig, [0.1, 0.1, 0.8, 0.8], aspect='equal') fig.add_axes(ax) ax.set_xlim(0., 2.) ax.set_ylim(0., 2.) # Force drawing, which freezes the clip path returned by WCSAxes fig.savefig(tmpdir.join('nothing').strpath) im = ax.imshow(np.zeros((12, 4))) ax.set_xlim(-0.5, 3.5) ax.set_ylim(-0.5, 11.5) return fig @pytest.mark.mpl_image_compare(filename='update_clip_path_nonrectangular.png', tolerance=1.5) def test_update_clip_path_nonrectangular(self, tmpdir): fig = plt.figure() ax = WCSAxes(fig, [0.1, 0.1, 0.8, 0.8], aspect='equal', frame_class=HexagonalFrame) fig.add_axes(ax) ax.set_xlim(0., 2.) ax.set_ylim(0., 2.) # Force drawing, which freezes the clip path returned by WCSAxes fig.savefig(tmpdir.join('nothing').strpath) im = ax.imshow(np.zeros((12, 4))) ax.set_xlim(-0.5, 3.5) ax.set_ylim(-0.5, 11.5) return fig @pytest.mark.mpl_image_compare(filename='update_clip_path_change_wcs.png', tolerance=1.5) def test_update_clip_path_change_wcs(self, tmpdir): # When WCS is changed, a new frame is created, so we need to make sure # that the path is carried over to the new frame. fig = plt.figure() ax = WCSAxes(fig, [0.1, 0.1, 0.8, 0.8], aspect='equal') fig.add_axes(ax) ax.set_xlim(0., 2.) ax.set_ylim(0., 2.) # Force drawing, which freezes the clip path returned by WCSAxes fig.savefig(tmpdir.join('nothing').strpath) ax.reset_wcs() im = ax.imshow(np.zeros((12, 4))) ax.set_xlim(-0.5, 3.5) ax.set_ylim(-0.5, 11.5) return fig wcsaxes-0.6/wcsaxes/tests/test_images.py0000644000077000000240000003723112553175753020472 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import os import shutil import tempfile import numpy as np import matplotlib.pyplot as plt from matplotlib.testing.compare import compare_images from matplotlib.patches import Circle from astropy import units as u from astropy.io import fits from astropy.tests.helper import pytest from astropy.tests.helper import remote_data from ..rc_utils import rc_context from .. import datasets, WCS, WCSAxes class BaseImageTests(object): @classmethod def setup_class(cls): cls._data_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data')) msx_header = os.path.join(cls._data_dir, 'msx_header') cls.msx_header = fits.Header.fromtextfile(msx_header) rosat_header = os.path.join(cls._data_dir, 'rosat_header') cls.rosat_header = fits.Header.fromtextfile(rosat_header) twoMASS_k_header = os.path.join(cls._data_dir, '2MASS_k_header') cls.twoMASS_k_header = fits.Header.fromtextfile(twoMASS_k_header) cube_header = os.path.join(cls._data_dir, 'cube_header') cls.cube_header = fits.Header.fromtextfile(cube_header) slice_header = os.path.join(cls._data_dir, 'slice_header') cls.slice_header = fits.Header.fromtextfile(slice_header) class TestBasic(BaseImageTests): @pytest.mark.mpl_image_compare(filename='image_plot.png', tolerance=1.5) def test_image_plot(self): # Test for plotting image and also setting values of ticks fig = plt.figure(figsize=(6, 6)) ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=WCS(self.msx_header), aspect='equal') ax.set_xlim(-0.5, 148.5) ax.set_ylim(-0.5, 148.5) ax.coords[0].set_ticks([-0.30, 0., 0.20] * u.degree, size=5, width=1) return fig @remote_data @pytest.mark.mpl_image_compare(filename='contour_overlay.png', tolerance=1.5) def test_contour_overlay(self): # Test for overlaying contours on images hdu_msx = datasets.fetch_msx_hdu() wcs_msx = WCS(self.msx_header) fig = plt.figure(figsize=(6, 6)) ax = fig.add_axes([0.15, 0.15, 0.8, 0.8], projection=WCS(self.twoMASS_k_header), aspect='equal') ax.set_xlim(-0.5, 720.5) ax.set_ylim(-0.5, 720.5) # Overplot contour ax.contour(hdu_msx.data, transform=ax.get_transform(wcs_msx), colors='orange', levels=[2.5e-5, 5e-5, 1.e-4]) ax.coords[0].set_ticks(size=5, width=1) ax.coords[1].set_ticks(size=5, width=1) ax.set_xlim(0., 720.) ax.set_ylim(0., 720.) return fig @pytest.mark.mpl_image_compare(filename='overlay_features_image.png', tolerance=1.5) def test_overlay_features_image(self): # Test for overlaying grid, changing format of ticks, setting spacing # and number of ticks fig = plt.figure(figsize=(6, 6)) ax = fig.add_axes([0.25, 0.25, 0.65, 0.65], projection=WCS(self.msx_header), aspect='equal') # Change the format of the ticks ax.coords[0].set_major_formatter('dd:mm:ss') ax.coords[1].set_major_formatter('dd:mm:ss.ssss') # Overlay grid on image ax.grid(color='red', alpha=1.0, lw=1, linestyle='dashed') # Set the spacing of ticks on the 'glon' axis to 4 arcsec ax.coords['glon'].set_ticks(spacing=4 * u.arcsec, size=5, width=1) # Set the number of ticks on the 'glat' axis to 9 ax.coords['glat'].set_ticks(number=9, size=5, width=1) # Set labels on axes ax.coords['glon'].set_axislabel('Galactic Longitude', minpad=1.6) ax.coords['glat'].set_axislabel('Galactic Latitude', minpad=-0.75) # Change the frame linewidth and color ax.coords.frame.set_color('red') ax.coords.frame.set_linewidth(2) return fig @pytest.mark.mpl_image_compare(filename='curvlinear_grid_patches_image.png', tolerance=1.5) def test_curvilinear_grid_patches_image(self): # Overlay curvilinear grid and patches on image fig = plt.figure(figsize=(8, 8)) ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=WCS(self.rosat_header), aspect='equal') ax.set_xlim(-0.5, 479.5) ax.set_ylim(-0.5, 239.5) ax.grid(color='black', alpha=1.0, lw=1, linestyle='dashed') p = Circle((300, 100), radius=40, ec='yellow', fc='none') ax.add_patch(p) p = Circle((30., 20.), radius=20., ec='orange', fc='none', transform=ax.get_transform('world')) ax.add_patch(p) p = Circle((60., 50.), radius=20., ec='red', fc='none', transform=ax.get_transform('fk5')) ax.add_patch(p) p = Circle((40., 60.), radius=20., ec='green', fc='none', transform=ax.get_transform('galactic')) ax.add_patch(p) return fig @pytest.mark.mpl_image_compare(filename='cube_slice_image.png', tolerance=1.5) def test_cube_slice_image(self): # Test for cube slicing fig = plt.figure() ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=WCS(self.cube_header), slices=(50, 'y', 'x'), aspect='equal') ax.set_xlim(-0.5, 52.5) ax.set_ylim(-0.5, 106.5) ax.coords[2].set_axislabel('Velocity m/s') ax.coords[1].set_ticks(spacing=0.2 * u.deg, width=1, exclude_overlapping=True) ax.coords[2].set_ticks(spacing=400 * u.m / u.s, width=1, exclude_overlapping=True) ax.coords[1].grid(grid_type='contours', color='red', linestyle='solid') ax.coords[2].grid(grid_type='contours', color='red', linestyle='solid') return fig @pytest.mark.mpl_image_compare(filename='cube_slice_image_lonlat.png', tolerance=1.5) def test_cube_slice_image_lonlat(self): # Test for cube slicing. Here we test with longitude and latitude since # there is some longitude-specific code in _update_grid_contour. fig = plt.figure() ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=WCS(self.cube_header), slices=('x', 'y', 50), aspect='equal') ax.set_xlim(-0.5, 106.5) ax.set_ylim(-0.5, 106.5) ax.coords[0].grid(grid_type='contours', color='blue', linestyle='solid') ax.coords[1].grid(grid_type='contours', color='red', linestyle='solid') return fig @pytest.mark.mpl_image_compare(filename='changed_axis_units.png', tolerance=1.5) def test_changed_axis_units(self): # Test to see if changing the units of axis works fig = plt.figure() ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=WCS(self.cube_header), slices=(50, 'y', 'x'), aspect='equal') ax.set_xlim(-0.5, 52.5) ax.set_ylim(-0.5, 106.5) ax.coords[2].set_major_formatter('x.xx') ax.coords[2].set_format_unit(u.km / u.s) ax.coords[2].set_axislabel('Velocity km/s') ax.coords[1].set_ticks(width=1, exclude_overlapping=True) ax.coords[2].set_ticks(width=1, exclude_overlapping=True) return fig @pytest.mark.mpl_image_compare(filename='minor_ticks_image.png', tolerance=1.5) def test_minor_ticks(self): # Test for drawing minor ticks fig = plt.figure() ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=WCS(self.cube_header), slices=(50, 'y', 'x'), aspect='equal') ax.set_xlim(-0.5, 52.5) ax.set_ylim(-0.5, 106.5) ax.coords[2].set_ticks(exclude_overlapping=True) ax.coords[1].set_ticks(exclude_overlapping=True) ax.coords[2].display_minor_ticks(True) ax.coords[1].display_minor_ticks(True) ax.coords[2].set_minor_frequency(3) ax.coords[1].set_minor_frequency(10) return fig @pytest.mark.mpl_image_compare(filename='ticks_labels.png', savefig_kwargs={'bbox_inches': 'tight'}, tolerance=1.5) def test_ticks_labels(self): fig = plt.figure(figsize=(6, 6)) ax = WCSAxes(fig, [0.1, 0.1, 0.7, 0.7], wcs=None) fig.add_axes(ax) ax.set_xlim(-0.5, 2) ax.set_ylim(-0.5, 2) ax.coords[0].set_ticks(size=10, color='blue', alpha=0.2, width=1) ax.coords[1].set_ticks(size=20, color='red', alpha=0.9, width=1) ax.coords[0].set_ticks_position('all') ax.coords[1].set_ticks_position('all') ax.coords[0].set_axislabel('X-axis', size=20) ax.coords[1].set_axislabel('Y-axis', color='green', size=25, weight='regular', style='normal', family='monospace') ax.coords[0].set_axislabel_position('t') ax.coords[1].set_axislabel_position('r') ax.coords[0].set_ticklabel(color='purple', size=15, alpha=1, weight='light', style='normal', family='sans-serif') ax.coords[1].set_ticklabel(color='black', size=18, alpha=0.9, weight='bold', family='serif') ax.coords[0].set_ticklabel_position('all') ax.coords[1].set_ticklabel_position('r') return fig @pytest.mark.mpl_image_compare(filename='rcparams.png', tolerance=1.5) def test_rcparams(self): # Test default style (matplotlib.rcParams) for ticks and gridlines with rc_context({ 'xtick.color': 'red', 'xtick.major.size': 20, 'xtick.major.width': 2, 'grid.color': 'blue', 'grid.linestyle': ':', 'grid.linewidth': 1, 'grid.alpha': 0.5}): fig = plt.figure(figsize=(6, 6)) ax = WCSAxes(fig, [0.1, 0.1, 0.7, 0.7], wcs=None) fig.add_axes(ax) ax.set_xlim(-0.5, 2) ax.set_ylim(-0.5, 2) ax.grid() ax.coords[0].set_ticks(exclude_overlapping=True) ax.coords[1].set_ticks(exclude_overlapping=True) return fig @pytest.mark.mpl_image_compare(filename='tick_angles.png', tolerance=1.5) def test_tick_angles(self): # Test that tick marks point in the correct direction, even when the # axes limits extend only over a few FITS pixels. Addresses #45, #46. w = WCS() w.wcs.ctype = ['RA---TAN', 'DEC--TAN'] w.wcs.crval = [90, 70] w.wcs.cdelt = [16, 16] w.wcs.crpix = [1, 1] w.wcs.radesys = 'ICRS' w.wcs.equinox = 2000.0 fig = plt.figure(figsize=(3, 3)) ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=w) ax.set_xlim(1, -1) ax.set_ylim(-1, 1) ax.grid(color='gray', alpha=0.5, linestyle='solid') ax.coords['ra'].set_ticks(color='red', size=20) ax.coords['dec'].set_ticks(color='red', size=20) return fig @pytest.mark.mpl_image_compare(filename='tick_angles_non_square_axes.png', tolerance=1.5) def test_tick_angles_non_square_axes(self): # Test that tick marks point in the correct direction, even when the # axes limits extend only over a few FITS pixels, and the axes are # non-square. w = WCS() w.wcs.ctype = ['RA---TAN', 'DEC--TAN'] w.wcs.crval = [90, 70] w.wcs.cdelt = [16, 16] w.wcs.crpix = [1, 1] w.wcs.radesys = 'ICRS' w.wcs.equinox = 2000.0 fig = plt.figure(figsize=(6, 3)) ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection=w) ax.set_xlim(1, -1) ax.set_ylim(-1, 1) ax.grid(color='gray', alpha=0.5, linestyle='solid') ax.coords['ra'].set_ticks(color='red', size=20) ax.coords['dec'].set_ticks(color='red', size=20) return fig @pytest.mark.mpl_image_compare(filename='set_coord_type.png', tolerance=1.5) def test_set_coord_type(self): # Test for setting coord_type fig = plt.figure(figsize=(3, 3)) ax = fig.add_axes([0.2, 0.2, 0.6, 0.6], projection=WCS(self.msx_header), aspect='equal') ax.set_xlim(-0.5, 148.5) ax.set_ylim(-0.5, 148.5) ax.coords[0].set_coord_type('scalar') ax.coords[1].set_coord_type('scalar') ax.coords[0].set_major_formatter('x.xxx') ax.coords[1].set_major_formatter('x.xxx') ax.coords[0].set_ticks(exclude_overlapping=True) ax.coords[1].set_ticks(exclude_overlapping=True) return fig @pytest.mark.mpl_image_compare(filename='test_ticks_regression_1.png', tolerance=1.5) def test_ticks_regression(self): # Regression test for a bug that caused ticks aligned exactly with a # sampled frame point to not appear. This also checks that tick labels # don't get added more than once, and that no error occurs when e.g. # the top part of the frame is all at the same coordinate as one of the # potential ticks (which causes the tick angle calculation to return # NaN). wcs = WCS(self.slice_header) fig = plt.figure(figsize=(3, 3)) ax = fig.add_axes([0.25, 0.25, 0.5, 0.5], projection=wcs, aspect='auto') limits = wcs.wcs_world2pix([0, 0], [35e3, 80e3], 0)[1] ax.set_ylim(*limits) ax.coords[0].set_ticks(spacing=0.002 * u.deg) ax.coords[1].set_ticks(spacing=5 * u.km / u.s) ax.coords[0].set_ticklabel(alpha=0.5) # to see multiple labels ax.coords[1].set_ticklabel(alpha=0.5) ax.coords[0].set_ticklabel_position('all') ax.coords[1].set_ticklabel_position('all') return fig @pytest.mark.mpl_image_compare(filename='test_axislabels_regression.png', savefig_kwargs={'bbox_inches': 'tight'}, tolerance=1.5) def test_axislabels_regression(self): # Regression test for a bug that meant that if tick labels were made # invisible with ``set_visible(False)``, they were still added to the # list of bounding boxes for tick labels, but with default values of 0 # to 1, which caused issues. wcs = WCS(self.msx_header) fig = plt.figure(figsize=(3, 3)) ax = fig.add_axes([0.25, 0.25, 0.5, 0.5], projection=wcs, aspect='auto') ax.coords[0].set_axislabel("Label 1") ax.coords[1].set_axislabel("Label 2") ax.coords[1].ticklabels.set_visible(False) return fig @pytest.mark.mpl_image_compare(savefig_kwargs={'bbox_inches': 'tight'}, tolerance=1.5) def test_noncelestial_angular(self, tmpdir): # Regression test for a bug that meant that when passing a WCS that had # angular axes and using set_coord_type to set the coordinates to # longitude/latitude, but where the WCS wasn't recognized as celestial, # the WCS units are not converted to deg, so we can't assume that # transform will always return degrees. wcs = WCS(naxis=2) wcs.wcs.ctype = ['solar-x', 'solar-y'] wcs.wcs.cunit = ['arcsec', 'arcsec'] fig = plt.figure(figsize=(3, 3)) ax = fig.add_subplot(1,1,1,projection=wcs) ax.imshow(np.zeros([1024, 1024]), origin='lower') ax.coords[0].set_coord_type('longitude', coord_wrap=180) ax.coords[1].set_coord_type('latitude') ax.coords[0].set_major_formatter('s.s') ax.coords[1].set_major_formatter('s.s') ax.grid(color='white', ls='solid') # Force drawing (needed for format_coord) fig.savefig(tmpdir.join('nothing').strpath) # TODO: the formatted string should show units assert ax.format_coord(512, 512) == "513.0 513.0 (world)" return fig wcsaxes-0.6/wcsaxes/tests/test_misc.py0000644000077000000240000000463512535045247020154 0ustar tomstaff00000000000000from __future__ import print_function import numpy as np import matplotlib.pyplot as plt from astropy.wcs import WCS from astropy.io import fits from astropy.tests.helper import catch_warnings, pytest from ..core import WCSAxes from ..utils import get_coord_meta def test_grid_regression(): # Regression test for a bug that meant that if the rc parameter # axes.grid was set to True, WCSAxes would crash upon initalization. plt.rc('axes', grid=True) fig = plt.figure(figsize=(3, 3)) WCSAxes(fig, [0.1, 0.1, 0.8, 0.8]) def test_format_coord_regression(tmpdir): # Regression test for a bug that meant that if format_coord was called by # Matplotlib before the axes were drawn, an error occurred. fig = plt.figure(figsize=(3, 3)) ax = WCSAxes(fig, [0.1, 0.1, 0.8, 0.8]) fig.add_axes(ax) assert ax.format_coord(10,10) == "" assert ax.coords[0].format_coord(10) == "" assert ax.coords[1].format_coord(10) == "" fig.savefig(tmpdir.join('nothing').strpath) assert ax.format_coord(10,10) == "11.0 11.0 (world)" assert ax.coords[0].format_coord(10) == "10.0" assert ax.coords[1].format_coord(10) == "10.0" TARGET_HEADER = fits.Header.fromstring(""" NAXIS = 2 NAXIS1 = 200 NAXIS2 = 100 CTYPE1 = 'RA---MOL' CRPIX1 = 500 CRVAL1 = 180.0 CDELT1 = -0.4 CUNIT1 = 'deg ' CTYPE2 = 'DEC--MOL' CRPIX2 = 400 CRVAL2 = 0.0 CDELT2 = 0.4 CUNIT2 = 'deg ' COORDSYS= 'icrs ' """, sep='\n') def test_no_numpy_warnings(): # Make sure that no warnings are raised if some pixels are outside WCS # (since this is normal) ax = plt.subplot(1,1,1, projection=WCS(TARGET_HEADER)) ax.imshow(np.zeros((100,200))) ax.coords.grid(color='white') with catch_warnings() as ws: plt.savefig('test.png') # For debugging for w in ws: print(w) assert len(ws) == 0 def test_invalid_frame_overlay(): # Make sure a nice error is returned if a frame doesn't exist ax = plt.subplot(1,1,1, projection=WCS(TARGET_HEADER)) with pytest.raises(ValueError) as exc: ax.get_coords_overlay('banana') assert exc.value.args[0] == 'Unknown frame: banana' with pytest.raises(ValueError) as exc: get_coord_meta('banana') assert exc.value.args[0] == 'Unknown frame: banana' wcsaxes-0.6/wcsaxes/tests/test_transform_coord_meta.py0000644000077000000240000001153112553175753023427 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst from distutils.version import LooseVersion import numpy as np import matplotlib.pyplot as plt import astropy from astropy import units as u from astropy.wcs import WCS from astropy.tests.helper import pytest from .. import WCSAxes from .test_images import BaseImageTests from ..transforms import CurvedTransform requires_astropy_10 = pytest.mark.skipif(str(LooseVersion(astropy.__version__) < LooseVersion("1.0"))) # Create fake transforms that roughly mimic a polar projection class DistanceToLonLat(CurvedTransform): def __init__(self, R=6e3): super(DistanceToLonLat, self).__init__() self.R = R def transform(self, xy): x, y = xy[:, 0], xy[:, 1] lam = np.degrees(np.arctan2(y, x)) phi = 90. - np.degrees(np.hypot(x, y) / self.R) return np.array((lam, phi)).transpose() transform_non_affine = transform def inverted(self): return LonLatToDistance(R=self.R) class LonLatToDistance(CurvedTransform): def __init__(self, R=6e3): super(LonLatToDistance, self).__init__() self.R = R def transform(self, lamphi): lam, phi = lamphi[:, 0], lamphi[:, 1] r = np.radians(90 - phi) * self.R x = r * np.cos(np.radians(lam)) y = r * np.sin(np.radians(lam)) return np.array((x, y)).transpose() transform_non_affine = transform def inverted(self): return DistanceToLonLat(R=self.R) class TestTransformCoordMeta(BaseImageTests): @pytest.mark.mpl_image_compare(filename='coords_overlay.png', tolerance=1.5) def test_coords_overlay(self): # Set up a simple WCS that maps pixels to non-projected distances wcs = WCS(naxis=2) wcs.wcs.ctype = ['x', 'y'] wcs.wcs.cunit = ['km', 'km'] wcs.wcs.crpix = [614.5, 856.5] wcs.wcs.cdelt = [6.25, 6.25] wcs.wcs.crval = [0., 0.] fig = plt.figure(figsize=(4, 4)) ax = WCSAxes(fig, [0.15, 0.15, 0.7, 0.7], wcs=wcs) fig.add_axes(ax) s = DistanceToLonLat(R=6378.273) ax.coords['x'].set_ticklabel_position('') ax.coords['y'].set_ticklabel_position('') coord_meta = {} coord_meta['type'] = ('longitude', 'latitude') coord_meta['wrap'] = (360., None) coord_meta['unit'] = (u.deg, u.deg) coord_meta['name'] = 'lon', 'lat' overlay = ax.get_coords_overlay(s, coord_meta=coord_meta) overlay.grid(color='red') overlay['lon'].grid(color='red', linestyle='solid', alpha=0.3) overlay['lat'].grid(color='blue', linestyle='solid', alpha=0.3) overlay['lon'].set_ticklabel(size=7) overlay['lat'].set_ticklabel(size=7) overlay['lon'].set_ticklabel_position('brtl') overlay['lat'].set_ticklabel_position('brtl') overlay['lon'].set_ticks(spacing=10. * u.deg, exclude_overlapping=True) overlay['lat'].set_ticks(spacing=10. * u.deg, exclude_overlapping=True) ax.set_xlim(-0.5, 1215.5) ax.set_ylim(-0.5, 1791.5) return fig @requires_astropy_10 @pytest.mark.mpl_image_compare(filename='coords_overlay_auto_coord_meta.png', tolerance=1.5) def test_coords_overlay_auto_coord_meta(self): fig = plt.figure(figsize=(4, 4)) ax = WCSAxes(fig, [0.15, 0.15, 0.7, 0.7], wcs=WCS(self.msx_header)) fig.add_axes(ax) ax.grid(color='red', alpha=0.5, linestyle='solid') overlay = ax.get_coords_overlay('fk5') # automatically sets coord_meta overlay.grid(color='black', alpha=0.5, linestyle='solid') overlay['ra'].set_ticks(color='black') overlay['dec'].set_ticks(color='black') ax.set_xlim(-0.5, 148.5) ax.set_ylim(-0.5, 148.5) return fig @pytest.mark.mpl_image_compare(filename='direct_init.png', tolerance=1.5) def test_direct_init(self): s = DistanceToLonLat(R=6378.273) coord_meta = {} coord_meta['type'] = ('longitude', 'latitude') coord_meta['wrap'] = (360., None) coord_meta['unit'] = (u.deg, u.deg) coord_meta['name'] = 'lon', 'lat' fig = plt.figure(figsize=(4, 4)) ax = WCSAxes(fig, [0.15, 0.15, 0.7, 0.7], transform=s, coord_meta=coord_meta) fig.add_axes(ax) ax.coords['lon'].grid(color='red', linestyle='solid', alpha=0.3) ax.coords['lat'].grid(color='blue', linestyle='solid', alpha=0.3) ax.coords['lon'].set_ticklabel(size=7) ax.coords['lat'].set_ticklabel(size=7) ax.coords['lon'].set_ticklabel_position('brtl') ax.coords['lat'].set_ticklabel_position('brtl') ax.coords['lon'].set_ticks(spacing=10. * u.deg, exclude_overlapping=True) ax.coords['lat'].set_ticks(spacing=10. * u.deg, exclude_overlapping=True) ax.set_xlim(-400., 500.) ax.set_ylim(-300., 400.) return fig wcsaxes-0.6/wcsaxes/tests/test_transforms.py0000644000077000000240000000237312533356400021406 0ustar tomstaff00000000000000import numpy as np from astropy.wcs import WCS from matplotlib.transforms import Affine2D from ..transforms import (WCSWorld2PixelTransform, WCSPixel2WorldTransform, CoordinateTransform) WCS2D = WCS(naxis=2) WCS2D.wcs.ctype = ['x', 'y'] WCS2D.wcs.cunit = ['km', 'km'] WCS2D.wcs.crpix = [614.5, 856.5] WCS2D.wcs.cdelt = [6.25, 6.25] WCS2D.wcs.crval = [0., 0.] WCS3D = WCS(naxis=3) WCS3D.wcs.ctype = ['x', 'y', 'z'] WCS3D.wcs.cunit = ['km', 'km', 'km'] WCS3D.wcs.crpix = [614.5, 856.5, 333] WCS3D.wcs.cdelt = [6.25, 6.25, 23] WCS3D.wcs.crval = [0., 0., 1.] # We add Affine2D to catch the fact that in Matplotlib, having a Composite # transform can end up in more strict requirements for the dimensionality. def test_2d(): world = np.ones((10, 2)) w1 = WCSWorld2PixelTransform(WCS2D) + Affine2D() pixel = w1.transform(world) world_2 = w1.inverted().transform(pixel) np.testing.assert_allclose(world, world_2) def test_3d(): world = np.ones((10, 3)) w1 = WCSWorld2PixelTransform(WCS3D, slice=('y',0,'x')) + Affine2D() pixel = w1.transform(world) world_2 = w1.inverted().transform(pixel) np.testing.assert_allclose(world[:,0], world_2[:,0]) np.testing.assert_allclose(world[:,2], world_2[:,2]) wcsaxes-0.6/wcsaxes/tests/test_utils.py0000644000077000000240000000776512443671565020376 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst from numpy.testing import assert_almost_equal from astropy import units as u from astropy.wcs import WCS from ..utils import (select_step_degree, select_step_hour, select_step_scalar, coord_type_from_ctype) def assert_almost_equal_quantity(q1, q2): assert_almost_equal(q1.value, q2.to(q1.unit).value) def test_select_step_degree(): assert_almost_equal_quantity(select_step_degree(127 * u.deg), 180. * u.deg) assert_almost_equal_quantity(select_step_degree(44 * u.deg), 45. * u.deg) assert_almost_equal_quantity(select_step_degree(18 * u.arcmin), 15 * u.arcmin) assert_almost_equal_quantity(select_step_degree(3.4 * u.arcmin), 3 * u.arcmin) assert_almost_equal_quantity(select_step_degree(2 * u.arcmin), 2 * u.arcmin) assert_almost_equal_quantity(select_step_degree(59 * u.arcsec), 1 * u.arcmin) assert_almost_equal_quantity(select_step_degree(33 * u.arcsec), 30 * u.arcsec) assert_almost_equal_quantity(select_step_degree(2.2 * u.arcsec), 2 * u.arcsec) assert_almost_equal_quantity(select_step_degree(0.8 * u.arcsec), 1 * u.arcsec) assert_almost_equal_quantity(select_step_degree(0.2 * u.arcsec), 0.2 * u.arcsec) assert_almost_equal_quantity(select_step_degree(0.11 * u.arcsec), 0.1 * u.arcsec) assert_almost_equal_quantity(select_step_degree(0.022 * u.arcsec), 0.02 * u.arcsec) assert_almost_equal_quantity(select_step_degree(0.0043 * u.arcsec), 0.005 * u.arcsec) assert_almost_equal_quantity(select_step_degree(0.00083 * u.arcsec), 0.001 * u.arcsec) assert_almost_equal_quantity(select_step_degree(0.000027 * u.arcsec), 0.00002 * u.arcsec) def test_select_step_hour(): assert_almost_equal_quantity(select_step_hour(127 * u.deg), 8. * u.hourangle) assert_almost_equal_quantity(select_step_hour(44 * u.deg), 3. * u.hourangle) assert_almost_equal_quantity(select_step_hour(18 * u.arcmin), 15 * u.arcmin) assert_almost_equal_quantity(select_step_hour(3.4 * u.arcmin), 3 * u.arcmin) assert_almost_equal_quantity(select_step_hour(2 * u.arcmin), 1.5 * u.arcmin) assert_almost_equal_quantity(select_step_hour(59 * u.arcsec), 1 * u.arcmin) assert_almost_equal_quantity(select_step_hour(33 * u.arcsec), 30 * u.arcsec) assert_almost_equal_quantity(select_step_hour(2.2 * u.arcsec), 3. * u.arcsec) assert_almost_equal_quantity(select_step_hour(0.8 * u.arcsec), 0.75 * u.arcsec) assert_almost_equal_quantity(select_step_hour(0.2 * u.arcsec), 0.15 * u.arcsec) assert_almost_equal_quantity(select_step_hour(0.11 * u.arcsec), 0.15 * u.arcsec) assert_almost_equal_quantity(select_step_hour(0.022 * u.arcsec), 0.03 * u.arcsec) assert_almost_equal_quantity(select_step_hour(0.0043 * u.arcsec), 0.003 * u.arcsec) assert_almost_equal_quantity(select_step_hour(0.00083 * u.arcsec), 0.00075 * u.arcsec) assert_almost_equal_quantity(select_step_hour(0.000027 * u.arcsec), 0.00003 * u.arcsec) def test_select_step_scalar(): assert_almost_equal(select_step_scalar(33122.), 50000.) assert_almost_equal(select_step_scalar(433.), 500.) assert_almost_equal(select_step_scalar(12.3), 10) assert_almost_equal(select_step_scalar(3.3), 5.) assert_almost_equal(select_step_scalar(0.66), 0.5) assert_almost_equal(select_step_scalar(0.0877), 0.1) assert_almost_equal(select_step_scalar(0.00577), 0.005) assert_almost_equal(select_step_scalar(0.00022), 0.0002) assert_almost_equal(select_step_scalar(0.000012), 0.00001) assert_almost_equal(select_step_scalar(0.000000443), 0.0000005) def test_coord_type_from_ctype(): assert coord_type_from_ctype(' LON') == ('longitude', None) assert coord_type_from_ctype(' LAT') == ('latitude', None) assert coord_type_from_ctype('HPLN') == ('longitude', 180.) assert coord_type_from_ctype('HPLT') == ('latitude', None) assert coord_type_from_ctype('RA--') == ('longitude', None) assert coord_type_from_ctype('DEC-') == ('latitude', None) assert coord_type_from_ctype('spam') == ('scalar', None) wcsaxes-0.6/wcsaxes/ticklabels.py0000644000077000000240000001570212441052514017121 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import numpy as np from matplotlib.text import Text from .frame import RectangularFrame def sort_using(X, Y): return [x for (y, x) in sorted(zip(Y, X))] class TickLabels(Text): def __init__(self, frame, *args, **kwargs): self.clear() self._frame = frame super(TickLabels, self).__init__(*args, **kwargs) self.set_clip_on(True) self.set_visible_axes('all') self.pad = 0.3 self._exclude_overlapping = False def clear(self): self.world = {} self.pixel = {} self.angle = {} self.text = {} self.disp = {} def add(self, axis, world, pixel, angle, text, axis_displacement): if axis not in self.world: self.world[axis] = [world] self.pixel[axis] = [pixel] self.angle[axis] = [angle] self.text[axis] = [text] self.disp[axis] = [axis_displacement] else: self.world[axis].append(world) self.pixel[axis].append(pixel) self.angle[axis].append(angle) self.text[axis].append(text) self.disp[axis].append(axis_displacement) def sort(self): """ Sort by axis displacement, which allows us to figure out which parts of labels to not repeat. """ for axis in self.world: self.world[axis] = sort_using(self.world[axis], self.disp[axis]) self.pixel[axis] = sort_using(self.pixel[axis], self.disp[axis]) self.angle[axis] = sort_using(self.angle[axis], self.disp[axis]) self.text[axis] = sort_using(self.text[axis], self.disp[axis]) self.disp[axis] = sort_using(self.disp[axis], self.disp[axis]) def simplify_labels(self): """ Figure out which parts of labels can be dropped to avoid repetition. """ self.sort() for axis in self.world: t1 = self.text[axis][0] for i in range(1, len(self.world[axis])): t2 = self.text[axis][i] if len(t1) != len(t2): t1 = self.text[axis][i] continue start = 0 for j in range(len(t1)): if t1[j] != t2[j]: break if t1[j] not in '-0123456789.': start = j + 1 if start == 0: t1 = self.text[axis][i] else: self.text[axis][i] = self.text[axis][i][start:] def set_visible_axes(self, visible_axes): self._visible_axes = visible_axes def get_visible_axes(self): if self._visible_axes == 'all': return self.world.keys() else: return [x for x in self._visible_axes if x in self.world] def set_exclude_overlapping(self, exclude_overlapping): self._exclude_overlapping = exclude_overlapping def draw(self, renderer, bboxes, ticklabels_bbox): if not self.get_visible(): return self.simplify_labels() text_size = renderer.points_to_pixels(self.get_size()) for axis in self.get_visible_axes(): for i in range(len(self.world[axis])): self.set_text(self.text[axis][i]) x, y = self.pixel[axis][i] if isinstance(self._frame, RectangularFrame): # This is just to preserve the current results, but can be # removed next time the reference images are re-generated. if np.abs(self.angle[axis][i]) < 45.: ha = 'right' va = 'bottom' dx = - text_size * 0.5 dy = - text_size * 0.5 elif np.abs(self.angle[axis][i] - 90.) < 45: ha = 'center' va = 'bottom' dx = 0 dy = - text_size * 1.5 elif np.abs(self.angle[axis][i] - 180.) < 45: ha = 'left' va = 'bottom' dx = text_size * 0.5 dy = - text_size * 0.5 else: ha = 'center' va = 'bottom' dx = 0 dy = text_size * 0.2 self.set_position((x + dx, y + dy)) self.set_ha(ha) self.set_va(va) else: # This is the more general code for arbitrarily oriented # axes # Set initial position and find bounding box self.set_position((x, y)) bb = super(TickLabels, self).get_window_extent(renderer) # Find width and height, as well as angle at which we # transition which side of the label we use to anchor the # label. width = bb.width height = bb.height theta = np.tan(height / width) # Project axis angle onto bounding box ax = np.cos(np.radians(self.angle[axis][i])) ay = np.sin(np.radians(self.angle[axis][i])) # Set anchor point for label if np.abs(self.angle[axis][i]) < 45.: dx = width dy = ay * height elif np.abs(self.angle[axis][i] - 90.) < 45: dx = ax * width dy = height elif np.abs(self.angle[axis][i] - 180.) < 45: dx = -width dy = ay * height else: dx = ax * width dy = -height dx *= 0.5 dy *= 0.5 # Find normalized vector along axis normal, so as to be # able to nudge the label away by a constant padding factor dist = np.hypot(dx, dy) ddx = dx / dist ddy = dy / dist dx += ddx * text_size * self.pad dy += ddy * text_size * self.pad self.set_position((x - dx, y - dy)) self.set_ha('center') self.set_va('center') bb = super(TickLabels, self).get_window_extent(renderer) # TODO: the problem here is that we might get rid of a label # that has a key starting bit such as -0:30 where the -0 # might be dropped from all other labels. if not self._exclude_overlapping or bb.count_overlaps(bboxes) == 0: super(TickLabels, self).draw(renderer) bboxes.append(bb) ticklabels_bbox.append(bb) wcsaxes-0.6/wcsaxes/ticks.py0000644000077000000240000001370512533356400016125 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import numpy as np from matplotlib.lines import Path, Line2D from matplotlib.transforms import Affine2D from matplotlib import rcParams class Ticks(Line2D): """ Ticks are derived from Line2D, and note that ticks themselves are markers. Thus, you should use set_mec, set_mew, etc. To change the tick size (length), you need to use set_ticksize. To change the direction of the ticks (ticks are in opposite direction of ticklabels by default), use set_tick_out(False). Note that Matplotlib's defaults dictionary :data:`~matplotlib.rcParams` contains default settings (color, size, width) of the form `xtick.*` and `ytick.*`. In a WCS projection, there may not be a clear relationship between axes of the projection and 'x' or 'y' axes. For this reason, we read defaults from `xtick.*`. The following settings affect the default appearance of ticks: * `xtick.major.size` * `xtick.major.width` * `xtick.color` """ def __init__(self, ticksize=None, tick_out=False, **kwargs): if ticksize is None: ticksize = rcParams['xtick.major.size'] self.set_ticksize(ticksize) self.set_tick_out(tick_out) # FIXME: tick_out is incompatible with Matplotlib tickdir option self.clear() line2d_kwargs = { 'color': rcParams['xtick.color'], # For the linewidth we need to set a default since old versions of # matplotlib don't have this. 'linewidth': rcParams.get('xtick.major.width', 1) } line2d_kwargs.update(kwargs) Line2D.__init__(self, [0.], [0.], **line2d_kwargs) self.set_visible_axes('all') self._display_minor_ticks = False def display_minor_ticks(self, display_minor_ticks): self._display_minor_ticks = display_minor_ticks def get_display_minor_ticks(self): return self._display_minor_ticks def set_tick_out(self, tick_out): """ set True if tick need to be rotated by 180 degree. """ self._tick_out = tick_out def get_tick_out(self): """ Return True if the tick will be rotated by 180 degree. """ return self._tick_out def set_ticksize(self, ticksize): """ set length of the ticks in points. """ self._ticksize = ticksize def get_ticksize(self): """ Return length of the ticks in points. """ return self._ticksize def set_visible_axes(self, visible_axes): self._visible_axes = visible_axes def get_visible_axes(self): if self._visible_axes == 'all': return self.world.keys() else: return [x for x in self._visible_axes if x in self.world] def clear(self): self.world = {} self.pixel = {} self.angle = {} self.disp = {} self.minor_world = {} self.minor_pixel = {} self.minor_angle = {} self.minor_disp = {} def add(self, axis, world, pixel, angle, axis_displacement): if axis not in self.world: self.world[axis] = [world] self.pixel[axis] = [pixel] self.angle[axis] = [angle] self.disp[axis] = [axis_displacement] else: self.world[axis].append(world) self.pixel[axis].append(pixel) self.angle[axis].append(angle) self.disp[axis].append(axis_displacement) def get_minor_world(self): return self.minor_world def add_minor(self, minor_axis, minor_world, minor_pixel, minor_angle, minor_axis_displacement): if minor_axis not in self.minor_world: self.minor_world[minor_axis] = [minor_world] self.minor_pixel[minor_axis] = [minor_pixel] self.minor_angle[minor_axis] = [minor_angle] self.minor_disp[minor_axis] = [minor_axis_displacement] else: self.minor_world[minor_axis].append(minor_world) self.minor_pixel[minor_axis].append(minor_pixel) self.minor_angle[minor_axis].append(minor_angle) self.minor_disp[minor_axis].append(minor_axis_displacement) def __len__(self): return len(self.world) _tickvert_path = Path([[0., 0.], [1., 0.]]) def draw(self, renderer): """ Draw the ticks. """ if not self.get_visible(): return offset = renderer.points_to_pixels(self.get_ticksize()) self._draw_ticks(renderer, self.pixel, self.angle, offset) if self._display_minor_ticks: offset = offset * 0.5 # for minor ticksize self._draw_ticks(renderer, self.minor_pixel, self.minor_angle, offset) def _draw_ticks(self, renderer, pixel_array, angle_array, offset): """ Draw the minor ticks. """ path_trans = self.get_transform() gc = renderer.new_gc() gc.set_foreground(self.get_color()) gc.set_alpha(self.get_alpha()) gc.set_linewidth(self.get_linewidth()) marker_scale = Affine2D().scale(offset, offset) marker_rotation = Affine2D() marker_transform = marker_scale + marker_rotation initial_angle = 180. if self.get_tick_out() else 0. for axis in self.get_visible_axes(): if not axis in pixel_array: continue for loc, angle in zip(pixel_array[axis], angle_array[axis]): # Set the rotation for this tick marker_rotation.rotate_deg(initial_angle + angle) # Draw the markers locs = path_trans.transform_non_affine(np.array([loc, loc])) renderer.draw_markers(gc, self._tickvert_path, marker_transform, Path(locs), path_trans.get_affine()) # Reset the tick rotation before moving to the next tick marker_rotation.clear() gc.restore() wcsaxes-0.6/wcsaxes/transforms.py0000644000077000000240000002126512553175464017221 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst # Note: This file incldues code dervived from pywcsgrid2 # # This file contains Matplotlib transformation objects (e.g. from pixel to world # coordinates, but also world-to-world). import abc import numpy as np from matplotlib.path import Path from matplotlib.transforms import Transform from astropy import units as u from astropy.wcs import WCS from astropy.extern import six from astropy.coordinates import (SkyCoord, frame_transform_graph, SphericalRepresentation, UnitSphericalRepresentation, BaseCoordinateFrame) from .wcs_utils import wcs_to_celestial_frame @six.add_metaclass(abc.ABCMeta) class CurvedTransform(Transform): """ Abstract base class for non-affine curved transforms """ input_dims = 2 output_dims = 2 is_separable = False def transform_path(self, path): """ Transform a Matplotlib Path Parameters ---------- path : :class:`~matplotlib.path.Path` The path to transform Returns ------- path : :class:`~matplotlib.path.Path` The resulting path """ return Path(self.transform(path.vertices), path.codes) transform_path_non_affine = transform_path @abc.abstractmethod def transform(self, input): raise NotImplementedError("") @abc.abstractmethod def inverted(self): raise NotImplementedError("") class WCSWorld2PixelTransform(CurvedTransform): """ WCS transformation from world to pixel coordinates """ def __init__(self, wcs, slice=None): super(WCSWorld2PixelTransform, self).__init__() self.wcs = wcs if self.wcs.wcs.naxis > 2: if slice is None: raise ValueError("WCS has more than 2 dimensions, so ``slice`` should be set") elif len(slice) != self.wcs.wcs.naxis: raise ValueError("slice should have as many elements as WCS " "has dimensions (should be {0})".format(self.wcs.wcs.naxis)) else: self.slice = slice self.x_index = slice.index('x') self.y_index = slice.index('y') else: self.slice = None @property def input_dims(self): return self.wcs.wcs.naxis def transform(self, world): """ Transform world to pixel coordinates. You should pass in a NxM array where N is the number of points to transform, and M is the number of dimensions in the WCS. This then returns the (x, y) pixel coordinates as a Nx2 array. """ if world.shape[1] != self.wcs.wcs.naxis: raise ValueError("Second dimension of input values should match number of WCS coordinates") pixel = self.wcs.wcs_world2pix(world, 1) - 1 if self.slice is None: return pixel else: return pixel[:, (self.x_index, self.y_index)] transform_non_affine = transform def inverted(self): """ Return the inverse of the transform """ return WCSPixel2WorldTransform(self.wcs, slice=self.slice) class WCSPixel2WorldTransform(CurvedTransform): """ WCS transformation from pixel to world coordinates """ def __init__(self, wcs, slice=None): super(WCSPixel2WorldTransform, self).__init__() self.wcs = wcs self.slice = slice if self.slice is not None: self.x_index = slice.index('x') self.y_index = slice.index('y') @property def output_dims(self): return self.wcs.wcs.naxis def get_coord_slices(self, xmin, xmax, ymin, ymax, nx, ny): """ Get a coordinate slice """ x = np.linspace(xmin, xmax, nx) y = np.linspace(ymin, ymax, ny) Y, X = np.meshgrid(y, x) pixel = np.array([X.ravel(), Y.ravel()]).transpose() world = self.transform(pixel) return X, Y, [world[:, i].reshape(nx, ny).transpose() for i in range(self.wcs.wcs.naxis)] def transform(self, pixel): """ Transform pixel to world coordinates. You should pass in a Nx2 array of (x, y) pixel coordinates to transform to world coordinates. This will then return an NxM array where M is the number of dimensions in the WCS """ if self.slice is None: pixel_full = pixel.copy() else: pixel_full = [] for index in self.slice: if index == 'x': pixel_full.append(pixel[:, 0]) elif index == 'y': pixel_full.append(pixel[:, 1]) else: pixel_full.append(index) pixel_full = np.array(np.broadcast_arrays(*pixel_full)).transpose() pixel_full += 1 world = self.wcs.wcs_pix2world(pixel_full, 1) # At the moment, one has to manually check that the transformation # round-trips, otherwise it should be considered invalid. pixel_check = self.wcs.wcs_world2pix(world, 1) with np.errstate(invalid='ignore'): invalid = np.any(np.abs(pixel_check - pixel_full) > 1., axis=1) world[invalid] = np.nan return world transform_non_affine = transform def inverted(self): """ Return the inverse of the transform """ return WCSWorld2PixelTransform(self.wcs, slice=self.slice) class CoordinateTransform(CurvedTransform): def __init__(self, input_system, output_system): super(CoordinateTransform, self).__init__() self._input_system_name = input_system self._output_system_name = output_system if isinstance(self._input_system_name, WCS): self.input_system = wcs_to_celestial_frame(self._input_system_name) elif isinstance(self._input_system_name, six.string_types): self.input_system = frame_transform_graph.lookup_name(self._input_system_name) if self.input_system is None: raise ValueError("Frame {0} not found".format(self._input_system_name)) elif isinstance(self._input_system_name, BaseCoordinateFrame): self.input_system = self._input_system_name else: raise TypeError("input_system should be a WCS instance, string, or a coordinate frame instance") if isinstance(self._output_system_name, WCS): self.output_system = wcs_to_celestial_frame(self._output_system_name) elif isinstance(self._output_system_name, six.string_types): self.output_system = frame_transform_graph.lookup_name(self._output_system_name) if self.output_system is None: raise ValueError("Frame {0} not found".format(self._output_system_name)) elif isinstance(self._output_system_name, BaseCoordinateFrame): self.output_system = self._output_system_name else: raise TypeError("output_system should be a WCS instance, string, or a coordinate frame instance") if self.output_system == self.input_system: self.same_frames = True else: self.same_frames = False @property def same_frames(self): return self._same_frames @same_frames.setter def same_frames(self, same_frames): self._same_frames = same_frames def transform(self, input_coords): """ Transform one set of coordinates to another """ if self.same_frames: return input_coords x_in, y_in = input_coords[:, 0], input_coords[:, 1] try: c_in = SkyCoord(x_in, y_in, unit=(u.deg, u.deg), frame=self.input_system) except: # Astropy < 1.0 c_in = SkyCoord(x_in, y_in, unit=(u.deg, u.deg), frame=self.input_system.name, **dict((key, getattr(self.input_system, key)) for key in self.input_system.get_frame_attr_names().keys())) c_out = c_in.transform_to(self.output_system) if (c_out.representation is SphericalRepresentation or c_out.representation is UnitSphericalRepresentation): lon = c_out.data.lon.deg lat = c_out.data.lat.deg else: lon = c_out.spherical.lon.deg lat = c_out.spherical.lat.deg return np.concatenate((lon[:, np.newaxis], lat[:, np.newaxis]), axis=1) transform_non_affine = transform def inverted(self): """ Return the inverse of the transform """ return CoordinateTransform(self._output_system_name, self._input_system_name) wcsaxes-0.6/wcsaxes/utils.py0000644000077000000240000001030612535045247016150 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import numpy as np from astropy import units as u from astropy.extern import six from astropy.coordinates import BaseCoordinateFrame # Modified from axis_artist, supports astropy.units def select_step_degree(dv): # Modified from axis_artist, supports astropy.units if dv > 1. * u.arcsec: degree_limits_ = [1.5, 3, 7, 13, 20, 40, 70, 120, 270, 520] degree_steps_ = [1, 2, 5, 10, 15, 30, 45, 90, 180, 360] degree_units = [u.degree] * len(degree_steps_) minsec_limits_ = [1.5, 2.5, 3.5, 8, 11, 18, 25, 45] minsec_steps_ = [1, 2, 3, 5, 10, 15, 20, 30] minute_limits_ = np.array(minsec_limits_) / 60. minute_units = [u.arcmin] * len(minute_limits_) second_limits_ = np.array(minsec_limits_) / 3600. second_units = [u.arcsec] * len(second_limits_) degree_limits = np.concatenate([second_limits_, minute_limits_, degree_limits_]) degree_steps = minsec_steps_ + minsec_steps_ + degree_steps_ degree_units = second_units + minute_units + degree_units n = degree_limits.searchsorted(dv.to(u.degree)) step = degree_steps[n] unit = degree_units[n] return step * unit else: return select_step_scalar(dv.to(u.arcsec).value) * u.arcsec def select_step_hour(dv): if dv > 15. * u.arcsec: hour_limits_ = [1.5, 2.5, 3.5, 5, 7, 10, 15, 21, 36] hour_steps_ = [1, 2, 3, 4, 6, 8, 12, 18, 24] hour_units = [u.hourangle] * len(hour_steps_) minsec_limits_ = [1.5, 2.5, 3.5, 4.5, 5.5, 8, 11, 14, 18, 25, 45] minsec_steps_ = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30] minute_limits_ = np.array(minsec_limits_) / 60. minute_units = [15. * u.arcmin] * len(minute_limits_) second_limits_ = np.array(minsec_limits_) / 3600. second_units = [15. * u.arcsec] * len(second_limits_) hour_limits = np.concatenate([second_limits_, minute_limits_, hour_limits_]) hour_steps = minsec_steps_ + minsec_steps_ + hour_steps_ hour_units = second_units + minute_units + hour_units n = hour_limits.searchsorted(dv.to(u.hourangle)) step = hour_steps[n] unit = hour_units[n] return step * unit else: return select_step_scalar(dv.to(15. * u.arcsec).value) * (15. * u.arcsec) def select_step_scalar(dv): log10_dv = np.log10(dv) base = np.floor(log10_dv) frac = log10_dv - base steps = np.log10([1, 2, 5, 10]) imin = np.argmin(np.abs(frac - steps)) return 10. ** (base + steps[imin]) def get_coord_meta(frame): coord_meta = {} coord_meta['type'] = ('longitude', 'latitude') coord_meta['wrap'] = (None, None) coord_meta['unit'] = (u.deg, u.deg) try: from astropy.coordinates import frame_transform_graph if isinstance(frame, six.string_types): initial_frame = frame frame = frame_transform_graph.lookup_name(frame) if frame is None: raise ValueError("Unknown frame: {0}".format(initial_frame)) if not isinstance(frame, BaseCoordinateFrame): frame = frame() names = list(frame.representation_component_names.keys()) coord_meta['name'] = names[:2] except ImportError: if isinstance(frame, six.string_types): if frame in ('fk4', 'fk5', 'icrs'): coord_meta['name'] = ('ra', 'dec') elif frame == 'galactic': coord_meta['name'] = ('l', 'b') else: raise ValueError("Unknown frame: {0}".format(frame)) return coord_meta def coord_type_from_ctype(ctype): """ Determine whether a particular WCS ctype corresponds to an angle or scalar coordinate. """ if ctype[:4] in ['RA--'] or ctype[1:4] == 'LON': return 'longitude', None elif ctype[:4] in ['HPLN']: return 'longitude', 180. elif ctype[:4] in ['DEC-', 'HPLT'] or ctype[1:4] == 'LAT': return 'latitude', None else: return 'scalar', None wcsaxes-0.6/wcsaxes/version.py0000644000077000000240000001545212553237431016502 0ustar tomstaff00000000000000# Autogenerated by Astropy-affiliated package wcsaxes's setup.py on 2015-07-20 20:34:01.763315 from __future__ import unicode_literals import datetime import locale import os import subprocess import warnings def _decode_stdio(stream): try: stdio_encoding = locale.getdefaultlocale()[1] or 'utf-8' except ValueError: stdio_encoding = 'utf-8' try: text = stream.decode(stdio_encoding) except UnicodeDecodeError: # Final fallback text = stream.decode('latin1') return text def update_git_devstr(version, path=None): """ Updates the git revision string if and only if the path is being imported directly from a git working copy. This ensures that the revision number in the version string is accurate. """ try: # Quick way to determine if we're in git or not - returns '' if not devstr = get_git_devstr(sha=True, show_warning=False, path=path) except OSError: return version if not devstr: # Probably not in git so just pass silently return version if 'dev' in version: # update to the current git revision version_base = version.split('.dev', 1)[0] devstr = get_git_devstr(sha=False, show_warning=False, path=path) return version_base + '.dev' + devstr else: #otherwise it's already the true/release version return version def get_git_devstr(sha=False, show_warning=True, path=None): """ Determines the number of revisions in this repository. Parameters ---------- sha : bool If True, the full SHA1 hash will be returned. Otherwise, the total count of commits in the repository will be used as a "revision number". show_warning : bool If True, issue a warning if git returns an error code, otherwise errors pass silently. path : str or None If a string, specifies the directory to look in to find the git repository. If `None`, the current working directory is used, and must be the root of the git repository. If given a filename it uses the directory containing that file. Returns ------- devversion : str Either a string with the revision number (if `sha` is False), the SHA1 hash of the current commit (if `sha` is True), or an empty string if git version info could not be identified. """ if path is None: path = os.getcwd() if not _get_repo_path(path, levels=0): return '' if not os.path.isdir(path): path = os.path.abspath(os.path.dirname(path)) if sha: # Faster for getting just the hash of HEAD cmd = ['rev-parse', 'HEAD'] else: cmd = ['rev-list', '--count', 'HEAD'] def run_git(cmd): try: p = subprocess.Popen(['git'] + cmd, cwd=path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) stdout, stderr = p.communicate() except OSError as e: if show_warning: warnings.warn('Error running git: ' + str(e)) return (None, b'', b'') if p.returncode == 128: if show_warning: warnings.warn('No git repository present at {0!r}! Using ' 'default dev version.'.format(path)) return (p.returncode, b'', b'') if p.returncode == 129: if show_warning: warnings.warn('Your git looks old (does it support {0}?); ' 'consider upgrading to v1.7.2 or ' 'later.'.format(cmd[0])) return (p.returncode, stdout, stderr) elif p.returncode != 0: if show_warning: warnings.warn('Git failed while determining revision ' 'count: {0}'.format(_decode_stdio(stderr))) return (p.returncode, stdout, stderr) return p.returncode, stdout, stderr returncode, stdout, stderr = run_git(cmd) if not sha and returncode == 129: # git returns 129 if a command option failed to parse; in # particular this could happen in git versions older than 1.7.2 # where the --count option is not supported # Also use --abbrev-commit and --abbrev=0 to display the minimum # number of characters needed per-commit (rather than the full hash) cmd = ['rev-list', '--abbrev-commit', '--abbrev=0', 'HEAD'] returncode, stdout, stderr = run_git(cmd) # Fall back on the old method of getting all revisions and counting # the lines if returncode == 0: return str(stdout.count(b'\n')) else: return '' elif sha: return _decode_stdio(stdout)[:40] else: return _decode_stdio(stdout).strip() def _get_repo_path(pathname, levels=None): """ Given a file or directory name, determine the root of the git repository this path is under. If given, this won't look any higher than ``levels`` (that is, if ``levels=0`` then the given path must be the root of the git repository and is returned if so. Returns `None` if the given path could not be determined to belong to a git repo. """ if os.path.isfile(pathname): current_dir = os.path.abspath(os.path.dirname(pathname)) elif os.path.isdir(pathname): current_dir = os.path.abspath(pathname) else: return None current_level = 0 while levels is None or current_level <= levels: if os.path.exists(os.path.join(current_dir, '.git')): return current_dir current_level += 1 if current_dir == os.path.dirname(current_dir): break current_dir = os.path.dirname(current_dir) return None _packagename = "wcsaxes" _last_generated_version = "0.6" _last_githash = "5ee3237058432ce4faea04f58f6021d72c6c44b4" # Determine where the source code for this module # lives. If __file__ is not a filesystem path then # it is assumed not to live in a git repo at all. if _get_repo_path(__file__, levels=len(_packagename.split('.'))): version = update_git_devstr(_last_generated_version, path=__file__) githash = get_git_devstr(sha=True, show_warning=False, path=__file__) or _last_githash else: # The file does not appear to live in a git repo so don't bother # invoking git version = _last_generated_version githash = _last_githash major = 0 minor = 6 bugfix = 0 release = True timestamp = datetime.datetime(2015, 7, 20, 20, 34, 1, 763315) debug = False try: from ._compiler import compiler except ImportError: compiler = "unknown" try: from .cython_version import cython_version except ImportError: cython_version = "unknown" wcsaxes-0.6/wcsaxes/wcs_utils.py0000644000077000000240000001143312535045247017026 0ustar tomstaff00000000000000# Adapted from Astropy core package until 1.0 is released # # Copyright (c) 2011-2014, Astropy Developers # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of the Astropy Team nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import numpy as np __doctest_skip__ = ['wcs_to_celestial_frame'] def _wcs_to_celestial_frame_builtin(wcs): from astropy.coordinates import FK4, FK4NoETerms, FK5, ICRS, Galactic from astropy.time import Time from astropy.wcs import WCSSUB_CELESTIAL # Keep only the celestial part of the axes wcs = wcs.sub([WCSSUB_CELESTIAL]) if wcs.wcs.lng == -1 or wcs.wcs.lat == -1: return None radesys = wcs.wcs.radesys if np.isnan(wcs.wcs.equinox): equinox = None else: equinox = wcs.wcs.equinox xcoord = wcs.wcs.ctype[0][:4] ycoord = wcs.wcs.ctype[1][:4] # Apply logic from FITS standard to determine the default radesys if radesys == '' and xcoord == 'RA--' and ycoord == 'DEC-': if equinox is None: radesys = "ICRS" elif equinox < 1984.: radesys = "FK4" else: radesys = "FK5" if radesys == 'FK4': if equinox is not None: equinox = Time(equinox, format='byear') frame = FK4(equinox=equinox) elif radesys == 'FK4-NO-E': if equinox is not None: equinox = Time(equinox, format='byear') frame = FK4NoETerms(equinox=equinox) elif radesys == 'FK5': if equinox is not None: equinox = Time(equinox, format='jyear') frame = FK5(equinox=equinox) elif radesys == 'ICRS': frame = ICRS() else: if xcoord == 'GLON' and ycoord == 'GLAT': frame = Galactic() else: frame = None return frame WCS_FRAME_MAPPINGS = [[_wcs_to_celestial_frame_builtin]] class custom_frame_mappings(object): def __init__(self, mappings=[]): if hasattr(mappings, '__call__'): mappings = [mappings] WCS_FRAME_MAPPINGS.append(mappings) def __enter__(self): pass def __exit__(self, type, value, tb): WCS_FRAME_MAPPINGS.pop() def wcs_to_celestial_frame(wcs): """ For a given WCS, return the coordinate frame that matches the celestial component of the WCS. Parameters ---------- wcs : :class:`~astropy.wcs.WCS` instance The WCS to find the frame for Returns ------- frame : :class:`~astropy.coordinates.baseframe.BaseCoordinateFrame` subclass instance An instance of a :class:`~astropy.coordinates.baseframe.BaseCoordinateFrame` subclass instance that best matches the specified WCS. Notes ----- To extend this function to frames not defined in astropy.coordinates, you can write your own function which should take a :class:`~astropy.wcs.WCS` instance and should return either an instance of a frame, or `None` if no matching frame was found. You can register this function temporarily with:: >>> from astropy.wcs.utils import wcs_to_celestial_frame, custom_frame_mappings >>> with custom_frame_mappings(my_function): ... wcs_to_celestial_frame(...) """ for mapping_set in WCS_FRAME_MAPPINGS: for func in mapping_set: frame = func(wcs) if frame is not None: return frame raise ValueError("Could not determine celestial frame corresponding to " "the specified WCS object") wcsaxes-0.6/wcsaxes/wcs_wrapper.py0000644000077000000240000000117012436367710017345 0ustar tomstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst from astropy.wcs import WCS as AstropyWCS from .core import WCSAxes # The purpose of the following class is to implement the ``_as_mpl_axes`` method # which allows us to use the ``projection=`` API for Matplotlib. Once WCSAxes is # merged into Astropy, we can just add this method directly to the 'real' WCS # class. class WCS(AstropyWCS): def _as_mpl_axes(self): return WCSAxes, {'wcs': self} def __iter__(self): # Backport of astropy/astropy#3066 raise TypeError("'{0}' object is not iterable".format(self.__class__.__name__))