photutils-0.7.2/0000755000214200020070000000000013573510273015744 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/CHANGES.rst0000644000214200020070000010236313573510173017552 0ustar lbradleySTSCI\science000000000000000.7.2 (2019-12-09) ------------------ Bug Fixes ^^^^^^^^^ - ``photutils.isophote`` - Fixed computation of upper harmonics ``a3``, ``b3``, ``a4``, and ``b4`` in the ellipse fitting algorithm. [#1008] - ``photutils.psf`` - Fix to algorithm in ``EPSFBuilder``, addressing issues where ePSFs failed to build (yielding striped ePSFs). [#974] - Fix to ``IterativelySubtractedPSFPhotometry`` where an error could be thrown when a ``Finder`` was passed which did not return ``None`` if no sources were found. [#986] - Fix to ``centroid_epsf`` where the wrong oversampling factor was used along the y axis. [#1002] 0.7.1 (2019-10-09) ------------------ Bug Fixes ^^^^^^^^^ - ``photutils.psf`` - Fix to ``IterativelySubtractedPSFPhotometry`` where the residual image was not initialized when ``bkg_estimator`` was not supplied. [#942] - ``photutils.segmentation`` - Fixed a labeling bug in ``deblend_sources``. [#961] - Fixed an issue in ``source_properties`` when the input ``data`` is a ``Quantity`` array. [#963] 0.7 (2019-08-14) ---------------- General ^^^^^^^ - Any WCS object that supports the `astropy shared interface for WCS `_ is now supported. [#899] - Added a new ``photutils.__citation__`` and ``photutils.__bibtex__`` attributes which give a citation for photutils in bibtex format. [#926] New Features ^^^^^^^^^^^^ - ``photutils.aperture`` - Added parameter validation for all aperture classes. [#846] - Added ``from_float``, ``as_artist``, ``union`` and ``intersection`` methods to ``BoundingBox`` class. [#851] - Added ``shape`` and ``isscalar`` properties to Aperture objects. [#852] - Significantly improved the performance (~10-20 times faster) of aperture photometry, especially when using ``errors`` and ``Quantity`` inputs with many aperture positions. [#861] - ``aperture_photometry`` now supports ``NDData`` with ``StdDevUncertainty`` to input errors. [#866] - The ``mode`` keyword in the ``to_sky`` and ``to_pixel`` aperture methods was removed to implement the shared WCS interface. All WCS transforms now include distortions (if present). [#899] - ``photutils.datasets`` - Added ``make_gwcs`` function to create an example ``gwcs.wcs.WCS`` object. [#871] - ``photutils.isophote`` - Significantly improved the performance (~5 times faster) of ellipse fitting. [#826] - Added the ability to individually fix the ellipse-fitting parameters. [#922] - ``photutils.psf`` - Added new centroiding function ``centroid_epsf``. [#816] - ``photutils.segmentation`` - Significantly improved the performance of relabeling in segmentation images (e.g. ``remove_labels``, ``keep_labels``). [#810] - Added new ``background_area`` attribute to ``SegmentationImage``. [#825] - Added new ``data_ma`` attribute to ``Segment``. [#825] - Added new ``SegmentationImage`` methods: ``find_index``, ``find_indices``, ``find_areas``, ``check_label``, ``keep_label``, ``remove_label``, and ``reassign_labels``. [#825] - Added ``__repr__`` and ``__str__`` methods to ``SegmentationImage``. [#825] - Added ``slices``, ``indices``, and ``filtered_data_cutout_ma`` attributes to ``SourceProperties``. [#858] - Added ``__repr__`` and ``__str__`` methods to ``SourceProperties`` and ``SourceCatalog``. [#858] - Significantly improved the performance of calculating the ``background_at_centroid`` property in ``SourceCatalog``. [#863] - The default output table columns (source properties) are defined in a publicly-accessible variable called ``photutils.segmentation.properties.DEFAULT_COLUMNS``. [#863] - Added the ``gini`` source property representing the Gini coefficient. [#864] - Cached (lazy) properties can now be reset in ``SegmentationImage`` subclasses. [#916] - Significantly improved the performance of ``deblend_sources``. It is ~40-50% faster for large images (e.g. 4k x 4k) with a few thousand of sources. [#924] - ``photutils.utils`` - Added ``NoDetectionsWarning`` class. [#836] Bug Fixes ^^^^^^^^^ - ``photutils.aperture`` - Fixed an issue where the ``ApertureMask.cutout`` method would drop the data units when ``copy=True``. [#842] - Fixed a corner-case issue where aperture photometry would return NaN for non-finite data values outside the aperture but within the aperture bounding box. [#843] - Fixed an issue where the ``celestial_center`` column (for sky apertures) would be a length-1 array containing a ``SkyCoord`` object instead of a length-1 ``SkyCoord`` object. [#844] - ``photutils.isophote`` - Fixed an issue where the linear fitting mode was not working. [#912] - Fixed the radial gradient computation [#934]. - ``photutils.psf`` - Fixed a bug in the ``EPSFStar`` ``register_epsf`` and ``compute_residual_image`` computations. [#885] - A ValueError is raised if ``aperture_radius`` is not input and cannot be determined from the input ``psf_model``. [#903] - Fixed normalization of ePSF model, now correctly normalizing on undersampled pixel grid. [#817] - ``photutils.segmentation`` - Fixed an issue where ``deblend_sources`` could fail for sources with labels that are a power of 2 and greater than 255. [#806] - ``SourceProperties`` and ``source_properties`` will no longer raise an exception if a source is completely masked. [#822] - Fixed an issue in ``SourceProperties`` and ``source_properties`` where inf values in the data array were not automatically masked. [#822] - ``error`` and ``background`` arrays are now always masked identically to the input ``data``. [#822] - Fixed the ``perimeter`` property to take into account the source mask. [#822] - Fixed the ``background_at_centroid`` source property to use bilinear interpolation. [#822] - Fixed ``SegmentationImage`` ``outline_segments`` to include outlines along the image boundaries. [#825] - Fixed ``SegmentationImage.is_consecutive`` to return ``True`` only if the labels are consecutive and start with label=1. [#886] - Fixed a bug in ``deblend_sources`` where sources could be deblended too much when ``connectivity=8``. [#890] - Fixed a bug in ``deblend_sources`` where the ``contrast`` parameter had little effect if the original segment contained three or more sources. [#890] - ``photutils.utils`` - Fixed a bug in ``filter_data`` where units were dropped for data ``Quantity`` objects. [#872] API changes ^^^^^^^^^^^ - ``photutils.aperture`` - Deprecated inputting aperture pixel positions shaped as 2xN. [#847] - Renamed the ``celestial_center`` column to ``sky_center`` in the ``aperture_photometry`` output table. [#848] - Aperture objects defined with a single (x, y) position (input as 1D) are now considered scalar objects, which can be checked with the new ``isscalar`` Aperture property. [#852] - Non-scalar Aperture objects can now be indexed, sliced, and iterated. [#852] - Scalar Aperture objects now return scalar ``positions`` and ``bounding_boxes`` properties and its ``to_mask`` method returns an ``ApertureMask`` object instead of a length-1 list containing an ``ApertureMask``. [#852] - Deprecated the Aperture ``mask_area`` method. [#853] - Aperture ``area`` is now an attribute instead of a method. [#854] - The Aperture plot keyword ``ax`` was deprecated and renamed to ``axes``. [#854] - Deprecated the ``units`` keyword in ``aperture_photometry`` and the ``PixelAperture.do_photometry`` method. [#866, #861] - Deprecated ``PrimaryHDU``, ``ImageHDU``, and ``HDUList`` inputs to ``aperture_photometry``. [#867] - The ``aperture_photometry`` function moved to a new ``photutils.aperture.photometry`` module. [#876] - Renamed the ``bounding_boxes`` attribute for pixel-based apertures to ``bbox`` for consistency. [#896] - ``photutils.background`` - The ``Background2D`` ``plot_meshes`` keyword ``ax`` was deprecated and renamed to ``axes``. [#854] - ``photutils.datasets`` - The ``make_noise_image`` ``type`` keyword was deprecated and renamed to ``distribution``. [#877] - ``photutils.detection`` - Removed deprecated ``subpixel`` keyword for ``find_peaks``. [#835] - ``DAOStarFinder``, ``IRAFStarFinder``, and ``find_peaks`` now return ``None`` if no source/peaks are found. Also, for this case a ``NoDetectionsWarning`` is issued. [#836] - Deprecated the ``BoundingBox`` ``as_patch`` method (instead use ``as_artist``). [#851] - Renamed the ``snr`` (deprecated) keyword to ``nsigma`` in ``detect_threshold``. [#917] - ``photutils.isophote`` - Isophote central values and intensity gradients are now returned to the output table. [#892] - The ``EllipseSample`` ``update`` method now needs to know the fix/fit state of each individual parameter. This can be passed to it via a ``Geometry`` instance, e.g. ``update(geometry.fix)``. [#922] - ``photutils.psf`` - ``FittableImageModel`` and subclasses now allow for different ``oversampling`` factors to be specified in the x and y directions. [#834] - Removed ``pixel_scale`` keyword from ``EPSFStar``, ``EPSFBuilder``, and ``EPSFModel``. [#815] - Added ``oversampling`` keyword to ``centroid_com``. [#816] - Removed deprecated ``Star``, ``Stars``, and ``LinkedStar`` classes. [#894] - Removed ``recentering_boxsize`` and ``center_accuracy`` keywords and added ``norm_radius`` and ``shift_value`` keywords in ``EPSFBuilder``. [#817] - Added ``norm_radius`` and ``shift_value`` keywords to ``EPSFModel``. [#817] - ``photutils.segmentation`` - Removed deprecated ``SegmentationImage`` attributes ``data_masked``, ``max``, and ``is_sequential`` and methods ``area`` and ``relabel_sequential``. [#825] - Renamed ``SegmentationImage`` methods ``cmap`` (deprecated) to ``make_cmap`` and ``relabel`` (deprecated) to ``reassign_label``. The new ``reassign_label`` method gains a ``relabel`` keyword. [#825] - The ``SegmentationImage`` ``segments`` and ``slices`` attributes now have the same length as ``labels`` (no ``None`` placeholders). [#825] - ``detect_sources`` now returns ``None`` if no sources are found. Also, for this case a ``NoDetectionsWarning`` is issued. [#836] - The ``SegmentationImage`` input ``data`` array must contain at least one non-zero pixel and must not contain any non-finite values. [#836] - A ``ValueError`` is raised if an empty list is input into ``SourceCatalog`` or no valid sources are defined in ``source_properties``. [#836] - Deprecated the ``values`` and ``coords`` attributes in ``SourceProperties``. [#858] - Deprecated the unused ``mask_value`` keyword in ``make_source_mask``. [#858] - The ``bbox`` property now returns a ``BoundingBox`` instance. [#863] - The ``xmin/ymin`` and ``xmax/ymax`` properties have been deprecated with the replacements having a ``bbox_`` prefix (e.g. ``bbox_xmin``). [#863] - The ``orientation`` property is now returned as a ``Quantity`` instance in units of degrees. [#863] - Renamed the ``snr`` (deprecated) keyword to ``nsigma`` in ``make_source_mask``. [#917] - ``photutils.utils`` - Renamed ``random_cmap`` to ``make_random_cmap``. [#825] - Removed deprecated ``cutout_footprint`` function. [#835] - Deprecated the ``wcs_helpers`` functions ``pixel_scale_angle_at_skycoord``, ``assert_angle_or_pixel``, ``assert_angle``, and ``pixel_to_icrs_coords``. [#846] - Removed deprecated ``interpolate_masked_data`` function. [#895] - Deprecated the ``mask_to_mirrored_num`` function. [#895] - Deprecated the ``get_version_info``, ``filter_data``, and ``std_blocksum`` functions. [#918] 0.6 (2018-12-11) ---------------- General ^^^^^^^ - Versions of Numpy <1.11 are no longer supported. [#783] New Features ^^^^^^^^^^^^ - ``photutils.detection`` - ``DAOStarFinder`` and ``IRAFStarFinder`` gain two new parameters: ``brightest`` to keep the top ``brightest`` (based on the flux) objects in the returned catalog (after all other filtering has been applied) and ``peakmax`` to exclude sources with peak pixel values larger or equal to ``peakmax``. [#750] - Added a ``mask`` keyword to ``DAOStarFinder`` and ``IRAFStarFinder`` that can be used to mask regions of the input image. [#759] - ``photutils.psf`` - The ``Star``, ``Stars``, and ``LinkedStars`` classes are now deprecated and have been renamed ``EPSFStar``, ``EPSFStars``, and ``LinkedEPSFStars``, respectively. [#727] - Added a ``GriddedPSFModel`` class for spatially-dependent PSFs. [#772] - The ``pixel_scale`` keyword in ``EPSFStar``, ``EPSFBuilder`` and ``EPSFModel`` is now deprecated. Use the ``oversampling`` keyword instead. [#780] API changes ^^^^^^^^^^^ - ``photutils.detection`` - The ``find_peaks`` function now returns an empty ``astropy.table.Table`` instead of an empty list if the input data is an array of constant values. [#709] - The ``find_peaks`` function will no longer issue a RuntimeWarning if the input data contains NaNs. [#712] - If no sources/peaks are found, ``DAOStarFinder``, ``IRAFStarFinder``, and ``find_peaks`` now will return an empty table with column names and types. [#758, #762] - ``photutils.psf`` - The ``photutils.psf.funcs.py`` module was renamed ``photutils.psf.utils.py``. The ``prepare_psf_model`` and ``get_grouped_psf_model`` functions were also moved to this new ``utils.py`` module. [#777] Bug Fixes ^^^^^^^^^ - ``photutils.aperture`` - If a single aperture is input as a list into the ``aperture_photometry`` function, then the output columns will be called ``aperture_sum_0`` and ``aperture_sum_err_0`` (if errors are used). Previously these column names did not have the trailing "_0". [#779] - ``photutils.segmentation`` - Fixed a bug in the computation of ``sky_bbox_ul``, ``sky_bbox_lr``, ``sky_bbox_ur`` in the ``SourceCatalog``. [#716] Other Changes and Additions ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Updated background and detection functions that call ``astropy.stats.SigmaClip`` or ``astropy.stats.sigma_clipped_stats`` to support both their ``iters`` (for astropy < 3.1) and ``maxiters`` keywords. [#726] 0.5 (2018-08-06) ---------------- General ^^^^^^^ - Versions of Python <3.5 are no longer supported. [#702, #703] - Versions of Numpy <1.10 are no longer supported. [#697, #703] - Versions of Pytest <3.1 are no longer supported. [#702] - ``pytest-astropy`` is now required to run the test suite. [#702, #703] - The documentation build now uses the Sphinx configuration from ``sphinx-astropy`` rather than from ``astropy-helpers``. [#702] New Features ^^^^^^^^^^^^ - ``photutils.aperture`` - Added ``plot`` and ``to_aperture`` methods to ``BoundingBox``. [#662] - Added default theta value for elliptical and rectangular apertures. [#674] - ``photutils.centroid`` - Added a ``centroid_sources`` function to calculate centroid of many sources in a single image. [#656] - An n-dimensional array can now be input into the ``centroid_com`` function. [#685] - ``photutils.datasets`` - Added a ``load_simulated_hst_star_image`` function to load a simulated HST WFC3/IR F160W image of stars. [#695] - ``photutils.detection`` - Added a ``centroid_func`` keyword to ``find_peaks``. The ``subpixels`` keyword is now deprecated. [#656] - The ``find_peaks`` function now returns ``SkyCoord`` objects in the table instead of separate RA and Dec. columns. [#656] - The ``find_peaks`` function now returns an empty Table and issues a warning when no peaks are found. [#668] - ``photutils.psf`` - Added tools to build and fit an effective PSF (``EPSFBuilder`` and ``EPSFFitter``). [#695] - Added ``extract_stars`` function to extract cutouts of stars used to build an ePSF. [#695] - Added ``EPSFModel`` class to hold a fittable ePSF model. [#695] - ``photutils.segmentation`` - Added a ``mask`` keyword to the ``detect_sources`` function. [#621] - Renamed ``SegmentationImage`` ``max`` attribute to ``max_label``. ``max`` is deprecated. [#662] - Added a ``Segment`` class to hold the cutout image and properties of single labeled region (source segment). [#662] - Deprecated the ``SegmentationImage`` ``area`` method. Instead, use the ``areas`` attribute. [#662] - Renamed ``SegmentationImage`` ``data_masked`` attribute to ``data_ma``. ``data_masked`` is deprecated. [#662] - Renamed ``SegmentationImage`` ``is_sequential`` attribute to ``is_consecutive``. ``is_sequential`` is deprecated. [#662] - Renamed ``SegmentationImage`` ``relabel_sequential`` attribute to ``relabel_consecutive``. ``relabel_sequential`` is deprecated. [#662] - Added a ``missing_labels`` property to ``SegmentationImage``. [#662] - Added a ``check_labels`` method to ``SegmentationImage``. The ``check_label`` method is deprecated. [#662] - ``photutils.utils`` - Deprecated the ``cutout_footprint`` function. [#656] Bug Fixes ^^^^^^^^^ - ``photutils.aperture`` - Fixed a bug where quantity inputs to the aperture classes would sometimes fail. [#693] - ``photutils.detection`` - Fixed an issue in ``detect_sources`` where in some cases sources with a size less than ``npixels`` could be returned. [#663] - Fixed an issue in ``DAOStarFinder`` where in some cases a few too many sources could be returned. [#671] - ``photutils.isophote`` - Fixed a bug where isophote fitting would fail when the initial center was not specified for an image with an elongated aspect ratio. [#673] - ``photutils.segmentation`` - Fixed ``deblend_sources`` when other sources are in the neighborhood. [#617] - Fixed ``source_properties`` to handle the case where the data contain one or more NaNs. [#658] - Fixed an issue with ``deblend_sources`` where sources were not deblended where the data contain one or more NaNs. [#658] - Fixed the ``SegmentationImage`` ``areas`` attribute to not include the zero (background) label. [#662] Other Changes and Additions ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ``photutils.isophote`` - Corrected the units for isophote ``sarea`` in the documentation. [#657] 0.4 (2017-10-30) ---------------- General ^^^^^^^ - Dropped python 3.3 support. [#542] - Dropped numpy 1.8 support. Minimal required version is now numpy 1.9. [#542] - Dropped support for astropy 1.x versions. Minimal required version is now astropy 2.0. [#575] - Dropped scipy 0.15 support. Minimal required version is now scipy 0.16. [#576] - Explicitly require six as dependency. [#601] New Features ^^^^^^^^^^^^ - ``photutils.aperture`` - Added ``BoundingBox`` class, used when defining apertures. [#481] - Apertures now have ``__repr__`` and ``__str__`` defined. [#493] - Improved plotting of annulus apertures using Bezier curves. [#494] - Rectangular apertures now use the true minimal bounding box. [#507] - Elliptical apertures now use the true minimal bounding box. [#508] - Added a ``to_sky`` method for pixel apertures. [#512] - ``photutils.background`` - Mesh rejection now also applies to pixels that are masked during sigma clipping. [#544] - ``photutils.datasets`` - Added new ``make_wcs`` and ``make_imagehdu`` functions. [#527] - Added new ``show_progress`` keyword to the ``load_*`` functions. [#590] - ``photutils.isophote`` - Added a new ``photutils.isophote`` subpackage to provide tools to fit elliptical isophotes to a galaxy image. [#532, #603] - ``photutils.segmentation`` - Added a ``cmap`` method to ``SegmentationImage`` to generate a random matplotlib colormap. [#513] - Added ``sky_centroid`` and ``sky_centroid_icrs`` source properties. [#592] - Added new source properties representing the sky coordinates of the bounding box corner vertices (``sky_bbox_ll``, ``sky_bbox_ul`` ``sky_bbox_lr``, and ``sky_bbox_ur``). [#592] - Added new ``SourceCatalog`` class to hold the list of ``SourceProperties``. [#608] - The ``properties_table`` function is now deprecated. Use the ``SourceCatalog.to_table()`` method instead. [#608] - ``photutils.psf`` - Uncertainties on fitted parameters are added to the final table. [#516] - Fitted results of any free parameter are added to the final table. [#471] API changes ^^^^^^^^^^^ - ``photutils.aperture`` - The ``ApertureMask`` ``apply()`` method has been renamed to ``multiply()``. [#481]. - The ``ApertureMask`` input parameter was renamed from ``mask`` to ``data``. [#548] - Removed the ``pixelwise_errors`` keyword from ``aperture_photometry``. [#489] - ``photutils.background`` - The ``Background2D`` keywords ``exclude_mesh_method`` and ``exclude_mesh_percentile`` were removed in favor of a single keyword called ``exclude_percentile``. [#544] - Renamed ``BiweightMidvarianceBackgroundRMS`` to ``BiweightScaleBackgroundRMS``. [#547] - Removed the ``SigmaClip`` class. ``astropy.stats.SigmaClip`` is a direct replacement. [#569] - ``photutils.datasets`` - The ``make_poission_noise`` function was renamed to ``apply_poisson_noise``. [#527] - The ``make_random_gaussians`` function was renamed to ``make_random_gaussians_table``. The parameter ranges must now be input as a dictionary. [#527] - The ``make_gaussian_sources`` function was renamed to ``make_gaussian_sources_image``. [#527] - The ``make_random_models`` function was renamed to ``make_random_models_table``. [#527] - The ``make_model_sources`` function was renamed to ``make_model_sources_image``. [#527] - The ``unit``, ``hdu``, ``wcs``, and ``wcsheader`` keywords in ``photutils.datasets`` functions were removed. [#527] - ``'photutils-datasets'`` was added as an optional ``location`` in the ``get_path`` function. This option is used as a fallback in case the ``'remote'`` location (astropy data server) fails. [#589] - ``photutils.detection`` - The ``daofind`` and ``irafstarfinder`` functions were removed. [#588] - ``photutils.psf`` - ``IterativelySubtractedPSFPhotometry`` issues a "no sources detected" warning only on the first iteration, if applicable. [#566] - ``photutils.segmentation`` - The ``'icrs_centroid'``, ``'ra_icrs_centroid'``, and ``'dec_icrs_centroid'`` source properties are deprecated and are no longer default columns returned by ``properties_table``. [#592] - The ``properties_table`` function now returns a ``QTable``. [#592] - ``photutils.utils`` - The ``background_color`` keyword was removed from the ``random_cmap`` function. [#528] - Deprecated unused ``interpolate_masked_data()``. [#526, #611] Bug Fixes ^^^^^^^^^ - ``photutils.segmentation`` - Fixed ``deblend_sources`` so that it correctly deblends multiple sources. [#572] - Fixed a bug in calculation of the ``sky_centroid_icrs`` (and deprecated ``icrs_centroid``) property where the incorrect pixel origin was being passed. [#592] - ``photutils.utils`` - Added a check that ``data`` and ``bkg_error`` have the same units in ``calc_total_error``. [#537] 0.3.1 (unreleased) ------------------ General ^^^^^^^ - Dropped numpy 1.7 support. Minimal required version is now numpy 1.8. [#327] - ``photutils.datasets`` - The ``load_*`` functions that use remote data now retrieve the data from ``data.astropy.org`` (the astropy data repository). [#472] Bug Fixes ^^^^^^^^^ - ``photutils.background`` - Fixed issue with ``Background2D`` with ``edge_method='pad'`` that occurred when unequal padding needed to be applied to each axis. [#498] - Fixed issue with ``Background2D`` that occurred when zero padding needed to apply along only one axis. [#500] - ``photutils.geometry`` - Fixed a bug in ``circular_overlap_grid`` affecting 32-bit machines that could cause errors circular aperture photometry. [#475] - ``photutils.psf`` - Fixed a bug in how ``FittableImageModel`` represents its center. [#460] - Fix bug which modified user's input table when doing forced photometry. [#485] 0.3 (2016-11-06) ---------------- New Features ^^^^^^^^^^^^ - ``photutils.aperture`` - Added new ``origin`` keyword to aperture ``plot`` methods. [#395] - Added new ``id`` column to ``aperture_photometry`` output table. [#446] - Added ``__len__`` method for aperture classes. [#446] - Added new ``to_mask`` method to ``PixelAperture`` classes. [#453] - Added new ``ApertureMask`` class to generate masks from apertures. [#453] - Added new ``mask_area()`` method to ``PixelAperture`` classes. [#453] - The ``aperture_photometry()`` function now accepts a list of aperture objects. [#454] - ``photutils.background`` - Added new ``MeanBackground``, ``MedianBackground``, ``MMMBackground``, ``SExtractorBackground``, ``BiweightLocationBackground``, ``StdBackgroundRMS``, ``MADStdBackgroundRMS``, and ``BiweightMidvarianceBackgroundRMS`` classes. [#370] - Added ``axis`` keyword to new background classes. [#392] - Added new ``removed_masked``, ``meshpix_threshold``, and ``edge_method`` keywords for the 2D background classes. [#355] - Added new ``std_blocksum`` function. [#355] - Added new ``SigmaClip`` class. [#423] - Added new ``BkgZoomInterpolator`` and ``BkgIDWInterpolator`` classes. [#437] - ``photutils.datasets`` - Added ``load_irac_psf`` function. [#403] - ``photutils.detection`` - Added new ``make_source_mask`` convenience function. [#355] - Added ``filter_data`` function. [#398] - Added ``DAOStarFinder`` and ``IRAFStarFinder`` as oop interfaces for ``daofind`` and ``irafstarfinder``, respectively, which are now deprecated. [#379] - ``photutils.psf`` - Added ``BasicPSFPhotometry``, ``IterativelySubtractedPSFPhotometry``, and ``DAOPhotPSFPhotometry`` classes to perform PSF photometry in crowded fields. [#427] - Added ``DAOGroup`` and ``DBSCANGroup`` classes for grouping overlapping sources. [#369] - ``photutils.psf_match`` - Added ``create_matching_kernel`` and ``resize_psf`` functions. Also, added ``CosineBellWindow``, ``HanningWindow``, ``SplitCosineBellWindow``, ``TopHatWindow``, and ``TukeyWindow`` classes. [#403] - ``photutils.segmentation`` - Created new ``photutils.segmentation`` subpackage. [#442] - Added ``copy`` and ``area`` methods and an ``areas`` property to ``SegmentationImage``. [#331] API changes ^^^^^^^^^^^ - ``photutils.aperture`` - Removed the ``effective_gain`` keyword from ``aperture_photometry``. Users must now input the total error, which can be calculated using the ``calc_total_error`` function. [#368] - ``aperture_photometry`` now outputs a ``QTable``. [#446] - Renamed ``source_id`` keyword to ``indices`` in the aperture ``plot()`` method. [#453] - Added ``mask`` and ``unit`` keywords to aperture ``do_photometry()`` methods. [#453] - ``photutils.background`` - For the background classes, the ``filter_shape`` keyword was renamed to ``filter_size``. The ``background_low_res`` and ``background_rms_low_res`` class attributes were renamed to ``background_mesh`` and ``background_rms_mesh``, respectively. [#355, #437] - The ``Background2D`` ``method`` and ``backfunc`` keywords have been removed. In its place one can input callable objects via the ``sigma_clip``, ``bkg_estimator``, and ``bkgrms_estimator`` keywords. [#437] - The interpolator to be used by the ``Background2D`` class can be input as a callable object via the new ``interpolator`` keyword. [#437] - ``photutils.centroids`` - Created ``photutils.centroids`` subpackage, which contains the ``centroid_com``, ``centroid_1dg``, and ``centroid_2dg`` functions. These functions now return a two-element numpy ndarray. [#428] - ``photutils.detection`` - Changed finding algorithm implementations (``daofind`` and ``starfind``) from functional to object-oriented style. Deprecated old style. [#379] - ``photutils.morphology`` - Created ``photutils.morphology`` subpackage. [#428] - Removed ``marginalize_data2d`` function. [#428] - Moved ``cutout_footprint`` from ``photutils.morphology`` to ``photutils.utils``. [#428] - Added a function to calculate the Gini coefficient (``gini``). [#343] - ``photutils.psf`` - Removed the ``effective_gain`` keyword from ``psf_photometry``. Users must now input the total error, which can be calculated using the ``calc_total_error`` function. [#368] - ``photutils.segmentation`` - Removed the ``effective_gain`` keyword from ``SourceProperties`` and ``source_properties``. Users must now input the total error, which can be calculated using the ``calc_total_error`` function. [#368] - ``photutils.utils`` - Renamed ``calculate_total_error`` to ``calc_total_error``. [#368] Bug Fixes ^^^^^^^^^ - ``photutils.aperture`` - Fixed a bug in ``aperture_photometry`` so that single-row output tables do not return a multidimensional column. [#446] - ``photutils.centroids`` - Fixed a bug in ``centroid_1dg`` and ``centroid_2dg`` that occured when the input data contained invalid (NaN or inf) values. [#428] - ``photutils.segmentation`` - Fixed a bug in ``SourceProperties`` where ``error`` and ``background`` units were sometimes dropped. [#441] 0.2.2 (2016-07-06) ------------------ General ^^^^^^^ - Dropped numpy 1.6 support. Minimal required version is now numpy 1.7. [#327] - Fixed configparser for Python 3.5. [#366, #384] Bug Fixes ^^^^^^^^^ - ``photutils.detection`` - Fixed an issue to update segmentation image slices after deblending. [#340] - Fixed source deblending to pass the pixel connectivity to the watershed algorithm. [#347] - SegmentationImage properties are now cached instead of recalculated, which significantly improves performance. [#361] - ``photutils.utils`` - Fixed a bug in ``pixel_to_icrs_coords`` where the incorrect pixel origin was being passed. [#348] 0.2.1 (2016-01-15) ------------------ Bug Fixes ^^^^^^^^^ - ``photutils.background`` - Added more robust version checking of Astropy. [#318] - ``photutils.detection`` - Added more robust version checking of Astropy. [#318] - ``photutils.segmentation`` - Fixed issue where ``SegmentationImage`` slices were not being updated. [#317] - Added more robust version checking of scikit-image. [#318] 0.2 (2015-12-31) ---------------- General ^^^^^^^ - Photutils has the following requirements: - Python 2.7 or 3.3 or later - Numpy 1.6 or later - Astropy v1.0 or later New Features ^^^^^^^^^^^^ - ``photutils.detection`` - ``find_peaks`` now returns an Astropy Table containing the (x, y) positions and peak values. [#240] - ``find_peaks`` has new ``mask``, ``error``, ``wcs`` and ``subpixel`` precision options. [#244] - ``detect_sources`` will now issue a warning if the filter kernel is not normalized to 1. [#298] - Added new ``deblend_sources`` function, an experimental source deblender. [#314] - ``photutils.morphology`` - Added new ``GaussianConst2D`` (2D Gaussian plus a constant) model. [#244] - Added new ``marginalize_data2d`` function. [#244] - Added new ``cutout_footprint`` function. [#244] - ``photutils.segmentation`` - Added new ``SegmentationImage`` class. [#306] - Added new ``check_label``, ``keep_labels``, and ``outline_segments`` methods for modifying ``SegmentationImage``. [#306] - ``photutils.utils`` - Added new ``random_cmap`` function to generate a colormap comprised of random colors. [#299] - Added new ``ShepardIDWInterpolator`` class to perform Inverse Distance Weighted (IDW) interpolation. [#307] - The ``interpolate_masked_data`` function can now interpolate higher-dimensional data. [#310] API changes ^^^^^^^^^^^ - ``photutils.segmentation`` - The ``relabel_sequential``, ``relabel_segments``, ``remove_segments``, ``remove_border_segments``, and ``remove_masked_segments`` functions are now ``SegmentationImage`` methods (with slightly different names). [#306] - The ``SegmentProperties`` class has been renamed to ``SourceProperties``. Likewise, the ``segment_properties`` function has been renamed to ``source_properties``. [#306] - The ``segment_sum`` and ``segment_sum_err`` attributes have been renamed to ``source_sum`` and ``source_sum_err``, respectively. [#306] - The ``background_atcentroid`` attribute has been renamed to ``background_at_centroid``. [#306] Bug Fixes ^^^^^^^^^ - ``photutils.aperture_photometry`` - Fixed an issue where ``np.nan`` or ``np.inf`` were not properly masked. [#267] - ``photutils.geometry`` - ``overlap_area_triangle_unit_circle`` handles correctly a corner case in some i386 systems where the area of the aperture was not computed correctly. [#242] - ``rectangular_overlap_grid`` and ``elliptical_overlap_grid`` fixes to normalization of subsampled pixels. [#265] - ``overlap_area_triangle_unit_circle`` handles correctly the case where a line segment intersects at a triangle vertex. [#277] Other Changes and Additions ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Updated astropy-helpers to v1.1. [#302] 0.1 (2014-12-22) ---------------- Photutils 0.1 was released on December 22, 2014. It requires Astropy version 0.4 or later. photutils-0.7.2/CITATION.rst0000644000214200020070000000011013572576654017716 0ustar lbradleySTSCI\science00000000000000See https://github.com/astropy/photutils/blob/master/photutils/CITATION photutils-0.7.2/CODE_OF_CONDUCT.rst0000644000214200020070000000025713572573650020766 0ustar lbradleySTSCI\science00000000000000Photutils is an `Astropy `_ affiliated package. We follow the `Astropy Community Code of Conduct `_. photutils-0.7.2/CONTRIBUTING.rst0000644000214200020070000001437413572573650020425 0ustar lbradleySTSCI\science00000000000000Contributing to Photutils ========================= Reporting Issues ---------------- When opening an issue to report a problem, please try to provide a minimal code example that reproduces the issue. Also, please include details of the operating system and the Python, Numpy, Astropy, and Photutils versions you are using. Contributing code ----------------- So you're interested in contributing code to Photutils? Excellent! Most contributions to Photutils are done via pull requests from GitHub users' forks of the `Photutils repository `_. If you're new to this style of development, you'll want to read over the `Astropy development workflow `_. Once you open a pull request (which should be opened against the ``master`` branch, not against any other branch), please make sure that you include the following: - **Code**: the code you are adding, which should follow as much as possible the `Astropy coding guidelines `_. - **Tests**: these are either tests to ensure code that previously failed now works (regression tests) or tests that cover as much as possible of the new functionality to make sure it doesn't break in the future. The tests are also used to ensure consistent results on all platforms, since we run these tests on many platforms/configurations. For more information about how to write tests, see the `Astropy testing guidelines `_. - **Documentation**: if you are adding new functionality, be sure to include a description in the main documentation (in ``docs/``). For more information, please see the detailed `Astropy documentation guidelines `_. - **Changelog entry**: if you are fixing a bug or adding new functionality, you should add an entry to the ``CHANGES.rst`` file that includes the PR number and if possible the issue number (if you are opening a pull request you may not know this yet, but you can add it once the pull request is open). If you're not sure where to put the changelog entry, wait until a maintainer has reviewed your PR and assigned it to a milestone. You do not need to include a changelog entry for fixes to bugs introduced in the developer version and therefore are not present in the stable releases. In general, you do not need to include a changelog entry for minor documentation or test updates. Only user-visible changes (new features/API changes, fixed issues) need to be mentioned. If in doubt, ask the core maintainer reviewing your changes. Other Tips ---------- - To prevent the automated tests from running you can add ``[ci skip]`` to your commit message. This is useful if your PR is a work in progress and you are not yet ready for the tests to run. For example: $ git commit -m "WIP widget [ci skip]" - If you already made the commit without including this string, you can edit your existing commit message by running: $ git commit --amend - To skip only the testing on Travis CI use ``[skip travis]``. - If your commit makes substantial changes to the documentation, but no code changes, then you can use ``[docs only]``, that will skip all but the documentation building jobs on Travis. - When contributing trivial documentation fixes (i.e. fixes to typos, spelling, grammar) that do not contain any special markup and are not associated with code changes, please include the string ``[docs only]`` in your commit message. $ git commit -m "Fixed typo [docs only]" Checklist for Contributed Code ------------------------------ A pull request for a new feature will be reviewed to see if it meets the following requirements. For any pull request, a Photutils maintainer can help to make sure that the pull request meets the requirements for inclusion in the package. **Scientific Quality** (when applicable) * Is the submission relevant to this package? * Are references included to the original source for the algorithm? * Does the code perform as expected? * Has the code been tested against previously existing implementations? **Code Quality** * Are the `Astropy coding guidelines `_ followed? * Are there dependencies other than the Astropy core, the Python Standard Library, and NumPy? - Is the package importable even if the C-extensions are not built? - Are additional dependencies handled appropriately? - Do functions and classes that require additional dependencies raise an `ImportError` if they are not present? **Testing** * Are the `Astropy testing guidelines `_ followed? * Are the inputs to the functions and classes sufficiently tested? * Are there tests for any exceptions raised? * Are there tests for the expected performance? * Are the sources for the tests documented? * Are the tests that require an `optional dependency `_ marked as such? * Does "``python setup.py test``" run without failures? **Documentation** * Are the `Astropy documentation guidelines `_ followed? * Is there a `docstring `_ in the functions and classes describing: - What the code does? - The format of the inputs of the function or class? - The format of the outputs of the function or class? - References to the original algorithms? - Any exceptions which are raised? - An example of running the code? * Is there any information needed to be added to the docs to describe the function or class? * Does the documentation build without errors or warnings? **License** * Is the photutils license included at the top of the file? * Are there any conflicts with this code and existing codes? **Photutils requirements** * Do all the Travis CI, AppVeyor, and CircleCI tests pass? * If applicable, has an entry been added into the changelog? * Can you checkout the pull request and repeat the examples and tests? photutils-0.7.2/LICENSE.rst0000644000214200020070000000273413547426552017575 0ustar lbradleySTSCI\science00000000000000Copyright (c) 2011-2018, Photutils developers All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Photutils 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. photutils-0.7.2/PKG-INFO0000644000214200020070000001205213573510273017041 0ustar lbradleySTSCI\science00000000000000Metadata-Version: 2.1 Name: photutils Version: 0.7.2 Summary: An Astropy package for source detection and photometry Home-page: https://github.com/astropy/photutils Author: Photutils Developers Author-email: photutils.team@gmail.com License: BSD 3-Clause License Description: ========= Photutils ========= |PyPI Version| |Conda Version| |Conda Downloads| |Astropy| |Travis Status| |CircleCI Status| |Coveralls Status| |Latest RTD Status| |LGTM Grade| Photutils is an `Astropy`_ package for detection and photometry of astronomical sources. Please see the `online documentation `_ for `installation instructions `_ and usage information. Citing Photutils ---------------- |Zenodo| If you use Photutils for a project that leads to a publication, whether directly or as a dependency of another package, please include the following acknowledgment:: This research made use of Photutils, an Astropy package for detection and photometry of astronomical sources (Bradley et al. 20XX). where (Bradley et al. 20XX) is a citation to the `Zenodo record `_ of the Photutils version that was used. We also encourage citations in the main text wherever appropriate. Please see the `CITATION `_ file for details and an example BibTeX entry. License ------- Photutils is licensed under a 3-clause BSD license. Please see the `LICENSE `_ file for details. .. |PyPI Version| image:: https://img.shields.io/pypi/v/photutils?label=pypi%20package :target: https://pypi.org/project/photutils/ :alt: PyPI Latest Release .. |Conda Version| image:: https://img.shields.io/conda/vn/astropy/photutils?label=conda%20package :target: https://anaconda.org/astropy/photutils :alt: Conda Latest Release .. |Conda Downloads| image:: https://img.shields.io/conda/dn/astropy/photutils?label=conda%20downloads :target: https://anaconda.org/astropy/photutils :alt: Conda Downloads .. |Astropy| image:: https://img.shields.io/badge/powered%20by-AstroPy-orange.svg?style=flat :target: https://www.astropy.org/ :alt: Powered by Astropy .. |Zenodo| image:: https://zenodo.org/badge/2640766.svg :target: https://zenodo.org/badge/latestdoi/2640766 :alt: Zenodo Latest DOI .. |Travis Status| image:: https://img.shields.io/travis/astropy/photutils/master?label=Travis%20CI :target: https://travis-ci.org/astropy/photutils :alt: Travis CI Status .. |Coveralls Status| image:: https://coveralls.io/repos/astropy/photutils/badge.svg?branch=master :target: https://coveralls.io/github/astropy/photutils :alt: Coveralls Status .. |CircleCI Status| image:: https://img.shields.io/circleci/build/github/astropy/photutils/master?label=CircleCI :target: https://circleci.com/gh/astropy/photutils :alt: CircleCI Status .. |Stable RTD Status| image:: https://readthedocs.org/projects/photutils/badge/?version=stable :target: https://photutils.readthedocs.io/en/stable/ :alt: Stable Documentation Status .. |Latest RTD Status| image:: https://readthedocs.org/projects/photutils/badge/?version=latest :target: https://photutils.readthedocs.io/en/latest/ :alt: Latest Documentation Status .. |LGTM Grade| image:: https://img.shields.io/lgtm/grade/python/g/astropy/photutils.svg?logo=lgtm&logoWidth=18 :target: https://lgtm.com/projects/g/astropy/photutils/context:python :alt: LGTM Grade .. _Astropy: https://www.astropy.org/ Keywords: astronomy,astrophysics,photometry,aperture,psf,source detection,background,segmentation,centroids,isophote,morphology Platform: UNKNOWN Classifier: Intended Audience :: Science/Research Classifier: License :: OSI Approved :: BSD License Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Cython Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Topic :: Scientific/Engineering :: Astronomy Provides: photutils Requires-Python: >=3.5 Description-Content-Type: text/x-rst Provides-Extra: all Provides-Extra: docs Provides-Extra: test photutils-0.7.2/README.rst0000644000214200020070000000632413563423715017443 0ustar lbradleySTSCI\science00000000000000========= Photutils ========= |PyPI Version| |Conda Version| |Conda Downloads| |Astropy| |Travis Status| |CircleCI Status| |Coveralls Status| |Latest RTD Status| |LGTM Grade| Photutils is an `Astropy`_ package for detection and photometry of astronomical sources. Please see the `online documentation `_ for `installation instructions `_ and usage information. Citing Photutils ---------------- |Zenodo| If you use Photutils for a project that leads to a publication, whether directly or as a dependency of another package, please include the following acknowledgment:: This research made use of Photutils, an Astropy package for detection and photometry of astronomical sources (Bradley et al. 20XX). where (Bradley et al. 20XX) is a citation to the `Zenodo record `_ of the Photutils version that was used. We also encourage citations in the main text wherever appropriate. Please see the `CITATION `_ file for details and an example BibTeX entry. License ------- Photutils is licensed under a 3-clause BSD license. Please see the `LICENSE `_ file for details. .. |PyPI Version| image:: https://img.shields.io/pypi/v/photutils?label=pypi%20package :target: https://pypi.org/project/photutils/ :alt: PyPI Latest Release .. |Conda Version| image:: https://img.shields.io/conda/vn/astropy/photutils?label=conda%20package :target: https://anaconda.org/astropy/photutils :alt: Conda Latest Release .. |Conda Downloads| image:: https://img.shields.io/conda/dn/astropy/photutils?label=conda%20downloads :target: https://anaconda.org/astropy/photutils :alt: Conda Downloads .. |Astropy| image:: https://img.shields.io/badge/powered%20by-AstroPy-orange.svg?style=flat :target: https://www.astropy.org/ :alt: Powered by Astropy .. |Zenodo| image:: https://zenodo.org/badge/2640766.svg :target: https://zenodo.org/badge/latestdoi/2640766 :alt: Zenodo Latest DOI .. |Travis Status| image:: https://img.shields.io/travis/astropy/photutils/master?label=Travis%20CI :target: https://travis-ci.org/astropy/photutils :alt: Travis CI Status .. |Coveralls Status| image:: https://coveralls.io/repos/astropy/photutils/badge.svg?branch=master :target: https://coveralls.io/github/astropy/photutils :alt: Coveralls Status .. |CircleCI Status| image:: https://img.shields.io/circleci/build/github/astropy/photutils/master?label=CircleCI :target: https://circleci.com/gh/astropy/photutils :alt: CircleCI Status .. |Stable RTD Status| image:: https://readthedocs.org/projects/photutils/badge/?version=stable :target: https://photutils.readthedocs.io/en/stable/ :alt: Stable Documentation Status .. |Latest RTD Status| image:: https://readthedocs.org/projects/photutils/badge/?version=latest :target: https://photutils.readthedocs.io/en/latest/ :alt: Latest Documentation Status .. |LGTM Grade| image:: https://img.shields.io/lgtm/grade/python/g/astropy/photutils.svg?logo=lgtm&logoWidth=18 :target: https://lgtm.com/projects/g/astropy/photutils/context:python :alt: LGTM Grade .. _Astropy: https://www.astropy.org/ photutils-0.7.2/ah_bootstrap.py0000644000214200020070000011063313572471322021007 0ustar lbradleySTSCI\science00000000000000""" 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 and by default the system-installed version of astropy-helpers will be used (however, ``ah_bootstrap.use_astropy_helpers`` may be called manually from within the setup.py script). This behavior can also be controlled using the ``--auto-use`` and ``--no-auto-use`` command-line flags. For clarity, an alias for ``--no-auto-use`` is ``--use-system-astropy-helpers``, and we recommend using the latter if needed. 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 io import locale import os import re import subprocess as sp import sys from distutils import log from distutils.debug import DEBUG from configparser import ConfigParser, RawConfigParser import pkg_resources from setuptools import Distribution from setuptools.package_index import PackageIndex # This is the minimum Python version required for astropy-helpers __minimum_python_version__ = (3, 5) # TODO: Maybe enable checking for a specific version of astropy_helpers? DIST_NAME = 'astropy-helpers' PACKAGE_NAME = 'astropy_helpers' UPPER_VERSION_EXCLUSIVE = None # 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) ] # Start off by parsing the setup.cfg file _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. """ SETUP_CFG = ConfigParser() if os.path.exists('setup.cfg'): try: SETUP_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)) # We used package_name in the package template for a while instead of name if SETUP_CFG.has_option('metadata', 'name'): parent_package = SETUP_CFG.get('metadata', 'name') elif SETUP_CFG.has_option('metadata', 'package_name'): parent_package = SETUP_CFG.get('metadata', 'package_name') else: parent_package = None if SETUP_CFG.has_option('options', 'python_requires'): python_requires = SETUP_CFG.get('options', 'python_requires') # The python_requires key has a syntax that can be parsed by SpecifierSet # in the packaging package. However, we don't want to have to depend on that # package, so instead we can use setuptools (which bundles packaging). We # have to add 'python' to parse it with Requirement. from pkg_resources import Requirement req = Requirement.parse('python' + python_requires) # We want the Python version as a string, which we can get from the platform module import platform # strip off trailing '+' incase this is a dev install of python python_version = platform.python_version().strip('+') # allow pre-releases to count as 'new enough' if not req.specifier.contains(python_version, True): if parent_package is None: message = "ERROR: Python {} is required by this package\n".format(req.specifier) else: message = "ERROR: Python {} is required by {}\n".format(req.specifier, parent_package) sys.stderr.write(message) sys.exit(1) if sys.version_info < __minimum_python_version__: if parent_package is None: message = "ERROR: Python {} or later is required by astropy-helpers\n".format( __minimum_python_version__) else: message = "ERROR: Python {} or later is required by astropy-helpers for {}\n".format( __minimum_python_version__, parent_package) sys.stderr.write(message) sys.exit(1) _str_types = (str, bytes) # 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): # Check that setuptools 30.3 or later is present from distutils.version import LooseVersion try: import setuptools assert LooseVersion(setuptools.__version__) >= LooseVersion('30.3') except (ImportError, AssertionError): sys.stderr.write("ERROR: setuptools 30.3 or later is required by astropy-helpers\n") sys.exit(1) # typing as a dependency for 1.6.1+ Sphinx causes issues when imported after # initializing submodule with ah_boostrap.py # See discussion and references in # https://github.com/astropy/astropy-helpers/issues/302 try: import typing # noqa except ImportError: pass # 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 # noqa 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... 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 not isinstance(path, str): 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 SETUP_CFG.has_section('ah_bootstrap'): return {} config = {} for option, type_ in CFG_OPTIONS: if not SETUP_CFG.has_option('ah_bootstrap', option): continue if type_ is bool: value = SETUP_CFG.getboolean('ah_bootstrap', option) else: value = SETUP_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') if '--auto-use' in argv: config['auto_use'] = True argv.remove('--auto-use') if '--no-auto-use' in argv: config['auto_use'] = False argv.remove('--no-auto-use') if '--use-system-astropy-helpers' in argv: config['auto_use'] = False argv.remove('--use-system-astropy-helpers') 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 None 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): # We use subprocess instead of run_setup from setuptools to # avoid segmentation faults - see the following for more details: # https://github.com/cython/cython/issues/2104 sp.check_output([sys.executable, 'setup.py', 'egg_info'], cwd=path) 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: if UPPER_VERSION_EXCLUSIVE is None: req = DIST_NAME else: req = '{0}<{1}'.format(DIST_NAME, UPPER_VERSION_EXCLUSIVE) attrs = {'setup_requires': [req]} # NOTE: we need to parse the config file (e.g. setup.cfg) to make sure # it honours the options set in the [easy_install] section, and we need # to explicitly fetch the requirement eggs as setup_requires does not # get honored in recent versions of setuptools: # https://github.com/pypa/setuptools/issues/1273 try: context = _verbose if DEBUG else _silence with context(): dist = _Distribution(attrs=attrs) try: dist.parse_config_files(ignore_option_errors=True) dist.fetch_build_eggs(req) except TypeError: # On older versions of setuptools, ignore_option_errors # doesn't exist, and the above two lines are not needed # so we can just continue pass # 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( r'^(?P[+-U ])(?P[0-9a-f]{40}) ' r'(?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 _AHBootstrapSystemExit( '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 _AHBootstrapSystemExit( '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, str): stdout = stdout.decode(stdio_encoding, 'replace') if not isinstance(stderr, str): 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 _verbose(): yield @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 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:]) 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() photutils-0.7.2/astropy_helpers/0000755000214200020070000000000013573510273021167 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/astropy_helpers/CHANGES.rst0000644000214200020070000005317313572251522023000 0ustar lbradleySTSCI\science00000000000000astropy-helpers Changelog ************************* 3.2.2 (2019-10-25) ------------------ - Correctly handle main package directory inside namespace package. [#486] 3.2.1 (2019-06-13) ------------------ - Reverting issuing deprecation warning for the ``build_sphinx`` command. [#482] - Make sure that all data files get included in tar file releases. [#485] 3.2 (2019-05-29) ---------------- - Make sure that ``[options.package_data]`` in setup.cfg is taken into account when collecting package data. [#453] - Simplified the code for the custom build_ext command. [#446] - Avoid importing the astropy package when trying to get the test command when testing astropy itself. [#450] - Avoid importing whole package when trying to get version information. Note that this has also introduced a small API change - ``cython_version`` and ``compiler`` can no longer be imported from the ``package.version`` module generated by astropy-helpers. Instead, you can import these from ``package.cython_version`` and ``package.compiler_version`` respectively. [#442] - Make it possible to call ``generate_version_py`` and ``register_commands`` without any arguments, which causes information to be read in from the ``setup.cfg`` file. [#440] - Simplified setup.py and moved most of the configuration to setup.cfg. [#445] - Add a new ``astropy_helpers.setup_helpers.setup`` function that does all the default boilerplate in typical ``setup.py`` files that use astropy-helpers. [#443] - Remove ``deprecated``, ``deprecated_attribute``, and ``minversion`` from ``astropy_helpers.utils``. [#447] - Updated minimum required version of setuptools to 30.3.0. [#440] - Remove functionality to adjust compilers if a broken compiler is detected. This is not useful anymore as only a single compiler was previously patched (now unlikely to be used) and this was only to fix a compilation issue in the core astropy package. [#421] - ``sphinx-astropy`` is now a required dependency to build the docs, the machinery to install it as eggs have been removed. [#474] 3.1.1 (2019-02-22) ------------------ - Moved documentation from README to Sphinx. [#444] - Fixed broken OpenMP detection when building with ``-coverage``. [#434] 3.1 (2018-12-04) ---------------- - Added extensive documentation about astropy-helpers to the README.rst file. [#416] - Fixed the compatibility of the build_docs command with Sphinx 1.8 and above. [#413] - Removing deprecated test_helpers.py file. [#369] - Removing ez_setup.py file and requiring setuptools 1.0 or later. [#384] - Remove all sphinx components from ``astropy-helpers``. These are now replaced by the ``sphinx-astropy`` package in conjunction with the ``astropy-theme-sphinx``, ``sphinx-automodapi``, and ``numpydoc`` packages. [#368] - openmp_helpers.py: Make add_openmp_flags_if_available() work for clang. The necessary include, library, and runtime paths now get added to the C test code used to determine if openmp works. Autogenerator utility added ``openmp_enabled.is_openmp_enabled()`` which can be called post build to determine state of OpenMP support. [#382] - Add version_info tuple to autogenerated version.py. Allows for simple version checking, i.e. version_info > (2,0,1). [#385] 3.0.2 (2018-06-01) ------------------ - Nothing changed. 3.0.1 (2018-02-22) ------------------ - Nothing changed. 3.0 (2018-02-09) ---------------- - Removing Python 2 support, including 2to3. Packages wishing to keep Python 2 support should NOT update to this version. [#340] - Removing deprecated _test_compat making astropy a hard dependency for packages wishing to use the astropy tests machinery. [#314] - Removing unused 'register' command since packages should be uploaded with twine and get registered automatically. [#332] 2.0.11 (2019-10-25) ------------------- - Fixed deprecation warning in sphinx theme. [#493] - Fixed an issue that caused pytest to crash if it tried to collect tests. [#488] 2.0.10 (2019-05-29) ------------------- - Removed ``tocdepthfix`` sphinx extension that worked around a big in Sphinx that has been long fixed. [#475] - Allow Python dev versions to pass the python version check. [#476] - Updated bundled version of sphinx-automodapi to v0.11. [#478] 2.0.9 (2019-02-22) ------------------ - Updated bundled version of sphinx-automodapi to v0.10. [#439] - Updated bundled sphinx extensions version to sphinx-astropy v1.1.1. [#454] - Include package name in error message for Python version in ``ah_bootstrap.py``. [#441] 2.0.8 (2018-12-04) ------------------ - Fixed compatibility with Sphinx 1.8+. [#428] - Fixed error that occurs when installing a package in an environment where ``numpy`` is not already installed. [#404] - Updated bundled version of sphinx-automodapi to v0.9. [#422] - Updated bundled version of numpydoc to v0.8.0. [#423] 2.0.7 (2018-06-01) ------------------ - Removing ez_setup.py file and requiring setuptools 1.0 or later. [#384] 2.0.6 (2018-02-24) ------------------ - Avoid deprecation warning due to ``exclude=`` keyword in ``setup.py``. [#379] 2.0.5 (2018-02-22) ------------------ - Fix segmentation faults that occurred when the astropy-helpers submodule was first initialized in packages that also contained Cython code. [#375] 2.0.4 (2018-02-09) ------------------ - Support dotted package names as namespace packages in generate_version_py. [#370] - Fix compatibility with setuptools 36.x and above. [#372] - Fix false negative in add_openmp_flags_if_available when measuring code coverage with gcc. [#374] 2.0.3 (2018-01-20) ------------------ - Make sure that astropy-helpers 3.x.x is not downloaded on Python 2. [#362, #363] - The bundled version of sphinx-automodapi has been updated to v0.7. [#365] - Add --auto-use and --no-auto-use command-line flags to match the ``auto_use`` configuration option, and add an alias ``--use-system-astropy-helpers`` for ``--no-auto-use``. [#366] 2.0.2 (2017-10-13) ------------------ - Added new helper function add_openmp_flags_if_available that can add OpenMP compilation flags to a C/Cython extension if needed. [#346] - Update numpydoc to v0.7. [#343] - The function ``get_git_devstr`` now returns ``'0'`` instead of ``None`` when no git repository is present. This allows generation of development version strings that are in a format that ``setuptools`` expects (e.g. "1.1.3.dev0" instead of "1.1.3.dev"). [#330] - It is now possible to override generated timestamps to make builds reproducible by setting the ``SOURCE_DATE_EPOCH`` environment variable [#341] - Mark Sphinx extensions as parallel-safe. [#344] - Switch to using mathjax instead of imgmath for local builds. [#342] - Deprecate ``exclude`` parameter of various functions in setup_helpers since it could not work as intended. Add new function ``add_exclude_packages`` to provide intended behavior. [#331] - Allow custom Sphinx doctest extension to recognize and process standard doctest directives ``testsetup`` and ``doctest``. [#335] 2.0.1 (2017-07-28) ------------------ - Fix compatibility with Sphinx <1.5. [#326] 2.0 (2017-07-06) ---------------- - Add support for package that lies in a subdirectory. [#249] - Removing ``compat.subprocess``. [#298] - Python 3.3 is no longer supported. [#300] - The 'automodapi' Sphinx extension (and associated dependencies) has now been moved to a standalone package which can be found at https://github.com/astropy/sphinx-automodapi - this is now bundled in astropy-helpers under astropy_helpers.extern.automodapi for convenience. Version shipped with astropy-helpers is v0.6. [#278, #303, #309, #323] - The ``numpydoc`` Sphinx extension has now been moved to ``astropy_helpers.extern``. [#278] - Fix ``build_docs`` error catching, so it doesn't hide Sphinx errors. [#292] - Fix compatibility with Sphinx 1.6. [#318] - Updating ez_setup.py to the last version before it's removal. [#321] 1.3.1 (2017-03-18) ------------------ - Fixed the missing button to hide output in documentation code blocks. [#287] - Fixed bug when ``build_docs`` when running with the clean (-l) option. [#289] - Add alternative location for various intersphinx inventories to fall back to. [#293] 1.3 (2016-12-16) ---------------- - ``build_sphinx`` has been deprecated in favor of the ``build_docs`` command. [#246] - Force the use of Cython's old ``build_ext`` command. A new ``build_ext`` command was added in Cython 0.25, but it does not work with astropy-helpers currently. [#261] 1.2 (2016-06-18) ---------------- - Added sphinx configuration value ``automodsumm_inherited_members``. If ``True`` this will include members that are inherited from a base class in the generated API docs. Defaults to ``False`` which matches the previous behavior. [#215] - Fixed ``build_sphinx`` to recognize builds that succeeded but have output *after* the "build succeeded." statement. This only applies when ``--warnings-returncode`` is given (which is primarily relevant for Travis documentation builds). [#223] - Fixed ``build_sphinx`` the sphinx extensions to not output a spurious warning for sphinx versions > 1.4. [#229] - Add Python version dependent local sphinx inventories that contain otherwise missing references. [#216] - ``astropy_helpers`` now require Sphinx 1.3 or later. [#226] 1.1.2 (2016-03-9) ----------------- - The CSS for the sphinx documentation was altered to prevent some text overflow problems. [#217] 1.1.1 (2015-12-23) ------------------ - Fixed crash in build with ``AttributeError: cython_create_listing`` with older versions of setuptools. [#209, #210] 1.1 (2015-12-10) ---------------- - The original ``AstropyTest`` class in ``astropy_helpers``, which implements the ``setup.py test`` command, is deprecated in favor of moving the implementation of that command closer to the actual Astropy test runner in ``astropy.tests``. Now a dummy ``test`` command is provided solely for informing users that they need ``astropy`` installed to run the tests (however, the previous, now deprecated implementation is still provided and continues to work with older versions of Astropy). See the related issue for more details. [#184] - Added a useful new utility function to ``astropy_helpers.utils`` called ``find_data_files``. This is similar to the ``find_packages`` function in setuptools in that it can be used to search a package for data files (matching a pattern) that can be passed to the ``package_data`` argument for ``setup()``. See the docstring to ``astropy_helpers.utils.find_data_files`` for more details. [#42] - The ``astropy_helpers`` module now sets the global ``_ASTROPY_SETUP_`` flag upon import (from within a ``setup.py``) script, so it's not necessary to have this in the ``setup.py`` script explicitly. If in doubt though, there's no harm in setting it twice. Putting it in ``astropy_helpers`` just ensures that any other imports that occur during build will have this flag set. [#191] - It is now possible to use Cython as a ``setup_requires`` build requirement, and still build Cython extensions even if Cython wasn't available at the beginning of the build processes (that is, is automatically downloaded via setuptools' processing of ``setup_requires``). [#185] - Moves the ``adjust_compiler`` check into the ``build_ext`` command itself, so it's only used when actually building extension modules. This also deprecates the stand-alone ``adjust_compiler`` function. [#76] - When running the ``build_sphinx`` / ``build_docs`` command with the ``-w`` option, the output from Sphinx is streamed as it runs instead of silently buffering until the doc build is complete. [#197] 1.0.7 (unreleased) ------------------ - Fix missing import in ``astropy_helpers/utils.py``. [#196] 1.0.6 (2015-12-04) ------------------ - Fixed bug where running ``./setup.py build_sphinx`` could return successfully even when the build was not successful (and should have returned a non-zero error code). [#199] 1.0.5 (2015-10-02) ------------------ - Fixed a regression in the ``./setup.py test`` command that was introduced in v1.0.4. 1.0.4 (2015-10-02) ------------------ - Fixed issue with the sphinx documentation css where the line numbers for code blocks were not aligned with the code. [#179, #180] - Fixed crash that could occur when trying to build Cython extension modules when Cython isn't installed. Normally this still results in a failed build, but was supposed to provide a useful error message rather than crash outright (this was a regression introduced in v1.0.3). [#181] - Fixed a crash that could occur on Python 3 when a working C compiler isn't found. [#182] - Quieted warnings about deprecated Numpy API in Cython extensions, when building Cython extensions against Numpy >= 1.7. [#183, #186] - Improved support for py.test >= 2.7--running the ``./setup.py test`` command now copies all doc pages into the temporary test directory as well, so that all test files have a "common root directory". [#189, #190] 1.0.3 (2015-07-22) ------------------ - Added workaround for sphinx-doc/sphinx#1843, a but in Sphinx which prevented descriptor classes with a custom metaclass from being documented correctly. [#158] - Added an alias for the ``./setup.py build_sphinx`` command as ``./setup.py build_docs`` which, to a new contributor, should hopefully be less cryptic. [#161] - The fonts in graphviz diagrams now match the font of the HTML content. [#169] - When the documentation is built on readthedocs.org, MathJax will be used for math rendering. When built elsewhere, the "pngmath" extension is still used for math rendering. [#170] - Fix crash when importing astropy_helpers when running with ``python -OO`` [#171] - The ``build`` and ``build_ext`` stages now correctly recognize the presence of C++ files in Cython extensions (previously only vanilla C worked). [#173] 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. 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, #137] - 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, #137] - Likewise, fixed a confusing warning message that could occur in the same circumstances as the above issue. [#121, #137] 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. photutils-0.7.2/astropy_helpers/LICENSE.rst0000644000214200020070000000272313536771066023017 0ustar lbradleySTSCI\science00000000000000Copyright (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. photutils-0.7.2/astropy_helpers/README.rst0000644000214200020070000000266313572251522022663 0ustar lbradleySTSCI\science00000000000000astropy-helpers =============== .. image:: https://travis-ci.org/astropy/astropy-helpers.svg :target: https://travis-ci.org/astropy/astropy-helpers .. image:: https://ci.appveyor.com/api/projects/status/rt9161t9mhx02xp7/branch/master?svg=true :target: https://ci.appveyor.com/project/Astropy/astropy-helpers .. image:: https://codecov.io/gh/astropy/astropy-helpers/branch/master/graph/badge.svg :target: https://codecov.io/gh/astropy/astropy-helpers The **astropy-helpers** package 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 is not a traditional package in the sense that it is not intended to be installed directly by users or developers. Instead, it is meant to be accessed when the ``setup.py`` command is run - see the "Using astropy-helpers in a package" section in the documentation for how to do this. For a real-life example of how to implement astropy-helpers in a project, see the ``setup.py`` and ``setup.cfg`` files of the `Affiliated package template `_. For more information, see the documentation at http://astropy-helpers.readthedocs.io photutils-0.7.2/astropy_helpers/ah_bootstrap.py0000644000214200020070000011063313572251522024230 0ustar lbradleySTSCI\science00000000000000""" 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 and by default the system-installed version of astropy-helpers will be used (however, ``ah_bootstrap.use_astropy_helpers`` may be called manually from within the setup.py script). This behavior can also be controlled using the ``--auto-use`` and ``--no-auto-use`` command-line flags. For clarity, an alias for ``--no-auto-use`` is ``--use-system-astropy-helpers``, and we recommend using the latter if needed. 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 io import locale import os import re import subprocess as sp import sys from distutils import log from distutils.debug import DEBUG from configparser import ConfigParser, RawConfigParser import pkg_resources from setuptools import Distribution from setuptools.package_index import PackageIndex # This is the minimum Python version required for astropy-helpers __minimum_python_version__ = (3, 5) # TODO: Maybe enable checking for a specific version of astropy_helpers? DIST_NAME = 'astropy-helpers' PACKAGE_NAME = 'astropy_helpers' UPPER_VERSION_EXCLUSIVE = None # 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) ] # Start off by parsing the setup.cfg file _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. """ SETUP_CFG = ConfigParser() if os.path.exists('setup.cfg'): try: SETUP_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)) # We used package_name in the package template for a while instead of name if SETUP_CFG.has_option('metadata', 'name'): parent_package = SETUP_CFG.get('metadata', 'name') elif SETUP_CFG.has_option('metadata', 'package_name'): parent_package = SETUP_CFG.get('metadata', 'package_name') else: parent_package = None if SETUP_CFG.has_option('options', 'python_requires'): python_requires = SETUP_CFG.get('options', 'python_requires') # The python_requires key has a syntax that can be parsed by SpecifierSet # in the packaging package. However, we don't want to have to depend on that # package, so instead we can use setuptools (which bundles packaging). We # have to add 'python' to parse it with Requirement. from pkg_resources import Requirement req = Requirement.parse('python' + python_requires) # We want the Python version as a string, which we can get from the platform module import platform # strip off trailing '+' incase this is a dev install of python python_version = platform.python_version().strip('+') # allow pre-releases to count as 'new enough' if not req.specifier.contains(python_version, True): if parent_package is None: message = "ERROR: Python {} is required by this package\n".format(req.specifier) else: message = "ERROR: Python {} is required by {}\n".format(req.specifier, parent_package) sys.stderr.write(message) sys.exit(1) if sys.version_info < __minimum_python_version__: if parent_package is None: message = "ERROR: Python {} or later is required by astropy-helpers\n".format( __minimum_python_version__) else: message = "ERROR: Python {} or later is required by astropy-helpers for {}\n".format( __minimum_python_version__, parent_package) sys.stderr.write(message) sys.exit(1) _str_types = (str, bytes) # 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): # Check that setuptools 30.3 or later is present from distutils.version import LooseVersion try: import setuptools assert LooseVersion(setuptools.__version__) >= LooseVersion('30.3') except (ImportError, AssertionError): sys.stderr.write("ERROR: setuptools 30.3 or later is required by astropy-helpers\n") sys.exit(1) # typing as a dependency for 1.6.1+ Sphinx causes issues when imported after # initializing submodule with ah_boostrap.py # See discussion and references in # https://github.com/astropy/astropy-helpers/issues/302 try: import typing # noqa except ImportError: pass # 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 # noqa 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... 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 not isinstance(path, str): 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 SETUP_CFG.has_section('ah_bootstrap'): return {} config = {} for option, type_ in CFG_OPTIONS: if not SETUP_CFG.has_option('ah_bootstrap', option): continue if type_ is bool: value = SETUP_CFG.getboolean('ah_bootstrap', option) else: value = SETUP_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') if '--auto-use' in argv: config['auto_use'] = True argv.remove('--auto-use') if '--no-auto-use' in argv: config['auto_use'] = False argv.remove('--no-auto-use') if '--use-system-astropy-helpers' in argv: config['auto_use'] = False argv.remove('--use-system-astropy-helpers') 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 None 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): # We use subprocess instead of run_setup from setuptools to # avoid segmentation faults - see the following for more details: # https://github.com/cython/cython/issues/2104 sp.check_output([sys.executable, 'setup.py', 'egg_info'], cwd=path) 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: if UPPER_VERSION_EXCLUSIVE is None: req = DIST_NAME else: req = '{0}<{1}'.format(DIST_NAME, UPPER_VERSION_EXCLUSIVE) attrs = {'setup_requires': [req]} # NOTE: we need to parse the config file (e.g. setup.cfg) to make sure # it honours the options set in the [easy_install] section, and we need # to explicitly fetch the requirement eggs as setup_requires does not # get honored in recent versions of setuptools: # https://github.com/pypa/setuptools/issues/1273 try: context = _verbose if DEBUG else _silence with context(): dist = _Distribution(attrs=attrs) try: dist.parse_config_files(ignore_option_errors=True) dist.fetch_build_eggs(req) except TypeError: # On older versions of setuptools, ignore_option_errors # doesn't exist, and the above two lines are not needed # so we can just continue pass # 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( r'^(?P[+-U ])(?P[0-9a-f]{40}) ' r'(?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 _AHBootstrapSystemExit( '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 _AHBootstrapSystemExit( '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, str): stdout = stdout.decode(stdio_encoding, 'replace') if not isinstance(stderr, str): 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 _verbose(): yield @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 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:]) 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() photutils-0.7.2/astropy_helpers/astropy_helpers/0000755000214200020070000000000013573510273024412 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/astropy_helpers/astropy_helpers/__init__.py0000644000214200020070000000331213536771066026532 0ustar lbradleySTSCI\science00000000000000try: 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 import os # Ensure that all module-level code in astropy or other packages know that # we're in setup mode: if ('__main__' in sys.modules and hasattr(sys.modules['__main__'], '__file__')): filename = os.path.basename(sys.modules['__main__'].__file__) if filename.rstrip('co') == 'setup.py': import builtins builtins._ASTROPY_SETUP_ = True del filename photutils-0.7.2/astropy_helpers/astropy_helpers/commands/0000755000214200020070000000000013573510273026213 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/astropy_helpers/astropy_helpers/commands/__init__.py0000644000214200020070000000000013536771066030322 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/astropy_helpers/astropy_helpers/commands/_dummy.py0000644000214200020070000000531213572251522030056 0ustar lbradleySTSCI\science00000000000000""" Provides a base class for a 'dummy' setup.py command that has no functionality (probably due to a missing requirement). This dummy command can raise an exception when it is run, explaining to the user what dependencies must be met to use this command. The reason this is at all tricky is that we want the command to be able to provide this message even when the user passes arguments to the command. If we don't know ahead of time what arguments the command can take, this is difficult, because distutils does not allow unknown arguments to be passed to a setup.py command. This hacks around that restriction to provide a useful error message even when a user passes arguments to the dummy implementation of a command. Use this like: try: from some_dependency import SetupCommand except ImportError: from ._dummy import _DummyCommand class SetupCommand(_DummyCommand): description = \ 'Implementation of SetupCommand from some_dependency; ' 'some_dependency must be installed to run this command' # This is the message that will be raised when a user tries to # run this command--define it as a class attribute. error_msg = \ "The 'setup_command' command requires the some_dependency " "package to be installed and importable." """ import sys from setuptools import Command from distutils.errors import DistutilsArgError from textwrap import dedent class _DummyCommandMeta(type): """ Causes an exception to be raised on accessing attributes of a command class so that if ``./setup.py command_name`` is run with additional command-line options we can provide a useful error message instead of the default that tells users the options are unrecognized. """ def __init__(cls, name, bases, members): if bases == (Command, object): # This is the _DummyCommand base class, presumably return if not hasattr(cls, 'description'): raise TypeError( "_DummyCommand subclass must have a 'description' " "attribute.") if not hasattr(cls, 'error_msg'): raise TypeError( "_DummyCommand subclass must have an 'error_msg' " "attribute.") def __getattribute__(cls, attr): if attr in ('description', 'error_msg') or attr.startswith('_'): # Allow cls.description to work so that `./setup.py # --help-commands` still works return super(_DummyCommandMeta, cls).__getattribute__(attr) raise DistutilsArgError(cls.error_msg) class _DummyCommand(Command, object, metaclass=_DummyCommandMeta): pass photutils-0.7.2/astropy_helpers/astropy_helpers/commands/build_ext.py0000644000214200020070000002074213572251522030547 0ustar lbradleySTSCI\science00000000000000import errno import os import shutil from distutils.core import Extension from distutils.ccompiler import get_default_compiler from distutils.command.build_ext import build_ext as DistutilsBuildExt from ..distutils_helpers import get_main_package_directory from ..utils import get_numpy_include_path, import_file __all__ = ['AstropyHelpersBuildExt'] def should_build_with_cython(previous_cython_version, is_release): """ Returns the previously used Cython version (or 'unknown' if not previously built) if Cython should be used to build extension modules from pyx files. """ # 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 have_cython = False try: from Cython import __version__ as cython_version # noqa have_cython = True except ImportError: pass if have_cython and (not is_release or previous_cython_version == 'unknown'): return cython_version else: return False class AstropyHelpersBuildExt(DistutilsBuildExt): """ A custom 'build_ext' command that allows for manipulating some of the C extension options at build time. """ _uses_cython = False _force_rebuild = False def __new__(cls, value, **kwargs): # NOTE: we need to wait until AstropyHelpersBuildExt is initialized to # import setuptools.command.build_ext because when that package is # imported, setuptools tries to import Cython - and if it's not found # it will affect the rest of the build process. This is an issue because # if we import that module at the top of this one, setup_requires won't # have been honored yet, so Cython may not yet be available - and if we # import build_ext too soon, it will think Cython is not available even # if it is then intalled when setup_requires is processed. To get around # this we dynamically create a new class that inherits from the # setuptools build_ext, and by this point setup_requires has been # processed. from setuptools.command.build_ext import build_ext as SetuptoolsBuildExt class FinalBuildExt(AstropyHelpersBuildExt, SetuptoolsBuildExt): pass new_type = type(cls.__name__, (FinalBuildExt,), dict(cls.__dict__)) obj = SetuptoolsBuildExt.__new__(new_type) obj.__init__(value) return obj def finalize_options(self): # First let's find the package folder, then we can check if the # version and cython_version are accessible self.package_dir = get_main_package_directory(self.distribution) version = import_file(os.path.join(self.package_dir, 'version.py'), name='version').version self.is_release = 'dev' not in version try: self.previous_cython_version = import_file(os.path.join(self.package_dir, 'cython_version.py'), name='cython_version').cython_version except (FileNotFoundError, ImportError): self.previous_cython_version = 'unknown' self._uses_cython = should_build_with_cython(self.previous_cython_version, self.is_release) # 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 that 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: build_py = self.get_finalized_command('build_py') package_dir = build_py.get_package_dir(self.package_dir) src_path = os.path.relpath( os.path.join(os.path.dirname(__file__), 'src')) shutil.copy(os.path.join(src_path, 'compiler.c'), os.path.join(package_dir, '_compiler.c')) ext = Extension(self.package_dir + '.compiler_version', [os.path.join(package_dir, '_compiler.c')]) extensions.insert(0, ext) super().finalize_options() # If we are using Cython, then make sure we re-build if the version # of Cython that is installed is different from the version last # used to generate the C files. if self._uses_cython and self._uses_cython != self.previous_cython_version: self._force_rebuild = True # 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 = None for extension in self.extensions: if 'numpy' in extension.include_dirs: if np_include is None: np_include = get_numpy_include_path() idx = extension.include_dirs.index('numpy') extension.include_dirs.insert(idx, np_include) extension.include_dirs.remove('numpy') self._check_cython_sources(extension) # Note that setuptools automatically uses Cython to discover and # build extensions if available, so we don't have to explicitly call # e.g. cythonize. super().run() # Update cython_version.py if building with Cython if self._uses_cython and self._uses_cython != self.previous_cython_version: build_py = self.get_finalized_command('build_py') package_dir = build_py.get_package_dir(self.package_dir) 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) def _check_cython_sources(self, extension): """ Where relevant, make sure that the .c files associated with .pyx modules are present (if building without Cython installed). """ # Determine the compiler we'll be using if self.compiler is None: compiler = get_default_compiler() else: compiler = self.compiler # Replace .pyx with C-equivalents, unless c files are missing for jdx, src in enumerate(extension.sources): base, ext = os.path.splitext(src) pyxfn = base + '.pyx' cfn = base + '.c' cppfn = base + '.cpp' 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 elif os.path.isfile(cppfn): extension.sources[jdx] = cppfn else: msg = ( 'Could not find C/C++ file {0}.(c/cpp) for Cython ' 'file {1} when building extension {2}. Cython ' 'must be installed to build from a git ' 'checkout.'.format(base, pyxfn, extension.name)) raise IOError(errno.ENOENT, msg, cfn) # Cython (at least as of 0.29.2) uses deprecated Numpy API features # the use of which produces a few warnings when compiling. # These additional flags should squelch those warnings. # TODO: Feel free to remove this if/when a Cython update # removes use of the deprecated Numpy API if compiler == 'unix': extension.extra_compile_args.extend([ '-Wp,-w', '-Wno-unused-function']) photutils-0.7.2/astropy_helpers/astropy_helpers/commands/build_sphinx.py0000644000214200020070000002173213572251522031260 0ustar lbradleySTSCI\science00000000000000 import os import pkgutil import re import shutil import subprocess import sys from distutils.version import LooseVersion from distutils import log from sphinx import __version__ as sphinx_version from sphinx.setup_command import BuildDoc as SphinxBuildDoc SPHINX_LT_16 = LooseVersion(sphinx_version) < LooseVersion('1.6') SPHINX_LT_17 = LooseVersion(sphinx_version) < LooseVersion('1.7') SUBPROCESS_TEMPLATE = """ import os import sys {build_main} os.chdir({srcdir!r}) {sys_path_inserts} for builder in {builders!r}: retcode = build_main(argv={argv!r} + ['-b', builder, '.', os.path.join({output_dir!r}, builder)]) if retcode != 0: sys.exit(retcode) """ def ensure_sphinx_astropy_installed(): """ Make sure that sphinx-astropy is available. This returns the available version of sphinx-astropy as well as any paths that should be added to sys.path for sphinx-astropy to be available. """ # We've split out the Sphinx part of astropy-helpers into sphinx-astropy # but we want it to be auto-installed seamlessly for anyone using # build_docs. We check if it's already installed, and if not, we install # it to a local .eggs directory and add the eggs to the path (these # have to each be added to the path, we can't add them by simply adding # .eggs to the path) sys_path_inserts = [] sphinx_astropy_version = None try: from sphinx_astropy import __version__ as sphinx_astropy_version # noqa except ImportError: raise ImportError("sphinx-astropy needs to be installed to build " "the documentation.") return sphinx_astropy_version, sys_path_inserts class AstropyBuildDocs(SphinxBuildDoc): """ A version of the ``build_docs`` 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. """ 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 self.traceback = False def finalize_options(self): # This has to happen before we call the parent class's finalize_options if self.build_dir is None: self.build_dir = 'docs/_build' SphinxBuildDoc.finalize_options(self) # Clear out previous sphinx builds, if requested if self.clean_docs: dirstorm = [os.path.join(self.source_dir, 'api'), os.path.join(self.source_dir, 'generated')] 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') def run(self): # TODO: Break this method up into a few more subroutines and # document them better import webbrowser from urllib.request 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 # 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') if ah_importer is None: ah_path = '.' else: ah_path = os.path.abspath(ah_importer.path) if SPHINX_LT_17: build_main = 'from sphinx import build_main' else: build_main = 'from sphinx.cmd.build import build_main' # We need to make sure sphinx-astropy is installed sphinx_astropy_version, extra_paths = ensure_sphinx_astropy_installed() sys_path_inserts = [build_cmd_path, ah_path] + extra_paths sys_path_inserts = os.linesep.join(['sys.path.insert(0, {0!r})'.format(path) for path in sys_path_inserts]) argv = [] if self.warnings_returncode: argv.append('-W') if self.no_intersphinx: # Note, if sphinx_astropy_version is None, this could indicate an # old version of setuptools, but sphinx-astropy is likely ok, so # we can proceed. if sphinx_astropy_version is None or LooseVersion(sphinx_astropy_version) >= LooseVersion('1.1'): argv.extend(['-D', 'disable_intersphinx=1']) else: log.warn('The -n option to disable intersphinx requires ' 'sphinx-astropy>=1.1. Ignoring.') # We now need to adjust the flags based on the parent class's options if self.fresh_env: argv.append('-E') if self.all_files: argv.append('-a') if getattr(self, 'pdb', False): argv.append('-P') if getattr(self, 'nitpicky', False): argv.append('-n') if self.traceback: argv.append('-T') # The default verbosity level is 1, so in that case we just don't add a flag if self.verbose == 0: argv.append('-q') elif self.verbose > 1: argv.append('-v') if SPHINX_LT_17: argv.insert(0, 'sphinx-build') if isinstance(self.builder, str): builders = [self.builder] else: builders = self.builder subproccode = SUBPROCESS_TEMPLATE.format(build_main=build_main, srcdir=self.source_dir, sys_path_inserts=sys_path_inserts, builders=builders, argv=argv, output_dir=os.path.abspath(self.build_dir)) log.debug('Starting subprocess of {0} with python code:\n{1}\n' '[CODE END])'.format(sys.executable, subproccode)) proc = subprocess.Popen([sys.executable], stdin=subprocess.PIPE) proc.communicate(subproccode.encode('utf-8')) if proc.returncode != 0: retcode = proc.returncode if retcode is None: 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.') # Here we explicitly check proc.returncode since we only want to output # this for cases where the return code really wasn't 0. if proc.returncode: 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) class AstropyBuildSphinx(AstropyBuildDocs): # pragma: no cover def run(self): AstropyBuildDocs.run(self) photutils-0.7.2/astropy_helpers/astropy_helpers/commands/src/0000755000214200020070000000000013573510273027002 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/astropy_helpers/astropy_helpers/commands/src/compiler.c0000644000214200020070000000524013572251522030757 0ustar lbradleySTSCI\science00000000000000#include /*************************************************************************** * Macros for determining the compiler version. * * These are borrowed from boost, and majorly abridged to include only * the compilers we care about. ***************************************************************************/ #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 }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "compiler_version", NULL, sizeof(struct module_state), NULL, NULL, NULL, NULL, NULL }; #define INITERROR return NULL PyMODINIT_FUNC PyInit_compiler_version(void) { PyObject* m; m = PyModule_Create(&moduledef); if (m == NULL) INITERROR; PyModule_AddStringConstant(m, "compiler", COMPILER); return m; } photutils-0.7.2/astropy_helpers/astropy_helpers/commands/test.py0000644000214200020070000000267213572251522027551 0ustar lbradleySTSCI\science00000000000000""" Different implementations of the ``./setup.py test`` command depending on what's locally available. If Astropy v1.1 or later is available it should be possible to import AstropyTest from ``astropy.tests.command``. Otherwise there is a skeleton implementation that allows users to at least discover the ``./setup.py test`` command and learn that they need Astropy to run it. """ import os from ..utils import import_file # Previously these except statements caught only ImportErrors, but there are # some other obscure exceptional conditions that can occur when importing # astropy.tests (at least on older versions) that can cause these imports to # fail try: # If we are testing astropy itself, we need to use import_file to avoid # actually importing astropy (just the file we need). command_file = os.path.join('astropy', 'tests', 'command.py') if os.path.exists(command_file): AstropyTest = import_file(command_file, 'astropy_tests_command').AstropyTest else: import astropy # noqa from astropy.tests.command import AstropyTest except Exception: # No astropy at all--provide the dummy implementation from ._dummy import _DummyCommand class AstropyTest(_DummyCommand): command_name = 'test' description = 'Run the tests for this package' error_msg = ( "The 'test' command requires the astropy package to be " "installed and importable.") photutils-0.7.2/astropy_helpers/astropy_helpers/conftest.py0000644000214200020070000000361213536771066026623 0ustar lbradleySTSCI\science00000000000000# This file contains settings for pytest that are specific to astropy-helpers. # Since we run many of the tests in sub-processes, we need to collect coverage # data inside each subprocess and then combine it into a single .coverage file. # To do this we set up a list which run_setup appends coverage objects to. # This is not intended to be used by packages other than astropy-helpers. import os import glob try: from coverage import CoverageData except ImportError: HAS_COVERAGE = False else: HAS_COVERAGE = True if HAS_COVERAGE: SUBPROCESS_COVERAGE = [] def pytest_configure(config): if HAS_COVERAGE: SUBPROCESS_COVERAGE.clear() def pytest_unconfigure(config): if HAS_COVERAGE: # We create an empty coverage data object combined_cdata = CoverageData() # Add all files from astropy_helpers to make sure we compute the total # coverage, not just the coverage of the files that have non-zero # coverage. lines = {} for filename in glob.glob(os.path.join('astropy_helpers', '**', '*.py'), recursive=True): lines[os.path.abspath(filename)] = [] for cdata in SUBPROCESS_COVERAGE: # For each CoverageData object, we go through all the files and # change the filename from one which might be a temporary path # to the local filename. We then only keep files that actually # exist. for filename in cdata.measured_files(): try: pos = filename.rindex('astropy_helpers') except ValueError: continue short_filename = filename[pos:] if os.path.exists(short_filename): lines[os.path.abspath(short_filename)].extend(cdata.lines(filename)) combined_cdata.add_lines(lines) combined_cdata.write_file('.coverage.subprocess') photutils-0.7.2/astropy_helpers/astropy_helpers/distutils_helpers.py0000644000214200020070000001767113572251522030544 0ustar lbradleySTSCI\science00000000000000""" 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, log 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_main_package_directory(distribution): """ Given a Distribution object, return the main package directory. """ return min(distribution.packages, key=len).replace('.', os.sep) 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)) photutils-0.7.2/astropy_helpers/astropy_helpers/git_helpers.py0000644000214200020070000001453713572251522027301 0ustar lbradleySTSCI\science00000000000000# 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 __all__ = ['get_git_devstr'] 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 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 == 128: # git returns 128 if the command is not run from within a git # repository tree. In this case, a warning is produced above but we # return the default dev version of '0'. return '0' elif 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() # This function is tested but it is only ever executed within a subprocess when # creating a fake package, so it doesn't get picked up by coverage metrics. def _get_repo_path(pathname, levels=None): # pragma: no cover """ 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 photutils-0.7.2/astropy_helpers/astropy_helpers/openmp_helpers.py0000644000214200020070000002216113572251522030004 0ustar lbradleySTSCI\science00000000000000# This module defines functions that can be used to check whether OpenMP is # available and if so what flags to use. To use this, import the # add_openmp_flags_if_available function in a setup_package.py file where you # are defining your extensions: # # from astropy_helpers.openmp_helpers import add_openmp_flags_if_available # # then call it with a single extension as the only argument: # # add_openmp_flags_if_available(extension) # # this will add the OpenMP flags if available. import os import sys import glob import time import datetime import tempfile import subprocess from distutils import log from distutils.ccompiler import new_compiler from distutils.sysconfig import customize_compiler, get_config_var from distutils.errors import CompileError, LinkError from .distutils_helpers import get_compiler_option __all__ = ['add_openmp_flags_if_available'] try: # Check if this has already been instantiated, only set the default once. _ASTROPY_DISABLE_SETUP_WITH_OPENMP_ except NameError: import builtins # It hasn't, so do so. builtins._ASTROPY_DISABLE_SETUP_WITH_OPENMP_ = False CCODE = """ #include #include int main(void) { #pragma omp parallel printf("nthreads=%d\\n", omp_get_num_threads()); return 0; } """ def _get_flag_value_from_var(flag, var, delim=' '): """ Extract flags from an environment variable. Parameters ---------- flag : str The flag to extract, for example '-I' or '-L' var : str The environment variable to extract the flag from, e.g. CFLAGS or LDFLAGS. delim : str, optional The delimiter separating flags inside the environment variable Examples -------- Let's assume the LDFLAGS is set to '-L/usr/local/include -customflag'. This function will then return the following: >>> _get_flag_value_from_var('-L', 'LDFLAGS') '/usr/local/include' Notes ----- Environment variables are first checked in ``os.environ[var]``, then in ``distutils.sysconfig.get_config_var(var)``. This function is not supported on Windows. """ if sys.platform.startswith('win'): return None # Simple input validation if not var or not flag: return None flag_length = len(flag) if not flag_length: return None # Look for var in os.eviron then in get_config_var if var in os.environ: flags = os.environ[var] else: try: flags = get_config_var(var) except KeyError: return None # Extract flag from {var:value} if flags: for item in flags.split(delim): if item.startswith(flag): return item[flag_length:] def get_openmp_flags(): """ Utility for returning compiler and linker flags possibly needed for OpenMP support. Returns ------- result : `{'compiler_flags':, 'linker_flags':}` Notes ----- The flags returned are not tested for validity, use `check_openmp_support(openmp_flags=get_openmp_flags())` to do so. """ compile_flags = [] link_flags = [] if get_compiler_option() == 'msvc': compile_flags.append('-openmp') else: include_path = _get_flag_value_from_var('-I', 'CFLAGS') if include_path: compile_flags.append('-I' + include_path) lib_path = _get_flag_value_from_var('-L', 'LDFLAGS') if lib_path: link_flags.append('-L' + lib_path) link_flags.append('-Wl,-rpath,' + lib_path) compile_flags.append('-fopenmp') link_flags.append('-fopenmp') return {'compiler_flags': compile_flags, 'linker_flags': link_flags} def check_openmp_support(openmp_flags=None): """ Check whether OpenMP test code can be compiled and run. Parameters ---------- openmp_flags : dict, optional This should be a dictionary with keys ``compiler_flags`` and ``linker_flags`` giving the compiliation and linking flags respectively. These are passed as `extra_postargs` to `compile()` and `link_executable()` respectively. If this is not set, the flags will be automatically determined using environment variables. Returns ------- result : bool `True` if the test passed, `False` otherwise. """ ccompiler = new_compiler() customize_compiler(ccompiler) if not openmp_flags: # customize_compiler() extracts info from os.environ. If certain keys # exist it uses these plus those from sysconfig.get_config_vars(). # If the key is missing in os.environ it is not extracted from # sysconfig.get_config_var(). E.g. 'LDFLAGS' get left out, preventing # clang from finding libomp.dylib because -L is not passed to # linker. Call get_openmp_flags() to get flags missed by # customize_compiler(). openmp_flags = get_openmp_flags() compile_flags = openmp_flags.get('compiler_flags') link_flags = openmp_flags.get('linker_flags') tmp_dir = tempfile.mkdtemp() start_dir = os.path.abspath('.') try: os.chdir(tmp_dir) # Write test program with open('test_openmp.c', 'w') as f: f.write(CCODE) os.mkdir('objects') # Compile, test program ccompiler.compile(['test_openmp.c'], output_dir='objects', extra_postargs=compile_flags) # Link test program objects = glob.glob(os.path.join('objects', '*' + ccompiler.obj_extension)) ccompiler.link_executable(objects, 'test_openmp', extra_postargs=link_flags) # Run test program output = subprocess.check_output('./test_openmp') output = output.decode(sys.stdout.encoding or 'utf-8').splitlines() if 'nthreads=' in output[0]: nthreads = int(output[0].strip().split('=')[1]) if len(output) == nthreads: is_openmp_supported = True else: log.warn("Unexpected number of lines from output of test OpenMP " "program (output was {0})".format(output)) is_openmp_supported = False else: log.warn("Unexpected output from test OpenMP " "program (output was {0})".format(output)) is_openmp_supported = False except (CompileError, LinkError, subprocess.CalledProcessError): is_openmp_supported = False finally: os.chdir(start_dir) return is_openmp_supported def is_openmp_supported(): """ Determine whether the build compiler has OpenMP support. """ log_threshold = log.set_threshold(log.FATAL) ret = check_openmp_support() log.set_threshold(log_threshold) return ret def add_openmp_flags_if_available(extension): """ Add OpenMP compilation flags, if supported (if not a warning will be printed to the console and no flags will be added.) Returns `True` if the flags were added, `False` otherwise. """ if _ASTROPY_DISABLE_SETUP_WITH_OPENMP_: log.info("OpenMP support has been explicitly disabled.") return False openmp_flags = get_openmp_flags() using_openmp = check_openmp_support(openmp_flags=openmp_flags) if using_openmp: compile_flags = openmp_flags.get('compiler_flags') link_flags = openmp_flags.get('linker_flags') log.info("Compiling Cython/C/C++ extension with OpenMP support") extension.extra_compile_args.extend(compile_flags) extension.extra_link_args.extend(link_flags) else: log.warn("Cannot compile Cython/C/C++ extension with OpenMP, reverting " "to non-parallel code") return using_openmp _IS_OPENMP_ENABLED_SRC = """ # Autogenerated by {packagetitle}'s setup.py on {timestamp!s} def is_openmp_enabled(): \"\"\" Determine whether this package was built with OpenMP support. \"\"\" return {return_bool} """[1:] def generate_openmp_enabled_py(packagename, srcdir='.', disable_openmp=None): """ Generate ``package.openmp_enabled.is_openmp_enabled``, which can then be used to determine, post build, whether the package was built with or without OpenMP support. """ if packagename.lower() == 'astropy': packagetitle = 'Astropy' else: packagetitle = packagename epoch = int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) timestamp = datetime.datetime.utcfromtimestamp(epoch) if disable_openmp is not None: import builtins builtins._ASTROPY_DISABLE_SETUP_WITH_OPENMP_ = disable_openmp if _ASTROPY_DISABLE_SETUP_WITH_OPENMP_: log.info("OpenMP support has been explicitly disabled.") openmp_support = False if _ASTROPY_DISABLE_SETUP_WITH_OPENMP_ else is_openmp_supported() src = _IS_OPENMP_ENABLED_SRC.format(packagetitle=packagetitle, timestamp=timestamp, return_bool=openmp_support) package_srcdir = os.path.join(srcdir, *packagename.split('.')) is_openmp_enabled_py = os.path.join(package_srcdir, 'openmp_enabled.py') with open(is_openmp_enabled_py, 'w') as f: f.write(src) photutils-0.7.2/astropy_helpers/astropy_helpers/setup_helpers.py0000644000214200020070000007055213572251522027655 0ustar lbradleySTSCI\science00000000000000# 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. """ import collections import os import re import subprocess import sys import traceback import warnings from configparser import ConfigParser import builtins from distutils import log 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 setup as setuptools_setup from setuptools.config import read_configuration from setuptools import find_packages as _find_packages from .distutils_helpers import (add_command_option, get_compiler_option, get_dummy_distribution, get_distutils_build_option, get_distutils_build_or_install_option) from .version_helpers import get_pkg_version_module, generate_version_py from .utils import (walk_skip_hidden, import_file, extends_doc, resolve_name, AstropyDeprecationWarning) from .commands.build_ext import AstropyHelpersBuildExt from .commands.test import AstropyTest # These imports are not used in this module, but are included for backwards # compat with older versions of this module from .utils import get_numpy_include_path, write_if_different # noqa __all__ = ['register_commands', 'get_package_info'] _module_state = {'registered_commands': None, 'have_sphinx': False, 'package_cache': None, 'exclude_packages': set(), 'excludes_too_late': False} try: import sphinx # noqa _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 def setup(**kwargs): """ A wrapper around setuptools' setup() function that automatically sets up custom commands, generates a version file, and customizes the setup process via the ``setup_package.py`` files. """ # DEPRECATED: store the package name in a built-in variable so it's easy # to get from other parts of the setup infrastructure. We should phase this # out in packages that use it - the cookiecutter template should now be # able to put the right package name where needed. conf = read_configuration('setup.cfg') builtins._ASTROPY_PACKAGE_NAME_ = conf['metadata']['name'] # Create a dictionary with setup command overrides. Note that this gets # information about the package (name and version) from the setup.cfg file. cmdclass = register_commands() # Freeze build information in version.py. Note that this gets information # about the package (name and version) from the setup.cfg file. version = generate_version_py() # 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() package_info['cmdclass'] = cmdclass package_info['version'] = version # Override using any specified keyword arguments package_info.update(kwargs) setuptools_setup(**package_info) def adjust_compiler(package): warnings.warn( 'The adjust_compiler function in setup.py is ' 'deprecated and can be removed from your setup.py.', AstropyDeprecationWarning) 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 add_exclude_packages(excludes): if _module_state['excludes_too_late']: raise RuntimeError( "add_package_excludes must be called before all other setup helper " "functions in order to properly handle excluded packages") _module_state['exclude_packages'].update(set(excludes)) def register_commands(package=None, version=None, release=None, srcdir='.'): """ This function generates a dictionary containing customized commands that can then be passed to the ``cmdclass`` argument in ``setup()``. """ if package is not None: warnings.warn('The package argument to generate_version_py has ' 'been deprecated and will be removed in future. Specify ' 'the package name in setup.cfg instead', AstropyDeprecationWarning) if version is not None: warnings.warn('The version argument to generate_version_py has ' 'been deprecated and will be removed in future. Specify ' 'the version number in setup.cfg instead', AstropyDeprecationWarning) if release is not None: warnings.warn('The release argument to generate_version_py has ' 'been deprecated and will be removed in future. We now ' 'use the presence of the "dev" string in the version to ' 'determine whether this is a release', AstropyDeprecationWarning) # We use ConfigParser instead of read_configuration here because the latter # only reads in keys recognized by setuptools, but we need to access # package_name below. conf = ConfigParser() conf.read('setup.cfg') if conf.has_option('metadata', 'name'): package = conf.get('metadata', 'name') elif conf.has_option('metadata', 'package_name'): # The package-template used package_name instead of name for a while warnings.warn('Specifying the package name using the "package_name" ' 'option in setup.cfg is deprecated - use the "name" ' 'option instead.', AstropyDeprecationWarning) package = conf.get('metadata', 'package_name') elif package is not None: # deprecated pass else: sys.stderr.write('ERROR: Could not read package name from setup.cfg\n') sys.exit(1) if _module_state['registered_commands'] is not None: return _module_state['registered_commands'] if _module_state['have_sphinx']: try: from .commands.build_sphinx import (AstropyBuildSphinx, AstropyBuildDocs) except ImportError: AstropyBuildSphinx = AstropyBuildDocs = FakeBuildSphinx else: AstropyBuildSphinx = AstropyBuildDocs = 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, 'build_ext': AstropyHelpersBuildExt, 'build_sphinx': AstropyBuildSphinx, 'build_docs': AstropyBuildDocs } # 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 = 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) 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, exc)) 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: 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 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()``, and ``get_external_libraries()``. 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. """ ext_modules = [] packages = [] package_dir = {} # Read in existing package data, and add to it below setup_cfg = os.path.join(srcdir, 'setup.cfg') if os.path.exists(setup_cfg): conf = read_configuration(setup_cfg) if 'options' in conf and 'package_data' in conf['options']: package_data = conf['options']['package_data'] else: package_data = {} else: package_data = {} if exclude: warnings.warn( "Use of the exclude parameter is no longer supported since it does " "not work as expected. Use add_exclude_packages instead. Note that " "it must be called prior to any other calls from setup helpers.", AstropyDeprecationWarning) # Use the find_packages tool to locate all packages and modules packages = find_packages(srcdir, exclude=exclude) # Update package_dir if the package lies in a subdirectory if srcdir != '.': package_dir[''] = srcdir # 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) 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, } 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', '.cpp')): 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 exclude: warnings.warn( "Use of the exclude parameter is no longer supported since it does " "not work as expected. Use add_exclude_packages instead. Note that " "it must be called prior to any other calls from setup helpers.", AstropyDeprecationWarning) # Calling add_exclude_packages after this point will have no effect _module_state['excludes_too_late'] = True if not invalidate_cache and _module_state['package_cache'] is not None: return _module_state['package_cache'] packages = _find_packages( where=where, exclude=list(_module_state['exclude_packages'])) _module_state['package_cache'] = packages return packages 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 and its dependencies must be installed " "for build_docs.") except: log.error('error: Sphinx and its dependencies must be installed ' 'for build_docs.') sys.exit(1) photutils-0.7.2/astropy_helpers/astropy_helpers/sphinx/0000755000214200020070000000000013573510273025723 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/astropy_helpers/astropy_helpers/sphinx/__init__.py0000644000214200020070000000000013536771066030032 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/astropy_helpers/astropy_helpers/sphinx/conf.py0000644000214200020070000000023413536771066027231 0ustar lbradleySTSCI\science00000000000000import warnings from sphinx_astropy.conf import * warnings.warn("Note that astropy_helpers.sphinx.conf is deprecated - use sphinx_astropy.conf instead") photutils-0.7.2/astropy_helpers/astropy_helpers/utils.py0000644000214200020070000002056713572251522026134 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import contextlib import imp import os import sys import glob from importlib import machinery as import_machinery # 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. import builtins if hasattr(builtins, '__NUMPY_SETUP__'): del builtins.__NUMPY_SETUP__ import imp import numpy imp.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 = '' 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 = 'r' if name is None: basename = os.path.splitext(filename)[0] name = '_'.join(os.path.relpath(basename).split(os.sep)[1:]) if not os.path.exists(filename): raise ImportError('Could not import file {0}'.format(filename)) 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 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. Examples -------- >>> def foo(): ... '''Hello.''' ... >>> @extends_doc(foo) ... def bar(): ... '''Goodbye.''' ... >>> print(bar.__doc__) Hello. Goodbye. """ def decorator(func): if not (extended_func.__doc__ is None or func.__doc__ is None): func.__doc__ = '\n\n'.join([extended_func.__doc__.rstrip('\n'), func.__doc__.lstrip('\n')]) return func return decorator def find_data_files(package, pattern): """ Include files matching ``pattern`` inside ``package``. Parameters ---------- package : str The package inside which to look for data files pattern : str Pattern (glob-style) to match for the data files (e.g. ``*.dat``). This supports the``**``recursive syntax. For example, ``**/*.fits`` matches all files ending with ``.fits`` recursively. Only one instance of ``**`` can be included in the pattern. """ return glob.glob(os.path.join(package, pattern), recursive=True) photutils-0.7.2/astropy_helpers/astropy_helpers/version.py0000644000214200020070000000063613536771356026470 0ustar lbradleySTSCI\science00000000000000# Autogenerated by Astropy-affiliated package astropy_helpers's setup.py on 2019-09-13 19:50:06 UTC from __future__ import unicode_literals import datetime version = "3.2.1" githash = "ba3734222a40f4c2864c375c6639f32cd9df06cd" major = 3 minor = 2 bugfix = 1 version_info = (major, minor, bugfix) release = True timestamp = datetime.datetime(2019, 9, 13, 19, 50, 6) debug = False astropy_helpers_version = "" photutils-0.7.2/astropy_helpers/astropy_helpers/version_helpers.py0000644000214200020070000003062613572251522030200 0ustar lbradleySTSCI\science00000000000000# 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__ """ import datetime import os import pkgutil import sys import time import warnings from distutils import log from configparser import ConfigParser import pkg_resources from . import git_helpers from .distutils_helpers import is_distutils_display_option from .git_helpers import get_git_devstr from .utils import AstropyDeprecationWarning, import_file __all__ = ['generate_version_py'] 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} UTC import datetime {header} major = {major} minor = {minor} bugfix = {bugfix} version_info = (major, minor, bugfix) release = {rel} timestamp = {timestamp!r} debug = {debug} astropy_helpers_version = "{ahver}" """[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): try: from astropy_helpers import __version__ as ahver except ImportError: ahver = "unknown" epoch = int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) timestamp = datetime.datetime.utcfromtimestamp(epoch) 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, ahver=ahver, 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:]) verstr = version 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=None, version=None, release=None, debug=None, uses_git=None, srcdir='.'): """ Generate a version.py file in the package with version information, and update developer version strings. This function should normally be called without any arguments. In this case the package name and version is read in from the ``setup.cfg`` file (from the ``name`` or ``package_name`` entry and the ``version`` entry in the ``[metadata]`` section). If the version is a developer version (of the form ``3.2.dev``), the version string will automatically be expanded to include a sequential number as a suffix (e.g. ``3.2.dev13312``), and the updated version string will be returned by this function. Based on this updated version string, a ``version.py`` file will be generated inside the package, containing the version string as well as more detailed information (for example the major, minor, and bugfix version numbers, a ``release`` flag indicating whether the current version is a stable or developer version, and so on. """ if packagename is not None: warnings.warn('The packagename argument to generate_version_py has ' 'been deprecated and will be removed in future. Specify ' 'the package name in setup.cfg instead', AstropyDeprecationWarning) if version is not None: warnings.warn('The version argument to generate_version_py has ' 'been deprecated and will be removed in future. Specify ' 'the version number in setup.cfg instead', AstropyDeprecationWarning) if release is not None: warnings.warn('The release argument to generate_version_py has ' 'been deprecated and will be removed in future. We now ' 'use the presence of the "dev" string in the version to ' 'determine whether this is a release', AstropyDeprecationWarning) # We use ConfigParser instead of read_configuration here because the latter # only reads in keys recognized by setuptools, but we need to access # package_name below. conf = ConfigParser() conf.read('setup.cfg') if conf.has_option('metadata', 'name'): packagename = conf.get('metadata', 'name') elif conf.has_option('metadata', 'package_name'): # The package-template used package_name instead of name for a while warnings.warn('Specifying the package name using the "package_name" ' 'option in setup.cfg is deprecated - use the "name" ' 'option instead.', AstropyDeprecationWarning) packagename = conf.get('metadata', 'package_name') elif packagename is not None: # deprecated pass else: sys.stderr.write('ERROR: Could not read package name from setup.cfg\n') sys.exit(1) if conf.has_option('metadata', 'version'): version = conf.get('metadata', 'version') add_git_devstr = True elif version is not None: # deprecated add_git_devstr = False else: sys.stderr.write('ERROR: Could not read package version from setup.cfg\n') sys.exit(1) if release is None: release = 'dev' not in version if not release and add_git_devstr: version += get_git_devstr(False) if uses_git is None: uses_git = not release # In some cases, packages have a - but this is a _ in the module. Since we # are only interested in the module here, we replace - by _ packagename = packagename.replace('-', '_') 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) package_srcdir = os.path.join(srcdir, *packagename.split('.')) version_py = os.path.join(package_srcdir, '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)) return version 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. """ version = import_file(os.path.join(packagename, 'version.py'), name='version') if fromlist: return tuple(getattr(version, member) for member in fromlist) else: return version photutils-0.7.2/astropy_helpers/astropy_helpers.egg-info/0000755000214200020070000000000013573510273026104 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/astropy_helpers/astropy_helpers.egg-info/PKG-INFO0000644000214200020070000000503113536771356027212 0ustar lbradleySTSCI\science00000000000000Metadata-Version: 2.1 Name: astropy-helpers Version: 3.2.1 Summary: Utilities for building and installing packages in the Astropy ecosystem Home-page: https://github.com/astropy/astropy-helpers Author: The Astropy Developers Author-email: astropy.team@gmail.com License: BSD 3-Clause License Description: astropy-helpers =============== .. image:: https://travis-ci.org/astropy/astropy-helpers.svg :target: https://travis-ci.org/astropy/astropy-helpers .. image:: https://ci.appveyor.com/api/projects/status/rt9161t9mhx02xp7/branch/master?svg=true :target: https://ci.appveyor.com/project/Astropy/astropy-helpers .. image:: https://codecov.io/gh/astropy/astropy-helpers/branch/master/graph/badge.svg :target: https://codecov.io/gh/astropy/astropy-helpers The **astropy-helpers** package 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 is not a traditional package in the sense that it is not intended to be installed directly by users or developers. Instead, it is meant to be accessed when the ``setup.py`` command is run - see the "Using astropy-helpers in a package" section in the documentation for how to do this. For a real-life example of how to implement astropy-helpers in a project, see the ``setup.py`` and ``setup.cfg`` files of the `Affiliated package template `_. For more information, see the documentation at http://astropy-helpers.readthedocs.io Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Framework :: Setuptools Plugin 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 Provides: astropy_helpers Requires-Python: >=3.5 Provides-Extra: docs photutils-0.7.2/astropy_helpers/astropy_helpers.egg-info/SOURCES.txt0000644000214200020070000000162313536771356030004 0ustar lbradleySTSCI\science00000000000000CHANGES.rst LICENSE.rst MANIFEST.in README.rst ah_bootstrap.py setup.cfg setup.py astropy_helpers/__init__.py astropy_helpers/conftest.py astropy_helpers/distutils_helpers.py astropy_helpers/git_helpers.py astropy_helpers/openmp_helpers.py astropy_helpers/setup_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/requires.txt astropy_helpers.egg-info/top_level.txt astropy_helpers/commands/__init__.py astropy_helpers/commands/_dummy.py astropy_helpers/commands/build_ext.py astropy_helpers/commands/build_sphinx.py astropy_helpers/commands/test.py astropy_helpers/commands/src/compiler.c astropy_helpers/sphinx/__init__.py astropy_helpers/sphinx/conf.py licenses/LICENSE_ASTROSCRAPPY.rstphotutils-0.7.2/astropy_helpers/astropy_helpers.egg-info/dependency_links.txt0000644000214200020070000000000113536771356032164 0ustar lbradleySTSCI\science00000000000000 photutils-0.7.2/astropy_helpers/astropy_helpers.egg-info/not-zip-safe0000644000214200020070000000000113536771356030344 0ustar lbradleySTSCI\science00000000000000 photutils-0.7.2/astropy_helpers/astropy_helpers.egg-info/requires.txt0000644000214200020070000000002713536771356030515 0ustar lbradleySTSCI\science00000000000000 [docs] sphinx-astropy photutils-0.7.2/astropy_helpers/astropy_helpers.egg-info/top_level.txt0000644000214200020070000000002013536771356030640 0ustar lbradleySTSCI\science00000000000000astropy_helpers photutils-0.7.2/astropy_helpers/licenses/0000755000214200020070000000000013573510273022774 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/astropy_helpers/licenses/LICENSE_ASTROSCRAPPY.rst0000644000214200020070000000315413536771066026635 0ustar lbradleySTSCI\science00000000000000# The OpenMP helpers include code heavily adapted from astroscrappy, released # under the following license: # # Copyright (c) 2015, Curtis McCully # 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. photutils-0.7.2/docs/0000755000214200020070000000000013573510273016674 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/docs/Makefile0000644000214200020070000001074513504422775020346 0ustar lbradleySTSCI\science00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest #This is needed with git because git doesn't create a dir if it's empty $(shell [ -d "_static" ] || mkdir -p _static) 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 " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" clean: -rm -rf $(BUILDDIR) -rm -rf api -rm -rf generated 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/Astropy.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Astropy.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/Astropy" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Astropy" @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." 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." 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: @echo "Run 'python setup.py test' in the root directory to run doctests " \ @echo "in the documentation." photutils-0.7.2/docs/_static/0000755000214200020070000000000013573510273020322 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/docs/_static/favicon.ico0000644000214200020070000003535612444404542022454 0ustar lbradleySTSCI\science00000000000000 h6  ¨ž00 ¨%F(  ¨o1‘xm²t,G®p(¦m.ª¤l,£¢j*z h)1’\ ¨o/©q4.­p*É¡k1ÿšj9þ¥k*ÿ¢j)ÿŸh)ÿf'üšc&»—a%4‘[¦o35«o*ô–lFÿtfýŽjNübOüœe)üœd&ü™c'þ—a$ÿ–_!ÿ”]s“Y¡m6©o-Ìžg,ÿ‘ymúͪƒÿÑ­‚ÿ¢ƒiÿƒ]>ÿbÿ–^ÿ•^üŽ\%û[$ÿY{ŽX¤l-Z¥l*ÿ—e0üŽp\ÿÓ±‡ÿؽžÿ±“vÿ€]Aÿ’a+ÿƒePÿZÿuWDþmTJüˆUÿ‰TI¡i* žg*ÿ¢g#üƒ`Eÿ‹iNÿ¡}Zÿ‹{{ÿŠVÿ†eJÿƒ€”ÿ}R)ÿ†hQÿ“sTüqP6ÿˆQÍOGWf(½že$ÿ^.ýŽ^-ÿ…[4ÿ}Y<ÿŠVÿ“ZÿŠXÿƒT#ÿ…TÿsT?ÿ¡xGÿs\Qý~KÿNTœd%µ’]%ÿ„uuýngÿ“Zÿ‘[ÿ‚fUÿ\;ÿŠTÿ‰Uÿ‚QÿpUEÿÁ£ÿƒoeürEÿ~K¢Ÿd‰U/ÿº´³ü’‚|ÿˆQÿ}U2ÿ™’šÿnhÿƒOÿƒOÿ‚JÿlQ@ÿƯ•ÿxgýhAÿ{H ÌŸ`>ƒX/þ„|„þ|_Jÿ‹Uÿ‰TÿzT3ÿ}R&ÿ‚MÿzW6ÿr\OÿfI6ÿždÿ}[:ýeC&ÿwDÓY»yQ-ÿ†Sü‰TÿzO#ÿzN!ÿ€NÿxGÿvwÿykkÿg?ÿz`Mÿš|]ýgI0ÿq=¸‰U7ŠUüˆSþpM0ýzbSÿ„l[ÿjQDÿgI5ÿnEÿsB ÿuC ÿaG8ÿubZücA#ÿq<q…Q€Qg„PÿkK2ü`Gû¼—iÿ¦‚ÿdJÿeG2ÿtC ÿqA ÿj?ûU:+ÿh< Ün;ƒP~La}JùeG2ÿpZOþ–~jü˜yYü\HDük?üm> ýk<ÿk;üh:E€NyH)zF ¯h?úeF-ÿdJ8ÿd=ÿl=þh;ÿf9Óc9 :h:M}G H*s<sn9 m<ªg:‘f9Nb5g:øÿàÀ€€€€Ààðøÿ( @ ªq0©o.«q1©p/&¨o.>§n-G¦m-A¥l,-¤l,›d&›d&ªp/ªp/¬s1ªq0S©p/©¨o/Þ¨n.ø§n-ÿ¦m-ÿ¥l,ÿ¤k+û¢j+ç¡i*¾ h)|Ÿg(*—a$—`$ªp/©o/«q0Yªp0ߨo1ÿªo,þªn)ÿ§m+ÿ£l.ÿ¤k,þ£j+þ¢i*ÿ¡i*ÿ h)ÿŸg(ÿf(ýœe'½›d&A˜a$”^"ªp/ªq0 ªp/©©p0ÿªo,þ¯q&ü l6û—j?ýŸk3þªl!ÿ£j*ÿ i+ÿ h)ÿŸg(þžf(üœe'û›d&þ›d&ÿ™c%ÿ˜b$°—`$“]!ªp/ªp/ ªp/Ĩo0ÿªn*ú£m2ým]fÿncrÿragÿj_pÿsclÿ h)ÿ¡g&ÿf)ÿe'ÿœe'ÿ›d&ÿšc%ÿ™b%ü˜a$ü—`$ÿ•_#ð”^"S[ ¥m-©o/±¨o.ÿ¨n,ù¥n1ÿaZsÿ¬œ–ÿ³|=ÿ«o)ÿ«r0ÿ}[Dÿe_xÿŸf%ÿœe'ÿ›d&ÿšc&ÿ™b%ÿ˜a$ÿ—`$ÿ–`#ÿ”_"û“^"ý’]!ÿ‘\ yŽY¨n.¨n.q§n.ÿ¤m/ú®n$ÿq]_ÿ™„{ÿÙ²€ÿ¹’gÿÊ­Žÿʯ’ÿËœ`ÿvZMÿv`]ÿ¢dÿ˜b'ÿ˜b$ÿ—a$ÿ–`#ÿ•_"ÿ”^"ÿ’]"ÿ“\ý’\û[ ÿZŒX§n-¦m-ë¥l,ÿ¤k,þ¤m.ÿfXdÿÅ¡xÿ¸bÿѶ—ÿɪˆÿ¶_ÿË®ÿ¬„ZÿbUcÿœc"ÿ—a%ÿ•`%ÿ–`"ÿ“^#ÿ“]!ÿ’]!ÿ“\ÿ[$ÿ‹Z$þ‘YûŒXÿŒWjŠW¥l,u¥l,ÿ£k+û£j)ÿžj2ÿiW\ÿÄžsÿ»•lÿÕ¾£ÿøôðÿØÃ«ÿ®‚Qÿ¾yÿcQYÿ˜b&ÿ•_$ÿ™_ÿ’_'ÿ–^ÿ’\ÿ‘[ÿ‹Z%ÿ\WpÿXWvÿ€W1þŽWþ‰Vü‰U<‰U¤k+Ç£j+ÿ¡i*ý h+ÿ¤h$ÿg]oÿk7ÿÓ¸šÿÀžyÿÈ©‡ÿ»™sÿ»“eÿ¯”{ÿ_Q]ÿ›aÿ—_ÿvXDÿ`d‰ÿgYbÿŽYÿ•ZÿmXSÿoRBÿ…OÿTTvÿŠUüˆTÿ‡SуQ‡T¢j+$¢j*ô¡i*ÿ h)þg*ÿ¤gÿbOÿhZfÿ©jÿ¾–fÿ³‰XÿµˆRÿìÕ·ÿc\rÿ[>ÿ˜^ÿ‘^%ÿab„ÿãÆ ÿ‚˜ÿuVAÿ™[ÿ`QXÿŒmQÿ³ƒFÿgPHÿhSOÿSû„Rÿ„Qx„R¡i*L h)ÿŸg)þžf(ÿe'ÿ™d*ÿŸdÿr__ÿe[lÿV-ÿ‡V#ÿ™}hÿjj‡ÿoWNÿ™^ÿ\#ÿ”\ÿgW[ÿ|}™ÿdazÿ„V%ÿ‘Wÿ`Uaÿ¦‹rÿ°Š_ÿ£YÿQI`ÿ†SþƒPÿ‚Pç€NŸg)gžf(ÿf'üœe'ÿšd'ÿ¡dÿžcÿbÿ„_@ÿk]fÿh\jÿfV[ÿ€W2ÿ—^ÿ[!ÿZÿŽZÿŽXÿwU;ÿ…U#ÿ‹VÿŒUÿ_TbÿW-ÿzAÿ¶_ÿcWcÿpN3ÿ†Oû€NÿMif'qœe'ÿ›d&üšc&ÿc ÿv\Rÿv\Qÿ˜`!ÿ™_ÿ›_ÿ—^ÿ˜^ÿ•]ÿ”]ÿZÿYÿŒXÿ‹WÿXÿŠVÿ†TÿŒTÿ^R^ÿyO&ÿ£zKÿ¯‰[ÿ…naÿYHKÿ‡O ü}Mÿ}L¾›d&i›d&ÿ˜b'üŸcÿo[ZÿrciÿlamÿxZIÿ˜^ÿ\$ÿ\"ÿ‘[ÿŽ[#ÿ}]Eÿ‹Y#ÿŽXÿŠWÿ‰VÿˆUÿ‡Tÿ…Sÿ‹Sÿ^MRÿ_Dÿ·–nÿ¸›{ÿŸ^ÿPGYÿNþ|Kÿ{JòzI"™c%O˜b%ÿšb!þŽ_/ÿ`ZrÿDz“ÿ¢ƒÿcRXÿ˜^ÿŽ["ÿZÿ‰X$ÿUOgÿwoÿTOiÿ‚T%ÿŠUÿ‡Tÿ†Sÿ…RÿƒQÿ‰QÿaKEÿzcVÿ­†WÿÒ²ÿ°cÿSJYÿvK ÿ|JýyIÿyHU˜a$*–`%øœaÿuWFþswÿçãÚÿ¨œ—ÿbPUÿ•\ÿŒY"ÿ–\ÿnZXÿ€ÿûá·ÿ—†€ÿgW\ÿWÿ„Rÿ„RÿƒQÿPÿ†OÿjK6ÿkZ\ÿ¹–kÿáÙÒÿµ‘eÿ]NRÿjI/ÿ}H üwGÿwG˜b%“_%Õ›`ÿkSMý’…ƒÿëèàÿ”‡„ÿePOÿ•[ÿŠX!ÿXÿvW@ÿfbyÿÄ«ÿjezÿnSCÿŠSÿƒQÿ‚PÿPÿ„PÿƒNÿsL&ÿ[Q`ÿ¶”jÿÌ»ªÿª„VÿgRJÿ_G=ÿ|FüuFÿuEš‘]%•™^ÿiRNû~zÿÒ¾žÿgatÿxU8ÿXÿŠVÿ‰UÿŒUÿiOCÿ[XsÿeNFÿ‡Qÿ‚PÿOÿƒOÿƒM ÿlF%ÿxKÿLÿOI^ÿ¥†dÿ±•vÿ²‘hÿfH2ÿYHJÿ{EüsDÿsC£Ž\$?”\ÿ|X:ýb[pÿze\ÿ[SfÿWÿ‰Vÿ‰Uÿ‡Tÿ…SÿŠSÿŒVÿ‰Qÿ‚Pÿ€OÿƒOÿwJÿRQoÿqtŽÿQSvÿJ ÿQCLÿwkÿvKÿ‡Y"ÿfC$ÿVJSÿxCüqCÿqB ™‡TY Å‘YÿpUHübRYÿŠWÿŠUÿˆTÿ†Sÿ†RÿˆRÿ‡Rÿ„Qÿ€OÿNÿ€Nÿ|KÿUUsÿÀ»¹ÿµ°®ÿNMiÿHÿaD2ÿg^lÿ¦Rÿm9ÿxdÿRHTÿvAüoAÿo@ {ŒXXM‹WÿWüWÿˆUÿ‡Tÿ…Sÿ‰RÿƒRÿtO.ÿmG%ÿvKÿƒOÿ„M ÿLÿoH%ÿV]…ÿ€“ÿMNpÿrEÿzG ÿuHÿFB]ÿž|Yÿ©‰bÿ´«¨ÿJ=FÿvBþm@ ÿn? L‰U‰V«‡Uÿ†Tû†Sÿ„RÿˆQÿqQ9ÿPMjÿ_S]ÿyv‹ÿd`vÿMEXÿ]LMÿxLÿ‚IÿiG+ÿ_@+ÿyF ÿxF ÿsEÿzDÿTFLÿ]F>ÿ§|Eÿ‰xqÿN?Eþs?ÿk> çl= ‡TˆU†Så…Rÿ„Rý„QÿPÿQNjÿ€Rÿ³Œ]ÿ¡vAÿ™l8ÿ‡_3ÿiRGÿFC_ÿ^JFÿ€Gÿ{H ÿuFÿtDÿsDÿsC ÿpBÿCFlÿj6ÿQ>CÿXB:üp=ÿj=  …R…RC„Qü‚Pþ‚Oý€OÿQLdÿ‡Vÿª‹iÿ€S!ÿ¾¨ÿµ™yÿ°Œ_ÿžvGÿRFPÿRIWÿxEÿsDÿrC ÿqB ÿpAÿr@ÿcA'ÿDGlÿIE^ÿj= ýj<ÿi< 8„Q‚OYNÿNý„M ügNBÿOGZÿšj0ÿ±’mÿıÿßÔÈÿ½§ÿ›ySÿ¦zBÿNBMÿ\G@ÿvBÿpBÿpA ÿo@ ÿm? ÿo=ÿh>ÿi< új;ÿh;›i;‚OMT~Lø|KÿJû_LJþIE^ÿ|W1ÿ uAÿ¦Uÿ¤‚[ÿl:ÿ«ŒgÿxIÿJE\ÿsAÿn@ ÿn? ÿm> ÿl= ÿj= ÿj;úi;ÿg:Ôh9f9€N|K4{JÜyIÿ~GükJ.ûJF`þNBNÿlQ?ÿ£Œvÿ»¦‘ÿŽkDÿRACÿQEQÿr?ÿl? ÿl> ÿk= ÿj<ýi;úg:ÿf9àf9#g9~LzI xH“vGüyEÿyEþfG.ûUHQüVRiþXWpþE?TÿRDIÿn? ÿl> þk= þj<üi;ûh:ýg9ÿf9Æe8f9|KyHvE,sD§rC÷uBÿvAþq>ÿl<ÿq@ÿr=þk= ÿj< ÿi;ÿh:þg:ÿf9ìe8sc6m@ f9yIyHpAqB oAlm@³m@ ám? øk= ÿi= ÿi<ÿh;úg:ãf9´f8ce7f9f9vEuEk= k= 'j<=i;Fh;@g:+e9 h:f9e8ÿÿÿÿÿ€?ÿþÿøÿðÿààÀÀ€€€€€€€€€€ÀÀààðøüþÿÿ€ÿàÿüÿÿÿÿÿ(0` $«q0ªp/ªo.¶v.Ÿg)Ÿg)žf(«q0ªq0©o.ªp/ªp/U©o/ˆ¨o.­¨n.ŧn-Ѧm-Ô¦m-Ï¥l,Á¤k,¨£k+ƒ¢j+S¢i* ¨q6œe'œd'ªq0ªq/«r1ªq0gªp/Īp/ù©o/ÿ¨o.ÿ§n.ÿ§m-ÿ¦m-ÿ¥l,ÿ¤l,ÿ¤k,ÿ£k+ÿ¢j+ÿ¢i*ÿ¡i*ú h)ÍŸg)~Ÿg('™c%™b%ªp/¬r1«q0tªq0éªp/ÿ©o/þ¨o.ÿ§n.ü§m.û¦m-ü¥l,ü¥l,ý¤k,ý£k+ý¢j+ü¢i*û¡i*û h)ü h)ÿŸg)ÿžg(ÿžf(ûe'·œd'B—a$–`#ªp/«q09ªq0תp/ÿ©o/þ¨o/ü¥n1ü§n-þ©n*ÿ§m+ÿ£l.ÿ£k.ÿ£k+ÿ£j+ÿ¢j*ÿ¡i*ÿ¡i*ÿ h)ÿŸg)ÿžg(þžf(üf'ûœe'þœd'ÿ›d&ÿšc&¿™b%4—`#”_"©p/ªq0mªp/ý©p/ÿ©o.û¦n1ý¬o'ÿ±p ÿ¥m.ÿœk8ÿŸk2ÿ«l"ÿ¬lÿ¡j,ÿ¡i+ÿ¡i*ÿ h)ÿŸg)ÿŸg(ÿžf(ÿf(ÿœe'ÿœd'ÿ›d&ÿšc&üšc%ü™b%ÿ˜b$þ—a$’–`# “^!©o/ªp/ƒªp/ÿ©o/û¨o.ü¥n0ÿ±o ÿ“kHÿ\^…ÿT^“ÿW_ÿU^’ÿU^‘ÿxcaÿ¨j ÿ¢i(ÿŸh*ÿŸg(ÿžf(ÿf(ÿe'ÿœe'ÿ›d&ÿ›d&ÿšc%ÿ™b%ÿ˜b%ÿ˜a$ü—a$ü–`#ÿ•_#Ú”_"4’]!©o.©p/x©o/ÿ¨o.ú¨n.þ¥m0ÿ°n ÿsepÿHV•ÿŠo`ÿ¢m2ÿ¦l(ÿ¢h'ÿ’hAÿ^`†ÿP\“ÿ g(ÿ g&ÿf(ÿe'ÿœe'ÿ›d&ÿ›d&ÿšc&ÿ™b%ÿ™b%ÿ˜a$ÿ—a$ÿ–`#ÿ–`#þ•_#û”^"ÿ”^"ú“]!_\ Z©o.©o/P©o.ÿ¨n.ü§n-þ¤m0ÿ¯n ÿxfkÿLS†ÿÍ iÿëÓ³ÿ›^ÿœc"ÿ£m1ÿž`ÿ©b ÿubeÿM[•ÿ£gÿ›e(ÿœd'ÿ›d&ÿšc&ÿ™c%ÿ™b%ÿ˜b$ÿ—a$ÿ—`$ÿ–`#ÿ•_#ÿ”_"ÿ”^"ÿ“^!ü’]!ü’\ ÿ‘\ |Z¨o.¨o.¨o.æ§n.ÿ¦m-ý¥m-ÿ¨m)ÿ›k:ÿGX™ÿ³~?ÿîâÕÿ¢n3ÿ·Œ[ÿæ×ÆÿäÔÃÿãÓÁÿ²Œcÿ§_ÿ`_ÿm^hÿ¥eÿ™c(ÿšc%ÿ™b%ÿ˜b%ÿ˜a$ÿ—`$ÿ–`#ÿ•_#ÿ•_"ÿ”^"ÿ“^!ÿ“]!ÿ’\!ÿ‘\ þ[ û[ÿZƒX§n.§n.›§m-ÿ¦m-û¥l,ÿ£k/ÿ®mÿndvÿmVUÿݹŒÿÁ {ÿ¨u:ÿíâÖÿ­}Gÿœc#ÿ¯Nÿìâ×ÿº‘bÿŽZ$ÿO\”ÿc!ÿ˜b&ÿ˜b%ÿ˜a$ÿ—a$ÿ–`#ÿ–`#ÿ•_"ÿ”^"ÿ“^!ÿ“]!ÿ’] ÿ\"ÿ‘\ÿ[ÿŽZ!þZûŽYÿYwŒW§m-§m-0¦m-û¦m-ÿ¥l,ÿ¤k,ÿ¢k.ÿªk!ÿ\`Šÿ‰]4ÿáɬÿ¬|GÿͰÿá{ÿÁžvÿìáÔÿª{Fÿ¥s;ÿäØÊÿŸcÿTZ‡ÿŒa7ÿ›b ÿ—a$ÿ–`#ÿ–`#ÿ”_$ÿ“_$ÿ”^"ÿ“]!ÿ’]!ÿ’\ ÿ\!ÿ”[ÿZ ÿŽZ ÿ”ZÿŒY þXüŒXÿ‹WXŠV¦m-¦m-™¥l,ÿ¤k,û£k+ÿ£j+ÿ¡j,ÿ§j#ÿZ_ŒÿŒ[)ÿÜħÿ³ˆYÿº“gÿþþýÿÿÿÿÿ÷óîÿãÔÃÿ”ZÿÛʸÿ²~AÿTTxÿ†`@ÿ›aÿ•`$ÿ•_#ÿ“^#ÿ›aÿ›`ÿ‘\!ÿ‘\!ÿ‘\ ÿ[!ÿ“[ÿ‚Y4ÿDU”ÿBT–ÿsWFÿ“Xÿ‰Wþ‹WÿŠVò‰U,‰U¥l,¤l,ê¤k+ÿ£k+þ¢j+ÿ¢i*ÿŸi,ÿ¨iÿ[_ˆÿ†[6ÿ½‘]ÿäÖÅÿ–\ÿȪˆÿÈ©‡ÿ´‹]ÿáоÿ‘VÿÛÉ·ÿ°~EÿNRÿ‹`5ÿ˜`ÿ”_#ÿ”^"ÿ˜^ÿz_Qÿy_Rÿ–]ÿ‘\ÿ[ ÿŽZ!ÿ–ZÿHUŒÿuWDÿŒYÿ;SŸÿzV7ÿVÿˆVü‰UÿˆTƃO¤k+P£k+ÿ¢j+ü¢i*ÿ¡i*ÿ h)ÿžg+ÿ©hÿl_lÿmamÿ¢^ ÿ˱–ÿçÙÊÿº”iÿ¼˜oÿëàÓÿ®ƒSÿše+ÿçÖÁÿa6ÿKWŽÿš`ÿ“^$ÿ’]"ÿ˜^ÿNNsÿWa”ÿXb“ÿKMtÿ”[ÿY ÿYÿƒX.ÿLU‡ÿVÿŒQ ÿ}W6ÿ@S•ÿŽUÿ‡Uÿ‡Tû‡Sÿ†Sy†S¢j+¢j*ÿ¡i*û¡i*ÿ h)ÿŸg)ÿžg)ÿŸf&ÿ˜e.ÿEYŸÿ›e)ÿ˜[ÿ¯‡[ÿзœÿзœÿ£r<ÿ¡q<ÿøøûÿÌ`ÿMNuÿo]^ÿœ_ÿ‘]%ÿ™_ÿ}_KÿWb”ÿà™ÿâÄ›ÿYb’ÿx]Mÿ”[ÿ’YÿrWHÿSQpÿ—\ÿ—oFÿŽNÿRTwÿcSWÿT ÿ…Sþ…Rÿ…Rñ„Q"…R¡i*Á¡i*ÿ h)üŸg)ÿŸg(ÿžf(ÿf'ÿ›e)ÿ¤eÿx_WÿGY›ÿe%ÿž[ ÿ’UÿTÿ”[ÿѱ‰ÿêÍ¥ÿe_uÿNV†ÿ›_ÿ‘]#ÿ‘\"ÿ—^ÿ~^GÿQ^•ÿع‘ÿÚ»“ÿR^“ÿy[Hÿ‘Zÿ’XÿgUVÿ\SfÿË©|ÿÉ´ÿ³eÿvJÿCT‘ÿŠSÿ„Rÿ„QûƒQÿƒP˜ƒQ¡i*  h)àŸh)ÿŸg(ýžf(ÿf(ÿe'ÿœe'ÿ›d&ÿ˜c)ÿ£dÿu^YÿCXŸÿp^`ÿb7ÿ”`'ÿšn@ÿ…k[ÿCIyÿRW€ÿ˜^ÿ’\ ÿ‘\ ÿ[ ÿŽZ!ÿ•[ÿRNjÿP^–ÿQ^–ÿOLlÿ‘XÿˆV ÿ“Xÿ\LSÿwuÿÁšjÿu;ÿư™ÿ£q3ÿEJuÿnRBÿ‰Qÿ‚Pþ‚Pÿ‚OõO%OŸh)Ÿg)ñžf(ÿžf(þe'ÿœe'ÿ›d&ÿšd'ÿ˜c(ÿ˜b(ÿ–b(ÿ bÿŽ`1ÿ^ZuÿNXŒÿNXŒÿKU‰ÿRVÿz]Mÿ›^ÿ‘\ ÿ\ ÿ[ÿZÿŽZÿŽZÿ“Yÿ|\Cÿ{[Dÿ‘WÿŠWÿˆVÿ‘V ÿ_R]ÿbWeÿ’XÿNÿ•j;ÿȨ€ÿbH<ÿPRvÿ‹Pÿ€OÿOû€Nÿ€N†€Nžf((žf(øf'ÿœe'þœd'ÿ›d&ÿ™c'ÿ›c#ÿ¢cÿ¡cÿ™a!ÿ”`'ÿ˜`ÿŸ`ÿ™_ÿ’^#ÿ•^ÿœ^ÿ˜]ÿ\#ÿ\!ÿZÿZÿŽYÿYÿXÿŠWÿ‘Yÿ‘YÿˆUÿ‰Vÿ‡UÿT ÿbSZÿ[Q`ÿR ÿ€Nÿw?ÿ¿¤†ÿd7ÿ?KÿPÿNÿ€NýMÿ~MÜ|Kf'*œe'úœd'ÿ›d&þšc&ÿ™c'ÿœc ÿ”a,ÿY[€ÿWZ‚ÿ‘_+ÿ˜`ÿ”_$ÿ’^%ÿ’^#ÿ“] ÿ‘\!ÿ\#ÿ["ÿŽ["ÿŽ\$ÿY ÿŽYÿXÿŒXÿ‹Wÿ‹Wÿ‰Vÿ‰VÿˆUÿˆTÿ†TÿS ÿfRPÿXSkÿ‡Jÿ°’qÿ¶˜wÿ¡}Wÿ²ˆUÿCDhÿmP>ÿ„M ÿ~Mÿ~Lý}Lÿ}KCœd'$›d&ö›d&ÿšc%þ™b%ÿ™b#ÿ—a&ÿCWœÿrZRÿnZZÿKWÿš_ÿ’^#ÿ“]!ÿ’]!ÿ‘\ ÿ‘\ÿ[!ÿ‘Zÿ™]ÿœd ÿ”XÿŒXÿ‹Wÿ‹WÿŠVÿ‰Vÿ‰UÿˆTÿ‡Tÿ†Sÿ…Sÿ‹RÿlRCÿNNoÿ“\ÿ¼¤‰ÿ²“qÿ²•vÿ¹”dÿYHJÿWPdÿ†Lÿ|Lÿ}Kû|Kÿ{J‰›d&šc&ë™b%ÿ™b%þ–a'ÿ¡bÿXY|ÿl^fÿ¼™iÿ²†NÿPT€ÿ€\@ÿ—]ÿ‘\!ÿ‘\ ÿ[ÿZ!ÿ’Zÿ†Y+ÿWY~ÿT`”ÿdV^ÿXÿŠWÿŠVÿ‰UÿˆUÿ‡Tÿ‡Sÿ†Sÿ…Rÿ„RÿˆQÿtQ3ÿEJuÿšh-ÿ°’rÿ–l>ÿϽ©ÿ¸—qÿuS7ÿFMzÿƒK ÿ{Kÿ{Jü{JÿzIÛd&™b%טb$ÿ—a$ý™a!ÿŽ`1ÿGS‹ÿª†[ÿÇÎÙÿÁ­‘ÿaYnÿnYVÿ™]ÿ[!ÿ[ÿŽZÿYÿˆX%ÿ8KŽÿm[[ÿ¤ŒxÿACjÿUSqÿU ÿ†TÿˆTÿ‡Tÿ†Sÿ…Rÿ…Rÿ„QÿƒQÿ„Pÿ}P"ÿ@J|ÿ•i5ÿ¯mÿ» ‚ÿêâÙÿ´—wÿ‹`0ÿ>I|ÿzKÿ{JÿzIþyIÿyHéxG˜a$µ—a$ÿ•`%ü`ÿq[Xÿ`YpÿÄ­ŽÿÝâëÿȵšÿc[oÿkXXÿ˜\ÿŽZ!ÿŽZÿŒZ!ÿ™]ÿa[pÿmeuÿѨpÿìâ×ÿ¯BÿK]›ÿ‚Y2ÿ‹Vÿ†Tÿ†Sÿ…Rÿ„QÿƒQÿƒPÿ‚PÿOÿƒOÿAK}ÿ‡a:ÿ³“nÿů–ÿòíçÿ±•vÿšl4ÿ@EpÿmK0ÿ}I ÿxHÿxHÿwGþwG4–`#ƒ–`#ÿ“_%ûž`ÿ^WnÿuddÿÑŲÿêïöÿÄ®ÿYWsÿrXMÿ•[ÿY ÿYÿ‹Y"ÿš`ÿ_]{ÿ…xzÿâÈ¥ÿõöùÿÈ¡oÿXd—ÿ]@ÿŒWÿ…Sÿ…Rÿ„QÿƒPÿ‚Pÿ‚OÿOÿNÿ‡MÿIMtÿqVCÿ¸–mÿí•ÿïèâÿ¨Šiÿ£v>ÿGB[ÿ_LIÿ~GÿwGÿwGývFÿvFQ•_#G”_"ÿ’^$ýœ_ÿVUvÿ€kaÿÒÉ»ÿÝáæÿ²•rÿLQ~ÿY4ÿYÿŒXÿŒXÿŠWÿUÿxT6ÿ4Fˆÿ‰_5ÿáwÿU>;ÿCPˆÿ‰Q ÿƒQÿ„QÿƒQÿ‚Pÿ‚OÿOÿNÿ~Nÿ}Mÿ†LÿXN]ÿXJSÿ¹”eÿ»£‰ÿÒÁ®ÿ{Uÿ¥zEÿP@DÿSL^ÿFÿuFÿvFýuEÿtEd”^"“^!è‘]$ÿ›^þVTtÿ~g]ÿÈÁ¶ÿÉÆÃÿŽpVÿFQ†ÿ“Zÿ‹Xÿ‹Wÿ‹WÿŠVÿˆVÿUÿmTJÿEW˜ÿPbŸÿHRƒÿ‚S!ÿ†RÿƒQÿƒPÿ‚PÿOÿNÿ„NÿˆNÿ‡MÿLÿK ÿjN<ÿBCfÿ²‹[ÿ®’tÿ«kÿ¦‡dÿœq<ÿZ@3ÿJKmÿ}EÿtEÿtEütDÿsDm‘\ ’\ ¢\#ÿš\üaWgÿhX^ÿ¸™nÿ´ZÿPS|ÿhVXÿ“Xÿ‰WÿŠVÿ‰Vÿ‰UÿˆTÿ†TÿŒSÿŠVÿ‰^1ÿŠP ÿ…Qÿ‚Pÿ‚Pÿ‚OÿOÿNÿˆNÿpL+ÿKGbÿBJxÿjL7ÿ€J ÿyLÿ8BuÿzQÿ¤ƒ^ÿ«Œjÿȵ ÿ|I ÿdE,ÿCJvÿ{DÿsDÿsDürC ÿrC i[\ D[ ÿ’Zý„Y0ÿ>S›ÿ„X-ÿ]TgÿHSˆÿ‘Wÿ‰VÿŠVÿ‰UÿˆUÿ‡Tÿ‡Sÿ†Sÿ„Rÿ…Rÿ‡TÿPÿ‚Pÿ‚OÿOÿ€NÿNÿ†M ÿQI]ÿ?U›ÿ‚™ÿ|qtÿ9J‰ÿ{JÿIÿCIsÿpVEÿ¿¢ÿr@ ÿzKÿwCÿrQ3ÿ?IzÿxDÿrCÿrC ýqB ÿqB YZÇY ÿ“YýsWGÿDT‘ÿVUsÿŒWÿ‹Vÿ‰UÿˆUÿˆTÿ‡Sÿ†Sÿ…Rÿ„RÿƒQÿƒQÿƒQÿ‚OÿOÿ€Nÿ€Nÿ~Mÿ†MÿRK`ÿQf¦ÿϱÿìܾÿƒ|ƒÿ@GuÿI ÿ~Hÿ[LQÿE?UÿÀžsÿŠd:ÿn<ÿzIÿ‡jOÿ=I~ÿvBÿqBÿqB ÿpA ÿo@ ?YYVXÿ‹XüXÿ‘Wÿ’WÿŠVÿˆUÿˆTÿ‡Tÿ†Sÿ…SÿƒRÿ…Qÿ‡Qÿ†Pÿ„PÿOÿOÿNÿMÿ~Mÿ€LÿtL%ÿ=NŒÿÁ¤yÿÖ˹ÿ€“ÿ2K–ÿsIÿzH ÿxGÿrHÿ5C|ÿ‘h8ÿ»¤‹ÿ]%ÿìÿ¯Ÿ“ÿ5>pÿuCÿpAþo@ ÿo@ ðn@ ‰V‹WÁ‹Wÿ‰VüˆVÿ‡UÿˆTÿ‡Tÿ†Sÿ†Sÿ„Rÿ†QÿŒQ ÿPÿvR2ÿtP1ÿwM$ÿ€Nÿ‡Mÿ†Mÿ~Lÿ{Lÿ~KÿuK ÿ;N‘ÿ^bƒÿFW“ÿ ÿl> ‘ˆUˆUŠˆTÿ‡Sû†Sÿ…Rÿ…Rÿ„Qÿ„Qÿ‚Pÿÿk> ýl> ÿk= D†SŠU†SdžSÿ…Rü„QÿƒQÿ‚Pÿ‰P ÿdOLÿRQnÿ‡DÿŸ|Wÿ»¢‡ÿ~Oÿ{IÿšrEÿ¡vCÿ“_ÿsA ÿLCSÿ7O™ÿaI>ÿFÿtGÿvFÿuEÿuEÿtDÿsCÿrC ÿqCÿtAÿfB#ÿ1J–ÿqBÿ~>ÿ?EpÿUB?ÿq=ýj= ÿj<Ôj< …R…R#„Qé„QÿƒPý‚PÿOÿ†O ÿgOCÿNQvÿ~@ÿªmÿžyRÿj1ÿ¼£‡ÿ°”sÿ¢\ÿ¯”wÿ»¢…ÿ›k.ÿi; ÿ9M‘ÿQI\ÿ}EÿsEÿtDÿsDÿsC ÿrC ÿqB ÿqA ÿnAÿu?ÿTCFÿ4H‹ÿJDYÿ6G‡ÿm=ÿj= ûj<ÿi<ki<„QƒQ=‚P÷‚OÿOý€NÿNÿ‚Mÿ;O“ÿqJ&ÿ‡Rÿȶ£ÿ‡Y&ÿ°“rÿÝÐÂÿØÉ¹ÿ¿§ÿ”nCÿº¤Œÿ¯lÿv;ÿÿ]@-ÿED`ÿg=ÿl<ýi< ÿi;Ôi;h;ƒPOJ€Nù€NÿMü~Mÿ‚L ÿlL4ÿ6OœÿuDÿŽ[#ÿ¯šÿ©‹hÿ¾¦‹ÿÖȸÿÞÒÅÿ̹¥ÿn:ÿ¶‚ÿ¡€Zÿo9ÿ5L•ÿjDÿtBÿqB ÿpA ÿo@ ÿo@ ÿn? ÿm? ÿm> ÿk> ÿn<ÿr;ÿk<ÿi;üh;ÿh:Jh:OMDMó~Lÿ}Lû{KÿƒJÿeK=ÿ5OžÿdD.ÿFÿ§„[ÿ±—|ÿ«oÿ­‘qÿ²—yÿsC ÿo>ÿº¤Žÿw@ÿSGPÿLG\ÿx@ÿnAÿo@ ÿn? ÿn? ÿm> ÿl> ÿk= ÿk<ÿi< ÿh< ÿh;úh:ÿg:Œh:€N~L/}KÞ|Kÿ|JûyJý€IÿoI%ÿ:MÿGKrÿg<ÿ}Dÿ\!ÿŠ_.ÿˆ`2ÿvIÿœ|Yÿ´…ÿv9ÿXFGÿGFdÿw?ÿm@ÿn? ÿm> ÿl> ÿl= ÿk= ÿj<ÿi<ÿi;ÿh:úg:ÿg9²i9i;~M|K{J°zIÿyIýwHû{G þ}FÿWIOÿ;NÿAHuÿdSSÿŠlNÿÙɶÿæ×Âÿµ•mÿwFÿ^A-ÿ1J–ÿdA!ÿp?ÿm? ÿl> ÿl= ÿk= ÿj<ÿj<ÿi;ÿh:ýg:úg9ÿf9¹e8 f9}L{JyHcxGîwGÿvFýuFû|EþwD ÿ^F;ÿEHlÿ;I‚ÿ9F}ÿIWŽÿ8@pÿ7E~ÿ:HÿaA)ÿq>ÿl> ÿl> ÿk= ÿj<ÿj<ÿi;ÿh;þh:ûg:ýf9ÿf8Ÿf7i=f9|KzIwGvF˜uEùuEÿsDþsDüxCüzBþtBÿkBÿb>ÿdC&ÿjAÿt>ÿp>ÿk> ÿl= ÿk= ÿj<ÿi;ÿi;ýh:ûg:ýf9ÿf8ðe8bf9f9yIvFtE%tD–sC ïrC ÿpBþoBÿoA ýq@ ûr@ûq?ün>ýk> ýk= ýk=üj<üi<ûi;ûh:þg:ÿf9ÿf9÷e8™e8f9f8wGwGqB qC qB dpA ¸o@ ño@ ÿn? ÿm? ÿl> ÿl= ÿk= ÿj<ÿi<ÿi;ÿh:ÿg:ÿg9þf9Öf8€e8f9f8uEtDn@ n? Cm> tl> k= ºj<Ëj<Òi;Ñi;Çh:³g:‘g9bf9+d8f8e8rC qB qB g:f9e8ÿÿÿÿÿÿÿÿÿÿÿøÿÿÿàÿÿÿ€ÿÿÿüÿüÿøÿðÿàÿàÀ?ÀÀ€€€€€€€€€€€ÀÀÀààððøøüþÿÿ€ÿÀÿàÿð?ÿüÿþÿÿÿ€ÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿphotutils-0.7.2/docs/_static/photutils.css0000644000214200020070000000040112721610567023063 0ustar lbradleySTSCI\science00000000000000 @import url("bootstrap-astropy.css"); div.topbar a.brand { background: transparent url("photutils_logo-32x32.png") no-repeat 8px 3px; background-image: url("photutils_logo.svg"), none; background-size: 32px 32px; } #logotext1 { color: #e8f2fc; } photutils-0.7.2/docs/_static/photutils_banner-475x120.png0000644000214200020070000005045312444404542025344 0ustar lbradleySTSCI\science00000000000000‰PNG  IHDRÛxº…XÀtEXtSoftwareAdobe ImageReadyqÉe<PÍIDATxÚì]`UúÿfÓ„E^Xè+MITä°&6ÄFâY°œ³œå¼$÷·ßiÀV’xŠŠ%ÁÆY *EQ U9–* B =;ÿ÷½}3ûfvfwf[xLvgwöÍ›yoÞïý¾÷"Dˆ!B"*±âKâø[ÒAüïª_:×%îˆ!B„ V¤£í‚“ϼ=h*y›F´S|ïÄ}Y–uGËʶ«¾+ÇOÉÞò¾’¼© û Ë_¬]Jˆ!B„U`Û.ý'ÂtŠ(¸‚œÎ!'ÿVùW‹¾ú2è"ðR.'à+±!B„9òÀ¶}ÆLd¨ÓÈÛtÀz©E°ôè*{¤˜òZÖ¸B¯!B„Ø9ò5€U¦Ý`m€=+AuAÈLð¨ˆÃ–a)‡ªæÙà}I¨›£,‰“ò³•¾@\uŸä‹;&DH«[Y¶m³Ú¬T‡³ÿŠë¬Ù¤)fàº+mIRAN’$XJì¿–›jàŽÄZPÆ·žc-”ãùwÀ•<Ÿ+ÓZ˜ ¬¸¥"²_7úFÝYt£*ж#”“M€­!BÂ*޶Vá”sîJM9ûNZÒ²[H@-ÑÌóE7Â!X*€éK‰"qûÊ5åp“(mìX+ehêBË!“)ì  ‹ÀëÝPˆ!BŽli3Ì6eâ]hÜ”GÙ‰$1†*)ŠZ/ÐÉvªì%¥F Õ˵ǖ=û¤˜™d?™.a¹ù¢; "¤­Šœ Ùà]ª©Ê LÜ•6¶'ÞN^ȲUQYt:Еչ C¤jÙZ9²Ête™®œGÕœ9tËE·"DHÚ" ¶ügÅpsÄÝñH«U#;Ïý[ªóÜ{Š"-&[:¨°&é̺ STõmDTËËÑ(Ÿ¹‰{ë£ZÆw8#\,TËB„iƒŒ6Ûà«löÖ¶ÎI÷:“þ–O°h  l-@yaK’´@æK)‚ ë=Ì|=7XàVAw&ù³ŠnšèžB„i2!ÈïŽ*iUjäNº×e‹dÊòŒÖa¨)jXÆý©–;Ju0"æw³†Çì%ûõpFÌÃó¯i>Ö’íë¦^ðAã¨r'èÖs#©ZVÊ¡û©¤d¹¹+^*ÝTˆ!B؆²“ïs2ã§™Ôh‰âŽ?ã'ÿ ;Üñ;\û+œO¶á޽ô˜µîc ˜v%`ÚæÖŸ•JñøAAûxÒWð|ògðzÃ`¸§öLº‘[Ï•¹µfïÚ28ÑU(nôM#W¼˜+ºª#Y'å/†®YuŸäKâNÙÑ’K*‹ˆ[FÌËöóÖ¶ÇL¾°"tá‘yÐÆ?èzÊkl„`yUì:¸%îè+UÁ6¹#|Ôt¼Þé|˜¿³TÊ Ð±}"ŒØ†ìç“×¾Ý9ï.—®£ÅØ8P-ë‚ØMt—Àq›aò¡K Pw±mD¥ ˆaný¬B®!Ë…™pp…¡#YRÅ-ˆˆðþåårpê ·8Bà.ÀÖ6О÷@> ¥±ž¡Ò}IXI9%˜ý̳ßÇQ ÷Æ-¥@[Eõ£æãanc&¬!Lße \uzOض{?̽{ Ü$õüU‡j጑ǑïÀšM;U Ãr^o6 „Û½‹Ú¿ Cªs Š°a-C Ì"lªåìø17áN®Hv D€­Ö&huLwIX´[;Òùü¿£µm)A¡toä'/ ¤¬0Ëí먂¿Å"È®¥,öÖ†ó(“E T0ïªI§À׫…oVo‚ñ#¶=`8Û×?]IAö‚qÃàÖKϤìö–'Þ€JÀ XbYç¾ –µžHú n®™¨c¨Ñr¢û8kÄû–%º­!BZ!à pmM`ÛåüÓŒ,¦À!Y]‡Õ‚.‚ìô˜•„i&Âmdç7÷Æ"VVuH9ó?ý^ïoÖÀ^}»u¢À;ÿ“•ô'¾ú a·d¿ æÞ3®úÇ< È!à>R?OÄIÛĪEÐeÌÞ€-g†[DØ­P) 9b$qR~º¸ áÕÐJ$ª®?].x0›Çb#NÉÔ=G2uóAc§% E0=ö{x¾ùTH«»…ío9>¾¬ )ÿ#»¥ ̹ }½z3\•WLYîðãzù¸çlsw¤ë¸¡ûçz™»nN¨sÉõë*„*å"Ñu…bA„ÏþÑÆl½ð3 a+TªçEå€-Žo‰ùŽý –ºû„†ëa›œâ»žËÊp¶K„ázÀ°=¡#y‚ë³-[OÁÖÈUUÍøÝã†ÃÚM»4uQP°£Ô@˜n|p¡ j™îÍK–¿ Ô6Bû"D€­´y4”—ÄÀCæÔŠ5®Ì?iÃ-JðlÌ05f <Ñ|<ÞtŸÈNU-wl—çÓ³ÆS EAðÄ ?{ô–‹`né7pßÜ÷ ýs˜”AÞPïlÅ]¨u„~,Š{sEò*D7"Ø—!G9Øv½(¿ˆI6‡Ž`tééLX®êàÕØ·a˜´®mº >n>A)AKÙé™ãè†ò1a¯¿ö9|³f3NPmêÄ“aÎ]WP†‹L–B:|\ÇEKeü³%VAõªø ðaÓqÞ¥Sh5©üJ àŽ"€+,”…´eé(n¶!­‡Ñ2+bH Y®t ½¸ñZX'wÕ?¡œ?f(<û×KéûçË–Âó¥K¡ê°`Ç }»9©Ae¥x=êaP?ãû1Âz€é1\V!\'Æ·ÔM­AWè kÌÂ×?W’LËHÅü¸äa0%¤-‹P# `4Ð^\àÍ!˪ñ“UÐ}Öñh›ÐB7Ž{ÖsŸÍ½¦žsÙeðÄë_@%Ùñ`§gŽ¥êd3©:T/ßà5X"uA¶‹|F~ x -áÄrXëî ¯7ƒp§ò3fa ¸³ÆN/©_ö|¹èÎañFÈ!r¦ÿˆ\Bްí–ùÏ"‚Ù\¤'  «³˜,ý W:VÃ_š/‚õrwàƒY Úxá£×CŽ×>ô:|¼lƒÊrÿóàÕ~ëUu¸®ùç«ô#J=2ýB¸jâÉp5Z\ßåUÔ÷Å-£1•Ç×\繄֛ʯ(aÜôQõKŸo•êdæÚ›”\” ®;¯&[YÝ'ù­^%N®'•¼d’m$xœøŒU²kQ@»œ\Oy+©o:«oÇ&¬¾•l[ÝBu  D€­} ý?£5\‹år¹Rlò fÑjᙘ÷á÷éð¦<’‹å)ãÂhh/¾÷X·ù7Z&6)êd3ŵÜÇ^ûÂk05°' +ËÔ½è¶Ä 83n'ý^ðpÍ©Ø2ÌHwKqýÒ¹®05§ÓãXÂe» ëOpÀÏd ›Ó˜.›xApk‹©l1ƒ]OE„ëêýWÚÁ1›”WÎ& ¡‚n8|Ãí0à%! ¼ú‰f\#– Äà|)ÃHdsõã&5úöO#Ç/¶Y½«‘¡ôe[½†Y¼wÓô-=)Àßás<Ç?r–ƨ°-ÚLÏÅ z(v˜?™î•R¼(†jHòYÏ½çª xó‹U°l­‹oîàZ,2Ý¥k·hز‚K㇤ `9=v%<ÿ%Ú[ë'³ŸNågtý%'»Þlÿ8¥zx­~0=âöÄÕpaÜf]ue àV2'EÓXj‚n g} ,®XV:)3«%Y.9?j òÂP¨‹Iy‘\¦®/‚ðÆNgíÐj&?Q+ÍÖr¾Tý3˜ó,±ÙWÚ “U&8é!<Ïø¬’²fÀ ¨U Øö¸äazb/CU¢Ûݾd‚Їl‹äA@ÂrútuÒí…÷Wø°åE+~"@|,yævxã‹ ˜VRëcØb@w7bU5¯%`|ÛSïÀŸýjV.ïí#ñ_PVûxã8xŒlzëgSЕeŸD fë¹f`92æwXÔþ=ØêN1ÕSið üñkõƒà¿)¥ð@òwðpíiØrvâø[ ê¾™ãŠâ ¡°©"á.*'Š*ÁJvM8ˆ•Bx-eiLpRö¨pƒ)³1ÚH‰2ùɈ4;"$ l¶Ð)(¯ вä‘fðÜÏ#e";Î! [1°íqé#JR§¯ZØèú³(Т¬‡î\Œ`(î:Û÷T‚Þ?wûž*ȸcÜ|Ñ7¼?^*Y.2^´VþxùOêz-ç0KËïØÏÅ}¡®i¸„fò‚(ø&Jàüs•º‡¢ZÆP˜?vò¡K š%SÀÃ1{Ñsui„áVב,¯?¶LÕ‡ÑÊ›ÆT¬¥Ù¬-¨†uE‰áV°kZ ‘ ¶Êô°h "8Ñ1›,¬ŠòäGHàÉa¹ŸöJÓkw¢ä:’nÚ"€E†ZfÏ`Ï›S÷\/&ß瘩ÝC[ÉÃhSõja­ñ“¤2I¿Á,€‰¬î¥k]ÔÐéÊsFÁ‹ï/÷aËÂi‘6º”ì-Y[gXv„:ø[ì74©†¼¨ñ|x9†j=a}(ªeÌ(ÔÏQíIã‡@« fñl}ÜŸô-\¿…2ÝlYa·ÑR÷­ŠÒyö‚g¨Ù>®…ÎC\ Ñ÷SÅÉÀmy!;ö¡ `HgýCH¶…uÔ­2ÑÕOVr¬î~c:A$4y:m’bXh(!%"èyÙ£äDR¦&¬¾¤†äg $>%.Ï€¤°„;ÀÃ^'K ËyñýðÐ ‚›ƒ•$É´bû$'@½—€lEÂ\˜³nk¼.l¸š¦ê“Ô2ì'JPÀ%90/ÇóçŒØpuü˜^{®šP-™‹ŸÐ8.ˆß &É ØåѺ8£Är¢-NÆ #-ÙQºža`µÁm… pE0 !mIôö$ŽVVº•Ìhn§-Èòg,4Øö¼ì1ò I…> ¢$; »àÄ2è7IË Ëù×›KàÅ<€ûÃË3áî©0nx*ÛúÓ }g5µáê‡1ޑɮJ˜76ûBó©0ªþVxÓ=@W—ð€.— Èh@þ<Ÿô)|Ø8nþ² á÷gÆî ”HÝ­¬“»˜š¦<5/éÌëHl¦hg†01¨àÚ£œ :A±êP®Aˆ(³ÚtÝÇYŒ©†¤Y Û(ÚåþŽ ZLÆvª÷Öªs9u)Ç$Ý|ŒÖseøL†Ïa|ïëdž?×0 ë¹þUË÷Ç/§ëµ÷Ö§ûÍ4â¸Þ°vË>z,ª›qm׿®œ–tÆm©µ_?çja€¥¦ñuŸä» ÀBñM·Yn¡?UM„Ï»|×±ðPýœj³<¼ÅA­‘:ÌJ{€IàÆRgØpe½8˱&ŸO°Ñ lÔ­\@Œ?«ò@àht–Øöºâñ|2¶§ù‚¥Ð5 fÁ¯çJ°z'þø?ø¾—¶À¿å xOÅ÷ö½•ðà+Ÿè¢P©sjè4VrÁy1©JÕÆKå~4"Õî0¯ÅjÀ’£ÿ`ö×sÑúùÖøaNÃI4_®d²ž‹Á7.?ùu'-»_ÌAr|Š•T~عò[ Sã@žh=Ã(cÁìø`¦"P›Óˆ ÈæM¸=Ÿ©uí€Õ„`Àìû¬“ºçhº…kÉ`Ïà }¢Ó¯‘ïóM&ùVÁÖ¬ !B,>k¼”D»¶Á¶÷O ÈæÉÏPuÆOf Ð"Ë}KËȳ~,†ÙR)ÞE°”ì¯'@¼”Ž|Š=€>r%ô‘*aì†aÒnÕªy©œ ÿrO€Ý'ÀvÙ©‚1‡ú† ÕË t¯Žó„™œÓx’¦.˜yèüqà_·càµO¾ƒ ÇPM¼Ö4 gÄ›z[‰Buq €-¸YvŒ˜”ÑØÆ&€L‹»µ4qà®%‡‹ÜdEl¯yr¡/ôzÐE×$ð¾Y\dÙ£Äx.¤Kš¦§uƒ­¢¾òF\ò’e–ktÑXj†| ü2`2ücɽÁ×»$ß(UR"uÚFõM9 –‹@ ªE/•°~¼c;(á™ÖÊ]¡JN t5®BdÿÖø`~ãPO™¬Œá{Á9p·íÙ÷M›Dý…?\º–²\½U€ÐiÉgþ%µæ«g¢Õ©f‘:(—#¸l°BdSÎ[&S㉠,†s# ¶`/ÀF™ åÚ£ƒ‰€uKó´Ð6bGZܶÀØöžò¯luV­€%ˆèzØòv¹¼H öE£!¦Zïû`RùéÁr˜c/Mï×WªŽÀíÏ7J˜òñ4‘¼Fµlƒ-_»ž”] sšNVkôéÞ >~òVê 0<æwvÉ’®…xëge_š¥~²¿(6;à©ks ´œ,ŒÐŒÛŽ•ùl?kÌ–µ`ÝR9n Ò¥" Z¥è€-¹ÑÕ ˜{ŠèjG|I‡§^p ‡«P° «­‹Aã¥Eò‰Ðбœ›Ö¦Œ?zN‡‡ÜWt¾¾?þ_ê‰:E˜¦ÐE¶Œiû0ö²â*tË%gPC¨[þõT³ô(ãG¤¯#Èw’Xüº I-Ô¡B; ©ks…A=©p†é6Ž ™õ³û0Û¦¶Aˆ¶¶3äÌ誖-mß©O:=³jIÃHMƒYØb¹áÝÀl8òÜ¢í“âàøaÔ€®>¢\2î˜4v8¼}Üõpcò p^Üfx?~¾p-úçÞÿ# žACB"­iŸ ÷];æ¾÷5¬Ý´K-?G2ʇËÖy¯A³`F Û¦ÀÖæš_k¾6;`m‰ 2²UæXV h_,Æt!md"ÏRa4+`‘ÙJ3ÉÀíÔ”¸~XnXA±åð©–¹O„)ÒjWÃo•µàFPLiÇõégŽ™cO€äácáö”› oÌ!¸uººpuó¢>œó ‹½ìùî–¬ñôõ±×>ó‰B¥¨‘1¾3Oñ×è'‚”æÛ¥ÏHocE¹Õ™eîQ¶6YíÂp]mWê(DHÔ„E‰Ò-Ù„ÝE«Á¶ïUO9ɘ=Ã,úàZQÏP-²ÜÄ„¸A“Öãší?jÞ÷ÀZ×>¨:\ 1±1ÐýØÎ0ü¸Þ0é”ÐkäÉpK» ¯£šF¦ …jxÌ^ªFƹ ã¾êÜS`né7Pù(T¸n{þ]ÏSÕ22^gû$-pKF ËÝ+ûƒykW[°#”gd*³hN€DG!­Ur &¸«Xé–[ Y-HN/fø] ÔAnÓ§° ñyºå7½½å¾ê\ÓõÜð©–c¡¬çzÞUA\×|œëÞ·î}>­ØËÖo‡-;öÂÁC‡!6†€î1)pêñÝÁÑo0<“A“ô“ª¹¾ ‹éûÖº»Â6èH?¼`ìPšÍˆæÕ5 ý8ÿÓï)ð~³f“~*bûÙ‡å¶5°ÝjãØ£i`·ÜŽÈŽ´5õ"$ÊìVIÚPi0Ž`Æž"–Õ§eÀ–ŒØÓTàT­Ê ÞjaAÃøsó×°ÞÑ V8Â$÷zXÞð\Þü}dUË ëÉÐøÉÿz®—宓»Ã_ÜÃ%?ÀÍ¿ý¾ú~#|üÝ/°jãVعgÔÖÕCûÄXH=¶ÌKÔ ScÖø€%_´`~£y¸zï¦VûѲõ°]Mý§7ƒb,÷0§¢ ´ Û¯=vT°GS\Þ–1;à-˜­¶¸.ƒ¯³É¶Š1ÝìpPùõ³íwõ¬lPÒçñ¸Q/5CŠ\ã Œ¥0ö\ÊtŸjz‹¶ æ_¿Ú0ùçò¡ããT¬ñ›Êϯ¯—å¾%„íÍN(·à´}[ ïÐe°`Ï8¡WGèÑ)b ‹Þ[U MÍnXä>ÆIÛ||k•`ÃòRw?zÎŒ5f\óÏÿLå§`§Ç ìæÏmkLC$& lËÅ­"Ä?à ňg…`ìÛF\Ë-$ÇáZïìP[ Y­lrž÷§Ë¿Âh÷¯0%á6¨–’!†|ŒZ\7é c'Ñcž$€»Ãq ,—³0]¿¡4É °Œ‰q@\L y×hÜöAÃFžÕ|<-¿ój^„®0çXx-aÄ’ ®ªi¨;D`XH¾n<;EV‹VÈërþØ¡”±~´lO³ A÷›Õ›i9Øèk«þ @þ\oÀ!B„Â.ÍcKÀc$cà–tÍ‚1²\dÂèWì/^P`›zÍìTZÅðÉt/oZ Pu3ãЧSôp&¡ú&ؼ÷0Ì®™cÜ›àÉÆ·`lÂý|ÁÒ ©º úÁD¡"ûtsB%…lÙ?èʺL>Û¡d¹¯ƒ±°î–—ÀÓÍÿªº$XÝèqC{èq/¸Og_†z¾ƒ1›8 «ýxÙz5‚TJûD¸jâÉôØùŸþà laPŽG ¯ %F³ò\£,ÔzB„b º¨ *g)ø”¬WNÍR!c»ÅäµÄnÖ X?¬v†Ì€MG=èŽnþæÅI­z MÜú› ‡ë›aŦýðý–J¸Sž ‹êŸ¤jeT/›w8TËÝi’â=`¤”?¶¬É•cÈ–õ,7ËÝ&:+m…¾l‚ó±ûDxÃ=’†p4b¨˜uh˜´wŸáeºlo{êz,æà}ÿ‰©±ʰ=à¶'ß6NäÀ@ùË*ı\‘oTˆ!Büƒ.2W´VÎÅõZðøŒ›iQØ.‚mUÐõ£F–2%l2ŸÆŽ®/ÊÐA®…Þò~Âl{C)Ð…€ï¼Ø3!…€óåÍ+!(ÿ\ £Í>¾ …Ý„AÏì} îû¹ äàOò†¨„~ôõÖ[?cö ­4Ÿ®Ræøá`Ýæß`ûžJê?;=s<_¶ÖnÞ /÷¬á' «·8F¡ ï â-K’äC’À×]¨õ‹&î:ŠÆ«×š*†K!BÂÃvÉ–O6dG˜ËŒÁb(ãÅ܆ Á– ÐÓŒýju Ë@×k;&ÇBÚÄÄHNN‚”vIp\÷пk2ÔÇ·ƒwbO…Iîu¾Á,ÐÕ H5qÂ$ñï4¿Ÿ6? WÈ?Bs—~3pŒ…-0O~>s?K€ø·ÐAW_ýÝ PÆ8i+³Bö|‚Ìv-[T'wl—/”-SÝ|0!Áø‘4A1” DÕr¢ß$ºÙ ¤ì¸* °ئ‹6r”oÙÐe¨¿ è¦\3?Ûtc¿Zt½Xã€øXÄÆÆ@bB´KN&[tII‚]ÛCJb|3Îm^GÝ„¼˜|* ¤ñvó‹ÐÀe17Á蘿AÙIwÃú³îƒswÀé1wÓcßu¿Lט¡š³e C !ô£“Lp½ÖÃl=eášìÒµ.úÁåž«ÏV*2^,ñg˜’óê³ðÃrÛ–Ø ¶(Nb$Dˆ—í"èÇ@­\‘™®ØœöúÕ¦ñ€cÌB2À@]oâã!))‰²ÛöÉ Ð³S]Çý.Öx´¼ Âúñ•¦Wi@scgÀ ‡‡NÙF èNÜÇÀeŽa»Ô æ¹_o±T~Ø¥òz¹;-§o7'e²ë6ïVY.ÊÔ‰'⣧.}U,ѼõT~ZÐm3b•EU†1Ø~[–Œ¬e¹¼D¯"¤5‚n9c¹F©ûfZe¶é¾¡A›ó´ã–š™å/†2Dv‹€‹¯Û'À±) P“LÝ„†ºw‚¿ÐV@w˜¼ ÆÈ›!7æ ¨¦4˜ßï >0 ç1ÐçX'ý¨ZJ‚?;®¥ìÕÌÑMåçy‡*dŒFU%%Òý¾]=Çë¶üÃö¤À‹‚¯ãF 0KyaµAäÏm3ƒadvR´mÁ/ì´ãÅal“T`+’9š·Œ£Q¦ïó[L8.Iª[Ëe‚já¦fjÜÐìv{7.–mBBÔÎ`=ÃAî ŒCC*õ»á¼S!¥Çù†óOQËDf»Àq2L!`ÝT~°¤`‹þ¸¬ŒqÃû3VK´«¶=¨ëÆËÁ€Ãj*?ßµå6!v@báÑô`3Æh'‘{¸\¾ìL€«r4nŽîc§Ñscäú“Ήī×Ç3ÈëqcâÞë›Cum446CssuŠ! 7.¦b¡Sr$°E¦‰VÉ<Ȝϫ‘{Nb| Ä8ô€nÎöôøŒÝÛ`O—S û¤“à´A½aˆTh°ÅmÉê-dsAüú-Ðû—· ëíL¿ß_] MÍôýẓ`,ÔúQuñ±î*4TÚMýp=åH4L#u,¡Åq°•ôȬd¶)ª4uñ f¡úç¶!Àe *[ ì~¥Ìâ=Röâ0œs†cK"ÝGZhé UÀŠ?€‹A1*t ‘~™íq9s„E¥ú°7¦»ÃÑ»wBc³ön„ÚúFhhh„úúhjj¢Çà:nÌøØø–0Û!TÌ3K_–‹1Ž‘·#mùí€Ç@×Nía`ÏcÈ÷±rlw3¤ MíªZ^†¦vƒSNì }ºv„Ž„ãoñ}Â(;&{Ô·íãÉyÈvÕ2Æ2ƀ롻Êt‡õïËÖmSKa TÕ2?éQŒ¬üe2a¹KÚHŸÍ³q¬+BiìZ»Øaóy¡²[òûl@6‰è¹Ø ñÙL Àl¥4Fg=¬SÌBe€ŒR}{<Œnúþã> öj€ªšF¨«¯‡ÚÚZp'$–ë¦Ç£µ2%§\Ju³x˸¿®±‰‹Å@Þ¯¶#Ü0ù$øóyžp‡Ë7l‡ü’/aýqR~órhzÀg?lò–©¾ø·¬Bųî@A1†V‹²”®£Ëvj­¡õ‚Öʼ´H ý8̱—~¾ª‘õÁ,¼uñ(|ã$GABÔ3m²ÚÙGãÓLÀ¬ŒÜ+—ÅÁ?•M`rƒllÓÂ(´I¹‰Vz44hq*딀¸lLÜH??BZ…œh:t¬*I’ÀËý6æx8½ùp`Ùw°öT×AM]=Ô°EÀmlj·ÛíeÅ\9æÇúua_÷œÂå]ÐÐowü^ù¯.V‹/ @»Áµ—þ]„®pÿŸ8††5•_à`„ÅÂnØNÍêØa©°nËnkn®tÝ '¬ƒY`?s‹cS¦[…ŽVDçô u%ÆUÁ¯ø(~¨ l;“±Ó`€v± ¥MìØ´(ÞgW ¦a†4… 䈇v°—úI:£%%ð½è~{]ƒ=§q ¨i‚M{j`ÿÁ:8|¸†nõx›šš¡¡Éí±VÖŒß`’©Õò'Ža°ÁÑ^n,Ö÷Wk\x«aýÖßU¬*hþ€¾_à8lçÏåá^gü¤e©Æªå>R%[ p©>\gØÛöVª®@ë™eºŽ=°Nîf1˜…wÀj銳]LéB;ªKÆhí ê”A†Wy´>°äÚ‹Áž/k‘Àå€Ö¸Û&6UÏ©¤~3[lÓÃ}´‹!zjjÁ #'iú5rª @wGLgø,n$\Úø-Ô5ɰåZØþÚš:ÊnQ¥\ߨë›àÊÐQ5Ž ‚åê@÷θ©Ð[> æÒWüð«5[aÍfê6Eªƒ§šÀåîï!?öB8(%é"Q™³Âfµ< öÀ2T!¸áþ²uÚöØNÀדрªª¦N½š –‚Y¨•¨¬üä1W;„[è¦ùc³d+%oKm8 ÏϵmÕ0îâmâd ¼Å&ÐVÀ µMìh_ .3¶ Uô¶‡³9 d,ð¨°s!TôQ«õÄê˜f*pAí=ã6[Ó”µÖ¸ÊJççl¯yz6ÿ»«Ž…õ»A—ñÐ|¹mÕ5ÂÞêÆnjL…ªgœe¶Ï¯ç²7ÔgwJü­ðRCü·á)Êvã×ÿí÷õ€ü¦/àòæïé¡o;NVáÑ›Ê/ø„õV×sÑ¿·JÄY]kÙò:¶¦Œ‚»lÝV¸{ªÇ5ˆÏl€îC˜¾O3!ð“lž[Ïm #"']Ta"8V°­ŠuÈ´fò¹G3«åØ ®Ý"ÃͶñ3df«Øš/‚$cBÌ-' —´ÐæùpÑJº„õ­JÖ§R•k!ß Ñ` ï¿–œ†¡øÂ‘DÜh+#Á:MÖžÃr mIXB\ªÊŠÄº;+?3ÐR¶dŒNÕæ•U†o™a-oŒCGtx7~4ÜQ÷‹© ý`šUÈæz.þÃ`ÁÅ[ÖÀ§áz®«å>l ¤Ì–n\—G˜¬jü4 ;U!ÿ÷ÛŸa8Z7yËnõxýkµuQÙ«õõTåGÀÃBAE¨MA*£6Ü“Ÿ‚0_G8Ö'gÔ©(À%¿Ég@›ÊõëH°,½Ì6Ð6MÖÏF}ŠÚ–„2qâ€V/ËÌÚÔáÅÿn>F Ëïÿ­Ý4Øéè Ï~5í QuÔ `pó¸£îc(NÈÿ BÝý‡jáõÇ•‚Hågå]t9ÒN$<ïÑ÷kx‚W$Á]WN @»ªjêaìðT ¼Ô?˜•9Yú–É©`%•Ÿ®~û=­A¸,‚³òŒ£,á€]ÀÅ{Ô?ŠZŒ‚­2qÈ c‘©¡J±õ=#–‚€‹ )=À`œŠ2ÙÐè,O,IyD×m žÏlVÿTêW#6Ih5`èž\®‰HÉг…µ‘å¾BŽÍÄûg´~5p:)P×ben UÌ»ô(©TÕ ×tø+¼v°^?TïÅ¡–ʧ7ý²ë¿¤ïŸN8¼K¿ÞÐt3~òœÖâz.·FÙHÀ}oåaŽêÉêÚ'+<Àš°çwáXÏE[j‰¬«Ë²õ[á®)gÂ?æ%Âì¿\D¿yð•OéQ¸vKÕÉìcž÷KÕ~ ® °ýdaü,f!Îs¹`´–ï?Þ£Qh&G 8hçD2«ª¥É5P0 S‘80‡hd°žEV4ìË6(ÕÊz#@” l0O3™@f1Œ–ä°ú:uõß –suïÈêÎˬô°2ðjÚRR…­W`žY mXF~SÎ&<úç#•[…lïÇj®ÏWrí8Òà>jÆ+÷)V«‡ôððÇþâ$óVËÕR2\”ò×Kê—ÑWd»Å gÁÓ‰ç{ÏdoÙty°ÔF³’LÀòp]£—Ìše8AWÖ˜>i&ÚøÆžß¼µx ÜxÁé°ñµ»©Ô%þªkêèõÖþþÊ'^V ?ÓõÚÊz-·Ùè–EyÀŸEÊrÖqÓC(ª’±'áâc¿ rI”„¡ ôíƒÛ¬hL|8À-„Ð-t'@Ö‚ÉšÃ@Õh"cÇpcZF²"àË«0tR\n0òi·bd®8ÛÁÈlØ:9-A¹U­Á\Ôy`l$˜Ê¶L›u, åÔÄj0‚±ZÕÅLjåZÝâij(ÀªÀ¦à’E¶ìµ8¶Çr×7A»„ØlÙ:è¶OŒ‡C˜¨@ò^£Or3–+ór¯Õrõáz8çΗ`XÿnÔõ§Š©½'>RÚ%ÂòuÛÔ{0VrÁ"yŠÛú$Jâ}¢òâú㣇*Z`°§j_æ¯9ì­›á,²$Zƒú®VÎ`½¦Að–Ç.6ÐG»=à–û­Öu ê…Œu§Úüy[Ì`ÏMê?ŠÕ?Ýæ}„¬7Z…›ôƒ´ Ê£Rf£2!8WÄJ®]-Ý#uéqÐMóÒ=3¼˜Æ±IYEX$ïQ²&ž±öçrepÇêÊ‘õuãÀ²]bœ‡Ýrqe],d ^iN¨­]»„8OV “k4,‡ã÷˰z@žã|]]4?R7ëö‹(Ÿý×é~¹VJOA¶<Á e(,W}?k߇ÿÒú¬[%“2ÒØ€Ÿfò€—3µÍôP~a¡ÒËSXŒÓD½éb «¼µ$z`ë®™\ýSý¨ùúG $˜U±¿~­¨–œË¢¬2¶SÿtÀR꾄ս¢•Ô9ŸÕ9U×gCVɳû}l$+?ÍB+³«Z5Â_o0 Ó•%-Xš2T£€ ñϵ–m¯ç$NðÏ–ý³ÜDÛúÆ ÖsQªYÂx½ŠÚ(•ßäÓO€¿õ•w_ú‰º ý«uãË0f¹ èJ%­áa¶H(Þ²m ÌÀËÚhýqp›­(r 6Û¯Ûbý™š6¿-߇œ$#Ð尜ղxËfIëµ<\›Ø[FM}“íÐf®B•Ô}ýsu•Mµ©«Ð”Œ‘T…Œë¹J]Æ’ Ô"Z ©üt~¾û>ügT¤0&*"Dˆ#Rb9`¨ô·®õ\#¦Ë§òÃŽhÁŒ 7o§¯;¤Î°Óq >µ"æxO*9ø(TælYËt{vN-»+M¬Ÿ ؼOl Õg @‹ë¹ø›¾Òø“üäÀUÀ‡m ˜´ÞS·–`µipt&s"Dˆ{`ûÓ 9ƒ§±q=< ë?ô£²zËûáŽÚàœÆ ®ü⧘>`ñýt{7ÿÙ ;<àK>7n4ŧC5$…º&ÆOÇ÷î K×oókýìOµì\sW¡±CúÂØ¡ýàÒ·^WÁüOÀTÈÒ`f„¬1~Ò…~ä&’T)Ýéç„"¤uƒ­<€te?®B Ð`¹p>px\Ò°œº=“t0å‰ŸÌ gD…l÷Ò†o!§a1ÝŠâ3`vÂdKë¹Fî9¸8–‹`žÛô œÛ¼z/Üwà_îóbΠ¯v\…ð `±â¹épYþ|XŽÀ­Ý;§œA?_¾~«ºž;Ž Á0ôöÏrË~_Xò "DHk}н -誫£¾ë¹Šië¹ç4¬†Å•P•1FŸJïø0'œ ;c:›–Ó§Kú‚‡’.ƒ þ Åhp?<ü8 qïM¢GˆB… é—Ö?Dö•Ø3á‡ëæÃKÝ®¡©ßj˜ëÉ$d)ô#—†ð÷*º MíúT~7ž*ŒÚþQô¹ú›að %Ûé$îzü§òãÖs D—"DˆV¶¨†”$}°|°`üdt‘ÉÎ94—ÆT¾¸ãß¡4a¬Îˆ tûNÔz›½phÙ‰çÁ…íï£ûókž&€»3¤Ð/ÕσÒ109ñN˜w& š|),ízMrP; žl|Ƹ7yËÑÞ<^?À݉°ÖíXOÑ€åÐþÝàÎ+΀—?Z \{Ô2n”—ѤË¥þvóçï]˜ç]Zˆ!BZ?³]Â@"ºYõËá±CÅðLò…poûl šÞrÀÔjùÛŸwÑ­º¶^¿7æ“íÜ“ÀGg¸ªÝ ª~ž_3†4ï *ÞòeÍ+éÚñM ×ÃAR§¡ýºB»Äx¸`ô‰ôw³âÎ…Žp}ó×`%Á®¹v„ZºÿÔ;K¡÷±á†ó<€;´Wx'ÿ*ØNï“o/Uãw„:ø“¼^vŒµ”´žgòä¥Dtg!B„i¢_³eÌH5¸ñì)á®çòyo}×sOkÜH€¶ž%@ûlÒ…>q’­øçîÜw²\…íâ~ѧ«ážO“áù𠏶»—‚°‘űYèÇÑÍ¿ÂWÉ£ Ó€Á0ºwg¸þO£< þ%¸ñ¼“aÓo`óoûaïÃê±mJ]%d£˜%_Â'+1CûÀÛåkaAù:Ð[?_.ÿ@Xíxja-ÙKXŸ+º²!B„´°]?纊¡·¾ZI†p§ž¡Úg¹Zн½æ}úûû;\ïëºÂîiƒzðëL@ÎxT}¼q—Æ=ç¡7—’ãzªÇÜ‘y*\ýø.8H@ꞤkáƒC¥߻q§ûøÕÖ54«Œ´¦¾þø¹¾ûy'ô«OÑKÞ†ô•ýéºðŒKN‡ËÎBYé?_[Ÿ~¿ ®oZ3¥$xiÑ~Â6z™m®ûS C]±a;ݼ—âeÜ—»€>òXs²—¹ðÏe [¼»ôA—èÊB„ÒFÀ–üådÏ”#4b¹vA·§ûw¸®ös¸mµ#Y•-#hN;{\wÎ0@ùËE'CuM”|¾ž^ø=¨ûÁ3ä}uM=<0uU'_:þDx÷›ðSlx/~4ÜQÿ1¼K^­†~ü,v\߸„ª“Wì;f¿÷-ÛyŸTÀ§?l†¨%ßŸÆ W ¾¯®WµŒ¾Â( Û¥N~]…Rä:(hþ²Úx¬ªD˜Ê¯R–$Áj…"¤•‹Ãà³%À;yßj ŒQy ¼¤nìŒé¥Iã|ÊLXlÙ?.Û/:‰-ª‰K—ýž}ÿGúºóƒôsÝ÷ó/ƒ ¡HŠ(þl-¼·ôPòÙ»½øTµ\Lç×ÛýœÛ¸Ú0ô£>ñ=eбÇÓèT/Ô½L­šwì;Hѯܸ“úÞþ»þ ¸³â&Y ý¸Üq-w(ì è*tƒ{)Ý*æ0L|/qÚ¾€‚Ýï= üj…"¤­1[ Ã2c"]ŽYy˜!cº:#óõ\/sˬ[ _$Œâ’Í{ÊÜçxõÎó YØ÷ÀªÂÊÍwÜ?e æ¹·O‚kžø@]ÏEÐ6q]»Ò· ]¿Eã¨ocO€‰MkhÒzÓT~:–;=éx¡öeø¨æ ¼ÇÁŽg7ÂÌëáÔÚïè÷W&ÞNËö2Kÿ¡78zÂh÷&øÄ1Ì4ñýPyüµù3ȹÈÃ†ÍØ²/Ë­øí½DÎW!B„i‹ÌvÝs׸ÈK…¾Ì ‚`¹½›ÿ€^Íû 4q<ðÜ2¥]<<{ë9hÞþdý_)”.ÿÅÐ?·”0Økÿõ!ýè´{Àé'öT™º}‡kº€ÖɽTÿÜÏ ÈžC˜m c¦+é2àº-Z'‡2³Vžý`aÄ[U°D Ì€zåÆßT°DŸX…¡z%ØÝf.,”Öø‰ã÷6X®ÿ\Эرàa},Dˆ!mTbý}¹ö™©ÅÃïx#dHµAJ50ò¬6nŒï½ª÷ÑDñ™E¯¤G[òÿgfŒ„k¹ƒúv¦ªâiO."Œ÷8í„îtÝöÛ»á;¨*Þ“Šj¹tÙ/P]Û¨&ÜäÉo‹VÉæñ–e¿ë¹õÚ‘3Ä …Êîz®™®.ÉA%¹±v*¤Åä /t’—4²U~ðÁGصe“—T`­ýúŽä¶8ªÁ–aZùS$ƒ¤ ì7˜5Üû9®Ÿ‡6ü_$žì±fk²¢sÔr$([þ+dŽ9î¿ü4˜öÔ)!#ÓÕà ³~~4û ÊjQå¬O)ÓXAC7‚.˜…ov"Ðd²jµ.ÐÕ'JÐ%' €œ±ý­»…µ¯–܃Ç:ýˆ˜ø1ÐZÌ®M }Z!ÚBH‹€í𧧏ãdüO“%›q’É߃Ždø’€lfÍ7ôYùË^ú»Sï¦úÚ¢<÷Ñj8;­/œJ@ø™[΂ûK¾¡@ª·Ü›üæ´Ö(÷E݇øç4¬‚ÏãG¸Ð˜±Üp®ìë*¤€®¬³’Ìr³¶½qWE ÎØ·°ÝYd&œÅÁ¬ˆ¼d³]œ…w 㬥‚”yÄNBȵÊ&_U2@(!×_,†° %›õ%­,ÑÆBZl2à ½8Øä_& xz5ÿAc$ïÚˆî ¶×f †ÇÞYI¿kÿaxìí•ððuãàì‘}áó‡/ƒRÂvWþo7MF€V̰È(”Ñ.ø>¯Øæ%Øä_VÝRz®’¤sü‚¥mÐ5p⸲O&ŸUË9ÛÞøkyˆí›É^]ì}4“drïd`É$GY˜fõÀfõåGÁ3Z Û Ô%ÒÉ=Fî©`7ÁÉö:»LÚZe“sã³–NÎ/!Ø|ò’‡c¹¦¨–ÀvÍÓW–˜ñæ,‚3­³PA—¼_˜|&ÜZ] ·|èt¤9­¢™áÚ³CÙŠMêš­çý¸c)¸bð %/h<õ(ZT1KººÜ^ó|AXí.G Ðù]™s6YÏžj63Úi hK°“‘ΖuVXn†ŽÇÅ@ƒ¥±#¤½òMþb6g ö”89)ÚXHka¶êì+“`A*AÊ,˜…&@ùîqç50ûB(#À»2a¬üu|¹f;œ5¢çž ,eî>2ÞKù°Û>p"²Y€Q02²Ü/“ÝAUÏÞ5c…¡Þvø‹ùºŽwÛ fYÕ² Е ÐÎh™ ™à,ry |+,þ>]aÅäAwÙ<ýÅìgKØ"ç8_:ÇÄËÆÁ©§ñ,—|®¼§*ev͸©Æ#œL…žY³Iª–Œ¥ÁWÎTëZ!•EwÀf׊Ïc)»×ÅmŸÊß í¦LÂ9!³[£6 p¼º´ ¶ìsÀ~ô½ ÔÆ!Þ³Pžm¿m6—w”ºµWϰ÷‹u£ÏD¸ú•-õÀÈo¥Ët¶¥‰8dݾ:(qFU³ÿx N­ÿ &u›EóÚvHŠƒ¢ ƒí»xþåÅrÊj•£› <;‡¹t><Ûîbx6ù"mÊl’ü R‹Ù!ƒÝ÷LV?ýu™¶»g38¦§Lvr”AF.ÝïKÙyñ¾Íâú€­º°~PÈM¸LÛ™;G!xí”ö›mÄ î›^4×fr_ÊÙuV˜”™ËŽ)å®»“PØmcýgì|ú{†ŸgÓê5)êã ÛØÄ W_Ý8“ÎÞ;õÏ›ócésiÒo\ìø2Ýy I¤Ò_X{”±q«”+3‹Ý·tvoË ê1“Õ£À¬ÿ9ì à«gO)Gëä`ƒYü½ÓtØs,ÌÛ÷0¤¸kàPm#äÌþŒlÏÎíáÝû. ~¶š\®\9š9‚¤ Ú?¨y;¼zà ø.~a¸#%ú@ÙKNp(¦™O¾ŸÀž‘¾žì¾d°ørVŸÅ¬õ7¸-†÷#\ml YººW°û¥Y²±{MÊ=%ßå±ý|“Irª“Ã2·²ºúéçý¹öÁߌduœ¦ƒð»~ìÞf2ðS¤” xf^ÆîC!+«œ•cØæãF…®~DÙýÈ&¯¹ºçEY²+÷§–wÕ$r%R!£R|äd†º1>.ïö(}ÿÎÞûᬺ¨ÛÎŒ—Àãïþ`›-ßvh!xœ2ÚiÇü 9Úùa¨’Žû†[ôV;–k1•ùCºp-7x¡,ä™26ãËô3ã\hÐY\ÜÃmE…œ©?7zžõ2bxJ}ËCd*ëtŽ-óê ö°Îæ®Õ‡ ê“\ŽUb·xýeV×yq‚¡ÛJb”rþž€K9ÇöyÉãîS¥~½0@²Ù@Va,6ë’fÄ฾˜©زٹ&%úY ÉãØœQýqK5Ñ~¸ ‹;mÌI…þsî~9ÃxMfl6žÌ2Yþ©dÀ”j2ÎèûØj?cÐVýuq¶Åzµ>+Ÿí4“ó’“g „›TÁ˜æW[Lo\=kJåÈ™ 2h‡d§7.ƒd‰åîŠ=þÜõïpKÕ»ÔhjeÂ`˜›r ¬Œ VÙrfí7pëÁRH‘kà¹ö™tó2I_÷/C ‚åFÀ?—W†“–-¯Þ ãE…¬g°eÜ ±8BçUU㜧RÇ|ùsç€wýt›—°‡(”{Sn2k5šð¿ÉãT‚vÏ—ªpíæê€u†Ñ gaðçôb³Ù97áQfñéþT”vݱ¸52e-ËÊä+P]\è–ëuEÕï£Z5Qç:uÇ¥ºõÃ|ƒ?£þá ²ÏÚjã(_“?õv…‰ö ’=Çé¬M]k”:TùQë+ÇÙ:¿«Y¬­fè&ÓØWv°õî p¥Å4œvóÞ$ ô‰N×Á—ɧPÐ÷ûÄ1ð‚ïÏq}éú®RΠ†­pbãV8µág8›°áî(Ks:dQõ1˜Ö0Ë®5ëç‚-¯þ%?w»ñç4oU%lW.Ö©™Ì¬ªJf*ÇJN-•Æ6Tæ„Á7 ðf«R¥c»•hËø‰ ÙÇ2ä»2¾d±Ýl ˜ÉM¬–0¶^jÀðƒàëÚ8+”º0™Í&…ì·ÊÄň‘¥s»Ì0?;vîKZ¸ÎI?Ö]“Ý2#ñ Oà&*ya“ˆbÆØ©%§BHbC99Ü ÆpÉ(9ƒI6ÿ}ÂÂr‡@Ϧßᚃ‹à”úŸàšCÿ5='1,†~ÜÉùÑŒfЕý†~TtÓ~Y.æ£ÍÚôêmåì às꽊Ùhí4Ô‡ÚicðÓ0k¨eŒ5Í`/–‡FýÃáž`À°ÓÀP »çÉ©Âx)â®5"çk¬X…â¹ôkJ>ªCýg6ÀËÍPÚ ×nuÆQ¶ê¢0 ææ’§<+™J¯Ì@ûöˆh6ïK›ˆK¡k*·p‘ºO ÏŠà„üL g0­œÑ²YøÁVÜ´Ü‹˜û†èdΠH g¾Éæ‘Õ"ÓU\|ÛÁ}ØsŒ§ÛÅÃ`Um4Çí„4 fÁù ›øç†¨Z.'edm*¾5b>™àUš­¥éŒ ÂÉny Í2ðiÅz‹?fÍÔ79äØÕ3§ª\7)уÄ4ÝÃlGÒÁ»æ«°Û Âf+9C©i¹Ð€ÙLiÕ8ï)®Ó¥ÛPUR eà˜ËÚ<T¹‚­ ëÊàUþí»¸þ‰ˆhî‹¢j] mGÂ}MJ¤ù™´§El]Üs5°e}¿¼FhÓX_XG8*PQxEÁ¢ Iâolhyo1ÁJÂzé–8vÅk»}]ŒÜsôTawª$Ÿæ͈$Ðr3@ç[È1ÜH0j0bŒl0Vú‡j¤…Æ Ì²Õ õF?Æ^`æJÝ02O!WźØÃcy"BÀ[IÕh £†RL…¬SEMü¨cŽB£{hbXR¡ `sX+ ±.Š&ƒ®y2㸠“6t× '?·¬€SOÕ?,¬Ïµ2 öš\F}µA1k³™eæ³ïÊè•Ò‹bð™mCUîâ44¡²['»NËjòØp]9ÜÊ´Ü·p #‘³eÀ,9UW!¿ Õ[ކjÙo926‚”ûkñôh °Rià Œ­‘RK½0EI嘭?·‘…ÜŒ7“û]&3«çE(ƒ;`ÅÜ€‘­XO’W;±N VqÅLš­ÒŒ}²`<¨2 Í“ ,Šà"É^J•Á€õ‡lvMN]?@«×‹Áëg©ø!¦‚×÷vT€ÉKs³ÈÔ©“mÕ…Ñ—Òè•ëÚ7‹µasç˜ÍÊMUž«æ‚6ÓØdl1Wv:7AÍjKI0B¸¦rÖfE¬8ÁëÒÇk6úq}{×ÎY¼&\?Åò±-fk©%«Æz”è–8–°ºå±1P±)â~r÷n¶•ß9Ây* /¯$̤ ó°ò‰Ö-&›·Ì‚d˦u‘B`º†l)ë×¢é¸Ehu*ä@3­2ŽQ„[…¼ÄÂyéCÉüó”àŠÿ)à"Ã`FcÀvÓl<(XF0V¡—ƒÎgÏ€! ÿ,Z/ÆW6¸g˜¹q › ‘1JãÈÅÚb1x£óµi¼¿³8vªø[V‚u‹é\v|çºe«.L‹ L´ò 6LW) œÂ(v?Ó•¼‘Ȇ8󔲕Éਖbp æš””ƒé\;frm ÐHÿHOHX3¸IR‡BðÆe×÷³bÖ•{¬†o¶nòP"fGX.†OæRáÊÚhA†~ŒX9ºï Ë0ÙXIþÎþå•›òAH0ì8•c´|=Ó9•¯+ÈsZŽéŠá¥2¦ñ¨„qsYQ ³ðŒ“c³¢pÓ8•¬ËÆïB¾ŸÁÖ…±„l£šõ‹B6Șí{Ý£Qv >k¶®)P;¶†Ô—vêŽ8Ê\xÆ\Áè‚-ºùžÙƒì”u±‡[t–a'ÙtqÖ8ë/ß(½ƒm¿ÅYt‰—Ÿ£l’…ñ›³ÙĽÀ_Üc!B¢ØoW1À¶Ìà‘®TEáåù•TìQçr8/…fD¥)4±«F³ “jŸdûÍ@+Äh©ß°Ú€’éÇPKQõ•‹Û$¤m>cѶr!G5)0a¹¨¾Àu‚t­jÙCmªeßL>.ò§„¼›µñ¥À f«?ÖÉ‚Z`GV›eb©,Ô„È^‹XÅ?\‰—‹’#rº iÁ>ª`W*Û|bŠ·*°Õî4¯ÕrÀ2„r8ÀÅ äç¯,E€­¿cóÙƒé"[®`µ–³lϘ ‰N¤¸jÍ>RÖK…´y°EYhu¶ÅÁ–ÝTÏŒVžF0.5Ú k±Œ ‹…²Ÿ^ȼ!B„±-Rk©HZî‚t‚qèF‘ ªUj8@7¨2h,WRFÙOÏg €"Dˆ!GØò2ræ\|FÚ> ¾:½v–[IÙ+W(ß0÷ºrÑ-„"Dȶ¾àûV*e»2à~2e¾²Ç¯Ê:è–³Ö*™îË®õÏ]+˜«!B„`kUFÜñFšìaÁ®µÏL *Dˆ!B„"Dˆ!Gƒü¿F®ÕTBIˆIEND®B`‚photutils-0.7.2/docs/_static/photutils_banner.pdf0000644000214200020070000006065313504422775024412 0ustar lbradleySTSCI\science00000000000000%PDF-1.5 %µí®û 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream xœå}Ë®$IrÝ>¾" rÂßî[‚€ZŒ´ÐBЂH©Y nIh΂óù²sŽ™GܼÅ⨵$=uÍ3Âææöv‹ßß”Ö3ÏõHé|–•?©¬gÏé1ÛsŽa`~®Rµ?Ky¤³>KœŸg¯×c´çèùq|ËÏ|¦GéÏtæÇ·ô\«>~ìx¸åf«Ï6u<Ïšù™ÒxÌþl³>Êùgá,f;ìÑæÓ*Ík5Ÿ«Ùï¥>WÊ÷Y¿ß²’ÿöøßÇùÌ#ŸÖõiÿûvAÏUû˜ÓzLϳÍñxý8þôçãŸþòøÓ_¾·Ç_¾>Òÿû/ÿé¡_›ò9Ï´ÿzœ°ÿþùøïÿÃú:ÿó¨ÿüøÝžæ8ø‡ˆKm劾k{f{qg-ÓæVÏgoù±Ê3¯ñ(ÓPRËV ~«ÝræçœÅWË3ÛŠ³?×ÙG¶5ð<ףæf8ÍxüÄŸ5M cÿoÏõ‘s=O[ïã¿>b…ÿòOØ”56åT:ÛmàÛ“jTÛ·Òµù¨¶›Ãµ.SÂäl%6¼íL¯ùxõÌABè¶öãD¿Ã L­aäŽõ® ¦ (MÂDB#'Ѐ-3Û€ teÓ>5®M‘ó­špdz÷ùßãóO ”·µþví³ÑG)˨þ_­íì¿>~µ§¶]FÞs~pëm ±l¹6Ðß0€‘”ÍÉHmj€aLÁàldÂzÜoL›EýÛ0²é†›8Ï®uh$þŒ$Øk‰pþo§ñW›TŸgê8Z‰7æ– Ïöʶìk£²ci„Q:—œçnØCv`rµc‡SZö·w’eYÕg­ mõÌ:ã€LqvqD“팽:2Àõ,´m Ë%ÀìÔœ³ž‹:ØÉfuV £Æl†'ˆ5Ùæžg¦ó×ܧƒß÷üït2àVlDpM;ãÆY+–“6øâ2sÀÇ#ÛÙ)ûeA ¸ÒŸ¶X¶^šéY×îÒ¡—xDƒÏÇß¼fŠ“zŸ÷Å®¸öšÏÖméÙÉ¿Ã{{¹³ ¶Ù±œÆz ÎÆÀl6XØ=ãjÆ/—í&˜ %–½šŒes³ý8}ýw0ÂjÔ?‰+7vMYÈŽm}3?F›5¡TMÌØ‹í48ɰ7æÛ›ßFá: «¶G†mÈOcéݤŸÍüD;ì¹fÄ4AqU›5Hï`‹1[!Ø^o†¾Ö(ÐÑ}çãŸàŸA‡ƒUw ;#¶vÌ}%6†êÙ6w ä\l-ù”¬²¹ʺwoÈÉYK]ZjNz~¯Ý~¦qˆ(Þ±õ‡x/Tm°GdݨÚNv>Ÿà1ã4È~µÆ~mãBHÛžƒìûýõ?̾ ‰ÃD‘u”H¡¶ß¡ ÜÕàe#^ã°o;GÉ6ÍvÉÿÀ®ùkqi6¨NÆ…ìÜþöm[­'tЧLÑ×ÁRöþ}Í4lY¿dßë|dCMËÚ¢e:d–@3'ÁN¦oƒ¬NêQî ÷48C0ñl=wò0CEªE-ƨ{€oö*„„Zè%Ö»€fH;x"ŒðÐ`ÒÕ é?›Ð°1Á9å›qç^fÿÄ·M–ŒFÅÔÿø.2¼ }¨ú.‚˜ ËdäÚ›MÓÒ:N+ ðRènxˆ¿TÉϯ:ä¿H¡õL¯B 3YæãúÏ>'¾šŸgÌÃû¶†¯\½÷õ·±u°˜b´Z«àvx(Ü»ôF0ˆl²uã¯ùP¼ŒK7PÇÂ&?FyV¨Ô¦,Û¡·®ÊԣˠIþ¿$Æ~mñ“ÒÐð!?%µS¡ð¨Ð)ŽwÍÓ€œ³‘²Mú{iYL5>™³& …ÀxK§–Æ £€²*´{°QÄÅfd ¬·†Ÿƒ‡àÉçM¤Ýv Y &7N) ÅŒ#›{)އn‡Èp¸š˜z“üy¡šú§•ÿ¤ ÷Žª?ÌÙ±%cÑÖ„>l– -QSc!¿?¨ÏäBÓ#åä Ó0B“„Üý­‹?ÌÜÙ3H~ÒªÃdL\OZ)} ŽÝ)YØPþÇûF¾YCÔàr©XžýEC ÿJ! ÁÈ>ÑSÞc°¡¥òÿÄåAHÀ«QaJ#ÎÈZÁÂA–yŠÕUiÍÐ ›|i§±#ÓN ”〞¦×›†oÕU;-äH^¤L;ö‰–0´ÿ¾?‚ynLlRƒÃI¶†²JæÏ0zì´7šòo¦úÿVѱD04ÖD@ X`¥Æ¯V£Éoë;×™ÑK~t·=̾¯F9öϬõÀÔZ‘‚؆ÔH˜7Ö°örü5¬ËJ©ÑÚï‹",Aã1Ó¨ÚD¯‘µ@<6Xº‰Ò’úãmæ:Èo‹qR(u¤NRø¤5(–¼cå› í eÏpQ@Ùjp-UãSߌ@²1(›`5ÍâçZ‚}3 kjéÃOz}8˜Õýäóh°]5%vñm“&®—w 5âIåB#óW“þšVÇ{ìI!_Ö„üþøÓ_:=N¿ÿ?Þ2ղԲŜ зA 8~PÔ!ì„Oh«m‡€±/:&Œžý3änö·ý³±ùEþào/´ç½÷ýû÷ã}üß~Eì¿Ö¹»u`ÿê0Úø¦tˆA–‘s,I5 è‚‚ºSÎýj@ì÷ ¬ëÞßl^Fï×!3Æ|Xoð)ù«Ÿæû’Ö_@ld’ïð¯¦Tî­4¶¨¶ò¶™C}À¯–q<†fTí7lÞ˜ôTãbú2žß§TžÃ;¸0Ýfå[p›²C ~ÿ~¼Oáë~þbæ“Ö>¸í‡Ã+Ñö›F5™¾MðTŸŠC´’áò|ôÏèU‡¼ã׆}Žþ*¸ñ™¢cA`S>®ÿsÔ«ŸgŒ}|_ƒXTÊe I+¬Ì¢­rýñßF& €è"‡l CÊo±\Ó¨³A²°aß =ìTñ×Ã@³Bl2ƒšž ‚޳\ésÓ«¦»“µGǀȲc\X–šÒà‹éñy¾dNo+Iÿ‡^þŸ¿ƒžÀ^ºJƒï[’ªþ/ÿ‹¡…ß¶÷¦à¬Å²6KmÝxÎ-®ð×Tê=ÁwoTZ5B£kñ›‰ÔœÚm´ç•4„~=•éOÚšfy­ü6H»9Ñ«N´-qÖ‚=5ÜÃL66äaQ¾h²RŠ735è0ÛǶ¼~m`Ð s‚iY ioMòK-8‹³70q5Lj0°¾* «îq Ó}ÖiÜ!›Mt7wô'¸FW$jᓹ=Ó91#È,v)ØÞ0&²Ú8nôíAªÐl·æR%W¾2“B*ù™àx¯¨]Ó”6!Ý×R¨7¤I«l 8j†ÜÊ…èJSv©)™mªûeêG{ö\3=ð\$†Œyh£æÏ£Áæ]ô3ù_¦‡½'¸ìL.j¢þ4ÙmêX „«¤œY¹t_,|!Ð- ±G²ÃÔŒé@§J…n,“qTÔ Ú í•)I 'SÆ«)ãf<0ö Ú#ÜjðLÄöuwî^¦ Êú’ €c²¸e¼+ö­tøg9ÓÑ%ƒTmŒI­Ùž„7¶#˜4Ø4ex%;GCD¦C}æ`…ú©Á'vÕžª4½TJëâÄÁ) æCü>2¹öRýV8°q/tö"âðo@:¬N_¶­ðÑùzà¤E› ãÑh4»€|GíoG>W”²­•jlN™':Z>®³¹Î‘½…lÀE…6sdcœ0$à‚±©gãf œúbç3›²ãþîÖéJ$!ºtP¶÷ÍF=âDç<è‘¿}6!¥3îOëB, gèÊ;"c<¤e¯ÔD7Žâa#Ó3)LȰxáãj€ª¬•hË&~Þ[p®ëœä\¡•Rõi¶†¥0²b ò°ã&ÄÙë1wc§«bóÂó´aŽ`ŽÅÏpK#vRŸcMÙ6vì·d„mÒœ/Æöl•^LFQ 7[ÿ+Û›ZßÙÈÁçµ¹ÉY»Yq†÷œF?™µÁ•ì2˜ù‘a1´tc÷¦¯ÐÕ!ƒµÎ‹vFã7ê¤ÐK¤dã¡P3w¶å4­¯1¦|1l˜UŒÇeJÆÉþ´l•¼X¨m,7ÔÑ`ÍÝöù“½xBf" †¶hvзáu5Øâ )éuH•dÜÞ»gÈkéq ßäÚs£x{îðJR‹¯ìz-þ€L:=ÆÎ1Økã2…qEq±âhh‡âwß¿xÛ7øêÝI Fw ÑäŽMB×ìÄbu¢ÀXºèFŒÓ¯wlò¼~&0VNÇ(ó:Ñ`¢¼É‚š â‹}0M¢cƒº“kØ=pßcè&SÕú l9jU^Iü>³Œm*(&~õ…¶öøP'LˆÙ¸ Éf¥¶sÄëÆæêŠîÁWJ×ãr‹‡K“C~Ž=yd˾ºx@‹ß¯;r®îy>ºcöðɽ¡þ§»ñÛQ’Q#F0Ô b¡yEÃÇnab-qô·òkz7BK½»°g¬)+¡ç'-×kŒ£ä¯-ÇmxëK41æwDƒkA%7òh€Ë8„YŠ9Ft¨œ Ž{C)†ÍFMî‚b²¡ò­ ÅÇF€n:·aç« Èô3xÌs dBÇUH­ ²ª!ê–:˜¦± e¦´5LͯJ©ìÈ2ÁH‡ŽALoo•³˜l¤Z$ª¼ðÛ—´ÄèÔ€K‚jÒ™8…¸_ÇíäV°1ÎèENÚH|¡ ¿D56J*‚œ£„³Ú–?¨f’ž`P£Dÿ /Ðq ÀwôøF|o~³ÚJ Y#õÈêój»åc· ei] 8äHh€~°ƒÐËËH3ã–ÅÖFj|¼ÃðË4Wñ0Ø{°w ŸÃ´‘ø=l‚Å«2`{]6\1CDÏTuËžj9Òl’ëàGÑp[ÞìÒ3¾´le¤›©«Ÿ[΋È?®v,f¤@#*0|ÅDkFV…vÝ„+i)Œ— G}_ŒëÑA\œëZE¦Í±0òBÒÙu”^9D&2o2UTH«œ÷¶ãL#ö(ð€ÜiYûWÊøí¨§{`lr¬²©3£ác7à­Ò™m…¸Þš7ô¢eÁ]ÞUÙ°@@_áë;ƒ`"_[4òq{kÏ%:âTåÞÐé׈£KÍè´"΃´$#èH/¶ uÊö~€Ð’@×­˜t4CÒ£q$HÝ5eÒ䯪ð鈪—÷^¥ˆ Ä5 ì2'¦š3Ã2ƒÑ,äípš"K1ŸâJ“ š=ml CÜÎYLnA²Är*¶ñk`Þæª_ð5­»åcÅp$?ˆõ§ƒ9¸*ücÈ/i›`±¦DýbñA85WðJ€«æLTBðÚp­*1t1€5 qTDç»2$Sjö!ìYq " é¬EŽwC*@Ø|HÁ²ã Œ$“Ë?s7dÌ™È7ÚP‡©Øò—s`G£(Ð…x–§½lèÚ-µÐWÁì7ÐC©<±˜ež¹Z*„g14{ Pgp.&’7l‡lÄ+jYŒr{f3!ßùª1Š5Lš1Œ<°qÍÒà¹ðu8Œè;n0ÿñêa1/÷6ÒxaakËöY·†½ÝâK.6*|¶0‹ã†O÷ÝmtÞî›aã.Û~°¨#7Æâ-›ÕÇK7Óôk?FàÀ°ÒèX-Ì{N<ñÑò±[:×÷†“‘ÇJcâØ,2­Ü8”‚Ü6Ç€I‘ÊfP©Î âq†Vhù` }¼Q©jQ^£¿F¯8ÊäÎ#¤Õ8äÇ¡qäÇú1‡ÝAQtÅJ0΃X™˜ Ϥ«V{þ›)@)jÛ¹eåØàV+¾ÿç¶ðu\ܶÁ1|UÈ.Db ¬ÃžƒmW3i‘hÙ3L¬M¦çkp1UøÌùlBÄ`eFñ´ç—‚ ûw%ãB[Ã5‹|À“ yÍømC^eQrøå© O82¡r8¸Å¯«aRè€qârX2{ƒ?–É ÏË5I-Æ_½)5Éc «…»oQ»Å|‘#°ƒ¬…%ƒ'×7@+¦KBfZ´ÕªdãAc'v æ¸ôøÉ”!3Áé.‘L3ÍÄP ËÜÀ%¡5©pdˆ-æJLd÷6¤‹AÇ‚/ÛÖÌ¢ ¯v]ʱàFC\['ˆüTÄMšm$6´+¯_i»H¢?AèXpK1Ñ_à¶þvC¡šKÊB˜ •ý3㣇º0¦ù&1¬B™Ë6yhŒðÑä³éNBö¤f¶ˆá FB9D©’´—²˜z’ç‘K€3ÿ\ ”¬’¹y• kÇ”áOÈË´;' ‰æªU£ï$D… ¼ $V%!à\BŽ"„gÍ!üD¢HìBJÈ̼›à¦`îø?ˆyakŠ3Ã+_夣#ʆi#P.øE *hêØ "+$ìGYTý"ÓS™f fD÷3Mo,C؇謷p¤ yÌ^܈„­ë´º*Cät+à¢É”yŽ“pê ÙÖrøBiP™Œ.g(ãæ†³}7œL8pq5€Ïçp:(F‚Ùœ…&ÊE$¶$2I¸’»¨pbœj©¼fÑB ¦-²NFû²µ-)lÍ7«ó3ùq@1쇛 ‚Ó…„VÐ&ÒìEÚ‹äÒÈ0¦ÓŠ Sq¤YÈxwv„§•P ëç³9NêÚt Ÿ#F!€ç;œî@‡ ¬dOqDsKÄÞ1ÜB ¥R‹ SÓÙ§|‰§Ø%E:!.0ÚZèRÈÈ¥AÛ6Ú¦ÓKžÝõí9ÀÎPž5&2Ç>#%8‹=éþòÔà[®£ñ%ä7•yÀ[’|ÿ*ë~CžB²_ÿ@þ¨_%É'Õølƒ}@£ yDÆMýïP,K&Ë̸²Q f0èÜü®î¼1‰ºS¥½ " v¥2åI½[Cõ†ãC—æJºÞ8©ÊïþLwî$÷ŠùäÅí×lÂp¦ùrìù<ºò3³TÞÌA`ˆa;ÙÆË!Fá°Bûh ®&iš‰×xeYLktºÌ‘`*ÅÉÕJ¼?uãY¿›Á Miôc*„‰Þi;#Çfc°“`M™0à`èùuoȦÜ0E£„yˆÑñáFp!_fh8¾&µ?N®“‹NŸ=ò"æ /“ø@Ŧ1'–×Z¯Žx¦’ì›6ä… XP…Èäe(÷`ÕíŸê«o`‰h‡‡SnÀWŒ;àpD ­¦H\ÙÉÂ"d.ê@!n œB\áö@#Ãáä‘8„ðjÒ•Á gtöº ­7€05ít@UÂl –æˆD˜;| 8¸×†œо³)iƒ7Þ ³pìßóÀŠ™qbÆy_ã=¿få%g¦æT17Þý˜I‡ygÉï<Ì™nžõØxš)šÝ sãê¯=@ö–äóƒWÍffîd  '¬g^ ç´Ìëg˜)\+Cr€Ê¢Ôœ"È®¢,mÜÁ^e®7°ŸÅéÂàâÆÛ'Y³IŠ¡Îp=/)ðÊá2@LP#COǕϪô@¢ÈH´x±ä›d¥:„äÇgPBâŠçí€_ŸŸ<Ú$Ïéée‹÷Êh¤ †¬=ÉÈêÜR†“âó™§¢ì ®2í7í¶µé!‘[¬€t±Á¿!Æ5½Ì“Ô99ÃÙFBƒYŒ€)H¨ :wfö˸%Cêôî-û×5¼²© ‚&Ëk‹kÁæÁ·—ƒ–Áô‘&©Éœ´‰Ra¼có4rq'ÅE ®9ÚÉQr«§C!Í×am?•±x éÊa!1‘§, –²ŸóÙ8[R®G0áЇ|2©yUƒï_ˆÉäfÍæ™2˳ÁóôW}]ùÃ{©’ƒÈÂ*ò¢6òÁì=Òâ—†xe!øÅxÇ~úšÀúyMu7 N€?µ£iôø ä…•>?=àh!ý,ÝL Ûêq0¤¤Ë½˜]b”¨)© ~ çbÏè-QÒ™¯§JŸ¢ÀHdÆØÄü®åù J¤ôù 6ð|É—²i€ÙJëF#°æ†Ã#—Ô58 :)P‹,ÎÅÎÉžÓ )UÅ&à“‚D¡ :]¸›c)yw„ÞŽ»%Ki—•)ŽLJÑã¨ó!ßô8¯ÛG |'7£ÀUyDEF€fÝR\mú€vü]0$ñ­a°l JàAM ò Û=Ekô½'ÔL(ümòvò’¨(Ëp-!«vË:$šöˆ5ÈìÀ ˜ÒË™2º™é@ãTt<”O¦ûº5O@±/ŸÀ!5µéý“±NÀ8a?Šœòú†ƒ¾èwÞ©8úŠ…gV­y+´˜àö%wL? ä™áš‚€˜ñ<#!¡ ú.ÝÔ·}C.¥.Ògà.C­AöáÉ ;g°?ÎKk¡&Ÿºñ-}RЬB…/# ­')1LŠ9u±zQÛ˜ -£ìôK aÎMÔw žBT;«j·_ …ý;b°)ûõtÒßµµûñÓøI>Õ˜âŠ}\³7¹]˜ŒËKbåZ<3¡þ^È¡y8±k9f ó¯ ž;²]Êsôž”ÎúÚ£#ƒJML†ÕìÁ¦fããJ ,Öî!.Ç åÚìBΩðV¡PÜ:O Üo{ã GlÝ~]{{uï{ã;eÄìœr4ûÃ)M:Wçtkwº¼#² ܳÇã3Í3ù ³Ù{ñã±á©$G¤Po~òhô|ÒÅZ‘J…å䡼ù„Ó¸(:mk7ÓtUðu‚Süyfe#¤ÅkxìœVù¸É(ņë ÞÍÌì9vïà)±Íô‚ÀßöÔ JC#&ðµ—vì´ôýºP³{wÄiôÖ˜›Àãñ5í żVŸý–H4L²ë¦m£öÁ; y¢ÌpX‡ùøÔ€Œw¸fx‹ XͽúBŽ èS"…y\Sžs%ÉÚ`¬·‹“¡cøÝW‚^ Jæ 7˜_Çõ@§FËþ˜TŽˆIUYèÊǶnPå`%û"[sPHõîõÈ”Ÿ%] Ì`àmÿá·0Mê.Ž˜‡.ÖãØ±‚ZgêÅVOÑÀbgJ±ÃB¨'Uš0]ÓÖ¡?1'ZpètÕŠ©Ð +7¦ l^L‰)“ýµ>…÷$&$ˆCçý/ضEK.¼M8•6©-šèm)É]R°{°¥*_ æ@; ÐP&uv%þdZ‡YhF–=—’xq¡^Cþæb¹RŸèÃÀz=œ8 Š1ªñºjLrèÌÏ‚n»ºï¹C§ÆtHšä]ÖÓð[?¤'Ùf̤ñ5iÛoð¢6ÐÒl§ Z@÷â`k<ÿ¿ƒ©I$Ó¹JºU9Ù\`¯½Õ*B6’»M‰ µˆB+~p›ªHŠ:å8FpÝžÍ!|FñkæõÓ¬,ÞTRO’„LVÍ4¦m:S—L‹û8~F?¦N•S9ºOÖ'è7 éËö©L Fð÷lÎ|´Â%÷ ÄW1,®@ZÉŠ'û¯EAHZ+€èWC “~µ\*#5dý… «ä$å"†ÀÅŠ¥;+JÓÅ1û+,cp㘘+“Ê®bÆi”4&÷+JTwáœY;ñ !ÈȽ†›AÐÙ šá‚J“SÉÓGº™7lZ÷]ôý©žßm¼.Í(&»èJ?öb<èZ\×ÑõL5°x¸Qñ #¿1VGÞÈöiÀŸt师,Ìq×åzÂæ1+’\n%ÊÛL‰Oä;£~^\Áå¢Ûþ•";SCœ>Œ(fúe<À L3~F¬ or'¤žJÂþLÆÿ^l0£¨HÚ1¬¼Œ@wµp[EÊÔ€« tÑ-ÖÎÊÍ3ór;)3s‡—xG MXm‹þªŒŒ0•“+ë1!23‡¦±&Ú©Ë9n¸ÿ ôvr€³ÉFëºÀsH‹–ª}‰×•±»»Ïq'+†Ïb±š¿4ªbúIålxÏcÒwמåÊ£‡·‹áž%D]"?æ}­Àì)í10/Ï»ª†ÝàVá±wï2Ñ Š¬`¾#q?++yo¢š:'-s=Q¯©Å‚ ½“… ,€‡4ø.7HüúólèÌLÒë,·»Gîn×ñ"jf¹JÞñùJ—"Ã`Ð1ûéŽÔ5|=?]³1s$Û¥ŠþÇn˜ºœÄ|2LƒQ‚•â s_÷™à,'#ιËGŸ˜¦€ $Ôâ"‚yk tBÚ–*ÜByí¼L´h>eÞ-Ô½ƒŒîÓýqM*_V?€']îÀå'ç¥"ЏÍ2Ì–pa@v<Â>!š„Z×¥÷íWÁëem<`4^1¢paOG%0Ý )Ó•q¼ý ¼(ÕZXâ|‚*o•Äóœ‰Ú:o]Ûƒ„ Lž;x=8Ù¾ÕXÍ£SqêÜ…Ú¿/]8Do8¤¸~+CÎn4xÚà ËIGn x:©ÞG´ÄqãM¢Y>Á̲҅^50õj˜ L_Ü.J˜JR˜¤Uë2GöH&Ü™`(@À¥fxsgç¨&?–[òðŽ$Ö`ò¡íYyÁDZ ÛÏçG·œÖ…v*Îr5Вﺎ–HGe ÔªD\áP$ݦÅÐX+sÃZe¡±ò´Úõ{'á“,4<^Ø< GLVYæÜûɉÔý¼¯ˆÕª&ånX¬oÆ‚{׃-Sœ £ ?ÿ]µ8®[”#Ô²&78£—×¥¨O Åî> éûXär™Ì"êôëéÈ*ºzEŒdâ¨w}¼íÄO7ÇX Ó=W„Hm¿¼ GIºäþº˜.E&åÖ#B°­l÷"k°A«ç£¡µÐß3£|3ì`†Ãx•ßÊÛ™ sÀôÀ >¸ÑãÜN¤¹ÞŽõt·püÌ»P—Í”*uVãz g« =8#¢Ò››ü‘Åí¹Dz|Ò«§ªsl©ò#Åë†âyÈ—Àð],zI¤MUm&Ëå䙜5âuÁr±XdRÆï¨&YMèd¨.òŽ—ha÷JÞ.§²ê)ÔÞüÎÄ{SÁt »ƒnè“lu+F¾‚šh¨ …ƒnòAŠhcÛSÐk7IÉéñ6ȸ§Ýû@pøN•)–3 >ÏÂ+H@Î5Íßä³gÑæ³™ÁN)VÇŒØa] kAÞ9lÜ‘‡W–•ƒd$Ï]Ø«ô»GFq¹ äMJr”Ã)£Œn‰Pø8­mf‹Ò×ç÷«X}}JmV 8Æ.iƒ:U†×SÄD¶Wu¦ˆ>rç0×’73Gä¹”·gþÇþÝpSÇå³Jºzg ޶GÇÆ±FõÃïé›û²Ž—ëÌ%QÞÅ+ʸ²KÈl(^´õ›÷¨Jû+"ÃzçN¿ñÖ¯í¬ð˼gùôÉ' kf–ŸŸ·”7H‘1w°EÒb‡Q3^yßdyñÌ(ÖpÁåt&jo˜…ÿŽH9ñ9tš Ä£š÷Mÿ¼[ÙòzË[×F׊ƒm´œ§¤‡k£™ÕFZ¡Öé_¡ŽxnåÇ‘:zkà]W€ŠEAXpcë£h¡ŽI}ç˜>ZN•üÛ )n @æÒºB uĶBŠ›Î¬i-…´°:i0¿ÂÐ@½˜#”ddñ'飉­¢!—k2ªÕ"u” lÓÍ—ê^ê(ÒœÏê(;È)ÔQô^ûŽgœŽgRŽÎÉfÏÅ)™K“³Zb‹˜ºÔSàu*¨¢4dAô¨—6ZNe¤º6 °Ë…6ºÁÐF½áØ„ÇZþ“‡òɆœ>7xq*8Ã1aj9RFyG½_º(7KÊggáã ˆ;Õ#r~øÞ¿ÆçsÏxÇ’­Ž"RœÛVGã|P=oˆ7U‘´=Ò¥ñÜ Žbtr ©£œÌœ—>ІūdÒG9ÿš‚bu§ôMqD4x(H¿£ük¨£€Ì0¹©£Ä¥|½ƒ›/³×ÕÑ8¡[Ý [ÅœÕQ ÐÚÖGÉJ¿ôQž±ŒB‘t}0݈¡bõÈbw}`QÕK裓~=Y¼P´õÑkê£o[ñÓÝAI„¾K`äÇãÖ`Ê ÁÉ{1*‡;R,N¯\€kÐûò+ót½µÊ»÷‰VÇ%r•JÝ¿*{eÑó‚IUºç~`ñÑÅ~Ö3õ5ýO“¥_„¡3ãNp.á©;à1DÕˆÖÕŒ³_þI»†@ROÖ0»+ÅÏÎT ö&Á‚¼g€ ¬¿!ÂÉ…`ŠjøqCöVÚ\chú¼ü¨)à/Rp{¡éƒðAêé–7s ^–8þ<YEë&·Ëöê:L¶;n?Ó>›»¹Äêgˆæ ºDƒ „xx$H8Œ ¿®H‡k™ºçY®u_•É:x¾õxÖãÈg? -/i0$¼ 6U(¹¨ °@öˆ´H€¬E×T}Yϳ|fã <®f«2°Ie¼=øQ?Ho0ž!o Å^–;+qÑÀÌÚÊ|5ÇÁ©æ)‚K—h÷‰á}€'å"êʱ3ÊÐɈN‰èûÉû¯œ÷H©«"qkÓc€Añºií yL2Dõõg÷UwnRµ“¤r†“ <ˆGˆ”¿6ªC¸(êŸê˜zV«r¢, BÆ ¼´;í±3^r%bÈýpyXɲ,ùçV•è¨}2íä×7™'1Øã^põCüjî€ÒãV–¢„/à**Š”ô5¢qJgpS(#w*9`— ¸5Ïã[(ÈKxW£‘¹®ÓÎÄJŸËz*ù@((Ä„`ø­Ôï³xî[~§>GSY‚ËÔ• *ZÁÅw±7nïì×M¾x‡ýÞ½K‘¾J`rÇ^sß ñxfR¤¯[¬á†–øV ng ­šÍ í-\%Ú•&{Öt‘ø¶«º¾¿w½Kõ’øD2?¥"SÖ³¾<·Ý3ÑU©äwfàÜ8”<–§ÎtÓµXÏt,»F¹-x£.³?w&>ÀGËS½¥.<¸g=¶ƒÅ»xãPþß’= Ìe4n‡Þ¼Ç¨üÅÌÿÙY!&ðT cfI\÷Eƒ #¸”¸zŠ”+€¸ŠïÉÏ/V*;«.ÿÛ(½2RøK6Å釬¤\TÅ´GÄg î|}ů¶‚Nš|8èHßGRâZÉž¦©†Èúî¹0)YâLþJ*^yÐt‘ÊéHõä Zß0‡Õw·øL¡{«o{¸¤HìGª ¾É>VñO4°$©· ¯— ´*س¼œœEŽ¥y>øÀTBX©þöTíÔh]YûÊ&Ãl"MÔsuO’&Ò_\, ZÄÙ=Íò¦WÞ›¼©…‰UÛ< õNåç¢îãJà%õëR`y8¦g 1?<ð¦ºÒVCÏÁr®Ã(oêÛÙä FÑ É|?»A¹]@ ¿!ÍÝi‘8/t!Ëñ`FV%‚\¥ŠŸ™[çÐÕt|ãg«ÂËOä1ÚS=¥·0mQAêÓÑéWÈz%žw#°«or¡8Êf´ré‰^~²+Ó‹åÌÃ3NýîI•Èrã¹ÉQsü]ÆððET]"mü"Ï, W !=PH_î2ªté4Æ"p+\7ÀU4lÝã]7Ž[‹\©×;ï ÛãW‹égø¸¿‘â6Ç[ƒBsW·‰y§~Ü[”ÃÙö‹WUK•ã¦l§IÕ§yp᤭^ŒLÐP qéà‹ Š—ÿ®²²äÛuc%Tä-ƒšïŠ|æUßš¥|¬rù"go¸óà}¯±ýHž¾‰;Á*ÄB¥¥\P„JûýrÓãÂS=šÊîñþ~„JÑ@œ3TŠ"}nSbšpߪ›Må+%âL9E7q‡œ£~9¥[÷ì“xÝ–"‹ºˆfÄð3üáœÚŠd˜¹9%–†ë­ÉBÅ‹ïoÄ ‡®Qo(Ħè"±*ð¸Y<ŒÎ_w{0zßQ§Ý£R‡Ï.‚V1ûKdùâ<è+÷˜X`F\þpTεCrÙŽùKŠøÎìß¹oÇõz w›Kßø=¾¨bÏÎ]²1û#Èj/OTç«¢¼°ãDØs 'jÇg‚Òô±ï3 ör~J¾„ÔÀìyÑtë-ëÎŽG{¹¼V"ÚËZ”=_Á^àƒoìXÇö\Y )Õ »*:¡hoáGXw0wïF{KÛ©¥h8 ¿Q¯×{¼ÝIÕD°Y³* ÀÙNLüÞ„¯N×céóŽz§¼T/Ü-Çê¡¿÷Ïa-O½áùèqî}@ö}2G„ýc¶;î«ñ¤X«§.®œƒ@–'%.#(b/¯þc¯÷ø¢„=;QÊmö¤¤ÛòTMx/^”xÃ(uãNtˆõ½ýŠôM t–£ÚU8P¯6›TD&Òaª 1w}3ýS?¬›f»j»N© -*wU³ŸNZÖ/6 I³ßj² ¥Í~=àuX­ lÕ¨æ¯×-|cË(ø\†Ç=Uâ #Æ[ƒCṡëú8oC pˆï¾IÔe”ÂOxŒ¥Áƒ‚±R'èõaä¸Cé ‘œ"H¼Ò„"Xí [ÇÑF]Ñ÷÷³½ô{á;ǹð›9óÊq.^OËÊTÞ¸ç8£20¿7½sœËÔG1=Ç ê¤zŽsÁá|¥8&,D†3 ºüCØP‡çyF†sÁêU#Ã`öê<ü°÷6:v‹2œ÷ë^‰;º g?2œcrIWcîžßÌ•õùÍ\·{Àt•rá9ðöZw«Ê_ÞXüæ2U¦pç7GÃÞ[mÜqß]Ô0Sª­r}ËÔçj½S*9Ò›1ßSÕw”ÞŒ”:Ь6,׿·¼%jB³øÖ¦¤TBR¢á¨Œß^×oÝ7~bøÆ•O ú[ ƒFõµ=CÒW–†F÷u'÷M^’ Úà†>•˜E¬:¼U‹Ý ƒ&^w½0zß*»~„N“s?f¿M‚Xœ› ±ò¨…,ÌÜ.†êÜ" ̺Á˜ßMìL\ Û¯Ÿrcíî}ãc|§Š˜ˆ&НMT±:§¹X»“ä…'Ù@žúظýLñ*Ø­›·C0£ËÞb‚ïš “CkÇzŒpWë¹¾¶BçˆräÛ¢AÙ •ׯ¶Epæy³hXK~l‹¦ú'¦ÝbÙÛ «¥—Ë¢Áö ÔÛHO¾w^Yåm^#¿^s«JöØöLet¯nÚ½ðÔî¨wÂËÛž¸Ò6i¼Naéßñª+çÑõVÞ}äÈXöi¹æÓÞ¦A,ËM‡X´Ži½‡€’ì „ºÙ²9O˜5±!ûwm×±_ç†^fMlxŒîässr¹æ.rÚf“[˜5AŽfœ\sNÌŽVAÇ/éßä‚ßÃvÿßVð× ùw`ͪഠ|T@åЦÙ·fOÁøÒp½3"mò­Ã÷wöD¼,q®{ƒræðí‚“õ UW•Îh]wñmÚ !©šýf¬|ò•vÒº\ô5÷ðF á¨ºí¬Ã¶øsSòwâ5^4x+¬!ܲîÁ)Ÿ"<8¹å,šscÀ ¢3îb+{éC®­+û ÌmPÕ¢šu*87Ô´qçÜÙCŠñ{Uú“2½*=ï3Ôê²jR"Õ[<•ÊÎ:Ë Ïž£ÀÇ‹ YŒ×ñ+ öˆX?Ñ÷= }”‚ŸSSbf çrnp¸»øøþ•JA¸óÆSŒn‡àÍúþKÈe^m±w ;:hkÙJ)ôqe¶ßÔèQk«3%…¾}×·×Ý?‹¯/¸¾A}į‡:S”=p©3¥í"þÎ/²×ë=й:S†ò~}ø©â£>5e3ÞfŽòë¸V¶Âò¦:ƒÏAçË? ¸ÔK©§âªŽT7–„Èõ×C"{ï—ÄöÑÃ?ë³Ûßg©3¾¸P|åûÓ=òÝ?ë¸Ûúˆc6ˆÞ1 ß™ý;÷í¸^×Î^êŒoü?…v¥Ù‘hn“'M{uNs¡ÎD¶T÷™…Ì÷©_JAÙUy¨4øÂC¥ ^Ž›Êáx •ÄÑK0Ÿ­Ñø¶xû¶_/Ê\¹ºßuÁ5¼ˆbOND£ÉNdc\‹#É]KIÞp#’ݸKÛš"fÓgcê'gÀäB-qAXî¾Ê/ÔßT ·ÐáYç½5GwñlÀÌ•'¤"Ɇº'¤Ö©ð´E¶+ª-“€ûŠJ‚Nàü¸öEàŒœìì°:²ª<îAð³±5ÒÃ*JE«ÒÃzEéa¾ß€ÄRg7=U€ß ÁEJÙ³R9ükžÐÝMn¡ {†XÀž"F0E†ûRpQbÀ£WÎUFZæNõjAm}è–g¤ˆ³EYZ•¿ûGd]&Û¸ës(—0¯ŸÓSñ]~¼mxáàHC§'ˆ³Òƒ!f׺2İ<ž4Ï«£ÄŒRýõÙ"CŒÛ¦ë,þµ2T„¯QlOÕUÃq>¯»·/®´Ž±óê—ìͱ«Øç¥9öŠ,Üú$àéaNß·ô0€s×HSTéaq~vzXœ¯HÛçÑuÇÏÇS_ )b‚‘ï´”Vù!úéaÜÝ8wepð³‚JéJÚéÕwÏ”„€RrÐàUöâw¯FõK‘Î[‚ K^WDĈO©!´C@‡©\ bD¯ÌC&ˆ>¥D!A f™ÙH#þ•uɯF%ˆÕÞ#?w'ˆ}A¾06Å–¶çdèë‚—Ç"¶ïdL5¶.‚[Úä|ÛU‚bëó+¼ß˜.p¾4\žeOCðå7qØÝ&óô´}æ ¯`W!´°4ž»MP¡Û«p€Ò£¾÷&]Ö^¸ÿÜXuÙ½&*­póšÌ9 %ø—¾Âm‚µ•p›øã«ÊDs·Éô{bî6™ÛqA· ÆÓ53w› ’ƒê#Aµ;ø§}°ù§ë½ïâP¿ŸQÃP UŸ¡p$®ÆŠK÷t› åA†ÛßLHw· 꾫’ Ý&(”_‰+ºMPìÀ3bW<ž®ò*Aá6 0Ü&ß¿R¨-¢¡µÞ´ã©šè7zÚå¿•¶€†¢Tí« žÇ€¯1›S.ˆ©O4î<|¥KáwZ ËS¾\º®…@â;eÙ?vß1cµ }rkùg"‹?ß¾ƒ¸—âéêKÅvãGÑ”oá\feiCJb¨^IÜ“ö¬ºJb@ qœR̕ŀ…/%€øGÚV8q6§®¹~nFüRY Ѱ/ߨ›âõ¾u¶›ø¤3^:yYÎvs1Ëž М?{/4¿Ê×Tç .¾Tb·UqI ðh~ï&dŽÒΤåDŠß‡n4¬} PNÄä_„dzøIå$;jMùS2‚x1¯cêª>/æwW‡xåBr€Ô8§ÌÕï êC÷/Gå‡&—®£ðë¢M_0ó’ÅÉg©ºbçÕ¹ÊÏ•í A%€~ûT¾ ƹ·|°%>¹‚Ï…¡~y!U ÝU1¿9bBøˆã)5AóÅ'ÕxM#îmð‹zº.¨ã3fõîGgL±Ó½YµÐç•)Ë8CL)I“ˆ5%æ¥T\NÞ-9ˆ#~E‰Q^ŽÖ§É–îã-qClïDWÁ’C{òjÒñrò@Ã(ú„$Â:ªKéGQ¥”Ç;SúU·q â¶éëDÓ/×èÇØýV~(lJ·_úžöäç#ÈßÈoÇŸÿ í¼Å­ endstream endobj 4 0 obj 15625 endobj 2 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> /s6 6 0 R /s8 8 0 R /s10 10 0 R /s12 12 0 R >> /Shading << /sh5 5 0 R >> /XObject << /x7 7 0 R /x9 9 0 R /x11 11 0 R /x13 13 0 R /x14 14 0 R /x15 15 0 R >> >> endobj 16 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 512 132.915924 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 2 0 R >> endobj 17 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 41 52.915924 73 85.915924 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.19 /ca 0.19 >> >> >> >> stream xœ3P0¢týD…ôb.CS#=KCSK#c#cc…¢T…4.¯Ù˜ endstream endobj 7 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 41 52.915924 73 85.915924 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x18 18 0 R >> >> >> stream xœ+ä2T0B©k g`ab`nj©œË¥Ÿh ^¬ _ah¡à’ÏȽ & endstream endobj 19 0 obj << /Type /Mask /S /Alpha /G 17 0 R >> endobj 6 0 obj << /Type /ExtGState /SMask 19 0 R /ca 1 /CA 1 /AIS false >> endobj 20 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 46 57.915924 68 80.915924 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.595 /ca 0.595 >> >> >> >> stream xœ3P0¢týD…ôb.3Ss=KCSK####c…¢T…4.°  endstream endobj 9 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 46 57.915924 68 80.915924 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x21 21 0 R >> >> >> stream xœ+ä2T0B©k g`ab`nj©œË¥Ÿh ^¬ _ad¨à’Ïȼô endstream endobj 22 0 obj << /Type /Mask /S /Alpha /G 20 0 R >> endobj 8 0 obj << /Type /ExtGState /SMask 22 0 R /ca 1 /CA 1 /AIS false >> endobj 23 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 65 31.915924 91 56.915924 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.19 /ca 0.19 >> >> >> >> stream xœ3P0¢týD…ôb.3ScC=KCSK##3#S…¢T…4.°JŸ endstream endobj 11 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 65 31.915924 91 56.915924 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x24 24 0 R >> >> >> stream xœ+ä2T0B©k g`ab`nj©œË¥Ÿh ^¬ _ad¢à’ÏȽ # endstream endobj 25 0 obj << /Type /Mask /S /Alpha /G 23 0 R >> endobj 10 0 obj << /Type /ExtGState /SMask 25 0 R /ca 1 /CA 1 /AIS false >> endobj 26 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 69 35.915924 87 52.915924 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.595 /ca 0.595 >> >> >> >> stream xœ3P0¢týD…ôb.3KcS=KCSK#C Cs…¢T…4.±© endstream endobj 13 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 69 35.915924 87 52.915924 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x27 27 0 R >> >> >> stream xœ+ä2T0B©k g`ab`nj©œË¥Ÿh ^¬ _ad®à’ÏȽ & endstream endobj 28 0 obj << /Type /Mask /S /Alpha /G 26 0 R >> endobj 12 0 obj << /Type /ExtGState /SMask 28 0 R /ca 1 /CA 1 /AIS false >> endobj 29 0 obj << /FunctionType 2 /Domain [ 0 1 ] /C0 [ 0.188235 0.443137 0.670588 ] /C1 [ 0.0196078 0.219608 0.396078 ] /N 1 >> endobj 5 0 obj << /ShadingType 2 /ColorSpace /DeviceRGB /Coords [ 121.590797 450.859406 367.959412 24.1366 ] /Domain [ 0 1 ] /Extend [ true true ] /Function 29 0 R >> endobj 30 0 obj << /Length 31 0 R /Filter /FlateDecode /Type /XObject /Subtype /Image /Width 19 /Height 18 /ColorSpace /DeviceGray /Interpolate true /BitsPerComponent 8 >> stream xœc`À1DXyÄØ9Q„™$=’œ5XBæ«.ž?;+Þ„&Äî¾ýûïßïnÏŽ–`‚kœùñï¿¿>ï)Ôƒ©ã=ôùï¿ÿÿ¾]o2ေHä\ýúÿÿÿߟvËB-aTÉ;õý/Pì÷…"I˜qÊé›>ýüÿïß·ÍœP1ž€ §?}ÿóóRªÜOšÑ“.^º¹6^áf6-ó¬Âp5d¯1ròJ ³(8»‘E endstream endobj 31 0 obj 185 endobj 14 0 obj << /Length 32 0 R /Filter /FlateDecode /Type /XObject /Subtype /Image /Width 19 /Height 18 /ColorSpace /DeviceGray /Interpolate true /BitsPerComponent 8 /SMask 30 0 R >> stream xœÁ ‚@EýÉþÇ/h´h%´›y:øP0ÑPH©Ål¢o°ˆ#há].÷<žeMËŠ¬ó2ì(Ð0ð’/r(Dä!#1ˆÒ¼,$r:hd»<«Î][J€™f„bÙ)ukdì;ºFDV÷çý$£­>ȺWêzLÁ5sdE{éš½Œ6Yr!U!ãYƒ³åˆ)Fœ˜KÞ^Â(§cëÓ$~³‰ù›xi endstream endobj 32 0 obj 180 endobj 33 0 obj << /Length 34 0 R /Filter /FlateDecode /Type /XObject /Subtype /Image /Width 19 /Height 33 /ColorSpace /DeviceGray /Interpolate true /BitsPerComponent 8 >> stream xœc`ÀјعؘPDXøä´äùX5ñGåÆ˜‰"‰±©æ¬Û³¶ÎN˜nÇü{¯ªµà‡Y¢œwèÓŸ/¶eª°ÁôôÞúùÿßó]xaB¦+^ÿýÿïß÷óù2P—°ZoÿôïÿÿÿžÌ²å˜Æé¾ ,ô÷ÞD)ˆ2nÏ­ŸABÿ~\kÑ€¸ËiÛW°Ðß7+MX!Ž0Ùúÿÿë>°a¬¦‹_þ }?ž&ö›aßÝ_`¡Ÿ—kTÁ†±¨–_þ ù÷û~:X£h̰Ðÿ¿/gjC¬ätÙúá/HèÏó¹æì`!vãI÷~Ýÿl®5ÄJyÇ¿@„æ™AƒQÀmÐãÿÿýy>SŒÌJuW¾ÿû÷ÿ÷ Vhà ù-}øóß¿¯Ç •`À¡™·ãÅŸ¯Ö‹Â⎉߲îàƒGg[Œ8q+dW½|ÍD_qx$"jí"ωãâr¢ì¨©€‰™•…yª»_ endstream endobj 34 0 obj 381 endobj 15 0 obj << /Length 35 0 R /Filter /FlateDecode /Type /XObject /Subtype /Image /Width 19 /Height 33 /ColorSpace /DeviceGray /Interpolate true /BitsPerComponent 8 /SMask 33 0 R >> stream xœ’IRÂ@…¹¤÷á î²bßU¡çt:&LA4&R(Pê "&a¥ÿò«×ÿð^×jÿ®œ( ~F̶q`ž" ¢œè$œ1‚¯@Eê3!uÎÈ«N„ê¦m:W+Ù^$Ý^àšR+ÔáV0Ež›‡ NÏâБèðPéîI˜B-eœ~¼\eÉ +x‰ —þ4]¿fOÃJ¹þôq»{ºíKÞ*ÛwtoºÚ}®ï#›“b ‹³í׿aäpX43¡æŽ–o›lìjô¢0 P;Lž·ïéÄÒ"½iúò¼»“]"á çiš 4Ê-šÜêÇÉ|9‚•'å-¢;Ñä&¾¶x§º1Ó ‡¡'Tþ0*-¯çw­ì©5ÐÞXË’ ³« ʸ.‚¿ÉåïSÂðè~‘ ¦¤Ý> stream xœ]± €0 {Oñ;ÁN2#ÐÀþ„H ¡¯^§¿ßIQsÌèFÁ|R¯¬^ØÌÙÔkÕ±ÂKa‘³hë–>œ mM/Nr+ó·ÎÆ[³¿|ù½O4П@ ö endstream endobj 37 0 obj 101 endobj 36 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 21 0 obj << /Length 39 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 46 58 68 81 ] /Resources 38 0 R >> stream xœ]» Ã@ C{MÁ hù>’nŒŒ&va¶÷ŒK‚°"yÈŒžsÁôT,—cJÖh†Õ¨‘`A׌ Õ©%££ô™3jûšòf®´Ù‡Ê½~Vxý¿}ÉCnåcØ endstream endobj 39 0 obj 102 endobj 38 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 24 0 obj << /Length 41 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 65 32 91 57 ] /Resources 40 0 R >> stream xœeŽ;€0 C÷œÂ'é'M{ ŽÀB`î/Q¨òYϲ³“í£b˜õ¤¤\BDŒœD±ÁŒMÂí};+,³“‚à9¶Øãե΋°Ï z z@YœïšØòÃß/¿féÃ"= endstream endobj 41 0 obj 105 endobj 40 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 27 0 obj << /Length 43 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 69 36 87 53 ] /Resources 42 0 R >> stream xœeŽ1Ã0 w½‚/`­J¶ägô ]šíäÿ@ÒÂ…‡Bq AqÅç¶—{Á²KëÌRáÎvÊ´8Ù˜¡x!’Z:¬ÑÊàôœ~6º:dÌ@¥¹Ï‚ze×/?ÿù7á!79’Î"o endstream endobj 43 0 obj 106 endobj 42 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 1 0 obj << /Type /Pages /Kids [ 16 0 R ] /Count 1 >> endobj 44 0 obj << /Creator (cairo 1.14.0 (http://cairographics.org)) /Producer (cairo 1.14.0 (http://cairographics.org)) >> endobj 45 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 46 0000000000 65535 f 0000023749 00000 n 0000015741 00000 n 0000000015 00000 n 0000015717 00000 n 0000020004 00000 n 0000017040 00000 n 0000016587 00000 n 0000017951 00000 n 0000017498 00000 n 0000018861 00000 n 0000018407 00000 n 0000019774 00000 n 0000019320 00000 n 0000020650 00000 n 0000021702 00000 n 0000015996 00000 n 0000016218 00000 n 0000022307 00000 n 0000016980 00000 n 0000017127 00000 n 0000022665 00000 n 0000017891 00000 n 0000018038 00000 n 0000023024 00000 n 0000018801 00000 n 0000018949 00000 n 0000023386 00000 n 0000019714 00000 n 0000019862 00000 n 0000020228 00000 n 0000020627 00000 n 0000021061 00000 n 0000021084 00000 n 0000021679 00000 n 0000022284 00000 n 0000022592 00000 n 0000022569 00000 n 0000022951 00000 n 0000022928 00000 n 0000023313 00000 n 0000023290 00000 n 0000023676 00000 n 0000023653 00000 n 0000023815 00000 n 0000023943 00000 n trailer << /Size 46 /Root 45 0 R /Info 44 0 R >> startxref 23996 %%EOF photutils-0.7.2/docs/_static/photutils_banner.svg0000644000214200020070000012633013504422775024433 0ustar lbradleySTSCI\science00000000000000 photutils logoimage/svg+xmlphotutils logoLarry Bradley photutils-0.7.2/docs/_static/photutils_banner_original.svg0000644000214200020070000003743613504422775026327 0ustar lbradleySTSCI\science00000000000000 photutils logoimage/svg+xmlphotutils logoLarry Bradleyphot utils An Astropy Package for Photometry photutils-0.7.2/docs/_static/photutils_logo-32x32.png0000644000214200020070000000407112444404542024661 0ustar lbradleySTSCI\science00000000000000‰PNG  IHDR szzôtEXtSoftwareAdobe ImageReadyqÉe<ÛIDATxÚ¤W PT×þÎaaewwQpäµ ò¨ƒ©±¶¤˜„Ñ’¦Ð´3u™Nf´“Nb§í$ÓÎ$mÆ´i’JÓv:MšJ§6ŽŽŒB4JRÌ¡€°°,( ¸¼–ǽýï¹û¸ ¤ÑÊðï½÷<þÇ÷?Îùîá/jçadXeY¢/²¬ýØç.ÿÖ~'<ØÝ ¹¿¶Œ„|‹Hyn„ìTÂ7f§G=}ürþÊëö{VÀøÀ3ÕÄô9­PU ¤úŽÀ{-®%EÜw­@ìÞcVâð±)Ó2/ë‚[Ž€qU$Ü“1~q!ù3•¡7=w‘-ZþaÿKx\ù³Õ`ìÏŒ± EW#ób¿®)|)_ªÀ‡j¾­Í£ ý·nã‹:'º¤5ª]ŒÑ¿úï@$M 3\_ø¨ãsˆÿÚs'Iãj¿ÙlÙ¸…FnGIÎ&¸§<ÂúÓM­(ÍMÅ¥ëÝ„J7Nϧ.±^Ò¸Kâ†]s¼&Э$<ᡫ–ÌHð̘DkÊ^”oJÄW‹2‰¶Âvc,wÃ-¬o•Ö‘±\$Õ<™ƒib†A6ÑûIúÈ_щûr„;*PôTÀœx[PaÆ©K6Ü_Ž÷.·ãüG]ðÎ/ÂûïsÂ=ÍR’r¨ðC%›Ã£ú.äêF`“â•ÉDe[ßBsKI¼PYzID¯BL…‘ÉŠ*¦ÕQÈIKÂ÷_>%"Ü,ßF ëƒ ëÐ(Yˆ¯o­õïUè±ðœðZ‘Ç‘6…¾ÅeÝÓôSÉ•/öÒ†K#8KÂŒ‰oó:ª=ÑF8zz) "ÑD‚…Ÿ¡‰xM”ò~ôIä¡4/ §ó .Î'Óeò˜üây‘ãøŠÜ¯2k—“Ð&¯W… û‹eªë¸,üü¢ñCŒ7ap`œË `âs°ìÞ [·¹›7 ‘¾ÕìàÊö2%bRõ²‰qþ4çY¸‰Jùcšç" ÄýÄ©™ãDýºì<øMl~ð ª"ÚĸÉ'lbzŽa7”ªÊ7ðf)"có¾r€T:`Ä,òùë P:qí<9˜ÏœeHKŽÃØ„'˜ãDÍ3±ˆ¶Áz6 ׈ŸÈ ØÍ{ ´ö AŽÆë7 ÷ŒÂ£ï¬@€´Q­'_;,%8\± ±ñkEdsŸ?ÅÌŽ‡×Œ¢}ËúÝT:ŽÚbð§Å¼à>¢òâl‚?׸o,ˆO«~Ußêƒúð0¤lHÂdæ.d“BèiÞŒq)¶=\%2ÂÂÆU8y!Ó(ìGçgO–cÂãEn˜ «q§²‡q+÷Yà [ ÓX¦<3H4EÃÀfã(}Ìñ&ìKÆÞÊJeY°÷@%*¶¬FjRÅD„ˆ •T^FÊýI…ª’>”aá“@¬¹m*ó§½¢@‘û ÎÜ‹›î™€%Þ ƒcSxut¾Ýùs¼ÓÛ‚¶†³xƒ—*gŒH·`T3(‡ £IN…¡µO~}‡@Ì(uSj‹R¢Ñ§ lƒ2øZt^¸ ƒäAO˜ÚyeÇÉð2 ÐD\ÔíG.ìõ×…Œ²W/ň½yF¸ÃĽjuUôûе>Vèjø,HŒÊN4uñªŸ‚i#¨Õî ñ£ßMÚ TàWçÚìð÷Ð7î±÷~ÚÀù²<çè· CgãJjîY´a‡ÔMÏV‘S³ó¡u€öÄ›V•¨–î3׺`I0Á⺎÷ÙV­±õE5C ‹2¶c± {>Á¹+:Œ¹0?ø8jbû±è F?Ñ—¥6¼çÁw¤FŸ1*RÅÙ)ÈN]ׄP\Ë›è¸8Žia‹z|ùý§ÁÉ .±áTd ÓE$;G§ñë_€³êqŠæ8Ì„¯‚‰î% X¿q†h=Î^ÑÁ5> ãŒm}#4v&¨¨)1á‹‘º[õÏÚÅ-ë{¸Mƒ&íA²o¦çbËp¬²Ÿ:FÅx 1û´D ¶ëqV—+Î\À£ÑhjëÇYž-ÎŒ­„Ò8ôTõbñÄÂ%ʘºi>èÝÚ÷„ÂG2 «öe=ÈÛq®uÞÄöoGù}iÂÂSt!Ógw7œÞxjð¯Çü‡ ÎW$~OªUCs0`†Uz\ëº%”8ï™ÃÕÿ â/lÄßš:‘ì;Tü¨OÏRV¹(ãï†eâF$Õ ¼}´N{g핃 u|IJ6·t¢¢h³PBñeEqºˆæê©éÊžIÆÒ”¤®zŠ68þòLÍÒ˜.x;eµ´ºŒTÞ¨ p!z;ªœÿÂäh":œ³¨¿rCX#Mcß| ÞŠÚ­Zå³N^v|€ŠÀ#«yíç6&yGÞ¶Òã 2ùo´»fš… *,Šp…é9}~èÝ+4%Bñ~¼ç­ÃÏßqgd­}ǪÞZeëŠMäÏh>¤ŽHiÍ触ûäS wÝ’&zQZ±•„.·^ZÒÊÇ;ßønÝ=7§¤ˆrG¤žgërÈV+mW=Ñß;^«©¿›f÷Ž›SŠ“Pb9öÖÙÿßÿ¿ æ(HU¿Ž’ŠIEND®B`‚photutils-0.7.2/docs/_static/photutils_logo.svg0000644000214200020070000003625212721610567024127 0ustar lbradleySTSCI\science00000000000000 photutils logoimage/svg+xmlphotutils logoLarry Bradleyphotutils-0.7.2/docs/_templates/0000755000214200020070000000000013573510273021031 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/docs/_templates/autosummary/0000755000214200020070000000000013573510273023417 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/docs/_templates/autosummary/base.rst0000644000214200020070000000037212345377273025074 0ustar lbradleySTSCI\science00000000000000{% 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. #}photutils-0.7.2/docs/_templates/autosummary/class.rst0000644000214200020070000000037312345377273025270 0ustar lbradleySTSCI\science00000000000000{% 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. #}photutils-0.7.2/docs/_templates/autosummary/module.rst0000644000214200020070000000037412345377273025451 0ustar lbradleySTSCI\science00000000000000{% 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. #}photutils-0.7.2/docs/aperture.rst0000644000214200020070000007373313572573650021301 0ustar lbradleySTSCI\science00000000000000Aperture Photometry (`photutils.aperture`) ========================================== Introduction ------------ In Photutils, the :func:`~photutils.aperture.aperture_photometry` function is the main tool to perform aperture photometry on an astronomical image for a given set of apertures. Photutils provides several apertures defined in pixel or sky coordinates. The aperture classes that are defined in pixel coordinates are: * `~photutils.aperture.CircularAperture` * `~photutils.aperture.CircularAnnulus` * `~photutils.aperture.EllipticalAperture` * `~photutils.aperture.EllipticalAnnulus` * `~photutils.aperture.RectangularAperture` * `~photutils.aperture.RectangularAnnulus` Each of these classes has a corresponding variant defined in sky coordinates: * `~photutils.aperture.SkyCircularAperture` * `~photutils.aperture.SkyCircularAnnulus` * `~photutils.aperture.SkyEllipticalAperture` * `~photutils.aperture.SkyEllipticalAnnulus` * `~photutils.aperture.SkyRectangularAperture` * `~photutils.aperture.SkyRectangularAnnulus` To perform aperture photometry with sky-based apertures, one will need to specify a WCS transformation. Users can also create their own custom apertures (see :ref:`custom-apertures`). .. _creating-aperture-objects: Creating Aperture Objects ------------------------- The first step in performing aperture photometry is to create an aperture object. An aperture object is defined by a position (or a list of positions) and parameters that define its size and possibly, orientation (e.g., an elliptical aperture). We start with an example of creating a circular aperture in pixel coordinates using the :class:`~photutils.aperture.CircularAperture` class:: >>> from photutils import CircularAperture >>> positions = [(30., 30.), (40., 40.)] >>> aperture = CircularAperture(positions, r=3.) The positions should be either a single tuple of ``(x, y)``, a list of ``(x, y)`` tuples, or an array with shape ``Nx2``, where ``N`` is the number of positions. The above example defines two circular apertures located at pixel coordinates ``(30, 30)`` and ``(40, 40)`` with a radius of 3 pixels. Creating an aperture object in sky coordinates is similar. One first uses the :class:`~astropy.coordinates.SkyCoord` class to define sky coordinates and then the :class:`~photutils.aperture.SkyCircularAperture` class to define the aperture object:: >>> from astropy import units as u >>> from astropy.coordinates import SkyCoord >>> from photutils import SkyCircularAperture >>> positions = SkyCoord(l=[1.2, 2.3] * u.deg, b=[0.1, 0.2] * u.deg, ... frame='galactic') >>> aperture = SkyCircularAperture(positions, r=4. * u.arcsec) .. note:: Sky apertures are not defined completely in sky coordinates. They simply use sky coordinates to define the central position, and the remaining parameters are converted to pixels using the pixel scale of the image at the central position. Projection distortions are not taken into account. If the apertures were defined completely in sky coordinates, their shapes would not be preserved when converting to pixel coordinates. Converting Between Pixel and Sky Apertures ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The pixel apertures can be converted to sky apertures, and vice versa. To accomplish this, use the :meth:`~photutils.aperture.PixelAperture.to_sky` method for pixel apertures, e.g.: .. doctest-skip:: >>> aperture = CircularAperture((10, 20), r=4.) >>> sky_aperture = aperture.to_sky(wcs) and the :meth:`~photutils.aperture.SkyAperture.to_pixel` method for sky apertures, e.g.: .. doctest-skip:: >>> position = SkyCoord(1.2, 0.1, unit='deg', frame='icrs') >>> aperture = SkyCircularAperture(position, r=4. * u.arcsec) >>> pix_aperture = aperture.to_pixel(wcs) Performing Aperture Photometry ------------------------------ After the aperture object is created, we can then perform the photometry using the :func:`~photutils.aperture.aperture_photometry` function. We start by defining the aperture (at two positions) as described above:: >>> positions = [(30., 30.), (40., 40.)] >>> aperture = CircularAperture(positions, r=3.) We then call the :func:`~photutils.aperture.aperture_photometry` function with the data and the apertures:: >>> import numpy as np >>> from photutils import aperture_photometry >>> data = np.ones((100, 100)) >>> phot_table = aperture_photometry(data, aperture) >>> phot_table['aperture_sum'].info.format = '%.8g' # for consistent table output >>> print(phot_table) id xcenter ycenter aperture_sum pix pix --- ------- ------- ------------ 1 30.0 30.0 28.274334 2 40.0 40.0 28.274334 This function returns the results of the photometry in an Astropy `~astropy.table.QTable`. In this example, the table has four columns, named ``'id'``, ``'xcenter'``, ``'ycenter'``, and ``'aperture_sum'``. Since all the data values are 1.0, the aperture sums are equal to the area of a circle with a radius of 3:: >>> print(np.pi * 3. ** 2) # doctest: +FLOAT_CMP 28.2743338823 Aperture and Pixel Overlap -------------------------- The overlap of the aperture with the data pixels can be handled in different ways. For the default method (``method='exact'``), the exact intersection of the aperture with each pixel is calculated. The other options, ``'center'`` and ``'subpixel'``, are faster, but with the expense of less precision. For ``'center'``, a pixel is considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. For ``'subpixel'``, pixels are divided into a number of subpixels, which are in or out of the aperture based on their centers. For this method, the number of subpixels needs to be set with the ``subpixels`` keyword. This example uses the ``'subpixel'`` method where pixels are resampled by a factor of 5 (``subpixels=5``) in each dimension:: >>> phot_table = aperture_photometry(data, aperture, method='subpixel', ... subpixels=5) >>> print(phot_table) # doctest: +SKIP id xcenter ycenter aperture_sum pix pix --- ------- ------- ------------ 1 30.0 30.0 27.96 2 40.0 40.0 27.96 Note that the results differ from the true value of 28.274333 (see above). For the ``'subpixel'`` method, the default value is ``subpixels=5``, meaning that each pixel is equally divided into 25 smaller pixels (this is the method and subsampling factor used in SourceExtractor_.). The precision can be increased by increasing ``subpixels``, but note that computation time will be increased. Multiple Apertures at Each Position ----------------------------------- While the `~photutils.aperture.Aperture` objects support multiple positions, they must have a fixed size and shape (e.g., radius and orientation). To perform photometry in multiple apertures at each position, one may input a list of aperture objects to the :func:`~photutils.aperture.aperture_photometry` function. In this case, the apertures must all have identical position(s). Suppose that we wish to use three circular apertures, with radii of 3, 4, and 5 pixels, on each source:: >>> radii = [3., 4., 5.] >>> apertures = [CircularAperture(positions, r=r) for r in radii] >>> phot_table = aperture_photometry(data, apertures) >>> for col in phot_table.colnames: ... phot_table[col].info.format = '%.8g' # for consistent table output >>> print(phot_table) id xcenter ycenter aperture_sum_0 aperture_sum_1 aperture_sum_2 pix pix --- ------- ------- -------------- -------------- -------------- 1 30 30 28.274334 50.265482 78.539816 2 40 40 28.274334 50.265482 78.539816 For multiple apertures, the output table column names are appended with the ``positions`` index. Other apertures have multiple parameters specifying the aperture size and orientation. For example, for elliptical apertures, one must specify ``a``, ``b``, and ``theta``:: >>> from photutils import EllipticalAperture >>> a = 5. >>> b = 3. >>> theta = np.pi / 4. >>> apertures = EllipticalAperture(positions, a, b, theta) >>> phot_table = aperture_photometry(data, apertures) >>> for col in phot_table.colnames: ... phot_table[col].info.format = '%.8g' # for consistent table output >>> print(phot_table) id xcenter ycenter aperture_sum pix pix --- ------- ------- ------------ 1 30 30 47.12389 2 40 40 47.12389 Again, for multiple apertures one should input a list of aperture objects, each with identical positions:: >>> a = [5., 6., 7.] >>> b = [3., 4., 5.] >>> theta = np.pi / 4. >>> apertures = [EllipticalAperture(positions, a=ai, b=bi, theta=theta) ... for (ai, bi) in zip(a, b)] >>> phot_table = aperture_photometry(data, apertures) >>> for col in phot_table.colnames: ... phot_table[col].info.format = '%.8g' # for consistent table output >>> print(phot_table) id xcenter ycenter aperture_sum_0 aperture_sum_1 aperture_sum_2 pix pix --- ------- ------- -------------- -------------- -------------- 1 30 30 47.12389 75.398224 109.95574 2 40 40 47.12389 75.398224 109.95574 Background Subtraction ---------------------- Global Background Subtraction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :func:`~photutils.aperture.aperture_photometry` assumes that the data have been background-subtracted. If ``bkg`` is a float value or an array representing the background of the data (determined by `~photutils.background.Background2D` or an external function), simply subtract the background:: >>> phot_table = aperture_photometry(data - bkg, aperture) # doctest: +SKIP Local Background Subtraction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ One often wants to estimate the local background around each source using a nearby aperture or annulus aperture surrounding each source. The simplest method for doing so would be to perform photometry in an annulus aperture to define the mean background level. Alternatively, one can use aperture masks to directly access the pixel values in an aperture (e.g. an annulus), and thus apply more advanced statistics (e.g. a sigma-clipped median within the annulus). We show examples of both below. Simple mean within a circular annulus """"""""""""""""""""""""""""""""""""" For this example we perform the photometry in a circular aperture with a radius of 3 pixels. The local background level around each source is estimated as the mean value within a circular annulus of inner radius 6 pixels and outer radius 8 pixels. We start by defining the apertures:: >>> from photutils import CircularAnnulus >>> aperture = CircularAperture(positions, r=3) >>> annulus_aperture = CircularAnnulus(positions, r_in=6., r_out=8.) We then perform the photometry in both apertures:: >>> apers = [aperture, annulus_aperture] >>> phot_table = aperture_photometry(data, apers) >>> for col in phot_table.colnames: ... phot_table[col].info.format = '%.8g' # for consistent table output >>> print(phot_table) id xcenter ycenter aperture_sum_0 aperture_sum_1 pix pix --- ------- ------- -------------- -------------- 1 30 30 28.274334 87.964594 2 40 40 28.274334 87.964594 The ``aperture_sum_0`` column refers to the first aperture in the list of input apertures (i.e. the circular aperture) and the ``aperture_sum_1`` column refers to the second aperture (i.e. the circular annulus). Note that we cannot simply subtract the aperture sums because the apertures have different areas. To calculate the mean local background within the circular annulus aperture, we need to divide its sum by its area. The mean value can be calculated by using the :meth:`~photutils.aperture.CircularAnnulus.area` attribute:: >>> bkg_mean = phot_table['aperture_sum_1'] / annulus_aperture.area The total background within the circular aperture is then the mean local background times the circular aperture area:: >>> bkg_sum = bkg_mean * aperture.area >>> final_sum = phot_table['aperture_sum_0'] - bkg_sum >>> phot_table['residual_aperture_sum'] = final_sum >>> phot_table['residual_aperture_sum'].info.format = '%.8g' # for consistent table output >>> print(phot_table['residual_aperture_sum']) # doctest: +SKIP residual_aperture_sum --------------------- -7.1054274e-15 -7.1054274e-15 The result here should be zero because all the data values are 1.0 (the tiny difference from 0.0 is due to numerical precision). Sigma-clipped median within a circular annulus """""""""""""""""""""""""""""""""""""""""""""" For this example we perform the photometry in a circular aperture with a radius of 5 pixels. The local background level around each source is estimated as the sigma-clipped median value within a circular annulus of inner radius 10 pixels and outer radius 15 pixels. We start by defining an example image and an aperture for three sources:: >>> from photutils.datasets import make_100gaussians_image >>> from photutils import CircularAperture, CircularAnnulus >>> data = make_100gaussians_image() >>> positions = [(145.1, 168.3), (84.5, 224.1), (48.3, 200.3)] >>> aperture = CircularAperture(positions, r=5) >>> annulus_aperture = CircularAnnulus(positions, r_in=10, r_out=15) Let's plot the circular apertures (white) and circular annulus apertures (red) on the image: .. plot:: from photutils.datasets import make_100gaussians_image from photutils import CircularAperture, CircularAnnulus from astropy.visualization import simple_norm data = make_100gaussians_image() positions = [(145.1, 168.3), (84.5, 224.1), (48.3, 200.3)] aperture = CircularAperture(positions, r=5) annulus_aperture = CircularAnnulus(positions, r_in=10, r_out=15) norm = simple_norm(data, 'sqrt', percent=99) plt.imshow(data, norm=norm) aperture.plot(color='white', lw=2) annulus_aperture.plot(color='red', lw=2) plt.xlim(0, 170) plt.ylim(130, 250) We can use aperture masks to directly access the pixel values in any aperture. Let's do that for the annulus aperture:: >>> annulus_masks = annulus_aperture.to_mask(method='center') The result is a list of `~photutils.aperture.ApertureMask` objects, one for each aperture position. The values in these aperture masks are either 0 or 1 because we specified ``method='center'``. Alternatively, one could use the "exact" (``method='exact'``) mask, but it produces partial-pixel masks (i.e. values between 0 and 1) and thus one would need to use statistical functions that can handle partial-pixel weights. That introduces unnecessary complexity when the aperture is simply being used to estimate the local background. Whole pixels are fine, assuming you have a sufficient number of them on which to apply your statistical estimator. Let's focus on just the first annulus. Let's plot its aperture mask: .. doctest-skip:: >>> import matplotlib.pyplot as plt >>> plt.imshow(annulus_masks[0]) >>> plt.colorbar() .. plot:: from photutils import CircularAperture, CircularAnnulus import matplotlib.pyplot as plt positions = [(145.1, 168.3), (84.5, 224.1), (48.3, 200.3)] aperture = CircularAperture(positions, r=5) annulus_aperture = CircularAnnulus(positions, r_in=10, r_out=15) annulus_masks = annulus_aperture.to_mask(method='center') plt.imshow(annulus_masks[0]) plt.colorbar() We can now use the :meth:`photutils.aperture.ApertureMask.multiply` method to get the values of the aperture mask multiplied to the data. Since the mask values are 0 or 1, the result is simply the data values within the annulus aperture:: >>> annulus_data = annulus_masks[0].multiply(data) Let's plot the annulus data: .. plot:: from photutils import CircularAperture, CircularAnnulus from photutils.datasets import make_100gaussians_image import matplotlib.pyplot as plt positions = [(145.1, 168.3), (84.5, 224.1), (48.3, 200.3)] aperture = CircularAperture(positions, r=5) annulus_aperture = CircularAnnulus(positions, r_in=10, r_out=15) annulus_masks = annulus_aperture.to_mask(method='center') data = make_100gaussians_image() annulus_data = annulus_masks[0].multiply(data) plt.imshow(annulus_data) plt.colorbar() From this 2D array, you can extract a 1D array of data values (e.g. if you don't care about their spatial positions, which is probably the most common case):: >>> mask = annulus_masks[0].data >>> annulus_data_1d = annulus_data[mask > 0] >>> annulus_data_1d.shape (394,) You can then use your favorite statistical estimator on this 1D array to estimate the background level. Let's calculate the sigma-clipped median:: >>> from astropy.stats import sigma_clipped_stats >>> _, median_sigclip, _ = sigma_clipped_stats(annulus_data_1d) >>> print(median_sigclip) # doctest: +FLOAT_CMP 4.848212997882959 The total background within the circular aperture is then the local background level times the circular aperture area:: >>> background = median_sigclip * aperture.area >>> print(background) # doctest: +FLOAT_CMP 380.7777584296913 Above was a very pedagogical description of the underlying methods for local background subtraction for a single source. However, it's quite straightforward to do this for all the sources in just a few lines of code. For this example, we'll again use the sigma-clipped median of the pixels in the background annuli for the background estimates of each source:: >>> from astropy.stats import sigma_clipped_stats >>> from photutils import aperture_photometry >>> from photutils import CircularAperture, CircularAnnulus >>> from photutils.datasets import make_100gaussians_image >>> >>> data = make_100gaussians_image() >>> positions = [(145.1, 168.3), (84.5, 224.1), (48.3, 200.3)] >>> aperture = CircularAperture(positions, r=5) >>> annulus_aperture = CircularAnnulus(positions, r_in=10, r_out=15) >>> annulus_masks = annulus_aperture.to_mask(method='center') >>> >>> bkg_median = [] >>> for mask in annulus_masks: ... annulus_data = mask.multiply(data) ... annulus_data_1d = annulus_data[mask.data > 0] ... _, median_sigclip, _ = sigma_clipped_stats(annulus_data_1d) ... bkg_median.append(median_sigclip) >>> bkg_median = np.array(bkg_median) >>> phot = aperture_photometry(data, aperture) >>> phot['annulus_median'] = bkg_median >>> phot['aper_bkg'] = bkg_median * aperture.area >>> phot['aper_sum_bkgsub'] = phot['aperture_sum'] - phot['aper_bkg'] >>> for col in phot.colnames: ... phot[col].info.format = '%.8g' # for consistent table output >>> print(phot) id xcenter ycenter aperture_sum annulus_median aper_bkg aper_sum_bkgsub pix pix --- ------- ------- ------------ -------------- --------- --------------- 1 145.1 168.3 1131.5794 4.848213 380.77776 750.80166 2 84.5 224.1 746.16064 5.0884354 399.64478 346.51586 3 48.3 200.3 1250.2186 4.8060599 377.46706 872.7515 .. _error_estimation: Error Estimation ---------------- If and only if the ``error`` keyword is input to :func:`~photutils.aperture.aperture_photometry`, the returned table will include a ``'aperture_sum_err'`` column in addition to ``'aperture_sum'``. ``'aperture_sum_err'`` provides the propagated uncertainty associated with ``'aperture_sum'``. For example, suppose we have previously calculated the error on each pixel's value and saved it in the array ``error``:: >>> positions = [(30., 30.), (40., 40.)] >>> aperture = CircularAperture(positions, r=3.) >>> data = np.ones((100, 100)) >>> error = 0.1 * data >>> phot_table = aperture_photometry(data, aperture, error=error) >>> for col in phot_table.colnames: ... phot_table[col].info.format = '%.8g' # for consistent table output >>> print(phot_table) id xcenter ycenter aperture_sum aperture_sum_err pix pix --- ------- ------- ------------ ---------------- 1 30 30 28.274334 0.53173616 2 40 40 28.274334 0.53173616 ``'aperture_sum_err'`` values are given by: .. math:: \Delta F = \sqrt{\sum_{i \in A} \sigma_{\mathrm{tot}, i}^2} where :math:`\Delta F` is `~photutils.segmentation.SourceProperties.source_sum_err`, :math:`A` are the non-masked pixels in the aperture, and :math:`\sigma_{\mathrm{tot}, i}` is the input ``error`` array. In the example above, it is assumed that the ``error`` keyword specifies the *total* error -- either it includes Poisson noise due to individual sources or such noise is irrelevant. However, it is often the case that one has calculated a smooth "background-only error" array, which by design doesn't include increased noise on bright pixels. To include Poisson noise from the sources, we can use the :func:`~photutils.utils.calc_total_error` function. Let's assume we have a background-only image called ``bkg_error``. If our data are in units of electrons/s, we would use the exposure time as the effective gain:: >>> from photutils.utils import calc_total_error >>> effective_gain = 500 # seconds >>> error = calc_total_error(data, bkg_error, effective_gain) # doctest: +SKIP >>> phot_table = aperture_photometry(data - bkg, aperture, error=error) # doctest: +SKIP Pixel Masking ------------- Pixels can be ignored/excluded (e.g., bad pixels) from the aperture photometry by providing an image mask via the ``mask`` keyword:: >>> data = np.ones((5, 5)) >>> aperture = CircularAperture((2, 2), 2.) >>> mask = np.zeros(data.shape, dtype=bool) >>> data[2, 2] = 100. # bad pixel >>> mask[2, 2] = True >>> t1 = aperture_photometry(data, aperture, mask=mask) >>> t1['aperture_sum'].info.format = '%.8g' # for consistent table output >>> print(t1['aperture_sum']) aperture_sum ------------ 11.566371 The result is very different if a ``mask`` image is not provided:: >>> t2 = aperture_photometry(data, aperture) >>> t2['aperture_sum'].info.format = '%.8g' # for consistent table output >>> print(t2['aperture_sum']) aperture_sum ------------ 111.56637 Aperture Photometry Using Sky Coordinates ----------------------------------------- As mentioned in :ref:`creating-aperture-objects`, performing photometry using apertures defined in sky coordinates simply requires defining a "sky" aperture at positions defined by a :class:`~astropy.coordinates.SkyCoord` object. Here we show an example of photometry on real data using a `~photutils.aperture.SkyCircularAperture`. We start by loading a Spitzer 4.5 micron image of a region of the Galactic plane:: >>> import astropy.units as u >>> from astropy.wcs import WCS >>> from photutils import datasets >>> hdu = datasets.load_spitzer_image() # doctest: +REMOTE_DATA >>> data = u.Quantity(hdu.data, unit=hdu.header['BUNIT']) # doctest: +REMOTE_DATA >>> wcs = WCS(hdu.header) # doctest: +REMOTE_DATA >>> catalog = datasets.load_spitzer_catalog() # doctest: +REMOTE_DATA The catalog contains (among other things) the Galactic coordinates of the sources in the image as well as the PSF-fitted fluxes from the official Spitzer data reduction. We define the apertures positions based on the existing catalog positions:: >>> positions = SkyCoord(catalog['l'], catalog['b'], frame='galactic') # doctest: +REMOTE_DATA >>> aperture = SkyCircularAperture(positions, r=4.8 * u.arcsec) # doctest: +REMOTE_DATA Now perform the photometry in these apertures on the ``data``. The ``wcs`` object contains the WCS transformation of the image obtained from the FITS header. It includes the coordinate frame of the image and the projection from sky to pixel coordinates. The `~photutils.aperture.aperture_photometry` function uses the WCS information to automatically convert the apertures defined in sky coordinates into pixel coordinates:: >>> phot_table = aperture_photometry(data, aperture, wcs=wcs) # doctest: +REMOTE_DATA The Spitzer catalog also contains the official fluxes for the sources, so we can compare to our fluxes. Because the Spitzer catalog fluxes are in units of mJy and the data are in units of MJy/sr, we need to convert units before comparing the results. The image data have a pixel scale of 1.2 arcsec/pixel. >>> import astropy.units as u >>> factor = (1.2 * u.arcsec) ** 2 / u.pixel >>> fluxes_catalog = catalog['f4_5'] # doctest: +REMOTE_DATA >>> converted_aperture_sum = (phot_table['aperture_sum'] * ... factor).to(u.mJy / u.pixel) # doctest: +REMOTE_DATA Finally, we can plot the comparison of the photometry: .. doctest-skip:: >>> import matplotlib.pyplot as plt >>> plt.scatter(fluxes_catalog, converted_aperture_sum.value) >>> plt.xlabel('Spitzer catalog PSF-fit fluxes ') >>> plt.ylabel('Aperture photometry fluxes') .. plot:: from astropy import units as u from astropy.coordinates import SkyCoord from astropy.wcs import WCS from photutils import aperture_photometry, SkyCircularAperture # Load dataset from photutils import datasets hdu = datasets.load_spitzer_image() data = u.Quantity(hdu.data, unit=hdu.header['BUNIT']) wcs = WCS(hdu.header) catalog = datasets.load_spitzer_catalog() # Set up apertures positions = SkyCoord(catalog['l'], catalog['b'], frame='galactic') aperture = SkyCircularAperture(positions, r=4.8 * u.arcsec) phot_table = aperture_photometry(data, aperture, wcs=wcs) # Convert to correct units factor = (1.2 * u.arcsec) ** 2 / u.pixel fluxes_catalog = catalog['f4_5'] converted_aperture_sum = (phot_table['aperture_sum'] * factor).to(u.mJy / u.pixel) # Plot import matplotlib.pyplot as plt plt.scatter(fluxes_catalog, converted_aperture_sum.value) plt.xlabel('Spitzer catalog PSF-fit fluxes ') plt.ylabel('Aperture photometry fluxes') plt.plot([40, 100, 450],[40, 100, 450], color='black', lw=2) Despite using different methods, the two catalogs are in good agreement. The aperture photometry fluxes are based on a circular aperture with a radius of 4.8 arcsec. The Spitzer catalog fluxes were computed using PSF photometry. Therefore, differences are expected between the two measurements. Aperture Masks -------------- All `~photutils.aperture.PixelAperture` objects have a :meth:`~photutils.aperture.PixelAperture.to_mask` method that returns a list of `~photutils.aperture.ApertureMask` objects, one for each aperture position. The `~photutils.aperture.ApertureMask` object contains a cutout of the aperture mask and a `~photutils.aperture.BoundingBox` object that provides the bounding box where the mask is to be applied. It also provides a :meth:`~photutils.aperture.ApertureMask.to_image` method to obtain an image of the mask in a 2D array of the given shape, a :meth:`~photutils.aperture.ApertureMask.cutout` method to create a cutout from the input data over the mask bounding box, and an :meth:`~photutils.aperture.ApertureMask.multiply` method to multiply the aperture mask with the input data to create a mask-weighted data cutout. All of these methods properly handle the cases of partial or no overlap of the aperture mask with the data. Let's start by creating an aperture object:: >>> from photutils import CircularAperture >>> positions = [(30., 30.), (40., 40.)] >>> aperture = CircularAperture(positions, r=3.) Now let's create a list of `~photutils.aperture.ApertureMask` objects using the :meth:`~photutils.aperture.PixelAperture.to_mask` method:: >>> masks = aperture.to_mask(method='center') We can now create an image with of the first aperture mask at its position:: >>> mask = masks[0] >>> image = mask.to_image(shape=((200, 200))) We can also create a cutout from a data image over the mask domain:: >>> data_cutout = mask.cutout(data) We can also create a mask-weighted cutout from the data. Here the circular aperture mask has been multiplied with the data:: >>> data_cutout_aper = mask.multiply(data) .. _custom-apertures: Defining Your Own Custom Apertures ---------------------------------- The :func:`~photutils.aperture.aperture_photometry` function can perform aperture photometry in arbitrary apertures. This function accepts any `~photutils.aperture.Aperture`-derived objects, such as `~photutils.aperture.CircularAperture`. This makes it simple to extend functionality: a new type of aperture photometry simply requires the definition of a new `~photutils.aperture.Aperture` subclass. All `~photutils.aperture.PixelAperture` subclasses must define a ``bounding_boxes`` property and ``to_mask()`` and ``plot()`` methods. They may also optionally define an ``area`` property. All `~photutils.aperture.SkyAperture` subclasses must only implement a ``to_pixel()`` method. * ``bounding_boxes``: The minimal bounding box for the aperture. If the aperture is scalar, then a single `~photutils.aperture.BoundingBox` is returned. Otherwise, a list of `~photutils.aperture.BoundingBox` is returned. * ``area``: An optional property defining the exact analytical area (in pixels**2) of the aperture. * ``to_mask()``: Return a mask for the aperture. If the aperture is scalar, then a single `~photutils.aperture.ApertureMask` is returned. Otherwise, a list of `~photutils.aperture.ApertureMask` is returned. * ``plot()``: A method to plot the aperture on a `matplotlib.axes.Axes` instance. See Also -------- 1. `IRAF's APPHOT package`_ 2. `SourceExtractor Manual [PDF]`_ (Sec. 9.4 p. 36) .. _SourceExtractor: https://www.astromatic.net/software/sextractor .. _SourceExtractor Manual [PDF]: https://www.astromatic.net/pubsvn/software/sextractor/trunk/doc/sextractor.pdf .. _IRAF's APPHOT package: http://iraf.noao.edu/scripts/irafhelp?apphot Reference/API ------------- .. automodapi:: photutils.aperture :no-heading: photutils-0.7.2/docs/background.rst0000644000214200020070000004554513572573650021571 0ustar lbradleySTSCI\science00000000000000Background Estimation (`photutils.background`) ============================================== Introduction ------------ To accurately measure the photometry and morphological properties of astronomical sources, one requires an accurate estimate of the background, which can be from both the sky and the detector. Similarly, having an accurate estimate of the background noise is important for determining the significance of source detections and for estimating photometric errors. Unfortunately, accurate background and background noise estimation is a difficult task. Further, because astronomical images can cover a wide variety of scenes, there is not a single background estimation method that will always be applicable. Photutils provides tools for estimating the background and background noise in your data, but they will likely require some tweaking to optimize the background estimate for your data. Scalar Background and Noise Estimation -------------------------------------- Simple Statistics ^^^^^^^^^^^^^^^^^ If the background level and noise are relatively constant across an image, the simplest way to estimate these values is to derive scalar quantities using simple approximations. Of course, when computing the image statistics one must take into account the astronomical sources present in the images, which add a positive tail to the distribution of pixel intensities. For example, one may consider using the image median as the background level and the image standard deviation as the 1-sigma background noise, but the resulting values are obviously biased by the presence of real sources. A slightly better method involves using statistics that are robust against the presence of outliers, such as the biweight location for the background level and biweight scale or `median absolute deviation (MAD) `__ for the background noise estimation. However, for most astronomical scenes these methods will also be biased by the presence of astronomical sources in the image. As an example, we load a synthetic image comprised of 100 sources with a Gaussian-distributed background whose mean is 5 and standard deviation is 2:: >>> from photutils.datasets import make_100gaussians_image >>> data = make_100gaussians_image() Let's plot the image: .. doctest-skip:: >>> import matplotlib.pyplot as plt >>> from astropy.visualization import SqrtStretch >>> from astropy.visualization.mpl_normalize import ImageNormalize >>> norm = ImageNormalize(stretch=SqrtStretch()) >>> plt.imshow(data, norm=norm, origin='lower', cmap='Greys_r') .. plot:: import matplotlib.pyplot as plt from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize from photutils.datasets import make_100gaussians_image data = make_100gaussians_image() norm = ImageNormalize(stretch=SqrtStretch()) plt.imshow(data, norm=norm, origin='lower', cmap='Greys_r') The image median and biweight location are both larger than the true background level of 5:: >>> import numpy as np >>> from astropy.stats import biweight_location >>> print(np.median(data)) # doctest: +FLOAT_CMP 5.225529518399048 >>> print(biweight_location(data)) # doctest: +FLOAT_CMP 5.186759755495727 Similarly, using the median absolute deviation to estimate the background noise level gives a value that is larger than the true value of 2:: >>> from astropy.stats import mad_std >>> print(mad_std(data)) # doctest: +FLOAT_CMP 2.1443760096598914 Sigma Clipping Sources ^^^^^^^^^^^^^^^^^^^^^^ The most widely used technique to remove the sources from the image statistics is called sigma clipping. Briefly, pixels that are above or below a specified sigma level from the median are discarded and the statistics are recalculated. The procedure is typically repeated over a number of iterations or until convergence is reached. This method provides a better estimate of the background and background noise levels:: >>> from astropy.stats import sigma_clipped_stats >>> mean, median, std = sigma_clipped_stats(data, sigma=3.0) >>> print((mean, median, std)) # doctest: +FLOAT_CMP (5.199138651621793, 5.155587433358291, 2.094275212132969) Masking Sources ^^^^^^^^^^^^^^^ An even better procedure is to exclude the sources in the image by masking them. Of course, this technique requires one to `identify the sources in the data `_, which in turn depends on the background and background noise. Therefore, this method for estimating the background and background RMS requires an iterative procedure. Photutils provides a convenience function, :func:`~photutils.segmentation.make_source_mask`, for creating source masks. It uses sigma-clipped statistics as the first estimate of the background and noise levels for the source detection. Sources are then identified using image segmentation. Finally, the source masks are dilated to mask more extended regions around the detected sources. Here we use an aggressive 2-sigma detection threshold to maximize the source detections and dilate using a 11x11 box: .. doctest-requires:: scipy >>> from photutils import make_source_mask >>> mask = make_source_mask(data, nsigma=2, npixels=5, dilate_size=11) >>> mean, median, std = sigma_clipped_stats(data, sigma=3.0, mask=mask) >>> print((mean, median, std)) # doctest: +FLOAT_CMP (5.001013475475569, 5.000584905604376, 1.970887100626572) Of course, the source detection and masking procedure can be iterated further. Even with one iteration we are within 0.02% of the true background and 1.5% of the true background RMS. .. _scipy: https://www.scipy.org/ 2D Background and Noise Estimation ---------------------------------- If the background or the background noise varies across the image, then you will generally want to generate a 2D image of the background and background RMS (or compute these values locally). This can be accomplished by applying the above techniques to subregions of the image. A common procedure is to use sigma-clipped statistics in each mesh of a grid that covers the input data to create a low-resolution background image. The final background or background RMS image can then be generated by interpolating the low-resolution image. Photutils provides the :class:`~photutils.background.Background2D` class to estimate the 2D background and background noise in an astronomical image. :class:`~photutils.background.Background2D` requires the size of the box (``box_size``) in which to estimate the background. Selecting the box size requires some care by the user. The box size should generally be larger than the typical size of sources in the image, but small enough to encapsulate any background variations. For best results, the box size should also be chosen so that the data are covered by an integer number of boxes in both dimensions. If that is not the case, the ``edge_method`` keyword determines whether to pad or crop the image such that there is an integer multiple of the ``box_size`` in both dimensions. The background level in each of the meshes is calculated using the function or callable object (e.g. class instance) input via ``bkg_estimator`` keyword. Photutils provides a several background classes that can be used: * `~photutils.background.MeanBackground` * `~photutils.background.MedianBackground` * `~photutils.background.ModeEstimatorBackground` * `~photutils.background.MMMBackground` * `~photutils.background.SExtractorBackground` * `~photutils.background.BiweightLocationBackground` The default is a `~photutils.background.SExtractorBackground` instance. For this method, the background in each mesh is calculated as ``(2.5 * median) - (1.5 * mean)``. However, if ``(mean - median) / std > 0.3`` then the ``median`` is used instead (despite what the `SExtractor `_ User's Manual says, this is the method it always uses). Likewise, the background RMS level in each mesh is calculated using the function or callable object input via the ``bkgrms_estimator`` keyword. Photutils provides the following classes for this purpose: * `~photutils.background.StdBackgroundRMS` * `~photutils.background.MADStdBackgroundRMS` * `~photutils.background.BiweightScaleBackgroundRMS` For even more flexibility, users may input a custom function or callable object to the ``bkg_estimator`` and/or ``bkgrms_estimator`` keywords. By default, the ``bkg_estimator`` and ``bkgrms_estimator`` are applied to sigma clipped data. Sigma clipping is defined by inputting a :class:`astropy.stats.SigmaClip` object to the ``sigma_clip`` keyword. The default is to perform sigma clipping with ``sigma=3`` and ``maxiters=10``. Sigma clipping can be turned off by setting ``sigma_clip=None``. After the background level has been determined in each of the boxes, the low-resolution background image can be median filtered, with a window of size of ``filter_size``, to suppress local under- or overestimations (e.g., due to bright galaxies in a particular box). Likewise, the median filter can be applied only to those boxes where the background level is above a specified threshold (``filter_threshold``). The low-resolution background and background RMS images are resized to the original data size using the function or callable object input via the ``interpolator`` keyword. Photutils provides two interpolator classes: :class:`~photutils.background.BkgZoomInterpolator` (default), which performs spline interpolation, and :class:`~photutils.background.BkgIDWInterpolator`, which uses inverse-distance weighted (IDW) interpolation. For this example, we will create a test image by adding a strong background gradient to the image defined above:: >>> ny, nx = data.shape >>> y, x = np.mgrid[:ny, :nx] >>> gradient = x * y / 5000. >>> data2 = data + gradient >>> plt.imshow(data2, norm=norm, origin='lower', cmap='Greys_r') # doctest: +SKIP .. plot:: import matplotlib.pyplot as plt from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize from photutils.datasets import make_100gaussians_image data = make_100gaussians_image() ny, nx = data.shape y, x = np.mgrid[:ny, :nx] gradient = x * y / 5000. data2 = data + gradient norm = ImageNormalize(stretch=SqrtStretch()) plt.imshow(data2, norm=norm, origin='lower', cmap='Greys_r') We start by creating a `~photutils.background.Background2D` object using a box size of 50x50 and a 3x3 median filter. We will estimate the background level in each mesh as the sigma-clipped median using an instance of :class:`~photutils.background.MedianBackground`. .. doctest-requires:: scipy >>> from astropy.stats import SigmaClip >>> from photutils import Background2D, MedianBackground >>> sigma_clip = SigmaClip(sigma=3.) >>> bkg_estimator = MedianBackground() >>> bkg = Background2D(data2, (50, 50), filter_size=(3, 3), ... sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) The 2D background and background RMS images are retrieved using the ``background`` and ``background_rms`` attributes, respectively, on the returned object. The low-resolution versions of these images are stored in the ``background_mesh`` and ``background_rms_mesh`` attributes, respectively. The global median value of the low-resolution background and background RMS image can be accessed with the ``background_median`` and ``background_rms_median`` attributes, respectively: .. doctest-requires:: scipy >>> print(bkg.background_median) # doctest: +FLOAT_CMP 10.821997862561792 >>> print(bkg.background_rms_median) # doctest: +FLOAT_CMP 2.298820539683762 Let's plot the background image: .. doctest-skip:: >>> plt.imshow(bkg.background, origin='lower', cmap='Greys_r') .. plot:: import matplotlib.pyplot as plt from astropy.stats import SigmaClip from photutils.datasets import make_100gaussians_image from photutils import Background2D, MedianBackground data = make_100gaussians_image() ny, nx = data.shape y, x = np.mgrid[:ny, :nx] gradient = x * y / 5000. data2 = data + gradient sigma_clip = SigmaClip(sigma=3.) bkg_estimator = MedianBackground() bkg = Background2D(data2, (50, 50), filter_size=(3, 3), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) plt.imshow(bkg.background, origin='lower', cmap='Greys_r') and the background-subtracted image: .. doctest-skip:: >>> plt.imshow(data2 - bkg.background, norm=norm, origin='lower', ... cmap='Greys_r') .. plot:: import matplotlib.pyplot as plt from astropy.stats import SigmaClip from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize from photutils.datasets import make_100gaussians_image from photutils import Background2D, MedianBackground data = make_100gaussians_image() ny, nx = data.shape y, x = np.mgrid[:ny, :nx] gradient = x * y / 5000. data2 = data + gradient sigma_clip = SigmaClip(sigma=3.) bkg_estimator = MedianBackground() bkg = Background2D(data2, (50, 50), filter_size=(3, 3), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) norm = ImageNormalize(stretch=SqrtStretch()) plt.imshow(data2 - bkg.background, norm=norm, origin='lower', cmap='Greys_r') Masking ^^^^^^^ Masks can also be input into `~photutils.background.Background2D`. As described above, this can be employed to mask sources in the image prior to estimating the background levels. Additionally, input masks are often necessary if your data array includes regions without data coverage (e.g., from a rotated image or an image from a mosaic). Otherwise, the data values in the regions without coverage (usually zeros or NaNs) will adversely contribute to the background statistics. Let's create such an image and plot it (NOTE: this example requires `scipy`_): .. doctest-requires:: scipy >>> from scipy.ndimage import rotate >>> data3 = rotate(data2, -45.) >>> norm = ImageNormalize(stretch=SqrtStretch()) # doctest: +SKIP >>> plt.imshow(data3, origin='lower', cmap='Greys_r', norm=norm) # doctest: +SKIP .. plot:: from photutils.datasets import make_100gaussians_image from scipy.ndimage.interpolation import rotate from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize import matplotlib.pyplot as plt data = make_100gaussians_image() ny, nx = data.shape y, x = np.mgrid[:ny, :nx] gradient = x * y / 5000. data2 = data + gradient data3 = rotate(data2, -45.) norm = ImageNormalize(stretch=SqrtStretch()) plt.imshow(data3, origin='lower', cmap='Greys_r', norm=norm) Now we create a coverage mask and input it into `~photutils.background.Background2D` to exclude the regions where we have no data. For real data, one can usually create a coverage mask from a weight or noise image. In this example we also use a smaller box size to help capture the strong gradient in the background: .. doctest-requires:: scipy >>> mask = (data3 == 0) >>> bkg3 = Background2D(data3, (25, 25), filter_size=(3, 3), mask=mask) The input masks are never applied to the returned background image because the input ``mask`` can represent either a coverage mask or a source mask, or a combination of both. Therefore, we need to manually apply the coverage mask to the returned background image: .. doctest-requires:: scipy >>> back3 = bkg3.background * ~mask >>> norm = ImageNormalize(stretch=SqrtStretch()) # doctest: +SKIP >>> plt.imshow(back3, origin='lower', cmap='Greys_r', norm=norm) # doctest: +SKIP .. plot:: from photutils.datasets import make_100gaussians_image from photutils.background import Background2D from scipy.ndimage.interpolation import rotate from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize import matplotlib.pyplot as plt data = make_100gaussians_image() ny, nx = data.shape y, x = np.mgrid[:ny, :nx] gradient = x * y / 5000. data2 = data + gradient data3 = rotate(data2, -45.) mask = (data3 == 0) bkg3 = Background2D(data3, (25, 25), filter_size=(3, 3), mask=mask) back3 = bkg3.background * ~mask norm = ImageNormalize(stretch=SqrtStretch()) plt.imshow(back3, origin='lower', cmap='Greys_r', norm=norm) Finally, let's subtract the background from the image and plot it: .. doctest-skip:: >>> norm = ImageNormalize(stretch=SqrtStretch()) >>> plt.imshow(data3 - back3, origin='lower', cmap='Greys_r', norm=norm) .. plot:: from photutils.datasets import make_100gaussians_image from photutils.background import Background2D from scipy.ndimage.interpolation import rotate import matplotlib.pyplot as plt from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize data = make_100gaussians_image() ny, nx = data.shape y, x = np.mgrid[:ny, :nx] gradient = x * y / 5000. data2 = data + gradient data3 = rotate(data2, -45.) mask = (data3 == 0) bkg3 = Background2D(data3, (25, 25), filter_size=(3, 3), mask=mask) back3 = bkg3.background * ~mask norm = ImageNormalize(stretch=SqrtStretch()) plt.imshow(data3 - back3, origin='lower', cmap='Greys_r', norm=norm) If there is any small residual background still present in the image, the background subtraction can be improved by masking the sources and/or through further iterations. Plotting Meshes ^^^^^^^^^^^^^^^ Finally, the meshes that were used in generating the 2D background can be plotted on the original image using the :meth:`~photutils.background.Background2D.plot_meshes` method: .. doctest-skip:: >>> plt.imshow(data3, origin='lower', cmap='Greys_r', norm=norm) >>> bkg3.plot_meshes(outlines=True, color='#1f77b4') .. plot:: from photutils.datasets import make_100gaussians_image from photutils.background import Background2D from scipy.ndimage.interpolation import rotate import matplotlib.pyplot as plt from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize data = make_100gaussians_image() ny, nx = data.shape y, x = np.mgrid[:ny, :nx] gradient = x * y / 5000. data2 = data + gradient data3 = rotate(data2, -45.) mask = (data3 == 0) bkg3 = Background2D(data3, (25, 25), filter_size=(3, 3), mask=mask) back3 = bkg3.background * ~mask norm = ImageNormalize(stretch=SqrtStretch()) plt.imshow(data3, origin='lower', cmap='Greys_r', norm=norm) bkg3.plot_meshes(outlines=True, color='#17becf') The meshes extended beyond the original image on the top and right because :class:`~photutils.background.Background2D`'s default ``edge_method`` is ``'pad'``. Reference/API ------------- .. automodapi:: photutils.background :no-heading: photutils-0.7.2/docs/centroids.rst0000644000214200020070000000646113563423715021432 0ustar lbradleySTSCI\science00000000000000Centroids (`photutils.centroids`) ================================= Introduction ------------ `photutils.centroids` provides several functions to calculate the centroid of a single source. The centroid methods are: * :func:`~photutils.centroids.centroid_com`: Calculates the object "center of mass" from 2D image moments. * :func:`~photutils.centroids.centroid_1dg`: Calculates the centroid by fitting 1D Gaussians to the marginal ``x`` and ``y`` distributions of the data. * :func:`~photutils.centroids.centroid_2dg`: Calculates the centroid by fitting a 2D Gaussian to the 2D distribution of the data. Masks can be input into each of these functions to mask bad pixels. Error arrays can be input into the two fitting methods to weight the fits. Getting Started --------------- Let's extract a single object from a synthetic dataset and find its centroid with each of these methods. For this simple example we will not subtract the background from the data (but in practice, one should subtract the background):: >>> from photutils.datasets import make_4gaussians_image >>> from photutils import centroid_com, centroid_1dg, centroid_2dg >>> data = make_4gaussians_image()[43:79, 76:104] >>> x1, y1 = centroid_com(data) >>> print((x1, y1)) # doctest: +FLOAT_CMP (13.93157998341213, 17.051234441067088) .. doctest-requires:: scipy >>> x2, y2 = centroid_1dg(data) >>> print((x2, y2)) # doctest: +FLOAT_CMP (14.040352707371396, 16.962306463644801) .. doctest-requires:: scipy >>> x3, y3 = centroid_2dg(data) >>> print((x3, y3)) # doctest: +FLOAT_CMP (14.002212073733611, 16.996134592982017) Now let's plot the results. Because the centroids are all very similar, we also include an inset plot zoomed in near the centroid: .. plot:: :include-source: from photutils.datasets import make_4gaussians_image from photutils import centroid_com, centroid_1dg, centroid_2dg import matplotlib.pyplot as plt data = make_4gaussians_image()[43:79, 76:104] # extract single object x1, y1 = centroid_com(data) x2, y2 = centroid_1dg(data) x3, y3 = centroid_2dg(data) fig, ax = plt.subplots(1, 1) ax.imshow(data, origin='lower', interpolation='nearest', cmap='viridis') marker = '+' ms, mew = 30, 2. plt.plot(x1, y1, color='#1f77b4', marker=marker, ms=ms, mew=mew) plt.plot(x2, y2, color='#17becf', marker=marker, ms=ms, mew=mew) plt.plot(x3, y3, color='#d62728', marker=marker, ms=ms, mew=mew) from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes from mpl_toolkits.axes_grid1.inset_locator import mark_inset ax2 = zoomed_inset_axes(ax, zoom=6, loc=9) ax2.imshow(data, interpolation='nearest', origin='lower', cmap='viridis', vmin=190, vmax=220) ax2.plot(x1, y1, color='#1f77b4', marker=marker, ms=ms, mew=mew) ax2.plot(x2, y2, color='#17becf', marker=marker, ms=ms, mew=mew) ax2.plot(x3, y3, color='#d62728', marker=marker, ms=ms, mew=mew) ax2.set_xlim(13, 15) ax2.set_ylim(16, 18) mark_inset(ax, ax2, loc1=3, loc2=4, fc='none', ec='0.5') ax2.axes.get_xaxis().set_visible(False) ax2.axes.get_yaxis().set_visible(False) ax.set_xlim(0, data.shape[1]-1) ax.set_ylim(0, data.shape[0]-1) Reference/API ------------- .. automodapi:: photutils.centroids :no-heading: photutils-0.7.2/docs/changelog.rst0000644000214200020070000000011312721610567021351 0ustar lbradleySTSCI\science00000000000000.. _changelog: ********* Changelog ********* .. include:: ../CHANGES.rst photutils-0.7.2/docs/citation.rst0000644000214200020070000000007413572576654021257 0ustar lbradleySTSCI\science00000000000000.. _photutils_citation: .. include:: ../photutils/CITATION photutils-0.7.2/docs/conf.py0000644000214200020070000002033613563423715020202 0ustar lbradleySTSCI\science00000000000000# -*- 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: from sphinx_astropy.conf.v1 import * # noqa except ImportError: print('ERROR: the documentation requires the sphinx-astropy package to be installed') sys.exit(1) # Get configuration information from setup.cfg try: from ConfigParser import ConfigParser except ImportError: from configparser import ConfigParser conf = ConfigParser() conf.read([os.path.join(os.path.dirname(__file__), '..', 'setup.cfg')]) setup_cfg = dict(conf.items('metadata')) plot_formats = ['png', 'hires.png', 'pdf', 'svg'] # -- General configuration ---------------------------------------------------- # By default, highlight as Python 3. highlight_language = 'python3' # If your documentation needs a minimal Sphinx version, state it here. needs_sphinx = '1.7' # To perform a Sphinx version check that needs to be more specific than # major.minor, call `check_sphinx_version("x.y.z")` here. # check_sphinx_version("1.2.1") # intersphinx_mappings to not include del intersphinx_mapping['h5py'] # We currently want to link to the latest development version of the # astropy docs, so we override the `intersphinx_mapping` entry pointing to # the stable docs version that is listed in `astropy/sphinx/conf.py`. intersphinx_mapping['astropy'] = ('https://docs.astropy.org/en/latest/', None) # Extend astropy intersphinx_mapping with packages we use here intersphinx_mapping['skimage'] = ('https://scikit-image.org/docs/stable/', None) intersphinx_mapping['gwcs'] = ('https://gwcs.readthedocs.io/en/latest/', None) # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns.append('_templates') # Exclusion of template PSF block specification documentation exclude_patterns.append('psf_spec/*') # This is added to the end of RST files - a good place to put substitutions to # be used globally. import photutils rst_epilog = """ .. _Astropy: https://www.astropy.org/ .. _Photutils: index.html """ # -- Project information ------------------------------------------------------ # This does not *have* to match the package name, but typically does project = setup_cfg['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. # Note: photutils was explicitly imported above package = sys.modules[setup_cfg['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 = None html_theme_options = { 'logotext1': 'phot', # white, semi-bold 'logotext2': 'utils', # orange, light 'logotext3': '' # white, light } # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = '' # 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. from os.path import join html_favicon = join('_static', 'favicon.ico') # 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' # Static files to copy after template files html_static_path = ['_static'] html_style = 'photutils.css' # -- 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')] latex_logo = '_static/photutils_banner.pdf' # -- 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 += ['sphinx_astropy.ext.edit_on_github'] versionmod = __import__(setup_cfg['name'] + '.version') edit_on_github_project = setup_cfg['github_project'] if versionmod.release: edit_on_github_branch = "v" + versionmod.version else: edit_on_github_branch = "master" edit_on_github_source_root = "" edit_on_github_doc_root = "docs" autodoc_docstring_signature = True # -- Resolving issue number to links in changelog ----------------------------- github_issues_url = 'https://github.com/{0}/issues/'.format(setup_cfg['github_project']) # -- Turn on nitpicky mode for sphinx (to warn about references not found) ---- nitpicky = True nitpick_ignore = [] # Some warnings are impossible to suppress, and you can list specific references # that should be ignored in a nitpick-exceptions file which should be inside # the docs/ directory. The format of the file should be: # # # # for example: # # py:class astropy.io.votable.tree.Element # py:class astropy.io.votable.tree.SimpleElement # py:class astropy.io.votable.tree.SimpleElementWithContent # # Uncomment the following lines to enable the exceptions: # for line in open('nitpick-exceptions'): if line.strip() == "" or line.startswith("#"): continue dtype, target = line.split(None, 1) target = target.strip() nitpick_ignore.append((dtype, target)) photutils-0.7.2/docs/contributing.rst0000644000214200020070000000303413572573650022144 0ustar lbradleySTSCI\science00000000000000Reporting Issues and Contributing ================================= Reporting Issues ---------------- If you have found a bug in Photutils, please report it by creating a new issue on the `Photutils GitHub issue tracker `_. That requires creating a `free Github account `_ if you do not have one. Please include an example that demonstrates the issue and will allow the developers to reproduce and fix the problem. You may be also asked to provide information about your operating system and a full Python stack trace. The developers will walk you through obtaining a stack trace if it is necessary. Contributing ------------ Like the `Astropy`_ project, Photutils is made both by and for its users. We accept contributions at all levels, spanning the gamut from fixing a typo in the documentation to developing a major new feature. We welcome contributors who will abide by the `Python Software Foundation Code of Conduct `_. Photutils follows the same workflow and coding guidelines as `Astropy`_. The following pages will help you get started with contributing fixes, code, or documentation (no git or GitHub experience necessary): * `How to make a code contribution `_ * `Coding Guidelines `_ * `Developer Documentation `_ photutils-0.7.2/docs/datasets.rst0000644000214200020070000000350313572573650021246 0ustar lbradleySTSCI\science00000000000000.. _datasets: Datasets (`photutils.datasets`) =============================== Introduction ------------ `photutils.datasets` gives easy access to load or make a few example datasets. The datasets are mostly images, but they also include PSF models and a source catalog. These datasets are useful for the Photutils documentation, tests, and benchmarks, but also for users that would like to try out or implement new methods for Photutils. Functions that start with ``load_*`` load data files from disk. Very small data files are bundled in the Photutils code repository and are guaranteed to be available. Mid-sized data files are currently available from the `astropy-data`_ repository and loaded into the Astropy cache on the user's machine on first load. Functions that start with ``make_*`` generate simple simulated data (e.g. Gaussian sources on a flat background with Poisson or Gaussian noise). Note that there are other tools like `skymaker`_ that can simulate much more realistic astronomical images. Getting Started --------------- Let's load an example image of M67 with :func:`~photutils.datasets.load_star_image`:: >>> from photutils import datasets >>> hdu = datasets.load_star_image() # doctest: +REMOTE_DATA >>> print(hdu.data.shape) # doctest: +REMOTE_DATA (1059, 1059) ``hdu`` is a FITS `~astropy.io.fits.ImageHDU` object and ``hdu.data`` is a `~numpy.ndarray` object. Let's plot the image: .. plot:: :include-source: from photutils import datasets hdu = datasets.load_star_image() plt.imshow(hdu.data, origin='lower', interpolation='nearest') plt.tight_layout() plt.show() Reference/API ------------- .. automodapi:: photutils.datasets :no-heading: .. _astropy-data: https://github.com/astropy/astropy-data/ .. _skymaker: https://www.astromatic.net/software/skymaker photutils-0.7.2/docs/detection.rst0000644000214200020070000002573013563423715021416 0ustar lbradleySTSCI\science00000000000000Source Detection (`photutils.detection`) ======================================== Introduction ------------ One generally needs to identify astronomical sources in their data before they can perform photometry or morphological measurements. Photutils provides two functions designed specifically to detect point-like (stellar) sources in an astronomical image. Photutils also provides a function to identify local peaks in an image that are above a specified threshold value. For general-use source detection and extraction of both point-like and extended sources, please see :ref:`image_segmentation`. Detecting Stars --------------- Photutils includes two widely-used tools that are used to detect stars in an image, `DAOFIND`_ and IRAF's `starfind`_. :class:`~photutils.detection.DAOStarFinder` is a class that provides an implementation of the `DAOFIND`_ algorithm (`Stetson 1987, PASP 99, 191 `_). It searches images for local density maxima that have a peak amplitude greater than a specified threshold (the threshold is applied to a convolved image) and have a size and shape similar to a defined 2D Gaussian kernel. :class:`~photutils.detection.DAOStarFinder` also provides an estimate of the objects' roundness and sharpness, whose lower and upper bounds can be specified. :class:`~photutils.detection.IRAFStarFinder` is a class that implements IRAF's `starfind`_ algorithm. It is fundamentally similar to :class:`~photutils.detection.DAOStarFinder`, but :class:`~photutils.detection.DAOStarFinder` can use an elliptical Gaussian kernel. One other difference in :class:`~photutils.detection.IRAFStarFinder` is that it calculates the objects' centroid, roundness, and sharpness using image moments. As an example, let's load an image from the bundled datasets and select a subset of the image. We will estimate the background and background noise using sigma-clipped statistics:: >>> from astropy.stats import sigma_clipped_stats >>> from photutils import datasets >>> hdu = datasets.load_star_image() # doctest: +REMOTE_DATA >>> data = hdu.data[0:401, 0:401] # doctest: +REMOTE_DATA >>> mean, median, std = sigma_clipped_stats(data, sigma=3.0) # doctest: +REMOTE_DATA >>> print((mean, median, std)) # doctest: +REMOTE_DATA, +FLOAT_CMP (3668.09661145823, 3649.0, 204.41388592022315) Now we will subtract the background and use an instance of :class:`~photutils.detection.DAOStarFinder` to find the stars in the image that have FWHMs of around 3 pixels and have peaks approximately 5-sigma above the background. Running this class on the data yields an astropy `~astropy.table.Table` containing the results of the star finder: .. doctest-requires:: scipy >>> from photutils import DAOStarFinder >>> daofind = DAOStarFinder(fwhm=3.0, threshold=5.*std) # doctest: +REMOTE_DATA >>> sources = daofind(data - median) # doctest: +REMOTE_DATA >>> for col in sources.colnames: # doctest: +REMOTE_DATA ... sources[col].info.format = '%.8g' # for consistent table output >>> print(sources) # doctest: +REMOTE_DATA id xcentroid ycentroid sharpness ... sky peak flux mag --- --------- --------- ---------- ... --- ---- --------- ------------ 1 144.24757 6.3797904 0.58156257 ... 0 6903 5.6976747 -1.8892441 2 208.66907 6.8205805 0.48348966 ... 0 7896 6.7186388 -2.0682032 3 216.92614 6.5775933 0.69359525 ... 0 2195 1.6662764 -0.55436758 4 351.62519 8.5459013 0.48577834 ... 0 6977 5.8970385 -1.9265849 5 377.51991 12.065501 0.52038488 ... 0 1260 1.1178252 -0.12093477 ... ... ... ... ... ... ... ... ... 282 267.90091 398.61991 0.27117231 ... 0 9299 5.4379278 -1.8385836 283 271.46959 398.91242 0.36738752 ... 0 8028 5.0693475 -1.7623802 284 299.05003 398.78469 0.25895667 ... 0 9072 5.5584641 -1.862387 285 299.99359 398.76661 0.29412474 ... 0 9253 5.3233471 -1.815462 286 360.44533 399.52381 0.37315624 ... 0 8079 6.9203438 -2.1003192 Length = 286 rows Let's plot the image and mark the location of detected sources: .. doctest-skip:: >>> import numpy as np >>> import matplotlib.pyplot as plt >>> from astropy.visualization import SqrtStretch >>> from astropy.visualization.mpl_normalize import ImageNormalize >>> from photutils import CircularAperture >>> positions = np.transpose((sources['xcentroid'], sources['ycentroid'])) >>> apertures = CircularAperture(positions, r=4.) >>> norm = ImageNormalize(stretch=SqrtStretch()) >>> plt.imshow(data, cmap='Greys', origin='lower', norm=norm) >>> apertures.plot(color='blue', lw=1.5, alpha=0.5) .. plot:: import numpy as np import matplotlib.pyplot as plt from astropy.stats import sigma_clipped_stats from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize from photutils import datasets, DAOStarFinder, CircularAperture hdu = datasets.load_star_image() data = hdu.data[0:401, 0:401] mean, median, std = sigma_clipped_stats(data, sigma=3.0) daofind = DAOStarFinder(fwhm=3.0, threshold=5.*std) sources = daofind(data - median) positions = np.transpose((sources['xcentroid'], sources['ycentroid'])) apertures = CircularAperture(positions, r=4.) norm = ImageNormalize(stretch=SqrtStretch()) plt.imshow(data, cmap='Greys', origin='lower', norm=norm) apertures.plot(color='blue', lw=1.5, alpha=0.5) Masking Regions ^^^^^^^^^^^^^^^ Regions of the input image can be masked by using the ``mask`` keyword with the :class:`~photutils.detection.DAOStarFinder` or :class:`~photutils.detection.IRAFStarFinder` instance. This simple examples uses :class:`~photutils.detection.DAOStarFinder` and masks two rectangular regions. No sources will be detected in the masked regions: .. doctest-skip:: >>> from photutils import DAOStarFinder >>> daofind = DAOStarFinder(fwhm=3.0, threshold=5.*std) >>> mask = np.zeros(data.shape, dtype=bool) >>> mask[50:151, 50:351] = True >>> mask[250:351, 150:351] = True >>> sources = daofind(data - median, mask=mask) >>> for col in sources.colnames: >>> sources[col].info.format = '%.8g' # for consistent table output >>> print(sources) .. plot:: import numpy as np import matplotlib.pyplot as plt from astropy.stats import sigma_clipped_stats from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize from photutils import datasets, DAOStarFinder, CircularAperture from photutils import RectangularAperture hdu = datasets.load_star_image() data = hdu.data[0:401, 0:401] mean, median, std = sigma_clipped_stats(data, sigma=3.0) daofind = DAOStarFinder(fwhm=3.0, threshold=5.*std) mask = np.zeros(data.shape, dtype=bool) mask[50:151, 50:351] = True mask[250:351, 150:351] = True sources = daofind(data - median, mask=mask) positions = np.transpose((sources['xcentroid'], sources['ycentroid'])) apertures = CircularAperture(positions, r=4.) norm = ImageNormalize(stretch=SqrtStretch()) plt.imshow(data, cmap='Greys', origin='lower', norm=norm) plt.title('Star finder with a mask to exclude regions') apertures.plot(color='blue', lw=1.5, alpha=0.5) rect1 = RectangularAperture((200, 100), 300, 100, theta=0.) rect2 = RectangularAperture((250, 300), 200, 100, theta=0.) rect1.plot(color='salmon', ls='dashed') rect2.plot(color='salmon', ls='dashed') Local Peak Detection -------------------- Photutils also includes a :func:`~photutils.detection.find_peaks` function to find local peaks in an image that are above a specified threshold value. Peaks are the local maxima above a specified threshold that are separated by a specified minimum number of pixels. By default, the returned pixel coordinates are always integer-valued (i.e., no centroiding is performed, only the peak pixel is identified). However, a centroiding function can be input via the ``centroid_func`` keyword to :func:`~photutils.detection.find_peaks` to compute centroid coordinates with subpixel precision. :func:`~photutils.detection.find_peaks` supports a number of additional options, including searching for peaks only within a specified footprint. Please see the :func:`~photutils.detection.find_peaks` documentation for more options. As a simple example, let's find the local peaks in an image that are 5 sigma above the background and a separated by at least 5 pixels: .. doctest-requires:: scipy >>> from astropy.stats import sigma_clipped_stats >>> from photutils.datasets import make_100gaussians_image >>> from photutils import find_peaks >>> data = make_100gaussians_image() >>> mean, median, std = sigma_clipped_stats(data, sigma=3.0) >>> threshold = median + (5. * std) >>> tbl = find_peaks(data, threshold, box_size=11) >>> tbl['peak_value'].info.format = '%.8g' # for consistent table output >>> print(tbl[:10]) # print only the first 10 peaks x_peak y_peak peak_value ------ ------ ---------- 233 0 27.477852 493 6 20.404769 207 11 24.075798 258 12 17.395025 366 12 18.729726 289 22 35.853276 380 29 19.261986 442 31 30.239994 359 36 19.771626 471 38 25.45583 And let's plot the location of the detected peaks in the image: .. doctest-skip:: >>> import numpy as np >>> import matplotlib.pyplot as plt >>> from astropy.visualization import simple_norm >>> from astropy.visualization.mpl_normalize import ImageNormalize >>> from photutils import CircularAperture >>> positions = np.transpose((tbl['x_peak'], tbl['y_peak'])) >>> apertures = CircularAperture(positions, r=5.) >>> norm = simple_norm(data, 'sqrt', percent=99.9) >>> plt.imshow(data, cmap='Greys_r', origin='lower', norm=norm) >>> apertures.plot(color='#0547f9', lw=1.5) >>> plt.xlim(0, data.shape[1]-1) >>> plt.ylim(0, data.shape[0]-1) .. plot:: import numpy as np from astropy.stats import sigma_clipped_stats from photutils import find_peaks, CircularAperture from photutils.datasets import make_100gaussians_image data = make_100gaussians_image() mean, median, std = sigma_clipped_stats(data, sigma=3.0) threshold = median + (5.0 * std) tbl = find_peaks(data, threshold, box_size=11) import matplotlib.pyplot as plt from astropy.visualization import simple_norm positions = np.transpose((tbl['x_peak'], tbl['y_peak'])) apertures = CircularAperture(positions, r=5.) norm = simple_norm(data, 'sqrt', percent=99.9) plt.imshow(data, cmap='Greys_r', origin='lower', norm=norm) apertures.plot(color='#0547f9', lw=1.5) plt.xlim(0, data.shape[1]-1) plt.ylim(0, data.shape[0]-1) Reference/API ------------- .. automodapi:: photutils.detection :no-heading: .. _DAOFIND: https://iraf.net/irafhelp.php?val=daofind .. _starfind: https://iraf.net/irafhelp.php?val=starfind photutils-0.7.2/docs/epsf.rst0000644000214200020070000003054213572574524020377 0ustar lbradleySTSCI\science00000000000000.. _build-epsf: Building an effective Point Spread Function (ePSF) ================================================== The ePSF -------- The instrumental PSF is a combination of many factors that are generally difficult to model. `Anderson and King (2000; PASP 112, 1360) `_ showed that accurate stellar photometry and astrometry can be derived by modeling the net PSF, which they call the effective PSF (ePSF). The ePSF is an empirical model describing what fraction of a star's light will land in a particular pixel. The constructed ePSF is typically oversampled with respect to the detector pixels. Building an ePSF ---------------- Photutils provides tools for building an ePSF following the prescription of `Anderson and King (2000; PASP 112, 1360) `_ and subsequent enhancements detailed mainly in `Anderson (2016), ISR WFC3 2016-12 `_. The process involves iterating between the ePSF itself and the stars used to build it. To begin, we must first define a sample of stars used to build the ePSF. Ideally these stars should be bright (high S/N) and isolated to prevent contamination from nearby stars. One may use the star-finding tools in Photutils (e.g. :class:`~photutils.detection.DAOStarFinder` or :class:`~photutils.detection.IRAFStarFinder`) to identify an initial sample of stars. However, the step of creating a good sample of stars will also likely require visual inspection and manual selection to ensure stars are sufficiently isolated and of good quality (e.g. no cosmic rays, detector artifacts, etc.). Let's start by loading a simulated HST/WFC3 image in the F160W band:: >>> from photutils import datasets >>> hdu = datasets.load_simulated_hst_star_image() # doctest: +REMOTE_DATA >>> data = hdu.data # doctest: +REMOTE_DATA The simulated image does not contain any background or noise, so let's add those to the image:: >>> from photutils.datasets import make_noise_image >>> data += make_noise_image(data.shape, distribution='gaussian', ... mean=10., stddev=5., random_state=12345) # doctest: +REMOTE_DATA Let's show the image: .. plot:: :include-source: import matplotlib.pyplot as plt from astropy.visualization import simple_norm from photutils import datasets from photutils.datasets import make_noise_image hdu = datasets.load_simulated_hst_star_image() data = hdu.data data += make_noise_image(data.shape, distribution='gaussian', mean=10., stddev=5., random_state=12345) norm = simple_norm(data, 'sqrt', percent=99.) plt.imshow(data, norm=norm, origin='lower', cmap='viridis') For this example we'll use the :func:`~photutils.detection.find_peaks` function to identify the stars and their initial positions. We will not use the centroiding option in :func:`~photutils.detection.find_peaks` to simulate the effect of having imperfect initial guesses for the positions of the stars. Here we set the detection threshold value to 500.0 to select only the brightest stars: .. doctest-requires:: scipy >>> from photutils import find_peaks >>> peaks_tbl = find_peaks(data, threshold=500.) # doctest: +REMOTE_DATA >>> peaks_tbl['peak_value'].info.format = '%.8g' # for consistent table output # doctest: +REMOTE_DATA >>> print(peaks_tbl) # doctest: +REMOTE_DATA x_peak y_peak peak_value ------ ------ ---------- 849 2 1077.6815 182 4 1715.4047 324 4 3017.0213 100 9 1142.7459 824 9 1296.9274 ... ... ... 751 992 809.9401 114 994 1583.773 299 994 656.79885 207 998 2808.3181 691 999 2614.8846 Length = 429 rows Note that the stars are sufficiently separated in the simulated image that we do not need to exclude any stars due to crowding. In practice this step will require some manual inspection and selection. Next, we need to extract cutouts of the stars using the :func:`~photutils.psf.extract_stars` function. This function requires a table of star positions either in pixel or sky coordinates. For this example we are using the pixel coordinates, which need to be in table columns called simply ``x`` and ``y``. We plan to extract 25 x 25 pixel cutouts of our selected stars, so let's explicitly exclude stars that are too close to the image boundaries (because they cannot be extracted): .. doctest-requires:: scipy >>> size = 25 >>> hsize = (size - 1) / 2 >>> x = peaks_tbl['x_peak'] # doctest: +REMOTE_DATA >>> y = peaks_tbl['y_peak'] # doctest: +REMOTE_DATA >>> mask = ((x > hsize) & (x < (data.shape[1] -1 - hsize)) & ... (y > hsize) & (y < (data.shape[0] -1 - hsize))) # doctest: +REMOTE_DATA Now let's create the table of good star positions: .. doctest-requires:: scipy >>> from astropy.table import Table >>> stars_tbl = Table() >>> stars_tbl['x'] = x[mask] # doctest: +REMOTE_DATA >>> stars_tbl['y'] = y[mask] # doctest: +REMOTE_DATA The star cutouts from which we build the ePSF must have the background subtracted. Here we'll use the sigma-clipped median value as the background level. If the background in the image varies across the image, one should use more sophisticated methods (e.g. `~photutils.background.Background2D`). Let's subtract the background from the image:: >>> from astropy.stats import sigma_clipped_stats >>> mean_val, median_val, std_val = sigma_clipped_stats(data, sigma=2.) # doctest: +REMOTE_DATA >>> data -= median_val # doctest: +REMOTE_DATA The :func:`~photutils.psf.extract_stars` function requires the input data as an `~astropy.nddata.NDData` object. An `~astropy.nddata.NDData` object is easy to create from our data array:: >>> from astropy.nddata import NDData >>> nddata = NDData(data=data) # doctest: +REMOTE_DATA We are now ready to create our star cutouts using the :func:`~photutils.psf.extract_stars` function. For this simple example we are extracting stars from a single image using a single catalog. The :func:`~photutils.psf.extract_stars` can also extract stars from multiple images using a separate catalog for each image or a single catalog. When using a single catalog, the star positions must be in sky coordinates (as `~astropy.coordinates.SkyCoord` objects) and the `~astropy.nddata.NDData` objects must contain valid `~astropy.wcs.WCS` objects. In the case of using multiple images (i.e. dithered images) and a single catalog, the same physical star will be "linked" across images, meaning it will be constrained to have the same sky coordinate in each input image. Let's extract the 25 x 25 pixel cutouts of our selected stars: .. doctest-requires:: scipy >>> from photutils.psf import extract_stars >>> stars = extract_stars(nddata, stars_tbl, size=25) # doctest: +REMOTE_DATA The function returns a `~photutils.psf.EPSFStars` object containing the cutouts of our selected stars. The function extracted 403 stars, from which we'll build our ePSF. Let's show the first 25 of them: .. doctest-skip:: >>> import matplotlib.pyplot as plt >>> from astropy.visualization import simple_norm >>> nrows = 5 >>> ncols = 5 >>> fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=(20, 20), ... squeeze=True) >>> ax = ax.ravel() >>> for i in range(nrows*ncols): ... norm = simple_norm(stars[i], 'log', percent=99.) ... ax[i].imshow(stars[i], norm=norm, origin='lower', cmap='viridis') .. plot:: from astropy.visualization import simple_norm from photutils import datasets hdu = datasets.load_simulated_hst_star_image() data = hdu.data from photutils.datasets import make_noise_image data += make_noise_image(data.shape, distribution='gaussian', mean=10., stddev=5., random_state=12345) from photutils import find_peaks peaks_tbl = find_peaks(data, threshold=500.) size = 25 hsize = (size - 1) / 2 x = peaks_tbl['x_peak'] y = peaks_tbl['y_peak'] mask = ((x > hsize) & (x < (data.shape[1] -1 - hsize)) & (y > hsize) & (y < (data.shape[0] -1 - hsize))) from astropy.table import Table stars_tbl = Table() stars_tbl['x'] = x[mask] stars_tbl['y'] = y[mask] from astropy.stats import sigma_clipped_stats mean_val, median_val, std_val = sigma_clipped_stats(data, sigma=2.) data -= median_val from astropy.nddata import NDData nddata = NDData(data=data) from photutils.psf import extract_stars stars = extract_stars(nddata, stars_tbl, size=25) import matplotlib.pyplot as plt nrows = 5 ncols = 5 fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=(20, 20), squeeze=True) ax = ax.ravel() for i in range(nrows*ncols): norm = simple_norm(stars[i], 'log', percent=99.) ax[i].imshow(stars[i], norm=norm, origin='lower', cmap='viridis') With the star cutouts in hand, we are ready to construct the ePSF with the :class:`~photutils.psf.EPSFBuilder` class. We'll create an ePSF with an oversampling factor of 4.0. Here we limit the maximum number of iterations to 3 (to limit it's run time), but in practice one should use about 10 or more iterations. The :class:`~photutils.psf.EPSFBuilder` class has many other options to control the ePSF build process, including changing the centering function, the smoothing kernel, and the centering accuracy. Please see the :class:`~photutils.psf.EPSFBuilder` documentation for further details. We first initialize an :class:`~photutils.psf.EPSFBuilder` instance with our desired parameters and then input the cutouts of our selected stars to the instance: .. doctest-requires:: scipy >>> from photutils import EPSFBuilder >>> epsf_builder = EPSFBuilder(oversampling=4, maxiters=3, ... progress_bar=False) # doctest: +REMOTE_DATA >>> epsf, fitted_stars = epsf_builder(stars) # doctest: +REMOTE_DATA The returned values are the ePSF, as an :class:`~photutils.psf.EPSFModel` object, and our input stars fitted with the constructed ePSF, as a new :class:`~photutils.psf.EPSFStars` object with fitted star positions and fluxes. Finally, let's show the constructed ePSF: .. doctest-skip:: >>> import matplotlib.pyplot as plt >>> from astropy.visualization import simple_norm >>> norm = simple_norm(epsf.data, 'log', percent=99.) >>> plt.imshow(epsf.data, norm=norm, origin='lower', cmap='viridis') >>> plt.colorbar() .. plot:: from astropy.visualization import simple_norm from photutils import datasets hdu = datasets.load_simulated_hst_star_image() data = hdu.data from photutils.datasets import make_noise_image data += make_noise_image(data.shape, distribution='gaussian', mean=10., stddev=5., random_state=12345) from photutils import find_peaks peaks_tbl = find_peaks(data, threshold=500.) size = 25 hsize = (size - 1) / 2 x = peaks_tbl['x_peak'] y = peaks_tbl['y_peak'] mask = ((x > hsize) & (x < (data.shape[1] -1 - hsize)) & (y > hsize) & (y < (data.shape[0] -1 - hsize))) from astropy.table import Table stars_tbl = Table() stars_tbl['x'] = x[mask] stars_tbl['y'] = y[mask] from astropy.stats import sigma_clipped_stats mean_val, median_val, std_val = sigma_clipped_stats(data, sigma=2.) data -= median_val from astropy.nddata import NDData nddata = NDData(data=data) from photutils.psf import extract_stars stars = extract_stars(nddata, stars_tbl, size=25) from photutils import EPSFBuilder epsf_builder = EPSFBuilder(oversampling=4, maxiters=3, progress_bar=False) epsf, fitted_stars = epsf_builder(stars) import matplotlib.pyplot as plt norm = simple_norm(epsf.data, 'log', percent=99.) plt.imshow(epsf.data, norm=norm, origin='lower', cmap='viridis') plt.colorbar() The :class:`~photutils.psf.EPSFModel` object is a subclass of :class:`~photutils.psf.FittableImageModel`, thus it can be used as a PSF model for the `PSF-fitting machinery in Photutils `_ (i.e. `~photutils.psf.BasicPSFPhotometry`, `~photutils.psf.IterativelySubtractedPSFPhotometry`, or `~photutils.psf.DAOPhotPSFPhotometry`). photutils-0.7.2/docs/geometry.rst0000644000214200020070000000050413563423715021263 0ustar lbradleySTSCI\science00000000000000Geometry Functions (`photutils.geometry`) ========================================= Introduction ------------ The `photutils.geometry` package contains low-level geometry functions used mainly by `~photutils.aperture.aperture_photometry`. Reference/API ------------- .. automodapi:: photutils.geometry :no-heading: photutils-0.7.2/docs/getting_started.rst0000644000214200020070000001240013563423715022615 0ustar lbradleySTSCI\science00000000000000Getting Started with Photutils ============================== The following example uses Photutils to find sources in an astronomical image and then perform circular aperture photometry on them. We start by loading an image from the bundled datasets and selecting a subset of the image:: >>> import numpy as np >>> from photutils import datasets >>> hdu = datasets.load_star_image() # doctest: +REMOTE_DATA >>> image = hdu.data[500:700, 500:700].astype(float) # doctest: +REMOTE_DATA We then subtract a rough estimate of the background, calculated using the image median:: >>> image -= np.median(image) # doctest: +REMOTE_DATA In the remainder of this example, we assume that the data is background-subtracted. Photutils supports several source detection algorithms. For this example, we use :class:`~photutils.detection.DAOStarFinder` to detect the stars in the image. We set the detection threshold at the 3-sigma noise level, estimated using the median absolute deviation (`~astropy.stats.mad_std`) of the image. The parameters of the detected sources are returned as an Astropy `~astropy.table.Table`: .. doctest-requires:: scipy >>> from photutils import DAOStarFinder >>> from astropy.stats import mad_std >>> bkg_sigma = mad_std(image) # doctest: +REMOTE_DATA >>> daofind = DAOStarFinder(fwhm=4., threshold=3.*bkg_sigma) # doctest: +REMOTE_DATA >>> sources = daofind(image) # doctest: +REMOTE_DATA >>> for col in sources.colnames: # doctest: +REMOTE_DATA ... sources[col].info.format = '%.8g' # for consistent table output >>> print(sources) # doctest: +REMOTE_DATA id xcentroid ycentroid sharpness ... sky peak flux mag --- --------- ---------- ---------- ... --- ---- --------- ----------- 1 182.83866 0.16767019 0.85099873 ... 0 3824 2.8028346 -1.1189937 2 189.20431 0.26081353 0.7400477 ... 0 4913 3.8729185 -1.4700959 3 5.7946491 2.6125424 0.39589731 ... 0 7752 4.1029107 -1.5327302 4 36.847063 1.3220228 0.29594528 ... 0 8739 7.4315818 -2.1777032 5 3.2565602 5.418952 0.35985495 ... 0 6935 3.8126298 -1.4530616 ... ... ... ... ... ... ... ... ... 147 197.24864 186.16647 0.31211532 ... 0 8302 7.5814629 -2.1993825 148 124.31327 188.30523 0.5362742 ... 0 6702 6.6358543 -2.0547421 149 24.257207 194.71494 0.44169546 ... 0 8342 3.2671037 -1.2854073 150 116.45 195.05923 0.67080547 ... 0 3299 2.8775221 -1.1475467 151 18.958086 196.34207 0.56502139 ... 0 3854 2.3835296 -0.94305138 152 111.52575 195.73192 0.45827852 ... 0 8109 7.9278607 -2.24789 Length = 152 rows Using the source locations (i.e. the ``xcentroid`` and ``ycentroid`` columns), we now define circular apertures centered at these positions with a radius of 4 pixels and compute the sum of the pixel values within the apertures. The :func:`~photutils.aperture.aperture_photometry` function returns an Astropy `~astropy.table.QTable` with the results of the photometry: .. doctest-requires:: scipy >>> from photutils import aperture_photometry, CircularAperture >>> positions = np.transpose((sources['xcentroid'], sources['ycentroid'])) # doctest: +REMOTE_DATA >>> apertures = CircularAperture(positions, r=4.) # doctest: +REMOTE_DATA >>> phot_table = aperture_photometry(image, apertures) # doctest: +REMOTE_DATA >>> for col in phot_table.colnames: # doctest: +REMOTE_DATA ... phot_table[col].info.format = '%.8g' # for consistent table output >>> print(phot_table) # doctest: +REMOTE_DATA id xcenter ycenter aperture_sum pix pix --- --------- ---------- ------------ 1 182.83866 0.16767019 18121.759 2 189.20431 0.26081353 29836.515 3 5.7946491 2.6125424 331979.82 4 36.847063 1.3220228 183705.09 5 3.2565602 5.418952 349468.98 ... ... ... ... 148 124.31327 188.30523 45084.874 149 24.257207 194.71494 355778.01 150 116.45 195.05923 31232.912 151 18.958086 196.34207 162076.26 152 111.52575 195.73192 82795.715 Length = 152 rows The sum of the pixel values within the apertures are given in the ``aperture_sum`` column. Finally, we plot the image and the defined apertures: .. doctest-skip:: >>> import matplotlib.pyplot as plt >>> plt.imshow(image, cmap='gray_r', origin='lower') >>> apertures.plot(color='blue', lw=1.5, alpha=0.5) .. plot:: import numpy as np import matplotlib.pyplot as plt from astropy.stats import mad_std from photutils import (datasets, DAOStarFinder, aperture_photometry, CircularAperture) hdu = datasets.load_star_image() image = hdu.data[500:700, 500:700].astype(float) image -= np.median(image) bkg_sigma = mad_std(image) daofind = DAOStarFinder(fwhm=4., threshold=3.*bkg_sigma) sources = daofind(image) positions = np.transpose((sources['xcentroid'], sources['ycentroid'])) apertures = CircularAperture(positions, r=4.) phot_table = aperture_photometry(image, apertures) brightest_source_id = phot_table['aperture_sum'].argmax() plt.imshow(image, cmap='gray_r', origin='lower') apertures.plot(color='blue', lw=1.5, alpha=0.5) photutils-0.7.2/docs/grouping.rst0000644000214200020070000002460513572573650021276 0ustar lbradleySTSCI\science00000000000000Grouping Algorithms =================== Introduction ------------ In Point Spread Function (PSF) photometry, a grouping algorithm is used to separate stars into optimum groups. The stars in each group are defined as those close enough together such that they need to be fit simultaneously, i.e. their profiles overlap. Photoutils currently provides two classes to group stars: * :class:`~photutils.psf.DAOGroup`: An implementation of the `DAOPHOT `_ GROUP algorithm. * :class:`~photutils.psf.DBSCANGroup`: Grouping is based on the `Density-Based Spatial Clustering of Applications with Noise (DBSCAN) `_ algorithm. DAOPHOT GROUP ------------- Stetson, in his seminal paper (`Stetson 1987, PASP 99, 191 `_), provided a simple and powerful grouping algorithm to decide whether the profile of a given star extends into the fitting region of any other star. Stetson defines this in terms of a "critical separation" parameter, which is defined as the minimal distance that any two stars must be separated by in order to be in different groups. Stetson gives intuitive reasoning to suggest that the critical separation may be defined as a multiple of the stellar full width at half maximum (FWHM). Photutils provides an implementation of the DAOPHOT GROUP algorithm in the :class:`~photutils.psf.DAOGroup` class. Let's take a look at a simple example. First, let's make some Gaussian sources using `~photutils.datasets.make_random_gaussians_table` and `~photutils.datasets.make_gaussian_sources_image`. The former will return a `~astropy.table.Table` containing parameters for 2D Gaussian sources and the latter will make an actual image using that table. .. plot:: :include-source: from collections import OrderedDict import numpy as np from photutils.datasets import (make_random_gaussians_table, make_gaussian_sources_image) import matplotlib.pyplot as plt n_sources = 350 sigma_psf = 2.0 # use an OrderedDict to ensure reproducibility params = OrderedDict([('flux', [500, 5000]), ('x_mean', [6, 250]), ('y_mean', [6, 250]), ('x_stddev', [sigma_psf, sigma_psf]), ('y_stddev', [sigma_psf, sigma_psf]), ('theta', [0, np.pi])]) starlist = make_random_gaussians_table(n_sources, params, random_state=1234) shape = (256, 256) sim_image = make_gaussian_sources_image(shape, starlist) plt.imshow(sim_image, origin='lower', interpolation='nearest', cmap='viridis') plt.show() ``starlist`` is an astropy `~astropy.table.Table` of parameters defining the position and shape of the stars. Next, we need to rename the table columns of the centroid positions so that they agree with the names that `~photutils.psf.DAOGroup` expect. Here we rename ``x_mean`` to ``x_0`` and ``y_mean`` to ``y_0``: .. doctest-skip:: >>> starlist['x_mean'].name = 'x_0' >>> starlist['y_mean'].name = 'y_0' Now, let's find the stellar groups. We start by creating a `~photutils.psf.DAOGroup` object. Here we set its ``crit_separation`` parameter ``2.5 * fwhm``, where the stellar ``fwhm`` was defined above when we created the stars as 2D Gaussians. In general one will need to measure the FWHM of the stellar profiles. .. doctest-skip:: >>> from astropy.stats import gaussian_sigma_to_fwhm >>> from photutils.psf.groupstars import DAOGroup >>> fwhm = sigma_psf * gaussian_sigma_to_fwhm >>> daogroup = DAOGroup(crit_separation=2.5*fwhm) ``daogroup`` is a `~photutils.psf.DAOGroup` instance that can be used as a calling function that receives as input a table of stars (e.g. ``starlist``): .. doctest-skip:: >>> star_groups = daogroup(starlist) The ``star_groups`` output is copy of the input ``starlist`` table, but with an extra column called ``group_id``. This column contains integers that represent the group assigned to each source. Here the grouping algorithm separated the 350 stars into 92 distinct groups: .. doctest-skip:: >>> print(max(star_groups['group_id'])) 92 One can use the ``group_by`` functionality from `~astropy.table.Table` to create groups according to ``group_id``: .. doctest-skip:: >>> star_groups = star_groups.group_by('group_id') >>> print(star_groups) flux x_0 y_0 ... amplitude id group_id ------------- ------------- ------------- ... ------------- --- -------- 1361.83752671 182.958386152 178.708228379 ... 54.1857935158 1 1 4282.41965053 179.998944123 171.437757021 ... 170.392063944 183 1 555.831417775 181.611905957 185.16181342 ... 22.1158294162 222 1 3299.48946968 243.60449392 85.8926967927 ... 131.282514695 2 2 2469.77482553 136.657577889 109.771746713 ... 98.2692179518 3 3 ... ... ... ... ... ... ... 818.132804377 117.787387455 92.4349134636 ... 32.5524699806 313 88 3979.57421702 154.85279495 18.3148180315 ... 158.34222701 318 89 3622.30997136 97.0901736699 50.3565997421 ... 144.127134338 323 90 765.47561385 144.952825542 7.57086675812 ... 30.4573069401 330 91 1508.68165551 54.0404934991 232.693833605 ... 60.0285357567 349 92 Length = 350 rows Finally, let's plot a circular aperture around each star, where stars in the same group have the same aperture color: .. doctest-skip:: >>> import numpy as np >>> from photutils import CircularAperture >>> from photutils.utils import make_random_cmap >>> plt.imshow(sim_image, origin='lower', interpolation='nearest', ... cmap='Greys_r') >>> cmap = make_random_cmap(random_state=12345) >>> for i, group in enumerate(star_groups.groups): >>> xypos = np.transpose([group['x_0'], group['y_0']]) >>> ap = CircularAperture(xypos, r=fwhm) >>> ap.plot(color=cmap.colors[i]) >>> plt.show() .. plot:: from collections import OrderedDict import numpy as np from astropy.stats import gaussian_sigma_to_fwhm from photutils.datasets import (make_random_gaussians_table, make_gaussian_sources_image) from photutils.psf.groupstars import DAOGroup from photutils import CircularAperture from photutils.utils import make_random_cmap import matplotlib.pyplot as plt from matplotlib import rcParams rcParams['image.aspect'] = 1 # to get images with square pixels rcParams['figure.figsize'] = (7, 7) n_sources = 350 sigma_psf = 2.0 # use an OrderedDict to ensure reproducibility params = OrderedDict([('flux', [500, 5000]), ('x_mean', [6, 250]), ('y_mean', [6, 250]), ('x_stddev', [sigma_psf, sigma_psf]), ('y_stddev', [sigma_psf, sigma_psf]), ('theta', [0, np.pi])]) starlist = make_random_gaussians_table(n_sources, params, random_state=1234) shape = (256, 256) sim_image = make_gaussian_sources_image(shape, starlist) starlist['x_mean'].name = 'x_0' starlist['y_mean'].name = 'y_0' fwhm = sigma_psf * gaussian_sigma_to_fwhm daogroup = DAOGroup(crit_separation=2.5*fwhm) star_groups = daogroup(starlist) star_groups = star_groups.group_by('group_id') plt.imshow(sim_image, origin='lower', interpolation='nearest', cmap='Greys_r') cmap = make_random_cmap(random_state=12345) for i, group in enumerate(star_groups.groups): xypos = np.transpose([group['x_0'], group['y_0']]) ap = CircularAperture(xypos, r=fwhm) ap.plot(color=cmap.colors[i]) DBSCANGroup ----------- Photutils also provides a :class:`~photutils.psf.DBSCANGroup` class to group stars based on the `Density-Based Spatial Clustering of Applications with Noise (DBSCAN) `_ algorithm. :class:`~photutils.psf.DBSCANGroup` provides a more general algorithm than :class:`~photutils.psf.DAOGroup`. Here's a simple example using :class:`~photutils.psf.DBSCANGroup` with ``min_samples=1`` and ``metric=euclidean``. With these parameters, the result is identical to the `~photutils.psf.DAOGroup` algorithm. Note that `scikit-learn `_ must be installed to use :class:`~photutils.psf.DBSCANGroup`. .. plot:: from collections import OrderedDict import numpy as np from astropy.stats import gaussian_sigma_to_fwhm from photutils.datasets import (make_random_gaussians_table, make_gaussian_sources_image) from photutils.psf.groupstars import DBSCANGroup from photutils import CircularAperture from photutils.utils import make_random_cmap import matplotlib.pyplot as plt from matplotlib import rcParams rcParams['image.aspect'] = 1 # to get images with square pixels rcParams['figure.figsize'] = (7, 7) n_sources = 350 sigma_psf = 2.0 # use an OrderedDict to ensure reproducibility params = OrderedDict([('flux', [500, 5000]), ('x_mean', [6, 250]), ('y_mean', [6, 250]), ('x_stddev', [sigma_psf, sigma_psf]), ('y_stddev', [sigma_psf, sigma_psf]), ('theta', [0, np.pi])]) starlist = make_random_gaussians_table(n_sources, params, random_state=1234) shape = (256, 256) sim_image = make_gaussian_sources_image(shape, starlist) starlist['x_mean'].name = 'x_0' starlist['y_mean'].name = 'y_0' fwhm = sigma_psf * gaussian_sigma_to_fwhm group = DBSCANGroup(crit_separation=2.5*fwhm) star_groups = group(starlist) star_groups = star_groups.group_by('group_id') plt.imshow(sim_image, origin='lower', interpolation='nearest', cmap='Greys_r') cmap = make_random_cmap(random_state=12345) for i, group in enumerate(star_groups.groups): xypos = np.transpose([group['x_0'], group['y_0']]) ap = CircularAperture(xypos, r=fwhm) ap.plot(color=cmap.colors[i]) Reference/API ------------- .. automodapi:: photutils.psf.groupstars :no-heading: photutils-0.7.2/docs/index.rst0000644000214200020070000000355113563423715020544 0ustar lbradleySTSCI\science00000000000000 .. the "raw" directive below is used to hide the title in favor of just the logo being visible .. raw:: html ********* Photutils ********* .. raw:: html .. only:: latex .. image:: _static/photutils_banner.pdf **Photutils** is an `affiliated package `_ of `Astropy`_ that primarily provides tools for detecting and performing photometry of astronomical sources. It is an open source Python package and is licensed under a :ref:`3-clause BSD license `. .. Important:: If you use Photutils for a project that leads to a publication, whether directly or as a dependency of another package, please include an :doc:`acknowledgment and/or citation `. Getting Started =============== .. toctree:: :maxdepth: 1 install.rst overview.rst pixel_conventions.rst getting_started.rst contributing.rst citation.rst license.rst changelog User Documentation ================== .. toctree:: :maxdepth: 1 background.rst detection.rst grouping.rst aperture.rst psf.rst epsf.rst psf_matching.rst segmentation.rst centroids.rst morphology.rst isophote.rst geometry.rst datasets.rst utils.rst .. toctree:: :hidden: test_function.rst .. note:: Like much astronomy software, Photutils is an evolving package. The developers make an effort to maintain backwards compatibility, but at times the API may change if there is a benefit to doing so. If there are specific areas you think API stability is important, please let us know as part of the development process! photutils-0.7.2/docs/install.rst0000644000214200020070000001114513572576136021107 0ustar lbradleySTSCI\science00000000000000************ Installation ************ Requirements ============ Photutils has the following strict requirements: * `Python `_ 3.5 or later * `Numpy `_ 1.13 or later * `Astropy`_ 2.0 or later Photutils also optionally depends on other packages for some features: * `Scipy `_ 0.19 or later: To power a variety of features in several modules (strongly recommended). * `matplotlib `_ 2.2 or later: To power a variety of plotting features (e.g. plotting apertures). * `scikit-image `_ 0.14.2 or later: Used in `~photutils.segmentation.deblend_sources` for deblending segmented sources. * `scikit-learn `_ 0.19 or later: Used in `~photutils.psf.DBSCANGroup` to create star groups. * `gwcs `_ 0.11 or later: Used in `~photutils.datasets.make_gwcs` to create a simple celestial gwcs object. Photutils depends on `pytest-astropy `_ (0.4 or later) to run the test suite. Installing the latest released version ====================================== The latest released (stable) version of Photutils can be installed either with `pip`_ or `conda`_. Using pip --------- To install Photutils with `pip`_, run:: pip install photutils If you want to make sure that none of your existing dependencies get upgraded, instead you can do:: pip install astropy --no-deps Note that you will generally need a C compiler (e.g. ``gcc`` or ``clang``) to be installed for the installation to succeed. If you get a ``PermissionError``, this means that you do not have the required administrative access to install new packages to your Python installation. In this case you may consider using the ``--user`` option to install the package into your home directory. You can read more about how to do this in the `pip documentation `_. Do **not** install Photutils or other third-party packages using ``sudo`` unless you are fully aware of the risks. Using conda ----------- Photutils can be installed with `conda`_ if you have installed `Anaconda `_ or `Miniconda `_. To install Photutils using the `astropy Anaconda channel `_, run:: conda install photutils -c astropy Installing the latest development version from Source ===================================================== Prerequisites ------------- You will need `Cython `_ (0.28 or later), a compiler suite, and the development headers for Python and Numpy in order to build Photutils from the source distribution. On Linux, using the package manager for your distribution will usually be the easiest route. On MacOS X you will need the `XCode`_ command-line tools, which can be installed using:: xcode-select --install Follow the onscreen instructions to install the command-line tools required. Note that you do not need to install the full `XCode`_ distribution (assuming you are using MacOS X 10.9 or later). Building and installing manually -------------------------------- Photutils is being developed on `github`_. The latest development version of the Photutils source code can be retrieved using git:: git clone https://github.com/astropy/photutils.git Then to build and install Photutils, run:: cd photutils python setup.py install Building and installing using pip --------------------------------- Alternatively, `pip`_ can be used to retrieve, build, and install the latest development version from `github`_:: pip install git+https://github.com/astropy/photutils.git Again, if you want to make sure that none of your existing dependencies get upgraded, instead you can do:: pip install git+https://github.com/astropy/photutils.git --no-deps Testing an installed Photutils ============================== The easiest way to test your installed version of Photutils is running correctly is to use the :func:`photutils.test` function: .. doctest-skip:: >>> import photutils >>> photutils.test() Note that this may not work if you start Python from within the Photutils source distribution directory. The tests should run and report any failures, which you can report to the `Photutils issue tracker `_. .. _pip: https://pip.pypa.io/en/latest/ .. _conda: https://conda.io/en/latest/ .. _github: https://github.com/astropy/photutils .. _Xcode: https://developer.apple.com/xcode/ photutils-0.7.2/docs/isophote.rst0000644000214200020070000002443613563423715021274 0ustar lbradleySTSCI\science00000000000000Elliptical Isophote Analysis (`photutils.isophote`) =================================================== Introduction ------------ The `~photutils.isophote` package provides tools to fit elliptical isophotes to a galaxy image. The isophotes in the image are measured using an iterative method described by `Jedrzejewski (1987; MNRAS 226, 747) `_. See the documentation of the :class:`~photutils.isophote.Ellipse` class for details about the algorithm. Please also see the :ref:`isophote-faq`. Getting Started --------------- For this example, let's create a simple simulated galaxy image:: >>> import numpy as np >>> from astropy.modeling.models import Gaussian2D >>> from photutils.datasets import make_noise_image >>> g = Gaussian2D(100., 75, 75, 20, 12, theta=40.*np.pi/180.) >>> ny = nx = 150 >>> y, x = np.mgrid[0:ny, 0:nx] >>> noise = make_noise_image((ny, nx), distribution='gaussian', mean=0., ... stddev=2., random_state=12345) >>> data = g(x, y) + noise .. plot:: import numpy as np import matplotlib.pyplot as plt from astropy.modeling.models import Gaussian2D from photutils.datasets import make_noise_image g = Gaussian2D(100., 75, 75, 20, 12, theta=40.*np.pi/180.) ny = nx = 150 y, x = np.mgrid[0:ny, 0:nx] noise = make_noise_image((ny, nx), distribution='gaussian', mean=0., stddev=2., random_state=12345) data = g(x, y) + noise plt.imshow(data, origin='lower') We must provide the elliptical isophote fitter with an initial ellipse to be fitted. This ellipse geometry is defined with the `~photutils.isophote.EllipseGeometry` class. Here we'll define an initial ellipse whose position angle is offset from the data:: >>> from photutils.isophote import EllipseGeometry >>> geometry = EllipseGeometry(x0=75, y0=75, sma=20, eps=0.5, ... pa=20.*np.pi/180.) Let's show this initial ellipse guess: .. doctest-skip:: >>> import matplotlib.pyplot as plt >>> from photutils import EllipticalAperture >>> aper = EllipticalAperture((geometry.x0, geometry.y0), geometry.sma, ... geometry.sma*(1 - geometry.eps), ... geometry.pa) >>> plt.imshow(data, origin='lower') >>> aper.plot(color='white') .. plot:: import numpy as np import matplotlib.pyplot as plt from astropy.modeling.models import Gaussian2D from photutils.datasets import make_noise_image from photutils.isophote import EllipseGeometry from photutils import EllipticalAperture g = Gaussian2D(100., 75, 75, 20, 12, theta=40.*np.pi/180.) ny = nx = 150 y, x = np.mgrid[0:ny, 0:nx] noise = make_noise_image((ny, nx), distribution='gaussian', mean=0., stddev=2., random_state=12345) data = g(x, y) + noise geometry = EllipseGeometry(x0=75, y0=75, sma=20, eps=0.5, pa=20.*np.pi/180.) aper = EllipticalAperture((geometry.x0, geometry.y0), geometry.sma, geometry.sma*(1 - geometry.eps), geometry.pa) plt.imshow(data, origin='lower') aper.plot(color='white') Next, we create an instance of the `~photutils.isophote.Ellipse` class, inputting the data to be fitted and the initial ellipse geometry object:: >>> from photutils.isophote import Ellipse >>> ellipse = Ellipse(data, geometry) To perform the elliptical isophote fit, we run the :meth:`~photutils.isophote.Ellipse.fit_image` method: .. doctest-requires:: scipy >>> isolist = ellipse.fit_image() The result is a list of isophotes as an `~photutils.isophote.IsophoteList` object, whose attributes are the fit values for each `~photutils.isophote.Isophote` sorted by the semimajor axis length. Let's print the fit position angles (radians): .. doctest-requires:: scipy >>> print(isolist.pa) # doctest: +SKIP [ 0. 0.16838914 0.18453378 0.20310945 0.22534975 0.25007781 0.28377499 0.32494582 0.38589202 0.40480013 0.39527698 0.38448771 0.40207495 0.40207495 0.28201524 0.28201524 0.19889817 0.1364335 0.1364335 0.13405719 0.17848892 0.25687327 0.35750355 0.64882699 0.72489435 0.91472008 0.94219702 0.87393299 0.82572916 0.7886367 0.75523282 0.7125274 0.70481612 0.7120097 0.71250791 0.69707669 0.7004807 0.70709823 0.69808124 0.68621341 0.69437566 0.70548293 0.70427021 0.69978326 0.70410887 0.69532744 0.69440413 0.70062534 0.68614488 0.7177538 0.7177538 0.7029571 0.7029571 0.7029571 ] We can also show the isophote values as a table, which is again sorted by the semimajor axis length (``sma``): .. doctest-requires:: scipy >>> print(isolist.to_table()) # doctest: +SKIP sma intens intens_err ... flag niter stop_code ... -------------- --------------- --------------- ... ---- ----- --------- 0.0 102.237692914 0.0 ... 0 0 0 0.534697261283 101.212218041 0.0280377938856 ... 0 10 0 0.588166987411 101.095404456 0.027821598428 ... 0 10 0 0.646983686152 100.971770355 0.0272405762608 ... 0 10 0 0.711682054767 100.842254551 0.0262991125932 ... 0 10 0 ... ... ... ... ... ... ... 51.874849202 3.44800874483 0.0881592058138 ... 0 50 2 57.0623341222 1.64031530995 0.0913122295433 ... 0 50 2 62.7685675344 0.692631010404 0.0786846787635 ... 0 32 0 69.0454242879 0.294659388337 0.0681758007533 ... 0 8 5 75.9499667166 0.0534892334515 0.0692483210903 ... 0 2 5 Length = 54 rows Let's plot the ellipticity, position angle, and the center x and y position as a function of the semimajor axis length: .. plot:: import matplotlib.pyplot as plt from astropy.modeling.models import Gaussian2D from photutils.datasets import make_noise_image from photutils.isophote import EllipseGeometry, Ellipse g = Gaussian2D(100., 75, 75, 20, 12, theta=40.*np.pi/180.) ny = nx = 150 y, x = np.mgrid[0:ny, 0:nx] noise = make_noise_image((ny, nx), distribution='gaussian', mean=0., stddev=2., random_state=12345) data = g(x, y) + noise geometry = EllipseGeometry(x0=75, y0=75, sma=20, eps=0.5, pa=20.*np.pi/180.) ellipse = Ellipse(data, geometry) isolist = ellipse.fit_image() plt.figure(figsize=(8, 8)) plt.subplots_adjust(hspace=0.35, wspace=0.35) plt.subplot(2, 2, 1) plt.errorbar(isolist.sma, isolist.eps, yerr=isolist.ellip_err, fmt='o', markersize=4) plt.xlabel('Semimajor Axis Length (pix)') plt.ylabel('Ellipticity') plt.subplot(2, 2, 2) plt.errorbar(isolist.sma, isolist.pa/np.pi*180., yerr=isolist.pa_err/np.pi* 80., fmt='o', markersize=4) plt.xlabel('Semimajor Axis Length (pix)') plt.ylabel('PA (deg)') plt.subplot(2, 2, 3) plt.errorbar(isolist.sma, isolist.x0, yerr=isolist.x0_err, fmt='o', markersize=4) plt.xlabel('Semimajor Axis Length (pix)') plt.ylabel('x0') plt.subplot(2, 2, 4) plt.errorbar(isolist.sma, isolist.y0, yerr=isolist.y0_err, fmt='o', markersize=4) plt.xlabel('Semimajor Axis Length (pix)') plt.ylabel('y0') We can build an elliptical model image from the `~photutils.isophote.IsophoteList` object using the :func:`~photutils.isophote.build_ellipse_model` function ( NOTE: this function requires `scipy `_): .. doctest-requires:: scipy >>> from photutils.isophote import build_ellipse_model >>> model_image = build_ellipse_model(data.shape, isolist) >>> residual = data - model_image Finally, let's plot the original data, overplotted with some of the isophotes, the elliptical model image, and the residual image: .. plot:: import matplotlib.pyplot as plt from astropy.modeling.models import Gaussian2D from photutils.datasets import make_noise_image from photutils.isophote import EllipseGeometry, Ellipse from photutils.isophote import build_ellipse_model g = Gaussian2D(100., 75, 75, 20, 12, theta=40.*np.pi/180.) ny = nx = 150 y, x = np.mgrid[0:ny, 0:nx] noise = make_noise_image((ny, nx), distribution='gaussian', mean=0., stddev=2., random_state=12345) data = g(x, y) + noise geometry = EllipseGeometry(x0=75, y0=75, sma=20, eps=0.5, pa=20.*np.pi/180.) ellipse = Ellipse(data, geometry) isolist = ellipse.fit_image() model_image = build_ellipse_model(data.shape, isolist) residual = data - model_image fig, (ax1, ax2, ax3) = plt.subplots(figsize=(14, 5), nrows=1, ncols=3) fig.subplots_adjust(left=0.04, right=0.98, bottom=0.02, top=0.98) ax1.imshow(data, origin='lower') ax1.set_title('Data') smas = np.linspace(10, 50, 5) for sma in smas: iso = isolist.get_closest(sma) x, y, = iso.sampled_coordinates() ax1.plot(x, y, color='white') ax2.imshow(model_image, origin='lower') ax2.set_title('Ellipse Model') ax3.imshow(residual, origin='lower') ax3.set_title('Residual') Additional Example Notebooks (online) ------------------------------------- Additional example notebooks showing examples with real data and advanced usage are available online: * `Basic example of the Ellipse fitting tool `_ * `Running Ellipse with sigma-clipping `_ * `Building an image model from results obtained by Ellipse fitting `_ * `Advanced Ellipse example: multi-band photometry and masked arrays `_ Reference/API ------------- .. automodapi:: photutils.isophote :no-heading: .. toctree:: :hidden: isophote_faq.rst photutils-0.7.2/docs/isophote_faq.rst0000644000214200020070000002241713572573650022124 0ustar lbradleySTSCI\science00000000000000.. _isophote-faq: Isophote Frequently Asked Questions ----------------------------------- .. _harmonic_ampl: 1. What are the basic equations relating harmonic amplitudes to geometrical parameter updates? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The basic elliptical isophote fitting algorithm, as described in `Jedrzejewski (1987; MNRAS 226, 747) `_ , computes corrections for the current ellipse's geometrical parameters by essentially "projecting" the fitted harmonic amplitudes onto the image plane: .. math:: {\delta}_{X0} = \frac {-B_{1}} {I'} .. math:: {\delta}_{Y0} = \frac {-A_{1} (1 - {\epsilon})} {I'} .. math:: {\delta}_{\epsilon} = \frac {-2 B_{2} (1 - {\epsilon})} {I' a_0} .. math:: {\delta}_{\Theta} = \frac {2 A_{2} (1 - {\epsilon})} {I' a_0 [(1 - {\epsilon}) ^ 2 - 1 ]} where :math:`\epsilon` is the ellipticity, :math:`\Theta` is the position angle, :math:`A_i` and :math:`B_i` are the harmonic coefficients, and :math:`I'` is the derivative of the intensity along the major axis direction evaluated at a semimajor axis length of :math:`a_0`. 2. Why use "ellipticity" instead of the canonical ellipse eccentricity? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The main reason is that ellipticity, defined as .. math:: \epsilon = 1 - \frac{b}{a} better relates with the visual "flattening" of an ellipse. By looking at a flattened circle it is easy to guess its ellipticity, as say 0.1. The same ellipse has an eccentricity of 0.44, which is not obvious from visual inspection. The quantities relate as .. math:: Ecc = \sqrt{1 - (1 - {\epsilon})^2} 3. How is the radial gradient estimated? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The radial intensity gradient is the most critical quantity computed by the fitting algorithm. As can be seen from the above formulae, small :math:`I'` values lead to large values for the correction terms. Thus, :math:`I'` errors may lead to large fluctuations in these terms, when :math:`I'` itself is small. This usually happens at the fainter, outer regions of galaxy images. `Busko (1996; ASPC 101, 139) `_ found by numerical experiments that the precision to which a given ellipse can be fitted is related to the relative error in the local radial gradient. Because of the gradient's critical role, the algorithm has a number of features to allow its estimation even under difficult conditions. The default gradient computation, the one used by the algorithm when it first starts to fit a new isophote, is based on the extraction of two intensity samples: #1 at the current ellipse position, and #2 at a similar ellipse with a 10% larger semimajor axis. If the gradient so estimated is not meaningful, the algorithm extracts another #2 sample, this time using a 20% larger radius. In this context, a meaningful gradient means "shallower", but still close to within a factor 3 from the previous isophote's gradient estimate. If still no meaningful gradient can be measured, the algorithm uses the value measured at the last fitted isophote, but decreased (in absolute value) by a factor 0.8. This factor is roughly what is expected from semimajor-axis geometrical-sampling steps of 10 - 20% and a deVaucouleurs law or an exponential disk in its inner region (r <~ 5 req). When using the last isophote's gradient as estimator for the current one, the current gradient error cannot be computed and is set to `None`. As a last resort, if no previous gradient estimate is available, the algorithm just guesses the current value by setting it to be (minus) 10% of the mean intensity at sample #1. This case usually happens only at the first isophote fitted by the algorithm. The use of approximate gradient estimators may seem in contradiction with the fact that isophote fitting errors depend on gradient error, as well as with the fact that the algorithm itself is so sensitive to the gradient value. The rationale behind the use of approximate estimators, however, is based on the fact that the gradient value is used only to compute increments, not the ellipse parameters themselves. Approximate estimators are useful along the first steps in the iteration sequence, in particular when local image contamination (stars, defects, etc.) might make it difficult to find the correct path towards the solution. However, if the gradient is still not well determined at convergence, the subsequent error computations, and the algorithm's behavior from that point on, will take the fact into account properly. For instance, the 3rd and 4th harmonic amplitude errors depend on the gradient relative error, and if this is not computable at the current isophote, the algorithm uses a reasonable estimate (80% of the value at the last successful isophote) in order to generate sensible estimates for those harmonic errors. 4. How are the errors estimated? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Most parameters computed directly at each isophote have their errors computed by standard error propagation. Errors in the ellipse geometry parameters, on the other hand, cannot be estimated in the same way, since these parameters are not computed directly but result from a number of updates from a starting guess value. An error analysis based on numerical experiments (`Busko 1996; ASPC 101, 139 `_) showed that the best error estimators for these geometrical parameters can be found by simply "projecting" the harmonic amplitude errors that come from the least-squares covariance matrix by the same formulae in :ref:`Question 1 ` above used to "project" the associated parameter updates. In other words, errors for the ellipse center, ellipticity, and position angle are computed by the same formulae as in :ref:`Question 1 `, but replacing the least-squares amplitudes by their errors. This is empirical and difficult to justify in terms of any theoretical error analysis, but it produces sensible error estimators in practice. 5. How is the image sampled? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When sampling is done using elliptical sectors (mean or median modes), the algorithm described in `Jedrzejewski (1987; MNRAS 226, 747) `_ uses an elaborate, high-precision scheme to take into account partial pixels that lie along elliptical sector boundaries. In the current implementation of the `~photutils.isophote.Ellipse` algorithm, this method was not implemented. Instead, pixels at sector boundaries are either fully included or discarded, depending on the precise position of their centers in relation to the elliptical geometric locus corresponding to the current ellipse. This design decision is based on two arguments: (i) it would be difficult to include partial pixels in median computation, and (ii) speed. Even when the chosen integration mode is not bilinear, the sampling algorithm resorts to it in case the number of sampled pixels inside any given sector is less than 5. It was found that bilinear mode gives smoother samples in those cases. Tests performed with artificial images showed that cosmic rays and defective pixels can be very effectively removed from the fit by a combination of median sampling and sigma-clipping. 6. How reliable are the fluxes computed by the `~photutils.isophote.Ellipse` algorithm? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The integrated fluxes and areas computed by `~photutils.isophote.Ellipse` were checked against results produced by the IRAF ``noao.digiphot.apphot`` tasks ``phot`` and ``polyphot``, using artificial images. Quantities computed by `~photutils.isophote.Ellipse` match the reference ones within < 0.1% in all tested cases. 7. How does the object centerer work? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The `~photutils.isophote.EllipseGeometry` class has a :meth:`~photutils.isophote.EllipseGeometry.find_center` method that runs an "object locator" around the input object coordinates. This routine performs a scan over a 10x10 pixel window centered on the input object coordinates. At each scan position, it extracts two concentric, roughly circular samples with radii 4 and 8 pixels. It then computes a signal-to-noise-like criterion using the intensity averages and standard deviations at each annulus: .. math:: c = \frac{f_{1} - f_{2}}{{\sqrt{\sigma_{1}^{2} + \sigma_{2}^{2}}}} and locates the pixel inside the scanned window where this criterion is a maximum. If the criterion so computed exceeds a given threshold, it assumes that a suitable object was detected at that position. The default threshold value is set to 0.1. This value and the annuli and window sizes currently used were found by trial and error using a number of both artificial and real galaxy images. It was found that very flattened galaxy images (ellipticity ~ 0.7) cannot be detected by such a simple algorithm. By increasing the threshold value the object locator becomes stricter, in the sense that it will not detect faint objects. To turn off the object locator, set the threshold to a value >> 1 in `~photutils.isophote.Ellipse`. This will prevent it from modifying whatever values for the center coordinates were given to the `~photutils.isophote.Ellipse` algorithm. photutils-0.7.2/docs/license.rst0000644000214200020070000000017213563423715021053 0ustar lbradleySTSCI\science00000000000000.. _photutils_license: License ======= Photutils is licensed under a 3-clause BSD license: .. include:: ../LICENSE.rst photutils-0.7.2/docs/make.bat0000644000214200020070000001064112345377273020312 0ustar lbradleySTSCI\science00000000000000@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 photutils-0.7.2/docs/morphology.rst0000644000214200020070000000752613563423715021642 0ustar lbradleySTSCI\science00000000000000Morphological Properties (`photutils.morphology`) ================================================= Introduction ------------ The :func:`~photutils.morphology.data_properties` function can be used to calculate the morphological properties of a single source in a cutout image. `~photutils.morphology.data_properties` returns a `~photutils.segmentation.SourceProperties` object. Please see `~photutils.segmentation.SourceProperties` for the list of the many properties that are calculated. Even more properties are likely to be added in the future. If you have a segmentation image, the :func:`~photutils.segmentation.source_properties` function can be used to calculate the properties for all (or a specified subset) of the segmented sources. Please see `Source Photometry and Properties from Image Segmentation `_ for more details. Getting Started --------------- Let's extract a single object from a synthetic dataset and find calculate its morphological properties. For this example, we will subtract the background using simple sigma-clipped statistics. First, we create the source image and subtract its background:: >>> from photutils.datasets import make_4gaussians_image >>> from astropy.stats import sigma_clipped_stats >>> data = make_4gaussians_image()[43:79, 76:104] >>> mean, median, std = sigma_clipped_stats(data, sigma=3.0) >>> data -= median # subtract background Then, calculate its properties: .. doctest-requires:: scipy >>> from photutils import data_properties >>> cat = data_properties(data) >>> columns = ['id', 'xcentroid', 'ycentroid', 'semimajor_axis_sigma', ... 'semiminor_axis_sigma', 'orientation'] >>> tbl = cat.to_table(columns=columns) >>> tbl['xcentroid'].info.format = '.10f' # optional format >>> tbl['ycentroid'].info.format = '.10f' >>> tbl['semiminor_axis_sigma'].info.format = '.10f' >>> tbl['orientation'].info.format = '.10f' >>> print(tbl) id xcentroid ycentroid ... semiminor_axis_sigma orientation pix pix ... pix deg --- ------------- ------------- ... -------------------- ------------- 1 14.0225090502 16.9901801466 ... 3.6977761870 60.1283048753 Now let's use the measured morphological properties to define an approximate isophotal ellipse for the source: .. doctest-skip:: >>> import astropy.units as u >>> from photutils import EllipticalAperture >>> position = (cat.xcentroid.value, cat.ycentroid.value) >>> r = 3.0 # approximate isophotal extent >>> a = cat.semimajor_axis_sigma.value * r >>> b = cat.semiminor_axis_sigma.value * r >>> theta = cat.orientation.to(u.rad).value >>> apertures = EllipticalAperture(position, a, b, theta=theta) >>> plt.imshow(data, origin='lower', cmap='viridis', ... interpolation='nearest') >>> apertures.plot(color='#d62728') .. plot:: import astropy.units as u import matplotlib.pyplot as plt from photutils import data_properties, EllipticalAperture from photutils.datasets import make_4gaussians_image data = make_4gaussians_image()[43:79, 76:104] # extract single object cat = data_properties(data) columns = ['id', 'xcentroid', 'ycentroid', 'semimajor_axis_sigma', 'semiminor_axis_sigma', 'orientation'] tbl = cat.to_table(columns=columns) r = 2.5 # approximate isophotal extent position = (cat.xcentroid.value, cat.ycentroid.value) a = cat.semimajor_axis_sigma.value * r b = cat.semiminor_axis_sigma.value * r theta = cat.orientation.to(u.rad).value apertures = EllipticalAperture(position, a, b, theta=theta) plt.imshow(data, origin='lower', cmap='viridis', interpolation='nearest') apertures.plot(color='#d62728') Reference/API ------------- .. automodapi:: photutils.morphology :no-heading: photutils-0.7.2/docs/nitpick-exceptions0000644000214200020070000000010413546777712022447 0ustar lbradleySTSCI\science00000000000000# photutils.morphology py:class photutils.morphology.CompoundModel1 photutils-0.7.2/docs/overview.rst0000644000214200020070000000162613563423715021304 0ustar lbradleySTSCI\science00000000000000Overview ======== Introduction ------------ Photutils contains functions for: * performing aperture photometry * performing PSF-fitting photometry * detecting and extracting point-like sources (e.g. stars) in astronomical images * detecting and extracting extended sources using image segmentation in astronomical images * centroiding sources * estimating the background and background RMS in astronomical images * building an effective Point Spread Function (ePSF) * matching PSF kernels * estimating morphological parameters of detected sources The code and issue tracker are available at the following links: * Code: https://github.com/astropy/photutils * Issue Tracker: https://github.com/astropy/photutils/issues Contributors ------------ For the complete list of contributors please see the `Photutils contributors page on Github `_. photutils-0.7.2/docs/pixel_conventions.rst0000644000214200020070000000223313563423715023177 0ustar lbradleySTSCI\science00000000000000Pixel Coordinate Conventions ---------------------------- In Photutils, integer pixel coordinates fall at the center of pixels and they are 0-indexed, matching the Python 0-based indexing. That means the first pixel is considered pixel ``0``, but pixel coordinate ``0`` is the *center* of that pixel. Hence, the first pixel spans pixel values ``-0.5`` to ``0.5``. For a 2-dimensional array, ``(x, y) = (0, 0)`` corresponds to the *center* of the bottom, leftmost array element. That means the first pixel spans the ``x`` and ``y`` pixel values from ``-0.5`` to ``0.5``. Note that this differs from the `IRAF`_, `FITS WCS `_ , `ds9`_, and `SourceExtractor`_ conventions, in which the center of the bottom, leftmost array element is ``(x, y) = (1, 1)``. Following Python indexing, the ``x`` (column) coordinate corresponds to the second (fast) array index and the ``y`` (row) coordinate corresponds to the first (slow) index. ``image[y, x]`` gives the value at pixel coordinates ``(x, y)``. .. _SourceExtractor: https://www.astromatic.net/software/sextractor .. _IRAF: http://ast.noao.edu/data/software .. _ds9: http://ds9.si.edu/ photutils-0.7.2/docs/psf.rst0000644000214200020070000007663113572573650020242 0ustar lbradleySTSCI\science00000000000000PSF Photometry (`photutils.psf`) ================================ The `photutils.psf` module contains tools for model-fitting photometry, often called "PSF photometry". .. warning:: The PSF photometry API is currently considered *experimental* and may change in the future. We will aim to keep compatibility where practical, but will not finalize the API until sufficient user feedback has been accumulated. .. _psf-terminology: Terminology ----------- Different astronomy sub-fields use the terms "PSF", "PRF", or related terms somewhat differently, especially when colloquial usage is taken into account. This package aims to be at the very least internally consistent, following the definitions described here. For this module we take Point Spread Function (PSF), or instrumental Point Spread Function (iPSF) to be the infinite resolution and infinite signal-to-noise flux distribution from a point source on the detector, after passing through optics, dust, atmosphere, etc. By contrast, the function describing the responsivity variations across individual *pixels* is the Pixel Response Function (sometimes called "PRF", but that acronym is not used here for reasons that will soon be apparent). The convolution of the PSF and pixel response function, when discretized onto the detector (i.e. a rectilinear CCD grid), is the effective PSF (ePSF) or Point Response Function (PRF). (This latter terminology is the definition used by `Spitzer `_. In many cases the PSF/ePSF/PRF distinction is unimportant, and the ePSF/PRF are simply called the "PSF", but the distinction can be critical when dealing carefully with undersampled data or detectors with significant intra-pixel sensitivity variations. For a more detailed description of this formalism, see `Anderson & King 2000 `_. All this said, in colloquial usage "PSF photometry" sometimes refers to the more general task of model-fitting photometry (with the effects of the PSF either implicitly or explicitly included in the models), regardless of exactly what kind of model is actually being fit. For brevity (e.g., ``photutils.psf``), we use "PSF photometry" in this way, as a shorthand for the general approach. Building an effective PSF (ePSF) -------------------------------- Please see :ref:`build-epsf` for documentation on how to build an ePSF. PSF Photometry -------------- Photutils provides a modular set of tools to perform PSF photometry for different science cases. These are implemented as separate classes to do sub-tasks of PSF photometry. It also provides high-level classes that connect these pieces together. In particular, it contains an implementation of the DAOPHOT algorithm (`~photutils.psf.DAOPhotPSFPhotometry`) proposed by `Stetson in his seminal paper `_ for crowded-field stellar photometry. The DAOPHOT algorithm consists in applying the loop FIND, GROUP, NSTAR, SUBTRACT, FIND until no more stars are detected or a given number of iterations is reached. Basically, `~photutils.psf.DAOPhotPSFPhotometry` works as follows. The first step is to estimate the sky background. For this task, photutils provides several classes to compute scalar and 2D backgrounds, see `~photutils.background` for details. The next step is to find an initial estimate of the positions of potential sources. This can be accomplished by using source detection algorithms, which are implemented in `~photutils.detection`. After finding sources, one would apply a clustering algorithm in order to label the sources according to groups. Usually, those groups are formed by a distance criterion, which is the case of the grouping algorithm proposed by Stetson. In `~photutils.psf.DAOGroup`, we provide an implementation of that algorithm. In addition, `~photutils.psf.DBSCANGroup` can also be used to group sources with more complex distance criteria. The reason behind the construction of groups is illustrated as follows: imagine that one would like to fit 300 stars and the model for each star has three parameters to be fitted. If one constructs a single model to fit the 300 stars simultaneously, then the optimization algorithm will have to search for the solution in a 900 dimensional space, which is computationally expensive and error-prone. Reducing the stars in groups effectively reduces the dimension of the parameter space, which facilitates the optimization process. Provided that the groups are available, the next step is to fit the sources simultaneously for each group. This task can be done using an astropy fitter, for instance, `~astropy.modeling.fitting.LevMarLSQFitter`. After sources are fitted, they are subtracted from the given image and, after fitting all sources, the residual image is analyzed by the finding routine again in order to check if there exist any source which has not been detected previously. This process goes on until no more sources are identified by the finding routine. .. note:: It is important to note the conventions on the column names of the input/output astropy Tables which are passed along to the source detection and photometry objects. For instance, all source detection objects should output a table with columns named as ``xcentroid`` and ``ycentroid`` (check `~photutils.detection`). On the other hand, `~photutils.psf.DAOGroup` expects columns named as ``x_0`` and ``y_0``, which represents the initial guesses on the sources' centroids. Finally, the output of the fitting process shows columns named as ``x_fit``, ``y_fit``, ``flux_fit`` for the optimum values and ``x_0``, ``y_0``, ``flux_0`` for the initial guesses. Although this convention implies that the columns have to be renamed along the process, it has the advantage of clarity so that one can keep track and easily differentiate where input/outputs came from. High-Level Structure ^^^^^^^^^^^^^^^^^^^^ Photutils provides three classes to perform PSF Photometry: `~photutils.psf.BasicPSFPhotometry`, `~photutils.psf.IterativelySubtractedPSFPhotometry`, and `~photutils.psf.DAOPhotPSFPhotometry`. Together these provide the core workflow to make photometric measurements given an appropriate PSF (or other) model. `~photutils.psf.BasicPSFPhotometry` implements the minimum tools for model-fitting photometry. At its core, this involves finding sources in an image, grouping overlapping sources into a single model, fitting the model to the sources, and subtracting the models from the image. In DAOPHOT parlance, this is essentially running the "FIND, GROUP, NSTAR, SUBTRACT" once. Because it is only a single cycle of that sequence, this class should be used when the degree of crowdedness of the field is not very high, for instance, when most stars are separated by a distance no less than one FWHM and their brightness are relatively uniform. It is critical to understand, though, that `~photutils.psf.BasicPSFPhotometry` does not actually contain the functionality to *do* all these steps - that is provided by other objects (or can be user-written) functions. Rather, it provides the framework and data structures in which these operations run. Because of this, `~photutils.psf.BasicPSFPhotometry` is particularly useful for build more complex workflows, as all the stages can be turned on or off or replaced with different implementations as the user desires. `~photutils.psf.IterativelySubtractedPSFPhotometry` is similar to `~photutils.psf.BasicPSFPhotometry`, but it adds a parameter called ``n_iters`` which is the number of iterations for which the loop "FIND, GROUP, NSTAR, SUBTRACT, FIND..." will be performed. This class enables photometry in a scenario where there exists significant overlap between stars that are of quite different brightness. For instance, the detection algorithm may not be able to detect a faint and bright star very close together in the first iteration, but they will be detected in the next iteration after the brighter stars have been fit and subtracted. Like `~photutils.psf.BasicPSFPhotometry`, it does not include implementations of the stages of this process, but it provides the structure in which those stages run. `~photutils.psf.DAOPhotPSFPhotometry` is a special case of `~photutils.psf.IterativelySubtractedPSFPhotometry`. Unlike `~photutils.psf.IterativelySubtractedPSFPhotometry` and `~photutils.psf.BasicPSFPhotometry`, the class includes specific implementations of the stages of the photometric measurements, tuned to reproduce the algorithms used for the DAOPHOT code. Specifically, the ``finder``, ``group_maker``, ``bkg_estimator`` attributes are set to the `~photutils.detection.DAOStarFinder`, `~photutils.psf.DAOGroup`, and `~photutils.background.MMMBackground`, respectively. Therefore, users need to input the parameters of those classes to set up a `~photutils.psf.DAOPhotPSFPhotometry` object, rather than providing objects to do these stages (which is what the other classes require). Those classes and all the classes they *use* for the steps in the photometry process can always be replaced by user-supplied functions if you wish to customize any stage of the photometry process. This makes the machinery very flexible, while still providing a "batteries included" approach with a default implementation that's suitable for many use cases. Basic Usage ^^^^^^^^^^^ The basic usage of, e.g., `~photutils.psf.IterativelySubtractedPSFPhotometry` is as follows: .. doctest-skip:: >>> # create an IterativelySubtractedPSFPhotometry object >>> from photutils.psf import IterativelySubtractedPSFPhotometry >>> my_photometry = IterativelySubtractedPSFPhotometry( ... finder=my_finder, group_maker=my_group_maker, ... bkg_estimator=my_bkg_estimator, psf_model=my_psf_model, ... fitter=my_fitter, niters=3, fitshape=(7,7)) >>> # get photometry results >>> photometry_results = my_photometry(image=my_image) >>> # get residual image >>> residual_image = my_photometry.get_residual_image() Where ``my_finder``, ``my_group_maker``, and ``my_bkg_estimator`` may be any suitable class or callable function. This approach allows one to customize every part of the photometry process provided that their input/output are compatible with the input/ouput expected by `~photutils.psf.IterativelySubtractedPSFPhotometry`. `photutils.psf` provides all the necessary classes to reproduce the DAOPHOT algorithm, but any individual part of that algorithm can be swapped for a user-defined function. See the API documentation for precise details on what these classes or functions should look like. Performing PSF Photometry ^^^^^^^^^^^^^^^^^^^^^^^^^ Let's take a look at a simple example with simulated stars whose PSF is assumed to be Gaussian. First let's create an image with four overlapping stars:: >>> import numpy as np >>> from astropy.table import Table >>> from photutils.datasets import (make_random_gaussians_table, ... make_noise_image, ... make_gaussian_sources_image) >>> sigma_psf = 2.0 >>> sources = Table() >>> sources['flux'] = [700, 800, 700, 800] >>> sources['x_mean'] = [12, 17, 12, 17] >>> sources['y_mean'] = [15, 15, 20, 20] >>> sources['x_stddev'] = sigma_psf*np.ones(4) >>> sources['y_stddev'] = sources['x_stddev'] >>> sources['theta'] = [0, 0, 0, 0] >>> sources['id'] = [1, 2, 3, 4] >>> tshape = (32, 32) >>> image = (make_gaussian_sources_image(tshape, sources) + ... make_noise_image(tshape, distribution='poisson', mean=6., ... random_state=1) + ... make_noise_image(tshape, distribution='gaussian', mean=0., ... stddev=2., random_state=1)) .. doctest-requires:: matplotlib >>> from matplotlib import rcParams >>> rcParams['font.size'] = 13 >>> import matplotlib.pyplot as plt >>> plt.imshow(image, cmap='viridis', aspect=1, interpolation='nearest', ... origin='lower') # doctest: +SKIP >>> plt.title('Simulated data') # doctest: +SKIP >>> plt.colorbar(orientation='horizontal', fraction=0.046, pad=0.04) # doctest: +SKIP .. plot:: import numpy as np from astropy.table import Table from photutils.datasets import (make_random_gaussians_table, make_noise_image, make_gaussian_sources_image) sigma_psf = 2.0 sources = Table() sources['flux'] = [700, 800, 700, 800] sources['x_mean'] = [12, 17, 12, 17] sources['y_mean'] = [15, 15, 20, 20] sources['x_stddev'] = sigma_psf*np.ones(4) sources['y_stddev'] = sources['x_stddev'] sources['theta'] = [0, 0, 0, 0] sources['id'] = [1, 2, 3, 4] tshape = (32, 32) image = (make_gaussian_sources_image(tshape, sources) + make_noise_image(tshape, distribution='poisson', mean=6., random_state=1) + make_noise_image(tshape, distribution='gaussian', mean=0., stddev=2., random_state=1)) from matplotlib import rcParams rcParams['font.size'] = 13 import matplotlib.pyplot as plt plt.imshow(image, cmap='viridis', aspect=1, interpolation='nearest', origin='lower') plt.title('Simulated data') plt.colorbar(orientation='horizontal', fraction=0.046, pad=0.04) Then let's import the required classes to set up a `~photutils.psf.IterativelySubtractedPSFPhotometry` object:: >>> from photutils.detection import IRAFStarFinder >>> from photutils.psf import IntegratedGaussianPRF, DAOGroup >>> from photutils.background import MMMBackground, MADStdBackgroundRMS >>> from astropy.modeling.fitting import LevMarLSQFitter >>> from astropy.stats import gaussian_sigma_to_fwhm Let's then instantiate and use the objects: .. doctest-requires:: scipy >>> bkgrms = MADStdBackgroundRMS() >>> std = bkgrms(image) >>> iraffind = IRAFStarFinder(threshold=3.5*std, ... fwhm=sigma_psf*gaussian_sigma_to_fwhm, ... minsep_fwhm=0.01, roundhi=5.0, roundlo=-5.0, ... sharplo=0.0, sharphi=2.0) >>> daogroup = DAOGroup(2.0*sigma_psf*gaussian_sigma_to_fwhm) >>> mmm_bkg = MMMBackground() >>> fitter = LevMarLSQFitter() >>> psf_model = IntegratedGaussianPRF(sigma=sigma_psf) >>> from photutils.psf import IterativelySubtractedPSFPhotometry >>> photometry = IterativelySubtractedPSFPhotometry(finder=iraffind, ... group_maker=daogroup, ... bkg_estimator=mmm_bkg, ... psf_model=psf_model, ... fitter=LevMarLSQFitter(), ... niters=1, fitshape=(11,11)) >>> result_tab = photometry(image=image) >>> residual_image = photometry.get_residual_image() Note that the parameters values for the finder class, i.e., `~photutils.detection.IRAFStarFinder`, are completely chosen in an arbitrary manner and optimum values do vary according to the data. As mentioned before, the way to actually do the photometry is by using ``photometry`` as a function-like call. It's worth noting that ``image`` does not need to be background subtracted. The subtraction is done during the photometry process with the attribute ``bkg`` that was used to set up ``photometry``. Now, let's compare the simulated and the residual images: .. doctest-skip:: >>> plt.subplot(1, 2, 1) >>> plt.imshow(image, cmap='viridis', aspect=1, interpolation='nearest', origin='lower') >>> plt.title('Simulated data') >>> plt.colorbar(orientation='horizontal', fraction=0.046, pad=0.04) >>> plt.subplot(1 ,2, 2) >>> plt.imshow(residual_image, cmap='viridis', aspect=1, ... interpolation='nearest', origin='lower') >>> plt.title('Residual Image') >>> plt.colorbar(orientation='horizontal', fraction=0.046, pad=0.04) >>> plt.show() .. plot:: import numpy as np from photutils.datasets import (make_random_gaussians_table, make_noise_image, make_gaussian_sources_image) from astropy.table import Table sigma_psf = 2.0 sources = Table() sources['flux'] = [700, 800, 700, 800] sources['x_mean'] = [12, 17, 12, 17] sources['y_mean'] = [15, 15, 20, 20] sources['x_stddev'] = sigma_psf*np.ones(4) sources['y_stddev'] = sources['x_stddev'] sources['theta'] = [0, 0, 0, 0] sources['id'] = [1, 2, 3, 4] tshape = (32, 32) image = (make_gaussian_sources_image(tshape, sources) + make_noise_image(tshape, distribution='poisson', mean=6., random_state=1) + make_noise_image(tshape, distribution='gaussian', mean=0., stddev=2., random_state=1)) from photutils.detection import IRAFStarFinder from photutils.psf import IntegratedGaussianPRF, DAOGroup from photutils.background import MMMBackground, MADStdBackgroundRMS from astropy.modeling.fitting import LevMarLSQFitter from astropy.stats import gaussian_sigma_to_fwhm bkgrms = MADStdBackgroundRMS() std = bkgrms(image) iraffind = IRAFStarFinder(threshold=3.5*std, fwhm=sigma_psf*gaussian_sigma_to_fwhm, minsep_fwhm=0.01, roundhi=5.0, roundlo=-5.0, sharplo=0.0, sharphi=2.0) daogroup = DAOGroup(2.0*sigma_psf*gaussian_sigma_to_fwhm) mmm_bkg = MMMBackground() psf_model = IntegratedGaussianPRF(sigma=sigma_psf) fitter = LevMarLSQFitter() from photutils.psf import IterativelySubtractedPSFPhotometry photometry = IterativelySubtractedPSFPhotometry(finder=iraffind, group_maker=daogroup, bkg_estimator=mmm_bkg, psf_model=psf_model, fitter=LevMarLSQFitter(), niters=1, fitshape=(11,11)) result_tab = photometry(image=image) residual_image = photometry.get_residual_image() from matplotlib import rcParams rcParams['font.size'] = 13 import matplotlib.pyplot as plt plt.subplot(1, 2, 1) plt.imshow(image, cmap='viridis', aspect=1, interpolation='nearest', origin='lower') plt.title('Simulated data') plt.colorbar(orientation='horizontal', fraction=0.046, pad=0.04) plt.subplot(1 ,2, 2) plt.imshow(residual_image, cmap='viridis', aspect=1, interpolation='nearest', origin='lower') plt.title('Residual Image') plt.colorbar(orientation='horizontal', fraction=0.046, pad=0.04) plt.show() Performing PSF Photometry with Fixed Centroids ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In case that the centroids positions of the stars are known a priori, then they can be held fixed during the fitting process and the optimizer will only consider flux as a variable. To do that, one has to set the ``fixed`` attribute for the centroid parameters in ``psf`` as ``True``. Consider the previous example after the line ``psf_model = IntegratedGaussianPRF(sigma=sigma_psf)``: .. doctest-skip:: >>> psf_model.x_0.fixed = True >>> psf_model.y_0.fixed = True >>> pos = Table(names=['x_0', 'y_0'], data=[sources['x_mean'], ... sources['y_mean']]) .. doctest-skip:: >>> photometry = BasicPSFPhotometry(group_maker=daogroup, ... bkg_estimator=mmm_bkg, ... psf_model=psf_model, ... fitter=LevMarLSQFitter(), ... fitshape=(11,11)) >>> result_tab = photometry(image=image, init_guesses=pos) >>> residual_image = photometry.get_residual_image() .. doctest-skip:: >>> plt.subplot(1, 2, 1) >>> plt.imshow(image, cmap='viridis', aspect=1, ... interpolation='nearest', origin='lower') >>> plt.title('Simulated data') >>> plt.colorbar(orientation='horizontal', fraction=0.046, pad=0.04) >>> plt.subplot(1 ,2, 2) >>> plt.imshow(residual_image, cmap='viridis', aspect=1, ... interpolation='nearest', origin='lower') >>> plt.title('Residual Image') >>> plt.colorbar(orientation='horizontal', fraction=0.046, pad=0.04) .. plot:: import numpy as np from photutils.datasets import (make_random_gaussians_table, make_noise_image, make_gaussian_sources_image) from astropy.table import Table sigma_psf = 2.0 sources = Table() sources['flux'] = [700, 800, 700, 800] sources['x_mean'] = [12, 17, 12, 17] sources['y_mean'] = [15, 15, 20, 20] sources['x_stddev'] = sigma_psf*np.ones(4) sources['y_stddev'] = sources['x_stddev'] sources['theta'] = [0, 0, 0, 0] sources['id'] = [1, 2, 3, 4] tshape = (32, 32) image = (make_gaussian_sources_image(tshape, sources) + make_noise_image(tshape, distribution='poisson', mean=6., random_state=1) + make_noise_image(tshape, distribution='gaussian', mean=0., stddev=2., random_state=1)) from photutils.detection import IRAFStarFinder from photutils.psf import IntegratedGaussianPRF, DAOGroup from photutils.background import MMMBackground, MADStdBackgroundRMS from astropy.modeling.fitting import LevMarLSQFitter from astropy.stats import gaussian_sigma_to_fwhm bkgrms = MADStdBackgroundRMS() std = bkgrms(image) daogroup = DAOGroup(2.0*sigma_psf*gaussian_sigma_to_fwhm) mmm_bkg = MMMBackground() psf_model = IntegratedGaussianPRF(sigma=sigma_psf) psf_model.x_0.fixed = True psf_model.y_0.fixed = True pos = Table(names=['x_0', 'y_0'], data=[sources['x_mean'], sources['y_mean']]) fitter = LevMarLSQFitter() from photutils.psf import BasicPSFPhotometry photometry = BasicPSFPhotometry(group_maker=daogroup, bkg_estimator=mmm_bkg, psf_model=psf_model, fitter=LevMarLSQFitter(), fitshape=(11,11)) result_tab = photometry(image=image, init_guesses=pos) residual_image = photometry.get_residual_image() from matplotlib import rcParams import matplotlib.pyplot as plt rcParams['font.size'] = 13 plt.subplot(1, 2, 1) plt.imshow(image, cmap='viridis', aspect=1, interpolation='nearest', origin='lower') plt.title('Simulated data') plt.colorbar(orientation='horizontal', fraction=0.046, pad=0.04) plt.subplot(1 ,2, 2) plt.imshow(residual_image, cmap='viridis', aspect=1, interpolation='nearest', origin='lower') plt.title('Residual Image') plt.colorbar(orientation='horizontal', fraction=0.046, pad=0.04) plt.show() Fitting additional parameters ----------------------------- The PSF photometry classes can also be used to fit more model parameters than just the flux and center positions. While a more realistic use case might be fitting sky backgrounds, or shape parameters of galaxies, here we use the ``sigma`` parameter in `~photutils.psf.IntegratedGaussianPRF` as the simplest possible example of this feature. (For actual PSF photometry of stars you would *not* want to do this, because the shape of the PSF should be set by bright stars or an optical model and held fixed when fitting.) First, let us instantiate a PSF model object: .. doctest-skip:: >>> gaussian_prf = IntegratedGaussianPRF() The attribute ``fixed`` for the ``sigma`` parameter is set to ``True`` by default, i.e., ``sigma`` is not considered during the fitting process. Let's first change this behavior: .. doctest-skip:: >>> gaussian_prf.sigma.fixed = False In addition, we need to indicate the initial guess which will be used in during the fitting process. By the default, the initial guess is taken as the default value of ``sigma``, but we can change that by doing: .. doctest-skip:: >>> gaussian_prf.sigma.value = 2.05 Now, let's create a simulated image which has a brighter star and one overlapping fainter companion so that the detection algorithm won't be able to identify it, and hence we should use `~photutils.psf.IterativelySubtractedPSFPhotometry` to measure the fainter star as well. Also, note that both of the stars have ``sigma=2.0``. .. plot:: :include-source: import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import LogNorm from photutils.datasets import (make_random_gaussians_table, make_noise_image, make_gaussian_sources_image) from photutils.psf import (IterativelySubtractedPSFPhotometry, BasicPSFPhotometry) from photutils import MMMBackground from photutils.psf import IntegratedGaussianPRF, DAOGroup from photutils.detection import DAOStarFinder from photutils.detection import IRAFStarFinder from astropy.table import Table from astropy.modeling.fitting import LevMarLSQFitter sources = Table() sources['flux'] = [10000, 1000] sources['x_mean'] = [18, 9] sources['y_mean'] = [17, 21] sources['x_stddev'] = [2] * 2 sources['y_stddev'] = sources['x_stddev'] sources['theta'] = [0] * 2 tshape = (32, 32) image = (make_gaussian_sources_image(tshape, sources) + make_noise_image(tshape, distribution='poisson', mean=6., random_state=1) + make_noise_image(tshape, distribution='gaussian', mean=0., stddev=2., random_state=1)) vmin, vmax = np.percentile(image, [5, 95]) plt.imshow(image, cmap='viridis', aspect=1, interpolation='nearest', origin='lower', norm=LogNorm(vmin=vmin, vmax=vmax)) Let's instantiate the necessary objects in order to use an `~photutils.psf.IterativelySubtractedPSFPhotometry` to perform photometry: .. doctest-requires:: scipy >>> daogroup = DAOGroup(crit_separation=8) >>> mmm_bkg = MMMBackground() >>> iraffind = IRAFStarFinder(threshold=2.5*mmm_bkg(image), fwhm=4.5) >>> fitter = LevMarLSQFitter() >>> gaussian_prf = IntegratedGaussianPRF(sigma=2.05) >>> gaussian_prf.sigma.fixed = False >>> itr_phot_obj = IterativelySubtractedPSFPhotometry(finder=iraffind, ... group_maker=daogroup, ... bkg_estimator=mmm_bkg, ... psf_model=psf_model, ... fitter=fitter, ... fitshape=(11, 11), ... niters=2) Now, let's use the callable ``itr_phot_obj`` to perform photometry: .. doctest-requires:: scipy >>> phot_results = itr_phot_obj(image) >>> phot_results['id', 'group_id', 'iter_detected', 'x_0', 'y_0', 'flux_0'] #doctest: +SKIP id group_id iter_detected x_0 y_0 flux_0 --- -------- ------------- ------------- ------------- ------------- 1 1 1 18.0045935148 17.0060558543 9437.07321281 1 1 2 9.06141447183 21.0680052846 977.163727416 >>> phot_results['sigma_0', 'sigma_fit', 'x_fit', 'y_fit', 'flux_fit'] #doctest: +SKIP sigma_0 sigma_fit x_fit y_fit flux_fit ------- ------------- ------------- ------------- ------------- 2.05 1.98092026939 17.9995106906 17.0039419384 10016.4470148 2.05 1.98516037471 9.12116345703 21.0599164498 1036.79115883 We can see that ``sigma_0`` (the initial guess for ``sigma``) was assigned to the value we used when creating the PSF model. Let's take a look at the residual image:: >>> plt.imshow(itr_phot_obj.get_residual_image(), cmap='viridis', ... aspect=1, interpolation='nearest', origin='lower') #doctest: +SKIP .. plot:: from photutils.datasets import (make_random_gaussians_table, make_noise_image, make_gaussian_sources_image) import matplotlib.pyplot as plt from photutils.psf import (IterativelySubtractedPSFPhotometry, BasicPSFPhotometry) from astropy.stats import gaussian_sigma_to_fwhm from astropy.table import Table from photutils import MMMBackground from photutils.psf import IntegratedGaussianPRF, DAOGroup from photutils.detection import DAOStarFinder from astropy.modeling.fitting import LevMarLSQFitter from photutils.detection import IRAFStarFinder sources = Table() sources['flux'] = [10000, 1000] sources['x_mean'] = [18, 9] sources['y_mean'] = [17, 21] sources['x_stddev'] = [2] * 2 sources['y_stddev'] = sources['x_stddev'] sources['theta'] = [0] * 2 tshape = (32, 32) image = (make_gaussian_sources_image(tshape, sources) + make_noise_image(tshape, distribution='poisson', mean=6., random_state=1) + make_noise_image(tshape, distribution='gaussian', mean=0., stddev=2., random_state=1)) daogroup = DAOGroup(crit_separation=8) mmm_bkg = MMMBackground() psf_model = IntegratedGaussianPRF(sigma=2.05) iraffind = IRAFStarFinder(threshold=2.5*mmm_bkg(image), fwhm=4.5) fitter = LevMarLSQFitter() psf_model.sigma.fixed = False itr_phot_obj = IterativelySubtractedPSFPhotometry( finder=iraffind, group_maker=daogroup, bkg_estimator=mmm_bkg, psf_model=psf_model, fitter=fitter, fitshape=(11, 11), niters=2) phot_results_itr = itr_phot_obj(image) plt.imshow(itr_phot_obj.get_residual_image(), cmap='viridis', aspect=1, interpolation='nearest', origin='lower') Additional Example Notebooks (online) ------------------------------------- * `PSF photometry on artificial Gaussian stars in crowded fields `_ * `PSF photometry on artificial Gaussian stars `_ * `PSF/PRF Photometry on Spitzer Data `_ References ---------- `Spitzer PSF vs. PRF `_ `Kepler PSF calibration `_ `The Kepler Pixel Response Function `_ `Stetson, Astronomical Society of the Pacific, Publications, (ISSN 0004-6280), vol. 99, March 1987, p. 191-222. `_ `Anderson & King, Astronomical Society of the Pacific, Publications, Volume 112, Issue 776, pp. 1360-1382, Nov 2000 `_ Reference/API ------------- .. automodapi:: photutils.psf :no-heading: .. automodapi:: photutils.psf.sandbox photutils-0.7.2/docs/psf_matching.rst0000644000214200020070000002175113572573650022105 0ustar lbradleySTSCI\science00000000000000.. _psf_matching: PSF Matching (`photutils.psf.matching`) ======================================= Introduction ------------ This subpackage contains tools to generate kernels for matching point spread functions (PSFs). Matching PSFs ------------- Photutils provides a function called :func:`~photutils.psf.matching.create_matching_kernel` that generates a matching kernel between two PSFs using the ratio of Fourier transforms (see e.g., `Gordon et al. 2008`_; `Aniano et al. 2011`_). For this first simple example, let's assume our source and target PSFs are noiseless 2D Gaussians. The "high-resolution" PSF will be a Gaussian with :math:`\sigma=3`. The "low-resolution" PSF will be a Gaussian with :math:`\sigma=5`:: >>> import numpy as np >>> from astropy.modeling.models import Gaussian2D >>> y, x = np.mgrid[0:51, 0:51] >>> gm1 = Gaussian2D(100, 25, 25, 3, 3) >>> gm2 = Gaussian2D(100, 25, 25, 5, 5) >>> g1 = gm1(x, y) >>> g2 = gm2(x, y) >>> g1 /= g1.sum() >>> g2 /= g2.sum() For these 2D Gaussians, the matching kernel should be a 2D Gaussian with :math:`\sigma=4` (``sqrt(5**2 - 3**2)``). Let's create the matching kernel using a Fourier ratio method. Note that the input source and target PSFs must have the same shape and pixel scale. >>> from photutils import create_matching_kernel >>> kernel = create_matching_kernel(g1, g2) Let's plot the result: .. plot:: :include-source: import numpy as np from astropy.modeling.models import Gaussian2D from photutils import create_matching_kernel import matplotlib.pyplot as plt y, x = np.mgrid[0:51, 0:51] gm1 = Gaussian2D(100, 25, 25, 3, 3) gm2 = Gaussian2D(100, 25, 25, 5, 5) g1 = gm1(x, y) g2 = gm2(x, y) g1 /= g1.sum() g2 /= g2.sum() kernel = create_matching_kernel(g1, g2) plt.imshow(kernel, cmap='Greys_r', origin='lower') plt.colorbar() We quickly observe that the result is not as expected. This is because of high-frequency noise in the Fourier transforms (even though these are noiseless PSFs, there is floating-point noise in the ratios). Using the Fourier ratio method, one must filter the high-frequency noise from the Fourier ratios. This is performed by inputing a `window function `_, which may be a function or a callable object. In general, the user will need to exercise some care when defining a window function. For more information, please see `Aniano et al. 2011`_. Photutils provides the following window classes: * `~photutils.psf.matching.HanningWindow` * `~photutils.psf.matching.TukeyWindow` * `~photutils.psf.matching.CosineBellWindow` * `~photutils.psf.matching.SplitCosineBellWindow` * `~photutils.psf.matching.TopHatWindow` Here are plots of 1D cuts across the center of the 2D window functions: .. plot:: :include-source: from photutils import (HanningWindow, TukeyWindow, CosineBellWindow, SplitCosineBellWindow, TopHatWindow) import matplotlib.pyplot as plt w1 = HanningWindow() w2 = TukeyWindow(alpha=0.5) w3 = CosineBellWindow(alpha=0.5) w4 = SplitCosineBellWindow(alpha=0.4, beta=0.3) w5 = TopHatWindow(beta=0.4) shape = (101, 101) y0 = (shape[0] - 1) // 2 plt.figure() plt.subplots_adjust(wspace=0.4, hspace=0.4) plt.subplot(2, 3, 1) plt.plot(w1(shape)[y0, :]) plt.title('Hanning') plt.xlabel('x') plt.ylim((0, 1.1)) plt.subplot(2, 3, 2) plt.plot(w2(shape)[y0, :]) plt.title('Tukey') plt.xlabel('x') plt.ylim((0, 1.1)) plt.subplot(2, 3, 3) plt.plot(w3(shape)[y0, :]) plt.title('Cosine Bell') plt.xlabel('x') plt.ylim((0, 1.1)) plt.subplot(2, 3, 4) plt.plot(w4(shape)[y0, :]) plt.title('Split Cosine Bell') plt.xlabel('x') plt.ylim((0, 1.1)) plt.subplot(2, 3, 5) plt.plot(w5(shape)[y0, :], label='Top Hat') plt.title('Top Hat') plt.xlabel('x') plt.ylim((0, 1.1)) However, the user may input any function or callable object to generate a custom window function. In this example, because these are noiseless PSFs, we will use a `~photutils.psf.matching.TopHatWindow` object as the low-pass filter:: >>> from photutils import TopHatWindow >>> window = TopHatWindow(0.35) >>> kernel = create_matching_kernel(g1, g2, window=window) Note that the output matching kernel from :func:`~photutils.psf.matching.create_matching_kernel` is always normalized such that the kernel array sums to 1:: >>> print(kernel.sum()) # doctest: +FLOAT_CMP 1.0 Let's display the new matching kernel: .. plot:: :include-source: import numpy as np from astropy.modeling.models import Gaussian2D from photutils import create_matching_kernel, TopHatWindow import matplotlib.pyplot as plt y, x = np.mgrid[0:51, 0:51] gm1 = Gaussian2D(100, 25, 25, 3, 3) gm2 = Gaussian2D(100, 25, 25, 5, 5) g1 = gm1(x, y) g2 = gm2(x, y) g1 /= g1.sum() g2 /= g2.sum() window = TopHatWindow(0.35) kernel = create_matching_kernel(g1, g2, window=window) plt.imshow(kernel, cmap='Greys_r', origin='lower') plt.colorbar() As desired, the result is indeed a 2D Gaussian with a :math:`\sigma=4`. Here we will show 1D cuts across the center of the kernel images: .. plot:: :include-source: import numpy as np from astropy.modeling.models import Gaussian2D from photutils import create_matching_kernel, TopHatWindow import matplotlib.pyplot as plt y, x = np.mgrid[0:51, 0:51] gm1 = Gaussian2D(100, 25, 25, 3, 3) gm2 = Gaussian2D(100, 25, 25, 5, 5) gm3 = Gaussian2D(100, 25, 25, 4, 4) g1 = gm1(x, y) g2 = gm2(x, y) g3 = gm3(x, y) g1 /= g1.sum() g2 /= g2.sum() g3 /= g3.sum() window = TopHatWindow(0.35) kernel = create_matching_kernel(g1, g2, window=window) kernel /= kernel.sum() plt.plot(kernel[25, :], label='Matching kernel') plt.plot(g3[25, :], label='$\sigma=4$ Gaussian') plt.xlabel('x') plt.ylabel('Flux') plt.legend() plt.ylim((0.0, 0.011)) Matching IRAC PSFs ------------------ For this example, let's generate a matching kernel to go from the Spitzer/IRAC channel 1 (3.6 microns) PSF to the channel 4 (8.0 microns) PSF. We load the PSFs using the :func:`~photutils.datasets.load_irac_psf` convenience function:: >>> from photutils.datasets import load_irac_psf >>> ch1_hdu = load_irac_psf(channel=1) # doctest: +REMOTE_DATA >>> ch4_hdu = load_irac_psf(channel=4) # doctest: +REMOTE_DATA >>> ch1 = ch1_hdu.data # doctest: +REMOTE_DATA >>> ch4 = ch4_hdu.data # doctest: +REMOTE_DATA Let's display the images: .. plot:: :include-source: import matplotlib.pyplot as plt from astropy.visualization import LogStretch from astropy.visualization.mpl_normalize import ImageNormalize from photutils.datasets import load_irac_psf ch1_hdu = load_irac_psf(channel=1) ch4_hdu = load_irac_psf(channel=4) ch1 = ch1_hdu.data ch4 = ch4_hdu.data norm = ImageNormalize(stretch=LogStretch()) plt.figure(figsize=(9, 4)) plt.subplot(1, 2, 1) plt.imshow(ch1, norm=norm, cmap='viridis', origin='lower') plt.title('IRAC channel 1 PSF') plt.subplot(1, 2, 2) plt.imshow(ch4, norm=norm, cmap='viridis', origin='lower') plt.title('IRAC channel 4 PSF') For this example, we will use the :class:`~photutils.psf.matching.CosineBellWindow` for the low-pass window. Note that these Spitzer/IRAC channel 1 and 4 PSFs have the same shape and pixel scale. If that is not the case, one can use the :func:`~photutils.psf.matching.resize_psf` convenience function to resize a PSF image. Typically, one would interpolate the lower-resolution PSF to the same size as the higher-resolution PSF. .. doctest-skip:: >>> from photutils import CosineBellWindow, create_matching_kernel >>> window = CosineBellWindow(alpha=0.35) >>> kernel = create_matching_kernel(ch1, ch4, window=window) Let's display the matching kernel result: .. plot:: :include-source: import matplotlib.pyplot as plt from astropy.visualization import LogStretch from astropy.visualization.mpl_normalize import ImageNormalize from photutils.datasets import load_irac_psf from photutils import CosineBellWindow, create_matching_kernel ch1_hdu = load_irac_psf(channel=1) ch4_hdu = load_irac_psf(channel=4) ch1 = ch1_hdu.data ch4 = ch4_hdu.data norm = ImageNormalize(stretch=LogStretch()) window = CosineBellWindow(alpha=0.35) kernel = create_matching_kernel(ch1, ch4, window=window) plt.imshow(kernel, norm=norm, cmap='viridis', origin='lower') plt.colorbar() plt.title('Matching kernel') The Spitzer/IRAC channel 1 image could then be convolved with this matching kernel to produce an image with the same resolution as the channel 4 image. Reference/API ------------- .. automodapi:: photutils.psf.matching :no-heading: .. _Gordon et al. 2008: http://adsabs.harvard.edu/abs/2008ApJ...682..336G .. _Aniano et al. 2011: http://adsabs.harvard.edu/abs/2011PASP..123.1218A photutils-0.7.2/docs/psf_spec/0000755000214200020070000000000013573510273020476 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/docs/psf_spec/background_estimator.rst0000644000214200020070000000415313547426552025450 0ustar lbradleySTSCI\science00000000000000BackgroundEstimator =================== EJT: Existing code documented at https://photutils.readthedocs.io/en/stable/api/photutils.background.BackgroundBase.html - while the ``__call__`` function has no docstring, the ``calc_background`` function is the actual block API. I'm providing this as an *example* block because it is heavily used in other parts of `photutils` and therefore probably should not be changed much unless absolutely necessary. A single sentence summarizing this block. A longer descrption. Can be multiple paragraphs. You can link to other things like `photutils.background`. Parameters ---------- data : array_like or `~numpy.ma.MaskedArray` The array for which to calculate the background value. axis : int or `None`, optional The array axis along which the background is calculated. If `None`, then the entire array is used. Returns ------- result : float or `~numpy.ma.MaskedArray` The calculated background value. If ``axis`` is `None` then a scalar will be returned, otherwise a `~numpy.ma.MaskedArray` will be returned. Methods ------- This block requires no methods beyond ``__call__()``. Example Usage ------------- A variety of implementations of this block already exist in ``photutils``. A canononical example is the mode estimation algorithm ``3 * median - 2 * mean``. This can be done on an array called ``image_data`` by using the block like so:: from photutils.background import ModeEstimatorBackground bkg_estimator = ModeEstimatorBackground() bkg_value = bkg_estimator(image_data) The median/mean parameter values can be adjusted as keyword arguments to the estimator object if desired:: tweaked_bkg_estimator = ModeEstimatorBackground(median_factor=3.2, mean_factor=1.8) new_bkg_value = tweaked_bkg_estimator(image_data) The estimator will also accept a sigma clipping object that automatically does sigma clipping before the background is subtracted, like so:: from astropy.stats import SigmaClip clipped_bkg_estimator = ModeEstimatorBackground(sigma_clip=SigmaClip(sigma=3.)) clipped_bkg_value = clipped_bkg_estimator(image_data) photutils-0.7.2/docs/psf_spec/block_diagram.png0000644000214200020070000163221713547426552024005 0ustar lbradleySTSCI\science00000000000000‰PNG  IHDR°ÔÒgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ< pHYs  šœYiTXtXML:com.adobe.xmp 1 LÂ'Y@IDATxt½bÞ8²k;I÷yÿ'žÎÅZ@Irï¹´%‘U(Ô)JŸã$¿þúýÿþü‡ö럜èþöúëWFœþùõŸ?þüçׯ¢ü´Èb“ÜŸð ’J.‘ýúÏ?ªø ·tŒ«£tPðýk–ð ùo”áA‚^)•Ô^ia¼Ø7Ç¢ÑÅ>ú_ä÷áªij[ЩAéuAF¿‘L/dàL« ë*½èÓ§”WSk, €­7F²§¶AüùõÍ ãº V4âýEßü‚1úh½!Þ€rùM|ñÿƒØ ú²N×F\à%’âwò+–´ôó-ÏD” Ä‚ œÂõç¿â›BÀ€ÒÌ! ¬­2ɦz”ʉ‹Ö<b%³ð©«9ÞúÁ–Ößcº´Ùmal"ë:ª”›ƒ\³!Bj„ÊõÍ5­á·xAÁ¦• Û©sk†œ¾-DÎuÖµŒ%a€wYãÖÊŸ?Ü—eþ@m~‰;þÍë?ÿ cîPS-–µkƒ‹$kbÌÕTþŸýâŸq% •M>s"wé˜÷´?ò`4Þ ˜NH4aE±ÆÑfL¾ù¢ÿÖ½¨_‰ãÏïæçzJ°bS˜x—°~ ÝÖSÆ©Dm´#VZôŸÜ+qjèBï|xë‚8‰Lâþ‚æáÝG‚µ<ÁËeÆ1ŒPü2eH ˆkx‰µë„Xr´&Œ……ƒì1.c:kJƒ5ê¸Ø›¨ ÒˆácÔyF#¸Öž>qC:ÿò“ë-ÄäÄAiÝ/‰è¢j¿{{dámk1!Ã|0¥ã»W¡/oÎôyæ¾*"îâŸ/ô>ëÀÙ‡ž˜ý•>÷¬VÓŒÿ’ JÝ:Ô®AÞœD\P:±+×ßr0î-¾Ì÷Öfçÿ¹K¤bì‰ >ˆ…øÿ›®‚¯¡k'ñjÜ$øÎŸu_Î7ôÄ‘ÎkI}ZGç‹Ù¸r”«kàÓOn­x0ÆW+ÎFk]êGa¿¹\}W0÷>ò„a 0HØzfع#žã; «>¼Ñ´¥×ïÔ vß>Hæ+vÚô“®s3[bNŸºÔ‚ sµ¦kεòŸ>KÛ‹ÏWà½[qÑgj×Ac¦>ÄT_®iÌãƒL]v–”uƒƒSGÚu ›l†û¨F˜Ãgvä›qêV*Jݹ_ȱUxçáæ¤>¢‡â3¿%ˆÕÝšÂÕŠyÏàùŠïã{Þ§ã‡-à R6œ?M¤AHšÓ›”Ù‰5ièÿGMbµsLä|«¦€ô3°W5²>°¢ë 1Ñ·…5}­`ÌwS¢ëô¼¯Fƒ/Žœ±õ&r”~Æy«1?à'E4VMrŠŠÈAÜú8þµ‹7ââV~b@2‡FÝg "FJ(ù’ß“‡ xÁ¢ïÙ¾Lóh‡ ¾fé4ÖNëÅÙ¼Ž!ÁÕ.6ÖÞM!X\Ñ4†ô¬yÔh\?òú°' Låç,Rš’#)µUÃMæòx”%„G I’±*¼$wõ‹Ý~}“M“ç¤ wjLå/ulnÍÌÚn3ý1gÆ¥ÜãÈúòeÀ8æ„åô€‹GÓ‡oìâëØxÄu\"A‹ë¼´–Ì•Ïè6mÁ5ZÂ{í+«¿èðÛ‹¨c¢¬RÕƒs„M³ÀŒºŸ›ºÔ§‹0:4r:ùãP#É–¯‚›Od[–óÅ{…qåþÔ#÷/msE.Øøðå«.ØÈüÒc·Eebëòå”Çç§µRàËØ8 ` üàÂYÅv¼vá¤.ÃSs49ýb¯2_¢¥åœ1×çÞgxmë°µÂ0x_piÜëa3úÅÃuzmÜ¢qìÁ)µÍ…¨©²Uxæ90b6/°C Y:¬që=Lú¨âÉ/®š*-—Æp`Ç•n¼ÞË?2_®ÕŒ7Á ~t‘•?~£ßÑ'×IVr†—'¶€Í'ð‘YzÊZ4OQÁþ]­¡ë ½Ù´ð­u³”uتøœ€§O!ƒ‹ú¹pÊ>ž+Ÿóúð'ÖŸMʉê)ö}\™¤É‹©¯q¡ðøcŠ/{>CÒ×ÁïXf¥·H‘Á]U?|`ÞþgŒìƒxƆ´óšþ‚ÇÚC ,è¬Ò‡ÄÛÜ_õ¤¥ï…ëéÞKuò‡ûbôÆq+¡kI¥AQ³è<”bu¯å«¸Q’qzÎaä©AŸpÍçn½1ìý5|+’AÖ‘ó·5à 7xãÒ˜(8ðÌþM™3v¨ªä_¡ž8](±Y ÖLä—hÞ—¸iÒÌ+]íMf}µœˆ—|á9›*Ÿü´F×}~d½Dzk z£È®ò!̵cm¢R¤ë|k¡µâÚ§ý ¿ûTÈæ ñcö6jmE""û̇þ޸ȯsî°›sˆÛ𯸦ÁÇÑÌ8ÞW|^DMÌb¶Öy†8»r™×;u%Ä€ËÇaœœ0, -8Ã'zÂñ¸ ™Ù'X7ΨèQ’¢87É"¯%×܆ô àç°ØôÃeaË w{œYŽprpÞÍÊ8ßb«bð4ä|…÷Á‰"s3xïÛÜào|‚Â×htOÌíä\^%@çy¯5¡¨¾•n}Àü¦˜ª2âš·ÚRøËWúµ=fF´,‡M•z„ÐRl¾µ½ùŒ|˜m5È¢õ†­_ ±‰QĆ„½ÈcXü$æ¦ëc˜¼¬½…⩟ènaLj/€OMàh3· \ØÖñ0øæÆ!Z»‹Oâœp:Çoø‘½v]c‹3Ö_£Ç ¼1Ï®78˜Ê];°,¾~ÅÒyiœägúØCq*ìÍù¼ždãiïøõùj´vÈéä‘ dÜü¢[6é“…MÉñæ_ œr}Æè1ºµ ´DtÂ{­[èR£Õý°]Tß9äI/ ^XÚÐOqõtLLób‹þî3‚º¹cÙöe,¸¼Ýý‡Œm¦Ç.’‹ï h‘4Šœñ#Ååœ5¹Ö¨14NühqJlÇuC ŽRnlç…ü•µ"ÐJçz\©¢^Ó]k}î~Õ¢“·ü“U„FÉýY’ È8‚šóÕØŽÝ9t@èxRbx˜ûS=l#æ!?§%/u™óÌ01ä‰0{3 ¢`Þ=Oˆ\F÷¸¥³uR.çéäOŒ]ðvçgÔW³›ÃÎ?ÑŒñ<ë*6õÔ@æ5Ò[Ó‹ …÷DÈí¼Ô[˜œáãÛ9ø`Œ\¿à|[m.LT͹‡óŸJâ‡qÚùӿŠÚÏŸd®†/žJ!¦Û7¡.ÿƒè³â¼ ìÚbãk“2ÜÚc^|V Âèò€ªû½6S0ÏŠ+ý…–0„Ň!QOœ½º>èú‚:Y•Ã&ÞÓYŒ26~H~Ö^˜»ø#Çnd>©E¾ñìQ¿¬Ù"1~ è3¬(—2ˆ3òŠLhu¼o¸?.Š€†Ö½+tòawä1Z{Þûpz†áèOã'X<äÒ¹AÞ¡é;ÏqŸÐ×Àã^,ûÄx^–æu÷Ö BÔºV¬Aq÷§²®®©`Šm.˜®ˆVöî3:bp¿ÑÇ/¡¯n¸æ@†Yçù€ö믿þvš •öa ‚4ø˜$A•°¬€t±g$dP’¼Ÿ¤°C#…ØË" ƒX^0)x8á*Sôð|. 9ѧ=>pã΋…ÔL9Ú¨¿»VY8»ábÿPÙð]^}(Ÿ2þŸ  IRP{/®þ>]µ™óÙ¢ÎMª¿œLMôi˃HÛS…À·¡à/€b o„ %³S%H7Æxb£û¯ÊÀõXìlW/zÈ%ø6˜Î#bÖ ¹—•`Õ,›ÚØðkèÔ¯gN +õà¦ÌªQžqŠÏ¹UÙ5Q¶ž±mÄœ#ã…¬ÝÑ—¥¾À©ÑjÊÀ|c26°B¥WãŒ0F˜ë§>FnÐ[wÞØ5†ÙqAøzxú½ÿ:ü'óêž6®S•{ª›-ƒoeŽ¥ IëÞõ°±—ó!yr ÷7õñ×MHþÖyúÂðÕ{ ›yÆ©)_è±h^ô>säkÈñÔ¬–ÏUˆòý6¸`ëõ~z¥¯põÞ`À_LñÑ%üþ0 yý“Ó‹‹;7fùØÿˆp¾q’3º6|G·5/vºF“:ñkT€þ˜ÚHL`DÛ}ñFøÆÁ ×1Ç­ã°¹ø§@ÍùtšCÒØ{?hÕ÷Ô|sÖµ£“ƒüPD¿côÇÛ5ñO°•1Æ?6œÞXZÕáàáaÆõ 8ßsÆT0‡D@÷:ðÍÝBÜã¯:³ˆ¼_@Às\KDw|_ßy.òlª‘f±· ¨d­SŸ§¤L†ôùqÆ2Ïñ=C}¾úâ  û#Hð×°»[µæ#?@®ðd6l}&à398EÄÚÅöYÚ¹7ÂÈñ×û#£®ÁÕ4ÏN~]¯˜Ø¦Y,á]ŽÝ7(óƒ5Ã7RÀ~×Ý×'ÜøçÐpý\^ƒh™ÕâÜ'ÿÄþÛbás½s‰=Ïï›@­ÝããÿÚ¾ñÀy•O¤É½žÏ?רC‘n™\…#¯bꂾ¬x,MWøí“ÇÃXu.ˆkŽÅÆؘd¾¹ þܯÏÂ{Ù¥•¾²ú„-¾S½"ye˜b×ýâÖ’C£ëØ8Q²·?kqælÚïZ®-ÌícúõHÙß\OÎ<¦Ä!5¡öÒ¨øèƒ[óùÈ:¯€Dû'õ{K êè3DÒÆ{Nc®<ýÌEg4(ÈhÎ#PßFÀŠ:Æfˆ‹á¬qÀb‘â:í`œG G@]ÇQ;Ut#~4và;ˆîÈï]ª©Ñý{F!èbáÜÀàäë‰Ø.Îre«#ëë³üïBÍĶc°sKX2U%Æþd¨?=̵êĶ#Œˆ5?³ Bq‰Ï¡«œ4ŠŽk‚ñ…ÆÛIÿ!6î<4y^àçñuôIþÑ¥ªø„㸠}¶øa ÒïËÖi{­mW’7dâýã‡(ƒ5³/øóõÇ_V ¬¾HJ®ËHôXÆÄB~¨ÑÑöò¿1Ò® rŠM'0¨‚æâLïx¤™ºµš%cë¡!wN-QM¢ ®œ#4ÿ“_x(o]¹×ÅCö…¸æœÑI{P=MH|3ÏzXÌÓþðýžåh/ø›îÔEä©;x *JNõž‘…¼¹Æ ¿[ ÷k‡T»œû“$K¬Î€Bî7»ôäâºPÅÌ·Gäϯ‰RoýC‰WâèÜ%{%Çr!:¯Mlz8ÆiË%pÄRúÕäœ5à™›û¯IìëóâºGÿ~ˆÆ9½úò#iy©WÆÁ­þgY>³±ˆú–f_ŠÕÕsù·¾?ï³³ƒ}¡­±’ÄóaEÆDLk}è5{òV·DZë¡QJùd×*Ë ˜véÌd3 \Õ)¸_A¤Í^ºÖjúä!f8„‡Ÿ‚‹µØš¶ÜÂ8Fά´ŒýF>c!ñ!É1Gè8'Éj W[õÚ(¨1ç†'iû¡@—£?”ù£@”—8éÞ5ÝWï%\C|ýUšsnÛç‡ ©ùW{1×LjŽ0fÅržÕSo>ê5Õbx‰6XinÝ !0„p€k'o‚[É/Ÿks‹÷ èôëŸAðÎÕ#£q¼º»ŸZD¨ |7ã{n½¼e&xç*}×–ñØk8%„4yqMô,‚ËÇ­âKv¯EºA]àÊ¢êÔC:| röei¾¹36Ž¥Y3‚¦²Ûšéì˜Î³ã_×àEW£h\ÓGؾ™Es ÖO¿gÿ^Õ¥bäæ .®BéwwK‡%fCˆ(˜ËJù¡He*4Îý½ÍÃóƒ–¾çà»¶w¿¸Ø³9~ýõ÷ÿ³$ù±`R·$BÄÀæT€di<ʰ#Ù4Æ_}í‘þ“/’ë„5€³À(ö’å4¥\¨òÕ?ÂÂÇù!ÖoË(ßÚP·)¯®¢M Þ! }LùïWp)‹È?"®.à^G½ñ³PÂÝ~¸ÈßÄp vŸúþüW¯½Ïô¨Wë!›+ñqø—È"îϽá6KÆ"n~¼B”Ný:?ä E¹IbA?¹Ö?løBd‹ô3R—Z¹À2 Ž|uÝž\ö¹}u¿¿÷Ç´ˆÛ.ËcçèÉû‚âš·¬,õ“=wcƒ,öGUbË×ýt«ó…ÍÝ™äðö‹£–äïæ£cû¾Ú"üžo®ÅU†}u]×VHfŸ™ËJ1ÛyJ'-ã89«RgD<˜ª ¬E)^¢häýØ%–Æ|s6†G~qq­=ðž`­ñr‘7ñÏD,±àĘª¸°ñØ%˜ëõ«·ÏËeü{oµýïß|XÀ3ñs1šù¼Üê•Ýý»¯`¶Ð´ç”˜åÄܶXsaox^g‰¥E JëîžðØF›Zé&°'^ç¸&µOìÆ¨”·¾¼K¬#ø[o\u߸s.©!-—JœŸšÆÜºS¿« îÇ!qq ªþG—Ë”û‹¯pC{ÖÔ§ëo÷ùbª=^‚ln¾Ïד¤ŠÃ>\ºcÔƒlôKïÙ›Ìì˜3?MN“—SãeA©:§úAM›[ι ‹¦ŠÔ@Â`×$ŠÎ_ûè½}¸\ãÍ€Ø9·ÁCìüÅ]î-tĶÆþÎÚ ;»|qçãÕ±|ôÌ\ÏHÂëý䲸£»/aWÛ®ãÖ¼ëk4?ÖþœŸèú, D G-æépï6f„Ì-WâFs¨ål;rÏö%.Êþþ‹Ê +sÉXˆæ$ÿžÿÌ»5®~û—UÉoLÇ=‹ýu ò4’rÒížA¶<#™"oìîÍAðU²êˆÓA†Ø×ø"YÁX“H¨€5Ÿ—<ïI£ãBÎ`YÇÆ¦¬ñiç:?ÿ#ô‚ÏXâvãÎ-s½<û`Ö¢"ZïM:E}ZãÌÍÿŠ@Îܯš9 ar-á+Rþâ5yÅÇkßšYkãD >pða[›\¶–„ä´ªGÁŸzqnÝbc øcŽñxñÌÖçMí9ÿâ_g‚1 Of^X qÏ¢‡¼þ´©´ú42c)^ZƒåÝ· ±\÷@ëšý|`ÙÇs‹Œrö 3Зˉ Q¢r€á_/Ú#(ñ[»NA”Ê"§Kü› â:‘hÚÙeaêéÙh¦CH`Èá"Èû›Ú=¿Ó×$FϦ œè±M<ò#¤…$€šÀ‹¼5oŇIž vú•sÊ-¸´õWƒ”.]6B«ÉÚÐ?ú´¸«o⃻ip<Òu"-NÀq=<,d8‡ÃU8_Å"gùâÿ6kQÖ¥<ü@ßÞ•¦¤òÕ!ÜmõšƒQŽ|˯ÈÁ ¦wñ¢jAb G®nöŒ9ž9Ôb[—6ƒÔ¯“4]ó‚¶îáI4À\NDdÝáú%둇òþÊ px‘àž’Q6ê!Ï37Ìe8pESÙný Ma]LQ®â*ÝŠ=`ìÇI»1²†®MùÁá™ë¼ì¹>À”r ÏEmNÍIÖ õ ×nî†sAЩG7úØ|Ã;|F OƬwC.¼uÎ-ZâiGúì[ðœ£ô/ð=8଱§Ï I® #‚5æžnuªµIoØæ茗3ãóu?ÔÀüCÉ) 3º·vX!¨ÿ\kã›A0]³?ÿ¹sõ'kÆÖŸ„ÿ²5i=ÐÙM|Ö¨b9ë1œ·†1E†§Ìs Ûƒ Œ¹œì}Ì4ØÊÀ¦i{Ý›Æø©çÎåõÕø'þ0pÀ‡ª«{¹%¨­.hmÎ/÷ª10/å©öP5¡hY±À‚³C¼­C}RÕ‘ä»z´Œoývè³N-‹ÉyLåÁ4j+_Ð÷U$¶Ê¼ùT^vúi»Jƒë¥ 8ºþL÷8ØXçVÁíw°½­ÑáêòÒln1Ýß8@ppÝÜ¡BT¹f€_ïS+(Zš–;…T‘¸ùKèðé¡éb±ñ¥Öزç}xdÌe2/L!Ò'9ïüÎSxà´ØDY#5.Öw}#ŸeŒxOìªe c¤À~zêäWw¶Å¡¯ ò5Ìc`-´) Úæ\pß\ŒÄNí^¾²ƒ.öô¬ˆXÆÎ)yÇg³šoÌñNK’‘ÿ‚¢uùĤ<§p±O½s2?úŒ>ìÚ3N'"ãÉžŒöâ„ë4Y>6Ùjì‹#/xùâÓ÷o  1H¥ÕwmÃuSUíÃë-ä=À´Í©iÄ—R ÉûADz-u“ô(¢wÂè>Àôaè¡ #L!ד!ÏQ׎ÔkÔA£ŒžE,¨Áü¯ò€h Þ …?ù7úÄáÆíC–ú#ËÁ¯ç„¿‘äì†úJtNÎòr*’« 2"kû¼T”èi\•²hÍ£òI3 63Zÿ•Gƒ½¸J±rÃdXÑôÝ4ð‰oU9ñ®F*]ôü‘å= eM¡„aÃ]ü‰‡4ØîQs”:[s9"£É Z ÏΙó)@hc~ðµ`ÈKµ¼ôÅqÚ ·ú<ÿá] K)ÚØ—–È5ޱ}g ñõ±—@¡­9f æzº)/²þU9Ê:0qk@pt€w˜<#ë·2p0•­(à æ<†²Ôÿc1ü^£³0•G¯g°»£œüS·ÈÏF‘úPÈš:]}hÔŸ=¬¾ÔÌ~,w›Ë ຘbë¹óòðá'ˆ*:ïÑzæ??šìJj¦=ëg~˜3–î8ˆ¡{uíå|ó™AÌ_‹`Zá‘3jéð4ª]g²õ¸ÖG‘X¬9bÒæ {·÷²Aaƒ-ñøZ?—ÌSºÚwüî<˜0ÄÌ¿÷%l¥­Ác݈Øú(IÝDFì矘Ÿæ`<ÆE ßËq´\ùAUs8¢d¸ ñ™„xˆzPàÕçÄøêê¾B0Óê§{¥?Ö#¨'ˆÔP{™añ «Ç³  ãEP»œáã½â âTÑ$ˆÛÓ¡ûÞ÷T‚xE}“G·Â5û! ƒÃÓêæ"Šhï:hÍï°šÖ¾5Ë>Ò,LZçuM†ú'¶Y\ ˆ…óÓ ¨mýÉ9cŒ2ïr~lŠÏkÙ2€؃¼h4j-uhœ EDbtø•ãMÂÉÍú¨‘œƒED4 æØ»#¸ûPƒ†-Ã{ TæºçÞ oye Žq9êmƒ£ø©YûÚTrçp…´£˜§sÉœ$–oÆ —ÿ³V < ¹‚‘ãáÝŠ1&i ’S¾ÃGBkÎaÀ>óå?¹¬ù±rÛp3ŽÇŸf˜ÚàóOÿþû¯Ô6#ULZ^Õd†ßeÊ@¹Ïm[·TÇ&ƒaÈÑD°LŸ$éD`UþÖ NŽøÁ•B$ ÓÊ)~ÂgTUÓœð›ËõÁ¢ÂÖ¯é ó­3W|ÝOHu%+ŠlÊòBÇ !¾¹®¡l °¦‰@]-9;TÙøÈµ9†‹Zùqíë `î(×ÇCÒ—0¢«Iì#{>Í»hBa+ú¾xß“WoDXôô¯7ø:]ü§K÷¡(ÝŸ-úXì \¸­a.ûK.è%ÁJbÄ…ý\‚çËøpf‹ópú .ŸŸ« %ÈÌ%~›#]ð`±Úš‘œªèd' »v"Èã_?yvc2?H¨ck2þúñùŽ‹{yðBêŸÊ`¨‹l#‹S '€Ë¿øOŒ±BEHÆ ƒ²—|çúõ‚~ñC='ëž üÌ)9†g|3Ïĸ—k©‰DÑu~\¯0%g/>Àʹ­^*('~i®Š`‰k2/Ø;ræóxr½?"¢ M*W jÜqFý®2òÜÐn°¨»'E3mØ*àXž¸7—ñËg®©ø1ÙÅ”^²kô™·´pí=ÁË5µéÈb~ ãÆÌùCã\¾óA-çGÕaÊõ#Dûa©×_:ôY'šªˆ¬<–è(ï^,‚ÅОdÁ»JÌ+©4ˆºÖÁ4ìzïó¼¹X«³O­Yle– +L7WÄÍßGë‡>“¢7·Dãßthµm¿çBs=ôÍ%ßÆÖ—à§æL’æ O1Ïd¸¹DuAÐ?ÜÍfüÚ÷ÝÜ£¿á€áòÔjü.§èyecìÿã2Æ`Qðf -\(é=u`ýЊ¿:ûÞÉwxt]±}×e™Ñ›ßbÌ„ëó5GA$Ä,¸ó–.¡4 uÒ,õóÕT#bE–1ä‹ob÷R|_Æ'dÕwøW¨`è^'ˆ æúà¹eôøÑ¡' ê@Ÿu›Ëê­.rUÆ„.Ü8'\ e DÞèë Pl­ü´àøbÞÍ>ŽŸqp(ÏVºœ¾¿iç¾ êøµÎpn­Õd^ºXñ@¦óÁyÿ™/sôÞqè{^¬ƒ1öhë«sH†±Ì;zqµT‘¨âºÖ½®‰ôïGFA½Î=œ<ÛÎáà’Vþ‰Õ{Œ<8àl×ú/7c’wý¦Ÿ«pñÓZýùÏß}ÖÁ„¢’‡ #"n&§Å+IKÓI´6ÌÅè‡ßú1×à ¸ nÊ$A·"-9 áÖ»…¥â*äÆ>L'Üù®Rã5úžôŨ(º™Èdƒˆ9„Ó¼RõÍûâB¨¿èú2 c0pÐ"oêãÚ¦àæ:Ìiê87Ÿ‚ñ.¨’=*É·!ÎÌqófxþÅ!OÄQtS@¸ "|o2Œê„óK'íì^-ö!´8‘Z<‘ú&ÔÑãŠÁÓ£µã >_]§¬Åæ"÷—°®á£ÝƒRΚ#4yš³žïDqÂç:“¼,u+¨öà|C; 8¬²?ëýµ»0(ν`ž`©Ozé/§ÒƒO“:‡pÒ÷윪ЀÓl‚Q”a-*ïYM°w…®5Á]È«GzÛÀðJ©:¯ÑKÈÉŽ¦·V oTé/üjšÜF;‘e|¦ôÖEYPŽw!á‰%Añ@7>ãÙ“TMµ_•Iƒ4F„‡ÙAáé(’ :»Í™üá)fv‹+‰¼ÂFlÝ[í›”® aÈ’/h£¦£Oñÿ-z|èÂ>uL§Pα®™×VÅPôyªrb ÏùbȟЕSƒÇ÷å|µ?¿A^» ¤ãtŠ9uŽörÔDŒÛÅ"vq„À´¹#ƒ/šÔÔ~†Wï»h¯u/YíνáÜ[ú>¢øç›Ó^Ä‚”3`ëh‚W&É뾀͢ùYü(îeâ?yœ-…dng*3Y×OcAÈPŽ½è—¯qM½ú’ܵ6š*!Y;å0—?Ÿá½//ÀY³ÿêË$O|r}ò¢ïFRëw×Ú³úØÅ÷û+x¼à©IìRJFé+‹M¢ïÇ,vÈT!¤#‚žØãétFʼ1WðÕ¶â%¼9bܹ•U82¬Îöí!Æõx–2|>û sã*ÊãÆ¦É„Å×=[,ö9/‚Ê·/îšS7¹¨0>Už¬vab«y÷Ɖ¢,•4L4]sœŸ$è#äÄÁ3~þÓ³Ôhœ_BCœbJÇÚD<ÿÌ%M¤ë¸cϩں<üMÆ|—ºÝ_Ï|óŒ²ï?Rí‡ÁþŸúkÓU£»³!¯æŠÞ_ œ°w=¦C,@9^mïÆ Å1Z®Â'ú&É@$éâÂ%w’N9}šÜŒÇw¡uñÔþ€}œ!èñØ"¹*Z°w±é.p“΀±ÜÁÁâX$J¸A> J…$OcŸcrJÄUÙ76ˆËtóî¸xûû©EÃîbÔ,–Ïž >qp:_Ÿž  ¸8>6±o­Î2œÚAŽÐÑ/g—5M½äF/”v4¢*8ƒ•“:Ó—³q¾@pƒ¬ÃÚ0þü¥VÌú"',TÌG­¨:ýénŠ+%®÷…EñðÔgc “>ä®ñ‚™]=¶6mùa7æ`[ËXYïØ†Ây$×îK¹³sŸ+}Ý:i•%?Ɉ-ðo#[ô½ÏŠ«0|´3Ì(A#{ëÙ"ê9ñ³úò\KlÉŸË’SKþî­yˆÎ{àLñs®Å‚Go(( üYóì[5Ë™ÚäKS„`ÇI,ïZ¥}š?‰µóîÛ2<¼Â<¹Lµ“ÜÞ‡j}×ÎãoFddþÚBˆˆú²€_ýŸXSÛüâŸxU—\“ ×Ìd­Á¸Í}<ËX} g±gžrÈ8Ö€ÁÍ·Ü¥.gôÌ´=Ï(ý“HŸuôášV®Ç¨šp 1îÿ9@,Ý?síž.UpÌ5}öœðû,;øütÞyÜzw"'~ ;r‰ˆ*Ûa`>ÍYaÀAs`eL™aã­œüä¬Ä·•½¾©u¿ZÕpòzßÈk¨9Eš?½ê/Ò?û,6‰É_£¡ÆGa5†Øè¶ÜÇŠµPìuК|cCký+8h÷E4|ñý¶ãQÝj­iÙÁv-×ôî½ËÝqƒ-k>NâŸÿ˜É†O0RŽWZ°œ‘SçúQÓ¤ÓE×Ö}5ñ":0×`Šj.ž#x,媺îÉ×%å.˜HV-ÔÑ»G…ƒ5KÄú…«þ=+dŽQ>Þ7o ºç>{dðÆ&±v?L¿ êáò^‡&8ËœÞÏ÷™ã"]"`޼ÚÐïâ¬ݧ‘{ g€üô7%åîà`^˜ £{¶sËü¶vU®ŽZ†ƒ®ý±øwuǽÇn}Ÿ4ÜÓ]GŒÒÿû¯¿ÌÆê$” ¸ 9Q1+h74^Ò 4rð¬›ôï?ðP§ Ü`jjBÚ‘(7×Z8˜`ì f3t*b®…é"(§â;•zT¦/!МFüˆG§æÒ'À|ÓGùü±;þúÓ¯>ìЧ‰ãd'&8¹xÕ)ÑX&qµ+*84ß`Ì™+qQƒÖèñ£ÑñSK0qFlЙ¶]žð¶råìÿ\Éùæζ–%xEèënù‚§G†KôU’u<._øŸÜËýV§KlÏ }Zó"¾Îƒrsrû0…Óº1ìEŒ-íÆTcµÇóQ6¦~ s|¹.#"þôM†ùb ¬Ù@vt2®ÿjj¨Â ‚b{òØij`qotÑ£2ŽüØ=ýß@œkDô¹æŸë<¶Þíë¤ yöeÀ|ç}}fصŸp¥« s±Põ§.þl6±±IÐ|Ñ sþ Þ\87.h9“#÷ }¾R·>Èɉ>ÄÈ›O_&æô©iÕá9ì­ÇÖ¦«¯ëÈwO‡§ïÙ0> ñoDÚ8A¸_ J·Éô‚Z€ç×~Cý’¡Yö‚‘DFì:æO(†(69>“$þ†pÝ!Lm"b«<ìd 7phüê“ ÷WØ` vù¨$†®q¨ ‡—ø±¶úƒBÊ|çpµöµ™­rXÁ±.ƒçz¾t\D¨‚AjYæs ÔN{p¢bó®‘“ dÔC˜§â ㉅5‡Ç̯¹ψ0­U¢6\™ÒgÀÓöììwW[÷ÎÕõ€uj¬ˆJâ«©úÕèG~Ì;Üá‹ÛÖ§1—šà8h—ËÆäo¨]Ý®³Kïѱ'Q­ÃÂ=†éç[†dEGÞp8&¨A Pváº\:™±¥èý|µ¬ylŽèºÂ£µNÄ)yÆhÔ?eP®*'e—O ÆKžÈÖ䉭æp!ïóÙºøG 9¶¯}þe®N¢1±gT¾_Í»Ž€"fÝaÙ{P`„³·v³Ãÿjyëûbû]§ÌKãJvøiçùG™ï›:‹ŸüKŽ«_‰ËÇ.ï¾ 9|ìññ™¾at²FX‚s?`Ì^ˆ¾ç~ÈŸ\|à¨mO'£*y¶¼ï°Ìü½gÏæZv†®6—c÷¯0zoÛ4ÈÓêµdA­«j<Ñ@΄ühA!ñ_É9È/ªK8âš·¸ËË$0176ž‘r´/¹£[#Ñ·­>7€ñ ¬åØ_³9¹¢€ÖûFÔ&îs£ˆ=ß¡¥ûzó×(ÂùãŸôÜÆ[dôU}x.rÆŸ0ä ]¤÷ÂôÉÝÎ| °…àÉ»ñë2²Þ¼ŒÞ ~茡¡Ðå&hm¦0žÄåGïÆÕ 8f³ Ûâó=~ëÿ™â]RD܇pùc¬ËÝ$´ý .¬¹ ›‹µãwô.VB4LnŠÅë_y!ç»Æ$>r8ž‰ÀœÍè+&æÞßJ&ËΛããÖ9y7»ÿ“VÝU¼°ž5禳ÊnÓ2XB–7œ·>tð,‡æVœž>µ÷AE¯7¸Ð­Ì¸ÀÒ¹C…8-°û¶óŒ¾ÄЭµƒ½7 Wv—Xô7—©èâ:ë ZéræÂfý©‹1sa:!x6R=¼Ùå‡N%œØ¾\oÿêЈ¶Õy%œ/ÙãèG‹‚^ݧ(3µ*íŸëpY!Íè_K/‰¢XÆä„þ‹ªð掼~6«_ÌnA{ÈñC.½7ë£&ø‚!à<ähÙkŽ,$d †aåë‰7…‡§ë$,çDAýC®2úR’Q#ˆÒÏæÄpæç·ia€–¶¼o ôœ+«Å#ërqzEáwãañd¨ S;JP?ò{cÛ´p`ƒ¾upW^{U€œ+¡V4Q˜“Iƒv=Ç­´X"Ê®†Ì‡F«'ö‘“ ÚbWLµß>Ar;2y¢y[-N–Qêà‹Ù¿¨Z‘ØM®…5k<Ä„ªuüò¸_±9‘/­%ÑÚ|ÈQ²»~캖©ÓìάL/òÜ"cûé¿ùh@ðSƒÎ¹¡ÆæîµôÆÉ¥AôCï3»sŒ”Õ3pîâ·ËªSÏÔÞ{ŽÎ‡æ³Õ]ù´v¯Œ\Çfdv¹Œ ISî³¢ý*Û7òXeWž_lŽçáÒ´GLäý|HÒv™ó°k¶ª©Iddþ ] VF‰MÁ± _^0|–`ÁZ7´³«¿sùnl¯‡Å´ýî ¡³y¨*F«³J0èbÁï© ÇéýÅŸ<- t1¸Oi,p:Ù"¹E’.ÉûˆüSTGZ·@×NÒŒ èãzo¼Sû"¨"~†£À‚#Ç õS 8þO“ ¸>\úI ß½I$ÛËwù"Q<Óc‚?¤ÐÃGHl¢r×'ÂóCI'B9 ló £tkÆâ¨È¤äIÝ‘ÖÉiÕÝ óÝZv~RA`_î F3—N#¤œ¯[ÈÆWʰ»Ú§fqlÃU7#ú­Á7ëÆ©EEVcˆœH­9Å£‡Œ®±fÍe^º©‡¦õäªóXaÇŸÀ¤ak¸õS. UÐ_0|J·¯Ą‡k¢ñEMsBs¶)W’¾\sŒŒ|evS­ÓÁ‰~aòYîSD×OôÜJûÃÌ´;­ ãyêzú"#ahlgúèŸ\¿ûÂûDHt¬ÇáhÒgͨ²LZKpmT“g–ƒÑåTéÆ RƒÖ8óÀó'- hÆ”+$ÈòMWí ò»‡)ϺjpE§Ü{=WFcâ¯;$¬Ct¬ îô¼Ý»^Ç‡Žµ0­^Åé`÷`ú½on­é(|± öÁo/¨7<¦©$¸té¿­+;ùpfáðŸ rïT~¸¯ $PÅ—ÝþeDdîÑ}ãÒ{õSsÐ;¨(ò%7ßÍ—GPm½Gü‰ZŠ~¨ÓrýîU®Kçýò¹ß•-{íâ{jrøM½:‰ª©.sáþ_M‡¸Ñ1bN!éüK|÷Ɇ%Ó·‘3íbЇÅPÔÉ‹ê rŽ·-žc-.×øt]Ý©*ÙñÕý÷üÄ“ÉPÍ51çP… ù—ï—Úú4¦Æ·ÂhãÚ›}k ¦8âò'¬„æ=ú_ç‡øµÄƾÚs#º®FÆë‹î÷á6^– õa«_=g=ê×_x 7¥AÑL¼´b°¼=²$ßý]íØáçÌy/pÏ$^î©ãÏ50Fþ‰{üö¹ùY_øä~Ã~ °ePjN·®"£Vƒë»ŒµÌ©qÇ—}HÐÐ0z 5Pc=+×çâ÷•Øšƒâ ¦° ¥&TUòáªÂ£OCöƯ‚œÅ'N7úŽÏºqPÏÁð@ýrÅomo*…·Y\.åìgÍ’Å^Šá£Ÿ¯>ª…ã7âdžƒ:€úòGcmªo$Ïx¹gÐcÛð“‡TЭÝt1%rÜÉ 61§ÿý-è¬@ˆ¼‡½·F9ÁòŸ†‰ºs8þúëoc¡àÎÅHÏÀHQ”H‹¦¬ü9Ç&x*¸hsÚ2äæ³è`úg•],ý̦=ÖrÊý¸› ±ê¤`Òø ¦Úsé6:³ï2ÀfCÌÌ€B?¤ær‹ >üW ôÆKåëMûØ:Ý ¬±½ö¼tû¯Ü¬”0Ò1ñ'†ÜOLÄ'cs)º^Ûçœ1ްå%S§àÃ7Ðñ;lPoœxˆŒz‘ëÄ’Œ.‡cÂ'.´h•à8Fb‚'¢ÈhÁ”Ѫ5ï@ÚÄÔTõZ¼h,ÍËßaëÏ4 óÿV“Ú\LŹl‰¼~ †ï®S¨NJÄ“/éÑ©ߨúëpÑ‹ÐÓ“ Ãú°gíÇ"itñ=1¼a‘ÆÙˆ”´Çùâcθ—iÚd‘»«>ý¹Ÿ ¾˜_Èr: rÙ«…ôœâ›=cÆ‹Àˆ›’o|òP‘6'޹"K\}ˆê!'äñ‘K:pZ› ‘hï¿(uñïÅñMD`ï÷Z;‘ò:ƒËJMqÍW„ý=ÓŒ§ÅϹ >0P#¹´¯†5Öâçá,ùhA6©PNl±¥B†ó\°§u Fo§†ð3šHpö‘1¾õ[Ô´Í™†ö+‘tàËÎ †@÷ÁbÉÖcÏ4îœ5Gþ¯¶˜}f,®—ÿðøJ I ŸÌà/·6?–5¢&'üÞ¬S8±^:Žê¹Pož*"Éñ©]»Èž(è#¦¦´œéîêB,Udã·àâ,ö´gÓvAvŠè™dâaœcÜôè#æt)ˆpÍsòŠ,ç‡-øÿÙÊG­KjZÇÓõD­Ъt~6'—×ãóp\ñÏ9±«ß0쟣éÙ+iÕ9DÓ¥T™û©M­Xj²µòÒ•ÇÐŽsJ\3ûeíþ4eƒíе¹¹7šðÕ¼Øàº>[ÓÚ _€·nç'ý2|'5Âb5Õ#OjÈY# º¤(šx4ËÅõ]Oš¬Nð ~üaSÛï’Stm/<Ѥ¶`ËCL‡òÀEžÇÛîƒAM[Ìý!M-3J>˜ÀÛõÕ´ÖGm0ðÃý8 NùOWg¯>F­eyÌà.Áæå˧r§‹mœˆÏkÈ9.œ{UÈòÍh…ЧZ(òíiÂüXB kÞ Â‚êÊ…ŸŠ;rˆî>ÐȤQ ¾'8}7ò 5sáà­ Ö™ø#ÿp‰tùë ‚i¶—38D£iÐrœÝá#‰¸_ôeáÜaÝ HºÚKC˜Ib¬œ¿<)AÝÆã d¤gݰ±Ö×ê4ý(£[6òC%±sÓµžõ×s´æðŒÂÒ~¯D_Xº6÷‚sJv1‘úá޶þq9À“|»á †ï‹b<·Yœ^êQÖüEý²ã ^V7Ü™1AØ5ŽÓ‰‹M^ùãÈ1wHõ`NSäÒ‡ÖE0?óÙºépö¬ØÐ<ø9OxI¿î ±YaiÎßù׌‡º€BŠüœ‘P–h‡SŽ®åÑ¦Ž° ‡v@r¹Ëù¼üÓx7dY]RN?¤(©¸pï:Ž^výDE}¦*–Ê@åìŽê„»ìÓ¥–®7grÎMW¡ƒ—#g'¿üœ B®¨9„hÜzÕBÐý·¯_h],zV­ÊÞ¯}mjŠ.ÖŸóy}y&(¾c¢ÐF‚úïËSúªºÓã%õ¯Oý­OâOçKÌ‹¦]K~òI<áåƒdé#ÁWäÒ9ë—õXls‰í-¼¹«‡9šd­[®p¸ ÖZÀWöˆóOjÖ€ÒxX½7EíÂTß]?]3ÈórE*TÌIWØÍyTW7b‚;ö¬õÖ¡¦Íø#‡‡{ö!×°±É…ŸãéµÊÝWÆoíJcU5ªýÁuü€˜¯ñ-¨¢1[’,’Ô¢Œã=s±œjU&†ûP’ÍZU_ãÖ PbÐüî_ìãç-ˆf¾L# ¬Þ:?µ2æ‰B².ø×]|!H>lu“þjÚXÅù‹Þ5C\pŇx‘ÄwóÑ;>"óßG¹È@ô…¸=ÄîOÖ\Û»4ìýa.~qùp¾þ‹Ðdd?ó“üÓh dì8ÅyâøÖ[¹ç—ùw<“ ÜŸcÓ—Ÿè±¹vÝÙÔ7øpù¨€U0÷Mp}Ÿ/åÀ>Zü§ws†Ôû^]Ÿoèýç)c¨ý OÚ¶ßQŸ¯ÃF[¸o£øG,Á¥ës ¹Rb%O£p6Ô_ÐN7¨e…g—QæÞçÝ"Fï4^‡«~ŽGÁsº2Üóµõè=y”zŽŸç—\o¯{Xè€ÊÁºù‘À7îBÈ›}°0òfnˆïbĆ>|ë¹ô¶þ|?¢ßšÕ2}¿Zÿ(måN÷‰+~S{£Â§Ï|lÂws¦¶±¼û±à#^-Z½Âä‡;\ðÓ¬¶H<ôM¼ÑGÔ5I—€IãVÙÚ7ty:IW\×S,á Ó«CŒ+Ï×kµeÔ{ïÆõ™(¢aVD¸~~úÛô™'l©Cðéƒáhÿ¯<Áµrì;éë¨öÔÆ{ÿ3>jF[:W§ ‘<Ñ´hÕ×*ç í¿fŽï×ë¡hÙž™Á òÀ©cÑ# ©yÖL”Ô6ájÃ”Ç -” ƒ¬òµ˜.nr€ðЫ˜ŒùÕçwOñÛŠÓé12GôÕܧñâ¹y´zX4ÍŽ:ÁåV›¸V¸.A‡ëêÃï7Wl88Ö˜â¶ÌŽž«Â¿)À‰:_áÅ‘«Ôž°ËØÄ‰•Q!‡B[nÍæskø¡ÀÊX×/ÔÇ}që„Ñ1¸äÑñé¯U1\,̆¬Y»õûy ¬a Hj=y ŠPNlÓÀb„X›Hw-xöË«¡•ßûf./mcøú3’Ç…õµ ÙhhÇçF´zµJO ¹}ºnxøli—Ðmßæq œHÒ°£7úp…¬_V+úÖGÏÑk›ÿê¾-#ƒmÜj#0~}˜ã Á@aŠèžŸpÙ'îiòsÕ3Ѭßz·”‘U +q‡=ŠÍšzçñläNnÖ£ÖØP ØZ'IsBFMxº ˜X¢_IŒú/ȵÚRzÜÞW7Vb*v»‡ƒ0Xc2 s”îªcÙ ­!Œ@ç²V;çòû”w˜sªs@XË¥Ln< ‰Ç—®×Òs^zî¾÷y—OÍë‰RWå®=ÿ †¹ØX¤-'¨"¾#bcäOŸ™WUEv¾šT_®âaϬ§ç/†W7²Ã ²Ý-+òBWúÅX~bç[!Dî;ÇbfON5ï‚éî¤+ŒÓYÍ:²YróKe¢Ðpw?"Ǭè=Nÿ‡Ì=nk5ü%µL»’–Yå®§øvž‡}­W¿Á'GNê ÒiÄoôEGƒL%§¶¹%ÁëÊáàìru}b^T+üå±t7¾8|Èâ2i¿¶éï&?S¼®àÑ}òÓãCr%Þ4´ÚYW¥X¡mv-UðvƆ¹Øp–*‚KOeÄùÒ¬>_@²#ÎÕ«yO„iÈÓ¹u¯ íúlì_ÍJôŽŒ&§þ®F}´t<½û /3Ö(¾-”ÆœkbjM¢¸vü(ŽBŒ÷æI-ÀׯûRÉå88/ 9ž›=Ö< !ñ'6š÷ãcÙ±¾ÿúýÿBP‚ ¡Å­ºû2ß@dMß„åøWÃnþ£)Ÿ›^°n,˜ôl‚È– éf*sîfWdc޳£<ã >ùòÅ9Pmèâv ê'gY\áéoNdœ>¡²àØhü!ŠFù"kË•îåÅÍ,¿QĤP«R[ ;Æ.Zü½ƒaÁíï8Ç.ÿf|N9 "Öð¾#®&¢'N^"’×¥?±Í%ý¦Ýè‰Î(á×®¹´¦õWúÞe̙ذ"OüYL÷²ãï>ï“®!€xsvî«}~²çC8#@IDAT‘á“_^­#Ü…… ›tž²×V·¨Ú âÓO<ˆ¬“~ýû䈕ó5KÑ7&¿ÓÐ'Ö®;å‰}âL}ðÃZ¤nzg]¤ÇÜ÷/Lwüå0T9µÉúp§,â4s30¦ýé8Ø|œßÈÀË©Œnùõ`þ‘¥Ú¾&9‡¡!‰t‘™gdƈÑâýFîOV‰Æ‡)جч‹N¹1ÃGÍ'®ìœùýãÊÓ‘‹eø‘„Òrѽ;Â2eÜ<˜gbJÌqx¿Ã9ÓÿE7•VŸ˜àkí{OæM<ñé´q6’`MðdXºdë:5i0‰1w/uý |6‹ùèÅ'FÔ¬÷ØçuA}°|p°‡]?=0Æñÿho³ÐAø¸Fæ± §–S5 ·e­€ÅïâW‚m$‰½6Ä S0ñ‡ç®ˆDp¥9öÅú,&Nâ'0°‹5ŠÙq"ÇîZ{—ó# ]ŸïØÖâ‰ëYë}ÙÓa×pZÓóÒ˜ÁôæD?‡¢ÃFdtã;]茼$"0£s–ˆ±X®­¯rœ°ÞÊC꼤%×bŸ“ÎÛƒŠJ¸.ÿÌ_ꮺÆL<Ú¤zæåØêsþ‰ïs{,, »eæ 4Ò4Ì ‚C£cTI¤‡µÃ 2ÁWЈ,Â1@ ®†'ý½¿£Pþù;%Wçšã¹$Žóÿ\È÷øÄ¢ Ï ›'u“ÄsúÍÈ€D'ïòH3y¡ÔAø&uq˜ýÉÙ¨ÃËðµ5N¡íBÚZiP½y/aun§ÎeíŸn#ÖÙ³ÖÀí¼® N×ëŽÞŽÇ^mr)KGäxòÒúASÓTxÉó¾GüDedŒÕa“øàMØ÷Ì ]k>}¨uþïw„×̈k¼âI%1ómLˆSû‘Ïü™£÷Ì85„\‰rÆ‘érk]Þhžo‡É.bÑ¯á ›/gcÓiPujL`3ÆGªÜ'o§qSÍYë» ÂKî\iåS¶êצڞññôÖ1)ÍJ=8¬‰“–Ÿ.ó"C¬ŽwBÙ úJ룆âµò‘uÝmsMç›Êß| @#»¡fX\¼hïü^nì 7>R夨Az  Œ.ç¬ñK& ¾o==ùDº÷Ýô‚x¸Õ™Ý€ {ôÃ9cÇ1£‚Ÿ¯·½1tÍSŸ®™/ ü{ïD#Ù±P“eÒ"}|ô3eÌ$}‚ià+ÁC*ÆSÔï|ÓN]³Ã½/â…˜CPYä¢x|æ¾ËÅ=+ñƒ‘›Ón©MeWæ{1D»‰hž€¡GžïqTú=S¿Äª‘@ß¾ –øûò v‰(¦‹pþ"0÷[e¹ÞühB®p¬=2î™Ú|U’*0ßM#j­±VõA…š ën®'U•1wüâšL±”D D~Ç*>í“ãÇÙ _×{”Xy‡D¼ñVëy\<§¬»÷)õAÁQ¬?±_yͨ7k/°žè¤U‹ãïküé¦ÍРV?ê4_ðA¯Ã /|þŸRú`5tfgì—l÷XX,xËíþdÛ—Û¶~sŸC§TÏ€¨':dÝ›¨+su±T?ûag‡Þ‘Q>jª4†ºK_QÏÚ9:æ†piE\°ÐŽûqXöÀØÃÕøzd Ãw9ïåïýž+ñ¯üñdÿñÈ“ Áë‡ÌÚ m7-S 6Ò`øTD0㑱öö®0Òd!"Ò,“þ)ä9FÚËŠ~O ¢/Ƣȓhà\eøµ‡ú#Ê1dDü~šûÞ8ÄA êžÀº€ð-ùbKÿbƒ+¸³“nÃ8k¯ÿ'Ï V[&¥5Ážƒø¸¤¹òaJ :äiDOkNoÿjDlܾüäŸ2ÕjW6ªÄ( šÐô;ýèë@žj‘ñ¢€ÙÙÌn¬'ÕÕ¿Nþt vÐÞMyQÉIîÑ[çG9 Mä^L]ÿr@Þ@jTÛ'GðÌ5ô‚„¾ÓˆÚ€Ë!)¸Ê+‚€UÄù]?®«à&1ƒ¸Fýèç1‘ŸîöE ã*ʉ{[Áé^HÓ7bÉð°¨l',ÎiÊZô~øÆG¤”5ŽOò‡¥µÊ½#ˆ¿¹þ¢Mç½/’W¾Ø ø°ÐY€5ˆMþy\𑺦áôñÉ:/÷“û äZ€æÙ:·†Äa”º©Ìعi=à¯~‘ã7íûnŒ 9GšìyôWBbè™üÈe2gý¨*²þ¨H¿@òu+FªžrÆi4¹ø Í+9Óț濃þä2aUÿ:K&ssæ…ñúþ%oWÈš__´5׺-BbÁ”5k¿8lÌ82—³úàž–¬·Ÿ«oñžØ,¦/7à`Õ=³cd{™iýÀ¹òâÏ€*Èyåš112_ÖŒ½å’ÝHY»å¯lªØ¦VÆmxÎãí¿Þ ùKÔMqÉ4~ZbÀ"Y`K׬¸â=(ƒMxj¦íY 嘂KLƒ‡›÷&üÚIŸ½~xîŠÕ5üØ0çô“ÕÙcêԃŠ7‚»^º‡{s$=%ö÷råp75N œ¬-êJ}¥ô©;¿¥@ž•·‚«ñ¿~{Ï”‡²j¡£Pµ¨@¿¸°ed £‹§„xf‹ÍóŠP9§²¼÷*ãÕT¼‹GRl8ˆƒ^t:II©ûz\´³ÉãüÊ;/J²vyhA½?m÷êúÕ§õ„?ð&\ä¦Ù† Ô( }†‰…ÂÆòZc,kädIñ•Ã:?1`\çÖ`yÞz»¬Em.¾2ãÉéö鋽?üÈÆnŽ0dµ~å1àÄæ.àÕà›mônîÔ  ;ÚÖÊrÀGó ²n"Âo¥g#OÄ~@‹/Aø¥Åæ™3Ì!;£×C¹Á;OfŒŸe‚I ®cº_\ãÏÉ9ˆ~â ÓÏ‘ +‘a.¿Úœ&ˆÌȉgzM@håYMÀ²Ž¸ ;[@ók àçµsÄírçsñò£±öœŽGN'Sùb¯ûõÕWZ®pxŸصÜÔµ§°œn03)r©í%sœ]›¢µå^'—ÆC Ϻ 4/!¶‘Õ5ò¡5t@\59sâÒûPZ{©ðN#޵ëÈ[çËé]HyoÉó%6¾@.Fs×é ÀñÄãfuð£.îÅ$ù"Nß}ÆÆòüdn5üÔÊt‘>ž§È«x³fLg iPz×d¸au üëLš×ÞXñ”Xu¬{©†³.Óܯˆ¯z´}öVï3S7aÖ±Ë[?2`f²Ô5 ¥ovÅ€}~ݼ“ˆ(­<íküHKíá½HZÛo7¡¦ä9ØÅi=~ØÃñùÎ8 ¢1ë°®Ò=~øbÑLýÃöŽ×ÚîŸÿü] §Õ®7¢~›’=ÜÜ„e¯x¡Ð~s2gj Ô( €OÔlID.zè¸q¾-Ò/#3¹›„ ˜(âá‚RUN7F¬ûzêñ7ŠaUz ôÓçÌÕA°EI—gÍ|Æ 0ÆwómA܉îG͠Ѷ{A¼¥t~¬é ª»O qÝsp–Mb±EÂEÉ‹BôÍM½vÁÎ qœë'ÃlœðIŽsÁµÖ‡i¬Á mLô;¶ÅMFB7^C6–¨X7¬.lZ—BXÓöS]KÔŰ¹ºVV=:ŸÔ™Í ³æŠ¬å­yÖ_ëî„Õ±aÜ\—8¿É4þ°m=Ò‘£kŠ<Á|ñ¿Þø°f.ÖlÄ·æšOyê‹ØÇI]Óú«ôõW û— ÀŸTÆøE˜+; ^ûá§ñ,Šþäkœþ“mláö ¬¯äiÍË}®ÚéÅÈë,ˆÍOt☺B¢OttWÓD[ìàV?á΂f¬^åÞÍú»WÒW£"åSîˆÕÔYzÉÿѦÓù&«œ_ia7ä"Ê£I9›ó±¾WµÏzp¡5ÐKÖ ¤è\Ó›WbF½\žHZŸÃtÝ”+þ ÅxírZÄ]|ò"1G©˜Ö.þÄŠ_ôgÏ<ç#œQ§ÎIGœ#=?Ž"{Uï˜ØØ_ñMë¹¼¤Ò±Œt優9wŸFK\]{1rO‚Í6,þ/JÂn #±Ïžq¹ê+×øk U~û¬iRh fàÜb÷/2| &8z <á¿5UuË–Ñ8”Ÿ–VUæ2ÍLr²FÌB—/W_kÕ|Õ6JòÓN®(Ï¡ C"˜«As_…/k¢ˆÃÕ¸ÏÈöïlãþ’ºt[×QCOÃìõÓësFƒŒê—ç‰Ù÷QT#žëçQ<¤ý‘ ^“ÿðëº7ùmàÔ†B8ÿjq”Ö"¦2ÂWE[Ÿ:`údG1ô_IÈøç 2ÙÇ—®¤ˆŠÂ#€3ð-r·þQ‹•Alà\pœ,ÝÿÓþõ1RÇI·‹c ÷'it¶XÙ8³L–~­™(ªÄO)û“ÍÜhtÈÏ:TÊy>ä«Ô®lÇ:© /ÈøÜÐÅ?¹‹s‹ú6¤Þ6oG §}S% x#cN¹Ðå:ûÔø@æ!H ®‡'>l0ÆæßŸ¦#/qtz”ëòI2F¥ âD⿎„TMXƒåÁ@»¬¸3:Pæ -öGnv‘³~‹ícDѵ_¯TämðàƒÇÄÛ‹`R 'kŸ¸|q{˜,Ã?Ú@?5 DOžÈh‰gNn-t."€1 ‚§*ç.óê9E»º€Sr>uÿ_Ð}U—¶”áÆŠ½áäž#ùüàÃ[äÀúŒ>3Ì8Z`Ázß±Kt¿hTØ 2Gù%ÊøpQÈ_H°·ªÈ™„äzÅ3%‘-1Ö0üj>rFØ>/‹¿û€ÊœæxøVák Kò“,]üßHNÝq§°*ûŸµmò”(}ce™)Œˆ>‚à°ïÉ%yj.ã±L(œ€iÒ5I*Œž¯î‰ðéê1Ó¶Æí6¸õdžoó@ŒO®œâ/Cn}ÚAš Ú)ªÍ¹6rÈÜY­œ3û­5êaº»/D…ûÐp;ZàqÌ—qì>5nÀߦM쟎˜hì9·Š)ý°<‹à·æÈ8 =Ž ##ïZÌ18¤Þ߉–˜å©üù€ar”KÌr’M_Ô‰QçÖz9Žo9ãI0Ò¡óK5ëÉï`‘}ŸA ƒqy˜ãÅ‘M’pó+ÒÌ!ªèˆý±1È©spÌ1ÄššÃe¼`èc@‰ÁØ[¿®9ÁÅ{Qløál“ƺ|Ƶl€`–Öõ~ýá‡np-È ,üÁaßýþÏß± a·èhPÖEo^´sKÐgÑ¡@vyC‡®í·×âZ’`( øm6ÄÆ›ø±¿¢CKaZ|¨ 9þ±¹D¡ãz/$6NLù83Q2¶JS`]hë-R²_Òqº6uoh„Fç _…¢Î£6åi‹OÒÚaOsLÈQ{¨ôíö%ô^ÆÌ3êÎo¸L&Á_‹eÅ6ðžG‹+×x5Œ'‚v‚Žœ R§‹XI68ÇÚEoa›MKGœ%¿Hƒb$†;ù•¢®]s˜žF5ôãw¸L&ÐìídQžLˆ“Öº¥“¡æ•z~ÑøÀ0¤èØÍ5t×Í¿‹çösÖs~­Æf ï5W.^—hÇš`)˃pu¢2zоéÇfPólhrÁN½sá¤þÀ#Ø* 0{^¼"±1?.Ëqzăh[gQ ‹BŸéò‚‰,¶¬gĽÇÁ%F}”ðÅ%~“,ó·K8nܯ֧|ö¿V÷÷ZŒÙhúÀ€áöÐXó«]ãˆÖà@o ³½ò–kâÓæì³—ÀýƒÅ‚ØñÓL*‡ÞN®¼(0Ú}™«ÜÂU¤ç`&Ì?öÔ#ÍçÖK,©ê¨ÞŸ ëÑ}ë÷À'ާ6.¡&Ÿ¡ŠÒ s>¾Ÿê4cHŒ }œŽÑâ°Çý–uÒ}nÜ@iç*)Àûî=‡‰L7©“†˜^‚ÎO‡}iL>.i°·]àa8»>:—ÅÕÙSlQ âÔuàý@œ‘è1Ø€>ðôoÐû 4 c~}’…Eê±Àd9ªÕäb"Ñç{±Vš³÷bÖL6R"Ö¨{ÙuŒ‚Ñ öÈ×— E…³FÞuþ„MˆîÖU.P<±¢L¸®ã Z“«ÇÅTYbg=´…¸ù^²L‰äðÛöžÛ &à dpŒI’tÚí úãkÀÀa`nÏòƒ»}Šúú°‡D–${ŒòúÛ·H8ˆðWN{í9eâß§7ˆ»œé&X>‰™L>Þú ω§Hø!¯‹…GùзßÞ'”P …­ ¨tV2º[ð‘êWGòÂù/ÞßD%_Çñ‘¥à„O¾.Æ!]>çvШ‡ƒ©ŠjØú°G$º6øöwÙ’c¿2é/½Œ/ÿØÃ¡;=cÅÍôÆL·¯™ Tþ :,.¥Ú»p#‘Uºg$ÞÅ_b²V÷âÆ6õ^ñ>˜‹=vø]#øÌ*©›‘Y¦Øâ=FÈTXóês.yt[!!·[/eÅ®ù÷Ã4LñZ:i­ÛùDžÚJûFwçgîSïQ*ÒÚ@Þ­$<-?bãë|O½÷@ÀÄu÷ƒó{öÑùbé8}˜(ÂÄpƒGþ$6âEÓZ霨h‰›7<!¢‹ŒGׂôÚ6‚s9vü•·ç§¢³cÌÁóGƒ»Ê©]ý ÛºŸÛï<»Ï(ÏÉ8bEþÐ5,ãµm‹~|ÐåøÑNpûoÆÍ%X9K÷Ù¶XqLtËBì r çPúŸ )áci€®+ã)®Ú‹¶Æ]ßäVÊê<ÇwëPoý‰‘†MuK@™ªNLg-Œá»ÿ#¡¼Gl]ë¶”à8Ü=àoŽ]'l\©†0û!Àèõè ‹;*xÈ•€lî•@0v.Ò+\ì4(gPt㔞1þ¸ .¼è ƒ´ÅÀ§Ø1ÜÅrÒ/Ø‹é(BͰ¿12ÓŒíÙßÕØà|ñ™Øô[ƒòp'ÏôQ)¯2cI"ÄÆ0r –¾¦6ëÚG“F¼üÒ—²b¹+^²Ìésïi˜akŠi³þÜGÐa~‰c¿œ :'Zr?Èq1¢(ÄÌ Vœ½?ɯ\RŒAFÔø3´áƒ†ž>6½–¤á$ЩZ†òÅADÇ8‘kã]ð™îS7 ˆÔ"¶¯î ˆ9šñ«";ÚäÆÄ³»»·ªSùѨ*sz[ë[+Gùu‡ïZh5èÑÊˆÑ ¶°ÒäjÂÿ€N[5ÒK`7¸ÁÚ.èÌuIysü‰klìô°9{º‘eX vèsôÆÉ52¾ïȯ [uãÙÚKŒV ™œåp.#ó‡ró÷çXÿ¹¤y‰ ­Çoä“!wŽÿþý>Óâðcàäk3!˜G6fWbÞv^$ŽÝ®ÎT†Ù`oº£c(bKbõ1IE.ÖFcüâ‡# Yƹß$šM¡ŠZB:[㌯Bså&aЃxÿ?ºÞíWÃí*ïû¼½÷ö>ú„mðÙM¥JA(H ‰ ¥ ¹Ná!¥ÿø*½HE*5B\ $ª† ¤´8HH©+„`m0ŠÏ1>nö¡Ïï÷Œ1ßïÛvæZïûÎ9Æ3žq˜ó=|ßúÖZz:òº˜ô’.‹n&.òJ*ž¸·.Ïž‹M^éÊ žĘºœÛ"4øðà`r=‘@6pô§œÔz0b!ë¸y熹õ>¶`ŽUàÅW‚5ñŽ,:zÃMP20xú®öÎyʱ ËgeˆåVƒ¾‡‹_58ñ;þ,Öˆãé·×ø³˜‘ÃÖ&&<\8k»|‚³Óß:•Èrœ¼ =[|ä jb'gjÙL¢A¯ÿ>|oŽã¯6ØÊCÌS7/L•ï; ÷`sC0s¬ÏøòEä›´]œ—ëoãè¥8˜píœnÎü*Äö¯ ™mNç{d‚IåxRµàÛ;]ñÁ'ZÆ]CÅï~§×^Øh}ÁGí7$\»&mXàô۹ªWj xã¡5t×M»¾®(À]ç²å‰“Æ»k³ãïKƒÚFg”x$LÄÍ-+;ã^cÒ1öŒ½1` d}bƒ=›õLF¢Ë–Rü^7jtÚ®_f¥¶àùv3ž´z=?úâÆé—§Ü ?8 n8C${”Ç?”úKˆuZ·îg@\Ës!é…ïØf¨­Y¨¡ þ"É­Ýäü×_•œ˜ùŠÜºÈÙhê[ZüH˘ü‘QÛ½VmP-W_ød¡òtNÖ°溴–ðãp Éq®@ˆk ETvúpË3r}±¾édË7ô|9#g#&CKìÉ—•aÜ3çÄ8h;¬ ÌbG½-ÜpÉ7ëìœT`øßs¯µ¤æQ˜_í+y„å§ŸF,v¨q:4<ŽB˜2æ¼Â˜ÁEܹJHÄŒ7.zF­zPLCwX‹¬¦“5äf–0OŒfF±i^ø}äg~ ¤êî±hí4¬ ô1.¹à8)ÖÃ`Ï‹-=„Ú˜UŦckIn†2Î5Å^ýfÜ‹RrŒImEÝ;Iõ#CvÔ¤Ó[ÜÌõòËeÀ 5±ä´ñV¢©9ÙÑïCôU$ä^˜"â?m²x¤„ˆï;B­Ø)Ï*ÉSwób¦ðU¾{I~k$OðD`Lw` “áTt'‰fMr½àð¡ênÊ•¶6â+túDÛ‚‹“0À44Õrì ×ô’üu<¢´¢8ÐÀs+{b`Ü/ñìÒŽÛÏ`1MÓncw0s¶  hçóä†ÌàRþ!ùmŽÕ—ÉýåøN¸]”´p¥ë9’.Ìò#fÛˆ»:Ž]g]½€ÔäE°«(µ³öKe¼áÛq:ž àqn[%ÇíªzžVµ5 ¸Ì@}4wöÓ§¾¼ª‡x³½Ádmðà—½¸»£œá 'K§YvúŎᥑSÍN]Á²í¼É¥ò6¿WôPoâÒ×€Ù-Íÿg s<ªºr£W›sþ'F$„ªó’Ä>5Š%lRÁqÿKëMlôõ5ô/ šh}¸¿Î‰æy‡2¯puÁÃ7ñò¦ÚÄÝ:ââò¿¦”¬oaî&só3ÙEýÿ.zì í3Nk®Þ'Zb;ʘÁÁ ŠÙ8¤M¹]èà8Ìé3d}C¦ÊHÈàz®F0²Zõª˜»õn¼¢ïhj²|õ!Ê:lÔ÷ŒV]ŽG¢æŒ­É'þò°§‘S‰ÆŽÐ9n~Ä{Åå4êÉœâˆoŒñUBHÛ¶Çœ{>ñ¢`ÙcߪìYm×Ô«ŽÆW9Ûa^W“/ëXgæuB$Ìá¶;õ^Æa#›œˆ†n6V"K!sÒg†ZWºñT_MЈGÅš§ù%à§J;Œ(:ø€¼hñã7Tùàë›ða¿‚ZÞ%Ÿòô‰£4ß½Hÿ\“˜L™è7ð§9Ñå†ä½i—±'/åËÖ3;ÝØgÿ:­cR6“=Ea€BeDàÒw8:4OÌ(vùô„CÄÜ:v9% }öqH¸êë:¡­B„Í»q”vNbóGÁ<“Ë™ ý±5¿Øpq Žcb‹Ïè¥p/àN!Æ!v¾Ä;iüÒm?î…üþ}ɉ¯îô!ÁëÜËÄÎ@ÏˆŽ w©î5©£q‡Èš:õ5;kå>'Ë0…÷'=É’´‘X,ÀÌT.tÍ ú1R†Msi èª\Èà ˜‡úµÄ¹p/²4D®u8I¼¼(ȱ71ÌÐyCF>¬F¢zB·­&q˜,˜›Ú˜ˆu,ï¼5Ü@–!&Ö@ª÷HjÔºµF1(}7N‘c8Nù°W)xô?dAýíkÁNEPÙŠø®õ§8598À03ñÿÆ7æ#@«%ì°lré¤ÅÈâF'†d§…¨~"!øð¸vpb‹ ¦­ïóq êªk‡ løÕó(–Z‡€n}ïþèªÄ¬*ÃÞ<6 Ìd(yµÔüÌ>RôæÃ9H<©#Ä!Èøk¡@,öG?_Å4Éæ\{÷S‘†0ù׉ ÒÀ°H³˜{ÌÁºp ¿çôÑ= `ט/#ÆÁ#ï}1´¥Ê±‚‚$¼†ç87#-‡v3¾âjÍ䪛Ø_­œ;.ÉP­0Ç5Dƒ·^ìfÆÏ‘îôz„-b+R ý€zC[ƒ+¿!2ç‘zß·ÒŽßQ c]q Ù~ŽÖ rùÀ†K=ý´S„‘GÙµ²>‰~gƒ¹FIš"çÂÂÍéÜGÎZ!ä´—ŽN ļÀ4™†G¥yÕCçI‹Qæ'X†KUÇ,HÚ b• U™Rˆ®|NÀê7ÎkþÊÑ_¤Çã(8¶<ÌÓîb—Ãh«Ú½5‡Ž|¡Ù8 ¯ˆ{ßµS1‡°5`–ˆ·ö%¿Ë!* 7.õì˜Ç‰U¶ûù.ÓËXAöziƉçJ7c $mXÌK¹ÙxØaÓ,rŒ%“]ÔË™>*Û=&ý1}`ÈÏTIC×AGÄ·ïã6º †›Ð4^Öt£ô^C»Få¯aí0¾š20Ç÷¥÷Á[ÓÄDŽw~Ê` õ%ì‚\š Jâܘ5M޹Ο˜ë‹ü°qí/±¶ìÀ°Ge‡Gn‘µ¾½&\7,Y[õ[ê0±ˆgs6SÞô@ï!Xýê(ýä˜XxQ2ABL˜’EÊ"ì¹iHq5.Ü«y@¼`« ¾Ž­›špùLX v´×%ÅX ¾½q b‡¥ûï~9$¸:€iõÑþš™PvÓ¨ÁÃ0±eŒ=KØht«0Ï|“³dù<çäGm˜trg¯µhžÆC}¸ p,QX›Yd樿jˆÍx8wÍ9Ä!Œä2§Ò©@5M’,‚pð›2|ÁD”9ŸØ0áDïP^‚D¬h­ÖË~ÆU•‹º°‘¿ _†‘ÉÝ[Ù[ ãÜ.ÞW87²’â›­µÀ¦}:õkpÖáð¾LQØôÒðáDGãmcŽ¡*ÇÄœÍ<ÃÉÈ®u¡ÎÄ×x„3æåhŽ3>7 ÆÔòP¥ùÒöi„ *0'n¼^ÍÑ 8Ï2Ù†»¡~i¢Q"±ÓÜù‰õö"æƒk,ÛÁÒ/’y± ÐuÇœ]$D®«k} Müc„ÞyhiyÈꃖ7ÞÈ R^ó²D–èœÉC+µ:ô­ ñT€¼ ëüÃ1Tv;½9¦g`‘9!õ‹Öþ4 ¿—¼7ê÷a¦9eT†μµñØKD°þ‘Ñþñ¯'â߸¢oŸè¶ÚÆÛ¹#_>úŸœ.Có ¬%°³.ìcWW}8 ß/rØùí ¾¶»÷Üñ:G-øJ‹Áu+@ˆÃ"&FxuÄ#ê=J‚;iDî%A%€‰+&`¶®íñ†ÂÆØÖ¤õStCR"ùÌgLŠ#¶­G êóáñN…l «7„ˆŒQ12ç eê˜!Ö3’l™4Ú>m¹9f3¦ÆV¿#—›,zᤤW‹œ€Þ{ȹJLÎûhïgØÅűz†ÎI:n<_\g²_Œøde7Cç$=ƒ,o QZ‰úSõè'¾=o¬ÖÉÑÙl;âކíù¤Ì#èæ³woÌñ×ýÖÐz_gí\^šÇ5îŠŶe½ŽðëN6bñ¡ó@àÜZ3/n9L=JFŠ‚iŸ1¨urš´ŒMÄx¡2ì`ŽùÊy£H,ðšLGÒèrÔ¶ëÐXˆ(Xæ®o~‰Ò¼ó9dä§mvt­ ºŽ+Ìð4t´ÁWæ×ÉàI"Ìr놓;NàË*«ÆùŒ¦›õ•¡ÅXŸ…4AbîyÜzÕyä§ÑOrΧ-+ý’tOÁÐa ïr2D™B2l›ž†¸pŒøBÕ0v½Î” –…p•µŸ'%ì{R£È&'¨³^¸€_$ éŒï9è—‡=9D8]˨ËŠ÷FŠéßǪmŠ—úî[lóî¥võ j¢®¿uwqURW¹ébCøÑ”#ãtè—?ubL.ʺÃÞZ¦yQ½HÎ\SsqÃ06ØWÜjh­ä¹ìnVbÈfCƒ[È©¢9êÂ6+ccÇ֓ÓÛ5Л–ÿÕ—“Ç…]$kBöÔÝÅíÚAccÁK=öá”À®qÓßõ†.ÍdsT©DÙZ É 0¤Ä¹‚5žúŠý¶+éqmÖ¹†ÑaòK¾óï\6üQÛÔ¬ÀGÊ3‚ä{ùÀÚâP\*(uí¬gäjYýÖ·ˆÄFL\T;×3gË»u ÁŠüÅù×ø+axdvØtT` Œ©ë-ˆËí¹‚s[cë ‚Ånuaí"Ž‚kN€,nˆå"oš3§ƒrɱÜÄ\>lhu ‘£‘Éh¿a¤»Üг[ †É!Ã>èVÓÚ°ŸÚ‚ÑG}bƒ~•3*ž(Ûàl_”iäZ×w™8?±l& ­Q'¸ó€° ×p>ÊPCòºé\bñZ,и˜y§þéÑν„¢DN¯ù9ð£Šé9·õ®ƒAö^þÊò¨èH…[니1_þíðŒøÿ50¨³6`2Ž©P'"·Ê ¶®Îq†2[›oêk ý©"Xô±s!ìšœu¤ß‡0"ò܃CÈÌÒ`c&÷nµnΆ9q2?ØY d‡(ýɃ5dÀ¢¨ø T ugéõÏûÓW_”ÚQÃt°ñͧƒû*øÉ…¼{Oì¾ÌeÀdµÀŸëŒã°·6Å!ç±çþ÷£¯P¥Q»6pc7qF mƒfÀ?k%ÁkÚØM*ÊÕ/§)-ìpÔÓ#‡Šú§.9G†Z‹™m1ÈÆ7çƒör>K|Õ²~©i<¾áF~Ðä@B—ó cè†-±!J³žíŠ ~D¸>å98øç™ÀÉÇ08m¬€}}%YéÓ'jž•Ô+$ˆÀK`‹ë\ªvMOb×vŽúÁÎÅ89$Q™KRjMê£xúiS“ G,:=¯w.'ƒ8E¥¾“cbu*Ž.!LŠ^FƵ“·füYÔãG¬;´ (=cZyµ{9ZPeºZôbœä\`ÙQ«êtvÑ0ÜÜ vUp¥a[ Î-åàî¹ðž¯ÁÖ˜…Ô¯d<[[ßQgbWNah>®‡p9Õ9öÂ3¾#å ïÝÚ¿¸P ÉÂvñć„åæ©:~ï!¨mÄÏ¢ë¸Ò.Xúõ¹žËÛDv·0Àñ…±òW..òEÓ¥‘ë'Rß]ôP¿.â‚-G¾5 $ûËw؃àm¹³x‡(bÖ¸m0ƒÐ^bŠLbâŽì¤™9ZEiט>Ö—<«C˜¤³ $n§·F{ÁÌV¬j¸GÚ5;ƒ=ø ’AÀ ÒÀ0[_,­AÆŠ³óâÓ~k¡¶|Ôbc ƒÊîä°øPž j»Ï:÷ÜMª‘ì½¾”p•~ˆUj#ìµ-²}C²öóðÖ4 lÙäàÁ i÷WŒÇÚ ñЇ& p€p|ªËøaÌ¢ý²eVõÑÏŽ{ üaæN{~ôЂ0y`Áez}à_þg54àÙx&ÚÂûãŒ:*€=8d>kÑx.›0M6ëþþÔ[:Á<,”y¡eÖEÒ'Ög­¦C,Èy€"çl=ÐQgòÇ 1;«ëvSç®æ8»© × †àrݡ澣%oH¢Û‡Ã¦TbÂ_{”ƈ8'0ÅŸQɆ}EÉÑù5Áô!a«Âãò¢ðZ.üžù€0­5_Ô+[ù¢öõƒ¦±—õ‰;¢§&mõC¿Y©6À*\ÒAÃjñ1âð/Iq*©}|2¿qC–Pžû¡H8’a6æ{ç øÇ6ù†Lú(ûGGvÕäè‰-µ¤^§ð‰3Î7¥(Ty}¹Õ3Npé´(ñEЉ#‡ô:jüpî6¦x¹dáp´1-)ë¹~Øa¹ÖV.2•åۮǙgxΖ.-¢^_é0‘Y; ¢g¿¶eÜwÌP¤N‰Ã#»Ötûãœù›1=º4Á 2'»FUdWç3º·ÅhÇéû=õ oíÖ~gMh’5F Ïý6XM׫â:—EGrZŸo9+Ã;òºªß´álÜ‘‰Åwªë¡¾;{@0¾fDß8F.0ÇÇæsˆõÛÀ6mNî}÷ßšíÚ#¸´Bê£ç%$\w9V 8^ ¯*Ú&Ò…kÈ àÄ['=©·¿GŠQ' oëqú‡'ãøF=Ó<lLÈ©!‹}ÍžØs‚ñKâ€E]go*]Ðdn|r.fúSl´p”´¾±áB¨·"Ê5¼°-j8„ÐGž©qLü”.{,É죡ÏFÍ9R÷ôéÒ×oŒéçxf¦NN»³$Ñ%2ÆãýªcDfH‚ph,âmQ¸TGÕª17ö.Rò…¦GhÌ]“Aú­I:ºq§·Æqr¦®¯½þ¯!‰Â/„à—Dú@E§ï2woi0xÃË>5.Æ1ÉÆ›tš7üW‹²ÁŽˆ DÒ0ªªqú‰oûØ`êì-Gö¼]¨ËVrÏÖZ€Ý|S¿Ô¸ua´uö¦©-2lÍ—®µ'ÞT}浇ÆÖZf0ÝïzwX8 %·fåï˾À#ÿÚ],3÷Ô%&Šè×þMÔ0Ûèù§B§ôcÊ5Ìn_¸LuÂMÍ`¢ÅýûI#ܣʵ s‘·~‹9££4 9Ì­„rAzd€qDc~° —sU?G-&óLLœiöÔ‚©5ö±t^i´‡")½mãÈà>þ±¡Æhòºw&ž¼VGŒ½. a#VoÐÁÔÓð%¡þ¥ ƒ]äÎî.¾A]úZDÜ6=n³Ä'0ÌsþðŸ¶Y§ãEwó<¢ £r@ž=ß»Ž0‡¾x4¨(‘¥ï1|WT¦Þ{Í´BQö©†ó!SÖ¯éú£|*f‡ðçCC 6ß½=Ö¥=k;@ócáуk ïõÅ~„Ê©a±s„Û{ZkÌúR \|%’i0퉈²l3wC¬/uB.®ñ«õä Ô×®ÀÚ­¹ÁsZøâ“Ô½¦ZœfTÚô ³;×ññáóWôüïá£/®¹z®ÃËyÑ‹Þá±jð†gý;À\„ÀÎnø;?t’‡cwÓÒgâfP•j°ÐËÔÿs¢•ãcT ½ûkPÆ'–òvæ|†²2¾®õ…|¸üÝL0ÌQ|k2ö{Îü#Ÿá …³ñõ:Μâk)«ƒú1n#t¯é -,ü‚<6ZF·FÄ3<Ö ÄĈ¼æÁ¤+,ZìÄÔÖŒYMدq?}ýr‚“¬5î‚ÕFGvROåݾÇkG0W—\4$Ѿ‡äjyâTbŸØkð‰á=.L9,\v¥#] rd‚Y”ѾœÈ7êr1F1ª‘åp.àĆõô-ãN@³V —q×ýóQ+f±ñµ¡„”S­F0ÐZƒuè¾Sª®I·»ðO¨éwÎVYgH¢ûµhޏÞu›ÁÔ\>õò¯ Æð5þÜ!aØn¹ FCãxê€ 7_ŠlL‚ŠìüɦS·6ÔN&FÊê+2‹°žsIJ¨¬Õ¢‘ÙÏ/~s±à!º€ÇÃε˜Øî|˳òÅàldÔÚ‹TEﺼxV«?ÃÝøà .5òZ3´uÔ€›åÑÑÈ2ê;Ç5ؘv®v™'ÍÇ|éb×… ,/ŽíËû¸PÖèH"÷{ŽT²çðæ[ ÖK{äæs’Ãr4wÙðQq»¾4Ò/‰q-3Ä⪪Ñy€7±n_7Z1¢Ž‚@Œpqû¨q0[rb{ÕóZ+‹ 4Ò™q¸àE>«äŽoÏs‘ã;â/·Û@IDAT©_)&®@Œa6Ìë„k7ᢑ¡+Œ=sÖhû1– Õöè­ŒPÖ®ü•šUªÚ,ñÙJ*¾v.[ ެ/gBjÝQ¥gØ`éÜùCætD¼k LQÕ»§Žò0Š–6›gœ˜§–`Ëà^ÜØ©—±»åh oÆêÊ3´Æh¥ãÿ¬GìðÁ…ÎØí;Ðë¢' ¼üÉðÇºŠ gkµg’t"‘¼œ£tçMþ§Z`]ûÁµÉ¿ƒ`â= :;ëgÂsÙ8ÁUïÿd8kY÷m©Ûë·«f¤á|·ƒe>±¡¥ïuY±ÅO\¨ÉœëÆ'Xyjwø- Ê<»»†ÎBÛk9˜¤—%ˆnçþîú#(gÚÔ—K¦(†YsIñƒÑ]n—·™/¼‘Še˜<e$öïäv™#¶4ýDˆ\ÝYM–‰kyô×úZÌ«d¥H—â›<äj‹\@ã¡ËÛ½æ ^k^íÆTGÅàû¼AµÏT{ ЯN6È9J ¹[ê7¿BÆ[œ A„ €K"%Ýûc·j#Dðy¥uNX+„Á“ÃI£å6ÝMášG}³,\ÆÁ{c€ꡇ}¿Ä ÒKì`áÖdº-ú±Ü`]¤Á9«8ÂþŒSÈ=|=èá+ž£a|±ë jã_"ƒÁþQ&ÅÙ=ž¨em~\„Ù†ßc¼ÎVÂ“ÂÆË<šHsŽ'!všRw:m¤Hô»?òø7OЉbÚý$™2üøMéÖ]:ü(•::S7/Úá ù ‰VzdÄcø»j½Ñ¶ÖYüož'#âvºÓê!6™»»Ç§“WϼmdaÙ˜G¶±ôßþø"~·HâcÏ=e¦¶Ìຆ Íðwvæb|̱4.×Jâržª©¯‰¼[­ALZ;/NWj­ulZâh\M!™2'·õÄ™N³MkfÌ…¨b¦î[Í*mìSëäb ûà€ÔÒ/Kc»|GŸAë´7+VøÄgö6æ“®-]sªÌ³ÑnübKÍÉ£qüEçº~gVlz=™‹6àÎ5×Ô­qãĸ¼Ë>Fò·(H˜#}í\÷„Ý2•‡Q6_d cœ–µµzâ»Ô3k’ë+æÚ`Ç<ј‹öà¹j"ÆñlS2ýÝòS[ÍbŽ€âá°D€Èƒ˜Oý0ª!é;ñÑs7kF“¬MÏÑȵ#‡¶Z³G2k˜¸Cԟȧðä8~]‘Õ[zmåf=”Ÿšéf,Qn10ÈfŽÓªùXúGÅÞwe 5‘‘kÃb‘O\Û‡‡zà‹Ù¦x¦=¯ëylºÍžóH”&.ªñÖu·óEý»!ÀB‘ã†îÆÕÏXGb­P¤ zSÌÓù„g#êšQ€>YŸž':*·vøž€›»~öJ„õD˜ãÔYžÆÕغV»Î¨øã5¢öÄÿ$í¹þþ‚E~æOÄÁèãˆ#!FzâáÙ6 ³`;Ñ3ö¼ÜsSA ¥`WsËÜà”ù¢²O-Z“òca9“t×ÌÎqiÑb½uØly—³^†)Œæ§õæë:ΰ“JåCsŽ• 1ÂAðõÔt_l¿QÁ–Ÿâ-wþ‚%¦µZ?Ôã¾!_]]aá:&3ÃdÅO(zuÞ¢Eçï­ªãì4iÏuÊPÐÀ\ü˜išãæ¶Ïœ’Ani‚ÒIýy=Jþoxã“ù?‡Š…ÎE“ Æ)†U='}…˜ÔF¡"î|w.‚©ÀžB-Âpƒ·Õ·¤Ë'*vW(QZ1t9éÏ;€€sð?Ãõ·®ãø2ø¢qáp¼PU06¸-w¡æ;t0µ¢È…@Té§Ž,+ç4ãfÇ8}ñu‡O/R¾öDnŽÃåIúÎLDÖ ²6ù!ì½nú°‡fðf‘x‰’w÷;Swð“Û=±ê.¥§MòÚŒyÂGÛÕQƒšŽU # ”­¶=Ž¥vV?f`ËÍE¿ë ä(ègs­kÜqöbæøq‡%öXCð 4hÅ1êÌÙ«Yyj7j×%\K»ç/þ13Ïß]/³>12H­u-"$c!¦Dd¤ÞÁƒ+ÅD_rº+]¢ Ž‘\=kXêÓ*õæ6ªHKLjb/ÇñÅ ºöØ<64‰ שÑ(ÁÇÁ®¥`EgL,‘aqèʦ2Š^ëdÔaäá_Xõ^sfÃÌCo £½xñÛÛ úðcæ¾÷°­’!0£Øð&s¯={¡ÞóâXß9è4^Êw^°Äaa Æÿ˜j°¹e`žƒ6”â8-CÄ-“=F#$?@ðOGôâ¢P̘‡Dê’>o–å`®ÙMˆ¬ P”h#ÛH­ÿ]^Ò$væ ºïn®[¥ÁžAac@Óí9¢P°t°©»:Á”ê’/ú’¤ÈÇtiÌ‘+MyôÓš'¦µ—wòÅÃhêÌ84'´aßÂwG 4¯Y_‡žó2ç¶a·Ö Zñµal´Ï8kùÎñë˜5gXMÕc}öÞ&|Ñ­éIHH«q?ÉU›³ CKõuÙƒÙÊÑ›ëh㇙ë@ä¶ØÞ5-¡³æ†m|ºXÏ4¢iõ‡%šj]4ôc‡Åz«:Ø|ƒ„sdG¾a s ³mø© Ýè5ÛA1>ÇNÍŽ__ G/1ä¢`/V„27»ñax\€Z”·³nlc€JlÇ&G—©Á1Ïx|“ ñêŠU:휨“ ¾p=å jÀZ”·¡­œÅÑxt‚E Â1 ŽHFóì ¬Rã^96ÔÏw¹Y×¹±ÍþyÑE¢¯Kn•61¤dÇ; íc|µ,’ÇXUº€èIƒÊ^ñÐ0éY¾YŒáì¿4hèÓÔò>>ËmNYOòÄ ˀðè6Iø‰j̃Ā¿ŽLºÁáŸ9 +bØ B8?´Tá¬q§[¦ËËZl®Tˆ"˜ 1ê sŒ«£¾õ}©ŽMìz‡+Í2:ßà û€†;>—FÛ¨¥1 éräHt´b“Z•oĬ\KÕ‚1VÝjß}YïåÀš·H À·Ä—fÅç¿ì5‰Î¥'|`CFÄlõÕzµi[HGÆ W¹ƒ‘ss¬?0˜`rä ”v;×"èÒŽOcºVI#Áž¶¾X_Õð#YcWÔ¾¹?>5;ûµ¾×ì…2¸Ápà¼,#_ËF‚ ³:Zé Iyvm6‰I4­vÇš¹ð¡ÕVÙØ`2äJ744iaŠhYÓá{îEÕWR’Aä"¸ôáÖ }§aâ‰|ù÷‡¾è¦!)_ö6âdr̃ˆÒµww. ã%sÈÜtŽ&½f1¦Á»vŽ”µÖèÃSu±z '÷—é‹"_y &¶ó QsÙfì›@ìL1ˆ|±q|f,nW‹dælšÙMøÆúÞ0£ãÈŒF_®Ë06û˜ó öDL$Ò¨ Y‘7Òì¨5ÇûmüÔ Ô 9M¢b4[#…»:ØÚ¾Cîù¥ÜÍ+#ë` ZÌcBq¯<§.ƒÅŠË@ãkltpõšÉYvjÁ5‘&V×%ƒ$;ßÎi ‚ñ¸œðîVV¥ý¢të? ÇËI ˜QÖÁ=êœ ©ùØô'µ·¦£‚Æ«;œÃ[n Ônµ;‡µhE6Ê16!bÙ~uŠÎNó55‡m×KŸUÙÆ¼ÐËnEï ¡÷ÌD N,@䔸"'Tk5|^ó'îNëØÛrA3|ÈÓ¬¥²ø¾ÿOÀ˜»½ñH=AОˆŠ)@xÁ¯*nf´ }ÐÌèÃ.b‚üHQ]h¨›Qtæ¤}£Ñpl·Ï‘wAcÃ+[â{[‹à$ÿZ~äÆ4o±›¶ÄÉ…‡~x¹™ ¬±FFì;Ié‚Ûp‰„ÄЉ]Ã;»µDŒtØ;'1#¹ì` gƃ}dv#_5ÝQÃ^ Ï.Tm5A)Æi!ëÒèbÉp Öµ1ýŸ’(]}êo=¸øÐȽ€I7Þ3ö„VÕh47† nA¶–D†Ýä 8ÑÎܵ•c—Üüù~â ¢ÈĘ(/ª›ÃßV$/À0Úµ~çeßÉRD4±]¹³zijóª/è¨9ØÊ(Õ8kșۡv!Œ^¼ý5€tâðÈʉ.ßðàͯ™›•¸æ hmá+gcB>7=?1¥]:ÓîãEôú±‹!¤°÷waꇸ}¡&Oô9EzÃ+öz™:—^Š›y3‡)×!בMޤ¬ë£+!#]“q„ƒÜv0©þ¨/~Á5úÌ…¨uWÆuZ/9‡Qé D’|àôlŒ¾«6t˜Ì5øáz8ï:ÌõAgËCd>þG/„v#7îµ# ƒ6úèžn Ë2JŠÚÜ<ß2ÎÈû — k‡ [ŒÛzMJÐHWϱqëÓpÙÉqúÂ# ¨¹UÓÚ0v¨¶PD‡:¿Ðä4;±¬—eœñøâ@Ì^¶ÌWˆ 5hó¥?˜a›q픥Z‹-»¾0¥È'>ÙÂMÏú ¼LS:ð*§¾CÖ˜½9?d‘)F4ú4 à 6\áй~FVÓ±…Øß;•¢µÃ£k$j#Ÿõ]pd“{Æ©1òk b|€COƒŒ˜°¨N5<‘{šÑÍ×¢ÊM,‘êãŒâV^”!n‹Ý t 'v®«a±Gæ$¤O0¶Öú^¶Ž±ie¼°µEÜnö\iñ/ bgàô”C…BðªXë1ÒÝÔàðJ.¦¡ã`üFпùOâ¨N:ùà F1í¹þì‡Q¦Ck@ýØ"q1ž\M¬˜ž_õÜk}Ÿo¨«x¯%ÑO½Gá,œ9LIš_î×^ƒÔò,ÂùPæ`"‚,võ@œÈуàK;øé×h¸ ŽŒƒ ”ø˜äO~eÛœéÇG|Eß%ì0{ߟ)¥qF"€i´Y‰(¯JÕ£]zG†c6 “sD¾âbÙcG°µG_äÔÂ"C¯â¿ûXáÓ Î…”>܆¡=±„#r]œ~Ç× 0x×íœéòà£Øú”mu&z-ö£ƒb[sLbC¿Jb].t´(ÊI8'¶úˆz8€íÖº•‡ZŽË\¬ê ÌGÇÈÃGÂ^¨Uu¢}×Iµ»åÄ‚™cŽ•3y›ÓÔüD*¨|·[×RÀG+Ï‚èpÆ;¦»H‚] OYN…ì¹qc—¡ô¦ÌÚFèkð5¢×½“ã ÿ[1¤äZ¸‡p3dú¸âÜ,WÕp’Ï.ƒ}èÛüúÎ^øh(£ë½Ü#¹K!Ñ:—h“1QU‚´òî#'¡4ê2]FÍѺÕ†fG×ZÓÁW«$]óÑbì%§=r®õ vh¨YãÁWl(ßaÓ]¾¡ÁjŽÂÐhšF=1­|«Ìqì¼*j1ËkÃùWǹ ,  ®Ø;Œ ¸6ËJ÷ÈZoE î9ܽŽã5ðŒŒ‘ñe߯w|"¤­ Wc§*|¥Í‚Ëu}}q­K”ã£+U+[®]5õ5€-ý|ãšÚ›»´àÀ0§Å0>ÍóL¢ã0Íè3>>Õé@P´³‚ïò–ÿ¡H\È£õ@'”Š2ÿ"âñà®\’G«W›0œ9†#6züÔwјvMï±f<Œ?yœ¸—§žº'6¾cálÞà©{¸h!ß>ëq«ŸÎÄ pE0¤W$ÞOn.•e´@u‰ÇoòD!yöú—1:¼¸2’†Ük S(§ Ÿ˜ˆm5KÜœöäoÜä)v9 aWOåBUDðyO ¸ˆ(‚-×Ö½ø *v©WKjœqT­€÷/Ú9@ÇšcáVº14äm›£ÞøP³Ëap’'xCƪƒŸ€ä’¶v,\ß=QÄØ•­†±ˆT™XxÓ÷ä• í}cކÝð9ŠŽoÜO0 Ùhõ]~cP0xQ ‡Žkih» ¥>j¢[–LÇî ¥:°ÙLMá²›øˆõY|Ø)À¢Í“1¹rÈí‡N6ý%.ÄÆ–>?Ê—95í }1è;ž¼2bÛZ›€ui)‚Íwãn, HÓg€`Ÿàæ{*lr#5d€ÜÙaÑ\,bÛ5Q™êì`ä¢í«t/0Ø7þ2u Þ‡;ê±ïxDæÿbˆŸë½1™‰ô…‡\Ùá9÷äLˆyäˆ×ž3—ÏÆ¹1Hss,=Œi¾{Á\ 0J_èq¯xÒ&~|÷ߘ³s“27^L”Žx#EÌ:†~Úõ ë  šì §í{ëèZ[t½€E†)IQZ.Z5Ê"¶Î4þëMñè®›…•õÅ[¹Ç†&žÓ"Sœ$=SPdÓkÝ.ò­A¤ýxdÀØŒÐ̨¼ùbmACÛsTàónç¶ÐÑ™›ý^Àº–3÷ícäÿp’®€½뙺ƒM3ÆË®Âˆ#›&CüžeH³í9V$, ×¥y`[dK*)(°ÎÜt~b³Àè×›×åc„׉…¼‘¢Öb õÈ®5eãÕ;ÿ½5Õ9ÁØ‹<œÎNrôO‰ÆsÓ/|¥˜1ÔqtD ¾z8ùâH;5Ùu]b ÂdB·f‡ÖX5Ž Ò¼SPOãYâ%`!écúÉwÏ>–ÌöÁÃd©ï0茽׈K¾Yc)Èu×µrm~S!B7¾á¨k=A„Ä}!êØŸ9Âgr¯ 9¹T-ŒX7pµëì,hó7þ0ùe†?s, Â&¦uBœ‘g(3uåAá1î5r¬Ïí‚°=ŸvVàVwĉžÝfŽ®zUÌ&qÁ¯Ÿê°¶æ+õ}UHð ‚:5=ÉkTÇÈ”¯.çT#@ã©ç†~ì ¨ ëtþlï82ž>×GPÖ3¹ñý®M}îý Çhügb .Œ 4î ‡Ù÷¼¬ÏÎÃ:縸v:‡]Û(½v Äó+0ù©ç4¯ûžf×õ™$žàœC­í$^ŽÙÕ®d¼ Ë'@;MÐgsím?Š}>àˆ9ç‘縎ð“|}Ó6`C¹†¶'Ÿ|21d„À¨èèëTl¡} £݄粋9M–éàÇÞ³Oß„‘® VÝÐõ"Žzo¦LLäE;ôxW1„“6)Ãw¯É[k£-O y¨ ¢Œ­iø¨Ûê£=†ø+ÅEsš"È°ËæÅ.Gc¬M!˜äAq6þNÊÌi¢·ðаÇ~n¸Úác} \}AV5¶4älÍ›>4“V̾pÑOÖzÁn&†J>hçž6Ò×Ü=9¾6ŽˆÐ\|Á#S;âÀóUUpÄàˆØWcK«sn¶ßHÉ)‰’‹¡d —ÒQ‰.¼{îšë¬¿».i ¨1™(ì0×&Õ`xÓ–xé³:ŽÆŠ}›=jrDtàÊ‘:ê k£"tHÀµ’à2Âw¿ÕßiEK5ËSÂAs¯ÐåðÕÊ=@KÁèÄÅ€H`Ù-y+í>]GÕƒ]Yص/ÿ^«e\\²FèPî <ÒµÖÄDìˆZfÆ•]9Ek ¯—7O錪½:Ù=6´Ä{8ˆ=òŒ×¢¿x˨>zþaG½XóÈ÷£zó×VFŠx®gà9¥M¸É¡kX\Gšû@´YÏ>oýU€ë\8\¬v8\évô!ãC> Ì&ÄEHÇŒ9ru•*D|𓨴>_rÄ<;°v¼F¦_žT×8v½Æ&`¾dd‡ÓlÆ­1±m¬Ë½–ßÚnLAœø$bxv®q‚›8Hwï³ô·uàê‡ö5P0÷r<ñ´Swž­Õ†ÛÜ¢@ÇõÖûÀ±¼ÖkÃæ¡zìÍ!¯ãŒAcÛ{‹1QØ+²tYï­o-ÇÇ},µÅ¿KâžqYÃÊŒW† sÓ"}.$ë5ƒal$[`·Á‡>v[;oœ\PÊÃlêbiÕDfP±5ag*ÝØÁgN9À±ã&M¾œO^4¤Ÿ kéÙe#¯GdÌ7>Á¦åÝäÁÉL¾jÝXê Mk1&Ua5ªb›8{9ÇÚã•x‘5‚X °^@;ÒSq9£ëÅ _äêµ6Ô¬/9Áq¾Â½s ˜¶ÇËçÊîã-–\Û«åŽ#DN­Cƒ*Ú »â±Cšm\¥›Yd4ÖÏ6lW~ç0ê–52;ØèM¾!žü ”qíÓ]ßÊpšl“ÇÅ]ÖœIF–kœ.ñ=b;æ²ÕÛ‡ûˆZGtɳªôPÀÀC[*‡«ÎtquÇXÃàÀGÉaLƒóGý¬-Ø­åà¬/ýZr$ ,ðÑZŒþ F/‡Û ŠÁÒuìÐUÑ´s·ë³vF•n#=ªøt•K£k¤©~ÇÏL€K6óSáQtˆ­Þê‹ó´_7$qž¦ät´[srÊ×Ä8¤wÆwü]ÌåÓ¯F2NeZ³ðù‹žÄHߨ挱ò|¨¹p¥O\D€Õ51äà<Þå,´ÔLO;æ¤ý7¹Ðí<,b²<}¦Jƒ‘“Ñ"zÿ‘K1»dç>Ð3W$2ðj!Cäb„ŽUê aO÷ZWÄ ]òë oùºÔl‡x£Þd±ÛÌfŒš¨(ÒCÛqýÖë`\=Ä¡:Šä¾‘Ô7ûá3€¢Ú‰gã`x‘›8Ã4òc25F…¿iWò@<ñ4ºìi8V6ú¢¼Ö‰#ô]kåŸý™ÿŒ`7êÏ—Ãq‡µ†²5ìš‚byÓ§¾qÍ`ÚK`µˆ,kß{.’½fÆþpÆBºìŒŒ8ÈäÛ8ÃþÆ7ÎOTLt!f¸S¤ÃjDMgØ´_м\Ü¿¹j•1+QŽ{ÁEvß\í x•Fó†ŽÝâ+ßøveŒÜø"C76NÐlLŽ ™["„´Sì¥C1­uê~êREíò¶õó¡ÇZdÌ„¹˜ðà Õ\ƒ³æ‰…^Å:F¡!R6õ0Den‘žœ‡ [j: ܺÁmb‰¸qð‘›üÏÔW_ÖŠÿRÈEt]k žrZüË`GÛïÚ݇r”Ôƒ|ù ƒ˜][=©O ú;†é&†iÞÃØv$À›'fÙ_cÂJP6Ñ8˜<[hyºCNÛXáËZ×}tùîI‰R8鵟®£Æ_.þ<€£¨ìsñÀðÕWòNf,XÌ ¡u¾º—( fx ‘)Äȶ‘qvÞ~‚¹'Ÿh´…ùÏ€9⤮(û`(Ûp0’Bìéè%¶\#Ï÷9W´Ð÷H< 4b¤%‡pœÿ£q WŸÅÜﱯ(½3+R“[¥µ*Þõ™XZ ,Ì4åÃ&µË˜ª¾úJÿηÿáS;ðÔ§::¹9]¬²OnÔ*xcÃf[Á­­â;Ýb¾ç‘اþÑ¿šé3—=·ñ¹ÆÄÚªØ^,ÍôƒhoüOجÌÎñ}ì¥^DŽã£äŠåÕèWÖ‡°ôƒó% $jÖ ëC\¿â‹¨hX۷̑ӹC{ù°Ï¼°¶­ñB&ëúãô`]p|sŽŽWz¦ ÖuÊ‘ Í4AôWž<"ÓDÈ`‘ c-Јƒ¦4Çf³Ô\ë©‹•í½œç3!õ×{ærH8œÕŸ}êjÿuЮ%êÿSÖgb_ÃÈxÁpQ ¿æ–\øò•øAë?>ü%aâì<ÐkÃ?½ž[} üë1ëbBòùAùêRA®i¹Vñ§ÔмÐÁBl`ïü4>=ÛRùSÏøòa¯|›Ëåço9.wˆè²£ŽV‡<­FOACˆ›u”´"ˆHý‚”šûßZË3xûŸN8œ_à™OB”)¥©1.é–qâG<ˆkå¾ÏqT6š)ÎÐVÕqý FžÈ_ã%‹¤õϼàŸõáy,Ak:ÁiO ÆØ•TöÔŽã(!Û~oHò7Atwzl5ãÇ}‹ÂxF–$y®£y/1öR„½ò©îÅ-êpo]s>á+ë¡ç|ã§÷ÿÆg}¡›ëÓuH=ßÈ”¦pÇuÀˆ¢“hú m‘M<FŸ…¸c\²í›^”–d8±ñ¢ÀÄȱXÀ$·lœ0è’x º”ÍÏ´ë \s×~ƒª~"ÑÇyh Up„ß±Ù§WÛžX6ŒZx{‡©·î ŒùN9vcŸ1Ë"©%ËäE§ ûü72 ˆ-1Ò'›Lé!Or_yôÈ 3$.ð^|èÈÃË‹/¾x{áÍ/X˯|å+·¯ýë·7æÄ«{*„Ó:nm2´=´B":Z;øÇ·šø× L«_ðúˆ2ø2#cÎX‹éo=ã¨;úÉØŸQliÕ êX{P47—tDŽ‚Æ±}"(§‘¨eÌ£_Ì×ÚÅ™·îE•oé7¾ÁÃój^4?ùÔS·ïû¾ï»å/wݾóíïܾðÅ/+ù€1ª<Ô=ý¦7Ýžî9ÇßøÆ7nßþö·ûbÁĈ©¼,m®˜%!|ûãÔõP뤑‘µ4ä†Ò–ÁÌ©u”<­\/bÞHƒõ¦¦ ÕÙ±¼‘Îd ?ç¡s0 Ó¯Ÿ]Cׯ8—Ü]¬t;çèi¹è& /¢€pcodq£–¥hÜXLÒKÔ!{%óõ¶·¼ýöü‹Ï§ö\£šý—¾ô··¯|åË·|ô20WBè[ W¶¡Oü4]çF\pZ µgëu¸ó0ãÈÅY;P]O _xñ…ÛS‰ãå—¿sûú×¾ª®z,˜‹ý Hç¥Dx„;º9´@+G½^Ån Ð-ªÝïÅ“ ±ÇnÁ©_DFOþö‘§T}â̱b„¢6í!! ԬܳÒA"£€ ‘!¢ŒctX&™2-Bte<æñŠšÀ$B¯/ðP#̺àð €Ìe] S  4ýË{ÖÁQ(há³ØÐt™†ä:ˆ™x d žŽ„O¦qÆ (}•e߆lòL¯£Áé£Zjp_Ë®}®'£ÇrŠk.Æzš { ëÉ.¢;7Ô#ùZjjŒŠ·À±ÉÞȱU‚£FdÎÓå`üh© auò¦4e³ÎøÔÀ§U/JY¾ÆÐŸŒöþŠHØK74H;W¢²79¶P°?6rÆo[!ì‘gg­áq’С .®=ñ̺5/tKÍ$Dê£+(µ!€KÙÖÓ*ä; fÜØ0Æ_±Rv€B~дÖÐn%ÆÍ˜œö ƒC\«[õŸÚ„5b4´¡nÚ Mrt:•÷žÈ" ¾*§ö‰žGrÌld“g cOÛ‘ß”ìšÑ·11á'›ßaƒ Ç'Ÿx#ñFIÀW-ã, ň \û Φ,”+J±/ÄÏ\ôÊ…¿yç³ÒGƒÃîÚQúM¯W…ïŠ&*V‹Û4Šd·eZq¯ƒÑŒó¾ LÆ›¶5К¸‘wûÂy€.æv‡«±ÖÏÆAl“!\ùêÅ/¾áSœ'd=¡Ö¾|Œ` -º±0&ø°ß—(‚£Ý›.q?õÔÓ·o}ë›UÍžËW¾óí«o8ÊIþõ­å'`Lúæw½^­cÙP·Œ³^\Z>\®]TÑ‘ÎÆïD¬/XŠõ…|\ÐàÐy“?ýc¸è——X؈ý}…ÃC#Ÿ3†ÿê艿ñC¸­÷r,_Ǭ)íÂ}¡!{$Èxã¡Ò(ïîÉ'ŸòÅçPc͈ÈCÝ·¿õíƒâa“߉ìyVVx‹'F§ÄŸ~¶ò¿nªÊ9 *pÔäÔ°.[C8#_tða¡XjO<iÛŒ©a'<ºÖœ}ÃÃ7\¬;b`ndŒ_×´èî0ç¡ALüŸP¶£ahç9äOú4P ‚Øx±öÞ÷¾ïöÅ/|ñöÍo½„ø¡½ð ·¯}ík¾óZOÒ6bÖ /2Ì=ÿM¸qƒ`}ƽq·äPkôÈ:*%±×ùÚ™\į°(¦õ§ ¦¾Ú¥úÚ5>>A1Eá€Ö™¥·Xd£Ȩ²[¼Hä —a[â ƒòbÓ''.¨qŸ‡çLÖ®©½—”ÿ,d)6‡Õ'8/Žzñ;Š`¸ðÈÁ®“(y†.’¥Ú=9’¤6 ÈDÎõ2ÂF¼ í)0‹[y«n<%¯ŒÚöÏdn’dµH{U~ÙµÀàê_ ŠŽW¨tê‘7&8°1’t½Ä]²™À++ÉFŸƒvÈX ,,RZ¸Y$¸p>8â-dÈq¨ƒ‹Çqî/ÄÁ©ANhkC¹‘£Éây’w™¿åø­o}ëíÙgŸ½}úÓŸéÇtnýuIÃ5'ð4þýíÊèɤ_i‚‹:T¹¸ó Ù¬„’k\ùÉ`Û”1 á÷¨YúõÛ9m">8Ó yÿU=ëMADXË`)÷A uuàØ²§^ιC$Ù°%ß¾À†öF‰zìéqáCþjâî|çoÅ @ÀXLÏ-â¸åÚþØ9Û»½ãïÈ;É_½½ôÒKyì»ÉpñpùÕ¯~¥$³Ó›žŸ”OÖ™uš ë7¬C׬ï~¬e)A'zr3/v÷XÕY‹°äm×5gq‹†€žÚÉ«:1¹NDJÝJâXœ ®/QðP‘ù:0øÎðw *Bn ‘cLJÀà†°} ÄüJ>¢õþ÷¿ÿö©O} '·Ÿú©ŸºýÄOüÄíÍo~óíoÿöË·|ä#·ÿð>r{þ…o/}㥸Âãló®°†ú"àä>Üæ†Òx°«oD{ѧ¯©ªäo²–2†Íô¸äÇß˯ôã}ˆ™‡§žz2ñ¿\¯+®ýÔúªÇÌÝgF"‡èð¥3vÔsTè2v³Ó,k.Xk®M‚ô8·‰pdˆë¬°»}_ä >Á]q] ì‰'TÄ’ ëÙëzãlT y8_äZÛ½–flŒÁÃ?½†ÈT’(z_mJ׋³®ï뼫o<˜s —~òS~k‘/èâ<I]Ñ͵ʼ‰‹s#1q‡¢ùA9#:ÙæÚK—é¢u2¾ÏçNo@1€ÂF‡X§ïÚ`P%"¸°ëbô{MµÔí @éÁ›KE]Æ,wãœ'þYØpSÓ{Ïå‰D]FĶ5Á Cvá.={¶Ö'š3¶ vÚ®Ö¤³ê=%öÔVýÑC^·uåJJu#$Tg•8>=Ä^¤ÆÁ/J§±VýXTdžçÍÌL¨ ,Íß?s+±F†~´ó،ᩴvŠÓ¢LÑ›9Ôƒ½ÖíØBNÃØLX=äÈ9E y¡ë<Á6¸;ß]ír?>¯/¼iÞŸÓG™«È³<Kbk”™¹È7d±‰K—†œkdä(~t×9+[J¡…æuÄ ×B‡RflÎÁJ€ MlÃn4€«*hè"º.zØ5X1!Ií)[’\W°²¸Ñ(?ìZô¢$íQç:›FéME.Ä‚ )páçĘˉ/fà®XOá\`Éñxdb¦fÑ6žv똭 ÔÕÂõ,k1x:%X:§ÿkEy wO@ÆLO&Ø2ÈCAÞ½üÀ?àÃÿ¯ýÚ¯Ý>ó™ÏÜ>úÑÞ~ögVÌ{ßó^߉»š;‚rÀÃí5/ŪHwls¸_¬75ÚmòÄǺÄ7ÐI¹DÍÆÐGüJ@¼˜ùøÛûÞÿ¾ÛÛßþ¶¼CÛ‡ kºœÀ¡Ùqœ¹†u%megžN(óulM ïžC$±¿z{×;ßáÃ"Gƒ\& _ÍÍøyØçáÿŸÿóÿùögög™“Oß~ó73ÿ_‘œÞâÍÿûßõ.þù—Ù9ûƒ?øƒÛÿò/þE~’óÒíû¿ÿ]·XÐx¨Ù‡‹îÂÞ@Чl».W?ó-ÙÊ{´ŽØd¸ç6ƒºAZnötïëŽ7<¨³¿=Àp>Ž+Œ gòÚUçÕåPÔ5Ã>6§öÕ²z^_Œg…ÍqóEº<üðƒôáÿü'ÿäöû¿ÿû·_ÿõ_¿ýê¯þêíñoþð¯Þþé?ýŸtœ¿:¿_CF¦yM\ÈÈ„ØøI/Öˆ*ß½F¡ßf3OÃ8ÂqƬ¥çžεÄÃÿoÿöoßþøÿøö[¿õ[·|àý·ï|çÛ··½-çŸ‡Þ álŸxB çz'&]{Œ”u5kÉóßÚ'±…êþ(ÄPìÉ­ì­hòwÏ`š„ÆPU™²Ñ¤‡áø´^¼˜Ì«ajÚ9V IL›!m;®¤ V#šö¡«9Ž“‰lZ·?Ä—ÁD;ú;*ÀÙöÊ@óFB®gÌë»ßûžlï¾=÷Ü3žëýL{²•§lÃ7›óç‘aíŒÞEÐrb»†9Rb¸ºV–´µÄÕñKÇA= ›Ð#¿ð °oŠÔ7ûÔt|`­­®ˆ„Ü|3‡G_,doŽØ ïÈëåÓyÁûîxw~Z÷ÞÛ‹o~Ñ:êõ3ÜÐ'öžsXGÀ|‡ieô¥F:Ië®B´Õµöi¶b9bcdðBïZíz5?íõ’ÞÁA;¶p£‹ÐùÈÄ\oˆ¥NÖä"a˜Å€œ†MíZßs@]ˆöõªÁ‘·Æ€±M]š¨"äo;×éØ|èM_êÍ\]pÞ9’[uÜ×Öä ¡v²«%²n;—Èù©²ýý !qx=Ö¦LÄnËtÑï¹ÛùãYcA°ÇßÄ ÔÆÀºrCÏÆa´õƒÐtžCΡûø×‡tì€ë³ÞHòÚíÉñSBrÞLÓ)öC²zSŒa/zü80FÔ(3®ÓšAâ,j숽ïEî§:ÉPˆèR¶È üz×®¾ºÆx¼kØRÖYÎb»Ÿ ?¯Òõ÷që#²r6òpòð®-ªS— 7e¦(ž\}WÁÅ|9Ç^’«ß³~ÆT ¡Z/Š<ÓÓžÐôý'‹Ãž~p[kYñw-bclõù|ù&õwÿî“Çï÷Á†wšiÏ<û¦’X cG<‘ÖkeúF¶QÉ{ò+{Þ™(æÚ÷GcÃE¨8`–vêÎ œ 0œ9¾’9{úé~”éÓŸþO mÏä£L/'s4\%‡ÁÆPÆÛùtøÁ…vìØ8©°iéØ×ºÀ¡ŒD{‚»ùnëg?÷ÙÂgÿôÓÏøyl~/F.€/'™_|óí3ŸýìíüƒÿîöÃ?üâŸ~ú©“Ëwò±¬gžyfXn·ŸüÉŸ¼ýØýXb}ÍPO¿)x/lWüüÉzÅ_+Øß\ «¶û|™çµÍ:gþÍdó?6;Ñžˆ8›àÖ/׌Œºê°ÏHÇSwk½ˆë¤>ÛO|‘e«&pÞeŠœŒ\,’–¿ë4üÌ3¶ùš3¼þSpNóž3Ì—Q‰Ã”ÇÓz,†wÎßÿ¾÷Ýþê¯þêöÓ?ýÓ·ÿãßþÛÛ‡>ô!”§ï_ÿu2ðÊË÷ï¾S[üáº4^‡Œ2d-Ø!fãÊ8­!öä (‡fU}™+ù¾é™§o_ýZuüd‚ÆoûÛýÉÒgžy¶n&úcòQ:ç ªdø ?õŠÖœÈÏ»l æÀ0¶ý\j‚‡›w²)ƒ­s,½XÊ@†"µ`d$ Êî&šV„;Çx17Мt 9a–Q:µÀ7²l‚Ðõ]Á¾sEÈÎ"A‚v­@P.½–žH±SÐ×úŒkÃ>ý`jÛØ_}™‡ÿg}áÿ“¿çò;@/å÷ü­½ jØ—>®5éçá¼i<Ĭ1[­Ç_zo;×àÉwC®‰yMWœ"m£—9‰ñúFN-ˆ¡>‡H'(yÌidÔ,ZïÇH°íæ³KúoÊuó¥o¾tûOw÷…çž{ÁŸ¨J5Ñ—C¬‡0gs-!J3µ§YQsbp»›7šÂp4î`¯{ Œ4rÈÞ„†Ë8Œ(š9Rài>'e`ö0²ÝÍ cjÜókéÕgz““² ½9lkò0„x;‚rÅÿªE­oU<¤v0U·æƒ>óo|ÍÞs.ôÉÒΗ‰#‡âY­?…LߩѨq1¹Í'º·&ë 4øå÷QǪn±šŸXȵÇÊÌs&ÏœS¾àñM^zQ¾^J¶£qâ>¶Ø3DióF§;®\Åkò†Û“3J‹¡=ˆ¦&O`‡ÊÞÍÁ©Iåι¿ŒkÉ(œ9\ôI6c˜þêG^3Ù"™›‹6æòpdb6NúØrÒ¯sº ıs˜qäxèÅM’ØF²˜"ËSuô|M\J$vô£——»7Œò³iÅÐÛ8ûb§õ…6Ï(„¦ÃBVÕ\wë;´ª vX–«žO®uàžï$½õ­o»}ⓟPöÁü$€öÉO~òöþÎïØçmqßü\É+>2ÜõÓr€lê&Xõ&Œ]mÑWÎÞ^öXƒ`OGçéÌX!£‰ ä\ ŸÉÃÿKù=†w¾ó·ô?ü#©ùsŸÿÜíw’ 'Æó¹›sÆh(IÄw,ñIÝ'NÄ)iˆÅ¿“„È“9qTÊõˆ_>Ëÿ­o}ëöÏ~æŸÝÞù®wæ£<_¹ýþÿó‘Ûg?÷™Û³ù¸Î·òNìuâfÝ3Ÿi?øƒ?è‘ÝŸþéŸÚϻߓ‡ÎOÞÞ•wÿ?óÙÏT–w´hÈ÷w×>7雹¬#£Šœó·s1Ñ/îzó­®cd11÷Þþ:·í\`-ÆÊ(ŠFư5Á×i!1=oîØÕ¶%f>‹½,VB=aé¼ìaÝ•¥<š+h.\GÌÁ›n—ÝZà8¢¯‰•Õ7° Wíçí9o>õ7ãøÃþðíCúPÖÖk·þ½ýÞïýž/¢9OþýÿýïÅ|ñKÿÙßpη…FR^¯_yî#nÁé5®„JM;›Tµç›7ˆŒ™!µ6va·o~³¿ãÑ¿.Eë»pgŒu=0†¹x¦^\SЬjgi×ùµ”%Þù†óHJα4¼Õ-, ŠÚƒúlT‰ :A+Ÿx@‘HWRøqr㳞ç¸\~ÖXb‰¼É˼t8ŠÑ‰ z×"|òÝ^€ÆÅˆòÕŽ¾7¿žs’Škm%Ö¯¥^;ùæÝ׿þÛþèÞ~è‡~HðŸüÉŸÜØž{öykïÓ—Ó˜ž 1mþ½žqk=êÛü +5qy I?'¬iåÅWK¿ç ãðsðEC+Ôk(ÂÔ ót=G"i‘¶¡‹L¸]‘7~êG^‚X~õödÞ<ááÿïüÿ:o”ü¨o}üã¿ýáþaúù=7?×½öâ˜Ç5baAcðüÃ#­óÚ(ð—Q¯³®‹M’XÜ )?úÖß'ëùdŽr§þÇl¬G4©RZߌÄk.GU.¸ôùp4hèÒÚoÊéŸèâçœ8 ËÅXJÃŽc?Z Žsä\O2>øã¾ׄ %5Ð)3NÇ?ì  +%sš5ÔxÅn×â!pÑCNNµ›Îàœ·ôñÚh£ƒØ³ŠqGíú ÂmC™¥0N÷†'ýšéª8‹¶.r£9A&(NŸ Ä („XöxÛ¶Ä#£Xé¾–;YßíZ+ø(`ÆŠÂN.= —u=p× eBOô'ö a-}ÑØV–l§xåw²z!C³>ÓK×p-G¢Ue*éY·±é ‘ú«áôñ¼\u~ö§îHt–cÀäÓ‹;ŠõŸð½v{áùço_ÊÃÉÏüÌÏøqŸÿüçoÏ4¿ãï¼}ùË_ÉE-^ð;Ø×CæA%¦m2Û^4ÅE2b`ÓM‡Q¶;*â¼Çீ€ÌO cá#ïÏnŸøÄ'nÿý?ü‡·ó¿ÿßíüwÿ׿óÀ{ÞóîÛg?û¹Ø§Múºóg>.£GN õ2¾2âºìsU.gÎÓÚ]]ÄÏ[ßòæÛ—þöKx½ý«ÿõ_Ý~äG~äöGôGÞÀ‘ñ—Y^úÂç}qÂG6øìø_þå_ ÊÇ4>à‘þç³ïŸ ïSù A´üÓÿØ Ñÿüç¿pûØÇ>Ž·ôAÀX¸±¥näœq󙜑ªkS²ä&6ªØð2;:çîªE“-§Ô`âÇivÛFеûÊ9–ï’dìâF5:©±žÐ”Ô,16f|‘\@œ•¥ÝHBĦ„w`ϱ•÷òײ^¼ýçÌë/ýÒ/Ý~üÇ\íüÿ£Ÿÿwp·{öÙçnßxé›sA®¯ª×[Gûð¬7×uK¤1)Û‰-]§D7îá²^éÇHôžƒÁùçI9ÞÉ–¹™–Ÿ‡¦Þ¼öºú§.¢9SõT*½ׯýÄÖŸ!‰Ÿ!QOÿá3ã ¥vƂѧ͘yT|§§^+gÏÚ쌷hÄÈV[4®òØÊ}ëœô—æmÐh¦a™Z%>îïhZzäÁ8|Ç îûY•Á”KŸhg‚;†±5uì6T8óÔËü¥‹¯ú%.09gKÔ¸¾;oºüͧþÆãýʯüÊí-oyËí7~ã7n?÷s?—{Ü÷ݾøÅ/槪}AÜuÂ|Ã:ùzœT’·oú…_¿ø Ò:¦³ñ«ÍÀkëØ[  %w»p•¬ru bÆz¥Ÿºó‘½ô|VÐë!PÖy¾2ˆà¤Ûë±ÀË6½6j¹346æ>¶šÕ¶Ñe/÷ƈ´šò!ÇlåÅ‹ÀŽæüsuv=6°"ã‚z¢_t…<ø+`ôdì¼rÓ¾×9€ ùJ<篆ÙyØù1–ØòÍšl.ðÝÖ@Ž+vôù¤YÌS{Àრ>{‘uV‘"aÔ¹¤6´=ê‹u¥ÎÚ<‰ Bš°# |—>¼ùÎI°n8–H”á´—½ÄŒæõ†ã)âÓxKRøF¡×öÁŽ[o(#{P c‘ÒX8œ˜˜vÖGT_aâ+1 ‹{væ6ñä$ëÀr_ÅŒºp¸ÁÒº¨À›5˜ŒÒ_jëILøNþcI<Fȸ qB^g¼Ó×?YÚX¢l ¶<AoªUÁÝè"G<,šàÍÕŰÈç_x^ã¿ÿ÷â¼øøÇ?¡ì­¹P~!ÙÄ?ah#&v‡‘ÛK¬(ãPwvg"'¦Ø/Ó‡„Øèv§ úA"O+©"Zômû€óßþ½¿ç;äH¿üÿ³vð~UÞrÓIHBK ÷¦@hR„PÀÅ‚i²l¸»Š¢ ¬‹eEWÐË.MWÖe¥*¼*RL@zPLrÈMi$$ôÿûûþΜçÿ¿7ôãûNò¿Ï<3gΜ9sfæÌÌ™yt#nèÐa2·Y(E;ç(„ò(ø­¼&NÁÇuªŠV¦îÄE$²#ÀÉ?©ê¥[Êæ–¶5epÒÛOªvÚi'ÅUõJìØ1ÛUkÙ¶ïsàÚ°1b³¥Ýu×ùPv n¹ågN»\WBI›ïE®ª8Ð&DbŽ‚®ƒÁËWèÊPù£öƒVÞTÄ(³«_2Ä{ʲ H[§Œ¤Q€ÿAØ>REªIÁEµ†pþÈE2.ÒcíA0‡À³I‚Š)Óü@IDATÛx‘d!BQ§IÑ~bºà+t¹N,é‹ÂÈC9loKN¼|³Né枊íY °Ÿ©Bº…ÏKa`‹Â ƒt@žIîè£vûÀdîG?ú‘ÿW®´r¶tɲjýº¸–Õ‘æ+>ú‰  ¦¬3è‰üZûd“HÈÅ€%2+A—Aª~V¨Å2sõ /™È¥‡ŸàÂ_ê¼ ž¤ (?]qIÒ±—6ñꨤƒNi þ»`΂áÍý•6¯Âd•Nžûð}ô1²÷Џ=æG °–)äÐ…£1h)¯Š|‹Ÿ‡ëÚÐü¡À¤§üÀe=Ðpà^Ýêé§Ÿ6ðÈQ#«¥Ë–ˆ‡ÜêC§ÜGtn¨ô—½ª&_þò—©Ÿ ^«V­R}’rÖ¤I“êÝ€gžyÆpýtØmƒx üîć'8òôê8 d㎿´Ι |½ 3˜ÌuttT-”9з¿ýmûÙiÂ<‹ï8ø¦pE¶Šÿ e¯þ$ 3E¦È‹k`ƒ6d„záüG¶«àŠX”Ý­Ké-ÏdÂÀ“zsQ¸#˜`d i™Vhhó›Ëí)x÷Iyn´éD$é ¬øç6Jy/åv å7.À•–¸ÌùsÙõ׸·qòݬ—“fY—•W–LjÁ/¾¨_ØÒˆ³}µ‹ 7mÞ`yr9ÌQoš T¸7»;ÞæøPªY(B~—Õד60@;ƒpÞÂDßD¾ÈRÈdäÓV+_¤ƒá÷äù ª²î£ßŒté'`GI#>]ñcžüÈŠþEi)Wd´gÀk¹*æ<–+ÊNFñ—Ó¹Àåë2(Mp“<€·~P À«Þ=ˆeù7¨Â‘ ú1Ú«Óê/“¡úúHÊÒ"ë¦Þ#ÇØÆxÇ‚VŽ{ðŠp+IÒZÓAP”E‰ .è2/A(âL3<€ÿ¥ž,Ž ˜Lšàc†(oÑŸ‹,?ˆ³^É T}$n— HYäK¶ô™†›âè_)'åߟ]nS$~…tEG­‘þ½Ò9ŠÙ ºã~È/õÎmÉø¢Ì u]'b5M)kÀµ)?H0öÀÑPÂ]¯DÌgæª.aNR’;2ÿ8ß:V(¡‡Há• Ç»èP^ÈtB?Çê­”IuN!öÃ+ÁB‹ó1޼”†pØÏ“0„ó*ðG$7@ñP‰Šp¹X3 ^¹¿ªùV'Àüë2 mQyb²ï ˜Í\ L¡CI"7:+ Á!û‰qæz¦€ÇW•ÊuD|8<°óf€ >PˆÈÏ%'AiøÁ´_ø F¡õ*ÎHmS!#ÎÜóéúC%%l‰«áyç'ˆR!5ã Ò?òi:uk„+¬û =TxBá ¥-5.Ãe#„th¯;@÷ò9LålÓŠñújÍÚ¸G<:ÀJ«¾£e¿?Ò™1ˆ€ß+»Z§þ–èÀ)´Ó(ÉßüUœe‘ÕýP™&¬|1ÌS&Nì0®õþÀƒÙ²9D0¤`ΧàÔÃ¶ì˜ ¡HŵT$S„~¹€ˆ,)6DM™²Þnìv^%‡wuçEG%ºYe}añR)³ëT)É _a¢yªÎ ¥pÛÑ£*ìýq\ˈcåü ™ÛàP¦XÚȄLj#ñºtjÀ¸#ÎuÁÅÏSyº: ÒÇC¼ÙÅü§ !/Ô#,C¹©ªÉ“§¸ŽPàfÏ., DÔÿ)?žè´9ä;¸šÐ>Á“»õºžua×BÕëj ^}«þúÙ¦Ò˜zûãÓqNÀš”*}õÏxTh/(l(¾ãvg^Ào~ Vœ`pàÌ׿Ò3ƒ~”èlû*aÐ ÒB?üÁOˆ]áa„D27LÊ8pðn©^Ryàh¸õ¹7n¼8#k”ƒ:ᇼ,]¶L°ZSYQ³q»S¦mÀÙù"·T‘«-6i!“¬ZÖÈ  ñk„âþʺ—cBf,BDSñüW'Èäl¨Ìæø(Û¡‡fœ”wžÎÍนi£””š¤Q×N§´Y¿òÖ>Úü°0úµ†•E&Ûo·}QXb"”uoV¬xQ•–+Ú‡ë z] ®¥:¯W÷ Еütç¦wÂà;ü¿ÓÎÕ Õ´l§ž0IfhCËdƶšo ¤¨”…΢Þò7róW®3fôØjÄÈžõ@>€·D¦mÜ€…|úŒ•°0þ¨ª!Ú.yÊ‹ÎÝhB;hÐ߆…C3&v(/”‡t+Õ¿åŽZ,˜€,h¹Qëq×…p¨ó´Ü œr’ÊκB”†d, ômë¯Cã;—v·Iý‘äž~Ž2 ˆvǤ²±IûÁ}ùVS"|È·i'¦¦§é'Ž:鯳P,~ x$·8Žó+µËHœûBI 2F»$ “Ï¥êGÝö-Kô‘Œ¸6ËbÔ+Ò< Jå¯IÝòƒ´êÙ#µe8ÒFÙü×éÅŠëj[cl®ãöʕȊÌ~Šs,L²Y ð‚…r€ôŸ~úßW<£,ŽQúàIÐF“úZúÚ­ÒCWëäÌc«Â‚J ÈP #O$ï›Ë5μE½‘F1…QÐB’ú Äg“Àªj;]ÈÁn.‹\)¼Tm¬Mô– „µÔ‹ÊÈÄ– íè/4YÚ,äƒ|õUùYƒ_Ȳ’( ‹0é‡R“¨hÊä"šô/–ßAºPC}ýOÈo,⬕~bùUžŒ1‘Mê"”ë@¼*’ìp>þŒ+ÞØýû¬Žø`êZ#Î'|Õ?ÍòÖ¹­òVêÌõg”+<gI­’YŽ =€ÒßboÆòÄé)>&TL2ÁMœòô³ÀÊ¡ŽËPžá ™8"êOxK¶~+°䥖Ì (T @ØñÔOd&¨£@¦_ .ZdV½J¡ä¼æ ;WBEi r"ÈD ¦ IÈ›ÿ^YL,%ÅŒ¤B0¬X*Æ'P½7ñ !ÆeÌÚˆSN¼ëieÕµ­·’=šO0Í  "…ðC®p®àw¬¢Ë"\Q`É% ^ë-“û-ÊuÆÆ)ÎÛÄt|ì åŸ[z8¸ûÌ3’ÐŒO¸|²¢¿L ÓJ™"0[·ràÒ"Ì¢^åÛFƒîóÏ?ïÃQàÅÿóŸßjÿ(­P£tvÎëô{o&MšT-\¸Ð“è†/%ƒxº¼…´á7¢Œ/EO Î)é¸÷†8uu-0_ŒT<‡ŸÙ a7ÏÍ9(p»OÝÝ×¼‹é¶ÛoS\L¤XEòWrE'0_E?a¼•l>ÔD9¼ÓÒJˆå¢.-O”A Å6új2‡q)÷J™ùŸÍ¥Ô††¡»ßeûýr¢Î ü}àœ×0r`íZÝÏ?eaÅEƒQ2çÍVæ#q«]àöDF<‘?n…dåÇ×ýØ~P·6 Ê;]¨½½]üoÔ¦Bîå²?¸–USäÓõj™Åu kÌÚ¯ÂÜ]ßz%B3e›¢&`ä‰_:Ηp𮣣CIÚªÎιµÕs[}y;™MÍ·©“7µ7÷IÆOÛ$[ - †¤o”"È¡pÚÌìÙ¶¢ºâÀDwÇ!ÛWóÅwp¡Láaå“IufsÄD¶pÏ=÷œŸLÌ9ܽ~ƒlþ½bqjç<à›x’ƒ ”Ξ"{´ – í%;¯¨¬óIØ«ãã”)»ºLL-{ÆD{^÷UäÒ›k ~-oº¡mYÉW}´··;ñü2Áé a#u(rÓÕµH}Á+¢Eã +%r´™ðÁNV:c%—v‹Â2G;ŽË–/5loè›Æé O×Â.µ‡u.§š˜\ð’zRóQíyjoïð®ã_ËM™2Å n»È:3^9× ËÔÒ,‡£J°W{ ˆÛÂUD§@Y7n¼V°ûI®æõªŽ¾Emû:LÉ@?p©\ƒuݧwHŒ¸pÔŽúßF\dv£ð„œ‰fƒ’KZÆ]vYwÜ‘+D‡úÌQψ#ÃtRå9r„ûòà«Ö,,ÑßÁ Ï×kÖ3 ð¥”Ò?qÕ,íô…%KªUŒG¢ÓíÖHôÇ<ÖCiãøú97U±PÂöjŽ3Rô)ôÜž¦œ ¯êOxÀ…°èÃG.q„¥K?õÂ5ªL,6­bÂ%ƒ¾ööv/F¬Óù…’=7j@¸žý„Ýä‹?Œò›µ(ÄÂWŽÂó5úêv—ÆøAzù¼›}Ô˦ /Yùz¢z™[-ј’n;bqÅÛ}ŠÊK_ØNœ8É»ÆišiZŸð‹‰Èüyó”³j‰6*ÚCªÁ‰‹¾Ü„ª­2—ü²«ü×È/‹v]]]Îlaâ‰r«ÔÂIÑÓïE%‡Ã Gù M™qA›1™f`¦ €Tø ëþGï®SÁ*o¸.Û2!‘<‰ÿª–—èipò(ùø]ù;/ñ³Gñ gÊÏø‚Ï–ÿB?ËCŸH* š¹˜àô O]®BÞsq4ò‡¸MK­ˆë—ô¹±’2‰Ì’9@ÈOZyM€^¢//`Ç‹3¦ÕM$L8=ëBxþ/9™$D† q ¸æ€ ¼îl‰2Äi‚kæA qÞ~rf)ì…Á‘ÜéŒG0%7c­#ŠÇ<.éO³¡2#è=*:J¹fhâ¿ÿ((Ù„b:PõFßùèX} ££ŽqÞ¼N+šÄ¼óÔwV{îµ§^>•q×\sÕ9N¼£náJÌ03!£fa‡HÉÄMŸ>Í«-ø;;;yT{ì±§LUž²ÿ¤“NªöÞ{ïjW)/¿òr5gîœjÑÂE¶y¦“ÚN‡¬Ø±xI¤òì_e@>ÍEŠI–Êš‘m†ðM8s…#Ý{ÞsZÅà7yò$wàd@~衇¥,ßo°ŽŽ+® ¢£GA¡#deÅŠþ¸Ï¾ûÔ6ñÆÑiòÃÐÙ—t.€¯ÓYey‰PV¦„bÅÚ•cV™`¶Bù; üÒ1hA ;3/®\á_Æ¥¢Î„‹[bpYG”‡ý?gXMa%:Ý0…y"-bm^zòÉ'{nÁ‚>lÁ¾,’C¨ Ó!VÓ’ûï¿¿¯e@àÇê#|€¶o¸¡¦‹ˆ°87AÉ•¹j;sXây¿:_Ë”Âðº²%Ì37õS:Ùª,²BY‡ê>s”“¤ 9xãß(ùÛÃ4£X/Z´È4ýâ¿ðDšÙ ÀL*” !+y@2‚YJS{{».vªpgœq†ïî'øÈ þ§žzZõòÃ0p³2¼aS¬~3ÈŽ”RÄä —J /~ÿæ7Q§üSìÂ>Lçk6É«É#Pú¨›¢<Ä£,Ž=FãAµ\‹}öÙÇ7Bqx‘zæ@#íçVÝnŤÇD9^&lQ …)~ßúORÏàš T›%ÿÃ$G£õ øƒÛÿ×ûàú8Ý=ÒL»@Ù`âßzë­ÞMäâ€AZ%dBLÝЄ,€Eµ£ìh_L¶–ieåwæ™gª˜XutLt»&_dïÉ'Ÿ¬îºë.÷L6«Ïba$pǪpàEYÙT Öª?7mÍŸ?Ïx“–'ú•çž}ÎJöO~ò“z7Žï9P”4;*) gT‡M–u†Rä^Î}DÀ†&S&´ ï|B}XüÐC•LvhR°“åiÞ<ʹ¨ºöÚk¬ð­óç?'“ÂØ…*›õÕR$ùŽ.ðÓ÷ã¸\ ݈mPâWzqƒEê©Õe»È°ÓN;M‚ÌŸýìf7LD‘ù”{`£ÿ,2­ Ç4ËÊ $L˜·v‰”~~é<¹Ð.C?õqãŽ0¸ï⬾*ù•‹_´WäöºQåèTŸN{ýýï_ó‚þ`¥p¾¤Ý0êÙ$ÿák^žÑÁh‹&17ÏaeL¼Íì´¨Àw1ð#ƒ­Žë¤1Ñ AA ±@N¬„j€™‹7ô©s[3Fh²ËŽ'J âÂâ·¿ýuõ²c©—Ÿ©^†x ¾ÓŽXp`,Ê…®$fažÑ_Ðò{ðÁÍ3ÊWêâUê›êþ“^I´…ËäI¥Ó/ëƒt\vpètÉoG»Ù úmÚ):ã6ù}Vrâë DÊ:QŒ§P¼£Á/V(Ð$(6&‘Ž-4¥:5ŽðJëvZðF1²MWäâ/ù Êùʹ}úÓ CX]Ó-p„ËA°òM–|¥|ú™è=ÓP K$¤«cÉ:ã@\é)ç™x"Tr"M@’s`"ЉãvÐg8)O wC NCÛß )—òóž?½·õk¨ãQ|ÿ×Þ7ðñ+am¤4¢â'-?à‰Ë'þÈ×°¯¶òÐÓ¬pð$_ðök+ùÔù–ü§YCf'%àø•ò>è1.ÓAZh/tóÞß|€ü¦´ŽÓ³Ÿð)Ž_¤ zœwÁ©•u§üå7ÍàÎ_¤5/ûé#è<5ÎRNø¢šjhôó£ýhCW»5t«KãÒK/ÍoŒ=ºñï|§¡ ¡NFrÞtÚmHáh¨Sküà?¨ÓŒ7Îþ~ýÚú©mömLœy}ýë_—®¤îXNëtÿôOÿÔÐjuC+¶ÍLäÓ€ÒyPC©jüë¿þ«áØØfø6ö?(;Ü{ï½ Ç¼ñÃþÐðRÔý”‚kú)³®rtu Ut#_Y¿Ôg‘ååœ6mšë‚ôԗ믽ÝO}œ«ñÐC5î»ï>ÑöxC+<¦‹2ÍšuoCWÐ5ôÁµÆ/ùKËiwÞy§UÞÐuž ]ýÙ¸þúëkº¤0GEFtF ¡AÓx³ÞvÙe‚xõ N)d.~ ò_ýêWæ«&?5ŸðHùlh¥ª¡‰@ãúÿ¹¾±çž{:/êŒÞ¥;/hk´ÚtáùÓ"Û’k·á>ýƒmŒ9Êøþë¿~Ü¢e¼å-oq´iØÐ‡ª]]]–¯$.eAJ·yöáØi4¡i :ÜþèS²Íõ·lÓn¥hÕø¯¼ò*óS;Ýd|t€·!Ű1sæÌº·;¶¡oJ8ýöÛïàç™gžayzðÁ‡ü\¼ø“ /}ôQ‡=ðÀƒ®wêŸrm¿ÝnîWú¤ѧ ‡À™Ï;Ñv«†>úfÜšL5n¹å–†vT~ÐA¹aŒ‘2çºÍþfêÔ©†¡þçþ‡q~ðƒtØð¡ÛHVÔÇx¬D–áIi Ó¹¢†" K𫝾F8þ³‘í}ÔÈm£o(<Ô¢žÖÚí…ÿÐüýïßõÓÛØ ‹Rj=6è&$çƒ,Œ=Ö~íŒ5²ÿÊW¾â~–qàÉ?<é~¾‘ž16À3øB‘wö³Œmô«_ùêWųè´˜âþÅ2¡vFÙS¢Úí0Žƒ9¤ñ-É6é/¸à³Óm` 64‰ò;í•:Géû4‘q8õ¢?zìÏzÑ­EŽ7n|cà ÷Zû‹üãµ¼çX“òA;Ò¤©ñë_ÿºA{¦ŒZ°kl§±ÏþSçîT®jÿ¯ò}±u¬ZVRÊ6†Þ§~Ÿ`¬+©ý‘-SÐC˜âëñưès¥="%¬N'™°.‰|gʨÂé‹lè‰%Îý”âk™Ž¶Œ|…Þ ½Ä'LÈ@À7qB'ýˆå£<›8#<ûäÎ~ÒzÚ(å__çôFš(¿aß̳™ôAsàÖì•‚&ñ<ùeXë»Â s-à†. \¯né¥4Iqfƒ %Š4ü€GùŽ<Ìôâ¯qªã@± RûóTº`yž %ñ‚ AA9#¾(ø—ž\£Œb–ýÁÀf™•gVP¬ O9ŒÜÂa^Öú7@ÆG^ÐR 3ðÝÒF…žÂKà‹°ÛnÑñ^uÕUÙ~ߺü[n¨_ûÚ×Z¬Ã0”@hä=‚V6¹hìÐ7hÐÐFþ7ßü3'ÇÙgŸeø;ï¼³:.òA1ou `©X£Pk•¤® ó¦”k—Ò™Ðᠰ˼¤ &4äÑsÀF9ûìg£¥Ó££Õj•éŸlÖ»áê©Hd$Ê6ðÉcílX ~Ö¬YŽÓ–°;q­¨nSÖ£^y'½V~ýÔ¡ÏDÝ ¾ˆÛ}÷P¬TþGçO:”}ôË~”—¬O”@âwA±×¿ìþýd°ÆQ7ŸúÔ§6iÒ$?ÓŽQí‡>”žV—²Ós" J…>åôÁkÚœø!YGÞ£MÐ)"ßÑñĤ ešv¥Ÿ:ïQ£št0iÄiE¾¦M+û.ƒ#ô‡úGÎ…žŽpä‡ò!ÓÚ=¢«º¢ º/ŠAg„ †—­“BðŸ2£\ô”5Â/U;GGL ²^n¼ñÆžäl¥'@N´g\Ù÷„LÁÃèGTÈ«u0×—z·jgÉ꬧ÓÊoãMÇg<ÙÎú·1è£ @LvÉ£9èÔ ú™Ì—Å ”h­Kj\È ­N+ æuÓS™Eñ@‘!/}¸®!sã¤Îþ-û!`fΜيڼÌ> 7Üúž‡q“6&´QÉ¢3¤ÉV(ÿLŠzÒ²{Nbdj¢ è{Œ{¼”v-À™¹Îºê«E˘eM~'´ƬSW¤ü—þމ“˜VGÛ†”µ§²F_—)íê4dJROâè+ZýÿzºìSRööØ}Oú?ü;ý½§7´ÂÝ3©$ˆ×j¯á¾ô¥/Õ0?ýéO†Ìè|Eôîr ¥ ö×0¤±ÓŽ1±$M:p›¶í5Úr×^N¨‡žåŒÅ‰5½Ž ðQ_ß6^pÓ× kðŽwú–ž®gý¯Û‹Y¤e’€ƒOÙ¯ç˜I¿çqŸòã/í¸½ôgŸ}v-ƒ,¢o¬&§LÆÅœ]]]΃ñ˜w¿û=u;uDùC9ˆG®¿[Ûã²Ôê^­¿ ]\wÝuÆeš´ÂÓú:“ô4!׋Qÿoò+ZÝ>› .ù Óюܮܪý¸-ÝÌaÈc‹h*ïÍ×ìë Œp¹P]À+Ç¥m‡ë(êÉí—÷z¼ZL“èËÖ †0è)Oç Ξ´D|”‡¾!û›e†ÎÄ—c©q½Sï&òŠ2„NÜ ‹2 ôædÉx˜Ë ^ã6NìäêéTÓ]"ýžÈ”ÎØ © P|Úãz‹42*Èõ[Gƒdû­êÔ“´å‰c›íöÿó*)ÙÕé§Ÿî0l#¸ÿêÁ‡´¶Ÿ 8âð#ªÃ?Ì~ùòç-·Þ¢/ÊN«^”i ¦ kÖ`“ÎöèPm¥.4>­ù©•bÜ¡zyÍËê:±‹3ª<·§OŸnü˜gi2à²>'3œ j'd}̵Sè¯\Sïo~ó›%/7UoûÛÕW”ùŸÎÄè)8ÇÈìó¨/~ñ‹Õ¹çžkÓh„î™3g¹}`‹Œr˜qšÌá³”Y›P"ëä¾O¼®Mßt†£Õy\Ñ‚dÃ[ߦC½òÿmÆ‚9´H™Õýüº?2O¹Ÿxâ ›~@;íáàƒ2/0)C´ójó¨ï~/¾.½xÑó&ÓAÌihïî'ˆ@®»tI@Ø»÷S_fB´m²O…#íDÙ‹_¬vAã04¶ùÈjš%|¶oàROpÙ °JÙò2ÄfdKšÖôÑ8ÜʘÂX‡ùÈG>ò‘êâ‹/®ûxˆìÓgr1c m™z;\cçªè—Þõ®w¹]œzê©ê79Ô;¨6ùÔ¬û LW1¯;à€ ;{öõ|3¡¿ø6Àç¿B7Úâq¤.€<”»YöˆAç©‚Ê ½c÷4uZ%QL˜×ȧù[·zÙsϽªK.ù—º_ׂÇ׋ÆW푙ŋC&ZÇSúL}èGùn ý5åÛ{ï½ÜŽè¯gÞýîw»Ÿ{ÛÛÞ&SÓu2ËÝÆæeRDmF7~ü8Éïs’ßÓþ ù-ù=x+ù]*ó¾ïI~µp%¤gÅÎG†£%Ÿ2Ì<2Ki[rèT“_ù)’—f·…“DNàõâ1ʼV”â2ã¥>“yL“³2L$Žw¢ Jy6ñj­P±8ž¢Ó¯!Ž4N’’w8ñĨò]O†ï‚<¡q*ÆSƒGR"‹³·–?ð+"”Y­ëDæ1ˆ™DÌfʬɳž2+I¿f±½Ð>f=eÆQÃ6g(žÙxõ¿ÌŽ˜™xœÕzà'¯œÝµ†1kÊÙu¤gG ¶_˜=œÌŒ7qåÌ-éhÁé™­àÊJ|à"]Àêd½gO±%;ÌÚ‚&h6-äkú3¯&ßš+A‘6àÊ,¬žõQÒ6ÓQÃÛ­Yª*WJskXÂæ…o~ó›ˆÃ«þÔ¬¶º¯j “4¹"„?WHdÛëíAàY•eå'›^­HÇJó«å‡ÙMº»ï¾ÛyÈîÐ+̇^ó$œœÆe‡aÒ¤XÝ÷ Þõœu+ lKé3î'ž>/\¸°q衇9LƒªV3tË;wXm¥%ýl‰³%›»lGãtø¬6IÉELSH7N¦]]±zôdÙE œÝ|¡úí[M˜Œ‹?ðOÊS¯4$-¬žæ*3;$ ϪŸ:Ì™6C;WÑf%ÏðL?¿+¹NÓ )ìõŠ'»1¹2& ¤¡·ç%—\Òm^¦É ;OÒ>ÍÝ4ɬù£´qùå—¿&þéÓmH ©y•«dííÞòO“‚¤ >¥“ÒÙ+îa2• üÞ É¶ïv2Eÿ¥+]k“˜ÖÕJÊ÷ÿø½âM¾øÏ_´ùMÒÁ®q˜Gi"ãú½m¬ðÞ} vªbE3x×ÞÞîôŸùÌg,{à•-vãóŸÿÂkÒnú%Vcq¬¦žxâ‰N“u&Nœè0ú#)¥†eGSŠÛkâÿ¬Ú&fF8)¦5_²­Ž+ÿ:WP—‘v0’W½=1ƒ’Âd¼üÁì8LŒà}X˜³–~Þïø©?ý´Ê–ãRôåý¼#¥CçÆÃÊo:Lïz£¡5ŒŽ\Æ\'ã¢>cW&ÃZå/w›2ŽçP™Çé«áÆ1uênyó:M ã ;L8ê ”w—ÝL¯ jx‚ÓþË¿\R×UšÅÀ ñ†ñKãeŽcgÙ]\ïä.%õf–î#5“_¶áÃ;¼Þ¥€Z©û餫ç“>$ù¥É^½K ~`#ZÓœ}ÖÙußvÝuÍ]ƒ„ѵÈZ¥º#L aæf‘=w̲¾kYp_WÕ;gÊÔF ZN™ø0ÇÄ’'ïàÌ>‡¾ùížáXͿ馛ë]©¤oÄðâyÿÚ4yIGÛþä'?Ù­¼™.Ÿì,±”.wRáåAÞÙÙIüÿ’_v>ØU€vëln?©ã… E;ß:U¶3ÂHO¯ŠËßO»lÍ4¥=º ŒQÝ߯ÁáqªŒOÓšG3M—WÑK¾Î¿Ð¦r4ËB~`cLéäµ¢i’à-<>•êÆrlÙ‰‹ceSp|HmÆ„‚OZÎ'Œ1Êþ4ÓѪeÝé¢l7iÒdý&™¯ÙÙꀣãˆÏ ‹iÓ§;<ív'M % ÛW[¶¤cR‡™.ïœ%È OˆtøÞ{¿®1±cR·:Õj¼Ÿ A;>ÆË úo|Ãi’/nS’éܾÉ1òrßl¯´¿˜iwÁ8~üã/õ˜´“´òƒ'“'O±¤\cn•&W_üϵ¬"§Z-t:ä³Oi_ªkpåàˆâý1aÈæ_ð Yc…¶VÑEŸ¯M‚ü’®ÑšTáǾ\;ö'ä9[A¼Ê+­Ôè†+Û5c} ý|*¿ÒæsRŽ\§9ƒtN¼ —ògû§¶Nš‰âyBs¶_&nçwžÃÓž:i¶û`ªáÒ¤at1N«æuý_~yœ1@ž§¨n²Â;Òêb€ºßâ¬@º+¯¼Òø;:˜@µ“˜8k÷²–ƒ<ßÄBÄ„ ¥îÕ¨~h'izÁ¹§Tör¢OàgGiÿ*Ó­„ɶFyèé#]çJƒ¼ìóº}Lß¾ûì[+ž,€hgÓá´s­Ÿ ?ãuý½·ßݧ—>\á´Æ+ò¢¼ôÖ·ÆB 8»õ’wú úVÒðƒò¤žLµÓÝ8äiÏñ8ÇÕžò;X&äßo¿ýšò+ÜôwI~ÑSúÓ”X Ý0ô·Ô…¥àe.òšÇ‹öú’ÒÒÞ ¾&,icc9´.§0Ázl¢SO~F>u_ ¬û夅öžz¬òjÕ ^~ôå¤<Ü·L„Îñ¥ÏwY€'-?&<)_À×r¥ükšÐI)‡Ò¤NâE%Ñ<+qÄ; Çtµ¼£vŸdÁM0‰šÄõó5ÞYÄ…3[àÍ”îÌH\ÍIEx)“•~pNôx¶Vç¡p˜Daô³™!¤ æÆ*[øoašÊDãlV6L‹_Àeš|F9“þš&ò%¯’Ÿ…É~ʵuÚ­*‚²˜~`¡ú”—„ \4®‰£‘¢Ø |¥ÓÝÌ÷½ïÃh»ßðtp̬9@ïMÛM:ÛT(Pþ´•n#°(Þ<[WˆÉO§ùN'’Jpf ÇÏ ÏSN9¥ž ,XÐ¥Ž´Ýá˜U?J(éàHË¥?oþx ÃRi«]qº´ã§CÃÞ ¥|Wup¤v\Lb¾æ0WhºÍ«£P­ikÞ°„£±†Üfc³ÌÕÊlìŠ`sŸŠ«h¤¥ó·,¨^“Ϭ^f=4Ðq²“ ¹ Åaœ6pô†ƒj…EŒ0™ÐhbÁ€«F<[W¿ó+ºÅM*gXõNÇ®éð°+Ư-x+9øùåàríµ?Ìd^-$.êŽiÑM[ -"Ó)û´~ù®§`ØÙHE$•æTÒr`?tQÿø‘g°2¹ãÐT¬8Tî—·ýÒñ ^tÒyhíõR&»ºbwdáÂ…µ2’“äÁm§ÈsN®Ž?þøzÐ&]Ú£8B‡îK÷î^ XñÎoô˜Ñ!kÙ™â•òs[OÞˆVàsÂ…?wü6lØØàP>a ¶” ¶ }pËï¬zO‘òM+×éP ‹‰Pï M÷Íq†Ï•Xþ•+W‹àÒuõ„>@»ÍºMY; (ŠO:¸4 ÛDÒÁWæ;µ Ð7¤bÅâ†Ì–Œ#'Öô›ÔgGÀ;_ì’-\»{ìJ{lLf9órÛzF#M¦âƒ2´‡Lõï߯ž\Ð~ÓåÄ¥‰ü=Þe¹EÆÕi.‚©p(ø\Œ`b“rž+À»H©fl®)QŸ9±$]ºßÞq‡aY¸Ñ-@ö3á"=—<¤ûÚ×.uXN– ˜œÜ±Òœ€LsÙe±#F¾Lº}ð[—8p€–vÝûàú‚—3Lš}¤ûJ¯˜öSßö×Lšã;ƒLxpЙ»FYÊ’òŸ}DÆM›6½^ˆaRÃaXàe¨§x+y…Êç 7Üà0&ú¾…ëS–-cë«M˜™TõiÑPºPà‚ç¹ñj€!C×cr»u½\fº˜ä »È=ÊåÑj!À8]Ûøò—¾ì4ôº]È~àáze¦ºeá?;céòòˆl'¯)¿â)mYøùõ*¿ÚÅ!ŽÔCt…Ç µ·)á =ˆ'¿P€sḺ¤©Gµèl9ö8]¶Åćn…_z•Æ&ÿh«)«¤qzê-àòiæi%Ü0àÊ1-ð'}^øªÇ¾Œ6%Ócfâï9F²c¼‰±³™¿p¸ME98¸ ÍŽ÷B{¼ÿH›´F82zfÒ¤÷¨/U‹íŸeÕ*¯ "¼¸è—üRÌ‹ì—àÈ®(­˜¨_Œ–ø ¨ꉋ4 '¯ˆO@ò•“ §“ù/êx2„)OZ)ø•&l¸@€ÕÓÓ%^ùƒ ¿_„+îEq”pÍü”Î顺)[àr0‰ƒÀx[÷°Àᅧ'xyçn\óˆ(уý­Vnm ˜“m‰ñã¸ßýª«®´-ùO<é+ ¹;XÆÁ’V:4mXì&q7üô†Úv™û¶ÕÉ;\7›øMìzqêHýä”óJ—ìâã¬wk`Ó•h|D&lú58×öé¸ÂãøèWÚá6êŽéd#ý¬®“RU½õ­ou8ö«ŸùÌöSFlU7ËÀ²ó1±ÌC®+7øº3€¹ P"§ÓÄÅOlF¹CŸ²§Ý½” Çi ¨¯ˆ'õNß>½#îô3OóýÔøóš: ˜ÕšÕk%ZºJNõ„„©€®7}P9*­òùlnq2Óò;åÍ›9s ¡[üööŽš_œÝÀ©T]ë£/1~”A«ÄŽ;üˆÃk›aÎ"à4¸Œdtõe|@ƒ‡ã°û”¢f¿?‘)œVƒüÔŠ»ìŽóúÀWl_ØN#Cê C&:;u ëâlœ×ñ%ÿ£ô4±äMiwæV”ÁíC9s¥í0Ùœjj:¤TøI`Óû‰ó>á÷ÝD§¶ÀMCÊšVôŘ>¾.oùòmÇ 0gÒñ#Ü+¶uík»pާ˦[aœVØ”×"_g'ÅW¼§¬š6ëãqСγnwóæÏw]J‰õµ“6l2Žä+ò†{Ç;Þa[müRfyøìÈš—òŒDH#\p-9'oTíqᜂ&'xe«þt¥­|_ï7gÎ\Ë WfÛ ßC~–-[b{sÒ\{íµ¾Š?çZtóìÙçé|ÃèšoÄusîÌ b¸Š·Ç{êúÀh#´1ýÁ }t̼S½kb¦fÁëŽö™|ÔsÊIž­Y¶ty5kn ¬L—%RÒW„ÌR&ý2: OíÖÉ6{‘mò¹V÷Áï÷õŠ´ïñ²Sxd.h‡Gé´óc¯JG õ3º [²OµFxpØåC»V_e?>Øa|€,ƽ6³PN‘‡&*“òufFädõhÉôŒ-8®J†oÐK{‡çnêo²q&(Ï{ð¥n<”‚mŠQò> sãE»Óý~þñêŸ8Ïm„|çÌ™í:\«ó›6Åx×G·Ìý´Q±tî+5®%%Yöš¤üÐn¬Ï¯| 'øÌ~Ý–äkS¤äZh£Úa\ÐÔWªþàmæÞ{géŒÚL’Ú®}ÆŒcìçÃg:UˆêÎ3ƒùèºõxߌ L.ò”nÒDù3“,?![;£þ·Ž‹ñW‡nuívîh+uŽŒïÄ4t†f¸¾€ûÜç>W÷?ñxõÙÏ}ÖýÏ3ÏÌöÇÝyÎWHTÝD±FWtsžÇ˳O~ÃAopy!û©uõ*¿„·ôÔ/ø«]¶,¾KÓ”ßuµü/[¶T:¢ò‹qÁâäT>Cž8 ™õdZÌ\ørfb‹¾~¢\Ô¢ª‰\\£öáѧěBœ„˜üÉg<ä¯6À™Qñ™@^CžSæK»‡& ² ÁÁ4!é58Gë õ&|NÆI€hv<ÁÄ”p¿ZW,ù¹_¬"²O1OÁ­ÿ“ëòšwÉ_½HdHF —ˆ$>âÌHŒ)…Ùñ&1*r9Lb8@\@ÙSÒeP¦/]‡^[i(錫‰#˜.Ì” ጓÌüÊŸÈ%…¹†‘'Ȉênk*žxpè‡ ®ÆM°ÒE%K” , ìÀ#.ð8­B:*“ À6º3|±”"œVLýäÊï‡u¨²0‚GfÒG5©1tºäÓj³Ó>úØ£ÐxAXR`xò.m9N«K~2!]¤ýÛo¿e¡˜{ …X ÌÓ.< Ú9èvuÅÄCÛÔRÜãà- ïÿj…ö¶Ûn«nׇ¹PLQø466Ӧޅgð`Èg^ç<¥cc2“N«iR¢†i¢ñ¬ƒÚÛÛýä0ó¬Y1(p`±…p}cAʈŠŽVVìO\€„®fâ‹IšV¶ÄÓ8Ô©B§å@oÞÍâˆãpbúuŽÂat¾üãŸì§ƒÙ¢=•~Íþ‹|UUGG‡óÈ¡A"×­_gÅìÙ约•+?Áû+Ç­ZµZé@0ŒŽ>¿M=ñr¤UUÃnN&"þ²di±”~Ü5×\[Ý}÷=V4³^y2á“EaàI“I„ÑQêU†˜Ëi CÖüä 8Šd:ÿÞ÷ûû*í,TÒÝùµ,iÈÈôq{ËXÊ/“5”Ld!•`Ía`öÉS&WËï_.þ¼&¬-®ÔåÃiÕßOò¿êÊ«¬œÊÃað^“×ÀÁUWR*$ ´%Ú똱cü¨œˆ“(ùÏmé(ºYWóæuÖmƒ×I¹ùæ›Ü®eÞæò/kR‹Ηj™¼/_ÿ«ê4Í¡ÄWtqÀúõ|+-|^0}ªû·oúp¸Ìt,$\€¼«¼–icâøoæÓŸò^”ÉN²“¾ÇÝüL¼©¿ìcQ´¹£ZÖ®}Ùùã£\›t˜ƒÐôô‘2ÓQŸ©oŠèRÚ3‡¢™èww¯V±­PFôeû!ö!]“©Põ´&œô/ͯý*Âãê«ã§ì!á1Ž¥´› %Yk~ά۟†ï“Ì-¨´ãYMš4ɱŒI?ýéÿÚÏÄe?¾$œã9ɯ>Åääe)8´”a\*aø¹9E¦"•šòjÇ$"YVYY]{VÊ2¿t²ÿô„ ™;Hj Á( Ð#ÕV’Å ò€“w½²LÝ\xÁ…gPÂÍÊGÖ9¨áý yf½S^”!­øŽJ@IDAT« ƒ“øsÅ9¹ÒVzõýïÿ úà? ‰FLÀP|P°@Ï—WQ´H¿I+þ÷ßÿ{2µC^d¾ã›1PÄX5Æí±Çîþ2&íóšÈâÀƒƒf~îW C\ ù3¥– YÞä‘ +Ð÷κ×xPY-fðîÀ!#v<õ¶V“QøÀ )7δ:äaùŠe*gܺÔ×£¢ÅÇñøHÓ7Þà_ÂËNÂ(øø |€m…àÓ-ÒÄ7mÚ!uЬEH&W½´Fma{OØ)d ù|ßûÞç Ö׿~©q𸣴Z.yC[µRñ ì¶äŽ p¬X2ÑfrŒcwèÔSO1O¸ñDç€,÷9A×Õ¤ú*ôö. }‹«µã·qã:ßœb$úÃmHôaærí dœ£—âA_‹L†Œ7wŒ™LÆÁú¨ÜG?ú÷Aííí¾Aé§œâ]VPàà­¶ø-”ƒYmÙ¸¥zèáæ.uËG³h¯î‚Ž:ÞDò–áùŒ[€ØéÅqk®¡þ(ÊúZy®àelQ´O}«Þ±4©y%o3KçÑúÇíS;p¸ÇÌðŽ~v¯ïºë.M¦G”-tðÂû -xÍ.N?}Œr¡ûD™VVüÒé›#1¡r?Ø$¤Wš„>òPjû›ð‰Ï¼i¾Ô¾ì« ­é¯£·öuk» M¾Óÿr;Ž ¿Ç¬Rçô#Zú &Á¸Z˜øÝ=¿³Ÿñc»Û-äS;Eb]ôW¹ÊÿÑGíú3;Øìôáî¸ãÉïGkùå6¥“O>õ5äw½w+¶liÓÍ[Ý妽¨GêÃÑÍÌwÆræñ¥E5èºãŽßÚÏ„— =+Ù¹²=_Ên—]Æëk‘sħ6›FïÉ'Ÿòê2ñÔë5×\£/ÖþF«l?­dë/LJã꼉'Ù쇄íu­" 5“A”tL¢Ý! ù‹´3œ²TÓžü‚¼ôÕnP(íí,+¤MtõâK/V»íº›¿Ò‰Ùqg%-xR&Ôg•ö!{ T!_¹ûiji£V£4Àá0 Ð!iËò{öÙgyåö¿~ø£jñ ±Óf`ý ³²>Þa3j¬¾&;ÈægË´òÌŠ.ñСC¬pfÜ8)ÅrLÒšÊÔÑŠJ°&Ð/X˜ÄøAyhýš¤i¢…ÓÙœº 2‰¾ë&z¼^wûƒRÎ N¿½íÏj1×:zåÓô$[“Ö=RÏÛÊ|ˆ‰´l•¥ˆl©¿Þš:ý\L¾\Ǩ‹T–C­\yY:VÜ^ye`G;è'?ùo]Q| ËÍùâ‹¿PxâßUì8üïÿÞ ¯0WËôLb¶1VýÌ+ÐŽŒòÝ+_d2Ò§ºì²oj§éT¯ÒV0=|æOÏT÷üîO~‘û… »­Ÿ²7÷s½&6ôÁ,¼¨I6«ñRÅ”UŽi€©?¤Nù$.ê%X6ºÕMPÙa›9s¦•YÌÅp‡rpu¿v¼fÍšå+buÖ Z¨>¡Õ‘Žò°² ÏX̱iÛyE]G䫇+Uj²67ã‘AË¡À©ã_ÿê7NHÛyLØÖgú[óè.3Ä8ĠȺä·bÕš¬‡ŸxBܸqãõöög¿ÍnšwÝÀåþŸÛymñBÇKÚbÕ[eÿMœ1›ñÄ …©Å™¾–w¼JÕwø&hk8tèWÆÄ€Qú@ÔLÒ‹/ê ¥Dª¨¬ú{‘r*¢˜`¦˜.ûþ#<²î/˜0ݬ¯6ãæÍëLÐ×|¦n Yç˜Ã¤—Ýs]–°•ü²ëpÿý÷Z~Ct±ÂVòK?jùÕõÓèôEÔc–±.)V°Pr`U{›Íiâ]YÔ‹Bü΃¶m®Éð¶¾ ÀÈzÁï|ˆr !Æ튼rL&F0&øp[W±hh’! ^4^úüú~è´Îh¸(›Ç@É®$+¹Å£dNEë @`•ÔÊÇéô<JNñæ·âù@j3NE¢Ò™Ñà’@ü‘i§†iÄdGfÆ %g9OL(°]!ÀTË€GÇ)ÇŸgl ª`{—/‘i–Óaà2 \¼he†‚.âÁWh'ôå“<›øä.Š W“è8E’@V^å¤JH.Ì™H“4¨'÷â\t¾‘‚·ÚÑXÒwomãçJöþð¤aè$BPyÁ$Ê¡WWO½ÓqÜŸ÷¯c7ž+ô *¾§ì,Q®ÙjÏÕ&ëµ…rႹP&:¦¡2]X²t YÔJ4ƒŠ¾´ë0`ùä:îÀô“UC>»¯h7€ÕUŠŽ:в˜ÿZâ1#aEÇ 0åÞ[EéÃì…eN±]¦lÙ¸µ¾+[z}^ƒÃá‡^+¾<òÈÃVpYuu>®Wg#V›Ãzán¯½dR&¹"‰Í9'í‰}öØ©¨/xnÃvÐVõóº£]U.'¾Š§9!cCR ×յЫðÔwX3ùÛ´)L=PØqóæùªx(zÙ%À…â»—ïhçîÌFq»øâ‹mc˪øo{§”•;eV1°ª½½£š??ðbç TEÍ ³D!RzXñpYÀ¹´U›U¹C‡ FÁŽf•;MK;IÝ„üÖúG1úÏD"¹ÏŽBÿþ!ãÈþavÖÕÕeeþç?¿Õf1úЇL;r¶¿&¼Ü5Ι ̱yô‘êš«¯Ö=ÕÏO‡Ê½D¼eË–ªcÒA™1×buìE};`‚&2L¦pÈ¢n²…=BQlyv”[г_‹:ÊöŽ,å. õßu‹•¿àw`‰¿p*9ZáÒäŸo  逶å)LÊJŸÛŸ˜”*½õé;0×b7rîÜ9uœnÈÒÖÿ~6³˜4i¢Û0(ïð…_:äг–,ÜGŠŸ tY¹Ð!ÄjbGGõ±ܦ?”Ÿ69mÚôêœsÎQý̵]:²‰Y"¦UË—Ó¶b"K=ÛX%mh"¶ÆmvT0áºæš«=áf×Ývõïä“ßaÛiÌý¨ú#](Pïté¾¾•²R€5R,e^C(C©;{! x̸¦w”QÆ&^•5«µc!§K<áž1c†ß‘LáøžwýÿùϳÍgG0ãÊó[Lª6H¤.ÜŸ«ˆ•EòBœ•Ÿ­þˆI˜|«ÁìA±üóìgЉ1´™"Æ™|k¦Oy̘ %9Ó*Uò×@Íôé£lÔ„7~|L¦ñçb LÐ æ`¸tV®"Ôý ý;a²‘§o¤Mq‹þÂmƒÊQš×rPÍ?“+ø‚½[Ðl^~w¯n‰{y)UXd'(/¦®¸Œw®ÊØúËgörìÁ„9öXhþâ_ê@·y¬¤­2ñÄ1þ±€¸ú¯ßø‡ЂÓl·UÆOä7ûQôÆü¥ÒçÍ\•Ãå*å l°¾¡^“¯ãDL2<vÜêÀŒŒgÊeö¿Á¿cœ®ÝV¤W.ÂCVx/l¥A¶È5øJ~ ‹Ð”Þô«  TïàѿГ[hih—$u9— ‚õKì%Ã:¿ SñNO¬h39à\ ˆô oMar&‚” Òñ+"‚ W_I蘨xî›±S­¹3RH&4èˆ Æ9‚9ôJ%»ˆf’pP`Ç7Ó%±M|ÂXh3™hºE êJzJ~öBN𮌠´î˜:£tÍö© ’€½ákºˆˆw%vÖäåpþèg >ãoA帘x¡½cƒ™Ê«ê8R]/i? |ƒfçÆjºÀ­(Ÿu%Ûb ̸cßxl=0/•BÃ`‡Ã|‚Ɖ«¾”2\áj~K°ôæÿìðÂEhªˆ-Yò‚ì6'×+¡(Ñ¿þõ¯œBV`¦NÝ£ŽG1ž5ë^Ç£¨á¨{êÏܦLéÌ&ø‰ùCtÞð$ÞP²C™](Þ—¼ŠUUííÆÀ ǃûîã>(é§ÝP?Lü´˜äP^tQÕ9~u®&i˜½1Q¦žá¿#<Â;‹LØfÿy¶Ï‹0iEùGAÆ,îÁ}º`Ǻ Ž5Rõ¶¯m˜¡~„¶ÏGá0Éþ SKLõÕß@ÎCyéã]‡ÊQþäjSú¡„ß@MØ×ÙDUVä ÓG&ÝÈ. õÍå üpðäÓŸþ´wìn— õþëG×í)2ÒÄN}nÃÆ~îŸð·ŠGòÚŠ¥p±CFŸ“«Æ­ bÂÖ8( c2Å"P“:ξÞþÐ?Ó3Pzþ’¿Òš0=oW­Xˆ‚>\šRBýi¸f"Â7:ø¯ÿc|bx0hCãf`À!uj-jɶ׿ÐJ™¡]^À)QM× «’ˆ²Õ× ×ŽüÙ~ã!ÖøÃHT÷R®‘x@¿“ý*8þV—cüg‡z¥vªic(ð!¿ßõeL8hËäÏ!m~8vÌÎ?ÿ|™Cþ±ÒÍl•nr8; |P ³Òèÿ¨Ÿç"Æ.ˆYèz ž7~„s¼^s"Ü𠿉_œŒzÉô¯H¨àBZ]ïTJÝ7„$Ëùx@(º@ÚÃËîäe¿')‚T{jæ 0OI]ú™<Á†ÔF<òt$ÊâH‰x<“ä Ìd ¼xð¢Ãžv.íF *!B 0¢©(€8"Œ5Þ>˜®·¦sb%txÀA– ©§“ƒ[ÿŒ½®°ð‹|å1ŒÒQ‘8OFôJïÉ„€H8âȉÜUáÈ™ t3HN êç8Âõ#%‚×qÂcR1Ì`D (b…ˆú92«1è0“M‘OAï4Š#584†Ë¯òr(,kù ”:fV;œ•T­~ˆ\©‚&\®&ò•ÐÜIXT¾$‰Í)[Ýi{œŠ$‡vÒ†’Á/¨eÊ&J…Ô_‡•u— À›Ž{S­D³ZÛIø±Ç{ì1õV%JßÌ™¿Ó--œsX)\¬Ð¨$úÏ ”3 L8e„Í#»iÁmÙæ*ÉGŒ.Åcq…‚’ «Â¬ãÂŽš]XÝÌE;W-çK ÁÅ!¸+>»°ùT]‹÷Æ •ò±È°y ¦îìw:Êøb±£Lþbß™öüµ<*þ‘õ£CeІΜqà›Á’ÕûT8sâ†Òu§Vîq˜ ÷ð¥š:Þq}Õxñ"xsÅ*.+’(ýÈõˆÒ…rïø¢UrV'¿õ­oIiù®ëóùçµã¢Æ@Ÿ­î<‹¬¹+ü¢úà^”)rÒÆ©G‚úðæÎãwQy^«ƒ¢ÁE£T`rýÁv»çíGØLÿY+P8dƒ‰'寄ƒ&@ú •~ŸÓÙ–¯úËÒL¦hìÖpF€ß±Ç« À­ÕYg¥°—5yió'ÊÈV|È?“¿©õ$0‹+´a²›´[ÆÝ¯¨lù$A"“:ê~­„;pµs/¬7˜,üf/ì‰ ¥å¶ ò“XH Gtûá‹Ï€ò²ú•¯|ÅÊr&ß|EY¦¿À\ŽÅÚ²}Õ•WkQ`¢¾Z~»“d[c¥—6ÚêH»ì¼¯’ ¿ÓO?CöÈGY!F6Q0¨Úmy?Dç ¸QŒó6W\qE+ºÚÏG¹qh½òÄô†¯¿÷ô÷úKÂÔ=‹#L©/d€“ú*][ê//]»›5ҿѳhQœ5"ù¹ç~ÈX.ºèB™J½¡êèh¯8è©;ðÝQ^Ú%²N|ˉú"ì—´+}‹—?ì à|öAu¤?n¥&A¬€¯^-Y”Ë]Ç•ZÉCÄyV…ø~LrÜað†Ü"[HD³ï#¦§KyEþBdÑ Šsò‡3¨ç“ôd‹CþÓ5ñBàG‚š8{A86äg•–ÜãV¯P4Ù…a\dG ©–¢efÝž¥(¯Þ]‰wd ,ýU–<Ñ{òJ‘(c7l%Ï‹ü3Þ\­óˆP]CTã»GiNXÓòšTD¤éP§ÎbÃSO=åÀµê;Å8›O¡ü3¦­òeí~ýUŸ¿è³þRüÄI“|öŽöÄ`”ä˜;Þ'¼ù-º¼«:û¬÷Yùggm¡ô}+CyÚå‹ê¥n¡špê5ê:…Ãʾ‹Íâ1} É'¾ËÑC6êhÆLþLg§ó8¦W Zå.ôåaœŸYB£é6½…Önõža¦P‰©kÉ®}‘™G9x'"òЉâH8PÊÏøÐ>þŠú„×[«s¹‰<bqýÈD&._­?%ƒ$3pDtΦ^gGzyëA+ÃU‘Þ°ÆHF‚B‡|ÑÐñAxà ÑÁ?Â30_­ÉL‡ˆRØP¶J‡áp¥6¹¥<¼ð_4—G9JE*¢»;gÀ~+ê\6åbûèt¼ÚæÃÑHõ¥DûsBÀÕØÓZ`$‰dÃòdãÍU¥©ZµË݆T„P®XiÅu´kÓ;ŧ{Òü•I9Äuñü*ÿ’8 7òàòÐÊ·ÓàÖê37±`tˆ> ‚ŒË}”ôE‹› ’¬Š1!À¥2óÈ#±Ë7JÐI§:2E¢‘ê2dV…—ëÜîõÎ+|Ü`‚c6œÊÌŽ Ž E7o·Xí‰^à$N_‚U'&()8&Øï‡ ~Ú@æ¥ãÅ1I„”¦ ìˆVøÏíMmm¥ü/Ö Ñ6IÒé:Üy£Ó±"íù>û¼Î“ŽIêÐÉ›ô(!\KIé.uójÁÝŒ¤®9t;1côG+ °”;ê|œì¡sE{_­ ³ƒKY¢÷M›7hðÒjwôMŠ-mUx-u*:¸˜H0 1©euǤòÖr¨lõë nß¾²ß—mø ™s0qììì¬ôͧÁVxÆŒ£mš†Ò\utLôdžê|ó€çˆ:HÏî’Ê×_ƒßƱ:™‡´™œÎ;ÌŽYø‡$ÃðZÐVÐñ´ÛlÏÔ5“ÇœBhàÒŸ;áƒÝ„€8²P Ñ^ƨm1I/¦,ìŒaÓNº¿Æ±ºÇjÝ1Ç[}ï{ß«w™P20Ùš93lÚsbÚÎ:¿”uNÛÂí6uwµÁ.cð'RBç°a»»ÝüèG?ÔªáqlQ†Ùõk—òIòM¿Ã“ÃΛ4YùÉõ×W“;:¼ ÑŠ—ü‘øùð£ye=è˜Zaò8Uôpf»gv˜ ÐO_¢­ôM”Js¿H¿íÅ• ÷oúKz&eô“ÏÉ^[_Õ5ž]ÚÛ«=´ú='N² ´Ð_¢P1)¹à‚ÏTßÐíDÎf±‚ <²¿rÕ‹6e¢¼ÈNßÁ¨Fh§ƒ~XxàÝ@ñó øÒµ°Ë°üáæ'n„£ïê«~Ã-ù²Ìô&8ÝÀ÷øV‚ø§²†,·Ê~d-Ò´«m#¯bm­Ã€ ÙŽþ&2{mz« âè“Ø9«3Kðn£¸b†Ð J¾ñØê/¼ª!ÒÛ jë@èd&N8E,$i¸ÔW74°Tð'f ”¥»S F%/dkÁMAúâv÷$ã‡x|T‡AÙ† ªK-VUC$“(ñsçΩ>ÿùÏרÙ`a‡~tò$µÕŽvïF0n¿Y“€;ïºCüÏ©xà~/Æ,Ñ"@šì…²+T¥¸®cø§2¢ÁÁ¤‘g€à ¿åDú¢cO<)êqˆ÷:az,9† „Jå(°à׋3вgQAKÕ@?0äLl:½)1èb1.Ôn² 'ÈfRE¾Qâ€hÂF»qÿí?¤þºC´ÑÁG*èvÙM“ÂyšqWeäm!k“Í“ ˜ OÈ1_ÈT?Ãyö ƒåÇ#ßã5ÂôWiƒ(`Jœ™D« ì˜ ñÎß`~©‚€/ КƄ£Pçäþíúo¡s~ñî%Ž{§Á® Ìzú["HJÞyàë²-Ñ© §§SYˆ9p¢ÄÀåàÏ :•;`â– L È¿ðAá™}6$`7iåG_3ôa Aƒ†kpÙÓô±Jœ7¿¬ZùR5rT(ýØC³†›£Ã£8îÈ_¬XÓ/>“3BFG޲Zìšà¸I#W·éô¶”ÃgÛHJ—J+¹(R!]Ö>‡<É“ü˜€$OôaíŠìbpìíÿû¿¯³Ÿ-ßœ€À·œlä*9¼Û¤o ôï7ÐöèÜ´ø…0ÙÀT‡W¯qX5éŠ: "ñ³JžÛèo{Û[êmWb·–¼,;T*f›m8À¶Ô+ɘà–• «Ò º”yáJêg\î€7' ÜÖ„ËÉ\«Œ´N¼–.Y¦ÜeN¦-ÜT¶‘˜%Kk0¸joï°’üœxøÔSOúgÄúƒÒÑEŸ÷ALvPF°QfÀŽË¶ÛŽ)æ:1°[&œ8k…šeÈ>fMê›qÚÛÛÅÛàgòÑÉý‡vÞ‚KhXÙšN‹M&L~òÀöáÏ<óÇjÌ豨Vë G›¥AVQV­\m³&vA˜ltiƒ2ÅÍ0üÒñ] ìÎ'MšhÙ)Aá½æšk*&óæuJûi›ûE'ÉIgrr2ÊÛ ©ܧ5• ÝýFô ^¡,Š7â°ë¶í¶TÎ’‡Ñ’‘åÞ1Ñw$+Ñ£!‡0˜‡»SƒÙÎF¥‰uÊQ£G±Ý|pÝÀ-š¡àe׊ï_àäSY8ЗC»ÝŒ”HÀbŠ\2Yâ¦&2,\ÐG¼ >Wæ;ãwŽ›¦²ïËôñ”„Š9§i•:Ø5À ‰çjÉýž~ªêÔŽ}&y8òÜC„Ow´›7f‹cZÿ˜KÕÛO>Éøé—÷fï¦ÍÕ®ßsÜ £V‰1Ÿ¤I× X7÷tï»[ñþ-þ å‡É9ýh+-]Ú¡{^‹?,Æp¶e“úÇ~z219õ]§š^ÚA«{»d” Ñe÷o´”ß/õ«4˜V°â^üQ»4³uƇ¼Ï×Î}éM7ܨúZ«¼GÙŽºƒ)²{àKüª7UXŒyȤ}VçÐú·Õõ• 3­2㥖ء'åä€K˜ '0±Æ Uû@~h{!ô3ŠPV‘ùò9ÜÏ‚é)óҥ˵K§q_¼$ú3v¯öÂØÅãý ù¥ãû ïÿßû†:Æ4&ÊŸ6mš¯ñ¦ “=¸´eö·EŸ«òPmúPY­Ž¤*)½Àȩ̂ñºCɱ„²NÝÙéy`*Ï;äÒXD&BZÚ’ëŬ3r³soŽ€G2Æáp¼€;ÊCx´eh‚?ò[w޵D™p𥾬Y°ÊÙBr‰ êgðC&@ Ì´0VÄ)nç õ|dBœ™C«‚Ÿ3¯H…ãël(täjþ“ïà+”Ö  pf¼|æ™3Î'Ò qJeô@;DèÈè XJþdó*8ÁŸð.ÿ:Ñ@¸p9üQ¡x`[è:,ò-áÆC°œÉ ¯þŠó&ƒ‡|ä¡\”òì4œGâsúfyM ü®æŒöÄŠû…~ºÚyÂÎN…íùwþÖö±] ©³ˆN#Ï`^2gN˜2 ™²BcîªìC‡÷*!¡¹SÍý7„BÅ5˜y+ON.€UÓ›7=É'ó(0È]|ô%äïØcßX+úyG: üÒ¥Ë<˜iòäIVDP@òV–Ø/º2Ìç¸ãŽ—r+è(Ú(‘(fE׸èA!Ò, ÞIèGá•4òÅ6‡²»R“+æ<(®¸¼~’wv[úöÕª7mN¦NÇDŽ3ˆä™>íîtLè¸í¤¿V¶}W¿BY1d F‘˜ÛÙi8}bÚÅÕ’(¹\šn›á#µüR…]?+Ùúš¤ÏœÄŠ_œ]€¾ÓN{O…Í7.hVÚwßñ}¶vAÔÚv„Í Þõ®wËìgƒÒ6>þ±[ùg0ÇD™C‘5Îò¬]£ûúÕ䢱Ñÿ³ú“E’óÝtVe£4ø­IÈ—±ûm_…2×|‚½a„ßhgE¸ç³àEYκLÙBaˆCèÄD9Ì…‡ž¨þ½cÏr.Ê„œ#aò(ÙÔŠ<Êí°Iww Hc³?3©¦Œ¯å˜@ù™ú×u +·i—ùÉ?þøü¡ ¢9gpÅßÅk¥c°Ê‚Ée‡ÉFÚ3úKžÊ‹¢äê0x€WOðç­Ð Ì ßÞ{ïUó—[JpLÖÉ} +&S¦Lvõ–W¯²(ÿçžûa}1õA ¿ä’KÔé®´â; ¿Ìt*¢ÜœgXüüRO\vÛuªq¢T£xàIV¤q±… Ä ¦W¼¥Ø¡RvúŽ\<ˆ=Ýl$ó׳æÍF¼§¢BÚ5j(ú 7%úÅà²Ñ+ó|”écû˜mLÁÑÙÙiuüžèÑfµ«‰ ?zo¼ñ&Ý->ƶàì^°ÂLJiµ±«ëy™M=_­Ð€ÆÍ$‡s˜R¥KcÕ3­PØ0ÍH…&obGbÍjÝÒ¤ª…gnË(èQÕBI„ÿ‡N‰g¯H~p>úˆ•oüL>^ÿúýñÊF|¨2 èúÜ©BÄ |˜—¤ü¼ó§úœ;i2ÇÁݦ¥­¶Ë;'­|PÝVYýçúL”*>@¸`A—¯Ð}~ñ›±kÌç5©F¦r=®÷B'uÃä^ó§þ‹xváè³â_GÁ ÿ¡/â™ y¿&Nò¬ñnlÁ»Þ+ôëÄÉ“~+Úñ_ õ/•å/ÄsгYÆuòðGù Ù‡v&z/ãF+^Ldá <ê®YðƒüÜ ãÆ«Ž;á8WÝ*™1ÙÀl©9ÞÄj¼ô'7¤¯Œ’òA¸Ú2‰ücÒÞߊùî»ï©~il&¯Ÿ‰‡Ú+ã޶4nœn¼[±´LÄR•Qx#h#LSi]20F7ÙàŽ;þ›ïq‹çDž·ÀáDޝîEé?œS7àV:éûz:t Bi™æ¯ ,¨O\NfðSGéºÓ醿[C—t@­_¿Î(~ø¡º¿à&VØqL\׬}I;Ñë=V¬ÕÎ< ALl×êù²;֪ͲØÈŽ3;¼|ðñÊ+¯ªÎ8ãL+ÿðž]óµº ‹‹#¨>ìµ÷Þ¯ó¸¼í¨Ñª«—•~‰ìúÙ¶ٲ喧‰]æË/¿¼^„cG–se¸˜È¢gáš\h;¨ƒ:&˜¿…ÃD¸‚;‘\Œ#rðŠJž\5×Ϫ–\Ÿ—þ ·z1$äçŸ",sÖ5®‰¥X•C&ÞéB6ã ³V :2ÖePeXtTÑX×tSnÆU—‰pIe3%‘R×Ç&Iƒ'rpvÅÛÌ›È?<ººÎP‡hÌ,Äd@aH 5„åžѤwc, ÊäJó gPèÁ_~àDÒoJCå $\²PH ·ó 7F„ALj:˜FÞE Jƒ1J§ÿÉ$žê KéðƤ'€iakÅß‚€LL ì ”˜rC¢`žF4(L7ÉÕ‰nÖJ©fÔó:ç9qÚ¦ó‚¢ÁGRp( m}°Þ‚O%OÂÛôõS)bÂê!á›ßüfµ—”I·ñq¯¡CôÑ¡ç—YñEI7cäò ]·ø˜¾nÜÞÞaÅ›~ _3ÄaþÃa>\Š•G‚Åä'e sTð—/ß2AØÌ²NÊÍ`Éd„C¸(f8ñåÎ|üýïp8ålHYæ’bEk„vÇ¡¨ç H¶)G.ÉCbÚWõ— ÷”)»ž]Œ4í±,)4v^T9ÇÕü`š¯éâ°‰NEpŠl§8ààäîf»˜Pµœ% üq¯>7Ǭó­MÀ1¢^p ÷ߟý±Š+yUçJG>¡}guöíZ1ß%v'Šý{tT¢ZüÌ{û rgd¹_øJ¤Z‚å×¹Š/ô)ÔŠãxJÍÉÐYgå ”[~v‹éšj¬ˆ±•Ä5t¢ô2ÊÈÐËÚó~¾kís@¼yž—x_üá:ç·÷Úk}ûêk¯µ¶±›nª#'{žéoè\~Õgd-Zx;Ï+éèB@Uâ*ݬ‡ôÞB;€6vÃæäÄÂÄô·Vvúög-ºÎA}G9­Ú‹¼IhsÊ•S÷tô‡oN:©6ÁçhP7zþŠÓШŽvØtÖ?æ{'$éèšG•ÍoAxzUÙ±NË2ßK°µßøpYFjxhK?õžÿüÞá 'Ë(—æ¿é?ÃÿsZ‡é´i!EÓiê¯rüp¼ßÆs—eºžÕQy~½ŽÔôÓäÿÿbuëú’$±ß#Ùœ™ê—qR–®%ÆcÝíÄK? ¢/Ou ›3Ý©*lÏ$ÈÏßüi[:¿øÍú‚7Nò°b ½jõJ&ì®ÁoDz®ö[ Þëå{dWØÞþŒmŽv€nL!î~Õ³ÚŒ¶J+6fìo.®xA•OóÓ¯©|I?$ý*&Þ¶2,õ½x%ð2ÉÓù‚(óxOå KJ Ò5‘ï”aù¥ºr€Eéâä¨òñ˜éThèô·:…^‹µ¨Ñé”úá”úkX¼T3A.Õ™ìŒ2pVéø½+LSH)u>v¿ÏcÉ>RŽò ¦P†ZDe1!s$Y+ R¹iò`åh a**dQ( HT»‹×äªA ‘á;¥O×_J1H£g.²oPKiû #DG¦Œ( £"ÈLÙX‰ÄÉßJø,Û±cõÔ§îG'¾:ÊVÖvÆžýìí™þòÉfG*_ã­„ï½oå°1…'>ñ YÓ}øá‡¯~õ«SèíØ|ücþ&›nL!½+ë\ ØcÏ=xå·qâ–,Yœ»;ûÝ8˜ÊÕLšLÔufmùÚƒYs+gO•ÃsµuvÌtvtÎÄ»VQg§ï÷ÿò¥Ù ¶¦‘Xî]ÖÄBÇÓB<…ÄJfÙ²k‡ãŽûØøa2oj'ixÆv:t­ÃvÀ°¯¡ÖÚ÷Óˆ<>Ͻ IÒ½ ¹:Ug:.½ãc²øÀ™mõ°Aõë sÙ±ûãwg™ÐelÊ;†Ù¥š-ß%gœqšÞq™Å|–øÜÍŒË>ûìÛdwÚi§U_ M^@õwƒÕ >”¢ë§?Ù1ö\~]5¼_Y³éÏ:ðYãlºkóuY™ý¥ûªãPqõú}Ýì½pÖÐ|S+UgHýBr_Ö²ï¾S3À—_^éºå[±ü…Ͱägt<'ÝAß":—­¼çŽäátXÐÑ’<3ká• ŽLµÓl}£sFÙ©­XqÓ°ÃŽ“äéÕ‰Kç¤åñ{ï[•ÍÖÎTÚÀ| ŸnÖwÞyÃ_±ArCÖ-;ko§Cç:}Oå_gØŽÁIüë:ȰÓ×:xè[é|ïà`ÉÙ°vØÔñ¢yÒIÿÜÛ9[ßtsP ëƒÊÎŽéäÿàƒÌ&çÉLÖ1©o¬»ZºX¤R¬|&üþ°=:¿%`ºë,›Ç×´íŸôÄÀiƒÈœ²ïÒ•Õ¼aYo|“õ¶·ýÅøÌ%Eg0s¿Ýv ”—ƒÝ/æø)g9Öõ¥<úû Ù´s¹ÏÈëÏ·MÊ~iä2%–×'ï¹W6µŽe¨u¨«®*ÛÿÎÿرÅ!yÊ»›Ä }կˆt.¹äÒÀÚqwBEgÞpi¥mµf÷3IÒÄöÇæðvA7}éSMz‘×°•:¥³î=Ês±‚,C§Çý²êdÙúhÁé ¼:;ù‡DàÛ–”|€ ÏÍÆâ•³~î4¡g†t” 0¤Ã‰ ^O¯Q¼§`¦Ã@$Ø« ϶¡×èB«´!4D…÷üSq¡Pru™ïN³÷©ÍoŠg´N|é2dçUGV‰ÀX™ÙïÂh#ÊðÝoˆ„ò`10¡ 0¶âãiê(A /M•Èy‰çs€ðë™+  >K„VÔÄw­›f ‡ŽªŠÊØhÙtÑ âýy'®x…R”B'yvÚ gO¸ˆeŸ¢!]3^òØ¥þ*ŠJ‹à>0):âÊ‘5àlå˜|E³/¹(*CÖ<»fý{ßû·,°ÒLG9]«¹›Œ/Yš£(_ËòÿÁ’¾éê+_ùêp—O&&&i ¯£"ömAuÒ÷¤“á1tºþñß2¸Ì'¯ËÒômÀÀfýy|Ô‰·º‰í'r·ÃðÿQGÕÕ+ʵ³áÇlöùÏ.3øÎ(Ó‘GÉfäÍ2]vÙ53ŒV.fg§Á¾ì²ªt>ÀI¯ýëÒ ¹YýcŽyGø©KֲϜ]ÙƒP—;ôú¾ÖÞ™*—mÜAÇÕs´ëUyHŒ6ði—]jÖ}½õç w˜ÈQ“YC‰æn¤µ£çììk^ó^™¾5›6´Óçùº-ÙdÚgÈlu3êÆLËUtžÊd'ϯÌÞ|ó­ä‰Ú|íµWç5n_&ãZû¾¶¼/£ê3Ð{Ñ îºöt3ϸ·Ãuº›˜ØasÐ099™S"\óä'ï•åZ•ïª\£ž.CÙ{¯½ùÔûKÓ`›®}ã¸ç·ûå\7bÞu÷4Ê;æ$gù\FðÃþˆÍ`'3Ó³Q|–?O!R]_Žb=bœ³ioas¨›œÝ_àœÚ]5€2ÙÐ8èÒüñÙü«ßÿ;ÞñN½)7‚ú·ÜoÐ;°Úè9¼=óƒPæ­zSPçô›ßÌwn\½øâêÄä#O†úéÏ~ÆÉP?¡³?A/n£ä9y¦sðÒ÷£d RŸ LlÕu±3Ì,ï–£ÜSéXW(ÃLˇmlËIRßÎʵw_Êäî™zñEæ-€yº/Q;眳ófÕIïï{ßûòAµ=XßmÝîà8ùZsyäö?ó™ÏPçÕ›è)å[®£­q©‰hݾð…áàçœ 0OÙ:‘ÍÉ/e÷¢EW¦~°Y°U‡È·\áä@?™ËNëßÿýûCóVŽåõ «ƒÕ¸„Úæ–ë¼ç±oÊo>¸<òæ›oîc¢Ì<®óp N½èE‡„ö%ÔY»ïþ0·¤ìhCÂÖ9.›;è93ÁñÒà÷:o, ½ïÕÍ0%NDœþh­QYIQæXpÃõ71Q± Gv}8ꨣRÇi‹¿üo9|ösŸÍÿÝvÝ-ß¡¨%°Öó,3¥¬Z¦­ç:èà,—² ó-cÿ’ð¶Û-HYðÁš„tÑ ^ð‚Lîxbœ{Ô<©Ë· ¶wÖU¯Uš8h’þäääøáIóÑT=éÄ íýÓS£il_›ÛgJ¿£Ù¿*¯ÓëÒêw•mí§•sæ­ÒBqíÜiŒò^õý€Ñ£¼pbJHí€1žÿ†„_ŽÊ ŽD½T¯àPö@ajºüòêyK2=_(m:ï’ò'rHä‘¿2 Ù¡¼J\ˆŠ[ºˆ+t‰—ëÌBTHÃE*e:ÁH¬J˜˜ZE4<ÂçĽ^̦…Y1pÊž@SƒH'MŽq½YPä2 ­0åqTeÆ1$™ÈÖÅj8Ò/´¦wè©d&„ƒ†’›ðúœ]”ž#J;«R‘Xó‹(|2EáéÏ)&=ú £Œ:®²äO1ËÞŽÌFÚù±P^vÙåéœÚqv'ýÑG;³ñÃŽð+÷ãŽ;n8ôÐCY>SN;o~óѬ‘äô*Bgî}M_f›™i×ùjÿŽÊÓÕÌ=§ÿà¯ÔV®’ÚÁ»Knn¸í:A‡­,ÈÝÎù‰'žÿªUkÒ1vÃéÂ…yj%Ò;Ùžµý‰O|¹ÞœY× =ìâæ"âó1gœåøà?˜ÐN;î”5÷3éü{JFŸ•œœ©8+¯³cÙݼ¹¦£b§Ew-k™³¼‚Ù&gLþâ/ÞÆ Èÿìà¿rÏ{Þ3üùŸÿy;Ï?ï³CK–,¬³âË—ßD½²NSwÝu×tÒô÷ Ùh×]m̽-ém˜ƒƒþÚ¼/-Y¸p‡aiÖ²²ô¢½í˜˜œÐðWoÿë៿µsÒ@YÞß÷¾¿£Ñý¢ÑuÔ‡w¾óã›OåøøÇ?žNÂòýšñLðšP¡@Xê2å[+7£?ý©Ï²4à¨Ìúeíï°ÔÊŽÏÏ^uÄCH´7‹ãò‚ïϲ¼ÚÎøEõGBú]ØcÂiŸ(¯Þ«mC,²Æ f³l²rIË™gž™NáÃ?|¸” ¶'´==D‘êé£ùh&M|rM_Æ9ë¹ý³`_?üÑùß—³Ôzú…/üƒ Š_üâ?býÀ¦¸ãÿùóEñ;u³©nûí¼3›Ýëüæ2¥§K˜t}Ò)\|³æÄ‘îsŸû|¾œîÞ¿jïdÄk_ûZ½&þá—CyQ–Ü:™ã?ý¤:a­üÝÊæC\úV«,OZs7¨õ¶ûíÿíí÷¾ýÏ©/¬ó|ãþÞ÷üíðµ¯u$ÿpÏQG5¼ý¯Þ>ž¤vÞy?aYëgéφÃòW0`Z'“…¶ÃŸc@qøáœã¢]ÂùÞ÷¾'õ÷×¾öÈô¯»îÚ°3ûRæËøÚºõ‘Î%…iÇP+“¡ôÒïò9ý(žS‡ª7oê )8é̳õ÷šM.Î~›Ö«{¿J":†µfÍ\שpY*« VuêË_ò9¡bONg߸è´^*a=õ*D>£$r~ü™æl ¶KV÷­iÁM¹öWç,q?EÇÊý¾ûîa†s:¥t@w}ðŠ›n¦s;‡ ýO³–ðÀŸ•ŠÐ·{1}…ZçnGáÁTb®ß~ÚÓž:VnT}?GÛ9 °Ã·èª%ÈÀ²#FNn\³ºf˜·å˜Áîüz¨3Ίhgˆ}{²Î¬õÚg Cø¾TlýÍÁ1ÇüuÖÌŸ}öÙYÖãàÀ·#{³YØ™góu'œpBö=ø‘;¾çŸAÂIq ȺððµÎµñ½ñq-¥ ƒ†Üd“ÍØˆu×ðõo|- otΪô†biëP‹ï&PÏg¾nÙëKPÜp G$êú²¬›x;ãÆnׄ»qëM|aUç«k×ÑŸrÊÒ‘»…Ž´'Aè<©ÈoJk4?@IDAT(h÷¾ÁûG?úQfߌwÅš5«2£ï³ÎWÇvþu΂õåJÙsa&}Ü íÒz7q÷À¢E‹²9×4u ûÒ—þQf¬\þrñÅ—äÍŒéê@Ø¥Hæ‡ÞqpæßÎÿÇ>vÜ09¹ù«3»grnã¯ûä'?Åëêgf™”yÀY>Î>ël:פ|˜¾.Ûwß}rªütæ7{î3qùŒEÓÌÂb³6ê{ú`7ÙºöÕ"êK«ª‚sðO˜eǼa™š*ÿ~!óúë¯&'?;ÿ§9‚Ó¯z[î;¿ü†ÓO?ƒt½&j;.;ï¼3Ë㞎nû&¯C˜þtì YøÆÀš Ž£³s®+»µ`t]°:_sÍÒtrÞñŽwdÖÓŽØùçŸOú~Ò Dªþ™XØ“Ë|#å~#;†–;7Y»þßÍþ²šÎ»qûÝí1dóÁ jÖôëÆ4#÷ް ~'ÁSê|ðÿðÑá%/~ ùòô¬÷6½ýšýÞ{ïå"}¹žõËè^ùÊW„~ç&´þ9«½GL¾õ­o¶¤\zØ¡mÆýEi#|ÃøÓŸþ$HñçÎÇÛʽ2‰Po\¢wˆûÂð©O}jè$›ÆÉ£–ŸØÞ­ývèßö¶¿Ìñµ›nº mñöj•Á=+9I²‹x#òo|“Þ’·ÑN²9¹sòɧwmøóùýY&ã~'']¬KŽÿâ—†7yDêõ^ÏwûöµÛ)ŸØ9á힇vɤcKu÷mçõ¼é´<ÿ‚ŸQ_¼{ø oËý‚uù§>õI>|÷ªLà¸ÏÔôKÜ~‘Þ¶lŸ}ž2¾AV~Ûc{×|é·œ¤IG›ðw¿ëoxù¹,}œ˜˜`ïã¼ý=t8ïÇç K9FVXmëD¥}‘žyÀàÄÎ¥” .Óm³Ív´a7Ð&¦6$E¬L žç¬Ç õ¹åÀVOæ47¼&ÿà/è*ÍæÌÃÂzI?’gîR*ºÚÙÊ:};òBÛç‘»“ÖÕåOÅNˆ˜’.§G…ctÉnlÁ°ŧD‘ƒÕÔĵ´l3Då’2á¿¶ï2QÒnÒ/é"¿pàU>IÔ4:!×.ÆîÌÞÏhDÉ0D”‡Aí³Ý1P ¬ÞÀk$ÅÒ•`Š‚Í܉—Ÿòárþà [Nþㇿôù•<D< V~i³¨žÆY:Üõ*w—OrÂI3á ¹ž¾®)”Ô-hÜN3¯™Œ ¯‚îâ4fHZRñ©9õ釯çç2ò¾þ†šÎèëÿí̸|ƃ}ô£ÿ@‡h‡thœyx›µòÊ]|¥gÃÛÝ/~ñølTÉÙ÷.ƒùå/o óÆGŒèôô¥üܼjÏ/tžOÇcîúu ¦&ŠìJ­JíÉNGïк¾½o»êªEaï’÷®Õô»rùò•ÙÇàºÌ8 •è>t¼üÙ‰ÖÞÒv¶¿Ó÷-…ë¼=öýTdÿ6LLLf¦¨Ò ìw/¯kçÍ«õ†v÷¢AÐù5×ýöÛ/v‘žM[nµy6šM°1léÕK†Ï~æ³Ã»Þý®TÎêbåÌv·­vÕ¾º[$}þ _ ±ø‹q9³Ξèê­Š§±†´ ’ªó˜ètîývùÏŽ³¯¬L.Ü~ø%otvètÎÿüõ¦@¿Í<*góȾûþ^:ßÂ9íÛ•™'êòzvêžÃ7 Ž>úèÌòôÙ1_Ýûó¶¶ñ7}­¦ö¿Ðýë^' ã­Yús=i¶ã¬öƒa\‹/Œo\®ºê €Íb+¢û™5·¨s¯ˆK~tÎàû6k·Ýv¥yU^-;¸òç ·ËÕBâØY×Îï|çÏŒø$Ák®¾¶ò°9tï4o¼ñ— ·ÏÛÓÜY-ÓUÞ¾ ð˶½aSoÓ·§•iþ:Ïï}Ï{±é÷2{xõ5×f [{&¬Ð…\/o}©™ùÞÓH|+efN½èVøñWâNúo½Ó'<ؾKÐ8Èõ+·–‰w¾ó,Ú1ƒ2O6ñU¼ËÁjpáò´õÃÅ‹6:õßO:ø „¹DÀ2!]Çy5SVà.й̨oÒîñæ©Í6Û2ƒ ß¾îõ¯ ß’ù›žF–™3gQ®g0@y'6ßÁ¦ÄnëàwžÇ¤l`Óa_!i£Ì¥™È¹ù&ÞnÇÇîá­âŸpbÌ?¦Lo̾£?ü×0±ñÂö¦ÌýµÇ‰;¼ýù7¿ù͵þëå§ò^á¬\u÷0g5KÚfÏ{Õa,=Z™¯8;€wpîÏ™hó¹òšïÌ¿Ý9 õyfêÙÞtÓ-9Aè6ö"Üù…‘¯K9u–/–pÂlo±e9“ü¬'¤óÇ|xn¸Aê}¿Ví$–§ ½œI5y;pðgy¨¥Ê¾¯ïaÈÃÉ–?ýÓ?KýúÖ¿ø¯õ,¢`YêÞÔ]ôZx³ëÀC—2I¬®â­CøÙNº˜NN‚-aÙoÕ_ˆMÆú‚e Ö.^Í©AÚËúnzj˜ƒõ#^ÿ†á’K/N½ißÁ¶Ä^‰éè8·³>=õGÃ[Þò_†|àïc3ëT—ÊöD×ëÓéõÁ•W^ÎòÍžÔG7´rªŽmZú¶Õ‡Ž^v¦Ç~“ :MÑL`ÿ.¨-Øh”›zJg¥lW³ù·çUaÚ®ìH8hÖ¿Ê ÉïÒ–AFì-›œ- X…Ç*\õ7ÚÒ-|"m…a„ðlZË#8Ü•!l e "^â‰êçëˆÕgüå­½¤Sòí>É4Ò—vø«Cו»èá"~ú[3ÿ¦ h ?æ×¬4Ó‰.c4xo×XQÖæâ•ƒ 4>k ùè¦ŽÑ §‰Ié‚3-\Ô2^¤ó1Χ4b‘„ qpÌÙX g¼\z¸2–H±Ÿ§ ÈpŸG úyêt’ú&¬KÈà/Ãå]p%ƒÙ]?®áìÛ‹™Myõ«_•ŠÄsû]?é ù—¾ôOtÄ6ü¨–„?_T+¡¥K—拨Gq$Ëq¾‘5énøq²3P$ƒýjvëo»`[ô{Í»WÿÎlïYgŸ½ÙcE^ 檦%76pÃø¾Þt  oü ÒW\Naš5¬æìæžÈ®½ôsôžZsç]w¦âõû~Œ«ë`çS=l¬Üí€:³ðQŽû“?ysÖ#Úá»öšë׊©X¤ºx—Þ¸áÖmštÇté¶±ôÙÏ~.35ë¯?y8 ížUÌ–lšŽžu±r´òRŽn[µwçä“OÎ,Ñ?þã§é1ëÄ,Šè9çœË«Í±cgV¯Ê[ 'ÖžišÜ=œüýÓŒ<+Œ2IÛŸËU\ßzæ™g0s;ü¹ÞZ›:ðùú׿–޵3®³´³çÒ›=X‡=¹pat>çœs²¬gCf›î¾{%2Ù`{ööÝù¸Ñ=Ü¿úÕ¯fƒ°okºÍ»ŽÞ•Ëüã̼3Z~ì#ù0šÏ`€¸%rrðè×|YfÄ à¶lˆ} ƒ,xísê©§ÆFsx“å‰"–ßZhWO):úMGÎÛ¹÷«½§œrJ6¼^Çú¿½0—ü`>˜ž¤íÒ/—ó|úÓÿ˜Æß}æ…«—^ O¹`+SûKÙ"Ÿº9ÜÎç)§œLvC Òï¶ïyM;Ùéw†ÌÁŧ?ýéá G‘üæÉ!W_³,ƒÅÞÙ37à®\y'a9]gì\7¿;¨¾‹cñzƒ^¶u‹%®»ªcRŸõY-ë‚ÔÀ¤.™'''ø¸Ø©Ìü—Í”æq;êà[“ž?µ§ƒÐÔŸýìpį³tÖœ!\›NBÊ.WËoqtûï¿ÊÚE]ÌFç“È,SheßPiKëšOüfÊã&oÂw=êë´ÓÓHZèL#ëªÃ?œ7!WOg–ØS¾”¯§ÏïîU Ø Ð¹ ÿÝK¿œå¶9lÝhþtpËß|³xÉ%qúÖwóvs.y¼ØóD/[Nê¸9þc>ñæ7m6É›*óÑr&´œ²ói§×c)]Zë‰5;é7L¬§òñAàî=rÙêôúA>ÖÕÊ·|¹‡0œ™Áò'X®èÀ×É3÷ X_ýïÓ݉~8ø±žÞÁ/äæóVÑvB—A_ôPêU¡Õ”½ÔkNaV5|ù%$5l¡ëv© Ö.Xxèi`cW[‚mǃAû~ x©2òT“ÐÕŸ•‡PU×ëŸrW4ªÿXñ]µÄ—p )«7Û‹þ„¯Ó†˜&ãd‹Bzëxøãozö"<>•ža¯™kÏVߢÅ=•@ÃP@ S±\) ÁÀFθDwÚÀ—aÅCØÆDÏÔ«Ò;á©Ç裒‰#S4åóå ª!@'ž{&¬Ñ*Ê’)ybR-D럆'‚.ÂÇôCÜžÐ&BfìBKPi¶6]œÎ¢DwaTEƖƆ–·‚ŒÀÜÿfeÒñ¸2›\ßÍŒ´œ…k£÷ÜóÉÙT# 7Ølxå¡4ìö¸]ÓɱÃlƒ{9Ú·Ýí°pÇá::?.ÇȇVzb‘Ž÷³j}6»zVðt·Ñ†›Ð¸³L¡ˆÑ¨Ah—¦ •Èü çÑQ¹¥EÖÍ#Ïì¼Ú±ª¼c8ù3xZÉt&%¿ýŽ[ƒp衇eÆ[Ý­¬ÜGàŒK Î:ëÌÀ8k @ž?n‘•%ÄL¥oåÃ6ÚŽæMÃÄÄŽÌz»vy2g|ÿâ ‡ÓN=m8—c,]fe'Îãµá O^2­Î<ó,:Ìßf³Îô^§gq³3¹=þ~YoΙ™r–ÂeE~¿aåÊ»ztî~16ëÏéà™gÍgÚÌSu\jd‡Îå_º7Ñßm·]3à4ÿÝxãò¬ÝwæÇ͸Ý-\¸zÞ’Š3È©äÈ·! Ðúsù@ ߘî6Üp£áÎÛ Âfqgµ¶ä8¼eË®ayÐX;ÿ¬4>Î ž@ããæA—ÙèæmÔ^{=™Ùîi\7H'ØFä¢ /æmÄIÙxãÍhˆggmª’8©G¯„Õßüi¹Üf›­)KæÀÚå““Ék6‚‹/N¾ru饵Wd“M7æÐñYFce>–^U Ð¥àØ)vÀt·Aòýô5àŠn²9Óï̆‰m2ãcjõNL\¯wݰ8A>ô-UwžÑ½pr!ƒ¿‰ =Eìü;XÔmÁIM\ÎWŸýÈ\äçÙôïL #k(SnítìL9 ߣEÝë³9ƒä«› /|á!™õµÐÓèÊ+H£‹/ʦ~é9PréÃË}eÞ¼X?Uý9Åíw¾Çž¬¯-Sß|Ò·¿Ãdz.ákðm3?åØR`;~ïý÷d‡eZ·ÓŽ»0Ëü\N˜Ì›FËŒÇI[¦Ž?þ‹Ùf›ms:šyrº[w¾¹Â<ùÃF“ý~É~îúó8n“aéÒÅAٛ㪟Ê9ò“““´{[¥l:QääÕÙgŸÃ`âœÀí°ÃNòk®ã»žvC^w MæOß%<\æä²ÙMóV|Ûm¶çT¹£òVÔÎëÅt¾ÏdùÏgœ²cgÕ¢ãÀȯE¯;{7„׫^õêagÊÂÄd•GÛ6—0~áódzĶÚgç/Yø~QokVaO^s±šez”ºB9d€3‹ým P‡Q`tQ噪1œ•öíÍý¿R_ø÷½¶gNY_,¡¾¸‚ Å/ù„Pq`㇯cù¡“„é›Xɇ µG˜yêàªqi ˆóçoBßä‡]xc½ívud°)K—.Í’É^ ;19ɶ«S·¤®yë¡6£~•†9ÅßPEI_ ùÃØ±ÞlòU'=œ÷jÕ+¶‹„CÄv:µ/úÚÉûvFRW–JeÁ><Žw3–>ÙO¸ü?©/$e_áF>äåa¾)IgTê­~ŠÑdÌ¿Ý{­6Ý‚Ã|á¸BÿG·óλf´íŸK#û2© A3º…×T»•§n¦!·òæ¹ £^Ná:!àrÚNµPÔ(b¥ þiN@¥~´_b?U¬ú‡N§G :ÂzW®p¹Š§€*ÐëüŠ÷ªlyê²4>ÒqI¸mMMœ—m ¬ÛIšº.H÷ÙV©ƒñæ*o-—Јê&úñ`ÝÐ ™QÐŒ9N_ à6¸­0²JJÕ©*Æó—k„ǯì8ášT>5¿X6b•pÕ ¶Çƒ#’.Œªƒ”°„WáÍóÂV·gŒ¦¡©dò’n#¬º‘Æç—ç@íà:8!^=¨ œUôäU«îN?íôljòµþÞpd–,Øz[Fèձ݊N®ËXî§#b%¦˜ù°³³šË9FÂÎÚB=¿&]øõ•”ûY¦Qñú G©[r&-A®Ìj…ŒÆ±‹Tª‚~N–n­µXKÝòhH<òÒ&΀Úá©N…ˆÙ˜ïÔ)™ 1âãk]N.YÍIVÄÅ_z•z'+ Õäã†=î´ÏzœÖr3KŠàÒ;É.Jî°Ó+Ÿ¸Æî>NÎÙpC:™ hÔ,ë½ —¯ò¸´çzÖ.ª³³dvŠ­¬íôù†%d*f°^Ù™GÜmÊÒ›ù¬%µ3n¼4½{6»3?y£mó“z˜.Égvü5`hª»²×ÚLgtÒ´aвÍÖ€ó˜ 7lN'î6'Ûh»‘5i@Þ½:¯ClŽSv_§DHÌ 4vÃâ•wýº¦¸ÊäëqéÆ!‡oµ¶Ûn»l&}éKÿhpé”3Ãçž{n6g³8¯¶ïºûvÕ¹ €7c}&ºÔúÞn{;Ü71¸¼ë®ÛZ^ÐFðQx\™§=`A匌Ƞ³íò¬Í·ØY=r°Ò@úÊ®þ¦¯{ÖÜ»š°u³l‹˜ÑŒÄfO`åÀT<Á™¡Sˆ&©Øù*bLÖâå[vUvý8.úǺ3¡v¶D:ÐtsÝfô™o,÷=ŸÕ€ÛM·’~76²1×RáE¤òŒüçgGfËÔÌë95ŠÀØNy +>¥Ò†s™)tÉœ"rIè#³KÝ<—ÝÍþ.ªNуÃÑoùS¾/²QÒ“T ­ÇòEóc–vy,Kú[MÝ©sLKËÂw9˜á ÎÞÏ€¥•5 `>¶|[fœ§CKYۚɗçxt¦åßüfÙ0ïÞÊQš·ò¶,}Ú' |ƒ'Ìwøõh6™frC̘ææÅ ómÀ :ô[3Q5›Ù÷Ê{b«î².uyä ×-§wÖ¿Õ[Ö¡ÒT·ÜŠ.Þ´3.>·Þ÷T—~¦½¸Ÿ*wýõ˱‰}ë\ ´þ&pbÁ/á:Á!Õj¿Š—o÷è¸vÞ\¯cÜ\ëDŽû¹\åÛÑ .RÁ(«ËCrE€ßÂY¾);½N‹>¶[ê¤Ñ e›Èä¥ì[MžtÒ9<#e<Êbj²IW\þ¢þŠ(>Õ¼”a (yŠN¬~­ãÿËI$λhå,¿%=Ãÿ¶ÛnÖ™9/ŸdÔußûÞ)Á²“él±ëýn cL,Ïì—Ž¤›N©,rü)at`tU ›Ì )¿éÓ%³_0óA ¦Oþ”œtçÓÖ•yKÿ¤V„!ghOøeW¾ü›žÆÅš!±ù  •,úÛøš¡k+‘ t_µÚ‘uÝ£òÍàíEßPI€A~³*CS€ƒžxó¡[g– MU¤Bj/ mÒ×Mè&¼˜È<“™ªÛo¿‹4¸UÈTXF´¡¶&c·“2z¤ª:j+óä!ó%ù„%È´‚†pëàgÑ8i"7¦Ù©ó ³CåšÍ)I¤Œ˜h)VºE.ljCm¨ic¾Ð¶>WþÃâ+ƒñŒa6o"Vð[¼ûÈ' ÜKÛm®î•,sD†4¸§Ó­ ÐT*#=}‰Å$ Û¹ëW?¿+ sso?5gñâ% ›Ï,ÒŠ‹á7'K”–²ŒM.6à™1£Qñ-ƒtz^ejù53ñÅ[žþpˆ©øê·öŒÙ™_Ê«éèG­Íì¬Ø¹°±Á¥/}ЃÉDm®ìZÔ¹òoy,¬m“ö@rDôÉ|Ïö©8Ó£‘E†¼YиBl'2"?NiܼâìåѶ–;aä9â×0ë§è>´òÒy„#áv`º>PâAýW1(fô™¼V¥S= n£Dy¶ú…ã%K—ä9ù˜òä‰/÷1ÐÓy6¹ËæV­v`þ±Cˆ þÌagÇÅŽŒùKYîÿ†À¤wã‰ÙóÖÏû#:LXƒmRÉŒ1æ“G„þÿhy²ž`i¤6H9 åã_^„ë\ ìDoÁLg÷ØdMgPñ¾¥¬úÄåƒòï&[÷µNwCêeò3Ÿ9Q`™¨2lþs/{È„µPà@-¾Ê[I´Ê¢wi¥½`FW_"·n¶<½êü='ì’/ 5kíÙ¬»¿ƒ´K=H MÐù^ƒî:í£ŒÊnÞªöÂoëX×T™¬Ž§öV.x³¯™Ûˆi}«]Lon)ËømÈÀ©| œ —:YÜÂÛØª/hÏl£­§(‹–×*çÔè! Ó[Y%$)}õŒ—ú3è§îY :¶ \´ŒèO^ _8¬o-h3é¯+zåW)S”MŠW"#û¿ŠçY£t} ERÃFøÜ1EÃ/Ýј`ÄßÒ2tà \Œ2-¶ø…ª´îÅÆ…þQ IxR·ªa±5B¹á-ºú±&‘_*~.nø…PÑÓ5»‡‡Ò_/~1É÷Ê:½­é dœýü¢'/§!åšè.HnÊPÈEX qïÚ(Ôg'¨F‚±Eò0@…©â ÙèhŒ†ßíЄ!”Bb`N *yj”Fr—"rOUXF\ ¯¢+Oðª*¦Œ"}ÉS†”Ÿ?p âL£Ò0 °¦Gƒ¢ˆÀ·9¢"™ b•HøŠ~‹¥,·X ^qèK²¬F ×ÓÝyç­ÌsªŠè€I¡rí³:Ða&N]}À–W~$± °5k#¥VèÐ+(ö·±“ ?þ‹2ÔUjZIçÁt°ÁÐ8é©‚ÆL¥h”ñU©éWNÉVöGÒî1UAZI˜ÆVLž "NU`eÉTæ¢è‚+]ÓKzEWŸÿqÀTƒá,©±÷zû'ß°ø X6A:Tɬ\ï³ñÒŒ0R餀¥™/M3p%Y¸ëbîFàOaD·Ò‰â¦žüU &í%o5«òSy¿W*$µ½²`|tÕ±E“ŒrñpÉxö—ïZ4 òÍL;q&£Ìžßé…BDðaó‰¡ákZã[ X bLKµPÿkñ0:˜:O6Ò–6Ø‹]•°Y4âé|nãD÷‘gmÊ›­°­F¸Ò€ØÊ›o½¬7´á ÐŒÐÐBßà$ê·ää¡2 e $å ?Õðþ8:-¾A½‹åOzÂø¶ÃïqÆüφ³Îýq6Eº¬c:®Jvòqí Áe3šÓÓȺ“ŸDãÔ¿Ó2Þ8ߨE`ü:ùÎïì)U?ÿÅ…9õÅe]Yj… ]‡Õ¼5|âãwÏRÑË®¸"ûzzœt§LêôreÀ¦BqÖÚÐ|MЉ2Ïh á4ßñœ¼Ç ˜ž³+íÛSâ–U ‚-?а2!/6¡G,3Y"¼âˆZe§dRN+½¢Jd#ÐI›/`9¡K"*ß<ülŠtñÅüÇÏùðŸ'…1`oòÖ½2.Ý»S³ØŠï À&ù¥\gõu`à1”ËX“Y{äP;ìÆy¤tnåˆÛ;Ûƒÿm³`AÑ¥óïPq=Nׄõ¿8{sŠÕæà‡þ²†ÝU»&T>ˆBÔzÀL‚ü­?–¨¼OO%¼2DòO"ä<&¯ðh[^®å;SL°”ÊçÂV]c8„×õþCp NÆäý¦‡ø„wVÂsíß«çäå&gX௺TzÖFA¸9Ÿ›-ºPa\°Q!x–`›,ÁQöð*R £ø5¾FHç]Ú…´üK{¤þú36MP Å!uJ¹ Ѫ;Cc&L›°ªÁ"C?È¡]ðʳ¸Å_^qtrkF­êφ²ÚÀ4VŠÞÆ1»Q‘7DR‡fß@;8‹~ÒÂ…}`rŒ&8´F¹­¿œˆdbÍÁ®ê9°íu¼Õ?“@ñ7®ò…°2Tˆ†ç³4Á+¯öi‘¥`ƒrhq­ %* O>1.LlsÊ–Nˆ… ׸AŸúD `¥iÈÔ_Iahã!á»HÆ”ØøD—ˆ@!Õ¬Žðà3 ®b´ÄH!·ÍÊ?Ó„uù㬨JŠï½„7&rD–w±§=Òá,”Š{º>‘ƒ(e)'Œ¶­§*Pâ r ¯–×â7¯„K§«¬ÄT+A1’°ð*Z=ÈËY±éo¼`êõlË#¡ÈERù‰h ty+a2ÿݰ¦\FÆ ¾=—MŠ„éá¢acº®.¥O )7!AhaikÏržxøÙRÝK¸6ä”Nü‘£a¥4*‹yF¸‘Q<$Øó_ðÜabbB/‚¯É}bb!yü.ÞÂÊ·IaùÆ¥ì 'õŠn™ÊçæÑ.z5ÖÚÑ4h „‘DÏ!ÉżÝ*Ud÷í[‰ FøZ†*´ŒÒÆTƒñe oôRiãçíœy1Æ€¡ò“zU(ô:SÈH?W}6<%›°¥÷ÎØh+¯˜ISxà"«Ê-}žFÑÀ4XÀ*[`¥Xº×Û qÅœî¤+ Â¸Õ GdJ¥hìQb;ƿݟRù!¼[o=ì³÷“3Ã~+ç—;“îÚê[ˆÛarbxê¾OIœoO®zÒŸ@g~íáÇ?ùÙp‡›3ÛÛƒ‡Êû 7]»¾ÖðŽªõô;è:ž¯…Ð5?k îßÚ˜ÿOê¾tØ7Vð•l-nçßÁ‚xûì½Ç6nŸ £Îþ{jÛjäü%û[o5ìÇ—³7ŒÁ€ÿÍ6Ý$T¯¸rQ6_:øx¨Œ‚}mkø)k¹^NÌCþš#Í-ïÉc°ù§ri² UþÌ•':zž±}ì•@óš„ )ØN£—杖 .d#XÒ†tŠnòiªQäÿQ×¢`ˆî–è•¶³ “¸Hhœ¿f«†®8‚ŽõŽŸõP:©%`«Ûq!¢Xa”½áBtÓ*‹Ævú½Ž4¥ToGy0R§–Ò[/Ò[h.ß eJÝŠU‰Uõ@Kcà“fÐ ©àkéšG/y úG.žÓŸ è†–À£ú†£ÜáÒx7¿¤tE[Fa’礛œý·½Àƒh`úW¶¬ºW€’öú©»éU{ÂsHÊHBÐá9*”8îxªMÁ—z”»$åÉ_&@­Ëå¡;¢4ÅÏ%÷qâÚ¾ònÑ+HI„&±ENüNC¾:e-aͧ:e‰`yf Pz5‚[Ú³4dnø(Ò-(Òa4”áüÌ©Âòƒ&¢—¡L E×Ti,Íž„…§—+ [Ù€ ±¢&¿ ë¸-¾Ó M±í‹C!V‡<ñl|ËHÆJZYºË,‚xÉTõ†wn!±V6Ó&‚¨º‡ÞªàÊhtåÊ[†Í6YÀ±a·1ûsûp)úÁNh}6Y6¦Œ­RÈÔKÙ¦90KGE>ѱ ÔG Ÿ´©.™4ŠŽ1à !}•VØéÁACⓊcÖ2Ê ±UqYxÃS˜"Ü -z範¦SG`C•Ó8%©üBöò‘g;¨•z<È!4M‡Ã¸ €?¶1Œÿ²½á:˜5oè({·³þ \øü$äq %àS®ÕIš\¼•Üî1É“ Sxi`„1.eÖÆzª•ÎÎͲe˲$ÈYV]ffÙðíþŒ²¥jð'32‡퟈F;˜ .¡à©6Áwº]Ô;hÉh!Ù°¹Ì´áTq!Ö*ÊÐ:ÜJäQ ÜòU¥¿Ï•ÆæIÓÛ†¢§Y*ðЖwÓ-™d‡+o:@£–^(šÈ%‹OÚ©¤æÚô !Yãªa€F7[xˆ…ƒ¶A¡5å-æÀ¸´LÀN ož§äªr‡ äRl€—a=H€ÇÖ™´Mhôñ(^ÌGž¢µߟxö³žÉÎ5Ã|>ªç¹æôœá;|ˆè’K/ÏG}ÙK9¦t³ÌÜ?óÏNüÖ·‡{ØØüÔßÛ'ñûqÆü©|LÊÁ‚õYÓí‰0vØ÷ÚsaÏ=žD=½’ÓO8†ÍÎçþøÇùË–í‚§~úðï§Ÿ™ï·¼äE/và;$ÚÄuö¹Ã™Lè˜_ÿ¸Ý†ž¹?kä+ìû”½µG@_›Í”¯älõ­9™Æ%B<óÃ)?øÑðÃSOvçÛî_¹Ö²MÒ«:â73ªIZسÞ÷„ìwóˆ@É ÅlLÓ K®¬ÌSÙÀ|̳¹Ù¬a^ÆŸúú¯W½É{-ß™«RwVxó7î–Щ >ÌÓæÃÖü®…aãª<ÞŒ/¾Á×_`Ÿ¸¢)ß‚->²Ñ•½xð9 V™éð†WݦÄ-®!‡—8ÝÅ_m\‚ÏøÃOy£y±#BÕh¤%@N¡¬M¬ã℞»ºÃOQºS~!À1í 4ZI¡Ã³t©ô’®?\ÒAôËV>—R¨«,_3¢’²Èg„Ž:µ…µ­ôQ–’­@ÞÄП}b☸J÷)ˆ ýü¢¤®4FW›+¦¿´$:íøyœR“>]ÑT.aT€i° µÔÓH`‚o¾3ÌGä”,.ñ’´m„Ïj;|k—‹iYª!ŠTy)õÓp]â“Ôy,†R8;øºžY3ëUøeT L:1Á¬çŒ¦TN§r-.ìÅixf¼Æ"<àVÉÄ]¦ª4U)Py“10g¬Þø@'•Oè- ÄþÀ+}Gµfvy§Ò‘f$è‰0È'ä­ WXDàRùÍL$Mù"o 'L%!¥&ÏÝwùmqîŽ:êh^ïÍ×€_Æ«ß94ëåsæÎJ‰£*¡yRv{ÄI‡šA&²Ä„žY!ð@ć'vèã/êãßC]³”¤££Ké´[F13Ú!&%í+–ñ"ø,õâI0VqÕ6EÏ{$ J| <ÆW¥G¸öUèz‹-äYüê^üF¾ÈÔÁ¥kÒIK̼I~„~“øŒ:J†Jß’;:[:gZç¹Â:ÏÌ($ÏÈHžÜµG0ñ…(Tšž]À¤³ú%\œ¢þð|ß­(D2`TG®iÌDÇW¼Ÿ\š<üïöi eÛná)í¤Û!{f¨dMtéV§¯¿ÎS"ÖNüæ·†çü>µÏðŽcÞE¾žÍ›€ëXúÆl½f“–¸Ú!D`f®b¸…­—Q(pˆÄ#¸ò±Ä OšÒ*yòdH\Uø6Ò“ŒñøG0ÓÑò+a¢§ yP›´´ñQ*sð€K^•±åÍr ކ_ÈyÝî‚ß—yRW9¹ò´ü™È-=øU¾Pæ6k+âÒ9 ¼ü:µò‡ä埾²3·8íR4J?ý%hÇÃR˜SKSÍAÀ£ü³3¬~Îä;;nݰ¯ãÄá#ÿ븜?þ><÷ó‹/dpà à¸r8öýÌÒgþÏûéùhÕ/.¼ˆÁwÊøØJ:΄«Ÿ§½ì¸ÃB:ô ùŠë/†¿ùÛcó-ç=÷àañ’%ÃÛþúœ‰~Õðd ¿¸äòáÏ;8ðÿò¯ÿ{xßûÿçðÓó/žÆþ]õKî/xþóò•Ôÿ¯ '|å«õ;çœ÷Óáå/}É0Þç>ý™á/ÿªè>uß}†9ÚY\ß ÿ’ãV]¶ä² G˦ÓÓJ•”ÇÓó]…UŽLý>-­Mñ 3¿˜§+ŸhÐdm Ùò±¾´³– Ë™ù˲Ò~A7Œ) Éd@z˜<ÀãQòS¥%¬xž‚3OW^¯²¤ ’HùP†‚®,®, ªE<ð“gØWt.”‘Í)gŠ{“qÔHÄ,ͽv<î{Agl{ˆ¯vÀÚÈ:!Vxö²-#ƒì%•c“«,“‰«AAÕ“¥¥RŒP™0)ÛÇŠíòJ_-¤­ Æ«NÝ›€>ñg«*,ö; EõÕÏM_ÕË%w… ‰d>ð±sØ7dU'ð^ÌSçBS:¡ÍÁõED«páµ!òEp¡~yÓŒò—L5‰"ñøO»ƒìÏ?\¥tÑ×Zt@HìÌÁº´¿`)OéPòûvÁg ›+`¥~³m£U+1à”ÁC„„—IéóPœ—#ãXR¢B"t *fþÊ0ÄÅÓq+ާ˜Ê{%Ä%Á³‘_Ѿ\$‚tW\4p& E·(šf’ ¼Nãj,*1]âHó ŽtÔØ,÷hZhUáÉÌèÝJªºÓ¥¶A_¿úlš{)Y"aÐÄT⨠!:m[Ý å±¯3‹#+WpfîŠ[ì4•›5s.øDvý•A>QM”©¸ˆÑ TuÒ{zDäkКÀsáGG@ƒªô¾0ºX\{É·ƸŽÀ\RüÚW=uÊ´clJº$¹Ú 2…ò)XÑ´iÙµqo¶–¦´ÕQèãŠÐ§ˆ*ÎØrÒ.hÂë3&¾›…Ã_Ö]»¢›Ä•ñ ú'zñšIcÑUXb‹RñMž ¦¶ ^¥f ¸ºGTèTžíù¥çEx…9°ü‡mÐäןµyIÙàQö`ãeåŽi¬ ¸È›´“p/zûl€zvÈ¢Qb³¢;3{özY§þ„8—9œÉïñ¡ÕQ !BÕŸ[)Ý@å=Ó$‘ë+œ²‹h<#Ð(·åR±"±õjç!iŸ¤ ¸^Ú€«”*·&D1ˆM'^ÝSî$íàQoYê‡_H 'ž¶%‹€TÌ\¹5‰eÜD¨Ê— G"ÚÆ›´à/=É.ºizh¸¶®¹GŠOx"¼.,¸qÊUþ†Ñ¹©CòÇHçò˨²‡:K·hgy •›3ÊÕ¦õ(º¦.kþïÊW¿oà+⟠ã¼ÉÆ›d-ý9?>o8`ÿg ÍŸÇ™íe&Þ¯…ßÎRO|ÒoRl8,œØ.oìÈßÂR›Í6߃tèŠPº¹ºm«‹|„âŽP [B‘_I¬ˆ’÷“»à‘ed+.Â#êÌŸ•×0-c/Aøñj8”±’•p1œ·f[¨”4âðçbc¾‘]9}õK؆P;`eQÒ}à<ðâç@Øë|x@Æn?£F{7ÚÞ,kVßÇòŠØ<fké|ùã䙽¬A+À±A—‰{ýGºnGcµO TúšÄœ!‚vQŽ@„ኚ|S0£Ü!ÒâxCixaJG<(y“B!L¥õ¨³Ü½”×àA'e;¶2Z7)È×?]—+"T™S/E&´äg˜ùüÔ½g2·–@IDATJdÙ”^Õ =WR£ô[C§Œ‚Ž7b5kÐäÈ]È.áFi¾kºD:m4âMá´L4ÎN§£:e ¢÷(]]¿ËtœÝ¿è¢‹y4sØ‚e>vÜ7£Óî¹ó«lžÄlü˘]Ý¿&nûéùçÿüﲩv| ý¦›V ›0Hp¯Uu¬Isö§ÜÃ××ywÃïU‹Û°6ÓMù€!ñóÎ;/øs‰›Ë€.byÛÿxø­Î=ïgÓ8±Ç= Ê¡=×á €Â;ƒeF{ì¾kNñY¸í‚XÂÈÞ{í™ÀäÄÄðpݼì2 K/»ŒAÌí” _Ôé?}öÌw¿¡AI×Ê3¤©=š–졚ÌhÇf¦c‹«$5O^øÉF4¸düæ“Þ1¬¶Á0ò3.ÝÐ| jŒ–åð fã!õÎ\z7‘§^våÑõ!¸å§!âñKþYàåN–ýOð¡/5(ouR›XÅ7¬‰Wš,ÛŒüÄZFuˆ¬ÕÂWUÙ*Ü|o½í÷¶  kyS†Â3.ŽöÃä‘qÈWèx‹pi5å-Zò°þ0Æú¢;‰…WBÑ£è QqÆüÓÄDWàé#hkIJ^ò©xÖÓ°üé' ­‚Á›v‘»{ãÔ[>ÀTJ­I„ ·‘‘:’~YÓµBàޙܓ¬ÒU*½ôqÂ/\d`ÛÜÓ£d0Ö8y ¡Fʧ¿B€ç!jµÐh.8 Eˆë‘§äª¤ïü̃ê'`é*™jÏKŽ~U†’CÒòlÄ£°¸æó©GoË9œˆµÐH5W}f%"A‚¹†ƒVˆ˜Ê>Ò÷Y¤©Y!;Ò:¯ËO¥´cæè‘¡s ~ Š €¹‹”ÏQVÍuö8ã/¹c"„2NÍð+@Ë_™WðS¨’6€vŒÓ¸=³A:•ÁÄ( —©È~«­ ×¾âÁ‰Ù²_._‘éä|ïè/O±t1C,d+N~þÉGºÂWAï&)í|ú¦d‰Üy&Hg†Ñ¾õ„Ìf¾¢¨œbF<±TàõWwÜL)pÒ0Ôó¥»\ÉÈ‘-)P\Ò)Ö –i’ˆü©<µQQòVy¬Â§ò O¤ 7ΨÄ~®5R¹+ŸÜñ&¯pãå ¶åš *.-6p•O„±£LzTM6©*W1V®¬¥¼e0!:GIʼn§g*¯VÀ4Ä&…!æ+ÃB)•ºøþL3Ãø…žaÊn~0Ì8…Av[¥ÀÈ£ê ÓÅÆ}å=«Úb15¯:ëhS¹ [Kkê rÈe3IB?4õû³à±C*MÊ`B0J­@B&ü†’8lÝ|íÚô i³=ÎÈ¡£'ED±|{ÀrƒK£Axl™€?U7gÞQŠvÓk¹Ícü%CòOƒK®Hç£× B›·JŸº‹L(¶­Š½^®›UšÊ‘]u j•éê„-‰ÀPàŸŽ†é­íuá,dRFòWPZ< Ò7HYkY RY†ÂG"’CD×é»^}ŽI¶~Õ¢EÙwâf]?–¸ÓN;p’ÚÒaWî³×]wxï±¶§ÃýŒýž:<ë€grêÏ¥ìØ þ¥W_“€ åÕ–v¾oç” wÚ1:ÝÈ©=nÒu  †nôUGÏî·s'=Àítúoåmœ$tÑ¥WÏ?ø9Ù;àÉ>Ò\ÌéæÌžÍ2¢ëófBÙO;ýŒáéû=m¸òÊ«†?xÉ‘Ãk_õâo<àéÃ5×.¶Ûv›L ]Îö88°½hIöÕT3Où‘Ï¼ÙÆ¯«ºÕ2Òêb³º¤sƒ«|Ôê #1/˜òçckÇ,£Ä'_Y&B³½Y0Ÿ„fÕ£ù޼Æ|&aó54„%Ü[#˜pòŸò&ž|SV}¨LÕ_¡ByIÑ©«&½Ô ’µ®C÷БY‘Og¯º[Ñ67Ô‘%¹!¬ÑŒ-ÑײX’gCÊÚ-”i à¿éb9Óuº”u“1‘Ÿíc€;ï†LÉZõª2Š'õ´’øxŽÌa˸8Ý)³a¸Ð’K{ŽŒ½@š‚åj®ûÁ›d¯a0iY¿t}ÌKMýä¯<ÅsÊg~’Qð«tÇ¯ìæµüïª?©ÓK}e€’Wé(ö”nÒò¹xˆZ \”§èÇ’áIˆtDL\ù³1ñY0B©[AZwÙd$!1âáfÊÚÊ~ƒ®ì“|h=W¾R>bå@8„rÓhAòI'›p˜ x¨Ü¨»’€(=õ u!’€É=qVÍØ(xð¤m!n cX¾XXÆ.ÊJ‰ {+ŸTOù ìKèèÍ/6Ì‘+Ôz„þ6çi>ž¸óço9*Çy~ñ„¯ Oc“ï«{å°'÷œøýÓò5ìUlþ½å4Û2 ÆM7ß üœØfmö[å îvø,Ø:o–³ßçí·Û6uõ2–òÜ îÄöÛ¥CåU‹²FkN!Ú}׆«|¼ü%¿?<~÷Ç gžuöpvt)ÒS8ýçZ:÷óxsð 6üΟ?øÙÿ÷ Ûm·{öͦC_ñÒáÅl&ö#K»0ñ¨è«¯Y–%I†iÛßÄŽÓÓÁN¤¿œŠãÝ´ÔacsCòmÒØühª|˜ºÕ6#ùÄ0Àæ¹—!ËMÊ®y;xpž…†ßh§-‘™5äk;ƒU>à!?âÂïõ G×e$Æb«\®6#e€0ƒ”¸Ê<,§Y¬!ÚÛRi |zsá‘rë i*š‰ë”–~ˆék?Ÿùõ`žŒ õ¦s‚Z¨vK(BikùczùÚ)vL(iD)õ(žyÔðŒ] ލS—ª£BØ´j¨‘1@:Ü­ƒ Sü™À«\“´ob$ͺÞ•y:þ<Ũ·Ÿ•hÂLñ’°Ü ·ŽÞ~¬§a=ïÅ|q­o£ õ'ÓÛXéšÖ=Ö{kSGžÂ›™Ôš¦ È‘Mtàò×è•Ùpæ9¸ÔCe‡êo2ÂÄx#·„KH|H@ÉÃÈ¢«Ä ï‡ßÌ Jâ ZÝëå®åCÃ}ËAÄÄk ½Áe”QììäµHE¦fSE±Ëü¦®Sè>ÉZ3o®V jpåg¢FmœçÈ|äT€újéZ}» Ah)¥q47ú¤Â2¬BŠ 6ØVNâ…s4¢&sFW9‘ÀŽ(N ¾ T×nÏ‘h Â.—Ìš]·Ðl‰!­. ̺Î!a–S”lòÐ’ÊÉ¥œaVˆÀUÃ]ÒdPa‚S:gÙMQ­ˆPPòâêO+È!QÑųå‘àÄ@DF !u—~VC,{ÝùÅßôóM¸¢haÊæ ’òSXˆø¯ ³4å sÖãÁtêI§À'ØØx"±0h·Ä"¼iQÀÂHC>òm±’J‡¯%duæ¸äüÈX¸–•¤_h¨Âç_¤Jƒ–¼µÿ ôª¼‡„Óð“ÿ‚~:zJO[$¯H[Mz˜rä¡x«Š¿†ïݼîd¹ÍšÓÀ MtÊ]è芪ôŠošé”É„XÆË²*Ûë‹*› ê5ó_”’çÍw¡Uù%$=äl¹/^ OI«œ3z&AAµ@ÒÈ ËTç_½L;* ¨š|eœ<ˆOÚ¦3+‰S¢Õ©LÁM*º~5¤‡©“ð\cëó¸Ï‰7ݺ,¯_vm²_1Jf7Eë"_|„GþN¿xc‰†#¬rˆ/¬·”¦â†äÉÑŽâ¹ZZ„ºµÎ~–t4¹»vÊ"½ù{ûìãegÍš5¼ûoÏ›uÖ™5|ãÄoqÜæÃ%—]Îô=‡£Þðúá°W¾|˜7oîp*§ê,f#ºÒ_Æ›e¼1p;F•°0ùçö;ïÎ×y¿íö;Ói÷ «‹—,áw¥ã?›Ù|ãWrêÕigœ=ö–7g€1oÞ¼áô3ÎNg?ÀœÙs† ~þsö%쟂Vó•ì{YªtþdÒç?õDh(—6*9ÃÐÔn|¹á*Ï s—¼ÎÒ¡«Yhô¡mLiFÿJŽ@4¤ÃK\øÇ!äE„¸Âïe®þÇÜ5®Ê¹JÕí§<§nRÏN³hyµî/(쥼‚›fm¶Ñ/i/¸Du¥ê0‚¼âͰ_AüˆQßm¡eôã Wø&C`«ÑVBF…T>‚É]Z&oñÜ +° \ˆÐËŒüð–ö-i0ÅÃ0CÔ¯¼š·n¦X<ôvºúÓB£á‘šI €‹ØE¹R&g®½~Ës2iÆÁ %d=K¤\ ìK²Ž|6˜v˜0C1,‚„øÚ_ƒ'K€è-Ö ´FŠŒfŽÊU‰”:Õ¡1Á¢¡äèJƒ?e(•M>M]é§q*ÔWÿ†°yZ…H}šþe`‰v‘”vЋ—‰°Ò©ARóK·¢O¹|’”üø®Ø<•bôµ%áµCs*é¬'ÁÚ¤d‘He†Ø¢XD'±R‰¨"`I¡ä®Oâ{ë™ú÷x(½Bn$W¸i+â§ð‹±VêNe¾`J —ɳӗtMOe—¿Îøâ^~å–»ñW“4yµK clá]dlϋتƒn1Fí®7O°0U}V¼¥“:TÈQ¹Z…ÿáe¯|EuV™­n(ÆY<¢sÑ’«‡?{ó‘Yó‘ãþŸáß^äóL?ĵ喛³ÿŽÌšï½ç“X׿v–þ,»þÆa‹-6c“íªÈæ·æ³ÎÞ€©iá+—]µhq-7¢³î üê:ÿ™ø×fýó,äp)’v±c.½Ÿü¤¬ÕwðqÅUµwÀ8—=õÿ[±ÁwéÒ«‡ËYò³ƒåZ¹rÇ{Îæ4£'&u.øù…Ãõ,;r#±'þ¬"~öìu©òÍ+=¡ c åWg>ãÔS‡k®^Ä[‘°ÑjlO3‹y ¼{ž«‰2ƒŒ47×xZ])¸Uí ¬ –š‡«½€Œ–2#³@Š\tC€2—¶°˜VzA¬š‚’g-—Aa¦@ ŸòmžT6ËBsÒS¨Ô † _7=J çèÕ¡ä7VØ‚ nîæ¡À¨«ÑE¬“œâ£Ïr%Xl+°ÿ‘Uùä* ü!ëáW:¾ÁEácg.NZ*cpKGíá~…ðÐ>Ú °ªlC‹“ßò˜ê ÐÀ†9¢5嬗¬2¸kð‡f3€µ¤b03„^ú†ƒ¯¿·ÎSÖé8<>ÄW Th“Mœ¤‹ù(ùCÝ€U¾Ð/p) çµø®ß|,¬v¨4 DòˆZðZÔrð,»jåÕ¢ª¦ÅAìÊ-ÒM¸²šåø«Ao¥‹ÁŠ=AÓ% À“–aM†Ø\[Ôt{‡üÕ?BJaH÷´}Æ©GàóÐö˜økbâ3a+Ó,ù«‰X ±h–¿ Ê4^ ¦1ãS\¦ ·2ðÀ&ºøóH<åÔZå!°`ñQޏ…uɧ ŹQ%­¦JeȪµÌ§ì¡l"—Üe½¦«ÁÒ–x¥â(†<£qPšZ°:‘›KÀ„$t‰0=$ŠPB+†tÝÍ-Ò“6 Wz-‹@1+ÒVXIwåƒ?‰–D° _ÿE—0azl#‚Ü %H“¿³¥QM®àó,lÓ5é É^é†ñV¶*[•ªé£]ET7Ä ¡FÕÑù \ì7pR6 ¥‰Ÿ0u®2¥U=¬Ù+65r/¬üd|áçi,š<µoåÀÉà <¼I3¼@ñKÓpèç&y&¿é4E²e‚&Ki<-Pº”õ¥Xƒ±¢U49¢ƒòG8 ±› JE¹DQ¿ÈÕf‚ˆ_‹EǑ߼Ѹ„Ø Z‚MðÑÓÁ¹iPü*¿‹§] m28>BÞËÀá-'u¶?YÓÜX2{—¶¨çð¬ŠÏU8㽕§–• …³ÕE¬~Ó+ä­í¼Ï§óì†Ük¯½v¸ùÖ;†S~xZ–ôlIç~S޵SíÒ7ÿË¿’úæ„û5Ýÿ—½ûùpÍïó ß¬µfcÏ~Æ3vlÏ”:S*•6å€Rå ÍIi%þªÐ"8¨@ª8BœpVú9q’PDJØ© V(H= (1¸&‰dìÄ73íÙ¬5\×õ¹ïßû®å‰³3ÒÄ]÷û¾ÏsßßÍ绹7Ïý<¿Íû6ߣï¦ÜïéÿØG?ÚŸß­súæ[oí-E¼=È·¹9ö­7®ü ÿ¿âô‡6Ì7?~=§7ÿ×ÿøÿÎç¾Å€?Ó‡ýÇ_o2þÊOýôã?ùKÿéã3Ÿúdoÿ“$µù÷ˆ¿ðÿÏ=…ÿüç>Óæ_]søa6ÿ–òiåäÛêïGq<¶6·Ž ¡:Æ2äü·O%9Ƨçør<5h}"K»±sô7a7NïÜйœ¨•Æ[µck#UedÜ8!ÙÛ 8«¤ïùt6¢FµÑ_o ̽ Ë"@²Îç‘°{{6‹Súk<±t\έ¯ÇsåÍ¢ ××ÍÐñÐ;p6œæ°xþ16ÀjSzóV"¥«{7øâçpÍw Q¬ ²…"Jc»ê¡É€#A:þè]ŸøWLò3f²”²ýu¤3«ÔôFUÿà§«/¢r® /›Ò5àÁ\XWÏŠýv0i&ÁÁoƒX_Ãsq;q^¾±©¥®ÊB‚­aߘ<_;Š “ŸøŸ‹µS¦¦l£ï,úJÑ8™ITîõÓšù†Ø^lÒ…´…}ÀâJàÍ}•Ϫƻ£Ùt¡ø´7Š÷₾~K1âXõi7ß„Ÿ‡ë_ Nãy±xÆ $Î`W %÷ÝB•Øq¸mR·¯ÒMk´õåx’—]+âY†åq¹£–ùu8OeŠ7³‡|ý‰‚pØx/½q ¦¯ 8úó”Üú¢¼kæêª2MT©©ÎÅWŸ]Ûö‰Jý>Þâ÷mž´‚·óümžÒÿôö3/þØô @nâ}bîSyãwíæý‹¼ßß(}Bï ůßü6›î?÷¿ý Ý,ô Ewô­0ÿØGÛüÛÝx·2B6ʯOþØöGþòÏÂ<뇟¸Å›‡Ïðõ£?ÄgÜøûa^L¥‹þ›|†A?-Þ \Ýl–Ïßç<^ÇÌŒøŒ£ÞD½Â¹‡l¯ú¯¯¿4GŠøW匔ëC¹k¨DåÜ :&á&­ñë˜Ö Çí^‰q ÚrŽìšäšczx~NÎü;?]KüÕú°i@÷ú(R—ŒË[c¶ÏüÈ–|6MÍù¾âS< \ý?v_h›kÚ4nÏKŸŽ¬îüÔƒÖLÖ^1ôjù‘N=ÿõÀºœ]yÅ0¨g¾k« y°5 ‘è¥Û¬Þƒõâc³Šü—ôb¤rõ­ö£=µŸcd¼ù#LU”ÙõCꮳÚF½ð±1bzºc|Z2Þ’öTP•UõÆåx_†ÊH<Ó¡‰ çtˆst_?%é“ Q Ü–Jz3ƒŽ!\IfOŸKB }B¥\;žŽË=d 4‘°‡M:º›Ð²¢³»©@AüyrÔçpM® Ÿ©'/&e樃ùL¼ ³í)9•RM~ö§_.–I4/NÝê´OÌâ¬~쨣ñë“?Nf}Õ†‘98ÏtTgØñ5’1Wnú/e›/Ъ2òol»I-SˆuÓ~]­üÉC&…)-TŽˆö? ï,•/æýðiÖ1PN̳ ¶‚°4ìÍp†Ô3×þtgjÛ¾.D3¿Õ%NÈQ9;œ'îÇYð%3ø‘F‹†Q€eLc€gCù~‘g+|«O{bh ]¢ûAqð\2‘áÇ _å)£ÏWÜ ý%—,¸‚‡«h³œ¨{¦xiÔ6q+kŒïòa«I «·q³¼ï„õ²EE ý¶¾¿q yê9£¿ .Ïò†­žô•#Rc‘Ù{庿~“­‘¾Ýb*ŸQ›‘ß"˜ýäè[½°ÑŸ_J³ÐÓçºëøPŸö@€zþxæ¯âù4¶¸Ê”ó²ˆ6Æ’I Îlÿû8ŸZ1‰©iü.]bÅI#VõIC´'rÒDR<[°£Ó¬\]ù š;cõ ü.fÒõCA!û´—¯òûM¦p{ ®±hƒ~…ÚÂì­ßaT”¸E-Ê!ñj; ÇmëÉüu³Ûçðï9×.È?æ™­3›ú7x‚ÿöãϳy÷ýû¾·ß·ýè¾£Ãß;ÞfÓïÁÊrkØw‹ê·}Чóß«¨ûº,_‡¢ú»Û¿ó6ÿÛ¤Ù/ÈTïÄÛ‡¾EžÆÔÅwãù^~¾Ëæ»4~ŸŒ•Öoæ˜7mÏBºN\?Ïð¦Mpišé7S>udì{ÌÉ×~¢/75Ïc&ðZ'^)ÆšIï:ëܲu’‘Ì&vù˜Ìø7ÑÓÏMpæ„ÒþÕÒ^2³'çR–#ƒ)![çÂ*((+ OtëÎ-Nü;eùƵ¢¹h®¯¹ìJ§4ï_Ÿ.ÉJTd¤¯î ®¿³ÕñZú«RŽ醑7BèÖ¾lB¡Íÿå}>KÑv×%#Ê.QáÃ\Ô9A–*Jqòú—D¸Ki@ŠtQ£®T¿àoîíh”Ö`üò2qëûƹyyíÚz>t9¾èɤT6¾:%\s`Y‰µµr9X²ô‡·º»¢ˆi_4j!ӞΠõ¦,ÆVÞ€ÈGèEˆ‰pÞÍá0¥mÍUwå»Úv/Áùz¯oÉŠôð´~âCõ­],ÁØASx=NJ¨›˜ñDÁÄBpP [RO;Éy|7 Œmznç…«‘CØSïäŽrœN H}ö¯°ÕŽ\&©­³ä+¹—v³ƒÅ= Ȳ“@rBÔ‰¶2ÿ¦ÂÄÀ,™ùíE޶±©'û ìL!é4èGXtæ×Òø%®ªÁ<+Ëwà…•ÿ (b߀*c¿Ñ¯–¢waHÞ§U „ß­Î|e?³¡xgjÆ‘WÚ©sõã_ßÉ«š`¦Ü „›S'~ú-¾ÌšÚ¥ï“§-Ïóv(£' €Ü£0md}¹^?ÁBïe,yibO9«MÑÓÇõüÑÆÌ¬akÙs­Ä!ˆÜìž1±E%áù¹~|‹}FÈ3ŽãCãÁMT~²À!¬–ã0U±Ž…³'òHéGòÆO]ÅÜ»OIÌ.<°|z¹!hÙs!)“Q‘¿Û ×Í!µ+)5Ža&á™r^Ø+jN»sýc¶µq‹|Ôt¼¾:t†ãýæ{ŸIJ’Ãl‹’vë•-tPØÈô}åªÞib :ñƒ°Õ)?ðÊõIdó_ÉúÊM ‚Ž;h^‰tÝ’¸,µí·óämê!“¬öø18ÚõMh2•Z|Å==i,þ¯& ºÎáå3Ä£®›á”;HMMÖ<%šÃÒg#™”‹à™{7…ÆÇê€ÈÚ“mÚ3,Ìï_ÑQþüNKõ%$¿åUîù4‹ê½4â]&žBGõ½‚ïæ?m\ò{ÅéÔ;®È˹‘ôÒü]µßK÷w ÿãð[?½Æì€g<1“V½^)G7Æ]¯r§O{£~p^ ÊŒ;qàu „W·yàÏëøx‹R²²ÓÑÍ;Wžy£!Ÿ’0Ág )oõÄm¯àØ÷gwàÈ…|âÛ͆bžå‹ä[wh/QGML×fÎÀì£=û.*áÊP²óÌ·#êc|d±Õµ1YÚPÖ"OòÑÍuÖÒū̽&à‡¹IY|}ЗSR~nµVÖœÍ_ÅŠD|ÊbÁí }ˆm0úï« ÛgÊ.o5 /]!рɧ²ÿöêN½ˆhâbŠ¯Æƒ‡[?íyt„œ)8~ýöÀ6Áøò6}ÓõC”dõŒRÓúbb¹ª–Œqún€()!OÃê¢öš"­„í¼aòÞnBÌÈSÐÝ©T3p·Ïò 9™gΤKsØ9 Põ¾‚$[¯µÝ[¼d‚¥OæeûA|a\¾5Å48˜ë.Þ—¦Ó…Ï€®–ËPŽ ÍÛUN“]J‹0²Ðä®E=n +91á¿L,7= ðs«·åCEÔ{QÖíëiy’ëäCÌùk‘¿*‘é˜E¶“#X†ŽÙ0Æ38ëÄT:Ç‹æ€~1ÒÝø,ƒ}²eg#âÀ(X êðNÆ5°_ǪԵ?/<šwu¬§€=³WÆêxó¢Ü~Œg‹â ?Œ$8 ÙÂb.Ë‹OÒÄ*‹Ôf)„ÆÇÅN >ý¨ëÆE¥ l©U“þ<¾ˆ9 g9¾ù2&f)›õ-$Ó«?fL Ô¤7wú¢Œv9úW.Z•µ'¢NN:º.}†ÄºR‚(V¡æ³æ2» ‰É[Õ–êX7—Û»²µ‡« Ì›-ŒÚ7Œ9FŸÙ³ü•CýB« èMÒÆBØУéFU+‹‰ú €S’[¬µ}ªý1 Ù^¢7vlâõq–ÌŸ õŠy^^WFׯ|W;ÁçydP,u—ýT©eÌ<¾•Fl«øè¯bRÖ"óĦ{ÇòÔ‘o¬¾ªUBh*çƒ1¤±¹Ô:Í1ýÁÉÎÑÙ*Æ£s óMŒx´Ó'/AI¯l” GOßòÿŒÓ]¬r/õÇ¢ŒGüÕ//0£–þ'¯çÞðÊß$|Ïo¾I†ä˜Ò¤uËÓï°G¯Ÿ¦v÷k>ÌÕûÖ–æË‘ûý>}àíy®yûG*ÿÈŠÿHÖ¾•îï«@›+xYZÖ¯‘wTl>+²ë{#Æ´ábX¶q4)E¶®mrƒ"œóA–&!‰]ïJç·} x›vóC~û‚5Ñ[;³Ô㣠Vh)/ ZkÍ'¶6„àl“y5Îüºñ0[s]›¯¢â<>æ‡N‚ÑNI,q F<÷¡{£´¯mÜà ýS^9dšëè–ðÁÍ£ì™ä‡?=ýpMÂ£× d«‡ªFõ“>#ÖRܲ´>X裚â¢ï,l1-fZÂÙÒ&¹í¿Žß §ªlµ´Æ¶ŸRøT>ö/àêŸÐz…‰£kg"Šá“öª²h"ïæ9Soÿžÿ“fë”ÊG¯ý¡¸„ðvó(†ãU?°˜Ëضncú–7]Ë ðrFŽœ†(Û#j§ä.§Òù[¿øn‹$=„-G{UÑQßÑ7b7>ʆ‹Êþ£7¿ó¡Ò–e¾)U¨åêUælò®Iã¤ÏÓöé¶(ÆYÂëDÕIJb´ƒÀ\P "7èN$“ÊŸÀp)nR“/áP"{–LYYÉ©’¯·/E<Ñ^OX¹ú $móÍ“›e³ß‰>Ê,«ÆA'§§’Âú+$1PWv“¦²´õ) åh龪vfõW²±$®:"¹‘¶ñÝ *®änμI[Žœƒ7@õ—©£Ž/úŠü‚ÉþÞƒH?Ÿ—÷ÞOýBŽEkpï_6x|Þ´r,ËnJÑéÔ!ã[P ÖÏ+è”ù·ºGG̵Eÿ¶/³7}òƒ.üýqƒn‹ƒMdü•˜ýúÆš6SŸ“ΪПØá¬_7ÁÅÄ#Oðû–„$C.q- .ú¡à{©Ý8ŸV‚ĵü¥ç< ¬/3Éa~6¶Ào¹ÅïŒêT^©Ù¦+ý-6ØÄìÍln]ÚÍyAS+ABk—PºäN*¹Z0ìã£<}ø[|ùzæòûf ¥øÃ—á¬í1âÀ4<ý…xK±yÎ@Mˆ“mý Äüˆmÿ•XÊæ,´ƒ÷nÐóY4Ê“9ToX õÀh:Íš5¶ Ëú¥¹­=ô删w+Ò4M ˆ[£6¿Ä™Ùüš„2dA÷Ô°ŸÂ!bˆ]ÈgIyB¤1Bqä—ö®Œ üµ®3¿ø}ª}¥ÍvîW=fÉœòö•mh´L&|IÚ5ý¬ë£¾ü¾ÍÙgÎØÑÏ"+IwóºÒ1)WÑÖß †£·kŒ‹sçJ7¹‡º•ÞYëzá˜DÏáØ|p>3¹>ìz-ãeí›9uøaL÷Åu mEh ê^Á [þdšSUמö NásÐýkž{ + ­8Ç‹Ìd·X†d~2oL4Â9ÊbÍ!e/¿¶“ÿÇSü‚ãµ°g(Õ¤ù •8›ÃVàún›C†—,_Ü#çvr=ãIqªæt×oj,·^ÃkT‡>²¢Œ¿ú`]}sw÷’ Ñîɸ™5ËEPgëÛö¤æz¨,”¥<>˜Ÿ«»ü+%MÇ“¢mó¼¼L ¡•÷ØÕÖ(C3·'ÉðpE奄– dºø ·z*6R¢¥cÖÕe žœÖ¥!ß|ªoŸI³¡æØ˜¥ñûŒ"—!³cßjunÂ@Ë»M/B×JcÄ„³¢Ã¾%ÐñDQ×Mÿîç´¤"ëÎg¿ðÅ6¤£›ãtþÇ©@¦JHR߯QÞ<\’†±Ù¤Üµc’΀Je> äf/héÙñ&…ZI—ã`Øß;uú䎥ò‘žËA‹n1.‰ÐÔ5oGÉC ÛŒÙìb?ø×`ñL®|v‹ Í Ä»‰º¿Ù¶²F öÜÄk·Mƒ©ŽHEû£¶¶Ä–ec²®5ù‰ÄµïÄqðCW¿@ôWøwbÐÒ^tòÙ&Tõ ¿äEŒkkã+8 Ï–Ñ'ƒ]4ù±/ñ#"ú'Y¥³1žC˜2'æÒþñÈʇ HÊYö61q͇v´§-Žˆ×(°4`ñ»’¸¸3Þõ É|Ïœ¨ÇnÉÄ:QhkasQ«â«+Mw5ÊßÓOo°dJžÿóvý¾ns²¥xcˆ…MÑlhJCsù¢*k}?Š(0ßk £xW<—ÆY@é­¡ò)CÊQ1(m®•ïãLÈ£k\1•÷­—[îžÚA<$®;®t¯XœSà¢ðÄéÖmï8¶N®ßÉØßŠ›ÈÅu}VÆñ¶y¦Ÿਂ-±[ŒÜ$Ö)n«ð8å‚Ü ¹‹‘L„1¤dù:ô8Õ ýÈ1¨Mtƒµ³Ì„TÚK½CÀo®àDPK6reÞëVM€\o•è®r‹Š8ê.r2-%#Í:ÀïWîåσWúGÛKãgïJ g¶ SŠº$c ½7¼ *«éì¢t%»Þ±>}Dá|¬r&ž´mJ©(݈ѶO±'¶\Rý“¿Ò/™S1: ݟǤÊËÄ·‰ä‰e#Å~=2Ï `‚ø.v³ºqA~Mžù”¦¿hRüR̉9ÂŽ°uÝ'''þù+-dÎHÊs·ªÍi';QŽ.OÎ= ظ'þþg…ºÇÏi~Ú9(’5 jÚ¯ZsRz÷®½ãzš—’OÜ7øf†·ý¯‰â†¥äì§SœÆ 9ºvO¾®â«û^YCÁ¶yôU±O ÓX9§må×'ZZ -3~la²½˜çÓ©'k=ÔÎZ¿É‚Ñ ·c¤CþóÑÛi_ÓQz,Ù}ßy´k{øËS’¨;  Ÿ$wÉÐ0Åùºžj6TožÀ[ºcr6Ä’çANz¥«¾Ñ)1'õô;m~[ŸTs\{&÷öåz ?–QcÔö5­8ÞüEÀ›yÕÃ2O$ïÞ,§T›è¬Ó»ØÛ×JÞ*”£RbVOªÞ(²=Íõ_´ƒÃê/ûä ©y@UZù¾ø`ïÐ|¿» œÌâ ´ƒŸZÒÖÎC¢$iZ^Í!ý+‹§3¯_®Š~›¼çêr¬B `ä¢,_¨ø{ЧÅéæ²ý_âߨ±´NŸîYƒOWEu=·%¢o÷©nü‹#eŸ¶^ÝöT=.WÑE´o†q=ÎbúE½ ¸ë—ïCPöÅÇ»g]ÎfcIKf Ɖ¶ôÝý¯}m^#y¤Ø “‰ž.íÖdùÈk¹ºúöÕqE9ËâWO,N‚yàO¿M-;ë#0úìJ’ŽAú›Þš=­Á½pÐæ¾¹ÏP S¹•ñv¼Vm¡qEˆ[½ž˜´3ºþCÇïÄôAÀâàŒÏK½\}PÀš ížÎ7´BÜÕB m\ÇföiG>Šƒ)œ Wù” ]qvQ™œNàyeŒèKê×¼½Èôn{7)Ž»Ùó¦Ná½R _êkÃbN¤ûJ°oyÆø3LÑÃ]~ÔzÆiίàMÜã)’Ë»ãó˜;¹-l«“ŸŠRwÌZµ®<çwxˆ ü ǃãÜnêoîž’nvå‘UDßqã oo††ù¾ùºÔlð5˜Jot,ŠŹN±Oãë§ïäë—‹ï³ ‹¬ïS£œ1ÏÇmÞ1®ž¼åI|säŒm½ n«]?iÛÙåÌO·*a­Á'Б÷¬ÿâØ§RÕGûœàIµ¡T¹’uDbÅA®ØÖo)÷Ê~æú­6¨hK0m[ÕF„wëb¡9/>ëµþQæ»ÚóÏNÞ'e—mäuZÛ”ÆDcÁ^d6Ðrû 6”ëóDß?|Ÿf`cÓyG¯2ÖIKÎÍ;ï'Žž­ƒ…ÆÓæÉ>p©®ãV}kœ*¶¤n¼6Öš_{ȽSZmÌ5ŸW6UCYØÍ-jêKðºßZ«=Æâønrl ß¹í|–,u Åmó[7¾9³uSÞæ Ž)a^TZ "fmç¸Ç Dư¹p+™ìÑ3nÝ•æ|½¥=Ë&¯ù'{•*Óy€À) iÌë ¹Þ*&˘@éú#šW0•Tšë s7g3¤’®KŠÙ¤ámŒ4ž×õrîü/©pÅÕŸ£ rÒbÚ £­›ò—O½Û«ÌÊRM§UÍ+‡T}NwSðÇgû(ðsšßÆÈ":"³¶õ̼¯»¿’k_ÕÇæ:ðWµŽMs™ïbQ‡Ûú}–ãŸÇ×c}±ÇâpŠàš…ÖmýVçìéØTvq¨§ýù­OÛ“H/›aÖgæÍhÓSázà°Cº~XÑèÜ Gt0¶áMÙp¾Û¶Ê/þŠkíèæ€äæo}cÞ†"ož»wK½M¸ÜÛv~5vô yüPݧIšS°Ø«ëŸ˜JÀM@ ´­ŽÕ_xÐsF„õGÌŒ{k˜æÆ¾,&+X ‡uÌ,—É`1 å/H9' ßJ9”>?†d.ÏjÎÆj5¡M.'¯ß® Ç|îüÍ%ŒC25ã NÏžÍòqCðü ßV;Z³½–W_q¹s‡šö”Ü"cd©‡¤†fhG’£ORÕr|èy#ßù~ÁÕ· è¸kpæÀ|ȼ£‚†1{’\Þ©ÁS¥·>Äwï•ÿ\ûÛü“­̇ÖBeß/ß·ØšÌ?Xã?ݯS}|èñÿ§À~ï€gƇV·­ö¿sÑn¯ë7ÈŠ¯q ÕaãqO­m¡Ó‰Q¨¼˜òãŒvF¬’üxtþB}Æm<´·—8¾*˱å¸Éa=}¯¯dN{^=ê÷Å:KnËä¯v^j{²±âš¯3/ðCWZÃz…¥‹XçØ<—s×Sè˽çcñ‰¥W²]_ÄríR®¼]¿œ¿‘¯‹åT®‘ˆ>I ñ§ÃÒ½–S³§”JgºéOÎÝ\òDw”–޶»a ß­;á ;›33[ʪ£­Öȼ<'YüèŽ õ¤‚Å¢Õå;í3bÊWÏä[‹ŽjãÆºüÆÂå{­ÒÞˆ¡.ölÏ‘WiÊ‹n9OÁüSºÖù`(GN?P·'{bÏÜì•Uc×#²8ï[lGWQÖŽõ—`i¦…¸rꥈ=èµ'/ Ÿ€Ø…àt€&ÈïÕÍÒèÀ5¨œyMT“NëàΩ%¸⡌N–3ÎýÞ’*t› M@Ù±Ó ¤ú¨êLÏï^.”+b{¾wÿ¸4M´óÏëSÊ•u“èv>'|,R‘èж‘õ¢•v‰Ö—ywÔ28s¿’Ç! Íi§ÔA³-¯h‰ï>µ—NéGbŽ@µáAÏ%çßÀÊÿæ‡^lù;£OŽúÄÏn€ôœ$K¼kG3]Ê`ôŠjó.Œã9Wn\[Þx@_|”«•]œ"f“GÇ¢þ+ÿ’f1¥Æá(GÖoÊMÌÆzóH[Â;_HZéjî„^»^¤B«˜£BAÏR˜!Ú¹·Þk¢°¹¤O²À‹>ŸN}–z£…I’j.Ÿ4³§Ï™ãŒ¦qðcŽ´×z§èB&¶ä-Wò>ø!þ¹ïjû•_ù•Ç'?õ†äQ8VÿI:™S»jcüýË?HÞ_ûÚW_ÿÚ/?>ò‘Ïò? k&ÁA&öÔÒñõB«ê0i $ ‰³`çԆ罒çˆP‹º{•î©Ñ ßëÆÞ$¸¥ÌVAMHéK¨­'ã}/ðRFù„HÛ)å>%pXSÎÝÐÓÖÖ:T¹½N~d‡^#8óYhœ3Éqq 15t½W˜Ðô‘´ U)ÅãSídÊ9þÊÕ¥ f‡û]ìØ¸½…i¶[ ÕÇX8AÍf}éTwÀ@†• ‡ <ßï´|óë Ç®ô ùœÂúè(wO‹Õ÷é¼9 Ô?À5Ò*¯æ÷"œú¢R´ûòXHº’¶<$1¹ØSYœNÒÊ ´Xx1oµ,¿ÿúZ•ƒ2²pè;HÍ]0o™]©OO›¶+9;Æç~Ý,ìð¦>O?·°¹l×ëêR'¿v3GizÞX„oÌʨíë—ö•µ¬;îtYßr¡oëgåöjÊóí,Ê#2„”ª‹³›v=—«˜8pZ´Àq\—;|±ï\D5Ç›·)©JÙ[[ô£Ìúpí‹R–º`Q»±¯OŒMÿnŸ%žïÚ”·[8“Ëó%ô žã×úW{ºçßÀA¨û¤¼Ïv_ßæDJtê•—Úõ&0¦Žcq™4’ƾ£Ï|ÔÖem —TåS?–íÎJ97áðïgD_úµrrù‹~}“%Ÿ½.kœŽ,ýàg96­”“âµ¾5YÜìѶ4ÍÙQxúuv`˜‹¢bœôy(HGä8Fôí·ýLËG?÷×ÿÖãó?ü#ü7ÝïŸ[þÉ&‡güÝíC~ž®ü{ÏO÷à¼Wü{Ûï¥Ë·è¶ÿ=XýÂ-ËëtòîãßÿÝÒ/­«wÏ/œÕ.ýž/ÿ¶ÿAÏê)[!(ÿ ±¯Ú|‰ÿ¬ì»ƒ½6¬ãOÉâexŽGÅzôs¼rË‘¯>OâŽFù²¶×ƒëúÁט àKãO¯2ËÓÖa×M‰ ¯ü‚6\收ʽ±khz#^ß$Éuh\x**×™*çãÞнy¦è¡)¿ §¨Ñ†·>@îYŒ§ðb$ƒëÈ®q¶•Q¬y͘V&áß(Zä˜ÓGó—:ªÒç"QˆS*(™bcG)s±q¤†%MÌÃAÏ=ž¹C,ž!¾0Ž>ðæ[ŸZV^ çW‰³)Ù]†³*Öq‚ªµÐn“À 3`dÝG»Žtm cIc“eѦƒöɧˆÀ:Î\:þø2MFõ6ÇüÛäx–SRèÞås3ÙáÀ»d“A¹“N4ãŽæi0µ³~x¹u…®\}aÃI¡¢¿Ã›m½´Vמã+y¸' Xûô¹ñ+gT ÎÐÊ’\ Ò f-›èØæs_Z¤7½4–Eû±Z²ÏÕ»ê½j›¥‡› Ž@™‹s|ëzÙ% ÇÃñ<çRîf¥'&:²Šúlÿ‰•!êòuÎI&ÝæêÑiNÆ–?NZqj“±Z~Ði –§ùÝEÉ RRØBe›díÝÃëéµöÏ&Ô.sxµQÕ¶êå-/¦8~v๔‰0ßÎEðú 5K³«”7 ÐôihäÅÉä93æg>KØ ÛäkÇö0Ÿ:œ›žS_ÇÉߨï=ù⇭ž'5‹õ6ÜI-P7wÊ–Ï^øï»]”ß mfIVk$v ûZNUoÀq–D}ülÂÛˆp,)ÃØ8;È…‹o͈èתö§“ÌÓQm*è1p‡#p–Qpûû®1 ³õP7ûÒËÃKÜÒ_Jè`õÿZÖ ¥³ªœmøóíxƒ|ñ&¯>=A%¾óü¥]?ßñ\–e¸u|“·’üÎ×_ø§~âñÏþÿK}äÃm*BÌØ‘ú=EÒÓô{x6ÿ~ü«råÞ{¾üà³n Bq³jÕöï売׮õ÷–ïÅû^´÷êýã´_ãW?qõ‚hÞä˾õ­o>þÚÏüÌãoýÜÏ<>üáÏôô±ŸùPÐDðqp’s¦ÏÆšk¨lG4â­Ÿ6ÏZ–ìQغ#NœÎ5Ü&c¤kɪ`:÷kúîÁ9ˆÞêœÃˆ-7zïõ¾ƒY¾uÿ\t˜4ó¬æÀÑkP"mÞöª¼>‰Ž1åqüÙOÚCåT¸†´Zdιâüפ¶sKýÍ[ãèšÁõ¢ë%XZAKa˜V(úròQ³œ*©XÒºy¦æ°ä,_óÿ ò°ùH®'Íø7´Õ('Þ CÃv|Ã9ý¹5"núb†¯]¯¥ù£m­ø*‚ç<š£Éݶ1¸/9¾ëâÒ‚`K¦Æ©øvßòë”?I¹Ó?"'!doVj — hñ[?]_»2¥€ýæqf]ãØ’¥v0B-œ{kÏ}·FÚÖúbÏ÷£™Oâ‡3o¨_ÐÃé¬/Rn§fßýîä´«¼õÁOr³·n¨3D(¹s,/Èd Çœ¤Ù">IÛžsÐŒdÛÉ*’/ÔQ4q‘HÜ’>L6ZÈ>Ÿ#&Ì,¸aÏõQÁQ_¸½ Mâêd²­ŸÊCÇmÜRÀ%Ò{KÁßqsƹÔ#ôò¡dô}/ùËU L~Â-åž‘ªjZ9¥ÜÒ~ò\ Âô¬u£³8¼ ¾iÑV^EÖ:‹ ­6`êðÛ@D¬Øµ!('sÓ‡{hè«å)×F ‹þíɯñjwÉOK5äæñ²Òv úÉ— !©µŸ›Ë…íã]¸‰IeÎîÃ@ëí»XâˆyP¦Êøb”KáðF:?bdýèù”´'<ór´fÙ¬JZ*ƒ?ð¬¸^ɵ¾<+pÄɲò,FzØŽC!Œ šà¤b£ÜºjÜÉ¡é#¥ÐËøé¬eKôOýÄ‘ð‹!Ý\ [iÎAýRßÑ©:÷UÖ0¥ƒ•÷ùð:yظ´ÝÃÙ¡f)÷V³%渳 ­drÆ?\?Å«¤”<É´ë[]ä¦ c0È×úÙ~gáç µù.°Ÿª`‰`wz^×Î#Û“LzBJÅðàú wàçWI.§ñTW¬[O›?ŽmfÀ‡çÜnc^ë/QæëÑXùˆYÿÁËE¨ÐAÛKñÖm;ÊŒæÅ¸ðE‚Àüì¹ùɾêh/á¡ÐàGy@0Çz†î,hë°¤„ƒÒo}ëëÏýð>þ™Ÿü#üÇÞ!Å¿|Ëi.¿¿‹ùüøÈãÿöŸþÔãßûý;/~ñ‹ÿñÿäúøì§?Á¼?cþû;„ßÓ;ãûÎw|µæñøïûÿ[óç_ú[íñá}æñ¶og¡#½cö—ãBi{ÛâŠX_‡Î©ñ|‡-Ç|]ÎúÆÑÆÀó‰cjàâ:dhïLuwìÕÎè©m¼ÞÍóÄgËëè.9´S9cÝyploÝA«ñž6‡wãÛ~yÈ!¿Üw^*~ä9umƒÖ+g>Übþ,U``¾‡WÞ9ÚÜ0fD…2Tk\åý9Æ0yçêõž¶Î:4ÙQ›?œ+Ù[œ›´2ªAþ4wì§£ÓQ\o©dÒ>žl7j`VçÙÕØ­Cëͯ(áœ"ÂC[°LB·ÔÃ8ùÚWI/ÛåáÑ…ŽN±&öɧ.Ø:ô­}PŠ_÷f|}xrûʧY"ÖÖâ^ =¾—–cìè‡}á?#¶=u‰#ü®UÔ¥ZœuÚЇ¼IŽšmÖxg$ä§:ØKÛòSÖgðúËéTVÄKŒµØµù©éŠÖÚXæP³hXñTh9á˜Áýã êOþä1u‡r¬ãŽúÒX<Ôñù¡ÜEVSå–ÈÌãSp,všúɪ¤W<ëòà(kÀ µ™†w{ƒ\IœK,]ôÌ)1(ò­ê-ņð¢×θÞ|”1ƒ‚6¯¡”»I‹!ûhØLN»¤»"Ü´ºDAâgOY]œ•Ú$Jû-À‚û[©R Añs{}aÁ{[_Q(ƒVé«Ýn¡WÎáÃ2GT6ÄR¨^¬ãõ-Æ{KIº9ýôâ’œ˜’•ù±Q8?R¡¿Û<2?´®VëZ0Â(XiÖÉ1&W{˜­ˆœB³Gg*c ]ΛæðØÅÝ9j?gÕºˆæçl)½±#Š¡ÞI+-¹ÆºöM¯>/2rÅèLÕô„©4{ål› ÑõÀÒø(_Î?m ib+çúæ”Ο¿ô‡•Ä;oü94Svˆ§,dGm¤ïÃþÄã+_þ2¿úøì}:ùÏ}îs}˜˜²ÉÔ˃pê™ sð“5áäoíJ¯}ªñº.á¶ïy7ߟzTˆãm>û©O~ìñµ/ýÕÇ—éËÿÊ¿ôÇ?øÁ<þòÿë¯<~ü}þñ­o?ÿ~þ ªM‹²¯ºü×¼×më·\{¶¯¼õïE¿ö.oòÓ~À÷+_ùÊãmn¾öÕ¯s3ðM6ÿ?ôøÎ;ß)®­?׆Ú8p í:Íx ËëçuÞ!ì4.Ì•ë|Ɖuç[n"^oMdž6V!Ék}9㵼燶îÐkÜ?“‘¢¾&ø)å˜ÛƳ¹=ýI!xýhÜÛ8ëë‘ì;ÖÑïZ”:ý6Þ¥iñ¨€ŸÅF½÷Âóöª¾}hhŘƒ®5¬ã=ÿ©Ž.” ô¡ÕçÆÀ•ªÁ#WNÔSž X~Š®gV(Æâ:{CÏ5&‚\ºë#Ñ÷@ÐÊRüÚâÞú¬•ðgÍ@„l=×Mì†Ç®g©sOÈJçÚ«~kÆf?9Îô¥Å^<þøU®Ð3¤Tòô‰(”,]“ÏÃK²DÎ(j±|EÈŸ2^+¬ ¨ãQfý)ÿÄzûw¼Å1|°U)UGÕü·ÿ¹¹e¨j¶t&æLxüJ_Ië™TÎ뚎Q7®gÎ ŸñK-DeÞ:XÒhûž3+ü°¥u›`íbfãt†£†£³ºciˆñêÛ#ĪZë–µ¸îëXüü ­/úZÇÅÛt…Bo›/þ|ÉÒ€úÇ1c—-(&½¢ÎÚ’]4ô3[AˆÎ kª"ö$—OüÂWo ÎÖ ¢êÞ;+fÙà|¦°yv‘›Ï‹ê”>\,§MgµÖ•×ñ½·o<±Ÿ1d_IµÔsùg³i¿ièL.|ñdrÆ#×£o‹h‹‡$cáOêùO])4iãIyTE´•¼f'â©Ý|øÏ$gPÛ ÷„™³¨lpÔçmWù¤_§î7-×ï Q‹ñYäéún¬3 ¯rYUÓ?íwñ±N<ÛL›7äôÝñH¹ëæò£,ô6HXß¾¶x]]\)Ðñ…Cú²¨c$!dÕ§Þïh(õ^vå_ü#rr¡\9G á*ϱêâLOc³;÷i¨ë²vòKÝ1élúL[þÐÇØd¾ýøU>ìàþÕ¯ü]ο¯Ë‡>ø©üû_ý/ÿ×?ý§ÿëö'ÿðã?ùÿ/o}ýë¯þÆ—¿¯}ÿsîɽù?>ôÁ=¾ÝWC²oíÀ¦ŒcøŒ¯ûmÜh9r”UZÂ1ÞþAY¸ ÇE³ù‰£#ùa{FöÌ…m6½Áp0 êX^ãKóp*Ϻ>^ºšc$—<GH}E¢é•Oú)I['Öü;êkŸf_ÝÜ:®‚oÉ›—âš ×½µÞº°ÄÙ÷ J´£ “«b2åÉßsNFÙ-ƒ2fÒÒº¤¯%k¾jS„ß“®¼†lŸ¤/[‹´øFo7‚þµ?¶²ßÖÃpô6ž¾-æHìz¤{‚±d ´®£úfÜ[,QõÁ^YBØ'ä⫇ v燖¯5ö:¦†=«†ÂB>±«o\¦¨±Ä)ŸaØ}Ö3’¡ãŸ°^|=Åë£9 ?™CÙPcöWé†%9üÕu L÷Îæ œ;ñÃÑó yü­«î+‹/ké—!e£ú­H‹?c£©dÅ9™å“ž=c×xß"L„Ü¢(¢z.¢áTž$tÝÉíT¦làbÁ‡¥TɉI½nHꬃ/û@↞\2˜P23›& Ì9?iǪ¢ý9®ºÐ–Qva’®~Où³Ÿ‡´%Ž{ö.dë0•d#ÏÞVOâÏ…›ËÄ=è¯êœþàûÎÊ+¤’1a5)Ö¡œ8œ;w1,óžô$õïó}ê ´Ý„v&}O§zâ'6ëûp+4ÅãÏw76Ì]Ì£C¡a¨¾:²â‡ã+[ö9Ò;Ÿî‹çÑ¢?êŠÐÛ¸Â8fØÕ¤žïooƒùòiH ýòCÜ/‹ÙñF‘ÓAîßïÿlæö]Öó]H½{Æ`˸¯÷öK7a>ÍÐÖð|¿o#k²¡Øwy_tó(ē듋ð™_mT^68§(æ°_ˆäûdz·ƒ[ÌõƒS'üÆ+•:ð%ã6Dþ®ßÏŸ<Í|ƒV™S·ŸJý˜?G,ÍzX\ËÍOwMãç s«ù„ß›#~ÅÁeaϸã¤z¼ö†R "6?ÐÛ~ %lÂvB.ÛúäßJ½üæhÙsË'UûJ{QVýר¡}‹UøÓG#¾zÆÕµ "ÓÇÈrêg<¤·4?¯¿VÔ|І›sóä/˜…Cã~›³îdóèíU!XD$*û¯«®-?­ ’µ¸.{’à_KŸ1¡Iû~¡€ë]s(ÁòŠŒÞ;–Þúà[¼Üì[€Èê›@â+õÜøÔ¢aµõ]ã+«:v@rŒ\–u£m,G]);›_5nƒvô”½ýU—ˆ¡4 ÷Ï|öŸzüµ¿þÿyüÆo|ýñ/ü‹ÿåøŸýÜg¿ó­·y;“cX’‡k‡èKÚÖ».¼´_ò«#}ƒkUÙ¾Ð\|¬8ÇùUÎ&mT$ªÜü·²¹E„Ç—ušã [ WaPñÕ¦ïòŠÀ[ŽõõCÂòlÅ„[×vÙ¸*~ìoc…= d t߯ŒB.Çú¥¸Ôÿ`6ew…7 G¹¬qôÄËOCgóH¿ÂÑ*ºÂâ›uùv¹wÅ ™º¯zqR–Ÿb?8ÏñÝ 9êK 2'✵>Ýë¬c œH·´|r]??ðǹÝFÆ•5.¥UçÇÍ¡¾ì«ˆí Ö%è\VŠ)AžOÚ»9aÔ“ýŠFùC‡7€Ì8®A.-ošû^™ôøª°¿í…DÑKgGäÎ…]Ûÿãþˆuì¢mÓÖ®O[c•Y¿ § ©§æ`kLv„Ÿ­ÕȘ3èRýY]$~ZÿÄ¢8…‚w²’•¯ ƒšVSÛYÍèhVë†øÖÇÜØW¯ úébc‘–ß¾[À$Kã/_¨vófßá}¡£sCÿáK×AÎÞx¤š£Ä± /¢’§n4ð«ÁtéȦ¯º¢”Ä.Ä⨿§‹9+‡•hú»Å[BòGg¶ÕW^äå eOØgý2bóa“¿»L‰Ã0_ÚbWä©„½_ {•6)ÒLä;ùåšuûaÞMž5Ðdk85/†w“ƒˆðù\Ïå×Å^ó¾áãSŸþÈãç"þ,ǯë÷õóÙ~ ¾ª ã`ÍèÕ—m\GL^Iz¥v«ë¨µ”±œÓ; eO©€˜§É饼&Z¿ÅD½jg÷Ò.ý¾Måë1žÄ ÈùøñŠ;yá½·~‘fÍ5Nvª£¿D=)ü}/ÍXįïeˆœ¡käè¾–;2&{óh¤Ë¿XèÆ¾¹<&§‹@ìSÞ5.ý5ÞSÊ9E?¿«\ ÏóÐÒy­ ~“†³¾Øg­ äÐÝáÆpmÐwåäâN¯\È·\µA‰‡Ÿ-êÏØ.ïØ¹rϼ]ºàï­K³Ìh\–§kîxm½¦]Ì{†—mÛ/4k¶[ï"Ÿ5êø=™ÄfJ—zhŸ±Y%rí(<ݤbÝù}IÉ{ä’Aì¹&Mç·ßæàS_ú¥¿Íך~åñOÿÓ?!ƒÏ3üÀã‡?ÿi¦ùQúÜÒ– ´xÊäõáÌÉ ~ž9‘ê{0ĪÙƒï¸Û5æÓîñIù§ý¹ôìƒ9ÿøö=hús\^Éîæ||ýžPõ«r5¡=±®|õˆ¼Œ‹é¿¦<Ã}u¸&"Ù89ý]>óÎíá©tÔsþßré·}=¹Ž-í÷*GÇØß•÷E*Äò"_û–¨«– K»¶à'Bû™ç#þŒåØ}b [µ6°A½¶sôŸsÙöµg=M+ï)x|ý7¾ñøõ_ÿ-¾Yʘܽ8P©ÿŒÜ6Ýâð2‡öz´íO…#“ÍK‹–rÞ,?Ã5Wà>oЄ@¯+Ây°cºã‡ùg™°†”YŸÛr¶aú2òÜ×Ím÷fð“´ù¸±Ð˜:{á@‘ë¡`ù‘¬7úl¬'–»Á¯Þ hpÙ©¿fÊ'£ i÷f¤<¦sn²¼1×6rÚ·¼µŽñ©¾”=M+²‰1òx(¾m=.²&E‡MÉ †&6ßöŽ~×iê+ß¶2²ÙQcöíŠ[äÛáۀʮ;"-‰§Í¯£ô`ICÐäÀ+yÅ¡ í¹‘œín¢zjK£E‡»\Šb¼Å!6S„j~VÁÛlßœùôðD‡?Öõ­Mˆx0+‚ZvnpÅ{³g’úÇÜ¡´.êöl?Ó!wÞ¤Ñ*¿{éÍ;}ŸVK@µÙÒ´.&õƒè[ÿsì§?õ±Ç¯þê/<~íWa½_ÞÏÀûx?À3ð¥Ÿ_€ñÿðzü÷þ»ÿõ¯þå?àQ¿ÞûøÇËÀg>ýc¯~õ·xãÈݲŸxîÝ—m7µ½Õö,íWÎFè|2'܇ìf@¶!Gž=Y;*6÷nz§æîÏÝ :ÛmŸã^­½t4÷޽Zƒ²»i?{#ým;¥û­°UVIƒ¾zÂíñ:ŠžtUÙôŒq÷W~³Ý»Þa’<°¿Ò¥W}z•{¶vcpxº ¶‡E_m¥ÝãikðûÉO~âñ…/üøã/þïÿâã7¿ñ›¼ýgoYyöAèqÎ,‡ ¤ôNüµÀ±÷»ô¤Üñ8ÇWúß3ÞËãÀ̧Cêˆbq¸~d\>¯c}—?¯ùÚBÿöûü½`Ê¿Gæ]må2ȉ³vïùB¼«}mªvôÔæûè«KµÃSÿÈ?Ûò-¯pÖ¡ÐRŽûârWT¾uK¢¯á?óóéô0.þ|¥þ.{×Îs¾\ý‹ômÞ¸ÞeþS䨼íwÉË;Œwé_²8È$¦Âo¾ùÖã/ý¥ÿÇãßÿ÷ÿ=þèãßøû'þ1k|÷ JoŸÑCbvÝmêU©}Û݇à^ÝšId“] ûªÄ„ã•€ûVr9¯tŽâñÜn¬5òÆ•{¤Þ¯”ƒÉ*íΪýqƒO”í£z0×ý {¬ù¿Wàl­Èñ+ÍÛ3ò¿÷Þ#ïç!ÛS>W~Öt·ýZ1žHìäCw_¶› ìKý"íäº4+ãmŸ-8dþfÈ·æ%î0èc¨$ ºòæÝT» D[ÇóÍM­rBÊUÆ·ütû1¯êÜà”€ßSÿFï­-M1DL¸Aö=ãÝ1¡ïhÛK0©ßïŒ÷©·úÊ'C½—z2<ßî3rß–¥óYP 4=ßÓoxgó¯”ú{ßÓg´ÒûÓ«–*óÕ<©çfÜí¿²ë(åwÃa[G–&@†v¶½ùw<ňM7CÏn]-­ÙξÞ8Ý÷-ƒ¨9ËïÔ>Ú¾„­½‡þnJçϺþœO|ü#¯þúãñÇÿøükÿÚŸàýò~ÞÏÀûøÏUþÔŸ~íûÏU‡¿ì?t¼9öàcÿÁÇ7¿ù|°{›í‰¶Or¯è^èóÀU#îsÜ©´ñðÜÍœíºÔÝN¬ö;Gô©³ýŠÒbÍâÙû´ybçýlŸ†zÌÍ®/¥=¤{`}ew©ú ò}XÚ~ 2¨éffõ\´0ûÜš¶?R+WWB{l7ìî  <§ü¸9âݳýâ¶÷—V<÷€Ë—µµÐ£ìü DZ&÷8´o°Ø‡Læ®*n,M‚ºlÍóÚ=h™hŠÈ9nk6´éFs–9Z9Xû~TIè듘ëÝÏäBD·ü©ï“ú`¹Ûîa@s×?V¼+•Ïbd@\~´ †‘.Bht@ž½å ûéí.+ñÛòG kIß Ráxm¶}o–wN ×Yœ„ÞPÈ•þÌ«³õ¯Ï$æ@_eªpòù8ŸD¨/ºÁóû·AÒ§#YXèUDÁçÀ<ðGîÿløýÑÿóÿÅŸ}üÂÏÿ<ï‡ýh_é'Êûåý ¼Ÿ÷3ð-^¿üðŸü“òñ‰O|üñçþÜŸ|úÓŸú>Z÷v…øƒ–÷÷ãù'#oðe ßàU±ÿñ/<þÛÿÖŸi¡ç½?ÞÍÅwZô R=mõXö•pb}Gìùbº‡ºúîi$ºoÛ^«íÐÙ ‰¦]QÎÎ ŠXî Ü/¶+Н¬Ôí•y6i´ŸÅ›c§½lXîo_ÄÜË^$°Àl³Ï>ñìÓ„½\ÕÅɘz`´ß’”Ûyêÿ|¾tÏ0oó>{ë{3´h8*“o)¥ÄÙÛ¥æ—(ou7ÄÆ³$œYs°÷ÆãŸMÝÌG1tƒï“wrœ“x NLŒÒÛ·‘ì•+’¬Ø±b,ð6úšn¯Nè£Éô=Wa< R„ᨒMÅB× &0t= ¬Ú™øÝ+ J€+Þ‘NÊ»ºðk“Qè11Ÿ—›z9&§Ãª‹'ä¼ÓwÑ_6€0O y)‹Žê-QP6°åó<,§ú„P>¡£ }w°q¾·GZ¶½x/„y7ŽŽÔõ<Ž“,sk纞o² ‚?´Ï$xƒ÷}‡¯õûþ7ÿ»Çôýe¿_ÞÏÀûx?à3ð‘üÀã_ý¢§›àƒ}?À÷3ð™?ñ¯þ©Ç¿ùoþ·ø–@÷ì5ܰœ½P_Ÿ:¢;~ØõyD÷dÊÅä´}Êýg¬Ûƒ‚wp¶;»÷3n–(wå&FÊ$æG¦+WûÊet·Ï’/®òî‚â-<úÍJ=¹žÔ_¼íÛI¡çVtïrŒá„¡±êîÿ÷ÍQÓÈðœÃ>»³L»ÿÒ+Ý0Ô Í[«òC#DŒí?ѧjê²çsÿŠSzg4ƒÙÛA ãvÐÝdûµ\~âZùØ€ ±ß£ÿŽÊ%Êíe’'Èž—Qôr‹…’ônªâʜַ{w¶Ís·üÓª³iF®§èú3÷ Ë ZOþ5䆖â#ov@Š}ïOºŠ©™AUßþ¥)Xte¨Ú)úP½Ý‘,¯ ÓßU‘Ò£÷Eö]óÆ„ñ=úw|;:bý!\=¼Ä§†õÞ-¼”Y]¬¾<$ô|¸Û|m§½œ!wßÞ¥k §¼TWæù9ì>ØóÅ/~¡æ?÷Ïý |êÿ7‘=>NŠ£í£ó¤ÝÊ¢šÌ3žªWçè×Wþê{~-÷º}eÞc?œ#ÜÆÞE¹Z;¿¦‚C³ñ!dåYYóŠ›kóun–n?Ž-ýꢲ^”[I±9„ñ$¼ØX‡­­pr§yOÆY¹ö®­ÑgíÊ<•¨ˆ·Ó­³"Ñ_ë8FFžÓG±“Ë‘úxõìáÊ£ò®¾¾rï=®ð­¼û|Å£¾Çæk_¬ëC}fV¨^ñ—D¼Â¾öZý L&’óÍyøº\Уïü‹´çSé•Ú»€ÅºwŽK»vä]¾Š¿Kyü qHÔC„#nÝua´'÷ˆ¨³ùïhµí’u$Ÿs K¹å›Cktë ¦´c¤9®ÍƒýªÄˆ©@”Ñ^U#_žtäŸxV,žÏØxx|2—¶ ð'ø‡`ÿïŸú>~ú§æñoüÿúãÏü™ûñgÿìÿìñÏÿóÿ_ŠðÕÞ"yf1ÚW7 òaM. #îxû] ÊÙÅ¢’|y‡®lÕÃWµñ'ñÈ ð´_á<é* tËÕ»mu¨¿"·få‡22.®mм«pû>†‡ ôJ&Þë¶uË{e_ËÀÎi§?ŸŽB ý§}±üsÞÉ~iӤض¨{xéÚ7¯ðëÁéqNî‘VÐyòÉÓÍÅk¹Ãö*Û|ºs/ØaOÄ:¶#Ý1"B¶&5Í–Å»âIlœöQA-W###ØkžõÃO¼O|⣟ú©¿ÌËþñ}èw(…î~%ÝçºxUNÈ-Ú»²Þ6/u×Ë·]H…åoÉÚó‹”¹Õ=5©‡9÷€š<å‡ÉS1èÇÍ©v68Ê®@÷ƒÌàl ”§®ò/R}–Ÿ¤öÿjìŸlONÜýj_Uuµ{0ˆá‰I9ãLóż>³ÀùìçÉY?÷êƒÈêáyÜêú”œøð D°œuS¬ø6Ì&j×+•ú}:Ž›è—§÷÷ûÓ68tsð|4pŠôšÈÍž´븷Jí­KjŠú+®ƒ Ç„Þ …pµ ‘êHš˜îÍ÷_íP·MÅ$ ëw ™‹sDMÿ¼iÈ÷#ºá3 Žjo0‹+”ZåBù؆w¿6U?|‹“Ù6—ŠÎ‡éÛªD§†Bßòc;j¢hÿØ)âñOĦ¿`‘†ØÍV²pÞ×»â2‰Æ‚‚fγ¿Z¢xÂÞ·¿½#ï‘ü;÷×ɯ}£?¾J£Xö;!òçbÖWÞd@uCaæ6(¨S”SAƒ bûWà}EÖ¾s7v¾Ï.2Ò¾}ÈtÔÍ1Ô+1“o¢ä?íói;dó‚¥B}…âŒá7[ù­Ys‚ŸàÞOñ£Àÿbd#G ëXy)øÓÄ µòšÙÌL’£«y±CÉ´NX*hogO §¾D(OdçŒóÇ—5Ï$öˆt}0cÖÆæÓúÞù´4 kîìSrg®Ô›Þf4bD‹'¡`†,6f÷†>{ÚXæ¯$"®Îæ­ù1&~¢£“)!øbÙx&c>h˜§§ip´ =¬¼öóHŽIåä›mÏ#cY17ö9múlÞÊK>’;)ó’Uy"ØõUýnÝèõFy½7¿·-Ò‹§ë0Œëôý>k¥ž(äo†Ê©rûœ“±¨dìÆ©Ð-òÄ„/Ýöo¾Ó6Ñ^½9ùjªÿ‹aó]}d…å»ÌùÆå+­¿\“ylq°!—WslÝ‹cÖ< $\œÙŠ\Óǽ}r†~Ü\?ª¨ŒE¨¡[Ží|KëÂáÁyúç¿ùíXþÏÿ‡ÿÁÿßyüÑ?úGkã7ëñó?ÿ˽ùáâxØæÜ\Ù;YªÒõÇ_%¡óoÒ—ç8{ÆŒ„}¿]ÑÞ«Øþ? M\;³™ôQiÆ‘¾.×·}·øúDc°/‹áN×èêòõñ‰7ì1È*[œ{ø” Í6¿¬ÜqÑæJ9‚²QÕÖ/…è&×Êyõ[¿êù|Î;ä=‹âj‚È Ulí{âÕ>ïRˆ°>#sØZmË[þŸs¡4ž}fй‘µ£gº¦K)šþ?ƾñ8¼Þ7Ÿ²Œ ûÚuð®ì©¡ø»þld¡¼#»‡RÐìG3¢qÌ=ÿsº†‹K$õ<  ža;z}£3ú,Þw?öc±ßaO°< C¿Ã©ÓðŒ·é3vëöcœÏ¸rMyÖË¥6ÍÉú±€ô‰µFÛ7N­€oÕÙ¨g;õùuE‹Æk>HâHæGq:Æ,Ê¥'OÙ²ÈÙuÍ\hÞñBÅØüÕÿ¬ œLXè'"Sߌz]Çt®@"Šj–× ý6¯u¡Ë›õ„+Öw°ë’üìk¤²gŸ F»´…À?Ë¡PtXëø&ÌmtË1úæ°g›vg–g.Z²žhÛ1»¤kÁ¾$ÍÄ€¶ƒÄÉ)ÆA&tg" 2 òͦÙr³ ¾ÅËH_£YÔnnÕ–‹ºlmkI»f×¶å¾1)e,úi×À;“O'ë¤øêšM$‰iþÈWÊü~›¡&=’·ƒÎÆÑ¼šæýC)Ÿ~AÀÿ¡y[9ñV; ¤Bõý ¬$Ð0·ö²7»Ó>ðÈÉ_¹çˆØ»’zþR´Ó+ œ»pÞFàúŒYs)=(ÎÛ!–ÃŒlÒWÑll,.†Å¥]³.6 Pzä + vô¥c1L2H`KëëãýÓ9íiùrbŸÙœ=ir= £ÿæ`#`y”{cËõnˆU¢¥iãîo^7â›1Ýð诱HH­£îÊÑôÆ«höñ¤vÓ¦7w1äÛØñ<µ0Gý£¬Ö.9è0îL™à» Pá"tÇ…±ìÌðí\ÊàÌÝ6~üøP~é‹}Aœ8Vºór¾÷M[ÇŸðYIŽlýg úŒ ŒO³¿ö.Z¨Ÿ0ø¦}ιQgD{å-A§-Ç–Î:rl½E¼Z¼õ V1ßíeѱ Yß?£šVI]+5•Ó{ŠkUwŒè…+²rœ[gì f£u׿¤Ê›y/üv´dé;@ÄÑšö"Ï2ýXèû““âhÅõ ãO›ÃDüàM%U±éÜûò±Xà¨)«þ94™n&Ã"›ØqÌ–CO]`µOLpbAwÜYºqæÜ‰ýA}¾.‰Eâ2"ËúL]ûMkÆ‚t!oŽËÛü×çm¢ÔuTl-ÐÌr‰ ²¡ ΃ßüúo?þÐúÃ_üÅŸ}üÚ¯ÿÚã'ò¨þøíßþæã#þo‰Ôذ\û6ÆtZ_°m¨ˆlt‰¶Ï(€©×)ͮ˭q]¿®v¢ámÙ£§®oЯŸNr²C}¯¨×É—IEš»¬_ëJ¯Ážëоé‡ãÔ›'úF¯í®–"6X~•WÚ†1fG:ºŒ4ÞhHÙunÙÿÐw’˜ªþ ‰ì‡—7È–% ¨Ššƒ$ðžzŠÐ‹Æ6òÛShÃq„§Ää8ÕÌÆcÞC9†×¸µsÍ;ŰŠçØT· »ë’„F×ðáÚÚftñeÒƒøøÐ‡ßä[4Þ~|ýëß"sï<>Øÿo_ÞãÛoñ?:ŠKŸNÞ3SÛ gÆ__¹Ó›‚xÊÎný|曹°ÿËŸ~=/x­4è;ïæ‡ýiv¦#6_8`è½* ÙÉŸ9‚Ù e}¸þÐŽe½¾õìÚîÚ¯·K&dî…±oõSÛn*Wõ~S7ªƒVAe)úŽž0ö7×”}¥µ7äòˆÎ~3àÿÖo}çñ£?úƒÑîçþæãý±±ú/ü¿ñøáþïüò×{—@9iÜxƒì<9>€£ Å\Ì–7»ðöÑü}ÙÜ,çüŸ”7¶(>²$6ý3À5p„×Óu .½§¢¯ÄÒË1Òˆ.'*·´C­&3{:médY8¯¯Ê]·jÐo¦«tÈ`è}zÒk\ÿ¤lî͇þ#½þeäÈ#[ÑGcem)Pleìæ•¬"r©O+¿[w°ö¼ FT‹·Óv¬ZŠKІô!>ãÒZ‡8”ɼr³Ce%’cT<Çeù Õüˆv#ËŸm»t±É1GœÆž.z’vÃ0žòš¹9‡µîòŒAãÎßìË^ÕW&ü2F-{ ³kH¨à£by°³/¸ômÚ7ÿÍ1coÊHè›ø“¥J¾c$]p•²tÍjÿ~}í|C_-óµj}T†ˆ;gÅK?«l¬ltê{²!%šÚ²¥£¡ü´ì,Ÿ/¶”sGÈ s–s!ûdÂÅ`µ\£'H,Ï kÀÐý©ÅËĦ}ÇbÔ§ËOñ Bc&u³u2„É–küÈ2)T®Ã¼Iç¸A½E­‚QÒ ƒ¯PÉÒ1,ØéÙ7=@ïiæ:ªÞ.<½ÂÓdu qŠ BšÜܸ(5æµ"Ĩ”вb;ʰ•³z¸ç€R] õPª^*g¾”I‡ã’ -Xå–ô²f/»AðBc’ÒŒC3´aÉ£nžT p‹Ùxõ«N¬ã«’•ùX>â-§z£µä’°E^Ø¿yî.`ðºÛgRQüÝe¡#×Íáðßä³ ŸûüÇ{Rök¿æôæjñïC]]~7IÙ8€\fÊògį̈>ø·xªK¾³Ù¸O³ÅÐqvÁœ–Ù ?:ÖÌžÝÒM}䇜?óC}üÀ|èñË¿ôu6rŽm¡ ÷ä‚XuëŒ#¡Ä¯è»¹(wv&¿%Z£Q®y|‡MâÿÈÇRûå_ú9RÆcT,‹]â‚À÷F¡L`ÞFÿ³ŸýA¾•ä£üã•ß|üòWþvX_üây|ðC|üò—¿öø›Gÿ+c# [¤ÄÉO=9~«Iuøo?¾óÎwÀþèã#y‹<üfùé‰2ù†äÉh6Õµo6´&a~Œ4¹êg^`?»ÅáüâB˜ ’Œíe`æ~Ò9‡qZGVÜÍTFœn¾H »þXŠ}µÙç˜añt<ç“TúÈl×ß7];‚Ò/åxÀxøÐßzücý7¾öÛlÖ¿‰ÌwyOìgû¯±ßuƒ®cîì[èÞyüÎoÿO”‹—Î}EæÍpÞdúÂ?óø x?û³÷ñø:o¯{|îñÿÌó•zß~|ù¿º›Öƒïðýô?ò#Ÿà¿sìF±¢!«¨~ù—~ýñµ¯þöã'~âóÜT|ˆåèú¯ s ½9ø­o|ëñk¿öhB~ðCo>>÷¹>¾ö¿Elßædkë¾`%y«OI!Ϯ՞4ë ¦}ê¬ýô·v!6ÆÈQóª1®œ-•SÏoq[ ",íÍn1t-ݸI—…ãû fç­c)b>œ*2£mžR/")í†]mó3ÿc=þê_ù©Ç¿ò¯ü×ÿý¿ùøÿÂÀM·ÿ`ëg^§ã~ZÄ,jkÅõñ¬[=ÔHZ;»áQßöÑ=z]g¤é²7Ðý¡‚¿*PoÌËŠ@rΫ=Æ(ûÌÑùèú¢þ+ùl͆¸ ñdòq:T_‰¢¿\殨`7ÆCâ:eZ@§—«xâÛJÖ¼ŸùÒU7—P8:ž•_†ßæ{90==~i§uÁœÒ¬/‡»&¬^<“[ÿˆu‹+yÝ wïðÆÄÿÀ<9ûÖãçá¯'ôCŸý/<~ý×~›úϳá5_þòo°15/xТM?ŠS¿-f=/×hö27ãψ'‡’Ò_#»4)äÂ\ÞÔš6c  øÇ“r“ûí·¿óøüç?öøò/ÿM)Ÿì«Nç·¿ÃÞÆ—ï¸qX¼ÎûãéS~è1еú¿ñé8E¬Xõà»OæÃ_ü¥ŸUùñ™OññlÖòâÂïÐØÜÄçG`8×¾Í[~ìÇ>ùø…¿ó×_ù^Ê—¾´¼äÃ?ÒÍ̯üÊoò^å!`>ÙÜøS~ÔKîUŒå;ôáqô+_ù›¾ùæ·üÖ7ßîý“²>-_òô‰%{Ùǧ>ù¡þoį|åëoòôZÑI Î:‘Î}òµ‹%œŠ~™Ù|’‚¬Å1[Vüõ‚Ù øŽ+õ&Íg)Äó6¶çX|â?ðø þ|çwظx½„oŸ(¿>™îÍõ.ˆÞ\v)ÄòƒïmPQØ\æóÄûÑ}„~û ïÿEÐèÇÏ|áñ6oÿÒ—~¦öïuø±û#|ˆžÍ5ýþƒÜp~–œéKÿßw©¼óøÊãoü¯DûÂ~’›ºo×o=>‡ì/þÒÏñ÷.ñ¿gÃ9ø³?÷ÓOþe|áÇÿì½wØ_EµÇ;Þ IHH§÷*"Vl`ņÄ.*–cÇ‚]±aÁލ  ŠGTA.$„@è Tˆ÷óù®½ß>ç>÷Þç¹÷»ß÷·ËÌj³fÍÌšÙ3³·lwÞ¹´9¤-{ø~ÒEG„câ„ÙéDlÀwAª<¡ÿЇ:ô‡š’uÚv½5ò¹£lw¬q%“xñØZ:#Ú0Þ\-^ü–Ië2'9$uëi$§BKF!a.÷÷‰Ö “³ä[Œ"TÂ=á²ÖÎãÏŽ| äÔ¦«Ö' 8¢„¢Ü/]b§¨µŸ}B;èmoi{Ä nåEùN‚Ÿ8…,=ð<û'A%/K/¸>#¸8‰ŒXÑAàIúÆ’9ÉÁôeù^b'RähÕa9•PéßòÃÑ+w€4…1.'®)v"„„AA6@¢ƒÊNà{åö­X) zŽÐ)¿¼CÏ{勌vS‘*ED” P'âTJ#º*:¦•ÿÈXrÖfOe\J§kXL8•_ĦƒG@¼lã$nzĬ#¢ˆ”ƒ<Äd‰ŽåM˜8¢Ýwÿü¶ã{´ÏágìpMûÄ'>Ö6ž²iF>ï¼ë–`N˜0“ÑR.EfÒá˜6„œC Ù(Tý„; S¼·Q𬠜@ÓªÜr£>‚.Ë¡-‚Âçà™ûqãG´;™Ûë1~ì¬6GñŽ;nl_üâ—ÛŽ;îÔ>öÑ϶k®½¸Mš8·=È*¾Oª¤E "i·Cm)ª9|äÆ_:ÜÞ’+Cµ‘8>÷?0ŸE~ßúÖ7·1cg·Çx±f5zéh‚ÑqC†‘&§‰LÛdlœÿ Úôö³c¿Š¼;0"<…7¶E‹îj]ô×öþ÷ÿW[¹ªáhÍÅ™§ÀGZÖ’Ÿ%½ù Áð‘‹™˜h“7…Svkûâa_n[m½u;è­d´úVÞБ{pº7Í–ó ™pÜV3ª=‘¼€4-YBXÍ4–ñí‘åkp’”½Â,xƒ•éÈàœ+£+}ΜÑ,ÓîB«Ìz]®¸ ŒzŒ³»)g]Jþ„qZÔø Èóà‚¶t)m“ ŒrÛ™+2ª¼y´iþ,9·§š¢W¥O‡vâÄQíÞûokÏzÖ>íxo;í´?´üà»2ƾÔvÚi§Ü§NSWØ _–½å–ÛÚ)§œÖÎ?ÿLÌÉmÂ8§˜¬ÅÙ¾©½åÍoo¯ÙÿUmΜÙmüøqè{I›?AûùÏOlÇû“6mêæÐJ§oùûÁöÌgîU;Ñô GOæ‘™»Aûùq'´ãO8¶yäy31+¶oœeÀ7u5±í@IDAT<²"»ÜüðÇÑiÿG›»é¶m…g?ûy±¡SOý¸ß o;R™‹þupuT¢ó(ŸºÒa ëTæe¹ÖÉ; ×âüOÚh8²y‘vØÐiäÉ tmH£'~lÓeÞC·³7Ù”ÉjDÜ!Gl0•g•jï­El Èðë·àKÐ#Wlo…UGƒk eö¬­Û:uK0î3feõªGÛðƒÛò•k€íä ­"Z µi)söܵ3i'M¤3”€1Ø4GfóŽÊpµkhéÎ ã”MxÂC€7ÖudIO¼uQ}˜!–ð°‘Ut2‘—¶ÆWÛfÉTæÂKeµ]]jœ4\L HxE^TyÒÉ\'yD•xÚ0¨;½-‚¯/Q÷Êe¾c7ðò)zÑòTR+]iˆ‹ ÆFö®nS—Ò'Ny"¶øÔÁj-Ží&›Œg÷¥›ÚK_úÊöõ¯…·“éh]×þþ÷+ƒ¡ƒòîwÌ|å]3eáÞ{ï'-Û÷-'‡¬\5QSnØÄc8ñƒ™ª5†Qm–wâÚŸøDFi‡ È´¨á8‹ o£ÏU«™[®™ §"Mž42Né¾ûîÇéÚI'ýº]}Í¥8Ý3ÛJæQ;µjjÛàÑ òFáŸN¯Rh˜GkhS—†wŠ ÓdòÆÒ<#°ú€'º}Œ²6”)Jv0V®ÀA‡†ùëuâFÕíåùò\ƒ/Ïž^ð‚ÐØ‘ŽÔâ8è¡Î×¶§=õil'ù¦ö›ßœÒÞøÆ×óa‹tæ¾ÿ½¶×¿þµØå’vã7¦³0„NÛ;lß¾ÿýo·m¶Ùº}ìcn;í¸;ìym¯½žÑ^üâµûî»4“š4ÚJn®’ÓÊNùüÓŸÎIØË_þ2:ƒ“YÐzÓŒœ¾RuÍcØßsŸûœöö·¿GÿGíSŸúxàM—exÞ¼Ûò±lpS¨,·ÚŠô³=•8z‚®§iÉÛžÕ¥…¼³°Nµ(=3451t¤•º9Á–_èqODw'!Äp›öÚ5à'´°ÆÚŠtéTÙB ª£ÃEG"ŽŠg£ù©ÇL‘E?©m ÀQë¾ãëj.Ò(‚WtxW=>ÆQ¹@GÛö°ocM[ì5mS¨q2 .fòÎÀ¦³Nd`I¦¦IتjSéÈŽ8`Jr} î 2†›Ð2]Š&þ„?žƒî“ñ /À :¢¾ÂÕaè„núgÅh‚B?4áù¤£‚×…§3b"€Žá¶Ý¨DÆ›þiI£¯.+:òº§<–Q!àJ'v¢/¢<è-¹ ¾‡´êJü@á¹ï¨4 C4Ë^À6¹¿øÚv/]Ñå|s±jõÁzî”?Nm ¤U°æl• ŸåYÖ¤"BW©˜ÐO"•A43V[ñÁgeÍ7<$xNìŸD¨£ ‚­my’²&jd3œÏÐH˜x§¿VfxaÈÛÇÄ«° ¹Ô V4 x‡SL‚+/‘V@‘[¡zã¬4@ÇðÕNNÒ"@Þe4Þsk&å 3s"¦½c ½<•ɉ)q l#+¯ð°òÔøË0 àU Uqð¶– ý’I¹%bè¿ÿ"ÿ2úÒ­DxF¤U«VáÄЈr ^ÎÒÛx…n˜€Ì“v^³Î:í8#¡ÃÛæ;"ùÀ}Ëq‡£8”ÑëeÌe_…sºa[I>x8S&î¾{I›µq}•óîÅСÓù3zX›4y ýšvß=·#·©à8b·øNöîÆÑ7~8SZ['ÏW+ë‘õ„Nj—\r)S&æ+9ÁF'3Bû`d0½ÉA’ª#4köDÕØnŸ¿$ŽÇHÐ$¦3‚éËÚïf<´6lw1½BÝôZ\½Šžp Åy3zdæî¯dÎ÷`’ú'|Fƪñmþ‚šòÅÃ>ǨüFí€ýߨ~ê¯C£?qÄwÚ;ßùŽvôÑ?ko~ó ;£­ÀŸ”EÆÈvÏÒ¶#ߣMÛÒGØ }EäŸãر#Ñߘ²·û—c#ã2Ÿÿ~lϹü:Ö66<ÓgŒ£34y–¢;ßðæŽrVW¢§8€ÀzXAÏŸ{›;wv¤!“Ò&í/ß«}ä£hoxÃë uдw½ë}|IóÍíâ‹/¡óùÔgÝåŠ+®Œƒ~Ö™ç´sέð)ßÒ¥µ¿ðÕíâ¿ð~®CÊÝÎËrgÝyá…·§>uOž-tæ8&o´U{ù~{Ó¹øŽíû{>vsTòÝüïÓ5nùóð#m$v蔸{±…åäWül¸G©‡F ÔfN‡Þþ[ËÂô±c}󲊩uËR÷l4yt[òPkûðjÞ\m׎9æÊÖâ6vü0¦­NGxòBû¼—üBçÌò»†ÎÚÝ‹)?ð±Œ9Ø0w“Ét˜–Ñ’ζuÇðÃȯ È›%ä׆È366³bÅ Êäx:kè=”<ªê™ºyå锤{ï]’:gÓɼ[ƒlKketuÎ9çSg¼µ}ä#¤ðÃØ¬yýà«Úf¬Õxø‘åÈI;[†-¾kë|Æ$ݮɉ®°©ÔÝð´£2uc×qlѰa¤—?Œ”KÒ`FÛ%þ´ÛÄA¯Ä¬x¡¥c½_Š¿÷‘Ã*»ª `d੃©ðÀE7U°½)´V›lk¯ói« öølGd„ŒÊ-¥¨³Ï,·Æ b¯§¶'E¨GýÄ™7ž#ø¡m¸â]{šÑb'{’©Ä,~–g7jÂJâ‚ó̯‰>d%L¦%å*¦p @Þž}ÛÕë'ÝÛæ/$C]hþT(ÂÛÖ »ÎáI}E N^9Ä/úTév@!ùª+„Há'LÅ·K·Ž& B%©JÒG‘À%=¦C)‹}À¸ðèˆ0¶¨J£ø†¹‰Qs¹-ÚàèWË ”Ç|ºÜæ^LíÞ®d"ÇæÕ±zVZ….ªëá€Â\;ù£HɨWìD²ááµìbcD5…{<Þ•¬"ú^<}õ_vûï:, €’f H9ÏÊ•4+¸´,ÇÒÀ0oÔlY˜>€¡†¥ÌËC´NCëä¹TŽ4B¯ž ±Gyš'T|Ç Nj}"4̼GP[Î|øK:xWÓl¤‰Qr à6]‘–ÇN¬¢R »B-<9€ËT ÈW手iíàåÑëÏ çè+éF¶(¾*´BU‰¸u†UdTžGáZž"y`×…KH;I¡¬ –ò‹„2–±1. °]¡æ¹FŠSè…§ÒWÚd s$‘’¨TYÌ“Êã^ƒB¯+Hé%±Ê™¤GÞèÊ…Ʊ¬ª<¬ 5Båìh’Ç>%yyòÙ_/[Á˜NÁEÃ+¿¤»°o¼aQ(8b5ªÇ-·^Ó¦OÛ²-ºë~œý Ìg^ÔîÇ1íÛÞ[ç OÜh4æR¦¹ŒËè·£FÎ`±äµ=x;nVFö–²¸rÉC —Óvßÿ@=N™²e`œÿ›`oGÁãúë¯`”u—ö³Ÿgª©Sg"gñ˜Êô‹Z¬[:y”†~ãÇ´ ®ü„ñ³qHW2E`ÔÞ÷¾÷dôß}_øyóÿÁë,œ»š>qÂ:'Žp²ˆ•‘•Ù‚nþùÖè Ò‰p:í÷×]÷÷gÞy7÷|útòo‹U»QØûî»?õÄÅ_ØU+WÓi{¤ÝxSÍ%/ºu;zf{‡o*:\|÷-Œd¯‹]Œ,îô·ñÆèý ŽS¯ß¶¾~ç—}ùÆaôˆQÈm©ntˆ<—tò<¸dyÅ1c‡áÞÅ›ùó´paÝÄÚ Þ Ü{ŸÓ¾¬Ó6hS§%O?¯ÿê«+/\´[yX¶.•”×u„Œà§#¾²ýú¿OÈo1 Ü›7þpkvœ"ßžþôWÓx{°;Ç8˜£Ûå—_ÜÞðúƒÛß.ýs{ßûß5Ѐ PP꾿¸úöF¾;Úœvd8« ýð‡ßÉÔ¤SO=¹½ì¥/IÀD™R+®¸8×þ4bÄL¦­ÌÚkê ãGæíÒmó®ëA˜ÖèÔãŒé[¥cõpçL/_¾<ŽüÂ…¥× 7ؘ…µf-Ä‚ÛËN{B÷wýš3¶jw-Z_ËÃÝmÙÍ]¦õ€ë]gÍÜ›ZFgt唓°÷/Ó‘EÌ’¼­qZÖPä¾ù–«ï©·åÁƒ¦ñ¨êš&ÎIý iÒ䥅»ß¼1ØnÞT¦j §jÔQ Ö7ÀÄ¡óëÂYë{«ì‚¨sr>ÕtNq”´ãøï]›RN´±M*ÞÏD¤®ç±B¼AîÀ*ží0<[ÞÒ‚ –x-¦5­ÙÂË#œËW¨çþÞ„ ÍUA;‘¼À€Gÿl%9‡·0â"¤ê-¼AI€?a(Lù(§t,p‡ÔAš¿HVÈi»zDâ½ü¦®ÞôjÚ½ú#IžrB=³(ŠopåkÚ„:8œ„HrKèAa$%mŸ 1’yê ’ØEh‡üÍ?Ã‰Ž„Üg÷ÅЭ°ÒÞàPO§ÀôB°ï h‚Q]’¡\JeNó¶“7äNÌSÝEË@k7JÒù^£ §q¤ÎNZò™.éȪ×A“TdÑ¿4r}{çYV‚Dx£¹íGëÍõ"Õ´&N§3,*ýè¼¾ j¡:|Š2Ü)£¼ C´?;þÚšrGŸ‘H¼¢Ú–Թ#–£Ò@™'IqúÐHQm¦üø’¡c~âæmžJ‘¿Á5â_ E „BÀ"3VFˆ#0,u ÛÁ Ÿî«sÃ|«—h‹‚¯ÓjZ:‡3° ˆ<¡Ÿ‚¬Q€“að»¥ÐA—vW‘D“Å¢FAÔ²u„ÅP)Ê£‚ –W®dà!ᦋHîןƓŠÍø uºà^.ý¡XH!¤<ùÃ!² H7Ów€‰È©|­•PÓ›?Å+yC'dH^TOáÝÇ»ÇÚ p#ƒ–Z‹+«‡œâ ÒžÄWºÕ¯:‰B´„ÈCŠÔ•z‚‡ôR0ÃÍ9z“k ê[)ŒFï3G"Ž7¼ñ¥íÅ/za›Â„Gªÿó¥o¾å–öÞ÷þó’·¡ñ-'úG?:ºí²ËÎŒÄ Ãz˜¹ì3*ù^œ±»ÛܹÛáH_×=ô“ÜÏio}ë[Ú7¿ùí8ºçžû猤n4q6Rßݾýíï3}ewF GÄɸ›–ÿ8çBŒâ0ÕâMÍ)S6F^Ý;ûÖ[okÿõ_ïn¿ãÝí »ïÖ>þñ/ÑxßÄ´ˆ£pbîejġȿ9 F¤QÉäÉ#ã¸~îs‡eÎ;Þñ6ænçÇžÔ>ù©CÚæ›o–i5÷㈞qÆÛ—¿ü…6fÔŒ6ši6ëŽÒѾû¾Š7 3ÛI¿8¥Ýƒ1z丌VŽ3ggAÛ~»=ÚÞû<‹·'_Êî/Ž„/¼½œ”‘#F2 ùŽòC8¯:'­sÎ9|±tç¶éÜp‚®j[m3›¯™¾³ýõ¯“ÞSèTÌadô1œpÁáíSŸü£¦w´£ùQðS©`·Í»2S¥ìLŒ7ŽÜêvë-·¶~äómÞ‚«IÏ̶äÁ‡3Çü©O}j:Gù-¬ÅíðÃàmÌøöÉOÂöèl c^ù{u_Î4™ýqgºÎÿÄq›µo÷ómk¦¹ ¥ã®4N©ùú׿ƒ œC‡Å¢¾m¹×N;îÙ>ñÉG¿:¨1þçóÎg½ÉG‘}ÓyÆÿyî¼ó.Â~ÜÎ=÷Læm'‰íÇØÛÎÿÖÞóÔ7møfçPçÿ•¯|m{Ó›_ϨéÑ›6ñìì¶[çS|(½½íC:eÝúŒcÌØ™¬#Û–ãøctzã©Û¶K/ý ÷­m‹-6̈#è˜w¶,ö-ýÃËV’®•”®Mx›rIòsÑ¢Êï q’ï¦ÛÙÁØý Ûàp¯ŒŠR¥v:n¾1ꞺŽÚæ›ÍämÏ£Ø×jÞ†fªÞ¦ FžQÎ6ý™O@¯µ¯|åëmÏ=÷ ¾1Z‡cÛ‰'þŒÿ-xù0ÓÆ§þyå~´7¿å „o<§Jù6е{íµw{Ç;Þ‚ó?šúiè€Üo|ãûˆ}°ýô§?kW^y6õÛöË_}2>ºö…/cÿSHk1Žÿ ºšMGý1ZȵØÅ0Þ Ík¯xÅk±µ‰¤íXFdGd(°›g}>ê¼èbW{@]MDZ'óg <ùeNëÙÔ(7ÀÛn :âÞêÅA“áÚoè'\¨CÀ–\4,$„Ã7¯îV#”Ⴈ¤B6?òÎ —š¢bZ$ŠäÑé÷m<Ø«4Š2†iP…N°­lJ´”JlQ|*ñÕÏ&¬“› ã_â½æ¾ §}ŒÏ¤.ÍÐðÃKP~^ RC…%ÜzçtGà’Iý^f\“0‚º¿rÀ ·0äœøòQ}$Æü|KHžÐÏxçQºÁ­¼!j¸ïÀ„c例S®ìÙï3÷fOò€+VÅYX~ã“PâêPæ’@[§rÕ§ðLºèÀ™¾ѵž.ùe†…Páɶšû]ú*ÄÈä>tÕ“¸rÔ÷’Ÿ0üÊgDgÜ‹T® œwÄ/¡*‹Nÿ˜¾ÞV‚ϳ Æ¥,’1ã”#Gi< WÙ«ò,’œzªð¼’ŸrGfâ½ç'„G¡†+¢É­brî€ ‹èÄ ï½yÉ›¼B\¹fqO”Æ×,¡4‚ÊN¨bøQV‘‹¤Qsøú§r:ÍÐ2Ì@:§É—…Ûî;®^‰Ñ«1@ž\t´r˜¡xù³€*PgHÙËy¤]ÓjÀ±'®‚%Ë)hÈoª,ŇY2â–ê7Æ{ƒ£íxéó‚^•ÁÇŽ’|ú4ª™ÊL! CðO½y5Ó¹Ï/n¿üå¯ÛA½…Qø) ÷tÿ p”þÜœ[íZƒÛoŸÏˆÝ"¾à¹eûÖ·¾ÎÜø÷vôè1lŸ91²(Ï„ “˜ª0.q»î¶+#²/¤c25Ï;ì°Cäðáž{o§ì0îç'ÞŽÈvÛm—ûE‹nÄqÙ¿zÚ¯pPžÌ[€»ãÈê zèGqîÕ–=r#¥–…:úÑóMq¼>óÙOàX½ˆ¥L#±¢2ÜhRééㇾ¿}ð|tË'´#¿û«äÓË^þ’¹ø’óqR¯gG™‡“G;lÿœö2·ûÙ8g±‚¶õÖ›Ñáz‹;÷ ΄‰cxkâH0SÚòvð;ßÖö{å˸/xœjñÛßžJ'ìýqìÍ—eŒTïó¼}Ú¹çJ‡â•¤g!ÓqFáNÄ¡sô}œ¤qÑï=÷<Èhö¶mß}_œéV®µØu×I? ‘pþW¯¹³M²M»à¢SÛó_ð<¦´,MžÝ{ÏÝtìžÆŽ£Û“÷|6ÎÿͼÙ$ÎÿþLy:õ´“Û“Ÿ¼'žÒc˜–ñ¡Èjc«ã3~üF“gœòÑQò˜={ÇvÕ•×´Wü[{»00÷1ì¼éf“±ŸÛg?{£â?l;ÏwÞ¹ˆŽÒÂØéÛÞþ–tŠÒà³+bý½eŠ{KµkUtþ=fÑÙsº’Ç7Ü”çO}ŠN;;]sí¥¼¡¸…¢·¶m±å: ;Ðaz~;øàw ‡]ƒ“òFY½èB;Ï+Ú¥—]ÈbÞËqø/o×òózÝuõ&&ë”'2ÙnRd¯½öò¶ÉÔíÒ‘õ-އë|c·çž{¶ŸŸðÖ‘LÂæï‰ƒú¶·ÔÎ:ëO@-Í:ÔÍqË3Ú‡>ô8övàî½÷Þ¬…°ãý‘ ÌýqŒÇSöìäkûãÇM <Ï «îàmÄÛWÿo¸¦óVæöè{úôMÚ×¾öYç_n[mµ9ë`^Ú9äƒt0?†£=)åm옱íý,Êþò—¿Ö~ýëZg!mŹëfœ6ç[À­·™–rs衟Içb‹-¶€çÂüfÏžÍ@Â7èÄ~SvÈ8&Sˆ|à”´ñã'Ð!î§]Êz Î;ÿd: ÏH§ägžÚ8àUí ‡}:4–òfrìØ¡LÉB§¾^G|éKŸÅ_JüÒLÃë–?AîhegûbÝìæ¶,Ž@{²Þ·µæG/†y<žjô‘ëüà'ªðÞÁ‰ðÔ°ÒðèèdKФYÏ0ByNÏC¸ŽgÜðÈ t*Ò¾ƒ°´r³M RµMám[ UÛ*žÝѯFl-AÊ_xÒ«8ÛqŸÌ©ÊJœéäò@R¯†‘I˜P ‡gÚÇèÆetZ@tصqqФŒó7·¥óW`òÂÏ\Y'Cà“ö‚íDé42º¶iéôAÞKÇ´ÊN°àqêÓX¾—x¦ªp½WŠþgl/O$ ±NöÎo0¨hx®{;YBÊF%hŸ@}|n»S—~åU@Œ«ò¿ò¦jC@‰ kèT‡V KÖžšñR‹ö •)7”çr± Pè+޾¶#rtX¸qÊÑYxgšýE½=ÉGú}š$~ÒÚr$N/}… SGQ´¢wÄ]n‘H©z®´ÝßN>¡ÆÄhhš{¢¹B¹+аRyhK·h,lgOT1=O;}–’w¬_%ÈPVº——T ·’a…Žu^ìxX0ƒ¯€ù1pÌé*¡ÏS¼ê²CNñ¬Ðð¥IÑIJ²¡a¡2U€’ÊÇ#¯n,ð¬I5„ãì—rͦê¹C"R@ Xø™Ö(E! H‘FàS¹TæJ÷I`%…Q:ý&ë*ˆÓ˜xH:Ô®i0(iéG¢3ÓÔñî^Ó b—‰•£²™c•¦¼Þ_*:B•KŠ!%¹Ü™)u Po(^˜T^C†C]>ˆ–ƒÓÕH·lHšz-`Àr82äqâ ¿mßýÞ·pP®Ç©XS·GÂgÎÜšÆö†ö»ßÍbÊím½³ýêäçéÃþxûô§ͨݛÞôú„;ïyҤ߮}ö3_h‡íKLš•8G÷t ?ÿ¹/¶Ã¾øÙ„õ§… ñ&âuí»ßý&‹*š…•ò<ù‰=XœžÕ«Ù>G}süŠŽÆç>ÿéöùÏ)ކóƹÿÁÇÚ>ÿå8;vF<µ¹8 ‡eîð¬YO"¤¦¦ç|üW½ê•q„¾ò•à ÊÑ|qÄWÛNûÇñ•œÏ¿þµo¶/å ÐûìóFGÚ¾ð…Ïàtÿ Úÿd÷šWâtÙÉz#¸ïmýõÜÀ?ùÉ»eDÿ©O}J;óg#ó«¾)otn›wg;éWGñæÄ¹ñ´?sZâ<½èEûÁã˜ö¾«]´ßŸ˜ÿ]ó¸>ÿùOņ6Ýtî¬7't2ú}EûÒ—ÏbÙ×¼f¿õäyòœÓœúáqüñGâlioïÂÞŽO˜§µ·[n}°=÷9/nïy÷;éÈ-Ȩõ07?ûéqtš^‘a瘯;\¬î A£S¶_ÅÜ{_]O9å÷¤y:o¾—€oû¨ö¬gí•NâYD­s}æn×ßxùÀš-¶Ø1óÊW0ÕËòe~pàÞtH¶Á›©*Ú¦¥ÎéKwÜqW;ûì?ðTusú=ÖŸ:çô¸ñc·h¿;õØäÿ‰'þ*0¦ÇNÀ{<§ùFö?•pOßÿþQ픥|䌰—]uÔOÚ>û<·ýøÇG3R~Ь7×]w=Ïw·ÿ=„ßäwê©§³P}—öÄ=ž0û’2zþyazÔ³½9ó̳ÛÅî?úÑ÷é_Mý³6Jóü‹ë•÷sÏ=Ù>È´¾ÛûÞû¡vâ/~6@ëvÞš9Ò‰?m×ýãïtb_•]œ„}ÊS,³ëéXïœþ‡3Ûï~÷ëü,k»ïîù^î ÐßätævÛm7Êá_Úk^õ–vó­5e¤=“Á稓\`=‘Ž·ïg—,Y@~:¶ÿóŸWç:–µtº]ïdM›º;íµ7xÜ“Áii{j†02Þ¼Oû’ºË¶"­jì¡wlêAHë¯=îýËàø¶}þÕ¼éLf =Ã(î"s’¿÷¾õWâ’±ÚÍ@Y \…/Ÿ€!6ñÃ8DZ2$=çÖK§v$ «ut¤ésXC22»VG3ø5ÚnÚÂ_pÜ9ÎnUiVö‚5µ9 ‹HųB¯2’imøŽÑn‡_Ó¥z}K#q\£Ü°ÇŒ5*Nz+ŠdÄ×U Ê[ö¬&*ã—v"ê.%'Aqp8z‰6´ÕÊ+§nùJSd°É¯:WóÝ8AJ·)S†øIš‚Ñ`©$hHº“ êáU´™€ø&Ögî‹u…™Èäs'-).ôÄ6L»sLŽüâÒrôÕôQDŸ «ƒp®ÊД–ªï"xæ^cų…Nwd6Dæïø¨ÒL"åH‡xÐg†è'øFÅUÓš&¤—F0b©àîúp‘°@-|¡g¡©Œ‡¯âz½IÒÂOš±æA±hÓ yE^^rí’ lÉF0¥[ rˆˆÈ¤á¬«XÑ*oz-žÃ$v‡qI71ìì"׃3dãM&&B‡eâØvÛÝâü;Ÿ}ûí·o?øþãüo³ÍNŒ Îjsçlƒ3ýÅ8COúÓÀp´Í·'娞tÒ¯âüo±ùŽm[>z؉¸ä’¿ÅùŸ5s«6gÎö4°[&î²K/k³UÄÝáW#¯%O´Á‚Äê”h§*ÇÅ‚G|ëkÙÍeŸ}ž“gGE×tÎÝÞ„¹ÓËw¾óÄ}뻡ߨ½û=äy#Ž;0‡X§sdãÞtÓM8/¬§Òý:-Ÿwþm‹Í7oÏ{ÞK=½•) c€ZÇtâĉí4œ&-·Ø¹øºÚ·Žø#ŠcYDz0S ŽÁ±›×þüçóé4}…‹óÛ¼ù×ÒA©éFVNë¨ "1u庄¸p©ÓÉ'ÿ:ÎÿöÛíÆ[„]Ûv{JûãËhìÛ–[nÁT©Oeý„ÐŽ’bNŒZÏ)dÎ~ôÊ©XóæÍpþgÏÞ¦Ý6oa`”ÿ8#ÎÿN;=‘)[>‚NÍÉÁÙzëÊ?wmúÖ·¾Gü4:_în»>™|³ó6¸½úÕûå-’SÈúcܸÇËsç]7³ÏÁmíÑdÿ­·Þ=ÏYÏÞÎf.¾öVS©~ç[y[1¸½tßׇ쮻î=h_v(¯ºêê8â½Ã/ŽöìÙ3ÛÕW_“N¯Í믿¾]sõµt$nÏBßãŽ;ž·=ïaäëöë/¥Ã³?[ƒ^Àˆû“Úa‡}Ž)M§ã8ÿÿ›éG¶›o¾[{0‹b{£GŠã{ì±GcƒG¦ï´ïóóú£IçÍ‘yòäM³öf÷ÝwÍ4eQ&×\smûÇ d{˯ÑÑs=€‡vî®PùË…qþ7ßlû¦¾=ÞÉÛ¢eË–‘Žzö›/zñ ÑÅUqþ ·ýv»ãœWü^ÿŽt”¿üUßÔ1|8‹u©«,ëÆÖÛ6?@¤wþÝNx§Ê)wG¢|·qo G]“éb—_þ÷è`3ä{⟚¸K/½<×ßÿþqþwÞy:%Ë 7Ü@™,~|ð[™Ê´bÀùŸ3{Ûlûiœo—3]í ·OÃÔÉØ1cÚþ¯yƒÔ¥ÓYs4?»d¹ŽãyÏß;Îÿ[ìDìxlõÓ¼ÁZœÎ‘ðîDTNJ£œïé…Õ¹ra½ Ô©l`Sß[Û†Ùrâ—?n3@cýOH—vÈêÄ6€ŸeQ:—º†Bç2m‰|¨ŒõHMÄ)<¬ˆp“¶LñáÑx¡ãTÉÛ€õèûh`ÚHœ2§ÀÇö5õ®m²UD®ò‹óÏU\ÛiSŽa¦ÇÖ¬äW ˆ˜!½ø„veGAغB 5Ê×tÇ –r  ¸'Þ¼ÈWtC˜6QZ50ZáÅ9ƒ+ßHƒ:‹‡éó‡M‘~óLNI‡d£>|p.©ƒ½R–låÞÔ˜Wõ+iªgœÑê[ï•Ápô;ú¼çºÖmÆJPð½h% (½Z²U“¼Ä·NÅ,Durð˜4r£HC'2„¸±ê¸KCì"H„wz†Tü {Ó²õ\¼Ä*ŸßÀ_Xƒ…#ãð¬Ý'¤=>mp€ €¸¦³K_â€S}òç?ù‘4š’Òn§™E_eµÄ¦“„tè:¢vtLARhÚ}àÐþÌÿØiø$Í<*Ǿl'¶‰¬¦5:OzJ×ÚPuÂ鎨 5Ôé¹|:iR6Ò+0UþdæêoÕ‰:‰'š@E°VN¢™S h¯ãª0U@¥ËsX”ÂTož£B¢bõE8ÿ]^ð\ªD¥Èped•0¥±¢ <Í‚«… R|@ .FHCŠ.Ý…KŽH ?©º5§Á3ÞuüÄ >Ñ¥ïžffuy¤Oú4òÛÀQõ…‘g*9Ú#‰æ Œê€É•ìUÖÈÂ÷%YéØ'î8Èà®ãTië¤Ñ I¼©©Cç°RVÒÜWœ)D1»#Ï¥%% žFÇU{Å»îΧ~‹Nï£Gε°FðùÏÅÙ^ÙýÄQ„²MáÂÕ¼_ÍZ¡ãT\Ë«÷1ìG¿ž‡á8<ðÀƒí¨#Éó°ly碇ڈa3Aÿx{Æ3tÞ˜Z´ðFœ­k™³=iÞÊÜã’oÑé¿È'¼O(½Ó_˜Á ‹/þÎüæí9Ï~!»ðüÇú:¦×¼¸m¶Ù¦Ù¹¥Çs®±SŽN?ý7mÚ”m™çýóªn[oµ}@ÜÞ9ƳfìУ<îúóŸŸ”<ÝÿýîSç=ï¹ìŽó`ûìç>™gõ=—ÎÍû™4kÖÌöñ}’ÑÉS™S|:ÿø!í¦•xà›qBÿœÿqªÌ낈ևÙÍK?î8õÌ’Qvƹá†Û™³_#ñ?ýé/á÷@ÖlôxýÛ wGê[_vYˆêD.\ðÑ#Ù>t‹öÚbšD½¸êª¿15cI{ oqw?üʇ¢æ6Îåw:ÎÄ sqŠï$} øÎÄ\&·^so¾ƒ¾Kú7Pý"NŸ½­ÐÞ=’§ñmñ¢•YÈúØ£ëìMïu–L;í´龑„.§ãµS»òŠÛy^Än8ÕAø#o5¤?|ذðìO§t¸\gáÏ:c Sœœ¢voºA1lóÛW0­g·vÓÍ—eÊÖsžó’tìþv饩žóìg±0ýGä¯oGþɹGÂÂoVò¡‡Ÿw"#òGòM‰cpú2ðsíŠo<î¿o5gê™h ÒdÅ ëc~ó›ß¶½ð•¡Þa‡ÝƒãË„i÷°[´èÞÜÓ¥çê¶›Ö'©ioç-ÜHÖü9Ïc™víu·µy·.f­Ìæí²ËÏ£³ÆêÌ('k"¿°˜7 ÏLÙøÛßê ×–[îÜ®½f!å~ ¿þú㽘n(à¸: ÷°3˜‡Ûº>ÌŽEvp<fGžØ…*ˆmTƒ >o·Ý¶¼E»6QÛm÷$Ê÷RÄ?LùªŽä"ìÍ)„ý¡N†ÞvÛ­âG-Xöü¶g ž;Í3#hJ8ýèiOÛ›M®cc«é¸îº—þíÒÀ̳r’O4$¦-õ«1>ä©®Õ k(m'ð¹·n6mMœ]Âõ.W™A89b.Nl·m×ʪ@æð›yØNéXؾ¤ã>Î,D¬Fªëëhch‘ŠÈj{f… a±A°ùåØgÍÈLé¨Î­[1ØèD™Ò¢œ,L ´ä.Å ¼ØôÒéÌHÐë'0ùqÆAª)VÀÓZ×&X|þeGk@¢ÍðêÛ;<—šá l9ÐJf<° S"òGZÜEnå7ÞÂÊa*+%Gˆz.xýÛ€;šq#(|¥“´ëq;”+︻ôëç98ëÀbÉkžkKê{éyxíåõ9)1¼‚Ͻ ’&5¢Ž¹(†—äƒáʨ,PÜøðñAØÒMø.ÍúS*ðCVRW&–‚´àtbߥ ÀDòW܃½«cƒã‡*—¡I{^Ζ¯’³àEœ×ÜçFh…οT¹MŠŠGBJŒØ\`‡ÆÐøÝœMCd¾x5¹Ú\¥ÞXäÁ4aŠœ<“/úð¯"æXìSÀMBÔ“ÄD4ñCÀH!KPcˆØj \Ÿ,Ðq%ch8æGñ‚ð—îŒ}ò¿ µRû¨øÒGÌà'8:¥”é@Ÿ{¥P1I”—»Ð!L…ÈKù¼—@½rÈCÞÈ®‘ío€‘±„GyòðÆ{ÿ‰P™¹'\õ'¾þENq”)B42C7Ù¢ÜÒ2Ìä“¶DMaЪ#ÞÁ©—L½ Ú¤i*ªîkÔ¥!‚a¤F&éÊÏg)’fÉoe«Âg¼Âq~½IZíį{ȞĶi@äP<þïqhz6‚Åy“&mD#|ZÒ^²£ªŽ?–ùØs訽óûïºÇÆ}-»Þ0Ua°ÛTe±äÅíe/{ ÎÛþmΜYYtꨴ»Ç¸V@yÈ Qì ^Nlqyü9)@_Õë¶ÐÚ/N<9s°_÷úýÛÙ,–ôxݯÉ4Ÿýô„<{Ò!Úl³¹8-× މ„ ir·!§Ô8ò¹ûÛµÛ︦ÓoiÂQ}GÖ]ê(°Ç•W^Ü6Ût7 Ž–£°ÝvO˜Û½Ù¦;°]é-í;LkZÿø Sqþë½ïÊÈèÕWý#zqäò?fâã§#8’}Í ñN,;³3ZjGi"rþ=#§ë¶º¬ÏÕ ääÔ8ª­Zµ"Ï+pZÙ©‘_¿°ŒßÍíÝïz?#ÈÏ'6f4x $ÇÄù…“í· úc ó»W¬(xC¦¸lH¾:œ¹é«XŒ<’‘ld½árœºêô6¿îÊ»…ÇÙ–jÙ0Ó¹ ØÛ„qmÃvâ„ t4nÉ} Ê–­°KÇ|xÍ…Ñë¯ëÐyÖáÝygGÿý1sƶÙó~v­ºþzG¬GóÖ`6»í\_õä=ŸÃ´C™cþÖ½•iNÆù&ÍÀ;>„§{ðsÕ–v£åW¶½öªQòØ”)»O­é~ÿî¯ï›:ìP ¶Ô»­Í™;+#ã7ÝTzª—ßÏøgÁÔ2;í›o>5OEÝ‹»:‰T³mï’¥:â›s?²ÝÞ<ÜösÈ0m°ïŒóN ]?å){R>öbkàGR_ôN§Î8í©ë_å«òkû»ܯ+ 3¢7 ¸’5!.@OÝÝQq1úܹsý~B¦ó[DÝS-¶ÛnÃ33÷Ó!c+Oþ2u0·=]Æö¿cÇÕ›É_žôëŒö¿éM¯m\pfðÞö¶7¤¾øÝï«>±Ít Q§ÿhÊœ:«ë$Æ|H¢Œ ëëjKÄ0”?׺øT<¡¬ãÓJT94¨4ÁYêpKùš-Ws¾©iuƳ}ª6Gßf)´C0|ÂN¦ühO`‘‘\â È}ÉeZ‹¯"(u' wn‰hHÜçš ËS”Ë6!åI © HúFpw5³µÌ ›eÄYƒPo+ª3í&tL¹á r­û´ÃxŽ™ö‚v„ˆ/¾Dø‹©dÒà@?÷AÈ™âám‚l“½á'!9×S‰¯a;oˆ}þ‡Æ¤Bò“¿í¸ÿú`Jc™m¿ôç8¹nH¸:ßÕI#á!×é®K›t£êiƒÍç-¤æ)ô"Wž8™öðVžžF/‹éÆçŠS®JT„Hþˆy–»øb)¡L˜²Fb"Ï)âfdO¹ãcþFãtœxRséx™—$À4=B Õó¨\Ž^FŒ~Vt¡N拈ږ7ú½LZ°Z±SUy³îí@Ùƒ8%Y%¹l~`D?2«/S[é©ÎaÈ‘N“ YJõ†|ξ–žÇp ±äa9ŒÑC—YÅ1µpA¸7ŽP“h¤”‚‡D*qšaUJ fb5Hà9¹0×¢pîäœøS=Ä%ðÄñ•…¸Òx°ÖÉ|-ÙI”!+-ÿü÷§}Ô³ø¦Ò'MVfÒ—2Ôa˜ .§Ú “†g{ae„QŠŽ ;i<>Ÿ ”0:uÒe€Døo¿¢.wî:Y šjËÐG! çЈ\¦#rv0œÆ¹(2 —o–„Q]Úò,ªz1¿¬T”C¡ÁÅ#¸u[Äwò÷E>±¢­w<­ïuèW¬XÞÎ;ïÏÄÐ åYx¯~~àØñJ×Ö1’·Ó¦fÄÿºöÕ¯~ƒ©6oÌT›nº™×ë÷à@¬lßþæÑíkßü4£v»æcO!ô¯§RrR›‚–·¹swh`DÿÖ[?žùÐ=Ú÷Ø=Îú¹>½Í™½#‡×åHÊzÖYgáÌÔqŸG£V±¶À7-˜¿0dª“QM·ÇYgþ©½ëݳ#ÑY„¨#ÿf: ÃÛÉ¿:%ñîSÿŒ§ï…·gŸy£ß32ÍÇ’è´¥{?Ì>óLABw‡ò~v®9€w.N*²ß£³ã,r¯°=3¤1€JvTYç\LwIž±Å&^€;¢ô,ÿ×£/?ùÚÒyí¿øUœ#f;?¢¿‡˜^ò¾÷}“ŽÎï3ÚºŽhÙ„Ï:9v,j$›}áGfAò‚€þO9Ö ¶ÎÞÎößÛ›»Åœ{îù¡UŸÂ·Ì™gŽ®T¾jÖÿjáEWÆΠcÃW‘ù¦Áö™·¨Þ|`E{ˆu“6ÙžòÔýXãp_»øo—í)u€¥}Ñ_ÏnÏyÎÙYëá””M¦îÐî\Lç‘Dú¦ïÏ6öyr¦°= Òo'/õã-·Xn¬÷¯Ñê¹s¶ÃVãÛkØæuH~«ùðÞÂ;â Ò$Å8útZ×VclTG¿S´r¬Ï·â)»¼ rm‰‡åX¸Ñ£‡âð/*Ëé­—yÕÀ«õ²S;ƒ6ÂCéh›ï}¹©Æ¸ä9œ`ÞõÌK‡î®tƧ3}oÂzõ‹¢lˆü)¹­¶Ú˜´-ê)òÕó‰m›Ü÷à 4¨3½1Ö¢1¥gò¤ÍÛ)¿ýeûÄmm{>©:öÂ<ýéOaÁûBº÷1f1úÏ·'À‹bÒ^p]ÐjX-óWr¶Våž«ž®/ï®ö¤4¨ÛªÝ“¦ñÅF jÑGµlûeûàH¶4eTm@nvÁ? FÃF>Ð €'„)¸Ê¯8Ù‰£-ÕáM½ ¾²£o}†Ês½Ê›4•Ѷ©:uðQ>%ä)+¡“˜špõ(q¶æ5=GJ¶Ä%›3„²Sb<·´ÉžDäšdp mÃtÜx€©8R3ñÜ"‹&Ñ×ÔúM☪â("‡(¦‹Ûä£uK$ªÈý5y*—úrH•ñØÉâè´¬‘¦”ÄS¾rÚ+ï !"eVåAI]‡4^^yªìA‹4«ë’‚€¢éå0¼âòØGçò‰¯hŠ¥LEKÚ¶åíÉŸº¦h ÙñÉÜÙ0»0IXXñŒÊ¹äé¢Tå¤b½7?Ê®ÁIž‡-p±½G·¥ €ø&^= Rå™ü$Jù!µäM¤YvV yÅ÷¨mWM`:¤áá=9}j‹ÖKÒ⇙ï€Á¦ÃIš€}iŠ òŠ2ú8Óª|Å_œÁ:•á¹Ö!KÅÊE\ + åÞ¤ä0¬Ð¨zë‰%×´wH ·ì˜¶B3ÃC<| K¡OäºT—2Ä p¤‘R®òB#±RˆÒr >ñ}¬øÁÒi4Q4$Ç)O>‘A[ÙúizÒ8ã¼áÌ–Ž…éKaqä‚}ÁR‡}áφ!4Š8ƒìHØ ÖeRGcUzõ! ¹Eƒ—TWU®JaAñdx2=DúÔ#ŸÏ“Þ(Pþ›îô{¾ æ”Þa¥({‰”DÔõžs[•´ôALݯ7€ƒLæ›±p슂³œí ÇþŸ1섲E¢ûJ§`×°ÛÌ(¶½’¹é{ežý-l/ú¤'9/üñG9jëËTñ½<ýÕPïû)Jc˜ÎàqöÙç´÷¼ç]í5Ìý%Û2šâ‰'%n,sÍsþ»Ç¸Ê>fã´×Èàú0óQ%+‡C?qx{ýdNøóÓØk¯§g{Îcû1#¨;âÐ]ݾ÷ý¯0¿zçýpJ.ÍVŸ ™º°!öºÃŽ3ÚUW/jcjó—§N6IÉïíÛr8†·‘ÃØªP;XïÐa³ã±å–3Ø‘æٵŽãýˆÚƒ ñµ-ø„ÿÍXEÚÊëñ´Ö·!§åÌ™½¦kÓÉÙwßeúÒk^óÊ:ý°ëÓr¤Ý·=#ø"ï lǯDΚÉVŽtßú–w²µë”öË“~Û‘0ÁëlÎ@ÇÿÝÞ¦ )xwŽ]‹©‡òu×á|7a5Îù8>\vþà´M6f$—ÑnôõïŽ|ÑGØe#«ysõÀ+ùêòcÍb=ôÈm¤c§öõ¯}µ]ÃõŒò¿ùåÓyãp7€ Ø_~(sןÆô© òb&ß~Øy—­Ú§ûöÈÃNŸvÃ^N>~»­Y·û…êM¦—ífªf!Ö¯ÓúóKº«Ùjô~¾-|JwW>« <§Ô“}9¯›W[n¹Y†³£ÁnPc™þŨ¶‡oà/¾çÿö<[Ž-gkøê³Ç-|ãb_ž9ÑvwÒ†ïît~ ÌcÎÜÙL×ZÊN;g±æãµ S6 ùo²ƒÿµûù'kMË·n@IDATnoý¨oRþÓ±)oöÆ&Ò·®°ãñÊWïÝ~pä |'bÜã•Â7T2•q«-7â-—Ûòþ™¹”m?í`Κ5‹­‰Þôéµ[nâíäÔàú¹ä,úIrÔ“õºÎZ­3„u÷„ºKPÙ:pëë!4¤g[tuK{û©œ„êzõw9~v®±¤ÐŠ4‘ËEÉ›pqÓ!†˜õGêfî¥åNwCù0\<`ÊÒZgíR¾ú:5¶[®10ÕÒŠ¿Ý~ô2aÅ% |ý¾’y¦½4!oI]ÒYyFE'ŒÒöê\/ 1‰ºÑ+¢< Áƒ2©ñˆ,Š¦Æ ż=ˆ OBÓÎFñ’Ÿ¸†•^Š®g9‹_´ª¬ÐË ìvèØ˜D¢t@ƒÙ•+ƒzÚE©¨«w¿acyOÉ#m•’‚Ö÷Ë[±qâÒÀCì^ú¢\²y…EˆXVr”]†…‡õJÐ4ÄðA'(GŸæ°!$é%Þq éªÐÞМvDÑ®%c¡ðδxh¤‘6x•rS*Cé$ŸUE»è¨^jù@VÅŠ$—Òª|éµÃ)hÎþA=¢(w€ 00ë?W°NBï(õçE±KÆ3÷báãW™—}H{Ö³žÇüÝå8œCx]þ§l÷¹ë®»¶ý÷sˆ¤rí¸xñ«À{î¹kFÝO9¥œ¿gïb¦ÜEŽŒíè€ûÛuòôN†iŠ­p¾Nëí¡‡Þœ·ýÒ—¾ˆ§ ²§øg?ûIîuþ+­W2õçÅ/zA{éK^èß/X€ ŒZ>òÈ#L º„=øÿ†ã0˜Åе•#ˆ¸«½ßŒ=Îo½í*`¯fJÄ6íùÏ{rOoÿýß5ú?Ž©1νwŠÓ~û½½]Êîà6{Ž_`ÕvJ–9L'ÊT”ûî½78v€Œ.G%ÕØ5Gôö…+Û›ÞòæjOp&EXÁâ]÷<Å~û¶ þr&ÎÉ :“âÔµ+Xoq@¶¼úškBß“öå|÷^ÚJŒO¦…0‡ÚcÇ·~-»6}5ÏO}ê³á…çäyÒ¤É,†¾'÷ž®¼âêöÒ—íËŽAûó1­³@t%Nãí·W?ø¡÷fÚÒ¿ø™åYßf.¼èâöÌgio_!O?²ž½ ÅÞÎŽ½ù¦èÕ¯z#s×ïá›·µ]غÔÃí5]ܺžÜϼŽç>÷YèÆé8刦]õ#Ô~DmõêGÛÃ|‰9»» N¯ršÌÐ!3qÚ¯Š³øDvÛñ¸öºKÛ¶Û<ztvp|ç³S’ÇÔ©S±%æ¼_{KžJW ±A”Ed(çŽLy t˜÷y`Æ7+VX?7ÔnQú3{zº–îÿqôíFW{7Ö]ü¤½ó]ïÈôqìŒl¹Å””Í«¯¾„…ï¯Ævæf­AOSÇѺ`9¼7n.‹×ÏhóçÏo;²æÂãúþÎÚ™]˜v4„yþµŽeçwfAⵡ*§œØ}êÑÄv§Þæ”[ãÏQåÛ5#­ÝÛn»m^Þ 5˜üØóI[‡î¥—ÜÐV­¹£ÝtÓ­ÌíÿåþÅÁLÞÙp ×m)£½^óÀ)50,ùŽ9L‡ò­öZvíÚwßdʘo3~tTuìøà"#¿`[†‘]:i; ÑJ«ƒJq¸mÃ’^$>½¶uÒždyòû1â÷ŽNˆGWÚBÁ^Z‡¢„Bx9ö•øHص“ª×VKÛ1ÊàZÖ«,Î:y,Š\‹ÏºgãL‡r÷ü ó^)ú«a®úûþJPâ|o}˜¤ˆ°>N~¶ã}8·Á1^¼ž¯WŽV{5¾—µÇíaˆÊa¸aý}5L|žžWÄéåëùõtˆJ¼×¾¿÷êa¸4ü™¶ž·ÇŒh£F¦]²“gˆe‡À5M ï“0O`âý sßûÄ|$Õűl,â@3Ö”²XòI»˜ò§\ ­ ÒĶì8zègÈÏ)Å®€Ò‘pÒ2\Úm')øØip€•¬Ð ®>,©'íD×òŒ„À+€ÿ¤YÃö1ÏÐîäóíK}1ã‚Ò—u÷Š’æ…€'2\á‹Xâk¡RäΚéœ#ùS yòSI&°­4 jÉ7Óùq£é&2ôž0Óá«™ªÜàGTÒ©FÅÏÛ GÏåm¤ŠÄÑÕX‚KÚaáÞÄö/,ë”gÓBqBÚ+¿¤[z%Sðetàáé„—|ÕP„¸e`…%º±öÚC z•C/ƒÉ‹B Æc¬•:R¤ò¢wù‹è¯;äÙkΦ1î‹` ×»÷Ë›+º¯0]uõÅL]™•]2.\ÈÂÈ7·½žñFÊÎ`ôúü8ÿo|ãÛY´¹þ<æÀŸÛÑ•Onsz´A¼}á8kýß#áçw&Ó'þçÿ‡?äƒO8N⛯üjþvM)Çíª«.ÞÀ©ã±tÉrFñtïC®ËpêŸÎb¾§àÌ_Ð-·äã`÷¹¨µµ#ptœ´Þ |ÈJçÿk_;Gcæw×bØ ˜Ž_üíG»ÝÇ5_ûúaù@Ô 'ü:àK—>’ë»Þqs¥1MæÝíU¯|}æÛq¸mÞ5ðú %wnï}ß»ÒQøÁ‘? Î1Ç“:=ûÙÏÌóßÿ~aÖ´6w`—GØŽNɯxÅËØÖó}í†ÿ};'ó¶å™ùÚð]w-fËͯ²ûÒ¶A³“`œvÚ:]–PåÆ-2mX[[|×Ý™w}à¯Êó_þò§VÎÿ&ìt:Nï:ƒÝâM ¾÷ý£ã<öÅÏ^Yn¼é õÞÁâ×cÚœ9sØRö´Äyrú‰òœþ‡Ê+çqvØgèô,Ìw öÚk}{;›^ÙÛ¼yó²pU¿8éäì`ãBpôÛn»:ß&8âˆï±s+dZC'@§§;ëž))XÞ‰C§î a>?¼lM>B%Ɖ|pjò¤I,¢=7þqýeèújÞ®ü¯ßš­M§®Í-\è”ʰwm§³Ÿ*áj—è÷uQ€é„(O?§GŠ 4°¡‘ºQ!ûcý{Ãxà÷ëÊûígœ…]ìÆ‡ê¾Ívµ7²¨ù h—ÞÝëÞÐ_üÒ· Ó¤SØ9^öÐmì~3/LO<á—YòÛSNÍó 7^ÁÔ§ÒûÙg“|8öØ—0 èå´îúO‡‚wƒ´ìÍÞò­× ¹`úÑ5 ©wÎb磳ãü»]ëÌ™Ó3zßSvÿo¼‘5³¼ˆ…ëëá†3ˆNÕ⻡þØ…è”ý+³IÁ³Ÿó,ÞÒ]Mù»°m¾Ù,D¤ sªT5mo 3Ÿ£©Q¿ÊO“`û(XôožÄ°¼Ø•ÔHì€<,Î{ŸŒ­v¡Úó’éð3¶p´Ù‚7T t¬`ˆKÛHt|°]7q8uÓøÈWñ†Ú†bšuÃô1”7(C©Û†pBš-+Cyƒ6”7{Æ ËýàØê0¦¬Y§Ç+¯¡–­w(ë%¤zà ÂÛ¢šÂöÏEÛ2 -ëÖÂ_þÊQ?é[N¤5LÙà1Ly AþNV;óòr:šTßL†.t¯G˰aò oî“ÎJ‡iYÄ‘~ÏËúÐ×:º%sô¤Ù¥ý–ÔiUîÄIÇ_‡K:FŽÊ×Ùòë[`àKדּ‰¯FÞZ$±ýŠz“T6‘e—ÿ`Y“öQ‡vÓÆ­«÷CÊkÝ[7z«ë„”Íam†ÆïŸèŒgê›qDèæ3ŒòÛ‡‰å‰˜®÷@Ÿ+ƒ¨ÒQ¢øt=Oe&éœÄ΂Ž<·ÝUxîé°âs3pýd$‰p¶”‹°`‡ÒHÏa*Ì#4âçñ–`¶œü#{—‹5ÈwÜ!òÌ»m~>†eÅ«ìµØ‰´ ŸU«KçÇsB¦i8ûïü$²¯b$uѵ¹sv`Ç3pÖ¾ÆÖ˜΂ū®º2£œÓ¦nÒ¶aÑàÿxÓÞÊ×^·cúÈu™âÑë”=Ìœð¡Cg³«Ë·ÚŒîùä=âŸ{îilgº- N:ÀâÛ¯ãK§_dŸû϶ã~þãöÁ½'k œG=lØFÖwˆÍ|áó_aôòö¯ßƒQÔKx“ð[ø¿'þ¦=Ì‹C5wî\¦fÜp¹ÕhL`>´ 7/¹øÒ¬)xõk^˜Q̵߅•\0û™Ïø½,âÞÇ´1Z½ ‹xÏ<óxè/`W™Ã32îT"§Nxظοõ~Lm:_óýh{.ùõÎw½=__v¡°òo¶Ù¦|ôk!ÓUȾC;æ§Çñ–àà³²·ÿGYã°€øk®¹:v=mÚ´ìærúégðEãe”^G}þ¼ùÈ3´ñÇãò¥g;RÚÉ!úùw8#ÒÿÉÞöCÒ¡8nÛ³¯ý÷ó¦âmo{ k7n§p]œo÷ñ÷ãq¿§ÃñZ¾m0º›&d}{2dHu2}Nùëë›”5C|“ó_ ÞŒi_a‘û\øî—¯ñúm‡GuŸûùw§šË/¿Û{'óÔ7'_néÊÓ²AáÀN­ãò¢£W©¶9˜iO+Ø’µF£³öDâ]=VŽ€”㮸Û9¶ôù& ÿÝaùÖáªNÏ[ìÂöœoÄ®7a·®7óíˆ'Q¶èÜ Æ(ù¶ûô§?3QÛeç'·+®¼û_Ôžü”'3ò~skÔÃÿÞ/ñq®-Ùöt¿ìîcÇßôm¶Ùfyò}¶ þîw¿tZ/ŸÕW ¯ÌÆù¦ÅCÙ«ögÕNeÕ¾Y™š­†7ÝtS:f:ÛM7Ýü†|qx3ÊÚ vWúY¦âí¼ÓžíÊ«þšéxOxÂnÍ©yv`ê¸3üz}X–­ ­Û©íz;/ÇóÃð?ü+•Ž 6ÒV“Qó=²uq*ý’ÙA.òѬ²~·.2å¤uu5!©ëIzÚªª„*þfš#¤€©¡ÊB웟¡ª(bÄet è΄„WÒV›>ØRH7­GÒ;rä`Þ8ÞÔ¶Ý~·¶Ç“^ÁW¯7κ¨L’ýÿü¿®ós ÓènæÍÖOÿ=òPF…­Ñ~8ÿ¾ìÍü]ÏbÈúø :®]ÅR‘IÒÆºk.yÀv**Æ@9±Úļt¶CçuC_E/L?îZ×n»ïýÇX®Ä;MIC«|¥ ‘/é Üò?2¶LšŠux˽Fû½ƒ‰eÁò&à#GdânV—¦™¨ô:5;Ï”wq’&Ű_ä —@` ï×H¨|°JÏÀ:Y•'S•’²ÉU¿0zÒßS ã=§\f@&hò³œ’‚_z¡õ\|ˆsüg’¨ô=®8 ”J£îâËÙ2ÿ8sY”„ù—?ÕSAàXy ÏÆ b Ð?C]ÔÊŒ°2Ž‚ )qÅà$ï {:ú&• HŽ|WÏ“æÐÆ!a¸ò™é(Kdƒ²é·÷iãa˜- éy“{ΰ-¥j2‹=ŒmîRY¤¡\¤ N@ûÈÈ«ŒKÝ•LJç½1Ò,ðpƒFôðä¯\OXþ¸íŽ¢Qt RÒ2êÊsž ^¯¹*wSh扉VÌQ£Ü¥ãnœœóß½µ¯ºúïìâ²1‹5׆’SòÒÓy>|SLF3j£i°EàDFŸï¦âYC>3Óqœü»ßÐæà8;ºÆéµY³7aÄmfÛGÔÆôì³ÿ”¹ðö†§M›ã³ÜYl]¸Ü¿"#sœÍwt±rå0>õ#…émî?‚59²#uo;èƒí[ßþ2€§å«Ä\p!NÇÍ8´«ÒÈϘ13Nðoû›àûEÚ?žqó•ÙY„/Ö>´t ÕÂök¿9f´Ëé¤üð¨oóeÙMÛ#‡–³ Nágüši s¶ žÅ‚: 'ýâ—ìAÿdžŽ³8Ú÷¶¹s7öf:gÐPŽgj óÙgM$wµ§?ãq~ò㟶‹.º€Å¢Sµaw‘e+¡=3˜ /¼štŽc*ÎÆÙfÐ=òÍÑ+ÙýC>Ň´ŽF†mÛ¢;–’“éÇô›ÑÌ™Ÿ™ÆÙż¾ÕxÉK^D¾ÌÓuþùç!#ßT˜1›-?ïá{ûƒ3gx+p¦r?"ûÛ¿ç݇0Ú~pîhô õÒ¸¼µÙ|óMqž6Å6lþå¯8ê·#ûx:GÒñ¸§ŽoU¦NC‡ç>ì3øÄlì`2NÌÜêK.¹¤½ü/a^ô¢¶%_|µ“tä‘ÇBgz;ëìSÚ-7/̇¼fLŸýº'üñ?ÿE¾Ê;tð¬ö(ðË—ÀöÎD/[ ÈsöÙfôþF½kÙªõ"Òü¯öv6ööR¿"Ê;-ã ³·“O>g}oV¦EãÆO‡ëðÃH‡d»í¶êÒçÛMx#°¬ýí’ËqÚ¯ÃÛZæÚc¢)+–AË–äU«œä±,†þQž'°ë[»ú¡3;dK—.£Óò{¾0ýð– × ¶„½;åà^¹Ÿ~Æ9ùâî AìvµŠÚ›‘u™¡~ϵüF€7*2ý…Žñ5LÙZ»v, t­1ªÌZX•Xïè3›/cÆlD9’/q›oÚ§Ý+ÅΚœiù(ל=OBÎ øÅ‘±óÒ)K£GÁ¾oj‡|øèðxìn{Þ–=Œ/aà.ô?ƒ2@ÎɾË[®Žj¿ýݱÐZŽ=ÌæÃmÓ™4ŽÒwçcd_ùêaäçN”»™Â0^ÃÈã‹è(^NGel5?²ü6eò4ê¡åŒêŸKgy£¨È΂çG¹{ÃÛ›;©?þB:†µ©oB½qtÊÕ,¾#²1kf̃%l»ûïÉ75>ƶ¡[ð&j%r.ióo»Û›žo ø…ó;î¸7pW³þakê…¿· þr~t‡ŠÈ·žkV»[Õøö÷+ΣþvFÇb‹Þ×°x[¥sà78(0e#H•6‰ ©:ÝŒ¡.OƒŽîÍ^ÛbÓî oüÿ©ë¿òÿ¿J÷£ó¿Å÷|ÿïÂýŸÅïùõWðF°-óÄ&Röfµ¹›mÑnøÇ-”÷•Ùla-u‚‡¨„þSÙ%ö/+©@|Ù JY½§í´ónLm{!ƒ>óÛñÇÿß`*eåѼ}¡½Äžµ;î¡§»*+ÕËæú5%ÂÄè¨'µo7†‰íåÉr®„nh2¶¬óŸ­ÓÁ“\¿¼ªlu²teÆ2U~¥üü)W13Nò5í§“Ç¨nÍ•~Hô£¼Ñq ôe3aÊ ŠxÝ]ÒC á=ìOáƒÃIZq”oZò„§aêA’;=¸–3 ¼¬¯ö¯À`•Ô8¯È¥+q¡¦äò«SÙ.”%"‰‚Bd«Ô¦\FšPi·51 ƒtcX?×[ÉÀ¼rǃìtÑ`׃ÍÞ˜8Ý Í˜9šÎÅ¿OËFà¨ç{XΜûÑ8nׇפI[áP®Ä‘‰¾Æ2Ïû’86~3`ÓMç3Ge&£k~(ˆî¦7sæXòåêà×iGÙ„Í™½Îÿ2>ÍáâL #Í•¾ Ü8òÿ@î6ž¼u®wß[pÓ§oC>—œ‰Xï4gÎNŒÔ/%ýæ;»ñ¦¥µ»ÖƒØ˜{*ßVóاLÚ†t.g!- xy«2eÊplCøšO¿"·.}x Îü§Œ¢S±~º×aMæM„ß xpÉê6v”vèäuúpßÿÑtF'°óÎÂ…×®C|ÜÝýÉ|oà!œJ_ù¢ÁdÁïÿÞ<½ÿþ›Baʤ­±Á5èáÖ<½i[³Šrl=hÆYF([UAFùw}À¶°ɼé;ï,Û.qfq¹½nsžC<¶Ýy×ÒØÈÝÙ׈MÚ¶Ï\¾|5òZ÷Øa Ö”§.ø6tŪù¡2q–™~„Ùòo`¼õyµš7cÇ Î(!ï(‚3™|{ÅËÚ¹ëþ‰ŽW¬™—¸)3wßý0Ñ‘±Í{î)]$r½“ûêß¾À©2”UÒûà’Ûr¿d:ŽÃ¨ÄÝ~û¿×õÜ9;’oQ.u6vwÐ'm´ ¼Ýà­æÄ‰#Ú½]~´6‰7‰1Íh¥šgšÕ(ì­ìzäÈÍqÌÿIþ²©í¤ÿÑfÍÚ!‹¤uhÆŒÔñ­5'®é¹ð¿²èÿ½ɘ2e«v?å4oNÁ_Åô°m·Î›¸KÛSŸ²œ$8+o|srËÍÄÆ´ ²À ùPuò&ùbfi;æ˜y«É7x2÷ˆ!žÀ&K0“ZÙÆùÔ[l±Úg©x€Jµ*ŽûÀsågÝ.q0ä¢egN±ÍNaí¸Óví¯|1Ï£±ëõ¦†òÿúÿ’|ç^zÉe|¡û8òÌ’­ló¦½ÄA'«ÍmýŽT_XAþc}Ô-›LÍ»kÚë_ëY¾ÇÇÏe»ì}ØäaÇvï=@Ÿ£¡‚ÍP>c§:äúD*‡Ø'mÏC¸òYô‘CжÄQpŽøLú†õ`ñåÝÀI‰Ä‡¬ÒIÛ ¡,k–Á(hŽ‘ø“ò¡\!dïÏ•ßVeSùÐeRzþY"…hª_à Y ¦†‹O¸2p¸¤m}ã|ƒr8@®øi囃+"0…_ô ÌŽ˜ªl|€œÏŠãx–;ˆÓÀkß6ª ¥¶_Vü»m‰d“Þ*)ªàYþ Wž;µ†”€cŒJƒ¡Î¯‰Ì Ë?ðµÄW9b.8îÞIÛ£ð½‡Z€DÙ„%%+E y(²–²@‘`Œ²25@`™&»?ï}ƒÃ‡ÔsOº… L¢ ’ pÓ¢Ú¨¯^¢R%ÔP%I&!¼FYŠ[úG½‰)tè©Ëÿƒ½7þ-- üNߥ÷}¥iº›}§Q‘   ¢h¢‰Ù'™2©dæÌ™8U“JÍ$5SS©©‰3ê2:ÁQ\0ŠŠ( "»ˆ44½oôJ/÷Þ¾·ïí%ŸÏç9çw/M«€S'œßïû=ïyßgžw=ï9ßFÀK-££I"®¶”°ä&±É*ˆ·–,ÆÉ Ú•D¡hùÚlWÛ(Fc¬‡×;—\h_ùFŒáo±ð­'§°åãœóžËªüÞ€á¶:NVÛ/8ÿ xîæNÀ©üBíaG{÷<²ÜxÃ}m‹q?â 7ÜÀž»¬T?á¢3Á;´|áöȲ•ãŽÛ839‘‡^t(Žƒ(Š¢&‹‹.zû¦yÅâ½û»pñÎbPæ^ãC  xý!­ÜanwÞqÛýL(žÙT}‘w±ŸÂ*Éw>°œ}æÓŒÏ`{oKpA•õÇý˜¬\ü¼Œpë­ @(ÈüÚ N $öÕŠq]ž#Ë9Ü 9ûœ3ßr?ös"£Ž»°Ëã/|V´¿À>ás¸ÜΠŽEÝå[_ô:¶´<{ùu~ÜËãiO}*«+÷ô°¨»¹ và û²™¶¸Ö:üàµÁ25`Òp+¼.7aË]îeÛ̓øÅ;—^úîZâÝù÷r—åô9£ÕÏ={×kïÂÚÕ‰›@_Wùä'_Πñ~O_änÇɬÕöß<ä ÙIêAHgœ~ vd«Òöõ¶ãŽs‰…ûîãÁYhÀ¾S߯½÷ø]Èp>aïKy¦ánüþ@4οàôåÞ»²’2Û¤.dRÇÛnîf ~ïr AípÝõNZäuŒ§.gžs?µo¹Ÿ;2'óùAàÏ8ýTV¼žÉ¤]ÝúÁ6 Æ·ðÚGœ<‡øØË’Á÷¡C¬&ŸLñÆïJ|áb‡®µÌüÄÝ“/{~¿âzãòd:rñ9øcöx;HÜÞ]w1ÐÄxÞq…ÿf~ Î»C¶7îKµ^ÚæN%¢î®v¸ï>~]úÈË9á…›€¹ÏÖ—u7Í­n·~Á»k'V§Îc¢vû«ï¸c_m}èÕÞa÷Úâä0ÚÊ_›9Ù¸ƒX;Ž˜pÁVÆÖbÚ-Û޽τçÀ¾‡¨Ÿg00~ü²zëà×^Úe·V²ëEÈ‹YÍ÷7n§£÷!ô/ÞÅo1œº—׈¾8#Vîð· ö,—^B,òƑ믻»®oàPßóXUwËÚmwÜ·œÂÄîAÚž}äG—a7Ýäd7¼Î"Îvç7cê |O9ùTls±{ÉÄ¡ö‡Ûb:8ȩ̈ò°ú‰øã å<ŸÁ`Dz;šd?ßî&&îouÐÕù»nŸ÷Áë›o–ç#Üi9›‰Æñ\ïï­M'ž°«úÖYgòæ§K–+Ùbæ‰Ë.½x}÷d?ݽÐw°c?z:wûü{ü­¿ý7;ÿÄO¼¥ó‡‹!B™cÚÛÚdÃ$©Kä«^ÒaÍ1ÝÓ jlxz5b4ìˈ4bAüµ·!.¥#îô¯´ôþLÏydý XNŒíψ4kê!íÖËݧ¿ŸxñnÊ«_ó2IN¡Ý§ ~,)ùÆñõgïJ;žxÖsž¹¼èůZ>ò¡O°¢}¥~#ÖpqMÐ>žà Ó|Òm#Üqðš?@8&:œ š‡øô’‚ð­´;´7[É‘ò|Û–­^£ÙZ2c™‘I*Žï|88â%«b­„ýÔZ»XDZ7¦g¤8ʤªfŽ]›ÅõL" Ó€N™§NȲq3íê6Væ!*ÌšoDŸUÆí9Ô‡<á; ¼ŽÑÈÙ´¨Ë­Ñ”=õ]ÚËØNÄE\Úc&*0‚Öß„II 3$¢ÙRÎŒÁ)…›Ñh )I0»hd åŒLPÒÁÞ:Ââ j•–Üg¥Úk’„ƒÆ$›òôèÔCé’M)£6is1º #›vÕv„Ú“2ýsö¤QÓ5TÒò!= 0½78a€Ayƒ3-<€Ý ‚u&»Ó0£Ó4¾¿”Q ¨¿ù~—8J°ÛV«â¬±°}™ÒY3³©´t¤ú†å8øU H«wÜÃW¿‚Jã§ÑÈú ‚yø$7JRºhY¡= &bØs^)Å£ ÍÖTFw20°R9@”‚¯œ¼“„ƒ„óÏ=­NÜÖkv˜·Ü²Á‡«Ô'#êIë á>|Â*ƒ1'KÒÚ·Ÿ7ª0È‹(U¸ð*;{ËO=íxV—y§7w$a•Ê[ñ¼ø°Aǃäï‚Ö]wÝO ìyL˜¬ìâívâ®â6©A~Ÿ…ðÍPUXlv'ƒL»»ì©©}ý#¶Í¦(º»ÉóD^SyÞ9§Öp¦±½öš»²ƒjC4wß}8Ùá) š¯ä}ýÿoDzE¯ø¼óŽ;y¨ÏHøÞtÞ‚”ÙÃØØÃdës>(æŠê‰'=§2·•xgæð2ð×Cl10ÞüÑ7ÜËfíYíó“„û’gï^ô@?·€hÜ{y…¡UÛýË×\ýEö‰j§sóÃð•ô÷oô8˜T'H¼[žWÉxwà ÈöÀo6Æs~ó„ïNࡺ/2º—ÜéÜprá–ˆk¯½»&Ê¡: ™­—½= ²z±ÜxÝ}Ü Ø“}Ý‚fgv58x »0HÅV»±¯“€‡•óÎ;º&Ÿ“ã™||IŠzçh7ñæ¶¡ë a;a­IѬÐU.×\{/ƒâÝÅ.`À{U÷#ð;n¹ýNb9{­*¨·ð[  {-!€²‡U[ªí®]]‡õ ƒø0Þa¶ë\{Ý=ÜIÙÍÝ^-züžæ|9pÿÙ_Þð¬Ïï½I-“ImS‹cϸ€X—ák}µÓ•ïõøÝöƇç!9Ê jÛÉ:i Šyk$ô™+0aåMY ÿrHdÓw0‘€·6”µõO{_e¬ðë¸Ö¿Gh¼ÿþ¨&îãê£[æNbà>¾ñ÷w/¶tr¨N!FÏ¥^'wßíö›‡¨Ã¶Ç£—Û›n¿õ@ºàêðÁþLF¦Lh~ ýíû¸;¤½%‰üãðË®»æîå$îð{Þ™µIÆî­Ðw‹–~4¦ö7N0žp‘á±Þë¯_¾…‡³=®¾æV&ñgd_ÛBçÂÉä¡Ã'.?ñã?¹<›Öå—¿€­GïàîÞo/—põVîŒãÖRÊè§ùÏÖún¡¦À2œÌ5“;Ñ‚6¢˜^o¤TwÚPÃ{-h±GùÂìÄøÀÚîc!`] 4»9f½.2ŸÀݘ‡îdõÿ™ü:÷YÕ³ì ¨l¿q|ýZÀç¸üñ»'?å&¿O]~Ürq¡Ú)bÌ©=!QO{?‘hQ$Z"ØÎaœ®EÅ€[½í?m_¤»í÷uëÓЊ*'Ú÷"Ø/(±HÒržÓÈwêbwV*ÕúÇkF»‘<1<ƒk©øG)_[ 2À!p]4iìK¿äµÖ™òD“üê²ÊgFcÒ°ÉôÕG]_4(H*ÒÁ$„@¬øÖÒÕA:j A«XRÛÒã‘Å—“€“ÝÃVrwPìÐKÿm8šžͪ€Ìü×8x1(ËÖXd8¨ôZ¸˜ JJ áÕ/Çb¬iÔçu-]aPT9N;[§ªäs4hö’cdÇd N)F3¡lÑQùHŸ4€ªQ/„þICÐ8pPº…Ô4½”ŒÕÁ'm&2WIÍfwr’ ÈŸ=w l®ßè’-µÝèºUŠ&)Aü#oj˜¤—À­d:˜"(²µµî[~[°lúJ¯a÷‰]h9‹-–,XE=nµyƒÉ'OØc»UŸr(/a¹M"£ïíÐêdÔ•\`|°v?t'vÀúRi嵇·!t/+Åʦ>šÉUÂâŠRWU½5N0ða#¬zÙÁ{›|?ûä z°³"³x§Ë–C Ž…WÏ®N@ž^ ®ÖcwC<¥¨pÙ#%'xn¿)_šÚ?ˤ9é¹#á$ãnVOµå>h¹1`)ÆÃNqż7Šžv?6ö-í/ÿ{ïq-Û£ØöÀj¿ƒÖXƒ+=i9`òEÚ÷2¨qd‰6u¢p<{rõÁ&•úVÜÿýšTÃíbãòݧaðMh¯‡°µ6ßÀøûË2m%ÌÛü0wÆnÌ|×½uÈÕo†ËÕ©SÔ¯µnS —ú×_Te¤þ“0upÄ©à:ðÃÔé.öÛÀùKÑw߇ñ¸¦´­.Â;ÈTí¬ïXr(ómß­''0jŒ/È jlµ³>’ž96É»÷øÃYþ¢ñÔ-í¼ÇÀ‚àüWۉȌ6ÕÛ»ªàŠÎ—Â`£äR_Áz%4±5êþ;|M#õÞúo~áè¤Ow‡Äã¥úÚé ´ðþww[¹[ó}ƒ Y‰¤-ŒÛ.#8rØ\‘5ÊÔe檆 c[J‹J>e"[?‰Ýš£Q'z¦h{æ“#ë fñ®ÂL|ˆ}xh?N´÷ó*RI+f çûð`"øwêì¾­ÃÞÅR¬ž†.=Ë¥2Æ·2Z'µG°\iÀ°ÏÐêM|űD°N£Ì~P?ÙŽ‡]_ƒë/®,.ÖX÷¾q|ý[À:äë²= qWœkS ?føß:V¬áÛyQ,³«Rë÷D©ø3@·õ“ž‘kîÄpôÅtwùrªœª½áªÐ&ßã²mÊÖõ5¾¤\ßµuFIŒI9÷àM^µˆÜ ××#|$(žX)hóŸlƒm°eQ =­¸ãCDM°ª¸”Ïí7«6±´ U&æ˱à.;Q׊㪔ëÃäsŒoDW_HD:~ññÏŸ—]/Ì‹¦iÊv3Ð0¯ µÇ"ž6è3ý*5‰(YwF¶˜r`¯ô×H!­Þ¤;n:î*öª£6+f‹d³l«?j W/ofKÊé§>mùÿàòùGÐe™ã"Þäö(·£èE(ȲTÏ¡`&R·ë¸½äsmyFú å+¶£¡ê–xÚw¦Òuõ0í´þiö:}@¤ µlEÌ=0,Ï–ÆÜ# £AþÑR#L#iž3Ÿ/rEl«UF)›ñÚJ­£v®m/¬'s§P}´¡«ßÌ#uçBXú¼ÕnàÜ#+yå[v¾¹@ˆn ‹imZC.ý¶:­úž¸°ˆ bŒ ‡*L‘ L½BQ¤œ¶a{¸~˜UuÛã¶^=º ˜í”™tmrµÆ®kô.˜8)¬^ /[.A%Fñ”~^B'i©‰d¼š‰kmÕV[ïàÚ†G.Ä‹¾©b†»MbLg Ž0 KfଫʸÇX@f§á 4[w‚:“~|0Ô9…ꆒQ¶éÑ'8i›(c;¡W$«G%E&ùq;²óm¦Õ£lªôÐÁ5 Þœ=‡ìž³ûïÜ;ðNfw ëÛ÷p÷àÈ‘Kx•ñëd±÷<Ô=ÜIð. ·)ä—ü:ÁPç¨n`›i㑚ڧÅS8¼cô{8)LC@ ûÁ|_©:ÍF»óÞi NPhDþ¢æEãXÒÕ=|@°=!î8}£[–Ø~U¶:iÔ7|¾q|}[@Y‡N?ãtR'2!§vA¦H‡ÄLmõÇ?cÊÕ{˧'8F¿G»›“öN þÔ}¢Ç¶Àö£Ð5Ž)¿Ø3ÈH•k¹—ªÕ±ö^¸.,°ZÌy¢–¦<ÛÈä­Ý–zWý‘v4¨-ÕkºMé…±ý»yŽ ìå¤ðS·¬¶?–X¯J÷àqŽB¥‰œpðì\žI:YÉ£æêj[k0˜±å#Ô¹ø¹´©gú‘ÅH+¾icð™ò8æTæFuê#!«²tló@º‘„0«À« ‘] KÇÐâÏÐYCŒ`ÐÓ†œê¤mÜ4èJ‡„èáçË$ÄOØ„ãrÂMø~ YÁ)€1Ÿ2L Ê‹«•n‰¬1ÝC#®·í5RÞä’cL§³Kœ´ÒêD‚zV@À µUX¦èà¥Q¦Žªd: v†$üpO^K|‘É@ÀN6¤ókÁcƒãZâv0¢}8É{¨›P‰UÿÓ©‰—‰ &0C&rº ‚rB«I¨P«Šs=6F>ù G:v6ÚpxÍÖ0s„ _"ùZÉF6K-DBI‚[Lj ã›×"”4˜Å{X:Á;„€‚É7Zå+‰Ò¬&[±„ñZ~&gÀ9¢V<Ó•…t„›_f´TD€9±Aat&j†®iiìØÕé¼6I7¥•>Ub¥zÏ®Çqâ:òxS¿në;Äݯ 8‡±¢ßIzͧIë£d·zž €©ñ³ú°ƒ¯êŒ>.ŠÄâL{dékQ±š*Øü$W6j@(¢"Nð^KM^ÃS)¹ª1%ŒÌ&žôÏ@ó]c²Ù¿ã?-^y:ÕE ­EƒðV…#r˜j‚ £`á:ÀÍ$QSG?C'01œÔ‹Œv:¤24G­4¬íüŒƒÄ§ë“pD3´v#iGæöMîö¦­%ćLë¹g¾ÓièCeõ¥<Œ•´Ñ”¶Ò rÃoö²ä@š\iê×ø$P¦Ü|I7ÿb>YuwjF‹²ígKÞ¥—ž½\{íMl#üb?ÚJ[´¼kæ6@A} Ý–ï¿ß‡áo㹂gñ ŠwÈ/»O&bWåPKÛ¦Iiøx›¯\Ó?Sˆ~³vO7n~#gj#óÜÙÿHY;jngôÚ¶ÓxÑ¿Å2t´©–´k,Ž0F°¤Š%C¿;.~xÁÆ‘óÎ? Ïrø0‹6øÇ×·¬ôkgò\ËîãÇ]áÃls<¡;SFKœùÙ: O­ÜY¬¾=£ŸAågóºþ'޼µ¸2Æ¢õ¶šR²E áeèS('m[)»à9[¬òJ[H'ñFv÷ô×3¾Y¡áá2@2°cÜ¥ƹw Moµ¤qéš'ŠPƸúNÚÜu"Ý¥²lV €8ž6xõ°¿Ó|pæSmâzx§ie×vÈTèp¶â®Ç´uBIsÚS%ˆ<5ߨ&dÒòM•2 ZŽIkDÍ¡ƒdÓª+E±to±j3q €xŽ‚^*R䭱┑c'1šBHZ~àT@ü5×”M‡8Êê,|8Ë*CÓ¸i²§T•W„H§ŠGÖÈ©®ŒÖ$k4V¨ë5wdIËÁr5zu2E±ŠÌpÄ(Í…dÕy$Ü*#eu8+Åf¤`®B%ëxAYÞR*%+*&\+Em-nïÌ…>xHûÃËUm\Û«¯Ò©ÇìñTí*[B°AŒåæéG¤wëX®¸u®âsÌ¡1=ÔõuʲõüÒÄâ |´Óî Ê·úVÍ\AÐn5ñø!½Á·7s5[WlâÈ­ÍÊê¨O 7´)Åx¼–$ÆÐœçQ„Y?æ­r 0üõ‰ñ¤]&ÚH?úžo…XÅ´xUž<åS?2k1„Û±;9a³ú‰ì{>ãŒçòàéCËn>ȶ„áÛ*€¼á3ñ1K)Ïgà,¯þÀÉ6¶Uí4ü‡F«0ASˆÎù eõ§4fj‰„ÙC¹#­c}ÿôמ×Jˆò‹+ùÒ”r+Ǥ½®¸K¸ ‡YÅáè¤çð¥E R*›Ã¨px»ð-¿êŒ– ¥oÃ]Ü$Q%æöII )Wåªñ›²­1_‘Œ “[ À c:5Q$íµ{\ÁצrÚp™/³åW)yIõr›©þ桟øÔ7Ÿù±hô¦ äÞôBžPòJo®½{z¶Ûál^ ɱ´¥>uk$ˆL¶N“\¬ãR,¡Éò:š”M34ý‘›Ä¯­—>ÝC™ûA+€Å…më@[\ôQ”BEÄ·Þé®Êà–¯ú°G=B€ž$sYJsÊéÁ[¤­‰¼òŽ4Ù±¥nÁ𓟠Ýk®¾†ýï<”Îáï:œ|"möí gò\;ϪœÍÃèð É<7³{Ýžg}Ö'´çê5z*—mÊzÊU9y]p%ûUßì öCè=qjaH‘®—dB…ƒ¯l®ýàT|(‹Eä š$<€Ã+» Û=?1ìÖÍ=lÇâÎ7w›Ž!%ùãëØÆ…þòùª‡\-ǯ3fšàÚútãoê›qR„K šÕÏ,?asqcJ\c3qfØÕÖLPƒA Ï:cÛ"Á¢<{'½n›1´„q§]~ Ê·˜O#¹øÛ–@MøjB/Žò 2E›>…¦>R–ÒÐ&IŽ¡¥ Ê3(ù‚¨¤´¯í~-gqj;ä%j|d)¶Dµƒ¼¼€kè÷ì€0kÙÀS_“-0Q¸–ÊÐ’…yë×´c\;¨7å5¶£¤ø Pa¤ %6rê)‚׺Ça‚Y62vZ“²Z6æ n™ê‡<ø ß‘‘FŠY¥p0…ÙøtQ^v¨ÒÛ˜k ÉÔˆ¯òKOÃø_ûq¨‹ØÊ•,zí ‰xÈ<†v ‘œò°\”ˆh`ÓR‘¶”ü3)¬úiõò ”Ѻú3˜jƒ¼t«%:ÕL©H?~#³2(ÙL™< Ë`â)~l%jÅAJñùh¯ (–®TÇwòãM¢^¬vUˆì‰Tc 9Äæ¡M!ížòÑ?¦È Í(S5™ÒꫬšúÄ»FV²È'Mv(uV„ Û‘£Ï`aP ¿Õ2q•GzðN¬É´tò°ÃèÉu²(8ñ “|.lóù¿Œ|†ZõQYmW ]äð•Â’&xÚNY0„7Ži ´—’Éϸä¨MñRhtã–ÝažQðøäŸæ7;^±¼ô%ßÁ/¿s¹à¼góª`ž9Q/èÐ ôÀ³¯¦¥Š³Jni õÍ‚$¬a-Ʋ~¯áSà$Ty«‘¦œlñk $ký¶þÊCÚàζD½7úæ'ýÔÝ«ðΨ>FVÁùkQE_ðß Í(A<3ã_Ù|ãøú´ÀŽÏjô/‡_%ð§AbûáÉ6ßÃúe]3¾œ¹4chñM 96TøYÎá¿Ø3YÌpe¼KäZÕiŒ@“ Œ8ÊAžµØ*£\F¹²Y›¼/ÞVF®«ý€'¸™Q…‡0Äðªéô=¢ÅK ÑWÿ¡¯„±Îw÷ HiX<¬ÇÃS‚A"_¢JU}75ô#®€Ã<{´]U[Š­èâudB\ÊÉS„á?<õÅéºç }V›„²!BžqèÚ‘l†’ßJJ$JHBi䑈2VXþ´”Rñ?À|ƒI²¦4¯/t‡› 5;ƒ.¡‘gxŽóWîÐÜ8r–„bÄ ™š§3*”ÄT,ïÞ‰§Ìƒ²ƒW¾å6ŒvF Ô%Òá%-,"¦nY­&ÍøH®ÒÙtÍŒ|©ÈuŒÊK`lƒ~RªóJX© ÏÇ`R…ä« ª=ä³ÑSeF.ÿº\“xdWóí $Yç¥Å˜(5á€þ €á €Ê_’¬+ð §D &DŒôøl*³‘ݪ!oíÛ¹˜—~dJEZé±Ò‹ð²ð’[-ß™»P3K ãÓs+›,cZ™FÄÑòø˜—üj LÊC&Çð4aùVè„'(ùr°°É°q4† åÏÍKdšɵ J–°a€‹`êàÑA†q£‰3"‘ˆß|Рº„®’µPxmËDZ@IDATþd,RHs £Jűþks}ÍŸÛf‚à0;XãV¨¡¹Åht€¨®$Å0ÎÞRb°"=áõ‹rÈkê¼Xföæo¦uÈì|möƒ„ê5ªóàrò,0•¡·&7ßÈSê³GHu¯åV2ƒL}‹§ ‘ƒ¼ÁG»P7µÍs½[(] Йç—Vy¤ëˆ£Ž•Sl­m±ßù’Œ1áLHô2ž¸ “ÉÇgº„ïƒ.ù£À,™líR¾Õ¾Âƒ§VRëÛ•xîb¬…i¾ùÄ<ívxExòc:-ß Xÿ00s×Èýá ¾ÚUMµ7XÑ!ÙÝ=7O…8”¯öH||aafù:ðÛXœvUºV iGRœä§]ìè; yp+Ì~ÙZZ†Àõ‹”g íˆ}}¨ki¿ñï_ü•è׿áÕMÎåw8p2>iâµv¢:M¾ŒÅ¹:/õ¡9.S(3Dû.½ÒØëx¯±;åêJ!|·v§;›\YîßÔGëm²z ŽÌoëœYÒ¯â Á2(s¡'P—d^íá…èý†ö«ÏWYf¥·ª€Åá/)ÉËε䡟}ÅòµoÀ­νó‘B˜ŒŠîÚ¶³‰<£_®ŽA¨•.·£rH¦¨À2¤¿5ƒ-o    ©’ä`¬(rí%2>4•``‡ÁêÔ¦¼•O IYZ…&ÏFÖT¤DÕŽ&»´:q-y#Æ£:òAó(k†‰­LG„Tv²L'ñ•QîBYŠdïö÷ÆWA:ÖŒõÊ Wc,]A´g?#ïÀò«Qœl¨³ÿê/?"À¿À2|†VÈùf@´]ÕPºÒ‚w²ü–å—|ãp¤m\àxŸjêÐÐq€<j5Yn+}ê:“Oy« ÿO (wòÄ;ÇKI%”~Y¿¤~5Û’×N¬!Ÿj/Ÿå‚h°U)lzÖ!…ô\ˆÑ>~©€«G Ú?r×çf ìnjpµ‰2{&G9Ìöðd^YÖX>ÚXLi%¯˜pYñ#£cEÚ%NhÀ¦ RbÓF+ùÕ›‡æV~ñÑ€Ä gê:6‹?Ù¾Ú¸ ãÁ)V”%¯yéŵyÀ—3ø[uÕ>4ÔÆtÖÓ&Ø\ý´•~Ê^k£¥<ä Ìœ!Ï"W½´ ¼:¯Z×y%)§‚³-}ÈkÝlOhpÉ>â \}R¡l³r+?êd¹A9rÑá£[SaôVÞ9L[.¾z¹·Y_í@îfCÓÒê<%ÃGú\+ƒþŸE(ª¤ÝÚ$ýÁu4ÐæMBb눣ñ­«C‘6-ž†,#Z&å5ÏW µü•{„ ¸¯ºU<ÝX hoóä·Ñ3æL+ç‘™,R™]|Ó6*㿯žaZñP<}’Œâð¡ {m”µk×ñ v{€_¢ð¶<ÚàMv­cÀOKú—¦0ðÀÞ½Oäu²ŸàuŸ÷.—^z©ÂñzØýý~€¯³U'½]\*)ièïc¹¿Q høÐ 9eq}Žã-nMö¥Åþ¤“ ÍÎ0 HRfÓ&AhùÅ6eì"xmó l<ÇÖ}[¿à!\~Tn#Ö|&ƒ ;ú|jþ7ޝk P_lfÒ¦ãùàÏ|¬‹sIèÓb€/p¶z~⧠ͰÉ~^4aMÖÉGGËÅÙ˜Ÿ6 õ£:m¾td$Îp´_Ë„v$Êm絡õÉô¨µê(ôГÃ~%úÖñ1‚|§Ý31ݲôÈöäp$àovæ%a¥æ­Ó6ÊГ5bÓ"ÊeŒë9\…‚±V””·]ø|ÕLAŽQS®…¥Q7a‡Žo£¦7:]Õ´¡Q^ƒÅÆØ™^[ŽäIiÿ¢7‹4Ù4 eRà:ñÐI® ¨È S6p£³xÈèGx«äºjG­†ôʨŸ¨|5à‚¿~nÀ Y­8Ù4¨™Çæõ ª r"6rÍÀ`صRo…Ùô’ˆiÊfpddeE©[Ê7gôI^evø#ó¬nôh4ôBÞ¾F¸¹Ré2æ¢@2“ë*™él1iù‡$‰ äÑNÊF²iªý•U8ý5³||º½ÚÓÏ\ëdI[áveÜ ’·×Ð÷ªh*\NuhÄß80²WY@—„xæIm|bÎÄ€bŒNƒ—¾«íãc!™±å¦«ÄÀ(¿q"Š+£óF‰šPL¶+ä=V¡ÖrOÄ*°Fl<¤­¿†@2ø:ÅÐn%½ÕMGýh™×m³á<ÛP󅙆ݻD4ˉ‡w9[ú0ÀÚãsô“´•0¯•½Åñ8V^{uöØô©‘•=+š).<‚Ä/^«ýÙ¡·‡e6¨v0Qæk¼6eÖù1ŒúY¡õN“6]aÕ;dù“™WÐkš}¯Æ?id,©3m®õOž À)T;f}68›ìê+kð¦rP.ßÊŸ"Z”€–(Üz”âkhHÛE \m¬IÔs"iQuÚÒׇӑÈuPë„_6á+·òðW{§[dR™SÂi¶ŒŒ^Ýù3ˆzÇ®Nî´{àÏñ‡õV²ð¿kQÞ ¯‡.›Voì©¿ºsa?—.Ò"š Reƒ’sYJA¥ÃŸ)Wûl¥ýѲK.=k¹úêeùèG>¾¼ôeߺ¼ô¥o@œ‡yÏÿ§øq³“yU-4 ³k}µŸüôÕ ¼²-T=™ÚsmÔÀ(Énä /ªéeç0)Œ44»ýNöW`íoµÕØÅ^ÇC?ÀÛrÓ”zA^-ÔØï*vsÓßl· ';ÓgÃC¿eGò„þÆñõmëÏzî°¯4F 2f±‡å…N±¼}’q;XñM‰Ôâl­ŸÿFF­•qŸú[ˆÖÓä‹2 ®êS3+³0FQ¦¬ÂPT»T[:ôF/ êøÀO†‘]•­SÕ7ò£LÝmkªõù-_ÅNêMŽ62aÖº©¬Òƒî´Ã1àZRGÀ鿼Nƒ’ï›$­‡â¿ú#ÉT D#‹ý¼m°¶¿ÕsÚ¦t±g&äC*ké[Ê¥±‡6“à Ϥ@TD·}A¡ø× | ÿNkC!óˆH0Z*&q;ܸ ¾òÑ!0 šA9 Ûþ`‰À 4œZcÌIÙ&ÜFð½–†¥µwâÙð×<‘m>y5“98BৈèÔŠ™û(‚—A´1!eû m žä¥·0\|pŒ1 ÉSOù­(£жê,k2¤A ”¦L¹"Ûd‡2áÅC+Ç\C¦8’ð!(Æ^Ë“kós¾$융 Z) v4HÀ”›2aÌçn®â)#לRÕoªãÕNênöÆÛ"l”?eVÃÆf; ̲@x JYÔp&c¤ š„G[(¯ƒ•Ç*“X­F”G®²kƒ›-HÇüê>Uc+¿ô¹ð?ø‘/%¢åé¢cžò&|1—¯­á8´v+ÚП7šX¢OÜ»’*ùq²…*mƒ(ÔÅbPÛ™üBNæ›/ÒŽš†h!FþÐ}4%M$¹MLõ¡¸|EÝ”Rþ$L׿a¸âÛkñýâ‡IkCq¡~Ê\¬tÇwÙÈ2øÓi’” ì,ó¹ÅƒÊwÜV†Ø AFÈ -D0`Ý’æûÅl7KNS}p­ûsM¬¨4ŠH#- l»`žÊgó¼®2ëoË×와¬ìÉW—…°róPŸãø!œ&D«Ÿ‹ÕèKH-4ºÿ#‡œôÜÐPN>08ýô“ü_¹üàþåU¯~y¯}ë[ßÌk|ÿ1€w.ç_ðMüð!?–"knzfdQ°|íJÞðQÞñ¥C¹yømôç¶ ‘—^ÚKxÀ«íÄ•Ö' àÔÛ°LWíPþ:³?¸½|Ú—,„ ÚAþ|ÃFû:¹^DéÂHæ6@j!yݽ%o°#ñÿù—¼ÕÑv{&v•Ò|åê+å,ÄaËcâö±(ôl0GûÐÇ‚úóó@ŸÙîj[§çýY`% à‚slh›Õ¥p;‰øÚŽ"Îæ%ôHØÙ¼3>DîüCÐ^éê·yxZ Z/=á" ¢3íeQæu¤m¦-ª}0fÅÉFS«”£z\æy³¾Š×zY¼h{b\ŽþN†íŽíTú#*ÚZ±4ƒyîT7VÞêƒ$ýørÊtÐE€–yð±ÿURš‰o¾ú·\a„µ Ôa8[«\å’,mÂH/<”l+ÈËË\»Ï 3¨ç—¬•FE½‚ˬH˜,¹rž¾×\&@É£_‘‘k4¸vÅE­F1©Ožúã@´Á/£º±âÓö#%­Q”‰üxšžò†Öæ@Åš”ÁL#ŒÍ>ê}J$ ùœ Ÿ×Á9: H8 ½Ì8õF“t£ ðd–”ëúq0UOU4;Útålã«þýŽjth%mAý žäÑÃNÇiEèU Š)'Ë •¿âù%wÍ»á Üz­í Ö 72y ¥¼ž9)Ò–m®+Æ\oƒS,ŒyˆÂa¥4u,‚Õ>«­„h4d‹‹€³³³LíV‚`'Ó?\¸_*øްr'Ò²»é#ès`’Ñìµ(FB³­oÚv¥”bÐVa¥3[3œ43+Íé¯ñ#ùþÕ â§& ŒŽÑ€±,®q¬ßðçÄ?%“¥yfz$üš ¼8·\ùO~ÓÒ]ñÒ»±+ò8(´”̱‡H6`úBÙpJt¬YdúßIRçÐÌþ,S¿V«E"Ãï¡m]–”.rz‘œ+@¤$1ÑÓz\¹ÆD‡àÉt0šæ's•%€®•[@³ç ÛH?–æÓpgkµÙFB—TSµ%º×&mº¤/¸ÇˆçÅHU6_«ÄDæN/&&®6“9õNM&†ÌŸÎZi|Qi2smÙapÈc¬VÖ.yURÛ*“FVRÙdå© !B_lþÙžÝÐþ‚SPÛ8"èãs­g Ûoøw'ð6œyÛÍ~lÿ~¤Ny£Âyâöh^¿9h+ùoƒÙòFâUp=6úÇÂNÉQ¸ æØüï±xyášò[…Ô<«só>¼<éIOäWOìÏ~÷w?áû<À]‚¤ÅÛ>Òßxö¨2éË÷Xý ·] ³ÑòìqLL”ž-}Sæ·rŒ »w¿œqö ýàÁG¨£úÎA“À3ÕeØ8¯-¤¦2¬iòÖ¸’®õÂA«}Á&ÿ*Û5åöÀý÷ó‹Ò'Ó¯Ò§À_…4_9Oå¾ÿÐAê+?TxÂñTÅǰ¤.ä8tÀ_ßËoIøËÞ7`î·žz˜´¶)BáÛ°ƒX}ŠcGP˜²ûZöŽ_*-†¸Ð¡XZ;/øÀÙ2ÓÆT}¡Äké£,=ã/èpÁÄdްÄW<Ûæ€íóÈ]r²*UÇNÊžhÅ÷& ñN¹oG´o°/èù&mÁúÑØmðfŽ–f—­0üSfŸ9úqò‚ünKHÝæ¯|Øz'Ú‰õÜ ¶€*ù‚ŒÄ€2ƒ‰]à] )y’ÅŒpE˜º©”Òð‡?Ù×.qM3”/â´ê6ìäv(¢Lr¦0áì'ÇêÓ€ì´IÂ)¿õh +%5dX`¢)Aç"=ã!O‚f†ä«2ß‚'•'c쪦ãà "M¤è"°¸6J¬½,³&Ý”Y2Ò2ÑèÈ„÷ŽˆõhÛ Î ƒ"{ ^ÆSOx Ï˜Ä[ü– ‹^8@½5C¨AêÇH¨zÒ"ÃàWOe&Ëj×-].¼ »“qh32%)xüw麉ž²d6å„.nåøbc'ÖLNsŒ<ê¥Ê¯F®–è‘ÚÁðÜ—$ŽÜª…È è'3¹–NP¤«°dG©”M|€÷–ºùÁ»]|+`¤²]~—9+ƒ&šò*wLì•ö5O¢ ,ñ‰ò8 *‚ämÚò¢ AMpÉç;˜E¾zù7ùøç›y@£„¸$רÖ&Æ~²˜+ô XjÆÀ@e@͵>€ ¼¯‡õׇYêÞ–r2aô(¤×ÉENPJ¤ˆïJÊ(TÍ&Aä³Hã/(ïÆ‘îŸWyhžªKEÆù^X.=1€×5Ù11•XK¥ëy¤¦tÕÏe-¿s[ˆû§ûÛã] ‘Ž¡ìmg6Þˆ8¬ðùí]ÂYÃÁ¦ðŸÛ­J m(e¢%€ú)Â4ùV/µ +E8mhy+CÂW/Ã^ÿjqô)x;¸"êcié[;8ü Í—rAª ‡†…½úwµO40\ÛmT{kqûcðaì‘~È•nú fešú›ÀBÜ´€¾!ê䓿¶÷íû,™g2;›WcŽîÖïmƒÇ¨DHZÚ׸Ú’Ô+³ ˆ´‚«,Åç*ŒeÇÈ‚è¡jâ{&{Ö„|ÛˆÞ¾ÄY[v¬>’¼ªÓÏÃ,‰•‡÷Ü{ÿrÉ%Ï[Þö¶µœuÖéËþèÿ¾\ý Ë 7|l9÷ܧ/G<¯ws÷ØY ‘m!ö„P£¤sò¥Û*ì6G7-áà!ÝWþMö”AG¯±¿Ô:ªÓà:rçØ¸ ¯-ýÁ²û÷-_¼ó*JŸ„ü'ñzRàQr"¸êlp¹“ãö!Å›/y l±/’2"Ïl¸‹ì+‡ÄÐo‡ôu3JUŸ­Ž>ÒÀÿéO{êrÝ 7 ÛýLÎ|])0Ú0è.%méoã’¯L~ëåè-M·sýgÐw°+ïNƒgòÐ,O¸èñÙñ–/ÜÊ$™Qߘ:¿âgY.}Ò“xöd¿6Oº%ñd¿‚´¢Ê$÷½$eÌ‚nÅ~­Š.Š´›õ ^&'‡„å[LsI<Òê¨-•T_]>ýQeÄ€…ÒŸVÍ\ÛsìGI[§ÈÍ®ÈÊß=̦w;ÂWþ87\„PÜi'å ½¡dü#ßfˆ* Ö:L*ycJYZ @ºã6¾â'Ñ‘S6–oxò$ís­-ìòÀkùQ²>†86*M8É*í QáöÔ‘n̬ C!'?àæ#1ÊF÷KÒ6Ú}\ë;:ÒŒ=Î’«C”AÞ*?ë±ÉÛ \ÆàKæVòÜ!Ã4òR«ž¥‡ã´ƒ¯Šá©«a 㘇}÷ºŽR¹á£2ê=iJıãG·U„hxU ‚[‰xÐ’g1´ƒ3­$tdOe³c™J¼Vu†A!i±¶-5b#oüaPèk7ªp°<øj,}äP*ˆÞ(ÿ’ðÕñê ?&Ê&³Fz‰l‡es€ ®×àÜÀ[mí€# %ø9“,È$B_òAJIA2J1ª”©/G1`ö‘¹l9 >Åiª(äÕP€?0’šùGh*Òµr äH)×%¹Ü:—¤†B0yªxù¸4q ¤ôRMaÈSº*(Hs¶LDù "ž Ž1z!åM$6¹6…rø02¾d$~Õ Z«^Ðx[õÙ„ëq?ùði0žeæ×Œñ£4!½½Å@V²7*´Áhl¦¬æqÚb\Øl4ô‹ç_Ñ=Šnb´½HG'zÆË毜ÆKYTl?Ä ‚YL®ŒJ¤9^JÓsö@ðl'ãÕ~H5[qªvæ§•A8¶ Y(è„'%Ràʬþ¾«ºà Ir®àZ9”)¡ÂÓNpé˜­Š«¬ØA7+ÞL`AÆŠÕb &6WžÙ¹$ŒŒ©Îeí*W^g“5e{UlJwµm2§•1~–qdwÒê)ým€£6ž£óÀúøSNÙ»Üs+ßËò]oü¾åÒËžÔ 98›CÚ ¼^oéí¼fw:6Ï´ÇÈ6éc¿7Ø îXØ­ìXxÓì£i>Vþ–w ì¸ë¸ï_n½ýöå=ï}/¢·üíÿáïð[§gOc÷K?‹Ï—B}éÕ£q,=–®å^op[zƒùòrcéÀþLXnZ>ôO.·Ü|çrÎÙç.ûöóëÅNü¬Ï´cn‹õ§Êpxا›Û79 ã—Z^Jìðo㊤¬G‡8ÉãweÙàç„IJC‡¸ÃÄùʼÞÏ€ÿ"ÒÏîs–n¼±_'v¥ü pˆç»ï…õ•®G¸[p„0;á„Ê{˜2é}ùa¥§¡L‚ãÄb4ü¸ƒ à÷ú+Þз|‡>pòx4ýž;CåR¯ÀÅË^Š_®_>uåg–'<þñËýFK\ùî¿ÿàr&ñõšo{õòÞ÷½o¹úºë– /¸  çcËüåZìä䳑…ñ%¾GíͯMøjÚlṳ̂Y”È1;¤ŽM¨wô8›ôÊvËÁ¶e+§)°LÒ¶Ä—¥Žëìe,¾ö˜-/¢ „H¹˜ÝÄ´xJ+0òj³¤<'®Õ–ŽØ×ö/-©8Œ””§]œÚiM­ö õ½øzm8‡[´e(}NÐL õ3¡ÍÉóõééa³H¾E5(Wž¤*>´&:¸¦k›Íå_S¾ÁÊ{%*ÓþýøömŒ“†péÊ×k ®ÀýE8´!XçH™’ÎC¼)“«8£ç@:÷š’ÊSö0Ëù‚k$ø5¢qP¾)T9_vºYkêU²Ç-Àä ñ‹ ŒÛ`M! ¾ÕÚ·X¾À¥ª°äÍcG Œ, ´¥÷,{€o` !ø=äÈdë`P)¥6¢-Œ,Vbtóá:S€V• 8ÿ¬ù̇Á÷"»40R•Ü}ç½¾ã•òU®ÁvÞ ¥—ÉiƒfùÔ,a¢±)­T Ìûü!-¿H¨×¤ÉÝ9ÈYÓê½ì£w„Å>ʧ.è¨Í›L)ßT>-™=Èu¦mÅ´Äø˜x\ýM©«“ö®¤ò“?4¥&Oí½U4ŠƒÔà´‹x^4è•×ÄDʤ(ÕØyÈ’t1ïܼNå#p”bÈJ§É1ƒë¡£>â9˧Ԅ‡|Ô »Ì¢-6#ÝVœì7¶18§£Úæ?UÖÈp6ÅA^ .áðÊ”Ný}ð¨˜RI±·‰Žg¢Ë¾e&›âH+¿(—4º£ƒB§ÁÝÒ²=Œ¨ÆÅú®¶Då¸ôä:Ò3Ì’ºåsWGu[Å$³˜€¯²Ù ·Ú",xÑÍÉ1 ÈÈXäXŒG)·M-Î)±°@û'Zu,e€X¦ïB½¡“”‹:%«Š [™‹ r,µß *ãôžñ#k&¶ Ê4r†¯¼¬˜[m¬1Œ+¢©]'&l›¥/–4¥5×µOÜUÇÚ$êIÉKRÑÙ²ø+kºˆGú$Ì­_ê@ùÈ@R*ätÊ.ÿû—ÓN;aù¯~ø{–‹/¾ð‘ " ýGrü90_mù¿MzËßΖ›þ³àwòÅã–sÎ=gù䧯`Åöøå²Ë.ÉŽ_µ¾Å÷ؼcÓÿÇʳlËßÎüÎù‘åì³ÏZžðÄ',OÆS–_ûï,Ÿºâªå¬³/XÞÏÊ¢î\ïÔ§CÅ ô¶º´C*f´…“¼&ŸÈQˆ¯5%-Ànç9çì³´ñî{–ÓN=¥­/–íg+Ì…çŸß ÿN~•ÙÉשlû¹þ†—·Þô‹ÈµðKÌàCƒ_¼½ýλò™4”ù¶;îXN9ùäåŒÓO_n¿ãÎVÝO:ù¤Ýšo; yëÕJ&ì⸠˜¾ƒås°©×šä¤OŒÆwÝE}8m9ý´S‡>x':Ñ€Þ½÷ÞÇÄá¡åqœ_™[z¤yãM776¸õ¶Û¹>;j'-·Ý~GÿÃG¯ìÞq’“™m±Éû•œ¥±=lëlÑX,éHÓNÔÒ^Z{)€v° MZ›rÔæè¡Í%V_/ 2êwû°¸,y–ÃS‹/ývUp)ìÈB×[»Vcdƒ% gF@&Ëh¸±æÔf9®S@&CB]Ë2ñ&OñÉ“š‹ãöc‡Äõ0Oc'Äoû%e’U‹ÛeðEQv³%?,Ë ró²W7fxÅß6Õ1D: áEÉí®<Ûå-ÇŠÐ@Þd“®#ƒ—½&\øœ%/öèJ¹bdv¥1ÖŽÌQ‹A °£Ä…_ vò MœÎ~ØÙN³Òm BùÆC9ä£à$‡´!=xg‹Ž*‘2”K#?ghHý8£ýt˜3I°0“‚¢ò§UxySXÝ´Sm8°6¨é¾ ¶ ôBpň!¹É›«2„©$·¨Ãä™¶XYçîF¾²öÝC;r¯ Ñ.Ð#¹Í.§èÛ]“*pUb àn¦ùÌ€Ë ã’1«4£ M’àxyìAN—ŲxÎôù^û®•Z~ÜMÉn«¼bw¿­ræc”p3”’…k Š|ûR“eAëÙ§º5ä0೤F[¶ò5&ß¹¼ìÉÊXHÍd#LéçпY9lq–¼æ§Œb+ÓÈß _ÊSf}êÕ$z¬xpvÒÖõ¡á§ß‘{d_ÈzÞ&Ö 9¯SÕc`€’Y<’'¿¯¨ÚBÝ7Øá!p±8@£G@«Ÿ4äÀÊÕ-vù'£´½wàCÈÄ:0Þ5PqƒÑ—küè1us`ŠòŒrK…÷yë̪¾”ÆøÚAuS+`”K’J ¶¶r¨.¶GЩ«C§•ÍM|”ÆØ,9Eg¨Œn±/f¶ƒ‘SíÄEkÀC:™¨c§`F6¯:D&TÙ¨x’ìlez X:!ÑžŒî‚ø=í©Oeà~Çò»ï~ÏòÒk1¿ÿþå—~õíËL4|þ;¿ãÛ·"rò)ËÝ÷ܳüÚ¯ÿÆr/“„C‡Xžö”'/¯zù˱ùË>h_Ëjþ&47Ý|3?·wyã^¿<ù²Ky¾ä¤åæ[nY~ý¿• cÅß»7Þ|Ëòø /ìîBý_ŽÚ$þ‹ÏÚÚ;ú¬1ÏÚÖÚÐáþÚ›é§Ýò›V vÓq_~”‹,³NDŒÐˆØÖÖ¦`Ç£wŒi"d»e, Â7éßñ¡-j«³Eàâ\`§×˜vihϸÀ4¹’I§®r[f±<ÌñDÚ6Nmöì—æõÀ”+y[”«¿¶ÙMGgŸÜØPºÓ.Êíò5=vÜ`_f3š^Àë䉖ì€Ñ¢%?‰Úùi«[’ïV.ž5MÒ¡*½rŒElß­ÂòÑ â`¶iŽnsyª·^Zæ¡ró¼Ý±ŽSÒ8§Á‘Lµ¬²t˜1”Ƶ£Z]íE`ÉCYÊ’Û ›ç˜i%v3™%Ð) ,Š0üIc¬à•5±•qh5c„ÿºvUak°«¡ÉÕ”Î'ø-·³W_¸JVè œ,/BÒ‹“a§ÌDCSÛVhp ¾ Ð B¸¦£6ÕŽ„wÙGSdZ|G þ¯×+V62ôånÀ¹ÊY¬x*ìாN†ì'q>Ûy½\c§¸ÑæÔö Ô´òÇ›TvÕf0"]ÐFK¬2(ÛØEúaómã¼2`ÿÎÒ§óÈ$yžlOTe/ÂV¹wq{ó“òÞâ!¸ð$ž„òmÀÛĘafCI¾¬k•.-õÒv6îÏ›ºd3 ÎŠkÌ)ßèàäT¿õf˜l#÷ÙįÈkWß5RÓÃI¦BÜêŹ™?YåŸÛWûyw¦C½³ Wë@„d_••¼ ^¸À$?6qEÄ?J›Ø!nÆì@W’ÚÔ~–ÇQŸJSm¢ü–‡€kÅ–£j–2ßò_|s‹eB%ìèåP|é¡¥|BªÚ Ì.y'›\ÅTV&Gż¸£·iÿ­?úÕ3Þ6^¥×k™hlæ>iäRæ|†²¤ƒØ)a|ŽÏ¦“ {‡¿¸$² Q|ï"Šñg¼3|»Ðd=ÛÎM¸þªÏÈd»v7«ã_tÑò*&î…Û/ýÊò‡øàò2ögŸyf0ÿÑüû ÷o~ñmËo½ó]ËåÏþò¢^Î*ÿ—ç<ûYm«yÚ“/ãWš_²|ôc]~ògÞÒÝ„W¿ò•˧þôsËk^õÊÿ¿ÏVšöÏÿEƒj'n!rð®O7ù­0wq÷á…—?ùæ¾pùìç>·ü«Ÿû×ËYÈòŸýÇ?´ÜÈV£ÿó'ºs_õ²—-ÿÏ{Þ¿|ÿ÷|÷òìg=sùƒ÷`ù©·¼%™¿÷ß½\ÍŸ§\véò&Ò·ÝvÛò3ÿ×Ï.Ÿýìg—oíkáùÈòñ+®\~àûÞÄDãqËÛ~ùW–Ÿy Ï™œqæòò—¼x¹þ¦[šøÜÉãÀý‡ÚÂäñ6Y¿â³}>x~jøÂœƧ kW_ÛÈBí·m9_v”W±t€±_uF`íÏÖι ¢~Þµ—+¢u©q$¢gÈ+oûÄÚž6víÿadKÞŸ<ÓËŸô ܳ@;ºIo⺾Ûö?û‡Ú=øû"3­ãŸííŸ$¹Tz£¢ÃÛM6ÚŠZõ ¥C‰J“C™6W×]ÜR}9ÞHËÑäÙ¼ê%eBde TeñÍ¡ }®mÒÉ‘8ºX{UM£› õVþ½F;eDeC ÓÝên+ Å!Æ¥% ámHÔ§·M–òI½¡ÕH‚fЈ(ÒÐW^—:}{SŽN(Í5"$=·=`JÏ%' ößn5QÊl¤e*²§p<‘…=Ê£ÅÊ]à uK@ìc9ÇŽ¤A±´<”²ðÞÎV›k“­6ùÙ"ýi³BÜ©°’ªhÙJÕ¼XåµaN–•…µ\ÙUR}+³‚òï€N{?ûí}¨ÄuwdÔïàUîØÎë¥åÈ]E K½ä%oª­RžVø{>Æfâ˜ïI›û`©r ߤDØ•Žc; )Ï–éŠd¥žxê hd È Õ¸¬‚#@ö†~|UéìG‡H†V饯@ONÚ¿ÉŸ"$ tL'Š7\å¬Id>²de„´á¯5ƒ¡<£Évð]IhÛ˜˜Àç[u‡bÇ0†+ÒÊ&7¯Ó ~A+H«{V‹àáïokèGežz’´‘Wÿh{eüJ‡fšÕç)WŒ™s&ÝŠ3Ž´¡-Ž*çKmõ w L‡YEz¦Qy€ oë9Æš²J"!¦¬k¾æ5›ècq °.­±¾„³ô²(eß©'À /›\·3E%>¦F.ä "éž)omsôà¹È–ùì¨É(× d[ØB¼ù(ÈÝí±ÍSWr,Ñ~:Aí”Å\ëtÚX|ä¨$wh©90M_‰å!sb€T“7ñü³ÒH߉'ñ¡¥ â¢âZ\øÖ›¬Ó6€c'GPš—']r1ä‰q'EÊŒž–ü»~«å_'}kS@º ½,g°}˜ÕçÝ˃‡Ç÷ÀÄŸ=u€x²N[wŒ ƒÁ J/­&—gþ×p@Çvßm;_ü„åš«¯Yþù¿üÉåd¶õÜðÐò⽈»J‡—ïùÎ7ðv©Ëü/ÿëòŒ§>yù½?øàò¬g>ƒí1,œwNûí¯üÌg–ç?ïyü0ÛIËûþðCË'?{{èyxû‰/¯xñ·,Ï{îs—ß{÷»—+®üÓô¸òO?Ûàþd¶Õ¸­g/Ï?lí­w$Îf Ñélçy÷{Þ³¼ùç~~¹øñ.ß…×\{Íòþ[ÎåŽÄw¾þ;–ûxÀú¿xÓw-Oa…ÿÍ?õÓËŸù\õsÞûûËë¿ýµË…ç·ü{¯zÕòùÏ_µüÿù./ÿæË—Ÿü¹·ò;/Ynçy’×¼òeÈøÄå-?û³Ë½ÜPïnº‰‡µÏZNC—3™t|úÓŸžú¿Ú½¾ð«5÷ŽÏLðïÊv>ÅÓkÝÕ÷½¶šüúÚh®ºyK­gN¸¨CœØÙf*ÿ ¬a”×ÄíDh³Å“mŒ‡p®l{]ëdvrq†¦/P°¼±•p¦åe¦4_àš¸’#K2ž `]ˆõz·ó”³•u»“ýŽ*˜“î‚C@Zæ:¨ŽX -ëÁQ]WX·aJ!©ÚçúRŠ_åQÎÕÊ”[~ämå’etMÓw…L»,|ÙW”=¶½•©Ül°Õe‡øË/ê-ºIð ­"~4½^&¯UjÅ!&Ét ¦¥aÑ–‡Ã|˜;xŸíò“±64LË ù$àš†Ë:½¢I8®_PQ„Q·"ðo²Ìt%­y›mÆ{v´®µú׌ö= ¬$GÁ†À‡Y©É5P2õ'Þ E޵zÛ8Ê0deeËøä Ãapù'Üì·ã€°òèø6[=u¥I¹z"’ÖP7¾¢ïÉKsWv7ÃbWÃùƒ0¸¤”-@($³|(J£F0jR\ó‡¶8Ôg Ä×ûS"ðÚØrÕ[^ʜĊá5ÚDódKà¦Ê“oGž`àdƒˆR†¢x”)î+^+Ø0«Ç'ÚÂÛYÃ_Lø ¼%ùHjÚÅÆ([Àd w²¿Icƒ‘îê­òÍ£F¤Ö®8ÝË{Uß>=2ƒ}îH'{H[oÕWšÅPøÚeµzkmß]äm‚²êݳXSû(orrN2Iv;ÝaiëYÉJÍ‚6ÛY'ä©Ï°‡46{_\{ª&ÇWšÅ[p+åä9ÚH”0ÐF9‹à· ÓäÏ]*™JGß!pü¦íƒB/›)`ur`ÄlÌVwáÊþ×6Œ+ãHú†Aþdð) ÐáCyˆ8ÑR:ð$§oÌq›\¨[þ¢^=Z*1WÍÕ'ù…ËyÂø7òHJ~µ!ÚÑ¥pp’ŸBDƒTñ]®ñEPé Û£ê‹ue3¿ÿáºEœÌ1´4¦2&硈Ô!ß*³ŸÆÚ³çœåô3N+Ïüñ©°ñ±Á*Ã_æÎ_–ÆŸÇÿ/¢ÿ•ÿy´ÿ*Ê´•“µÓØkþŒg=yùÓ+o_Î9ù´&S%&èõ{Cƒ#Z¶bbõ—t¸—Ê_â8Ì[|N浪®®;ˆ?‹É‰Û`žÍÿî{îf¥þðré%—´•ç¶0¹%ÇUû½ì¯w›Ï>ÀCÃwp'à£lrþïÿÈßm‹ÏâË?ù±ŸZþñßÿyVà”ÊÜd¼:Q¸ýöÛxÏ!ÊN%϶ٻi¼5 ú—^ò¤î |ⓟ\^€,OxÂãÃyÇo~d¹gs'åtöð¿ïýïïa^W÷?òñ?Y¾õ›_¸|áÖÛš<(×eÐñµ±øÁ./}áó{vÀÁ™Ï\{ÝõË·|Ó { è·q7Bz¾ÕÈg®¸âSË“yåì&&W_{ír&eò¶©Ú¼¯ÁäúÌEˆicð°í-€àvkbÍ´m#J»ò£ÏÁ£‚—×Ó`e›T¹-¹¶¶3¶õ»íKÌ›ˆ’ÄN¿]ÛµR vñÜ€#´„Y{¦i+lǤ5í’’×ôK7ÙåíR«çs²I¬6Ó¾JþpØîj9s‘ªÑ±ÑsÜÚ?@“Å>DÄB]à Æ,Œ© |m‹x #¥É“W2÷ÍE«Ãw®ÕÅruM|`Œ¥íB^pꢪ\×÷¶Jž# ú? ]Lv¡lR6ÀËI° M)Î=¨*÷ã~’q°"ÿ&¨Œ½eÎLLkк>ïYk ò)Yû Ä¢Ü+™¤g»éhË‹ÙZ@¯Sk §COÞ>x¨ˆÊŒÐw5:å½ /g"ÁÒC,ˆtúk‘ s{Šg®d02`¹l°`c Aul¶ 0ÕCþt¬Ê+)až'†ÐänHÈ[9çtÄc&$´3XÊv·‡tö¸ˆ|ÒM¦,#3{«¿F±c/™¹bçÏA‡tÆá€¢»\g‚@ žâif·5ÌŠéÈENÇÑ+ì™ÀÈGC«·ÈPÙuš:O£ªÆV¾U²´[‰Í@&òˆ¯ÖÈ¡˜Ìä²%öU.3E‘²˜Qæ«3¾QSG{p& ¸–•ͱŒ¾#v¹k`ÌéÇUiD*{’©_Ik/£O)æNùê) ò¢‚ã-dó ÿ£) Ãrxµ/e¿L®TÐpEåàK\%]Óùwt•Nø— „§aË»)úBkËxúŸ³I­ŽüäŽÜó@®7Ê2(¾à*—˜DÃè¨2´/Mô²Þ×fÈ@IL¬_ŠÁ„Ÿºˆ+ ¬jÔhøÕZ=C®ÂûÜéruÄï`ÑdN±pÚ\šŠ‰ÅÏú['À?ÙÈ®—ƱÆÑö2á;¸lD~åäW¡ŠÊüâ.É”H+׃¬$;˜œ¶J¤úê·ncpQ%a¾´/Yé(öÄýWÈÿËýÙg%íQ0Úvêá€ñk=Š{õXëþ×Jç+ųÿv``_çlh¸Š7£Ð±ÕcC’Ƴ,®jKjl_¥C|ðˆÿj¾¥«í|¸×}ý{÷îi½oÀ¹‡Áñ¹ýSدïó7±Þ7âø€¬ïû?÷œ³—}èÃí‹wÅþà¡hYþéþØòìg<}yÊ“/[¾ýu¯]n½íŽå|V᯽îÚå'ÞüÓËe—^²|ñî»Á{æîC†éo­_굇ë»ï¹oy%[ÛÜ{ïÃÆ‡îô^Û‡ú¯v¼y¸ßzë­ Ö÷V'>sõuËúCÿ!ôï]NäÃAVõ¯½þFÆ>»çžûìg6远Wð\ÀG>ú±åm¿úk‹“…{î¹·ÉÆ•l[zá ž—¯ã`',GØfWÛÿ¯öÈ›Ïðq‹iA—ï´ƒÿ»¬›Óª–\¯¦w2Àzé?ˆ'ùt4¦jßl¬\œ0{Å™v×h¢Ra€mŸq'Ôs"sµöU‘Ezö-BÙN5éáÂ’òö5Æå÷ˆ[{Ö#öŠ!yl.Çú«hsU™ôÁÒs ®|.橹=¹"ÍaŠ\øÍ$ÈKù›?Pmì–°êKmúÜuc2’ üíšÙÉþƒ2bS+°pç,QÀÔø¦I4»'á¶€z5zRë²@•sÜS‰ äIC§¨SÌQLu%E5M¦Kˉ—Ð¥|5ÆõÃõ¼.ËÆ\;ŠØ#>í¬[lú“)ä^ b<Å*ÈäœÚÌŸº¨Ÿ­î"¬¤åÑ›±hPáeE–kåéÇ"àQÞ)mŽ—éNjHÓ¨jMHủ.A†*ÇêÇÍØéŒÑ·™ôà½c;9é`õ0Ùø:œk…ðÔ}`äíuAj1N-01TT•ÁOôÔ÷è!„‡agi˜Ì¾qe!T¸lkg+$§äÓnöt'“™Âs®œïéT"2tÕA\¿HË«m`ùÁ2”£lÅȇîq6#H*C&R2bøÁöÒ¨eS)™:ÁÙà"6šé¯ôµ‰ug°ä9×Ê¥Îöûù»DŠU WÌ“—k ¦aP*‰@“ú#]c%Òú"%2W}«wœÜbShý PpàÛî•× >À«ƒ±ä¡˜ù 6öÕó ®Ü‚GÐú,’"’?ÛtÄõ³2Bä,(GnòŒ?Û¡?~åô'Èý“æQ¹‰oר¥Ê-•Ò|5È•¤ %ôÒƒk)Ù`{·d BZ{j£Xx¬&Cᕆ´í’¾‰×ú¥ Ai}¢ ÂóÑ\(‘–è'ÉDM&:JkÃnb .YÉ6-8™hÄ…eäÈ ÊÕÒ²!R[€0Æî´ºH¤¬©;DÆ›™µew7U†ìtZËÔ˰±=®b“–”RØöP{£ä↰¥_/I¨s«rœøˆó˜ËŽ-']ýA'|vÊ w,½ÊEßI„´°Õ q öXZ•~ïm œæAs“Û¬–tÀ’î¢ó%öxT™<Üzr°é/ý³®­Û£¯Å{¿¾6sâæD hWNÌëWc,eÒõµ¯Æ‡qg‡e›ï7º_õþÒsÿ¿Ût|«’oıÍñU›>ðê`Û7ëxGÀë~òÊöæÿϸ%èïú½å©l½¹™i/|ÜùËßúo¸·üüÈßý§Ë/þʯñ{ÒN³e ;»•æWüéò›ì×"o¬úÞ7¾±‡¢ÝSïäÃɨ|õ©¯ñtO¾oîñaàøèÒK.éYßÖãµìjºòÓÅàlGº y?É£üžïþIË»y]¬‹‘>|}š+?ûùžUx#[‰|;Ї?öÇñ>ãŒ3–_ù…·.ø£O,ßÄ7|j³-Jž>(|Ë­·÷ Ò¯yÿ?‚Z/¶z:‹:Ù¶ÄÆ„.íÏëí'õµÿœÇí\pÌ÷£RfnƒFá°õ°ëàlŒØÙzxö°ýi!‚k›XcË·ù\Á{m…¢×ÖÒÇ™³ "­IÏyÚáK½”\}ãΘS®@ ùäÐ~lç]pU´t6!¯•]—(d]½¦ïÀEa1wÔþ’ÞÙjo‰|Ô§±”„3œeœ¢I3yDif샵 ôV[E÷²ÒúEÆ/* Iê m3 $Ô+bbSÖœÙ*ºÌEU¢C m ØWǦˆVM) /-„òŸü8¤ ×5i @ Ÿ¡—`f¿}H•´,nžË$! /ì½Ä#½Ë'9¸l6 }”^åc¶Ð.°&Ø…þ£‡³Ð©$’SBh×–çÌé<¬fe\ ”z°Ñ^®g6À5=t:lH_y+€¶N{(ƒÇH OR ¨MrÌŒ f­œuƪ{ƒWá,¶&YBº"ùz;d÷o­Fé’H®ce(mŽd4 ß&*«ýDèÕ£ŽÔ†5¹Éºm‰‰~´Çs=º‡çr¸¯ÊFÚ³tÈ${½6nܶ•/·tµöÃÀVȤ‹úv—:ãʱ²Å{Õɧ;4ê5¢˜Á–†Sœö ¢øf‰ŽêñŒÔFÇ3Ž6\hÓ“aŒUßt ˆ ÂW‹ ¡¥;Há«W·.ù6Ðê2( C’?m'±!§‚ÂË2nËN`•/3eÞ7{ WC4¸Àø—Wò‰:{†Y6µ=AWÕ3>ø.ÖR@Îöåa'Y’æ ¨%r"‚ü‚+–¾6 ”Uº–‡©u@UG #þÖ(§-_m»’pù’“õGº2‘‚q­-G&c“"?Â)¤ÎÄaB ,_þ¶;<\N¥€eè¬Ñú?²ËÚ±€»¶„R4åU݇ýjœ¼ÚX ñ•ÝGul¢#/ôÔf ÏeR±• »¢ÆüdN©´ü)=¾¦ó^q¡×[.àÓ3JIJ’xÛ¥/¶òl»ö¥4±Ñc@<îeU÷µßöê4¿ý;ïb»ƒûÑÁOpìåmrƒ CHfy¶kùŒA›"¼îµ¯Yþ„-®úúE¡£L¶¿Šãk£¯Aà ]ñ÷ñvßÚòŒ§=}ù½÷¾'ž}ÐYyö±ïûO{ÛTžÉÖ”ßínÈñÇûCN+x¾Ò}´<bnKq xÇbù1$ ºj²ÝØž¹hòKþ±6Ó>µ/Ú ,a3–~•/õH»()×oqô!—Æãg1ª íã§«ý¬›ïŠÊWù]íík?Ï$|ÃŽoÓqkÛ]ðò>~Åg–«®ºzùnÍî³÷m@ÒÿïŸÿ–=£´o͹êšë²ÿÿ×ÿåòöÞ_ÄCÅ×óÃ`ïÿàG³ÇþŸüÐòË?ý㬰ßÓ|>þñ?^Þñ;¿·<îüóðçÕ&Æ«ú/má¹êª«ò¹Ï ¸Ç‡½ó¡ó¼pçw.wß·ùЇ?²|ß÷¾qùÿäk’p!wÞÇÛ‹>öÇW,—]òÄ~‡á¿ÿo~xùô¼ób¬|ŽgîÛw`ùèGÿhyÝë^³üqd?qÁyç÷¬ÂçùÝï,ÜÄóñ\í5Nú*m-¸õÇ8"6 –\ÅHÊIò_ÝÇÅJhÆE­ƒ¥}oö!ÚMû3Ö£Z,Òµ-dÖnTèBÎÜmöRy+‘®íP+÷$f]jEŠQå!éT½‚—ÈÄ·rûï•C ¸$¸Æ\åIˆÐàÁÙìº1SK¼¾gP\Ú‘§¬à«„àµçÚž…1@IDAT1_û mäŸù2YÉj/›F©ï²~®tô‹ˆY¡ÛK(Úqép[É]i뀙lHY3Xˆt³8€Œùâ¬Ì‹ù ˜hõ3‘Ì×l0Ya”½x97Þfpô›¾ÝK¦rm1HfÐÒàŠY'¦äÝT^ … nâñ(êC£BÓ‰ÌCy‰ÐX%GBR$†„yó'ÏNÙ ¼5nÙ Ûàù唡­–+¹Â*¤JNŽå~’ўݴYkù8…¼õ¼FÚ:¢‚PWóüwpߊ²Èfi X5P·Ã{¨ 0 W×Mðªk,a®ˆU,PE’–6H{pƒò ÀòÐTWƒ§ç9VxOŠCslƒV ×ìðáñ=ò4<•ewƒj‚•UõG~®£'‚„øôjÆÑ&bpàJí&n¬\íUôG¥´Çªo• ~’™_¨ÕFåõ¼¾ODè0ø)Ç<”yQ½˜]ËÔ•/LN´P°;eb™ÈÐëfuqP+/éÇP"s¬úIë¸õõ¹12y°ã ÀMc ¡§o‡ReUr¯WòÝk$fGÏ[sꟺú'±lËy| Ü“7Tðab<ÛY&àĺ–+ÿØÌëáJ>y Ô•]Hh%Û ù-8yk Š+,vsp’%×róŠùuŽx¨›^ІIq+³‚PŸòQvèÚá¥OŒ'>“Õ2G4*( ®g[™ŒÌæ·Ê¹Æ×øÇLè0‡$ºL™)—ñÇ5üe£¥7clKrÐØ–©Ì «½mçXåÌ#ñ›O»`ÜŠ2Ì4ƒp3ˆ—¼mWVAVy¨JNTÓu«ïÃcrø%èÆ@£QŽñ³án2+á½ p|#\{7ú‰'œØÀÿ:ÞŒ"o}ï ¸+›x`Sîvp cíÛ(` †«³§ñ~uqˆ?žZ·ŽÜË– a¥!ìaad9@ë¹-uàKë1ñÅdÃmÒ78nµðõŽ®8Ÿxâ Ëçy0Õ˜7ßÓîC°nqeúÓW~¦U|ùܾeǺ!¼o³QVCpvèGž¸>ýÔSy å©l ¹~ùÞô½IöÇòIŠ—DëX;*µÛ_\‘VV÷¾k÷Ë»=Å‰ŠƒaÐNäí]óÅvÊð†1‰)Œ×™iJÝ“…½*‰È3–,ÀÇõGš1ONìçwh–eÑ×p¸ÿß÷õûCXŸâµžþÕÇϯ¾ý×Ûªóœ§?eyË¿~ëòÊ—¾x¹ˆýþŸgýÞ÷½Ù‡-.`ðþ ¿ôËm±ñýþ?ö/ß¼¼ì%ßÚ¶›÷ÿáxøƒ½GÿO>uåòæŸ~Ëò‚ç=Wô–¡O~ú3Ë›¾ë üXÛvvâ\C,݉øÍwþN±¡­÷ãë?÷s7àtb@[˜m;níyÑ žËJþÇÛ®ô|ésüÒ¯¼}ù(Ï\ò¤‹›\üø›jyòŸÀDâSŸúôòËoÿµîj<ûéO]~ãïbâsgw2ŒŸwüæo/ŸfûÏK¿ùËoþö;{eèÅ]ˆ_ãœàçk9ô=>­3ÝFÓ;ÖÞL›QaóÀ˜nš&I`;¦Ùá¼]¯‰tL›e»7RJü›Æ[*cðoA‚ÜŠ(¨ÆrPmb ][E&Ý$q~ ÑkKE.=8;©P 'èAG½wà”IÙ×f×"è PжMem‹%ÜaÝ ®Éß½>kJ±´–}—¼ á쇔W^3ƪu~èÕžBsÄ1•Æ· WRm·-šoÛ« 7vW¾µ'"CIø;cçå,AÅÈCÑU-„+¬äÃ3ƒëlÍÞ æºÄÆ^2 浤,#?Í(’¶kßí€ËàÅÕô¬ðeBOGQ ó{G58[~Jâ@P7;Û €n†h®6µ¢¬6LÑ·}ÙRXàÊŠ?d•+ÈÊO/ñ½D.XΡ\O*£ÜY!B„*C‘|=ÜN"lò«¼È­¼˜]¹Û4mËIvt×.ʆ äY×ÃAÚ¤É/ ÌÿÙ{¨í®ª@ó&ù3B !™ dA$  hQ DK(µÑeõàD/íªUÝVuu[m£ÕÚÚ¶UH—È ˆb¡¢È Å, !„@IC !’~žgßûý_~£’r¿ï}ï½çìyï³Ï¹çž{_A¤¯ý9 <ÁšM<j É:>ms°S;®<‰ñDÚÔ þ‹Syè'eJö‚†HYfT´î?{¼É¦oäVCÑ®S" ËK* *» µ±‰ºÎŒ¼VZ ¥<:¼FTÌpž¨Ph¨ké+·ñ;ògPŠm•”|X60µLRa/9ŽÃ×G]~S,28#›Ñ‡ó™Í§D+Òj™HF¿å@é©{”‘…'Vé®Ú2¸-“G\ƒŒ#ÿôÆÚ#¢ñ¦­¬)fÔ™$7–ØÖ&“ å+ÇÒÈMrTxwÑkt C¡ö¦%{a ,ú rJär¾ÍnåŸâÏ×ÐΉS©›<“Ÿ¸˜Ä¬ÒR?k"~ò…Ò#ž¼8p¦<œ8ŽøIÏ×A(s“4µ-¥ÚW9ÚV›ª! Œõ+i(‡àÔ~’oå”éëÈQ&ú¸)#+ìÄ øÇ¶µ™9…–`Âð-#þu³ú¯• LíàÃçK±b²ç»4K€B]Û@±É䫤óƨÑkë zž‹zåñ"pûh6wÔÝÀ»Ï}=ãi§žºÜÄ€ýïzW³¼¾YÅjrÖ¶70>äÐC–‡yfè7¿õm-Ù0n˜?ö+Ý[R®dæÖ÷ÂûCJ\xaK4¨»ŽúpžÀ›U|¤ƒó·½ó †¬#]ßÚà ×Yé;@—·€*w\Zòd^ùPds­÷ÛÞñ.4¾=ý•ÙK©wyÉço¸¹_¢}ài§uAãàðsW®·ÓxÇãô=uégÔFÔA¼¯ä–yðƒ™ýÿôrÿïÇ/ËòšGbÐuvœ_[>b9öð#¸09¢‡X]ÿÚ×ýÙò`ÞKï€ó:.œþ‚Á®ºÜ€]ýѪ³yõ¥Ë:°|óÛÞVŒx1Ð…>ï &¶KÚëÏÅ Îs†§íÚ?ãÚ¡{‚µö½«×«ùb¿ä®Îþ(—ýÚáÜ ±EêËKX¤ýÁ,ýõ{¯y-=7tqpßãköÿÎ}Ͼ[^|úÊÏ,ÿþE¿™¿½³"œyÆ;ÿ‚,ozËÛçÙ{ôÃÆkAÏl-þÜ%¡½©0Û5W_½¼ñÍoçÍ?÷é‚U}}–À y¹}ôò¯Œ÷äÂô½ï{?ôßAÍ-ÈvNæý\à(ÇU,%ú÷¿ñ’äòÐ »îúÒÏó7ñÖ¢Wÿñë°7?4wô={°yïM{ùÕéO%¯ŸÝõ‰ó?ìK»6«¾æ2wõF¦¥v Çõ€Ý5²_¯ìvÚ÷~ì«7N‚œ\réGZ®ŒÊ¥N^œ8ã|9Ÿ~†åÃy¤¦¾”÷Ð;È~"o¾ï‚ –×3ý=ßý]ÍÊ»\ã„î×;ß_öۿÑO³åi=ê?ÝçÞÇócVß²üêoüwŽlvþîzȡ˵\àhíl`eGfœ¿â¬³–'<þk– ¹è¹žÁþƒøÀåÄûˆ½¸ãÀù)'Ü@ò?¼è7–³¸PùƧ=µçÇ?ù‰ìà’™—1KîMyMŸŒ~Šv¼oÕ÷åæîiSúylgLÌÆƒ?~7¶ žøæàÏAµñäE̶Ý;1ÚÂ;æ¦0 ®È€5ž»6KoNŸºLç§<·f½[$ÎQGÝŸ²ÜLµ9ÿ8kù_ô_RýÆsö·4è?éþ'ŽWÜü±04oüâùa\$ºY¯¾½ÈW‡FŸ//bÜnÞ{sB®LnòîÐB8ßnäg|.§n.=ÒWɀ̊þÝÆvä2jÑÅ\‹}”ÅÔØ8ÏSn)_è÷±çðæd×¶sVÞ J o© `ê”Þq3ùÃþRB3FJy΂¤Üœ§3ÙA KT*?ãF =Ï0”)¶Ä B‚ä3qý¢\LñoqËwælr¨6ˆŸ°ëì¾ÇÓn&Ø?´Tg%)Nt3Òð· ›gâ-¨¦s¬þ#¬Ò$Tòçˆ$òдçŽ0Ž#ÝæM@ÚP€å£ ¢0ßµoäöŒ_ÆÐËà)Àü×½ÛùÜŸŽâ\¹älYaoÇãJV~ ¼ %±„dÐ[I$pê!œC`žøÓÈ%$I‰‰‡~è+í*,.n=—¯@òtm¢Wv‚G å>Áô6ù„›ƒu„ÖŒNùÊ$Úò&pmÛÉ}:9¦‰·Ž,>æeGš.”Ã6"ið“‰3÷€fg“µý E¹õBè˦Æ_ê­ªÄL LÂC9õ§X[#£6`ÔÓXÐúºk=à8ÚCiñ1W¯{Ø×6Öö9å¥S°X¶±e'éÁbb±¯ Ë º/mN£9¶J:Êí‚í0³ôôs/]ÐÚåÊ—QöÐA"Äe*CpI(Λ‰¡~Ã𕲂n¸Hž% 0`ÉcŒB[˜r:Ídμ‘Ä(/BÑ¥0>´è ÓÙéW±Ôá?ú#Ë?û¡^¾•å.¾ký>÷¾wò¼‡%öÑ~ÉË^¶\Æ€ì›xk‹g:°ÿ†§>•™Û»/¿øKÿ÷r³ï¾Må§þõO.7\uÃr¯O¼7t>À ØõÛþÂꕬ£ÿ?þ¯_Zνø’å¹Ï|Æò]ÏùŽåÞ,úïZï5æm@ì~†yúŽoý–åP<ýù_üÅåJfhç"âÇ~è¿e@}ÒrÞû.hyѹçžË ñ7—«ˆ=wžóìog†öhèРý.\ü)gyÿ·þìònò|Ë:~âÇ~´å).ñ}õ/å¢âmù®xü×?ð|f¦o=ø™—lF›‹môöw¼sù,ìWvqåR¤rôô'}mç¾'þ‰,ºÇ‘÷Xþ￈»'pgƒ×F2ˆu‰OÙâ–#Ê[]°Õ¦ŒyZwµÍCF”¯(G ‡>58Û¸µíSÎ!6ŠÙ‰hÕn3nCý‡ìk‡»ð#:”¥[ÎËÈàaüvÁUÍùÀ{¶…È0êonŽÄÚûð+ÓG[]û}çæ7·á½oJ•ùÖüµã&A·… Ž’e­—ò{®ÐŽ3ê£=ÙXŽŒ¹–ÑPn5ãì^²=ƒáM“AïL\fç|X¬çw0†, ؤpù›ù3ÓÚUÚ7YW~£mIÙ¥ozÀåŠÁb'aÝ´!…Q`v»cy4ñ¡øhWqWûŠH*krp1Ë ¹òv‡·s¾Ù]x$6¿)›¯Ï»VІ[òi´´XyÓ‘¥KQ¢Ò_ÓH <¾:ÀíãMIâºÔ×ÖØ$›ÒØ »_wÓ§mý¸GZà 4„¥€ÿ´)+L!’q¼«8r’¶Ð]Ú.¡¤Eò' ¦£¥ÉUZN½ÿgŒuä5¥¢„$'Mg þm䬶 ø¼O›úì±7†_Ýe¸òÕ,¨N’Xé(§Ý›#IàƒôÔ𮄀l@¥܆†œÄSwe1<‡WÁät!td=5+p2¨uâ9ÈÑ^¢Ú©[žýM¾ž'Pц7çÚB_” s¦È R^ÁÔ„=ES§Õ·7DÈÏëâƒcïÔHS|‡Q:X•¶‘ò¾M87dÞIáÛ7hÅ-{À¦z -sNÚq6зVkå˜ö¥ø S•zCÓ‡3o¾™dbcÀÒÕ™ƒÌsj»Ú›~™Xòo¶±£WóÐß:íšo°› ùü^BKy£ob£Îz×ï#»BþÙBä§ÿÆ0#£ZIÞDç€\ m ÕÍ^ÃÛv!+ý-Ïkž* p‰ÃaRÑ#;éB€™-}åÂ+б~Hl~‡—6:@û(ç]¡ZþµüÇ«ìãùê@à8C(×#šÐ!<¾–š¶ÍN<ÛGFKBi?«“E~ÃC:žxqá¹[Ù¶lM](ׂ( ‹W£¹t l) Ûô-á/<™Ø>aÝl+ÕS%maÔÙÜÊ=ÒÌf©H\ŠLñ®<ðq!ÝÚ8ÇÚÕu­ÎjÍ$ÄÄsЧI!ã,Íê#,¦b¶Éô²Z¹•hÛ±¶¦?ùªµ*›ry40Ú«Ò]1’.˜K†ÛHóâE ÂÕrE*FðÃ\Tÿ&ýË·óm¿ñÝÿ|+woüFî–y¾m¬çÛñß·ß »ÿñ{¾ñÚ·•}ñ{t5å{´ÜòªpéÒbÿ*ƒÿs§˜òn3ÐÆ?xÇcØ_Ô×®v5ÛÍE‡Pö—eàŒcÊ<•ž¹NüƒÖI £Ò>(d d¤åˆeyÇq2–=¢hë¤\ÕfouåÇ(æ8ý¥w—8šÞ€©~:"›w#{ yœl† y# <·Á¿{eu©Æ- ¶Ý>ÿ‚÷/?ñoþm?ÐôË/ü)x=}y#¯Ftë Úc,ŒW=ºÞ߇)ïÁLøï¯Çô ÀŠA­ôŸõžÑ|~Âãß]†_zY¯Œ¼‘AïýÛŸY¾æŒÓ‹ÇxÞw7àv°ï~ò´]Оы”h&Þ7³ø.úü¾ïi€þFÞÓóԟѳé§Y2äßà¢à£W|œ •{ñJÈvq!­ßâbç³×\×…ÇóyÝäÝYo ¸Gò6 ßÖóá\ì3Ÿñ =¤übî†x—à½ç‡<\ÜbˆHrÆf飷ڤA˜œ¹ÐÞx1\&;‚ŒÇÝ¡¶ùw#åÛ„ÅwØöËFàN>®¥¾ÈàI‘i'ÈÁÓ÷”§ bÇhÆ´:¤‡âË„­Á7rˆã@ÝñÀÖ¶<^Cpö ¸žcÌŽ †ÆdLׄŒþÒž¾Ê¾Ñ6³AXoìÅ…«Ìlh<›Kõ“¸Ùm=Y™©¡Ní¥3ùy&À,§^Ò6ià}~›HX¯cËFy%BQ݈•$™)_ÝÔìtZ¦T2Žº…Á±uÉâNé¹Cà :m!B 0ààÐíêmÍjŒDpeÐ@ÏA··•äŽÜ6Jàÿ Šu%ÀD6çj€pÀ·GÖ` ™/¸2Tóßf< º±åðFŽ ]<Ç:8¿¤J7$H©zØ/ ú%ØÎF«K½üÚt1 ¦cuVMÛû/ßRë¸Úb,j5<2%Ž–Ù<õBl<…}„@A;xÕXB‚šÞ\v+Í]çÕAGäÞK@:`OUhm*ç„ZþT[( iúʪýFWÙÎ%ÕŠÒ‡?kI*ACñݺð¡zfyÑ ?9Ù¬¼I‹YúŒ‹Œ©%©h q/XÝÍNr^ãå‰~ä¯Ö{í]3ØÊ@àhçd¿ ×/a-óϨ Zý-©ñC -ÒãnÙI×xÛDJ Û[NÕ¦ÊA)n&Êq áÂa¹G ÛEfLVY`%×â]X;·èi]y¦UÇÊÚ…2º'<„aš‚+ÅiWøCÆæ põÃ68S±hC'\¾ÓXÛ•]”‰«LòSyèˆ[¾Ñþð’mÓá]šM„·±ÚÚ]ôÓ–Îä»n݇Uµƒ¯êtFÿí,[9éþ'öí»Ï=où¯¾çy­ÿ÷‡–\‹}ƒ]´¾ÁçrÖ««Çó¾ë;yû[ùeÔ{ÃϼÿƒZþÉsžÓC°×1¸¾˜‡ký¨G-/ÿ¹öv ¯äø^ðü½W¿ºÁ²~ß7ï¶—?—ÆxñU,Ïù¾ç=w9‡ßxè™g,§ž|òò*pîÏ _ãéCŸ^H\ÙàÿQ¼éåËË_ñ;ËCôÀÞÈóIä¼A>*/ÿâ¿ÿ±å?¿å­ÑQï7¼ñMËGX²ä2¢o|úÓºè8õ”“—G>âáËëßð†ån\ðøÃTÞAð]ö_`¶Ó⇂-»„ÊA»¯ôü!ûƒwS¼›qöÙÃ(ÍÖ;a€ÿÁ‹¹3ñ̳–üÞçqÇâŠx¹ôçU¿ÿêPöB£ÁAî~bB_ËØx$Bõ?‚X7ƒün;76Œ/cCÁ(+¿X4DØ«E²Ýu~g±‡þ²}º9¦r%€[ 4­À÷ÝÑ×û$ŠÍ‹>rsÏ$›Ðvm@ÖMNÑåyÝx1g8ö¢Äö<¹¾ÂÀÏ(ºYo`g` ¿ ͶþÛX~‹?ñgE’„¬ø+@'6ÑIýtReQdéte[ëÕø¯±®„3¹¶ò ×… íéÁ¶#%‡:ÓM‘Z~QE]}´µÙ™ö$ ò8.Å#©…•‹l4gÌÔÊ ëkDŸ ‰[\Ф/¡­j1—›;–déLÿ„SH r,QVZ.À~„} fo§ï6£ïNc­”+Œµˆ,;õÊK¡†·Îw–<£måÑ:â#›…>°« SDÊ…‰Ös4‘o÷võ ™¯oÒpLwÖN@HCä24õo¾4¾t­£^c698„u@¸‡ø­­T„jÙˆ@ (7ŽÍ‹)ž! j‚ÆÒÖ /=²_úÕ•ÅJ¼€ïHAÛF—f'À-þæ?ߨ‹ÇÀ¦£2©¯#lh5ð°6Ù¥ _Ng9 öP®tzÖ§«ƒœÊ±!v36|ÎÇ2‹µ¡Äz…ån3Ø{"±„®cN¥±¿š‘òÉFs.m=.mŽa _ùéÕr€ÒC<¬Ï/ Yf± ¬^(:Ç”UýÊÒS/} Mì*Ÿü @´Güì)=,r\é³%ThmxAL;þÒT…Ö82N“A¾ù}øz ]ŒkÎðš?Z¾þÉg/OyËsxõ]¼úòuoüóåŒÓO_ÞôçÑ»ö?Ê«0¯æ` Kã®u÷]þÎ^¿â•¯\ž þ“Ÿôuý ÓåÌ‚»ÄåXÎ.yñõ™gžþ Þ!ôQ¯o™‘Ï8p~éË_ÎLøG¸¨¸W¯åDƒ6]¬|—]~ÅòGü'Ìê?jyÊÙg/Ÿç™…ßýýß_|0ùÁ àß²¾ŠôŒ‡‡pÄᕾ‡±”h.ü17ƒ|—$yÇáRÞPt8ÇÞ9qY’?>åì¿3ÿ¾õÍ\xxáôž÷ž×² ï´œvÚ©½Ãþ·ù*dô7|›Ž‚ÏRƒ¼ˆ5t6ÿº˜/íãfh`h‰…™JÀ³Ÿg™Ë,³x­ð€­‚9¼ëüNes„K˾ðã‹×™â<ÛɃ0pêe rŽ^Äë£ÿ­Ûµí;‹¬FOHκÆBæ$é×ë ÚËf,Ð|h f-’U1êX þNýŽ­|/º¹Ÿ0ÞúuûŸûIó—Ä¡èDŸ¿¨y ?4*}éÀ{{ðÜ~\;4þ¥ßnœ‰>Ž“|Æ ~ÙLd4bœr¦G•éGJ•5QÕÆö1yhÌäêÆÍÉ‘Db€.ž„Va96ãzA†„Š ¤È›stö5üŠ6ý7úr,™ƒµî÷I%Q1zZÙèÓÁ-Ìø œè•DÑB ž2 ^E×r./ j|„ãÎC…§sžºD“.¼4®†nˆƒeXGlP–f§àI8ð­ ”±ß uÄX~Oƒ7ÊU˜f¼¡—!ô2H4›|2Y1ž§Ž¤¬cì!Ï FáäWÝÊß²ô5ú8Xuz^pM„óáhè˜âø'+×-'õ–¥›>²CD‰c^ü+Pöoà,[åS>ÖOÇ$ÁNnIV‘çYvÔÒ¨\ü;Se;ŸpÝY?¸m®v)0¸WÒµ¶/³H ò"Ár|O…†kêfÐ. 2RÙŒçðsf_|xd—à tOktW0O•Ëml‡•4݈lŒE1£<ÆŸ¸]İWw;½ ®ö¹…“I’ƒUaeã?:ÆÜv’” sCÕø[ý& yÉIÞñ’II\é:Jœ8À¯Â¼æ2vÆ× ‘ÂHê´Áƒâ$$èi_qnaö/~ÚüyК»ÄÈdP{Bõj€Í¾qƒADsiÉÕØWÑu|sÊ8iÐë½ÒJcŒáä˜o¥%]O¨n²rà,… ì!/Ê´‹à’õB‹#ŽÏÖQ±Cè@HbÈŠ­EO9†·±6¼Õ¥;KÐÌÅ~Ú2‘d¨> ¼£$è+ [åÚµ3bÛxÖ$ˆ²äSeÆ“ž¯ÎÎuqÆïæÛ½y¤¤´5¯r'ºb3J¤Ü±ÙÀ\¬åÔ7$àz6a=5ãÈl°ÚO:ÅŪúvò¡àÈC¬öAeõá9îõÝü¿ò¢÷êÅ뮽¾u÷.›¹âã_>pñÅ=Dû—uŽ{@•ƒ^çùz.Œ1_«éà÷øÉÿy9éÄ–‡ñ{¾ÚóϘ=wþ»Îyw³ê­§‡ïk_÷ú–ù–›ËY¢ãúx—¿Å’"¾Å<\®s>¯î|ÒøËsÎ釹>Í……“5'rç @ÊÁü;‘Ñ×=:Û$¯íô¼\›÷¼óp_~“À|ßþ—ïB×{2ãÿÌr K„î] ¹tç—~å×zs Êâàß~_òòßînÄSŸ|ör,ký÷ÉIŸÆ_1ú:î$ø~{Ö?ï»ð‹o RO½ý!.rÞÇ›‡îÎr"cõ½ÀøÏoá"çÐ~UW8åöbm`Þpb¦4ª.+¹êÆ/çßÈÎJžÇ|º'~Š7éÚ °QõQƒl-cÈÔ€©A”ì±»±í0Θ‘ž2fEdV'ÉUÎNÝËâ?dËõ¡±ª¤ ´µ(Ûüa-q®Çr(Ës7ïJÈ:~ß5ïCº>T{5K•Ç[xÅ2ž·½ý•#u@-:G²LÈWºž_{mv‡ ß“e;Û@߇s=>—»ûË©|ŸDNïÎô÷Vèùœ„¯ÕÞnÂ)kù ?xáã…ËuüB­›§¼³åÖbÿ‹_Üh<Ê›‡)áÜ~±n…¯é»&&|Œ¤ü·ú}·ïꮯ;¥&ßå<ä›ÜHøà[>ÄîÆçø¿îô§;´2)³mG³¯mñå¤f¿®ŽÐ¦­é'/±õ±öaüB‡Rò΀Æ]}4'/C§ü­\ c$R‚ìÖKO¤6ºƒ/L4ã#a`õ”‰ñ$/¼žÍ’Ùú•‹6”®Ë´¼8ÜÎåXœè×Hñ¥Tu•Æè‚þ jŒ0ßAãEÑ•m ¡¯ÀÊ“Xo0“|ä¨^ÎhR;íJ‚k¼uð’?ÂÂÈqèç'…›ÍD­zF„"/Öä["P&°B)m&¤©2H¶†¯…­*) ½ô íRg*TTN}Wǽù(‚žýÑ×ÒAv åNe‘–0µé©·5ËGÚÔŒ®¢ÉŠ/ËÙl1…V‡8Ï%76²kÐÚ\‘ÕÝr㢈úóœ9®\>â[ç¿6—çÊQLô5Võ.Ê<È%ñ´e°ƒ/2€ÕµÄºÀzåìÒµ°ÒÒþ2‘OòÆYY,‡’{îptFÙV„h‰´Å‡<…eó•vÞ‡In €Éì3v•°V÷ç9 Çä^Î5¯0Á¼0Â_áW|ýMêÔ&¨Q¥ 7°9œÂlu Ør¸nZ[ü™Q’Šö:“—¯Ø/ÛvóØ «¶c¡Û&¼’ŒÌ[{ßãþ§?þ“å\–´œÂƒ­ÂŸÏ{ù/eÙŽkÞô§ë†§*À¨ËžƒãŸÏó«ºïÿÀE­—/~VXeq îàÛu÷¶»Ôà4øG/7ŸãðMBNVív/zéû@í˘¹ÿÀÅê7”WYŒ·ÑõÖtnä÷"ä¿cç¨Ý&Ž×ß%§x®ùÿÛ6I¹4l³üØá ~Ú Ÿíy2õnÓVÅ’u#Hƒ(ÔÏQoŒêïîÀ#£Pê06ç÷=%S7᫽ÝQ‘çn£»¾ïTÐý8Ò ïÏ_w},c}îíÔ2DšôL¯1³é¶úz#d5‡À„ F£Å㨠zå jœ`è±ñœØ*瀑\v.+Cå0¯Â`³‘ÙrcX õ¬©º¢¦›5ö7ì̓éɹr™Þꃂ`è̬;TAòNBäÝí¦¹ò–®4ÝCn[cA;X™`ÄG¶›Ð=CK3D~}Þxû2™úšÕ. 5Fn/l8jr›2¹MÛ¥úõ}±½”{ߘd@UŽ·t“%ƒüCPÒÄ=š"ƒ†SS ¬œi`ÙÄŒ²•W{–¬‘5 eñiÆEÆÐ2Vï)ϙДUƒØç6ì€OÄ?¾Â(WÌ•‰úü¿)£Îuu$žt,`qöyfà4<´uõÒG*¾9ÕAz\Z:ÄdmÝDÁì×ãèJ_YÙ t¥Ì ˆw¤JΫ·CA¸‘¦÷úÃBl®çaÜJQf¸CDYèø­Ã%ýb[‡Y“¼Ù‰ RóÛ±VJõz H‘P)3³ú¥ë&å°®-¼Iªø[ WäÜàWgäì*^ž2”ÕMªÐ­``Y}Y¨ÃkëŒBddæ,dÙ†ÆÖ޲¯¼Ôí%Ç,ƹ6ÑÖÍ2ËúlE2`• 5U4y¨©ÖÀk;8]3|FþÉ–ˆ‘¹§[Ú©*Ï”js>âÛN·¸é‹$†xæ_u/À§Ñu1fÐï±a,†Eû¶]úôÁ±çÏ‹—Ú”X€‰çgîÔ²³¸/ÇO&Å–%'|ü¥8)AXäÁ ö@Ð`M5&AÙ˜‡f³«df xÀÏF« Æ©Ó6þq,KÄJ>Ò±&жV(õ(Yt±°Æ’IS¾kòR«ñ•·•}[ƒXîbÀ¨—4PÄ¡Akr9×òƒDÛváQéZá I_ ·þÒô¬E¤M^÷ÝÝ"ºi/uïÖ#çæepÀœMÔWNÓë þ²%§ Êu¢´ZN¡ÔZËE„þKö¾¶ˆ’'xðñ.K‰kÍGòk™Õ’ž¹jì4²ö óÕôé¡\%:¡˜–ü\èk³ÖÉË­ïñj]èÈ óƒcȫܑ¯†3+-f³Úާ¥^Ê•–Ã_r^Ü w1ÉE‹0ŽÁõåÐp?ñì>›ÊÏMqÍôÛ@IDATÐ$š “G©EA”§d•AxމK¹TD ‚«lÆ”Q/qÔ]zò8ÉÁ»¸Ufkµ…õ‡| wÑĦ°-ÑTuUoÊFÆcã¹ þÒ‰°·ÞVn]ø÷œs®}?’e8n71 îrÕúû¶M iümÛþt¶6•~èèCÁ^ðy§ ü¡›ø¡#ߪãÒ!/ôÃ5×^×—eƒ¿!å›\ûƒ|1rîûwß?Ëú>–ÿrŽ1TÜëæCF0¶ëò½3-ÂyŽË9dcÙÓQ‡-žår÷{±sì=·Yëg³î@‹ñÿͶÑßö·—UÕH§MŸÛ‹þíMg·þ«ì«§â„oÌ—.ÇûÐEgÂñ€åÃlÿzÒv‹ÿ×I€íÙ/k¬Ë§ö«¦€¿î'?„Ì ®í7N"\^–ïD„ËᛣdÌÏwpßöc"u&ܰSïÀ͸lcÔü£ÀÎo·Ðr-[œhö¿ê‡Ü ûÊákðÓ·)³±ï¹.NtÊ8´?±¼I@í:x@ùA.S ÜÜVÞ]ù•S©´»¾Ú¤ÜO_èÄÈFð£Œ}ùC«)ã0Ù°‰äØ-/˜ò÷ß.VKb¤žiì¤í‹øFXä?„Ûw×_#o¸zyôc°œqÆ© @)ÉÉo¬Ã¯©Ù9í@)-wï¶f+Û]¾•ÝÎF+Bû}íÆ³jÿó <-W)v˲¯~;Ú·¿5\Î\+',7^û0n­çîòý7ÜMß—å8G}êSW.¼ïCË_¾óbu÷å¸ã£“ã–Nªù,ÀR`i4m(ÓΆ¦8›×ìômÌaIÖˆJÖ Bµ²Ø¹1Ã%Uƒõ66ËÅÓü6®`àÈ¿º$S*Î)´rENšòò¨†bõêZ„¶Ù{‰fƒèJÛ'u+m€ñäð–æ$ª8 îppµÀØ)½V¹I]ÞÊm€ÛJí nì ½]ú³ót$ÕC_8xQ®_L`I1Auµ^pàv1¾³¸IH¢“X ÎF•@ÌEÑØÔÁ­Ú»opߤ Ž65Ñ _ÄV¿ „äÀ…®víՂŲÊ/‘•§‡ k‚³¢jâ«m³©rZ‚0ÐG†=^DÀ»%m [‰2»cWgÞÅ7Ö S½8_¥š&É_냱xŠ¢Ì—|·;6ÙK¢–66Ví†.eÔÕ‘ÈÐBvYÕƒŽb¤U+¤Ì®/¡V^ìIÄHÿ1˜þ‰friGtR„·Ð¶$> åZ¤8cˆé(`Xü!ç->s„MõÚ$ßÈ:4ô¾b/û<õnð6 âpÂ.ù:ã¥^$wlç*Ô”ŒÉ*¸ðvÎÚ’–ñðÎNö®â*í—.$ö—óK%ZŒ`Çm@61NtÂÈvb´cnñ´#Å Àæ«»yÈrÞ9—/'vÝrܽ^>Ä •<õ¥Šy‡ákup…ÄühÚ&ÊíÆX=®¹ú:fþ?¹\wõÍüXž¿aþ\óJ·|½»ËYò —ZHÛ˜ ´M$}¼ËÏ[n¡Ìüå 0î8ÆR`nᡬ—Ï^åCM×,ß÷ü§.§?ø´ÔRˆÿ²mÕ*© |»ní¨çnŸýë§ö‹û¾=hl÷—Ïòþ¶ß`o{ÒÉ÷_zÖC–‡?ââåÕ¯zËrõg¿ÀÇðÀ—³°¸´ lté"-a0ëú¬Â±cÜ F`VSy5_DÐp'0A Ö 2Ù ”Î FQ>Û‘JækWÛ¦ÀÎ!̈mCuaÛrkàÚüçã ³t‘¯¢Î ƒ2‹áo§â•·•5Œö¦ÓSe¬(%êáqôU×¼GF€|M, ?`4˜2Qà8hÔé^›xkPšIˆ¥:(ŸÔø%IHœÍP¨©“«Wû꥙-—Ó JÕÝ …XVЀ˜IRÀ¨\FXÈÚìÊjv%“Y~Ñ·ë€RNÈ&O“§TÂW}¥¯)B¶-¡©¯:˜· í<Mô™é*•mñ(”›KW»h4;ÏñßœTEÆ^Àm¿H>2©”‚A’¡™Ü+ðº)×(`ÇPWvuNìouÄgÀÌà•Dñ¶þê¤ Ÿ‰ñ‰=%è™cu+?Z ÑääX÷Ô‘YÌ.ÏÖìºÅ9A®ž{ÁÏÆ¹²)G1J¦£â\ÿ’4…–Â]Ô’)Ú£í¹6Õ†Â×HÓoÙr¾sKãT_k\nçñÐgkbQ6i$õÑ Ø°1ºÛGÞ®[:¦ÃíH¢ú×I_éùi–G|ðA½¾óaüêï9ï~w¿ipÌ1¼Ç7ÿ\ÃC½Çßû¸Åׄ¾‡W~Þpà =»0ïOÚÛQÐÛ‘6´Ûõ›ñ„Ç¿¶µ‰UmS¼ €ë8V;óÓä.'«.:ïÊå²K?»{ÜÀC`h} ÍÇc¾ÛAC_NQåž×ÖjêCà ÐÚÃZ·áÕN櫚­z؉´2ØÅÇèƒUíáæ-óæç¿k¹ç½N_îwü=x~…Ü@ኲת֔ß¿t´–Ïn¦RØEL½åïÛ .ȦëV'È´B+9Ë C,v¢DÏê±éµ×ܰ|ê_àô=Ëa‡¼Üh¡Z=G¬ñÇŽOÀ7wÈ<Ÿ{ÈóNƒÅqÛ&¬üìxËTü€#ÿKWzå'ö{(s5¢X¦ï!?ç©Ñ'·–ÐØFùÝüc![îž#GP¼y­²¹¸3^)'Ùɯ>Oj뱩«ìÀ­ÇÄü‹ÚÑ $éËØÍ¡.b'åUVãmP9ìÏÇ~iA}^0Jа®rÉI|õ‚àäÓ‘“³ú'nã¼Þt½L@Ûœ ω›kƒÔÉf†ëÈ×óÃ)Ïÿ§/g>ôÁ%ï™ÍXºk÷ÿ«tÞÁ¼¥â¬‡ÁUùáË/üÜ«{øúð»ù“í4ƒmçµ·7,f`nq¢ÄÓ±7—š%ÔbÉ âß@pöü°ðM|VûÙÙD*Ê+ÚDè,YqÎWe4ˆi[üÚè@™Øl€¶H ŽŸæ×í,V\;PQ&õIR«8²!x^t8qð>„h*À»Ôc8×nn$› Éç^Õ¸Vq’B×ê3!D’và%d¥”2¾1Œ¤•v¾ƒžì£œ(ìEOIG»H›óʬÆ/)”OOE€©Þ½€U.äÓVpé"$ûB+û‰’Õ][‹Û0/úœ4«/=mPþÑ;KrŒulÀm‰-SO!2RϯÜtÎŽ-´“xê^Àpœ ˜ñ¨›zi(Aähä z³À á‰#}è'Ú‰›±åÇ¡]Ë0ØPÉæA#޳HÙX¹ª³ñÖƒÁÌÞ Facýâ{åÙ‘£*ÎÑCušÎ 𛽫›x°¾UôMw°¤ÅiUò²€Í±­¸¢Þ?qã%OÏáÑžã Ü>²/Ô½vnâi¿|´Q;´††î–æÌöAOpŠzã—áë¹|P zˆ>~Ë¿«ÒÑÇ«˜Ž@E!ôaeG+¾<6ím|\ÁëFóÈGð;gôcZ—ò®mò¡}˜ ²ƒùÑ­O,~ÄW,æ7.ýèG—w¾ë.>³<þ«ÛoøN—+ù& ‰ƒ;§þú̸±é¢]ÜŽve¼ª÷Ä©±Ì1ðzݶ¤{ öúZb,%¡ÿÚs o=úÂMËG/ù|“ FÇL6t”3ð‰-ŸOñBלëË›"h¢>…2®)àA¡^Xw0‡Î®wÀƒÔ¶A7Ï;L wᘈ^‡¡t±± æot;23P‚)—†I¤9l§h‰:÷Zcòe%?plÝtQ‡·§J7~å˜ÆlÒÂ~D{ÉÌ6>‰Á—gY7¾Ÿ™ëAϰ±=ŸID‰ˆhÏ»*0²šT”S]½C`©6.Õ”ô¥Ý5»4ð§2Ú»äîÞÖ]3©úÉøëÖ1•ÖùjÒYëoì@G;P§íêd ¿É*ç>ìêð’™"aò'6‡†w.L„ê{à-,=ÐnfN5çp¨Èøµ=t‡¸ük9Ð5vYLpÕ½|8È»_›†'ØÑ×g=p›!W¿N/•ßlŸÊÛòŽi6sÊ^>ŲpžóUtÙ&9¯R” º©§ìÆ eÉlúE°‹WQÕyî|éÓ‰ý)V´ÁH»Ö•NÖJ[¦Ê㧯-–©7¶(_"ƒýH6ÕÙ_.›6ÄžW±öùÿô»ùÕâÓ–«®ºj9íÔS²õõ×_Ç{þ/é5žßÏ/ëÞ—õºöºk—G<œ ~àYÿÍ/?ð½÷î—Œ¯ïü>€Ëƒ¤ygÝ”,ãOÛ–çë|mÌè¾U|}ê Eµc†c¿·öî±o4¦}=éÁ‡~´-_Šm™X^•3`ZÆ@9 Çg“§YÙPðíÙq(¶9HòÚ=܇2AGB6GPn““oÅÞª$à·޽Ûrþg߸¼àÿryòÙ_·üÔ[6˜»39wôQ“†®ZÚDi[ÒåXjhá-b/M±[j\-Pn\aÅR4ET&4¨m%™·äÐAxÛ¶ªl|„ŽB"»Í>Ö)‡Òï]aë´“çbÛÚ0¶Thû6©¶dSzœèêù’ÚôÑ⻉µoËg”ÉÃ~¤žQÁ(1à ÄJ¯€_ýe™69~¸îR¢âÅQŠ]i;ðÕ® ?:Æ)<}%¸yŠJâcr¥Øê;õj͹34YyG¦(ë—µ|ìa›˜²ä^ñ¬s\$wcb]ìÚ>´¡´”%8ÎoqìÀy1;N ¦»'ù­ì{¨«*qäRí{IS.“õhëquàpЏоþš½Ë‡±œrÊý‡äP2ú®íޱržÐ<ठ>ž¸–wd¾‡r“N^°6ðFJ}¦kkF|êL(vÑ¢OP&„~½ØÈ4 È×Ôùo¢©yÒ6ûí¬bq(÷c’…"§ ˆhQ·6ü¡GàÒ)Éß½i²¼¶Ó"L£Q¼4™r@›mÃbœ÷òÊO“VÃM†\¾TéŒm&ÐAh`(ßhÔ™°òAž}†ì¡¤ÑØ&Á¸ÂdOÁdž›»Ê’½¸ÒP~IùÍ–iä6r9@ %À–¾´Öæ²tóר -3Yæõâ%K!²|‰ˆ £zh#Š@¬j‹ <–‡ ñâ­,ò3qYb­rŽtÚe.TdÈ ¬`@ا ³è+’ ÏRZ6 ÅðŒ>¶R>u׿770¦nóA¶'¦ØÇY»#K§H”ÊÔ¨_¶DMêo1øÌ‰ºeÑäžS¾É*²À›eC‰ËWš(ÐÅg ~ƒ_Ñ@“³D 4ûEÉÚ­ô‘Sºüu»ÊbW¤®3¨ =¯]„ï QùècH{ñ#¥ Žºq(ÒÁËÊ–øAÃó±Å*?zŒ/Ø+¸ÑRà%õàIqëèY,¬Ÿë ;Qi·¤|Ylˆéo\òÑË—úÏæÆ¸üʯ½hùÓ?ëò„Ç>jù_ÿõO.}ðƒËË~óÅËË_ñ;]üÄ¿üÉåO^óûË ~üŸ/ÏãGÊþñã¹Í;÷?Ξ}þ–?`3_zgߌ›–m6(ŧúÙùO‡z ýH»0s¼ ãfV !ÿ›æþ™%€³©E«¢Í•OÁ«^byÝ nÍw¤­§Í˜; BfÿNðîúR4/¸©¶£|7R9yÁ87€'žœjòAñ…¶„lÀؾlÖÂ]…Ë?ö¹$xÎs¾uù«¿úëå×~ý¸+ô¤åòË?Ç'†FóõØÁ>^+M¥Št÷5²ê;ÊÕ}Õ6zY„M+Ý Ûä…bÉ,Û¸Ô8Î|ð0®½:ùDœiÓæÉY6Œ,Úgå¯,- Nr©·´{MnÚêô±ù§Dɉ/m˜ü_ótú‰®žû¶.Š8MxÒ7;¡ÆŸ}­}º¹bî`wÿÔCuÕžæ÷.Mtר£züfõJ;›ÂÌ?„ƒ‡¨£ŸEnYÝÄOê«·ö•§ åâö áѪŸö™äW®C£‘SZr•ˆq$Ž9:ìbpØSn¿E$ߦË8H`¤>úÀ¢s`Mç«ðøOœÔVÆÍŠˆLQ¦2lV “omè-mb…n Üðyæût€~îÚîx èßmíO½?ô÷ZÞsΕËýîÎ2 |e2ô Ökê–£pN ùO‡7@ôIýl¤†»k˜—°6.ƒÅ°š€)Œh €RaàíÚ*\Ëbq×À³!Y§õâÕ€@6LÐ’3t•aëÀ½œIB iÌkCQÆWVa¡ü—_L* Æl à¥@Ò‘gð<Ǥ|ôZûž"„î¶ê•Q}ÀÚ k/žcÿI†"…ýM—é‰íÁ*m`»3zKÒ¡ŸnR¤ÚQ³Ï,öQ>aÔ‰}ãUtl¨Þù™rÛ1ôR ;4åòb'*ñ@²úÈ`g¾¤b'€º™8Ô½·+ Ð øŒe¶Ð \íï±ré›Už$^Å‚ƒcG¹i§q;&!¢ (5³l9ôwÞd¤ÜÈhÈÏ”Öæ]ŒØ«h­ú ‚éÖXq¬~*#µCŠÅÆ”…êëCiŠb’Çà+Ž%o²ë eB6%ð>Äè èØ=D› êØ1õI‰@š¶ì’µ$>fê®`0¾ åŽ6»ì†‰Š•^%̉q71)?q)]å¦c'î* Fxuê.†…b§ÐO8)l‘›ËåŒA?-áPÁ;ý¦ìÃŽ¿×±Ë£XúóÚ?ùÓå•ü†å©OxìòÞ .Z.»ì²åÒK/]wöÓ—GRÿî÷¼gùæg<}ùŽoû–ånüâ®Û ÷9~9âð×ñËÆ>¬}¶—/Ü™M œºÉt#Äòñ8Ü8q™ÈÄÇô&‚¾7=ÙæE–ÅÆEñÄQchÒ8¤CƒPÛ†»‰©¢RÁ˜_<>dÍõåxŽËUœow!ýY^Ô=ÑðœG[âÜu¹³‡-…¡ '½´Œqâv.¢UGɽ ÓrÜqü‚ôeoZ~þç™·<¾|û³ÿ5^®½†ßÀ&Û]8ÐÑG\sSRSç™2sž­@My*‰zaÍI ÙX8Ô0ó8ðÓÚµB©Á8óÊup`bºqó™- û†Ê´:[Ü䌶S¶äÑœEݶé·P¯=Ë&Å-#AŽa üÖ­÷ÑÙÆ¶Íê€ ç-7Šl\ˆºÚAÝÜŒ3õ¼®ÅD äGó”6UWá©ÏÈ`nÜ@}¿;oÑ4ö6fÑW “ÙŒ‘mu‚|¶ uSÌð(ôÍÊGq@{µ3'º¢É±¬-`À+›wÚí'=v´“½ô›R§¼"ØßZd>ÍgÄ•}œò¬ ‹Œá'"›¶‘¿47¹•M?§ÊMû8p¹æ†›—St–-˜¬e²j¡»¾î@ ऽ,añsÇ ‚|luªMƒ?\µ]ßšîÅàÖÛÏ&Ï0 „ŒÂàplPÛ¼¬j ïmU# 4aûž=Äø›¦Z…4lƒü™\Z^n¼k]6õvR¨q˳ÁP4T %Õ!º.Ôûk²@A^ÑQndkG=i˜(æIÏÑ.³5Р<Ú  (Cåæá 6P&“îXO@Ò-ce7;”ùXÝ`ZY¤¥Ú6{íWÍž+ÉuÂAI1_ÁX±U¬2f¿ÕàF;8dD/gYÌaýȉ,™’ÇàhþfVù© Æ] ëiI&^ØBXÊc©rHRR±t“«äC °9˜[\“O}:Xn©eaäÎXÀ$/çòmV>>ÐWl0šý0qqâ¹lžˆ¥ï”´UËaØ»HÌMðÚ GÚ«„*.J©—ƒy¯ÅãÚVªãX-ªƒ©‰Ó-q.oKÄëzƒ RòupÃI6äKJ Œ+þ,ÙüQGâ­)ê6^PYåšÙ’2&níu¥¯–ݧZ>ô+£“N¦särí°›1£´ ßÈ8²å?„ìGó0EOmCÊ?Í6ES|øù5V@|h±^Õ¤ƒôv÷¶zúìñ`^†ñ©+¯ZžòÄÇóðîçùuáó–'}Õ£úa°ûŸp|¾—_ç}Ö7z¢#3û'žpB:Úoþù_üwÃÆ-¸èâåÈ#ø%^Êó­~ZpgÕßvf\/ ¦õ*íeî N[¸úEšÌP1•ÚZ…åF¡p'Æ~¨õbØ6gô c?e»-Ï;¶ã8šÜi2Œ]ZºåæHvÄœôøŽŸGT”ÛsδÎŬ¹¾–ÇðAëøI!^tPG}ørÞ{/_N9õk—¯ÿú'-¯yÍkÁ|÷òPfÿ¯`öÿ Ç`rK^íc¼7àƒˆm ÊT ^Èø×ÝÚ.jFCa²’"7•¸ž?zT6€V0i!²¶²Q—×Ì-âYÇ–sC <ŒÇ¹Ó¢îø˜ƒ¸…ÔŒ:ô4·<¥—® p¤¥Ïµƒ†w ·Ad×֠ΣÜKaüÙ a@|‹åW°Ó¦W6Šõ2˜”Õ<áÅ>oàÂqýI ±n²p»3í•×í³W_ÃÀï(&^öòccñFŸ{-ï½è’åG¾ÿ¹½öó5ú†å_¼à‡{.à;žýìåÿêå¢w¿mùéþìòáK>²œrÊɽô£—]ÎóuÜ­¥½íoƒ;“Þ꬜#«$1îômM‘é¥_“{âU¹ã$ö•ÚÈåùŠ#û`”A“ /qͰž ”êÀ`I&JŒ}iä_€œˆÕï~¼+øøÍ=õæçê¬@§øx¨Täy‹å¯Ón”etN6!9¯c)kü‚þ%-öô.‘$nÃNÂõOª£( "¹;Èíø®ýk‹n á¨mPÈÍKBeBWÖŒ&ü9D °M#  œ‚˜Fgc2J ]^Rðpz0Ǧº½æÏ˜#E›Í˜ ¢Óƒôj&j‰ÊÆ[)´3i–DLÊL"ÛŒ4%ɤ?2—h€3œ%ì¹o|˜ÙRÜàIþè©}jü‚óWRƒ®¥;ëG9[£^ ÈB]»A[|²1àPišjèZ\kt¯ÜÚNÆJW;®Uu3q™pìØ4Š2µõÊñùÀ'¤+8Ê©‘ð¹Ý¯*Í,*vÈ–CùPê¥gþ‰ÎC¿zÜGîZÖS¿­CêøÉ²‰"÷$?\:å˜ÂzmÎTæ<¿Q>3<Òæ#½ÀLhê‡d¸øR6œ<§˜:?]B»‹0ÀDé_V[ñ„ߥT˜#ωòª£<-+æ£Ï¹ø5}¦ÞÒñ‘F?YÑÓ=•ñç[9óY² —Ìå˜#çØÀ:1Õ††—€¡ŸŸÎÎs œ °3P–lÆaõͶ)£1ÊGš¾f±=@鉤ê®<RÇäR?rFžGîœb“Ûà bгa6ßðʘ(ì;йp³…®„¥Ÿ \Ü­vUGñÙ9`tTâñ—ÁÇ»çÝï¶|”¥>'0³ÿƒß÷Üå¨{¹|ﳟ¹<ãžÆdÙuË_½å½ñç>Çßgyá¿û¹å‘¼5ïWý7–ozÆ7ôüÀO=u¹æšk– ?|iK7}Žk.†îä6ÐWÄ…}ޱåk< ¢Çqwñ‹_ÕÅXt3vMI}pÆç{VXg@ˆclrè©  ôŠNèy.Cê«8*Þä)Š36«µçúkF\Ra{ˆÅÂYoXÚŽlÓÊßì,5“?w'ŒºS~ oí¹ï½ï¾œûž7,ÿä»p9ë¬3——½ô•Ô,Ë1ÇÜmù‚oâ+‡H}ÅÒ0îí2ìmmÄ »¶Žf"› «mÈÓ2W'¯2#Å^^ŒmÁ•}9Žc§PmŸpÑ'ÑàXE²!ŧ B_›êËì!-êköÀ°è]kè«—äË'©’Ÿ¡â Õ“Êòý7s*4ã¹ö9èœ_Ç;K1’2!ˆ“‡Ê1íÃúP º TdÖþÁRn¿àëDÝŒ©õ0½,³^û[Pî£lË—Þ5ÕúbgLh1·äC}û¾?ÅÔ.œ­ñem‡Yô%Êω„H–dl,5“1F„6ƒŒ„kŒÎÐÊxd_?¶2éq´ñÊvK‚ý¹ÙwC.èÄ•ÍÎ̺Ç^´8ÔWöˆH>úÌ„EU8]Œ ×Q0éÆ ¥• øî’H\ᤧ–, §Ú ò& }´²…ž “2Ñý“?°¹(Z#þÏ [ÙÀ›ð|(P?ÖqcšÙ”´=QúÙKzÖ‘§ÌO÷Xçý‰´pÕV9‚áÜ.‘4@W™5c± Aå…æU¨kâT ‚ɺcåÒ¯Ðö={ÚWðøKG}°‡µEíÃqúȹ}ßEœ±Sj*oìÐÒ"ÄÒˆrµ5o3{];œáÕ|ìão7Ã+:²zaKAy‡òÓ2kYxñ¡Ü¾:ÊÚ—c¹+§KäüSÉüíRO¡6o[Jc›Hꂇs(ñq¿mw¶ó…[¼q¹×1G/oyû»z«Ïžð5Ë™gž±|úÊ+yøó~$ó³Ë“Ÿþ–?ü“×/§žròòO{êò¸¯z,R{–ß}Õï/¯ü£7.ØÃ–÷¿ÿÂ娣î™ï½ãVLmjïìï\úO¢m§n¶7]ç‘ýŠ>¬½:¡k˜çsÞ ÖcÌ<È¾ÄØl³|<êj3nñX€£¤•)è+„mo‡®ù™œíŽªä8y hÌ2ªl›!å\F¶ óº"éH”ô±Ü×~^Í;òݾÿùÏ]>ȃ߿ð ?½œ~úy»Ó ÌÌO¾Ô8˜‹ìéyÙç«Üæ;ÙA:Ý·Q®Ì~)bÈR½rXŽ|Óï‰/ßé"4ç5vÊ–Ÿv@_ÍX` n&œå}•cÆ*?uÉ" ¶ÀD Êú<¸ðæpó•(òí·/ëGýiþæL·)@^ØÄ®Ø×XãŸñ¦•ß”­’Ÿ2Ë•”§*ù.œìÑÞ.O—!ÝÔqnÿ!ãV&ÇöÝLñ£ÅÁfCêëëAnh/pR¬¡P§|]È4à¶ÇÚAþ¡²—}‡Xáqœ”ÀÖO"L°ØT\ó±Â8û /)Nª’.UÀ1ìá0kà/i½#QjîÚî` 芉(œ«Gˆ@Î'iN(õ78¿æÁzg½»5Ý,Q¥¹zœÈ{ ²6ކží': X¾Ée 4Ha³bÛ-Må(Ê ÑßÚúøDHZó±Ñ+¹¾†Ïd£¼KmO‚6Fëd8éÊZÆ¡®Q]Ò“²i\ò°œso9fKlä~—£²¡“NvX]]S£lÎ48‰?4BSþ ØM˱LûÙQ ? 2ÁíÉ€Q†cG{xîŸÿ°Vùô·&ºê{/njàœ;(T™Û,½¾Ž :úR›)ƒ¾´ßð}ÀD}µ¦ó‡I:ÆÊHÅ7Fñ‚«TM¢š€µÐÞO¸–(´htËQùáÛ;ºÙ}‘E»¦Á–†(™ÔÍŒ‚)G·ƒã"ȯÞà*Sr"/N’¥œò€­&Ay¾ô;n–i E7Ñ[l|\Ô°ˆ¿‹  ´×ü N4I"|÷XTÛ ò·-cB¤ly¸PÎ>Ú T‚SæèZž$ù$‘cž'Pw…ú|†çž¹AYxöBxQêCmÚGVë±èJGHø V§øØqͶ—ÈõèÆ¼HYñzF³UASÙ•85šXáœÀÒŽž+·Ær Ùá§mÛ¯§ z«íŽ>GTä>†ÁûÏüŸ¿¼œyúi˱ǵ\ðþ‹ø±¯Ï,Dz4è(êœ,û_þ÷Ÿ_¾â¡§{Ôrîù,W}îšåký°å¥¯x•ÆïGÃ|•sÛŽþ·R–“;Zß]ü9l°¥ß8n¡„øÒfXéZuóyÇ& 1·¬ZÉ1ð7ñg_Ðã¸Hæ­‰ #Çþ¢=ômeÓ´ÊĽ5Á’üÃìl涉/©Ì𠧤R"&×|È´iœÙFˆÕø%Òô“§¥~ ?ºyØrÞyoXþõ¿úéå¾÷=~ùg?øãÀûœäýfÒÁëÀµ~OäøK~µ—²{•¤Ú„¤«QƒÏÚ‰ç¶ä¡N]&-¡ESìE5ÐíÜh-Ï™ÍEú„=$e L]Ø`Ú©ðÃC¶ùÒI˜: ëlçZM†±»tbo@h?ë|±B0²å£zE˜)õ»qÊ”r¦æê wÐ8³,Fƒ¦jö­ö•å1ŽÇÆŠáEŠbÛbK¡g¼)[Q ÌTa é®j5QÎ)À¥ÙÞk®tÊx€ËÃVÙB¶Sé‹(š¸ÅÒóúéKéKFSüîý'mA^EZ…)>ÙZ3þ¦`Ék éê3éºD¼'²J*»}‡£?c6~ÏþÆ‹ ©JèÂLÒ:Ví5D:ݵ¿ƒìÛ­ ìÄ/Ù–ØpPNÖQ8°eøÏ™ô @‚Å>xV 9^ƒ(§{ì¿4ØZÂQà{b,LR0åNÀê´{Ó½ñbïFež¤³2"H=ö‚³`uð ;ép$Ýi”ûdsvÝ™]g aåB$‚`ñh8¿[w²<˜lÛÀÐFRV½œV†„°ló@Òð¯Ñ i[þÙÊཪ‘$к‰èÍÌÌø§Jà&Ž ¿Ì¢˜ "/Uù­æ9•ñe Ô$?ØH[¯mÒPÏÉ8ᤊ²§Zä„óaDZ³Í¦ž)«ã¤Gjð)ãè›Ü3ù˜,:«&¹|«Ì€{¦4ãK¦È³ò<Èa";ÞpÊ¢ú“”Ò2ñ³K<ÒÆ«ÃÌC‘Ž ½©@Ј¢`ŒŠå±Ç<‰ [bïDc7š+ Ò‹@èfh3ÃôÞçL¾ßßÚûÌ!o|Þ?Þäý¸Ï¹ï{ïµ®¾®u­²×^Úҩˤ ¶ÂH˜Ks=­Òpƒzîi-oùª4õ²óRKôÿ‡fÕ÷Sæ³èÃtþ÷9¼L¿gÖóû,–þžTÛØ5v‘&²hÿtáÖI£nÚN¥¦JWûÈ;8À"—|ê7í Ì2`ò,Gih GýþÓïÿ—vÐiÊKC -¢ üxf2GL^ÙÔ4e¤_Á£GQz‰-ádBƒhiÔ£’βçO½ó ;³U¾ªÌüK¢:64ŒIê­Õ;¤ž×¾I8é{jï¤7nŒR(ŸÐ«ô ¿Ö‹´ë€X’J…Ç*)r-.Pµ7?²DÚÔvL,àÔ2ú³wt¼kyʧ¶¯.»…?ŸÊ`iºOVþegD9šòN¿"m„Úyßõ86Ò×°šûOÇ Xºµ,ìÜæØDnG‡Iˆ#4ç© œÖÆ».wÑ÷)];Ñ\Çj'ÖQHØ‘5cÕÐqÚ#@N•ªŠdš×Þ –­ô Ì &ÔÀºv±ÒCšVÓA¯uȬð¯NÊ…5'ºé¸Õ+•/kÈ«0̯=¨T?ë@‚½ÞœÙ h™–£d•/´ùæ:úñ+ï$XYá¨ë UGZÊQeH#'­¤©úp-LÛˆÍ9ŒÅñÞoÈ“¦ù•?·8Éë‘zÇu ¦Œ¤Õ.ƒV> @.’TVÿÒù–f’„t;16Æ‘‰tóÖªƒmb3þy.­Z.$ œ¤¥ËðHâÜ€`3ô#§><åK^™÷”–F…Jò¼Tžœ˜¥,$f¦þÎVaò¤{’²R.e1]~\Z~J?Ž]åì!Ï Ëi¦?H‘&DÊ 8gÇBZ¯׋eä]û|ÒLé‘·›gÍs* Œj˜‡Th)•±Ï"4Ææ$†áÜËúSˆ;Òp¢²tù*‚ÖA6vÉŒ“Û#¥ò3GYÒáF>“Òg€V4HZz^BežbPQ ²Ü•3mrÈë¯æM)â{ÞÉ’kâ'¶Ñ5ç*XqZýÇRk}TV©¤Åæ&۱ˉßÚVÎ8dl—Ë*»Xú+™U¶†Ÿéú·ô¥#¾ôp+•(ÎæKJÒÐI) .„Û&t¦’)Äu†ÀÔ ©üÿóh;²ØsØ;ûðÇaý1ž6~c¡·œu` Aä,u‹ÑkNÈáÏЃs¥x-Sän*\ Šœð `´KO§9œÉ“þ§Iªü=¦Oh…ö©·„íTJ¸©5T`ÏÁˆ{éœê! \ÒO%@ÿ4MM¢4ìfP!(C–q%<„÷Ü_ùµ¤"g«m¬%±£z™Ì‘E8ÓùMÿØI‰¯ïH3,›¦Bdt5‘ç±³²šŸ©UÓñ`"0wrÍ3¨UeC1,dÒ‚I‚È_m•«|©Q:ÖÎÌð0ß™ÙÞtNSˆ€EB  m¨âäàDÏ1­íÖýãT†Oþ‘! e#VÛ˜Ùà™äq@ãŠVFÞrmÝ:ÓAA49—Ží¤@¤“%UGž²8 Ì0øñQ?T ¾šzª‚Àw?ƒ \~äP.c]çÖœê¸æÑf î$8f‘¶uö[ _>T=qÌç/wFr¡¤É Nø #y‘&žGv ¥íLg: éOÛm”Øt옇úÐMõɨvŒÞê$.6Ë(JKWú‰lÞïÍ.BJÞRá<öÓÞÊì=3}QYIÑ߸¶S&˜È±Û º²lÉ´Þ¼™|ëÖí¥cãÖ2gÎmäv+ãÇYV,ÝPFŽRz÷éƒ y·@Lr´çÿ#«òi"åöó\òšC^`*¼8Ïÿ|tÚôŠýßÒiŸ‹^›VÝömw:V®ØPzõêMíÇ&æ`4å¨OKôWý±Í²Jz!¤§‰Å&dñ[k_ˆƧ¡%L6­N$®õ?MJ}³z^ë°‚&¦pbP®Hïeõév N_Ä–¤¾óÌ3(}ú8"žWÞÿ¾*‹/)úÐûËÔ©Góð÷¦ÒË;Äñ‚Xg•1õXZÒTw2¢§1DÚpÒ>ò§Æ%T6dŒ à[å ©ª«8~Ð+m„¤­žÑL®m£  )¹óç516X6»q,KR¤!ˆAÂ%©&Ò.ˆl`ÕÑÃ,c¶òÄ0¦™Ø\ÔdJ4m¶F°ý0Ûœ›¨£½8¯ý³†>°U6®#"0ÄÂôÅÈ‹/Ä&#¿‡ºsèêÑ8Ïs\øgCiõ7ËNÑIJ9ø«žiç%$í-½œUŠßšDzë ”@@žMÁßÉ\þâÄGá“r¬riG·­µ|2Gƒè³]­ÔB“D›F9¤¬åYý#ö¨ Áu@g{«¹£ Êõ?>\ÏÎN06RVö: ÷¿r4¶Q™çˆa8k.ÉÚ}4ðIà¼6 €Šû,¸çÌkð;å”PW¼–“pϦáõÆÍ›ÍÉm2ºùz–\á…|ëÙº_¿¾é0´xϦßI¦•>q gÑ|N™;‘»œ<Ž”º2¿Ë)9Ê+/—‰\KŒ²õƒ¬)tAaTוã  ŠøVgS)=ƒùÆ(pí ú©ÀY_kKNòÓœÙláTgúvûPf5¥bm³Vñï‘ Ç¹ƒENç(9Ê-0·×áe',kçHj\ÊkëÕEçð&0,Ú ŸsáÓúh ¾2xR?þ£¦„¬*?¶ЊHå«H\«~tUs`,í!,5*"om ´*YVÎÀ4ðÁtFÅÀ O\ŸžŽ,×Á‘¥*Ü…±‚gÖÖ†ž$P©ÓIÓ.m™`çlJÖC­>˜©Œm ßµæ2²3KMàP(! Ÿ4Þ²äÒ Ñžcð‡€ö¸Á%lUÛ… 2“ÃGº9ÿ„ÕY4®ÍMÑ7T,-åÚŽ€ÏtIBt&Õ1T®³P|¹Ú9å¤ìÒoüôÈaX=ŒšßÒ«r˜gÀÔqc#’“¥­ÈhP££ç–¿*ä%\êܺ¼‰dv"úžƒÓÕ í£½\·KÉÏÇ |"ËåRb)G9ÒþÚÍ÷‰™oRΤ ¿8 í¬šqÌ­-Å4dæ‘ÞÙqËšBfîàÝw@OfI+Î6¶¶ôÙ—ÕË·•-;îi|ÙkúÔò–¿¾”å0;Ë¥—þ »àô.óç.+¦ìÁ “zu©ç iþ‹¿-,àω÷|ù¦wÍkñÛ´ö·MoMáøÕ2Ï>Z¼ö·kþ³ÓÚëgÓiÓŸë×´ÖF]Ïåó\tZæ·ç-\{ÝUŸö¼…¯õÆAÚ¢§——•K;ÊÀýʶDÐÿS¸F§hú©¾œIa¨ÀYó̹qÊÚ•ÚÂuüßL$a M}9™ ëFfD¤ÿ%ˆ@IDAT% #ý°»w»è'ôÑt ŒYQ«Âú¤`ÆÆFo/ñzx#+ç ÂŠˆk\”d¥ÊZOÒ®cvlíVÆŒ\î»ïwåío{Ùk¯©å#þ¡é'ô*«V³$Ê6S0B¶]„~Øç-/þ3kŽ\hüW¾lÖ€ìycº×»-ƒŒ^ƒŠ`éƒWÁs)_ÝAJ»¡õ»ñ½¼‹+ÓÚQgyiŸCFxuhÎÖ&†4>¨)ITi‡äL(ÐÆJ_=œCñÜ6:M[k?aÉa+™Js“cÙxaX09,¥¦#JóA^ÿò,šñ)¹¶–¢6f·ÜHŽ?é7èGð°ÍÒoôµ´mö3Ô!ràÈÚúKB×4u ~5`#Am ƒJC>A¬¶‰ni£MÕŠè…À¶ïµ]±èàÃÏeªº’ö—oÛOJlï íS~V-ùdÅ3iyh›$ûB­ÌzJ½‹£nÐÀ&ic «LúLÚ|S¡ÕìTU”¡ž óÿéPÕÌžkðp­ZÊ»ûÚÙRyƒÿ›çáÔ;0†Fp]ªMu:û\{8Ï Fòëɹ¿¾°¬'·ã”¹“~ #A•‹ÒOžŽ´ä»mû¶2yâÄ@Î_°0|´Ð5Ш‡xv$=ߺm+£ÿ^eÿYû–ÅK–°=3$\Û ìJ¿>ô…‘j…kes›¸?Ô'&iÙ?篺Æv‰3 [g¦Ü›%&Ú›LuôW-(¬ûªuI'Í¿tŽ©½5 NšeRåð‡Š• «D0 Y‚×'ÞJL” zÝH\ƒ•2·2%št<Ü,GÞAˆzFà­À dâò¯ãúfQñ¢k(z›¯:åµ–Y[ó¨ˆÊ‘JȯgÒExÈË„då Ë\¹T®ºdH²ºÔÚ£,¤å¨rWu*žz&à Gð”3u b¨³³Tê’™ èkrÍXY¨gsÍ(!òjéÙ¨æy~ùvÆ\ûº±+_©ËP ɦ,K&r¨ƒe¤ »/·[¾ÒÎ`"§Èà5¶±q³6&ð€«=3U¿!èVÞ*Wã‚ô’¸{ŒgH9 UÓ&~/ à ë¡Òç ñaIy$á:äUõWËÜ€©hñ‰Z´Ê!Þ„‹L‚“‡¥Ajõ¨zË_ƒ¦ 3€±aŒWmž„†‡8©s\[™©RFsõOº6ãÜ€®œÈâóµE:Cꃄ打g8·Œ­ßZÔ8mºiYHMGw5|¨‡®É  4“Z;Fà§jx+sŒ$=˜åï×·7Ë`¶§¬|={â÷`·—½<ÈgË$¦–‹/~73ÿOñ ä-åŒ3N-÷ßÿyKËá3ÊÊe›‰ŸKÊØ=‡òR¥¾F™?ÿ­,`¼¥c[Yµb}Y¾¸ÿ`6oDîÍóë×ò\ƒ1?JÙác5ëÃø‹ñ?Ë8,Z+°þn d|Ñ_k&¾©/æºñÛ††£r'/½4„¨¾AW¤È`~Ÿ¬Æ; ¯ßêZ•oíÏØ^)Žtpo>À‘ùÅ÷ODþ ìY–±ÄÇã¼W[xðáò½ï•ýÿOÄß;RW@);øÊxßJ bìÂo&Ê eÇXAw€­vƒ¬±™ÔRdI¬j¨x® æœs;¶êåÑw¹ë]ÂÚÑUõ“zbñ‰ùvôŒ•ä«ºÚø»t<¼"Xµ“ñÁ#í¾ºðI§3íiÅÍ@LÈ%Mã‰45c HÙ<í<´±rÕôèg°âË|c_õ‰ªƒC™Ó O™iS?2¯b~å* ?é{Dìk2_îZ–(z.cŠ)±…‡žrŠ“>0IÒËd>çhîœù2ÐЀâÃKÙEÉãLÆpßàÂÀ|yÚ¦e°(–tmôúyõ,‡Eâ É²J<4ð’éˆÎÃáè²–0ÕøT|AËIµU-õ)éµIk{:8@(ñ«sYéA¤Aºò° 67'®¶ÛSâ7["“|L:¡¤:¥òZ)›ÚÁ¹×Ê/Ùtœð Õ‰Ýplõ³Œâã2çËȶs×Dþ|¤ªì¸TéÝ×e=KGÇzÜ\æÏ¢ ê¿gYÏC¡#Y½¥>çž{þ/–ë¯ÿ}¹í?î)'Ž/óæ-,·Ýú`yåyo+óæ..ÆO–‚ÄÅ «¶—Ù«–•᣸{Šý,'m‘鸨%ÛyEBtõ7GŒO«×Шö¶|wƒÄ×P\Ý¥ºûhàcs:±8Ço!¦™sè{Jµ<¤”2¨¹õ[úä§:@ÒÅ“vÐÄãÊsË –º`µ;a]*dͯç vHÊL½"™@‘)~îE`<ñhèE>B.ÞЩõ`+e½vÍ6`»—¾túu×Ç¿‘ï™eÿýÇñï˜7u?D(‡Ô›ªŸõÚÃø˜3®kœP^R"³íQµAfÒu6êVî†!ä  < tj¤ï¤‰ŽÚÿªºË#‚ïó.a!gl,Kõ–Vd% uÊàB8Å'­…0"ôЧ<ùä5åsŸûj2dHù‹¿x7ÓãìôL=t.÷ª“±G‰ì :OŒBÞºõ³ô9”Eæ¹¾vüc?ËC•¥ùèg–ƒÉ†N\Ë0´Ýu$X>ÀUjyê‰Ägàæ.Œ2‹Þü¥ìI ékÿ"|ј¿‚¶qÑB“¿ÐÂx´í‹"äŒUå`‹Jÿ ?í* ªÇDj""_5F ç pð Œ:C¿–¿ñ öçôãFVùeà ¸<ò'q€_`ýFÚúcú/ÀzäN?ˆjš‰ð¼+"zøÉ“snâóÕP/µ­”ÕWÙe‘¨'MWD¹ŽúEÿª§xU ò4h1,Ìþ³Ã—ÿ1£G—óÏ{%ñ!l‰ö/Ìx2û$ß|Ë­å€ýö‹£<úØã¥73àƒé ï?kVyø‘GÊê5kÊqÇ]^pÀ¬ëQzø‘rý7¥cïƒU§žtBÙgï™ÑKø›~KΧN™\Ž}ÑÑeÀ€þeÅŠåw×\Ëú¼utÒû¥Ómg{3åyé™§óÚî=Òy¿å¶ÛÊÝ÷ÜG‡ÿ¬ 1è9/=Yf—ÞìvàáÝ-÷çvN`¶lÙZîºûžrÓ-·”—žq:»=Œ(/>îXîl ì翪Œ52þ[n…þ½÷gÏà÷ß/²ì¿ß,ÈÛËmwÜYÎ~éKÊÌÓ£Ã#èsýM¿g`ÔÏrÒŸÿˆãղРzôæ–}? éæÍÈ‹#õÔ«lݲƒ·n/õKÇm3 u¿~uçæf8/Ó›·£o7,=ÒÈ[azõí\;`ƒXÏëëÈ·nÝAP¬mܸ­ôgmd߬lDÕ?"Ö®Ü"ݸi+~ƒ,¼@%;fÐfôØ oÚÉ` YèXD71ÓÔ çS†-4úi³­È¾þýúõfàÉ9ôú¡¿Ê¸#GøSñ-Ko÷a`jºK\äoyù[^]¿“%[°G¿ýâç)ÿ¾”3upÃì¯ü”G‡òóg9mÁ_¶sr€Ë< [°MÊmÄfv µß¶­†Óåñ'VRG†²Gz?tÚŠ½¹eOLè Àìø‡Á&f¯Ú¸KÁÙy»Û9£¥(ðEäT‡´”ŸAOw“s€Là°>HÇ<³äÓœÆ.§1M°ôÜ\Ä2ˆ×η>„z!rnÐleB/I߆ÊRùåÈ€ žV9j€÷Ç€3–;«ÓÊr–Lš<–;´Êª =¨ßÚygY·²ÞIHû„4;‚mÌi±¸&Øü΃‹:s+5ü’ê×>ó¢SœáÅöÖÒÚ¿)6@°‰p΂pΘ²±ô0¦E(°/‹²È=ü‰Â,ƒQÇìªaùå®› ȧŠ‘må“K#N:0éœY@ð«³Ù– ú´s'0ˆÂØé¢œ ê\YwôÉÈåÊŒ"¹q6ó@wi¡:—Û)[ôU&øä®¬Ž‰!C›ôîăÞÄÇaCú³÷ýõåïø@9ã̱Œë åÚkZ>èT–Àl">TŸ2ÎûWÕÑR÷§«o*±yÔ²30óD¦~â§nOœnP-ŸJ$xR4ž„vРƵ$bCaÑUÖ>XZ3ÔÉO•ÉoH‹Mìç$Ï”\"K·´m>°’Aë±å¤“Ž/×\{w´®+‡rjY´h]ÚÙz§!@.ô)y¦Jâã•#œRTÖ7âX8‡UxYa‰à±_SN’Ê>Ï„€ÌÐB.5n©U5#¿”§}6ÍàD޾Pm@šöàÏ8b»&/ã‚õ3lQ NÐä [^ð°ÞA°ÆkòðS—ãæ¹©Š(›ð’qâ,‚¶6WZeÒ_õU3½6ÞÖgèrÑà€ Ï•òÔ%Õ3ô9±þ+$4 ¥À·ú Ï?&hgümF´iôpA~l,!1EA6Å3ÅuvùŽõÙÁGÞBì°Ì~{ø,ƒ+}›H·ÚȺZc‰t=‡õÛŠ×Èg¹ØÜos,:+´ÐUˆÄÓA­*i_rÁMÝo4C©m'üM€U5®“Zab'd­1EÐohbcr%žgÌPB9>Ï¡í` `fÿ¼?yYϬüïé$3¦¼’kß–øÁO|¦¼áuâhÛËu7ÞÌ>É£Ê^SG–“O<¾Ü@Gÿ”“O,‡|oW¼›ÎôŽrÔ ÌrœÏ|ékå½õMÅÎóM7ÿ>½£Žzaònäúœ³^J#õd¹óÎ;Ë <²¼êÏ_Q¾òõ˲圳ãÎÆ»œèœ³^†Œ›Ë7Ý ß©åäN(Ë–-/ .¢ã´ ¹I½dYôÎ(]×0¸ð5ç—Q#G"ãe„ñå4Þô¸uëÖòôÓOçŽÀ2fò`¼šAÏÖ­[Êè²×^ÓÊ)'Èëá–uk×—SO>¹¬[¿®<øàCåÁ‡./;óŒrÐ ¤!½¹êƒ®v`úó_2€Ú#ƒ…ç1uõ ½“cÛ³í¤“¶~Ý6tY[ÆŽœ€>ïÑåeøÈ”G2gö ÑÞeܸþå±ÇlÌ{”©“–'žÜ@¡o/“& )kWo-+×lâU÷ƒRéžš¿¾ ãõæƒèÎyl%½>e¼øsÖ¿“†}@™ÿ4Ï?П®G¼Ùô‘eî“kpñ]Ìœô†?wnºõ.ã'„VÅŸ8i@™÷ÔfÍ·•ña£­ì²‘å ÁÏv•yó——aƒ•ÁCz”ÙÊÜ£7{l÷/?æ-Ù]eò¤AÌÎl¢!Û ÝAÜÙÙBƒ´™ÁÖ`|vW™;o5¼0À„ÿœ•¥/úÎc«ƒ?iÒ`f(ÁÇ'Bkü×®^ƒí±á?¬Ä€göœåtÎû–qcÅw/èR‚?#üŽ2NïzðW®ZÏà’Ãçχ?øƒé|+ï^½±m¿òXö’.eJäW—íàÂöeú߆î¼5eè°e¹ÙÈß‹2´_µÕÿ©yÜUÚ¾¥Lš8„òßZžZ¹®ì >‘¤ÌÖ~#” Ô@¯>eø?þÝ(?ì7w##þmøô|sKY9wú¡škÿ•eð°~e¨úÏ^Uz0ð?ºO#ÿÎ2œ¹Oü{ŒêÏÎ.½i(g•«¯¾žfYÈaÈï]8­E‰aƒ¡ÆMðõ„™j·ØÛɯˑr‡Ç˜Óøv‚²­'±ÇÎf}š†2n&9NzÈà ͵þç:Çø¡×éŒSWR] –µkoºõÝ£6”â I£kZÏÉËÃl¤ÕÙ<)„ £á…NQˆkŸ¯QìZ‰ÂÛs°í Ϥ­mi! Òàæ§ò6É lR–É$‰)&ÚØ-¯ƒ×~j‹Ú¸C7rJžu€_• ÚB…¾öRF—%dI#ƒE—ö(¯3Ms› §ù|(§6«vØùåk_ùuyýÅg—sÎyiùüç/׿•n¸¹Ü{ï#媫ïäócà'•)Ó&B~bL¿‰òè±ÏÉ”%_ØQ•¿ñI»Û‰S¾5/åCz÷(®R‚a=Åç·n_\Ók¡–NúW=Kg@½C¸–—±,eå4ùŸ†3d› ÖÆiòk_äOçµ,*Œp)né¢áC¨’`ÀÓÁà7z‘ºÒ䵺E*-4õfåò°œ»Þ ˆ"À(^½ÛF‹Žà¥Î)n-Љo ¡qÔ»>ý{D»{w9ëìÓËW¾ò‰òÙÏL._ÿÆ?–}ö=ŠÁ3,‡éM;q1ŠuÆzâûF)íé]ý>5¦ób=D"û®ùÞµ‹ f¬O:{õëjëÔ=èàõ˜>ÍÝsÅ×F|·')?m¬/Hʲ’Ÿ`Êר™_ÿÕÅÛÀHÜ.åÞò©Oÿ´lÚ¸©¼åÍo(S&¿¨¬Z¹1“6±²ˆ¦,’·ézU/»rÈ™~™Ô.õhËD¼:k¬U°t1¦u"9ÔY;¹£M†ü¶¥^!¸"ÿN^*kTVGéx÷™Lðƒëó з´,ÐPä—ñ §X4²f)¢ЊÎ9T‰ƒXËÇkËÞ|Œ•·þj4øTþj -´LE ¾ñí ŽΫݳl‡Nsîäã«Þº#šßQÁsÛm€î=H”—ÍQÛù¹{¢æcÙï„@•IÛ¯*Ÿ:ˆ÷ž2‰Ž²‘ÎrбJà41_[nŒåUeJŽwÇh`ÂŒvÞ4ùjïTKø×¶PY´hxx¦¶Mrqpœ˜¾rAæq´íˆºˆ$[e/åg2 ZÂ6Ê( Fƒ€JljZkJðY‡3t+x5ú+Î9+â¿ýðG™…ìÇMå>>1K~–Ì™,i¹¼Ç™&…q™ÐˆÃËì_®¹æÚòm¶Ùr ±‰Nù‰ÇÏ[g ±ysGùà§>GGw]ùÈ{Þ”» 'LÈ2›«®½¶|î¿UÎ~Å)åܳ_–ÙþÕkÖÒñí—mÙ&ì9®<úèìòíïÿ ¬\»¡L™8®|ò£*ûî3³¼ö³ß,ç¿ÊÎûÖrå5×—qp–1('‘ñãÆÑ!šWÞvÉ[Ë´-oýË bì{î œË@çö;îŠ}|5ø×¿ùÏeþS&—O]úá²ÏÌå7W_›àpï½÷–‹Þ÷wå˜g•©“'G¿öKeÁâUåïßq1»dŒ‹Ü[ºÓæÏ²s{™ ÁE_mwßÈzÅ¡CG1ƒœ ¼ž|Tfí8͘Á *€·ê÷š6<ÎåúÎ)Sf×ó!Cú”{ `Ö—`œcï{ÔdÊF|·uFzú :ˆä;S ²L˜ "гÑC‡ô¥#9žÈýògÆ\ÿ›¾×È”…3ð{Ms™´¸;0i*ËÆøó®Ìà¡}ˈQË6ÒµÝô½F¡oeG~ümÛð÷b€Áálö¤‰ýðfݹk2|h¤ý3ë­ÿÏœ1:òºvÆtdÔ<Ëe¯½à/>2«îi$·–AÈ?bdäréü±¿³ï.q›>}«þö2múÐTæ­àO›6?r}Gö)cG ÂWÁ'‚NŸ>2³þÚofÊù›ŽüVC×`O’ÏÁÁÄ@gøð=Hš3gj¿mé`ë ÊáŒþŒ½†iÞàO<(¸ƒò<¸w³ÐûyÌÇ;.ù™¾× ôúkm6ûèß§<úàò2ˆ­?ùÉ óÖò•/§üËþƒõÞ‰;¡!OËJ\å÷wÐàþÜéàŽ¹[Á ëw­v¸ç<á¡Þ>¥)Çæ2KB`óA¸ÜÂ6g‚«6QN^‰_ð¢Ü*o>&™a$=aŸˆÙô‹Sn™ŸhhKG10縮Ñt¶„Ó”g42ƒ«àÊê•;Š©é s‘A‹:)|´‡iòÍÇ<2y*#o!€Õ¿l 2Iá¯(Ú*9œ“¯_!…ÂSéžËžÜi²à]¥^tÜ6nØš;K=vƒÈ³Ê›ÿú•,õØ·¼óß`ÆÿÅ儎eòbñùÖ²`ÁâòûßßÇÌð¢rå•ÿüøÈxɓ׽ûã„‹ƒ;×»nsð”Ý?Ë3 •-rº<©6CêÊŒ¹WMoYµ«ÕÄ-ƒ}„—Ž×Ý©¶mŠøÃfÕòKùZF–zW²û ¦ö‚èÂ46ª·Ü8én…W-Mã‘æWœJ͸'„ùÕÎMzd"ÝB’}À:.ÿÈD ™Aäø„)ÐÌ-ìa§Fë*耣ìö9Ä[­ìègý0:)übcy7ãÔ ²Ä‘ŒYžh‡¶.!dà­çã‰ÓwÜñt9Ëw¾ó/åýx{9àÀ}Ê›éz(“!CËò%)ÿz·LU¥ç×΋ä:ãJ‚iðË̲É«ú“ )ŽY‹¬OÞ¥ðî‹ËY·~¡£¶ôB?º³þ%³¥ÐŒ?¯OX>1jyR©ƒ/u%¡R)óÇ,÷ÞwWyå+/*‡zPùêW¿%G&9ú–U«6¥îDØ*¦v“žÄŒ®ºI`¸_óÓ7Iyk§tciÈi™ù섾խY²“úДr:‚ÑW~^òÝ*¥fuVï¾ê7ZÌM‡vj/}Ï‚GïvfYö5¦HÉ í)M±í¬B9´ô‹jK% #÷ê«Ê ÐÓo !%ªöÉ¥_’®õ;æÖsm—;¬ `Ê…ú$°ÕÖ*Š.ÀÙ—Èv–«1Jž¦žÊ7F‘:(Ú”H8 ¼—©Ë i Ê] ª±W&‰ ádNk;ñS¶úôùÛ­©’„…` `ÁèÜà ÙÍ• ê,‚JÌë oÜWLËÂXÝ@·n*ɺ×–§åT¾ÅåZÛFF±% ¼$õÃ:Y+J$qY=h±›JFô"A xáÐg~IP.7nf–slY±|Ef|š1ÙÏ'Ê#t¼½ï?a »#hò©NÎzC:ãÀÆëÓd9ΧYähZp½èŒiSË﮾&w~ý:Ø+WfýÊß]Sö;†W²Ï)½þõå%,ÉY¼di¹ò·Wá”=˜=D'hkÖä?9w.ÓöòŽKÞR@Ç·'ÎÚ13~K x˜™F¤³CoÍÁ‰³!»á¦›ÊqÇSnfÉÑ*9·³|çö»î-ûí»w :œûo|”øÐò®·_B§ØŽuOîÐ e Q?ž9ذqCy’g Náát´†—k¯¿¡œõ²—”ÿöe œVò€ÑCå翺¢ŒÇ–PÖª?ÓÌ»¯(ó½»qîŸÉƒJ?)ç½ò4fêN._øâ׃É%—+suùÞw®,_ûÚGXžñd¹ø¢ ÊÏ~vyèœsΙåßøNv6xÝ…ï/ç¿öÔrÚé§”Ïáq®·¾õâò›ßü®|ÿ{¿©øƒ±øWÄñÎ>ûŒrÙeâO+Çÿeè2’ž,éW^ö²3ËûÞwI¹âŠß•ï}þ_‡ƒÿóŸWþgŸ½›ÿðÍkN+§Ÿ®üßh俈ÎÅUåû?¸’Ù¦®øWDþ³Ï~ òÿsø_xáûÊkÏ?=òñ èÏqÉ%o,W€ÿ½Fþ'¢\„ü?ÿy‹_åŸ6mZQÿל*üO©üÅGÿ+¯ü]ùöw[ùŸˆþ?oìw¶öS|ó Þ×àŸ\¾ûwƒ¿ö¿ª|ç»W”¯ý£èÿTµ_ôßUÎQÿÿu¼¿¼öµg ?úc·5øßƒÿW¿öágØ7ev·ýÔ?ö³ü¿pYAøcÿïFÿóË'Ñÿ/ž©?å?ò{ý…ØmÿÏk¿*ÿÊOùi—ñ]tÑ_”Ÿ!¿A®–ß·éøM+ç¿úݬó>¾ì½÷ °}¹M~P9ýŒ_–W½êR9¼•I=‰q6b„=rMtÝý5‘Ó!<:a?îšÐà±ê¤)¯ lÖ³ ´éšN Í²£D+C&ø00Š‹ÔŸœ;ŽÏæòÿðÅ”áËÏebdÖÞe_âÛa‡ïYþ鲟–þðWeÞ‚UeÙâuåºë®.{ŒÞßŲ¹3˜tàí3ãºÏ{ø¼M:+is°IråWpíÖ4Êhla ã Xµ¥vÀv6œÐ¾³slÇ¿Ð2êžü LUöÏt~Õ¹NJ[Æš ’…ÍC °’…I-¬ô"QmPý­t=×±"53Üä[F¦×Î ²&¤Èy§èI]4€ yº4úÎJÃ|(Õ*ŸéÊ-.XžY³DFå¥Mgñ¥zÝÀƸŒ‹ê‹ óÔQEȬ4ômbYáô#ˆñ/*\p^ùà?V.¼ðÕåòËWÎ<ó5åþ5OQç+K—ÕçûìФn@ªÑÊEàP?.½ÎòéÉ(ÆA‘õ¬–>‹A2P bµ¿51bcý"Kj¨Üòªúq¼ô­x W•±6T_ËUž^JXãÜ%™Õ`+Ë›Þta™;w~ùÌg>ʄʋs—Õ~‰KAº9Cª4ô)LÇþ0­üšN°öƒ¨²È+o{Åðb»äÙ8,þ¦D®d™ ÊÂr‚' Ä-ëtॠG}ÀÚ¡«uE:ÚB]ëRIË8®‰½ü­ìùæZßs»`Ó4„vE?"·¦$[î! o[/* ÎÃÝ‚,1eT.ÏM¬GªYÖ}-"iÔ«‹é#R5´±C|¼^Õ²“¤eŸúJ*åœtí õÍ#]Ò$KüM'¾µ.+¤2/Cˆ3–¹tIˆÝC1ׂ7¸–g*¹H,8g’iÈ=Óý——>×b]¸òIK˜@`îŠKZT -{ JJU \O  >P;üÕòÐÞ>Wg9V«‡}b€X\> Çñª`&ýÁ ±‚èÔ6Ä ì̹ýºsŽŒ $ë7Qxܲ¡Sœ žË£kî·1ówÏ=÷2Ø”õü®öÁ]×ÿ/šóxùâ—¿V?ô–YŒ*§zr:_?üÉ¿•¯~ã›åˆÃfYȤ,íyû[ÿºüðG?áIýu¹“°rÕêrèÁ/('xËvæ³J„ßç-t Z·Ÿò ÿ¶ü´Ÿü=Dÿj?íõeeù/_®ºŠò{ä‰è¢ü®Í¶üvÛÿÊÿ|pQ|$å/þ‚å`ï ýÇà®ý*~µ¿u9úßqü•UøßC>^Öq7L†·ÞvÏÉÜW&²äjÝú­Ü¡ë5å>«ÑŽè: Þ¡ùà¿Ã ™åO+WðèÂòÔÜE4¸ ñ«…eñ¢ÖNì<&s6Œ:Ø—A}OžéÁ‡æÃÀ‰Ÿ8“Ÿ;]¬[÷eã ÿéŒZâ êþZ)øOpä:ƒ†è¤æ5x×ík‡Cà4¸Àêá'¤4¨¶„QòìÈyîŸÛ Æ9×.^Õ/ ðÄæàË 0~ø¯¸|§9É:ú—Èî¹rWˆd'w:^vF yöƒ:é3>ÎYB{ŽÍÆ}Ë~³Æ•[nyŒŽý׳äð„ß”‰ 'cfî3˜ÙÝ/¿ªŒ16wÂV³ÄpËÆ¦Ùéï=†;€<„mÜ!‚EîÌè"ˆ‘Õ_µˆ<ÈŸNE5Eä÷Ú2ª;p'<¸ÐÛ}'¤ÑG5ÕUjÉÏ×õЖΔj#;dÊ$¡ØD«’àÌž ¼sä̹hÝOÇÞY5à­‹öŽ”Á¯4–âAÓ$ ÉúiGÌC>Jhš·)ôAÏÍU£øŠ0êOzšh{!v\ã6¡ªXÑK¹²dL ÉâË‘d šo³ä§Ï§Îõœò¤å—M»zèWhH{+‹(µ“ŽLÎÁ“•½CÒ|ùœúœÏ<ñÌÒÁV>úÑ¿)wÝõ¿ïeÙíïÊßüÍ'Êoû/å ƒN¡“̃¹»é³AtØ^+Õú¤L1)æg·+#«i‘#‚vÊ¡W}†’$/K€¨çÒÖö²êKš< OfÒ•E ò[G¡Ñßúd9é'[‰#Fö+÷ÜýÛò¿ÿöãLfŽ)ïz×߃2.ƒÍ›µ·4 úÚY¬Á?å@~;ó~ˆ¾–{qúOS^¡x¢ JKk7ø!=ãÏdÆ?‘Ù2Œ?ê;A½‘ƺÅŒoë_ÊøxÈ;×Mš1OÿSï:ð`–_›s-ŠzÚ9‰3eJ"º%)²˜¬Á«ÿàß”«oŽÎ_½òÛëðÄlj )èñ[+ra–ÂȇÃrR¦ÈÙµ‡ ›¯­€ÌGðÄzäq0^c \µŸþ/tk94ò†ŽåœD…‹wÁ"vŠMTžÒÕ N¥BîZÄÖ2NáòKlÑFP–žw³zµ´ä}‚<Ó”¦ÚY&Âè1œ‹ï_uI\kª'H5u= ;\këÄød­7õáë*r·iӎݵb馲Ïþ#Ê~Næ)\8=×Až3Þ yIƹg½´Lgûï>|)`K:ð_øÇOò°hof—öf[¸ë(œîåU_RÆ^ÞûŽ·”Ã?¬\ú‰O•KÞü×åò+®(ïy÷»à2¦|ìï,‡rpùܿ ïyt´7–7¼þíä­-_ûÆeåx¾ýñ¿þ4Ï |˜«¯¼¢Êiå_þ<ÚþGùçïýˆŒ÷)÷>@°ú»¿ÁJ;Ë1ÇSº›YÎ:êàòÙO‚ŽÞÕå¢7¼—5Ž¿Ès oc‰Î)/>*­P¶ Ãy¯<—mì,xß{¢ý¯~}9ë¦'”K?ùéò±ýïò¡}¼\ðšós§áè£*eiåìã/êý³Ÿÿ¢ÜøûÛÊ'/ýpù·ûi¹swûñaä ì ô†×¿š«™åýzvúÔ?~6wRÜ1ÉÁžÏøB®8¥{Åå·±£F÷²nc ²¬âJ‹‡ëÖÝÁõ~4ÚÃX¾tç£Xʲ/k{o©™3^ÌÚò9œ/âî1t„}6à!ú:"δfõY ªXë=ÏuݘáŽÎìk9g‰Îôã¡eÛŽE¡¸¦¼øÅǰtà½åŸ¾ùÙ¤ÊHÖŠËs wrö.sž¸>y3˜Q™3{6ç‹áq<äÿ®#tϲv½Ý}x¨tƒ„›9ß“eA3ó ÌH½˜õðp¶´Lž|,Gñä™ð© U~ôŸ<´Ì›+þIJ÷ÌiÜ-ºŽs—!ÿù«ÿ±èï³”!‹¯¯Ûx'׳ʔÉÃé˜j¿ÑðÜž×sÿéðìaΖÿ"ðÙ½ª<ÊÓ‡3´æ™ŒÈ¿/yÃÉ“?úƒïƒd3NkÿÉØ®ø”Á§lw•µ,?ð'‚ýÇÂoøWüéÈ_õ_R¦L=®<õ¤ü‡yà|ÊãåߟµþCËÜ”ÿsÙÏÙßåe"ö›?·ê?@ù‰7Uü‰“‡Wí7cæ^”YSþ3Oà\û/¦SXé¶½GùÈ'.`@¶€]3>F:Íæ¸£²Dí‰'){Ž™–eR.Z³‡B' /õÆóʬýf‚ß—;u<¬ÎÝ#—´-[¶’Nkqs;ª%eá¢%<‹³:ƒ£œÏÀ”!Ïðˆ¾lšc¿.ïJýTFíÑ/w¤²dˆFÀZäÃÊ.sr‡ÛeÄÁ&òѰ¾ˆÂ»èܦ2xcÓDÚP¢YÉøoŽƒ÷=ªÃL|‘t:£²0›Ò$¸æUºmÇU^5øÃW¡øÏLº1ÝÆ$t-Ý48§ó=tcðÀ}³Tl/àš¿ Öûq{Î(/<ªÚù{ß»žûùÜ•<á„7°lëÍi$¿ü¥ŸP‡žB¾eÔhžGbpÕË™/õBN;>Tø±Rĺ„§ªÕX©ÓfÆ[j‰î6\"qj{b£WõÚ†J fæ?0àpä Í/í¡Ì…,8²µù>´ÛÍu´º„BÛB!¸μҎYŠ…½´ 24‹Ë 4r8™¥+Ô;B¢s @v!£8æ»þ8V %h!Gíøk¯ZVò³ÁN¼L8a‡!í+çúw$Úíø´}§¨{:z×D¾6wP¬íô¨Qô4bõhþÒŽ+ªð¤Õ Ѓlx¨W®µƒuHßôÜ"3fƒôûaÉì•?¤]ŸÎÝàïñ€ðY:x|:Ë«¹ËäîQAnµW­#ØDào¾jÕŽ’Û›Ám¾`zE䇎åU;K¬ ³vlýޝÀcëÖVÂb®!_౤!à+míÒy—°”iݺ5<‡øS&°f—óÏEyÁ§ägÛéÔhí¬©…â˜^xè“ñíÆ¹ryâL}œPm’þˆ[`´o|ÄÄ(£þÊ©?6òFnQ ͲVwY^{‡‚Ëz.nd©úŠU¹{\®„‘rZÂÀ_åNç‹_Jà‘oqZÛrª晩êöôEú°Rã>úW¯)_þò§èûÝÈ*…³ªÏ¹±ˆô”_¾Æ]µI™Ê[÷¡Ço–w\„sÒÓ‰—„¹áÉvbzª_ÙíH#§!ÜNqUKi¥ì5~Ì]í‡âÒÁÃÅ+|ì^íàý25¶:yàR}À‰tô‘­µ`ì-è{‚b˜Ôé<ˆLÛšåfj./ˆ7ºª£´”X%ô…žÐ³œt‹R;׺.° ‘ûhMãH(¨¼&±Oâ•ïêËó-Ð]Fk|4(ƒü20¤s³k%»LŸ9¬ÌÚŸ„8€y¾C\×oãúfàåvç]wÓ›XbYÏÒ¥KËy¯û«ò†×ž—¥:÷Üwk§;èà’ïW_ð†ò–¿º¨Á`àVvçqtuć³¾üÞò¾}¢¼å QŽñqt@çäÁ\vÇŸ¯]ö­ò®w\’µÇ.5šÌ]×ìÿ‡?*OΛÏ6¢t x÷åg¿4´ï情çNEûî³7kýî/ûÑO”ÿÍ{yâ|ùÙ/~ÉÎEóô„[¾b%ϼ´°ÿ~¼ä~œ­{ÞõaÞüøßÊg>uiÒ½{!Ì=È«cùðó¬Yû–ÛÐå×Wþ6Kƒ~ú³Ÿ—›o½=úŽü'žx<ðÇØ=cm9ä dyÑWÑÇ;ÚÓàý|GŠ?úðSeÎ#+YÎ45z3ˆ¡ã„» e{¾MìÔâÎa<Œêzðu¶æ\'Zµn¨öaÖºgÖê÷a w¨Y»žž6„%›6máîËvpÜêoÚ­<ØÙ/ÚUV­aW%x bï[nù%Ë…®)®~ó›ßKcð£rôQ‡–ËÖgž¡xÃx×%ëxØmúS4Ø û±&Ôu¯«yxÚ·Eº~ v1ßgÄïÀnÚizˆ?txßÐ_ÃC׃xÀ×ÜM£ú`Û9÷—¶öEç êßᔟ×õë‘EûQ«نÏoÝùg»#e±|½Æ%46lκÿaC‘û­§l}­½awͪðÇ~Ƚzífèô@ÿ>ÑÅà¯ÌéDúLBø£Ç:à†c?ékóÁì.åîG«×nb׌,õ[LΣ|¸?pÀ©å¾ûa0ð2eʤrÖY§óŒÆ¦Q®#y­ؼwv‘ʳÌþíàn$ወˆw4Nu Åa…±PùI€Î)_ œœ&ä—çðOH ÒlºôYÏ%¥ý*¶…צÃy Ó¶xÐ#3Óü¦A¦ll7ŒMvÈܽ©7õ­ÄÞåtºÖ¬tà<ºLºO¹ðÂ32ñ±KÁú_̄Ùg¾…uý¯¤no,ÿþ³[¸3ç n ö~uÁ;*lš@̨³Q´ØÁx’¾ –Ž,ç¨ÔÅ&\ä¿jÐÙI·1BI;v¡B(Dp9WéÌf{N½¬³ÒZDV~k7™…9¤¸æ<4ì|dp×tØ)œ”‡4‡¦m_fJ‚t¹*“´÷*¸ĤÜêçú .µSê‚JQ^îJ“Ž–ÎúïŠ,–¿ížb«€üÔ®­ U§Ö.ú’¹æƒ/<€Rßv¸ú”i˜Ä¶|‘ƒ#Ån¡ ’1Û—~}ýëßæ]GÐ_x=íÞV^f7˜XÌR±q0·áM} Ú5´ûziu²#,] ÚŽi+gµwr8­e! rëË–o{(µ•Nµ…º%]gSÓFþ¤æ²–´ƒØi¸ª}ü,õŠÎžu;¶Y&‚sHÙw¿© ÁÝ=çžuݾÛyަ“탷#Ø*s,·žÿþ£Ÿd]üˆr4ëàÝúÓ-Cï¹÷¾,x$ûõ,…9±L›:•8;™0CüÓ_üšÝWÆÒ1]_Ž8ôà,Ãñ…[KPüæªkèT­Ï-lwr ¾;þ¸ýæý>œ-:³ü¹\¦#Œk–M»ãλhìé´³-鿳óŽ!ŸyúiÌ6?]®øíUY‚Ãbàµ,%:é„ã˜AžÚݘžË3 ×bð]4¯üíï2øØ;¾:ýžÐÁgí»OùíUWgPòô‚È»Ú2°8òðC”/ PЇ%"W²æÞATß>}«S§xþÐÒúGÊ“ßî{¬<õïQ`»¶tblÄëLwe¸­ÇˆX¿’T7dÖ™º1"ÜÁ<=\ç™™"‚½ÛjÚ‚8skLÙ¹°ùÀ®£vT|Ò²-åƒ]ÝeðžÌÍšõ*êV:*tDKy’O×£WÒÿ rÀÁ{r7g\™2ewEÆ1Øe‡¦Áyh4’Q® póP±„•+×B`'†õ쵘ÁÊZl«³kÍå—?AžägSITÆŽéŸÁc?¶@T¿t€(doÆå œpÓ¶ñ ì ]Òa±œ,Ž¿Ö7í“k~µ÷.§µ€³ÈHª‡·ìùÏTÙvø%¿–Ÿ\¤Õ‡mg}ÖÆc 3_–û¢§7áSÞ­™ZŽd õ6õv™Æ±tä-üI_̨‘2áŒÔZ2ÑÆú¡¶ðÜ¿w˜|g„ï½p9ÔÈá#Ø4ÀÎRJºœù’}ËÛÞözÖbßS~ùˡ>ü6žÁ¹‡ð¿ÁRÌÉ,e˜_&OaØSKá7¤Lžj r‰ÌβÝzò¾ÊÒî*$aÌYâ×,¡Ñ·ÎGoKGVÂO{à›y»0Š´rˆ¾tøÓ_ô¥ø3!Ï—guí®>ƒø§ü=¯ügL"An‰¬u½LóKJ›ÕêÉ`XÓ¸™›6*D5•.¾¥¯¹Kšre²³Ì†qmᘞºGº|^Zµ €GÙ*#IÓWcÕR•½¹€œºª‰ö%Yÿæ·ÖÿˆL¢ù& ÐÀBW^‘Ã4lšòƒžæËµì1ŽýÐ7 ©˜ŸN–ðœ+¶àâ'&A_–QÁtBEØ‘ ý[Ù+Ý:øÔ¯<ð®îíw\ÎjÓÊ?}ã£iç>þñ/ð|ÉW¹xJî>¯ç½+¾I8|‰Ï–£\Ê ]RÝ'ß; Ê5€-Àà à1ðÀu,:• Þö?…¥áÜmÍdC†Îe+µ"C ½ð%sýl-“DS÷RN:åHžÕ¨/ˆàOÇiííDÒSOÎ+¿ùõíÜåbÒž)gh9Äö‚8¤ÎFH÷ÂŒç9œÈ‹¸~øQf§•Wñ ìËÿliìýÎZç_^~%û¸ËC°cGïíJ¯V˜úÂ-+È„qc«ƒÃÇÌ6:Ý-ìv?^ÛvüöÝw§ É“&Ô £˜/žòêªÖ_¼,w!Ò Ê%ŽœËm¤#©“&¦sžY©VOë>¸{Ža¦Q™9Z¹ÄÅ2…°Àá}8¹…‰S?”Ùñuçï<èôÊ勱ž¡•Yz.%‚]•»•áÙ¿Š!Pœ··ÞI·¹vB ÀY¯Óùå7U[¥ÅØ–’ß`sjZÍÐ_ ìDÇt”#¨œ [MÓÈU_6ÖžÌ ScPØ×4C°gU#¡ §ÑOÊUnuª‚ðòcbGÅó@‡:â¶ìl4±@•ôä¨NuöK8ƒdµ¡}}y4£Šç–n5x±¯r£¬êŸ¤'ítx»^;8Ñ´¹ùy{¬¼¥¡F¦Bóoš6Oc’‹¤gÊÑ’ ³h;äÂÖŽ$8ñíh%#®Íl'é)¤e`:N®X†ŽìøD¾hVvÂC0-'¡BBÙðqe€š©ÑßYñ>YVUÖçAíñê€ýQš·óì±ç°4àÞ¢ùÎòÝï~†™®.gœ~nwt¶õýÞY‚<‡¾Qù:H¶8¾pá’Ü=pyќ٠¸s8ú øx·¢=q2ŒÏ`–«ñüÁè¾e ñD¿ÉÃè ¬up ëòmí­)li<󳪄:h í€ç~žË9ˆu›}Ê+^q³”sË9ç¾ ¼ñ¯É.[×ßp7ò­œ·ÞúÏ] [´Nž@ç¿6”ÀtѾ…¥µÇP׿=)=ØhBdÛ¡ÄÕ0’·ÉÕÊæ§}áÄlT3 ¾á­Oé#ÚÔºdçÐ\M¤j¶ñН.¦‰'„w—õ܉=)âȈØ|äfvýywv¾úä'?ôàlJ±™ºB1…?‰i/h* #Nˆ‡±#ôêDMŽY¶×İÀœÇnÊã¿6·¶ 5‚AI”æp°µdɺrà &²ÜnTùó??»|úÓ_dÀzv™ ­Üépó7”—½|ïÜݵ{Šü§ãÿÊN@Gfî³W9æØ%å{—•‘cfYw¬\•nFw,`ýg‡7¦-,ßd»Š[³lÆ­/Ýã_|òÝEÖ…VN»^?ó¼Ët±æà¤ËÕ3ÏuØÝ`í)¿»Óëi—ë.PÏ}Ú¶ ý®4»ÊóôŸÓrè‚ù.W-Àü*Emô*g+šiâÖ†¯ÖÍV*Zš&*’ ’#»4¦V<êamæ ëvl• 1À¥ Àذv6TÌT\+&ggªV+¶³3vÒQ>~¥Qœ6O8R%h‚Bü°ÁÎ8­ýìÈL02÷™<Â/§$"m󸝔±×áÇo½€n`kð­ûƒ+¥#m‰kE® †Y^x7ò“glíør màV¶,k_½ö°¡OƒÏy-Mƒ-gà!Vµ#|´ºHu°Í*]â>žJ9ßb[é†8.לÐâ‡Ó´ l‘²iRЧ¾¹å®ŸÙùûÞ@oŸßqǯÙCþKåøãakÏ—ïÿæò’—ÀCÞGÐiÞZ60›í»îºëïað)v¹š÷.œD{ 3üý³}`&ò BƒKõXd'Ãv±Þ@®Èˆpðç|vàqFȉm -gwÇòÐñDÞnÛàÐØÙ}ÿ”—/…óïÍ|š½¬Ü}Ï“ð]ÄÇY÷®ÇatÂÇ”)<0ÙçøÐo`ž?˜6m2t»°+ƒ.çû°3Ò9Ìœîþ§ObiÓ‘eÞÜEåÂw×#åC;VŽ–>m\Ê~£bWò™â.îHäðÅ‚õE©©[] ÿéü²€“æ½XÆ:qò˜rÓsËc%^å=6ž–©•„R l ºÃrJNß¾¬•å# é`ú—¿:þßY@ÖÎZ¥ã –Õ¨š*SM2RKçŽÊh£EÙd» ¥ÙâÙó2ÈBØJèLÒx¥µƒ.0 „YÁ áC‹“Îò¥ú‹Kz$Wñ…“62(O˜¥K™jüA®ð Z|‰*#ú Àsí$ÃMÖ'W”j“ÀcÃjð7DÎrèâÈâÍÎíuía&FJÀªY±G5VÕ]zéÜ7Þ`ÖÒ¨þÊÓ œƒ_ë‘w[ü5 ÛØ&¸š¿t(P;yc²– ¡Å3]=Y‚¡6Òm>í,uõôߣêÌES°¾lJ}Ò9XÀD‚¹¤#\4ç7fmÇ»éÔÎÿ/þ_åÜsÏ*?øá¿Òùÿ KjN.×]óX™0‰ñ±û‘kÎÝ¡æ°Ãa°ðËÞÍr O3¸†AÀ‰LS†ÓQ_ÏJô§±'2R1¤ì•ÓktÎVo Û"Dom•P¯r8«ŽíXfã€JJ…Ô§SƒyVgÈ`ŸÆgBò|¾'vrP±–«n»m ·|}Bä.‡Ö;Œ—!ÍäêžÜñÎÄCyCôØì\4mÚÔrø³;T?v‡â%I€;[¶|ùª<±yóÆìd4š»£{²ÑÁ;ÞñÞ=•—líÁÎZOþöÞ`¯ªº÷Þ„Ìd 3áMB˜çD@¡ˆŠZ½¶µ*–ÛªµÖ¡µV[Djµj­­ÖÖëtZEPQ@@d™!1@Bæy ÷÷û¯sB¤õÞïë×øMž÷}žçœ½×^Ó^{íáìχ™:ñ>œß~.î6P˜ÈÚ›ssRóVoÑHÙîˆþdF^mcRå—òuòœgíÕŽ»—#Ðy“beLœåËmX[ëGÙb‰³Dq™O1M:¯ צal°¼ÓÞø“¶ùšÆex)zõ–¹üQòG<”Ë¿qÚ·¾*|ñ[­ í¸Ã™°JSþÀ{ÒÅfHåÀ“æ™àEx¢å§ Bû©KD?D~»ƒ‰»2-ueÅÔ¦¤À„Ñ«IÖû¡*§¢‘—Òs‘ƒ „5ÿâSöÒDÐIjDÖâOq þ‹/÷¾S?¿èÈòA¤2½ú•ã¼edÂh&ÄßÑ7 }…yj>k¿.ˆ0_Óêø3©ÓÝÜšÑ7YÇwnûÂç?Çç'ìþò|Ù~hûà/f˜§³Eèà¬Ê›?ÒšÍ`††´('JñøVù–¾¼@Ã|$¹ÈAõO˜‡}Óp§Pç¤Ê_ŸÏñ#èD:®_»õ&ÊÔ´S™›Î.F?¼ŽíÀ¿Ê`Åo°Ë¾¼â”– S¤}ëdXÅiÀ¤üpŸ7Ó§®«³,ùñY½Õ½òäJn/dò¯|tå«pæ:’hò[$õØ^o쉕­J?mp„+xо}ãh'Îíc·ØÀ|GßÁC:èX”Ì“®ò¢ÏmDËæÍy¥4 çRvºÄ-7ý·yT6­À¡Ñ C2;ÔO›RÛ:k¯¶IÕ寯ÿëpÚ}ÍÈ)Óî˜rEFWîì0ؘF÷¿ºúh~Óq蟻¼Ò~}ýh=&@e¾XÌ8_ü‚ñ|ZSƒ²ù¬îÐ ƒ —£}.˧iSØ Èþ¶Ä¥±J¸%4$ÃxÖÅI™†û_¸„a™ŒJÓôH¡åNg©GÉ¥#àž0Û±µü›.LJT%-¿¹/gA´iØÂW¸eÁÅ™:(|TêjVâñ ÎŽ'C*^:>„«j[×cÒ nUà°F@æVÆ;ët-;PÐpÒ¬Û`o"¦¯\ÓO!)þH+‡ÂXÑq9ùIµ *óB5en‚ü>QnÕ™"ÁÒ)ŠSE'¤Q¼òá)äòl…‘¼–$7ò®®Ñ‘Ï-ì5ž­]oúñÝí´§>¯½þ ¯â€±µ?{ëëYð{NÛÀ!Q3öqëWF…ELº!Cv§!»žNÀÁ™ºò’—þIû̧߷ãMÀöÝNi{1Ï߃Ãz^Ò„á4T5ÄNþngß:õ"k©óÆðNNxÔVðÞÅlâ¨gÓla*Û ÌŒQ^qG¸S¡”_YÝÞõà‡1ê8Ž-OçÖúà6ùö€Å¹«é´\~¹‹†/áó䋵l6pÒ LÚ‡ÅÑSÙ lö2„Ñýs˜ï?ŠQÒŸæ4s×( °]êr6:p4ýsŸ{§//`£€ÇØ9ìHU/i·Þ¼¤=Ì>/ö-…‡®yã3šÏmü®?¨)F£Ü©Y6þ·Ð óœ…-¾²Á ¸~"5dÌ V§[ž”—lR…\¥¨*yn¤ÊQ}P;Ä t÷Ž2ÆŸh”Ðp”Ö¦´0É‹¯Òç;tc¿$±ìÅZùíyIòÐHí(Š>> nZÊRŒS))‘Á²Àt±ƒ„C]),?âˤQã äg;ºpšœ6†Hgc¦èoûÏré³–—<êd”Pa°Í\Ò%˜ÎøÃOÅ?JL#QÚ/÷!~ßÞççÍN0JQA[M×Ö ðk6J£Ÿðeú‡_dµ3–´ +öôí!ž(‘ŠDxõ¢>+Z:Épå^œ ¢XnêsÌ1§¶[~òh;ýôSÚ§?õùöÚ×¾’…µsÛ+^q>[ýžØfÍ×Vàk2ä=©ÒÈžŠ?3:~ËHY‚pü§ôx¬xisŸÄ*Ï{ÿµ#U“/@•ŸòAk»‘³0¾Ä åÖÕü5Û–Ÿšª%oÈà‹/f2(§†'eéIT#÷ÚA߉ó1ï'ÏÞTgÑP9©ÀÒ¹õ¸¾)Æ ë‡àÎ:ÂNŸC?Ê”&|P¨C¡AbõiòPéxð‘«l +ß¼X~´ì®oKœSG¡‰®Sn¬£„ïìD;ÒÜ-ÿ‘”ÖEN+TÒ⟟.µ)o'ã ë9„¨¸H‹ Cˆ_¹js›1{lÞºº»ßÿã:òŒ8%ÇNBþ¿àÖòæ›5­»üå›,@€^Ù‰Œ1ý'¤úϦûOúÿK’TBÛçKt¥¯Bš2¥ˆ3Ðqë üàr #"¯Û,ÿVîæÆǦòŸRšÝm¸§ > E”ô„%¡¿ý%r*ý8ïHÃGô–ƒÞB(Hè…œ_ÂRá O:$݇õ® ÄmÔü›ÞÖl*ž„÷MFFáà T,‚†*¿ìÔ‚ÓR¬#S²êO¡£ðœ‘R S†žQ¤7ÏbQù5¼pŒ<»£íX)¥WñgrøÁW¤1ëh¸1àòQ%g•k$ꆆ™\…1e’géìÐ…Ž%E‡Šb¡’ÊùvðFTY\ŠAØhëa´Ë¥y®Ï^Æú›ƒ™@góéí¥œðÖ?½¨]ðß—ã¾Ëˆû«8Ëd1‹†kKYÖB±1µ¢¬–mù†µäw2}Gˆ»íÈKD…&â'e#Ô.ÁõTnX2¬Ývë¼öÜóÎçmÅѼ‘üw±uùløfg>ϲe4HÔ2goøN>1[ Â]Ê Ïf„?ùVÊâÅ ÿÆ‹ÍÓ•Ói½t¼h}Ûƒf4]/mÒùÆ(øüŠh …>ļWv~͇ ëhJŸ«c#qæç dˆŒEK‚ý.KÚ‚ú‹­’¸t P¶º‘gïÃ[OXË.–RD —?/Óùª××Èýt(:Þ®¶šàñ ËU:È…éWþ½B52ÃO:el8ãæ-îHYáÅwê(yþ¸TsѦ8ÍrýJ/iÓö™8i‡vŽÌ´¼ÝyÌ"à®ÀËüŽÏ¯”µ_ûßh *‘ÞÐ(ôÀ—™ªmž:d~j’þ¾!iCM— eŸ8Ë›ÎÍÛb ³ŒT¼^+šzN _U@tbP:Bç¯xº†:aÙ·Þ†<C«¦€ â‹tâÒ¸CF§Ä„[Œ·s•ÄÓ@¡2N¡#qh‚¯.èv£`V†JÅ ‹Té8€V±s…N@ ™°±Ž }#':OFE€‹n• Pñ(xú zçÐ+ç(*¯p¼ Ž‘nÌx£zäß&n!ðÙŠÇ–ˆù›H}'`òÄ¿øp’ÄðIhÑë—×Ñi,”^„·ºîª¥Qüè‡ ˆy°á-'µu¬¿6þ™ÚG#ÔÜ]¼è*òïEÎÓOóøODMŒ6³Î’Ðyó\R–ÎÕõ ¡»ñ&ÀNÀatnk/?ÿÍt\PÓö9­7œQï ŒþXyÈG ê.+;ÛRUòK8”ÿWt)6|Xî<άu håq›÷©“§äÍ®‡Êæ-§Õx”[Ó; hÝ©ïªoÑ·DîÚ‚íg€ʶô^5è¾ëeS·ýÖn,ºyg3 VÉV”žº‰ÜϾ2x×3õk ÿÇ4P#8sËAFI¼éœ e¯o¤º;ŒE9EÆŒ•µˆâcµ0ú©…``Ð] !^ЍåC)ÇÀ g¡¨« wŸN`ñê¡tÖA ³ñϦ4|å[ wæêå9ù¤’N4à”{ã*5rB$¨Mšûêœk8A”Ã\Ƨa,òÔó ¬â—6xâ]yæ> ãHë.4)< ´}xuJd?uŸNQê9••¥Ká=ALatôR¢Ã£®ÜÒTdyó á~í€òIát’„‰"LX¡à,å~ÒçàV÷+ s¬”¢Ö á+s`ÍWñf$QXI1ŠJ„qÇRHã”’Áì`3„żÿÚ.¹ä‹mÖ¬™íüóßH¢-mξãÙñk]íÞ#¢0ÎHb b‡q+6_½/gtðØão?¾ñ®ìôÉ, ®NÀÞÛY0ntN|¬{ñ{@ 3Ÿè#£•œÑ½ñ”|3ÜD`c7ÆõùÝu"y§8¡´É4zc(¼ç„dOdv y5'mc—û篧ñïb‡´3Ÿ~P{É‹ÿ¸ÝqǽíÆooÏ}î94pnoüÛo §/1}ça…Z›Í”¢}Ùy虤ݞ=þg a‘òîSx$ÿà×QOçö{róí·-Gß ]ÂgŸþ¢jG´3ÏØ·Í;½íÅ Ê„8}úäì¾60°O;üðCXß0†3H6 Ûµr‚²ë–±PyÓfÎV`›ÓXØæ³‹Ñ÷=Be>8è ðë.Ió;yÊPÞ" mÃYÏ1täàj@is؇æ²Å™Vxî¾S±Ñ±ÝŠ<êÜ7:„ùÖ1¶©9˜‰üVÙ-<&S/ƒ°5m'¶ÏsòÒ7u ¡}Ö¥7´rˆ&Í[qÊ› EløÒMY€€)Rþ»‚`xÑ5!ÿü¤!ÊMŸI¾TÃP>ô¥ð™Nà ò*46.IÓÅ–xÈ[i!nüa|‚´ü@ž“š–NÙ(AÂDa`& 0†{p¿ )â‘®¸Ú€Tœ„pò°ú%/rAÓ²åºoÜ^XYlèÙ|ïØ" lÁÏ/ÿº ”i°¥áÊoêšÈ_ñòRœ1à4:ÉΩ?îøg·+¾ó>ç±mïGóöðècjïxǛڜÎu’¹–kuM¢»ªÏä\~J·²å}GTGˆ†X’‡O4©-èô{ý·™…ò“÷ÂäËÚ[ßzQÀ‡½õ­.üu1Ҙ罌½ÏÀî¤3¸#ÈÙµòç3\Ð#è•Lt€¶Ý¨¼…Ó5© m"ZxÔtª>6þœgӛ㹠ὸ2Øe‚.ÊuñûÒ7LäÜz/ÿvB|®_íªà’'ÚWñ„¢_;A˜ÕǤ+ºj W—¦ø…yS‘Ðñ^{’¬ò̽ÏÂvŸøelµÈîàØ•_%‹oK×®[ËQ{FËÙÝrì˜19`væÞ3rÐë•ßýol'±3ܪ4üÝ~5‡QêG1hc#ß(]ćx+EÃÔˆüôÑVz-hïpŸÀ&ÈèÄÆ…¥Q c>r©©†2á5Do©¼­\­x ©Àü[±ÙÒ©WcÏÑÚä(Jů°ÞG97JzñŽ˜ú1P¬U¹cþÇH¤Ü‚ÉD¦ `3ib€/‹ÿ";ª¢ ÂÇ‚ '+Ò·åa97ÜðÍö—ùÞvÊ)Oa矷k¯ý*¯ÐŸÅ"_ÿ¾a’»â<¤Á!†º£ŠÈÜK]K£àÀvã ÷dað%Ÿù›ÓvtZöÿ_Ë"\×TC^+\7²éd¯9 çÐŒäÀú·;¶Ÿ¼Ƭ,ý¨C xð9\“_Ž’âàá#sPÖ&v,ÙÈ~ü·ÛšuÛpØ©šÚoýÖQløWíÊ+Èþ¼6{ά(ö½ïß×ÞôÆ‹8wi›5k/>^î)Ì}žØöžöLFè·e`Å©7i8@ ðÝE‚4rÝ*t?c4hO*”ì´b>9Ÿßs,ûW^u'Ÿï@cçÎòÄ!Œ{·é3&µ)SY_Àúƒ)S'1Ê4‚ÃÒöà~{žoo§æ9 £3’µ|ùªð±’=ÍJné£ËèÀ,n7^÷`{dÉ<ðº•jOË­]ƒ0}aÊÒH::¬— çÙú¨Ítdœå˜gF >y€¬–?œ¶ñ„…€ŠœëŠ¶â¿™,i*w¹5œòQ±æ¡ #á’ë ¿Ò<´ ¢âÿ:Tvä„Mc‡_Ô}2 ÊfÉŽ¯Ê4‹I'ß±ÂíR(ClR”\½/ ;Äk£þU#=%H²RJ›$DMÂÃf'¦Lx0·¾¥Þ((½Ø-jÈTOØPx$\4…17¹ÐæXãÕ<Š‹moà&ÅíqÏÞ¡Kp L'œ éäê Év'¿Â'iEc™\ºt o´ö¥¡³¾=‹ÿþ>Ö^ö²ßns(;/~ñ H|,[…N¡³àaŸ¥³èŽ´²`Ùõ.~žå9aÞð±l˜S¥/¸K–§=¸àqôÈ!mår¦µ½ÙžôÙí¦ŸÜÚ¾øEÍ{f:Ü¢R¡ñµÞ–±E.iÛØÍ%Œxc0¦Ä!,ôÜÁŒ/ðh¿ògÖy ß4ÀJáàgO^PVh‡EFCÔ>€ÀkÁ+}É·Ý‘?~ýÔ€G—FºÖ¤…ýˆC0ëðÀ ìq#å.¥RYBŸ@"*¿ÁÇ}M#" dc뽬rÓÉ#V¯¾¼(AGLS”S™K[Aä-rBWi,Ãù Ëjgˆm×^Ú£õΓ?÷ìßàìke¤þ¡E‹Ú7.»œ âðÛ£ñë[Û‘‡ÖnýÙíÄãŽm‡tp›Õ®þáÛwßÃBæ)í¨#gƒˆ=rfÔ¥—_Îú°˜&z@ýËÙRúÛßùN¦y Ì÷.¼,[ÖÉò˜Køº¸ã?tH«üqv’˜¸v]ðà)1P0âØˆˆƒíèˆÓðJ œ¸Å«G'<ÄPX^Sƒ'qDÉgœ-èÁÊxÝ~ño^ŸJ„+N¿¸E3ê nXèH‹W¶Å±tåÛ«ôèo±ƒäñ®V"Uñ P M)žJ#¬yŸÃ¯Á¥OFvÑÙ¤‰chü_CEý‡4Ö_Ô¾öõËÛßÿý_1‡÷9mé2Nصrò-TC!Í$INbãÖˆwí2ÖÜíÞ¼üåonŸøø»wtf <Æéˆ¶Žý¸wo´T´{ù”7ó=y‡\JT”ÍO«FŸÌiàd&y¼CU ièÔ˜BŽfôqè°A¡õ³;<äëÖ6yüÑmO¦Æœxâ‰í¶›çµß~ñÉíw÷…í _üz›ÿóEøFö×߸ÑÌÛø\@š!lË9¾}çÊû8S`LÛsa4xŽ¢Œnmë6læ ¯}1d·UUQöz)aû¯ÜqZØVÒ•s ¢d‡£ÊcÆŽd”S“öƦ´AFrQ®ƒ6«V¯o·þt9Ÿ‡à«o´÷ ‡«á¾ïÜ™tØÞtŸiì64]&°r*£\¸¸WÖ¨ëÕ«×¥æÖ¦‹/ÍAiëÖ¯m <œÓ‰—ØI˜ÿh»ÿ>Ï€xò£}ÈItÆ0Ê5¤a:ˆ§?;j»1Þp¿Åo¼2½ÙÍßÊs±/§Ú³@ŠÊüÊ”o“†pâa;z³Á‡(\µ|P»iÂS–bO…Œ íKd¦ö+¨éŒ¹ôÛ¢Ùdžè73 MƒzñIÄd öf ;B‚hÇñDð¿º%›üÉ“¿s_SRŠ Êpç¯4ãþlò3POÓÐ'ÂnÒ`¾sž)Êa]o=Pœ(¿Âêwmà™ÖM%R¾|pœ„mM;I‘ßдó†§`ÄÙpÂ[ •+6°SÖÎ9§½ú/h?»ýMí5¯¹€M®§Cý6Fæ¯o'>夶ü±5Y›âÛBù‹ÞÀ]˦ô(2U2 'Îß¾aýù¥2øŒâÐÂïüfûð‡?Máílj86 ¸¼í¬Q£ù]oJö~d\C>öË èŸoT¡édDV>ÓÂàÊ%[WèH˜ÔC„Sg¨7Ù”¦©o;¸²SHK(ëâ3xÒ©†¾ñò/?Ö›â³ñªþ #:—y*”†Éw¢|&Ph¯|  ¾ã½õ«œþÇÿÄ·vá„I!ß*k§K=ç--0^É¿¾×³Ýž†eÕ¿´Aa´ô²…`}#IØw½Õ³Î9‡ºhlûÒ—¿Ì®uÓ9pñÌvȶ»9äö´SO倯»Ú 7ý¤~ÚSÛQ‡Ñ®ûÑÚ]÷ÜÓÎ~Æ3ډǟЮ¾æºvØÁìÝw·¯_úMêŠ}ÛþûÍM£ƒ¹/øÍçÓ‰8<‡æº•¾y¶K/ð?î´/tšÎ¨Ù„о¬õ7îrÄøêW)+‰Zv)_¿Fþ¿Ò€Aa óÖ­å+(2.¶BAÉhNòÌ%«,W¾î¦ŽÍ•í]¹·q–×àn«ÁÊ}òY RÓ§CAúþ PA@ýB %˜»¯Ðé,H§a0p:”¸pÕŸm„û €qõ¾RçÞFwáÇYúÌŸ#çÊ*Y#4\G‘Ñ~¥—´‰Á5 Ú¤R&`B°Kd&©ŽIXžC#ÁKx£°uÝ´Ã…¸: ¦«ÎŠ iõj…e= êLÌê@qÂÊ T ›ŠøjL€Ú¦¡œÊAî+¿¼çcÞÈ0 F­¹ä]I¤tJ‹5±zI/¿y6?xg…y3ÄÇd”~q8’i,¯É~þ¯{í+rúç *ê}7M)N‡®.}ô“nŠxà ¯Ò¡žÊ•;¯îtܱQùÿ´½ü÷ÞÒ>ñ ×t YsžÆˆI- vW›ÒÒ¡;ï%cþkÿÚ€¬ËIi¡î*#ì†ÓpöMÅV›#8ù׺-4Ðo»íçÄÞÙF>¾}ö¾íÈ#ÎmŸþä•tvžÉ”žg¶¿û;ç /c¡í4v¶¯}õ¦öµ¯|Œ4Ç0‚3‰ŽÀF†¬Öi§f„ÞÑþ•«6”=ѹQ v¤ÚÍ1 \œ¯C´ u†LÑ«yÞi?ÊNIÀø¶`X[˜šô8ó¬­,œ»L²äé˜ÑÃÛavH]ËÊzœœ•ß̨ÖJ¦l]ú[‰¸š„GùôבíˆÃ§¶Y³§µ}öáÖ ì9nOFµF1b;€žF"çæŒr å ñòÇV¢ic#I[BGaõO(fjÑ]ÑÁó ¶y|Üδ¿¸ÏþÞ#XX>¬NAÆœNd^Zܲÿú{m×NƒzÊé»üF¡ÀÄž‘SÝúW;åh×*@íasÜÛ1÷Ðʘ?_Â{éliÃ,tØmè0eSÈ”i‰¯Oëœ%,¨ø’G¸ bƒP”Hç¶Ð…Ë›y”`“h Ê^¢ /ú ¢ G¼trñã†þ%H](@.‘ʯ~GtÜTVË7ùÄ Nº„w¨ûÇD»å§Ê£ðþ—lÂêʈÂd¬¼J>ŸpüsÚ?þã?µ«¯¾­}üãµË.ûp{ßû>ÂýÚQì&¦moäc•°£CBÞ)Žöa¹‰V,ä°L„ mG}ùdT£˜ÊwãKÚSNz^;í´“Û·¾}¶yE¶,µc¢/°1D .àÚQ¤z‹ãÍ ·°Vk2Uò'a—^h§Ùˆ5}ô(é’Ô¼ÒÖHoù¯ë@ž4Dô/ ñ+cÙr“:SË:¬SåÂED PgÑu ŸxSÀJaä!WÉ/};ôƒÁ'3:›*Æ@¯ì$@Y±×ˆA@”ci}ÒA>õ%ò”5øV?vlWtDË:–tú@a¤ÿôõÖ“0ÿ—=*‚>ÂÑçñÌœÙ~¾àçíºßÌ´Êû˜V¹–äÖgÖZîoøñMtôm“­k_ýÆ×ÛíwÞͺª½,YKÇa¶rõj6x˜†o\Ò>þ©O·?Ò~ãì³Òñ¼îúÛzÖ8PàT!·vp)zý/“èß#Š=æ €¶f~Aݳ$Qób<‹9£«—³öØõ8hº!ƒÌà__ÿ÷i@÷ì®b_ñG—02Çb”T;Jy§£¨P2ÕRM!ÄSÚ¨ŒS&uúVtG˜*_Å]NÊׄqHf·øØ÷òQ-SOT.NÂGÙ|Q†b\–yñé´ŠᵸËbeËÁÉ& (÷^y ßÉHLäðG¸€'`d9«AJœŽÅð¨@Xiàhø‹Î€¥>ЛDTÀ‘7• •’´éž¹ ÍŒ0"ƒ£=’/§Mdò@§«©D ³’•e5_¼èd)+Fá°»ßàˆû¯•Èšú –EpöŽŸ.4¿QŸw]¦¥Ó O|úJRg›œ‚åH[9›Û.Žd· øiíþö¥/]•yо:?`ÿ3Û¦ Ìù†7ûCi“N¾½c;òjgÚ€M ñÍt¹OŒé"4\WðÚÿøãã-ÃíüóÙè“;- xj7nS^Ø"ÔáF‘HâæI©:¹—Ž´ê¯hXÛØ°±°‰Ã¿„ÙÈš˜uÛm÷‚è>Ç´W¾ò\v1zC»øâiÏxÆ©íôÓOb~üƒœ`ü³Lµ»Øë´ }å+ÿøÃFÙ›ÉtwÑñ®¡)æ‰k§Ò)¥\1€ ?ð[–6+Q\{xìóH§û‹å{æÏp^x‡Ò„ñèº4ƒ¶ÓBÙÛ,·üiVDvÜvcîµWð˜ZáA…ȃˆŒ®tŽ6¸ø]¤AGU?MîÊN9à±Ýe‘O š_y³&õsQp0Ô7˜ÃOÒ•ï­vlñpF&Ì¡â%ÜÊ`¹Õ¯Hùá_Æ˯·^¢7²’¤ôЃXùýâeNŠÛºï}!7…VyµËvùˆ5« ë,ó\¦wñ倣>b5k¨nºù' RÛ>ðîw±¹Âcí»W_Ýî}`^;ëŒÓóFwÑ£F2mt=[‘ùßÈ|ÿ}öamØmÝú ¼UÏÙÛ‘gwÞìß®¿áÆöôÓOo¾ým¼±]Í×¶;˜*äpN—ÜÕWòl‡>¡Ö12€¬p¤ÌL_ò'÷Q)Œ3, ÙÕŒýÿ/×€5l“¸t1GªÛÀ …±ÍŒ£°ØÐ´Y4úòéèƒù™õ”ª*\"éTŠrT}bœ@Ê_ÜX`3b@œˆªêˆ(WÑõ»ðjIÞ–[Ѫò k¶ Áó’"N™/hD(hèwâT¼7=ðv$bÀ<ƹ%߯©CxîáÓ(6øÃ„0ðΜî[bG¾tLB˜úßKçhÅajyô·ôOÃNgeå.9ùÈ7‚ ËöžòMœiò–C\ ´ì #âÌaO>ÀEœ¿ªJ£à8FÕ)3àKzâÅ':P·~#„83€K¥O6DŠ_‹¼"w»Èæ}—).ßbÔwT;ý܆Œ8!‡è¸sÇdZi#³8«ƒ™v:R÷iü†ø³B 4o­œ]|üñÓ ¸»ÿ²·°;ÓêM@ÛNsÕ}ë%¬z´³ª ±]õ Ü„+–‡üÃ(Íf»®mKWnmì»#~‹p$}H{ç;_Ř¹íþèýŒfÚ:xÔîÕ.½ô*NF¼¾Ý{ïÃ4L™ïþ•·©SN͈ø°á{ãÌ72gžÑI>ÒËBG;ÊB…."3zvѵ<ªsuÁzŠîi­ÔÁF•6ÒXC.u–|Iæ—ݘNÜ~×]Ä'8K' /’+N´«NÅŸAÌ6šk[A<ƒmÕÆSù”tʦME£~÷Ó™u 4ihÓ˜w ‚„ü`!Ÿk¡öäi?pÜ̶Ï̽ÚdÎ7˜>c2‹ä&sJì˜6ÀiʸëHXfìú*ÊÇØÁêtžÖ¶L-ZÆùË[Áý’vó´ûîŸGü&>î”´–O¿@y$8Ærþ„!ÔOÈK½åÛ¢­È¸•iFÎÏu*«ÓH²í¡úßSPŒš5ª;zP_ñwÄš§òeƒ< ­ÇÀA*yKn%CÌ{m.å8ÆàSáÖÔq<¿±p•_%Ô<’–™)3Þb ž;éˆ[¯O Ö@IDAT*ÙF8ýO?òmy/ ¼Wð˜Æ?ã Û1ˆ rD»”O1[0’¿âëMm£˜ð, :Ñ… :qËÉÀëo!‘rݦü‘.,‚dúàÑGMa0á¬öÂ>§½ó¢÷gšÝܹWpšøùmþ¼ 4¨fµÇ˜·/«~¥<ñ›»adœ³‘ô5•RúðÎG2N•æ[n¾·½üü×¶Ã;¤}èCvä·ÆO¬`ôß…åa,‹ÏU‰: ±ÌÇÁ•<'Ä)¬ñÑ ñ9¥8 ú:C¬•ͪ},aõö›4ÊÁ_ÐcpΞ1_½Ê=›Qõ —XIƒÎ Võ±”{ñ^>< wø×bÂ#éÒ¹#,õ øD¿¼ÊZüš÷¦Ë¥Ä¸ê'ñuB¿ÂC¢ÂþFö\‰?pæ_îüÖš”E¥é³¼j‹Otäe×_èö'M˜Ø®e”þλîÎbß#8¢½àyÏm¿÷}m<‹‚WÓx¿wÞüöìß8»zÒIí.¦ø¸#Ð’Gi¿ùÜóÚƒ-j³gîyþ+Xôëåâûx€mœl{OŸÞa-ÁyÏ~VûÜ¿„ï[žÎ„þjW^Ñ6Æ–º&úÇئÔ)–zÉFÏœ{»äÁumÍè mäè!érç0®“L §}¦Ò_;‡í|ßÇ?ùW˜ÓÿGñ†=Aµ z>žœÞ"¨ï|ýâÓ/Òëã~}|‡#ý÷ì ³sú'¥yR\q^…ª°î”C÷dE+]ÜúµT¾ëÏüE+9Sù_•EÏP•¿8:—¢ŠY²²!¼:ãrUÈõ6G\Yål !zțƫÿŸA¶‰÷¦£v(çXÜÉ«x˱’WáUC,zqê 5mPjo½c]z£â𼑨Lsù#|îý¿.¥F§Ï¿… FÑâ|KžÀ«–º8¾µ[ÂLJI± D”.ñE¨(b'ç©¶»„ÐêX"ÌpÓƒE}š^y¹ñ^}¦/, ‘?$\•C/>ÃGÀùJ>û‰,$Ôa÷¢õn’ðŠÚ­í9fhûÑõßä5ý§ÛÐÞøÆ ÛÚ•‹i¤ÄQýâT°2Ä^ÂcPÈ öŠÃæ×JH½ÛÄèy/š¾eòOšv8v£Ñ·ŽQÁ¼·ýÞïý)Óþª}‹NÀÙœ±ÍšÍku:„C‡ ã•=‹ëÊ |Íîà‰!f.åÊ›…NG¨qçv'ûÿqó vTm鮿³v`YDOfN.ѱæJ _zÂøÉalÀÕ› ðznþ§|šs¦ƒnµl{’IgÎz™Grƒ¨»<Æ&ão çŸ ŒIªå¯<„ÁØ©D_)é·Ÿ°XB“LÃVabï²å vîÒ!"L½‰Q9lСC´.ð_MÙ>Ì­BÏmþ¶×“—÷µ·¼ùÕÙpà-ú¶ÓýëpÎã­÷zÞÐóMhTÀ¯þ7ÿ‘(ŠÍÛ‡è>mÍ”4JïçüV»ŸÎäßýÝÅ¡·Š· ¢õ£è)OŠÏ%‡æ“aÚŒeI=¨‘´Štdâ«ò1¿À«³‡tÞZpbê"HÁÃ}v"ZXÁ¢(qC¼´’ŽçLÐi¾ÅyÄsßQQnÀ¬_~’/É_‚äÅh¾•Q ŒÞš´³®ãÞÇøõVÁa~—¸| ™+•|¨•Šë¿mP›Ç¾HÖÛB? hy󲯗—Ò›êGw]' ã¶Çø_þ«¦Ì÷å4Ø_ô‚ßä4û¡íÏ.º˜ÁŠÍíu£G³‹ÛX˜ÀÏÅ‹·»<Ô.<ê(ô Ûï¼émíì£oÏ9çìì tËç>ßÜ¿ ¨?›ÏœßrkæÌhïûà‡ÚçÿõŠöš—üN;oúŒØ˜Ó3U­²FùÿåÒÂРü”Nñý)›øÇ¨$nž¢{÷»óºxóF*×u[“lTG%¸ Ü‚™OF¥ð˜&ɪLæñlæ©T°æ[ã§»-x² Rä0Ò¸íÌ3–ÏÓ6¼^›ÕVÜ=f€Nد]ýTØo­NÀ·¾ËÜüÓ™ZÂv,"\ÃÂ`çr;<#½îX掭hsfïÓÎ{î4&G´Ë¾qGûÌgßJcr0rüÇ4æ³kl;ÿåïþ¶6{ÖSS†Æï5„‘îÁà5¬ ŒÏ§õ¶ädPH«Ö|RóI[1JÙ”“pM7å†0l+ Xà“Dh¤6œâ<êDzgòø)á ôÚe"‰n“{UŽ|6¼N‡a:ÓÁöÈ ˆÓGP/-_¾|ìo>²Œ‘·eLYÕÓI¸çÞ‡Ú5?|¬ øH£¿öᆅϓF±zx:CèTºþ 'cÏ6ЕUõ'[yŽ=£»x3Б_3!Õ…y.ôÏ­ù¨›á¥çz m&Ú“Êæ›>Èä„úãrÐ"Š$ãÅïy&Dåy áÏä¡*C¸—'Ù†­JIKÓ°j8r î„!ñ v¡IIÞ–fí6ë ¾4þMàIô¼€ª “–²À;ñŽof®¿[ßžxÂyíóŸû6Ÿ[ÚUW½§}ô£·ÿóAí¯ßóvÞÒC9¦ƒIçM=„òŸ_¹ÈtJÉ$Œ7@¬y™¸×èö£}é}›írßyч€8;¬¦l!\d®üépFóD-s‰T¹£/n­·È+ã’m&6ÄKÿÚ’ñØòº››O SR˜±…'Dd…ðÆ—Æ¶”Œ«S 4úNûŽ61…¾ìš>GφÕsâì˜Y·aãi+`¯â6Î?éz%W¹˜‚/xƒÞ<´BL§ͳ@Mo~TºbÞ ÂkhGÉÛò9ÉôbÂÕ™pá+ Uu¿ÑqbvÕþ´+Ï‹Øñ猧Ö.üÓ7‡çö_síul¥Ì,#F¶öÛ¿=ïé§3±°zÈÁí²~(ej$óù]h¾ë¼l[0/_Þödºä‚ Û1GÙþè•Ð~_5ƒÆÿ­·ÝÖæý|ö:1k"y‰¿k„$c]Äž·SÚ±ÙÃWZ—å1Ô‘A.ÂÑlu´òåk«4Ô¼·@vÆf$æÈ>FîÆ…×‰Iü6åRð #~çUq}E«ë´¼˜>¯³H•×Õ8Ðø7ô¬Ÿ¹å^Û”ç»&ß<×?N fÞrRò °X²i‹_ø‹3ÖaY¥aGÚ‚FUI'NÕYñoH÷Bßà0Ü÷,@Y1>$çʼ~î¯;¬ÔH‡ú#­ª°´É0‘“ÄõêO’$ãü<÷‹¤a£UãÚÔiÃÛ˜‘C³Ždõ_¦Ÿé„”]Ûn·‘¹•Wê¶Ì=X9¦ )½6£’̉XC g‚Ô›7\Õ¨#OÈ‹‚y`=h¿¯…åc íA[tT6îšh|-x‘rÊ¢‘«Ã«)z|e¨†dÚVìÇT¹—bÙœk„Ò°_p)ƒ,PŠ¢ÒØx"̲¡ÏeÙö&|™€¢åò-Šr/cªÏñ'ÒZ¸ªqÆ©¬ú\{å«Îos÷›Õ.¸àwYXyJ˜=Ž­<7fW!e,«-îÁ§E»•‡‘£†¶®`ÝÈIÙzôšk®Ç|–ùÜÏn«ØF7]ùˆª”G=qñ•i=†kû0šÎPjé>#PšAÀ¨§”¯P†²@W•‹èÇ·ÚTCŒ`’ñ&e#sõ¯¡¡¾°Íœ>­}ÿ?h³ØùÿߺâÊøçú/]º¬ýøæ[ØŠùÐØØ=÷ÞÇ"âj?g³Ü{ÿýís_ø"Û…„ˆÛI{E»íöŸ±áƸ’ýïj cS”mÖöØ`Ë5:õäwr¥!J]…òSYè˜T<2qàÁèFÐ5icøF™qiÈ›ã`6m*Dï‰ €C+Šùi„Ô@ÙØÊSZšˆ&)!ž¯a¤‘€—ŽGž2U®…\.ÔVqNJNœ‘˜W€‰LE“?e0‰…HÕ¯§ð–ɦЀWîÁØñë=§Á¢¤ç7£ÙÈeš!Z•G\ôA4IóIA£`ÒÎ"è){ôG¸b¬Üq~0Ò2_<ÞÝÞ´H8j0<U݉OՈϴ;dŠõ l•(a€§Â1J/Ò2ÐÜå—ÌËŽ02­=ó2æÊK%ì=Ô¿»)ìNže·§&ÉX¦ËÜwï Fø'·‹.|#sæïm¿ÿû/ÍÁU«Wn(ÙH—„0q„<„mDVÙ-d Á7üûe>:„ ëê;ÑFÊ£ô50õBÐ[™zrÒS¦3rûßùÕz/û+Û9çœÉº„£Û™gîßÞööO0òò`»ö‡·¶ç³8ùî»ïmïÿÀwXPx)»E4G°ÕßCÿàƒàµÿ‰È¶{óÕ¿~+o5ÂüißЯ…ðp#úžj Yʪ:/žÕ¬ÂÃqðWá"/0Úo”±gG)åØ)”â gs\T|âÈ!SDÉ“MAÑ¥’ÞsÔ§<êïÌG$ ué5oÕ Q¥i¤{Oœi¸òÆ_ÝPÒhÄ¥Œ*“¨aBÙ".|è+˧èÿ¥Ü×u&LpX'l5=÷2(û¹õ‹«Ï/v¤¯O}H¾z/p~H—ÎÁ¡îЀú‹3 0·Ày¥&Nh§Ž‡P$t³Ò³à}ÂøQ,úç$]`-;>Ê+¡_ÉE'’ n»ýŽv ëÔ™káÆ³#šüÜq×=íºojh¸`÷žo_õ]Þ px.#ÿvínà-€&¹†í²y…µ…5I#FŒhóy p xUÚhL`*¤6dgJÕíj Åog0¾FãFÏ–Zof‡ß„›)ÉLRTOÙu¶fw™«œÐÀõéŒÏ\2¡p4ò¼]U†h\b¸?ãu FŸ¸”•|¸Xº"æ«Uâ,CLjñ¬ÃÆÈL!Å´ã€M6„6¸«KláœòOóKÔ,_ÿ™&N9qT¦ÖÑ*QdPwöÕRð+Å4”‚§”o0Èü†'9€ ò„êA(o¥m!ôÚ¡¥"ió—Š ¯ˆá \Q?iœ8¡w¤“!)1*µ£Uð•Ý3Ÿ­Àlà„qšž°¾S§-¤aRãø”íérKò+˜¨ã™sã—÷¤É¨AžáC`>å (£ l^¹k&ƒ½ô$íåêí]À Lø…Ù¼ “Ò¸Ï{ä—@ÉwmG‡ÉBp9jgz„¯ŽŽ¦øFNù)¡»Ïà3OEde¼5*£xà3ß ­>û…v`ø»o ŠÆ³bÎH§kM[ñ¶æ».Ó*žùÌW1òqf𻨲֚h9`“\ÐáÖù¨É7xNå!_g7‹DÈéL™J_ÞÃoº†²Ë Žs»×XAßyDz6ƒ…¨û0µýô§—ÓÆt ‹iÝ×Þñö÷ÁËn9ívÍš5íê, ¡ÿ~âfzÏ(æø~ £åÇv¥‡§¬Y·1S‡úLPæäµ°–” ín”¯ì$ ÇR>Ôv²H«õG€6£ Ê™<7¯"d~“GÀø§ÀÚRæ=3Ú´†`þ€£|’Ù¬÷0•$Fž-GÜA.„•y"m'е,’.t…—e¾d P¨•mÅ`¤Ã³6¥œÆ¤,ig‚ çŸæIî@ž*W)‘g©¨DŠÍ…?±Š(‘ ¸mðgÃbÌõ;±lqw%e Ö­Ý^FqcŠa4 í$,fÝÁÂ…‹Y\¾ŒÆå2:#.‚þž \ÝàGhM€ÆXÖ¦Œh#˜^ä›4’ŽA(Û1àÓŸÍ’ìêòWÀtâCQ¢yÀO¾Ð_b]™J£U}Ÿ |á–R¼yoiõ·KN¤5E:¤±en–†¿Âw&Qvb^ð—7L¢"]l´Œ‚t1;Rɇ¼†h§=I½dðÙXƒl|€ºä!Tû$SÛzÞÀynÀñ'<»ýÍûÞ×n¿ý>¦ð¼‰»þ©ýÕ»ÿ¾}áóð¶¤M#ŸÁ6 Ñ•:LC<¾¹¹þ†‡Ú³žý2¶ú<º}ùË—2…ù‡íðCžÃi­ëSþ$§ *R|%¿áMµçŽSýf•åT»½~Àà‰‹ô z’/–“È"ˆŸò&søò9¥áá·3(=ÿô)Á >y1{-ÛúóŒB‘r%›ì'ØÞGp‡˜#M:5rC¼zÚbï;†¸çY[ nGç|Ü10š>“†ËºIØøñðÛ…ó#oêÀZA6ó•_ïI— ô®âsê¥ÓY‡“—“'k×]¿¸-øùÕD²æªíÛŽ9vFôo¤ÁÆE²«/uçf{àö(b<Ûˆ7ܑߨh×o;=¨¿äsiÒNïœÿõUœì ë úËÍ ¢ôê]~™N™¯zŒé’ƒ3]…ÿ4ô`ïµ®.ý§©Ú1ªC"S×4¹·_Æ Ró|Ükº^æ¡a1 ¾P`Qq,ðÜ/X3QäM}ç=¨õWü‰‹ÎôoàAæèˆ8õ¥ç ’tbÈÀ™MÚSì[œU¶!aáq~ 0€ Xÿ‚˜†„Äã? PökJž„‘¿øâù«|Š2pðãÛ„$1 ­"!*k…ˆxÎ+VÕ¨Æ"K¦‹(éÊ—²øÃz"NOÙˆ•’o‰”]ýKc‹>SÁÊ•£ëN’èS@t⛣ÓÆ2ï–Ñ4}§² :"ªÚìŽ@ŒÈ» ì÷¿ÿSAn&½*÷ënû3µhöìÉm``*Ÿé”…½¡Éö¦“ØÊo¶j½4ˆ]ñFÒIXÃÛ¤µ¸ïêð÷g 𼣈ÃéAC€)Fð½•^ŒÇ.›º†$zÅ@tÏj§¡jѼ%Dñ§M @-‡ª”À›VÔ.LE¢Ü VÿF›·É+°gÝUú#¼˜FS“žöâ³Ù{æ·Ëfò«J†üÅ'÷ô0^ІóÓ{9SÑ7% ~ý/t3;·1µjÕªM¬;:³}ûŠ»øœËndkï¼ðMLÿšÝæî;+ƒ½ë³¼¡œÍ Á–PµlSă§µ›Ú«_õžlÝø6{ÙjvÑÓ.3˜M5™¡©4D-;¶q¼*L¿žžKÿ¬öJªïÊ  ,†øFì×7%õ†±tkn‹Qïžzš¥#SÁ#ÊÏà@á7«®«YH×üæ¿|¼¸a€²* *Ú¶“¼ó#ç¡©þðᤵï.|ÿ4¾M t¤,v‡ôÛ®½2/Å«ÍE—„‹ƒo‘zÃ¿î¸æU6è }§“«_ëáVò6gá¼õmÓÖëXwv'¨_˜·¹óæ- ówë»îŒ~Òa„¸þª¿*ïàIãÝE׿m”]ÅéÉv":evg‘·ÑqýàÂÖNªñÙÎ^¯ªqì ‘DO|%ßÐÕŽ|"*wÿ»øÁCÕƒæ¹6ð¡>“Ç–uò&î„›¯¬~›éúÿè>g)ÓÉVöj<Æ)g-d‘¤(Á°â™ ŧ©Gžwsª qQ¬NŠˆŒx†"°]KM8™×Û<¬tSˆäÐâ_ómš¤2¶Ó±…Q~À“x«#°t 0øe˜¼YdT 5Ÿm8 ïÊnBú¾¢ƒU6ÄeˆÆæ­¸QAHù Kú$6ctBé$땪òx>Ðyïw¦¨K€ww¤ÙÈ<£`Óðít”‘Oaàɯ_^…7ôyŠ®IW,)Zó´HIgêºäIÎùãvwÓ„˜¶¨®¾t´üÉ€èЕrd«q‘Q!5ЂáŽt¦¿<ô޹FÌÍ'¬Ø Hã¥òR…TÔvtjVZ¦×‚?z7¼Ë·ùjÃ-ô\YD©¸b×ò£ •¹hÀ2TúWH V*ukssÑ0Yé¼òd…B-š¿i¸©“„\é36M`UÜàDVÓHÓ2'™ 2<Ãt%u‚ªAFà ûߓþ®¹æ«ÄóaFÌl^ø~vq¹“ý¹`[2wü)›KBD.yÇ™›ÓL˜üdžÑK‘†?Šž ³E®`Ú;²Œ–QO;³·ÜÊ6›ì3?s`Ÿ¶ÿ“Û{Ñ©íòËnl¯úÃsÛYgŸÁiß`^åºvÏ=÷±#êvùåßf¡àâö•¯¾Ÿƒƒ®h¾óÛ³Î=¹ý/_Õæ°°×<¤Gã°Ê²ÏÒ—?ó6v¢¿AQæ•Á^Jaˆy’’IÿìPlÃÊC¥ú8s°:`H 8·Æ’/èWtéœTµhGÒ+;€Jg•¦x&:ëäЖ‘ä±8 éÖCjñÝ+gdI&Ä b]į<ñ˜|êBQ2BKl"V/9gœ¼¸„ïüÖ_æ}dá¹ìx•êÇKñüÒV„ÉSÙñ^„àJgdwI$QÆ\üXö"·¨øD÷áÇ2Vä¬GÌZÏD`¾Pê™^Ö!6¦†qŽ€oÆßãƒL\iÔ@l=;H­fzØ¿ýÛ}<ÙAàýŽËѽIí˜#æ´™©Ecǰé¤ñœU0œãØÍh/v0bñ3L­çÓ»/Âv±Y˜¼›ÜÀ[„•íç?ˆ7ì^´`1k\Ü­j>µ/§ä³G›2ÍÑE:´fÝqË2ËÊ4Oüùä®8Úû†û&@º!«ŠŠfch¤ì_•dg^}ÆžÉEuGÒ¤œhšDƒ:î¬|„듯&ÐÿÕ?AÕù0?©ªSë¤~Òíz3à±<šœ?~å)™ ¬8,nšÃ ÖsÜÞœ²Wæñë£.¸àÅè| ÛÐþ¨]ô®¿€Âì4^²Ä&pnÈÕ×ÜÚ^ÿº·³~`N»è¢¿æt8„| =€-<Ñ`”sàŠ…J_¹øuq´QõS^ys¤¨$&̲;×ֈ˔ȧíô» nÒ«c£QÖ-÷Ä[¯%C,# S?ò(\¦›`ú‰‹t(+~ú¦OCOøà–Yo WÏ!žg¿Ìë[‹Žù¡Ȇ'!,å>µéa™pË”Y–ÒÅßðd'VRõÜ5ò ¯ç±9Y~þÏWµU+\{ã›:ŽÿÔöÜß<œœçµÓO?…í™÷Ëg;¾ýÃ?|œÁŸkÚI§‚Vߤ/Dùòi[f+o‹×SÆÿ?{ÁfòD|OØÃ/Á"pí|oØÎÏ¿ìþÉpÝsò—ûÈMñï/gMx0ÙМýdŽüâ¥í« §ý²K9ÝMá4¤zãª?ÐfÊnYP¾c”+¹Oˆ`儹‰a”A§² Ó5ú‡zeN gÕ ÓcÈ‘°eT5GœK¸Kî:=-ÔK|–€L˜PÀ(ˆN!ä7•¸½Ìg8Œñ;®l½|)”ÀÕüÞ –zâE¹Â»äÁ%¡\ +Ï6¾Á‹ßUà( åðp솀°û£¼H"°8ZøD^q¾I¤D¥AL“¼N"•½8ù„%ÂÒ¶ŸzQ×ŬŽAÍ”nô-Ä=KUùàÅ-6t¤^*?” 20è®KÑmG—17Rp…ºÍJ«Nü®p•_q.¡TÁÚ›¼*9©TÈ'Ž([\k…“ðÊœðZ•ŠÊ1̼†Ò‹[Ê2a”±E#7à‹öy´“‚+nG-x«t’‘zr1œyÉLÌŒûDM‘ð‘Ÿ]:¸¾ãH.Qvld)?‰/©zºVö¢•+õ)O¥+d—/þÍqá’Ÿ6.Àc~ªMC)äaâÄÑ4þ¯môš?kÏÞ³Ú%ŸùSmÞßN9ùyl˹!¯âµ‡‚¯tñ•¯ðfZšÕ©³ÎÔ6â´.7Ýôsöç²0ÔET·‘p; Mi/{Ù‰LçØ·}ðƒ_k/}ÉyíÈ#gßäG8q÷œúöáŸß®»v!üü-¯‰Ol'Ÿt2;0Ìk¯{íEí]¿¡]véG3çò{ßûqûñu Û\¦†ø*ÕŠAÉc«ªI… &+aYF3‘'Q¼ é+;GNÕì'‰É,CŽŒcM™Òjá%¼J.¸:ý—MB:ò0|Ð…*Ê—|¿ü`¨È·xäÔr(âœ>÷‚qÚÐLÒ×'$?:ŒÉ³ NŸ‘VâÕI°—AEêàãF±² xW„NÐø`µIê ž+]„¡7ßÿŸßõ‹T3µôÕòßRHxWˆs£ ò’ú†`5펹Wµú^õ Fð® „åßóÌ×:dÐÌ÷Õ½ ˆSŸF˜©Î{,ƒ{ì1œåѤŸ‚í²}aŽÎo泉·K^ÝnºõjÒ.äãÛƒ)‹“g͜Ä),Hž˜7{ï=|c™R4Š•g´à”i¶;†õ (qÙ²¼QØ þͬ9XœS”W²Hùᇗ²Ÿø"°;½h Ï?°“0‰¤ C†ámÖìQm »ba§ ;¥³`™v­Ä¶ru”QÞ14B}D¥¼¾•M™Vf]ƒêÝÌF766Ôk <„Ö‰’g¯ â%ÀŒ ¼%—0wÄ!AÓd5ø¹'.uyfþT9‚8—ùŸÁ’&[ ƒOÃùa`S0làÀi¾?Ë‚`ÓpÂ1íò§í½óÅvì1sy»Ã^R¬ºúšÊ›¿äL¼ƒ·†`áøs耱…pÞÊAшð¶)ú‹A <§ZÙVòOågå±Êe¦RÁ¯h,áéÐF0žI ~Sîˆ,(ùUߥ{é“2$i$QxÊ}ÿL´œ¦m$ë䫃˜ñ¤·ü¤Ëtp 'ÄÕ³>$ÄH€lÊ8€@w%½ôX0d®Yž2+!x‘…ç´©Ëõ/ÃFÒÑfÀg8óÞU†sâ½lxúÆíæŸ<ÒN?cN;ü°ÓyÛ6‡·m.Ú—yò©V­ZÍgMXøÈG>ÉK˜4;¦®¥àkß ¡çðáÃÛÑGÖî›7/ÏžÜÛ_åëêI±Í¯è’_íÝ7GÚ5š)9;ÇlåáÂFVîŸÐNT™gáÃ[/=¯'Ãîfš5kŽæô§áŒK<ᦟ¿âr Ñô´†±^½Lú¯!È=fÜâ×þ‚|ÂDàÜÌ6¦{OŸ]ßsÿm 2—FþÍC  }hÇųþ:{É3 ˆ6~­¢\€Sᘎx•§ýee™¥ È€øeÎK0îm@x•þ-²ÑLàâÈOel02˜gÉk’y/¶hgÿ;ž1Låæ>׎›|Lc|ªMg¡ ç/ùND4aõé eT¢*½rã_*ÄÐ4\$"5{àÇ 8x£èÐÞ‚[r¾¹tc´þrY™¦! Óvý7OSV +†Þ¤’‘)ù„ó\ë;·*­ç+z•(:nƒ7Žùk®YÐN;ýií_sóëÛÛþüõ©,—¯X½Gà1½Ü*·eSKËV ÜçÒ~ùÓªu$Ciø?Nãছ.g~þ{ÚK^òBæóþc;ùä#Û!‡Ø^óêµ3Î8© °kË¥—^ݾòåo3-ãjFû¶ŸÝ¾”—µ}çÎeû¿É4þÏËÔ‹5k6µcŽÞ»}ÿêET6ƒ³­Ÿ´Ï:û¤öÝï^ÉB¬Sè8°E¨«í»«|0?)6ÖãðW—士8#ŸªDFt?¼ib9Q³x«CÏ#6(u‚ÄÜ&/ùŽ¡H Œ—½›Ïâ›6ÓA^åžd¶Æ|CJt¦ïh+¤ZêÖ´ò{×ÀŇ™#yûhý‚0’ e‚ µ䋟09áÚ‹¼§A¡Ý¿ð¦…éˆI¸ø.zÒapoy3•oÒ9‘—¡‡vlG(½Äw´ô£kS¦ñ v"ã ¯={¥ñhBÃ`¨ôÈ]ð[Œ¥ ;Ê'ÃЖ<ôL­I/1•_ĆŸZŒZ¶!ÞMÛXwÀBIG;€òc•3yúè6c`O:sòD‘,©\Wq†Ä•W.€‚olø¸hØÄî,4¤M;¹yì´6köÞLÌvœZ4köƒC™Z4š¯{ÞoÍ´¹eË–³«ÈcÙÁèÑG—±×ø#íÎDxhÑRÎËx ¼·ðñ׌r»SÒ¤6gß1TðÙg<4 Õ“znajs·Q6ÓHŒ=¡lTý¥ÃDC?y¡î@ixùÖÊ ßÒ–?@ÅÑ»ÚåŠ]«RêÀÎf®èóƒHë‚–÷¦2Ê[îãÃxH^’œ#ÞÚ:uB_a>ÿ¦dÍ;‡i=‡ùYlS[WàŽŸÍÚ€)L!¼ ùöîwŒ­OCL“•¨Äø‰ÝÇL b¹Ðfà16L»ùž²šòv Ö’bƒ– n­Ï´ªÀñ\­Š’ÕâoýR²šÖ$%' gù€§Öæ|Ž;ªoãëéùSÏd(Ý7Òá%gÊ‚72,Á–G1Ž/×0ùÆ=í8iÀÛAìŸ4wß{?z› ùìdX´xI;ã©§phÞ‘í“—|6!GðM¯>¼ä‘vîÙOoí¿ûÈÇ>ɴ‘)'ž)ߌ|¯]·Ž]ˆÆòýxüÈCdëÛfzO¹ÌJ%}®a×ÒĨ4¢ú݆ˆˆ);BëlTŠH Ëǯ ªtS ™iPhAÜÇ鯩t—zƒH9cý ÿJ‡mHWäX )0AIA!}ê ¸e€RVàÜÅè H!âtDßL.IĤD  勒 8O ™«6à9 ìþ7Ò…±ÂW†9)–!qUøL¦«* ±¨½¤Qœz_=áê à4ö‘[Ÿ“m¢äC•hd‰•<:,„€(Gé%•L>›lQw>ªSâk,Oph\ÅB8Å%©„íÒ¹Í\2l½Ó ‚sFÅ™JÑ|¶âÁìH%.«B‚Ša|p A‘yÓæCð>?´*Ò@ Õcò)鸇VäFèLí›F×ñŸQ]ùô£Îùã§tãRJž±›m8Î(Íg€´«Ýèøá6¬ &+\õ×竎!ö¯ýo0‚T;M£>=KQ¨5pó••|úTÜÄédä§l“;Îcð²ó`%?ŠÆÁ‚ù6´·µ÷ÿÍ[™š°S8_Àüùg±×¶øŸ4ø±?pD@Ù èÖ<*GYˆñ,êÊÇqÛÖþéŸ.i/}éË«ËýÙÎÏQ÷rØgö7ïýTÖP‡°£Âb¶÷ÛÆkà=Ú‘‡O`.ÿÔŒÌ8o{ ¬¼†ñFaÙÒuí¬³fµùóи™FÀ)'ý½8„ª^‘*;mµj†oîá+ö®Rø zTûe©0NωÃöÍc‚2òNƒÇ2 2¥†{Ѻ‹†¿É/“^U¶ù+"U^Yž =€Gþæ–¯øƒR£Oi!Ïá14M_ù'nIš?¡"#uÇ·´}æ‡øä¡ÏÀh‹F¦»Ãétö‚.4"1“h‡_IÊFG0©¡Ÿ©&ŒWÙdY¼„gÒÂWÒS6£.*…¿ÊËlÁàØµ6L¤§Îgä\€È/.•ÃíøÚ€-'\Nzí‘'ð¢ÏL%Êmé“ôÈk&¼IùHá“ ÃG^Ü >2'^É7‰À×3:LMÞ¢¿Š7*·ýÔ·SÚ³¶8»|ÊQ40ÏÌŽ[ÓmžJãÚFµëÊfsF‹Sàî¹çþv-S´®¼ênÒ8ÕΩoSs(ã‡Og×·wó¼­§ŸË”¼õip'ß°Cßj fÌ‚µ¿èY ûÏÿT¶^Gw dæ:-h‹ùDZ€×·….ZLyT[è Ó§Mió<ÔN<îØv ð¯_öoÔIL5c±ÿjFчÆ¢Þ ”±U)WcØýg- wüqg ;¾°‘í6ËúÞ`LcÍòzh¡aåÙÁÂ¥œòë›ú[I·ðá%íe/þmÎ+¹·}몫ÛáìT÷õ°íš÷â9cZÞLgÛÑ Ö·¯}ç‡í´cÏ´Bw#ò$ôõë7°öiZêKO&v›å‡×Ý…|»1’· 9K¾ù?óô§µÃ=¸]þí+Ùö›ó7vaÅ÷Ž_ËÐ(43žæA<Ðü÷¿oÊ`¶Qr쇯z²R œ©M[†i«ÜTĉׯ—Ï¥¦påÁ“4$­‘òr<¦”»‚9Jhœ†eJ¾ ’‡|†Z*­È#x;‘(\¦ÀoA·g§lÌÉ£¡ ÎÅ)‰K=`Lq–òY2Va6ºè­J^‡ZsðL+sè„ðR>Ï\a“†mJõÊÏJY‡€©ÃTjÝÈ™T¥¥S“ÿÒHÎ1¾\ vôÏ`Ïȸ$$­â0z+øäX¥-ÖTüÕU©{06ÌË«ºã~äHÞø' yU‚:TŽ$…A:ÒŸ¯·+@'ÁŒF׿[¥Mç"Ñ⯰6%fè„F€8¢åõ$?ÄÎ…ÎC*+nrÚ¬ÀÚSlSHi–D“ÿ‚pë•7?ü– Vº¬©¤IWeÉê“uÒá4OíÔèZQ.yl™<ù…ÎúÆSæÊK\bÕÈq:Žxöå„âg³åãDÞ ìÇ)‹ë2âY=ù1o};Gjô©>Ô‹r“…äeûÊIT’ðe¤-fÞA Ò`‰¿áY-Û1ÒV®z(åŽ8vÜbmDk ’µ]¡½ô'‘ž‚^šà±œT>’&q¦%¦”Ãr’a–0}Þ6uD\Éâ Ü$]ýO^桞®FØ 7?Í=?‚ ó%²ŠÔpþô3–-e ~ÒÂ@ÆבIQÓ&áD‘ßøÈD¸IV'†I;ë Bi”¬Þ .hˆˆÿ𫇬”ò .Ä*&Óɧr•ýFwÚñé¬@»AZø’9!£(ÏÁ$6žKw©lLªƒÐ…]fÏØì}YÌÔ ¹1Ùw¹b¤t,‡×Íâ ‚ ° ¾ì~Ôÿdï=öªª|ïÒ{#=! B ¡÷Žt±·Q§8:Ÿ£sïèØgœù¦}ã8–¹Žut@•é½H'@¤‘é’@îï÷ßç¼ ¨3¢#/ß½9ïû<Ï9{¯½öÚk¯µöÚõÀû ›¡{®Üzû²úJ7?ÁÇ=2^£ù .{î5±ì½ç^6:Ç :(o¶€“3„†|(ÏíÚißzì,Â’ÅË2ò·þ™uì;X\æÏ[T.XV{dEydÖlàçðñǧ¾ÿ`ܘ^jç vºõê›y烹_9èàá8>è(§uÉG9íHt(?#4òŠ{ä»Ê²\¨|UŽ#gí¯‚²QÖk•@Qhù=ø|OÇБÌÀL>6K³V®Z_å¨ÖA,ƒêE¼Ë±Ø7N~•rć”ÓO?¦Üvóœ2f\ÿl·!—ïÑ'4v Xm¶TZ%ªùüþ~€mLŽWxÈ/¢–8é&e%>›‡0ö~•á ø“˜W¬H`@[ÛàkY]XåÈrW<¦NC¤M½xå´gé2)ï2‹C”¸øntBõdÍ<ö0y‡çX:`à…¯Hgwü ¯t&Õbä„-:¯ ¯g6J‡ŸåtDä°ˆ©œœõ–2}\£qªu:u€×rìå܇9Jzê>{”»î¾·œ|Òq¤ófÐÞ£³×æ°3ʱ¹jß}GAû–ààr¶î=+/M×Zñôʲï>{³Œh¯òÝï}?{;tÆuˆßpÖks°t_ý³kÊÝ÷ÞŸöîŒS^C›³;2Ý“ea÷—ó/¼¤œpôáåˆÃËHû‡TV³©_˜ÆŽÍÌÀ—¿úu¥WÞó®·Ç¶3pÁÅ—”%ìéÎÌÁ¾ûLÓï ÀFQ.\T~páÅe eßoßiü®åÈêùqø½?xÿyIálÂÔ­÷¼ý-t”v¦ƒ³¹ì¹ëÎéԼᵧq’Ý.ð§_:—]~e:ŽÜ¯æ¥a_ú›O¤Ã"-^|)ЧÒáñê>öXYNÇcôèQå½ïz§MÄl,W_s]ù9|ð$£y/È2¡'O.ë7\Z†Ðã×<Ë/XëQõ&7GÇä§—pxKb!„•‚ö;ÃZ2 ƒõDœ‚ A¨e©é’V|R ÄeÝU¬üÖÔ±æÎ@IDATüòÌ­ä„wÄÈÍÚq«ÐÙ“Ðð)»h’Þü­¥Ðc¾š,óOxo( æ˜:„vù’ͪ¬;•¦«õD¸¨p<..4åÙ{€¸Ò€‰¤üƒö8 àQ’§õAþN‡Âu»q†”wèô!4ƒà“æ€ENLÁŽéx3^þ(õ¦‹dР8Zúªt•-Zsê&2 Ž”—¯˜m)ýŽhzЉ¥.¨ó€Î8(ótµ­›t”©Òj½5÷„è”H™H-U:KA ýd¢MÎQÁ!Jþ“V6´X ʤŒ‡È^+Â?iSÞ67ˆ í°š’0'+,“Ÿ¯ZZé†êŒéA˜ú£E8íΉϜì‰d9©añ_M®4ðhýƒ*øHcûaÇ´®§¬¼Y8ز»× ?Ëuú³I¾ëq¢& ÷Ú,öÐQöD«•Œ†ž÷ý;Hµ„Ï>\‡lbÙiÜ$Þ”=”‘P–4ŒŽ^»ÿ` YôzK‹8wϽâ ÷¢#òÔS«è(p–>Nß“,)Z¾ƒ§q¬sÌ霹¼gáæàu”})Ÿ^,Çø8Gó>ÊKù>W&O<|=sª—ú¢Ž¨—’Óݽ Lri¥K¸eU÷”‡pPæBzãf½å’wÄÃP¤—,ªîZÔ#¡upÀ7A÷îÓ={º÷0íJfaØÜÍ5oÞ墋.g©Ã“eäX^:îúCù^ó!k°ùÅ7Ÿ…«u‡dh×Vë=$CPK¦ƒ:ÒhIÄaùb j"‘ó¬p$šGt|Ê–¸b“RGhtƒ_|¤×¨ç¡•4‚Ÿ½uy¯ÞŒDÉjäË#fsI¤ù˜œuÿ^Å›P«+ÑMäÞ‘i;©ét/^²ŽY%—°=ÍGœƒÊ‘Gî^¦ís8G3³×eòøl|ïÕ«g:š:§=6—NæBŽk}¤Üsß‚2oΕåu¯ûýòzÞÑâ¡nn?îØ“2‹´¯£àkÖn€tj_9½à4—ÅT–´yÚ¶ °ŒeqòG¿‡ûš›n-“YF:røðòæ7¾>2|íu×Ó9Ø»œròkÊ­wÜ]Î<í¸<ßrË­ÈÇŽå裎¤|K˜XœÑòysç±çæ‘rò‰'ðÆù˜¡x”ËÝ,©™R^ÿº×R¦ÇYvz}9ð€±kùŸÿtÙyÒ„rúi§Â£EìU{¨,×qÇÎÏIg¼·üþ»ßÉšûçp¼H'a* ãÏ;ÿ‡,áÙœ˼‰eH³ÈÛ‚Nû¸±cX6{üØìáèéÓå›ß=Ÿ}E#‹¬»yÁ˜´X†w¼õÍåcŸùkÏÆf¶a>oÁ‹È~ïíoeÐí¹r͵×ÒYØ­œ~ÊÉœ°Ç;Nà›ob·Ãa#u}É€2¢ Î&`™mÉ|+BñEœ¢Œ„ŸÑ±x!°Æ[uÈ]·ŽÜX±*¾@V"q¤_&ê}VÐÅ!¨¿UD¤xøG¸BÛ(T””Ðæ_ʈ0p™Ê1°m i°JŸQZ M@m “§``”=ñù®°idJi5H.‹—ŽaÕ!pD®RªÔYNîÓ‘§eѬÞNœ(-O»ÿ€ÇŽKÜÁÅFÓüH“´á¥“•æSi©Ù’?ddpë*K«Vã¤/,L4æußb³¬3ðz&w}æ‰üjÉý­8¼Ëe´iL ¯2 ˜$"i…—6½LÉÍ»à?àä–Ë©§,m‘ïü% ¸k}’ËÞøº1£ÇâÈ:Ô©hG2R?ö¸ì d®¼Ê©¥lë8r”<Á¼£vµÌ €®Öá±D¡:ÀÀø‚œª 'IäßLƒÝë˲qg~YºdÞE•.V0ÆaJG• CSçÂú‘ÇÚ0dM>aa²e_Åâ™WbChd¿ àm¹«Êþåkœ›~1gêÎÒ8•Ç‘…&¿4DqžšN£§•˜.L™v+½û²9oèy×/®æÈ½eK×ó6ÅEå‚ ¯€Š¡l°Ü)k#ßÖ!]M•-ЖÍôðÜpÅЃžÎÂ~ö Y<©Ö¥ñŸ¶ÏxF$7sŒ(Ç1’ÎòBTôˆG ®ø„LËaÇÖãç”ïI@jª#é[`°’T¹4?út¨S^r ™ùî­<…Ô”AýU·¬a0%P©mĪ÷ ˆ•¶,ÇóÞJ;XM9–.B-—²¡ã,u:–‹[`=®×–r˜{(S÷¸må-XÓ±$/;'——ܶޏ£·nކO:­®#÷¥<ÊWª¢à6]f:B¬”zA³ÄÖTºL¼BÄ•AdÅ’¦vÔˆ‹o` Íehé…?–)ELZe0€MvÐ@þšòëœZ¿a±¦äuv­Ö[åWù"/27…|U~šÌ’eÛyôÁ6Ìø&·ZNÓH/¤¸H¬ä&aA+µ²Æš„ä§Ä¸TÈ®–Ð,BÞc£ˆS']:|XFû³'fÙ2š‹£¤mÙÈ~…Õ«7–ë¯[ÌhêR»´ÈŽâÞ|àPŒáøÌÑ,ÇZò¢¢Ñ£‡ãX £ƒ0† ™»0B8çúYœ—ÒuÍ2;vN;íDœ›®eï©»–o}sfœßÝá&c/g ×3ƒ±‘Ò–±ilw-gì›BÞ(J<+Ûäy4¥'\ñOmÔø—©Ö:ê3uà ßòÖZz,ëÌ™W•}èŸpH¯bÓãQðx KpÀSë¶ÅY%ƒz±¶ÅzñœüT¯Ù*³DêÐåàM:syKÅ=‚&m‹m’öÑzÖYôàW¯Éÿy+•OÂÖ«Ú)àåG“©ú&O²ô-…¨¹Ê RY”EOIc[g›$™æ?y¸á½+õë‹ÒÌ@Y›?5â<ç3šÎäÔò¶·Â~­)8¥£™u þ¾YŸâMë¾YÙµû·ßöKÛ<9K™«³Hûìãfõƒ˜A9ä­åÝTV­á¸O:³Ñ—IÁøIaå‹€®øXÂÛAܧè¤Nß{,)úÑ–AŒŒ{4¯K\~~Ͻåÿ/eÙc‹ËG?þ¾rÖkÏÌYüÓ§M+³gÏ.xÿ£Ë—ÿþ£,y63 K—.+—μ¼üð¼sËŸüñÑ^-+ïü£–ÑèÅ—?÷ÌÜWÞñçŸ){Uxè‘òá~ ì_úõéSœEøÈŸ}¨L™<‘¯þ,í‘·§¿íÍgÃåÃñ©µ=ŠeLý©¿(Svž\œõXðÙás6ÅÙö*ƒ Ñúïð¿½N`U#å;4ñ‚Óeµ^¬ë²V"éɈãb KEfX s­ìÖ ×øä©ŽYÙV¸ÍÃä5E•ëæ©ÍײÆ&òV!„G±(Ëažˬ³IµXÁà a-pÁqä-kïå«™ò‰“0Ó°¡1HÍüÞ§}¦¾i c”#U11ü5ߌjRA)—ÄGEyGÝ|ÁmR/n%C§uäè3é‰nêÒ‘³ìÔ7ôÅQ!/Ïz_ÍÑ Œ:÷â¨?GÍÌZ<©zosÉÒó§U©„Ôœ¸oè14¼ÎÁâ¬õTÒ&qoxÛä±µpæä¥|68ÚrÉw) ™*@…–vá½L©ó˜òÏ]“qM°—|Õ$©b3¯ú$߯ó’¢}ú•aœóô±Ç¦ÑïϺÙ@šümyÞ„ÎZyŸ0༳¾uæÏYÅúÅeÈð>p‹‘xœÆwRºì0Š‘"^ÖÄTrÎ9 ‘®OÄŒ,Ûý {:O2Y¼d-ç¥÷)ã ×eQ¡ƒ«à°ûy´(3ß–Qº¼¤0åð±²!á¹L++Ömåwà%¯­nËn"â ÐâÊ/È“ œ?IcPETåmk¦Ü$¡¨Ag|‡£|m&æoÙÁ¬ÀÍ7<´Ï¹7¦Æûø­d‰okÚ­8¼UÎLed /\ò‘µeì¸̲¹_Àhp{2S›ùµƒ‚!CÆ•µlD“LŸÍŸ+Óâð;¦˜_zxṡrLè¦x$ª°iOˆ Þx\ÜËßä[¹$ΰ\ ­–ßu×Õv5´@ƒµ‘äÊ0µr‚A«U;r‹áþøè¥È ?\íhZå|‰ëµÅWm0x=vµÍ¾Únó·ÔÐC¸õæ{D줚çM›7AÏ ,é‘§nN¬íR<Ü!Cº³, UV„ÇdŒÎ±‡†97<Ιó$GgÎ'5æy|¼vç”"¾8zŒ4Ž•}}ûö§óç õvMGAÈ÷¿ÿ=8Ê»ßýå2c?:Ðú<—E¯+ÃG³üfbœ KZ¯6ù¦51ü´q¹áÙ2×Z¶Æ·òäSM)D‘ÀúdÊa£â}×–O}ê[eï}†•ãO8‹cX=¶fÙ¡¾êe÷ÍO7Ï•ë¬ÊUòn~›äD5ôˆ†/e¡Þð  °ÒH¸ujŠúí]+ qþ5¡É3÷ ò‹xøIi|"òVÙY¼`Ÿ5Ù¨Þ‹uà–[xH;omîQ·<¸ªlØ|/±ž2µ oWžV~ï÷ŽaIÊ„2‡ß“y\«®“¨ÃÿÄ ËìÇæ•Ûn½¿\~…k÷oç3–ÏŽeâø¡,ó™˜Nc·´ÑÈ'‡@¸Þ£)¥Ý?;¤±.C¦¥Yù¶Jda-úÃXõÁy‘ždCü‰ÇÍr°çó&^ÿtmÿ=¼U÷ðC*ßþâ?Æ6Lž8‘Qõ5åzfΘ?Ÿ™‹}²$h>£ù^zyy|Ñ“åm¯?“€žŒŽ/-§õFŽîž„Ÿ•'fÝS>óßɨú7¾}nyÃ1‡¦ããÚzGõÍoô¨QœÒuo¹üšËq‡\F±ÇÁÍÁ®ÇÇi<‹/)“'Mʲ¢7“3,?¸àbÖê¤,¾dc™0aBœþÝé\¸lè!Þ,|Ö™g”w²/ÀM¾ñ?—%NÓ§Nå„KÊ÷ta9tß©Á¥ãægmÂØ1c8&{eäfï½öJÇâ/?þçìèO»¤Œ+9]̶¥7eìN½lÙ²tLà:üÒ·Bvav7+C£Ø:Xé-PöîW³Ëþ¦nb7bÜ™pM™¯”wóŒuÕã”'§N»p,)˸¨P ŸaË R<ßMCF~ÁçI—Ñ%zºö U*´øŸ6Œ6*ôœóGœJ%VàºÚ;ë;´1¨ŒFáÉnlbÝ„ ÒNËB88¯ “tn±CD¼S…Šké†!Sñ(‡Î«Œr*·´n‚w³σ{Òn—k3i-S7âž%ÝÖ¯9Ý›99ª í,—›jîP¯âÀ8ÔL=º^•ì(àëÏTçÀÁLyöfŠ˜%*‰ÓÉFRÊd%ro¹ ©?ÁŸQEa¡Óó²£­­Êg}H… Òã¦É²©’qvÄÇU@e#dKºxHýMKǼãâV~;c¤É&3T†Â{òlRå‚ìnšð^„òxiHÄM½9²³téš2e×Áå$Ž×ÊܺmÉ0ùöë—sà¤Se¾uk'.Rç—õ¹á´F9žfYÁìGŸ(÷ß˺Ü!ýãึ9î€ÂÀU§‚©]e€zt­|–u´ò ¾My{³=õÌ}hFfC—¢³ýzå9°†cù-ZV~~Ç*^^•Í’Ô¶k3ÍÚÕFkC”§Øgm$•œŽ:ºÃ¶+^8Dñc7‚;¦ ]ëˆkÏ43q’›´1 ‚VŽÔùÚ¨2­ñ4§ŒóùìÄÇÃ>X>ûÙÿÁR¡¥å–[î(÷Ü;+›õ7ÛÞÑÁpÏÁ‘ÇOdiȤҥFv›Ô¯ôeÞ§qDøõ[ÙµWšðÿ†üÔÓÅèéwÌ¥>Ÿcľgf‘V,çE[¼‡¥¾{o}?²œrúî¼iùe"£Ù£G`6Õ“cºñ¢4F÷YvrÇ?Ï’žë®¹¯Ü{¿{Ræð_†šˆ3=‚µû¯O{ì¦øÌ(#v6ŸÃ VM{÷AqªÔò«´+qú ʸBl' R­¶(†È2_~Õ+m φÐzÕé×ÌìÕRX—´¸Ì­'ëúßÃò¯Ç¢ÌÃáÏ[åqÖ³Ôå«ßüN9 '}çɓʌéÓ³6þ]ïÿ³Ì"ø&ù[ïy¨¼î”ãÓ6¹T¦ŒÙ={V¬àýàðˆÐY,o:õÄcé–ûw½cKî-£˜ypìžYsËûÿà=ðo GY?]±ï?=§÷ÜvÛíå¾YsÊ~Sw϶!̶õ‡¶9³ç”‡8ÙëOþðÝeÏÝÙ<·.G²Ã`çÛ5ûGymëÓÌž¬g¹ÏNCü`yëÙgd-ÿ·ÞUN=é58ôËËäI3àÞó¶^ܬ,ÏæÎ"Ë<ñȃn¸‘ÍÁ=S+ÖCì…¶¢NŸÂÉøZ8±L¯¯gÍÝèQ}ËþN(½zwaª& · ·½¨®T»a/½oásÖÄW!¨qõÞtíÕâßfê*NÂÔ'ï€à_£(ì¶yûâkÛØ*1ôýËÓKÅKâTð턹îq.oF]<méÇi=¨<‰Œ¢ ¨UñyÌè‘y&&MB¡î‘lkfÂ&­ÍŒÊç³$0¹çÆ@ 3§„ &G’¼(sðŽß Q9Ì0#Yê½ÚäR,œŠ¿¦ Èä›6°à†€Xó¹ çÿÃ8>oÆ­W~¶_/—xÜ¿åå¦&0´10ðáró ³Ë`:Õ)£©3÷fdã½u¤¦Ú«ÌY³þ{ÚÄÚÕHÛ³}ÜAegª ¦¹ý긮|Sâ#F )W^~W6öf4Lû»B Ź…¼T:ݶÊÔc¼e»˜˜1!ÐgjTy@±ÕW7ïf@XÍE5ÊN@Òl¢ìD$â 0 íFz“džh0Àx: É£±2±8DÇáÚç´y-|Jdv¤NXRGí¼8*fJnæÀ8⛥9¤±õG·ÝßêÌ4gÖ4ÂPÖJ«6ÚN#Rð´tVBqµ áhî£K†{ADôHüŽeÙò§ËŸ~è/ËEzbËl>»s<ï0ŠÊˆ'˃N8ia&¦¬µn:ˆxÅo›ȇYÿöví/Ào‘a«§ÃÔÓ™w²ÔfSÞº;yʰrÆ™ñr­‹ÿ`6ËzT¤ƒ6ž$5gö|:‹Ê½÷7éòÖ刪zš ²°É?š_ÓÆ!H¸ £,e‹4zéœÔÆGü#qüç ùT9l÷’9»c¼kׯÝXÆîÔ¯ì5u—È¥§¿ýê,Ø0;FG`OêdñbÎ,Ÿ·†©äP%Iy´m°½·‚¡g(bÙAæx¶‘™qÀÞlÞ1g:w¶SÑY}5å«ÞŽæí«ºk™yñ½¥÷(:Î`bÜW î¥ÑQÿ¢¸Zß~ûl<ÿ\mWyp©‹ÂQuÍDÞ‡@Píp#d‹¬f^âhJfÈ7vƒ|â8Ç!!„t±9b6IœÈ–2ðè¼H¡ep69¶ˆ{íWÊ@œÎŒË_E ŽMfÿwys¹¶ 3+vÿ#ßÀÕÁ™jëâ›'ºÒ™uÀaË„øKw€ é‘䔕æŠ.°[rÊ›·Ñ/gŽ3“bçK^úgÛûoÒ#bÊÆ½ñ‰mîñ­rÊΖ.oèÖÐÆ 7Ó¬O,X^–.~¦L›6gj:Êtté’5åÄ“÷Œóßž›.ÅÛ¯Î〲î[’;qzùÚWn`iÏÎåÏ?òtìF³AvuÖ¦ßrËŒî³vÿö‡éwÆÇÍÞ,`£ï”)ƒñõØÌÊT'³CnZ]µ’ågщZ6Íèò«¨(Õõ»ê_d_&MÕ?Ó‡çN¹Cƒ’/S;cÅF»ÚéWo ã‘8ôÎ6„0?.}É öðG7°ôÔ}+ýû(ßúü_av ü£9擆˜Õ°“sÈÁ–oýûw’™'öÜqçŒâ/);â8`þðãNΆfßÔ½„‘ôÝ'Œ-·0bÿžw½£\òí/"ÿ ³‰xݺµåo?÷År:3ëÖ¯cþnå[ßþNï}™Y¸÷ÞûÊ%W^]öÞ}×òà£sàÝsðs—òÉOÿUYÁ uo~ÃY9¦÷-øåÓÿc:gò,‡³gà–ÛqìÑ©Ã;¤Lüú7sZøž\º´œõ¦·…ýúö+ßÿÁ×RÆÙYùâW¾QNay’m®³s71kó®w¬+_þü?–éXHߎ-uŸ‚3"…}bS÷Þ‹½÷”{[Ž>x?f{V¦dºîKø­°êt=ž3ÏÞ—×iO¤÷ÀYÆBjÊšÙ~ýî9PuªƒçVôλL@9»•Ë/ºƒÍqaT¬S=}—%6ÕJ¢6#@Æg-$‘6F6^9Å&w(& èh­œ"Jóh£bH£±QxÑ'¿É¯Â‹ˆ„µ!κ~ƒ´Äš­lŒ‰XÅ nñ 4¸]hˆ"ˆÉS£a¬ßÊ»¥ßoÿ¥/ÓdÕùW@¶u *ó]Û¨±Ùcωåñ9÷dÉ⮥1ÐÀPçÊ‘›úuz„Ù¥ O?õL™:}lŽ:tsc:¤ï”BmÏ´á@m€7±wd,ë«—rŒä*–ÜõaÙ‰{ëU½Ä¶Îf3´*%uéà¾:Úu…ÀXÒìàšQ „:¯@p‹Ùàâ^Ö¥Žƒ7?âuzÒl±"…gn’H<<7 ·,)Õ®‰ È.ó»NHÛ9M¬øãìˆl™õ±fL¼tøxm¸Dç’ÑØæ€C”3„µ¶ÐåNîè©÷²¢Ž¤ îê,5¼5³”¾Z0òç$´ð”3kîä-ßõ^9ó2*ÉÄ‹«Ò^—~ZN“‘.KuëàO½Ðç]¦ ¥½á´wÖ;£2aïó˜46¾K ªÓÔÛ¿:‰­ž:sºÿ#pÜ×–+~| {xž,ß?ß5ÿ®ÝÏg06v`™6}ËFx‹uš%Î úºWKÇÚuæ¶Ó:ûY­EŠ"&Ÿ•TeÒñå7êè Eúˆ£ÂËžÛ{%µÊp#Œ„-zó«òkZóó ?$ÊR7›Ï›ÿx–ÕôÇÁï×·K¹ò§?‹?áÙríµ×•Kü“rÜáÓxWÆeœäý§í]®¿ñ¦ø>n*п¹…½ަJçÁ÷<Æhû.º´Ì]¶ªØ‰x”Í»wpZ/ÕÒ¦]yÕUåû\V&qªžïã¸ó±…I;yœsù5å´ÃH~nž>îЩeöœyåäÈÒìAXV.¸è’t&Q†{ï»'ý>föfÏÀ(и8{Ý`¼ë”)9¥è¼^þž9àGì-xbáâœ÷ÿ¯_ùZ9éD^ F¹\÷ιç•Ç9žtÙS«Ëÿè÷ƒo~ç{eÆž»æÞº‹ý†ÝÚ,ú[TvyÕŠõåÀCÇ׆˜i‚5Äêeûõ»ç@Ëk~Ÿç •n4Å2‹½¦+wÞüD6’*k(®(c£tÞ§q Qu#±ëasºH*Ó G¹ µé޾©†¤÷²1Ì­øÓÉ: 6 „å –©¿^é½7>ÕˆXŒLŽ‹Þx[ îí„Hƒ¨BùI=þÛ¨P6¶qu¯~¼úºŸ¬ Ô`T£AÚíW§q@C¨œ(Wö£sÆÙ¤ä™ä:„õ¢ž½Ö|ÚêÑ›!C¤Ññ”¯íu6tú—m€ tΘ紗j;ÚÊsã¶õ‰&£«iâ£ëØ=ê¼u^µ)ê¹*ûÄÏ ¾¨Žô®ÿÏH6²ààƒÖÉ™¤éüjDÉGm‰nmÌ<ÚÒý*˜>ÑIëœùH¤r•N8µMÙ{P‡ÇEØhz°(ÛÁ]–KûÅMlš÷Ø»À‰Ÿ+¶U8C®w9]¦)Qh /ü‘v šœ*Ë ù9gáUïÝ[¥}N¶ÒÖä•NÏÒ×R¬Ë•SÂì¬e¦D;ël Û¥KXCì¨XÞ,[Ì7éz¹tÃ=z«ž~¦ì»ÿ®È/EÊéE²#·ý«“8@Ý;X«Ó;iò˜rÙÅ”;þéâÒ§g_Þš¼#{©Îˆ¬x”ï[Ñ^{€CdyŠåƒÿ* Åš­Î¹aŠ$)Ô:–ÂU}¨áµÝc•,nrçw”W¶ Ê>€³jé ƒ°Î)üEé¼³ôh8o;— ¿‡|gíïS®bîØQ#ÊçÿõYïNeG^4yûÝ÷‘®KNú_ßøÄÙ¡±³3y¸dýƒ‹.++¾un™È1¹8!9.cuä~8Çi^sýÍå¼ g²\¨GÒïÊ‹ÌvçÍݾ=ØÙ€OòãeÿÃË‹ºz³${'%Éw_BöÍ¿ûXÚ²¯~ãÛåØ{¥\3¯ºþ÷fT~`Þ“ð—œèã;|Ù×u,ÉùÞ…—g†oVÀ¾ƒŸ^{#/êœ ÃÒ~Å57A¡oßTvßy<3ƒË öÌáÈÛÁì)ð=ѱ¸ü#Ÿ)ƒúõ.+×®/»s\«O;qF:AçÿðG)«ƒÉ¶¯¾PPÜ=Ø´­=á¸m7ö`L™.ØyʸŒøjåŒÄò…†­uÛÖñößF3~Gü­ÊãF˜¨¬ F—{ïz‚]é¼¾šõl^6cùµq‹£Ž§eÐ˜Û T(´ØÆ£mTœþQ³ë,A«¨MÃ'¬ZŽBmaH Æàö7¹¶_< ¸äT…¶iv|­â“ÉRYùoÒáèµÁäYTâ!Äzo“kÓåt68ù`Ä‚«%aûo§p íˆ9S¨c0zìÀòøÜúfB±µW—q¥ò­ÕL;*Škd†_íMÇ+ÓSH¶_ÂZSUUh¸a#³gQF­=@Ϲê®:‹³Zk\õ„~õÝu½Ú ¥Ë鬟3ƒÕ­ö«Å!RÓE‚D¦±BXvð…¤ÑY¨#‹b?4:€à½í™Ç¸:;!mŠaF×#€&œ6„‘/¾#oy©˜âÒQ†¬C½›„Ú+á!I0Àù‡‰»t„K¨ß)|òq=tN‘‰|ÈŒ¨e‹«ÝyðšcŸíæR òô¥O;œÞ`·yIøÔ÷t,£m•é CìjÕ2/ý©'à¡(uiZAó.l±YÄ' ;†^Ûõ4lè´/«Ó6Yq¼†ôíÝ­ìrÈDÂ<öÑ—kÑ9F檌’ ‰êO:{tî²yÛ|£mëí(l± ¶Þ“LUž”„XàÙ6·<©3b¯þˆo¸U¦ñcøö)i×Í9R_ê ”<#R&UÆôGmœ¥ˆƒþØœùåλîŽ-ª‡Ô¼Pv<ÞS›÷=m9 *}SÕ6âJ…1‘ølëQàI€ Gϵ—à€ü™5øhT…Ê=ž½’eÒºä§6Ü9fÏP‹ÀGÁ ]„Ù¸ù*Ô"eðͱ+9!fÊCÙÑ;‚ÇAÞ˜ýö«S9`x–¾ PFNr:˜r„¼éT(O¶T±BÙˆõÑÐ#×}9s~ÐàœWŒýéÔRýß¹µæBƒÓ“ë×z‹cˆ]¨ûtÚzvô]x-Îb\àègœ t1 =$—ºn>ÁëoÕ{nÀB„‚c:dEZxJþ‘#Ã|ÖFå†ô !oòÑñð¹FÕ_³4ªŒú4[×Ï×xA%‰ãáÚ9¿ƒÓ`o½àž,Ó¸Wm"y¨}3L4‰ ±>WG[:â,%Ky0zÑáØ} ó—ŸÎj<ú«“Þ.ï4‡8H1¬â_r‡¶†€T@­GºGvWümé -9ñkùÌ“ñØæØŽhÓüæaûW§p "H=X/ñ ¨½õë7V9‚¢*&ʘ:ÕÊ¨Âæ½³JÌÆ+S¶ÿ[÷•ÂK9U§M­ óNhî•ýša«ÜÊ’ñ´& ªª7$á¹¹\=M¾†§?º¯ÚQïžÌ$»ÂôsÏ¿ §Ú ÅI®çÙ3Hmšmd0Ï亥?Uî%ú€óòhÜö^¼^mïŸÅ¡ö2¬æƒŒÝ;Ÿå7¾‰wG¥®c#²ò/® [Êe?¾‚Šž*K9²TÇ^‡_:ì¦êÎæÍî[lh!¯ö¾-Cûœ¥÷IÙÐבxðÍ6o“v+ÐL'Æ«¿>eæ?Í{FÆ=Òa¾ÎÚ²¼‹c÷jçËù&¶a#úÑK¡%¯ ±È¶_Ëô%S®½èÝ9¨<úÐrŽäâ t•%²dCPˆzÏâªBEùXa<‡š;Õ6…ªÊgSk}£Åj"OÝ'À}”\€·ö ¦WÒYÁ#Š4*ÄK¸_\Èã)s—ŽX†X“ÀÅy ó@–À“gòÆIäfYöÎU˜Z†dBèö«S9@}fdÛ¡#Ø^6Ê]\ë5ò‡yâ(QVôä-Ä}8Dy¨£6­L´X¶ÿvÔ.ë$/ŠªQG,%°†l¨½ìÌÛ˜ÄÓEscM¬k×}´ú›¾ÐMÓÒá ›>²`:âÐæ 'µÎfî‰2'QÄ¥Æ)þ|ÂòУ5¸8ÿçìSœ ½¨CÀüD¥Mjs0Xü”„e7:V–*!ÀKeò-ð”,°•F]¢ -ùJ«ÈM ކ_Òã³@â _£]Ö^hªùšBE¼ÄñkQZçžI•`Mlx— soxÅN½õÜ©wes_sEO“ù&I–$ö™ðª˜s»ý«Ó8PåÌ©ÈJFŸjôèpk¨vÚ¬CU¥•¨ˆšÑÖ±äQ ÖjÕ•Ü*\MÃ]eSgÛò22@jõLéh?Fxm$¿ŠO\|¢[®¨Bäêé_‘{”!4"lÎTYs@ðù¼àËY —;µWë8ÿ²çmã~Õ½é¶{)Kã²™Ç,æ,þ™¨¯-dý}hÖì,åÙ‘%9Î\X–mñþ:÷bÚ®ÍaÛ°_uÿÒ´Ò쀱ïp‰mêÞª¶YN½û„²Âƒözt-Ï=³¹ Ùe0‰z„Á*¾Æeûõêà@ t­å¨˜ÊÚ5­+•J5e™…-†Ü¿#„*â1sTR‰°vmÚbÜ9üºÞó­f”Y‰ ù‹®‹­h¦Å‰ƒ`Þ1"6ÀÍÈB† sM¿WG™hUl›CGm+5 þ×YaÜTªPkôö«9 8XU.jÔ}"­ìX§„kôS—¦ÀéjÒ$˜ðö¼g,7†n7=0èUqÕFØÊ³^SßV6§3oêxÛÈ·N¨u'¤uìå¨~j\½V ¯Ž‰j7Ž{ qnÍÆß†ª*h‹À¥Mj1 ¬ã:mŠ/O§‰´ ¢È„¤ÁÔˆÅ9i¨R`§z,—É¥’´¢jmŒ)Lnp艱mÒƒ'6.¶2@1rO‚ŒªK1ù$kËÃsx“²o„¶Ñ¤N§è½7iì\x’Ve™áµl™—E×FŠ«HZò ¢úLTÄ”\alì-‡\´—Ä”w‹vÐW¿Ì”)+­Âx¤h-ž´R/<[wµþºý«“9}jêÅAmmþ¬2d¢Ê#U T×\ÔÔ30qú‘C†Ú(‰P\ùªr•ýxÄšÉÉ•>7!þÙö§Í÷^þ$½ ÊIt²5RyÕ΋Á{ñ·²Ê‹¬pP×<ýþ(³î'Ë tGî@vdÀýïò2Ï.Å%9uyQì`D“µË”¼ê|[Þ&²“~äЦ¼¼¥–A[´vͳ噵,!ïNyªqáýU-zg*µ½›jü¨ JMÛIEØžm8@Ä)ç! ÞÔ õ©++֖ˆÀêò89m=€øUÍxc.†"àÀs+ÂÄ[× ¸ÓÝ6´i´k»C¸*ç\ ÓžŒlY ¯ ]Ý;Ÿ’ 2z<ñÃ|¡Ãž½çÏ[ð{ç…üùÇ£é-NAÜ ò2]Û8‡”¤ÙþÕY°úkõYºü)7TNfxΞ­/;qíå`£q†TÇ VñFÄ+Æí×+Ï–÷þZêœmƒºh¸¨©iêëš¿ª÷5u­kîq²ÖÂÄÀT_W›¥LˆB̌:·uô™çØ òDЄO–bK&<;È îöâÖ¼ ÚŽ{‹¡æE¶(Ëõ^戃\ŸÔ8ÄÕÖÕ4m6¡CÆü(_&°Vá“a|Œ”º8a$§P¹—8é’gøAH&”˜†ÕªëtÈʧäK>ŠG Ys‚Ä%-ö_¼6ù`IynyR7kËsIN@¥ÜÒeX»Õñ1s×ïò¶RF¼³üÆD­ýÓ†42ªÌññ¾Ê¨øHœLÈC@â,¥…°Ãat«†vDµÁH¾ÐÀ iÁÅí4êÇT ä }qü;ÂLŒù$-Ï$=)0‘!Ãz ZMx‚ÂCëAZ²É“@íp:W&ÇæKRMôÁ/ͤNÞ0Sak8aÒ!¯ì¨‡•.QñÙ~u¬— ®PTSí·Ú~*T¶þz'2Ái€ÊR´ÖM”õ¬¾¯L!’ù®OU#3‚%9ØÁQgèø5Qµþ‰÷‰UõùVW’_ÎæÕôÎ웈gåBBý]gÐ|ñé&ÞX½|ÉúÒPö—90Ðà+¸’¼Þò¢KÚR&TqöJÞmœ8˜¨Ès‹Ó&IšGG0I_“¿è;°ÛDÖ’þjx·dµˆ^ôü¢‡B^Õ2m›¾¥Ó²<ÏþÞuëž+ëV󒸺çÅdÝÚ1:V¤bP•ÛÊŠ‚×ÝšÓö»Ná@“¦.Tt7q(Lq«íÛDQtî2kir2†šmPù3H…C<6æ6`mc˜§‡ÓX¤<°uxs0•Ò²õΆ,8 ä ¹¤IäÝð4X‰¥áx;¤­FHqš´:"³±OF¥µŽàÅà…‚ ÜþÕɈ# TY&jµ}åÈZÔÊxµ¿Í‚¢Œ(_q,R¿‘â@oÿê\¨Ö‹CÚ!õUgY{¢½ð¶.ƒ1Çxë³.Ù‘vF§‰Š^« 8¥³’ ²†€ ÒQïÜ›ÞDQÂê{€!¢º+ÂU;¤$ëi>Òiz凫18uÍ<02è@ÄÞ%+r¯xM§ ÆaN¨%il“„ÄNäm%6±03;ò¬ëñ•ooó"8P„$p¢•Fí[,8Ф l“XØCË(]:ío哸ª^uIÔ±À<%ÀŒH'í|òâ6F†Ýô)_Ò!"<#ý!J¦@wø`<é5âþ‹‚gÛD“>õ—|·½8™ ^jûH}Sq9ÁǺ¶•/€”3Ûe`«3Vçò2/å·Æ‘2r_u¾Ši‘õP‹ wcð16ÂLÔ÷üU°2] úÊy*z„'_ž¥»•=öª²?•wÅ,ßÌÈõff,#ˆÀå€nÿÔË)jß¶-ÁJ e·ØƲ™Ò[Ë”;n¥‰{ìË® %u- ð† ¶M¼Á•8ò¨…¨äÙà©Ì Dýjq›W}]“WšҴ×Q†Š¤Â›¶½å$y–&±»{¯ð?¶)0Ô3¼Ç«ƒù‘ ºCâ8XÖZCHƒûÏ+ͦ"•/«#‚Á0!åí*0z’ߨî6Ðû(w£ô Gzܤ®Nš 'MC¨¨wm¼üÖØ{Wß„iŒª_\‘ ¡Hx)\fdIÑ:S‰Ï Û*MNrC9LHÅn§Âì*¤Þ´”=J𼉕\©Ë—òC”¬‘þ—{ý¦é^n>ÿmðÚ ‰näSTF¬ºˆ'Èc›å±É,ï¡10Ûgÿ¤ƒ_b“¿œP(ýÀ[—j/5ºG*°Âl ]5¼³ ìLIvxQêqÇtjƒ«ð«üŠe63’¬¡–nÿU3¯Øªž0ýËHpV<Ð Œza á­Ké-µÜá¯xš¿œz}6A —@Ë -±¯à‹zJ¼”ùÛÔeâ+µJ —ñUÿJ¾ø\ã"÷Mþê|OŽ<í m3hÅEZ;[¼ Ø„(5¹ÔJ Bl 2b³Ëœ¼zëÃ+øÝÙùÿwÕ2X‘M]¤^"T«TQ&+Õ)ú*˜HU'ëù­WâKÆNmë¤wàù¯#NÆZaMžÈw5Ha‹°ô Œ"RY\ …©X•¾D}Ó&¿J(*07äÁ½˜ÞQ6#wÍS™‚¹¦‘DWùîUpYŒÐèQ_M¦¯¡¿Òùòh´®L'+äÏ«þJùk]ømCã§5N:9nް´)‡ñ×xxÇa© Å«¾ÔF ]œA™ý»–òÈè¨}É z¬82Žþ6½xi2XÓ“º·>Úlh¢íFò¯ É %wèv["‘ˆÆfÔ†”ó*"?&Žýa[3Œ“­]o¦M‹há–°È\l‘úÅI)Ä¿'&˜ÑýEþ´1„×ÎåilZìÎvÖò‚‘8²No’ýO),(ùZ~ŸCƒt€_ÛRšx÷å ?tŠ2ûɯ³$uÖ–¼àimì%‚08ØøŠpâD畼ŒÉ­¶?etƄڼøéÊx 5—¼èuHrp[”,_¨v$¶æñjýÖ?ï;l,WFžaYx(ÅÖHå’ûc+A^i¤ ר'þLë‰Øxãøõò[¨öàoZ'5‚xm‹ôÇ©6\<Ñt±tÞ%M–ÇS |iH¯ž=9Ö²gY¹z5o ì‘£¸4Ì1ÿ ™Á#¸ÖnXŸ—tïÎé¿FÚÿí+ÕA»b@w¡î4¦Lóí&3ÍL5NÖf»´Kqñx7!Ó`8z»óŠýÿ‹LªôoC*<[Ã)}e}W@>Ò 8r„þ«nY:Bùï½N `­F_Rµ I;bÚ:¥Â£ÎM°ÂiŒtÌZG·µoæ­â·ËM´yÚ“Øº§- Wk§: oít†¶8É)éLäWSŽùÕÞ5 öã4ÚÊk„šÜÛ@(ôÊ5h—é>367Âñ'ÏÉKÁ7½Aþ†~Â$ œ&Ó {ù ÕwÞ•²BÓfFšN;ù¤tf^qe9âƒyߪòàóҩ ‘Uù44§h˜økÙ|9Éþûî[–.[V_¸°ôëÓ7e•‡ZnÒÊ®ÖiJƒœWþËÕqñ‚BêËßX“¦.« ZáÙ\]í‚/}+¼ÝÕ²ÕO5bAö|é”FTä3ŸPÁoCH~Ú:} ¯(E¶Ød\‹T*Òܛި4ŠeS/Mª_ý³MIˆFc}V.¤Õ Xñ›ÄrÔn*òqÀ~û–åËW”¹óç…/ýpiä:’™†D ¾ßV^D+_Z™ø6´yx)ì¶@¿×àñ'8ùí §Eþ›þ‚ª¡Sù¦]Ÿ#bÜdZG"%¬–#Î|ºü„žªRŠˆõ‹0Â_®%GgŸ™¯{`¶ÊBŒäÛ°lÞ¼¥¾€¬ ì(b½É$Z2SŽâüseDŒ€µ³‚TlX @ fa4`ÐFx·Þ€E9¤«Ãè"nा³/×'.ZòdyÍñÇ– ãÇ—Ÿ]s /ÚØXÈ›Wñ&ÀgK¿¾}yýö³¼eðÙÒ‡s8r[O@RCº0:õL^Öa¹†Vö›±o¹ê'¼Å7!¾Ðë…²jõšðD<VŸ„_×¼ñЙùÞYW;’£CˆÌXŸü)‹T#Â¥™÷±Ž’Ô·‹ò¨zÆö4öG¹|™E‘òf#}ò¼w¯Þyk¤¯O3j¾Àø vßœh=¾á™ ¼uòÙtÜz÷êUyhÞÛò’t0] ¹Œ¶ëÉÇ[?pùªö¶^*Ô/ÿVî×B£úsv´¶nõú5ÉΑJ/Ëb~k‘_âÒ»w/f’zQ® qø÷£ƒøÓ«–·;*¾u²{·îÕ‘¥|ëŸy&xþ;äŲz,`ê’úkË^ tJ«åªwUk°Ö„ {T%ÁÔ\Új?ÑëÒÄÊâ&ƒz @G†Àš@ÛÆ+"F‹(ö„_—·T8ÀÈ<8I`–1šþzKBm‹ôk‚´›6ì/8ŠoáĘ#—ïÍ›ïÈ‚Ïf Ü‰‹2&ˆ“œÓ­ŒàbƒMb "QÂ%¢:'â!_x~w]~È8rÂ&? ûjø8 Œ¤B¾ÕýÜû¼ÚRÔç°>e'…儾 ‡Ï<8äœäŸ|’–:Ä êºá¹Ôc;!ɃX’™ßÑ×Ú!³ Z>‰«2 %¥ 4yÙ)ÔGlþd®óô)€€V„• À[Ö—u§¥Ú×%¿ë­o)Íž]®»éæ2lÇ¡ño‹_'È{ naE•Q,VBOðŠ€=ð„Ùðª ;‚÷q.¯àæwÝZòÛÖü‡ï¸cFÏÚü5¢: µa“mÕ°‰C#"A9órÔ­5âOco9R!)4ôÕQ¸®ž•g—Šh™òüryYQÔò¨/ÈèÅ‹1zôt{ü–Ò]Þúð/NXî¬#p ¿e’~ ’ÏäÞ4ÝCp½4šDuÁóVé©ìÞ£{Y¶l}¹í¶'I³¼y šöâ¡ 5<4>ò×K+˜aáR´¦Æ¥"ž l¨gqG¸·žLU¥ ÖQêØ¤,bïœKúuÐX¦ì¼s™7o^¹pæË´½ö,3y5¸2ëí*–>¬Œ¶s™ÿÄ‚²nýú¼¡O¹Ò¹7vL5rDyࡇë5e›Ç讲³~ý3e÷]wIý>òØfêÞiÖ3jTäqÙŠчÊíW˜ÊÁ6uƒH¶Óºï¨.nº2“Ô«G76tmÂÁbí𞟗µ É[9YùÔÓeìèQe·)»”Å4ôO._^Ókm‡üIÆ3ò<£èãÆŒ.»œÂ+Ü—•E‹Ÿ,ôÏË\,öEê´òÛgõ=Ú› ;í”NÆì¹óR?é@û"¹¬ÅK…˜FùÞeò¤Ðôð#aëº!;“Ã9È#‘¾ÞWÒ‹àÀeá¢ÅqX¤aDçΛžjûìŸWίF–ì¬[~íÁ‹¼€'ÊaQlèÚõÔ–¥u˜”ˆvc/²~Wy00þ¦ƒ˜gdAcDCä_xE6D[ìé«é‹¬.mÄ€À©s“Åž ofØ‹Ì";hµ,m¾5¹hÿÏP¡-‡6%Yâ,@íT€“:Œ8ƒPؤGèRF mCmðròñ)—ˆùô ^ºˆhÙaž¦6Ün‡‰àpÀ]/OjƒNtL‚ä ƒÑ]Š ‰‡ÿœÂFÚà…nígm_k¹tªm[¡,A”S]Uν”zÛéßT¦íõÆÏ•C:€¢l)]z)|(™‰Õï4vlÙ §ÿAlí¦MËΓ&¢gã)ÏuÑï§ž^™Û©{îÁщëËôÌŽ¹6­Õ{qØIp™gl„BÔÉ|Pß³4&«„UÉUVÕE3òéMªo•z6v·õ‡¬HäG0íjÀ‘ÅÈ.á¹hË1CU.›CdƒòÓÑ$Y…U´Rdö¶öüR/U7}Pëo½ÙœºÌÄœ„_Y¬ìñu8X¡‰Òç´9kóóOû€bVúy”†èž~Ž:Bë5å#RÍ<2€Ðž²pã¯y€ñ'vx0v@z*”7‰žå”--œù…Çê/é óÈ\mù¥!’HtŽBª{4ÐaâZ_¯MT¿ÍÄ„Öü&C|¯‰|v ýRoc $‡?ÝÕn2¢ö.ˆ´Ö(A…–†—sY(/”»þóò²•bãÔ6lÆ¢a¶±ÛȺ</•IZŸF ‡ œÊq4K:á”&§ëtº2mKø;qò𣠅]'kó¦ºìHGÉüW4ù¯\µgcS×Ñ2ózÍš¦±/4üBt¸–ÛQ/; C¡%‚À³ ±ŒéwGFÀ(ž/ðµËÒ¿Š|Öá´IkŸ>½Ë ðzï'…é˽H«asZóò™7’zŸ]øˆÓjö· »_ï}nEKðNŽú5÷mzÃŒka¼7®ŸËà!Ç—ýðÓeáÂÅåïxCŽð$¨³êâUE¬¦ƒ2£ˆí4Ÿ W1CN$$+Àw8U[`^£µ\ž’ŽA#‹I~†§ÀuÂE‡FG›_süqeœ¸~Œ:~Ðé”ÚÈüû9ß-'¿æÄ4 êÀ¨Q#3ú|ÑÅ—–…‹‡ü3O;%im°:àdgòÿt™KGáˆC.GqDF«•¥%Ì4œ÷ƒFœq6lGdshyøá‡ËÃ>VFŽžîN`Gš2ÔÝëÞcƒH)ÖmkIº1óôªgʬ›×”CŽ \7ZõÛ£qâ£QÓ¯sÅFa$íTÉËݦL!Ù–Ø”¥K—EïÎ=ÿ,«š^¦í³úÚ?ôW¿ù-–l½¦ì ¼2ê¾›n¾¥Ì¼ò'åÔל}ûé5×e$Q[qèÁ•«¯½–ÎÞ rÄa‡Æ9ÿ‡ ÂýºòÝóÎ/«UÔNéxµ—ƒÚ“ÆŒ)GqxêÇ¡C¨·!åλïæLæîeÒÄ evâþû(çýèBfv,¯;óŒ šhGm›yÅå*è9þ˜£3àñÀ¬GË3¦Göâ‰rÉåW”ýy>æÈ#·ÊË“ÊË~©¼Ìzì1ìå¯'/ÙÓýmÚÛŠ˜¼(ªoœTO«†[|nS‡µyCÛ©P?:¢ª¶³Žê¾J`mûÀA‡6ÔD¶MĘ6Þ€vI õ;vþ¤ÍÞ˜´gÆ'9_„VûÛàŽÛÔ’6„<ò‚DÓ6ô˜Æì ‰]Jz‘:„×Т[3¤,:2Y›÷`€'U+êš~ój:•É]mzmžeUig2Ê©Ãf[n²73þÅ^ËÄ­õa`Øb¸dZ ¢´jyMåe1j;íLœ÷¢†ðM›ž/½ûô(ÓfŒ,?8ÿ!b7—çÈ6¨COÛB·¿"îäKÚöj‹A_í…ý¼ã®»Ë)'Xn¿ã®2mêÞe<3µ+09˜ƒ<03qÓö™Ý?œ¥›Î8Ù§wŸ2ëÑGÊ÷ÑIN:á8ìÇ€ø&×ßpS™Ïì°¡Cã „éXþÔ9«LD–¨ÏZ_Öm4úEçjÿ•9EŽ0ë´¶Ó蜦úPÔÙææ^a"]d4™ kM+^qéÃÈ —r†'È7œTh€U•ð®(´£ûFi¤QÝŽ­ÆEÚä)Pþd@±Ê-¨{pJŽ®x;tBÄlôшæjÓÆùozï)Vh•’dZiâJ8_DÔr—#ðÈe–}‡ð]XÊg£yWõˆH ñõxÓøàud\XÁoC³YW$]EI¹Ï}åIê‰ZX­‰5Έuȳyxg:gÜ-{•¶–1/duˆà$NåK<É’€à—q™…—ØìqÛ09|ÀþåÍgŸ]6m¬œŠ Ö[åx‹ß0¯mŸÛûóbø6¬ýÝšÞ¼3ú‰£rÐA3XŽp(¿sR>;tö*ks.ƪ92L PrI„Ú鵈¤A„¿`ÏT-Wð•NÓ"¹uK(O„«¤ŽPÙd¦WO2õLXäÓ<:é²ílŒËIœb¶Ñ¹è’ËÊM·ßYþìï‹#hGq_dt1ξâÒO|ô–Ãqìßøþ—¯ÿýgËΓ'‘îÒr÷=÷•3N=¹¼þ¬×•™3/ÏHô Ç[fÍšUþýÜïe¤ÿÃü@°‹gêìÍ`dî™òísÎ-O¯\•ÊŽqG•¿‚|i •YúÒ‘%‹Ö•þC7§ ‘ÒFi5–óç®+§Ÿ¹{9æèËç?))z•éÓ†P¯Õöä÷eT«O®X^^‡ó¿73/S·Ýy§ÃÊÛÞòærNö7ÜVÞþæ7UÞÁkü7¿áõ8ÿ»”K.Yn¹ãNôê¬8 ·r¿3u¹Œ=Žv¥“?5~Ü8f3çnê^{—K.»,õÖÝ~ß¼·sÔ‘å‹ÿöõ² #Š/¸÷‰?ù¢Œ8˜`çoOÖ$_qÕOÊþõ+åg½¶œzòÉåún(ûÔ_–מ~j9òðÃKò;îè#±ƒ=Ë?ÿËé.,ŸùØŸ³„aßòÿö­8í.k˜Èzæ7 + .(?çžíßÒhœá†µô¶ÏÂèN{µy¾ŸqòÀ ]}Q9Z~µxÅ%ÎKA¹|nÃZzZ:·}Þö^Üí³iå¡—ygÇLâÃh×>U>ô§Ï”/ù;å†+cF÷#7¤0;!¶Éq"Hñj¹ìôØîΞ3/ú»œÀo|çœr±GãŒ,K—.ÅoPÆŽSÎÇ©wPðƒ*³™¸“ÈÑù¿ñÆ›Êy^\Ž>ìØñÀ¯[¿¡¸ÿå:_ÿÖ¿gÌÁ„›:Çæ¾”綇Ž\k?u测 ãÙÁ'ë×z‹òe[lóÜÅQ®vIOjU p¤³™XÛnÛkñ+u&ä\f·xÖïW>63`!§p„yç•%ŸÞo,šÀf°8¤+¾%"ÔÈÄrÛ¦i‚SÓK7¿–­Â¶–PñWÜôJ?aIÓ8õ=oü‘. 8ˆÛÌMa§(~œN?Èä‰þr:OüŠ.Ù^mgŸYL—!YGêMí9%_;k’ÔaÚ¤â7sùjGƒ´ÁŸ)(˜ec±2Hxî»8’/ÞÊs#eÉ©)ouv7{Ü0bn•@3—a„5iZºþË_Ñp­dÄÿ}¿ÿÞrëí·ÇI:ûu¯Åɹ‡i÷åe"äYgœ^þ¿/|9K'Î8íÔò0ŽÎ}Œ€éÀJ/Ü5ºùìß•¯~îïY ý\ù<¦§ïO:ñ„òÿôÏQvi´Óàeƒæè¾J°mþN§¿éì×3#p=ÿ§ÒïÕLñ-yr K0Æâð¿¦|á+_-3 p´À‚5t`tà\Æñƒ‹.Ž"½åggÚðQFÐ |ë›Þ˜u‚ŸþìßÄ);©]ZNeS¨£Â×bP† ­KBèËüR^´ß/¤µ‚dú¶Õ†5•‘4ÛÞд¿½MG:…ÛôUÁŒVyBt42 ˆ…TFì*ÞLÑ£3œ=}7º(¥õˆ=¬ –ÅŠfJ M²ì†…áÛvPáˆ@v½ÀÌųÏ>—eëé ÝM‡oGFvŒð`ùäßþS9é˜#Ê¬Çæ–{ï»?K¸”ܺŒq«®z áFÖè;Ð1ë‘Gp4Î…GÝ‘ç.eΜ9åœó¾Ï÷-Ü­åK_ûfqFáøce—òsh‰¼¬A^˜]¼Ð9†s¾{^¹yÙwê^/K^t¬ì¼=òÐêòÆ·îZ¾ôåe_‚³±/¶ ¿ª¦~1\kÒ¹Úû‹4ýŸò›òÖº¬í)»î:9³b3Ð¥Ë/¿º|æ3_U+SiÂØÆv¶ý}i}©;.ÍéÞ™®t¼›=§,^±’e£™5{¦Üxû]åHfáì8ƒ¶öו³y´¬c™ÓÑG‘Ù× žÍ œƒ}ÚT÷9Óç ÀW¾ö²}7fTåC§_TŒ¾mj~¹×ôÒ–i—¤’[ôØe úv| œ^ü:gc+€M" h&ÊŽÄIKXÛ^›Œ*h…Ç·ìö¼K« ª3+N»#¶ ~ÄšuCޏÔÔùc xhr݈!>ƒeNâô!LQI°sBaECÎxîÉX<ÆåŸçäïj! Nù[&6.zॠkšL2H®Ú9’ÆoÃqf¾Â6'ëãTü"àÝ ÌŽÈÓØ­ÒP&ñ>ÞV°ðœr&‰’¢úJúîñ›H’t t¯¼*D½§­wþÄRyo€tA G]_Öxm žböB5íšå]pQ™yý-åmgžRÞýη—]&N a] ì åºëo(ß½à’Œ|¹aò裎(F ‡yNÏ÷È”û ;Ê̲!Î¥>702Äᇕk˜-˜3ïñ4².ó±€Ûæß³GÏ8OçÿðGåëÿvN9ïüof:þ3Ÿýë2óº›ËÙ'_ÞþÖ7—ñ¬vdÌ©ø·ôÓeË‚'Êç>ÿŒÔT6â,ìµûî™­p4÷²Ÿü,†æ³ŸøhFå,÷!,ÿ¸…™„ßÿð§ ë Ê×þîeKncêÑ¥"ÝXïÛò7tP]6›ÑâÝwÝ•Qä§Ër–¡¹¹W™t©ÇÏ®¹–Y«Ù$<ëÑÇ«]Óp92µ’ÎÁœ¿Ét’ÕAG–í Û¹}†NÆ<Þ)i¨|葲/#¼Î?|© |%BžÐéfhgö¦OÛ£¼ãíoŒÎª×ÕHO­ÇçáY¿þ}3í~Ì1‡•©S÷,Ÿÿ篔yÞôm§ ÿŸ–±Ñ)µà©86üvÀ;`ߨ“Ñt ¤ÇÙ™ƒ¦ï êQî‡wû¶/K¦föDgy4gPtòÉQÏ„xü‰Y.ä¾;úÎâ0y§ÔíÏ®¹¥¼ïÔlî8 _DüZì˜N¼rÑvĤÏ"gû3Zø3›Žºlн‹À¹‘%c؃í±sè,‘3?#y&Î1ìk¸”a;ÉFóE‹¥C"ž5žŒ±¤×É?'¦C^˜ý¼ÿÁF^è\<8ë‘2~¿,y‰zV{:jl/–r®-?¿ç8N–skýn­-’Ä?x±~V9‰|*§y)²/¹¢ó «‘qFô1È› áÛ+*ðË °mÚ&AlT²iqðð pÛlMð‹`-ío‹RÈJ¸_rß–Ë4‰óFûÖ°&¼j${Žšsc¢\òÊ+õâmGþb¸ñUym\µËvêt¤'Mš=xðÁYÌB²W¥4½€~m°Ÿ\¿m{%¿)«ú¦ïàº~ucƒã™y€ÌêիʲUkD‘δ¶I½êÙ³WybÁÂr 2.;v£½iÓk¯—.[Z›3‡ÙÙS²2a%ò?yâ„ì ¯_ å×™mêEš²ÿ~D°iUf›:8§ðÄÅ&]»,¥ ,<ŒãʈuXEHL¶ËàŽhY¿„)ÂþØ èÖÓ@:~U"«Ãß8ªDg•ôQp þY2®¶•N‚«{V’{,Pè¬Ù5ùšˆ»áôÛái2Á§2ý ‰åR„)\² 5ooCqCHм'„;; ÐèFý˜ŸndPáÔ%Ó0#EžÆ¹T~êç›fÝðn¸¶R »’;¶Ovš¬W» >É1T Í—T|,eú3ͳ´þVXáÀÆR,^f‰’XBÌo*Ü©@pi T U¦'Y.3E;éˆCnŽ}Y×ìNô•,¹ÿÁ‡Ê!4än´±ñu*o/—ð´ëÿ[ÃãÒN×è©ôîøw ¯qÛ‘‰Œ&väß5½~OkyÃ[_&٠ϦÓpÂaÄ®IïÒ¢ï_xI9êÐË9ÿðÙ„M¿Sð/]¶¢¼ö´ÉYï{Û]?g”q:K€–f]¡£:e®ëuIÒ…ÿñ¯¡ßrïÈò ‘Ç¥ìƒØ,Ã)³½¬»_çÎ5ª}q_sòAeõÓ›x³›'–PõÖÊOzµâkðg³˜uk>„EÞ¹³­W8Œ°â“F‘ªøªV â¶ì‘‘Ý?ýÓ¢sô4ãÒ ã&eÈ;»ÒµÇ¹Ù(¸Y{G`ä< “4rMƒu§’ TE^ZìÛú©8U&I|Z®Nºd]F; .,‹–?]N`]µ£O2ªt衇°æ©ìqmªNM7GpœP¾…K–æÄ ;î{°|äÿ92ÎYuû—¯³NýF²‡ï84Nãžtîd©Ð=5žF!ì qeú+Ì‘Z î‰ñ¤—É|ó›ßkô‘ú£À©+j­G3¬€GGsH9묑q,®¼òÚrËm÷•cú²–¶Ú‹±_£Úªõ4øÎ®9Í=kö¼¬‹¿^¾ç­ufî!Fú\ꣴ-]¾‡¹wFÅÝ«ó䊧ËN,í¹ëÁ‡™U<çaPìb¶å :º:ÒîóNþœÙËÝv™œ‘@àÜŒ¬ê¬;ã¨#a§Î‘}ij7PNuHì@8ÿ$ðí,N–Í]{ç@‰—>¾éõ¯‹óå>7 : ðÞw½½<„ónGgŽÌ§?ûÿ–£ø8ãôSÁ=€zdòœs¿ËŒÐðcÈ6òr9ðä…N¥¼RÇ^®¼tiÊ4xPï²`áSå}ô%KÆÇ‡ö’s*¯¥v`Âûv ¡ÊˆuP­éêÒƒ ߦÕBµ8——ñÛ¦5¼ ‹Áๅ7ÜxÃ[‹ÇmžÛ4m¸ô9ÈÑÂ ×æ¹Õqx1q´å2­¸˜Ñɯxü´e3Îg/ÓøÜæmX›×sÜ‹£-WÞþ¶yŠ×<]ªc\›¿<3ù.¬÷Âo˜¸…iá_Z6áM'ÜJ>£ŸD° |ä#Ÿãy'lÙ°²Ñ*ÇÆ8‚¬ÎÕüÔ‡Îý¶mÝÀ@€Kr]5à à 6ÑƱŸ3{N™ŸWEù!ºr uÓŠQëÔö”à4¾È6Y§S¿ µÏiÏô%…ÖImÖÏð¬tXÐv,^¶Éüð§ÍSä<¨;v¸•Ú* ´ë&õò7Ž1©ÂU WäÒ%Â>óTí2Í 󮹉"¡¿õ%ê^!‹ßKÜú ¢€´¤Ö/!JÉ¿>j@¨I 2©íUƒÈgCó,Á†'pk™¤«=‰HÏ$éS•¿){Óa°S|éHdó¸S|y[žÈÛL}¦øjæ-\|+ÓP¡C`K•’áwFÞ5O邞0Á|¡9FH„äfRó)³²”!ÿ« ìÏå÷'š 0 û"‚„.*ÜЗ¹6K>òVi†VºÊJþÊ"JüÔÑ ¶›Íî­XØÈ‡çaHxŽAñŸm0¼U"ŠÔI€›9O†ÏØÙ$`x¶ðƒâ#¼ÀÙ ƒ'jzA‹\¤  ”{Û,uušqÑ7 }Ë·ü0×/}è—C,h\Ïíd]íE†r0:œQöqn`.ôJªw¼ûOÿ|yÔÃþVã¼WZü€û‘WpåíýËÑž%¼=o ¼š×ù[>Ì­Ár«Ý#¹EèùW—¯øòv{ï[¹‚ö§ävOâ_ÅÕýmâ6W¿Î %ó0*¥œ¹z×øÂ63\ç[ôL«¿…}}¿7Û<ÐØ&L&.·$ˆZõ¶ŸÑfŒÕç»m(6ÔÉo¯]ü ú°‚mýTâAöaï1¶V:Е?å‰c ëÈí<°Úª£‰ØŸ™…qo•ÆÚÏ9hå\$©Ð®-š{ÈGª) ^}·>’€¶ƒ«ì’P0*ª“4†Ÿ z4·;?íTÿ$w·%É«þ蕉=ò™O½Ò$-%Ð㣕Qþæt´xóKý×VèHß…%¢I´^ö¬´à†iÑÀÅLÎû“”‰#êëô²Í˜7Æ,5ùÆ¡ÂÉÌ"ñø±mUIÞ³uÒH¤À€Å% «ÓNdÿ®‹ì RP—‰Ê:Žë"-åVÅUýÄçgnI©®6NŠ]¹õÞm_Ûy§Kn[òx×»ßÍm—ðªw Š·•\ÃÉ¥'Â]ÊŠþ+_ýšåÞ¬è?é<‘Ü?ÄIÃ5<¼öîž…ù+¥W¼êU½Çú'ÿí“YY?Ú-&?û´§/w€îG¸böÎw½k¹Í­...ÇçŸ+½>K:ú‰øöÄ÷o=ä.Ý*£ã¶xÏÅ´8x‡å-o½ryúÏ_¾<ôa_H_¾”[ž>ªƒ·}s˜ìÄÈMÉãJÜ©åÖÜßÿÜüzoóù_¿íâJãZ¡ói¯$Þñ–· ŽNsKÖ»šûÖŸµ¸+·Ø|×w<±+)^A|ù+^±¼øw^έ-<”ÌÛ‚žò¯(›;qó[Þ²üñ{ÿœ Áñà;ùA¡;/Oþÿ¬«žú,†ù÷ÁÛ«ž-ö°_yËÀ#XhðÙ'_3ꢃW+ÿìÏ®ìe·àØ÷üû¶´+Þù®ånw¹ëòP®½òeÏm!Á[›Lìßû?|s“•«¸Ù“Nù¾öµ¯K¯Xüò?ì¡_±ü‡ýáÝxáÙ“â…ÛʼZ[™K?³xÁ'èÑàb'¤CcÂQ%Õf>š>:ù…:ïÜõkžñR8'wöþÖoÖÁ óÍ \ÍýŽ xÕ;q°ÝüEþ Ÿ¸¸`ŒˆÚ¡i ¬ÆØIÄÉ%>ÄDZqè+Ž…j‚o¯ŽžfäjšRüž畤†´µÓ6$âÔÄ_óÍ ¾Ô 9›9 Eý°¡ƒÜrrá‹n@ «L¾/\ä&eáKqyQBoì€ÉÈg¦)¥ Õ˜M ÷7 ’ƒ£¾£y*ÔF˜ú¢Ãîä5¯S…Œ'á<°øðG\â­œÀòÊ[ÚÊÿŽ€;ŽR>#6õõ*¹ûÓôÁ÷ò’û®·ßùÜŸ·Þí®w­o<žÅŸÝñ÷W¾äž÷[¾÷û¶åÙÏÿÕ”üã×ÛÂÓßË-À?óôg.ƒ+oޮ牀‹'éCÆt»3B{üÇ_ý´0ÎŒ'âgÏ}òÝ„¡Ç Åh‘ÂW}­˜²•‚†Áj¼/NqD}HÔ²on1ç‡m›a,~zëqÔɰJƒÇиÆ,1†meÐÄ]2êП:L_ׯ{æFNøi†¾zɵØv^5iÊ“6µ§ ]'è²@mÑ X’xvר@ØvO„§Ÿ)Û0|U¨-Øa5zL}ùš¼Dkòœ˜Åv`Ê×È¢>Òµ9~êC)Zkvšcí 0tü“¾þ{u0\˜— –Ù[–ã¶EUd>Vïß GÝö‹ˆ®„õã48Ä3;_wçq­úçårë=v¥üËüàåÉLnœ„ßýîw[^Ì›-N4ßÍep_Á÷#ß÷¤&ûaî+ðŒN¤qo”ó®¶9QÕ`þàWl7Q{ÿ½ü}JÝÄ eyæ‡OÄñ^^ügÿü_r_îù9©ù ÞðÛ¿ûòž9øîïú˯ñ¦–¯ã¶¿Ü>Hôº7¼iyÌW_¹üÃïüÎîÓõÄä¿}ü×vkÈûÿâªîÑ5qfû=fýkv¼Q»îú"¿#yÏ:¡lÁÑjb”´­P/€uÆVÑ„#jBÅÖ¡ìQž¸`BŠ„ͼæk(oß3¨¯€Jí;ƒ¤t9F Å™ Þ%*팓håœ× ]á½ìèi°Ãg4’Éø”Ž_7Ïæ {ßþô´§ÿB'¼>ö¢—üN—Ÿ/`àyÖ/=¯8õþó÷<Ü›¯œ¸ ç³?úcÿž{²/Csæ=Õ\%p‚xï{~1“Ú_ãaÓwpEáŽMø_Çmg^E:J¬ýü3ŸU?õþsOBtâxöæ±…>^©8¹þ8‰ñ€Nc2A›€cÇOqµìÈòUþâ&ä×\Ã;Æ ü: “*Ÿb3r}ÚôËŠÿSæi\q¹4Ÿýš¯îžÿûÝãnËË^ñªž!r,/îûñÿðSLôï×muNޝàäë^_òÅËyþÇÛ¶¾øîwåjÆ—?|ËÛx ù(÷ì_ÒÛ€ÞÄsþ€Ð£ñ°nò­A¦Lß æJ¾¿¨W ½]è o|SsŸÇDß·y¢÷6^z`^òw>ð.Ï๢cøòä•?~÷»{™'‹ïä&¼ÿý˜¸Ÿ\~í7_Ž9Ò‰ˆz<ðÚån<þË¿úBNß¹ÆËGyõát¢qô|ãåÙåó‹8YýŒã%ßš·Ì“/òŽ}·u |ÒÁuÝä"qÕé¦NzÍaêë-]£¶½n ÎÁß|ád‘ŠzÚȩ™ã{mg4©aÂ~ 6&¦ØÎÑö· I»lsû‚Mæó óÚò9gò*˜ò¯ÕoÇi)Çè‘~‚´):B¯ö')‘Žü$>NÔÇö8Lx:! nÚÄÔ¶[.Ì&H2²zI×ZD˜ ºÉ®>Úzñ\eGNi:FG«oém~g› ½ÏØ Ùy‚©‘¦Ž;'âž ›¶àãÉôsžÿ+¼)ïÄrú³÷÷?íÏì-~W²òÿ‹<Ëçx}ñ­.Z~ë·_Ús9Wq{ï¥<ôÔŸûϽ¸á¶,мïýï_.㛹ÚzI¿Êþtr®yÅW—Û³™ ÏÍø5NwoúƒWàrb}üqd?ñ8Ç"¼þO|ª'> (ý`´;qŽe¯ÈÏ »qeÇbJ•U¤¶mŸÂSé‹?zØxˆcêÒ!Zk¬künÏH¨a ;ûO›òšŸ¯Hö`ÝêÛW¥ÞIÈ.™ G•0³9xöJ³Ýd©’ÝiÆ6Ñ•Á!.ûÂ@8û¸¼×^ôoÈ€Æ^X™þ$W!xmy®ã§U«PßS΃æÄ¬éü (|¥9ÆoÂÊÚ4•ÓÐë°ú v¤Tã…6Žn«;2kN$Ò€ý¶YçvS{šD±ÙûÕý n'ðMþ™\;¹9ÌDÜ'ò_þòWô£Hw¿ëÝhŸÿ‚_é;2Ïd0|Åk^»üíG?œI÷ï5>úQ_Ù ˜o¾ð¾ÜÛðþsÞóÁ¾Ë.»w÷Ïzùÿb.Õ9Pøö—óöá?“erÖ§þ? ?òjr ì{¸÷#Èá?NÞ}'û ùA'¼Wþ€{‹ŸúÓ?×+û¾îñkçëC}ýà]ît‡åi?ÿLîáåu‚¼ZÌç |ë‡u·æ¢‚›Iã@˜hw»){î©wð؇~ŒFOöá«ÀšÀ“°ƒLƒ&æ¼c(4¹Úœ„“ DC"ÚD¢ÁäXàIEB»,ê òðÓˆãžã#çOÙÀŒÞŠ#ÕÍk?‚PÃ_o«›Xןme¥ûø42Å–æâSy“ßf“æÿÛoµöµ—®ú"®•ÉÁAß{b9¿Ð:õ ê­aMlð‰“yïõ·Ž¸ù{ç3™õ¤Ô•N'†ï`EørnõðDÖ˸÷Ä×ÍÉe“*nN#È&yæ¾ZÕ|9ás²6«9&áöºkùQ,–õM4¨ž[ (`ØO¥’IS HÍ·†y¢þ{ôá[sÿûý¸ç=òžÞôEw¾S·jCizÿ»W½ù»ÜN剺«„·ç>ÛÎç¤Î«{ÈÉ—'þsÒàï”Ü:þƒ¯#þ3žÛx዇“¾S䛋ÒÑ7Ü’ûñ]aïjè'~þFÀ_q…÷÷ø2„NrhëÄÚmbáø©ãÕoí¯|íë99:^~òýãð‡oéÄf~'Eb3âKŒ7 Ðø1^¼5H:Æ‹1b jOO}Å<¼”O½;ÁÅ_­ý[/}ysìËEßg!ÏÛ‚]ÜñÇCõ³'ÍÚÁö3ëÞÿ±·zÛ?O7Û³ŸâKã¯ÀÆã5ÖNjî݉#pëÓ.íE6íæå°Ï·ýpN’¡¿XBÌØ1—{¼AKÉ£ògáÐlÌXøÆpìjì“ÞÞ㢑m`ql|o<=¶AIhP'ƒñ-)×B»ýËM0dódh&Áê@ÊV½L.Ûm²ò¨I½«qų£Ot”MyÖ2`2©¨L›Œ U“ëšC1ÛÐ[J¤@˜ü'?2J:8žÖž]ˆGàó—hÀõzõyò76”°UÊ–ýr~É$~<¼çrˆƒÄà•±b}¦›ƒçó~å×[©’þ嬜]B‡R?Ôç°Âéí?þ.€«¹=ÿE¿½\È@z+ܹ#¯îr²ç ~æ?ÿBµ9¸ú:D¾ÛÜúV ÜO{Æ/6à9sÒïÀéæ ¿Ãí/Ó›Y¡›íªž¼}¸Ry\|æs~¹‡çþò£[~ð_ÿh¨—ÖM ¯á~_íò¥¬Ì>î1_½¼è·^ÂCËïèy‚Á;º])|÷æúc?Oaeñ¶ÜÏ«±¯b²àÛH\qð£¶ÏÒ¦3Ù%õ!«Ë8 Ø fûRÃ@oOíç|ueLÛôëЊ®•fVâˆä|Ñy L~± ì&€‡çxÙO1ìË…’܈#i!èÈ4(CXw»,DÆ.ƒ[öPDèÙyM,8¡Á§“!ŽÕêæÜùŒ=¥1^ÝœÌ:a7†mØÛæ âG<'žn•<ÐÊËë/¼ú››ðÛ=ÿFŸyj¿9¿Ô­ÁF= ÐqÚˆ„ÿ])2"ÔÉÖÇSžcËê³}¶“‰!pãß%O’¡t}½å£ùÞ•ÿlwª÷x?ÿ×£7íx<«-ØP»BÎ>í$Ñ|à¦Ìæ–Ur>ñÖœüpî}ÀùŠwþQ ¾6ÔÅ„½·-ýú‹^œýUt7:þ@àE·¸°~™«dQû6ˆC‡ªæã éA2v…÷Cc2I,@ÔsO[“ˆê§,ù77MN£@m0y“€Yx“•õÒW2éùE]ƒýjcå/ÞQh+"'øÄ´@&‰%TÞNŠ6~¡$YÉ_z£ëØ–”7þ‚·Ï“žÈéLÚÉÇô å´ïïôúŒòû«ínÞ=àI‚/èPGûŠcÜm»·M|ûU'ë o¶ØÚÏ”ý¦·þ×/†Í¬ëOŽq¬v°l|ló=åWçOÌ¥°ü©¾·ØªØ"0ô³¶3H&—Jk*A'îÖþÆ¡#4Û&þÛ$¡p×r­NU#_?Ã^RŽ^_Ф$;Q·ö YmÏÓ ¼}\yíðq.$U6ma°µÍ‚­ ´ÛŸ½]ºÄ¢}Ù:u–¦©MYZ„ÍHrtÛ‘®£1ÚØ]}ºšñ»}HÐ#ŸIw°øù´•%H61âz@ kI]ô;à wš·ú ʱòu2ä%Š¶ï® ªÌWúš§4€Ï1TèÌŒ0b¬˜ŸñŽóîžÛ&F·¿äè¼}BJçåò>Òküü±-ïÃ}åyâ`çœ÷i çÐIyªŸ•.W¶.rB„ðÛû¶]55¨ ”U×½üeéI†+|6ŸÏ%tÏø{†Ès'¬t’~ðèÁ.#š|»‹I¢dB'ñvLÇ_ö¹ƒ‹¾à"Q{Ï»—וÁW‰Îd⽯]ýÕGóÆ\~ŸÅ¦Of#ÈàãDódÉ™À¢ÉO~†‘˜¼3áOQá¯-c6+hvg…8Sׄ4‹và6$él•U þ'íT6‰vvèò1Ðݸk‘–´=²®È¥Â˜sd§>Þr³sñ°,LÂÆjrJøfÞ”i›X"*¾Þ±P²îo·íTXm³UhšmÛKײ[ö*ÙšäfÛÚÖÛm§t¬~)ÎÖ¤i­÷9šÓR²Ú¾ÚÔ‰„”mÔF¨‘¼ÔÄtóšÏÄ;j©¨ì7ÖGl6;OÖcþì{¯ŒòÜŠ±ÁUy&}!˜¾Ê=&F‹pæÆ%²ïŠñ4ÙÖ" Ü9±„[ îú—ý7yËÃ?i¹Å¬ê•_ABõÎ*`<8húÈ9§¦æÊ´ ´%2ÑG›´ëÙ2³l³>Uˆ‘q{óÏĬ± ¬cáúà=ÜïGÙ•cå“„UgÚv6ó t¶[Ùíç>¿#<àÁ{uOQd§U”ÕÌ’jÊ-NÖ7éOø8!k·PIDÌ&÷öç¹[C{é­ä§¹IßÍçsŠÎd“veR?ö-R(>Öe­¿Èpµg×Wµ"š¯UT|ùá!<3è, žœ?Ë­ËÏàÊ«‰‘7dð*ÀLÄÿøÝ²üØ?/oòaI··t;“×@;4¥¥.uöIJÇLl;°”½J´Ñ<Ém{Åó²_$M”ºuÚ%Ž[]âdàÇò§—sOî¸ßXú—s¯2{©~ã7m š«ÒÓîŸõ–^I7tŒJþ•i6ôi ¥“c/k礃•y{…V>ƒg:á€HOÄN¬‰ž:¡ÑáW(?b)EÌC Hã¹¼#Ú½bÙîÅçx¨´ík§°ß„†XQƒþ >ÀY^©‹ã‰6tÝ) ÿÉL›¤í”gʆ8£Ûîî3-û°öÖ©ó¶í)nU7ß^at¾;>%Ë&©ø¾*ÇùßUÐÓöEqô7ý­•ÅÏÀ¯Nð½•ï^÷¸E÷9ù8·çŠ" ­Of«­­ýv <Ê¿nÅeßßoC9rkd/ìiNìÅ€T!žÝö·î?Œ~¦ÿ¨F\@IDAT0{á?'ñAÌÉ­?fi?Ì¿/ÿèw|;™aËÀQo·Æ{c\Œ°Óââ´Ä. TFðe.{}ŒŠ¥¬æ€*«¹(”ú }€¿V6gôž´„¥¹«e;Aes^ù”dà½Ëüçm5¼«ô3Ÿ ÍÀc+}Ç qå¥!ÊbÚÅ¢ ÂHµÉ8ë•)jµ‰ $õt5÷*”i“Š6c­UÜ”kò‚!:ñ A´°âHatËV² c©+ ´ûo]•ð Ê: [_Þ½Ÿ)ÑmN8¤vfnª£^Û¶§¸·ºæ½mVlÇÛþÆhlugÄ^Aù8i-ÎŒ!þ&f,ÓlÍ5©°Î=ÿõ«Ö<.€\co‚Æø~|‹-+üpõáuä×´€›`¬²Ž Ò\ãNÉì+𳡷žX¿¬qÙYoÐã+)ó‹ó¹ÇT!öÙ+;(¡Ä±‡Mbßz¤!^uÃCCUe‡Ü‘]<ê³âK`t|`!ºåe“ß|¦~äI° ýŒ£c‡™ì‡‘ØÉ¿Ì72Ifìê‚dt{úB£T˜,øÆ/ úOàÐhpK>s‚jÇ1é Ï9‘ň\;‹ð7 B s•‚Jƒ Ô)£RŒf” ~¸¾Ê@,ÂÙíæ¶À¬Xê1ý:ñQÜ3Æ!læsïÆÎ„¸­þ;PÍ Ð§ë\p¹Z·¾<‚ȰCÞ€úté$Í'ù2¥}SôV}öQš¸ý¯zs%f\[û¢.¦.[—1\YN“«lvZ}s·{|pYlH=À¼Ñˆ\´°[¦Û,ý0A!'Ptò\2‘kØ Êa@ófÛÓd,Ÿk7åÛ‚| îŒß¼<ˆ¼·¹˜·‰,¾QdÆÉ¿[6«ô¹ÿ*ˆðVA„·”£äLYgòO$ RÌÈŽÀš>¹v›hÛ‚»ÀµŠ:ãÀ±3wùÈjè+-yZld¶2gQ;Q ÇÎjƒr­ñ䈢Œâ ‘“Ÿvå^«ªóXü†Þ•_g· žuÐpG$8ûuó[`wrÌ„ÄD¥L¤fR&†¦¼ B‚l‘´M*\€˜¬úéê´7vËÆÊñéÒùTp»´oòSµß8ÖµôÇ&‚ôãù§šsôçºw ·?÷7“ /³ ZÈ[{Ÿ¼¹ b†‡8­Bâ´îO-L|®á ièQ4CXŸ âÅÄ+‡BÈ¢Lq5Ï ³\JÈu¥©Ê1°J#ÕŸæ°$9ûÖI·9¸@å%Øh–ô¦­‚>²t%Eû1ÔÕ ­rVFЄ—$ö–žý§·+í¢èâ&BFzåÁ‰Q-—q’4'J ÝÎ à|Ö …->Š-êÝ»Yoß=ã™9a.¦§ÇõÅðÆ_ šÄ¯±Q¤ ÙüW6Îí[ÝögÃÎFDs(÷â’Øk%ZÅÕ³U: 4¾âÙÇÙ’‡ïM&÷öyó»Ú;Yã¸îL¯ûe Á™Rî®°FmWÓÈ>¾¼Ã®SÏÏñÏÍy¸HSîgŒÿy`¶C² VG´;ü "KïNÙÉ] óØá¿p1Žˆ¬õCS‰ßŽg·¦søgoô8wCӳǵ\ÁviæÏËðNêŒ!ï÷¶c7É#Pg¥`³r†“XóEç8Dâ±Ì MJš¸¶Á«,ß"4SÁ V€³Ûac® ƒ_fâ†?%¶<µÆ µ´[á­ z›X¬‘wFèõÿw!¦¿âúcŒ¦><@¿uÚ™€Û}moËQë-€çÌCðó™]¯6‘0O„3¹GšB˜ÌCŽq±2gQ«[y¸§–b¹#|sžcIÕÑ+åYŠžòr¥™¿èQç`è­ò²bH](áøØ†LJW~ó*'L]©ŸÕMÕ¶MX)ˇro¢á¸òE×B%˜™¨o:¡ €æ¡3Ƭ<üÍíÖ;)°zîù¥ž«b«Ý9”‡°à W•y™¸76“„q Œ²¼(FdÞ¾$ ìY1@ºöÓ‘Wà³Û™`ýnÌu‚‡O O,êÎZósý 'nÂÐq`Üó±_{r_ N°Ï8>1b­³¸Cï^ã*†LATAsž©hj!~ìßM¨ƒžV?ÏXK.Š´;7qs…Ü­îe¬ c [gLRô¨+ŒuúÑM•"á|ȹR´é_ 9´WÈl±wî±ðìW†²°ÈáD•—‹€9Ĩ+}blùMþb— ÐÙ:LûÈ7x£¿R #eÆÄ:ÖÚ'š$+ÜpÝü¡¯Nº`í DYg˜vPBÀº{OFèÌç{¿Iþùæó¹¢¿WÞ½åÏý]:úgóE¾âÀc?=-¸`gÐ÷¶%Õ8—cƒ@/E“Ì mË^ìµu+¬Ì¤0ƒ„C«‚r‰Âݺ{`OômóKxymŠ$­ÆY¿ö'Ç.yœ¦ÇUE9$-v©`y*Ÿc©4}@säâX~g·3Ãkìì¸Dç®ûñ(1«?‹'4f#Aø"©ç÷frFù¬_Ï —&…îÉ©ܦcÓçá>}h/us¢9‰Õ‡÷À¡Nwq`\½öi1Œ ÚüŸÀ È/MêlpÜ3?LL8$*'áÉ"…õƒÉ‹üË;>]žƒ˜*“@³+LìC¥v&"N3Ì©MM"Jªìp\s™íL®·@…žôÕ¡ÓÅSêU‘“Yz Pª”}hx[ÏÉ&Nà ¥ðkÐGÐrwøÒ•u\1o¢€¾#ÏȰ²©N[y Áð”•2Æ’«ÚJû¾ú7ùÉ0ãÑø‚¯uW '˜®þÇSµÎng†ô‹¾5^òb™b'}\<:LÛ7¤ÿä}qŠiëø'&f|µÿoÆ(´üP1+íÓ¿=>å ¢4h7váàÛL Œ¥y^FX¥=$‰§!`üY4kDÐ>'Œô ɓÓ -å¨Û×)_z ;õ ÜÉŠÉeí»öÿô• Òc·Ú~ˆ2O¿N:ÀõÍI>4}D<L²ÎšøRŸ>Q5á “ˆ"ð¥íæ_9ìgÔZæïÔ\N¹6*ê0¶Wþt¢Þ?eöx+G¥'i¶"•BúÍ +_Øx&#£Ng·3Ãö™ ýä'ïzRÛæn;ã·B·Û™DZÕÇÓú|6 ‰ëoÍæ~¤>¯D1^ }š"2:DZzæÀ€”¬tèþÒ¦ôM n¡2ÑšœÆšÃ®^§±¥Vaˆ¸®СŽ_wœÙ:±>wºk•6Pg·›ÙÆä¬ào&jãa’]«¬ÄƒÉvêýÿ žÌ–Ñ‘÷¸­ÇàzÛ‚žcÎHÚ79ì‡r¦ïZ”w²vw¾¤<.[¨7GÎÓäŒö±NBQŸú2ºÊkºÜh aT¡âõm'ç ÞÌ›¤/¯ÄˆnwgxâB}Ãô —â<~?£Wc8Èy¢Òìò’ßÙíf´nœÀ)ÄØûCÖç_¾f@4Œ }Û€l`ÐÕãÌ™€Ñ9 Ħ2`ìâ°&üèB_Jò‰¢ÌWZ–¤wä¤?™dRh!ÔAê´ƒ‚åÙ$>ÇMþ¨\s@ d#ˆÀŽìÆc}žýÙKÐcÉ3éÛ•†ãÇNò œþ¼éj’ÓD«—pÉ/惫X3úŒö&2&g'g’GG–`NóúcªCùªŽJ³«\]=ôù­|Kr l“o{n“|;2®wP6§”ƒˆ#!ÿÇʉ:*'óÁn“`ŠñÖÙÂä” v?f£Ä¸f⑦ôZô&­+é³ò^ ò¬kX6ÅMÚ,B“#Ù¨wÝd­=: Î-~ĺäa߀­¼E4_Ó§0Þm›<|MáLŒj¢lÞU*2i9zà¹Di_IPð!ÀÇÁÜ?ÕÆÅ4ONõ²rô´J]™Ž8‘¾-ì‹BM¥tÜ„•@ò »8½Ú{9°³_g€ôí‰þž'jzÐØ`‡ W•¿Û asüjßœèÐÛÄÁYÿ²SÔ6“p[‹ãšÏt”húàt"9­t# UÁ­…ž“ÿ9ÑŸ1À<1TÖüp2Ê;> ÐiÄVœ¸Ø$ƒ Œƒðì_³¥žè .Š®t tP¾ÈýlÛÖGìs¢1{Å'Æ©o%}9”Ateô´^Ú] rz–º®¬„ pNÂbÍ•¼]Ywc °Ñ•oio¡ÎJ6ÄiÇPÛ+G;ÑOYÑ£ç€î5 V]ÌÄð—L1°<»1Ðy'ùyvWâ8Rpéh½dìZ˜ÁÔ¨2`‹®ú§á'@!A`sñd™;"ÁIÕÀ¯t€› òxê(T>ÍÙ°¢Ð6ŠÑ†fgÄOø†Y`zЈ*-Èzû®ÌF†iÓ·ÛL¼{•‰Ø4ù4ÑgïU@it%Ê86å©’ O£ÅZÜ~Qì«—ÁÀ‰—ÀÛO„«Ö®Ò°Ö’ˆ+xù@þ¶ Áí9–S„šðA ‹~›\ðÐ~"ÉZ§œÃHA¡ØÇqEª‰|lëµC—öNRh"=WÑ’E?µ%ü”)Å´5eñ3€æ«iËØšêƒT{.#Á¹”O­Â…‹ù:{œ­v,òù¶Œê xõ÷IŸ"ò¸@“ãtÎí²sN_ƒ×YGr_« 9Ë콌mÙUµ¢£ 6w9Šê§á¥BÐ6 ™ Š0Ÿ­‡o}+¶ Ä‘]uPp\ °¥:WCÓf\’D«¤NW:¼\{õõ >@ ¶kǤy@?Å^8·•úÜÈñÖ°ÁíßßTûV¿SøŸ n?Þþã «ß¼Õoû›jß_¿ïßï¥cÙM¿'®<]5'§Ï#޼¸¹¶Z0‰âWãÍéF®uG6òA¾á8?ÿqíÕ'–ó/ô6 ‰AQ¥¿í¥èö©Žj÷{?üÖ²·þÆÊ{ëÄÙ{lÙí“É·ÁßÔ~(ÜîVç~ÃÛênêø¦ê÷ãÝÜV¿íwð¬@Šk®>ÎÉÙ¹ü²÷¢ÚWíÙhÎ÷º’7,×—«':ºž=çè“R|Íðç` qP¶ÞªKÚ²§…*±ç„‚$b=”p‡iÞ’!¼-!i0Wfs¢Í4Ý<ýU#y#HùH%"¼ÖAÔ… OƒdhŠ•ˆ“ ”%p™ÙÜûAέœÀY‚TÄÇcè–^)ÍÊáØ‰eðáÁ6øòZÑ©ˆVÂ@¹”£«j  '2’ÈètÌ‹˜+Ž{Ç–æ/Õ䎟àÙë®å×Ì`Ïelt5îÞµ>0†ˆcøDü-Æ2Žžñ~|ÕX Uýæü"<_ÕΟìfŒ_8¨àï$!,ÚÚ|99ðЈ¡ßÌètbi´¥ÊŸ‡8ôؼáM2=Ì Tp}Û%•^ëñ,ЯÅãÓ Ht¡:Lÿ1ÌE7'Ä— ûFÁmŽÃ±Ü•‰*»å”­CîÞ ½®ž¬Bë&ÍÙ7ÒÓ™VŠ«&À)‘|·9™:—¨‘ùGI€²"{Ä2Ó`›…؆ôÔÑA F¶Qoþ|öRûºœÁ0Éížcמ䵜ƒ¸ÝÖaó ¶³Ç70ÇçÕ>ÚŸžf%êØu'™0bl¡cç#_¹ãØ€H'\ Ù Èu¸ƒ¡À‡Ð¢ÍP˜€˜À·#‹¹ÑßcköÔDuÖ¶BcåH0’€x²³ÔÁ¨s ã{¨5ÒÑd@FÿˆÒºª!ÿm¢ïÊÆ)î3v¢x”ßd:Ðê× .ëµxSû rk¿©ãýõü¶¿©ö­~ÿ~ÃÛöûÛ·ã­ýÓÝïÇÛ¼ŸÎMµï¯ßŽ÷ï7zÖï”ñÏ ®L]Ëä9ç¹ÃÉn ™‚Aa0àõV:= þJp4¹ éÄîС#Ä÷qb›_üîA2#e¶m¿îÔßÔñV¿í÷ãßXý^˜­¼í?]øýpþMí÷ÃoÇÛ~ÃûTÇÿ¥pþ¶ßáGÅõŒÇ®ÿt뉾ã£?û_'¾MÎýuEšf¢p‚:‘t+Çl>§Þñ¾<$Cóƒ1²Nd×*kÆß$¹=Æ,a@-mÿ ãæyHƒ¨t‰)oµqâìÄF"{ñ­rS¾™wLá\r–!;9 €N^4€ ?aäM‰odR?™øm{³-h#Tò‚7,q€ èt‚^úÌŒ-Ç_';èÅq‹‹Ê¢ÛN?Ã&\«_5²œl@êI"x§ÀHAùCÛI°AnnARŸžå^ºçñkÛÇ®wœ8¶œwáÜjÕOº}ªöýÈûá?ÝãýpÝ­~ÛßTýÖ¾í7¸m¿¿~ÿñwSû ~Ûop7u¼Õª½þ³Ÿ^ûq®Ò±Hf?Ósž8†žfѰ(äÀ¿m’®Çƒ¿[€òDÕx;‡“ä™6BHŒCc†¯µÊÝ!4dBYÚ¾ÒÒÒî¬Çõ¬±4yz¶ ,­NÃÇ«ŽÊè”é«’–·qÒª¬è晽ý ¼N\„W€bÐj.dm:@Ÿ6iÊRŠYð`ä¤?ö‚„Vû‡x³©7Ç®¨'éJ¯öƒÁ4|Ð_×f]/úe|0ÇBs²Ïd\½…Ï­%"ÏÉ ˜T–óVPSÇÚ£Ù«ˆráEŤ¤ÿÊS2ã^ÀÁÔ_£é&WãŽó0ÞµN,çïÃ+Wvg·›ÏvïÁ=Æ*é!Þ”b‡+`ñ›É¼ ç6Á²®mœn§ĸןVãÁ†ë$}tnÕYƒCšâGBnhS\š»"Q4š8¢IpÂ,øÕl‰4Ùhh‚8¼×J8¾¤GÍZXÛê<#¿á³*W”‰âyœ½RÆ]ù$³É:%k,Åahï9¶Í–ÑÆ#·] ½<bíÅêBo”¶š þ†û½¸[ËþºÂFq/œå©ß/ë&ÙÖ¾ 9øÕê½Ë{?½½ðÓ¶AO'ùõ[ãr9ÍäÿȈjì$N…Ô?{ySZóºCrÏ!Nlyøº]·œ8+<‡™À™(7ÔöçTvpCù­ÚazàÛ¨nXãK7{÷âþ¶ýõCgƒR’ÝòFËšÙ¶¶ÙïÊwÃøÚ…µ´q´¼áß°¼ÑÙ43.÷–¥10âýõí·œ:ÁUÇcÜúqð0÷ÍÚ‚ÉŽSÍ ¬ 0Ö3h[¹m:XÙ÷½5ÆÔà|´A´ °zÚ[¯Õ0P7ƒ6rBà$u`.WÌÇ2 À™˜Gœ„8ÉæÄWZ•¶H{¦èh Rá$¡•EÚ< éä:æM‡ÑM._GèÈØÝà•½ü¬õ‰EÍH¡é Š Zº*/ÿšÝ8Š OuLv•>«‚wzgb¨˜ÒàÏöíÁCV”î¬öK‘cè ?/‚ˆã ³Ê€‚4EI94€j -åX¥£ h;D_½þú>·£>/ $Ü|ôI·•O0ûËi·Ò@˽¾GÙ{jj"·ÂN9U*n\6û[öJ<0…mCŽ»ø[»ûËÞºÝòH9ú|29ôél{¥Žû[NÑ1NÇÇÏ]³ˆrà «ôLßÜ:kŸd2o ÏØÇÈqÎÐ‹Ž Ås¥L)dµØOóª%7àÔ[P`[ð8ámÆK6÷Š.=6tDHw@T§ËçÐÐ;ö!ÉÍäd’Êr+”‡ïèŽøcX°á@ÂP¯¼D1ÿÙÎ÷ó%2­t•«Mx É|·~íñQ6Èf”´7òô€•ygé²I¤õ%‚øÁœqÀ+½Ç8SOöó*M€ð:ÅS˜¾Úlä×2“¤D“´«¶^ 8ɳ>@Š\yÿÂ`Mæ&à,!òpä8äN°-ÊÛ4‚„ô3 6fyÚfª65T³ u ùßèX›ì«Üÿ+õÕŠâÌê–\‡§2ÍÄ.!vÚå­ømêD{“/öýÂe²N ›±}Á­_YÖƒ‡EŒlÇëûFa]—b¡Ñ>ÌX½Úx˜É^cƒˆ­è ñ€¨÷Éî¬Ø‘â¹\Iö!6Y®W⓳Ø6¬b Pƒ_Œ×¿Ž3Öz55@ê)»žæV‰"Ã3®Z!F,äAÙ¾eqt°mµ][üŒ$ûVÊPQ§^bc• 39 <à@_†X :Ñ_éä×ÀW8ùJ•+PÖ¾èßôgsFˆJCY™À¤NY½B±3A“âš«mßd|a'w’ Q¥½~ÄOö³ÆakDþhäÃàÜvšƼþ¯úèóUNQÅß¾µ)ÎuWð;õRù£ì-¼c ¼ò Šé¸¶8‡íÊd¤ ¬6Wµ³Å^X¡/Œï€'z͈6›¥oÑv>ó<Ó2ÜÑM*žh/¥ÑCÝ(eXå±Mèu d«^[±)(h!Žƒ“0@H‡ ø!1ÇBið̾<ÄB˜Ï^ÍdjýÞEÑ:tå'9èùc|–[€cîÖ9õó°¾´€‚ùÈUK¼|ÓÐ>û⑊­6âLEiŸ¹€uâóíX!Ãel£=W]l×ç|FUåZ}ºö…¦W¢9m#Æjkê':o íø‚kê0vLü“1cÜ$ìØX¿3ŽW= V¿+”öt¨•„_ðÈzÊßåjÔ"=wàULOþ¡Ó¬~@ú‰²™[”ׇ€K^g0]™ð™\]œA˜[NxàR9vO‰?wXOQv¶‘t§]”ÝÖÞ¥ «¶åÆåá9nŒÖжb—RƒgG[½ ¥ëF!V1âhÂ4@¦ ÉÚ‹PWº‘‰Rgý­&„Z†*(Cä|Æ®;œg“×@pâå ë)î»<È œ«ßLð+¸VÆHÐ&(­g[›)­:´•ÆæSß·“9 s‹†¶ÒÞ&‚¡5£³%Éj­rc/¯ øRÿ”Ï•4ë}øÅ7ÀÈ×Ô3gÅr°•Êö´e#p£#¼‚¥²Uë}ˆ<·BÑ¥aâX“åæyù„Kî²YVn&:l;Ž虹¢h<ËN<´NŽÕI‹à’ØúBzNEõê±s™ÝIFvµM±©s¯q¤ýlŠTT&üƒ8IsæÃ<„w‚Ë'YÍT )©²Í*å–Å…Àš‹ ã¬ôMDÔ¬ÌÓ©$:ôLŠÊ^þk˜Z“l+$Èfœ˜Ä¬vS¿sûã×3§êúã\UüøñåV·:º=z$ÙÅ‘¾†³æá÷ éøÐ˜«>Úƒ„O(¯ð[)KæÀ˜Ð€W¿ÇGÓfþÔ£ 9UŸ„¾ÍóÀÖo…CÐ,‚=Ô×~é…\›,³¦ZýqÀŽ‘.ÖÇ¢E¤¤YœZ˜-ߨ® ‡pøÓ^Іžq«œc¿¤£~¥.3E Æ\‘7’{do2©SàKQ²¯2¯ˆõsýê±€%ûÇ@Ú4‰µå61ä”oC1ã1À6¢?’§îø‘²œš$ ˆ‡N ÛÅ~«]:Áˆxêg!»®º™ªâÙÌ0.ŸZ€ÉHŸAA™ý•â¾f¾ÄØì4}X¹R@{X&;‰LªŠ;vËÜ‚Aí Ð$¿|3†¡m¶N¬@ÞVHmßÔ)‡² tÞYm‹¥fBDïüÏ|ñZ!È"~ììSÒ¤J9¤˜ŒûO$­>P†UO(eª2´2‘t!æ” üóž¯yÅ÷ÄÅ# ÒTiRŠ)Cs;׸ö6[4áçxÚÐÃBC˜6pûÂfÁ ¯0~檢đh­/½iÎë§b>4&_L.Ür†D•³þ©½ˆ³ kß‘ÏÈ?²5&`V°mT.2ÐѲò/hÀÅöÔû%Qìë£WÕ5wÕ Ð®©’€@ÊÜ)Ý9äC_ºPÌÔ¦gáß’·ÔʲlpŠ1q•xÿr“CænA㡱á=‘n^ûi×ý›±%–>ŸÌ©H«ßöðuž-¹ÆF…~Ä éFý,@  åhOiâvxI_bŽ ’Ê'ŸmêÉ1[»Æ«©—©•|¸(ÍNXBPûoDE_Am_h³èVä¬þü‹.Š£<Ù–¢2×uñhVwLО¸ºS¨ñï*ôˆ£Ï†m¶’)¼{ûQ>óP]h`×/zPž[–”ŸzlÄ9¨z \FjÕôÔI.#*P‰¢ ç ‹ò¡ãËî»å ¾àèrŒÂ=PÇ|b@ ÕbuW7¶Ô’æúWçÇÈÙBÿ8HH\Q«᩟ròQtl`Ú(J?{< ¾Š$oj"‡8à]wõ±åÎ_xëåŽwºt¹æš«—÷¿ïƒô'ÙBOáV9Ãb±’DXއÙTT–ÊJ¤j~­n+ŽÌ¬ùF[Žl‚(¿ßÑ…ŸýÃ>Ì6Qc¾6ºÙ©Z¿¨ÓnZp&¸ ?Ì2°Ð¥áÝm¤þÌ>Ò—Æ Œ½•K{Û¦ÌòadlHØámá «yÒpNÒÕµÂØ@øÎÎI~‘Q}'¬_k4z@y¶‘Ëœ;q&w) a•nQ-BtÄ›h*ä–é@ÚÌñ",ö󭳿•#ÆqŽÚÜÛ·cšÈ7Œy倉3¥ƒl¶Ü½Úã>à”Kîà˜ \ÈÕÇ|Ú0R_3­zf1( ζå.岊*ZŽðÛ/öõ<ÆÂ¤'s;–@0PL ›Ä/ÊÔz‚k¦L,aT2xq€…®¼WËjIYULDãÑi…C1} é Ïm2=1!Ìš›‡I´²Eô5“Mm.³°Ó“‚Á¶ úêe ‚5?I$¹û,ôÓz p…¯52“®üùÌx)%€øŸIáPuóAôŒedÑ7]A‹¾TEà›“iÇ.¹¶YdÓ¾ï>¾²W]‘ÒE_q̧16Tå¤<Îá·\ØJ*¤7b£—ôªSfm%S?è‘ÌÉQAhš¬H»¡e s©n« ÕEØ!FJ÷|Ž £ºh‚?öQ>t¦TÒ"~¹Àü³¢KÊPü[R6¸¹FÊÝPu4€äªsëdF eE ¬¿¬Ëô*Ge«"’TH3NP4@4ÞEY8È[G «¾¶ObÐ, Ñ6?²›]2P®¹†※Åç7q—@Fn{ß²&îÁ*õæ£h£;¡\áõUð'DÑ„¬T‹3)nbÁu£[pê=‘ -Œª&[Ô÷ UhâX8ýO2rÓ ¾Ö ’Ž©ýO‘ ¢«àòÈ&Øy·¤ª,c'&– 9¡²#¹$ Åtk±ÑŠ:8-d"t_0‡!ŒÒŒ¯´ymê§ÌÚ;ÕŠúÓÄX"rlà%O«ÀG=­*OÇHhM»l +˜<ÜTÌÍcmÃq×:ÎÔæê»É¦dÀµr£N€i'¥ g|ýòþÑ¿<ìa^Žðl€ÉæÉ?üËÏýÜ3–Ç?þñ à0â€OȪviwPì3‘#?bG¦øT9(e¸dJðVÅn+töÅßbS<Ú5Îv+’ƒ›òë$qµ½¸îl€¯ÊXBLùBfîQõ‰ºEévUÔ+FÆ][¶iŽÍ «?<÷^r'Z‡û°;S4hôjT ´¦áòb<òÍP‰µ´•[OµbVtR׊ãNÝÇ^}ͱð‰–ƒ9ü”¶ê€9%Ð~g“Ú´ ÇToÁ}7_ëÊ“úD+:2ÆSê$-jƒÄ*Êc¿(N—|ìo°â’°MX¢¥l#÷¸rOÌÈCz#NÜܧ7µ•%À'î¤è·{³neHÙÔd]ýÔ Cm½¥ä®ýj¡Öxd5PðºPWH¿5ÍLÍ,.Q¥m’™<Щ û$hÐç#L»öP®­Mºàé×M‡émJäAˆ.ÊV®°ÚVýdö®* úQg.˜v>âÇ; ß××´‘c€oú_qÅ3^}í±åÅ/yï wj¹ç=o¹|Ñ]LßàŠüc l~ÈÞÒ bm+^2>Ú^¹00þÍES¸'†5ùFŸ-^bB½êY'Œ<šdEpý§}¥SŸã(;"l|VvÄ„þ44¼5Gšþå_øL´MádÜâ¨Lˆ!!„‰Š|Ýäe3_U nêk/ÿ$Ø„[À͆Á„zU–®t¶/êWÿöš]'pÀÏI$R Z“hjÛDf3ÖìëŽ%³>c" ªGfëÝz³Åñ£&y9™ÿÐøæŠ" ^ 0ÞïTL'¨lQÅGÀûQÝÔ–<Ä#Ž—Š!Íú ¨3Ð3ðGùG)8äÑ`lÊÛĚìG{ïÛ׈Ú.yG×l-mjg\If&ê€sœ]V‰Ç”Fޱ™4iR=á࡬Æ%µæ[”–½ò•‡œÇ<ߎ{El¢àd7&nqñkD•p1.A˜*Œ[ƒOÊÆŽÚøž3Lé«‚>«;ê)M1‡fè `lCý¼ùEŒŒޓޫ?~ÝrŸ{ß%¤+ÞñÞå‚óÏ_Žs£U älõ OòÔH‡¬3y^M¥ó³i2ý}Y*õÅ!¼•²û_•ÕPÈNÎ$5ÍïÙzT5~úOqõ´ÕA1DíiÍ„&—·ŠãJiË™$€Ì%…|“dª‡\T’m«ØKŒmt<ßÉ.–Z„E£6ªc$³íÆË ë‰ÃÂꂜãeT.k¥%wÊì :c¥À24µW*å(ÕìÏ—¶3r4-¾ È€tEÜ8Ñ+Uê³Mæ›@Û´Ò–àøD&C+Íh×¶’™b—wIîÀxKÀ$MóƒR©Õª³åNžµ4ê\€„¯ß­•”¶ ÉkCõàÈø¡GLx)Œ^Ú\ú +_—ßýÝ÷-ÿäû¿tyøÃ²|ó7=~yÛÛ®X~ùy¿½üÉ{þb¹àÜ3Ï•€bZþòW¾f»º#­l©OPä œëÉ4èʤOVôã_i›0RÚVFh–e]uÃo&^}¨½D¶/.çœ\Þþö?Zûد\.¾ø–ËûÞÿåÞ÷¹ÇòoþÍ?_~ã7_½¼þµXnq‹Ë—ÞûÖªüFÓܲ32K¾“ xÏê,õøCšù[¹Àe¹HƒÃJVʪØŽ¿ñ+¾&‹¹s`pÊí‰é@LAšÆ$DgW% õ*ÍïÒ¯Ý~Lål©Gj+2J©}kpËnì'’¤gŒØîäGiS^Y8¥£´„ݸËÉ·RœZ.¹ô–Ëþà¯.ÿøûþÏ媫>´¼éoåAµƒËƒüeË'¸­ð_ü«o^žôÝ_Ë€ÓËÛßñ¡åÍo½*Ü£G-ç󜀄Ðç7eM W±©RÞ$Ìò*›q¨@&p© KÙ¤×É:åyüÜv01çÀƒ¤ž_«Nò–œ7ߨ¡“¤'}ÛóµÉžN±?H@„›À !åùä,^¥ƒvÜîôçïûØò¿|ûã—gýâ÷.ùšÿf9zþ‘YÁŽ“*ýW|Êbûƒ‡yQ9\‘®iFûÈȈ«Îa‚ª® Y°X‹~Ò]¿ò7*¡€ ªÖ„xukÁ‚¶úÇ3º:¤y×p‹å¦ÖIU¹Òœ¾¬ü‹1 ,kŠ~ÜÄîÇs„ò@(m1€£‡²Ù·\¿€Ðì³·”Œj*-µÃ«¿£þÁK39Æ(b‰À÷È‘K©µB|ÿ‘Š$dϦPô¥ÉiCé$„\kÜ@È?+µ§WcµImÊfsyƒØ›6Û•‰väë7Ž~”óqìÆôÉ.op( ׳NÖË[ÖQ¹%)Íu¬ <ÛðöþqåslŽg4ðØJo\y %/*éÕ´ãÉ/UTMU¸êyôüÃË{ÿô£ËWüùò•üŠå›Xüx$û“¬ü¿á ï[.à è@e,ÒÜYŽP^dRŸZÙ•+Å Í“™™»à§ä’’q,œ:ŒϼD›),.–·yƒ8;cÐ:Èl1.BpêžßÖèVL•¦=ÿ֦܀e³Õ¾€4F ÇŸ¼“Üäà ։We¯pžÐ+Sôõ§F”<ÙæX”å|“OÄ‚Íâ*\„e"u±ú(‹*ŸÓ唦¶’ò 5ôÔKÒMP]éXVV7s†l¶Æ-ê•NÄèÕ‰làÚÂŽ®Î 7¿+Äå –¦ì"¸p ¦´åÀΈz̳^‡>–©Sw…å;1*bçhr ×-¸>Ÿ©«öÔþÔÏÜ[-Õ_oC?*íä[öÐζ×*–AÝ8¶/¸(9q%¬­@ç Œ¤Àæ„»=ŒíáV˃²"9šdà±A9s q…(*&ÛfÄàIÒ¦‰M¼ÇËbÓÈÚdÊÒ—É@]ÛTÌà?zôðòö+®Zþᓽ<øÁ÷ïIOzäò’¿i¹Ç—Ün¹†È’û­]5…ã¹²Ö×P•ÍSšV'>²¸D¨ –§É‚:3í¸´9PÚà ãI…"š"Åõ–ÙF´ÑÊÐÑIjvÑÙÑšøTs†¦Î4Im<”Qüħl½_®0%²Qge°í^’2™¨ ¶.$w@ØT®Á(7ºI˜Q %$àÁ· ÁKœ6k ‰$¡ƒ°~¤ =E„š­ Îõë„ç@ÛxÂÒ@Ž‚>°79²Øò‚‡¶Vºü™Ü½Àžßd"™Vgðƒ¥M’‘êÊÀÐßAA4`Ô%ܳœ½ìñ´‰ÉdK’ÁB×¾±Ã?Y¡`ÉÚvâÑÐõ¥jL‹jÇŸý ½ï÷e·]^õê·-z%ƒÞùG—ŸýÙg/¿ò‚×.yìj—R´â£ºEmqQßI3y¯›zhNX·¢¼UCZ­˜Õâ±úx°ÙB ü6Îæ8 ‘Í_ ýÚ¯½ÇòÊ—¿cùaný±í™Ï|õrßË.YþŠW}Þõ®wæ$á6\ݸ|ùÎïxƒú)úëë—7¿ó*~lèôrÙ}nË«ˆ9@ÈcÇ8Z­"?7mk)¿3µBýRØt¢‚}ËKÀ{‹†0Nܺ¥ øt/pzÂ8Uöi¦-à±ÚM¾>änÌ{qÓ•j0$}<Á5:Ç>ÉdôpíH =ðð~õw¼ýãì.Oø;ß°|Ã7>®§Ÿÿùç-Ï}Îï-·½Ýs¥ÚÓ‡ ‹^ÒÊ‘×DãÄýÇ¿¹¿žz@•¿â28þÕÇ[þ@K¢Cq!<0®,ªÒœ|Pð˜ upœpE[-ç ^vI­ÛW4­P>p‡ï*¿„ÙZ]Öv´«‘ÆŽÒ~Ôò¯ ÕÒ·”«o‹·‘ñšR!s’òÊÑò+ºU} $þ6€o jœÄå[islî±”)Xîx*5Çèâ`"l±U’˜øL²¡'-àŠR [%jžŒ›DÝJ¬–Õ˜¶xŽÞÞ.ršsfEpñòºÌ¥ÿÍšò•:Ñæßä@G)·<4þ™ …ŠÍ/l7Wm)›$&5õWž"? “¦I9UÀÉ¥PY€:e”DÊq E¯ žâÖÆ÷¾çÃË7|×>ð2òßë»úùÖ·^±|ûÿ=yÄ[€|¦lå“rÊd<£]2«%Uðq"¨ý{ýx›ˆv+G•tO8å€Àøh4²ß¨™tReœnr‚«>Bf“‰ë`ÀMke°´òL…¤Â8•¶&›ü¢¯´»:¹Nf €V3Óf¼­xÚR ›ŽÚbÞà¦>Òܬ¢Ž‚Ê/ØÌ¦8å y æÍk:Z3ßÑ[ÀàSý+l'zºMJnËox$ÇÅ>°â—ºñ¡ÒÔ&Œ9Á¿”µ.>5SW#ÀâÄr• ‹lqi¬]8éÑ*maÌýÆôô÷±¹Ì…Kw:€¿‹¸kÙùÁøËfìàø2VáXëÊ%+É„ƒU6 ¤0#*k·e``ü7gÅ/rT)àâ)3SÒhÈk3šU©T9.h#e öÓ‡HðŒŒ(§]í 5Œ2,3G ÆÓÄ>$ë!ŽÐŽÚ zЛ¿¬&,ÊsÆ,Ždý¢º¿<÷„'|Ýò‹Ïýƒå®´y)³ €Œ@3?I‹ÍücÀénA mE4ÚD±óДÁt¨0¢pþA¥±º›ú•|x]½È>&¡œ8 #u(K\Œ’’rUèÆÔI‚=ÂŽ–ßA((„i[4‡eÀºA»Rиá;ðl… Zè¦{ ¡¤$·t8aw‘»*¼òÒÍ´Qy*8FÅQ–]ÒmÅ;ëPpM­7L€7‰r:Þ6qX%“GƲ´Šo>ê<Ý!{¨£àµOÛ¦’Pc²Ñydi„‚G:`¥*z*iߌŠ|•†e»)ØgÂãÁÄbùÌ _ v1!É È_Ø=¹½àÐríµ×-Ï~Ö¯,o¸ümË•W~dù¹Ÿý'Ë«¸*ðû¯ûãåÒ;\´;áIîf‹-ˆKõ܉1 „,z9»MK,`L(ÔòœÞÄgºI/9Äs³VÙØ7zL4§G œ“€»}ñm–W¾â-¬šZ¾ì¾—2™?±\tñÑåþåS—Kn{áòá_³Üç>÷\n}당ÊñÖåþ6®`»W€óº×¾ØËÿÀã@IDAT]¾èV\ÍãnøóÄ"Çå\…]Ò¶Êë dŠØÉM ö“Ä¥ Hñ•—M‹X¯´—´ìnµZA©we¯ô®Ÿ¸§nú&–á`¬f±qÖYy u‘Áãnü÷ð‡]²ü§ÿôÂåÑ_õ°åîw¿ Ï3]»¼à¯\>ƃԷÇǧ€Ñö麖gBP[Ú“™=ñUZàSÂMJK `lž¬”#‰ íf,lvñ þcL[/] c{Œ65†fßÀØÒ¶½ô†_¢³àSŸ Ë6 oñ:V\M/Ÿ¡˜øw7ÇÉ_ à%OÛb [ uߘÅä6m_àiê ¹Ð!\0Qï&”´ùƒJÒ‰¼ò¯Jöòµí;xKþ4ö9Æ&MÒu›Ö-?¨M¶IÓN]tÄKddÓ~Ø’‰#Í+ m­%BR@ÊÊ6µƒßâ™A³“ŠôÔ—½ŽG¶ÍGšné[aô“‰ÞŽƒ`lê8¦"JŸ-AWy”U]ÊqìédaÓìí:‡8Y?—à¼ÿcËyG9i„æîŸåÞ÷ºçòÿÏ3¸%î¢å•¯|=ï)\xþéh¹ ÛB2k²Ÿ¶ø#ÝWQôç¡ýØ ¯¾øÖp{Ññø»Ø§˜Å†ðȮϻB«ñ/®ï÷>ø«“nwé-¸B« °¢±°_ÏiHLë Ãj;ÕõÉV͇_n©ŸAaˆc/™ëóY|œS6#B^´Ñ+h''ºÓ#êå¨ Êdη`‰ÕþÞE­|åZ&—äfó‰+l€\)Œ=\ 2<×oáDêÒ=$Ïá'+©Ä«ÒÈöSû’0X(¸¢:B³¼Iy¶‰a[Ç¿æ,M¯Ò Zê'=óT T)kcuR–‚ûƒÈÑUaE†yýÂ`P6 K4úê…¤u -ªl›<1ó_o™Ês²&}ŒÁKð”EÔ¡«uÑ­@1-Vãɯ¬rÅã·_ú˹]Êßûøþïÿ·Ëßý{_³¼ûßËÉÐLZ.ìj&êÚ@å ³ånõ„týÙ…jR3åURäl@ãìc£GÀ·(cÚŠ›Âd'ãhÒ°Ätýµ.Û0¯/ÅÆÐÓ Ó šñ†sLhÒ.öMý£ÌÊã.ÓQ’F–†d§ÑÛüo’-4üUû@ýbSÄxYÐp9žb4|ßé7š“7lÊè¨þr°ÇfÙ„vea íù˜C}A›~@ùÊö$¯Åpó¥j®BˆµJeË Pž5Ÿdë¡?…”p P´³t–}ÄckWË&âÖB£8õŦ^“9Öð“Zr‹·é|Ód›–HžõHQÍ¥.Нi¦üá^½¼î Y¾ã;¾|yâ¿uyÍk._þÝ¿{.Wø½÷ûÔò¯~ð§8 [–/{àí—ã,$èïnV+´«)§ré#ÌOUk˜aàÖ¡ÛÞî¢n÷xֳ߯3U—.GÏ;ÌXQäîê ¢¥RS/>RÆëŠ+>´<ñÛK;ÂUØ.w¼ý-—“L^fÄVÇ›±¡ Äd½±•õZ•:ÇÒÕ?]åÎFÄ8R)DzwÓ~êæ‚˜`| d?š°Jï€í+(٧ŧ·b èñŒ~³nó…]üŠ´­¾ž±IÆ´§Þª<ñ]uòS3}K{Vlõmž…RÚZ>ã)ãÌ’ýHé¾,%#jìeQ/.ÁóäÍ=æ®ñ6L«Ñ˜~Ä… õ¡ÛiX³šÑîs¦Ê>9j´0/¨@<õ e¬/Ȇ–Ùñ íÊÔnó0¨)‚@ÇEVK•É:m®ò6[ló¸:$G:Cê²Ò‡O>ˆôã\ÛïÅ(Sãð@;SsY<½r ·¥puÌN…ì¾d h'8d¢^¬õ¶‡I‚²Þº‰Ñª9öjCÆÖX)°ÇX8F^3ÉP ˶[F’€²i†­%ö븧—øÿcyÀ~S(Ïòõßðí ¤& i‚ž‘=hWîµuÎ܆‹zÊ|³Hµâ$Ÿô Qí”O7“ÉÀM°0è Ó¿ô ,v;ƒÎX³rÙ݇X¶aÚØ¦‚¨È–?ÇFDnlä@}©…Rz<KÚ& ŽítÀ69–6ªmö@•ÚúÁ³ÕM=i À¥( 24_vì±ém²ps*)i©Ø.ÿ*Ü£‹JÇ‚¢¾/é]'ˆ ´=a©¬ÞÈŽbÓM’†:ä€V‰¶r‰k ±ëŒÒ€_b:ÓD1/U¡ÑÄ«ÞàW@eò¿€:ézþ†Zሧ¶Ÿ`Õü—ˆ„²û8l£û Yæ•èîpKxÐ5 ?¾üÓúß-yÌC—'ÿàÓøÑ¾ÃË­ns!+ɾ‹[JúN1äà&÷ÔC0›ik-KCÓ%äU&§-' ÔnôŒÌújnCÈ€ës@k؃ϡ'e'œ¤k `šhIçžÏýþúä‚ ,W¾ïÃËùZ~ò?þÒr»ÛÝ’Wž~lyЃ¾ /Yþè]W.÷½ï]¡{îòö·ýÉòÁ¿ü84® ð,I+é1÷“ñ²'riò4®*;R›ßÐh.í32k?mæ) H…q¨^ €Ô ³6¥SÄiÏù¶­ nù±ˆ‹žvÜi§˜Ìþªò©å¸”Û»~gùõ_}ÙòêW¾gùžïùûË—ÜóîËSžòRö-w¾ó­V:গýOÛ'u:ÊM(£Q¤võoëø+&WM•Ñ«%n 6«bc²5 5œê‰‰ðªç‘–Ür”=1õ©Ûb¦/…c¼ ü•›ÊSÓaÄÊÞ{öè(Ÿtýä¼'ÏèÔóÍ&ƒ~Rعº5ÙÃÐlp§£Ë»Í Jn÷Á²qTþ”•ê­!„¡­‡b)KeÀ%²éb‰¿ ŽÝô ‚ =R@ ÛM ‚=$GgtɘÂتþsÀŸ £½”qAnˆíÒ„E9]úúH^©Ði$nî%Nú5WC^êV€þ´j‹2šêÅXoßÑþÙ^Ÿ–vªþ¢É;Jјãê©UéèGßxåüû£½vyÈÃî³<âÑüÊðõ×/ï|ç»—Ë/kz^tÑÑÆÓã<|€þîíACÞ>*Ÿ‰h×uÖt²k3ŒðLÁ‡>rÝryä[¸Sà[¿õ/—ðlÒsžû’ú‘·öà´•. €c?‚dó Û/½ä‹ Ÿ„ÿs—´WþÈWÛˆN“®ªÏ§lÓ÷E‘úlö©‘ß[4´¢:{7¾­ÄZ°«…Và ;}f-‹W±¾3Ÿ"6ˆ¯²·uÂëX÷)Á(Yp)§zLýæ'éWž$ÙEFú‰ïDŽ HÎ8‡l´ý6èae0NU@°ä ÔmDÚœŠl ;()ËĶPa.«È"§Ìùüi·í¶?aýSN1\õ•fý\dÿy­s¹ºÑ–®|øÛ¨§€Ã_4Ç‚±‰$à£iH5àb¥šü¹õÖIå†nw~H$évy­œ‚U†ˆ²þ¿ì½ô§Uyï»iL/Ì }˜aATF”&F@š¯Äs"±XˆÑ$æx¢FMÌ1š¨è²$’˜HD4Š *bEz“ÎÀÐë0Ãô ÷óù>ûýÏ,ÏÍ:÷ÞuÖ2g-Þ_ywyÊ÷yö³÷»ß.ié×NcÞ~XìÙ‘¥´rIÏÚŸÚî]í+, œÊ Q”ŽôHáŠÒ’xÒCä^«ÁeY&²a 1á¤!+èT i@¹ÎàR7ØÒŸé2¯Ë• >¯Ó`†:…€—Áȉ^NçcÐjÞ{ôÑol_>ç¢P›^³†Sæ,i˜ÞxØÅ£z~e_þƒ5a)àîüÀDïȆZÀæƒYÄ/<½“C§Tƪñ›þaR<´ #yfÍ”+šŸkÁÉŸ=MK{…`“VÖ:(¬U%Àú.XÑ‘`àOýÀ‡O,è0j Œu-P#\zJµ¤{½ jð© N;AÿCSGþ b)ËEšHLoê…`ª@®ÍÄJžLü‰ÓêÌW$à‡=Á0~ÛBKŒ»a§HúϪ;Œ"d91]$QEi‰èᤠ'úo þ:•î=U®/;°¬²—LJ©ê´‹–¤}ÌÀ«Þx™ôÈd™}¶!ï¶`ðáÉ/{Ùží¡oë8}ÀKd’{ÿOärtÕ™œ²#}OoTG¢êÇ…Bxö ÛVøa¤ÉÄÏ–&¶Íx†>š#òÒ<($Y.ð$ÆM© úQ?ã0ß0}j=ç{劵í±Gïk“§ŒmŸûì¹mGÎ ,^¼¤ýÁ)'²3°Cû›¿ù\[°ÇΑ¹è®ÛC=[=3°57rk={-ê×Ãê-[…¨]õW}UÚPQ.]!Ô'·¬×ãëêºZÇÊ%ªF aú<áKœ*Ô3nƒbq 'þL*übP‹G;ßûh{†Ë öÞg»ö±ýs›:ebû«¿:¾?®}ï¢ËÛžd,ä1ˆ²9†Ò€W ÀÔ’ Ææ£¯;™¤¡¿:êïNÌò+»²Ñ` ŠO´!}ÔPp\’†4Û/ߨ{FÜ>”ne£Ô‡»d\…ÝÊב¯>ä9ÿÊØ¦L5ºF–uÒgŒ¢P¼…2yêBÚ¿Lrƒ¸œ‘K{¬ª eS/cLÄÆ. ŸÕÁ tºGyèP²¨©mž¡˜hØøÊA´ÏÄÏvE"û`s„ÎlP!Œº¡Í¥­Åê·°”2Ç|uÅ—”GyÅ'ŽR›XaŒŒÅ¬#’?}?2qJ¬ ú­à;ì4k Ølßš!Šô/lv²V‚jŒÍ¶83"#Å:eÈÂ_?HiÊ™¾%\Üw.z¢ÝqÛšöÚ×ìÑÞô¦×¶{î¹£ìŸn_ùÚUmÁü©m'.}3Ö}ÒÙhôùÚ‡’ü8¯ü¢!ª«¶IϹö rsvѾûíëÛQ¿sjßþö%í’‹¯m¯<öEŒß¼ü=#/…Ô½¤øŠ«jÇóœö‡§¾†û˜.j?ûé]í…ûs–³ÚêuëŸaLT§ÍcLÚ|(È»Ý6ïS‘Q¬P•ûÓ®#ÛýjÙÐuÕvÔUuè²oSBc¿6ƒ ò`QIl“·HÊu yaùãË_a23ÒI-f€•<õq’é’%Ÿ:"7ð%´¿éýt±øÂ¶Ìí“@&~î,˜pE NllgãÛ#™‰™ÈÔ÷Ðë+ÿ=+¦L“줣!ò% qb×r`D_ôÊÄ’[ã* dÙΪ±Ï(5ý,éÌNÝýPûÄ'Ò^ú²ÚÂöi—üàÊÙêñ<ÖtÖö“sÙÞÚõëÚÍ¿fg€²ûÒ7ÚÙÜûÈ#Ë8ëqh{ÛÛþk›±Ýd6ÄóÚ~ÏßË7µ§–­áÝêØ<?qI1¾säu ýLˆ‘Í@¬#âJƒÚbåxÏÊŒ3ú ùq¢O´"g߈MëÇøÂ /ÔØ&-u œJ®>¡¿Í¨A>ꂉBôyÏËDžn2yÚøìyVàËç^Û¶ßaf;á„£Úž{íÊÄå&vB¸·i„e0Ï$\àtœQGáQ®ùA/ú„L¾xõG9¥ÚJX¼ÜŶ1†46;Ñ]®>K.ê“‹ž¼×¤X¢?¾T—¾§¼v΀¼öøê^~â¶–1 S|†LÛ'm¤(Ç mQ’=¢l5ã¬bJAÀOÞ>.y©ÄCRéÙ!©¨¡¼4‡àrÛ^¢äKIéÎCÈS¿ël}UVj‹Kùx˜H«/2-F®ê㺌MErYÊ¢\öÕÚ&‹ }()9óþÕ†^Y¦-¥^ãÎE~]P;ÖIáRtú#Ì) ¸â/‚¿äjúÚ”øøO»hŸr<àÙ†Õ«Öqã©öö·×¾õÍ?#–·¦Ÿ×Î8ãëíyÏ›Õ|ñÎmÚÞåÃÅâ.x6ãÊTVü;jz¢Ez9ÄÑ †ŽË¾èA†»îz¬Ý½øQCü³vá…ßmsçÎAßkß½hQ{øÑ¥í‰%Ëñƒr”âûLèŒMÇÿÜì|ÿ‚{®6pô¯½gål&•ÃáH›Ôz U¯?³¤¤ï8㎪L›aذM´/ öU¿`Ž[˜¬1 çãÆ”oï Á¬ž·Âû,¬8€VQºj;-á•.ó/茳Ü/¯?Í¢,íj“6@¨eU›‰dæd‰j(«ë"R§˜Ȩ̂(Ô^Ÿð¥¤ÜVŽ~4HÇ/ýZüñQá)ƒ&OYæZ/‚tGž-ª¾–4JÙ—F€òËb³$çµÈÄp‰A=Ù @x¤±¿ ¾l49Ôg›c–²Ú¬qÕ~©ÌœyJlÈ/¡q»yÞlIâZÛý+ýuº“Pú¤ŠBM$Ë_ù¦ú·¶UÞzofvÁ¿Eí@eÊl ‰"?\D¥ôÊkxûZ¡0éd–“]XB놾åÊÌx}ü)k ]d©.JSuÔg£e^#ñ…C{8c¹Îÿškïi‡~ ¿ƒÚu×.nc8M—~‚SóËy¥_±MÜb³`X”` „ngð‰"ÀS vh”‚ŒH`=lxãiY²ñQÁ·\ÚÍÁ …ÀÁ }êÅ%/ÎÓWÑhБI¸"£Náj†2 —3mA>óAtP•¤Þ .;¦¶z³cüDºlÒNqH[4nå¯?¯zýW~Q¦çzrÚ@ƒ A8¥(io¦¤×u]¾‘ÕUEYö¢Ó`Á…U<sBŒM4Fáï¨øÑ…“ȇNVX>äl`7ÜYb¼5úœ_ü†>‰¨iJ—¾êp5ˆäºú *p“Å7æÈ•·|\ùø¥–¹ªIíæ§Õ˜(N˜8Ž'íÌißä—^zU;ýôwµ9»mÏôiwc€I×`†oôl¦Rœ¤£G%,hÈbÎX˞أzÊåq)OPQÜ]ª¬!Xfí‡òj;jH»™<’‰Ç}R mä‘>/cRæØÑ<÷{Ú$®ÓÝ–.]ÍÁ·rsà˜vþùßoçŸ÷vß=·c_ù2žþõmǦs³ðv\>4%]ÍÙ¿U«¸N˜ÏhÞ3àSvbœø ‘à—Ú-2^µÏëÁÉi³þ&W¤‚–oÉï@f t88I ¬ÈeU,£*m®(lN¼™f1£OÆRÄÉáDG°c‰O=ÛsÔ1óÛW¿rIûìg¿uùÿ…G$Žã ÷ ä2ªŠQmâÛö®ÄTå&C Í(”6öØJ¥–YYg5±ÓZŒœ € ú m­¬ðÀd›³hNô)&'7C\+ÄIÒ0~É›KI»â\˜õ½â˜‚7YŠ5Âê’«¬Èƒ8]¼ç¥‰ô5±(\éÏmÃt™¶)ÕŽnP#1ò‘ãŒSmp;“Ê`T>± (¸LU&Hæ£ùW¦¶èOÖ‰5ù%ðOñÒáO'h)0KJ-pzÞÑIUaFXA¢<þe;]U ™~‡<5Ejb0ëù옑‰‰üévqh‘æ†8H†d鳪ÆH¬ßî`‰æ$~¡G•áÛ|ÙgmKžXÝfÏšÞvÜaJÛ}Þœà¾{Ñ#íß»£ê9Ò?š5}€É¶zµ'aäç=@‰Ëk’«F”ùÇ»¡u(rçâλžh¯yÍ¡ÜOô9®8˜3j_lgžùõv䑇¶³Î:­=ç9;·#~[Í=G.cº|ùÚöý‹ïc>ñâ¶×^óÚ?üý·ÚZêó”"úhÙˆFtDFÚ¶Õè‡@J[ÛF9 Tý]”ÃÙð`Æ7ŽSi£xœx‹cµjcõ6îÔÒ0)Sa{‚#rËWÚ§Ÿb2m©ÍX—|ü,A•öQ—1œ9²²T-ßè Ê£¹Ù®Cï'÷³šüê´ÍÅ-"áSn;³fL¡ÈI'Y§ƒ§NÍ1¿¡‘2ÁÚ\!AŽíæ¢åùñ¤å·‘êÓ ðÎDÑ•S±`³áeŸÁ•§Í˜Æ?‘†­åtÜKYÀÄà»á9ôÐmڙк!ÕðZÔ¡\þ• üTF/üäÉÀo–܉Iè³êD:±ec&Ÿ„¬ Õ $oÃXï†Ó𥊺ÒM• %Ä$ .ÂO”¢#Ð rñgðf% š›>»ÎøL™jµšµ¸jgŒDä•»ZÎFH£ltVÃUðŒ…¤^U.f½åMYH‚,œ >1YaPŠUì4VÒÖ¹WŸ2Šd×K¦ ñš6ê+ŒHÀâôR¥¦Tá eòUž `ºø¥Œ'­þŠAcNÏW<éKµºV¿.ÂÒħ¾â­‰ŒSŒÒ 7¦‘ú d’ Hû‘qš7 JÌ"4mË*de™üü“í¸L§ÍÁNÚöj©¬#8^Š¢«ïãÒŸ©S&´iS§ä5oöÊû/8‚囄•S¤Ô¯õ‹äÕt¹Òö‰LÌëtŠ B~‰š—ý¸v@‹íbµ<1¯~ ©³-ÃcZƒl{Û½‘߯q–ÞZËôÔFŽÀ™òf½‰¼ÝÛ#ß‹™ø_~ù¢¶ëΓÙùùA›¿Ç®íÁŸlïxÇÉmÁ‚yícÿðÏm OMRür9êcDõÉ„ c²Ã桘WÚc[N¹{i‡ ñ¥nûV§Ó_ª=ôÉÐ˵¡€SKyõmHøS§-’ÔÍ’Ó³¬’F›("µî±3÷ÄIã8òC{þ~;´·ŸvJ›¿`n{íkÿ¶rð¼6‘A#Õ—7?@Ø¥3ÕM²tsT“Û,öD“DE#~Û'haRœ>È¢rö›O ÙÈ‘ö`’øÕ=y•-ã–눠GÉŒ$BÞc 7ÇI‡0õ $Û"hõ‡ìÕì• ,Zc“OÇŒÞ)³-¥áåÅC±Aƒ»yÅ› q«CÝ|¥±Ý=:\ú„åTtR[aRœ>©í‚9üÒË刑2y+xȳà4à “à¤Ìz¾Á­~SøÄ>™¶Htö;x·fùe?2²¢@Ì%Ú¡N–v&ýË´‰2ðQ¦*'iê3.P— R$–¥b²€Ó¸†ÁIyö{ó{7—¶ÝqëòöùÏŸ’—~ñ_¿ÖþÛ{þ±ãxÛñD°Ù;Loëx3xÞ~R,D¢ ¯ŽfM‘íWW¨ORè{[§cÇŽj7Þü0—ï¼¼xÂÑy‰âSË—sàdÿvÞ¹¿Ê›ÈÿðÔßãÞ›Û¿ÿû%í .o{ï=©-Yºœ+ æ´Wu@ûÎE?ÉøqÌ1ûæþ9}^í]>4-žDFM ‹¡_´TyMaµ:‚Hð>íEâæ•±ÛJì¨=~©©€¬déMÓü§A:»£ʳ´uœNžö‰YÔ€c”ë©/âW¯%CÓåI‰tƒ~å°;u¶{ ‹°’›ÕWTñ™±™>Fte®<Ôê7Y«=Ô >q§ËßFÖ³fMf Û¦½ÿgµãŽ}^{ÿûßÈ©ío´G™ïÊu¯”í‡uûb$:Ū´’MBì0þÑ[Í[>Õ ÕVà1¦(°•2±èuÆ›þÏÀ>y¤±©·Vó³ ·N§èXâ; ÕÏp”RÙn¡ÚÈ5·0OŸ>ž§yLÌ#Rïºën\ܶ㽋¾óNÏßß}di;õͯâ¨Ý‚ö©OŸÙžxb¢¸Ohõ:lªÙÖœ (8s¤Gpä“Öpœ®.}Ÿñ¥ˆstÉk_ð†ÚÁ' ízÊŽp3øƒ£aˆî"¤¨t6ôiŸÖ’I«~ÐrˆÝÙ۟뎗.]Ù>ÿggGïÏß};:kÛ-7ÞÇ}ãxlÝž²üJé-•±$qŠ F`-¥Clû1\ò¸ƒÃ‡Ôá ]cn`ˆ3&bsd„Ãø±ß E‘Û™þHßtc›³„‘)•1ÈwHª¿³¡ÉD!qCZ]4Ž—àÕXgZùüŸ¬j!Ý'M±ÝKÖ$bƒ’66Â0,ã´˜•#3íƒ=…@ÒX¿ôb„´l£‰ÒRME¾ñ•jJ Ì”h?å$^ /‘ä%¯ :i¯Ï×Dúó…uF©1ºG®¸B ¡ýF89‹:"„²OÄ)Ž’È?di/Ö6;|…Iά¯ë ‹¶({ðs<@á¡Î—yæHú:oÞåˆõ[N=¦ÝwßÜ¡\Ò~úÓËÛ¯o¼»í0‹3|¼ðk®õëÖ•OJltj’ò2)+Hƒ+@Ôí4ú4Æ]Ûôcmãž.“4¶fÏß|ÉÂvó-·µß;ù½ÔíÔ^÷_žÛ>wÆ»ÚY_º°}ô£_h/دvÉ%W´¹óf¥~þó‡ÚË^öQ¼gûÁ®¥ÿmj“ÙÑV/A˭݉Óx°F+GÖ!Fõ]bSC´>Û/.NTYÍÐ¥–Hcxç@¡ ×Äž-àxš:cÙN^«¢‰Òb•VR}EGL˜ËÆId²ê:ïðبìÅä»gÌŒ5Øâ7éEæqIPVE¨„1ãaÇOyú‚ôùU¹úd*³èÙˆœ«bõñ œÆeÆnñÛrlÓŒÚžŠ«–ˆv|'Šd°Ô•TÆùØb)t ‰>Óu;E¿ÌÏ•V-^· ÑZ´ŽÁàöX'oú⺂9bPhs’¶¬Œ‹¨ú¤SO×X¤_r¯†ì”Ç&ÒÙ®ŠWÑ7IR·É3ßAQ&é6uµ*ø^—êà›é …¬Þ2'a € AÌÀ“#wÊÑDx°'²ËˆS@Q.¬%•Á%ÊÕG¹N’¨ï¸³A«_³ÙËç¸N7®}ÿ{¿núë·Fèa‡½“}^ÐÖ¯^Ÿ‰¾ ­.)X'N50k¯uVÀJyHÄAii1˜C·)Ÿ÷iRW9 )3JŠŽU¥#jc튟£×©IÂbšOíì F//ñ¬‡õ â„[é54%Û”³ƒöd ‡X $‘•#¦mõXÓë«m"¬ª£ã èô]RØF¿¹$°‡ý.ÒØE£ì!èÖ۔ʎ–™XàceEnÝž¥¡Uµ?Ê ÓÆ`ö®Õ-^•eÑ—È€ÜêvÑŽ ÆXc“ºÕ*þº˜š"—ô|h!Ò Ú–‰}™Êe‘fdQ‚xýv~J²Ë6+í;dÀ·€±ýìc¼©¨ J{Á.¾äãÿ'J‘×:¹„¹ä yéCm2"Ù5<Ú9¬Q¼ó3yJ—²ôK·1~Jmð"åw½TeìtPÜÐè1ƒ%ò°×vï¨âÓ4ˆ:yä×\hÄjÛÆð×û»àT†€{½kà±ÈA9ߤz¶"FÙÕ‰aÙ#H»÷º’Ðl`¯|ÌX®¿â{/gÈ@‘ˆN#-S’\:On.–Ú,¤uSÂÞ®k Ø1wk} °QdÉ$Æ­6—¨+'ë4¿vˆ5«Ÿn»ÍÖ® ÓRÒæÍοռ<Ç'‚ä˜Ixåñ3²wœPTi×…BD£B¾$tnŒ÷íÜ1£—YÒAJN}Ÿ=Њ•nŽMöŽØLÒ³ ñ'üi+xÒ¸$t.ŸŸ¾Ž'yÃDžîäÌ=;÷8ƒ-š€-ޤY#3)Ë ÒÖKR–ífpgI†¿¨I,mÑmA† žrPÈY‹¾‰ûjÒn!¹¼ý͹_oÿ‡7ð‚°YíÜ3¯hó÷œÌ5ò3r)LâPÈtï?±GºÖ€';µ@³a¢"d}C›ÒvZ ¬–Enǔƭƒ¶¢d¥ ݶø©Z%±Êh—–Z…!L¢D—ª£é Òñȉ›&MߦNŸÈ„bc»ñÆÅí\ßv›;™Ë…®oËW¬âèùŠvòëŽjûì³'Gѿ̛wâIaëÛäÉc8¢>&voÙûC6òÁP8uçè(úw™üÛ~¶X8¶dÇúĉýÿi—½.1kÊ@§¨§thcŸ¼"ÃOÜe6ŠvCŽþ)ÜùŠWìÕ¾òå‹Úþ ÷j;í:³í2g7L/nSð¢}Tž5ŽõeR¢iе=è3Ê«ö.›:Û&dÔ¬xjæiºÚÎϼ5šöË7ÚÔ“Õ¾ƒF£ÒéM}U䤥(öA æ«8ÚÈ»ÎÕŽ“Òd‰üü¥/)kdÂ4J¡‹ÎBéuQa”ã“ì˜K¤âÍÆ›jBT8Ê Ÿ˜Å ص¦–ˆ”‡¬31lTžpâ)£Nž³r©´Ý5è†a¸d#öC9þexC)éD “©`!ïö8¾Òñ±A¹òÂ'6sás-jûgµÝ`»8ÊŒbЧiûÐ+ÝPTŒ Ó¶ÇV,ºsþ裫ò²­Oœ~Z&ÞçœýöðC_l·ßú`;ö¸=8CÏ6Žm³/Óʼ= [j±˸™ñ8¯ÜZfíÑíFÅ'±tÓ¼,v “ÿÇ[ÍËó¦¶ .x7/|²]uõí„ã§ýíßþgHÏáʯáý$3xŠØcí…/œÕvß}6—mÌý7ƬgÖ1mú„\þ£3rÃ&‰l9‰ûl-Ç'âOúøwïPd`è÷Ÿý.;µø«&u\”/Ý–ÉÇ*ÿjˆèX+Oo¡Óf°7e;f)yå8N8èÌÔø¨K±”\ã03ŒO]h*c»æXêP‹ôâ§Î¼nRco¡Š ^_Òi‹/RqŽìƈþ 3)äeN>ىī…§ûÐ8×6cÔí]âFjÒÚãRh¤3ãUeiÊí×ÙÁ$›K|û„)ŒÈLß)¡°?Qš?çé ‘Qs¥š_èLa%Ã%ã¿m&uå4 ãsñÒÙ¦¬µÝO s!ÐÈ_ÆEO¶«È5*Ó6‘Ÿ&¥LÀp"8<8#:”¦ã¡MŸT]\Ëuqî-ï¾ÇLÞ¸7†GòMà†Ãm9"¢S‚Ä¿ZÔš2³C‚²¤‡u‘áÀ¾-é;|±DCýPçZ™Ã²E=<¶u[²ìѨ>å͇a\Zv þ¹ä²3¯ÊŒ¸dKL’÷–|Ò[.ï“–®rf=Më[@ŸzjÑz^‰þOEq’26m÷(=5¡³Á A‚¡w8Û8ò-N:†ã(âdTŸ× €X¼–ó7 ΆjĆ¡´:›ƒ`‚…¹V\Å|-Í€9¤£¬ôFé¬h'a¡c”ÏxLS­} ²:hyñüyËY;N‰Ì2¨dF±ïêE*YWŸ ‚*÷ŸLÝÐÌôíá³jã¢<ôf`!«%%§|— ¥ók‡%_ôzŒ3õ!„¸|r[òäÒvÞù¿lsÙAv©̒.&òn5,ÑÖÁA‰XëH©3ÆÜI‡dÄ¢u‘7׉ʤ}¬"@›€í௥ʎñ½%qĺ6,ü²,ˆmUA¹~p°Ç¤$½¿ãSÅä2!^šuðìÉŒe›ÚOv[;û¬+9’7¹ÝpÃmkKŸ\É»Nàzß=Ú¿þëùí†ëïΙ”‰“Æäè¡xFgç-Áª¥ý²;1ø‰‘¬5ÈP²M2¨ë£S_ÒF¶]6¾”à‡\¶ÂD Î˜²!ÓöLi}Æ/Oéü¬OÖs´/7\ÆÙž÷ü÷sÚ;ßyt{ûÛ_Ï% ?á>ˆ/µ£^±{¸”ç„!‹“-mÐïd£šö7¤~Àíå'Úà˜â"m8U#/?˜Œc3СK^[åÕÀèSNÿY–4·Ð ¨è_}õ¦Rˤö#62èüoÚ +lú³úDd…¸8E©èHîöÃlUd»áÍ8ô“Hׯ8‡ú>†)͸v)ßÊé¢M—þ ^øâQBg…¼þ¤a ͱ 1dbXÐç8þò^¡…3>±M¢O¨ÏOpH¡Í”™W¥4êu 4‰q#éL¤«måCøåSDxd§L–ÑÄ£—Ý®Zµ†ƒVcØ1Ϭuô¥qí®;ïm‹ï~,}nân^ßÄuþÌì3¦$l/pèD;º´L¹¶—©nMl²"ЩwòïÞ›9÷ -]ºªí6wFûów¿™ƒë9Ó° ×¶k¯½©Èã?_vØAmÚ4Æ‚oáÉi×µyÔèÒ'WµþìvÖ¿¼…†¥íßñ/ìdïÙfL›˜m®;ÓÕTÚ_ì…tö±øÄúHlØTc|rE«ñ¼q8™$‡q"ŒF>õ"ÚLâ,ÂØlÒ&EÚ¬")½+ãS¿’éÜ·,¨ÐøÑÝV[O].Ç#)Æš“È‚MÐHo›ç Ž‰Åa<€&ÛÌGF°’ÍA-«Sÿe¬DqðB•¸Ui8\óC¾;énw²R¯Å|jg Yôí­þ¸,ƺŸ’ˆ-Êsñ €c€¾¨ù@Š#Û>áñà3(øjzÄ óµÝò‚©Uü´Í"éh7Œ*ÒÒ3«i©q‚˜øLj %^Ú®šM¹©¦Láäã,}B:x¨’F¦$óz}])ô$n‘[÷ï¹k Fê=¹‡(bƒ¯›çæ…îÆÛ9ggC[­ü?`™Ì3³]ì4ÿ'/“&OÈ£ÿ´cööÓÚÕWÜÁÑJžúÁ€êÆÛè0¸ Óš«ÅäTg¢ÜŠDD‚T¤B¾p£ _ª*¨BÖ„T:’újI$k§T RêCP‰ÇKÂ]1UÁáÆÄ;ŠP†pSž~}M LP~±‘LQá²³ºaFcˆìCf† Ø*ð­µó8 z¤u°V'ô²f01yü*¿eN‚„(?ðf`Ng ü䣆zQØ.Ùpʧ|D¥"_ì“ ª°òu¥eöœè°4ߢŠ\ °;X‘k3K$¿Ï»¶MW¬[Ûzx9ýwä±m&oÞããA!Êe"N$˜*/þ0§ÄB딈*í0o»Â`[×ÀFÂvë€+kÿ ÌJ›Á(]Åu‘«}ÚËÏ} 2~Ü`6À Yꭣܴmh§ˆ9Å: Àø Џæ?Ïé~¦í²Ë4ž>57^qåmí›ßººí4{b»åæ;Ú¤Ix|èªöÆ7¾’ljîÓÎøç¯´[n½¿­X¶¾ÍâÝ'ŽA¶Gí¸!·Ÿ²Ö+ч#ô‡¸lK ùn¾TÒ|¼ÿÀ.µÅñ¬’pL È6µ.~HLCmãB›I|â‰~O[¸³3†I׫Nxg;q9Ð÷˜|­mozã‹ÛãO<ÕÖ`ûxžº² ýig\Ðw´„6ˆ¯6 ârƒ"|«_‰×ä%î´<6<&¤í4I(Mû]¡Ëèö¿ôi£u³õ3=,°P_Ô©WÂ¥PäÈ¢ì-øLý'z;¡“žàQÆHLP‰¬Xm½þg&·¦K72åèlñ³Ý[¾¡}ÍeÑÁ³È;¬“Ò„`U5úÓ22æë¾…8 *û2©P—„Œ82•\ÓuªÎ¶„¨äF9•o#ëk²9Sf}dk³šX7ìÈÈoÁ YFaÊRwa7IIƒ–"/r¨÷ /˘t_wÝ“l«|Ç;ÛvÛMoüÐçÚi§Îd{t›;fämà†üI°»УÅX쮵*“ëŒbt‘ht‰¸c‘i€åò1Déå?{¼ý•×dòÈ!ïå~ µ?zËÉ\.7§]ðõï¶wÙ¡Ý{ïÜTeÛy'Æbr×Ýf·wì½k»êŠy Èúvô+öÈÓƒ6p6уKÆ…p’½äS?P'F|oSˆ_ÿeB—´ ÃÎ_­ÙŸˆŠÝé;èâEÈ•%OŸÓŠñi&å*J[ôØ‘Ó2Q*7; ä7zÍ¿å”ÍàÌÀL~’þâç·ðæá_àŸI%ܡ͞=+GXÿ¯“oû¿pßöµ¯]Ô~þËÛÚ£÷­i{ì3•›'"›K8|9lË#è#½¶‰ÀÅ™ ±õPg6eMoJÏQ=påÂê½aSZ"-m§rñjbPýç%vŒo¢üò9?j7ýzE»ì²¿‰þÓþøãm{ž¬2qÂØìøPÌú¶6:AKnë>©³OˆÛr{ ÿª×0¦À>¹èHªÛ›KUl3~ñ½q}v¸aè­Ò…*5KõWøÈÅ8”s1hx‚JìÒ¨8PÌ+Q)È9yQŸ5m­ µý³OB+¯tÊ¢ÒIIYL6ÊžQózrÏüÈoÈ 7´¬ÏbÏ®EmÊU‡ ‡³±ÞEáÁÄîÌèt—=±¡(?9’ —BŽ:¥)ËO]|­F•wZéJiâÛb³_M;~±ÎMÅ0NQ‘…Y숄O}–¹äŸ¿`H¦â"•ÐŽö2 Ê—0ùß—wï¼õ­'µŸýìÚvýõ·òfßemåòu<^s6¸gg= øÓ>¨Ï$y+ÎK—ýÀË"mÙR.cÄÓ$mn[™8’Dþh®=±Ý—²3?uê(žþ36“ücÇ%s“Ú[ßöw\øñö{¯;¡}ö3gµo}ãš¶ð%»ä‘Ãßãñ£ùÈyñØœöww&ÏüÅ‘ÎÒÏݶÔgÛßwý¨Ì\¤ô1ó§ÿõ·È݉¶*Ûkmèg­ŒA6¶ §?Tc‹ ´9Öö6.cX[£'ÓfæÈíoéßʇ&—g+‡z·•¥SJ×wÖØþe_É0ÿ é—–…ÚŽ/¸ÒM¨#å‘#`Í¢^dPa±>.÷É €Æ³+´¥XœzxlÚži Wÿ B QVë6Ë•­ÕÅTø¥Ã7BRÙóÛlcß&é3*F®œˆvÍ*LæTB(K“ÈÁÛ£|€•òK¿Ã^[Ñþ>ŠíiZkò/6ê ’h÷_lR¡!yÇA|àœ­Ûa<¡ BõèuÚð¹S£nÆ¯Ðø‡õ HØÿjìŒbâ?ÏŸÿ‚9YͤçLeo}§Lþc„¼RÖÿô³ü7[Ò[÷ÿ5¿%Ï–éÿ•œ-i·Lÿ¯ø~³^Þÿ'þÿ¨ü7ùÿwäÑɱb6ôžÙ؆-ÉÃ.審1é(F’më¸ô´‘”˜0 ,4L)K@æ¿¢ÁU@IDAT®í}ã,¼¨ CJ>vÂG=Ø ôÉCwܾ²ýÁå 3;·ÿøò¶hÑÃm*/.òúKˆÒèÃõ´*Mÿ°,ê©APBtˆ<ᥘP$H«KŸrW”…´,¶““<7¶Ù°Kè ô(ÓG T¹8HæÚH:L œòÛ)¨ì=%rÍÚñÃ]Ìbt ËÀr2ðd’D…¸YGL´KÍ–ý&A5îäEÿYpdÖ"cç“.¿²Ë;`*¿L6eáf½±öR¡¹fÍš\:rÄÏi?¾4—»(3K÷µÒ‰9zj½ö±.W–¦üSU¾—F)+Á Å:—ÓHC˜` ¾ûÒÁPºP'±Y2>¨Äf+@˜¡Ñ6â[ÂâëCbµâð£\.ŠÚ˲âühƒ‰ÇrTpZ›8yÛvÝ ÷ð…K¹ìg#;ÜÓøÍj7ÝtG{å1/iò§¯áÉ%2Á~°-ºsi›Â=^gì%ÊNs±Î† zcTá×ôjTÅ’Í‹äËNhm \¡SW<Õ>n˜bu *‘³¦bÛŠ³“ÙÃY^fDášÕ+s™…Gf'ð"5}T¾ˆ†R6èRJt Ò¨°aÈÖä¿úHjTz¥A–v&M>;x©×ЖÐäÉn«Ý~­˜àNÚŠjã)õ*滇>¤2)•¯ï)Sy&ù q'î´; ò‰ô©£&ÍåOrÁZï’IŠÌ~£ j‚ÊåSî_)…!ý>Jáƒ1öw…’鳜ø†h›¼ò˜°Ð$Âã2±+þ£? ã™>*rþ;† “iiýWô29þ˜/>ë Ÿ¶(¾@Š=©?/ÞäYýÞS³œ—ï=¹b];ùµG´}÷Ý«]}Õ íïÿþ2v’—3‰žPÄíO‘£Üò:M»¨ÇñÙ%g£Ò<ÖYcï·Àc7E>ùLq^~´ä‰•¬Gs9ÜåjÊLþÊcƒ}©Þw¿{÷@Mi/Z¸}ú6ÎTÜÒfΞÐVðÖñ3&·ÓþøwÛM7ÜÑ~Åe“S¹‡Æ¾ ©pѦvÁl²Û1lŸ¬O¼Øf~h÷´grÖɘHè.0] JŽ<)IL¥[ zìÿÔ­®â‹ï’äÅíUþe5´!<ÙÆ¥ñ©A„6IS˜‡|ñQœx“ÇÉkfðs1|‡cÚ(ÎÀ¬ æÏß±qÄAíþûl_?óçmîž\zê½A?”'ªXYö¬€+UtbŒw«žƒF>¾< ¨Ÿ† ãgÚ‰òa‡¸ú¡Rj‘|³¯‘­ŠRS>WùºC½¥|TD¾>ÑúRt¦#‡tPLUv¸u– üöÆ‘Ô|þ+òÛ¶ú¥ªâwú>ÉÄzœŸr”]ÌOJ't‘©êx˜rÒ`Ô±—ì¾Î*­ gŒžæÉ>3Õ›sd„­dCüìòÛñ &r6âT®G´ä9É^Îá„Û ÚÚ;oH+€²áHšHL#œ[ OÔBoÔ w¨²©…Ü@›Ù–VB CÞ=ÞºÀ”†HþtJ)Œç  ` :wïCÎ_ðš'-‹”(O!ìôÎÒnÁÖ~ñº+ÈN«—ùçC¦ËÏäÁbUû‡\L¨?;dÊĨÏê:5åiôÔÆâ‡ì+ zäent‚GÁùáŸt|²ÝŽì¶XMýZµ‘Œyr5#-˜ÐøB~ôâöç~x;øàý¹ÞýÎvÿý˨}j 7âA¯ü DÊV–v‹‘úÙöŒob_)u€±>˜ñ%RÇÅ«7¯üyمʆ#AJÈ™†|Lá¯ŽÄÆbJ-×OÕÎ9*×y¬³ÜUÅå>ä•瘖ø„Ä7þé®]˜ôÏýÝ<4à™öã^ßÎ>ûç<]h[.ƒœ•þæäâä“k îÛÎã]#×ñÒÁeO­çæÛ©¼©xÛÜÔï徜+M§nœ»é³n·’¡Üã3Ú]Ø*þDžã6ø' ÐWül›ò+ õc¥øÇ.ŠÖñâ³ÉܧuÅ•··ü›íc{s;·³ÎþzûÆyW¶çî;»qåuºö–“;ŠòÅbÔ*\¬Êñg”ú§A@…!i ÆÖm4H"¹|üær7eâ{=Rã“`!¾;/ÈŽQt—„0#ÏO×V.‰ ¹íäâqšBÎñ€T‹ í¬vÔ}ÑŸJe]iÎhCšÜ¡XºÖ®ß·„„†»*$M?§N)Ã,ömÏ&©3—|2—›…LÖÍ¥ð·\î³øíø£÷å@ÐIÜ`kù~ûÆ…—¶•LOzõ<΢>“ÇÒq½­‚†ñ.ƒ0ú–ŸãC.=‰/ÑË·Æ Ï …,HŒWï75ÿpÄsúv“Ú›O=‰Ëfgñð’UíG—Ý–68á¸ÃyGÈ#Ô½¶­ß°¾½þõŸæ™ÿ»òèä©\*·2¶NžÄuþ|ä-ã;ï0-~L»!V{„Ívî>ÓÆÈ–q oŒëLPñµüøwpѻƩ\¦Ã:/«Ò š`­,‘¯·w‹½Æ 2ö¿´ºªmƒ±ïŒ¹È¡LÚ®#2d¤LªÒÓ ð¥oVUl•R^ãBÖQøùiŽ2»xE1’K£}Õ§¬Ý¼¬LˆŠ8´a,¥ÏT›3Àª.‘é:û…K;D\ùÒ´ó"íN…u>\þY¥lu E™Õ¿)ã‹@\êÇòµŒfç>¹QY:6c¨$ÖD~Ù#tšCÕÿ¤òÉ—ñS–ÕÄܶÓÏ#­"þ—’¤Ž«¥wKHa£nðÑæ eÑólhbc·ÛOŸ˜¹5/Ý”6cÎΕsl·Øs®‰f6¦xªûR<Ï.¿5Tpä¦tÌ8¦ œ0ˆ<X{š¶0e^WÍÆ¶“O™”t‚)ò Fÿ‰Éêà\ä'L$d _N‹'‘ Ý ÏN›Á>}XæFŽtöd Èt ;KçDFa³¤d&¾ÅkÇ3¥±N ˆ½®Ñþ”ëäe¢RÄ©6nÓ[$M©Åé¬Ò‘6ÅO¦3$€©ÐÔà u×'}„¢@ÛŠìéJíÊÓ©Š–*Ù©s’åMê9ƒ3¸_ˆÀcqw0ðô­~Ñ.:9‚¬×Õª1’br±,^ôˆ„Æ:V@ K j ÿêWíÕî¼ó6ÖÿÖŽ>ê@®ËÒ¾pÆ·ÛöÛOʽ(V¢b>“.éJ˜J:´ÊdðPªõ‰M $ øO²÷ë 9…ÂL>5&YÇnc.8‡xAZ‡ehfL•K<ð—Å)¸§ÜºÂš Šó¼ì53Çól<ÇM( ×Á)-KÔ[M]á6ÚYÔý—‰š¥’PÊC™üç@™Ô+€ŸVê?Í)ûJvÚ„¬¾oýÀ`=¶Aì[|…ôoä~Á æµ…ûo“ËlyôñvËMwµÕ+ÖðÌÿ­ÚΦ­á¹ÿ>å./#Ì °§‹eQ¦X3¸™d‰‹)7îÒ¾èÔ¡ØoŨ—ƒ î¸ïÊ“¯Öq‰òEß¹“Ýôǽ8뵉GÞ×^H_|äá%¹!ùƒzg=—´äÉ_/ùÖ©,úM‹™l_ ™ŽI_Ù(úBÍúcR–ÿè,œÊr‡.[yñšŽÏ©àÞ½a|ËÜOùÊ{tÅàÕ)3¡ t‡GrŠŒ7ñŒ²~#G¯&p½¨G'íD5PAøìòŸÂ>ZͧM:¡=ñèš¶0÷äœ_×NjȸÔBÌÀ… Ïñ0¤%XÜ6ä’¡ Ï·cº7P]ÉRqeÆ`Q$u£KW¢œÞ’ù ^U[5Lä¬ê“Ú3„"·‹G¶†Ne^ ÉGçæÁß2m”±S€võ:´ˆ$¿²a£ÜZ´CíÔtüvŠ=tWÒ‘³C¥Œ ³P“.¸Ð8y²Ü[ƒ¤¸ÔKt‹ÿ=I'˜WVdÀ7Ð/q¸)¨á!È#µøÄU:2ðH§ÑY(G‘噲ƒŸ¯ÐÕë½—öX³Ê£ÔöïgÚ³}sðèÜ÷´e"P&|:4H1:G Õ£|ët„>äg>¶Çïú#-‹$,uR®gr³2 m6`&U€,ý¯{2Iîéäѧ¥ÚÄ®BÄ>}­ÝŠ[Jhå1çR 3è…òÈÈLÇ&}?õÕÛ‡²ÆÍŒ“ò8C¥}ÿûWr¤ó'Ü 0¦{ì‹9ЏþÉíèc^Ô~àyí¢‹~Ún¸fïaXÞxéÌ6ƒ¾êÆÕ›®ÝaÍö×ÎWSkÖ…¿`âGÝÊÞˆ$Ù`h‹À²¡Aµ…§­iÃÄÀÐ õñÁN¾¼‘ñíoú§¶ï‹fr]ó;Û>Ü>ôá³Ús¸dSö½ ¸Z ^ÿ»cŒÕn=«_¬³­£OLÃOåXD½í?ôç\sÜw(J“2ŠrÍé툃lI’E,ÙìHS¢õvƒ¦¸Š^,¶]7$JÅ º* sXžr‹~åØ>Ö@OA&i4ŒGáâ/õ£j$øCY]k Md[N¡ü€·ù¤×g¥:õäu@UBuÕ/ub!o¼ÆŸdŒ‰ìÄÚ9øÙnÚÄÐ ’ÔáØ`©ÉR¨ÈÎ'õrù”ãM)ª™Þ¬$”£(O<ÝsÏ^ܵ¼½ú¤í ox-Ï|¤½ã´Ï´³¿ú˶çnÓxäð”ô)ßÿ“ %âŸøJ+2: Û$'Ä¡¸tlÊ@£š¡3$æ°_ßJ?nܨöÐýO¶—¹çø/äÌÜ.K½»ýÕ{?ÉËÿ˜{wþ¢½ù Ÿä2¾mÛg>óå¶ç»¶k®»³­ç=>Ös"gÊŽ>z¯v÷Ý÷æI{/X8+;±Þ k²gÕ=;…¾ŒðöK½ÝýâøY, T(\ÊH‘çö(LEÙPu&¥[ïÔÆRí”K¬nWRX¤éƒQBã+4ÃX/*N0àY€Q£íácRÚ$” yÆòØjÞ¾äÝ?_"žr%87dU|Š‘^9|cdK;zl·ì–ú5}Z¿6u\¤Û+‘R\Ð@”O‚J¾²E,×/ñå¶¢eÎÚxÏQtå…¿ë‘P¹q®m+jìSµ\[g|r„ÜÚ”U­$R•=´EùJõ8سVD°"ÇöËPîšOµñ¯Æ9°ßÝDX:, #ˆð—.@]50…F‡ÐȆÎ(¬ÓF5ñ­£»tÁàác *<¡¥ž0IoÅ}á.Š2r="ŸP¿\1– ÂÁ¨væ„ÊV‰yKèЄœ?×þ{Y 7Iz ýrÂn’v.ë”æQͤc28)sLç“‹ÒXØ;BÜÖå[ ŠLøQuÐj³ü 5¸—ýÕ Lf­_ àïàbãè°Sq¬c€kd¥­B§.‹PD¡úœìZ˜ò"EQ*‘újG%uo®g‚Q9úm§§·ï_|EûÅ/—´ Îg»—ë4ÿìÏÎcB;7Gì2Q€¸ÎXÚú¥;uì×ŸÆ +~|l}ƒÚ`^…ê$í¥%NtÌJãÇÓ¶ƒìL¨ô‰nú&tÐF'º”¡.W&Ú•8RoŽÂÙ€›¡ wÚ=º'2uŠËö‡Fh#—çÈÅ«XžLÈg ÕwÄ ÕÛ³Ã4{{_:ö /¼¦ÞåÜ€;ª½êÄ9z¸;SÚá¿óüö¹oûÁ%¿à±ƒwóÖumÁîÓx¹ïòÀ–a䌑8l·B, ðöKúXa‰@dŸ{ž"ïè;d¼ð"€ÆÆûroÐ<’ Ÿäq§×ßp3—Ni»ðÄ“ZÞ¦1ÎçÆá ì˜dÚ~Ññ R_瀀Ž2GRßQÉG—¦è#kä·7ZÏ?«`3f> òFP àˆ´9tÙaPõÆHhÉÆû 1e½v¢ÁŸt©IÊCDkI‡WOJ奈]wp[¥ßc+ãÆiªöût ÍV¶rjÇ8™ðÉš³ B!c¾¨ñù2Ù`­ªÚ2|úqd‘88ås×Wc—v( ö!øõ‘Vˆ4qK2ú ñ „1æ8X&—½EˆhÒçz½¸J¹}I%ü\Q®n·Í_¾lm;å”#Ûœ9;·o}ëGí›ß¼˜³‰÷·çì=“ƒ†ãroÑúþ<ÿLb±‰DñÞ^~çpÕÐlT¤?¢Ãö’N_ºÅh¸è ù«zˆ7q0l÷Ýgµoó—í˜WÁe/âÍç_nç|åLÎiïú³7¶³Ï}O;ýgq9Кvéo ïNn“x¢×…ÞÆ%r¯Ë£AßôGŸiÏÛ{:gC¹ˆ¾ âŠv|©_]²1¦p`Üã=8)ÈΡeVºÐø±Xkü¥ÒDè Œ@¬'P•XCºý"G{ÝvGŒÄ@Ø©Ï$ÿf|‚&8Â?‘§FWƒ\ukS½Cf*«Vó2î±Î‚Û¨ü¯ T”bÖ¤áu«åؘµ)+öªW΄ɶ{½¬2š"í`·žê'AâèÔbˆú?”hdP¯!8?„þÿÝ$Ф÷™âT„!Zû„¸äóþÆœŸ@®qYJn6ÜŽu2”³¨®ºôáH(eEp“ã›!Ù>õV¹mqÍOËR…ným¾æiƆþáߘP¼•ïÛÝYˈ>¡~¯Ò¿$aTXÉRmkoíY]š!î}xé i£”±R‡çÙ¿ß’lçtVZ/pÐ:½ÌÈü¬O]5Y(–šÚ(HaûRÄ’‰/‘`™‘Ȁ↰ڜÈ1ÈZVA·UŸ9äVÀ〒šYe( ¾ê¼LA鵿F D â’#&eTg¢ Ù±;`H‡‘ÒIC‡è²Ó’‰„pL[¼ø¡öè#Or€7sx#0ªA 5&˜P¡þ2->R¬†£^–gg‚AÕ8Ð¥.úÇ“&E†>¸ÄÊœì"¦áXy½bãzEML±¢š?eª~‰ ã…ˆ/jP” äY¬â;U‰ÙrÒŽúXÓæÊr\$/ÉÆáÊwØžÙ¶åÓíÎ \|ñU9Òô1ðÖá¹íæ›ïj>Êw¿ýöl?¾ôÊvÇø÷ñÕmÞœ)m"÷ lCÚ¸ÓîLf’ñw+ &õ»ÊOÿ˜ªöQÎ_Åy¼_~,r•ýÏpÍ3/‡›8¾söÅíWW<ÐþùŒ·µ½Ÿ»GûìgÏi?¼´Íàhè.¥P›;æ™t(#Z±µú¥¢)¡Þö©çóCm$ÁÖÛC9J@¨ÃÿËkC,às·;9ò 7d¤m‹lÜ(‘{Ê+Þœ Œã¯â¾éå Þ‹à%L.Ù!íW¯ˆ­‰Œ'dÅvʵ&ãžÖ¨Y RBâ•Db+hË,h?cÚ¸¯ÓçåW¼LI›BN"XZªüObôU†@Êã·Þ¡»j§¸”XìXçÙ7ñÖ¤P+l%þU”tƒ=U¦âóqÁ¾ ËgãOŸÉ%‚0í½×µÅ÷<ξ÷ryÙä6fÛ1<ëCd:yxúMšmú*¶ TœbÓÝ‹ðÀUcV/Ó»yŒck®­}í—^ú3Š—õ=¹luûÙ勸ç;ÜÏô`;è …í#÷áöÞ¿üb»íöûÛ§>ýžöû§×>üá3Ûž<‰håSk¹y|ûÄ'^×n¿m1ï¹½vðnàb‡Ù—æ(Ý'ZJ:˜?1_ æH}ú£ôE–1Âö®ÆVˆuÖºŽ3°¯.£„-‹¾W¡ã‹’“¥Æ¾R|ò³„¦° ö›טHÞ‡ZØ®Ãx­Îš«LéÒÇñÁ¨ï;¼xE4t½Xµ.÷¬ÑW¸ÅY˜-ÓÆÌ¤ä)¬“½ zÆŽ5¦Ð]PJvˆaØ&‹=c.>Ì<‡qFÓ×Lè£RH!ö+KÝ€2V'>ûØÖWÒjçÓ¾(.ü%¡<Èb ò3GFPüC™²õÚÐïóð8_5J¬:}F¦ueo…„5,þuRb^_ °Ó›TVù¸È;#¬Ò…º|#1í.Hñ:6hƒM‘34Šç—zm$Jê ±_„à;” ó§äºô§ƒèF–$ ž]~êÒM€è5Obm`d1à ‚ z›.3!F‡bƒAÇ|…àƒuxc¡é ‚’–NÖE'6˜ t\B]©iÏAÖ»"X|<›]3Á\â ¥#Ê XybB—•d$`Ñ/»É°‡Ÿ@!5 óàƒ‰Gç‘9bÑS¶—,{†eéìd7á6 ËÌð¿–eè3rÊSvÖð›Ãßñ]g輦=5Õ£újÃ:ò‘kÜÁïê"â4[š0¹êÐ6¥£Pé]X«ÕCÇlkúF¸î ñˆýS&äÚ(nj½ôG7ò²¿Ù\?{$7ö=Õ~ôƒ[ÚÎÍγ€êж²³tëw‡FQ¦]‚ªüf²¿ÂßVj¡¥¾V‰A¨Ã-î‘ØîmÍn«mGÊE~µ?“Jbº–.œ _âDšaÆ# g-µþt´Bi;ó GôA½Rmûì_fNZZþ|D Ië§Î˜ÔÖóødïIùÉe×ñ(ÄëÛž¿Ô˲°OÞ6êˑްpoμ\ËÑÓG¸$ge[0oZ›ÄÑx1oäý+¹îUWÆ>ƒ‹ºàiA¶ã”×RöýP\á¥ÞYüD`í²ëŒ<ôÆoÏQÜ]x¿Ë 7<˜w̘1ÊÚ(¦PëÙŸô%¤Nm´BúGZÛsüŒÂ,þôÍ´Ö0åCµMúPœ`)”V z»/Ôê1^]ÄðÏ`@QÆ %ÆÙ ?©âËøÍÜI‹öÕ˜T#Xí™–TNÔŽR©f÷™2éRwÒ0(tûnù1($Æ@wf½t±˜#.i}àÑ{°øemÑ­+Ú_ô5ípžærÖ™0‘þ—¼oÒäqðùHD‡•øù™,`w6ÈÊEÿÝNyýsÛ//¿¡-ºëá¶lɺ¶ó®Ü±í¨ô_j”pA®MYqˆ¿ü4Q$öšH™§}ÊñÁ‘>k;1ÉX»jSžTtçí´“>ûÑvÂë÷jÿôOïnWñÈÆóοŒ¥Moë}A“‚ÑÛÍ”rRåÄLz Pûf=Ãß6P7$²‘V†e©(°],$æ‹ úy¦nÀ W2«N6ô©0ªÚÜO¡FÚÒ˜V§¿ÈcÂNä“oµcû!užmq- }èÙ3ÕŒ¬‡h-4âÆ(³hG:·bö›˜%¶”. Î%dª.TXÏä(mOdƒ%òã¤.BòßÇ&êñR&©5œH㸠7ߨJ>>èÜ•V~ÉKöþÛ‹‚ąQyŽxÝëŽ`õѶzÍÚvÍÕ7´;n»?—Œã²1q®å ¿âŽÿ5‡Bñdamùuò…¨ªÂ²Oz0)CbWä”?S®ïgÙÐözÎ.mŪÕí’oÝÚÞú®#ÛÉLö‡û¯ºj!O8û$; ˹à.gÜÔ¾ôoçó¿kÚ>û̦|M{ïû^ÏYÎÚ©oùL;ø Û®¼Ðÿ«wô«m¢§³µ—ÚÛŸÜNx‰fÁ‰KH‡¸ÑFí©ñ ¶*Õ,‘,‚lœë,Óœñ˘oÉ Ýq˜­6¢>ô8fÕØkœ[Á¤Ñ(@NF7ñD`Ñx¹¦€³}¢.¼ ˆÍÈ´XÇò!9ú`“ÕYJDÈZ:fÑ÷"Šs&H¢ÞL>àÐqW|É!œzmé‘IJÄ)­ð%‰`U¤ý11L&þU Êâ4Ó&Á%Tð¦}Ы˜^KˆÙGŠG6qeßž"íÕúÁï^ì3@%P¡|åõ[ö(·ì‚Kyú6zèk!˜«=’t„ØHKÂŽ¸}_¶ƒv¨ymþYh¹°P$zs(ôpÞ,ßfÛ (ó®Ó²*s±µÅƒ…nPSÒ]kÄZ 7WÃjƒ‡ÉzŸeb]ãôƒˆÄF:yúž/·?q\;òÄ9<hÏpªí¸ãlîàýkãÓ2vx¸âºäD„¾B¤iç&~ègdùÕ¿:msž fâNËm„Þj ‘‹×o:7ýÍb—2²‚‚¬2sùmsS†×ÅÓÓ˽DžýÁvÒ'.Æ¿}¡ÁdY—QGu¥Tbí¨Ë±Ê¸Ë$„u&;ò)“ÿLFäAQù¤ø­µ6yé#÷DÁ#.£F!² 2OÆ>õš¦Nï‰3 e9zÇ:ƒ<|N]ÄbÃ1šj‘µ~GªÓ@ê†ÙÎ[ó ÀõkÖ·û/m÷>¼ºýÉiG¶ãOøžiûÓ?=¯íó¼Im·9ƒDìä-ãĵ1ì‹÷‚¿t ª”¯lóÆ&ˆc <–ƒ-ý‰DY•Ÿø®¦ˆ]ùðn3jt{pñrŽòÜ{ÙK8Â6ëÛÝwß׎?þoIÏiý¡·òîwµ—¼ä¿ó.£5y»÷Õ×ÞÎÓŠvDØ6Ì›ƒ5kÖñrÄ)iWïYÐîtŠÓ31NFÅk܈^LnZLŽ C"'¥J¢¬Àç­Á’ŸÞ‰]m3 àó_¡HDT4'¬ ‚ä»\uZÚ0Qoc"zĬ ¤M–5Ê(=¶Câ'ü½)¢#ø}JäþmQnÓ–h°Ÿô—”J«xå‡Qs’OôÉ—ŸnK¥p€,FçÅe#l¤ÉiZù†>–­8ºƒ$ýYòFpdЉ©X?ø³ £¬PÓ’»-£2.‰ÿ‰O›å÷ç”Y]–•O£}Ä©¶ð±¶¶½ÕÞæã@ÖO; S/½’GIt‡],Ú_ã…õò ¿Ú¶T»ÈS6˜H&tñ"û0$úCUü¥°³ÉœûLŠ:’‰Ñ¡–ãÙå?ƒj¯&¢a ÜaP&Ñb´ámIB¥=ÝŠØ®ˆä£B±B.uФ½ˆe­×5()O|‘µí˜ôÜÈfØ9å¨;Än1Õ5±ï@¥z+¨Ž–ÙáÙNlÝC÷Èp®_gm,”GGé²ÓÝs82c¯x­Wzub‰³QÑ/êS& e¨Sˆ9Õ«z[7"’”NYzÍiÛÞ±rÃ~ÍIˆÂ(Ÿ&ºtÏ‘ ^Jd]ÃU©Oÿ8}Íu¢ÃŸlHÈÆ("\i+ró¡ -¢ ê± I)­é·ªP¹Aó:ôÙ3§¶»¼nöôËÚ§?õûm§¶oïþ‹3ÚܹÓòÔŒMOstØsµú 1Cùüò§xu÷%0’ʈ=7„Е †v1/ôÝS,Š ñJüäè•­&­vˆÅ)_µ¸ÙÖ.c5µ(³*k-¯ÊuQ†€ ²œSKáWÛŒ%wÊw ¶lÉ©W·²ÕA"qMÚ‰„ñkƒº¡ÍË›r'Nª'ù”µ+®¼™ Ìœ XÑ^üâ½Û±ÜÈè£ /»ìÚvøá/h¿¾y—6,k+–óÔ.yØvÛѹA{#ÍSBÄÐ7ÒÙ k,Ö.})¤Ímœ)¢\ñR0ù’7ȯ¶L™Â£[p£o¤ýR†Œ`N¦Œ€ß±ÀèÉ$wê^’Ò]÷#`U°@g—yÅ©Ï39pÎDð ›8I›” Ô®38tÂZíÊ*Iò:)vŒ(>J F÷_´•zŘ¯ð ¸Ø¶t .;©ÚìƒʉCŸ¶„ÇÃN7®½ï¯NÉÿïñ$«3¾pNûõM÷µ“xâ×¼oXǽ*tU,:«¯¨º|Z} bI'×2w‚Ä'¯|Ú% 6ÅøÑÆ?´»Ië?“S/Eœ¿ûŒöÕ¯^½KSÛûÞZ[¾|e{ßû>ÕŽ;v~[µzCûÔ§ÎâÆÞ÷ð;‰7ž‰3móò´¼ .¸[Nm3¶›-ŸnG¾|GÆ:._ÂîœùAMô£-S+!º±IžqÄaá1鳕Ĕ˜§ #•ÚÔ9 T EPëo…´£mŠ Šßjï!„loÛM9Ž-i7åÈÁ½Œx2ï¸ßK¯IÚL›Ǒߑ•ê@‡L Ý¦ÀžËK–Áô’¢ièŒm4®Ù>¥÷À“®-&ðD.„ÅöEŸØÏc«íMMI¢Œ¼7·ëeTM×ÊJ›ýåR!€*3ý¢Ó*.r£Œ¿ ª<}+ã7tÁÆÚ°Ô&¿–egÙµå:!ÚI¨>9“ó/þN?—N[%´¢¨Rün  ±=3TË+Pûu9Zη•+!¥[H+=ÛºÐéu*Õ´¨’…5í Ÿ¥î`ENþÕJi‚³êl³ºüRœÜl Ìß–gFxä{vù­yÀØÉ€’ÆdòdøfÆAó’´«­Ò*Ðl[Ê3Á’pq‚@êùšåæýã[´†Š«Büœ0“AòÝÏ€W£duxG«…‡_QpéˆýÖ‚WnõLÅ•>ê\"ÁÑ.Zº¶t$¡hS ¦bÆ¡¦”G„è.ļÄ$GÝc•~¢Œ^£UØ1ÄWGû‘NmŒí%9T¡O;JÈ«9k}€8M²ÓR‘¼´£;hªN_YÁ®5ˆSêVšŠ`sQoƒ®ÓÖ$õàGŠÝ~ÙóäØS6i©­&kÉ&ÁâÀáÁž 8ñ„¼àênò»¹½ímGÅŸç}í§mÇ&ñæO_<§m(:%ÝœëœÁcfðÏÆ š.×Ï ¸š”•Qý¤qÅæd(cM]âD¤‚¥¨vHK+IVÊòÉ l¨Ã§­”Qg Úb"N¾óÙ.%°¢¸,ì².Ž#/eVÈkƒNulаôÁŠì­ŒÖ­”G¥o%ÕGNâxpI.úÕ¯nn<ðH{ìñeíyû.àò‹Û%?¸¬]|ɯڡ?¿ÝzË=ì(¬â­¥kÚŒ™¼¥t,OB²““ê6ø2ºP,ààwƒŠÃ)ü¨…9Úê–9\qïâ'¸ø±v(—&ùLõs¿rc{é!;´ñ¶Å}ÙäÄwzÙÆrƒV^ˆ{uÅ(¥Î¼t ¤Y #ö½Ç94¶’ÜÉw#gt£ô)uÕ }¢¦ û,³Nßék9JÝ6Oópª7™V„~ ¾fJ]¦þ Ì~8HN_¸mHªýŒò€%H OÖζÍ ƒTÙ˜m§HagP«Öv¡`˜h˜U–fªÌ¾R&[aÂ6ëXT©·-Ïœ4<ÖHëQ ,D>ÄÁ`U¿£ÏøŒÂáQ¾pÔÓnèôë}\,‚çÍÛ!oÐ={&oºæÚø[âž•'ÛdÎ^mpòÆãƒãk¡¸D¥þ·œ¼å‡Ä¡JѼ¹?Jfleì«= è…¯ÃãóúBÏõ²Q¦ÏV¯\ÇÑüÝ9‹v%o¸^ÇdþXãù’vÚi_j¶Ú¶½ùOˆ¾åO-o´;/3š·ðƒ'ämÞŽ'œÈSÎX»#S“Ÿò™^)?é1)š±AxŒ-ÛÐÖ–æÌ%iò›]Rþ(Ÿ‹A÷2›(¶åhCçÑN„ÄUÄjÊ cX,d‰‰ÿ`‘’EÙ/‰9ê{3XZX¥QO*Ê.wB†ö²ýb7¼6ºdl#©?þoöÞüïªÎó=Fz©H§„^- "¬â\½t•µ®k«Îè£ãÌ<êÎ8ãØÅ†ÎX ¨«¢H”"M^RH ûz½?çûOÜ«»÷yÖrïÃ÷W¾§|úùœÏ9ßómÆûI—Rƒ°ŽÐuPP²‹ ¯Š7l£¹ Ø—že‰Šò[åùíÛÑÊl1 ‹è“$ˆ7èˆ,bw J@‰2ƒ'|º–7õåjàaQ}QH•å›¶3X˜¦¤âBTù‚#‹o¯^Èw5¹ånÚN¹lÓ~”!2—Nºt†…ØÅOnÀWÈ´a Oñd¾á<Í‚ˆXú}þáç u%6-ê9°{>÷Ii?õ„gâ'<ðn0Á§<ïiVH=ª‹R%¤|þ¿¾ ƒn£ŒNí7l›òí1YŠd¶­æ§uôªÓerY"XN#ëÈ&r‰Uæ³çöŽ)ôÒîâéžê5ɦí2Ñ„Çfy$¨ÿLª¢k*C®Lo뎚‚OXZó4™ÆK4Û'~¥)ŨdÙÞù%è*‡b¸1ªèm%’‡êúg´Ì@!Ku®@¢Àvj÷Ñ¢ÌTúF(5Rš2±èLV¨—¶å’(;”à‘Á>› z1(å:W:àÁOyê‰$%‚!ªIéY‹üÙ“ é 4FËn‘ f¾¬)ÁIäÀ›•¬Ê°Š‰èÊUëÚaÛ77 ÏŸ¿s^|õà&ŸýÊaEbÔ•“ú h™K»XŒ´3nv=J#ШSúLj$#œ052‘B.åÌ®ªZKÑÆ5A€¼6’×`‹Ò‰2Øæ\_š¦þêí&Н&^êÏ–:¥“f >BF-õô#=e—eN>Ü:: ÚÖ+~h<ÍÖál[a忳—1PYtÃMwrÖŽ<«üZž¼òyîÁX×öÙk~;ƒ³~v^ûá.h‡¾„§—Ü’=¸a—dŒ N‚:¶Ó|š%)äÀÈÊj™îýyÖ˧©ì>o:—z\оô•Ÿµ§³?/<û+^¢t~ûíU7·IS'†—ö‹ÒL[$¿ ÍR¸ì2З‡ÐØiK ŠTx?„—EÀÁƒcKì7’AÀ«ä蜼|”ÁJ„J?¦ ’8Ñbµ¸Ô9žZ°€‹ãÏ{‰l'\ Í™RåÌf‚öST©ö¶î•ÙABÀéÄP0›3ù+»¾ÊW8ùÕfAù®F©k»¥2PÒB7 øqPçåu"ª#‰ÜÐÏÞIltë¿ÒÇx%0pîºüOí& ØûR\Z6–³R£óüûw¿û•¼Çb:ï‰øl®¡ÍAþBÞî3é=[TWH7_È Ã°ªbÈÛ]öö5Û$0æKQ$‚üg Ÿà ¬ñ5<íGg~<7ÏßÉYŠÉS&·W¾ò…í{gü¤}ò“_l/}éñmÚÔ)íÚënj/~ñsxÊÖí»§_ØöÜkNûŹ×ST;ôиà´vÛíws‰Û ünsñ,eß.]´9[d;Á;÷žuß™äaKuÙȌ؉BÇúõ4µ†×Ö[fŸðàÛX–ØB± ïžº^ 3DuAø+_ ã¦/ðÑ_Ë/ôŠ¡ÿ@=*¾CM¼ yÒ?Å´ýÂH¹ÄCt°ÈibXk ¬Î¤˜½›¸Ò«‹ŠkÆuÁ•Õ-q›ôï[M«}ˆŒöçabí³„£t"H›­º`F†”–BqÄáÀ[¸e‚NÍpÆÅ ¾òá}oŠ .oÒYú¨«¹†Õr6û…Ç’V¡ÿ”Õ2è\³yF€4¶È)éØFA b§d0=x"JU™œXÆ¿,.«XЬ@ÑÁ{[ho[ı8´ìxÒ¡Ü’øœ:)[UÀT&é»Ñ®Œ &VI+I½€”:|£tlK2Ø'¨YÍ ÀCÞ½K(“7Ÿúb°%Kf·ï|ëì¶|Åý\[ûšÜ<÷–·œÂ5·õMïÐÊœ@ádâB¾ ŽÂ$0£r™ÇV™4$g¡6âß¶÷šiÔþꨯÅñ0ºú¨¯¬Ô½_ùvÂÊZ³Ær¤ÝÄ)OÛUiÚÌ¥`G>~×6k®ï<¨Úv«f‘(rcÛ\î¤m(°}££l‰&,ñ réÅæ6‹7OáB'¶)€ì%J¢È'‘~ÑûR*èä Ðÿ)J Qj:lbØï”²o$ëB­ZD¨‚$a½ °ã%o©‰bÚéUM9 uüØ´ÇÖW¤r!ÙŠ`¬¾Î@K›Ò@ؤB2ÄÂH˜jgà‘¯8¬òHÏú{×lÈ¥)ÓÆÓ¯ok]x9—ÑlÌqì—®{Éš'>ôüÄ»"ÿô(}¡ûSú‰Ý”OÉ_}Bg)—Jƒx–º®—k™ª­è¡;r&Ò>ᮇ83yíµw¶ù vnœ{u›8á{í%/}Üý9oõýr{ûÛ_ߎ9vS»à‚‹Û—¿òÝ6jléø‘¾¡Þ¥íŸÿéË<±h2ï蘞˴†›¦_²ON¹ueµL†¢2YÜý@üPèíŸJuïyWº€…J߇ªmœ6u3~©´¼Eµo‰”bàL¯¢e‘u®˜Ll‹‘ a#l@"2HòÌ ŒLÚÂŒ•¶\H"E‰³Ô…¿íàá¸QTÐUj2v†i'Ò±¨ú³ÙJ>À*k ß‘Vnb þi RP —tyõ 7Ù&ž3žx0ÛY!#`Œi“ÔÏÐ.µ`S¦º¥gK‹,è XqQZÑSB)†®r(UìUcöN¹eÖ*2Ù'–›ºÎÌ—Ž ö¯žpe?dî|ƒË_É NOŠª<Üd‰l%'ü”³s•©í'¨’T0öÄ7g %RÆ3Û`.ÉARÛ^$éíkÓÝশiˆêêƒñûDÒgü>ðàƒ\÷:–ël¹9Ïëú€qò¿aÃÉ¿«œ¦re*ÆÔÛ×ÇAßAgY[dE& ]­ÙŒ6Ñf5`KGg·¢{u¨<&ÊŠ€±øÕK+» wT%HÈ•ðy„1¯ó:ü‹l PΛv3O½“†šèÄüÔ—òTëÝl ¥&8:uq¢Æ™­Š©UI’SEvÈH8ù}K‘ •]zrÌž–I×ÍÕ)$iˆ'o½HªÃf'L«w)„ePR]ÊL‰“ƒ ê¢ ÿéÂ*ää-6ÑetfA!›U*i;zk/ vÒÉGzû*’}›‡xêÆŒYœÄ ô/Y-ÞÔ>ü‘ñÄš[Û%¼éÖgàGOÕ0ð9i—£êñÉdQiÒŽÉS9Ø+òQ§%5Âò‘’[p"ž>Eræ@Êö—R…‡éøuƒÜ©ˆW€Ú£ÚW`ÛŒUAá\Š«oI„tŸùÄÿ;µxN§—v'í ©K×âMzö¡J{;‘«ƒhëË&‘M½x {¥ož ÊX=÷¼ßpýÿ¸¶–§2}å+§¶»î¾‡§š,j¯yõ í¼_\ØN>ùǹ„cÅò»°ÍCÜT¼¹Mš0.g“Ò—J¹»#&¢ñÉA ,¹”ÇNáÑŽw¯¹¯½ûo>Ö&s™Ò>ÿº¶îþûÛéß=·Í™QOƒò&b7–m z«mÇ"€:ÉÏÁ™¼¢'ùûï[ßvÙe\[´ç|Þ¢<%~fõcÛ¿·vàÀrC»íÖUíÖ›îjÿè·yOÄx.™™®«æFq=Ä­úpù²uñéGg1ŒŸ‹Bºj-:ÎnÒ„ÏXÏ_ÞÍdõYqôàØ;ª­çÉCp†k§±cÛÎøÞË^q8+¾ˆ{hƵoý¼\ÿÿæ¿|%—ý‚G~©í³Ï’öŽwžÔ–.Ù¹~Ø’¼”lÅŠÕíþ Úh\€ÐußEPeHFFòµÐU2«ƒUæâ㊥|üÄV¦Q'@™¨A?uÐ5¾JÀ1#7k Û`Ç=mBÞ¢( ì0Þ 2elTAWL²W†ºÉÖØb+­è#EyÙ:‰;àf|PŠS­|„w(“øÚB’æá'7ã±ò:±tSÎäE3¯$ÐJR瘟ÆeoÒÇkÏT$v”•ÙЙõ“U<åÈØfIÁ ™”[|þ¤qIz –kàÉ+}&àì= pÌÎ%ŒÄ}yÅÿˆƒ5`[Êõ_‰Ë22ƒgã¦/¤JÆèïåÄÀ—Gçêù~1¬&L¼—šQÒTÖØ1º÷ƒ+xÖ„¿ð œBD©+öÒd+ކÐñ(HàÙ÷ÿmÛI½êʆ\<Žœâ"YŒ 5J cgÙ~Np|öðúLÜÓÄíƽ<½DßQ÷7nÊÏ íÚu÷vöÌ™¶è€8úd¢ï`º7?ÍØe—ÀÝÿúÔyð°}Ú ä²xÑà@IDATBÈèÒÛmø¤ýPo6 uHY_Ý8þ¬k {­(þ¬`Ó¢9ç°£¤žrÍ+”vÞÌ5·É¥’Ò:Üpž¤ŒŽ'LÒ‹ž.þæI»Rîìã™LÚaurêä|ÒU—DÚ]…޾JX2†žì,;ÊPè>xÒN†”)ãUä†';t&¯a(1YWàäp’¥Ú©ˆU ¥½!šŽG½ÖR7·±žR õËÄ›}º2z‡¾€vë¨Ø˜ð2 ñ"Š…Ë.ÁQ~ôâÀ6|À5¦tèÄʪ´ÆCmîd€zñ¯®cux ÷ÌfžÈ £ÜÊ*ÝŽ ÖkÓæ‡zñ‘·ršï{®b Ëæ´±dŠä¶;8…^ú6â“Véߥ¥¾hw}„é`8›éMŽÂÙ6¥3ûnɑˬ u=í^[¦OÁW,ôéLÀÊF‰;FðmúR *Ë÷«mƒ§‚âK¬óÍ`k:úF¥Ü èÓVä?·6ï2}BÊÎ<ó׬†ÞΪíŠöÍoŸ· ÿ¶vøž\ºñšvüñǶõë6¶… fgw7 ?°qcD+½ð¨ð ã² É´þãåÞŸ0a§Ñí†ß­ÊSTŽäÅJ>òœ_ÜÈ;xQûi}“oì„i4¥¦¢Lé^õ8“1sÖøvÐaKyqÚÎàhÃòßÿõ=|ÿd´”éOMïO¥çŸŠÎ#\:6¡í³laÛkÙnm¿Ð6±áʧMf•_M;Ú®ÐwøÚ_„Öî•Â*Ö˜­ˆ+¬õ%·†¶ú¸éV‰9`65–ËîX~/ø‡Ûü=fá¿›ÛêÕ÷ð‚¯CÛ;ßõÚvO%[¸tFûô‰çµóÎûU;á„çeü~û_Ž'ûLç%†ëÚqO‹Û{Þývçª{ÚŒé“kQäÄ"åRÖòåLÈZá1CIÒ€©ʼnø¢/^7VÒÚ ym•þ€oKÿœ¡îiÙÛgòë("ÈCc8WS{[ä.2*§B„¿D"fʲJN‘óœaÒúÏ”"ÕŽÜÈÁá€"²Ú6ÌyäéP®q“B¶ÄF*„3>X2–ä”o‘7ñ!H¢âKàK©S•lÛÀH*\øSײ™ØÉ9€eÆ*hko¶ÒWšæŒ©R–7eI¥´×U›„®`i«Ž+9úà?ÒÆ!W¼*®);Ÿîûåày:zÁ»"GÒB)› ÚJžfƒôp/ uù»TF,qbhÄë|£~§—Ë;3¬¢¶×çÒÛàùЉ²‹ûÒÃ4}½ƒå± RÊoÛ3Ào7›J¸z±tÉ¢¶`þüöósÎã©´'>îð¶`ÁüvêégpÍêÆvÈA²Ú´s;í{?hî¿o{êÑOfpóq|[Ú¯/½”ín¾×þãþ×Ùîe{ñˆ°{Û~òÓ¶ú®»YqãqgdlOºWœ±1*ÚhNrÕ@5¸ÛT¸vÊ¥ÀؤºœAÌ·å‘M-­8:ð,­Æ !W)þM÷|Q߀Æ*Æyó nJPG”ò­Ëœ¨Š¯\ôödä¾b”£« ™ß)[HB§×(«ªJK“J±#¡mëÄÒù S2y‘#´Ø;­®›CHÂÀQ\W!¤æÏ2­ 7 B Jvt]£JÚâC‚1â@-×Ö±e&¹´yY °®¬KÓ-dŤc—^ÐìD§–—ÖE,JL7ôT{ËEHxšpUÂ@¡Á•AD¾u W¢òÖ¯K¡ÔÏ` z¨ ä[¨¹üc7nã}ïý·ö„'8á|EûÆ·~ÐÎ>÷wíç…_®…·q´Ö Rä±]³ ä¶Nbá€RYò(#}Ο“õÚØG.ö|ã ú—°üröCPõ†l Õ®ÚÛrýÌË$dKÅú@ÐâÔ…>ÀƒZ®/¥i€ÈÀ/hÁsûy¬%¤cw ° zFJi+FdP5Ø“×Óò>”ê[ížÍ¯OÙi/óÚ9±Ù³1gœñ«¬ôO›>¾}ÿg2Ù¹«tÐâöêלÐ.øå%íä¯ý˜§MbadC›Âã}/ÁXØ\«§z¡³mÅ–~CÌÇËá/žÝ¾pÒéŒkG±÷!×~ôÃór?Àü|‘½)͉Üâêóš":dmóÈ?~ÂŽmÙþ à?–çÇoêöVsÛǶ=Êô§²Léæp\p˜¿`Ì|°Ý|Ã=<1g’Ý>›îiSÚmJÛÉÇ~Ú³õ£}zyV5m?{¼}6=’v/>Æ[ÏXŠ3ŠÀ » Ç_¶Š=à<êóŽ{ÚÑGОwü38ó8•—åÝÔ>ö±¯µ|àsí]ïz}ûèÇßÎËÈ>ÕîÛ°–ñ}:ͽŒ|¯o 9ˆyò“Éü¯ŸòCÎ"Œidz[xο=Km”Ï®†Vƒ?dŠ~ô}'gV8®*\ÅÒ%g¹Á9Å…«­²Ž>¥i< 0¢#ð“äáÑÇÃ˪á¸pÏDX貿|«\y|ìgòŠÒeQ¦Ä1(¬´6w+ËÛ¾5&˜@/ƒ¡…þ” àázýè%~ÆÕÂT 2Ê®lZµ&—d@ª¸%4{{û”ÎŒK>ÊS1NHó)Ý?‡8\ä¡*º ò§ˆ&l+vþÅ83Ø)…ª¹…)¿ËeA”íÈ"NÎÞ‡'í¥.’á/ñ[ß_þÃAEÚ¨,ŒY'‚í ’¼…wQ§le–¶ª’¾)~ðJNØÐÑè” n2[Ç\zŽ«âè«5ži»Ž¨ÐHÑÑ-€[Xñ'\ £}M@#Â×>óDQ´¡•%£Ä î6:{Ø^~ êA¾„dŸ½÷j³fîÒn_±ªí·ï¾íàƒjÓ¹!hÅ«Û!Ä5´cbˆãŸól¥w7¹}kk¯nÇóÔ¶dᮡݫ~è!LúÒN>å<al{æŸ=ƒ³2ù×Û‹Þqt¯34dÚY§ÐÑiW–Ói_Ò:˜w¶û© ”)aªó•Ãð(¤=Â4è׺“NåWzq¯p™¸Â ì°e"!¬3@œ-¯ÌžùàOÕV$Ý8áƒB'#µ… €ÑU¶| “•U|Ò:å–t­ª;µ2ó“g W9€…r¥8rDoŽF‘ƒGÉ)Ï.W ‹nz,éLÈlxêŸ"*K2Ÿ`M%¼¬MK¡'P¤@²ô»ðÀô[ó*uÖ¶\â=b[mì£ÜÔ³· ½£SRATŒð†Gx)!?âÜáà ­éäeÃ'àöL€AsÁ¢™^Ä‹¦N™Ø^÷ê§~#+ua'ŸVi(sqU¶0¶a ž–¡HKHÁ&hËŸe(Ïöä”­¢DBÛ7Ö“Zäƒûü¥ýrY'"m¡~ä…!ïÇñÇÁQ¨´ ð¼êÿDQ&óÂû•¯²å \?<#<õÚ‰è't“5ͯ÷CíZIT]ì¥þòâ©Z)²WÏp3Ÿ™Ø„K0¢îÎsÙà{´7ðžwÎUÜ(¹¦ýŒË"n½y9 {´÷¼ç Ü7ð Þð¼>b¬¹ëþèñð&ˆid‹Þ(‰D2æÌž‚·6•ëÃo䑜M}Üó|õýÚ©§]ÝÖßÿ@äs@ Qlf²è5´Ê¯y×ýÏž3…•Úq¹4CƒÚOê§ÊCz{Ùo2ý©lSºÙÔÞ„íY¦]w›ÁŸ|X/ ˜ÉmšÇÍÚ¶øh„ãÀx;÷ØÈú¤ãH’2üˆ¥?Ä£p¥À¥O“þeW±¢gIŽá sõj:À¢¿ø¹mù+Úw¿ûž’µ"7+_rþòöŒ§¿+ãþ{ßû—íì³ÿ…×ÍkßþöÚe—ÜÌ¥Bc¸'m\›È¬ß]»Ý¾²©Ènd(Ðß !«žb²”: !2°ŠÜ‰¤ëZmú :SqWÐj£(¯žÍÈŸÄmåLòOqaaŸKß ½p(å£ÚXÑ.9¥W’fÌR6x—¼²¥ž|îIGê)—•<¤g}H€GE°=k4«x>À [1‰§Õ)PÑ;2j'õŠP¤+v×D“2‹3ت tÀ ²ò–ɧb#e¸¡H–EÒ]»Ø"¯¸ü„Q§`XÂG´ÝRj:`¡bŒ•–%–Ë,–‚àSúl”‘Ë´ÐÈPÒ2i"ó#ì–¹N.‚p0°±Ds%t27èxâgõ^À·dW7S¶yéïíL.UXöÐ. “´º’r¶}d“"ŒZb9ÏÃOÄõ#Ï(,¤›Ï!dxËÍw8á,+ Óî¦âãX¹¿îúy‚Áº¶pÁ‚¤-¿ñƹv!7Æ­äF¡ íÇgþ´=÷YÏäÚÿÚ?øãœöœÔ®ºæºÜ°™¬É使ÿÆ›oi]ö›v÷´#;¤M›2%o?µ.öèªüG¸Û>´ ?›'ÎLÚ•M›$0ëHVRî–ÀîžöÕiê4 N¬ãH,]BÒl:YÁ·ã3*G’8¤øÛÀ‰îOV:¢Ž&|V"¬ã#‚“?{R ` ŽH©óÚ)+PÖ5¤@vAÒY; tþ¬8¤c ÒoZù%^›ò¸’ô.‹ÂxSäÁ#¯\±EÈ•,…  Džü¤£”µò/ŽÙ¢[ubnàÈl_&ëƒO©¯Eöµè+m;%8¹†3Ä$ÈÆÁVNÆtU¡ ti ùÉÛâeP ŒBYø(íX$²Ô-—j™94(‹¼ÐQ·:s@èÒ÷ruL?ùé3Ûk^ùä¶÷ÞKÚ…^M{(/˜r’úH(!hBÅö¯—(™Ó7mèÁ¶‚•h]JpÛ×%‘JÑÕ œªgCí˜ò”|R)v0õH´ƒˆ«NÆ56å¨ÿ ’œ¥VZ¶u/k¡ü ¨V`Š“L0À¹h¢_ê%#Å ¸Ô)UÂPš€ìSc¢=rZçá\£­m¶URÛÈ .ý œl`–-™Ö–v?/@:és?lSYñß•›/¼ðÒœØÿ€ùí5¯{qûõ%W´/ÿÛ÷3ßșөS&d±#7k¾NΑ‹—Ìl—_ö»öü48cÛÇ?ör®_Ñ®¸ò>&çR-NÝ¢¤ºAĶ×Ô½…÷HLÎÂMùºÀJþØöh[À39ã¹_Ä›×ܵ)qcTB<íX¾Vþ62Á¥éJÄüŸÕïŒËñlûxqÑ Ñô ý*Ê–Ï»ð ŸsåÛîp/¹=Ú-·ÜÖžóœwR=©ý¤í/<¦½í¯öi7Ýtk{õ«þ‘·ùþ'Zæ´Ï}öäö¡ŸÖ>ô¡×s5Àníc=¹í0f‡¶„'=ÌÙ®¼¼Ú™LuÞµë=*r•ï:™×ýÕÉ“ùûè!åå³EÏre®¸­üåïv`HaèáûÆP 4 °¦µ“ücµ*‹a(5gŒ ¼ä“»…©è2n•EÒ¦»P–w’üÕBb8tB¡ÓNÔª/l¨à¯·QÆ óÐsgu­‚ gYI.@(!`¥bŒh«Ïx†QÛ”¥Y,t°–„ I5;ë•FXìAd·LÞQ‹´›#eTtº€ ßäT:ÁWÆbP»ä¨>J+_ÞKÑ骺ò ~êcRò1@ˆ—iÏÄr™ïYÔA7‹J®¾WwgòÊu0¦F÷[j™6#¹Õ˜2ë#i ¶ö?å¢(æ³Jt´ !‰Ž_})é@#Bñ-•»h”é´¹Ä,Ë@<1uë%@°Ýü#¹ÕzW­ZÅõ¤³Úû.ã€x–õ ž`1³zð©¿äŠ«Ú+^öÞvy×+i çïN#?ÒN?ã‡4ïX±’ç´7ýùë¹þ×8¯l?øÑ™ j›XIp`48hÈígÓ2ÀÒp:ÖˆC(g}ãñHEÈ™­VTq±L:ªK ×fûd'”9z–< !vtyJAG3ï¥5;Ž&Àude§Hç£}t¬êˆ%hp»·%R¬ å«bK[%¬J¦rå‘ãÈ©Ë4¨u"Mi&wª~,3°…"%žåÔÒöÉÇû#1­ÁnGŠ:iøo¾¾Àô`Ý s ÌËž B䵃v'rL b:2E6d4láCz8P mÊk¤ä„È™b:9{i(gtÇn™\H‰"™b\W|äŸdï:/µç£ ©¯­h#r¶h i™Ošyê“·ß][ûÁ/n/{ÙÓò6Ù}èä\:7s–/Ùq,eàcIä‚Aµ¯œ*Ìi%Ÿá}bse1¡ÔÒ`éDÁO.ĶÞ¤FLýÀS›®7èÆïÉ猉†”²m²!$BØbµ:$W=²& Áã/“YXXãà•6v¾ì*¹L„QI]­ËäIþÅ:Í-ÿ¬¶z9ž8Âä*ýä&7SC›a/{tðKœÛwß]ñ-¬–nnŸúÌwÛ&x»íÊå]ΣEïm Ïm¯yÍ‹Úe—]ÕNùÆOÛXfsÂΠÝr†É³S›µã–¶‘ǾNåQ¥+VÜÃ;l/{ùóÚ!:ÐMX“y|!~–øctðIç%ÕÈ8dú Y>ÕMQŒ¿è‰;ú8™)SÆqiÙæÜËwðAK¸§åH®å_Êã;—·_rIÛsŸûgíÿz˃í¯ø$gøg³ø0·½ÿ}/o7Ýx[[±r57 Oͼ·@áá»güÜâCÿT4$Éå¡Êa=e>É®â,º Ûý˜ªl’²HX7ǸêßöGi²Qf?v…7´Bßc {™aØT&iQ9ø×ò5Õ†®†+Ê©7—–”mãf¬Êµ¨b»×ä¬ Ø~lí.±œy@ÞŠŽêàA¯ÆUiùªÝ·r³ÔOÁFq…`‹¨Ð^h5Ç"Å¡oÊXÙ)t>·…»v½q·O„ÔNì1dìQ䘊å„=ùh¿ªvqRé{¾ ¾%‹Û69;±:{¶ØJ^É#18zB7ã«Ôð­‘1(}¼V$ªËì±D$Ô¶*G6ªÒ~gœg¨ ¬6×ügS†\)ÞqÌ#ñγ`ý/^¶·µtb§ÐTš’Qóãû1‚¬ák¥óB¯ÛÔÊG}3Ny7Ú•û›næÔôa¼8g?žY¾*ù£Ž|bÛwÙ>¬"ÜÒ–ß½6+ùêà Ã6Ä=k×¶½–.ÉY„U«îlÿö•“Ûî»Íåž‚Å\´w{í«^Ѿðůä€Â3 Ûã}6Bu'š˜Þ‘&go—òý/ jÝ ªÅ{#ê0ñ$pHÚ±’7æ]-rË„QÚö6ƒ•½¢‚U‡ë·D–mœI7vâ6Ð >æ¤äò 3©¾ÊËyK"ý^°¿§ gÎ%FPŒÖQ;À«t†rëU-ö °ú9ðÊJåd§cU!ùT’íüå…|D®Ð–~ð•QîJ#‚)ù›)=”A>’ÉžäC—}k¼ÃAÝÈBFè”ͤ–ú‡ÂRù¥;+­’PF2$¥E™r:.–£P‡-•§ Å¨y…v­R) 6¹$h›†št‹føYDýº¶p†§åðbyË5rgè.æ¢VVecªMSàÞùB8('yjúlš)¶á/¹ÒAÚJž­Œ$¸j{Ïê$Ö*O§K€h[¤=5YQ@'k-€þ ,åkè-u™—@CÛŠ­{àæ^y\™÷Ÿ+¯úmNYÌõþ7sϯ/ÿ 72Mc€[Ô~}ÙåmÑn³¹¬çÆ\+xÈû¶s.¸ˆSäÚñÏ}v›Ë™ƒE‹æ·7¼öUíÂ__Þ^ûêWµ¯}ý›ÜS0«ÍÛun»›•²\ª°ÍÀõh꽕7ïÊÍÆ®”}Øl mX;ŒNë—ªÔÃ(çGëÇùÅÖYØÙ× ÒxNfq_¯G;U9{Ôj¼xÂwš0ðô_²«#uóJÁ&KèíÀä1ZYaã%:wV¾#°âu #°ðõ—O§Hàryp~ÔÝ•…Ñ [h mwîç´  ÑÇ}dK§¢\ÛXfáLÇ¢@Û¢÷¤ä´L±ôSí“0¥ ÖåÓõ!]Ö”é0!M©´RZ\öê]¶ú(JR?„Söš[ÛR¯ZáÌU@¥ fúH¨S •ð bQZåÏ]B#ˆ@<ô›ÉdðÊ+nlŸøÔ™<šrOVŸ—´Ë¯X‘‰¤7|fb,¾<¡"ùe ‰ÏDóäÕqø‰Þ1\@E&}õñÓ‰vù;‡ÛÚ. Ê M”ðú`æFãž„Ú1 ÿj‹àkq"{6!gX”[™ØÇ±=ßÀ¼2wXËå®!ä ¨õÑÙHgÀVºI£ÌÚn8%%(˜ì{&6„†ó×¼á™ën÷Þ{1o&7}nhïÿû/µo~óg<)ms[Éã½)tÑ¢ÙíŸ?ø–ö’—<½­áq ·Ü²ºÝqûš¬Þ{©ÈÎ$xÐðµ¯^Ê}vi/|á³Ú!‡,m矋ÇèÕßG¹ ÀŠA«ÿN$2¦à¤u9ÛcûGÕ‰öc= _"_1¢¼––K[ê›ö›`ÿ*muú?íþ Ó;3A6¸Ú_ýPNk'm?!Q“™ŠL9Èœ:u|ûÍonn§žúžtuC;…ÇÛ~þç0ù¿½ýýßýgÞQ0·yæy<šx|{ËÛ^BŒÕþå_¾Âb„¾;§mæàC&h+“{“|Š'Lí@ ü©ˆÞµXCyK;qUEaggUÝ2¦¥Næå ÿ[8àBbx”ýªÛ7ìûµª^v”F"°ŒÂÃ~®Ò5V‘ì˜2 ”¼ËPRE2’¥ƒtB 2“ˆéÈꄟöT^òi{“áTñ(Ubjt·NiJDÓêÅ[ác䡆raQG•Ô3›²ƒ¨Ýb;Ê‹No 2™—Æ.P¹ËVq>ÖHhÉ?éxy©ùÌxw8«3è@õV—¾•ÏÊFÜ’Ç*!†¼´ÝÚ•îtÔܳ¬ahtõß”Í_t.J6œ/èÒW³ šº>æÀM™(Ê8¡ðw~4Œ5‘ÃIÛ¿ÆílëX,·üζ‘?+… ­ü±xœ#^Q“ÌÔvôçµu>1àæÛîষÕmÞn»µ[o»½-ç)÷óÜjõ»òªkÚ^‹¶Ÿ}^ÛséRVö_ÙŽ~Ê“Úóæåæ§ó.ø%×´ŽoG>á í¿þݻۚ7¿±Íç¡ëo¸!»ðfÄ\ ›`»íg+alàr>:€mË'‘ °·0ûʋ哪E Ù å ¬ Wÿfæ: ©tL:¤$¿œúÒË@ê[uOJ8’æa;:rø‰Ã…άy¯¿ó¯©ƒ”ΞFó²”’Ê%7×XŒ“‡lìÒq”‹Š´QE·“Ê®d@.&"éðÈ?tåjñEšüËPNVÔ×@žjå F:Wà̲¥›+¤A¨:²¸@:Ø&¼l§Pê|ÀOа3“.Ê ¢ ñÑ#¸Êh}é¯H…é iV7éh͈ÜuÊuð½HºúKx Œö2X81[t¾‘Ö60IWšN'1p{­î|>gÎ6µÿúþWpߪöå/ÿ,×ñò¥ò“ö°a ƒ>0š(v£^˜2™:R¹¤Q0Â[®¼î%/>‹lß`…½•$øS9í4˜.1A½Z¹H:opëžP¶!íuÖ뛑Dzè >{m—AÑÊ(V~Têì[NÀF38ç5öðÍÓ>ØÇ§¨S-5”‡ŸÔÈ×-“o„u_–/ál+;ß8bçÏc^¾…g­olóžÏ·©SǶŠgs#æ]mOµÚu×Ûþ/dzºzCûΩgóæÞMá±ë¼iíéÇ-lçüüâÜ[°üÿòŠ£Û7-ÏKËÆEÜìí†Ly¡Ÿí‚Cª“ãJü+’>ö÷èZ ÷„讃wé«ñ¦ø®i§&åA¦Ëÿãiº$0åsꤧf28«B.IçÌLì^q;…XrïÚûYT¸½ýÅ›žÛþús¹„wm;üðƒx÷Èe,ô­lËö›ßn¾å^lãy™œ¸n™ÐJ·w>ûŠ’˜Ïd«rÄŠøáþ)!¿4€¤o§\êì›'^$®5nú±‹gÒŠ>š-—ÜŒÔY#€Æ~?d-‘ŠûTåœô,e‚WgJ‹Ožî–jjm`J¦@§,ãUy‹0L"2e´f©qÁ±ÃÁ=”E†[ ¤¯í2žAÄØœ± s…n êsÿXhv” ’†6÷îjs1NÁÈñsêjìuþ¡ô`£/"ÈÛ¼ŠŒü­+}3Þ¦GþþYû€¤F;±P†¢{ö%“]ìÇÞEºŒ;Ôe `´Ô´ñZ|ÒúJâ©:RC”–– púqt"´çS—'É!ŠLd :1]jÓ€—©²gŽ#_T!œXÄÇ~–±ÒrÒz™m¾ÚY¿ƒœÐâW²œU5ö2î¨h~@e°¸0ÅÞ®¶M\ƒ°;+õßÿo?f…à,®ùߨ–í¹¸òÍo粟§OC—Z ýä§OjG=ñq jsÛeW\ÑÎ>çyN¶=é_¿ØžôÄ'pýád^ªsAûÅ¿ÊÁ:Zݰ]©McVGH+êlY›!i› í<4¶ÍlÆGÓÚ…Ÿ›€ ’ètp™|FÞRßÎŽLùl#KöÁ2xJAgã±…–IÞ#2uþ™€âÀ:¶ôSÂÕ,L‡•ZwúH¬uéBIK¾èÇá©Á׋.D³ %Ý|éÎ\58*ž.PÉ”9³3 +ÞJã»\ƒ©ÉbØ“6º‰ÈùJÖ ÀðùêG ¤Ô0ÕÃrq†Uú4‚° ´Šgòꩉ‚ƒéNÅdòîPmÏØ.jÿÈ–´@Âñ³R_a›H‡Ê …¡HUÞÐC.q¤KZx­è•›—ŠläR“»V¯i÷ñ>§³/ää¥=9Ù sñm³¬ò$Z¦O*¯THK›”þdJ²Šb­€VšNccÝ/4l3ä3x(ÿ¥ ÿêDöèP¼ª?HS²Ñ º¹D‡Rw)¿FlƒØè ºäÕ¦8ä+±ÈÅ®ÓVÁU9º|#’ES2:¾<Ò¢þ ]!8;')E„ó ½ðÝI…®”rX¢=}O £òøô•öŸG™ïUy°ýó?|±í4ql›3gg&ýr‰×T^Ú5‰' =»ÝróííûgœËSÖÖrv\»•³ ¸àU=‰a”…Š%"j‡a2+lDʯ?IA¦lF= "¯…Ø•£y’‰'ág:B“H?³V”Ò%ÑBBa Mzy©•mS°iv%L)ŒÄ¤hŽvŒm‘ÍÅÛ9cƒæá7ˆ!ÿhY‹g89Á2Ðgd^Ð[ ¥°ä4i‰[ìNªÔüÆ:òÀ3õ%í$ÝèÏ^ˆ´|á 1LM¶q¢a|Bû„D•9øÀå F ÊbCm ¿èLal!½BÉxg O>… [GH ).c_|VŠòP­~ãäXË©å‹Ýµ9ˆžqBµpV7{Fê Kñº^Û”qù¸„’ÖVj¶‘‘šígS>'ú À&ðÜ~ r/ûTK¯ßßÌ E>ÉgܸÚ÷ôÓ¼ñw ×ÅΙ5#oÔ<>âî«ßøNVûÇó±Ù3gg3×´–·«-—¤¥Ò¾´Þ‡#‘+ô¢‘N­Àz 휥ý¸6õ‹¼Ÿ`N{鋎ÈBÌõ¿»ƒ•Üzˆ‚òÅß`jÌöWB#„‚låÿ}íáiû¸ÞíǨb‹ *m©ŽÕ}±·Õðt¬§XFÓ¥çŒYâ ±ÃJ}Ù½-œ>M˜l¼œ<„é¾áB‚/»èÂëÚθ¤]|ù]íoÿö™íãyûÆ)ÿ-÷¢<ûùKãjÒÝ…(6r§ÀÿÞOBÞ˜Þc‚|­#Ÿ0LÚhÙŒÁÂú¨T{‘ľ¢.ઈ E¥‘¢l9}Èdù»Ed(ȘêÙw:¸«óöq™Kw 7Ç&°“Ÿ‘Î7÷>M†ªâ!9óòbK¤r›bJiØaHcÕÄR7+HÐ&Gò”bÇœ-—iE+¥Ï€rÑéL¥3wºö„AxÆÍ=Åæ¬J'îÐQÄüŒ<@¼g)(… ÝG•w zòäúDåíGć—מ%âY\¶1oçr+ÛXW‡ TdÓ†Iƒ‡tžÊ›ÎD=õßOõ*3Žd>H½I®é°Â¥1)ÙŸ»"uWääŒù¨k§¶œ_ÊÙ™t+þØ Ø‡B˜"‡-= ‘– LíÿüE&ƒU1bN:<”ÐÄ ñeÄîòeS ÷˜Ée$;´¯~õtV§µÏ|éuí¬³.ä¥>wð<ø©9c0ÂV*%~ iÖÁ‹lÑŽnTT{n…¥šMÛu¸¤H£´ñO_'m~M «-äãÏJy«‚DOÍš‘Ër òµ=! Mƒg줣5´™d4ø––.¢PG¡õd›è¿x|”ÑI…ïí Mi•ŸœùméH2~0TZ€z…°¼¥Ê“ªbç~ŠÊ·sRUü:ÏZÕ«8êSV<ÈßÄ"É߾糼ˆlbåŒÆ‹Y»ñcÑÎÅ»Ûn¾³Íâ‰V®×}'¸vúòqóÞ$/i1‡»eo7³¿Ê» äŸ¼åêD©$T.Û—ÌK•7£…tíyÌËOðAþOêÍÛw©ÊTÚ©4²+?—g+Ÿ'ðÊÁ¼Œ)Éx$™"¤áçb#s Öø$'è² OÁʲâ¡¢ÄI­¢$-'ÓâuüX•Âtv`cf øL„C@ÞaG%[ô 1(…Y/×N0„ru–§¶UæÊ—jŽEëw)›ÖWñ³h°îà§)¡¾Êùïèɧ>!X~¢¬1´2Öu^]ÌØªl Ú½è„q®°…ÒÙ¥’3R©•‰ísóz«m·móå80èrž¨ÕëLw{…Ü€»-íí#­”:–A;ÙfJu“–«‘PÔ €Éå)6Xà4Á‘9ÒéâÞ$ÔH3«9xO|Ô½¸vRvþm©‡é’¡‚¼ÎU²Týà±C°ÊdG"‰Nд¸Õ%ëuÛžvÎu”ä ªéf€u£wu*hPž &²ÝAáÄ:S¯pNä“¢ó+BŠùË$›‘/ÎXHÙŽ^ ¡Ø˜Ž’AF*Ù´Áf2í$)“?Áÿ˜R»XÈP2 ;@™4Ò’~‘±ÚÕ &w$ ½ß£¹@îX¹ÑÒö¶(o¢5!Sl‰Ì¨”`äÊJµŽíNµvæ£ý”Kým¿Ø_Þ´7btÿÂ>Úú I—pE+â(7t|iX{hǶ|åξÏÙµqãǶ¥{îÖÖÝ·>´#¯¼å¥Èl8 ¤¤‡32ѽ$O+õ°¥ÝÝ, ŪUp)kHJ²º”j8¸×î”+«ûè ¼nUZvKð¬4RU$ê ØØ1ô±‡òûµÝPØù¥ˆ´Ô…¡<‡~¤µwÀ¶ÃôñØ å±­lw!ž=ÔºÑR­‘lOv9 Åþ‘IŒ8Ÿ¼ =\Ðß&­ä´ßhA,‘òîÜT)ãQ¼ùw7ذ¹ýý{>Ã}ã²ð⥓˖íÙŽþ¡mò”IíöÛWä’Œën\Õv;­M8>4†³Êµ°Ô•ø½ëÂÿQøÿYýEüßX±=Êôûê–Çm•S‹§á ñwóú•Nª”´ ý¥Ç”8§ÅIÈCÊnúp÷qV_¦¬ ;6ä^èÕ;I$]2ý“ëÛ›ÞögmÙ¾KÛ'>ñ\^¸;O°òŒ•,<«N^WO_¿ ´ôîaâìsõ‡:/]QDÐÙìöUŒ<\\T$uÒr–¾Åü"ˆHCšÂè8 £l Ÿ vä+Q•ÕI¼óÓß©ÐFÒòc?Ï4u²(\Pê <øUg«Œÿt>òË=cIòì˨ŽñÄq[%´‚ Ž‚Z"8t„6?eCþr¿  <ìÄû&os r†#N2œ (ž’«âSlCÞØåñ‹“ÝÈ/rØÎ %u¿ÒHB~pLLü£F˜h ž,: EÍèDEh¯Ø6DshžLGN±'%Ê‚àvy¥/IK9àY²Qý¤¨ìUªä¨ùÞ]›})íiQo·0$Ÿ˜/ï".Wˆ(Oµ?NLÚŠù/{ñ$. hH;¶Ïqµó†-¶ÿÿþïöÚ¾•¤MÒrì P¦ã;Ã^ééh©ðȾ7¼A!Ž=8†NèFyõ@ÌÀ¤G ¯?Ä9â&:iªr½Ÿ+=.Õ¦¯è…80‘K§£#—ÿÔ^vÈDÒÁ ü:ޏÂt˜Ð@„®+´‡ËdÒ©JP|xH‡d’¦]ÓÀ¦¢X"ŸX‰½[&¼ÒA%—ô×6•÷g&£Ø <ö >´‡zi*+¥J"3ÀÅZÊgü þH&ð?œƒ;g]h@ÔV¹™JÃȃO„¸Yaˆâ#èÏÌ>5•nlCƒ“yÅ« ÷æê`'eaÁ„6¤&+EÁP·*£¸ðÈ5—Uª!ÀÎe¥nݺûÛûÞr{ÙKŸÂ›dnŸüÄÉmí½ë¹¶w—Àz©ËBi/c²E‡Ð– Ä¥›Ö‚·:SÖyÕ`ÊQx Ðâ‚‘²MV`€©>c]Ôm¿Á‚dX&ÀÊ ³ÄZ²M¥“°…Ú6$_Ó¡GZbîÒ'õI˜8PX&]u©ÓÂ…S~¾MZžÒT¸tTqýQhyla‰i”KOâÂÆOd.Uê+V *iqKß!)ž“*R'æö¥Fà;ªÍbbÿ0y}òÿø…¼TÌK~æÌšÉ»îo«W­koÛ‹Ûòåw¶sϽ*ðB–èªG@åúŸoòL[!ÇÚ¢4í-bª§cÃí¢óŸJ®ÿžþŸŠn& Šœ†f§ì~ôMO[é¯Dàô"Á+ŽˆÁF¥)Œ=‹å6ø¦±)4ª4¶©¼Ân&GÐñ ¼×ö¿ñ-OÏæÆéÓ'´-SvÊä_?2^Kßn™x %eì~ZÂFˆÈ•“^ÄÔpÃÇ#+ÕéR]†ê´”™§Â>#dN¤+£:‹c:Æ€_/4o “FêeÍG*e'qR"û¨s3&eqH|€|rc‰ð’,bÉSN_Ò¿Œ%Z6Þ/¼ –‡¬0”%í¸Q0Ž'Fh8èyÙ¡û’UE‡ÒlêOu—]”@oñ‰9Ó}׊푟òI3ˆ!Ÿ1a bÜÈê9¼õµœq0Ð(àÇq˜ãÔøD-+‚‘âBG|˜)§´"?ø¡H¥¶‘ƒD!ÇÆØòŒM"¿tá#’R‘nÛ¡Ýs(Ö¶‘S9ÈØFúM5I”ÊÕ ÊªŒ Ì1“s‹aÒ­€ËSk˜’_`•Ÿv±Oþ­¶LæÊepTIM/gë¦>‚–´EhÄþòãSg$Šá‡K€Âh+¥ÇR²â|iüdÄQh·4]Ü¥7?n™ŽÎ¢Hߪ9³±.=p;˜ÀJZÇ ˆÔë Ã‘¥ÅB×ÀÀ‹½pTÊ/óÉt ÝÎòúy³‘È]ŠžEêÉAòIq–Þ’ÎâD¬sŠœÃ$¢÷Sʨ:Ôc˜•Ý@â]]Çnîí8Ê Oká#½t$ xíTm ©A?àraƒ‡rD> Ÿo: *¹ÇÐQéJMô‹NÉ:21S ¢R’‰‘­C&Ó™Œ–òˆ¾â²’ÍÚ¬ð¤žv/rX]´;¨Å#›6‹c7teé4H¥ÓN›YÊ’ïAÍãÒåùzØÞmîÜ™í´SÏb5¨µéœæw2iÄN¢l–üüØëÔ× P‚*¥emDàý¬’(_Áƺ•¤´<>A;Pƒz]chÚþ®ZÅÁÃFÒ²MùØhСÝjâo‰›õà#‹*é[Êeà÷ØNÌ*‚_U«®Vf²ª¢l©÷OF†0Bñ€ÚÁAÒuý¬ò+›ä-eë6N‰zôòàG#uµ”_˜ÂM[æSå]ÞÃRÃɴ铿éO¶|à LÜ&´‰<£}éÒ…<~yW.ýº„ö*zŽ)YYï°úã¡Ïû¤ŸQ¿—yF¦m0”ËB çSáÊÆÛü»%±{tãQz£êÒÃû˜´ú¨êQ<~õU.õÞ£à%«²M—Ò?ó)ªòrK«$ñ„É#3—dõ~¶¥¾|òqXü «š4xú$¾DÛÓ´ICÿ¨¥ +çäqçí÷òŒÿéížñÚ©?æ%`×µù fÔÛÄ£ æ AÌo:Y|Á¶°ŸYÄ]°™“>åVæ‘úE—G¾’ã¹è§è’¾(}Ëé;Ö×Áºù‚O°Ò å‰öËà)xþ™²°v9x°Œ¢¨‘“Ö"à…š¶(Z™Þ£É½êã¦ûäfÕ¯Þ‰O¿–¶¸ÒËÞeÈYï~qÁ¤ä †/wic\mí7‚ëf_Oë$VWYÊ™(ñ8;ä@¬ôVÛÕ‰ôáh›ù6ÉCÀ »™èÔíãN;dVÖ0‚r_m?EA"X¥r@¦:b»h©.Á¥°(&|C£øJ þ.Œ•b%þ’Á—•£ö B‘¿Ø‚DæèµÄõçæ~PÒ¤2Z.fÎd¡_îC‘—åüELöà ¯Ž9(¶À¾”¼ÝDÆ¥Ax¡ÄÕ1•Ùqm´6Ž0T ”<¶mG¨A°Z×FÓu‡£É”V«–t¹Ë­kâ¤3xÙH&[:›Ž+%ÝÅ£sÝ#õR§N§Êd ¯Š“Cpp<À£˜2ÿKÆìAÊJ”p¤í¨ë`’vÅBì´AôµƒwÝÈkíaF½”ÃÁÇÕƒ•(á c£PåO™Ù“ï'Ó©ì°&´U0N:-&¼‚(I­cyÐ ß„õšHÆþÊxå±^RH!M3Vš!ºÅO”LRðSæ1À®_ÿ@»ñæ»x,è©›7J'Oàq~+9q¤J \"@VâÛlƒ –¥[\,¸|ÑØ° °Õþf¥³ÕŽ‘Ïv dª"On®£0þ ‡ Vñ‹L—i¤¿Aº|Bû)JØÀR‚]¼ %¹£Dã`y½/;‹z.>eyh Úm­‰£»~ãÛ.|rÄœ¼$$ö2Í/¼Á©³fò‘™õaùZ¤ùƒ"¬<sTÿÕÍ+µHâQ΄ÔiÀ(&‰c¸qóA,üûÞ÷Y®ážÒ¦M݉˾6Ç/ê 3) ôß3Œ¾ýƒl;óHæóο€IþØè”Ë9‘íþõëÛSŽ:2on?§·MŸ65>T—¯¸@‡¨ëõ%­,ÿC}3ý$ޥ™| )†u&´jô–1ÀŸ)x#½þñ¢çß.¿òÊvÝ 7¶É“&Ö$YÄÑzé?ÒW%s§oy=Ð7~\îÇFîÊnbÑäÞèÇ'1Gézÿ£­&KÕ¢¥wTFÚ_›é úUM"/äñ9íS6Ô¿²ÂDüÈõ÷Öc .„~¤½L [½•4hy¤1ýß·®Zyo ßü–ÚW\Ó>ò¡¯q 0¥íÁäß›qÇnü¤ÑAÇê'‘"e[ g»…§>.¦òØO°§5Fi"ßB®¤ñwhj  I[ÈG{—.ò„;“=š8<Ô-ÀSÛÒÏÖø>y¿Õ6Ôj[±bc±‘h›2)Æô&ˆÂ0ÍXi“¬òêKð6tÙkƒÈ‡ÚÖ!_¤£°bTHt^ЃWÆ{Û›|3Çèt¢2¶›ÕÒ’¾Ùø/m ³OE¥iá<äËF&°á£ü0/B©®ÅÀF9©ÔØþŠ|Ò¶ÃÖ1­ôÊ"ã@,"):äæ´Uµ—V¬³€(—VOýäeÜKœ×ù´2¤>†P\í$5ö¨Y=S¡Í% ];-rÝ~¦´‡´” nÐ uÉr ‹·ÅÈÞ&~U{I©ÚZ’¡ž¦ÍÌÚ­`½oóvLR¨Ñ a¡Šë0ƒ“鱿íÆ¶Ïˆs¥­*Nè #~N9Ë1q&“:aö¦É¸‹ßéÓÜX´>å•/$•ަe¹Ä@;8•@vêüJЕ÷ÉòWP2-Z™T.c;I'Ä¢öî]q T¢tFÉPVÁ”ŒÔÝ…™; -è~¬ÍLÛŒ!%ÕV­+püË£‹T‚0EÔ>dA…(ö(öPWV*‡@’6 ®’žøö±êŒÂz>!‚$ R–bŠW2‘*œ‹iMê8å6‡Œ²HÏ€¦í2ñ‰JfE®à†6âK˜²œ MmXÒ&H9ÙÁ¯Äsh “ ‘W˜Rt%¢º.]:—gy_Íྡྷ½õ-ÏÍãý.bße—IÜX:6mÞH 1ËKÃ2ù´µmŠaµk1'ï— è›7Ýã[í¢lÔ¥]·…n*C¤š¬l†ô¬¼ÚN½,\ˆ]ÍÈ"¼Š¾ÿæ½Á¶Ú™‚D+§<¡Õ)RÖÉPn€§–²*:jå„+/" ß«ŒÿYµ !pËѵ˜ÙR”SŸ˜žfC'lhY¸)‡øl¶õŽcQÓ&뤥.þ°³\úŒeãx¬¨ô&NڱݷnCžvåd7_üÁ R xÅëýëF÷ñN—¥K–¤m¯¸úš<¬a'žî6eòäLú½¬aOÞê~íµ×åLÀ”‡'å `üøñySüLÆ×ACžS¹WÁÕs'w>ú´:~Ÿ»vEÞÈ#¥×q)ÓCœÁšYCšêJ ¾¸n ZÑ;)±Ô2™¤­«ÇÂRªŽàhù›rðŠ‘´Ó°h zŒÐ'ÄVÖ8^‘:ŠbdT&EQBõŠ òuéœÍmác]Ýd¯‚Æ^1Ê…ÐÆbi©‘:ˆ£Ø2=È>“¤<Ôƒ¡Þ¶lêÄ£*¢¥ ›ZQߢ!->¶Q*Ü£~6ZÁ;>@ß-©”§ì˜rà”QüÌH9 >»Ÿƒå$Qª7˜—]4Nùໂf~¯^vò€ý÷ogüà‡í\.1zÖqOkG~7:ßÇJþÎmßeËÚÇ?õévä>o{ì>¯]/Ü¿¼|ë´ï¶ÿxüóràÙˆyóvk‹sõ]wsYÓ4¦qVlIû×/µÝÍäþ¸cß¾¹‘z:õNú?sÒ¿¶e{ïÕvŸ·{{ûÄó¥—'¼ð´WµÃðó€ã[§¯=ûÏŽk?âð´ÃZH.þõ¥Õb}Àÿ˜=íE)mbû§)ÉØD‰‡–ë/À¥¿³·®"ɧթ«…„¸PþÒ÷¤kl„¸ãýU¼{ÍýmíÝÚÿòí®»îi'}á;´ù¤öø', Ý­«ÕÈ"ÝÉ{ÈÌÄY¥ MuSN%QÎ.o¬•Â(IUµ·BÉÁ¼D©ËÆ®¢)ý‡7íWŸ—‚¶]½–Ìàââ“ÍOŠn^qjGâØåá®{ô(±TÀˆP’Dfu€«—޼©^ZJQ dFÎxh1ßÞ,ÌP-%Û¯'„Ô^5ÆÈɶ TvÑÔôe«W7ÙÖËh±qÆ0+Ù¹•£7MUä¿ÇÓNK‚NV•¿ô<OäcylC™ï&ÑöµjïøRæ‚Bµ¥¨ÇÄ–~ù€êÔíHè/Û=Ùøˆü»ñœ å/Õ&1n'@z–œ2—<íl«”›¤.°‚«öÑ6’‰EÈû>ãpø—é°UÓQ'}ú 8Õàî¥j¶ìV@â” *Ô…zÆÕM§±¼ †ËéhÏj äÀäûmo6à¨ø¡jàr\Ë–¦1uB$íJóIµ5ˆW£Ç9h|ëÊ¡’*b H¡ƒ#toÒÝœ˜IW¦®Ô&ï”&›F‹DÙüÙÑÅÌdC|‰<*pSBœñ*|({¡§®(eNÎj•‰«Ø]ù§Ú•8±³â² 䙬¿€å%¶ò@O7RŽa-JàBoÑüÏ QB½¸|+UðP·_0”Ç\¡ÛÕ|6v’ÈY‚NBÒJ»Æèb\$¡ÎÁ¢øIC çHW›–¾Ö‹É)ÕÙ@ä“Ô9º‘.u¥z¦ŽÃ‰.kÚÊAXù£»¶€‡KYÜòÔAÄ&pqaîìií⋯i_ü׳ۂ»¶ùówhTÛ‰7 -0…†[J”^iÃÐïõÚÇ'Óº—cù òdÐ'¢‘°Ò„ošCPáù/íP«O!ÓÛÌX™Ó¯6¸z†©\Éöˆ-¾ù¬è[o޽öËjVJ„ñ£PôÉŒÆN{[žk®m°ËEý0¦ „ (â¹l^òÛ_àÆè"9E/€µ‰²÷¶VqdY÷ùöê7½¥]}ÍoÛÿøÜ„ì$y «æsfÏj'¼àx®!_Õ¾ùÓÚ®sf·g>ã8VƯoïý‡jo}çß°z~OÛkÏ=Ya¾•çÑ™”««ã›ú{íþT&ïO=úÉíª«¯n/Ý_´ƒ}÷¨ÜÒöÛwY.ÓyâžÐ~Á½Gydûo÷úüY3f´ß\uUà¾rò×9ø¸2+øk×­…Þdn„žÇKÓnnõî¿Ë[ç÷ØcØmioúëw¶O|šÇ©réÎ^>9³žY8ý{g´£þãËÛ»Þó÷™ü,Y´ ]zùíÖ[om_ø·/5Wú_r‹ÚÎ|ð#k¯zÓ[›g ?ôÐ8,\°{Ìi§}÷{ícŸúlb£xÏBü¡±|Ä6»ö¶¡-íŸþ3¬:•MŸ³T—O_´Á{iïï^Wœþ@M] Òýâ9˜fqñ>ÞþÄ#÷kÇwp»þú[ÚjÞ.ý‡6Õ"N.Ñ‚´}vÈä„«o$”·âg©‘aؼ”Ø^ô¡Øx£„ÕÏ"… V,ÙZW}*Ú‡_ù:ÑšêRì ^2¥§ ³w$ò…8]™œF¬þ(-#lb,¶‚ U‰j쇼੉œ¦"Mdí}OqÐð/|óvhAËy³~M^ZrŠ–àJ˜Ÿ¤2A“tÐÂSE~æ;*ÆÊ)(ŒN è0âf…×@Žr…^@ÀÕ°TäÉê$´t„g‹  !œí“”U %žÉ&á¾GŠ fÖð“–$M§)¡ÒY¤ª+Û‘.»‚’r(…—äØD¤ Í•r€Œ× `ðR¶ ʤ<°R—jßÒSå‘jÙ¼RÊøÚ€2‹^³Zì¥ “'o{Âüö“Ÿüª­Zuo{õ«Ÿ“}ðƒ§´=öØ™‰ÑĶ ‡ßúdbº‘Qžø”i>LE’Ö—”Œ|ôVjû r ‚¤½é'˜ò»71`}gÀˆzòõ,ì+Þ”+K&»ô…òuíoÁ4mhkG%cB¶¨+ƒõÑG³é(Š ¾è9p}Ü-“kÀS_vlÖ[àWMj+ kõ›ÒgPCϘ¯\… ½ZÉ”€í6B'6éýÒéÆÀªÿáíTgàºíä3íÑkþÐîîIZ¿áæå<+V,oÿòñÛÒE‹Úâ{´k®¹®-]¼¤Ífâíõù;³ÿÖ7ÿE»ò7WµŸø™\rsô“ŽâìÒÚöÁØöcõ|'î ¸öw×·лcùŠ\nã³äãÏéˆ[ryͱG?;7»rþ®·½9×ÑO25+þÞàéK&÷]¶O{ß?ü#—!ÝÚ>ÁÛ{žýÌgä€å6Þ°7g¼ çznþÝkÏ%È¿¢}ék_oóçíÊ*þn¼'áööõo~›Kyvá@enøÞ ¿;WßݾsÚé¹àÓ÷ÎPÌÍ“®¾æÚ¬èoälÅÙ¿¼¸½çoe|Þ±}ä'¶9sæ´Cö[Ö~wý m!÷,]8?÷ œõóŸ·¯Ÿöýöô§ÉXÁÕõôŸ?ds½¢ÊmUÛÍm(#ÙÛxhs=aˆ#- ÚHŒé¾*]]7n2ÅÉ0 ìh&Tòr¹¹sgáÖ[Úþé[dÍæ©ñÌ Ã.ù$ñWdt¼(?ˆï uöGøå/}Ë\Áë“鿳)Ç K&h€ÖY>,B]º°ò¶UY¨S’ƒíz)pö´­›õ–»,—†[õJì+ì,M}ߛޮðuž_TJŽ„ø„¶PÎʸ—޲¢™Dák)àz&Ø´}b•–H¬ïrtšÈÐp‰%ªX!ßò“üÇ>J>Hõ+ZÃÿÖh@Rb­ÈÌÎ’± y3±p¾³AžY”‚¾ÓutSÅÀ iJÄN©ŠM{Ò"}(¡J)†Ø*¶øýMn‘4vM“Œ ÇzËFtacèAˆúZÚ„½ÀäŠna•Yèøk„¦¾p=¼,#jøÁ±ÇåÜw@l«ýB—EJZ]+¥ ›-áÆò)Å >ºlÓÆÑȹÍK:¹é±ý¿·zƒyNžë­G—É€A%'«¿àÒyq ë²Ê…¸ÃŠ¢uºo9F︔”oèÐ&“:©TuK+ìty´ôG6`< ÑE]É\Ý{«£¤†É lþÕ”Ê5Á‰.ÖuÝ“`˜ÞWø°‹LåÐWGæ ¡H&™ÞÜ T:eþ•Kºlv#‚ʸi+’±M×7åéHÚC+`fõT:Àis'ıøáE™ÕR6 ™S·:-+-’–ÉGõ“Ïô¨O'¯,~©.`i†Á]:Á—V%‹ 0ÚÑBfCÇAAymG‰B#dõ“ÀA(½D7Ð fe¸J[Æù Ÿ!'*u¶?ÍløUá2x¸:Ì"ñÃÜP§ ·´iÓ&´Ë.»š7¶W¾ò¸Ü€{Ê)gñ|ù©mÒÄq4 ø>g\vÊT2ø¯T<É!SFýàJ•A$ë]YÑ̶µv±XPNl+ Gª1pòÑÆÈ MA“©ö”»tµ•<Ü2˳²ü“H½+¤Sû—6Ê&=ôÍð‡jÿ°É_úLl³Tv†Ê®œecdäR‡=e%é—ÒM_G¸á©â†›xŶ8©Zq­2íRèBðÃøÊcrÒáçmú‡ÏÍä=×ßxS®ÉwµÿN/aÂ7«þ^7¿háÂ<&ôŠ+Çf0^Ðîã]¯}¿™ssÀªþj`Å_uçmÍ=k™xÎΤ82 ÏfF3¹_¸`A[ϵ³fÍÊÆÞH»råÊ\cË+Ú·N=­ýä£Ú³Ÿõ,ty¸ýôgg1Ñ>#qŸH´rõ]íЃ Ù[ÿoöÞ<èºìªÏ;êþº¿þzž¤¤VkBh@hÀH&`1ccLŠ2WH\e\¡Êv9U®¤œÊŽÿH\qÅÀ ‰)TÄ!#4B2ÂQR«©çnµ¤þzÎó\~ÙeÝÊä­F^pþv¿N/ŽŸ|3'/{ ·îðço)ø=ÇÆ{>ð¡íÛ¿õ[¸UŽ/ ¿«¯ºª“ lÏï@|€›+øÄÃEþYÇÏâ7Î"f×mÏγé«ÓˆåÜæô¹b^ŽÒ7û<à ¦¹V.gÐd¥Ùùl¦œ[5hæ¢9Ñ?uá†Ç¼%7h:ƒ[9îùÔÉí½ï¹iûÿð¯q2uÆö?ñúí‚ ÏÙ^þ²§ð½/lí¿T­=(ÀoÑ®ZÊïÝxjRgã¿V®ª2jãaŽÉÎe±ó™Ž]7û:ÙðÕÄFyŽ ¶+aÿzÙ?1"íØVŸÈŒÆAzO“!Æýå·€IhØø0ˆãåæ^‰ŠÖ[¦æ¯7`G‰æí1&²M_J¦ïPeØšûl;”ÁÐNå«ßÒ7qê:>®[ŒÈtôàˆ×&›òÜ·ÃÖÑhTœñ¨ÍvhlÚ èuÞS|ÒWÇ2¤ÒaÜdà¥Å{¸’3¦õ8¹-—Œ‘E îéÃC ƒö5,áˆ[>¡L{}NR Û1®`œyŒç.? ñ\)Á®háåöÿ©b`<ÄG¤~ìs¬3êúÍÎ5Áœ0Mô^tdù@ƒÆ¿Ým‘\c|Ùè`šgµ/†’Á–£ûûH”퇄1L²3™Mü›M#|QÃÛ©­IDþ‘‰[Ýf{¼4˜ŒÈø×Ø’—6“7¿ÅM6\s*:•Û'ò^ÿøó$eÔŒ\ Ó£‡š¹ Ø¡VµFÛs´Yµ{Bøé‚°QIŒØDÖg csEÞ\Ä‚³)§ÿì¥øJÎ΢ÑéKîwm¬®Ÿs0UH9O<ÚŒ/q¦¯ˆm8?:¦MR²fíÁ2T?:/&L2c•Ù¸°Ë›¨»šÀQl7ÛGL+E’¿iùRIX&øþ,ôÜôåœsÏÚ®½ö¦í=﹡«¨~Ù‹Ÿ¾=íéWð…ʰ‘?U6“DEÅ\OìuëeÚãl€ïd¬Y¾Z´è›lí,ÌËLž@ìý‘d7}ZC¢vAŒ¿bñW¶ÆfdxÂ×⥶Ésí…¡õü5ÕØ6à5ÎÌÐæ–­» {ó’Xé¿>ÀW*SJƒþ¦®ü‡‡—ˆÉŒujûÒƒnØÅQÝaƒE™¼TD¸zWW„ŽŽ!ô‘õÏóòé;êyâ¯d¼=´}ðÃ7r…ü¶íÖ;îâ˶ÏÞ>rÃGú²­O¼ù‘ýñíû?~¤“…<ÿyÛ57ÜØI‚÷Ëßð±›·³¿›õ—r/¿÷îßͿÀ9CKý1ºcÜt!};_ÒýëßñW·ò?ÿ³pÿï¼/ç·KŸüüü@ÕuòªW~%yy' ÞZô¡ÝÊÉÀe}ràÉÊ%|a÷N:NòEhù…`ëÞÃï•y¿À{+~]uåÛW½ê•Û;~÷w·ÿþüŸ¶¯}õ÷l×sÛÐGù´àSà_ȉÐu×]Ç'Ç{ª_¾é–Û8!š˜<—O%®»þz«Ëo2 èùÒ²Oò;Ÿ/εyl'_,»™Í™»àM/Ò›õ³{svxõ˼P®2õ¹å)h~Z¡¯·Üz×öâ=kûøÆí=ÿáC<¹é:¾}¢Ûjü¾!LR¡Â º¹)EeØ£rsÖ?Ú{nAóD4þl± C²Úã0ÏKbæ©äÅã¥êŽ!Ê4:ÍcÇŸOÚêi[ÅJ[26G â1ue7ûp­Ol'^Gv«ÉFu!ŸÇè]p¦rpÑwêüæü™ÍÊŸí˜ã¡2Z£ÞÞ-ÀËþ1ûHÿšK&H"?ù’1áØJ¼|`AŸ"ªž¿ $—øoSr6ZÃņþóbdØôqœqº ¥Y~l?K…ÂòÁ¡5IAÔw¼ÛÝL1 ™¨/;­-º “k ÎzÉ~hÝ_ò´Æ£ ¼QÚ×4Ãd£4* 넆E¦Â~ŸJÈk`ØêO«b¤olW¡ŠÁ?¯jUF— ÒØF SÒ’ÐÖy h‡oŸÉdóÈy|‹Ç¨=Ž«Á'!ÔŸ|Óʬy ˆSùN-?†ØŸÛæÏå£ô6‚öð±íÌÓÎá*ÏÙ=ÅB² 8I1åÕý­›¨%‰nÇ ±ÄT°³Î}â3­اZËbzÂ!ÎL>³X+´,óæÞýrpu²™sþŒõÎ.ÕùÁEŒØ.Ùò!^³ÌVÐUhž:¨ÁòËÅ—xÅö ‹ ä&ñÁ”ÖB9qOsRF‘ÃÓ³ê•÷€z°Y–ÓäΤdºÙ›Ú³ªæ {®ê¬8ætä(²9 ñ'Ÿ.8žŒ¹²á©W|‡ªìú4úäiqÇ[c¹¢…?±ÌÑc@ÛÓN= uCÛu\ê~0HB>Û‡ žD«‹g4Â.°Í{öëšU§–³–Uþ´ä·¸B Y:ZÁs¹o\a%ß½Ââ©Ó}øÀÙ<ëü¼§œ³ýÂ/þÆv×'îÝ~èï·s|b{Û[?°]ýäK·ãÇùr°·5b\ì´27y3DâùÏ‘h&;*EÉ6JT¡ázH hqôÅ›.<´uIC 7"|Õ³ËÑ%9`‰Ük:Ì6§:bìn%»«q9#)«.”iç¥D¾ %œ•}~Ùnr¿Xä‹CªFŠôÙÓ9Ñ“wò‚ö·!¤O`tUh÷K1Úõu2Ij‹Pâàî|ÆGýÊ÷•50¸…¦‚Ÿcs¡åâý îë¿ô’K¹æ‘í¯|Õ_è9ðÿÃ?ú!> :gûé×þ\_˜½ÅñÜê#Üû?ðí•_ù•Ûÿþã?ÅJoß^öÒ—nïà °çÀÿÝÜ3ÿdÍùëo|ãvnWÖç¢Ö˜í÷´íNp\XÿÅ¿øªíûà¿í$âÕßð_ßÇm¯ý…_Úþ›¿óý\ÝaWâ/ösÏ9w»þúoϼúI}r·Ë„¤_Ï'g±÷‘ž÷Š=·ôhïq~¸ìª'=‰Çâ¾3Û|té\síö¬§?}ûŽoýæíkþÒWoozÓonÏâ¶§óø.A£e|ÜÆ¢ÿ…/xÁöu_ùržjôàöèïeÿOüÔk¶ïúkßѧ×`×S¯~2Wÿ}’ßôóçwyVoìI^ߨ¿æ6{ê„ ІӜÜèß.:¬6ù­Oÿ"«q}˜ÓùÜæwÖñ3¶³Ï9±]réEÛÏÿÂ[8:Á ÀÙ]PlÎ7Ÿmkž1ufdæAú²ðX]òô‰Ò²Õï‰naìq!^gIMû£Ú¢_ÒÁÈgöê SØÇÌJ°z0¼Iš¼dDEÆe­m^¤hþŒÏ·‘˜•1öP_mîØ¡Rùœ—(Ou<È>!âž]zЖ¼kü‹¡Í~rb¿9 åÉ#ã'0 Úo{þ‰ƒÜ ¡_ykÙ-¶|º(B¿Êí_4ájNÅ)ó`Ä7ýµ`ƒOIæä´‘·ö…Ó#Ê!”„h HöY¶Ï½3¶ɓ±Žš€Üò¿µEHFŽ—ùP?„kŒ&Tmžþbï'¢ã ,þ¡·~—iaPX:á7¥ÕYöˆ ärÓÿÓ` _qèü™£ó½‘‘nÉ\RnNXíKÆ}>~LÿÙ÷°·M>š˜ˆ¥ã&ù«®ÓŸ÷ü—ÿ“œ Ps5ùX‹ž˜B@ºõ¡@ÃÀ×ß}ÊÃ#~ þðBÛ¡L{2¶KGi“Ì”wÚÎÿ(œøc†õã°ÿ ÝòfÏ£m8à0v{‰Ë²U¿öògßïí³?òëûŸ †¼KζƒþÆÞdÎfÚM±…±Û],r¹û”~à„ìØ9Ûq>âõKlûÂÆŽ+!€«sÙí[géf½ml})¨Òdš@2`5x4Èë®ro‰š(M–ìíþ(Y}ó­ŸÜ¾þë_ÊÝž¸½åÍïàÊÜÍ|t}ƒqðˆÎü!sHL02%=¥±qڈȄÚÇŽ,¢.Ú”÷í»ïÙ64qˆeí¹äôsíjbC§²vÑ™v9ãS˜íËÆ%¨ñâo&CÁdœØ8ªµUìñYä7nj’ÏRËvÅt0”´Í7KàÏë”dzºt\›k²>ÚÄäA‰Ÿ0ÞÕ“ …µE¥Éa¿{uÙ(™×Lðƒ_‚½%'ÿ¼MìÕ, 8K°þò ÇôÍ\U™òÞì¢áâ ÏåK›çþîë¶ïýÞWo—>þ‚í—^ÿ®íÂ‹ÎæD€g¹§PD|ÐV±}7.öªút`éjQ¡–ª’²Z)/ê¹E³MLäô!¬Ñ1£µk>„$Øèhâ9|aúßú¤5!cÝúÒŽ¤ÅFe—¼UÉ;¿ý-Ó¨Aç:8wkD>¶%#/•Cþ©_Ú€Ð0~»pC][ªd‘p°}ÅXW›6 _½EÿÐE|àû¸ßï–¹ Ô€Ïþ*†èò~÷+¸]æagé—|]Ø¿èKŸök¸þC×d{ÑbøC×x%ù¼®¬ûƒaŸà˾>ùæË^üBž+ÿåœ4^Õ•pyï¿qûWÎÝ>ÍcC}Lç§ù®,Î<ãÌíã7ßÜ…¿œ/Ô~ѳŸÙbÿGÿõOvÅÞû%â/ÿ²õôo zÍë~Ž'WàVŸçõØÍ[oþ8'°'øBð‡ûTá ,øßö[¿CŒOÏÆ³¹‚ÿ®ß{w1ðË¿—r;Ó{ßÿ~nã¹v{ßø _ñŠí‹Ÿóœ~gàSŸâ—„9yyÿ?¸} _B~ ú;n»•{/v<3ßüÄÃÛf~êßþ ·9ݹ=ýiOáSŠ›˜‡oLv~aû³Çº¾®ìžºt/·û>Âq†Oÿ%›Ž÷f¬•ËÆ`Í+—IªM$2æ?›9çã[½²ÿ{ï¾iûÆW¿|{Å+^¸½îg߸½ï}×qËÒ…œq‹1ãÜE™‰˜ä™tV÷äüä¹eç$ñmÛsKº$ä1 ]|Ø iÒìL¦¹ò{ðõi0¨ƒÒ›@üW·Àkì"àg³™*ÒŽÂð$DTÒÍ:ìúÔsjaN“£„H`ä9l¡PÛf\BÕ6vÖÛ²Wý¼è¼ñÇñ& â7‡Ùè¿¶VFF,ˆzê»±²ì/``ˆŒœ²8¯‚lò˜Cúgùt(ÿInã|òU—o¯|åK·òh×_ýÕßæ ýç•[ÆÒ-¯ÀÆrúP« eßÁ6µY»æ"ÜÄ@÷óI#™_Z¸€BLǪÓܧ¬*Ws¹aôGg8µÈ§_ê–`,¼h0€ƒŒ°mòY8t‹6ð*tP•ù¥åµNÖå©X³Þ"_hèØ>ûR6½+U×WãºËé£8+"6W·0ôÑf9oûßùƒY¢óQmá ‡¼ ˆSŸù5>ÝaƒEY·q‘À5sÌÕÖÎzlÃqÑp‡PÉFF5ø¥Á±Dc#>l0ˆ'ÐÛ:`d„Î⾺’Aš€ÙQÎ-–…¬ ž¹Úæ5ÄBÖ¾À)«±D%›SæBK{lB–}g ê²–Þ‰˜Bu–LÙs¯]Œ”ðÂà«ÓÐfÿè±Ý+êýRêiÞßL¹ìtN]Pg˜¾íöƒ³Çq>NZ1CEỞDï\]W52ÚÈ«~ÓþÊuí«N; ÜÄU·›·þÏþ.“ûK¶úOÿÅöö·¾g{üetðë E(èìXÕüuU²ä¯6ú ÏíH&=ÜËã¨^9uR?9bXKÿ>Hó[úyU(fÙÄ&Lí/Ís‰€åe7¸Æf¦xãf­ItoW\ Ò€®0ðkøõêlÌåK:ÀÇÚÆÉaÒ”ÂÂhNö`ðÈ¥“ÛBW‡¤‰Ø1}l_‰?:ha3ZÊCëß7ûíºí€¢ŠÆFxT‚E}\ÆêcW°Â”8u4~õ»xË›ºôî'rjƒêœâ²'’<ý¦"f ´ìÒþï»ïApp yAŸœàÓ_~ç;ÿ€ûºÏ-ÖÊ ǃ Ë1qV?›–½ÅÉfìñÄO•mµéçô´™`§Ù÷ €þÛ¿ªÛ‡ú©í2Ë0“;èkñB#Kà¥[£ä¤‡“¥È‘VÁ#z h”Ù¤>1ª‰=Õ‘Ï ºFëd›“|pÁ«h/èö£ëÚêgH‹ ”—.jµ»ß·±PŠq˜8*j ä‹Þ÷~úžíÜ‹Oçâ'môÑ©²;ÆgÛûKÀsžþÔ'wÏø¹Bîóûý1-ËÁòGÁŒŒ·}ðºë·oúú¯Ýžxå•ÛýäOoÏàK±÷òiÂwÿ¿Nž=¼½õí¿Å'_Þs©Ïqá­”>±çMo~ëv¿àÅ•§pŸýÉûNrEþºîÕw!îï œÇUý'í—v¯åKÀ~‘טÁml>þó.îí÷v#Otü/0ì,ýǸÿ]ûü‘/TÌ“ óÉ“¿0lœ<éy2·að;Þâä÷'´Å9ég˜Ôy÷í÷±¨áÄšøFü™C§Ã ¼ü·Ñœ¬=:$Ž Ðüî 7ܾ}ÕW¿`{úÓŸ¼ýöoÿúþLnºƒ~Ü™ $šˆÙ4¹¬õë¾ìe‡1”nSW;-Õ¯!Òø ]ܳIN6­BÒW7}“XÝ oÈØ$ƇפOz’Z¾rØ"&Ö¸œ«ñꆞ¿ÊÈ’‚ìQYsŒ¢6ñ:uÜÝ£®N7âë&¿F±õIhuÞ{Žmj§”ñh§Ød[1P¿ÅfsöÚ6:?NHð²ÇSí76ÔDX;mã‰ÇO‡lµüéÍ¿sûНxþöþñßÝÞö¶wlÿÝßÿ_·g?çÊNX›àS›ó°-à‹3âlV Œ#ã|æúR]ó§°¶7ï`‡–Úâ~ŠÍßÄß’üÓ,1È€úÒydÅ%ò—\?x1‰Á35™Á†(¶ì°ä“Œr{ˆI§<ö׎€´Éß%c߯ìNZl)Š®¼\±0’ðcÝQ¹c‚Ê•áÏãGKÈed±s­t?–@ E<“W_åóÝùGiøß‡Zd)Å"N‡:[Ñ Tƒ·ûG½El:tŸM¾Úy#@% éA5=¢ìWÙìJŸY>@ée‡¡J‰v¯ (ǦÃÁ¯vBRÙ·t§®élý™„VNãFS•8- Z [ÙêÆtJÊÔú‰Aïú&Rv¨×t²·JxÊDcEÔí^¼‚š2ŒÎ°ÓvÙ)²‚ªÏ ©„Þþ)ú"KñRN±±»…Ù£îdjmúÁ'=‚ ºÛôÓCåL¶Ê~%,H~1T»µÊ–¦žlÕƒé$«N"Ædü@}èˆe0eñ2‹„IlaïïíÍÏ=Ë͘à÷À¢±JÞ¢5äq÷ûc¥ö€»€ó=›¤Õçy?yÓƒ˨ɘúýÆ|ÝøGÃ×=í´‰`Ÿ˜áþ=LC:÷ ZCÉ=i"sú7ëã]*êMsë‡tÔæ?»Æxxø¹=ú“' 褠dI|ÓsØ€C•1Cì °,v}OEôšŒá†vO{cÕŠÜðÌ¢}då;Á-?çñ+ÁoøµßîDéû¾ï¿ÜnøÈMÐNl'øá°û9AØç#'yÑ@ ³¾³¸â(Ñj_ö•QõÀ~Ü“^sU“ý2_·™…,4û¯Oéòii Kd£b^Âè'lΣÊÙߎíú‚0ÚWnÀßý´°”÷Ù%<…±ZÔd³wúÈõ™gm ·ùR8?²YÏÕ‰¼^h^P…ž”¯TZrì¶ÁœOÈzò  /œóÁjo^Z1±}NºÐSìÈ8&Kóæ`«6|ŽM{ü¥]·¹§]Ù ©ûe]ÀǹEÕ/½† ¯·Ô\ÎwÛ^ñ²—vÅüÖ[¹'Ÿ§éx‹Ð|<Û¼“OŸÉÉÁõ\å—G^m½ÇãΚŘ6–ÇÞêŒáÜcâ^»œzÏÈ#4«æµ¾” `ÄÍ .8o{é+O^)¼î¼ó|ÂðÀv÷ü÷ŸPIšÙ§TÊh!ëXnŸºÑ²Ïyš«®6åe^@Z‘¬H1E¡ÕœSÐúŒ#sÓ‹.ó` *ÿê[¹ìì[B}ÓG3#ʵÏoºc(ª[!Çv¬m;µGU$oú(ÌL AûŒ…æ`¬¹PȨ.Ž¢'@ Ñ=^‹é­¦ê”ÏÖæcpk8@q&ÏÈ«fhCOy>%Ð Èæ ¸ä’Çðâ`îjKÇeóòÐâútÏkeà —²Ç;¾9Êdù‘ˆb§‘9­`-½ÓJF‰²•'TÉ2ù~AÁ¡9ç‡ßº1|nÂLIfëÓª¼tùÃâ–™c$€É$¶N'È76u– o†½yÚ0 †º¥ÛhÊs«ÌüQ?9=G8c㺺ôÅ&?Žšˆ‰3 Óí´ëØ’Û†aŠKJL'­w¡dÜgâh¹¯Q0F¾€zÖ†i?<Ó_†4“ÎÁ\PŸ‰$j‹ý%ܽtØ“¨º(ïàÏô…¨Znï<¨Ïÿâ‚D#œUÖrÛqœ€ÕÏb«A¢˜ý ãL‚”TŒ!ö½[“5±™ª>™ú#ßá£>sL Ø Ýâê±¶ØRÞ@«Ëw|+I)cލPÞÁh›ÀÄÙæ}B0®Žsß`96Ú5eÆ?í•¢˜üu| œ ‹¼-(Ãg³f;L™ ÀÚŒÀ r?ÐÉH*/n®w|<× [¤ÁlÜüÃpãå«þaqTãη*õ–”°Wà —ÿbñ§Œ6ˆcy?éTΉ­³—ýKÀܼÿž·~ùÅ`<¼ý›Ÿz}†ûÛßÿmÜNð¡íGø Ûó¿ôJNŽs«‰OPLð*/Ã!é«~j…ý¢=MšÒú×^}Wÿ`ì÷Ø35@ßCMSCÁÑ9¾+â5“óô+¢mŽmqÌç${¡…"Ž…æT9åq üÖÝÖ.CdóǘEgçbVÔW?†1ýoJàál#b0¥SdÍ~ûÔÃïaþaäôÍã>u‰ËÞÜØë =Ö¶/”Ïñª4ÛäÂý”ìŸ ?@yeü‚óÏí™{îù‘íË^ôn;‹yßökoøwßÁúÿçMomÁ¬UÚéŽÏåªü•Üן—ìt}èœ|=n¾(ì•~t¨ú¡î¯×®z³÷¡^õ–œ±Ì–±™]›§c{›#Ù<ÃÞXvÝ“…?3ÌSñxГxù„Á͘ø8]«Qÿ8oZ4VµØÖ9 oo„ÈsHæ¸ëYÍñ$2ÓüçÅåCý¿îúÛ¶¿üuWm/Å‹¶ó“¿´ýÆo¼{{ÊS/Lj¡Y "üúÎÛ¨¡¬:&¯^~Z íÐ9&X1ïz4³¼b01Êâ[ó-°³¯3’Ÿ“ó“±â9¶\ØÐq)êÔ„fSQ¦ûø™÷ Ÿí‚d— ×¶Ö¤Õ'fÍ“õ9ö)ËÛ!öª¤.^ö}‰ÿ0/]?î[z³¼ö›ôñÙ0¤2¥kÉ«‡¢Ø~?`d#d³m.Â=Ž”#rbÔÑšK⟎äŽb¶Œ5Òi6ÀÒá•}ïc½óÏO¸mé˜>¥Ê¶MáÆsqwÔ 6-môàž@aŒ7Ù!W¯3 `™-Í9fùíD0¢ÈŒvy$Þ8ì B“-m¶Ïbg´™È$å¥ ~mÒ¶Ý)‰ÚkÇ)=“ \ð¨/÷–9š¢N7;4Ð%·_™2Á€¬­Åº>óŸm‚±¹n‘IuA×ñ.æÜ:¢M™ñvìŒeúS<f›äWPýÊYOfq`Lf+ÉásÀ§… èbp7Q_C~0—=Y…Ó¶ÛO?ⳃ>f¡˜gŒ%6ô²²oÐŒ›vx[Náªðye|ís³e,bP‘¡lh; cß÷ È0òù]-;J]l4–û}–ÊÏxœ£Œ:hþMÌĤ¤ž©Š4«~;_÷» Ÿ’‹²ÒÃo_i˜ `€co„“æH|´94Üꈚ䉌vï\9{E¸ò—Bñ[ã ”l…Ú¶úe4òN*Ìæ¨¾°‰tó}ú ;i›‘;V—²nmÇ›v›ËÈ\¦’ÚŸ¶@’§øžÙìû“n<5ŽÍ°Í¤9ÆCd³º@ê`ïBM¢ qÞööwmŸ¸ûSÛýÿº}äú›¶7þú¿ß®ºz®Øöq´X*¨_-°‰'ULÁP>þ }N~i¡Ÿôøtš4¬ã³0CCûgs‰=rÖlwÑÐØD·y¯& Ð:•єSÂI™>sîi^QH)ã‡øåê‘<ÐÄÖ·=-Ä*§Ÿü4i·Y-êϹ •“¦°5j_sMòÎU½Ø†žÉ· S5R&õîqpÔℎæéÌ­ãÉ£d>;†O¬óV™]{ýöfž™¯eÞõ“®àÖ›ãÙý%_ô¬G!YÑ?Øõ˜jÞFß>v?³m éG“ÿØ5N6>‡Ìÿÿ³ñ~ö˜|ÈÙ.*óì¶.N?OrÒTŠÇyÄcÐ,¾ìUR…yÞcꇯ»u{ñKž¹}ó7ÿ¥íÍoyÇöº×þr·F=õ)Oè„Æy¼åÕÿŽ-‹Í{ª¡ÝüÕ<[|&˜žMº­@S·oÙn±1Kqcž:ƒ¨C>Ê[Juk#4[€çȽàçv¯´z^òÒgñû'·Ûn½{;“û5·ƒ,ºÍý¢¡©a¼ÒŸÉɉµšºâÏ>ƒÀ誎È9ÖõsƨLâ šÓ“?’í}¶‰7mQ¦OH–ÀjÏɨEîŠL¢Êލ0–÷…J°Å|×hÚj>¬"ªØsÇp „@Ú„ÍÑÔç€k¤hs"§} Ÿø€Dû«oæ819Û˜ >ÙƒAF¹«eFÎùާùOu{€“˜çþï}åÉ£ |7Ÿœ³oã͸ZŸî ÿíKS:eTvùôÑä\Ù@4V—–ùFô(ûxÞó/8gûÚ¿ü’¾£s?hvï§îßn¹ùn_zN·“È×ÚÈ7ļ`Õ¼i.8ÄÙϨǎÆtÇé)›9Õ¨%W«ïÌ5óÚšDé5hšmC³PN:#Ló»‚Ðû´™¶ÉmùN¼Tþ‘sÜžÚR-nö,vs¡±V]O \üé×¢¨«9´ð4_FUŒ¼˜1§ThcNíòÎ\•¥™­†ŽÿÚCq`¯lsÓphÎK`ø#‡Zt„BBŸÊ¨—~ÝãEu>Ñ68íE³|OšßPSÊfk<åÇ&'Œè´dÇ(›wÊ-^Óµ#/ïv€Mó¯Ð •HÃ]£þç”{˜{õ ƒ³>™¸å—Lü‹ÝkOp&åíhÚ÷þoe\ ¯A_}°¾äc}ñ)ᙾ§Ê6^à• ´µ‰™´cÙÅ´8VZ 'öŒ¼OŒNö0R[öŽÎÜAî@Ù)S¿Ø iYª [›X &H쉧NƒsÅ?yʶÎ"?+Lo $q튒\4{ÓÞYX‹•âe_V #Qò@Òêy ÀâD¹ìµ®m\úk€*§ÍâÐiêómvÆŸÒÑ„ÏXSžm²6óiUnYNg·“µÛ|ú¥e‹E›AÝ1Æn]?DïdµìÊŠ1}8;>Ö¯/­e+|" Û«¡Ð@wNI cïRÎ@×]ÇdqZ>MÛê'sm2êÒLrc“ êRë¾ù3rú·Çòp¿%:Š˜ó ùe—_€ƒl?ö#¿¸]våEÛ÷|Ï·l¿ýö¿}ìïØNœ31èã~xÊÔ8Ö;Ѳë}FCŒõlpQ§ÿä¯,4¶lÝÜ'Fz'¾1šXеÀP¶ïŠ*ºŒ­5.À{¢Dœð ÂVÔdlÛ±¢‚³[3ºÍO%šÈѧ-Z¡îàŠ1”‹¨ôDœ¢1šEɵË( µÚOÒ&/Å¢"î²WîÝ·ÊÊ® PÂDFf^–åOm»Ïçî³j^!ø ¾l˜U@IDAT»%î;FûUœß³©ü G§ïMŒ÷»ˆšÄ¹Wç ÇÐý'Úξìøöe/yþö+¿ò›ÛOþä¶§=í <îó‚¾ÀmžßökœU¯CÐŒ23ÌMR:…úD[&ÿ¦ÝZ6´sÜ)kæR¦Ø1êƒ`µyñšÍ'éUKØÜ-š•ŽùˆÚáÔŽ° ä‹c½!Ø&Ý0)à±Á=›ãy†È0I'tõHÞ5ÆlX­ ´¡úh*ÕÇ\‹3.Å¡•—œ 5çìâé‚wÀ(`hǸåK8Š!Ç\ÖñêÄPáfüÞ©,>öé36êƒìœ¸Ú—ÓÖâÌBUèw[†[Æž¦ ‚œš+ECD_´Åø;çJÞoÝt>·‚§œkcM¶(£Ön_³,¤Lj˜¦7'†6úç¦=p;u¤<Ð#^ q)04å,ÏúT¤ªó>I½=ŽûOu˪±.`a‡u·ö¼aAöÕŸ+®Ú?±˜ã˜¼ôcÖÌJ¬½.m?é¯F>`È9 À€hðÖsJa©3Ö€ç2K‘%ÏîÄ zx NuÞóÛwhC¼4²qch÷¼A-¨;‡6ÁZ"˜óŽ>x•{¶Ñ3D‹& aå«d´•W ´i%¯žËŸhA³>gÓæBØEIŒ@Ù®@zÄð¼ÒgË:ÙNXmò:£Æ­ Ýʱ(wo2n]M„>5Zt ˆ@f½\x÷ûæ[ø ×âLùü7fŠIsÛíf¶ðsD*-öŽ$'Šƒ)Ý F𪡯„ƒZÂÑ4[Ó4}<ʇâØ0>Ößy¥WN  --„´U_Ù<o£å_+Ÿ>ˆ¤½Ä£¥ò~F^?V”Üô£äüƒ” ã'M-¨ÀAÃ}­+»\ÚN9~è5ùÜôYk²›úø®±Ã7…‡f{×4È›º.iêë$’}÷Z_´ý>ÁF—~¬œÓ‰üKÑàxâžovÂÚ²VVÞ$Ÿ›1ÌöüCü…¡Íðdå*4æ Cu›_~:7¶ÉÛ,²åwÁái•yî Ù‡OzÒ%ÔOÛ^ûÚ_%îlßû·¿ûÀöÚŸyëöì/º|;~gõéá¶Aê{?í&(;‘±]{èm-FæQ(°E»dDÀþÓÂjú+(6–C9”pñ+Ó=úÈ—ú¯û3¯8V]hí÷ΛÓ2¨fωý ʃX ¨ËmPÓ˜îÄŒV8FãØ’™ƒ½|é¢Ò1ɃIôyëØš1’iòm?.h·ºìËùõåÝV¬TÕÀ ¦ ¶Å:¶+)ÑiË7X{p‰À´9K:6õ£Ûp4!Å_€¸DÉ„b ˆ²S~¸´\V»b€Ö}e'µ%ã@©•ÊÏnÚWG©ÇÁê“NŠI˜ýçeRt`§£¶:˜ÄØi¦º'{PáÓFp-uÐ$­@ÉnóÊv¹÷¤ìŠñ(S¢ö†’º©Î`7ó'1Àl té}êî´1NËþUW÷ °¹JIÛ–¤¨…­-VÂì'Ñ1• »ã l¦¦(6[u©XB"Ëþa‘¦¤qµºâjHrÈ7£g2Å~W~¼U¯ì‹‘ò.CûŠíä›}®-£SÛK§Ô­ü²o§¼O¶Â,£Ø´ ŸšWΊlÿ=æÇš±EË&gØ¿qí*Ï@ÏòRÖ —süNVš8¼a¢¹XÈíêÄðKˆ$±¿ˆŽãŸ/aÈ¡—:xÍOÈ<"|Îíû‰Œ\_ØþlD`úÚÞf‘g^P*«ídú½[ÄÈ ú _²¿…qvéãÏÝþÖßúÆíCüðöž÷~G•Þ/£˜/ùº(ô‚˜8õ¹cWø¡Äwʈ°Í Òç)ï ™.Øì«®~# îòJ~”%«|ð¸"¥¿t«Į̀Þs~ÚàYla͸wdO7£B:Ø{Ä ÜöÌ—Û¹aÙ cÇ#ÛaUÜ=ÒÖvl/f3O Òª™IZ¯€Ù- 8ÒÅvYäŽÍÆgñ`ŽÎ!Þ²Q 2k“ºÝ[‚dð¬ +Úh£ì˜·­•s¦‡ÆXáVº ›m oÜ¥·UG Úµi@(G¡ã´kP·L½Ü˵So¾•Ì_FYnm¥ò8QN`ÇáäIUÇ{å&îúÑ¿ø[þ#`¬Â±¤é¼= ¨-€p¦ †¥Ð°T*¤I»/¬û?Ê5ĤFUW¾¶ÙXع&«’vÌFÆýB šrÚEV,‘Ã)ÙkQ”ŠíõT/ ˆW En—o©‘íÄ.Ø-˪˜­¬Û&‘-¿+ £ç~¹š-$ÂÊ4‹ÌZW—u6º€¢ÊDhMä<’ÆníB7tï,ºù` ŠƒˆiŠvÒhÄ5ŽûÉMÎI×–¥e£rû¦œI9XZ\[¼,ëÀÉ’:`ªoß´Ý-[)[Í3 Ëïö2êBX¼Ù. …ù£"Or±NÈ!(¢Ê1ŸzÊ´˜[ì$ºâ&°ÛÊ9û/õª¯ÆôÅë¨/öü›iiÐ#Ÿñ`hÉÞ{L© 4»Æ¤Üxx[K[ÈŵÁ¦ÁÔËý“‡±o&½"FÅtèd\¿ÂÀªˆ"²©ÇÀ©§H¯ÄÍîø‘=ÅSA{ ²“ÁdçJój&>0á7Ç;o :TžÍ>ÿ`¹Ø)±G,^xÂsŠí­oy7W<£ò9ìßôM¯àyë'·7½ñÝÛÅ—œ·{"„qæ!-›RWnIY6UÝwSeûfuý@²Á!’¢âÀ0m–§9g2n\‘®7óÝ*¯^Ž4ï(²EJ¨bLI8Z|5Ð÷+"Ú ½Om׎Ø7b®liå=ŒÛµ è#5ØúW¸Ñe~t[b4ç@¯–¡˜zzSn4y¹È\ÚeüÂög!Íu rOVž‘'-dJD3ááí~•ûü ÎÝ^öòçòlwöÃfþ>ÍÿýúßáKÖoçó£}~×bÏãÉm=œœš\›,îÎó×üã?^Ôø ž Ø'¬ŒQ'ƒ m¬…·ì$ñö–âˆpw|zÜ뢘'ÐÔi*ç$`ò[r º¨~ýϦ±ƒ*ds׈Ÿ¸ÃN>ÓJÅünáI»òù³&­>U›5×Pò8_ f¹x­ÖµA K¼ƒi ,Êt‘ËÂn#í…Mf¶b°ó£WýBÔ& ¯l´<‡4Û±¯f¸%Hª¶© DÚG`W„þÓ‹Ç`É×¢¨Ú_6iƒ±Tà°¥ðG‡:΢vâ;zG׬]É®ñ?+®"Oœ&àö×Lhº¡.ÞÚ—}­¾r êô“|ZÙnÅB]Ұþ2¹dG06Iž¿†í{·|A‰ºy36,‘Õ¤MKN0ø¾"d–&'/q–LìŠîþ ¿s:Ÿ¬àApæ 1Ï ÷çŠÖðQ2Ê!ä° ØZ€R®Àt^œ²îl° h?ØÂ礋 ¢ºzm©KkîlK·R¬l…t©ÛÉf‚ÁÉÉHˆ"“Ž|žîUvö>1ÐVd,…ßížO(v}Ë>¬!`%M–}¹µ×þÕÖíH-ôª\‰HÙ}»Ð×pÔ+ï½b„“ˆž†*o±+“È@J‡©"­ÉI$°éçòzüD·Ñ/&M«W½bg‰njËlÞdQ¿Ï=ÚÔ3µ‘Yo#ºþ±‰¥å±j(›ïæAI£¬Øn©‹ÒIј{$̇ì£]ý©Ùs¾ÓÖAL›÷¬ÑtËï©SFécÕ´ïý> `Ú(–âÀ?]§¬}ÏŸbÑ®ÍsU#iøcüµ)’8oÕ“ìâˆ_³³ -?ÖíÄÓì>î?.†&$A>!=¢±FaæŒ]ñ„¯  ãC^äñŠÇŽ¥}”µ ñèNŽd •· ~, /íÉSn±k®ÙM µØmjâÑ3v4UÕneô5›‹ßøúƒQ²\rñyÅ÷g_ûÆí £ø7ÿæ7l½á¦í…/~úv&?˜ôü(?vt¬ç¿/ t#É‚ ×Hà„¾Œ?¦†¿ûæ Lý‡­}Üža™ùÚ;ý†ÍòŠ‘•éŸHòÓ`UrïcO'Hb dfFã>\öWye›2ði(̺F1ŒŠÑÎtÛ÷3¸•ª¶Ã€W— ×f ²$fí¶mð⋞ìWm”ë³Í Jš·t@‡ÅÎH M&Rˆ8c¬’a7‹v ‰Ã®%& BfB]¹ó´›ÿ´Š³Ù ¬vàéê§.fzin‘Ý-î]¿6@îÙððk“W>K ¨3 Ü$|õ½•‘»þ‹¿IôÑ[b`£°µÆLIÚÞçÈÕŸI;\ĵ4•Åi³Ø¯Ç¢;ê÷³óÚNSòêUN« ášÔ¨•Üâa‡}j˜Üïý£Ïv\^Ö>x„å­œX4wÒÓëðY°je Ç–šbÛvürª:ë)´Ëm³M†½ûÔƒZgï{ ó¶³¬•7XÚàWVJ ¿åóÜ)·6ªtª7^ß¡Ks[Ó“…‘‘f99˜,O E´’¨6yâa—;-;QÛÿBöòÒ„ÐSpø2˜òN²‡“¥”AVŸ[ì ,޶›"É6Z¹@ÁÉ/›^qå%=~ðß¾æW¶OÝsrû¯àÛ·›o¹}»öš›¶ Î;‡útúíK¸B»S5Ú ;Ê#ZÓ¾ìÝ0.;'žT“ çñË«3{ïÉ\Û&ÀމsC×ÅÐfùf¾‘}ŸûbáM;ÍÏtS×´|ˆNYLò>óšnæ’9åün¹-ÁÔ㉺FN.siü…¦# ö²=½Ñw?¶õßé;DÈ}aû³Çò1nìö‘žvýº/bn½å.¾KsÕöW^ýÕÛ¯ýÚ[¶ÿñ_äÎÎØžõ¬Ëâ{ˆÛ‚ü%óÓ8vÍÜ®ìø×m*`y2ëŸYâœ?ãÙ<œüŒ¥å4Jæÿ+kË«²Ïd\š•5ó®½åãâ6;žd|{^Ç%Q æ»Z°IÅåp…Êoj{Úç‰y<:•Õ—Y€Sc Ìœ¦müek¥ÆŽËÁY‰cùš>½Í,¤´n6}j¼KÀI/ÊÍœ8‘+:ÂÂâqNÞ™K'F²x­nìí=ÈØ1o}ú’§`¯bŠŒ{å‹¥æµÔ¼¢…rè;Ø0šF{Ôà›ß0åø ÛÍIÙÉ›Àìªb?¡…aúX°Ì" ¾2ˆ6#j&IÑO×BÆeyݲœÂ+îæÚƾVvìPòМ·´Á9Xf]§¿dl4Úå†0ŸØkÍð¥ ÓÕ?Xã$¶¬`&+õrpçöÊ¢¬ùÛR¢âo-ì´¹²9îqBiõÈ"doÈã±ÑÈrXN]çå/müx˜Á”…¿ cðRt”=‘ÛÏ8TOo1¦^ͱ˚ †Ãàmq0x9!€­ȳëª}dô½–ïÔµ)Àä4Cá EÅbŸ,¦C<ˆ¡¢ÁŠükÜò ¼¹J)®^€`{zF—òéµZ3\«\Àõ!™´ CÞ#á:Ǭól;µ¿6‚ÓÕZÀš60.¸šÅ2.¦;h’grSyT '¹…=˜ ¦ =WF Ó¸ƒåá`ú>ÿrG›§¶åÎ wá§á†Ì‘‚aØYU»¤çˆ~ê} Cœ©Ž²=>ê†88gCÆNdsPù‰ŠjÜö)Ïz¢àT¶"Í /M³08{¸y·rü Iƒ]m»Vø×}”¿Ø¬LTJWDprî „ùHrl/gÁIvå0nå‹–uÆÎ^=eì&‹ ߌ+òHÞcI¼;Ÿc°<9!vbï’o&:IxeÊçDÒ6 Í‚lß}¤«ÌSÎvxE˜1>nÌÉ¥:á_c &b«½k"h&Ú>¬výnWbÐk7€Æ˜Ýýü"©Ðçœsœ_ >¾ýÊëß¼ÝrÛÝÛw~ç×o÷¼û±û¥¾pÆq~ßýÓ»èAh¬)4/QŒaÎþ©Óø&\ãE_h(Vå…†vm³xÊR÷ojšN͆…žÐf®X1V7rö[òÅâ]Ü”'v³¹e<,½SoŽZïô©O `4¶ÙƒŽT (&RƒÚ°h.ŸÿÎQމ1«24m§;c;íî!è~|.ÛG‡ª¾°ý'‹Àä—óÙÛéüºð1ÆÙ1ö÷Ýÿàv?èõâ—ÚCá]»×¦‰bVbàæ;ñ .]݇ñêÂRp¶ôçâ¤x9vŒ²UÞÔ¾lšñ·ÿgVv&œùWª7¶ª0¦èÐþŠª\ÌU² ì™ØõÇÏÆŸØé{;ò`mÓwó<´T7er<­ bc?Ó%ëî–ìVÚÆƒ½,¾qP¤‘uqŽ6ìr¢LW”ëK¢8Ñ$Ñ 1¾ôÁF\K~âPJŸ>“Ö¤'© <;s—ΪöÁÄ5èh.–@»ûîO²¸9}{×;ß»Ý~û]ÛwÿWßÐM~ø_ýâvéÎåþ泋Ü8 L@ìýø\ŸµKüNdÒ ´®@-!åô­+6Bô ǹ¿¥‰Í|ðð±³ù%Øû‹<¢ÜL×µì ÛDŠåC¾è›·ü™gg;Á÷fÎâKòl7ÜtóöÂ>m{Õ«^´½ÿ×mø±[¶O~òÞí†ß¼]zÙùÜtfŸ¬ÕuŽ1reÿ}‹rŸ7íñÍ\l1E®µ>`.—§|qgê0–CÔòÚÌq¬9¯ùr8 øùkþoá§ÖaP©:Í[ë6jK:å2Òyh%o>в_ŒÐr›$ͧ«4Ìé Kpt뀹Ìx]"ò*¿•b’؇ÛQK g·ó»ëcäÖ?q;xAO¯ãp×Hª²:ù&Á^6ÛìÈÌØKza…Cþâè~·ÇØ…´*ékLÍF%ÆvêGê ©‹-šBG›ØiFiCÍãXöä­®Á ˜øZ †FØ¿xhl‘¶x”‰&^œ¶²‰9:ªåH®„9ºŒßΧ°qzù7>jƒó²æLgI¼Fn7J¬‘žuAqJƒ(‹÷ày¿¾œíèíùZÙ]¶qr®Þ«?Ip `MÔ÷x 2y½øŠ›ú3ù\ Zð>?1wMy¬… º3ƒÎ4ÍÞäô`è1=7×AJsôËP¿åIÕ:@;‚ 2Fž`,#­f‰üKµhD> œß ¶~à¯qdr [³K–¥a|Š0$®½ÿ 6‹þiÇ”wÿ: ·Äf& !JUÞF–ª‰dËê8ûcïŒÎÜØ;©¶ÝZÑgo—R¬äße”Ç^ÿü"›+#/«HðK#VzFQ(‡~^N˜¶…%q£E_ îŠemÅ#ê\2Ö„V@êU®oá©Ý>Óþë cG¾ ¶²3y˜€ÒËsqÅXÑÚØ¯LþéBór‚󯺊y¥7c·@c„T ºC¼†T‹?ArB1®Ú°ª×øDòµ÷žFPÏvJºUß@vÂÕ„êÐÝÊ‘‰Ž>kMNå/50;Y‹~tÂ(¶m]½±hÔ!Fv(`ÀÁhÇ~ׯl›(ÆW/ÜÆ>Ë{Ì瓳]?ýS‚2üX 7ñR&ôeêË%~±aÍ—GwyѵËwÊŠ…Gc¨ê³ìzã¶…ã´]ïê“÷m·Ý~ÇvòÞû¶oxõ˸¿ùüíçþM|Gà´íâ‹ÏŸÅóŠMß»XÓ¬Ư4_ëÓŽ‰ñâòÆtòaÈÆG>óȰf°Þoþ¥5kö ºaáæá“_‘e“ýµ§RDÆô,k­dáˆÆW5sŠ!<1CÖÌ\åTÑð‰9'A©O‡?IdK1FǸ4TŸ#ìøñíøvîvò{èû1`—©øçþHMl?‹'Ÿ¯MvÛÝêcöŸçMà”·]öÒ÷TÚA›ã›þ;~ÆyÛ™ÇÎÚîá6¹«¯¾œG{^½M So¦U^_Û†=érMÍêÐgF_þ±]¡‚XXÕ‡_ã‹’º”ô}x".?m™úÌÅ”#Á)³RçœvØP:¦Ãˆ¢†O<äõÖ•„ך$­ñA·‰9´yÇ2Û¾0ÖOç¼aB¡zBoV ׿ááæl°[!QaÚj›“ ÏÄ\½Yjø´Õ®Öî|éUÿ"Å-+e^ù&Á™cø+ê\º½ç"¹ÕÞªVŒˆlûJºâ ^[}ψU’Æ–ÚZ®ÉBSk}QÕNbAkŽe/Ü0€\ÌÆÃÃñ¢¸¨vÆcˆ•-jvÃk±ªi'(¯†<ÇÔe$Ù;Qà!Â8©aà $ à%³g)vîèž@¶Ë¡ÒD†KYê¾jž·œívD¸ê6Á\`ÐÙÜz9$­ƒ0´¾€¦Ï¦à Cd㬳7 õvÕÜ{åP¹£û»¦¹ «sÙÞ•Ä|AÆ? fëE=e Š­Øî†/pÔB¾|ëÉ.øºÇÛÖîv4åîÍ0M‡ÿ¦qµ_{ÐÛº¾·Hƒìžw.(O} ²¨ó¿úÀsÒÁ-Ùè‹p ôaY‰VldS_™Ä®›šV üÚøب]üÙ¦½(µ¨›¤±{ò*³¥80©˜ ññÖVMCȱàB¼v¡¨Ëi>ó¿´}ZÞ¦p±OÜÀšÉuø4HëÜÔ3ú×{´o—ÖlGÿú¤ìÛ’‡$ËnÓ®G9u:øg¼! ýÙ„O`vÅ(åŒþ\QÀ;W?•jÓ2r³5‰ƒgÉ?¹ä÷¯+PÔf“œ‹É}î~$ìCÕÈe¾Ä|Ø-›íåÑ]èÙ´%ër`´eÆ¢L· yó\“„LÆý̶“3c;°©sÆ‘X=ûì³¶óÎ=±½åÍïæi&ŸÜ¾ë»¾¦¾ÿâçÇAè _™6wû`t°®v¼±(+«ÇþR—>BGû´×zsŒÅcôŠÑUë5÷·úN)6ËK×#~rÊvô8ÌÑî,£!SÓŽD§<ÁCÙôŒcal’c¿ún¹ û:¥G¶:áê³裛¼šÝF››M¾êüaiMÎcŽ<+ë—\²h•{—(6Ètœ€ÚÅ@11Bã¨x2)F},bÐv8%?)j^è­›ðiÖv³o–g îü[}^ÚÕêrÇvE¦M¾L¾4è‡<Æbª°>y€—v\L`/<;.øò|ÅUl{TæäÓ“¢â0'êQƒ<ìØÌEësÅÔâž+ô=<ûb¼|¢ÍVMòŠ€6;™ØGÆÔÖÊY¦=ú"F*€V™ºÆûÚ§©~pPÇŠÀ©}Y>ćüÂëdWw0ø;XhN•GZèÅl'"mj N}ª˜“ ; ߦlêL%åÑ mšÚw…•×&›·½D£ Åê¶íT¾h£8ÉÆ %éw £KûF»}é—ŒWMmõG=bç,-û|aŸÙiÍ?°AÚ%—œ¿]ÊëMÿî]ünÀÜôuÛÅ]¸½ÿ½×r"pñöñÝÞÕN¿# ñy¸fPsBJv§ÆoIš8XlÀ?ks¼¨¿§Ý>rlìÁÑ×ÂIØêG²ã» ú‡X€¼ïb }Xþì®[—¤­ü¯øY¯¶e˜mâ)óD´÷À?ñž9lñc cÙÜñHVç\·É'|ãû1sœÛç}N×f)„?œy<ôÐéø³ËB/Pƒ7ïö°fÏ˜Ó Çã8)‡2±\] EËĶÉâòU)ˆŽõ[œ«Gc%y…u³<`©¯¨ øï­z§skÙY|ÂqzW¡$ï,aljƒ®?£{ µvl_<ȶSÍ›)§i1†²sÚâXÛû&uÓˆ ±'ÕÇx¦ÿéü —O ¹‘_Î~ñ‹¿˜Û~¾xû™ŸùåíúÿrñyÒÕÑUü _ò ,˜bwÜ'á2•þÜe~‘Ô§×ÕOèusžs¼¹™.ú®- ¯xè}P>É Š,ùÞí7ûÑÏ´-~5õ²®Qà*<òs,±VÜŀǶYL«¡ZØâ$¹Û‚ú,Ç}—Q/-ñÆãâtÄâî¶Î\Š~cŒ¹°Ï M*ǶìÄÙf;³ Ô”„HŒìwPÖ ¸ã‰}íFM<ãMç=®ÐäñÇί1Ði¡ˆÉ½6ÊÚÝmeØQ, >5Ù›ÎUÕÓÝžÑS/¦“¦Ú‡èÙwèõ‰æi€vhOB:A!;#,œZksÇ~¯ãL_,쌇•ÅRûw.””è5oc´Ù1óµcFù•Óå#5eWæ ÅtíoÊù%_ÐK{?|íÛ7Û+¶oÿö§òcyoé ¾þ×É{ïßNç©MàÛ¸ÒjÇ’¹¬ßè(¿Él' ”̱yåü°Ÿbƒþh›ù¾Œk.ôÀ˶Û;ñ"Ãq;ž%ªîâb|L>£¿¸4–´ÛF„Ò3cKU-h/ïÍ Ž½œSêRFÉq{Tut)9/ƒ£NýÙÅ&öЂ°ŒÇàÖW;c@ƒÝ‰tÃâØ”fÛÇÎY8îXEaÚ4¹d)׊â'Ñü“q½'™~AsöBOUø'qbÏ–‡8‘°ÛxÔgkP~ªÇ2³¿·õóè3üÊà Ìœ‰ØÔw» PË K9›õýzi]Aak³‰šqÒ1ǽ8å^ý32ê×_™Ü¯HƧ¬[¾R)ª098ö“Xµ•bH³iâÑ .¹ÛÄuôΰ!kÍØ¢Fã@]lEäD6=¹•z¿b Ÿ6››}Ú#_Hî÷«3y •½6ûíT£tŶú\¥œ±Ê:ŸaPÂõ¨£ ߊ˜Þ›/oà±òf~Glp§†ºó à±ßa©síœ/4ÀÈŠ#ß rR”N4ÇZYì îUÀ›²é¢ÖI¢+6õ0aÑêø6–µK›šaà_›‹nLÛf³ŽÝÑââçâ‹Îå—„¯ÝÞùŽ÷m/xá³¶ç>÷™Û¿þ±ÿk;yÿýÛE—œ»ÁÉì\w±â„¯¤}Ê?ÛØ1Ú&ö駬¯¥SŠq󢂲-@,ÐnH4 O²øçyFÛ³ž}9¿¾zQ/dØo_ØþlDà²Ë/ádì¡íÎ;îÙnºñŽíÞ“°€ædÍ>ÇÄzŠþÚóS«ï,¦8Ò9¢ËѾ6BMÊc¤&wó#å«czòžÏ¦ÚD÷8éH=ŒiÊ3çÛÊ|AÞœ¼ïäö‘nÞ¾îk^¼}ÕW_´]wýÛÍ7ßÚåÝrë]ü¸×9ÛÙ<1Ë“ËFªŽxâ¢4©Û(uî‹c¯c¢ÿŽ×xí±«1žAÓFqNˆÅ”Þÿ*8©XïȈY@]z¬ñǺ|–/Îñ¶ƒm™ª“òEŠ¢¾È¦BðÕ©9nóɹqÕçJ{t-3Š2ƒµùkD>8¶ÓÍõ‹óL¨ÁdÒ\lÐ$ùa–Ų~øDð1W µÑDãÐ$!^烆-`äQ6;—h·­*±EJµA•˜KÅ€Šj”’8Õd\ÈF€oJÍd”aZ[%q‚ömÔvŒxQ|–JA-ÑàׄĿÖ|Ë`O¡ÑÞ‡A‰+û̧ø;1Ÿ¦>óóTQì»á55D¯a«/Àí¸.˜Ý*%›1¤nWz/›°ùÝXmÙ헀̬“ o¦jIžZ€ß]EÞ6(ú5Še¬ÞØ–£±¢íÓÏÚÐò³»~GÄc'e1õ¹˜¨M_Géü˜Š_míÕ½o)^õÎ8i0™•ka·êbê’9dgöCbÁjD°³·]o¯q&lÉ?&Ó.N[I-£”a²²­@h¼õÛh1yü“}kÚ Åì( ¬«•M¿-Ë»bP%Ææ "¼dA÷£7¢ƒ¯·“tBšöB¹É.”þÉãßnŸ:õ…]5·A)‚…Úöû,‹+`bø/nùʾcËúØ"ÿ‘nòN`Ê` ¿Š2cbM‚ú71™8ëÆ`/ùÏø!°™ŒÀÄaÏ\Ue?ºåçP jˆµÏU¢U»¢Žã›±ZýK›¿,h_ŸºÑ lý¶a[ƒNóô8+Ľ82±Ö‡’W¹…›ø‘ïØÖ CnúQL7q&å•G-{/lYvÌ`lò #Š©9“·¹¨¾AL»E þJö!’Ñ$‰MÅbcÒ+¼flÇŽ=Ò´¢Æ0a”?ð:{¬N~È9qªkwEP-*hN¥’7‡Ó&˜Ò¢:rˆ!Á¨«¾þGÙ”© ëÆVy•&Æã“tãîÌ‘êõâ³hã©M‰‰ßYgßîºëSÛ§?ùéíö[ïÜ~÷¿¿=ïyOÝžû¼gò‹§¿¹}ôÆÛ·Ë/¿°x4ÂÜX‹Rƒžïý‚µ~¢¥Fû]ë#» i¯k¿c÷Èö'?|ßöÜ/¹z»è"¾˜Ì'~2æbóÿw[ùzõG‘},žÇjÿ<¦5¯ÑyÂEüÊôYÛûÞsãv?·kà©:]ö¤_ýôÈ.6-èsäQ=¼¢Gˆ©ÖøO£6·Qð˜W½ÜAz*sü£âÛOýòî§y’Ï3ŸõÄíiO½’û¸Oc±þvý5Û~ÿÝ×nW^qñvñ…ç•[ CtvX;Rç ‘LÛi.@åÉÊèSN ‰ð7î<QÞgËhp·NêÂÂ0¼ãj<€²E†¿X£{Æ’Ú‹Z<áM©S¨1Q¼‘ç}ø×Ø‹¿qRv¶A´ÞloóõŽQp–MàyŒÓ¶œìÕ=·CQ¦£Duó½µ’è‹_;Üœ÷c¥œê%i$ÅÞ–+”›ïp`ÿtñpŒ²°u| hí8˜«íÁ§"€ó)£j\ø¯o”éve¤C˜þ´7áÅ yº8X÷¢·ùÃa‘WrM”E`Ã1f‰eÕ¥iËѶÐî6f?F-pÜ\Ÿq¡­)€.„åè¾O)š®¶YÏê_jØ×À\X6ÆFy üñž*‹a³2$nœ.#Øi)ø»ÕåÂr¼8òð®Ûû4£~z@2cŽ,mU!VgŸ‹«Ñ˜?÷ý@j ”‰ÞQc¤Î–g¨@ê²7JAN©NÓ¤K%O½ ŸXc¼Ü;öðj¹F«Åÿ6ë€&7GžáY‹…<†Ô@É ñ€’‚á½…Ñ#HxµËßÑ”sÐË*ïq%¡XæB º@çÀîâu Î"^øÇ8P N¢v¼šl(Ðÿ¹ò˜ñ:!k¯Bþ‹¾ŽõKíþ5IÄ5:xŸÚB0•åmÃ1¶ÈÅ™]È%xÈù‰À¾IÞmYø@ G²VíJܲ¢1N¡"ý6“š*¡Ãì_ÿ1H׆uñZ`yÆ'£:À(J}xj½R;[¤-‘±MÞ‰áŠ]&ùfà ð\Éhh 1ïy5$˜†ê××ÁWyi‚Üî—²Á\ÿÒ”òà:Ðpy!ÿÎWî¶ÇkÇ«ÓïÙO{ÈûIßt!vË:ƃ}(ˆœ.ÓÉ$Þ< >ÿM„xôwòEiMÞí´|ÐJmÐ:Y×?Êð sì4¾S¾uì@ [ôUÃ;jµi0ƬÁÒG/@Ä®^øêé:‘͸ÏðWO¹Íæ¦oá– »¶—½â¹Ûí·Ý¹]“‚¾îk_¾½ýí¿·]sÍòýŸžr¬Û G|*Q¿y¬ŸÚY;o-V4Vôz±kúýá‡dyÿvõÓÏãIÏÝî£ì¦¹³P¥îDöjú©ŸõY‹…ÿ™BÅJ»Å?©ýÉ>†ücá?V{®Éôèø6ßB~€3iúª'_²]÷¡[ù~Ù=fvø ›÷ûøcòµO Èagîš²yQzö¶Ú(C.LÍ-æ4çé¢záèôZlŸæ)W¶›Ï¶=ñ‰—cß•ÛÿŸ¿°ýî;?°]tÁ9Û…Ý}þðEÖFüsaHLs¸‘‚ôà&+ š¸W15óÜŒqó¿‹ZM`òΘÖÖìõ¹9*ŒŸ`@– KФ_=ü7]Ó|PIÁ¦€ØYÉR«b¹q•£Dç!ÞÄ¡bQ©Ñ‹m`Ê«Ž²bœıLqî£ Ï·æ¥S2©O­RÃ>'7Ë&}X}¨EnÎyŒéÑî”È dÛ/\6×@êÑÑà•G9qæ c»˜ÁóFY³ÇX{¢";ü;žÖ脇¢ìBÆã’Xûœ«Œ«Ó†žø´Ò•‘*Ø›³ô(Çmõ×'ÒÝdàß^A.—P‡ÅÞs3ÚPò±¶5Ãî•wukÂn%¤-váë[Þ“Ymìö>–âgt~F¶ºÁV^㛥٦ÿ…ßióбÌM¨6wÂKy¸šOtžvÅiG{3­¦eU\ýŒe.@U^{Ì̵ð!s’>nÖ–}z:Ž•AXö5Úl™àY‡(°A²£ÝçÔ2moD€Ñ;»%Ÿ KC¡ÒœXIlÿÔa™©[pP.á1£Žæ‹MÕ¡Ëaº,TçCs;àS:´é‰Ú³™¹Þ6öŒáÆ Bvp¸©«IªÚ´‹Qâ³7g€ô«|( 3`½ø-‹œpr˜‰2y8­ƒÆº>¤™½«*u(Òƒ°<ý"O¼öƒAú׊á79\Xš°ý ôÙ°ÀY\A© â@î©’,bK£ßf’bOpTeŒ\ N¾È¤ú‰KØÔ›h³Ávô)ˆ®ú‘Ešý\¬ië65š—Ê"§ïã 1F¶ €A«L¥ñwôˆ?ù*È´ñNÑÞq‚š˜'gvL·ü¿ì½gÌ­×y¦·LžÃzÈÃN±S")ŠfEuÙ’eY¦<–=—1AL)ƒg`ØŽ'™üJ&ó'2@<±F²å:¶%KcY”DQ”ØE±‹E4{¯‡½äºî{­ý}¢e#±h}ßÞïZO¹Ÿ²Ê[ö»ßýÝcb ¼º¦¦Ããj°Vdf«\¢ HRŠñ*Ã[hðÒ'¡øFl ›¼d09’Ë“oÜΧ¢ØoÈ¢»æjT4#ÓÚsÆ]–¹ÙggÆ»ðé{ð¥IçÆl¦?m)Ï¿Wlwì388;ˆï*¼ÈN¹cÐô´l* a1þ´·A}ÏêvÛ ¼ºýj¥WóÿÿÖn¼öß+ÙuÐþãÀ]ûð(Múp'ƒ–ñ·æYÖs:8c.óÌa`Ÿ£Lßg“…ÍqèÚez3r²§>ÇHÆLÖQôS˜£®MÔŸyš&È1Ç>î»ïÑqæoGyøøO~°ÿ ãnuÓ—W/b=M©íVW cÊÚ$‘—Ø¥3§³:Ì#eÁîMDÄÀ÷¿²ž+è¹õQÂ,ÎóÜ"AÛ”d.lø±\ãT»æ›GóëŒ]Ø0±Ýë(ë‡Vµ“\³1±Ø‹}nM¥ëÂáZÛÔÓÆw匽ÊSÙDîÂMs¤‚C™`¤:<1H—;Nà+Ø(ØŽé2åUoÌ©`Xý4\`u¶d Xš–x#Nú¢û8$+{ C²ÔŸñX{Itú=ãŽ/¦$`q%ê‚ïà¤4*JfBÄÂꪰ¶³Naè_ŒG©úëT*SáhÖ ¥O³ÿã…æ»òÓé«i+ðÅÔW÷—3Ì´È›±8~y¡Yo¾ùÕ×Ĩå¸Ý›1hÉ|ìúfÞ­¾i#B´ñÖV9ÑrÂjÿÉ¢jõ ´Ý" \s€oS¾}RÝþðq%:Á”_Uäoù¦î&ÀšØ \v ÉðÑ…:èËf+¨ÖfôODÁåÆNÊ Õ¨lÞ$-|u‘ÑßpËN‡ˆcðZÎ$BV;É­UUÊr§,†ò‚Ç¡vr\PÅt2bÄd“ÿ9£Uncƒ”¯QäÙJ63€â—V¦Ãúh=Û.õC…Æá¶6éåO:8®óF®z W۱ϠY}­ÑŠ+¸ZÇÅøg}*$'ëKx1ÂŒ€¨³Lïᙣ`3Ðó£FÜ8ßX¤C‹#,~@4¤œÚ‡ÂKôcT·I¯B¬œáSßqYŸªS¿!ñçâæ_°Úc¡ë»gðÁO<ÓФóÒlÓÖ¾æ]Vò=…Ë9£‡’[Šz9y‘/´êMðôDפ©àÖEªò/J›§Øªjt:îµÕ|•mvÌwüOùàk½ôg|‚*™ðsÄaÖ$•˜IémɃÐáL]g§¼£L®/߃&Û¢rÂl_J³›-«ïgÙô0ò5tä×§ ÅWÓ˜˜c AÛNueVnÌS˜;<¥!\›úKÀôé¥ç_;x4ÂñÇž{¼ã7þdwüá|9xߘÿÌÏ~/TîŸýÌ7ÆáG4vØÇ\¾Ì`R"vàñÏÄŽ£ªÚñ@IDATʽ~\­mȈ<ÿ <’qlsJí—•)ÙY¥öý·¿­ðî,Oܵ/áÏ0ÛßérÖäÎEiÛ"èË8èì(?ëUe³® b;4G’•B¹ôö‹gùß<ÝçP~Ë⾜üîwÍýýÏŒ?ÿâ¥ã¸cà‘Ÿ{ñ Ù•Q=è:g ßÀøçxŷئÞ}Ø´fæR¼^á4¨EϺ®¾Àa5ºì“ñ;¿Ï ?¢98r¾ÓH³®tY«úÄ Ï~[÷_~_-¹W†ªã§»ÿ®Rî¥É÷BW‹‚Ú¦,ÿ‘P2ð½ûÎ[%§áz¼|1©žžhÁ;‡ãMcbâêD÷ SŽDª£ßP„ð?%¾È´°]Øõ/¤X­@ßãÓ–ŠVë¹k¾.&Ÿ1®æo#Á\ð—,iSâô-ë¶ŒõŒ'ùÓž‚tu« Ì)¿ÝWãÀ§Í˜Ð•æ³ïK}ú²ðÕÙ’ëI§ŸÍ»n˜¯ÜÞJ\~ÿ‚PÕdwÁžÖºq$–âɵ©‹3ÒÖ]ÑòñÆö‘Ö¢ÀÆQ]]Ô0ÖãêÚW8à•>~H3–5²oÔvä-¸ó.Í ã»!,c•°|µ/$h¢ØÊ7‡™ß³î…B¿úŸ¦À¹mζq$·,ÑLH;:ä¦a¼ „霃X!Þ4fâm7í;Açdäj¥h©f@F+dkvšfL­þÙ¨¥„Ÿz4xÛt0þ¶c¼|K— ¶|Œ›ºô8:“TiZÀiS+¢ªCŽæê0r‘*¼° >2´…0ŠuÏl¥Rùvl^T%ÎÕ™ú,„Љ´i™gå´­Á¥“DL¹Ê¢+.obÛ–Ø s·Ëcâ 2)æ[QlÇ+‰í‹ºW3½àB’®£b8²#€ž1aþ¨[2P·9­u¼ÊêYväpøåSeñ“T2}%ÄNÆ©ÁÎ'Cc)ú:Ù¨þGD‹­Û•ÆÔÜR—aYYÜÒZã­êª£°t‘1OHç~J“$ŸÒ/¥%ˆtJžXsd{Mò+b?HצèIû½ôÌexü'ÖðiùE4ñmû‰`†É´£l«Œ‘™³Ž‡ äm®ù¿Pˆèf‹ÁK¿ûñ» Jˆ¾‘5còO’Øš–øE»á7¦ìŠ?SOìêv, c¿ÅwÆNÖ@¤õÓ ÐµÃ›ûAå^ä Â{q`uü Gä€üÓ¿ýùáãAßúÖ7GùUáù‘sså÷O?w WvvŒ#¹=ȸ_ò„¤|â%¨¸ŒGS›]jˬõW‹-yú´ï—¿`’8¦Ò»  ôsÆâf%/cÐZn_dP0²ö8`Rºvo­ÿ×O ’—ÀfHŽ—}rß9Øg¿œ€î3žÙóÜøÈGÞËmjwŒ /¼tħSÏpÿÿí·Ü/ø 1Åv³½=«úæ#9þ{/{\2ÓŒG×!¯y-}íþ3_ignfn©¿5ÿTܺº‰\’¹†a#ùÑ`yóU¬,GÉ™ëœÃðô׿ì3Ÿ’õÌ5ÅS"oÚFZ@xêx°%=¹†mEEÆ`•5'³/ ¯o:—ß¶¾¹p”dês¡ô›‚fè u1’Oø„ª¯zU\ës<¶(¡Äà®cÊBå-~ÐŠÐºÖÆú±mœÆª:b¡\í·SÒ¶ŸE×Ç '˜_$Ì+¥&BQ½ös”·ñ1ëá&oÑ…£n…DS ”>YêUëk¿´‡Ž4ïÒò¥Œáx‹tÁDŒk39±][”C&BP‡ ¨y‘!® kŸãLÏñ‡II°ø!ž1(ç6uhÇCñ5Ò~W¼£FÇ¢Ú Ä”•ˆŠ³ *±Y{×É“¾U6øT³ÚmÌ~²²ÆlNjAS©n’«()ä»Î÷޽Ùéìè,W—*_é¾›òâUFtF'–Sò­ÛÑž±ÉI’ú»•+ÜÈ´³Ð4ÁË«d&6Ö‰“0’)E[WµÆ@¥Wm‹oÒ„Š)yÞÜÖ‚µæEY_¥P¡$n(J$F™KÓXÃClã7ÙŽ,:6³“°‚žþo-~Õ—¥Ïêx›„Aæ^\Ï‹¹3/Y¼‰·nlS´ü^Y¬Xœ¤gЇM¡¾ò¯®¨ÚÅžQ, lcS‰³?"g[:z]ÈPL¬’Ía±Åϰ”°üÍ‚š§æy#“‰ŸAR/òÓ¼i'J\Òg1ÐÒ‰Ò¾.îò rså^Ä8AõŠÜÚÉÖŠ2S›U“ûÆ/F™Ü«§`ˆ1­Å¸ %‡§íÜšÝ_YÕ®ªëSø¡¼z«ZωW)Qï!ï›<@SÎ7ûAûùGX˜Œ½%@¿‰C ˜ ‰3Ô1‘-ÝÙÔNn sìÅÿæJ9Oø*­\w;±Uº¯úÓ[r¦aBO1*^mK¦_n,ýt¦kJ)2ÐgMú$·OL=\H.£‹D=e§â•}þŽ>úÄù‡¿a›øÑ½g<Ã{Î{û©ã¤Ÿù㯌8ÜÍÁ—^ôDÈä+s®]¦c9ÐjŒ4+èé“·!åd™¶Ê3]ú~ù[šûØU&÷Q;RŒviú3“úêKÇ|:u®þ6æøSc«Ó×aXI~‘Ò /úÅ^ž8t _6Þš¿týãûáqÉ×®äGî.Ϙ»ëž‡Æ~íà{$f-õ–/š¸&çÈ LÌé{=õ^óÎGçY$¡oÊv]°ª¯ÎuãQÚYâ\ÎÁ¡â®û®uÊZV¼Î›UDÎ/÷ð"ÏÛËè·€=ú°â©"˜³+' j/y©ãC&ð=r„\¿¢ßk)ôÝ@¤OašÔ7â~y™p”ÅÜé€ôæª #L^mâ@ä”ñEqß[ÍhSïÚÞ²ß]òÓøÆ× ’ýwÐvKÉþŒmüŒ\ûRRØLÑé³±uljöx3%¹×<<=fj_˜æ¸6¡Å׌k¸òY§ÈIÅv@#7þ:©í¾Ö1DŽÑ1K9!SÅ¿ä͹²ÕWžhiP›ù§X³HK p×±¤ch c;Gs¶U;ÙÁRß<¤2Çgöu2xõ“ˆÊ¨¾—'2(Ô¿ÚÑÆêŸÞå2}Ÿ aSÍ[oóÙ<Éžq`Ê…bÍPç‚v.FÏŒ3SǾp› ­¶ušOÕ‹E7 °]°¦Ct"DU93a+ÁQ™9À2”‹^˜ EÖ71¦õÔTÉaÛ.0ú©í¥f¸~4’³1 Å+¬ææ`©NT“œ‚¢ãB5w²‰sEå•™pI·©%ÆcCgÔÇ&^®ö¨¯äèM­Ê§^£kC†î@YPA3ø)_ôäÚimN¸ØwÆñë¾xz°æt@ú„é+ìim¢!„Û¬¬È/û¦J™¼6z•­î’T&H2ãƒÛ,æaÌžÎä‘c)MoÉdÓ9©!ˆÐ’“¼¡‚À”ñ‹ž Åš˰"]ÁV%}Û¼yȾ:æ ½èÚ–C#PM Íæ.,ddF.¸dX?§ŒXb‹çã#QW ÎÂWH”…‹ÊÒÏÖ±]ùÚÎN²ù;;¥•‹Ai Rgا"û©S îK¾E¼ÄÚ±’ñ„%è´ƒ®> !¯ž6vÃÛ{%›D-¹²áÜáÏ<©ÜþOK‹xPá3îš¶È+Ò õ´§ÏîŸeçYùÄ›1ÇDÓ^ü„iÞ²ðšÝFü] k7RluR¦Ý½¼Ä€<èàýÇîÝŒ¯~ùŠñÈãOñI€†?á(žô†ñµ¯]=îæ‡–Ž8òàáï x¸¿FìdtÁ_ó/áN#Ù€áÖ€žxµ=½øþæoq<¸I¿:ÚVŸZ¡Os°Ë8ËÚÍ9›å`Ê–c<³ZÉŽZN²#è—Áçàÿ@n7{ü±ÆqŒµwžÖøSžRõå/c<ùäžqÏÝø°ï8òˆƒ3Öœ®ŸÎUךÆz0)ò3™i{µ€æšs6¢Í~q­5PUßÄ’£(e]³;ǵ¨˜o9–b327‘Íz£F¢­°u6ÎëðêC…ÜqBNLæ[¹¸þWöb©¯ ß‘¯í®5ÖËP‚U‚$ŒG¦qEZ?ÍS ŽFƹ>¥HVwâÆ/ìÓÈA·žüytÒ7 „SŒibJ¡¡þr°(u®ié[5—*¦3Œ±Ù7‡YW'hÇÉ_\ž¸ÆÒÜo tdõ Œô‹¤ì7"c\ê,Ö$x«Œö}g…z¢Ü\t¬]Šù£‚þ7ö *²Ó–ý6zæ5í(+ˆBèêu œpgLŽƒT¡Ëi®zâPÞÄRwá˜Sì8¦_¦4™~;Rç»Çâ›·  WÉlxk‰÷Ë vÜGy,njùXÐãIè)OÑz¶­R¯#@ÃDºÿOV‘®ó$?'½ëÔ‚¡Ü£°é2|éÞÛ¯ž$ùÐ^½²ÑÔ0E‹Ù"¿ªá£*¼ø šX …HýÜ!¨ ;Vòä@¼@ÆøbU•mhEÑD}ž@øœá‘f–`5ã‹•BÆ^ÆQ¯ èïÇN)«‰Þ–ýM(ð§GÝê_rHSû¶§loM¨XòÝÍã±(0µä–­g¡¼:l‘MI±a¿æy“&us­}uÀ‰ =_…µïâàÓ’kxËŒƒ,Aº¨†ùÉvæ6©«£ä¬=yÚ‹£Ù†ªb3íÜÂw¬â' ª®ëÑVj ⊵Ic³ž~°lh:gïð⓱翹3¦Ä_ºý¦Ï9û7?Éÿt]³(ŽÅ¼Ú¿Ê¯4èQv‚ú‚LÍ Ü±åGŽïú¯QMJˆ|Î W¢á‰‰HófmªÈ”=•m´ë'ˆúl€6.Ú^/b1 ùDþò=ã@þÌéÚệô„À"Ý<$Ñ”: Éã•1ˆŒy5‹ñK1‚§™Žƒæ2þ'Wò¥Añj©:T/qA_¶µ£tY™ËEWkSô bÍ•Œœd ä¢ê†á ì•—_?îáÉAï}ï[óƒPsrð¾÷Ÿ3¾uÍÍãê+nG{ÈØŸ³Wøâe.LàSû©öõÓ¾ÍAýšO4ðýòw(®?gôiG#¨¼Î©­zFrŽgõ²6TœÔgžtªáÀ=úøžqæ™'7½ñµã³ŸûʸüòkÇ>ºóîrbp¿píïZ¼Ä¯ø:ž€äW>y[¾@ÌsæõL²¼ŒEÓìz…¥¹ŽÂÉŒ˜“#|ë⮡Qý† |\ÆVŠx1/s «­€˜‡®½æ"Šõoâö`Y £ŸÌ"§¿Áïò’ºfÄKA&ÒQ~ÉuM‚ÖÕIô=t×5ó’“±”Cuùd|öŠtT›¶»Æà¡±Ydô?@!›syºxhÈ…cÐõƒzBC8Ç–ÊÆ×Ê›@d«–µ3È´50T|¢9Åk6 ?‘îZ©-u¢9ÐTgÚ¶¯³fê§rü¡¡ ÿ‘ÓŽL77òJ7T×u‰Ý÷ÛŽ{ó=»—‹[=]Ï~G }CLþö…GjÊbn ®iZó@Æwô¡M=€†Ÿ‰ÉK|å¦ßuQ-+¿bÕž•;‰¯.VÛùÍ éߺÐ,Ó¼V“k=f1Rm€mÅ\ÅŸ¹/“u2"h_§ÿ&Vç°vÀ4·U!­[T4%èRÝ‘$CVv”Ll3(ôSpÏdÈKÐlSSS¹í™kK+ZŒ\Ìk:‘!2X9PÈD³'Ê`«îLR´µÓ$êWäÔz°’æ$2rÓ®*úW;h­§ËHZIOa+«‰¤nÛÖÑ0´‘C¸Ỹðò(KÂÌq K”‘¡bâŸÂèÌÐj[^:Ø|JJtôG¨Xš9ËÕ#ˆÒ½°# §r´‘¶^à)§¿æ’¶‹]¾¢³Ô»ESmp¶SGI¼Zƒžv­DMyŸr‰3 2KDŠk¬)'_¯½•ÆÅœE. ;…ñ¹–¥!NT@\=1lRS{±å@·Àëdiî$TË- Q Ôb ì,Iõø8}b-Úr-Ã9ít•Z2§žIÔW1½Ê®Âès3E›è`Éû®NNVmG)É‘ŽEŠèíùÆŒOÌlx‹*­ÆÛr£Zæ&®IVcQ6qÄ<;åñaÎ^÷ú£Çí·ß;¾qÉõü€×ñã€ýöOžæç>ÈcEóä ÃùŽÀ®ökÿ©šù…}€´xÓ†¯ï—¿C°»èÏ dª™Ssœf¼ò–“SF›]ù®Oú˜¾gŒe#ó~œ'èø©‘r>Úóáÿ©Ê8ûÊ—.ëm@O>3®ä‘žr¿Ñgù¿È·‘];æÉ&ãuŽk÷—úå$èPÝuô;ô³£në ¡•È;©ˆ/²5’PõÛÑ»Lh>sXÂö!9 #íB4´;«Š›>øÑw®ëP°Íþ! „o/«õ[åm`Ñ,I<‘¢“ùŒÕé÷ê(Ñ¢ïŪÎípêÚ›5O¦º¯¢[K,Ú±ŽÍ…™uZÖQ¸"Úæ<1æá¬Ä|«&6Š'²Âì¹Í?Ê3-¡+&±Ÿb>ý+/ŽÎuF›Ñ¯åŒÇ¾Æ°½ñÓý¨V̯tãJüt%à’5)[E¯äNŒüõ—s‘ mÖÁ3iŸ¿W8Su:™®;B¡@ ²Ñ±m“àþ9D7åk±¯x.ªÙŽ^e‚MY…“£ Ù# V!lD”Rº|[Šñ·¾h¬fræºnÛ` ý©ŠÒ:–jsfàj϶¦ûƒ¸ bVOƒø!Dm¯*~P_cNôâÈQÅySÝÒ[€hy ì§e*¼vx‰†ƒI5§ñLN¨¹ª*CºÅÍ%õr ž–Î;:åLûFÀ©Ph“±êšpasáÔ”C³…v#ƒS V¼ˆÚ¤µÅ‰ËfNƒÈû‹ªt`e £á@[åŒø îVâ£,¢Ú&C¾U–§ô±%ÁØÆOhJå|ÄC°šÉFÃûÊeDÕ.`¯TPwÀ=Næ =æpVùù˜Ó@ <¾iØõÚMLPúä„x¥\þô‰—g¯küHŸµnŠ…Îv2' š2ød¼Š™ŠÍݨïDíU_ S/3Àøèƒö–YjžÄʧ+bQ2Ô¬Àð*¬èɪ&)® m ?¸Ð\0zÒ¥¢8-G~Ò d‚!O; ½iÇqîHŒG>Lx7StZ³ß]ªçÜ•©JüÔÇú²x&L“¸|V6Í(F#ÒÌ7aK¾"mB–q¤&ŽýéœÑ–ŸÁÍá¥S‘«?v\̃[ù9–ŒDsB§ˆ]žÔÍw†æºá ÷åJ‹!¶r‚MÛÅt ¬Ï‘#†Íô—ü36WÿK1|›C–+µ/r°Æ†?b<ΕÚO|êOÇ!<òíï8ƒß¸oüØGÎ/ð$–/ýù•¹…èx¬ Z$Ⱥ¶ý€­¸ë©f·Ó¾ßþ›ÏG{ÆŠ/NîtÐ×Ó»kíËš±Ž8Û\`a'àï@ìÍIÀ>;vއ~rüü/|d<þē㊫®Gq(?X÷Ô¸ô×ñ´¨ƒÇá¹½ìÅüW×8|XcÛAÎxrr Ù\lÁŸî##¸KŽí Eo©…•ýs2¸òŒNz6ÓmQ\B6ûêœy0'âE[§T÷'6 »Åßâ°˜µ4MpR"y›²ÀƒÁCKQ"YyiáóÖ6®‹êÄ+Õ’‹]úÀO36J°dÉc›©xÖÎ\B.BN’Ì•FàëMã“o KÇ<È¥Ä7èVëðâ°ÖŠÁŸ€þÃï Íä|s¼¦Lœ)°è·&%¾L ©ÄËvŸ%¯Zrhƒ4³2[üÆ$q­Ñj4Gà@ÏK"%v9¡Ò†'}±båÌ‚ý¾.€¨c ´ç{꾡i·˜³åËò;'Z@þå«ÍÈJ7ž½=¥þòÜñ{ÌŠñè¬ûðµJÐqÀtnœahšÛÚ¯%|ZÎ"\¿ˆ32íÝœ|Ç(ž5¥íëô+uÇ‘Xþ9Bcš7ÃÒð:¾Î9¸Úø¨iãJÓW}œÚÁ*@=“cÉðÖ–4\wø¾NÀ7© Iøvšm¯p ã»Î:,:]qfák`*g@àYÒ°øâaСž[…ÀK"Գȗ"pü¡Î6÷ÃÂôÀJýH#+l$Rµ‰&¢Ïb#,ÞôFº:ë:;BéˆwÐ)ml¢¥ÍuEH¶|íX 3ú:5UsÀÏî¶«Œ/òÁÁäÔŽôÍÓªÖ>Ðßì´Øf1јNgGî¶õ´cª>iMŸ_´!m>}€fŸéŸ¼úÊôž>$Ñ ¹§ýläc«£›Ñ—4Çú,¦ò•djaÔêâiËyJY¤Ù®yj¿Y”ÐŽÍÈšk*`ø!S3ÆH­•Ú ÇædªÛ| ãUý9}ÏF‹sL®óWY‹rÁ¦’¾$¦0V¨é³rÕ¨»¶äÖ“àbû’W«(Sëâ ULBŒÃ pµ³ XÆU½­ÙË.#‡ñÌu/¨|úÓÿž{ï^ûÉŒûî};Oög—fô»î'ÙIµN4¿Í ­–WÓ¾ß^™ù›Ìc€žpëc‚öoŽÃîCsÈ9šìoÒü•ç—8ܹ“kq >u/¸àýãÆoã*ÿu<~vŸq×xltã…±ù"cÊÇÎ:e²3'tÇË0YÓfñ¥OŽ÷Ôëf4¨¦ô ]çiú²:åÖ-|a8öki TÇ{¼3}µ‚¿D‰Aç“¶7EŒ9×qÞÔ¤$å¨ÌÙ69ñÈ<‘Œ'þÌwsеËúOnÍ£Ø=€&_ÎiËV`]¯Å• ¶–^ò( Yõu5¹$µ]Ó¥¥dg¤fû{Áöø¦~¹àKdzÎ`Cõ–ÚRT_k;ïà‡bñM?5˜t³$á»úÚË>Ñ~ê«ãM¶îïóÉä¸!+EIœÉ€™2«Øÿq¢¼è"”csÃkk~j›Ìeá%2Hö=V—Aì/_M¿Q{qǵßRTôZ‰¬yHÀ×÷ÅSC?#šÆcä !Iý„† RÑÅNÂÕ?êbyE_ IAË0t|u}Ìq®õ= zÄ#ñ93ç£cœÀñÊ-÷ðÚ¶Íò@G‰ßyÇH]Š®uŠ4s-T¿Ðßx£;˜ãO»Ú<´6 ÜÈ2 Luåë0<ÿq„M’¥ƒÖi¬À±%?Ívh?h0“OUDжe&¤iáƒM‹Mx±È’0ó,ÒÎR¸¸ &‰ðϸ”×/]j‡iÛݶ;ðÆÚ;ÌA­A8$8B•u0•¶æ—ƒ,ærúzµ¦í&…ÆÌ¡ÉH1OđɉL|Ò¬7¨Èæœ À^5@ßÿä]t1hcKì,Ìlc¼¸öÌ#²Ê¤è»›Îƒ´a‹¬(à›ƒWh30°…y…ÏZ; ÄT­¶×â…Dèk“µ‚õt¶ÉSrA€YCØM‡~'åB1¾ÚƬ½Æo6WʺÕ6ÒD2ꈗñÔz@*ê;¥XÙ ÅËÑ—“ÂÕž8ù¤kù¼Ñ­Žv,I·˜ú`{ÒmDÇÚïõË'9>óÙ‹Æcìÿé÷çÀï-o9qœzêÆ¾ðõñ,p<ð ýÆó<Ï}¿¹! ŒSŒþz[¾ŠŸ4¾zñåãšoÝ”öºþúïŒ]»öGðÅ^O ýbï:êÉònöW.j eŸçº¦=vàŽØÆbGn›’ëm*ýTš9àúИª—a¾Æz&èJ)Ÿ"T˜3çO!øú‡›±“ã 0ô2E¼ÄS¾ fµ;mÞgí‚>Õ½¬2.¬êÓöÍØÛ¿ï×,kòrÍXÓ}õy–ÚnßR7ßÊ ¯o=^XònµÇ#šU-mê½è"·C#ó0òJÍÞ¤ë²6â©ÈÅ pí4l âˆl6ë­z‚-}j¶,bêo®BC,™´ys íÛž¬È¨OúÝ‹ŠXÄ]\é­'…ÈdPG](ò¡{¢bÛzž4݈ÖUñS uûÁ:ÿ‹e¥‹6’ðÔž;=ëé<|‚׫,Ж]U”§•7‘ÙÍ«Xoʬ˜|”±âA`:^ƒZE¹],žyv X¨;ÿ(ÒÌ‘–ôÔ“¶ŽêKõµ’oú_¢šÜIÛ{{¹‘È•´È¢ŒXv¶IP}é˜ÑF—Æ|¢b‘ÕËŠ–RÑ÷ÓðÄ¢¢ß V?S·£ziTæ¡ñh"nKKÅÜJ¯öÕN© A‚Á`ÛµYspe|Å1ç×Ì%Ö,ÁGeí2Ždƒ¡é„Mþ’wñ5‘ôú”ŸÕÇŽ'¡W,öÛ| ع¯|ùÊñÀCOŒ÷¿÷Œ<²ñàÝ»ÆÇ?þ¡ñõ¯_5žÜóO Úw>vTõoÚ¶ùëxÛĶU͉?4¦oþh”·šØ¯ë7P¶‰þ T·Çcî^áW‘_àÑY$õÓ_vl»Þ_æþ?¥¬Ü(¿›µ½¿‘‚s3;ʭ ×>ç†ÃB}⩌IŸõì3ÏcŽ>|üàY§ó©ÐÅãúnO?õìøÖ7oÏ“¦Žâѳ>NÖûûÕ"¸"Ù—Ò¼XÔáËyWO”Ó/K‡%UOn3¯ôyé‰=fê@‰ç ª›úÄ ¦~À#JRGW0×jªñWèÄw ÆbÁôÖ£^œš~ £cÊ«,E»®Fk_a.ºÖ÷vÐ;ú“•±>Dkÿ†‹"vnǯڌ)y“=ßu)µ(S_\¶AÂݘ9IÅox‘ÁTK“eU_ƒEy/`ÊK¡ÿëØªzÅpÝRo ‰Š!u0BH+¾(™õ”m|óym)ªÎТ6”9ÏQ¥KnÃÄvþŠÙ˜êÖSä ^‹êÅ[Jð5LIìØïÝõ‰\‰n%ëÞ ZÆW¥ÑÐÁ޹>ðD l¹;…®M×ÿfY™bXÍÎ8ZV!êø²Y1äª-üp¡N<9 Ã}ŠšÊÙÆ~ôk_\i™?Ô"ÏV?ÛÇ óòbx C—$¤òÔCëø'¶ô‰ùû½’ƒô/Ô±Ó‘áwç"« DÈ[´-9 ÑÚ¦hÞùŒqȶrVêĈ¸÷ jœFf8žIºC× ÊƒêùÒªtþs_zXTù&ÀûœÈjn™DEQɸØtQÀft `’õÛ¨³¾3úítѬDlR¥W§Õ‰¡.¢Ó¤ƒ#7r¼Õž~Ïi ]Ëò¦Q¥«À¨L&^„’ñÄ%rì%—2«ã ’þÚ·ùbL°£’šÖ|9¼/®ïfp¦PÿòÄù‘Á! )¬ˆ|è9\Œbyê&gæúÊ«ñH·"â`M­—’AïÕä5½¦nyÔ-•ŽŠoÐ…”­Ïv!j´d)ÕÞÎæü°ÿ«Åfê‰#ü:hv'düº*¯H«ŸAÍJŠL’—±–q¨3¶~‡";ÅxI[«éŸñM\K1Çž|.¨8Ç<¦¯adöL§Ñ‰¦|t_;è¤ ¬§íԕö}MŽ‹8[¹Y¾1ŠéGõÁ—œÀ‚~Ÿ†jLR‹Ißš"sµt€0Zv,µ&J"ANA×lóß¹DÅO”víJEЂïŠÂµjò(~\?%ÎEµy‡ OÜh± =âõ!ã¾-ë9¡ÀÙäŠ5±âÊpv¼á±¾¿ÌIÂ>ûì'ñ=ëo¸}\zé ãØcqçÝü‚ëãÃ~×xøÑÇíwÜ>Øÿ.öhÿ¥’ƒIq ÃØZ×ç–ÕŽ@lûÅR1-O?ó ?µ+¿jìUèu‹‡Zß‚ÁñoÌMÑJúˆí÷Âù«yŒpbHŽðÓ¼ºûžwÿÌxáùr¢ò=mÿ•yˆßí÷ö<½Ê×±yàÜZÃßS{öÄþ_í+ž|¯|8PÄ“uÆ®'òHwÝxòɧǾûî3Þuþã;ß¹{œö–7ŽC=x|îó_Åþmã™gŸ_¾ðªqøa»‡zçXüIÙg‰chñÔþÐBŒØØÆç©Fœ)üz‡œ¶ZÛ{seûÌñ«ì F0»$<ˆýþšÄêº8•#¯îœ—qÌuøÎoç™±OsO'%S~¿ƒVߢ>ñÖŠÓ¹h¿ObÄ9ÇR?ÙÓ a™*þòCÀ’/A)Kw6ã ¢Qtm§¸´mÖQyé{±°mÝ ²ˆ6²jIÖíØ?+Ò·|õ…H?O>qPIíY6ÙgHFÆõÐ O/ql•õÊú#Ž±ŠŒ¹ìÉ•0ʲÕ^m´ÄžVjΜú±>wÝK¬J’c1¬jÎ\~ Ó†Dר8RyqQ³ŠZ̓üÕ/•­mó¢èšOŽ=íG—¬Hž³T¶ò3˜t‹‚bi7WgÐËGB–1ZËZ0uÄÑÞÊsNJõƒ²òéø²äÙèÓÞ‹þ‘§ûO,{O½Ê7[d¹yIþå"¥ü‰áðª[è;ò©ûœ#  ›O ¶Õ`@}CÆïR²#“X””$4YF 9—Nƒg„°§)‘M ÇÀõO)ëà+ pä-e Ò+a2£¯]ðeËÁn¢!¦Ø“K:)œ©*oìôs•A ^=¸sgN3¸Ð]4D×¢¸æôÏ'·xëO¯^nÅ¡ŒE ¯°)«Ž}OM# †F§/4§aímìDb¶Åáe”¤³vì©j‰Þ<ÈI!ÛP—¼lè8Q”‹ _œhÇ\ÛgxDÃHsÀOZ¦;V‘qO—Úa8áâß“À*9ì}å_ÿP¨µúÙì([zN1ì:¬Î2 éî@ Â+ƒ¤ñ8éŒÆ÷Ô´5•õ5“^5éÓZhGL튳ÆJÐËœ¬¿e'J³”Ó¬@mÚL¶–YûA1ÚO–ØkZ5V ö´Ä%Ïÿø¡£6jÔM›”XNK@2òitÌ4È 9}ΛZ‹žo]tºÈJ2[’q‡7#ÇkÖKÝL˜æCœcvÜi?SGn–JŒg~³MÆÜ „sÑua{N´eŸ%€‰)Vs$“êêÄtF,URh».l-ØQP¢ë…A¨0KvhÔs0Â6!šÈð†ƒžïÇàQGÂàçÆ¿xYn¹òŠëÇm·ÞÁIÂÎÜîä¾×+·h~êú˜ÇE6gýAuó‰ ²=Á Ƈ>8Þü¦7ާžzjüø}dûš×ŒG{|ì»Ï>ÄÆ«ð¤©o¾·c¾Ú'yö—¾X·¨g=_ò›msàÕjyž¬-þ^üpMÒ ÿùçŸçv—ÃLJäCc¿}öÍÉŠØKv»íï™í¿ÊïìÈ'†8âù Ïö‘Å“ ¼÷½Ÿ2zèaò¿OúKÙíù}5îvŸr8ðwì½#¿Ìë•üûì/ïæ“ž .øß 9xœpÂ1y”çEüŽÄ7¾þÍñìÓÏñÛßädçÅqìq‡;÷ŠÎËœ˜t_̈ÖUüÖs•ÕÓ¶ão®?¸ˆ8`-l”ÍšÑ ¯i¼~÷ª°›OïÔl_ÚÌ\h{IÛ·W1lnìÂuŸ4¢ñl;vô‚;íÅ ŠkŸ˜vúÊØ×_-‹iÉ:n5Ó‘ 9‘ÕÙ‘ôéò-:ð­[ˆi8º[ms¥?úßÉ[öð Æ)|bYq¦otŘQ±4ŸÛ¬&SÅè"§N¾s`æ\HôIlüË~ľ‡—Y§ ¸µ›TœÃ…Û(z¡Ï»2ƒØÄ‰2JEFœØÒ¶üö!C“¾•)êÂißQ“è-òp$4\OíÍþKeò%²ß.%äXQ7 ʰ­èS‰¯Ò•™¯ô–´9"dÈIõ£”±ÑñV´·ˆlö90ŠÝOƒÀ\3ºü¡Ðc&uš TçR³!¥’¹¬Ž¢ÉzÔo±"Ny:´|JN{¹•» ¬ZðôHÜ铺ø®~ '¶v8pͰ>WE¡îAZ³½tZqùNë«Qu ¤ÉÉÎS …´Ã_vÚ9Èf@ë\ên}U´ƒÄúL€úèzàdÛ\IWûS”Ò§–ð½¶SâykÈa‡ÂÀ½Æž§Ÿ畱?¿ëXã©§ŸïÐCá–’Ýãþà–“£óiÀý>ÀOwï9¼½5È'~è¡ ï5žåÀø9nzæÙg¹…é€\%µ_Úñ6"?Uxìñ'bÛƒø}ñáà]æöýò–#Ò?Ë!»ù±*Š;¯‡y$võû¶;þb¼ýì³s }ç]w]ñI1æÀe’¸íóà<3öø}~S÷JúsÏ?—ûååyëÓÁ4öÉ—láóì|O|váßÃ<:Ž;æ5㨣Ž7Üxcð¤ó&÷»òÁ'ædåë­Fv?_Ô=â°CÆ1Ç1ž|êéñÚ“¯ÃI㢯\†Ÿ?_îý]¾~ ß qlßwσôž<6–[¿ˆÓ8XQˆO4çD笡s¯;! 2¥^sê{HL pòûÈ•g¥ ý°[„L¡ÒªD) ”å|]u#–¼æb}–­L\uŠažÂÏúášY]¯Èû)¡¸YÓôsÚs|çä½V€r­€ïD”'¼ÒÁ’W?õG¾·;>r¼yËüÁõ⣊B@l¾IVôì†$Xœ““^!qª¯„v‹N£êÙ¦¯$aÈ—þ»Ž+SüT»ÖA¶‹adG.ØzW+æsõú`êÃ:f²±æštÛ®iÕ_ûäD\ÃXþ+/?²:Á¿õ½è,óUU(äÂt¨WüY^ßô*ý[ÐXçϾ“­`âYlÚ_Ö¬·ÿÍYÂu½¥(•õbdqÚöŠ[‰öoêw£-!®k\™¥8SšCÙbŸyí)VAtó-Ñ–7ÞN\ZÒíkc‘k‰o“—‹~à&âëøÓЋ)•Xã\ªX¢94­¥/ÁY}iÅouW"ñ]9û½M(‡sq ÿü#5[N›1qÒù1h+æ¦Ö ‰E‘â®xÅ΄ î` ® *Öõ£¶hèK ¨Í¿A[  ‰‚AkÅ3H#9ªÆw‘4šè Œ¨íe5`õà âÁ”Åw$#ã›FéêY28•€°,Ë ?¾ÌØP‹«H"!ÿ¥àøÑóÿ„ŒŒqÖÎâ/ ÛÅp“ÖÄï K¢”Ñ¢?SNg¬Ö[ì$+ÆX°êÔBÃÖ-ýBQ=_õK†júY™`H ƒwèzc.Û×Ôs°enõÄ.Q°¯#»¥+WàŒ›4$S|# „ú©#d|!†"äwÑtKisµ .sg¶v¹š©\JPŠKUºhP׿åK5ÜXÙfÑÕ8™øTì#eÖÂh$úñM5cEª`Óíù¨W_0îIþµcA€!¥yI—"\è›ü«âƦ,žì‰É´¡`ÎBK¾;8“ûqùÎ6ß9Æú´%¾IËb¦‚“K[Ö“ËÖ?'…ðµ™E±õ©Sú@Ì _¼‰MÎV?eœÀ°[Ó^ã¨Zp ËÏ I,ζ=Å_þfžBÊIºYàÅg.dûï¿“+Î<Ö‘ƒå/ÜMÑîÃ=2ÎûÛÇÛÞz:°»Æ 7Ý4¾ðÅ sEûÄãË}óßá Úƒr'yΞÉ#$¯Gu8¯Œ›nþö8ÿ¼·s`ÿ,·Ý…½ãç;ÞvÆ[s@{ó·o~á—ÆKϽ<^{òIÜ*t`>5x‘Ó?ø£?æ‰4ûáEFZòçsêò‰qäá‡ýøGùTãròÊøòE_×Þpú»ã«¡¾éo„äøæ·¾5.üÊEc7åüŸçž}?¢v_~½–'Ý@øá|jq'7/ò ¸É“ýb…þü©'ˆãÜqæÛÞ½›o¾yüy°_{òÉã rsî§¼éMì?:þø³ŸËÉÌ /òe[x|”O@Ž9f<øÐCãæo{<Ëÿ=÷ÜËö9¾ŸñîqÆé§‘É×Íã äÃØ×½öääÈOQ^xñ…ñûøG¼÷©<ÞÞ…Ðøá>gÜvÛ=ãmgž_.¾øª<¿ÿ  û¿ÿçc÷Á»8ø?Ñ—{BÂIÉK¹}|ÏÉ&Ûö¿ñvÌÁu¸2ºÌ½ãÇv²1ëLò¤F3ƒXYÆk&4|r}e3\Ñ-R»V¸Íú3ÛbÅt÷®9±ENráškWÆ…˜"f‚XmL1Ëyý`¨g©íC²ëK«kƒSOÉåŸæjÐmKרÞ9@_éSÑ럡šŸ¬ÑÔ=IqM3±-&uû.³­M±l*lÓ˜øé7Ý×(U›‚jCe0Õ³¢M±d§©N‹4uÍIòIÐÊJ‹ÌäÛ/fݾ¯E¸ðê³ò6Ò ÝvNH%ãGm‹XËñY‘°°•5éë»|YÑëÚ /zÝŠ¶ Öxƒ¶÷…JÙ_ê—IІrÁ,¦k¿XFh[/‹U£ÝNjH )ÇJ09®Œ’ã_;“œüÀX9.«|/ÜÈ×j ›¸¨9B= ¦øŽXÉ“ ªáøÚ¯©,Vs.›¶n%Äêª&!c$:íx ýÈnL_DjÓ‹aPá5Iv’_\@,ÜüC?î¨ÌÈ÷¨; €ƒ¢oà’…I0í«/ž¶mº…ߺívjq-xBLuƒå6³Xx¦aÁ‚©¬¬t,›°´¯å±NîˆÑO) Ó ¨=U‹‡†X´SÂÐ<âjžàˆ MúOS¾JÆ©-—·ÄlCî>L7…tà EéÂâ;¯ä~úåkzÔ ‰BìËÇFòªMAôT{ })ôlíÛÀÈ—B¿zE¯‹¸c»bC°òLN¦.Œ`'(¶ýCoÖÀ‘‚Ÿq…EIfLè*lE3~P÷ÄC5ýe½èË«|Ï(ÆKl9i“Ó寶5&€8Ó†Ö\,Ó–•ô½%Žt„ÖŠ™Å:àʨ©ž±5Gê¤Wâö–1ç vqµ.b‰o_ûÁJÒÓ5²8ÁŒHóªx”çÜÕÍ“¸ÎÕ€Ì8ÑïbvLì¨åªX^oâÄFÌü§GJ²"è›ÎäŠmk¹´ò£:yÀ€áê+·ÖØ'M1@–¾xÝa‘o@ú’ÈKÛ`õÃvhlôv•¤‚v<15ÄäÁá«_úõ ·§\À­;ï~×;s`z ÒïzçùãÝç¿c\~Uëo|ýëù‚'ø4àé\é?÷œsrP{Äá‡=Oí÷ßÿà8’ƒðG{l\wÓ­ã£?ú#ãçž;nºñ¦qÙe—ÓO;u¼ïÝïW^sÝxÇÛÏ?ù$þ›9q°l÷ÏžÚó4WÐÿàïÿ4_ Ý{|…ÿÇl|èƒ?œ+óöõý±qÖ™g1®¿áÆñNü=ëmgÄÆ‡~èãÃüซ«ý—^zÙxëi§óßqÞð$&WÅ°é ‘àÚöÏ+ô?ÊíLï8ï¼q'—_Žß°¿—¼è÷;ÑÿèG>ÌŸ—|ýœ>~‚““[oÿÎ8ìCÇ/þüÏåÓŒ¯^|1'/Œÿ½ŸH¾/¹ìŠñ3?õ÷ÆyçžîãÒË.Ûà^võ5äã\òñ±ä㦛nî¸ >o¿ZýuÒIÇãO8š[z®W_}Ãxœçö_|ñÕc/në9üˆÝüÐã‹1è|j.S&Ù¡âˆpürÍ«³/¤Ð2~i:ij³ÊŠ©î0‹?ç¼+‚ÓÁ¶ÿ*»QV;]g©“sVÌ`¨4µÍÁÜÒ‰~qïoMãë=Õ:KU(56Z:‘ýR¼Ñ*¸‰Ã3gl²þ1 uNzØêñˆïÊ/ ì`A[YSÎJƒœ%w.°5¦]Ê:H>ôÑž8Áfìåd…œÅ.L‘ƒ•6BÑ^ü0ÈorOSÁè ’ýÂÔ]Ç$f=yW绎=àÒáâXôeí_ê—ŸD­5¯2˜1wLéš²bSOð"óšIÍc.ikurØòg\)³úbÞ=ˆO¼BL¾›„HõÚgÖW;àȹnZ„·_ì7If¸^@Ù¦i…µ›Fûª±¯\®ïáAí>4‰¥þXK ˆ%ýšqR (ª¦ßÍ•uýFÏ’@ëT£ f¿¬¼Í”é«4_ä-ß­†—ýǺ ðìgUÒ4ÛŒ%ÁqrõÕ+\%p.$Þjƨª2’}uÿƒ2,‚"k º˜üZ¸]ÑÁ³˜&D'ª"+Ît ¨Ö'?€F¦V'WHR¢’~kÃ0 ‰/®¡¨—-ïú"ËŽÈx“ÏŸ' ¹*¬ä Ô°ó7;a)§Æ^°[ ¸Ø+qéfÚN¨òLXþæ•<ù’c𣉠•ßN£™8âÓº5#ÄÄ#žE—¬êC3pü[ygo‘ÎL®§Ï™€È(¯î*N ÝðcA½BbZ%h#ºýŽ®ÀÕc6ÇöËL¶ƒ$~¢(®?=¾)²0KÉÓw4צv2¾´Á¥.‹Õ„kl( °¾ Ci9úi«ƒ6DyÒòQrø±yÈÈ¢+9L_P˱!9ˆ±Uš|ª¾ºhÎ$$Äè×”QÞWSY]Þ¬޲¥œÙô¯EÙõEíßZÄ·9wuý1zÅq¨j^ß<¨p\¬Œi£W Èe BUß3Sæ×üh[§¬«Ç&EO­»v¼¬¼6”[‘d"“9€‚þh{óH?ãæQp™,bÊåFw†¶QÃüÅ_l¬ÜAê(ЭpÍY~L*aiÔoˆ9þô4s)šŽ¹•CdÂ¥Ÿœ;ÁF)QŠÇË+´ÆD}•È˾±ÏÄÌUÜÅR2uä2‹`#<}ê'‰Tì7xLF¾Å[Qyä±qç§Ÿzêøä§~k\ôõË80~%·Ú¸Ó8‚+åï:hÜpý Ä»·Ÿì'žpBpoºåöñ ?û3¹÷ÿ‘ÇŸÇpïÿµ×^;Þ÷ÎóÆ)§œ¼+¯¹vÜûÀÃã`®Ø{eÜÇÑÜ*t#Ÿ0üÒ¯þóqÊ_Ïswç`¼^ñÎ|òkå–¡oq2ò¿þoÿÇØóÜ ã>~A> p,wì±ÜÂóâøíßý½ñÍkoÈýõ§œò¦|²pò Çó8¨þ“?ùÌøÃÏ|~<ϧ ž¸ü£_ü‡ãž{ïÍm@/ŸÛèSïÇ÷ÖÓO{Ë8åÍoŸþß—\vå0¦C¸ÅI¿wsuÿPrqåUW‰?;øA­ƒ¹Ýè´·¼eÜy÷}ã¿ûoÿÉxìÑGÇ?ûµÿ/Û:^øüÆÿþ¯þ—ñ?¶uÚ)oÎ Ð'þí§ÆeW}s<øÈ|I÷ÐÄàAþÑGÅmB7ŒÿêŸþò8óô· o«òäÄâ³~ÿ÷¿Àm\æS‹'øµÞvq«Ðàן‘{‘—rvnÆo~"äHȘ`8¶2|©8l\'[Öûí4¬‰!'ã%çYðy Ž|dýí—Ìi}Õ~…bÓÅcÍâÁºFÀ1<^އ£[WdÚrÄk$ötÒvìiˆ–¼TŒQ‚ حʧž†¼b¨›êj_-ý`yw<ÔýBoÖ×üJÑot²ÿOÞµG.¡Õ×åW±ã*ª»Þˆ¯†ÿº”õ(v¥ n fø•§š<åùS$'W›žì§јøÊĨڑ—Ð/õæ Úr*ˆ1Ž£t=¡Apb…§uq ©#®±ÛHlq IÒ˜‹jél­N!¥ÐÍq@öÊE™þ0›tÝï&NM$–öÜ5¨“¾ì¿áËé1ÑmÎÌłʧȹ/ vx@IDAT޼ö`£ÈúœØ >s°,ÇS ‘j+Œø V‘ñk%4Xs h¶G-Œ€èØ6‹Ö&RêQâc†)R”¶p̯ÃXznãŠlÍvÿ,óž>µ?¦º¬Çä`é#Ÿºráú¾¸Tñ!tH›eÕ¯ôåÇ@ž©š§’{Läµ§¹ÊÎK ª ^¹…D©ØB¾cÍq·rµÝKXˆb‡Q‚HpõÅøÍ¢%ëÇwÝ9.ºäRnQ95ü?øw2žxòI®âŸ¹q·õì³sŸ<æÓa¤â ÔÛ…nä÷?6á×q…Û[]Ø¿\‘÷K·/r[ËQÜ*ä•ú³ßvÚxŽÛa>÷ï¿0Þü†×åï7ÒæcÁ±}#Wý…ç_üÚ/ç ýøãOóÉÀŸ]ôõqÁÿظõ–[Ǖ߼vœ:ü=Á¹’l¯â?üð#ã³öÅqæ[O#ާrBqß}÷{ï¹ïìŸ{â×AzÞ¿&·+yÏÛ9yÐo¿sàÉÊMœ¬œò¦×çàûÏ¿ø¥q:öÜévØaã¶ÛoçœyznAú7¿ù‰qüqÇò ÉQù4ánCºõÖÛÆûß÷žÜNtþùçý°ùx‘|÷¼³Þ–OR>û§Ÿg¼åÍã¨#ŽÈw$šŽ]ýÜ=ç?ÞåACNæHXvàÎMx=ˆšc0ɤ³äè¡’õ’´ „fÝ‹!W~ê;À²óp¬HVÞÒ[03hWÆvù”«k©Â–i‡ZñÌ(Oïèî°•èKjën‹ÀŒÆ×z-sM¥Ò§úª"Åo«EèA'²’7¶â¬40‚J¾[” ¥˜±_Ókßåü°ñ³£­—k?¢vö…Y®è…ø­`£qÕ~×^ó#•?tA½ò]zK¨qýÚÕs/ *¤_][ëf±¶liå-çHø"†x]S1î?~ö“àè¶ŸRÅGIzXG³nU,²PÃ*¿VÚxÕ¡Ålª7Ååíà“ÛŒ‰¾ú–Mp£ Ž'Ô“+v›ûõ^­®yÕm¯5žÄXãQÊãEójN2>Ws˜‹`1ªäÖ¤®¾‹œù†6 [›ÒŸŠ`KuMI+ñ¤6•3é'óãh‚Úæ¥ùV "íc–'¼óAÓO«1ÐX­ÉÃyÿÌ ÑU˜’9¢Ez Ù ÐÞ›8µ;% Q›öyØ2†Ãò]^Åâ@bëè’ (oàÀ2rài"Ô71MÅÍY¹Ì™`jÈ­ ö¥ 1©˜‘€‰-—¿8 Ü$Vœ‚c@È!ë6 HKLòF+Bí Ú(ô/œÚÔšô ¸ÆA=nŶlø¼¢Æ\ƒ=îHA×”idæÊÿsä¶‹BIÒ]DToþQDÙx"A%l’Á•Þ4§0tíM­© O\”‚SÛ¢÷Ï0; e´£ß6ÑÒf®Y±"!6/áÓ'ì ÅÚ^´`<9È ‹7þƒ6A”ÑîZÛ×B/oÁrŽ›ùËó}É¥yŠ|ûÀ’‰&æô×."ÆSs·q ¾~Ëwbd°8È»ðD—v¡“ÃiF‘æ+•ÚK·{u[\H‚÷`o¶!mrìuõ⩃niÛñKâVÉøWPÿõ-ÝËx¡™ºm9ȬñA34¯4çDT;êâ,HÅ‚g~Åò56q*æb'=˜¼ Öt5•éÒÌ[}Š€>‰C>ë®W*\#W‰b¿ºû¡’¹SaÝ&”þD0¾ÂkÿÆu³ '8¥éáæ$I˜êc7ò5›~ÑŽ6kôÆ\Ô[BÄ¥¬ú‰±d³™+†1˜…ʳjlæ4¡K’Ð`á©«žs'êßõ €1ûE\¿°úr½²½ûàƒƒýȣ׿îäñm®ðɽ÷{@-œ}ï•yåá ÞG€ÞÆ-0¯ç¾~ýºëî{ÇÉ'4®»þúqÙåWæ^ý=<sÿöWs°þvN(Ä{ì±'ò4}ð`vÅfžý-ýöÝwüüÏþ},mùqßý÷'¯x?ñÌ |AùPnï¹+÷ûïáK±'xü1n¹í;ã'>öããŽ;×Þýˆ>}øƒ?ħOŽ{ï`¼æ5GÏßDè:ôü ÏçKÆÇò©Âõ7\Ït.Í—wŸäh_¾D{Ýõ7æ$ɧúçÝ~4¯~ÑÖðS‹5ÀìC_ö‰ Y+¦¼õ•Ó$:ÿSaôº†Û§â(¥]û‚@Öé N®2‘U‡?5\qm³½^¬Lµs±)±!#ž °(«»ü·‘9‰?&£sµÃ#NÀWnÑÝ¿DOŠs3Àúá¤X´aΧ$^½¢x‘F@™0õË*¸æÄ‘=»³Ò£„§“ô¥—PÛÁ‚Õ|â |¢ cЕ’m‚Ü5u½PvNªÕÀùƒ–ɯOx™K9uÖŸØ2ñÃ)膤7ñŠÔêġЫkƧ´H(ß©“+áØÒ?¹[VÜfášfl×>ñtÚõÉüåà_lê›™h+—€¹.œzÓèη¹ìàè§ ] ñ­½H®;œm¢‰=}1³n±¾Gó¿©«á¢á$Šî\ lxð¨œ1§ß( ìâ.ïcзXÊ*ž l›bŸôLÖØ‹mÊ0hnÚŸ Ðzòƒœ¼‰wÞa8,ÌF&¼4ÂóΣ9ãÕk6mϺ1%?1Ußô ¾~¸p‚vú ŠSÛ} ) ìEÍëʵfÔ‹U·â/­Û¯–Ä+`›&6ǹÁf¥µí4‚9ÏFG åòŒ§~`CSü‰/Dü "ì9žò’oÝDªÌ˱c±iYøÊ¹c(DçÑÊ•ùS0ñ¤rí;±ä‘d‚.¨9?¼ê¶=AÜî³ÐÎgEëæ×?£Ë™t³’[Ÿt| ]gU!€ØÑÚöH«ýéÈfœ±eœ#߃ˆz`|†¢\|«äÔ>÷Š˜s>[êlïËÁ¶_½êºo«®¹žçÉŸ—ÇyzϽ_®}ŠVï¿öÆ[Æ?ð¾Üsã77rûŽåº¬¿GŽî7Ýz;O¤Ù?ßøõ_û•ñËÿò_g°qöYgå¾þc=†çÖ?9îðÁØÕWŸ¨ãÉ´¯|yÕGf¾û]ïÈ­:üÜ<þá?þgãò+¯á^÷#Æ·ùbíÙoy·æìæËÆwrE|ßñ=ñ„ãcÿ b8/ûºöæÛÆíßù‹|:áöc¼ûÝOšþ‹MòÆöîÙ÷1Þ²ó/þÇ_ÿê_¿Ÿ~×ÁOINäãIì<ðàÃyzÐÑ<Ýg?>Iøö·o-¿Ôì}oýÎãî{ï?ú#̧#_çV"O²Åö?ÿïuü ùx–ƒü•ãøÄÀOZîã;;ˆÝ[Ÿ¶÷õG)=š¾—Ò±u§l:¼S%cÅ‘d‘•QE®§!u°HF4ëŸ@æÅq£ºô©á¸´Þ1Í»Xv ´\ š},.ïÅdtMͯÄ+Ëá—¼.X§±S°®¸®:€¬ª©#ì_ ñSá¸à¢-lÚÊ+;_4sŒ¤­µŸU7sBæÔ³©Åà[] ÊRÅ~`þè™óYOÔQl3‡]™¡éZ.öÁŒÇ´õCØM™±ö#rÚç߾ˮE}­NPRQ™‰lú”Û8ƒ_ÛÐ'j.»võÚwô¬~) j/0°­0“_Þ²¯Púyf èü¯T㡵ŗb~ˆ¢/!s‚l¥;^F10¼u4ž¦šügl¸:u½V…Õ‰Œ ¢_Þ$cȈª¾ä¯ºE–†Œ‡³Ýÿ‹§úê|Èþkco«:_\ûµ*¢ßIÓß±VØòÁt]2!GŸ¡ùRš­SE3mÏ㡤 ”[@•Ç]8Ú¨¼ 0xIK‘}+´iå6ß`ó¶ù1„‰‰¢6:DBÌj´^6±ÖcWØ$¼2î¼<@Jds Ó4&mDœ‘. ãÑ%•ö÷w$tB›e©Kßtt¡k£·‡Ðqb)‡/žk;ÕfÞQd›ZvÀ’”•ÌÖ×´h%ؾQýPLÄQ¾WÕ!>¦Óq6ùªY|êÀRNŸ·#W¹–ìZý_%ù’&>ôŒ1ÛqÀ8•äÍ`)ÃoIŠ©¼% m%¹R2ù‚ÿ72õÕÜGË\âDNr‚ÆÔ©5³º4ÒL Y8ëNË dŒ"{‘ž¥>ƒWßjÇ„•·X*:£PÆÆÄÇE#W?`a "„TÐ>†q&n±“3+¤¦J#íDëþCÁð'\ôJB!yÁSD¡ªT›&gY`¸¨…@t–¬t@¯Ýºb"Aƒ¾²Ðºµ½Æ‚,õ: Õ<N?lO]›áM™'¦’éƒÝu*ïË<ª9Çj`õ‘J|É cÌj]èÊ›@ðb_Ú¶b‹ÒµÊF“òêE¦JÒÍPwTÓ¶S(;ÕÙŒ¿ð¢5A&&>'Våy‰“úcüÚá-ý¿ÆÍòGùè 6ýrºÑˆÏ+`I™Âù4£Rº¤¤›[m~í—þËܪr*÷µí’KÆ­qOî?óÌ3Æ?ùÏÿSù<Ägq ýÔ¸æºÇô‹g§¹·þ«W]?þ³üŸð}‚‡ÇÕ7Þ•Ç^¾ÿ}ïŸü­ßγëOç¶¢«xbУH{åþ~®æ?Í-7ÏðˆÏ=¼z"®‡\ñݱŸžãw |ªÎAãþõ_Ê‚|Ú÷âË?ƒ{õ_à >wÞywx{ž~4·=Â=ø÷?øäæ¶›ÿéWþi¾Ÿp ã´Ïnà¤åIêúüzq²é¨íäÄà™øý¾÷¾g|ⓟâ$aßqê©oßüæ5ãÎçvŸÛo¿½þq:<Î=‘1ç~!ù¿ù¯ÿ‹qÍ5ßâñ«‡“N:‘«ÿwo\ ·Ý<>ð÷ûÉßJÎýbñ•W^ɧ '÷r;•õ±Í/ðiÄì°ô“]è˜Ùé:G£CÞ1QÔñ ½c 6ö³½Ÿ!@ÅyîXLQ¨@s¬F>8S†MƒͬwYbÀv$Ö@åÕ)cÐ1îHWI À®Ë‘ëZ¥@„Âó\ÇKç†vÔˉ"Êù!ÈZkâ4,žòÚÅâN¿§î<2ÈÇ Ù &{ÐÔîa×(%ï&è&?Ú5ŸbŠ&Sv·1­/5_2ÆG¹ÄO#½È³ùV@½äÿoêÛ*%bµš8Œu ˆå‘¶Üoå˜Eìjhmƒ³òUV–›OÄãµÉ¨~‹b l­·ÄPpm'/¶$SÜÏö ¾º‚ æD?«ë!Aöç騃³M˜y°E^Q\dl,uHÁ–¹n’Ø FƒðÒ—3¤CÛâüIÿè0ÿëdEMÛŠ'ª%Ï6°ñCó6Äô0ë×ÂļØV&ÇñY#¥…‹€¹UzõŸ±8žýÓ7¹ê›(•†ç±TÇÓr¶4[¾2gµ‘àÍKÇVPM*RæbÙ6v1'Ú&¾½Ï9罿š?‘\Bñ 0ƒ°ž`¦@d¨Ï~Ù$£ ” U‘Ëâ&N›ðW]ç;q29!·@G7æLZäI&ÕÖ qi©£&Mt]ˆMjšrÊòßd{€J[™I_uš)¦Î?;ЭÈCÕvÌ4Þu–´øNG *å¨L)F“Á‡ò¯GlS·õ®)³W­ã¼ïâî»Ø/RýÒ7@ÃW~JÓ6_ñD‰bM¹´ NÕÉicúÂÖ~ò-ßóž³ÆqÇ3.ùÚãþ{y~ùû±£uÀ‡ªö_ŽúÙN?Í<Õa,Ø÷êP¢ªo¼6ùù3€ úð++|”•ŸùÍ0IÏ4âîTÁ”3*K­þ:1,ú_¿Í …ͳt«™RÆ£ô–Í 4)qˆ­1k^]ëû¸·Ù¨9Ýfä•)Ù¹²í˜1GÑ.[ãÚô­JÝäSÁÄ Mv­!¿M/žÑv'^;PtÙ¯}ænŽ›ô•a) ·½E+ÏáO?ÀTW;üiÚdhSe]fªi0Ó/f®Þ+žý8åGµÍNäkWcK&¾G³lûŒð@âKç…Òñ‘7ÇF ‚@?Èà\*#®äËrç¡JǸÔõ=[ÞR×¾þûG}-ùÊ+/Œ½wB³ò"7qÈ­(ߺîxwæÖO .äñ”ŸûÂ…|yõãÖÛnÏ‹|ò‰¹Jþ¥/_4®â ø%N ¼uåÛ·Ü2vƒñ,¿®{Ã7×ô¸–[fvîÜ{œpüñ\ï_½ø’ñ{ø'üRñqãñ'çñ˜·Œ<&ôÈ#Gð˜ÏÝ”/¾ú ï¹›gôßpWòy|çk_{2î¾2¾ôå¯ä6$¿°û;îäS‚‡Æ]<^Óöþûî‡ýgÇõà¿öø£ÆMødŒ'ð©€' W\yÕ¸üŠ«ÆCÜ“>íÆŽ_<ö÷ üÂí.ž½ï8ôQ¡û¿Ÿ&¨wñ×¾6~û÷þÝxÃëNÎ ‰'~Z¡Må½ÍÈOöpòp·úø%èÃ9ø¿›[¾ü•¯’»ÛƘ¼ø[Çc{§ùøêÅãÓ¿÷GãuäÔOü®ÃNòïþǵn«7üñ]gx;ù„€Yž~µgïÒßYŸìw_0€a8N½vìàè¨ê(qñç\Ê¥e°ÅOÝ)šfHåÅœW‰üwðFAŽO°t[[ø1תI -è©^ÿ]ºF»?ÍØÖ/þŒ[ÁìG… U»…RßËùs‚D§[mJ÷]CÖ,ÎËžk‹q8¶Œ%Òqj›°´gŒ™Ÿn]P"ǦI«ßÓJdcWÕ8‡3Ÿ¡ 6•ÄÖÚ÷Ø®†y­`ü3Ó–ž«|X- Mn 3Äé¿&gN£†Œ˜vš1ñ— ‚x·b%Дã¥_YÇÙ†—­5µû¾¶¶Œ3¯àG c¤ÖŠá±aŽg´¡¼îø·”©«sî™gŸÇ{Äxç»Îwßu߸ø¢«ùþþèÐ!æF;‰ ôõw³ º>ñBNxKlÉ«ã(Ícµ²ƒ™(¦ÂZƒ;^PÂïâ(%¶ï¨!ßœ•¿ö¹ʾA™hºÕo|žyZý q ›‹af|@ˉqx¥;_ÄJ Ð$[ÿÔïÚ@9Ó¦¢ü·>Û‹áüÐ~«·Æ¡ŠÉ±ºt\‡ç”ÑöŽ$Bt„=\g&3Ÿ0ÊSNMY•i¤ 81¶5œé4‘%TXP“è=ñyÅ"‰.Ñl œÌs¶*ålÉhЖ%:i­¶«ÛA¬ª® hà¶"£Úd#¿éøH>'ƒþÇNÞ#˜ñ–{@µ¦gI™´D$¦)üˆ1ªø†Žo9Óf&<¡,É’`)«1;ÞHRW†ªõí6%é‹Oøö•*¶-[†© [FÚs¥-D}e‡ ^À¤A 6 3Nsk÷6Ï*å­;ÇÕ2]Ddà›3‹àßË'–/^^쎉c¢âG•ê­ïªC›rµEݺþ} ǘƒ!‘¼BTws-¯Ðùœ±¨$j›R_«_Ptr!˜6µ7u²#…–…@ØS›­¹C0¹§LUõXþ„ §³ÌÊÂAŒ2£‡'ŒÒoâÌ" Δ©Ô˦Vã; y|…‘>FÅWÅÜôS-ñTtš³ +©O dg¡oÈdcb®¤wÀ𵋻FÔ»65î•ËÌãè×wcZ~H1‹Õ«¿]—‘ºéù™½âÉÔ‡® 袴Ä0Q•™¨±QžTdÕQ•J.§H6~zÔÛnþÍ'>A¯¬ïâ˽>‚sÝ~ò‰OþNž¤ãŽØûÔýUÚ9h¾qdÊøoñ$Oàd@ÚoüæoÇ‚uoÓ9á¸ã‚§Üëé÷ Þó®óse=?R5ûA Ä¿pá—Ço~êwrÒ¡Ú¸ö†›é¯½âßeW~3?f\α+¯¾&öýÑ/å?õ;/Û’a>I80WØìÃgýàÛ‚iÜøãÏüirñ}òÓñßã<ùÄã3¿Á­<ûóÃZ~Úrç]÷ðŠç¸uj'9ûæ$ꋾ–Ç”týòäÂï-üŸ¿ù[Ñó ÀÞru2Ÿ¸O¼š[«üb¯ßyx žã&Ýi›ô#Gö°sƱPZŽŒÏ>¶·3¿°?Žî×z•«¹âÉ ¸˜Ut}I=ZX!¿ÎÿŒHäSœ«Úg‚ˆ©¼óG{­C,0RŽ9'„N¡…¿ö’¾ó`¨O×CR9U±ßӢͶŸùQQ×¢-·³i;§7àëkbŒ? Pá?¯8h=P±L6 ^ü¯îwͦ…ƒNÖE@³†Îø5bî³Q×Z+5µ?ôÀÕQ+ëUc˜Kd_NŸëßôÛ´¶&®&@ô"‘ÇñÁ€„@\ÙìçЕ£ê ²d“ÞØ˜Q29¹¢¿s»“[¹f é1”]¸­íä’væf|¬éìßõÍ5Ï>‡ÔI¡)iÌ­Ñ´to]{:ï+c«9 s"Ybk_,nTæXz¤Q'.ŽSÄ^JÒ¨ØVÄø’Gê8”ìǾx”‰ãÁ¸%ù\± +ô h=ƒ$'' R£¿}~¬ãX0äXuÖjÕ4m‡Àòæg7•~#—âhGw§_×6±·¸ÿtÂÍXYÏÏþñE0iŠ*ýuÆCt’AO5ß m_³íhïfÁî^w®¨v/è6‚uÞÿîoÿƒ.T›“Øó;ñ:!ï·~ëï·në\!â FÓ¿ô£o~Æ tãRÏ|þÃßù­ïʈçÓwÿô¥ùç_ýëÓRèÇâ㔲?á—z}úïöâùžÜLŒ¹ñÂùW±çò½Éò‚;û|Úa½ý>¯xnž¸|‚ÿð˃äŸ>û•¤ïñÔÿ·ÑÓ¦zÚ56å~õWþvÞиù» ?äAŒÇ/A›ÆßŸEΛû¿ËŸ&½±¼çÃO=ŒÇïþ/{ß ˜"ê«1øÓ×Þ8*Õ?¨ãhãp´ÍkÚ @¦œk Õºc¾C·ßEs'8©P¬õì!wðL“oׯrâXÙ£.ì»UÏbòHï†;.(à6ŽwÚqN´yD¤.xžl#!àqµ®Œ35ÍÆ$]õć7?Ò¤=_mlN Ô šŸ¹„ÌVÕªÙRÝÖ ó6ÊHÉØ·±°ñÇÏöÇ qLžd”p+vsu;_‰ï»¡r#×úM/»ØòÕ˜#ä¸ÚE·ƒm>¤¹yABÏH‰Òã”Êäûtžñ5y¥gϱ(ÝÑþÅï ùûh•2btÐ_´sI;³ìPÄ1ÊÕ‰b´GŸ~×+úHÁØj£øÎ ¾GoÝ(‡w,ÔÓ77›WOÜ.ú£\!°gzblÐU2}$ê¤/¸ü–‡¤ð!$§¤JAGoóQÍIÐJ, iÍ7gžôq'5;Uñ@ç "”é ³‘7Oùú€çcŒiYº<ÿÖ>ðdƒÉqcª°ã2º¶Ì˾ҴzT×µÀÚT¿Äž/ÔG@Ú`nr>âJDv›FT¹µ' •¿Ï‚Ñ'<h±˜L:D‘þê6‡;±¦XŠpªT'Ûà•ÜúøVÆ@Ä‹O{;IŸ"Ü|P´€·@éK( \½2,Mì ½³Œ8vWEI4©T/mPŒã«¬C÷˜Ë°-¼!r?H¾ì*½íùË=pB˜ xã14ß&½¿ "òáU,ä?ìbWT0³¤î±”kßžŒà‰ÙšCÄÐ ž At¨€¸A(Õà‰²¼ær¼™9<üPf©4E@ã«>{‰ìˆGLßÔàN9*HŸˆR*=ª4î…q¿ ƒ@ÁAWfÎëopÍ„±6.×·#¦|2:tëÔqÐaŠ&×}:묆k DÃTÖwwÚгѸ“'â÷¯6ÄÌ?½ç­ªî¨E«¼^ÆKÔ¹w\ï¯dœù )wüÛÙÖ‹z{å²fRž1³ê^=ínCÐúÇÅ\ÌÏ}ù 3ŸÅ´Ý<¤–ŸER{ÒÝéó½Ð¡©¶ù©Rf8´;¸*#gLõ¡²¦óÌUqD„× À¡Ì¡á\×NHIé²1 Z•ªœÈÀPaóAN4ý5Bag 9õÊ?*PMÛ7)zÌOêA³oyßÚ¸€õ‚¾9óè9y\äãÃSŸ±ë‰µ­s¡•§KÈÿ<<éñ¶?üoô`‚Ëøè'^`ûKµßôéJ1»Åò•êmþöêµü›‡¸Èÿóþò‘˜wÓžÿÙxŸ|ý—Øœl7¿ÃÉË Æ¿$´ y0oŒ6þÊ||Cï@|ãà ÏÚnÐÁt›Ô³¶{›{Î…8$]b®H«6˜ ã Ý-yµ«ÞÎÃÖ÷ýXÓ«Ÿr§s`˜}Äé¾úúðm ß㓘íèw£w£RÔïÌè=*ðgƒ^ÊÒšÕóÙx‹Õ§ÚEQ˜;§`Ãàëokôá~¶¨Ýƒ}SäyÑS¡FuÝ&0¼7׊éø*Ž^鸲«'ñÇ͘6ÓÙhqÀ_÷5€ 6„œ×b¹ó`662ËKsÆÖÁ“JúéÚ¸8-åÊC×·rhðÅŒ}|ê"˜ã½&蟴ê«?ˆÞ\¹öá.›nËw#Ô”:òÆ·ö¹†kå—‰ÕàD•7cÝ8)e^ýÚËsbë÷Ð8œ ¿Ä´Í:k7¸žïé‹{tõ[Ë›[boÛ: § £EGßÑãÇn>,~ò!š_ÅU:|ŽŽgzÝ!éêÊçl[³õ tʱþ߸-Þs8j6b®†<ÐÓS{yoå2—7åõOCØÔDRuÃpwo°®'87žçßt¼º"nãÒô1L"“fš·©Ó?ÉIžÀ¼j‡zŒ@ð"Í”²A ¸éyê¦6=…p±;Q:@ “î~Ñì__»‰‘³³W bpÒõ#pªn~m æEûäÙùvLúe˜Nºü.<…¡¿{*æ œ<œXËºŠ¢m7ùÉÌç© BM$ëèƒíjñ;Ѻ89<Ÿs%ÿ,Rƒ.á™»}Ï»‹|”Õ?6+˜“´TF€<ï»ëˆC¸²Ì‚cnBÈx:è®”êÈ57‰ a×M_ÎPäÞó”Q“RÀvc~è´¨ùbMñª§=t÷Ñ'ØŽ4ÌV^«L5ØØ=–Âqµ§®z`€0925:6·ÖfžnMˆ›‡0‚˜)ÚÌ õ0/ÊI(g> (´Ä2RiX¬ñŠM€-‘ìÎ6†ù˜‚nûhM.ù›·B|¤„Ü< ±\Μ¸³Õ ø18|»¾õv{²ìÉÆ ÃѦï¼³ !ö:qå¯;󤯾^GÕ­?^Éf#"rêÝÎÞŒQ™íg6%1‘×›°‹[Í Ê¡oÛ…Mì8JíÓY´7žæ‹‡ëÇݪw4È~‰xj¸>±7CWéíøîOÉxçÓ!ñÂY¼ã}£mBïööˆ¿Ä׉Ê˶1û¤Ü¯àÚ7}º`÷ø†IoXï1ˆã×}üªÍ»åÞ—_ñ<]8ŒîBõ¾ûéÛ6Nÿ!?oÅò¢ÏÒ·û— ý¬­Q\+ 9²Oyoßa7&…–;ÛnÔŠ&(Žê£,ˆa_c«5×ú«õ÷¶WoâgK×D¶ãÎgûžKüBv•º~ÉÏ?t‘I7©aV£Èg–c_{€_¼ï9o<ž³Ý:]cÞÙ)f}iS@¢¾D:ô’wÛˆÐ4þnîõu‰ Bd»ÃTy'‚l–Ãß‘¹3vj¹ÜsM M‡ º “$]»ß<´ÄAŒsøsbú*ª¯o~¤sv¨Gúðëá }­¥\Šã(è_Èå[M1rž§ã"“žªÝÌæhæ]þp,ŽbBÖõ±¯¹)xTŒÙm¨fÛq¶ïú'’ñåÿµ ÿ¡0ç¶°®••Gö ~v_ö7ªÒ4ßD¡]爣¶k¯óÀw7l2ø9ŠôUÒ» u—÷ÖÀÊmº©KŽV’ʤѕ;%>Wáš“ÜT2ÅU-Ýü)_çw{š0Z7(öærÞ4ݱj˜r¾èLã-Çæ‹7Lftw¹Y×7ŽÎ¦*çþq,‘%bÉüPQqNµÜÁ7ÈýYª¡_ÿLÓ’²E±HÆï¶è59îÇ—åGÿ3¬»|eI·SbgV¼3•Ø.Šcy–îÞ!ÛŬ¶ÅãÅ1»â¹¹P4ÖúŶmͪ@¯ï½SlªÝ_ÌRt›‹±ªh £äEºâ$8žˆ‹ÖˆW¼I ¯NŸ  >šàíD1œ†Wƒg«ßŠyìÀ»¾‰¯7Jçƒã ^|ýz`´-Ë ¡ðñ…f7Fò´wuèìİñ–ï À×F•fL´ÔCC¶L8¾Ö¥À:¹,¸ðµ¥d“nºjŠëQEQ1¹ö’í+ôƹ²*_ýòÂH@s¼:¡‚XÝ#k¾9¸êÏü˜yµ8ðe!h'/uôÄ69ºº°›'ÛØ'Ó;+kDh“¯G4ü3fE•Ÿ:rýTRv¬ E’u­-˜#´]x1¨íýâRuoìÖÈ*k™Ø¹ uh{_ÄSκcÜc1RÇõ`Ève ùy Ô¢å¼¼$Ö$5=SÝ´\Hw—¯@Ó5²óÓõVºÆœŽæÆY+×Ê:žD׈œýb´"G'}¸ Ð¤% m± s-Úþxn31Ž{r¼k|OD·}’NCšÁ„}tOWÙF–þÎèÆ"|äE»ÑÕs-8:ùÃNèMöã?ïf²5I˜«%}Nÿò;³×Z’ñÏ :-OÇûáÝ+é|·~õÁ—?rÞgýËž>z~CŸäi¨Ûu”t<°}íƒey½VŸÉ*Ãæ~ë¥ík c<™ÒñhgUeÔ’b»Íñ®3ê²<ÖÆÈö¢5a–}_ÙƒÚ/ߢ~N?Ï|ûB7%'¼.ÜÑ›—έ˜5l"ãƒÞi³‰ˆó˱Ìïü„†h×–âèOtëJLÐ$«÷:ëI\„ê(¤{•¸Æô,¾B…5ßÛåN4¶eáÄ¢'nÙôXƒ¥Y¾ïÆ ó˜ âór¢¢´‘¸(Yê¤Ú“–YÌT1õo= ÁuR3XñóÝN:×…«|‰ú ˜‹‘¹³%¶¬m0âkÅ=[²[ó„UùʘçpsQ4¿l!ÈVßÑèf€:û„×N ޵…åt®úË)b?~jGyÍûîFTyMø†o×±°[ûÅ„|øŠÀlÜ”êGts7EÛ+€3– ãHI)Ú {XÄҌï%ÔÖØ¡U{G­5^hÅÈØÐ÷òÝMÿz’ÏN“{’Òãs^“Këß­u Yu«ñ;mÈÓ–`»8JÒ~·|þkôï¯ÛÞÿ^h juï\qä¬ ÕÔ­#*Á&xGÜúéœßÙ9cëxL·”³ †0áx\ƒ/jÔŸ5ú]¨DF1æ‘™’*Ñï\g (!ödNp±ÅÑÉ­„r¼ÖÜÀºx²˜i¯‹ÞüA/ÿôÍ!œžúåÌÆÁØäPÂ`õaNsÑÏÈ£¢€>ž¥ë8² ×Ùq¯%myboti¾xtP´]úä ÒG_\<€£¡ž¼6å úC;̓vTÐ#·ü¿-t¶x@8úý’!N좢íËTÜœöäè.´³ƒ¸˜ÚBN·å7Ö¶m°éÚDÄÁ£.ègaÒVh['žìl_^BJ¥¼ÂLëøÿæ,$—LzøG^üdIamCß¶1äA¼ü™ÌDã_º`©‹ÚàôžpÄÑüq¾h‰ yaòþÜ@¬‚RV %Ev¨tv3žþçYXÖ€}ì$îâ@`» yÃRGÈ´–^·Èš×¤G}u» “þëX7Na§ÂD좳ÉÙâì²€Ž^ž¬X{Í‘a«¾íD†¢c³“ ²ø ]/|*gß_¤Ü…šŒ}s2_`[©t碌/ï±—Gr•éüT;ÊYà)“Jšüºh¶]¯<5*¤ž¾¤“/bml5´æáëx¾<£´Âд—{Bæ»C§,?Òf­\Šcïö¿ÐØ8[ñmÖ ótuºqmìÿ =2««jb篘̋s´†|úØ:¸IJUÉBÊOÓ¼„Ð (C1 [û×–}Ú«ÁÍE«Z#™gg]F’ã̈öå+ ®Çùâ’¤o9 ·þ&Mˆ¿AÓž¬ôØÍ¾çÌÎ>LA²$®Fz⯌J[ƒ°À>Íз+›BÄÞ9@.[FŠø–æõ|xy®‚þÍpjúl<&£¼Ë…Ôß–™ÛFÖÕ¢í¨]‘ÔX[þzìù©žG%È‹6¬ ^Ó;ª§?ëÖ¡º;‡«³œ-f-mc½Ä/e ·µVTi Øž?]'Ð>ÎqÀR9S×ö"8Àé;<-±‚DcdPÇŽúRt$9ÐëÎ I]7hO@ä,! @Éc,lœã¨é>¦ÌK²xÕ¹ÃsX‡ÇqÌÚvþ˜è-’Õ qwQdÆ¥Ž[Lxß¹_jΓDßÍäkhðÑófh£Êƒvt÷hÝvu-[ñ^»Æ o€ø%`=ÃNÞº+ œ7Ñ`fü¬¾jÂÄ"Pÿ_QacÖÒ´G)C¯Iž´ؤ‰ååŅ̃XAS±±Õ·!8Å•†‰V”TèG'Ÿ-·Ã¢A4v.ƒc¿œDNŒs¡„j²Wç”Ïh‡70$ÍM/ñÓÌД‡—}vŒÅxæÔ¶¬œÐ/ÇI?œ¶Íé²uôMÂt•iLU̇`ÜA@®Kµh" G[›–üÚmêtâ(ã¹)ŽB«[m«Ð¼Z ´\¿š°Èè¨ ÏEµ_8õ –h³¯™C¦Ü Ô_Û€ŸßÚH ùÔgºZQݺÞ&]Çô 6k¹¤£ç Gs‡¯Nc%ÈÙÒ§= ½xà&º7cÙ78òœyÖV4æƒÐôGÿÐw:g”–qüéú{ZßÅm';ó¬È¥5~„r»nß›¶Õ‘¢3Xd&¬e€ÔrJÃûÌÉüä"Fô¯^Dc Pw~ÍŸi äÀ3‡eé;6^õštœÙõ¬Ck4°…‚ó“,¸)Ú ë—Ûå½ÔѪ#扫˜ V[pïVWßštsÓ˜&µ¸ŒÙS¢õ!ûeûDœ¼¸YMñ=E=¹Þm~Ì–¶Ç€ˆ»èy¾JßA3`%ò]Z˜Zj½ƒâ»6TzxnûÓïo]ð²V¯"m.РE¯9)ßð‘К¬ëî4*Ïì™ÚDNÉ{³qé8†ž«§›ö•±Ý Ïã¹îXåêlŽ?!鬪*³X±I.ñÁøâ™D8½ì‡¾£‹”Óh1kO[†“]X¨ëæ''ÎI¿;ºTf¡¯o!o&ûV@œ#‘‹„ íÌ«<ïúH,t ,¾ŸÆ`W§ü,ãàðt–AÈAL\}ä­¨ÈM¸æ3[ È±Ù÷gƒ-åËé2ùh÷´öÈËÁžüÝy.AÃCÎl=”éBƒ¯A}>‰2Ù$u\#Ô'ô!ô‘GcÓ¦±µÒþêÌBåUYm)\nVŠ¢$eÍv²7õþÝõ]´«ÒÜ¿-µ•¢R&ZEø6Ü9‘¨Ò5ÒK;‡&JZˆLJuv2užÀ9ìc=œrf sâå/‰Ò ŒÏqº¿D)Œ~øî{r *g>øbg2”ëk¿U`98âæ°1±ï§º•N_@!JSºÍÏÕ¡:Οц&øðÃ޾gUjøX=m#”⥃±®—r¾èoôW8×ÎE,1Õ6G2ù±‹ãÒé†Ýºl‡^µ ¦vŠ/!v­¯BX#Gvp݉½ü±*"sPh,(»26c¯•3—„Ol +Js# ëÈH—àx7tUSݹQÛúÅgeÈ^òÔ•ï¶ÜÌï«Tþè(W.8>_u;åsÄã˜aZ%WS¶Äl91æ¬çšI’yç¡£ŸõÛæh6‘r °ïù#vöÿ’ ” Â¸¶Xâäª#C{õh3{ÎŒ× !Mc»5¡_ý-2]ØÒ–%ïì-»*Ñ ž@ ¾äiÕDõb£bªb£ÀÁ@WÄ(H•OË G×E_M?-Žr *äô”e»t…Ù\¼fE¾ñÓ ]z³W\mÓßO®é×Пm"¹)o¦ƒ® 4/€U­›º›hÉ›ÅK¤ø‘kæe°Û‹{ ­èé›o¶öúŠ€‹’nä«sy@nÙ‹ Íe4k„=½tJ¬hJ#eŒb.>y96ïnÖ;âéÁÛäa®:’&Ú ;·ӇsñC_òΘ.@ï8ÈÉ—ÚJ€±‹§J“R–åd9A•X,Z›P§ ìô@Ò$>eKŸ¤ÈÚоâòY -Yl ëé?€ÙÑRyzð¥\¢ bÁhµ+Ë‹\Ç\Ú±y¿€$=è“ïâ³®•“á±½¨¶æYmðFfŽùÑ1èM—oÅìbtÇÁ±ÑãtüEA -ñk œ<‡Lð¬Ó?Òí¸šÀ ÔØ[”u3BåBSsáê+´ù¦Ôæ­NÔjÍß=Ôàho]À13n¨ª÷Y,óåá :çBr†|cjðÓókƒç÷-ÀønûkÞyÉßßX=;žÌU8±%êÀûÃÛ­ã&½s"hѵÞZÓ\Ï-;«{Á²‰«‚s1êh»hê òœÀíF¥Ê¼vh=Ó÷³à—ÏWá±µá>X­³OMpb8L y‘cÐÍÙLÐÂÖïËÇI¤ØÜÇå à¨å*6ý‡­>zú/y`cH û '¾«¨&È­­b—"€#:Ò½xÚ¼=ÖëlîÏÛax޲ŸôÃÕoÞ]ûÀ±&úÄT ù‘ í÷1µË-Ÿ8_y Û}ñn ¯OYŒ¥Áž'6ÅRJ,_ †úqÿbzÌ „4ä.ÝqKºæÿ†äÍâÊ:ÃaXNñŨ6–«oÔxõÚÚΈ1Õ%ƒw0ÄQC+Uïª+Ñ×ySõS$w´‡dg[ÐâøTžWç.„Í[ßrpn0{Ó‚à°c8#[ڔǧHÚJ7>~Љz}RE^ƒt}D9_ò|{>´e;zc°ºÛX‡rð§×9ô ìú.er†,?ü#0½wÐ9)jÀ„jN•+n|´¼:Çô…uW %Γ­nûö£õ{WbMŽT«þ6Cé"‘c°ð-{é^é‚îÒ…A:&NL;HuÙVRøÈƒ¼^‡¤™¶òqì"?UðÏàO~`®Œ©HùâH%e¦[Ñ"™I­ÁEñ"Ê·§˜à Š(&vô+{­¶¨Îz¸e U;!ª i=L¡ž>E½VÇ6o1²Ekº«Šñõ'9©÷´$€ºï“T¨ØvÌyY›øû^¥ñ-¿Ë³)›¤hóÇ‹ßþü©ýƒY1#™îulûæ×´Š¥«úcLÆñG®jµ¦èX..&ž>›#碲O“ŽoÝ‹hÇ‹Ýhç>¹ó©ÑÈ`ºS§xgͪٯ@iß:Ô‡ÊÎã­e¤Ë±ACw?!|ÕŽ€þÀXnÇ–¾ueùHM Œm|°F?¼”'ë'qÃ…O ú¢‘Rì½Zè*éùKƲü"ö¥½ÿÉ9í./ÃÛ¹jþ}5GsZlb)Ê! +KÿlfÄ“"„Õ1Ufy=ã ñÙò¥ìµ×®Zâ™›:3ˆ–¨’äuÓÏ`õ;ŠË;ôï—pã@IDATü(O“wj¾ ;ß±ãþ¾FòɇÏX/–g¾Ûþ&dÀºùô“O©Æ×A·f:pôÁBU±yà¸[ïÕô]ä#³ÂAv<+Éۃ ”üµ?ףΠ(û§”ÝÚgÓuà °ú|:£ªç…؈Z³¿æÄA:XÑðKïâ†A:ŸÁ2DMæÍ}«@ÿª_yRÓ=Ú®#¢ñ¥­hyT/Å6foûôîÌßÙ&T¡ð«¼fqvi.W`´¾i÷˜JETå/¨1\‹Ñ­ ß6¢­ö`”gc“ÇKÚÖ=y‚}ŠUãÞï1)—¬ö`û.Fè¶”ÓÆÖ¼ƒ)G'ú8 šêÙXý,+ú=»yÓøŠì¶õS¿8‘,!)>¥÷$b¾wޱ» ª³=õ‚fü#m=9Òòqòæ"’Ác³ñƒï9±z*¡á)çùd2¶ŸkŠÜx’ àpŒß:^k:zaF*yÇÈò€‚nÖè¨AÌÏÚ•Å|áÀ{|‰Q[÷ã地ï¼ëLrŸ†¤Z0Æ{ì4xØ2'iôÔ„ÌÏF!#µcÑKˆ‰º·£×ÈÚU·9³HDRG<¿±Ú–µ¯F0 ÚÇ¿.`ÐtçÀ8 ŠO®voP’ašÊ{G¥¨€¡oÐ˅ňrˆ˜øM(0”Ÿ öå¯{”í¦k"u·$H<Ùi¢è‡<Œ³ì|¥Ñwv»#•*ÏH´¯I}-µí诫‘þ‡l›¦“ƒƒÛåØ.ûØ¡ßEÉz¸…¢þÚû÷•»å¼š\”dÃ]>¡t7H·Ø¼~úØ‹'x­ë°ÍÚØCŸp‘ò¬*ÏL-³ÈOÃͰä‡m Žøû>4(–ßB_dýPYeÒ³¯¼èbJ+O’˜)ûð¥(níì"nr‚À'MûvëbVN6g'ûBà“¶|™êÕà]NÌHtq –FuÀŽ÷#I—mçÔ.^ÚÆ æ’yšŸ&I›n[‡Ô®Âå% ;XC}'DDAÛŽÃ|PR ¾=9ÿ¬«¡æœÌ^t¢m Ð7÷—Ë$Œíú prá‹C¿“ÀšŠN@†J®K‘> åKoÞH4ͯããÅY'Î$Ò1·ÓÔÿr@䯫 ¯År¡ï&ÄCAC‹ý¿w¶µ`¼BNwöØÏ¼ú0]{>áâ‡?øÑ‡?ÿìOùÏ´?Åö椲 ­ñÝþ"ŽìÆÐ¯l}ï“|øÁ÷ø N@ …EÃ1·V;6ÈÖ LTÕ¾toôý^®5tiN&Û–z²Õv€ìœS0ª={ÎÙ[wG¾[“&Úïp±>òßZoô@î<ÖÆ˜î[×÷4àÿ¬ç¼KϘôýb¥ÑÏäõ‘.moZÐ%bé`´.6?‘sÁШŽöZ7Q剫9½á¥Èä‹\ØâcÇM;Ê.±^ßLHvz^ w9rÈvƒó€˜Õ|§¨MmCZY¶{O?? Y‹.±ãóÀ\Ó…tÖ·84 5æðo·55Á#›Z×òpºÑ*åŒÄH‰º^],yŵ±W kö`5ɽỏ£³é¬}³xÓ×Cdzè—]äxÍÓElv”tñÇmÍ^®*ÍØe«Ýšd­ÿO„·Žd %*râü §“K…º×¦„™™×¦ú¯X“÷ôµ ^Xó×}V`¨âø§aç^È e;¯keß?óõ ¤,eª-ØwX<Õ‘:¼õ[«Ê·]{ôwþtL[ïŸj*CVvóÊÞV°)So‹CAŸÀ6,ˆV e8èÃч@5ðÃÕâCå{Q ý© dÕ6š-.<ñEÀ€73°”sÔ¯I¯¨åCZè ¬„täòiŒV ~¹sk’dæ¼§±ÿ• eó0œž¤ÄÄ¿“ðUl4×wdº•qñËçé8<_YöÀÖ¡ï጖}É.Žn"oƒÑŠ%‚5·êÞåÀ_¡ïkCñQÑ‹rÀæ"l x‰5÷ór+ôÁg1ú”ÿÐùÉ÷¬ôLŒX|M@áXí@jºhž¿{º¢ŒîØÔ›ÐÜd ë€râŒÙBÍUÍ —rµšÀ+úê(¡ÍØaêã– xÙÑx99¡*ÕEVÝÔéÚÀ£íÓΉ>ﲇ°ôˆsý|†Ñâ;ÙÝ OÖâh3Ÿ>õÔ/)ƒÝÖ† VßMCàå¶ jÚMþcËu,o!kôÓíë椘Õ÷I©ë~3Š ?KÛ“§üt¼µ…ŠÒÖ¥ù qàÿÝLm\N(ûëE/žùY—|VØNÀÎQâXž•Q€78>¹úÔ#NþÉOþøÃ_åĆÔwÛ/N[ ‚%ˆ‹ÿO?ýðk¿üë~ô£øøSV9˜{Â=­éÍŠF:¢úÞÄ;æ}zf ¨gÅYÖ/¼J“n2Pä?(ÎAkŠ‚ÊöÉ$„ž´Ž@o}ÜœP˜óœ6M¹îµ#Ñå `së“M}Ä?çGþ êm›OÆ7ÿ,Ùú¬€¿éÿ«ç|tžfRÿÞG¹9Ë‹I_22šÈmÊRAi)×qkçEMô䉧+élÚÌOv猒öœErK3’b¤R{7V¯s›—kˆ65Åÿ»~ÖµÎÊÆò³|´ŽX£±4c®ºqa±Ì,}ãÌ×ÚÇït!¤“« ú­7úm›ƒ«L_Ý”êk}|!†¨ë¯X»K²ºÊ,ã¦[ûƸœsª¡ö¿ÿ=®>éO(„g#-ê‹/ÞÛ6æ@=w¨sÎ Êßmã3ÏÍtÂ;—hî^ó8ìkÓsŒþÖ­Í›Ø0<_u­‰M¿²m|Ùаq ªGø·ŒCŽ…:á)ø‰SãÊ×zP8‰F°``«1Âñà:B®È÷ýf‹<@@8Y íZã[Z›ªâšG½òÁâB‘Ƨ]¬ÁÌ='ƒ¦exÍ™Ä=…íï: 4Ã8)‘-²4û‹ž¥mÉÍÉñp^%KrF›¹ ®4ö]0Òv`¥ åN#4O1§ÏÎ>õûèUu¶Í-ýÓ¢Øð‚ðùetݳ8ªV᳋'/îÌ#þlÏîWü§ÛÏöÙ‡ÿù§_~ø£?þ£Ÿ}ùç|µ„±7„3‹Î±/>ïï¶ÿ÷ØÌÁŽ5tÆù ÖîòÔÿïþÚo0öŸ}ø³Ÿü÷êÌY°_äNœz°ÊΆnS…n7ð:—ZƒYM«}ZÔoë.²®uŸPß^3·æ4×Ö®†+t —š²žÔ¥ÛE»s¤Z>sçØVÀú¹l pq:G©2ü8Kº¤;|ëPœˆÖº‹Ê¹Ž×`¯=HÈ¡ŒÛमæÅXOŠmµ+–7Æ/)Úšªc$ì²=_±Ê€8ØüØ¿nŽ&¾µ¦ëÚ(P)ÙÞ@)4Û&í4H×޸„ AýÌÛja}e2rüw­HÚßÚh|‰OžÉttíØºð ºò¿Ç&«—ÅqÖŒÔØå3Ç¡Îæ¬³ÖËD/½µj @Ùp]£´:h,§þÊ,çôõB£{þMNp?åFøÿëÿøð»¿ûg¼ÏŸ”Í/í8¾Q´9ÜbÔ)7Ž6«q×¼ÜW{8…âÜô*T\Ör¶ÇóúcvL”)ýj<ö³ªì‰yî°OX]t­Ê„ôÉXÂ! ÛÐOôð'6މºs”šôÃk¿Œ=:ͳâöžŸ* &W.Y#4Ý´1p;am<¤ÿáúµYþ =·#¿èº{• ãɰò*:öi¿ñ*.„”Û@1 Ê¥!‘w ØQUÜ&ë û ]ôŠä“®¦@ÆÄ»†:Èâ-¨¯Ay:‚€ÉÓï†K›'ÁËQäîäº`Š;â­ˆh)Ç£¶7¡œ@Êh Þñaú`+¯»`(Ÿ½Ë»ÛÌ*òb“™pu5®4Úæ}i‘ðïÈK73ˆ%·±‚ºŸôµ•ÿД3Î.ú'ýÖ?Êæ'-$ÄÉñÿ“ôá7~óï|øÁ~HÌ­ÖÜŒ‚-<}Ó7÷“¹áDy“KìMî ¥u£|•ñE|átôÙžï«i“~BÐb±[r`^¼ù™m„š€t6ÆQæZöõX¹ ±7£ÐO=ý,¯y|HÕ­HŽ­ª7ŽhIK‹qx“½üÌÕ92Œ·œ(/ˆük‰kô ×îl]O@êÿ‘ ‰óÇ!_œ—Ü‹~ó7¤a+gþ¬CZ8Ñ”ºÛ°§wéyŒHq#xe^3Îù(u£2,)wÎåÄUñŒ´H†2öË¿p€ÈoÕDv¾^ø,­#¤ÿØé‹/¿øðùOúáÏ~ú§>ÿüsn°?ï¢Rì[ƒ¶¿Ûþz2Ðèœô+ßÿþxÚù}žúÿRkŸkb_ÿysç¯ÕóÞVd3ì0žÚ~Íe*¯¶Ë¶:\û…i«š À‡ ï³ÖLs4«R–‡‹퀎&Å ·µóWæD6ÃÿšSÃí}îõÏ¥eulqlîôK6»=Õ£SÿÉT2»ñ@¾¸ê °X¼Ãt»E‘U}WDûÚeú1K#7qÄ'(~Šê]©ƒ(ô=Y± ´ñ°`¼p¼™1Æ!2<²ÍqúgÿüŸ ôÝö]¾ËÀÿå 8SöùÏ>|ñ…o? âIœÍ}3šFSûhûçl­òT~ß. ´­!ïÌӞ鿨û&úóF}ój~î_áÆã;ÐÏÿ2ߎïòßè ñí¾ ï´Ó~‘\WYÿ¸ðiç÷¾÷½Ž×öwÇï2ð]Þ2ÀŽsÅIåS)½†‚âU‹Ç]æ0©º@ÝÚà‹×µšr®÷šÆ–×-ºî’µk¯÷ºÒƒ§jÔsÝÒÃLD»¾zÓÝ'Î/Y%òÕë§¼Ø^¯õ¹¯®‚í:ÜŹ¾`ÃkÙœÊq¬xÝ V]®¥lûßˊžAè§2즦åÓáàõ–ë™—bÝÜц”íµ¼v<˜´ü`$ ”¤Ö¯¬€MˆáV H~:â7-v÷ñ(Ο43XÞí +œÿ\À'ð}¥G«]¨3 " ñ*’ˆv®oðSgWuÎ4k_9’ŠŠp=¤©®ѨV0 Øó g èJ¹Þ~ø“¿ú*bOY»ûÀ‚ñõä3<õ,Š=¯ •—nnCŒÇ‹7~'+.jÉ]ݼ‚ñ’¥åŒk!Œ®$ Þð˜ív¥42dHÙô+Ä“s¬Ô‡qqÃ)»ù0ñȯ¯aLú+>öþå_ù[~ÿ÷ÿý‡Ÿr·ÿ%_YÀü6]bËçŒOwŽŒ—óŽmŒ¦Ú…¸R¯#œ+ÐÑ[F<òn\Åå Cï†Êݾiãà>Ì"}ùþr„€Éc³ÜÂÈ »:ã%p쯭ïdwLRŒôÞiO‡Ž9ç9…“««$è¡OçøŸvøj'4‘³—®ý7#/:\®”y=0/óCЪõ4;oãÙ¸_”Ó?rÊ<$pÁ k“‰ïíKŒÆî÷Ö.~e3uñõÏÚ¦BÞdg9Aš0´›ÿ§=*:1Ž_¶Ãã© Õƒ>ì:ñ¯ìG‰låÿŒÝ(ìQÄÍ&Á¼¿çÀ»¡+<•»ÏvPîQ&x³šgLæÙºî Aµ—ê«õNUö¯ÞÔs;qÝä_ò˜°!”KpÜôbÖ.õåÙ‹òøóîâeÿe´Ë{?^fòój_,dôÍR.—åï%ö$íÁDv#.²ë­Ù<»üΑÑÞ·÷*"|··Ô±¤Ý=†è(þ蜾Ä+œüDBNvr‰\´·NMH#&án\ŽÄÉe¯¶4ù!I~¶÷È!^Ûo|i[GÍþ©jJÁãÈ ?šÑÖ~Ï£zñE›1lsëõجŒJÓÉØ;-òŒ>kßùøw11 Y4îæ+üxD™oåL›¹©^ßEU¾v£Ó Òhß·Û›²ûgMLlz5aZ ŸðuÉÿøþ× ?êÁ²ë˜êÍc(…·.wiíÊB¶O ¸Pñ:°ˆ<>ÒXB¯«軰ݸ'^ùÕí Ú\ãÉ®2}ûÖFWO./o* }¯-s«‘ñÅ ôæJ r]‹M¯³¾1L^W"çuÉݪÙlAó™R•G–¤,Ö«ˆØÅ6$Í»·›1ÌQ{£]Î Ü|ù öí©ê¥w:[šlÇhO§mâÕAôqT§ö5°×ÕÞŜԴž“YP²„jÑwäмÆÕêݹŽG%ØÂð+}Zp Q‡Ôo½Q‚›eÈöM;Y:GUXé]L.!AJSçÊ•.®»ñHwè·ÎûåDÁp§kn-“ãbÚ†<‰“Oo®ú=ˆpz%£5øÇ\.`\  _ ²6=‹ šŽ;.“µ€SDKÅ&­í9ü5{ÿÃïýÞ¿ûð/ÿÅ¿ã†_ñv—‹ï Ⱦú/ Žñò‰ß¿òÓ#£è_Üå⃈»Õ ã´ÿ¥“Fp’mM =z¹À'… Dy‹Ì§òZàédkäùåsu2*&~¨ŽŒý9¦üôu‹>£·Å„qдØäÇq¶fòº§ùÇ>œ¾«§¹‚N!úÑ\ Ñé–Àøˆ¯(°ÅÃxùXS§4ÁÁ¥ ² æ›óPsÓï4Ä·´ÓXè|ÖXÔ‘î/œî»·™+NãåFF!dª@ú-ÎøEÖ aO'ͳq ìWYÏrežñË鯺 –Žxn;Ö¹ Õv›9÷-¦É‘qÄ륭V.®cJft V#G[ßïöþiWŸ`¸6ÞסbÔ¾@"ÕÜÐ)Žpõ;cÅØ/>ËsÒ—‡N‹ux'Nt›C`ûÅðNxæ´ÅåÓ4ÿü‚è;-õã´}s™ú:Œyó¤æéÒÚòĦ‹{X`.é0Ê¢ß?&QJÙ Á?¹´6ô×ïT·³8bk'¯ ËÖ‰ ^sWÿ ï#íû»ê£+ž*úE.üýõ‡"¨¹¡'/ãÐÄr#[>4ö>ò·­É¾›¯¾¶g¿—4©U™þà#zbWSè”g «slŠ?%Õ·F¹&iÞ­Äyw~7É|‹[âÜñ×åŬOlì§AK^æÙˆ§lçûÖûûé: .ã·u =Æ«§š_À3 6}ÿ‹ì0¸O·©©;×ü…Ö¾Ú€ì]»N玳sÇ?Êa.ÍÓW}¾Æ–]ùæŠj#ç^‚wÇÍø—üâ嘕ÇìöÃ×sl¦;6dÕqÄ7JöüâÇìWãòú.=º@‹Þ¹G |ÓkÃÑÛ8Ì®êjm0_*Þ1~·¥ôë‘£qjØ…/ÍÌO×ïÀ3FÅá‹_4*Z³Ö8á´ðÐÄ Ç<Kck)8Èû—dÌÇ6æpìç×Éãl-fW…šÏ0Ôlý‚æŸ ­–t)9™ú|r±5‘9 Ív/ãQ޾¾¹öÿê¯ýøÃü£ÖŒ‚ÙÓªøêæ°1ã«¶ÇÃ+XÖ™y…‘^ò…´6è7ú­?Ž]´“ºŽó °H6pŸÅ·X“c³ª°q9~üÊâjZ*´Ö6ø¢¨¯Üråè\+úãvÝî§ócf¡Ã!§…FÀ“^ŽHf9 à (7ŸõͼOCÝ´Ó””^Gqý“‰æ%hŸ¦B„9¡6 ôW_}C¦“¾t• OT{Ø$2"éLâÅR±NYgʳ¸iØ@³¾ “>i)ãè-.m´éÆ,·Y±­5üê`R¿,¶N´úoð‘M™{GØ M5f‰FÈ©åd½Ã¤šXÜ4ÛŽ%¸Š³cR€æµQ·¡9 YNªê[E“ ×V'$aš3ÛbÝÜ@sõzíÂ%N·`Á/×E´ × fJÀ‰G®€¬Àû¥ÿðÃù$ÀIàÉønJ悜q‘(OÅuGH)éú¨ [c¨Ÿ.Oáfjµ’<_ŽéöÖŒ”Åâb+¦yØbpbŸó@À,žY1 µ¬…Dç£Ø£_8dGË—u{â¦ÿ O´í{k¤ÁíÔ«õœ?#¶ßN©}Ò*vºxÒoTô£ŸŒ?/Çår…Óïs–˜üd<]*‡¼p+˜(=¹åHÄùÒñø qó™äÀp®©â_.Çûü b= æg,âOJ‰ üM1q!g|J/Jëg½áQ^j±¡tÞ‹©–qÒTn'–wiHyÁ8XôéBca äÅM_/ôºúTMõ U%ÇK›;ï!ÓØNžž9‰wN|uª`ÞËyƇı;œ&7çC®¨à&É6ïü®9’¶náõoá8~àӘˬ~#$íVð徸΃À l-y+b)ýÔºÃ%½†´ä‚f§ûI^“ºéšÓ….½û}Weï×X%óQ÷´GLý=lºwkN4Ö¦j6­èy™{½UD^²¶«»Úrà”¨'·\ª¿‰«lz9v° ÛÞµÏ]ÐY4èG>Wo³µs¡u ÿ ƒ ðÇ6]Î/]O_—/þºó%ùÈ©²|ê¯zY_œpïyws+ýól.ÑñGÌjOœÙGĘøšoqå•uCŽÍYߎ­Ÿ0½®­ˆl·ÎìkRúvL•*TÅi)É ›Ü¡.í”Ê×u ÍŸ°‘Ñ^7NÑÇÓÚ®m€G[Ô]BÚó<§óú Jze…~”ä[K‘Öž3Å k»îfÖÑë•Oëöà_Ÿ4uì‰àö¬S´M{õgÛLWc ]?ikAw¢É#.Ùáʶoo¬¼aéaËé·F¢¿µcò ÇW6 îØP¶^¼ ,÷‹QœšyEyg/Í&á¤Í¢’ƒ›dçÄÐ5âð«›“£Õ5Xw‚¸ö--týd{k˜4!Ûh$ V7ÇПå!9—ËÆdÂsWû' Tö­%­asýÚÌ»£\þ«Q¯<)«—wüã ]þIˆ˜ÙÆH“׋ˆ€ÜoS/Ûî pœìæìdûºNµuÐAyYxZƒY€zû1 ¿a–àħsÕíå2!v#ÁO¦Äº`6Û ÝÏ;ÃØd@ÿÄT=ÀM¬²»ÈœïikGzž…ÉøäFMÚ-²I±c[ŠT@“ÚÁêT ñ˜9»Ø´µMVÐms0N³#-0«_ñOÔMd]Â*¥¢®4 éIà”+aþ{üÙy©-òE›»`ÒÇ’>³¦º‰tm#˜’VUL›áL7?ÒÛ ¾Y–Põ?|à&…‰5bµ·'qÕu‚ƒÓ,gçõ‹cbdY@Z·/ Ñf{¯6åýrt³#’^ì+ªD1ˆ¥Dáâ!g]øæÇZ °»µÑ&œ=¤øºÿ0‰má­J;ÏÉ‹3°y»7‘Šì‰xÒ[óëñY—=µ[d†n991—ô4Zíé‡}êº46×&å¶+v7SÊŸ1(³=²'¨­}zE—3ç¾ô(b4§¦ztáê›ßƒÍ_Vm»šCY-kÎ-=PtÙ¶¡Ô¸ ŽÞ]Ia¾iHòQ–óN4ÊÜ„ óu+׿ ~†"¿ŸE'NމɦŒÍ¯½hW‰ÎæG×EíB¼ë­Vù²™ä5Pa© ÏzÕ÷º×6Ÿ³±XÅÆ$ñj¤‹ùwœZO´—Èš*fÛ*ï€`k¾Iß üÍÖé©“_Œ‡MÚ_â{3Üb±*5ÝÒÛåÜ®öEVþKkåôsPN×9õóa±)§~¾Þ™ê†gµ ÇVwñIäö8`ØsHݸØÔ*×|ÚŠ$“-)ÓOwœËúéXëHî¼²èñbI,ŒÉ»7H%&ï'æÆvk`qBóŒÛ¾|ˆÔ_™Aß¶?ÝVø‘]zèzþº~drÊŒ¾\#X^‘G©ØŠ\:þ àÆÑÿƒR9¸ÅÞŸƒ‡™å› ,bã!yx´ÜI_«=Xyy}eåµ·ÕZ+N×yõ, Žû4ZœÒIß:oÑ4û²RèðëRœÙ9 ý4'uå*s|;&‚Ó´2åUŠUµZ“<Þ©Ñ#{SåØð YèaOŒ1»ƒå$VÚ»¹sö¤9p‚¢<0‰^øyÈWÈ`G ïf×EMZq:ðhÁi¾þèK˜çâq¢ê£gü*ä ô†~κéˆgÔ}âhÒ©‡ ²/½ù vØkLõE"nSâx›£µ<ä3~•É´¯œyéo5Žþóc8’£ãÍŸÿZÕ D³ó&dÝé÷©ÿü&"ž'zÀ¦Mî'MÅŽ šÑõ¶:ÀÛ¬V³tãE–J_û©ì¾t”P²“àòiÛª´Ž|,«)dãÛ[¾›ƒâO‡Y+w„š4 «‹ý9ò:R-AÐ÷ã’¤hX›ëRà»°Äžƒ|Þ („6åä.÷Ôôà#+·=ùož;PoṴ́Å6Ç{k_Vp¸“¿ë!¯­cˆ|å˜VI2a,^ÿ´£HñdÁÅ2¼üØo]R7 $àuA1¡t÷A˜§àùqÈ[lüĽù‘îIK«ÍwmlÀŽ7õ溇°ŠQé ð‡Ä9„Õ)|5¸Ýø!~÷µÇÂ6$ó~Ÿ.Sy³žrÙ¹±Îøk‹ ?Ù¡:çG·5Õüƒïlüê^àÂ7­w›¾¹ ÇZcmëC>Ñ”¥-sÛe‘O„ú«]­‰Õ| qÀ=ùÕºÚ7öÍÕWÍ9Îb‹Ë…^9Æyà¡ }‹Á.¯À9DßzlÎh4×yøãñWµ Ì£©Ï/ó¯ ±zœþóäSj¾aÕÅ¢€\}逑öÅ;ÇØ1òF¿‹XMLã4.Ö¥^_L 6ºØÚgÃJìülNÍF°— ¨•;Ôî|ˆ§råÛܰ¹¯E¿¨}ðtddxƒ%_[ŤÕp±˜P¡õ !ðæh‹nø×ž²´¡9èE©ïZ†ä×fW#PJ8ý&½É×ÖÁSmkùl¦§Íìñp¬ {£¢¾²Š¸?MkYB:þ8Æ£ol¦;Ÿ§9'‚JÝ<ù²¨Ì‡DØÑ_;ЩK£•YŒun%桪2´“¥ðTl¼‘äF'UMéGã8à©X–xw,iB2®¬ lŽÊ‡æ.aëÚœEN}…-PIbóº²è¡ã⦤Œ08Ún> SÞ3˜m&/ ë_›zê ¥6~¬É­û6àm3bò« B… ËÔ_œ”'ÇÔP“·ÒnYòd"IÇ|³Q—º žÐpÊbFÊ…šä,X¤„Wý›œìÈѤ‚ŸÍÄ“½æÙÎññ6(³»ÔEüòu’Ÿñ™ÆøŠ,sÎÒ¼Éïúß|T0ZÆ'Z oŒO± Ф¯s(6˜B”§â7^}—}‡åD’9(VÚ7Ýrþ±K×|‰•2ã0t˸"+s†Ù\ƒn´}—SÛ‚¿PÝ¥ª/ }÷»UãšL„¥J”‘oÐàmüfsÝëE"îÑ56ƒLGim-Fqh™?MYí5­ò.-Ý9ÕEBE¨þx5P2&m•"x}mõýô¥–5éø[“Ç : ˆ7J³©E›qÝÎavb,WâvêEð£ss\îÄ5p;)•hëkcb#_Ë£Tíû¢uyåâøoµ· ¦>#{R‚1ã{sVËð÷´Ã`ôåÊìPqý]ô ÷aUÞØ•wŽùG'¿óçh—$Úv‘õ¸§EëfAz¬’RNÄS¥üptJ·\*í¦¢lÞÖ…R-äˆ×(ñ¡{ãQ;<øºè…^£!œ¹Ó²¾ÚF ¼ÚOQÝUkÉ¢Â_~xÅ-ŽdiµîɰÆ2¿= ’sfmCvãØÜÑn‰F³>¥tžÍ2„Êhð YöU¥æ›k_ƒ¼Ù8*Ÿ YŸ 6'6&ÚÞÌÜ‹Å;7˜#ÛéÃG°uÿø϶Ra(¹yv<ØØHVØ`æ¬ßMGã9öt ùåG¦ lÒ3—R¢ŠËf.ܺ¶ôò=á·Ø‘sçÄnBES­æòÕfˆ9¥”ˆL¿2Ô`¥›´sqE믇 ˜,ûçÓ>ÿJе“ãß +„>;•‡àö}ŸÀKr, DwVïæ¤å$¯«1Vr‚Mß Ç/% cl'Ÿ^„GˆMŸ:JåÇ1nu³Œl÷ÍG}P÷<]þÔ±å¸ÎKù›7~]—_•g§£½›÷q„ž¿«»|šRl¹=9ÈqF ¦áWªŽé0N²k z9V4=i=ÖÀ!6sºÈAæØÖg7³ çÖ’¸¡rìÚãœ)\…{'sœR;¬ëhC<éúÐ5Š}Ú  Õ´ï9ø*›§®¡`;6Jºuà>£[8Ú}…ÎZ¸k„U$÷CÒ®¾¹…ªßt=؈îó44Wáæ~'T2ïÂè†g(Í0qóúR3‘šfœ¿"û—}¢—ku¶vu%CKذ.mïA×0·&Ó†o 1Ê-ÕÝ dqÞ매Z+ŒQ!í({¾"¦<œfYT¦H‰¤¹yâ7pyñw\óìa÷¹ÊñOß7'Ò€Ûæäˆ·€xîE¤›M’Î-ŒðABå1çÕæ^ºÂúã:ë<Ë èñ5”Ô,ê¤‘Ï Ž…Ð…,Þä[ñµÅ‹¬z|_»)€6ÅÙ‘',öRƒåÞBzHÆ!;>"Èta¡.Œ[ ét]UÇñ×À¾ÃhÇ –ÙÔùéÆ%ChŒm“š#â >“ýâ?»`)Yæ;á|4Sû1SxB·cíklµÂÑR,v–¦Lßld& SP£Ç{Éîf‰ ºP‚IæHáåN&ßÉ¥ö#èdìó^¥l¼rNžpÓ9Rö£@¶KEBVžnë‹c«ölå:~I©àPêWeœøï˜*²<ÀD!¸^\¤ÑZä§lqŸì/¿òÀ½qžÄdùÐOd|“£Í|¹( L_úuBjнœÄÐA);ܺ¨_°êž¸C;Fñd¹8Ê)8Ú÷Uè³›ÈÆ]”#¾Nd¶çãñ"=!{Ögw7¶¡¤£|92@ðüJK5Q?õ`êfdºÍk!åFgëDq<í¯æ'7qçªÒĶnœ‡®cÏœ†n_‹Êe“–'È6§Ïñø&D»M’Gܱi ‹2×ßäõ§¹DÁsÜ7"g*¨yúõ¤w6m9<ævÄ>ö"]G¥# s¯ïåiìzweõCÛÇoeòPí¡$|o°}±®Yk›”*,ú¹\ÌWåÉ ´xȫ⮓,GO–ÑÝIDÇ<X®OÓxų®Z³QŽg§ÒŠ÷ÈhN7>ù¯—Ã1uÜA^ŒùEª–Å[pi4éÐøÑ/ž{M¤ëš eŒ ¹lh¯Ñµ(E´°®ï“ƒúKmÇ0Ÿ$ÕÞk¹p!“lÀóéð=!u1y\Ô¶Ûn€ÀÐ=v¦lÏ©ËuýK!Q&`¬¢«Ö‰GßT„ Ö\•+MžDÓQ®ùí~¥æ‰D9&Ùš_ØÙ“…õa ï‰"øÈ Xs¨Ç Pˆ×¼©“=…èçÅ€àii~oL'Ÿ÷Í+1ÍéòÀ6¿ ‚D¾öµ¨¯‰àÇ\ôµLåb¥;*WÔ »=9sîʕߟ¬=yܜΠ¯Í­NÊà›cÛ£|Œå»ã¶–U _£¢•»ü1G‡æñð»Ð±¿ –€z €zvPT¾“„޳°³‘’þlrÅÏWZF«°~ôË¡ê΀­ÅáHJ÷yñÉÁ´b¬ëæ¾s¬Sü”ÑNÞqÚÖýÛKöÜ››+)Ž‚/ÿ:QöwwGíùrKºL#ø*Å%c3@ŒYÊÿbFM«Ä®d“D¢S¾q&c´ýü°Éëú=ÜŸ7BC<åîäX=_ýU–;?ONvŽC^8xqµ¬íÓ_Ï«“y¾`ó}-²0ÔﻀÅí_]Ñ<+¨Õz"ô­£†Wm×cð†1ñ·‘÷Ž÷l(—òÕ$ÉlÌvÈáY nsÔèD7)E˜Õ€a= Ú¹@u¹¹]Õ %Ô$æ¯ZS«³úK—MlŽ¿µ_M¼@àÏò°òÈeCÞ ÏGr”»ã“ŸN(¢YïŸÄ™JçDñÄ¥­/ŒO0r¨/Z‹š+zúÍH]oßy™bŸ$º|¿ôXaL6ÊŽ4ºðN ±”ëéb¡gðåBù½’Í1W¡ÓÆ ØÊÍiIíÖ’¸ÇlxstÓ?üioŽûE_T›-uœ5È•Sç Tð›ÖbfëŽÕé¨wok:1Ý ¢ŽXˆæÍÝaåô˜®G›¯ú™™”Ž.½ë\3(vrbÓÕ ȪU²'ߎløÖWy›0tq·û}X«‹ûL;ÖêLýÁzÕ¯c• ìž>~Zk}ª›£ú‡çÚ'žgƒ77_³^Ïï\XP‹C_´í ¨¨£æ„6¿L 5…¦y„#=k˜l¶ B"r 4óNÙ½é8¯DfÀ £òâ*Ïkö.Íþ´L <í6éÐËØÚíI¨2ðÑBP¿´+LÂ<˜Öð5iÅyo®=ûr:,pëEß(+MeÓ®¹´¯~x'âxßEŒÍ‰'¦•¦^KžÐ澸|ëý=)™ö¼_’¥mËCÉÉI Ì 6³ ¿Ô¬zùNÃ4jWÓdO'¢^\0”ç¥ ÷B µ@NÃBÀï­/oÊ“FÒ<Ú^7=ûÆýhÊWî(å_j7¶ÍÙDÐ;p*ÝŸÚKÃÉA7Q’_Ò™”R8Fioþ¾ÚËþ¼´§öh`Ì1ßupù¥×Äx¡ÁLjçΗ/xµtÏ^nà.¯[#ÌWÞ°îºî9æ¾&‡|woêvjaåñ×"ŠúÕݵDjƒ„_» –æ<½L·{´íÔ|ÖæPÓÏ‚¹q-GÞ Þ;ÏT›ä«e.”½Q?Î+‚>.q¤¡=:Æ0Y19ùûýèWb'Ðêdù×Ãб=íŒÑE¥.êéù§~GÓ1äM’kÂ6tæ¹a<ÎsÇM{9›° öÐÉ1g·ú„ÚÉ{~6†GSüo úCgÒØ0î0¯­‚46´¥L “¹’Š,¿7´(RgáÉ!ýp€²€,;açúÂ݉#ŸŸù:›zkþ6GP@Vw£ÛÆ%1]Û»µR¤wâ³'MÏÚM¼TçƒJ¥@£‘:~ÝkQ?ü±nÒi¿ŽÜó3,:] óé‚ØÆ¡€1¸ÍõÕs¸×G4ÚtEç-΄ÝgÏXW™&G_5rì”&…}K>bvwmÊ.mûÓ³a{UyŸšëóÆC¦ Êè™ £ÝëªaÉÛ;ãG”6CrK‰†~<³àh¿˜Ö=‘XhôÔc*噯¡8Wª3¤K^Bå¤Ü× dnìŽÃ ˜ðsõêE²ñ&‚nˆWmä¿•7lIΪHê.ˆ7Û®Mê»6Þó‡7);¿Ÿ#“Xïãùƒ«^F3EO[ ®þBÐN¿“çÃÍ…Hêñ§e ¢„ wˈG÷[Û= ©1-÷ZQ˜I]Fèntsúbnü®Gè!ûÜ™á±IR¹DÙ韊É`“–²´7*ùs“Lûøpûû97 r¶’Gû@«$¦¤ÎÊ2I[Z£ÕšöYAú½Ï±$ñý? ž\ r}Huî—¯»H(o!WÄSjàEƒo|ª&K#ûðÏùåx•g‚±9–ú‡oô]äÊ€ÏII°ä:°«ì“µ-Ž~iËÒ\Ï<¸áct¿;j7ñ*wu’‚Ö‰,‡Ò2ÉÒ?²¥Â £´òAïnÝíiÛÉ~1(¨„xϨ¬_Òú æôÝ&{s8’ºyw;c0oÃÝIOlnûð×mHÐpÔ¸8·ÀÕ<Ù@‚a|PÂIí*–Ëu¤3 ó!ÈÉGí7v¾ ‰ˆØ¹£|Û™c åíiÛ+>¿Â¤²yö5¼ Û”VTÛðO))Ñ6kà ß]^êàfvå rc¢=ÛñPúµX ˆÖNtî/‡JnmY+'éü´]JËW™È÷µÏ¨ëÇœ8R¡Šhm¿Œë‘z q˜¶óýÄ£ ‹sç.yó M‚ý?WÑ¥){wwÒ0䩹äPû*¸¥¸f]xþ$¢Ïø›(„6:Aµ"NXÍÁ#»¯Ï û¨ÇÑIÝÃÄùÔØkÏ÷õKÜÌ °:yä»5GÑÉûýæœÐO0·>ÊD©yY#=í6¿´ÍÛÛ Í翆H‘‰xοÒrŒ£ºLã_²ôºÎöøâà(gí4ð3ažX¾h¦^}cSˆ­ð¦£/Õ€(þüòuP¤§`Œ ™å½&÷m<Ô¡,ƒ×j€=°ç5¬m1m(‹@†ŠmùslꟋ¥Üû„N¬üÎŽúËÿøšøæÓ^ðÚøE¦%l`ëß}MâŒå K 7aƒ?}&{nNsLêjXIê•–+/Ð``(=ã·îUò‰¢øŒï÷¯”—Ým¬K8«7t²( båÓ=mOc÷t7:´.Í•x›? ¿Æ\\¡ûé¶ ¨_‹ðÁ²›O°¬ÝÕˆù¾>È4HúÉe˜¶'#Û‘Õ;kv‚tUÃCÜUÅ0Zü]¼ŠöϪÒ6ŽNÊÚU­  |¸/Og =*10B1Ö— ·¯<œøªLÏë ~ÚÊ+9{â2p‹9ÝwYã7×bŠ<;å@Ç2ÏK$æþ.^¦£á+ëÍWâê—,ƒÓIË|ÄÅŽ4sžnûÙB$oÕ—ÇkRë+©³©†»ƒÝøÓ7G¶‰ýò"ªñ‘5w](Ó®öO.µµ .k^SbðÑ|OIÕs´yk?æm¢«¡b>ö¦óLÿV?Æ¡•oÇÔññ9Âqr€‡QÞ-^hû$ 5ÁœÓ#·´òmÞ\xÜ…â|±V ¥ÃxÊ4¼$ÛÖ'ëN\óÊ!kY»õ­yžz€Í–X«É“5ÆCV9ôÝÿ["N_#ÃzvIpTó"ù¢ÚW©Ò€¨ÝN.[÷êJƸ/mßs’…‰~ö® ÆZÝ ,¿•“sÖXôãÎ×ú(E;yKG `ʦݔ¼Ù—^d`–q4Ðbç¸íK°ÒôAÛæBdu]ÍvžHZ¬tåßcùBq‹c~‰Œ~u,’›zrÿtkŸþ°nŠ©öâO4'\¹óA=åä âiû`SRuI«OC4?Ë„|ƒv,!ÜÚSÛ¸ŒD¾ÿçHž[ó^A·ãÈâYßpíïÙ…–¿¡"£ªùån}ió¿|Gcçxꋵq•«œ§ãßFFƒÖ@ç#AWq7cÊ÷—‰Óˆî¼RËó%ùsw6릚DÛŸbÖ¢™šžõrk©µòÈ‘ØJW[¶¬AœðšÉ\g±çœâ3oÛähC€u6©ÛBóF«ùr {JCEb»cš64gÿ§+Ráop N/€ÌŠ»_ÿˆA•ÿL˜ŒLnÍ ·G°”O¢4Ê®Në܃9‡éäSZ4U´´ô#J}ùlg²+ÓI„‘PÆXwáD[˜ô/”2äÀ ô ]Ñ™“.Õ8`ÚöJt|AGAÛß ’öNŽhŒ0ˆ„É',úHGˆå ´gC ò`q~…{¸údu&)›H“£ØIïÈš^ŠJdÁ¡ª¯\Ýpˆ¤aÞ"ŒZ¿ @«'¨bŒŠ?jZèR–§|@R6qsh’Ù‘†CNº  š6·¾»Ú¢n*ª€Lh.¤çÓš0 —]d¬±ý¯ bãbjS/‹à`fŽÐ.jºèfžâ…F¾õfëNvúνniDiCÛ·¸Ú›o2¥G¬½ ¬W«]*žl*ë»M»4èç?{u"@ó‚×vÿôªvæ%â3rÒxûTUý [VÀ#ÜùÙ B‘CNßОP½ŽŒ¹AÇ„÷³Í°QŽh×U¬,m\"›RУ®®jÃlµÑñ—„×ÈõY¾²7·ŒùÓƒ ëK¿x™Ó6lŠÒ_ŽJîä<7׈¹ʇ°’5ß´ú˜V4eGšÎ‰+ýg æç|ånú£Ïøy}=:zÙ<žÎ¤5É Ó~‚U>tœoiîÄmìbHü¬V#ÒW]1×׆?maeEÖ0Í·òËìÄÝ)lÅsO!ÚÝ )¿nuÔÔo,–S5}_;öœÿEÖÛ(ÆÎãH²;3ýþO¼Ýs#"A•¿»´K"ñ“H€¥*ûøt?hˆH¦W‰›8ý­ƒÖ@z€4¶ÅÑ~µ&™(žŒSµl5~5¥Reâøjº7ããxm±®‚n|8i~{þï§»­}cÊS"vâcß¶³j×öê4q.ÆÑÆœô;;ðF•VÍ3g—×4qZA²)âù•“óåØzS–‡0úh¬ÜfÍë<¡á5¥_³Fƒž×“–ÊÞ¯®ºfÄ\ZöЖÏë,÷Ë]{cÐ~2ëqC«¯uÐ_®Î¡Y,ÆbŒQzM¨Õ~•)Ç Æ2"Ø÷×b5ð³cKþûë?Ø# ¢ÄÅ“šÙ?8Ã÷–WõPí\k/±1fDQ¼¾6·ã±£jvôË;{k°z®Ö‚NV] ®=9jNò­sðËW/ÃF2‹Æö>Q9ºtWCfÍ\ó‡«óH¿!6>÷™ñ@졇X{> ~ý+g'ínLf»‡\ló îXyš£i?†Íˆþ#¥EE»âéİÆED›èG@·È»Ø¦ÂÁ„´¼øp†8¿O±—8rš¶ÆÍ< ©ÀÞ³XÉ딉‹…Ýñ°>3  |¸mDì“ìÞŸëÓT³¾ð¹ECš‡8È ¿•Á6Pþ“kš´‘ׯ±P‹½@cÖIª:3–³òžƒgH÷T‰Ú"Ð[s7¾W³¸†«/XEu¡lAE4#Ñh8¿¼¶áÉï"‘T ®£`=â?ˆ]:oä…"ÚÆƒäÁ¡€Æëj2a‰+õW[œëi[žŒ½hÑ·ŽRš;zü7Ÿ—)~Ž÷)¹ÊË%°=v˜}B‰ñ—»¢Åmßq¬§ÇdþåCßpH~Ç]¸1PìŽÑøf,ÏhlŒóÜ{!˜C5„}7+óÇA]žMŸ‚ÕEXþc§j˜qzs$šñå}¤6SÉ;î`Ìú|TS7ï4ˆß¯µÌR@u4ù¾¡8ùx°ºêànUêÖ>ÚÖàóÓnßKPóâ ÷z]›^gC^E`°5-=ÜíøeýÕôaBA”Y{ÑÔ·¬ÎRi>7ì°ä<狘Î÷`6 Õ =ÙÜÍ´vôª‰áÐëú?\›¤]ð{Î]ê”p+ÄåÔíÜ¡ ×>{å¾Ì¡&|ÌsÁã·Ô_ ,a–ˆÞƒ‘Ö…°^êÛåB–(äÒÄU_y§¦Íj?u= l@ž%ä'ª››Èb–Õ3 ™6èòÊÙ3µ/yÅ‘>üöÓŸþ©1HËK{yx6Úš¾Vl ý‰S &×Òn^úô§˜ooD 16ÜiòÉòƒgžÑ›i%C¾¾\l®81¨ÞŒ‚K9‹c§†-~shm(êk¾zµ~µ=0ÇßÚMüf4dDý@½¼\°}sØ"i>ôÐÂWus @~+¿èY˜ÏãîÙÚ¾ÿÌLè_³:èå굜‰ãà‡ìr´®¢Ùn”˜kõÃˇCê§Ó¯b³7 ºÌϹäC†HRcÓ±¿ëÏ\´B†ÂÚûa•1VïTTÐ8ί6zn¼.lÎÉÑàòÖæZ˜YÔz¼ø9G½¹ÿxíÝ8J­É btž1¾ýÍé‹"Tü Gç]h»Éj´YlS̘|¤^jãRšÈ¬Ú">&Œ]Œjñ¤Ó~U¢ hÊÞ¦øÆ.ì–ó•ñÙV@ú“]Þµa=é'vc»ð€žµÙ&s¸3ç8ù[£j×ð#¶µé›ó{C÷æ4Ž7×­†ŒÇ¡’ÉÃdU,g·ÙÑ¿ýI¨Ãçno¸þ<¾˜âYTÕïøŽñ(²]o (ÂÖU€”™úEóÀXÍÞà9W®ZϹº`Û_©(¨ÅaU©vlÀ†Ûž#Á6nP Ð?hO ­5×í{’‹-¨,>;sl¿È,¦—ç,ªI‚ C« ÅøÕS;õ­—öôýjÄ~ô\’ë?²9=œµjgA­”ë@n#§ØÃPÏu~Jj]dŽšêHõ99ÿCMãa5SÉE¹uèykç­Ë÷&\o×òý"ÇæÂ¦°ëÚQúvø­¬ÇŽ(Žo¹ÂoµÐKê¢}(ÇËËss+ûáÙ³ cà@_΀&Ç:ôSmt•±eÃEéM†8Æ•«¶qÐP†ãT PfÿZGæ…¼ÚÛ¥ï7?‹!öꙟ¢LÕ;r.(Ø´¿±ß çycxúa§XÖÍJ Úžº eSë·o$_^ TX©jGoyy­N®}t¹Îú 0©˜ãoÿ &²æ°8ÄÀÀ˜•ˆÃtrc=³wøÆ0Úe¨Œ~­ßóyÏóßÚܵý[ÿŠ¥`(í?;÷ªƒ?çµÂ–ïj”F™ÜÝÓm*±&¨ùä7xêÄZ“S87?? ¦-´OlìæÓú•bµTO^ÖUDÃÅý`þrù áúà/†ÝÃä«ßòžÎ£b(ð^ÚѺî®ïþ×E9Óo1Ž“kl׈ð‘-†X6Ê‘¨RᥜO¦³’¡¯åì·÷Í'üCüÅkØžuƒf¬GºÊlB|íZÂŒÞ)öÏDzËp-Z2ÍTíkfÒ”ä¼(qfè?ó÷Ét×\qðá9Ñ ‹ß„[ ñü_ ƒ˜ƒ[Ì©·-¯Ÿ™ e ÝüCŸ…Çà¶ºŽ«“ìÄš¹Z}}°¯—ž‹úoŒO˜hU5¡œYrÕGš §õ{2£;'Æ£ŽÆÚ2:Ö‰ÝçB1ċכ<ç–oÎ×nñþø) Ó¶–M^b×’šÓfã|&F7²Ùý8ÉQzüÞ¯¬ø€¤ç ±é,¢òôPhcò’~n®ïn69¦Ó®¯³×¯jU”¶#&#Dìôɪ¾ñ|Á©ñyµÆ¨‹èðË›äì±–ä6ù:Ó‚¾õø|Þ†?çR"kÎÑo}ú _h"¢[ü$ôUEðtv—ŸºzS ò¥k”üÆThÆñž5nµ'7–×Ô`æújÌÏo¹*4SʵMX<Ú2–;rLÞµ˜£“n×­FŠ=q…C¸i;B{=;ç9±¶A|þOž¿`r3EÏ/ãlý7#·‹ }oÍœíâz² o‚ºXœƒØ!½>¾JÉsEp4éö yíÕŽÛ úテÖ[Æ1îâyqÍû2í/À½ñâ*ߺÕ0| u5Ö>K:«­“¦ª€ù"vÊí—gM[3·/#„蛯Ïvæ:hؼûkz~)ò=©OÕ–šø¥b¥F¤¼¹×Ö sÿ¨žÄýn°íþÁ'zù€þ@Â~Ãh/ž¦zÙ¬¹¯VçßZ~zç _bÞ<`ÔhËFÝ»OokõÌj$²7΂;”£y/Æã[U$gMæ’›ÕÌ{ð« -9qXŽt¬5µt‰÷aÔ‡|úhÏ·/‘̵~j-ê åñÁÀ`¼V…Ü"»zèÕ^aLähz æ<´Ïeþg=h¢µF‡Ö¹…²q^ïÇéÅØ c*1ß&,·±(PõsH^{‡xó+ï]kxÑߪ¦|.ÚÕKðÿ`0Šj÷É Ñ“‚2õ.­¨©±jßYŸé={ex}Lký?NÏ¢ÌÇ!ýÖ͸áo/®hæðf‹óqÒçÕ}ñd)ŠXò‘§ë»F‹¹HÖ÷Z|fÑ¿_k½‚’|1„aH°…ôqÞž°Ÿâ" Ió•ÅqzÏc7»GÂSñ<3£G[ó¼îI´%.²ïõirùrnGþ€ðþÂô.™råF_ãÝ[èO~õ !, »=Èàì\:ïÇEƒËÞ \úª6ñrhtÅŒ+Ñ‹ñ±+lHúÌVäšÊ8s™ÒïÓϼTmÚ4ÑO MWä“›ƒYõkH弫߹¾ÿ¯Ošu|0h3´ºŒŸ°.N9˜‰äÚS#Õàv£âVdδ^+Þù‹±@ñ÷Iž¦º„5¾]ùeþæÐ¦6º°]næÛ±8³ÐMÜÚc+oxn‰í?ŽWO¹Ôò^2í€B—\í{CŽŽzSH=Ì"ÎÕr¨ •›PÕ}70=•‡Å~}ùª¤Å.ÿÒÚùÓ3lÍ(ï¡áóB¢ÌÖJµº*±¥‘¨}NÂgïÀžõãK¬m ¡kNÓF'ÿþñì;íPÎÓˆè§Á|ªo|¼vs ™:ymþÅ[’7C»Þï½Ç0Tb¶Í.ó‚Ñ›Î{À[s,šœ«õK‹²œÞyr‡µ¬ÒQ‡þê"æÓ™@×V¯B®F}ÞÕ¤ýfÄZЇ%ó {z8+ÌçƒÌQæ±N¶â*{ë¼Ë3 ØÃ"Žø'Bý¦9׿e¨øê䣴ýµµ*¦Co{7²‡çÈ9n<Þ®ƒN/†@t9Q™ãÑZM6„þÓ|a¹ hígd*2:cZÇÎùê»7ãÊrÃøËnúEµ§ò¹+÷ksª×v®çúQê`õá_¾QñlóøŠåO^bÃa«BìÕ¬{¹XÏ3çÚÑëÖ™  hçBà»:Ó1–Šø(ß¶ØÇiñ6ÈÞ®œ½¹ùט¼Ç™÷Û>vÁ{ÀàÚ»W$ Ö—/­>Ëëì“krõÔÑÎ׫¯÷óÝÙù¥‡™×ÿþÑ·W2¾ß=?®å×›Slí¶ì˜‹ÓW.! ¹Ïj‚ê;ÚS–œõà % „^Æ ˜;2‡ß3‹Žuxø `{×Ã_îj¬É€—çžo°Â>¾ÍÃ5×_y±òòõ“ë›—Û¼ym&aõrî÷æ ¹ ¸¥§Ý׸þhòäúÇ3¾³Œ£1³;®a /¶kõÛ÷å.° ³yµ<¢cvÃ4Ÿ œe]=!Û~"¦¿æë¿a›…×k¡TÕoX˜â»ÂìšXþµ7[×ì9ËëÇåp4:~æ&îj€Ð ‘ff§G¶fåœkOìrdì›>kÇL"£µfWW ©í³ ô­ ÈÍ?cü±µàa ¿îŒÄ$c‘±]spÌù߯]àbÙ¯ÿé·àu#ã&;ÁM¦‡S'Ÿ¯ò ˆ´z’ÆXŽ ìÔÏ-×ã9IIàÙ3(1%öÝ$´Û¥4»be¸I4„cµí×@ö§â¼²xÜÆŽÁøh=¹¤ÛÀ1 I49 ôUäƒÄ6—Ml?Îo7[î³éFE_?9+w}2¥³¥y FrËËÝL·±~¾»vCÐS¼‹:r­vjæ¶9;ÁIÇg.0:³Bê»^1,rñ—Û·Qaö¢è™U5[ÌŽ1òb’»\þÝÅœ»bó( x¿ÅݼÄMààr!n1Wú¡h]f'm 1u‹ c0ôÓ†Co,¾L„`F½*7aúKfÙ“C>Úƒ'|•Ûò[×5lu“²›Ä+^1½9ÙW¼-¸ÓË/³¢ t…ùµf¹ Žc_ë…®³N¼¬ÇvòÆ Kgh­cÔÑ9ž^«·l>˜1ƒHõÐ_&»*Þ?æzÒ‹œkC¬j“µo‚€ÓF,/㪟‚“s´ˆÖ²O²KfÄtÉ[ú­ \·wX „ø‹ö)tO'D7Ñøáu›wõú6㚌¡ˆ¿YRì^˜AŒô±¾ú™ ðóå7UE 3«7yn¸ÐñÚÊæpÎ}Bô[ ™¿~ÄÓï(p”·€ò }Ÿh7Òk¾Zb{0Â۹Ѩ<›¼zs‚ø=¼½©9+RÇcQ6?æ£núÑ¢ïí+9å²ÜÅü®1°m` ¸ª9·.OçíqÊ3¢”ãæÔ¾3Fóúï\·ka«Aé¸5m ½Nz#,±v£ÿ‹ÙÃ!¢„­1Àk®áÓúK·ºl ”óÐ7ÍÈÄèK]:®o÷«—;ý­¬Î÷ܪÑóLï=Wƒ5gh¤ÝçE¡¨}Î?ê«ßÖÀVö±’s ¾{±üÄÏqFæ‚b‰”b¾Zí“èÏ»Å/Kí ùáæÔ7œ«\¹fåwíÈp?æœi/—ò”£ÌÀ°VVÚ9G£a±uéØkИ£€Ñ¾7V‡ÂØE`¼=hu}uÆ"î†ÐÜæ™ êÍ`8I‹Tuw_tÊsæ`vrçºì¨‡û±ëKúvéû/hÞ¿œÄ2ö ƒvbdËÊk¥&¯½:ÒVžch(kA¾Ù.¼îG,ßõ¦£¶¹ÛXlÅ8=`1’x`žÔñ¥ŒoûâµæQ÷œF¶‹»öß:ú›“Å-.|Ÿm\'MââÉ-,Î…û‰jûÙ_z<ù!Pûã˜ÉN‡ã,2ÿ€î.NgiEœ½û{ 俯x‚Ë"œ£îI°dÒ…øa6…øÌnQ“`©«|gÄCŠã¢n‚]èZÒ Çâ0A}U„Ó½ކcl,Q÷;õM¤¶61Ò©·‰&¨çµ>‰r“@žõɦÞ÷Iœö æÛÃGâ$ÝíŠkÅôôª¡ Æœœ`ñª–°Õöá›}ì¢$`Š®öñÝü+“^PZp!ÊLx=]œs«þâè\,Ô <¬ Ï4âಿT0\³˜î-,MŒÏ%ò6KâìÙܱ½€z›±ÇG0îêówþúìÆkÄáë¿O§”Ùf?K†º*®×g¸Ê­Öé3•ù~ã7ÇxéË‹þ³sŸ ïnøò^ÎXT£±ÔÌÍy»ÏÖ¶qkš’˜2î~s¼#îbÞ‘ñ›qιÛXoXÇëÓ¶¹GðØõAŽ/KƧ–8›v:¿_Â嘢™è竵™d(ÉuI· •ÉüÁÑËùR?6À뻡&çàYëêâÞWý’”Óp2ððµ]×ÏwQ{Øk°ºhcF¾‘, £e8[b#ï«zÿ]Kxz¯ZçÇÅnžt Íý,8 E™·Ôå°k±µ%Ú–“ù«Ï5FÈ”~ûò®„/kQϵÕVýDŒM„Q>P>ŠÈŒõù2ŽÇð‡¿6r§›ág£?xè ƒÑem_Ô>þaà }ÈoͿРϴz0P7»óÇT F1±<;þÿ9iµ‡ xö8—áÊ*÷+B,ÊwúösÇÈܾ‡)%>œ<ûWáÔmçÒŽ9)U>®tlÙªW3?ÏÆ´ Ò¾œÆÆ1Ü“4ó sr·ú>5r5ÇÀþÛ§d2?PµŠ±°ù0‚wù\¬Y¡Ô‚ºSýël=LhœÞ4œy xî±Ê¿š3ÕgÚ5-“áüý?-Tœãyì9‡§¿¾>qVöEÂOW_æÐöÎuüžO>^Ú娡ø¼‘ãð´Ëê,®>ˆ‹`¡,FvÔÁ‹ŸîY;jëúš^}‡öÛ³Ýk0 ülè‡öCßµ³=€¾k°ûµŽÚæ ñdWŒ¨ÍRdk7‹>ÁÝÔ»ÖÉÙÜ´µyõWc¨#¯q@©ˆ/etO¯D™:åó;u:ó5–ïM­f³½)¢ „dnã¡Rß#Ø^dñZ;bè¥^\Ó„ʾÍps¸e´þª²üÉK¯ž›È®‰'c©h•8çðÿµB©Ô« ×—›D:xQÚ¥½‡7—\/)Amù½3¿F1ù€-ˆ?h$‰ ‰®?]‹¥~pôét ÂôëŸxaÐ:Ó–ÍNä„äÏ8,zŒÀgAï6‘Kë±wpÃÈ ¤>in`ñCrèá*6æ$vðsfÖë†Ägm,ì-”|ì«síqÚ˜º˜2ãgø¹â§ë[Œ‹:F-j.¤Ùny3x:c¨äµ ž%òÞÍÇíy¡ÃxuÈ¥øùJPuqìÛspµýd–SÌû ¾³u/?ô¢œ7½?±t2 §ŸÅ«©¾PîGrR˜V@1õ¥s»œ?ÖÞf»unQ üD¯°E\™±V+Óï"¢ÖŒ¬+n¼ 0üp®Îœ)olS¶¸ï•m(qÔw a0ñú‡ÿ7/ÔÖ<\tƒ?.Ïç ¿ƒÐ\qczùEÐ>ܲ¥ÿ| ïµÙ__ã$†Œmý™MtËàÌd'¦_Ùꇮ#o‡Ñí¡q’b\Ý2ù"ذcnÞNò6I+‚ yõЩ‡c ç?rÑAéy"HÔÙ7Jß#ÖYÍm\äªïöBã¶mýåôÖø›óã…hÞš—‹£.8yí{­nâ–û9¾•±)9!5}u’UÛwJÖÛÂñm®]«Ã)W%ú™ç¿BM«>Ý«5ÔÍú¯œÛJXªòñxyÀÁZš´òçH(q§3®kê݃­¯Ñ”õÁ“´çÿx½\ÀBù_<6ÿqDF¼ls\¿Ÿ¼üá¡AÑJhÙšr&¾¬í˜E€æ¦ÏðVúsâ(šÌ±G˜ÝXÕÿö:1þðúê¬mû1ÎÇ©°Æ Ðø»ÚÙaÍÑhßO©Á‘‰ü»%ÚhÙê$üru>݇„Ãrô¬¿K)¥ºšû™ši^ý¦Ãhdϯ1bA¾¨ÎEk3¨ð¶6ÿhH%‡|HØ3/OÈ› /žÓ86aßYö0gì—z±°ý>¨Ê‹\$ÊyøžJ²ÚØá(¾º¿-™ ÷gãÛßþ†»kH?‰?G»ÎfAÔËù-¶eëäZ¾ocƬ2V˜— Xe)$ Ùþ&çŽöðhL圔#¶šË±"àc¼7 9µßÂÒ럵0Ž]ЂySÄ—þX9F°…ˆÌïÏF(&ÇéDÏÝø)‹°Bã°••ŒÒØ`! ›¿á«˜ÁŠó»#*°PYY-гý@ㇷQ *|QfÉA»Zy©°>JÆyz2K85ÅG¶¾öò®<çwq¦o==c/Ž}kUÚª”U s~› á+AêÅËN[ùQ3çv›}\•=Ný3Vi¢Óë¡Ââôôgsz¡÷ÆûT¢éf+»ú*‡+‡Ç+;Tj=|.(âÁÓfK±óm}ºÝè°€œÏ¥eÛÈyÔˆ—'¾–`#Õ8ïøYi»—œgÀÏOlü4x\ ¥Ÿßr.»Ÿõ î¾b<¿D&3J€V; ßÞ§­gÜXøЯ º¹ÚÔõU6­×™v•M›†!±žÆÃø=˜„ýXiL{±*øw£cϽ ˆ/È‹Y,=HWà}­,4ã5îõ¿ÞŸ4îòË dy¸™—ûÏ®‡"#ÓZÔL¯g¡¤¸ÃW:mÅóüÔ~Õ)¹5ò¶S ­ÉpŲ§8Qu O…úÍ‹ÿ>esæZ-SÃ…/ãMY‡nŒ"ÒŸ±ŽÙguüuYŒêЄ…誌?ÕÉjDâú5𡯕ÈÞ9Òiñd$¦1옎=@–ô”ùÔ5'Ú+¤]ì|p—™ ºµàþÏ”á5WÇoi1·ªtù­˜E@)¥ÕP‰¸Ëcð¿{™@& Æ5Ó±…†jûËCÇx5Å@φ^#îGÖBGù–^ô9Oèu³Ðœ¿fO'ß’oq|åR¬e¸Æp6ý2º¸ÃÐþ×/"¸>£Û‡œo¼Òö›Í±æî³)jùùˆaû—f/ôKhªPÑòEÚ4¦øÓýŠ­nøtÉÃrê;79D;³È¼  qÅe¸ÿÄG‹ÿf!¹ ×âöÐîD-ZqCÔ¥Àt –ùòDs (±C:èz"™Íû½Áê‚®œ‚Úe¸¹Âòw46MïAª…¯Ð ËåFæŸðÒÇØ`ƒÌüÖÛNËö‰òoòÎï¦×Õfó˹ƒÝêñ.üÙhªD‡Ç±ÏD_£ëøê‘ Øý9ÒlÈÞs–ð&-s2¼Ñ›gô•,;Ò7†yŸ•˜Ó›µ•œwü\Üæ»Øi1+3øÅ!&ân°tÄ{œn r]ÖGõÅF¤ä3ŸOÎâaŽÊÌŠ˜:Gp·c’Cù‰½±}±…FìååÊÖE»Þ_Ò©: .¾Ý,'Ó×Mw-½r;›쌂`η©käzýÓþol5Ûú/@õÔ9H“îºÚ: ¿ÝTpÔŸ±žMQXŒåpºY›Ñ9[ßHíjDñoô»¦ñeltÿ¶NnøÆµ‰áìû_¡û0°›ÖÆ«.:{zê”ç“l¤Õöbð¥Y8rÄ·Y¿ÜB ô³Ãqn똹ÛMÚ:¬Y«å¨PÁm¾ŸX»þú»÷Eƒï’,ŠüXAÖØ/kta–齃Î~kÏ‹¶¿]C¹¨:ç‡áœ‰{zëÙѳ÷{½Æ~V-è_¼·/´Þ!×OjÎåyþÏ7ûÿÏ*¨Ê÷“=¬Hi¹zUÜ/Á퉢9 5O^+Rsî,.W͹… _®ÝUqž u£éaËáå=Ò<=zt ^ù1¸ò¡×~׋ë@=-9ç8³žòåqb€“Ø)´“¯Í°ÃCâäÚxe8§ 4ý$!¡ôeÀ:½a(A*…ká1 }iðP'úðï,Ï¢úSb(ìºál¼ãÝ<› 0ýE8±k`K('*΂Y‡ã«çä(¿…iK•ïC^üîA¸t;Mç`-~8x6Ç_–w`¸\à›m+û…šLÔå_µ9Ô¨½åŠÊel{9áØšÊ=PÜVz€÷ÓUß1¨H7\Sö'Tš•zr鳨"7ßPì,öjàõïu«÷•Y€´Y|!>Žs {ûÜK¦'#äxZOÿNuÚ¹ª:¯6bœœ“5xÜ¿{ê[®:¸o*õþ¢ˆ¾U×ß:toÊåLƒ­ôøz÷šèàïº|÷Ä(å?ä2{ò‹÷A ÐÊ´ñW퇃¢^z®¥­9°ä=öXkš³ØÚ0‡^ü F|[lÍ5Á}^…ՀΠC?<,ž#õ_Û¢ ›Jý7ÿ4:‚šfŽŸ…O':ù‹ÇPãŠL¿ITp1°ÊÇß óá³ÍG› Ë3~å×hù 0Ìe,Îa XøO"Êb#s9ÎgÕ<¡u¤}G‚„rònüô—‡vióx\c=„a•ÝÛ¬ëcs*«ÜÂÔ ™áÌ`¿³&Êb)h~“e<#_ OoR®ŽÅ°–r.¯·8O&„M?^A8䫲߅„{¯¥ð¬I¶,t6&íÝŸÞlõã@Œýt­0bë%›eHKõkÛ˜¿Ö™ÀÞ84 2B{Ñ>ý.uCç)2öíàe­ÊÝþçŽ}ºC<Þ=pà·OM†§Ÿêé´7o°’q0?OÊä:èôŽk(›cjg±èìïU`ûŒ³]€U\¾ÁsÖêm®Úl ³ÙP¨žÇ³f>‡« ×åˆ:gÓ§W£î¤Añäj>N‚oö¿F׌æpéT6rÀÙÚë;ÎÈ‚; ååMÊ?ŽoÏKdH}t=Á÷?ý’ì8+±å4ÛtE{¾¯jË;jE²¼â@§9N°‡¢÷˜*¦5²æÏõ'Žâw±‡ÄÑÜ5ôô|ªãÄš¶Ÿÿ_Æ]ÕÙ5¥ãϦZuÕ˜7—åÛŠxqŸc¹t ïÿG,ŸÁGıëúòMkÞ<$¼Y•³‰C#išCoÔÎŒûY×]6Í2WÄÚ-Ñѹ©qõÎñN¦üö)ñB¿ž¼ë¹ôä£ì^^2jéž,ZYY×ã'ãß…c-Ê7kð>I <kÅPqëÄø+î‚ÝÜ´¹¤ÄC÷âkcÚA¦røù͇üž\f[ÓæAþ‡g£œ°"˜3`×ÄfIs¦Û~ªÁ ZdÌöÝÉC8‹E_‹µÃ§ŽÊº/¹xù^.qعG(ŸŽÓøÙIª_ ómjR Ï®åéþùäa; ¡ÔÇtÖä 'Ó¼l»Þ¸š<Œ¬8øà$Ù7'Ó*Ǻy3šíÖªëÇ{ïê¦ÏêÖuÛüä¾4.„ '0eYãÓ}%k°fZMÔïèð¬O~øh&7×R­µŠÔ!'õâNðdêgN9h£Õ{È`»Aa¾kRnëì«Û qq.Äö…7ÀF†dØ_ŠêiT`I.·Wü6‹Ó¢‹N<@†U¤è+‡¯Ìšm. ¾ùª›R©˜”Ókt8hD1æ^¼¡çé„:ë=oôŸßÙkWúh¿NÖ7@D0U6mâ†Ão!«_žØSÛ—1ã¾#Õ5j˜î0ÔŽ ’úô§³£ÜÌ» –ò˜«‹p¿št‹3(äž±ô]žú¢ÅOÀµlû«Z»ýŽ.“ñ-|ä®j5Ñ~‚þá®\Ä–ä·>,Ëù0ëq˜Iõm¹œal01Ù9¬{µó´ˆ«EhˆñyÚy«‰Xn¨:fôsøq4‹ÎÛȰ›WhÅÄì{`Áy×ÚnfnÈ>p4»Ì¥±ý U»áÒ·$Î^ ÿn÷¦¨B/8‚)§â~K€ÌºÐ`ÓhÂà¥Æ·dÈÐë”o•IJ…K_ å'nMØï/öôd÷4b»xÝäñÓ³˜a¨³¶kÖ\o=CQaàÎh8r8ë0­Ë°Æpú‘òªßÿ/Îã#b¼hA§ˆ&indõxÙoÏûêM]B1õ3W:ö­õyLszeúd¯ÙðÒž¬z x¦Î‘kå¹å!gí­‡ ‹½¹ÚuŒrè©i7F&þ/Ž9¹c¸ZÎÇŸž©w× }ÅÎ+ekeúGxF´æH?upFö§öŽ›øÎ³SMBE%ÆÐe¹ä0Ã7®öô1^Ö®Þbl„UÂxoêºËëªø\ÿ`„(° Ÿâ5ð¦ú…¢òxÙ¥IQñoŒã×Ç§Ô {Ø^î¿Ô1ãyÄÀÁ¸qŠfœå¦d'Ø ÞæûÕsܶ©ˆ'cÊËÓ>™„•û¯H/Jú›sWãÖÌï*rŽ™el¶—,ÿqÐ9‡ö®€ÉMù}"vùÉ¡1Óy°tFrB]µ´™IÌw_t­üO-Ïk »4±IɵÚ}OáÛß迵÷rÒ^lm?ûGüe€¾/ 9•è½SþOö¬*¼r>-¦ßЉÒï³m0Ò¸l­ËIÛµw=5¸}|QËÌ8í§ê.¶žï׌]cË€lÎ_ŸÓ®ª­ i½ýcUœ|®XCÿÒýI°aU‘£º¥*¯ a§„èðm·ç«KÒüŠj½‘9êW]ô»æ\µçç‹0°ìòµüf¼¾DصûbŽßw 7vÏ âòe{5zå/‚«VŽYzà5¯õeT~Óq@0?„¶žO@|8úâ³Á¡5Ô5sG¶³s¾CT¦,m ì‡ÞD¡LU%9ϯ¤éâ\’túÇ"¨ø½bL«N¢ˆg—¾³æôi®/¸.9Ê¡dI¢0³LŠ l4™*×÷Ÿ-CD/îÞ•ŸéÛ…D .aÿ‚„7ÌÚ‡m@%+œýñ› qzM¾ÍHmââ?½¥0jÒjCÏ¡­„83–×ÌÃio¬ð4÷‹yìñcö–ž¿ÎÁˆt{k½_¼øx‘k`ë‚çD· äêd\eï8{qg±ÂËnv€cpÙ… ’²F×î{( â jþJW›=d '©÷®Ü©øÖiὩ…[Çüž$ä/ÆÊ±KN¯Ûå@/OTRô!þ5}ö:k'تøeó¸°¾™á‹Aº Ðïç ædðý­…ê±[„oóDþoüŒ·ªèk¬ñj-5îA ·Ž\#ò{ñ[×z¶°ôÀ*ÓKFOaÔÒÆÇ9¶*Ÿº÷7Øý0¯¯ïƒ{¾Þ¼ü>Ž[—#VO“D–¯â†Ç»û½â;iùýê_>†žËKyûEöx‡a@›A¼ýñe—~7:ÆŠVÓ/¦{štR«/2ý|)rÅU2—@9TÃì6o{Ó¡ßàÄ…fñ¦³¾‚Áyì†O ÿ—õ³è œÖ4£ñ’­kÎÊøÕcGš)MyþŽgcü`¡kÿ«i:­•/]Ñýöo€W}ÚžÙt!žõ(7ƒ"¬²ð ¼øþÔUÎÊ…ãªä\èh«¯#Mýud;±Žè¨AŽT ¿E÷_¯Ä¢ãïú1Æ~uJßÍÇË\GŰÃ~£CLòˆ«ÖóÇâkE–7ÝÄößÿ#Ù±’”:Gˆj[—ľ‡v(óqâ+ä|¶¶îúV%vHÛ‹¶?M¡ÎX½ñÃÌ–Ïúê ¯Ü_%ù/ÈÞ´Tׯ&$Ûú/xBl%a3N`« GͳzéDG1¦S6v´Þ¹‡í‡b¸à”ònoÔë¢?B†Å*Sdõø G o¡ûòѳŸRœ`kY_7÷Ä÷'EÖ~rs1®˜HÄãЯL+ƒz1O—¥磽hְ볺‰,â°Ã´¿çXM‡% ÀÖˆ* ›p;™ûL×µ¿2£ÿ?÷Ä–ëÃýƒrPÃ6C\ÛuOý”¨ÛÁ4UçÚh>Ëkê)~bøL¡—µu¬¾ºbþæàÀfÕ i,¬<)ÈvJ%}Ͱ¾žÉs;ôço0‹HØ}ï[]{»á0>{ÓRôçølN…·ýë# I÷é‰á<ÿ/¿|Ú-M o‚žéM+cü?/LtÄèÛÞ¤}~!Ë;P„]Î.¹ñ±p ˆ¥îF‹]¦ßj£ïu ‚ÞᣕÌv7lߦ´Z¨4Asà@‹ƒ]ƒNå);±ÍÛ¯¾³]Ú|žãåÖòxn¡h¼ a Š¡>òõæÁ ¿ [ñÕu Î7tq’Uó€¢ñ|ïr½hTmQ ­èšvÚ‹«ç?ÃæÃÙ›!r´ÿ0'mSi³tž®ÛL5UÙèCñE¯üÄ”_ òÝP»!"UɹMóì¼~ŽâAõÄö·Ö!ï¯?gsÛæ¬+xX3åxm€¸/èÇ¿¾Ôóê¡õáÞE.‹7‡C,‰‡žG9í7¯ñ—¢}73Ó—Ãêmp›äÕM f¯³&px²ì=` 2ÃoÝÕ_‡¼4Eáw2Çë ú|zƒýô¹’¿`x}¨ª"t;¦..súÎrç:b´ ¯¶·$E@WòÑÖï”Á Øbîè.½Ù¡æ{ Çû!Ç-€´æžsœ‡Ù 8 • ]»ÎC$‹°õŒüðÆ£m{ƒÑ,.žð¯FØî¦¼jäi6l+¹x>t5©ïÕ=r­½"]!ºî§h˜qí´ˆCÏ—mG¬ÍG|öÓtrG´5x{U¾bóÊáæ«ùt°Éu{Eü!¾xžÁ%Öp½&þ4÷û’ñ/w¹ˆù³µ®­Û€Ä㋾úB_ëá[[–‰Á©Â À`éz€F¾kpüºÚœSbXÿêP×€"€/ºêlb¡ÜñÍKÏ5cjÓŸc4æ/®üm¡*<ûZ¯îñrxu†—Û8•¨!†%'t|‡³ÈÅËÃÝ õ¾BuŸ§“×U×E¸!çÿ÷Ë fk~ã1N*¯feÝ]65EzH„Œ¯úk0¾¬a†VpëAg”É:…5D¯ud,MWá Íõ‹ í{ÖjHò=síö³æ±Ë-ý"èâíÿë‘vaÍÞñò1!Œ±å Æené#IA8³¡ÝêÉ·}±Ý iÛžN¶ðtÄq§ð>ßÜ (Tr­Ö†L 뢈Ckf ¢¼ÜO{ÆD¦Ø7Ò@>wWU?”;ËÂz¸¯1÷p5@qÒ¨cäK•úL°9£†„y¿îEÖüÎÿÔHŸëÅ‘×täˆo”4zùq¾0[Æj«ñœ½}ë |žÙ¤c[`‹ËoPFÎg¢ó] ŒM/C¸CÄÀÕ‰‘Çzò¤¯v }q>\ä5&§­XÕ•ÃÛ4g4í6­˜´ ©<´Ú,3‹Ð7<{@H…tdúrr]Æ@ªkNô›‚{:ÿ ôB®&j—ƒÖz÷uz½C8¬ýþ¨uÑêZ o«fh p[¼7”¬‹A“ç#ÈE\X5Ú<ÉII>‹ŽÃùaæ§PÌ0VFQdÙB¦€ÏOyÛ—ý)º WwÇmkŽ)V%"–h°¨æI²:Yu§_Ö ÀZ^Ù!SU¿GZ‡¾kWËž®Tú:[úŠ]3{˜|ˆ‹SæØ¸w“[Œ6—ædš+êP=ô± 8š/r7_™¥á`SŸÎµêÅ?ÌRσ‘ë” ®ã]7DqGM¯cNŽÀ´íÁõ|ä÷T´.¹®&¢áÏ?f·èÅ{.Ù!f\|Œä¼Ûz„¤öZŒ;r9éÀk»Ç|£¢b@º‡ëܹÁü|ì;G°Fœ7Þû½cç%Íôêêôå+Úô¦»–þc׊?ûa:Ê>!d$÷Lèósý˜1ýÎÈ¿>1­.s¬W×YÊãl5¶³ˆk+sû?ŽûuDŠ­[ÉkÙnÉ™~ ä[d窽ì®UÜËÇ(ý[øz-h½à„ÆûÅ ß›1,Œa¾åç_$ò¦•îŠßÛëÅfLçÈŽøIµ£gTÛxYŽýšÛTÙ/ªvÆcÄœ|?Õ @„Xåå5º}Ý€D*ðêf ‡áXÌ¢ç]Ÿ¡ÜÛßo>dZds2m˜“Ý›J73Ë„7þ£¤¹Pµ_Pň ‡ùÌFlcu­«\ÉñaÕõ…,µ´¦§"{¿CÀÁ÷2Ò`f º>©ÿ…BcmtÉľu W‰¹ |µµ«îâÆ7ŸA=ùßÿ+À ¶Þ°+’qTè„ÅÞ‡eX'Šž3Þ­š£~ûÔæà/'Nìã¼ÚÊÆ©Ñ¾UÀÉŒÿ¥=½¶ï9½1gÛíÕ«Rþáç¾½g =Æ{'âcÜÜ!®¡>tcLúI2Jñ¿}Jh²j>–‹¼´ñ0[úYîÍ»uA€Ï`­J’C5E¢®øt†ZÆVð*—OvE{:m\䨾zÛÃ;(±…P¢=;Ù&@æzÆÞõ¬†.aÇCì0vøÕsx›§>ËÑyv@öi¡¿ØbÚ¿ûVóÁxœÝ÷e¼¦Y¶#ÅÈx/' IÓCžî™ÓÔq}ò¶_m¬¹Ê^2ÓWgD>9c­^ËGßöìÁÀ˜‰´WÉ^w´pOåoŸ/{³Óû8»O3XkŒáXs¶P­QúÇÉâk4yqêÊËÀÉ+Æî‹›5 Ξ ýU6õà}ÏUÅË3Í[c¿:‡¥~ä2ð’®'TUÕŸöÞÈÙ½dòÊ}¨Ž_Òbú-_ e¨þÁaØ[«„äÓjh~î- wmEÊi=D×Ù!éG‘‹vöZÙ´Ówåd$¯„jõó› ”ÛS×S%êJ¤y²2êÛ$p\Ñ/¾á;¶›ST…†hñ÷µuõ šµ# eŽH8‰Y³sœ[\éNB:BüÍŒ¶ÞšFE1–}^%á+Ýýâü׿*—V-LâR›£þÚÍœ;€K7ç„",Æu°ÕøÝðN´šo ìm_ÛŽk÷Ÿÿõ?ý9t» ^}Ô,YzÙYwe|zð!±§]µáÝ~”mB!Ü2¹JBh¿_KåzÈZ»ÓGcµ]µSt;­L_U£ôÞEƒpÉÅ9ÒqUÈb¢Ã&¦›_#§€KL!9Á¿‡môÚhf}[;šÍó7îÚþA~¬Ì$ûû¨/žŸ¼’ë"†g䞛ǚû€7­’¯É}×\nBäØ',Qça³‹ÀqóáÒ¿# oCîݼ6f'æ8Mï0¦Ø³–½²zE¼¥ÿ¬K ³Ë'’ðr­ØçÕ.†›ôk®«bã ƶíããdøÆdÍ/ Çñ›ßWÏ~Šà•Ág4–ƒE‘òì¯~k>z â®Í Ö)—ÂiðšìÁœoýŒ³¼‘l†Y¤cIi0̌ӛû“&Ê:䀗ýwÝ>¤ÝO~µmÄ1Î׬9¶ÊÇóænšjŸ¥×‰óP2œÂ9 ‘¨åiÁiº¤; ÿ];èZŒ¼Ù¿°³Å¾Ú,ŒGùÊÍ-‹«¿1_œI´3ýç|­9Áùï}âéþž£‰ÛÀ /æjoM^}ÜãÚå ˆa=˶ë2PµúX3mûwv|Q,K±<)‰"=8îè´Ë88‹{þb/Â"Ic‘èH »÷Ó!È]½öíçÚ·k¤«–æ¨ -ÌÀ|Y]ÑBÜ‘Bf¯èîã$„|[•j¶!²’ÙöÜã(„|Q[‹¬ê3PåI^uˆÖ½GÞàX=Ü0J$ãÖZû¶=sÓyÛ‡´‡Û&C¹õ]àAí÷é‡+šüšŸæ~¼Ìy×ÃóC§PN¹7‘‚ËéËQŒU†•ÃXçLí¡³¦û@ÙœnïÉL/ãiï—A¿ÞiMáb½y‘ËÂÍ–~(œßÜæã! "¼ý‰T·æ˜Ï·3øqÔ–oìźöåýÇæôÚ›zû+@G¢¢©ÖXKѯ›‰QY¼T·d×ÿgr h4ôùña©ü½Ór!âêsQØo‰VN–ñÜ\Çõž¡´ž¬.¼¦ßØ-dãw3Õg¹Έ¨u·Å´#Xhðù–—>“Ò¡µ|Ÿˆi«ÎE¢‚#N-™%h1ÓTí.˜‹‡0ôp„Z€Nj”#â»ÖЊq1ó+r熤í6^‘©çè<ãßÅÎâ$2 ÓüDéâýÃCT#ùÓ$?¤öSÕ"TÓ¼,²g$Ñë`_#¥It2ú{°ºZ#Úæ§¬õ1½­ X[;ôÙ¤üRÞÝ+H$ÔW®ºûrShOÓÑkªmšvg½éÓI»¡Ø¸}Yv”êMQÙŽC~O“ñ³5/ÌnÕ‚a>>àVñ0·'¶¡/,xÙÌSßõWgäš7ŽÛté?¯Óû“ ¯˜ ŸEdÿÍr!»I\î­'‹bkÙE²µÔ†–Ê5§3Gùaã#¶iák}hm˜Úh-r0Ä¡WXdêÇéCNæÁß¹öK›øzÎÖ±±=£·Ó|Óy\1PüÖߌsËG»xálט½|ð“cÀ l‰IÈÙ™—0‡e¬Ú¡/T0Ú—ûl[cÚ %÷P$¿ôëávsEÝ{ò®Ü8>﯇}×!:}é<ÔKç–ÕÐ:˜£1U#,œ^Ùx½Tçù·&+GÎ^ {¨Üu«ãbáí78{óÆu2Ä WÛ\š‡aVWϺsˆËË’¨ÖßE±§geŠ·ÇÍE÷‘¯àÌuàéEŽãíýþJbùÿå"ôî|>qí+Jãí D.yÎÄØW•бªÊG÷ÓêG-z®ÿ®K=mÑ=ß!ÞüZ"¸mšñù°P¬>‰´£Âr²Æoõ‚”31PIDATÕõðˆ áéçdIÊK†C¦çæI<¿Wel¨·†•¹µÎ"Úÿ£ñ&^¿þ­_³ÉQ:Óú,¢ÆE_»L,”b¾´-pyÈǸ¢q‡®ŸÂ*_ª9 àæ–‘¶^] haY]ªE‘†÷2ôÕ%p1õ@ñ1­‚%å~ýÔä†Ïî‹Drá`Ná7k OkÀx×är ª¸Èñý“¶‹c#kƒÕZÒ:ùÒ.|,€æç:äÃ"Y¯€§ß!¿É×¾û6fq Z0ß°ŒûAÿp\t §ñ-„–n0QX)Ž'¼û­‡³C[-âåè«:Áhé]_ åäš\Ìj‘¡.‘·R*§{‹‹åj+æž3¬ÑÖöŒ‚mAŠXd‡WnÉ–'o.Å}æòHƒ—‰˜m¼Ô À êSC°_ a”ö‡'¡² ë$'ãÐú`ñwü¢ÿn&Uª­äó©bfƒÄ¬z1GxœuCtÙm «?ÿnªÃ-Ň«—·àA.¿®Îþæ`6*:rh¬J\hzg|x£lÝZQ.…,­ì¾¬‰û›­Íº^€?e–Åq|.væ77£!®Ñ,;Øúx`‚¼·/þí_ è¹-:_Ý ‰)N‹Ìà¶Š>½UP×´RTï›æâZèÇ”œÕ»ÙU3úzîHבµ|ÐÚ1ðî¨[7}|‡AûÞ1‹ÜLߨ J“¿]¼;Êwð‹«¹í¡–„ÅÚ¢W–²œ@4Žb…Œ÷ŸldV$•mêú²“ÆM&ÚûMW^6†ýØ´ii¡M6‹Ù?»…kVò›èÍ‘T.Ó0ª\i=(‰‚5©£E}9h™üÕ$UJ!_¹-çí ¬,͈g3l` Š|¬ém(L­,e&c°ô›ŸƒêfÔ›]¥tl-Üš#p{ÈËYô#c¾C_fÓiº¾g9y­ŒÏ꣑ëdkn>óÃŽöÐu›Ö#¾„b9ŒúqPÿÖ®ž*›CõêŽó(7&Zb}þúì× ƒ‚´„Ÿ_¿˜F(ŽóÇ5 ƒƒ ~¹ûæÑ˜j­I5ƒà½±9l)úÒN¹&;ɼuuzk6=\ãø¼¹þÌùÙ]õÓ7ÿà·D‘¸žÌÉD÷÷âÅ©øÈä$–cå¬Ûbªo•ι*/¤b&€s›˜þVîo+r©…¬ô„×aSì4ÆjN•¾÷0ÜCú5«ÌÇðZ.s mµûÆ –âýtÑ7BšÌg'è4‡ºXzNÔØþ·2>ßL”ËgpóqP1'_ööŸgó52C ò´›Wâj3¥–«‹.ösÎ'qRúg‹Hi::E[2ågoO©y'c­YyŸ´•‹Û+ªÿØÄõa1ørÖGLÕ”Ñêe½ÕÏ«ÊèæÀØ€ô»ÖŠžÑHØÅÈZ¾ë?Ü|RƸ°tªê¸µõË0Ó¶W"ó^5~èž'‚>‘6¦b›¿üñâûr Zª;õD±% L×õrÒ3­{´GÁ*ê±GFe`àÛ/ú0éj4Sm ô*aÅ·C ùBT[‡lX{»&5±6ͤµÃܲW¹<­mv ÝßsØâSétýªïˆ×a`#\Ìé+]#jt÷ð÷“€Ið ÿÍ•ãÕˆkèW‘Ñg&½ ŹôÛˆžôHþ±³k¿$·E*-’cÓS[ÔŠùB ×ÏUMm[A3x.ˆ›GVMà»@œ™LJ³½±@+_^B?ø6Ú¯ y¡{E°0¥)Y–R¤§˜Ó›ªjòåo)i/¶ß ^ømC"^rÏòu0*> ÝÁZÜÙ(¸gÛ õ0Ž,‚Û/Èä¬MôÂÕ÷âæ!‹Í™FNA®9„(К:jU jº›{ŸqH¿­¡è­Q‚õ?=fG@ÅIϱÍ6" ;X—>#7Ðf×yö«„·¬5®†ÞÕÀðr[áŸæHop– gë³vc¼HèR¥SÝKû܆!НÖg/9+DZõ,«§ã.hDJÍiœìë´ù¥ÐVb6}qØMðÏ–bÈ÷ù‡j š8ͩ㌲BÊàý^ò«‚RbäkÐÃÅkPÿŠ„œÌ52C×óÞltÑN}vؼŠStÎ|¿Y2"}%{ùß¼k×¾¥œþQ œD¥c¾ú¿æÍÆÑ{½Îw]¶ÎôËð&«Ýµ×Ú’}#×õ‘15ýdÿð°~sµ–è‡2(É3¶ÿö,jùdó²(Ú"$¢^’Á¾­¾Ú/#y¬"#ÛFŒÍÖK@Ðíú³ÐÚݯ}PoÎÓÅ6ã<¤ÖŠBÄ^ ý㣷¢ª…ö‹s@76¦uÊ9 ¡6§•¥X •Ldï^S†b—ú‰ÁåˆÅþ+9†È±ëBeddìC‚gç;TÉhâèHíÏÞ¤ýZSwÝ0/§i•ekÃ6…Ë¿ë¢ýãøçZ~Ç‹ñ¯ÃiL>Åy36oɹÎ;cêýaúÕ儯‚_ó<õ±ñ§ÆÑòÝ3E" Æ9 ËòÕÂóÒ±0èƒä3eE_Œ[7öEöeß[P<ñµõ:/}uóËØâ]ŽÑhÓ_àYø{©¨ÝèÑ8¶>tš{údO‹¾ òŸd÷NûpLgòìx°®ÖNÇõ„ÅüxŸþr[oCT[í+óZÐŽ9jÏRžbr­,sê_²Åc7×g—ݪ Y\”¼äa,«?ãæ†0L€r;~ö×x©7^ßÌ–O®Ì3‰]=ã:o~)˜ñø;düø©ríùægñÎÊPÆõÕú°.úóE•-¹jİx[§ºh§ogŽÅ'öýéfü[»gÓü訟/cÔ_\Áü#¶vº%®¡wd;܃ˆ2ñؼ,‰6B ë"zFÜ’UŽx別dŸP!軇勭Ÿ‚´‘ë‡Aü8”Fë ¶‹3íôÏö¢Èk—åð_Ñ´Ù†#K‹y\Qr¸¾‚—ÇVÄê·Êă”Ãá¨u¼ aÎ[öO<¿O€poLyå«­õÒn~ÇÛ4oöÏæû‰ ‚7;ÚàÖìvƒÍÚY³ê Þ "9;‹a‹‡ ¶ŸYƒX8†¨ßºK̬Æú¡…vhú4{k¿¹Qn%,Zÿá/TÉ1nèìç/ᇼJ zrU¼\·ëé‡-÷P,W.ÎUU[ô¼ìù﬩uð†ÒÍÉ,µýõ$DckU@; ­SÑíì{cBáf¦¼½ÃÔ¼œ_9‹ÿã BνՉ+ýõ)¼` Ö]å'ÏRëùS¥®•W—]³¬s…hßõ`¼5óEÿ8£Xt¾ÈLµvâe_9g‡‰8Û¶ÞóŠ‹ë­,ykO¬Þ@<]~‹ú®‡qLæe¿§>FûSpö÷ŸÊõ‰îYÇ-·oé»ûìâxg™ÝòÓOnïº+öåf”ò¶Ü_-­A FpÜ]ë-~&Ï®ÄÔ²6Ψy×Öåp ×€ êñò:ã¼V/ùæÂ·¸còcäng ²÷À«u’D»/5sG0fŸ­¹k•tôÅP¡´Ú0ö¬¼kTýjX÷˜™£¯¬Üw-¯²á¨YîÄx…Èü5tí^FhÆ!¾mš,F<µ9ŽÚ¢©þžÖí^R•t$õ협äÖ®gú f­o^ÚÅ8ªga]ê]ýè[“‘ûúYC/GÍ1{tXH–§~Ãu\hñy ýúJ}Îèði½ä„\¼§æ¼ë·Îúçþ&¥F>˜É¡{’šŸ°?íÖÀåx›6Vqû‚0ã]ÆpŽ•nѺqV÷¥“†X®=ƒœô4WŶ·^7büxp—iŒ'÷³Õ ßgÇé0{n £JäüçFYí‡ÄÔ¤|®æÝ¶TÏÍéQoÊ¿u_=,‚F–f÷¡Éڇ˟q¸Öýêè°»ÃQ7}sp>¢×ùîytðÛ“ |±‰C"ªI¼ÿ¶fTÒhÁcµ*¬Zìã¯Õ%ž…8´›Å¢ÈíaºÑ¬p.¾n›7 òÓ¸c=Ô‘“3T/ÍÛ,yðÐ÷ü£Þâ€* Jeµ eq‡•…Ñ€£×6ÙusŽ€$tÝÆŸêgKôëQts\£ŸÃÞµ¹x‹%ääû*ò3>­c5pÀHg]¸“«’Å×®d˜éÞ?¨Éfç’½oB#´·ZLûdÎZhpñ°Ó½ª<@²ãâå“tš—÷‹ C^Õnx­G3ƒ.€‚×\_I,5)¿ggÃÞ8h^ÀÕa@„–z¾õ4@YT;¹öTXÐÉÖ@Ú¾›²îŒßz1„µQì]¯úƒpSi]žœ7çãªØZ´†,•¬Y“Fq ˜<*ø~Š޼uï&}aoöÝJož‘SÊBe:}‡OcóåC5ÑzÃQíŒAs3Ò# iæ¨ L7YëÅ`5ÒÂMýìÊXŸ;Leæšýl<-¡ÖøÛì¶žÜLäe®3ÒÍ6®¢î8ÞV6#cƒxí‘@>œ_Óò÷¬Œ5Êœ…£,ÚêÐðj>‰.–îïáXyÁ”ÙKçÁ™p.ìz6Î&]Þ8¥ÇÆo9Ôô /ñöõ “›À¡ô0õϯ›¤Ö˜÷Ó}«µ/Ž1m²ðtµq¹û¢9gëÉ•æ Üåès3XþË£â?• ¾.êǯõê'ÎjCTÌwm+É‘ñbcŽ×­úÙ £×û8i«Ý®i1ÞË<è_,¥6íúË9b_ÆÝOš„|¿=-ðì†j ç&š«ö×&_môkåc¶Z"¯€‹oÎÚÇÙMÕÌÀöúðºùÉiÓµ‹š~¯¸‰"ŽxÞwÚçôÓ> 'Ï`v®Ê6ßþE®]“r!7Ýjù^‡“Š;Q´ù9HñV—÷ï¨Ú×äàÖÒ-Rƒ*äÈô«—æÂ¾5n‰«¨ÁöMf(¶΀뵻RsQ ùϵý) ó¡9_B½+gv_ïÇ{kgY§×VÝénä˜WK‰|sÏ*Øoº¶NÛãâB%u$¹¼ëßìúBÕޝùû∿vÏ‘­=k®ÞuRRÍ¥u²Q-ärÊYy°¡‡,>6ë\VsŒùÞóšëŸ¾1äê©%?;TÕÊWÛ÷hÊt¢ý+ú*r<]Ë[kêÇÙÕÜïksþüÐZÇæTéGj@µU/…¿c-ZS.¼ê6þÚ‰ÚQÝ×ò`ôªˆ®9UróŽs|4}ýóf󬿜5¹5Áà…5¤ýit~\vÎQ° †#¢^Æ®]lYiöÏv±$@Ûiþöí]Dµùï“Jç‹ôÀ#¯êcÜEV%Ôõ‡¶ßÖ ¯k9Ŷܿh%°Hƒk󤿺wÝmS²Uyµ™½9Q/^Ζ½w¸¾=̾°ác Gk—,wz~£ÿÖå‚bû‘†\v¬}GÅ;¤V ‡=ÀÌ®‚ÁŸÕP.ùÛW‡ßZÖ‘f]Cnöx©‚ÿö.­ÌOŽÓÅAŽš×è\.wZV…Ú÷–2}ó›¯öXÅã[} £!¬t U8ÇèªQ)gM¾=Ï»¯ñI»ò‡mdS¶þ¾{qÏŸ£kà0å!FKG£—8Å.,ÔÙqh®ÓŸlHóAï—{Ds%&²‡'‘o­µ`Ë·ÑÍN[ÿÓ`ýí/ƒ#CÿêÇ(«@ŸAè…õp3{|§Áá/#ë(„óÎô½§ÌjowŸÅ†"ø×ŽÊÑØç>ëÐ㺠R_Z9aм£áª¯æQ ´¶:Dæ=ã=øÐß&‹¡5;*ɼ*Åh ƒ#¶sãjsmôáZßÜ/¦QÄ6žk[w~J»GèRfC¯x¢”…'sÐÒxù#³Ïõ ý[%…3„êü6×7V6ŦçhÀÑZøiu@¨Ü–þ ðÕ#.;ŒLê›ëxýæmÙÄUÄ8 넬Lt¤py_I䟋¯Þõv­9ûO[Ôqt/±JågÝ´}ùëfq_#ÖöÆeeæksð8‚˜`ÌfBŸbã¢fhúûÂñâÒݺB®‡­ݸ² ¾k¾¹ ÿjÿ} +Ñ!,þ›ÄÖ Qª@¥É§…:J¨MéöVC(u-vDíši­î®²Ý¨‘c(„m¸ºÑêÌÑyÛÃ)¼¥ Óêðy?Zç¼­_—+gõ’(²ðÅlÎêm¢b‚°I›Gyø¢Í|°1¸Í áÔ0\åg¯ž¡¡5P3»zô—qý>}Í•Kçbõã Sœ5ñüíÓpAìÍ ùµG˱QÔ´ít#ŠHêÔ\ V¨'G5Š ,ïÂ1ãoh§ãÍÓ¿¯šb E›o®/bV’¯žh/‘ª&œëDLäýžêñË×ûD¬aL»ïòU)9¬·nâ§ÎºÃYXc!/·ŠV$seäI/ù~?2Í9 YÓ^µE¦úo+–@†JyqófEv*¸¹é[3×€fyt¹_Há.VAWµ›l>ôWKþé0jç }R7KÛòèAœ¾ÿã…뫵!$Fþ‚á6bÑÖœ·ùOç j_ìf*j»ÖUêûVK‡]{úÕ”[·[3ˆWyöS:js!Wgm•„…½Ì¬‰é<‡ºÈËÏQµ5çÖ|ÍG×`BFÀà½ÉÒ¦êe‡×ç_þ/öpº^‡(ªHSHס§(šÊöt¹Ôöß²ÌÐɆppÿ³rŽÐ}sg0Xx¯Dd1¸µæl>ÚÉчò’cCc¥™ßI7|~ÿÆÞ}{øvQä7_1†hf¬ÖÇK9¾™ð¬DåŠe¨Ÿbmå*öÔ¥×FdÃñ4ù[Õ\#='ŒlÁ›‡HNL<}8½ÿKC 9»¦Rº<´»á¸÷ô´áÇ„bêµøÕñ xó'~FãW'ñËÜìЊ)QÑ‘ù·Î«îaù´UðÍ>ןqEvû”YÈfNÝóª½ûºsè:á×D¯?Éx¯\õ§ikó*s'ö³®eû5âê²üvn9(éSñùïIµó¢íF‡§¯-ì±ÛÁõq^4ˆß8çz².+ú»Î°¼š,€<·®šGŸ½îí²!_øÛŒéê1V ïæ`úôܼ'ÓwÉe/Îj¿(­H¡ŒÕ\½¹I¥*èblÚÖnÝÕ¨gµ$eBO£Wƒ¸™'|ŒÈÕõŽ^ÿ<8˜AYpô›#¥‡ëLS$Ö¹5íÍ`ÞÕ¿ªˆ×¼õÍãÐ>ì¢~oA‚çp¬¤‘èö:å¤fŠ}u®` ôþU1g½J¯2"%¡” Ò~ª „Þ"èƒ| Ä"ˆÊ6¾¥ŒÌÀ|‹Óþ.Ü÷fÄ Ð÷ì1i2MÞ42QX¢„ÝÑLÊ&N¬]ZÈ N· uÂ×}T†Mã!PgQý”Üø>8qbµ€Àý»)ê×Îýý‡c ½£|…qŠøMÑ Ð]]´=ùŠó.Ec÷ãHGOOµ–\•Š4½ ÚÌÌùÓ`ß¼è>=gõçëƒÉuÑ\°lÍ)Çá;Öª5Â=ˆQ<¬û6‘<ï8¶Jû+NÕü0í'‡ïÅ›'BÛ\qöŽÿ¸TŒ&Dô¶øÕ:CdF–C{é®ÏØÞÂplh¥‡îÎŽãÙ¤ÉøóÐ(ÛÙŸœ“—ònjè¹N~ù‰*è›3ˆ‡\](ôé Žt]«î=_íþ¬”®‰Ù,àbî8U°µX þ(¹—0ø8sþ¹Øß¸|9¼õð[§ÇRÜŸ·{‹É›ÎFF³ë#&XÝzÓ£½Vœå§o—¨¦¼ª}y{=«µý8ʯ{úÉæÓêõÖ¾±„ÚŠ±'ô{X­Õ}àh_¯<».¦7kÖ˜¨~É·ùÝDeåO’YÏI û`Bc¨ñå°2`\Ðaó"íƒóó]·êµõòo¨åÇQ]ųïÉÀJŸ›[‡Z8MíU¨ý­îPUº{‹Yø’ÐNºÛ+ÑVÆTîËN­‘lgóÙ'¡êŸñó.2–Ã~ç½Ä&kêC»5–^ƒ»y3¾æ|…œ5±i÷Ð w¾û•3­| ÕQàEÊÃsŸƒŸ.ŽM=eºj½²[Û]aêk†Ø¼ƒ§ @'‘ˆ8GÃ.:ê»8±ÙBÏS ¯%Ñ»Y=Å»¸,ªñ{¤˜ ¼þ'3øyküºôKX|½_úÅnÜÍ•û|ƒ»›UX1¸|ÄÄÀOK\É&ýñÀø8ì’œ«‘˜ÇÓÌZîJ×4£¢®’Ÿ®D´»zéÝ…ÎA:â{z¯ß†äÔ þ~Y1ž­êaýpr|Â@X€]åYÿ™;çç¼µXÍ×cça‰»IIvÝì ÓÚÁ?ûCŒ»‡_A[\ ³µË<^L8~êL0ߦ\¼\…Ô‡‘°P Œ˜Û¹xn@X:ö_Í[åËQ÷vÕüˆd/pVà­?ä]T#¯‹ƒm@[F«I޶èœýd •㇤EpiãÈãï*WïËõÊ™\K3hÚ8‹ÛK‰†wè†ê:2W¾®°ž_Lc\ù¾³ÈB¹,ŽCÖãbŬ+!ùx­æZŠé¨g ^Ø> xˆÝ¬2Ð(³uìóÚÜ(öú¹e™TËÌ>+%×F°œ—;¶ß5<¯ä·FÌñ\¨räb¼ÐÉÍþ2Ä_ˆ`8\­—÷6ìrP>ж³~'Í/¡–ؼxÈÚ§?ÿßZkÞ»Íxî-'ÁG°ãcPLóp‰%Ó/ó@–]Hø„k'uCC¬‹¹jaÀw%æÜ›)\Óæ5Ch¼³½§%f0d}yL3߸4øæ/ÆPªY¸¯þÓtÀ±Ë_ÏïîfŽŒ,HN¬qúõ°PnˆÞˆÓaàýáø¹/½š#ùšÄ\›Ž\²@ŠÍ¥ufË7Ð/W¹ÆƒîÚá7©H¬À<°Å¿º‰á:U¡¶Îgµ‡q§íÖî-ªŸ¯¹lm*»†tmo¿1Îb&¼¸†±^Êâù5_±W)’vwpH Ϻbà«û» åuñ³¶¥¤^Ý,(…×¢.G½,¼þÆm{µrmºzÃÚúGŠï(ŽÉî§ãKzþ³ -ª n¦DW)Úûd>dÄÝÇ>_8H?]rØû¼Ò7_^ƒŽ‡¨üÌQÈÔ[h‡ì¬Yå`9ü] –ë:ŽçÌþ×üº#"A•ûÉ%‰‰)JöuÕõ©1ÄC_u{žêuVH©+4:«7ž2V!„¾ ö½yYâ|êhÁÍ›^¨²á=gFã¸?s±ìÖÇ×£T“Æpˆ Þñl-#‚ýì´‘n=åáA¦Ü”?bºŠ^ù?Š;W+>/¸å‡ƒÞí9^Éè…¥gT » ¢ØulC »<Â¥³øOÎÅZ+Ðù1ôR”dçÈ Hÿ" ½a‹ü›üÈ‹~Þ€  ]‘èðóx»[Àõ&¨Jaŵ¤b×`“M³Û$¾m„¹R²BÉ£ÂcIÂL¾8Œ>/.ÆcbÚYGÏ{–>ŸøÞÃdôOnÞ媒çO}ÉzÐÎÔ¾ÎÀwÒßúÂûÀÆ.Õ÷Ò¸‰‡NúBàÌ›y2–&ö³ùaôY†Ã7fèÊ›œÕ¹ðÊ-âŒÿonE¯/¥òŽDè$ ‹„z!ô‹Í&“I…hû2šlãÔËübhê‰]Cx´3¹.§MHŠæ«y«Ã¶Ç}ݬ‡-z°Ÿê C¾edKi=ùìÞZ»´ç꫊Ù9O»ú­»œ±yxcõÉó_~Ñ{Îïøö° 2€¼ã콇vݸ84²Nð_ßë¯7Æú-LÞ,—›sÚO¬Œ‘–{°ÅOzå|GÁZp¬!¸ÀëãÅaÔ/Ö÷5ÇL\kôùŠþøRwy°õ³5ɉƒ<ñmmŒ[Þ˜8íï‰+2p0ù’q»6UÈ¿µl¯?{„±•bÑ/–¹{"Uáï õWz+†à²Ù5£¸¾[rz"šGÆ-O6’ùⶆþŠbù5—fÛµ6rrh³Ü%´åc‡yMS¤`÷ o‚™Kz5­ ÛHÆ ýÂûDMLØEŠ=½|ƒÃÏâÙ)UMÇŠFÓ nófR7/Î'ãŸÚêfŒt}Z.Ëu`t@½Ù˜swâQdŽΫ1(¯ÿ»ÙwŒvk«÷q‡± ðá°šÐ^|Ö Uq€);ƪB®ëëÅ܃àaªgã?ÿýQ„šó”‹¨9à'Õèõ°¸™K¤ò¿ë<{ƒaÛX¯^ω1×E÷,vö¸–XZ'XÊH‡#îƒVu'˜hŽd¼ööº¨—¦Øo9o­¡VDJñ!öÆsÏDÚ({1¤¿×kÙþB÷äîÌ¡AÝUOrÕbé$„¤9ÁÙæNœUÎÖ¶ãÝúvô½›W!­øâpZ7>¹áÍ"Å!þyÓé*ð­Ý`þ­_—¿¦ÆÔò«9Û>PUÿxs´ùýÅ­LLWÄâ:øê‡ú]`3äp[§xRÖµd¼‹é&­=\í•>¯åäòÆ`rÇàïÀ°`ˆå`“YÇ›;»Ÿ¿*‰½$­¹7„,¯*Bˆwëa4‰¨…ê?tÒØ ¸ü)¾ˆLdÎJ©AiÞ©7rIÎÞå^ õªj„[>8<³Ÿÿ:’ѯ-‰=e¯ÆOµßvC0»O³ú‹‚Æ$“î Í2­6en™p¶VS-«Œò,ÃwÖÚa#1[qò5žrºsp²»'ÉɸËJœ§q™ÖÒvc¢6йñ.,«*>›<Ú)ðü]À S\ÎúÍ’þªóð=ŒIqÛ´trúço¾<ÊuSÂá4…æ…ûÅ‚?Ó~1Ïž¾›FpM]5¶êBMž:dA¸UºÄ4^u—µ~´CŒêO€¨šœÕI/JkgÏŒ×O¬F Øìhc_ldvw}ñ߸j¢ £¿XNk$îÕìoÜt¼ØÐ‰É72œð Ä› ‹Ë/ßйkÁyzÐTT4jg޶ôJ½Rèwxiÿ6•·¼`ì¿5p¸ã¡£>ÏqêüñæLÏKÊNÐWEèºïB¥}›lòƒë }ì¯Tßÿ^ÛÖ ¯Ù ,Ç8§qM F1Î AT9é¿»Ò·7Àšò:ßomÌ/²yÔ‰Þ°?qÛÖvW‹µ4#;ay!+ù|"ôç« j3Pª6ÕF¾¯_Ê@zô7ÚúøÿÊþû/;¦»k5Ù¿qˆÕcÏ…åýøÔí¹è0à—Ëjð,‹›N³–ó‹sõ2b7£{EJ[aÔôÔî`éikg[«¤_é×ãð¤:ÖÄXzx ë6lJÈé;«eé1°ö-ÚôÊl˜Ñ»¨ ¯udßÓƒ2ïFï¾0´Ý þ&¢Ÿrm3!ì%fàl?þ78'Ÿ¶ã“¼©™›9NÞÊÈ|P1¾©Õð‚¸‹ïÜT;k1ŒÆÙkk£œ”?Nå·ÍúëÐPwúìµ°OæâõGs2¢oŒÕ‹.F1Ø•‰ÝËKÎ]^p>`iOý’`3WpíºÍʉ¢•Ûo,bu£q9"°_½”·-o>} õÍ©è[ÌÁǧ4¬¶ß$Ù)G@| vÀ]ò*ævð2÷]FDû3\ÞUèѽ÷÷è]œýÚjÞV (›ý“G#†‹¾üÕ·˜Åt1Ûî•ÍÜˬ¿§³“Çæ¼r¶ àý…§LP\Há¸[ZŸ}J>³W[{½äz|6òG>*jõÅ ¶<œOqåÈÈöéºa<pŒY9a¶üÕ2wC&Ò¸QÓ¥cçi©ýzÝ8IÞpkfTp|»}cFàˆŽþ΂˜c}uƒL½›ÒßÉÈ>ë?Œ­ñ1OãÒÿ¦ÐäO¿óx52ÎlqÔž÷ÿy¨ `Ü›Çxð’1ÿ5ŒnsŒý|’ï{)ëÚ¤@é¯P]·Évã·ÿbyÜK)ö鬊biEްdÄ-ž+ŒÔ"›šÃÝX~±Ö¸'[»éþÙWP>”~~º`/7gWs÷…ËÞ˜™OëæïCý1êG{zsÔiþ‡ºñÞ¼ö­sZëí;w8'ÚtŒ°û þ:ߨ”o‹5²xÔàÏu™øæÚ1ªo\@z…RLÙ£x33~mZ£P1&Ï´Ëå,V1VA¥>Ø;Ⱥ¤A¡Ü6Í/rÇܦˆÆh89ÆFðl”;]ÓÚ½u>\yñ+ÞÁਸ਼zÖvòIqÒú]?ªšç{y•¹Øxß^W’µÅI9èÚ¨G®$þr>³)ÛŽÆ"Z>dę̻јÞBˆß\œîÏ~-óLˆ¼‘<;åþ¢71Àe¦—ÚóË…bMö×ANo–4a·Vï©õÐÊ0ûpÁ3¼[=ôëëSÿ Hëâr”ìÍÂÐûÊÏÿ0öîšlËy54çè.ÖÝG›°éó_H°çôõ!­úõ¯ŠO‡Á[EWG+!5«*ëõK¤ÖùiA3fíj‘”}o*õÌèW»ôÒÜ?†¡õ*cMÆî™Î­ï"º^·ÆP™¶{´ö^>>ͼjŠÜ®í?/Ëc¾µ™ÿ²죸Fï›-Ï“áÅå¡öìþÃï¦b²à G ‡%d0öÄ€^‚FNJ±É rÿÛŒûm›ZPØßC‡°Môe2„ǽ~ê·‚‡‹Yñ9ùBxò"Ò'Æm[¹"›îżþöÉ<~é‹6P]œÉ›h’ ˜^Ø¢¥Ö Õ› †—;Ma£¼<Ò{©.gÏæmdM ñ¬µrÙ^ž4“Iýøç¡¯!$s𵜼PÃ!JÆñq£ùˆm»xlBj¯…ÒPø•Û‘uZ¡7NòV½O@gÓe“âÔT÷=Ê:+¼Ýºm.F5yÆ[šKùKÖB’èü?gmëú‘°ÉÕüíŠnÁê• Í«‚#åFˆþÑ>ÍW»Ç;zÄÊbt_DD[.cý«›~ñ/ám߬ÐmñèÜÎû%óå¥Åÿ÷®òôÅb[>°p>ÍQO»£X“¼»hn,‡]ó/ÕUŒ¯‡Ùà^yžØ¹»q,Ƨ²Òꬅµ^}ÈW:íø±Hf6^Kc”p±¤Îž¤„¶+˜}Ù©bS²¾([ýóñi‹òÚ6o5­ÉÇ s:/{2à“)Áèš“&Å–GnRöú“¦8‚BÙL¤?Kâ±taãlŠƒã£È_=i‡óX·_[ã7÷òu7.YMO}Û‚ü|(ÿ§Oô̱mÄÖÂLs~„ƒ;¾ßŸÆJˆ],†µ¼õÿ1šc¾1؃0'åÆr›14 Õ}í·fÄUmiý;8ì ·,õs±¯2ó­ý¶å¾ûÎ…“!æìÛŒÃíY½üâl|¬/(öÖ°eŒA×¹¹ñcz³+„+‰ÚC`#µúqž„!¦;ßtA±ád_t P²c*ÕÕ ÎŒgúóÊZ–ÅûÚžÆìݽýøjµYȽüÂÂKöú÷>¿Ô5ǺÈ~€‘T¿Š‚ðºØ­§L¥l;××{:Î*Uð×ééTC4­íêk]pmÐà²Ë~×Ûó†ÎDÕ8æoF ©iØðä1ÛWGE¶ÅzæÞ½ìT°!{–õ=—Ï…rZ×ñ6YE$÷¬ÆÝøÓæ¨n˜—÷,d3¾õ†wœ ã„ðÆÆÙwOóYa+WÒ|_,hHM$¬l9_?Œt¦s÷¯`iûpºOázä ó.Ñxel9žy&dùásÅ3ÌÙo’Y8w9ˆ'ÚÆ”à¾Ê 5Ç&äÊ£ÐrºÈÛæ‡ÆÖ*Ë—ˆ£>îb5_±àš®Ï¯ÞJö"BÖw•ÍÆhX‚åkt7öã›Y.D¼\r™‰öl @t·0#ƒgQì!ØD¿i–Ûºƒ9\ö³G\èã9»qʸhÌÎÙÑMÚ:°ÇÄÈ­¥rÞv8vN}yi£X®ìeP‹æ›ÑèùáJÎ,Ïùø±q¼&Oì„,Jlw9/:šÒ(Ú'*ÖÆ…P.쬖ìÈLöâÐl:ñ¬¿gµx&#€Á~Qjã|müÁhÆcXó]¼'ÛE—Ë€¯ý¸‡“k×AÎNÑænNnbZãAÈe~‚†`_Lå­r?sûÚ²ëÏ´2÷¦I â\k}Å}WwOÌ‘ˆƒ—“yQýÖüü7:cJ'NˆÇW‹ÍŒì3gÞûL€sîC¯ïdóbäͧ]«Qõh¡âl6ÑÖm³Pc.|ÚôM§y$»ÀÛ„4!<™»ØÔ´1Ò®Í3giüñÞ¿b ë_·“§Ð5aÿ§Ã5#ùç„h/–îÁ§ÏÒ‚a¦2Åj숊M¤•óµ:í>©|æórÐÌíõLJÔö}°"@¿¢´{qg'ŸÚÙmŽØÍ©Ã(ùj±¯ãöÏÿý´¡ã5XÖ.}IEND®B`‚photutils-0.7.2/docs/psf_spec/block_template.rst0000644000214200020070000000264713547426552024235 0ustar lbradleySTSCI\science00000000000000:orphan: BlockClassName ============== [Link to code if it exists] A single sentence summarizing this block. A longer descrption. Can be multiple paragraphs. You can link to other things like `photutils.background`. Parameters ---------- first_parameter_name : `~astropy.table.Table` Description of first input second_parameter_name : SomeOtherType Description of second input (if any) Returns ------- first_return : `~astropy.table.Table` Description of the first thing this block outputs. second_return Many blocks will only return one object, but if more things are returned they can be described here (e.g., in python this is ``first, second = some_function(...)``) Methods ------- Not all blocks will have these, but if desired some blocks can have methods that let you do something other than just running the block. E.g:: some_block = BlockClassName() output = some_block(input1, input2, ...) # this is what is documented above result = some_block.method_name(...) #this is documented here method_name ^^^^^^^^^^^ Description of method Parameters """""""""" first_parameter : type Description ... second_parameter : type Description ... Returns """"""" first_return : type Description ... Example Usage ------------- An example of *using* the block should be provided. This needs to be after a ``::`` in the rst and indented:: print("This is example code") photutils-0.7.2/docs/psf_spec/culler_and_ender.rst0000644000214200020070000000266113547426552024531 0ustar lbradleySTSCI\science00000000000000CullerAndEnder ============== EJT: No currently existing code in `photutils`. A single sentence summarizing this block. A longer descrption. Can be multiple paragraphs. You can link to other things like `photutils.background`. Parameters ---------- first_parameter_name : `~astropy.table.Table` Description of first input second_parameter_name : SomeOtherType Description of second input (if any) Returns ------- first_return : `~astropy.table.Table` Description of the first thing this block outputs. second_return Many blocks will only return one object, but if more things are returned they can be described here (e.g., in python this is ``first, second = some_function(...)``) Methods ------- Not all blocks will have these, but if desired some blocks can have methods that let you do something other than just running the block. E.g:: some_block = BlockClassName() output = some_block(input1, input2, ...) # this is what is documented above result = some_block.method_name(...) #this is documented here method_name ^^^^^^^^^^^ Description of method Parameters """""""""" first_parameter : type Description ... second_parameter : type Description ... Returns """"""" first_return : type Description ... Example Usage ------------- An example of *using* the block should be provided. This needs to be after a ``::`` in the rst and indented:: print("This is example code") photutils-0.7.2/docs/psf_spec/finder.rst0000644000214200020070000000305213547426552022506 0ustar lbradleySTSCI\science00000000000000ObjectFinder ============ EJT: Existing code documented at https://photutils.readthedocs.io/en/stable/api/photutils.detection.StarFinderBase.html - see the ``find_stars`` function for the basic API. A single sentence summarizing this block. A longer descrption. Can be multiple paragraphs. You can link to other things like `photutils.background`. Parameters ---------- first_parameter_name : `~astropy.table.Table` Description of first input second_parameter_name : SomeOtherType Description of second input (if any) Returns ------- first_return : `~astropy.table.Table` Description of the first thing this block outputs. second_return Many blocks will only return one object, but if more things are returned they can be described here (e.g., in python this is ``first, second = some_function(...)``) Methods ------- Not all blocks will have these, but if desired some blocks can have methods that let you do something other than just running the block. E.g:: some_block = BlockClassName() output = some_block(input1, input2, ...) # this is what is documented above result = some_block.method_name(...) #this is documented here method_name ^^^^^^^^^^^ Description of method Parameters """""""""" first_parameter : type Description ... second_parameter : type Description ... Returns """"""" first_return : type Description ... Example Usage ------------- An example of *using* the block should be provided. This needs to be after a ``::`` in the rst and indented:: print("This is example code") photutils-0.7.2/docs/psf_spec/fitter.rst0000644000214200020070000000060113547426552022531 0ustar lbradleySTSCI\science00000000000000Fitter ====== The fitter block is unique in that it is a class not implemented as part of `photutils`. Rather, it is an object that follows the iterface for fitters in the `astropy.modeling` package. Note that implicitly the fitters for PSF photometry are always fitters appropriate for *2D* models (i.e., 2 input dimensions for the x and y pixel coordinates and a "flux" output). photutils-0.7.2/docs/psf_spec/group_maker.rst0000644000214200020070000000331613547426552023555 0ustar lbradleySTSCI\science00000000000000GroupMaker ========== EJT: Documented as the ``__call__`` method of ``GroupStarsBase`` - see https://photutils.readthedocs.io/en/stable/api/photutils.psf.groupstars.GroupStarsBase.html It'll be substantial work to re-design the photometry loops if this is changed in a backwards-incompatible manner, but of course that's possible if there's a good reason for it. A single sentence summarizing this block. A longer descrption. Can be multiple paragraphs. You can link to other things like `photutils.background`. Parameters ---------- first_parameter_name : `~astropy.table.Table` Description of first input second_parameter_name : SomeOtherType Description of second input (if any) Returns ------- first_return : `~astropy.table.Table` Description of the first thing this block outputs. second_return Many blocks will only return one object, but if more things are returned they can be described here (e.g., in python this is ``first, second = some_function(...)``) Methods ------- Not all blocks will have these, but if desired some blocks can have methods that let you do something other than just running the block. E.g:: some_block = BlockClassName() output = some_block(input1, input2, ...) # this is what is documented above result = some_block.method_name(...) #this is documented here method_name ^^^^^^^^^^^ Description of method Parameters """""""""" first_parameter : type Description ... second_parameter : type Description ... Returns """"""" first_return : type Description ... Example Usage ------------- An example of *using* the block should be provided. This needs to be after a ``::`` in the rst and indented:: print("This is example code") photutils-0.7.2/docs/psf_spec/index.rst0000644000214200020070000000055613547426552022354 0ustar lbradleySTSCI\science00000000000000:orphan: PSF Photometry Block Diagram Specification ========================================== The block diagram: .. image:: block_diagram.png Blocks ------ .. toctree:: :maxdepth: 1 background_estimator block_template culler_and_ender finder fitter group_maker noise_data psf_model scene_maker single_object_model photutils-0.7.2/docs/psf_spec/noise_data.rst0000644000214200020070000000265113547426552023351 0ustar lbradleySTSCI\science00000000000000NoiseModel ========== EJT: No currently existing code in `photutils`. A single sentence summarizing this block. A longer descrption. Can be multiple paragraphs. You can link to other things like `photutils.background`. Parameters ---------- first_parameter_name : `~astropy.table.Table` Description of first input second_parameter_name : SomeOtherType Description of second input (if any) Returns ------- first_return : `~astropy.table.Table` Description of the first thing this block outputs. second_return Many blocks will only return one object, but if more things are returned they can be described here (e.g., in python this is ``first, second = some_function(...)``) Methods ------- Not all blocks will have these, but if desired some blocks can have methods that let you do something other than just running the block. E.g:: some_block = BlockClassName() output = some_block(input1, input2, ...) # this is what is documented above result = some_block.method_name(...) #this is documented here method_name ^^^^^^^^^^^ Description of method Parameters """""""""" first_parameter : type Description ... second_parameter : type Description ... Returns """"""" first_return : type Description ... Example Usage ------------- An example of *using* the block should be provided. This needs to be after a ``::`` in the rst and indented:: print("This is example code") photutils-0.7.2/docs/psf_spec/psf_model.rst0000644000214200020070000000356013547426552023213 0ustar lbradleySTSCI\science00000000000000PsfModel ======== EJT: the PSF models in the current ``photutils.psf`` are not explicitly defined as a specific class, but any 2D model (inputs: x,y, output: flux) can be considered a PSF Model. The `~photutils.psf.PRFAdapter` class is the clearest application specific example, however, and demonstrates the required convention for *names* of the PSF model's parameters. Hopefully that class can be used *directly* as this block, as it is meant to wrap any arbitrary other models to make it compatible with the machinery. A single sentence summarizing this block. A longer descrption. Can be multiple paragraphs. You can link to other things like `photutils.background`. Parameters ---------- first_parameter_name : `~astropy.table.Table` Description of first input second_parameter_name : SomeOtherType Description of second input (if any) Returns ------- first_return : `~astropy.table.Table` Description of the first thing this block outputs. second_return Many blocks will only return one object, but if more things are returned they can be described here (e.g., in python this is ``first, second = some_function(...)``) Methods ------- Not all blocks will have these, but if desired some blocks can have methods that let you do something other than just running the block. E.g:: some_block = BlockClassName() output = some_block(input1, input2, ...) # this is what is documented above result = some_block.method_name(...) #this is documented here method_name ^^^^^^^^^^^ Description of method Parameters """""""""" first_parameter : type Description ... second_parameter : type Description ... Returns """"""" first_return : type Description ... Example Usage ------------- An example of *using* the block should be provided. This needs to be after a ``::`` in the rst and indented:: print("This is example code") photutils-0.7.2/docs/psf_spec/scene_maker.rst0000644000214200020070000000317413547426552023520 0ustar lbradleySTSCI\science00000000000000SceneMaker ========== EJT: This object is not currently in the block diagram, as it represents a step beyond the "baseline" PSF fitting machinery. It should be developed in parallel with the ``SingleObjectModel``, which really doesn't have reason to exist without the scene maker. A single sentence summarizing this block. A longer descrption. Can be multiple paragraphs. You can link to other things like `photutils.background`. Parameters ---------- first_parameter_name : `~astropy.table.Table` Description of first input second_parameter_name : SomeOtherType Description of second input (if any) Returns ------- first_return : `~astropy.table.Table` Description of the first thing this block outputs. second_return Many blocks will only return one object, but if more things are returned they can be described here (e.g., in python this is ``first, second = some_function(...)``) Methods ------- Not all blocks will have these, but if desired some blocks can have methods that let you do something other than just running the block. E.g:: some_block = BlockClassName() output = some_block(input1, input2, ...) # this is what is documented above result = some_block.method_name(...) #this is documented here method_name ^^^^^^^^^^^ Description of method Parameters """""""""" first_parameter : type Description ... second_parameter : type Description ... Returns """"""" first_return : type Description ... Example Usage ------------- An example of *using* the block should be provided. This needs to be after a ``::`` in the rst and indented:: print("This is example code") photutils-0.7.2/docs/psf_spec/single_object_model.rst0000644000214200020070000000373313547426552025234 0ustar lbradleySTSCI\science00000000000000SingleObjectModel ================= EJT: This does not exist in the current `photutils.psf` model, because there is not an explicit separate single object model. Instead the psf_model is used directly, as the "single object model" is implicitly a delta function. To maintain backwards-compatibility, the new ``SingleObjectModel`` will need to default to the "point source" object model, and behave the same as the current behavior of a model with shape parameters is provided as the "psf model". But arguable that is *not* the desired behavior in the "new" paradigm that combines the ``SceneMaker``and the ``SingleObjectModel``. A single sentence summarizing this block. A longer descrption. Can be multiple paragraphs. You can link to other things like `photutils.background`. Parameters ---------- first_parameter_name : `~astropy.table.Table` Description of first input second_parameter_name : SomeOtherType Description of second input (if any) Returns ------- first_return : `~astropy.table.Table` Description of the first thing this block outputs. second_return Many blocks will only return one object, but if more things are returned they can be described here (e.g., in python this is ``first, second = some_function(...)``) Methods ------- Not all blocks will have these, but if desired some blocks can have methods that let you do something other than just running the block. E.g:: some_block = BlockClassName() output = some_block(input1, input2, ...) # this is what is documented above result = some_block.method_name(...) #this is documented here method_name ^^^^^^^^^^^ Description of method Parameters """""""""" first_parameter : type Description ... second_parameter : type Description ... Returns """"""" first_return : type Description ... Example Usage ------------- An example of *using* the block should be provided. This needs to be after a ``::`` in the rst and indented:: print("This is example code") photutils-0.7.2/docs/rtd_requirements.txt0000644000214200020070000000003213563423715023027 0ustar lbradleySTSCI\science00000000000000matplotlib<3.1 sphinx>2.* photutils-0.7.2/docs/segmentation.rst0000644000214200020070000007122613563423715022136 0ustar lbradleySTSCI\science00000000000000.. _image_segmentation: Image Segmentation (`photutils.segmentation`) ============================================= Introduction ------------ Photutils includes a general-use function to detect sources (both point-like and extended) in an image using a process called `image segmentation `_ in the `computer vision `_ field. After detecting sources using image segmentation, we can then measure their photometry, centroids, and morphological properties by using additional tools in Photutils. Source Extraction Using Image Segmentation ------------------------------------------ Photutils provides tools to detect astronomical sources using image segmentation, which is a process of assigning a label to every pixel in an image such that pixels with the same label are part of the same source. The segmentation procedure implemented in Photutils is called the threshold method, where detected sources must have a minimum number of connected pixels that are each greater than a specified threshold value in an image. The threshold level is usually defined at some multiple of the background noise (sigma) above the background. The image can also be filtered before thresholding to smooth the noise and maximize the detectability of objects with a shape similar to the filter kernel. Let's start by detecting sources in a synthetic image provided by the `photutils.datasets `_ module:: >>> from photutils.datasets import make_100gaussians_image >>> data = make_100gaussians_image() The source segmentation/extraction is performed using the :func:`~photutils.segmentation.detect_sources` function. We will use a convenience function called :func:`~photutils.detection.detect_threshold` to produce a 2D detection threshold image using simple sigma-clipped statistics to estimate the background level and RMS. The threshold level is calculated using the ``nsigma`` input as the number of standard deviations (per pixel) above the background. Here we generate a simple threshold at 2 sigma (per pixel) above the background:: >>> from photutils import detect_threshold >>> threshold = detect_threshold(data, nsigma=2.) For more sophisticated analyses, one should generate a 2D background and background-only error image (e.g., from your data reduction or by using :class:`~photutils.background.Background2D`). In that case, a 2-sigma threshold image is simply:: >>> threshold = bkg + (2.0 * bkg_rms) # doctest: +SKIP Note that if the threshold includes the background level (as above), then the image input into :func:`~photutils.segmentation.detect_sources` should *not* be background subtracted. In other words, the input threshold value(s) are compared directly to the input image. Because the threshold returned by :func:`~photutils.detection.detect_threshold` includes the background, we do not subtract the background from the data here. Let's find sources that have 5 connected pixels that are each greater than the corresponding pixel-wise ``threshold`` level defined above (i.e. 2 sigma per pixel above the background noise). Note that by default "connected pixels" means "8-connected" pixels, where pixels touch along their edges or corners. One can also use "4-connected" pixels that touch only along their edges by setting ``connectivity=4`` in :func:`~photutils.segmentation.detect_sources`. We will also input a 2D circular Gaussian kernel with a FWHM of 3 pixels to smooth the image some prior to thresholding: .. doctest-requires:: scipy >>> from astropy.convolution import Gaussian2DKernel >>> from astropy.stats import gaussian_fwhm_to_sigma >>> from photutils import detect_sources >>> sigma = 3.0 * gaussian_fwhm_to_sigma # FWHM = 3. >>> kernel = Gaussian2DKernel(sigma, x_size=3, y_size=3) >>> kernel.normalize() >>> segm = detect_sources(data, threshold, npixels=5, filter_kernel=kernel) The result is a :class:`~photutils.segmentation.SegmentationImage` object with the same shape as the data, where detected sources are labeled by different positive integer values. A value of zero is always reserved for the background. Let's plot both the image and the segmentation image showing the detected sources: .. doctest-skip:: >>> import numpy as np >>> import matplotlib.pyplot as plt >>> from astropy.visualization import SqrtStretch >>> from astropy.visualization.mpl_normalize import ImageNormalize >>> norm = ImageNormalize(stretch=SqrtStretch()) >>> fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 12.5)) >>> ax1.imshow(data, origin='lower', cmap='Greys_r', norm=norm) >>> ax1.set_title('Data') >>> cmap = segm.make_cmap(random_state=12345) >>> ax2.imshow(segm, origin='lower', cmap=cmap) >>> ax2.set_title('Segmentation Image') .. plot:: import numpy as np import matplotlib.pyplot as plt from astropy.stats import gaussian_fwhm_to_sigma from astropy.convolution import Gaussian2DKernel from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize from photutils.datasets import make_100gaussians_image from photutils import detect_threshold, detect_sources data = make_100gaussians_image() threshold = detect_threshold(data, nsigma=2.) sigma = 3.0 * gaussian_fwhm_to_sigma # FWHM = 3. kernel = Gaussian2DKernel(sigma, x_size=3, y_size=3) kernel.normalize() segm = detect_sources(data, threshold, npixels=5, filter_kernel=kernel) norm = ImageNormalize(stretch=SqrtStretch()) fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 12.5)) ax1.imshow(data, origin='lower', cmap='Greys_r', norm=norm) ax1.set_title('Data') cmap = segm.make_cmap(random_state=12345) ax2.imshow(segm, origin='lower', cmap=cmap) ax2.set_title('Segmentation Image') plt.tight_layout() When the segmentation image is generated using image thresholding (e.g., using :func:`~photutils.segmentation.detect_sources`), the source segments represent the isophotal footprint of each source. Source Deblending ----------------- In the example above, overlapping sources are detected as single sources. Separating those sources requires a deblending procedure, such as a multi-thresholding technique used by `SExtractor `_. Photutils provides a :func:`~photutils.segmentation.deblend_sources` function that deblends sources uses a combination of multi-thresholding and `watershed segmentation `_. Note that in order to deblend sources, they must be separated enough such that there is a saddle between them. The amount of deblending can be controlled with the two :func:`~photutils.segmentation.deblend_sources` keywords ``nlevels`` and ``contrast``. ``nlevels`` is the number of multi-thresholding levels to use. ``contrast`` is the fraction of the total source flux that a local peak must have to be considered as a separate object. Here's a simple example of source deblending: .. doctest-requires:: scipy, skimage >>> from photutils import deblend_sources >>> segm_deblend = deblend_sources(data, segm, npixels=5, ... filter_kernel=kernel, nlevels=32, ... contrast=0.001) where ``segm`` is the :class:`~photutils.segmentation.SegmentationImage` that was generated by :func:`~photutils.segmentation.detect_sources`. Note that the ``npixels`` and ``filter_kernel`` input values should match those used in :func:`~photutils.segmentation.detect_sources` to generate ``segm``. The result is a new :class:`~photutils.segmentation.SegmentationImage` object containing the deblended segmentation image: .. plot:: import numpy as np import matplotlib.pyplot as plt from astropy.stats import gaussian_fwhm_to_sigma from astropy.convolution import Gaussian2DKernel from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize from photutils.datasets import make_100gaussians_image from photutils import detect_threshold, detect_sources, deblend_sources data = make_100gaussians_image() threshold = detect_threshold(data, nsigma=2.) sigma = 3.0 * gaussian_fwhm_to_sigma # FWHM = 3. kernel = Gaussian2DKernel(sigma, x_size=3, y_size=3) kernel.normalize() segm = detect_sources(data, threshold, npixels=5, filter_kernel=kernel) segm_deblend = deblend_sources(data, segm, npixels=5, filter_kernel=kernel) norm = ImageNormalize(stretch=SqrtStretch()) fig, ax = plt.subplots(1, 1, figsize=(10, 6.5)) cmap = segm_deblend.make_cmap(random_state=12345) ax.imshow(segm_deblend, origin='lower', cmap=cmap) ax.set_title('Deblended Segmentation Image') plt.tight_layout() Let's plot one of the deblended sources: .. plot:: import numpy as np import matplotlib.pyplot as plt from astropy.stats import gaussian_fwhm_to_sigma from astropy.convolution import Gaussian2DKernel from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize from photutils.datasets import make_100gaussians_image from photutils import detect_threshold, detect_sources, deblend_sources data = make_100gaussians_image() threshold = detect_threshold(data, nsigma=2.) sigma = 3.0 * gaussian_fwhm_to_sigma # FWHM = 3. kernel = Gaussian2DKernel(sigma, x_size=3, y_size=3) kernel.normalize() segm = detect_sources(data, threshold, npixels=5, filter_kernel=kernel) segm_deblend = deblend_sources(data, segm, npixels=5, filter_kernel=kernel) fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(10, 4)) slc = (slice(273, 297), slice(425, 444)) ax1.imshow(data[slc], origin='lower') ax1.set_title('Data') cmap1 = segm.make_cmap(random_state=123) ax2.imshow(segm.data[slc], origin='lower', cmap=cmap1) ax2.set_title('Original Segment') cmap2 = segm_deblend.make_cmap(random_state=123) ax3.imshow(segm_deblend.data[slc], origin='lower', cmap=cmap2) ax3.set_title('Deblended Segments') plt.tight_layout() Modifying a Segmentation Image ------------------------------ The :class:`~photutils.segmentation.SegmentationImage` object provides several methods that can be used to visualize or modify itself (e.g., combining labels, removing labels, removing border segments) prior to measuring source photometry and other source properties, including: * :meth:`~photutils.segmentation.SegmentationImage.reassign_label`: Reassign one or more label numbers. * :meth:`~photutils.segmentation.SegmentationImage.relabel_consecutive`: Reassign the label numbers consecutively, such that there are no missing label numbers (up to the maximum label number). * :meth:`~photutils.segmentation.SegmentationImage.keep_labels`: Keep only the specified labels. * :meth:`~photutils.segmentation.SegmentationImage.remove_labels`: Remove one or more labels. * :meth:`~photutils.segmentation.SegmentationImage.remove_border_labels`: Remove labeled segments near the image border. * :meth:`~photutils.segmentation.SegmentationImage.remove_masked_labels`: Remove labeled segments located within a masked region. * :meth:`~photutils.segmentation.SegmentationImage.outline_segments`: Outline the labeled segments for plotting. Centroids, Photometry, and Morphological Properties --------------------------------------------------- The :func:`~photutils.segmentation.source_properties` function is the primary tool for measuring the centroids, photometry, and morphological properties of sources defined in a segmentation image. When the segmentation image is generated using image thresholding (e.g., using :func:`~photutils.segmentation.detect_sources`), the source segments represent the isophotal footprint of each source and the resulting photometry is effectively isophotal photometry. :func:`~photutils.segmentation.source_properties` returns a :class:`~photutils.segmentation.SourceCatalog` object, which acts in part like a list of :class:`~photutils.segmentation.SourceProperties` objects, one for each segmented source (or a specified subset of sources). An Astropy `~astropy.table.QTable` of source properties can be generated using the :meth:`~photutils.segmentation.SourceCatalog.to_table` method. Please see :class:`~photutils.segmentation.SourceProperties` for the list of the many properties that are calculated for each source. More properties are likely to be added in the future. Let's detect sources and measure their properties in a synthetic image. For this example, we will use the :class:`~photutils.background.Background2D` class to produce a background and background noise image. We define a 2D detection threshold image using the background and background RMS images. We set the threshold at 2 sigma (per pixel) above the background: .. doctest-requires:: scipy >>> from astropy.convolution import Gaussian2DKernel >>> from photutils.datasets import make_100gaussians_image >>> from photutils import Background2D, MedianBackground >>> from photutils import detect_threshold, detect_sources >>> data = make_100gaussians_image() >>> bkg_estimator = MedianBackground() >>> bkg = Background2D(data, (50, 50), filter_size=(3, 3), ... bkg_estimator=bkg_estimator) >>> threshold = bkg.background + (2. * bkg.background_rms) Now we find sources that have 5 connected pixels that are each greater than the corresponding threshold image defined above. Because the threshold includes the background, we do not subtract the background from the data here. We also input a 2D circular Gaussian kernel with a FWHM of 3 pixels to filter the image prior to thresholding: .. doctest-requires:: scipy, skimage >>> from astropy.stats import gaussian_fwhm_to_sigma >>> sigma = 3.0 * gaussian_fwhm_to_sigma # FWHM = 3. >>> kernel = Gaussian2DKernel(sigma, x_size=3, y_size=3) >>> kernel.normalize() >>> npixels = 5 >>> segm = detect_sources(data, threshold, npixels=npixels, ... filter_kernel=kernel) >>> segm_deblend = deblend_sources(data, segm, npixels=npixels, ... filter_kernel=kernel, nlevels=32, ... contrast=0.001) As described earlier, the result is a :class:`~photutils.segmentation.SegmentationImage` where sources are labeled by different positive integer values. Now let's measure the properties of the detected sources defined in the segmentation image using the simplest call to :func:`~photutils.segmentation.source_properties`. The output `~astropy.table.QTable` of source properties is generated by the :class:`~photutils.segmentation.SourceCatalog` :meth:`~photutils.segmentation.SourceCatalog.to_table` method. Each row in the table represents a source. The columns represent the calculated source properties. Note that the only a subset of the source properties are shown below. Please see `~photutils.segmentation.SourceProperties` for the list of the many properties that are calculated for each source: .. doctest-requires:: scipy, skimage >>> from photutils import source_properties >>> cat = source_properties(data, segm_deblend) >>> tbl = cat.to_table() >>> tbl['xcentroid'].info.format = '.2f' # optional format >>> tbl['ycentroid'].info.format = '.2f' >>> tbl['cxx'].info.format = '.2f' >>> tbl['cxy'].info.format = '.2f' >>> tbl['cyy'].info.format = '.2f' >>> tbl['gini'].info.format = '.2f' >>> print(tbl) id xcentroid ycentroid sky_centroid ... cxx cxy cyy gini pix pix ... 1 / pix2 1 / pix2 1 / pix2 --- --------- --------- ------------ ... -------- -------- -------- ---- 1 235.22 1.25 None ... 0.17 -0.20 0.99 0.18 2 493.82 5.77 None ... 0.16 -0.32 0.61 0.13 3 207.30 10.02 None ... 0.37 0.49 0.30 0.16 4 364.75 11.13 None ... 0.39 -0.33 0.18 0.13 5 258.37 11.77 None ... 0.37 0.15 0.16 0.13 ... ... ... ... ... ... ... ... ... 92 427.01 147.45 None ... 0.26 -0.07 0.12 0.12 93 426.60 211.14 None ... 0.67 0.24 0.35 0.41 94 419.79 216.68 None ... 0.17 -0.19 0.27 0.14 95 433.91 280.73 None ... 0.52 -0.83 0.49 0.23 96 434.11 288.90 None ... 0.18 -0.19 0.30 0.24 Length = 96 rows Let's use the measured morphological properties to define approximate isophotal ellipses for each source. Here we define an `~photutils.aperture.EllipticalAperture` object for each source using its calculated centroid positions (`~photutils.segmentation.SourceProperties.xcentroid` and `~photutils.segmentation.SourceProperties.ycentroid`) , semimajor and semiminor axes lengths (`~photutils.segmentation.SourceProperties.semimajor_axis_sigma` and `~photutils.segmentation.SourceProperties.semiminor_axis_sigma`) , and orientation (`~photutils.segmentation.SourceProperties.orientation`): .. doctest-requires:: scipy, skimage >>> import numpy as np >>> import astropy.units as u >>> from photutils import source_properties, EllipticalAperture >>> cat = source_properties(data, segm_deblend) >>> r = 3. # approximate isophotal extent >>> apertures = [] >>> for obj in cat: ... position = np.transpose((obj.xcentroid.value, obj.ycentroid.value)) ... a = obj.semimajor_axis_sigma.value * r ... b = obj.semiminor_axis_sigma.value * r ... theta = obj.orientation.to(u.rad).value ... apertures.append(EllipticalAperture(position, a, b, theta=theta)) Now let's plot the derived elliptical apertures on the data: .. doctest-skip:: >>> import numpy as np >>> import matplotlib.pyplot as plt >>> from astropy.visualization import SqrtStretch >>> from astropy.visualization.mpl_normalize import ImageNormalize >>> norm = ImageNormalize(stretch=SqrtStretch()) >>> fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 12.5)) >>> ax1.imshow(data, origin='lower', cmap='Greys_r', norm=norm) >>> ax1.set_title('Data') >>> cmap = segm_deblend.make_cmap(random_state=12345) >>> ax2.imshow(segm_deblend, origin='lower', cmap=cmap) >>> ax2.set_title('Segmentation Image') >>> for aperture in apertures: ... aperture.plot(axes=ax1, color='white', lw=1.5) ... aperture.plot(axes=ax2, color='white', lw=1.5) .. plot:: import numpy as np import matplotlib.pyplot as plt from astropy.stats import gaussian_fwhm_to_sigma from astropy.convolution import Gaussian2DKernel import astropy.units as u from astropy.visualization import SqrtStretch from astropy.visualization.mpl_normalize import ImageNormalize from photutils.datasets import make_100gaussians_image from photutils import Background2D, MedianBackground from photutils import detect_threshold, detect_sources, deblend_sources from photutils import source_properties from photutils import EllipticalAperture data = make_100gaussians_image() bkg_estimator = MedianBackground() bkg = Background2D(data, (50, 50), filter_size=(3, 3), bkg_estimator=bkg_estimator) threshold = bkg.background + (2. * bkg.background_rms) sigma = 3.0 * gaussian_fwhm_to_sigma # FWHM = 3. kernel = Gaussian2DKernel(sigma, x_size=3, y_size=3) kernel.normalize() npixels = 5 segm = detect_sources(data, threshold, npixels=npixels, filter_kernel=kernel) segm_deblend = deblend_sources(data, segm, npixels=npixels, filter_kernel=kernel, nlevels=32, contrast=0.001) cat = source_properties(data, segm_deblend) r = 3. # approximate isophotal extent apertures = [] for obj in cat: position = np.transpose((obj.xcentroid.value, obj.ycentroid.value)) a = obj.semimajor_axis_sigma.value * r b = obj.semiminor_axis_sigma.value * r theta = obj.orientation.to(u.rad).value apertures.append(EllipticalAperture(position, a, b, theta=theta)) norm = ImageNormalize(stretch=SqrtStretch()) fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 12.5)) ax1.imshow(data, origin='lower', cmap='Greys_r', norm=norm) ax1.set_title('Data') cmap = segm_deblend.make_cmap(random_state=12345) ax2.imshow(segm_deblend, origin='lower', cmap=cmap) ax2.set_title('Segmentation Image') for aperture in apertures: aperture.plot(axes=ax1, color='white', lw=1.5) aperture.plot(axes=ax2, color='white', lw=1.5) plt.tight_layout() We can also specify a specific subset of sources, defined by their label numbers in the segmentation image: .. doctest-requires:: scipy, skimage >>> labels = [1, 5, 20, 50, 75, 80] >>> cat = source_properties(data, segm_deblend, labels=labels) >>> tbl2 = cat.to_table() >>> tbl2['xcentroid'].info.format = '.2f' # optional format >>> tbl2['ycentroid'].info.format = '.2f' >>> tbl2['cxx'].info.format = '.2f' >>> tbl2['cxy'].info.format = '.2f' >>> tbl2['cyy'].info.format = '.2f' >>> tbl2['gini'].info.format = '.2f' >>> print(tbl2) id xcentroid ycentroid sky_centroid ... cxx cxy cyy gini pix pix ... 1 / pix2 1 / pix2 1 / pix2 --- --------- --------- ------------ ... -------- -------- -------- ---- 1 235.22 1.25 None ... 0.17 -0.20 0.99 0.18 5 258.37 11.77 None ... 0.37 0.15 0.16 0.13 20 347.00 66.94 None ... 0.15 -0.01 0.21 0.11 50 145.06 168.55 None ... 0.66 0.05 0.71 0.45 75 301.86 239.25 None ... 0.47 -0.05 0.28 0.08 80 43.20 250.01 None ... 0.18 -0.08 0.34 0.11 By default, the :meth:`~photutils.segmentation.SourceCatalog.to_table` method will include most scalar-valued properties from :class:`~photutils.segmentation.SourceProperties`, but a subset of properties can also be specified (or excluded) in the `~astropy.table.QTable` via the ``columns`` or ``exclude_columns`` keywords: .. doctest-requires:: scipy, skimage >>> labels = [1, 5, 20, 50, 75, 80] >>> cat = source_properties(data, segm_deblend, labels=labels) >>> columns = ['id', 'xcentroid', 'ycentroid', 'source_sum', 'area'] >>> tbl3 = cat.to_table(columns=columns) >>> tbl3['xcentroid'].info.format = '.4f' # optional format >>> tbl3['ycentroid'].info.format = '.4f' >>> tbl3['source_sum'].info.format = '.4f' >>> print(tbl3) id xcentroid ycentroid source_sum area pix pix pix2 --- --------- --------- ---------- ---- 1 235.2160 1.2457 594.2193 36.0 5 258.3710 11.7694 684.7155 58.0 20 346.9998 66.9428 864.9778 73.0 50 145.0591 168.5496 885.9582 33.0 75 301.8641 239.2534 391.1656 36.0 80 43.2023 250.0100 627.6727 55.0 A `~astropy.wcs.WCS` transformation can also be input to :func:`~photutils.segmentation.source_properties` via the ``wcs`` keyword, in which case the sky coordinates at the source centroids will be returned. Background Properties ^^^^^^^^^^^^^^^^^^^^^ Like with :func:`~photutils.aperture.aperture_photometry`, the ``data`` array that is input to :func:`~photutils.segmentation.source_properties` should be background subtracted. If you input the background image that was subtracted from the data into the ``background`` keyword of :func:`~photutils.segmentation.source_properties`, the background properties for each source will also be calculated: .. doctest-requires:: scipy, skimage >>> labels = [1, 5, 20, 50, 75, 80] >>> cat = source_properties(data, segm_deblend, labels=labels, ... background=bkg.background) >>> columns = ['id', 'background_at_centroid', 'background_mean', ... 'background_sum'] >>> tbl4 = cat.to_table(columns=columns) >>> tbl4['background_at_centroid'].info.format = '{:.10f}' # optional format >>> tbl4['background_mean'].info.format = '{:.10f}' >>> tbl4['background_sum'].info.format = '{:.10f}' >>> print(tbl4) id background_at_centroid background_mean background_sum --- ---------------------- --------------- -------------- 1 5.2020428266 5.2021662094 187.2779835383 5 5.2140031370 5.2139893924 302.4113847608 20 5.2787968578 5.2785772173 385.3361368595 50 5.1896511123 5.1895516008 171.2552028270 75 5.1409531509 5.1408425626 185.0703322539 80 5.2109780136 5.2108402505 286.5962137759 Photometric Errors ^^^^^^^^^^^^^^^^^^ :func:`~photutils.segmentation.source_properties` requires inputting a *total* error array, i.e. the background-only error plus Poisson noise due to individual sources. The :func:`~photutils.utils.calc_total_error` function can be used to calculate the total error array from a background-only error array and an effective gain. The ``effective_gain``, which is the ratio of counts (electrons or photons) to the units of the data, is used to include the Poisson noise from the sources. ``effective_gain`` can either be a scalar value or a 2D image with the same shape as the ``data``. A 2D effective gain image is useful for mosaic images that have variable depths (i.e., exposure times) across the field. For example, one should use an exposure-time map as the ``effective_gain`` for a variable depth mosaic image in count-rate units. Let's assume our synthetic data is in units of electrons per second. In that case, the ``effective_gain`` should be the exposure time (here we set it to 500 seconds). Here we use :func:`~photutils.utils.calc_total_error` to calculate the total error and input it into the :func:`~photutils.segmentation.source_properties` function. When a total ``error`` is input, the `~photutils.segmentation.SourceProperties.source_sum_err` property is calculated. `~photutils.segmentation.SourceProperties.source_sum` and `~photutils.segmentation.SourceProperties.source_sum_err` are the instrumental flux and propagated flux error within the source segments: .. doctest-requires:: scipy, skimage >>> from photutils.utils import calc_total_error >>> labels = [1, 5, 20, 50, 75, 80] >>> effective_gain = 500. >>> error = calc_total_error(data, bkg.background_rms, effective_gain) >>> cat = source_properties(data, segm_deblend, labels=labels, error=error) >>> columns = ['id', 'xcentroid', 'ycentroid', 'source_sum', ... 'source_sum_err'] >>> tbl5 = cat.to_table(columns=columns) >>> tbl5['xcentroid'].info.format = '{:.4f}' # optional format >>> tbl5['ycentroid'].info.format = '{:.4f}' >>> for col in tbl5.colnames: ... tbl5[col].info.format = '%.8g' # for consistent table output >>> print(tbl5) id xcentroid ycentroid source_sum source_sum_err pix pix --- --------- --------- ---------- -------------- 1 235.21604 1.2457344 594.21933 12.787658 5 258.37099 11.769376 684.71547 16.326605 20 346.99975 66.942777 864.97776 18.677809 50 145.05911 168.54961 885.9582 11.908449 75 301.86414 239.25337 391.16559 12.080326 80 43.202278 250.00997 627.67268 15.812197 Pixel Masking ^^^^^^^^^^^^^ Pixels can be completely ignored/excluded (e.g. bad pixels) when measuring the source properties by providing a boolean mask image via the ``mask`` keyword (`True` pixel values are masked) to the :func:`~photutils.segmentation.source_properties` function or :class:`~photutils.segmentation.SourceProperties` class. Filtering ^^^^^^^^^ `SExtractor`_'s centroid and morphological parameters are always calculated from a filtered "detection" image. The usual downside of the filtering is the sources will be made more circular than they actually are (assuming a circular kernel is used, which is common). If you wish to reproduce `SExtractor`_ results, then use the :func:`~photutils.segmentation.source_properties` ``filter_kernel`` keyword to filter the ``data`` prior to centroid and morphological measurements. The kernel should be the same one used with :func:`~photutils.segmentation.detect_sources` to define the segmentation image. If ``filter_kernel`` is `None`, then the centroid and morphological measurements will be performed on the unfiltered ``data``. Note that photometry is *always* performed on the unfiltered ``data``. Reference/API ------------- .. automodapi:: photutils.segmentation :no-heading: .. _SExtractor: https://www.astromatic.net/software/sextractor photutils-0.7.2/docs/test_function.rst0000644000214200020070000000012213563423715022310 0ustar lbradleySTSCI\science00000000000000Photutils Test Function ======================= .. autofunction:: photutils.test photutils-0.7.2/docs/utils.rst0000644000214200020070000000040113547426552020570 0ustar lbradleySTSCI\science00000000000000Utility Functions (`photutils.utils`) ===================================== Introduction ------------ The `photutils.utils` package contains general-purpose utility functions. Reference/API ------------- .. automodapi:: photutils.utils :no-heading: photutils-0.7.2/licenses/0000755000214200020070000000000013573510273017551 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/licenses/README.rst0000644000214200020070000000036313547426552021251 0ustar lbradleySTSCI\science00000000000000Licenses ======== This directory holds license and credit information for works Photutils is derived from or distributes, and/or datasets. The license file for the Photutils package itself is placed in the root directory of this repository. photutils-0.7.2/photutils/0000755000214200020070000000000013573510273017777 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/CITATION0000644000214200020070000000314713563423715021144 0ustar lbradleySTSCI\science00000000000000Citing Photutils ---------------- If you use Photutils for a project that leads to a publication, whether directly or as a dependency of another package, please include the following acknowledgment: .. code-block:: text This research made use of Photutils, an Astropy package for detection and photometry of astronomical sources (Bradley et al. 20XX). where (Bradley et al. 20XX) is a citation to the `Zenodo record `_ of the Photutils version that was used. We also encourage citations in the main text wherever appropriate. For example, for Photutils v0.6 one would cite Bradley et al. 2019 with the BibTeX entry (https://zenodo.org/record/2533376/export/hx): .. code-block:: text @misc{Bradley_2019_2533376, author = {Larry Bradley and Brigitta Sip{\H o}cz and Thomas Robitaille and Erik Tollerud and Z\`e Vin{\'{\i}}cius and Christoph Deil and Kyle Barbary and Hans Moritz G{\"u}nther and Mihai Cara and Ivo Busko and Simon Conseil and Michael Droettboom and Azalee Bostroem and E. M. Bray and Lars Andersen Bratholm and Tom Wilson and Matt Craig and Geert Barentsen and Sergio Pascual and Axel Donath and Johnny Greco and Gabriel Perren and P. L. Lim and Wolfgang Kerzendorf}, title = {astropy/photutils: v0.6}, month = jan, year = 2019, doi = {10.5281/zenodo.2533376}, url = {https://doi.org/10.5281/zenodo.2533376} } All Photutils versions (and more citation formats) can be found at https://doi.org/10.5281/zenodo.596036. photutils-0.7.2/photutils/__init__.py0000644000214200020070000000246713563423715022124 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Photutils is an Astropy affiliated package to provide tools for detecting and performing photometry of astronomical sources. It also has tools for background estimation, ePSF building, PSF matching, centroiding, and morphological measurements. """ import os # Affiliated packages may add whatever they like to this file, but # should keep this content at the top. # ---------------------------------------------------------------------------- from ._astropy_init import * # noqa # ---------------------------------------------------------------------------- if not _ASTROPY_SETUP_: # noqa from .aperture import * # noqa from .background import * # noqa from .centroids import * # noqa from .detection import * # noqa from .morphology import * # noqa from .psf import * # noqa from .segmentation import * # noqa # Set the bibtex entry to the article referenced in CITATION. def _get_bibtex(): citation_file = os.path.join(os.path.dirname(__file__), 'CITATION') with open(citation_file, 'r') as citation: refs = citation.read().split('@misc')[1:] if len(refs) == 0: return '' bibtexreference = "@misc{0}".format(refs[0]) return bibtexreference __citation__ = __bibtex__ = _get_bibtex() photutils-0.7.2/photutils/_astropy_init.py0000644000214200020070000000374713547426552023256 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst __all__ = ['__version__', '__githash__'] # 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__ = '' if not _ASTROPY_SETUP_: # noqa import os from warnings import warn from astropy.config.configuration import ( update_default_config, ConfigurationDefaultMissingError, ConfigurationDefaultMissingWarning) # Create the test function for self test from astropy.tests.runner import TestRunner test = TestRunner.make_test_runner_in(os.path.dirname(__file__)) test.__test__ = False __all__ += ['test'] # 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: update_default_config( __package__, config_dir, version=__version__) except TypeError as orig_error: try: update_default_config(__package__, config_dir) except ConfigurationDefaultMissingError as e: wmsg = (e.args[0] + " Cannot install default profile. If you are " "importing from source, this is expected.") warn(ConfigurationDefaultMissingWarning(wmsg)) del e except Exception: raise orig_error photutils-0.7.2/photutils/_compiler.c0000644000214200020070000000524013573510265022116 0ustar lbradleySTSCI\science00000000000000#include /*************************************************************************** * Macros for determining the compiler version. * * These are borrowed from boost, and majorly abridged to include only * the compilers we care about. ***************************************************************************/ #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 }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "compiler_version", NULL, sizeof(struct module_state), NULL, NULL, NULL, NULL, NULL }; #define INITERROR return NULL PyMODINIT_FUNC PyInit_compiler_version(void) { PyObject* m; m = PyModule_Create(&moduledef); if (m == NULL) INITERROR; PyModule_AddStringConstant(m, "compiler", COMPILER); return m; } photutils-0.7.2/photutils/aperture/0000755000214200020070000000000013573510273021626 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/aperture/__init__.py0000644000214200020070000000054413563423715023745 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage contains tools to perform aperture photometry. """ from .bounding_box import * # noqa from .circle import * # noqa from .core import * # noqa from .ellipse import * # noqa from .mask import * # noqa from .photometry import * # noqa from .rectangle import * # noqa photutils-0.7.2/photutils/aperture/_photometry_utils.py0000644000214200020070000001374013572576136026007 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module contains tools to validate and handle photometry inputs. """ import warnings import numpy as np from astropy.io import fits import astropy.units as u from astropy.utils.exceptions import (AstropyDeprecationWarning, AstropyUserWarning) from astropy.wcs import WCS def _handle_hdu_input(data): # pragma: no cover """ Convert FITS HDU ``data`` to a `~numpy.ndarray` (and optional unit). Used to parse ``data`` input to `aperture_photometry`. Parameters ---------- data : array_like, `~astropy.units.Quantity`, `~astropy.io.fits.ImageHDU`, or `~astropy.io.fits.HDUList` The 2D data array. Returns ------- data : `~numpy.ndarray` The 2D data array. unit : `~astropy.unit.Unit` or `None` The unit for the data. """ bunit = None if isinstance(data, (fits.PrimaryHDU, fits.ImageHDU, fits.HDUList)): warnings.warn('"astropy.io.fits.PrimaryHDU", ' '"astropy.io.fits.ImageHDU", and ' '"astropy.io.fits.HDUList" inputs are deprecated as of ' 'v0.7 and will not be allowed in future versions.', AstropyDeprecationWarning) if isinstance(data, fits.HDUList): for i, hdu in enumerate(data): if hdu.data is not None: warnings.warn('Input data is a HDUList object. Doing ' 'photometry only on the {0} HDU.' .format(i), AstropyUserWarning) data = hdu break if isinstance(data, (fits.PrimaryHDU, fits.ImageHDU)): header = data.header data = data.data if 'BUNIT' in header: bunit = u.Unit(header['BUNIT'], parse_strict='warn') if isinstance(bunit, u.UnrecognizedUnit): warnings.warn('The BUNIT in the header of the input data is ' 'not parseable as a valid unit.', AstropyUserWarning) try: fits_wcs = WCS(header) except Exception: # A valid WCS was not found in the header. Let the calling # application raise an exception if it needs a WCS. fits_wcs = None return data, bunit, fits_wcs def _validate_inputs(data, error): """ Validate inputs. ``data`` and ``error`` are converted to a `~numpy.ndarray`, if necessary. Used to parse inputs to `~photutils.aperture.aperture_photometry` and `~photutils.aperture.PixelAperture.do_photometry`. """ data = np.asanyarray(data) if data.ndim != 2: raise ValueError('data must be a 2D array.') if error is not None: error = np.asanyarray(error) if error.shape != data.shape: raise ValueError('error and data must have the same shape.') return data, error def _handle_units(data, error, unit): """ Handle Quantity inputs and the ``unit`` keyword. Any units on ``data`` and ``error` are removed. ``data`` and ``error`` are returned as `~numpy.ndarray`. The returned ``unit`` represents the unit for both ``data`` and ``error``. Used to parse inputs to `~photutils.aperture.aperture_photometry` and `~photutils.aperture.PixelAperture.do_photometry`. """ if unit is not None: unit = u.Unit(unit, parse_strict='warn') if isinstance(unit, u.UnrecognizedUnit): warnings.warn('The input unit is not parseable as a valid ' 'unit.', AstropyUserWarning) unit = None # check Quantity inputs inputs = (data, error) has_unit = [hasattr(x, 'unit') for x in inputs if x is not None] use_units = all(has_unit) if any(has_unit) and not use_units: raise ValueError('If data or error has units, then they both must ' 'have the same units.') # handle Quantity inputs if use_units: if unit is not None and data.unit != unit: warnings.warn('The input unit does not agree with the data ' 'unit. Using the data unit.', AstropyUserWarning) unit = data.unit # strip data and error units for performance unit = data.unit data = data.value if error is not None: if unit != error.unit: raise ValueError('data and error must have the same units.') error = error.value return data, error, unit def _prepare_photometry_data(data, error, mask): """ Prepare data and error arrays for photometry. Error is converted to variance and masked values are set to zero in the output data and variance arrays. Used to parse inputs to `~photutils.aperture.aperture_photometry` and `~photutils.aperture.PixelAperture.do_photometry`. Parameters ---------- data : `~numpy.ndarray` The 2D array on which to perform photometry. error : `~numpy.ndarray` or `None` The pixel-wise Gaussian 1-sigma errors of the input ``data``. mask : array_like (bool) or `None` A boolean mask with the same shape as ``data`` where a `True` value indicates the corresponding element of ``data`` is masked. Returns ------- data : `~numpy.ndarray` The 2D array on which to perform photometry, where masked values have been set to zero. variance : `~numpy.ndarray` or `None` The pixel-wise Gaussian 1-sigma variance of the input ``data``, where masked values have been set to zero. """ if error is not None: variance = error ** 2 else: variance = None if mask is not None: mask = np.asanyarray(mask) if mask.shape != data.shape: raise ValueError('mask and data must have the same shape.') data = data.copy() # do not modify input data data[mask] = 0. if variance is not None: variance[mask] = 0. return data, variance photutils-0.7.2/photutils/aperture/attributes.py0000644000214200020070000001207613572576136024405 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module defines descriptor classes for aperture attribute validation. """ import warnings from astropy.coordinates import SkyCoord import astropy.units as u from astropy.utils.exceptions import AstropyDeprecationWarning import numpy as np __all__ = ['ApertureAttribute', 'PixelPositions', 'SkyCoordPositions', 'Scalar', 'PositiveScalar', 'AngleOrPixelScalarQuantity'] class ApertureAttribute: """ Base descriptor class for aperture attribute validation. """ def __init__(self, name): self.name = name def __get__(self, instance, owner): if instance is None: return self return instance.__dict__[self.name] def __set__(self, instance, value): self._validate(value) if not isinstance(value, (u.Quantity, SkyCoord)): value = float(value) instance.__dict__[self.name] = value def __delete__(self, instance): del instance.__dict__[self.name] def _validate(self, value): """ Validate the attribute value. An exception is raised if the value is invalid. """ raise NotImplementedError class PixelPositions(ApertureAttribute): """ Validate and set positions for pixel-based apertures. In all cases, pixel positions are converted to a 2D `~numpy.ndarray` (without units). """ def __set__(self, instance, value): # This is needed for zip to work seamlessly in Python 3 # (e.g. positions = zip(xpos, ypos)) if isinstance(value, zip): value = tuple(value) value = np.asanyarray(value).astype(float) # np.ndarray self._validate(value) if isinstance(value, u.Quantity): value = value.value if value.ndim == 2 and value.shape[1] != 2 and value.shape[0] == 2: warnings.warn('Inputing positions shaped as 2xN is deprecated ' 'and will be removed in v0.8. Positions should be ' 'a (x, y) pixel position or a list or array of ' '(x, y) pixel positions, e.g. [(x1, y1), ' '(x2, y2), (x3, y3)].', AstropyDeprecationWarning) value = np.transpose(value) instance.__dict__[self.name] = value def _validate(self, value): if isinstance(value, u.Quantity) and value.unit != u.pixel: raise u.UnitsError('{} must be in pixel units'.format(self.name)) if np.any(~np.isfinite(value)): raise ValueError('{} must not contain any non-finite (e.g. NaN ' 'or inf) positions'.format(self.name)) value = np.atleast_2d(value) if (value.shape[1] != 2 and value.shape[0] != 2) or value.ndim > 2: raise TypeError('{} must be an (x, y) pixel position or a list ' 'or array of (x, y) pixel positions.' .format(self.name)) class SkyCoordPositions(ApertureAttribute): """ Check that value is a `~astropy.coordinates.SkyCoord`. """ def _validate(self, value): if not isinstance(value, SkyCoord): raise ValueError('{} must be a SkyCoord instance' .format(self.name)) class Scalar(ApertureAttribute): """ Check that value is a scalar. """ def _validate(self, value): if not np.isscalar(value): raise ValueError('{} must be a scalar'.format(self.name)) class PositiveScalar(ApertureAttribute): """ Check that value is a stricly positive (>= 0) scalar. """ def _validate(self, value): if not np.isscalar(value) or value <= 0: raise ValueError('{} must be a positive scalar'.format(self.name)) class AngleScalarQuantity(ApertureAttribute): """ Check that value is either an angular scalar `~astropy.units.Quantity`. """ def _validate(self, value): if isinstance(value, u.Quantity): if not value.isscalar: raise ValueError('{} must be a scalar'.format(self.name)) if not value.unit.physical_type == 'angle': raise ValueError('{} must have angular units' .format(self.name)) else: raise TypeError('{} must be an astropy Quantity instance'. format(self.name)) class AngleOrPixelScalarQuantity(ApertureAttribute): """ Check that value is either an angular or a pixel scalar `~astropy.units.Quantity`. """ def _validate(self, value): if isinstance(value, u.Quantity): if not value.isscalar: raise ValueError('{} must be a scalar'.format(self.name)) if not (value.unit.physical_type == 'angle' or value.unit == u.pixel): raise ValueError('{} must have angular or pixel units' .format(self.name)) else: raise TypeError('{} must be an astropy Quantity instance' .format(self.name)) photutils-0.7.2/photutils/aperture/bounding_box.py0000644000214200020070000002530413572576136024672 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module defines a class for a rectangular bounding box. """ from astropy.io.fits.util import _is_int from astropy.utils import deprecated from astropy.utils.decorators import deprecated_renamed_argument import numpy as np __all__ = ['BoundingBox'] class BoundingBox: """ A rectangular bounding box in integer (not float) pixel indices. Parameters ---------- ixmin, ixmax, iymin, iymax : int The bounding box pixel indices. Note that the upper values (``iymax`` and ``ixmax``) are exclusive as for normal slices in Python. The lower values (``ixmin`` and ``iymin``) must not be greater than the respective upper values (``ixmax`` and ``iymax``). Examples -------- >>> from photutils import BoundingBox >>> # constructing a BoundingBox like this is cryptic: >>> bbox = BoundingBox(1, 10, 2, 20) >>> # it's better to use keyword arguments for readability: >>> bbox = BoundingBox(ixmin=1, ixmax=10, iymin=2, iymax=20) >>> bbox # nice repr, useful for interactive work BoundingBox(ixmin=1, ixmax=10, iymin=2, iymax=20) >>> # sometimes it's useful to check if two bounding boxes are the same >>> bbox == BoundingBox(ixmin=1, ixmax=10, iymin=2, iymax=20) True >>> bbox == BoundingBox(ixmin=7, ixmax=10, iymin=2, iymax=20) False >>> # "shape" and "slices" can be useful when working with numpy arrays >>> bbox.shape # numpy order: (y, x) (18, 9) >>> bbox.slices # numpy order: (y, x) (slice(2, 20, None), slice(1, 10, None)) >>> # "extent" is useful when plotting the BoundingBox with matplotlib >>> bbox.extent # matplotlib order: (x, y) (0.5, 9.5, 1.5, 19.5) """ def __init__(self, ixmin, ixmax, iymin, iymax): if not _is_int(ixmin): raise TypeError('ixmin must be an integer') if not _is_int(ixmax): raise TypeError('ixmax must be an integer') if not _is_int(iymin): raise TypeError('iymin must be an integer') if not _is_int(iymax): raise TypeError('iymax must be an integer') if ixmin > ixmax: raise ValueError('ixmin must be <= ixmax') if iymin > iymax: raise ValueError('iymin must be <= iymax') self.ixmin = ixmin self.ixmax = ixmax self.iymin = iymin self.iymax = iymax @classmethod def from_float(cls, xmin, xmax, ymin, ymax): """ Return the smallest bounding box that fully contains a given rectangle defined by float coordinate values. Following the pixel index convention, an integer index corresponds to the center of a pixel and the pixel edges span from (index - 0.5) to (index + 0.5). For example, the pixel edge spans of the following pixels are: - pixel 0: from -0.5 to 0.5 - pixel 1: from 0.5 to 1.5 - pixel 2: from 1.5 to 2.5 In addition, because `BoundingBox` upper limits are exclusive (by definition), 1 is added to the upper pixel edges. See examples below. Parameters ---------- xmin, xmax, ymin, ymax : float Float coordinates defining a rectangle. The lower values (``xmin`` and ``ymin``) must not be greater than the respective upper values (``xmax`` and ``ymax``). Returns ------- bbox : `BoundingBox` object The minimal ``BoundingBox`` object fully containing the input rectangle coordinates. Examples -------- >>> from photutils import BoundingBox >>> BoundingBox.from_float(xmin=1.0, xmax=10.0, ymin=2.0, ymax=20.0) BoundingBox(ixmin=1, ixmax=11, iymin=2, iymax=21) >>> BoundingBox.from_float(xmin=1.4, xmax=10.4, ymin=1.6, ymax=10.6) BoundingBox(ixmin=1, ixmax=11, iymin=2, iymax=12) """ ixmin = int(np.floor(xmin + 0.5)) ixmax = int(np.ceil(xmax + 0.5)) iymin = int(np.floor(ymin + 0.5)) iymax = int(np.ceil(ymax + 0.5)) return cls(ixmin, ixmax, iymin, iymax) def __eq__(self, other): if not isinstance(other, BoundingBox): raise TypeError('Can compare BoundingBox only to another ' 'BoundingBox.') return ( (self.ixmin == other.ixmin) and (self.ixmax == other.ixmax) and (self.iymin == other.iymin) and (self.iymax == other.iymax) ) def __or__(self, other): return self.union(other) def __and__(self, other): return self.intersection(other) def __repr__(self): data = self.__dict__ data['name'] = self.__class__.__name__ fmt = ('{name}(ixmin={ixmin}, ixmax={ixmax}, iymin={iymin}, ' 'iymax={iymax})') return fmt.format(**data) @property def shape(self): """ The ``(ny, nx)`` shape of the bounding box. """ return self.iymax - self.iymin, self.ixmax - self.ixmin @property def slices(self): """ The bounding box as a tuple of `slice` objects. The slice tuple is in numpy axis order (i.e. ``(y, x)``) and therefore can be used to slice numpy arrays. """ return (slice(self.iymin, self.iymax), slice(self.ixmin, self.ixmax)) @property def extent(self): """ The extent of the mask, defined as the ``(xmin, xmax, ymin, ymax)`` bounding box from the bottom-left corner of the lower-left pixel to the upper-right corner of the upper-right pixel. The upper edges here are the actual pixel positions of the edges, i.e. they are not "exclusive" indices used for python indexing. This is useful for plotting the bounding box using Matplotlib. """ return ( self.ixmin - 0.5, self.ixmax - 0.5, self.iymin - 0.5, self.iymax - 0.5, ) @deprecated('0.7', alternative='as_artist') def as_patch(self, **kwargs): # pragma: no cover """ Return a `matplotlib.patches.Rectangle` that represents the bounding box. Parameters ---------- kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. Returns ------- result : `matplotlib.patches.Rectangle` A matplotlib rectangular patch. """ return self.as_artist(**kwargs) def as_artist(self, **kwargs): """ Return a `matplotlib.patches.Rectangle` that represents the bounding box. Parameters ---------- kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. Returns ------- result : `matplotlib.patches.Rectangle` A matplotlib rectangular patch. Examples -------- .. plot:: :include-source: import matplotlib.pyplot as plt from photutils import BoundingBox bbox = BoundingBox(2, 7, 3, 8) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) np.random.seed(12345) ax.imshow(np.random.random((10, 10)), interpolation='nearest', cmap='viridis') ax.add_patch(bbox.as_artist(facecolor='none', edgecolor='white', lw=2.)) """ from matplotlib.patches import Rectangle return Rectangle(xy=(self.extent[0], self.extent[2]), width=self.shape[1], height=self.shape[0], **kwargs) def to_aperture(self): """ Return a `~photutils.aperture.RectangularAperture` that represents the bounding box. """ from .rectangle import RectangularAperture # prevent circular import xpos = (self.extent[1] + self.extent[0]) / 2. ypos = (self.extent[3] + self.extent[2]) / 2. xypos = (xpos, ypos) height, width = self.shape return RectangularAperture(xypos, w=width, h=height, theta=0.) @deprecated_renamed_argument('ax', 'axes', '0.7') def plot(self, axes=None, origin=(0, 0), **kwargs): """ Plot the `BoundingBox` on a matplotlib `~matplotlib.axes.Axes` instance. Parameters ---------- axes : `matplotlib.axes.Axes` or `None`, optional The matplotlib axes on which to plot. If `None`, then the current `~matplotlib.axes.Axes` instance is used. origin : array_like, optional The ``(x, y)`` position of the origin of the displayed image. kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. """ aper = self.to_aperture() aper.plot(axes=axes, origin=origin, **kwargs) def union(self, other): """ Return a `BoundingBox` representing the union of this `BoundingBox` with another `BoundingBox`. Parameters ---------- other : `BoundingBox` The `BoundingBox` to join with this one. Returns ------- result : `BoundingBox` A `BoundingBox` representing the union of the input `BoundingBox` with this one. """ if not isinstance(other, BoundingBox): raise TypeError('BoundingBox can be joined only with another ' 'BoundingBox.') ixmin = min((self.ixmin, other.ixmin)) ixmax = max((self.ixmax, other.ixmax)) iymin = min((self.iymin, other.iymin)) iymax = max((self.iymax, other.iymax)) return BoundingBox(ixmin=ixmin, ixmax=ixmax, iymin=iymin, iymax=iymax) def intersection(self, other): """ Return a `BoundingBox` representing the intersection of this `BoundingBox` with another `BoundingBox`. Parameters ---------- other : `BoundingBox` The `BoundingBox` to intersect with this one. Returns ------- result : `BoundingBox` A `BoundingBox` representing the intersection of the input `BoundingBox` with this one. """ if not isinstance(other, BoundingBox): raise TypeError('BoundingBox can be intersected only with ' 'another BoundingBox.') ixmin = max(self.ixmin, other.ixmin) ixmax = min(self.ixmax, other.ixmax) iymin = max(self.iymin, other.iymin) iymax = min(self.iymax, other.iymax) if ixmax < ixmin or iymax < iymin: return None return BoundingBox(ixmin=ixmin, ixmax=ixmax, iymin=iymin, iymax=iymax) photutils-0.7.2/photutils/aperture/circle.py0000644000214200020070000003601013572576136023452 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module defines circular and circular-annulus apertures in both pixel and sky coordinates. """ import math import numpy as np from .attributes import (AngleOrPixelScalarQuantity, PixelPositions, PositiveScalar, SkyCoordPositions) from .core import PixelAperture, SkyAperture from .mask import ApertureMask from ..geometry import circular_overlap_grid __all__ = ['CircularMaskMixin', 'CircularAperture', 'CircularAnnulus', 'SkyCircularAperture', 'SkyCircularAnnulus'] class CircularMaskMixin: """ Mixin class to create masks for circular and circular-annulus aperture objects. """ def to_mask(self, method='exact', subpixels=5): """ Return a mask for the aperture. Parameters ---------- method : {'exact', 'center', 'subpixel'}, optional The method used to determine the overlap of the aperture on the pixel grid. Not all options are available for all aperture types. Note that the more precise methods are generally slower. The following methods are available: * ``'exact'`` (default): The the exact fractional overlap of the aperture and each pixel is calculated. The returned mask will contain values between 0 and 1. * ``'center'``: A pixel is considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. The returned mask will contain values only of 0 (out) and 1 (in). * ``'subpixel'``: A pixel is divided into subpixels (see the ``subpixels`` keyword), each of which are considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. If ``subpixels=1``, this method is equivalent to ``'center'``. The returned mask will contain values between 0 and 1. subpixels : int, optional For the ``'subpixel'`` method, resample pixels by this factor in each dimension. That is, each pixel is divided into ``subpixels ** 2`` subpixels. Returns ------- mask : `~photutils.aperture.ApertureMask` or list of `~photutils.aperture.ApertureMask` A mask for the aperture. If the aperture is scalar then a single `~photutils.aperture.ApertureMask` is returned, otherwise a list of `~photutils.aperture.ApertureMask` is returned. """ use_exact, subpixels = self._translate_mask_mode(method, subpixels) if hasattr(self, 'r'): radius = self.r elif hasattr(self, 'r_out'): # annulus radius = self.r_out else: raise ValueError('Cannot determine the aperture radius.') masks = [] for bbox, edges in zip(np.atleast_1d(self.bbox), self._centered_edges): ny, nx = bbox.shape mask = circular_overlap_grid(edges[0], edges[1], edges[2], edges[3], nx, ny, radius, use_exact, subpixels) # subtract the inner circle for an annulus if hasattr(self, 'r_in'): mask -= circular_overlap_grid(edges[0], edges[1], edges[2], edges[3], nx, ny, self.r_in, use_exact, subpixels) masks.append(ApertureMask(mask, bbox)) if self.isscalar: return masks[0] else: return masks class CircularAperture(CircularMaskMixin, PixelAperture): """ A circular aperture defined in pixel coordinates. The aperture has a single fixed size/shape, but it can have multiple positions (see the ``positions`` input). Parameters ---------- positions : array_like or `~astropy.units.Quantity` The pixel coordinates of the aperture center(s) in one of the following formats: * single ``(x, y)`` pair as a tuple, list, or `~numpy.ndarray` * tuple, list, or `~numpy.ndarray` of ``(x, y)`` pairs * `~astropy.units.Quantity` instance of ``(x, y)`` pairs in pixel units r : float The radius of the circle in pixels. Raises ------ ValueError : `ValueError` If the input radius, ``r``, is negative. Examples -------- >>> from photutils import CircularAperture >>> aper = CircularAperture([10., 20.], 3.) >>> aper = CircularAperture((10., 20.), 3.) >>> pos1 = (10., 20.) # (x, y) >>> pos2 = (30., 40.) >>> pos3 = (50., 60.) >>> aper = CircularAperture([pos1, pos2, pos3], 3.) >>> aper = CircularAperture((pos1, pos2, pos3), 3.) """ _shape_params = ('r',) positions = PixelPositions('positions') r = PositiveScalar('r') def __init__(self, positions, r): self.positions = positions self.r = r @property def _xy_extents(self): return self.r, self.r @property def area(self): return math.pi * self.r ** 2 def _to_patch(self, origin=(0, 0), indices=None, **kwargs): """ Return a `~matplotlib.patches.patch` for the aperture. Parameters ---------- origin : array_like, optional The ``(x, y)`` position of the origin of the displayed image. indices : int or array of int, optional The indices of the aperture positions to plot. kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. Returns ------- patch : `~matplotlib.patches.patch` or list of `~matplotlib.patches.patch` A patch for the aperture. If the aperture is scalar then a single `~matplotlib.patches.patch` is returned, otherwise a list of `~matplotlib.patches.patch` is returned. """ import matplotlib.patches as mpatches xy_positions, patch_kwargs = self._define_patch_params( origin=origin, indices=indices, **kwargs) patches = [] for xy_position in xy_positions: patches.append(mpatches.Circle(xy_position, self.r, **patch_kwargs)) if self.isscalar: return patches[0] else: return patches def to_sky(self, wcs): """ Convert the aperture to a `SkyCircularAperture` object defined in celestial coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `SkyCircularAperture` object A `SkyCircularAperture` object. """ return SkyCircularAperture(**self._to_sky_params(wcs)) class CircularAnnulus(CircularMaskMixin, PixelAperture): """ A circular annulus aperture defined in pixel coordinates. The aperture has a single fixed size/shape, but it can have multiple positions (see the ``positions`` input). Parameters ---------- positions : array_like or `~astropy.units.Quantity` The pixel coordinates of the aperture center(s) in one of the following formats: * single ``(x, y)`` pair as a tuple, list, or `~numpy.ndarray` * tuple, list, or `~numpy.ndarray` of ``(x, y)`` pairs * `~astropy.units.Quantity` instance of ``(x, y)`` pairs in pixel units r_in : float The inner radius of the circular annulus in pixels. r_out : float The outer radius of the circular annulus in pixels. Raises ------ ValueError : `ValueError` If inner radius (``r_in``) is greater than outer radius (``r_out``). ValueError : `ValueError` If inner radius (``r_in``) is negative. Examples -------- >>> from photutils import CircularAnnulus >>> aper = CircularAnnulus([10., 20.], 3., 5.) >>> aper = CircularAnnulus((10., 20.), 3., 5.) >>> pos1 = (10., 20.) # (x, y) >>> pos2 = (30., 40.) >>> pos3 = (50., 60.) >>> aper = CircularAnnulus([pos1, pos2, pos3], 3., 5.) >>> aper = CircularAnnulus((pos1, pos2, pos3), 3., 5.) """ _shape_params = ('r_in', 'r_out') positions = PixelPositions('positions') r_in = PositiveScalar('r_in') r_out = PositiveScalar('r_out') def __init__(self, positions, r_in, r_out): if not r_out > r_in: raise ValueError('r_out must be greater than r_in') self.positions = positions self.r_in = r_in self.r_out = r_out @property def _xy_extents(self): return self.r_out, self.r_out @property def area(self): return math.pi * (self.r_out ** 2 - self.r_in ** 2) def _to_patch(self, origin=(0, 0), indices=None, **kwargs): """ Return a `~matplotlib.patches.patch` for the aperture. Parameters ---------- origin : array_like, optional The ``(x, y)`` position of the origin of the displayed image. indices : int or array of int, optional The indices of the aperture positions to plot. kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. Returns ------- patch : `~matplotlib.patches.patch` or list of `~matplotlib.patches.patch` A patch for the aperture. If the aperture is scalar then a single `~matplotlib.patches.patch` is returned, otherwise a list of `~matplotlib.patches.patch` is returned. """ import matplotlib.patches as mpatches xy_positions, patch_kwargs = self._define_patch_params( origin=origin, indices=indices, **kwargs) patches = [] for xy_position in xy_positions: patch_inner = mpatches.Circle(xy_position, self.r_in) patch_outer = mpatches.Circle(xy_position, self.r_out) path = self._make_annulus_path(patch_inner, patch_outer) patches.append(mpatches.PathPatch(path, **patch_kwargs)) if self.isscalar: return patches[0] else: return patches def to_sky(self, wcs): """ Convert the aperture to a `SkyCircularAnnulus` object defined in celestial coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `SkyCircularAnnulus` object A `SkyCircularAnnulus` object. """ return SkyCircularAnnulus(**self._to_sky_params(wcs)) class SkyCircularAperture(SkyAperture): """ A circular aperture defined in sky coordinates. The aperture has a single fixed size/shape, but it can have multiple positions (see the ``positions`` input). Parameters ---------- positions : `~astropy.coordinates.SkyCoord` The celestial coordinates of the aperture center(s). This can be either scalar coordinates or an array of coordinates. r : scalar `~astropy.units.Quantity` The radius of the circle, either in angular or pixel units. Examples -------- >>> from astropy.coordinates import SkyCoord >>> import astropy.units as u >>> from photutils import SkyCircularAperture >>> positions = SkyCoord(ra=[10., 20.], dec=[30., 40.], unit='deg') >>> aper = SkyCircularAperture(positions, 0.5*u.arcsec) """ _shape_params = ('r',) positions = SkyCoordPositions('positions') r = AngleOrPixelScalarQuantity('r') def __init__(self, positions, r): self.positions = positions self.r = r def to_pixel(self, wcs): """ Convert the aperture to a `CircularAperture` object defined in pixel coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `CircularAperture` object A `CircularAperture` object. """ return CircularAperture(**self._to_pixel_params(wcs)) class SkyCircularAnnulus(SkyAperture): """ A circular annulus aperture defined in sky coordinates. The aperture has a single fixed size/shape, but it can have multiple positions (see the ``positions`` input). Parameters ---------- positions : `~astropy.coordinates.SkyCoord` The celestial coordinates of the aperture center(s). This can be either scalar coordinates or an array of coordinates. r_in : scalar `~astropy.units.Quantity` The inner radius of the circular annulus, either in angular or pixel units. r_out : scalar `~astropy.units.Quantity` The outer radius of the circular annulus, either in angular or pixel units. Examples -------- >>> from astropy.coordinates import SkyCoord >>> import astropy.units as u >>> from photutils import SkyCircularAnnulus >>> positions = SkyCoord(ra=[10., 20.], dec=[30., 40.], unit='deg') >>> aper = SkyCircularAnnulus(positions, 0.5*u.arcsec, 1.0*u.arcsec) """ _shape_params = ('r_in', 'r_out') positions = SkyCoordPositions('positions') r_in = AngleOrPixelScalarQuantity('r_in') r_out = AngleOrPixelScalarQuantity('r_out') def __init__(self, positions, r_in, r_out): if r_in.unit.physical_type != r_out.unit.physical_type: raise ValueError("r_in and r_out should either both be angles " "or in pixels.") self.positions = positions self.r_in = r_in self.r_out = r_out def to_pixel(self, wcs): """ Convert the aperture to a `CircularAnnulus` object defined in pixel coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `CircularAnnulus` object A `CircularAnnulus` object. """ return CircularAnnulus(**self._to_pixel_params(wcs)) photutils-0.7.2/photutils/aperture/core.py0000644000214200020070000006241113572576136023145 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module defines the base aperture classes. """ import abc import copy import warnings import numpy as np from astropy.coordinates import SkyCoord import astropy.units as u from astropy.utils import deprecated from astropy.utils.decorators import deprecated_renamed_argument from astropy.utils.exceptions import AstropyUserWarning from astropy.wcs.utils import wcs_to_celestial_frame from .bounding_box import BoundingBox from ._photometry_utils import (_handle_units, _prepare_photometry_data, _validate_inputs) from ..utils._wcs_helpers import (_pixel_to_world, _pixel_scale_angle_at_skycoord, _world_to_pixel) __all__ = ['Aperture', 'SkyAperture', 'PixelAperture'] class Aperture(metaclass=abc.ABCMeta): """ Abstract base class for all apertures. """ _shape_params = () positions = np.array(()) theta = None def __len__(self): if self.isscalar: raise TypeError('Scalar {0!r} object has no len()' .format(self.__class__.__name__)) return self.shape[0] def __getitem__(self, index): kwargs = dict() for param in self._shape_params: kwargs[param] = getattr(self, param) return self.__class__(self.positions[index], **kwargs) def __iter__(self): for i in range(len(self)): yield self.__getitem__(i) def _positions_str(self, prefix=None): if isinstance(self, PixelAperture): return np.array2string(self.positions, separator=', ', prefix=prefix) elif isinstance(self, SkyAperture): return repr(self.positions) else: raise TypeError('Aperture must be a subclass of PixelAperture ' 'or SkyAperture') def __repr__(self): prefix = '<{0}('.format(self.__class__.__name__) cls_info = [self._positions_str(prefix)] for param in self._shape_params: cls_info.append('{0}={1}'.format(param, getattr(self, param))) cls_info = ', '.join(cls_info) return '{0}{1})>'.format(prefix, cls_info) def __str__(self): prefix = 'positions' cls_info = [ ('Aperture', self.__class__.__name__), (prefix, self._positions_str(prefix + ': '))] if self._shape_params is not None: for param in self._shape_params: cls_info.append((param, getattr(self, param))) fmt = ['{0}: {1}'.format(key, val) for key, val in cls_info] return '\n'.join(fmt) @property def shape(self): """ The shape of the instance. """ if isinstance(self.positions, SkyCoord): return self.positions.shape else: return self.positions.shape[:-1] @property def isscalar(self): """ Whether the instance is scalar (i.e. a single position). """ return self.shape == () class PixelAperture(Aperture): """ Abstract base class for apertures defined in pixel coordinates. """ @property def _default_patch_properties(self): """ A dictionary of default matplotlib.patches.Patch properties. """ mpl_params = dict() # matplotlib.patches.Patch default is ``fill=True`` mpl_params['fill'] = False return mpl_params @staticmethod def _translate_mask_mode(mode, subpixels, rectangle=False): if mode not in ('center', 'subpixel', 'exact'): raise ValueError('Invalid mask mode: {0}'.format(mode)) if rectangle and mode == 'exact': warnings.warn('The "exact" method is not yet implemented for ' 'rectangular apertures -- using "subpixel" method ' 'with "subpixels=32"', AstropyUserWarning) mode = 'subpixel' subpixels = 32 if mode == 'subpixels': if not isinstance(subpixels, int) or subpixels <= 0: raise ValueError('subpixels must be a strictly positive ' 'integer') if mode == 'center': use_exact = 0 subpixels = 1 elif mode == 'subpixel': use_exact = 0 elif mode == 'exact': use_exact = 1 subpixels = 1 return use_exact, subpixels @property @abc.abstractmethod def _xy_extents(self): """ The (x, y) extents of the aperture measured from the center position. In other words, the (x, y) extents are half of the aperture minimal bounding box size in each dimension. """ raise NotImplementedError('Needs to be implemented in a subclass.') @property @deprecated('0.7', alternative='bbox') def bounding_boxes(self): return self.bbox @property def bbox(self): """ The minimal bounding box for the aperture. If the aperture is scalar then a single `~photutils.aperture.BoundingBox` is returned, otherwise a list of `~photutils.aperture.BoundingBox` is returned. """ positions = np.atleast_2d(self.positions) x_delta, y_delta = self._xy_extents xmin = positions[:, 0] - x_delta xmax = positions[:, 0] + x_delta ymin = positions[:, 1] - y_delta ymax = positions[:, 1] + y_delta bboxes = [BoundingBox.from_float(x0, x1, y0, y1) for x0, x1, y0, y1 in zip(xmin, xmax, ymin, ymax)] if self.isscalar: return bboxes[0] else: return bboxes @property def _centered_edges(self): """ A list of ``(xmin, xmax, ymin, ymax)`` tuples, one for each position, of the pixel edges after recentering the aperture at the origin. These pixel edges are used by the low-level `photutils.geometry` functions. """ edges = [] for position, bbox in zip(np.atleast_2d(self.positions), np.atleast_1d(self.bbox)): xmin = bbox.ixmin - 0.5 - position[0] xmax = bbox.ixmax - 0.5 - position[0] ymin = bbox.iymin - 0.5 - position[1] ymax = bbox.iymax - 0.5 - position[1] edges.append((xmin, xmax, ymin, ymax)) return edges @property def area(self): """ Return the exact area of the aperture shape. Returns ------- area : float The aperture area. """ raise NotImplementedError('Needs to be implemented in a subclass.') @deprecated('0.7', alternative=('e.g. np.sum(aper.to_mask().data) for a ' 'scalar aperture')) def mask_area(self, method='exact', subpixels=5): """ Return the area of the aperture mask. For ``method`` other than ``'exact'``, this area will be less than the exact analytical area (e.g. the ``area`` method). Note that for these methods, the values can also differ because of fractional pixel positions. Parameters ---------- method : {'exact', 'center', 'subpixel'}, optional The method used to determine the overlap of the aperture on the pixel grid. Not all options are available for all aperture types. Note that the more precise methods are generally slower. The following methods are available: * ``'exact'`` (default): The the exact fractional overlap of the aperture and each pixel is calculated. The returned mask will contain values between 0 and 1. * ``'center'``: A pixel is considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. The returned mask will contain values only of 0 (out) and 1 (in). * ``'subpixel'``: A pixel is divided into subpixels (see the ``subpixels`` keyword), each of which are considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. If ``subpixels=1``, this method is equivalent to ``'center'``. The returned mask will contain values between 0 and 1. subpixels : int, optional For the ``'subpixel'`` method, resample pixels by this factor in each dimension. That is, each pixel is divided into ``subpixels ** 2`` subpixels. Returns ------- area : float A list of the mask area (one per position) of the aperture. """ masks = self.to_mask(method=method, subpixels=subpixels) if self.isscalar: masks = (masks,) return [np.sum(mask.data) for mask in masks] @abc.abstractmethod def to_mask(self, method='exact', subpixels=5): """ Return a mask for the aperture. Parameters ---------- method : {'exact', 'center', 'subpixel'}, optional The method used to determine the overlap of the aperture on the pixel grid. Not all options are available for all aperture types. Note that the more precise methods are generally slower. The following methods are available: * ``'exact'`` (default): The the exact fractional overlap of the aperture and each pixel is calculated. The returned mask will contain values between 0 and 1. * ``'center'``: A pixel is considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. The returned mask will contain values only of 0 (out) and 1 (in). * ``'subpixel'``: A pixel is divided into subpixels (see the ``subpixels`` keyword), each of which are considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. If ``subpixels=1``, this method is equivalent to ``'center'``. The returned mask will contain values between 0 and 1. subpixels : int, optional For the ``'subpixel'`` method, resample pixels by this factor in each dimension. That is, each pixel is divided into ``subpixels ** 2`` subpixels. Returns ------- mask : `~photutils.aperture.ApertureMask` or list of `~photutils.aperture.ApertureMask` A mask for the aperture. If the aperture is scalar then a single `~photutils.aperture.ApertureMask` is returned, otherwise a list of `~photutils.aperture.ApertureMask` is returned. """ raise NotImplementedError('Needs to be implemented in a subclass.') def _do_photometry(self, data, variance, method='exact', subpixels=5, unit=None): aperture_sums = [] aperture_sum_errs = [] masks = self.to_mask(method=method, subpixels=subpixels) if self.isscalar: masks = (masks,) for apermask in masks: data_weighted = apermask.multiply(data) if data_weighted is None: aperture_sums.append(np.nan) else: aperture_sums.append(np.sum(data_weighted)) if variance is not None: variance_weighted = apermask.multiply(variance) if variance_weighted is None: aperture_sum_errs.append(np.nan) else: aperture_sum_errs.append( np.sqrt(np.sum(variance_weighted))) aperture_sums = np.array(aperture_sums) aperture_sum_errs = np.array(aperture_sum_errs) # apply units if unit is not None: aperture_sums = aperture_sums * unit # can't use *= w/old numpy aperture_sum_errs = aperture_sum_errs * unit return aperture_sums, aperture_sum_errs @deprecated_renamed_argument('unit', None, '0.7') def do_photometry(self, data, error=None, mask=None, method='exact', subpixels=5, unit=None): """ Perform aperture photometry on the input data. Parameters ---------- data : array_like or `~astropy.units.Quantity` instance The 2D array on which to perform photometry. ``data`` should be background subtracted. error : array_like or `~astropy.units.Quantity`, optional The pixel-wise Gaussian 1-sigma errors of the input ``data``. ``error`` is assumed to include *all* sources of error, including the Poisson error of the sources (see `~photutils.utils.calc_total_error`) . ``error`` must have the same shape as the input ``data``. mask : array_like (bool), optional A boolean mask with the same shape as ``data`` where a `True` value indicates the corresponding element of ``data`` is masked. Masked data are excluded from all calculations. method : {'exact', 'center', 'subpixel'}, optional The method used to determine the overlap of the aperture on the pixel grid. Not all options are available for all aperture types. Note that the more precise methods are generally slower. The following methods are available: * ``'exact'`` (default): The the exact fractional overlap of the aperture and each pixel is calculated. The returned mask will contain values between 0 and 1. * ``'center'``: A pixel is considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. The returned mask will contain values only of 0 (out) and 1 (in). * ``'subpixel'`` A pixel is divided into subpixels (see the ``subpixels`` keyword), each of which are considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. If ``subpixels=1``, this method is equivalent to ``'center'``. The returned mask will contain values between 0 and 1. subpixels : int, optional For the ``'subpixel'`` method, resample pixels by this factor in each dimension. That is, each pixel is divided into ``subpixels ** 2`` subpixels. unit : `~astropy.units.UnitBase` object or str, optional Deprecated in v0.7. An object that represents the unit associated with the input ``data`` and ``error`` arrays. Must be a `~astropy.units.UnitBase` object or a string parseable by the :mod:`~astropy.units` package. If ``data`` or ``error`` already have a different unit, the input ``unit`` will not be used and a warning will be raised. Returns ------- aperture_sums : `~numpy.ndarray` or `~astropy.units.Quantity` The sums within each aperture. aperture_sum_errs : `~numpy.ndarray` or `~astropy.units.Quantity` The errors on the sums within each aperture. """ # validate inputs data, error = _validate_inputs(data, error) # handle data, error, and unit inputs # output data and error are ndarray without units data, error, unit = _handle_units(data, error, unit) # compute variance and apply input mask data, variance = _prepare_photometry_data(data, error, mask) return self._do_photometry(data, variance, method=method, subpixels=subpixels, unit=unit) @staticmethod def _make_annulus_path(patch_inner, patch_outer): """ Define a matplotlib annulus path from two patches. This preserves the cubic Bezier curves (CURVE4) of the aperture paths. """ import matplotlib.path as mpath path_inner = patch_inner.get_path() transform_inner = patch_inner.get_transform() path_inner = transform_inner.transform_path(path_inner) path_outer = patch_outer.get_path() transform_outer = patch_outer.get_transform() path_outer = transform_outer.transform_path(path_outer) verts_inner = path_inner.vertices[:-1][::-1] verts_inner = np.concatenate((verts_inner, [verts_inner[-1]])) verts = np.vstack((path_outer.vertices, verts_inner)) codes = np.hstack((path_outer.codes, path_inner.codes)) return mpath.Path(verts, codes) def _define_patch_params(self, origin=(0, 0), indices=None, **kwargs): """ Define the aperture patch position and set any default matplotlib patch keywords (e.g. ``fill=False``). Parameters ---------- origin : array_like, optional The ``(x, y)`` position of the origin of the displayed image. indices : int or array of int, optional The indices of the aperture positions to plot. kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. Returns ------- xy_positions : `~numpy.ndarray` The aperture patch positions. patch_params : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. """ xy_positions = copy.deepcopy(np.atleast_2d(self.positions)) if indices is not None: xy_positions = xy_positions[np.atleast_1d(indices)] xy_positions[:, 0] -= origin[0] xy_positions[:, 1] -= origin[1] patch_params = self._default_patch_properties patch_params.update(kwargs) return xy_positions, patch_params @abc.abstractmethod def _to_patch(self, origin=(0, 0), indices=None, **kwargs): """ Return a `~matplotlib.patches.patch` for the aperture. Parameters ---------- origin : array_like, optional The ``(x, y)`` position of the origin of the displayed image. indices : int or array of int, optional The indices of the aperture positions to plot. kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. Returns ------- patch : `~matplotlib.patches.patch` or list of `~matplotlib.patches.patch` A patch for the aperture. If the aperture is scalar then a single `~matplotlib.patches.patch` is returned, otherwise a list of `~matplotlib.patches.patch` is returned. """ raise NotImplementedError('Needs to be implemented in a subclass.') @deprecated_renamed_argument('ax', 'axes', '0.7') @deprecated_renamed_argument('indices', None, '0.7', alternative=('indices directly on the ' 'aperture object ' '(e.g. aper[idx].plot())')) def plot(self, axes=None, origin=(0, 0), indices=None, **kwargs): """ Plot the aperture on a matplotlib `~matplotlib.axes.Axes` instance. Parameters ---------- axes : `matplotlib.axes.Axes` or `None`, optional The matplotlib axes on which to plot. If `None`, then the current `~matplotlib.axes.Axes` instance is used. origin : array_like, optional The ``(x, y)`` position of the origin of the displayed image. indices : int, array of int, or `None`, optional The indices of the aperture position(s) to plot. If `None` (default) then all aperture positions will be plotted. kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. """ import matplotlib.pyplot as plt if axes is None: axes = plt.gca() patches = self._to_patch(origin=origin, indices=indices, **kwargs) if self.isscalar: patches = (patches,) for patch in patches: axes.add_patch(patch) def _to_sky_params(self, wcs): """ Convert the pixel aperture parameters to those for a sky aperture. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- sky_params : `dict` A dictionary of parameters for an equivalent sky aperture. """ sky_params = {} xpos, ypos = np.transpose(self.positions) sky_params['positions'] = _pixel_to_world(xpos, ypos, wcs) # The aperture object must have a single value for each shape # parameter so we must use a single pixel scale for all positions. # Here, we define the scale at the WCS CRVAL position. crval = SkyCoord(*wcs.wcs.crval, frame=wcs_to_celestial_frame(wcs), unit=wcs.wcs.cunit) pixscale, angle = _pixel_scale_angle_at_skycoord(crval, wcs) shape_params = list(self._shape_params) theta_key = 'theta' if theta_key in shape_params: sky_params[theta_key] = (self.theta * u.rad) - angle.to(u.rad) shape_params.remove(theta_key) for shape_param in shape_params: value = getattr(self, shape_param) sky_params[shape_param] = (value * u.pix * pixscale).to(u.arcsec) return sky_params @abc.abstractmethod def to_sky(self, wcs): """ Convert the aperture to a `SkyAperture` object defined in celestial coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `SkyAperture` object A `SkyAperture` object. """ raise NotImplementedError('Needs to be implemented in a subclass.') class SkyAperture(Aperture): """ Abstract base class for all apertures defined in celestial coordinates. """ def _to_pixel_params(self, wcs): """ Convert the sky aperture parameters to those for a pixel aperture. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- pixel_params : `dict` A dictionary of parameters for an equivalent pixel aperture. """ pixel_params = {} xpos, ypos = _world_to_pixel(self.positions, wcs) pixel_params['positions'] = np.array([xpos, ypos]).transpose() # The aperture object must have a single value for each shape # parameter so we must use a single pixel scale for all positions. # Here, we define the scale at the WCS CRVAL position. crval = SkyCoord(*wcs.wcs.crval, frame=wcs_to_celestial_frame(wcs), unit=wcs.wcs.cunit) pixscale, angle = _pixel_scale_angle_at_skycoord(crval, wcs) shape_params = list(self._shape_params) theta_key = 'theta' if theta_key in shape_params: pixel_params[theta_key] = (self.theta + angle).to(u.radian).value shape_params.remove(theta_key) for shape_param in shape_params: value = getattr(self, shape_param) if value.unit.physical_type == 'angle': pixel_params[shape_param] = ((value / pixscale) .to(u.pixel).value) else: pixel_params[shape_param] = value.value return pixel_params @abc.abstractmethod def to_pixel(self, wcs): """ Convert the aperture to a `PixelAperture` object defined in pixel coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `PixelAperture` object A `PixelAperture` object. """ raise NotImplementedError('Needs to be implemented in a subclass.') photutils-0.7.2/photutils/aperture/ellipse.py0000644000214200020070000004632513572576136023660 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module defines elliptical and elliptical-annulus apertures in both pixel and sky coordinates. """ import math import astropy.units as u import numpy as np from .attributes import (AngleOrPixelScalarQuantity, AngleScalarQuantity, PixelPositions, PositiveScalar, Scalar, SkyCoordPositions) from .core import PixelAperture, SkyAperture from .mask import ApertureMask from ..geometry import elliptical_overlap_grid __all__ = ['EllipticalMaskMixin', 'EllipticalAperture', 'EllipticalAnnulus', 'SkyEllipticalAperture', 'SkyEllipticalAnnulus'] class EllipticalMaskMixin: """ Mixin class to create masks for elliptical and elliptical-annulus aperture objects. """ def to_mask(self, method='exact', subpixels=5): """ Return a mask for the aperture. Parameters ---------- method : {'exact', 'center', 'subpixel'}, optional The method used to determine the overlap of the aperture on the pixel grid. Not all options are available for all aperture types. Note that the more precise methods are generally slower. The following methods are available: * ``'exact'`` (default): The the exact fractional overlap of the aperture and each pixel is calculated. The returned mask will contain values between 0 and 1. * ``'center'``: A pixel is considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. The returned mask will contain values only of 0 (out) and 1 (in). * ``'subpixel'``: A pixel is divided into subpixels (see the ``subpixels`` keyword), each of which are considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. If ``subpixels=1``, this method is equivalent to ``'center'``. The returned mask will contain values between 0 and 1. subpixels : int, optional For the ``'subpixel'`` method, resample pixels by this factor in each dimension. That is, each pixel is divided into ``subpixels ** 2`` subpixels. Returns ------- mask : `~photutils.aperture.ApertureMask` or list of `~photutils.aperture.ApertureMask` A mask for the aperture. If the aperture is scalar then a single `~photutils.aperture.ApertureMask` is returned, otherwise a list of `~photutils.aperture.ApertureMask` is returned. """ use_exact, subpixels = self._translate_mask_mode(method, subpixels) if hasattr(self, 'a'): a = self.a b = self.b elif hasattr(self, 'a_in'): # annulus a = self.a_out b = self.b_out else: raise ValueError('Cannot determine the aperture shape.') masks = [] for bbox, edges in zip(np.atleast_1d(self.bbox), self._centered_edges): ny, nx = bbox.shape mask = elliptical_overlap_grid(edges[0], edges[1], edges[2], edges[3], nx, ny, a, b, self.theta, use_exact, subpixels) # subtract the inner ellipse for an annulus if hasattr(self, 'a_in'): mask -= elliptical_overlap_grid(edges[0], edges[1], edges[2], edges[3], nx, ny, self.a_in, self.b_in, self.theta, use_exact, subpixels) masks.append(ApertureMask(mask, bbox)) if self.isscalar: return masks[0] else: return masks @staticmethod def _calc_extents(semimajor_axis, semiminor_axis, theta): """ Calculate half of the bounding box extents of an ellipse. """ cos_theta = np.cos(theta) sin_theta = np.sin(theta) semimajor_x = semimajor_axis * cos_theta semimajor_y = semimajor_axis * sin_theta semiminor_x = semiminor_axis * -sin_theta semiminor_y = semiminor_axis * cos_theta x_extent = np.sqrt(semimajor_x**2 + semiminor_x**2) y_extent = np.sqrt(semimajor_y**2 + semiminor_y**2) return x_extent, y_extent class EllipticalAperture(EllipticalMaskMixin, PixelAperture): """ An elliptical aperture defined in pixel coordinates. The aperture has a single fixed size/shape, but it can have multiple positions (see the ``positions`` input). Parameters ---------- positions : array_like or `~astropy.units.Quantity` The pixel coordinates of the aperture center(s) in one of the following formats: * single ``(x, y)`` pair as a tuple, list, or `~numpy.ndarray` * tuple, list, or `~numpy.ndarray` of ``(x, y)`` pairs * `~astropy.units.Quantity` instance of ``(x, y)`` pairs in pixel units a : float The semimajor axis of the ellipse in pixels. b : float The semiminor axis of the ellipse in pixels. theta : float, optional The rotation angle in radians of the ellipse semimajor axis from the positive ``x`` axis. The rotation angle increases counterclockwise. The default is 0. Raises ------ ValueError : `ValueError` If either axis (``a`` or ``b``) is negative. Examples -------- >>> from photutils import EllipticalAperture >>> aper = EllipticalAperture([10., 20.], 5., 3.) >>> aper = EllipticalAperture((10., 20.), 5., 3., theta=np.pi) >>> pos1 = (10., 20.) # (x, y) >>> pos2 = (30., 40.) >>> pos3 = (50., 60.) >>> aper = EllipticalAperture([pos1, pos2, pos3], 5., 3.) >>> aper = EllipticalAperture((pos1, pos2, pos3), 5., 3., theta=np.pi) """ _shape_params = ('a', 'b', 'theta') positions = PixelPositions('positions') a = PositiveScalar('a') b = PositiveScalar('b') theta = Scalar('theta') def __init__(self, positions, a, b, theta=0.): self.positions = positions self.a = a self.b = b self.theta = theta @property def _xy_extents(self): return self._calc_extents(self.a, self.b, self.theta) @property def area(self): return math.pi * self.a * self.b def _to_patch(self, origin=(0, 0), indices=None, **kwargs): """ Return a `~matplotlib.patches.patch` for the aperture. Parameters ---------- origin : array_like, optional The ``(x, y)`` position of the origin of the displayed image. indices : int or array of int, optional The indices of the aperture positions to plot. kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. Returns ------- patch : `~matplotlib.patches.patch` or list of `~matplotlib.patches.patch` A patch for the aperture. If the aperture is scalar then a single `~matplotlib.patches.patch` is returned, otherwise a list of `~matplotlib.patches.patch` is returned. """ import matplotlib.patches as mpatches xy_positions, patch_kwargs = self._define_patch_params( origin=origin, indices=indices, **kwargs) patches = [] theta_deg = self.theta * 180. / np.pi for xy_position in xy_positions: patches.append(mpatches.Ellipse(xy_position, 2.*self.a, 2.*self.b, theta_deg, **patch_kwargs)) if self.isscalar: return patches[0] else: return patches def to_sky(self, wcs): """ Convert the aperture to a `SkyEllipticalAperture` object defined in celestial coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `SkyEllipticalAperture` object A `SkyEllipticalAperture` object. """ return SkyEllipticalAperture(**self._to_sky_params(wcs)) class EllipticalAnnulus(EllipticalMaskMixin, PixelAperture): """ An elliptical annulus aperture defined in pixel coordinates. The aperture has a single fixed size/shape, but it can have multiple positions (see the ``positions`` input). Parameters ---------- positions : array_like or `~astropy.units.Quantity` The pixel coordinates of the aperture center(s) in one of the following formats: * single ``(x, y)`` pair as a tuple, list, or `~numpy.ndarray` * tuple, list, or `~numpy.ndarray` of ``(x, y)`` pairs * `~astropy.units.Quantity` instance of ``(x, y)`` pairs in pixel units a_in : float The inner semimajor axis of the elliptical annulus in pixels. a_out : float The outer semimajor axis of the elliptical annulus in pixels. b_out : float The outer semiminor axis of the elliptical annulus in pixels. The inner semiminor axis is calculated as: .. math:: b_{in} = b_{out} \\left(\\frac{a_{in}}{a_{out}}\\right) theta : float, optional The rotation angle in radians of the ellipse semimajor axis from the positive ``x`` axis. The rotation angle increases counterclockwise. The default is 0. Raises ------ ValueError : `ValueError` If inner semimajor axis (``a_in``) is greater than outer semimajor axis (``a_out``). ValueError : `ValueError` If either the inner semimajor axis (``a_in``) or the outer semiminor axis (``b_out``) is negative. Examples -------- >>> from photutils import EllipticalAnnulus >>> aper = EllipticalAnnulus([10., 20.], 3., 8., 5.) >>> aper = EllipticalAnnulus((10., 20.), 3., 8., 5., theta=np.pi) >>> pos1 = (10., 20.) # (x, y) >>> pos2 = (30., 40.) >>> pos3 = (50., 60.) >>> aper = EllipticalAnnulus([pos1, pos2, pos3], 3., 8., 5.) >>> aper = EllipticalAnnulus((pos1, pos2, pos3), 3., 8., 5., theta=np.pi) """ _shape_params = ('a_in', 'a_out', 'b_out', 'theta') positions = PixelPositions('positions') a_in = PositiveScalar('a_in') a_out = PositiveScalar('a_out') b_out = PositiveScalar('b_out') theta = Scalar('theta') def __init__(self, positions, a_in, a_out, b_out, theta=0.): if not a_out > a_in: raise ValueError('"a_out" must be greater than "a_in".') self.positions = positions self.a_in = a_in self.a_out = a_out self.b_out = b_out self.b_in = self.b_out * self.a_in / self.a_out self.theta = theta @property def _xy_extents(self): return self._calc_extents(self.a_out, self.b_out, self.theta) @property def area(self): return math.pi * (self.a_out * self.b_out - self.a_in * self.b_in) def _to_patch(self, origin=(0, 0), indices=None, **kwargs): """ Return a `~matplotlib.patches.patch` for the aperture. Parameters ---------- origin : array_like, optional The ``(x, y)`` position of the origin of the displayed image. indices : int or array of int, optional The indices of the aperture positions to plot. kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. Returns ------- patch : `~matplotlib.patches.patch` or list of `~matplotlib.patches.patch` A patch for the aperture. If the aperture is scalar then a single `~matplotlib.patches.patch` is returned, otherwise a list of `~matplotlib.patches.patch` is returned. """ import matplotlib.patches as mpatches xy_positions, patch_kwargs = self._define_patch_params( origin=origin, indices=indices, **kwargs) patches = [] theta_deg = self.theta * 180. / np.pi for xy_position in xy_positions: patch_inner = mpatches.Ellipse(xy_position, 2.*self.a_in, 2.*self.b_in, theta_deg) patch_outer = mpatches.Ellipse(xy_position, 2.*self.a_out, 2.*self.b_out, theta_deg) path = self._make_annulus_path(patch_inner, patch_outer) patches.append(mpatches.PathPatch(path, **patch_kwargs)) if self.isscalar: return patches[0] else: return patches def to_sky(self, wcs): """ Convert the aperture to a `SkyEllipticalAnnulus` object defined in celestial coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `SkyEllipticalAnnulus` object A `SkyEllipticalAnnulus` object. """ return SkyEllipticalAnnulus(**self._to_sky_params(wcs)) class SkyEllipticalAperture(SkyAperture): """ An elliptical aperture defined in sky coordinates. The aperture has a single fixed size/shape, but it can have multiple positions (see the ``positions`` input). Parameters ---------- positions : `~astropy.coordinates.SkyCoord` The celestial coordinates of the aperture center(s). This can be either scalar coordinates or an array of coordinates. a : scalar `~astropy.units.Quantity` The semimajor axis of the ellipse, either in angular or pixel units. b : scalar `~astropy.units.Quantity` The semiminor axis of the ellipse, either in angular or pixel units. theta : scalar `~astropy.units.Quantity`, optional The position angle (in angular units) of the ellipse semimajor axis. For a right-handed world coordinate system, the position angle increases counterclockwise from North (PA=0). The default is 0 degrees. Examples -------- >>> from astropy.coordinates import SkyCoord >>> import astropy.units as u >>> from photutils import SkyEllipticalAperture >>> positions = SkyCoord(ra=[10., 20.], dec=[30., 40.], unit='deg') >>> aper = SkyEllipticalAperture(positions, 1.0*u.arcsec, 0.5*u.arcsec) """ _shape_params = ('a', 'b', 'theta') positions = SkyCoordPositions('positions') a = AngleOrPixelScalarQuantity('a') b = AngleOrPixelScalarQuantity('b') theta = AngleScalarQuantity('theta') def __init__(self, positions, a, b, theta=0.*u.deg): if a.unit.physical_type != b.unit.physical_type: raise ValueError("a and b should either both be angles " "or in pixels") self.positions = positions self.a = a self.b = b self.theta = theta def to_pixel(self, wcs): """ Convert the aperture to an `EllipticalAperture` object defined in pixel coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `EllipticalAperture` object An `EllipticalAperture` object. """ return EllipticalAperture(**self._to_pixel_params(wcs)) class SkyEllipticalAnnulus(SkyAperture): """ An elliptical annulus aperture defined in sky coordinates. The aperture has a single fixed size/shape, but it can have multiple positions (see the ``positions`` input). Parameters ---------- positions : `~astropy.coordinates.SkyCoord` The celestial coordinates of the aperture center(s). This can be either scalar coordinates or an array of coordinates. a_in : scalar `~astropy.units.Quantity` The inner semimajor axis, either in angular or pixel units. a_out : scalar `~astropy.units.Quantity` The outer semimajor axis, either in angular or pixel units. b_out : scalar `~astropy.units.Quantity` The outer semiminor axis, either in angular or pixel units. The inner semiminor axis is calculated as: .. math:: b_{in} = b_{out} \\left(\\frac{a_{in}}{a_{out}}\\right) theta : scalar `~astropy.units.Quantity`, optional The position angle (in angular units) of the ellipse semimajor axis. For a right-handed world coordinate system, the position angle increases counterclockwise from North (PA=0). The default is 0 degrees. Examples -------- >>> from astropy.coordinates import SkyCoord >>> import astropy.units as u >>> from photutils import SkyEllipticalAnnulus >>> positions = SkyCoord(ra=[10., 20.], dec=[30., 40.], unit='deg') >>> aper = SkyEllipticalAnnulus(positions, 0.5*u.arcsec, 2.0*u.arcsec, ... 1.0*u.arcsec) """ _shape_params = ('a_in', 'a_out', 'b_out', 'theta') positions = SkyCoordPositions('positions') a_in = AngleOrPixelScalarQuantity('a_in') a_out = AngleOrPixelScalarQuantity('a_out') b_out = AngleOrPixelScalarQuantity('b_out') theta = AngleScalarQuantity('theta') def __init__(self, positions, a_in, a_out, b_out, theta=0.*u.deg): if a_in.unit.physical_type != a_out.unit.physical_type: raise ValueError("a_in and a_out should either both be angles " "or in pixels") if a_out.unit.physical_type != b_out.unit.physical_type: raise ValueError("a_out and b_out should either both be angles " "or in pixels") self.positions = positions self.a_in = a_in self.a_out = a_out self.b_out = b_out self.b_in = self.b_out * self.a_in / self.a_out self.theta = theta def to_pixel(self, wcs): """ Convert the aperture to an `EllipticalAnnulus` object defined in pixel coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `EllipticalAnnulus` object An `EllipticalAnnulus` object. """ return EllipticalAnnulus(**self._to_pixel_params(wcs)) photutils-0.7.2/photutils/aperture/mask.py0000644000214200020070000002015513563423715023141 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module defines a class for aperture masks. """ import astropy.units as u import numpy as np __all__ = ['ApertureMask'] class ApertureMask: """ Class for an aperture mask. Parameters ---------- data : array_like A 2D array representing the fractional overlap of an aperture on the pixel grid. This should be the full-sized (i.e. not truncated) array that is the direct output of one of the low-level `photutils.geometry` functions. bbox : `photutils.aperture.BoundingBox` The bounding box object defining the aperture minimal bounding box. """ def __init__(self, data, bbox): self.data = np.asanyarray(data) if self.data.shape != bbox.shape: raise ValueError('mask data and bounding box must have the same ' 'shape') self.bbox = bbox self._mask = (self.data == 0) def __array__(self): """ Array representation of the mask data array (e.g., for matplotlib). """ return self.data @property def shape(self): """ The shape of the mask data array. """ return self.data.shape def _overlap_slices(self, shape): """ Calculate the slices for the overlapping part of the bounding box and an array of the given shape. Parameters ---------- shape : tuple of int The ``(ny, nx)`` shape of array where the slices are to be applied. Returns ------- slices_large : tuple of slices A tuple of slice objects for each axis of the large array, such that ``large_array[slices_large]`` extracts the region of the large array that overlaps with the small array. slices_small : slice A tuple of slice objects for each axis of the small array, such that ``small_array[slices_small]`` extracts the region of the small array that is inside the large array. """ if len(shape) != 2: raise ValueError('input shape must have 2 elements.') xmin = self.bbox.ixmin xmax = self.bbox.ixmax ymin = self.bbox.iymin ymax = self.bbox.iymax if xmin >= shape[1] or ymin >= shape[0] or xmax <= 0 or ymax <= 0: # no overlap of the aperture with the data return None, None slices_large = (slice(max(ymin, 0), min(ymax, shape[0])), slice(max(xmin, 0), min(xmax, shape[1]))) slices_small = (slice(max(-ymin, 0), min(ymax - ymin, shape[0] - ymin)), slice(max(-xmin, 0), min(xmax - xmin, shape[1] - xmin))) return slices_large, slices_small def _to_image_partial_overlap(self, image): """ Return an image of the mask in a 2D array, where the mask is not fully within the image (i.e. partial or no overlap). """ # find the overlap of the mask on the output image shape slices_large, slices_small = self._overlap_slices(image.shape) if slices_small is None: return None # no overlap # insert the mask into the output image image[slices_large] = self.data[slices_small] return image def to_image(self, shape): """ Return an image of the mask in a 2D array of the given shape, taking any edge effects into account. Parameters ---------- shape : tuple of int The ``(ny, nx)`` shape of the output array. Returns ------- result : `~numpy.ndarray` A 2D array of the mask. """ if len(shape) != 2: raise ValueError('input shape must have 2 elements.') image = np.zeros(shape) if self.bbox.ixmin < 0 or self.bbox.iymin < 0: return self._to_image_partial_overlap(image) try: image[self.bbox.slices] = self.data except ValueError: # partial or no overlap image = self._to_image_partial_overlap(image) return image def cutout(self, data, fill_value=0., copy=False): """ Create a cutout from the input data over the mask bounding box, taking any edge effects into account. Parameters ---------- data : array_like A 2D array on which to apply the aperture mask. fill_value : float, optional The value used to fill pixels where the aperture mask does not overlap with the input ``data``. The default is 0. copy : bool, optional If `True` then the returned cutout array will always be hold a copy of the input ``data``. If `False` and the mask is fully within the input ``data``, then the returned cutout array will be a view into the input ``data``. In cases where the mask partially overlaps or has no overlap with the input ``data``, the returned cutout array will always hold a copy of the input ``data`` (i.e. this keyword has no effect). Returns ------- result : `~numpy.ndarray` A 2D array cut out from the input ``data`` representing the same cutout region as the aperture mask. If there is a partial overlap of the aperture mask with the input data, pixels outside of the data will be assigned to ``fill_value``. `None` is returned if there is no overlap of the aperture with the input ``data``. """ data = np.asanyarray(data) if data.ndim != 2: raise ValueError('data must be a 2D array.') partial_overlap = False if self.bbox.ixmin < 0 or self.bbox.iymin < 0: partial_overlap = True if not partial_overlap: # try this for speed -- the result may still be a partial # overlap, in which case the next block will be triggered if copy: cutout = data[self.bbox.slices].copy() # preserves Quantity else: cutout = data[self.bbox.slices] if partial_overlap or (cutout.shape != self.shape): slices_large, slices_small = self._overlap_slices(data.shape) if slices_small is None: return None # no overlap # cutout is a copy cutout = np.zeros(self.shape, dtype=data.dtype) cutout[:] = fill_value cutout[slices_small] = data[slices_large] if isinstance(data, u.Quantity): cutout = u.Quantity(cutout, unit=data.unit) return cutout def multiply(self, data, fill_value=0.): """ Multiply the aperture mask with the input data, taking any edge effects into account. The result is a mask-weighted cutout from the data. Parameters ---------- data : array_like or `~astropy.units.Quantity` The 2D array to multiply with the aperture mask. fill_value : float, optional The value is used to fill pixels where the aperture mask does not overlap with the input ``data``. The default is 0. Returns ------- result : `~numpy.ndarray` or `None` A 2D mask-weighted cutout from the input ``data``. If there is a partial overlap of the aperture mask with the input data, pixels outside of the data will be assigned to ``fill_value`` before being multipled with the mask. `None` is returned if there is no overlap of the aperture with the input ``data``. """ cutout = self.cutout(data, fill_value=fill_value) if cutout is None: return None else: weighted_cutout = cutout * self.data # needed to zero out non-finite data values outside of the # mask but within the bounding box weighted_cutout[self._mask] = 0. return weighted_cutout photutils-0.7.2/photutils/aperture/photometry.py0000644000214200020070000002571313572576136024433 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module defines tools to perform aperture photometry. """ import warnings from collections import OrderedDict import numpy as np from astropy.nddata import NDData, StdDevUncertainty from astropy.table import QTable import astropy.units as u from astropy.utils.decorators import deprecated_renamed_argument from astropy.utils.exceptions import AstropyUserWarning from .core import Aperture, SkyAperture from ._photometry_utils import (_handle_hdu_input, _handle_units, _prepare_photometry_data, _validate_inputs) from ..utils.misc import _get_version_info __all__ = ['aperture_photometry'] @deprecated_renamed_argument('unit', None, '0.7') def aperture_photometry(data, apertures, error=None, mask=None, method='exact', subpixels=5, unit=None, wcs=None): """ Perform aperture photometry on the input data by summing the flux within the given aperture(s). Parameters ---------- data : array_like, `~astropy.units.Quantity`, `~astropy.io.fits.ImageHDU`, `~astropy.io.fits.HDUList`, or `~astropy.nddata.NDData` The 2D array on which to perform photometry. ``data`` should be background-subtracted. Units can be used during the photometry, either provided with the data (e.g. `~astropy.units.Quantity` or `~astropy.nddata.NDData` inputs) or the ``unit`` keyword. If ``data`` is an `~astropy.io.fits.ImageHDU` or `~astropy.io.fits.HDUList`, the unit is determined from the ``'BUNIT'`` header keyword. `~astropy.io.fits.ImageHDU` or `~astropy.io.fits.HDUList` inputs were deprecated in v0.7. If ``data`` is a `~astropy.units.Quantity` array, then ``error`` (if input) must also be a `~astropy.units.Quantity` array with the same units. See the Notes section below for more information about `~astropy.nddata.NDData` input. apertures : `~photutils.aperture.Aperture` or list of `~photutils.aperture.Aperture` The aperture(s) to use for the photometry. If ``apertures`` is a list of `~photutils.aperture.Aperture` then they all must have the same position(s). error : array_like or `~astropy.units.Quantity`, optional The pixel-wise Gaussian 1-sigma errors of the input ``data``. ``error`` is assumed to include *all* sources of error, including the Poisson error of the sources (see `~photutils.utils.calc_total_error`) . ``error`` must have the same shape as the input ``data``. If a `~astropy.units.Quantity` array, then ``data`` must also be a `~astropy.units.Quantity` array with the same units. mask : array_like (bool), optional A boolean mask with the same shape as ``data`` where a `True` value indicates the corresponding element of ``data`` is masked. Masked data are excluded from all calculations. method : {'exact', 'center', 'subpixel'}, optional The method used to determine the overlap of the aperture on the pixel grid. Not all options are available for all aperture types. Note that the more precise methods are generally slower. The following methods are available: * ``'exact'`` (default): The the exact fractional overlap of the aperture and each pixel is calculated. The returned mask will contain values between 0 and 1. * ``'center'``: A pixel is considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. The returned mask will contain values only of 0 (out) and 1 (in). * ``'subpixel'``: A pixel is divided into subpixels (see the ``subpixels`` keyword), each of which are considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. If ``subpixels=1``, this method is equivalent to ``'center'``. The returned mask will contain values between 0 and 1. subpixels : int, optional For the ``'subpixel'`` method, resample pixels by this factor in each dimension. That is, each pixel is divided into ``subpixels ** 2`` subpixels. unit : `~astropy.units.UnitBase` object or str, optional Deprecated in v0.7. An object that represents the unit associated with the input ``data`` and ``error`` arrays. Must be a `~astropy.units.UnitBase` object or a string parseable by the :mod:`~astropy.units` package. If ``data`` or ``error`` already have a different unit, the input ``unit`` will not be used and a warning will be raised. If ``data`` is an `~astropy.io.fits.ImageHDU` or `~astropy.io.fits.HDUList`, ``unit`` will override the ``'BUNIT'`` header keyword. This keyword should be used sparingly (it exists to support the input of `~astropy.nddata.NDData` objects). Instead one should input the ``data`` (and optional ``error``) as `~astropy.units.Quantity` objects. wcs : WCS object, optional A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Used only if the input ``apertures`` contains a `SkyAperture` object. If ``data`` is an `~astropy.io.fits.ImageHDU` or `~astropy.io.fits.HDUList`, ``wcs`` overrides any WCS transformation present in the header. Returns ------- table : `~astropy.table.QTable` A table of the photometry with the following columns: * ``'id'``: The source ID. * ``'xcenter'``, ``'ycenter'``: The ``x`` and ``y`` pixel coordinates of the input aperture center(s). * ``'sky_center'``: The sky coordinates of the input aperture center(s). Returned only if the input ``apertures`` is a `SkyAperture` object. * ``'aperture_sum'``: The sum of the values within the aperture. * ``'aperture_sum_err'``: The corresponding uncertainty in the ``'aperture_sum'`` values. Returned only if the input ``error`` is not `None`. The table metadata includes the Astropy and Photutils version numbers and the `aperture_photometry` calling arguments. Notes ----- If the input ``data`` is a `~astropy.nddata.NDData` instance, then the ``error``, ``mask``, ``unit``, and ``wcs`` keyword inputs are ignored. Instead, these values should be defined as attributes in the `~astropy.nddata.NDData` object. In the case of ``error``, it must be defined in the ``uncertainty`` attribute with a `~astropy.nddata.StdDevUncertainty` instance. """ if isinstance(data, NDData): nddata_attr = {'error': error, 'mask': mask, 'unit': unit, 'wcs': wcs} for key, value in nddata_attr.items(): if value is not None: warnings.warn('The {0!r} keyword is be ignored. Its value ' 'is obtained from the input NDData object.' .format(key), AstropyUserWarning) mask = data.mask wcs = data.wcs if isinstance(data.uncertainty, StdDevUncertainty): if data.uncertainty.unit is None: error = data.uncertainty.array else: error = data.uncertainty.array * data.uncertainty.unit if data.unit is not None: data = u.Quantity(data.data, unit=data.unit) else: data = data.data return aperture_photometry(data, apertures, error=error, mask=mask, method=method, subpixels=subpixels, wcs=wcs) # handle FITS HDU input data data, bunit, fits_wcs = _handle_hdu_input(data) # NOTE: input unit overrides bunit if unit is None: unit = bunit # NOTE: input wcs overrides FITS WCS if not wcs: wcs = fits_wcs # validate inputs data, error = _validate_inputs(data, error) # handle data, error, and unit inputs # output data and error are ndarray without units data, error, unit = _handle_units(data, error, unit) # compute variance and apply input mask data, variance = _prepare_photometry_data(data, error, mask) single_aperture = False if isinstance(apertures, Aperture): single_aperture = True apertures = (apertures,) # convert sky to pixel apertures skyaper = False if isinstance(apertures[0], SkyAperture): if wcs is None: raise ValueError('A WCS transform must be defined by the input ' 'data or the wcs keyword when using a ' 'SkyAperture object.') # used to include SkyCoord position in the output table skyaper = True skycoord_pos = apertures[0].positions apertures = [aper.to_pixel(wcs) for aper in apertures] # compare positions in pixels to avoid comparing SkyCoord objects positions = apertures[0].positions for aper in apertures[1:]: if not np.array_equal(aper.positions, positions): raise ValueError('Input apertures must all have identical ' 'positions.') # define output table meta data meta = OrderedDict() meta['name'] = 'Aperture photometry results' meta['version'] = _get_version_info() calling_args = "method='{0}', subpixels={1}".format(method, subpixels) meta['aperture_photometry_args'] = calling_args tbl = QTable(meta=meta) positions = np.atleast_2d(apertures[0].positions) tbl['id'] = np.arange(positions.shape[0], dtype=int) + 1 xypos_pixel = np.transpose(positions) * u.pixel tbl['xcenter'] = xypos_pixel[0] tbl['ycenter'] = xypos_pixel[1] if skyaper: if skycoord_pos.isscalar: # create length-1 SkyCoord array tbl['sky_center'] = skycoord_pos.reshape((-1,)) else: tbl['sky_center'] = skycoord_pos sum_key_main = 'aperture_sum' sum_err_key_main = 'aperture_sum_err' for i, aper in enumerate(apertures): aper_sum, aper_sum_err = aper._do_photometry(data, variance, method=method, subpixels=subpixels, unit=unit) sum_key = sum_key_main sum_err_key = sum_err_key_main if not single_aperture: sum_key += '_{}'.format(i) sum_err_key += '_{}'.format(i) tbl[sum_key] = aper_sum if error is not None: tbl[sum_err_key] = aper_sum_err return tbl photutils-0.7.2/photutils/aperture/rectangle.py0000644000214200020070000005265413572576136024171 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module defines rectangular and rectangular-annulus apertures in both pixel and sky coordinates. """ import math import astropy.units as u import numpy as np from .attributes import (AngleOrPixelScalarQuantity, AngleScalarQuantity, PixelPositions, PositiveScalar, Scalar, SkyCoordPositions) from .core import PixelAperture, SkyAperture from .mask import ApertureMask from ..geometry import rectangular_overlap_grid __all__ = ['RectangularMaskMixin', 'RectangularAperture', 'RectangularAnnulus', 'SkyRectangularAperture', 'SkyRectangularAnnulus'] class RectangularMaskMixin: """ Mixin class to create masks for rectangular or rectangular-annulus aperture objects. """ def to_mask(self, method='exact', subpixels=5): """ Return a mask for the aperture. Parameters ---------- method : {'exact', 'center', 'subpixel'}, optional The method used to determine the overlap of the aperture on the pixel grid. Not all options are available for all aperture types. Note that the more precise methods are generally slower. The following methods are available: * ``'exact'`` (default): The the exact fractional overlap of the aperture and each pixel is calculated. The returned mask will contain values between 0 and 1. * ``'center'``: A pixel is considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. The returned mask will contain values only of 0 (out) and 1 (in). * ``'subpixel'``: A pixel is divided into subpixels (see the ``subpixels`` keyword), each of which are considered to be entirely in or out of the aperture depending on whether its center is in or out of the aperture. If ``subpixels=1``, this method is equivalent to ``'center'``. The returned mask will contain values between 0 and 1. subpixels : int, optional For the ``'subpixel'`` method, resample pixels by this factor in each dimension. That is, each pixel is divided into ``subpixels ** 2`` subpixels. Returns ------- mask : `~photutils.aperture.ApertureMask` or list of `~photutils.aperture.ApertureMask` A mask for the aperture. If the aperture is scalar then a single `~photutils.aperture.ApertureMask` is returned, otherwise a list of `~photutils.aperture.ApertureMask` is returned. """ _, subpixels = self._translate_mask_mode(method, subpixels, rectangle=True) if hasattr(self, 'w'): w = self.w h = self.h elif hasattr(self, 'w_out'): # annulus w = self.w_out h = self.h_out h_in = self.w_in * self.h_out / self.w_out else: raise ValueError('Cannot determine the aperture radius.') masks = [] for bbox, edges in zip(np.atleast_1d(self.bbox), self._centered_edges): ny, nx = bbox.shape mask = rectangular_overlap_grid(edges[0], edges[1], edges[2], edges[3], nx, ny, w, h, self.theta, 0, subpixels) # subtract the inner circle for an annulus if hasattr(self, 'w_in'): mask -= rectangular_overlap_grid(edges[0], edges[1], edges[2], edges[3], nx, ny, self.w_in, h_in, self.theta, 0, subpixels) masks.append(ApertureMask(mask, bbox)) if self.isscalar: return masks[0] else: return masks @staticmethod def _calc_extents(width, height, theta): """ Calculate half of the bounding box extents of an ellipse. """ half_width = width / 2. half_height = height / 2. sin_theta = math.sin(theta) cos_theta = math.cos(theta) x_extent1 = abs((half_width * cos_theta) - (half_height * sin_theta)) x_extent2 = abs((half_width * cos_theta) + (half_height * sin_theta)) y_extent1 = abs((half_width * sin_theta) + (half_height * cos_theta)) y_extent2 = abs((half_width * sin_theta) - (half_height * cos_theta)) x_extent = max(x_extent1, x_extent2) y_extent = max(y_extent1, y_extent2) return x_extent, y_extent @staticmethod def _lower_left_positions(positions, width, height, theta): """ Calculate lower-left positions from the input center positions. Used for creating `~matplotlib.patches.Rectangle` patch for the aperture. """ half_width = width / 2. half_height = height / 2. sin_theta = math.sin(theta) cos_theta = math.cos(theta) xshift = (half_height * sin_theta) - (half_width * cos_theta) yshift = -(half_height * cos_theta) - (half_width * sin_theta) return np.atleast_2d(positions) + np.array([xshift, yshift]) class RectangularAperture(RectangularMaskMixin, PixelAperture): """ A rectangular aperture defined in pixel coordinates. The aperture has a single fixed size/shape, but it can have multiple positions (see the ``positions`` input). Parameters ---------- positions : array_like or `~astropy.units.Quantity` The pixel coordinates of the aperture center(s) in one of the following formats: * single ``(x, y)`` pair as a tuple, list, or `~numpy.ndarray` * tuple, list, or `~numpy.ndarray` of ``(x, y)`` pairs * `~astropy.units.Quantity` instance of ``(x, y)`` pairs in pixel units w : float The full width of the rectangle in pixels. For ``theta=0`` the width side is along the ``x`` axis. h : float The full height of the rectangle in pixels. For ``theta=0`` the height side is along the ``y`` axis. theta : float, optional The rotation angle in radians of the rectangle "width" side from the positive ``x`` axis. The rotation angle increases counterclockwise. The default is 0. Raises ------ ValueError : `ValueError` If either width (``w``) or height (``h``) is negative. Examples -------- >>> from photutils import RectangularAperture >>> aper = RectangularAperture([10., 20.], 5., 3.) >>> aper = RectangularAperture((10., 20.), 5., 3., theta=np.pi) >>> pos1 = (10., 20.) # (x, y) >>> pos2 = (30., 40.) >>> pos3 = (50., 60.) >>> aper = RectangularAperture([pos1, pos2, pos3], 5., 3.) >>> aper = RectangularAperture((pos1, pos2, pos3), 5., 3., theta=np.pi) """ _shape_params = ('w', 'h', 'theta') positions = PixelPositions('positions') w = PositiveScalar('w') h = PositiveScalar('h') theta = Scalar('theta') def __init__(self, positions, w, h, theta=0.): self.positions = positions self.w = w self.h = h self.theta = theta @property def _xy_extents(self): return self._calc_extents(self.w, self.h, self.theta) @property def area(self): return self.w * self.h def _to_patch(self, origin=(0, 0), indices=None, **kwargs): """ Return a `~matplotlib.patches.patch` for the aperture. Parameters ---------- origin : array_like, optional The ``(x, y)`` position of the origin of the displayed image. indices : int or array of int, optional The indices of the aperture positions to plot. kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. Returns ------- patch : `~matplotlib.patches.patch` or list of `~matplotlib.patches.patch` A patch for the aperture. If the aperture is scalar then a single `~matplotlib.patches.patch` is returned, otherwise a list of `~matplotlib.patches.patch` is returned. """ import matplotlib.patches as mpatches xy_positions, patch_kwargs = self._define_patch_params( origin=origin, indices=indices, **kwargs) xy_positions = self._lower_left_positions(xy_positions, self.w, self.h, self.theta) patches = [] theta_deg = self.theta * 180. / np.pi for xy_position in xy_positions: patches.append(mpatches.Rectangle(xy_position, self.w, self.h, theta_deg, **patch_kwargs)) if self.isscalar: return patches[0] else: return patches def to_sky(self, wcs): """ Convert the aperture to a `SkyRectangularAperture` object defined in celestial coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `SkyRectangularAperture` object A `SkyRectangularAperture` object. """ return SkyRectangularAperture(**self._to_sky_params(wcs)) class RectangularAnnulus(RectangularMaskMixin, PixelAperture): """ A rectangular annulus aperture defined in pixel coordinates. The aperture has a single fixed size/shape, but it can have multiple positions (see the ``positions`` input). Parameters ---------- positions : array_like or `~astropy.units.Quantity` The pixel coordinates of the aperture center(s) in one of the following formats: * single ``(x, y)`` pair as a tuple, list, or `~numpy.ndarray` * tuple, list, or `~numpy.ndarray` of ``(x, y)`` pairs * `~astropy.units.Quantity` instance of ``(x, y)`` pairs in pixel units w_in : float The inner full width of the rectangular annulus in pixels. For ``theta=0`` the width side is along the ``x`` axis. w_out : float The outer full width of the rectangular annulus in pixels. For ``theta=0`` the width side is along the ``x`` axis. h_out : float The outer full height of the rectangular annulus in pixels. The inner full height is calculated as: .. math:: h_{in} = h_{out} \\left(\\frac{w_{in}}{w_{out}}\\right) For ``theta=0`` the height side is along the ``y`` axis. theta : float, optional The rotation angle in radians of the rectangle "width" side from the positive ``x`` axis. The rotation angle increases counterclockwise. The default is 0. Raises ------ ValueError : `ValueError` If inner width (``w_in``) is greater than outer width (``w_out``). ValueError : `ValueError` If either the inner width (``w_in``) or the outer height (``h_out``) is negative. Examples -------- >>> from photutils import RectangularAnnulus >>> aper = RectangularAnnulus([10., 20.], 3., 8., 5.) >>> aper = RectangularAnnulus((10., 20.), 3., 8., 5., theta=np.pi) >>> pos1 = (10., 20.) # (x, y) >>> pos2 = (30., 40.) >>> pos3 = (50., 60.) >>> aper = RectangularAnnulus([pos1, pos2, pos3], 3., 8., 5.) >>> aper = RectangularAnnulus((pos1, pos2, pos3), 3., 8., 5., theta=np.pi) """ _shape_params = ('w_in', 'w_out', 'h_out', 'theta') positions = PixelPositions('positions') w_in = PositiveScalar('w_in') w_out = PositiveScalar('w_out') h_out = PositiveScalar('h_out') theta = Scalar('theta') def __init__(self, positions, w_in, w_out, h_out, theta=0.): if not w_out > w_in: raise ValueError("'w_out' must be greater than 'w_in'") self.positions = positions self.w_in = w_in self.w_out = w_out self.h_out = h_out self.h_in = self.w_in * self.h_out / self.w_out self.theta = theta @property def _xy_extents(self): return self._calc_extents(self.w_out, self.h_out, self.theta) @property def area(self): return self.w_out * self.h_out - self.w_in * self.h_in def _to_patch(self, origin=(0, 0), indices=None, **kwargs): """ Return a `~matplotlib.patches.patch` for the aperture. Parameters ---------- origin : array_like, optional The ``(x, y)`` position of the origin of the displayed image. indices : int or array of int, optional The indices of the aperture positions to plot. kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. Returns ------- patch : `~matplotlib.patches.patch` or list of `~matplotlib.patches.patch` A patch for the aperture. If the aperture is scalar then a single `~matplotlib.patches.patch` is returned, otherwise a list of `~matplotlib.patches.patch` is returned. """ import matplotlib.patches as mpatches xy_positions, patch_kwargs = self._define_patch_params( origin=origin, indices=indices, **kwargs) inner_xy_positions = self._lower_left_positions(xy_positions, self.w_in, self.h_in, self.theta) outer_xy_positions = self._lower_left_positions(xy_positions, self.w_out, self.h_out, self.theta) patches = [] theta_deg = self.theta * 180. / np.pi for xy_in, xy_out in zip(inner_xy_positions, outer_xy_positions): patch_inner = mpatches.Rectangle(xy_in, self.w_in, self.h_in, theta_deg) patch_outer = mpatches.Rectangle(xy_out, self.w_out, self.h_out, theta_deg) path = self._make_annulus_path(patch_inner, patch_outer) patches.append(mpatches.PathPatch(path, **patch_kwargs)) if self.isscalar: return patches[0] else: return patches def to_sky(self, wcs): """ Convert the aperture to a `SkyRectangularAnnulus` object defined in celestial coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `SkyRectangularAnnulus` object A `SkyRectangularAnnulus` object. """ return SkyRectangularAnnulus(**self._to_sky_params(wcs)) class SkyRectangularAperture(SkyAperture): """ A rectangular aperture defined in sky coordinates. The aperture has a single fixed size/shape, but it can have multiple positions (see the ``positions`` input). Parameters ---------- positions : `~astropy.coordinates.SkyCoord` The celestial coordinates of the aperture center(s). This can be either scalar coordinates or an array of coordinates. w : scalar `~astropy.units.Quantity` The full width of the rectangle, either in angular or pixel units. For ``theta=0`` the width side is along the North-South axis. h : scalar `~astropy.units.Quantity` The full height of the rectangle, either in angular or pixel units. For ``theta=0`` the height side is along the East-West axis. theta : scalar `~astropy.units.Quantity`, optional The position angle (in angular units) of the rectangle "width" side. For a right-handed world coordinate system, the position angle increases counterclockwise from North (PA=0). The default is 0 degrees. Examples -------- >>> from astropy.coordinates import SkyCoord >>> import astropy.units as u >>> from photutils import SkyRectangularAperture >>> positions = SkyCoord(ra=[10., 20.], dec=[30., 40.], unit='deg') >>> aper = SkyRectangularAperture(positions, 1.0*u.arcsec, 0.5*u.arcsec) """ _shape_params = ('w', 'h', 'theta') positions = SkyCoordPositions('positions') w = AngleOrPixelScalarQuantity('w') h = AngleOrPixelScalarQuantity('h') theta = AngleScalarQuantity('theta') def __init__(self, positions, w, h, theta=0.*u.deg): if w.unit.physical_type != h.unit.physical_type: raise ValueError("'w' and 'h' should either both be angles or " "in pixels") self.positions = positions self.w = w self.h = h self.theta = theta def to_pixel(self, wcs): """ Convert the aperture to a `RectangularAperture` object defined in pixel coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `RectangularAperture` object A `RectangularAperture` object. """ return RectangularAperture(**self._to_pixel_params(wcs)) class SkyRectangularAnnulus(SkyAperture): """ A rectangular annulus aperture defined in sky coordinates. The aperture has a single fixed size/shape, but it can have multiple positions (see the ``positions`` input). Parameters ---------- positions : `~astropy.coordinates.SkyCoord` The celestial coordinates of the aperture center(s). This can be either scalar coordinates or an array of coordinates. w_in : scalar `~astropy.units.Quantity` The inner full width of the rectangular annulus, either in angular or pixel units. For ``theta=0`` the width side is along the North-South axis. w_out : scalar `~astropy.units.Quantity` The outer full width of the rectangular annulus, either in angular or pixel units. For ``theta=0`` the width side is along the North-South axis. h_out : scalar `~astropy.units.Quantity` The outer full height of the rectangular annulus, either in angular or pixel units. The inner full height is calculated as: .. math:: h_{in} = h_{out} \\left(\\frac{w_{in}}{w_{out}}\\right) For ``theta=0`` the height side is along the East-West axis. theta : scalar `~astropy.units.Quantity`, optional The position angle (in angular units) of the rectangle "width" side. For a right-handed world coordinate system, the position angle increases counterclockwise from North (PA=0). The default is 0 degrees. Examples -------- >>> from astropy.coordinates import SkyCoord >>> import astropy.units as u >>> from photutils import SkyRectangularAnnulus >>> positions = SkyCoord(ra=[10., 20.], dec=[30., 40.], unit='deg') >>> aper = SkyRectangularAnnulus(positions, 3.0*u.arcsec, 8.0*u.arcsec, ... 5.0*u.arcsec) """ _shape_params = ('w_in', 'w_out', 'h_out', 'theta') positions = SkyCoordPositions('positions') w_in = AngleOrPixelScalarQuantity('w_in') w_out = AngleOrPixelScalarQuantity('w_out') h_out = AngleOrPixelScalarQuantity('h_out') theta = AngleScalarQuantity('theta') def __init__(self, positions, w_in, w_out, h_out, theta=0.*u.deg): if w_in.unit.physical_type != w_out.unit.physical_type: raise ValueError("w_in and w_out should either both be angles or " "in pixels") if w_out.unit.physical_type != h_out.unit.physical_type: raise ValueError("w_out and h_out should either both be angles " "or in pixels") self.positions = positions self.w_in = w_in self.w_out = w_out self.h_out = h_out self.h_in = self.w_in * self.h_out / self.w_out self.theta = theta def to_pixel(self, wcs): """ Convert the aperture to a `RectangularAnnulus` object defined in pixel coordinates. Parameters ---------- wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- aperture : `RectangularAnnulus` object A `RectangularAnnulus` object. """ return RectangularAnnulus(**self._to_pixel_params(wcs)) photutils-0.7.2/photutils/aperture/tests/0000755000214200020070000000000013573510273022770 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/aperture/tests/__init__.py0000644000214200020070000000000013563423715025072 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/aperture/tests/test_aperture_common.py0000644000214200020070000000351413563423715027606 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides base classes for aperture tests. """ from astropy.coordinates import SkyCoord from astropy.tests.helper import assert_quantity_allclose from numpy.testing import assert_array_equal class BaseTestApertureParams: index = 2 slc = slice(0, 2) expected_slc_len = 2 class BaseTestAperture(BaseTestApertureParams): def test_index(self): aper = self.aperture[self.index] assert isinstance(aper, self.aperture.__class__) assert aper.isscalar expected_positions = self.aperture.positions[self.index] if isinstance(expected_positions, SkyCoord): assert_quantity_allclose(aper.positions.ra, expected_positions.ra) assert_quantity_allclose(aper.positions.dec, expected_positions.dec) else: assert_array_equal(aper.positions, expected_positions) for shape_param in aper._shape_params: assert (getattr(aper, shape_param) == getattr(self.aperture, shape_param)) def test_slice(self): aper = self.aperture[self.slc] assert isinstance(aper, self.aperture.__class__) assert len(aper) == self.expected_slc_len expected_positions = self.aperture.positions[self.slc] if isinstance(self.aperture.positions, SkyCoord): assert_quantity_allclose(aper.positions.ra, expected_positions.ra) assert_quantity_allclose(aper.positions.dec, expected_positions.dec) else: assert_array_equal(aper.positions, expected_positions) for shape_param in aper._shape_params: assert (getattr(aper, shape_param) == getattr(self.aperture, shape_param)) photutils-0.7.2/photutils/aperture/tests/test_bounding_box.py0000644000214200020070000001020313563423715027055 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the bounding_box module. """ from numpy.testing import assert_allclose import pytest from ..bounding_box import BoundingBox from ..rectangle import RectangularAperture try: import matplotlib # noqa HAS_MATPLOTLIB = True except ImportError: HAS_MATPLOTLIB = False def test_bounding_box_init(): bbox = BoundingBox(1, 10, 2, 20) assert bbox.ixmin == 1 assert bbox.ixmax == 10 assert bbox.iymin == 2 assert bbox.iymax == 20 def test_bounding_box_init_minmax(): with pytest.raises(ValueError): BoundingBox(100, 1, 1, 100) with pytest.raises(ValueError): BoundingBox(1, 100, 100, 1) def test_bounding_box_inputs(): with pytest.raises(TypeError): BoundingBox([1], [10], [2], [9]) with pytest.raises(TypeError): BoundingBox([1, 2], 10, 2, 9) with pytest.raises(TypeError): BoundingBox(1.0, 10.0, 2.0, 9.0) with pytest.raises(TypeError): BoundingBox(1.3, 10, 2, 9) with pytest.raises(TypeError): BoundingBox(1, 10.3, 2, 9) with pytest.raises(TypeError): BoundingBox(1, 10, 2.3, 9) with pytest.raises(TypeError): BoundingBox(1, 10, 2, 9.3) def test_bounding_box_from_float(): # This is the example from the method docstring bbox = BoundingBox.from_float(xmin=1.0, xmax=10.0, ymin=2.0, ymax=20.0) assert bbox == BoundingBox(ixmin=1, ixmax=11, iymin=2, iymax=21) bbox = BoundingBox.from_float(xmin=1.4, xmax=10.4, ymin=1.6, ymax=10.6) assert bbox == BoundingBox(ixmin=1, ixmax=11, iymin=2, iymax=12) def test_bounding_box_eq(): bbox = BoundingBox(1, 10, 2, 20) assert bbox == BoundingBox(1, 10, 2, 20) assert bbox != BoundingBox(9, 10, 2, 20) assert bbox != BoundingBox(1, 99, 2, 20) assert bbox != BoundingBox(1, 10, 9, 20) assert bbox != BoundingBox(1, 10, 2, 99) with pytest.raises(TypeError): assert bbox == (1, 10, 2, 20) def test_bounding_box_repr(): bbox = BoundingBox(1, 10, 2, 20) assert repr(bbox) == 'BoundingBox(ixmin=1, ixmax=10, iymin=2, iymax=20)' def test_bounding_box_shape(): bbox = BoundingBox(1, 10, 2, 20) assert bbox.shape == (18, 9) def test_bounding_box_slices(): bbox = BoundingBox(1, 10, 2, 20) assert bbox.slices == (slice(2, 20), slice(1, 10)) def test_bounding_box_extent(): bbox = BoundingBox(1, 10, 2, 20) assert_allclose(bbox.extent, (0.5, 9.5, 1.5, 19.5)) @pytest.mark.skipif('not HAS_MATPLOTLIB') def test_bounding_box_as_artist(): bbox = BoundingBox(1, 10, 2, 20) patch = bbox.as_artist() assert_allclose(patch.get_xy(), (0.5, 1.5)) assert_allclose(patch.get_width(), 9) assert_allclose(patch.get_height(), 18) @pytest.mark.skipif('not HAS_MATPLOTLIB') def test_bounding_box_to_aperture(): bbox = BoundingBox(1, 10, 2, 20) aper = RectangularAperture((5, 10.5), w=9., h=18., theta=0.) bbox_aper = bbox.to_aperture() assert_allclose(bbox_aper.positions, aper.positions) assert bbox_aper.w == aper.w assert bbox_aper.h == aper.h assert bbox_aper.theta == aper.theta @pytest.mark.skipif('not HAS_MATPLOTLIB') def test_bounding_box_plot(): # TODO: check the content of the plot bbox = BoundingBox(1, 10, 2, 20) bbox.plot() def test_bounding_box_union(): bbox1 = BoundingBox(1, 10, 2, 20) bbox2 = BoundingBox(5, 21, 7, 32) bbox_union_expected = BoundingBox(1, 21, 2, 32) bbox_union1 = bbox1 | bbox2 bbox_union2 = bbox1.union(bbox2) assert bbox_union1 == bbox_union_expected assert bbox_union1 == bbox_union2 with pytest.raises(TypeError): bbox1.union((5, 21, 7, 32)) def test_bounding_box_intersect(): bbox1 = BoundingBox(1, 10, 2, 20) bbox2 = BoundingBox(5, 21, 7, 32) bbox_intersect_expected = BoundingBox(5, 10, 7, 20) bbox_intersect1 = bbox1 & bbox2 bbox_intersect2 = bbox1.intersection(bbox2) assert bbox_intersect1 == bbox_intersect_expected assert bbox_intersect1 == bbox_intersect2 with pytest.raises(TypeError): bbox1.intersection((5, 21, 7, 32)) assert bbox1.intersection(BoundingBox(30, 40, 50, 60)) is None photutils-0.7.2/photutils/aperture/tests/test_circle.py0000644000214200020070000000166413563423715025654 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the circle module. """ from astropy.coordinates import SkyCoord import astropy.units as u import numpy as np from .test_aperture_common import BaseTestAperture from ..circle import (CircularAperture, CircularAnnulus, SkyCircularAperture, SkyCircularAnnulus) POSITIONS = [(10, 20), (30, 40), (50, 60), (70, 80)] RA, DEC = np.transpose(POSITIONS) SKYCOORD = SkyCoord(ra=RA, dec=DEC, unit='deg') UNIT = u.arcsec class TestCircularAperture(BaseTestAperture): aperture = CircularAperture(POSITIONS, r=3.) class TestCircularAnnulus(BaseTestAperture): aperture = CircularAnnulus(POSITIONS, r_in=3., r_out=7.) class TestSkyCircularAperture(BaseTestAperture): aperture = SkyCircularAperture(SKYCOORD, r=3.*UNIT) class TestSkyCircularAnnulus(BaseTestAperture): aperture = SkyCircularAnnulus(SKYCOORD, r_in=3.*UNIT, r_out=7.*UNIT) photutils-0.7.2/photutils/aperture/tests/test_ellipse.py0000644000214200020070000000225113563423715026041 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the ellipse module. """ from astropy.coordinates import SkyCoord import astropy.units as u import numpy as np from .test_aperture_common import BaseTestAperture from ..ellipse import (EllipticalAperture, EllipticalAnnulus, SkyEllipticalAperture, SkyEllipticalAnnulus) POSITIONS = [(10, 20), (30, 40), (50, 60), (70, 80)] RA, DEC = np.transpose(POSITIONS) SKYCOORD = SkyCoord(ra=RA, dec=DEC, unit='deg') UNIT = u.arcsec class TestEllipticalAperture(BaseTestAperture): aperture = EllipticalAperture(POSITIONS, a=10., b=5., theta=np.pi/2.) class TestEllipticalAnnulus(BaseTestAperture): aperture = EllipticalAnnulus(POSITIONS, a_in=10., a_out=20., b_out=17, theta=np.pi/3) class TestSkyEllipticalAperture(BaseTestAperture): aperture = SkyEllipticalAperture(SKYCOORD, a=10.*UNIT, b=5.*UNIT, theta=30*u.deg) class TestSkyEllipticalAnnulus(BaseTestAperture): aperture = SkyEllipticalAnnulus(SKYCOORD, a_in=10.*UNIT, a_out=20.*UNIT, b_out=17.*UNIT, theta=60*u.deg) photutils-0.7.2/photutils/aperture/tests/test_mask.py0000644000214200020070000000641113563423715025341 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the mask module. """ import astropy.units as u import numpy as np from numpy.testing import assert_allclose import pytest from ..bounding_box import BoundingBox from ..circle import CircularAperture from ..mask import ApertureMask try: import matplotlib # noqa HAS_MATPLOTLIB = True except ImportError: HAS_MATPLOTLIB = False POSITIONS = [(-20, -20), (-20, 20), (20, -20), (60, 60)] def test_mask_input_shapes(): with pytest.raises(ValueError): mask_data = np.ones((10, 10)) bbox = BoundingBox(5, 10, 5, 10) ApertureMask(mask_data, bbox) def test_mask_array(): mask_data = np.ones((10, 10)) bbox = BoundingBox(5, 15, 5, 15) mask = ApertureMask(mask_data, bbox) data = np.array(mask) assert_allclose(data, mask.data) def test_mask_cutout_shape(): mask_data = np.ones((10, 10)) bbox = BoundingBox(5, 15, 5, 15) mask = ApertureMask(mask_data, bbox) with pytest.raises(ValueError): mask.cutout(np.arange(10)) with pytest.raises(ValueError): mask._overlap_slices((10,)) with pytest.raises(ValueError): mask.to_image((10,)) def test_mask_cutout_copy(): data = np.ones((50, 50)) aper = CircularAperture((25, 25), r=10.) mask = aper.to_mask() cutout = mask.cutout(data, copy=True) data[25, 25] = 100. assert cutout[10, 10] == 1. def test_mask_cutout_copy_quantity(): data = np.ones((50, 50)) * u.adu aper = CircularAperture((25, 25), r=10.) mask = aper.to_mask() cutout = mask.cutout(data, copy=True) assert cutout.unit == data.unit data[25, 25] = 100. * u.adu assert cutout[10, 10].value == 1. @pytest.mark.parametrize('position', POSITIONS) def test_mask_cutout_no_overlap(position): data = np.ones((50, 50)) aper = CircularAperture(position, r=10.) mask = aper.to_mask() cutout = mask.cutout(data) assert cutout is None weighted_data = mask.multiply(data) assert weighted_data is None image = mask.to_image(data.shape) assert image is None @pytest.mark.parametrize('position', POSITIONS) def test_mask_cutout_partial_overlap(position): data = np.ones((50, 50)) aper = CircularAperture(position, r=30.) mask = aper.to_mask() cutout = mask.cutout(data) assert cutout.shape == mask.shape weighted_data = mask.multiply(data) assert weighted_data.shape == mask.shape image = mask.to_image(data.shape) assert image.shape == data.shape def test_mask_multiply(): radius = 10. data = np.ones((50, 50)) aper = CircularAperture((25, 25), r=radius) mask = aper.to_mask() data_weighted = mask.multiply(data) assert np.sum(data_weighted) == radius**2 * np.pi # test that multiply() returns a copy data[25, 25] = 100. assert data_weighted[10, 10] == 1. def test_mask_multiply_quantity(): radius = 10. data = np.ones((50, 50)) * u.adu aper = CircularAperture((25, 25), r=radius) mask = aper.to_mask() data_weighted = mask.multiply(data) assert data_weighted.unit == u.adu assert np.sum(data_weighted.value) == radius**2 * np.pi # test that multiply() returns a copy data[25, 25] = 100. * u.adu assert data_weighted[10, 10].value == 1. photutils-0.7.2/photutils/aperture/tests/test_photometry.py0000644000214200020070000010441713572573665026637 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the photometry module. """ import pytest import numpy as np from numpy.testing import (assert_allclose, assert_array_equal, assert_array_less) from astropy.coordinates import SkyCoord from astropy.io import fits from astropy.nddata import NDData, StdDevUncertainty from astropy.table import Table import astropy.units as u from astropy.utils import minversion from astropy.wcs import WCS from astropy.wcs.utils import pixel_to_skycoord from ..photometry import aperture_photometry from ..circle import (CircularAperture, CircularAnnulus, SkyCircularAperture, SkyCircularAnnulus) from ..ellipse import (EllipticalAperture, EllipticalAnnulus, SkyEllipticalAperture, SkyEllipticalAnnulus) from ..rectangle import (RectangularAperture, RectangularAnnulus, SkyRectangularAperture, SkyRectangularAnnulus) from ...datasets import get_path, make_4gaussians_image, make_wcs try: import matplotlib # noqa HAS_MATPLOTLIB = True except ImportError: HAS_MATPLOTLIB = False NUMPY_LT_1_14 = not minversion('numpy', '1.14dev') APERTURE_CL = [CircularAperture, CircularAnnulus, EllipticalAperture, EllipticalAnnulus, RectangularAperture, RectangularAnnulus] TEST_APERTURES = list(zip(APERTURE_CL, ((3.,), (3., 5.), (3., 5., 1.), (3., 5., 4., 1.), (5, 8, np.pi / 4), (8, 12, 8, np.pi / 8)))) @pytest.mark.parametrize(('aperture_class', 'params'), TEST_APERTURES) def test_outside_array(aperture_class, params): data = np.ones((10, 10), dtype=float) aperture = aperture_class((-60, 60), *params) fluxtable = aperture_photometry(data, aperture) # aperture is fully outside array: assert np.isnan(fluxtable['aperture_sum']) @pytest.mark.parametrize(('aperture_class', 'params'), TEST_APERTURES) def test_inside_array_simple(aperture_class, params): data = np.ones((40, 40), dtype=float) aperture = aperture_class((20., 20.), *params) table1 = aperture_photometry(data, aperture, method='center', subpixels=10) table2 = aperture_photometry(data, aperture, method='subpixel', subpixels=10) table3 = aperture_photometry(data, aperture, method='exact', subpixels=10) true_flux = aperture.area if not isinstance(aperture, (RectangularAperture, RectangularAnnulus)): assert_allclose(table3['aperture_sum'], true_flux) assert_allclose(table2['aperture_sum'], table3['aperture_sum'], atol=0.1) assert table1['aperture_sum'] < table3['aperture_sum'] @pytest.mark.skipif('not HAS_MATPLOTLIB') @pytest.mark.parametrize(('aperture_class', 'params'), TEST_APERTURES) def test_aperture_plots(aperture_class, params): # This test should run without any errors, and there is no return # value. # TODO: check the content of the plot aperture = aperture_class((20., 20.), *params) aperture.plot() def test_aperture_pixel_positions(): pos1 = (10, 20) pos2 = [(10, 20)] pos3 = u.Quantity((10, 20), unit=u.pixel) pos4 = u.Quantity([(10, 20)], unit=u.pixel) r = 3 ap1 = CircularAperture(pos1, r) ap2 = CircularAperture(pos2, r) ap3 = CircularAperture(pos3, r) ap4 = CircularAperture(pos4, r) assert not np.array_equal(ap1.positions, ap2.positions) assert_allclose(ap1.positions, ap3.positions) assert_allclose(ap2.positions, ap4.positions) class BaseTestAperturePhotometry: def test_array_error(self): # Array error error = np.ones(self.data.shape, dtype=float) if not hasattr(self, 'mask'): mask = None true_error = np.sqrt(self.area) else: mask = self.mask # 1 masked pixel true_error = np.sqrt(self.area - 1) table1 = aperture_photometry(self.data, self.aperture, method='center', mask=mask, error=error) table2 = aperture_photometry(self.data, self.aperture, method='subpixel', subpixels=12, mask=mask, error=error) table3 = aperture_photometry(self.data, self.aperture, method='exact', mask=mask, error=error) if not isinstance(self.aperture, (RectangularAperture, RectangularAnnulus)): assert_allclose(table3['aperture_sum'], self.true_flux) assert_allclose(table2['aperture_sum'], table3['aperture_sum'], atol=0.1) assert np.all(table1['aperture_sum'] < table3['aperture_sum']) if not isinstance(self.aperture, (RectangularAperture, RectangularAnnulus)): assert_allclose(table3['aperture_sum_err'], true_error) assert_allclose(table2['aperture_sum_err'], table3['aperture_sum_err'], atol=0.1) assert np.all(table1['aperture_sum_err'] < table3['aperture_sum_err']) class TestCircular(BaseTestAperturePhotometry): def setup_class(self): self.data = np.ones((40, 40), dtype=float) position = (20., 20.) r = 10. self.aperture = CircularAperture(position, r) self.area = np.pi * r * r self.true_flux = self.area class TestCircularArray(BaseTestAperturePhotometry): def setup_class(self): self.data = np.ones((40, 40), dtype=float) position = ((20., 20.), (25., 25.)) r = 10. self.aperture = CircularAperture(position, r) self.area = np.pi * r * r self.area = np.array((self.area, ) * 2) self.true_flux = self.area class TestCircularAnnulus(BaseTestAperturePhotometry): def setup_class(self): self.data = np.ones((40, 40), dtype=float) position = (20., 20.) r_in = 8. r_out = 10. self.aperture = CircularAnnulus(position, r_in, r_out) self.area = np.pi * (r_out * r_out - r_in * r_in) self.true_flux = self.area class TestCircularAnnulusArray(BaseTestAperturePhotometry): def setup_class(self): self.data = np.ones((40, 40), dtype=float) position = ((20., 20.), (25., 25.)) r_in = 8. r_out = 10. self.aperture = CircularAnnulus(position, r_in, r_out) self.area = np.pi * (r_out * r_out - r_in * r_in) self.area = np.array((self.area, ) * 2) self.true_flux = self.area class TestElliptical(BaseTestAperturePhotometry): def setup_class(self): self.data = np.ones((40, 40), dtype=float) position = (20., 20.) a = 10. b = 5. theta = -np.pi / 4. self.aperture = EllipticalAperture(position, a, b, theta) self.area = np.pi * a * b self.true_flux = self.area class TestEllipticalAnnulus(BaseTestAperturePhotometry): def setup_class(self): self.data = np.ones((40, 40), dtype=float) position = (20., 20.) a_in = 5. a_out = 8. b_out = 5. theta = -np.pi / 4. self.aperture = EllipticalAnnulus(position, a_in, a_out, b_out, theta) self.area = (np.pi * (a_out * b_out) - np.pi * (a_in * b_out * a_in / a_out)) self.true_flux = self.area class TestRectangularAperture(BaseTestAperturePhotometry): def setup_class(self): self.data = np.ones((40, 40), dtype=float) position = (20., 20.) h = 5. w = 8. theta = np.pi / 4. self.aperture = RectangularAperture(position, w, h, theta) self.area = h * w self.true_flux = self.area class TestRectangularAnnulus(BaseTestAperturePhotometry): def setup_class(self): self.data = np.ones((40, 40), dtype=float) position = (20., 20.) h_out = 8. w_in = 8. w_out = 12. h_in = w_in * h_out / w_out theta = np.pi / 8. self.aperture = RectangularAnnulus(position, w_in, w_out, h_out, theta) self.area = h_out * w_out - h_in * w_in self.true_flux = self.area class TestMaskedSkipCircular(BaseTestAperturePhotometry): def setup_class(self): self.data = np.ones((40, 40), dtype=float) self.mask = np.zeros((40, 40), dtype=bool) self.mask[20, 20] = True position = (20., 20.) r = 10. self.aperture = CircularAperture(position, r) self.area = np.pi * r * r self.true_flux = self.area - 1 class BaseTestDifferentData: def test_basic_circular_aperture_photometry(self): aperture = CircularAperture(self.position, self.radius) table = aperture_photometry(self.data, aperture, method='exact') assert_allclose(table['aperture_sum'].value, self.true_flux) assert table['aperture_sum'].unit, self.fluxunit assert np.all(table['xcenter'].value == np.transpose(self.position)[0]) assert np.all(table['ycenter'].value == np.transpose(self.position)[1]) class TestInputNDData(BaseTestDifferentData): def setup_class(self): data = np.ones((40, 40), dtype=float) self.data = NDData(data, unit=u.adu) self.radius = 3 self.position = [(20, 20), (30, 30)] self.true_flux = np.pi * self.radius * self.radius self.fluxunit = u.adu @pytest.mark.remote_data def test_wcs_based_photometry_to_catalogue(): pathcat = get_path('spitzer_example_catalog.xml', location='remote') pathhdu = get_path('spitzer_example_image.fits', location='remote') hdu = fits.open(pathhdu) data = u.Quantity(hdu[0].data, unit=hdu[0].header['BUNIT']) wcs = WCS(hdu[0].header) scale = hdu[0].header['PIXSCAL1'] catalog = Table.read(pathcat) pos_skycoord = SkyCoord(catalog['l'], catalog['b'], frame='galactic') photometry_skycoord = aperture_photometry( data, SkyCircularAperture(pos_skycoord, 4 * u.arcsec), wcs=wcs) photometry_skycoord_pix = aperture_photometry( data, SkyCircularAperture(pos_skycoord, 4. / scale * u.pixel), wcs=wcs) assert_allclose(photometry_skycoord['aperture_sum'], photometry_skycoord_pix['aperture_sum']) # Photometric unit conversion is needed to match the catalogue factor = (1.2 * u.arcsec) ** 2 / u.pixel converted_aperture_sum = (photometry_skycoord['aperture_sum'] * factor).to(u.mJy / u.pixel) fluxes_catalog = catalog['f4_5'].filled() # There shouldn't be large outliers, but some differences is OK, as # fluxes_catalog is based on PSF photometry, etc. assert_allclose(fluxes_catalog, converted_aperture_sum.value, rtol=1e0) assert(np.mean(np.fabs(((fluxes_catalog - converted_aperture_sum.value) / fluxes_catalog))) < 0.1) # close the file hdu.close() def test_wcs_based_photometry(): data = make_4gaussians_image() wcs = make_wcs(data.shape) # hard wired positions in make_4gaussian_image pos_orig_pixel = u.Quantity(([160., 25., 150., 90.], [70., 40., 25., 60.]), unit=u.pixel) try: pos_skycoord = wcs.pixel_to_world(pos_orig_pixel[0], pos_orig_pixel[1]) except AttributeError: # for Astropy < 3.1 pos_skycoord = pixel_to_skycoord(pos_orig_pixel[0], pos_orig_pixel[1], wcs) pos_skycoord_s = pos_skycoord[2] photometry_skycoord_circ = aperture_photometry( data, SkyCircularAperture(pos_skycoord, 3 * u.arcsec), wcs=wcs) photometry_skycoord_circ_2 = aperture_photometry( data, SkyCircularAperture(pos_skycoord, 2 * u.arcsec), wcs=wcs) photometry_skycoord_circ_s = aperture_photometry( data, SkyCircularAperture(pos_skycoord_s, 3 * u.arcsec), wcs=wcs) assert_allclose(photometry_skycoord_circ['aperture_sum'][2], photometry_skycoord_circ_s['aperture_sum']) photometry_skycoord_circ_ann = aperture_photometry( data, SkyCircularAnnulus(pos_skycoord, 2 * u.arcsec, 3 * u.arcsec), wcs=wcs) photometry_skycoord_circ_ann_s = aperture_photometry( data, SkyCircularAnnulus(pos_skycoord_s, 2 * u.arcsec, 3 * u.arcsec), wcs=wcs) assert_allclose(photometry_skycoord_circ_ann['aperture_sum'][2], photometry_skycoord_circ_ann_s['aperture_sum']) assert_allclose(photometry_skycoord_circ_ann['aperture_sum'], photometry_skycoord_circ['aperture_sum'] - photometry_skycoord_circ_2['aperture_sum']) photometry_skycoord_ell = aperture_photometry( data, SkyEllipticalAperture(pos_skycoord, 3 * u.arcsec, 3.0001 * u.arcsec, 45 * u.arcsec), wcs=wcs) photometry_skycoord_ell_2 = aperture_photometry( data, SkyEllipticalAperture(pos_skycoord, 2 * u.arcsec, 2.0001 * u.arcsec, 45 * u.arcsec), wcs=wcs) photometry_skycoord_ell_s = aperture_photometry( data, SkyEllipticalAperture(pos_skycoord_s, 3 * u.arcsec, 3.0001 * u.arcsec, 45 * u.arcsec), wcs=wcs) photometry_skycoord_ell_ann = aperture_photometry( data, SkyEllipticalAnnulus(pos_skycoord, 2 * u.arcsec, 3 * u.arcsec, 3.0001 * u.arcsec, 45 * u.arcsec), wcs=wcs) photometry_skycoord_ell_ann_s = aperture_photometry( data, SkyEllipticalAnnulus(pos_skycoord_s, 2 * u.arcsec, 3 * u.arcsec, 3.0001 * u.arcsec, 45 * u.arcsec), wcs=wcs) assert_allclose(photometry_skycoord_ell['aperture_sum'][2], photometry_skycoord_ell_s['aperture_sum']) assert_allclose(photometry_skycoord_ell_ann['aperture_sum'][2], photometry_skycoord_ell_ann_s['aperture_sum']) assert_allclose(photometry_skycoord_ell['aperture_sum'], photometry_skycoord_circ['aperture_sum'], rtol=5e-3) assert_allclose(photometry_skycoord_ell_ann['aperture_sum'], photometry_skycoord_ell['aperture_sum'] - photometry_skycoord_ell_2['aperture_sum'], rtol=1e-4) photometry_skycoord_rec = aperture_photometry( data, SkyRectangularAperture(pos_skycoord, 6 * u.arcsec, 6 * u.arcsec, 0 * u.arcsec), method='subpixel', subpixels=20, wcs=wcs) photometry_skycoord_rec_4 = aperture_photometry( data, SkyRectangularAperture(pos_skycoord, 4 * u.arcsec, 4 * u.arcsec, 0 * u.arcsec), method='subpixel', subpixels=20, wcs=wcs) photometry_skycoord_rec_s = aperture_photometry( data, SkyRectangularAperture(pos_skycoord_s, 6 * u.arcsec, 6 * u.arcsec, 0 * u.arcsec), method='subpixel', subpixels=20, wcs=wcs) photometry_skycoord_rec_ann = aperture_photometry( data, SkyRectangularAnnulus(pos_skycoord, 4 * u.arcsec, 6 * u.arcsec, 6 * u.arcsec, 0 * u.arcsec), method='subpixel', subpixels=20, wcs=wcs) photometry_skycoord_rec_ann_s = aperture_photometry( data, SkyRectangularAnnulus(pos_skycoord_s, 4 * u.arcsec, 6 * u.arcsec, 6 * u.arcsec, 0 * u.arcsec), method='subpixel', subpixels=20, wcs=wcs) assert_allclose(photometry_skycoord_rec['aperture_sum'][2], photometry_skycoord_rec_s['aperture_sum']) assert np.all(photometry_skycoord_rec['aperture_sum'] > photometry_skycoord_circ['aperture_sum']) assert_allclose(photometry_skycoord_rec_ann['aperture_sum'][2], photometry_skycoord_rec_ann_s['aperture_sum']) assert_allclose(photometry_skycoord_rec_ann['aperture_sum'], photometry_skycoord_rec['aperture_sum'] - photometry_skycoord_rec_4['aperture_sum'], rtol=1e-4) def test_basic_circular_aperture_photometry_unit(): data1 = np.ones((40, 40), dtype=float) data2 = u.Quantity(data1*u.adu) radius = 3 position = (20, 20) true_flux = np.pi * radius * radius unit = u.adu table1 = aperture_photometry(data1, CircularAperture(position, radius)) table2 = aperture_photometry(data2, CircularAperture(position, radius)) assert_allclose(table1['aperture_sum'], true_flux) assert_allclose(table2['aperture_sum'].value, true_flux) assert table2['aperture_sum'].unit == data2.unit == unit def test_aperture_photometry_with_error_units(): """Test aperture_photometry when error has units (see #176).""" data1 = np.ones((40, 40), dtype=float) data2 = u.Quantity(data1, unit=u.adu) error = u.Quantity(data1, unit=u.adu) radius = 3 true_flux = np.pi * radius * radius unit = u.adu position = (20, 20) table1 = aperture_photometry(data2, CircularAperture(position, radius), error=error) assert_allclose(table1['aperture_sum'].value, true_flux) assert_allclose(table1['aperture_sum_err'].value, np.sqrt(true_flux)) assert table1['aperture_sum'].unit == unit assert table1['aperture_sum_err'].unit == unit def test_aperture_photometry_inputs_with_mask(): """ Test that aperture_photometry does not modify the input data or error array when a mask is input. """ data = np.ones((5, 5)) aperture = CircularAperture((2, 2), 2.) mask = np.zeros_like(data, dtype=bool) data[2, 2] = 100. # bad pixel mask[2, 2] = True error = np.sqrt(data) data_in = data.copy() error_in = error.copy() t1 = aperture_photometry(data, aperture, error=error, mask=mask) assert_array_equal(data, data_in) assert_array_equal(error, error_in) assert_allclose(t1['aperture_sum'][0], 11.5663706144) t2 = aperture_photometry(data, aperture) assert_allclose(t2['aperture_sum'][0], 111.566370614) TEST_ELLIPSE_EXACT_APERTURES = [(3.469906, 3.923861394, 3.), (0.3834415188257778, 0.3834415188257778, 0.3)] @pytest.mark.parametrize('x,y,r', TEST_ELLIPSE_EXACT_APERTURES) def test_ellipse_exact_grid(x, y, r): """ Test elliptical exact aperture photometry on a grid of pixel positions. This is a regression test for the bug discovered in this issue: https://github.com/astropy/photutils/issues/198 """ data = np.ones((10, 10)) aperture = EllipticalAperture((x, y), r, r, 0.) t = aperture_photometry(data, aperture, method='exact') actual = t['aperture_sum'][0] / (np.pi * r ** 2) assert_allclose(actual, 1) @pytest.mark.parametrize('value', [np.nan, np.inf]) def test_nan_inf_mask(value): """Test that nans and infs are properly masked [267].""" data = np.ones((9, 9)) mask = np.zeros_like(data, dtype=bool) data[4, 4] = value mask[4, 4] = True radius = 2. aper = CircularAperture((4, 4), radius) tbl = aperture_photometry(data, aper, mask=mask) desired = (np.pi * radius**2) - 1 assert_allclose(tbl['aperture_sum'], desired) def test_aperture_partial_overlap(): data = np.ones((20, 20)) error = np.ones((20, 20)) xypos = [(10, 10), (0, 0), (0, 19), (19, 0), (19, 19)] r = 5. aper = CircularAperture(xypos, r=r) tbl = aperture_photometry(data, aper, error=error) assert_allclose(tbl['aperture_sum'][0], np.pi * r ** 2) assert_array_less(tbl['aperture_sum'][1:], np.pi * r ** 2) unit = u.MJy / u.sr tbl = aperture_photometry(data * unit, aper, error=error * unit) assert_allclose(tbl['aperture_sum'][0].value, np.pi * r ** 2) assert_array_less(tbl['aperture_sum'][1:].value, np.pi * r ** 2) assert_array_less(tbl['aperture_sum_err'][1:].value, np.pi * r ** 2) assert tbl['aperture_sum'].unit == unit assert tbl['aperture_sum_err'].unit == unit def test_pixel_aperture_repr(): aper = CircularAperture((10, 20), r=3.0) assert ', r=3.0 pix)>') a_str = ('Aperture: SkyCircularAperture\npositions: \n' 'r: 3.0 pix') else: a_repr = (', r=3.0 pix)>') a_str = ('Aperture: SkyCircularAperture\npositions: \n' 'r: 3.0 pix') assert repr(aper) == a_repr assert str(aper) == a_str aper = SkyCircularAnnulus(s, r_in=3.*u.pix, r_out=5*u.pix) if NUMPY_LT_1_14: a_repr = (', r_in=3.0 pix, ' 'r_out=5.0 pix)>') a_str = ('Aperture: SkyCircularAnnulus\npositions: \n' 'r_in: 3.0 pix\nr_out: 5.0 pix') else: a_repr = (', r_in=3.0 pix, r_out=5.0 pix)>') a_str = ('Aperture: SkyCircularAnnulus\npositions: \n' 'r_in: 3.0 pix\nr_out: 5.0 pix') assert repr(aper) == a_repr assert str(aper) == a_str aper = SkyEllipticalAperture(s, a=3*u.pix, b=5*u.pix, theta=15*u.deg) if NUMPY_LT_1_14: a_repr = (', a=3.0 pix, b=5.0 pix,' ' theta=15.0 deg)>') a_str = ('Aperture: SkyEllipticalAperture\npositions: \n' 'a: 3.0 pix\nb: 5.0 pix\ntheta: 15.0 deg') else: a_repr = (', a=3.0 pix, b=5.0 pix,' ' theta=15.0 deg)>') a_str = ('Aperture: SkyEllipticalAperture\npositions: \n' 'a: 3.0 pix\nb: 5.0 pix\ntheta: 15.0 deg') assert repr(aper) == a_repr assert str(aper) == a_str aper = SkyEllipticalAnnulus(s, a_in=3*u.pix, a_out=5*u.pix, b_out=3*u.pix, theta=15*u.deg) if NUMPY_LT_1_14: a_repr = (', a_in=3.0 pix, ' 'a_out=5.0 pix, b_out=3.0 pix, theta=15.0 deg)>') a_str = ('Aperture: SkyEllipticalAnnulus\npositions: \n' 'a_in: 3.0 pix\na_out: 5.0 pix\nb_out: 3.0 pix\n' 'theta: 15.0 deg') else: a_repr = (', a_in=3.0 pix, ' 'a_out=5.0 pix, b_out=3.0 pix, theta=15.0 deg)>') a_str = ('Aperture: SkyEllipticalAnnulus\npositions: \n' 'a_in: 3.0 pix\na_out: 5.0 pix\nb_out: 3.0 pix\n' 'theta: 15.0 deg') assert repr(aper) == a_repr assert str(aper) == a_str aper = SkyRectangularAperture(s, w=3*u.pix, h=5*u.pix, theta=15*u.deg) if NUMPY_LT_1_14: a_repr = (', w=3.0 pix, h=5.0 pix' ', theta=15.0 deg)>') a_str = ('Aperture: SkyRectangularAperture\npositions: \n' 'w: 3.0 pix\nh: 5.0 pix\ntheta: 15.0 deg') else: a_repr = (', w=3.0 pix, h=5.0 pix' ', theta=15.0 deg)>') a_str = ('Aperture: SkyRectangularAperture\npositions: \n' 'w: 3.0 pix\nh: 5.0 pix\ntheta: 15.0 deg') assert repr(aper) == a_repr assert str(aper) == a_str aper = SkyRectangularAnnulus(s, w_in=3*u.pix, w_out=3.4*u.pix, h_out=5*u.pix, theta=15*u.deg) if NUMPY_LT_1_14: a_repr = (', w_in=3.0 pix, ' 'w_out=3.4 pix, h_out=5.0 pix, theta=15.0 deg)>') a_str = ('Aperture: SkyRectangularAnnulus\npositions: \n' 'w_in: 3.0 pix\nw_out: 3.4 pix\nh_out: 5.0 pix\n' 'theta: 15.0 deg') else: a_repr = (', w_in=3.0 pix, ' 'w_out=3.4 pix, h_out=5.0 pix, theta=15.0 deg)>') a_str = ('Aperture: SkyRectangularAnnulus\npositions: \n' 'w_in: 3.0 pix\nw_out: 3.4 pix\nh_out: 5.0 pix\n' 'theta: 15.0 deg') assert repr(aper) == a_repr assert str(aper) == a_str def test_rectangular_bbox(): # odd sizes width = 7 height = 3 a = RectangularAperture((50, 50), w=width, h=height, theta=0) assert a.bbox.shape == (height, width) a = RectangularAperture((50.5, 50.5), w=width, h=height, theta=0) assert a.bbox.shape == (height + 1, width + 1) a = RectangularAperture((50, 50), w=width, h=height, theta=90.*np.pi/180.) assert a.bbox.shape == (width, height) # even sizes width = 8 height = 4 a = RectangularAperture((50, 50), w=width, h=height, theta=0) assert a.bbox.shape == (height + 1, width + 1) a = RectangularAperture((50.5, 50.5), w=width, h=height, theta=0) assert a.bbox.shape == (height, width) a = RectangularAperture((50.5, 50.5), w=width, h=height, theta=90.*np.pi/180.) assert a.bbox.shape == (width, height) def test_elliptical_bbox(): # integer axes a = 7 b = 3 ap = EllipticalAperture((50, 50), a=a, b=b, theta=0) assert ap.bbox.shape == (2*b + 1, 2*a + 1) ap = EllipticalAperture((50.5, 50.5), a=a, b=b, theta=0) assert ap.bbox.shape == (2*b, 2*a) ap = EllipticalAperture((50, 50), a=a, b=b, theta=90.*np.pi/180.) assert ap.bbox.shape == (2*a + 1, 2*b + 1) # fractional axes a = 7.5 b = 4.5 ap = EllipticalAperture((50, 50), a=a, b=b, theta=0) assert ap.bbox.shape == (2*b, 2*a) ap = EllipticalAperture((50.5, 50.5), a=a, b=b, theta=0) assert ap.bbox.shape == (2*b + 1, 2*a + 1) ap = EllipticalAperture((50, 50), a=a, b=b, theta=90.*np.pi/180.) assert ap.bbox.shape == (2*a, 2*b) def test_to_sky_pixel(): data = make_4gaussians_image() wcs = make_wcs(data.shape) ap = CircularAperture(((12.3, 15.7), (48.19, 98.14)), r=3.14) ap2 = ap.to_sky(wcs).to_pixel(wcs) assert_allclose(ap.positions, ap2.positions) assert_allclose(ap.r, ap2.r) ap = CircularAnnulus(((12.3, 15.7), (48.19, 98.14)), r_in=3.14, r_out=5.32) ap2 = ap.to_sky(wcs).to_pixel(wcs) assert_allclose(ap.positions, ap2.positions) assert_allclose(ap.r_in, ap2.r_in) assert_allclose(ap.r_out, ap2.r_out) ap = EllipticalAperture(((12.3, 15.7), (48.19, 98.14)), a=3.14, b=5.32, theta=103.*np.pi/180.) ap2 = ap.to_sky(wcs).to_pixel(wcs) assert_allclose(ap.positions, ap2.positions) assert_allclose(ap.a, ap2.a) assert_allclose(ap.b, ap2.b) assert_allclose(ap.theta, ap2.theta) ap = EllipticalAnnulus(((12.3, 15.7), (48.19, 98.14)), a_in=3.14, a_out=15.32, b_out=4.89, theta=103.*np.pi/180.) ap2 = ap.to_sky(wcs).to_pixel(wcs) assert_allclose(ap.positions, ap2.positions) assert_allclose(ap.a_in, ap2.a_in) assert_allclose(ap.a_out, ap2.a_out) assert_allclose(ap.b_out, ap2.b_out) assert_allclose(ap.theta, ap2.theta) ap = RectangularAperture(((12.3, 15.7), (48.19, 98.14)), w=3.14, h=5.32, theta=103.*np.pi/180.) ap2 = ap.to_sky(wcs).to_pixel(wcs) assert_allclose(ap.positions, ap2.positions) assert_allclose(ap.w, ap2.w) assert_allclose(ap.h, ap2.h) assert_allclose(ap.theta, ap2.theta) ap = RectangularAnnulus(((12.3, 15.7), (48.19, 98.14)), w_in=3.14, w_out=15.32, h_out=4.89, theta=103.*np.pi/180.) ap2 = ap.to_sky(wcs).to_pixel(wcs) assert_allclose(ap.positions, ap2.positions) assert_allclose(ap.w_in, ap2.w_in) assert_allclose(ap.w_out, ap2.w_out) assert_allclose(ap.h_out, ap2.h_out) assert_allclose(ap.theta, ap2.theta) def test_position_units(): """Regression test for unit check.""" pos = (10, 10) * u.pix pos = np.sqrt(pos**2) ap = CircularAperture(pos, r=3.) assert_allclose(ap.positions, np.array([10, 10])) def test_radius_units(): """Regression test for unit check.""" pos = SkyCoord(10, 10, unit='deg') r = 3.*u.pix r = np.sqrt(r**2) ap = SkyCircularAperture(pos, r=r) assert ap.r.value == 3.0 assert ap.r.unit == u.pix def test_scalar_aperture(): """ Regression test to check that length-1 aperture list appends a "_0" on the column names to be consistent with list inputs. """ data = np.ones((20, 20), dtype=float) ap = CircularAperture((10, 10), r=3.) colnames1 = aperture_photometry(data, ap, error=data).colnames assert (colnames1 == ['id', 'xcenter', 'ycenter', 'aperture_sum', 'aperture_sum_err']) colnames2 = aperture_photometry(data, [ap], error=data).colnames assert (colnames2 == ['id', 'xcenter', 'ycenter', 'aperture_sum_0', 'aperture_sum_err_0']) colnames3 = aperture_photometry(data, [ap, ap], error=data).colnames assert (colnames3 == ['id', 'xcenter', 'ycenter', 'aperture_sum_0', 'aperture_sum_err_0', 'aperture_sum_1', 'aperture_sum_err_1']) def test_nan_in_bbox(): """ Regression test that non-finite data values outside of the aperture mask but within the bounding box do not affect the photometry. """ data1 = np.ones((101, 101)) data2 = data1.copy() data1[33, 33] = np.nan data1[67, 67] = np.inf data1[33, 67] = -np.inf data1[22, 22] = np.nan data1[22, 23] = np.inf error = data1.copy() aper1 = CircularAperture((50, 50), r=20.) aper2 = CircularAperture((5, 5), r=20.) tbl1 = aperture_photometry(data1, aper1, error=error) tbl2 = aperture_photometry(data2, aper1, error=error) assert_allclose(tbl1['aperture_sum'], tbl2['aperture_sum']) assert_allclose(tbl1['aperture_sum_err'], tbl2['aperture_sum_err']) tbl3 = aperture_photometry(data1, aper2, error=error) tbl4 = aperture_photometry(data2, aper2, error=error) assert_allclose(tbl3['aperture_sum'], tbl4['aperture_sum']) assert_allclose(tbl3['aperture_sum_err'], tbl4['aperture_sum_err']) def test_scalar_skycoord(): """ Regression test to check that scalar SkyCoords are added to the table as a length-1 SkyCoord array. """ data = make_4gaussians_image() wcs = make_wcs(data.shape) try: skycoord = wcs.pixel_to_world(90, 60) except AttributeError: # for Astropy < 3.1 skycoord = pixel_to_skycoord(90, 60, wcs) aper = SkyCircularAperture(skycoord, r=0.1*u.arcsec) tbl = aperture_photometry(data, aper, wcs=wcs) assert isinstance(tbl['sky_center'], SkyCoord) def test_nddata_input(): data = np.arange(400).reshape((20, 20)) error = np.sqrt(data) mask = np.zeros((20, 20), dtype=bool) mask[8:13, 8:13] = True unit = 'adu' wcs = make_wcs(data.shape) try: skycoord = wcs.pixel_to_world(10, 10) except AttributeError: # for Astropy < 3.1 skycoord = pixel_to_skycoord(10, 10, wcs) aper = SkyCircularAperture(skycoord, r=0.7*u.arcsec) tbl1 = aperture_photometry(data*u.adu, aper, error=error*u.adu, mask=mask, wcs=wcs) uncertainty = StdDevUncertainty(error) nddata = NDData(data, uncertainty=uncertainty, mask=mask, wcs=wcs, unit=unit) tbl2 = aperture_photometry(nddata, aper) for column in tbl1.columns: if column == 'sky_center': # cannot test SkyCoord equality continue assert_allclose(tbl1[column], tbl2[column]) photutils-0.7.2/photutils/aperture/tests/test_rectangle.py0000644000214200020070000000227713563423715026360 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the rectangle module. """ from astropy.coordinates import SkyCoord import astropy.units as u import numpy as np from .test_aperture_common import BaseTestAperture from ..rectangle import (RectangularAperture, RectangularAnnulus, SkyRectangularAperture, SkyRectangularAnnulus) POSITIONS = [(10, 20), (30, 40), (50, 60), (70, 80)] RA, DEC = np.transpose(POSITIONS) SKYCOORD = SkyCoord(ra=RA, dec=DEC, unit='deg') UNIT = u.arcsec class TestRectangularAperture(BaseTestAperture): aperture = RectangularAperture(POSITIONS, w=10., h=5., theta=np.pi/2.) class TestRectangularAnnulus(BaseTestAperture): aperture = RectangularAnnulus(POSITIONS, w_in=10., w_out=20., h_out=17, theta=np.pi/3) class TestSkyRectangularAperture(BaseTestAperture): aperture = SkyRectangularAperture(SKYCOORD, w=10.*UNIT, h=5.*UNIT, theta=30*u.deg) class TestSkyRectangularAnnulus(BaseTestAperture): aperture = SkyRectangularAnnulus(SKYCOORD, w_in=10.*UNIT, w_out=20.*UNIT, h_out=17.*UNIT, theta=60*u.deg) photutils-0.7.2/photutils/background/0000755000214200020070000000000013573510273022116 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/background/__init__.py0000644000214200020070000000034413563423715024233 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage contains tools to estimate the background and background RMS in an image. """ from .background_2d import * # noqa from .core import * # noqa photutils-0.7.2/photutils/background/background_2d.py0000644000214200020070000007561113572576136025217 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module defines classes to estimate the 2D background and background RMS in an image. """ from itertools import product from astropy.utils import lazyproperty from astropy.utils.decorators import deprecated_renamed_argument from astropy.version import version as astropy_version import numpy as np from numpy.lib.index_tricks import index_exp from .core import SExtractorBackground, StdBackgroundRMS from ..utils import ShepardIDWInterpolator if astropy_version < '3.1': from astropy.stats import SigmaClip SIGMA_CLIP = SigmaClip(sigma=3.0, iters=10) else: from ..extern.sigma_clipping import SigmaClip SIGMA_CLIP = SigmaClip(sigma=3.0, maxiters=10) __all__ = ['BkgZoomInterpolator', 'BkgIDWInterpolator', 'Background2D'] __doctest_requires__ = {('BkgZoomInterpolator', 'Background2D'): ['scipy']} class BkgZoomInterpolator: """ This class generates full-sized background and background RMS images from lower-resolution mesh images using the `~scipy.ndimage.zoom` (spline) interpolator. This class must be used in concert with the `Background2D` class. Parameters ---------- order : int, optional The order of the spline interpolation used to resize the low-resolution background and background RMS mesh images. The value must be an integer in the range 0-5. The default is 3 (bicubic interpolation). mode : {'reflect', 'constant', 'nearest', 'wrap'}, optional Points outside the boundaries of the input are filled according to the given mode. Default is 'reflect'. cval : float, optional The value used for points outside the boundaries of the input if ``mode='constant'``. Default is 0.0 """ def __init__(self, order=3, mode='reflect', cval=0.0): self.order = order self.mode = mode self.cval = cval def __call__(self, mesh, bkg2d_obj): """ Resize the 2D mesh array. Parameters ---------- mesh : 2D `~numpy.ndarray` The low-resolution 2D mesh array. bkg2d_obj : `Background2D` object The `Background2D` object that prepared the ``mesh`` array. Returns ------- result : 2D `~numpy.ndarray` The resized background or background RMS image. """ mesh = np.asanyarray(mesh) if np.ptp(mesh) == 0: return np.zeros_like(bkg2d_obj.data) + np.min(mesh) from scipy.ndimage import zoom if bkg2d_obj.edge_method == 'pad': # The mesh is first resized to the larger padded-data size # (i.e. zoom_factor should be an integer) and then cropped # back to the final data size. zoom_factor = (int(bkg2d_obj.nyboxes * bkg2d_obj.box_size[0] / mesh.shape[0]), int(bkg2d_obj.nxboxes * bkg2d_obj.box_size[1] / mesh.shape[1])) result = zoom(mesh, zoom_factor, order=self.order, mode=self.mode, cval=self.cval) return result[0:bkg2d_obj.data.shape[0], 0:bkg2d_obj.data.shape[1]] else: # The mesh is resized directly to the final data size. zoom_factor = (float(bkg2d_obj.data.shape[0] / mesh.shape[0]), float(bkg2d_obj.data.shape[1] / mesh.shape[1])) return zoom(mesh, zoom_factor, order=self.order, mode=self.mode, cval=self.cval) class BkgIDWInterpolator: """ This class generates full-sized background and background RMS images from lower-resolution mesh images using inverse-distance weighting (IDW) interpolation (`~photutils.utils.ShepardIDWInterpolator`). This class must be used in concert with the `Background2D` class. Parameters ---------- leafsize : float, optional The number of points at which the k-d tree algorithm switches over to brute-force. ``leafsize`` must be positive. See `scipy.spatial.cKDTree` for further information. n_neighbors : int, optional The maximum number of nearest neighbors to use during the interpolation. power : float, optional The power of the inverse distance used for the interpolation weights. reg : float, optional The regularization parameter. It may be used to control the smoothness of the interpolator. """ def __init__(self, leafsize=10, n_neighbors=10, power=1.0, reg=0.0): self.leafsize = leafsize self.n_neighbors = n_neighbors self.power = power self.reg = reg def __call__(self, mesh, bkg2d_obj): """ Resize the 2D mesh array. Parameters ---------- mesh : 2D `~numpy.ndarray` The low-resolution 2D mesh array. bkg2d_obj : `Background2D` object The `Background2D` object that prepared the ``mesh`` array. Returns ------- result : 2D `~numpy.ndarray` The resized background or background RMS image. """ mesh = np.asanyarray(mesh) if np.ptp(mesh) == 0: return np.zeros_like(bkg2d_obj.data) + np.min(mesh) mesh1d = mesh[bkg2d_obj.mesh_yidx, bkg2d_obj.mesh_xidx] interp_func = ShepardIDWInterpolator(bkg2d_obj.yx, mesh1d, leafsize=self.leafsize) data = interp_func(bkg2d_obj.data_coords, n_neighbors=self.n_neighbors, power=self.power, reg=self.reg) return data.reshape(bkg2d_obj.data.shape) class Background2D: """ Class to estimate a 2D background and background RMS noise in an image. The background is estimated using sigma-clipped statistics in each mesh of a grid that covers the input ``data`` to create a low-resolution, and possibly irregularly-gridded, background map. The final background map is calculated by interpolating the low-resolution background map. Parameters ---------- data : array_like The 2D array from which to estimate the background and/or background RMS map. box_size : int or array_like (int) The box size along each axis. If ``box_size`` is a scalar then a square box of size ``box_size`` will be used. If ``box_size`` has two elements, they should be in ``(ny, nx)`` order. For best results, the box shape should be chosen such that the ``data`` are covered by an integer number of boxes in both dimensions. When this is not the case, see the ``edge_method`` keyword for more options. mask : array_like (bool), optional A boolean mask, with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Masked data are excluded from calculations. exclude_percentile : float in the range of [0, 100], optional The percentage of masked pixels in a mesh, used as a threshold for determining if the mesh is excluded. If a mesh has more than ``exclude_percentile`` percent of its pixels masked then it will be excluded from the low-resolution map. Masked pixels include those from the input ``mask``, those resulting from the data padding (i.e. if ``edge_method='pad'``), and those resulting from any sigma clipping (i.e. if ``sigma_clip`` is used). Setting ``exclude_percentile=0`` will exclude meshes that have any masked pixels. Setting ``exclude_percentile=100`` will only exclude meshes that are completely masked. Note that completely masked meshes are *always* excluded. For best results, ``exclude_percentile`` should be kept as low as possible (as long as there are sufficient pixels for reasonable statistical estimates). The default is 10.0. filter_size : int or array_like (int), optional The window size of the 2D median filter to apply to the low-resolution background map. If ``filter_size`` is a scalar then a square box of size ``filter_size`` will be used. If ``filter_size`` has two elements, they should be in ``(ny, nx)`` order. A filter size of ``1`` (or ``(1, 1)``) means no filtering. filter_threshold : int, optional The threshold value for used for selective median filtering of the low-resolution 2D background map. The median filter will be applied to only the background meshes with values larger than ``filter_threshold``. Set to `None` to filter all meshes (default). edge_method : {'pad', 'crop'}, optional The method used to determine how to handle the case where the image size is not an integer multiple of the ``box_size`` in either dimension. Both options will resize the image to give an exact multiple of ``box_size`` in both dimensions. * ``'pad'``: pad the image along the top and/or right edges. This is the default and recommended method. * ``'crop'``: crop the image along the top and/or right edges. sigma_clip : `astropy.stats.SigmaClip` instance, optional A `~astropy.stats.SigmaClip` object that defines the sigma clipping parameters. If `None` then no sigma clipping will be performed. The default is to perform sigma clipping with ``sigma=3.0`` and ``maxiters=10``. bkg_estimator : callable, optional A callable object (a function or e.g., an instance of any `~photutils.background.BackgroundBase` subclass) used to estimate the background in each of the meshes. The callable object must take in a 2D `~numpy.ndarray` or `~numpy.ma.MaskedArray` and have an ``axis`` keyword (internally, the background will be calculated along ``axis=1``). The callable object must return a 1D `~numpy.ma.MaskedArray`. If ``bkg_estimator`` includes sigma clipping, it will be ignored (use the ``sigma_clip`` keyword to define sigma clipping). The default is an instance of `~photutils.background.SExtractorBackground`. bkgrms_estimator : callable, optional A callable object (a function or e.g., an instance of any `~photutils.background.BackgroundRMSBase` subclass) used to estimate the background RMS in each of the meshes. The callable object must take in a 2D `~numpy.ndarray` or `~numpy.ma.MaskedArray` and have an ``axis`` keyword (internally, the background RMS will be calculated along ``axis=1``). The callable object must return a 1D `~numpy.ma.MaskedArray`. If ``bkgrms_estimator`` includes sigma clipping, it will be ignored (use the ``sigma_clip`` keyword to define sigma clipping). The default is an instance of `~photutils.background.StdBackgroundRMS`. interpolator : callable, optional A callable object (a function or object) used to interpolate the low-resolution background or background RMS mesh to the full-size background or background RMS maps. The default is an instance of `BkgZoomInterpolator`. Notes ----- If there is only one background mesh element (i.e., ``box_size`` is the same size as the ``data``), then the background map will simply be a constant image. """ def __init__(self, data, box_size, mask=None, exclude_percentile=10.0, filter_size=(3, 3), filter_threshold=None, edge_method='pad', sigma_clip=SIGMA_CLIP, bkg_estimator=SExtractorBackground(sigma_clip=None), bkgrms_estimator=StdBackgroundRMS(sigma_clip=None), interpolator=BkgZoomInterpolator()): data = np.asanyarray(data) box_size = np.atleast_1d(box_size) if len(box_size) == 1: box_size = np.repeat(box_size, 2) self.box_size = (min(box_size[0], data.shape[0]), min(box_size[1], data.shape[1])) self.box_npixels = self.box_size[0] * self.box_size[1] if mask is not None: mask = np.asanyarray(mask) if mask.shape != data.shape: raise ValueError('mask and data must have the same shape') if exclude_percentile < 0 or exclude_percentile > 100: raise ValueError('exclude_percentile must be between 0 and 100 ' '(inclusive).') self.data = data self.mask = mask self.exclude_percentile = exclude_percentile filter_size = np.atleast_1d(filter_size) if len(filter_size) == 1: filter_size = np.repeat(filter_size, 2) self.filter_size = filter_size self.filter_threshold = filter_threshold self.edge_method = edge_method self.sigma_clip = sigma_clip bkg_estimator.sigma_clip = None bkgrms_estimator.sigma_clip = None self.bkg_estimator = bkg_estimator self.bkgrms_estimator = bkgrms_estimator self.interpolator = interpolator self.background_mesh = None self.background_rms_mesh = None self._prepare_data() self._calc_bkg_bkgrms() self._calc_coordinates() def _pad_data(self, yextra, xextra): """ Pad the ``data`` and ``mask`` to have an integer number of background meshes of size ``box_size`` in both dimensions. The padding is added on the top and/or right edges (this is the best option for the "zoom" interpolator). Parameters ---------- yextra, xextra : int The modulus of the data size and the box size in both the ``y`` and ``x`` dimensions. This is the number of extra pixels beyond a multiple of the box size in the ``y`` and ``x`` dimensions. Returns ------- result : `~numpy.ma.MaskedArray` The padded data and mask as a masked array. """ ypad = 0 xpad = 0 if yextra > 0: ypad = self.box_size[0] - yextra if xextra > 0: xpad = self.box_size[1] - xextra pad_width = ((0, ypad), (0, xpad)) # mode must be a string for numpy < 0.11 # (see https://github.com/numpy/numpy/issues/7112) mode = str('constant') data = np.pad(self.data, pad_width, mode=mode, constant_values=[1.e10]) # mask the padded regions pad_mask = np.zeros(data.shape, dtype=bool) yidx = data.shape[0] - ypad xidx = data.shape[1] - xpad pad_mask[yidx:, :] = True pad_mask[:, xidx:] = True # pad the input mask separately (there is no np.ma.pad function) if self.mask is not None: mask = np.pad(self.mask, pad_width, mode=mode, constant_values=[True]) mask = np.logical_or(mask, pad_mask) else: mask = pad_mask return np.ma.masked_array(data, mask=mask) def _crop_data(self): """ Crop the ``data`` and ``mask`` to have an integer number of background meshes of size ``box_size`` in both dimensions. The data are cropped on the top and/or right edges (this is the best option for the "zoom" interpolator). Returns ------- result : `~numpy.ma.MaskedArray` The cropped data and mask as a masked array. """ ny_crop = self.nyboxes * self.box_size[1] nx_crop = self.nxboxes * self.box_size[0] crop_slc = index_exp[0:ny_crop, 0:nx_crop] if self.mask is not None: mask = self.mask[crop_slc] else: mask = False return np.ma.masked_array(self.data[crop_slc], mask=mask) def _select_meshes(self, data): """ Define the x and y indices with respect to the low-resolution mesh image of the meshes to use for the background interpolation. The ``exclude_percentile`` keyword determines which meshes are not used for the background interpolation. Parameters ---------- data : 2D `~numpy.ma.MaskedArray` A 2D array where the y dimension represents each mesh and the x dimension represents the data in each mesh. Returns ------- mesh_idx : 1D `~numpy.ndarray` The 1D mesh indices. """ # the number of masked pixels in each mesh nmasked = np.ma.count_masked(data, axis=1) # meshes that contain more than ``exclude_percentile`` percent # masked pixels are excluded: # - for exclude_percentile=0, good meshes will be only where # nmasked=0 # - meshes where nmasked=self.box_npixels are *always* excluded # (second conditional needed for exclude_percentile=100) threshold_npixels = self.exclude_percentile / 100. * self.box_npixels mesh_idx = np.where((nmasked <= threshold_npixels) & (nmasked != self.box_npixels))[0] # good meshes if mesh_idx.size == 0: raise ValueError('All meshes contain > {0} ({1} percent per ' 'mesh) masked pixels. Please check your data ' 'or decrease "exclude_percentile".' .format(threshold_npixels, self.exclude_percentile)) return mesh_idx def _prepare_data(self): """ Prepare the data. First, pad or crop the 2D data array so that there are an integer number of meshes in both dimensions, creating a masked array. Then reshape into a different 2D masked array where each row represents the data in a single mesh. This method also performs a first cut at rejecting certain meshes as specified by the input keywords. """ self.nyboxes = self.data.shape[0] // self.box_size[0] self.nxboxes = self.data.shape[1] // self.box_size[1] yextra = self.data.shape[0] % self.box_size[0] xextra = self.data.shape[1] % self.box_size[1] if (xextra + yextra) == 0: # no resizing of the data is necessary data_ma = np.ma.masked_array(self.data, mask=self.mask) else: # pad or crop the data if self.edge_method == 'pad': data_ma = self._pad_data(yextra, xextra) self.nyboxes = data_ma.shape[0] // self.box_size[0] self.nxboxes = data_ma.shape[1] // self.box_size[1] elif self.edge_method == 'crop': data_ma = self._crop_data() else: raise ValueError('edge_method must be "pad" or "crop"') self.nboxes = self.nxboxes * self.nyboxes # a reshaped 2D masked array with mesh data along the x axis mesh_data = np.ma.swapaxes( data_ma.reshape( self.nyboxes, self.box_size[0], self.nxboxes, self.box_size[1]), 1, 2).reshape(self.nyboxes * self.nxboxes, self.box_npixels) # first cut on rejecting meshes self.mesh_idx = self._select_meshes(mesh_data) self._mesh_data = mesh_data[self.mesh_idx, :] def _make_2d_array(self, data): """ Convert a 1D array of mesh values to a masked 2D mesh array given the 1D mesh indices ``mesh_idx``. Parameters ---------- data : 1D `~numpy.ndarray` A 1D array of mesh values. Returns ------- result : 2D `~numpy.ma.MaskedArray` A 2D masked array. Pixels not defined in ``mesh_idx`` are masked. """ if data.shape != self.mesh_idx.shape: raise ValueError('data and mesh_idx must have the same shape') if np.ma.is_masked(data): raise ValueError('data must not be a masked array') data2d = np.zeros(self._mesh_shape).astype(data.dtype) data2d[self.mesh_yidx, self.mesh_xidx] = data if len(self.mesh_idx) == self.nboxes: # no meshes were masked return data2d else: # some meshes were masked mask2d = np.ones(data2d.shape).astype(bool) mask2d[self.mesh_yidx, self.mesh_xidx] = False return np.ma.masked_array(data2d, mask=mask2d) def _interpolate_meshes(self, data, n_neighbors=10, eps=0.0, power=1.0, reg=0.0): """ Use IDW interpolation to fill in any masked pixels in the low-resolution 2D mesh background and background RMS images. This is required to use a regular-grid interpolator to expand the low-resolution image to the full size image. Parameters ---------- data : 1D `~numpy.ndarray` A 1D array of mesh values. n_neighbors : int, optional The maximum number of nearest neighbors to use during the interpolation. eps : float, optional Set to use approximate nearest neighbors; the kth neighbor is guaranteed to be no further than (1 + ``eps``) times the distance to the real *k*-th nearest neighbor. See `scipy.spatial.cKDTree.query` for further information. power : float, optional The power of the inverse distance used for the interpolation weights. See the Notes section for more details. reg : float, optional The regularization parameter. It may be used to control the smoothness of the interpolator. See the Notes section for more details. Returns ------- result : 2D `~numpy.ndarray` A 2D array of the mesh values where masked pixels have been filled by IDW interpolation. """ yx = np.column_stack([self.mesh_yidx, self.mesh_xidx]) coords = np.array(list(product(range(self.nyboxes), range(self.nxboxes)))) interp_func = ShepardIDWInterpolator(yx, data) img1d = interp_func(coords, n_neighbors=n_neighbors, power=power, eps=eps, reg=reg) return img1d.reshape(self._mesh_shape) def _selective_filter(self, data, indices): """ Selectively filter only pixels above ``filter_threshold`` in the background mesh. The same pixels are filtered in both the background and background RMS meshes. Parameters ---------- data : 2D `~numpy.ndarray` A 2D array of mesh values. indices : 2 tuple of int A tuple of the ``y`` and ``x`` indices of the pixels to filter. Returns ------- filtered_data : 2D `~numpy.ndarray` The filtered 2D array of mesh values. """ data_out = np.copy(data) for i, j in zip(*indices): yfs, xfs = self.filter_size hyfs, hxfs = yfs // 2, xfs // 2 yidx0 = max(i - hyfs, 0) yidx1 = min(i - hyfs + yfs, data.shape[0]) xidx0 = max(j - hxfs, 0) xidx1 = min(j - hxfs + xfs, data.shape[1]) data_out[i, j] = np.median(data[yidx0:yidx1, xidx0:xidx1]) return data_out def _filter_meshes(self): """ Apply a 2D median filter to the low-resolution 2D mesh, including only pixels inside the image at the borders. """ from scipy.ndimage import generic_filter if self.filter_threshold is None: # filter the entire arrays self.background_mesh = generic_filter( self.background_mesh, np.nanmedian, size=self.filter_size, mode='constant', cval=np.nan) self.background_rms_mesh = generic_filter( self.background_rms_mesh, np.nanmedian, size=self.filter_size, mode='constant', cval=np.nan) else: # selectively filter indices = np.nonzero(self.background_mesh > self.filter_threshold) self.background_mesh = self._selective_filter( self.background_mesh, indices) self.background_rms_mesh = self._selective_filter( self.background_rms_mesh, indices) def _calc_bkg_bkgrms(self): """ Calculate the background and background RMS estimate in each of the meshes. Both meshes are computed at the same time here method because the filtering of both depends on the background mesh. The ``background_mesh`` and ``background_rms_mesh`` images are equivalent to the low-resolution "MINIBACKGROUND" and "MINIBACK_RMS" background maps in SExtractor, respectively. """ if self.sigma_clip is not None: data_sigclip = self.sigma_clip(self._mesh_data, axis=1) else: data_sigclip = self._mesh_data del self._mesh_data # preform mesh rejection on sigma-clipped data (i.e. for any # newly-masked pixels) idx = self._select_meshes(data_sigclip) self.mesh_idx = self.mesh_idx[idx] # indices for the output mesh self._data_sigclip = data_sigclip[idx] # always a 2D masked array self._mesh_shape = (self.nyboxes, self.nxboxes) self.mesh_yidx, self.mesh_xidx = np.unravel_index(self.mesh_idx, self._mesh_shape) # These properties are needed later to calculate # background_mesh_ma and background_rms_mesh_ma. Note that _bkg1d # and _bkgrms1d are masked arrays, but the mask should always be # False. self._bkg1d = self.bkg_estimator(self._data_sigclip, axis=1) self._bkgrms1d = self.bkgrms_estimator(self._data_sigclip, axis=1) # make the unfiltered 2D mesh arrays (these are not masked) if len(self._bkg1d) == self.nboxes: bkg = self._make_2d_array(self._bkg1d) bkgrms = self._make_2d_array(self._bkgrms1d) else: bkg = self._interpolate_meshes(self._bkg1d) bkgrms = self._interpolate_meshes(self._bkgrms1d) self._background_mesh_unfiltered = bkg self._background_rms_mesh_unfiltered = bkgrms self.background_mesh = bkg self.background_rms_mesh = bkgrms # filter the 2D mesh arrays if not np.array_equal(self.filter_size, [1, 1]): self._filter_meshes() def _calc_coordinates(self): """ Calculate the coordinates to use when calling an interpolator. These are needed for `Background2D` and `BackgroundIDW2D`. Regular-grid interpolators require a 2D array of values. Some require a 2D meshgrid of x and y. Other require a strictly increasing 1D array of the x and y ranges. """ # the position coordinates used to initialize an interpolation self.y = (self.mesh_yidx * self.box_size[0] + (self.box_size[0] - 1) / 2.) self.x = (self.mesh_xidx * self.box_size[1] + (self.box_size[1] - 1) / 2.) self.yx = np.column_stack([self.y, self.x]) # the position coordinates used when calling an interpolator nx, ny = self.data.shape self.data_coords = np.array(list(product(range(ny), range(nx)))) @lazyproperty def mesh_nmasked(self): """ A 2D (masked) array of the number of masked pixels in each mesh. Only meshes included in the background estimation are included. The array is masked only if meshes were excluded. """ return self._make_2d_array( np.ma.count_masked(self._data_sigclip, axis=1)) @lazyproperty def background_mesh_ma(self): """ The background 2D (masked) array mesh prior to any interpolation. The array is masked only if meshes were excluded. """ if len(self._bkg1d) == self.nboxes: return self.background_mesh else: return self._make_2d_array(self._bkg1d) # masked array @lazyproperty def background_rms_mesh_ma(self): """ The background RMS 2D (masked) array mesh prior to any interpolation. The array is masked only if meshes were excluded. """ if len(self._bkgrms1d) == self.nboxes: return self.background_rms_mesh else: return self._make_2d_array(self._bkgrms1d) # masked array @lazyproperty def background_median(self): """ The median value of the 2D low-resolution background map. This is equivalent to the value SExtractor prints to stdout (i.e., "(M+D) Background: "). """ return np.median(self.background_mesh) @lazyproperty def background_rms_median(self): """ The median value of the low-resolution background RMS map. This is equivalent to the value SExtractor prints to stdout (i.e., "(M+D) RMS: "). """ return np.median(self.background_rms_mesh) @lazyproperty def background(self): """A 2D `~numpy.ndarray` containing the background image.""" return self.interpolator(self.background_mesh, self) @lazyproperty def background_rms(self): """A 2D `~numpy.ndarray` containing the background RMS image.""" return self.interpolator(self.background_rms_mesh, self) @deprecated_renamed_argument('ax', 'axes', '0.7') def plot_meshes(self, axes=None, marker='+', color='blue', outlines=False, **kwargs): """ Plot the low-resolution mesh boxes on a matplotlib Axes instance. Parameters ---------- axes : `matplotlib.axes.Axes` or `None`, optional The matplotlib axes on which to plot. If `None`, then the current `~matplotlib.axes.Axes` instance is used. marker : str, optional The marker to use to mark the center of the boxes. Default is '+'. color : str, optional The color for the markers and the box outlines. Default is 'blue'. outlines : bool, optional Whether or not to plot the box outlines in addition to the box centers. kwargs : `dict` Any keyword arguments accepted by `matplotlib.patches.Patch`. Used only if ``outlines`` is True. """ import matplotlib.pyplot as plt kwargs['color'] = color if axes is None: axes = plt.gca() axes.scatter(self.x, self.y, marker=marker, color=color) if outlines: from ..aperture import RectangularAperture xy = np.column_stack([self.x, self.y]) apers = RectangularAperture(xy, self.box_size[1], self.box_size[0], 0.) apers.plot(axes=axes, **kwargs) photutils-0.7.2/photutils/background/core.py0000644000214200020070000004632313572576136023441 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module defines classes to estimate the background and background RMS in an array of any dimension. """ import abc from astropy.stats import biweight_location, biweight_scale, mad_std from astropy.version import version as astropy_version import numpy as np if astropy_version < '3.1': from astropy.stats import SigmaClip SIGMA_CLIP = SigmaClip(sigma=3.0, iters=10) else: from ..extern.sigma_clipping import SigmaClip SIGMA_CLIP = SigmaClip(sigma=3.0, maxiters=10) __all__ = ['BackgroundBase', 'BackgroundRMSBase', 'MeanBackground', 'MedianBackground', 'ModeEstimatorBackground', 'MMMBackground', 'SExtractorBackground', 'BiweightLocationBackground', 'StdBackgroundRMS', 'MADStdBackgroundRMS', 'BiweightScaleBackgroundRMS'] def _masked_median(data, axis=None): """ Calculate the median of a (masked) array. This function is necessary for a consistent interface across all numpy versions. A bug was introduced in numpy v1.10 where `numpy.ma.median` (with ``axis=None``) returns a single-valued `~numpy.ma.MaskedArray` if the input data is a `~numpy.ndarray` or if the data is a `~numpy.ma.MaskedArray`, but the mask is `False` everywhere. Parameters ---------- data : array-like The input data. axis : int or `None`, optional The array axis along which the median is calculated. If `None`, then the entire array is used. Returns ------- result : float or `~numpy.ma.MaskedArray` The resulting median. If ``axis`` is `None`, then a float is returned, otherwise a `~numpy.ma.MaskedArray` is returned. """ _median = np.ma.median(data, axis=axis) if axis is None and np.ma.isMaskedArray(_median): _median = _median.item() return _median class BackgroundBase(metaclass=abc.ABCMeta): """ Base class for classes that estimate scalar background values. Parameters ---------- sigma_clip : `astropy.stats.SigmaClip` object, optional A `~astropy.stats.SigmaClip` object that defines the sigma clipping parameters. If `None` then no sigma clipping will be performed. The default is to perform sigma clipping with ``sigma=3.0`` and ``maxiters=5``. """ def __init__(self, sigma_clip=SIGMA_CLIP): self.sigma_clip = sigma_clip def __call__(self, data, axis=None): return self.calc_background(data, axis=axis) @abc.abstractmethod def calc_background(self, data, axis=None): """ Calculate the background value. Parameters ---------- data : array_like or `~numpy.ma.MaskedArray` The array for which to calculate the background value. axis : int or `None`, optional The array axis along which the background is calculated. If `None`, then the entire array is used. Returns ------- result : float or `~numpy.ma.MaskedArray` The calculated background value. If ``axis`` is `None` then a scalar will be returned, otherwise a `~numpy.ma.MaskedArray` will be returned. """ raise NotImplementedError('Needs to be implemented in a subclass.') class BackgroundRMSBase(metaclass=abc.ABCMeta): """ Base class for classes that estimate scalar background RMS values. Parameters ---------- sigma_clip : `astropy.stats.SigmaClip` object, optional A `~astropy.stats.SigmaClip` object that defines the sigma clipping parameters. If `None` then no sigma clipping will be performed. The default is to perform sigma clipping with ``sigma=3.0`` and ``maxiters=5``. """ def __init__(self, sigma_clip=SIGMA_CLIP): self.sigma_clip = sigma_clip def __call__(self, data, axis=None): return self.calc_background_rms(data, axis=axis) @abc.abstractmethod def calc_background_rms(self, data, axis=None): """ Calculate the background RMS value. Parameters ---------- data : array_like or `~numpy.ma.MaskedArray` The array for which to calculate the background RMS value. axis : int or `None`, optional The array axis along which the background RMS is calculated. If `None`, then the entire array is used. Returns ------- result : float or `~numpy.ma.MaskedArray` The calculated background RMS value. If ``axis`` is `None` then a scalar will be returned, otherwise a `~numpy.ma.MaskedArray` will be returned. """ raise NotImplementedError('Needs to be implemented in a subclass.') class MeanBackground(BackgroundBase): """ Class to calculate the background in an array as the (sigma-clipped) mean. Parameters ---------- sigma_clip : `astropy.stats.SigmaClip` object, optional A `~astropy.stats.SigmaClip` object that defines the sigma clipping parameters. If `None` then no sigma clipping will be performed. The default is to perform sigma clipping with ``sigma=3.0`` and ``maxiters=5``. Examples -------- >>> from astropy.stats import SigmaClip >>> from photutils import MeanBackground >>> data = np.arange(100) >>> sigma_clip = SigmaClip(sigma=3.0) >>> bkg = MeanBackground(sigma_clip) The background value can be calculated by using the `calc_background` method, e.g.: >>> bkg_value = bkg.calc_background(data) >>> print(bkg_value) # doctest: +FLOAT_CMP 49.5 Alternatively, the background value can be calculated by calling the class instance as a function, e.g.: >>> bkg_value = bkg(data) >>> print(bkg_value) # doctest: +FLOAT_CMP 49.5 """ def calc_background(self, data, axis=None): if self.sigma_clip is not None: data = self.sigma_clip(data, axis=axis) return np.ma.mean(data, axis=axis) class MedianBackground(BackgroundBase): """ Class to calculate the background in an array as the (sigma-clipped) median. Parameters ---------- sigma_clip : `astropy.stats.SigmaClip` object, optional A `~astropy.stats.SigmaClip` object that defines the sigma clipping parameters. If `None` then no sigma clipping will be performed. The default is to perform sigma clipping with ``sigma=3.0`` and ``maxiters=5``. Examples -------- >>> from astropy.stats import SigmaClip >>> from photutils import MedianBackground >>> data = np.arange(100) >>> sigma_clip = SigmaClip(sigma=3.0) >>> bkg = MedianBackground(sigma_clip) The background value can be calculated by using the `calc_background` method, e.g.: >>> bkg_value = bkg.calc_background(data) >>> print(bkg_value) # doctest: +FLOAT_CMP 49.5 Alternatively, the background value can be calculated by calling the class instance as a function, e.g.: >>> bkg_value = bkg(data) >>> print(bkg_value) # doctest: +FLOAT_CMP 49.5 """ def calc_background(self, data, axis=None): if self.sigma_clip is not None: data = self.sigma_clip(data, axis=axis) return _masked_median(data, axis=axis) class ModeEstimatorBackground(BackgroundBase): """ Class to calculate the background in an array using a mode estimator of the form ``(median_factor * median) - (mean_factor * mean)``. Parameters ---------- median_factor : float, optional The multiplicative factor for the data median. Defaults to 3. mean_factor : float, optional The multiplicative factor for the data mean. Defaults to 2. sigma_clip : `astropy.stats.SigmaClip` object, optional A `~astropy.stats.SigmaClip` object that defines the sigma clipping parameters. If `None` then no sigma clipping will be performed. The default is to perform sigma clipping with ``sigma=3.0`` and ``maxiters=5``. Examples -------- >>> from astropy.stats import SigmaClip >>> from photutils import ModeEstimatorBackground >>> data = np.arange(100) >>> sigma_clip = SigmaClip(sigma=3.0) >>> bkg = ModeEstimatorBackground(median_factor=3.0, mean_factor=2.0, ... sigma_clip=sigma_clip) The background value can be calculated by using the `calc_background` method, e.g.: >>> bkg_value = bkg.calc_background(data) >>> print(bkg_value) # doctest: +FLOAT_CMP 49.5 Alternatively, the background value can be calculated by calling the class instance as a function, e.g.: >>> bkg_value = bkg(data) >>> print(bkg_value) # doctest: +FLOAT_CMP 49.5 """ def __init__(self, median_factor=3.0, mean_factor=2.0, **kwargs): super().__init__(**kwargs) self.median_factor = median_factor self.mean_factor = mean_factor def calc_background(self, data, axis=None): if self.sigma_clip is not None: data = self.sigma_clip(data, axis=axis) return ((self.median_factor * _masked_median(data, axis=axis)) - (self.mean_factor * np.ma.mean(data, axis=axis))) class MMMBackground(ModeEstimatorBackground): """ Class to calculate the background in an array using the DAOPHOT MMM algorithm. The background is calculated using a mode estimator of the form ``(3 * median) - (2 * mean)``. Parameters ---------- sigma_clip : `astropy.stats.SigmaClip` object, optional A `~astropy.stats.SigmaClip` object that defines the sigma clipping parameters. If `None` then no sigma clipping will be performed. The default is to perform sigma clipping with ``sigma=3.0`` and ``maxiters=5``. Examples -------- >>> from astropy.stats import SigmaClip >>> from photutils import MMMBackground >>> data = np.arange(100) >>> sigma_clip = SigmaClip(sigma=3.0) >>> bkg = MMMBackground(sigma_clip=sigma_clip) The background value can be calculated by using the `~photutils.background.core.ModeEstimatorBackground.calc_background` method, e.g.: >>> bkg_value = bkg.calc_background(data) >>> print(bkg_value) # doctest: +FLOAT_CMP 49.5 Alternatively, the background value can be calculated by calling the class instance as a function, e.g.: >>> bkg_value = bkg(data) >>> print(bkg_value) # doctest: +FLOAT_CMP 49.5 """ def __init__(self, **kwargs): kwargs['median_factor'] = 3. kwargs['mean_factor'] = 2. super().__init__(**kwargs) class SExtractorBackground(BackgroundBase): """ Class to calculate the background in an array using the SExtractor algorithm. The background is calculated using a mode estimator of the form ``(2.5 * median) - (1.5 * mean)``. If ``(mean - median) / std > 0.3`` then the median is used instead. Despite what the `SExtractor`_ User's Manual says, this is the method it *always* uses. .. _SExtractor: https://www.astromatic.net/software/sextractor Parameters ---------- sigma_clip : `astropy.stats.SigmaClip` object, optional A `~astropy.stats.SigmaClip` object that defines the sigma clipping parameters. If `None` then no sigma clipping will be performed. The default is to perform sigma clipping with ``sigma=3.0`` and ``maxiters=5``. Examples -------- >>> from astropy.stats import SigmaClip >>> from photutils import SExtractorBackground >>> data = np.arange(100) >>> sigma_clip = SigmaClip(sigma=3.0) >>> bkg = SExtractorBackground(sigma_clip) The background value can be calculated by using the `calc_background` method, e.g.: >>> bkg_value = bkg.calc_background(data) >>> print(bkg_value) # doctest: +FLOAT_CMP 49.5 Alternatively, the background value can be calculated by calling the class instance as a function, e.g.: >>> bkg_value = bkg(data) >>> print(bkg_value) # doctest: +FLOAT_CMP 49.5 """ def calc_background(self, data, axis=None): if self.sigma_clip is not None: data = self.sigma_clip(data, axis=axis) _median = np.atleast_1d(_masked_median(data, axis=axis)) _mean = np.atleast_1d(np.ma.mean(data, axis=axis)) _std = np.atleast_1d(np.ma.std(data, axis=axis)) bkg = np.atleast_1d((2.5 * _median) - (1.5 * _mean)) bkg = np.ma.where(_std == 0, _mean, bkg) idx = np.ma.where(_std != 0) condition = (np.abs(_mean[idx] - _median[idx]) / _std[idx]) < 0.3 bkg[idx] = np.ma.where(condition, bkg[idx], _median[idx]) # np.ma.where always returns a masked array if axis is None and np.ma.isMaskedArray(bkg): bkg = bkg.item() return bkg class BiweightLocationBackground(BackgroundBase): """ Class to calculate the background in an array using the biweight location. Parameters ---------- c : float, optional Tuning constant for the biweight estimator. Default value is 6.0. M : float, optional Initial guess for the biweight location. Default value is `None`. sigma_clip : `astropy.stats.SigmaClip` object, optional A `~astropy.stats.SigmaClip` object that defines the sigma clipping parameters. If `None` then no sigma clipping will be performed. The default is to perform sigma clipping with ``sigma=3.0`` and ``maxiters=5``. Examples -------- >>> from astropy.stats import SigmaClip >>> from photutils import BiweightLocationBackground >>> data = np.arange(100) >>> sigma_clip = SigmaClip(sigma=3.0) >>> bkg = BiweightLocationBackground(sigma_clip=sigma_clip) The background value can be calculated by using the `calc_background` method, e.g.: >>> bkg_value = bkg.calc_background(data) >>> print(bkg_value) # doctest: +FLOAT_CMP 49.5 Alternatively, the background value can be calculated by calling the class instance as a function, e.g.: >>> bkg_value = bkg(data) >>> print(bkg_value) # doctest: +FLOAT_CMP 49.5 """ def __init__(self, c=6, M=None, **kwargs): super().__init__(**kwargs) self.c = c self.M = M def calc_background(self, data, axis=None): if self.sigma_clip is not None: data = self.sigma_clip(data, axis=axis) return biweight_location(data, c=self.c, M=self.M, axis=axis) class StdBackgroundRMS(BackgroundRMSBase): """ Class to calculate the background RMS in an array as the (sigma-clipped) standard deviation. Parameters ---------- sigma_clip : `astropy.stats.SigmaClip` object, optional A `~astropy.stats.SigmaClip` object that defines the sigma clipping parameters. If `None` then no sigma clipping will be performed. The default is to perform sigma clipping with ``sigma=3.0`` and ``maxiters=5``. Examples -------- >>> from astropy.stats import SigmaClip >>> from photutils import StdBackgroundRMS >>> data = np.arange(100) >>> sigma_clip = SigmaClip(sigma=3.0) >>> bkgrms = StdBackgroundRMS(sigma_clip) The background RMS value can be calculated by using the `calc_background_rms` method, e.g.: >>> bkgrms_value = bkgrms.calc_background_rms(data) >>> print(bkgrms_value) # doctest: +FLOAT_CMP 28.86607004772212 Alternatively, the background RMS value can be calculated by calling the class instance as a function, e.g.: >>> bkgrms_value = bkgrms(data) >>> print(bkgrms_value) # doctest: +FLOAT_CMP 28.86607004772212 """ def calc_background_rms(self, data, axis=None): if self.sigma_clip is not None: data = self.sigma_clip(data, axis=axis) return np.ma.std(data, axis=axis) class MADStdBackgroundRMS(BackgroundRMSBase): """ Class to calculate the background RMS in an array as using the `median absolute deviation (MAD) `_. The standard deviation estimator is given by: .. math:: \\sigma \\approx \\frac{{\\textrm{{MAD}}}}{{\\Phi^{{-1}}(3/4)}} \\approx 1.4826 \\ \\textrm{{MAD}} where :math:`\\Phi^{{-1}}(P)` is the normal inverse cumulative distribution function evaluated at probability :math:`P = 3/4`. Parameters ---------- sigma_clip : `astropy.stats.SigmaClip` object, optional A `~astropy.stats.SigmaClip` object that defines the sigma clipping parameters. If `None` then no sigma clipping will be performed. The default is to perform sigma clipping with ``sigma=3.0`` and ``maxiters=5``. Examples -------- >>> from astropy.stats import SigmaClip >>> from photutils import MADStdBackgroundRMS >>> data = np.arange(100) >>> sigma_clip = SigmaClip(sigma=3.0) >>> bkgrms = MADStdBackgroundRMS(sigma_clip) The background RMS value can be calculated by using the `calc_background_rms` method, e.g.: >>> bkgrms_value = bkgrms.calc_background_rms(data) >>> print(bkgrms_value) # doctest: +FLOAT_CMP 37.06505546264005 Alternatively, the background RMS value can be calculated by calling the class instance as a function, e.g.: >>> bkgrms_value = bkgrms(data) >>> print(bkgrms_value) # doctest: +FLOAT_CMP 37.06505546264005 """ def calc_background_rms(self, data, axis=None): if self.sigma_clip is not None: data = self.sigma_clip(data, axis=axis) return mad_std(data, axis=axis) class BiweightScaleBackgroundRMS(BackgroundRMSBase): """ Class to calculate the background RMS in an array as the (sigma-clipped) biweight scale. Parameters ---------- c : float, optional Tuning constant for the biweight estimator. Default value is 9.0. M : float, optional Initial guess for the biweight location. Default value is `None`. sigma_clip : `astropy.stats.SigmaClip` object, optional A `~astropy.stats.SigmaClip` object that defines the sigma clipping parameters. If `None` then no sigma clipping will be performed. The default is to perform sigma clipping with ``sigma=3.0`` and ``maxiters=5``. Examples -------- >>> from astropy.stats import SigmaClip >>> from photutils import BiweightScaleBackgroundRMS >>> data = np.arange(100) >>> sigma_clip = SigmaClip(sigma=3.0) >>> bkgrms = BiweightScaleBackgroundRMS(sigma_clip=sigma_clip) The background RMS value can be calculated by using the `calc_background_rms` method, e.g.: >>> bkgrms_value = bkgrms.calc_background_rms(data) >>> print(bkgrms_value) # doctest: +FLOAT_CMP 30.09433848589339 Alternatively, the background RMS value can be calculated by calling the class instance as a function, e.g.: >>> bkgrms_value = bkgrms(data) >>> print(bkgrms_value) # doctest: +FLOAT_CMP 30.09433848589339 """ def __init__(self, c=9.0, M=None, **kwargs): super().__init__(**kwargs) self.c = c self.M = M def calc_background_rms(self, data, axis=None): if self.sigma_clip is not None: data = self.sigma_clip(data, axis=axis) return biweight_scale(data, c=self.c, M=self.M, axis=axis) photutils-0.7.2/photutils/background/tests/0000755000214200020070000000000013573510273023260 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/background/tests/__init__.py0000644000214200020070000000000013563423715025362 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/background/tests/test_background_2d.py0000644000214200020070000001761613563423715027413 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the background_2d module. """ import itertools import numpy as np from numpy.testing import assert_allclose, assert_equal import pytest from ..core import MeanBackground from ..background_2d import (BkgZoomInterpolator, BkgIDWInterpolator, Background2D) try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False try: import matplotlib # noqa HAS_MATPLOTLIB = True except ImportError: HAS_MATPLOTLIB = False DATA = np.ones((100, 100)) BKG_RMS = np.zeros((100, 100)) BKG_MESH = np.ones((4, 4)) BKG_RMS_MESH = np.zeros((4, 4)) PADBKG_MESH = np.ones((5, 5)) PADBKG_RMS_MESH = np.zeros((5, 5)) FILTER_SIZES = [(1, 1), (3, 3)] INTERPOLATORS = [BkgZoomInterpolator(), BkgIDWInterpolator()] @pytest.mark.skipif('not HAS_SCIPY') class TestBackground2D: @pytest.mark.parametrize(('filter_size', 'interpolator'), list(itertools.product(FILTER_SIZES, INTERPOLATORS))) def test_background(self, filter_size, interpolator): b = Background2D(DATA, (25, 25), filter_size=filter_size, interpolator=interpolator) assert_allclose(b.background, DATA) assert_allclose(b.background_rms, BKG_RMS) assert_allclose(b.background_mesh, BKG_MESH) assert_allclose(b.background_rms_mesh, BKG_RMS_MESH) assert b.background_median == 1.0 assert b.background_rms_median == 0.0 @pytest.mark.parametrize('interpolator', INTERPOLATORS) def test_background_nonconstant(self, interpolator): data = np.copy(DATA) data[25:50, 50:75] = 10. bkg_low_res = np.copy(BKG_MESH) bkg_low_res[1, 2] = 10. b1 = Background2D(data, (25, 25), filter_size=(1, 1), interpolator=interpolator) assert_allclose(b1.background_mesh, bkg_low_res) assert b1.background.shape == data.shape b2 = Background2D(data, (25, 25), filter_size=(1, 1), edge_method='pad', interpolator=interpolator) assert_allclose(b2.background_mesh, bkg_low_res) assert b2.background.shape == data.shape def test_no_sigma_clipping(self): data = np.copy(DATA) data[10, 10] = 100. b1 = Background2D(data, (25, 25), filter_size=(1, 1), bkg_estimator=MeanBackground()) b2 = Background2D(data, (25, 25), filter_size=(1, 1), sigma_clip=None, bkg_estimator=MeanBackground()) assert b2.background_mesh[0, 0] > b1.background_mesh[0, 0] @pytest.mark.parametrize('filter_size', FILTER_SIZES) def test_resizing(self, filter_size): b1 = Background2D(DATA, (23, 22), filter_size=filter_size, bkg_estimator=MeanBackground(), edge_method='crop') b2 = Background2D(DATA, (23, 22), filter_size=filter_size, bkg_estimator=MeanBackground(), edge_method='pad') assert_allclose(b1.background, b2.background) assert_allclose(b1.background_rms, b2.background_rms) @pytest.mark.parametrize('box_size', ([(25, 25), (23, 22)])) def test_background_mask(self, box_size): """ Test with an input mask. Note that box_size=(23, 22) tests the resizing of the image and mask. """ data = np.copy(DATA) data[25:50, 25:50] = 100. mask = np.zeros(DATA.shape, dtype=bool) mask[25:50, 25:50] = True b = Background2D(data, box_size, filter_size=(1, 1), mask=mask, bkg_estimator=MeanBackground()) assert_allclose(b.background, DATA) assert_allclose(b.background_rms, BKG_RMS) # test edge crop with b2 = Background2D(data, box_size, filter_size=(1, 1), mask=mask, bkg_estimator=MeanBackground(), edge_method='crop') assert_allclose(b2.background, DATA) def test_mask(self): data = np.copy(DATA) data[25:50, 25:50] = 100. mask = np.zeros(DATA.shape, dtype=bool) mask[25:50, 25:50] = True b1 = Background2D(data, (25, 25), filter_size=(1, 1), mask=None, bkg_estimator=MeanBackground()) assert_equal(b1.background_mesh, b1.background_mesh_ma) assert_equal(b1.background_rms_mesh, b1.background_rms_mesh_ma) assert not np.ma.is_masked(b1.mesh_nmasked) b2 = Background2D(data, (25, 25), filter_size=(1, 1), mask=mask, bkg_estimator=MeanBackground()) assert np.ma.count(b2.background_mesh_ma) < b2.nboxes assert np.ma.count(b2.background_rms_mesh_ma) < b2.nboxes assert np.ma.is_masked(b2.mesh_nmasked) def test_completely_masked(self): with pytest.raises(ValueError): mask = np.ones(DATA.shape, dtype=bool) Background2D(DATA, (25, 25), mask=mask) def test_zero_padding(self): """Test case where padding is added only on one axis.""" b = Background2D(DATA, (25, 22), filter_size=(1, 1)) assert_allclose(b.background, DATA) assert_allclose(b.background_rms, BKG_RMS) assert b.background_median == 1.0 assert b.background_rms_median == 0.0 def test_filter_threshold(self): """Only meshes greater than filter_threshold are filtered.""" data = np.copy(DATA) data[25:50, 50:75] = 10. b = Background2D(data, (25, 25), filter_size=(3, 3), filter_threshold=9.) assert_allclose(b.background, DATA) assert_allclose(b.background_mesh, BKG_MESH) b2 = Background2D(data, (25, 25), filter_size=(3, 3), filter_threshold=11.) # no filtering assert b2.background_mesh[1, 2] == 10 def test_filter_threshold_high(self): """No filtering because filter_threshold is too large.""" data = np.copy(DATA) data[25:50, 50:75] = 10. ref_data = np.copy(BKG_MESH) ref_data[1, 2] = 10. b = Background2D(data, (25, 25), filter_size=(3, 3), filter_threshold=100.) assert_allclose(b.background_mesh, ref_data) def test_filter_threshold_nofilter(self): """No filtering because filter_size is (1, 1).""" data = np.copy(DATA) data[25:50, 50:75] = 10. ref_data = np.copy(BKG_MESH) ref_data[1, 2] = 10. b = Background2D(data, (25, 25), filter_size=(1, 1), filter_threshold=1.) assert_allclose(b.background_mesh, ref_data) def test_scalar_sizes(self): b1 = Background2D(DATA, (25, 25), filter_size=(3, 3)) b2 = Background2D(DATA, 25, filter_size=3) assert_allclose(b1.background, b2.background) assert_allclose(b1.background_rms, b2.background_rms) def test_exclude_percentile(self): with pytest.raises(ValueError): Background2D(DATA, (5, 5), exclude_percentile=-1) with pytest.raises(ValueError): Background2D(DATA, (5, 5), exclude_percentile=101) def test_mask_badshape(self): with pytest.raises(ValueError): Background2D(DATA, (25, 25), filter_size=(1, 1), mask=np.zeros((2, 2))) def test_invalid_edge_method(self): with pytest.raises(ValueError): Background2D(DATA, (23, 22), filter_size=(1, 1), edge_method='not_valid') def test_invalid_mesh_idx_len(self): with pytest.raises(ValueError): bkg = Background2D(DATA, (25, 25), filter_size=(1, 1)) bkg._make_2d_array(np.arange(3)) @pytest.mark.skipif('not HAS_MATPLOTLIB') def test_plot_meshes(self): """ This test should run without any errors, but there is no return value. """ b = Background2D(DATA, (25, 25)) b.plot_meshes(outlines=True) photutils-0.7.2/photutils/background/tests/test_core.py0000644000214200020070000000556713563423715025641 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the core module. """ from astropy.stats import SigmaClip import numpy as np from numpy.testing import assert_allclose import pytest from ..core import (BiweightLocationBackground, BiweightScaleBackgroundRMS, MADStdBackgroundRMS, MeanBackground, MedianBackground, MMMBackground, ModeEstimatorBackground, SExtractorBackground, StdBackgroundRMS) from ...datasets.make import make_noise_image BKG = 0.0 STD = 0.5 DATA = make_noise_image((100, 100), distribution='gaussian', mean=BKG, stddev=STD, random_state=12345) BKG_CLASS0 = [MeanBackground, MedianBackground, ModeEstimatorBackground, MMMBackground, SExtractorBackground] # BiweightLocationBackground cannot handle a constant background # (astropy.stats.biweight_location needs to be fixed) BKG_CLASS = BKG_CLASS0 + [BiweightLocationBackground] RMS_CLASS = [StdBackgroundRMS, MADStdBackgroundRMS, BiweightScaleBackgroundRMS] SIGMA_CLIP = SigmaClip(sigma=3.) @pytest.mark.parametrize('bkg_class', BKG_CLASS0) def test_constant_background(bkg_class): data = np.ones((100, 100)) bkg = bkg_class(sigma_clip=SIGMA_CLIP) bkgval = bkg.calc_background(data) assert not np.ma.isMaskedArray(bkgval) assert_allclose(bkgval, 1.0) assert_allclose(bkg(data), bkg.calc_background(data)) @pytest.mark.parametrize('bkg_class', BKG_CLASS) def test_background(bkg_class): bkg = bkg_class(sigma_clip=SIGMA_CLIP) bkgval = bkg.calc_background(DATA) assert not np.ma.isMaskedArray(bkgval) assert_allclose(bkgval, BKG, atol=1.e-2) assert_allclose(bkg(DATA), bkg.calc_background(DATA)) @pytest.mark.parametrize('bkg_class', BKG_CLASS) def test_background_axis(bkg_class): bkg = bkg_class(sigma_clip=SIGMA_CLIP) bkg_arr = bkg.calc_background(DATA, axis=0) bkgi = [] for i in range(100): bkgi.append(bkg.calc_background(DATA[:, i])) bkgi = np.array(bkgi) assert_allclose(bkg_arr, bkgi) bkg_arr = bkg.calc_background(DATA, axis=1) bkgi = [] for i in range(100): bkgi.append(bkg.calc_background(DATA[i, :])) bkgi = np.array(bkgi) assert_allclose(bkg_arr, bkgi) def test_sextrator_background_zero_std(): data = np.ones((100, 100)) bkg = SExtractorBackground(sigma_clip=None) assert_allclose(bkg.calc_background(data), 1.0) def test_sextrator_background_skew(): data = np.arange(100) data[70:] = 1.e7 bkg = SExtractorBackground(sigma_clip=None) assert_allclose(bkg.calc_background(data), np.median(data)) @pytest.mark.parametrize('rms_class', RMS_CLASS) def test_background_rms(rms_class): bkgrms = rms_class(sigma_clip=SIGMA_CLIP) assert_allclose(bkgrms.calc_background_rms(DATA), STD, atol=1.e-2) assert_allclose(bkgrms(DATA), bkgrms.calc_background_rms(DATA)) photutils-0.7.2/photutils/centroids/0000755000214200020070000000000013573510273021771 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/centroids/__init__.py0000644000214200020070000000023513563423715024105 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage contains tools for centroiding sources. """ from .core import * # noqa photutils-0.7.2/photutils/centroids/core.py0000644000214200020070000005267213572576632023321 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ The module contains tools for centroiding sources. """ import inspect import warnings from astropy.modeling import Fittable2DModel, Parameter from astropy.modeling.fitting import LevMarLSQFitter from astropy.modeling.models import (CONSTRAINTS_DOC, Const1D, Const2D, Gaussian1D, Gaussian2D) from astropy.nddata.utils import overlap_slices from astropy.utils.exceptions import AstropyUserWarning import numpy as np __all__ = ['GaussianConst2D', 'centroid_com', 'gaussian1d_moments', 'fit_2dgaussian', 'centroid_1dg', 'centroid_2dg', 'centroid_sources', 'centroid_epsf'] class GaussianConst2D(Fittable2DModel): """ A model for a 2D Gaussian plus a constant. Parameters ---------- constant : float Value of the constant. amplitude : float Amplitude of the Gaussian. x_mean : float Mean of the Gaussian in x. y_mean : float Mean of the Gaussian in y. x_stddev : float Standard deviation of the Gaussian in x. ``x_stddev`` and ``y_stddev`` must be specified unless a covariance matrix (``cov_matrix``) is input. y_stddev : float Standard deviation of the Gaussian in y. ``x_stddev`` and ``y_stddev`` must be specified unless a covariance matrix (``cov_matrix``) is input. theta : float, optional Rotation angle in radians. The rotation angle increases counterclockwise. """ constant = Parameter(default=1) amplitude = Parameter(default=1) x_mean = Parameter(default=0) y_mean = Parameter(default=0) x_stddev = Parameter(default=1) y_stddev = Parameter(default=1) theta = Parameter(default=0) @staticmethod def evaluate(x, y, constant, amplitude, x_mean, y_mean, x_stddev, y_stddev, theta): """Two dimensional Gaussian plus constant function.""" model = Const2D(constant)(x, y) + Gaussian2D(amplitude, x_mean, y_mean, x_stddev, y_stddev, theta)(x, y) return model GaussianConst2D.__doc__ += CONSTRAINTS_DOC def centroid_com(data, mask=None, oversampling=1.): """ Calculate the centroid of an n-dimensional array as its "center of mass" determined from moments. Invalid values (e.g. NaNs or infs) in the ``data`` array are automatically masked. Parameters ---------- data : array_like The input n-dimensional array. mask : array_like (bool), optional A boolean mask, with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. oversampling : float or tuple of two floats, optional Oversampling factors of pixel indices. If ``oversampling`` is a scalar this is treated as both x and y directions having the same oversampling factor; otherwise it is treated as ``(x_oversamp, y_oversamp)``. Returns ------- centroid : `~numpy.ndarray` The coordinates of the centroid in pixel order (e.g. ``(x, y)`` or ``(x, y, z)``), not numpy axis order. """ oversampling = np.atleast_1d(oversampling) if len(oversampling) == 1: oversampling = np.repeat(oversampling, 2) # as these need to match data we reverse the order to (y, x) oversampling = oversampling[::-1] if np.any(oversampling <= 0): raise ValueError('Oversampling factors must all be positive numbers.') data = data.astype(float) if mask is not None and mask is not np.ma.nomask: mask = np.asarray(mask, dtype=bool) if data.shape != mask.shape: raise ValueError('data and mask must have the same shape.') data[mask] = 0. badidx = ~np.isfinite(data) if np.any(badidx): warnings.warn('Input data contains input values (e.g. NaNs or infs), ' 'which were automatically masked.', AstropyUserWarning) data[badidx] = 0. total = np.sum(data) indices = np.ogrid[[slice(0, i) for i in data.shape]] # note the output array is reversed to give (x, y) order return np.array([np.sum(indices[axis] * data) / total / oversampling[axis] for axis in range(data.ndim)])[::-1] def gaussian1d_moments(data, mask=None): """ Estimate 1D Gaussian parameters from the moments of 1D data. This function can be useful for providing initial parameter values when fitting a 1D Gaussian to the ``data``. Parameters ---------- data : array_like (1D) The 1D array. mask : array_like (1D bool), optional A boolean mask, with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Returns ------- amplitude, mean, stddev : float The estimated parameters of a 1D Gaussian. """ if np.any(~np.isfinite(data)): data = np.ma.masked_invalid(data) warnings.warn('Input data contains input values (e.g. NaNs or infs), ' 'which were automatically masked.', AstropyUserWarning) else: data = np.ma.array(data) if mask is not None and mask is not np.ma.nomask: mask = np.asanyarray(mask) if data.shape != mask.shape: raise ValueError('data and mask must have the same shape.') data.mask |= mask data.fill_value = 0. data = data.filled() x = np.arange(data.size) x_mean = np.sum(x * data) / np.sum(data) x_stddev = np.sqrt(abs(np.sum(data * (x - x_mean)**2) / np.sum(data))) amplitude = np.ptp(data) return amplitude, x_mean, x_stddev def fit_2dgaussian(data, error=None, mask=None): """ Fit a 2D Gaussian plus a constant to a 2D image. Invalid values (e.g. NaNs or infs) in the ``data`` or ``error`` arrays are automatically masked. The mask for invalid values represents the combination of the invalid-value masks for the ``data`` and ``error`` arrays. Parameters ---------- data : array_like The 2D array of the image. error : array_like, optional The 2D array of the 1-sigma errors of the input ``data``. mask : array_like (bool), optional A boolean mask, with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Returns ------- result : A `GaussianConst2D` model instance. The best-fitting Gaussian 2D model. """ from ..morphology import data_properties # prevent circular imports data = np.ma.asanyarray(data) if mask is not None and mask is not np.ma.nomask: mask = np.asanyarray(mask) if data.shape != mask.shape: raise ValueError('data and mask must have the same shape.') data.mask |= mask if np.any(~np.isfinite(data)): data = np.ma.masked_invalid(data) warnings.warn('Input data contains input values (e.g. NaNs or infs), ' 'which were automatically masked.', AstropyUserWarning) if error is not None: error = np.ma.masked_invalid(error) if data.shape != error.shape: raise ValueError('data and error must have the same shape.') data.mask |= error.mask weights = 1.0 / error.clip(min=1.e-30) else: weights = np.ones(data.shape) if np.ma.count(data) < 7: raise ValueError('Input data must have a least 7 unmasked values to ' 'fit a 2D Gaussian plus a constant.') # assign zero weight to masked pixels if data.mask is not np.ma.nomask: weights[data.mask] = 0. mask = data.mask data.fill_value = 0.0 data = data.filled() # Subtract the minimum of the data as a crude background estimate. # This will also make the data values positive, preventing issues with # the moment estimation in data_properties (moments from negative data # values can yield undefined Gaussian parameters, e.g. x/y_stddev). props = data_properties(data - np.min(data), mask=mask) init_const = 0. # subtracted data minimum above init_amplitude = np.ptp(data) g_init = GaussianConst2D(constant=init_const, amplitude=init_amplitude, x_mean=props.xcentroid.value, y_mean=props.ycentroid.value, x_stddev=props.semimajor_axis_sigma.value, y_stddev=props.semiminor_axis_sigma.value, theta=props.orientation.value) fitter = LevMarLSQFitter() y, x = np.indices(data.shape) gfit = fitter(g_init, x, y, data, weights=weights) return gfit def centroid_1dg(data, error=None, mask=None): """ Calculate the centroid of a 2D array by fitting 1D Gaussians to the marginal ``x`` and ``y`` distributions of the array. Invalid values (e.g. NaNs or infs) in the ``data`` or ``error`` arrays are automatically masked. The mask for invalid values represents the combination of the invalid-value masks for the ``data`` and ``error`` arrays. Parameters ---------- data : array_like The 2D data array. error : array_like, optional The 2D array of the 1-sigma errors of the input ``data``. mask : array_like (bool), optional A boolean mask, with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Returns ------- centroid : `~numpy.ndarray` The ``x, y`` coordinates of the centroid. """ data = np.ma.asanyarray(data) if mask is not None and mask is not np.ma.nomask: mask = np.asanyarray(mask) if data.shape != mask.shape: raise ValueError('data and mask must have the same shape.') data.mask |= mask if np.any(~np.isfinite(data)): data = np.ma.masked_invalid(data) warnings.warn('Input data contains input values (e.g. NaNs or infs), ' 'which were automatically masked.', AstropyUserWarning) if error is not None: error = np.ma.masked_invalid(error) if data.shape != error.shape: raise ValueError('data and error must have the same shape.') data.mask |= error.mask error.mask = data.mask xy_error = [np.sqrt(np.ma.sum(error**2, axis=i)) for i in [0, 1]] xy_weights = [(1.0 / xy_error[i].clip(min=1.e-30)) for i in [0, 1]] else: xy_weights = [np.ones(data.shape[i]) for i in [1, 0]] # assign zero weight where an entire row or column is masked if np.any(data.mask): bad_idx = [np.all(data.mask, axis=i) for i in [0, 1]] for i in [0, 1]: xy_weights[i][bad_idx[i]] = 0. xy_data = [np.ma.sum(data, axis=i).data for i in [0, 1]] constant_init = np.ma.min(data) centroid = [] for (data_i, weights_i) in zip(xy_data, xy_weights): params_init = gaussian1d_moments(data_i) g_init = Const1D(constant_init) + Gaussian1D(*params_init) fitter = LevMarLSQFitter() x = np.arange(data_i.size) g_fit = fitter(g_init, x, data_i, weights=weights_i) centroid.append(g_fit.mean_1.value) return np.array(centroid) def centroid_2dg(data, error=None, mask=None): """ Calculate the centroid of a 2D array by fitting a 2D Gaussian (plus a constant) to the array. Invalid values (e.g. NaNs or infs) in the ``data`` or ``error`` arrays are automatically masked. The mask for invalid values represents the combination of the invalid-value masks for the ``data`` and ``error`` arrays. Parameters ---------- data : array_like The 2D data array. error : array_like, optional The 2D array of the 1-sigma errors of the input ``data``. mask : array_like (bool), optional A boolean mask, with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Returns ------- centroid : `~numpy.ndarray` The ``x, y`` coordinates of the centroid. """ gfit = fit_2dgaussian(data, error=error, mask=mask) return np.array([gfit.x_mean.value, gfit.y_mean.value]) def centroid_sources(data, xpos, ypos, box_size=11, footprint=None, error=None, mask=None, centroid_func=centroid_com): """ Calculate the centroid of sources at the defined positions. A cutout image centered on each input position will be used to calculate the centroid position. The cutout image is defined either using the ``box_size`` or ``footprint`` keyword. The ``footprint`` keyword can be used to create a non-rectangular cutout image. Parameters ---------- data : array_like The 2D array of the image. xpos, ypos : float or array-like of float The initial ``x`` and ``y`` pixel position(s) of the center position. A cutout image centered on this position be used to calculate the centroid. box_size : int or array-like of int, optional The size of the cutout image along each axis. If ``box_size`` is a number, then a square cutout of ``box_size`` will be created. If ``box_size`` has two elements, they should be in ``(ny, nx)`` order. footprint : `~numpy.ndarray` of bools, optional A 2D boolean array where `True` values describe the local footprint region to cutout. ``footprint`` can be used to create a non-rectangular cutout image, in which case the input ``xpos`` and ``ypos`` represent the center of the minimal bounding box for the input ``footprint``. ``box_size=(n, m)`` is equivalent to ``footprint=np.ones((n, m))``. Either ``box_size`` or ``footprint`` must be defined. If they are both defined, then ``footprint`` overrides ``box_size``. mask : array_like, bool, optional A 2D boolean array with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. error : array_like, optional The 2D array of the 1-sigma errors of the input ``data``. ``error`` must have the same shape as ``data``. ``error`` will be used only if supported by the input ``centroid_func``. centroid_func : callable, optional A callable object (e.g. function or class) that is used to calculate the centroid of a 2D array. The ``centroid_func`` must accept a 2D `~numpy.ndarray`, have a ``mask`` keyword and optionally an ``error`` keyword. The callable object must return a tuple of two 1D `~numpy.ndarray`\\s, representing the x and y centroids. The default is `~photutils.centroids.centroid_com`. Returns ------- xcentroid, ycentroid : `~numpy.ndarray` The ``x`` and ``y`` pixel position(s) of the centroids. """ xpos = np.atleast_1d(xpos) ypos = np.atleast_1d(ypos) if xpos.ndim != 1: raise ValueError('xpos must be a 1D array.') if ypos.ndim != 1: raise ValueError('ypos must be a 1D array.') if footprint is None: if box_size is None: raise ValueError('box_size or footprint must be defined.') box_size = np.atleast_1d(box_size) if len(box_size) == 1: box_size = np.repeat(box_size, 2) if len(box_size) != 2: raise ValueError('box_size must have 1 or 2 elements.') footprint = np.ones(box_size, dtype=bool) else: footprint = np.asanyarray(footprint, dtype=bool) if footprint.ndim != 2: raise ValueError('footprint must be a 2D array.') use_error = False spec = inspect.getfullargspec(centroid_func) if 'mask' not in spec.args: raise ValueError('The input "centroid_func" must have a "mask" ' 'keyword.') if 'error' in spec.args: use_error = True xcentroids = [] ycentroids = [] for xp, yp in zip(xpos, ypos): slices_large, slices_small = overlap_slices(data.shape, footprint.shape, (yp, xp)) data_cutout = data[slices_large] mask_cutout = None if mask is not None: mask_cutout = mask[slices_large] footprint_mask = ~footprint # trim footprint mask if partial overlap on the data footprint_mask = footprint_mask[slices_small] if mask_cutout is None: mask_cutout = footprint_mask else: # combine the input mask and footprint mask mask_cutout = np.logical_or(mask_cutout, footprint_mask) if error is not None and use_error: error_cutout = error[slices_large] xcen, ycen = centroid_func(data_cutout, mask=mask_cutout, error=error_cutout) else: xcen, ycen = centroid_func(data_cutout, mask=mask_cutout) xcentroids.append(xcen + slices_large[1].start) ycentroids.append(ycen + slices_large[0].start) return np.array(xcentroids), np.array(ycentroids) def centroid_epsf(data, mask=None, oversampling=4, shift_val=0.5): """ Calculates centering shift of data using pixel symmetry, as described by Anderson and King (2000; PASP 112, 1360) in their ePSF-fitting algorithm. Calculate the shift of a 2-dimensional symmetric image based on the asymmetry between f(x, N) and f(x, -N), along with the differential df/dy(x, shift_val) and df/dy(x, -shift_val). Invalid values (e.g. NaNs or infs) in the ``data`` array are automatically masked. Parameters ---------- data : array_like The input n-dimensional array. mask : array_like (bool), optional A boolean mask, with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. oversampling : float or tuple of two floats, optional Oversampling factors of pixel indices. If ``oversampling`` is a scalar this is treated as both x and y directions having the same oversampling factor. Otherwise it is treated as ``(x_oversamp, y_oversamp)``. shift_val : float, optional The undersampled value at which to compute the shifts. Default is half a pixel. If supplied, must be a strictly positive number. Returns ------- centroid : tuple of floats The (x, y) coordinates of the centroid in pixel order. """ oversampling = np.atleast_1d(oversampling) if len(oversampling) == 1: oversampling = np.repeat(oversampling, 2) if np.any(oversampling <= 0): raise ValueError('Oversampling factors must all be positive numbers.') data = data.astype(float) if mask is not None and mask is not np.ma.nomask: mask = np.asarray(mask, dtype=bool) if data.shape != mask.shape: raise ValueError('data and mask must have the same shape.') data[mask] = 0. if shift_val <= 0: raise ValueError('shift_val must be a positive number.') # Assume the center of the ePSF is the middle of an odd-sized grid. xidx_0 = int((data.shape[1] - 1) / 2) x_0 = np.arange(data.shape[1], dtype=float)[xidx_0] / oversampling[0] yidx_0 = int((data.shape[0] - 1) / 2) y_0 = np.arange(data.shape[0], dtype=float)[yidx_0] / oversampling[1] x_shiftidx = np.around((shift_val * oversampling[0])).astype(int) y_shiftidx = np.around((shift_val * oversampling[1])).astype(int) badidx = ~np.isfinite([data[y, x] for x in [xidx_0, xidx_0+x_shiftidx, xidx_0+x_shiftidx-1, xidx_0+x_shiftidx+1] for y in [yidx_0, yidx_0+y_shiftidx, yidx_0+y_shiftidx-1, yidx_0+y_shiftidx+1]]) if np.any(badidx): raise ValueError('One or more centroiding pixels is set to a bad ' 'value, e.g., NaN or inf.') # In Anderson & King (2000) notation this is psi_E(0.5, 0.0) and # values used to compute derivatives. psi_pos_x = data[yidx_0, xidx_0 + x_shiftidx] psi_pos_x_m1 = data[yidx_0, xidx_0 + x_shiftidx - 1] psi_pos_x_p1 = data[yidx_0, xidx_0 + x_shiftidx + 1] # Our derivatives are simple differences across two data points, but # this must be in units of the undersampled grid, so 2 pixels becomes # 2/oversampling pixels dpsi_pos_x = np.abs(psi_pos_x_p1 - psi_pos_x_m1) / (2. / oversampling[0]) # psi_E(-0.5, 0.0) and derivative components. psi_neg_x = data[yidx_0, xidx_0 - x_shiftidx] psi_neg_x_m1 = data[yidx_0, xidx_0 - x_shiftidx - 1] psi_neg_x_p1 = data[yidx_0, xidx_0 - x_shiftidx + 1] dpsi_neg_x = np.abs(psi_neg_x_p1 - psi_neg_x_m1) / (2. / oversampling[0]) x_shift = (psi_pos_x - psi_neg_x) / (dpsi_pos_x + dpsi_neg_x) # psi_E(0.0, 0.5) and derivatives. psi_pos_y = data[yidx_0 + y_shiftidx, xidx_0] psi_pos_y_m1 = data[yidx_0 + y_shiftidx - 1, xidx_0] psi_pos_y_p1 = data[yidx_0 + y_shiftidx + 1, xidx_0] dpsi_pos_y = np.abs(psi_pos_y_p1 - psi_pos_y_m1) / (2. / oversampling[1]) # psi_E(0.0, -0.5) and derivative components. psi_neg_y = data[yidx_0 - y_shiftidx, xidx_0] psi_neg_y_m1 = data[yidx_0 - y_shiftidx - 1, xidx_0] psi_neg_y_p1 = data[yidx_0 - y_shiftidx + 1, xidx_0] dpsi_neg_y = np.abs(psi_neg_y_p1 - psi_neg_y_m1) / (2. / oversampling[1]) y_shift = (psi_pos_y - psi_neg_y) / (dpsi_pos_y + dpsi_neg_y) return x_0 + x_shift, y_0 + y_shift photutils-0.7.2/photutils/centroids/tests/0000755000214200020070000000000013573510273023133 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/centroids/tests/__init__.py0000644000214200020070000000000013563423715025235 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/centroids/tests/test_core.py0000644000214200020070000002255113572576632025513 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the core module. """ import itertools from astropy.modeling.models import Gaussian1D, Gaussian2D import numpy as np from numpy.testing import assert_allclose import pytest from ..core import (centroid_1dg, centroid_2dg, centroid_com, centroid_epsf, fit_2dgaussian, gaussian1d_moments) from ...psf import IntegratedGaussianPRF try: # the fitting routines in astropy use scipy.optimize import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False XCS = [25.7] YCS = [26.2] XSTDDEVS = [3.2, 4.0] YSTDDEVS = [5.7, 4.1] THETAS = np.array([30., 45.]) * np.pi / 180. DATA = np.zeros((3, 3)) DATA[0:2, 1] = 1. DATA[1, 0:2] = 1. DATA[1, 1] = 2. @pytest.mark.skipif('not HAS_SCIPY') @pytest.mark.parametrize( ('xc_ref', 'yc_ref', 'x_stddev', 'y_stddev', 'theta'), list(itertools.product(XCS, YCS, XSTDDEVS, YSTDDEVS, THETAS))) def test_centroids(xc_ref, yc_ref, x_stddev, y_stddev, theta): model = Gaussian2D(2.4, xc_ref, yc_ref, x_stddev=x_stddev, y_stddev=y_stddev, theta=theta) y, x = np.mgrid[0:50, 0:47] data = model(x, y) xc, yc = centroid_com(data) assert_allclose([xc_ref, yc_ref], [xc, yc], rtol=0, atol=1.e-3) xc2, yc2 = centroid_1dg(data) assert_allclose([xc_ref, yc_ref], [xc2, yc2], rtol=0, atol=1.e-3) xc3, yc3 = centroid_2dg(data) assert_allclose([xc_ref, yc_ref], [xc3, yc3], rtol=0, atol=1.e-3) @pytest.mark.skipif('not HAS_SCIPY') @pytest.mark.parametrize( ('xc_ref', 'yc_ref', 'x_stddev', 'y_stddev', 'theta'), list(itertools.product(XCS, YCS, XSTDDEVS, YSTDDEVS, THETAS))) def test_centroids_witherror(xc_ref, yc_ref, x_stddev, y_stddev, theta): model = Gaussian2D(2.4, xc_ref, yc_ref, x_stddev=x_stddev, y_stddev=y_stddev, theta=theta) y, x = np.mgrid[0:50, 0:50] data = model(x, y) error = np.sqrt(data) xc2, yc2 = centroid_1dg(data, error=error) assert_allclose([xc_ref, yc_ref], [xc2, yc2], rtol=0, atol=1.e-3) xc3, yc3 = centroid_2dg(data, error=error) assert_allclose([xc_ref, yc_ref], [xc3, yc3], rtol=0, atol=1.e-3) @pytest.mark.skipif('not HAS_SCIPY') @pytest.mark.parametrize( ('xc_ref', 'yc_ref', 'x_stddev', 'y_stddev', 'theta'), list(itertools.product(XCS, YCS, XSTDDEVS, YSTDDEVS, THETAS))) def test_centroids_oversampling(xc_ref, yc_ref, x_stddev, y_stddev, theta): model = Gaussian2D(2.4, xc_ref, yc_ref, x_stddev=x_stddev, y_stddev=y_stddev, theta=theta) y, x = np.mgrid[0:50, 0:50] data = model(x, y) mask = np.zeros(data.shape, dtype=bool) data[10, 10] = 1.e5 mask[10, 10] = True for oversampling in [4, (4, 6)]: if not hasattr(oversampling, '__len__'): _oversampling = (oversampling, oversampling) else: _oversampling = oversampling xc, yc = centroid_com(data, mask=mask, oversampling=oversampling) assert_allclose([xc, yc], [xc_ref / _oversampling[0], yc_ref / _oversampling[1]], rtol=0, atol=1.e-3) @pytest.mark.skipif('not HAS_SCIPY') def test_centroids_withmask(): xc_ref, yc_ref = 24.7, 25.2 model = Gaussian2D(2.4, xc_ref, yc_ref, x_stddev=5.0, y_stddev=5.0) y, x = np.mgrid[0:50, 0:50] data = model(x, y) mask = np.zeros(data.shape, dtype=bool) data[10, 10] = 1.e5 mask[10, 10] = True xc, yc = centroid_com(data, mask=mask) assert_allclose([xc, yc], [xc_ref, yc_ref], rtol=0, atol=1.e-3) xc2, yc2 = centroid_1dg(data, mask=mask) assert_allclose([xc2, yc2], [xc_ref, yc_ref], rtol=0, atol=1.e-3) xc3, yc3 = centroid_2dg(data, mask=mask) assert_allclose([xc3, yc3], [xc_ref, yc_ref], rtol=0, atol=1.e-3) @pytest.mark.skipif('not HAS_SCIPY') def test_centroids_withmask_nonbool(): data = np.arange(16).reshape(4, 4) mask = np.zeros(data.shape) mask[0:2, :] = 1 mask2 = np.array(mask, dtype=bool) xc1, yc1 = centroid_com(data, mask=mask) xc2, yc2 = centroid_com(data, mask=mask2) assert_allclose([xc1, yc1], [xc2, yc2]) @pytest.mark.skipif('not HAS_SCIPY') @pytest.mark.parametrize('use_mask', [True, False]) def test_centroids_nan_withmask(use_mask): xc_ref, yc_ref = 24.7, 25.2 model = Gaussian2D(2.4, xc_ref, yc_ref, x_stddev=5.0, y_stddev=5.0) y, x = np.mgrid[0:50, 0:50] data = model(x, y) data[20, :] = np.nan if use_mask: mask = np.zeros(data.shape, dtype=bool) mask[20, :] = True else: mask = None xc, yc = centroid_com(data, mask=mask) assert_allclose(xc, xc_ref, rtol=0, atol=1.e-3) assert yc > yc_ref xc2, yc2 = centroid_1dg(data, mask=mask) assert_allclose([xc2, yc2], [xc_ref, yc_ref], rtol=0, atol=1.e-3) xc3, yc3 = centroid_2dg(data, mask=mask) assert_allclose([xc3, yc3], [xc_ref, yc_ref], rtol=0, atol=1.e-3) def test_centroid_com_mask(): """Test centroid_com with and without an image_mask.""" data = np.ones((2, 2)).astype(float) mask = [[False, False], [True, True]] centroid = centroid_com(data, mask=None) centroid_mask = centroid_com(data, mask=mask) assert_allclose([0.5, 0.5], centroid, rtol=0, atol=1.e-6) assert_allclose([0.5, 0.0], centroid_mask, rtol=0, atol=1.e-6) @pytest.mark.skipif('not HAS_SCIPY') def test_invalid_mask_shape(): """ Test if ValueError raises if mask shape doesn't match data shape. """ data = np.zeros((4, 4)) mask = np.zeros((2, 2), dtype=bool) with pytest.raises(ValueError): centroid_com(data, mask=mask) with pytest.raises(ValueError): centroid_1dg(data, mask=mask) with pytest.raises(ValueError): centroid_2dg(data, mask=mask) with pytest.raises(ValueError): gaussian1d_moments(data, mask=mask) @pytest.mark.skipif('not HAS_SCIPY') def test_invalid_error_shape(): """ Test if ValueError raises if error shape doesn't match data shape. """ error = np.zeros((2, 2), dtype=bool) with pytest.raises(ValueError): centroid_1dg(np.zeros((4, 4)), error=error) with pytest.raises(ValueError): centroid_2dg(np.zeros((4, 4)), error=error) def test_gaussian1d_moments(): x = np.arange(100) desired = (75, 50, 5) g = Gaussian1D(*desired) data = g(x) result = gaussian1d_moments(data) assert_allclose(result, desired, rtol=0, atol=1.e-6) data[0] = 1.e5 mask = np.zeros(data.shape).astype(bool) mask[0] = True result = gaussian1d_moments(data, mask=mask) assert_allclose(result, desired, rtol=0, atol=1.e-6) data[0] = np.nan mask = np.zeros(data.shape).astype(bool) mask[0] = True result = gaussian1d_moments(data, mask=mask) assert_allclose(result, desired, rtol=0, atol=1.e-6) @pytest.mark.skipif('not HAS_SCIPY') def test_fit2dgaussian_dof(): data = np.ones((2, 2)) with pytest.raises(ValueError): fit_2dgaussian(data) @pytest.mark.skipif('not HAS_SCIPY') def test_centroid_epsf(): sigma = 0.5 psf = IntegratedGaussianPRF(sigma=sigma) for oversampling in [4, (4, 6)]: if not hasattr(oversampling, '__len__'): _oversampling = (oversampling, oversampling) else: _oversampling = oversampling x = np.arange(1 + 25 * _oversampling[0]) / _oversampling[0] x0 = x[-1] / 2 x -= x0 y = np.arange(1 + 25 * _oversampling[1]) / _oversampling[1] y0 = y[-1] / 2 y -= y0 offsets = np.array([0.1, 0.03]) data = psf.evaluate(x=x.reshape(1, -1), y=y.reshape(-1, 1), flux=1, x_0=offsets[0], y_0=offsets[1], sigma=sigma) mask = np.zeros(data.shape, dtype=bool) mask[0, 0] = 1 centers = centroid_epsf(data, mask=mask, oversampling=oversampling) assert_allclose(centers, offsets+x0, rtol=1e-3, atol=1e-2) psf = Gaussian2D() for oversampling in [4, (6, 2)]: if not hasattr(oversampling, '__len__'): _oversampling = (oversampling, oversampling) else: _oversampling = oversampling x = np.arange(1 + 25 * _oversampling[0]) / _oversampling[0] x0 = x[-1] / 2 x -= x0 y = np.arange(1 + 25 * _oversampling[1]) / _oversampling[1] y0 = y[-1] / 2 y -= y0 offsets = np.array([0.1, 0.03]) data = psf.evaluate(x=x.reshape(1, -1), y=y.reshape(-1, 1), amplitude=1, x_mean=offsets[0], y_mean=offsets[1], x_stddev=5, y_stddev=0.5, theta=0) mask = np.zeros(data.shape, dtype=bool) mask[0, 0] = 1 centers = centroid_epsf(data, mask=mask, oversampling=oversampling, shift_val=0.5) assert_allclose(centers, offsets+x0, rtol=1e-3, atol=1e-3) def test_centroid_exceptions(): data = np.ones((5, 5), dtype=float) mask = np.zeros((4, 5), dtype=int) mask[2, 2] = 1 # Test data and mask having the same shape with pytest.raises(ValueError): centroid_epsf(data, mask) with pytest.raises(ValueError): centroid_epsf(data, shift_val=-1) with pytest.raises(ValueError): centroid_epsf(data, oversampling=-1) with pytest.raises(ValueError): centroid_com(data, oversampling=-1) data = np.ones((21, 21), dtype=float) data[10, 10] = np.inf with pytest.raises(ValueError): centroid_epsf(data) photutils-0.7.2/photutils/conftest.py0000644000214200020070000000450413572573376022215 0ustar lbradleySTSCI\science00000000000000# This file is used to configure the behavior of pytest when using the Astropy # test infrastructure. import os from pytest_astropy_header.display import (PYTEST_HEADER_MODULES, TESTED_VERSIONS) from astropy.tests.helper import enable_deprecations_as_exceptions from .version import version, astropy_helpers_version def pytest_configure(config): config.option.astropy_header = True # Uncomment the following line to treat all DeprecationWarnings as # exceptions. For Astropy v2.0 or later, there are 2 additional keywords, # as follow (although default should work for most cases). # To ignore some packages that produce deprecation warnings on import # (in addition to 'compiler', 'scipy', 'pygments', 'ipykernel', and # 'setuptools'), add: # modules_to_ignore_on_import=['module_1', 'module_2'] # To ignore some specific deprecation warning messages for Python version # MAJOR.MINOR or later, add: # warnings_to_ignore_by_pyver={(MAJOR, MINOR): ['Message to ignore']} enable_deprecations_as_exceptions() # 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. Making it pass for KeyError is essential in some cases when # the package uses other astropy affiliated packages. # Customize the following lines to add/remove entries from # the list of packages for which version numbers are displayed when running # the tests. Making it pass for KeyError is essential in some cases when # the package uses other astropy affiliated packages. try: PYTEST_HEADER_MODULES['Cython'] = 'Cython' # noqa PYTEST_HEADER_MODULES['Numpy'] = 'numpy' # noqa PYTEST_HEADER_MODULES['Astropy'] = 'astropy' # noqa PYTEST_HEADER_MODULES['Scipy'] = 'scipy' # noqa PYTEST_HEADER_MODULES['Matplotlib'] = 'matplotlib' # noqa PYTEST_HEADER_MODULES['scikit-image'] = 'skimage' # noqa PYTEST_HEADER_MODULES['scikit-learn'] = 'sklearn' # noqa del PYTEST_HEADER_MODULES['h5py'] # noqa del PYTEST_HEADER_MODULES['Pandas'] # noqa except KeyError: pass # This is to figure out the package version, rather than # using Astropy's packagename = os.path.basename(os.path.dirname(__file__)) TESTED_VERSIONS[packagename] = version TESTED_VERSIONS['astropy_helpers'] = astropy_helpers_version photutils-0.7.2/photutils/cython_version.py0000644000214200020070000000007313573510272023421 0ustar lbradleySTSCI\science00000000000000# Generated file; do not modify cython_version = '0.29.14' photutils-0.7.2/photutils/datasets/0000755000214200020070000000000013573510273021607 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/datasets/__init__.py0000644000214200020070000000032713563423715023725 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage contains tools for making or loading datasets for examples and tests. """ from .load import * # noqa from .make import * # noqa photutils-0.7.2/photutils/datasets/data/0000755000214200020070000000000013573510273022520 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/datasets/data/README.rst0000644000214200020070000000025612410036146024201 0ustar lbradleySTSCI\science00000000000000This folder contains data files bundled with `photutils`. fermi_counts.fits.gz -------------------- Fermi LAT counts image created by Christoph Deil (copied from Gammapy). photutils-0.7.2/photutils/datasets/data/fermi_counts.fits.gz0000644000214200020070000005066012346164012026523 0ustar lbradleySTSCI\science00000000000000‹{‰Rfermi_counts_gc.fitsí}m\DZÞY.%ù^$äK¾$› øJFL“Ô‹e3qšZË„%JW†å‹€ ©•Ęä2»«·Ÿ™Y¶Tûl½wõ™³2 ¢v¦OwUuuÕSÕ}ÎÌÜ¿ûáÇìïíýn¡ƒ½ë{Žž}qtüôdïôhïwîïœ>|öùÃãϹ{{¿¿{ðñÝ¿ü~³â÷ðøøá÷{Ÿ?<}¸wúýóCžËtïö_îÞßøÝXñ{öõÓ¿ï}Ñ8?~zøìäñѳ–ßþ_öï½'Î7Lf/é%½¤—ô’^ÒKzI/é†Öåäý»ÝûÝÞëw?¼ýþª’Þ{\¾¾wÖzøÝéYUjñÓêç·ÞºwíÎíOÎûË'·¯]»öóŸÿü—{«ÿ­¸??><9|¶ZéÓ¯÷žýßÃG§k?zzxúÕÑç{w>Y¹Ë†ß›¿ºqó„öÿûõrøÅáñá³G‡’‹œ×ï“?ßþ€_ß½¿Úè·÷ðt£Ì±‡ñ÷ö?8`ù]»ñ«µýþrm³¤Ÿ=:Þ8ó¯Õr?ÿêû“Ç>Yí@Wf] }~tòøÎ§÷îžñ{ýóÃ/7ŒÎÛïã6ìëgO×|^æ»^7_¬Ç탋ëñÞþÈ‚lÖcÃïfÝzðñq¶+ý" ²YžßÙz|–X7#ëñ™¾Ÿ|tp[›ïݧ¿\MõèôáÆêo¬¤þB±ß{·Ö˜¼Öo…'o]»yóÚÍwnܸõæ[·n¼ûúŠáŸî=:><㷙ý7>[ѵ?¼öÞ{_}uëéÓ[''{Ÿnøýáîû÷n¸¿â÷·ÇÏž~þàÑÑ×+oxððW_¬ðxÍ0Dûìß¿óÑÇgþwÿà‚ýž=|z¸6Ûéá“ÓGGÏ÷¾<|vx¼ÒöÙ—gxŽîÞ»ðɧýVî¼iâù=~vrzüõÓ•'« ×ö»öÑïïoìwã7×Öÿ½}pó[o¿uë­_ÿjí×ë9Ÿœ><>=3ÞÃgŸï>~¡ôÊ+þvrxüÍ‹ÕútÃoÿÞ{m=Îø­ÖcóßüWLÜîÜýpí‚+~ͧÎÏwív'{_o†oX>Y±þ±Ïùâšß_÷?ùHô¿GOŽý}ÇÇ/âÞXß¿ûŸÝ_ûßÁ§ßæl=¹µf'ߟœ>]iºŠ®UŒ|}rˆÇlk~ŸìÿaÍïƒîÜþà¿Aà‹ãõRoxl¦¿p1ìüéödzùí+~ß~µÂµ<|1óÏqJçÿÕÓ½¿>Û{øüù“Çï|ÿÁGŸðù’ò[u<›ó·«ñ_?{øÍÃÇOþmŠ«©?|öýٵϿ¾÷Þý?íoìÇÐÛ¢ÙEÚÿߟ޽÷Ñ_.ò[y÷f}÷WéüÙÑwë%Y¥ºÝàëÉóÃG¿X¡Øé…sÅUhìòçýOVëññáéj^>~ôÕá““£g›e¹¾·‰êëëXüø®C¿;Ÿìß>øè“õú~yºB˜=\ßûG_œ~ûðø,2¾9<Þ•gðµŠß ˜QúãÝû+vŸ1’>xxzg ]>|~pøôù:$~ùÍ*k½µ6Å;×o¼}ýÆ;{oÞ¼uã×·Þúí*<\Íëûøí÷Ü1Ç|ÿ¸çO÷?ýp5ßÇ_üñèñ_ÿøìñç««¿¯oæûÇ÷>Ý[I~ô÷“¯Ÿî}ýüóMäþå¿>XáøÊó‚ß _n¯Ømðþ×ïÜüÍM´ßá6¹ÈÅõ½û«á¬ÞX•æ>¼}ÿOoìÿyÿÞÁƒ;«…½ÿË·~ùñ»þõ/^g¦ÆÒ{÷WhuÆï½U(oö« pßÍà¿V¯½~óÖYÉ™eõ‚ßj¾gù| 5üVó=ãÇás‚_«‡^?¸ýûp¿•à·BÓ3~·Þ?¸[ ßÊ~omøíßÛÿäýÏ*ìwÆïÃÃ?ï跲߿›ëd{ëæ‹ê4Éu3ß·7üþº¿ÊÃ|pûÞûì§uÜÌ÷m±žLð[Í÷Œßz®ïôòÛÿËÁºü[ó»÷à£{¨ßu²ÓßTZ5<=X'_=yrôíÆ¿z|rztüý&7®j¾Çë~|ôtU´=ÿútò«œûý^Ë ¿kEÔøý~ÿý»÷~ЋêtøÍz7ô`­Ô‹"øß6yÿÿhó­ÖïîÆ2OŸÙçÖÞõ“G«¢öÑW׿|òðäôéóëß|ëÆµ?ܼ~ãúñ7ßúí;ï¼ûöÍ·|sóÍ6u|tÔøæ]„ï?YW«š{µ¾·öÞX鱿6Ü•r'ÿíw7~±÷¯ÿº÷Æþ7§ûO>_•lëòç­võ/ô|wµÉY÷ø!ÿžïù?_ôüÍwohÛ!Q¿;ë{»w?:+OÏ9ãÕׯ¿[o~7Î}ztVt¬Jê•Sì®K·[„Ÿfý/ŽŽÖ~ÒÜäß¾<}|&ã¹0¬ñ#ÿ|òäÁwÏ<_µ<8¿oÝ\ó}°*¡Ÿ¯xþË/ÜÆ|-…0Äoì7~?–×ßþÅÏßÜûÝïönn|äGcqÓsû-bd 衧 9ñ8ÌüÀþÏ¿Ê9̰ù~uôôðúáÑ·‡Ï®¯KÒë«]ÛÓÇןutzôìúªpöòÁ·‡‡òýƒooÜøíÙ ¾¹qãææø!œ¹YÔßœ[ÔMš_ÃÄ‹ªdÕôâÕª­Õ«ÖÆom¥Õ~ÿÆÍõõM%¸±ù»zÿÖoß}ó×ï¾yã­uã†+ÍýëÆöþ‡ùn.lD½“ðâ ?¦Þøtͽñ#6§˜ou¾\?·ò"‹·¤ž¢jý^>Oó’^ÒKzI/é%½¤Ñ4ÍC;3ɹ̱öÝa^_éSG”é¯éY©ƒ&ÓË{'1Ö÷šæŽ%NÞ6ãyþ.$=—¤ÿ:þTâa4Uͧ'ŸxÇTcæòê×;ÏøˆŒÝé,‡_Æyr^U¾±Æ=u’·ÖYÎq6ÎêQUëq¤éÔë'#±c >» áËK¨÷¤÷#äeó¡‡säi\d>Zß‘óFR\-_–¨S£lœfÇrãªjàžs‹¹i ûB«–«ÂÜ%û?¥H½Þÿb_Ôs¾×#wÔØjsíq«xxx{qv[qšñIϹ}ô}Oô´GåÌuΗÅVUÚ´Š.ËYÛ(¬ŽêQ5~é6IÕs§ñU]÷eûõ𯨫2}¥1K¯gFÉßÖùJ5Uï]¤÷sҒψ3´íœ6wmâ‘›¹ÿ²”u½Ì˜ù’Æçó/×z>òì‹{Ïœ":DúY>3 o"{ú¨ŒŠºä²ÅÏeÓwéôS±§7άšhiöµ×Ÿ£ÏÈñ£({v°Ôù¬i®³ß¥ð®ËÕK]ïmÕÆ•µÝ½-žs=G=wñèµ_lzÎ¥Ë6|¤z\”8_ø©ãÍM™{‘þ?Õçó–â7œÿüŒÝó™ÃG×öKð‹Ë®ÿ4꜎‹ÇmÅÑ4*ž¶±ÏXâó5^Zж±k•þÔ“_©|Ïܸ1ǹNïxÏ&*iÔ³=ýG¬I¦ofï¥%âÿÈÜF½ÛÓ?;fmÐýs4-EFÛÔ§úÌ,Z¿djoné=[³t ÿ¬¾‘öŒ.s“5§Þšui1š¥jÿþ)ÐÈóϾ#¯ÖuÜ-Éï3X3k£´­û@ÙõÞÖ3-?Ç×s¯ïèsï|æ”Ý‹i=²G’§ž[¢Þ£)ZS.ÅFÛÈÛžû(ìÔøpÏsD0`d¶-y½Ô9K4;ç:ÿõðÎÆ\Ä_zq·ç{ô8‹F<ãV‘'æ: B²¾¯l[±‘‘—½?µä3õËÆw¹—)E1µbo”é[ͧúüškáÕë•å_5n4/äKkùŠÜ±äX¯8§¬î_ÅϳvK^JÛÀÌ¥Èé¥mŸ•/ ÷¸ó2žÁJ´ÏÐ\±þûÚ”¿'5ÁXÿޏ—²ÔøöèºísÎ%ÄU–.£Îm³ÎÎò‹øÐeX³UAœ«kûÌYTËsÝÃØ6UœÿZ}·] VÒ¶q¡ªfÈì'qMw„×½²zÇÍÍ3J#íÁÆžziäù~æ,³³k›ùbiõ‡–¸·ãdYõˆ·ŸÄ4mkOhñªXÿÞº¥ºÖÔøáþ6#/ëS#~:;†ŽÍâÛ¨Øé‰ályÙq{IgNž¾ÕBûl«nïáU}.•?ªÖÌ—?—æ>Oñ½ŽùÛ”³ ŒòðÛÕ{Ð <äê–¹êÓj;SÞ&£ýUÒÍãw=þ¡µEjÃȘ¹jLj¬9q[㑟ªÞci|ªÏþ2õFÎe¦¥øxOüõʉʛû»€«Ï5(Eμç#=úôRï³÷ÑZ màõ¯ž\7·Ý%yÈ/ò»•™ÞkK«-G¯MvGp·µkß:«ªjÕÑç #Î’$9#ûæƒ4âY-/Uøó¶ÏZztÕöL޹/õPt­çÖsŽü¶-¢9Û¼cé{o-¤ÅKÔïGÿ>aÅ^¡×‡,<ù|¾;,‘³Çˆoxøyè2Çrä\Å{­ò¢G¿ÑÄùotÏYM6Ý­uÒ~ft_e¿Ñ{ìHî‹à¯g-zr“¥Ç÷cŸˆ/Eë— Íu†cшg¡"ø7 «—ˆ¯ÄoçéÓ«gï^;3Ϊ“$ýzýó²Ö^ÊÎ/š»2û‡ˆ]çüþímŸqTÊϬD'î|Ã+÷§FÛð¯ê:ÅÛ18Sÿ"õüݨ³ )ïÌù J´w¼ã3g^¬ä}í:öãöm‘3XM®&»Ê3ùµ‚*÷’ej…LŸ¥œ{e® ¶ë3$ k3û|Á—ˆ=*cõÍäð9×rTmŠsÏàu¶¾Ÿ;¤{%Q¿òàµÕ‘×;¦Šw5¶ebidÅgí3u¨5ÎsÝC46Öñó³#uðRñÀ’iím<û#Mfï|«ãGÓ+Ûœ½z0":ßž:4CZLdjßÈûê=‰&#;¾Š*yVåæl Ô#ÛÛ¯çÙ÷l_Í®¯:dTQOþ´ø-*kË^Šìû²¼¼X«ôè“yfãyGàÓCž³ Ϙ¬ÜmÔÓªÀ¾è\­Xõ½}žÚ\;'Ä~Úø Ì‹K‘þV¿,¯ ®Z1‹¥{äRûHÜŽ­Ö‰“Ä}oêÈÜÕ“[³ø¤Åp…îÛÆm¤9ÏL­ªá{óÕ#‹[دz ½ùõŸ•rZ&xæ\‰ÑÞübÉÎ×[KDtÒxpuÅzË/¶±êå«­IE~îáåñïL š‘ã!+ž+ꈌþ#rüˆ>•ã´±­ÀÞLŒö÷žÕs2#­:ùiyÐSiü9=­¾^5Y^š^™8¬Æžl !ýfDÔF=X¤½ÏÖ¢Uq—­×~ T•ó­ö›Y¸ É¹"ôãøàøž|š­·qçÔ™ïqÈÆV¶¿$¯gO õåðÞ““zc8’ó¢øÓ›OFDÚÇX¼*dfpbTèåÕs!b³ªúgî<;rçå­“²ò310⹎ª|›Ñ%"¯ê÷çôiiÏVÉwD^çÆUÛ-ãk¿âž—ïÁÝ©ŸOu^ñðÔpÆÂ Í·zlñßJÊ~—‡zöðÜu\‹lò´U¬…´ÈòÊôíõÕª¹gøZõ\Ïo¨4ýz~+(S‡fûJ~Tµ·ôøI6î*kE­oÍOnŽs`gå>§ºfò®u—ð:=“ââ8òݯ\äãçØÿXýGò‘'¼k®­Ëœµ·ßRîˆðÏê…Tñ[b½ý½ùmD]™sõÞ£’*ðWêŸ]‡[yócÕ÷.е}ÅÑ'"/’ë³þV»¢¦å:i}´Tª·½Ô§Þ5¶ÎÒªœ ‡KÒs†^Š`W«dïgGütgê·¿·Vã®q¹4«OtÞ^õU”oÕ˜ ¼ÉR¤æ˜ Û¢y®J©N•bÑ‹èžÉ¢lž‹Ä¼ÅÛ²ƒôÚsÆÏéåsµOJ{‰~Õ}½kÇ}® ûkŸ}óØAò‹+ðº"†‘oT¯ÈumL/yí™cö·‰´š¨7ï{Ö k‡h½ƒçÌÑ¢jߊ̹'Þ´óæ,O‹8¿ã®Y<¬Ü“©#µAd\DžÔ'ãѸæÆië%æemæý®I«Æñø@U:G¼EeIùEš7gw)Oys^4v«jH¯?D)ãVný,FeóJs°oÆF#êÄ^¼ÐâAòY ã<>¦µizxÆZ„úáë]Òæù,§{iÏ¢röó♥_Åù‚–ü¾$é ýíWož•Ö»:ÿzyD×ÇKÑgq¼~Öc3Mf?¯OFùfÛ. q±Óó]ÞœôððÔØÒ˜lM!®ŽˆþÒ~Ek“ö¹sølE=ì¹7è‘Cç¼KÚ𺛼Ÿ9ñê%õÑê1ªËȵÌäG´e¦fÍ~__V¦fc ë¼X˜_D¬/ôúj¶¯„SÞZÄ«&»‘çÙ',L¶ÖÅ’EßGrw]³Ÿ‹4¾\?ézo|jgNø>â/ø¹¡®GâÂÓ_[o/E1жÎ+žû¿™Z4‹S™œEùxmñÊ;¢ò·ðg޼¡µiö‹ÌG‹MO¼j~`ñôÜg­¸wèë݃h9gŽú2“oFS÷¥6®Ô/òœRâý~:ìÓƒŸT¶VÇpr-òÖ4VÿhέÐ%zûDñÔÓó•ÈøŒLlóÔkYÙ]¿Òò@Ô×¢ëéyþ9b#O®[SälÑÞÜoQfŒ—·¶ÿµmv…kïö·ac¦¦”Ú)OOâ­g¼ûªjêÁ.'jµ˜ä›žÏÉZTy¶­ñíñ¥¨ÿ¶×^;H‰sq±ÅÅ`¡°ÆÖðÇöâ·ÖNÉÚ—dó”7F$œáâ–’ö]óžûœ^óúsæ;“­þ^Ì¥zJÏOIºà¾`wúÑo­Ü¤Õ\_«žMœãÚ*j+¯ßèØh}›¡ª:¦‚"qÐKÞg+¬ü©óbʉî<˜JõÉø¢FÃ<¿‰ÍsVüIqÒÚ¥{Ä?K^K¼y4"+’ÿw”¸ÒøbÍÃÉAÒÎ’8ŠÔí–N™Z‚ËyIë6â³%‘ÏR{k òÄi†¬ùzr‡…‰·6Öâ!éáåÁÕa´¯´¦QìÈ`M#m?›±KgÇã5ü|c„21Ðó¸ŸlÝnù­)®Nç÷ Ó¤ÛLòi¬›¼¼P_NiœFVÌk2"Ÿaµâœãѯ—0—qkåÕ^[óÕð0#ÏÓ¯çZ¤¶îÉ•ÜXŒ oÌ[6öú>GÒ^€»Ó“°^ã^kñï‰1ÚÆÅ}Õ籪ê&m ¥µÓÚ£²#c×5Þ«/þþó‹W>ž9á²÷FG¬ŸçÚú¯÷w³}"ýpL¶¾”Ú#zdóŽGÎMÊKÚü«b·——uBßWŸé"z}^#í3q½~¬é¥álçõ‰è~‡# ã¼ëoñ¶æ£­µ¯¹±¼÷ºÖýþiõïµÕ¿ÿ²ú÷_§ó9Dª5‘V‹Ò¶Ìó'yê,éó?Üx­ïšv᯴=uj”‡6xë=ë}¤Þìi÷7ßFÖÉ[ kmšœH®ÌèíÅnI®T_y>Áa\‹c,}­:Õ»&ÚùæUAž¥×Þ“W,ü·Æyðѫ׺?æ†5­÷ ?›ÎòÇzñšb=ÅJŸimhS-GEÖMÃI+Ÿrq¡ù¨äŸVN‘øKý¢ù£‘Sž³ø9Î{¹u·ò$Ó’_¹²rmöÙ)zjWoþá®EmÅÝ·öÖ\_N‡¨NÞšË[ažŒÞ_‹ø,’dÓ¨¸³Zé5Öûx­½_ãÞ+/þþ‡él?r•´IzIzÐ6Ï™P&wxûIÏ(OB;Î׊Km^ÌF}¬>š<üç•˽ÏàÇ»g^Ö#zDÚ£}£>ѧw ès–ÈÓËÛz>ª—4 ÓðŽã#ùm—žïÑ0“ÓMºæÍIkí_䬯ŠNg+jµLÓoGxý ù+åïºJÚÆÒçÀ8~ÑüŠzJ|µ:’æÕiâ}Ú+ZßfpE»fa•ã+pAóá(Ž×•‰ÇÁ(?ºö[°“Ö–ÍgÚGr®ÅS:óÏ®}V©¯Õ'ú,&—⠇ІÜ:Yò"íÙœÏùŠ뛼vf…{Žʵ^cÆ6b»%Çz/Å•”S´˜ëÅ(^õÈð>?çyÞyJµl„8ß¶ðNÃ~O­©=¼×¤…këÅ… ü¤|8[zðSò!K_OÞG^Ü}Iïž\¥a8‡Ù\ìÉåQ|¥mZ>÷òõÆ‘d+úk¾hŒzî­Yï38€}9~’?KßMÙ^kX!å?mœ—<¹!sÖïÉ]Œ†­»ÓÅú¥‘§¶èÍ>™|¯­_Ö¦š_¡/Xuo‹sim¤’bžÃ݉iß™.Ön(Çû¯e±õ´î‘Fb?g‘\01:p¹KÃ8‹?^oóÆuo}®NçÏr<þ/a®¥W¦®¥ý´ýµ¦‡ƒQ\Ö0OÃ?íšæKÒœ=<²ùŒÃŽbm—ÚÚ½·Ÿ1¼4 ×¹½¤—‡+¼8fñ´®yó#ʎȳps½GÖš¸8ðø¤$Ûj—| ¯k˜À½·|Púl¶ôW{­µ­ÉºCñ:r®£åBéµ”#=6çäqyÏë'§¤û(Y1låcÚæñ7ª¯ô žØŽÜG“tiã%ýè{+†²Ï2Eqyýwý,ù:‡ÐïÚ±ø´ØÕÎǦ‰^¨çtÒbyFÉë¿ÖkªG'é8<§î½WdµI¼$ý<ã"ùóÎvÖy°ä#‘œÄñ‘ô±ô¶ôàúxI£ùš…Õ‘8ÐÖei:dc…öçjié^­¦‹Ç_¹qT¦ÇÆœ®¹fF)ê^¿ }[ÎxÍËÅ›¦¯$›ÓÅK–ŸÐ÷8îÙéûU-ÜkºDHÂ+®°wf%éŠzZqÄá2§’šLIžg^œ/zb]ãíÅÚfù#Õûx1^³“•c¸÷<•üTòAí¸þvrºZçTZüïÂ{*ã%µI×½ñEÉ:3òø§¦Sï8ßzÖÕ’ÇñÌ<—"­¡ägôºW&cN‘dJ˜‰Äù!ç÷¨ŽÁñ´ýêdÏSÏÉãÎ<ø¢ñ—Ú´sNž´¶ôA»sd}qyG»¯EûrÏ@qxFåàP$‰Gžõó`úxdÏ<ÁxϼQVÔ$¾TwêÿÜ=IIž¥—öž“ý,œñP4' Eîÿp~â­½­}Ÿ–sü±óKoœp:FúröÃ>Ü9«µŽXÿ!qx§Å€4õ¢¼8²Ö•òçÆõÚßÂ0ÌÜžSz–m)Õª»ooÍ6žüý%_ñâ7ןËURÜq:H÷½½ßË*}î1SòkNljé+­þ¥¾ÐÎf88ùÑ{÷RÌr<%ݽ¯%~šj¾¬ùR#\7)¥ó@:&bËG´±/ª'’tÏŒêAÇzqóg®ÊB\‘âÇIë)ÝÇÔâ ãÆsdùö‘Î)¸>”h~¦Mãgw6ŠºKûiiM¸k´4–ãÑtD}¸ë”8L³|Pk—jtN®·žG9ܾSŠiœ§Æåt²æÄéï­a,½<×¹¿HÞs”­A=6£Ïrã$Üy;qk'­§—g#í™//k^\\aɾT/./pŸáÐ|ŽkËæIîšÕÞ®qòÛk »w ‡7ZÌéÉÉ×|ûã3n6îL¼m§P®¦£„×Ú\"{^äëÍG¨¿fŽ„ã´Íûœ®(ïÊt~ §)f_/Žxr“¶þÈOóY‰—Ä1FÃ>ÉîtNÖs¹Üžû£NíÝOs1"í¯¹{#Ó—òÐjWïþVZ Ï4l–0†{ÏÅ™D_¶°êèåMùJ6ÐHŠWN†äçÚ\iv”|SãMÛ_}ñÏ€#çéÓÇš—gÜ^K50ö‘tm¯Â{G³‰öÛ{’Or˜Ž}P.¶!YüiüÓ>R?Nõ!̹è\_)N-Ìð’7î9œoqÂÉGÿ—润‹vÅñÔ—®Nç×…Û·îÂ{ ³ZÜÓ=?Õ‰óE«­ýŒ·¶÷ÕÖ–óGÔÍ㟴æçè=ÝÆS«û¿qݤ}‡åãŽpëNeKõ —ÃP'É÷¥—óöçOWåaýƒë¡}o•ƒ¿5„:!iëíÁd‹pmaÞ´tF¬˜È{i߃:j¹Aò )7Ð>ÍæfYÄÅ•”Q7:¦bdkC~Ò~”óuîyX”gù ^£×)î#_œëšÚ÷H^yñš“oá ·VNIï%¡Äù«g\›”s9}$ÙFiúr¿Y&ñåj`idá¾å§†i±ê±“¦+µ=WksÏëXø¦éÌa$âú"/Å7ÎÇÂ(-×IûB-v‘8Œ’®5³bíƒ>„|­8Ôöô\¬hØËùW‡pó r¹ù£¾Ú?Ú_Ó–Ã{i<7OÔ‹“ÅÍ­ý¥ûQÉ9]hÞâpš«©ÐæW oëÏ̓¾·~‹ž«QO_8F›3ö‘j Î’Îô:mÇÜ$a g'-N9ì“âV:סüÖÔâýIÒÑ£¿ÔG‹[©N•tçÖR‹-Úoý÷UÒ_Zc-WHx…ûkÜWÒØA¾\Í€:qížïxÒü–úŠÛœµkønØg®ss§ã8>öÒ÷t¿Á=‡¸!a¦fwOþš9ô5ú'ËÒ‡«uè¼ñž¿Xxµ¦öÝJܺâñzQÛóIõG»ÆÅƼ„ãZm3Á5ÚŽñ)żƃúbg+ÖÑŽœOaÌ!îHAÇKù‚ë+Õ T_)þ¸u•jUJÞﲓÖ1±Žå|ë*Œ§g²‡°Ÿ`\› çS’¿qñÍÍ›«q¹z•Ê@âbžÓ[G ƒ¨´ß¢˜˜>Òo Q=¤ïÓÑ|ýñ…«¸ë¯LmÁ£5Ö«Ðg0~¸9LП¾çüÃÚÿHú#_ÎŽxašÎïéu©l|hMÏ«`®A_¡ü¤X¦óÄxÄëT_¼†uŽãt¡üÐîÜþ‡›—•9µµç®q{m®®‘üUõæIÎ/¸vl“ê.ko#á#õA®?wÿypÏO®‰žÝîÀiÞÔNø·ço8 s9~œoq×iŸÆ“Þãábý‰bú.Þ›§|1–´8˜kèçRüÐyá~Jóu.×j¯¹ç÷®B_J¸7k}¸X±Îg,_àlÊ=‹‹²¸5ELAûI¶ÁñO)&ôK/ÎæØc’Ži÷m¸zrbú£Ýp.šè8ŒõöšÓ›ÊåüŸ«ûè|P_Š C¹}=‡ T? [ék´‡7tîôúUè;Me¶qÔŸ^ëVÝÆá37h3ºÁ³(œ ç¸öt.hoÄ_´+Û“ò—Oå#I¶Ã>ÓtÞR|Ð6¬k%œåæ*õ·ìÓdbŒ`,Jµ^×to6E_¦<¥ûÜ&!hDçˆXù•ú—KÑ–T6Ý?ìNçmÜÚ'2–¾§ça­1»µ¡L)Ss÷̨íðû‡Ð'¨ h_û¸~h_´!ú”vomÄa0çSTW)Ïb}%ùíú_û~ø¶¦-ß¶õÄ<„8Eu£:^1œŽtÜ9cö`ý0Mçqw—Ìk®½2÷ oQß« oœó<´­Ö„Ò¹‡%\ŠÏFJøKe`_*S«M%=h_|ÝüL«»è{ëqNÔ§Ðܽj[íÞ±Trûn¬†IW˜œ©L.h|h±*ÅW/Òv®ÆáôD¼§uçCÈïUr;£@{p6@{Q½Zæ±ÖÛããþ•ÚX’Ïù+ýÛx"Qÿår7‡éœ->í <©^í=bç4?Šwë¾ëµjßñÛd½6ýˆ­ˆ›’­Ðwq 9Œâæ<)ïGqÏ¢~´ÆÁyá=.¿µqt-Zô+ÊŸûìy#®nàæËõÕì†x±#­EÓã›»ïCåJ˜.õå®q<¤34ìŽz`ÞÅsN.‡MÓy»q¾.]Ÿ˜vª'?´…V«I˜Bç#í‰[ûU×ú¬éCy¢PGúwšÎÛú5¢Åºn-¶°Þ£>Ì݃D¿Aœçü‡®úü4ý³Ü3üv§‹q޶h23¨?Ðþ8?¬¯h¦±ÁùêÐæ³;·5ž)qµÍ-íÚzM<š~m½©©ž\¾@ü£r9,äòÆ·ÈWª(:?j›W Ã•W&Y'j{/¦éâhìp„ö¡s–êÄb\Ô“‹»†m¾®S^ȃbæs<¿C|šàºåKÆâ¾—«Û<¿0ÏH¾‰:âz!6Ðkt½q´¾—æÃÉåÖ×ý˜âžAÑ8ÁÕ×󱉴a¾¢1߯`<4Â}#êD÷\^ã| ±ªí蜗Ú|0Néßç¯M?>3òOÓùuâöæèóÔF˜÷(Z—O/d"!~#.bô‡Æk¬f3êë˜7h=ñÏÓy_§¼¨­qÎt]±ÖÄúa"íTíËa'ÖèRþ¢¯ƒ¦é"oäÏÅ5Ö/4Žwa<æ: Oé{ô?är%<áâ´ñàäÒXÆ5E]'¦Oû» ©Ïq¹ëU¦ ç8M×Ã/ÃéƒûN?+¯Lë.ԓÛi=ÜÚ[íú‡>„sCŸ£ÔÖ²½FÝÚ8Z'ÒØÆØÃ<έÑDþJ¹Ú‚ž1M0ž{¾»_ÄÅù4Ï8~ý÷ÕéGœ£ÏÒ5ÆùТø€sçð—¶qµ÷#.LÂ{Œ_Êcš.Ötœï´÷íà4ñëÊéÖÚ(_ÄßѯQ6ú]̘Sðo«±éZ¿FôÆzƒö¥±†µ*êŠygš.Η®áUèÏÙ†Æe³óÕé<>N0Žòk„÷)¨|Ê“Êl5ÆÎ4—‹v¡„˜Ìá;µ)òÇqè T¬%^…¾ë¹ýûÿþóêß$}®>Í_#¨nˆ›4?#Ñ1\ŽjxÖâ…ÚabÚû9¬Ã\EóúZ3Á8J¨ òçr·v\ ÷0'¢_IÏp±DmÄåJÎní:â"õqúL bêÁ7qñï±Fŵ£u"½‡GûKøIýwš.ú=Å`N¦„hG¬—<9AzMm1M÷›¸'Ãó1j'<ì‹×p<[Ógwº8?zނפ¸‘Ö•¶ÑýW¿Oðþ ´Q_§s§òwá/­I¸œ¾ü§éÇøhDÇJkƒsnrp^LÓù¹4MÓù«ÅUÛËýlú±Â=¾–öSô/Î…Ë;4)/Ü×Òµ£9ŸÃHNäóêtž?ú5b‡ P& ÛðœþãpèµéüºP»N0ñyÓÜÍí ¸X×r7Ž®õajcnmv }"í­â3ú>‡EWá:—ç¥=.Ú }uG~ˆ#\ÎáÆcžâæÆá5Ú‰êCåp9Q´]ò—ê…÷‰9Ÿ@}&2†Ú®}û+}þŒòi×¹øä°—âÀ.ü£v³úÞ_âæÚx·¿ Ô'©oM¤þ¥üiÜ¢R}§é¼N˜S)íÀ5®îkúpÿZžù'"‡Ö†»Óùß.à0}ïHþMç€×è9Æ ú2}9”Ο‹äGuB›bNÇ9ruÆ4שéÂíwp[~çâ‚ÃHº^QÛ¢ °m\×zbÆqøCyR´æ¤c±^âêÎ8ì¤~€{¤iºÈ_s¥½&â&ú·œí&f,úÚ׆‹Yinxßʦ÷ª8þ¨âåÕößœšC¨~xÇÑ÷R¼ÓyÒkæà>³uë'Å §Ór)_ÄWií&¸Fý±ûÓxäb…öÅ9MЧ®­†ïÎp˜ÂåF‰·ˆ·hKn^?\;:ïs±Ì­'‡ö•ðŒË[Ôfíî¸õäâÇÑë\ç{¸†8ªî}¸ØãäaŽálŽv™˜ñÒ™…tŽ€úáëiº(SŠn ^Çk¸nqzPûãz4ÜHªýÛˆžQáÜѯµx¤ý^›.êLqk‚þéÃÕž­ýÇå>©ŽòêGç„þ3Mϲñ™3<ǧþ¾Cúp±Ž1xúpþÂÍCÊ·hÒÚp1ƒºáÜׄ÷#¹5Çùp~Ž:ríÓt1hîŒI®‘øJxŽþ„²Ú\‘Ú ûJשÿhºsïQgN')†%Ûr2¯À_j#´9žq¾ˆqÌù4g·ÖÎå^úšâ7ú+òhzrxLy#¯ÖÆñB>»pòÁ3Òv‹%ç˜ß&èÏù ­¤û'í:Úw‚6Îo¹ó< 'íËÙ’³›VsQþÜG‹g Ï´¸§íœÿL~Š$ÕY\å-áô·õEý‘/§Êåüû"¦Ó±xåigûèCX#j¸Ku”öáx®%ÙB«%° õxpk ­òÃsl“ü–êÏp˜ÈÉ‘æ%ù•´.´m=î5rÃÖ ®SÌAÞøÜ-â· v¤|QOªG#ÎQÎDú¡]=úMð^Zw Ë´÷ØÎǽªôšÓ‰ówIIÊ^—ÎÛ{®^àêGŽ$,àôàü…ó.o ÎøL±ÄŸÓm-åoËϧé|,q±§E]¸8ÐúIëOek˜C_ã½InWIúqyqbúHçx”'ÚCZNç¿í5÷y"Ä ®æðè%áæΞܺKµ(mãöê\sº£,Ô}­ÍcwâךÚùHy\óO-ÿp¼¨.œí8%¾Ö{ÔÕCXËqëÃÙ…ú!wÊñÔöÏ~#áÙóÄüm:MÐN× ÏÐñŒKÂWi­¹÷k_kÞGë‹|¤s±ÖOÚ3pü´µ§ò8ûj„}$\“ð_søHýHº_GÇIçi\_ª«d+lC½¨Þ8?ŠÇ!®S8ŸÀzÏÔ¸³]#¹¹JØŒ±lá©Ö†ã%[Jc%¬ vi¹¸åôæø5âîIs¢üð5ò”ÆqçO¨/î×è½Ͼ ¯K±Ïù7Æ3.²Î’žZ^àâEÃgf([ò+)†P/꿜ÍRT|Mûr5¾6_mèXÉO¥õÍwœ4 Wµ9¬IºoÃÙ˜Ó‡òÔb–ëO¯{ð µyî ¾ }9INÛ¹= §Ç ñB:Ç”|JâI_Kkƒ¹ÆÚSã>ûI52ÕuõÄ£EÜ3([ª§‰·/æ\©¶Ú™Î¯!7_ëÕ×ŸÚ uôÄ¥ôëF¨;gîs^t¼Eœý9°üCÂxs%–|WÓÓAZi¼GN#i¯/õ—ôÒ°/¢&Óª1i†c$›âûH}!‘´Å>^Lçtôìi¬õãü™;{âò77No­ŽÇùÓqÚwº iñ'=—´#\Ã9xžÁv‹'Îßz-å¡ îùmN7i¿§Í_KÏÎJñ¤í…©¾4/J5„‡¤ùHø"ÕbV OLŒ% Ó¤5¢<½g9Ÿ E1]ó)Ï8mݤ~Üù'[³wÆÂTî:ŽÏ朓ÆOó!ä×^s¸Œ¥Ú»íO4_´Îx°%iß&ù––K¸½ òÅkßÔüÑòEÉæíµtö|¸yI{6ŠÛÔ—$¼°æÄÕø8ÔÊÇkÆRRl7þ8^Ã^‰§„3’–? <¼æ­y%²žgòðÓöO^\çdYþ¯½ÖÖ_Â;mÎ~Xó’â/2ŽÃH‹?¶iö“t²b@ÛKKõ‡Ukb¿Ièká¶£¼æ>wbr׬ë´ÝÚ‡qµ g;mΜI¶œ¦‹±%Õ«–|œ#'¿Éãü ç‹û2ª?÷,Ÿ$OÒŸƒ<=ØÄ½—ôâdFðY›—öI Ë$_ôê$µi¶ÉøµÕ§‘ôYGKô mÝ,ý¼vúKŸoÔb©ýÕâ_cãg¤ñ? ϸXçHÃ'”-á*¾æžßËb…4Î:£ôìMÖ_aúàx_NÓùï³Hª§¡éÑl§}OígéŒï­5ÕtÔæíÍOÞZ¼-~™{—–¾Z?nÆòóúWó4¿Îà=ë&=gãÅCާtÆÂõ—ÖŽê†ØÏÙƒ’ç+ÊäÚ-¬ÔH³½'nPŽõä0É'<û7I~†$½0'xýX‹kË>Ú½s齯³½÷ø3ömï¥3^K¾´–]Qw|ïÅ7.½9‹9Hž=a$†=þAßGìšÁ¯]аtœ†MˆÍÚ}a8ž(“Ó£ý»)ßõ¿«L;÷9Un}µVjãbÏâ£ëü¼Xfá…—´{gžxo¯­¼ÀµsýÑÎQ¼ä®q¾Ëݳ‰ØM#ïz{Ú½q6‡îZ³Î¸1oéºv~®Ù"rFíÁl/I¸­ÉñžƒzH«¹véLÉÃ[²­µf\—·¹ïPãdcÓ°Úš¿–{­½Œû™œ< =û8I'¯ÕŸÊçleñ•òåËÉxP’ö´MËçš-=¹œ#m~Ïy4wFHÿ¡ŸX÷K<ë§µ¡ ½¸kùp…íµqžvϽ&ɇzs”ER¬®_sß%&é—yÀÛÎ]×θ#Äõ®?®¾–~Còu=ß«¦éÊŘÔߛù¾qúdÇc»–k,>‘uF™=ñJùà˜èÚeÈk'ÍϼxÀÕ%˜«q|ë£õóRd="ï5žÞ=¥'§Zí½<1âÍ£¸Ž‘1HÑ{ÐÖñ¦7^{ŽÆÂǨ½9’puŽìSé8‹¤<#á®us#ñcQD¾4ÖŠ¡FÜÙcôŒhÝWú5”cñ¡¹kÒ{ï5/yž‘Åvï&£Ÿ”;µ|êÕAÛçGó¢ô^#­ÎÈðˆ`„×4ì‘Ö"³ïæäYã%LãtÒäHzpm‘û2Ò™ 7Ž;çpÉë#˜o¸ñYŸ±¾óCjËä«­‘tJº®ÉŒ¬-76kcçëZÆæ‘>ÜótŒt¯/³ð`'§‡wŽž:–’öÜG-²¾ç6ŠÛyÎéûèºY¸já{ä^w=ëß.Hkì±{Ã)i÷Yð½?9ûÓ×Ñ3@´Q/þYX̵epŽó-´‹„oÈ;¢«ÖÛ1$ŸÒ°Ð3‡²Ö€ÊõÜWöòò´·k\ªñ¢×¥Üf­ŸÇ75ŸÄ³çu<ùÅËOÃ+oLX|{Ρ½ºS½µ˜Òüųw–j&Êד±/ž yî5[>ì™—Ó$²Ö±Ç_$þŽÈêÕ±±ênL$ιïÅB,Òîé{|ÉsU"/Frã,½¸°ðI{£åîÜQ‹)-V¬|eµ!?©¿‡_fí2ë¦õõ>Ë@ûzÏþ5¹ÙyxÆHµ½¦Õ e|É“«ñLuÕøc—÷´>œž/OÍñåâWúŽø¨ÏDâHÂ?Ú®}Ž<ªö·ÆZ~ç‘]ù,¥fË,ŸÞq¨‡gŸê½.­•çÙ=I?/i1Ê]ó¬³w>)ý4œòÔš<ÔQÓ‹ë#µyúhÏRry0ól¢7ïrkyî š³¹Ü¼¼ë¡É£ÔsvhéÔ“ ‡ÐÆFó¼·¯õ9ò‰<ƒ åGîºÖ¯‚¢ºVñƒ"çá^?·p=ó,Ф„9Úy©%Ǫy²:{ãÊÊmquk„¸Ø“ødy{s9Žáþjü8>–n#(ZJ˜×«£•Ç«ê%¯|nݬø³žYñÆOÖ–^=3Tñl„·Ÿ·¿÷ù`K^eó<®½4/éùĨoKŸQ¤~ÌÍC›[o}á5iŒ4Nš»%#›S¥þ‘³T©†Ç^ŠæÌ^,ª—­,]¢6ˆà’Ͻu”w#6ò>ï\!+ÊÈßÓ~VJ¸§ñÔxEÆôò§ãðþ:òôÌÉò[+GÐ>Z®öÄGE}„y³•$7›Ó35htm¬œ­¬>Öšzô°â#[ÃUÖš’>èãyïs|¸öP¯¢ë8‚zãldŸHަäÉ5²âÝ#ŸŽ“t±ÎÃ<ÏŽeÉSC!~Gòwk¯¾7 ‘õLš7ßkØá£]÷òÒÆgI[ç‘á!ë™@Ižç³Z}y¾ëãÍ‘ÜéµEëŸY³9òÊì©á"¼½|³ç 5biµ³†ñܹU¦Nµ®KñªÅD»¤s:OÔ¾_)B#Æj>áO׌{ÞÜâÙ/D÷ºÕ±%åpÏà3M^ß·úhzjºUåËϼ㣵®§Þ«~VËEÚÚecΪI¥÷™ú•ÒÚn‘{"^]¼ŸýäàµH,TáõnŒ&wD}àñ•žš%Ú?ÂO['î>p7¢úpc#¶³¾ÏÉ’eµ{^Gek¸á“é7'yãÑÂ}J‘Å{ÿ BÑgr+ûFȪٰ֑l„ßÓŽ×=zhü[íæ¡ÌgW=ØÌÕ5\ã­½:Jï›,íúܤÕdR ¥ñ²ê7_´ÖòŒ«Ê¡QYÚó–ÞMâí‰ÿ?‰—÷š…I¾^òú¤uÝŠMO-è‘íå£Õٺ““½ã´v‰¯Çf#bWjëy>/j«¾´Ö¡*'I:U]‹Ê®ä5'Yþå}VŸ»æÙ [¾µIµ ¥ZrkE)#_ª%«eG®k¸Ñóš¶õ®UÆ÷£|GÔÕT™Ó®0¯­1ZNò^«ð…Þqk›ÙcõÆz¦¶âøUc{DvTL­æãÉžºš»9wŠÚÏ[‹{Û£Ôã7ÜÜÑ^ÑïM@Þ–M´ü'áú{ã/ò Ië/QD§¨lnN‘=Œwoáy~_[}%},ž|ÑøTç;K.×··«¬}8ŠÔš}ïmåKoÌj}-}v”kUà‘FÖçü³þ:_8,«¨ÛGÌ%âOY™ÙzËêS9ßQäÑ{y¥WŽ7—Wɯ–1‚¬ZxdD}(»7°Ú¸vo“xõ¬±'ÿhíÖxé3ð_wkÏ~Ö0ÓVõ¹®l®ï­${yäVãGE½#­¯§ö§Ôû]–>ž~=6¶> ÕËy¨!«|À{'wÑg‚¢6‰~dz‡¨m8y;Â?M'IúIû]•g}W þ^¡'xô–Þ[c²µ^ËÆT”<¹VòÇÏ+j©LŸ©½3¼zuék=£êͯ=Ø5—ý8^žšÖ³Þ£âÛs>¦ñöÔÍÞÏÉyëÒªìé[7U¹ SëzõÏøOÏ÷ŒdäZå§é±­|Ðd{çäÙ+XsóÌu®ïcÈ'·ò¹rÄ‚^ÿ“Ö`T¬"ÿ ï;Ïé7˜ñ5®M4oyò]$Æ,ò|-JV ¦õÑÆÐq†{ý*2_§Tx÷UñÍm½¹pi”­O#µñlìY·Œnõ¤÷ZöœÙSc÷ä¼lÜ÷ö‹•/-=¬ÏíFëµõ?ϳQë4M±ïùÏð§ý£µˆ¶&œÞQ{÷Pœˆ¢±Ô«K%ï옞>’/p¾aý7Þâ©é±W¦6P¯ÿö`—ć{ïÕ«"ö½±Âí!¬üìÍß8뻀,²ösa§'ö*åeøEj6Ϻg}9J‘ú®Š,ìlò‘2µž÷û£2*ÉÒ ±£JF´OO²l\Þ1’/nË'4Ûxü×s=²o‰ÔÙ<±u•?Gq®:ÏIµÐ¶)û}¹È#2VùHílɑڪ¨×Ÿ{cÈê7b]=|%,²êhÍÌ]S½õІÓQ~=zDIÚ#H¸&­wdm-òîKz)cÞüX…W;“¼žž±Qþ‘ß/òêßS³aî‰Ì§Êo=ò¢˜à­'{}nDœUðŒÆ[¤6æd ŽEs€ÆÛ’½¦žïfaïÈþ#óÝ–|K·,Eô‘âLó,롹â8ƒcÙ|N×*>â½6JV»Þ;¯lNåÆY±^‘çzÇUä¿êuî?:¶=y”ËWsÆI„‡µïŒê!ÍŽÑ\gÅTðw'"cGP4n%ßœ3ïjDõˆ|µ;‘º·ÊW4œŒ~n7R£oƒªsÖèçm<÷=¢û!麵'ðÈjšÊ:E’˽ÎÈÊÚÛZskœ§¾‰Î)Ã#‹_sÄ|¥Œh¼Js¯Ú›Tçÿß“hßÐSK{rbO]4º†¬¦ŠÜÐ#¯çùí3¨Z®áújäÅ;IŸh¾“â3£gE>¨¢h™oöslÛö¯ «öèÕ±×½u\DŸJþÖÜ"ù,ƒAYŸñPEMé±±«^̪š«vMZ‹‘¹w ¸»d¹Û®—·I=˜R=X©ñÈø}Å~U‹oîŒnIµS…®¾²Ö«bŸÖ›_22=ý<û_iŒG~åïަžøª¦&¯ò{´«r휶ðÆf•NsÆi%Uä©(¯Þ½—µŸ« ϳÜ^=´ë•öߟ*»¢ã¸ÜìñŠzon\Ëø=WÇE0«wSEÙ¼ìÝëfuðú[FŽå5i¯¹xmµ2Êööï•Å­-Wóir³zDj¦ŠÜ¨õÍŽ Yš{ïBåE>ÐHòwš¯9{Æ É‡25~ï^Vºfa~U­ÑkëèøÈï&÷èÞûû–â°¶’¼˜§a×úuö»Ãµ>sû5>Z§Ò÷^UP¤æÊÄCVíºÔó…©<Ôó9oÿŠý ¶-ý;`«hä>.½¹¾G^tL%.J<=ß)nái&pûÔ±ëzö"ÙOË+=ØÒ“w­Üƒmžï¦çøTÕ}3|GÒÒ0¥ZÞè}¯öm¹™¯ mø'3³W÷ò¶ê‘4zŸ¥ÉÕÚ/½5µÕ®õ«¶†éšÍ=:ØTàÒ?ŠêŸù^ù Y5ÈO<µA´¶óø”UõÔȽc2{Ï ]¬ñ=õ+¾ÏÔ#Uy¬»#ûK®£{(‹sëU1nŽXi—¹ê¤mïu¢Øbý¦÷Þ[㌨s¼|²²{ϸ×kꉟž:e›{ƒ9b![x‹°G‡¬xô™ã·d¥~h³h â%MçÞz`„~]ªeTÈ÷®[oáAûFý*òÝ'Ú8Žzëâ5Z–GÕÞªgœ¶/Û“ÒW“ãÙsxøôR$.¼úYØÖ›{²±,é%Ų'ß i>Ð[?õŒ™ƒ¢þ«}_-öÙ&Í•#GÅ$£sUOX|GaaUáï‘gÙ|Äþ!j—9ÖÊ"ÔÙûí‘ëÙ¾~ZîòèQQ'gø{0>BUû9KÆHz׈êPñ{bÒžFÚ·jµ“·–µt©îëå׋u=²{øUî•GÈñ¶EÉ㯕ò$ÞÿQy¡ýÍždìÒ;ߥî[-Q¿¨NôJt¬ç7 ¤qÑ<ãå]‘+µq\Kóñè9c=vË<³™«Ö•W™KçÀÞ ßž\Ø‹¥VííñÙˆ®KÃÏQ¹_â9W}UÅ_Ò¿×nÕu–Ƴ÷=}Ov¿¡ê5ˆîq¤ö{à Ÿ¯ŠsOÏxîw%\Ûž æˆó‘Q5f†ÅXkßÙÚ²Ÿw‰êB_[¾Y—ž½yÅø¬¼È¹Àˆ}Z¤ÞÂ1sî½Xã;'Gúw-¥xŽÎ#º§Í|Wìœ5[ÕÚ Ÿès}’m£v™«NËúyÔ"ò³}GÔ†RåúôÊöäÎ 9=Ï&VQU]݃ÜÚâ:·g3{¯Q˜TÍoDG|¹šæÚ#6VîÍìÅ¢×zó$Çûý·Ú{K‡ ýz×Ú¯}o–g„"õ{V—lÝáÁù¥7>ªö(wDþÞöiTå?Ñš-:ߪõ¨&/®Î×£iiòzða©5ØHûnâ›Ñgî³%’f—LnÙYªµ¼u˜WfeiLU½Ø3wK~fëáÛK\~ªXGm¾YÌãé»ÓFÊ®ðç9b1ËSï¨_Œðo¯œ¹žQÅÞö沞þ~RnÈÈš«V‰âr†gïü2X‘]é«=ºnƒ¢øÛÃ/šGå±(U×{š « ¯WÄQdl¶Två~oŽõ³(£®oG瘷WOÍg=óÕäfÞW‘5¯%'ÏyíÍ™süælf/õ7<éú6ü`)øPEsÆØy2óÝ9ZÞ™Ó?£µŒ•C¤qÖøê}_Ïø*û:«˜‹*üœëÛkß^_©´sÕÞw‰T=—Þó4 ‡zÖ ‹G^ªä‘¥ÍËÒÞ`t>ŠâNvï:jm§õY$mÍæzþº‡Ï\¾á‘¿>¯%œuPù£ëÎ¥ïFðÉä· ÖeÎizs¢—ßœu:í¿í¸¢„Ï|ŒÐÍû\Éœqˆü­ý`µnKñk^£Ï/zp|)6´¨gŽÚïüFyYä=;ÉêâÑuŽÏÂWМ{%”Ë½Ž¶EeEùôìµé{Ëÿ3ò¬¾™ßè]J~ÈüvWškvÏœåSA‘½K¯Œª~V_nNÛÈ×ÙºÛÝ,57y)ºŸó\‹ö—~“ r?¿í<Í‘7¯USÅž·jO@Û<9·ú÷©ÙsÍ×*ñyÔþÜŠ•‘û¿ŒíæŽåm`‡uŽ^¡ÓÎÄóª²{eýZÉ_ã±ä|ÞûÛ=Ù±‹ø‘GŸ±ï­g22Ökƒù<3‡ê3ù|,;z}¥gÏìù¬ó¶Îg4’rxÔ‘zÁKUg=ÛÀÔ¹ðpô\*u‰®CÅ~o„_fiÄÙˆ5&ËkýþZÏ9ÚœµÁ¶øŽÞ£,!oT¬cOÌWŽÑøpk9VY4çÃ6ÈÒgiºFúEöQQŠœqhzK}¹3´Qg'#öܼ3÷ë*È»–ž9/©õÈ¡C… 2q.±~ÿvnŒÌÔ=]«ööò®×\çDÿÈÔ³©àÕK½2³ço£p+ãß#÷Z’Ž–žÿÈñX}†·„Üíc1Om_9zo·íÚ(Ãc„ΣîåeûÀ)nÝGŸÁE÷ѺÑÚ=ÉÊø­ôͨOfeGöò—…zÖ$º·X¿Ïà‡§™ƒ$[-57ŒàÕó “¹k^žK±ÅTU_ôæ/Oûh½î=þ·«\óò—rÓÜ¿:£´}<ñ0Z¿Ñ{Ïì~Ìë÷#ê·LŸÖoÄ^:sÞš‘3'--îªý§bÍFúôe¡Þ³Ñ(æŒÞÓGú¤¹}k®<6÷ÙWeÏTæðÕjª>ïíáQ}žë=Ÿ“|µ"4w]¹”šii{ÒmQï9_v/ºd;WíW²wm=ú SãFåVå¥jUDñÄÛ¿G–Ô–É—½²GаoY>RµŸ_^ž#~óÚcInä»y4æ&ÏœGગÏ;iûIÚ‰LŽ[¢O¬iIº¬©›¬µí©Uæ"¯o¢o{ÇX1¿„ýØ´´3¼*Zzí3âLinÏWužW…CžxŽRv.™}}¯/Ðó—9êK”ïmÏöë¡j|[Âb)¼æ¦HŒ/ažÕ:hŸEâß\±·:+s®é¡Ê߃Ëô™³&Ñr}fO½4º úÍ]ëõòÑ|£÷¼T?çg¸©æ;¢Ϫz?£ËÒã4BK¨‹·µßïÅ3n:õê<·ÌQ䎥Ÿ»hr²ydäœGå›9È[#fæU]cxe\F²ì\U[õ¬IïÞÌÛ÷§²¦¶9Ÿ‘ùmDŽ™«fž³6÷öûsÝÀ 횇·ÇFÖ=|ß‹ŸHUë8çYÒølCÞÒrÍæ6¢žµxnë|ˆk¯¨u·}Oii~­‘ÇîKˆ nüˆß½Íè1§ÜÔ{~iáËœgSÛ®-ç–×kÛŠûTKöó%ë&‘v<"×i|¬séÈ~‚ãÕ³o}®Øãû™ñÑ{‘þÛ¼gâÝ â{ תϽz¨'–4͵WÐ>'^MsÝ“ÑüÞSCY×¢úD© kªög•5ef_‘[éÏ^âµ¥kJ4'¶y~ÕKÛæÃáÆ6ö@saЬôÿ,á«æphotutils-0.7.2/photutils/datasets/load.py0000644000214200020070000002175113563423715023111 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for loading example datasets, from both within photutils and remote servers. """ from urllib.error import HTTPError, URLError from astropy.io import fits from astropy.table import Table from astropy.utils.data import download_file, get_pkg_data_filename __all__ = ['get_path', 'load_spitzer_image', 'load_spitzer_catalog', 'load_irac_psf', 'load_fermi_image', 'load_star_image', 'load_simulated_hst_star_image'] def get_path(filename, location='local', cache=True, show_progress=False): """ Get path (location on your disk) for a given file. Parameters ---------- filename : str File name in the local or remote data folder. location : {'local', 'remote', 'photutils-datasets'} File location. ``'local'`` means bundled with ``photutils``. ``'remote'`` means the astropy data server (or the photutils-datasets repo as a backup) or the Astropy cache on your machine. ``'photutils-datasets'`` means the photutils-datasets repo or the Astropy cache on your machine. cache : bool, optional Whether to cache the contents of remote URLs. Default is `True`. show_progress : bool, optional Whether to display a progress bar during the download (default is `False`). Returns ------- path : str Path (location on your disk) of the file. Examples -------- >>> from astropy.io import fits >>> from photutils import datasets >>> hdulist = fits.open(datasets.get_path('fermi_counts.fits.gz')) """ datasets_url = ('https://github.com/astropy/photutils-datasets/raw/' 'master/data/{0}'.format(filename)) if location == 'local': path = get_pkg_data_filename('data/' + filename) elif location == 'remote': # pragma: no cover try: url = 'https://data.astropy.org/photometry/{0}'.format(filename) path = download_file(url, cache=cache, show_progress=show_progress) except (URLError, HTTPError): # timeout or not found path = download_file(datasets_url, cache=cache, show_progress=show_progress) elif location == 'photutils-datasets': # pragma: no cover path = download_file(datasets_url, cache=cache, show_progress=show_progress) else: raise ValueError('Invalid location: {0}'.format(location)) return path def load_spitzer_image(show_progress=False): # pragma: no cover """ Load a 4.5 micron Spitzer image. The catalog for this image is returned by :func:`load_spitzer_catalog`. Parameters ---------- show_progress : bool, optional Whether to display a progress bar during the download (default is `False`). Returns ------- hdu : `~astropy.io.fits.ImageHDU` The 4.5 micron Spitzer image in a FITS image HDU. See Also -------- load_spitzer_catalog Examples -------- .. plot:: :include-source: from photutils import datasets hdu = datasets.load_spitzer_image() plt.imshow(hdu.data, origin='lower', vmax=50) """ path = get_path('spitzer_example_image.fits', location='remote', show_progress=show_progress) hdu = fits.open(path)[0] return hdu def load_spitzer_catalog(show_progress=False): # pragma: no cover """ Load a 4.5 micron Spitzer catalog. The image from which this catalog was derived is returned by :func:`load_spitzer_image`. Parameters ---------- show_progress : bool, optional Whether to display a progress bar during the download (default is `False`). Returns ------- catalog : `~astropy.table.Table` The catalog of sources. See Also -------- load_spitzer_image Examples -------- .. plot:: :include-source: from photutils import datasets catalog = datasets.load_spitzer_catalog() plt.scatter(catalog['l'], catalog['b']) plt.xlabel('Galactic l') plt.ylabel('Galactic b') plt.xlim(18.39, 18.05) plt.ylim(0.13, 0.30) """ path = get_path('spitzer_example_catalog.xml', location='remote', show_progress=show_progress) table = Table.read(path) return table def load_irac_psf(channel, show_progress=False): # pragma: no cover """ Load a Spitzer IRAC PSF image. Parameters ---------- channel : int (1-4) The IRAC channel number: * Channel 1: 3.6 microns * Channel 2: 4.5 microns * Channel 3: 5.8 microns * Channel 4: 8.0 microns show_progress : bool, optional Whether to display a progress bar during the download (default is `False`). Returns ------- hdu : `~astropy.io.fits.ImageHDU` The IRAC PSF in a FITS image HDU. Examples -------- .. plot:: :include-source: from astropy.visualization import LogStretch, ImageNormalize from photutils.datasets import load_irac_psf hdu1 = load_irac_psf(1) hdu2 = load_irac_psf(2) hdu3 = load_irac_psf(3) hdu4 = load_irac_psf(4) norm = ImageNormalize(hdu1.data, stretch=LogStretch()) fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2) ax1.imshow(hdu1.data, origin='lower', interpolation='nearest', norm=norm) ax1.set_title('IRAC Ch1 PSF') ax2.imshow(hdu2.data, origin='lower', interpolation='nearest', norm=norm) ax2.set_title('IRAC Ch2 PSF') ax3.imshow(hdu3.data, origin='lower', interpolation='nearest', norm=norm) ax3.set_title('IRAC Ch3 PSF') ax4.imshow(hdu4.data, origin='lower', interpolation='nearest', norm=norm) ax4.set_title('IRAC Ch4 PSF') plt.tight_layout() plt.show() """ channel = int(channel) if channel < 1 or channel > 4: raise ValueError('channel must be 1, 2, 3, or 4') filepath = 'irac_ch{0}_flight.fits'.format(channel) path = get_path(filepath, location='remote', show_progress=show_progress) hdu = fits.open(path)[0] return hdu def load_fermi_image(show_progress=False): """ Load a Fermi counts image for the Galactic center region. Parameters ---------- show_progress : bool, optional Whether to display a progress bar during the download (default is `False`). Returns ------- hdu : `~astropy.io.fits.ImageHDU` A FITS image HDU. Examples -------- .. plot:: :include-source: from photutils import datasets hdu = datasets.load_fermi_image() plt.imshow(hdu.data, vmax=10, origin='lower', interpolation='nearest') """ path = get_path('fermi_counts.fits.gz', location='local', show_progress=show_progress) hdu = fits.open(path)[1] return hdu def load_star_image(show_progress=False): # pragma: no cover """ Load an optical image of stars. This is an image of M67 from photographic data obtained as part of the National Geographic Society - Palomar Observatory Sky Survey (NGS-POSS). The image was digitized from the POSS-I Red plates as part of the Digitized Sky Survey produced at the Space Telescope Science Institute. Parameters ---------- show_progress : bool, optional Whether to display a progress bar during the download (default is `False`). Returns ------- hdu : `~astropy.io.fits.ImageHDU` The M67 image in a FITS image HDU. Examples -------- .. plot:: :include-source: from photutils import datasets hdu = datasets.load_star_image() plt.imshow(hdu.data, origin='lower', interpolation='nearest') """ path = get_path('M6707HH.fits', location='remote', show_progress=show_progress) hdu = fits.open(path)[0] return hdu def load_simulated_hst_star_image(show_progress=False): # pragma: no cover """ Load a simulated HST WFC3/IR F160W image of stars. The simulated image does not contain any background or noise. Parameters ---------- show_progress : bool, optional Whether to display a progress bar during the download (default is `False`). Returns ------- hdu : `~astropy.io.fits.ImageHDU` A FITS image HDU containing the simulated HST star image. Examples -------- .. plot:: :include-source: from photutils import datasets hdu = datasets.load_simulated_hst_star_image() plt.imshow(hdu.data, origin='lower', interpolation='nearest') """ path = get_path('hst_wfc3ir_f160w_simulated_starfield.fits', location='photutils-datasets', show_progress=show_progress) hdu = fits.open(path)[0] return hdu photutils-0.7.2/photutils/datasets/make.py0000644000214200020070000010047713572576136023120 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for making example datasets for examples and tests. """ from collections import OrderedDict from astropy import coordinates as coord from astropy.convolution import discretize_model from astropy.io import fits from astropy.modeling import models from astropy.table import Table import astropy.units as u from astropy.utils.decorators import deprecated_renamed_argument from astropy.version import version as astropy_version from astropy.wcs import WCS import numpy as np from ..psf import IntegratedGaussianPRF from ..utils import check_random_state __all__ = ['apply_poisson_noise', 'make_noise_image', 'make_random_models_table', 'make_random_gaussians_table', 'make_model_sources_image', 'make_gaussian_sources_image', 'make_4gaussians_image', 'make_100gaussians_image', 'make_wcs', 'make_gwcs', 'make_imagehdu', 'make_gaussian_prf_sources_image'] __doctest_requires__ = {('make_gwcs'): ['gwcs']} def apply_poisson_noise(data, random_state=None): """ Apply Poisson noise to an array, where the value of each element in the input array represents the expected number of counts. Each pixel in the output array is generated by drawing a random sample from a Poisson distribution whose expectation value is given by the pixel value in the input array. Parameters ---------- data : array-like The array on which to apply Poisson noise. Every pixel in the array must have a positive value (i.e. counts). random_state : int or `~numpy.random.mtrand.RandomState`, optional Pseudo-random number generator state used for random sampling. Returns ------- result : `~numpy.ndarray` The data array after applying Poisson noise. See Also -------- make_noise_image Examples -------- .. plot:: :include-source: from photutils.datasets import make_4gaussians_image from photutils.datasets import apply_poisson_noise data1 = make_4gaussians_image(noise=False) data2 = apply_poisson_noise(data1, random_state=12345) # plot the images import matplotlib.pyplot as plt fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 8)) ax1.imshow(data1, origin='lower', interpolation='nearest') ax1.set_title('Original image') ax2.imshow(data2, origin='lower', interpolation='nearest') ax2.set_title('Original image with Poisson noise applied') """ data = np.asanyarray(data) if np.any(data < 0): raise ValueError('data must not contain any negative values') prng = check_random_state(random_state) return prng.poisson(data) @deprecated_renamed_argument('type', 'distribution', 0.7) def make_noise_image(shape, distribution='gaussian', mean=None, stddev=None, random_state=None): """ Make a noise image containing Gaussian or Poisson noise. Parameters ---------- shape : 2-tuple of int The shape of the output 2D image. distribution : {'gaussian', 'poisson'} The distribution used to generate the random noise: * ``'gaussian'``: Gaussian distributed noise. * ``'poisson'``: Poisson distributed noise. mean : float The mean of the random distribution. Required for both Gaussian and Poisson noise. The default is 0. stddev : float, optional The standard deviation of the Gaussian noise to add to the output image. Required for Gaussian noise and ignored for Poisson noise (the variance of the Poisson distribution is equal to its mean). random_state : int or `~numpy.random.mtrand.RandomState`, optional Pseudo-random number generator state used for random sampling. Separate function calls with the same noise parameters and ``random_state`` will generate the identical noise image. Returns ------- image : 2D `~numpy.ndarray` Image containing random noise. See Also -------- apply_poisson_noise Examples -------- .. plot:: :include-source: # make Gaussian and Poisson noise images from photutils.datasets import make_noise_image shape = (100, 100) image1 = make_noise_image(shape, distribution='gaussian', mean=0., stddev=5.) image2 = make_noise_image(shape, distribution='poisson', mean=5.) # plot the images import matplotlib.pyplot as plt fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4)) ax1.imshow(image1, origin='lower', interpolation='nearest') ax1.set_title('Gaussian noise ($\\mu=0$, $\\sigma=5.$)') ax2.imshow(image2, origin='lower', interpolation='nearest') ax2.set_title('Poisson noise ($\\mu=5$)') """ if mean is None: raise ValueError('"mean" must be input') prng = check_random_state(random_state) if distribution == 'gaussian': if stddev is None: raise ValueError('"stddev" must be input for Gaussian noise') image = prng.normal(loc=mean, scale=stddev, size=shape) elif distribution == 'poisson': image = prng.poisson(lam=mean, size=shape) else: raise ValueError('Invalid distribution: {0}. Use either "gaussian" ' 'or "poisson".'.format(distribution)) return image def make_random_models_table(n_sources, param_ranges, random_state=None): """ Make a `~astropy.table.Table` containing randomly generated parameters for an Astropy model to simulate a set of sources. Each row of the table corresponds to a source whose parameters are defined by the column names. The parameters are drawn from a uniform distribution over the specified input ranges. The output table can be input into :func:`make_model_sources_image` to create an image containing the model sources. Parameters ---------- n_sources : float The number of random model sources to generate. param_ranges : dict The lower and upper boundaries for each of the model parameters as a `dict` mapping the parameter name to its ``(lower, upper)`` bounds. random_state : int or `~numpy.random.mtrand.RandomState`, optional Pseudo-random number generator state used for random sampling. Returns ------- table : `~astropy.table.Table` A table of parameters for the randomly generated sources. Each row of the table corresponds to a source whose model parameters are defined by the column names. The column names will be the keys of the dictionary ``param_ranges``. See Also -------- make_random_gaussians_table, make_model_sources_image Notes ----- To generate identical parameter values from separate function calls, ``param_ranges`` must be input as an `~collections.OrderedDict` with the same parameter ranges and ``random_state`` must be the same. Examples -------- >>> from collections import OrderedDict >>> from photutils.datasets import make_random_models_table >>> n_sources = 5 >>> param_ranges = [('amplitude', [500, 1000]), ... ('x_mean', [0, 500]), ... ('y_mean', [0, 300]), ... ('x_stddev', [1, 5]), ... ('y_stddev', [1, 5]), ... ('theta', [0, np.pi])] >>> param_ranges = OrderedDict(param_ranges) >>> sources = make_random_models_table(n_sources, param_ranges, ... random_state=12345) >>> for col in sources.colnames: ... sources[col].info.format = '%.8g' # for consistent table output >>> print(sources) amplitude x_mean y_mean x_stddev y_stddev theta --------- --------- --------- --------- --------- ---------- 964.80805 297.77235 224.31444 3.6256447 3.5699013 2.2923859 658.18778 482.25726 288.39202 4.2392502 3.8698145 3.1227889 591.95941 326.58855 2.5164894 4.4887037 2.870396 2.1264615 602.28014 374.45332 31.933313 4.8585904 2.3023387 2.4844422 783.86251 326.78494 89.611114 3.8947414 2.7585784 0.53694298 """ prng = check_random_state(random_state) sources = Table() for param_name, (lower, upper) in param_ranges.items(): # Generate a column for every item in param_ranges, even if it # is not in the model (e.g. flux). However, such columns will # be ignored when rendering the image. sources[param_name] = prng.uniform(lower, upper, n_sources) return sources def make_random_gaussians_table(n_sources, param_ranges, random_state=None): """ Make a `~astropy.table.Table` containing randomly generated parameters for 2D Gaussian sources. Each row of the table corresponds to a Gaussian source whose parameters are defined by the column names. The parameters are drawn from a uniform distribution over the specified input ranges. The output table can be input into :func:`make_gaussian_sources_image` to create an image containing the 2D Gaussian sources. Parameters ---------- n_sources : float The number of random Gaussian sources to generate. param_ranges : dict The lower and upper boundaries for each of the `~astropy.modeling.functional_models.Gaussian2D` parameters as a `dict` mapping the parameter name to its ``(lower, upper)`` bounds. The dictionary keys must be valid `~astropy.modeling.functional_models.Gaussian2D` parameter names or ``'flux'``. If ``'flux'`` is specified, but not ``'amplitude'`` then the 2D Gaussian amplitudes will be calculated and placed in the output table. If both ``'flux'`` and ``'amplitude'`` are specified, then ``'flux'`` will be ignored. Model parameters not defined in ``param_ranges`` will be set to the default value. random_state : int or `~numpy.random.mtrand.RandomState`, optional Pseudo-random number generator state used for random sampling. Returns ------- table : `~astropy.table.Table` A table of parameters for the randomly generated Gaussian sources. Each row of the table corresponds to a Gaussian source whose parameters are defined by the column names. See Also -------- make_random_models_table, make_gaussian_sources_image Notes ----- To generate identical parameter values from separate function calls, ``param_ranges`` must be input as an `~collections.OrderedDict` with the same parameter ranges and ``random_state`` must be the same. Examples -------- >>> from collections import OrderedDict >>> from photutils.datasets import make_random_gaussians_table >>> n_sources = 5 >>> param_ranges = [('amplitude', [500, 1000]), ... ('x_mean', [0, 500]), ... ('y_mean', [0, 300]), ... ('x_stddev', [1, 5]), ... ('y_stddev', [1, 5]), ... ('theta', [0, np.pi])] >>> param_ranges = OrderedDict(param_ranges) >>> sources = make_random_gaussians_table(n_sources, param_ranges, ... random_state=12345) >>> for col in sources.colnames: ... sources[col].info.format = '%.8g' # for consistent table output >>> print(sources) amplitude x_mean y_mean x_stddev y_stddev theta --------- --------- --------- --------- --------- ---------- 964.80805 297.77235 224.31444 3.6256447 3.5699013 2.2923859 658.18778 482.25726 288.39202 4.2392502 3.8698145 3.1227889 591.95941 326.58855 2.5164894 4.4887037 2.870396 2.1264615 602.28014 374.45332 31.933313 4.8585904 2.3023387 2.4844422 783.86251 326.78494 89.611114 3.8947414 2.7585784 0.53694298 To specifying the flux range instead of the amplitude range: >>> param_ranges = [('flux', [500, 1000]), ... ('x_mean', [0, 500]), ... ('y_mean', [0, 300]), ... ('x_stddev', [1, 5]), ... ('y_stddev', [1, 5]), ... ('theta', [0, np.pi])] >>> param_ranges = OrderedDict(param_ranges) >>> sources = make_random_gaussians_table(n_sources, param_ranges, ... random_state=12345) >>> for col in sources.colnames: ... sources[col].info.format = '%.8g' # for consistent table output >>> print(sources) flux x_mean y_mean x_stddev y_stddev theta amplitude --------- --------- --------- --------- --------- ---------- --------- 964.80805 297.77235 224.31444 3.6256447 3.5699013 2.2923859 11.863685 658.18778 482.25726 288.39202 4.2392502 3.8698145 3.1227889 6.3854388 591.95941 326.58855 2.5164894 4.4887037 2.870396 2.1264615 7.3122209 602.28014 374.45332 31.933313 4.8585904 2.3023387 2.4844422 8.5691781 783.86251 326.78494 89.611114 3.8947414 2.7585784 0.53694298 11.611707 Note that in this case the output table contains both a flux and amplitude column. The flux column will be ignored when generating an image of the models using :func:`make_gaussian_sources_image`. """ sources = make_random_models_table(n_sources, param_ranges, random_state=random_state) # convert Gaussian2D flux to amplitude if 'flux' in param_ranges and 'amplitude' not in param_ranges: model = models.Gaussian2D(x_stddev=1, y_stddev=1) if 'x_stddev' in sources.colnames: xstd = sources['x_stddev'] else: xstd = model.x_stddev.value # default if 'y_stddev' in sources.colnames: ystd = sources['y_stddev'] else: ystd = model.y_stddev.value # default sources = sources.copy() sources['amplitude'] = sources['flux'] / (2. * np.pi * xstd * ystd) return sources def make_model_sources_image(shape, model, source_table, oversample=1): """ Make an image containing sources generated from a user-specified model. Parameters ---------- shape : 2-tuple of int The shape of the output 2D image. model : 2D astropy.modeling.models object The model to be used for rendering the sources. source_table : `~astropy.table.Table` Table of parameters for the sources. Each row of the table corresponds to a source whose model parameters are defined by the column names, which must match the model parameter names. Column names that do not match model parameters will be ignored. Model parameters not defined in the table will be set to the ``model`` default value. oversample : float, optional The sampling factor used to discretize the models on a pixel grid. If the value is 1.0 (the default), then the models will be discretized by taking the value at the center of the pixel bin. Note that this method will not preserve the total flux of very small sources. Otherwise, the models will be discretized by taking the average over an oversampled grid. The pixels will be oversampled by the ``oversample`` factor. Returns ------- image : 2D `~numpy.ndarray` Image containing model sources. See Also -------- make_random_models_table, make_gaussian_sources_image Examples -------- .. plot:: :include-source: from collections import OrderedDict from astropy.modeling.models import Moffat2D from photutils.datasets import (make_random_models_table, make_model_sources_image) model = Moffat2D() n_sources = 10 shape = (100, 100) param_ranges = [('amplitude', [100, 200]), ('x_0', [0, shape[1]]), ('y_0', [0, shape[0]]), ('gamma', [5, 10]), ('alpha', [1, 2])] param_ranges = OrderedDict(param_ranges) sources = make_random_models_table(n_sources, param_ranges, random_state=12345) data = make_model_sources_image(shape, model, sources) plt.imshow(data) """ image = np.zeros(shape, dtype=float) yidx, xidx = np.indices(shape) params_to_set = [] for param in source_table.colnames: if param in model.param_names: params_to_set.append(param) # Save the initial parameter values so we can set them back when # done with the loop. It's best not to copy a model, because some # models (e.g. PSF models) may have substantial amounts of data in # them. init_params = {param: getattr(model, param) for param in params_to_set} try: for source in source_table: for param in params_to_set: setattr(model, param, source[param]) if oversample == 1: image += model(xidx, yidx) else: image += discretize_model(model, (0, shape[1]), (0, shape[0]), mode='oversample', factor=oversample) finally: for param, value in init_params.items(): setattr(model, param, value) return image def make_gaussian_sources_image(shape, source_table, oversample=1): """ Make an image containing 2D Gaussian sources. Parameters ---------- shape : 2-tuple of int The shape of the output 2D image. source_table : `~astropy.table.Table` Table of parameters for the Gaussian sources. Each row of the table corresponds to a Gaussian source whose parameters are defined by the column names. With the exception of ``'flux'``, column names that do not match model parameters will be ignored (flux will be converted to amplitude). If both ``'flux'`` and ``'amplitude'`` are present, then ``'flux'`` will be ignored. Model parameters not defined in the table will be set to the default value. oversample : float, optional The sampling factor used to discretize the models on a pixel grid. If the value is 1.0 (the default), then the models will be discretized by taking the value at the center of the pixel bin. Note that this method will not preserve the total flux of very small sources. Otherwise, the models will be discretized by taking the average over an oversampled grid. The pixels will be oversampled by the ``oversample`` factor. Returns ------- image : 2D `~numpy.ndarray` Image containing 2D Gaussian sources. See Also -------- make_model_sources_image, make_random_gaussians_table Examples -------- .. plot:: :include-source: # make a table of Gaussian sources from astropy.table import Table table = Table() table['amplitude'] = [50, 70, 150, 210] table['x_mean'] = [160, 25, 150, 90] table['y_mean'] = [70, 40, 25, 60] table['x_stddev'] = [15.2, 5.1, 3., 8.1] table['y_stddev'] = [2.6, 2.5, 3., 4.7] table['theta'] = np.radians(np.array([145., 20., 0., 60.])) # make an image of the sources without noise, with Gaussian # noise, and with Poisson noise from photutils.datasets import make_gaussian_sources_image from photutils.datasets import make_noise_image shape = (100, 200) image1 = make_gaussian_sources_image(shape, table) image2 = image1 + make_noise_image(shape, distribution='gaussian', mean=5., stddev=5.) image3 = image1 + make_noise_image(shape, distribution='poisson', mean=5.) # plot the images import matplotlib.pyplot as plt fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(8, 12)) ax1.imshow(image1, origin='lower', interpolation='nearest') ax1.set_title('Original image') ax2.imshow(image2, origin='lower', interpolation='nearest') ax2.set_title('Original image with added Gaussian noise' ' ($\\mu = 5, \\sigma = 5$)') ax3.imshow(image3, origin='lower', interpolation='nearest') ax3.set_title('Original image with added Poisson noise ($\\mu = 5$)') """ model = models.Gaussian2D(x_stddev=1, y_stddev=1) if 'x_stddev' in source_table.colnames: xstd = source_table['x_stddev'] else: xstd = model.x_stddev.value # default if 'y_stddev' in source_table.colnames: ystd = source_table['y_stddev'] else: ystd = model.y_stddev.value # default colnames = source_table.colnames if 'flux' in colnames and 'amplitude' not in colnames: source_table = source_table.copy() source_table['amplitude'] = (source_table['flux'] / (2. * np.pi * xstd * ystd)) return make_model_sources_image(shape, model, source_table, oversample=oversample) def make_gaussian_prf_sources_image(shape, source_table): """ Make an image containing 2D Gaussian sources. Parameters ---------- shape : 2-tuple of int The shape of the output 2D image. source_table : `~astropy.table.Table` Table of parameters for the Gaussian sources. Each row of the table corresponds to a Gaussian source whose parameters are defined by the column names. With the exception of ``'flux'``, column names that do not match model parameters will be ignored (flux will be converted to amplitude). If both ``'flux'`` and ``'amplitude'`` are present, then ``'flux'`` will be ignored. Model parameters not defined in the table will be set to the default value. Returns ------- image : 2D `~numpy.ndarray` Image containing 2D Gaussian sources. See Also -------- make_model_sources_image, make_random_gaussians_table Examples -------- .. plot:: :include-source: # make a table of Gaussian sources from astropy.table import Table table = Table() table['amplitude'] = [50, 70, 150, 210] table['x_0'] = [160, 25, 150, 90] table['y_0'] = [70, 40, 25, 60] table['sigma'] = [15.2, 5.1, 3., 8.1] # make an image of the sources without noise, with Gaussian # noise, and with Poisson noise from photutils.datasets import make_gaussian_prf_sources_image from photutils.datasets import make_noise_image shape = (100, 200) image1 = make_gaussian_prf_sources_image(shape, table) image2 = (image1 + make_noise_image(shape, distribution='gaussian', mean=5., stddev=5.)) image3 = (image1 + make_noise_image(shape, distribution='poisson', mean=5.)) # plot the images import matplotlib.pyplot as plt fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(8, 12)) ax1.imshow(image1, origin='lower', interpolation='nearest') ax1.set_title('Original image') ax2.imshow(image2, origin='lower', interpolation='nearest') ax2.set_title('Original image with added Gaussian noise' ' ($\\mu = 5, \\sigma = 5$)') ax3.imshow(image3, origin='lower', interpolation='nearest') ax3.set_title('Original image with added Poisson noise ($\\mu = 5$)') """ model = IntegratedGaussianPRF(sigma=1) if 'sigma' in source_table.colnames: sigma = source_table['sigma'] else: sigma = model.sigma.value # default colnames = source_table.colnames if 'flux' not in colnames and 'amplitude' in colnames: source_table = source_table.copy() source_table['flux'] = (source_table['amplitude'] * (2. * np.pi * sigma * sigma)) return make_model_sources_image(shape, model, source_table, oversample=1) def make_4gaussians_image(noise=True): """ Make an example image containing four 2D Gaussians plus a constant background. The background has a mean of 5. If ``noise`` is `True`, then Gaussian noise with a mean of 0 and a standard deviation of 5 is added to the output image. Parameters ---------- noise : bool, optional Whether to include noise in the output image (default is `True`). Returns ------- image : 2D `~numpy.ndarray` Image containing four 2D Gaussian sources. See Also -------- make_100gaussians_image Examples -------- .. plot:: :include-source: from photutils import datasets image = datasets.make_4gaussians_image() plt.imshow(image, origin='lower', interpolation='nearest') """ table = Table() table['amplitude'] = [50, 70, 150, 210] table['x_mean'] = [160, 25, 150, 90] table['y_mean'] = [70, 40, 25, 60] table['x_stddev'] = [15.2, 5.1, 3., 8.1] table['y_stddev'] = [2.6, 2.5, 3., 4.7] table['theta'] = np.radians(np.array([145., 20., 0., 60.])) shape = (100, 200) data = make_gaussian_sources_image(shape, table) + 5. if noise: data += make_noise_image(shape, distribution='gaussian', mean=0., stddev=5., random_state=12345) return data def make_100gaussians_image(noise=True): """ Make an example image containing 100 2D Gaussians plus a constant background. The background has a mean of 5. If ``noise`` is `True`, then Gaussian noise with a mean of 0 and a standard deviation of 2 is added to the output image. Parameters ---------- noise : bool, optional Whether to include noise in the output image (default is `True`). Returns ------- image : 2D `~numpy.ndarray` Image containing 100 2D Gaussian sources. See Also -------- make_4gaussians_image Examples -------- .. plot:: :include-source: from photutils import datasets image = datasets.make_100gaussians_image() plt.imshow(image, origin='lower', interpolation='nearest') """ n_sources = 100 flux_range = [500, 1000] xmean_range = [0, 500] ymean_range = [0, 300] xstddev_range = [1, 5] ystddev_range = [1, 5] params = OrderedDict([('flux', flux_range), ('x_mean', xmean_range), ('y_mean', ymean_range), ('x_stddev', xstddev_range), ('y_stddev', ystddev_range), ('theta', [0, 2*np.pi])]) sources = make_random_gaussians_table(n_sources, params, random_state=12345) shape = (300, 500) data = make_gaussian_sources_image(shape, sources) + 5. if noise: data += make_noise_image(shape, distribution='gaussian', mean=0., stddev=2., random_state=12345) return data def make_wcs(shape, galactic=False): """ Create a simple celestial `~astropy.wcs.WCS` object in either the ICRS or Galactic coordinate frame. Parameters ---------- shape : 2-tuple of int The shape of the 2D array to be used with the output `~astropy.wcs.WCS` object. galactic : bool, optional If `True`, then the output WCS will be in the Galactic coordinate frame. If `False` (default), then the output WCS will be in the ICRS coordinate frame. Returns ------- wcs : `astropy.wcs.WCS` object The world coordinate system (WCS) transformation. See Also -------- make_gwcs, make_imagehdu Notes ----- The `make_gwcs` function returns an equivalent WCS transformation to this one, but as a `gwcs.wcs.WCS` object. Examples -------- >>> from photutils.datasets import make_wcs >>> shape = (100, 100) >>> wcs = make_wcs(shape) >>> print(wcs.wcs.crpix) # doctest: +FLOAT_CMP [50. 50.] >>> print(wcs.wcs.crval) # doctest: +FLOAT_CMP [197.8925 -1.36555556] """ wcs = WCS(naxis=2) rho = np.pi / 3. scale = 0.1 / 3600. # 0.1 arcsec/pixel in deg/pix if astropy_version < '3.1': wcs._naxis1 = shape[1] # nx wcs._naxis2 = shape[0] # ny else: wcs.pixel_shape = shape wcs.wcs.crpix = [shape[1] / 2, shape[0] / 2] # 1-indexed (x, y) wcs.wcs.crval = [197.8925, -1.36555556] wcs.wcs.cunit = ['deg', 'deg'] wcs.wcs.cd = [[-scale * np.cos(rho), scale * np.sin(rho)], [scale * np.sin(rho), scale * np.cos(rho)]] if not galactic: wcs.wcs.radesys = 'ICRS' wcs.wcs.ctype = ['RA---TAN', 'DEC--TAN'] else: wcs.wcs.ctype = ['GLON-CAR', 'GLAT-CAR'] return wcs def make_gwcs(shape, galactic=False): """ Create a simple celestial gWCS object in the ICRS coordinate frame. This function requires the `gwcs `_ package. Parameters ---------- shape : 2-tuple of int The shape of the 2D array to be used with the output `~gwcs.wcs.WCS` object. galactic : bool, optional If `True`, then the output WCS will be in the Galactic coordinate frame. If `False` (default), then the output WCS will be in the ICRS coordinate frame. Returns ------- wcs : `gwcs.wcs.WCS` object The generalized world coordinate system (WCS) transformation. See Also -------- make_wcs, make_imagehdu Notes ----- The `make_wcs` function returns an equivalent WCS transformation to this one, but as an `astropy.wcs.WCS` object. Examples -------- >>> from photutils.datasets import make_gwcs >>> shape = (100, 100) >>> gwcs = make_gwcs(shape) >>> print(gwcs) From Transform -------- ---------------- detector linear_transform icrs None """ from gwcs import wcs as gwcs_wcs from gwcs import coordinate_frames as cf rho = np.pi / 3. scale = 0.1 / 3600. # 0.1 arcsec/pixel in deg/pix shift_by_crpix = (models.Shift((-shape[1] / 2) + 1) & models.Shift((-shape[0] / 2) + 1)) cd_matrix = np.array([[-scale * np.cos(rho), scale * np.sin(rho)], [scale * np.sin(rho), scale * np.cos(rho)]]) rotation = models.AffineTransformation2D(cd_matrix, translation=[0, 0]) rotation.inverse = models.AffineTransformation2D( np.linalg.inv(cd_matrix), translation=[0, 0]) tan = models.Pix2Sky_TAN() celestial_rotation = models.RotateNative2Celestial(197.8925, -1.36555556, 180.0) det2sky = shift_by_crpix | rotation | tan | celestial_rotation det2sky.name = 'linear_transform' detector_frame = cf.Frame2D(name='detector', axes_names=('x', 'y'), unit=(u.pix, u.pix)) if galactic: sky_frame = cf.CelestialFrame(reference_frame=coord.Galactic(), name='galactic', unit=(u.deg, u.deg)) else: sky_frame = cf.CelestialFrame(reference_frame=coord.ICRS(), name='icrs', unit=(u.deg, u.deg)) pipeline = [(detector_frame, det2sky), (sky_frame, None)] return gwcs_wcs.WCS(pipeline) def make_imagehdu(data, wcs=None): """ Create a FITS `~astropy.io.fits.ImageHDU` containing the input 2D image. Parameters ---------- data : 2D array-like The input 2D data. wcs : `None` or `~astropy.wcs.WCS`, optional The world coordinate system (WCS) transformation to include in the output FITS header. Returns ------- image_hdu : `~astropy.io.fits.ImageHDU` The FITS `~astropy.io.fits.ImageHDU`. See Also -------- make_wcs Examples -------- >>> from photutils.datasets import make_imagehdu, make_wcs >>> shape = (100, 100) >>> data = np.ones(shape) >>> wcs = make_wcs(shape) >>> hdu = make_imagehdu(data, wcs=wcs) >>> print(hdu.data.shape) (100, 100) """ data = np.asanyarray(data) if data.ndim != 2: raise ValueError('data must be a 2D array') if wcs is not None: header = wcs.to_header() else: header = None return fits.ImageHDU(data, header=header) photutils-0.7.2/photutils/datasets/tests/0000755000214200020070000000000013573510273022751 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/datasets/tests/__init__.py0000644000214200020070000000000013563423715025053 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/datasets/tests/test_load.py0000644000214200020070000000105313563423715025303 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the load module. """ import pytest from .. import get_path, load def test_get_path(): with pytest.raises(ValueError): get_path('filename', location='invalid') def test_load_fermi_image(): hdu = load.load_fermi_image() assert len(hdu.header) == 81 assert hdu.data.shape == (201, 401) @pytest.mark.remote_data def test_load_star_image(): hdu = load.load_star_image() assert len(hdu.header) == 104 assert hdu.data.shape == (1059, 1059) photutils-0.7.2/photutils/datasets/tests/test_make.py0000644000214200020070000001532313572576136025314 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the make module. """ from astropy.modeling.models import Moffat2D from astropy.table import Table from astropy.version import version as astropy_version import numpy as np from numpy.testing import assert_allclose import pytest from .. import (apply_poisson_noise, make_4gaussians_image, make_100gaussians_image, make_gaussian_prf_sources_image, make_gaussian_sources_image, make_gwcs, make_model_sources_image, make_noise_image, make_random_gaussians_table, make_random_models_table, make_wcs) try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False try: import gwcs # noqa HAS_GWCS = True except ImportError: HAS_GWCS = False SOURCE_TABLE = Table() SOURCE_TABLE['flux'] = [1, 2, 3] SOURCE_TABLE['x_mean'] = [30, 50, 70.5] SOURCE_TABLE['y_mean'] = [50, 50, 50.5] SOURCE_TABLE['x_stddev'] = [1, 2, 3.5] SOURCE_TABLE['y_stddev'] = [2, 1, 3.5] SOURCE_TABLE['theta'] = np.array([0., 30, 50]) * np.pi / 180. SOURCE_TABLE_PRF = Table() SOURCE_TABLE_PRF['x_0'] = [30, 50, 70.5] SOURCE_TABLE_PRF['y_0'] = [50, 50, 50.5] # Without sigma, make_gaussian_prf_sources_image will default to sigma = 1 # so we can ignore it when converting to amplitude SOURCE_TABLE_PRF['amplitude'] = np.array([1, 2, 3]) / (2 * np.pi) def test_make_noise_image(): shape = (100, 100) image = make_noise_image(shape, 'gaussian', mean=0., stddev=2.) assert image.shape == shape assert_allclose(image.mean(), 0., atol=1.) def test_make_noise_image_poisson(): shape = (100, 100) image = make_noise_image(shape, 'poisson', mean=1.) assert image.shape == shape assert_allclose(image.mean(), 1., atol=1.) def test_make_noise_image_nomean(): """Test if ValueError raises if mean is not input.""" with pytest.raises(ValueError): shape = (100, 100) make_noise_image(shape, 'gaussian', stddev=2.) def test_make_noise_image_nostddev(): """ Test if ValueError raises if stddev is not input for Gaussian noise. """ with pytest.raises(ValueError): shape = (100, 100) make_noise_image(shape, 'gaussian', mean=2.) def test_apply_poisson_noise(): shape = (100, 100) data = np.ones(shape) result = apply_poisson_noise(data) assert result.shape == shape assert_allclose(result.mean(), 1., atol=1.) def test_apply_poisson_noise_negative(): """Test if negative image values raises ValueError.""" with pytest.raises(ValueError): shape = (100, 100) data = np.zeros(shape) - 1. apply_poisson_noise(data) def test_make_gaussian_sources_image(): shape = (100, 100) image = make_gaussian_sources_image(shape, SOURCE_TABLE) assert image.shape == shape assert_allclose(image.sum(), SOURCE_TABLE['flux'].sum()) @pytest.mark.xfail('not HAS_SCIPY') def test_make_gaussian_prf_sources_image(): shape = (100, 100) image = make_gaussian_prf_sources_image(shape, SOURCE_TABLE_PRF) assert image.shape == shape # Without sigma in table, image assumes sigma = 1 flux = SOURCE_TABLE_PRF['amplitude'] * (2 * np.pi) assert_allclose(image.sum(), flux.sum()) def test_make_gaussian_sources_image_amplitude(): table = SOURCE_TABLE.copy() table.remove_column('flux') table['amplitude'] = [1, 2, 3] shape = (100, 100) image = make_gaussian_sources_image(shape, table) assert image.shape == shape def test_make_gaussian_sources_image_oversample(): shape = (100, 100) image = make_gaussian_sources_image(shape, SOURCE_TABLE, oversample=10) assert image.shape == shape assert_allclose(image.sum(), SOURCE_TABLE['flux'].sum()) def test_make_random_gaussians_table(): n_sources = 5 param_ranges = dict([('amplitude', [500, 1000]), ('x_mean', [0, 500]), ('y_mean', [0, 300]), ('x_stddev', [1, 5]), ('y_stddev', [1, 5]), ('theta', [0, np.pi])]) table = make_random_gaussians_table(n_sources, param_ranges, random_state=12345) assert len(table) == n_sources def test_make_random_gaussians_table_flux(): n_sources = 5 param_ranges = dict([('flux', [500, 1000]), ('x_mean', [0, 500]), ('y_mean', [0, 300]), ('x_stddev', [1, 5]), ('y_stddev', [1, 5]), ('theta', [0, np.pi])]) table = make_random_gaussians_table(n_sources, param_ranges, random_state=12345) assert 'amplitude' in table.colnames assert len(table) == n_sources def test_make_4gaussians_image(): shape = (100, 200) data_sum = 176219.18059091491 image = make_4gaussians_image() assert image.shape == shape assert_allclose(image.sum(), data_sum, rtol=1.e-6) def test_make_100gaussians_image(): shape = (300, 500) data_sum = 826182.24501251709 image = make_100gaussians_image() assert image.shape == shape assert_allclose(image.sum(), data_sum, rtol=1.e-6) def test_make_random_models_table(): model = Moffat2D(amplitude=1) param_ranges = {'x_0': (0, 300), 'y_0': (0, 500), 'gamma': (1, 3), 'alpha': (1.5, 3)} source_table = make_random_models_table(10, param_ranges) # most of the make_model_sources_image options are exercised in the # make_gaussian_sources_image tests image = make_model_sources_image((300, 500), model, source_table) assert image.sum() > 1 def test_make_wcs(): shape = (100, 200) wcs = make_wcs(shape) if astropy_version < '3.1': assert wcs._naxis1 == shape[1] assert wcs._naxis2 == shape[0] else: assert wcs.pixel_shape == shape assert wcs.wcs.radesys == 'ICRS' wcs = make_wcs(shape, galactic=True) assert wcs.wcs.ctype[0] == 'GLON-CAR' assert wcs.wcs.ctype[1] == 'GLAT-CAR' @pytest.mark.skipif('not HAS_GWCS') def test_make_gwcs(): shape = (100, 200) wcs = make_gwcs(shape) assert wcs.pixel_n_dim == 2 assert wcs.available_frames == ['detector', 'icrs'] assert wcs.output_frame.name == 'icrs' assert wcs.output_frame.axes_names == ('lon', 'lat') wcs = make_gwcs(shape, galactic=True) assert wcs.pixel_n_dim == 2 assert wcs.available_frames == ['detector', 'galactic'] assert wcs.output_frame.name == 'galactic' assert wcs.output_frame.axes_names == ('lon', 'lat') @pytest.mark.skipif('not HAS_GWCS') def test_make_wcs_compare(): shape = (200, 300) wcs = make_wcs(shape) gwcs_obj = make_gwcs(shape) sc1 = wcs.pixel_to_world((50, 75), (50, 100)) sc2 = gwcs_obj.pixel_to_world((50, 75), (50, 100)) assert_allclose(sc1.ra, sc2.ra) assert_allclose(sc1.dec, sc2.dec) photutils-0.7.2/photutils/detection/0000755000214200020070000000000013573510273021755 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/detection/__init__.py0000644000214200020070000000032513563423715024071 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage contains tools for detecting sources in an astronomical image. """ from .core import * # noqa from .findstars import * # noqa photutils-0.7.2/photutils/detection/core.py0000644000214200020070000003020013572576136023263 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This modules provides tools for detecting sources in an astronomical image. """ import warnings from astropy.stats import sigma_clipped_stats from astropy.table import Table from astropy.utils.decorators import deprecated_renamed_argument from astropy.version import version as astropy_version import numpy as np from ..utils.exceptions import NoDetectionsWarning from ..utils._wcs_helpers import _pixel_to_world __all__ = ['detect_threshold', 'find_peaks'] @deprecated_renamed_argument('snr', 'nsigma', 0.7) def detect_threshold(data, nsigma, background=None, error=None, mask=None, mask_value=None, sigclip_sigma=3.0, sigclip_iters=None): """ Calculate a pixel-wise threshold image that can be used to detect sources. Parameters ---------- data : array_like The 2D array of the image. nsigma : float The number of standard deviations per pixel above the ``background`` for which to consider a pixel as possibly being part of a source. background : float or array_like, optional The background value(s) of the input ``data``. ``background`` may either be a scalar value or a 2D image with the same shape as the input ``data``. If the input ``data`` has been background-subtracted, then set ``background`` to ``0.0``. If `None`, then a scalar background value will be estimated using sigma-clipped statistics. error : float or array_like, optional The Gaussian 1-sigma standard deviation of the background noise in ``data``. ``error`` should include all sources of "background" error, but *exclude* the Poisson error of the sources. If ``error`` is a 2D image, then it should represent the 1-sigma background error in each pixel of ``data``. If `None`, then a scalar background rms value will be estimated using sigma-clipped statistics. mask : array_like, bool, optional A boolean mask with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Masked pixels are ignored when computing the image background statistics. mask_value : float, optional An image data value (e.g., ``0.0``) that is ignored when computing the image background statistics. ``mask_value`` will be ignored if ``mask`` is input. sigclip_sigma : float, optional The number of standard deviations to use as the clipping limit when calculating the image background statistics. sigclip_iters : int, optional The number of iterations to perform sigma clipping, or `None` to clip until convergence is achieved (i.e., continue until the last iteration clips nothing) when calculating the image background statistics. Returns ------- threshold : 2D `~numpy.ndarray` A 2D image with the same shape as ``data`` containing the pixel-wise threshold values. See Also -------- :func:`photutils.segmentation.detect_sources` Notes ----- The ``mask``, ``mask_value``, ``sigclip_sigma``, and ``sigclip_iters`` inputs are used only if it is necessary to estimate ``background`` or ``error`` using sigma-clipped background statistics. If ``background`` and ``error`` are both input, then ``mask``, ``mask_value``, ``sigclip_sigma``, and ``sigclip_iters`` are ignored. """ if background is None or error is None: if astropy_version < '3.1': data_mean, _, data_std = sigma_clipped_stats( data, mask=mask, mask_value=mask_value, sigma=sigclip_sigma, iters=sigclip_iters) else: data_mean, _, data_std = sigma_clipped_stats( data, mask=mask, mask_value=mask_value, sigma=sigclip_sigma, maxiters=sigclip_iters) bkgrd_image = np.zeros_like(data) + data_mean bkgrdrms_image = np.zeros_like(data) + data_std if background is None: background = bkgrd_image else: if np.isscalar(background): background = np.zeros_like(data) + background else: if background.shape != data.shape: raise ValueError('If input background is 2D, then it ' 'must have the same shape as the input ' 'data.') if error is None: error = bkgrdrms_image else: if np.isscalar(error): error = np.zeros_like(data) + error else: if error.shape != data.shape: raise ValueError('If input error is 2D, then it ' 'must have the same shape as the input ' 'data.') return background + (error * nsigma) def find_peaks(data, threshold, box_size=3, footprint=None, mask=None, border_width=None, npeaks=np.inf, centroid_func=None, subpixel=False, error=None, wcs=None): """ Find local peaks in an image that are above above a specified threshold value. Peaks are the maxima above the ``threshold`` within a local region. The local regions are defined by either the ``box_size`` or ``footprint`` parameters. ``box_size`` defines the local region around each pixel as a square box. ``footprint`` is a boolean array where `True` values specify the region shape. If multiple pixels within a local region have identical intensities, then the coordinates of all such pixels are returned. Otherwise, there will be only one peak pixel per local region. Thus, the defined region effectively imposes a minimum separation between peaks unless there are identical peaks within the region. If ``centroid_func`` is input, then it will be used to calculate a centroid within the defined local region centered on each detected peak pixel. In this case, the centroid will also be returned in the output table. Parameters ---------- data : array_like The 2D array of the image. threshold : float or array-like The data value or pixel-wise data values to be used for the detection threshold. A 2D ``threshold`` must have the same shape as ``data``. See `detect_threshold` for one way to create a ``threshold`` image. box_size : scalar or tuple, optional The size of the local region to search for peaks at every point in ``data``. If ``box_size`` is a scalar, then the region shape will be ``(box_size, box_size)``. Either ``box_size`` or ``footprint`` must be defined. If they are both defined, then ``footprint`` overrides ``box_size``. footprint : `~numpy.ndarray` of bools, optional A boolean array where `True` values describe the local footprint region within which to search for peaks at every point in ``data``. ``box_size=(n, m)`` is equivalent to ``footprint=np.ones((n, m))``. Either ``box_size`` or ``footprint`` must be defined. If they are both defined, then ``footprint`` overrides ``box_size``. mask : array_like, bool, optional A boolean mask with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. border_width : bool, optional The width in pixels to exclude around the border of the ``data``. npeaks : int, optional The maximum number of peaks to return. When the number of detected peaks exceeds ``npeaks``, the peaks with the highest peak intensities will be returned. centroid_func : callable, optional A callable object (e.g. function or class) that is used to calculate the centroid of a 2D array. The ``centroid_func`` must accept a 2D `~numpy.ndarray`, have a ``mask`` keyword, and optionally an ``error`` keyword. The callable object must return a tuple of two 1D `~numpy.ndarray`\\s, representing the x and y centroids, respectively. error : array_like, optional The 2D array of the 1-sigma errors of the input ``data``. ``error`` is used only if ``centroid_func`` is input (the ``error`` array is passed directly to the ``centroid_func``). wcs : `None` or WCS object, optional A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). If `None`, then the sky coordinates will not be returned in the output `~astropy.table.Table`. Returns ------- output : `~astropy.table.Table` or `None` A table containing the x and y pixel location of the peaks and their values. If ``centroid_func`` is input, then the table will also contain the centroid position. If no peaks are found then `None` is returned. """ from scipy.ndimage import maximum_filter data = np.asanyarray(data) if np.all(data == data.flat[0]): warnings.warn('Input data is constant. No local peaks can be found.', NoDetectionsWarning) return None if not np.isscalar(threshold): threshold = np.asanyarray(threshold) if data.shape != threshold.shape: raise ValueError('A threshold array must have the same shape as ' 'the input data.') # remove NaN values to avoid runtime warnings nan_mask = np.isnan(data) if np.any(nan_mask): data = np.copy(data) # ndarray data[nan_mask] = np.nanmin(data) if footprint is not None: data_max = maximum_filter(data, footprint=footprint, mode='constant', cval=0.0) else: data_max = maximum_filter(data, size=box_size, mode='constant', cval=0.0) peak_goodmask = (data == data_max) # good pixels are True if mask is not None: mask = np.asanyarray(mask) if data.shape != mask.shape: raise ValueError('data and mask must have the same shape') peak_goodmask = np.logical_and(peak_goodmask, ~mask) if border_width is not None: for i in range(peak_goodmask.ndim): peak_goodmask = peak_goodmask.swapaxes(0, i) peak_goodmask[:border_width] = False peak_goodmask[-border_width:] = False peak_goodmask = peak_goodmask.swapaxes(0, i) peak_goodmask = np.logical_and(peak_goodmask, (data > threshold)) y_peaks, x_peaks = peak_goodmask.nonzero() peak_values = data[y_peaks, x_peaks] nxpeaks = len(x_peaks) if nxpeaks > npeaks: idx = np.argsort(peak_values)[::-1][:npeaks] x_peaks = x_peaks[idx] y_peaks = y_peaks[idx] peak_values = peak_values[idx] if nxpeaks == 0: warnings.warn('No local peaks were found.', NoDetectionsWarning) return None # construct the output Table colnames = ['x_peak', 'y_peak', 'peak_value'] coldata = [x_peaks, y_peaks, peak_values] table = Table(coldata, names=colnames) if wcs is not None: skycoord_peaks = _pixel_to_world(x_peaks, y_peaks, wcs) table.add_column(skycoord_peaks, name='skycoord_peak', index=2) # perform centroiding if centroid_func is not None: from ..centroids import centroid_sources # prevents circular import if not callable(centroid_func): raise TypeError('centroid_func must be a callable object') x_centroids, y_centroids = centroid_sources( data, x_peaks, y_peaks, box_size=box_size, footprint=footprint, error=error, mask=mask, centroid_func=centroid_func) table['x_centroid'] = x_centroids table['y_centroid'] = y_centroids if (centroid_func is not None or subpixel) and wcs is not None: skycoord_centroids = _pixel_to_world(x_centroids, y_centroids, wcs) idx = table.colnames.index('y_centroid') table.add_column(skycoord_centroids, name='skycoord_centroid', index=idx+1) return table photutils-0.7.2/photutils/detection/findstars.py0000644000214200020070000012232513572576136024342 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module implements classes for detecting stars in an astronomical image. The convention is that all star-finding classes are subclasses of an abstract base class called ``StarFinderBase``. Each star-finding class should define a method called ``find_stars`` that finds stars in an image. """ import abc import math import warnings from astropy.stats import gaussian_fwhm_to_sigma from astropy.table import Table from astropy.utils import lazyproperty import numpy as np from .core import find_peaks from ..utils._moments import _moments, _moments_central from ..utils.convolution import _filter_data from ..utils.exceptions import NoDetectionsWarning __all__ = ['StarFinderBase', 'DAOStarFinder', 'IRAFStarFinder'] class _StarFinderKernel: """ Class to calculate a 2D Gaussian density enhancement kernel. The kernel has negative wings and sums to zero. It is used by both `DAOStarFinder` and `IRAFStarFinder`. Parameters ---------- fwhm : float The full-width half-maximum (FWHM) of the major axis of the Gaussian kernel in units of pixels. ratio : float, optional The ratio of the minor and major axis standard deviations of the Gaussian kernel. ``ratio`` must be strictly positive and less than or equal to 1.0. The default is 1.0 (i.e., a circular Gaussian kernel). theta : float, optional The position angle (in degrees) of the major axis of the Gaussian kernel, measured counter-clockwise from the positive x axis. sigma_radius : float, optional The truncation radius of the Gaussian kernel in units of sigma (standard deviation) [``1 sigma = FWHM / 2.0*sqrt(2.0*log(2.0))``]. The default is 1.5. normalize_zerosum : bool, optional Whether to normalize the Gaussian kernel to have zero sum, The default is `True`, which generates a density-enhancement kernel. Notes ----- The class attributes include the dimensions of the elliptical kernel and the coefficients of a 2D elliptical Gaussian function expressed as: ``f(x,y) = A * exp(-g(x,y))`` where ``g(x,y) = a*(x-x0)**2 + 2*b*(x-x0)*(y-y0) + c*(y-y0)**2`` References ---------- .. [1] https://en.wikipedia.org/wiki/Gaussian_function """ def __init__(self, fwhm, ratio=1.0, theta=0.0, sigma_radius=1.5, normalize_zerosum=True): if fwhm < 0: raise ValueError('fwhm must be positive.') if ratio <= 0 or ratio > 1: raise ValueError('ratio must be positive and less or equal ' 'than 1.') if sigma_radius <= 0: raise ValueError('sigma_radius must be positive.') self.fwhm = fwhm self.ratio = ratio self.theta = theta self.sigma_radius = sigma_radius self.xsigma = self.fwhm * gaussian_fwhm_to_sigma self.ysigma = self.xsigma * self.ratio theta_radians = np.deg2rad(self.theta) cost = np.cos(theta_radians) sint = np.sin(theta_radians) xsigma2 = self.xsigma**2 ysigma2 = self.ysigma**2 self.a = (cost**2 / (2.0 * xsigma2)) + (sint**2 / (2.0 * ysigma2)) # CCW self.b = 0.5 * cost * sint * ((1.0 / xsigma2) - (1.0 / ysigma2)) self.c = (sint**2 / (2.0 * xsigma2)) + (cost**2 / (2.0 * ysigma2)) # find the extent of an ellipse with radius = sigma_radius*sigma; # solve for the horizontal and vertical tangents of an ellipse # defined by g(x,y) = f self.f = self.sigma_radius**2 / 2.0 denom = (self.a * self.c) - self.b**2 # nx and ny are always odd self.nx = 2 * int(max(2, math.sqrt(self.c * self.f / denom))) + 1 self.ny = 2 * int(max(2, math.sqrt(self.a * self.f / denom))) + 1 self.xc = self.xradius = self.nx // 2 self.yc = self.yradius = self.ny // 2 # define the kernel on a 2D grid yy, xx = np.mgrid[0:self.ny, 0:self.nx] self.circular_radius = np.sqrt((xx - self.xc)**2 + (yy - self.yc)**2) self.elliptical_radius = (self.a * (xx - self.xc)**2 + 2.0 * self.b * (xx - self.xc) * (yy - self.yc) + self.c * (yy - self.yc)**2) self.mask = np.where( (self.elliptical_radius <= self.f) | (self.circular_radius <= 2.0), 1, 0).astype(int) self.npixels = self.mask.sum() # NOTE: the central (peak) pixel of gaussian_kernel has a value of 1. self.gaussian_kernel_unmasked = np.exp(-self.elliptical_radius) self.gaussian_kernel = self.gaussian_kernel_unmasked * self.mask # denom = variance * npixels denom = ((self.gaussian_kernel**2).sum() - (self.gaussian_kernel.sum()**2 / self.npixels)) self.relerr = 1.0 / np.sqrt(denom) # normalize the kernel to zero sum if normalize_zerosum: self.data = ((self.gaussian_kernel - (self.gaussian_kernel.sum() / self.npixels)) / denom) * self.mask else: self.data = self.gaussian_kernel self.shape = self.data.shape class _StarCutout: """ Class to hold a 2D image cutout of a single star for the star finder classes. Parameters ---------- data : 2D array_like The cutout 2D image from the input unconvolved 2D image. convdata : 2D array_like The cutout 2D image from the convolved 2D image. slices : tuple of two slices A tuple of two slices representing the minimal box of the cutout from the original image. xpeak, ypeak : float The (x, y) pixel coordinates of the peak pixel. kernel : `_StarFinderKernel` The convolution kernel. The shape of the kernel must match that of the input ``data``. threshold_eff : float The absolute image value above which to select sources. This threshold should be the threshold value input to the star finder class multiplied by the kernel relerr. """ def __init__(self, data, convdata, slices, xpeak, ypeak, kernel, threshold_eff): self.data = data self.convdata = convdata self.slices = slices self.xpeak = xpeak self.ypeak = ypeak self.kernel = kernel self.threshold_eff = threshold_eff self.shape = data.shape self.nx = self.shape[1] # always odd self.ny = self.shape[0] # always odd self.cutout_xcenter = int(self.nx // 2) self.cutout_ycenter = int(self.ny // 2) self.xorigin = self.slices[1].start # in original image self.yorigin = self.slices[0].start # in original image self.mask = kernel.mask # kernel mask self.npixels = kernel.npixels # unmasked pixels self.data_masked = self.data * self.mask class _DAOFindProperties: """ Class to calculate the properties of each detected star, as defined by `DAOFIND`_. Parameters ---------- star_cutout : `_StarCutout` A `_StarCutout` object containing the image cutout for the star. kernel : `_StarFinderKernel` The convolution kernel. The shape of the kernel must match that of the input ``star_cutout``. sky : float, optional The local sky level around the source. ``sky`` is used only to calculate the source peak value, flux, and magnitude. The default is 0. .. _DAOFIND: https://iraf.net/irafhelp.php?val=daofind """ def __init__(self, star_cutout, kernel, sky=0.): if not isinstance(star_cutout, _StarCutout): raise ValueError('data must be an _StarCutout object') if star_cutout.data.shape != kernel.shape: raise ValueError('cutout and kernel must have the same shape') self.cutout = star_cutout self.kernel = kernel self.sky = sky # DAOFIND has no sky input -> same as sky=0. self.data = star_cutout.data self.data_masked = star_cutout.data_masked self.npixels = star_cutout.npixels # unmasked pixels self.nx = star_cutout.nx self.ny = star_cutout.ny self.xcenter = star_cutout.cutout_xcenter self.ycenter = star_cutout.cutout_ycenter @lazyproperty def data_peak(self): return self.data[self.ycenter, self.xcenter] @lazyproperty def conv_peak(self): return self.cutout.convdata[self.ycenter, self.xcenter] @lazyproperty def roundness1(self): # set the central (peak) pixel to zero cutout_conv = self.cutout.convdata.copy() cutout_conv[self.ycenter, self.xcenter] = 0.0 # calculate the four roundness quadrants quad1 = cutout_conv[0:self.ycenter + 1, self.xcenter + 1:] quad2 = cutout_conv[0:self.ycenter, 0:self.xcenter + 1] quad3 = cutout_conv[self.ycenter:, 0:self.xcenter] quad4 = cutout_conv[self.ycenter + 1:, self.xcenter:] sum2 = -quad1.sum() + quad2.sum() - quad3.sum() + quad4.sum() if sum2 == 0: return 0. sum4 = np.abs(cutout_conv).sum() if sum4 <= 0: return None return 2.0 * sum2 / sum4 @lazyproperty def sharpness(self): npixels = self.npixels - 1 # exclude the peak pixel data_mean = (np.sum(self.data_masked) - self.data_peak) / npixels return (self.data_peak - data_mean) / self.conv_peak def daofind_marginal_fit(self, axis=0): """ Fit 1D Gaussians, defined from the marginal x/y kernel distributions, to the marginal x/y distributions of the original (unconvolved) image. These fits are used calculate the star centroid and roundness ("GROUND") properties. Parameters ---------- axis : {0, 1}, optional The axis for which the marginal fit is performed: * 0: for the x axis * 1: for the y axis Returns ------- dx : float The fractional shift in x or y (depending on ``axis`` value) of the image centroid relative to the maximum pixel. hx : float The height of the best-fitting Gaussian to the marginal x or y (depending on ``axis`` value) distribution of the unconvolved source data. """ # define triangular weighting functions along each axis, peaked # in the middle and equal to one at the edge x = self.xcenter - np.abs(np.arange(self.nx) - self.xcenter) + 1 y = self.ycenter - np.abs(np.arange(self.ny) - self.ycenter) + 1 xwt, ywt = np.meshgrid(x, y) if axis == 0: # marginal distributions along x axis wt = xwt[0] # 1D wts = ywt # 2D size = self.nx center = self.xcenter sigma = self.kernel.xsigma dxx = center - np.arange(size) elif axis == 1: # marginal distributions along y axis wt = np.transpose(ywt)[0] # 1D wts = xwt # 2D size = self.ny center = self.ycenter sigma = self.kernel.ysigma dxx = np.arange(size) - center # compute marginal sums for given axis wt_sum = np.sum(wt) dx = center - np.arange(size) # weighted marginal sums kern_sum_1d = np.sum(self.kernel.gaussian_kernel_unmasked * wts, axis=axis) kern_sum = np.sum(kern_sum_1d * wt) kern2_sum = np.sum(kern_sum_1d**2 * wt) dkern_dx = kern_sum_1d * dx dkern_dx_sum = np.sum(dkern_dx * wt) dkern_dx2_sum = np.sum(dkern_dx**2 * wt) kern_dkern_dx_sum = np.sum(kern_sum_1d * dkern_dx * wt) data_sum_1d = np.sum(self.data * wts, axis=axis) data_sum = np.sum(data_sum_1d * wt) data_kern_sum = np.sum(data_sum_1d * kern_sum_1d * wt) data_dkern_dx_sum = np.sum(data_sum_1d * dkern_dx * wt) data_dx_sum = np.sum(data_sum_1d * dxx * wt) # perform linear least-squares fit (where data = sky + hx*kernel) # to find the amplitude (hx) # reject the star if the fit amplitude is not positive hx_numer = data_kern_sum - (data_sum * kern_sum) / wt_sum if hx_numer <= 0.: return np.nan, np.nan hx_denom = kern2_sum - (kern_sum**2 / wt_sum) if hx_denom <= 0.: return np.nan, np.nan # compute fit amplitude hx = hx_numer / hx_denom # sky = (data_sum - (hx * kern_sum)) / wt_sum # compute centroid shift dx = ((kern_dkern_dx_sum - (data_dkern_dx_sum - dkern_dx_sum*data_sum)) / (hx * dkern_dx2_sum / sigma**2)) hsize = size / 2. if abs(dx) > hsize: if data_sum == 0.: dx = 0.0 else: dx = data_dx_sum / data_sum if abs(dx) > hsize: dx = 0.0 return dx, hx @lazyproperty def dx_hx(self): return self.daofind_marginal_fit(axis=0) @lazyproperty def dy_hy(self): return self.daofind_marginal_fit(axis=1) @lazyproperty def dx(self): return self.dx_hx[0] @lazyproperty def dy(self): return self.dy_hy[0] @lazyproperty def xcentroid(self): return self.cutout.xpeak + self.dx @lazyproperty def ycentroid(self): return self.cutout.ypeak + self.dy @lazyproperty def hx(self): return self.dx_hx[1] @lazyproperty def hy(self): return self.dy_hy[1] @lazyproperty def roundness2(self): """ The star roundness. This roundness parameter represents the ratio of the difference in the height of the best fitting Gaussian function in x minus the best fitting Gaussian function in y, divided by the average of the best fitting Gaussian functions in x and y. A circular source will have a zero roundness. A source extended in x or y will have a negative or positive roundness, respectively. """ if np.isnan(self.hx) or np.isnan(self.hy): return np.nan else: return 2.0 * (self.hx - self.hy) / (self.hx + self.hy) @lazyproperty def peak(self): return self.data_peak - self.sky @lazyproperty def npix(self): """ The total number of pixels in the rectangular cutout image. """ return self.data.size @lazyproperty def flux(self): return ((self.conv_peak / self.cutout.threshold_eff) - (self.sky * self.npix)) @lazyproperty def mag(self): if self.flux <= 0: return np.nan else: return -2.5 * np.log10(self.flux) class _IRAFStarFindProperties: """ Class to calculate the properties of each detected star, as defined by IRAF's ``starfind`` task. Parameters ---------- star_cutout : `_StarCutout` A `_StarCutout` object containing the image cutout for the star. kernel : `_StarFinderKernel` The convolution kernel. The shape of the kernel must match that of the input ``star_cutout``. sky : `None` or float, optional The local sky level around the source. If sky is ``None``, then a local sky level will be (crudely) estimated using the IRAF ``starfind`` calculation. """ def __init__(self, star_cutout, kernel, sky=None): if not isinstance(star_cutout, _StarCutout): raise ValueError('data must be an _StarCutout object') if star_cutout.data.shape != kernel.shape: raise ValueError('cutout and kernel must have the same shape') self.cutout = star_cutout self.kernel = kernel if sky is None: skymask = ~self.kernel.mask.astype(bool) # 1=sky, 0=obj nsky = np.count_nonzero(skymask) if nsky == 0: mean_sky = (np.max(self.cutout.data) - np.max(self.cutout.convdata)) else: mean_sky = np.sum(self.cutout.data * skymask) / nsky self.sky = mean_sky else: self.sky = sky @lazyproperty def data(self): cutout = np.array((self.cutout.data - self.sky) * self.cutout.mask) # IRAF starfind discards negative pixels cutout = np.where(cutout > 0, cutout, 0) return cutout @lazyproperty def moments(self): return _moments(self.data, order=1) @lazyproperty def cutout_xcentroid(self): return self.moments[0, 1] / self.moments[0, 0] @lazyproperty def cutout_ycentroid(self): return self.moments[1, 0] / self.moments[0, 0] @lazyproperty def xcentroid(self): return self.cutout_xcentroid + self.cutout.xorigin @lazyproperty def ycentroid(self): return self.cutout_ycentroid + self.cutout.yorigin @lazyproperty def npix(self): return np.count_nonzero(self.data) @lazyproperty def sky(self): return self.sky @lazyproperty def peak(self): return np.max(self.data) @lazyproperty def flux(self): return np.sum(self.data) @lazyproperty def mag(self): return -2.5 * np.log10(self.flux) @lazyproperty def moments_central(self): return _moments_central( self.data, (self.cutout_xcentroid, self.cutout_ycentroid), order=2) / self.moments[0, 0] @lazyproperty def mu_sum(self): return self.moments_central[0, 2] + self.moments_central[2, 0] @lazyproperty def mu_diff(self): return self.moments_central[0, 2] - self.moments_central[2, 0] @lazyproperty def fwhm(self): return 2.0 * np.sqrt(np.log(2.0) * self.mu_sum) @lazyproperty def sharpness(self): return self.fwhm / self.kernel.fwhm @lazyproperty def roundness(self): return np.sqrt(self.mu_diff**2 + 4.0 * self.moments_central[1, 1]**2) / self.mu_sum @lazyproperty def pa(self): pa = np.rad2deg(0.5 * np.arctan2(2.0 * self.moments_central[1, 1], self.mu_diff)) if pa < 0.: pa += 180. return pa def _find_stars(data, kernel, threshold_eff, min_separation=None, mask=None, exclude_border=False): """ Find stars in an image. Parameters ---------- data : 2D array_like The 2D array of the image. kernel : `_StarFinderKernel` The convolution kernel. threshold_eff : float The absolute image value above which to select sources. This threshold should be the threshold input to the star finder class multiplied by the kernel relerr. mask : 2D bool array, optional A boolean mask with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Masked pixels are ignored when searching for stars. exclude_border : bool, optional Set to `True` to exclude sources found within half the size of the convolution kernel from the image borders. The default is `False`, which is the mode used by IRAF's `DAOFIND`_ and `starfind`_ tasks. Returns ------- objects : list of `_StarCutout` A list of `_StarCutout` objects containing the image cutout for each source. .. _DAOFIND: https://iraf.net/irafhelp.php?val=daofind .. _starfind: https://iraf.net/irafhelp.php?val=starfind """ convolved_data = _filter_data(data, kernel.data, mode='constant', fill_value=0.0, check_normalization=False) # define a local footprint for the peak finder if min_separation is None: # daofind footprint = kernel.mask.astype(bool) else: # define a circular footprint idx = np.arange(-min_separation, min_separation + 1) xx, yy = np.meshgrid(idx, idx) footprint = np.array((xx**2 + yy**2) <= min_separation**2, dtype=int) # pad the data and convolved image by the kernel x/y radius to allow # for detections near the edges if not exclude_border: ypad = kernel.yradius xpad = kernel.xradius pad = ((ypad, ypad), (xpad, xpad)) # mode must be a string for numpy < 0.11 # (see https://github.com/numpy/numpy/issues/7112) mode = str('constant') data = np.pad(data, pad, mode=mode, constant_values=[0.]) if mask is not None: mask = np.pad(mask, pad, mode=mode, constant_values=[0.]) convolved_data = np.pad(convolved_data, pad, mode=mode, constant_values=[0.]) # find local peaks in the convolved data with warnings.catch_warnings(): # suppress any NoDetectionsWarning from find_peaks warnings.filterwarnings('ignore', category=NoDetectionsWarning) tbl = find_peaks(convolved_data, threshold_eff, footprint=footprint, mask=mask) if tbl is None: return None coords = np.transpose([tbl['y_peak'], tbl['x_peak']]) star_cutouts = [] for (ypeak, xpeak) in coords: # now extract the object from the data, centered on the peak # pixel in the convolved image, with the same size as the kernel x0 = xpeak - kernel.xradius x1 = xpeak + kernel.xradius + 1 y0 = ypeak - kernel.yradius y1 = ypeak + kernel.yradius + 1 if x0 < 0 or x1 > data.shape[1]: continue # pragma: no cover if y0 < 0 or y1 > data.shape[0]: continue # pragma: no cover slices = (slice(y0, y1), slice(x0, x1)) data_cutout = data[slices] convdata_cutout = convolved_data[slices] # correct pixel values for the previous image padding if not exclude_border: x0 -= kernel.xradius x1 -= kernel.xradius y0 -= kernel.yradius y1 -= kernel.yradius xpeak -= kernel.xradius ypeak -= kernel.yradius slices = (slice(y0, y1), slice(x0, x1)) star_cutouts.append(_StarCutout(data_cutout, convdata_cutout, slices, xpeak, ypeak, kernel, threshold_eff)) return star_cutouts class StarFinderBase(metaclass=abc.ABCMeta): """ Abstract base class for star finders. """ def __call__(self, data, mask=None): return self.find_stars(data, mask=mask) @abc.abstractmethod def find_stars(self, data, mask=None): """ Find stars in an astronomical image. Parameters ---------- data : 2D array_like The 2D image array. mask : 2D bool array, optional A boolean mask with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Masked pixels are ignored when searching for stars. Returns ------- table : `~astropy.table.Table` A table of found stars. If no stars are found then an empty table is returned. """ raise NotImplementedError('Needs to be implemented in a subclass.') class DAOStarFinder(StarFinderBase): """ Detect stars in an image using the DAOFIND (`Stetson 1987 `_) algorithm. DAOFIND (`Stetson 1987; PASP 99, 191 `_) searches images for local density maxima that have a peak amplitude greater than ``threshold`` (approximately; ``threshold`` is applied to a convolved image) and have a size and shape similar to the defined 2D Gaussian kernel. The Gaussian kernel is defined by the ``fwhm``, ``ratio``, ``theta``, and ``sigma_radius`` input parameters. ``DAOStarFinder`` finds the object centroid by fitting the marginal x and y 1D distributions of the Gaussian kernel to the marginal x and y distributions of the input (unconvolved) ``data`` image. ``DAOStarFinder`` calculates the object roundness using two methods. The ``roundlo`` and ``roundhi`` bounds are applied to both measures of roundness. The first method (``roundness1``; called ``SROUND`` in `DAOFIND`_) is based on the source symmetry and is the ratio of a measure of the object's bilateral (2-fold) to four-fold symmetry. The second roundness statistic (``roundness2``; called ``GROUND`` in `DAOFIND`_) measures the ratio of the difference in the height of the best fitting Gaussian function in x minus the best fitting Gaussian function in y, divided by the average of the best fitting Gaussian functions in x and y. A circular source will have a zero roundness. A source extended in x or y will have a negative or positive roundness, respectively. The sharpness statistic measures the ratio of the difference between the height of the central pixel and the mean of the surrounding non-bad pixels in the convolved image, to the height of the best fitting Gaussian function at that point. Parameters ---------- threshold : float The absolute image value above which to select sources. fwhm : float The full-width half-maximum (FWHM) of the major axis of the Gaussian kernel in units of pixels. ratio : float, optional The ratio of the minor to major axis standard deviations of the Gaussian kernel. ``ratio`` must be strictly positive and less than or equal to 1.0. The default is 1.0 (i.e., a circular Gaussian kernel). theta : float, optional The position angle (in degrees) of the major axis of the Gaussian kernel measured counter-clockwise from the positive x axis. sigma_radius : float, optional The truncation radius of the Gaussian kernel in units of sigma (standard deviation) [``1 sigma = FWHM / (2.0*sqrt(2.0*log(2.0)))``]. sharplo : float, optional The lower bound on sharpness for object detection. sharphi : float, optional The upper bound on sharpness for object detection. roundlo : float, optional The lower bound on roundness for object detection. roundhi : float, optional The upper bound on roundness for object detection. sky : float, optional The background sky level of the image. Setting ``sky`` affects only the output values of the object ``peak``, ``flux``, and ``mag`` values. The default is 0.0, which should be used to replicate the results from `DAOFIND`_. exclude_border : bool, optional Set to `True` to exclude sources found within half the size of the convolution kernel from the image borders. The default is `False`, which is the mode used by `DAOFIND`_. brightest : int, None, optional Number of brightest objects to keep after sorting the full object list. If ``brightest`` is set to `None`, all objects will be selected. peakmax : float, None, optional Maximum peak pixel value in an object. Only objects whose peak pixel values are *strictly smaller* than ``peakmax`` will be selected. This may be used to exclude saturated sources. By default, when ``peakmax`` is set to `None`, all objects will be selected. .. warning:: `DAOStarFinder` automatically excludes objects whose peak pixel values are negative. Therefore, setting ``peakmax`` to a non-positive value would result in exclusion of all objects. See Also -------- IRAFStarFinder Notes ----- For the convolution step, this routine sets pixels beyond the image borders to 0.0. The equivalent parameters in `DAOFIND`_ are ``boundary='constant'`` and ``constant=0.0``. The main differences between `~photutils.detection.DAOStarFinder` and `~photutils.detection.IRAFStarFinder` are: * `~photutils.detection.IRAFStarFinder` always uses a 2D circular Gaussian kernel, while `~photutils.detection.DAOStarFinder` can use an elliptical Gaussian kernel. * `~photutils.detection.IRAFStarFinder` calculates the objects' centroid, roundness, and sharpness using image moments. References ---------- .. [1] Stetson, P. 1987; PASP 99, 191 (http://adsabs.harvard.edu/abs/1987PASP...99..191S) .. [2] https://iraf.net/irafhelp.php?val=daofind .. _DAOFIND: https://iraf.net/irafhelp.php?val=daofind """ def __init__(self, threshold, fwhm, ratio=1.0, theta=0.0, sigma_radius=1.5, sharplo=0.2, sharphi=1.0, roundlo=-1.0, roundhi=1.0, sky=0.0, exclude_border=False, brightest=None, peakmax=None): if not np.isscalar(threshold): raise TypeError('threshold must be a scalar value.') self.threshold = threshold if not np.isscalar(fwhm): raise TypeError('fwhm must be a scalar value.') self.fwhm = fwhm self.ratio = ratio self.theta = theta self.sigma_radius = sigma_radius self.sharplo = sharplo self.sharphi = sharphi self.roundlo = roundlo self.roundhi = roundhi self.sky = sky self.exclude_border = exclude_border self.kernel = _StarFinderKernel(self.fwhm, self.ratio, self.theta, self.sigma_radius) self.threshold_eff = self.threshold * self.kernel.relerr self.brightest = brightest self.peakmax = peakmax self._star_cutouts = None def find_stars(self, data, mask=None): """ Find stars in an astronomical image. Parameters ---------- data : 2D array_like The 2D image array. mask : 2D bool array, optional A boolean mask with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Masked pixels are ignored when searching for stars. Returns ------- table : `~astropy.table.Table` or `None` A table of found stars with the following parameters: * ``id``: unique object identification number. * ``xcentroid, ycentroid``: object centroid. * ``sharpness``: object sharpness. * ``roundness1``: object roundness based on symmetry. * ``roundness2``: object roundness based on marginal Gaussian fits. * ``npix``: the total number of pixels in the Gaussian kernel array. * ``sky``: the input ``sky`` parameter. * ``peak``: the peak, sky-subtracted, pixel value of the object. * ``flux``: the object flux calculated as the peak density in the convolved image divided by the detection threshold. This derivation matches that of `DAOFIND`_ if ``sky`` is 0.0. * ``mag``: the object instrumental magnitude calculated as ``-2.5 * log10(flux)``. The derivation matches that of `DAOFIND`_ if ``sky`` is 0.0. `None` is returned if no stars are found. """ star_cutouts = _find_stars(data, self.kernel, self.threshold_eff, mask=mask, exclude_border=self.exclude_border) if star_cutouts is None: warnings.warn('No sources were found.', NoDetectionsWarning) return None self._star_cutouts = star_cutouts star_props = [] for star_cutout in star_cutouts: props = _DAOFindProperties(star_cutout, self.kernel, self.sky) if np.isnan(props.dx_hx).any() or np.isnan(props.dy_hy).any(): continue if (props.sharpness <= self.sharplo or props.sharpness >= self.sharphi): continue if (props.roundness1 <= self.roundlo or props.roundness1 >= self.roundhi): continue if (props.roundness2 <= self.roundlo or props.roundness2 >= self.roundhi): continue if self.peakmax is not None and props.peak >= self.peakmax: continue star_props.append(props) nstars = len(star_props) if nstars == 0: warnings.warn('Sources were found, but none pass the sharpness ' 'and roundness criteria.', NoDetectionsWarning) return None if self.brightest is not None: fluxes = [props.flux for props in star_props] idx = sorted(np.argsort(fluxes)[-self.brightest:].tolist()) star_props = [star_props[k] for k in idx] nstars = len(star_props) table = Table() table['id'] = np.arange(nstars) + 1 columns = ('xcentroid', 'ycentroid', 'sharpness', 'roundness1', 'roundness2', 'npix', 'sky', 'peak', 'flux', 'mag') for column in columns: table[column] = [getattr(props, column) for props in star_props] return table class IRAFStarFinder(StarFinderBase): """ Detect stars in an image using IRAF's "starfind" algorithm. `IRAFStarFinder` searches images for local density maxima that have a peak amplitude greater than ``threshold`` above the local background and have a PSF full-width at half-maximum similar to the input ``fwhm``. The objects' centroid, roundness (ellipticity), and sharpness are calculated using image moments. Parameters ---------- threshold : float The absolute image value above which to select sources. fwhm : float The full-width half-maximum (FWHM) of the 2D circular Gaussian kernel in units of pixels. minsep_fwhm : float, optional The minimum separation for detected objects in units of ``fwhm``. sigma_radius : float, optional The truncation radius of the Gaussian kernel in units of sigma (standard deviation) [``1 sigma = FWHM / 2.0*sqrt(2.0*log(2.0))``]. sharplo : float, optional The lower bound on sharpness for object detection. sharphi : float, optional The upper bound on sharpness for object detection. roundlo : float, optional The lower bound on roundness for object detection. roundhi : float, optional The upper bound on roundness for object detection. sky : float, optional The background sky level of the image. Inputing a ``sky`` value will override the background sky estimate. Setting ``sky`` affects only the output values of the object ``peak``, ``flux``, and ``mag`` values. The default is ``None``, which means the sky value will be estimated using the `starfind`_ method. exclude_border : bool, optional Set to `True` to exclude sources found within half the size of the convolution kernel from the image borders. The default is `False`, which is the mode used by `starfind`_. brightest : int, None, optional Number of brightest objects to keep after sorting the full object list. If ``brightest`` is set to `None`, all objects will be selected. peakmax : float, None, optional Maximum peak pixel value in an object. Only objects whose peak pixel values are *strictly smaller* than ``peakmax`` will be selected. This may be used to exclude saturated sources. By default, when ``peakmax`` is set to `None`, all objects will be selected. .. warning:: `IRAFStarFinder` automatically excludes objects whose peak pixel values are negative. Therefore, setting ``peakmax`` to a non-positive value would result in exclusion of all objects. Notes ----- For the convolution step, this routine sets pixels beyond the image borders to 0.0. The equivalent parameters in IRAF's `starfind`_ are ``boundary='constant'`` and ``constant=0.0``. IRAF's `starfind`_ uses ``hwhmpsf``, ``fradius``, and ``sepmin`` as input parameters. The equivalent input values for `IRAFStarFinder` are: * ``fwhm = hwhmpsf * 2`` * ``sigma_radius = fradius * sqrt(2.0*log(2.0))`` * ``minsep_fwhm = 0.5 * sepmin`` The main differences between `~photutils.detection.DAOStarFinder` and `~photutils.detection.IRAFStarFinder` are: * `~photutils.detection.IRAFStarFinder` always uses a 2D circular Gaussian kernel, while `~photutils.detection.DAOStarFinder` can use an elliptical Gaussian kernel. * `~photutils.detection.IRAFStarFinder` calculates the objects' centroid, roundness, and sharpness using image moments. See Also -------- DAOStarFinder References ---------- .. [1] https://iraf.net/irafhelp.php?val=starfind .. _starfind: https://iraf.net/irafhelp.php?val=starfind """ def __init__(self, threshold, fwhm, sigma_radius=1.5, minsep_fwhm=2.5, sharplo=0.5, sharphi=2.0, roundlo=0.0, roundhi=0.2, sky=None, exclude_border=False, brightest=None, peakmax=None): if not np.isscalar(threshold): raise TypeError('threshold must be a scalar value.') self.threshold = threshold if not np.isscalar(fwhm): raise TypeError('fwhm must be a scalar value.') self.fwhm = fwhm self.sigma_radius = sigma_radius self.minsep_fwhm = minsep_fwhm self.sharplo = sharplo self.sharphi = sharphi self.roundlo = roundlo self.roundhi = roundhi self.sky = sky self.exclude_border = exclude_border self.min_separation = max(2, int((self.fwhm * self.minsep_fwhm) + 0.5)) self.kernel = _StarFinderKernel(self.fwhm, ratio=1.0, theta=0.0, sigma_radius=self.sigma_radius) self.brightest = brightest self.peakmax = peakmax self._star_cutouts = None def find_stars(self, data, mask=None): """ Find stars in an astronomical image. Parameters ---------- data : 2D array_like The 2D image array. mask : 2D bool array, optional A boolean mask with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Masked pixels are ignored when searching for stars. Returns ------- table : `~astropy.table.Table` or `None` A table of found objects with the following parameters: * ``id``: unique object identification number. * ``xcentroid, ycentroid``: object centroid. * ``fwhm``: object FWHM. * ``sharpness``: object sharpness. * ``roundness``: object roundness. * ``pa``: object position angle (degrees counter clockwise from the positive x axis). * ``npix``: the total number of (positive) unmasked pixels. * ``sky``: the local ``sky`` value. * ``peak``: the peak, sky-subtracted, pixel value of the object. * ``flux``: the object instrumental flux. * ``mag``: the object instrumental magnitude calculated as ``-2.5 * log10(flux)``. `None` is returned if no stars are found. """ star_cutouts = _find_stars(data, self.kernel, self.threshold, min_separation=self.min_separation, mask=mask, exclude_border=self.exclude_border) if star_cutouts is None: warnings.warn('No sources were found.', NoDetectionsWarning) return None self._star_cutouts = star_cutouts star_props = [] for star_cutout in star_cutouts: props = _IRAFStarFindProperties(star_cutout, self.kernel, self.sky) # star cutout needs more than one non-zero value if np.count_nonzero(props.data) <= 1: continue if (props.sharpness <= self.sharplo or props.sharpness >= self.sharphi): continue if (props.roundness <= self.roundlo or props.roundness >= self.roundhi): continue if self.peakmax is not None and props.peak >= self.peakmax: continue star_props.append(props) nstars = len(star_props) if nstars == 0: warnings.warn('Sources were found, but none pass the sharpness ' 'and roundness criteria.', NoDetectionsWarning) return None if self.brightest is not None: fluxes = [props.flux for props in star_props] idx = sorted(np.argsort(fluxes)[-self.brightest:].tolist()) star_props = [star_props[k] for k in idx] nstars = len(star_props) table = Table() table['id'] = np.arange(nstars) + 1 columns = ('xcentroid', 'ycentroid', 'fwhm', 'sharpness', 'roundness', 'pa', 'npix', 'sky', 'peak', 'flux', 'mag') for column in columns: table[column] = [getattr(props, column) for props in star_props] return table photutils-0.7.2/photutils/detection/tests/0000755000214200020070000000000013573510273023117 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/detection/tests/__init__.py0000644000214200020070000000000013563423715025221 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/detection/tests/data/0000755000214200020070000000000013573510273024030 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/detection/tests/data/daofind_test_thresh08.0_fwhm01.0.txt0000644000214200020070000000646413267754154032461 0ustar lbradleySTSCI\science00000000000000id xcentroid ycentroid sharpness roundness1 roundness2 npix sky peak flux mag 1 88.46990059776188 58.48886418244315 0.8762686366344555 0.5208952612806851 -0.4122721184034913 25.0 0.0 41.219046927862664 1.7835016184670074 -0.6281837694550259 2 327.4237440417888 65.44679142919296 0.9157937804266859 0.04525792010641404 0.7509409883712366 25.0 0.0 22.751918266079162 1.0446321071558946 -0.04740842477087964 3 35.3030291035496 100.99885418235492 0.9642784405023673 0.8997709899005626 0.4262749271277977 25.0 0.0 20.102985322609683 1.0144135507640197 -0.015537604949063939 4 207.35081374580741 114.17862428357554 0.8924335237573308 0.9346385083631819 -0.518807699686835 25.0 0.0 29.754644643579955 1.3969918280271438 -0.3629846640809128 5 290.43063459156474 113.06404861735642 0.898082603591199 -0.05099656208774482 -0.23165223978862307 25.0 0.0 46.446092373907746 1.900514493186413 -0.6971779646253444 6 200.92861884647542 131.13339385033788 0.9484922230198581 0.22387509766367475 -0.27402570026586753 25.0 0.0 35.98220832083827 1.0238148922854393 -0.025553606135659993 7 314.47263346346375 129.3969056629089 0.8887239985499058 -0.415497488077957 -0.981667389821615 25.0 0.0 37.2058611011273 1.462461712936029 -0.41271126282013204 8 10.651479210211352 141.89200443111378 0.8874321043149441 0.1038427584432066 0.6135710025317431 25.0 0.0 31.413937832962418 1.033701663235285 -0.035988037644573874 9 125.38583354043459 147.12287931014475 0.9045758881095933 0.018740208509969953 0.9822435679992049 25.0 0.0 47.21336918933935 1.6322194134762291 -0.5319463475288915 10 145.14914494499064 169.8101867232563 0.8849770368050671 0.15624574204422784 0.17519144635671952 25.0 0.0 83.38951276487094 5.207804548890224 -1.7916366915254869 11 394.08757117974244 186.3394174191881 0.8802050226751206 0.35607460226075754 0.09146988324132699 25.0 0.0 110.35005452953492 7.319441130206205 -2.161194805332651 12 206.70671685848117 198.52606581209523 0.8981872955879281 -0.914696580134408 0.03140476242070839 25.0 0.0 34.44956649698919 1.1330527665066235 -0.13562533880024377 13 48.107054682499836 199.00601737015663 0.8865292982659505 -0.25299384635714167 -0.29924860045592516 25.0 0.0 46.62575574744383 1.6718429529072263 -0.5579886972773125 14 426.0377480701111 211.01291166877795 0.8767982886712559 -0.18983407274095807 0.46718907337348503 25.0 0.0 76.36050307691691 4.157089774588257 -1.5469735085756775 15 256.89065375229984 218.8702651417756 0.8919076919119704 -0.6574612471815833 0.9250674332112004 25.0 0.0 31.145480617595414 1.3162412640878085 -0.29833875446097147 16 256.72686483357546 220.39592428590072 0.8657852930536363 -0.6868946128505259 0.7806774957564329 25.0 0.0 35.92343258547273 1.3961484705669713 -0.36232901226396025 17 10.748287200873916 224.20057800236486 0.8530832269725744 -0.6801043879386687 0.5439043607509917 25.0 0.0 55.76846840338447 2.9686701641588544 -1.1814048693326866 18 355.7777559665791 251.24144545680184 0.9076091250435318 0.03794133476381934 0.3071068705575514 25.0 0.0 34.568381338063475 1.194628367857395 -0.19308205841850107 19 140.49990182298185 275.4562630541407 0.8956136505852358 -0.12260502762650799 0.28058974799126774 25.0 0.0 29.39237884586493 1.0140636761486634 -0.015163066319055899 20 434.4873254828115 287.5722770696709 0.9358461422138549 0.7057077340015893 -0.2758037043682071 25.0 0.0 33.411944319652875 1.0657776539076416 -0.06916652543885461 photutils-0.7.2/photutils/detection/tests/data/daofind_test_thresh08.0_fwhm01.5.txt0000644000214200020070000001112213267754154032451 0ustar lbradleySTSCI\science00000000000000id xcentroid ycentroid sharpness roundness1 roundness2 npix sky peak flux mag 1 441.25133516377946 31.44957631443119 0.7184774674544862 0.2540826457659647 0.33820558007054197 25.0 0.0 30.239994137265167 1.0192109043077802 -0.020660153587305028 2 88.79813107802212 58.81911572547198 0.6412388176817487 0.5199389854407557 -0.44797314831347357 25.0 0.0 41.219046927862664 2.4129090339570833 -0.9563523735710178 3 327.7440399874977 64.66175083365357 0.8223868740403482 -0.11894585756005756 0.8073553959462378 25.0 0.0 22.751918266079162 1.1516880702259864 -0.15333717054005433 4 230.91695759765258 65.9894379571403 0.7813631775972321 0.4774209234454751 -0.05879164786084709 25.0 0.0 10.922343382751748 1.022964317973155 -0.02465121336733659 5 99.95188614111407 98.10665397029018 0.9127911170174968 0.5594087143983953 0.8968738122629868 25.0 0.0 24.984494810798402 1.0915006340968902 -0.09505998086117816 6 71.4226160551628 111.66081527853272 0.619266520607775 -0.05983418788263739 0.4400254302666273 25.0 0.0 35.0913969385426 1.2593500685848913 -0.2503661753928418 7 206.54934787497413 114.06617385814583 0.7025595284696313 0.9767349175473904 -0.5834171877869196 25.0 0.0 29.754644643579955 1.7568577222085846 -0.6118414797745659 8 290.7911753889566 113.64828526813636 0.7060267926521758 -0.07996579234428655 -0.22858041274721436 25.0 0.0 46.446092373907746 2.393405398069706 -0.9475406654982715 9 341.27356655729886 114.4587775240903 0.5829404636239032 -0.7700415392818774 -0.3323734952946145 25.0 0.0 28.65755220774481 1.1798300357956324 -0.17954862031485538 10 200.33443823023921 130.4136477492795 0.8372831521724797 0.22155345712781147 -0.23896573945028038 25.0 0.0 35.98220832083827 1.1482404524644518 -0.1500821074451444 11 313.52800888962287 129.7741880324062 0.6842530424213573 -0.3959581050304958 -0.9378705237493801 25.0 0.0 37.2058611011273 1.88054900173178 -0.6857116359467628 12 10.867021165882411 142.54063824155378 0.6947552024609119 0.11878849281679056 0.6710643184520064 25.0 0.0 31.413937832962418 1.3072195133461557 -0.29087130527521743 13 125.13873545366265 148.07110612241445 0.7149614754541866 -0.019729049737502204 0.9618448688309467 25.0 0.0 47.21336918933935 2.04451774222952 -0.776477209234867 14 344.82714268313856 166.27735480015838 0.5551520317059323 0.4640472588827457 -0.18830878258989417 25.0 0.0 27.631382749951754 1.025656792366861 -0.027505151167814216 15 145.04161669340027 168.43979551421813 0.6418746565917449 -0.02736696618181218 0.1153966295770878 25.0 0.0 82.74848117792747 6.884763660996454 -2.0947225911530913 16 394.65502401524253 187.37357173892647 0.6692365367195389 0.3413113809170677 0.08770438935586308 25.0 0.0 110.35005452953492 9.530860217374974 -2.44783025023155 17 480.1442854950754 188.34294135511698 0.9105534140545337 0.8093219184197902 0.9481584847725933 25.0 0.0 23.07234835743072 1.0771739794755455 -0.08071463480942372 18 48.67675424075205 200.4511294253465 0.637320895047539 -0.571948558370518 -0.3831872251686798 25.0 0.0 47.2892911443403 2.2190254912470717 -0.865405728140129 19 426.64088605663267 211.0035331399752 0.6532673887534252 -0.22682231797770286 0.43515782187184765 25.0 0.0 76.36050307691691 5.523929114370442 -1.8556202421835335 20 305.6288921959932 216.1599509336425 0.5855765105365481 -0.007370981867631505 0.3512345640013347 25.0 0.0 26.565020985170975 1.1775541535016305 -0.17745222161727764 21 257.6002296718719 217.77146625690213 0.6907143669914155 -0.6586594988741606 0.9959103449675526 25.0 0.0 31.145480617595414 1.6827007962410163 -0.5650172505850533 22 256.265775002328 220.7587474377063 0.6330394123373777 -0.6815183858246547 0.824192111519761 25.0 0.0 35.92343258547273 1.8904319045703657 -0.691402595542391 23 10.906589762292864 224.07169129851232 0.5915881373471015 -0.7302006348846717 0.4954582336704235 25.0 0.0 55.76846840338447 4.238223669541717 -1.5679596814822927 24 355.91280082770714 252.31749264525953 0.7520228837688127 0.008366802620332457 0.31569853010198345 25.0 0.0 34.568381338063475 1.4274161278306714 -0.38637649844105226 25 139.59065348749309 275.1884233884024 0.7154853585505654 -0.18441687745205232 0.2548543643003899 25.0 0.0 29.39237884586493 1.2567102535141665 -0.24808789627317712 26 121.14388458069425 284.8118762076604 0.7574664205028767 0.18170258067684428 0.16985955244315368 25.0 0.0 12.415425631454825 1.0092893140555754 -0.010039187860971983 27 433.5551160149825 288.4794012861741 0.8097201173279633 0.6995511520935703 -0.27322026456220144 25.0 0.0 33.411944319652875 1.2195121002893914 -0.21546528461092726 28 471.001033909076 297.8111400615592 0.7934292830937713 0.6600959397482591 0.23721748404523008 25.0 0.0 10.524420303596958 1.030199275938046 -0.032303100766317684 photutils-0.7.2/photutils/detection/tests/data/daofind_test_thresh08.0_fwhm02.0.txt0000644000214200020070000001163713267754154032460 0ustar lbradleySTSCI\science00000000000000id xcentroid ycentroid sharpness roundness1 roundness2 npix sky peak flux mag 1 441.3499172083869 31.402878654917814 0.6332823251229039 0.30085528401312445 0.3680354928019628 25.0 0.0 30.239994137265167 1.1572788429613632 -0.15859503387229676 2 0.8496908619052633 40.04305508436788 0.45619405869493956 -0.22810071231008808 0.7232872696244564 25.0 0.0 35.54828630019193 2.6662543983339755 -1.064753962208504 3 88.79956140550843 58.84568931520913 0.5582944988778225 0.5136344718362899 -0.4745844416283111 25.0 0.0 41.219046927862664 2.773675000415222 -1.1076389304199645 4 14.009742492766007 62.28240400026239 0.593724897815523 0.11641944621802239 0.15287632672275359 25.0 0.0 21.481924963251483 1.0271337239470224 -0.029067471679799464 5 327.70218373934637 64.7320262123344 0.8815643782278983 -0.25650986945379883 0.8672581850871744 25.0 0.0 22.751918266079162 1.0752641632256226 -0.07878792932136536 6 230.95864015413127 65.96089819494524 0.7532093773427389 0.5841683591471404 0.017434633001189193 25.0 0.0 10.922343382751748 1.062076683475109 -0.06538968642057963 7 7.328434526380554 69.5156220324513 0.5970223288209795 -0.9902229999019926 -0.36777328827511824 25.0 0.0 33.2880647048335 1.7553590999611413 -0.6109149375862932 8 99.90338602734467 97.94590143760601 0.9369113497949474 0.374463505034526 0.6482107118468855 25.0 0.0 24.984494810798402 1.0642779488426795 -0.0676376598520223 9 34.271919795938956 97.94540042765118 0.43062202850526665 0.9672893343791893 -0.1317036542420994 25.0 0.0 19.27625317566386 1.008392639521492 -0.009074167513830694 10 71.39201494648567 111.67855457865032 0.5196724941219817 -0.07293019182386253 0.3886579935129361 25.0 0.0 35.0913969385426 1.501939736999388 -0.44163126906439054 11 206.5524841594021 114.05764949550421 0.65064321348857 0.9917528207729931 -0.6371226317458737 25.0 0.0 29.754644643579955 1.8986065838796236 -0.696087456404153 12 290.81980079648145 113.6713740964111 0.6430087933779546 -0.09541554335946509 -0.2261751623126485 25.0 0.0 46.446092373907746 2.630139011027921 -1.0499467572765857 13 341.22590232689697 114.47439289227742 0.5191441535865722 -0.8605565678486781 -0.3979504981737904 25.0 0.0 28.65755220774481 1.325909399182182 -0.30628462318182176 14 313.4809249369467 129.79531153878077 0.6196365438299545 -0.36416701339821556 -0.9040072517542573 25.0 0.0 37.2058611011273 2.078368421780885 -0.7943063380385879 15 200.50844425205247 130.3249145251344 0.36839322322757534 0.09087190631722986 -0.22452517495084987 25.0 0.0 31.0622608687501 1.3149161534868317 -0.2972451515721313 16 10.872821371928692 142.50648812470342 0.6466298462154676 0.13850521836332988 0.718945864012764 25.0 0.0 31.413937832962418 1.4056679733123312 -0.36970687498996746 17 124.98844282543168 147.82993328621993 0.4556966042329859 -0.04138895629887515 0.67091498778985 25.0 0.0 45.57926969566492 2.325230959735237 -0.9161652420508276 18 344.7017528266213 166.2683042839413 0.4663098831416211 0.48104307824902254 -0.1252798314146538 25.0 0.0 27.631382749951754 1.2220741014411993 -0.21774385124610166 19 145.03763842687044 168.50637255629331 0.5701020092842325 -0.029731702887011314 0.10804684626541045 25.0 0.0 82.74848117792747 7.757912197426944 -2.2243621500740023 20 394.70347564634125 187.545695732136 0.6053888128969426 -0.17663263158596582 0.15140081222163074 25.0 0.0 111.07213962758318 10.54663671636893 -2.5577849669998876 21 480.1438082712454 188.24825828577048 0.961962354511558 0.7093991969108856 0.8500100573287711 25.0 0.0 23.07234835743072 1.0204491563081264 -0.021978427370778375 22 48.70622094028462 200.38639624622746 0.5563443241052142 -0.5730567456777012 -0.38716010778330917 25.0 0.0 47.2892911443403 2.544104543607104 -1.0138373839688648 23 426.68129895275075 210.99941585113444 0.5819568229039869 -0.25649780804993694 0.4101751816817609 25.0 0.0 76.36050307691691 6.205924359380613 -1.9820161947559602 24 305.66418356557824 216.1095259373655 0.49589375430169474 0.018404255168539715 0.40299126313766576 25.0 0.0 26.565020985170975 1.3916629465991646 -0.35883516046196595 25 10.914912580605002 224.06603573687934 0.5057191364084963 -0.7830489024133768 0.45914226256028107 25.0 0.0 55.76846840338447 4.961946854725386 -1.7391302710501153 26 355.83177174460354 252.09033401412367 0.5247423718988266 -0.01542369728380577 0.03998195526685211 25.0 0.0 35.77616395203726 1.6536995591431092 -0.5461415265566998 27 139.57526527495273 275.22358348387263 0.6714573499096007 -0.2016681835803816 0.23336192730652747 25.0 0.0 29.39237884586493 1.3402186094935478 -0.3179391100037833 28 121.14216985229885 284.808001888565 0.756547266010023 0.1816100396332748 0.29688354539695194 25.0 0.0 12.415425631454825 1.0113492584189694 -0.012252900872686396 29 433.3024759192166 288.60871367718977 0.4437378655853536 0.4050695181704022 -0.2599032109478057 25.0 0.0 29.897454380832716 1.3995809443498977 -0.36499505205356075 30 470.994349464043 297.7565141346699 0.7661467132938748 0.5285364269442019 0.10769026748619974 25.0 0.0 10.524420303596958 1.0677650194503476 -0.07118922259211052 photutils-0.7.2/photutils/detection/tests/data/daofind_test_thresh10.0_fwhm01.0.txt0000644000214200020070000000400613267754154032440 0ustar lbradleySTSCI\science00000000000000id xcentroid ycentroid sharpness roundness1 roundness2 npix sky peak flux mag 1 88.46990059776188 58.48886418244315 0.8762686366344555 0.5208952612806851 -0.4122721184034913 25.0 0.0 41.219046927862664 1.426801294773606 -0.38590873693488487 2 207.35081374580741 114.17862428357554 0.8924335237573308 0.9346385083631819 -0.518807699686835 25.0 0.0 29.754644643579955 1.117593462421715 -0.12070963156077162 3 290.43063459156474 113.06404861735642 0.898082603591199 -0.05099656208774482 -0.23165223978862307 25.0 0.0 46.446092373907746 1.5204115945491306 -0.45490293210520344 4 314.47263346346375 129.3969056629089 0.8887239985499058 -0.415497488077957 -0.981667389821615 25.0 0.0 37.2058611011273 1.169969370348823 -0.17043623029999083 5 125.38583354043459 147.12287931014475 0.9045758881095933 0.018740208509969953 0.9822435679992049 25.0 0.0 47.21336918933935 1.3057755307809833 -0.2896713150087505 6 145.14914494499064 169.8101867232563 0.8849770368050671 0.15624574204422784 0.17519144635671952 25.0 0.0 83.38951276487094 4.166243639112179 -1.5493616590053458 7 394.08757117974244 186.3394174191881 0.8802050226751206 0.35607460226075754 0.09146988324132699 25.0 0.0 110.35005452953492 5.855552904164964 -1.9189197728125098 8 48.107054682499836 199.00601737015663 0.8865292982659505 -0.25299384635714167 -0.29924860045592516 25.0 0.0 46.62575574744383 1.337474362325781 -0.31571366475717144 9 426.0377480701111 211.01291166877795 0.8767982886712559 -0.18983407274095807 0.46718907337348503 25.0 0.0 76.36050307691691 3.3256718196706054 -1.3046984760555367 10 256.89065375229984 218.8702651417756 0.8919076919119704 -0.6574612471815833 0.9250674332112004 25.0 0.0 31.145480617595414 1.0529930112702468 -0.05606372194083043 11 256.72686483357546 220.39592428590072 0.8657852930536363 -0.6868946128505259 0.7806774957564329 25.0 0.0 35.92343258547273 1.116918776453577 -0.12005397974381918 12 10.748287200873916 224.20057800236486 0.8530832269725744 -0.6801043879386687 0.5439043607509917 25.0 0.0 55.76846840338447 2.3749361313270834 -0.9391298368125456 photutils-0.7.2/photutils/detection/tests/data/daofind_test_thresh10.0_fwhm01.5.txt0000644000214200020070000000522313267754154032447 0ustar lbradleySTSCI\science00000000000000id xcentroid ycentroid sharpness roundness1 roundness2 npix sky peak flux mag 1 88.79813107802212 58.81911572547198 0.6412388176817487 0.5199389854407557 -0.44797314831347357 25.0 0.0 41.219046927862664 1.9303272271656666 -0.7140773410508767 2 71.4226160551628 111.66081527853272 0.619266520607775 -0.05983418788263739 0.4400254302666273 25.0 0.0 35.0913969385426 1.007480054867913 -0.008091142872700756 3 206.54934787497413 114.06617385814583 0.7025595284696313 0.9767349175473904 -0.5834171877869196 25.0 0.0 29.754644643579955 1.405486177766868 -0.3695664472544251 4 290.7911753889566 113.64828526813636 0.7060267926521758 -0.07996579234428655 -0.22858041274721436 25.0 0.0 46.446092373907746 1.914724318455765 -0.7052656329781305 5 313.52800888962287 129.7741880324062 0.6842530424213573 -0.3959581050304958 -0.9378705237493801 25.0 0.0 37.2058611011273 1.504439201385424 -0.4434366034266216 6 10.867021165882411 142.54063824155378 0.6947552024609119 0.11878849281679056 0.6710643184520064 25.0 0.0 31.413937832962418 1.0457756106769245 -0.04859627275507633 7 125.13873545366265 148.07110612241445 0.7149614754541866 -0.019729049737502204 0.9618448688309467 25.0 0.0 47.21336918933935 1.6356141937836162 -0.5342021767147259 8 145.04161669340027 168.43979551421813 0.6418746565917449 -0.02736696618181218 0.1153966295770878 25.0 0.0 82.74848117792747 5.507810928797164 -1.8524475586329505 9 394.65502401524253 187.37357173892647 0.6692365367195389 0.3413113809170677 0.08770438935586308 25.0 0.0 110.35005452953492 7.62468817389998 -2.2055552177114084 10 48.67675424075205 200.4511294253465 0.637320895047539 -0.571948558370518 -0.3831872251686798 25.0 0.0 47.2892911443403 1.7752203929976573 -0.6231306956199879 11 426.64088605663267 211.0035331399752 0.6532673887534252 -0.22682231797770286 0.43515782187184765 25.0 0.0 76.36050307691691 4.419143291496353 -1.6133452096633925 12 257.6002296718719 217.77146625690213 0.6907143669914155 -0.6586594988741606 0.9959103449675526 25.0 0.0 31.145480617595414 1.346160636992813 -0.32274221806491205 13 256.265775002328 220.7587474377063 0.6330394123373777 -0.6815183858246547 0.824192111519761 25.0 0.0 35.92343258547273 1.5123455236562926 -0.4491275630222501 14 10.906589762292864 224.07169129851232 0.5915881373471015 -0.7302006348846717 0.4954582336704235 25.0 0.0 55.76846840338447 3.3905789356333735 -1.3256846489621514 15 355.91280082770714 252.31749264525953 0.7520228837688127 0.008366802620332457 0.31569853010198345 25.0 0.0 34.568381338063475 1.1419329022645373 -0.14410146592091136 16 139.59065348749309 275.1884233884024 0.7154853585505654 -0.18441687745205232 0.2548543643003899 25.0 0.0 29.39237884586493 1.0053682028113333 -0.00581286375303618 photutils-0.7.2/photutils/detection/tests/data/daofind_test_thresh10.0_fwhm02.0.txt0000644000214200020070000000645713267754154032455 0ustar lbradleySTSCI\science00000000000000id xcentroid ycentroid sharpness roundness1 roundness2 npix sky peak flux mag 1 0.8496908619052633 40.04305508436788 0.45619405869493956 -0.22810071231008808 0.7232872696244564 25.0 0.0 35.54828630019193 2.1330035186671803 -0.8224789296883628 2 88.79956140550843 58.84568931520913 0.5582944988778225 0.5136344718362899 -0.4745844416283111 25.0 0.0 41.219046927862664 2.2189400003321778 -0.8653638978998236 3 7.328434526380554 69.5156220324513 0.5970223288209795 -0.9902229999019926 -0.36777328827511824 25.0 0.0 33.2880647048335 1.404287279968913 -0.3686399050661522 4 71.39201494648567 111.67855457865032 0.5196724941219817 -0.07293019182386253 0.3886579935129361 25.0 0.0 35.0913969385426 1.2015517895995103 -0.19935623654424928 5 206.5524841594021 114.05764949550421 0.65064321348857 0.9917528207729931 -0.6371226317458737 25.0 0.0 29.754644643579955 1.5188852671036988 -0.45381242388401194 6 290.81980079648145 113.6713740964111 0.6430087933779546 -0.09541554335946509 -0.2261751623126485 25.0 0.0 46.446092373907746 2.1041112088223364 -0.8076717247564446 7 341.22590232689697 114.47439289227742 0.5191441535865722 -0.8605565678486781 -0.3979504981737904 25.0 0.0 28.65755220774481 1.0607275193457455 -0.0640095906616806 8 313.4809249369467 129.79531153878077 0.6196365438299545 -0.36416701339821556 -0.9040072517542573 25.0 0.0 37.2058611011273 1.662694737424708 -0.5520313055184468 9 200.50844425205247 130.3249145251344 0.36839322322757534 0.09087190631722986 -0.22452517495084987 25.0 0.0 31.0622608687501 1.0519329227894652 -0.0549701190519901 10 10.872821371928692 142.50648812470342 0.6466298462154676 0.13850521836332988 0.718945864012764 25.0 0.0 31.413937832962418 1.124534378649865 -0.12743184246982645 11 124.98844282543168 147.82993328621993 0.4556966042329859 -0.04138895629887515 0.67091498778985 25.0 0.0 45.57926969566492 1.8601847677881895 -0.6738902095306866 12 145.03763842687044 168.50637255629331 0.5701020092842325 -0.029731702887011314 0.10804684626541045 25.0 0.0 82.74848117792747 6.206329757941555 -1.9820871175538612 13 394.70347564634125 187.545695732136 0.6053888128969426 -0.17663263158596582 0.15140081222163074 25.0 0.0 111.07213962758318 8.437309373095143 -2.315509934479746 14 48.70622094028462 200.38639624622746 0.5563443241052142 -0.5730567456777012 -0.38716010778330917 25.0 0.0 47.2892911443403 2.035283634885683 -0.7715623514487234 15 426.68129895275075 210.99941585113444 0.5819568229039869 -0.25649780804993694 0.4101751816817609 25.0 0.0 76.36050307691691 4.96473948750449 -1.7397411622358192 16 305.66418356557824 216.1095259373655 0.49589375430169474 0.018404255168539715 0.40299126313766576 25.0 0.0 26.565020985170975 1.1133303572793316 -0.11656012794182484 17 10.914912580605002 224.06603573687934 0.5057191364084963 -0.7830489024133768 0.45914226256028107 25.0 0.0 55.76846840338447 3.9695574837803087 -1.4968552385299745 18 355.83177174460354 252.09033401412367 0.5247423718988266 -0.01542369728380577 0.03998195526685211 25.0 0.0 35.77616395203726 1.3229596473144873 -0.3038664940365588 19 139.57526527495273 275.22358348387263 0.6714573499096007 -0.2016681835803816 0.23336192730652747 25.0 0.0 29.39237884586493 1.072174887594838 -0.07566407748364207 20 433.3024759192166 288.60871367718977 0.4437378655853536 0.4050695181704022 -0.2599032109478057 25.0 0.0 29.897454380832716 1.1196647554799182 -0.12272001953341974 photutils-0.7.2/photutils/detection/tests/data/irafstarfind_test_thresh08.0_fwhm01.0.txt0000644000214200020070000000232313267754154033517 0ustar lbradleySTSCI\science00000000000000id xcentroid ycentroid fwhm sharpness roundness pa npix sky peak flux mag 1 333.32967620268926 0.4922715732671872 1.2389649115388133 1.2389649115388133 0.1632730683139897 26.751332591232657 5.0 2.757612577414644 7.470385598813738 17.87026271806645 -3.1303273432349914 2 145.0334216330022 168.39799687136576 1.8918921328609848 1.8918921328609848 0.028604480029024524 118.25194333308633 12.0 16.46507005975501 66.92444270511594 406.86074671794165 -6.523614479572233 3 394.7628492905675 187.59049488469253 1.8259269954390203 1.8259269954390203 0.10712610861905057 131.1948064263936 11.0 20.151710346274722 90.92042928130846 527.6471044360048 -6.80585889802106 4 89.21399519459558 198.23805598325862 1.9699369976778611 1.9699369976778611 0.140512496831343 139.49061946497739 10.0 5.046355096294733 8.916265520602554 20.380914697547418 -3.2730591782220264 5 355.940683491333 251.70235184396 1.7522952194564725 1.7522952194564725 0.11598331430783908 52.09576852830077 10.0 19.585761501344383 16.190402450692876 88.75108703293594 -4.870434202614015 6 378.5365504434283 273.08553439796117 1.9282124502623856 1.9282124502623856 0.09786276609110564 14.700858135363946 8.0 4.744381064470213 8.45586154664661 18.53113999199971 -3.1697553422808005 photutils-0.7.2/photutils/detection/tests/data/irafstarfind_test_thresh08.0_fwhm01.5.txt0000644000214200020070000000504313267754154033526 0ustar lbradleySTSCI\science00000000000000id xcentroid ycentroid fwhm sharpness roundness pa npix sky peak flux mag 1 333.32967620268926 0.4922715732671872 1.2389649115388133 0.8259766076925422 0.1632730683139897 26.751332591232657 5.0 2.757612577414644 7.470385598813738 17.87026271806645 -3.1303273432349914 2 230.98520543324977 65.96062094855215 1.1045257887737336 0.7363505258491557 0.08474087768196263 175.16563683708682 7.0 4.906490485436556 6.015852897315193 10.355696896573836 -2.5379483261935247 3 71.21785006913522 111.76487474565829 2.041287275833218 1.360858183888812 0.13679659319094278 77.80260478241559 11.0 21.001696161595063 14.089700776947538 107.15742741630842 -5.075055696823615 4 290.88594008616707 113.76868287298815 2.0132511884469353 1.3421674589646235 0.09921593553744701 172.63151133250068 12.0 21.19225795812126 25.253834415786486 157.2638285640319 -5.491572110730435 5 200.23683161129125 130.21911528245474 2.068730352200946 1.3791535681339642 0.0772733520073215 8.31574194223727 13.0 20.931309472117615 15.050898848720653 96.98092311348633 -4.966715784084392 6 344.3860440796261 166.22517276873882 1.8853557992763632 1.2569038661842422 0.11363886565891375 142.91674058093935 11.0 18.685078458637985 11.30249791672627 62.9878292683161 -4.498141604100731 7 145.04228403850357 168.6571618278717 1.9066993974327817 1.2711329316218545 0.01132060172865575 34.75701626174368 12.0 16.35083410366516 67.03867866120578 413.9858186416701 -6.5424636608266695 8 394.7628492905675 187.59049488469253 1.8259269954390203 1.2172846636260135 0.10712610861905057 131.1948064263936 11.0 20.151710346274722 90.92042928130846 527.6471044360048 -6.80585889802106 9 243.47516596181347 197.2493890490569 1.7827428108977648 1.1884952072651764 0.17856028127225676 98.90230482066524 8.0 14.345012293985468 8.2293190831917 34.45785068493779 -3.843220461887511 10 439.9142185199256 197.98835995057703 1.431190377976779 0.9541269186511859 0.14568617232313683 165.69248581691983 8.0 5.521741711694806 6.475686441345677 12.410831724229434 -2.734502217876459 11 48.84191877412477 200.23603953697418 2.044906279964065 1.3632708533093767 0.15397555058991969 8.669913148933764 13.0 21.891667190520494 25.397623953819803 185.00884809430943 -5.667981247854074 12 305.8226567441267 215.56678011460988 1.8118994096837677 1.2079329397891785 0.15302459233581697 71.90351161795856 10.0 16.561617853554058 12.39941531540315 70.11439579638966 -4.614517989747707 13 355.940683491333 251.70235184396 1.7522952194564725 1.1681968129709817 0.11598331430783908 52.09576852830077 10.0 19.585761501344383 16.190402450692876 88.75108703293594 -4.870434202614015 photutils-0.7.2/photutils/detection/tests/data/irafstarfind_test_thresh08.0_fwhm02.0.txt0000644000214200020070000000616513267754154033530 0ustar lbradleySTSCI\science00000000000000id xcentroid ycentroid fwhm sharpness roundness pa npix sky peak flux mag 1 0.9463803041037677 40.05930171275073 2.1172882811901297 1.0586441405950648 0.15700998967332774 103.73294282811226 12.0 12.639904993835687 22.908381306356247 185.7046678317134 -5.672057050519047 2 13.990504104618 62.55334108277186 1.9112198263358675 0.9556099131679338 0.15520530817401776 50.54366391030623 11.0 13.70300905281337 7.8569227383370634 45.67009375413011 -4.14907975787997 3 230.98520543324977 65.96062094855215 1.1045257887737336 0.5522628943868668 0.08474087768196263 175.16563683708682 7.0 4.906490485436556 6.015852897315193 10.355696896573836 -2.5379483261935247 4 71.21785006913522 111.76487474565829 2.041287275833218 1.020643637916609 0.13679659319094278 77.80260478241559 11.0 21.001696161595063 14.089700776947538 107.15742741630842 -5.075055696823615 5 290.88594008616707 113.76868287298815 2.0132511884469353 1.0066255942234676 0.09921593553744701 172.63151133250068 12.0 21.19225795812126 25.253834415786486 157.2638285640319 -5.491572110730435 6 476.3854019214201 123.17381910435793 1.9095864585977254 0.9547932292988627 0.049460563907413366 141.18558248492255 10.0 13.976425258573249 7.392939939729255 49.30462300038852 -4.232219105973428 7 344.3860440796261 166.22517276873882 1.8853557992763632 0.9426778996381816 0.11363886565891375 142.91674058093935 11.0 18.685078458637985 11.30249791672627 62.9878292683161 -4.498141604100731 8 145.04228403850357 168.6571618278717 1.9066993974327817 0.9533496987163909 0.01132060172865575 34.75701626174368 12.0 16.35083410366516 67.03867866120578 413.9858186416701 -6.5424636608266695 9 433.96150057644644 172.11618975119973 1.5605837424622429 0.7802918712311214 0.09193780106796648 95.87470166499466 8.0 4.626744929765067 5.595633376366347 17.514050923880667 -3.1084665203219473 10 394.77243654370204 187.3653258347458 1.8382851657518942 0.9191425828759471 0.07664537864845197 57.84086299955225 11.0 20.06339188622815 91.00874774135504 535.3679088447971 -6.821630837610465 11 243.47516596181347 197.2493890490569 1.7827428108977648 0.8913714054488824 0.17856028127225676 98.90230482066524 8.0 14.345012293985468 8.2293190831917 34.45785068493779 -3.843220461887511 12 439.9142185199256 197.98835995057703 1.431190377976779 0.7155951889883895 0.14568617232313683 165.69248581691983 8.0 5.521741711694806 6.475686441345677 12.410831724229434 -2.734502217876459 13 48.84191877412477 200.23603953697418 2.044906279964065 1.0224531399820325 0.15397555058991969 8.669913148933764 13.0 21.891667190520494 25.397623953819803 185.00884809430943 -5.667981247854074 14 305.8226567441267 215.56678011460988 1.8118994096837677 0.9059497048418839 0.15302459233581697 71.90351161795856 10.0 16.561617853554058 12.39941531540315 70.11439579638966 -4.614517989747707 15 292.1680865716507 245.66007865305278 1.9132639276510426 0.9566319638255213 0.13981297941973697 131.64176988617768 12.0 17.382922811106205 26.281111155294354 151.39790010868757 -5.450299628835927 16 355.815359095706 252.07315473269793 2.040873269492875 1.0204366347464375 0.04014555235557765 166.92243604044648 13.0 20.266399267107513 15.509764684929745 112.63065620256117 -5.129141535958461 photutils-0.7.2/photutils/detection/tests/data/irafstarfind_test_thresh10.0_fwhm01.0.txt0000644000214200020070000000121613267754154033510 0ustar lbradleySTSCI\science00000000000000id xcentroid ycentroid fwhm sharpness roundness pa npix sky peak flux mag 1 145.0334216330022 168.39799687136576 1.8918921328609848 1.8918921328609848 0.028604480029024524 118.25194333308633 12.0 16.46507005975501 66.92444270511594 406.86074671794165 -6.523614479572233 2 394.7628492905675 187.59049488469253 1.8259269954390203 1.8259269954390203 0.10712610861905057 131.1948064263936 11.0 20.151710346274722 90.92042928130846 527.6471044360048 -6.80585889802106 3 355.940683491333 251.70235184396 1.7522952194564725 1.7522952194564725 0.11598331430783908 52.09576852830077 10.0 19.585761501344383 16.190402450692876 88.75108703293594 -4.870434202614015 photutils-0.7.2/photutils/detection/tests/data/irafstarfind_test_thresh10.0_fwhm01.5.txt0000644000214200020070000000262713267754154033524 0ustar lbradleySTSCI\science00000000000000id xcentroid ycentroid fwhm sharpness roundness pa npix sky peak flux mag 1 71.21785006913522 111.76487474565829 2.041287275833218 1.360858183888812 0.13679659319094278 77.80260478241559 11.0 21.001696161595063 14.089700776947538 107.15742741630842 -5.075055696823615 2 290.88594008616707 113.76868287298815 2.0132511884469353 1.3421674589646235 0.09921593553744701 172.63151133250068 12.0 21.19225795812126 25.253834415786486 157.2638285640319 -5.491572110730435 3 145.04228403850357 168.6571618278717 1.9066993974327817 1.2711329316218545 0.01132060172865575 34.75701626174368 12.0 16.35083410366516 67.03867866120578 413.9858186416701 -6.5424636608266695 4 394.7628492905675 187.59049488469253 1.8259269954390203 1.2172846636260135 0.10712610861905057 131.1948064263936 11.0 20.151710346274722 90.92042928130846 527.6471044360048 -6.80585889802106 5 48.84191877412477 200.23603953697418 2.044906279964065 1.3632708533093767 0.15397555058991969 8.669913148933764 13.0 21.891667190520494 25.397623953819803 185.00884809430943 -5.667981247854074 6 305.8226567441267 215.56678011460988 1.8118994096837677 1.2079329397891785 0.15302459233581697 71.90351161795856 10.0 16.561617853554058 12.39941531540315 70.11439579638966 -4.614517989747707 7 355.940683491333 251.70235184396 1.7522952194564725 1.1681968129709817 0.11598331430783908 52.09576852830077 10.0 19.585761501344383 16.190402450692876 88.75108703293594 -4.870434202614015 photutils-0.7.2/photutils/detection/tests/data/irafstarfind_test_thresh10.0_fwhm02.0.txt0000644000214200020070000000374713267754154033524 0ustar lbradleySTSCI\science00000000000000id xcentroid ycentroid fwhm sharpness roundness pa npix sky peak flux mag 1 0.9463803041037677 40.05930171275073 2.1172882811901297 1.0586441405950648 0.15700998967332774 103.73294282811226 12.0 12.639904993835687 22.908381306356247 185.7046678317134 -5.672057050519047 2 71.21785006913522 111.76487474565829 2.041287275833218 1.020643637916609 0.13679659319094278 77.80260478241559 11.0 21.001696161595063 14.089700776947538 107.15742741630842 -5.075055696823615 3 290.88594008616707 113.76868287298815 2.0132511884469353 1.0066255942234676 0.09921593553744701 172.63151133250068 12.0 21.19225795812126 25.253834415786486 157.2638285640319 -5.491572110730435 4 344.3860440796261 166.22517276873882 1.8853557992763632 0.9426778996381816 0.11363886565891375 142.91674058093935 11.0 18.685078458637985 11.30249791672627 62.9878292683161 -4.498141604100731 5 145.04228403850357 168.6571618278717 1.9066993974327817 0.9533496987163909 0.01132060172865575 34.75701626174368 12.0 16.35083410366516 67.03867866120578 413.9858186416701 -6.5424636608266695 6 394.77243654370204 187.3653258347458 1.8382851657518942 0.9191425828759471 0.07664537864845197 57.84086299955225 11.0 20.06339188622815 91.00874774135504 535.3679088447971 -6.821630837610465 7 48.84191877412477 200.23603953697418 2.044906279964065 1.0224531399820325 0.15397555058991969 8.669913148933764 13.0 21.891667190520494 25.397623953819803 185.00884809430943 -5.667981247854074 8 305.8226567441267 215.56678011460988 1.8118994096837677 0.9059497048418839 0.15302459233581697 71.90351161795856 10.0 16.561617853554058 12.39941531540315 70.11439579638966 -4.614517989747707 9 292.1680865716507 245.66007865305278 1.9132639276510426 0.9566319638255213 0.13981297941973697 131.64176988617768 12.0 17.382922811106205 26.281111155294354 151.39790010868757 -5.450299628835927 10 355.815359095706 252.07315473269793 2.040873269492875 1.0204366347464375 0.04014555235557765 166.92243604044648 13.0 20.266399267107513 15.509764684929745 112.63065620256117 -5.129141535958461 photutils-0.7.2/photutils/detection/tests/test_core.py0000644000214200020070000002172413572573665025503 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the core module. """ import warnings from astropy.tests.helper import assert_quantity_allclose, catch_warnings import numpy as np from numpy.testing import assert_allclose, assert_array_equal import pytest from ..core import detect_threshold, find_peaks from ...centroids import centroid_com from ...datasets import make_4gaussians_image, make_gwcs, make_wcs from ...utils.exceptions import NoDetectionsWarning try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False try: # shared WCS interface requires gwcs >= 0.10 import gwcs # noqa HAS_GWCS = True except ImportError: HAS_GWCS = False DATA = np.array([[0, 1, 0], [0, 2, 0], [0, 0, 0]]).astype(float) REF1 = np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]]) PEAKDATA = np.array([[1, 0, 0], [0, 0, 0], [0, 0, 1]]).astype(float) PEAKREF1 = np.array([[0, 0], [2, 2]]) IMAGE = make_4gaussians_image() FITSWCS = make_wcs(IMAGE.shape) @pytest.mark.skipif('not HAS_SCIPY') class TestDetectThreshold: def test_nsigma(self): """Test basic nsigma.""" threshold = detect_threshold(DATA, nsigma=0.1) ref = 0.4 * np.ones((3, 3)) assert_allclose(threshold, ref) def test_nsigma_zero(self): """Test nsigma=0.""" threshold = detect_threshold(DATA, nsigma=0.0) ref = (1. / 3.) * np.ones((3, 3)) assert_allclose(threshold, ref) def test_background(self): threshold = detect_threshold(DATA, nsigma=1.0, background=1) ref = (5. / 3.) * np.ones((3, 3)) assert_allclose(threshold, ref) def test_background_image(self): background = np.ones((3, 3)) threshold = detect_threshold(DATA, nsigma=1.0, background=background) ref = (5. / 3.) * np.ones((3, 3)) assert_allclose(threshold, ref) def test_background_badshape(self): wrong_shape = np.zeros((2, 2)) with pytest.raises(ValueError): detect_threshold(DATA, nsigma=2., background=wrong_shape) def test_error(self): threshold = detect_threshold(DATA, nsigma=1.0, error=1) ref = (4. / 3.) * np.ones((3, 3)) assert_allclose(threshold, ref) def test_error_image(self): error = np.ones((3, 3)) threshold = detect_threshold(DATA, nsigma=1.0, error=error) ref = (4. / 3.) * np.ones((3, 3)) assert_allclose(threshold, ref) def test_error_badshape(self): wrong_shape = np.zeros((2, 2)) with pytest.raises(ValueError): detect_threshold(DATA, nsigma=2., error=wrong_shape) def test_background_error(self): threshold = detect_threshold(DATA, nsigma=2.0, background=10., error=1.) ref = 12. * np.ones((3, 3)) assert_allclose(threshold, ref) def test_background_error_images(self): background = np.ones((3, 3)) * 10. error = np.ones((3, 3)) threshold = detect_threshold(DATA, nsigma=2.0, background=background, error=error) ref = 12. * np.ones((3, 3)) assert_allclose(threshold, ref) def test_mask_value(self): """Test detection with mask_value.""" threshold = detect_threshold(DATA, nsigma=1.0, mask_value=0.0) ref = 2. * np.ones((3, 3)) assert_array_equal(threshold, ref) def test_image_mask(self): """ Test detection with image_mask. Set sigma=10 and iters=1 to prevent sigma clipping after applying the mask. """ mask = REF1.astype(bool) threshold = detect_threshold(DATA, nsigma=1., error=0, mask=mask, sigclip_sigma=10, sigclip_iters=1) ref = (1. / 8.) * np.ones((3, 3)) assert_array_equal(threshold, ref) def test_image_mask_override(self): """Test that image_mask overrides mask_value.""" mask = REF1.astype(bool) threshold = detect_threshold(DATA, nsigma=0.1, error=0, mask_value=0.0, mask=mask, sigclip_sigma=10, sigclip_iters=1) ref = np.ones((3, 3)) assert_array_equal(threshold, ref) @pytest.mark.skipif('not HAS_SCIPY') class TestFindPeaks: def test_box_size(self): """Test with box_size.""" tbl = find_peaks(PEAKDATA, 0.1, box_size=3) assert_array_equal(tbl['x_peak'], PEAKREF1[:, 1]) assert_array_equal(tbl['y_peak'], PEAKREF1[:, 0]) assert_array_equal(tbl['peak_value'], [1., 1.]) def test_footprint(self): """Test with footprint.""" tbl = find_peaks(PEAKDATA, 0.1, footprint=np.ones((3, 3))) assert_array_equal(tbl['x_peak'], PEAKREF1[:, 1]) assert_array_equal(tbl['y_peak'], PEAKREF1[:, 0]) assert_array_equal(tbl['peak_value'], [1., 1.]) def test_mask(self): """Test with mask.""" mask = np.zeros(PEAKDATA.shape, dtype=bool) mask[0, 0] = True tbl = find_peaks(PEAKDATA, 0.1, box_size=3, mask=mask) assert len(tbl) == 1 assert_array_equal(tbl['x_peak'], PEAKREF1[1, 0]) assert_array_equal(tbl['y_peak'], PEAKREF1[1, 1]) assert_array_equal(tbl['peak_value'], 1.0) def test_maskshape(self): """Test if make shape doesn't match data shape.""" with pytest.raises(ValueError): find_peaks(PEAKDATA, 0.1, mask=np.ones((5, 5))) def test_thresholdshape(self): """Test if threshold shape doesn't match data shape.""" with pytest.raises(ValueError): find_peaks(PEAKDATA, np.ones((2, 2))) def test_npeaks(self): """Test npeaks.""" tbl = find_peaks(PEAKDATA, 0.1, box_size=3, npeaks=1) assert_array_equal(tbl['x_peak'], PEAKREF1[1, 1]) assert_array_equal(tbl['y_peak'], PEAKREF1[1, 0]) def test_border_width(self): """Test border exclusion.""" with catch_warnings(NoDetectionsWarning) as warning_lines: tbl = find_peaks(PEAKDATA, 0.1, box_size=3, border_width=3) assert tbl is None assert warning_lines[0].category == NoDetectionsWarning assert ('No local peaks were found.' in str(warning_lines[0].message)) def test_box_size_int(self): """Test non-integer box_size.""" tbl1 = find_peaks(PEAKDATA, 0.1, box_size=5.) tbl2 = find_peaks(PEAKDATA, 0.1, box_size=5.5) assert_array_equal(tbl1, tbl2) def test_centroid_func_callable(self): """Test that centroid_func is callable.""" with pytest.raises(TypeError): find_peaks(PEAKDATA, 0.1, box_size=2, centroid_func=True) def test_wcs(self): """Test with astropy WCS.""" columns = ['skycoord_peak', 'skycoord_centroid'] tbl = find_peaks(IMAGE, 100, wcs=FITSWCS, centroid_func=centroid_com) for column in columns: assert column in tbl.colnames @pytest.mark.skipif('not HAS_GWCS') def test_gwcs(self): """Test with gwcs.""" columns = ['skycoord_peak', 'skycoord_centroid'] gwcs_obj = make_gwcs(IMAGE.shape) tbl = find_peaks(IMAGE, 100, wcs=gwcs_obj, centroid_func=centroid_com) for column in columns: assert column in tbl.colnames @pytest.mark.skipif('not HAS_GWCS') def test_wcs_values(self): gwcs_obj = make_gwcs(IMAGE.shape) tbl1 = find_peaks(IMAGE, 100, wcs=FITSWCS, centroid_func=centroid_com) tbl2 = find_peaks(IMAGE, 100, wcs=gwcs_obj, centroid_func=centroid_com) columns = ['skycoord_peak', 'skycoord_centroid'] for column in columns: assert_quantity_allclose(tbl1[column].ra, tbl2[column].ra) assert_quantity_allclose(tbl1[column].dec, tbl2[column].dec) def test_constant_array(self): """Test for empty output table when data is constant.""" data = np.ones((10, 10)) with catch_warnings(NoDetectionsWarning) as warning_lines: tbl = find_peaks(data, 0.) assert tbl is None assert warning_lines[0].category == NoDetectionsWarning assert ('Input data is constant.' in str(warning_lines[0].message)) def test_no_peaks(self): """ Test for an empty output table with the expected column names when no peaks are found. """ tbl = find_peaks(IMAGE, 10000) assert tbl is None tbl = find_peaks(IMAGE, 100000, centroid_func=centroid_com) assert tbl is None tbl = find_peaks(IMAGE, 100000, wcs=FITSWCS) assert tbl is None tbl = find_peaks(IMAGE, 100000, wcs=FITSWCS, centroid_func=centroid_com) assert tbl is None def test_data_nans(self): """Test that data with NaNs does not issue Runtime warning.""" data = np.copy(PEAKDATA) data[1, 1] = np.nan with warnings.catch_warnings(): warnings.filterwarnings('error') find_peaks(data, 0.) photutils-0.7.2/photutils/detection/tests/test_findstars.py0000644000214200020070000002422213563423715026532 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the findstars module. """ import itertools import os.path as op from astropy.table import Table from astropy.tests.helper import catch_warnings import numpy as np from numpy.testing import assert_allclose import pytest from ..findstars import DAOStarFinder, IRAFStarFinder from ...datasets import make_100gaussians_image from ...utils.exceptions import NoDetectionsWarning try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False DATA = make_100gaussians_image() THRESHOLDS = [8.0, 10.0] FWHMS = [1.0, 1.5, 2.0] @pytest.mark.skipif('not HAS_SCIPY') class TestDAOStarFinder: @pytest.mark.parametrize(('threshold', 'fwhm'), list(itertools.product(THRESHOLDS, FWHMS))) def test_daofind(self, threshold, fwhm): starfinder = DAOStarFinder(threshold, fwhm, sigma_radius=1.5) tbl = starfinder(DATA) datafn = ('daofind_test_thresh{0:04.1f}_fwhm{1:04.1f}' '.txt'.format(threshold, fwhm)) datafn = op.join(op.dirname(op.abspath(__file__)), 'data', datafn) tbl_ref = Table.read(datafn, format='ascii') assert tbl.colnames == tbl_ref.colnames for col in tbl.colnames: assert_allclose(tbl[col], tbl_ref[col]) def test_daofind_threshold_fwhm_inputs(self): with pytest.raises(TypeError): DAOStarFinder(threshold=np.ones((2, 2)), fwhm=3.) with pytest.raises(TypeError): DAOStarFinder(threshold=3., fwhm=np.ones((2, 2))) def test_daofind_include_border(self): starfinder = DAOStarFinder(threshold=10, fwhm=2, sigma_radius=1.5, exclude_border=False) tbl = starfinder(DATA) assert len(tbl) == 20 def test_daofind_exclude_border(self): starfinder = DAOStarFinder(threshold=10, fwhm=2, sigma_radius=1.5, exclude_border=True) tbl = starfinder(DATA) assert len(tbl) == 19 def test_daofind_nosources(self): data = np.ones((3, 3)) with catch_warnings(NoDetectionsWarning) as warning_lines: starfinder = DAOStarFinder(threshold=10, fwhm=1) tbl = starfinder(data) assert tbl is None assert warning_lines[0].category == NoDetectionsWarning assert 'No sources were found.' in str(warning_lines[0].message) def test_daofind_sharpness(self): """Sources found, but none pass the sharpness criteria.""" with catch_warnings(NoDetectionsWarning) as warning_lines: starfinder = DAOStarFinder(threshold=50, fwhm=1.0, sharplo=1.) tbl = starfinder(DATA) assert tbl is None assert warning_lines[0].category == NoDetectionsWarning assert ('Sources were found, but none pass the sharpness and ' 'roundness criteria.' in str(warning_lines[0].message)) def test_daofind_roundness(self): """Sources found, but none pass the roundness criteria.""" with catch_warnings(NoDetectionsWarning) as warning_lines: starfinder = DAOStarFinder(threshold=50, fwhm=1.0, roundlo=1.) tbl = starfinder(DATA) assert tbl is None assert warning_lines[0].category == NoDetectionsWarning assert ('Sources were found, but none pass the sharpness and ' 'roundness criteria.' in str(warning_lines[0].message)) def test_daofind_flux_negative(self): """Test handling of negative flux (here created by large sky).""" data = np.ones((5, 5)) data[2, 2] = 10. starfinder = DAOStarFinder(threshold=0.1, fwhm=1.0, sky=10) tbl = starfinder(data) assert not np.isfinite(tbl['mag']) def test_daofind_negative_fit_peak(self): """ Regression test that sources with negative fit peaks (i.e. hx/hy<=0) are excluded. """ starfinder = DAOStarFinder(threshold=7., fwhm=1.5, roundlo=-np.inf, roundhi=np.inf, sharplo=-np.inf, sharphi=np.inf) tbl = starfinder(DATA) assert len(tbl) == 102 def test_daofind_peakmax_filtering(self): """ Regression test that objects with ``peak`` >= ``peakmax`` are filtered out. """ peakmax = 20 starfinder = DAOStarFinder(threshold=7., fwhm=1.5, roundlo=-np.inf, roundhi=np.inf, sharplo=-np.inf, sharphi=np.inf, peakmax=peakmax) tbl = starfinder(DATA) assert len(tbl) == 37 assert all(tbl['peak'] < peakmax) def test_daofind_brightest_filtering(self): """ Regression test that only top ``brightest`` objects are selected. """ brightest = 40 peakmax = 20 starfinder = DAOStarFinder(threshold=7., fwhm=1.5, roundlo=-np.inf, roundhi=np.inf, sharplo=-np.inf, sharphi=np.inf, brightest=brightest) tbl = starfinder(DATA) # combined with peakmax assert len(tbl) == brightest starfinder = DAOStarFinder(threshold=7., fwhm=1.5, roundlo=-np.inf, roundhi=np.inf, sharplo=-np.inf, sharphi=np.inf, brightest=brightest, peakmax=peakmax) tbl = starfinder(DATA) assert len(tbl) == 37 def test_daofind_mask(self): """Test DAOStarFinder with a mask.""" starfinder = DAOStarFinder(threshold=10, fwhm=1.5) mask = np.zeros(DATA.shape, dtype=bool) mask[100:200] = True tbl1 = starfinder(DATA) tbl2 = starfinder(DATA, mask=mask) assert len(tbl1) > len(tbl2) @pytest.mark.skipif('not HAS_SCIPY') class TestIRAFStarFinder: @pytest.mark.parametrize(('threshold', 'fwhm'), list(itertools.product(THRESHOLDS, FWHMS))) def test_irafstarfind(self, threshold, fwhm): starfinder = IRAFStarFinder(threshold, fwhm, sigma_radius=1.5) tbl = starfinder(DATA) datafn = ('irafstarfind_test_thresh{0:04.1f}_fwhm{1:04.1f}' '.txt'.format(threshold, fwhm)) datafn = op.join(op.dirname(op.abspath(__file__)), 'data', datafn) tbl_ref = Table.read(datafn, format='ascii') assert tbl.colnames == tbl_ref.colnames for col in tbl.colnames: assert_allclose(tbl[col], tbl_ref[col]) def test_irafstarfind_threshold_fwhm_inputs(self): with pytest.raises(TypeError): IRAFStarFinder(threshold=np.ones((2, 2)), fwhm=3.) with pytest.raises(TypeError): IRAFStarFinder(threshold=3., fwhm=np.ones((2, 2))) def test_irafstarfind_nosources(self): data = np.ones((3, 3)) with catch_warnings(NoDetectionsWarning) as warning_lines: starfinder = IRAFStarFinder(threshold=10, fwhm=1) tbl = starfinder(data) assert tbl is None assert warning_lines[0].category == NoDetectionsWarning assert 'No sources were found.' in str(warning_lines[0].message) def test_irafstarfind_sharpness(self): """Sources found, but none pass the sharpness criteria.""" with catch_warnings(NoDetectionsWarning) as warning_lines: starfinder = IRAFStarFinder(threshold=50, fwhm=1.0, sharplo=2.) tbl = starfinder(DATA) assert tbl is None assert warning_lines[0].category == NoDetectionsWarning assert ('Sources were found, but none pass the sharpness and ' 'roundness criteria.' in str(warning_lines[0].message)) def test_irafstarfind_roundness(self): """Sources found, but none pass the roundness criteria.""" with catch_warnings(NoDetectionsWarning) as warning_lines: starfinder = IRAFStarFinder(threshold=50, fwhm=1.0, roundlo=1.) tbl = starfinder(DATA) assert tbl is None assert warning_lines[0].category == NoDetectionsWarning assert ('Sources were found, but none pass the sharpness and ' 'roundness criteria.' in str(warning_lines[0].message)) def test_irafstarfind_sky(self): starfinder = IRAFStarFinder(threshold=25.0, fwhm=2.0, sky=10.) tbl = starfinder(DATA) assert len(tbl) == 4 def test_irafstarfind_largesky(self): with catch_warnings(NoDetectionsWarning) as warning_lines: starfinder = IRAFStarFinder(threshold=25.0, fwhm=2.0, sky=100.) tbl = starfinder(DATA) assert tbl is None assert warning_lines[0].category == NoDetectionsWarning assert ('Sources were found, but none pass the sharpness and ' 'roundness criteria.' in str(warning_lines[0].message)) def test_irafstarfind_peakmax_filtering(self): """ Regression test that objects with ``peak`` >= ``peakmax`` are filtered out. """ peakmax = 20 starfinder = IRAFStarFinder(threshold=7., fwhm=2, roundlo=-np.inf, roundhi=np.inf, sharplo=-np.inf, sharphi=np.inf, peakmax=peakmax) tbl = starfinder(DATA) assert len(tbl) == 117 assert all(tbl['peak'] < peakmax) def test_irafstarfind_brightest_filtering(self): """ Regression test that only top ``brightest`` objects are selected. """ brightest = 40 starfinder = IRAFStarFinder(threshold=7., fwhm=2, roundlo=-np.inf, roundhi=np.inf, sharplo=-np.inf, sharphi=np.inf, brightest=brightest) tbl = starfinder(DATA) assert len(tbl) == brightest def test_irafstarfind_mask(self): """Test IRAFStarFinder with a mask.""" starfinder = IRAFStarFinder(threshold=10, fwhm=1.5) mask = np.zeros(DATA.shape, dtype=bool) mask[100:200] = True tbl1 = starfinder(DATA) tbl2 = starfinder(DATA, mask=mask) assert len(tbl1) > len(tbl2) photutils-0.7.2/photutils/extern/0000755000214200020070000000000013573510273021304 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/extern/__init__.py0000644000214200020070000000024113563423715023415 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage contains tools that are bundled with the package but are external to it. """ photutils-0.7.2/photutils/extern/sigma_clipping.py0000644000214200020070000007424313572576136024666 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ The module contains tools for sigma clipping data. This module can be removed when photutils depends on astropy >= 3.1. """ import warnings from astropy.utils import isiterable from astropy.utils.decorators import deprecated_renamed_argument from astropy.utils.exceptions import AstropyUserWarning import numpy as np try: import bottleneck # pylint: disable=W0611 HAS_BOTTLENECK = True except ImportError: HAS_BOTTLENECK = False def _move_tuple_axes_first(array, axis): """ Bottleneck can only take integer axis, not tuple, so this function takes all the axes to be operated on and combines them into the first dimension of the array so that we can then use axis=0 """ # Figure out how many axes we are operating over naxis = len(axis) # Add remaining axes to the axis tuple axis += tuple(i for i in range(array.ndim) if i not in axis) # The new position of each axis is just in order destination = tuple(range(array.ndim)) # Reorder the array so that the axes being operated on are at the beginning array_new = np.moveaxis(array, axis, destination) # Figure out the size of the product of the dimensions being operated on first = np.prod(array_new.shape[:naxis]) # Collapse the dimensions being operated on into a single dimension so that # we can then use axis=0 with the bottleneck functions array_new = array_new.reshape((first,) + array_new.shape[naxis:]) return array_new def _nanmean(array, axis=None): """Bottleneck nanmean function that handle tuple axis.""" if isinstance(axis, tuple): array = _move_tuple_axes_first(array, axis=axis) axis = 0 return bottleneck.nanmean(array, axis=axis) def _nanmedian(array, axis=None): """Bottleneck nanmedian function that handle tuple axis.""" if isinstance(axis, tuple): array = _move_tuple_axes_first(array, axis=axis) axis = 0 return bottleneck.nanmedian(array, axis=axis) def _nanstd(array, axis=None, ddof=0): """Bottleneck nanstd function that handle tuple axis.""" if isinstance(axis, tuple): array = _move_tuple_axes_first(array, axis=axis) axis = 0 return bottleneck.nanstd(array, axis=axis, ddof=ddof) class SigmaClip: """ Class to perform sigma clipping. The data will be iterated over, each time rejecting values that are less or more than a specified number of standard deviations from a center value. Clipped (rejected) pixels are those where:: data < cenfunc(data [,axis=int]) - (sigma_lower * stdfunc(data [,axis=int])) data > cenfunc(data [,axis=int]) + (sigma_upper * stdfunc(data [,axis=int])) Invalid data values (i.e. NaN or inf) are automatically clipped. For a functional interface to sigma clipping, see :func:`sigma_clip`. .. note:: `scipy.stats.sigmaclip `_ provides a subset of the functionality in this class. Also, its input data cannot be a masked array and it does not handle data that contains invalid values (i.e. NaN or inf). Also note that it uses the mean as the centering function. If your data is a `~numpy.ndarray` with no invalid values and you want to use the mean as the centering function with ``axis=None`` and iterate to convergence, then `scipy.stats.sigmaclip` is ~25-30% faster than the equivalent settings here (``s = SigmaClip(cenfunc='mean', maxiters=None); s(data, axis=None)``). Parameters ---------- sigma : float, optional The number of standard deviations to use for both the lower and upper clipping limit. These limits are overridden by ``sigma_lower`` and ``sigma_upper``, if input. The default is 3. sigma_lower : float or `None`, optional The number of standard deviations to use as the lower bound for the clipping limit. If `None` then the value of ``sigma`` is used. The default is `None`. sigma_upper : float or `None`, optional The number of standard deviations to use as the upper bound for the clipping limit. If `None` then the value of ``sigma`` is used. The default is `None`. maxiters : int or `None`, optional The maximum number of sigma-clipping iterations to perform or `None` to clip until convergence is achieved (i.e., iterate until the last iteration clips nothing). If convergence is achieved prior to ``maxiters`` iterations, the clipping iterations will stop. The default is 5. cenfunc : {'median', 'mean'} or callable, optional The statistic or callable function/object used to compute the center value for the clipping. If set to ``'median'`` or ``'mean'`` then having the optional `bottleneck`_ package installed will result in the best performance. If using a callable function/object and the ``axis`` keyword is used, then it must be callable that can ignore NaNs (e.g. `numpy.nanmean`) and has an ``axis`` keyword to return an array with axis dimension(s) removed. The default is ``'median'``. .. _bottleneck: https://github.com/kwgoodman/bottleneck stdfunc : {'std'} or callable, optional The statistic or callable function/object used to compute the standard deviation about the center value. If set to ``'std'`` then having the optional `bottleneck`_ package installed will result in the best performance. If using a callable function/object and the ``axis`` keyword is used, then it must be callable that can ignore NaNs (e.g. `numpy.nanstd`) and has an ``axis`` keyword to return an array with axis dimension(s) removed. The default is ``'std'``. See Also -------- sigma_clip, sigma_clipped_stats Examples -------- This example uses a data array of random variates from a Gaussian distribution. We clip all points that are more than 2 sample standard deviations from the median. The result is a masked array, where the mask is `True` for clipped data:: >>> from astropy.stats import SigmaClip >>> from numpy.random import randn >>> randvar = randn(10000) >>> sigclip = SigmaClip(sigma=2, maxiters=5) >>> filtered_data = sigclip(randvar) This example clips all points that are more than 3 sigma relative to the sample *mean*, clips until convergence, returns an unmasked `~numpy.ndarray`, and modifies the data in-place:: >>> from astropy.stats import SigmaClip >>> from numpy.random import randn >>> from numpy import mean >>> randvar = randn(10000) >>> sigclip = SigmaClip(sigma=3, maxiters=None, cenfunc='mean') >>> filtered_data = sigclip(randvar, masked=False, copy=False) This example sigma clips along one axis:: >>> from astropy.stats import SigmaClip >>> from numpy.random import normal >>> from numpy import arange, diag, ones >>> data = arange(5) + normal(0., 0.05, (5, 5)) + diag(ones(5)) >>> sigclip = SigmaClip(sigma=2.3) >>> filtered_data = sigclip(data, axis=0) Note that along the other axis, no points would be clipped, as the standard deviation is higher. """ @deprecated_renamed_argument('iters', 'maxiters', '3.1') def __init__(self, sigma=3., sigma_lower=None, sigma_upper=None, maxiters=5, cenfunc='median', stdfunc='std'): self.sigma = sigma self.sigma_lower = sigma_lower or sigma self.sigma_upper = sigma_upper or sigma self.maxiters = maxiters or np.inf self.cenfunc = self._parse_cenfunc(cenfunc) self.stdfunc = self._parse_stdfunc(stdfunc) def __repr__(self): return ('SigmaClip(sigma={0}, sigma_lower={1}, sigma_upper={2}, ' 'maxiters={3}, cenfunc={4}, stdfunc={5})' .format(self.sigma, self.sigma_lower, self.sigma_upper, self.maxiters, self.cenfunc, self.stdfunc)) def __str__(self): lines = ['<' + self.__class__.__name__ + '>'] attrs = ['sigma', 'sigma_lower', 'sigma_upper', 'maxiters', 'cenfunc', 'stdfunc'] for attr in attrs: lines.append(' {0}: {1}'.format(attr, getattr(self, attr))) return '\n'.join(lines) @staticmethod def _parse_cenfunc(cenfunc): if isinstance(cenfunc, str): if cenfunc == 'median': if HAS_BOTTLENECK: cenfunc = _nanmedian else: cenfunc = np.nanmedian # pragma: no cover elif cenfunc == 'mean': if HAS_BOTTLENECK: cenfunc = _nanmean else: cenfunc = np.nanmean # pragma: no cover else: raise ValueError('{} is an invalid cenfunc.'.format(cenfunc)) return cenfunc @staticmethod def _parse_stdfunc(stdfunc): if isinstance(stdfunc, str): if stdfunc != 'std': raise ValueError('{} is an invalid stdfunc.'.format(stdfunc)) if HAS_BOTTLENECK: stdfunc = _nanstd else: stdfunc = np.nanstd # pragma: no cover return stdfunc def _compute_bounds(self, data, axis=None): # ignore RuntimeWarning if the array (or along an axis) has only # NaNs with warnings.catch_warnings(): warnings.simplefilter("ignore", category=RuntimeWarning) self._max_value = self.cenfunc(data, axis=axis) std = self.stdfunc(data, axis=axis) self._min_value = self._max_value - (std * self.sigma_lower) self._max_value += std * self.sigma_upper def _sigmaclip_noaxis(self, data, masked=True, return_bounds=False, copy=True): """ Sigma clip the data when ``axis`` is None. In this simple case, we remove clipped elements from the flattened array during each iteration. """ filtered_data = data.ravel() # remove masked values and convert to ndarray if isinstance(filtered_data, np.ma.MaskedArray): filtered_data = filtered_data.data[~filtered_data.mask] # remove invalid values good_mask = np.isfinite(filtered_data) if np.any(~good_mask): filtered_data = filtered_data[good_mask] warnings.warn('Input data contains invalid values (NaNs or ' 'infs), which were automatically clipped.', AstropyUserWarning) nchanged = 1 iteration = 0 while nchanged != 0 and (iteration < self.maxiters): iteration += 1 size = filtered_data.size self._compute_bounds(filtered_data, axis=None) filtered_data = filtered_data[(filtered_data >= self._min_value) & (filtered_data <= self._max_value)] nchanged = size - filtered_data.size self._niterations = iteration if masked: # return a masked array and optional bounds filtered_data = np.ma.masked_invalid(data, copy=copy) # update the mask in place, ignoring RuntimeWarnings for # comparisons with NaN data values with np.errstate(invalid='ignore'): filtered_data.mask |= np.logical_or(data < self._min_value, data > self._max_value) if return_bounds: return filtered_data, self._min_value, self._max_value else: return filtered_data def _sigmaclip_withaxis(self, data, axis=None, masked=True, return_bounds=False, copy=True): """ Sigma clip the data when ``axis`` is specified. In this case, we replace clipped values with NaNs as placeholder values. """ # float array type is needed to insert nans into the array filtered_data = data.astype(float) # also makes a copy # remove invalid values bad_mask = ~np.isfinite(filtered_data) if np.any(bad_mask): filtered_data[bad_mask] = np.nan warnings.warn('Input data contains invalid values (NaNs or ' 'infs), which were automatically clipped.', AstropyUserWarning) # remove masked values and convert to plain ndarray if isinstance(filtered_data, np.ma.MaskedArray): filtered_data = np.ma.masked_invalid(filtered_data).astype(float) filtered_data = filtered_data.filled(np.nan) # convert negative axis/axes if not isiterable(axis): axis = (axis,) axis = tuple(filtered_data.ndim + n if n < 0 else n for n in axis) # define the shape of min/max arrays so that they can be broadcast # with the data mshape = tuple(1 if dim in axis else size for dim, size in enumerate(filtered_data.shape)) nchanged = 1 iteration = 0 while nchanged != 0 and (iteration < self.maxiters): iteration += 1 n_nan = np.count_nonzero(np.isnan(filtered_data)) self._compute_bounds(filtered_data, axis=axis) if not np.isscalar(self._min_value): self._min_value = self._min_value.reshape(mshape) self._max_value = self._max_value.reshape(mshape) with np.errstate(invalid='ignore'): filtered_data[(filtered_data < self._min_value) | (filtered_data > self._max_value)] = np.nan nchanged = n_nan - np.count_nonzero(np.isnan(filtered_data)) self._niterations = iteration if masked: # create an output masked array if copy: filtered_data = np.ma.masked_invalid(filtered_data) else: # ignore RuntimeWarnings for comparisons with NaN data values with np.errstate(invalid='ignore'): out = np.ma.masked_invalid(data, copy=False) filtered_data = np.ma.masked_where( np.logical_or(out < self._min_value, out > self._max_value), out, copy=False) if return_bounds: return filtered_data, self._min_value, self._max_value else: return filtered_data def __call__(self, data, axis=None, masked=True, return_bounds=False, copy=True): """ Perform sigma clipping on the provided data. Parameters ---------- data : array-like or `~numpy.ma.MaskedArray` The data to be sigma clipped. axis : `None` or int or tuple of int, optional The axis or axes along which to sigma clip the data. If `None`, then the flattened data will be used. ``axis`` is passed to the ``cenfunc`` and ``stdfunc``. The default is `None`. masked : bool, optional If `True`, then a `~numpy.ma.MaskedArray` is returned, where the mask is `True` for clipped values. If `False`, then a `~numpy.ndarray` and the minimum and maximum clipping thresholds are returned. The default is `True`. return_bounds : bool, optional If `True`, then the minimum and maximum clipping bounds are also returned. copy : bool, optional If `True`, then the ``data`` array will be copied. If `False` and ``masked=True``, then the returned masked array data will contain the same array as the input ``data`` (if ``data`` is a `~numpy.ndarray` or `~numpy.ma.MaskedArray`). The default is `True`. Returns ------- result : flexible If ``masked=True``, then a `~numpy.ma.MaskedArray` is returned, where the mask is `True` for clipped values. If ``masked=False``, then a `~numpy.ndarray` is returned. If ``return_bounds=True``, then in addition to the (masked) array above, the minimum and maximum clipping bounds are returned. If ``masked=False`` and ``axis=None``, then the output array is a flattened 1D `~numpy.ndarray` where the clipped values have been removed. If ``return_bounds=True`` then the returned minimum and maximum thresholds are scalars. If ``masked=False`` and ``axis`` is specified, then the output `~numpy.ndarray` will have the same shape as the input ``data`` and contain ``np.nan`` where values were clipped. If ``return_bounds=True`` then the returned minimum and maximum clipping thresholds will be be `~numpy.ndarray`\\s. """ data = np.asanyarray(data) if data.size == 0: return data if isinstance(data, np.ma.MaskedArray) and data.mask.all(): return data # These two cases are treated separately because when # ``axis=None`` we can simply remove clipped values from the # array. This is not possible when ``axis`` is specified, so # instead we replace clipped values with NaNs as a placeholder # value. if axis is None: return self._sigmaclip_noaxis(data, masked=masked, return_bounds=return_bounds, copy=copy) else: return self._sigmaclip_withaxis(data, axis=axis, masked=masked, return_bounds=return_bounds, copy=copy) @deprecated_renamed_argument('iters', 'maxiters', '3.1') def sigma_clip(data, sigma=3, sigma_lower=None, sigma_upper=None, maxiters=5, cenfunc='median', stdfunc='std', axis=None, masked=True, return_bounds=False, copy=True): """ Perform sigma-clipping on the provided data. The data will be iterated over, each time rejecting values that are less or more than a specified number of standard deviations from a center value. Clipped (rejected) pixels are those where:: data < cenfunc(data [,axis=int]) - (sigma_lower * stdfunc(data [,axis=int])) data > cenfunc(data [,axis=int]) + (sigma_upper * stdfunc(data [,axis=int])) Invalid data values (i.e. NaN or inf) are automatically clipped. For an object-oriented interface to sigma clipping, see :class:`SigmaClip`. .. note:: `scipy.stats.sigmaclip `_ provides a subset of the functionality in this class. Also, its input data cannot be a masked array and it does not handle data that contains invalid values (i.e. NaN or inf). Also note that it uses the mean as the centering function. If your data is a `~numpy.ndarray` with no invalid values and you want to use the mean as the centering function with ``axis=None`` and iterate to convergence, then `scipy.stats.sigmaclip` is ~25-30% faster than the equivalent settings here (``sigma_clip(data, cenfunc='mean', maxiters=None, axis=None)``). Parameters ---------- data : array-like or `~numpy.ma.MaskedArray` The data to be sigma clipped. sigma : float, optional The number of standard deviations to use for both the lower and upper clipping limit. These limits are overridden by ``sigma_lower`` and ``sigma_upper``, if input. The default is 3. sigma_lower : float or `None`, optional The number of standard deviations to use as the lower bound for the clipping limit. If `None` then the value of ``sigma`` is used. The default is `None`. sigma_upper : float or `None`, optional The number of standard deviations to use as the upper bound for the clipping limit. If `None` then the value of ``sigma`` is used. The default is `None`. maxiters : int or `None`, optional The maximum number of sigma-clipping iterations to perform or `None` to clip until convergence is achieved (i.e., iterate until the last iteration clips nothing). If convergence is achieved prior to ``maxiters`` iterations, the clipping iterations will stop. The default is 5. cenfunc : {'median', 'mean'} or callable, optional The statistic or callable function/object used to compute the center value for the clipping. If set to ``'median'`` or ``'mean'`` then having the optional `bottleneck`_ package installed will result in the best performance. If using a callable function/object and the ``axis`` keyword is used, then it must be callable that can ignore NaNs (e.g. `numpy.nanmean`) and has an ``axis`` keyword to return an array with axis dimension(s) removed. The default is ``'median'``. .. _bottleneck: https://github.com/kwgoodman/bottleneck stdfunc : {'std'} or callable, optional The statistic or callable function/object used to compute the standard deviation about the center value. If set to ``'std'`` then having the optional `bottleneck`_ package installed will result in the best performance. If using a callable function/object and the ``axis`` keyword is used, then it must be callable that can ignore NaNs (e.g. `numpy.nanstd`) and has an ``axis`` keyword to return an array with axis dimension(s) removed. The default is ``'std'``. axis : `None` or int or tuple of int, optional The axis or axes along which to sigma clip the data. If `None`, then the flattened data will be used. ``axis`` is passed to the ``cenfunc`` and ``stdfunc``. The default is `None`. masked : bool, optional If `True`, then a `~numpy.ma.MaskedArray` is returned, where the mask is `True` for clipped values. If `False`, then a `~numpy.ndarray` and the minimum and maximum clipping thresholds are returned. The default is `True`. return_bounds : bool, optional If `True`, then the minimum and maximum clipping bounds are also returned. copy : bool, optional If `True`, then the ``data`` array will be copied. If `False` and ``masked=True``, then the returned masked array data will contain the same array as the input ``data`` (if ``data`` is a `~numpy.ndarray` or `~numpy.ma.MaskedArray`). The default is `True`. Returns ------- result : flexible If ``masked=True``, then a `~numpy.ma.MaskedArray` is returned, where the mask is `True` for clipped values. If ``masked=False``, then a `~numpy.ndarray` is returned. If ``return_bounds=True``, then in addition to the (masked) array above, the minimum and maximum clipping bounds are returned. If ``masked=False`` and ``axis=None``, then the output array is a flattened 1D `~numpy.ndarray` where the clipped values have been removed. If ``return_bounds=True`` then the returned minimum and maximum thresholds are scalars. If ``masked=False`` and ``axis`` is specified, then the output `~numpy.ndarray` will have the same shape as the input ``data`` and contain ``np.nan`` where values were clipped. If ``return_bounds=True`` then the returned minimum and maximum clipping thresholds will be be `~numpy.ndarray`\\s. See Also -------- SigmaClip, sigma_clipped_stats Examples -------- This example uses a data array of random variates from a Gaussian distribution. We clip all points that are more than 2 sample standard deviations from the median. The result is a masked array, where the mask is `True` for clipped data:: >>> from astropy.stats import sigma_clip >>> from numpy.random import randn >>> randvar = randn(10000) >>> filtered_data = sigma_clip(randvar, sigma=2, maxiters=5) This example clips all points that are more than 3 sigma relative to the sample *mean*, clips until convergence, returns an unmasked `~numpy.ndarray`, and does not copy the data:: >>> from astropy.stats import sigma_clip >>> from numpy.random import randn >>> from numpy import mean >>> randvar = randn(10000) >>> filtered_data = sigma_clip(randvar, sigma=3, maxiters=None, ... cenfunc=mean, masked=False, copy=False) This example sigma clips along one axis:: >>> from astropy.stats import sigma_clip >>> from numpy.random import normal >>> from numpy import arange, diag, ones >>> data = arange(5) + normal(0., 0.05, (5, 5)) + diag(ones(5)) >>> filtered_data = sigma_clip(data, sigma=2.3, axis=0) Note that along the other axis, no points would be clipped, as the standard deviation is higher. """ sigclip = SigmaClip(sigma=sigma, sigma_lower=sigma_lower, sigma_upper=sigma_upper, maxiters=maxiters, cenfunc=cenfunc, stdfunc=stdfunc) return sigclip(data, axis=axis, masked=masked, return_bounds=return_bounds, copy=copy) @deprecated_renamed_argument('iters', 'maxiters', '3.1') def sigma_clipped_stats(data, mask=None, mask_value=None, sigma=3.0, sigma_lower=None, sigma_upper=None, maxiters=5, cenfunc='median', stdfunc='std', std_ddof=0, axis=None): """ Calculate sigma-clipped statistics on the provided data. Parameters ---------- data : array-like or `~numpy.ma.MaskedArray` Data array or object that can be converted to an array. mask : `numpy.ndarray` (bool), optional A boolean mask with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Masked pixels are excluded when computing the statistics. mask_value : float, optional A data value (e.g., ``0.0``) that is ignored when computing the statistics. ``mask_value`` will be masked in addition to any input ``mask``. sigma : float, optional The number of standard deviations to use for both the lower and upper clipping limit. These limits are overridden by ``sigma_lower`` and ``sigma_upper``, if input. The default is 3. sigma_lower : float or `None`, optional The number of standard deviations to use as the lower bound for the clipping limit. If `None` then the value of ``sigma`` is used. The default is `None`. sigma_upper : float or `None`, optional The number of standard deviations to use as the upper bound for the clipping limit. If `None` then the value of ``sigma`` is used. The default is `None`. maxiters : int or `None`, optional The maximum number of sigma-clipping iterations to perform or `None` to clip until convergence is achieved (i.e., iterate until the last iteration clips nothing). If convergence is achieved prior to ``maxiters`` iterations, the clipping iterations will stop. The default is 5. cenfunc : {'median', 'mean'} or callable, optional The statistic or callable function/object used to compute the center value for the clipping. If set to ``'median'`` or ``'mean'`` then having the optional `bottleneck`_ package installed will result in the best performance. If using a callable function/object and the ``axis`` keyword is used, then it must be callable that can ignore NaNs (e.g. `numpy.nanmean`) and has an ``axis`` keyword to return an array with axis dimension(s) removed. The default is ``'median'``. .. _bottleneck: https://github.com/kwgoodman/bottleneck stdfunc : {'std'} or callable, optional The statistic or callable function/object used to compute the standard deviation about the center value. If set to ``'std'`` then having the optional `bottleneck`_ package installed will result in the best performance. If using a callable function/object and the ``axis`` keyword is used, then it must be callable that can ignore NaNs (e.g. `numpy.nanstd`) and has an ``axis`` keyword to return an array with axis dimension(s) removed. The default is ``'std'``. std_ddof : int, optional The delta degrees of freedom for the standard deviation calculation. The divisor used in the calculation is ``N - std_ddof``, where ``N`` represents the number of elements. The default is 0. axis : `None` or int or tuple of int, optional The axis or axes along which to sigma clip the data. If `None`, then the flattened data will be used. ``axis`` is passed to the ``cenfunc`` and ``stdfunc``. The default is `None`. Returns ------- mean, median, stddev : float The mean, median, and standard deviation of the sigma-clipped data. See Also -------- SigmaClip, sigma_clip """ if mask is not None: data = np.ma.MaskedArray(data, mask) if mask_value is not None: data = np.ma.masked_values(data, mask_value) sigclip = SigmaClip(sigma=sigma, sigma_lower=sigma_lower, sigma_upper=sigma_upper, maxiters=maxiters, cenfunc=cenfunc, stdfunc=stdfunc) data_clipped = sigclip(data, axis=axis, masked=False, return_bounds=False, copy=False) if HAS_BOTTLENECK: mean = _nanmean(data_clipped, axis=axis) median = _nanmedian(data_clipped, axis=axis) std = _nanstd(data_clipped, ddof=std_ddof, axis=axis) else: # pragma: no cover mean = np.nanmean(data_clipped, axis=axis) median = np.nanmedian(data_clipped, axis=axis) std = np.nanstd(data_clipped, ddof=std_ddof, axis=axis) return mean, median, std photutils-0.7.2/photutils/geometry/0000755000214200020070000000000013573510273021632 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/geometry/__init__.py0000644000214200020070000000054413563423715023751 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage provides low-level geometry functions. """ from .circular_overlap import * # noqa from .elliptical_overlap import * # noqa from .rectangular_overlap import * # noqa __all__ = ['circular_overlap_grid', 'elliptical_overlap_grid', 'rectangular_overlap_grid'] photutils-0.7.2/photutils/geometry/circular_overlap.c0000644000214200020070000140134113573510266025340 0ustar lbradleySTSCI\science00000000000000/* Generated by Cython 0.29.14 */ #define PY_SSIZE_T_CLEAN #include "Python.h" #ifndef Py_PYTHON_H #error Python headers needed to compile C extensions, please install development version of Python. #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) #error Cython requires Python 2.6+ or Python 3.3+. #else #define CYTHON_ABI "0_29_14" #define CYTHON_HEX_VERSION 0x001D0EF0 #define CYTHON_FUTURE_DIVISION 1 #include #ifndef offsetof #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) #endif #if !defined(WIN32) && !defined(MS_WINDOWS) #ifndef __stdcall #define __stdcall #endif #ifndef __cdecl #define __cdecl #endif #ifndef __fastcall #define __fastcall #endif #endif #ifndef DL_IMPORT #define DL_IMPORT(t) t #endif #ifndef DL_EXPORT #define DL_EXPORT(t) t #endif #define __PYX_COMMA , #ifndef HAVE_LONG_LONG #if PY_VERSION_HEX >= 0x02070000 #define HAVE_LONG_LONG #endif #endif #ifndef PY_LONG_LONG #define PY_LONG_LONG LONG_LONG #endif #ifndef Py_HUGE_VAL #define Py_HUGE_VAL HUGE_VAL #endif #ifdef PYPY_VERSION #define CYTHON_COMPILING_IN_PYPY 1 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 0 #undef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 0 #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #if PY_VERSION_HEX < 0x03050000 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #elif !defined(CYTHON_USE_ASYNC_SLOTS) #define CYTHON_USE_ASYNC_SLOTS 1 #endif #undef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 0 #undef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 0 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #undef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 1 #undef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 0 #undef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 0 #undef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 0 #undef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 0 #undef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 0 #undef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE 0 #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #elif defined(PYSTON_VERSION) #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 1 #define CYTHON_COMPILING_IN_CPYTHON 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #undef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 0 #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #ifndef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 0 #endif #ifndef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 1 #endif #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif #undef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 0 #undef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 0 #undef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 0 #undef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE 0 #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #else #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 1 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif #if PY_VERSION_HEX < 0x02070000 #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) #define CYTHON_USE_PYTYPE_LOOKUP 1 #endif #if PY_MAJOR_VERSION < 3 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #elif !defined(CYTHON_USE_ASYNC_SLOTS) #define CYTHON_USE_ASYNC_SLOTS 1 #endif #if PY_VERSION_HEX < 0x02070000 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #elif !defined(CYTHON_USE_PYLONG_INTERNALS) #define CYTHON_USE_PYLONG_INTERNALS 1 #endif #ifndef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 1 #endif #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif #if PY_VERSION_HEX < 0x030300F0 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #elif !defined(CYTHON_USE_UNICODE_WRITER) #define CYTHON_USE_UNICODE_WRITER 1 #endif #ifndef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 0 #endif #ifndef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 1 #endif #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif #ifndef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 1 #endif #ifndef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 1 #endif #ifndef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) #endif #ifndef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) #endif #ifndef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) #endif #ifndef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) #endif #endif #if !defined(CYTHON_FAST_PYCCALL) #define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) #endif #if CYTHON_USE_PYLONG_INTERNALS #include "longintrepr.h" #undef SHIFT #undef BASE #undef MASK #ifdef SIZEOF_VOID_P enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; #endif #endif #ifndef __has_attribute #define __has_attribute(x) 0 #endif #ifndef __has_cpp_attribute #define __has_cpp_attribute(x) 0 #endif #ifndef CYTHON_RESTRICT #if defined(__GNUC__) #define CYTHON_RESTRICT __restrict__ #elif defined(_MSC_VER) && _MSC_VER >= 1400 #define CYTHON_RESTRICT __restrict #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define CYTHON_RESTRICT restrict #else #define CYTHON_RESTRICT #endif #endif #ifndef CYTHON_UNUSED # if defined(__GNUC__) # if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) # define CYTHON_UNUSED __attribute__ ((__unused__)) # else # define CYTHON_UNUSED # endif # elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) # define CYTHON_UNUSED __attribute__ ((__unused__)) # else # define CYTHON_UNUSED # endif #endif #ifndef CYTHON_MAYBE_UNUSED_VAR # if defined(__cplusplus) template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } # else # define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) # endif #endif #ifndef CYTHON_NCP_UNUSED # if CYTHON_COMPILING_IN_CPYTHON # define CYTHON_NCP_UNUSED # else # define CYTHON_NCP_UNUSED CYTHON_UNUSED # endif #endif #define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) #ifdef _MSC_VER #ifndef _MSC_STDINT_H_ #if _MSC_VER < 1300 typedef unsigned char uint8_t; typedef unsigned int uint32_t; #else typedef unsigned __int8 uint8_t; typedef unsigned __int32 uint32_t; #endif #endif #else #include #endif #ifndef CYTHON_FALLTHROUGH #if defined(__cplusplus) && __cplusplus >= 201103L #if __has_cpp_attribute(fallthrough) #define CYTHON_FALLTHROUGH [[fallthrough]] #elif __has_cpp_attribute(clang::fallthrough) #define CYTHON_FALLTHROUGH [[clang::fallthrough]] #elif __has_cpp_attribute(gnu::fallthrough) #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] #endif #endif #ifndef CYTHON_FALLTHROUGH #if __has_attribute(fallthrough) #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) #else #define CYTHON_FALLTHROUGH #endif #endif #if defined(__clang__ ) && defined(__apple_build_version__) #if __apple_build_version__ < 7000000 #undef CYTHON_FALLTHROUGH #define CYTHON_FALLTHROUGH #endif #endif #endif #ifndef CYTHON_INLINE #if defined(__clang__) #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) #elif defined(__GNUC__) #define CYTHON_INLINE __inline__ #elif defined(_MSC_VER) #define CYTHON_INLINE __inline #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define CYTHON_INLINE inline #else #define CYTHON_INLINE #endif #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) #define Py_OptimizeFlag 0 #endif #define __PYX_BUILD_PY_SSIZE_T "n" #define CYTHON_FORMAT_SSIZE_T "z" #if PY_MAJOR_VERSION < 3 #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #define __Pyx_DefaultClassType PyClass_Type #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" #if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #else #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #endif #define __Pyx_DefaultClassType PyType_Type #endif #ifndef Py_TPFLAGS_CHECKTYPES #define Py_TPFLAGS_CHECKTYPES 0 #endif #ifndef Py_TPFLAGS_HAVE_INDEX #define Py_TPFLAGS_HAVE_INDEX 0 #endif #ifndef Py_TPFLAGS_HAVE_NEWBUFFER #define Py_TPFLAGS_HAVE_NEWBUFFER 0 #endif #ifndef Py_TPFLAGS_HAVE_FINALIZE #define Py_TPFLAGS_HAVE_FINALIZE 0 #endif #ifndef METH_STACKLESS #define METH_STACKLESS 0 #endif #if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) #ifndef METH_FASTCALL #define METH_FASTCALL 0x80 #endif typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); #else #define __Pyx_PyCFunctionFast _PyCFunctionFast #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords #endif #if CYTHON_FAST_PYCCALL #define __Pyx_PyFastCFunction_Check(func)\ ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) #else #define __Pyx_PyFastCFunction_Check(func) 0 #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) #define PyObject_Malloc(s) PyMem_Malloc(s) #define PyObject_Free(p) PyMem_Free(p) #define PyObject_Realloc(p) PyMem_Realloc(p) #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 #define PyMem_RawMalloc(n) PyMem_Malloc(n) #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) #define PyMem_RawFree(p) PyMem_Free(p) #endif #if CYTHON_COMPILING_IN_PYSTON #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) #else #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) #endif #if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 #define __Pyx_PyThreadState_Current PyThreadState_GET() #elif PY_VERSION_HEX >= 0x03060000 #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() #elif PY_VERSION_HEX >= 0x03000000 #define __Pyx_PyThreadState_Current PyThreadState_GET() #else #define __Pyx_PyThreadState_Current _PyThreadState_Current #endif #if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) #include "pythread.h" #define Py_tss_NEEDS_INIT 0 typedef int Py_tss_t; static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { *key = PyThread_create_key(); return 0; } static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); *key = Py_tss_NEEDS_INIT; return key; } static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { PyObject_Free(key); } static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { return *key != Py_tss_NEEDS_INIT; } static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { PyThread_delete_key(*key); *key = Py_tss_NEEDS_INIT; } static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { return PyThread_set_key_value(*key, value); } static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { return PyThread_get_key_value(*key); } #endif #if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) #define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) #else #define __Pyx_PyDict_NewPresized(n) PyDict_New() #endif #if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) #else #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS #define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) #else #define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) #endif #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) #define CYTHON_PEP393_ENABLED 1 #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ 0 : _PyUnicode_Ready((PyObject *)(op))) #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) #else #define CYTHON_PEP393_ENABLED 0 #define PyUnicode_1BYTE_KIND 1 #define PyUnicode_2BYTE_KIND 2 #define PyUnicode_4BYTE_KIND 4 #define __Pyx_PyUnicode_READY(op) (0) #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) #endif #if CYTHON_COMPILING_IN_PYPY #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) #else #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) #endif #define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) #define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) #else #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) #endif #if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) #define PyObject_ASCII(o) PyObject_Repr(o) #endif #if PY_MAJOR_VERSION >= 3 #define PyBaseString_Type PyUnicode_Type #define PyStringObject PyUnicodeObject #define PyString_Type PyUnicode_Type #define PyString_Check PyUnicode_Check #define PyString_CheckExact PyUnicode_CheckExact #define PyObject_Unicode PyObject_Str #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) #else #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) #endif #ifndef PySet_CheckExact #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) #endif #if CYTHON_ASSUME_SAFE_MACROS #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) #else #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) #endif #if PY_MAJOR_VERSION >= 3 #define PyIntObject PyLongObject #define PyInt_Type PyLong_Type #define PyInt_Check(op) PyLong_Check(op) #define PyInt_CheckExact(op) PyLong_CheckExact(op) #define PyInt_FromString PyLong_FromString #define PyInt_FromUnicode PyLong_FromUnicode #define PyInt_FromLong PyLong_FromLong #define PyInt_FromSize_t PyLong_FromSize_t #define PyInt_FromSsize_t PyLong_FromSsize_t #define PyInt_AsLong PyLong_AsLong #define PyInt_AS_LONG PyLong_AS_LONG #define PyInt_AsSsize_t PyLong_AsSsize_t #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask #define PyNumber_Int PyNumber_Long #endif #if PY_MAJOR_VERSION >= 3 #define PyBoolObject PyLongObject #endif #if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY #ifndef PyUnicode_InternFromString #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) #endif #endif #if PY_VERSION_HEX < 0x030200A4 typedef long Py_hash_t; #define __Pyx_PyInt_FromHash_t PyInt_FromLong #define __Pyx_PyInt_AsHash_t PyInt_AsLong #else #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : (Py_INCREF(func), func)) #else #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) #endif #if CYTHON_USE_ASYNC_SLOTS #if PY_VERSION_HEX >= 0x030500B1 #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) #else #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) #endif #else #define __Pyx_PyType_AsAsync(obj) NULL #endif #ifndef __Pyx_PyAsyncMethodsStruct typedef struct { unaryfunc am_await; unaryfunc am_aiter; unaryfunc am_anext; } __Pyx_PyAsyncMethodsStruct; #endif #if defined(WIN32) || defined(MS_WINDOWS) #define _USE_MATH_DEFINES #endif #include #ifdef NAN #define __PYX_NAN() ((float) NAN) #else static CYTHON_INLINE float __PYX_NAN() { float value; memset(&value, 0xFF, sizeof(value)); return value; } #endif #if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) #define __Pyx_truncl trunc #else #define __Pyx_truncl truncl #endif #define __PYX_ERR(f_index, lineno, Ln_error) \ { \ __pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \ } #ifndef __PYX_EXTERN_C #ifdef __cplusplus #define __PYX_EXTERN_C extern "C" #else #define __PYX_EXTERN_C extern #endif #endif #define __PYX_HAVE__photutils__geometry__circular_overlap #define __PYX_HAVE_API__photutils__geometry__circular_overlap /* Early includes */ #include #include #include "numpy/arrayobject.h" #include "numpy/ufuncobject.h" #include "math.h" #ifdef _OPENMP #include #endif /* _OPENMP */ #if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) #define CYTHON_WITHOUT_ASSERTIONS #endif typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; #define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 #define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 #define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) #define __PYX_DEFAULT_STRING_ENCODING "" #define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString #define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize #define __Pyx_uchar_cast(c) ((unsigned char)c) #define __Pyx_long_cast(x) ((long)x) #define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ (sizeof(type) < sizeof(Py_ssize_t)) ||\ (sizeof(type) > sizeof(Py_ssize_t) &&\ likely(v < (type)PY_SSIZE_T_MAX ||\ v == (type)PY_SSIZE_T_MAX) &&\ (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ v == (type)PY_SSIZE_T_MIN))) ||\ (sizeof(type) == sizeof(Py_ssize_t) &&\ (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ v == (type)PY_SSIZE_T_MAX))) ) static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { return (size_t) i < (size_t) limit; } #if defined (__cplusplus) && __cplusplus >= 201103L #include #define __Pyx_sst_abs(value) std::abs(value) #elif SIZEOF_INT >= SIZEOF_SIZE_T #define __Pyx_sst_abs(value) abs(value) #elif SIZEOF_LONG >= SIZEOF_SIZE_T #define __Pyx_sst_abs(value) labs(value) #elif defined (_MSC_VER) #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define __Pyx_sst_abs(value) llabs(value) #elif defined (__GNUC__) #define __Pyx_sst_abs(value) __builtin_llabs(value) #else #define __Pyx_sst_abs(value) ((value<0) ? -value : value) #endif static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); #define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) #define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) #define __Pyx_PyBytes_FromString PyBytes_FromString #define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); #if PY_MAJOR_VERSION < 3 #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize #else #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize #endif #define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) #define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) #define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) #define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) #define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) #define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { const Py_UNICODE *u_end = u; while (*u_end++) ; return (size_t)(u_end - u - 1); } #define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) #define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode #define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode #define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) #define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); #define __Pyx_PySequence_Tuple(obj)\ (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); #if CYTHON_ASSUME_SAFE_MACROS #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) #else #define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) #endif #define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) #else #define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) #endif #define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII static int __Pyx_sys_getdefaultencoding_not_ascii; static int __Pyx_init_sys_getdefaultencoding_params(void) { PyObject* sys; PyObject* default_encoding = NULL; PyObject* ascii_chars_u = NULL; PyObject* ascii_chars_b = NULL; const char* default_encoding_c; sys = PyImport_ImportModule("sys"); if (!sys) goto bad; default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); Py_DECREF(sys); if (!default_encoding) goto bad; default_encoding_c = PyBytes_AsString(default_encoding); if (!default_encoding_c) goto bad; if (strcmp(default_encoding_c, "ascii") == 0) { __Pyx_sys_getdefaultencoding_not_ascii = 0; } else { char ascii_chars[128]; int c; for (c = 0; c < 128; c++) { ascii_chars[c] = c; } __Pyx_sys_getdefaultencoding_not_ascii = 1; ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); if (!ascii_chars_u) goto bad; ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { PyErr_Format( PyExc_ValueError, "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", default_encoding_c); goto bad; } Py_DECREF(ascii_chars_u); Py_DECREF(ascii_chars_b); } Py_DECREF(default_encoding); return 0; bad: Py_XDECREF(default_encoding); Py_XDECREF(ascii_chars_u); Py_XDECREF(ascii_chars_b); return -1; } #endif #if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) #else #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) #if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT static char* __PYX_DEFAULT_STRING_ENCODING; static int __Pyx_init_sys_getdefaultencoding_params(void) { PyObject* sys; PyObject* default_encoding = NULL; char* default_encoding_c; sys = PyImport_ImportModule("sys"); if (!sys) goto bad; default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); Py_DECREF(sys); if (!default_encoding) goto bad; default_encoding_c = PyBytes_AsString(default_encoding); if (!default_encoding_c) goto bad; __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); Py_DECREF(default_encoding); return 0; bad: Py_XDECREF(default_encoding); return -1; } #endif #endif /* Test for GCC > 2.95 */ #if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #else /* !__GNUC__ or GCC < 2.95 */ #define likely(x) (x) #define unlikely(x) (x) #endif /* __GNUC__ */ static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } static PyObject *__pyx_m = NULL; static PyObject *__pyx_d; static PyObject *__pyx_b; static PyObject *__pyx_cython_runtime = NULL; static PyObject *__pyx_empty_tuple; static PyObject *__pyx_empty_bytes; static PyObject *__pyx_empty_unicode; static int __pyx_lineno; static int __pyx_clineno = 0; static const char * __pyx_cfilenm= __FILE__; static const char *__pyx_filename; /* Header.proto */ #if !defined(CYTHON_CCOMPLEX) #if defined(__cplusplus) #define CYTHON_CCOMPLEX 1 #elif defined(_Complex_I) #define CYTHON_CCOMPLEX 1 #else #define CYTHON_CCOMPLEX 0 #endif #endif #if CYTHON_CCOMPLEX #ifdef __cplusplus #include #else #include #endif #endif #if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__) #undef _Complex_I #define _Complex_I 1.0fj #endif static const char *__pyx_f[] = { "photutils/geometry/circular_overlap.pyx", "__init__.pxd", "type.pxd", }; /* BufferFormatStructs.proto */ #define IS_UNSIGNED(type) (((type) -1) > 0) struct __Pyx_StructField_; #define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0) typedef struct { const char* name; struct __Pyx_StructField_* fields; size_t size; size_t arraysize[8]; int ndim; char typegroup; char is_unsigned; int flags; } __Pyx_TypeInfo; typedef struct __Pyx_StructField_ { __Pyx_TypeInfo* type; const char* name; size_t offset; } __Pyx_StructField; typedef struct { __Pyx_StructField* field; size_t parent_offset; } __Pyx_BufFmt_StackElem; typedef struct { __Pyx_StructField root; __Pyx_BufFmt_StackElem* head; size_t fmt_offset; size_t new_count, enc_count; size_t struct_alignment; int is_complex; char enc_type; char new_packmode; char enc_packmode; char is_valid_array; } __Pyx_BufFmt_Context; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":776 * # in Cython to enable them only on the right systems. * * ctypedef npy_int8 int8_t # <<<<<<<<<<<<<< * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t */ typedef npy_int8 __pyx_t_5numpy_int8_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":777 * * ctypedef npy_int8 int8_t * ctypedef npy_int16 int16_t # <<<<<<<<<<<<<< * ctypedef npy_int32 int32_t * ctypedef npy_int64 int64_t */ typedef npy_int16 __pyx_t_5numpy_int16_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":778 * ctypedef npy_int8 int8_t * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t # <<<<<<<<<<<<<< * ctypedef npy_int64 int64_t * #ctypedef npy_int96 int96_t */ typedef npy_int32 __pyx_t_5numpy_int32_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":779 * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t * ctypedef npy_int64 int64_t # <<<<<<<<<<<<<< * #ctypedef npy_int96 int96_t * #ctypedef npy_int128 int128_t */ typedef npy_int64 __pyx_t_5numpy_int64_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":783 * #ctypedef npy_int128 int128_t * * ctypedef npy_uint8 uint8_t # <<<<<<<<<<<<<< * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t */ typedef npy_uint8 __pyx_t_5numpy_uint8_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":784 * * ctypedef npy_uint8 uint8_t * ctypedef npy_uint16 uint16_t # <<<<<<<<<<<<<< * ctypedef npy_uint32 uint32_t * ctypedef npy_uint64 uint64_t */ typedef npy_uint16 __pyx_t_5numpy_uint16_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":785 * ctypedef npy_uint8 uint8_t * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t # <<<<<<<<<<<<<< * ctypedef npy_uint64 uint64_t * #ctypedef npy_uint96 uint96_t */ typedef npy_uint32 __pyx_t_5numpy_uint32_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":786 * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t * ctypedef npy_uint64 uint64_t # <<<<<<<<<<<<<< * #ctypedef npy_uint96 uint96_t * #ctypedef npy_uint128 uint128_t */ typedef npy_uint64 __pyx_t_5numpy_uint64_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":790 * #ctypedef npy_uint128 uint128_t * * ctypedef npy_float32 float32_t # <<<<<<<<<<<<<< * ctypedef npy_float64 float64_t * #ctypedef npy_float80 float80_t */ typedef npy_float32 __pyx_t_5numpy_float32_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":791 * * ctypedef npy_float32 float32_t * ctypedef npy_float64 float64_t # <<<<<<<<<<<<<< * #ctypedef npy_float80 float80_t * #ctypedef npy_float128 float128_t */ typedef npy_float64 __pyx_t_5numpy_float64_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":800 * # The int types are mapped a bit surprising -- * # numpy.int corresponds to 'l' and numpy.long to 'q' * ctypedef npy_long int_t # <<<<<<<<<<<<<< * ctypedef npy_longlong long_t * ctypedef npy_longlong longlong_t */ typedef npy_long __pyx_t_5numpy_int_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":801 * # numpy.int corresponds to 'l' and numpy.long to 'q' * ctypedef npy_long int_t * ctypedef npy_longlong long_t # <<<<<<<<<<<<<< * ctypedef npy_longlong longlong_t * */ typedef npy_longlong __pyx_t_5numpy_long_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":802 * ctypedef npy_long int_t * ctypedef npy_longlong long_t * ctypedef npy_longlong longlong_t # <<<<<<<<<<<<<< * * ctypedef npy_ulong uint_t */ typedef npy_longlong __pyx_t_5numpy_longlong_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":804 * ctypedef npy_longlong longlong_t * * ctypedef npy_ulong uint_t # <<<<<<<<<<<<<< * ctypedef npy_ulonglong ulong_t * ctypedef npy_ulonglong ulonglong_t */ typedef npy_ulong __pyx_t_5numpy_uint_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":805 * * ctypedef npy_ulong uint_t * ctypedef npy_ulonglong ulong_t # <<<<<<<<<<<<<< * ctypedef npy_ulonglong ulonglong_t * */ typedef npy_ulonglong __pyx_t_5numpy_ulong_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":806 * ctypedef npy_ulong uint_t * ctypedef npy_ulonglong ulong_t * ctypedef npy_ulonglong ulonglong_t # <<<<<<<<<<<<<< * * ctypedef npy_intp intp_t */ typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":808 * ctypedef npy_ulonglong ulonglong_t * * ctypedef npy_intp intp_t # <<<<<<<<<<<<<< * ctypedef npy_uintp uintp_t * */ typedef npy_intp __pyx_t_5numpy_intp_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":809 * * ctypedef npy_intp intp_t * ctypedef npy_uintp uintp_t # <<<<<<<<<<<<<< * * ctypedef npy_double float_t */ typedef npy_uintp __pyx_t_5numpy_uintp_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":811 * ctypedef npy_uintp uintp_t * * ctypedef npy_double float_t # <<<<<<<<<<<<<< * ctypedef npy_double double_t * ctypedef npy_longdouble longdouble_t */ typedef npy_double __pyx_t_5numpy_float_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":812 * * ctypedef npy_double float_t * ctypedef npy_double double_t # <<<<<<<<<<<<<< * ctypedef npy_longdouble longdouble_t * */ typedef npy_double __pyx_t_5numpy_double_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":813 * ctypedef npy_double float_t * ctypedef npy_double double_t * ctypedef npy_longdouble longdouble_t # <<<<<<<<<<<<<< * * ctypedef npy_cfloat cfloat_t */ typedef npy_longdouble __pyx_t_5numpy_longdouble_t; /* "photutils/geometry/circular_overlap.pyx":22 * * DTYPE = np.float64 * ctypedef np.float64_t DTYPE_t # <<<<<<<<<<<<<< * * # NOTE: Here we need to make sure we use cimport to import the C functions from */ typedef __pyx_t_5numpy_float64_t __pyx_t_9photutils_8geometry_16circular_overlap_DTYPE_t; /* Declarations.proto */ #if CYTHON_CCOMPLEX #ifdef __cplusplus typedef ::std::complex< float > __pyx_t_float_complex; #else typedef float _Complex __pyx_t_float_complex; #endif #else typedef struct { float real, imag; } __pyx_t_float_complex; #endif static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float); /* Declarations.proto */ #if CYTHON_CCOMPLEX #ifdef __cplusplus typedef ::std::complex< double > __pyx_t_double_complex; #else typedef double _Complex __pyx_t_double_complex; #endif #else typedef struct { double real, imag; } __pyx_t_double_complex; #endif static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double); /*--- Type declarations ---*/ /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":815 * ctypedef npy_longdouble longdouble_t * * ctypedef npy_cfloat cfloat_t # <<<<<<<<<<<<<< * ctypedef npy_cdouble cdouble_t * ctypedef npy_clongdouble clongdouble_t */ typedef npy_cfloat __pyx_t_5numpy_cfloat_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":816 * * ctypedef npy_cfloat cfloat_t * ctypedef npy_cdouble cdouble_t # <<<<<<<<<<<<<< * ctypedef npy_clongdouble clongdouble_t * */ typedef npy_cdouble __pyx_t_5numpy_cdouble_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":817 * ctypedef npy_cfloat cfloat_t * ctypedef npy_cdouble cdouble_t * ctypedef npy_clongdouble clongdouble_t # <<<<<<<<<<<<<< * * ctypedef npy_cdouble complex_t */ typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":819 * ctypedef npy_clongdouble clongdouble_t * * ctypedef npy_cdouble complex_t # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew1(a): */ typedef npy_cdouble __pyx_t_5numpy_complex_t; /* --- Runtime support code (head) --- */ /* Refnanny.proto */ #ifndef CYTHON_REFNANNY #define CYTHON_REFNANNY 0 #endif #if CYTHON_REFNANNY typedef struct { void (*INCREF)(void*, PyObject*, int); void (*DECREF)(void*, PyObject*, int); void (*GOTREF)(void*, PyObject*, int); void (*GIVEREF)(void*, PyObject*, int); void* (*SetupContext)(const char*, int, const char*); void (*FinishContext)(void**); } __Pyx_RefNannyAPIStruct; static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; #ifdef WITH_THREAD #define __Pyx_RefNannySetupContext(name, acquire_gil)\ if (acquire_gil) {\ PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ PyGILState_Release(__pyx_gilstate_save);\ } else {\ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ } #else #define __Pyx_RefNannySetupContext(name, acquire_gil)\ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) #endif #define __Pyx_RefNannyFinishContext()\ __Pyx_RefNanny->FinishContext(&__pyx_refnanny) #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) #else #define __Pyx_RefNannyDeclarations #define __Pyx_RefNannySetupContext(name, acquire_gil) #define __Pyx_RefNannyFinishContext() #define __Pyx_INCREF(r) Py_INCREF(r) #define __Pyx_DECREF(r) Py_DECREF(r) #define __Pyx_GOTREF(r) #define __Pyx_GIVEREF(r) #define __Pyx_XINCREF(r) Py_XINCREF(r) #define __Pyx_XDECREF(r) Py_XDECREF(r) #define __Pyx_XGOTREF(r) #define __Pyx_XGIVEREF(r) #endif #define __Pyx_XDECREF_SET(r, v) do {\ PyObject *tmp = (PyObject *) r;\ r = v; __Pyx_XDECREF(tmp);\ } while (0) #define __Pyx_DECREF_SET(r, v) do {\ PyObject *tmp = (PyObject *) r;\ r = v; __Pyx_DECREF(tmp);\ } while (0) #define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) #define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) /* PyObjectGetAttrStr.proto */ #if CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); #else #define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) #endif /* GetBuiltinName.proto */ static PyObject *__Pyx_GetBuiltinName(PyObject *name); /* RaiseArgTupleInvalid.proto */ static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /* RaiseDoubleKeywords.proto */ static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); /* ParseKeywords.proto */ static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ const char* function_name); /* PyDictVersioning.proto */ #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS #define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) #define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) #define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ (version_var) = __PYX_GET_DICT_VERSION(dict);\ (cache_var) = (value); #define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ static PY_UINT64_T __pyx_dict_version = 0;\ static PyObject *__pyx_dict_cached_value = NULL;\ if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ (VAR) = __pyx_dict_cached_value;\ } else {\ (VAR) = __pyx_dict_cached_value = (LOOKUP);\ __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ }\ } static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); #else #define __PYX_GET_DICT_VERSION(dict) (0) #define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) #define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); #endif /* GetModuleGlobalName.proto */ #if CYTHON_USE_DICT_VERSIONS #define __Pyx_GetModuleGlobalName(var, name) {\ static PY_UINT64_T __pyx_dict_version = 0;\ static PyObject *__pyx_dict_cached_value = NULL;\ (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ } #define __Pyx_GetModuleGlobalNameUncached(var, name) {\ PY_UINT64_T __pyx_dict_version;\ PyObject *__pyx_dict_cached_value;\ (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ } static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); #else #define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) #define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); #endif /* PyObjectCall.proto */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); #else #define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) #endif /* ExtTypeTest.proto */ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /* IsLittleEndian.proto */ static CYTHON_INLINE int __Pyx_Is_Little_Endian(void); /* BufferFormatCheck.proto */ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts); static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, __Pyx_BufFmt_StackElem* stack, __Pyx_TypeInfo* type); /* BufferGetAndValidate.proto */ #define __Pyx_GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)\ ((obj == Py_None || obj == NULL) ?\ (__Pyx_ZeroBuffer(buf), 0) :\ __Pyx__GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)) static int __Pyx__GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack); static void __Pyx_ZeroBuffer(Py_buffer* buf); static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info); static Py_ssize_t __Pyx_minusones[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; static Py_ssize_t __Pyx_zeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* BufferIndexError.proto */ static void __Pyx_RaiseBufferIndexError(int axis); #define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1) /* PyThreadStateGet.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; #define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; #define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type #else #define __Pyx_PyThreadState_declare #define __Pyx_PyThreadState_assign #define __Pyx_PyErr_Occurred() PyErr_Occurred() #endif /* PyErrFetchRestore.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) #define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) #define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) #define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) #define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) #else #define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) #endif #else #define __Pyx_PyErr_Clear() PyErr_Clear() #define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) #define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) #define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) #define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) #endif /* WriteUnraisableException.proto */ static void __Pyx_WriteUnraisable(const char *name, int clineno, int lineno, const char *filename, int full_traceback, int nogil); /* RaiseException.proto */ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); /* PyCFunctionFastCall.proto */ #if CYTHON_FAST_PYCCALL static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); #else #define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) #endif /* PyFunctionFastCall.proto */ #if CYTHON_FAST_PYCALL #define __Pyx_PyFunction_FastCall(func, args, nargs)\ __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) #if 1 || PY_VERSION_HEX < 0x030600B1 static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); #else #define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) #endif #define __Pyx_BUILD_ASSERT_EXPR(cond)\ (sizeof(char [1 - 2*!(cond)]) - 1) #ifndef Py_MEMBER_SIZE #define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) #endif static size_t __pyx_pyframe_localsplus_offset = 0; #include "frameobject.h" #define __Pxy_PyFrame_Initialize_Offsets()\ ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) #define __Pyx_PyFrame_GetLocalsplus(frame)\ (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) #endif /* PyObjectCallMethO.proto */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); #endif /* PyObjectCallOneArg.proto */ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); /* DictGetItem.proto */ #if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key); #define __Pyx_PyObject_Dict_GetItem(obj, name)\ (likely(PyDict_CheckExact(obj)) ?\ __Pyx_PyDict_GetItem(obj, name) : PyObject_GetItem(obj, name)) #else #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key) #define __Pyx_PyObject_Dict_GetItem(obj, name) PyObject_GetItem(obj, name) #endif /* RaiseTooManyValuesToUnpack.proto */ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); /* RaiseNeedMoreValuesToUnpack.proto */ static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); /* RaiseNoneIterError.proto */ static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); /* GetTopmostException.proto */ #if CYTHON_USE_EXC_INFO_STACK static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); #endif /* SaveResetException.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave(__pyx_tstate, type, value, tb) static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); #define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset(__pyx_tstate, type, value, tb) static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); #else #define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) #define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) #endif /* PyErrExceptionMatches.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); #else #define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) #endif /* GetException.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); #else static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); #endif /* TypeImport.proto */ #ifndef __PYX_HAVE_RT_ImportType_proto #define __PYX_HAVE_RT_ImportType_proto enum __Pyx_ImportType_CheckSize { __Pyx_ImportType_CheckSize_Error = 0, __Pyx_ImportType_CheckSize_Warn = 1, __Pyx_ImportType_CheckSize_Ignore = 2 }; static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); #endif /* Import.proto */ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); /* CLineInTraceback.proto */ #ifdef CYTHON_CLINE_IN_TRACEBACK #define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) #else static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); #endif /* CodeObjectCache.proto */ typedef struct { PyCodeObject* code_object; int code_line; } __Pyx_CodeObjectCacheEntry; struct __Pyx_CodeObjectCache { int count; int max_count; __Pyx_CodeObjectCacheEntry* entries; }; static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); static PyCodeObject *__pyx_find_code_object(int code_line); static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); /* AddTraceback.proto */ static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename); /* BufferStructDeclare.proto */ typedef struct { Py_ssize_t shape, strides, suboffsets; } __Pyx_Buf_DimInfo; typedef struct { size_t refcount; Py_buffer pybuffer; } __Pyx_Buffer; typedef struct { __Pyx_Buffer *rcbuffer; char *data; __Pyx_Buf_DimInfo diminfo[8]; } __Pyx_LocalBuf_ND; #if PY_MAJOR_VERSION < 3 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags); static void __Pyx_ReleaseBuffer(Py_buffer *view); #else #define __Pyx_GetBuffer PyObject_GetBuffer #define __Pyx_ReleaseBuffer PyBuffer_Release #endif /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); /* RealImag.proto */ #if CYTHON_CCOMPLEX #ifdef __cplusplus #define __Pyx_CREAL(z) ((z).real()) #define __Pyx_CIMAG(z) ((z).imag()) #else #define __Pyx_CREAL(z) (__real__(z)) #define __Pyx_CIMAG(z) (__imag__(z)) #endif #else #define __Pyx_CREAL(z) ((z).real) #define __Pyx_CIMAG(z) ((z).imag) #endif #if defined(__cplusplus) && CYTHON_CCOMPLEX\ && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103) #define __Pyx_SET_CREAL(z,x) ((z).real(x)) #define __Pyx_SET_CIMAG(z,y) ((z).imag(y)) #else #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x) #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y) #endif /* Arithmetic.proto */ #if CYTHON_CCOMPLEX #define __Pyx_c_eq_float(a, b) ((a)==(b)) #define __Pyx_c_sum_float(a, b) ((a)+(b)) #define __Pyx_c_diff_float(a, b) ((a)-(b)) #define __Pyx_c_prod_float(a, b) ((a)*(b)) #define __Pyx_c_quot_float(a, b) ((a)/(b)) #define __Pyx_c_neg_float(a) (-(a)) #ifdef __cplusplus #define __Pyx_c_is_zero_float(z) ((z)==(float)0) #define __Pyx_c_conj_float(z) (::std::conj(z)) #if 1 #define __Pyx_c_abs_float(z) (::std::abs(z)) #define __Pyx_c_pow_float(a, b) (::std::pow(a, b)) #endif #else #define __Pyx_c_is_zero_float(z) ((z)==0) #define __Pyx_c_conj_float(z) (conjf(z)) #if 1 #define __Pyx_c_abs_float(z) (cabsf(z)) #define __Pyx_c_pow_float(a, b) (cpowf(a, b)) #endif #endif #else static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex); static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex); #if 1 static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex, __pyx_t_float_complex); #endif #endif /* Arithmetic.proto */ #if CYTHON_CCOMPLEX #define __Pyx_c_eq_double(a, b) ((a)==(b)) #define __Pyx_c_sum_double(a, b) ((a)+(b)) #define __Pyx_c_diff_double(a, b) ((a)-(b)) #define __Pyx_c_prod_double(a, b) ((a)*(b)) #define __Pyx_c_quot_double(a, b) ((a)/(b)) #define __Pyx_c_neg_double(a) (-(a)) #ifdef __cplusplus #define __Pyx_c_is_zero_double(z) ((z)==(double)0) #define __Pyx_c_conj_double(z) (::std::conj(z)) #if 1 #define __Pyx_c_abs_double(z) (::std::abs(z)) #define __Pyx_c_pow_double(a, b) (::std::pow(a, b)) #endif #else #define __Pyx_c_is_zero_double(z) ((z)==0) #define __Pyx_c_conj_double(z) (conj(z)) #if 1 #define __Pyx_c_abs_double(z) (cabs(z)) #define __Pyx_c_pow_double(a, b) (cpow(a, b)) #endif #endif #else static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex); static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex); #if 1 static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex, __pyx_t_double_complex); #endif #endif /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__NPY_TYPES(enum NPY_TYPES value); /* CIntFromPy.proto */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); /* CIntFromPy.proto */ static CYTHON_INLINE unsigned int __Pyx_PyInt_As_unsigned_int(PyObject *); /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); /* CIntFromPy.proto */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); /* FastTypeChecks.proto */ #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); #else #define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) #define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) #define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) #endif #define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) /* CheckBinaryVersion.proto */ static int __Pyx_check_binary_version(void); /* FunctionImport.proto */ static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**f)(void), const char *sig); /* InitStrings.proto */ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /* Module declarations from 'cpython.buffer' */ /* Module declarations from 'libc.string' */ /* Module declarations from 'libc.stdio' */ /* Module declarations from '__builtin__' */ /* Module declarations from 'cpython.type' */ static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0; /* Module declarations from 'cpython' */ /* Module declarations from 'cpython.object' */ /* Module declarations from 'cpython.ref' */ /* Module declarations from 'cpython.mem' */ /* Module declarations from 'numpy' */ /* Module declarations from 'numpy' */ static PyTypeObject *__pyx_ptype_5numpy_dtype = 0; static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0; static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0; static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0; static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0; static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); /*proto*/ /* Module declarations from 'photutils.geometry.core' */ static double (*__pyx_f_9photutils_8geometry_4core_area_arc)(double, double, double, double, double); /*proto*/ static double (*__pyx_f_9photutils_8geometry_4core_area_triangle)(double, double, double, double, double, double); /*proto*/ static double (*__pyx_f_9photutils_8geometry_4core_floor_sqrt)(double); /*proto*/ /* Module declarations from 'photutils.geometry.circular_overlap' */ static double __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_subpixel(double, double, double, double, double, int); /*proto*/ static double __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(double, double, double, double, double); /*proto*/ static double __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_core(double, double, double, double, double); /*proto*/ static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_9photutils_8geometry_16circular_overlap_DTYPE_t = { "DTYPE_t", NULL, sizeof(__pyx_t_9photutils_8geometry_16circular_overlap_DTYPE_t), { 0 }, 0, 'R', 0, 0 }; #define __Pyx_MODULE_NAME "photutils.geometry.circular_overlap" extern int __pyx_module_is_main_photutils__geometry__circular_overlap; int __pyx_module_is_main_photutils__geometry__circular_overlap = 0; /* Implementation of 'photutils.geometry.circular_overlap' */ static PyObject *__pyx_builtin_range; static PyObject *__pyx_builtin_ValueError; static PyObject *__pyx_builtin_RuntimeError; static PyObject *__pyx_builtin_ImportError; static const char __pyx_k_d[] = "d"; static const char __pyx_k_i[] = "i"; static const char __pyx_k_j[] = "j"; static const char __pyx_k_r[] = "r"; static const char __pyx_k_x[] = "x"; static const char __pyx_k_y[] = "y"; static const char __pyx_k_dx[] = "dx"; static const char __pyx_k_dy[] = "dy"; static const char __pyx_k_np[] = "np"; static const char __pyx_k_nx[] = "nx"; static const char __pyx_k_ny[] = "ny"; static const char __pyx_k_all[] = "__all__"; static const char __pyx_k_frac[] = "frac"; static const char __pyx_k_main[] = "__main__"; static const char __pyx_k_name[] = "__name__"; static const char __pyx_k_test[] = "__test__"; static const char __pyx_k_xmax[] = "xmax"; static const char __pyx_k_xmin[] = "xmin"; static const char __pyx_k_ymax[] = "ymax"; static const char __pyx_k_ymin[] = "ymin"; static const char __pyx_k_DTYPE[] = "DTYPE"; static const char __pyx_k_bxmax[] = "bxmax"; static const char __pyx_k_bxmin[] = "bxmin"; static const char __pyx_k_bymax[] = "bymax"; static const char __pyx_k_bymin[] = "bymin"; static const char __pyx_k_dtype[] = "dtype"; static const char __pyx_k_numpy[] = "numpy"; static const char __pyx_k_pxcen[] = "pxcen"; static const char __pyx_k_pxmax[] = "pxmax"; static const char __pyx_k_pxmin[] = "pxmin"; static const char __pyx_k_pycen[] = "pycen"; static const char __pyx_k_pymax[] = "pymax"; static const char __pyx_k_pymin[] = "pymin"; static const char __pyx_k_range[] = "range"; static const char __pyx_k_zeros[] = "zeros"; static const char __pyx_k_import[] = "__import__"; static const char __pyx_k_float64[] = "float64"; static const char __pyx_k_subpixels[] = "subpixels"; static const char __pyx_k_use_exact[] = "use_exact"; static const char __pyx_k_ValueError[] = "ValueError"; static const char __pyx_k_ImportError[] = "ImportError"; static const char __pyx_k_RuntimeError[] = "RuntimeError"; static const char __pyx_k_pixel_radius[] = "pixel_radius"; static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; static const char __pyx_k_circular_overlap_grid[] = "circular_overlap_grid"; static const char __pyx_k_ndarray_is_not_C_contiguous[] = "ndarray is not C contiguous"; static const char __pyx_k_The_functions_defined_here_allo[] = "\nThe functions defined here allow one to determine the exact area of\noverlap of a rectangle and a circle (written by Thomas Robitaille).\n"; static const char __pyx_k_numpy_core_multiarray_failed_to[] = "numpy.core.multiarray failed to import"; static const char __pyx_k_unknown_dtype_code_in_numpy_pxd[] = "unknown dtype code in numpy.pxd (%d)"; static const char __pyx_k_Format_string_allocated_too_shor[] = "Format string allocated too short, see comment in numpy.pxd"; static const char __pyx_k_Non_native_byte_order_not_suppor[] = "Non-native byte order not supported"; static const char __pyx_k_ndarray_is_not_Fortran_contiguou[] = "ndarray is not Fortran contiguous"; static const char __pyx_k_numpy_core_umath_failed_to_impor[] = "numpy.core.umath failed to import"; static const char __pyx_k_photutils_geometry_circular_over[] = "photutils/geometry/circular_overlap.pyx"; static const char __pyx_k_Format_string_allocated_too_shor_2[] = "Format string allocated too short."; static const char __pyx_k_photutils_geometry_circular_over_2[] = "photutils.geometry.circular_overlap"; static PyObject *__pyx_n_s_DTYPE; static PyObject *__pyx_kp_u_Format_string_allocated_too_shor; static PyObject *__pyx_kp_u_Format_string_allocated_too_shor_2; static PyObject *__pyx_n_s_ImportError; static PyObject *__pyx_kp_u_Non_native_byte_order_not_suppor; static PyObject *__pyx_n_s_RuntimeError; static PyObject *__pyx_n_s_ValueError; static PyObject *__pyx_n_s_all; static PyObject *__pyx_n_s_bxmax; static PyObject *__pyx_n_s_bxmin; static PyObject *__pyx_n_s_bymax; static PyObject *__pyx_n_s_bymin; static PyObject *__pyx_n_s_circular_overlap_grid; static PyObject *__pyx_n_u_circular_overlap_grid; static PyObject *__pyx_n_s_cline_in_traceback; static PyObject *__pyx_n_s_d; static PyObject *__pyx_n_s_dtype; static PyObject *__pyx_n_s_dx; static PyObject *__pyx_n_s_dy; static PyObject *__pyx_n_s_float64; static PyObject *__pyx_n_s_frac; static PyObject *__pyx_n_s_i; static PyObject *__pyx_n_s_import; static PyObject *__pyx_n_s_j; static PyObject *__pyx_n_s_main; static PyObject *__pyx_n_s_name; static PyObject *__pyx_kp_u_ndarray_is_not_C_contiguous; static PyObject *__pyx_kp_u_ndarray_is_not_Fortran_contiguou; static PyObject *__pyx_n_s_np; static PyObject *__pyx_n_s_numpy; static PyObject *__pyx_kp_u_numpy_core_multiarray_failed_to; static PyObject *__pyx_kp_u_numpy_core_umath_failed_to_impor; static PyObject *__pyx_n_s_nx; static PyObject *__pyx_n_s_ny; static PyObject *__pyx_kp_s_photutils_geometry_circular_over; static PyObject *__pyx_n_s_photutils_geometry_circular_over_2; static PyObject *__pyx_n_s_pixel_radius; static PyObject *__pyx_n_s_pxcen; static PyObject *__pyx_n_s_pxmax; static PyObject *__pyx_n_s_pxmin; static PyObject *__pyx_n_s_pycen; static PyObject *__pyx_n_s_pymax; static PyObject *__pyx_n_s_pymin; static PyObject *__pyx_n_s_r; static PyObject *__pyx_n_s_range; static PyObject *__pyx_n_s_subpixels; static PyObject *__pyx_n_s_test; static PyObject *__pyx_kp_u_unknown_dtype_code_in_numpy_pxd; static PyObject *__pyx_n_s_use_exact; static PyObject *__pyx_n_s_x; static PyObject *__pyx_n_s_xmax; static PyObject *__pyx_n_s_xmin; static PyObject *__pyx_n_s_y; static PyObject *__pyx_n_s_ymax; static PyObject *__pyx_n_s_ymin; static PyObject *__pyx_n_s_zeros; static PyObject *__pyx_pf_9photutils_8geometry_16circular_overlap_circular_overlap_grid(CYTHON_UNUSED PyObject *__pyx_self, double __pyx_v_xmin, double __pyx_v_xmax, double __pyx_v_ymin, double __pyx_v_ymax, int __pyx_v_nx, int __pyx_v_ny, double __pyx_v_r, int __pyx_v_use_exact, int __pyx_v_subpixels); /* proto */ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info); /* proto */ static PyObject *__pyx_tuple_; static PyObject *__pyx_tuple__2; static PyObject *__pyx_tuple__3; static PyObject *__pyx_tuple__4; static PyObject *__pyx_tuple__5; static PyObject *__pyx_tuple__6; static PyObject *__pyx_tuple__7; static PyObject *__pyx_tuple__8; static PyObject *__pyx_codeobj__9; /* Late includes */ /* "photutils/geometry/circular_overlap.pyx":30 * * * def circular_overlap_grid(double xmin, double xmax, double ymin, double ymax, # <<<<<<<<<<<<<< * int nx, int ny, double r, int use_exact, * int subpixels): */ /* Python wrapper */ static PyObject *__pyx_pw_9photutils_8geometry_16circular_overlap_1circular_overlap_grid(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static char __pyx_doc_9photutils_8geometry_16circular_overlap_circular_overlap_grid[] = "\n circular_overlap_grid(xmin, xmax, ymin, ymax, nx, ny, r,\n use_exact, subpixels)\n\n Area of overlap between a circle and a pixel grid. The circle is centered\n on the origin.\n\n Parameters\n ----------\n xmin, xmax, ymin, ymax : float\n Extent of the grid in the x and y direction.\n nx, ny : int\n Grid dimensions.\n r : float\n The radius of the circle.\n use_exact : 0 or 1\n If ``1`` calculates exact overlap, if ``0`` uses ``subpixel`` number\n of subpixels to calculate the overlap.\n subpixels : int\n Each pixel resampled by this factor in each dimension, thus each\n pixel is divided into ``subpixels ** 2`` subpixels.\n\n Returns\n -------\n frac : `~numpy.ndarray` (float)\n 2-d array of shape (ny, nx) giving the fraction of the overlap.\n "; static PyMethodDef __pyx_mdef_9photutils_8geometry_16circular_overlap_1circular_overlap_grid = {"circular_overlap_grid", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9photutils_8geometry_16circular_overlap_1circular_overlap_grid, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9photutils_8geometry_16circular_overlap_circular_overlap_grid}; static PyObject *__pyx_pw_9photutils_8geometry_16circular_overlap_1circular_overlap_grid(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { double __pyx_v_xmin; double __pyx_v_xmax; double __pyx_v_ymin; double __pyx_v_ymax; int __pyx_v_nx; int __pyx_v_ny; double __pyx_v_r; int __pyx_v_use_exact; int __pyx_v_subpixels; PyObject *__pyx_r = 0; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("circular_overlap_grid (wrapper)", 0); { static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_xmin,&__pyx_n_s_xmax,&__pyx_n_s_ymin,&__pyx_n_s_ymax,&__pyx_n_s_nx,&__pyx_n_s_ny,&__pyx_n_s_r,&__pyx_n_s_use_exact,&__pyx_n_s_subpixels,0}; PyObject* values[9] = {0,0,0,0,0,0,0,0,0}; if (unlikely(__pyx_kwds)) { Py_ssize_t kw_args; const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); switch (pos_args) { case 9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8); CYTHON_FALLTHROUGH; case 8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7); CYTHON_FALLTHROUGH; case 7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6); CYTHON_FALLTHROUGH; case 6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5); CYTHON_FALLTHROUGH; case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); CYTHON_FALLTHROUGH; case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); CYTHON_FALLTHROUGH; case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); CYTHON_FALLTHROUGH; case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); CYTHON_FALLTHROUGH; case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); CYTHON_FALLTHROUGH; case 0: break; default: goto __pyx_L5_argtuple_error; } kw_args = PyDict_Size(__pyx_kwds); switch (pos_args) { case 0: if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_xmin)) != 0)) kw_args--; else goto __pyx_L5_argtuple_error; CYTHON_FALLTHROUGH; case 1: if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_xmax)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("circular_overlap_grid", 1, 9, 9, 1); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 2: if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ymin)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("circular_overlap_grid", 1, 9, 9, 2); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 3: if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ymax)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("circular_overlap_grid", 1, 9, 9, 3); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 4: if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_nx)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("circular_overlap_grid", 1, 9, 9, 4); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 5: if (likely((values[5] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ny)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("circular_overlap_grid", 1, 9, 9, 5); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 6: if (likely((values[6] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_r)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("circular_overlap_grid", 1, 9, 9, 6); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 7: if (likely((values[7] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_use_exact)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("circular_overlap_grid", 1, 9, 9, 7); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 8: if (likely((values[8] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_subpixels)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("circular_overlap_grid", 1, 9, 9, 8); __PYX_ERR(0, 30, __pyx_L3_error) } } if (unlikely(kw_args > 0)) { if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "circular_overlap_grid") < 0)) __PYX_ERR(0, 30, __pyx_L3_error) } } else if (PyTuple_GET_SIZE(__pyx_args) != 9) { goto __pyx_L5_argtuple_error; } else { values[0] = PyTuple_GET_ITEM(__pyx_args, 0); values[1] = PyTuple_GET_ITEM(__pyx_args, 1); values[2] = PyTuple_GET_ITEM(__pyx_args, 2); values[3] = PyTuple_GET_ITEM(__pyx_args, 3); values[4] = PyTuple_GET_ITEM(__pyx_args, 4); values[5] = PyTuple_GET_ITEM(__pyx_args, 5); values[6] = PyTuple_GET_ITEM(__pyx_args, 6); values[7] = PyTuple_GET_ITEM(__pyx_args, 7); values[8] = PyTuple_GET_ITEM(__pyx_args, 8); } __pyx_v_xmin = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_xmin == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 30, __pyx_L3_error) __pyx_v_xmax = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_xmax == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 30, __pyx_L3_error) __pyx_v_ymin = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_ymin == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 30, __pyx_L3_error) __pyx_v_ymax = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_ymax == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 30, __pyx_L3_error) __pyx_v_nx = __Pyx_PyInt_As_int(values[4]); if (unlikely((__pyx_v_nx == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 31, __pyx_L3_error) __pyx_v_ny = __Pyx_PyInt_As_int(values[5]); if (unlikely((__pyx_v_ny == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 31, __pyx_L3_error) __pyx_v_r = __pyx_PyFloat_AsDouble(values[6]); if (unlikely((__pyx_v_r == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 31, __pyx_L3_error) __pyx_v_use_exact = __Pyx_PyInt_As_int(values[7]); if (unlikely((__pyx_v_use_exact == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 31, __pyx_L3_error) __pyx_v_subpixels = __Pyx_PyInt_As_int(values[8]); if (unlikely((__pyx_v_subpixels == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 32, __pyx_L3_error) } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; __Pyx_RaiseArgtupleInvalid("circular_overlap_grid", 1, 9, 9, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 30, __pyx_L3_error) __pyx_L3_error:; __Pyx_AddTraceback("photutils.geometry.circular_overlap.circular_overlap_grid", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; __pyx_r = __pyx_pf_9photutils_8geometry_16circular_overlap_circular_overlap_grid(__pyx_self, __pyx_v_xmin, __pyx_v_xmax, __pyx_v_ymin, __pyx_v_ymax, __pyx_v_nx, __pyx_v_ny, __pyx_v_r, __pyx_v_use_exact, __pyx_v_subpixels); /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } static PyObject *__pyx_pf_9photutils_8geometry_16circular_overlap_circular_overlap_grid(CYTHON_UNUSED PyObject *__pyx_self, double __pyx_v_xmin, double __pyx_v_xmax, double __pyx_v_ymin, double __pyx_v_ymax, int __pyx_v_nx, int __pyx_v_ny, double __pyx_v_r, int __pyx_v_use_exact, int __pyx_v_subpixels) { unsigned int __pyx_v_i; unsigned int __pyx_v_j; double __pyx_v_dx; double __pyx_v_dy; double __pyx_v_d; double __pyx_v_pixel_radius; double __pyx_v_bxmin; double __pyx_v_bxmax; double __pyx_v_bymin; double __pyx_v_bymax; double __pyx_v_pxmin; double __pyx_v_pxcen; double __pyx_v_pxmax; double __pyx_v_pymin; double __pyx_v_pycen; double __pyx_v_pymax; PyArrayObject *__pyx_v_frac = 0; __Pyx_LocalBuf_ND __pyx_pybuffernd_frac; __Pyx_Buffer __pyx_pybuffer_frac; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; PyArrayObject *__pyx_t_5 = NULL; double __pyx_t_6; int __pyx_t_7; int __pyx_t_8; unsigned int __pyx_t_9; int __pyx_t_10; int __pyx_t_11; int __pyx_t_12; int __pyx_t_13; unsigned int __pyx_t_14; size_t __pyx_t_15; size_t __pyx_t_16; int __pyx_t_17; double __pyx_t_18; size_t __pyx_t_19; size_t __pyx_t_20; size_t __pyx_t_21; size_t __pyx_t_22; __Pyx_RefNannySetupContext("circular_overlap_grid", 0); __pyx_pybuffer_frac.pybuffer.buf = NULL; __pyx_pybuffer_frac.refcount = 0; __pyx_pybuffernd_frac.data = NULL; __pyx_pybuffernd_frac.rcbuffer = &__pyx_pybuffer_frac; /* "photutils/geometry/circular_overlap.pyx":67 * * # Define output array * cdef np.ndarray[DTYPE_t, ndim=2] frac = np.zeros([ny, nx], dtype=DTYPE) # <<<<<<<<<<<<<< * * # Find the width of each element in x and y */ __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 67, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 67, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_ny); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 67, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_nx); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 67, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyList_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 67, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_GIVEREF(__pyx_t_1); PyList_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); __Pyx_GIVEREF(__pyx_t_3); PyList_SET_ITEM(__pyx_t_4, 1, __pyx_t_3); __pyx_t_1 = 0; __pyx_t_3 = 0; __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 67, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); __pyx_t_4 = 0; __pyx_t_4 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 67, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_DTYPE); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 67, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_dtype, __pyx_t_1) < 0) __PYX_ERR(0, 67, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 67, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 67, __pyx_L1_error) __pyx_t_5 = ((PyArrayObject *)__pyx_t_1); { __Pyx_BufFmt_StackElem __pyx_stack[1]; if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_frac.rcbuffer->pybuffer, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_9photutils_8geometry_16circular_overlap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { __pyx_v_frac = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_frac.rcbuffer->pybuffer.buf = NULL; __PYX_ERR(0, 67, __pyx_L1_error) } else {__pyx_pybuffernd_frac.diminfo[0].strides = __pyx_pybuffernd_frac.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_frac.diminfo[0].shape = __pyx_pybuffernd_frac.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_frac.diminfo[1].strides = __pyx_pybuffernd_frac.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_frac.diminfo[1].shape = __pyx_pybuffernd_frac.rcbuffer->pybuffer.shape[1]; } } __pyx_t_5 = 0; __pyx_v_frac = ((PyArrayObject *)__pyx_t_1); __pyx_t_1 = 0; /* "photutils/geometry/circular_overlap.pyx":70 * * # Find the width of each element in x and y * dx = (xmax - xmin) / nx # <<<<<<<<<<<<<< * dy = (ymax - ymin) / ny * */ __pyx_t_6 = (__pyx_v_xmax - __pyx_v_xmin); if (unlikely(__pyx_v_nx == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 70, __pyx_L1_error) } __pyx_v_dx = (__pyx_t_6 / ((double)__pyx_v_nx)); /* "photutils/geometry/circular_overlap.pyx":71 * # Find the width of each element in x and y * dx = (xmax - xmin) / nx * dy = (ymax - ymin) / ny # <<<<<<<<<<<<<< * * # Find the radius of a single pixel */ __pyx_t_6 = (__pyx_v_ymax - __pyx_v_ymin); if (unlikely(__pyx_v_ny == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 71, __pyx_L1_error) } __pyx_v_dy = (__pyx_t_6 / ((double)__pyx_v_ny)); /* "photutils/geometry/circular_overlap.pyx":74 * * # Find the radius of a single pixel * pixel_radius = 0.5 * sqrt(dx * dx + dy * dy) # <<<<<<<<<<<<<< * * # Define bounding box */ __pyx_v_pixel_radius = (0.5 * sqrt(((__pyx_v_dx * __pyx_v_dx) + (__pyx_v_dy * __pyx_v_dy)))); /* "photutils/geometry/circular_overlap.pyx":77 * * # Define bounding box * bxmin = -r - 0.5 * dx # <<<<<<<<<<<<<< * bxmax = +r + 0.5 * dx * bymin = -r - 0.5 * dy */ __pyx_v_bxmin = ((-__pyx_v_r) - (0.5 * __pyx_v_dx)); /* "photutils/geometry/circular_overlap.pyx":78 * # Define bounding box * bxmin = -r - 0.5 * dx * bxmax = +r + 0.5 * dx # <<<<<<<<<<<<<< * bymin = -r - 0.5 * dy * bymax = +r + 0.5 * dy */ __pyx_v_bxmax = (__pyx_v_r + (0.5 * __pyx_v_dx)); /* "photutils/geometry/circular_overlap.pyx":79 * bxmin = -r - 0.5 * dx * bxmax = +r + 0.5 * dx * bymin = -r - 0.5 * dy # <<<<<<<<<<<<<< * bymax = +r + 0.5 * dy * */ __pyx_v_bymin = ((-__pyx_v_r) - (0.5 * __pyx_v_dy)); /* "photutils/geometry/circular_overlap.pyx":80 * bxmax = +r + 0.5 * dx * bymin = -r - 0.5 * dy * bymax = +r + 0.5 * dy # <<<<<<<<<<<<<< * * for i in range(nx): */ __pyx_v_bymax = (__pyx_v_r + (0.5 * __pyx_v_dy)); /* "photutils/geometry/circular_overlap.pyx":82 * bymax = +r + 0.5 * dy * * for i in range(nx): # <<<<<<<<<<<<<< * pxmin = xmin + i * dx # lower end of pixel * pxcen = pxmin + dx * 0.5 */ __pyx_t_7 = __pyx_v_nx; __pyx_t_8 = __pyx_t_7; for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) { __pyx_v_i = __pyx_t_9; /* "photutils/geometry/circular_overlap.pyx":83 * * for i in range(nx): * pxmin = xmin + i * dx # lower end of pixel # <<<<<<<<<<<<<< * pxcen = pxmin + dx * 0.5 * pxmax = pxmin + dx # upper end of pixel */ __pyx_v_pxmin = (__pyx_v_xmin + (__pyx_v_i * __pyx_v_dx)); /* "photutils/geometry/circular_overlap.pyx":84 * for i in range(nx): * pxmin = xmin + i * dx # lower end of pixel * pxcen = pxmin + dx * 0.5 # <<<<<<<<<<<<<< * pxmax = pxmin + dx # upper end of pixel * if pxmax > bxmin and pxmin < bxmax: */ __pyx_v_pxcen = (__pyx_v_pxmin + (__pyx_v_dx * 0.5)); /* "photutils/geometry/circular_overlap.pyx":85 * pxmin = xmin + i * dx # lower end of pixel * pxcen = pxmin + dx * 0.5 * pxmax = pxmin + dx # upper end of pixel # <<<<<<<<<<<<<< * if pxmax > bxmin and pxmin < bxmax: * for j in range(ny): */ __pyx_v_pxmax = (__pyx_v_pxmin + __pyx_v_dx); /* "photutils/geometry/circular_overlap.pyx":86 * pxcen = pxmin + dx * 0.5 * pxmax = pxmin + dx # upper end of pixel * if pxmax > bxmin and pxmin < bxmax: # <<<<<<<<<<<<<< * for j in range(ny): * pymin = ymin + j * dy */ __pyx_t_11 = ((__pyx_v_pxmax > __pyx_v_bxmin) != 0); if (__pyx_t_11) { } else { __pyx_t_10 = __pyx_t_11; goto __pyx_L6_bool_binop_done; } __pyx_t_11 = ((__pyx_v_pxmin < __pyx_v_bxmax) != 0); __pyx_t_10 = __pyx_t_11; __pyx_L6_bool_binop_done:; if (__pyx_t_10) { /* "photutils/geometry/circular_overlap.pyx":87 * pxmax = pxmin + dx # upper end of pixel * if pxmax > bxmin and pxmin < bxmax: * for j in range(ny): # <<<<<<<<<<<<<< * pymin = ymin + j * dy * pycen = pymin + dy * 0.5 */ __pyx_t_12 = __pyx_v_ny; __pyx_t_13 = __pyx_t_12; for (__pyx_t_14 = 0; __pyx_t_14 < __pyx_t_13; __pyx_t_14+=1) { __pyx_v_j = __pyx_t_14; /* "photutils/geometry/circular_overlap.pyx":88 * if pxmax > bxmin and pxmin < bxmax: * for j in range(ny): * pymin = ymin + j * dy # <<<<<<<<<<<<<< * pycen = pymin + dy * 0.5 * pymax = pymin + dy */ __pyx_v_pymin = (__pyx_v_ymin + (__pyx_v_j * __pyx_v_dy)); /* "photutils/geometry/circular_overlap.pyx":89 * for j in range(ny): * pymin = ymin + j * dy * pycen = pymin + dy * 0.5 # <<<<<<<<<<<<<< * pymax = pymin + dy * if pymax > bymin and pymin < bymax: */ __pyx_v_pycen = (__pyx_v_pymin + (__pyx_v_dy * 0.5)); /* "photutils/geometry/circular_overlap.pyx":90 * pymin = ymin + j * dy * pycen = pymin + dy * 0.5 * pymax = pymin + dy # <<<<<<<<<<<<<< * if pymax > bymin and pymin < bymax: * */ __pyx_v_pymax = (__pyx_v_pymin + __pyx_v_dy); /* "photutils/geometry/circular_overlap.pyx":91 * pycen = pymin + dy * 0.5 * pymax = pymin + dy * if pymax > bymin and pymin < bymax: # <<<<<<<<<<<<<< * * # Distance from circle center to pixel center. */ __pyx_t_11 = ((__pyx_v_pymax > __pyx_v_bymin) != 0); if (__pyx_t_11) { } else { __pyx_t_10 = __pyx_t_11; goto __pyx_L11_bool_binop_done; } __pyx_t_11 = ((__pyx_v_pymin < __pyx_v_bymax) != 0); __pyx_t_10 = __pyx_t_11; __pyx_L11_bool_binop_done:; if (__pyx_t_10) { /* "photutils/geometry/circular_overlap.pyx":94 * * # Distance from circle center to pixel center. * d = sqrt(pxcen * pxcen + pycen * pycen) # <<<<<<<<<<<<<< * * # If pixel center is "well within" circle, count full */ __pyx_v_d = sqrt(((__pyx_v_pxcen * __pyx_v_pxcen) + (__pyx_v_pycen * __pyx_v_pycen))); /* "photutils/geometry/circular_overlap.pyx":98 * # If pixel center is "well within" circle, count full * # pixel. * if d < r - pixel_radius: # <<<<<<<<<<<<<< * frac[j, i] = 1. * */ __pyx_t_10 = ((__pyx_v_d < (__pyx_v_r - __pyx_v_pixel_radius)) != 0); if (__pyx_t_10) { /* "photutils/geometry/circular_overlap.pyx":99 * # pixel. * if d < r - pixel_radius: * frac[j, i] = 1. # <<<<<<<<<<<<<< * * # If pixel center is "close" to circle border, find */ __pyx_t_15 = __pyx_v_j; __pyx_t_16 = __pyx_v_i; __pyx_t_17 = -1; if (unlikely(__pyx_t_15 >= (size_t)__pyx_pybuffernd_frac.diminfo[0].shape)) __pyx_t_17 = 0; if (unlikely(__pyx_t_16 >= (size_t)__pyx_pybuffernd_frac.diminfo[1].shape)) __pyx_t_17 = 1; if (unlikely(__pyx_t_17 != -1)) { __Pyx_RaiseBufferIndexError(__pyx_t_17); __PYX_ERR(0, 99, __pyx_L1_error) } *__Pyx_BufPtrStrided2d(__pyx_t_9photutils_8geometry_16circular_overlap_DTYPE_t *, __pyx_pybuffernd_frac.rcbuffer->pybuffer.buf, __pyx_t_15, __pyx_pybuffernd_frac.diminfo[0].strides, __pyx_t_16, __pyx_pybuffernd_frac.diminfo[1].strides) = 1.; /* "photutils/geometry/circular_overlap.pyx":98 * # If pixel center is "well within" circle, count full * # pixel. * if d < r - pixel_radius: # <<<<<<<<<<<<<< * frac[j, i] = 1. * */ goto __pyx_L13; } /* "photutils/geometry/circular_overlap.pyx":103 * # If pixel center is "close" to circle border, find * # overlap. * elif d < r + pixel_radius: # <<<<<<<<<<<<<< * * # Either do exact calculation or use subpixel */ __pyx_t_10 = ((__pyx_v_d < (__pyx_v_r + __pyx_v_pixel_radius)) != 0); if (__pyx_t_10) { /* "photutils/geometry/circular_overlap.pyx":107 * # Either do exact calculation or use subpixel * # sampling: * if use_exact: # <<<<<<<<<<<<<< * frac[j, i] = circular_overlap_single_exact( * pxmin, pymin, pxmax, pymax, r) / (dx * dy) */ __pyx_t_10 = (__pyx_v_use_exact != 0); if (__pyx_t_10) { /* "photutils/geometry/circular_overlap.pyx":108 * # sampling: * if use_exact: * frac[j, i] = circular_overlap_single_exact( # <<<<<<<<<<<<<< * pxmin, pymin, pxmax, pymax, r) / (dx * dy) * else: */ __pyx_t_6 = __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(__pyx_v_pxmin, __pyx_v_pymin, __pyx_v_pxmax, __pyx_v_pymax, __pyx_v_r); /* "photutils/geometry/circular_overlap.pyx":109 * if use_exact: * frac[j, i] = circular_overlap_single_exact( * pxmin, pymin, pxmax, pymax, r) / (dx * dy) # <<<<<<<<<<<<<< * else: * frac[j, i] = circular_overlap_single_subpixel( */ __pyx_t_18 = (__pyx_v_dx * __pyx_v_dy); if (unlikely(__pyx_t_18 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 109, __pyx_L1_error) } /* "photutils/geometry/circular_overlap.pyx":108 * # sampling: * if use_exact: * frac[j, i] = circular_overlap_single_exact( # <<<<<<<<<<<<<< * pxmin, pymin, pxmax, pymax, r) / (dx * dy) * else: */ __pyx_t_19 = __pyx_v_j; __pyx_t_20 = __pyx_v_i; __pyx_t_17 = -1; if (unlikely(__pyx_t_19 >= (size_t)__pyx_pybuffernd_frac.diminfo[0].shape)) __pyx_t_17 = 0; if (unlikely(__pyx_t_20 >= (size_t)__pyx_pybuffernd_frac.diminfo[1].shape)) __pyx_t_17 = 1; if (unlikely(__pyx_t_17 != -1)) { __Pyx_RaiseBufferIndexError(__pyx_t_17); __PYX_ERR(0, 108, __pyx_L1_error) } *__Pyx_BufPtrStrided2d(__pyx_t_9photutils_8geometry_16circular_overlap_DTYPE_t *, __pyx_pybuffernd_frac.rcbuffer->pybuffer.buf, __pyx_t_19, __pyx_pybuffernd_frac.diminfo[0].strides, __pyx_t_20, __pyx_pybuffernd_frac.diminfo[1].strides) = (__pyx_t_6 / __pyx_t_18); /* "photutils/geometry/circular_overlap.pyx":107 * # Either do exact calculation or use subpixel * # sampling: * if use_exact: # <<<<<<<<<<<<<< * frac[j, i] = circular_overlap_single_exact( * pxmin, pymin, pxmax, pymax, r) / (dx * dy) */ goto __pyx_L14; } /* "photutils/geometry/circular_overlap.pyx":111 * pxmin, pymin, pxmax, pymax, r) / (dx * dy) * else: * frac[j, i] = circular_overlap_single_subpixel( # <<<<<<<<<<<<<< * pxmin, pymin, pxmax, pymax, r, subpixels) * */ /*else*/ { /* "photutils/geometry/circular_overlap.pyx":112 * else: * frac[j, i] = circular_overlap_single_subpixel( * pxmin, pymin, pxmax, pymax, r, subpixels) # <<<<<<<<<<<<<< * * # Otherwise, it is fully outside circle. */ __pyx_t_21 = __pyx_v_j; __pyx_t_22 = __pyx_v_i; __pyx_t_17 = -1; if (unlikely(__pyx_t_21 >= (size_t)__pyx_pybuffernd_frac.diminfo[0].shape)) __pyx_t_17 = 0; if (unlikely(__pyx_t_22 >= (size_t)__pyx_pybuffernd_frac.diminfo[1].shape)) __pyx_t_17 = 1; if (unlikely(__pyx_t_17 != -1)) { __Pyx_RaiseBufferIndexError(__pyx_t_17); __PYX_ERR(0, 111, __pyx_L1_error) } *__Pyx_BufPtrStrided2d(__pyx_t_9photutils_8geometry_16circular_overlap_DTYPE_t *, __pyx_pybuffernd_frac.rcbuffer->pybuffer.buf, __pyx_t_21, __pyx_pybuffernd_frac.diminfo[0].strides, __pyx_t_22, __pyx_pybuffernd_frac.diminfo[1].strides) = __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_subpixel(__pyx_v_pxmin, __pyx_v_pymin, __pyx_v_pxmax, __pyx_v_pymax, __pyx_v_r, __pyx_v_subpixels); } __pyx_L14:; /* "photutils/geometry/circular_overlap.pyx":103 * # If pixel center is "close" to circle border, find * # overlap. * elif d < r + pixel_radius: # <<<<<<<<<<<<<< * * # Either do exact calculation or use subpixel */ } __pyx_L13:; /* "photutils/geometry/circular_overlap.pyx":91 * pycen = pymin + dy * 0.5 * pymax = pymin + dy * if pymax > bymin and pymin < bymax: # <<<<<<<<<<<<<< * * # Distance from circle center to pixel center. */ } } /* "photutils/geometry/circular_overlap.pyx":86 * pxcen = pxmin + dx * 0.5 * pxmax = pxmin + dx # upper end of pixel * if pxmax > bxmin and pxmin < bxmax: # <<<<<<<<<<<<<< * for j in range(ny): * pymin = ymin + j * dy */ } } /* "photutils/geometry/circular_overlap.pyx":117 * # No action needed. * * return frac # <<<<<<<<<<<<<< * * */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(((PyObject *)__pyx_v_frac)); __pyx_r = ((PyObject *)__pyx_v_frac); goto __pyx_L0; /* "photutils/geometry/circular_overlap.pyx":30 * * * def circular_overlap_grid(double xmin, double xmax, double ymin, double ymax, # <<<<<<<<<<<<<< * int nx, int ny, double r, int use_exact, * int subpixels): */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_frac.rcbuffer->pybuffer); __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} __Pyx_AddTraceback("photutils.geometry.circular_overlap.circular_overlap_grid", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; goto __pyx_L2; __pyx_L0:; __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_frac.rcbuffer->pybuffer); __pyx_L2:; __Pyx_XDECREF((PyObject *)__pyx_v_frac); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/circular_overlap.pyx":126 * * * cdef double circular_overlap_single_subpixel(double x0, double y0, # <<<<<<<<<<<<<< * double x1, double y1, * double r, int subpixels): */ static double __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_subpixel(double __pyx_v_x0, double __pyx_v_y0, double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_r, int __pyx_v_subpixels) { CYTHON_UNUSED unsigned int __pyx_v_i; CYTHON_UNUSED unsigned int __pyx_v_j; double __pyx_v_x; double __pyx_v_y; double __pyx_v_dx; double __pyx_v_dy; double __pyx_v_r_squared; double __pyx_v_frac; double __pyx_r; __Pyx_RefNannyDeclarations double __pyx_t_1; int __pyx_t_2; int __pyx_t_3; unsigned int __pyx_t_4; int __pyx_t_5; int __pyx_t_6; unsigned int __pyx_t_7; int __pyx_t_8; __Pyx_RefNannySetupContext("circular_overlap_single_subpixel", 0); /* "photutils/geometry/circular_overlap.pyx":134 * cdef unsigned int i, j * cdef double x, y, dx, dy, r_squared * cdef double frac = 0. # Accumulator. # <<<<<<<<<<<<<< * * dx = (x1 - x0) / subpixels */ __pyx_v_frac = 0.; /* "photutils/geometry/circular_overlap.pyx":136 * cdef double frac = 0. # Accumulator. * * dx = (x1 - x0) / subpixels # <<<<<<<<<<<<<< * dy = (y1 - y0) / subpixels * r_squared = r ** 2 */ __pyx_t_1 = (__pyx_v_x1 - __pyx_v_x0); if (unlikely(__pyx_v_subpixels == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 136, __pyx_L1_error) } __pyx_v_dx = (__pyx_t_1 / ((double)__pyx_v_subpixels)); /* "photutils/geometry/circular_overlap.pyx":137 * * dx = (x1 - x0) / subpixels * dy = (y1 - y0) / subpixels # <<<<<<<<<<<<<< * r_squared = r ** 2 * */ __pyx_t_1 = (__pyx_v_y1 - __pyx_v_y0); if (unlikely(__pyx_v_subpixels == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 137, __pyx_L1_error) } __pyx_v_dy = (__pyx_t_1 / ((double)__pyx_v_subpixels)); /* "photutils/geometry/circular_overlap.pyx":138 * dx = (x1 - x0) / subpixels * dy = (y1 - y0) / subpixels * r_squared = r ** 2 # <<<<<<<<<<<<<< * * x = x0 - 0.5 * dx */ __pyx_v_r_squared = pow(__pyx_v_r, 2.0); /* "photutils/geometry/circular_overlap.pyx":140 * r_squared = r ** 2 * * x = x0 - 0.5 * dx # <<<<<<<<<<<<<< * for i in range(subpixels): * x += dx */ __pyx_v_x = (__pyx_v_x0 - (0.5 * __pyx_v_dx)); /* "photutils/geometry/circular_overlap.pyx":141 * * x = x0 - 0.5 * dx * for i in range(subpixels): # <<<<<<<<<<<<<< * x += dx * y = y0 - 0.5 * dy */ __pyx_t_2 = __pyx_v_subpixels; __pyx_t_3 = __pyx_t_2; for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { __pyx_v_i = __pyx_t_4; /* "photutils/geometry/circular_overlap.pyx":142 * x = x0 - 0.5 * dx * for i in range(subpixels): * x += dx # <<<<<<<<<<<<<< * y = y0 - 0.5 * dy * for j in range(subpixels): */ __pyx_v_x = (__pyx_v_x + __pyx_v_dx); /* "photutils/geometry/circular_overlap.pyx":143 * for i in range(subpixels): * x += dx * y = y0 - 0.5 * dy # <<<<<<<<<<<<<< * for j in range(subpixels): * y += dy */ __pyx_v_y = (__pyx_v_y0 - (0.5 * __pyx_v_dy)); /* "photutils/geometry/circular_overlap.pyx":144 * x += dx * y = y0 - 0.5 * dy * for j in range(subpixels): # <<<<<<<<<<<<<< * y += dy * if x * x + y * y < r_squared: */ __pyx_t_5 = __pyx_v_subpixels; __pyx_t_6 = __pyx_t_5; for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_6; __pyx_t_7+=1) { __pyx_v_j = __pyx_t_7; /* "photutils/geometry/circular_overlap.pyx":145 * y = y0 - 0.5 * dy * for j in range(subpixels): * y += dy # <<<<<<<<<<<<<< * if x * x + y * y < r_squared: * frac += 1. */ __pyx_v_y = (__pyx_v_y + __pyx_v_dy); /* "photutils/geometry/circular_overlap.pyx":146 * for j in range(subpixels): * y += dy * if x * x + y * y < r_squared: # <<<<<<<<<<<<<< * frac += 1. * */ __pyx_t_8 = ((((__pyx_v_x * __pyx_v_x) + (__pyx_v_y * __pyx_v_y)) < __pyx_v_r_squared) != 0); if (__pyx_t_8) { /* "photutils/geometry/circular_overlap.pyx":147 * y += dy * if x * x + y * y < r_squared: * frac += 1. # <<<<<<<<<<<<<< * * return frac / (subpixels * subpixels) */ __pyx_v_frac = (__pyx_v_frac + 1.); /* "photutils/geometry/circular_overlap.pyx":146 * for j in range(subpixels): * y += dy * if x * x + y * y < r_squared: # <<<<<<<<<<<<<< * frac += 1. * */ } } } /* "photutils/geometry/circular_overlap.pyx":149 * frac += 1. * * return frac / (subpixels * subpixels) # <<<<<<<<<<<<<< * * */ __pyx_t_2 = (__pyx_v_subpixels * __pyx_v_subpixels); if (unlikely(__pyx_t_2 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 149, __pyx_L1_error) } __pyx_r = (__pyx_v_frac / ((double)__pyx_t_2)); goto __pyx_L0; /* "photutils/geometry/circular_overlap.pyx":126 * * * cdef double circular_overlap_single_subpixel(double x0, double y0, # <<<<<<<<<<<<<< * double x1, double y1, * double r, int subpixels): */ /* function exit code */ __pyx_L1_error:; __Pyx_WriteUnraisable("photutils.geometry.circular_overlap.circular_overlap_single_subpixel", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0); __pyx_r = 0; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/circular_overlap.pyx":152 * * * cdef double circular_overlap_single_exact(double xmin, double ymin, # <<<<<<<<<<<<<< * double xmax, double ymax, * double r): */ static double __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(double __pyx_v_xmin, double __pyx_v_ymin, double __pyx_v_xmax, double __pyx_v_ymax, double __pyx_v_r) { double __pyx_r; __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("circular_overlap_single_exact", 0); /* "photutils/geometry/circular_overlap.pyx":158 * Area of overlap of a rectangle and a circle * """ * if 0. <= xmin: # <<<<<<<<<<<<<< * if 0. <= ymin: * return circular_overlap_core(xmin, ymin, xmax, ymax, r) */ __pyx_t_1 = ((0. <= __pyx_v_xmin) != 0); if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":159 * """ * if 0. <= xmin: * if 0. <= ymin: # <<<<<<<<<<<<<< * return circular_overlap_core(xmin, ymin, xmax, ymax, r) * elif 0. >= ymax: */ __pyx_t_1 = ((0. <= __pyx_v_ymin) != 0); if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":160 * if 0. <= xmin: * if 0. <= ymin: * return circular_overlap_core(xmin, ymin, xmax, ymax, r) # <<<<<<<<<<<<<< * elif 0. >= ymax: * return circular_overlap_core(-ymax, xmin, -ymin, xmax, r) */ __pyx_r = __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_core(__pyx_v_xmin, __pyx_v_ymin, __pyx_v_xmax, __pyx_v_ymax, __pyx_v_r); goto __pyx_L0; /* "photutils/geometry/circular_overlap.pyx":159 * """ * if 0. <= xmin: * if 0. <= ymin: # <<<<<<<<<<<<<< * return circular_overlap_core(xmin, ymin, xmax, ymax, r) * elif 0. >= ymax: */ } /* "photutils/geometry/circular_overlap.pyx":161 * if 0. <= ymin: * return circular_overlap_core(xmin, ymin, xmax, ymax, r) * elif 0. >= ymax: # <<<<<<<<<<<<<< * return circular_overlap_core(-ymax, xmin, -ymin, xmax, r) * else: */ __pyx_t_1 = ((0. >= __pyx_v_ymax) != 0); if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":162 * return circular_overlap_core(xmin, ymin, xmax, ymax, r) * elif 0. >= ymax: * return circular_overlap_core(-ymax, xmin, -ymin, xmax, r) # <<<<<<<<<<<<<< * else: * return circular_overlap_single_exact(xmin, ymin, xmax, 0., r) \ */ __pyx_r = __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_core((-__pyx_v_ymax), __pyx_v_xmin, (-__pyx_v_ymin), __pyx_v_xmax, __pyx_v_r); goto __pyx_L0; /* "photutils/geometry/circular_overlap.pyx":161 * if 0. <= ymin: * return circular_overlap_core(xmin, ymin, xmax, ymax, r) * elif 0. >= ymax: # <<<<<<<<<<<<<< * return circular_overlap_core(-ymax, xmin, -ymin, xmax, r) * else: */ } /* "photutils/geometry/circular_overlap.pyx":164 * return circular_overlap_core(-ymax, xmin, -ymin, xmax, r) * else: * return circular_overlap_single_exact(xmin, ymin, xmax, 0., r) \ # <<<<<<<<<<<<<< * + circular_overlap_single_exact(xmin, 0., xmax, ymax, r) * elif 0. >= xmax: */ /*else*/ { /* "photutils/geometry/circular_overlap.pyx":165 * else: * return circular_overlap_single_exact(xmin, ymin, xmax, 0., r) \ * + circular_overlap_single_exact(xmin, 0., xmax, ymax, r) # <<<<<<<<<<<<<< * elif 0. >= xmax: * if 0. <= ymin: */ __pyx_r = (__pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(__pyx_v_xmin, __pyx_v_ymin, __pyx_v_xmax, 0., __pyx_v_r) + __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(__pyx_v_xmin, 0., __pyx_v_xmax, __pyx_v_ymax, __pyx_v_r)); goto __pyx_L0; } /* "photutils/geometry/circular_overlap.pyx":158 * Area of overlap of a rectangle and a circle * """ * if 0. <= xmin: # <<<<<<<<<<<<<< * if 0. <= ymin: * return circular_overlap_core(xmin, ymin, xmax, ymax, r) */ } /* "photutils/geometry/circular_overlap.pyx":166 * return circular_overlap_single_exact(xmin, ymin, xmax, 0., r) \ * + circular_overlap_single_exact(xmin, 0., xmax, ymax, r) * elif 0. >= xmax: # <<<<<<<<<<<<<< * if 0. <= ymin: * return circular_overlap_core(-xmax, ymin, -xmin, ymax, r) */ __pyx_t_1 = ((0. >= __pyx_v_xmax) != 0); if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":167 * + circular_overlap_single_exact(xmin, 0., xmax, ymax, r) * elif 0. >= xmax: * if 0. <= ymin: # <<<<<<<<<<<<<< * return circular_overlap_core(-xmax, ymin, -xmin, ymax, r) * elif 0. >= ymax: */ __pyx_t_1 = ((0. <= __pyx_v_ymin) != 0); if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":168 * elif 0. >= xmax: * if 0. <= ymin: * return circular_overlap_core(-xmax, ymin, -xmin, ymax, r) # <<<<<<<<<<<<<< * elif 0. >= ymax: * return circular_overlap_core(-xmax, -ymax, -xmin, -ymin, r) */ __pyx_r = __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_core((-__pyx_v_xmax), __pyx_v_ymin, (-__pyx_v_xmin), __pyx_v_ymax, __pyx_v_r); goto __pyx_L0; /* "photutils/geometry/circular_overlap.pyx":167 * + circular_overlap_single_exact(xmin, 0., xmax, ymax, r) * elif 0. >= xmax: * if 0. <= ymin: # <<<<<<<<<<<<<< * return circular_overlap_core(-xmax, ymin, -xmin, ymax, r) * elif 0. >= ymax: */ } /* "photutils/geometry/circular_overlap.pyx":169 * if 0. <= ymin: * return circular_overlap_core(-xmax, ymin, -xmin, ymax, r) * elif 0. >= ymax: # <<<<<<<<<<<<<< * return circular_overlap_core(-xmax, -ymax, -xmin, -ymin, r) * else: */ __pyx_t_1 = ((0. >= __pyx_v_ymax) != 0); if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":170 * return circular_overlap_core(-xmax, ymin, -xmin, ymax, r) * elif 0. >= ymax: * return circular_overlap_core(-xmax, -ymax, -xmin, -ymin, r) # <<<<<<<<<<<<<< * else: * return circular_overlap_single_exact(xmin, ymin, xmax, 0., r) \ */ __pyx_r = __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_core((-__pyx_v_xmax), (-__pyx_v_ymax), (-__pyx_v_xmin), (-__pyx_v_ymin), __pyx_v_r); goto __pyx_L0; /* "photutils/geometry/circular_overlap.pyx":169 * if 0. <= ymin: * return circular_overlap_core(-xmax, ymin, -xmin, ymax, r) * elif 0. >= ymax: # <<<<<<<<<<<<<< * return circular_overlap_core(-xmax, -ymax, -xmin, -ymin, r) * else: */ } /* "photutils/geometry/circular_overlap.pyx":172 * return circular_overlap_core(-xmax, -ymax, -xmin, -ymin, r) * else: * return circular_overlap_single_exact(xmin, ymin, xmax, 0., r) \ # <<<<<<<<<<<<<< * + circular_overlap_single_exact(xmin, 0., xmax, ymax, r) * else: */ /*else*/ { /* "photutils/geometry/circular_overlap.pyx":173 * else: * return circular_overlap_single_exact(xmin, ymin, xmax, 0., r) \ * + circular_overlap_single_exact(xmin, 0., xmax, ymax, r) # <<<<<<<<<<<<<< * else: * if 0. <= ymin: */ __pyx_r = (__pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(__pyx_v_xmin, __pyx_v_ymin, __pyx_v_xmax, 0., __pyx_v_r) + __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(__pyx_v_xmin, 0., __pyx_v_xmax, __pyx_v_ymax, __pyx_v_r)); goto __pyx_L0; } /* "photutils/geometry/circular_overlap.pyx":166 * return circular_overlap_single_exact(xmin, ymin, xmax, 0., r) \ * + circular_overlap_single_exact(xmin, 0., xmax, ymax, r) * elif 0. >= xmax: # <<<<<<<<<<<<<< * if 0. <= ymin: * return circular_overlap_core(-xmax, ymin, -xmin, ymax, r) */ } /* "photutils/geometry/circular_overlap.pyx":175 * + circular_overlap_single_exact(xmin, 0., xmax, ymax, r) * else: * if 0. <= ymin: # <<<<<<<<<<<<<< * return circular_overlap_single_exact(xmin, ymin, 0., ymax, r) \ * + circular_overlap_single_exact(0., ymin, xmax, ymax, r) */ /*else*/ { __pyx_t_1 = ((0. <= __pyx_v_ymin) != 0); if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":177 * if 0. <= ymin: * return circular_overlap_single_exact(xmin, ymin, 0., ymax, r) \ * + circular_overlap_single_exact(0., ymin, xmax, ymax, r) # <<<<<<<<<<<<<< * if 0. >= ymax: * return circular_overlap_single_exact(xmin, ymin, 0., ymax, r) \ */ __pyx_r = (__pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(__pyx_v_xmin, __pyx_v_ymin, 0., __pyx_v_ymax, __pyx_v_r) + __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(0., __pyx_v_ymin, __pyx_v_xmax, __pyx_v_ymax, __pyx_v_r)); goto __pyx_L0; /* "photutils/geometry/circular_overlap.pyx":175 * + circular_overlap_single_exact(xmin, 0., xmax, ymax, r) * else: * if 0. <= ymin: # <<<<<<<<<<<<<< * return circular_overlap_single_exact(xmin, ymin, 0., ymax, r) \ * + circular_overlap_single_exact(0., ymin, xmax, ymax, r) */ } /* "photutils/geometry/circular_overlap.pyx":178 * return circular_overlap_single_exact(xmin, ymin, 0., ymax, r) \ * + circular_overlap_single_exact(0., ymin, xmax, ymax, r) * if 0. >= ymax: # <<<<<<<<<<<<<< * return circular_overlap_single_exact(xmin, ymin, 0., ymax, r) \ * + circular_overlap_single_exact(0., ymin, xmax, ymax, r) */ __pyx_t_1 = ((0. >= __pyx_v_ymax) != 0); if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":180 * if 0. >= ymax: * return circular_overlap_single_exact(xmin, ymin, 0., ymax, r) \ * + circular_overlap_single_exact(0., ymin, xmax, ymax, r) # <<<<<<<<<<<<<< * else: * return circular_overlap_single_exact(xmin, ymin, 0., 0., r) \ */ __pyx_r = (__pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(__pyx_v_xmin, __pyx_v_ymin, 0., __pyx_v_ymax, __pyx_v_r) + __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(0., __pyx_v_ymin, __pyx_v_xmax, __pyx_v_ymax, __pyx_v_r)); goto __pyx_L0; /* "photutils/geometry/circular_overlap.pyx":178 * return circular_overlap_single_exact(xmin, ymin, 0., ymax, r) \ * + circular_overlap_single_exact(0., ymin, xmax, ymax, r) * if 0. >= ymax: # <<<<<<<<<<<<<< * return circular_overlap_single_exact(xmin, ymin, 0., ymax, r) \ * + circular_overlap_single_exact(0., ymin, xmax, ymax, r) */ } /* "photutils/geometry/circular_overlap.pyx":182 * + circular_overlap_single_exact(0., ymin, xmax, ymax, r) * else: * return circular_overlap_single_exact(xmin, ymin, 0., 0., r) \ # <<<<<<<<<<<<<< * + circular_overlap_single_exact(0., ymin, xmax, 0., r) \ * + circular_overlap_single_exact(xmin, 0., 0., ymax, r) \ */ /*else*/ { /* "photutils/geometry/circular_overlap.pyx":185 * + circular_overlap_single_exact(0., ymin, xmax, 0., r) \ * + circular_overlap_single_exact(xmin, 0., 0., ymax, r) \ * + circular_overlap_single_exact(0., 0., xmax, ymax, r) # <<<<<<<<<<<<<< * * */ __pyx_r = (((__pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(__pyx_v_xmin, __pyx_v_ymin, 0., 0., __pyx_v_r) + __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(0., __pyx_v_ymin, __pyx_v_xmax, 0., __pyx_v_r)) + __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(__pyx_v_xmin, 0., 0., __pyx_v_ymax, __pyx_v_r)) + __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_single_exact(0., 0., __pyx_v_xmax, __pyx_v_ymax, __pyx_v_r)); goto __pyx_L0; } } /* "photutils/geometry/circular_overlap.pyx":152 * * * cdef double circular_overlap_single_exact(double xmin, double ymin, # <<<<<<<<<<<<<< * double xmax, double ymax, * double r): */ /* function exit code */ __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/circular_overlap.pyx":188 * * * cdef double circular_overlap_core(double xmin, double ymin, double xmax, double ymax, # <<<<<<<<<<<<<< * double r): * """ */ static double __pyx_f_9photutils_8geometry_16circular_overlap_circular_overlap_core(double __pyx_v_xmin, double __pyx_v_ymin, double __pyx_v_xmax, double __pyx_v_ymax, double __pyx_v_r) { double __pyx_v_area; double __pyx_v_d1; double __pyx_v_d2; double __pyx_v_x1; double __pyx_v_x2; double __pyx_v_y1; double __pyx_v_y2; double __pyx_r; __Pyx_RefNannyDeclarations int __pyx_t_1; int __pyx_t_2; double __pyx_t_3; double __pyx_t_4; __Pyx_RefNannySetupContext("circular_overlap_core", 0); /* "photutils/geometry/circular_overlap.pyx":197 * cdef double area, d1, d2, x1, x2, y1, y2 * * if xmin * xmin + ymin * ymin > r * r: # <<<<<<<<<<<<<< * area = 0. * elif xmax * xmax + ymax * ymax < r * r: */ __pyx_t_1 = ((((__pyx_v_xmin * __pyx_v_xmin) + (__pyx_v_ymin * __pyx_v_ymin)) > (__pyx_v_r * __pyx_v_r)) != 0); if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":198 * * if xmin * xmin + ymin * ymin > r * r: * area = 0. # <<<<<<<<<<<<<< * elif xmax * xmax + ymax * ymax < r * r: * area = (xmax - xmin) * (ymax - ymin) */ __pyx_v_area = 0.; /* "photutils/geometry/circular_overlap.pyx":197 * cdef double area, d1, d2, x1, x2, y1, y2 * * if xmin * xmin + ymin * ymin > r * r: # <<<<<<<<<<<<<< * area = 0. * elif xmax * xmax + ymax * ymax < r * r: */ goto __pyx_L3; } /* "photutils/geometry/circular_overlap.pyx":199 * if xmin * xmin + ymin * ymin > r * r: * area = 0. * elif xmax * xmax + ymax * ymax < r * r: # <<<<<<<<<<<<<< * area = (xmax - xmin) * (ymax - ymin) * else: */ __pyx_t_1 = ((((__pyx_v_xmax * __pyx_v_xmax) + (__pyx_v_ymax * __pyx_v_ymax)) < (__pyx_v_r * __pyx_v_r)) != 0); if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":200 * area = 0. * elif xmax * xmax + ymax * ymax < r * r: * area = (xmax - xmin) * (ymax - ymin) # <<<<<<<<<<<<<< * else: * area = 0. */ __pyx_v_area = ((__pyx_v_xmax - __pyx_v_xmin) * (__pyx_v_ymax - __pyx_v_ymin)); /* "photutils/geometry/circular_overlap.pyx":199 * if xmin * xmin + ymin * ymin > r * r: * area = 0. * elif xmax * xmax + ymax * ymax < r * r: # <<<<<<<<<<<<<< * area = (xmax - xmin) * (ymax - ymin) * else: */ goto __pyx_L3; } /* "photutils/geometry/circular_overlap.pyx":202 * area = (xmax - xmin) * (ymax - ymin) * else: * area = 0. # <<<<<<<<<<<<<< * d1 = floor_sqrt(xmax * xmax + ymin * ymin) * d2 = floor_sqrt(xmin * xmin + ymax * ymax) */ /*else*/ { __pyx_v_area = 0.; /* "photutils/geometry/circular_overlap.pyx":203 * else: * area = 0. * d1 = floor_sqrt(xmax * xmax + ymin * ymin) # <<<<<<<<<<<<<< * d2 = floor_sqrt(xmin * xmin + ymax * ymax) * if d1 < r and d2 < r: */ __pyx_v_d1 = __pyx_f_9photutils_8geometry_4core_floor_sqrt(((__pyx_v_xmax * __pyx_v_xmax) + (__pyx_v_ymin * __pyx_v_ymin))); /* "photutils/geometry/circular_overlap.pyx":204 * area = 0. * d1 = floor_sqrt(xmax * xmax + ymin * ymin) * d2 = floor_sqrt(xmin * xmin + ymax * ymax) # <<<<<<<<<<<<<< * if d1 < r and d2 < r: * x1, y1 = floor_sqrt(r * r - ymax * ymax), ymax */ __pyx_v_d2 = __pyx_f_9photutils_8geometry_4core_floor_sqrt(((__pyx_v_xmin * __pyx_v_xmin) + (__pyx_v_ymax * __pyx_v_ymax))); /* "photutils/geometry/circular_overlap.pyx":205 * d1 = floor_sqrt(xmax * xmax + ymin * ymin) * d2 = floor_sqrt(xmin * xmin + ymax * ymax) * if d1 < r and d2 < r: # <<<<<<<<<<<<<< * x1, y1 = floor_sqrt(r * r - ymax * ymax), ymax * x2, y2 = xmax, floor_sqrt(r * r - xmax * xmax) */ __pyx_t_2 = ((__pyx_v_d1 < __pyx_v_r) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L5_bool_binop_done; } __pyx_t_2 = ((__pyx_v_d2 < __pyx_v_r) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L5_bool_binop_done:; if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":206 * d2 = floor_sqrt(xmin * xmin + ymax * ymax) * if d1 < r and d2 < r: * x1, y1 = floor_sqrt(r * r - ymax * ymax), ymax # <<<<<<<<<<<<<< * x2, y2 = xmax, floor_sqrt(r * r - xmax * xmax) * area = ((xmax - xmin) * (ymax - ymin) - */ __pyx_t_3 = __pyx_f_9photutils_8geometry_4core_floor_sqrt(((__pyx_v_r * __pyx_v_r) - (__pyx_v_ymax * __pyx_v_ymax))); __pyx_t_4 = __pyx_v_ymax; __pyx_v_x1 = __pyx_t_3; __pyx_v_y1 = __pyx_t_4; /* "photutils/geometry/circular_overlap.pyx":207 * if d1 < r and d2 < r: * x1, y1 = floor_sqrt(r * r - ymax * ymax), ymax * x2, y2 = xmax, floor_sqrt(r * r - xmax * xmax) # <<<<<<<<<<<<<< * area = ((xmax - xmin) * (ymax - ymin) - * area_triangle(x1, y1, x2, y2, xmax, ymax) + */ __pyx_t_4 = __pyx_v_xmax; __pyx_t_3 = __pyx_f_9photutils_8geometry_4core_floor_sqrt(((__pyx_v_r * __pyx_v_r) - (__pyx_v_xmax * __pyx_v_xmax))); __pyx_v_x2 = __pyx_t_4; __pyx_v_y2 = __pyx_t_3; /* "photutils/geometry/circular_overlap.pyx":209 * x2, y2 = xmax, floor_sqrt(r * r - xmax * xmax) * area = ((xmax - xmin) * (ymax - ymin) - * area_triangle(x1, y1, x2, y2, xmax, ymax) + # <<<<<<<<<<<<<< * area_arc(x1, y1, x2, y2, r)) * elif d1 < r: */ __pyx_v_area = ((((__pyx_v_xmax - __pyx_v_xmin) * (__pyx_v_ymax - __pyx_v_ymin)) - __pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_xmax, __pyx_v_ymax)) + __pyx_f_9photutils_8geometry_4core_area_arc(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_r)); /* "photutils/geometry/circular_overlap.pyx":205 * d1 = floor_sqrt(xmax * xmax + ymin * ymin) * d2 = floor_sqrt(xmin * xmin + ymax * ymax) * if d1 < r and d2 < r: # <<<<<<<<<<<<<< * x1, y1 = floor_sqrt(r * r - ymax * ymax), ymax * x2, y2 = xmax, floor_sqrt(r * r - xmax * xmax) */ goto __pyx_L4; } /* "photutils/geometry/circular_overlap.pyx":211 * area_triangle(x1, y1, x2, y2, xmax, ymax) + * area_arc(x1, y1, x2, y2, r)) * elif d1 < r: # <<<<<<<<<<<<<< * x1, y1 = xmin, floor_sqrt(r * r - xmin * xmin) * x2, y2 = xmax, floor_sqrt(r * r - xmax * xmax) */ __pyx_t_1 = ((__pyx_v_d1 < __pyx_v_r) != 0); if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":212 * area_arc(x1, y1, x2, y2, r)) * elif d1 < r: * x1, y1 = xmin, floor_sqrt(r * r - xmin * xmin) # <<<<<<<<<<<<<< * x2, y2 = xmax, floor_sqrt(r * r - xmax * xmax) * area = (area_arc(x1, y1, x2, y2, r) + */ __pyx_t_3 = __pyx_v_xmin; __pyx_t_4 = __pyx_f_9photutils_8geometry_4core_floor_sqrt(((__pyx_v_r * __pyx_v_r) - (__pyx_v_xmin * __pyx_v_xmin))); __pyx_v_x1 = __pyx_t_3; __pyx_v_y1 = __pyx_t_4; /* "photutils/geometry/circular_overlap.pyx":213 * elif d1 < r: * x1, y1 = xmin, floor_sqrt(r * r - xmin * xmin) * x2, y2 = xmax, floor_sqrt(r * r - xmax * xmax) # <<<<<<<<<<<<<< * area = (area_arc(x1, y1, x2, y2, r) + * area_triangle(x1, y1, x1, ymin, xmax, ymin) + */ __pyx_t_4 = __pyx_v_xmax; __pyx_t_3 = __pyx_f_9photutils_8geometry_4core_floor_sqrt(((__pyx_v_r * __pyx_v_r) - (__pyx_v_xmax * __pyx_v_xmax))); __pyx_v_x2 = __pyx_t_4; __pyx_v_y2 = __pyx_t_3; /* "photutils/geometry/circular_overlap.pyx":215 * x2, y2 = xmax, floor_sqrt(r * r - xmax * xmax) * area = (area_arc(x1, y1, x2, y2, r) + * area_triangle(x1, y1, x1, ymin, xmax, ymin) + # <<<<<<<<<<<<<< * area_triangle(x1, y1, x2, ymin, x2, y2)) * elif d2 < r: */ __pyx_v_area = ((__pyx_f_9photutils_8geometry_4core_area_arc(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_r) + __pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_x1, __pyx_v_ymin, __pyx_v_xmax, __pyx_v_ymin)) + __pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_ymin, __pyx_v_x2, __pyx_v_y2)); /* "photutils/geometry/circular_overlap.pyx":211 * area_triangle(x1, y1, x2, y2, xmax, ymax) + * area_arc(x1, y1, x2, y2, r)) * elif d1 < r: # <<<<<<<<<<<<<< * x1, y1 = xmin, floor_sqrt(r * r - xmin * xmin) * x2, y2 = xmax, floor_sqrt(r * r - xmax * xmax) */ goto __pyx_L4; } /* "photutils/geometry/circular_overlap.pyx":217 * area_triangle(x1, y1, x1, ymin, xmax, ymin) + * area_triangle(x1, y1, x2, ymin, x2, y2)) * elif d2 < r: # <<<<<<<<<<<<<< * x1, y1 = floor_sqrt(r * r - ymin * ymin), ymin * x2, y2 = floor_sqrt(r * r - ymax * ymax), ymax */ __pyx_t_1 = ((__pyx_v_d2 < __pyx_v_r) != 0); if (__pyx_t_1) { /* "photutils/geometry/circular_overlap.pyx":218 * area_triangle(x1, y1, x2, ymin, x2, y2)) * elif d2 < r: * x1, y1 = floor_sqrt(r * r - ymin * ymin), ymin # <<<<<<<<<<<<<< * x2, y2 = floor_sqrt(r * r - ymax * ymax), ymax * area = (area_arc(x1, y1, x2, y2, r) + */ __pyx_t_3 = __pyx_f_9photutils_8geometry_4core_floor_sqrt(((__pyx_v_r * __pyx_v_r) - (__pyx_v_ymin * __pyx_v_ymin))); __pyx_t_4 = __pyx_v_ymin; __pyx_v_x1 = __pyx_t_3; __pyx_v_y1 = __pyx_t_4; /* "photutils/geometry/circular_overlap.pyx":219 * elif d2 < r: * x1, y1 = floor_sqrt(r * r - ymin * ymin), ymin * x2, y2 = floor_sqrt(r * r - ymax * ymax), ymax # <<<<<<<<<<<<<< * area = (area_arc(x1, y1, x2, y2, r) + * area_triangle(x1, y1, xmin, y1, xmin, ymax) + */ __pyx_t_4 = __pyx_f_9photutils_8geometry_4core_floor_sqrt(((__pyx_v_r * __pyx_v_r) - (__pyx_v_ymax * __pyx_v_ymax))); __pyx_t_3 = __pyx_v_ymax; __pyx_v_x2 = __pyx_t_4; __pyx_v_y2 = __pyx_t_3; /* "photutils/geometry/circular_overlap.pyx":221 * x2, y2 = floor_sqrt(r * r - ymax * ymax), ymax * area = (area_arc(x1, y1, x2, y2, r) + * area_triangle(x1, y1, xmin, y1, xmin, ymax) + # <<<<<<<<<<<<<< * area_triangle(x1, y1, xmin, y2, x2, y2)) * else: */ __pyx_v_area = ((__pyx_f_9photutils_8geometry_4core_area_arc(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_r) + __pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_xmin, __pyx_v_y1, __pyx_v_xmin, __pyx_v_ymax)) + __pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_xmin, __pyx_v_y2, __pyx_v_x2, __pyx_v_y2)); /* "photutils/geometry/circular_overlap.pyx":217 * area_triangle(x1, y1, x1, ymin, xmax, ymin) + * area_triangle(x1, y1, x2, ymin, x2, y2)) * elif d2 < r: # <<<<<<<<<<<<<< * x1, y1 = floor_sqrt(r * r - ymin * ymin), ymin * x2, y2 = floor_sqrt(r * r - ymax * ymax), ymax */ goto __pyx_L4; } /* "photutils/geometry/circular_overlap.pyx":224 * area_triangle(x1, y1, xmin, y2, x2, y2)) * else: * x1, y1 = floor_sqrt(r * r - ymin * ymin), ymin # <<<<<<<<<<<<<< * x2, y2 = xmin, floor_sqrt(r * r - xmin * xmin) * area = (area_arc(x1, y1, x2, y2, r) + */ /*else*/ { __pyx_t_3 = __pyx_f_9photutils_8geometry_4core_floor_sqrt(((__pyx_v_r * __pyx_v_r) - (__pyx_v_ymin * __pyx_v_ymin))); __pyx_t_4 = __pyx_v_ymin; __pyx_v_x1 = __pyx_t_3; __pyx_v_y1 = __pyx_t_4; /* "photutils/geometry/circular_overlap.pyx":225 * else: * x1, y1 = floor_sqrt(r * r - ymin * ymin), ymin * x2, y2 = xmin, floor_sqrt(r * r - xmin * xmin) # <<<<<<<<<<<<<< * area = (area_arc(x1, y1, x2, y2, r) + * area_triangle(x1, y1, x2, y2, xmin, ymin)) */ __pyx_t_4 = __pyx_v_xmin; __pyx_t_3 = __pyx_f_9photutils_8geometry_4core_floor_sqrt(((__pyx_v_r * __pyx_v_r) - (__pyx_v_xmin * __pyx_v_xmin))); __pyx_v_x2 = __pyx_t_4; __pyx_v_y2 = __pyx_t_3; /* "photutils/geometry/circular_overlap.pyx":226 * x1, y1 = floor_sqrt(r * r - ymin * ymin), ymin * x2, y2 = xmin, floor_sqrt(r * r - xmin * xmin) * area = (area_arc(x1, y1, x2, y2, r) + # <<<<<<<<<<<<<< * area_triangle(x1, y1, x2, y2, xmin, ymin)) * */ __pyx_v_area = (__pyx_f_9photutils_8geometry_4core_area_arc(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_r) + __pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_xmin, __pyx_v_ymin)); } __pyx_L4:; } __pyx_L3:; /* "photutils/geometry/circular_overlap.pyx":229 * area_triangle(x1, y1, x2, y2, xmin, ymin)) * * return area # <<<<<<<<<<<<<< */ __pyx_r = __pyx_v_area; goto __pyx_L0; /* "photutils/geometry/circular_overlap.pyx":188 * * * cdef double circular_overlap_core(double xmin, double ymin, double xmax, double ymax, # <<<<<<<<<<<<<< * double r): * """ */ /* function exit code */ __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":258 * # experimental exception made for __getbuffer__ and __releasebuffer__ * # -- the details of this may change. * def __getbuffer__(ndarray self, Py_buffer* info, int flags): # <<<<<<<<<<<<<< * # This implementation of getbuffer is geared towards Cython * # requirements, and does not yet fulfill the PEP. */ /* Python wrapper */ static CYTHON_UNUSED int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ static CYTHON_UNUSED int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { int __pyx_r; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0); __pyx_r = __pyx_pf_5numpy_7ndarray___getbuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags)); /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { int __pyx_v_i; int __pyx_v_ndim; int __pyx_v_endian_detector; int __pyx_v_little_endian; int __pyx_v_t; char *__pyx_v_f; PyArray_Descr *__pyx_v_descr = 0; int __pyx_v_offset; int __pyx_r; __Pyx_RefNannyDeclarations int __pyx_t_1; int __pyx_t_2; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; int __pyx_t_5; int __pyx_t_6; PyArray_Descr *__pyx_t_7; PyObject *__pyx_t_8 = NULL; char *__pyx_t_9; if (__pyx_v_info == NULL) { PyErr_SetString(PyExc_BufferError, "PyObject_GetBuffer: view==NULL argument is obsolete"); return -1; } __Pyx_RefNannySetupContext("__getbuffer__", 0); __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None); __Pyx_GIVEREF(__pyx_v_info->obj); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":265 * * cdef int i, ndim * cdef int endian_detector = 1 # <<<<<<<<<<<<<< * cdef bint little_endian = ((&endian_detector)[0] != 0) * */ __pyx_v_endian_detector = 1; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":266 * cdef int i, ndim * cdef int endian_detector = 1 * cdef bint little_endian = ((&endian_detector)[0] != 0) # <<<<<<<<<<<<<< * * ndim = PyArray_NDIM(self) */ __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":268 * cdef bint little_endian = ((&endian_detector)[0] != 0) * * ndim = PyArray_NDIM(self) # <<<<<<<<<<<<<< * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) */ __pyx_v_ndim = PyArray_NDIM(__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":270 * ndim = PyArray_NDIM(self) * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") */ __pyx_t_2 = (((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L4_bool_binop_done; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":271 * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): # <<<<<<<<<<<<<< * raise ValueError(u"ndarray is not C contiguous") * */ __pyx_t_2 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_ARRAY_C_CONTIGUOUS) != 0)) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L4_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":270 * ndim = PyArray_NDIM(self) * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") */ if (unlikely(__pyx_t_1)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":272 * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") # <<<<<<<<<<<<<< * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 272, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 272, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":270 * ndim = PyArray_NDIM(self) * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":274 * raise ValueError(u"ndarray is not C contiguous") * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") */ __pyx_t_2 = (((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L7_bool_binop_done; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":275 * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): # <<<<<<<<<<<<<< * raise ValueError(u"ndarray is not Fortran contiguous") * */ __pyx_t_2 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_ARRAY_F_CONTIGUOUS) != 0)) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L7_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":274 * raise ValueError(u"ndarray is not C contiguous") * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") */ if (unlikely(__pyx_t_1)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":276 * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") # <<<<<<<<<<<<<< * * info.buf = PyArray_DATA(self) */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 276, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 276, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":274 * raise ValueError(u"ndarray is not C contiguous") * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":278 * raise ValueError(u"ndarray is not Fortran contiguous") * * info.buf = PyArray_DATA(self) # <<<<<<<<<<<<<< * info.ndim = ndim * if sizeof(npy_intp) != sizeof(Py_ssize_t): */ __pyx_v_info->buf = PyArray_DATA(__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":279 * * info.buf = PyArray_DATA(self) * info.ndim = ndim # <<<<<<<<<<<<<< * if sizeof(npy_intp) != sizeof(Py_ssize_t): * # Allocate new buffer for strides and shape info. */ __pyx_v_info->ndim = __pyx_v_ndim; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":280 * info.buf = PyArray_DATA(self) * info.ndim = ndim * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * # Allocate new buffer for strides and shape info. * # This is allocated as one block, strides first. */ __pyx_t_1 = (((sizeof(npy_intp)) != (sizeof(Py_ssize_t))) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":283 * # Allocate new buffer for strides and shape info. * # This is allocated as one block, strides first. * info.strides = PyObject_Malloc(sizeof(Py_ssize_t) * 2 * ndim) # <<<<<<<<<<<<<< * info.shape = info.strides + ndim * for i in range(ndim): */ __pyx_v_info->strides = ((Py_ssize_t *)PyObject_Malloc((((sizeof(Py_ssize_t)) * 2) * ((size_t)__pyx_v_ndim)))); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":284 * # This is allocated as one block, strides first. * info.strides = PyObject_Malloc(sizeof(Py_ssize_t) * 2 * ndim) * info.shape = info.strides + ndim # <<<<<<<<<<<<<< * for i in range(ndim): * info.strides[i] = PyArray_STRIDES(self)[i] */ __pyx_v_info->shape = (__pyx_v_info->strides + __pyx_v_ndim); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":285 * info.strides = PyObject_Malloc(sizeof(Py_ssize_t) * 2 * ndim) * info.shape = info.strides + ndim * for i in range(ndim): # <<<<<<<<<<<<<< * info.strides[i] = PyArray_STRIDES(self)[i] * info.shape[i] = PyArray_DIMS(self)[i] */ __pyx_t_4 = __pyx_v_ndim; __pyx_t_5 = __pyx_t_4; for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { __pyx_v_i = __pyx_t_6; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":286 * info.shape = info.strides + ndim * for i in range(ndim): * info.strides[i] = PyArray_STRIDES(self)[i] # <<<<<<<<<<<<<< * info.shape[i] = PyArray_DIMS(self)[i] * else: */ (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(__pyx_v_self)[__pyx_v_i]); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":287 * for i in range(ndim): * info.strides[i] = PyArray_STRIDES(self)[i] * info.shape[i] = PyArray_DIMS(self)[i] # <<<<<<<<<<<<<< * else: * info.strides = PyArray_STRIDES(self) */ (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(__pyx_v_self)[__pyx_v_i]); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":280 * info.buf = PyArray_DATA(self) * info.ndim = ndim * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * # Allocate new buffer for strides and shape info. * # This is allocated as one block, strides first. */ goto __pyx_L9; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":289 * info.shape[i] = PyArray_DIMS(self)[i] * else: * info.strides = PyArray_STRIDES(self) # <<<<<<<<<<<<<< * info.shape = PyArray_DIMS(self) * info.suboffsets = NULL */ /*else*/ { __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(__pyx_v_self)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":290 * else: * info.strides = PyArray_STRIDES(self) * info.shape = PyArray_DIMS(self) # <<<<<<<<<<<<<< * info.suboffsets = NULL * info.itemsize = PyArray_ITEMSIZE(self) */ __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(__pyx_v_self)); } __pyx_L9:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":291 * info.strides = PyArray_STRIDES(self) * info.shape = PyArray_DIMS(self) * info.suboffsets = NULL # <<<<<<<<<<<<<< * info.itemsize = PyArray_ITEMSIZE(self) * info.readonly = not PyArray_ISWRITEABLE(self) */ __pyx_v_info->suboffsets = NULL; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":292 * info.shape = PyArray_DIMS(self) * info.suboffsets = NULL * info.itemsize = PyArray_ITEMSIZE(self) # <<<<<<<<<<<<<< * info.readonly = not PyArray_ISWRITEABLE(self) * */ __pyx_v_info->itemsize = PyArray_ITEMSIZE(__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":293 * info.suboffsets = NULL * info.itemsize = PyArray_ITEMSIZE(self) * info.readonly = not PyArray_ISWRITEABLE(self) # <<<<<<<<<<<<<< * * cdef int t */ __pyx_v_info->readonly = (!(PyArray_ISWRITEABLE(__pyx_v_self) != 0)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":296 * * cdef int t * cdef char* f = NULL # <<<<<<<<<<<<<< * cdef dtype descr = PyArray_DESCR(self) * cdef int offset */ __pyx_v_f = NULL; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":297 * cdef int t * cdef char* f = NULL * cdef dtype descr = PyArray_DESCR(self) # <<<<<<<<<<<<<< * cdef int offset * */ __pyx_t_7 = PyArray_DESCR(__pyx_v_self); __pyx_t_3 = ((PyObject *)__pyx_t_7); __Pyx_INCREF(__pyx_t_3); __pyx_v_descr = ((PyArray_Descr *)__pyx_t_3); __pyx_t_3 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":300 * cdef int offset * * info.obj = self # <<<<<<<<<<<<<< * * if not PyDataType_HASFIELDS(descr): */ __Pyx_INCREF(((PyObject *)__pyx_v_self)); __Pyx_GIVEREF(((PyObject *)__pyx_v_self)); __Pyx_GOTREF(__pyx_v_info->obj); __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = ((PyObject *)__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":302 * info.obj = self * * if not PyDataType_HASFIELDS(descr): # <<<<<<<<<<<<<< * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or */ __pyx_t_1 = ((!(PyDataType_HASFIELDS(__pyx_v_descr) != 0)) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":303 * * if not PyDataType_HASFIELDS(descr): * t = descr.type_num # <<<<<<<<<<<<<< * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): */ __pyx_t_4 = __pyx_v_descr->type_num; __pyx_v_t = __pyx_t_4; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":304 * if not PyDataType_HASFIELDS(descr): * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ __pyx_t_2 = ((__pyx_v_descr->byteorder == '>') != 0); if (!__pyx_t_2) { goto __pyx_L15_next_or; } else { } __pyx_t_2 = (__pyx_v_little_endian != 0); if (!__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L14_bool_binop_done; } __pyx_L15_next_or:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":305 * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): # <<<<<<<<<<<<<< * raise ValueError(u"Non-native byte order not supported") * if t == NPY_BYTE: f = "b" */ __pyx_t_2 = ((__pyx_v_descr->byteorder == '<') != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L14_bool_binop_done; } __pyx_t_2 = ((!(__pyx_v_little_endian != 0)) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L14_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":304 * if not PyDataType_HASFIELDS(descr): * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ if (unlikely(__pyx_t_1)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":306 * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 306, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 306, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":304 * if not PyDataType_HASFIELDS(descr): * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":307 * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") * if t == NPY_BYTE: f = "b" # <<<<<<<<<<<<<< * elif t == NPY_UBYTE: f = "B" * elif t == NPY_SHORT: f = "h" */ switch (__pyx_v_t) { case NPY_BYTE: __pyx_v_f = ((char *)"b"); break; case NPY_UBYTE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":308 * raise ValueError(u"Non-native byte order not supported") * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" # <<<<<<<<<<<<<< * elif t == NPY_SHORT: f = "h" * elif t == NPY_USHORT: f = "H" */ __pyx_v_f = ((char *)"B"); break; case NPY_SHORT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":309 * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" * elif t == NPY_SHORT: f = "h" # <<<<<<<<<<<<<< * elif t == NPY_USHORT: f = "H" * elif t == NPY_INT: f = "i" */ __pyx_v_f = ((char *)"h"); break; case NPY_USHORT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":310 * elif t == NPY_UBYTE: f = "B" * elif t == NPY_SHORT: f = "h" * elif t == NPY_USHORT: f = "H" # <<<<<<<<<<<<<< * elif t == NPY_INT: f = "i" * elif t == NPY_UINT: f = "I" */ __pyx_v_f = ((char *)"H"); break; case NPY_INT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":311 * elif t == NPY_SHORT: f = "h" * elif t == NPY_USHORT: f = "H" * elif t == NPY_INT: f = "i" # <<<<<<<<<<<<<< * elif t == NPY_UINT: f = "I" * elif t == NPY_LONG: f = "l" */ __pyx_v_f = ((char *)"i"); break; case NPY_UINT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":312 * elif t == NPY_USHORT: f = "H" * elif t == NPY_INT: f = "i" * elif t == NPY_UINT: f = "I" # <<<<<<<<<<<<<< * elif t == NPY_LONG: f = "l" * elif t == NPY_ULONG: f = "L" */ __pyx_v_f = ((char *)"I"); break; case NPY_LONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":313 * elif t == NPY_INT: f = "i" * elif t == NPY_UINT: f = "I" * elif t == NPY_LONG: f = "l" # <<<<<<<<<<<<<< * elif t == NPY_ULONG: f = "L" * elif t == NPY_LONGLONG: f = "q" */ __pyx_v_f = ((char *)"l"); break; case NPY_ULONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":314 * elif t == NPY_UINT: f = "I" * elif t == NPY_LONG: f = "l" * elif t == NPY_ULONG: f = "L" # <<<<<<<<<<<<<< * elif t == NPY_LONGLONG: f = "q" * elif t == NPY_ULONGLONG: f = "Q" */ __pyx_v_f = ((char *)"L"); break; case NPY_LONGLONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":315 * elif t == NPY_LONG: f = "l" * elif t == NPY_ULONG: f = "L" * elif t == NPY_LONGLONG: f = "q" # <<<<<<<<<<<<<< * elif t == NPY_ULONGLONG: f = "Q" * elif t == NPY_FLOAT: f = "f" */ __pyx_v_f = ((char *)"q"); break; case NPY_ULONGLONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":316 * elif t == NPY_ULONG: f = "L" * elif t == NPY_LONGLONG: f = "q" * elif t == NPY_ULONGLONG: f = "Q" # <<<<<<<<<<<<<< * elif t == NPY_FLOAT: f = "f" * elif t == NPY_DOUBLE: f = "d" */ __pyx_v_f = ((char *)"Q"); break; case NPY_FLOAT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":317 * elif t == NPY_LONGLONG: f = "q" * elif t == NPY_ULONGLONG: f = "Q" * elif t == NPY_FLOAT: f = "f" # <<<<<<<<<<<<<< * elif t == NPY_DOUBLE: f = "d" * elif t == NPY_LONGDOUBLE: f = "g" */ __pyx_v_f = ((char *)"f"); break; case NPY_DOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":318 * elif t == NPY_ULONGLONG: f = "Q" * elif t == NPY_FLOAT: f = "f" * elif t == NPY_DOUBLE: f = "d" # <<<<<<<<<<<<<< * elif t == NPY_LONGDOUBLE: f = "g" * elif t == NPY_CFLOAT: f = "Zf" */ __pyx_v_f = ((char *)"d"); break; case NPY_LONGDOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":319 * elif t == NPY_FLOAT: f = "f" * elif t == NPY_DOUBLE: f = "d" * elif t == NPY_LONGDOUBLE: f = "g" # <<<<<<<<<<<<<< * elif t == NPY_CFLOAT: f = "Zf" * elif t == NPY_CDOUBLE: f = "Zd" */ __pyx_v_f = ((char *)"g"); break; case NPY_CFLOAT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":320 * elif t == NPY_DOUBLE: f = "d" * elif t == NPY_LONGDOUBLE: f = "g" * elif t == NPY_CFLOAT: f = "Zf" # <<<<<<<<<<<<<< * elif t == NPY_CDOUBLE: f = "Zd" * elif t == NPY_CLONGDOUBLE: f = "Zg" */ __pyx_v_f = ((char *)"Zf"); break; case NPY_CDOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":321 * elif t == NPY_LONGDOUBLE: f = "g" * elif t == NPY_CFLOAT: f = "Zf" * elif t == NPY_CDOUBLE: f = "Zd" # <<<<<<<<<<<<<< * elif t == NPY_CLONGDOUBLE: f = "Zg" * elif t == NPY_OBJECT: f = "O" */ __pyx_v_f = ((char *)"Zd"); break; case NPY_CLONGDOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":322 * elif t == NPY_CFLOAT: f = "Zf" * elif t == NPY_CDOUBLE: f = "Zd" * elif t == NPY_CLONGDOUBLE: f = "Zg" # <<<<<<<<<<<<<< * elif t == NPY_OBJECT: f = "O" * else: */ __pyx_v_f = ((char *)"Zg"); break; case NPY_OBJECT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":323 * elif t == NPY_CDOUBLE: f = "Zd" * elif t == NPY_CLONGDOUBLE: f = "Zg" * elif t == NPY_OBJECT: f = "O" # <<<<<<<<<<<<<< * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) */ __pyx_v_f = ((char *)"O"); break; default: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":325 * elif t == NPY_OBJECT: f = "O" * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) # <<<<<<<<<<<<<< * info.format = f * return */ __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_8 = PyUnicode_Format(__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_t_3); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 325, __pyx_L1_error) break; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":326 * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) * info.format = f # <<<<<<<<<<<<<< * return * else: */ __pyx_v_info->format = __pyx_v_f; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":327 * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) * info.format = f * return # <<<<<<<<<<<<<< * else: * info.format = PyObject_Malloc(_buffer_format_string_len) */ __pyx_r = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":302 * info.obj = self * * if not PyDataType_HASFIELDS(descr): # <<<<<<<<<<<<<< * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":329 * return * else: * info.format = PyObject_Malloc(_buffer_format_string_len) # <<<<<<<<<<<<<< * info.format[0] = c'^' # Native data types, manual alignment * offset = 0 */ /*else*/ { __pyx_v_info->format = ((char *)PyObject_Malloc(0xFF)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":330 * else: * info.format = PyObject_Malloc(_buffer_format_string_len) * info.format[0] = c'^' # Native data types, manual alignment # <<<<<<<<<<<<<< * offset = 0 * f = _util_dtypestring(descr, info.format + 1, */ (__pyx_v_info->format[0]) = '^'; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":331 * info.format = PyObject_Malloc(_buffer_format_string_len) * info.format[0] = c'^' # Native data types, manual alignment * offset = 0 # <<<<<<<<<<<<<< * f = _util_dtypestring(descr, info.format + 1, * info.format + _buffer_format_string_len, */ __pyx_v_offset = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":332 * info.format[0] = c'^' # Native data types, manual alignment * offset = 0 * f = _util_dtypestring(descr, info.format + 1, # <<<<<<<<<<<<<< * info.format + _buffer_format_string_len, * &offset) */ __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 0xFF), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == ((char *)NULL))) __PYX_ERR(1, 332, __pyx_L1_error) __pyx_v_f = __pyx_t_9; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":335 * info.format + _buffer_format_string_len, * &offset) * f[0] = c'\0' # Terminate format string # <<<<<<<<<<<<<< * * def __releasebuffer__(ndarray self, Py_buffer* info): */ (__pyx_v_f[0]) = '\x00'; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":258 * # experimental exception made for __getbuffer__ and __releasebuffer__ * # -- the details of this may change. * def __getbuffer__(ndarray self, Py_buffer* info, int flags): # <<<<<<<<<<<<<< * # This implementation of getbuffer is geared towards Cython * # requirements, and does not yet fulfill the PEP. */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.ndarray.__getbuffer__", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; if (__pyx_v_info->obj != NULL) { __Pyx_GOTREF(__pyx_v_info->obj); __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; } goto __pyx_L2; __pyx_L0:; if (__pyx_v_info->obj == Py_None) { __Pyx_GOTREF(__pyx_v_info->obj); __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; } __pyx_L2:; __Pyx_XDECREF((PyObject *)__pyx_v_descr); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":337 * f[0] = c'\0' # Terminate format string * * def __releasebuffer__(ndarray self, Py_buffer* info): # <<<<<<<<<<<<<< * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) */ /* Python wrapper */ static CYTHON_UNUSED void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/ static CYTHON_UNUSED void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__releasebuffer__ (wrapper)", 0); __pyx_pf_5numpy_7ndarray_2__releasebuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info)); /* function exit code */ __Pyx_RefNannyFinishContext(); } static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info) { __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("__releasebuffer__", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":338 * * def __releasebuffer__(ndarray self, Py_buffer* info): * if PyArray_HASFIELDS(self): # <<<<<<<<<<<<<< * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): */ __pyx_t_1 = (PyArray_HASFIELDS(__pyx_v_self) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":339 * def __releasebuffer__(ndarray self, Py_buffer* info): * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) # <<<<<<<<<<<<<< * if sizeof(npy_intp) != sizeof(Py_ssize_t): * PyObject_Free(info.strides) */ PyObject_Free(__pyx_v_info->format); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":338 * * def __releasebuffer__(ndarray self, Py_buffer* info): * if PyArray_HASFIELDS(self): # <<<<<<<<<<<<<< * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":340 * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * PyObject_Free(info.strides) * # info.shape was stored after info.strides in the same block */ __pyx_t_1 = (((sizeof(npy_intp)) != (sizeof(Py_ssize_t))) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":341 * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): * PyObject_Free(info.strides) # <<<<<<<<<<<<<< * # info.shape was stored after info.strides in the same block * */ PyObject_Free(__pyx_v_info->strides); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":340 * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * PyObject_Free(info.strides) * # info.shape was stored after info.strides in the same block */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":337 * f[0] = c'\0' # Terminate format string * * def __releasebuffer__(ndarray self, Py_buffer* info): # <<<<<<<<<<<<<< * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) */ /* function exit code */ __Pyx_RefNannyFinishContext(); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":821 * ctypedef npy_cdouble complex_t * * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(1, a) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":822 * * cdef inline object PyArray_MultiIterNew1(a): * return PyArray_MultiIterNew(1, a) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew2(a, b): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 822, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":821 * ctypedef npy_cdouble complex_t * * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(1, a) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":824 * return PyArray_MultiIterNew(1, a) * * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(2, a, b) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":825 * * cdef inline object PyArray_MultiIterNew2(a, b): * return PyArray_MultiIterNew(2, a, b) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew3(a, b, c): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 825, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":824 * return PyArray_MultiIterNew(1, a) * * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(2, a, b) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":827 * return PyArray_MultiIterNew(2, a, b) * * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(3, a, b, c) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":828 * * cdef inline object PyArray_MultiIterNew3(a, b, c): * return PyArray_MultiIterNew(3, a, b, c) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 828, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":827 * return PyArray_MultiIterNew(2, a, b) * * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(3, a, b, c) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":830 * return PyArray_MultiIterNew(3, a, b, c) * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(4, a, b, c, d) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":831 * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): * return PyArray_MultiIterNew(4, a, b, c, d) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 831, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":830 * return PyArray_MultiIterNew(3, a, b, c) * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(4, a, b, c, d) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":833 * return PyArray_MultiIterNew(4, a, b, c, d) * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(5, a, b, c, d, e) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":834 * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): * return PyArray_MultiIterNew(5, a, b, c, d, e) # <<<<<<<<<<<<<< * * cdef inline tuple PyDataType_SHAPE(dtype d): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 834, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":833 * return PyArray_MultiIterNew(4, a, b, c, d) * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(5, a, b, c, d, e) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":836 * return PyArray_MultiIterNew(5, a, b, c, d, e) * * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__pyx_v_d) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("PyDataType_SHAPE", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":837 * * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< * return d.subarray.shape * else: */ __pyx_t_1 = (PyDataType_HASSUBARRAY(__pyx_v_d) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":838 * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape # <<<<<<<<<<<<<< * else: * return () */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(((PyObject*)__pyx_v_d->subarray->shape)); __pyx_r = ((PyObject*)__pyx_v_d->subarray->shape); goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":837 * * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< * return d.subarray.shape * else: */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":840 * return d.subarray.shape * else: * return () # <<<<<<<<<<<<<< * * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: */ /*else*/ { __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(__pyx_empty_tuple); __pyx_r = __pyx_empty_tuple; goto __pyx_L0; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":836 * return PyArray_MultiIterNew(5, a, b, c, d, e) * * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape */ /* function exit code */ __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":842 * return () * * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: # <<<<<<<<<<<<<< * # Recursive utility function used in __getbuffer__ to get format * # string. The new location in the format string is returned. */ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx_v_descr, char *__pyx_v_f, char *__pyx_v_end, int *__pyx_v_offset) { PyArray_Descr *__pyx_v_child = 0; int __pyx_v_endian_detector; int __pyx_v_little_endian; PyObject *__pyx_v_fields = 0; PyObject *__pyx_v_childname = NULL; PyObject *__pyx_v_new_offset = NULL; PyObject *__pyx_v_t = NULL; char *__pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; Py_ssize_t __pyx_t_2; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; int __pyx_t_5; int __pyx_t_6; int __pyx_t_7; long __pyx_t_8; char *__pyx_t_9; __Pyx_RefNannySetupContext("_util_dtypestring", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":847 * * cdef dtype child * cdef int endian_detector = 1 # <<<<<<<<<<<<<< * cdef bint little_endian = ((&endian_detector)[0] != 0) * cdef tuple fields */ __pyx_v_endian_detector = 1; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":848 * cdef dtype child * cdef int endian_detector = 1 * cdef bint little_endian = ((&endian_detector)[0] != 0) # <<<<<<<<<<<<<< * cdef tuple fields * */ __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":851 * cdef tuple fields * * for childname in descr.names: # <<<<<<<<<<<<<< * fields = descr.fields[childname] * child, new_offset = fields */ if (unlikely(__pyx_v_descr->names == Py_None)) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); __PYX_ERR(1, 851, __pyx_L1_error) } __pyx_t_1 = __pyx_v_descr->names; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0; for (;;) { if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break; #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) __PYX_ERR(1, 851, __pyx_L1_error) #else __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 851, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); #endif __Pyx_XDECREF_SET(__pyx_v_childname, __pyx_t_3); __pyx_t_3 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":852 * * for childname in descr.names: * fields = descr.fields[childname] # <<<<<<<<<<<<<< * child, new_offset = fields * */ if (unlikely(__pyx_v_descr->fields == Py_None)) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); __PYX_ERR(1, 852, __pyx_L1_error) } __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 852, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(1, 852, __pyx_L1_error) __Pyx_XDECREF_SET(__pyx_v_fields, ((PyObject*)__pyx_t_3)); __pyx_t_3 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":853 * for childname in descr.names: * fields = descr.fields[childname] * child, new_offset = fields # <<<<<<<<<<<<<< * * if (end - f) - (new_offset - offset[0]) < 15: */ if (likely(__pyx_v_fields != Py_None)) { PyObject* sequence = __pyx_v_fields; Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); if (unlikely(size != 2)) { if (size > 2) __Pyx_RaiseTooManyValuesError(2); else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); __PYX_ERR(1, 853, __pyx_L1_error) } #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); __Pyx_INCREF(__pyx_t_3); __Pyx_INCREF(__pyx_t_4); #else __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 853, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 853, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); #endif } else { __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(1, 853, __pyx_L1_error) } if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) __PYX_ERR(1, 853, __pyx_L1_error) __Pyx_XDECREF_SET(__pyx_v_child, ((PyArray_Descr *)__pyx_t_3)); __pyx_t_3 = 0; __Pyx_XDECREF_SET(__pyx_v_new_offset, __pyx_t_4); __pyx_t_4 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":855 * child, new_offset = fields * * if (end - f) - (new_offset - offset[0]) < 15: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * */ __pyx_t_4 = __Pyx_PyInt_From_int((__pyx_v_offset[0])); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 855, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 855, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_5 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_5 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 855, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = ((((__pyx_v_end - __pyx_v_f) - ((int)__pyx_t_5)) < 15) != 0); if (unlikely(__pyx_t_6)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":856 * * if (end - f) - (new_offset - offset[0]) < 15: * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") # <<<<<<<<<<<<<< * * if ((child.byteorder == c'>' and little_endian) or */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 856, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 856, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":855 * child, new_offset = fields * * if (end - f) - (new_offset - offset[0]) < 15: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":858 * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ __pyx_t_7 = ((__pyx_v_child->byteorder == '>') != 0); if (!__pyx_t_7) { goto __pyx_L8_next_or; } else { } __pyx_t_7 = (__pyx_v_little_endian != 0); if (!__pyx_t_7) { } else { __pyx_t_6 = __pyx_t_7; goto __pyx_L7_bool_binop_done; } __pyx_L8_next_or:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":859 * * if ((child.byteorder == c'>' and little_endian) or * (child.byteorder == c'<' and not little_endian)): # <<<<<<<<<<<<<< * raise ValueError(u"Non-native byte order not supported") * # One could encode it in the format string and have Cython */ __pyx_t_7 = ((__pyx_v_child->byteorder == '<') != 0); if (__pyx_t_7) { } else { __pyx_t_6 = __pyx_t_7; goto __pyx_L7_bool_binop_done; } __pyx_t_7 = ((!(__pyx_v_little_endian != 0)) != 0); __pyx_t_6 = __pyx_t_7; __pyx_L7_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":858 * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ if (unlikely(__pyx_t_6)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":860 * if ((child.byteorder == c'>' and little_endian) or * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< * # One could encode it in the format string and have Cython * # complain instead, BUT: < and > in format strings also imply */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 860, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 860, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":858 * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":870 * * # Output padding bytes * while offset[0] < new_offset: # <<<<<<<<<<<<<< * f[0] = 120 # "x"; pad byte * f += 1 */ while (1) { __pyx_t_3 = __Pyx_PyInt_From_int((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 870, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_t_3, __pyx_v_new_offset, Py_LT); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 870, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 870, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (!__pyx_t_6) break; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":871 * # Output padding bytes * while offset[0] < new_offset: * f[0] = 120 # "x"; pad byte # <<<<<<<<<<<<<< * f += 1 * offset[0] += 1 */ (__pyx_v_f[0]) = 0x78; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":872 * while offset[0] < new_offset: * f[0] = 120 # "x"; pad byte * f += 1 # <<<<<<<<<<<<<< * offset[0] += 1 * */ __pyx_v_f = (__pyx_v_f + 1); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":873 * f[0] = 120 # "x"; pad byte * f += 1 * offset[0] += 1 # <<<<<<<<<<<<<< * * offset[0] += child.itemsize */ __pyx_t_8 = 0; (__pyx_v_offset[__pyx_t_8]) = ((__pyx_v_offset[__pyx_t_8]) + 1); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":875 * offset[0] += 1 * * offset[0] += child.itemsize # <<<<<<<<<<<<<< * * if not PyDataType_HASFIELDS(child): */ __pyx_t_8 = 0; (__pyx_v_offset[__pyx_t_8]) = ((__pyx_v_offset[__pyx_t_8]) + __pyx_v_child->elsize); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":877 * offset[0] += child.itemsize * * if not PyDataType_HASFIELDS(child): # <<<<<<<<<<<<<< * t = child.type_num * if end - f < 5: */ __pyx_t_6 = ((!(PyDataType_HASFIELDS(__pyx_v_child) != 0)) != 0); if (__pyx_t_6) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":878 * * if not PyDataType_HASFIELDS(child): * t = child.type_num # <<<<<<<<<<<<<< * if end - f < 5: * raise RuntimeError(u"Format string allocated too short.") */ __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_child->type_num); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 878, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_4); __pyx_t_4 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":879 * if not PyDataType_HASFIELDS(child): * t = child.type_num * if end - f < 5: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short.") * */ __pyx_t_6 = (((__pyx_v_end - __pyx_v_f) < 5) != 0); if (unlikely(__pyx_t_6)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":880 * t = child.type_num * if end - f < 5: * raise RuntimeError(u"Format string allocated too short.") # <<<<<<<<<<<<<< * * # Until ticket #99 is fixed, use integers to avoid warnings */ __pyx_t_4 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 880, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_Raise(__pyx_t_4, 0, 0, 0); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __PYX_ERR(1, 880, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":879 * if not PyDataType_HASFIELDS(child): * t = child.type_num * if end - f < 5: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short.") * */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":883 * * # Until ticket #99 is fixed, use integers to avoid warnings * if t == NPY_BYTE: f[0] = 98 #"b" # <<<<<<<<<<<<<< * elif t == NPY_UBYTE: f[0] = 66 #"B" * elif t == NPY_SHORT: f[0] = 104 #"h" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_BYTE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 883, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 883, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 883, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 98; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":884 * # Until ticket #99 is fixed, use integers to avoid warnings * if t == NPY_BYTE: f[0] = 98 #"b" * elif t == NPY_UBYTE: f[0] = 66 #"B" # <<<<<<<<<<<<<< * elif t == NPY_SHORT: f[0] = 104 #"h" * elif t == NPY_USHORT: f[0] = 72 #"H" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_UBYTE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 884, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 884, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 884, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 66; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":885 * if t == NPY_BYTE: f[0] = 98 #"b" * elif t == NPY_UBYTE: f[0] = 66 #"B" * elif t == NPY_SHORT: f[0] = 104 #"h" # <<<<<<<<<<<<<< * elif t == NPY_USHORT: f[0] = 72 #"H" * elif t == NPY_INT: f[0] = 105 #"i" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_SHORT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 885, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 885, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 885, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x68; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":886 * elif t == NPY_UBYTE: f[0] = 66 #"B" * elif t == NPY_SHORT: f[0] = 104 #"h" * elif t == NPY_USHORT: f[0] = 72 #"H" # <<<<<<<<<<<<<< * elif t == NPY_INT: f[0] = 105 #"i" * elif t == NPY_UINT: f[0] = 73 #"I" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_USHORT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 886, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 886, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 886, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 72; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":887 * elif t == NPY_SHORT: f[0] = 104 #"h" * elif t == NPY_USHORT: f[0] = 72 #"H" * elif t == NPY_INT: f[0] = 105 #"i" # <<<<<<<<<<<<<< * elif t == NPY_UINT: f[0] = 73 #"I" * elif t == NPY_LONG: f[0] = 108 #"l" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_INT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 887, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 887, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 887, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x69; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":888 * elif t == NPY_USHORT: f[0] = 72 #"H" * elif t == NPY_INT: f[0] = 105 #"i" * elif t == NPY_UINT: f[0] = 73 #"I" # <<<<<<<<<<<<<< * elif t == NPY_LONG: f[0] = 108 #"l" * elif t == NPY_ULONG: f[0] = 76 #"L" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_UINT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 888, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 888, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 888, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 73; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":889 * elif t == NPY_INT: f[0] = 105 #"i" * elif t == NPY_UINT: f[0] = 73 #"I" * elif t == NPY_LONG: f[0] = 108 #"l" # <<<<<<<<<<<<<< * elif t == NPY_ULONG: f[0] = 76 #"L" * elif t == NPY_LONGLONG: f[0] = 113 #"q" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONG); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 889, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 889, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 889, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x6C; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":890 * elif t == NPY_UINT: f[0] = 73 #"I" * elif t == NPY_LONG: f[0] = 108 #"l" * elif t == NPY_ULONG: f[0] = 76 #"L" # <<<<<<<<<<<<<< * elif t == NPY_LONGLONG: f[0] = 113 #"q" * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_ULONG); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 890, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 890, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 890, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 76; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":891 * elif t == NPY_LONG: f[0] = 108 #"l" * elif t == NPY_ULONG: f[0] = 76 #"L" * elif t == NPY_LONGLONG: f[0] = 113 #"q" # <<<<<<<<<<<<<< * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" * elif t == NPY_FLOAT: f[0] = 102 #"f" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONGLONG); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 891, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 891, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 891, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x71; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":892 * elif t == NPY_ULONG: f[0] = 76 #"L" * elif t == NPY_LONGLONG: f[0] = 113 #"q" * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" # <<<<<<<<<<<<<< * elif t == NPY_FLOAT: f[0] = 102 #"f" * elif t == NPY_DOUBLE: f[0] = 100 #"d" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_ULONGLONG); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 892, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 892, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 892, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 81; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":893 * elif t == NPY_LONGLONG: f[0] = 113 #"q" * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" * elif t == NPY_FLOAT: f[0] = 102 #"f" # <<<<<<<<<<<<<< * elif t == NPY_DOUBLE: f[0] = 100 #"d" * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_FLOAT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 893, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 893, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 893, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x66; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":894 * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" * elif t == NPY_FLOAT: f[0] = 102 #"f" * elif t == NPY_DOUBLE: f[0] = 100 #"d" # <<<<<<<<<<<<<< * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_DOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 894, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 894, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 894, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x64; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":895 * elif t == NPY_FLOAT: f[0] = 102 #"f" * elif t == NPY_DOUBLE: f[0] = 100 #"d" * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" # <<<<<<<<<<<<<< * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 895, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 895, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 895, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x67; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":896 * elif t == NPY_DOUBLE: f[0] = 100 #"d" * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf # <<<<<<<<<<<<<< * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CFLOAT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 896, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 896, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 896, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 90; (__pyx_v_f[1]) = 0x66; __pyx_v_f = (__pyx_v_f + 1); goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":897 * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd # <<<<<<<<<<<<<< * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg * elif t == NPY_OBJECT: f[0] = 79 #"O" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CDOUBLE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 897, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 897, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 897, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 90; (__pyx_v_f[1]) = 0x64; __pyx_v_f = (__pyx_v_f + 1); goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":898 * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg # <<<<<<<<<<<<<< * elif t == NPY_OBJECT: f[0] = 79 #"O" * else: */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 898, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 898, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 898, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 90; (__pyx_v_f[1]) = 0x67; __pyx_v_f = (__pyx_v_f + 1); goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":899 * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg * elif t == NPY_OBJECT: f[0] = 79 #"O" # <<<<<<<<<<<<<< * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_OBJECT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 899, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 899, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 899, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (likely(__pyx_t_6)) { (__pyx_v_f[0]) = 79; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":901 * elif t == NPY_OBJECT: f[0] = 79 #"O" * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) # <<<<<<<<<<<<<< * f += 1 * else: */ /*else*/ { __pyx_t_3 = __Pyx_PyUnicode_FormatSafe(__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_v_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 901, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 901, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_Raise(__pyx_t_4, 0, 0, 0); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __PYX_ERR(1, 901, __pyx_L1_error) } __pyx_L15:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":902 * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) * f += 1 # <<<<<<<<<<<<<< * else: * # Cython ignores struct boundary information ("T{...}"), */ __pyx_v_f = (__pyx_v_f + 1); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":877 * offset[0] += child.itemsize * * if not PyDataType_HASFIELDS(child): # <<<<<<<<<<<<<< * t = child.type_num * if end - f < 5: */ goto __pyx_L13; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":906 * # Cython ignores struct boundary information ("T{...}"), * # so don't output it * f = _util_dtypestring(child, f, end, offset) # <<<<<<<<<<<<<< * return f * */ /*else*/ { __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_9 == ((char *)NULL))) __PYX_ERR(1, 906, __pyx_L1_error) __pyx_v_f = __pyx_t_9; } __pyx_L13:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":851 * cdef tuple fields * * for childname in descr.names: # <<<<<<<<<<<<<< * fields = descr.fields[childname] * child, new_offset = fields */ } __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":907 * # so don't output it * f = _util_dtypestring(child, f, end, offset) * return f # <<<<<<<<<<<<<< * * */ __pyx_r = __pyx_v_f; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":842 * return () * * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: # <<<<<<<<<<<<<< * # Recursive utility function used in __getbuffer__ to get format * # string. The new location in the format string is returned. */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __Pyx_AddTraceback("numpy._util_dtypestring", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XDECREF((PyObject *)__pyx_v_child); __Pyx_XDECREF(__pyx_v_fields); __Pyx_XDECREF(__pyx_v_childname); __Pyx_XDECREF(__pyx_v_new_offset); __Pyx_XDECREF(__pyx_v_t); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1022 * int _import_umath() except -1 * * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) */ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("set_array_base", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1023 * * cdef inline void set_array_base(ndarray arr, object base): * Py_INCREF(base) # important to do this before stealing the reference below! # <<<<<<<<<<<<<< * PyArray_SetBaseObject(arr, base) * */ Py_INCREF(__pyx_v_base); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1024 * cdef inline void set_array_base(ndarray arr, object base): * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) # <<<<<<<<<<<<<< * * cdef inline object get_array_base(ndarray arr): */ (void)(PyArray_SetBaseObject(__pyx_v_arr, __pyx_v_base)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1022 * int _import_umath() except -1 * * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) */ /* function exit code */ __Pyx_RefNannyFinishContext(); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1026 * PyArray_SetBaseObject(arr, base) * * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< * base = PyArray_BASE(arr) * if base is NULL: */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) { PyObject *__pyx_v_base; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("get_array_base", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1027 * * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) # <<<<<<<<<<<<<< * if base is NULL: * return None */ __pyx_v_base = PyArray_BASE(__pyx_v_arr); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1028 * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) * if base is NULL: # <<<<<<<<<<<<<< * return None * return base */ __pyx_t_1 = ((__pyx_v_base == NULL) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1029 * base = PyArray_BASE(arr) * if base is NULL: * return None # <<<<<<<<<<<<<< * return base * */ __Pyx_XDECREF(__pyx_r); __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1028 * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) * if base is NULL: # <<<<<<<<<<<<<< * return None * return base */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1030 * if base is NULL: * return None * return base # <<<<<<<<<<<<<< * * # Versions of the import_* functions which are more suitable for */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(((PyObject *)__pyx_v_base)); __pyx_r = ((PyObject *)__pyx_v_base); goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1026 * PyArray_SetBaseObject(arr, base) * * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< * base = PyArray_BASE(arr) * if base is NULL: */ /* function exit code */ __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1034 * # Versions of the import_* functions which are more suitable for * # Cython code. * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< * try: * _import_array() */ static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; __Pyx_RefNannySetupContext("import_array", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1035 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< * _import_array() * except Exception: */ { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); __Pyx_XGOTREF(__pyx_t_1); __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1036 * cdef inline int import_array() except -1: * try: * _import_array() # <<<<<<<<<<<<<< * except Exception: * raise ImportError("numpy.core.multiarray failed to import") */ __pyx_t_4 = _import_array(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1036, __pyx_L3_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1035 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< * _import_array() * except Exception: */ } __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L8_try_end; __pyx_L3_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1037 * try: * _import_array() * except Exception: # <<<<<<<<<<<<<< * raise ImportError("numpy.core.multiarray failed to import") * */ __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); if (__pyx_t_4) { __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1037, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1038 * _import_array() * except Exception: * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_umath() except -1: */ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__6, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1038, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(1, 1038, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1035 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< * _import_array() * except Exception: */ __Pyx_XGIVEREF(__pyx_t_1); __Pyx_XGIVEREF(__pyx_t_2); __Pyx_XGIVEREF(__pyx_t_3); __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); goto __pyx_L1_error; __pyx_L8_try_end:; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1034 * # Versions of the import_* functions which are more suitable for * # Cython code. * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< * try: * _import_array() */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1040 * raise ImportError("numpy.core.multiarray failed to import") * * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; __Pyx_RefNannySetupContext("import_umath", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1041 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); __Pyx_XGOTREF(__pyx_t_1); __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1042 * cdef inline int import_umath() except -1: * try: * _import_umath() # <<<<<<<<<<<<<< * except Exception: * raise ImportError("numpy.core.umath failed to import") */ __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1042, __pyx_L3_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1041 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ } __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L8_try_end; __pyx_L3_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1043 * try: * _import_umath() * except Exception: # <<<<<<<<<<<<<< * raise ImportError("numpy.core.umath failed to import") * */ __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); if (__pyx_t_4) { __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1043, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1044 * _import_umath() * except Exception: * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_ufunc() except -1: */ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1044, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(1, 1044, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1041 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ __Pyx_XGIVEREF(__pyx_t_1); __Pyx_XGIVEREF(__pyx_t_2); __Pyx_XGIVEREF(__pyx_t_3); __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); goto __pyx_L1_error; __pyx_L8_try_end:; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1040 * raise ImportError("numpy.core.multiarray failed to import") * * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1046 * raise ImportError("numpy.core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; __Pyx_RefNannySetupContext("import_ufunc", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1047 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); __Pyx_XGOTREF(__pyx_t_1); __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1048 * cdef inline int import_ufunc() except -1: * try: * _import_umath() # <<<<<<<<<<<<<< * except Exception: * raise ImportError("numpy.core.umath failed to import") */ __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1048, __pyx_L3_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1047 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ } __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L8_try_end; __pyx_L3_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1049 * try: * _import_umath() * except Exception: # <<<<<<<<<<<<<< * raise ImportError("numpy.core.umath failed to import") */ __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); if (__pyx_t_4) { __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1049, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1050 * _import_umath() * except Exception: * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< */ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1050, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(1, 1050, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1047 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ __Pyx_XGIVEREF(__pyx_t_1); __Pyx_XGIVEREF(__pyx_t_2); __Pyx_XGIVEREF(__pyx_t_3); __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); goto __pyx_L1_error; __pyx_L8_try_end:; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1046 * raise ImportError("numpy.core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } static PyMethodDef __pyx_methods[] = { {0, 0, 0, 0} }; #if PY_MAJOR_VERSION >= 3 #if CYTHON_PEP489_MULTI_PHASE_INIT static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ static int __pyx_pymod_exec_circular_overlap(PyObject* module); /*proto*/ static PyModuleDef_Slot __pyx_moduledef_slots[] = { {Py_mod_create, (void*)__pyx_pymod_create}, {Py_mod_exec, (void*)__pyx_pymod_exec_circular_overlap}, {0, NULL} }; #endif static struct PyModuleDef __pyx_moduledef = { PyModuleDef_HEAD_INIT, "circular_overlap", __pyx_k_The_functions_defined_here_allo, /* m_doc */ #if CYTHON_PEP489_MULTI_PHASE_INIT 0, /* m_size */ #else -1, /* m_size */ #endif __pyx_methods /* m_methods */, #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_moduledef_slots, /* m_slots */ #else NULL, /* m_reload */ #endif NULL, /* m_traverse */ NULL, /* m_clear */ NULL /* m_free */ }; #endif #ifndef CYTHON_SMALL_CODE #if defined(__clang__) #define CYTHON_SMALL_CODE #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) #define CYTHON_SMALL_CODE __attribute__((cold)) #else #define CYTHON_SMALL_CODE #endif #endif static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_DTYPE, __pyx_k_DTYPE, sizeof(__pyx_k_DTYPE), 0, 0, 1, 1}, {&__pyx_kp_u_Format_string_allocated_too_shor, __pyx_k_Format_string_allocated_too_shor, sizeof(__pyx_k_Format_string_allocated_too_shor), 0, 1, 0, 0}, {&__pyx_kp_u_Format_string_allocated_too_shor_2, __pyx_k_Format_string_allocated_too_shor_2, sizeof(__pyx_k_Format_string_allocated_too_shor_2), 0, 1, 0, 0}, {&__pyx_n_s_ImportError, __pyx_k_ImportError, sizeof(__pyx_k_ImportError), 0, 0, 1, 1}, {&__pyx_kp_u_Non_native_byte_order_not_suppor, __pyx_k_Non_native_byte_order_not_suppor, sizeof(__pyx_k_Non_native_byte_order_not_suppor), 0, 1, 0, 0}, {&__pyx_n_s_RuntimeError, __pyx_k_RuntimeError, sizeof(__pyx_k_RuntimeError), 0, 0, 1, 1}, {&__pyx_n_s_ValueError, __pyx_k_ValueError, sizeof(__pyx_k_ValueError), 0, 0, 1, 1}, {&__pyx_n_s_all, __pyx_k_all, sizeof(__pyx_k_all), 0, 0, 1, 1}, {&__pyx_n_s_bxmax, __pyx_k_bxmax, sizeof(__pyx_k_bxmax), 0, 0, 1, 1}, {&__pyx_n_s_bxmin, __pyx_k_bxmin, sizeof(__pyx_k_bxmin), 0, 0, 1, 1}, {&__pyx_n_s_bymax, __pyx_k_bymax, sizeof(__pyx_k_bymax), 0, 0, 1, 1}, {&__pyx_n_s_bymin, __pyx_k_bymin, sizeof(__pyx_k_bymin), 0, 0, 1, 1}, {&__pyx_n_s_circular_overlap_grid, __pyx_k_circular_overlap_grid, sizeof(__pyx_k_circular_overlap_grid), 0, 0, 1, 1}, {&__pyx_n_u_circular_overlap_grid, __pyx_k_circular_overlap_grid, sizeof(__pyx_k_circular_overlap_grid), 0, 1, 0, 1}, {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, {&__pyx_n_s_d, __pyx_k_d, sizeof(__pyx_k_d), 0, 0, 1, 1}, {&__pyx_n_s_dtype, __pyx_k_dtype, sizeof(__pyx_k_dtype), 0, 0, 1, 1}, {&__pyx_n_s_dx, __pyx_k_dx, sizeof(__pyx_k_dx), 0, 0, 1, 1}, {&__pyx_n_s_dy, __pyx_k_dy, sizeof(__pyx_k_dy), 0, 0, 1, 1}, {&__pyx_n_s_float64, __pyx_k_float64, sizeof(__pyx_k_float64), 0, 0, 1, 1}, {&__pyx_n_s_frac, __pyx_k_frac, sizeof(__pyx_k_frac), 0, 0, 1, 1}, {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1}, {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, {&__pyx_n_s_j, __pyx_k_j, sizeof(__pyx_k_j), 0, 0, 1, 1}, {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, {&__pyx_kp_u_ndarray_is_not_C_contiguous, __pyx_k_ndarray_is_not_C_contiguous, sizeof(__pyx_k_ndarray_is_not_C_contiguous), 0, 1, 0, 0}, {&__pyx_kp_u_ndarray_is_not_Fortran_contiguou, __pyx_k_ndarray_is_not_Fortran_contiguou, sizeof(__pyx_k_ndarray_is_not_Fortran_contiguou), 0, 1, 0, 0}, {&__pyx_n_s_np, __pyx_k_np, sizeof(__pyx_k_np), 0, 0, 1, 1}, {&__pyx_n_s_numpy, __pyx_k_numpy, sizeof(__pyx_k_numpy), 0, 0, 1, 1}, {&__pyx_kp_u_numpy_core_multiarray_failed_to, __pyx_k_numpy_core_multiarray_failed_to, sizeof(__pyx_k_numpy_core_multiarray_failed_to), 0, 1, 0, 0}, {&__pyx_kp_u_numpy_core_umath_failed_to_impor, __pyx_k_numpy_core_umath_failed_to_impor, sizeof(__pyx_k_numpy_core_umath_failed_to_impor), 0, 1, 0, 0}, {&__pyx_n_s_nx, __pyx_k_nx, sizeof(__pyx_k_nx), 0, 0, 1, 1}, {&__pyx_n_s_ny, __pyx_k_ny, sizeof(__pyx_k_ny), 0, 0, 1, 1}, {&__pyx_kp_s_photutils_geometry_circular_over, __pyx_k_photutils_geometry_circular_over, sizeof(__pyx_k_photutils_geometry_circular_over), 0, 0, 1, 0}, {&__pyx_n_s_photutils_geometry_circular_over_2, __pyx_k_photutils_geometry_circular_over_2, sizeof(__pyx_k_photutils_geometry_circular_over_2), 0, 0, 1, 1}, {&__pyx_n_s_pixel_radius, __pyx_k_pixel_radius, sizeof(__pyx_k_pixel_radius), 0, 0, 1, 1}, {&__pyx_n_s_pxcen, __pyx_k_pxcen, sizeof(__pyx_k_pxcen), 0, 0, 1, 1}, {&__pyx_n_s_pxmax, __pyx_k_pxmax, sizeof(__pyx_k_pxmax), 0, 0, 1, 1}, {&__pyx_n_s_pxmin, __pyx_k_pxmin, sizeof(__pyx_k_pxmin), 0, 0, 1, 1}, {&__pyx_n_s_pycen, __pyx_k_pycen, sizeof(__pyx_k_pycen), 0, 0, 1, 1}, {&__pyx_n_s_pymax, __pyx_k_pymax, sizeof(__pyx_k_pymax), 0, 0, 1, 1}, {&__pyx_n_s_pymin, __pyx_k_pymin, sizeof(__pyx_k_pymin), 0, 0, 1, 1}, {&__pyx_n_s_r, __pyx_k_r, sizeof(__pyx_k_r), 0, 0, 1, 1}, {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, {&__pyx_n_s_subpixels, __pyx_k_subpixels, sizeof(__pyx_k_subpixels), 0, 0, 1, 1}, {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, {&__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_k_unknown_dtype_code_in_numpy_pxd, sizeof(__pyx_k_unknown_dtype_code_in_numpy_pxd), 0, 1, 0, 0}, {&__pyx_n_s_use_exact, __pyx_k_use_exact, sizeof(__pyx_k_use_exact), 0, 0, 1, 1}, {&__pyx_n_s_x, __pyx_k_x, sizeof(__pyx_k_x), 0, 0, 1, 1}, {&__pyx_n_s_xmax, __pyx_k_xmax, sizeof(__pyx_k_xmax), 0, 0, 1, 1}, {&__pyx_n_s_xmin, __pyx_k_xmin, sizeof(__pyx_k_xmin), 0, 0, 1, 1}, {&__pyx_n_s_y, __pyx_k_y, sizeof(__pyx_k_y), 0, 0, 1, 1}, {&__pyx_n_s_ymax, __pyx_k_ymax, sizeof(__pyx_k_ymax), 0, 0, 1, 1}, {&__pyx_n_s_ymin, __pyx_k_ymin, sizeof(__pyx_k_ymin), 0, 0, 1, 1}, {&__pyx_n_s_zeros, __pyx_k_zeros, sizeof(__pyx_k_zeros), 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0} }; static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 82, __pyx_L1_error) __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) __PYX_ERR(1, 272, __pyx_L1_error) __pyx_builtin_RuntimeError = __Pyx_GetBuiltinName(__pyx_n_s_RuntimeError); if (!__pyx_builtin_RuntimeError) __PYX_ERR(1, 856, __pyx_L1_error) __pyx_builtin_ImportError = __Pyx_GetBuiltinName(__pyx_n_s_ImportError); if (!__pyx_builtin_ImportError) __PYX_ERR(1, 1038, __pyx_L1_error) return 0; __pyx_L1_error:; return -1; } static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":272 * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") # <<<<<<<<<<<<<< * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) */ __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_u_ndarray_is_not_C_contiguous); if (unlikely(!__pyx_tuple_)) __PYX_ERR(1, 272, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple_); __Pyx_GIVEREF(__pyx_tuple_); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":276 * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") # <<<<<<<<<<<<<< * * info.buf = PyArray_DATA(self) */ __pyx_tuple__2 = PyTuple_Pack(1, __pyx_kp_u_ndarray_is_not_Fortran_contiguou); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(1, 276, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__2); __Pyx_GIVEREF(__pyx_tuple__2); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":306 * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" */ __pyx_tuple__3 = PyTuple_Pack(1, __pyx_kp_u_Non_native_byte_order_not_suppor); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(1, 306, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__3); __Pyx_GIVEREF(__pyx_tuple__3); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":856 * * if (end - f) - (new_offset - offset[0]) < 15: * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") # <<<<<<<<<<<<<< * * if ((child.byteorder == c'>' and little_endian) or */ __pyx_tuple__4 = PyTuple_Pack(1, __pyx_kp_u_Format_string_allocated_too_shor); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(1, 856, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__4); __Pyx_GIVEREF(__pyx_tuple__4); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":880 * t = child.type_num * if end - f < 5: * raise RuntimeError(u"Format string allocated too short.") # <<<<<<<<<<<<<< * * # Until ticket #99 is fixed, use integers to avoid warnings */ __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_u_Format_string_allocated_too_shor_2); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(1, 880, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__5); __Pyx_GIVEREF(__pyx_tuple__5); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1038 * _import_array() * except Exception: * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_umath() except -1: */ __pyx_tuple__6 = PyTuple_Pack(1, __pyx_kp_u_numpy_core_multiarray_failed_to); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(1, 1038, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__6); __Pyx_GIVEREF(__pyx_tuple__6); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1044 * _import_umath() * except Exception: * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_ufunc() except -1: */ __pyx_tuple__7 = PyTuple_Pack(1, __pyx_kp_u_numpy_core_umath_failed_to_impor); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(1, 1044, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__7); __Pyx_GIVEREF(__pyx_tuple__7); /* "photutils/geometry/circular_overlap.pyx":30 * * * def circular_overlap_grid(double xmin, double xmax, double ymin, double ymax, # <<<<<<<<<<<<<< * int nx, int ny, double r, int use_exact, * int subpixels): */ __pyx_tuple__8 = PyTuple_Pack(28, __pyx_n_s_xmin, __pyx_n_s_xmax, __pyx_n_s_ymin, __pyx_n_s_ymax, __pyx_n_s_nx, __pyx_n_s_ny, __pyx_n_s_r, __pyx_n_s_use_exact, __pyx_n_s_subpixels, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_x, __pyx_n_s_y, __pyx_n_s_dx, __pyx_n_s_dy, __pyx_n_s_d, __pyx_n_s_pixel_radius, __pyx_n_s_bxmin, __pyx_n_s_bxmax, __pyx_n_s_bymin, __pyx_n_s_bymax, __pyx_n_s_pxmin, __pyx_n_s_pxcen, __pyx_n_s_pxmax, __pyx_n_s_pymin, __pyx_n_s_pycen, __pyx_n_s_pymax, __pyx_n_s_frac); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__8); __Pyx_GIVEREF(__pyx_tuple__8); __pyx_codeobj__9 = (PyObject*)__Pyx_PyCode_New(9, 0, 28, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__8, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_photutils_geometry_circular_over, __pyx_n_s_circular_overlap_grid, 30, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__9)) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; __Pyx_RefNannyFinishContext(); return -1; } static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); return 0; __pyx_L1_error:; return -1; } static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ static int __Pyx_modinit_global_init_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); /*--- Global init code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_variable_export_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); /*--- Variable export code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_function_export_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); /*--- Function export code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_type_init_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); /*--- Type init code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_type_import_code(void) { __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); /*--- Type import code ---*/ __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 9, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 sizeof(PyTypeObject), #else sizeof(PyHeapTypeObject), #endif __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_7cpython_4type_type) __PYX_ERR(2, 9, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = PyImport_ImportModule("numpy"); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 206, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_5numpy_dtype = __Pyx_ImportType(__pyx_t_1, "numpy", "dtype", sizeof(PyArray_Descr), __Pyx_ImportType_CheckSize_Ignore); if (!__pyx_ptype_5numpy_dtype) __PYX_ERR(1, 206, __pyx_L1_error) __pyx_ptype_5numpy_flatiter = __Pyx_ImportType(__pyx_t_1, "numpy", "flatiter", sizeof(PyArrayIterObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_5numpy_flatiter) __PYX_ERR(1, 229, __pyx_L1_error) __pyx_ptype_5numpy_broadcast = __Pyx_ImportType(__pyx_t_1, "numpy", "broadcast", sizeof(PyArrayMultiIterObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_5numpy_broadcast) __PYX_ERR(1, 233, __pyx_L1_error) __pyx_ptype_5numpy_ndarray = __Pyx_ImportType(__pyx_t_1, "numpy", "ndarray", sizeof(PyArrayObject), __Pyx_ImportType_CheckSize_Ignore); if (!__pyx_ptype_5numpy_ndarray) __PYX_ERR(1, 242, __pyx_L1_error) __pyx_ptype_5numpy_ufunc = __Pyx_ImportType(__pyx_t_1, "numpy", "ufunc", sizeof(PyUFuncObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_5numpy_ufunc) __PYX_ERR(1, 918, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_RefNannyFinishContext(); return -1; } static int __Pyx_modinit_variable_import_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); /*--- Variable import code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_function_import_code(void) { __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); /*--- Function import code ---*/ __pyx_t_1 = PyImport_ImportModule("photutils.geometry.core"); if (!__pyx_t_1) __PYX_ERR(0, 1, __pyx_L1_error) if (__Pyx_ImportFunction(__pyx_t_1, "area_arc", (void (**)(void))&__pyx_f_9photutils_8geometry_4core_area_arc, "double (double, double, double, double, double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) if (__Pyx_ImportFunction(__pyx_t_1, "area_triangle", (void (**)(void))&__pyx_f_9photutils_8geometry_4core_area_triangle, "double (double, double, double, double, double, double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) if (__Pyx_ImportFunction(__pyx_t_1, "floor_sqrt", (void (**)(void))&__pyx_f_9photutils_8geometry_4core_floor_sqrt, "double (double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) Py_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_RefNannyFinishContext(); return -1; } #if PY_MAJOR_VERSION < 3 #ifdef CYTHON_NO_PYINIT_EXPORT #define __Pyx_PyMODINIT_FUNC void #else #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC #endif #else #ifdef CYTHON_NO_PYINIT_EXPORT #define __Pyx_PyMODINIT_FUNC PyObject * #else #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC #endif #endif #if PY_MAJOR_VERSION < 3 __Pyx_PyMODINIT_FUNC initcircular_overlap(void) CYTHON_SMALL_CODE; /*proto*/ __Pyx_PyMODINIT_FUNC initcircular_overlap(void) #else __Pyx_PyMODINIT_FUNC PyInit_circular_overlap(void) CYTHON_SMALL_CODE; /*proto*/ __Pyx_PyMODINIT_FUNC PyInit_circular_overlap(void) #if CYTHON_PEP489_MULTI_PHASE_INIT { return PyModuleDef_Init(&__pyx_moduledef); } static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { #if PY_VERSION_HEX >= 0x030700A1 static PY_INT64_T main_interpreter_id = -1; PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); if (main_interpreter_id == -1) { main_interpreter_id = current_id; return (unlikely(current_id == -1)) ? -1 : 0; } else if (unlikely(main_interpreter_id != current_id)) #else static PyInterpreterState *main_interpreter = NULL; PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; if (!main_interpreter) { main_interpreter = current_interpreter; } else if (unlikely(main_interpreter != current_interpreter)) #endif { PyErr_SetString( PyExc_ImportError, "Interpreter change detected - this module can only be loaded into one interpreter per process."); return -1; } return 0; } static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { PyObject *value = PyObject_GetAttrString(spec, from_name); int result = 0; if (likely(value)) { if (allow_none || value != Py_None) { result = PyDict_SetItemString(moddict, to_name, value); } Py_DECREF(value); } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Clear(); } else { result = -1; } return result; } static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { PyObject *module = NULL, *moddict, *modname; if (__Pyx_check_single_interpreter()) return NULL; if (__pyx_m) return __Pyx_NewRef(__pyx_m); modname = PyObject_GetAttrString(spec, "name"); if (unlikely(!modname)) goto bad; module = PyModule_NewObject(modname); Py_DECREF(modname); if (unlikely(!module)) goto bad; moddict = PyModule_GetDict(module); if (unlikely(!moddict)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; return module; bad: Py_XDECREF(module); return NULL; } static CYTHON_SMALL_CODE int __pyx_pymod_exec_circular_overlap(PyObject *__pyx_pyinit_module) #endif #endif { PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; __Pyx_RefNannyDeclarations #if CYTHON_PEP489_MULTI_PHASE_INIT if (__pyx_m) { if (__pyx_m == __pyx_pyinit_module) return 0; PyErr_SetString(PyExc_RuntimeError, "Module 'circular_overlap' has already been imported. Re-initialisation is not supported."); return -1; } #elif PY_MAJOR_VERSION >= 3 if (__pyx_m) return __Pyx_NewRef(__pyx_m); #endif #if CYTHON_REFNANNY __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); if (!__Pyx_RefNanny) { PyErr_Clear(); __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); if (!__Pyx_RefNanny) Py_FatalError("failed to import 'refnanny' module"); } #endif __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_circular_overlap(void)", 0); if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #ifdef __Pxy_PyFrame_Initialize_Offsets __Pxy_PyFrame_Initialize_Offsets(); #endif __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) #ifdef __Pyx_CyFunction_USED if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_FusedFunction_USED if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_Coroutine_USED if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_Generator_USED if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_AsyncGen_USED if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_StopAsyncIteration_USED if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif /*--- Library function declarations ---*/ /*--- Threads initialization code ---*/ #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS #ifdef WITH_THREAD /* Python build with threading support? */ PyEval_InitThreads(); #endif #endif /*--- Module creation code ---*/ #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_m = __pyx_pyinit_module; Py_INCREF(__pyx_m); #else #if PY_MAJOR_VERSION < 3 __pyx_m = Py_InitModule4("circular_overlap", __pyx_methods, __pyx_k_The_functions_defined_here_allo, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); #else __pyx_m = PyModule_Create(&__pyx_moduledef); #endif if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) #endif __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_d); __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_b); __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_cython_runtime); if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); /*--- Initialize various global constants etc. ---*/ if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif if (__pyx_module_is_main_photutils__geometry__circular_overlap) { if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) } #if PY_MAJOR_VERSION >= 3 { PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) if (!PyDict_GetItemString(modules, "photutils.geometry.circular_overlap")) { if (unlikely(PyDict_SetItemString(modules, "photutils.geometry.circular_overlap", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) } } #endif /*--- Builtin init code ---*/ if (__Pyx_InitCachedBuiltins() < 0) goto __pyx_L1_error; /*--- Constants init code ---*/ if (__Pyx_InitCachedConstants() < 0) goto __pyx_L1_error; /*--- Global type/function init code ---*/ (void)__Pyx_modinit_global_init_code(); (void)__Pyx_modinit_variable_export_code(); (void)__Pyx_modinit_function_export_code(); (void)__Pyx_modinit_type_init_code(); if (unlikely(__Pyx_modinit_type_import_code() != 0)) goto __pyx_L1_error; (void)__Pyx_modinit_variable_import_code(); if (unlikely(__Pyx_modinit_function_import_code() != 0)) goto __pyx_L1_error; /*--- Execution code ---*/ #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif /* "photutils/geometry/circular_overlap.pyx":8 * """ * * import numpy as np # <<<<<<<<<<<<<< * cimport numpy as np * */ __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 8, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "photutils/geometry/circular_overlap.pyx":11 * cimport numpy as np * * __all__ = ['circular_overlap_grid'] # <<<<<<<<<<<<<< * * */ __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_u_circular_overlap_grid); __Pyx_GIVEREF(__pyx_n_u_circular_overlap_grid); PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_u_circular_overlap_grid); if (PyDict_SetItem(__pyx_d, __pyx_n_s_all, __pyx_t_1) < 0) __PYX_ERR(0, 11, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "photutils/geometry/circular_overlap.pyx":21 * * * DTYPE = np.float64 # <<<<<<<<<<<<<< * ctypedef np.float64_t DTYPE_t * */ __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 21, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_float64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 21, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; if (PyDict_SetItem(__pyx_d, __pyx_n_s_DTYPE, __pyx_t_2) < 0) __PYX_ERR(0, 21, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/circular_overlap.pyx":30 * * * def circular_overlap_grid(double xmin, double xmax, double ymin, double ymax, # <<<<<<<<<<<<<< * int nx, int ny, double r, int use_exact, * int subpixels): */ __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_9photutils_8geometry_16circular_overlap_1circular_overlap_grid, NULL, __pyx_n_s_photutils_geometry_circular_over_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (PyDict_SetItem(__pyx_d, __pyx_n_s_circular_overlap_grid, __pyx_t_2) < 0) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/circular_overlap.pyx":1 * # Licensed under a 3-clause BSD style license - see LICENSE.rst # <<<<<<<<<<<<<< * #cython: language_level=3 * """ */ __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1046 * raise ImportError("numpy.core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ /*--- Wrapped vars code ---*/ goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_2); if (__pyx_m) { if (__pyx_d) { __Pyx_AddTraceback("init photutils.geometry.circular_overlap", __pyx_clineno, __pyx_lineno, __pyx_filename); } Py_CLEAR(__pyx_m); } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ImportError, "init photutils.geometry.circular_overlap"); } __pyx_L0:; __Pyx_RefNannyFinishContext(); #if CYTHON_PEP489_MULTI_PHASE_INIT return (__pyx_m != NULL) ? 0 : -1; #elif PY_MAJOR_VERSION >= 3 return __pyx_m; #else return; #endif } /* --- Runtime support code --- */ /* Refnanny */ #if CYTHON_REFNANNY static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { PyObject *m = NULL, *p = NULL; void *r = NULL; m = PyImport_ImportModule(modname); if (!m) goto end; p = PyObject_GetAttrString(m, "RefNannyAPI"); if (!p) goto end; r = PyLong_AsVoidPtr(p); end: Py_XDECREF(p); Py_XDECREF(m); return (__Pyx_RefNannyAPIStruct *)r; } #endif /* PyObjectGetAttrStr */ #if CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { PyTypeObject* tp = Py_TYPE(obj); if (likely(tp->tp_getattro)) return tp->tp_getattro(obj, attr_name); #if PY_MAJOR_VERSION < 3 if (likely(tp->tp_getattr)) return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); #endif return PyObject_GetAttr(obj, attr_name); } #endif /* GetBuiltinName */ static PyObject *__Pyx_GetBuiltinName(PyObject *name) { PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); if (unlikely(!result)) { PyErr_Format(PyExc_NameError, #if PY_MAJOR_VERSION >= 3 "name '%U' is not defined", name); #else "name '%.200s' is not defined", PyString_AS_STRING(name)); #endif } return result; } /* RaiseArgTupleInvalid */ static void __Pyx_RaiseArgtupleInvalid( const char* func_name, int exact, Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found) { Py_ssize_t num_expected; const char *more_or_less; if (num_found < num_min) { num_expected = num_min; more_or_less = "at least"; } else { num_expected = num_max; more_or_less = "at most"; } if (exact) { more_or_less = "exactly"; } PyErr_Format(PyExc_TypeError, "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", func_name, more_or_less, num_expected, (num_expected == 1) ? "" : "s", num_found); } /* RaiseDoubleKeywords */ static void __Pyx_RaiseDoubleKeywordsError( const char* func_name, PyObject* kw_name) { PyErr_Format(PyExc_TypeError, #if PY_MAJOR_VERSION >= 3 "%s() got multiple values for keyword argument '%U'", func_name, kw_name); #else "%s() got multiple values for keyword argument '%s'", func_name, PyString_AsString(kw_name)); #endif } /* ParseKeywords */ static int __Pyx_ParseOptionalKeywords( PyObject *kwds, PyObject **argnames[], PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, const char* function_name) { PyObject *key = 0, *value = 0; Py_ssize_t pos = 0; PyObject*** name; PyObject*** first_kw_arg = argnames + num_pos_args; while (PyDict_Next(kwds, &pos, &key, &value)) { name = first_kw_arg; while (*name && (**name != key)) name++; if (*name) { values[name-argnames] = value; continue; } name = first_kw_arg; #if PY_MAJOR_VERSION < 3 if (likely(PyString_CheckExact(key)) || likely(PyString_Check(key))) { while (*name) { if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) && _PyString_Eq(**name, key)) { values[name-argnames] = value; break; } name++; } if (*name) continue; else { PyObject*** argname = argnames; while (argname != first_kw_arg) { if ((**argname == key) || ( (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) && _PyString_Eq(**argname, key))) { goto arg_passed_twice; } argname++; } } } else #endif if (likely(PyUnicode_Check(key))) { while (*name) { int cmp = (**name == key) ? 0 : #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 (PyUnicode_GET_SIZE(**name) != PyUnicode_GET_SIZE(key)) ? 1 : #endif PyUnicode_Compare(**name, key); if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; if (cmp == 0) { values[name-argnames] = value; break; } name++; } if (*name) continue; else { PyObject*** argname = argnames; while (argname != first_kw_arg) { int cmp = (**argname == key) ? 0 : #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 (PyUnicode_GET_SIZE(**argname) != PyUnicode_GET_SIZE(key)) ? 1 : #endif PyUnicode_Compare(**argname, key); if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; if (cmp == 0) goto arg_passed_twice; argname++; } } } else goto invalid_keyword_type; if (kwds2) { if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; } else { goto invalid_keyword; } } return 0; arg_passed_twice: __Pyx_RaiseDoubleKeywordsError(function_name, key); goto bad; invalid_keyword_type: PyErr_Format(PyExc_TypeError, "%.200s() keywords must be strings", function_name); goto bad; invalid_keyword: PyErr_Format(PyExc_TypeError, #if PY_MAJOR_VERSION < 3 "%.200s() got an unexpected keyword argument '%.200s'", function_name, PyString_AsString(key)); #else "%s() got an unexpected keyword argument '%U'", function_name, key); #endif bad: return -1; } /* PyDictVersioning */ #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { PyObject *dict = Py_TYPE(obj)->tp_dict; return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; } static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { PyObject **dictptr = NULL; Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; if (offset) { #if CYTHON_COMPILING_IN_CPYTHON dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); #else dictptr = _PyObject_GetDictPtr(obj); #endif } return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; } static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { PyObject *dict = Py_TYPE(obj)->tp_dict; if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) return 0; return obj_dict_version == __Pyx_get_object_dict_version(obj); } #endif /* GetModuleGlobalName */ #if CYTHON_USE_DICT_VERSIONS static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) #else static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) #endif { PyObject *result; #if !CYTHON_AVOID_BORROWED_REFS #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } else if (unlikely(PyErr_Occurred())) { return NULL; } #else result = PyDict_GetItem(__pyx_d, name); __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } #endif #else result = PyObject_GetItem(__pyx_d, name); __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } PyErr_Clear(); #endif return __Pyx_GetBuiltinName(name); } /* PyObjectCall */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; ternaryfunc call = func->ob_type->tp_call; if (unlikely(!call)) return PyObject_Call(func, arg, kw); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) return NULL; result = (*call)(func, arg, kw); Py_LeaveRecursiveCall(); if (unlikely(!result) && unlikely(!PyErr_Occurred())) { PyErr_SetString( PyExc_SystemError, "NULL result without error in PyObject_Call"); } return result; } #endif /* ExtTypeTest */ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { if (unlikely(!type)) { PyErr_SetString(PyExc_SystemError, "Missing type object"); return 0; } if (likely(__Pyx_TypeCheck(obj, type))) return 1; PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", Py_TYPE(obj)->tp_name, type->tp_name); return 0; } /* IsLittleEndian */ static CYTHON_INLINE int __Pyx_Is_Little_Endian(void) { union { uint32_t u32; uint8_t u8[4]; } S; S.u32 = 0x01020304; return S.u8[0] == 4; } /* BufferFormatCheck */ static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, __Pyx_BufFmt_StackElem* stack, __Pyx_TypeInfo* type) { stack[0].field = &ctx->root; stack[0].parent_offset = 0; ctx->root.type = type; ctx->root.name = "buffer dtype"; ctx->root.offset = 0; ctx->head = stack; ctx->head->field = &ctx->root; ctx->fmt_offset = 0; ctx->head->parent_offset = 0; ctx->new_packmode = '@'; ctx->enc_packmode = '@'; ctx->new_count = 1; ctx->enc_count = 0; ctx->enc_type = 0; ctx->is_complex = 0; ctx->is_valid_array = 0; ctx->struct_alignment = 0; while (type->typegroup == 'S') { ++ctx->head; ctx->head->field = type->fields; ctx->head->parent_offset = 0; type = type->fields->type; } } static int __Pyx_BufFmt_ParseNumber(const char** ts) { int count; const char* t = *ts; if (*t < '0' || *t > '9') { return -1; } else { count = *t++ - '0'; while (*t >= '0' && *t <= '9') { count *= 10; count += *t++ - '0'; } } *ts = t; return count; } static int __Pyx_BufFmt_ExpectNumber(const char **ts) { int number = __Pyx_BufFmt_ParseNumber(ts); if (number == -1) PyErr_Format(PyExc_ValueError,\ "Does not understand character buffer dtype format string ('%c')", **ts); return number; } static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) { PyErr_Format(PyExc_ValueError, "Unexpected format string character: '%c'", ch); } static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) { switch (ch) { case '?': return "'bool'"; case 'c': return "'char'"; case 'b': return "'signed char'"; case 'B': return "'unsigned char'"; case 'h': return "'short'"; case 'H': return "'unsigned short'"; case 'i': return "'int'"; case 'I': return "'unsigned int'"; case 'l': return "'long'"; case 'L': return "'unsigned long'"; case 'q': return "'long long'"; case 'Q': return "'unsigned long long'"; case 'f': return (is_complex ? "'complex float'" : "'float'"); case 'd': return (is_complex ? "'complex double'" : "'double'"); case 'g': return (is_complex ? "'complex long double'" : "'long double'"); case 'T': return "a struct"; case 'O': return "Python object"; case 'P': return "a pointer"; case 's': case 'p': return "a string"; case 0: return "end"; default: return "unparseable format string"; } } static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return 2; case 'i': case 'I': case 'l': case 'L': return 4; case 'q': case 'Q': return 8; case 'f': return (is_complex ? 8 : 4); case 'd': return (is_complex ? 16 : 8); case 'g': { PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g').."); return 0; } case 'O': case 'P': return sizeof(void*); default: __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return sizeof(short); case 'i': case 'I': return sizeof(int); case 'l': case 'L': return sizeof(long); #ifdef HAVE_LONG_LONG case 'q': case 'Q': return sizeof(PY_LONG_LONG); #endif case 'f': return sizeof(float) * (is_complex ? 2 : 1); case 'd': return sizeof(double) * (is_complex ? 2 : 1); case 'g': return sizeof(long double) * (is_complex ? 2 : 1); case 'O': case 'P': return sizeof(void*); default: { __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } } typedef struct { char c; short x; } __Pyx_st_short; typedef struct { char c; int x; } __Pyx_st_int; typedef struct { char c; long x; } __Pyx_st_long; typedef struct { char c; float x; } __Pyx_st_float; typedef struct { char c; double x; } __Pyx_st_double; typedef struct { char c; long double x; } __Pyx_st_longdouble; typedef struct { char c; void *x; } __Pyx_st_void_p; #ifdef HAVE_LONG_LONG typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong; #endif static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, CYTHON_UNUSED int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short); case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int); case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long); #ifdef HAVE_LONG_LONG case 'q': case 'Q': return sizeof(__Pyx_st_longlong) - sizeof(PY_LONG_LONG); #endif case 'f': return sizeof(__Pyx_st_float) - sizeof(float); case 'd': return sizeof(__Pyx_st_double) - sizeof(double); case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double); case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*); default: __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } /* These are for computing the padding at the end of the struct to align on the first member of the struct. This will probably the same as above, but we don't have any guarantees. */ typedef struct { short x; char c; } __Pyx_pad_short; typedef struct { int x; char c; } __Pyx_pad_int; typedef struct { long x; char c; } __Pyx_pad_long; typedef struct { float x; char c; } __Pyx_pad_float; typedef struct { double x; char c; } __Pyx_pad_double; typedef struct { long double x; char c; } __Pyx_pad_longdouble; typedef struct { void *x; char c; } __Pyx_pad_void_p; #ifdef HAVE_LONG_LONG typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong; #endif static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, CYTHON_UNUSED int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short); case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int); case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long); #ifdef HAVE_LONG_LONG case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG); #endif case 'f': return sizeof(__Pyx_pad_float) - sizeof(float); case 'd': return sizeof(__Pyx_pad_double) - sizeof(double); case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double); case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*); default: __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { switch (ch) { case 'c': return 'H'; case 'b': case 'h': case 'i': case 'l': case 'q': case 's': case 'p': return 'I'; case '?': case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U'; case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R'); case 'O': return 'O'; case 'P': return 'P'; default: { __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } } static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) { if (ctx->head == NULL || ctx->head->field == &ctx->root) { const char* expected; const char* quote; if (ctx->head == NULL) { expected = "end"; quote = ""; } else { expected = ctx->head->field->type->name; quote = "'"; } PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch, expected %s%s%s but got %s", quote, expected, quote, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex)); } else { __Pyx_StructField* field = ctx->head->field; __Pyx_StructField* parent = (ctx->head - 1)->field; PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'", field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex), parent->type->name, field->name); } } static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) { char group; size_t size, offset, arraysize = 1; if (ctx->enc_type == 0) return 0; if (ctx->head->field->type->arraysize[0]) { int i, ndim = 0; if (ctx->enc_type == 's' || ctx->enc_type == 'p') { ctx->is_valid_array = ctx->head->field->type->ndim == 1; ndim = 1; if (ctx->enc_count != ctx->head->field->type->arraysize[0]) { PyErr_Format(PyExc_ValueError, "Expected a dimension of size %zu, got %zu", ctx->head->field->type->arraysize[0], ctx->enc_count); return -1; } } if (!ctx->is_valid_array) { PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d", ctx->head->field->type->ndim, ndim); return -1; } for (i = 0; i < ctx->head->field->type->ndim; i++) { arraysize *= ctx->head->field->type->arraysize[i]; } ctx->is_valid_array = 0; ctx->enc_count = 1; } group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex); do { __Pyx_StructField* field = ctx->head->field; __Pyx_TypeInfo* type = field->type; if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') { size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex); } else { size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex); } if (ctx->enc_packmode == '@') { size_t align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex); size_t align_mod_offset; if (align_at == 0) return -1; align_mod_offset = ctx->fmt_offset % align_at; if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset; if (ctx->struct_alignment == 0) ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type, ctx->is_complex); } if (type->size != size || type->typegroup != group) { if (type->typegroup == 'C' && type->fields != NULL) { size_t parent_offset = ctx->head->parent_offset + field->offset; ++ctx->head; ctx->head->field = type->fields; ctx->head->parent_offset = parent_offset; continue; } if ((type->typegroup == 'H' || group == 'H') && type->size == size) { } else { __Pyx_BufFmt_RaiseExpected(ctx); return -1; } } offset = ctx->head->parent_offset + field->offset; if (ctx->fmt_offset != offset) { PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch; next field is at offset %" CYTHON_FORMAT_SSIZE_T "d but %" CYTHON_FORMAT_SSIZE_T "d expected", (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset); return -1; } ctx->fmt_offset += size; if (arraysize) ctx->fmt_offset += (arraysize - 1) * size; --ctx->enc_count; while (1) { if (field == &ctx->root) { ctx->head = NULL; if (ctx->enc_count != 0) { __Pyx_BufFmt_RaiseExpected(ctx); return -1; } break; } ctx->head->field = ++field; if (field->type == NULL) { --ctx->head; field = ctx->head->field; continue; } else if (field->type->typegroup == 'S') { size_t parent_offset = ctx->head->parent_offset + field->offset; if (field->type->fields->type == NULL) continue; field = field->type->fields; ++ctx->head; ctx->head->field = field; ctx->head->parent_offset = parent_offset; break; } else { break; } } } while (ctx->enc_count); ctx->enc_type = 0; ctx->is_complex = 0; return 0; } static PyObject * __pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp) { const char *ts = *tsp; int i = 0, number; int ndim = ctx->head->field->type->ndim; ; ++ts; if (ctx->new_count != 1) { PyErr_SetString(PyExc_ValueError, "Cannot handle repeated arrays in format string"); return NULL; } if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; while (*ts && *ts != ')') { switch (*ts) { case ' ': case '\f': case '\r': case '\n': case '\t': case '\v': continue; default: break; } number = __Pyx_BufFmt_ExpectNumber(&ts); if (number == -1) return NULL; if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i]) return PyErr_Format(PyExc_ValueError, "Expected a dimension of size %zu, got %d", ctx->head->field->type->arraysize[i], number); if (*ts != ',' && *ts != ')') return PyErr_Format(PyExc_ValueError, "Expected a comma in format string, got '%c'", *ts); if (*ts == ',') ts++; i++; } if (i != ndim) return PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d", ctx->head->field->type->ndim, i); if (!*ts) { PyErr_SetString(PyExc_ValueError, "Unexpected end of format string, expected ')'"); return NULL; } ctx->is_valid_array = 1; ctx->new_count = 1; *tsp = ++ts; return Py_None; } static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) { int got_Z = 0; while (1) { switch(*ts) { case 0: if (ctx->enc_type != 0 && ctx->head == NULL) { __Pyx_BufFmt_RaiseExpected(ctx); return NULL; } if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; if (ctx->head != NULL) { __Pyx_BufFmt_RaiseExpected(ctx); return NULL; } return ts; case ' ': case '\r': case '\n': ++ts; break; case '<': if (!__Pyx_Is_Little_Endian()) { PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler"); return NULL; } ctx->new_packmode = '='; ++ts; break; case '>': case '!': if (__Pyx_Is_Little_Endian()) { PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler"); return NULL; } ctx->new_packmode = '='; ++ts; break; case '=': case '@': case '^': ctx->new_packmode = *ts++; break; case 'T': { const char* ts_after_sub; size_t i, struct_count = ctx->new_count; size_t struct_alignment = ctx->struct_alignment; ctx->new_count = 1; ++ts; if (*ts != '{') { PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'"); return NULL; } if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->enc_type = 0; ctx->enc_count = 0; ctx->struct_alignment = 0; ++ts; ts_after_sub = ts; for (i = 0; i != struct_count; ++i) { ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts); if (!ts_after_sub) return NULL; } ts = ts_after_sub; if (struct_alignment) ctx->struct_alignment = struct_alignment; } break; case '}': { size_t alignment = ctx->struct_alignment; ++ts; if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->enc_type = 0; if (alignment && ctx->fmt_offset % alignment) { ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment); } } return ts; case 'x': if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->fmt_offset += ctx->new_count; ctx->new_count = 1; ctx->enc_count = 0; ctx->enc_type = 0; ctx->enc_packmode = ctx->new_packmode; ++ts; break; case 'Z': got_Z = 1; ++ts; if (*ts != 'f' && *ts != 'd' && *ts != 'g') { __Pyx_BufFmt_RaiseUnexpectedChar('Z'); return NULL; } CYTHON_FALLTHROUGH; case '?': case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I': case 'l': case 'L': case 'q': case 'Q': case 'f': case 'd': case 'g': case 'O': case 'p': if (ctx->enc_type == *ts && got_Z == ctx->is_complex && ctx->enc_packmode == ctx->new_packmode) { ctx->enc_count += ctx->new_count; ctx->new_count = 1; got_Z = 0; ++ts; break; } CYTHON_FALLTHROUGH; case 's': if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->enc_count = ctx->new_count; ctx->enc_packmode = ctx->new_packmode; ctx->enc_type = *ts; ctx->is_complex = got_Z; ++ts; ctx->new_count = 1; got_Z = 0; break; case ':': ++ts; while(*ts != ':') ++ts; ++ts; break; case '(': if (!__pyx_buffmt_parse_array(ctx, &ts)) return NULL; break; default: { int number = __Pyx_BufFmt_ExpectNumber(&ts); if (number == -1) return NULL; ctx->new_count = (size_t)number; } } } } /* BufferGetAndValidate */ static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) { if (unlikely(info->buf == NULL)) return; if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL; __Pyx_ReleaseBuffer(info); } static void __Pyx_ZeroBuffer(Py_buffer* buf) { buf->buf = NULL; buf->obj = NULL; buf->strides = __Pyx_zeros; buf->shape = __Pyx_zeros; buf->suboffsets = __Pyx_minusones; } static int __Pyx__GetBufferAndValidate( Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) { buf->buf = NULL; if (unlikely(__Pyx_GetBuffer(obj, buf, flags) == -1)) { __Pyx_ZeroBuffer(buf); return -1; } if (unlikely(buf->ndim != nd)) { PyErr_Format(PyExc_ValueError, "Buffer has wrong number of dimensions (expected %d, got %d)", nd, buf->ndim); goto fail; } if (!cast) { __Pyx_BufFmt_Context ctx; __Pyx_BufFmt_Init(&ctx, stack, dtype); if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail; } if (unlikely((size_t)buf->itemsize != dtype->size)) { PyErr_Format(PyExc_ValueError, "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "d byte%s) does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "d byte%s)", buf->itemsize, (buf->itemsize > 1) ? "s" : "", dtype->name, (Py_ssize_t)dtype->size, (dtype->size > 1) ? "s" : ""); goto fail; } if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones; return 0; fail:; __Pyx_SafeReleaseBuffer(buf); return -1; } /* BufferIndexError */ static void __Pyx_RaiseBufferIndexError(int axis) { PyErr_Format(PyExc_IndexError, "Out of bounds on buffer access (axis %d)", axis); } /* PyErrFetchRestore */ #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { PyObject *tmp_type, *tmp_value, *tmp_tb; tmp_type = tstate->curexc_type; tmp_value = tstate->curexc_value; tmp_tb = tstate->curexc_traceback; tstate->curexc_type = type; tstate->curexc_value = value; tstate->curexc_traceback = tb; Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); } static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { *type = tstate->curexc_type; *value = tstate->curexc_value; *tb = tstate->curexc_traceback; tstate->curexc_type = 0; tstate->curexc_value = 0; tstate->curexc_traceback = 0; } #endif /* WriteUnraisableException */ static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno, CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename, int full_traceback, CYTHON_UNUSED int nogil) { PyObject *old_exc, *old_val, *old_tb; PyObject *ctx; __Pyx_PyThreadState_declare #ifdef WITH_THREAD PyGILState_STATE state; if (nogil) state = PyGILState_Ensure(); #ifdef _MSC_VER else state = (PyGILState_STATE)-1; #endif #endif __Pyx_PyThreadState_assign __Pyx_ErrFetch(&old_exc, &old_val, &old_tb); if (full_traceback) { Py_XINCREF(old_exc); Py_XINCREF(old_val); Py_XINCREF(old_tb); __Pyx_ErrRestore(old_exc, old_val, old_tb); PyErr_PrintEx(1); } #if PY_MAJOR_VERSION < 3 ctx = PyString_FromString(name); #else ctx = PyUnicode_FromString(name); #endif __Pyx_ErrRestore(old_exc, old_val, old_tb); if (!ctx) { PyErr_WriteUnraisable(Py_None); } else { PyErr_WriteUnraisable(ctx); Py_DECREF(ctx); } #ifdef WITH_THREAD if (nogil) PyGILState_Release(state); #endif } /* RaiseException */ #if PY_MAJOR_VERSION < 3 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, CYTHON_UNUSED PyObject *cause) { __Pyx_PyThreadState_declare Py_XINCREF(type); if (!value || value == Py_None) value = NULL; else Py_INCREF(value); if (!tb || tb == Py_None) tb = NULL; else { Py_INCREF(tb); if (!PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto raise_error; } } if (PyType_Check(type)) { #if CYTHON_COMPILING_IN_PYPY if (!value) { Py_INCREF(Py_None); value = Py_None; } #endif PyErr_NormalizeException(&type, &value, &tb); } else { if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto raise_error; } value = type; type = (PyObject*) Py_TYPE(type); Py_INCREF(type); if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto raise_error; } } __Pyx_PyThreadState_assign __Pyx_ErrRestore(type, value, tb); return; raise_error: Py_XDECREF(value); Py_XDECREF(type); Py_XDECREF(tb); return; } #else static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { PyObject* owned_instance = NULL; if (tb == Py_None) { tb = 0; } else if (tb && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto bad; } if (value == Py_None) value = 0; if (PyExceptionInstance_Check(type)) { if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto bad; } value = type; type = (PyObject*) Py_TYPE(value); } else if (PyExceptionClass_Check(type)) { PyObject *instance_class = NULL; if (value && PyExceptionInstance_Check(value)) { instance_class = (PyObject*) Py_TYPE(value); if (instance_class != type) { int is_subclass = PyObject_IsSubclass(instance_class, type); if (!is_subclass) { instance_class = NULL; } else if (unlikely(is_subclass == -1)) { goto bad; } else { type = instance_class; } } } if (!instance_class) { PyObject *args; if (!value) args = PyTuple_New(0); else if (PyTuple_Check(value)) { Py_INCREF(value); args = value; } else args = PyTuple_Pack(1, value); if (!args) goto bad; owned_instance = PyObject_Call(type, args, NULL); Py_DECREF(args); if (!owned_instance) goto bad; value = owned_instance; if (!PyExceptionInstance_Check(value)) { PyErr_Format(PyExc_TypeError, "calling %R should have returned an instance of " "BaseException, not %R", type, Py_TYPE(value)); goto bad; } } } else { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto bad; } if (cause) { PyObject *fixed_cause; if (cause == Py_None) { fixed_cause = NULL; } else if (PyExceptionClass_Check(cause)) { fixed_cause = PyObject_CallObject(cause, NULL); if (fixed_cause == NULL) goto bad; } else if (PyExceptionInstance_Check(cause)) { fixed_cause = cause; Py_INCREF(fixed_cause); } else { PyErr_SetString(PyExc_TypeError, "exception causes must derive from " "BaseException"); goto bad; } PyException_SetCause(value, fixed_cause); } PyErr_SetObject(type, value); if (tb) { #if CYTHON_COMPILING_IN_PYPY PyObject *tmp_type, *tmp_value, *tmp_tb; PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); Py_INCREF(tb); PyErr_Restore(tmp_type, tmp_value, tb); Py_XDECREF(tmp_tb); #else PyThreadState *tstate = __Pyx_PyThreadState_Current; PyObject* tmp_tb = tstate->curexc_traceback; if (tb != tmp_tb) { Py_INCREF(tb); tstate->curexc_traceback = tb; Py_XDECREF(tmp_tb); } #endif } bad: Py_XDECREF(owned_instance); return; } #endif /* PyCFunctionFastCall */ #if CYTHON_FAST_PYCCALL static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { PyCFunctionObject *func = (PyCFunctionObject*)func_obj; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); int flags = PyCFunction_GET_FLAGS(func); assert(PyCFunction_Check(func)); assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); assert(nargs >= 0); assert(nargs == 0 || args != NULL); /* _PyCFunction_FastCallDict() must not be called with an exception set, because it may clear it (directly or indirectly) and so the caller loses its exception */ assert(!PyErr_Occurred()); if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); } else { return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); } } #endif /* PyFunctionFastCall */ #if CYTHON_FAST_PYCALL static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, PyObject *globals) { PyFrameObject *f; PyThreadState *tstate = __Pyx_PyThreadState_Current; PyObject **fastlocals; Py_ssize_t i; PyObject *result; assert(globals != NULL); /* XXX Perhaps we should create a specialized PyFrame_New() that doesn't take locals, but does take builtins without sanity checking them. */ assert(tstate != NULL); f = PyFrame_New(tstate, co, globals, NULL); if (f == NULL) { return NULL; } fastlocals = __Pyx_PyFrame_GetLocalsplus(f); for (i = 0; i < na; i++) { Py_INCREF(*args); fastlocals[i] = *args++; } result = PyEval_EvalFrameEx(f,0); ++tstate->recursion_depth; Py_DECREF(f); --tstate->recursion_depth; return result; } #if 1 || PY_VERSION_HEX < 0x030600B1 static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func); PyObject *closure; #if PY_MAJOR_VERSION >= 3 PyObject *kwdefs; #endif PyObject *kwtuple, **k; PyObject **d; Py_ssize_t nd; Py_ssize_t nk; PyObject *result; assert(kwargs == NULL || PyDict_Check(kwargs)); nk = kwargs ? PyDict_Size(kwargs) : 0; if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { return NULL; } if ( #if PY_MAJOR_VERSION >= 3 co->co_kwonlyargcount == 0 && #endif likely(kwargs == NULL || nk == 0) && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { if (argdefs == NULL && co->co_argcount == nargs) { result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); goto done; } else if (nargs == 0 && argdefs != NULL && co->co_argcount == Py_SIZE(argdefs)) { /* function called with no arguments, but all parameters have a default value: use default values as arguments .*/ args = &PyTuple_GET_ITEM(argdefs, 0); result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); goto done; } } if (kwargs != NULL) { Py_ssize_t pos, i; kwtuple = PyTuple_New(2 * nk); if (kwtuple == NULL) { result = NULL; goto done; } k = &PyTuple_GET_ITEM(kwtuple, 0); pos = i = 0; while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { Py_INCREF(k[i]); Py_INCREF(k[i+1]); i += 2; } nk = i / 2; } else { kwtuple = NULL; k = NULL; } closure = PyFunction_GET_CLOSURE(func); #if PY_MAJOR_VERSION >= 3 kwdefs = PyFunction_GET_KW_DEFAULTS(func); #endif if (argdefs != NULL) { d = &PyTuple_GET_ITEM(argdefs, 0); nd = Py_SIZE(argdefs); } else { d = NULL; nd = 0; } #if PY_MAJOR_VERSION >= 3 result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, args, (int)nargs, k, (int)nk, d, (int)nd, kwdefs, closure); #else result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, args, (int)nargs, k, (int)nk, d, (int)nd, closure); #endif Py_XDECREF(kwtuple); done: Py_LeaveRecursiveCall(); return result; } #endif #endif /* PyObjectCallMethO */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { PyObject *self, *result; PyCFunction cfunc; cfunc = PyCFunction_GET_FUNCTION(func); self = PyCFunction_GET_SELF(func); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) return NULL; result = cfunc(self, arg); Py_LeaveRecursiveCall(); if (unlikely(!result) && unlikely(!PyErr_Occurred())) { PyErr_SetString( PyExc_SystemError, "NULL result without error in PyObject_Call"); } return result; } #endif /* PyObjectCallOneArg */ #if CYTHON_COMPILING_IN_CPYTHON static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { PyObject *result; PyObject *args = PyTuple_New(1); if (unlikely(!args)) return NULL; Py_INCREF(arg); PyTuple_SET_ITEM(args, 0, arg); result = __Pyx_PyObject_Call(func, args, NULL); Py_DECREF(args); return result; } static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { #if CYTHON_FAST_PYCALL if (PyFunction_Check(func)) { return __Pyx_PyFunction_FastCall(func, &arg, 1); } #endif if (likely(PyCFunction_Check(func))) { if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { return __Pyx_PyObject_CallMethO(func, arg); #if CYTHON_FAST_PYCCALL } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { return __Pyx_PyCFunction_FastCall(func, &arg, 1); #endif } } return __Pyx__PyObject_CallOneArg(func, arg); } #else static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { PyObject *result; PyObject *args = PyTuple_Pack(1, arg); if (unlikely(!args)) return NULL; result = __Pyx_PyObject_Call(func, args, NULL); Py_DECREF(args); return result; } #endif /* DictGetItem */ #if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) { PyObject *value; value = PyDict_GetItemWithError(d, key); if (unlikely(!value)) { if (!PyErr_Occurred()) { if (unlikely(PyTuple_Check(key))) { PyObject* args = PyTuple_Pack(1, key); if (likely(args)) { PyErr_SetObject(PyExc_KeyError, args); Py_DECREF(args); } } else { PyErr_SetObject(PyExc_KeyError, key); } } return NULL; } Py_INCREF(value); return value; } #endif /* RaiseTooManyValuesToUnpack */ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { PyErr_Format(PyExc_ValueError, "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); } /* RaiseNeedMoreValuesToUnpack */ static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { PyErr_Format(PyExc_ValueError, "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", index, (index == 1) ? "" : "s"); } /* RaiseNoneIterError */ static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); } /* GetTopmostException */ #if CYTHON_USE_EXC_INFO_STACK static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate) { _PyErr_StackItem *exc_info = tstate->exc_info; while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && exc_info->previous_item != NULL) { exc_info = exc_info->previous_item; } return exc_info; } #endif /* SaveResetException */ #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { #if CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); *type = exc_info->exc_type; *value = exc_info->exc_value; *tb = exc_info->exc_traceback; #else *type = tstate->exc_type; *value = tstate->exc_value; *tb = tstate->exc_traceback; #endif Py_XINCREF(*type); Py_XINCREF(*value); Py_XINCREF(*tb); } static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { PyObject *tmp_type, *tmp_value, *tmp_tb; #if CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = tstate->exc_info; tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; tmp_tb = exc_info->exc_traceback; exc_info->exc_type = type; exc_info->exc_value = value; exc_info->exc_traceback = tb; #else tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; tstate->exc_type = type; tstate->exc_value = value; tstate->exc_traceback = tb; #endif Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); } #endif /* PyErrExceptionMatches */ #if CYTHON_FAST_THREAD_STATE static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { Py_ssize_t i, n; n = PyTuple_GET_SIZE(tuple); #if PY_MAJOR_VERSION >= 3 for (i=0; icurexc_type; if (exc_type == err) return 1; if (unlikely(!exc_type)) return 0; if (unlikely(PyTuple_Check(err))) return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); } #endif /* GetException */ #if CYTHON_FAST_THREAD_STATE static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) #else static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) #endif { PyObject *local_type, *local_value, *local_tb; #if CYTHON_FAST_THREAD_STATE PyObject *tmp_type, *tmp_value, *tmp_tb; local_type = tstate->curexc_type; local_value = tstate->curexc_value; local_tb = tstate->curexc_traceback; tstate->curexc_type = 0; tstate->curexc_value = 0; tstate->curexc_traceback = 0; #else PyErr_Fetch(&local_type, &local_value, &local_tb); #endif PyErr_NormalizeException(&local_type, &local_value, &local_tb); #if CYTHON_FAST_THREAD_STATE if (unlikely(tstate->curexc_type)) #else if (unlikely(PyErr_Occurred())) #endif goto bad; #if PY_MAJOR_VERSION >= 3 if (local_tb) { if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) goto bad; } #endif Py_XINCREF(local_tb); Py_XINCREF(local_type); Py_XINCREF(local_value); *type = local_type; *value = local_value; *tb = local_tb; #if CYTHON_FAST_THREAD_STATE #if CYTHON_USE_EXC_INFO_STACK { _PyErr_StackItem *exc_info = tstate->exc_info; tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; tmp_tb = exc_info->exc_traceback; exc_info->exc_type = local_type; exc_info->exc_value = local_value; exc_info->exc_traceback = local_tb; } #else tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; tstate->exc_type = local_type; tstate->exc_value = local_value; tstate->exc_traceback = local_tb; #endif Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); #else PyErr_SetExcInfo(local_type, local_value, local_tb); #endif return 0; bad: *type = 0; *value = 0; *tb = 0; Py_XDECREF(local_type); Py_XDECREF(local_value); Py_XDECREF(local_tb); return -1; } /* TypeImport */ #ifndef __PYX_HAVE_RT_ImportType #define __PYX_HAVE_RT_ImportType static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size) { PyObject *result = 0; char warning[200]; Py_ssize_t basicsize; #ifdef Py_LIMITED_API PyObject *py_basicsize; #endif result = PyObject_GetAttrString(module, class_name); if (!result) goto bad; if (!PyType_Check(result)) { PyErr_Format(PyExc_TypeError, "%.200s.%.200s is not a type object", module_name, class_name); goto bad; } #ifndef Py_LIMITED_API basicsize = ((PyTypeObject *)result)->tp_basicsize; #else py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); if (!py_basicsize) goto bad; basicsize = PyLong_AsSsize_t(py_basicsize); Py_DECREF(py_basicsize); py_basicsize = 0; if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) goto bad; #endif if ((size_t)basicsize < size) { PyErr_Format(PyExc_ValueError, "%.200s.%.200s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); goto bad; } if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { PyErr_Format(PyExc_ValueError, "%.200s.%.200s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); goto bad; } else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { PyOS_snprintf(warning, sizeof(warning), "%s.%s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; } return (PyTypeObject *)result; bad: Py_XDECREF(result); return NULL; } #endif /* Import */ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { PyObject *empty_list = 0; PyObject *module = 0; PyObject *global_dict = 0; PyObject *empty_dict = 0; PyObject *list; #if PY_MAJOR_VERSION < 3 PyObject *py_import; py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); if (!py_import) goto bad; #endif if (from_list) list = from_list; else { empty_list = PyList_New(0); if (!empty_list) goto bad; list = empty_list; } global_dict = PyModule_GetDict(__pyx_m); if (!global_dict) goto bad; empty_dict = PyDict_New(); if (!empty_dict) goto bad; { #if PY_MAJOR_VERSION >= 3 if (level == -1) { if (strchr(__Pyx_MODULE_NAME, '.')) { module = PyImport_ImportModuleLevelObject( name, global_dict, empty_dict, list, 1); if (!module) { if (!PyErr_ExceptionMatches(PyExc_ImportError)) goto bad; PyErr_Clear(); } } level = 0; } #endif if (!module) { #if PY_MAJOR_VERSION < 3 PyObject *py_level = PyInt_FromLong(level); if (!py_level) goto bad; module = PyObject_CallFunctionObjArgs(py_import, name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); Py_DECREF(py_level); #else module = PyImport_ImportModuleLevelObject( name, global_dict, empty_dict, list, level); #endif } } bad: #if PY_MAJOR_VERSION < 3 Py_XDECREF(py_import); #endif Py_XDECREF(empty_list); Py_XDECREF(empty_dict); return module; } /* CLineInTraceback */ #ifndef CYTHON_CLINE_IN_TRACEBACK static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { PyObject *use_cline; PyObject *ptype, *pvalue, *ptraceback; #if CYTHON_COMPILING_IN_CPYTHON PyObject **cython_runtime_dict; #endif if (unlikely(!__pyx_cython_runtime)) { return c_line; } __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); #if CYTHON_COMPILING_IN_CPYTHON cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); if (likely(cython_runtime_dict)) { __PYX_PY_DICT_LOOKUP_IF_MODIFIED( use_cline, *cython_runtime_dict, __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) } else #endif { PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); if (use_cline_obj) { use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; Py_DECREF(use_cline_obj); } else { PyErr_Clear(); use_cline = NULL; } } if (!use_cline) { c_line = 0; PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); } else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { c_line = 0; } __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); return c_line; } #endif /* CodeObjectCache */ static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { int start = 0, mid = 0, end = count - 1; if (end >= 0 && code_line > entries[end].code_line) { return count; } while (start < end) { mid = start + (end - start) / 2; if (code_line < entries[mid].code_line) { end = mid; } else if (code_line > entries[mid].code_line) { start = mid + 1; } else { return mid; } } if (code_line <= entries[mid].code_line) { return mid; } else { return mid + 1; } } static PyCodeObject *__pyx_find_code_object(int code_line) { PyCodeObject* code_object; int pos; if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { return NULL; } pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { return NULL; } code_object = __pyx_code_cache.entries[pos].code_object; Py_INCREF(code_object); return code_object; } static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { int pos, i; __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; if (unlikely(!code_line)) { return; } if (unlikely(!entries)) { entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); if (likely(entries)) { __pyx_code_cache.entries = entries; __pyx_code_cache.max_count = 64; __pyx_code_cache.count = 1; entries[0].code_line = code_line; entries[0].code_object = code_object; Py_INCREF(code_object); } return; } pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { PyCodeObject* tmp = entries[pos].code_object; entries[pos].code_object = code_object; Py_DECREF(tmp); return; } if (__pyx_code_cache.count == __pyx_code_cache.max_count) { int new_max = __pyx_code_cache.max_count + 64; entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( __pyx_code_cache.entries, (size_t)new_max*sizeof(__Pyx_CodeObjectCacheEntry)); if (unlikely(!entries)) { return; } __pyx_code_cache.entries = entries; __pyx_code_cache.max_count = new_max; } for (i=__pyx_code_cache.count; i>pos; i--) { entries[i] = entries[i-1]; } entries[pos].code_line = code_line; entries[pos].code_object = code_object; __pyx_code_cache.count++; Py_INCREF(code_object); } /* AddTraceback */ #include "compile.h" #include "frameobject.h" #include "traceback.h" static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( const char *funcname, int c_line, int py_line, const char *filename) { PyCodeObject *py_code = 0; PyObject *py_srcfile = 0; PyObject *py_funcname = 0; #if PY_MAJOR_VERSION < 3 py_srcfile = PyString_FromString(filename); #else py_srcfile = PyUnicode_FromString(filename); #endif if (!py_srcfile) goto bad; if (c_line) { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); #else py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); #endif } else { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromString(funcname); #else py_funcname = PyUnicode_FromString(funcname); #endif } if (!py_funcname) goto bad; py_code = __Pyx_PyCode_New( 0, 0, 0, 0, 0, __pyx_empty_bytes, /*PyObject *code,*/ __pyx_empty_tuple, /*PyObject *consts,*/ __pyx_empty_tuple, /*PyObject *names,*/ __pyx_empty_tuple, /*PyObject *varnames,*/ __pyx_empty_tuple, /*PyObject *freevars,*/ __pyx_empty_tuple, /*PyObject *cellvars,*/ py_srcfile, /*PyObject *filename,*/ py_funcname, /*PyObject *name,*/ py_line, __pyx_empty_bytes /*PyObject *lnotab*/ ); Py_DECREF(py_srcfile); Py_DECREF(py_funcname); return py_code; bad: Py_XDECREF(py_srcfile); Py_XDECREF(py_funcname); return NULL; } static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename) { PyCodeObject *py_code = 0; PyFrameObject *py_frame = 0; PyThreadState *tstate = __Pyx_PyThreadState_Current; if (c_line) { c_line = __Pyx_CLineForTraceback(tstate, c_line); } py_code = __pyx_find_code_object(c_line ? -c_line : py_line); if (!py_code) { py_code = __Pyx_CreateCodeObjectForTraceback( funcname, c_line, py_line, filename); if (!py_code) goto bad; __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); } py_frame = PyFrame_New( tstate, /*PyThreadState *tstate,*/ py_code, /*PyCodeObject *code,*/ __pyx_d, /*PyObject *globals,*/ 0 /*PyObject *locals*/ ); if (!py_frame) goto bad; __Pyx_PyFrame_SetLineNumber(py_frame, py_line); PyTraceBack_Here(py_frame); bad: Py_XDECREF(py_code); Py_XDECREF(py_frame); } #if PY_MAJOR_VERSION < 3 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags); if (__Pyx_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pw_5numpy_7ndarray_1__getbuffer__(obj, view, flags); PyErr_Format(PyExc_TypeError, "'%.200s' does not have the buffer interface", Py_TYPE(obj)->tp_name); return -1; } static void __Pyx_ReleaseBuffer(Py_buffer *view) { PyObject *obj = view->obj; if (!obj) return; if (PyObject_CheckBuffer(obj)) { PyBuffer_Release(view); return; } if ((0)) {} else if (__Pyx_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) __pyx_pw_5numpy_7ndarray_3__releasebuffer__(obj, view); view->obj = NULL; Py_DECREF(obj); } #endif /* CIntFromPyVerify */ #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) #define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) #define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ {\ func_type value = func_value;\ if (sizeof(target_type) < sizeof(func_type)) {\ if (unlikely(value != (func_type) (target_type) value)) {\ func_type zero = 0;\ if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ return (target_type) -1;\ if (is_unsigned && unlikely(value < zero))\ goto raise_neg_overflow;\ else\ goto raise_overflow;\ }\ }\ return (target_type) value;\ } /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(int) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(int) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof(int) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; return _PyLong_FromByteArray(bytes, sizeof(int), little, !is_unsigned); } } /* Declarations */ #if CYTHON_CCOMPLEX #ifdef __cplusplus static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { return ::std::complex< float >(x, y); } #else static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { return x + y*(__pyx_t_float_complex)_Complex_I; } #endif #else static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { __pyx_t_float_complex z; z.real = x; z.imag = y; return z; } #endif /* Arithmetic */ #if CYTHON_CCOMPLEX #else static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { return (a.real == b.real) && (a.imag == b.imag); } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; z.real = a.real + b.real; z.imag = a.imag + b.imag; return z; } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; z.real = a.real - b.real; z.imag = a.imag - b.imag; return z; } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; z.real = a.real * b.real - a.imag * b.imag; z.imag = a.real * b.imag + a.imag * b.real; return z; } #if 1 static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { if (b.imag == 0) { return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); } else if (fabsf(b.real) >= fabsf(b.imag)) { if (b.real == 0 && b.imag == 0) { return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.imag); } else { float r = b.imag / b.real; float s = (float)(1.0) / (b.real + b.imag * r); return __pyx_t_float_complex_from_parts( (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); } } else { float r = b.real / b.imag; float s = (float)(1.0) / (b.imag + b.real * r); return __pyx_t_float_complex_from_parts( (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); } } #else static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { if (b.imag == 0) { return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); } else { float denom = b.real * b.real + b.imag * b.imag; return __pyx_t_float_complex_from_parts( (a.real * b.real + a.imag * b.imag) / denom, (a.imag * b.real - a.real * b.imag) / denom); } } #endif static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex a) { __pyx_t_float_complex z; z.real = -a.real; z.imag = -a.imag; return z; } static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex a) { return (a.real == 0) && (a.imag == 0); } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex a) { __pyx_t_float_complex z; z.real = a.real; z.imag = -a.imag; return z; } #if 1 static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex z) { #if !defined(HAVE_HYPOT) || defined(_MSC_VER) return sqrtf(z.real*z.real + z.imag*z.imag); #else return hypotf(z.real, z.imag); #endif } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; float r, lnr, theta, z_r, z_theta; if (b.imag == 0 && b.real == (int)b.real) { if (b.real < 0) { float denom = a.real * a.real + a.imag * a.imag; a.real = a.real / denom; a.imag = -a.imag / denom; b.real = -b.real; } switch ((int)b.real) { case 0: z.real = 1; z.imag = 0; return z; case 1: return a; case 2: return __Pyx_c_prod_float(a, a); case 3: z = __Pyx_c_prod_float(a, a); return __Pyx_c_prod_float(z, a); case 4: z = __Pyx_c_prod_float(a, a); return __Pyx_c_prod_float(z, z); } } if (a.imag == 0) { if (a.real == 0) { return a; } else if (b.imag == 0) { z.real = powf(a.real, b.real); z.imag = 0; return z; } else if (a.real > 0) { r = a.real; theta = 0; } else { r = -a.real; theta = atan2f(0.0, -1.0); } } else { r = __Pyx_c_abs_float(a); theta = atan2f(a.imag, a.real); } lnr = logf(r); z_r = expf(lnr * b.real - theta * b.imag); z_theta = theta * b.real + lnr * b.imag; z.real = z_r * cosf(z_theta); z.imag = z_r * sinf(z_theta); return z; } #endif #endif /* Declarations */ #if CYTHON_CCOMPLEX #ifdef __cplusplus static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { return ::std::complex< double >(x, y); } #else static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { return x + y*(__pyx_t_double_complex)_Complex_I; } #endif #else static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { __pyx_t_double_complex z; z.real = x; z.imag = y; return z; } #endif /* Arithmetic */ #if CYTHON_CCOMPLEX #else static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { return (a.real == b.real) && (a.imag == b.imag); } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; z.real = a.real + b.real; z.imag = a.imag + b.imag; return z; } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; z.real = a.real - b.real; z.imag = a.imag - b.imag; return z; } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; z.real = a.real * b.real - a.imag * b.imag; z.imag = a.real * b.imag + a.imag * b.real; return z; } #if 1 static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { if (b.imag == 0) { return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); } else if (fabs(b.real) >= fabs(b.imag)) { if (b.real == 0 && b.imag == 0) { return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.imag); } else { double r = b.imag / b.real; double s = (double)(1.0) / (b.real + b.imag * r); return __pyx_t_double_complex_from_parts( (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); } } else { double r = b.real / b.imag; double s = (double)(1.0) / (b.imag + b.real * r); return __pyx_t_double_complex_from_parts( (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); } } #else static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { if (b.imag == 0) { return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); } else { double denom = b.real * b.real + b.imag * b.imag; return __pyx_t_double_complex_from_parts( (a.real * b.real + a.imag * b.imag) / denom, (a.imag * b.real - a.real * b.imag) / denom); } } #endif static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex a) { __pyx_t_double_complex z; z.real = -a.real; z.imag = -a.imag; return z; } static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex a) { return (a.real == 0) && (a.imag == 0); } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex a) { __pyx_t_double_complex z; z.real = a.real; z.imag = -a.imag; return z; } #if 1 static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex z) { #if !defined(HAVE_HYPOT) || defined(_MSC_VER) return sqrt(z.real*z.real + z.imag*z.imag); #else return hypot(z.real, z.imag); #endif } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; double r, lnr, theta, z_r, z_theta; if (b.imag == 0 && b.real == (int)b.real) { if (b.real < 0) { double denom = a.real * a.real + a.imag * a.imag; a.real = a.real / denom; a.imag = -a.imag / denom; b.real = -b.real; } switch ((int)b.real) { case 0: z.real = 1; z.imag = 0; return z; case 1: return a; case 2: return __Pyx_c_prod_double(a, a); case 3: z = __Pyx_c_prod_double(a, a); return __Pyx_c_prod_double(z, a); case 4: z = __Pyx_c_prod_double(a, a); return __Pyx_c_prod_double(z, z); } } if (a.imag == 0) { if (a.real == 0) { return a; } else if (b.imag == 0) { z.real = pow(a.real, b.real); z.imag = 0; return z; } else if (a.real > 0) { r = a.real; theta = 0; } else { r = -a.real; theta = atan2(0.0, -1.0); } } else { r = __Pyx_c_abs_double(a); theta = atan2(a.imag, a.real); } lnr = log(r); z_r = exp(lnr * b.real - theta * b.imag); z_theta = theta * b.real + lnr * b.imag; z.real = z_r * cos(z_theta); z.imag = z_r * sin(z_theta); return z; } #endif #endif /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__NPY_TYPES(enum NPY_TYPES value) { const enum NPY_TYPES neg_one = (enum NPY_TYPES) ((enum NPY_TYPES) 0 - (enum NPY_TYPES) 1), const_zero = (enum NPY_TYPES) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(enum NPY_TYPES) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(enum NPY_TYPES) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(enum NPY_TYPES) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof(enum NPY_TYPES) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(enum NPY_TYPES) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; return _PyLong_FromByteArray(bytes, sizeof(enum NPY_TYPES), little, !is_unsigned); } } /* CIntFromPy */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { if (sizeof(int) < sizeof(long)) { __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } return (int) val; } } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (int) 0; case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) case 2: if (8 * sizeof(int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); } } break; case 3: if (8 * sizeof(int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); } } break; case 4: if (8 * sizeof(int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); } } break; } #endif #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { goto raise_neg_overflow; } #else { int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) return (int) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif if (sizeof(int) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (int) 0; case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) case -2: if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case 2: if (8 * sizeof(int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case -3: if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case 3: if (8 * sizeof(int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case -4: if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case 4: if (8 * sizeof(int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; } #endif if (sizeof(int) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } { #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); #else int val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { PyObject *tmp = v; v = PyNumber_Long(tmp); Py_DECREF(tmp); } #endif if (likely(v)) { int one = 1; int is_little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&val; int ret = _PyLong_AsByteArray((PyLongObject *)v, bytes, sizeof(val), is_little, !is_unsigned); Py_DECREF(v); if (likely(!ret)) return val; } #endif return (int) -1; } } else { int val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); if (!tmp) return (int) -1; val = __Pyx_PyInt_As_int(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, "value too large to convert to int"); return (int) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, "can't convert negative value to int"); return (int) -1; } /* CIntFromPy */ static CYTHON_INLINE unsigned int __Pyx_PyInt_As_unsigned_int(PyObject *x) { const unsigned int neg_one = (unsigned int) ((unsigned int) 0 - (unsigned int) 1), const_zero = (unsigned int) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { if (sizeof(unsigned int) < sizeof(long)) { __PYX_VERIFY_RETURN_INT(unsigned int, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } return (unsigned int) val; } } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (unsigned int) 0; case 1: __PYX_VERIFY_RETURN_INT(unsigned int, digit, digits[0]) case 2: if (8 * sizeof(unsigned int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) >= 2 * PyLong_SHIFT) { return (unsigned int) (((((unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])); } } break; case 3: if (8 * sizeof(unsigned int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) >= 3 * PyLong_SHIFT) { return (unsigned int) (((((((unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])); } } break; case 4: if (8 * sizeof(unsigned int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) >= 4 * PyLong_SHIFT) { return (unsigned int) (((((((((unsigned int)digits[3]) << PyLong_SHIFT) | (unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])); } } break; } #endif #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { goto raise_neg_overflow; } #else { int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) return (unsigned int) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif if (sizeof(unsigned int) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(unsigned int, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(unsigned int) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(unsigned int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (unsigned int) 0; case -1: __PYX_VERIFY_RETURN_INT(unsigned int, sdigit, (sdigit) (-(sdigit)digits[0])) case 1: __PYX_VERIFY_RETURN_INT(unsigned int, digit, +digits[0]) case -2: if (8 * sizeof(unsigned int) - 1 > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 2 * PyLong_SHIFT) { return (unsigned int) (((unsigned int)-1)*(((((unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case 2: if (8 * sizeof(unsigned int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 2 * PyLong_SHIFT) { return (unsigned int) ((((((unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case -3: if (8 * sizeof(unsigned int) - 1 > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 3 * PyLong_SHIFT) { return (unsigned int) (((unsigned int)-1)*(((((((unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case 3: if (8 * sizeof(unsigned int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 3 * PyLong_SHIFT) { return (unsigned int) ((((((((unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case -4: if (8 * sizeof(unsigned int) - 1 > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 4 * PyLong_SHIFT) { return (unsigned int) (((unsigned int)-1)*(((((((((unsigned int)digits[3]) << PyLong_SHIFT) | (unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case 4: if (8 * sizeof(unsigned int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 4 * PyLong_SHIFT) { return (unsigned int) ((((((((((unsigned int)digits[3]) << PyLong_SHIFT) | (unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; } #endif if (sizeof(unsigned int) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(unsigned int, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(unsigned int) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(unsigned int, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } { #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); #else unsigned int val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { PyObject *tmp = v; v = PyNumber_Long(tmp); Py_DECREF(tmp); } #endif if (likely(v)) { int one = 1; int is_little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&val; int ret = _PyLong_AsByteArray((PyLongObject *)v, bytes, sizeof(val), is_little, !is_unsigned); Py_DECREF(v); if (likely(!ret)) return val; } #endif return (unsigned int) -1; } } else { unsigned int val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); if (!tmp) return (unsigned int) -1; val = __Pyx_PyInt_As_unsigned_int(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, "value too large to convert to unsigned int"); return (unsigned int) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, "can't convert negative value to unsigned int"); return (unsigned int) -1; } /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(long) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(long) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof(long) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; return _PyLong_FromByteArray(bytes, sizeof(long), little, !is_unsigned); } } /* CIntFromPy */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { if (sizeof(long) < sizeof(long)) { __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } return (long) val; } } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (long) 0; case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) case 2: if (8 * sizeof(long) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); } } break; case 3: if (8 * sizeof(long) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); } } break; case 4: if (8 * sizeof(long) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); } } break; } #endif #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { goto raise_neg_overflow; } #else { int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) return (long) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif if (sizeof(long) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (long) 0; case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) case -2: if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case 2: if (8 * sizeof(long) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case -3: if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case 3: if (8 * sizeof(long) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case -4: if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case 4: if (8 * sizeof(long) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; } #endif if (sizeof(long) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } { #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); #else long val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { PyObject *tmp = v; v = PyNumber_Long(tmp); Py_DECREF(tmp); } #endif if (likely(v)) { int one = 1; int is_little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&val; int ret = _PyLong_AsByteArray((PyLongObject *)v, bytes, sizeof(val), is_little, !is_unsigned); Py_DECREF(v); if (likely(!ret)) return val; } #endif return (long) -1; } } else { long val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); if (!tmp) return (long) -1; val = __Pyx_PyInt_As_long(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, "value too large to convert to long"); return (long) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, "can't convert negative value to long"); return (long) -1; } /* FastTypeChecks */ #if CYTHON_COMPILING_IN_CPYTHON static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { while (a) { a = a->tp_base; if (a == b) return 1; } return b == &PyBaseObject_Type; } static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { PyObject *mro; if (a == b) return 1; mro = a->tp_mro; if (likely(mro)) { Py_ssize_t i, n; n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) return 1; } return 0; } return __Pyx_InBases(a, b); } #if PY_MAJOR_VERSION == 2 static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { PyObject *exception, *value, *tb; int res; __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ErrFetch(&exception, &value, &tb); res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; if (unlikely(res == -1)) { PyErr_WriteUnraisable(err); res = 0; } if (!res) { res = PyObject_IsSubclass(err, exc_type2); if (unlikely(res == -1)) { PyErr_WriteUnraisable(err); res = 0; } } __Pyx_ErrRestore(exception, value, tb); return res; } #else static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; if (!res) { res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); } return res; } #endif static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { Py_ssize_t i, n; assert(PyExceptionClass_Check(exc_type)); n = PyTuple_GET_SIZE(tuple); #if PY_MAJOR_VERSION >= 3 for (i=0; i= 0x02070000 if (!PyCapsule_IsValid(cobj, sig)) { PyErr_Format(PyExc_TypeError, "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", PyModule_GetName(module), funcname, sig, PyCapsule_GetName(cobj)); goto bad; } tmp.p = PyCapsule_GetPointer(cobj, sig); #else {const char *desc, *s1, *s2; desc = (const char *)PyCObject_GetDesc(cobj); if (!desc) goto bad; s1 = desc; s2 = sig; while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } if (*s1 != *s2) { PyErr_Format(PyExc_TypeError, "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", PyModule_GetName(module), funcname, sig, desc); goto bad; } tmp.p = PyCObject_AsVoidPtr(cobj);} #endif *f = tmp.fp; if (!(*f)) goto bad; Py_DECREF(d); return 0; bad: Py_XDECREF(d); return -1; } #endif /* InitStrings */ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { while (t->p) { #if PY_MAJOR_VERSION < 3 if (t->is_unicode) { *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); } else if (t->intern) { *t->p = PyString_InternFromString(t->s); } else { *t->p = PyString_FromStringAndSize(t->s, t->n - 1); } #else if (t->is_unicode | t->is_str) { if (t->intern) { *t->p = PyUnicode_InternFromString(t->s); } else if (t->encoding) { *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); } else { *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); } } else { *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); } #endif if (!*t->p) return -1; if (PyObject_Hash(*t->p) == -1) return -1; ++t; } return 0; } static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); } static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { Py_ssize_t ignore; return __Pyx_PyObject_AsStringAndSize(o, &ignore); } #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT #if !CYTHON_PEP393_ENABLED static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { char* defenc_c; PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); if (!defenc) return NULL; defenc_c = PyBytes_AS_STRING(defenc); #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII { char* end = defenc_c + PyBytes_GET_SIZE(defenc); char* c; for (c = defenc_c; c < end; c++) { if ((unsigned char) (*c) >= 128) { PyUnicode_AsASCIIString(o); return NULL; } } } #endif *length = PyBytes_GET_SIZE(defenc); return defenc_c; } #else static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII if (likely(PyUnicode_IS_ASCII(o))) { *length = PyUnicode_GET_LENGTH(o); return PyUnicode_AsUTF8(o); } else { PyUnicode_AsASCIIString(o); return NULL; } #else return PyUnicode_AsUTF8AndSize(o, length); #endif } #endif #endif static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT if ( #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII __Pyx_sys_getdefaultencoding_not_ascii && #endif PyUnicode_Check(o)) { return __Pyx_PyUnicode_AsStringAndSize(o, length); } else #endif #if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) if (PyByteArray_Check(o)) { *length = PyByteArray_GET_SIZE(o); return PyByteArray_AS_STRING(o); } else #endif { char* result; int r = PyBytes_AsStringAndSize(o, &result, length); if (unlikely(r < 0)) { return NULL; } else { return result; } } } static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { int is_true = x == Py_True; if (is_true | (x == Py_False) | (x == Py_None)) return is_true; else return PyObject_IsTrue(x); } static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { int retval; if (unlikely(!x)) return -1; retval = __Pyx_PyObject_IsTrue(x); Py_DECREF(x); return retval; } static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { #if PY_MAJOR_VERSION >= 3 if (PyLong_Check(result)) { if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, "__int__ returned non-int (type %.200s). " "The ability to return an instance of a strict subclass of int " "is deprecated, and may be removed in a future version of Python.", Py_TYPE(result)->tp_name)) { Py_DECREF(result); return NULL; } return result; } #endif PyErr_Format(PyExc_TypeError, "__%.4s__ returned non-%.4s (type %.200s)", type_name, type_name, Py_TYPE(result)->tp_name); Py_DECREF(result); return NULL; } static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { #if CYTHON_USE_TYPE_SLOTS PyNumberMethods *m; #endif const char *name = NULL; PyObject *res = NULL; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x) || PyLong_Check(x))) #else if (likely(PyLong_Check(x))) #endif return __Pyx_NewRef(x); #if CYTHON_USE_TYPE_SLOTS m = Py_TYPE(x)->tp_as_number; #if PY_MAJOR_VERSION < 3 if (m && m->nb_int) { name = "int"; res = m->nb_int(x); } else if (m && m->nb_long) { name = "long"; res = m->nb_long(x); } #else if (likely(m && m->nb_int)) { name = "int"; res = m->nb_int(x); } #endif #else if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { res = PyNumber_Int(x); } #endif if (likely(res)) { #if PY_MAJOR_VERSION < 3 if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { #else if (unlikely(!PyLong_CheckExact(res))) { #endif return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); } } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "an integer is required"); } return res; } static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { Py_ssize_t ival; PyObject *x; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_CheckExact(b))) { if (sizeof(Py_ssize_t) >= sizeof(long)) return PyInt_AS_LONG(b); else return PyInt_AsSsize_t(b); } #endif if (likely(PyLong_CheckExact(b))) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)b)->ob_digit; const Py_ssize_t size = Py_SIZE(b); if (likely(__Pyx_sst_abs(size) <= 1)) { ival = likely(size) ? digits[0] : 0; if (size == -1) ival = -ival; return ival; } else { switch (size) { case 2: if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case -2: if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case 3: if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case -3: if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case 4: if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case -4: if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; } } #endif return PyLong_AsSsize_t(b); } x = PyNumber_Index(b); if (!x) return -1; ival = PyInt_AsSsize_t(x); Py_DECREF(x); return ival; } static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); } static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { return PyInt_FromSize_t(ival); } #endif /* Py_PYTHON_H */ photutils-0.7.2/photutils/geometry/circular_overlap.pyx0000644000214200020070000002025513563423715025737 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst #cython: language_level=3 """ The functions defined here allow one to determine the exact area of overlap of a rectangle and a circle (written by Thomas Robitaille). """ import numpy as np cimport numpy as np __all__ = ['circular_overlap_grid'] cdef extern from "math.h": double asin(double x) double sin(double x) double sqrt(double x) DTYPE = np.float64 ctypedef np.float64_t DTYPE_t # NOTE: Here we need to make sure we use cimport to import the C functions from # core (since these were defined with cdef). This also requires the core.pxd # file to exist with the function signatures. from .core cimport area_arc, area_triangle, floor_sqrt def circular_overlap_grid(double xmin, double xmax, double ymin, double ymax, int nx, int ny, double r, int use_exact, int subpixels): """ circular_overlap_grid(xmin, xmax, ymin, ymax, nx, ny, r, use_exact, subpixels) Area of overlap between a circle and a pixel grid. The circle is centered on the origin. Parameters ---------- xmin, xmax, ymin, ymax : float Extent of the grid in the x and y direction. nx, ny : int Grid dimensions. r : float The radius of the circle. use_exact : 0 or 1 If ``1`` calculates exact overlap, if ``0`` uses ``subpixel`` number of subpixels to calculate the overlap. subpixels : int Each pixel resampled by this factor in each dimension, thus each pixel is divided into ``subpixels ** 2`` subpixels. Returns ------- frac : `~numpy.ndarray` (float) 2-d array of shape (ny, nx) giving the fraction of the overlap. """ cdef unsigned int i, j cdef double x, y, dx, dy, d, pixel_radius cdef double bxmin, bxmax, bymin, bymax cdef double pxmin, pxcen, pxmax, pymin, pycen, pymax # Define output array cdef np.ndarray[DTYPE_t, ndim=2] frac = np.zeros([ny, nx], dtype=DTYPE) # Find the width of each element in x and y dx = (xmax - xmin) / nx dy = (ymax - ymin) / ny # Find the radius of a single pixel pixel_radius = 0.5 * sqrt(dx * dx + dy * dy) # Define bounding box bxmin = -r - 0.5 * dx bxmax = +r + 0.5 * dx bymin = -r - 0.5 * dy bymax = +r + 0.5 * dy for i in range(nx): pxmin = xmin + i * dx # lower end of pixel pxcen = pxmin + dx * 0.5 pxmax = pxmin + dx # upper end of pixel if pxmax > bxmin and pxmin < bxmax: for j in range(ny): pymin = ymin + j * dy pycen = pymin + dy * 0.5 pymax = pymin + dy if pymax > bymin and pymin < bymax: # Distance from circle center to pixel center. d = sqrt(pxcen * pxcen + pycen * pycen) # If pixel center is "well within" circle, count full # pixel. if d < r - pixel_radius: frac[j, i] = 1. # If pixel center is "close" to circle border, find # overlap. elif d < r + pixel_radius: # Either do exact calculation or use subpixel # sampling: if use_exact: frac[j, i] = circular_overlap_single_exact( pxmin, pymin, pxmax, pymax, r) / (dx * dy) else: frac[j, i] = circular_overlap_single_subpixel( pxmin, pymin, pxmax, pymax, r, subpixels) # Otherwise, it is fully outside circle. # No action needed. return frac # NOTE: The following two functions use cdef because they are not # intended to be called from the Python code. Using def makes them # callable from outside, but also slower. In any case, these aren't useful # to call from outside because they only operate on a single pixel. cdef double circular_overlap_single_subpixel(double x0, double y0, double x1, double y1, double r, int subpixels): """Return the fraction of overlap between a circle and a single pixel with given extent, using a sub-pixel sampling method.""" cdef unsigned int i, j cdef double x, y, dx, dy, r_squared cdef double frac = 0. # Accumulator. dx = (x1 - x0) / subpixels dy = (y1 - y0) / subpixels r_squared = r ** 2 x = x0 - 0.5 * dx for i in range(subpixels): x += dx y = y0 - 0.5 * dy for j in range(subpixels): y += dy if x * x + y * y < r_squared: frac += 1. return frac / (subpixels * subpixels) cdef double circular_overlap_single_exact(double xmin, double ymin, double xmax, double ymax, double r): """ Area of overlap of a rectangle and a circle """ if 0. <= xmin: if 0. <= ymin: return circular_overlap_core(xmin, ymin, xmax, ymax, r) elif 0. >= ymax: return circular_overlap_core(-ymax, xmin, -ymin, xmax, r) else: return circular_overlap_single_exact(xmin, ymin, xmax, 0., r) \ + circular_overlap_single_exact(xmin, 0., xmax, ymax, r) elif 0. >= xmax: if 0. <= ymin: return circular_overlap_core(-xmax, ymin, -xmin, ymax, r) elif 0. >= ymax: return circular_overlap_core(-xmax, -ymax, -xmin, -ymin, r) else: return circular_overlap_single_exact(xmin, ymin, xmax, 0., r) \ + circular_overlap_single_exact(xmin, 0., xmax, ymax, r) else: if 0. <= ymin: return circular_overlap_single_exact(xmin, ymin, 0., ymax, r) \ + circular_overlap_single_exact(0., ymin, xmax, ymax, r) if 0. >= ymax: return circular_overlap_single_exact(xmin, ymin, 0., ymax, r) \ + circular_overlap_single_exact(0., ymin, xmax, ymax, r) else: return circular_overlap_single_exact(xmin, ymin, 0., 0., r) \ + circular_overlap_single_exact(0., ymin, xmax, 0., r) \ + circular_overlap_single_exact(xmin, 0., 0., ymax, r) \ + circular_overlap_single_exact(0., 0., xmax, ymax, r) cdef double circular_overlap_core(double xmin, double ymin, double xmax, double ymax, double r): """ Assumes that the center of the circle is <= xmin, ymin (can always modify input to conform to this). """ cdef double area, d1, d2, x1, x2, y1, y2 if xmin * xmin + ymin * ymin > r * r: area = 0. elif xmax * xmax + ymax * ymax < r * r: area = (xmax - xmin) * (ymax - ymin) else: area = 0. d1 = floor_sqrt(xmax * xmax + ymin * ymin) d2 = floor_sqrt(xmin * xmin + ymax * ymax) if d1 < r and d2 < r: x1, y1 = floor_sqrt(r * r - ymax * ymax), ymax x2, y2 = xmax, floor_sqrt(r * r - xmax * xmax) area = ((xmax - xmin) * (ymax - ymin) - area_triangle(x1, y1, x2, y2, xmax, ymax) + area_arc(x1, y1, x2, y2, r)) elif d1 < r: x1, y1 = xmin, floor_sqrt(r * r - xmin * xmin) x2, y2 = xmax, floor_sqrt(r * r - xmax * xmax) area = (area_arc(x1, y1, x2, y2, r) + area_triangle(x1, y1, x1, ymin, xmax, ymin) + area_triangle(x1, y1, x2, ymin, x2, y2)) elif d2 < r: x1, y1 = floor_sqrt(r * r - ymin * ymin), ymin x2, y2 = floor_sqrt(r * r - ymax * ymax), ymax area = (area_arc(x1, y1, x2, y2, r) + area_triangle(x1, y1, xmin, y1, xmin, ymax) + area_triangle(x1, y1, xmin, y2, x2, y2)) else: x1, y1 = floor_sqrt(r * r - ymin * ymin), ymin x2, y2 = xmin, floor_sqrt(r * r - xmin * xmin) area = (area_arc(x1, y1, x2, y2, r) + area_triangle(x1, y1, x2, y2, xmin, ymin)) return area photutils-0.7.2/photutils/geometry/core.c0000644000214200020070000133761713573510270022745 0ustar lbradleySTSCI\science00000000000000/* Generated by Cython 0.29.14 */ #define PY_SSIZE_T_CLEAN #include "Python.h" #ifndef Py_PYTHON_H #error Python headers needed to compile C extensions, please install development version of Python. #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) #error Cython requires Python 2.6+ or Python 3.3+. #else #define CYTHON_ABI "0_29_14" #define CYTHON_HEX_VERSION 0x001D0EF0 #define CYTHON_FUTURE_DIVISION 1 #include #ifndef offsetof #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) #endif #if !defined(WIN32) && !defined(MS_WINDOWS) #ifndef __stdcall #define __stdcall #endif #ifndef __cdecl #define __cdecl #endif #ifndef __fastcall #define __fastcall #endif #endif #ifndef DL_IMPORT #define DL_IMPORT(t) t #endif #ifndef DL_EXPORT #define DL_EXPORT(t) t #endif #define __PYX_COMMA , #ifndef HAVE_LONG_LONG #if PY_VERSION_HEX >= 0x02070000 #define HAVE_LONG_LONG #endif #endif #ifndef PY_LONG_LONG #define PY_LONG_LONG LONG_LONG #endif #ifndef Py_HUGE_VAL #define Py_HUGE_VAL HUGE_VAL #endif #ifdef PYPY_VERSION #define CYTHON_COMPILING_IN_PYPY 1 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 0 #undef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 0 #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #if PY_VERSION_HEX < 0x03050000 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #elif !defined(CYTHON_USE_ASYNC_SLOTS) #define CYTHON_USE_ASYNC_SLOTS 1 #endif #undef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 0 #undef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 0 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #undef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 1 #undef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 0 #undef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 0 #undef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 0 #undef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 0 #undef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 0 #undef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE 0 #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #elif defined(PYSTON_VERSION) #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 1 #define CYTHON_COMPILING_IN_CPYTHON 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #undef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 0 #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #ifndef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 0 #endif #ifndef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 1 #endif #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif #undef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 0 #undef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 0 #undef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 0 #undef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE 0 #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #else #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 1 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif #if PY_VERSION_HEX < 0x02070000 #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) #define CYTHON_USE_PYTYPE_LOOKUP 1 #endif #if PY_MAJOR_VERSION < 3 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #elif !defined(CYTHON_USE_ASYNC_SLOTS) #define CYTHON_USE_ASYNC_SLOTS 1 #endif #if PY_VERSION_HEX < 0x02070000 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #elif !defined(CYTHON_USE_PYLONG_INTERNALS) #define CYTHON_USE_PYLONG_INTERNALS 1 #endif #ifndef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 1 #endif #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif #if PY_VERSION_HEX < 0x030300F0 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #elif !defined(CYTHON_USE_UNICODE_WRITER) #define CYTHON_USE_UNICODE_WRITER 1 #endif #ifndef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 0 #endif #ifndef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 1 #endif #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif #ifndef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 1 #endif #ifndef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 1 #endif #ifndef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) #endif #ifndef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) #endif #ifndef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) #endif #ifndef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) #endif #endif #if !defined(CYTHON_FAST_PYCCALL) #define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) #endif #if CYTHON_USE_PYLONG_INTERNALS #include "longintrepr.h" #undef SHIFT #undef BASE #undef MASK #ifdef SIZEOF_VOID_P enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; #endif #endif #ifndef __has_attribute #define __has_attribute(x) 0 #endif #ifndef __has_cpp_attribute #define __has_cpp_attribute(x) 0 #endif #ifndef CYTHON_RESTRICT #if defined(__GNUC__) #define CYTHON_RESTRICT __restrict__ #elif defined(_MSC_VER) && _MSC_VER >= 1400 #define CYTHON_RESTRICT __restrict #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define CYTHON_RESTRICT restrict #else #define CYTHON_RESTRICT #endif #endif #ifndef CYTHON_UNUSED # if defined(__GNUC__) # if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) # define CYTHON_UNUSED __attribute__ ((__unused__)) # else # define CYTHON_UNUSED # endif # elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) # define CYTHON_UNUSED __attribute__ ((__unused__)) # else # define CYTHON_UNUSED # endif #endif #ifndef CYTHON_MAYBE_UNUSED_VAR # if defined(__cplusplus) template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } # else # define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) # endif #endif #ifndef CYTHON_NCP_UNUSED # if CYTHON_COMPILING_IN_CPYTHON # define CYTHON_NCP_UNUSED # else # define CYTHON_NCP_UNUSED CYTHON_UNUSED # endif #endif #define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) #ifdef _MSC_VER #ifndef _MSC_STDINT_H_ #if _MSC_VER < 1300 typedef unsigned char uint8_t; typedef unsigned int uint32_t; #else typedef unsigned __int8 uint8_t; typedef unsigned __int32 uint32_t; #endif #endif #else #include #endif #ifndef CYTHON_FALLTHROUGH #if defined(__cplusplus) && __cplusplus >= 201103L #if __has_cpp_attribute(fallthrough) #define CYTHON_FALLTHROUGH [[fallthrough]] #elif __has_cpp_attribute(clang::fallthrough) #define CYTHON_FALLTHROUGH [[clang::fallthrough]] #elif __has_cpp_attribute(gnu::fallthrough) #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] #endif #endif #ifndef CYTHON_FALLTHROUGH #if __has_attribute(fallthrough) #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) #else #define CYTHON_FALLTHROUGH #endif #endif #if defined(__clang__ ) && defined(__apple_build_version__) #if __apple_build_version__ < 7000000 #undef CYTHON_FALLTHROUGH #define CYTHON_FALLTHROUGH #endif #endif #endif #ifndef CYTHON_INLINE #if defined(__clang__) #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) #elif defined(__GNUC__) #define CYTHON_INLINE __inline__ #elif defined(_MSC_VER) #define CYTHON_INLINE __inline #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define CYTHON_INLINE inline #else #define CYTHON_INLINE #endif #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) #define Py_OptimizeFlag 0 #endif #define __PYX_BUILD_PY_SSIZE_T "n" #define CYTHON_FORMAT_SSIZE_T "z" #if PY_MAJOR_VERSION < 3 #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #define __Pyx_DefaultClassType PyClass_Type #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" #if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #else #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #endif #define __Pyx_DefaultClassType PyType_Type #endif #ifndef Py_TPFLAGS_CHECKTYPES #define Py_TPFLAGS_CHECKTYPES 0 #endif #ifndef Py_TPFLAGS_HAVE_INDEX #define Py_TPFLAGS_HAVE_INDEX 0 #endif #ifndef Py_TPFLAGS_HAVE_NEWBUFFER #define Py_TPFLAGS_HAVE_NEWBUFFER 0 #endif #ifndef Py_TPFLAGS_HAVE_FINALIZE #define Py_TPFLAGS_HAVE_FINALIZE 0 #endif #ifndef METH_STACKLESS #define METH_STACKLESS 0 #endif #if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) #ifndef METH_FASTCALL #define METH_FASTCALL 0x80 #endif typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); #else #define __Pyx_PyCFunctionFast _PyCFunctionFast #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords #endif #if CYTHON_FAST_PYCCALL #define __Pyx_PyFastCFunction_Check(func)\ ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) #else #define __Pyx_PyFastCFunction_Check(func) 0 #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) #define PyObject_Malloc(s) PyMem_Malloc(s) #define PyObject_Free(p) PyMem_Free(p) #define PyObject_Realloc(p) PyMem_Realloc(p) #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 #define PyMem_RawMalloc(n) PyMem_Malloc(n) #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) #define PyMem_RawFree(p) PyMem_Free(p) #endif #if CYTHON_COMPILING_IN_PYSTON #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) #else #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) #endif #if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 #define __Pyx_PyThreadState_Current PyThreadState_GET() #elif PY_VERSION_HEX >= 0x03060000 #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() #elif PY_VERSION_HEX >= 0x03000000 #define __Pyx_PyThreadState_Current PyThreadState_GET() #else #define __Pyx_PyThreadState_Current _PyThreadState_Current #endif #if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) #include "pythread.h" #define Py_tss_NEEDS_INIT 0 typedef int Py_tss_t; static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { *key = PyThread_create_key(); return 0; } static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); *key = Py_tss_NEEDS_INIT; return key; } static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { PyObject_Free(key); } static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { return *key != Py_tss_NEEDS_INIT; } static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { PyThread_delete_key(*key); *key = Py_tss_NEEDS_INIT; } static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { return PyThread_set_key_value(*key, value); } static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { return PyThread_get_key_value(*key); } #endif #if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) #define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) #else #define __Pyx_PyDict_NewPresized(n) PyDict_New() #endif #if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) #else #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS #define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) #else #define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) #endif #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) #define CYTHON_PEP393_ENABLED 1 #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ 0 : _PyUnicode_Ready((PyObject *)(op))) #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) #else #define CYTHON_PEP393_ENABLED 0 #define PyUnicode_1BYTE_KIND 1 #define PyUnicode_2BYTE_KIND 2 #define PyUnicode_4BYTE_KIND 4 #define __Pyx_PyUnicode_READY(op) (0) #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) #endif #if CYTHON_COMPILING_IN_PYPY #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) #else #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) #endif #define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) #define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) #else #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) #endif #if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) #define PyObject_ASCII(o) PyObject_Repr(o) #endif #if PY_MAJOR_VERSION >= 3 #define PyBaseString_Type PyUnicode_Type #define PyStringObject PyUnicodeObject #define PyString_Type PyUnicode_Type #define PyString_Check PyUnicode_Check #define PyString_CheckExact PyUnicode_CheckExact #define PyObject_Unicode PyObject_Str #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) #else #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) #endif #ifndef PySet_CheckExact #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) #endif #if CYTHON_ASSUME_SAFE_MACROS #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) #else #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) #endif #if PY_MAJOR_VERSION >= 3 #define PyIntObject PyLongObject #define PyInt_Type PyLong_Type #define PyInt_Check(op) PyLong_Check(op) #define PyInt_CheckExact(op) PyLong_CheckExact(op) #define PyInt_FromString PyLong_FromString #define PyInt_FromUnicode PyLong_FromUnicode #define PyInt_FromLong PyLong_FromLong #define PyInt_FromSize_t PyLong_FromSize_t #define PyInt_FromSsize_t PyLong_FromSsize_t #define PyInt_AsLong PyLong_AsLong #define PyInt_AS_LONG PyLong_AS_LONG #define PyInt_AsSsize_t PyLong_AsSsize_t #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask #define PyNumber_Int PyNumber_Long #endif #if PY_MAJOR_VERSION >= 3 #define PyBoolObject PyLongObject #endif #if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY #ifndef PyUnicode_InternFromString #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) #endif #endif #if PY_VERSION_HEX < 0x030200A4 typedef long Py_hash_t; #define __Pyx_PyInt_FromHash_t PyInt_FromLong #define __Pyx_PyInt_AsHash_t PyInt_AsLong #else #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : (Py_INCREF(func), func)) #else #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) #endif #if CYTHON_USE_ASYNC_SLOTS #if PY_VERSION_HEX >= 0x030500B1 #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) #else #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) #endif #else #define __Pyx_PyType_AsAsync(obj) NULL #endif #ifndef __Pyx_PyAsyncMethodsStruct typedef struct { unaryfunc am_await; unaryfunc am_aiter; unaryfunc am_anext; } __Pyx_PyAsyncMethodsStruct; #endif #if defined(WIN32) || defined(MS_WINDOWS) #define _USE_MATH_DEFINES #endif #include #ifdef NAN #define __PYX_NAN() ((float) NAN) #else static CYTHON_INLINE float __PYX_NAN() { float value; memset(&value, 0xFF, sizeof(value)); return value; } #endif #if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) #define __Pyx_truncl trunc #else #define __Pyx_truncl truncl #endif #define __PYX_ERR(f_index, lineno, Ln_error) \ { \ __pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \ } #ifndef __PYX_EXTERN_C #ifdef __cplusplus #define __PYX_EXTERN_C extern "C" #else #define __PYX_EXTERN_C extern #endif #endif #define __PYX_HAVE__photutils__geometry__core #define __PYX_HAVE_API__photutils__geometry__core /* Early includes */ #include #include #include "numpy/arrayobject.h" #include "numpy/ufuncobject.h" #include "math.h" #include "pythread.h" #ifdef _OPENMP #include #endif /* _OPENMP */ #if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) #define CYTHON_WITHOUT_ASSERTIONS #endif typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; #define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 #define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 #define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) #define __PYX_DEFAULT_STRING_ENCODING "" #define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString #define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize #define __Pyx_uchar_cast(c) ((unsigned char)c) #define __Pyx_long_cast(x) ((long)x) #define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ (sizeof(type) < sizeof(Py_ssize_t)) ||\ (sizeof(type) > sizeof(Py_ssize_t) &&\ likely(v < (type)PY_SSIZE_T_MAX ||\ v == (type)PY_SSIZE_T_MAX) &&\ (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ v == (type)PY_SSIZE_T_MIN))) ||\ (sizeof(type) == sizeof(Py_ssize_t) &&\ (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ v == (type)PY_SSIZE_T_MAX))) ) static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { return (size_t) i < (size_t) limit; } #if defined (__cplusplus) && __cplusplus >= 201103L #include #define __Pyx_sst_abs(value) std::abs(value) #elif SIZEOF_INT >= SIZEOF_SIZE_T #define __Pyx_sst_abs(value) abs(value) #elif SIZEOF_LONG >= SIZEOF_SIZE_T #define __Pyx_sst_abs(value) labs(value) #elif defined (_MSC_VER) #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define __Pyx_sst_abs(value) llabs(value) #elif defined (__GNUC__) #define __Pyx_sst_abs(value) __builtin_llabs(value) #else #define __Pyx_sst_abs(value) ((value<0) ? -value : value) #endif static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); #define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) #define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) #define __Pyx_PyBytes_FromString PyBytes_FromString #define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); #if PY_MAJOR_VERSION < 3 #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize #else #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize #endif #define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) #define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) #define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) #define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) #define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) #define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { const Py_UNICODE *u_end = u; while (*u_end++) ; return (size_t)(u_end - u - 1); } #define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) #define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode #define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode #define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) #define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); #define __Pyx_PySequence_Tuple(obj)\ (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); #if CYTHON_ASSUME_SAFE_MACROS #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) #else #define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) #endif #define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) #else #define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) #endif #define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII static int __Pyx_sys_getdefaultencoding_not_ascii; static int __Pyx_init_sys_getdefaultencoding_params(void) { PyObject* sys; PyObject* default_encoding = NULL; PyObject* ascii_chars_u = NULL; PyObject* ascii_chars_b = NULL; const char* default_encoding_c; sys = PyImport_ImportModule("sys"); if (!sys) goto bad; default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); Py_DECREF(sys); if (!default_encoding) goto bad; default_encoding_c = PyBytes_AsString(default_encoding); if (!default_encoding_c) goto bad; if (strcmp(default_encoding_c, "ascii") == 0) { __Pyx_sys_getdefaultencoding_not_ascii = 0; } else { char ascii_chars[128]; int c; for (c = 0; c < 128; c++) { ascii_chars[c] = c; } __Pyx_sys_getdefaultencoding_not_ascii = 1; ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); if (!ascii_chars_u) goto bad; ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { PyErr_Format( PyExc_ValueError, "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", default_encoding_c); goto bad; } Py_DECREF(ascii_chars_u); Py_DECREF(ascii_chars_b); } Py_DECREF(default_encoding); return 0; bad: Py_XDECREF(default_encoding); Py_XDECREF(ascii_chars_u); Py_XDECREF(ascii_chars_b); return -1; } #endif #if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) #else #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) #if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT static char* __PYX_DEFAULT_STRING_ENCODING; static int __Pyx_init_sys_getdefaultencoding_params(void) { PyObject* sys; PyObject* default_encoding = NULL; char* default_encoding_c; sys = PyImport_ImportModule("sys"); if (!sys) goto bad; default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); Py_DECREF(sys); if (!default_encoding) goto bad; default_encoding_c = PyBytes_AsString(default_encoding); if (!default_encoding_c) goto bad; __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); Py_DECREF(default_encoding); return 0; bad: Py_XDECREF(default_encoding); return -1; } #endif #endif /* Test for GCC > 2.95 */ #if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #else /* !__GNUC__ or GCC < 2.95 */ #define likely(x) (x) #define unlikely(x) (x) #endif /* __GNUC__ */ static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } static PyObject *__pyx_m = NULL; static PyObject *__pyx_d; static PyObject *__pyx_b; static PyObject *__pyx_cython_runtime = NULL; static PyObject *__pyx_empty_tuple; static PyObject *__pyx_empty_bytes; static PyObject *__pyx_empty_unicode; static int __pyx_lineno; static int __pyx_clineno = 0; static const char * __pyx_cfilenm= __FILE__; static const char *__pyx_filename; /* Header.proto */ #if !defined(CYTHON_CCOMPLEX) #if defined(__cplusplus) #define CYTHON_CCOMPLEX 1 #elif defined(_Complex_I) #define CYTHON_CCOMPLEX 1 #else #define CYTHON_CCOMPLEX 0 #endif #endif #if CYTHON_CCOMPLEX #ifdef __cplusplus #include #else #include #endif #endif #if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__) #undef _Complex_I #define _Complex_I 1.0fj #endif static const char *__pyx_f[] = { "photutils/geometry/core.pyx", "__init__.pxd", "type.pxd", "bool.pxd", "complex.pxd", }; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":776 * # in Cython to enable them only on the right systems. * * ctypedef npy_int8 int8_t # <<<<<<<<<<<<<< * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t */ typedef npy_int8 __pyx_t_5numpy_int8_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":777 * * ctypedef npy_int8 int8_t * ctypedef npy_int16 int16_t # <<<<<<<<<<<<<< * ctypedef npy_int32 int32_t * ctypedef npy_int64 int64_t */ typedef npy_int16 __pyx_t_5numpy_int16_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":778 * ctypedef npy_int8 int8_t * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t # <<<<<<<<<<<<<< * ctypedef npy_int64 int64_t * #ctypedef npy_int96 int96_t */ typedef npy_int32 __pyx_t_5numpy_int32_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":779 * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t * ctypedef npy_int64 int64_t # <<<<<<<<<<<<<< * #ctypedef npy_int96 int96_t * #ctypedef npy_int128 int128_t */ typedef npy_int64 __pyx_t_5numpy_int64_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":783 * #ctypedef npy_int128 int128_t * * ctypedef npy_uint8 uint8_t # <<<<<<<<<<<<<< * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t */ typedef npy_uint8 __pyx_t_5numpy_uint8_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":784 * * ctypedef npy_uint8 uint8_t * ctypedef npy_uint16 uint16_t # <<<<<<<<<<<<<< * ctypedef npy_uint32 uint32_t * ctypedef npy_uint64 uint64_t */ typedef npy_uint16 __pyx_t_5numpy_uint16_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":785 * ctypedef npy_uint8 uint8_t * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t # <<<<<<<<<<<<<< * ctypedef npy_uint64 uint64_t * #ctypedef npy_uint96 uint96_t */ typedef npy_uint32 __pyx_t_5numpy_uint32_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":786 * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t * ctypedef npy_uint64 uint64_t # <<<<<<<<<<<<<< * #ctypedef npy_uint96 uint96_t * #ctypedef npy_uint128 uint128_t */ typedef npy_uint64 __pyx_t_5numpy_uint64_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":790 * #ctypedef npy_uint128 uint128_t * * ctypedef npy_float32 float32_t # <<<<<<<<<<<<<< * ctypedef npy_float64 float64_t * #ctypedef npy_float80 float80_t */ typedef npy_float32 __pyx_t_5numpy_float32_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":791 * * ctypedef npy_float32 float32_t * ctypedef npy_float64 float64_t # <<<<<<<<<<<<<< * #ctypedef npy_float80 float80_t * #ctypedef npy_float128 float128_t */ typedef npy_float64 __pyx_t_5numpy_float64_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":800 * # The int types are mapped a bit surprising -- * # numpy.int corresponds to 'l' and numpy.long to 'q' * ctypedef npy_long int_t # <<<<<<<<<<<<<< * ctypedef npy_longlong long_t * ctypedef npy_longlong longlong_t */ typedef npy_long __pyx_t_5numpy_int_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":801 * # numpy.int corresponds to 'l' and numpy.long to 'q' * ctypedef npy_long int_t * ctypedef npy_longlong long_t # <<<<<<<<<<<<<< * ctypedef npy_longlong longlong_t * */ typedef npy_longlong __pyx_t_5numpy_long_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":802 * ctypedef npy_long int_t * ctypedef npy_longlong long_t * ctypedef npy_longlong longlong_t # <<<<<<<<<<<<<< * * ctypedef npy_ulong uint_t */ typedef npy_longlong __pyx_t_5numpy_longlong_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":804 * ctypedef npy_longlong longlong_t * * ctypedef npy_ulong uint_t # <<<<<<<<<<<<<< * ctypedef npy_ulonglong ulong_t * ctypedef npy_ulonglong ulonglong_t */ typedef npy_ulong __pyx_t_5numpy_uint_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":805 * * ctypedef npy_ulong uint_t * ctypedef npy_ulonglong ulong_t # <<<<<<<<<<<<<< * ctypedef npy_ulonglong ulonglong_t * */ typedef npy_ulonglong __pyx_t_5numpy_ulong_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":806 * ctypedef npy_ulong uint_t * ctypedef npy_ulonglong ulong_t * ctypedef npy_ulonglong ulonglong_t # <<<<<<<<<<<<<< * * ctypedef npy_intp intp_t */ typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":808 * ctypedef npy_ulonglong ulonglong_t * * ctypedef npy_intp intp_t # <<<<<<<<<<<<<< * ctypedef npy_uintp uintp_t * */ typedef npy_intp __pyx_t_5numpy_intp_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":809 * * ctypedef npy_intp intp_t * ctypedef npy_uintp uintp_t # <<<<<<<<<<<<<< * * ctypedef npy_double float_t */ typedef npy_uintp __pyx_t_5numpy_uintp_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":811 * ctypedef npy_uintp uintp_t * * ctypedef npy_double float_t # <<<<<<<<<<<<<< * ctypedef npy_double double_t * ctypedef npy_longdouble longdouble_t */ typedef npy_double __pyx_t_5numpy_float_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":812 * * ctypedef npy_double float_t * ctypedef npy_double double_t # <<<<<<<<<<<<<< * ctypedef npy_longdouble longdouble_t * */ typedef npy_double __pyx_t_5numpy_double_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":813 * ctypedef npy_double float_t * ctypedef npy_double double_t * ctypedef npy_longdouble longdouble_t # <<<<<<<<<<<<<< * * ctypedef npy_cfloat cfloat_t */ typedef npy_longdouble __pyx_t_5numpy_longdouble_t; /* "photutils/geometry/core.pyx":24 * * DTYPE = np.float64 * ctypedef np.float64_t DTYPE_t # <<<<<<<<<<<<<< * * cimport cython */ typedef __pyx_t_5numpy_float64_t __pyx_t_9photutils_8geometry_4core_DTYPE_t; /* Declarations.proto */ #if CYTHON_CCOMPLEX #ifdef __cplusplus typedef ::std::complex< float > __pyx_t_float_complex; #else typedef float _Complex __pyx_t_float_complex; #endif #else typedef struct { float real, imag; } __pyx_t_float_complex; #endif static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float); /* Declarations.proto */ #if CYTHON_CCOMPLEX #ifdef __cplusplus typedef ::std::complex< double > __pyx_t_double_complex; #else typedef double _Complex __pyx_t_double_complex; #endif #else typedef struct { double real, imag; } __pyx_t_double_complex; #endif static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double); /*--- Type declarations ---*/ /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":815 * ctypedef npy_longdouble longdouble_t * * ctypedef npy_cfloat cfloat_t # <<<<<<<<<<<<<< * ctypedef npy_cdouble cdouble_t * ctypedef npy_clongdouble clongdouble_t */ typedef npy_cfloat __pyx_t_5numpy_cfloat_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":816 * * ctypedef npy_cfloat cfloat_t * ctypedef npy_cdouble cdouble_t # <<<<<<<<<<<<<< * ctypedef npy_clongdouble clongdouble_t * */ typedef npy_cdouble __pyx_t_5numpy_cdouble_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":817 * ctypedef npy_cfloat cfloat_t * ctypedef npy_cdouble cdouble_t * ctypedef npy_clongdouble clongdouble_t # <<<<<<<<<<<<<< * * ctypedef npy_cdouble complex_t */ typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":819 * ctypedef npy_clongdouble clongdouble_t * * ctypedef npy_cdouble complex_t # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew1(a): */ typedef npy_cdouble __pyx_t_5numpy_complex_t; struct __pyx_t_9photutils_8geometry_4core_point; typedef struct __pyx_t_9photutils_8geometry_4core_point __pyx_t_9photutils_8geometry_4core_point; struct __pyx_t_9photutils_8geometry_4core_intersections; typedef struct __pyx_t_9photutils_8geometry_4core_intersections __pyx_t_9photutils_8geometry_4core_intersections; /* "photutils/geometry/core.pyx":29 * * * ctypedef struct point: # <<<<<<<<<<<<<< * double x * double y */ struct __pyx_t_9photutils_8geometry_4core_point { double x; double y; }; /* "photutils/geometry/core.pyx":34 * * * ctypedef struct intersections: # <<<<<<<<<<<<<< * point p1 * point p2 */ struct __pyx_t_9photutils_8geometry_4core_intersections { __pyx_t_9photutils_8geometry_4core_point p1; __pyx_t_9photutils_8geometry_4core_point p2; }; /* --- Runtime support code (head) --- */ /* Refnanny.proto */ #ifndef CYTHON_REFNANNY #define CYTHON_REFNANNY 0 #endif #if CYTHON_REFNANNY typedef struct { void (*INCREF)(void*, PyObject*, int); void (*DECREF)(void*, PyObject*, int); void (*GOTREF)(void*, PyObject*, int); void (*GIVEREF)(void*, PyObject*, int); void* (*SetupContext)(const char*, int, const char*); void (*FinishContext)(void**); } __Pyx_RefNannyAPIStruct; static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; #ifdef WITH_THREAD #define __Pyx_RefNannySetupContext(name, acquire_gil)\ if (acquire_gil) {\ PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ PyGILState_Release(__pyx_gilstate_save);\ } else {\ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ } #else #define __Pyx_RefNannySetupContext(name, acquire_gil)\ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) #endif #define __Pyx_RefNannyFinishContext()\ __Pyx_RefNanny->FinishContext(&__pyx_refnanny) #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) #else #define __Pyx_RefNannyDeclarations #define __Pyx_RefNannySetupContext(name, acquire_gil) #define __Pyx_RefNannyFinishContext() #define __Pyx_INCREF(r) Py_INCREF(r) #define __Pyx_DECREF(r) Py_DECREF(r) #define __Pyx_GOTREF(r) #define __Pyx_GIVEREF(r) #define __Pyx_XINCREF(r) Py_XINCREF(r) #define __Pyx_XDECREF(r) Py_XDECREF(r) #define __Pyx_XGOTREF(r) #define __Pyx_XGIVEREF(r) #endif #define __Pyx_XDECREF_SET(r, v) do {\ PyObject *tmp = (PyObject *) r;\ r = v; __Pyx_XDECREF(tmp);\ } while (0) #define __Pyx_DECREF_SET(r, v) do {\ PyObject *tmp = (PyObject *) r;\ r = v; __Pyx_DECREF(tmp);\ } while (0) #define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) #define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) /* PyThreadStateGet.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; #define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; #define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type #else #define __Pyx_PyThreadState_declare #define __Pyx_PyThreadState_assign #define __Pyx_PyErr_Occurred() PyErr_Occurred() #endif /* PyErrFetchRestore.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) #define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) #define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) #define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) #define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) #else #define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) #endif #else #define __Pyx_PyErr_Clear() PyErr_Clear() #define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) #define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) #define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) #define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) #endif /* WriteUnraisableException.proto */ static void __Pyx_WriteUnraisable(const char *name, int clineno, int lineno, const char *filename, int full_traceback, int nogil); /* None.proto */ static CYTHON_INLINE long __Pyx_mod_long(long, long); /* PyObjectGetAttrStr.proto */ #if CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); #else #define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) #endif /* GetBuiltinName.proto */ static PyObject *__Pyx_GetBuiltinName(PyObject *name); /* PyDictVersioning.proto */ #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS #define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) #define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) #define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ (version_var) = __PYX_GET_DICT_VERSION(dict);\ (cache_var) = (value); #define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ static PY_UINT64_T __pyx_dict_version = 0;\ static PyObject *__pyx_dict_cached_value = NULL;\ if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ (VAR) = __pyx_dict_cached_value;\ } else {\ (VAR) = __pyx_dict_cached_value = (LOOKUP);\ __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ }\ } static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); #else #define __PYX_GET_DICT_VERSION(dict) (0) #define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) #define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); #endif /* GetModuleGlobalName.proto */ #if CYTHON_USE_DICT_VERSIONS #define __Pyx_GetModuleGlobalName(var, name) {\ static PY_UINT64_T __pyx_dict_version = 0;\ static PyObject *__pyx_dict_cached_value = NULL;\ (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ } #define __Pyx_GetModuleGlobalNameUncached(var, name) {\ PY_UINT64_T __pyx_dict_version;\ PyObject *__pyx_dict_cached_value;\ (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ } static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); #else #define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) #define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); #endif /* PyObjectCall.proto */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); #else #define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) #endif /* RaiseException.proto */ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); /* ExtTypeTest.proto */ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /* PyCFunctionFastCall.proto */ #if CYTHON_FAST_PYCCALL static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); #else #define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) #endif /* PyFunctionFastCall.proto */ #if CYTHON_FAST_PYCALL #define __Pyx_PyFunction_FastCall(func, args, nargs)\ __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) #if 1 || PY_VERSION_HEX < 0x030600B1 static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); #else #define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) #endif #define __Pyx_BUILD_ASSERT_EXPR(cond)\ (sizeof(char [1 - 2*!(cond)]) - 1) #ifndef Py_MEMBER_SIZE #define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) #endif static size_t __pyx_pyframe_localsplus_offset = 0; #include "frameobject.h" #define __Pxy_PyFrame_Initialize_Offsets()\ ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) #define __Pyx_PyFrame_GetLocalsplus(frame)\ (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) #endif /* PyObjectCallMethO.proto */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); #endif /* PyObjectCallOneArg.proto */ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); /* DictGetItem.proto */ #if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key); #define __Pyx_PyObject_Dict_GetItem(obj, name)\ (likely(PyDict_CheckExact(obj)) ?\ __Pyx_PyDict_GetItem(obj, name) : PyObject_GetItem(obj, name)) #else #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key) #define __Pyx_PyObject_Dict_GetItem(obj, name) PyObject_GetItem(obj, name) #endif /* RaiseTooManyValuesToUnpack.proto */ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); /* RaiseNeedMoreValuesToUnpack.proto */ static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); /* RaiseNoneIterError.proto */ static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); /* GetTopmostException.proto */ #if CYTHON_USE_EXC_INFO_STACK static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); #endif /* SaveResetException.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave(__pyx_tstate, type, value, tb) static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); #define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset(__pyx_tstate, type, value, tb) static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); #else #define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) #define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) #endif /* PyErrExceptionMatches.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); #else #define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) #endif /* GetException.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); #else static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); #endif /* TypeImport.proto */ #ifndef __PYX_HAVE_RT_ImportType_proto #define __PYX_HAVE_RT_ImportType_proto enum __Pyx_ImportType_CheckSize { __Pyx_ImportType_CheckSize_Error = 0, __Pyx_ImportType_CheckSize_Warn = 1, __Pyx_ImportType_CheckSize_Ignore = 2 }; static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); #endif /* Import.proto */ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); /* CLineInTraceback.proto */ #ifdef CYTHON_CLINE_IN_TRACEBACK #define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) #else static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); #endif /* CodeObjectCache.proto */ typedef struct { PyCodeObject* code_object; int code_line; } __Pyx_CodeObjectCacheEntry; struct __Pyx_CodeObjectCache { int count; int max_count; __Pyx_CodeObjectCacheEntry* entries; }; static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); static PyCodeObject *__pyx_find_code_object(int code_line); static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); /* AddTraceback.proto */ static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename); /* RealImag.proto */ #if CYTHON_CCOMPLEX #ifdef __cplusplus #define __Pyx_CREAL(z) ((z).real()) #define __Pyx_CIMAG(z) ((z).imag()) #else #define __Pyx_CREAL(z) (__real__(z)) #define __Pyx_CIMAG(z) (__imag__(z)) #endif #else #define __Pyx_CREAL(z) ((z).real) #define __Pyx_CIMAG(z) ((z).imag) #endif #if defined(__cplusplus) && CYTHON_CCOMPLEX\ && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103) #define __Pyx_SET_CREAL(z,x) ((z).real(x)) #define __Pyx_SET_CIMAG(z,y) ((z).imag(y)) #else #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x) #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y) #endif /* Arithmetic.proto */ #if CYTHON_CCOMPLEX #define __Pyx_c_eq_float(a, b) ((a)==(b)) #define __Pyx_c_sum_float(a, b) ((a)+(b)) #define __Pyx_c_diff_float(a, b) ((a)-(b)) #define __Pyx_c_prod_float(a, b) ((a)*(b)) #define __Pyx_c_quot_float(a, b) ((a)/(b)) #define __Pyx_c_neg_float(a) (-(a)) #ifdef __cplusplus #define __Pyx_c_is_zero_float(z) ((z)==(float)0) #define __Pyx_c_conj_float(z) (::std::conj(z)) #if 1 #define __Pyx_c_abs_float(z) (::std::abs(z)) #define __Pyx_c_pow_float(a, b) (::std::pow(a, b)) #endif #else #define __Pyx_c_is_zero_float(z) ((z)==0) #define __Pyx_c_conj_float(z) (conjf(z)) #if 1 #define __Pyx_c_abs_float(z) (cabsf(z)) #define __Pyx_c_pow_float(a, b) (cpowf(a, b)) #endif #endif #else static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex); static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex); #if 1 static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex, __pyx_t_float_complex); #endif #endif /* Arithmetic.proto */ #if CYTHON_CCOMPLEX #define __Pyx_c_eq_double(a, b) ((a)==(b)) #define __Pyx_c_sum_double(a, b) ((a)+(b)) #define __Pyx_c_diff_double(a, b) ((a)-(b)) #define __Pyx_c_prod_double(a, b) ((a)*(b)) #define __Pyx_c_quot_double(a, b) ((a)/(b)) #define __Pyx_c_neg_double(a) (-(a)) #ifdef __cplusplus #define __Pyx_c_is_zero_double(z) ((z)==(double)0) #define __Pyx_c_conj_double(z) (::std::conj(z)) #if 1 #define __Pyx_c_abs_double(z) (::std::abs(z)) #define __Pyx_c_pow_double(a, b) (::std::pow(a, b)) #endif #else #define __Pyx_c_is_zero_double(z) ((z)==0) #define __Pyx_c_conj_double(z) (conj(z)) #if 1 #define __Pyx_c_abs_double(z) (cabs(z)) #define __Pyx_c_pow_double(a, b) (cpow(a, b)) #endif #endif #else static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex); static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex); #if 1 static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex, __pyx_t_double_complex); #endif #endif /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__NPY_TYPES(enum NPY_TYPES value); /* CIntFromPy.proto */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); /* CIntFromPy.proto */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); /* FastTypeChecks.proto */ #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); #else #define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) #define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) #define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) #endif #define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) /* CheckBinaryVersion.proto */ static int __Pyx_check_binary_version(void); /* FunctionExport.proto */ static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig); /* InitStrings.proto */ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /* Module declarations from 'cpython.buffer' */ /* Module declarations from 'libc.string' */ /* Module declarations from 'libc.stdio' */ /* Module declarations from '__builtin__' */ /* Module declarations from 'cpython.type' */ static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0; /* Module declarations from 'cpython.version' */ /* Module declarations from 'cpython.exc' */ /* Module declarations from 'cpython.module' */ /* Module declarations from 'cpython.mem' */ /* Module declarations from 'cpython.tuple' */ /* Module declarations from 'cpython.list' */ /* Module declarations from 'cpython.sequence' */ /* Module declarations from 'cpython.mapping' */ /* Module declarations from 'cpython.iterator' */ /* Module declarations from 'cpython.number' */ /* Module declarations from 'cpython.int' */ /* Module declarations from '__builtin__' */ /* Module declarations from 'cpython.bool' */ static PyTypeObject *__pyx_ptype_7cpython_4bool_bool = 0; /* Module declarations from 'cpython.long' */ /* Module declarations from 'cpython.float' */ /* Module declarations from '__builtin__' */ /* Module declarations from 'cpython.complex' */ static PyTypeObject *__pyx_ptype_7cpython_7complex_complex = 0; /* Module declarations from 'cpython.string' */ /* Module declarations from 'cpython.unicode' */ /* Module declarations from 'cpython.dict' */ /* Module declarations from 'cpython.instance' */ /* Module declarations from 'cpython.function' */ /* Module declarations from 'cpython.method' */ /* Module declarations from 'cpython.weakref' */ /* Module declarations from 'cpython.getargs' */ /* Module declarations from 'cpython.pythread' */ /* Module declarations from 'cpython.pystate' */ /* Module declarations from 'cpython.cobject' */ /* Module declarations from 'cpython.oldbuffer' */ /* Module declarations from 'cpython.set' */ /* Module declarations from 'cpython.bytes' */ /* Module declarations from 'cpython.pycapsule' */ /* Module declarations from 'cpython' */ /* Module declarations from 'cpython.object' */ /* Module declarations from 'cpython.ref' */ /* Module declarations from 'numpy' */ /* Module declarations from 'numpy' */ static PyTypeObject *__pyx_ptype_5numpy_dtype = 0; static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0; static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0; static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0; static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0; static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); /*proto*/ /* Module declarations from 'cython' */ /* Module declarations from 'photutils.geometry.core' */ static double __pyx_f_9photutils_8geometry_4core_distance(double, double, double, double); /*proto*/ static double __pyx_f_9photutils_8geometry_4core_area_triangle(double, double, double, double, double, double); /*proto*/ static double __pyx_f_9photutils_8geometry_4core_area_arc_unit(double, double, double, double); /*proto*/ static int __pyx_f_9photutils_8geometry_4core_in_triangle(double, double, double, double, double, double, double, double); /*proto*/ static double __pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle(double, double, double, double, double, double); /*proto*/ static __pyx_t_9photutils_8geometry_4core_intersections __pyx_f_9photutils_8geometry_4core_circle_line(double, double, double, double); /*proto*/ static __pyx_t_9photutils_8geometry_4core_point __pyx_f_9photutils_8geometry_4core_circle_segment_single2(double, double, double, double); /*proto*/ static __pyx_t_9photutils_8geometry_4core_intersections __pyx_f_9photutils_8geometry_4core_circle_segment(double, double, double, double); /*proto*/ #define __Pyx_MODULE_NAME "photutils.geometry.core" extern int __pyx_module_is_main_photutils__geometry__core; int __pyx_module_is_main_photutils__geometry__core = 0; /* Implementation of 'photutils.geometry.core' */ static PyObject *__pyx_builtin_ValueError; static PyObject *__pyx_builtin_range; static PyObject *__pyx_builtin_RuntimeError; static PyObject *__pyx_builtin_ImportError; static const char __pyx_k_np[] = "np"; static const char __pyx_k_pi[] = "pi"; static const char __pyx_k_all[] = "__all__"; static const char __pyx_k_main[] = "__main__"; static const char __pyx_k_name[] = "__name__"; static const char __pyx_k_test[] = "__test__"; static const char __pyx_k_DTYPE[] = "DTYPE"; static const char __pyx_k_numpy[] = "numpy"; static const char __pyx_k_range[] = "range"; static const char __pyx_k_import[] = "__import__"; static const char __pyx_k_float64[] = "float64"; static const char __pyx_k_ValueError[] = "ValueError"; static const char __pyx_k_ImportError[] = "ImportError"; static const char __pyx_k_RuntimeError[] = "RuntimeError"; static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; static const char __pyx_k_elliptical_overlap_grid[] = "elliptical_overlap_grid"; static const char __pyx_k_ndarray_is_not_C_contiguous[] = "ndarray is not C contiguous"; static const char __pyx_k_The_functions_here_are_the_core[] = "\nThe functions here are the core geometry functions.\n"; static const char __pyx_k_numpy_core_multiarray_failed_to[] = "numpy.core.multiarray failed to import"; static const char __pyx_k_unknown_dtype_code_in_numpy_pxd[] = "unknown dtype code in numpy.pxd (%d)"; static const char __pyx_k_ERROR_vertices_did_not_sort_corr[] = "ERROR: vertices did not sort correctly"; static const char __pyx_k_Format_string_allocated_too_shor[] = "Format string allocated too short, see comment in numpy.pxd"; static const char __pyx_k_Non_native_byte_order_not_suppor[] = "Non-native byte order not supported"; static const char __pyx_k_ndarray_is_not_Fortran_contiguou[] = "ndarray is not Fortran contiguous"; static const char __pyx_k_numpy_core_umath_failed_to_impor[] = "numpy.core.umath failed to import"; static const char __pyx_k_Format_string_allocated_too_shor_2[] = "Format string allocated too short."; static PyObject *__pyx_n_s_DTYPE; static PyObject *__pyx_kp_u_ERROR_vertices_did_not_sort_corr; static PyObject *__pyx_kp_u_Format_string_allocated_too_shor; static PyObject *__pyx_kp_u_Format_string_allocated_too_shor_2; static PyObject *__pyx_n_s_ImportError; static PyObject *__pyx_kp_u_Non_native_byte_order_not_suppor; static PyObject *__pyx_n_s_RuntimeError; static PyObject *__pyx_n_s_ValueError; static PyObject *__pyx_n_s_all; static PyObject *__pyx_n_s_cline_in_traceback; static PyObject *__pyx_n_u_elliptical_overlap_grid; static PyObject *__pyx_n_s_float64; static PyObject *__pyx_n_s_import; static PyObject *__pyx_n_s_main; static PyObject *__pyx_n_s_name; static PyObject *__pyx_kp_u_ndarray_is_not_C_contiguous; static PyObject *__pyx_kp_u_ndarray_is_not_Fortran_contiguou; static PyObject *__pyx_n_s_np; static PyObject *__pyx_n_s_numpy; static PyObject *__pyx_kp_u_numpy_core_multiarray_failed_to; static PyObject *__pyx_kp_u_numpy_core_umath_failed_to_impor; static PyObject *__pyx_n_s_pi; static PyObject *__pyx_n_s_range; static PyObject *__pyx_n_s_test; static PyObject *__pyx_kp_u_unknown_dtype_code_in_numpy_pxd; static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info); /* proto */ static PyObject *__pyx_tuple_; static PyObject *__pyx_tuple__2; static PyObject *__pyx_tuple__3; static PyObject *__pyx_tuple__4; static PyObject *__pyx_tuple__5; static PyObject *__pyx_tuple__6; static PyObject *__pyx_tuple__7; static PyObject *__pyx_tuple__8; /* Late includes */ /* "photutils/geometry/core.pyx":39 * * * cdef double floor_sqrt(double x): # <<<<<<<<<<<<<< * """ * In some of the geometrical functions, we have to take the sqrt of a number */ static double __pyx_f_9photutils_8geometry_4core_floor_sqrt(double __pyx_v_x) { double __pyx_r; __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("floor_sqrt", 0); /* "photutils/geometry/core.pyx":50 * to be positive on paper. * """ * if x > 0: # <<<<<<<<<<<<<< * return sqrt(x) * else: */ __pyx_t_1 = ((__pyx_v_x > 0.0) != 0); if (__pyx_t_1) { /* "photutils/geometry/core.pyx":51 * """ * if x > 0: * return sqrt(x) # <<<<<<<<<<<<<< * else: * return 0 */ __pyx_r = sqrt(__pyx_v_x); goto __pyx_L0; /* "photutils/geometry/core.pyx":50 * to be positive on paper. * """ * if x > 0: # <<<<<<<<<<<<<< * return sqrt(x) * else: */ } /* "photutils/geometry/core.pyx":53 * return sqrt(x) * else: * return 0 # <<<<<<<<<<<<<< * * # NOTE: The following two functions use cdef because they are not intended to be */ /*else*/ { __pyx_r = 0.0; goto __pyx_L0; } /* "photutils/geometry/core.pyx":39 * * * cdef double floor_sqrt(double x): # <<<<<<<<<<<<<< * """ * In some of the geometrical functions, we have to take the sqrt of a number */ /* function exit code */ __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/core.pyx":61 * * * cdef double distance(double x1, double y1, double x2, double y2): # <<<<<<<<<<<<<< * """ * Distance between two points in two dimensions. */ static double __pyx_f_9photutils_8geometry_4core_distance(double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2) { double __pyx_r; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("distance", 0); /* "photutils/geometry/core.pyx":78 * """ * * return sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) # <<<<<<<<<<<<<< * * */ __pyx_r = sqrt((pow((__pyx_v_x2 - __pyx_v_x1), 2.0) + pow((__pyx_v_y2 - __pyx_v_y1), 2.0))); goto __pyx_L0; /* "photutils/geometry/core.pyx":61 * * * cdef double distance(double x1, double y1, double x2, double y2): # <<<<<<<<<<<<<< * """ * Distance between two points in two dimensions. */ /* function exit code */ __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/core.pyx":81 * * * cdef double area_arc(double x1, double y1, double x2, double y2, double r): # <<<<<<<<<<<<<< * """ * Area of a circle arc with radius r between points (x1, y1) and (x2, y2). */ static double __pyx_f_9photutils_8geometry_4core_area_arc(double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2, double __pyx_v_r) { double __pyx_v_a; double __pyx_v_theta; double __pyx_r; __Pyx_RefNannyDeclarations double __pyx_t_1; __Pyx_RefNannySetupContext("area_arc", 0); /* "photutils/geometry/core.pyx":91 * * cdef double a, theta * a = distance(x1, y1, x2, y2) # <<<<<<<<<<<<<< * theta = 2. * asin(0.5 * a / r) * return 0.5 * r * r * (theta - sin(theta)) */ __pyx_v_a = __pyx_f_9photutils_8geometry_4core_distance(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2); /* "photutils/geometry/core.pyx":92 * cdef double a, theta * a = distance(x1, y1, x2, y2) * theta = 2. * asin(0.5 * a / r) # <<<<<<<<<<<<<< * return 0.5 * r * r * (theta - sin(theta)) * */ __pyx_t_1 = (0.5 * __pyx_v_a); if (unlikely(__pyx_v_r == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 92, __pyx_L1_error) } __pyx_v_theta = (2. * asin((__pyx_t_1 / __pyx_v_r))); /* "photutils/geometry/core.pyx":93 * a = distance(x1, y1, x2, y2) * theta = 2. * asin(0.5 * a / r) * return 0.5 * r * r * (theta - sin(theta)) # <<<<<<<<<<<<<< * * */ __pyx_r = (((0.5 * __pyx_v_r) * __pyx_v_r) * (__pyx_v_theta - sin(__pyx_v_theta))); goto __pyx_L0; /* "photutils/geometry/core.pyx":81 * * * cdef double area_arc(double x1, double y1, double x2, double y2, double r): # <<<<<<<<<<<<<< * """ * Area of a circle arc with radius r between points (x1, y1) and (x2, y2). */ /* function exit code */ __pyx_L1_error:; __Pyx_WriteUnraisable("photutils.geometry.core.area_arc", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0); __pyx_r = 0; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/core.pyx":96 * * * cdef double area_triangle(double x1, double y1, double x2, double y2, double x3, # <<<<<<<<<<<<<< * double y3): * """ */ static double __pyx_f_9photutils_8geometry_4core_area_triangle(double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2, double __pyx_v_x3, double __pyx_v_y3) { double __pyx_r; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("area_triangle", 0); /* "photutils/geometry/core.pyx":101 * Area of a triangle defined by three vertices. * """ * return 0.5 * abs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) # <<<<<<<<<<<<<< * * */ __pyx_r = (0.5 * fabs((((__pyx_v_x1 * (__pyx_v_y2 - __pyx_v_y3)) + (__pyx_v_x2 * (__pyx_v_y3 - __pyx_v_y1))) + (__pyx_v_x3 * (__pyx_v_y1 - __pyx_v_y2))))); goto __pyx_L0; /* "photutils/geometry/core.pyx":96 * * * cdef double area_triangle(double x1, double y1, double x2, double y2, double x3, # <<<<<<<<<<<<<< * double y3): * """ */ /* function exit code */ __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/core.pyx":104 * * * cdef double area_arc_unit(double x1, double y1, double x2, double y2): # <<<<<<<<<<<<<< * """ * Area of a circle arc with radius R between points (x1, y1) and (x2, y2) */ static double __pyx_f_9photutils_8geometry_4core_area_arc_unit(double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2) { double __pyx_v_a; double __pyx_v_theta; double __pyx_r; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("area_arc_unit", 0); /* "photutils/geometry/core.pyx":113 * """ * cdef double a, theta * a = distance(x1, y1, x2, y2) # <<<<<<<<<<<<<< * theta = 2. * asin(0.5 * a) * return 0.5 * (theta - sin(theta)) */ __pyx_v_a = __pyx_f_9photutils_8geometry_4core_distance(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2); /* "photutils/geometry/core.pyx":114 * cdef double a, theta * a = distance(x1, y1, x2, y2) * theta = 2. * asin(0.5 * a) # <<<<<<<<<<<<<< * return 0.5 * (theta - sin(theta)) * */ __pyx_v_theta = (2. * asin((0.5 * __pyx_v_a))); /* "photutils/geometry/core.pyx":115 * a = distance(x1, y1, x2, y2) * theta = 2. * asin(0.5 * a) * return 0.5 * (theta - sin(theta)) # <<<<<<<<<<<<<< * * */ __pyx_r = (0.5 * (__pyx_v_theta - sin(__pyx_v_theta))); goto __pyx_L0; /* "photutils/geometry/core.pyx":104 * * * cdef double area_arc_unit(double x1, double y1, double x2, double y2): # <<<<<<<<<<<<<< * """ * Area of a circle arc with radius R between points (x1, y1) and (x2, y2) */ /* function exit code */ __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/core.pyx":118 * * * cdef int in_triangle(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3): # <<<<<<<<<<<<<< * """ * Check if a point (x,y) is inside a triangle */ static int __pyx_f_9photutils_8geometry_4core_in_triangle(double __pyx_v_x, double __pyx_v_y, double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2, double __pyx_v_x3, double __pyx_v_y3) { int __pyx_v_c; int __pyx_r; __Pyx_RefNannyDeclarations int __pyx_t_1; int __pyx_t_2; double __pyx_t_3; double __pyx_t_4; __Pyx_RefNannySetupContext("in_triangle", 0); /* "photutils/geometry/core.pyx":122 * Check if a point (x,y) is inside a triangle * """ * cdef int c = 0 # <<<<<<<<<<<<<< * * c += ((y1 > y) != (y2 > y) and x < (x2 - x1) * (y - y1) / (y2 - y1) + x1) */ __pyx_v_c = 0; /* "photutils/geometry/core.pyx":124 * cdef int c = 0 * * c += ((y1 > y) != (y2 > y) and x < (x2 - x1) * (y - y1) / (y2 - y1) + x1) # <<<<<<<<<<<<<< * c += ((y2 > y) != (y3 > y) and x < (x3 - x2) * (y - y2) / (y3 - y2) + x2) * c += ((y3 > y) != (y1 > y) and x < (x1 - x3) * (y - y3) / (y1 - y3) + x3) */ __pyx_t_2 = ((__pyx_v_y1 > __pyx_v_y) != (__pyx_v_y2 > __pyx_v_y)); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L3_bool_binop_done; } __pyx_t_3 = ((__pyx_v_x2 - __pyx_v_x1) * (__pyx_v_y - __pyx_v_y1)); __pyx_t_4 = (__pyx_v_y2 - __pyx_v_y1); if (unlikely(__pyx_t_4 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 124, __pyx_L1_error) } __pyx_t_2 = (__pyx_v_x < ((__pyx_t_3 / __pyx_t_4) + __pyx_v_x1)); __pyx_t_1 = __pyx_t_2; __pyx_L3_bool_binop_done:; __pyx_v_c = (__pyx_v_c + __pyx_t_1); /* "photutils/geometry/core.pyx":125 * * c += ((y1 > y) != (y2 > y) and x < (x2 - x1) * (y - y1) / (y2 - y1) + x1) * c += ((y2 > y) != (y3 > y) and x < (x3 - x2) * (y - y2) / (y3 - y2) + x2) # <<<<<<<<<<<<<< * c += ((y3 > y) != (y1 > y) and x < (x1 - x3) * (y - y3) / (y1 - y3) + x3) * */ __pyx_t_2 = ((__pyx_v_y2 > __pyx_v_y) != (__pyx_v_y3 > __pyx_v_y)); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L5_bool_binop_done; } __pyx_t_4 = ((__pyx_v_x3 - __pyx_v_x2) * (__pyx_v_y - __pyx_v_y2)); __pyx_t_3 = (__pyx_v_y3 - __pyx_v_y2); if (unlikely(__pyx_t_3 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 125, __pyx_L1_error) } __pyx_t_2 = (__pyx_v_x < ((__pyx_t_4 / __pyx_t_3) + __pyx_v_x2)); __pyx_t_1 = __pyx_t_2; __pyx_L5_bool_binop_done:; __pyx_v_c = (__pyx_v_c + __pyx_t_1); /* "photutils/geometry/core.pyx":126 * c += ((y1 > y) != (y2 > y) and x < (x2 - x1) * (y - y1) / (y2 - y1) + x1) * c += ((y2 > y) != (y3 > y) and x < (x3 - x2) * (y - y2) / (y3 - y2) + x2) * c += ((y3 > y) != (y1 > y) and x < (x1 - x3) * (y - y3) / (y1 - y3) + x3) # <<<<<<<<<<<<<< * * return c % 2 == 1 */ __pyx_t_2 = ((__pyx_v_y3 > __pyx_v_y) != (__pyx_v_y1 > __pyx_v_y)); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L7_bool_binop_done; } __pyx_t_3 = ((__pyx_v_x1 - __pyx_v_x3) * (__pyx_v_y - __pyx_v_y3)); __pyx_t_4 = (__pyx_v_y1 - __pyx_v_y3); if (unlikely(__pyx_t_4 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 126, __pyx_L1_error) } __pyx_t_2 = (__pyx_v_x < ((__pyx_t_3 / __pyx_t_4) + __pyx_v_x3)); __pyx_t_1 = __pyx_t_2; __pyx_L7_bool_binop_done:; __pyx_v_c = (__pyx_v_c + __pyx_t_1); /* "photutils/geometry/core.pyx":128 * c += ((y3 > y) != (y1 > y) and x < (x1 - x3) * (y - y3) / (y1 - y3) + x3) * * return c % 2 == 1 # <<<<<<<<<<<<<< * * */ __pyx_r = (__Pyx_mod_long(__pyx_v_c, 2) == 1); goto __pyx_L0; /* "photutils/geometry/core.pyx":118 * * * cdef int in_triangle(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3): # <<<<<<<<<<<<<< * """ * Check if a point (x,y) is inside a triangle */ /* function exit code */ __pyx_L1_error:; __Pyx_WriteUnraisable("photutils.geometry.core.in_triangle", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0); __pyx_r = 0; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/core.pyx":131 * * * cdef intersections circle_line(double x1, double y1, double x2, double y2): # <<<<<<<<<<<<<< * """Intersection of a line defined by two points with a unit circle""" * */ static __pyx_t_9photutils_8geometry_4core_intersections __pyx_f_9photutils_8geometry_4core_circle_line(double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2) { double __pyx_v_a; double __pyx_v_b; double __pyx_v_delta; double __pyx_v_dx; double __pyx_v_dy; double __pyx_v_tolerance; __pyx_t_9photutils_8geometry_4core_intersections __pyx_v_inter; __pyx_t_9photutils_8geometry_4core_intersections __pyx_r; __Pyx_RefNannyDeclarations int __pyx_t_1; int __pyx_t_2; double __pyx_t_3; double __pyx_t_4; __Pyx_RefNannySetupContext("circle_line", 0); /* "photutils/geometry/core.pyx":135 * * cdef double a, b, delta, dx, dy * cdef double tolerance = 1.e-10 # <<<<<<<<<<<<<< * cdef intersections inter * */ __pyx_v_tolerance = 1.e-10; /* "photutils/geometry/core.pyx":138 * cdef intersections inter * * dx = x2 - x1 # <<<<<<<<<<<<<< * dy = y2 - y1 * */ __pyx_v_dx = (__pyx_v_x2 - __pyx_v_x1); /* "photutils/geometry/core.pyx":139 * * dx = x2 - x1 * dy = y2 - y1 # <<<<<<<<<<<<<< * * if fabs(dx) < tolerance and fabs(dy) < tolerance: */ __pyx_v_dy = (__pyx_v_y2 - __pyx_v_y1); /* "photutils/geometry/core.pyx":141 * dy = y2 - y1 * * if fabs(dx) < tolerance and fabs(dy) < tolerance: # <<<<<<<<<<<<<< * inter.p1.x = 2. * inter.p1.y = 2. */ __pyx_t_2 = ((fabs(__pyx_v_dx) < __pyx_v_tolerance) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L4_bool_binop_done; } __pyx_t_2 = ((fabs(__pyx_v_dy) < __pyx_v_tolerance) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L4_bool_binop_done:; if (__pyx_t_1) { /* "photutils/geometry/core.pyx":142 * * if fabs(dx) < tolerance and fabs(dy) < tolerance: * inter.p1.x = 2. # <<<<<<<<<<<<<< * inter.p1.y = 2. * inter.p2.x = 2. */ __pyx_v_inter.p1.x = 2.; /* "photutils/geometry/core.pyx":143 * if fabs(dx) < tolerance and fabs(dy) < tolerance: * inter.p1.x = 2. * inter.p1.y = 2. # <<<<<<<<<<<<<< * inter.p2.x = 2. * inter.p2.y = 2. */ __pyx_v_inter.p1.y = 2.; /* "photutils/geometry/core.pyx":144 * inter.p1.x = 2. * inter.p1.y = 2. * inter.p2.x = 2. # <<<<<<<<<<<<<< * inter.p2.y = 2. * */ __pyx_v_inter.p2.x = 2.; /* "photutils/geometry/core.pyx":145 * inter.p1.y = 2. * inter.p2.x = 2. * inter.p2.y = 2. # <<<<<<<<<<<<<< * * elif fabs(dx) > fabs(dy): */ __pyx_v_inter.p2.y = 2.; /* "photutils/geometry/core.pyx":141 * dy = y2 - y1 * * if fabs(dx) < tolerance and fabs(dy) < tolerance: # <<<<<<<<<<<<<< * inter.p1.x = 2. * inter.p1.y = 2. */ goto __pyx_L3; } /* "photutils/geometry/core.pyx":147 * inter.p2.y = 2. * * elif fabs(dx) > fabs(dy): # <<<<<<<<<<<<<< * * # Find the slope and intercept of the line */ __pyx_t_1 = ((fabs(__pyx_v_dx) > fabs(__pyx_v_dy)) != 0); if (__pyx_t_1) { /* "photutils/geometry/core.pyx":150 * * # Find the slope and intercept of the line * a = dy / dx # <<<<<<<<<<<<<< * b = y1 - a * x1 * */ if (unlikely(__pyx_v_dx == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 150, __pyx_L1_error) } __pyx_v_a = (__pyx_v_dy / __pyx_v_dx); /* "photutils/geometry/core.pyx":151 * # Find the slope and intercept of the line * a = dy / dx * b = y1 - a * x1 # <<<<<<<<<<<<<< * * # Find the determinant of the quadratic equation */ __pyx_v_b = (__pyx_v_y1 - (__pyx_v_a * __pyx_v_x1)); /* "photutils/geometry/core.pyx":154 * * # Find the determinant of the quadratic equation * delta = 1. + a * a - b * b # <<<<<<<<<<<<<< * if delta > 0.: # solutions exist * */ __pyx_v_delta = ((1. + (__pyx_v_a * __pyx_v_a)) - (__pyx_v_b * __pyx_v_b)); /* "photutils/geometry/core.pyx":155 * # Find the determinant of the quadratic equation * delta = 1. + a * a - b * b * if delta > 0.: # solutions exist # <<<<<<<<<<<<<< * * delta = sqrt(delta) */ __pyx_t_1 = ((__pyx_v_delta > 0.) != 0); if (__pyx_t_1) { /* "photutils/geometry/core.pyx":157 * if delta > 0.: # solutions exist * * delta = sqrt(delta) # <<<<<<<<<<<<<< * * inter.p1.x = (- a * b - delta) / (1. + a * a) */ __pyx_v_delta = sqrt(__pyx_v_delta); /* "photutils/geometry/core.pyx":159 * delta = sqrt(delta) * * inter.p1.x = (- a * b - delta) / (1. + a * a) # <<<<<<<<<<<<<< * inter.p1.y = a * inter.p1.x + b * inter.p2.x = (- a * b + delta) / (1. + a * a) */ __pyx_t_3 = (((-__pyx_v_a) * __pyx_v_b) - __pyx_v_delta); __pyx_t_4 = (1. + (__pyx_v_a * __pyx_v_a)); if (unlikely(__pyx_t_4 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 159, __pyx_L1_error) } __pyx_v_inter.p1.x = (__pyx_t_3 / __pyx_t_4); /* "photutils/geometry/core.pyx":160 * * inter.p1.x = (- a * b - delta) / (1. + a * a) * inter.p1.y = a * inter.p1.x + b # <<<<<<<<<<<<<< * inter.p2.x = (- a * b + delta) / (1. + a * a) * inter.p2.y = a * inter.p2.x + b */ __pyx_v_inter.p1.y = ((__pyx_v_a * __pyx_v_inter.p1.x) + __pyx_v_b); /* "photutils/geometry/core.pyx":161 * inter.p1.x = (- a * b - delta) / (1. + a * a) * inter.p1.y = a * inter.p1.x + b * inter.p2.x = (- a * b + delta) / (1. + a * a) # <<<<<<<<<<<<<< * inter.p2.y = a * inter.p2.x + b * */ __pyx_t_4 = (((-__pyx_v_a) * __pyx_v_b) + __pyx_v_delta); __pyx_t_3 = (1. + (__pyx_v_a * __pyx_v_a)); if (unlikely(__pyx_t_3 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 161, __pyx_L1_error) } __pyx_v_inter.p2.x = (__pyx_t_4 / __pyx_t_3); /* "photutils/geometry/core.pyx":162 * inter.p1.y = a * inter.p1.x + b * inter.p2.x = (- a * b + delta) / (1. + a * a) * inter.p2.y = a * inter.p2.x + b # <<<<<<<<<<<<<< * * else: # no solution, return values > 1 */ __pyx_v_inter.p2.y = ((__pyx_v_a * __pyx_v_inter.p2.x) + __pyx_v_b); /* "photutils/geometry/core.pyx":155 * # Find the determinant of the quadratic equation * delta = 1. + a * a - b * b * if delta > 0.: # solutions exist # <<<<<<<<<<<<<< * * delta = sqrt(delta) */ goto __pyx_L6; } /* "photutils/geometry/core.pyx":165 * * else: # no solution, return values > 1 * inter.p1.x = 2. # <<<<<<<<<<<<<< * inter.p1.y = 2. * inter.p2.x = 2. */ /*else*/ { __pyx_v_inter.p1.x = 2.; /* "photutils/geometry/core.pyx":166 * else: # no solution, return values > 1 * inter.p1.x = 2. * inter.p1.y = 2. # <<<<<<<<<<<<<< * inter.p2.x = 2. * inter.p2.y = 2. */ __pyx_v_inter.p1.y = 2.; /* "photutils/geometry/core.pyx":167 * inter.p1.x = 2. * inter.p1.y = 2. * inter.p2.x = 2. # <<<<<<<<<<<<<< * inter.p2.y = 2. * */ __pyx_v_inter.p2.x = 2.; /* "photutils/geometry/core.pyx":168 * inter.p1.y = 2. * inter.p2.x = 2. * inter.p2.y = 2. # <<<<<<<<<<<<<< * * else: */ __pyx_v_inter.p2.y = 2.; } __pyx_L6:; /* "photutils/geometry/core.pyx":147 * inter.p2.y = 2. * * elif fabs(dx) > fabs(dy): # <<<<<<<<<<<<<< * * # Find the slope and intercept of the line */ goto __pyx_L3; } /* "photutils/geometry/core.pyx":173 * * # Find the slope and intercept of the line * a = dx / dy # <<<<<<<<<<<<<< * b = x1 - a * y1 * */ /*else*/ { if (unlikely(__pyx_v_dy == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 173, __pyx_L1_error) } __pyx_v_a = (__pyx_v_dx / __pyx_v_dy); /* "photutils/geometry/core.pyx":174 * # Find the slope and intercept of the line * a = dx / dy * b = x1 - a * y1 # <<<<<<<<<<<<<< * * # Find the determinant of the quadratic equation */ __pyx_v_b = (__pyx_v_x1 - (__pyx_v_a * __pyx_v_y1)); /* "photutils/geometry/core.pyx":177 * * # Find the determinant of the quadratic equation * delta = 1. + a * a - b * b # <<<<<<<<<<<<<< * * if delta > 0.: # solutions exist */ __pyx_v_delta = ((1. + (__pyx_v_a * __pyx_v_a)) - (__pyx_v_b * __pyx_v_b)); /* "photutils/geometry/core.pyx":179 * delta = 1. + a * a - b * b * * if delta > 0.: # solutions exist # <<<<<<<<<<<<<< * * delta = sqrt(delta) */ __pyx_t_1 = ((__pyx_v_delta > 0.) != 0); if (__pyx_t_1) { /* "photutils/geometry/core.pyx":181 * if delta > 0.: # solutions exist * * delta = sqrt(delta) # <<<<<<<<<<<<<< * * inter.p1.y = (- a * b - delta) / (1. + a * a) */ __pyx_v_delta = sqrt(__pyx_v_delta); /* "photutils/geometry/core.pyx":183 * delta = sqrt(delta) * * inter.p1.y = (- a * b - delta) / (1. + a * a) # <<<<<<<<<<<<<< * inter.p1.x = a * inter.p1.y + b * inter.p2.y = (- a * b + delta) / (1. + a * a) */ __pyx_t_3 = (((-__pyx_v_a) * __pyx_v_b) - __pyx_v_delta); __pyx_t_4 = (1. + (__pyx_v_a * __pyx_v_a)); if (unlikely(__pyx_t_4 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 183, __pyx_L1_error) } __pyx_v_inter.p1.y = (__pyx_t_3 / __pyx_t_4); /* "photutils/geometry/core.pyx":184 * * inter.p1.y = (- a * b - delta) / (1. + a * a) * inter.p1.x = a * inter.p1.y + b # <<<<<<<<<<<<<< * inter.p2.y = (- a * b + delta) / (1. + a * a) * inter.p2.x = a * inter.p2.y + b */ __pyx_v_inter.p1.x = ((__pyx_v_a * __pyx_v_inter.p1.y) + __pyx_v_b); /* "photutils/geometry/core.pyx":185 * inter.p1.y = (- a * b - delta) / (1. + a * a) * inter.p1.x = a * inter.p1.y + b * inter.p2.y = (- a * b + delta) / (1. + a * a) # <<<<<<<<<<<<<< * inter.p2.x = a * inter.p2.y + b * */ __pyx_t_4 = (((-__pyx_v_a) * __pyx_v_b) + __pyx_v_delta); __pyx_t_3 = (1. + (__pyx_v_a * __pyx_v_a)); if (unlikely(__pyx_t_3 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 185, __pyx_L1_error) } __pyx_v_inter.p2.y = (__pyx_t_4 / __pyx_t_3); /* "photutils/geometry/core.pyx":186 * inter.p1.x = a * inter.p1.y + b * inter.p2.y = (- a * b + delta) / (1. + a * a) * inter.p2.x = a * inter.p2.y + b # <<<<<<<<<<<<<< * * else: # no solution, return values > 1 */ __pyx_v_inter.p2.x = ((__pyx_v_a * __pyx_v_inter.p2.y) + __pyx_v_b); /* "photutils/geometry/core.pyx":179 * delta = 1. + a * a - b * b * * if delta > 0.: # solutions exist # <<<<<<<<<<<<<< * * delta = sqrt(delta) */ goto __pyx_L7; } /* "photutils/geometry/core.pyx":189 * * else: # no solution, return values > 1 * inter.p1.x = 2. # <<<<<<<<<<<<<< * inter.p1.y = 2. * inter.p2.x = 2. */ /*else*/ { __pyx_v_inter.p1.x = 2.; /* "photutils/geometry/core.pyx":190 * else: # no solution, return values > 1 * inter.p1.x = 2. * inter.p1.y = 2. # <<<<<<<<<<<<<< * inter.p2.x = 2. * inter.p2.y = 2. */ __pyx_v_inter.p1.y = 2.; /* "photutils/geometry/core.pyx":191 * inter.p1.x = 2. * inter.p1.y = 2. * inter.p2.x = 2. # <<<<<<<<<<<<<< * inter.p2.y = 2. * */ __pyx_v_inter.p2.x = 2.; /* "photutils/geometry/core.pyx":192 * inter.p1.y = 2. * inter.p2.x = 2. * inter.p2.y = 2. # <<<<<<<<<<<<<< * * return inter */ __pyx_v_inter.p2.y = 2.; } __pyx_L7:; } __pyx_L3:; /* "photutils/geometry/core.pyx":194 * inter.p2.y = 2. * * return inter # <<<<<<<<<<<<<< * * */ __pyx_r = __pyx_v_inter; goto __pyx_L0; /* "photutils/geometry/core.pyx":131 * * * cdef intersections circle_line(double x1, double y1, double x2, double y2): # <<<<<<<<<<<<<< * """Intersection of a line defined by two points with a unit circle""" * */ /* function exit code */ __pyx_L1_error:; __Pyx_WriteUnraisable("photutils.geometry.core.circle_line", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0); __Pyx_pretend_to_initialize(&__pyx_r); __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/core.pyx":197 * * * cdef point circle_segment_single2(double x1, double y1, double x2, double y2): # <<<<<<<<<<<<<< * """ * The intersection of a line with the unit circle. The intersection the */ static __pyx_t_9photutils_8geometry_4core_point __pyx_f_9photutils_8geometry_4core_circle_segment_single2(double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2) { double __pyx_v_dx1; double __pyx_v_dy1; double __pyx_v_dx2; double __pyx_v_dy2; __pyx_t_9photutils_8geometry_4core_intersections __pyx_v_inter; __pyx_t_9photutils_8geometry_4core_point __pyx_v_pt1; __pyx_t_9photutils_8geometry_4core_point __pyx_v_pt2; __pyx_t_9photutils_8geometry_4core_point __pyx_v_pt; __pyx_t_9photutils_8geometry_4core_point __pyx_r; __Pyx_RefNannyDeclarations __pyx_t_9photutils_8geometry_4core_point __pyx_t_1; int __pyx_t_2; __Pyx_RefNannySetupContext("circle_segment_single2", 0); /* "photutils/geometry/core.pyx":207 * cdef point pt1, pt2, pt * * inter = circle_line(x1, y1, x2, y2) # <<<<<<<<<<<<<< * * pt1 = inter.p1 */ __pyx_v_inter = __pyx_f_9photutils_8geometry_4core_circle_line(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2); /* "photutils/geometry/core.pyx":209 * inter = circle_line(x1, y1, x2, y2) * * pt1 = inter.p1 # <<<<<<<<<<<<<< * pt2 = inter.p2 * */ __pyx_t_1 = __pyx_v_inter.p1; __pyx_v_pt1 = __pyx_t_1; /* "photutils/geometry/core.pyx":210 * * pt1 = inter.p1 * pt2 = inter.p2 # <<<<<<<<<<<<<< * * # Can be optimized, but just checking for correctness right now */ __pyx_t_1 = __pyx_v_inter.p2; __pyx_v_pt2 = __pyx_t_1; /* "photutils/geometry/core.pyx":213 * * # Can be optimized, but just checking for correctness right now * dx1 = fabs(pt1.x - x2) # <<<<<<<<<<<<<< * dy1 = fabs(pt1.y - y2) * dx2 = fabs(pt2.x - x2) */ __pyx_v_dx1 = fabs((__pyx_v_pt1.x - __pyx_v_x2)); /* "photutils/geometry/core.pyx":214 * # Can be optimized, but just checking for correctness right now * dx1 = fabs(pt1.x - x2) * dy1 = fabs(pt1.y - y2) # <<<<<<<<<<<<<< * dx2 = fabs(pt2.x - x2) * dy2 = fabs(pt2.y - y2) */ __pyx_v_dy1 = fabs((__pyx_v_pt1.y - __pyx_v_y2)); /* "photutils/geometry/core.pyx":215 * dx1 = fabs(pt1.x - x2) * dy1 = fabs(pt1.y - y2) * dx2 = fabs(pt2.x - x2) # <<<<<<<<<<<<<< * dy2 = fabs(pt2.y - y2) * */ __pyx_v_dx2 = fabs((__pyx_v_pt2.x - __pyx_v_x2)); /* "photutils/geometry/core.pyx":216 * dy1 = fabs(pt1.y - y2) * dx2 = fabs(pt2.x - x2) * dy2 = fabs(pt2.y - y2) # <<<<<<<<<<<<<< * * if dx1 > dy1: # compare based on x-axis */ __pyx_v_dy2 = fabs((__pyx_v_pt2.y - __pyx_v_y2)); /* "photutils/geometry/core.pyx":218 * dy2 = fabs(pt2.y - y2) * * if dx1 > dy1: # compare based on x-axis # <<<<<<<<<<<<<< * if dx1 > dx2: * pt = pt2 */ __pyx_t_2 = ((__pyx_v_dx1 > __pyx_v_dy1) != 0); if (__pyx_t_2) { /* "photutils/geometry/core.pyx":219 * * if dx1 > dy1: # compare based on x-axis * if dx1 > dx2: # <<<<<<<<<<<<<< * pt = pt2 * else: */ __pyx_t_2 = ((__pyx_v_dx1 > __pyx_v_dx2) != 0); if (__pyx_t_2) { /* "photutils/geometry/core.pyx":220 * if dx1 > dy1: # compare based on x-axis * if dx1 > dx2: * pt = pt2 # <<<<<<<<<<<<<< * else: * pt = pt1 */ __pyx_v_pt = __pyx_v_pt2; /* "photutils/geometry/core.pyx":219 * * if dx1 > dy1: # compare based on x-axis * if dx1 > dx2: # <<<<<<<<<<<<<< * pt = pt2 * else: */ goto __pyx_L4; } /* "photutils/geometry/core.pyx":222 * pt = pt2 * else: * pt = pt1 # <<<<<<<<<<<<<< * else: * if dy1 > dy2: */ /*else*/ { __pyx_v_pt = __pyx_v_pt1; } __pyx_L4:; /* "photutils/geometry/core.pyx":218 * dy2 = fabs(pt2.y - y2) * * if dx1 > dy1: # compare based on x-axis # <<<<<<<<<<<<<< * if dx1 > dx2: * pt = pt2 */ goto __pyx_L3; } /* "photutils/geometry/core.pyx":224 * pt = pt1 * else: * if dy1 > dy2: # <<<<<<<<<<<<<< * pt = pt2 * else: */ /*else*/ { __pyx_t_2 = ((__pyx_v_dy1 > __pyx_v_dy2) != 0); if (__pyx_t_2) { /* "photutils/geometry/core.pyx":225 * else: * if dy1 > dy2: * pt = pt2 # <<<<<<<<<<<<<< * else: * pt = pt1 */ __pyx_v_pt = __pyx_v_pt2; /* "photutils/geometry/core.pyx":224 * pt = pt1 * else: * if dy1 > dy2: # <<<<<<<<<<<<<< * pt = pt2 * else: */ goto __pyx_L5; } /* "photutils/geometry/core.pyx":227 * pt = pt2 * else: * pt = pt1 # <<<<<<<<<<<<<< * * return pt */ /*else*/ { __pyx_v_pt = __pyx_v_pt1; } __pyx_L5:; } __pyx_L3:; /* "photutils/geometry/core.pyx":229 * pt = pt1 * * return pt # <<<<<<<<<<<<<< * * */ __pyx_r = __pyx_v_pt; goto __pyx_L0; /* "photutils/geometry/core.pyx":197 * * * cdef point circle_segment_single2(double x1, double y1, double x2, double y2): # <<<<<<<<<<<<<< * """ * The intersection of a line with the unit circle. The intersection the */ /* function exit code */ __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/core.pyx":232 * * * cdef intersections circle_segment(double x1, double y1, double x2, double y2): # <<<<<<<<<<<<<< * """ * Intersection(s) of a segment with the unit circle. Discard any */ static __pyx_t_9photutils_8geometry_4core_intersections __pyx_f_9photutils_8geometry_4core_circle_segment(double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2) { __pyx_t_9photutils_8geometry_4core_intersections __pyx_v_inter; __pyx_t_9photutils_8geometry_4core_intersections __pyx_v_inter_new; __pyx_t_9photutils_8geometry_4core_point __pyx_v_pt1; __pyx_t_9photutils_8geometry_4core_point __pyx_v_pt2; __pyx_t_9photutils_8geometry_4core_intersections __pyx_r; __Pyx_RefNannyDeclarations __pyx_t_9photutils_8geometry_4core_point __pyx_t_1; int __pyx_t_2; int __pyx_t_3; double __pyx_t_4; double __pyx_t_5; __Pyx_RefNannySetupContext("circle_segment", 0); /* "photutils/geometry/core.pyx":241 * cdef point pt1, pt2 * * inter = circle_line(x1, y1, x2, y2) # <<<<<<<<<<<<<< * * pt1 = inter.p1 */ __pyx_v_inter = __pyx_f_9photutils_8geometry_4core_circle_line(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2); /* "photutils/geometry/core.pyx":243 * inter = circle_line(x1, y1, x2, y2) * * pt1 = inter.p1 # <<<<<<<<<<<<<< * pt2 = inter.p2 * */ __pyx_t_1 = __pyx_v_inter.p1; __pyx_v_pt1 = __pyx_t_1; /* "photutils/geometry/core.pyx":244 * * pt1 = inter.p1 * pt2 = inter.p2 # <<<<<<<<<<<<<< * * if (pt1.x > x1 and pt1.x > x2) or (pt1.x < x1 and pt1.x < x2) or (pt1.y > y1 and pt1.y > y2) or (pt1.y < y1 and pt1.y < y2): */ __pyx_t_1 = __pyx_v_inter.p2; __pyx_v_pt2 = __pyx_t_1; /* "photutils/geometry/core.pyx":246 * pt2 = inter.p2 * * if (pt1.x > x1 and pt1.x > x2) or (pt1.x < x1 and pt1.x < x2) or (pt1.y > y1 and pt1.y > y2) or (pt1.y < y1 and pt1.y < y2): # <<<<<<<<<<<<<< * pt1.x, pt1.y = 2., 2. * if (pt2.x > x1 and pt2.x > x2) or (pt2.x < x1 and pt2.x < x2) or (pt2.y > y1 and pt2.y > y2) or (pt2.y < y1 and pt2.y < y2): */ __pyx_t_3 = ((__pyx_v_pt1.x > __pyx_v_x1) != 0); if (!__pyx_t_3) { goto __pyx_L5_next_or; } else { } __pyx_t_3 = ((__pyx_v_pt1.x > __pyx_v_x2) != 0); if (!__pyx_t_3) { } else { __pyx_t_2 = __pyx_t_3; goto __pyx_L4_bool_binop_done; } __pyx_L5_next_or:; __pyx_t_3 = ((__pyx_v_pt1.x < __pyx_v_x1) != 0); if (!__pyx_t_3) { goto __pyx_L7_next_or; } else { } __pyx_t_3 = ((__pyx_v_pt1.x < __pyx_v_x2) != 0); if (!__pyx_t_3) { } else { __pyx_t_2 = __pyx_t_3; goto __pyx_L4_bool_binop_done; } __pyx_L7_next_or:; __pyx_t_3 = ((__pyx_v_pt1.y > __pyx_v_y1) != 0); if (!__pyx_t_3) { goto __pyx_L9_next_or; } else { } __pyx_t_3 = ((__pyx_v_pt1.y > __pyx_v_y2) != 0); if (!__pyx_t_3) { } else { __pyx_t_2 = __pyx_t_3; goto __pyx_L4_bool_binop_done; } __pyx_L9_next_or:; __pyx_t_3 = ((__pyx_v_pt1.y < __pyx_v_y1) != 0); if (__pyx_t_3) { } else { __pyx_t_2 = __pyx_t_3; goto __pyx_L4_bool_binop_done; } __pyx_t_3 = ((__pyx_v_pt1.y < __pyx_v_y2) != 0); __pyx_t_2 = __pyx_t_3; __pyx_L4_bool_binop_done:; if (__pyx_t_2) { /* "photutils/geometry/core.pyx":247 * * if (pt1.x > x1 and pt1.x > x2) or (pt1.x < x1 and pt1.x < x2) or (pt1.y > y1 and pt1.y > y2) or (pt1.y < y1 and pt1.y < y2): * pt1.x, pt1.y = 2., 2. # <<<<<<<<<<<<<< * if (pt2.x > x1 and pt2.x > x2) or (pt2.x < x1 and pt2.x < x2) or (pt2.y > y1 and pt2.y > y2) or (pt2.y < y1 and pt2.y < y2): * pt2.x, pt2.y = 2., 2. */ __pyx_t_4 = 2.; __pyx_t_5 = 2.; __pyx_v_pt1.x = __pyx_t_4; __pyx_v_pt1.y = __pyx_t_5; /* "photutils/geometry/core.pyx":246 * pt2 = inter.p2 * * if (pt1.x > x1 and pt1.x > x2) or (pt1.x < x1 and pt1.x < x2) or (pt1.y > y1 and pt1.y > y2) or (pt1.y < y1 and pt1.y < y2): # <<<<<<<<<<<<<< * pt1.x, pt1.y = 2., 2. * if (pt2.x > x1 and pt2.x > x2) or (pt2.x < x1 and pt2.x < x2) or (pt2.y > y1 and pt2.y > y2) or (pt2.y < y1 and pt2.y < y2): */ } /* "photutils/geometry/core.pyx":248 * if (pt1.x > x1 and pt1.x > x2) or (pt1.x < x1 and pt1.x < x2) or (pt1.y > y1 and pt1.y > y2) or (pt1.y < y1 and pt1.y < y2): * pt1.x, pt1.y = 2., 2. * if (pt2.x > x1 and pt2.x > x2) or (pt2.x < x1 and pt2.x < x2) or (pt2.y > y1 and pt2.y > y2) or (pt2.y < y1 and pt2.y < y2): # <<<<<<<<<<<<<< * pt2.x, pt2.y = 2., 2. * */ __pyx_t_3 = ((__pyx_v_pt2.x > __pyx_v_x1) != 0); if (!__pyx_t_3) { goto __pyx_L14_next_or; } else { } __pyx_t_3 = ((__pyx_v_pt2.x > __pyx_v_x2) != 0); if (!__pyx_t_3) { } else { __pyx_t_2 = __pyx_t_3; goto __pyx_L13_bool_binop_done; } __pyx_L14_next_or:; __pyx_t_3 = ((__pyx_v_pt2.x < __pyx_v_x1) != 0); if (!__pyx_t_3) { goto __pyx_L16_next_or; } else { } __pyx_t_3 = ((__pyx_v_pt2.x < __pyx_v_x2) != 0); if (!__pyx_t_3) { } else { __pyx_t_2 = __pyx_t_3; goto __pyx_L13_bool_binop_done; } __pyx_L16_next_or:; __pyx_t_3 = ((__pyx_v_pt2.y > __pyx_v_y1) != 0); if (!__pyx_t_3) { goto __pyx_L18_next_or; } else { } __pyx_t_3 = ((__pyx_v_pt2.y > __pyx_v_y2) != 0); if (!__pyx_t_3) { } else { __pyx_t_2 = __pyx_t_3; goto __pyx_L13_bool_binop_done; } __pyx_L18_next_or:; __pyx_t_3 = ((__pyx_v_pt2.y < __pyx_v_y1) != 0); if (__pyx_t_3) { } else { __pyx_t_2 = __pyx_t_3; goto __pyx_L13_bool_binop_done; } __pyx_t_3 = ((__pyx_v_pt2.y < __pyx_v_y2) != 0); __pyx_t_2 = __pyx_t_3; __pyx_L13_bool_binop_done:; if (__pyx_t_2) { /* "photutils/geometry/core.pyx":249 * pt1.x, pt1.y = 2., 2. * if (pt2.x > x1 and pt2.x > x2) or (pt2.x < x1 and pt2.x < x2) or (pt2.y > y1 and pt2.y > y2) or (pt2.y < y1 and pt2.y < y2): * pt2.x, pt2.y = 2., 2. # <<<<<<<<<<<<<< * * if pt1.x > 1. and pt2.x < 2.: */ __pyx_t_5 = 2.; __pyx_t_4 = 2.; __pyx_v_pt2.x = __pyx_t_5; __pyx_v_pt2.y = __pyx_t_4; /* "photutils/geometry/core.pyx":248 * if (pt1.x > x1 and pt1.x > x2) or (pt1.x < x1 and pt1.x < x2) or (pt1.y > y1 and pt1.y > y2) or (pt1.y < y1 and pt1.y < y2): * pt1.x, pt1.y = 2., 2. * if (pt2.x > x1 and pt2.x > x2) or (pt2.x < x1 and pt2.x < x2) or (pt2.y > y1 and pt2.y > y2) or (pt2.y < y1 and pt2.y < y2): # <<<<<<<<<<<<<< * pt2.x, pt2.y = 2., 2. * */ } /* "photutils/geometry/core.pyx":251 * pt2.x, pt2.y = 2., 2. * * if pt1.x > 1. and pt2.x < 2.: # <<<<<<<<<<<<<< * inter_new.p1 = pt1 * inter_new.p2 = pt2 */ __pyx_t_3 = ((__pyx_v_pt1.x > 1.) != 0); if (__pyx_t_3) { } else { __pyx_t_2 = __pyx_t_3; goto __pyx_L22_bool_binop_done; } __pyx_t_3 = ((__pyx_v_pt2.x < 2.) != 0); __pyx_t_2 = __pyx_t_3; __pyx_L22_bool_binop_done:; if (__pyx_t_2) { /* "photutils/geometry/core.pyx":252 * * if pt1.x > 1. and pt2.x < 2.: * inter_new.p1 = pt1 # <<<<<<<<<<<<<< * inter_new.p2 = pt2 * else: */ __pyx_v_inter_new.p1 = __pyx_v_pt1; /* "photutils/geometry/core.pyx":253 * if pt1.x > 1. and pt2.x < 2.: * inter_new.p1 = pt1 * inter_new.p2 = pt2 # <<<<<<<<<<<<<< * else: * inter_new.p1 = pt2 */ __pyx_v_inter_new.p2 = __pyx_v_pt2; /* "photutils/geometry/core.pyx":251 * pt2.x, pt2.y = 2., 2. * * if pt1.x > 1. and pt2.x < 2.: # <<<<<<<<<<<<<< * inter_new.p1 = pt1 * inter_new.p2 = pt2 */ goto __pyx_L21; } /* "photutils/geometry/core.pyx":255 * inter_new.p2 = pt2 * else: * inter_new.p1 = pt2 # <<<<<<<<<<<<<< * inter_new.p2 = pt1 * */ /*else*/ { __pyx_v_inter_new.p1 = __pyx_v_pt2; /* "photutils/geometry/core.pyx":256 * else: * inter_new.p1 = pt2 * inter_new.p2 = pt1 # <<<<<<<<<<<<<< * * return inter_new */ __pyx_v_inter_new.p2 = __pyx_v_pt1; } __pyx_L21:; /* "photutils/geometry/core.pyx":258 * inter_new.p2 = pt1 * * return inter_new # <<<<<<<<<<<<<< * * */ __pyx_r = __pyx_v_inter_new; goto __pyx_L0; /* "photutils/geometry/core.pyx":232 * * * cdef intersections circle_segment(double x1, double y1, double x2, double y2): # <<<<<<<<<<<<<< * """ * Intersection(s) of a segment with the unit circle. Discard any */ /* function exit code */ __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/core.pyx":261 * * * cdef double overlap_area_triangle_unit_circle(double x1, double y1, double x2, double y2, double x3, double y3): # <<<<<<<<<<<<<< * """ * Given a triangle defined by three points (x1, y1), (x2, y2), and */ static double __pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle(double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2, double __pyx_v_x3, double __pyx_v_y3) { double __pyx_v_d1; double __pyx_v_d2; double __pyx_v_d3; PyBoolObject *__pyx_v_in1 = 0; PyBoolObject *__pyx_v_in2 = 0; PyBoolObject *__pyx_v_in3 = 0; PyBoolObject *__pyx_v_on1 = 0; PyBoolObject *__pyx_v_on2 = 0; PyBoolObject *__pyx_v_on3 = 0; double __pyx_v_area; double __pyx_v_PI; __pyx_t_9photutils_8geometry_4core_intersections __pyx_v_inter; __pyx_t_9photutils_8geometry_4core_point __pyx_v_pt1; __pyx_t_9photutils_8geometry_4core_point __pyx_v_pt2; __pyx_t_9photutils_8geometry_4core_point __pyx_v_pt3; __pyx_t_9photutils_8geometry_4core_point __pyx_v_pt4; __pyx_t_9photutils_8geometry_4core_point __pyx_v_pt5; __pyx_t_9photutils_8geometry_4core_point __pyx_v_pt6; PyObject *__pyx_v_intersect13 = NULL; PyObject *__pyx_v_intersect23 = NULL; double __pyx_v_xp; double __pyx_v_yp; double __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; double __pyx_t_3; int __pyx_t_4; double __pyx_t_5; double __pyx_t_6; double __pyx_t_7; double __pyx_t_8; double __pyx_t_9; double __pyx_t_10; double __pyx_t_11; double __pyx_t_12; int __pyx_t_13; int __pyx_t_14; __pyx_t_9photutils_8geometry_4core_point __pyx_t_15; __pyx_t_9photutils_8geometry_4core_point __pyx_t_16; __Pyx_RefNannySetupContext("overlap_area_triangle_unit_circle", 0); /* "photutils/geometry/core.pyx":271 * cdef bool on1, on2, on3 * cdef double area * cdef double PI = np.pi # <<<<<<<<<<<<<< * cdef intersections inter * cdef point pt1, pt2, pt3, pt4, pt5, pt6, pt_tmp */ __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 271, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_pi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 271, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 271, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __pyx_v_PI = __pyx_t_3; /* "photutils/geometry/core.pyx":276 * * # Find distance of all vertices to circle center * d1 = x1 * x1 + y1 * y1 # <<<<<<<<<<<<<< * d2 = x2 * x2 + y2 * y2 * d3 = x3 * x3 + y3 * y3 */ __pyx_v_d1 = ((__pyx_v_x1 * __pyx_v_x1) + (__pyx_v_y1 * __pyx_v_y1)); /* "photutils/geometry/core.pyx":277 * # Find distance of all vertices to circle center * d1 = x1 * x1 + y1 * y1 * d2 = x2 * x2 + y2 * y2 # <<<<<<<<<<<<<< * d3 = x3 * x3 + y3 * y3 * */ __pyx_v_d2 = ((__pyx_v_x2 * __pyx_v_x2) + (__pyx_v_y2 * __pyx_v_y2)); /* "photutils/geometry/core.pyx":278 * d1 = x1 * x1 + y1 * y1 * d2 = x2 * x2 + y2 * y2 * d3 = x3 * x3 + y3 * y3 # <<<<<<<<<<<<<< * * # Order vertices by distance from origin */ __pyx_v_d3 = ((__pyx_v_x3 * __pyx_v_x3) + (__pyx_v_y3 * __pyx_v_y3)); /* "photutils/geometry/core.pyx":281 * * # Order vertices by distance from origin * if d1 < d2: # <<<<<<<<<<<<<< * if d2 < d3: * pass */ __pyx_t_4 = ((__pyx_v_d1 < __pyx_v_d2) != 0); if (__pyx_t_4) { /* "photutils/geometry/core.pyx":282 * # Order vertices by distance from origin * if d1 < d2: * if d2 < d3: # <<<<<<<<<<<<<< * pass * elif d1 < d3: */ __pyx_t_4 = ((__pyx_v_d2 < __pyx_v_d3) != 0); if (__pyx_t_4) { goto __pyx_L4; } /* "photutils/geometry/core.pyx":284 * if d2 < d3: * pass * elif d1 < d3: # <<<<<<<<<<<<<< * x2, y2, d2, x3, y3, d3 = x3, y3, d3, x2, y2, d2 * else: */ __pyx_t_4 = ((__pyx_v_d1 < __pyx_v_d3) != 0); if (__pyx_t_4) { /* "photutils/geometry/core.pyx":285 * pass * elif d1 < d3: * x2, y2, d2, x3, y3, d3 = x3, y3, d3, x2, y2, d2 # <<<<<<<<<<<<<< * else: * x1, y1, d1, x2, y2, d2, x3, y3, d3 = x3, y3, d3, x1, y1, d1, x2, y2, d2 */ __pyx_t_3 = __pyx_v_x3; __pyx_t_5 = __pyx_v_y3; __pyx_t_6 = __pyx_v_d3; __pyx_t_7 = __pyx_v_x2; __pyx_t_8 = __pyx_v_y2; __pyx_t_9 = __pyx_v_d2; __pyx_v_x2 = __pyx_t_3; __pyx_v_y2 = __pyx_t_5; __pyx_v_d2 = __pyx_t_6; __pyx_v_x3 = __pyx_t_7; __pyx_v_y3 = __pyx_t_8; __pyx_v_d3 = __pyx_t_9; /* "photutils/geometry/core.pyx":284 * if d2 < d3: * pass * elif d1 < d3: # <<<<<<<<<<<<<< * x2, y2, d2, x3, y3, d3 = x3, y3, d3, x2, y2, d2 * else: */ goto __pyx_L4; } /* "photutils/geometry/core.pyx":287 * x2, y2, d2, x3, y3, d3 = x3, y3, d3, x2, y2, d2 * else: * x1, y1, d1, x2, y2, d2, x3, y3, d3 = x3, y3, d3, x1, y1, d1, x2, y2, d2 # <<<<<<<<<<<<<< * * else: */ /*else*/ { __pyx_t_9 = __pyx_v_x3; __pyx_t_8 = __pyx_v_y3; __pyx_t_7 = __pyx_v_d3; __pyx_t_6 = __pyx_v_x1; __pyx_t_5 = __pyx_v_y1; __pyx_t_3 = __pyx_v_d1; __pyx_t_10 = __pyx_v_x2; __pyx_t_11 = __pyx_v_y2; __pyx_t_12 = __pyx_v_d2; __pyx_v_x1 = __pyx_t_9; __pyx_v_y1 = __pyx_t_8; __pyx_v_d1 = __pyx_t_7; __pyx_v_x2 = __pyx_t_6; __pyx_v_y2 = __pyx_t_5; __pyx_v_d2 = __pyx_t_3; __pyx_v_x3 = __pyx_t_10; __pyx_v_y3 = __pyx_t_11; __pyx_v_d3 = __pyx_t_12; } __pyx_L4:; /* "photutils/geometry/core.pyx":281 * * # Order vertices by distance from origin * if d1 < d2: # <<<<<<<<<<<<<< * if d2 < d3: * pass */ goto __pyx_L3; } /* "photutils/geometry/core.pyx":290 * * else: * if d1 < d3: # <<<<<<<<<<<<<< * x1, y1, d1, x2, y2, d2 = x2, y2, d2, x1, y1, d1 * elif d2 < d3: */ /*else*/ { __pyx_t_4 = ((__pyx_v_d1 < __pyx_v_d3) != 0); if (__pyx_t_4) { /* "photutils/geometry/core.pyx":291 * else: * if d1 < d3: * x1, y1, d1, x2, y2, d2 = x2, y2, d2, x1, y1, d1 # <<<<<<<<<<<<<< * elif d2 < d3: * x1, y1, d1, x2, y2, d2, x3, y3, d3 = x2, y2, d2, x3, y3, d3, x1, y1, d1 */ __pyx_t_12 = __pyx_v_x2; __pyx_t_11 = __pyx_v_y2; __pyx_t_10 = __pyx_v_d2; __pyx_t_3 = __pyx_v_x1; __pyx_t_5 = __pyx_v_y1; __pyx_t_6 = __pyx_v_d1; __pyx_v_x1 = __pyx_t_12; __pyx_v_y1 = __pyx_t_11; __pyx_v_d1 = __pyx_t_10; __pyx_v_x2 = __pyx_t_3; __pyx_v_y2 = __pyx_t_5; __pyx_v_d2 = __pyx_t_6; /* "photutils/geometry/core.pyx":290 * * else: * if d1 < d3: # <<<<<<<<<<<<<< * x1, y1, d1, x2, y2, d2 = x2, y2, d2, x1, y1, d1 * elif d2 < d3: */ goto __pyx_L5; } /* "photutils/geometry/core.pyx":292 * if d1 < d3: * x1, y1, d1, x2, y2, d2 = x2, y2, d2, x1, y1, d1 * elif d2 < d3: # <<<<<<<<<<<<<< * x1, y1, d1, x2, y2, d2, x3, y3, d3 = x2, y2, d2, x3, y3, d3, x1, y1, d1 * else: */ __pyx_t_4 = ((__pyx_v_d2 < __pyx_v_d3) != 0); if (__pyx_t_4) { /* "photutils/geometry/core.pyx":293 * x1, y1, d1, x2, y2, d2 = x2, y2, d2, x1, y1, d1 * elif d2 < d3: * x1, y1, d1, x2, y2, d2, x3, y3, d3 = x2, y2, d2, x3, y3, d3, x1, y1, d1 # <<<<<<<<<<<<<< * else: * x1, y1, d1, x2, y2, d2, x3, y3, d3 = x3, y3, d3, x2, y2, d2, x1, y1, d1 */ __pyx_t_6 = __pyx_v_x2; __pyx_t_5 = __pyx_v_y2; __pyx_t_3 = __pyx_v_d2; __pyx_t_10 = __pyx_v_x3; __pyx_t_11 = __pyx_v_y3; __pyx_t_12 = __pyx_v_d3; __pyx_t_7 = __pyx_v_x1; __pyx_t_8 = __pyx_v_y1; __pyx_t_9 = __pyx_v_d1; __pyx_v_x1 = __pyx_t_6; __pyx_v_y1 = __pyx_t_5; __pyx_v_d1 = __pyx_t_3; __pyx_v_x2 = __pyx_t_10; __pyx_v_y2 = __pyx_t_11; __pyx_v_d2 = __pyx_t_12; __pyx_v_x3 = __pyx_t_7; __pyx_v_y3 = __pyx_t_8; __pyx_v_d3 = __pyx_t_9; /* "photutils/geometry/core.pyx":292 * if d1 < d3: * x1, y1, d1, x2, y2, d2 = x2, y2, d2, x1, y1, d1 * elif d2 < d3: # <<<<<<<<<<<<<< * x1, y1, d1, x2, y2, d2, x3, y3, d3 = x2, y2, d2, x3, y3, d3, x1, y1, d1 * else: */ goto __pyx_L5; } /* "photutils/geometry/core.pyx":295 * x1, y1, d1, x2, y2, d2, x3, y3, d3 = x2, y2, d2, x3, y3, d3, x1, y1, d1 * else: * x1, y1, d1, x2, y2, d2, x3, y3, d3 = x3, y3, d3, x2, y2, d2, x1, y1, d1 # <<<<<<<<<<<<<< * * if d1 > d2 or d2 > d3 or d1 > d3: */ /*else*/ { __pyx_t_9 = __pyx_v_x3; __pyx_t_8 = __pyx_v_y3; __pyx_t_7 = __pyx_v_d3; __pyx_t_12 = __pyx_v_x2; __pyx_t_11 = __pyx_v_y2; __pyx_t_10 = __pyx_v_d2; __pyx_t_3 = __pyx_v_x1; __pyx_t_5 = __pyx_v_y1; __pyx_t_6 = __pyx_v_d1; __pyx_v_x1 = __pyx_t_9; __pyx_v_y1 = __pyx_t_8; __pyx_v_d1 = __pyx_t_7; __pyx_v_x2 = __pyx_t_12; __pyx_v_y2 = __pyx_t_11; __pyx_v_d2 = __pyx_t_10; __pyx_v_x3 = __pyx_t_3; __pyx_v_y3 = __pyx_t_5; __pyx_v_d3 = __pyx_t_6; } __pyx_L5:; } __pyx_L3:; /* "photutils/geometry/core.pyx":297 * x1, y1, d1, x2, y2, d2, x3, y3, d3 = x3, y3, d3, x2, y2, d2, x1, y1, d1 * * if d1 > d2 or d2 > d3 or d1 > d3: # <<<<<<<<<<<<<< * raise Exception("ERROR: vertices did not sort correctly") * */ __pyx_t_13 = ((__pyx_v_d1 > __pyx_v_d2) != 0); if (!__pyx_t_13) { } else { __pyx_t_4 = __pyx_t_13; goto __pyx_L7_bool_binop_done; } __pyx_t_13 = ((__pyx_v_d2 > __pyx_v_d3) != 0); if (!__pyx_t_13) { } else { __pyx_t_4 = __pyx_t_13; goto __pyx_L7_bool_binop_done; } __pyx_t_13 = ((__pyx_v_d1 > __pyx_v_d3) != 0); __pyx_t_4 = __pyx_t_13; __pyx_L7_bool_binop_done:; if (unlikely(__pyx_t_4)) { /* "photutils/geometry/core.pyx":298 * * if d1 > d2 or d2 > d3 or d1 > d3: * raise Exception("ERROR: vertices did not sort correctly") # <<<<<<<<<<<<<< * * # Determine number of vertices inside circle */ __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0])), __pyx_tuple_, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 298, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_Raise(__pyx_t_2, 0, 0, 0); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __PYX_ERR(0, 298, __pyx_L1_error) /* "photutils/geometry/core.pyx":297 * x1, y1, d1, x2, y2, d2, x3, y3, d3 = x3, y3, d3, x2, y2, d2, x1, y1, d1 * * if d1 > d2 or d2 > d3 or d1 > d3: # <<<<<<<<<<<<<< * raise Exception("ERROR: vertices did not sort correctly") * */ } /* "photutils/geometry/core.pyx":301 * * # Determine number of vertices inside circle * in1 = d1 < 1 # <<<<<<<<<<<<<< * in2 = d2 < 1 * in3 = d3 < 1 */ __pyx_t_2 = __Pyx_PyBool_FromLong((__pyx_v_d1 < 1.0)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 301, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (!(likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_7cpython_4bool_bool)))) __PYX_ERR(0, 301, __pyx_L1_error) __pyx_v_in1 = ((PyBoolObject *)__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/core.pyx":302 * # Determine number of vertices inside circle * in1 = d1 < 1 * in2 = d2 < 1 # <<<<<<<<<<<<<< * in3 = d3 < 1 * */ __pyx_t_2 = __Pyx_PyBool_FromLong((__pyx_v_d2 < 1.0)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 302, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (!(likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_7cpython_4bool_bool)))) __PYX_ERR(0, 302, __pyx_L1_error) __pyx_v_in2 = ((PyBoolObject *)__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/core.pyx":303 * in1 = d1 < 1 * in2 = d2 < 1 * in3 = d3 < 1 # <<<<<<<<<<<<<< * * # Determine which vertices are on the circle */ __pyx_t_2 = __Pyx_PyBool_FromLong((__pyx_v_d3 < 1.0)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 303, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (!(likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_7cpython_4bool_bool)))) __PYX_ERR(0, 303, __pyx_L1_error) __pyx_v_in3 = ((PyBoolObject *)__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/core.pyx":306 * * # Determine which vertices are on the circle * on1 = fabs(d1 - 1) < 1.e-10 # <<<<<<<<<<<<<< * on2 = fabs(d2 - 1) < 1.e-10 * on3 = fabs(d3 - 1) < 1.e-10 */ __pyx_t_2 = __Pyx_PyBool_FromLong((fabs((__pyx_v_d1 - 1.0)) < 1.e-10)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 306, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (!(likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_7cpython_4bool_bool)))) __PYX_ERR(0, 306, __pyx_L1_error) __pyx_v_on1 = ((PyBoolObject *)__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/core.pyx":307 * # Determine which vertices are on the circle * on1 = fabs(d1 - 1) < 1.e-10 * on2 = fabs(d2 - 1) < 1.e-10 # <<<<<<<<<<<<<< * on3 = fabs(d3 - 1) < 1.e-10 * */ __pyx_t_2 = __Pyx_PyBool_FromLong((fabs((__pyx_v_d2 - 1.0)) < 1.e-10)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 307, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (!(likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_7cpython_4bool_bool)))) __PYX_ERR(0, 307, __pyx_L1_error) __pyx_v_on2 = ((PyBoolObject *)__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/core.pyx":308 * on1 = fabs(d1 - 1) < 1.e-10 * on2 = fabs(d2 - 1) < 1.e-10 * on3 = fabs(d3 - 1) < 1.e-10 # <<<<<<<<<<<<<< * * if on3 or in3: # triangle is completely in circle */ __pyx_t_2 = __Pyx_PyBool_FromLong((fabs((__pyx_v_d3 - 1.0)) < 1.e-10)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 308, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (!(likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_7cpython_4bool_bool)))) __PYX_ERR(0, 308, __pyx_L1_error) __pyx_v_on3 = ((PyBoolObject *)__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/core.pyx":310 * on3 = fabs(d3 - 1) < 1.e-10 * * if on3 or in3: # triangle is completely in circle # <<<<<<<<<<<<<< * * area = area_triangle(x1, y1, x2, y2, x3, y3) */ __pyx_t_13 = __Pyx_PyObject_IsTrue(((PyObject *)__pyx_v_on3)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 310, __pyx_L1_error) if (!__pyx_t_13) { } else { __pyx_t_4 = __pyx_t_13; goto __pyx_L11_bool_binop_done; } __pyx_t_13 = __Pyx_PyObject_IsTrue(((PyObject *)__pyx_v_in3)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 310, __pyx_L1_error) __pyx_t_4 = __pyx_t_13; __pyx_L11_bool_binop_done:; if (__pyx_t_4) { /* "photutils/geometry/core.pyx":312 * if on3 or in3: # triangle is completely in circle * * area = area_triangle(x1, y1, x2, y2, x3, y3) # <<<<<<<<<<<<<< * * elif in2 or on2: */ __pyx_v_area = __pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_x3, __pyx_v_y3); /* "photutils/geometry/core.pyx":310 * on3 = fabs(d3 - 1) < 1.e-10 * * if on3 or in3: # triangle is completely in circle # <<<<<<<<<<<<<< * * area = area_triangle(x1, y1, x2, y2, x3, y3) */ goto __pyx_L10; } /* "photutils/geometry/core.pyx":314 * area = area_triangle(x1, y1, x2, y2, x3, y3) * * elif in2 or on2: # <<<<<<<<<<<<<< * # If vertex 1 or 2 are on the edge of the circle, then we use the dot * # product to vertex 3 to determine whether an intersection takes place. */ __pyx_t_13 = __Pyx_PyObject_IsTrue(((PyObject *)__pyx_v_in2)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 314, __pyx_L1_error) if (!__pyx_t_13) { } else { __pyx_t_4 = __pyx_t_13; goto __pyx_L13_bool_binop_done; } __pyx_t_13 = __Pyx_PyObject_IsTrue(((PyObject *)__pyx_v_on2)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 314, __pyx_L1_error) __pyx_t_4 = __pyx_t_13; __pyx_L13_bool_binop_done:; if (__pyx_t_4) { /* "photutils/geometry/core.pyx":317 * # If vertex 1 or 2 are on the edge of the circle, then we use the dot * # product to vertex 3 to determine whether an intersection takes place. * intersect13 = not on1 or x1 * (x3 - x1) + y1 * (y3 - y1) < 0. # <<<<<<<<<<<<<< * intersect23 = not on2 or x2 * (x3 - x2) + y2 * (y3 - y2) < 0. * if intersect13 and intersect23 and not on2: */ __pyx_t_4 = __Pyx_PyObject_IsTrue(((PyObject *)__pyx_v_on1)); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 317, __pyx_L1_error) __pyx_t_13 = (!__pyx_t_4); if (!__pyx_t_13) { } else { __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_t_13); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 317, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L15_bool_binop_done; } __pyx_t_13 = (((__pyx_v_x1 * (__pyx_v_x3 - __pyx_v_x1)) + (__pyx_v_y1 * (__pyx_v_y3 - __pyx_v_y1))) < 0.); __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_t_13); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 317, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __pyx_t_1; __pyx_t_1 = 0; __pyx_L15_bool_binop_done:; __pyx_v_intersect13 = __pyx_t_2; __pyx_t_2 = 0; /* "photutils/geometry/core.pyx":318 * # product to vertex 3 to determine whether an intersection takes place. * intersect13 = not on1 or x1 * (x3 - x1) + y1 * (y3 - y1) < 0. * intersect23 = not on2 or x2 * (x3 - x2) + y2 * (y3 - y2) < 0. # <<<<<<<<<<<<<< * if intersect13 and intersect23 and not on2: * pt1 = circle_segment_single2(x1, y1, x3, y3) */ __pyx_t_13 = __Pyx_PyObject_IsTrue(((PyObject *)__pyx_v_on2)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 318, __pyx_L1_error) __pyx_t_4 = (!__pyx_t_13); if (!__pyx_t_4) { } else { __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 318, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L17_bool_binop_done; } __pyx_t_4 = (((__pyx_v_x2 * (__pyx_v_x3 - __pyx_v_x2)) + (__pyx_v_y2 * (__pyx_v_y3 - __pyx_v_y2))) < 0.); __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 318, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __pyx_t_1; __pyx_t_1 = 0; __pyx_L17_bool_binop_done:; __pyx_v_intersect23 = __pyx_t_2; __pyx_t_2 = 0; /* "photutils/geometry/core.pyx":319 * intersect13 = not on1 or x1 * (x3 - x1) + y1 * (y3 - y1) < 0. * intersect23 = not on2 or x2 * (x3 - x2) + y2 * (y3 - y2) < 0. * if intersect13 and intersect23 and not on2: # <<<<<<<<<<<<<< * pt1 = circle_segment_single2(x1, y1, x3, y3) * pt2 = circle_segment_single2(x2, y2, x3, y3) */ __pyx_t_13 = __Pyx_PyObject_IsTrue(__pyx_v_intersect13); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 319, __pyx_L1_error) if (__pyx_t_13) { } else { __pyx_t_4 = __pyx_t_13; goto __pyx_L20_bool_binop_done; } __pyx_t_13 = __Pyx_PyObject_IsTrue(__pyx_v_intersect23); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 319, __pyx_L1_error) if (__pyx_t_13) { } else { __pyx_t_4 = __pyx_t_13; goto __pyx_L20_bool_binop_done; } __pyx_t_13 = __Pyx_PyObject_IsTrue(((PyObject *)__pyx_v_on2)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 319, __pyx_L1_error) __pyx_t_14 = ((!__pyx_t_13) != 0); __pyx_t_4 = __pyx_t_14; __pyx_L20_bool_binop_done:; if (__pyx_t_4) { /* "photutils/geometry/core.pyx":320 * intersect23 = not on2 or x2 * (x3 - x2) + y2 * (y3 - y2) < 0. * if intersect13 and intersect23 and not on2: * pt1 = circle_segment_single2(x1, y1, x3, y3) # <<<<<<<<<<<<<< * pt2 = circle_segment_single2(x2, y2, x3, y3) * area = area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) \ */ __pyx_v_pt1 = __pyx_f_9photutils_8geometry_4core_circle_segment_single2(__pyx_v_x1, __pyx_v_y1, __pyx_v_x3, __pyx_v_y3); /* "photutils/geometry/core.pyx":321 * if intersect13 and intersect23 and not on2: * pt1 = circle_segment_single2(x1, y1, x3, y3) * pt2 = circle_segment_single2(x2, y2, x3, y3) # <<<<<<<<<<<<<< * area = area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) \ * + area_triangle(x2, y2, pt1.x, pt1.y, pt2.x, pt2.y) \ */ __pyx_v_pt2 = __pyx_f_9photutils_8geometry_4core_circle_segment_single2(__pyx_v_x2, __pyx_v_y2, __pyx_v_x3, __pyx_v_y3); /* "photutils/geometry/core.pyx":324 * area = area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) \ * + area_triangle(x2, y2, pt1.x, pt1.y, pt2.x, pt2.y) \ * + area_arc_unit(pt1.x, pt1.y, pt2.x, pt2.y) # <<<<<<<<<<<<<< * elif intersect13: * pt1 = circle_segment_single2(x1, y1, x3, y3) */ __pyx_v_area = ((__pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_pt1.x, __pyx_v_pt1.y) + __pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x2, __pyx_v_y2, __pyx_v_pt1.x, __pyx_v_pt1.y, __pyx_v_pt2.x, __pyx_v_pt2.y)) + __pyx_f_9photutils_8geometry_4core_area_arc_unit(__pyx_v_pt1.x, __pyx_v_pt1.y, __pyx_v_pt2.x, __pyx_v_pt2.y)); /* "photutils/geometry/core.pyx":319 * intersect13 = not on1 or x1 * (x3 - x1) + y1 * (y3 - y1) < 0. * intersect23 = not on2 or x2 * (x3 - x2) + y2 * (y3 - y2) < 0. * if intersect13 and intersect23 and not on2: # <<<<<<<<<<<<<< * pt1 = circle_segment_single2(x1, y1, x3, y3) * pt2 = circle_segment_single2(x2, y2, x3, y3) */ goto __pyx_L19; } /* "photutils/geometry/core.pyx":325 * + area_triangle(x2, y2, pt1.x, pt1.y, pt2.x, pt2.y) \ * + area_arc_unit(pt1.x, pt1.y, pt2.x, pt2.y) * elif intersect13: # <<<<<<<<<<<<<< * pt1 = circle_segment_single2(x1, y1, x3, y3) * area = area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) \ */ __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_intersect13); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 325, __pyx_L1_error) if (__pyx_t_4) { /* "photutils/geometry/core.pyx":326 * + area_arc_unit(pt1.x, pt1.y, pt2.x, pt2.y) * elif intersect13: * pt1 = circle_segment_single2(x1, y1, x3, y3) # <<<<<<<<<<<<<< * area = area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) \ * + area_arc_unit(x2, y2, pt1.x, pt1.y) */ __pyx_v_pt1 = __pyx_f_9photutils_8geometry_4core_circle_segment_single2(__pyx_v_x1, __pyx_v_y1, __pyx_v_x3, __pyx_v_y3); /* "photutils/geometry/core.pyx":328 * pt1 = circle_segment_single2(x1, y1, x3, y3) * area = area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) \ * + area_arc_unit(x2, y2, pt1.x, pt1.y) # <<<<<<<<<<<<<< * elif intersect23: * pt2 = circle_segment_single2(x2, y2, x3, y3) */ __pyx_v_area = (__pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_pt1.x, __pyx_v_pt1.y) + __pyx_f_9photutils_8geometry_4core_area_arc_unit(__pyx_v_x2, __pyx_v_y2, __pyx_v_pt1.x, __pyx_v_pt1.y)); /* "photutils/geometry/core.pyx":325 * + area_triangle(x2, y2, pt1.x, pt1.y, pt2.x, pt2.y) \ * + area_arc_unit(pt1.x, pt1.y, pt2.x, pt2.y) * elif intersect13: # <<<<<<<<<<<<<< * pt1 = circle_segment_single2(x1, y1, x3, y3) * area = area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) \ */ goto __pyx_L19; } /* "photutils/geometry/core.pyx":329 * area = area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) \ * + area_arc_unit(x2, y2, pt1.x, pt1.y) * elif intersect23: # <<<<<<<<<<<<<< * pt2 = circle_segment_single2(x2, y2, x3, y3) * area = area_triangle(x1, y1, x2, y2, pt2.x, pt2.y) \ */ __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_intersect23); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 329, __pyx_L1_error) if (__pyx_t_4) { /* "photutils/geometry/core.pyx":330 * + area_arc_unit(x2, y2, pt1.x, pt1.y) * elif intersect23: * pt2 = circle_segment_single2(x2, y2, x3, y3) # <<<<<<<<<<<<<< * area = area_triangle(x1, y1, x2, y2, pt2.x, pt2.y) \ * + area_arc_unit(x1, y1, pt2.x, pt2.y) */ __pyx_v_pt2 = __pyx_f_9photutils_8geometry_4core_circle_segment_single2(__pyx_v_x2, __pyx_v_y2, __pyx_v_x3, __pyx_v_y3); /* "photutils/geometry/core.pyx":332 * pt2 = circle_segment_single2(x2, y2, x3, y3) * area = area_triangle(x1, y1, x2, y2, pt2.x, pt2.y) \ * + area_arc_unit(x1, y1, pt2.x, pt2.y) # <<<<<<<<<<<<<< * else: * area = area_arc_unit(x1, y1, x2, y2) */ __pyx_v_area = (__pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_pt2.x, __pyx_v_pt2.y) + __pyx_f_9photutils_8geometry_4core_area_arc_unit(__pyx_v_x1, __pyx_v_y1, __pyx_v_pt2.x, __pyx_v_pt2.y)); /* "photutils/geometry/core.pyx":329 * area = area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) \ * + area_arc_unit(x2, y2, pt1.x, pt1.y) * elif intersect23: # <<<<<<<<<<<<<< * pt2 = circle_segment_single2(x2, y2, x3, y3) * area = area_triangle(x1, y1, x2, y2, pt2.x, pt2.y) \ */ goto __pyx_L19; } /* "photutils/geometry/core.pyx":334 * + area_arc_unit(x1, y1, pt2.x, pt2.y) * else: * area = area_arc_unit(x1, y1, x2, y2) # <<<<<<<<<<<<<< * * elif on1: */ /*else*/ { __pyx_v_area = __pyx_f_9photutils_8geometry_4core_area_arc_unit(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2); } __pyx_L19:; /* "photutils/geometry/core.pyx":314 * area = area_triangle(x1, y1, x2, y2, x3, y3) * * elif in2 or on2: # <<<<<<<<<<<<<< * # If vertex 1 or 2 are on the edge of the circle, then we use the dot * # product to vertex 3 to determine whether an intersection takes place. */ goto __pyx_L10; } /* "photutils/geometry/core.pyx":336 * area = area_arc_unit(x1, y1, x2, y2) * * elif on1: # <<<<<<<<<<<<<< * # The triangle is outside the circle * area = 0.0 */ __pyx_t_4 = __Pyx_PyObject_IsTrue(((PyObject *)__pyx_v_on1)); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 336, __pyx_L1_error) if (__pyx_t_4) { /* "photutils/geometry/core.pyx":338 * elif on1: * # The triangle is outside the circle * area = 0.0 # <<<<<<<<<<<<<< * elif in1: * # Check for intersections of far side with circle */ __pyx_v_area = 0.0; /* "photutils/geometry/core.pyx":336 * area = area_arc_unit(x1, y1, x2, y2) * * elif on1: # <<<<<<<<<<<<<< * # The triangle is outside the circle * area = 0.0 */ goto __pyx_L10; } /* "photutils/geometry/core.pyx":339 * # The triangle is outside the circle * area = 0.0 * elif in1: # <<<<<<<<<<<<<< * # Check for intersections of far side with circle * inter = circle_segment(x2, y2, x3, y3) */ __pyx_t_4 = __Pyx_PyObject_IsTrue(((PyObject *)__pyx_v_in1)); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 339, __pyx_L1_error) if (__pyx_t_4) { /* "photutils/geometry/core.pyx":341 * elif in1: * # Check for intersections of far side with circle * inter = circle_segment(x2, y2, x3, y3) # <<<<<<<<<<<<<< * pt1 = inter.p1 * pt2 = inter.p2 */ __pyx_v_inter = __pyx_f_9photutils_8geometry_4core_circle_segment(__pyx_v_x2, __pyx_v_y2, __pyx_v_x3, __pyx_v_y3); /* "photutils/geometry/core.pyx":342 * # Check for intersections of far side with circle * inter = circle_segment(x2, y2, x3, y3) * pt1 = inter.p1 # <<<<<<<<<<<<<< * pt2 = inter.p2 * pt3 = circle_segment_single2(x1, y1, x2, y2) */ __pyx_t_15 = __pyx_v_inter.p1; __pyx_v_pt1 = __pyx_t_15; /* "photutils/geometry/core.pyx":343 * inter = circle_segment(x2, y2, x3, y3) * pt1 = inter.p1 * pt2 = inter.p2 # <<<<<<<<<<<<<< * pt3 = circle_segment_single2(x1, y1, x2, y2) * pt4 = circle_segment_single2(x1, y1, x3, y3) */ __pyx_t_15 = __pyx_v_inter.p2; __pyx_v_pt2 = __pyx_t_15; /* "photutils/geometry/core.pyx":344 * pt1 = inter.p1 * pt2 = inter.p2 * pt3 = circle_segment_single2(x1, y1, x2, y2) # <<<<<<<<<<<<<< * pt4 = circle_segment_single2(x1, y1, x3, y3) * if pt1.x > 1.: # indicates no intersection */ __pyx_v_pt3 = __pyx_f_9photutils_8geometry_4core_circle_segment_single2(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2); /* "photutils/geometry/core.pyx":345 * pt2 = inter.p2 * pt3 = circle_segment_single2(x1, y1, x2, y2) * pt4 = circle_segment_single2(x1, y1, x3, y3) # <<<<<<<<<<<<<< * if pt1.x > 1.: # indicates no intersection * # Code taken from `sep.h`. */ __pyx_v_pt4 = __pyx_f_9photutils_8geometry_4core_circle_segment_single2(__pyx_v_x1, __pyx_v_y1, __pyx_v_x3, __pyx_v_y3); /* "photutils/geometry/core.pyx":346 * pt3 = circle_segment_single2(x1, y1, x2, y2) * pt4 = circle_segment_single2(x1, y1, x3, y3) * if pt1.x > 1.: # indicates no intersection # <<<<<<<<<<<<<< * # Code taken from `sep.h`. * # TODO: use `sep` and get rid of this Cython code. */ __pyx_t_4 = ((__pyx_v_pt1.x > 1.) != 0); if (__pyx_t_4) { /* "photutils/geometry/core.pyx":349 * # Code taken from `sep.h`. * # TODO: use `sep` and get rid of this Cython code. * if (((0.-pt3.y) * (pt4.x-pt3.x) > (pt4.y-pt3.y) * (0.-pt3.x)) != # <<<<<<<<<<<<<< * ((y1-pt3.y) * (pt4.x-pt3.x) > (pt4.y-pt3.y) * (x1-pt3.x))): * area = area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) \ */ __pyx_t_4 = (((((0. - __pyx_v_pt3.y) * (__pyx_v_pt4.x - __pyx_v_pt3.x)) > ((__pyx_v_pt4.y - __pyx_v_pt3.y) * (0. - __pyx_v_pt3.x))) != (((__pyx_v_y1 - __pyx_v_pt3.y) * (__pyx_v_pt4.x - __pyx_v_pt3.x)) > ((__pyx_v_pt4.y - __pyx_v_pt3.y) * (__pyx_v_x1 - __pyx_v_pt3.x)))) != 0); if (__pyx_t_4) { /* "photutils/geometry/core.pyx":352 * ((y1-pt3.y) * (pt4.x-pt3.x) > (pt4.y-pt3.y) * (x1-pt3.x))): * area = area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) \ * + (PI - area_arc_unit(pt3.x, pt3.y, pt4.x, pt4.y)) # <<<<<<<<<<<<<< * else: * area = area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) \ */ __pyx_v_area = (__pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_pt3.x, __pyx_v_pt3.y, __pyx_v_pt4.x, __pyx_v_pt4.y) + (__pyx_v_PI - __pyx_f_9photutils_8geometry_4core_area_arc_unit(__pyx_v_pt3.x, __pyx_v_pt3.y, __pyx_v_pt4.x, __pyx_v_pt4.y))); /* "photutils/geometry/core.pyx":349 * # Code taken from `sep.h`. * # TODO: use `sep` and get rid of this Cython code. * if (((0.-pt3.y) * (pt4.x-pt3.x) > (pt4.y-pt3.y) * (0.-pt3.x)) != # <<<<<<<<<<<<<< * ((y1-pt3.y) * (pt4.x-pt3.x) > (pt4.y-pt3.y) * (x1-pt3.x))): * area = area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) \ */ goto __pyx_L24; } /* "photutils/geometry/core.pyx":355 * else: * area = area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) \ * + area_arc_unit(pt3.x, pt3.y, pt4.x, pt4.y) # <<<<<<<<<<<<<< * else: * if (pt2.x - x2)**2 + (pt2.y - y2)**2 < (pt1.x - x2)**2 + (pt1.y - y2)**2: */ /*else*/ { /* "photutils/geometry/core.pyx":354 * + (PI - area_arc_unit(pt3.x, pt3.y, pt4.x, pt4.y)) * else: * area = area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) \ # <<<<<<<<<<<<<< * + area_arc_unit(pt3.x, pt3.y, pt4.x, pt4.y) * else: */ __pyx_v_area = (__pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_pt3.x, __pyx_v_pt3.y, __pyx_v_pt4.x, __pyx_v_pt4.y) + __pyx_f_9photutils_8geometry_4core_area_arc_unit(__pyx_v_pt3.x, __pyx_v_pt3.y, __pyx_v_pt4.x, __pyx_v_pt4.y)); } __pyx_L24:; /* "photutils/geometry/core.pyx":346 * pt3 = circle_segment_single2(x1, y1, x2, y2) * pt4 = circle_segment_single2(x1, y1, x3, y3) * if pt1.x > 1.: # indicates no intersection # <<<<<<<<<<<<<< * # Code taken from `sep.h`. * # TODO: use `sep` and get rid of this Cython code. */ goto __pyx_L23; } /* "photutils/geometry/core.pyx":357 * + area_arc_unit(pt3.x, pt3.y, pt4.x, pt4.y) * else: * if (pt2.x - x2)**2 + (pt2.y - y2)**2 < (pt1.x - x2)**2 + (pt1.y - y2)**2: # <<<<<<<<<<<<<< * pt1, pt2 = pt2, pt1 * area = area_triangle(x1, y1, pt3.x, pt3.y, pt1.x, pt1.y) \ */ /*else*/ { __pyx_t_4 = (((pow((__pyx_v_pt2.x - __pyx_v_x2), 2.0) + pow((__pyx_v_pt2.y - __pyx_v_y2), 2.0)) < (pow((__pyx_v_pt1.x - __pyx_v_x2), 2.0) + pow((__pyx_v_pt1.y - __pyx_v_y2), 2.0))) != 0); if (__pyx_t_4) { /* "photutils/geometry/core.pyx":358 * else: * if (pt2.x - x2)**2 + (pt2.y - y2)**2 < (pt1.x - x2)**2 + (pt1.y - y2)**2: * pt1, pt2 = pt2, pt1 # <<<<<<<<<<<<<< * area = area_triangle(x1, y1, pt3.x, pt3.y, pt1.x, pt1.y) \ * + area_triangle(x1, y1, pt1.x, pt1.y, pt2.x, pt2.y) \ */ __pyx_t_15 = __pyx_v_pt2; __pyx_t_16 = __pyx_v_pt1; __pyx_v_pt1 = __pyx_t_15; __pyx_v_pt2 = __pyx_t_16; /* "photutils/geometry/core.pyx":357 * + area_arc_unit(pt3.x, pt3.y, pt4.x, pt4.y) * else: * if (pt2.x - x2)**2 + (pt2.y - y2)**2 < (pt1.x - x2)**2 + (pt1.y - y2)**2: # <<<<<<<<<<<<<< * pt1, pt2 = pt2, pt1 * area = area_triangle(x1, y1, pt3.x, pt3.y, pt1.x, pt1.y) \ */ } /* "photutils/geometry/core.pyx":363 * + area_triangle(x1, y1, pt2.x, pt2.y, pt4.x, pt4.y) \ * + area_arc_unit(pt1.x, pt1.y, pt3.x, pt3.y) \ * + area_arc_unit(pt2.x, pt2.y, pt4.x, pt4.y) # <<<<<<<<<<<<<< * else: * inter = circle_segment(x1, y1, x2, y2) */ __pyx_v_area = ((((__pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_pt3.x, __pyx_v_pt3.y, __pyx_v_pt1.x, __pyx_v_pt1.y) + __pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_pt1.x, __pyx_v_pt1.y, __pyx_v_pt2.x, __pyx_v_pt2.y)) + __pyx_f_9photutils_8geometry_4core_area_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_pt2.x, __pyx_v_pt2.y, __pyx_v_pt4.x, __pyx_v_pt4.y)) + __pyx_f_9photutils_8geometry_4core_area_arc_unit(__pyx_v_pt1.x, __pyx_v_pt1.y, __pyx_v_pt3.x, __pyx_v_pt3.y)) + __pyx_f_9photutils_8geometry_4core_area_arc_unit(__pyx_v_pt2.x, __pyx_v_pt2.y, __pyx_v_pt4.x, __pyx_v_pt4.y)); } __pyx_L23:; /* "photutils/geometry/core.pyx":339 * # The triangle is outside the circle * area = 0.0 * elif in1: # <<<<<<<<<<<<<< * # Check for intersections of far side with circle * inter = circle_segment(x2, y2, x3, y3) */ goto __pyx_L10; } /* "photutils/geometry/core.pyx":365 * + area_arc_unit(pt2.x, pt2.y, pt4.x, pt4.y) * else: * inter = circle_segment(x1, y1, x2, y2) # <<<<<<<<<<<<<< * pt1 = inter.p1 * pt2 = inter.p2 */ /*else*/ { __pyx_v_inter = __pyx_f_9photutils_8geometry_4core_circle_segment(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2); /* "photutils/geometry/core.pyx":366 * else: * inter = circle_segment(x1, y1, x2, y2) * pt1 = inter.p1 # <<<<<<<<<<<<<< * pt2 = inter.p2 * inter = circle_segment(x2, y2, x3, y3) */ __pyx_t_16 = __pyx_v_inter.p1; __pyx_v_pt1 = __pyx_t_16; /* "photutils/geometry/core.pyx":367 * inter = circle_segment(x1, y1, x2, y2) * pt1 = inter.p1 * pt2 = inter.p2 # <<<<<<<<<<<<<< * inter = circle_segment(x2, y2, x3, y3) * pt3 = inter.p1 */ __pyx_t_16 = __pyx_v_inter.p2; __pyx_v_pt2 = __pyx_t_16; /* "photutils/geometry/core.pyx":368 * pt1 = inter.p1 * pt2 = inter.p2 * inter = circle_segment(x2, y2, x3, y3) # <<<<<<<<<<<<<< * pt3 = inter.p1 * pt4 = inter.p2 */ __pyx_v_inter = __pyx_f_9photutils_8geometry_4core_circle_segment(__pyx_v_x2, __pyx_v_y2, __pyx_v_x3, __pyx_v_y3); /* "photutils/geometry/core.pyx":369 * pt2 = inter.p2 * inter = circle_segment(x2, y2, x3, y3) * pt3 = inter.p1 # <<<<<<<<<<<<<< * pt4 = inter.p2 * inter = circle_segment(x3, y3, x1, y1) */ __pyx_t_16 = __pyx_v_inter.p1; __pyx_v_pt3 = __pyx_t_16; /* "photutils/geometry/core.pyx":370 * inter = circle_segment(x2, y2, x3, y3) * pt3 = inter.p1 * pt4 = inter.p2 # <<<<<<<<<<<<<< * inter = circle_segment(x3, y3, x1, y1) * pt5 = inter.p1 */ __pyx_t_16 = __pyx_v_inter.p2; __pyx_v_pt4 = __pyx_t_16; /* "photutils/geometry/core.pyx":371 * pt3 = inter.p1 * pt4 = inter.p2 * inter = circle_segment(x3, y3, x1, y1) # <<<<<<<<<<<<<< * pt5 = inter.p1 * pt6 = inter.p2 */ __pyx_v_inter = __pyx_f_9photutils_8geometry_4core_circle_segment(__pyx_v_x3, __pyx_v_y3, __pyx_v_x1, __pyx_v_y1); /* "photutils/geometry/core.pyx":372 * pt4 = inter.p2 * inter = circle_segment(x3, y3, x1, y1) * pt5 = inter.p1 # <<<<<<<<<<<<<< * pt6 = inter.p2 * if pt1.x <= 1.: */ __pyx_t_16 = __pyx_v_inter.p1; __pyx_v_pt5 = __pyx_t_16; /* "photutils/geometry/core.pyx":373 * inter = circle_segment(x3, y3, x1, y1) * pt5 = inter.p1 * pt6 = inter.p2 # <<<<<<<<<<<<<< * if pt1.x <= 1.: * xp, yp = 0.5 * (pt1.x + pt2.x), 0.5 * (pt1.y + pt2.y) */ __pyx_t_16 = __pyx_v_inter.p2; __pyx_v_pt6 = __pyx_t_16; /* "photutils/geometry/core.pyx":374 * pt5 = inter.p1 * pt6 = inter.p2 * if pt1.x <= 1.: # <<<<<<<<<<<<<< * xp, yp = 0.5 * (pt1.x + pt2.x), 0.5 * (pt1.y + pt2.y) * area = overlap_area_triangle_unit_circle(x1, y1, x3, y3, xp, yp) \ */ __pyx_t_4 = ((__pyx_v_pt1.x <= 1.) != 0); if (__pyx_t_4) { /* "photutils/geometry/core.pyx":375 * pt6 = inter.p2 * if pt1.x <= 1.: * xp, yp = 0.5 * (pt1.x + pt2.x), 0.5 * (pt1.y + pt2.y) # <<<<<<<<<<<<<< * area = overlap_area_triangle_unit_circle(x1, y1, x3, y3, xp, yp) \ * + overlap_area_triangle_unit_circle(x2, y2, x3, y3, xp, yp) */ __pyx_t_6 = (0.5 * (__pyx_v_pt1.x + __pyx_v_pt2.x)); __pyx_t_5 = (0.5 * (__pyx_v_pt1.y + __pyx_v_pt2.y)); __pyx_v_xp = __pyx_t_6; __pyx_v_yp = __pyx_t_5; /* "photutils/geometry/core.pyx":377 * xp, yp = 0.5 * (pt1.x + pt2.x), 0.5 * (pt1.y + pt2.y) * area = overlap_area_triangle_unit_circle(x1, y1, x3, y3, xp, yp) \ * + overlap_area_triangle_unit_circle(x2, y2, x3, y3, xp, yp) # <<<<<<<<<<<<<< * elif pt3.x <= 1.: * xp, yp = 0.5 * (pt3.x + pt4.x), 0.5 * (pt3.y + pt4.y) */ __pyx_v_area = (__pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle(__pyx_v_x1, __pyx_v_y1, __pyx_v_x3, __pyx_v_y3, __pyx_v_xp, __pyx_v_yp) + __pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle(__pyx_v_x2, __pyx_v_y2, __pyx_v_x3, __pyx_v_y3, __pyx_v_xp, __pyx_v_yp)); /* "photutils/geometry/core.pyx":374 * pt5 = inter.p1 * pt6 = inter.p2 * if pt1.x <= 1.: # <<<<<<<<<<<<<< * xp, yp = 0.5 * (pt1.x + pt2.x), 0.5 * (pt1.y + pt2.y) * area = overlap_area_triangle_unit_circle(x1, y1, x3, y3, xp, yp) \ */ goto __pyx_L26; } /* "photutils/geometry/core.pyx":378 * area = overlap_area_triangle_unit_circle(x1, y1, x3, y3, xp, yp) \ * + overlap_area_triangle_unit_circle(x2, y2, x3, y3, xp, yp) * elif pt3.x <= 1.: # <<<<<<<<<<<<<< * xp, yp = 0.5 * (pt3.x + pt4.x), 0.5 * (pt3.y + pt4.y) * area = overlap_area_triangle_unit_circle(x3, y3, x1, y1, xp, yp) \ */ __pyx_t_4 = ((__pyx_v_pt3.x <= 1.) != 0); if (__pyx_t_4) { /* "photutils/geometry/core.pyx":379 * + overlap_area_triangle_unit_circle(x2, y2, x3, y3, xp, yp) * elif pt3.x <= 1.: * xp, yp = 0.5 * (pt3.x + pt4.x), 0.5 * (pt3.y + pt4.y) # <<<<<<<<<<<<<< * area = overlap_area_triangle_unit_circle(x3, y3, x1, y1, xp, yp) \ * + overlap_area_triangle_unit_circle(x2, y2, x1, y1, xp, yp) */ __pyx_t_5 = (0.5 * (__pyx_v_pt3.x + __pyx_v_pt4.x)); __pyx_t_6 = (0.5 * (__pyx_v_pt3.y + __pyx_v_pt4.y)); __pyx_v_xp = __pyx_t_5; __pyx_v_yp = __pyx_t_6; /* "photutils/geometry/core.pyx":381 * xp, yp = 0.5 * (pt3.x + pt4.x), 0.5 * (pt3.y + pt4.y) * area = overlap_area_triangle_unit_circle(x3, y3, x1, y1, xp, yp) \ * + overlap_area_triangle_unit_circle(x2, y2, x1, y1, xp, yp) # <<<<<<<<<<<<<< * elif pt5.x <= 1.: * xp, yp = 0.5 * (pt5.x + pt6.x), 0.5 * (pt5.y + pt6.y) */ __pyx_v_area = (__pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle(__pyx_v_x3, __pyx_v_y3, __pyx_v_x1, __pyx_v_y1, __pyx_v_xp, __pyx_v_yp) + __pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle(__pyx_v_x2, __pyx_v_y2, __pyx_v_x1, __pyx_v_y1, __pyx_v_xp, __pyx_v_yp)); /* "photutils/geometry/core.pyx":378 * area = overlap_area_triangle_unit_circle(x1, y1, x3, y3, xp, yp) \ * + overlap_area_triangle_unit_circle(x2, y2, x3, y3, xp, yp) * elif pt3.x <= 1.: # <<<<<<<<<<<<<< * xp, yp = 0.5 * (pt3.x + pt4.x), 0.5 * (pt3.y + pt4.y) * area = overlap_area_triangle_unit_circle(x3, y3, x1, y1, xp, yp) \ */ goto __pyx_L26; } /* "photutils/geometry/core.pyx":382 * area = overlap_area_triangle_unit_circle(x3, y3, x1, y1, xp, yp) \ * + overlap_area_triangle_unit_circle(x2, y2, x1, y1, xp, yp) * elif pt5.x <= 1.: # <<<<<<<<<<<<<< * xp, yp = 0.5 * (pt5.x + pt6.x), 0.5 * (pt5.y + pt6.y) * area = overlap_area_triangle_unit_circle(x1, y1, x2, y2, xp, yp) \ */ __pyx_t_4 = ((__pyx_v_pt5.x <= 1.) != 0); if (__pyx_t_4) { /* "photutils/geometry/core.pyx":383 * + overlap_area_triangle_unit_circle(x2, y2, x1, y1, xp, yp) * elif pt5.x <= 1.: * xp, yp = 0.5 * (pt5.x + pt6.x), 0.5 * (pt5.y + pt6.y) # <<<<<<<<<<<<<< * area = overlap_area_triangle_unit_circle(x1, y1, x2, y2, xp, yp) \ * + overlap_area_triangle_unit_circle(x3, y3, x2, y2, xp, yp) */ __pyx_t_6 = (0.5 * (__pyx_v_pt5.x + __pyx_v_pt6.x)); __pyx_t_5 = (0.5 * (__pyx_v_pt5.y + __pyx_v_pt6.y)); __pyx_v_xp = __pyx_t_6; __pyx_v_yp = __pyx_t_5; /* "photutils/geometry/core.pyx":385 * xp, yp = 0.5 * (pt5.x + pt6.x), 0.5 * (pt5.y + pt6.y) * area = overlap_area_triangle_unit_circle(x1, y1, x2, y2, xp, yp) \ * + overlap_area_triangle_unit_circle(x3, y3, x2, y2, xp, yp) # <<<<<<<<<<<<<< * else: # no intersections * if in_triangle(0., 0., x1, y1, x2, y2, x3, y3): */ __pyx_v_area = (__pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_xp, __pyx_v_yp) + __pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle(__pyx_v_x3, __pyx_v_y3, __pyx_v_x2, __pyx_v_y2, __pyx_v_xp, __pyx_v_yp)); /* "photutils/geometry/core.pyx":382 * area = overlap_area_triangle_unit_circle(x3, y3, x1, y1, xp, yp) \ * + overlap_area_triangle_unit_circle(x2, y2, x1, y1, xp, yp) * elif pt5.x <= 1.: # <<<<<<<<<<<<<< * xp, yp = 0.5 * (pt5.x + pt6.x), 0.5 * (pt5.y + pt6.y) * area = overlap_area_triangle_unit_circle(x1, y1, x2, y2, xp, yp) \ */ goto __pyx_L26; } /* "photutils/geometry/core.pyx":387 * + overlap_area_triangle_unit_circle(x3, y3, x2, y2, xp, yp) * else: # no intersections * if in_triangle(0., 0., x1, y1, x2, y2, x3, y3): # <<<<<<<<<<<<<< * return PI * else: */ /*else*/ { __pyx_t_4 = (__pyx_f_9photutils_8geometry_4core_in_triangle(0., 0., __pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_x3, __pyx_v_y3) != 0); if (__pyx_t_4) { /* "photutils/geometry/core.pyx":388 * else: # no intersections * if in_triangle(0., 0., x1, y1, x2, y2, x3, y3): * return PI # <<<<<<<<<<<<<< * else: * return 0. */ __pyx_r = __pyx_v_PI; goto __pyx_L0; /* "photutils/geometry/core.pyx":387 * + overlap_area_triangle_unit_circle(x3, y3, x2, y2, xp, yp) * else: # no intersections * if in_triangle(0., 0., x1, y1, x2, y2, x3, y3): # <<<<<<<<<<<<<< * return PI * else: */ } /* "photutils/geometry/core.pyx":390 * return PI * else: * return 0. # <<<<<<<<<<<<<< * * return area */ /*else*/ { __pyx_r = 0.; goto __pyx_L0; } } __pyx_L26:; } __pyx_L10:; /* "photutils/geometry/core.pyx":392 * return 0. * * return area # <<<<<<<<<<<<<< */ __pyx_r = __pyx_v_area; goto __pyx_L0; /* "photutils/geometry/core.pyx":261 * * * cdef double overlap_area_triangle_unit_circle(double x1, double y1, double x2, double y2, double x3, double y3): # <<<<<<<<<<<<<< * """ * Given a triangle defined by three points (x1, y1), (x2, y2), and */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_2); __Pyx_WriteUnraisable("photutils.geometry.core.overlap_area_triangle_unit_circle", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0); __pyx_r = 0; __pyx_L0:; __Pyx_XDECREF((PyObject *)__pyx_v_in1); __Pyx_XDECREF((PyObject *)__pyx_v_in2); __Pyx_XDECREF((PyObject *)__pyx_v_in3); __Pyx_XDECREF((PyObject *)__pyx_v_on1); __Pyx_XDECREF((PyObject *)__pyx_v_on2); __Pyx_XDECREF((PyObject *)__pyx_v_on3); __Pyx_XDECREF(__pyx_v_intersect13); __Pyx_XDECREF(__pyx_v_intersect23); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":258 * # experimental exception made for __getbuffer__ and __releasebuffer__ * # -- the details of this may change. * def __getbuffer__(ndarray self, Py_buffer* info, int flags): # <<<<<<<<<<<<<< * # This implementation of getbuffer is geared towards Cython * # requirements, and does not yet fulfill the PEP. */ /* Python wrapper */ static CYTHON_UNUSED int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ static CYTHON_UNUSED int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { int __pyx_r; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0); __pyx_r = __pyx_pf_5numpy_7ndarray___getbuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags)); /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { int __pyx_v_i; int __pyx_v_ndim; int __pyx_v_endian_detector; int __pyx_v_little_endian; int __pyx_v_t; char *__pyx_v_f; PyArray_Descr *__pyx_v_descr = 0; int __pyx_v_offset; int __pyx_r; __Pyx_RefNannyDeclarations int __pyx_t_1; int __pyx_t_2; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; int __pyx_t_5; int __pyx_t_6; PyArray_Descr *__pyx_t_7; PyObject *__pyx_t_8 = NULL; char *__pyx_t_9; if (__pyx_v_info == NULL) { PyErr_SetString(PyExc_BufferError, "PyObject_GetBuffer: view==NULL argument is obsolete"); return -1; } __Pyx_RefNannySetupContext("__getbuffer__", 0); __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None); __Pyx_GIVEREF(__pyx_v_info->obj); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":265 * * cdef int i, ndim * cdef int endian_detector = 1 # <<<<<<<<<<<<<< * cdef bint little_endian = ((&endian_detector)[0] != 0) * */ __pyx_v_endian_detector = 1; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":266 * cdef int i, ndim * cdef int endian_detector = 1 * cdef bint little_endian = ((&endian_detector)[0] != 0) # <<<<<<<<<<<<<< * * ndim = PyArray_NDIM(self) */ __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":268 * cdef bint little_endian = ((&endian_detector)[0] != 0) * * ndim = PyArray_NDIM(self) # <<<<<<<<<<<<<< * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) */ __pyx_v_ndim = PyArray_NDIM(__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":270 * ndim = PyArray_NDIM(self) * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") */ __pyx_t_2 = (((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L4_bool_binop_done; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":271 * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): # <<<<<<<<<<<<<< * raise ValueError(u"ndarray is not C contiguous") * */ __pyx_t_2 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_ARRAY_C_CONTIGUOUS) != 0)) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L4_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":270 * ndim = PyArray_NDIM(self) * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") */ if (unlikely(__pyx_t_1)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":272 * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") # <<<<<<<<<<<<<< * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 272, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 272, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":270 * ndim = PyArray_NDIM(self) * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":274 * raise ValueError(u"ndarray is not C contiguous") * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") */ __pyx_t_2 = (((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L7_bool_binop_done; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":275 * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): # <<<<<<<<<<<<<< * raise ValueError(u"ndarray is not Fortran contiguous") * */ __pyx_t_2 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_ARRAY_F_CONTIGUOUS) != 0)) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L7_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":274 * raise ValueError(u"ndarray is not C contiguous") * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") */ if (unlikely(__pyx_t_1)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":276 * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") # <<<<<<<<<<<<<< * * info.buf = PyArray_DATA(self) */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 276, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 276, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":274 * raise ValueError(u"ndarray is not C contiguous") * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":278 * raise ValueError(u"ndarray is not Fortran contiguous") * * info.buf = PyArray_DATA(self) # <<<<<<<<<<<<<< * info.ndim = ndim * if sizeof(npy_intp) != sizeof(Py_ssize_t): */ __pyx_v_info->buf = PyArray_DATA(__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":279 * * info.buf = PyArray_DATA(self) * info.ndim = ndim # <<<<<<<<<<<<<< * if sizeof(npy_intp) != sizeof(Py_ssize_t): * # Allocate new buffer for strides and shape info. */ __pyx_v_info->ndim = __pyx_v_ndim; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":280 * info.buf = PyArray_DATA(self) * info.ndim = ndim * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * # Allocate new buffer for strides and shape info. * # This is allocated as one block, strides first. */ __pyx_t_1 = (((sizeof(npy_intp)) != (sizeof(Py_ssize_t))) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":283 * # Allocate new buffer for strides and shape info. * # This is allocated as one block, strides first. * info.strides = PyObject_Malloc(sizeof(Py_ssize_t) * 2 * ndim) # <<<<<<<<<<<<<< * info.shape = info.strides + ndim * for i in range(ndim): */ __pyx_v_info->strides = ((Py_ssize_t *)PyObject_Malloc((((sizeof(Py_ssize_t)) * 2) * ((size_t)__pyx_v_ndim)))); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":284 * # This is allocated as one block, strides first. * info.strides = PyObject_Malloc(sizeof(Py_ssize_t) * 2 * ndim) * info.shape = info.strides + ndim # <<<<<<<<<<<<<< * for i in range(ndim): * info.strides[i] = PyArray_STRIDES(self)[i] */ __pyx_v_info->shape = (__pyx_v_info->strides + __pyx_v_ndim); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":285 * info.strides = PyObject_Malloc(sizeof(Py_ssize_t) * 2 * ndim) * info.shape = info.strides + ndim * for i in range(ndim): # <<<<<<<<<<<<<< * info.strides[i] = PyArray_STRIDES(self)[i] * info.shape[i] = PyArray_DIMS(self)[i] */ __pyx_t_4 = __pyx_v_ndim; __pyx_t_5 = __pyx_t_4; for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { __pyx_v_i = __pyx_t_6; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":286 * info.shape = info.strides + ndim * for i in range(ndim): * info.strides[i] = PyArray_STRIDES(self)[i] # <<<<<<<<<<<<<< * info.shape[i] = PyArray_DIMS(self)[i] * else: */ (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(__pyx_v_self)[__pyx_v_i]); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":287 * for i in range(ndim): * info.strides[i] = PyArray_STRIDES(self)[i] * info.shape[i] = PyArray_DIMS(self)[i] # <<<<<<<<<<<<<< * else: * info.strides = PyArray_STRIDES(self) */ (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(__pyx_v_self)[__pyx_v_i]); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":280 * info.buf = PyArray_DATA(self) * info.ndim = ndim * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * # Allocate new buffer for strides and shape info. * # This is allocated as one block, strides first. */ goto __pyx_L9; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":289 * info.shape[i] = PyArray_DIMS(self)[i] * else: * info.strides = PyArray_STRIDES(self) # <<<<<<<<<<<<<< * info.shape = PyArray_DIMS(self) * info.suboffsets = NULL */ /*else*/ { __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(__pyx_v_self)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":290 * else: * info.strides = PyArray_STRIDES(self) * info.shape = PyArray_DIMS(self) # <<<<<<<<<<<<<< * info.suboffsets = NULL * info.itemsize = PyArray_ITEMSIZE(self) */ __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(__pyx_v_self)); } __pyx_L9:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":291 * info.strides = PyArray_STRIDES(self) * info.shape = PyArray_DIMS(self) * info.suboffsets = NULL # <<<<<<<<<<<<<< * info.itemsize = PyArray_ITEMSIZE(self) * info.readonly = not PyArray_ISWRITEABLE(self) */ __pyx_v_info->suboffsets = NULL; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":292 * info.shape = PyArray_DIMS(self) * info.suboffsets = NULL * info.itemsize = PyArray_ITEMSIZE(self) # <<<<<<<<<<<<<< * info.readonly = not PyArray_ISWRITEABLE(self) * */ __pyx_v_info->itemsize = PyArray_ITEMSIZE(__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":293 * info.suboffsets = NULL * info.itemsize = PyArray_ITEMSIZE(self) * info.readonly = not PyArray_ISWRITEABLE(self) # <<<<<<<<<<<<<< * * cdef int t */ __pyx_v_info->readonly = (!(PyArray_ISWRITEABLE(__pyx_v_self) != 0)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":296 * * cdef int t * cdef char* f = NULL # <<<<<<<<<<<<<< * cdef dtype descr = PyArray_DESCR(self) * cdef int offset */ __pyx_v_f = NULL; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":297 * cdef int t * cdef char* f = NULL * cdef dtype descr = PyArray_DESCR(self) # <<<<<<<<<<<<<< * cdef int offset * */ __pyx_t_7 = PyArray_DESCR(__pyx_v_self); __pyx_t_3 = ((PyObject *)__pyx_t_7); __Pyx_INCREF(__pyx_t_3); __pyx_v_descr = ((PyArray_Descr *)__pyx_t_3); __pyx_t_3 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":300 * cdef int offset * * info.obj = self # <<<<<<<<<<<<<< * * if not PyDataType_HASFIELDS(descr): */ __Pyx_INCREF(((PyObject *)__pyx_v_self)); __Pyx_GIVEREF(((PyObject *)__pyx_v_self)); __Pyx_GOTREF(__pyx_v_info->obj); __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = ((PyObject *)__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":302 * info.obj = self * * if not PyDataType_HASFIELDS(descr): # <<<<<<<<<<<<<< * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or */ __pyx_t_1 = ((!(PyDataType_HASFIELDS(__pyx_v_descr) != 0)) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":303 * * if not PyDataType_HASFIELDS(descr): * t = descr.type_num # <<<<<<<<<<<<<< * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): */ __pyx_t_4 = __pyx_v_descr->type_num; __pyx_v_t = __pyx_t_4; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":304 * if not PyDataType_HASFIELDS(descr): * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ __pyx_t_2 = ((__pyx_v_descr->byteorder == '>') != 0); if (!__pyx_t_2) { goto __pyx_L15_next_or; } else { } __pyx_t_2 = (__pyx_v_little_endian != 0); if (!__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L14_bool_binop_done; } __pyx_L15_next_or:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":305 * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): # <<<<<<<<<<<<<< * raise ValueError(u"Non-native byte order not supported") * if t == NPY_BYTE: f = "b" */ __pyx_t_2 = ((__pyx_v_descr->byteorder == '<') != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L14_bool_binop_done; } __pyx_t_2 = ((!(__pyx_v_little_endian != 0)) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L14_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":304 * if not PyDataType_HASFIELDS(descr): * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ if (unlikely(__pyx_t_1)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":306 * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 306, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 306, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":304 * if not PyDataType_HASFIELDS(descr): * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":307 * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") * if t == NPY_BYTE: f = "b" # <<<<<<<<<<<<<< * elif t == NPY_UBYTE: f = "B" * elif t == NPY_SHORT: f = "h" */ switch (__pyx_v_t) { case NPY_BYTE: __pyx_v_f = ((char *)"b"); break; case NPY_UBYTE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":308 * raise ValueError(u"Non-native byte order not supported") * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" # <<<<<<<<<<<<<< * elif t == NPY_SHORT: f = "h" * elif t == NPY_USHORT: f = "H" */ __pyx_v_f = ((char *)"B"); break; case NPY_SHORT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":309 * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" * elif t == NPY_SHORT: f = "h" # <<<<<<<<<<<<<< * elif t == NPY_USHORT: f = "H" * elif t == NPY_INT: f = "i" */ __pyx_v_f = ((char *)"h"); break; case NPY_USHORT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":310 * elif t == NPY_UBYTE: f = "B" * elif t == NPY_SHORT: f = "h" * elif t == NPY_USHORT: f = "H" # <<<<<<<<<<<<<< * elif t == NPY_INT: f = "i" * elif t == NPY_UINT: f = "I" */ __pyx_v_f = ((char *)"H"); break; case NPY_INT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":311 * elif t == NPY_SHORT: f = "h" * elif t == NPY_USHORT: f = "H" * elif t == NPY_INT: f = "i" # <<<<<<<<<<<<<< * elif t == NPY_UINT: f = "I" * elif t == NPY_LONG: f = "l" */ __pyx_v_f = ((char *)"i"); break; case NPY_UINT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":312 * elif t == NPY_USHORT: f = "H" * elif t == NPY_INT: f = "i" * elif t == NPY_UINT: f = "I" # <<<<<<<<<<<<<< * elif t == NPY_LONG: f = "l" * elif t == NPY_ULONG: f = "L" */ __pyx_v_f = ((char *)"I"); break; case NPY_LONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":313 * elif t == NPY_INT: f = "i" * elif t == NPY_UINT: f = "I" * elif t == NPY_LONG: f = "l" # <<<<<<<<<<<<<< * elif t == NPY_ULONG: f = "L" * elif t == NPY_LONGLONG: f = "q" */ __pyx_v_f = ((char *)"l"); break; case NPY_ULONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":314 * elif t == NPY_UINT: f = "I" * elif t == NPY_LONG: f = "l" * elif t == NPY_ULONG: f = "L" # <<<<<<<<<<<<<< * elif t == NPY_LONGLONG: f = "q" * elif t == NPY_ULONGLONG: f = "Q" */ __pyx_v_f = ((char *)"L"); break; case NPY_LONGLONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":315 * elif t == NPY_LONG: f = "l" * elif t == NPY_ULONG: f = "L" * elif t == NPY_LONGLONG: f = "q" # <<<<<<<<<<<<<< * elif t == NPY_ULONGLONG: f = "Q" * elif t == NPY_FLOAT: f = "f" */ __pyx_v_f = ((char *)"q"); break; case NPY_ULONGLONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":316 * elif t == NPY_ULONG: f = "L" * elif t == NPY_LONGLONG: f = "q" * elif t == NPY_ULONGLONG: f = "Q" # <<<<<<<<<<<<<< * elif t == NPY_FLOAT: f = "f" * elif t == NPY_DOUBLE: f = "d" */ __pyx_v_f = ((char *)"Q"); break; case NPY_FLOAT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":317 * elif t == NPY_LONGLONG: f = "q" * elif t == NPY_ULONGLONG: f = "Q" * elif t == NPY_FLOAT: f = "f" # <<<<<<<<<<<<<< * elif t == NPY_DOUBLE: f = "d" * elif t == NPY_LONGDOUBLE: f = "g" */ __pyx_v_f = ((char *)"f"); break; case NPY_DOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":318 * elif t == NPY_ULONGLONG: f = "Q" * elif t == NPY_FLOAT: f = "f" * elif t == NPY_DOUBLE: f = "d" # <<<<<<<<<<<<<< * elif t == NPY_LONGDOUBLE: f = "g" * elif t == NPY_CFLOAT: f = "Zf" */ __pyx_v_f = ((char *)"d"); break; case NPY_LONGDOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":319 * elif t == NPY_FLOAT: f = "f" * elif t == NPY_DOUBLE: f = "d" * elif t == NPY_LONGDOUBLE: f = "g" # <<<<<<<<<<<<<< * elif t == NPY_CFLOAT: f = "Zf" * elif t == NPY_CDOUBLE: f = "Zd" */ __pyx_v_f = ((char *)"g"); break; case NPY_CFLOAT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":320 * elif t == NPY_DOUBLE: f = "d" * elif t == NPY_LONGDOUBLE: f = "g" * elif t == NPY_CFLOAT: f = "Zf" # <<<<<<<<<<<<<< * elif t == NPY_CDOUBLE: f = "Zd" * elif t == NPY_CLONGDOUBLE: f = "Zg" */ __pyx_v_f = ((char *)"Zf"); break; case NPY_CDOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":321 * elif t == NPY_LONGDOUBLE: f = "g" * elif t == NPY_CFLOAT: f = "Zf" * elif t == NPY_CDOUBLE: f = "Zd" # <<<<<<<<<<<<<< * elif t == NPY_CLONGDOUBLE: f = "Zg" * elif t == NPY_OBJECT: f = "O" */ __pyx_v_f = ((char *)"Zd"); break; case NPY_CLONGDOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":322 * elif t == NPY_CFLOAT: f = "Zf" * elif t == NPY_CDOUBLE: f = "Zd" * elif t == NPY_CLONGDOUBLE: f = "Zg" # <<<<<<<<<<<<<< * elif t == NPY_OBJECT: f = "O" * else: */ __pyx_v_f = ((char *)"Zg"); break; case NPY_OBJECT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":323 * elif t == NPY_CDOUBLE: f = "Zd" * elif t == NPY_CLONGDOUBLE: f = "Zg" * elif t == NPY_OBJECT: f = "O" # <<<<<<<<<<<<<< * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) */ __pyx_v_f = ((char *)"O"); break; default: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":325 * elif t == NPY_OBJECT: f = "O" * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) # <<<<<<<<<<<<<< * info.format = f * return */ __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_8 = PyUnicode_Format(__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_t_3); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 325, __pyx_L1_error) break; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":326 * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) * info.format = f # <<<<<<<<<<<<<< * return * else: */ __pyx_v_info->format = __pyx_v_f; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":327 * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) * info.format = f * return # <<<<<<<<<<<<<< * else: * info.format = PyObject_Malloc(_buffer_format_string_len) */ __pyx_r = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":302 * info.obj = self * * if not PyDataType_HASFIELDS(descr): # <<<<<<<<<<<<<< * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":329 * return * else: * info.format = PyObject_Malloc(_buffer_format_string_len) # <<<<<<<<<<<<<< * info.format[0] = c'^' # Native data types, manual alignment * offset = 0 */ /*else*/ { __pyx_v_info->format = ((char *)PyObject_Malloc(0xFF)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":330 * else: * info.format = PyObject_Malloc(_buffer_format_string_len) * info.format[0] = c'^' # Native data types, manual alignment # <<<<<<<<<<<<<< * offset = 0 * f = _util_dtypestring(descr, info.format + 1, */ (__pyx_v_info->format[0]) = '^'; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":331 * info.format = PyObject_Malloc(_buffer_format_string_len) * info.format[0] = c'^' # Native data types, manual alignment * offset = 0 # <<<<<<<<<<<<<< * f = _util_dtypestring(descr, info.format + 1, * info.format + _buffer_format_string_len, */ __pyx_v_offset = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":332 * info.format[0] = c'^' # Native data types, manual alignment * offset = 0 * f = _util_dtypestring(descr, info.format + 1, # <<<<<<<<<<<<<< * info.format + _buffer_format_string_len, * &offset) */ __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 0xFF), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == ((char *)NULL))) __PYX_ERR(1, 332, __pyx_L1_error) __pyx_v_f = __pyx_t_9; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":335 * info.format + _buffer_format_string_len, * &offset) * f[0] = c'\0' # Terminate format string # <<<<<<<<<<<<<< * * def __releasebuffer__(ndarray self, Py_buffer* info): */ (__pyx_v_f[0]) = '\x00'; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":258 * # experimental exception made for __getbuffer__ and __releasebuffer__ * # -- the details of this may change. * def __getbuffer__(ndarray self, Py_buffer* info, int flags): # <<<<<<<<<<<<<< * # This implementation of getbuffer is geared towards Cython * # requirements, and does not yet fulfill the PEP. */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.ndarray.__getbuffer__", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; if (__pyx_v_info->obj != NULL) { __Pyx_GOTREF(__pyx_v_info->obj); __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; } goto __pyx_L2; __pyx_L0:; if (__pyx_v_info->obj == Py_None) { __Pyx_GOTREF(__pyx_v_info->obj); __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; } __pyx_L2:; __Pyx_XDECREF((PyObject *)__pyx_v_descr); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":337 * f[0] = c'\0' # Terminate format string * * def __releasebuffer__(ndarray self, Py_buffer* info): # <<<<<<<<<<<<<< * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) */ /* Python wrapper */ static CYTHON_UNUSED void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/ static CYTHON_UNUSED void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__releasebuffer__ (wrapper)", 0); __pyx_pf_5numpy_7ndarray_2__releasebuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info)); /* function exit code */ __Pyx_RefNannyFinishContext(); } static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info) { __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("__releasebuffer__", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":338 * * def __releasebuffer__(ndarray self, Py_buffer* info): * if PyArray_HASFIELDS(self): # <<<<<<<<<<<<<< * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): */ __pyx_t_1 = (PyArray_HASFIELDS(__pyx_v_self) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":339 * def __releasebuffer__(ndarray self, Py_buffer* info): * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) # <<<<<<<<<<<<<< * if sizeof(npy_intp) != sizeof(Py_ssize_t): * PyObject_Free(info.strides) */ PyObject_Free(__pyx_v_info->format); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":338 * * def __releasebuffer__(ndarray self, Py_buffer* info): * if PyArray_HASFIELDS(self): # <<<<<<<<<<<<<< * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":340 * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * PyObject_Free(info.strides) * # info.shape was stored after info.strides in the same block */ __pyx_t_1 = (((sizeof(npy_intp)) != (sizeof(Py_ssize_t))) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":341 * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): * PyObject_Free(info.strides) # <<<<<<<<<<<<<< * # info.shape was stored after info.strides in the same block * */ PyObject_Free(__pyx_v_info->strides); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":340 * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * PyObject_Free(info.strides) * # info.shape was stored after info.strides in the same block */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":337 * f[0] = c'\0' # Terminate format string * * def __releasebuffer__(ndarray self, Py_buffer* info): # <<<<<<<<<<<<<< * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) */ /* function exit code */ __Pyx_RefNannyFinishContext(); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":821 * ctypedef npy_cdouble complex_t * * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(1, a) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":822 * * cdef inline object PyArray_MultiIterNew1(a): * return PyArray_MultiIterNew(1, a) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew2(a, b): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 822, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":821 * ctypedef npy_cdouble complex_t * * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(1, a) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":824 * return PyArray_MultiIterNew(1, a) * * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(2, a, b) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":825 * * cdef inline object PyArray_MultiIterNew2(a, b): * return PyArray_MultiIterNew(2, a, b) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew3(a, b, c): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 825, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":824 * return PyArray_MultiIterNew(1, a) * * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(2, a, b) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":827 * return PyArray_MultiIterNew(2, a, b) * * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(3, a, b, c) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":828 * * cdef inline object PyArray_MultiIterNew3(a, b, c): * return PyArray_MultiIterNew(3, a, b, c) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 828, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":827 * return PyArray_MultiIterNew(2, a, b) * * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(3, a, b, c) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":830 * return PyArray_MultiIterNew(3, a, b, c) * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(4, a, b, c, d) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":831 * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): * return PyArray_MultiIterNew(4, a, b, c, d) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 831, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":830 * return PyArray_MultiIterNew(3, a, b, c) * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(4, a, b, c, d) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":833 * return PyArray_MultiIterNew(4, a, b, c, d) * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(5, a, b, c, d, e) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":834 * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): * return PyArray_MultiIterNew(5, a, b, c, d, e) # <<<<<<<<<<<<<< * * cdef inline tuple PyDataType_SHAPE(dtype d): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 834, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":833 * return PyArray_MultiIterNew(4, a, b, c, d) * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(5, a, b, c, d, e) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":836 * return PyArray_MultiIterNew(5, a, b, c, d, e) * * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__pyx_v_d) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("PyDataType_SHAPE", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":837 * * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< * return d.subarray.shape * else: */ __pyx_t_1 = (PyDataType_HASSUBARRAY(__pyx_v_d) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":838 * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape # <<<<<<<<<<<<<< * else: * return () */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(((PyObject*)__pyx_v_d->subarray->shape)); __pyx_r = ((PyObject*)__pyx_v_d->subarray->shape); goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":837 * * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< * return d.subarray.shape * else: */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":840 * return d.subarray.shape * else: * return () # <<<<<<<<<<<<<< * * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: */ /*else*/ { __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(__pyx_empty_tuple); __pyx_r = __pyx_empty_tuple; goto __pyx_L0; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":836 * return PyArray_MultiIterNew(5, a, b, c, d, e) * * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape */ /* function exit code */ __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":842 * return () * * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: # <<<<<<<<<<<<<< * # Recursive utility function used in __getbuffer__ to get format * # string. The new location in the format string is returned. */ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx_v_descr, char *__pyx_v_f, char *__pyx_v_end, int *__pyx_v_offset) { PyArray_Descr *__pyx_v_child = 0; int __pyx_v_endian_detector; int __pyx_v_little_endian; PyObject *__pyx_v_fields = 0; PyObject *__pyx_v_childname = NULL; PyObject *__pyx_v_new_offset = NULL; PyObject *__pyx_v_t = NULL; char *__pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; Py_ssize_t __pyx_t_2; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; int __pyx_t_5; int __pyx_t_6; int __pyx_t_7; long __pyx_t_8; char *__pyx_t_9; __Pyx_RefNannySetupContext("_util_dtypestring", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":847 * * cdef dtype child * cdef int endian_detector = 1 # <<<<<<<<<<<<<< * cdef bint little_endian = ((&endian_detector)[0] != 0) * cdef tuple fields */ __pyx_v_endian_detector = 1; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":848 * cdef dtype child * cdef int endian_detector = 1 * cdef bint little_endian = ((&endian_detector)[0] != 0) # <<<<<<<<<<<<<< * cdef tuple fields * */ __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":851 * cdef tuple fields * * for childname in descr.names: # <<<<<<<<<<<<<< * fields = descr.fields[childname] * child, new_offset = fields */ if (unlikely(__pyx_v_descr->names == Py_None)) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); __PYX_ERR(1, 851, __pyx_L1_error) } __pyx_t_1 = __pyx_v_descr->names; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0; for (;;) { if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break; #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) __PYX_ERR(1, 851, __pyx_L1_error) #else __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 851, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); #endif __Pyx_XDECREF_SET(__pyx_v_childname, __pyx_t_3); __pyx_t_3 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":852 * * for childname in descr.names: * fields = descr.fields[childname] # <<<<<<<<<<<<<< * child, new_offset = fields * */ if (unlikely(__pyx_v_descr->fields == Py_None)) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); __PYX_ERR(1, 852, __pyx_L1_error) } __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 852, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(1, 852, __pyx_L1_error) __Pyx_XDECREF_SET(__pyx_v_fields, ((PyObject*)__pyx_t_3)); __pyx_t_3 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":853 * for childname in descr.names: * fields = descr.fields[childname] * child, new_offset = fields # <<<<<<<<<<<<<< * * if (end - f) - (new_offset - offset[0]) < 15: */ if (likely(__pyx_v_fields != Py_None)) { PyObject* sequence = __pyx_v_fields; Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); if (unlikely(size != 2)) { if (size > 2) __Pyx_RaiseTooManyValuesError(2); else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); __PYX_ERR(1, 853, __pyx_L1_error) } #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); __Pyx_INCREF(__pyx_t_3); __Pyx_INCREF(__pyx_t_4); #else __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 853, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 853, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); #endif } else { __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(1, 853, __pyx_L1_error) } if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) __PYX_ERR(1, 853, __pyx_L1_error) __Pyx_XDECREF_SET(__pyx_v_child, ((PyArray_Descr *)__pyx_t_3)); __pyx_t_3 = 0; __Pyx_XDECREF_SET(__pyx_v_new_offset, __pyx_t_4); __pyx_t_4 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":855 * child, new_offset = fields * * if (end - f) - (new_offset - offset[0]) < 15: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * */ __pyx_t_4 = __Pyx_PyInt_From_int((__pyx_v_offset[0])); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 855, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 855, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_5 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_5 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 855, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = ((((__pyx_v_end - __pyx_v_f) - ((int)__pyx_t_5)) < 15) != 0); if (unlikely(__pyx_t_6)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":856 * * if (end - f) - (new_offset - offset[0]) < 15: * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") # <<<<<<<<<<<<<< * * if ((child.byteorder == c'>' and little_endian) or */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 856, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 856, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":855 * child, new_offset = fields * * if (end - f) - (new_offset - offset[0]) < 15: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":858 * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ __pyx_t_7 = ((__pyx_v_child->byteorder == '>') != 0); if (!__pyx_t_7) { goto __pyx_L8_next_or; } else { } __pyx_t_7 = (__pyx_v_little_endian != 0); if (!__pyx_t_7) { } else { __pyx_t_6 = __pyx_t_7; goto __pyx_L7_bool_binop_done; } __pyx_L8_next_or:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":859 * * if ((child.byteorder == c'>' and little_endian) or * (child.byteorder == c'<' and not little_endian)): # <<<<<<<<<<<<<< * raise ValueError(u"Non-native byte order not supported") * # One could encode it in the format string and have Cython */ __pyx_t_7 = ((__pyx_v_child->byteorder == '<') != 0); if (__pyx_t_7) { } else { __pyx_t_6 = __pyx_t_7; goto __pyx_L7_bool_binop_done; } __pyx_t_7 = ((!(__pyx_v_little_endian != 0)) != 0); __pyx_t_6 = __pyx_t_7; __pyx_L7_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":858 * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ if (unlikely(__pyx_t_6)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":860 * if ((child.byteorder == c'>' and little_endian) or * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< * # One could encode it in the format string and have Cython * # complain instead, BUT: < and > in format strings also imply */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 860, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 860, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":858 * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":870 * * # Output padding bytes * while offset[0] < new_offset: # <<<<<<<<<<<<<< * f[0] = 120 # "x"; pad byte * f += 1 */ while (1) { __pyx_t_3 = __Pyx_PyInt_From_int((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 870, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_t_3, __pyx_v_new_offset, Py_LT); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 870, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 870, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (!__pyx_t_6) break; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":871 * # Output padding bytes * while offset[0] < new_offset: * f[0] = 120 # "x"; pad byte # <<<<<<<<<<<<<< * f += 1 * offset[0] += 1 */ (__pyx_v_f[0]) = 0x78; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":872 * while offset[0] < new_offset: * f[0] = 120 # "x"; pad byte * f += 1 # <<<<<<<<<<<<<< * offset[0] += 1 * */ __pyx_v_f = (__pyx_v_f + 1); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":873 * f[0] = 120 # "x"; pad byte * f += 1 * offset[0] += 1 # <<<<<<<<<<<<<< * * offset[0] += child.itemsize */ __pyx_t_8 = 0; (__pyx_v_offset[__pyx_t_8]) = ((__pyx_v_offset[__pyx_t_8]) + 1); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":875 * offset[0] += 1 * * offset[0] += child.itemsize # <<<<<<<<<<<<<< * * if not PyDataType_HASFIELDS(child): */ __pyx_t_8 = 0; (__pyx_v_offset[__pyx_t_8]) = ((__pyx_v_offset[__pyx_t_8]) + __pyx_v_child->elsize); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":877 * offset[0] += child.itemsize * * if not PyDataType_HASFIELDS(child): # <<<<<<<<<<<<<< * t = child.type_num * if end - f < 5: */ __pyx_t_6 = ((!(PyDataType_HASFIELDS(__pyx_v_child) != 0)) != 0); if (__pyx_t_6) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":878 * * if not PyDataType_HASFIELDS(child): * t = child.type_num # <<<<<<<<<<<<<< * if end - f < 5: * raise RuntimeError(u"Format string allocated too short.") */ __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_child->type_num); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 878, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_4); __pyx_t_4 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":879 * if not PyDataType_HASFIELDS(child): * t = child.type_num * if end - f < 5: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short.") * */ __pyx_t_6 = (((__pyx_v_end - __pyx_v_f) < 5) != 0); if (unlikely(__pyx_t_6)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":880 * t = child.type_num * if end - f < 5: * raise RuntimeError(u"Format string allocated too short.") # <<<<<<<<<<<<<< * * # Until ticket #99 is fixed, use integers to avoid warnings */ __pyx_t_4 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_tuple__6, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 880, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_Raise(__pyx_t_4, 0, 0, 0); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __PYX_ERR(1, 880, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":879 * if not PyDataType_HASFIELDS(child): * t = child.type_num * if end - f < 5: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short.") * */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":883 * * # Until ticket #99 is fixed, use integers to avoid warnings * if t == NPY_BYTE: f[0] = 98 #"b" # <<<<<<<<<<<<<< * elif t == NPY_UBYTE: f[0] = 66 #"B" * elif t == NPY_SHORT: f[0] = 104 #"h" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_BYTE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 883, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 883, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 883, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 98; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":884 * # Until ticket #99 is fixed, use integers to avoid warnings * if t == NPY_BYTE: f[0] = 98 #"b" * elif t == NPY_UBYTE: f[0] = 66 #"B" # <<<<<<<<<<<<<< * elif t == NPY_SHORT: f[0] = 104 #"h" * elif t == NPY_USHORT: f[0] = 72 #"H" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_UBYTE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 884, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 884, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 884, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 66; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":885 * if t == NPY_BYTE: f[0] = 98 #"b" * elif t == NPY_UBYTE: f[0] = 66 #"B" * elif t == NPY_SHORT: f[0] = 104 #"h" # <<<<<<<<<<<<<< * elif t == NPY_USHORT: f[0] = 72 #"H" * elif t == NPY_INT: f[0] = 105 #"i" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_SHORT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 885, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 885, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 885, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x68; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":886 * elif t == NPY_UBYTE: f[0] = 66 #"B" * elif t == NPY_SHORT: f[0] = 104 #"h" * elif t == NPY_USHORT: f[0] = 72 #"H" # <<<<<<<<<<<<<< * elif t == NPY_INT: f[0] = 105 #"i" * elif t == NPY_UINT: f[0] = 73 #"I" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_USHORT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 886, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 886, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 886, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 72; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":887 * elif t == NPY_SHORT: f[0] = 104 #"h" * elif t == NPY_USHORT: f[0] = 72 #"H" * elif t == NPY_INT: f[0] = 105 #"i" # <<<<<<<<<<<<<< * elif t == NPY_UINT: f[0] = 73 #"I" * elif t == NPY_LONG: f[0] = 108 #"l" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_INT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 887, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 887, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 887, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x69; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":888 * elif t == NPY_USHORT: f[0] = 72 #"H" * elif t == NPY_INT: f[0] = 105 #"i" * elif t == NPY_UINT: f[0] = 73 #"I" # <<<<<<<<<<<<<< * elif t == NPY_LONG: f[0] = 108 #"l" * elif t == NPY_ULONG: f[0] = 76 #"L" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_UINT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 888, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 888, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 888, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 73; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":889 * elif t == NPY_INT: f[0] = 105 #"i" * elif t == NPY_UINT: f[0] = 73 #"I" * elif t == NPY_LONG: f[0] = 108 #"l" # <<<<<<<<<<<<<< * elif t == NPY_ULONG: f[0] = 76 #"L" * elif t == NPY_LONGLONG: f[0] = 113 #"q" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONG); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 889, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 889, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 889, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x6C; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":890 * elif t == NPY_UINT: f[0] = 73 #"I" * elif t == NPY_LONG: f[0] = 108 #"l" * elif t == NPY_ULONG: f[0] = 76 #"L" # <<<<<<<<<<<<<< * elif t == NPY_LONGLONG: f[0] = 113 #"q" * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_ULONG); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 890, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 890, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 890, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 76; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":891 * elif t == NPY_LONG: f[0] = 108 #"l" * elif t == NPY_ULONG: f[0] = 76 #"L" * elif t == NPY_LONGLONG: f[0] = 113 #"q" # <<<<<<<<<<<<<< * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" * elif t == NPY_FLOAT: f[0] = 102 #"f" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONGLONG); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 891, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 891, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 891, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x71; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":892 * elif t == NPY_ULONG: f[0] = 76 #"L" * elif t == NPY_LONGLONG: f[0] = 113 #"q" * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" # <<<<<<<<<<<<<< * elif t == NPY_FLOAT: f[0] = 102 #"f" * elif t == NPY_DOUBLE: f[0] = 100 #"d" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_ULONGLONG); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 892, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 892, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 892, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 81; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":893 * elif t == NPY_LONGLONG: f[0] = 113 #"q" * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" * elif t == NPY_FLOAT: f[0] = 102 #"f" # <<<<<<<<<<<<<< * elif t == NPY_DOUBLE: f[0] = 100 #"d" * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_FLOAT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 893, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 893, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 893, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x66; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":894 * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" * elif t == NPY_FLOAT: f[0] = 102 #"f" * elif t == NPY_DOUBLE: f[0] = 100 #"d" # <<<<<<<<<<<<<< * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_DOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 894, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 894, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 894, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x64; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":895 * elif t == NPY_FLOAT: f[0] = 102 #"f" * elif t == NPY_DOUBLE: f[0] = 100 #"d" * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" # <<<<<<<<<<<<<< * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 895, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 895, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 895, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x67; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":896 * elif t == NPY_DOUBLE: f[0] = 100 #"d" * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf # <<<<<<<<<<<<<< * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CFLOAT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 896, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 896, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 896, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 90; (__pyx_v_f[1]) = 0x66; __pyx_v_f = (__pyx_v_f + 1); goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":897 * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd # <<<<<<<<<<<<<< * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg * elif t == NPY_OBJECT: f[0] = 79 #"O" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CDOUBLE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 897, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 897, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 897, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 90; (__pyx_v_f[1]) = 0x64; __pyx_v_f = (__pyx_v_f + 1); goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":898 * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg # <<<<<<<<<<<<<< * elif t == NPY_OBJECT: f[0] = 79 #"O" * else: */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 898, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 898, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 898, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 90; (__pyx_v_f[1]) = 0x67; __pyx_v_f = (__pyx_v_f + 1); goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":899 * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg * elif t == NPY_OBJECT: f[0] = 79 #"O" # <<<<<<<<<<<<<< * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_OBJECT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 899, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 899, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 899, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (likely(__pyx_t_6)) { (__pyx_v_f[0]) = 79; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":901 * elif t == NPY_OBJECT: f[0] = 79 #"O" * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) # <<<<<<<<<<<<<< * f += 1 * else: */ /*else*/ { __pyx_t_3 = __Pyx_PyUnicode_FormatSafe(__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_v_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 901, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 901, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_Raise(__pyx_t_4, 0, 0, 0); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __PYX_ERR(1, 901, __pyx_L1_error) } __pyx_L15:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":902 * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) * f += 1 # <<<<<<<<<<<<<< * else: * # Cython ignores struct boundary information ("T{...}"), */ __pyx_v_f = (__pyx_v_f + 1); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":877 * offset[0] += child.itemsize * * if not PyDataType_HASFIELDS(child): # <<<<<<<<<<<<<< * t = child.type_num * if end - f < 5: */ goto __pyx_L13; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":906 * # Cython ignores struct boundary information ("T{...}"), * # so don't output it * f = _util_dtypestring(child, f, end, offset) # <<<<<<<<<<<<<< * return f * */ /*else*/ { __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_9 == ((char *)NULL))) __PYX_ERR(1, 906, __pyx_L1_error) __pyx_v_f = __pyx_t_9; } __pyx_L13:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":851 * cdef tuple fields * * for childname in descr.names: # <<<<<<<<<<<<<< * fields = descr.fields[childname] * child, new_offset = fields */ } __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":907 * # so don't output it * f = _util_dtypestring(child, f, end, offset) * return f # <<<<<<<<<<<<<< * * */ __pyx_r = __pyx_v_f; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":842 * return () * * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: # <<<<<<<<<<<<<< * # Recursive utility function used in __getbuffer__ to get format * # string. The new location in the format string is returned. */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __Pyx_AddTraceback("numpy._util_dtypestring", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XDECREF((PyObject *)__pyx_v_child); __Pyx_XDECREF(__pyx_v_fields); __Pyx_XDECREF(__pyx_v_childname); __Pyx_XDECREF(__pyx_v_new_offset); __Pyx_XDECREF(__pyx_v_t); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1022 * int _import_umath() except -1 * * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) */ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("set_array_base", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1023 * * cdef inline void set_array_base(ndarray arr, object base): * Py_INCREF(base) # important to do this before stealing the reference below! # <<<<<<<<<<<<<< * PyArray_SetBaseObject(arr, base) * */ Py_INCREF(__pyx_v_base); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1024 * cdef inline void set_array_base(ndarray arr, object base): * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) # <<<<<<<<<<<<<< * * cdef inline object get_array_base(ndarray arr): */ (void)(PyArray_SetBaseObject(__pyx_v_arr, __pyx_v_base)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1022 * int _import_umath() except -1 * * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) */ /* function exit code */ __Pyx_RefNannyFinishContext(); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1026 * PyArray_SetBaseObject(arr, base) * * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< * base = PyArray_BASE(arr) * if base is NULL: */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) { PyObject *__pyx_v_base; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("get_array_base", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1027 * * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) # <<<<<<<<<<<<<< * if base is NULL: * return None */ __pyx_v_base = PyArray_BASE(__pyx_v_arr); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1028 * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) * if base is NULL: # <<<<<<<<<<<<<< * return None * return base */ __pyx_t_1 = ((__pyx_v_base == NULL) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1029 * base = PyArray_BASE(arr) * if base is NULL: * return None # <<<<<<<<<<<<<< * return base * */ __Pyx_XDECREF(__pyx_r); __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1028 * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) * if base is NULL: # <<<<<<<<<<<<<< * return None * return base */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1030 * if base is NULL: * return None * return base # <<<<<<<<<<<<<< * * # Versions of the import_* functions which are more suitable for */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(((PyObject *)__pyx_v_base)); __pyx_r = ((PyObject *)__pyx_v_base); goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1026 * PyArray_SetBaseObject(arr, base) * * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< * base = PyArray_BASE(arr) * if base is NULL: */ /* function exit code */ __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1034 * # Versions of the import_* functions which are more suitable for * # Cython code. * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< * try: * _import_array() */ static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; __Pyx_RefNannySetupContext("import_array", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1035 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< * _import_array() * except Exception: */ { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); __Pyx_XGOTREF(__pyx_t_1); __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1036 * cdef inline int import_array() except -1: * try: * _import_array() # <<<<<<<<<<<<<< * except Exception: * raise ImportError("numpy.core.multiarray failed to import") */ __pyx_t_4 = _import_array(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1036, __pyx_L3_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1035 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< * _import_array() * except Exception: */ } __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L8_try_end; __pyx_L3_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1037 * try: * _import_array() * except Exception: # <<<<<<<<<<<<<< * raise ImportError("numpy.core.multiarray failed to import") * */ __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); if (__pyx_t_4) { __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1037, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1038 * _import_array() * except Exception: * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_umath() except -1: */ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1038, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(1, 1038, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1035 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< * _import_array() * except Exception: */ __Pyx_XGIVEREF(__pyx_t_1); __Pyx_XGIVEREF(__pyx_t_2); __Pyx_XGIVEREF(__pyx_t_3); __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); goto __pyx_L1_error; __pyx_L8_try_end:; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1034 * # Versions of the import_* functions which are more suitable for * # Cython code. * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< * try: * _import_array() */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1040 * raise ImportError("numpy.core.multiarray failed to import") * * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; __Pyx_RefNannySetupContext("import_umath", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1041 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); __Pyx_XGOTREF(__pyx_t_1); __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1042 * cdef inline int import_umath() except -1: * try: * _import_umath() # <<<<<<<<<<<<<< * except Exception: * raise ImportError("numpy.core.umath failed to import") */ __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1042, __pyx_L3_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1041 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ } __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L8_try_end; __pyx_L3_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1043 * try: * _import_umath() * except Exception: # <<<<<<<<<<<<<< * raise ImportError("numpy.core.umath failed to import") * */ __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); if (__pyx_t_4) { __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1043, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1044 * _import_umath() * except Exception: * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_ufunc() except -1: */ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__8, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1044, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(1, 1044, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1041 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ __Pyx_XGIVEREF(__pyx_t_1); __Pyx_XGIVEREF(__pyx_t_2); __Pyx_XGIVEREF(__pyx_t_3); __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); goto __pyx_L1_error; __pyx_L8_try_end:; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1040 * raise ImportError("numpy.core.multiarray failed to import") * * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1046 * raise ImportError("numpy.core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; __Pyx_RefNannySetupContext("import_ufunc", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1047 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); __Pyx_XGOTREF(__pyx_t_1); __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1048 * cdef inline int import_ufunc() except -1: * try: * _import_umath() # <<<<<<<<<<<<<< * except Exception: * raise ImportError("numpy.core.umath failed to import") */ __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1048, __pyx_L3_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1047 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ } __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L8_try_end; __pyx_L3_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1049 * try: * _import_umath() * except Exception: # <<<<<<<<<<<<<< * raise ImportError("numpy.core.umath failed to import") */ __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); if (__pyx_t_4) { __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1049, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1050 * _import_umath() * except Exception: * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< */ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__8, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1050, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(1, 1050, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1047 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ __Pyx_XGIVEREF(__pyx_t_1); __Pyx_XGIVEREF(__pyx_t_2); __Pyx_XGIVEREF(__pyx_t_3); __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); goto __pyx_L1_error; __pyx_L8_try_end:; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1046 * raise ImportError("numpy.core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } static PyMethodDef __pyx_methods[] = { {0, 0, 0, 0} }; #if PY_MAJOR_VERSION >= 3 #if CYTHON_PEP489_MULTI_PHASE_INIT static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ static int __pyx_pymod_exec_core(PyObject* module); /*proto*/ static PyModuleDef_Slot __pyx_moduledef_slots[] = { {Py_mod_create, (void*)__pyx_pymod_create}, {Py_mod_exec, (void*)__pyx_pymod_exec_core}, {0, NULL} }; #endif static struct PyModuleDef __pyx_moduledef = { PyModuleDef_HEAD_INIT, "core", __pyx_k_The_functions_here_are_the_core, /* m_doc */ #if CYTHON_PEP489_MULTI_PHASE_INIT 0, /* m_size */ #else -1, /* m_size */ #endif __pyx_methods /* m_methods */, #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_moduledef_slots, /* m_slots */ #else NULL, /* m_reload */ #endif NULL, /* m_traverse */ NULL, /* m_clear */ NULL /* m_free */ }; #endif #ifndef CYTHON_SMALL_CODE #if defined(__clang__) #define CYTHON_SMALL_CODE #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) #define CYTHON_SMALL_CODE __attribute__((cold)) #else #define CYTHON_SMALL_CODE #endif #endif static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_DTYPE, __pyx_k_DTYPE, sizeof(__pyx_k_DTYPE), 0, 0, 1, 1}, {&__pyx_kp_u_ERROR_vertices_did_not_sort_corr, __pyx_k_ERROR_vertices_did_not_sort_corr, sizeof(__pyx_k_ERROR_vertices_did_not_sort_corr), 0, 1, 0, 0}, {&__pyx_kp_u_Format_string_allocated_too_shor, __pyx_k_Format_string_allocated_too_shor, sizeof(__pyx_k_Format_string_allocated_too_shor), 0, 1, 0, 0}, {&__pyx_kp_u_Format_string_allocated_too_shor_2, __pyx_k_Format_string_allocated_too_shor_2, sizeof(__pyx_k_Format_string_allocated_too_shor_2), 0, 1, 0, 0}, {&__pyx_n_s_ImportError, __pyx_k_ImportError, sizeof(__pyx_k_ImportError), 0, 0, 1, 1}, {&__pyx_kp_u_Non_native_byte_order_not_suppor, __pyx_k_Non_native_byte_order_not_suppor, sizeof(__pyx_k_Non_native_byte_order_not_suppor), 0, 1, 0, 0}, {&__pyx_n_s_RuntimeError, __pyx_k_RuntimeError, sizeof(__pyx_k_RuntimeError), 0, 0, 1, 1}, {&__pyx_n_s_ValueError, __pyx_k_ValueError, sizeof(__pyx_k_ValueError), 0, 0, 1, 1}, {&__pyx_n_s_all, __pyx_k_all, sizeof(__pyx_k_all), 0, 0, 1, 1}, {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, {&__pyx_n_u_elliptical_overlap_grid, __pyx_k_elliptical_overlap_grid, sizeof(__pyx_k_elliptical_overlap_grid), 0, 1, 0, 1}, {&__pyx_n_s_float64, __pyx_k_float64, sizeof(__pyx_k_float64), 0, 0, 1, 1}, {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, {&__pyx_kp_u_ndarray_is_not_C_contiguous, __pyx_k_ndarray_is_not_C_contiguous, sizeof(__pyx_k_ndarray_is_not_C_contiguous), 0, 1, 0, 0}, {&__pyx_kp_u_ndarray_is_not_Fortran_contiguou, __pyx_k_ndarray_is_not_Fortran_contiguou, sizeof(__pyx_k_ndarray_is_not_Fortran_contiguou), 0, 1, 0, 0}, {&__pyx_n_s_np, __pyx_k_np, sizeof(__pyx_k_np), 0, 0, 1, 1}, {&__pyx_n_s_numpy, __pyx_k_numpy, sizeof(__pyx_k_numpy), 0, 0, 1, 1}, {&__pyx_kp_u_numpy_core_multiarray_failed_to, __pyx_k_numpy_core_multiarray_failed_to, sizeof(__pyx_k_numpy_core_multiarray_failed_to), 0, 1, 0, 0}, {&__pyx_kp_u_numpy_core_umath_failed_to_impor, __pyx_k_numpy_core_umath_failed_to_impor, sizeof(__pyx_k_numpy_core_umath_failed_to_impor), 0, 1, 0, 0}, {&__pyx_n_s_pi, __pyx_k_pi, sizeof(__pyx_k_pi), 0, 0, 1, 1}, {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, {&__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_k_unknown_dtype_code_in_numpy_pxd, sizeof(__pyx_k_unknown_dtype_code_in_numpy_pxd), 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0} }; static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) __PYX_ERR(1, 272, __pyx_L1_error) __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(1, 285, __pyx_L1_error) __pyx_builtin_RuntimeError = __Pyx_GetBuiltinName(__pyx_n_s_RuntimeError); if (!__pyx_builtin_RuntimeError) __PYX_ERR(1, 856, __pyx_L1_error) __pyx_builtin_ImportError = __Pyx_GetBuiltinName(__pyx_n_s_ImportError); if (!__pyx_builtin_ImportError) __PYX_ERR(1, 1038, __pyx_L1_error) return 0; __pyx_L1_error:; return -1; } static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); /* "photutils/geometry/core.pyx":298 * * if d1 > d2 or d2 > d3 or d1 > d3: * raise Exception("ERROR: vertices did not sort correctly") # <<<<<<<<<<<<<< * * # Determine number of vertices inside circle */ __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_u_ERROR_vertices_did_not_sort_corr); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 298, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple_); __Pyx_GIVEREF(__pyx_tuple_); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":272 * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") # <<<<<<<<<<<<<< * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) */ __pyx_tuple__2 = PyTuple_Pack(1, __pyx_kp_u_ndarray_is_not_C_contiguous); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(1, 272, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__2); __Pyx_GIVEREF(__pyx_tuple__2); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":276 * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") # <<<<<<<<<<<<<< * * info.buf = PyArray_DATA(self) */ __pyx_tuple__3 = PyTuple_Pack(1, __pyx_kp_u_ndarray_is_not_Fortran_contiguou); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(1, 276, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__3); __Pyx_GIVEREF(__pyx_tuple__3); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":306 * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" */ __pyx_tuple__4 = PyTuple_Pack(1, __pyx_kp_u_Non_native_byte_order_not_suppor); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(1, 306, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__4); __Pyx_GIVEREF(__pyx_tuple__4); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":856 * * if (end - f) - (new_offset - offset[0]) < 15: * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") # <<<<<<<<<<<<<< * * if ((child.byteorder == c'>' and little_endian) or */ __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_u_Format_string_allocated_too_shor); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(1, 856, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__5); __Pyx_GIVEREF(__pyx_tuple__5); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":880 * t = child.type_num * if end - f < 5: * raise RuntimeError(u"Format string allocated too short.") # <<<<<<<<<<<<<< * * # Until ticket #99 is fixed, use integers to avoid warnings */ __pyx_tuple__6 = PyTuple_Pack(1, __pyx_kp_u_Format_string_allocated_too_shor_2); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(1, 880, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__6); __Pyx_GIVEREF(__pyx_tuple__6); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1038 * _import_array() * except Exception: * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_umath() except -1: */ __pyx_tuple__7 = PyTuple_Pack(1, __pyx_kp_u_numpy_core_multiarray_failed_to); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(1, 1038, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__7); __Pyx_GIVEREF(__pyx_tuple__7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1044 * _import_umath() * except Exception: * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_ufunc() except -1: */ __pyx_tuple__8 = PyTuple_Pack(1, __pyx_kp_u_numpy_core_umath_failed_to_impor); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(1, 1044, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__8); __Pyx_GIVEREF(__pyx_tuple__8); __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; __Pyx_RefNannyFinishContext(); return -1; } static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); return 0; __pyx_L1_error:; return -1; } static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ static int __Pyx_modinit_global_init_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); /*--- Global init code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_variable_export_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); /*--- Variable export code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_function_export_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); /*--- Function export code ---*/ if (__Pyx_ExportFunction("distance", (void (*)(void))__pyx_f_9photutils_8geometry_4core_distance, "double (double, double, double, double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) if (__Pyx_ExportFunction("area_arc", (void (*)(void))__pyx_f_9photutils_8geometry_4core_area_arc, "double (double, double, double, double, double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) if (__Pyx_ExportFunction("area_triangle", (void (*)(void))__pyx_f_9photutils_8geometry_4core_area_triangle, "double (double, double, double, double, double, double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) if (__Pyx_ExportFunction("area_arc_unit", (void (*)(void))__pyx_f_9photutils_8geometry_4core_area_arc_unit, "double (double, double, double, double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) if (__Pyx_ExportFunction("in_triangle", (void (*)(void))__pyx_f_9photutils_8geometry_4core_in_triangle, "int (double, double, double, double, double, double, double, double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) if (__Pyx_ExportFunction("overlap_area_triangle_unit_circle", (void (*)(void))__pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle, "double (double, double, double, double, double, double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) if (__Pyx_ExportFunction("floor_sqrt", (void (*)(void))__pyx_f_9photutils_8geometry_4core_floor_sqrt, "double (double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; __Pyx_RefNannyFinishContext(); return -1; } static int __Pyx_modinit_type_init_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); /*--- Type init code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_type_import_code(void) { __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); /*--- Type import code ---*/ __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 9, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 sizeof(PyTypeObject), #else sizeof(PyHeapTypeObject), #endif __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_7cpython_4type_type) __PYX_ERR(2, 9, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(3, 8, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_7cpython_4bool_bool = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "bool", sizeof(PyBoolObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_7cpython_4bool_bool) __PYX_ERR(3, 8, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(4, 15, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_7cpython_7complex_complex = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "complex", sizeof(PyComplexObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_7cpython_7complex_complex) __PYX_ERR(4, 15, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = PyImport_ImportModule("numpy"); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 206, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_5numpy_dtype = __Pyx_ImportType(__pyx_t_1, "numpy", "dtype", sizeof(PyArray_Descr), __Pyx_ImportType_CheckSize_Ignore); if (!__pyx_ptype_5numpy_dtype) __PYX_ERR(1, 206, __pyx_L1_error) __pyx_ptype_5numpy_flatiter = __Pyx_ImportType(__pyx_t_1, "numpy", "flatiter", sizeof(PyArrayIterObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_5numpy_flatiter) __PYX_ERR(1, 229, __pyx_L1_error) __pyx_ptype_5numpy_broadcast = __Pyx_ImportType(__pyx_t_1, "numpy", "broadcast", sizeof(PyArrayMultiIterObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_5numpy_broadcast) __PYX_ERR(1, 233, __pyx_L1_error) __pyx_ptype_5numpy_ndarray = __Pyx_ImportType(__pyx_t_1, "numpy", "ndarray", sizeof(PyArrayObject), __Pyx_ImportType_CheckSize_Ignore); if (!__pyx_ptype_5numpy_ndarray) __PYX_ERR(1, 242, __pyx_L1_error) __pyx_ptype_5numpy_ufunc = __Pyx_ImportType(__pyx_t_1, "numpy", "ufunc", sizeof(PyUFuncObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_5numpy_ufunc) __PYX_ERR(1, 918, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_RefNannyFinishContext(); return -1; } static int __Pyx_modinit_variable_import_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); /*--- Variable import code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_function_import_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); /*--- Function import code ---*/ __Pyx_RefNannyFinishContext(); return 0; } #if PY_MAJOR_VERSION < 3 #ifdef CYTHON_NO_PYINIT_EXPORT #define __Pyx_PyMODINIT_FUNC void #else #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC #endif #else #ifdef CYTHON_NO_PYINIT_EXPORT #define __Pyx_PyMODINIT_FUNC PyObject * #else #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC #endif #endif #if PY_MAJOR_VERSION < 3 __Pyx_PyMODINIT_FUNC initcore(void) CYTHON_SMALL_CODE; /*proto*/ __Pyx_PyMODINIT_FUNC initcore(void) #else __Pyx_PyMODINIT_FUNC PyInit_core(void) CYTHON_SMALL_CODE; /*proto*/ __Pyx_PyMODINIT_FUNC PyInit_core(void) #if CYTHON_PEP489_MULTI_PHASE_INIT { return PyModuleDef_Init(&__pyx_moduledef); } static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { #if PY_VERSION_HEX >= 0x030700A1 static PY_INT64_T main_interpreter_id = -1; PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); if (main_interpreter_id == -1) { main_interpreter_id = current_id; return (unlikely(current_id == -1)) ? -1 : 0; } else if (unlikely(main_interpreter_id != current_id)) #else static PyInterpreterState *main_interpreter = NULL; PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; if (!main_interpreter) { main_interpreter = current_interpreter; } else if (unlikely(main_interpreter != current_interpreter)) #endif { PyErr_SetString( PyExc_ImportError, "Interpreter change detected - this module can only be loaded into one interpreter per process."); return -1; } return 0; } static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { PyObject *value = PyObject_GetAttrString(spec, from_name); int result = 0; if (likely(value)) { if (allow_none || value != Py_None) { result = PyDict_SetItemString(moddict, to_name, value); } Py_DECREF(value); } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Clear(); } else { result = -1; } return result; } static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { PyObject *module = NULL, *moddict, *modname; if (__Pyx_check_single_interpreter()) return NULL; if (__pyx_m) return __Pyx_NewRef(__pyx_m); modname = PyObject_GetAttrString(spec, "name"); if (unlikely(!modname)) goto bad; module = PyModule_NewObject(modname); Py_DECREF(modname); if (unlikely(!module)) goto bad; moddict = PyModule_GetDict(module); if (unlikely(!moddict)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; return module; bad: Py_XDECREF(module); return NULL; } static CYTHON_SMALL_CODE int __pyx_pymod_exec_core(PyObject *__pyx_pyinit_module) #endif #endif { PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; __Pyx_RefNannyDeclarations #if CYTHON_PEP489_MULTI_PHASE_INIT if (__pyx_m) { if (__pyx_m == __pyx_pyinit_module) return 0; PyErr_SetString(PyExc_RuntimeError, "Module 'core' has already been imported. Re-initialisation is not supported."); return -1; } #elif PY_MAJOR_VERSION >= 3 if (__pyx_m) return __Pyx_NewRef(__pyx_m); #endif #if CYTHON_REFNANNY __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); if (!__Pyx_RefNanny) { PyErr_Clear(); __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); if (!__Pyx_RefNanny) Py_FatalError("failed to import 'refnanny' module"); } #endif __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_core(void)", 0); if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #ifdef __Pxy_PyFrame_Initialize_Offsets __Pxy_PyFrame_Initialize_Offsets(); #endif __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) #ifdef __Pyx_CyFunction_USED if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_FusedFunction_USED if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_Coroutine_USED if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_Generator_USED if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_AsyncGen_USED if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_StopAsyncIteration_USED if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif /*--- Library function declarations ---*/ /*--- Threads initialization code ---*/ #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS #ifdef WITH_THREAD /* Python build with threading support? */ PyEval_InitThreads(); #endif #endif /*--- Module creation code ---*/ #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_m = __pyx_pyinit_module; Py_INCREF(__pyx_m); #else #if PY_MAJOR_VERSION < 3 __pyx_m = Py_InitModule4("core", __pyx_methods, __pyx_k_The_functions_here_are_the_core, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); #else __pyx_m = PyModule_Create(&__pyx_moduledef); #endif if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) #endif __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_d); __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_b); __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_cython_runtime); if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); /*--- Initialize various global constants etc. ---*/ if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif if (__pyx_module_is_main_photutils__geometry__core) { if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) } #if PY_MAJOR_VERSION >= 3 { PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) if (!PyDict_GetItemString(modules, "photutils.geometry.core")) { if (unlikely(PyDict_SetItemString(modules, "photutils.geometry.core", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) } } #endif /*--- Builtin init code ---*/ if (__Pyx_InitCachedBuiltins() < 0) goto __pyx_L1_error; /*--- Constants init code ---*/ if (__Pyx_InitCachedConstants() < 0) goto __pyx_L1_error; /*--- Global type/function init code ---*/ (void)__Pyx_modinit_global_init_code(); (void)__Pyx_modinit_variable_export_code(); if (unlikely(__Pyx_modinit_function_export_code() != 0)) goto __pyx_L1_error; (void)__Pyx_modinit_type_init_code(); if (unlikely(__Pyx_modinit_type_import_code() != 0)) goto __pyx_L1_error; (void)__Pyx_modinit_variable_import_code(); (void)__Pyx_modinit_function_import_code(); /*--- Execution code ---*/ #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif /* "photutils/geometry/core.pyx":7 * """ * * import numpy as np # <<<<<<<<<<<<<< * cimport numpy as np * */ __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 7, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "photutils/geometry/core.pyx":10 * cimport numpy as np * * __all__ = ['elliptical_overlap_grid'] # <<<<<<<<<<<<<< * * */ __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_u_elliptical_overlap_grid); __Pyx_GIVEREF(__pyx_n_u_elliptical_overlap_grid); PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_u_elliptical_overlap_grid); if (PyDict_SetItem(__pyx_d, __pyx_n_s_all, __pyx_t_1) < 0) __PYX_ERR(0, 10, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "photutils/geometry/core.pyx":23 * from cpython cimport bool * * DTYPE = np.float64 # <<<<<<<<<<<<<< * ctypedef np.float64_t DTYPE_t * */ __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 23, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_float64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 23, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; if (PyDict_SetItem(__pyx_d, __pyx_n_s_DTYPE, __pyx_t_2) < 0) __PYX_ERR(0, 23, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/core.pyx":1 * # Licensed under a 3-clause BSD style license - see LICENSE.rst # <<<<<<<<<<<<<< * #cython: language_level=3 * """ */ __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1046 * raise ImportError("numpy.core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ /*--- Wrapped vars code ---*/ goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_2); if (__pyx_m) { if (__pyx_d) { __Pyx_AddTraceback("init photutils.geometry.core", __pyx_clineno, __pyx_lineno, __pyx_filename); } Py_CLEAR(__pyx_m); } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ImportError, "init photutils.geometry.core"); } __pyx_L0:; __Pyx_RefNannyFinishContext(); #if CYTHON_PEP489_MULTI_PHASE_INIT return (__pyx_m != NULL) ? 0 : -1; #elif PY_MAJOR_VERSION >= 3 return __pyx_m; #else return; #endif } /* --- Runtime support code --- */ /* Refnanny */ #if CYTHON_REFNANNY static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { PyObject *m = NULL, *p = NULL; void *r = NULL; m = PyImport_ImportModule(modname); if (!m) goto end; p = PyObject_GetAttrString(m, "RefNannyAPI"); if (!p) goto end; r = PyLong_AsVoidPtr(p); end: Py_XDECREF(p); Py_XDECREF(m); return (__Pyx_RefNannyAPIStruct *)r; } #endif /* PyErrFetchRestore */ #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { PyObject *tmp_type, *tmp_value, *tmp_tb; tmp_type = tstate->curexc_type; tmp_value = tstate->curexc_value; tmp_tb = tstate->curexc_traceback; tstate->curexc_type = type; tstate->curexc_value = value; tstate->curexc_traceback = tb; Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); } static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { *type = tstate->curexc_type; *value = tstate->curexc_value; *tb = tstate->curexc_traceback; tstate->curexc_type = 0; tstate->curexc_value = 0; tstate->curexc_traceback = 0; } #endif /* WriteUnraisableException */ static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno, CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename, int full_traceback, CYTHON_UNUSED int nogil) { PyObject *old_exc, *old_val, *old_tb; PyObject *ctx; __Pyx_PyThreadState_declare #ifdef WITH_THREAD PyGILState_STATE state; if (nogil) state = PyGILState_Ensure(); #ifdef _MSC_VER else state = (PyGILState_STATE)-1; #endif #endif __Pyx_PyThreadState_assign __Pyx_ErrFetch(&old_exc, &old_val, &old_tb); if (full_traceback) { Py_XINCREF(old_exc); Py_XINCREF(old_val); Py_XINCREF(old_tb); __Pyx_ErrRestore(old_exc, old_val, old_tb); PyErr_PrintEx(1); } #if PY_MAJOR_VERSION < 3 ctx = PyString_FromString(name); #else ctx = PyUnicode_FromString(name); #endif __Pyx_ErrRestore(old_exc, old_val, old_tb); if (!ctx) { PyErr_WriteUnraisable(Py_None); } else { PyErr_WriteUnraisable(ctx); Py_DECREF(ctx); } #ifdef WITH_THREAD if (nogil) PyGILState_Release(state); #endif } /* None */ static CYTHON_INLINE long __Pyx_mod_long(long a, long b) { long r = a % b; r += ((r != 0) & ((r ^ b) < 0)) * b; return r; } /* PyObjectGetAttrStr */ #if CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { PyTypeObject* tp = Py_TYPE(obj); if (likely(tp->tp_getattro)) return tp->tp_getattro(obj, attr_name); #if PY_MAJOR_VERSION < 3 if (likely(tp->tp_getattr)) return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); #endif return PyObject_GetAttr(obj, attr_name); } #endif /* GetBuiltinName */ static PyObject *__Pyx_GetBuiltinName(PyObject *name) { PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); if (unlikely(!result)) { PyErr_Format(PyExc_NameError, #if PY_MAJOR_VERSION >= 3 "name '%U' is not defined", name); #else "name '%.200s' is not defined", PyString_AS_STRING(name)); #endif } return result; } /* PyDictVersioning */ #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { PyObject *dict = Py_TYPE(obj)->tp_dict; return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; } static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { PyObject **dictptr = NULL; Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; if (offset) { #if CYTHON_COMPILING_IN_CPYTHON dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); #else dictptr = _PyObject_GetDictPtr(obj); #endif } return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; } static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { PyObject *dict = Py_TYPE(obj)->tp_dict; if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) return 0; return obj_dict_version == __Pyx_get_object_dict_version(obj); } #endif /* GetModuleGlobalName */ #if CYTHON_USE_DICT_VERSIONS static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) #else static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) #endif { PyObject *result; #if !CYTHON_AVOID_BORROWED_REFS #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } else if (unlikely(PyErr_Occurred())) { return NULL; } #else result = PyDict_GetItem(__pyx_d, name); __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } #endif #else result = PyObject_GetItem(__pyx_d, name); __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } PyErr_Clear(); #endif return __Pyx_GetBuiltinName(name); } /* PyObjectCall */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; ternaryfunc call = func->ob_type->tp_call; if (unlikely(!call)) return PyObject_Call(func, arg, kw); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) return NULL; result = (*call)(func, arg, kw); Py_LeaveRecursiveCall(); if (unlikely(!result) && unlikely(!PyErr_Occurred())) { PyErr_SetString( PyExc_SystemError, "NULL result without error in PyObject_Call"); } return result; } #endif /* RaiseException */ #if PY_MAJOR_VERSION < 3 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, CYTHON_UNUSED PyObject *cause) { __Pyx_PyThreadState_declare Py_XINCREF(type); if (!value || value == Py_None) value = NULL; else Py_INCREF(value); if (!tb || tb == Py_None) tb = NULL; else { Py_INCREF(tb); if (!PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto raise_error; } } if (PyType_Check(type)) { #if CYTHON_COMPILING_IN_PYPY if (!value) { Py_INCREF(Py_None); value = Py_None; } #endif PyErr_NormalizeException(&type, &value, &tb); } else { if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto raise_error; } value = type; type = (PyObject*) Py_TYPE(type); Py_INCREF(type); if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto raise_error; } } __Pyx_PyThreadState_assign __Pyx_ErrRestore(type, value, tb); return; raise_error: Py_XDECREF(value); Py_XDECREF(type); Py_XDECREF(tb); return; } #else static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { PyObject* owned_instance = NULL; if (tb == Py_None) { tb = 0; } else if (tb && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto bad; } if (value == Py_None) value = 0; if (PyExceptionInstance_Check(type)) { if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto bad; } value = type; type = (PyObject*) Py_TYPE(value); } else if (PyExceptionClass_Check(type)) { PyObject *instance_class = NULL; if (value && PyExceptionInstance_Check(value)) { instance_class = (PyObject*) Py_TYPE(value); if (instance_class != type) { int is_subclass = PyObject_IsSubclass(instance_class, type); if (!is_subclass) { instance_class = NULL; } else if (unlikely(is_subclass == -1)) { goto bad; } else { type = instance_class; } } } if (!instance_class) { PyObject *args; if (!value) args = PyTuple_New(0); else if (PyTuple_Check(value)) { Py_INCREF(value); args = value; } else args = PyTuple_Pack(1, value); if (!args) goto bad; owned_instance = PyObject_Call(type, args, NULL); Py_DECREF(args); if (!owned_instance) goto bad; value = owned_instance; if (!PyExceptionInstance_Check(value)) { PyErr_Format(PyExc_TypeError, "calling %R should have returned an instance of " "BaseException, not %R", type, Py_TYPE(value)); goto bad; } } } else { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto bad; } if (cause) { PyObject *fixed_cause; if (cause == Py_None) { fixed_cause = NULL; } else if (PyExceptionClass_Check(cause)) { fixed_cause = PyObject_CallObject(cause, NULL); if (fixed_cause == NULL) goto bad; } else if (PyExceptionInstance_Check(cause)) { fixed_cause = cause; Py_INCREF(fixed_cause); } else { PyErr_SetString(PyExc_TypeError, "exception causes must derive from " "BaseException"); goto bad; } PyException_SetCause(value, fixed_cause); } PyErr_SetObject(type, value); if (tb) { #if CYTHON_COMPILING_IN_PYPY PyObject *tmp_type, *tmp_value, *tmp_tb; PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); Py_INCREF(tb); PyErr_Restore(tmp_type, tmp_value, tb); Py_XDECREF(tmp_tb); #else PyThreadState *tstate = __Pyx_PyThreadState_Current; PyObject* tmp_tb = tstate->curexc_traceback; if (tb != tmp_tb) { Py_INCREF(tb); tstate->curexc_traceback = tb; Py_XDECREF(tmp_tb); } #endif } bad: Py_XDECREF(owned_instance); return; } #endif /* ExtTypeTest */ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { if (unlikely(!type)) { PyErr_SetString(PyExc_SystemError, "Missing type object"); return 0; } if (likely(__Pyx_TypeCheck(obj, type))) return 1; PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", Py_TYPE(obj)->tp_name, type->tp_name); return 0; } /* PyCFunctionFastCall */ #if CYTHON_FAST_PYCCALL static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { PyCFunctionObject *func = (PyCFunctionObject*)func_obj; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); int flags = PyCFunction_GET_FLAGS(func); assert(PyCFunction_Check(func)); assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); assert(nargs >= 0); assert(nargs == 0 || args != NULL); /* _PyCFunction_FastCallDict() must not be called with an exception set, because it may clear it (directly or indirectly) and so the caller loses its exception */ assert(!PyErr_Occurred()); if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); } else { return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); } } #endif /* PyFunctionFastCall */ #if CYTHON_FAST_PYCALL static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, PyObject *globals) { PyFrameObject *f; PyThreadState *tstate = __Pyx_PyThreadState_Current; PyObject **fastlocals; Py_ssize_t i; PyObject *result; assert(globals != NULL); /* XXX Perhaps we should create a specialized PyFrame_New() that doesn't take locals, but does take builtins without sanity checking them. */ assert(tstate != NULL); f = PyFrame_New(tstate, co, globals, NULL); if (f == NULL) { return NULL; } fastlocals = __Pyx_PyFrame_GetLocalsplus(f); for (i = 0; i < na; i++) { Py_INCREF(*args); fastlocals[i] = *args++; } result = PyEval_EvalFrameEx(f,0); ++tstate->recursion_depth; Py_DECREF(f); --tstate->recursion_depth; return result; } #if 1 || PY_VERSION_HEX < 0x030600B1 static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func); PyObject *closure; #if PY_MAJOR_VERSION >= 3 PyObject *kwdefs; #endif PyObject *kwtuple, **k; PyObject **d; Py_ssize_t nd; Py_ssize_t nk; PyObject *result; assert(kwargs == NULL || PyDict_Check(kwargs)); nk = kwargs ? PyDict_Size(kwargs) : 0; if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { return NULL; } if ( #if PY_MAJOR_VERSION >= 3 co->co_kwonlyargcount == 0 && #endif likely(kwargs == NULL || nk == 0) && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { if (argdefs == NULL && co->co_argcount == nargs) { result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); goto done; } else if (nargs == 0 && argdefs != NULL && co->co_argcount == Py_SIZE(argdefs)) { /* function called with no arguments, but all parameters have a default value: use default values as arguments .*/ args = &PyTuple_GET_ITEM(argdefs, 0); result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); goto done; } } if (kwargs != NULL) { Py_ssize_t pos, i; kwtuple = PyTuple_New(2 * nk); if (kwtuple == NULL) { result = NULL; goto done; } k = &PyTuple_GET_ITEM(kwtuple, 0); pos = i = 0; while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { Py_INCREF(k[i]); Py_INCREF(k[i+1]); i += 2; } nk = i / 2; } else { kwtuple = NULL; k = NULL; } closure = PyFunction_GET_CLOSURE(func); #if PY_MAJOR_VERSION >= 3 kwdefs = PyFunction_GET_KW_DEFAULTS(func); #endif if (argdefs != NULL) { d = &PyTuple_GET_ITEM(argdefs, 0); nd = Py_SIZE(argdefs); } else { d = NULL; nd = 0; } #if PY_MAJOR_VERSION >= 3 result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, args, (int)nargs, k, (int)nk, d, (int)nd, kwdefs, closure); #else result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, args, (int)nargs, k, (int)nk, d, (int)nd, closure); #endif Py_XDECREF(kwtuple); done: Py_LeaveRecursiveCall(); return result; } #endif #endif /* PyObjectCallMethO */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { PyObject *self, *result; PyCFunction cfunc; cfunc = PyCFunction_GET_FUNCTION(func); self = PyCFunction_GET_SELF(func); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) return NULL; result = cfunc(self, arg); Py_LeaveRecursiveCall(); if (unlikely(!result) && unlikely(!PyErr_Occurred())) { PyErr_SetString( PyExc_SystemError, "NULL result without error in PyObject_Call"); } return result; } #endif /* PyObjectCallOneArg */ #if CYTHON_COMPILING_IN_CPYTHON static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { PyObject *result; PyObject *args = PyTuple_New(1); if (unlikely(!args)) return NULL; Py_INCREF(arg); PyTuple_SET_ITEM(args, 0, arg); result = __Pyx_PyObject_Call(func, args, NULL); Py_DECREF(args); return result; } static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { #if CYTHON_FAST_PYCALL if (PyFunction_Check(func)) { return __Pyx_PyFunction_FastCall(func, &arg, 1); } #endif if (likely(PyCFunction_Check(func))) { if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { return __Pyx_PyObject_CallMethO(func, arg); #if CYTHON_FAST_PYCCALL } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { return __Pyx_PyCFunction_FastCall(func, &arg, 1); #endif } } return __Pyx__PyObject_CallOneArg(func, arg); } #else static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { PyObject *result; PyObject *args = PyTuple_Pack(1, arg); if (unlikely(!args)) return NULL; result = __Pyx_PyObject_Call(func, args, NULL); Py_DECREF(args); return result; } #endif /* DictGetItem */ #if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) { PyObject *value; value = PyDict_GetItemWithError(d, key); if (unlikely(!value)) { if (!PyErr_Occurred()) { if (unlikely(PyTuple_Check(key))) { PyObject* args = PyTuple_Pack(1, key); if (likely(args)) { PyErr_SetObject(PyExc_KeyError, args); Py_DECREF(args); } } else { PyErr_SetObject(PyExc_KeyError, key); } } return NULL; } Py_INCREF(value); return value; } #endif /* RaiseTooManyValuesToUnpack */ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { PyErr_Format(PyExc_ValueError, "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); } /* RaiseNeedMoreValuesToUnpack */ static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { PyErr_Format(PyExc_ValueError, "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", index, (index == 1) ? "" : "s"); } /* RaiseNoneIterError */ static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); } /* GetTopmostException */ #if CYTHON_USE_EXC_INFO_STACK static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate) { _PyErr_StackItem *exc_info = tstate->exc_info; while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && exc_info->previous_item != NULL) { exc_info = exc_info->previous_item; } return exc_info; } #endif /* SaveResetException */ #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { #if CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); *type = exc_info->exc_type; *value = exc_info->exc_value; *tb = exc_info->exc_traceback; #else *type = tstate->exc_type; *value = tstate->exc_value; *tb = tstate->exc_traceback; #endif Py_XINCREF(*type); Py_XINCREF(*value); Py_XINCREF(*tb); } static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { PyObject *tmp_type, *tmp_value, *tmp_tb; #if CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = tstate->exc_info; tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; tmp_tb = exc_info->exc_traceback; exc_info->exc_type = type; exc_info->exc_value = value; exc_info->exc_traceback = tb; #else tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; tstate->exc_type = type; tstate->exc_value = value; tstate->exc_traceback = tb; #endif Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); } #endif /* PyErrExceptionMatches */ #if CYTHON_FAST_THREAD_STATE static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { Py_ssize_t i, n; n = PyTuple_GET_SIZE(tuple); #if PY_MAJOR_VERSION >= 3 for (i=0; icurexc_type; if (exc_type == err) return 1; if (unlikely(!exc_type)) return 0; if (unlikely(PyTuple_Check(err))) return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); } #endif /* GetException */ #if CYTHON_FAST_THREAD_STATE static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) #else static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) #endif { PyObject *local_type, *local_value, *local_tb; #if CYTHON_FAST_THREAD_STATE PyObject *tmp_type, *tmp_value, *tmp_tb; local_type = tstate->curexc_type; local_value = tstate->curexc_value; local_tb = tstate->curexc_traceback; tstate->curexc_type = 0; tstate->curexc_value = 0; tstate->curexc_traceback = 0; #else PyErr_Fetch(&local_type, &local_value, &local_tb); #endif PyErr_NormalizeException(&local_type, &local_value, &local_tb); #if CYTHON_FAST_THREAD_STATE if (unlikely(tstate->curexc_type)) #else if (unlikely(PyErr_Occurred())) #endif goto bad; #if PY_MAJOR_VERSION >= 3 if (local_tb) { if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) goto bad; } #endif Py_XINCREF(local_tb); Py_XINCREF(local_type); Py_XINCREF(local_value); *type = local_type; *value = local_value; *tb = local_tb; #if CYTHON_FAST_THREAD_STATE #if CYTHON_USE_EXC_INFO_STACK { _PyErr_StackItem *exc_info = tstate->exc_info; tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; tmp_tb = exc_info->exc_traceback; exc_info->exc_type = local_type; exc_info->exc_value = local_value; exc_info->exc_traceback = local_tb; } #else tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; tstate->exc_type = local_type; tstate->exc_value = local_value; tstate->exc_traceback = local_tb; #endif Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); #else PyErr_SetExcInfo(local_type, local_value, local_tb); #endif return 0; bad: *type = 0; *value = 0; *tb = 0; Py_XDECREF(local_type); Py_XDECREF(local_value); Py_XDECREF(local_tb); return -1; } /* TypeImport */ #ifndef __PYX_HAVE_RT_ImportType #define __PYX_HAVE_RT_ImportType static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size) { PyObject *result = 0; char warning[200]; Py_ssize_t basicsize; #ifdef Py_LIMITED_API PyObject *py_basicsize; #endif result = PyObject_GetAttrString(module, class_name); if (!result) goto bad; if (!PyType_Check(result)) { PyErr_Format(PyExc_TypeError, "%.200s.%.200s is not a type object", module_name, class_name); goto bad; } #ifndef Py_LIMITED_API basicsize = ((PyTypeObject *)result)->tp_basicsize; #else py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); if (!py_basicsize) goto bad; basicsize = PyLong_AsSsize_t(py_basicsize); Py_DECREF(py_basicsize); py_basicsize = 0; if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) goto bad; #endif if ((size_t)basicsize < size) { PyErr_Format(PyExc_ValueError, "%.200s.%.200s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); goto bad; } if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { PyErr_Format(PyExc_ValueError, "%.200s.%.200s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); goto bad; } else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { PyOS_snprintf(warning, sizeof(warning), "%s.%s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; } return (PyTypeObject *)result; bad: Py_XDECREF(result); return NULL; } #endif /* Import */ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { PyObject *empty_list = 0; PyObject *module = 0; PyObject *global_dict = 0; PyObject *empty_dict = 0; PyObject *list; #if PY_MAJOR_VERSION < 3 PyObject *py_import; py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); if (!py_import) goto bad; #endif if (from_list) list = from_list; else { empty_list = PyList_New(0); if (!empty_list) goto bad; list = empty_list; } global_dict = PyModule_GetDict(__pyx_m); if (!global_dict) goto bad; empty_dict = PyDict_New(); if (!empty_dict) goto bad; { #if PY_MAJOR_VERSION >= 3 if (level == -1) { if (strchr(__Pyx_MODULE_NAME, '.')) { module = PyImport_ImportModuleLevelObject( name, global_dict, empty_dict, list, 1); if (!module) { if (!PyErr_ExceptionMatches(PyExc_ImportError)) goto bad; PyErr_Clear(); } } level = 0; } #endif if (!module) { #if PY_MAJOR_VERSION < 3 PyObject *py_level = PyInt_FromLong(level); if (!py_level) goto bad; module = PyObject_CallFunctionObjArgs(py_import, name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); Py_DECREF(py_level); #else module = PyImport_ImportModuleLevelObject( name, global_dict, empty_dict, list, level); #endif } } bad: #if PY_MAJOR_VERSION < 3 Py_XDECREF(py_import); #endif Py_XDECREF(empty_list); Py_XDECREF(empty_dict); return module; } /* CLineInTraceback */ #ifndef CYTHON_CLINE_IN_TRACEBACK static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { PyObject *use_cline; PyObject *ptype, *pvalue, *ptraceback; #if CYTHON_COMPILING_IN_CPYTHON PyObject **cython_runtime_dict; #endif if (unlikely(!__pyx_cython_runtime)) { return c_line; } __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); #if CYTHON_COMPILING_IN_CPYTHON cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); if (likely(cython_runtime_dict)) { __PYX_PY_DICT_LOOKUP_IF_MODIFIED( use_cline, *cython_runtime_dict, __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) } else #endif { PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); if (use_cline_obj) { use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; Py_DECREF(use_cline_obj); } else { PyErr_Clear(); use_cline = NULL; } } if (!use_cline) { c_line = 0; PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); } else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { c_line = 0; } __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); return c_line; } #endif /* CodeObjectCache */ static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { int start = 0, mid = 0, end = count - 1; if (end >= 0 && code_line > entries[end].code_line) { return count; } while (start < end) { mid = start + (end - start) / 2; if (code_line < entries[mid].code_line) { end = mid; } else if (code_line > entries[mid].code_line) { start = mid + 1; } else { return mid; } } if (code_line <= entries[mid].code_line) { return mid; } else { return mid + 1; } } static PyCodeObject *__pyx_find_code_object(int code_line) { PyCodeObject* code_object; int pos; if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { return NULL; } pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { return NULL; } code_object = __pyx_code_cache.entries[pos].code_object; Py_INCREF(code_object); return code_object; } static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { int pos, i; __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; if (unlikely(!code_line)) { return; } if (unlikely(!entries)) { entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); if (likely(entries)) { __pyx_code_cache.entries = entries; __pyx_code_cache.max_count = 64; __pyx_code_cache.count = 1; entries[0].code_line = code_line; entries[0].code_object = code_object; Py_INCREF(code_object); } return; } pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { PyCodeObject* tmp = entries[pos].code_object; entries[pos].code_object = code_object; Py_DECREF(tmp); return; } if (__pyx_code_cache.count == __pyx_code_cache.max_count) { int new_max = __pyx_code_cache.max_count + 64; entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( __pyx_code_cache.entries, (size_t)new_max*sizeof(__Pyx_CodeObjectCacheEntry)); if (unlikely(!entries)) { return; } __pyx_code_cache.entries = entries; __pyx_code_cache.max_count = new_max; } for (i=__pyx_code_cache.count; i>pos; i--) { entries[i] = entries[i-1]; } entries[pos].code_line = code_line; entries[pos].code_object = code_object; __pyx_code_cache.count++; Py_INCREF(code_object); } /* AddTraceback */ #include "compile.h" #include "frameobject.h" #include "traceback.h" static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( const char *funcname, int c_line, int py_line, const char *filename) { PyCodeObject *py_code = 0; PyObject *py_srcfile = 0; PyObject *py_funcname = 0; #if PY_MAJOR_VERSION < 3 py_srcfile = PyString_FromString(filename); #else py_srcfile = PyUnicode_FromString(filename); #endif if (!py_srcfile) goto bad; if (c_line) { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); #else py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); #endif } else { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromString(funcname); #else py_funcname = PyUnicode_FromString(funcname); #endif } if (!py_funcname) goto bad; py_code = __Pyx_PyCode_New( 0, 0, 0, 0, 0, __pyx_empty_bytes, /*PyObject *code,*/ __pyx_empty_tuple, /*PyObject *consts,*/ __pyx_empty_tuple, /*PyObject *names,*/ __pyx_empty_tuple, /*PyObject *varnames,*/ __pyx_empty_tuple, /*PyObject *freevars,*/ __pyx_empty_tuple, /*PyObject *cellvars,*/ py_srcfile, /*PyObject *filename,*/ py_funcname, /*PyObject *name,*/ py_line, __pyx_empty_bytes /*PyObject *lnotab*/ ); Py_DECREF(py_srcfile); Py_DECREF(py_funcname); return py_code; bad: Py_XDECREF(py_srcfile); Py_XDECREF(py_funcname); return NULL; } static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename) { PyCodeObject *py_code = 0; PyFrameObject *py_frame = 0; PyThreadState *tstate = __Pyx_PyThreadState_Current; if (c_line) { c_line = __Pyx_CLineForTraceback(tstate, c_line); } py_code = __pyx_find_code_object(c_line ? -c_line : py_line); if (!py_code) { py_code = __Pyx_CreateCodeObjectForTraceback( funcname, c_line, py_line, filename); if (!py_code) goto bad; __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); } py_frame = PyFrame_New( tstate, /*PyThreadState *tstate,*/ py_code, /*PyCodeObject *code,*/ __pyx_d, /*PyObject *globals,*/ 0 /*PyObject *locals*/ ); if (!py_frame) goto bad; __Pyx_PyFrame_SetLineNumber(py_frame, py_line); PyTraceBack_Here(py_frame); bad: Py_XDECREF(py_code); Py_XDECREF(py_frame); } /* Declarations */ #if CYTHON_CCOMPLEX #ifdef __cplusplus static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { return ::std::complex< float >(x, y); } #else static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { return x + y*(__pyx_t_float_complex)_Complex_I; } #endif #else static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { __pyx_t_float_complex z; z.real = x; z.imag = y; return z; } #endif /* Arithmetic */ #if CYTHON_CCOMPLEX #else static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { return (a.real == b.real) && (a.imag == b.imag); } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; z.real = a.real + b.real; z.imag = a.imag + b.imag; return z; } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; z.real = a.real - b.real; z.imag = a.imag - b.imag; return z; } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; z.real = a.real * b.real - a.imag * b.imag; z.imag = a.real * b.imag + a.imag * b.real; return z; } #if 1 static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { if (b.imag == 0) { return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); } else if (fabsf(b.real) >= fabsf(b.imag)) { if (b.real == 0 && b.imag == 0) { return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.imag); } else { float r = b.imag / b.real; float s = (float)(1.0) / (b.real + b.imag * r); return __pyx_t_float_complex_from_parts( (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); } } else { float r = b.real / b.imag; float s = (float)(1.0) / (b.imag + b.real * r); return __pyx_t_float_complex_from_parts( (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); } } #else static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { if (b.imag == 0) { return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); } else { float denom = b.real * b.real + b.imag * b.imag; return __pyx_t_float_complex_from_parts( (a.real * b.real + a.imag * b.imag) / denom, (a.imag * b.real - a.real * b.imag) / denom); } } #endif static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex a) { __pyx_t_float_complex z; z.real = -a.real; z.imag = -a.imag; return z; } static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex a) { return (a.real == 0) && (a.imag == 0); } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex a) { __pyx_t_float_complex z; z.real = a.real; z.imag = -a.imag; return z; } #if 1 static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex z) { #if !defined(HAVE_HYPOT) || defined(_MSC_VER) return sqrtf(z.real*z.real + z.imag*z.imag); #else return hypotf(z.real, z.imag); #endif } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; float r, lnr, theta, z_r, z_theta; if (b.imag == 0 && b.real == (int)b.real) { if (b.real < 0) { float denom = a.real * a.real + a.imag * a.imag; a.real = a.real / denom; a.imag = -a.imag / denom; b.real = -b.real; } switch ((int)b.real) { case 0: z.real = 1; z.imag = 0; return z; case 1: return a; case 2: return __Pyx_c_prod_float(a, a); case 3: z = __Pyx_c_prod_float(a, a); return __Pyx_c_prod_float(z, a); case 4: z = __Pyx_c_prod_float(a, a); return __Pyx_c_prod_float(z, z); } } if (a.imag == 0) { if (a.real == 0) { return a; } else if (b.imag == 0) { z.real = powf(a.real, b.real); z.imag = 0; return z; } else if (a.real > 0) { r = a.real; theta = 0; } else { r = -a.real; theta = atan2f(0.0, -1.0); } } else { r = __Pyx_c_abs_float(a); theta = atan2f(a.imag, a.real); } lnr = logf(r); z_r = expf(lnr * b.real - theta * b.imag); z_theta = theta * b.real + lnr * b.imag; z.real = z_r * cosf(z_theta); z.imag = z_r * sinf(z_theta); return z; } #endif #endif /* Declarations */ #if CYTHON_CCOMPLEX #ifdef __cplusplus static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { return ::std::complex< double >(x, y); } #else static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { return x + y*(__pyx_t_double_complex)_Complex_I; } #endif #else static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { __pyx_t_double_complex z; z.real = x; z.imag = y; return z; } #endif /* Arithmetic */ #if CYTHON_CCOMPLEX #else static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { return (a.real == b.real) && (a.imag == b.imag); } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; z.real = a.real + b.real; z.imag = a.imag + b.imag; return z; } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; z.real = a.real - b.real; z.imag = a.imag - b.imag; return z; } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; z.real = a.real * b.real - a.imag * b.imag; z.imag = a.real * b.imag + a.imag * b.real; return z; } #if 1 static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { if (b.imag == 0) { return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); } else if (fabs(b.real) >= fabs(b.imag)) { if (b.real == 0 && b.imag == 0) { return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.imag); } else { double r = b.imag / b.real; double s = (double)(1.0) / (b.real + b.imag * r); return __pyx_t_double_complex_from_parts( (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); } } else { double r = b.real / b.imag; double s = (double)(1.0) / (b.imag + b.real * r); return __pyx_t_double_complex_from_parts( (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); } } #else static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { if (b.imag == 0) { return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); } else { double denom = b.real * b.real + b.imag * b.imag; return __pyx_t_double_complex_from_parts( (a.real * b.real + a.imag * b.imag) / denom, (a.imag * b.real - a.real * b.imag) / denom); } } #endif static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex a) { __pyx_t_double_complex z; z.real = -a.real; z.imag = -a.imag; return z; } static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex a) { return (a.real == 0) && (a.imag == 0); } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex a) { __pyx_t_double_complex z; z.real = a.real; z.imag = -a.imag; return z; } #if 1 static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex z) { #if !defined(HAVE_HYPOT) || defined(_MSC_VER) return sqrt(z.real*z.real + z.imag*z.imag); #else return hypot(z.real, z.imag); #endif } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; double r, lnr, theta, z_r, z_theta; if (b.imag == 0 && b.real == (int)b.real) { if (b.real < 0) { double denom = a.real * a.real + a.imag * a.imag; a.real = a.real / denom; a.imag = -a.imag / denom; b.real = -b.real; } switch ((int)b.real) { case 0: z.real = 1; z.imag = 0; return z; case 1: return a; case 2: return __Pyx_c_prod_double(a, a); case 3: z = __Pyx_c_prod_double(a, a); return __Pyx_c_prod_double(z, a); case 4: z = __Pyx_c_prod_double(a, a); return __Pyx_c_prod_double(z, z); } } if (a.imag == 0) { if (a.real == 0) { return a; } else if (b.imag == 0) { z.real = pow(a.real, b.real); z.imag = 0; return z; } else if (a.real > 0) { r = a.real; theta = 0; } else { r = -a.real; theta = atan2(0.0, -1.0); } } else { r = __Pyx_c_abs_double(a); theta = atan2(a.imag, a.real); } lnr = log(r); z_r = exp(lnr * b.real - theta * b.imag); z_theta = theta * b.real + lnr * b.imag; z.real = z_r * cos(z_theta); z.imag = z_r * sin(z_theta); return z; } #endif #endif /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(int) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(int) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof(int) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; return _PyLong_FromByteArray(bytes, sizeof(int), little, !is_unsigned); } } /* CIntFromPyVerify */ #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) #define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) #define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ {\ func_type value = func_value;\ if (sizeof(target_type) < sizeof(func_type)) {\ if (unlikely(value != (func_type) (target_type) value)) {\ func_type zero = 0;\ if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ return (target_type) -1;\ if (is_unsigned && unlikely(value < zero))\ goto raise_neg_overflow;\ else\ goto raise_overflow;\ }\ }\ return (target_type) value;\ } /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__NPY_TYPES(enum NPY_TYPES value) { const enum NPY_TYPES neg_one = (enum NPY_TYPES) ((enum NPY_TYPES) 0 - (enum NPY_TYPES) 1), const_zero = (enum NPY_TYPES) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(enum NPY_TYPES) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(enum NPY_TYPES) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(enum NPY_TYPES) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof(enum NPY_TYPES) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(enum NPY_TYPES) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; return _PyLong_FromByteArray(bytes, sizeof(enum NPY_TYPES), little, !is_unsigned); } } /* CIntFromPy */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { if (sizeof(int) < sizeof(long)) { __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } return (int) val; } } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (int) 0; case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) case 2: if (8 * sizeof(int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); } } break; case 3: if (8 * sizeof(int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); } } break; case 4: if (8 * sizeof(int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); } } break; } #endif #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { goto raise_neg_overflow; } #else { int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) return (int) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif if (sizeof(int) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (int) 0; case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) case -2: if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case 2: if (8 * sizeof(int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case -3: if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case 3: if (8 * sizeof(int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case -4: if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case 4: if (8 * sizeof(int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; } #endif if (sizeof(int) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } { #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); #else int val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { PyObject *tmp = v; v = PyNumber_Long(tmp); Py_DECREF(tmp); } #endif if (likely(v)) { int one = 1; int is_little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&val; int ret = _PyLong_AsByteArray((PyLongObject *)v, bytes, sizeof(val), is_little, !is_unsigned); Py_DECREF(v); if (likely(!ret)) return val; } #endif return (int) -1; } } else { int val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); if (!tmp) return (int) -1; val = __Pyx_PyInt_As_int(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, "value too large to convert to int"); return (int) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, "can't convert negative value to int"); return (int) -1; } /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(long) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(long) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof(long) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; return _PyLong_FromByteArray(bytes, sizeof(long), little, !is_unsigned); } } /* CIntFromPy */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { if (sizeof(long) < sizeof(long)) { __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } return (long) val; } } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (long) 0; case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) case 2: if (8 * sizeof(long) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); } } break; case 3: if (8 * sizeof(long) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); } } break; case 4: if (8 * sizeof(long) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); } } break; } #endif #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { goto raise_neg_overflow; } #else { int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) return (long) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif if (sizeof(long) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (long) 0; case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) case -2: if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case 2: if (8 * sizeof(long) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case -3: if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case 3: if (8 * sizeof(long) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case -4: if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case 4: if (8 * sizeof(long) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; } #endif if (sizeof(long) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } { #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); #else long val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { PyObject *tmp = v; v = PyNumber_Long(tmp); Py_DECREF(tmp); } #endif if (likely(v)) { int one = 1; int is_little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&val; int ret = _PyLong_AsByteArray((PyLongObject *)v, bytes, sizeof(val), is_little, !is_unsigned); Py_DECREF(v); if (likely(!ret)) return val; } #endif return (long) -1; } } else { long val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); if (!tmp) return (long) -1; val = __Pyx_PyInt_As_long(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, "value too large to convert to long"); return (long) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, "can't convert negative value to long"); return (long) -1; } /* FastTypeChecks */ #if CYTHON_COMPILING_IN_CPYTHON static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { while (a) { a = a->tp_base; if (a == b) return 1; } return b == &PyBaseObject_Type; } static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { PyObject *mro; if (a == b) return 1; mro = a->tp_mro; if (likely(mro)) { Py_ssize_t i, n; n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) return 1; } return 0; } return __Pyx_InBases(a, b); } #if PY_MAJOR_VERSION == 2 static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { PyObject *exception, *value, *tb; int res; __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ErrFetch(&exception, &value, &tb); res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; if (unlikely(res == -1)) { PyErr_WriteUnraisable(err); res = 0; } if (!res) { res = PyObject_IsSubclass(err, exc_type2); if (unlikely(res == -1)) { PyErr_WriteUnraisable(err); res = 0; } } __Pyx_ErrRestore(exception, value, tb); return res; } #else static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; if (!res) { res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); } return res; } #endif static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { Py_ssize_t i, n; assert(PyExceptionClass_Check(exc_type)); n = PyTuple_GET_SIZE(tuple); #if PY_MAJOR_VERSION >= 3 for (i=0; i= 0x02070000 cobj = PyCapsule_New(tmp.p, sig, 0); #else cobj = PyCObject_FromVoidPtrAndDesc(tmp.p, (void *)sig, 0); #endif if (!cobj) goto bad; if (PyDict_SetItemString(d, name, cobj) < 0) goto bad; Py_DECREF(cobj); Py_DECREF(d); return 0; bad: Py_XDECREF(cobj); Py_XDECREF(d); return -1; } /* InitStrings */ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { while (t->p) { #if PY_MAJOR_VERSION < 3 if (t->is_unicode) { *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); } else if (t->intern) { *t->p = PyString_InternFromString(t->s); } else { *t->p = PyString_FromStringAndSize(t->s, t->n - 1); } #else if (t->is_unicode | t->is_str) { if (t->intern) { *t->p = PyUnicode_InternFromString(t->s); } else if (t->encoding) { *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); } else { *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); } } else { *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); } #endif if (!*t->p) return -1; if (PyObject_Hash(*t->p) == -1) return -1; ++t; } return 0; } static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); } static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { Py_ssize_t ignore; return __Pyx_PyObject_AsStringAndSize(o, &ignore); } #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT #if !CYTHON_PEP393_ENABLED static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { char* defenc_c; PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); if (!defenc) return NULL; defenc_c = PyBytes_AS_STRING(defenc); #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII { char* end = defenc_c + PyBytes_GET_SIZE(defenc); char* c; for (c = defenc_c; c < end; c++) { if ((unsigned char) (*c) >= 128) { PyUnicode_AsASCIIString(o); return NULL; } } } #endif *length = PyBytes_GET_SIZE(defenc); return defenc_c; } #else static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII if (likely(PyUnicode_IS_ASCII(o))) { *length = PyUnicode_GET_LENGTH(o); return PyUnicode_AsUTF8(o); } else { PyUnicode_AsASCIIString(o); return NULL; } #else return PyUnicode_AsUTF8AndSize(o, length); #endif } #endif #endif static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT if ( #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII __Pyx_sys_getdefaultencoding_not_ascii && #endif PyUnicode_Check(o)) { return __Pyx_PyUnicode_AsStringAndSize(o, length); } else #endif #if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) if (PyByteArray_Check(o)) { *length = PyByteArray_GET_SIZE(o); return PyByteArray_AS_STRING(o); } else #endif { char* result; int r = PyBytes_AsStringAndSize(o, &result, length); if (unlikely(r < 0)) { return NULL; } else { return result; } } } static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { int is_true = x == Py_True; if (is_true | (x == Py_False) | (x == Py_None)) return is_true; else return PyObject_IsTrue(x); } static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { int retval; if (unlikely(!x)) return -1; retval = __Pyx_PyObject_IsTrue(x); Py_DECREF(x); return retval; } static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { #if PY_MAJOR_VERSION >= 3 if (PyLong_Check(result)) { if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, "__int__ returned non-int (type %.200s). " "The ability to return an instance of a strict subclass of int " "is deprecated, and may be removed in a future version of Python.", Py_TYPE(result)->tp_name)) { Py_DECREF(result); return NULL; } return result; } #endif PyErr_Format(PyExc_TypeError, "__%.4s__ returned non-%.4s (type %.200s)", type_name, type_name, Py_TYPE(result)->tp_name); Py_DECREF(result); return NULL; } static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { #if CYTHON_USE_TYPE_SLOTS PyNumberMethods *m; #endif const char *name = NULL; PyObject *res = NULL; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x) || PyLong_Check(x))) #else if (likely(PyLong_Check(x))) #endif return __Pyx_NewRef(x); #if CYTHON_USE_TYPE_SLOTS m = Py_TYPE(x)->tp_as_number; #if PY_MAJOR_VERSION < 3 if (m && m->nb_int) { name = "int"; res = m->nb_int(x); } else if (m && m->nb_long) { name = "long"; res = m->nb_long(x); } #else if (likely(m && m->nb_int)) { name = "int"; res = m->nb_int(x); } #endif #else if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { res = PyNumber_Int(x); } #endif if (likely(res)) { #if PY_MAJOR_VERSION < 3 if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { #else if (unlikely(!PyLong_CheckExact(res))) { #endif return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); } } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "an integer is required"); } return res; } static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { Py_ssize_t ival; PyObject *x; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_CheckExact(b))) { if (sizeof(Py_ssize_t) >= sizeof(long)) return PyInt_AS_LONG(b); else return PyInt_AsSsize_t(b); } #endif if (likely(PyLong_CheckExact(b))) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)b)->ob_digit; const Py_ssize_t size = Py_SIZE(b); if (likely(__Pyx_sst_abs(size) <= 1)) { ival = likely(size) ? digits[0] : 0; if (size == -1) ival = -ival; return ival; } else { switch (size) { case 2: if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case -2: if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case 3: if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case -3: if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case 4: if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case -4: if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; } } #endif return PyLong_AsSsize_t(b); } x = PyNumber_Index(b); if (!x) return -1; ival = PyInt_AsSsize_t(x); Py_DECREF(x); return ival; } static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); } static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { return PyInt_FromSize_t(ival); } #endif /* Py_PYTHON_H */ photutils-0.7.2/photutils/geometry/core.pxd0000644000214200020070000000133513563423715023304 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst #cython: language_level=3 # This file is needed in order to be able to cimport functions into other Cython files cdef double distance(double x1, double y1, double x2, double y2) cdef double area_arc(double x1, double y1, double x2, double y2, double R) cdef double area_triangle(double x1, double y1, double x2, double y2, double x3, double y3) cdef double area_arc_unit(double x1, double y1, double x2, double y2) cdef int in_triangle(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3) cdef double overlap_area_triangle_unit_circle(double x1, double y1, double x2, double y2, double x3, double y3) cdef double floor_sqrt(double x) photutils-0.7.2/photutils/geometry/core.pyx0000644000214200020070000002756013563423715023341 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst #cython: language_level=3 """ The functions here are the core geometry functions. """ import numpy as np cimport numpy as np __all__ = ['elliptical_overlap_grid'] cdef extern from "math.h": double asin(double x) double sin(double x) double cos(double x) double sqrt(double x) double fabs(double x) from cpython cimport bool DTYPE = np.float64 ctypedef np.float64_t DTYPE_t cimport cython ctypedef struct point: double x double y ctypedef struct intersections: point p1 point p2 cdef double floor_sqrt(double x): """ In some of the geometrical functions, we have to take the sqrt of a number and we know that the number should be >= 0. However, in some cases the value is e.g. -1e-10, but we want to treat it as zero, which is what this function does. Note that this does **not** check whether negative values are close or not to zero, so this should be used only in cases where the value is expected to be positive on paper. """ if x > 0: return sqrt(x) else: return 0 # NOTE: The following two functions use cdef because they are not intended to be # called from the Python code. Using def makes them callable from outside, but # also slower. Some functions currently return multiple values, and for those we # still use 'def' for now. cdef double distance(double x1, double y1, double x2, double y2): """ Distance between two points in two dimensions. Parameters ---------- x1, y1 : float The coordinates of the first point x2, y2 : float The coordinates of the second point Returns ------- d : float The Euclidean distance between the two points """ return sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) cdef double area_arc(double x1, double y1, double x2, double y2, double r): """ Area of a circle arc with radius r between points (x1, y1) and (x2, y2). References ---------- http://mathworld.wolfram.com/CircularSegment.html """ cdef double a, theta a = distance(x1, y1, x2, y2) theta = 2. * asin(0.5 * a / r) return 0.5 * r * r * (theta - sin(theta)) cdef double area_triangle(double x1, double y1, double x2, double y2, double x3, double y3): """ Area of a triangle defined by three vertices. """ return 0.5 * abs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) cdef double area_arc_unit(double x1, double y1, double x2, double y2): """ Area of a circle arc with radius R between points (x1, y1) and (x2, y2) References ---------- http://mathworld.wolfram.com/CircularSegment.html """ cdef double a, theta a = distance(x1, y1, x2, y2) theta = 2. * asin(0.5 * a) return 0.5 * (theta - sin(theta)) cdef int in_triangle(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3): """ Check if a point (x,y) is inside a triangle """ cdef int c = 0 c += ((y1 > y) != (y2 > y) and x < (x2 - x1) * (y - y1) / (y2 - y1) + x1) c += ((y2 > y) != (y3 > y) and x < (x3 - x2) * (y - y2) / (y3 - y2) + x2) c += ((y3 > y) != (y1 > y) and x < (x1 - x3) * (y - y3) / (y1 - y3) + x3) return c % 2 == 1 cdef intersections circle_line(double x1, double y1, double x2, double y2): """Intersection of a line defined by two points with a unit circle""" cdef double a, b, delta, dx, dy cdef double tolerance = 1.e-10 cdef intersections inter dx = x2 - x1 dy = y2 - y1 if fabs(dx) < tolerance and fabs(dy) < tolerance: inter.p1.x = 2. inter.p1.y = 2. inter.p2.x = 2. inter.p2.y = 2. elif fabs(dx) > fabs(dy): # Find the slope and intercept of the line a = dy / dx b = y1 - a * x1 # Find the determinant of the quadratic equation delta = 1. + a * a - b * b if delta > 0.: # solutions exist delta = sqrt(delta) inter.p1.x = (- a * b - delta) / (1. + a * a) inter.p1.y = a * inter.p1.x + b inter.p2.x = (- a * b + delta) / (1. + a * a) inter.p2.y = a * inter.p2.x + b else: # no solution, return values > 1 inter.p1.x = 2. inter.p1.y = 2. inter.p2.x = 2. inter.p2.y = 2. else: # Find the slope and intercept of the line a = dx / dy b = x1 - a * y1 # Find the determinant of the quadratic equation delta = 1. + a * a - b * b if delta > 0.: # solutions exist delta = sqrt(delta) inter.p1.y = (- a * b - delta) / (1. + a * a) inter.p1.x = a * inter.p1.y + b inter.p2.y = (- a * b + delta) / (1. + a * a) inter.p2.x = a * inter.p2.y + b else: # no solution, return values > 1 inter.p1.x = 2. inter.p1.y = 2. inter.p2.x = 2. inter.p2.y = 2. return inter cdef point circle_segment_single2(double x1, double y1, double x2, double y2): """ The intersection of a line with the unit circle. The intersection the closest to (x2, y2) is chosen. """ cdef double dx1, dy1, dx2, dy2 cdef intersections inter cdef point pt1, pt2, pt inter = circle_line(x1, y1, x2, y2) pt1 = inter.p1 pt2 = inter.p2 # Can be optimized, but just checking for correctness right now dx1 = fabs(pt1.x - x2) dy1 = fabs(pt1.y - y2) dx2 = fabs(pt2.x - x2) dy2 = fabs(pt2.y - y2) if dx1 > dy1: # compare based on x-axis if dx1 > dx2: pt = pt2 else: pt = pt1 else: if dy1 > dy2: pt = pt2 else: pt = pt1 return pt cdef intersections circle_segment(double x1, double y1, double x2, double y2): """ Intersection(s) of a segment with the unit circle. Discard any solution not on the segment. """ cdef intersections inter, inter_new cdef point pt1, pt2 inter = circle_line(x1, y1, x2, y2) pt1 = inter.p1 pt2 = inter.p2 if (pt1.x > x1 and pt1.x > x2) or (pt1.x < x1 and pt1.x < x2) or (pt1.y > y1 and pt1.y > y2) or (pt1.y < y1 and pt1.y < y2): pt1.x, pt1.y = 2., 2. if (pt2.x > x1 and pt2.x > x2) or (pt2.x < x1 and pt2.x < x2) or (pt2.y > y1 and pt2.y > y2) or (pt2.y < y1 and pt2.y < y2): pt2.x, pt2.y = 2., 2. if pt1.x > 1. and pt2.x < 2.: inter_new.p1 = pt1 inter_new.p2 = pt2 else: inter_new.p1 = pt2 inter_new.p2 = pt1 return inter_new cdef double overlap_area_triangle_unit_circle(double x1, double y1, double x2, double y2, double x3, double y3): """ Given a triangle defined by three points (x1, y1), (x2, y2), and (x3, y3), find the area of overlap with the unit circle. """ cdef double d1, d2, d3 cdef bool in1, in2, in3 cdef bool on1, on2, on3 cdef double area cdef double PI = np.pi cdef intersections inter cdef point pt1, pt2, pt3, pt4, pt5, pt6, pt_tmp # Find distance of all vertices to circle center d1 = x1 * x1 + y1 * y1 d2 = x2 * x2 + y2 * y2 d3 = x3 * x3 + y3 * y3 # Order vertices by distance from origin if d1 < d2: if d2 < d3: pass elif d1 < d3: x2, y2, d2, x3, y3, d3 = x3, y3, d3, x2, y2, d2 else: x1, y1, d1, x2, y2, d2, x3, y3, d3 = x3, y3, d3, x1, y1, d1, x2, y2, d2 else: if d1 < d3: x1, y1, d1, x2, y2, d2 = x2, y2, d2, x1, y1, d1 elif d2 < d3: x1, y1, d1, x2, y2, d2, x3, y3, d3 = x2, y2, d2, x3, y3, d3, x1, y1, d1 else: x1, y1, d1, x2, y2, d2, x3, y3, d3 = x3, y3, d3, x2, y2, d2, x1, y1, d1 if d1 > d2 or d2 > d3 or d1 > d3: raise Exception("ERROR: vertices did not sort correctly") # Determine number of vertices inside circle in1 = d1 < 1 in2 = d2 < 1 in3 = d3 < 1 # Determine which vertices are on the circle on1 = fabs(d1 - 1) < 1.e-10 on2 = fabs(d2 - 1) < 1.e-10 on3 = fabs(d3 - 1) < 1.e-10 if on3 or in3: # triangle is completely in circle area = area_triangle(x1, y1, x2, y2, x3, y3) elif in2 or on2: # If vertex 1 or 2 are on the edge of the circle, then we use the dot # product to vertex 3 to determine whether an intersection takes place. intersect13 = not on1 or x1 * (x3 - x1) + y1 * (y3 - y1) < 0. intersect23 = not on2 or x2 * (x3 - x2) + y2 * (y3 - y2) < 0. if intersect13 and intersect23 and not on2: pt1 = circle_segment_single2(x1, y1, x3, y3) pt2 = circle_segment_single2(x2, y2, x3, y3) area = area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) \ + area_triangle(x2, y2, pt1.x, pt1.y, pt2.x, pt2.y) \ + area_arc_unit(pt1.x, pt1.y, pt2.x, pt2.y) elif intersect13: pt1 = circle_segment_single2(x1, y1, x3, y3) area = area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) \ + area_arc_unit(x2, y2, pt1.x, pt1.y) elif intersect23: pt2 = circle_segment_single2(x2, y2, x3, y3) area = area_triangle(x1, y1, x2, y2, pt2.x, pt2.y) \ + area_arc_unit(x1, y1, pt2.x, pt2.y) else: area = area_arc_unit(x1, y1, x2, y2) elif on1: # The triangle is outside the circle area = 0.0 elif in1: # Check for intersections of far side with circle inter = circle_segment(x2, y2, x3, y3) pt1 = inter.p1 pt2 = inter.p2 pt3 = circle_segment_single2(x1, y1, x2, y2) pt4 = circle_segment_single2(x1, y1, x3, y3) if pt1.x > 1.: # indicates no intersection # Code taken from `sep.h`. # TODO: use `sep` and get rid of this Cython code. if (((0.-pt3.y) * (pt4.x-pt3.x) > (pt4.y-pt3.y) * (0.-pt3.x)) != ((y1-pt3.y) * (pt4.x-pt3.x) > (pt4.y-pt3.y) * (x1-pt3.x))): area = area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) \ + (PI - area_arc_unit(pt3.x, pt3.y, pt4.x, pt4.y)) else: area = area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) \ + area_arc_unit(pt3.x, pt3.y, pt4.x, pt4.y) else: if (pt2.x - x2)**2 + (pt2.y - y2)**2 < (pt1.x - x2)**2 + (pt1.y - y2)**2: pt1, pt2 = pt2, pt1 area = area_triangle(x1, y1, pt3.x, pt3.y, pt1.x, pt1.y) \ + area_triangle(x1, y1, pt1.x, pt1.y, pt2.x, pt2.y) \ + area_triangle(x1, y1, pt2.x, pt2.y, pt4.x, pt4.y) \ + area_arc_unit(pt1.x, pt1.y, pt3.x, pt3.y) \ + area_arc_unit(pt2.x, pt2.y, pt4.x, pt4.y) else: inter = circle_segment(x1, y1, x2, y2) pt1 = inter.p1 pt2 = inter.p2 inter = circle_segment(x2, y2, x3, y3) pt3 = inter.p1 pt4 = inter.p2 inter = circle_segment(x3, y3, x1, y1) pt5 = inter.p1 pt6 = inter.p2 if pt1.x <= 1.: xp, yp = 0.5 * (pt1.x + pt2.x), 0.5 * (pt1.y + pt2.y) area = overlap_area_triangle_unit_circle(x1, y1, x3, y3, xp, yp) \ + overlap_area_triangle_unit_circle(x2, y2, x3, y3, xp, yp) elif pt3.x <= 1.: xp, yp = 0.5 * (pt3.x + pt4.x), 0.5 * (pt3.y + pt4.y) area = overlap_area_triangle_unit_circle(x3, y3, x1, y1, xp, yp) \ + overlap_area_triangle_unit_circle(x2, y2, x1, y1, xp, yp) elif pt5.x <= 1.: xp, yp = 0.5 * (pt5.x + pt6.x), 0.5 * (pt5.y + pt6.y) area = overlap_area_triangle_unit_circle(x1, y1, x2, y2, xp, yp) \ + overlap_area_triangle_unit_circle(x3, y3, x2, y2, xp, yp) else: # no intersections if in_triangle(0., 0., x1, y1, x2, y2, x3, y3): return PI else: return 0. return area photutils-0.7.2/photutils/geometry/elliptical_overlap.c0000644000214200020070000134105513573510266025663 0ustar lbradleySTSCI\science00000000000000/* Generated by Cython 0.29.14 */ #define PY_SSIZE_T_CLEAN #include "Python.h" #ifndef Py_PYTHON_H #error Python headers needed to compile C extensions, please install development version of Python. #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) #error Cython requires Python 2.6+ or Python 3.3+. #else #define CYTHON_ABI "0_29_14" #define CYTHON_HEX_VERSION 0x001D0EF0 #define CYTHON_FUTURE_DIVISION 1 #include #ifndef offsetof #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) #endif #if !defined(WIN32) && !defined(MS_WINDOWS) #ifndef __stdcall #define __stdcall #endif #ifndef __cdecl #define __cdecl #endif #ifndef __fastcall #define __fastcall #endif #endif #ifndef DL_IMPORT #define DL_IMPORT(t) t #endif #ifndef DL_EXPORT #define DL_EXPORT(t) t #endif #define __PYX_COMMA , #ifndef HAVE_LONG_LONG #if PY_VERSION_HEX >= 0x02070000 #define HAVE_LONG_LONG #endif #endif #ifndef PY_LONG_LONG #define PY_LONG_LONG LONG_LONG #endif #ifndef Py_HUGE_VAL #define Py_HUGE_VAL HUGE_VAL #endif #ifdef PYPY_VERSION #define CYTHON_COMPILING_IN_PYPY 1 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 0 #undef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 0 #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #if PY_VERSION_HEX < 0x03050000 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #elif !defined(CYTHON_USE_ASYNC_SLOTS) #define CYTHON_USE_ASYNC_SLOTS 1 #endif #undef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 0 #undef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 0 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #undef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 1 #undef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 0 #undef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 0 #undef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 0 #undef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 0 #undef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 0 #undef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE 0 #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #elif defined(PYSTON_VERSION) #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 1 #define CYTHON_COMPILING_IN_CPYTHON 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #undef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 0 #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #ifndef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 0 #endif #ifndef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 1 #endif #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif #undef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 0 #undef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 0 #undef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 0 #undef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE 0 #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #else #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 1 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif #if PY_VERSION_HEX < 0x02070000 #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) #define CYTHON_USE_PYTYPE_LOOKUP 1 #endif #if PY_MAJOR_VERSION < 3 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #elif !defined(CYTHON_USE_ASYNC_SLOTS) #define CYTHON_USE_ASYNC_SLOTS 1 #endif #if PY_VERSION_HEX < 0x02070000 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #elif !defined(CYTHON_USE_PYLONG_INTERNALS) #define CYTHON_USE_PYLONG_INTERNALS 1 #endif #ifndef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 1 #endif #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif #if PY_VERSION_HEX < 0x030300F0 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #elif !defined(CYTHON_USE_UNICODE_WRITER) #define CYTHON_USE_UNICODE_WRITER 1 #endif #ifndef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 0 #endif #ifndef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 1 #endif #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif #ifndef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 1 #endif #ifndef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 1 #endif #ifndef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) #endif #ifndef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) #endif #ifndef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) #endif #ifndef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) #endif #endif #if !defined(CYTHON_FAST_PYCCALL) #define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) #endif #if CYTHON_USE_PYLONG_INTERNALS #include "longintrepr.h" #undef SHIFT #undef BASE #undef MASK #ifdef SIZEOF_VOID_P enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; #endif #endif #ifndef __has_attribute #define __has_attribute(x) 0 #endif #ifndef __has_cpp_attribute #define __has_cpp_attribute(x) 0 #endif #ifndef CYTHON_RESTRICT #if defined(__GNUC__) #define CYTHON_RESTRICT __restrict__ #elif defined(_MSC_VER) && _MSC_VER >= 1400 #define CYTHON_RESTRICT __restrict #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define CYTHON_RESTRICT restrict #else #define CYTHON_RESTRICT #endif #endif #ifndef CYTHON_UNUSED # if defined(__GNUC__) # if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) # define CYTHON_UNUSED __attribute__ ((__unused__)) # else # define CYTHON_UNUSED # endif # elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) # define CYTHON_UNUSED __attribute__ ((__unused__)) # else # define CYTHON_UNUSED # endif #endif #ifndef CYTHON_MAYBE_UNUSED_VAR # if defined(__cplusplus) template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } # else # define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) # endif #endif #ifndef CYTHON_NCP_UNUSED # if CYTHON_COMPILING_IN_CPYTHON # define CYTHON_NCP_UNUSED # else # define CYTHON_NCP_UNUSED CYTHON_UNUSED # endif #endif #define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) #ifdef _MSC_VER #ifndef _MSC_STDINT_H_ #if _MSC_VER < 1300 typedef unsigned char uint8_t; typedef unsigned int uint32_t; #else typedef unsigned __int8 uint8_t; typedef unsigned __int32 uint32_t; #endif #endif #else #include #endif #ifndef CYTHON_FALLTHROUGH #if defined(__cplusplus) && __cplusplus >= 201103L #if __has_cpp_attribute(fallthrough) #define CYTHON_FALLTHROUGH [[fallthrough]] #elif __has_cpp_attribute(clang::fallthrough) #define CYTHON_FALLTHROUGH [[clang::fallthrough]] #elif __has_cpp_attribute(gnu::fallthrough) #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] #endif #endif #ifndef CYTHON_FALLTHROUGH #if __has_attribute(fallthrough) #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) #else #define CYTHON_FALLTHROUGH #endif #endif #if defined(__clang__ ) && defined(__apple_build_version__) #if __apple_build_version__ < 7000000 #undef CYTHON_FALLTHROUGH #define CYTHON_FALLTHROUGH #endif #endif #endif #ifndef CYTHON_INLINE #if defined(__clang__) #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) #elif defined(__GNUC__) #define CYTHON_INLINE __inline__ #elif defined(_MSC_VER) #define CYTHON_INLINE __inline #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define CYTHON_INLINE inline #else #define CYTHON_INLINE #endif #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) #define Py_OptimizeFlag 0 #endif #define __PYX_BUILD_PY_SSIZE_T "n" #define CYTHON_FORMAT_SSIZE_T "z" #if PY_MAJOR_VERSION < 3 #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #define __Pyx_DefaultClassType PyClass_Type #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" #if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #else #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #endif #define __Pyx_DefaultClassType PyType_Type #endif #ifndef Py_TPFLAGS_CHECKTYPES #define Py_TPFLAGS_CHECKTYPES 0 #endif #ifndef Py_TPFLAGS_HAVE_INDEX #define Py_TPFLAGS_HAVE_INDEX 0 #endif #ifndef Py_TPFLAGS_HAVE_NEWBUFFER #define Py_TPFLAGS_HAVE_NEWBUFFER 0 #endif #ifndef Py_TPFLAGS_HAVE_FINALIZE #define Py_TPFLAGS_HAVE_FINALIZE 0 #endif #ifndef METH_STACKLESS #define METH_STACKLESS 0 #endif #if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) #ifndef METH_FASTCALL #define METH_FASTCALL 0x80 #endif typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); #else #define __Pyx_PyCFunctionFast _PyCFunctionFast #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords #endif #if CYTHON_FAST_PYCCALL #define __Pyx_PyFastCFunction_Check(func)\ ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) #else #define __Pyx_PyFastCFunction_Check(func) 0 #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) #define PyObject_Malloc(s) PyMem_Malloc(s) #define PyObject_Free(p) PyMem_Free(p) #define PyObject_Realloc(p) PyMem_Realloc(p) #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 #define PyMem_RawMalloc(n) PyMem_Malloc(n) #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) #define PyMem_RawFree(p) PyMem_Free(p) #endif #if CYTHON_COMPILING_IN_PYSTON #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) #else #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) #endif #if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 #define __Pyx_PyThreadState_Current PyThreadState_GET() #elif PY_VERSION_HEX >= 0x03060000 #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() #elif PY_VERSION_HEX >= 0x03000000 #define __Pyx_PyThreadState_Current PyThreadState_GET() #else #define __Pyx_PyThreadState_Current _PyThreadState_Current #endif #if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) #include "pythread.h" #define Py_tss_NEEDS_INIT 0 typedef int Py_tss_t; static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { *key = PyThread_create_key(); return 0; } static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); *key = Py_tss_NEEDS_INIT; return key; } static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { PyObject_Free(key); } static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { return *key != Py_tss_NEEDS_INIT; } static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { PyThread_delete_key(*key); *key = Py_tss_NEEDS_INIT; } static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { return PyThread_set_key_value(*key, value); } static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { return PyThread_get_key_value(*key); } #endif #if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) #define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) #else #define __Pyx_PyDict_NewPresized(n) PyDict_New() #endif #if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) #else #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS #define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) #else #define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) #endif #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) #define CYTHON_PEP393_ENABLED 1 #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ 0 : _PyUnicode_Ready((PyObject *)(op))) #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) #else #define CYTHON_PEP393_ENABLED 0 #define PyUnicode_1BYTE_KIND 1 #define PyUnicode_2BYTE_KIND 2 #define PyUnicode_4BYTE_KIND 4 #define __Pyx_PyUnicode_READY(op) (0) #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) #endif #if CYTHON_COMPILING_IN_PYPY #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) #else #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) #endif #define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) #define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) #else #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) #endif #if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) #define PyObject_ASCII(o) PyObject_Repr(o) #endif #if PY_MAJOR_VERSION >= 3 #define PyBaseString_Type PyUnicode_Type #define PyStringObject PyUnicodeObject #define PyString_Type PyUnicode_Type #define PyString_Check PyUnicode_Check #define PyString_CheckExact PyUnicode_CheckExact #define PyObject_Unicode PyObject_Str #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) #else #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) #endif #ifndef PySet_CheckExact #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) #endif #if CYTHON_ASSUME_SAFE_MACROS #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) #else #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) #endif #if PY_MAJOR_VERSION >= 3 #define PyIntObject PyLongObject #define PyInt_Type PyLong_Type #define PyInt_Check(op) PyLong_Check(op) #define PyInt_CheckExact(op) PyLong_CheckExact(op) #define PyInt_FromString PyLong_FromString #define PyInt_FromUnicode PyLong_FromUnicode #define PyInt_FromLong PyLong_FromLong #define PyInt_FromSize_t PyLong_FromSize_t #define PyInt_FromSsize_t PyLong_FromSsize_t #define PyInt_AsLong PyLong_AsLong #define PyInt_AS_LONG PyLong_AS_LONG #define PyInt_AsSsize_t PyLong_AsSsize_t #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask #define PyNumber_Int PyNumber_Long #endif #if PY_MAJOR_VERSION >= 3 #define PyBoolObject PyLongObject #endif #if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY #ifndef PyUnicode_InternFromString #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) #endif #endif #if PY_VERSION_HEX < 0x030200A4 typedef long Py_hash_t; #define __Pyx_PyInt_FromHash_t PyInt_FromLong #define __Pyx_PyInt_AsHash_t PyInt_AsLong #else #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : (Py_INCREF(func), func)) #else #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) #endif #if CYTHON_USE_ASYNC_SLOTS #if PY_VERSION_HEX >= 0x030500B1 #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) #else #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) #endif #else #define __Pyx_PyType_AsAsync(obj) NULL #endif #ifndef __Pyx_PyAsyncMethodsStruct typedef struct { unaryfunc am_await; unaryfunc am_aiter; unaryfunc am_anext; } __Pyx_PyAsyncMethodsStruct; #endif #if defined(WIN32) || defined(MS_WINDOWS) #define _USE_MATH_DEFINES #endif #include #ifdef NAN #define __PYX_NAN() ((float) NAN) #else static CYTHON_INLINE float __PYX_NAN() { float value; memset(&value, 0xFF, sizeof(value)); return value; } #endif #if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) #define __Pyx_truncl trunc #else #define __Pyx_truncl truncl #endif #define __PYX_ERR(f_index, lineno, Ln_error) \ { \ __pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \ } #ifndef __PYX_EXTERN_C #ifdef __cplusplus #define __PYX_EXTERN_C extern "C" #else #define __PYX_EXTERN_C extern #endif #endif #define __PYX_HAVE__photutils__geometry__elliptical_overlap #define __PYX_HAVE_API__photutils__geometry__elliptical_overlap /* Early includes */ #include #include #include "numpy/arrayobject.h" #include "numpy/ufuncobject.h" #include "math.h" #include "pythread.h" #ifdef _OPENMP #include #endif /* _OPENMP */ #if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) #define CYTHON_WITHOUT_ASSERTIONS #endif typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; #define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 #define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 #define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) #define __PYX_DEFAULT_STRING_ENCODING "" #define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString #define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize #define __Pyx_uchar_cast(c) ((unsigned char)c) #define __Pyx_long_cast(x) ((long)x) #define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ (sizeof(type) < sizeof(Py_ssize_t)) ||\ (sizeof(type) > sizeof(Py_ssize_t) &&\ likely(v < (type)PY_SSIZE_T_MAX ||\ v == (type)PY_SSIZE_T_MAX) &&\ (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ v == (type)PY_SSIZE_T_MIN))) ||\ (sizeof(type) == sizeof(Py_ssize_t) &&\ (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ v == (type)PY_SSIZE_T_MAX))) ) static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { return (size_t) i < (size_t) limit; } #if defined (__cplusplus) && __cplusplus >= 201103L #include #define __Pyx_sst_abs(value) std::abs(value) #elif SIZEOF_INT >= SIZEOF_SIZE_T #define __Pyx_sst_abs(value) abs(value) #elif SIZEOF_LONG >= SIZEOF_SIZE_T #define __Pyx_sst_abs(value) labs(value) #elif defined (_MSC_VER) #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define __Pyx_sst_abs(value) llabs(value) #elif defined (__GNUC__) #define __Pyx_sst_abs(value) __builtin_llabs(value) #else #define __Pyx_sst_abs(value) ((value<0) ? -value : value) #endif static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); #define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) #define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) #define __Pyx_PyBytes_FromString PyBytes_FromString #define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); #if PY_MAJOR_VERSION < 3 #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize #else #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize #endif #define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) #define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) #define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) #define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) #define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) #define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { const Py_UNICODE *u_end = u; while (*u_end++) ; return (size_t)(u_end - u - 1); } #define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) #define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode #define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode #define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) #define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); #define __Pyx_PySequence_Tuple(obj)\ (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); #if CYTHON_ASSUME_SAFE_MACROS #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) #else #define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) #endif #define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) #else #define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) #endif #define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII static int __Pyx_sys_getdefaultencoding_not_ascii; static int __Pyx_init_sys_getdefaultencoding_params(void) { PyObject* sys; PyObject* default_encoding = NULL; PyObject* ascii_chars_u = NULL; PyObject* ascii_chars_b = NULL; const char* default_encoding_c; sys = PyImport_ImportModule("sys"); if (!sys) goto bad; default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); Py_DECREF(sys); if (!default_encoding) goto bad; default_encoding_c = PyBytes_AsString(default_encoding); if (!default_encoding_c) goto bad; if (strcmp(default_encoding_c, "ascii") == 0) { __Pyx_sys_getdefaultencoding_not_ascii = 0; } else { char ascii_chars[128]; int c; for (c = 0; c < 128; c++) { ascii_chars[c] = c; } __Pyx_sys_getdefaultencoding_not_ascii = 1; ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); if (!ascii_chars_u) goto bad; ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { PyErr_Format( PyExc_ValueError, "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", default_encoding_c); goto bad; } Py_DECREF(ascii_chars_u); Py_DECREF(ascii_chars_b); } Py_DECREF(default_encoding); return 0; bad: Py_XDECREF(default_encoding); Py_XDECREF(ascii_chars_u); Py_XDECREF(ascii_chars_b); return -1; } #endif #if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) #else #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) #if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT static char* __PYX_DEFAULT_STRING_ENCODING; static int __Pyx_init_sys_getdefaultencoding_params(void) { PyObject* sys; PyObject* default_encoding = NULL; char* default_encoding_c; sys = PyImport_ImportModule("sys"); if (!sys) goto bad; default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); Py_DECREF(sys); if (!default_encoding) goto bad; default_encoding_c = PyBytes_AsString(default_encoding); if (!default_encoding_c) goto bad; __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); Py_DECREF(default_encoding); return 0; bad: Py_XDECREF(default_encoding); return -1; } #endif #endif /* Test for GCC > 2.95 */ #if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #else /* !__GNUC__ or GCC < 2.95 */ #define likely(x) (x) #define unlikely(x) (x) #endif /* __GNUC__ */ static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } static PyObject *__pyx_m = NULL; static PyObject *__pyx_d; static PyObject *__pyx_b; static PyObject *__pyx_cython_runtime = NULL; static PyObject *__pyx_empty_tuple; static PyObject *__pyx_empty_bytes; static PyObject *__pyx_empty_unicode; static int __pyx_lineno; static int __pyx_clineno = 0; static const char * __pyx_cfilenm= __FILE__; static const char *__pyx_filename; /* Header.proto */ #if !defined(CYTHON_CCOMPLEX) #if defined(__cplusplus) #define CYTHON_CCOMPLEX 1 #elif defined(_Complex_I) #define CYTHON_CCOMPLEX 1 #else #define CYTHON_CCOMPLEX 0 #endif #endif #if CYTHON_CCOMPLEX #ifdef __cplusplus #include #else #include #endif #endif #if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__) #undef _Complex_I #define _Complex_I 1.0fj #endif static const char *__pyx_f[] = { "photutils/geometry/elliptical_overlap.pyx", "__init__.pxd", "type.pxd", "bool.pxd", "complex.pxd", }; /* BufferFormatStructs.proto */ #define IS_UNSIGNED(type) (((type) -1) > 0) struct __Pyx_StructField_; #define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0) typedef struct { const char* name; struct __Pyx_StructField_* fields; size_t size; size_t arraysize[8]; int ndim; char typegroup; char is_unsigned; int flags; } __Pyx_TypeInfo; typedef struct __Pyx_StructField_ { __Pyx_TypeInfo* type; const char* name; size_t offset; } __Pyx_StructField; typedef struct { __Pyx_StructField* field; size_t parent_offset; } __Pyx_BufFmt_StackElem; typedef struct { __Pyx_StructField root; __Pyx_BufFmt_StackElem* head; size_t fmt_offset; size_t new_count, enc_count; size_t struct_alignment; int is_complex; char enc_type; char new_packmode; char enc_packmode; char is_valid_array; } __Pyx_BufFmt_Context; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":776 * # in Cython to enable them only on the right systems. * * ctypedef npy_int8 int8_t # <<<<<<<<<<<<<< * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t */ typedef npy_int8 __pyx_t_5numpy_int8_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":777 * * ctypedef npy_int8 int8_t * ctypedef npy_int16 int16_t # <<<<<<<<<<<<<< * ctypedef npy_int32 int32_t * ctypedef npy_int64 int64_t */ typedef npy_int16 __pyx_t_5numpy_int16_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":778 * ctypedef npy_int8 int8_t * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t # <<<<<<<<<<<<<< * ctypedef npy_int64 int64_t * #ctypedef npy_int96 int96_t */ typedef npy_int32 __pyx_t_5numpy_int32_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":779 * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t * ctypedef npy_int64 int64_t # <<<<<<<<<<<<<< * #ctypedef npy_int96 int96_t * #ctypedef npy_int128 int128_t */ typedef npy_int64 __pyx_t_5numpy_int64_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":783 * #ctypedef npy_int128 int128_t * * ctypedef npy_uint8 uint8_t # <<<<<<<<<<<<<< * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t */ typedef npy_uint8 __pyx_t_5numpy_uint8_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":784 * * ctypedef npy_uint8 uint8_t * ctypedef npy_uint16 uint16_t # <<<<<<<<<<<<<< * ctypedef npy_uint32 uint32_t * ctypedef npy_uint64 uint64_t */ typedef npy_uint16 __pyx_t_5numpy_uint16_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":785 * ctypedef npy_uint8 uint8_t * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t # <<<<<<<<<<<<<< * ctypedef npy_uint64 uint64_t * #ctypedef npy_uint96 uint96_t */ typedef npy_uint32 __pyx_t_5numpy_uint32_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":786 * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t * ctypedef npy_uint64 uint64_t # <<<<<<<<<<<<<< * #ctypedef npy_uint96 uint96_t * #ctypedef npy_uint128 uint128_t */ typedef npy_uint64 __pyx_t_5numpy_uint64_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":790 * #ctypedef npy_uint128 uint128_t * * ctypedef npy_float32 float32_t # <<<<<<<<<<<<<< * ctypedef npy_float64 float64_t * #ctypedef npy_float80 float80_t */ typedef npy_float32 __pyx_t_5numpy_float32_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":791 * * ctypedef npy_float32 float32_t * ctypedef npy_float64 float64_t # <<<<<<<<<<<<<< * #ctypedef npy_float80 float80_t * #ctypedef npy_float128 float128_t */ typedef npy_float64 __pyx_t_5numpy_float64_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":800 * # The int types are mapped a bit surprising -- * # numpy.int corresponds to 'l' and numpy.long to 'q' * ctypedef npy_long int_t # <<<<<<<<<<<<<< * ctypedef npy_longlong long_t * ctypedef npy_longlong longlong_t */ typedef npy_long __pyx_t_5numpy_int_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":801 * # numpy.int corresponds to 'l' and numpy.long to 'q' * ctypedef npy_long int_t * ctypedef npy_longlong long_t # <<<<<<<<<<<<<< * ctypedef npy_longlong longlong_t * */ typedef npy_longlong __pyx_t_5numpy_long_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":802 * ctypedef npy_long int_t * ctypedef npy_longlong long_t * ctypedef npy_longlong longlong_t # <<<<<<<<<<<<<< * * ctypedef npy_ulong uint_t */ typedef npy_longlong __pyx_t_5numpy_longlong_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":804 * ctypedef npy_longlong longlong_t * * ctypedef npy_ulong uint_t # <<<<<<<<<<<<<< * ctypedef npy_ulonglong ulong_t * ctypedef npy_ulonglong ulonglong_t */ typedef npy_ulong __pyx_t_5numpy_uint_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":805 * * ctypedef npy_ulong uint_t * ctypedef npy_ulonglong ulong_t # <<<<<<<<<<<<<< * ctypedef npy_ulonglong ulonglong_t * */ typedef npy_ulonglong __pyx_t_5numpy_ulong_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":806 * ctypedef npy_ulong uint_t * ctypedef npy_ulonglong ulong_t * ctypedef npy_ulonglong ulonglong_t # <<<<<<<<<<<<<< * * ctypedef npy_intp intp_t */ typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":808 * ctypedef npy_ulonglong ulonglong_t * * ctypedef npy_intp intp_t # <<<<<<<<<<<<<< * ctypedef npy_uintp uintp_t * */ typedef npy_intp __pyx_t_5numpy_intp_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":809 * * ctypedef npy_intp intp_t * ctypedef npy_uintp uintp_t # <<<<<<<<<<<<<< * * ctypedef npy_double float_t */ typedef npy_uintp __pyx_t_5numpy_uintp_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":811 * ctypedef npy_uintp uintp_t * * ctypedef npy_double float_t # <<<<<<<<<<<<<< * ctypedef npy_double double_t * ctypedef npy_longdouble longdouble_t */ typedef npy_double __pyx_t_5numpy_float_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":812 * * ctypedef npy_double float_t * ctypedef npy_double double_t # <<<<<<<<<<<<<< * ctypedef npy_longdouble longdouble_t * */ typedef npy_double __pyx_t_5numpy_double_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":813 * ctypedef npy_double float_t * ctypedef npy_double double_t * ctypedef npy_longdouble longdouble_t # <<<<<<<<<<<<<< * * ctypedef npy_cfloat cfloat_t */ typedef npy_longdouble __pyx_t_5numpy_longdouble_t; /* "photutils/geometry/elliptical_overlap.pyx":27 * * DTYPE = np.float64 * ctypedef np.float64_t DTYPE_t # <<<<<<<<<<<<<< * * cimport cython */ typedef __pyx_t_5numpy_float64_t __pyx_t_9photutils_8geometry_18elliptical_overlap_DTYPE_t; /* Declarations.proto */ #if CYTHON_CCOMPLEX #ifdef __cplusplus typedef ::std::complex< float > __pyx_t_float_complex; #else typedef float _Complex __pyx_t_float_complex; #endif #else typedef struct { float real, imag; } __pyx_t_float_complex; #endif static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float); /* Declarations.proto */ #if CYTHON_CCOMPLEX #ifdef __cplusplus typedef ::std::complex< double > __pyx_t_double_complex; #else typedef double _Complex __pyx_t_double_complex; #endif #else typedef struct { double real, imag; } __pyx_t_double_complex; #endif static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double); /*--- Type declarations ---*/ /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":815 * ctypedef npy_longdouble longdouble_t * * ctypedef npy_cfloat cfloat_t # <<<<<<<<<<<<<< * ctypedef npy_cdouble cdouble_t * ctypedef npy_clongdouble clongdouble_t */ typedef npy_cfloat __pyx_t_5numpy_cfloat_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":816 * * ctypedef npy_cfloat cfloat_t * ctypedef npy_cdouble cdouble_t # <<<<<<<<<<<<<< * ctypedef npy_clongdouble clongdouble_t * */ typedef npy_cdouble __pyx_t_5numpy_cdouble_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":817 * ctypedef npy_cfloat cfloat_t * ctypedef npy_cdouble cdouble_t * ctypedef npy_clongdouble clongdouble_t # <<<<<<<<<<<<<< * * ctypedef npy_cdouble complex_t */ typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":819 * ctypedef npy_clongdouble clongdouble_t * * ctypedef npy_cdouble complex_t # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew1(a): */ typedef npy_cdouble __pyx_t_5numpy_complex_t; /* --- Runtime support code (head) --- */ /* Refnanny.proto */ #ifndef CYTHON_REFNANNY #define CYTHON_REFNANNY 0 #endif #if CYTHON_REFNANNY typedef struct { void (*INCREF)(void*, PyObject*, int); void (*DECREF)(void*, PyObject*, int); void (*GOTREF)(void*, PyObject*, int); void (*GIVEREF)(void*, PyObject*, int); void* (*SetupContext)(const char*, int, const char*); void (*FinishContext)(void**); } __Pyx_RefNannyAPIStruct; static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; #ifdef WITH_THREAD #define __Pyx_RefNannySetupContext(name, acquire_gil)\ if (acquire_gil) {\ PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ PyGILState_Release(__pyx_gilstate_save);\ } else {\ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ } #else #define __Pyx_RefNannySetupContext(name, acquire_gil)\ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) #endif #define __Pyx_RefNannyFinishContext()\ __Pyx_RefNanny->FinishContext(&__pyx_refnanny) #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) #else #define __Pyx_RefNannyDeclarations #define __Pyx_RefNannySetupContext(name, acquire_gil) #define __Pyx_RefNannyFinishContext() #define __Pyx_INCREF(r) Py_INCREF(r) #define __Pyx_DECREF(r) Py_DECREF(r) #define __Pyx_GOTREF(r) #define __Pyx_GIVEREF(r) #define __Pyx_XINCREF(r) Py_XINCREF(r) #define __Pyx_XDECREF(r) Py_XDECREF(r) #define __Pyx_XGOTREF(r) #define __Pyx_XGIVEREF(r) #endif #define __Pyx_XDECREF_SET(r, v) do {\ PyObject *tmp = (PyObject *) r;\ r = v; __Pyx_XDECREF(tmp);\ } while (0) #define __Pyx_DECREF_SET(r, v) do {\ PyObject *tmp = (PyObject *) r;\ r = v; __Pyx_DECREF(tmp);\ } while (0) #define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) #define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) /* PyObjectGetAttrStr.proto */ #if CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); #else #define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) #endif /* GetBuiltinName.proto */ static PyObject *__Pyx_GetBuiltinName(PyObject *name); /* RaiseArgTupleInvalid.proto */ static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /* RaiseDoubleKeywords.proto */ static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); /* ParseKeywords.proto */ static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ const char* function_name); /* PyDictVersioning.proto */ #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS #define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) #define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) #define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ (version_var) = __PYX_GET_DICT_VERSION(dict);\ (cache_var) = (value); #define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ static PY_UINT64_T __pyx_dict_version = 0;\ static PyObject *__pyx_dict_cached_value = NULL;\ if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ (VAR) = __pyx_dict_cached_value;\ } else {\ (VAR) = __pyx_dict_cached_value = (LOOKUP);\ __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ }\ } static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); #else #define __PYX_GET_DICT_VERSION(dict) (0) #define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) #define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); #endif /* GetModuleGlobalName.proto */ #if CYTHON_USE_DICT_VERSIONS #define __Pyx_GetModuleGlobalName(var, name) {\ static PY_UINT64_T __pyx_dict_version = 0;\ static PyObject *__pyx_dict_cached_value = NULL;\ (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ } #define __Pyx_GetModuleGlobalNameUncached(var, name) {\ PY_UINT64_T __pyx_dict_version;\ PyObject *__pyx_dict_cached_value;\ (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ } static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); #else #define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) #define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); #endif /* PyObjectCall.proto */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); #else #define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) #endif /* ExtTypeTest.proto */ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /* IsLittleEndian.proto */ static CYTHON_INLINE int __Pyx_Is_Little_Endian(void); /* BufferFormatCheck.proto */ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts); static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, __Pyx_BufFmt_StackElem* stack, __Pyx_TypeInfo* type); /* BufferGetAndValidate.proto */ #define __Pyx_GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)\ ((obj == Py_None || obj == NULL) ?\ (__Pyx_ZeroBuffer(buf), 0) :\ __Pyx__GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)) static int __Pyx__GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack); static void __Pyx_ZeroBuffer(Py_buffer* buf); static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info); static Py_ssize_t __Pyx_minusones[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; static Py_ssize_t __Pyx_zeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* BufferIndexError.proto */ static void __Pyx_RaiseBufferIndexError(int axis); #define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1) /* PyThreadStateGet.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; #define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; #define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type #else #define __Pyx_PyThreadState_declare #define __Pyx_PyThreadState_assign #define __Pyx_PyErr_Occurred() PyErr_Occurred() #endif /* PyErrFetchRestore.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) #define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) #define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) #define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) #define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) #else #define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) #endif #else #define __Pyx_PyErr_Clear() PyErr_Clear() #define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) #define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) #define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) #define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) #endif /* WriteUnraisableException.proto */ static void __Pyx_WriteUnraisable(const char *name, int clineno, int lineno, const char *filename, int full_traceback, int nogil); /* RaiseException.proto */ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); /* PyCFunctionFastCall.proto */ #if CYTHON_FAST_PYCCALL static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); #else #define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) #endif /* PyFunctionFastCall.proto */ #if CYTHON_FAST_PYCALL #define __Pyx_PyFunction_FastCall(func, args, nargs)\ __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) #if 1 || PY_VERSION_HEX < 0x030600B1 static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); #else #define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) #endif #define __Pyx_BUILD_ASSERT_EXPR(cond)\ (sizeof(char [1 - 2*!(cond)]) - 1) #ifndef Py_MEMBER_SIZE #define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) #endif static size_t __pyx_pyframe_localsplus_offset = 0; #include "frameobject.h" #define __Pxy_PyFrame_Initialize_Offsets()\ ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) #define __Pyx_PyFrame_GetLocalsplus(frame)\ (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) #endif /* PyObjectCallMethO.proto */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); #endif /* PyObjectCallOneArg.proto */ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); /* DictGetItem.proto */ #if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key); #define __Pyx_PyObject_Dict_GetItem(obj, name)\ (likely(PyDict_CheckExact(obj)) ?\ __Pyx_PyDict_GetItem(obj, name) : PyObject_GetItem(obj, name)) #else #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key) #define __Pyx_PyObject_Dict_GetItem(obj, name) PyObject_GetItem(obj, name) #endif /* RaiseTooManyValuesToUnpack.proto */ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); /* RaiseNeedMoreValuesToUnpack.proto */ static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); /* RaiseNoneIterError.proto */ static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); /* GetTopmostException.proto */ #if CYTHON_USE_EXC_INFO_STACK static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); #endif /* SaveResetException.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave(__pyx_tstate, type, value, tb) static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); #define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset(__pyx_tstate, type, value, tb) static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); #else #define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) #define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) #endif /* PyErrExceptionMatches.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); #else #define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) #endif /* GetException.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); #else static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); #endif /* TypeImport.proto */ #ifndef __PYX_HAVE_RT_ImportType_proto #define __PYX_HAVE_RT_ImportType_proto enum __Pyx_ImportType_CheckSize { __Pyx_ImportType_CheckSize_Error = 0, __Pyx_ImportType_CheckSize_Warn = 1, __Pyx_ImportType_CheckSize_Ignore = 2 }; static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); #endif /* Import.proto */ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); /* CLineInTraceback.proto */ #ifdef CYTHON_CLINE_IN_TRACEBACK #define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) #else static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); #endif /* CodeObjectCache.proto */ typedef struct { PyCodeObject* code_object; int code_line; } __Pyx_CodeObjectCacheEntry; struct __Pyx_CodeObjectCache { int count; int max_count; __Pyx_CodeObjectCacheEntry* entries; }; static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); static PyCodeObject *__pyx_find_code_object(int code_line); static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); /* AddTraceback.proto */ static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename); /* BufferStructDeclare.proto */ typedef struct { Py_ssize_t shape, strides, suboffsets; } __Pyx_Buf_DimInfo; typedef struct { size_t refcount; Py_buffer pybuffer; } __Pyx_Buffer; typedef struct { __Pyx_Buffer *rcbuffer; char *data; __Pyx_Buf_DimInfo diminfo[8]; } __Pyx_LocalBuf_ND; #if PY_MAJOR_VERSION < 3 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags); static void __Pyx_ReleaseBuffer(Py_buffer *view); #else #define __Pyx_GetBuffer PyObject_GetBuffer #define __Pyx_ReleaseBuffer PyBuffer_Release #endif /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); /* RealImag.proto */ #if CYTHON_CCOMPLEX #ifdef __cplusplus #define __Pyx_CREAL(z) ((z).real()) #define __Pyx_CIMAG(z) ((z).imag()) #else #define __Pyx_CREAL(z) (__real__(z)) #define __Pyx_CIMAG(z) (__imag__(z)) #endif #else #define __Pyx_CREAL(z) ((z).real) #define __Pyx_CIMAG(z) ((z).imag) #endif #if defined(__cplusplus) && CYTHON_CCOMPLEX\ && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103) #define __Pyx_SET_CREAL(z,x) ((z).real(x)) #define __Pyx_SET_CIMAG(z,y) ((z).imag(y)) #else #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x) #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y) #endif /* Arithmetic.proto */ #if CYTHON_CCOMPLEX #define __Pyx_c_eq_float(a, b) ((a)==(b)) #define __Pyx_c_sum_float(a, b) ((a)+(b)) #define __Pyx_c_diff_float(a, b) ((a)-(b)) #define __Pyx_c_prod_float(a, b) ((a)*(b)) #define __Pyx_c_quot_float(a, b) ((a)/(b)) #define __Pyx_c_neg_float(a) (-(a)) #ifdef __cplusplus #define __Pyx_c_is_zero_float(z) ((z)==(float)0) #define __Pyx_c_conj_float(z) (::std::conj(z)) #if 1 #define __Pyx_c_abs_float(z) (::std::abs(z)) #define __Pyx_c_pow_float(a, b) (::std::pow(a, b)) #endif #else #define __Pyx_c_is_zero_float(z) ((z)==0) #define __Pyx_c_conj_float(z) (conjf(z)) #if 1 #define __Pyx_c_abs_float(z) (cabsf(z)) #define __Pyx_c_pow_float(a, b) (cpowf(a, b)) #endif #endif #else static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex); static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex); #if 1 static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex, __pyx_t_float_complex); #endif #endif /* Arithmetic.proto */ #if CYTHON_CCOMPLEX #define __Pyx_c_eq_double(a, b) ((a)==(b)) #define __Pyx_c_sum_double(a, b) ((a)+(b)) #define __Pyx_c_diff_double(a, b) ((a)-(b)) #define __Pyx_c_prod_double(a, b) ((a)*(b)) #define __Pyx_c_quot_double(a, b) ((a)/(b)) #define __Pyx_c_neg_double(a) (-(a)) #ifdef __cplusplus #define __Pyx_c_is_zero_double(z) ((z)==(double)0) #define __Pyx_c_conj_double(z) (::std::conj(z)) #if 1 #define __Pyx_c_abs_double(z) (::std::abs(z)) #define __Pyx_c_pow_double(a, b) (::std::pow(a, b)) #endif #else #define __Pyx_c_is_zero_double(z) ((z)==0) #define __Pyx_c_conj_double(z) (conj(z)) #if 1 #define __Pyx_c_abs_double(z) (cabs(z)) #define __Pyx_c_pow_double(a, b) (cpow(a, b)) #endif #endif #else static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex); static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex); #if 1 static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex, __pyx_t_double_complex); #endif #endif /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__NPY_TYPES(enum NPY_TYPES value); /* CIntFromPy.proto */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); /* CIntFromPy.proto */ static CYTHON_INLINE unsigned int __Pyx_PyInt_As_unsigned_int(PyObject *); /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); /* CIntFromPy.proto */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); /* FastTypeChecks.proto */ #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); #else #define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) #define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) #define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) #endif #define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) /* CheckBinaryVersion.proto */ static int __Pyx_check_binary_version(void); /* FunctionImport.proto */ static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**f)(void), const char *sig); /* InitStrings.proto */ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /* Module declarations from 'cpython.buffer' */ /* Module declarations from 'libc.string' */ /* Module declarations from 'libc.stdio' */ /* Module declarations from '__builtin__' */ /* Module declarations from 'cpython.type' */ static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0; /* Module declarations from 'cpython.version' */ /* Module declarations from 'cpython.exc' */ /* Module declarations from 'cpython.module' */ /* Module declarations from 'cpython.mem' */ /* Module declarations from 'cpython.tuple' */ /* Module declarations from 'cpython.list' */ /* Module declarations from 'cpython.sequence' */ /* Module declarations from 'cpython.mapping' */ /* Module declarations from 'cpython.iterator' */ /* Module declarations from 'cpython.number' */ /* Module declarations from 'cpython.int' */ /* Module declarations from '__builtin__' */ /* Module declarations from 'cpython.bool' */ static PyTypeObject *__pyx_ptype_7cpython_4bool_bool = 0; /* Module declarations from 'cpython.long' */ /* Module declarations from 'cpython.float' */ /* Module declarations from '__builtin__' */ /* Module declarations from 'cpython.complex' */ static PyTypeObject *__pyx_ptype_7cpython_7complex_complex = 0; /* Module declarations from 'cpython.string' */ /* Module declarations from 'cpython.unicode' */ /* Module declarations from 'cpython.dict' */ /* Module declarations from 'cpython.instance' */ /* Module declarations from 'cpython.function' */ /* Module declarations from 'cpython.method' */ /* Module declarations from 'cpython.weakref' */ /* Module declarations from 'cpython.getargs' */ /* Module declarations from 'cpython.pythread' */ /* Module declarations from 'cpython.pystate' */ /* Module declarations from 'cpython.cobject' */ /* Module declarations from 'cpython.oldbuffer' */ /* Module declarations from 'cpython.set' */ /* Module declarations from 'cpython.bytes' */ /* Module declarations from 'cpython.pycapsule' */ /* Module declarations from 'cpython' */ /* Module declarations from 'cpython.object' */ /* Module declarations from 'cpython.ref' */ /* Module declarations from 'numpy' */ /* Module declarations from 'numpy' */ static PyTypeObject *__pyx_ptype_5numpy_dtype = 0; static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0; static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0; static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0; static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0; static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); /*proto*/ /* Module declarations from 'cython' */ /* Module declarations from 'photutils.geometry.core' */ static double (*__pyx_f_9photutils_8geometry_4core_distance)(double, double, double, double); /*proto*/ static double (*__pyx_f_9photutils_8geometry_4core_area_triangle)(double, double, double, double, double, double); /*proto*/ static double (*__pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle)(double, double, double, double, double, double); /*proto*/ /* Module declarations from 'photutils.geometry.elliptical_overlap' */ static double __pyx_f_9photutils_8geometry_18elliptical_overlap_elliptical_overlap_single_subpixel(double, double, double, double, double, double, double, int); /*proto*/ static double __pyx_f_9photutils_8geometry_18elliptical_overlap_elliptical_overlap_single_exact(double, double, double, double, double, double, double); /*proto*/ static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_9photutils_8geometry_18elliptical_overlap_DTYPE_t = { "DTYPE_t", NULL, sizeof(__pyx_t_9photutils_8geometry_18elliptical_overlap_DTYPE_t), { 0 }, 0, 'R', 0, 0 }; #define __Pyx_MODULE_NAME "photutils.geometry.elliptical_overlap" extern int __pyx_module_is_main_photutils__geometry__elliptical_overlap; int __pyx_module_is_main_photutils__geometry__elliptical_overlap = 0; /* Implementation of 'photutils.geometry.elliptical_overlap' */ static PyObject *__pyx_builtin_range; static PyObject *__pyx_builtin_ValueError; static PyObject *__pyx_builtin_RuntimeError; static PyObject *__pyx_builtin_ImportError; static const char __pyx_k_i[] = "i"; static const char __pyx_k_j[] = "j"; static const char __pyx_k_r[] = "r"; static const char __pyx_k_x[] = "x"; static const char __pyx_k_y[] = "y"; static const char __pyx_k_dx[] = "dx"; static const char __pyx_k_dy[] = "dy"; static const char __pyx_k_np[] = "np"; static const char __pyx_k_nx[] = "nx"; static const char __pyx_k_ny[] = "ny"; static const char __pyx_k_rx[] = "rx"; static const char __pyx_k_ry[] = "ry"; static const char __pyx_k_all[] = "__all__"; static const char __pyx_k_frac[] = "frac"; static const char __pyx_k_main[] = "__main__"; static const char __pyx_k_name[] = "__name__"; static const char __pyx_k_norm[] = "norm"; static const char __pyx_k_test[] = "__test__"; static const char __pyx_k_xmax[] = "xmax"; static const char __pyx_k_xmin[] = "xmin"; static const char __pyx_k_ymax[] = "ymax"; static const char __pyx_k_ymin[] = "ymin"; static const char __pyx_k_DTYPE[] = "DTYPE"; static const char __pyx_k_bxmax[] = "bxmax"; static const char __pyx_k_bxmin[] = "bxmin"; static const char __pyx_k_bymax[] = "bymax"; static const char __pyx_k_bymin[] = "bymin"; static const char __pyx_k_dtype[] = "dtype"; static const char __pyx_k_numpy[] = "numpy"; static const char __pyx_k_pxmax[] = "pxmax"; static const char __pyx_k_pxmin[] = "pxmin"; static const char __pyx_k_pymax[] = "pymax"; static const char __pyx_k_pymin[] = "pymin"; static const char __pyx_k_range[] = "range"; static const char __pyx_k_theta[] = "theta"; static const char __pyx_k_zeros[] = "zeros"; static const char __pyx_k_import[] = "__import__"; static const char __pyx_k_float64[] = "float64"; static const char __pyx_k_subpixels[] = "subpixels"; static const char __pyx_k_use_exact[] = "use_exact"; static const char __pyx_k_ValueError[] = "ValueError"; static const char __pyx_k_ImportError[] = "ImportError"; static const char __pyx_k_RuntimeError[] = "RuntimeError"; static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; static const char __pyx_k_elliptical_overlap_grid[] = "elliptical_overlap_grid"; static const char __pyx_k_ndarray_is_not_C_contiguous[] = "ndarray is not C contiguous"; static const char __pyx_k_The_functions_defined_here_allo[] = "\nThe functions defined here allow one to determine the exact area of\noverlap of an ellipse and a triangle (written by Thomas Robitaille).\nThe approach is to divide the rectangle into two triangles, and\nreproject these so that the ellipse is a unit circle, then compute the\nintersection of a triangle with a unit circle.\n"; static const char __pyx_k_numpy_core_multiarray_failed_to[] = "numpy.core.multiarray failed to import"; static const char __pyx_k_unknown_dtype_code_in_numpy_pxd[] = "unknown dtype code in numpy.pxd (%d)"; static const char __pyx_k_Format_string_allocated_too_shor[] = "Format string allocated too short, see comment in numpy.pxd"; static const char __pyx_k_Non_native_byte_order_not_suppor[] = "Non-native byte order not supported"; static const char __pyx_k_ndarray_is_not_Fortran_contiguou[] = "ndarray is not Fortran contiguous"; static const char __pyx_k_numpy_core_umath_failed_to_impor[] = "numpy.core.umath failed to import"; static const char __pyx_k_photutils_geometry_elliptical_ov[] = "photutils/geometry/elliptical_overlap.pyx"; static const char __pyx_k_Format_string_allocated_too_shor_2[] = "Format string allocated too short."; static const char __pyx_k_photutils_geometry_elliptical_ov_2[] = "photutils.geometry.elliptical_overlap"; static PyObject *__pyx_n_s_DTYPE; static PyObject *__pyx_kp_u_Format_string_allocated_too_shor; static PyObject *__pyx_kp_u_Format_string_allocated_too_shor_2; static PyObject *__pyx_n_s_ImportError; static PyObject *__pyx_kp_u_Non_native_byte_order_not_suppor; static PyObject *__pyx_n_s_RuntimeError; static PyObject *__pyx_n_s_ValueError; static PyObject *__pyx_n_s_all; static PyObject *__pyx_n_s_bxmax; static PyObject *__pyx_n_s_bxmin; static PyObject *__pyx_n_s_bymax; static PyObject *__pyx_n_s_bymin; static PyObject *__pyx_n_s_cline_in_traceback; static PyObject *__pyx_n_s_dtype; static PyObject *__pyx_n_s_dx; static PyObject *__pyx_n_s_dy; static PyObject *__pyx_n_s_elliptical_overlap_grid; static PyObject *__pyx_n_u_elliptical_overlap_grid; static PyObject *__pyx_n_s_float64; static PyObject *__pyx_n_s_frac; static PyObject *__pyx_n_s_i; static PyObject *__pyx_n_s_import; static PyObject *__pyx_n_s_j; static PyObject *__pyx_n_s_main; static PyObject *__pyx_n_s_name; static PyObject *__pyx_kp_u_ndarray_is_not_C_contiguous; static PyObject *__pyx_kp_u_ndarray_is_not_Fortran_contiguou; static PyObject *__pyx_n_s_norm; static PyObject *__pyx_n_s_np; static PyObject *__pyx_n_s_numpy; static PyObject *__pyx_kp_u_numpy_core_multiarray_failed_to; static PyObject *__pyx_kp_u_numpy_core_umath_failed_to_impor; static PyObject *__pyx_n_s_nx; static PyObject *__pyx_n_s_ny; static PyObject *__pyx_kp_s_photutils_geometry_elliptical_ov; static PyObject *__pyx_n_s_photutils_geometry_elliptical_ov_2; static PyObject *__pyx_n_s_pxmax; static PyObject *__pyx_n_s_pxmin; static PyObject *__pyx_n_s_pymax; static PyObject *__pyx_n_s_pymin; static PyObject *__pyx_n_s_r; static PyObject *__pyx_n_s_range; static PyObject *__pyx_n_s_rx; static PyObject *__pyx_n_s_ry; static PyObject *__pyx_n_s_subpixels; static PyObject *__pyx_n_s_test; static PyObject *__pyx_n_s_theta; static PyObject *__pyx_kp_u_unknown_dtype_code_in_numpy_pxd; static PyObject *__pyx_n_s_use_exact; static PyObject *__pyx_n_s_x; static PyObject *__pyx_n_s_xmax; static PyObject *__pyx_n_s_xmin; static PyObject *__pyx_n_s_y; static PyObject *__pyx_n_s_ymax; static PyObject *__pyx_n_s_ymin; static PyObject *__pyx_n_s_zeros; static PyObject *__pyx_pf_9photutils_8geometry_18elliptical_overlap_elliptical_overlap_grid(CYTHON_UNUSED PyObject *__pyx_self, double __pyx_v_xmin, double __pyx_v_xmax, double __pyx_v_ymin, double __pyx_v_ymax, int __pyx_v_nx, int __pyx_v_ny, double __pyx_v_rx, double __pyx_v_ry, double __pyx_v_theta, int __pyx_v_use_exact, int __pyx_v_subpixels); /* proto */ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info); /* proto */ static PyObject *__pyx_tuple_; static PyObject *__pyx_tuple__2; static PyObject *__pyx_tuple__3; static PyObject *__pyx_tuple__4; static PyObject *__pyx_tuple__5; static PyObject *__pyx_tuple__6; static PyObject *__pyx_tuple__7; static PyObject *__pyx_tuple__8; static PyObject *__pyx_codeobj__9; /* Late includes */ /* "photutils/geometry/elliptical_overlap.pyx":37 * * * def elliptical_overlap_grid(double xmin, double xmax, double ymin, double ymax, # <<<<<<<<<<<<<< * int nx, int ny, double rx, double ry, double theta, * int use_exact, int subpixels): */ /* Python wrapper */ static PyObject *__pyx_pw_9photutils_8geometry_18elliptical_overlap_1elliptical_overlap_grid(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static char __pyx_doc_9photutils_8geometry_18elliptical_overlap_elliptical_overlap_grid[] = "\n elliptical_overlap_grid(xmin, xmax, ymin, ymax, nx, ny, rx, ry,\n use_exact, subpixels)\n\n Area of overlap between an ellipse and a pixel grid. The ellipse is\n centered on the origin.\n\n Parameters\n ----------\n xmin, xmax, ymin, ymax : float\n Extent of the grid in the x and y direction.\n nx, ny : int\n Grid dimensions.\n rx : float\n The semimajor axis of the ellipse.\n ry : float\n The semiminor axis of the ellipse.\n theta : float\n The position angle of the semimajor axis in radians (counterclockwise).\n use_exact : 0 or 1\n If set to 1, calculates the exact overlap, while if set to 0, uses a\n subpixel sampling method with ``subpixel`` subpixels in each direction.\n subpixels : int\n If ``use_exact`` is 0, each pixel is resampled by this factor in each\n dimension. Thus, each pixel is divided into ``subpixels ** 2``\n subpixels.\n\n Returns\n -------\n frac : `~numpy.ndarray`\n 2-d array giving the fraction of the overlap.\n "; static PyMethodDef __pyx_mdef_9photutils_8geometry_18elliptical_overlap_1elliptical_overlap_grid = {"elliptical_overlap_grid", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9photutils_8geometry_18elliptical_overlap_1elliptical_overlap_grid, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9photutils_8geometry_18elliptical_overlap_elliptical_overlap_grid}; static PyObject *__pyx_pw_9photutils_8geometry_18elliptical_overlap_1elliptical_overlap_grid(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { double __pyx_v_xmin; double __pyx_v_xmax; double __pyx_v_ymin; double __pyx_v_ymax; int __pyx_v_nx; int __pyx_v_ny; double __pyx_v_rx; double __pyx_v_ry; double __pyx_v_theta; int __pyx_v_use_exact; int __pyx_v_subpixels; PyObject *__pyx_r = 0; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("elliptical_overlap_grid (wrapper)", 0); { static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_xmin,&__pyx_n_s_xmax,&__pyx_n_s_ymin,&__pyx_n_s_ymax,&__pyx_n_s_nx,&__pyx_n_s_ny,&__pyx_n_s_rx,&__pyx_n_s_ry,&__pyx_n_s_theta,&__pyx_n_s_use_exact,&__pyx_n_s_subpixels,0}; PyObject* values[11] = {0,0,0,0,0,0,0,0,0,0,0}; if (unlikely(__pyx_kwds)) { Py_ssize_t kw_args; const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); switch (pos_args) { case 11: values[10] = PyTuple_GET_ITEM(__pyx_args, 10); CYTHON_FALLTHROUGH; case 10: values[9] = PyTuple_GET_ITEM(__pyx_args, 9); CYTHON_FALLTHROUGH; case 9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8); CYTHON_FALLTHROUGH; case 8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7); CYTHON_FALLTHROUGH; case 7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6); CYTHON_FALLTHROUGH; case 6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5); CYTHON_FALLTHROUGH; case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); CYTHON_FALLTHROUGH; case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); CYTHON_FALLTHROUGH; case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); CYTHON_FALLTHROUGH; case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); CYTHON_FALLTHROUGH; case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); CYTHON_FALLTHROUGH; case 0: break; default: goto __pyx_L5_argtuple_error; } kw_args = PyDict_Size(__pyx_kwds); switch (pos_args) { case 0: if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_xmin)) != 0)) kw_args--; else goto __pyx_L5_argtuple_error; CYTHON_FALLTHROUGH; case 1: if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_xmax)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("elliptical_overlap_grid", 1, 11, 11, 1); __PYX_ERR(0, 37, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 2: if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ymin)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("elliptical_overlap_grid", 1, 11, 11, 2); __PYX_ERR(0, 37, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 3: if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ymax)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("elliptical_overlap_grid", 1, 11, 11, 3); __PYX_ERR(0, 37, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 4: if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_nx)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("elliptical_overlap_grid", 1, 11, 11, 4); __PYX_ERR(0, 37, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 5: if (likely((values[5] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ny)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("elliptical_overlap_grid", 1, 11, 11, 5); __PYX_ERR(0, 37, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 6: if (likely((values[6] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_rx)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("elliptical_overlap_grid", 1, 11, 11, 6); __PYX_ERR(0, 37, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 7: if (likely((values[7] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ry)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("elliptical_overlap_grid", 1, 11, 11, 7); __PYX_ERR(0, 37, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 8: if (likely((values[8] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_theta)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("elliptical_overlap_grid", 1, 11, 11, 8); __PYX_ERR(0, 37, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 9: if (likely((values[9] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_use_exact)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("elliptical_overlap_grid", 1, 11, 11, 9); __PYX_ERR(0, 37, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 10: if (likely((values[10] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_subpixels)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("elliptical_overlap_grid", 1, 11, 11, 10); __PYX_ERR(0, 37, __pyx_L3_error) } } if (unlikely(kw_args > 0)) { if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "elliptical_overlap_grid") < 0)) __PYX_ERR(0, 37, __pyx_L3_error) } } else if (PyTuple_GET_SIZE(__pyx_args) != 11) { goto __pyx_L5_argtuple_error; } else { values[0] = PyTuple_GET_ITEM(__pyx_args, 0); values[1] = PyTuple_GET_ITEM(__pyx_args, 1); values[2] = PyTuple_GET_ITEM(__pyx_args, 2); values[3] = PyTuple_GET_ITEM(__pyx_args, 3); values[4] = PyTuple_GET_ITEM(__pyx_args, 4); values[5] = PyTuple_GET_ITEM(__pyx_args, 5); values[6] = PyTuple_GET_ITEM(__pyx_args, 6); values[7] = PyTuple_GET_ITEM(__pyx_args, 7); values[8] = PyTuple_GET_ITEM(__pyx_args, 8); values[9] = PyTuple_GET_ITEM(__pyx_args, 9); values[10] = PyTuple_GET_ITEM(__pyx_args, 10); } __pyx_v_xmin = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_xmin == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 37, __pyx_L3_error) __pyx_v_xmax = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_xmax == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 37, __pyx_L3_error) __pyx_v_ymin = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_ymin == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 37, __pyx_L3_error) __pyx_v_ymax = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_ymax == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 37, __pyx_L3_error) __pyx_v_nx = __Pyx_PyInt_As_int(values[4]); if (unlikely((__pyx_v_nx == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 38, __pyx_L3_error) __pyx_v_ny = __Pyx_PyInt_As_int(values[5]); if (unlikely((__pyx_v_ny == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 38, __pyx_L3_error) __pyx_v_rx = __pyx_PyFloat_AsDouble(values[6]); if (unlikely((__pyx_v_rx == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 38, __pyx_L3_error) __pyx_v_ry = __pyx_PyFloat_AsDouble(values[7]); if (unlikely((__pyx_v_ry == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 38, __pyx_L3_error) __pyx_v_theta = __pyx_PyFloat_AsDouble(values[8]); if (unlikely((__pyx_v_theta == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 38, __pyx_L3_error) __pyx_v_use_exact = __Pyx_PyInt_As_int(values[9]); if (unlikely((__pyx_v_use_exact == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 39, __pyx_L3_error) __pyx_v_subpixels = __Pyx_PyInt_As_int(values[10]); if (unlikely((__pyx_v_subpixels == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 39, __pyx_L3_error) } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; __Pyx_RaiseArgtupleInvalid("elliptical_overlap_grid", 1, 11, 11, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 37, __pyx_L3_error) __pyx_L3_error:; __Pyx_AddTraceback("photutils.geometry.elliptical_overlap.elliptical_overlap_grid", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; __pyx_r = __pyx_pf_9photutils_8geometry_18elliptical_overlap_elliptical_overlap_grid(__pyx_self, __pyx_v_xmin, __pyx_v_xmax, __pyx_v_ymin, __pyx_v_ymax, __pyx_v_nx, __pyx_v_ny, __pyx_v_rx, __pyx_v_ry, __pyx_v_theta, __pyx_v_use_exact, __pyx_v_subpixels); /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } static PyObject *__pyx_pf_9photutils_8geometry_18elliptical_overlap_elliptical_overlap_grid(CYTHON_UNUSED PyObject *__pyx_self, double __pyx_v_xmin, double __pyx_v_xmax, double __pyx_v_ymin, double __pyx_v_ymax, int __pyx_v_nx, int __pyx_v_ny, double __pyx_v_rx, double __pyx_v_ry, double __pyx_v_theta, int __pyx_v_use_exact, int __pyx_v_subpixels) { unsigned int __pyx_v_i; unsigned int __pyx_v_j; double __pyx_v_dx; double __pyx_v_dy; double __pyx_v_bxmin; double __pyx_v_bxmax; double __pyx_v_bymin; double __pyx_v_bymax; double __pyx_v_pxmin; double __pyx_v_pxmax; double __pyx_v_pymin; double __pyx_v_pymax; double __pyx_v_norm; PyArrayObject *__pyx_v_frac = 0; double __pyx_v_r; __Pyx_LocalBuf_ND __pyx_pybuffernd_frac; __Pyx_Buffer __pyx_pybuffer_frac; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; PyArrayObject *__pyx_t_5 = NULL; double __pyx_t_6; double __pyx_t_7; double __pyx_t_8; int __pyx_t_9; int __pyx_t_10; unsigned int __pyx_t_11; int __pyx_t_12; int __pyx_t_13; int __pyx_t_14; int __pyx_t_15; unsigned int __pyx_t_16; size_t __pyx_t_17; size_t __pyx_t_18; int __pyx_t_19; size_t __pyx_t_20; size_t __pyx_t_21; __Pyx_RefNannySetupContext("elliptical_overlap_grid", 0); __pyx_pybuffer_frac.pybuffer.buf = NULL; __pyx_pybuffer_frac.refcount = 0; __pyx_pybuffernd_frac.data = NULL; __pyx_pybuffernd_frac.rcbuffer = &__pyx_pybuffer_frac; /* "photutils/geometry/elliptical_overlap.pyx":80 * * # Define output array * cdef np.ndarray[DTYPE_t, ndim=2] frac = np.zeros([ny, nx], dtype=DTYPE) # <<<<<<<<<<<<<< * * # Find the width of each element in x and y */ __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 80, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 80, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_ny); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 80, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_nx); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 80, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyList_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 80, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_GIVEREF(__pyx_t_1); PyList_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); __Pyx_GIVEREF(__pyx_t_3); PyList_SET_ITEM(__pyx_t_4, 1, __pyx_t_3); __pyx_t_1 = 0; __pyx_t_3 = 0; __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 80, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); __pyx_t_4 = 0; __pyx_t_4 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 80, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_DTYPE); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 80, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_dtype, __pyx_t_1) < 0) __PYX_ERR(0, 80, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 80, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 80, __pyx_L1_error) __pyx_t_5 = ((PyArrayObject *)__pyx_t_1); { __Pyx_BufFmt_StackElem __pyx_stack[1]; if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_frac.rcbuffer->pybuffer, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_9photutils_8geometry_18elliptical_overlap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { __pyx_v_frac = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_frac.rcbuffer->pybuffer.buf = NULL; __PYX_ERR(0, 80, __pyx_L1_error) } else {__pyx_pybuffernd_frac.diminfo[0].strides = __pyx_pybuffernd_frac.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_frac.diminfo[0].shape = __pyx_pybuffernd_frac.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_frac.diminfo[1].strides = __pyx_pybuffernd_frac.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_frac.diminfo[1].shape = __pyx_pybuffernd_frac.rcbuffer->pybuffer.shape[1]; } } __pyx_t_5 = 0; __pyx_v_frac = ((PyArrayObject *)__pyx_t_1); __pyx_t_1 = 0; /* "photutils/geometry/elliptical_overlap.pyx":83 * * # Find the width of each element in x and y * dx = (xmax - xmin) / nx # <<<<<<<<<<<<<< * dy = (ymax - ymin) / ny * */ __pyx_t_6 = (__pyx_v_xmax - __pyx_v_xmin); if (unlikely(__pyx_v_nx == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 83, __pyx_L1_error) } __pyx_v_dx = (__pyx_t_6 / ((double)__pyx_v_nx)); /* "photutils/geometry/elliptical_overlap.pyx":84 * # Find the width of each element in x and y * dx = (xmax - xmin) / nx * dy = (ymax - ymin) / ny # <<<<<<<<<<<<<< * * norm = 1. / (dx * dy) */ __pyx_t_6 = (__pyx_v_ymax - __pyx_v_ymin); if (unlikely(__pyx_v_ny == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 84, __pyx_L1_error) } __pyx_v_dy = (__pyx_t_6 / ((double)__pyx_v_ny)); /* "photutils/geometry/elliptical_overlap.pyx":86 * dy = (ymax - ymin) / ny * * norm = 1. / (dx * dy) # <<<<<<<<<<<<<< * * # For now we use a bounding circle and then use that to find a bounding box */ __pyx_t_6 = (__pyx_v_dx * __pyx_v_dy); if (unlikely(__pyx_t_6 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 86, __pyx_L1_error) } __pyx_v_norm = (1. / __pyx_t_6); /* "photutils/geometry/elliptical_overlap.pyx":92 * * # Find bounding circle radius * r = max(rx, ry) # <<<<<<<<<<<<<< * * # Define bounding box */ __pyx_t_6 = __pyx_v_ry; __pyx_t_7 = __pyx_v_rx; if (((__pyx_t_6 > __pyx_t_7) != 0)) { __pyx_t_8 = __pyx_t_6; } else { __pyx_t_8 = __pyx_t_7; } __pyx_v_r = __pyx_t_8; /* "photutils/geometry/elliptical_overlap.pyx":95 * * # Define bounding box * bxmin = -r - 0.5 * dx # <<<<<<<<<<<<<< * bxmax = +r + 0.5 * dx * bymin = -r - 0.5 * dy */ __pyx_v_bxmin = ((-__pyx_v_r) - (0.5 * __pyx_v_dx)); /* "photutils/geometry/elliptical_overlap.pyx":96 * # Define bounding box * bxmin = -r - 0.5 * dx * bxmax = +r + 0.5 * dx # <<<<<<<<<<<<<< * bymin = -r - 0.5 * dy * bymax = +r + 0.5 * dy */ __pyx_v_bxmax = (__pyx_v_r + (0.5 * __pyx_v_dx)); /* "photutils/geometry/elliptical_overlap.pyx":97 * bxmin = -r - 0.5 * dx * bxmax = +r + 0.5 * dx * bymin = -r - 0.5 * dy # <<<<<<<<<<<<<< * bymax = +r + 0.5 * dy * */ __pyx_v_bymin = ((-__pyx_v_r) - (0.5 * __pyx_v_dy)); /* "photutils/geometry/elliptical_overlap.pyx":98 * bxmax = +r + 0.5 * dx * bymin = -r - 0.5 * dy * bymax = +r + 0.5 * dy # <<<<<<<<<<<<<< * * for i in range(nx): */ __pyx_v_bymax = (__pyx_v_r + (0.5 * __pyx_v_dy)); /* "photutils/geometry/elliptical_overlap.pyx":100 * bymax = +r + 0.5 * dy * * for i in range(nx): # <<<<<<<<<<<<<< * pxmin = xmin + i * dx # lower end of pixel * pxmax = pxmin + dx # upper end of pixel */ __pyx_t_9 = __pyx_v_nx; __pyx_t_10 = __pyx_t_9; for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) { __pyx_v_i = __pyx_t_11; /* "photutils/geometry/elliptical_overlap.pyx":101 * * for i in range(nx): * pxmin = xmin + i * dx # lower end of pixel # <<<<<<<<<<<<<< * pxmax = pxmin + dx # upper end of pixel * if pxmax > bxmin and pxmin < bxmax: */ __pyx_v_pxmin = (__pyx_v_xmin + (__pyx_v_i * __pyx_v_dx)); /* "photutils/geometry/elliptical_overlap.pyx":102 * for i in range(nx): * pxmin = xmin + i * dx # lower end of pixel * pxmax = pxmin + dx # upper end of pixel # <<<<<<<<<<<<<< * if pxmax > bxmin and pxmin < bxmax: * for j in range(ny): */ __pyx_v_pxmax = (__pyx_v_pxmin + __pyx_v_dx); /* "photutils/geometry/elliptical_overlap.pyx":103 * pxmin = xmin + i * dx # lower end of pixel * pxmax = pxmin + dx # upper end of pixel * if pxmax > bxmin and pxmin < bxmax: # <<<<<<<<<<<<<< * for j in range(ny): * pymin = ymin + j * dy */ __pyx_t_13 = ((__pyx_v_pxmax > __pyx_v_bxmin) != 0); if (__pyx_t_13) { } else { __pyx_t_12 = __pyx_t_13; goto __pyx_L6_bool_binop_done; } __pyx_t_13 = ((__pyx_v_pxmin < __pyx_v_bxmax) != 0); __pyx_t_12 = __pyx_t_13; __pyx_L6_bool_binop_done:; if (__pyx_t_12) { /* "photutils/geometry/elliptical_overlap.pyx":104 * pxmax = pxmin + dx # upper end of pixel * if pxmax > bxmin and pxmin < bxmax: * for j in range(ny): # <<<<<<<<<<<<<< * pymin = ymin + j * dy * pymax = pymin + dy */ __pyx_t_14 = __pyx_v_ny; __pyx_t_15 = __pyx_t_14; for (__pyx_t_16 = 0; __pyx_t_16 < __pyx_t_15; __pyx_t_16+=1) { __pyx_v_j = __pyx_t_16; /* "photutils/geometry/elliptical_overlap.pyx":105 * if pxmax > bxmin and pxmin < bxmax: * for j in range(ny): * pymin = ymin + j * dy # <<<<<<<<<<<<<< * pymax = pymin + dy * if pymax > bymin and pymin < bymax: */ __pyx_v_pymin = (__pyx_v_ymin + (__pyx_v_j * __pyx_v_dy)); /* "photutils/geometry/elliptical_overlap.pyx":106 * for j in range(ny): * pymin = ymin + j * dy * pymax = pymin + dy # <<<<<<<<<<<<<< * if pymax > bymin and pymin < bymax: * if use_exact: */ __pyx_v_pymax = (__pyx_v_pymin + __pyx_v_dy); /* "photutils/geometry/elliptical_overlap.pyx":107 * pymin = ymin + j * dy * pymax = pymin + dy * if pymax > bymin and pymin < bymax: # <<<<<<<<<<<<<< * if use_exact: * frac[j, i] = elliptical_overlap_single_exact( */ __pyx_t_13 = ((__pyx_v_pymax > __pyx_v_bymin) != 0); if (__pyx_t_13) { } else { __pyx_t_12 = __pyx_t_13; goto __pyx_L11_bool_binop_done; } __pyx_t_13 = ((__pyx_v_pymin < __pyx_v_bymax) != 0); __pyx_t_12 = __pyx_t_13; __pyx_L11_bool_binop_done:; if (__pyx_t_12) { /* "photutils/geometry/elliptical_overlap.pyx":108 * pymax = pymin + dy * if pymax > bymin and pymin < bymax: * if use_exact: # <<<<<<<<<<<<<< * frac[j, i] = elliptical_overlap_single_exact( * pxmin, pymin, pxmax, pymax, rx, ry, theta) * norm */ __pyx_t_12 = (__pyx_v_use_exact != 0); if (__pyx_t_12) { /* "photutils/geometry/elliptical_overlap.pyx":109 * if pymax > bymin and pymin < bymax: * if use_exact: * frac[j, i] = elliptical_overlap_single_exact( # <<<<<<<<<<<<<< * pxmin, pymin, pxmax, pymax, rx, ry, theta) * norm * else: */ __pyx_t_17 = __pyx_v_j; __pyx_t_18 = __pyx_v_i; __pyx_t_19 = -1; if (unlikely(__pyx_t_17 >= (size_t)__pyx_pybuffernd_frac.diminfo[0].shape)) __pyx_t_19 = 0; if (unlikely(__pyx_t_18 >= (size_t)__pyx_pybuffernd_frac.diminfo[1].shape)) __pyx_t_19 = 1; if (unlikely(__pyx_t_19 != -1)) { __Pyx_RaiseBufferIndexError(__pyx_t_19); __PYX_ERR(0, 109, __pyx_L1_error) } *__Pyx_BufPtrStrided2d(__pyx_t_9photutils_8geometry_18elliptical_overlap_DTYPE_t *, __pyx_pybuffernd_frac.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_frac.diminfo[0].strides, __pyx_t_18, __pyx_pybuffernd_frac.diminfo[1].strides) = (__pyx_f_9photutils_8geometry_18elliptical_overlap_elliptical_overlap_single_exact(__pyx_v_pxmin, __pyx_v_pymin, __pyx_v_pxmax, __pyx_v_pymax, __pyx_v_rx, __pyx_v_ry, __pyx_v_theta) * __pyx_v_norm); /* "photutils/geometry/elliptical_overlap.pyx":108 * pymax = pymin + dy * if pymax > bymin and pymin < bymax: * if use_exact: # <<<<<<<<<<<<<< * frac[j, i] = elliptical_overlap_single_exact( * pxmin, pymin, pxmax, pymax, rx, ry, theta) * norm */ goto __pyx_L13; } /* "photutils/geometry/elliptical_overlap.pyx":112 * pxmin, pymin, pxmax, pymax, rx, ry, theta) * norm * else: * frac[j, i] = elliptical_overlap_single_subpixel( # <<<<<<<<<<<<<< * pxmin, pymin, pxmax, pymax, rx, ry, theta, * subpixels) */ /*else*/ { /* "photutils/geometry/elliptical_overlap.pyx":114 * frac[j, i] = elliptical_overlap_single_subpixel( * pxmin, pymin, pxmax, pymax, rx, ry, theta, * subpixels) # <<<<<<<<<<<<<< * return frac * */ __pyx_t_20 = __pyx_v_j; __pyx_t_21 = __pyx_v_i; __pyx_t_19 = -1; if (unlikely(__pyx_t_20 >= (size_t)__pyx_pybuffernd_frac.diminfo[0].shape)) __pyx_t_19 = 0; if (unlikely(__pyx_t_21 >= (size_t)__pyx_pybuffernd_frac.diminfo[1].shape)) __pyx_t_19 = 1; if (unlikely(__pyx_t_19 != -1)) { __Pyx_RaiseBufferIndexError(__pyx_t_19); __PYX_ERR(0, 112, __pyx_L1_error) } *__Pyx_BufPtrStrided2d(__pyx_t_9photutils_8geometry_18elliptical_overlap_DTYPE_t *, __pyx_pybuffernd_frac.rcbuffer->pybuffer.buf, __pyx_t_20, __pyx_pybuffernd_frac.diminfo[0].strides, __pyx_t_21, __pyx_pybuffernd_frac.diminfo[1].strides) = __pyx_f_9photutils_8geometry_18elliptical_overlap_elliptical_overlap_single_subpixel(__pyx_v_pxmin, __pyx_v_pymin, __pyx_v_pxmax, __pyx_v_pymax, __pyx_v_rx, __pyx_v_ry, __pyx_v_theta, __pyx_v_subpixels); } __pyx_L13:; /* "photutils/geometry/elliptical_overlap.pyx":107 * pymin = ymin + j * dy * pymax = pymin + dy * if pymax > bymin and pymin < bymax: # <<<<<<<<<<<<<< * if use_exact: * frac[j, i] = elliptical_overlap_single_exact( */ } } /* "photutils/geometry/elliptical_overlap.pyx":103 * pxmin = xmin + i * dx # lower end of pixel * pxmax = pxmin + dx # upper end of pixel * if pxmax > bxmin and pxmin < bxmax: # <<<<<<<<<<<<<< * for j in range(ny): * pymin = ymin + j * dy */ } } /* "photutils/geometry/elliptical_overlap.pyx":115 * pxmin, pymin, pxmax, pymax, rx, ry, theta, * subpixels) * return frac # <<<<<<<<<<<<<< * * */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(((PyObject *)__pyx_v_frac)); __pyx_r = ((PyObject *)__pyx_v_frac); goto __pyx_L0; /* "photutils/geometry/elliptical_overlap.pyx":37 * * * def elliptical_overlap_grid(double xmin, double xmax, double ymin, double ymax, # <<<<<<<<<<<<<< * int nx, int ny, double rx, double ry, double theta, * int use_exact, int subpixels): */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_frac.rcbuffer->pybuffer); __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} __Pyx_AddTraceback("photutils.geometry.elliptical_overlap.elliptical_overlap_grid", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; goto __pyx_L2; __pyx_L0:; __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_frac.rcbuffer->pybuffer); __pyx_L2:; __Pyx_XDECREF((PyObject *)__pyx_v_frac); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/elliptical_overlap.pyx":124 * * * cdef double elliptical_overlap_single_subpixel(double x0, double y0, # <<<<<<<<<<<<<< * double x1, double y1, * double rx, double ry, */ static double __pyx_f_9photutils_8geometry_18elliptical_overlap_elliptical_overlap_single_subpixel(double __pyx_v_x0, double __pyx_v_y0, double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_rx, double __pyx_v_ry, double __pyx_v_theta, int __pyx_v_subpixels) { CYTHON_UNUSED unsigned int __pyx_v_i; CYTHON_UNUSED unsigned int __pyx_v_j; double __pyx_v_x; double __pyx_v_y; double __pyx_v_frac; double __pyx_v_inv_rx_sq; double __pyx_v_inv_ry_sq; double __pyx_v_cos_theta; double __pyx_v_sin_theta; double __pyx_v_dx; double __pyx_v_dy; double __pyx_v_x_tr; double __pyx_v_y_tr; double __pyx_r; __Pyx_RefNannyDeclarations double __pyx_t_1; int __pyx_t_2; int __pyx_t_3; unsigned int __pyx_t_4; int __pyx_t_5; int __pyx_t_6; unsigned int __pyx_t_7; int __pyx_t_8; __Pyx_RefNannySetupContext("elliptical_overlap_single_subpixel", 0); /* "photutils/geometry/elliptical_overlap.pyx":135 * cdef unsigned int i, j * cdef double x, y * cdef double frac = 0. # Accumulator. # <<<<<<<<<<<<<< * cdef double inv_rx_sq, inv_ry_sq * cdef double cos_theta = cos(theta) */ __pyx_v_frac = 0.; /* "photutils/geometry/elliptical_overlap.pyx":137 * cdef double frac = 0. # Accumulator. * cdef double inv_rx_sq, inv_ry_sq * cdef double cos_theta = cos(theta) # <<<<<<<<<<<<<< * cdef double sin_theta = sin(theta) * cdef double dx, dy */ __pyx_v_cos_theta = cos(__pyx_v_theta); /* "photutils/geometry/elliptical_overlap.pyx":138 * cdef double inv_rx_sq, inv_ry_sq * cdef double cos_theta = cos(theta) * cdef double sin_theta = sin(theta) # <<<<<<<<<<<<<< * cdef double dx, dy * cdef double x_tr, y_tr */ __pyx_v_sin_theta = sin(__pyx_v_theta); /* "photutils/geometry/elliptical_overlap.pyx":142 * cdef double x_tr, y_tr * * dx = (x1 - x0) / subpixels # <<<<<<<<<<<<<< * dy = (y1 - y0) / subpixels * */ __pyx_t_1 = (__pyx_v_x1 - __pyx_v_x0); if (unlikely(__pyx_v_subpixels == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 142, __pyx_L1_error) } __pyx_v_dx = (__pyx_t_1 / ((double)__pyx_v_subpixels)); /* "photutils/geometry/elliptical_overlap.pyx":143 * * dx = (x1 - x0) / subpixels * dy = (y1 - y0) / subpixels # <<<<<<<<<<<<<< * * inv_rx_sq = 1. / (rx * rx) */ __pyx_t_1 = (__pyx_v_y1 - __pyx_v_y0); if (unlikely(__pyx_v_subpixels == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 143, __pyx_L1_error) } __pyx_v_dy = (__pyx_t_1 / ((double)__pyx_v_subpixels)); /* "photutils/geometry/elliptical_overlap.pyx":145 * dy = (y1 - y0) / subpixels * * inv_rx_sq = 1. / (rx * rx) # <<<<<<<<<<<<<< * inv_ry_sq = 1. / (ry * ry) * */ __pyx_t_1 = (__pyx_v_rx * __pyx_v_rx); if (unlikely(__pyx_t_1 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 145, __pyx_L1_error) } __pyx_v_inv_rx_sq = (1. / __pyx_t_1); /* "photutils/geometry/elliptical_overlap.pyx":146 * * inv_rx_sq = 1. / (rx * rx) * inv_ry_sq = 1. / (ry * ry) # <<<<<<<<<<<<<< * * x = x0 - 0.5 * dx */ __pyx_t_1 = (__pyx_v_ry * __pyx_v_ry); if (unlikely(__pyx_t_1 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 146, __pyx_L1_error) } __pyx_v_inv_ry_sq = (1. / __pyx_t_1); /* "photutils/geometry/elliptical_overlap.pyx":148 * inv_ry_sq = 1. / (ry * ry) * * x = x0 - 0.5 * dx # <<<<<<<<<<<<<< * for i in range(subpixels): * x += dx */ __pyx_v_x = (__pyx_v_x0 - (0.5 * __pyx_v_dx)); /* "photutils/geometry/elliptical_overlap.pyx":149 * * x = x0 - 0.5 * dx * for i in range(subpixels): # <<<<<<<<<<<<<< * x += dx * y = y0 - 0.5 * dy */ __pyx_t_2 = __pyx_v_subpixels; __pyx_t_3 = __pyx_t_2; for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { __pyx_v_i = __pyx_t_4; /* "photutils/geometry/elliptical_overlap.pyx":150 * x = x0 - 0.5 * dx * for i in range(subpixels): * x += dx # <<<<<<<<<<<<<< * y = y0 - 0.5 * dy * for j in range(subpixels): */ __pyx_v_x = (__pyx_v_x + __pyx_v_dx); /* "photutils/geometry/elliptical_overlap.pyx":151 * for i in range(subpixels): * x += dx * y = y0 - 0.5 * dy # <<<<<<<<<<<<<< * for j in range(subpixels): * y += dy */ __pyx_v_y = (__pyx_v_y0 - (0.5 * __pyx_v_dy)); /* "photutils/geometry/elliptical_overlap.pyx":152 * x += dx * y = y0 - 0.5 * dy * for j in range(subpixels): # <<<<<<<<<<<<<< * y += dy * */ __pyx_t_5 = __pyx_v_subpixels; __pyx_t_6 = __pyx_t_5; for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_6; __pyx_t_7+=1) { __pyx_v_j = __pyx_t_7; /* "photutils/geometry/elliptical_overlap.pyx":153 * y = y0 - 0.5 * dy * for j in range(subpixels): * y += dy # <<<<<<<<<<<<<< * * # Transform into frame of rotated ellipse */ __pyx_v_y = (__pyx_v_y + __pyx_v_dy); /* "photutils/geometry/elliptical_overlap.pyx":156 * * # Transform into frame of rotated ellipse * x_tr = y * sin_theta + x * cos_theta # <<<<<<<<<<<<<< * y_tr = y * cos_theta - x * sin_theta * */ __pyx_v_x_tr = ((__pyx_v_y * __pyx_v_sin_theta) + (__pyx_v_x * __pyx_v_cos_theta)); /* "photutils/geometry/elliptical_overlap.pyx":157 * # Transform into frame of rotated ellipse * x_tr = y * sin_theta + x * cos_theta * y_tr = y * cos_theta - x * sin_theta # <<<<<<<<<<<<<< * * if x_tr * x_tr * inv_rx_sq + y_tr * y_tr * inv_ry_sq < 1.: */ __pyx_v_y_tr = ((__pyx_v_y * __pyx_v_cos_theta) - (__pyx_v_x * __pyx_v_sin_theta)); /* "photutils/geometry/elliptical_overlap.pyx":159 * y_tr = y * cos_theta - x * sin_theta * * if x_tr * x_tr * inv_rx_sq + y_tr * y_tr * inv_ry_sq < 1.: # <<<<<<<<<<<<<< * frac += 1. * */ __pyx_t_8 = (((((__pyx_v_x_tr * __pyx_v_x_tr) * __pyx_v_inv_rx_sq) + ((__pyx_v_y_tr * __pyx_v_y_tr) * __pyx_v_inv_ry_sq)) < 1.) != 0); if (__pyx_t_8) { /* "photutils/geometry/elliptical_overlap.pyx":160 * * if x_tr * x_tr * inv_rx_sq + y_tr * y_tr * inv_ry_sq < 1.: * frac += 1. # <<<<<<<<<<<<<< * * return frac / (subpixels * subpixels) */ __pyx_v_frac = (__pyx_v_frac + 1.); /* "photutils/geometry/elliptical_overlap.pyx":159 * y_tr = y * cos_theta - x * sin_theta * * if x_tr * x_tr * inv_rx_sq + y_tr * y_tr * inv_ry_sq < 1.: # <<<<<<<<<<<<<< * frac += 1. * */ } } } /* "photutils/geometry/elliptical_overlap.pyx":162 * frac += 1. * * return frac / (subpixels * subpixels) # <<<<<<<<<<<<<< * * */ __pyx_t_2 = (__pyx_v_subpixels * __pyx_v_subpixels); if (unlikely(__pyx_t_2 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 162, __pyx_L1_error) } __pyx_r = (__pyx_v_frac / ((double)__pyx_t_2)); goto __pyx_L0; /* "photutils/geometry/elliptical_overlap.pyx":124 * * * cdef double elliptical_overlap_single_subpixel(double x0, double y0, # <<<<<<<<<<<<<< * double x1, double y1, * double rx, double ry, */ /* function exit code */ __pyx_L1_error:; __Pyx_WriteUnraisable("photutils.geometry.elliptical_overlap.elliptical_overlap_single_subpixel", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0); __pyx_r = 0; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/elliptical_overlap.pyx":165 * * * cdef double elliptical_overlap_single_exact(double xmin, double ymin, # <<<<<<<<<<<<<< * double xmax, double ymax, * double rx, double ry, */ static double __pyx_f_9photutils_8geometry_18elliptical_overlap_elliptical_overlap_single_exact(double __pyx_v_xmin, double __pyx_v_ymin, double __pyx_v_xmax, double __pyx_v_ymax, double __pyx_v_rx, double __pyx_v_ry, double __pyx_v_theta) { double __pyx_v_cos_m_theta; double __pyx_v_sin_m_theta; double __pyx_v_scale; double __pyx_v_x1; double __pyx_v_y1; double __pyx_v_x2; double __pyx_v_y2; double __pyx_v_x3; double __pyx_v_y3; double __pyx_v_x4; double __pyx_v_y4; double __pyx_r; __Pyx_RefNannyDeclarations double __pyx_t_1; double __pyx_t_2; double __pyx_t_3; __Pyx_RefNannySetupContext("elliptical_overlap_single_exact", 0); /* "photutils/geometry/elliptical_overlap.pyx":175 * """ * * cdef double cos_m_theta = cos(-theta) # <<<<<<<<<<<<<< * cdef double sin_m_theta = sin(-theta) * cdef double scale */ __pyx_v_cos_m_theta = cos((-__pyx_v_theta)); /* "photutils/geometry/elliptical_overlap.pyx":176 * * cdef double cos_m_theta = cos(-theta) * cdef double sin_m_theta = sin(-theta) # <<<<<<<<<<<<<< * cdef double scale * */ __pyx_v_sin_m_theta = sin((-__pyx_v_theta)); /* "photutils/geometry/elliptical_overlap.pyx":180 * * # Find scale by which the areas will be shrunk * scale = rx * ry # <<<<<<<<<<<<<< * * # Reproject rectangle to frame of reference in which ellipse is a */ __pyx_v_scale = (__pyx_v_rx * __pyx_v_ry); /* "photutils/geometry/elliptical_overlap.pyx":184 * # Reproject rectangle to frame of reference in which ellipse is a * # unit circle * x1, y1 = ((xmin * cos_m_theta - ymin * sin_m_theta) / rx, # <<<<<<<<<<<<<< * (xmin * sin_m_theta + ymin * cos_m_theta) / ry) * x2, y2 = ((xmax * cos_m_theta - ymin * sin_m_theta) / rx, */ __pyx_t_1 = ((__pyx_v_xmin * __pyx_v_cos_m_theta) - (__pyx_v_ymin * __pyx_v_sin_m_theta)); if (unlikely(__pyx_v_rx == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 184, __pyx_L1_error) } __pyx_t_2 = (__pyx_t_1 / __pyx_v_rx); /* "photutils/geometry/elliptical_overlap.pyx":185 * # unit circle * x1, y1 = ((xmin * cos_m_theta - ymin * sin_m_theta) / rx, * (xmin * sin_m_theta + ymin * cos_m_theta) / ry) # <<<<<<<<<<<<<< * x2, y2 = ((xmax * cos_m_theta - ymin * sin_m_theta) / rx, * (xmax * sin_m_theta + ymin * cos_m_theta) / ry) */ __pyx_t_1 = ((__pyx_v_xmin * __pyx_v_sin_m_theta) + (__pyx_v_ymin * __pyx_v_cos_m_theta)); if (unlikely(__pyx_v_ry == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 185, __pyx_L1_error) } __pyx_t_3 = (__pyx_t_1 / __pyx_v_ry); __pyx_v_x1 = __pyx_t_2; __pyx_v_y1 = __pyx_t_3; /* "photutils/geometry/elliptical_overlap.pyx":186 * x1, y1 = ((xmin * cos_m_theta - ymin * sin_m_theta) / rx, * (xmin * sin_m_theta + ymin * cos_m_theta) / ry) * x2, y2 = ((xmax * cos_m_theta - ymin * sin_m_theta) / rx, # <<<<<<<<<<<<<< * (xmax * sin_m_theta + ymin * cos_m_theta) / ry) * x3, y3 = ((xmax * cos_m_theta - ymax * sin_m_theta) / rx, */ __pyx_t_3 = ((__pyx_v_xmax * __pyx_v_cos_m_theta) - (__pyx_v_ymin * __pyx_v_sin_m_theta)); if (unlikely(__pyx_v_rx == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 186, __pyx_L1_error) } __pyx_t_2 = (__pyx_t_3 / __pyx_v_rx); /* "photutils/geometry/elliptical_overlap.pyx":187 * (xmin * sin_m_theta + ymin * cos_m_theta) / ry) * x2, y2 = ((xmax * cos_m_theta - ymin * sin_m_theta) / rx, * (xmax * sin_m_theta + ymin * cos_m_theta) / ry) # <<<<<<<<<<<<<< * x3, y3 = ((xmax * cos_m_theta - ymax * sin_m_theta) / rx, * (xmax * sin_m_theta + ymax * cos_m_theta) / ry) */ __pyx_t_3 = ((__pyx_v_xmax * __pyx_v_sin_m_theta) + (__pyx_v_ymin * __pyx_v_cos_m_theta)); if (unlikely(__pyx_v_ry == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 187, __pyx_L1_error) } __pyx_t_1 = (__pyx_t_3 / __pyx_v_ry); __pyx_v_x2 = __pyx_t_2; __pyx_v_y2 = __pyx_t_1; /* "photutils/geometry/elliptical_overlap.pyx":188 * x2, y2 = ((xmax * cos_m_theta - ymin * sin_m_theta) / rx, * (xmax * sin_m_theta + ymin * cos_m_theta) / ry) * x3, y3 = ((xmax * cos_m_theta - ymax * sin_m_theta) / rx, # <<<<<<<<<<<<<< * (xmax * sin_m_theta + ymax * cos_m_theta) / ry) * x4, y4 = ((xmin * cos_m_theta - ymax * sin_m_theta) / rx, */ __pyx_t_1 = ((__pyx_v_xmax * __pyx_v_cos_m_theta) - (__pyx_v_ymax * __pyx_v_sin_m_theta)); if (unlikely(__pyx_v_rx == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 188, __pyx_L1_error) } __pyx_t_2 = (__pyx_t_1 / __pyx_v_rx); /* "photutils/geometry/elliptical_overlap.pyx":189 * (xmax * sin_m_theta + ymin * cos_m_theta) / ry) * x3, y3 = ((xmax * cos_m_theta - ymax * sin_m_theta) / rx, * (xmax * sin_m_theta + ymax * cos_m_theta) / ry) # <<<<<<<<<<<<<< * x4, y4 = ((xmin * cos_m_theta - ymax * sin_m_theta) / rx, * (xmin * sin_m_theta + ymax * cos_m_theta) / ry) */ __pyx_t_1 = ((__pyx_v_xmax * __pyx_v_sin_m_theta) + (__pyx_v_ymax * __pyx_v_cos_m_theta)); if (unlikely(__pyx_v_ry == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 189, __pyx_L1_error) } __pyx_t_3 = (__pyx_t_1 / __pyx_v_ry); __pyx_v_x3 = __pyx_t_2; __pyx_v_y3 = __pyx_t_3; /* "photutils/geometry/elliptical_overlap.pyx":190 * x3, y3 = ((xmax * cos_m_theta - ymax * sin_m_theta) / rx, * (xmax * sin_m_theta + ymax * cos_m_theta) / ry) * x4, y4 = ((xmin * cos_m_theta - ymax * sin_m_theta) / rx, # <<<<<<<<<<<<<< * (xmin * sin_m_theta + ymax * cos_m_theta) / ry) * */ __pyx_t_3 = ((__pyx_v_xmin * __pyx_v_cos_m_theta) - (__pyx_v_ymax * __pyx_v_sin_m_theta)); if (unlikely(__pyx_v_rx == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 190, __pyx_L1_error) } __pyx_t_2 = (__pyx_t_3 / __pyx_v_rx); /* "photutils/geometry/elliptical_overlap.pyx":191 * (xmax * sin_m_theta + ymax * cos_m_theta) / ry) * x4, y4 = ((xmin * cos_m_theta - ymax * sin_m_theta) / rx, * (xmin * sin_m_theta + ymax * cos_m_theta) / ry) # <<<<<<<<<<<<<< * * # Divide resulting quadrilateral into two triangles and find */ __pyx_t_3 = ((__pyx_v_xmin * __pyx_v_sin_m_theta) + (__pyx_v_ymax * __pyx_v_cos_m_theta)); if (unlikely(__pyx_v_ry == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 191, __pyx_L1_error) } __pyx_t_1 = (__pyx_t_3 / __pyx_v_ry); __pyx_v_x4 = __pyx_t_2; __pyx_v_y4 = __pyx_t_1; /* "photutils/geometry/elliptical_overlap.pyx":196 * # intersection with unit circle * return (overlap_area_triangle_unit_circle(x1, y1, x2, y2, x3, y3) + * overlap_area_triangle_unit_circle(x1, y1, x4, y4, x3, y3)) * scale # <<<<<<<<<<<<<< */ __pyx_r = ((__pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2, __pyx_v_x3, __pyx_v_y3) + __pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle(__pyx_v_x1, __pyx_v_y1, __pyx_v_x4, __pyx_v_y4, __pyx_v_x3, __pyx_v_y3)) * __pyx_v_scale); goto __pyx_L0; /* "photutils/geometry/elliptical_overlap.pyx":165 * * * cdef double elliptical_overlap_single_exact(double xmin, double ymin, # <<<<<<<<<<<<<< * double xmax, double ymax, * double rx, double ry, */ /* function exit code */ __pyx_L1_error:; __Pyx_WriteUnraisable("photutils.geometry.elliptical_overlap.elliptical_overlap_single_exact", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0); __pyx_r = 0; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":258 * # experimental exception made for __getbuffer__ and __releasebuffer__ * # -- the details of this may change. * def __getbuffer__(ndarray self, Py_buffer* info, int flags): # <<<<<<<<<<<<<< * # This implementation of getbuffer is geared towards Cython * # requirements, and does not yet fulfill the PEP. */ /* Python wrapper */ static CYTHON_UNUSED int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ static CYTHON_UNUSED int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { int __pyx_r; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0); __pyx_r = __pyx_pf_5numpy_7ndarray___getbuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags)); /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { int __pyx_v_i; int __pyx_v_ndim; int __pyx_v_endian_detector; int __pyx_v_little_endian; int __pyx_v_t; char *__pyx_v_f; PyArray_Descr *__pyx_v_descr = 0; int __pyx_v_offset; int __pyx_r; __Pyx_RefNannyDeclarations int __pyx_t_1; int __pyx_t_2; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; int __pyx_t_5; int __pyx_t_6; PyArray_Descr *__pyx_t_7; PyObject *__pyx_t_8 = NULL; char *__pyx_t_9; if (__pyx_v_info == NULL) { PyErr_SetString(PyExc_BufferError, "PyObject_GetBuffer: view==NULL argument is obsolete"); return -1; } __Pyx_RefNannySetupContext("__getbuffer__", 0); __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None); __Pyx_GIVEREF(__pyx_v_info->obj); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":265 * * cdef int i, ndim * cdef int endian_detector = 1 # <<<<<<<<<<<<<< * cdef bint little_endian = ((&endian_detector)[0] != 0) * */ __pyx_v_endian_detector = 1; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":266 * cdef int i, ndim * cdef int endian_detector = 1 * cdef bint little_endian = ((&endian_detector)[0] != 0) # <<<<<<<<<<<<<< * * ndim = PyArray_NDIM(self) */ __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":268 * cdef bint little_endian = ((&endian_detector)[0] != 0) * * ndim = PyArray_NDIM(self) # <<<<<<<<<<<<<< * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) */ __pyx_v_ndim = PyArray_NDIM(__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":270 * ndim = PyArray_NDIM(self) * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") */ __pyx_t_2 = (((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L4_bool_binop_done; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":271 * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): # <<<<<<<<<<<<<< * raise ValueError(u"ndarray is not C contiguous") * */ __pyx_t_2 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_ARRAY_C_CONTIGUOUS) != 0)) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L4_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":270 * ndim = PyArray_NDIM(self) * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") */ if (unlikely(__pyx_t_1)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":272 * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") # <<<<<<<<<<<<<< * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 272, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 272, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":270 * ndim = PyArray_NDIM(self) * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":274 * raise ValueError(u"ndarray is not C contiguous") * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") */ __pyx_t_2 = (((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L7_bool_binop_done; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":275 * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): # <<<<<<<<<<<<<< * raise ValueError(u"ndarray is not Fortran contiguous") * */ __pyx_t_2 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_ARRAY_F_CONTIGUOUS) != 0)) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L7_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":274 * raise ValueError(u"ndarray is not C contiguous") * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") */ if (unlikely(__pyx_t_1)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":276 * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") # <<<<<<<<<<<<<< * * info.buf = PyArray_DATA(self) */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 276, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 276, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":274 * raise ValueError(u"ndarray is not C contiguous") * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":278 * raise ValueError(u"ndarray is not Fortran contiguous") * * info.buf = PyArray_DATA(self) # <<<<<<<<<<<<<< * info.ndim = ndim * if sizeof(npy_intp) != sizeof(Py_ssize_t): */ __pyx_v_info->buf = PyArray_DATA(__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":279 * * info.buf = PyArray_DATA(self) * info.ndim = ndim # <<<<<<<<<<<<<< * if sizeof(npy_intp) != sizeof(Py_ssize_t): * # Allocate new buffer for strides and shape info. */ __pyx_v_info->ndim = __pyx_v_ndim; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":280 * info.buf = PyArray_DATA(self) * info.ndim = ndim * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * # Allocate new buffer for strides and shape info. * # This is allocated as one block, strides first. */ __pyx_t_1 = (((sizeof(npy_intp)) != (sizeof(Py_ssize_t))) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":283 * # Allocate new buffer for strides and shape info. * # This is allocated as one block, strides first. * info.strides = PyObject_Malloc(sizeof(Py_ssize_t) * 2 * ndim) # <<<<<<<<<<<<<< * info.shape = info.strides + ndim * for i in range(ndim): */ __pyx_v_info->strides = ((Py_ssize_t *)PyObject_Malloc((((sizeof(Py_ssize_t)) * 2) * ((size_t)__pyx_v_ndim)))); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":284 * # This is allocated as one block, strides first. * info.strides = PyObject_Malloc(sizeof(Py_ssize_t) * 2 * ndim) * info.shape = info.strides + ndim # <<<<<<<<<<<<<< * for i in range(ndim): * info.strides[i] = PyArray_STRIDES(self)[i] */ __pyx_v_info->shape = (__pyx_v_info->strides + __pyx_v_ndim); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":285 * info.strides = PyObject_Malloc(sizeof(Py_ssize_t) * 2 * ndim) * info.shape = info.strides + ndim * for i in range(ndim): # <<<<<<<<<<<<<< * info.strides[i] = PyArray_STRIDES(self)[i] * info.shape[i] = PyArray_DIMS(self)[i] */ __pyx_t_4 = __pyx_v_ndim; __pyx_t_5 = __pyx_t_4; for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { __pyx_v_i = __pyx_t_6; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":286 * info.shape = info.strides + ndim * for i in range(ndim): * info.strides[i] = PyArray_STRIDES(self)[i] # <<<<<<<<<<<<<< * info.shape[i] = PyArray_DIMS(self)[i] * else: */ (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(__pyx_v_self)[__pyx_v_i]); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":287 * for i in range(ndim): * info.strides[i] = PyArray_STRIDES(self)[i] * info.shape[i] = PyArray_DIMS(self)[i] # <<<<<<<<<<<<<< * else: * info.strides = PyArray_STRIDES(self) */ (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(__pyx_v_self)[__pyx_v_i]); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":280 * info.buf = PyArray_DATA(self) * info.ndim = ndim * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * # Allocate new buffer for strides and shape info. * # This is allocated as one block, strides first. */ goto __pyx_L9; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":289 * info.shape[i] = PyArray_DIMS(self)[i] * else: * info.strides = PyArray_STRIDES(self) # <<<<<<<<<<<<<< * info.shape = PyArray_DIMS(self) * info.suboffsets = NULL */ /*else*/ { __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(__pyx_v_self)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":290 * else: * info.strides = PyArray_STRIDES(self) * info.shape = PyArray_DIMS(self) # <<<<<<<<<<<<<< * info.suboffsets = NULL * info.itemsize = PyArray_ITEMSIZE(self) */ __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(__pyx_v_self)); } __pyx_L9:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":291 * info.strides = PyArray_STRIDES(self) * info.shape = PyArray_DIMS(self) * info.suboffsets = NULL # <<<<<<<<<<<<<< * info.itemsize = PyArray_ITEMSIZE(self) * info.readonly = not PyArray_ISWRITEABLE(self) */ __pyx_v_info->suboffsets = NULL; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":292 * info.shape = PyArray_DIMS(self) * info.suboffsets = NULL * info.itemsize = PyArray_ITEMSIZE(self) # <<<<<<<<<<<<<< * info.readonly = not PyArray_ISWRITEABLE(self) * */ __pyx_v_info->itemsize = PyArray_ITEMSIZE(__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":293 * info.suboffsets = NULL * info.itemsize = PyArray_ITEMSIZE(self) * info.readonly = not PyArray_ISWRITEABLE(self) # <<<<<<<<<<<<<< * * cdef int t */ __pyx_v_info->readonly = (!(PyArray_ISWRITEABLE(__pyx_v_self) != 0)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":296 * * cdef int t * cdef char* f = NULL # <<<<<<<<<<<<<< * cdef dtype descr = PyArray_DESCR(self) * cdef int offset */ __pyx_v_f = NULL; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":297 * cdef int t * cdef char* f = NULL * cdef dtype descr = PyArray_DESCR(self) # <<<<<<<<<<<<<< * cdef int offset * */ __pyx_t_7 = PyArray_DESCR(__pyx_v_self); __pyx_t_3 = ((PyObject *)__pyx_t_7); __Pyx_INCREF(__pyx_t_3); __pyx_v_descr = ((PyArray_Descr *)__pyx_t_3); __pyx_t_3 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":300 * cdef int offset * * info.obj = self # <<<<<<<<<<<<<< * * if not PyDataType_HASFIELDS(descr): */ __Pyx_INCREF(((PyObject *)__pyx_v_self)); __Pyx_GIVEREF(((PyObject *)__pyx_v_self)); __Pyx_GOTREF(__pyx_v_info->obj); __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = ((PyObject *)__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":302 * info.obj = self * * if not PyDataType_HASFIELDS(descr): # <<<<<<<<<<<<<< * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or */ __pyx_t_1 = ((!(PyDataType_HASFIELDS(__pyx_v_descr) != 0)) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":303 * * if not PyDataType_HASFIELDS(descr): * t = descr.type_num # <<<<<<<<<<<<<< * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): */ __pyx_t_4 = __pyx_v_descr->type_num; __pyx_v_t = __pyx_t_4; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":304 * if not PyDataType_HASFIELDS(descr): * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ __pyx_t_2 = ((__pyx_v_descr->byteorder == '>') != 0); if (!__pyx_t_2) { goto __pyx_L15_next_or; } else { } __pyx_t_2 = (__pyx_v_little_endian != 0); if (!__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L14_bool_binop_done; } __pyx_L15_next_or:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":305 * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): # <<<<<<<<<<<<<< * raise ValueError(u"Non-native byte order not supported") * if t == NPY_BYTE: f = "b" */ __pyx_t_2 = ((__pyx_v_descr->byteorder == '<') != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L14_bool_binop_done; } __pyx_t_2 = ((!(__pyx_v_little_endian != 0)) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L14_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":304 * if not PyDataType_HASFIELDS(descr): * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ if (unlikely(__pyx_t_1)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":306 * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 306, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 306, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":304 * if not PyDataType_HASFIELDS(descr): * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":307 * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") * if t == NPY_BYTE: f = "b" # <<<<<<<<<<<<<< * elif t == NPY_UBYTE: f = "B" * elif t == NPY_SHORT: f = "h" */ switch (__pyx_v_t) { case NPY_BYTE: __pyx_v_f = ((char *)"b"); break; case NPY_UBYTE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":308 * raise ValueError(u"Non-native byte order not supported") * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" # <<<<<<<<<<<<<< * elif t == NPY_SHORT: f = "h" * elif t == NPY_USHORT: f = "H" */ __pyx_v_f = ((char *)"B"); break; case NPY_SHORT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":309 * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" * elif t == NPY_SHORT: f = "h" # <<<<<<<<<<<<<< * elif t == NPY_USHORT: f = "H" * elif t == NPY_INT: f = "i" */ __pyx_v_f = ((char *)"h"); break; case NPY_USHORT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":310 * elif t == NPY_UBYTE: f = "B" * elif t == NPY_SHORT: f = "h" * elif t == NPY_USHORT: f = "H" # <<<<<<<<<<<<<< * elif t == NPY_INT: f = "i" * elif t == NPY_UINT: f = "I" */ __pyx_v_f = ((char *)"H"); break; case NPY_INT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":311 * elif t == NPY_SHORT: f = "h" * elif t == NPY_USHORT: f = "H" * elif t == NPY_INT: f = "i" # <<<<<<<<<<<<<< * elif t == NPY_UINT: f = "I" * elif t == NPY_LONG: f = "l" */ __pyx_v_f = ((char *)"i"); break; case NPY_UINT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":312 * elif t == NPY_USHORT: f = "H" * elif t == NPY_INT: f = "i" * elif t == NPY_UINT: f = "I" # <<<<<<<<<<<<<< * elif t == NPY_LONG: f = "l" * elif t == NPY_ULONG: f = "L" */ __pyx_v_f = ((char *)"I"); break; case NPY_LONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":313 * elif t == NPY_INT: f = "i" * elif t == NPY_UINT: f = "I" * elif t == NPY_LONG: f = "l" # <<<<<<<<<<<<<< * elif t == NPY_ULONG: f = "L" * elif t == NPY_LONGLONG: f = "q" */ __pyx_v_f = ((char *)"l"); break; case NPY_ULONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":314 * elif t == NPY_UINT: f = "I" * elif t == NPY_LONG: f = "l" * elif t == NPY_ULONG: f = "L" # <<<<<<<<<<<<<< * elif t == NPY_LONGLONG: f = "q" * elif t == NPY_ULONGLONG: f = "Q" */ __pyx_v_f = ((char *)"L"); break; case NPY_LONGLONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":315 * elif t == NPY_LONG: f = "l" * elif t == NPY_ULONG: f = "L" * elif t == NPY_LONGLONG: f = "q" # <<<<<<<<<<<<<< * elif t == NPY_ULONGLONG: f = "Q" * elif t == NPY_FLOAT: f = "f" */ __pyx_v_f = ((char *)"q"); break; case NPY_ULONGLONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":316 * elif t == NPY_ULONG: f = "L" * elif t == NPY_LONGLONG: f = "q" * elif t == NPY_ULONGLONG: f = "Q" # <<<<<<<<<<<<<< * elif t == NPY_FLOAT: f = "f" * elif t == NPY_DOUBLE: f = "d" */ __pyx_v_f = ((char *)"Q"); break; case NPY_FLOAT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":317 * elif t == NPY_LONGLONG: f = "q" * elif t == NPY_ULONGLONG: f = "Q" * elif t == NPY_FLOAT: f = "f" # <<<<<<<<<<<<<< * elif t == NPY_DOUBLE: f = "d" * elif t == NPY_LONGDOUBLE: f = "g" */ __pyx_v_f = ((char *)"f"); break; case NPY_DOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":318 * elif t == NPY_ULONGLONG: f = "Q" * elif t == NPY_FLOAT: f = "f" * elif t == NPY_DOUBLE: f = "d" # <<<<<<<<<<<<<< * elif t == NPY_LONGDOUBLE: f = "g" * elif t == NPY_CFLOAT: f = "Zf" */ __pyx_v_f = ((char *)"d"); break; case NPY_LONGDOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":319 * elif t == NPY_FLOAT: f = "f" * elif t == NPY_DOUBLE: f = "d" * elif t == NPY_LONGDOUBLE: f = "g" # <<<<<<<<<<<<<< * elif t == NPY_CFLOAT: f = "Zf" * elif t == NPY_CDOUBLE: f = "Zd" */ __pyx_v_f = ((char *)"g"); break; case NPY_CFLOAT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":320 * elif t == NPY_DOUBLE: f = "d" * elif t == NPY_LONGDOUBLE: f = "g" * elif t == NPY_CFLOAT: f = "Zf" # <<<<<<<<<<<<<< * elif t == NPY_CDOUBLE: f = "Zd" * elif t == NPY_CLONGDOUBLE: f = "Zg" */ __pyx_v_f = ((char *)"Zf"); break; case NPY_CDOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":321 * elif t == NPY_LONGDOUBLE: f = "g" * elif t == NPY_CFLOAT: f = "Zf" * elif t == NPY_CDOUBLE: f = "Zd" # <<<<<<<<<<<<<< * elif t == NPY_CLONGDOUBLE: f = "Zg" * elif t == NPY_OBJECT: f = "O" */ __pyx_v_f = ((char *)"Zd"); break; case NPY_CLONGDOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":322 * elif t == NPY_CFLOAT: f = "Zf" * elif t == NPY_CDOUBLE: f = "Zd" * elif t == NPY_CLONGDOUBLE: f = "Zg" # <<<<<<<<<<<<<< * elif t == NPY_OBJECT: f = "O" * else: */ __pyx_v_f = ((char *)"Zg"); break; case NPY_OBJECT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":323 * elif t == NPY_CDOUBLE: f = "Zd" * elif t == NPY_CLONGDOUBLE: f = "Zg" * elif t == NPY_OBJECT: f = "O" # <<<<<<<<<<<<<< * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) */ __pyx_v_f = ((char *)"O"); break; default: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":325 * elif t == NPY_OBJECT: f = "O" * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) # <<<<<<<<<<<<<< * info.format = f * return */ __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_8 = PyUnicode_Format(__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_t_3); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 325, __pyx_L1_error) break; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":326 * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) * info.format = f # <<<<<<<<<<<<<< * return * else: */ __pyx_v_info->format = __pyx_v_f; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":327 * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) * info.format = f * return # <<<<<<<<<<<<<< * else: * info.format = PyObject_Malloc(_buffer_format_string_len) */ __pyx_r = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":302 * info.obj = self * * if not PyDataType_HASFIELDS(descr): # <<<<<<<<<<<<<< * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":329 * return * else: * info.format = PyObject_Malloc(_buffer_format_string_len) # <<<<<<<<<<<<<< * info.format[0] = c'^' # Native data types, manual alignment * offset = 0 */ /*else*/ { __pyx_v_info->format = ((char *)PyObject_Malloc(0xFF)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":330 * else: * info.format = PyObject_Malloc(_buffer_format_string_len) * info.format[0] = c'^' # Native data types, manual alignment # <<<<<<<<<<<<<< * offset = 0 * f = _util_dtypestring(descr, info.format + 1, */ (__pyx_v_info->format[0]) = '^'; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":331 * info.format = PyObject_Malloc(_buffer_format_string_len) * info.format[0] = c'^' # Native data types, manual alignment * offset = 0 # <<<<<<<<<<<<<< * f = _util_dtypestring(descr, info.format + 1, * info.format + _buffer_format_string_len, */ __pyx_v_offset = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":332 * info.format[0] = c'^' # Native data types, manual alignment * offset = 0 * f = _util_dtypestring(descr, info.format + 1, # <<<<<<<<<<<<<< * info.format + _buffer_format_string_len, * &offset) */ __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 0xFF), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == ((char *)NULL))) __PYX_ERR(1, 332, __pyx_L1_error) __pyx_v_f = __pyx_t_9; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":335 * info.format + _buffer_format_string_len, * &offset) * f[0] = c'\0' # Terminate format string # <<<<<<<<<<<<<< * * def __releasebuffer__(ndarray self, Py_buffer* info): */ (__pyx_v_f[0]) = '\x00'; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":258 * # experimental exception made for __getbuffer__ and __releasebuffer__ * # -- the details of this may change. * def __getbuffer__(ndarray self, Py_buffer* info, int flags): # <<<<<<<<<<<<<< * # This implementation of getbuffer is geared towards Cython * # requirements, and does not yet fulfill the PEP. */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.ndarray.__getbuffer__", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; if (__pyx_v_info->obj != NULL) { __Pyx_GOTREF(__pyx_v_info->obj); __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; } goto __pyx_L2; __pyx_L0:; if (__pyx_v_info->obj == Py_None) { __Pyx_GOTREF(__pyx_v_info->obj); __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; } __pyx_L2:; __Pyx_XDECREF((PyObject *)__pyx_v_descr); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":337 * f[0] = c'\0' # Terminate format string * * def __releasebuffer__(ndarray self, Py_buffer* info): # <<<<<<<<<<<<<< * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) */ /* Python wrapper */ static CYTHON_UNUSED void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/ static CYTHON_UNUSED void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__releasebuffer__ (wrapper)", 0); __pyx_pf_5numpy_7ndarray_2__releasebuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info)); /* function exit code */ __Pyx_RefNannyFinishContext(); } static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info) { __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("__releasebuffer__", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":338 * * def __releasebuffer__(ndarray self, Py_buffer* info): * if PyArray_HASFIELDS(self): # <<<<<<<<<<<<<< * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): */ __pyx_t_1 = (PyArray_HASFIELDS(__pyx_v_self) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":339 * def __releasebuffer__(ndarray self, Py_buffer* info): * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) # <<<<<<<<<<<<<< * if sizeof(npy_intp) != sizeof(Py_ssize_t): * PyObject_Free(info.strides) */ PyObject_Free(__pyx_v_info->format); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":338 * * def __releasebuffer__(ndarray self, Py_buffer* info): * if PyArray_HASFIELDS(self): # <<<<<<<<<<<<<< * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":340 * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * PyObject_Free(info.strides) * # info.shape was stored after info.strides in the same block */ __pyx_t_1 = (((sizeof(npy_intp)) != (sizeof(Py_ssize_t))) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":341 * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): * PyObject_Free(info.strides) # <<<<<<<<<<<<<< * # info.shape was stored after info.strides in the same block * */ PyObject_Free(__pyx_v_info->strides); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":340 * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * PyObject_Free(info.strides) * # info.shape was stored after info.strides in the same block */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":337 * f[0] = c'\0' # Terminate format string * * def __releasebuffer__(ndarray self, Py_buffer* info): # <<<<<<<<<<<<<< * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) */ /* function exit code */ __Pyx_RefNannyFinishContext(); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":821 * ctypedef npy_cdouble complex_t * * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(1, a) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":822 * * cdef inline object PyArray_MultiIterNew1(a): * return PyArray_MultiIterNew(1, a) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew2(a, b): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 822, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":821 * ctypedef npy_cdouble complex_t * * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(1, a) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":824 * return PyArray_MultiIterNew(1, a) * * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(2, a, b) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":825 * * cdef inline object PyArray_MultiIterNew2(a, b): * return PyArray_MultiIterNew(2, a, b) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew3(a, b, c): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 825, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":824 * return PyArray_MultiIterNew(1, a) * * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(2, a, b) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":827 * return PyArray_MultiIterNew(2, a, b) * * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(3, a, b, c) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":828 * * cdef inline object PyArray_MultiIterNew3(a, b, c): * return PyArray_MultiIterNew(3, a, b, c) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 828, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":827 * return PyArray_MultiIterNew(2, a, b) * * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(3, a, b, c) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":830 * return PyArray_MultiIterNew(3, a, b, c) * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(4, a, b, c, d) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":831 * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): * return PyArray_MultiIterNew(4, a, b, c, d) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 831, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":830 * return PyArray_MultiIterNew(3, a, b, c) * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(4, a, b, c, d) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":833 * return PyArray_MultiIterNew(4, a, b, c, d) * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(5, a, b, c, d, e) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":834 * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): * return PyArray_MultiIterNew(5, a, b, c, d, e) # <<<<<<<<<<<<<< * * cdef inline tuple PyDataType_SHAPE(dtype d): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 834, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":833 * return PyArray_MultiIterNew(4, a, b, c, d) * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(5, a, b, c, d, e) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":836 * return PyArray_MultiIterNew(5, a, b, c, d, e) * * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__pyx_v_d) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("PyDataType_SHAPE", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":837 * * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< * return d.subarray.shape * else: */ __pyx_t_1 = (PyDataType_HASSUBARRAY(__pyx_v_d) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":838 * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape # <<<<<<<<<<<<<< * else: * return () */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(((PyObject*)__pyx_v_d->subarray->shape)); __pyx_r = ((PyObject*)__pyx_v_d->subarray->shape); goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":837 * * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< * return d.subarray.shape * else: */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":840 * return d.subarray.shape * else: * return () # <<<<<<<<<<<<<< * * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: */ /*else*/ { __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(__pyx_empty_tuple); __pyx_r = __pyx_empty_tuple; goto __pyx_L0; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":836 * return PyArray_MultiIterNew(5, a, b, c, d, e) * * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape */ /* function exit code */ __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":842 * return () * * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: # <<<<<<<<<<<<<< * # Recursive utility function used in __getbuffer__ to get format * # string. The new location in the format string is returned. */ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx_v_descr, char *__pyx_v_f, char *__pyx_v_end, int *__pyx_v_offset) { PyArray_Descr *__pyx_v_child = 0; int __pyx_v_endian_detector; int __pyx_v_little_endian; PyObject *__pyx_v_fields = 0; PyObject *__pyx_v_childname = NULL; PyObject *__pyx_v_new_offset = NULL; PyObject *__pyx_v_t = NULL; char *__pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; Py_ssize_t __pyx_t_2; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; int __pyx_t_5; int __pyx_t_6; int __pyx_t_7; long __pyx_t_8; char *__pyx_t_9; __Pyx_RefNannySetupContext("_util_dtypestring", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":847 * * cdef dtype child * cdef int endian_detector = 1 # <<<<<<<<<<<<<< * cdef bint little_endian = ((&endian_detector)[0] != 0) * cdef tuple fields */ __pyx_v_endian_detector = 1; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":848 * cdef dtype child * cdef int endian_detector = 1 * cdef bint little_endian = ((&endian_detector)[0] != 0) # <<<<<<<<<<<<<< * cdef tuple fields * */ __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":851 * cdef tuple fields * * for childname in descr.names: # <<<<<<<<<<<<<< * fields = descr.fields[childname] * child, new_offset = fields */ if (unlikely(__pyx_v_descr->names == Py_None)) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); __PYX_ERR(1, 851, __pyx_L1_error) } __pyx_t_1 = __pyx_v_descr->names; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0; for (;;) { if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break; #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) __PYX_ERR(1, 851, __pyx_L1_error) #else __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 851, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); #endif __Pyx_XDECREF_SET(__pyx_v_childname, __pyx_t_3); __pyx_t_3 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":852 * * for childname in descr.names: * fields = descr.fields[childname] # <<<<<<<<<<<<<< * child, new_offset = fields * */ if (unlikely(__pyx_v_descr->fields == Py_None)) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); __PYX_ERR(1, 852, __pyx_L1_error) } __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 852, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(1, 852, __pyx_L1_error) __Pyx_XDECREF_SET(__pyx_v_fields, ((PyObject*)__pyx_t_3)); __pyx_t_3 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":853 * for childname in descr.names: * fields = descr.fields[childname] * child, new_offset = fields # <<<<<<<<<<<<<< * * if (end - f) - (new_offset - offset[0]) < 15: */ if (likely(__pyx_v_fields != Py_None)) { PyObject* sequence = __pyx_v_fields; Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); if (unlikely(size != 2)) { if (size > 2) __Pyx_RaiseTooManyValuesError(2); else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); __PYX_ERR(1, 853, __pyx_L1_error) } #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); __Pyx_INCREF(__pyx_t_3); __Pyx_INCREF(__pyx_t_4); #else __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 853, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 853, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); #endif } else { __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(1, 853, __pyx_L1_error) } if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) __PYX_ERR(1, 853, __pyx_L1_error) __Pyx_XDECREF_SET(__pyx_v_child, ((PyArray_Descr *)__pyx_t_3)); __pyx_t_3 = 0; __Pyx_XDECREF_SET(__pyx_v_new_offset, __pyx_t_4); __pyx_t_4 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":855 * child, new_offset = fields * * if (end - f) - (new_offset - offset[0]) < 15: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * */ __pyx_t_4 = __Pyx_PyInt_From_int((__pyx_v_offset[0])); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 855, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 855, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_5 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_5 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 855, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = ((((__pyx_v_end - __pyx_v_f) - ((int)__pyx_t_5)) < 15) != 0); if (unlikely(__pyx_t_6)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":856 * * if (end - f) - (new_offset - offset[0]) < 15: * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") # <<<<<<<<<<<<<< * * if ((child.byteorder == c'>' and little_endian) or */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 856, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 856, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":855 * child, new_offset = fields * * if (end - f) - (new_offset - offset[0]) < 15: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":858 * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ __pyx_t_7 = ((__pyx_v_child->byteorder == '>') != 0); if (!__pyx_t_7) { goto __pyx_L8_next_or; } else { } __pyx_t_7 = (__pyx_v_little_endian != 0); if (!__pyx_t_7) { } else { __pyx_t_6 = __pyx_t_7; goto __pyx_L7_bool_binop_done; } __pyx_L8_next_or:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":859 * * if ((child.byteorder == c'>' and little_endian) or * (child.byteorder == c'<' and not little_endian)): # <<<<<<<<<<<<<< * raise ValueError(u"Non-native byte order not supported") * # One could encode it in the format string and have Cython */ __pyx_t_7 = ((__pyx_v_child->byteorder == '<') != 0); if (__pyx_t_7) { } else { __pyx_t_6 = __pyx_t_7; goto __pyx_L7_bool_binop_done; } __pyx_t_7 = ((!(__pyx_v_little_endian != 0)) != 0); __pyx_t_6 = __pyx_t_7; __pyx_L7_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":858 * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ if (unlikely(__pyx_t_6)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":860 * if ((child.byteorder == c'>' and little_endian) or * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< * # One could encode it in the format string and have Cython * # complain instead, BUT: < and > in format strings also imply */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 860, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 860, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":858 * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":870 * * # Output padding bytes * while offset[0] < new_offset: # <<<<<<<<<<<<<< * f[0] = 120 # "x"; pad byte * f += 1 */ while (1) { __pyx_t_3 = __Pyx_PyInt_From_int((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 870, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_t_3, __pyx_v_new_offset, Py_LT); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 870, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 870, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (!__pyx_t_6) break; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":871 * # Output padding bytes * while offset[0] < new_offset: * f[0] = 120 # "x"; pad byte # <<<<<<<<<<<<<< * f += 1 * offset[0] += 1 */ (__pyx_v_f[0]) = 0x78; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":872 * while offset[0] < new_offset: * f[0] = 120 # "x"; pad byte * f += 1 # <<<<<<<<<<<<<< * offset[0] += 1 * */ __pyx_v_f = (__pyx_v_f + 1); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":873 * f[0] = 120 # "x"; pad byte * f += 1 * offset[0] += 1 # <<<<<<<<<<<<<< * * offset[0] += child.itemsize */ __pyx_t_8 = 0; (__pyx_v_offset[__pyx_t_8]) = ((__pyx_v_offset[__pyx_t_8]) + 1); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":875 * offset[0] += 1 * * offset[0] += child.itemsize # <<<<<<<<<<<<<< * * if not PyDataType_HASFIELDS(child): */ __pyx_t_8 = 0; (__pyx_v_offset[__pyx_t_8]) = ((__pyx_v_offset[__pyx_t_8]) + __pyx_v_child->elsize); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":877 * offset[0] += child.itemsize * * if not PyDataType_HASFIELDS(child): # <<<<<<<<<<<<<< * t = child.type_num * if end - f < 5: */ __pyx_t_6 = ((!(PyDataType_HASFIELDS(__pyx_v_child) != 0)) != 0); if (__pyx_t_6) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":878 * * if not PyDataType_HASFIELDS(child): * t = child.type_num # <<<<<<<<<<<<<< * if end - f < 5: * raise RuntimeError(u"Format string allocated too short.") */ __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_child->type_num); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 878, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_4); __pyx_t_4 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":879 * if not PyDataType_HASFIELDS(child): * t = child.type_num * if end - f < 5: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short.") * */ __pyx_t_6 = (((__pyx_v_end - __pyx_v_f) < 5) != 0); if (unlikely(__pyx_t_6)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":880 * t = child.type_num * if end - f < 5: * raise RuntimeError(u"Format string allocated too short.") # <<<<<<<<<<<<<< * * # Until ticket #99 is fixed, use integers to avoid warnings */ __pyx_t_4 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 880, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_Raise(__pyx_t_4, 0, 0, 0); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __PYX_ERR(1, 880, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":879 * if not PyDataType_HASFIELDS(child): * t = child.type_num * if end - f < 5: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short.") * */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":883 * * # Until ticket #99 is fixed, use integers to avoid warnings * if t == NPY_BYTE: f[0] = 98 #"b" # <<<<<<<<<<<<<< * elif t == NPY_UBYTE: f[0] = 66 #"B" * elif t == NPY_SHORT: f[0] = 104 #"h" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_BYTE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 883, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 883, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 883, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 98; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":884 * # Until ticket #99 is fixed, use integers to avoid warnings * if t == NPY_BYTE: f[0] = 98 #"b" * elif t == NPY_UBYTE: f[0] = 66 #"B" # <<<<<<<<<<<<<< * elif t == NPY_SHORT: f[0] = 104 #"h" * elif t == NPY_USHORT: f[0] = 72 #"H" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_UBYTE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 884, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 884, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 884, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 66; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":885 * if t == NPY_BYTE: f[0] = 98 #"b" * elif t == NPY_UBYTE: f[0] = 66 #"B" * elif t == NPY_SHORT: f[0] = 104 #"h" # <<<<<<<<<<<<<< * elif t == NPY_USHORT: f[0] = 72 #"H" * elif t == NPY_INT: f[0] = 105 #"i" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_SHORT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 885, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 885, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 885, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x68; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":886 * elif t == NPY_UBYTE: f[0] = 66 #"B" * elif t == NPY_SHORT: f[0] = 104 #"h" * elif t == NPY_USHORT: f[0] = 72 #"H" # <<<<<<<<<<<<<< * elif t == NPY_INT: f[0] = 105 #"i" * elif t == NPY_UINT: f[0] = 73 #"I" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_USHORT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 886, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 886, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 886, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 72; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":887 * elif t == NPY_SHORT: f[0] = 104 #"h" * elif t == NPY_USHORT: f[0] = 72 #"H" * elif t == NPY_INT: f[0] = 105 #"i" # <<<<<<<<<<<<<< * elif t == NPY_UINT: f[0] = 73 #"I" * elif t == NPY_LONG: f[0] = 108 #"l" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_INT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 887, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 887, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 887, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x69; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":888 * elif t == NPY_USHORT: f[0] = 72 #"H" * elif t == NPY_INT: f[0] = 105 #"i" * elif t == NPY_UINT: f[0] = 73 #"I" # <<<<<<<<<<<<<< * elif t == NPY_LONG: f[0] = 108 #"l" * elif t == NPY_ULONG: f[0] = 76 #"L" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_UINT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 888, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 888, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 888, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 73; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":889 * elif t == NPY_INT: f[0] = 105 #"i" * elif t == NPY_UINT: f[0] = 73 #"I" * elif t == NPY_LONG: f[0] = 108 #"l" # <<<<<<<<<<<<<< * elif t == NPY_ULONG: f[0] = 76 #"L" * elif t == NPY_LONGLONG: f[0] = 113 #"q" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONG); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 889, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 889, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 889, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x6C; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":890 * elif t == NPY_UINT: f[0] = 73 #"I" * elif t == NPY_LONG: f[0] = 108 #"l" * elif t == NPY_ULONG: f[0] = 76 #"L" # <<<<<<<<<<<<<< * elif t == NPY_LONGLONG: f[0] = 113 #"q" * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_ULONG); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 890, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 890, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 890, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 76; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":891 * elif t == NPY_LONG: f[0] = 108 #"l" * elif t == NPY_ULONG: f[0] = 76 #"L" * elif t == NPY_LONGLONG: f[0] = 113 #"q" # <<<<<<<<<<<<<< * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" * elif t == NPY_FLOAT: f[0] = 102 #"f" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONGLONG); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 891, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 891, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 891, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x71; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":892 * elif t == NPY_ULONG: f[0] = 76 #"L" * elif t == NPY_LONGLONG: f[0] = 113 #"q" * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" # <<<<<<<<<<<<<< * elif t == NPY_FLOAT: f[0] = 102 #"f" * elif t == NPY_DOUBLE: f[0] = 100 #"d" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_ULONGLONG); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 892, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 892, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 892, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 81; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":893 * elif t == NPY_LONGLONG: f[0] = 113 #"q" * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" * elif t == NPY_FLOAT: f[0] = 102 #"f" # <<<<<<<<<<<<<< * elif t == NPY_DOUBLE: f[0] = 100 #"d" * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_FLOAT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 893, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 893, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 893, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x66; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":894 * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" * elif t == NPY_FLOAT: f[0] = 102 #"f" * elif t == NPY_DOUBLE: f[0] = 100 #"d" # <<<<<<<<<<<<<< * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_DOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 894, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 894, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 894, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x64; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":895 * elif t == NPY_FLOAT: f[0] = 102 #"f" * elif t == NPY_DOUBLE: f[0] = 100 #"d" * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" # <<<<<<<<<<<<<< * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 895, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 895, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 895, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x67; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":896 * elif t == NPY_DOUBLE: f[0] = 100 #"d" * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf # <<<<<<<<<<<<<< * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CFLOAT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 896, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 896, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 896, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 90; (__pyx_v_f[1]) = 0x66; __pyx_v_f = (__pyx_v_f + 1); goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":897 * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd # <<<<<<<<<<<<<< * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg * elif t == NPY_OBJECT: f[0] = 79 #"O" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CDOUBLE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 897, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 897, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 897, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 90; (__pyx_v_f[1]) = 0x64; __pyx_v_f = (__pyx_v_f + 1); goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":898 * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg # <<<<<<<<<<<<<< * elif t == NPY_OBJECT: f[0] = 79 #"O" * else: */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 898, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 898, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 898, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 90; (__pyx_v_f[1]) = 0x67; __pyx_v_f = (__pyx_v_f + 1); goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":899 * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg * elif t == NPY_OBJECT: f[0] = 79 #"O" # <<<<<<<<<<<<<< * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_OBJECT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 899, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 899, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 899, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (likely(__pyx_t_6)) { (__pyx_v_f[0]) = 79; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":901 * elif t == NPY_OBJECT: f[0] = 79 #"O" * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) # <<<<<<<<<<<<<< * f += 1 * else: */ /*else*/ { __pyx_t_3 = __Pyx_PyUnicode_FormatSafe(__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_v_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 901, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 901, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_Raise(__pyx_t_4, 0, 0, 0); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __PYX_ERR(1, 901, __pyx_L1_error) } __pyx_L15:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":902 * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) * f += 1 # <<<<<<<<<<<<<< * else: * # Cython ignores struct boundary information ("T{...}"), */ __pyx_v_f = (__pyx_v_f + 1); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":877 * offset[0] += child.itemsize * * if not PyDataType_HASFIELDS(child): # <<<<<<<<<<<<<< * t = child.type_num * if end - f < 5: */ goto __pyx_L13; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":906 * # Cython ignores struct boundary information ("T{...}"), * # so don't output it * f = _util_dtypestring(child, f, end, offset) # <<<<<<<<<<<<<< * return f * */ /*else*/ { __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_9 == ((char *)NULL))) __PYX_ERR(1, 906, __pyx_L1_error) __pyx_v_f = __pyx_t_9; } __pyx_L13:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":851 * cdef tuple fields * * for childname in descr.names: # <<<<<<<<<<<<<< * fields = descr.fields[childname] * child, new_offset = fields */ } __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":907 * # so don't output it * f = _util_dtypestring(child, f, end, offset) * return f # <<<<<<<<<<<<<< * * */ __pyx_r = __pyx_v_f; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":842 * return () * * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: # <<<<<<<<<<<<<< * # Recursive utility function used in __getbuffer__ to get format * # string. The new location in the format string is returned. */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __Pyx_AddTraceback("numpy._util_dtypestring", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XDECREF((PyObject *)__pyx_v_child); __Pyx_XDECREF(__pyx_v_fields); __Pyx_XDECREF(__pyx_v_childname); __Pyx_XDECREF(__pyx_v_new_offset); __Pyx_XDECREF(__pyx_v_t); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1022 * int _import_umath() except -1 * * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) */ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("set_array_base", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1023 * * cdef inline void set_array_base(ndarray arr, object base): * Py_INCREF(base) # important to do this before stealing the reference below! # <<<<<<<<<<<<<< * PyArray_SetBaseObject(arr, base) * */ Py_INCREF(__pyx_v_base); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1024 * cdef inline void set_array_base(ndarray arr, object base): * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) # <<<<<<<<<<<<<< * * cdef inline object get_array_base(ndarray arr): */ (void)(PyArray_SetBaseObject(__pyx_v_arr, __pyx_v_base)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1022 * int _import_umath() except -1 * * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) */ /* function exit code */ __Pyx_RefNannyFinishContext(); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1026 * PyArray_SetBaseObject(arr, base) * * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< * base = PyArray_BASE(arr) * if base is NULL: */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) { PyObject *__pyx_v_base; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("get_array_base", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1027 * * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) # <<<<<<<<<<<<<< * if base is NULL: * return None */ __pyx_v_base = PyArray_BASE(__pyx_v_arr); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1028 * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) * if base is NULL: # <<<<<<<<<<<<<< * return None * return base */ __pyx_t_1 = ((__pyx_v_base == NULL) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1029 * base = PyArray_BASE(arr) * if base is NULL: * return None # <<<<<<<<<<<<<< * return base * */ __Pyx_XDECREF(__pyx_r); __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1028 * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) * if base is NULL: # <<<<<<<<<<<<<< * return None * return base */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1030 * if base is NULL: * return None * return base # <<<<<<<<<<<<<< * * # Versions of the import_* functions which are more suitable for */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(((PyObject *)__pyx_v_base)); __pyx_r = ((PyObject *)__pyx_v_base); goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1026 * PyArray_SetBaseObject(arr, base) * * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< * base = PyArray_BASE(arr) * if base is NULL: */ /* function exit code */ __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1034 * # Versions of the import_* functions which are more suitable for * # Cython code. * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< * try: * _import_array() */ static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; __Pyx_RefNannySetupContext("import_array", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1035 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< * _import_array() * except Exception: */ { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); __Pyx_XGOTREF(__pyx_t_1); __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1036 * cdef inline int import_array() except -1: * try: * _import_array() # <<<<<<<<<<<<<< * except Exception: * raise ImportError("numpy.core.multiarray failed to import") */ __pyx_t_4 = _import_array(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1036, __pyx_L3_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1035 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< * _import_array() * except Exception: */ } __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L8_try_end; __pyx_L3_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1037 * try: * _import_array() * except Exception: # <<<<<<<<<<<<<< * raise ImportError("numpy.core.multiarray failed to import") * */ __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); if (__pyx_t_4) { __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1037, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1038 * _import_array() * except Exception: * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_umath() except -1: */ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__6, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1038, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(1, 1038, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1035 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< * _import_array() * except Exception: */ __Pyx_XGIVEREF(__pyx_t_1); __Pyx_XGIVEREF(__pyx_t_2); __Pyx_XGIVEREF(__pyx_t_3); __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); goto __pyx_L1_error; __pyx_L8_try_end:; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1034 * # Versions of the import_* functions which are more suitable for * # Cython code. * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< * try: * _import_array() */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1040 * raise ImportError("numpy.core.multiarray failed to import") * * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; __Pyx_RefNannySetupContext("import_umath", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1041 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); __Pyx_XGOTREF(__pyx_t_1); __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1042 * cdef inline int import_umath() except -1: * try: * _import_umath() # <<<<<<<<<<<<<< * except Exception: * raise ImportError("numpy.core.umath failed to import") */ __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1042, __pyx_L3_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1041 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ } __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L8_try_end; __pyx_L3_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1043 * try: * _import_umath() * except Exception: # <<<<<<<<<<<<<< * raise ImportError("numpy.core.umath failed to import") * */ __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); if (__pyx_t_4) { __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1043, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1044 * _import_umath() * except Exception: * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_ufunc() except -1: */ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1044, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(1, 1044, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1041 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ __Pyx_XGIVEREF(__pyx_t_1); __Pyx_XGIVEREF(__pyx_t_2); __Pyx_XGIVEREF(__pyx_t_3); __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); goto __pyx_L1_error; __pyx_L8_try_end:; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1040 * raise ImportError("numpy.core.multiarray failed to import") * * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1046 * raise ImportError("numpy.core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; __Pyx_RefNannySetupContext("import_ufunc", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1047 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); __Pyx_XGOTREF(__pyx_t_1); __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1048 * cdef inline int import_ufunc() except -1: * try: * _import_umath() # <<<<<<<<<<<<<< * except Exception: * raise ImportError("numpy.core.umath failed to import") */ __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1048, __pyx_L3_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1047 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ } __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L8_try_end; __pyx_L3_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1049 * try: * _import_umath() * except Exception: # <<<<<<<<<<<<<< * raise ImportError("numpy.core.umath failed to import") */ __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); if (__pyx_t_4) { __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1049, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1050 * _import_umath() * except Exception: * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< */ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1050, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(1, 1050, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1047 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ __Pyx_XGIVEREF(__pyx_t_1); __Pyx_XGIVEREF(__pyx_t_2); __Pyx_XGIVEREF(__pyx_t_3); __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); goto __pyx_L1_error; __pyx_L8_try_end:; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1046 * raise ImportError("numpy.core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } static PyMethodDef __pyx_methods[] = { {0, 0, 0, 0} }; #if PY_MAJOR_VERSION >= 3 #if CYTHON_PEP489_MULTI_PHASE_INIT static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ static int __pyx_pymod_exec_elliptical_overlap(PyObject* module); /*proto*/ static PyModuleDef_Slot __pyx_moduledef_slots[] = { {Py_mod_create, (void*)__pyx_pymod_create}, {Py_mod_exec, (void*)__pyx_pymod_exec_elliptical_overlap}, {0, NULL} }; #endif static struct PyModuleDef __pyx_moduledef = { PyModuleDef_HEAD_INIT, "elliptical_overlap", __pyx_k_The_functions_defined_here_allo, /* m_doc */ #if CYTHON_PEP489_MULTI_PHASE_INIT 0, /* m_size */ #else -1, /* m_size */ #endif __pyx_methods /* m_methods */, #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_moduledef_slots, /* m_slots */ #else NULL, /* m_reload */ #endif NULL, /* m_traverse */ NULL, /* m_clear */ NULL /* m_free */ }; #endif #ifndef CYTHON_SMALL_CODE #if defined(__clang__) #define CYTHON_SMALL_CODE #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) #define CYTHON_SMALL_CODE __attribute__((cold)) #else #define CYTHON_SMALL_CODE #endif #endif static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_DTYPE, __pyx_k_DTYPE, sizeof(__pyx_k_DTYPE), 0, 0, 1, 1}, {&__pyx_kp_u_Format_string_allocated_too_shor, __pyx_k_Format_string_allocated_too_shor, sizeof(__pyx_k_Format_string_allocated_too_shor), 0, 1, 0, 0}, {&__pyx_kp_u_Format_string_allocated_too_shor_2, __pyx_k_Format_string_allocated_too_shor_2, sizeof(__pyx_k_Format_string_allocated_too_shor_2), 0, 1, 0, 0}, {&__pyx_n_s_ImportError, __pyx_k_ImportError, sizeof(__pyx_k_ImportError), 0, 0, 1, 1}, {&__pyx_kp_u_Non_native_byte_order_not_suppor, __pyx_k_Non_native_byte_order_not_suppor, sizeof(__pyx_k_Non_native_byte_order_not_suppor), 0, 1, 0, 0}, {&__pyx_n_s_RuntimeError, __pyx_k_RuntimeError, sizeof(__pyx_k_RuntimeError), 0, 0, 1, 1}, {&__pyx_n_s_ValueError, __pyx_k_ValueError, sizeof(__pyx_k_ValueError), 0, 0, 1, 1}, {&__pyx_n_s_all, __pyx_k_all, sizeof(__pyx_k_all), 0, 0, 1, 1}, {&__pyx_n_s_bxmax, __pyx_k_bxmax, sizeof(__pyx_k_bxmax), 0, 0, 1, 1}, {&__pyx_n_s_bxmin, __pyx_k_bxmin, sizeof(__pyx_k_bxmin), 0, 0, 1, 1}, {&__pyx_n_s_bymax, __pyx_k_bymax, sizeof(__pyx_k_bymax), 0, 0, 1, 1}, {&__pyx_n_s_bymin, __pyx_k_bymin, sizeof(__pyx_k_bymin), 0, 0, 1, 1}, {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, {&__pyx_n_s_dtype, __pyx_k_dtype, sizeof(__pyx_k_dtype), 0, 0, 1, 1}, {&__pyx_n_s_dx, __pyx_k_dx, sizeof(__pyx_k_dx), 0, 0, 1, 1}, {&__pyx_n_s_dy, __pyx_k_dy, sizeof(__pyx_k_dy), 0, 0, 1, 1}, {&__pyx_n_s_elliptical_overlap_grid, __pyx_k_elliptical_overlap_grid, sizeof(__pyx_k_elliptical_overlap_grid), 0, 0, 1, 1}, {&__pyx_n_u_elliptical_overlap_grid, __pyx_k_elliptical_overlap_grid, sizeof(__pyx_k_elliptical_overlap_grid), 0, 1, 0, 1}, {&__pyx_n_s_float64, __pyx_k_float64, sizeof(__pyx_k_float64), 0, 0, 1, 1}, {&__pyx_n_s_frac, __pyx_k_frac, sizeof(__pyx_k_frac), 0, 0, 1, 1}, {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1}, {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, {&__pyx_n_s_j, __pyx_k_j, sizeof(__pyx_k_j), 0, 0, 1, 1}, {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, {&__pyx_kp_u_ndarray_is_not_C_contiguous, __pyx_k_ndarray_is_not_C_contiguous, sizeof(__pyx_k_ndarray_is_not_C_contiguous), 0, 1, 0, 0}, {&__pyx_kp_u_ndarray_is_not_Fortran_contiguou, __pyx_k_ndarray_is_not_Fortran_contiguou, sizeof(__pyx_k_ndarray_is_not_Fortran_contiguou), 0, 1, 0, 0}, {&__pyx_n_s_norm, __pyx_k_norm, sizeof(__pyx_k_norm), 0, 0, 1, 1}, {&__pyx_n_s_np, __pyx_k_np, sizeof(__pyx_k_np), 0, 0, 1, 1}, {&__pyx_n_s_numpy, __pyx_k_numpy, sizeof(__pyx_k_numpy), 0, 0, 1, 1}, {&__pyx_kp_u_numpy_core_multiarray_failed_to, __pyx_k_numpy_core_multiarray_failed_to, sizeof(__pyx_k_numpy_core_multiarray_failed_to), 0, 1, 0, 0}, {&__pyx_kp_u_numpy_core_umath_failed_to_impor, __pyx_k_numpy_core_umath_failed_to_impor, sizeof(__pyx_k_numpy_core_umath_failed_to_impor), 0, 1, 0, 0}, {&__pyx_n_s_nx, __pyx_k_nx, sizeof(__pyx_k_nx), 0, 0, 1, 1}, {&__pyx_n_s_ny, __pyx_k_ny, sizeof(__pyx_k_ny), 0, 0, 1, 1}, {&__pyx_kp_s_photutils_geometry_elliptical_ov, __pyx_k_photutils_geometry_elliptical_ov, sizeof(__pyx_k_photutils_geometry_elliptical_ov), 0, 0, 1, 0}, {&__pyx_n_s_photutils_geometry_elliptical_ov_2, __pyx_k_photutils_geometry_elliptical_ov_2, sizeof(__pyx_k_photutils_geometry_elliptical_ov_2), 0, 0, 1, 1}, {&__pyx_n_s_pxmax, __pyx_k_pxmax, sizeof(__pyx_k_pxmax), 0, 0, 1, 1}, {&__pyx_n_s_pxmin, __pyx_k_pxmin, sizeof(__pyx_k_pxmin), 0, 0, 1, 1}, {&__pyx_n_s_pymax, __pyx_k_pymax, sizeof(__pyx_k_pymax), 0, 0, 1, 1}, {&__pyx_n_s_pymin, __pyx_k_pymin, sizeof(__pyx_k_pymin), 0, 0, 1, 1}, {&__pyx_n_s_r, __pyx_k_r, sizeof(__pyx_k_r), 0, 0, 1, 1}, {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, {&__pyx_n_s_rx, __pyx_k_rx, sizeof(__pyx_k_rx), 0, 0, 1, 1}, {&__pyx_n_s_ry, __pyx_k_ry, sizeof(__pyx_k_ry), 0, 0, 1, 1}, {&__pyx_n_s_subpixels, __pyx_k_subpixels, sizeof(__pyx_k_subpixels), 0, 0, 1, 1}, {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, {&__pyx_n_s_theta, __pyx_k_theta, sizeof(__pyx_k_theta), 0, 0, 1, 1}, {&__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_k_unknown_dtype_code_in_numpy_pxd, sizeof(__pyx_k_unknown_dtype_code_in_numpy_pxd), 0, 1, 0, 0}, {&__pyx_n_s_use_exact, __pyx_k_use_exact, sizeof(__pyx_k_use_exact), 0, 0, 1, 1}, {&__pyx_n_s_x, __pyx_k_x, sizeof(__pyx_k_x), 0, 0, 1, 1}, {&__pyx_n_s_xmax, __pyx_k_xmax, sizeof(__pyx_k_xmax), 0, 0, 1, 1}, {&__pyx_n_s_xmin, __pyx_k_xmin, sizeof(__pyx_k_xmin), 0, 0, 1, 1}, {&__pyx_n_s_y, __pyx_k_y, sizeof(__pyx_k_y), 0, 0, 1, 1}, {&__pyx_n_s_ymax, __pyx_k_ymax, sizeof(__pyx_k_ymax), 0, 0, 1, 1}, {&__pyx_n_s_ymin, __pyx_k_ymin, sizeof(__pyx_k_ymin), 0, 0, 1, 1}, {&__pyx_n_s_zeros, __pyx_k_zeros, sizeof(__pyx_k_zeros), 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0} }; static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 100, __pyx_L1_error) __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) __PYX_ERR(1, 272, __pyx_L1_error) __pyx_builtin_RuntimeError = __Pyx_GetBuiltinName(__pyx_n_s_RuntimeError); if (!__pyx_builtin_RuntimeError) __PYX_ERR(1, 856, __pyx_L1_error) __pyx_builtin_ImportError = __Pyx_GetBuiltinName(__pyx_n_s_ImportError); if (!__pyx_builtin_ImportError) __PYX_ERR(1, 1038, __pyx_L1_error) return 0; __pyx_L1_error:; return -1; } static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":272 * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") # <<<<<<<<<<<<<< * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) */ __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_u_ndarray_is_not_C_contiguous); if (unlikely(!__pyx_tuple_)) __PYX_ERR(1, 272, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple_); __Pyx_GIVEREF(__pyx_tuple_); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":276 * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") # <<<<<<<<<<<<<< * * info.buf = PyArray_DATA(self) */ __pyx_tuple__2 = PyTuple_Pack(1, __pyx_kp_u_ndarray_is_not_Fortran_contiguou); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(1, 276, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__2); __Pyx_GIVEREF(__pyx_tuple__2); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":306 * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" */ __pyx_tuple__3 = PyTuple_Pack(1, __pyx_kp_u_Non_native_byte_order_not_suppor); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(1, 306, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__3); __Pyx_GIVEREF(__pyx_tuple__3); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":856 * * if (end - f) - (new_offset - offset[0]) < 15: * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") # <<<<<<<<<<<<<< * * if ((child.byteorder == c'>' and little_endian) or */ __pyx_tuple__4 = PyTuple_Pack(1, __pyx_kp_u_Format_string_allocated_too_shor); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(1, 856, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__4); __Pyx_GIVEREF(__pyx_tuple__4); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":880 * t = child.type_num * if end - f < 5: * raise RuntimeError(u"Format string allocated too short.") # <<<<<<<<<<<<<< * * # Until ticket #99 is fixed, use integers to avoid warnings */ __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_u_Format_string_allocated_too_shor_2); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(1, 880, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__5); __Pyx_GIVEREF(__pyx_tuple__5); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1038 * _import_array() * except Exception: * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_umath() except -1: */ __pyx_tuple__6 = PyTuple_Pack(1, __pyx_kp_u_numpy_core_multiarray_failed_to); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(1, 1038, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__6); __Pyx_GIVEREF(__pyx_tuple__6); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1044 * _import_umath() * except Exception: * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_ufunc() except -1: */ __pyx_tuple__7 = PyTuple_Pack(1, __pyx_kp_u_numpy_core_umath_failed_to_impor); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(1, 1044, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__7); __Pyx_GIVEREF(__pyx_tuple__7); /* "photutils/geometry/elliptical_overlap.pyx":37 * * * def elliptical_overlap_grid(double xmin, double xmax, double ymin, double ymax, # <<<<<<<<<<<<<< * int nx, int ny, double rx, double ry, double theta, * int use_exact, int subpixels): */ __pyx_tuple__8 = PyTuple_Pack(28, __pyx_n_s_xmin, __pyx_n_s_xmax, __pyx_n_s_ymin, __pyx_n_s_ymax, __pyx_n_s_nx, __pyx_n_s_ny, __pyx_n_s_rx, __pyx_n_s_ry, __pyx_n_s_theta, __pyx_n_s_use_exact, __pyx_n_s_subpixels, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_x, __pyx_n_s_y, __pyx_n_s_dx, __pyx_n_s_dy, __pyx_n_s_bxmin, __pyx_n_s_bxmax, __pyx_n_s_bymin, __pyx_n_s_bymax, __pyx_n_s_pxmin, __pyx_n_s_pxmax, __pyx_n_s_pymin, __pyx_n_s_pymax, __pyx_n_s_norm, __pyx_n_s_frac, __pyx_n_s_r); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(0, 37, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__8); __Pyx_GIVEREF(__pyx_tuple__8); __pyx_codeobj__9 = (PyObject*)__Pyx_PyCode_New(11, 0, 28, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__8, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_photutils_geometry_elliptical_ov, __pyx_n_s_elliptical_overlap_grid, 37, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__9)) __PYX_ERR(0, 37, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; __Pyx_RefNannyFinishContext(); return -1; } static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); return 0; __pyx_L1_error:; return -1; } static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ static int __Pyx_modinit_global_init_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); /*--- Global init code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_variable_export_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); /*--- Variable export code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_function_export_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); /*--- Function export code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_type_init_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); /*--- Type init code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_type_import_code(void) { __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); /*--- Type import code ---*/ __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 9, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 sizeof(PyTypeObject), #else sizeof(PyHeapTypeObject), #endif __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_7cpython_4type_type) __PYX_ERR(2, 9, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(3, 8, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_7cpython_4bool_bool = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "bool", sizeof(PyBoolObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_7cpython_4bool_bool) __PYX_ERR(3, 8, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(4, 15, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_7cpython_7complex_complex = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "complex", sizeof(PyComplexObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_7cpython_7complex_complex) __PYX_ERR(4, 15, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = PyImport_ImportModule("numpy"); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 206, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_5numpy_dtype = __Pyx_ImportType(__pyx_t_1, "numpy", "dtype", sizeof(PyArray_Descr), __Pyx_ImportType_CheckSize_Ignore); if (!__pyx_ptype_5numpy_dtype) __PYX_ERR(1, 206, __pyx_L1_error) __pyx_ptype_5numpy_flatiter = __Pyx_ImportType(__pyx_t_1, "numpy", "flatiter", sizeof(PyArrayIterObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_5numpy_flatiter) __PYX_ERR(1, 229, __pyx_L1_error) __pyx_ptype_5numpy_broadcast = __Pyx_ImportType(__pyx_t_1, "numpy", "broadcast", sizeof(PyArrayMultiIterObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_5numpy_broadcast) __PYX_ERR(1, 233, __pyx_L1_error) __pyx_ptype_5numpy_ndarray = __Pyx_ImportType(__pyx_t_1, "numpy", "ndarray", sizeof(PyArrayObject), __Pyx_ImportType_CheckSize_Ignore); if (!__pyx_ptype_5numpy_ndarray) __PYX_ERR(1, 242, __pyx_L1_error) __pyx_ptype_5numpy_ufunc = __Pyx_ImportType(__pyx_t_1, "numpy", "ufunc", sizeof(PyUFuncObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_5numpy_ufunc) __PYX_ERR(1, 918, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_RefNannyFinishContext(); return -1; } static int __Pyx_modinit_variable_import_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); /*--- Variable import code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_function_import_code(void) { __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); /*--- Function import code ---*/ __pyx_t_1 = PyImport_ImportModule("photutils.geometry.core"); if (!__pyx_t_1) __PYX_ERR(0, 1, __pyx_L1_error) if (__Pyx_ImportFunction(__pyx_t_1, "distance", (void (**)(void))&__pyx_f_9photutils_8geometry_4core_distance, "double (double, double, double, double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) if (__Pyx_ImportFunction(__pyx_t_1, "area_triangle", (void (**)(void))&__pyx_f_9photutils_8geometry_4core_area_triangle, "double (double, double, double, double, double, double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) if (__Pyx_ImportFunction(__pyx_t_1, "overlap_area_triangle_unit_circle", (void (**)(void))&__pyx_f_9photutils_8geometry_4core_overlap_area_triangle_unit_circle, "double (double, double, double, double, double, double)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) Py_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_RefNannyFinishContext(); return -1; } #if PY_MAJOR_VERSION < 3 #ifdef CYTHON_NO_PYINIT_EXPORT #define __Pyx_PyMODINIT_FUNC void #else #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC #endif #else #ifdef CYTHON_NO_PYINIT_EXPORT #define __Pyx_PyMODINIT_FUNC PyObject * #else #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC #endif #endif #if PY_MAJOR_VERSION < 3 __Pyx_PyMODINIT_FUNC initelliptical_overlap(void) CYTHON_SMALL_CODE; /*proto*/ __Pyx_PyMODINIT_FUNC initelliptical_overlap(void) #else __Pyx_PyMODINIT_FUNC PyInit_elliptical_overlap(void) CYTHON_SMALL_CODE; /*proto*/ __Pyx_PyMODINIT_FUNC PyInit_elliptical_overlap(void) #if CYTHON_PEP489_MULTI_PHASE_INIT { return PyModuleDef_Init(&__pyx_moduledef); } static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { #if PY_VERSION_HEX >= 0x030700A1 static PY_INT64_T main_interpreter_id = -1; PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); if (main_interpreter_id == -1) { main_interpreter_id = current_id; return (unlikely(current_id == -1)) ? -1 : 0; } else if (unlikely(main_interpreter_id != current_id)) #else static PyInterpreterState *main_interpreter = NULL; PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; if (!main_interpreter) { main_interpreter = current_interpreter; } else if (unlikely(main_interpreter != current_interpreter)) #endif { PyErr_SetString( PyExc_ImportError, "Interpreter change detected - this module can only be loaded into one interpreter per process."); return -1; } return 0; } static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { PyObject *value = PyObject_GetAttrString(spec, from_name); int result = 0; if (likely(value)) { if (allow_none || value != Py_None) { result = PyDict_SetItemString(moddict, to_name, value); } Py_DECREF(value); } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Clear(); } else { result = -1; } return result; } static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { PyObject *module = NULL, *moddict, *modname; if (__Pyx_check_single_interpreter()) return NULL; if (__pyx_m) return __Pyx_NewRef(__pyx_m); modname = PyObject_GetAttrString(spec, "name"); if (unlikely(!modname)) goto bad; module = PyModule_NewObject(modname); Py_DECREF(modname); if (unlikely(!module)) goto bad; moddict = PyModule_GetDict(module); if (unlikely(!moddict)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; return module; bad: Py_XDECREF(module); return NULL; } static CYTHON_SMALL_CODE int __pyx_pymod_exec_elliptical_overlap(PyObject *__pyx_pyinit_module) #endif #endif { PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; __Pyx_RefNannyDeclarations #if CYTHON_PEP489_MULTI_PHASE_INIT if (__pyx_m) { if (__pyx_m == __pyx_pyinit_module) return 0; PyErr_SetString(PyExc_RuntimeError, "Module 'elliptical_overlap' has already been imported. Re-initialisation is not supported."); return -1; } #elif PY_MAJOR_VERSION >= 3 if (__pyx_m) return __Pyx_NewRef(__pyx_m); #endif #if CYTHON_REFNANNY __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); if (!__Pyx_RefNanny) { PyErr_Clear(); __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); if (!__Pyx_RefNanny) Py_FatalError("failed to import 'refnanny' module"); } #endif __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_elliptical_overlap(void)", 0); if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #ifdef __Pxy_PyFrame_Initialize_Offsets __Pxy_PyFrame_Initialize_Offsets(); #endif __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) #ifdef __Pyx_CyFunction_USED if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_FusedFunction_USED if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_Coroutine_USED if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_Generator_USED if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_AsyncGen_USED if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_StopAsyncIteration_USED if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif /*--- Library function declarations ---*/ /*--- Threads initialization code ---*/ #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS #ifdef WITH_THREAD /* Python build with threading support? */ PyEval_InitThreads(); #endif #endif /*--- Module creation code ---*/ #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_m = __pyx_pyinit_module; Py_INCREF(__pyx_m); #else #if PY_MAJOR_VERSION < 3 __pyx_m = Py_InitModule4("elliptical_overlap", __pyx_methods, __pyx_k_The_functions_defined_here_allo, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); #else __pyx_m = PyModule_Create(&__pyx_moduledef); #endif if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) #endif __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_d); __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_b); __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_cython_runtime); if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); /*--- Initialize various global constants etc. ---*/ if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif if (__pyx_module_is_main_photutils__geometry__elliptical_overlap) { if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) } #if PY_MAJOR_VERSION >= 3 { PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) if (!PyDict_GetItemString(modules, "photutils.geometry.elliptical_overlap")) { if (unlikely(PyDict_SetItemString(modules, "photutils.geometry.elliptical_overlap", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) } } #endif /*--- Builtin init code ---*/ if (__Pyx_InitCachedBuiltins() < 0) goto __pyx_L1_error; /*--- Constants init code ---*/ if (__Pyx_InitCachedConstants() < 0) goto __pyx_L1_error; /*--- Global type/function init code ---*/ (void)__Pyx_modinit_global_init_code(); (void)__Pyx_modinit_variable_export_code(); (void)__Pyx_modinit_function_export_code(); (void)__Pyx_modinit_type_init_code(); if (unlikely(__Pyx_modinit_type_import_code() != 0)) goto __pyx_L1_error; (void)__Pyx_modinit_variable_import_code(); if (unlikely(__Pyx_modinit_function_import_code() != 0)) goto __pyx_L1_error; /*--- Execution code ---*/ #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif /* "photutils/geometry/elliptical_overlap.pyx":11 * """ * * import numpy as np # <<<<<<<<<<<<<< * cimport numpy as np * */ __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 11, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "photutils/geometry/elliptical_overlap.pyx":14 * cimport numpy as np * * __all__ = ['elliptical_overlap_grid'] # <<<<<<<<<<<<<< * * */ __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 14, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_u_elliptical_overlap_grid); __Pyx_GIVEREF(__pyx_n_u_elliptical_overlap_grid); PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_u_elliptical_overlap_grid); if (PyDict_SetItem(__pyx_d, __pyx_n_s_all, __pyx_t_1) < 0) __PYX_ERR(0, 14, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "photutils/geometry/elliptical_overlap.pyx":26 * from cpython cimport bool * * DTYPE = np.float64 # <<<<<<<<<<<<<< * ctypedef np.float64_t DTYPE_t * */ __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 26, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_float64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 26, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; if (PyDict_SetItem(__pyx_d, __pyx_n_s_DTYPE, __pyx_t_2) < 0) __PYX_ERR(0, 26, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/elliptical_overlap.pyx":37 * * * def elliptical_overlap_grid(double xmin, double xmax, double ymin, double ymax, # <<<<<<<<<<<<<< * int nx, int ny, double rx, double ry, double theta, * int use_exact, int subpixels): */ __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_9photutils_8geometry_18elliptical_overlap_1elliptical_overlap_grid, NULL, __pyx_n_s_photutils_geometry_elliptical_ov_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 37, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (PyDict_SetItem(__pyx_d, __pyx_n_s_elliptical_overlap_grid, __pyx_t_2) < 0) __PYX_ERR(0, 37, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/elliptical_overlap.pyx":1 * # Licensed under a 3-clause BSD style license - see LICENSE.rst # <<<<<<<<<<<<<< * #cython: language_level=3 * """ */ __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1046 * raise ImportError("numpy.core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ /*--- Wrapped vars code ---*/ goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_2); if (__pyx_m) { if (__pyx_d) { __Pyx_AddTraceback("init photutils.geometry.elliptical_overlap", __pyx_clineno, __pyx_lineno, __pyx_filename); } Py_CLEAR(__pyx_m); } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ImportError, "init photutils.geometry.elliptical_overlap"); } __pyx_L0:; __Pyx_RefNannyFinishContext(); #if CYTHON_PEP489_MULTI_PHASE_INIT return (__pyx_m != NULL) ? 0 : -1; #elif PY_MAJOR_VERSION >= 3 return __pyx_m; #else return; #endif } /* --- Runtime support code --- */ /* Refnanny */ #if CYTHON_REFNANNY static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { PyObject *m = NULL, *p = NULL; void *r = NULL; m = PyImport_ImportModule(modname); if (!m) goto end; p = PyObject_GetAttrString(m, "RefNannyAPI"); if (!p) goto end; r = PyLong_AsVoidPtr(p); end: Py_XDECREF(p); Py_XDECREF(m); return (__Pyx_RefNannyAPIStruct *)r; } #endif /* PyObjectGetAttrStr */ #if CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { PyTypeObject* tp = Py_TYPE(obj); if (likely(tp->tp_getattro)) return tp->tp_getattro(obj, attr_name); #if PY_MAJOR_VERSION < 3 if (likely(tp->tp_getattr)) return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); #endif return PyObject_GetAttr(obj, attr_name); } #endif /* GetBuiltinName */ static PyObject *__Pyx_GetBuiltinName(PyObject *name) { PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); if (unlikely(!result)) { PyErr_Format(PyExc_NameError, #if PY_MAJOR_VERSION >= 3 "name '%U' is not defined", name); #else "name '%.200s' is not defined", PyString_AS_STRING(name)); #endif } return result; } /* RaiseArgTupleInvalid */ static void __Pyx_RaiseArgtupleInvalid( const char* func_name, int exact, Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found) { Py_ssize_t num_expected; const char *more_or_less; if (num_found < num_min) { num_expected = num_min; more_or_less = "at least"; } else { num_expected = num_max; more_or_less = "at most"; } if (exact) { more_or_less = "exactly"; } PyErr_Format(PyExc_TypeError, "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", func_name, more_or_less, num_expected, (num_expected == 1) ? "" : "s", num_found); } /* RaiseDoubleKeywords */ static void __Pyx_RaiseDoubleKeywordsError( const char* func_name, PyObject* kw_name) { PyErr_Format(PyExc_TypeError, #if PY_MAJOR_VERSION >= 3 "%s() got multiple values for keyword argument '%U'", func_name, kw_name); #else "%s() got multiple values for keyword argument '%s'", func_name, PyString_AsString(kw_name)); #endif } /* ParseKeywords */ static int __Pyx_ParseOptionalKeywords( PyObject *kwds, PyObject **argnames[], PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, const char* function_name) { PyObject *key = 0, *value = 0; Py_ssize_t pos = 0; PyObject*** name; PyObject*** first_kw_arg = argnames + num_pos_args; while (PyDict_Next(kwds, &pos, &key, &value)) { name = first_kw_arg; while (*name && (**name != key)) name++; if (*name) { values[name-argnames] = value; continue; } name = first_kw_arg; #if PY_MAJOR_VERSION < 3 if (likely(PyString_CheckExact(key)) || likely(PyString_Check(key))) { while (*name) { if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) && _PyString_Eq(**name, key)) { values[name-argnames] = value; break; } name++; } if (*name) continue; else { PyObject*** argname = argnames; while (argname != first_kw_arg) { if ((**argname == key) || ( (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) && _PyString_Eq(**argname, key))) { goto arg_passed_twice; } argname++; } } } else #endif if (likely(PyUnicode_Check(key))) { while (*name) { int cmp = (**name == key) ? 0 : #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 (PyUnicode_GET_SIZE(**name) != PyUnicode_GET_SIZE(key)) ? 1 : #endif PyUnicode_Compare(**name, key); if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; if (cmp == 0) { values[name-argnames] = value; break; } name++; } if (*name) continue; else { PyObject*** argname = argnames; while (argname != first_kw_arg) { int cmp = (**argname == key) ? 0 : #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 (PyUnicode_GET_SIZE(**argname) != PyUnicode_GET_SIZE(key)) ? 1 : #endif PyUnicode_Compare(**argname, key); if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; if (cmp == 0) goto arg_passed_twice; argname++; } } } else goto invalid_keyword_type; if (kwds2) { if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; } else { goto invalid_keyword; } } return 0; arg_passed_twice: __Pyx_RaiseDoubleKeywordsError(function_name, key); goto bad; invalid_keyword_type: PyErr_Format(PyExc_TypeError, "%.200s() keywords must be strings", function_name); goto bad; invalid_keyword: PyErr_Format(PyExc_TypeError, #if PY_MAJOR_VERSION < 3 "%.200s() got an unexpected keyword argument '%.200s'", function_name, PyString_AsString(key)); #else "%s() got an unexpected keyword argument '%U'", function_name, key); #endif bad: return -1; } /* PyDictVersioning */ #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { PyObject *dict = Py_TYPE(obj)->tp_dict; return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; } static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { PyObject **dictptr = NULL; Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; if (offset) { #if CYTHON_COMPILING_IN_CPYTHON dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); #else dictptr = _PyObject_GetDictPtr(obj); #endif } return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; } static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { PyObject *dict = Py_TYPE(obj)->tp_dict; if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) return 0; return obj_dict_version == __Pyx_get_object_dict_version(obj); } #endif /* GetModuleGlobalName */ #if CYTHON_USE_DICT_VERSIONS static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) #else static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) #endif { PyObject *result; #if !CYTHON_AVOID_BORROWED_REFS #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } else if (unlikely(PyErr_Occurred())) { return NULL; } #else result = PyDict_GetItem(__pyx_d, name); __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } #endif #else result = PyObject_GetItem(__pyx_d, name); __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } PyErr_Clear(); #endif return __Pyx_GetBuiltinName(name); } /* PyObjectCall */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; ternaryfunc call = func->ob_type->tp_call; if (unlikely(!call)) return PyObject_Call(func, arg, kw); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) return NULL; result = (*call)(func, arg, kw); Py_LeaveRecursiveCall(); if (unlikely(!result) && unlikely(!PyErr_Occurred())) { PyErr_SetString( PyExc_SystemError, "NULL result without error in PyObject_Call"); } return result; } #endif /* ExtTypeTest */ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { if (unlikely(!type)) { PyErr_SetString(PyExc_SystemError, "Missing type object"); return 0; } if (likely(__Pyx_TypeCheck(obj, type))) return 1; PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", Py_TYPE(obj)->tp_name, type->tp_name); return 0; } /* IsLittleEndian */ static CYTHON_INLINE int __Pyx_Is_Little_Endian(void) { union { uint32_t u32; uint8_t u8[4]; } S; S.u32 = 0x01020304; return S.u8[0] == 4; } /* BufferFormatCheck */ static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, __Pyx_BufFmt_StackElem* stack, __Pyx_TypeInfo* type) { stack[0].field = &ctx->root; stack[0].parent_offset = 0; ctx->root.type = type; ctx->root.name = "buffer dtype"; ctx->root.offset = 0; ctx->head = stack; ctx->head->field = &ctx->root; ctx->fmt_offset = 0; ctx->head->parent_offset = 0; ctx->new_packmode = '@'; ctx->enc_packmode = '@'; ctx->new_count = 1; ctx->enc_count = 0; ctx->enc_type = 0; ctx->is_complex = 0; ctx->is_valid_array = 0; ctx->struct_alignment = 0; while (type->typegroup == 'S') { ++ctx->head; ctx->head->field = type->fields; ctx->head->parent_offset = 0; type = type->fields->type; } } static int __Pyx_BufFmt_ParseNumber(const char** ts) { int count; const char* t = *ts; if (*t < '0' || *t > '9') { return -1; } else { count = *t++ - '0'; while (*t >= '0' && *t <= '9') { count *= 10; count += *t++ - '0'; } } *ts = t; return count; } static int __Pyx_BufFmt_ExpectNumber(const char **ts) { int number = __Pyx_BufFmt_ParseNumber(ts); if (number == -1) PyErr_Format(PyExc_ValueError,\ "Does not understand character buffer dtype format string ('%c')", **ts); return number; } static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) { PyErr_Format(PyExc_ValueError, "Unexpected format string character: '%c'", ch); } static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) { switch (ch) { case '?': return "'bool'"; case 'c': return "'char'"; case 'b': return "'signed char'"; case 'B': return "'unsigned char'"; case 'h': return "'short'"; case 'H': return "'unsigned short'"; case 'i': return "'int'"; case 'I': return "'unsigned int'"; case 'l': return "'long'"; case 'L': return "'unsigned long'"; case 'q': return "'long long'"; case 'Q': return "'unsigned long long'"; case 'f': return (is_complex ? "'complex float'" : "'float'"); case 'd': return (is_complex ? "'complex double'" : "'double'"); case 'g': return (is_complex ? "'complex long double'" : "'long double'"); case 'T': return "a struct"; case 'O': return "Python object"; case 'P': return "a pointer"; case 's': case 'p': return "a string"; case 0: return "end"; default: return "unparseable format string"; } } static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return 2; case 'i': case 'I': case 'l': case 'L': return 4; case 'q': case 'Q': return 8; case 'f': return (is_complex ? 8 : 4); case 'd': return (is_complex ? 16 : 8); case 'g': { PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g').."); return 0; } case 'O': case 'P': return sizeof(void*); default: __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return sizeof(short); case 'i': case 'I': return sizeof(int); case 'l': case 'L': return sizeof(long); #ifdef HAVE_LONG_LONG case 'q': case 'Q': return sizeof(PY_LONG_LONG); #endif case 'f': return sizeof(float) * (is_complex ? 2 : 1); case 'd': return sizeof(double) * (is_complex ? 2 : 1); case 'g': return sizeof(long double) * (is_complex ? 2 : 1); case 'O': case 'P': return sizeof(void*); default: { __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } } typedef struct { char c; short x; } __Pyx_st_short; typedef struct { char c; int x; } __Pyx_st_int; typedef struct { char c; long x; } __Pyx_st_long; typedef struct { char c; float x; } __Pyx_st_float; typedef struct { char c; double x; } __Pyx_st_double; typedef struct { char c; long double x; } __Pyx_st_longdouble; typedef struct { char c; void *x; } __Pyx_st_void_p; #ifdef HAVE_LONG_LONG typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong; #endif static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, CYTHON_UNUSED int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short); case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int); case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long); #ifdef HAVE_LONG_LONG case 'q': case 'Q': return sizeof(__Pyx_st_longlong) - sizeof(PY_LONG_LONG); #endif case 'f': return sizeof(__Pyx_st_float) - sizeof(float); case 'd': return sizeof(__Pyx_st_double) - sizeof(double); case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double); case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*); default: __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } /* These are for computing the padding at the end of the struct to align on the first member of the struct. This will probably the same as above, but we don't have any guarantees. */ typedef struct { short x; char c; } __Pyx_pad_short; typedef struct { int x; char c; } __Pyx_pad_int; typedef struct { long x; char c; } __Pyx_pad_long; typedef struct { float x; char c; } __Pyx_pad_float; typedef struct { double x; char c; } __Pyx_pad_double; typedef struct { long double x; char c; } __Pyx_pad_longdouble; typedef struct { void *x; char c; } __Pyx_pad_void_p; #ifdef HAVE_LONG_LONG typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong; #endif static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, CYTHON_UNUSED int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short); case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int); case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long); #ifdef HAVE_LONG_LONG case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG); #endif case 'f': return sizeof(__Pyx_pad_float) - sizeof(float); case 'd': return sizeof(__Pyx_pad_double) - sizeof(double); case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double); case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*); default: __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { switch (ch) { case 'c': return 'H'; case 'b': case 'h': case 'i': case 'l': case 'q': case 's': case 'p': return 'I'; case '?': case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U'; case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R'); case 'O': return 'O'; case 'P': return 'P'; default: { __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } } static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) { if (ctx->head == NULL || ctx->head->field == &ctx->root) { const char* expected; const char* quote; if (ctx->head == NULL) { expected = "end"; quote = ""; } else { expected = ctx->head->field->type->name; quote = "'"; } PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch, expected %s%s%s but got %s", quote, expected, quote, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex)); } else { __Pyx_StructField* field = ctx->head->field; __Pyx_StructField* parent = (ctx->head - 1)->field; PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'", field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex), parent->type->name, field->name); } } static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) { char group; size_t size, offset, arraysize = 1; if (ctx->enc_type == 0) return 0; if (ctx->head->field->type->arraysize[0]) { int i, ndim = 0; if (ctx->enc_type == 's' || ctx->enc_type == 'p') { ctx->is_valid_array = ctx->head->field->type->ndim == 1; ndim = 1; if (ctx->enc_count != ctx->head->field->type->arraysize[0]) { PyErr_Format(PyExc_ValueError, "Expected a dimension of size %zu, got %zu", ctx->head->field->type->arraysize[0], ctx->enc_count); return -1; } } if (!ctx->is_valid_array) { PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d", ctx->head->field->type->ndim, ndim); return -1; } for (i = 0; i < ctx->head->field->type->ndim; i++) { arraysize *= ctx->head->field->type->arraysize[i]; } ctx->is_valid_array = 0; ctx->enc_count = 1; } group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex); do { __Pyx_StructField* field = ctx->head->field; __Pyx_TypeInfo* type = field->type; if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') { size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex); } else { size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex); } if (ctx->enc_packmode == '@') { size_t align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex); size_t align_mod_offset; if (align_at == 0) return -1; align_mod_offset = ctx->fmt_offset % align_at; if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset; if (ctx->struct_alignment == 0) ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type, ctx->is_complex); } if (type->size != size || type->typegroup != group) { if (type->typegroup == 'C' && type->fields != NULL) { size_t parent_offset = ctx->head->parent_offset + field->offset; ++ctx->head; ctx->head->field = type->fields; ctx->head->parent_offset = parent_offset; continue; } if ((type->typegroup == 'H' || group == 'H') && type->size == size) { } else { __Pyx_BufFmt_RaiseExpected(ctx); return -1; } } offset = ctx->head->parent_offset + field->offset; if (ctx->fmt_offset != offset) { PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch; next field is at offset %" CYTHON_FORMAT_SSIZE_T "d but %" CYTHON_FORMAT_SSIZE_T "d expected", (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset); return -1; } ctx->fmt_offset += size; if (arraysize) ctx->fmt_offset += (arraysize - 1) * size; --ctx->enc_count; while (1) { if (field == &ctx->root) { ctx->head = NULL; if (ctx->enc_count != 0) { __Pyx_BufFmt_RaiseExpected(ctx); return -1; } break; } ctx->head->field = ++field; if (field->type == NULL) { --ctx->head; field = ctx->head->field; continue; } else if (field->type->typegroup == 'S') { size_t parent_offset = ctx->head->parent_offset + field->offset; if (field->type->fields->type == NULL) continue; field = field->type->fields; ++ctx->head; ctx->head->field = field; ctx->head->parent_offset = parent_offset; break; } else { break; } } } while (ctx->enc_count); ctx->enc_type = 0; ctx->is_complex = 0; return 0; } static PyObject * __pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp) { const char *ts = *tsp; int i = 0, number; int ndim = ctx->head->field->type->ndim; ; ++ts; if (ctx->new_count != 1) { PyErr_SetString(PyExc_ValueError, "Cannot handle repeated arrays in format string"); return NULL; } if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; while (*ts && *ts != ')') { switch (*ts) { case ' ': case '\f': case '\r': case '\n': case '\t': case '\v': continue; default: break; } number = __Pyx_BufFmt_ExpectNumber(&ts); if (number == -1) return NULL; if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i]) return PyErr_Format(PyExc_ValueError, "Expected a dimension of size %zu, got %d", ctx->head->field->type->arraysize[i], number); if (*ts != ',' && *ts != ')') return PyErr_Format(PyExc_ValueError, "Expected a comma in format string, got '%c'", *ts); if (*ts == ',') ts++; i++; } if (i != ndim) return PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d", ctx->head->field->type->ndim, i); if (!*ts) { PyErr_SetString(PyExc_ValueError, "Unexpected end of format string, expected ')'"); return NULL; } ctx->is_valid_array = 1; ctx->new_count = 1; *tsp = ++ts; return Py_None; } static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) { int got_Z = 0; while (1) { switch(*ts) { case 0: if (ctx->enc_type != 0 && ctx->head == NULL) { __Pyx_BufFmt_RaiseExpected(ctx); return NULL; } if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; if (ctx->head != NULL) { __Pyx_BufFmt_RaiseExpected(ctx); return NULL; } return ts; case ' ': case '\r': case '\n': ++ts; break; case '<': if (!__Pyx_Is_Little_Endian()) { PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler"); return NULL; } ctx->new_packmode = '='; ++ts; break; case '>': case '!': if (__Pyx_Is_Little_Endian()) { PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler"); return NULL; } ctx->new_packmode = '='; ++ts; break; case '=': case '@': case '^': ctx->new_packmode = *ts++; break; case 'T': { const char* ts_after_sub; size_t i, struct_count = ctx->new_count; size_t struct_alignment = ctx->struct_alignment; ctx->new_count = 1; ++ts; if (*ts != '{') { PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'"); return NULL; } if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->enc_type = 0; ctx->enc_count = 0; ctx->struct_alignment = 0; ++ts; ts_after_sub = ts; for (i = 0; i != struct_count; ++i) { ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts); if (!ts_after_sub) return NULL; } ts = ts_after_sub; if (struct_alignment) ctx->struct_alignment = struct_alignment; } break; case '}': { size_t alignment = ctx->struct_alignment; ++ts; if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->enc_type = 0; if (alignment && ctx->fmt_offset % alignment) { ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment); } } return ts; case 'x': if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->fmt_offset += ctx->new_count; ctx->new_count = 1; ctx->enc_count = 0; ctx->enc_type = 0; ctx->enc_packmode = ctx->new_packmode; ++ts; break; case 'Z': got_Z = 1; ++ts; if (*ts != 'f' && *ts != 'd' && *ts != 'g') { __Pyx_BufFmt_RaiseUnexpectedChar('Z'); return NULL; } CYTHON_FALLTHROUGH; case '?': case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I': case 'l': case 'L': case 'q': case 'Q': case 'f': case 'd': case 'g': case 'O': case 'p': if (ctx->enc_type == *ts && got_Z == ctx->is_complex && ctx->enc_packmode == ctx->new_packmode) { ctx->enc_count += ctx->new_count; ctx->new_count = 1; got_Z = 0; ++ts; break; } CYTHON_FALLTHROUGH; case 's': if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->enc_count = ctx->new_count; ctx->enc_packmode = ctx->new_packmode; ctx->enc_type = *ts; ctx->is_complex = got_Z; ++ts; ctx->new_count = 1; got_Z = 0; break; case ':': ++ts; while(*ts != ':') ++ts; ++ts; break; case '(': if (!__pyx_buffmt_parse_array(ctx, &ts)) return NULL; break; default: { int number = __Pyx_BufFmt_ExpectNumber(&ts); if (number == -1) return NULL; ctx->new_count = (size_t)number; } } } } /* BufferGetAndValidate */ static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) { if (unlikely(info->buf == NULL)) return; if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL; __Pyx_ReleaseBuffer(info); } static void __Pyx_ZeroBuffer(Py_buffer* buf) { buf->buf = NULL; buf->obj = NULL; buf->strides = __Pyx_zeros; buf->shape = __Pyx_zeros; buf->suboffsets = __Pyx_minusones; } static int __Pyx__GetBufferAndValidate( Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) { buf->buf = NULL; if (unlikely(__Pyx_GetBuffer(obj, buf, flags) == -1)) { __Pyx_ZeroBuffer(buf); return -1; } if (unlikely(buf->ndim != nd)) { PyErr_Format(PyExc_ValueError, "Buffer has wrong number of dimensions (expected %d, got %d)", nd, buf->ndim); goto fail; } if (!cast) { __Pyx_BufFmt_Context ctx; __Pyx_BufFmt_Init(&ctx, stack, dtype); if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail; } if (unlikely((size_t)buf->itemsize != dtype->size)) { PyErr_Format(PyExc_ValueError, "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "d byte%s) does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "d byte%s)", buf->itemsize, (buf->itemsize > 1) ? "s" : "", dtype->name, (Py_ssize_t)dtype->size, (dtype->size > 1) ? "s" : ""); goto fail; } if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones; return 0; fail:; __Pyx_SafeReleaseBuffer(buf); return -1; } /* BufferIndexError */ static void __Pyx_RaiseBufferIndexError(int axis) { PyErr_Format(PyExc_IndexError, "Out of bounds on buffer access (axis %d)", axis); } /* PyErrFetchRestore */ #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { PyObject *tmp_type, *tmp_value, *tmp_tb; tmp_type = tstate->curexc_type; tmp_value = tstate->curexc_value; tmp_tb = tstate->curexc_traceback; tstate->curexc_type = type; tstate->curexc_value = value; tstate->curexc_traceback = tb; Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); } static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { *type = tstate->curexc_type; *value = tstate->curexc_value; *tb = tstate->curexc_traceback; tstate->curexc_type = 0; tstate->curexc_value = 0; tstate->curexc_traceback = 0; } #endif /* WriteUnraisableException */ static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno, CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename, int full_traceback, CYTHON_UNUSED int nogil) { PyObject *old_exc, *old_val, *old_tb; PyObject *ctx; __Pyx_PyThreadState_declare #ifdef WITH_THREAD PyGILState_STATE state; if (nogil) state = PyGILState_Ensure(); #ifdef _MSC_VER else state = (PyGILState_STATE)-1; #endif #endif __Pyx_PyThreadState_assign __Pyx_ErrFetch(&old_exc, &old_val, &old_tb); if (full_traceback) { Py_XINCREF(old_exc); Py_XINCREF(old_val); Py_XINCREF(old_tb); __Pyx_ErrRestore(old_exc, old_val, old_tb); PyErr_PrintEx(1); } #if PY_MAJOR_VERSION < 3 ctx = PyString_FromString(name); #else ctx = PyUnicode_FromString(name); #endif __Pyx_ErrRestore(old_exc, old_val, old_tb); if (!ctx) { PyErr_WriteUnraisable(Py_None); } else { PyErr_WriteUnraisable(ctx); Py_DECREF(ctx); } #ifdef WITH_THREAD if (nogil) PyGILState_Release(state); #endif } /* RaiseException */ #if PY_MAJOR_VERSION < 3 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, CYTHON_UNUSED PyObject *cause) { __Pyx_PyThreadState_declare Py_XINCREF(type); if (!value || value == Py_None) value = NULL; else Py_INCREF(value); if (!tb || tb == Py_None) tb = NULL; else { Py_INCREF(tb); if (!PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto raise_error; } } if (PyType_Check(type)) { #if CYTHON_COMPILING_IN_PYPY if (!value) { Py_INCREF(Py_None); value = Py_None; } #endif PyErr_NormalizeException(&type, &value, &tb); } else { if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto raise_error; } value = type; type = (PyObject*) Py_TYPE(type); Py_INCREF(type); if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto raise_error; } } __Pyx_PyThreadState_assign __Pyx_ErrRestore(type, value, tb); return; raise_error: Py_XDECREF(value); Py_XDECREF(type); Py_XDECREF(tb); return; } #else static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { PyObject* owned_instance = NULL; if (tb == Py_None) { tb = 0; } else if (tb && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto bad; } if (value == Py_None) value = 0; if (PyExceptionInstance_Check(type)) { if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto bad; } value = type; type = (PyObject*) Py_TYPE(value); } else if (PyExceptionClass_Check(type)) { PyObject *instance_class = NULL; if (value && PyExceptionInstance_Check(value)) { instance_class = (PyObject*) Py_TYPE(value); if (instance_class != type) { int is_subclass = PyObject_IsSubclass(instance_class, type); if (!is_subclass) { instance_class = NULL; } else if (unlikely(is_subclass == -1)) { goto bad; } else { type = instance_class; } } } if (!instance_class) { PyObject *args; if (!value) args = PyTuple_New(0); else if (PyTuple_Check(value)) { Py_INCREF(value); args = value; } else args = PyTuple_Pack(1, value); if (!args) goto bad; owned_instance = PyObject_Call(type, args, NULL); Py_DECREF(args); if (!owned_instance) goto bad; value = owned_instance; if (!PyExceptionInstance_Check(value)) { PyErr_Format(PyExc_TypeError, "calling %R should have returned an instance of " "BaseException, not %R", type, Py_TYPE(value)); goto bad; } } } else { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto bad; } if (cause) { PyObject *fixed_cause; if (cause == Py_None) { fixed_cause = NULL; } else if (PyExceptionClass_Check(cause)) { fixed_cause = PyObject_CallObject(cause, NULL); if (fixed_cause == NULL) goto bad; } else if (PyExceptionInstance_Check(cause)) { fixed_cause = cause; Py_INCREF(fixed_cause); } else { PyErr_SetString(PyExc_TypeError, "exception causes must derive from " "BaseException"); goto bad; } PyException_SetCause(value, fixed_cause); } PyErr_SetObject(type, value); if (tb) { #if CYTHON_COMPILING_IN_PYPY PyObject *tmp_type, *tmp_value, *tmp_tb; PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); Py_INCREF(tb); PyErr_Restore(tmp_type, tmp_value, tb); Py_XDECREF(tmp_tb); #else PyThreadState *tstate = __Pyx_PyThreadState_Current; PyObject* tmp_tb = tstate->curexc_traceback; if (tb != tmp_tb) { Py_INCREF(tb); tstate->curexc_traceback = tb; Py_XDECREF(tmp_tb); } #endif } bad: Py_XDECREF(owned_instance); return; } #endif /* PyCFunctionFastCall */ #if CYTHON_FAST_PYCCALL static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { PyCFunctionObject *func = (PyCFunctionObject*)func_obj; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); int flags = PyCFunction_GET_FLAGS(func); assert(PyCFunction_Check(func)); assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); assert(nargs >= 0); assert(nargs == 0 || args != NULL); /* _PyCFunction_FastCallDict() must not be called with an exception set, because it may clear it (directly or indirectly) and so the caller loses its exception */ assert(!PyErr_Occurred()); if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); } else { return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); } } #endif /* PyFunctionFastCall */ #if CYTHON_FAST_PYCALL static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, PyObject *globals) { PyFrameObject *f; PyThreadState *tstate = __Pyx_PyThreadState_Current; PyObject **fastlocals; Py_ssize_t i; PyObject *result; assert(globals != NULL); /* XXX Perhaps we should create a specialized PyFrame_New() that doesn't take locals, but does take builtins without sanity checking them. */ assert(tstate != NULL); f = PyFrame_New(tstate, co, globals, NULL); if (f == NULL) { return NULL; } fastlocals = __Pyx_PyFrame_GetLocalsplus(f); for (i = 0; i < na; i++) { Py_INCREF(*args); fastlocals[i] = *args++; } result = PyEval_EvalFrameEx(f,0); ++tstate->recursion_depth; Py_DECREF(f); --tstate->recursion_depth; return result; } #if 1 || PY_VERSION_HEX < 0x030600B1 static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func); PyObject *closure; #if PY_MAJOR_VERSION >= 3 PyObject *kwdefs; #endif PyObject *kwtuple, **k; PyObject **d; Py_ssize_t nd; Py_ssize_t nk; PyObject *result; assert(kwargs == NULL || PyDict_Check(kwargs)); nk = kwargs ? PyDict_Size(kwargs) : 0; if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { return NULL; } if ( #if PY_MAJOR_VERSION >= 3 co->co_kwonlyargcount == 0 && #endif likely(kwargs == NULL || nk == 0) && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { if (argdefs == NULL && co->co_argcount == nargs) { result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); goto done; } else if (nargs == 0 && argdefs != NULL && co->co_argcount == Py_SIZE(argdefs)) { /* function called with no arguments, but all parameters have a default value: use default values as arguments .*/ args = &PyTuple_GET_ITEM(argdefs, 0); result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); goto done; } } if (kwargs != NULL) { Py_ssize_t pos, i; kwtuple = PyTuple_New(2 * nk); if (kwtuple == NULL) { result = NULL; goto done; } k = &PyTuple_GET_ITEM(kwtuple, 0); pos = i = 0; while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { Py_INCREF(k[i]); Py_INCREF(k[i+1]); i += 2; } nk = i / 2; } else { kwtuple = NULL; k = NULL; } closure = PyFunction_GET_CLOSURE(func); #if PY_MAJOR_VERSION >= 3 kwdefs = PyFunction_GET_KW_DEFAULTS(func); #endif if (argdefs != NULL) { d = &PyTuple_GET_ITEM(argdefs, 0); nd = Py_SIZE(argdefs); } else { d = NULL; nd = 0; } #if PY_MAJOR_VERSION >= 3 result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, args, (int)nargs, k, (int)nk, d, (int)nd, kwdefs, closure); #else result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, args, (int)nargs, k, (int)nk, d, (int)nd, closure); #endif Py_XDECREF(kwtuple); done: Py_LeaveRecursiveCall(); return result; } #endif #endif /* PyObjectCallMethO */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { PyObject *self, *result; PyCFunction cfunc; cfunc = PyCFunction_GET_FUNCTION(func); self = PyCFunction_GET_SELF(func); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) return NULL; result = cfunc(self, arg); Py_LeaveRecursiveCall(); if (unlikely(!result) && unlikely(!PyErr_Occurred())) { PyErr_SetString( PyExc_SystemError, "NULL result without error in PyObject_Call"); } return result; } #endif /* PyObjectCallOneArg */ #if CYTHON_COMPILING_IN_CPYTHON static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { PyObject *result; PyObject *args = PyTuple_New(1); if (unlikely(!args)) return NULL; Py_INCREF(arg); PyTuple_SET_ITEM(args, 0, arg); result = __Pyx_PyObject_Call(func, args, NULL); Py_DECREF(args); return result; } static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { #if CYTHON_FAST_PYCALL if (PyFunction_Check(func)) { return __Pyx_PyFunction_FastCall(func, &arg, 1); } #endif if (likely(PyCFunction_Check(func))) { if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { return __Pyx_PyObject_CallMethO(func, arg); #if CYTHON_FAST_PYCCALL } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { return __Pyx_PyCFunction_FastCall(func, &arg, 1); #endif } } return __Pyx__PyObject_CallOneArg(func, arg); } #else static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { PyObject *result; PyObject *args = PyTuple_Pack(1, arg); if (unlikely(!args)) return NULL; result = __Pyx_PyObject_Call(func, args, NULL); Py_DECREF(args); return result; } #endif /* DictGetItem */ #if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) { PyObject *value; value = PyDict_GetItemWithError(d, key); if (unlikely(!value)) { if (!PyErr_Occurred()) { if (unlikely(PyTuple_Check(key))) { PyObject* args = PyTuple_Pack(1, key); if (likely(args)) { PyErr_SetObject(PyExc_KeyError, args); Py_DECREF(args); } } else { PyErr_SetObject(PyExc_KeyError, key); } } return NULL; } Py_INCREF(value); return value; } #endif /* RaiseTooManyValuesToUnpack */ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { PyErr_Format(PyExc_ValueError, "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); } /* RaiseNeedMoreValuesToUnpack */ static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { PyErr_Format(PyExc_ValueError, "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", index, (index == 1) ? "" : "s"); } /* RaiseNoneIterError */ static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); } /* GetTopmostException */ #if CYTHON_USE_EXC_INFO_STACK static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate) { _PyErr_StackItem *exc_info = tstate->exc_info; while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && exc_info->previous_item != NULL) { exc_info = exc_info->previous_item; } return exc_info; } #endif /* SaveResetException */ #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { #if CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); *type = exc_info->exc_type; *value = exc_info->exc_value; *tb = exc_info->exc_traceback; #else *type = tstate->exc_type; *value = tstate->exc_value; *tb = tstate->exc_traceback; #endif Py_XINCREF(*type); Py_XINCREF(*value); Py_XINCREF(*tb); } static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { PyObject *tmp_type, *tmp_value, *tmp_tb; #if CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = tstate->exc_info; tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; tmp_tb = exc_info->exc_traceback; exc_info->exc_type = type; exc_info->exc_value = value; exc_info->exc_traceback = tb; #else tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; tstate->exc_type = type; tstate->exc_value = value; tstate->exc_traceback = tb; #endif Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); } #endif /* PyErrExceptionMatches */ #if CYTHON_FAST_THREAD_STATE static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { Py_ssize_t i, n; n = PyTuple_GET_SIZE(tuple); #if PY_MAJOR_VERSION >= 3 for (i=0; icurexc_type; if (exc_type == err) return 1; if (unlikely(!exc_type)) return 0; if (unlikely(PyTuple_Check(err))) return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); } #endif /* GetException */ #if CYTHON_FAST_THREAD_STATE static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) #else static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) #endif { PyObject *local_type, *local_value, *local_tb; #if CYTHON_FAST_THREAD_STATE PyObject *tmp_type, *tmp_value, *tmp_tb; local_type = tstate->curexc_type; local_value = tstate->curexc_value; local_tb = tstate->curexc_traceback; tstate->curexc_type = 0; tstate->curexc_value = 0; tstate->curexc_traceback = 0; #else PyErr_Fetch(&local_type, &local_value, &local_tb); #endif PyErr_NormalizeException(&local_type, &local_value, &local_tb); #if CYTHON_FAST_THREAD_STATE if (unlikely(tstate->curexc_type)) #else if (unlikely(PyErr_Occurred())) #endif goto bad; #if PY_MAJOR_VERSION >= 3 if (local_tb) { if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) goto bad; } #endif Py_XINCREF(local_tb); Py_XINCREF(local_type); Py_XINCREF(local_value); *type = local_type; *value = local_value; *tb = local_tb; #if CYTHON_FAST_THREAD_STATE #if CYTHON_USE_EXC_INFO_STACK { _PyErr_StackItem *exc_info = tstate->exc_info; tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; tmp_tb = exc_info->exc_traceback; exc_info->exc_type = local_type; exc_info->exc_value = local_value; exc_info->exc_traceback = local_tb; } #else tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; tstate->exc_type = local_type; tstate->exc_value = local_value; tstate->exc_traceback = local_tb; #endif Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); #else PyErr_SetExcInfo(local_type, local_value, local_tb); #endif return 0; bad: *type = 0; *value = 0; *tb = 0; Py_XDECREF(local_type); Py_XDECREF(local_value); Py_XDECREF(local_tb); return -1; } /* TypeImport */ #ifndef __PYX_HAVE_RT_ImportType #define __PYX_HAVE_RT_ImportType static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size) { PyObject *result = 0; char warning[200]; Py_ssize_t basicsize; #ifdef Py_LIMITED_API PyObject *py_basicsize; #endif result = PyObject_GetAttrString(module, class_name); if (!result) goto bad; if (!PyType_Check(result)) { PyErr_Format(PyExc_TypeError, "%.200s.%.200s is not a type object", module_name, class_name); goto bad; } #ifndef Py_LIMITED_API basicsize = ((PyTypeObject *)result)->tp_basicsize; #else py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); if (!py_basicsize) goto bad; basicsize = PyLong_AsSsize_t(py_basicsize); Py_DECREF(py_basicsize); py_basicsize = 0; if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) goto bad; #endif if ((size_t)basicsize < size) { PyErr_Format(PyExc_ValueError, "%.200s.%.200s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); goto bad; } if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { PyErr_Format(PyExc_ValueError, "%.200s.%.200s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); goto bad; } else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { PyOS_snprintf(warning, sizeof(warning), "%s.%s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; } return (PyTypeObject *)result; bad: Py_XDECREF(result); return NULL; } #endif /* Import */ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { PyObject *empty_list = 0; PyObject *module = 0; PyObject *global_dict = 0; PyObject *empty_dict = 0; PyObject *list; #if PY_MAJOR_VERSION < 3 PyObject *py_import; py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); if (!py_import) goto bad; #endif if (from_list) list = from_list; else { empty_list = PyList_New(0); if (!empty_list) goto bad; list = empty_list; } global_dict = PyModule_GetDict(__pyx_m); if (!global_dict) goto bad; empty_dict = PyDict_New(); if (!empty_dict) goto bad; { #if PY_MAJOR_VERSION >= 3 if (level == -1) { if (strchr(__Pyx_MODULE_NAME, '.')) { module = PyImport_ImportModuleLevelObject( name, global_dict, empty_dict, list, 1); if (!module) { if (!PyErr_ExceptionMatches(PyExc_ImportError)) goto bad; PyErr_Clear(); } } level = 0; } #endif if (!module) { #if PY_MAJOR_VERSION < 3 PyObject *py_level = PyInt_FromLong(level); if (!py_level) goto bad; module = PyObject_CallFunctionObjArgs(py_import, name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); Py_DECREF(py_level); #else module = PyImport_ImportModuleLevelObject( name, global_dict, empty_dict, list, level); #endif } } bad: #if PY_MAJOR_VERSION < 3 Py_XDECREF(py_import); #endif Py_XDECREF(empty_list); Py_XDECREF(empty_dict); return module; } /* CLineInTraceback */ #ifndef CYTHON_CLINE_IN_TRACEBACK static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { PyObject *use_cline; PyObject *ptype, *pvalue, *ptraceback; #if CYTHON_COMPILING_IN_CPYTHON PyObject **cython_runtime_dict; #endif if (unlikely(!__pyx_cython_runtime)) { return c_line; } __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); #if CYTHON_COMPILING_IN_CPYTHON cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); if (likely(cython_runtime_dict)) { __PYX_PY_DICT_LOOKUP_IF_MODIFIED( use_cline, *cython_runtime_dict, __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) } else #endif { PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); if (use_cline_obj) { use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; Py_DECREF(use_cline_obj); } else { PyErr_Clear(); use_cline = NULL; } } if (!use_cline) { c_line = 0; PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); } else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { c_line = 0; } __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); return c_line; } #endif /* CodeObjectCache */ static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { int start = 0, mid = 0, end = count - 1; if (end >= 0 && code_line > entries[end].code_line) { return count; } while (start < end) { mid = start + (end - start) / 2; if (code_line < entries[mid].code_line) { end = mid; } else if (code_line > entries[mid].code_line) { start = mid + 1; } else { return mid; } } if (code_line <= entries[mid].code_line) { return mid; } else { return mid + 1; } } static PyCodeObject *__pyx_find_code_object(int code_line) { PyCodeObject* code_object; int pos; if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { return NULL; } pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { return NULL; } code_object = __pyx_code_cache.entries[pos].code_object; Py_INCREF(code_object); return code_object; } static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { int pos, i; __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; if (unlikely(!code_line)) { return; } if (unlikely(!entries)) { entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); if (likely(entries)) { __pyx_code_cache.entries = entries; __pyx_code_cache.max_count = 64; __pyx_code_cache.count = 1; entries[0].code_line = code_line; entries[0].code_object = code_object; Py_INCREF(code_object); } return; } pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { PyCodeObject* tmp = entries[pos].code_object; entries[pos].code_object = code_object; Py_DECREF(tmp); return; } if (__pyx_code_cache.count == __pyx_code_cache.max_count) { int new_max = __pyx_code_cache.max_count + 64; entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( __pyx_code_cache.entries, (size_t)new_max*sizeof(__Pyx_CodeObjectCacheEntry)); if (unlikely(!entries)) { return; } __pyx_code_cache.entries = entries; __pyx_code_cache.max_count = new_max; } for (i=__pyx_code_cache.count; i>pos; i--) { entries[i] = entries[i-1]; } entries[pos].code_line = code_line; entries[pos].code_object = code_object; __pyx_code_cache.count++; Py_INCREF(code_object); } /* AddTraceback */ #include "compile.h" #include "frameobject.h" #include "traceback.h" static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( const char *funcname, int c_line, int py_line, const char *filename) { PyCodeObject *py_code = 0; PyObject *py_srcfile = 0; PyObject *py_funcname = 0; #if PY_MAJOR_VERSION < 3 py_srcfile = PyString_FromString(filename); #else py_srcfile = PyUnicode_FromString(filename); #endif if (!py_srcfile) goto bad; if (c_line) { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); #else py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); #endif } else { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromString(funcname); #else py_funcname = PyUnicode_FromString(funcname); #endif } if (!py_funcname) goto bad; py_code = __Pyx_PyCode_New( 0, 0, 0, 0, 0, __pyx_empty_bytes, /*PyObject *code,*/ __pyx_empty_tuple, /*PyObject *consts,*/ __pyx_empty_tuple, /*PyObject *names,*/ __pyx_empty_tuple, /*PyObject *varnames,*/ __pyx_empty_tuple, /*PyObject *freevars,*/ __pyx_empty_tuple, /*PyObject *cellvars,*/ py_srcfile, /*PyObject *filename,*/ py_funcname, /*PyObject *name,*/ py_line, __pyx_empty_bytes /*PyObject *lnotab*/ ); Py_DECREF(py_srcfile); Py_DECREF(py_funcname); return py_code; bad: Py_XDECREF(py_srcfile); Py_XDECREF(py_funcname); return NULL; } static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename) { PyCodeObject *py_code = 0; PyFrameObject *py_frame = 0; PyThreadState *tstate = __Pyx_PyThreadState_Current; if (c_line) { c_line = __Pyx_CLineForTraceback(tstate, c_line); } py_code = __pyx_find_code_object(c_line ? -c_line : py_line); if (!py_code) { py_code = __Pyx_CreateCodeObjectForTraceback( funcname, c_line, py_line, filename); if (!py_code) goto bad; __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); } py_frame = PyFrame_New( tstate, /*PyThreadState *tstate,*/ py_code, /*PyCodeObject *code,*/ __pyx_d, /*PyObject *globals,*/ 0 /*PyObject *locals*/ ); if (!py_frame) goto bad; __Pyx_PyFrame_SetLineNumber(py_frame, py_line); PyTraceBack_Here(py_frame); bad: Py_XDECREF(py_code); Py_XDECREF(py_frame); } #if PY_MAJOR_VERSION < 3 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags); if (__Pyx_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pw_5numpy_7ndarray_1__getbuffer__(obj, view, flags); PyErr_Format(PyExc_TypeError, "'%.200s' does not have the buffer interface", Py_TYPE(obj)->tp_name); return -1; } static void __Pyx_ReleaseBuffer(Py_buffer *view) { PyObject *obj = view->obj; if (!obj) return; if (PyObject_CheckBuffer(obj)) { PyBuffer_Release(view); return; } if ((0)) {} else if (__Pyx_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) __pyx_pw_5numpy_7ndarray_3__releasebuffer__(obj, view); view->obj = NULL; Py_DECREF(obj); } #endif /* CIntFromPyVerify */ #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) #define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) #define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ {\ func_type value = func_value;\ if (sizeof(target_type) < sizeof(func_type)) {\ if (unlikely(value != (func_type) (target_type) value)) {\ func_type zero = 0;\ if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ return (target_type) -1;\ if (is_unsigned && unlikely(value < zero))\ goto raise_neg_overflow;\ else\ goto raise_overflow;\ }\ }\ return (target_type) value;\ } /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(int) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(int) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof(int) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; return _PyLong_FromByteArray(bytes, sizeof(int), little, !is_unsigned); } } /* Declarations */ #if CYTHON_CCOMPLEX #ifdef __cplusplus static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { return ::std::complex< float >(x, y); } #else static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { return x + y*(__pyx_t_float_complex)_Complex_I; } #endif #else static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { __pyx_t_float_complex z; z.real = x; z.imag = y; return z; } #endif /* Arithmetic */ #if CYTHON_CCOMPLEX #else static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { return (a.real == b.real) && (a.imag == b.imag); } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; z.real = a.real + b.real; z.imag = a.imag + b.imag; return z; } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; z.real = a.real - b.real; z.imag = a.imag - b.imag; return z; } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; z.real = a.real * b.real - a.imag * b.imag; z.imag = a.real * b.imag + a.imag * b.real; return z; } #if 1 static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { if (b.imag == 0) { return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); } else if (fabsf(b.real) >= fabsf(b.imag)) { if (b.real == 0 && b.imag == 0) { return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.imag); } else { float r = b.imag / b.real; float s = (float)(1.0) / (b.real + b.imag * r); return __pyx_t_float_complex_from_parts( (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); } } else { float r = b.real / b.imag; float s = (float)(1.0) / (b.imag + b.real * r); return __pyx_t_float_complex_from_parts( (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); } } #else static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { if (b.imag == 0) { return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); } else { float denom = b.real * b.real + b.imag * b.imag; return __pyx_t_float_complex_from_parts( (a.real * b.real + a.imag * b.imag) / denom, (a.imag * b.real - a.real * b.imag) / denom); } } #endif static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex a) { __pyx_t_float_complex z; z.real = -a.real; z.imag = -a.imag; return z; } static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex a) { return (a.real == 0) && (a.imag == 0); } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex a) { __pyx_t_float_complex z; z.real = a.real; z.imag = -a.imag; return z; } #if 1 static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex z) { #if !defined(HAVE_HYPOT) || defined(_MSC_VER) return sqrtf(z.real*z.real + z.imag*z.imag); #else return hypotf(z.real, z.imag); #endif } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; float r, lnr, theta, z_r, z_theta; if (b.imag == 0 && b.real == (int)b.real) { if (b.real < 0) { float denom = a.real * a.real + a.imag * a.imag; a.real = a.real / denom; a.imag = -a.imag / denom; b.real = -b.real; } switch ((int)b.real) { case 0: z.real = 1; z.imag = 0; return z; case 1: return a; case 2: return __Pyx_c_prod_float(a, a); case 3: z = __Pyx_c_prod_float(a, a); return __Pyx_c_prod_float(z, a); case 4: z = __Pyx_c_prod_float(a, a); return __Pyx_c_prod_float(z, z); } } if (a.imag == 0) { if (a.real == 0) { return a; } else if (b.imag == 0) { z.real = powf(a.real, b.real); z.imag = 0; return z; } else if (a.real > 0) { r = a.real; theta = 0; } else { r = -a.real; theta = atan2f(0.0, -1.0); } } else { r = __Pyx_c_abs_float(a); theta = atan2f(a.imag, a.real); } lnr = logf(r); z_r = expf(lnr * b.real - theta * b.imag); z_theta = theta * b.real + lnr * b.imag; z.real = z_r * cosf(z_theta); z.imag = z_r * sinf(z_theta); return z; } #endif #endif /* Declarations */ #if CYTHON_CCOMPLEX #ifdef __cplusplus static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { return ::std::complex< double >(x, y); } #else static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { return x + y*(__pyx_t_double_complex)_Complex_I; } #endif #else static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { __pyx_t_double_complex z; z.real = x; z.imag = y; return z; } #endif /* Arithmetic */ #if CYTHON_CCOMPLEX #else static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { return (a.real == b.real) && (a.imag == b.imag); } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; z.real = a.real + b.real; z.imag = a.imag + b.imag; return z; } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; z.real = a.real - b.real; z.imag = a.imag - b.imag; return z; } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; z.real = a.real * b.real - a.imag * b.imag; z.imag = a.real * b.imag + a.imag * b.real; return z; } #if 1 static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { if (b.imag == 0) { return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); } else if (fabs(b.real) >= fabs(b.imag)) { if (b.real == 0 && b.imag == 0) { return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.imag); } else { double r = b.imag / b.real; double s = (double)(1.0) / (b.real + b.imag * r); return __pyx_t_double_complex_from_parts( (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); } } else { double r = b.real / b.imag; double s = (double)(1.0) / (b.imag + b.real * r); return __pyx_t_double_complex_from_parts( (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); } } #else static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { if (b.imag == 0) { return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); } else { double denom = b.real * b.real + b.imag * b.imag; return __pyx_t_double_complex_from_parts( (a.real * b.real + a.imag * b.imag) / denom, (a.imag * b.real - a.real * b.imag) / denom); } } #endif static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex a) { __pyx_t_double_complex z; z.real = -a.real; z.imag = -a.imag; return z; } static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex a) { return (a.real == 0) && (a.imag == 0); } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex a) { __pyx_t_double_complex z; z.real = a.real; z.imag = -a.imag; return z; } #if 1 static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex z) { #if !defined(HAVE_HYPOT) || defined(_MSC_VER) return sqrt(z.real*z.real + z.imag*z.imag); #else return hypot(z.real, z.imag); #endif } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; double r, lnr, theta, z_r, z_theta; if (b.imag == 0 && b.real == (int)b.real) { if (b.real < 0) { double denom = a.real * a.real + a.imag * a.imag; a.real = a.real / denom; a.imag = -a.imag / denom; b.real = -b.real; } switch ((int)b.real) { case 0: z.real = 1; z.imag = 0; return z; case 1: return a; case 2: return __Pyx_c_prod_double(a, a); case 3: z = __Pyx_c_prod_double(a, a); return __Pyx_c_prod_double(z, a); case 4: z = __Pyx_c_prod_double(a, a); return __Pyx_c_prod_double(z, z); } } if (a.imag == 0) { if (a.real == 0) { return a; } else if (b.imag == 0) { z.real = pow(a.real, b.real); z.imag = 0; return z; } else if (a.real > 0) { r = a.real; theta = 0; } else { r = -a.real; theta = atan2(0.0, -1.0); } } else { r = __Pyx_c_abs_double(a); theta = atan2(a.imag, a.real); } lnr = log(r); z_r = exp(lnr * b.real - theta * b.imag); z_theta = theta * b.real + lnr * b.imag; z.real = z_r * cos(z_theta); z.imag = z_r * sin(z_theta); return z; } #endif #endif /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__NPY_TYPES(enum NPY_TYPES value) { const enum NPY_TYPES neg_one = (enum NPY_TYPES) ((enum NPY_TYPES) 0 - (enum NPY_TYPES) 1), const_zero = (enum NPY_TYPES) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(enum NPY_TYPES) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(enum NPY_TYPES) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(enum NPY_TYPES) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof(enum NPY_TYPES) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(enum NPY_TYPES) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; return _PyLong_FromByteArray(bytes, sizeof(enum NPY_TYPES), little, !is_unsigned); } } /* CIntFromPy */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { if (sizeof(int) < sizeof(long)) { __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } return (int) val; } } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (int) 0; case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) case 2: if (8 * sizeof(int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); } } break; case 3: if (8 * sizeof(int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); } } break; case 4: if (8 * sizeof(int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); } } break; } #endif #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { goto raise_neg_overflow; } #else { int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) return (int) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif if (sizeof(int) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (int) 0; case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) case -2: if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case 2: if (8 * sizeof(int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case -3: if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case 3: if (8 * sizeof(int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case -4: if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case 4: if (8 * sizeof(int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; } #endif if (sizeof(int) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } { #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); #else int val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { PyObject *tmp = v; v = PyNumber_Long(tmp); Py_DECREF(tmp); } #endif if (likely(v)) { int one = 1; int is_little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&val; int ret = _PyLong_AsByteArray((PyLongObject *)v, bytes, sizeof(val), is_little, !is_unsigned); Py_DECREF(v); if (likely(!ret)) return val; } #endif return (int) -1; } } else { int val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); if (!tmp) return (int) -1; val = __Pyx_PyInt_As_int(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, "value too large to convert to int"); return (int) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, "can't convert negative value to int"); return (int) -1; } /* CIntFromPy */ static CYTHON_INLINE unsigned int __Pyx_PyInt_As_unsigned_int(PyObject *x) { const unsigned int neg_one = (unsigned int) ((unsigned int) 0 - (unsigned int) 1), const_zero = (unsigned int) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { if (sizeof(unsigned int) < sizeof(long)) { __PYX_VERIFY_RETURN_INT(unsigned int, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } return (unsigned int) val; } } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (unsigned int) 0; case 1: __PYX_VERIFY_RETURN_INT(unsigned int, digit, digits[0]) case 2: if (8 * sizeof(unsigned int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) >= 2 * PyLong_SHIFT) { return (unsigned int) (((((unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])); } } break; case 3: if (8 * sizeof(unsigned int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) >= 3 * PyLong_SHIFT) { return (unsigned int) (((((((unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])); } } break; case 4: if (8 * sizeof(unsigned int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) >= 4 * PyLong_SHIFT) { return (unsigned int) (((((((((unsigned int)digits[3]) << PyLong_SHIFT) | (unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])); } } break; } #endif #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { goto raise_neg_overflow; } #else { int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) return (unsigned int) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif if (sizeof(unsigned int) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(unsigned int, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(unsigned int) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(unsigned int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (unsigned int) 0; case -1: __PYX_VERIFY_RETURN_INT(unsigned int, sdigit, (sdigit) (-(sdigit)digits[0])) case 1: __PYX_VERIFY_RETURN_INT(unsigned int, digit, +digits[0]) case -2: if (8 * sizeof(unsigned int) - 1 > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 2 * PyLong_SHIFT) { return (unsigned int) (((unsigned int)-1)*(((((unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case 2: if (8 * sizeof(unsigned int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 2 * PyLong_SHIFT) { return (unsigned int) ((((((unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case -3: if (8 * sizeof(unsigned int) - 1 > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 3 * PyLong_SHIFT) { return (unsigned int) (((unsigned int)-1)*(((((((unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case 3: if (8 * sizeof(unsigned int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 3 * PyLong_SHIFT) { return (unsigned int) ((((((((unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case -4: if (8 * sizeof(unsigned int) - 1 > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 4 * PyLong_SHIFT) { return (unsigned int) (((unsigned int)-1)*(((((((((unsigned int)digits[3]) << PyLong_SHIFT) | (unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case 4: if (8 * sizeof(unsigned int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 4 * PyLong_SHIFT) { return (unsigned int) ((((((((((unsigned int)digits[3]) << PyLong_SHIFT) | (unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; } #endif if (sizeof(unsigned int) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(unsigned int, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(unsigned int) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(unsigned int, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } { #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); #else unsigned int val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { PyObject *tmp = v; v = PyNumber_Long(tmp); Py_DECREF(tmp); } #endif if (likely(v)) { int one = 1; int is_little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&val; int ret = _PyLong_AsByteArray((PyLongObject *)v, bytes, sizeof(val), is_little, !is_unsigned); Py_DECREF(v); if (likely(!ret)) return val; } #endif return (unsigned int) -1; } } else { unsigned int val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); if (!tmp) return (unsigned int) -1; val = __Pyx_PyInt_As_unsigned_int(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, "value too large to convert to unsigned int"); return (unsigned int) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, "can't convert negative value to unsigned int"); return (unsigned int) -1; } /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(long) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(long) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof(long) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; return _PyLong_FromByteArray(bytes, sizeof(long), little, !is_unsigned); } } /* CIntFromPy */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { if (sizeof(long) < sizeof(long)) { __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } return (long) val; } } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (long) 0; case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) case 2: if (8 * sizeof(long) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); } } break; case 3: if (8 * sizeof(long) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); } } break; case 4: if (8 * sizeof(long) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); } } break; } #endif #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { goto raise_neg_overflow; } #else { int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) return (long) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif if (sizeof(long) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (long) 0; case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) case -2: if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case 2: if (8 * sizeof(long) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case -3: if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case 3: if (8 * sizeof(long) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case -4: if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case 4: if (8 * sizeof(long) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; } #endif if (sizeof(long) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } { #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); #else long val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { PyObject *tmp = v; v = PyNumber_Long(tmp); Py_DECREF(tmp); } #endif if (likely(v)) { int one = 1; int is_little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&val; int ret = _PyLong_AsByteArray((PyLongObject *)v, bytes, sizeof(val), is_little, !is_unsigned); Py_DECREF(v); if (likely(!ret)) return val; } #endif return (long) -1; } } else { long val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); if (!tmp) return (long) -1; val = __Pyx_PyInt_As_long(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, "value too large to convert to long"); return (long) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, "can't convert negative value to long"); return (long) -1; } /* FastTypeChecks */ #if CYTHON_COMPILING_IN_CPYTHON static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { while (a) { a = a->tp_base; if (a == b) return 1; } return b == &PyBaseObject_Type; } static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { PyObject *mro; if (a == b) return 1; mro = a->tp_mro; if (likely(mro)) { Py_ssize_t i, n; n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) return 1; } return 0; } return __Pyx_InBases(a, b); } #if PY_MAJOR_VERSION == 2 static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { PyObject *exception, *value, *tb; int res; __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ErrFetch(&exception, &value, &tb); res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; if (unlikely(res == -1)) { PyErr_WriteUnraisable(err); res = 0; } if (!res) { res = PyObject_IsSubclass(err, exc_type2); if (unlikely(res == -1)) { PyErr_WriteUnraisable(err); res = 0; } } __Pyx_ErrRestore(exception, value, tb); return res; } #else static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; if (!res) { res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); } return res; } #endif static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { Py_ssize_t i, n; assert(PyExceptionClass_Check(exc_type)); n = PyTuple_GET_SIZE(tuple); #if PY_MAJOR_VERSION >= 3 for (i=0; i= 0x02070000 if (!PyCapsule_IsValid(cobj, sig)) { PyErr_Format(PyExc_TypeError, "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", PyModule_GetName(module), funcname, sig, PyCapsule_GetName(cobj)); goto bad; } tmp.p = PyCapsule_GetPointer(cobj, sig); #else {const char *desc, *s1, *s2; desc = (const char *)PyCObject_GetDesc(cobj); if (!desc) goto bad; s1 = desc; s2 = sig; while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } if (*s1 != *s2) { PyErr_Format(PyExc_TypeError, "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", PyModule_GetName(module), funcname, sig, desc); goto bad; } tmp.p = PyCObject_AsVoidPtr(cobj);} #endif *f = tmp.fp; if (!(*f)) goto bad; Py_DECREF(d); return 0; bad: Py_XDECREF(d); return -1; } #endif /* InitStrings */ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { while (t->p) { #if PY_MAJOR_VERSION < 3 if (t->is_unicode) { *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); } else if (t->intern) { *t->p = PyString_InternFromString(t->s); } else { *t->p = PyString_FromStringAndSize(t->s, t->n - 1); } #else if (t->is_unicode | t->is_str) { if (t->intern) { *t->p = PyUnicode_InternFromString(t->s); } else if (t->encoding) { *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); } else { *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); } } else { *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); } #endif if (!*t->p) return -1; if (PyObject_Hash(*t->p) == -1) return -1; ++t; } return 0; } static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); } static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { Py_ssize_t ignore; return __Pyx_PyObject_AsStringAndSize(o, &ignore); } #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT #if !CYTHON_PEP393_ENABLED static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { char* defenc_c; PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); if (!defenc) return NULL; defenc_c = PyBytes_AS_STRING(defenc); #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII { char* end = defenc_c + PyBytes_GET_SIZE(defenc); char* c; for (c = defenc_c; c < end; c++) { if ((unsigned char) (*c) >= 128) { PyUnicode_AsASCIIString(o); return NULL; } } } #endif *length = PyBytes_GET_SIZE(defenc); return defenc_c; } #else static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII if (likely(PyUnicode_IS_ASCII(o))) { *length = PyUnicode_GET_LENGTH(o); return PyUnicode_AsUTF8(o); } else { PyUnicode_AsASCIIString(o); return NULL; } #else return PyUnicode_AsUTF8AndSize(o, length); #endif } #endif #endif static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT if ( #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII __Pyx_sys_getdefaultencoding_not_ascii && #endif PyUnicode_Check(o)) { return __Pyx_PyUnicode_AsStringAndSize(o, length); } else #endif #if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) if (PyByteArray_Check(o)) { *length = PyByteArray_GET_SIZE(o); return PyByteArray_AS_STRING(o); } else #endif { char* result; int r = PyBytes_AsStringAndSize(o, &result, length); if (unlikely(r < 0)) { return NULL; } else { return result; } } } static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { int is_true = x == Py_True; if (is_true | (x == Py_False) | (x == Py_None)) return is_true; else return PyObject_IsTrue(x); } static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { int retval; if (unlikely(!x)) return -1; retval = __Pyx_PyObject_IsTrue(x); Py_DECREF(x); return retval; } static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { #if PY_MAJOR_VERSION >= 3 if (PyLong_Check(result)) { if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, "__int__ returned non-int (type %.200s). " "The ability to return an instance of a strict subclass of int " "is deprecated, and may be removed in a future version of Python.", Py_TYPE(result)->tp_name)) { Py_DECREF(result); return NULL; } return result; } #endif PyErr_Format(PyExc_TypeError, "__%.4s__ returned non-%.4s (type %.200s)", type_name, type_name, Py_TYPE(result)->tp_name); Py_DECREF(result); return NULL; } static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { #if CYTHON_USE_TYPE_SLOTS PyNumberMethods *m; #endif const char *name = NULL; PyObject *res = NULL; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x) || PyLong_Check(x))) #else if (likely(PyLong_Check(x))) #endif return __Pyx_NewRef(x); #if CYTHON_USE_TYPE_SLOTS m = Py_TYPE(x)->tp_as_number; #if PY_MAJOR_VERSION < 3 if (m && m->nb_int) { name = "int"; res = m->nb_int(x); } else if (m && m->nb_long) { name = "long"; res = m->nb_long(x); } #else if (likely(m && m->nb_int)) { name = "int"; res = m->nb_int(x); } #endif #else if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { res = PyNumber_Int(x); } #endif if (likely(res)) { #if PY_MAJOR_VERSION < 3 if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { #else if (unlikely(!PyLong_CheckExact(res))) { #endif return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); } } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "an integer is required"); } return res; } static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { Py_ssize_t ival; PyObject *x; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_CheckExact(b))) { if (sizeof(Py_ssize_t) >= sizeof(long)) return PyInt_AS_LONG(b); else return PyInt_AsSsize_t(b); } #endif if (likely(PyLong_CheckExact(b))) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)b)->ob_digit; const Py_ssize_t size = Py_SIZE(b); if (likely(__Pyx_sst_abs(size) <= 1)) { ival = likely(size) ? digits[0] : 0; if (size == -1) ival = -ival; return ival; } else { switch (size) { case 2: if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case -2: if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case 3: if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case -3: if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case 4: if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case -4: if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; } } #endif return PyLong_AsSsize_t(b); } x = PyNumber_Index(b); if (!x) return -1; ival = PyInt_AsSsize_t(x); Py_DECREF(x); return ival; } static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); } static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { return PyInt_FromSize_t(ival); } #endif /* Py_PYTHON_H */ photutils-0.7.2/photutils/geometry/elliptical_overlap.pyx0000644000214200020070000001524513563423715026260 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst #cython: language_level=3 """ The functions defined here allow one to determine the exact area of overlap of an ellipse and a triangle (written by Thomas Robitaille). The approach is to divide the rectangle into two triangles, and reproject these so that the ellipse is a unit circle, then compute the intersection of a triangle with a unit circle. """ import numpy as np cimport numpy as np __all__ = ['elliptical_overlap_grid'] cdef extern from "math.h": double asin(double x) double sin(double x) double cos(double x) double sqrt(double x) from cpython cimport bool DTYPE = np.float64 ctypedef np.float64_t DTYPE_t cimport cython # NOTE: Here we need to make sure we use cimport to import the C functions from # core (since these were defined with cdef). This also requires the core.pxd # file to exist with the function signatures. from .core cimport distance, area_triangle, overlap_area_triangle_unit_circle def elliptical_overlap_grid(double xmin, double xmax, double ymin, double ymax, int nx, int ny, double rx, double ry, double theta, int use_exact, int subpixels): """ elliptical_overlap_grid(xmin, xmax, ymin, ymax, nx, ny, rx, ry, use_exact, subpixels) Area of overlap between an ellipse and a pixel grid. The ellipse is centered on the origin. Parameters ---------- xmin, xmax, ymin, ymax : float Extent of the grid in the x and y direction. nx, ny : int Grid dimensions. rx : float The semimajor axis of the ellipse. ry : float The semiminor axis of the ellipse. theta : float The position angle of the semimajor axis in radians (counterclockwise). use_exact : 0 or 1 If set to 1, calculates the exact overlap, while if set to 0, uses a subpixel sampling method with ``subpixel`` subpixels in each direction. subpixels : int If ``use_exact`` is 0, each pixel is resampled by this factor in each dimension. Thus, each pixel is divided into ``subpixels ** 2`` subpixels. Returns ------- frac : `~numpy.ndarray` 2-d array giving the fraction of the overlap. """ cdef unsigned int i, j cdef double x, y, dx, dy cdef double bxmin, bxmax, bymin, bymax cdef double pxmin, pxmax, pymin, pymax cdef double norm # Define output array cdef np.ndarray[DTYPE_t, ndim=2] frac = np.zeros([ny, nx], dtype=DTYPE) # Find the width of each element in x and y dx = (xmax - xmin) / nx dy = (ymax - ymin) / ny norm = 1. / (dx * dy) # For now we use a bounding circle and then use that to find a bounding box # but of course this is inefficient and could be done better. # Find bounding circle radius r = max(rx, ry) # Define bounding box bxmin = -r - 0.5 * dx bxmax = +r + 0.5 * dx bymin = -r - 0.5 * dy bymax = +r + 0.5 * dy for i in range(nx): pxmin = xmin + i * dx # lower end of pixel pxmax = pxmin + dx # upper end of pixel if pxmax > bxmin and pxmin < bxmax: for j in range(ny): pymin = ymin + j * dy pymax = pymin + dy if pymax > bymin and pymin < bymax: if use_exact: frac[j, i] = elliptical_overlap_single_exact( pxmin, pymin, pxmax, pymax, rx, ry, theta) * norm else: frac[j, i] = elliptical_overlap_single_subpixel( pxmin, pymin, pxmax, pymax, rx, ry, theta, subpixels) return frac # NOTE: The following two functions use cdef because they are not # intended to be called from the Python code. Using def makes them # callable from outside, but also slower. In any case, these aren't useful # to call from outside because they only operate on a single pixel. cdef double elliptical_overlap_single_subpixel(double x0, double y0, double x1, double y1, double rx, double ry, double theta, int subpixels): """ Return the fraction of overlap between a ellipse and a single pixel with given extent, using a sub-pixel sampling method. """ cdef unsigned int i, j cdef double x, y cdef double frac = 0. # Accumulator. cdef double inv_rx_sq, inv_ry_sq cdef double cos_theta = cos(theta) cdef double sin_theta = sin(theta) cdef double dx, dy cdef double x_tr, y_tr dx = (x1 - x0) / subpixels dy = (y1 - y0) / subpixels inv_rx_sq = 1. / (rx * rx) inv_ry_sq = 1. / (ry * ry) x = x0 - 0.5 * dx for i in range(subpixels): x += dx y = y0 - 0.5 * dy for j in range(subpixels): y += dy # Transform into frame of rotated ellipse x_tr = y * sin_theta + x * cos_theta y_tr = y * cos_theta - x * sin_theta if x_tr * x_tr * inv_rx_sq + y_tr * y_tr * inv_ry_sq < 1.: frac += 1. return frac / (subpixels * subpixels) cdef double elliptical_overlap_single_exact(double xmin, double ymin, double xmax, double ymax, double rx, double ry, double theta): """ Given a rectangle defined by (xmin, ymin, xmax, ymax) and an ellipse with major and minor axes rx and ry respectively, position angle theta, and centered at the origin, find the area of overlap. """ cdef double cos_m_theta = cos(-theta) cdef double sin_m_theta = sin(-theta) cdef double scale # Find scale by which the areas will be shrunk scale = rx * ry # Reproject rectangle to frame of reference in which ellipse is a # unit circle x1, y1 = ((xmin * cos_m_theta - ymin * sin_m_theta) / rx, (xmin * sin_m_theta + ymin * cos_m_theta) / ry) x2, y2 = ((xmax * cos_m_theta - ymin * sin_m_theta) / rx, (xmax * sin_m_theta + ymin * cos_m_theta) / ry) x3, y3 = ((xmax * cos_m_theta - ymax * sin_m_theta) / rx, (xmax * sin_m_theta + ymax * cos_m_theta) / ry) x4, y4 = ((xmin * cos_m_theta - ymax * sin_m_theta) / rx, (xmin * sin_m_theta + ymax * cos_m_theta) / ry) # Divide resulting quadrilateral into two triangles and find # intersection with unit circle return (overlap_area_triangle_unit_circle(x1, y1, x2, y2, x3, y3) + overlap_area_triangle_unit_circle(x1, y1, x4, y4, x3, y3)) * scale photutils-0.7.2/photutils/geometry/rectangular_overlap.c0000644000214200020070000127745213573510267026062 0ustar lbradleySTSCI\science00000000000000/* Generated by Cython 0.29.14 */ #define PY_SSIZE_T_CLEAN #include "Python.h" #ifndef Py_PYTHON_H #error Python headers needed to compile C extensions, please install development version of Python. #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) #error Cython requires Python 2.6+ or Python 3.3+. #else #define CYTHON_ABI "0_29_14" #define CYTHON_HEX_VERSION 0x001D0EF0 #define CYTHON_FUTURE_DIVISION 1 #include #ifndef offsetof #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) #endif #if !defined(WIN32) && !defined(MS_WINDOWS) #ifndef __stdcall #define __stdcall #endif #ifndef __cdecl #define __cdecl #endif #ifndef __fastcall #define __fastcall #endif #endif #ifndef DL_IMPORT #define DL_IMPORT(t) t #endif #ifndef DL_EXPORT #define DL_EXPORT(t) t #endif #define __PYX_COMMA , #ifndef HAVE_LONG_LONG #if PY_VERSION_HEX >= 0x02070000 #define HAVE_LONG_LONG #endif #endif #ifndef PY_LONG_LONG #define PY_LONG_LONG LONG_LONG #endif #ifndef Py_HUGE_VAL #define Py_HUGE_VAL HUGE_VAL #endif #ifdef PYPY_VERSION #define CYTHON_COMPILING_IN_PYPY 1 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 0 #undef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 0 #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #if PY_VERSION_HEX < 0x03050000 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #elif !defined(CYTHON_USE_ASYNC_SLOTS) #define CYTHON_USE_ASYNC_SLOTS 1 #endif #undef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 0 #undef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 0 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #undef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 1 #undef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 0 #undef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 0 #undef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 0 #undef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 0 #undef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 0 #undef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE 0 #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #elif defined(PYSTON_VERSION) #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 1 #define CYTHON_COMPILING_IN_CPYTHON 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #undef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 0 #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #ifndef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 0 #endif #ifndef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 1 #endif #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif #undef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 0 #undef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 0 #undef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 0 #undef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE 0 #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #else #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 1 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif #if PY_VERSION_HEX < 0x02070000 #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) #define CYTHON_USE_PYTYPE_LOOKUP 1 #endif #if PY_MAJOR_VERSION < 3 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #elif !defined(CYTHON_USE_ASYNC_SLOTS) #define CYTHON_USE_ASYNC_SLOTS 1 #endif #if PY_VERSION_HEX < 0x02070000 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #elif !defined(CYTHON_USE_PYLONG_INTERNALS) #define CYTHON_USE_PYLONG_INTERNALS 1 #endif #ifndef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 1 #endif #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif #if PY_VERSION_HEX < 0x030300F0 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #elif !defined(CYTHON_USE_UNICODE_WRITER) #define CYTHON_USE_UNICODE_WRITER 1 #endif #ifndef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 0 #endif #ifndef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 1 #endif #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif #ifndef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 1 #endif #ifndef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 1 #endif #ifndef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) #endif #ifndef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) #endif #ifndef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) #endif #ifndef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) #endif #endif #if !defined(CYTHON_FAST_PYCCALL) #define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) #endif #if CYTHON_USE_PYLONG_INTERNALS #include "longintrepr.h" #undef SHIFT #undef BASE #undef MASK #ifdef SIZEOF_VOID_P enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; #endif #endif #ifndef __has_attribute #define __has_attribute(x) 0 #endif #ifndef __has_cpp_attribute #define __has_cpp_attribute(x) 0 #endif #ifndef CYTHON_RESTRICT #if defined(__GNUC__) #define CYTHON_RESTRICT __restrict__ #elif defined(_MSC_VER) && _MSC_VER >= 1400 #define CYTHON_RESTRICT __restrict #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define CYTHON_RESTRICT restrict #else #define CYTHON_RESTRICT #endif #endif #ifndef CYTHON_UNUSED # if defined(__GNUC__) # if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) # define CYTHON_UNUSED __attribute__ ((__unused__)) # else # define CYTHON_UNUSED # endif # elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) # define CYTHON_UNUSED __attribute__ ((__unused__)) # else # define CYTHON_UNUSED # endif #endif #ifndef CYTHON_MAYBE_UNUSED_VAR # if defined(__cplusplus) template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } # else # define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) # endif #endif #ifndef CYTHON_NCP_UNUSED # if CYTHON_COMPILING_IN_CPYTHON # define CYTHON_NCP_UNUSED # else # define CYTHON_NCP_UNUSED CYTHON_UNUSED # endif #endif #define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) #ifdef _MSC_VER #ifndef _MSC_STDINT_H_ #if _MSC_VER < 1300 typedef unsigned char uint8_t; typedef unsigned int uint32_t; #else typedef unsigned __int8 uint8_t; typedef unsigned __int32 uint32_t; #endif #endif #else #include #endif #ifndef CYTHON_FALLTHROUGH #if defined(__cplusplus) && __cplusplus >= 201103L #if __has_cpp_attribute(fallthrough) #define CYTHON_FALLTHROUGH [[fallthrough]] #elif __has_cpp_attribute(clang::fallthrough) #define CYTHON_FALLTHROUGH [[clang::fallthrough]] #elif __has_cpp_attribute(gnu::fallthrough) #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] #endif #endif #ifndef CYTHON_FALLTHROUGH #if __has_attribute(fallthrough) #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) #else #define CYTHON_FALLTHROUGH #endif #endif #if defined(__clang__ ) && defined(__apple_build_version__) #if __apple_build_version__ < 7000000 #undef CYTHON_FALLTHROUGH #define CYTHON_FALLTHROUGH #endif #endif #endif #ifndef CYTHON_INLINE #if defined(__clang__) #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) #elif defined(__GNUC__) #define CYTHON_INLINE __inline__ #elif defined(_MSC_VER) #define CYTHON_INLINE __inline #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define CYTHON_INLINE inline #else #define CYTHON_INLINE #endif #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) #define Py_OptimizeFlag 0 #endif #define __PYX_BUILD_PY_SSIZE_T "n" #define CYTHON_FORMAT_SSIZE_T "z" #if PY_MAJOR_VERSION < 3 #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #define __Pyx_DefaultClassType PyClass_Type #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" #if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #else #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #endif #define __Pyx_DefaultClassType PyType_Type #endif #ifndef Py_TPFLAGS_CHECKTYPES #define Py_TPFLAGS_CHECKTYPES 0 #endif #ifndef Py_TPFLAGS_HAVE_INDEX #define Py_TPFLAGS_HAVE_INDEX 0 #endif #ifndef Py_TPFLAGS_HAVE_NEWBUFFER #define Py_TPFLAGS_HAVE_NEWBUFFER 0 #endif #ifndef Py_TPFLAGS_HAVE_FINALIZE #define Py_TPFLAGS_HAVE_FINALIZE 0 #endif #ifndef METH_STACKLESS #define METH_STACKLESS 0 #endif #if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) #ifndef METH_FASTCALL #define METH_FASTCALL 0x80 #endif typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); #else #define __Pyx_PyCFunctionFast _PyCFunctionFast #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords #endif #if CYTHON_FAST_PYCCALL #define __Pyx_PyFastCFunction_Check(func)\ ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) #else #define __Pyx_PyFastCFunction_Check(func) 0 #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) #define PyObject_Malloc(s) PyMem_Malloc(s) #define PyObject_Free(p) PyMem_Free(p) #define PyObject_Realloc(p) PyMem_Realloc(p) #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 #define PyMem_RawMalloc(n) PyMem_Malloc(n) #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) #define PyMem_RawFree(p) PyMem_Free(p) #endif #if CYTHON_COMPILING_IN_PYSTON #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) #else #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) #endif #if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 #define __Pyx_PyThreadState_Current PyThreadState_GET() #elif PY_VERSION_HEX >= 0x03060000 #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() #elif PY_VERSION_HEX >= 0x03000000 #define __Pyx_PyThreadState_Current PyThreadState_GET() #else #define __Pyx_PyThreadState_Current _PyThreadState_Current #endif #if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) #include "pythread.h" #define Py_tss_NEEDS_INIT 0 typedef int Py_tss_t; static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { *key = PyThread_create_key(); return 0; } static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); *key = Py_tss_NEEDS_INIT; return key; } static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { PyObject_Free(key); } static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { return *key != Py_tss_NEEDS_INIT; } static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { PyThread_delete_key(*key); *key = Py_tss_NEEDS_INIT; } static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { return PyThread_set_key_value(*key, value); } static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { return PyThread_get_key_value(*key); } #endif #if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) #define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) #else #define __Pyx_PyDict_NewPresized(n) PyDict_New() #endif #if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) #else #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS #define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) #else #define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) #endif #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) #define CYTHON_PEP393_ENABLED 1 #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ 0 : _PyUnicode_Ready((PyObject *)(op))) #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) #else #define CYTHON_PEP393_ENABLED 0 #define PyUnicode_1BYTE_KIND 1 #define PyUnicode_2BYTE_KIND 2 #define PyUnicode_4BYTE_KIND 4 #define __Pyx_PyUnicode_READY(op) (0) #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) #endif #if CYTHON_COMPILING_IN_PYPY #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) #else #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) #endif #define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) #define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) #else #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) #endif #if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) #define PyObject_ASCII(o) PyObject_Repr(o) #endif #if PY_MAJOR_VERSION >= 3 #define PyBaseString_Type PyUnicode_Type #define PyStringObject PyUnicodeObject #define PyString_Type PyUnicode_Type #define PyString_Check PyUnicode_Check #define PyString_CheckExact PyUnicode_CheckExact #define PyObject_Unicode PyObject_Str #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) #else #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) #endif #ifndef PySet_CheckExact #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) #endif #if CYTHON_ASSUME_SAFE_MACROS #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) #else #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) #endif #if PY_MAJOR_VERSION >= 3 #define PyIntObject PyLongObject #define PyInt_Type PyLong_Type #define PyInt_Check(op) PyLong_Check(op) #define PyInt_CheckExact(op) PyLong_CheckExact(op) #define PyInt_FromString PyLong_FromString #define PyInt_FromUnicode PyLong_FromUnicode #define PyInt_FromLong PyLong_FromLong #define PyInt_FromSize_t PyLong_FromSize_t #define PyInt_FromSsize_t PyLong_FromSsize_t #define PyInt_AsLong PyLong_AsLong #define PyInt_AS_LONG PyLong_AS_LONG #define PyInt_AsSsize_t PyLong_AsSsize_t #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask #define PyNumber_Int PyNumber_Long #endif #if PY_MAJOR_VERSION >= 3 #define PyBoolObject PyLongObject #endif #if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY #ifndef PyUnicode_InternFromString #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) #endif #endif #if PY_VERSION_HEX < 0x030200A4 typedef long Py_hash_t; #define __Pyx_PyInt_FromHash_t PyInt_FromLong #define __Pyx_PyInt_AsHash_t PyInt_AsLong #else #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : (Py_INCREF(func), func)) #else #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) #endif #if CYTHON_USE_ASYNC_SLOTS #if PY_VERSION_HEX >= 0x030500B1 #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) #else #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) #endif #else #define __Pyx_PyType_AsAsync(obj) NULL #endif #ifndef __Pyx_PyAsyncMethodsStruct typedef struct { unaryfunc am_await; unaryfunc am_aiter; unaryfunc am_anext; } __Pyx_PyAsyncMethodsStruct; #endif #if defined(WIN32) || defined(MS_WINDOWS) #define _USE_MATH_DEFINES #endif #include #ifdef NAN #define __PYX_NAN() ((float) NAN) #else static CYTHON_INLINE float __PYX_NAN() { float value; memset(&value, 0xFF, sizeof(value)); return value; } #endif #if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) #define __Pyx_truncl trunc #else #define __Pyx_truncl truncl #endif #define __PYX_ERR(f_index, lineno, Ln_error) \ { \ __pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \ } #ifndef __PYX_EXTERN_C #ifdef __cplusplus #define __PYX_EXTERN_C extern "C" #else #define __PYX_EXTERN_C extern #endif #endif #define __PYX_HAVE__photutils__geometry__rectangular_overlap #define __PYX_HAVE_API__photutils__geometry__rectangular_overlap /* Early includes */ #include #include #include "numpy/arrayobject.h" #include "numpy/ufuncobject.h" #include "math.h" #include "pythread.h" #ifdef _OPENMP #include #endif /* _OPENMP */ #if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) #define CYTHON_WITHOUT_ASSERTIONS #endif typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; #define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 #define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 #define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) #define __PYX_DEFAULT_STRING_ENCODING "" #define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString #define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize #define __Pyx_uchar_cast(c) ((unsigned char)c) #define __Pyx_long_cast(x) ((long)x) #define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ (sizeof(type) < sizeof(Py_ssize_t)) ||\ (sizeof(type) > sizeof(Py_ssize_t) &&\ likely(v < (type)PY_SSIZE_T_MAX ||\ v == (type)PY_SSIZE_T_MAX) &&\ (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ v == (type)PY_SSIZE_T_MIN))) ||\ (sizeof(type) == sizeof(Py_ssize_t) &&\ (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ v == (type)PY_SSIZE_T_MAX))) ) static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { return (size_t) i < (size_t) limit; } #if defined (__cplusplus) && __cplusplus >= 201103L #include #define __Pyx_sst_abs(value) std::abs(value) #elif SIZEOF_INT >= SIZEOF_SIZE_T #define __Pyx_sst_abs(value) abs(value) #elif SIZEOF_LONG >= SIZEOF_SIZE_T #define __Pyx_sst_abs(value) labs(value) #elif defined (_MSC_VER) #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define __Pyx_sst_abs(value) llabs(value) #elif defined (__GNUC__) #define __Pyx_sst_abs(value) __builtin_llabs(value) #else #define __Pyx_sst_abs(value) ((value<0) ? -value : value) #endif static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); #define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) #define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) #define __Pyx_PyBytes_FromString PyBytes_FromString #define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); #if PY_MAJOR_VERSION < 3 #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize #else #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize #endif #define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) #define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) #define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) #define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) #define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) #define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { const Py_UNICODE *u_end = u; while (*u_end++) ; return (size_t)(u_end - u - 1); } #define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) #define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode #define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode #define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) #define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); #define __Pyx_PySequence_Tuple(obj)\ (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); #if CYTHON_ASSUME_SAFE_MACROS #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) #else #define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) #endif #define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) #else #define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) #endif #define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII static int __Pyx_sys_getdefaultencoding_not_ascii; static int __Pyx_init_sys_getdefaultencoding_params(void) { PyObject* sys; PyObject* default_encoding = NULL; PyObject* ascii_chars_u = NULL; PyObject* ascii_chars_b = NULL; const char* default_encoding_c; sys = PyImport_ImportModule("sys"); if (!sys) goto bad; default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); Py_DECREF(sys); if (!default_encoding) goto bad; default_encoding_c = PyBytes_AsString(default_encoding); if (!default_encoding_c) goto bad; if (strcmp(default_encoding_c, "ascii") == 0) { __Pyx_sys_getdefaultencoding_not_ascii = 0; } else { char ascii_chars[128]; int c; for (c = 0; c < 128; c++) { ascii_chars[c] = c; } __Pyx_sys_getdefaultencoding_not_ascii = 1; ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); if (!ascii_chars_u) goto bad; ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { PyErr_Format( PyExc_ValueError, "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", default_encoding_c); goto bad; } Py_DECREF(ascii_chars_u); Py_DECREF(ascii_chars_b); } Py_DECREF(default_encoding); return 0; bad: Py_XDECREF(default_encoding); Py_XDECREF(ascii_chars_u); Py_XDECREF(ascii_chars_b); return -1; } #endif #if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) #else #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) #if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT static char* __PYX_DEFAULT_STRING_ENCODING; static int __Pyx_init_sys_getdefaultencoding_params(void) { PyObject* sys; PyObject* default_encoding = NULL; char* default_encoding_c; sys = PyImport_ImportModule("sys"); if (!sys) goto bad; default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); Py_DECREF(sys); if (!default_encoding) goto bad; default_encoding_c = PyBytes_AsString(default_encoding); if (!default_encoding_c) goto bad; __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); Py_DECREF(default_encoding); return 0; bad: Py_XDECREF(default_encoding); return -1; } #endif #endif /* Test for GCC > 2.95 */ #if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #else /* !__GNUC__ or GCC < 2.95 */ #define likely(x) (x) #define unlikely(x) (x) #endif /* __GNUC__ */ static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } static PyObject *__pyx_m = NULL; static PyObject *__pyx_d; static PyObject *__pyx_b; static PyObject *__pyx_cython_runtime = NULL; static PyObject *__pyx_empty_tuple; static PyObject *__pyx_empty_bytes; static PyObject *__pyx_empty_unicode; static int __pyx_lineno; static int __pyx_clineno = 0; static const char * __pyx_cfilenm= __FILE__; static const char *__pyx_filename; /* Header.proto */ #if !defined(CYTHON_CCOMPLEX) #if defined(__cplusplus) #define CYTHON_CCOMPLEX 1 #elif defined(_Complex_I) #define CYTHON_CCOMPLEX 1 #else #define CYTHON_CCOMPLEX 0 #endif #endif #if CYTHON_CCOMPLEX #ifdef __cplusplus #include #else #include #endif #endif #if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__) #undef _Complex_I #define _Complex_I 1.0fj #endif static const char *__pyx_f[] = { "photutils/geometry/rectangular_overlap.pyx", "__init__.pxd", "type.pxd", "bool.pxd", "complex.pxd", }; /* BufferFormatStructs.proto */ #define IS_UNSIGNED(type) (((type) -1) > 0) struct __Pyx_StructField_; #define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0) typedef struct { const char* name; struct __Pyx_StructField_* fields; size_t size; size_t arraysize[8]; int ndim; char typegroup; char is_unsigned; int flags; } __Pyx_TypeInfo; typedef struct __Pyx_StructField_ { __Pyx_TypeInfo* type; const char* name; size_t offset; } __Pyx_StructField; typedef struct { __Pyx_StructField* field; size_t parent_offset; } __Pyx_BufFmt_StackElem; typedef struct { __Pyx_StructField root; __Pyx_BufFmt_StackElem* head; size_t fmt_offset; size_t new_count, enc_count; size_t struct_alignment; int is_complex; char enc_type; char new_packmode; char enc_packmode; char is_valid_array; } __Pyx_BufFmt_Context; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":776 * # in Cython to enable them only on the right systems. * * ctypedef npy_int8 int8_t # <<<<<<<<<<<<<< * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t */ typedef npy_int8 __pyx_t_5numpy_int8_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":777 * * ctypedef npy_int8 int8_t * ctypedef npy_int16 int16_t # <<<<<<<<<<<<<< * ctypedef npy_int32 int32_t * ctypedef npy_int64 int64_t */ typedef npy_int16 __pyx_t_5numpy_int16_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":778 * ctypedef npy_int8 int8_t * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t # <<<<<<<<<<<<<< * ctypedef npy_int64 int64_t * #ctypedef npy_int96 int96_t */ typedef npy_int32 __pyx_t_5numpy_int32_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":779 * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t * ctypedef npy_int64 int64_t # <<<<<<<<<<<<<< * #ctypedef npy_int96 int96_t * #ctypedef npy_int128 int128_t */ typedef npy_int64 __pyx_t_5numpy_int64_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":783 * #ctypedef npy_int128 int128_t * * ctypedef npy_uint8 uint8_t # <<<<<<<<<<<<<< * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t */ typedef npy_uint8 __pyx_t_5numpy_uint8_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":784 * * ctypedef npy_uint8 uint8_t * ctypedef npy_uint16 uint16_t # <<<<<<<<<<<<<< * ctypedef npy_uint32 uint32_t * ctypedef npy_uint64 uint64_t */ typedef npy_uint16 __pyx_t_5numpy_uint16_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":785 * ctypedef npy_uint8 uint8_t * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t # <<<<<<<<<<<<<< * ctypedef npy_uint64 uint64_t * #ctypedef npy_uint96 uint96_t */ typedef npy_uint32 __pyx_t_5numpy_uint32_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":786 * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t * ctypedef npy_uint64 uint64_t # <<<<<<<<<<<<<< * #ctypedef npy_uint96 uint96_t * #ctypedef npy_uint128 uint128_t */ typedef npy_uint64 __pyx_t_5numpy_uint64_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":790 * #ctypedef npy_uint128 uint128_t * * ctypedef npy_float32 float32_t # <<<<<<<<<<<<<< * ctypedef npy_float64 float64_t * #ctypedef npy_float80 float80_t */ typedef npy_float32 __pyx_t_5numpy_float32_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":791 * * ctypedef npy_float32 float32_t * ctypedef npy_float64 float64_t # <<<<<<<<<<<<<< * #ctypedef npy_float80 float80_t * #ctypedef npy_float128 float128_t */ typedef npy_float64 __pyx_t_5numpy_float64_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":800 * # The int types are mapped a bit surprising -- * # numpy.int corresponds to 'l' and numpy.long to 'q' * ctypedef npy_long int_t # <<<<<<<<<<<<<< * ctypedef npy_longlong long_t * ctypedef npy_longlong longlong_t */ typedef npy_long __pyx_t_5numpy_int_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":801 * # numpy.int corresponds to 'l' and numpy.long to 'q' * ctypedef npy_long int_t * ctypedef npy_longlong long_t # <<<<<<<<<<<<<< * ctypedef npy_longlong longlong_t * */ typedef npy_longlong __pyx_t_5numpy_long_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":802 * ctypedef npy_long int_t * ctypedef npy_longlong long_t * ctypedef npy_longlong longlong_t # <<<<<<<<<<<<<< * * ctypedef npy_ulong uint_t */ typedef npy_longlong __pyx_t_5numpy_longlong_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":804 * ctypedef npy_longlong longlong_t * * ctypedef npy_ulong uint_t # <<<<<<<<<<<<<< * ctypedef npy_ulonglong ulong_t * ctypedef npy_ulonglong ulonglong_t */ typedef npy_ulong __pyx_t_5numpy_uint_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":805 * * ctypedef npy_ulong uint_t * ctypedef npy_ulonglong ulong_t # <<<<<<<<<<<<<< * ctypedef npy_ulonglong ulonglong_t * */ typedef npy_ulonglong __pyx_t_5numpy_ulong_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":806 * ctypedef npy_ulong uint_t * ctypedef npy_ulonglong ulong_t * ctypedef npy_ulonglong ulonglong_t # <<<<<<<<<<<<<< * * ctypedef npy_intp intp_t */ typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":808 * ctypedef npy_ulonglong ulonglong_t * * ctypedef npy_intp intp_t # <<<<<<<<<<<<<< * ctypedef npy_uintp uintp_t * */ typedef npy_intp __pyx_t_5numpy_intp_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":809 * * ctypedef npy_intp intp_t * ctypedef npy_uintp uintp_t # <<<<<<<<<<<<<< * * ctypedef npy_double float_t */ typedef npy_uintp __pyx_t_5numpy_uintp_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":811 * ctypedef npy_uintp uintp_t * * ctypedef npy_double float_t # <<<<<<<<<<<<<< * ctypedef npy_double double_t * ctypedef npy_longdouble longdouble_t */ typedef npy_double __pyx_t_5numpy_float_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":812 * * ctypedef npy_double float_t * ctypedef npy_double double_t # <<<<<<<<<<<<<< * ctypedef npy_longdouble longdouble_t * */ typedef npy_double __pyx_t_5numpy_double_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":813 * ctypedef npy_double float_t * ctypedef npy_double double_t * ctypedef npy_longdouble longdouble_t # <<<<<<<<<<<<<< * * ctypedef npy_cfloat cfloat_t */ typedef npy_longdouble __pyx_t_5numpy_longdouble_t; /* "photutils/geometry/rectangular_overlap.pyx":25 * * DTYPE = np.float64 * ctypedef np.float64_t DTYPE_t # <<<<<<<<<<<<<< * * cimport cython */ typedef __pyx_t_5numpy_float64_t __pyx_t_9photutils_8geometry_19rectangular_overlap_DTYPE_t; /* Declarations.proto */ #if CYTHON_CCOMPLEX #ifdef __cplusplus typedef ::std::complex< float > __pyx_t_float_complex; #else typedef float _Complex __pyx_t_float_complex; #endif #else typedef struct { float real, imag; } __pyx_t_float_complex; #endif static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float); /* Declarations.proto */ #if CYTHON_CCOMPLEX #ifdef __cplusplus typedef ::std::complex< double > __pyx_t_double_complex; #else typedef double _Complex __pyx_t_double_complex; #endif #else typedef struct { double real, imag; } __pyx_t_double_complex; #endif static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double); /*--- Type declarations ---*/ /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":815 * ctypedef npy_longdouble longdouble_t * * ctypedef npy_cfloat cfloat_t # <<<<<<<<<<<<<< * ctypedef npy_cdouble cdouble_t * ctypedef npy_clongdouble clongdouble_t */ typedef npy_cfloat __pyx_t_5numpy_cfloat_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":816 * * ctypedef npy_cfloat cfloat_t * ctypedef npy_cdouble cdouble_t # <<<<<<<<<<<<<< * ctypedef npy_clongdouble clongdouble_t * */ typedef npy_cdouble __pyx_t_5numpy_cdouble_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":817 * ctypedef npy_cfloat cfloat_t * ctypedef npy_cdouble cdouble_t * ctypedef npy_clongdouble clongdouble_t # <<<<<<<<<<<<<< * * ctypedef npy_cdouble complex_t */ typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":819 * ctypedef npy_clongdouble clongdouble_t * * ctypedef npy_cdouble complex_t # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew1(a): */ typedef npy_cdouble __pyx_t_5numpy_complex_t; /* --- Runtime support code (head) --- */ /* Refnanny.proto */ #ifndef CYTHON_REFNANNY #define CYTHON_REFNANNY 0 #endif #if CYTHON_REFNANNY typedef struct { void (*INCREF)(void*, PyObject*, int); void (*DECREF)(void*, PyObject*, int); void (*GOTREF)(void*, PyObject*, int); void (*GIVEREF)(void*, PyObject*, int); void* (*SetupContext)(const char*, int, const char*); void (*FinishContext)(void**); } __Pyx_RefNannyAPIStruct; static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; #ifdef WITH_THREAD #define __Pyx_RefNannySetupContext(name, acquire_gil)\ if (acquire_gil) {\ PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ PyGILState_Release(__pyx_gilstate_save);\ } else {\ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ } #else #define __Pyx_RefNannySetupContext(name, acquire_gil)\ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) #endif #define __Pyx_RefNannyFinishContext()\ __Pyx_RefNanny->FinishContext(&__pyx_refnanny) #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) #else #define __Pyx_RefNannyDeclarations #define __Pyx_RefNannySetupContext(name, acquire_gil) #define __Pyx_RefNannyFinishContext() #define __Pyx_INCREF(r) Py_INCREF(r) #define __Pyx_DECREF(r) Py_DECREF(r) #define __Pyx_GOTREF(r) #define __Pyx_GIVEREF(r) #define __Pyx_XINCREF(r) Py_XINCREF(r) #define __Pyx_XDECREF(r) Py_XDECREF(r) #define __Pyx_XGOTREF(r) #define __Pyx_XGIVEREF(r) #endif #define __Pyx_XDECREF_SET(r, v) do {\ PyObject *tmp = (PyObject *) r;\ r = v; __Pyx_XDECREF(tmp);\ } while (0) #define __Pyx_DECREF_SET(r, v) do {\ PyObject *tmp = (PyObject *) r;\ r = v; __Pyx_DECREF(tmp);\ } while (0) #define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) #define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) /* PyObjectGetAttrStr.proto */ #if CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); #else #define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) #endif /* GetBuiltinName.proto */ static PyObject *__Pyx_GetBuiltinName(PyObject *name); /* RaiseArgTupleInvalid.proto */ static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /* RaiseDoubleKeywords.proto */ static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); /* ParseKeywords.proto */ static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ const char* function_name); /* PyDictVersioning.proto */ #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS #define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) #define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) #define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ (version_var) = __PYX_GET_DICT_VERSION(dict);\ (cache_var) = (value); #define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ static PY_UINT64_T __pyx_dict_version = 0;\ static PyObject *__pyx_dict_cached_value = NULL;\ if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ (VAR) = __pyx_dict_cached_value;\ } else {\ (VAR) = __pyx_dict_cached_value = (LOOKUP);\ __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ }\ } static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); #else #define __PYX_GET_DICT_VERSION(dict) (0) #define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) #define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); #endif /* GetModuleGlobalName.proto */ #if CYTHON_USE_DICT_VERSIONS #define __Pyx_GetModuleGlobalName(var, name) {\ static PY_UINT64_T __pyx_dict_version = 0;\ static PyObject *__pyx_dict_cached_value = NULL;\ (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ } #define __Pyx_GetModuleGlobalNameUncached(var, name) {\ PY_UINT64_T __pyx_dict_version;\ PyObject *__pyx_dict_cached_value;\ (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ } static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); #else #define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) #define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); #endif /* PyObjectCall.proto */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); #else #define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) #endif /* ExtTypeTest.proto */ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /* IsLittleEndian.proto */ static CYTHON_INLINE int __Pyx_Is_Little_Endian(void); /* BufferFormatCheck.proto */ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts); static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, __Pyx_BufFmt_StackElem* stack, __Pyx_TypeInfo* type); /* BufferGetAndValidate.proto */ #define __Pyx_GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)\ ((obj == Py_None || obj == NULL) ?\ (__Pyx_ZeroBuffer(buf), 0) :\ __Pyx__GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)) static int __Pyx__GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack); static void __Pyx_ZeroBuffer(Py_buffer* buf); static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info); static Py_ssize_t __Pyx_minusones[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; static Py_ssize_t __Pyx_zeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* PyThreadStateGet.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; #define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; #define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type #else #define __Pyx_PyThreadState_declare #define __Pyx_PyThreadState_assign #define __Pyx_PyErr_Occurred() PyErr_Occurred() #endif /* PyErrFetchRestore.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) #define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) #define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) #define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) #define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) #else #define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) #endif #else #define __Pyx_PyErr_Clear() PyErr_Clear() #define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) #define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) #define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) #define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) #endif /* RaiseException.proto */ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); /* BufferIndexError.proto */ static void __Pyx_RaiseBufferIndexError(int axis); #define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1) /* WriteUnraisableException.proto */ static void __Pyx_WriteUnraisable(const char *name, int clineno, int lineno, const char *filename, int full_traceback, int nogil); /* PyCFunctionFastCall.proto */ #if CYTHON_FAST_PYCCALL static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); #else #define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) #endif /* PyFunctionFastCall.proto */ #if CYTHON_FAST_PYCALL #define __Pyx_PyFunction_FastCall(func, args, nargs)\ __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) #if 1 || PY_VERSION_HEX < 0x030600B1 static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); #else #define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) #endif #define __Pyx_BUILD_ASSERT_EXPR(cond)\ (sizeof(char [1 - 2*!(cond)]) - 1) #ifndef Py_MEMBER_SIZE #define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) #endif static size_t __pyx_pyframe_localsplus_offset = 0; #include "frameobject.h" #define __Pxy_PyFrame_Initialize_Offsets()\ ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) #define __Pyx_PyFrame_GetLocalsplus(frame)\ (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) #endif /* PyObjectCallMethO.proto */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); #endif /* PyObjectCallOneArg.proto */ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); /* DictGetItem.proto */ #if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key); #define __Pyx_PyObject_Dict_GetItem(obj, name)\ (likely(PyDict_CheckExact(obj)) ?\ __Pyx_PyDict_GetItem(obj, name) : PyObject_GetItem(obj, name)) #else #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key) #define __Pyx_PyObject_Dict_GetItem(obj, name) PyObject_GetItem(obj, name) #endif /* RaiseTooManyValuesToUnpack.proto */ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); /* RaiseNeedMoreValuesToUnpack.proto */ static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); /* RaiseNoneIterError.proto */ static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); /* GetTopmostException.proto */ #if CYTHON_USE_EXC_INFO_STACK static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); #endif /* SaveResetException.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave(__pyx_tstate, type, value, tb) static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); #define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset(__pyx_tstate, type, value, tb) static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); #else #define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) #define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) #endif /* PyErrExceptionMatches.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); #else #define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) #endif /* GetException.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); #else static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); #endif /* TypeImport.proto */ #ifndef __PYX_HAVE_RT_ImportType_proto #define __PYX_HAVE_RT_ImportType_proto enum __Pyx_ImportType_CheckSize { __Pyx_ImportType_CheckSize_Error = 0, __Pyx_ImportType_CheckSize_Warn = 1, __Pyx_ImportType_CheckSize_Ignore = 2 }; static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); #endif /* Import.proto */ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); /* CLineInTraceback.proto */ #ifdef CYTHON_CLINE_IN_TRACEBACK #define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) #else static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); #endif /* CodeObjectCache.proto */ typedef struct { PyCodeObject* code_object; int code_line; } __Pyx_CodeObjectCacheEntry; struct __Pyx_CodeObjectCache { int count; int max_count; __Pyx_CodeObjectCacheEntry* entries; }; static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); static PyCodeObject *__pyx_find_code_object(int code_line); static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); /* AddTraceback.proto */ static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename); /* BufferStructDeclare.proto */ typedef struct { Py_ssize_t shape, strides, suboffsets; } __Pyx_Buf_DimInfo; typedef struct { size_t refcount; Py_buffer pybuffer; } __Pyx_Buffer; typedef struct { __Pyx_Buffer *rcbuffer; char *data; __Pyx_Buf_DimInfo diminfo[8]; } __Pyx_LocalBuf_ND; #if PY_MAJOR_VERSION < 3 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags); static void __Pyx_ReleaseBuffer(Py_buffer *view); #else #define __Pyx_GetBuffer PyObject_GetBuffer #define __Pyx_ReleaseBuffer PyBuffer_Release #endif /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); /* RealImag.proto */ #if CYTHON_CCOMPLEX #ifdef __cplusplus #define __Pyx_CREAL(z) ((z).real()) #define __Pyx_CIMAG(z) ((z).imag()) #else #define __Pyx_CREAL(z) (__real__(z)) #define __Pyx_CIMAG(z) (__imag__(z)) #endif #else #define __Pyx_CREAL(z) ((z).real) #define __Pyx_CIMAG(z) ((z).imag) #endif #if defined(__cplusplus) && CYTHON_CCOMPLEX\ && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103) #define __Pyx_SET_CREAL(z,x) ((z).real(x)) #define __Pyx_SET_CIMAG(z,y) ((z).imag(y)) #else #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x) #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y) #endif /* Arithmetic.proto */ #if CYTHON_CCOMPLEX #define __Pyx_c_eq_float(a, b) ((a)==(b)) #define __Pyx_c_sum_float(a, b) ((a)+(b)) #define __Pyx_c_diff_float(a, b) ((a)-(b)) #define __Pyx_c_prod_float(a, b) ((a)*(b)) #define __Pyx_c_quot_float(a, b) ((a)/(b)) #define __Pyx_c_neg_float(a) (-(a)) #ifdef __cplusplus #define __Pyx_c_is_zero_float(z) ((z)==(float)0) #define __Pyx_c_conj_float(z) (::std::conj(z)) #if 1 #define __Pyx_c_abs_float(z) (::std::abs(z)) #define __Pyx_c_pow_float(a, b) (::std::pow(a, b)) #endif #else #define __Pyx_c_is_zero_float(z) ((z)==0) #define __Pyx_c_conj_float(z) (conjf(z)) #if 1 #define __Pyx_c_abs_float(z) (cabsf(z)) #define __Pyx_c_pow_float(a, b) (cpowf(a, b)) #endif #endif #else static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex, __pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex); static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex); #if 1 static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex); static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex, __pyx_t_float_complex); #endif #endif /* Arithmetic.proto */ #if CYTHON_CCOMPLEX #define __Pyx_c_eq_double(a, b) ((a)==(b)) #define __Pyx_c_sum_double(a, b) ((a)+(b)) #define __Pyx_c_diff_double(a, b) ((a)-(b)) #define __Pyx_c_prod_double(a, b) ((a)*(b)) #define __Pyx_c_quot_double(a, b) ((a)/(b)) #define __Pyx_c_neg_double(a) (-(a)) #ifdef __cplusplus #define __Pyx_c_is_zero_double(z) ((z)==(double)0) #define __Pyx_c_conj_double(z) (::std::conj(z)) #if 1 #define __Pyx_c_abs_double(z) (::std::abs(z)) #define __Pyx_c_pow_double(a, b) (::std::pow(a, b)) #endif #else #define __Pyx_c_is_zero_double(z) ((z)==0) #define __Pyx_c_conj_double(z) (conj(z)) #if 1 #define __Pyx_c_abs_double(z) (cabs(z)) #define __Pyx_c_pow_double(a, b) (cpow(a, b)) #endif #endif #else static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex, __pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex); static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex); #if 1 static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex); static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex, __pyx_t_double_complex); #endif #endif /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__NPY_TYPES(enum NPY_TYPES value); /* CIntFromPy.proto */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); /* CIntFromPy.proto */ static CYTHON_INLINE unsigned int __Pyx_PyInt_As_unsigned_int(PyObject *); /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); /* CIntFromPy.proto */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); /* FastTypeChecks.proto */ #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); #else #define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) #define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) #define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) #endif #define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) /* CheckBinaryVersion.proto */ static int __Pyx_check_binary_version(void); /* InitStrings.proto */ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /* Module declarations from 'cpython.buffer' */ /* Module declarations from 'libc.string' */ /* Module declarations from 'libc.stdio' */ /* Module declarations from '__builtin__' */ /* Module declarations from 'cpython.type' */ static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0; /* Module declarations from 'cpython.version' */ /* Module declarations from 'cpython.exc' */ /* Module declarations from 'cpython.module' */ /* Module declarations from 'cpython.mem' */ /* Module declarations from 'cpython.tuple' */ /* Module declarations from 'cpython.list' */ /* Module declarations from 'cpython.sequence' */ /* Module declarations from 'cpython.mapping' */ /* Module declarations from 'cpython.iterator' */ /* Module declarations from 'cpython.number' */ /* Module declarations from 'cpython.int' */ /* Module declarations from '__builtin__' */ /* Module declarations from 'cpython.bool' */ static PyTypeObject *__pyx_ptype_7cpython_4bool_bool = 0; /* Module declarations from 'cpython.long' */ /* Module declarations from 'cpython.float' */ /* Module declarations from '__builtin__' */ /* Module declarations from 'cpython.complex' */ static PyTypeObject *__pyx_ptype_7cpython_7complex_complex = 0; /* Module declarations from 'cpython.string' */ /* Module declarations from 'cpython.unicode' */ /* Module declarations from 'cpython.dict' */ /* Module declarations from 'cpython.instance' */ /* Module declarations from 'cpython.function' */ /* Module declarations from 'cpython.method' */ /* Module declarations from 'cpython.weakref' */ /* Module declarations from 'cpython.getargs' */ /* Module declarations from 'cpython.pythread' */ /* Module declarations from 'cpython.pystate' */ /* Module declarations from 'cpython.cobject' */ /* Module declarations from 'cpython.oldbuffer' */ /* Module declarations from 'cpython.set' */ /* Module declarations from 'cpython.bytes' */ /* Module declarations from 'cpython.pycapsule' */ /* Module declarations from 'cpython' */ /* Module declarations from 'cpython.object' */ /* Module declarations from 'cpython.ref' */ /* Module declarations from 'numpy' */ /* Module declarations from 'numpy' */ static PyTypeObject *__pyx_ptype_5numpy_dtype = 0; static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0; static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0; static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0; static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0; static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); /*proto*/ /* Module declarations from 'cython' */ /* Module declarations from 'photutils.geometry.rectangular_overlap' */ static double __pyx_f_9photutils_8geometry_19rectangular_overlap_rectangular_overlap_single_subpixel(double, double, double, double, double, double, double, int); /*proto*/ static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_9photutils_8geometry_19rectangular_overlap_DTYPE_t = { "DTYPE_t", NULL, sizeof(__pyx_t_9photutils_8geometry_19rectangular_overlap_DTYPE_t), { 0 }, 0, 'R', 0, 0 }; #define __Pyx_MODULE_NAME "photutils.geometry.rectangular_overlap" extern int __pyx_module_is_main_photutils__geometry__rectangular_overlap; int __pyx_module_is_main_photutils__geometry__rectangular_overlap = 0; /* Implementation of 'photutils.geometry.rectangular_overlap' */ static PyObject *__pyx_builtin_NotImplementedError; static PyObject *__pyx_builtin_range; static PyObject *__pyx_builtin_ValueError; static PyObject *__pyx_builtin_RuntimeError; static PyObject *__pyx_builtin_ImportError; static const char __pyx_k_i[] = "i"; static const char __pyx_k_j[] = "j"; static const char __pyx_k_x[] = "x"; static const char __pyx_k_y[] = "y"; static const char __pyx_k_dx[] = "dx"; static const char __pyx_k_dy[] = "dy"; static const char __pyx_k_np[] = "np"; static const char __pyx_k_nx[] = "nx"; static const char __pyx_k_ny[] = "ny"; static const char __pyx_k_all[] = "__all__"; static const char __pyx_k_frac[] = "frac"; static const char __pyx_k_main[] = "__main__"; static const char __pyx_k_name[] = "__name__"; static const char __pyx_k_test[] = "__test__"; static const char __pyx_k_xmax[] = "xmax"; static const char __pyx_k_xmin[] = "xmin"; static const char __pyx_k_ymax[] = "ymax"; static const char __pyx_k_ymin[] = "ymin"; static const char __pyx_k_DTYPE[] = "DTYPE"; static const char __pyx_k_dtype[] = "dtype"; static const char __pyx_k_numpy[] = "numpy"; static const char __pyx_k_pxmax[] = "pxmax"; static const char __pyx_k_pxmin[] = "pxmin"; static const char __pyx_k_pymax[] = "pymax"; static const char __pyx_k_pymin[] = "pymin"; static const char __pyx_k_range[] = "range"; static const char __pyx_k_theta[] = "theta"; static const char __pyx_k_width[] = "width"; static const char __pyx_k_zeros[] = "zeros"; static const char __pyx_k_height[] = "height"; static const char __pyx_k_import[] = "__import__"; static const char __pyx_k_float64[] = "float64"; static const char __pyx_k_subpixels[] = "subpixels"; static const char __pyx_k_use_exact[] = "use_exact"; static const char __pyx_k_ValueError[] = "ValueError"; static const char __pyx_k_ImportError[] = "ImportError"; static const char __pyx_k_RuntimeError[] = "RuntimeError"; static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; static const char __pyx_k_NotImplementedError[] = "NotImplementedError"; static const char __pyx_k_rectangular_overlap_grid[] = "rectangular_overlap_grid"; static const char __pyx_k_ndarray_is_not_C_contiguous[] = "ndarray is not C contiguous"; static const char __pyx_k_This_module_provides_tools_to_c[] = "\nThis module provides tools to calculate the area of overlap between a\nrectangle and a pixel grid.\n"; static const char __pyx_k_numpy_core_multiarray_failed_to[] = "numpy.core.multiarray failed to import"; static const char __pyx_k_unknown_dtype_code_in_numpy_pxd[] = "unknown dtype code in numpy.pxd (%d)"; static const char __pyx_k_Exact_mode_has_not_been_implemen[] = "Exact mode has not been implemented for rectangular apertures"; static const char __pyx_k_Format_string_allocated_too_shor[] = "Format string allocated too short, see comment in numpy.pxd"; static const char __pyx_k_Non_native_byte_order_not_suppor[] = "Non-native byte order not supported"; static const char __pyx_k_ndarray_is_not_Fortran_contiguou[] = "ndarray is not Fortran contiguous"; static const char __pyx_k_numpy_core_umath_failed_to_impor[] = "numpy.core.umath failed to import"; static const char __pyx_k_photutils_geometry_rectangular_o[] = "photutils/geometry/rectangular_overlap.pyx"; static const char __pyx_k_Format_string_allocated_too_shor_2[] = "Format string allocated too short."; static const char __pyx_k_photutils_geometry_rectangular_o_2[] = "photutils.geometry.rectangular_overlap"; static PyObject *__pyx_n_s_DTYPE; static PyObject *__pyx_kp_u_Exact_mode_has_not_been_implemen; static PyObject *__pyx_kp_u_Format_string_allocated_too_shor; static PyObject *__pyx_kp_u_Format_string_allocated_too_shor_2; static PyObject *__pyx_n_s_ImportError; static PyObject *__pyx_kp_u_Non_native_byte_order_not_suppor; static PyObject *__pyx_n_s_NotImplementedError; static PyObject *__pyx_n_s_RuntimeError; static PyObject *__pyx_n_s_ValueError; static PyObject *__pyx_n_s_all; static PyObject *__pyx_n_s_cline_in_traceback; static PyObject *__pyx_n_s_dtype; static PyObject *__pyx_n_s_dx; static PyObject *__pyx_n_s_dy; static PyObject *__pyx_n_s_float64; static PyObject *__pyx_n_s_frac; static PyObject *__pyx_n_s_height; static PyObject *__pyx_n_s_i; static PyObject *__pyx_n_s_import; static PyObject *__pyx_n_s_j; static PyObject *__pyx_n_s_main; static PyObject *__pyx_n_s_name; static PyObject *__pyx_kp_u_ndarray_is_not_C_contiguous; static PyObject *__pyx_kp_u_ndarray_is_not_Fortran_contiguou; static PyObject *__pyx_n_s_np; static PyObject *__pyx_n_s_numpy; static PyObject *__pyx_kp_u_numpy_core_multiarray_failed_to; static PyObject *__pyx_kp_u_numpy_core_umath_failed_to_impor; static PyObject *__pyx_n_s_nx; static PyObject *__pyx_n_s_ny; static PyObject *__pyx_kp_s_photutils_geometry_rectangular_o; static PyObject *__pyx_n_s_photutils_geometry_rectangular_o_2; static PyObject *__pyx_n_s_pxmax; static PyObject *__pyx_n_s_pxmin; static PyObject *__pyx_n_s_pymax; static PyObject *__pyx_n_s_pymin; static PyObject *__pyx_n_s_range; static PyObject *__pyx_n_s_rectangular_overlap_grid; static PyObject *__pyx_n_u_rectangular_overlap_grid; static PyObject *__pyx_n_s_subpixels; static PyObject *__pyx_n_s_test; static PyObject *__pyx_n_s_theta; static PyObject *__pyx_kp_u_unknown_dtype_code_in_numpy_pxd; static PyObject *__pyx_n_s_use_exact; static PyObject *__pyx_n_s_width; static PyObject *__pyx_n_s_x; static PyObject *__pyx_n_s_xmax; static PyObject *__pyx_n_s_xmin; static PyObject *__pyx_n_s_y; static PyObject *__pyx_n_s_ymax; static PyObject *__pyx_n_s_ymin; static PyObject *__pyx_n_s_zeros; static PyObject *__pyx_pf_9photutils_8geometry_19rectangular_overlap_rectangular_overlap_grid(CYTHON_UNUSED PyObject *__pyx_self, double __pyx_v_xmin, double __pyx_v_xmax, double __pyx_v_ymin, double __pyx_v_ymax, int __pyx_v_nx, int __pyx_v_ny, double __pyx_v_width, double __pyx_v_height, double __pyx_v_theta, int __pyx_v_use_exact, int __pyx_v_subpixels); /* proto */ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info); /* proto */ static PyObject *__pyx_tuple_; static PyObject *__pyx_tuple__2; static PyObject *__pyx_tuple__3; static PyObject *__pyx_tuple__4; static PyObject *__pyx_tuple__5; static PyObject *__pyx_tuple__6; static PyObject *__pyx_tuple__7; static PyObject *__pyx_tuple__8; static PyObject *__pyx_tuple__9; static PyObject *__pyx_codeobj__10; /* Late includes */ /* "photutils/geometry/rectangular_overlap.pyx":30 * * * def rectangular_overlap_grid(double xmin, double xmax, double ymin, # <<<<<<<<<<<<<< * double ymax, int nx, int ny, double width, * double height, double theta, int use_exact, */ /* Python wrapper */ static PyObject *__pyx_pw_9photutils_8geometry_19rectangular_overlap_1rectangular_overlap_grid(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static char __pyx_doc_9photutils_8geometry_19rectangular_overlap_rectangular_overlap_grid[] = "\n rectangular_overlap_grid(xmin, xmax, ymin, ymax, nx, ny, width, height,\n use_exact, subpixels)\n\n Area of overlap between a rectangle and a pixel grid. The rectangle is\n centered on the origin.\n\n Parameters\n ----------\n xmin, xmax, ymin, ymax : float\n Extent of the grid in the x and y direction.\n nx, ny : int\n Grid dimensions.\n width : float\n The width of the rectangle\n height : float\n The height of the rectangle\n theta : float\n The position angle of the rectangle in radians (counterclockwise).\n use_exact : 0 or 1\n If set to 1, calculates the exact overlap, while if set to 0, uses a\n subpixel sampling method with ``subpixel`` subpixels in each direction.\n subpixels : int\n If ``use_exact`` is 0, each pixel is resampled by this factor in each\n dimension. Thus, each pixel is divided into ``subpixels ** 2``\n subpixels.\n\n Returns\n -------\n frac : `~numpy.ndarray`\n 2-d array giving the fraction of the overlap.\n "; static PyMethodDef __pyx_mdef_9photutils_8geometry_19rectangular_overlap_1rectangular_overlap_grid = {"rectangular_overlap_grid", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9photutils_8geometry_19rectangular_overlap_1rectangular_overlap_grid, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9photutils_8geometry_19rectangular_overlap_rectangular_overlap_grid}; static PyObject *__pyx_pw_9photutils_8geometry_19rectangular_overlap_1rectangular_overlap_grid(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { double __pyx_v_xmin; double __pyx_v_xmax; double __pyx_v_ymin; double __pyx_v_ymax; int __pyx_v_nx; int __pyx_v_ny; double __pyx_v_width; double __pyx_v_height; double __pyx_v_theta; int __pyx_v_use_exact; int __pyx_v_subpixels; PyObject *__pyx_r = 0; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("rectangular_overlap_grid (wrapper)", 0); { static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_xmin,&__pyx_n_s_xmax,&__pyx_n_s_ymin,&__pyx_n_s_ymax,&__pyx_n_s_nx,&__pyx_n_s_ny,&__pyx_n_s_width,&__pyx_n_s_height,&__pyx_n_s_theta,&__pyx_n_s_use_exact,&__pyx_n_s_subpixels,0}; PyObject* values[11] = {0,0,0,0,0,0,0,0,0,0,0}; if (unlikely(__pyx_kwds)) { Py_ssize_t kw_args; const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); switch (pos_args) { case 11: values[10] = PyTuple_GET_ITEM(__pyx_args, 10); CYTHON_FALLTHROUGH; case 10: values[9] = PyTuple_GET_ITEM(__pyx_args, 9); CYTHON_FALLTHROUGH; case 9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8); CYTHON_FALLTHROUGH; case 8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7); CYTHON_FALLTHROUGH; case 7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6); CYTHON_FALLTHROUGH; case 6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5); CYTHON_FALLTHROUGH; case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); CYTHON_FALLTHROUGH; case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); CYTHON_FALLTHROUGH; case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); CYTHON_FALLTHROUGH; case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); CYTHON_FALLTHROUGH; case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); CYTHON_FALLTHROUGH; case 0: break; default: goto __pyx_L5_argtuple_error; } kw_args = PyDict_Size(__pyx_kwds); switch (pos_args) { case 0: if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_xmin)) != 0)) kw_args--; else goto __pyx_L5_argtuple_error; CYTHON_FALLTHROUGH; case 1: if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_xmax)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("rectangular_overlap_grid", 1, 11, 11, 1); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 2: if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ymin)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("rectangular_overlap_grid", 1, 11, 11, 2); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 3: if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ymax)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("rectangular_overlap_grid", 1, 11, 11, 3); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 4: if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_nx)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("rectangular_overlap_grid", 1, 11, 11, 4); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 5: if (likely((values[5] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ny)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("rectangular_overlap_grid", 1, 11, 11, 5); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 6: if (likely((values[6] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_width)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("rectangular_overlap_grid", 1, 11, 11, 6); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 7: if (likely((values[7] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_height)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("rectangular_overlap_grid", 1, 11, 11, 7); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 8: if (likely((values[8] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_theta)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("rectangular_overlap_grid", 1, 11, 11, 8); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 9: if (likely((values[9] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_use_exact)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("rectangular_overlap_grid", 1, 11, 11, 9); __PYX_ERR(0, 30, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 10: if (likely((values[10] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_subpixels)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("rectangular_overlap_grid", 1, 11, 11, 10); __PYX_ERR(0, 30, __pyx_L3_error) } } if (unlikely(kw_args > 0)) { if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "rectangular_overlap_grid") < 0)) __PYX_ERR(0, 30, __pyx_L3_error) } } else if (PyTuple_GET_SIZE(__pyx_args) != 11) { goto __pyx_L5_argtuple_error; } else { values[0] = PyTuple_GET_ITEM(__pyx_args, 0); values[1] = PyTuple_GET_ITEM(__pyx_args, 1); values[2] = PyTuple_GET_ITEM(__pyx_args, 2); values[3] = PyTuple_GET_ITEM(__pyx_args, 3); values[4] = PyTuple_GET_ITEM(__pyx_args, 4); values[5] = PyTuple_GET_ITEM(__pyx_args, 5); values[6] = PyTuple_GET_ITEM(__pyx_args, 6); values[7] = PyTuple_GET_ITEM(__pyx_args, 7); values[8] = PyTuple_GET_ITEM(__pyx_args, 8); values[9] = PyTuple_GET_ITEM(__pyx_args, 9); values[10] = PyTuple_GET_ITEM(__pyx_args, 10); } __pyx_v_xmin = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_xmin == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 30, __pyx_L3_error) __pyx_v_xmax = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_xmax == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 30, __pyx_L3_error) __pyx_v_ymin = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_ymin == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 30, __pyx_L3_error) __pyx_v_ymax = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_ymax == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 31, __pyx_L3_error) __pyx_v_nx = __Pyx_PyInt_As_int(values[4]); if (unlikely((__pyx_v_nx == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 31, __pyx_L3_error) __pyx_v_ny = __Pyx_PyInt_As_int(values[5]); if (unlikely((__pyx_v_ny == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 31, __pyx_L3_error) __pyx_v_width = __pyx_PyFloat_AsDouble(values[6]); if (unlikely((__pyx_v_width == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 31, __pyx_L3_error) __pyx_v_height = __pyx_PyFloat_AsDouble(values[7]); if (unlikely((__pyx_v_height == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 32, __pyx_L3_error) __pyx_v_theta = __pyx_PyFloat_AsDouble(values[8]); if (unlikely((__pyx_v_theta == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 32, __pyx_L3_error) __pyx_v_use_exact = __Pyx_PyInt_As_int(values[9]); if (unlikely((__pyx_v_use_exact == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 32, __pyx_L3_error) __pyx_v_subpixels = __Pyx_PyInt_As_int(values[10]); if (unlikely((__pyx_v_subpixels == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 33, __pyx_L3_error) } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; __Pyx_RaiseArgtupleInvalid("rectangular_overlap_grid", 1, 11, 11, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 30, __pyx_L3_error) __pyx_L3_error:; __Pyx_AddTraceback("photutils.geometry.rectangular_overlap.rectangular_overlap_grid", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; __pyx_r = __pyx_pf_9photutils_8geometry_19rectangular_overlap_rectangular_overlap_grid(__pyx_self, __pyx_v_xmin, __pyx_v_xmax, __pyx_v_ymin, __pyx_v_ymax, __pyx_v_nx, __pyx_v_ny, __pyx_v_width, __pyx_v_height, __pyx_v_theta, __pyx_v_use_exact, __pyx_v_subpixels); /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } static PyObject *__pyx_pf_9photutils_8geometry_19rectangular_overlap_rectangular_overlap_grid(CYTHON_UNUSED PyObject *__pyx_self, double __pyx_v_xmin, double __pyx_v_xmax, double __pyx_v_ymin, double __pyx_v_ymax, int __pyx_v_nx, int __pyx_v_ny, double __pyx_v_width, double __pyx_v_height, double __pyx_v_theta, int __pyx_v_use_exact, int __pyx_v_subpixels) { unsigned int __pyx_v_i; unsigned int __pyx_v_j; double __pyx_v_dx; double __pyx_v_dy; double __pyx_v_pxmin; double __pyx_v_pxmax; double __pyx_v_pymin; double __pyx_v_pymax; PyArrayObject *__pyx_v_frac = 0; __Pyx_LocalBuf_ND __pyx_pybuffernd_frac; __Pyx_Buffer __pyx_pybuffer_frac; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; PyArrayObject *__pyx_t_5 = NULL; int __pyx_t_6; double __pyx_t_7; int __pyx_t_8; int __pyx_t_9; unsigned int __pyx_t_10; int __pyx_t_11; int __pyx_t_12; unsigned int __pyx_t_13; size_t __pyx_t_14; size_t __pyx_t_15; int __pyx_t_16; __Pyx_RefNannySetupContext("rectangular_overlap_grid", 0); __pyx_pybuffer_frac.pybuffer.buf = NULL; __pyx_pybuffer_frac.refcount = 0; __pyx_pybuffernd_frac.data = NULL; __pyx_pybuffernd_frac.rcbuffer = &__pyx_pybuffer_frac; /* "photutils/geometry/rectangular_overlap.pyx":72 * * # Define output array * cdef np.ndarray[DTYPE_t, ndim=2] frac = np.zeros([ny, nx], dtype=DTYPE) # <<<<<<<<<<<<<< * * if use_exact == 1: */ __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_ny); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_nx); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyList_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_GIVEREF(__pyx_t_1); PyList_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); __Pyx_GIVEREF(__pyx_t_3); PyList_SET_ITEM(__pyx_t_4, 1, __pyx_t_3); __pyx_t_1 = 0; __pyx_t_3 = 0; __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); __pyx_t_4 = 0; __pyx_t_4 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_DTYPE); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_dtype, __pyx_t_1) < 0) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 72, __pyx_L1_error) __pyx_t_5 = ((PyArrayObject *)__pyx_t_1); { __Pyx_BufFmt_StackElem __pyx_stack[1]; if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_frac.rcbuffer->pybuffer, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_9photutils_8geometry_19rectangular_overlap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { __pyx_v_frac = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_frac.rcbuffer->pybuffer.buf = NULL; __PYX_ERR(0, 72, __pyx_L1_error) } else {__pyx_pybuffernd_frac.diminfo[0].strides = __pyx_pybuffernd_frac.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_frac.diminfo[0].shape = __pyx_pybuffernd_frac.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_frac.diminfo[1].strides = __pyx_pybuffernd_frac.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_frac.diminfo[1].shape = __pyx_pybuffernd_frac.rcbuffer->pybuffer.shape[1]; } } __pyx_t_5 = 0; __pyx_v_frac = ((PyArrayObject *)__pyx_t_1); __pyx_t_1 = 0; /* "photutils/geometry/rectangular_overlap.pyx":74 * cdef np.ndarray[DTYPE_t, ndim=2] frac = np.zeros([ny, nx], dtype=DTYPE) * * if use_exact == 1: # <<<<<<<<<<<<<< * raise NotImplementedError("Exact mode has not been implemented for " * "rectangular apertures") */ __pyx_t_6 = ((__pyx_v_use_exact == 1) != 0); if (unlikely(__pyx_t_6)) { /* "photutils/geometry/rectangular_overlap.pyx":75 * * if use_exact == 1: * raise NotImplementedError("Exact mode has not been implemented for " # <<<<<<<<<<<<<< * "rectangular apertures") * */ __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_NotImplementedError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 75, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __PYX_ERR(0, 75, __pyx_L1_error) /* "photutils/geometry/rectangular_overlap.pyx":74 * cdef np.ndarray[DTYPE_t, ndim=2] frac = np.zeros([ny, nx], dtype=DTYPE) * * if use_exact == 1: # <<<<<<<<<<<<<< * raise NotImplementedError("Exact mode has not been implemented for " * "rectangular apertures") */ } /* "photutils/geometry/rectangular_overlap.pyx":79 * * # Find the width of each element in x and y * dx = (xmax - xmin) / nx # <<<<<<<<<<<<<< * dy = (ymax - ymin) / ny * */ __pyx_t_7 = (__pyx_v_xmax - __pyx_v_xmin); if (unlikely(__pyx_v_nx == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 79, __pyx_L1_error) } __pyx_v_dx = (__pyx_t_7 / ((double)__pyx_v_nx)); /* "photutils/geometry/rectangular_overlap.pyx":80 * # Find the width of each element in x and y * dx = (xmax - xmin) / nx * dy = (ymax - ymin) / ny # <<<<<<<<<<<<<< * * # TODO: can implement a bounding box here for efficiency (as for the */ __pyx_t_7 = (__pyx_v_ymax - __pyx_v_ymin); if (unlikely(__pyx_v_ny == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 80, __pyx_L1_error) } __pyx_v_dy = (__pyx_t_7 / ((double)__pyx_v_ny)); /* "photutils/geometry/rectangular_overlap.pyx":85 * # circular and elliptical aperture photometry) * * for i in range(nx): # <<<<<<<<<<<<<< * pxmin = xmin + i * dx # lower end of pixel * pxmax = pxmin + dx # upper end of pixel */ __pyx_t_8 = __pyx_v_nx; __pyx_t_9 = __pyx_t_8; for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) { __pyx_v_i = __pyx_t_10; /* "photutils/geometry/rectangular_overlap.pyx":86 * * for i in range(nx): * pxmin = xmin + i * dx # lower end of pixel # <<<<<<<<<<<<<< * pxmax = pxmin + dx # upper end of pixel * for j in range(ny): */ __pyx_v_pxmin = (__pyx_v_xmin + (__pyx_v_i * __pyx_v_dx)); /* "photutils/geometry/rectangular_overlap.pyx":87 * for i in range(nx): * pxmin = xmin + i * dx # lower end of pixel * pxmax = pxmin + dx # upper end of pixel # <<<<<<<<<<<<<< * for j in range(ny): * pymin = ymin + j * dy */ __pyx_v_pxmax = (__pyx_v_pxmin + __pyx_v_dx); /* "photutils/geometry/rectangular_overlap.pyx":88 * pxmin = xmin + i * dx # lower end of pixel * pxmax = pxmin + dx # upper end of pixel * for j in range(ny): # <<<<<<<<<<<<<< * pymin = ymin + j * dy * pymax = pymin + dy */ __pyx_t_11 = __pyx_v_ny; __pyx_t_12 = __pyx_t_11; for (__pyx_t_13 = 0; __pyx_t_13 < __pyx_t_12; __pyx_t_13+=1) { __pyx_v_j = __pyx_t_13; /* "photutils/geometry/rectangular_overlap.pyx":89 * pxmax = pxmin + dx # upper end of pixel * for j in range(ny): * pymin = ymin + j * dy # <<<<<<<<<<<<<< * pymax = pymin + dy * frac[j, i] = rectangular_overlap_single_subpixel( */ __pyx_v_pymin = (__pyx_v_ymin + (__pyx_v_j * __pyx_v_dy)); /* "photutils/geometry/rectangular_overlap.pyx":90 * for j in range(ny): * pymin = ymin + j * dy * pymax = pymin + dy # <<<<<<<<<<<<<< * frac[j, i] = rectangular_overlap_single_subpixel( * pxmin, pymin, pxmax, pymax, width, height, theta, */ __pyx_v_pymax = (__pyx_v_pymin + __pyx_v_dy); /* "photutils/geometry/rectangular_overlap.pyx":91 * pymin = ymin + j * dy * pymax = pymin + dy * frac[j, i] = rectangular_overlap_single_subpixel( # <<<<<<<<<<<<<< * pxmin, pymin, pxmax, pymax, width, height, theta, * subpixels) */ __pyx_t_14 = __pyx_v_j; __pyx_t_15 = __pyx_v_i; __pyx_t_16 = -1; if (unlikely(__pyx_t_14 >= (size_t)__pyx_pybuffernd_frac.diminfo[0].shape)) __pyx_t_16 = 0; if (unlikely(__pyx_t_15 >= (size_t)__pyx_pybuffernd_frac.diminfo[1].shape)) __pyx_t_16 = 1; if (unlikely(__pyx_t_16 != -1)) { __Pyx_RaiseBufferIndexError(__pyx_t_16); __PYX_ERR(0, 91, __pyx_L1_error) } *__Pyx_BufPtrStrided2d(__pyx_t_9photutils_8geometry_19rectangular_overlap_DTYPE_t *, __pyx_pybuffernd_frac.rcbuffer->pybuffer.buf, __pyx_t_14, __pyx_pybuffernd_frac.diminfo[0].strides, __pyx_t_15, __pyx_pybuffernd_frac.diminfo[1].strides) = __pyx_f_9photutils_8geometry_19rectangular_overlap_rectangular_overlap_single_subpixel(__pyx_v_pxmin, __pyx_v_pymin, __pyx_v_pxmax, __pyx_v_pymax, __pyx_v_width, __pyx_v_height, __pyx_v_theta, __pyx_v_subpixels); } } /* "photutils/geometry/rectangular_overlap.pyx":95 * subpixels) * * return frac # <<<<<<<<<<<<<< * * */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(((PyObject *)__pyx_v_frac)); __pyx_r = ((PyObject *)__pyx_v_frac); goto __pyx_L0; /* "photutils/geometry/rectangular_overlap.pyx":30 * * * def rectangular_overlap_grid(double xmin, double xmax, double ymin, # <<<<<<<<<<<<<< * double ymax, int nx, int ny, double width, * double height, double theta, int use_exact, */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_frac.rcbuffer->pybuffer); __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} __Pyx_AddTraceback("photutils.geometry.rectangular_overlap.rectangular_overlap_grid", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; goto __pyx_L2; __pyx_L0:; __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_frac.rcbuffer->pybuffer); __pyx_L2:; __Pyx_XDECREF((PyObject *)__pyx_v_frac); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "photutils/geometry/rectangular_overlap.pyx":98 * * * cdef double rectangular_overlap_single_subpixel(double x0, double y0, # <<<<<<<<<<<<<< * double x1, double y1, * double width, double height, */ static double __pyx_f_9photutils_8geometry_19rectangular_overlap_rectangular_overlap_single_subpixel(double __pyx_v_x0, double __pyx_v_y0, double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_width, double __pyx_v_height, double __pyx_v_theta, int __pyx_v_subpixels) { CYTHON_UNUSED unsigned int __pyx_v_i; CYTHON_UNUSED unsigned int __pyx_v_j; double __pyx_v_x; double __pyx_v_y; double __pyx_v_frac; double __pyx_v_cos_theta; double __pyx_v_sin_theta; double __pyx_v_half_width; double __pyx_v_half_height; double __pyx_v_dx; double __pyx_v_dy; double __pyx_v_x_tr; double __pyx_v_y_tr; double __pyx_r; __Pyx_RefNannyDeclarations double __pyx_t_1; int __pyx_t_2; int __pyx_t_3; unsigned int __pyx_t_4; int __pyx_t_5; int __pyx_t_6; unsigned int __pyx_t_7; int __pyx_t_8; int __pyx_t_9; __Pyx_RefNannySetupContext("rectangular_overlap_single_subpixel", 0); /* "photutils/geometry/rectangular_overlap.pyx":109 * cdef unsigned int i, j * cdef double x, y * cdef double frac = 0. # Accumulator. # <<<<<<<<<<<<<< * cdef double cos_theta = cos(theta) * cdef double sin_theta = sin(theta) */ __pyx_v_frac = 0.; /* "photutils/geometry/rectangular_overlap.pyx":110 * cdef double x, y * cdef double frac = 0. # Accumulator. * cdef double cos_theta = cos(theta) # <<<<<<<<<<<<<< * cdef double sin_theta = sin(theta) * cdef double half_width, half_height */ __pyx_v_cos_theta = cos(__pyx_v_theta); /* "photutils/geometry/rectangular_overlap.pyx":111 * cdef double frac = 0. # Accumulator. * cdef double cos_theta = cos(theta) * cdef double sin_theta = sin(theta) # <<<<<<<<<<<<<< * cdef double half_width, half_height * */ __pyx_v_sin_theta = sin(__pyx_v_theta); /* "photutils/geometry/rectangular_overlap.pyx":114 * cdef double half_width, half_height * * half_width = width / 2. # <<<<<<<<<<<<<< * half_height = height / 2. * */ __pyx_v_half_width = (__pyx_v_width / 2.); /* "photutils/geometry/rectangular_overlap.pyx":115 * * half_width = width / 2. * half_height = height / 2. # <<<<<<<<<<<<<< * * dx = (x1 - x0) / subpixels */ __pyx_v_half_height = (__pyx_v_height / 2.); /* "photutils/geometry/rectangular_overlap.pyx":117 * half_height = height / 2. * * dx = (x1 - x0) / subpixels # <<<<<<<<<<<<<< * dy = (y1 - y0) / subpixels * */ __pyx_t_1 = (__pyx_v_x1 - __pyx_v_x0); if (unlikely(__pyx_v_subpixels == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 117, __pyx_L1_error) } __pyx_v_dx = (__pyx_t_1 / ((double)__pyx_v_subpixels)); /* "photutils/geometry/rectangular_overlap.pyx":118 * * dx = (x1 - x0) / subpixels * dy = (y1 - y0) / subpixels # <<<<<<<<<<<<<< * * x = x0 - 0.5 * dx */ __pyx_t_1 = (__pyx_v_y1 - __pyx_v_y0); if (unlikely(__pyx_v_subpixels == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 118, __pyx_L1_error) } __pyx_v_dy = (__pyx_t_1 / ((double)__pyx_v_subpixels)); /* "photutils/geometry/rectangular_overlap.pyx":120 * dy = (y1 - y0) / subpixels * * x = x0 - 0.5 * dx # <<<<<<<<<<<<<< * for i in range(subpixels): * x += dx */ __pyx_v_x = (__pyx_v_x0 - (0.5 * __pyx_v_dx)); /* "photutils/geometry/rectangular_overlap.pyx":121 * * x = x0 - 0.5 * dx * for i in range(subpixels): # <<<<<<<<<<<<<< * x += dx * y = y0 - 0.5 * dy */ __pyx_t_2 = __pyx_v_subpixels; __pyx_t_3 = __pyx_t_2; for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { __pyx_v_i = __pyx_t_4; /* "photutils/geometry/rectangular_overlap.pyx":122 * x = x0 - 0.5 * dx * for i in range(subpixels): * x += dx # <<<<<<<<<<<<<< * y = y0 - 0.5 * dy * for j in range(subpixels): */ __pyx_v_x = (__pyx_v_x + __pyx_v_dx); /* "photutils/geometry/rectangular_overlap.pyx":123 * for i in range(subpixels): * x += dx * y = y0 - 0.5 * dy # <<<<<<<<<<<<<< * for j in range(subpixels): * y += dy */ __pyx_v_y = (__pyx_v_y0 - (0.5 * __pyx_v_dy)); /* "photutils/geometry/rectangular_overlap.pyx":124 * x += dx * y = y0 - 0.5 * dy * for j in range(subpixels): # <<<<<<<<<<<<<< * y += dy * */ __pyx_t_5 = __pyx_v_subpixels; __pyx_t_6 = __pyx_t_5; for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_6; __pyx_t_7+=1) { __pyx_v_j = __pyx_t_7; /* "photutils/geometry/rectangular_overlap.pyx":125 * y = y0 - 0.5 * dy * for j in range(subpixels): * y += dy # <<<<<<<<<<<<<< * * # Transform into frame of rotated rectangle */ __pyx_v_y = (__pyx_v_y + __pyx_v_dy); /* "photutils/geometry/rectangular_overlap.pyx":128 * * # Transform into frame of rotated rectangle * x_tr = y * sin_theta + x * cos_theta # <<<<<<<<<<<<<< * y_tr = y * cos_theta - x * sin_theta * */ __pyx_v_x_tr = ((__pyx_v_y * __pyx_v_sin_theta) + (__pyx_v_x * __pyx_v_cos_theta)); /* "photutils/geometry/rectangular_overlap.pyx":129 * # Transform into frame of rotated rectangle * x_tr = y * sin_theta + x * cos_theta * y_tr = y * cos_theta - x * sin_theta # <<<<<<<<<<<<<< * * if fabs(x_tr) < half_width and fabs(y_tr) < half_height: */ __pyx_v_y_tr = ((__pyx_v_y * __pyx_v_cos_theta) - (__pyx_v_x * __pyx_v_sin_theta)); /* "photutils/geometry/rectangular_overlap.pyx":131 * y_tr = y * cos_theta - x * sin_theta * * if fabs(x_tr) < half_width and fabs(y_tr) < half_height: # <<<<<<<<<<<<<< * frac += 1. * */ __pyx_t_9 = ((fabs(__pyx_v_x_tr) < __pyx_v_half_width) != 0); if (__pyx_t_9) { } else { __pyx_t_8 = __pyx_t_9; goto __pyx_L8_bool_binop_done; } __pyx_t_9 = ((fabs(__pyx_v_y_tr) < __pyx_v_half_height) != 0); __pyx_t_8 = __pyx_t_9; __pyx_L8_bool_binop_done:; if (__pyx_t_8) { /* "photutils/geometry/rectangular_overlap.pyx":132 * * if fabs(x_tr) < half_width and fabs(y_tr) < half_height: * frac += 1. # <<<<<<<<<<<<<< * * return frac / (subpixels * subpixels) */ __pyx_v_frac = (__pyx_v_frac + 1.); /* "photutils/geometry/rectangular_overlap.pyx":131 * y_tr = y * cos_theta - x * sin_theta * * if fabs(x_tr) < half_width and fabs(y_tr) < half_height: # <<<<<<<<<<<<<< * frac += 1. * */ } } } /* "photutils/geometry/rectangular_overlap.pyx":134 * frac += 1. * * return frac / (subpixels * subpixels) # <<<<<<<<<<<<<< */ __pyx_t_2 = (__pyx_v_subpixels * __pyx_v_subpixels); if (unlikely(__pyx_t_2 == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "float division"); __PYX_ERR(0, 134, __pyx_L1_error) } __pyx_r = (__pyx_v_frac / ((double)__pyx_t_2)); goto __pyx_L0; /* "photutils/geometry/rectangular_overlap.pyx":98 * * * cdef double rectangular_overlap_single_subpixel(double x0, double y0, # <<<<<<<<<<<<<< * double x1, double y1, * double width, double height, */ /* function exit code */ __pyx_L1_error:; __Pyx_WriteUnraisable("photutils.geometry.rectangular_overlap.rectangular_overlap_single_subpixel", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0); __pyx_r = 0; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":258 * # experimental exception made for __getbuffer__ and __releasebuffer__ * # -- the details of this may change. * def __getbuffer__(ndarray self, Py_buffer* info, int flags): # <<<<<<<<<<<<<< * # This implementation of getbuffer is geared towards Cython * # requirements, and does not yet fulfill the PEP. */ /* Python wrapper */ static CYTHON_UNUSED int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ static CYTHON_UNUSED int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { int __pyx_r; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0); __pyx_r = __pyx_pf_5numpy_7ndarray___getbuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags)); /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { int __pyx_v_i; int __pyx_v_ndim; int __pyx_v_endian_detector; int __pyx_v_little_endian; int __pyx_v_t; char *__pyx_v_f; PyArray_Descr *__pyx_v_descr = 0; int __pyx_v_offset; int __pyx_r; __Pyx_RefNannyDeclarations int __pyx_t_1; int __pyx_t_2; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; int __pyx_t_5; int __pyx_t_6; PyArray_Descr *__pyx_t_7; PyObject *__pyx_t_8 = NULL; char *__pyx_t_9; if (__pyx_v_info == NULL) { PyErr_SetString(PyExc_BufferError, "PyObject_GetBuffer: view==NULL argument is obsolete"); return -1; } __Pyx_RefNannySetupContext("__getbuffer__", 0); __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None); __Pyx_GIVEREF(__pyx_v_info->obj); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":265 * * cdef int i, ndim * cdef int endian_detector = 1 # <<<<<<<<<<<<<< * cdef bint little_endian = ((&endian_detector)[0] != 0) * */ __pyx_v_endian_detector = 1; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":266 * cdef int i, ndim * cdef int endian_detector = 1 * cdef bint little_endian = ((&endian_detector)[0] != 0) # <<<<<<<<<<<<<< * * ndim = PyArray_NDIM(self) */ __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":268 * cdef bint little_endian = ((&endian_detector)[0] != 0) * * ndim = PyArray_NDIM(self) # <<<<<<<<<<<<<< * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) */ __pyx_v_ndim = PyArray_NDIM(__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":270 * ndim = PyArray_NDIM(self) * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") */ __pyx_t_2 = (((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L4_bool_binop_done; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":271 * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): # <<<<<<<<<<<<<< * raise ValueError(u"ndarray is not C contiguous") * */ __pyx_t_2 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_ARRAY_C_CONTIGUOUS) != 0)) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L4_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":270 * ndim = PyArray_NDIM(self) * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") */ if (unlikely(__pyx_t_1)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":272 * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") # <<<<<<<<<<<<<< * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 272, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 272, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":270 * ndim = PyArray_NDIM(self) * * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":274 * raise ValueError(u"ndarray is not C contiguous") * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") */ __pyx_t_2 = (((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L7_bool_binop_done; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":275 * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): # <<<<<<<<<<<<<< * raise ValueError(u"ndarray is not Fortran contiguous") * */ __pyx_t_2 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_ARRAY_F_CONTIGUOUS) != 0)) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L7_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":274 * raise ValueError(u"ndarray is not C contiguous") * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") */ if (unlikely(__pyx_t_1)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":276 * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") # <<<<<<<<<<<<<< * * info.buf = PyArray_DATA(self) */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 276, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 276, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":274 * raise ValueError(u"ndarray is not C contiguous") * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":278 * raise ValueError(u"ndarray is not Fortran contiguous") * * info.buf = PyArray_DATA(self) # <<<<<<<<<<<<<< * info.ndim = ndim * if sizeof(npy_intp) != sizeof(Py_ssize_t): */ __pyx_v_info->buf = PyArray_DATA(__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":279 * * info.buf = PyArray_DATA(self) * info.ndim = ndim # <<<<<<<<<<<<<< * if sizeof(npy_intp) != sizeof(Py_ssize_t): * # Allocate new buffer for strides and shape info. */ __pyx_v_info->ndim = __pyx_v_ndim; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":280 * info.buf = PyArray_DATA(self) * info.ndim = ndim * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * # Allocate new buffer for strides and shape info. * # This is allocated as one block, strides first. */ __pyx_t_1 = (((sizeof(npy_intp)) != (sizeof(Py_ssize_t))) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":283 * # Allocate new buffer for strides and shape info. * # This is allocated as one block, strides first. * info.strides = PyObject_Malloc(sizeof(Py_ssize_t) * 2 * ndim) # <<<<<<<<<<<<<< * info.shape = info.strides + ndim * for i in range(ndim): */ __pyx_v_info->strides = ((Py_ssize_t *)PyObject_Malloc((((sizeof(Py_ssize_t)) * 2) * ((size_t)__pyx_v_ndim)))); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":284 * # This is allocated as one block, strides first. * info.strides = PyObject_Malloc(sizeof(Py_ssize_t) * 2 * ndim) * info.shape = info.strides + ndim # <<<<<<<<<<<<<< * for i in range(ndim): * info.strides[i] = PyArray_STRIDES(self)[i] */ __pyx_v_info->shape = (__pyx_v_info->strides + __pyx_v_ndim); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":285 * info.strides = PyObject_Malloc(sizeof(Py_ssize_t) * 2 * ndim) * info.shape = info.strides + ndim * for i in range(ndim): # <<<<<<<<<<<<<< * info.strides[i] = PyArray_STRIDES(self)[i] * info.shape[i] = PyArray_DIMS(self)[i] */ __pyx_t_4 = __pyx_v_ndim; __pyx_t_5 = __pyx_t_4; for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { __pyx_v_i = __pyx_t_6; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":286 * info.shape = info.strides + ndim * for i in range(ndim): * info.strides[i] = PyArray_STRIDES(self)[i] # <<<<<<<<<<<<<< * info.shape[i] = PyArray_DIMS(self)[i] * else: */ (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(__pyx_v_self)[__pyx_v_i]); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":287 * for i in range(ndim): * info.strides[i] = PyArray_STRIDES(self)[i] * info.shape[i] = PyArray_DIMS(self)[i] # <<<<<<<<<<<<<< * else: * info.strides = PyArray_STRIDES(self) */ (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(__pyx_v_self)[__pyx_v_i]); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":280 * info.buf = PyArray_DATA(self) * info.ndim = ndim * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * # Allocate new buffer for strides and shape info. * # This is allocated as one block, strides first. */ goto __pyx_L9; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":289 * info.shape[i] = PyArray_DIMS(self)[i] * else: * info.strides = PyArray_STRIDES(self) # <<<<<<<<<<<<<< * info.shape = PyArray_DIMS(self) * info.suboffsets = NULL */ /*else*/ { __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(__pyx_v_self)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":290 * else: * info.strides = PyArray_STRIDES(self) * info.shape = PyArray_DIMS(self) # <<<<<<<<<<<<<< * info.suboffsets = NULL * info.itemsize = PyArray_ITEMSIZE(self) */ __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(__pyx_v_self)); } __pyx_L9:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":291 * info.strides = PyArray_STRIDES(self) * info.shape = PyArray_DIMS(self) * info.suboffsets = NULL # <<<<<<<<<<<<<< * info.itemsize = PyArray_ITEMSIZE(self) * info.readonly = not PyArray_ISWRITEABLE(self) */ __pyx_v_info->suboffsets = NULL; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":292 * info.shape = PyArray_DIMS(self) * info.suboffsets = NULL * info.itemsize = PyArray_ITEMSIZE(self) # <<<<<<<<<<<<<< * info.readonly = not PyArray_ISWRITEABLE(self) * */ __pyx_v_info->itemsize = PyArray_ITEMSIZE(__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":293 * info.suboffsets = NULL * info.itemsize = PyArray_ITEMSIZE(self) * info.readonly = not PyArray_ISWRITEABLE(self) # <<<<<<<<<<<<<< * * cdef int t */ __pyx_v_info->readonly = (!(PyArray_ISWRITEABLE(__pyx_v_self) != 0)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":296 * * cdef int t * cdef char* f = NULL # <<<<<<<<<<<<<< * cdef dtype descr = PyArray_DESCR(self) * cdef int offset */ __pyx_v_f = NULL; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":297 * cdef int t * cdef char* f = NULL * cdef dtype descr = PyArray_DESCR(self) # <<<<<<<<<<<<<< * cdef int offset * */ __pyx_t_7 = PyArray_DESCR(__pyx_v_self); __pyx_t_3 = ((PyObject *)__pyx_t_7); __Pyx_INCREF(__pyx_t_3); __pyx_v_descr = ((PyArray_Descr *)__pyx_t_3); __pyx_t_3 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":300 * cdef int offset * * info.obj = self # <<<<<<<<<<<<<< * * if not PyDataType_HASFIELDS(descr): */ __Pyx_INCREF(((PyObject *)__pyx_v_self)); __Pyx_GIVEREF(((PyObject *)__pyx_v_self)); __Pyx_GOTREF(__pyx_v_info->obj); __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = ((PyObject *)__pyx_v_self); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":302 * info.obj = self * * if not PyDataType_HASFIELDS(descr): # <<<<<<<<<<<<<< * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or */ __pyx_t_1 = ((!(PyDataType_HASFIELDS(__pyx_v_descr) != 0)) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":303 * * if not PyDataType_HASFIELDS(descr): * t = descr.type_num # <<<<<<<<<<<<<< * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): */ __pyx_t_4 = __pyx_v_descr->type_num; __pyx_v_t = __pyx_t_4; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":304 * if not PyDataType_HASFIELDS(descr): * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ __pyx_t_2 = ((__pyx_v_descr->byteorder == '>') != 0); if (!__pyx_t_2) { goto __pyx_L15_next_or; } else { } __pyx_t_2 = (__pyx_v_little_endian != 0); if (!__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L14_bool_binop_done; } __pyx_L15_next_or:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":305 * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): # <<<<<<<<<<<<<< * raise ValueError(u"Non-native byte order not supported") * if t == NPY_BYTE: f = "b" */ __pyx_t_2 = ((__pyx_v_descr->byteorder == '<') != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L14_bool_binop_done; } __pyx_t_2 = ((!(__pyx_v_little_endian != 0)) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L14_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":304 * if not PyDataType_HASFIELDS(descr): * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ if (unlikely(__pyx_t_1)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":306 * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 306, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 306, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":304 * if not PyDataType_HASFIELDS(descr): * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":307 * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") * if t == NPY_BYTE: f = "b" # <<<<<<<<<<<<<< * elif t == NPY_UBYTE: f = "B" * elif t == NPY_SHORT: f = "h" */ switch (__pyx_v_t) { case NPY_BYTE: __pyx_v_f = ((char *)"b"); break; case NPY_UBYTE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":308 * raise ValueError(u"Non-native byte order not supported") * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" # <<<<<<<<<<<<<< * elif t == NPY_SHORT: f = "h" * elif t == NPY_USHORT: f = "H" */ __pyx_v_f = ((char *)"B"); break; case NPY_SHORT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":309 * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" * elif t == NPY_SHORT: f = "h" # <<<<<<<<<<<<<< * elif t == NPY_USHORT: f = "H" * elif t == NPY_INT: f = "i" */ __pyx_v_f = ((char *)"h"); break; case NPY_USHORT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":310 * elif t == NPY_UBYTE: f = "B" * elif t == NPY_SHORT: f = "h" * elif t == NPY_USHORT: f = "H" # <<<<<<<<<<<<<< * elif t == NPY_INT: f = "i" * elif t == NPY_UINT: f = "I" */ __pyx_v_f = ((char *)"H"); break; case NPY_INT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":311 * elif t == NPY_SHORT: f = "h" * elif t == NPY_USHORT: f = "H" * elif t == NPY_INT: f = "i" # <<<<<<<<<<<<<< * elif t == NPY_UINT: f = "I" * elif t == NPY_LONG: f = "l" */ __pyx_v_f = ((char *)"i"); break; case NPY_UINT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":312 * elif t == NPY_USHORT: f = "H" * elif t == NPY_INT: f = "i" * elif t == NPY_UINT: f = "I" # <<<<<<<<<<<<<< * elif t == NPY_LONG: f = "l" * elif t == NPY_ULONG: f = "L" */ __pyx_v_f = ((char *)"I"); break; case NPY_LONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":313 * elif t == NPY_INT: f = "i" * elif t == NPY_UINT: f = "I" * elif t == NPY_LONG: f = "l" # <<<<<<<<<<<<<< * elif t == NPY_ULONG: f = "L" * elif t == NPY_LONGLONG: f = "q" */ __pyx_v_f = ((char *)"l"); break; case NPY_ULONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":314 * elif t == NPY_UINT: f = "I" * elif t == NPY_LONG: f = "l" * elif t == NPY_ULONG: f = "L" # <<<<<<<<<<<<<< * elif t == NPY_LONGLONG: f = "q" * elif t == NPY_ULONGLONG: f = "Q" */ __pyx_v_f = ((char *)"L"); break; case NPY_LONGLONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":315 * elif t == NPY_LONG: f = "l" * elif t == NPY_ULONG: f = "L" * elif t == NPY_LONGLONG: f = "q" # <<<<<<<<<<<<<< * elif t == NPY_ULONGLONG: f = "Q" * elif t == NPY_FLOAT: f = "f" */ __pyx_v_f = ((char *)"q"); break; case NPY_ULONGLONG: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":316 * elif t == NPY_ULONG: f = "L" * elif t == NPY_LONGLONG: f = "q" * elif t == NPY_ULONGLONG: f = "Q" # <<<<<<<<<<<<<< * elif t == NPY_FLOAT: f = "f" * elif t == NPY_DOUBLE: f = "d" */ __pyx_v_f = ((char *)"Q"); break; case NPY_FLOAT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":317 * elif t == NPY_LONGLONG: f = "q" * elif t == NPY_ULONGLONG: f = "Q" * elif t == NPY_FLOAT: f = "f" # <<<<<<<<<<<<<< * elif t == NPY_DOUBLE: f = "d" * elif t == NPY_LONGDOUBLE: f = "g" */ __pyx_v_f = ((char *)"f"); break; case NPY_DOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":318 * elif t == NPY_ULONGLONG: f = "Q" * elif t == NPY_FLOAT: f = "f" * elif t == NPY_DOUBLE: f = "d" # <<<<<<<<<<<<<< * elif t == NPY_LONGDOUBLE: f = "g" * elif t == NPY_CFLOAT: f = "Zf" */ __pyx_v_f = ((char *)"d"); break; case NPY_LONGDOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":319 * elif t == NPY_FLOAT: f = "f" * elif t == NPY_DOUBLE: f = "d" * elif t == NPY_LONGDOUBLE: f = "g" # <<<<<<<<<<<<<< * elif t == NPY_CFLOAT: f = "Zf" * elif t == NPY_CDOUBLE: f = "Zd" */ __pyx_v_f = ((char *)"g"); break; case NPY_CFLOAT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":320 * elif t == NPY_DOUBLE: f = "d" * elif t == NPY_LONGDOUBLE: f = "g" * elif t == NPY_CFLOAT: f = "Zf" # <<<<<<<<<<<<<< * elif t == NPY_CDOUBLE: f = "Zd" * elif t == NPY_CLONGDOUBLE: f = "Zg" */ __pyx_v_f = ((char *)"Zf"); break; case NPY_CDOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":321 * elif t == NPY_LONGDOUBLE: f = "g" * elif t == NPY_CFLOAT: f = "Zf" * elif t == NPY_CDOUBLE: f = "Zd" # <<<<<<<<<<<<<< * elif t == NPY_CLONGDOUBLE: f = "Zg" * elif t == NPY_OBJECT: f = "O" */ __pyx_v_f = ((char *)"Zd"); break; case NPY_CLONGDOUBLE: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":322 * elif t == NPY_CFLOAT: f = "Zf" * elif t == NPY_CDOUBLE: f = "Zd" * elif t == NPY_CLONGDOUBLE: f = "Zg" # <<<<<<<<<<<<<< * elif t == NPY_OBJECT: f = "O" * else: */ __pyx_v_f = ((char *)"Zg"); break; case NPY_OBJECT: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":323 * elif t == NPY_CDOUBLE: f = "Zd" * elif t == NPY_CLONGDOUBLE: f = "Zg" * elif t == NPY_OBJECT: f = "O" # <<<<<<<<<<<<<< * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) */ __pyx_v_f = ((char *)"O"); break; default: /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":325 * elif t == NPY_OBJECT: f = "O" * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) # <<<<<<<<<<<<<< * info.format = f * return */ __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_8 = PyUnicode_Format(__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_t_3); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 325, __pyx_L1_error) break; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":326 * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) * info.format = f # <<<<<<<<<<<<<< * return * else: */ __pyx_v_info->format = __pyx_v_f; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":327 * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) * info.format = f * return # <<<<<<<<<<<<<< * else: * info.format = PyObject_Malloc(_buffer_format_string_len) */ __pyx_r = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":302 * info.obj = self * * if not PyDataType_HASFIELDS(descr): # <<<<<<<<<<<<<< * t = descr.type_num * if ((descr.byteorder == c'>' and little_endian) or */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":329 * return * else: * info.format = PyObject_Malloc(_buffer_format_string_len) # <<<<<<<<<<<<<< * info.format[0] = c'^' # Native data types, manual alignment * offset = 0 */ /*else*/ { __pyx_v_info->format = ((char *)PyObject_Malloc(0xFF)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":330 * else: * info.format = PyObject_Malloc(_buffer_format_string_len) * info.format[0] = c'^' # Native data types, manual alignment # <<<<<<<<<<<<<< * offset = 0 * f = _util_dtypestring(descr, info.format + 1, */ (__pyx_v_info->format[0]) = '^'; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":331 * info.format = PyObject_Malloc(_buffer_format_string_len) * info.format[0] = c'^' # Native data types, manual alignment * offset = 0 # <<<<<<<<<<<<<< * f = _util_dtypestring(descr, info.format + 1, * info.format + _buffer_format_string_len, */ __pyx_v_offset = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":332 * info.format[0] = c'^' # Native data types, manual alignment * offset = 0 * f = _util_dtypestring(descr, info.format + 1, # <<<<<<<<<<<<<< * info.format + _buffer_format_string_len, * &offset) */ __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 0xFF), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == ((char *)NULL))) __PYX_ERR(1, 332, __pyx_L1_error) __pyx_v_f = __pyx_t_9; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":335 * info.format + _buffer_format_string_len, * &offset) * f[0] = c'\0' # Terminate format string # <<<<<<<<<<<<<< * * def __releasebuffer__(ndarray self, Py_buffer* info): */ (__pyx_v_f[0]) = '\x00'; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":258 * # experimental exception made for __getbuffer__ and __releasebuffer__ * # -- the details of this may change. * def __getbuffer__(ndarray self, Py_buffer* info, int flags): # <<<<<<<<<<<<<< * # This implementation of getbuffer is geared towards Cython * # requirements, and does not yet fulfill the PEP. */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.ndarray.__getbuffer__", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; if (__pyx_v_info->obj != NULL) { __Pyx_GOTREF(__pyx_v_info->obj); __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; } goto __pyx_L2; __pyx_L0:; if (__pyx_v_info->obj == Py_None) { __Pyx_GOTREF(__pyx_v_info->obj); __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; } __pyx_L2:; __Pyx_XDECREF((PyObject *)__pyx_v_descr); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":337 * f[0] = c'\0' # Terminate format string * * def __releasebuffer__(ndarray self, Py_buffer* info): # <<<<<<<<<<<<<< * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) */ /* Python wrapper */ static CYTHON_UNUSED void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/ static CYTHON_UNUSED void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__releasebuffer__ (wrapper)", 0); __pyx_pf_5numpy_7ndarray_2__releasebuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info)); /* function exit code */ __Pyx_RefNannyFinishContext(); } static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info) { __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("__releasebuffer__", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":338 * * def __releasebuffer__(ndarray self, Py_buffer* info): * if PyArray_HASFIELDS(self): # <<<<<<<<<<<<<< * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): */ __pyx_t_1 = (PyArray_HASFIELDS(__pyx_v_self) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":339 * def __releasebuffer__(ndarray self, Py_buffer* info): * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) # <<<<<<<<<<<<<< * if sizeof(npy_intp) != sizeof(Py_ssize_t): * PyObject_Free(info.strides) */ PyObject_Free(__pyx_v_info->format); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":338 * * def __releasebuffer__(ndarray self, Py_buffer* info): * if PyArray_HASFIELDS(self): # <<<<<<<<<<<<<< * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":340 * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * PyObject_Free(info.strides) * # info.shape was stored after info.strides in the same block */ __pyx_t_1 = (((sizeof(npy_intp)) != (sizeof(Py_ssize_t))) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":341 * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): * PyObject_Free(info.strides) # <<<<<<<<<<<<<< * # info.shape was stored after info.strides in the same block * */ PyObject_Free(__pyx_v_info->strides); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":340 * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< * PyObject_Free(info.strides) * # info.shape was stored after info.strides in the same block */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":337 * f[0] = c'\0' # Terminate format string * * def __releasebuffer__(ndarray self, Py_buffer* info): # <<<<<<<<<<<<<< * if PyArray_HASFIELDS(self): * PyObject_Free(info.format) */ /* function exit code */ __Pyx_RefNannyFinishContext(); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":821 * ctypedef npy_cdouble complex_t * * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(1, a) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":822 * * cdef inline object PyArray_MultiIterNew1(a): * return PyArray_MultiIterNew(1, a) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew2(a, b): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 822, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":821 * ctypedef npy_cdouble complex_t * * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(1, a) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":824 * return PyArray_MultiIterNew(1, a) * * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(2, a, b) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":825 * * cdef inline object PyArray_MultiIterNew2(a, b): * return PyArray_MultiIterNew(2, a, b) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew3(a, b, c): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 825, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":824 * return PyArray_MultiIterNew(1, a) * * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(2, a, b) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":827 * return PyArray_MultiIterNew(2, a, b) * * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(3, a, b, c) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":828 * * cdef inline object PyArray_MultiIterNew3(a, b, c): * return PyArray_MultiIterNew(3, a, b, c) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 828, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":827 * return PyArray_MultiIterNew(2, a, b) * * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(3, a, b, c) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":830 * return PyArray_MultiIterNew(3, a, b, c) * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(4, a, b, c, d) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":831 * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): * return PyArray_MultiIterNew(4, a, b, c, d) # <<<<<<<<<<<<<< * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 831, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":830 * return PyArray_MultiIterNew(3, a, b, c) * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(4, a, b, c, d) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":833 * return PyArray_MultiIterNew(4, a, b, c, d) * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(5, a, b, c, d, e) * */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":834 * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): * return PyArray_MultiIterNew(5, a, b, c, d, e) # <<<<<<<<<<<<<< * * cdef inline tuple PyDataType_SHAPE(dtype d): */ __Pyx_XDECREF(__pyx_r); __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 834, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":833 * return PyArray_MultiIterNew(4, a, b, c, d) * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< * return PyArray_MultiIterNew(5, a, b, c, d, e) * */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":836 * return PyArray_MultiIterNew(5, a, b, c, d, e) * * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__pyx_v_d) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("PyDataType_SHAPE", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":837 * * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< * return d.subarray.shape * else: */ __pyx_t_1 = (PyDataType_HASSUBARRAY(__pyx_v_d) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":838 * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape # <<<<<<<<<<<<<< * else: * return () */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(((PyObject*)__pyx_v_d->subarray->shape)); __pyx_r = ((PyObject*)__pyx_v_d->subarray->shape); goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":837 * * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< * return d.subarray.shape * else: */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":840 * return d.subarray.shape * else: * return () # <<<<<<<<<<<<<< * * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: */ /*else*/ { __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(__pyx_empty_tuple); __pyx_r = __pyx_empty_tuple; goto __pyx_L0; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":836 * return PyArray_MultiIterNew(5, a, b, c, d, e) * * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape */ /* function exit code */ __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":842 * return () * * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: # <<<<<<<<<<<<<< * # Recursive utility function used in __getbuffer__ to get format * # string. The new location in the format string is returned. */ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx_v_descr, char *__pyx_v_f, char *__pyx_v_end, int *__pyx_v_offset) { PyArray_Descr *__pyx_v_child = 0; int __pyx_v_endian_detector; int __pyx_v_little_endian; PyObject *__pyx_v_fields = 0; PyObject *__pyx_v_childname = NULL; PyObject *__pyx_v_new_offset = NULL; PyObject *__pyx_v_t = NULL; char *__pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; Py_ssize_t __pyx_t_2; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; int __pyx_t_5; int __pyx_t_6; int __pyx_t_7; long __pyx_t_8; char *__pyx_t_9; __Pyx_RefNannySetupContext("_util_dtypestring", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":847 * * cdef dtype child * cdef int endian_detector = 1 # <<<<<<<<<<<<<< * cdef bint little_endian = ((&endian_detector)[0] != 0) * cdef tuple fields */ __pyx_v_endian_detector = 1; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":848 * cdef dtype child * cdef int endian_detector = 1 * cdef bint little_endian = ((&endian_detector)[0] != 0) # <<<<<<<<<<<<<< * cdef tuple fields * */ __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":851 * cdef tuple fields * * for childname in descr.names: # <<<<<<<<<<<<<< * fields = descr.fields[childname] * child, new_offset = fields */ if (unlikely(__pyx_v_descr->names == Py_None)) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); __PYX_ERR(1, 851, __pyx_L1_error) } __pyx_t_1 = __pyx_v_descr->names; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0; for (;;) { if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break; #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) __PYX_ERR(1, 851, __pyx_L1_error) #else __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 851, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); #endif __Pyx_XDECREF_SET(__pyx_v_childname, __pyx_t_3); __pyx_t_3 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":852 * * for childname in descr.names: * fields = descr.fields[childname] # <<<<<<<<<<<<<< * child, new_offset = fields * */ if (unlikely(__pyx_v_descr->fields == Py_None)) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); __PYX_ERR(1, 852, __pyx_L1_error) } __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 852, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(1, 852, __pyx_L1_error) __Pyx_XDECREF_SET(__pyx_v_fields, ((PyObject*)__pyx_t_3)); __pyx_t_3 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":853 * for childname in descr.names: * fields = descr.fields[childname] * child, new_offset = fields # <<<<<<<<<<<<<< * * if (end - f) - (new_offset - offset[0]) < 15: */ if (likely(__pyx_v_fields != Py_None)) { PyObject* sequence = __pyx_v_fields; Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); if (unlikely(size != 2)) { if (size > 2) __Pyx_RaiseTooManyValuesError(2); else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); __PYX_ERR(1, 853, __pyx_L1_error) } #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); __Pyx_INCREF(__pyx_t_3); __Pyx_INCREF(__pyx_t_4); #else __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 853, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 853, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); #endif } else { __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(1, 853, __pyx_L1_error) } if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) __PYX_ERR(1, 853, __pyx_L1_error) __Pyx_XDECREF_SET(__pyx_v_child, ((PyArray_Descr *)__pyx_t_3)); __pyx_t_3 = 0; __Pyx_XDECREF_SET(__pyx_v_new_offset, __pyx_t_4); __pyx_t_4 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":855 * child, new_offset = fields * * if (end - f) - (new_offset - offset[0]) < 15: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * */ __pyx_t_4 = __Pyx_PyInt_From_int((__pyx_v_offset[0])); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 855, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 855, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_5 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_5 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 855, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = ((((__pyx_v_end - __pyx_v_f) - ((int)__pyx_t_5)) < 15) != 0); if (unlikely(__pyx_t_6)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":856 * * if (end - f) - (new_offset - offset[0]) < 15: * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") # <<<<<<<<<<<<<< * * if ((child.byteorder == c'>' and little_endian) or */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 856, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 856, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":855 * child, new_offset = fields * * if (end - f) - (new_offset - offset[0]) < 15: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":858 * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ __pyx_t_7 = ((__pyx_v_child->byteorder == '>') != 0); if (!__pyx_t_7) { goto __pyx_L8_next_or; } else { } __pyx_t_7 = (__pyx_v_little_endian != 0); if (!__pyx_t_7) { } else { __pyx_t_6 = __pyx_t_7; goto __pyx_L7_bool_binop_done; } __pyx_L8_next_or:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":859 * * if ((child.byteorder == c'>' and little_endian) or * (child.byteorder == c'<' and not little_endian)): # <<<<<<<<<<<<<< * raise ValueError(u"Non-native byte order not supported") * # One could encode it in the format string and have Cython */ __pyx_t_7 = ((__pyx_v_child->byteorder == '<') != 0); if (__pyx_t_7) { } else { __pyx_t_6 = __pyx_t_7; goto __pyx_L7_bool_binop_done; } __pyx_t_7 = ((!(__pyx_v_little_endian != 0)) != 0); __pyx_t_6 = __pyx_t_7; __pyx_L7_bool_binop_done:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":858 * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ if (unlikely(__pyx_t_6)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":860 * if ((child.byteorder == c'>' and little_endian) or * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< * # One could encode it in the format string and have Cython * # complain instead, BUT: < and > in format strings also imply */ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 860, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 860, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":858 * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") * * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< * (child.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":870 * * # Output padding bytes * while offset[0] < new_offset: # <<<<<<<<<<<<<< * f[0] = 120 # "x"; pad byte * f += 1 */ while (1) { __pyx_t_3 = __Pyx_PyInt_From_int((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 870, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_t_3, __pyx_v_new_offset, Py_LT); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 870, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 870, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (!__pyx_t_6) break; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":871 * # Output padding bytes * while offset[0] < new_offset: * f[0] = 120 # "x"; pad byte # <<<<<<<<<<<<<< * f += 1 * offset[0] += 1 */ (__pyx_v_f[0]) = 0x78; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":872 * while offset[0] < new_offset: * f[0] = 120 # "x"; pad byte * f += 1 # <<<<<<<<<<<<<< * offset[0] += 1 * */ __pyx_v_f = (__pyx_v_f + 1); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":873 * f[0] = 120 # "x"; pad byte * f += 1 * offset[0] += 1 # <<<<<<<<<<<<<< * * offset[0] += child.itemsize */ __pyx_t_8 = 0; (__pyx_v_offset[__pyx_t_8]) = ((__pyx_v_offset[__pyx_t_8]) + 1); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":875 * offset[0] += 1 * * offset[0] += child.itemsize # <<<<<<<<<<<<<< * * if not PyDataType_HASFIELDS(child): */ __pyx_t_8 = 0; (__pyx_v_offset[__pyx_t_8]) = ((__pyx_v_offset[__pyx_t_8]) + __pyx_v_child->elsize); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":877 * offset[0] += child.itemsize * * if not PyDataType_HASFIELDS(child): # <<<<<<<<<<<<<< * t = child.type_num * if end - f < 5: */ __pyx_t_6 = ((!(PyDataType_HASFIELDS(__pyx_v_child) != 0)) != 0); if (__pyx_t_6) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":878 * * if not PyDataType_HASFIELDS(child): * t = child.type_num # <<<<<<<<<<<<<< * if end - f < 5: * raise RuntimeError(u"Format string allocated too short.") */ __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_child->type_num); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 878, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_4); __pyx_t_4 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":879 * if not PyDataType_HASFIELDS(child): * t = child.type_num * if end - f < 5: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short.") * */ __pyx_t_6 = (((__pyx_v_end - __pyx_v_f) < 5) != 0); if (unlikely(__pyx_t_6)) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":880 * t = child.type_num * if end - f < 5: * raise RuntimeError(u"Format string allocated too short.") # <<<<<<<<<<<<<< * * # Until ticket #99 is fixed, use integers to avoid warnings */ __pyx_t_4 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_tuple__6, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 880, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_Raise(__pyx_t_4, 0, 0, 0); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __PYX_ERR(1, 880, __pyx_L1_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":879 * if not PyDataType_HASFIELDS(child): * t = child.type_num * if end - f < 5: # <<<<<<<<<<<<<< * raise RuntimeError(u"Format string allocated too short.") * */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":883 * * # Until ticket #99 is fixed, use integers to avoid warnings * if t == NPY_BYTE: f[0] = 98 #"b" # <<<<<<<<<<<<<< * elif t == NPY_UBYTE: f[0] = 66 #"B" * elif t == NPY_SHORT: f[0] = 104 #"h" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_BYTE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 883, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 883, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 883, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 98; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":884 * # Until ticket #99 is fixed, use integers to avoid warnings * if t == NPY_BYTE: f[0] = 98 #"b" * elif t == NPY_UBYTE: f[0] = 66 #"B" # <<<<<<<<<<<<<< * elif t == NPY_SHORT: f[0] = 104 #"h" * elif t == NPY_USHORT: f[0] = 72 #"H" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_UBYTE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 884, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 884, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 884, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 66; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":885 * if t == NPY_BYTE: f[0] = 98 #"b" * elif t == NPY_UBYTE: f[0] = 66 #"B" * elif t == NPY_SHORT: f[0] = 104 #"h" # <<<<<<<<<<<<<< * elif t == NPY_USHORT: f[0] = 72 #"H" * elif t == NPY_INT: f[0] = 105 #"i" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_SHORT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 885, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 885, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 885, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x68; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":886 * elif t == NPY_UBYTE: f[0] = 66 #"B" * elif t == NPY_SHORT: f[0] = 104 #"h" * elif t == NPY_USHORT: f[0] = 72 #"H" # <<<<<<<<<<<<<< * elif t == NPY_INT: f[0] = 105 #"i" * elif t == NPY_UINT: f[0] = 73 #"I" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_USHORT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 886, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 886, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 886, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 72; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":887 * elif t == NPY_SHORT: f[0] = 104 #"h" * elif t == NPY_USHORT: f[0] = 72 #"H" * elif t == NPY_INT: f[0] = 105 #"i" # <<<<<<<<<<<<<< * elif t == NPY_UINT: f[0] = 73 #"I" * elif t == NPY_LONG: f[0] = 108 #"l" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_INT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 887, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 887, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 887, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x69; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":888 * elif t == NPY_USHORT: f[0] = 72 #"H" * elif t == NPY_INT: f[0] = 105 #"i" * elif t == NPY_UINT: f[0] = 73 #"I" # <<<<<<<<<<<<<< * elif t == NPY_LONG: f[0] = 108 #"l" * elif t == NPY_ULONG: f[0] = 76 #"L" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_UINT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 888, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 888, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 888, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 73; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":889 * elif t == NPY_INT: f[0] = 105 #"i" * elif t == NPY_UINT: f[0] = 73 #"I" * elif t == NPY_LONG: f[0] = 108 #"l" # <<<<<<<<<<<<<< * elif t == NPY_ULONG: f[0] = 76 #"L" * elif t == NPY_LONGLONG: f[0] = 113 #"q" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONG); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 889, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 889, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 889, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x6C; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":890 * elif t == NPY_UINT: f[0] = 73 #"I" * elif t == NPY_LONG: f[0] = 108 #"l" * elif t == NPY_ULONG: f[0] = 76 #"L" # <<<<<<<<<<<<<< * elif t == NPY_LONGLONG: f[0] = 113 #"q" * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_ULONG); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 890, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 890, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 890, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 76; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":891 * elif t == NPY_LONG: f[0] = 108 #"l" * elif t == NPY_ULONG: f[0] = 76 #"L" * elif t == NPY_LONGLONG: f[0] = 113 #"q" # <<<<<<<<<<<<<< * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" * elif t == NPY_FLOAT: f[0] = 102 #"f" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONGLONG); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 891, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 891, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 891, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x71; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":892 * elif t == NPY_ULONG: f[0] = 76 #"L" * elif t == NPY_LONGLONG: f[0] = 113 #"q" * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" # <<<<<<<<<<<<<< * elif t == NPY_FLOAT: f[0] = 102 #"f" * elif t == NPY_DOUBLE: f[0] = 100 #"d" */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_ULONGLONG); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 892, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 892, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 892, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 81; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":893 * elif t == NPY_LONGLONG: f[0] = 113 #"q" * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" * elif t == NPY_FLOAT: f[0] = 102 #"f" # <<<<<<<<<<<<<< * elif t == NPY_DOUBLE: f[0] = 100 #"d" * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_FLOAT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 893, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 893, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 893, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x66; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":894 * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" * elif t == NPY_FLOAT: f[0] = 102 #"f" * elif t == NPY_DOUBLE: f[0] = 100 #"d" # <<<<<<<<<<<<<< * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_DOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 894, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 894, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 894, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x64; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":895 * elif t == NPY_FLOAT: f[0] = 102 #"f" * elif t == NPY_DOUBLE: f[0] = 100 #"d" * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" # <<<<<<<<<<<<<< * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 895, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 895, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 895, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 0x67; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":896 * elif t == NPY_DOUBLE: f[0] = 100 #"d" * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf # <<<<<<<<<<<<<< * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CFLOAT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 896, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 896, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 896, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 90; (__pyx_v_f[1]) = 0x66; __pyx_v_f = (__pyx_v_f + 1); goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":897 * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd # <<<<<<<<<<<<<< * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg * elif t == NPY_OBJECT: f[0] = 79 #"O" */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CDOUBLE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 897, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 897, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 897, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 90; (__pyx_v_f[1]) = 0x64; __pyx_v_f = (__pyx_v_f + 1); goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":898 * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg # <<<<<<<<<<<<<< * elif t == NPY_OBJECT: f[0] = 79 #"O" * else: */ __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 898, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 898, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 898, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (__pyx_t_6) { (__pyx_v_f[0]) = 90; (__pyx_v_f[1]) = 0x67; __pyx_v_f = (__pyx_v_f + 1); goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":899 * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg * elif t == NPY_OBJECT: f[0] = 79 #"O" # <<<<<<<<<<<<<< * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) */ __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_OBJECT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 899, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 899, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 899, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (likely(__pyx_t_6)) { (__pyx_v_f[0]) = 79; goto __pyx_L15; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":901 * elif t == NPY_OBJECT: f[0] = 79 #"O" * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) # <<<<<<<<<<<<<< * f += 1 * else: */ /*else*/ { __pyx_t_3 = __Pyx_PyUnicode_FormatSafe(__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_v_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 901, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 901, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_Raise(__pyx_t_4, 0, 0, 0); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __PYX_ERR(1, 901, __pyx_L1_error) } __pyx_L15:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":902 * else: * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) * f += 1 # <<<<<<<<<<<<<< * else: * # Cython ignores struct boundary information ("T{...}"), */ __pyx_v_f = (__pyx_v_f + 1); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":877 * offset[0] += child.itemsize * * if not PyDataType_HASFIELDS(child): # <<<<<<<<<<<<<< * t = child.type_num * if end - f < 5: */ goto __pyx_L13; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":906 * # Cython ignores struct boundary information ("T{...}"), * # so don't output it * f = _util_dtypestring(child, f, end, offset) # <<<<<<<<<<<<<< * return f * */ /*else*/ { __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_9 == ((char *)NULL))) __PYX_ERR(1, 906, __pyx_L1_error) __pyx_v_f = __pyx_t_9; } __pyx_L13:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":851 * cdef tuple fields * * for childname in descr.names: # <<<<<<<<<<<<<< * fields = descr.fields[childname] * child, new_offset = fields */ } __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":907 * # so don't output it * f = _util_dtypestring(child, f, end, offset) * return f # <<<<<<<<<<<<<< * * */ __pyx_r = __pyx_v_f; goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":842 * return () * * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: # <<<<<<<<<<<<<< * # Recursive utility function used in __getbuffer__ to get format * # string. The new location in the format string is returned. */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __Pyx_AddTraceback("numpy._util_dtypestring", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XDECREF((PyObject *)__pyx_v_child); __Pyx_XDECREF(__pyx_v_fields); __Pyx_XDECREF(__pyx_v_childname); __Pyx_XDECREF(__pyx_v_new_offset); __Pyx_XDECREF(__pyx_v_t); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1022 * int _import_umath() except -1 * * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) */ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("set_array_base", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1023 * * cdef inline void set_array_base(ndarray arr, object base): * Py_INCREF(base) # important to do this before stealing the reference below! # <<<<<<<<<<<<<< * PyArray_SetBaseObject(arr, base) * */ Py_INCREF(__pyx_v_base); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1024 * cdef inline void set_array_base(ndarray arr, object base): * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) # <<<<<<<<<<<<<< * * cdef inline object get_array_base(ndarray arr): */ (void)(PyArray_SetBaseObject(__pyx_v_arr, __pyx_v_base)); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1022 * int _import_umath() except -1 * * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) */ /* function exit code */ __Pyx_RefNannyFinishContext(); } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1026 * PyArray_SetBaseObject(arr, base) * * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< * base = PyArray_BASE(arr) * if base is NULL: */ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) { PyObject *__pyx_v_base; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations int __pyx_t_1; __Pyx_RefNannySetupContext("get_array_base", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1027 * * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) # <<<<<<<<<<<<<< * if base is NULL: * return None */ __pyx_v_base = PyArray_BASE(__pyx_v_arr); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1028 * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) * if base is NULL: # <<<<<<<<<<<<<< * return None * return base */ __pyx_t_1 = ((__pyx_v_base == NULL) != 0); if (__pyx_t_1) { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1029 * base = PyArray_BASE(arr) * if base is NULL: * return None # <<<<<<<<<<<<<< * return base * */ __Pyx_XDECREF(__pyx_r); __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1028 * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) * if base is NULL: # <<<<<<<<<<<<<< * return None * return base */ } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1030 * if base is NULL: * return None * return base # <<<<<<<<<<<<<< * * # Versions of the import_* functions which are more suitable for */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(((PyObject *)__pyx_v_base)); __pyx_r = ((PyObject *)__pyx_v_base); goto __pyx_L0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1026 * PyArray_SetBaseObject(arr, base) * * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< * base = PyArray_BASE(arr) * if base is NULL: */ /* function exit code */ __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1034 * # Versions of the import_* functions which are more suitable for * # Cython code. * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< * try: * _import_array() */ static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; __Pyx_RefNannySetupContext("import_array", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1035 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< * _import_array() * except Exception: */ { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); __Pyx_XGOTREF(__pyx_t_1); __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1036 * cdef inline int import_array() except -1: * try: * _import_array() # <<<<<<<<<<<<<< * except Exception: * raise ImportError("numpy.core.multiarray failed to import") */ __pyx_t_4 = _import_array(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1036, __pyx_L3_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1035 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< * _import_array() * except Exception: */ } __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L8_try_end; __pyx_L3_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1037 * try: * _import_array() * except Exception: # <<<<<<<<<<<<<< * raise ImportError("numpy.core.multiarray failed to import") * */ __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); if (__pyx_t_4) { __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1037, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1038 * _import_array() * except Exception: * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_umath() except -1: */ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1038, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(1, 1038, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1035 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< * _import_array() * except Exception: */ __Pyx_XGIVEREF(__pyx_t_1); __Pyx_XGIVEREF(__pyx_t_2); __Pyx_XGIVEREF(__pyx_t_3); __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); goto __pyx_L1_error; __pyx_L8_try_end:; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1034 * # Versions of the import_* functions which are more suitable for * # Cython code. * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< * try: * _import_array() */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1040 * raise ImportError("numpy.core.multiarray failed to import") * * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; __Pyx_RefNannySetupContext("import_umath", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1041 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); __Pyx_XGOTREF(__pyx_t_1); __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1042 * cdef inline int import_umath() except -1: * try: * _import_umath() # <<<<<<<<<<<<<< * except Exception: * raise ImportError("numpy.core.umath failed to import") */ __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1042, __pyx_L3_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1041 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ } __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L8_try_end; __pyx_L3_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1043 * try: * _import_umath() * except Exception: # <<<<<<<<<<<<<< * raise ImportError("numpy.core.umath failed to import") * */ __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); if (__pyx_t_4) { __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1043, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1044 * _import_umath() * except Exception: * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_ufunc() except -1: */ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__8, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1044, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(1, 1044, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1041 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ __Pyx_XGIVEREF(__pyx_t_1); __Pyx_XGIVEREF(__pyx_t_2); __Pyx_XGIVEREF(__pyx_t_3); __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); goto __pyx_L1_error; __pyx_L8_try_end:; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1040 * raise ImportError("numpy.core.multiarray failed to import") * * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1046 * raise ImportError("numpy.core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; int __pyx_t_4; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; __Pyx_RefNannySetupContext("import_ufunc", 0); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1047 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); __Pyx_XGOTREF(__pyx_t_1); __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1048 * cdef inline int import_ufunc() except -1: * try: * _import_umath() # <<<<<<<<<<<<<< * except Exception: * raise ImportError("numpy.core.umath failed to import") */ __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1048, __pyx_L3_error) /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1047 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ } __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L8_try_end; __pyx_L3_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1049 * try: * _import_umath() * except Exception: # <<<<<<<<<<<<<< * raise ImportError("numpy.core.umath failed to import") */ __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); if (__pyx_t_4) { __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1049, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1050 * _import_umath() * except Exception: * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< */ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__8, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1050, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(1, 1050, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1047 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< * _import_umath() * except Exception: */ __Pyx_XGIVEREF(__pyx_t_1); __Pyx_XGIVEREF(__pyx_t_2); __Pyx_XGIVEREF(__pyx_t_3); __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); goto __pyx_L1_error; __pyx_L8_try_end:; } /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1046 * raise ImportError("numpy.core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ /* function exit code */ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } static PyMethodDef __pyx_methods[] = { {0, 0, 0, 0} }; #if PY_MAJOR_VERSION >= 3 #if CYTHON_PEP489_MULTI_PHASE_INIT static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ static int __pyx_pymod_exec_rectangular_overlap(PyObject* module); /*proto*/ static PyModuleDef_Slot __pyx_moduledef_slots[] = { {Py_mod_create, (void*)__pyx_pymod_create}, {Py_mod_exec, (void*)__pyx_pymod_exec_rectangular_overlap}, {0, NULL} }; #endif static struct PyModuleDef __pyx_moduledef = { PyModuleDef_HEAD_INIT, "rectangular_overlap", __pyx_k_This_module_provides_tools_to_c, /* m_doc */ #if CYTHON_PEP489_MULTI_PHASE_INIT 0, /* m_size */ #else -1, /* m_size */ #endif __pyx_methods /* m_methods */, #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_moduledef_slots, /* m_slots */ #else NULL, /* m_reload */ #endif NULL, /* m_traverse */ NULL, /* m_clear */ NULL /* m_free */ }; #endif #ifndef CYTHON_SMALL_CODE #if defined(__clang__) #define CYTHON_SMALL_CODE #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) #define CYTHON_SMALL_CODE __attribute__((cold)) #else #define CYTHON_SMALL_CODE #endif #endif static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_DTYPE, __pyx_k_DTYPE, sizeof(__pyx_k_DTYPE), 0, 0, 1, 1}, {&__pyx_kp_u_Exact_mode_has_not_been_implemen, __pyx_k_Exact_mode_has_not_been_implemen, sizeof(__pyx_k_Exact_mode_has_not_been_implemen), 0, 1, 0, 0}, {&__pyx_kp_u_Format_string_allocated_too_shor, __pyx_k_Format_string_allocated_too_shor, sizeof(__pyx_k_Format_string_allocated_too_shor), 0, 1, 0, 0}, {&__pyx_kp_u_Format_string_allocated_too_shor_2, __pyx_k_Format_string_allocated_too_shor_2, sizeof(__pyx_k_Format_string_allocated_too_shor_2), 0, 1, 0, 0}, {&__pyx_n_s_ImportError, __pyx_k_ImportError, sizeof(__pyx_k_ImportError), 0, 0, 1, 1}, {&__pyx_kp_u_Non_native_byte_order_not_suppor, __pyx_k_Non_native_byte_order_not_suppor, sizeof(__pyx_k_Non_native_byte_order_not_suppor), 0, 1, 0, 0}, {&__pyx_n_s_NotImplementedError, __pyx_k_NotImplementedError, sizeof(__pyx_k_NotImplementedError), 0, 0, 1, 1}, {&__pyx_n_s_RuntimeError, __pyx_k_RuntimeError, sizeof(__pyx_k_RuntimeError), 0, 0, 1, 1}, {&__pyx_n_s_ValueError, __pyx_k_ValueError, sizeof(__pyx_k_ValueError), 0, 0, 1, 1}, {&__pyx_n_s_all, __pyx_k_all, sizeof(__pyx_k_all), 0, 0, 1, 1}, {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, {&__pyx_n_s_dtype, __pyx_k_dtype, sizeof(__pyx_k_dtype), 0, 0, 1, 1}, {&__pyx_n_s_dx, __pyx_k_dx, sizeof(__pyx_k_dx), 0, 0, 1, 1}, {&__pyx_n_s_dy, __pyx_k_dy, sizeof(__pyx_k_dy), 0, 0, 1, 1}, {&__pyx_n_s_float64, __pyx_k_float64, sizeof(__pyx_k_float64), 0, 0, 1, 1}, {&__pyx_n_s_frac, __pyx_k_frac, sizeof(__pyx_k_frac), 0, 0, 1, 1}, {&__pyx_n_s_height, __pyx_k_height, sizeof(__pyx_k_height), 0, 0, 1, 1}, {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1}, {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, {&__pyx_n_s_j, __pyx_k_j, sizeof(__pyx_k_j), 0, 0, 1, 1}, {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, {&__pyx_kp_u_ndarray_is_not_C_contiguous, __pyx_k_ndarray_is_not_C_contiguous, sizeof(__pyx_k_ndarray_is_not_C_contiguous), 0, 1, 0, 0}, {&__pyx_kp_u_ndarray_is_not_Fortran_contiguou, __pyx_k_ndarray_is_not_Fortran_contiguou, sizeof(__pyx_k_ndarray_is_not_Fortran_contiguou), 0, 1, 0, 0}, {&__pyx_n_s_np, __pyx_k_np, sizeof(__pyx_k_np), 0, 0, 1, 1}, {&__pyx_n_s_numpy, __pyx_k_numpy, sizeof(__pyx_k_numpy), 0, 0, 1, 1}, {&__pyx_kp_u_numpy_core_multiarray_failed_to, __pyx_k_numpy_core_multiarray_failed_to, sizeof(__pyx_k_numpy_core_multiarray_failed_to), 0, 1, 0, 0}, {&__pyx_kp_u_numpy_core_umath_failed_to_impor, __pyx_k_numpy_core_umath_failed_to_impor, sizeof(__pyx_k_numpy_core_umath_failed_to_impor), 0, 1, 0, 0}, {&__pyx_n_s_nx, __pyx_k_nx, sizeof(__pyx_k_nx), 0, 0, 1, 1}, {&__pyx_n_s_ny, __pyx_k_ny, sizeof(__pyx_k_ny), 0, 0, 1, 1}, {&__pyx_kp_s_photutils_geometry_rectangular_o, __pyx_k_photutils_geometry_rectangular_o, sizeof(__pyx_k_photutils_geometry_rectangular_o), 0, 0, 1, 0}, {&__pyx_n_s_photutils_geometry_rectangular_o_2, __pyx_k_photutils_geometry_rectangular_o_2, sizeof(__pyx_k_photutils_geometry_rectangular_o_2), 0, 0, 1, 1}, {&__pyx_n_s_pxmax, __pyx_k_pxmax, sizeof(__pyx_k_pxmax), 0, 0, 1, 1}, {&__pyx_n_s_pxmin, __pyx_k_pxmin, sizeof(__pyx_k_pxmin), 0, 0, 1, 1}, {&__pyx_n_s_pymax, __pyx_k_pymax, sizeof(__pyx_k_pymax), 0, 0, 1, 1}, {&__pyx_n_s_pymin, __pyx_k_pymin, sizeof(__pyx_k_pymin), 0, 0, 1, 1}, {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, {&__pyx_n_s_rectangular_overlap_grid, __pyx_k_rectangular_overlap_grid, sizeof(__pyx_k_rectangular_overlap_grid), 0, 0, 1, 1}, {&__pyx_n_u_rectangular_overlap_grid, __pyx_k_rectangular_overlap_grid, sizeof(__pyx_k_rectangular_overlap_grid), 0, 1, 0, 1}, {&__pyx_n_s_subpixels, __pyx_k_subpixels, sizeof(__pyx_k_subpixels), 0, 0, 1, 1}, {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, {&__pyx_n_s_theta, __pyx_k_theta, sizeof(__pyx_k_theta), 0, 0, 1, 1}, {&__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_k_unknown_dtype_code_in_numpy_pxd, sizeof(__pyx_k_unknown_dtype_code_in_numpy_pxd), 0, 1, 0, 0}, {&__pyx_n_s_use_exact, __pyx_k_use_exact, sizeof(__pyx_k_use_exact), 0, 0, 1, 1}, {&__pyx_n_s_width, __pyx_k_width, sizeof(__pyx_k_width), 0, 0, 1, 1}, {&__pyx_n_s_x, __pyx_k_x, sizeof(__pyx_k_x), 0, 0, 1, 1}, {&__pyx_n_s_xmax, __pyx_k_xmax, sizeof(__pyx_k_xmax), 0, 0, 1, 1}, {&__pyx_n_s_xmin, __pyx_k_xmin, sizeof(__pyx_k_xmin), 0, 0, 1, 1}, {&__pyx_n_s_y, __pyx_k_y, sizeof(__pyx_k_y), 0, 0, 1, 1}, {&__pyx_n_s_ymax, __pyx_k_ymax, sizeof(__pyx_k_ymax), 0, 0, 1, 1}, {&__pyx_n_s_ymin, __pyx_k_ymin, sizeof(__pyx_k_ymin), 0, 0, 1, 1}, {&__pyx_n_s_zeros, __pyx_k_zeros, sizeof(__pyx_k_zeros), 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0} }; static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { __pyx_builtin_NotImplementedError = __Pyx_GetBuiltinName(__pyx_n_s_NotImplementedError); if (!__pyx_builtin_NotImplementedError) __PYX_ERR(0, 75, __pyx_L1_error) __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 85, __pyx_L1_error) __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) __PYX_ERR(1, 272, __pyx_L1_error) __pyx_builtin_RuntimeError = __Pyx_GetBuiltinName(__pyx_n_s_RuntimeError); if (!__pyx_builtin_RuntimeError) __PYX_ERR(1, 856, __pyx_L1_error) __pyx_builtin_ImportError = __Pyx_GetBuiltinName(__pyx_n_s_ImportError); if (!__pyx_builtin_ImportError) __PYX_ERR(1, 1038, __pyx_L1_error) return 0; __pyx_L1_error:; return -1; } static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); /* "photutils/geometry/rectangular_overlap.pyx":75 * * if use_exact == 1: * raise NotImplementedError("Exact mode has not been implemented for " # <<<<<<<<<<<<<< * "rectangular apertures") * */ __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_u_Exact_mode_has_not_been_implemen); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 75, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple_); __Pyx_GIVEREF(__pyx_tuple_); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":272 * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)): * raise ValueError(u"ndarray is not C contiguous") # <<<<<<<<<<<<<< * * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) */ __pyx_tuple__2 = PyTuple_Pack(1, __pyx_kp_u_ndarray_is_not_C_contiguous); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(1, 272, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__2); __Pyx_GIVEREF(__pyx_tuple__2); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":276 * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) * and not PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)): * raise ValueError(u"ndarray is not Fortran contiguous") # <<<<<<<<<<<<<< * * info.buf = PyArray_DATA(self) */ __pyx_tuple__3 = PyTuple_Pack(1, __pyx_kp_u_ndarray_is_not_Fortran_contiguou); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(1, 276, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__3); __Pyx_GIVEREF(__pyx_tuple__3); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":306 * if ((descr.byteorder == c'>' and little_endian) or * (descr.byteorder == c'<' and not little_endian)): * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< * if t == NPY_BYTE: f = "b" * elif t == NPY_UBYTE: f = "B" */ __pyx_tuple__4 = PyTuple_Pack(1, __pyx_kp_u_Non_native_byte_order_not_suppor); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(1, 306, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__4); __Pyx_GIVEREF(__pyx_tuple__4); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":856 * * if (end - f) - (new_offset - offset[0]) < 15: * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") # <<<<<<<<<<<<<< * * if ((child.byteorder == c'>' and little_endian) or */ __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_u_Format_string_allocated_too_shor); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(1, 856, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__5); __Pyx_GIVEREF(__pyx_tuple__5); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":880 * t = child.type_num * if end - f < 5: * raise RuntimeError(u"Format string allocated too short.") # <<<<<<<<<<<<<< * * # Until ticket #99 is fixed, use integers to avoid warnings */ __pyx_tuple__6 = PyTuple_Pack(1, __pyx_kp_u_Format_string_allocated_too_shor_2); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(1, 880, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__6); __Pyx_GIVEREF(__pyx_tuple__6); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1038 * _import_array() * except Exception: * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_umath() except -1: */ __pyx_tuple__7 = PyTuple_Pack(1, __pyx_kp_u_numpy_core_multiarray_failed_to); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(1, 1038, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__7); __Pyx_GIVEREF(__pyx_tuple__7); /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1044 * _import_umath() * except Exception: * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< * * cdef inline int import_ufunc() except -1: */ __pyx_tuple__8 = PyTuple_Pack(1, __pyx_kp_u_numpy_core_umath_failed_to_impor); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(1, 1044, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__8); __Pyx_GIVEREF(__pyx_tuple__8); /* "photutils/geometry/rectangular_overlap.pyx":30 * * * def rectangular_overlap_grid(double xmin, double xmax, double ymin, # <<<<<<<<<<<<<< * double ymax, int nx, int ny, double width, * double height, double theta, int use_exact, */ __pyx_tuple__9 = PyTuple_Pack(22, __pyx_n_s_xmin, __pyx_n_s_xmax, __pyx_n_s_ymin, __pyx_n_s_ymax, __pyx_n_s_nx, __pyx_n_s_ny, __pyx_n_s_width, __pyx_n_s_height, __pyx_n_s_theta, __pyx_n_s_use_exact, __pyx_n_s_subpixels, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_x, __pyx_n_s_y, __pyx_n_s_dx, __pyx_n_s_dy, __pyx_n_s_pxmin, __pyx_n_s_pxmax, __pyx_n_s_pymin, __pyx_n_s_pymax, __pyx_n_s_frac); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__9); __Pyx_GIVEREF(__pyx_tuple__9); __pyx_codeobj__10 = (PyObject*)__Pyx_PyCode_New(11, 0, 22, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__9, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_photutils_geometry_rectangular_o, __pyx_n_s_rectangular_overlap_grid, 30, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__10)) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; __Pyx_RefNannyFinishContext(); return -1; } static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); return 0; __pyx_L1_error:; return -1; } static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ static int __Pyx_modinit_global_init_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); /*--- Global init code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_variable_export_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); /*--- Variable export code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_function_export_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); /*--- Function export code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_type_init_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); /*--- Type init code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_type_import_code(void) { __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); /*--- Type import code ---*/ __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 9, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 sizeof(PyTypeObject), #else sizeof(PyHeapTypeObject), #endif __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_7cpython_4type_type) __PYX_ERR(2, 9, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(3, 8, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_7cpython_4bool_bool = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "bool", sizeof(PyBoolObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_7cpython_4bool_bool) __PYX_ERR(3, 8, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(4, 15, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_7cpython_7complex_complex = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "complex", sizeof(PyComplexObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_7cpython_7complex_complex) __PYX_ERR(4, 15, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = PyImport_ImportModule("numpy"); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 206, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_ptype_5numpy_dtype = __Pyx_ImportType(__pyx_t_1, "numpy", "dtype", sizeof(PyArray_Descr), __Pyx_ImportType_CheckSize_Ignore); if (!__pyx_ptype_5numpy_dtype) __PYX_ERR(1, 206, __pyx_L1_error) __pyx_ptype_5numpy_flatiter = __Pyx_ImportType(__pyx_t_1, "numpy", "flatiter", sizeof(PyArrayIterObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_5numpy_flatiter) __PYX_ERR(1, 229, __pyx_L1_error) __pyx_ptype_5numpy_broadcast = __Pyx_ImportType(__pyx_t_1, "numpy", "broadcast", sizeof(PyArrayMultiIterObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_5numpy_broadcast) __PYX_ERR(1, 233, __pyx_L1_error) __pyx_ptype_5numpy_ndarray = __Pyx_ImportType(__pyx_t_1, "numpy", "ndarray", sizeof(PyArrayObject), __Pyx_ImportType_CheckSize_Ignore); if (!__pyx_ptype_5numpy_ndarray) __PYX_ERR(1, 242, __pyx_L1_error) __pyx_ptype_5numpy_ufunc = __Pyx_ImportType(__pyx_t_1, "numpy", "ufunc", sizeof(PyUFuncObject), __Pyx_ImportType_CheckSize_Warn); if (!__pyx_ptype_5numpy_ufunc) __PYX_ERR(1, 918, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_RefNannyFinishContext(); return -1; } static int __Pyx_modinit_variable_import_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); /*--- Variable import code ---*/ __Pyx_RefNannyFinishContext(); return 0; } static int __Pyx_modinit_function_import_code(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); /*--- Function import code ---*/ __Pyx_RefNannyFinishContext(); return 0; } #if PY_MAJOR_VERSION < 3 #ifdef CYTHON_NO_PYINIT_EXPORT #define __Pyx_PyMODINIT_FUNC void #else #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC #endif #else #ifdef CYTHON_NO_PYINIT_EXPORT #define __Pyx_PyMODINIT_FUNC PyObject * #else #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC #endif #endif #if PY_MAJOR_VERSION < 3 __Pyx_PyMODINIT_FUNC initrectangular_overlap(void) CYTHON_SMALL_CODE; /*proto*/ __Pyx_PyMODINIT_FUNC initrectangular_overlap(void) #else __Pyx_PyMODINIT_FUNC PyInit_rectangular_overlap(void) CYTHON_SMALL_CODE; /*proto*/ __Pyx_PyMODINIT_FUNC PyInit_rectangular_overlap(void) #if CYTHON_PEP489_MULTI_PHASE_INIT { return PyModuleDef_Init(&__pyx_moduledef); } static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { #if PY_VERSION_HEX >= 0x030700A1 static PY_INT64_T main_interpreter_id = -1; PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); if (main_interpreter_id == -1) { main_interpreter_id = current_id; return (unlikely(current_id == -1)) ? -1 : 0; } else if (unlikely(main_interpreter_id != current_id)) #else static PyInterpreterState *main_interpreter = NULL; PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; if (!main_interpreter) { main_interpreter = current_interpreter; } else if (unlikely(main_interpreter != current_interpreter)) #endif { PyErr_SetString( PyExc_ImportError, "Interpreter change detected - this module can only be loaded into one interpreter per process."); return -1; } return 0; } static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { PyObject *value = PyObject_GetAttrString(spec, from_name); int result = 0; if (likely(value)) { if (allow_none || value != Py_None) { result = PyDict_SetItemString(moddict, to_name, value); } Py_DECREF(value); } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Clear(); } else { result = -1; } return result; } static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { PyObject *module = NULL, *moddict, *modname; if (__Pyx_check_single_interpreter()) return NULL; if (__pyx_m) return __Pyx_NewRef(__pyx_m); modname = PyObject_GetAttrString(spec, "name"); if (unlikely(!modname)) goto bad; module = PyModule_NewObject(modname); Py_DECREF(modname); if (unlikely(!module)) goto bad; moddict = PyModule_GetDict(module); if (unlikely(!moddict)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; return module; bad: Py_XDECREF(module); return NULL; } static CYTHON_SMALL_CODE int __pyx_pymod_exec_rectangular_overlap(PyObject *__pyx_pyinit_module) #endif #endif { PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; __Pyx_RefNannyDeclarations #if CYTHON_PEP489_MULTI_PHASE_INIT if (__pyx_m) { if (__pyx_m == __pyx_pyinit_module) return 0; PyErr_SetString(PyExc_RuntimeError, "Module 'rectangular_overlap' has already been imported. Re-initialisation is not supported."); return -1; } #elif PY_MAJOR_VERSION >= 3 if (__pyx_m) return __Pyx_NewRef(__pyx_m); #endif #if CYTHON_REFNANNY __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); if (!__Pyx_RefNanny) { PyErr_Clear(); __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); if (!__Pyx_RefNanny) Py_FatalError("failed to import 'refnanny' module"); } #endif __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_rectangular_overlap(void)", 0); if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #ifdef __Pxy_PyFrame_Initialize_Offsets __Pxy_PyFrame_Initialize_Offsets(); #endif __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) #ifdef __Pyx_CyFunction_USED if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_FusedFunction_USED if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_Coroutine_USED if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_Generator_USED if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_AsyncGen_USED if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif #ifdef __Pyx_StopAsyncIteration_USED if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif /*--- Library function declarations ---*/ /*--- Threads initialization code ---*/ #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS #ifdef WITH_THREAD /* Python build with threading support? */ PyEval_InitThreads(); #endif #endif /*--- Module creation code ---*/ #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_m = __pyx_pyinit_module; Py_INCREF(__pyx_m); #else #if PY_MAJOR_VERSION < 3 __pyx_m = Py_InitModule4("rectangular_overlap", __pyx_methods, __pyx_k_This_module_provides_tools_to_c, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); #else __pyx_m = PyModule_Create(&__pyx_moduledef); #endif if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) #endif __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_d); __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_b); __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_cython_runtime); if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); /*--- Initialize various global constants etc. ---*/ if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif if (__pyx_module_is_main_photutils__geometry__rectangular_overlap) { if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) } #if PY_MAJOR_VERSION >= 3 { PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) if (!PyDict_GetItemString(modules, "photutils.geometry.rectangular_overlap")) { if (unlikely(PyDict_SetItemString(modules, "photutils.geometry.rectangular_overlap", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) } } #endif /*--- Builtin init code ---*/ if (__Pyx_InitCachedBuiltins() < 0) goto __pyx_L1_error; /*--- Constants init code ---*/ if (__Pyx_InitCachedConstants() < 0) goto __pyx_L1_error; /*--- Global type/function init code ---*/ (void)__Pyx_modinit_global_init_code(); (void)__Pyx_modinit_variable_export_code(); (void)__Pyx_modinit_function_export_code(); (void)__Pyx_modinit_type_init_code(); if (unlikely(__Pyx_modinit_type_import_code() != 0)) goto __pyx_L1_error; (void)__Pyx_modinit_variable_import_code(); (void)__Pyx_modinit_function_import_code(); /*--- Execution code ---*/ #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif /* "photutils/geometry/rectangular_overlap.pyx":8 * """ * * import numpy as np # <<<<<<<<<<<<<< * cimport numpy as np * */ __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 8, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "photutils/geometry/rectangular_overlap.pyx":11 * cimport numpy as np * * __all__ = ['rectangular_overlap_grid'] # <<<<<<<<<<<<<< * * */ __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_u_rectangular_overlap_grid); __Pyx_GIVEREF(__pyx_n_u_rectangular_overlap_grid); PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_u_rectangular_overlap_grid); if (PyDict_SetItem(__pyx_d, __pyx_n_s_all, __pyx_t_1) < 0) __PYX_ERR(0, 11, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "photutils/geometry/rectangular_overlap.pyx":24 * from cpython cimport bool * * DTYPE = np.float64 # <<<<<<<<<<<<<< * ctypedef np.float64_t DTYPE_t * */ __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_float64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; if (PyDict_SetItem(__pyx_d, __pyx_n_s_DTYPE, __pyx_t_2) < 0) __PYX_ERR(0, 24, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/rectangular_overlap.pyx":30 * * * def rectangular_overlap_grid(double xmin, double xmax, double ymin, # <<<<<<<<<<<<<< * double ymax, int nx, int ny, double width, * double height, double theta, int use_exact, */ __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_9photutils_8geometry_19rectangular_overlap_1rectangular_overlap_grid, NULL, __pyx_n_s_photutils_geometry_rectangular_o_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (PyDict_SetItem(__pyx_d, __pyx_n_s_rectangular_overlap_grid, __pyx_t_2) < 0) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "photutils/geometry/rectangular_overlap.pyx":1 * # Licensed under a 3-clause BSD style license - see LICENSE.rst # <<<<<<<<<<<<<< * #cython: language_level=3 * """ */ __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "../../../../../../../usr/local/lib/python3.7/site-packages/Cython/Includes/numpy/__init__.pxd":1046 * raise ImportError("numpy.core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< * try: * _import_umath() */ /*--- Wrapped vars code ---*/ goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_2); if (__pyx_m) { if (__pyx_d) { __Pyx_AddTraceback("init photutils.geometry.rectangular_overlap", __pyx_clineno, __pyx_lineno, __pyx_filename); } Py_CLEAR(__pyx_m); } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ImportError, "init photutils.geometry.rectangular_overlap"); } __pyx_L0:; __Pyx_RefNannyFinishContext(); #if CYTHON_PEP489_MULTI_PHASE_INIT return (__pyx_m != NULL) ? 0 : -1; #elif PY_MAJOR_VERSION >= 3 return __pyx_m; #else return; #endif } /* --- Runtime support code --- */ /* Refnanny */ #if CYTHON_REFNANNY static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { PyObject *m = NULL, *p = NULL; void *r = NULL; m = PyImport_ImportModule(modname); if (!m) goto end; p = PyObject_GetAttrString(m, "RefNannyAPI"); if (!p) goto end; r = PyLong_AsVoidPtr(p); end: Py_XDECREF(p); Py_XDECREF(m); return (__Pyx_RefNannyAPIStruct *)r; } #endif /* PyObjectGetAttrStr */ #if CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { PyTypeObject* tp = Py_TYPE(obj); if (likely(tp->tp_getattro)) return tp->tp_getattro(obj, attr_name); #if PY_MAJOR_VERSION < 3 if (likely(tp->tp_getattr)) return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); #endif return PyObject_GetAttr(obj, attr_name); } #endif /* GetBuiltinName */ static PyObject *__Pyx_GetBuiltinName(PyObject *name) { PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); if (unlikely(!result)) { PyErr_Format(PyExc_NameError, #if PY_MAJOR_VERSION >= 3 "name '%U' is not defined", name); #else "name '%.200s' is not defined", PyString_AS_STRING(name)); #endif } return result; } /* RaiseArgTupleInvalid */ static void __Pyx_RaiseArgtupleInvalid( const char* func_name, int exact, Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found) { Py_ssize_t num_expected; const char *more_or_less; if (num_found < num_min) { num_expected = num_min; more_or_less = "at least"; } else { num_expected = num_max; more_or_less = "at most"; } if (exact) { more_or_less = "exactly"; } PyErr_Format(PyExc_TypeError, "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", func_name, more_or_less, num_expected, (num_expected == 1) ? "" : "s", num_found); } /* RaiseDoubleKeywords */ static void __Pyx_RaiseDoubleKeywordsError( const char* func_name, PyObject* kw_name) { PyErr_Format(PyExc_TypeError, #if PY_MAJOR_VERSION >= 3 "%s() got multiple values for keyword argument '%U'", func_name, kw_name); #else "%s() got multiple values for keyword argument '%s'", func_name, PyString_AsString(kw_name)); #endif } /* ParseKeywords */ static int __Pyx_ParseOptionalKeywords( PyObject *kwds, PyObject **argnames[], PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, const char* function_name) { PyObject *key = 0, *value = 0; Py_ssize_t pos = 0; PyObject*** name; PyObject*** first_kw_arg = argnames + num_pos_args; while (PyDict_Next(kwds, &pos, &key, &value)) { name = first_kw_arg; while (*name && (**name != key)) name++; if (*name) { values[name-argnames] = value; continue; } name = first_kw_arg; #if PY_MAJOR_VERSION < 3 if (likely(PyString_CheckExact(key)) || likely(PyString_Check(key))) { while (*name) { if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) && _PyString_Eq(**name, key)) { values[name-argnames] = value; break; } name++; } if (*name) continue; else { PyObject*** argname = argnames; while (argname != first_kw_arg) { if ((**argname == key) || ( (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) && _PyString_Eq(**argname, key))) { goto arg_passed_twice; } argname++; } } } else #endif if (likely(PyUnicode_Check(key))) { while (*name) { int cmp = (**name == key) ? 0 : #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 (PyUnicode_GET_SIZE(**name) != PyUnicode_GET_SIZE(key)) ? 1 : #endif PyUnicode_Compare(**name, key); if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; if (cmp == 0) { values[name-argnames] = value; break; } name++; } if (*name) continue; else { PyObject*** argname = argnames; while (argname != first_kw_arg) { int cmp = (**argname == key) ? 0 : #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 (PyUnicode_GET_SIZE(**argname) != PyUnicode_GET_SIZE(key)) ? 1 : #endif PyUnicode_Compare(**argname, key); if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; if (cmp == 0) goto arg_passed_twice; argname++; } } } else goto invalid_keyword_type; if (kwds2) { if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; } else { goto invalid_keyword; } } return 0; arg_passed_twice: __Pyx_RaiseDoubleKeywordsError(function_name, key); goto bad; invalid_keyword_type: PyErr_Format(PyExc_TypeError, "%.200s() keywords must be strings", function_name); goto bad; invalid_keyword: PyErr_Format(PyExc_TypeError, #if PY_MAJOR_VERSION < 3 "%.200s() got an unexpected keyword argument '%.200s'", function_name, PyString_AsString(key)); #else "%s() got an unexpected keyword argument '%U'", function_name, key); #endif bad: return -1; } /* PyDictVersioning */ #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { PyObject *dict = Py_TYPE(obj)->tp_dict; return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; } static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { PyObject **dictptr = NULL; Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; if (offset) { #if CYTHON_COMPILING_IN_CPYTHON dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); #else dictptr = _PyObject_GetDictPtr(obj); #endif } return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; } static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { PyObject *dict = Py_TYPE(obj)->tp_dict; if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) return 0; return obj_dict_version == __Pyx_get_object_dict_version(obj); } #endif /* GetModuleGlobalName */ #if CYTHON_USE_DICT_VERSIONS static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) #else static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) #endif { PyObject *result; #if !CYTHON_AVOID_BORROWED_REFS #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } else if (unlikely(PyErr_Occurred())) { return NULL; } #else result = PyDict_GetItem(__pyx_d, name); __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } #endif #else result = PyObject_GetItem(__pyx_d, name); __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } PyErr_Clear(); #endif return __Pyx_GetBuiltinName(name); } /* PyObjectCall */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; ternaryfunc call = func->ob_type->tp_call; if (unlikely(!call)) return PyObject_Call(func, arg, kw); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) return NULL; result = (*call)(func, arg, kw); Py_LeaveRecursiveCall(); if (unlikely(!result) && unlikely(!PyErr_Occurred())) { PyErr_SetString( PyExc_SystemError, "NULL result without error in PyObject_Call"); } return result; } #endif /* ExtTypeTest */ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { if (unlikely(!type)) { PyErr_SetString(PyExc_SystemError, "Missing type object"); return 0; } if (likely(__Pyx_TypeCheck(obj, type))) return 1; PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", Py_TYPE(obj)->tp_name, type->tp_name); return 0; } /* IsLittleEndian */ static CYTHON_INLINE int __Pyx_Is_Little_Endian(void) { union { uint32_t u32; uint8_t u8[4]; } S; S.u32 = 0x01020304; return S.u8[0] == 4; } /* BufferFormatCheck */ static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, __Pyx_BufFmt_StackElem* stack, __Pyx_TypeInfo* type) { stack[0].field = &ctx->root; stack[0].parent_offset = 0; ctx->root.type = type; ctx->root.name = "buffer dtype"; ctx->root.offset = 0; ctx->head = stack; ctx->head->field = &ctx->root; ctx->fmt_offset = 0; ctx->head->parent_offset = 0; ctx->new_packmode = '@'; ctx->enc_packmode = '@'; ctx->new_count = 1; ctx->enc_count = 0; ctx->enc_type = 0; ctx->is_complex = 0; ctx->is_valid_array = 0; ctx->struct_alignment = 0; while (type->typegroup == 'S') { ++ctx->head; ctx->head->field = type->fields; ctx->head->parent_offset = 0; type = type->fields->type; } } static int __Pyx_BufFmt_ParseNumber(const char** ts) { int count; const char* t = *ts; if (*t < '0' || *t > '9') { return -1; } else { count = *t++ - '0'; while (*t >= '0' && *t <= '9') { count *= 10; count += *t++ - '0'; } } *ts = t; return count; } static int __Pyx_BufFmt_ExpectNumber(const char **ts) { int number = __Pyx_BufFmt_ParseNumber(ts); if (number == -1) PyErr_Format(PyExc_ValueError,\ "Does not understand character buffer dtype format string ('%c')", **ts); return number; } static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) { PyErr_Format(PyExc_ValueError, "Unexpected format string character: '%c'", ch); } static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) { switch (ch) { case '?': return "'bool'"; case 'c': return "'char'"; case 'b': return "'signed char'"; case 'B': return "'unsigned char'"; case 'h': return "'short'"; case 'H': return "'unsigned short'"; case 'i': return "'int'"; case 'I': return "'unsigned int'"; case 'l': return "'long'"; case 'L': return "'unsigned long'"; case 'q': return "'long long'"; case 'Q': return "'unsigned long long'"; case 'f': return (is_complex ? "'complex float'" : "'float'"); case 'd': return (is_complex ? "'complex double'" : "'double'"); case 'g': return (is_complex ? "'complex long double'" : "'long double'"); case 'T': return "a struct"; case 'O': return "Python object"; case 'P': return "a pointer"; case 's': case 'p': return "a string"; case 0: return "end"; default: return "unparseable format string"; } } static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return 2; case 'i': case 'I': case 'l': case 'L': return 4; case 'q': case 'Q': return 8; case 'f': return (is_complex ? 8 : 4); case 'd': return (is_complex ? 16 : 8); case 'g': { PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g').."); return 0; } case 'O': case 'P': return sizeof(void*); default: __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return sizeof(short); case 'i': case 'I': return sizeof(int); case 'l': case 'L': return sizeof(long); #ifdef HAVE_LONG_LONG case 'q': case 'Q': return sizeof(PY_LONG_LONG); #endif case 'f': return sizeof(float) * (is_complex ? 2 : 1); case 'd': return sizeof(double) * (is_complex ? 2 : 1); case 'g': return sizeof(long double) * (is_complex ? 2 : 1); case 'O': case 'P': return sizeof(void*); default: { __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } } typedef struct { char c; short x; } __Pyx_st_short; typedef struct { char c; int x; } __Pyx_st_int; typedef struct { char c; long x; } __Pyx_st_long; typedef struct { char c; float x; } __Pyx_st_float; typedef struct { char c; double x; } __Pyx_st_double; typedef struct { char c; long double x; } __Pyx_st_longdouble; typedef struct { char c; void *x; } __Pyx_st_void_p; #ifdef HAVE_LONG_LONG typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong; #endif static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, CYTHON_UNUSED int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short); case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int); case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long); #ifdef HAVE_LONG_LONG case 'q': case 'Q': return sizeof(__Pyx_st_longlong) - sizeof(PY_LONG_LONG); #endif case 'f': return sizeof(__Pyx_st_float) - sizeof(float); case 'd': return sizeof(__Pyx_st_double) - sizeof(double); case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double); case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*); default: __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } /* These are for computing the padding at the end of the struct to align on the first member of the struct. This will probably the same as above, but we don't have any guarantees. */ typedef struct { short x; char c; } __Pyx_pad_short; typedef struct { int x; char c; } __Pyx_pad_int; typedef struct { long x; char c; } __Pyx_pad_long; typedef struct { float x; char c; } __Pyx_pad_float; typedef struct { double x; char c; } __Pyx_pad_double; typedef struct { long double x; char c; } __Pyx_pad_longdouble; typedef struct { void *x; char c; } __Pyx_pad_void_p; #ifdef HAVE_LONG_LONG typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong; #endif static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, CYTHON_UNUSED int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short); case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int); case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long); #ifdef HAVE_LONG_LONG case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG); #endif case 'f': return sizeof(__Pyx_pad_float) - sizeof(float); case 'd': return sizeof(__Pyx_pad_double) - sizeof(double); case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double); case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*); default: __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { switch (ch) { case 'c': return 'H'; case 'b': case 'h': case 'i': case 'l': case 'q': case 's': case 'p': return 'I'; case '?': case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U'; case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R'); case 'O': return 'O'; case 'P': return 'P'; default: { __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } } static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) { if (ctx->head == NULL || ctx->head->field == &ctx->root) { const char* expected; const char* quote; if (ctx->head == NULL) { expected = "end"; quote = ""; } else { expected = ctx->head->field->type->name; quote = "'"; } PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch, expected %s%s%s but got %s", quote, expected, quote, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex)); } else { __Pyx_StructField* field = ctx->head->field; __Pyx_StructField* parent = (ctx->head - 1)->field; PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'", field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex), parent->type->name, field->name); } } static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) { char group; size_t size, offset, arraysize = 1; if (ctx->enc_type == 0) return 0; if (ctx->head->field->type->arraysize[0]) { int i, ndim = 0; if (ctx->enc_type == 's' || ctx->enc_type == 'p') { ctx->is_valid_array = ctx->head->field->type->ndim == 1; ndim = 1; if (ctx->enc_count != ctx->head->field->type->arraysize[0]) { PyErr_Format(PyExc_ValueError, "Expected a dimension of size %zu, got %zu", ctx->head->field->type->arraysize[0], ctx->enc_count); return -1; } } if (!ctx->is_valid_array) { PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d", ctx->head->field->type->ndim, ndim); return -1; } for (i = 0; i < ctx->head->field->type->ndim; i++) { arraysize *= ctx->head->field->type->arraysize[i]; } ctx->is_valid_array = 0; ctx->enc_count = 1; } group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex); do { __Pyx_StructField* field = ctx->head->field; __Pyx_TypeInfo* type = field->type; if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') { size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex); } else { size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex); } if (ctx->enc_packmode == '@') { size_t align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex); size_t align_mod_offset; if (align_at == 0) return -1; align_mod_offset = ctx->fmt_offset % align_at; if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset; if (ctx->struct_alignment == 0) ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type, ctx->is_complex); } if (type->size != size || type->typegroup != group) { if (type->typegroup == 'C' && type->fields != NULL) { size_t parent_offset = ctx->head->parent_offset + field->offset; ++ctx->head; ctx->head->field = type->fields; ctx->head->parent_offset = parent_offset; continue; } if ((type->typegroup == 'H' || group == 'H') && type->size == size) { } else { __Pyx_BufFmt_RaiseExpected(ctx); return -1; } } offset = ctx->head->parent_offset + field->offset; if (ctx->fmt_offset != offset) { PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch; next field is at offset %" CYTHON_FORMAT_SSIZE_T "d but %" CYTHON_FORMAT_SSIZE_T "d expected", (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset); return -1; } ctx->fmt_offset += size; if (arraysize) ctx->fmt_offset += (arraysize - 1) * size; --ctx->enc_count; while (1) { if (field == &ctx->root) { ctx->head = NULL; if (ctx->enc_count != 0) { __Pyx_BufFmt_RaiseExpected(ctx); return -1; } break; } ctx->head->field = ++field; if (field->type == NULL) { --ctx->head; field = ctx->head->field; continue; } else if (field->type->typegroup == 'S') { size_t parent_offset = ctx->head->parent_offset + field->offset; if (field->type->fields->type == NULL) continue; field = field->type->fields; ++ctx->head; ctx->head->field = field; ctx->head->parent_offset = parent_offset; break; } else { break; } } } while (ctx->enc_count); ctx->enc_type = 0; ctx->is_complex = 0; return 0; } static PyObject * __pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp) { const char *ts = *tsp; int i = 0, number; int ndim = ctx->head->field->type->ndim; ; ++ts; if (ctx->new_count != 1) { PyErr_SetString(PyExc_ValueError, "Cannot handle repeated arrays in format string"); return NULL; } if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; while (*ts && *ts != ')') { switch (*ts) { case ' ': case '\f': case '\r': case '\n': case '\t': case '\v': continue; default: break; } number = __Pyx_BufFmt_ExpectNumber(&ts); if (number == -1) return NULL; if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i]) return PyErr_Format(PyExc_ValueError, "Expected a dimension of size %zu, got %d", ctx->head->field->type->arraysize[i], number); if (*ts != ',' && *ts != ')') return PyErr_Format(PyExc_ValueError, "Expected a comma in format string, got '%c'", *ts); if (*ts == ',') ts++; i++; } if (i != ndim) return PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d", ctx->head->field->type->ndim, i); if (!*ts) { PyErr_SetString(PyExc_ValueError, "Unexpected end of format string, expected ')'"); return NULL; } ctx->is_valid_array = 1; ctx->new_count = 1; *tsp = ++ts; return Py_None; } static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) { int got_Z = 0; while (1) { switch(*ts) { case 0: if (ctx->enc_type != 0 && ctx->head == NULL) { __Pyx_BufFmt_RaiseExpected(ctx); return NULL; } if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; if (ctx->head != NULL) { __Pyx_BufFmt_RaiseExpected(ctx); return NULL; } return ts; case ' ': case '\r': case '\n': ++ts; break; case '<': if (!__Pyx_Is_Little_Endian()) { PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler"); return NULL; } ctx->new_packmode = '='; ++ts; break; case '>': case '!': if (__Pyx_Is_Little_Endian()) { PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler"); return NULL; } ctx->new_packmode = '='; ++ts; break; case '=': case '@': case '^': ctx->new_packmode = *ts++; break; case 'T': { const char* ts_after_sub; size_t i, struct_count = ctx->new_count; size_t struct_alignment = ctx->struct_alignment; ctx->new_count = 1; ++ts; if (*ts != '{') { PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'"); return NULL; } if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->enc_type = 0; ctx->enc_count = 0; ctx->struct_alignment = 0; ++ts; ts_after_sub = ts; for (i = 0; i != struct_count; ++i) { ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts); if (!ts_after_sub) return NULL; } ts = ts_after_sub; if (struct_alignment) ctx->struct_alignment = struct_alignment; } break; case '}': { size_t alignment = ctx->struct_alignment; ++ts; if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->enc_type = 0; if (alignment && ctx->fmt_offset % alignment) { ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment); } } return ts; case 'x': if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->fmt_offset += ctx->new_count; ctx->new_count = 1; ctx->enc_count = 0; ctx->enc_type = 0; ctx->enc_packmode = ctx->new_packmode; ++ts; break; case 'Z': got_Z = 1; ++ts; if (*ts != 'f' && *ts != 'd' && *ts != 'g') { __Pyx_BufFmt_RaiseUnexpectedChar('Z'); return NULL; } CYTHON_FALLTHROUGH; case '?': case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I': case 'l': case 'L': case 'q': case 'Q': case 'f': case 'd': case 'g': case 'O': case 'p': if (ctx->enc_type == *ts && got_Z == ctx->is_complex && ctx->enc_packmode == ctx->new_packmode) { ctx->enc_count += ctx->new_count; ctx->new_count = 1; got_Z = 0; ++ts; break; } CYTHON_FALLTHROUGH; case 's': if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->enc_count = ctx->new_count; ctx->enc_packmode = ctx->new_packmode; ctx->enc_type = *ts; ctx->is_complex = got_Z; ++ts; ctx->new_count = 1; got_Z = 0; break; case ':': ++ts; while(*ts != ':') ++ts; ++ts; break; case '(': if (!__pyx_buffmt_parse_array(ctx, &ts)) return NULL; break; default: { int number = __Pyx_BufFmt_ExpectNumber(&ts); if (number == -1) return NULL; ctx->new_count = (size_t)number; } } } } /* BufferGetAndValidate */ static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) { if (unlikely(info->buf == NULL)) return; if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL; __Pyx_ReleaseBuffer(info); } static void __Pyx_ZeroBuffer(Py_buffer* buf) { buf->buf = NULL; buf->obj = NULL; buf->strides = __Pyx_zeros; buf->shape = __Pyx_zeros; buf->suboffsets = __Pyx_minusones; } static int __Pyx__GetBufferAndValidate( Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) { buf->buf = NULL; if (unlikely(__Pyx_GetBuffer(obj, buf, flags) == -1)) { __Pyx_ZeroBuffer(buf); return -1; } if (unlikely(buf->ndim != nd)) { PyErr_Format(PyExc_ValueError, "Buffer has wrong number of dimensions (expected %d, got %d)", nd, buf->ndim); goto fail; } if (!cast) { __Pyx_BufFmt_Context ctx; __Pyx_BufFmt_Init(&ctx, stack, dtype); if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail; } if (unlikely((size_t)buf->itemsize != dtype->size)) { PyErr_Format(PyExc_ValueError, "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "d byte%s) does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "d byte%s)", buf->itemsize, (buf->itemsize > 1) ? "s" : "", dtype->name, (Py_ssize_t)dtype->size, (dtype->size > 1) ? "s" : ""); goto fail; } if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones; return 0; fail:; __Pyx_SafeReleaseBuffer(buf); return -1; } /* PyErrFetchRestore */ #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { PyObject *tmp_type, *tmp_value, *tmp_tb; tmp_type = tstate->curexc_type; tmp_value = tstate->curexc_value; tmp_tb = tstate->curexc_traceback; tstate->curexc_type = type; tstate->curexc_value = value; tstate->curexc_traceback = tb; Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); } static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { *type = tstate->curexc_type; *value = tstate->curexc_value; *tb = tstate->curexc_traceback; tstate->curexc_type = 0; tstate->curexc_value = 0; tstate->curexc_traceback = 0; } #endif /* RaiseException */ #if PY_MAJOR_VERSION < 3 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, CYTHON_UNUSED PyObject *cause) { __Pyx_PyThreadState_declare Py_XINCREF(type); if (!value || value == Py_None) value = NULL; else Py_INCREF(value); if (!tb || tb == Py_None) tb = NULL; else { Py_INCREF(tb); if (!PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto raise_error; } } if (PyType_Check(type)) { #if CYTHON_COMPILING_IN_PYPY if (!value) { Py_INCREF(Py_None); value = Py_None; } #endif PyErr_NormalizeException(&type, &value, &tb); } else { if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto raise_error; } value = type; type = (PyObject*) Py_TYPE(type); Py_INCREF(type); if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto raise_error; } } __Pyx_PyThreadState_assign __Pyx_ErrRestore(type, value, tb); return; raise_error: Py_XDECREF(value); Py_XDECREF(type); Py_XDECREF(tb); return; } #else static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { PyObject* owned_instance = NULL; if (tb == Py_None) { tb = 0; } else if (tb && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto bad; } if (value == Py_None) value = 0; if (PyExceptionInstance_Check(type)) { if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto bad; } value = type; type = (PyObject*) Py_TYPE(value); } else if (PyExceptionClass_Check(type)) { PyObject *instance_class = NULL; if (value && PyExceptionInstance_Check(value)) { instance_class = (PyObject*) Py_TYPE(value); if (instance_class != type) { int is_subclass = PyObject_IsSubclass(instance_class, type); if (!is_subclass) { instance_class = NULL; } else if (unlikely(is_subclass == -1)) { goto bad; } else { type = instance_class; } } } if (!instance_class) { PyObject *args; if (!value) args = PyTuple_New(0); else if (PyTuple_Check(value)) { Py_INCREF(value); args = value; } else args = PyTuple_Pack(1, value); if (!args) goto bad; owned_instance = PyObject_Call(type, args, NULL); Py_DECREF(args); if (!owned_instance) goto bad; value = owned_instance; if (!PyExceptionInstance_Check(value)) { PyErr_Format(PyExc_TypeError, "calling %R should have returned an instance of " "BaseException, not %R", type, Py_TYPE(value)); goto bad; } } } else { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto bad; } if (cause) { PyObject *fixed_cause; if (cause == Py_None) { fixed_cause = NULL; } else if (PyExceptionClass_Check(cause)) { fixed_cause = PyObject_CallObject(cause, NULL); if (fixed_cause == NULL) goto bad; } else if (PyExceptionInstance_Check(cause)) { fixed_cause = cause; Py_INCREF(fixed_cause); } else { PyErr_SetString(PyExc_TypeError, "exception causes must derive from " "BaseException"); goto bad; } PyException_SetCause(value, fixed_cause); } PyErr_SetObject(type, value); if (tb) { #if CYTHON_COMPILING_IN_PYPY PyObject *tmp_type, *tmp_value, *tmp_tb; PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); Py_INCREF(tb); PyErr_Restore(tmp_type, tmp_value, tb); Py_XDECREF(tmp_tb); #else PyThreadState *tstate = __Pyx_PyThreadState_Current; PyObject* tmp_tb = tstate->curexc_traceback; if (tb != tmp_tb) { Py_INCREF(tb); tstate->curexc_traceback = tb; Py_XDECREF(tmp_tb); } #endif } bad: Py_XDECREF(owned_instance); return; } #endif /* BufferIndexError */ static void __Pyx_RaiseBufferIndexError(int axis) { PyErr_Format(PyExc_IndexError, "Out of bounds on buffer access (axis %d)", axis); } /* WriteUnraisableException */ static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno, CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename, int full_traceback, CYTHON_UNUSED int nogil) { PyObject *old_exc, *old_val, *old_tb; PyObject *ctx; __Pyx_PyThreadState_declare #ifdef WITH_THREAD PyGILState_STATE state; if (nogil) state = PyGILState_Ensure(); #ifdef _MSC_VER else state = (PyGILState_STATE)-1; #endif #endif __Pyx_PyThreadState_assign __Pyx_ErrFetch(&old_exc, &old_val, &old_tb); if (full_traceback) { Py_XINCREF(old_exc); Py_XINCREF(old_val); Py_XINCREF(old_tb); __Pyx_ErrRestore(old_exc, old_val, old_tb); PyErr_PrintEx(1); } #if PY_MAJOR_VERSION < 3 ctx = PyString_FromString(name); #else ctx = PyUnicode_FromString(name); #endif __Pyx_ErrRestore(old_exc, old_val, old_tb); if (!ctx) { PyErr_WriteUnraisable(Py_None); } else { PyErr_WriteUnraisable(ctx); Py_DECREF(ctx); } #ifdef WITH_THREAD if (nogil) PyGILState_Release(state); #endif } /* PyCFunctionFastCall */ #if CYTHON_FAST_PYCCALL static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { PyCFunctionObject *func = (PyCFunctionObject*)func_obj; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); int flags = PyCFunction_GET_FLAGS(func); assert(PyCFunction_Check(func)); assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); assert(nargs >= 0); assert(nargs == 0 || args != NULL); /* _PyCFunction_FastCallDict() must not be called with an exception set, because it may clear it (directly or indirectly) and so the caller loses its exception */ assert(!PyErr_Occurred()); if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); } else { return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); } } #endif /* PyFunctionFastCall */ #if CYTHON_FAST_PYCALL static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, PyObject *globals) { PyFrameObject *f; PyThreadState *tstate = __Pyx_PyThreadState_Current; PyObject **fastlocals; Py_ssize_t i; PyObject *result; assert(globals != NULL); /* XXX Perhaps we should create a specialized PyFrame_New() that doesn't take locals, but does take builtins without sanity checking them. */ assert(tstate != NULL); f = PyFrame_New(tstate, co, globals, NULL); if (f == NULL) { return NULL; } fastlocals = __Pyx_PyFrame_GetLocalsplus(f); for (i = 0; i < na; i++) { Py_INCREF(*args); fastlocals[i] = *args++; } result = PyEval_EvalFrameEx(f,0); ++tstate->recursion_depth; Py_DECREF(f); --tstate->recursion_depth; return result; } #if 1 || PY_VERSION_HEX < 0x030600B1 static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func); PyObject *closure; #if PY_MAJOR_VERSION >= 3 PyObject *kwdefs; #endif PyObject *kwtuple, **k; PyObject **d; Py_ssize_t nd; Py_ssize_t nk; PyObject *result; assert(kwargs == NULL || PyDict_Check(kwargs)); nk = kwargs ? PyDict_Size(kwargs) : 0; if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { return NULL; } if ( #if PY_MAJOR_VERSION >= 3 co->co_kwonlyargcount == 0 && #endif likely(kwargs == NULL || nk == 0) && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { if (argdefs == NULL && co->co_argcount == nargs) { result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); goto done; } else if (nargs == 0 && argdefs != NULL && co->co_argcount == Py_SIZE(argdefs)) { /* function called with no arguments, but all parameters have a default value: use default values as arguments .*/ args = &PyTuple_GET_ITEM(argdefs, 0); result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); goto done; } } if (kwargs != NULL) { Py_ssize_t pos, i; kwtuple = PyTuple_New(2 * nk); if (kwtuple == NULL) { result = NULL; goto done; } k = &PyTuple_GET_ITEM(kwtuple, 0); pos = i = 0; while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { Py_INCREF(k[i]); Py_INCREF(k[i+1]); i += 2; } nk = i / 2; } else { kwtuple = NULL; k = NULL; } closure = PyFunction_GET_CLOSURE(func); #if PY_MAJOR_VERSION >= 3 kwdefs = PyFunction_GET_KW_DEFAULTS(func); #endif if (argdefs != NULL) { d = &PyTuple_GET_ITEM(argdefs, 0); nd = Py_SIZE(argdefs); } else { d = NULL; nd = 0; } #if PY_MAJOR_VERSION >= 3 result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, args, (int)nargs, k, (int)nk, d, (int)nd, kwdefs, closure); #else result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, args, (int)nargs, k, (int)nk, d, (int)nd, closure); #endif Py_XDECREF(kwtuple); done: Py_LeaveRecursiveCall(); return result; } #endif #endif /* PyObjectCallMethO */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { PyObject *self, *result; PyCFunction cfunc; cfunc = PyCFunction_GET_FUNCTION(func); self = PyCFunction_GET_SELF(func); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) return NULL; result = cfunc(self, arg); Py_LeaveRecursiveCall(); if (unlikely(!result) && unlikely(!PyErr_Occurred())) { PyErr_SetString( PyExc_SystemError, "NULL result without error in PyObject_Call"); } return result; } #endif /* PyObjectCallOneArg */ #if CYTHON_COMPILING_IN_CPYTHON static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { PyObject *result; PyObject *args = PyTuple_New(1); if (unlikely(!args)) return NULL; Py_INCREF(arg); PyTuple_SET_ITEM(args, 0, arg); result = __Pyx_PyObject_Call(func, args, NULL); Py_DECREF(args); return result; } static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { #if CYTHON_FAST_PYCALL if (PyFunction_Check(func)) { return __Pyx_PyFunction_FastCall(func, &arg, 1); } #endif if (likely(PyCFunction_Check(func))) { if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { return __Pyx_PyObject_CallMethO(func, arg); #if CYTHON_FAST_PYCCALL } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { return __Pyx_PyCFunction_FastCall(func, &arg, 1); #endif } } return __Pyx__PyObject_CallOneArg(func, arg); } #else static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { PyObject *result; PyObject *args = PyTuple_Pack(1, arg); if (unlikely(!args)) return NULL; result = __Pyx_PyObject_Call(func, args, NULL); Py_DECREF(args); return result; } #endif /* DictGetItem */ #if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) { PyObject *value; value = PyDict_GetItemWithError(d, key); if (unlikely(!value)) { if (!PyErr_Occurred()) { if (unlikely(PyTuple_Check(key))) { PyObject* args = PyTuple_Pack(1, key); if (likely(args)) { PyErr_SetObject(PyExc_KeyError, args); Py_DECREF(args); } } else { PyErr_SetObject(PyExc_KeyError, key); } } return NULL; } Py_INCREF(value); return value; } #endif /* RaiseTooManyValuesToUnpack */ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { PyErr_Format(PyExc_ValueError, "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); } /* RaiseNeedMoreValuesToUnpack */ static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { PyErr_Format(PyExc_ValueError, "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", index, (index == 1) ? "" : "s"); } /* RaiseNoneIterError */ static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); } /* GetTopmostException */ #if CYTHON_USE_EXC_INFO_STACK static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate) { _PyErr_StackItem *exc_info = tstate->exc_info; while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && exc_info->previous_item != NULL) { exc_info = exc_info->previous_item; } return exc_info; } #endif /* SaveResetException */ #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { #if CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); *type = exc_info->exc_type; *value = exc_info->exc_value; *tb = exc_info->exc_traceback; #else *type = tstate->exc_type; *value = tstate->exc_value; *tb = tstate->exc_traceback; #endif Py_XINCREF(*type); Py_XINCREF(*value); Py_XINCREF(*tb); } static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { PyObject *tmp_type, *tmp_value, *tmp_tb; #if CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = tstate->exc_info; tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; tmp_tb = exc_info->exc_traceback; exc_info->exc_type = type; exc_info->exc_value = value; exc_info->exc_traceback = tb; #else tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; tstate->exc_type = type; tstate->exc_value = value; tstate->exc_traceback = tb; #endif Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); } #endif /* PyErrExceptionMatches */ #if CYTHON_FAST_THREAD_STATE static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { Py_ssize_t i, n; n = PyTuple_GET_SIZE(tuple); #if PY_MAJOR_VERSION >= 3 for (i=0; icurexc_type; if (exc_type == err) return 1; if (unlikely(!exc_type)) return 0; if (unlikely(PyTuple_Check(err))) return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); } #endif /* GetException */ #if CYTHON_FAST_THREAD_STATE static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) #else static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) #endif { PyObject *local_type, *local_value, *local_tb; #if CYTHON_FAST_THREAD_STATE PyObject *tmp_type, *tmp_value, *tmp_tb; local_type = tstate->curexc_type; local_value = tstate->curexc_value; local_tb = tstate->curexc_traceback; tstate->curexc_type = 0; tstate->curexc_value = 0; tstate->curexc_traceback = 0; #else PyErr_Fetch(&local_type, &local_value, &local_tb); #endif PyErr_NormalizeException(&local_type, &local_value, &local_tb); #if CYTHON_FAST_THREAD_STATE if (unlikely(tstate->curexc_type)) #else if (unlikely(PyErr_Occurred())) #endif goto bad; #if PY_MAJOR_VERSION >= 3 if (local_tb) { if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) goto bad; } #endif Py_XINCREF(local_tb); Py_XINCREF(local_type); Py_XINCREF(local_value); *type = local_type; *value = local_value; *tb = local_tb; #if CYTHON_FAST_THREAD_STATE #if CYTHON_USE_EXC_INFO_STACK { _PyErr_StackItem *exc_info = tstate->exc_info; tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; tmp_tb = exc_info->exc_traceback; exc_info->exc_type = local_type; exc_info->exc_value = local_value; exc_info->exc_traceback = local_tb; } #else tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; tstate->exc_type = local_type; tstate->exc_value = local_value; tstate->exc_traceback = local_tb; #endif Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); #else PyErr_SetExcInfo(local_type, local_value, local_tb); #endif return 0; bad: *type = 0; *value = 0; *tb = 0; Py_XDECREF(local_type); Py_XDECREF(local_value); Py_XDECREF(local_tb); return -1; } /* TypeImport */ #ifndef __PYX_HAVE_RT_ImportType #define __PYX_HAVE_RT_ImportType static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size) { PyObject *result = 0; char warning[200]; Py_ssize_t basicsize; #ifdef Py_LIMITED_API PyObject *py_basicsize; #endif result = PyObject_GetAttrString(module, class_name); if (!result) goto bad; if (!PyType_Check(result)) { PyErr_Format(PyExc_TypeError, "%.200s.%.200s is not a type object", module_name, class_name); goto bad; } #ifndef Py_LIMITED_API basicsize = ((PyTypeObject *)result)->tp_basicsize; #else py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); if (!py_basicsize) goto bad; basicsize = PyLong_AsSsize_t(py_basicsize); Py_DECREF(py_basicsize); py_basicsize = 0; if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) goto bad; #endif if ((size_t)basicsize < size) { PyErr_Format(PyExc_ValueError, "%.200s.%.200s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); goto bad; } if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { PyErr_Format(PyExc_ValueError, "%.200s.%.200s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); goto bad; } else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { PyOS_snprintf(warning, sizeof(warning), "%s.%s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; } return (PyTypeObject *)result; bad: Py_XDECREF(result); return NULL; } #endif /* Import */ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { PyObject *empty_list = 0; PyObject *module = 0; PyObject *global_dict = 0; PyObject *empty_dict = 0; PyObject *list; #if PY_MAJOR_VERSION < 3 PyObject *py_import; py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); if (!py_import) goto bad; #endif if (from_list) list = from_list; else { empty_list = PyList_New(0); if (!empty_list) goto bad; list = empty_list; } global_dict = PyModule_GetDict(__pyx_m); if (!global_dict) goto bad; empty_dict = PyDict_New(); if (!empty_dict) goto bad; { #if PY_MAJOR_VERSION >= 3 if (level == -1) { if (strchr(__Pyx_MODULE_NAME, '.')) { module = PyImport_ImportModuleLevelObject( name, global_dict, empty_dict, list, 1); if (!module) { if (!PyErr_ExceptionMatches(PyExc_ImportError)) goto bad; PyErr_Clear(); } } level = 0; } #endif if (!module) { #if PY_MAJOR_VERSION < 3 PyObject *py_level = PyInt_FromLong(level); if (!py_level) goto bad; module = PyObject_CallFunctionObjArgs(py_import, name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); Py_DECREF(py_level); #else module = PyImport_ImportModuleLevelObject( name, global_dict, empty_dict, list, level); #endif } } bad: #if PY_MAJOR_VERSION < 3 Py_XDECREF(py_import); #endif Py_XDECREF(empty_list); Py_XDECREF(empty_dict); return module; } /* CLineInTraceback */ #ifndef CYTHON_CLINE_IN_TRACEBACK static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { PyObject *use_cline; PyObject *ptype, *pvalue, *ptraceback; #if CYTHON_COMPILING_IN_CPYTHON PyObject **cython_runtime_dict; #endif if (unlikely(!__pyx_cython_runtime)) { return c_line; } __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); #if CYTHON_COMPILING_IN_CPYTHON cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); if (likely(cython_runtime_dict)) { __PYX_PY_DICT_LOOKUP_IF_MODIFIED( use_cline, *cython_runtime_dict, __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) } else #endif { PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); if (use_cline_obj) { use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; Py_DECREF(use_cline_obj); } else { PyErr_Clear(); use_cline = NULL; } } if (!use_cline) { c_line = 0; PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); } else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { c_line = 0; } __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); return c_line; } #endif /* CodeObjectCache */ static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { int start = 0, mid = 0, end = count - 1; if (end >= 0 && code_line > entries[end].code_line) { return count; } while (start < end) { mid = start + (end - start) / 2; if (code_line < entries[mid].code_line) { end = mid; } else if (code_line > entries[mid].code_line) { start = mid + 1; } else { return mid; } } if (code_line <= entries[mid].code_line) { return mid; } else { return mid + 1; } } static PyCodeObject *__pyx_find_code_object(int code_line) { PyCodeObject* code_object; int pos; if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { return NULL; } pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { return NULL; } code_object = __pyx_code_cache.entries[pos].code_object; Py_INCREF(code_object); return code_object; } static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { int pos, i; __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; if (unlikely(!code_line)) { return; } if (unlikely(!entries)) { entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); if (likely(entries)) { __pyx_code_cache.entries = entries; __pyx_code_cache.max_count = 64; __pyx_code_cache.count = 1; entries[0].code_line = code_line; entries[0].code_object = code_object; Py_INCREF(code_object); } return; } pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { PyCodeObject* tmp = entries[pos].code_object; entries[pos].code_object = code_object; Py_DECREF(tmp); return; } if (__pyx_code_cache.count == __pyx_code_cache.max_count) { int new_max = __pyx_code_cache.max_count + 64; entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( __pyx_code_cache.entries, (size_t)new_max*sizeof(__Pyx_CodeObjectCacheEntry)); if (unlikely(!entries)) { return; } __pyx_code_cache.entries = entries; __pyx_code_cache.max_count = new_max; } for (i=__pyx_code_cache.count; i>pos; i--) { entries[i] = entries[i-1]; } entries[pos].code_line = code_line; entries[pos].code_object = code_object; __pyx_code_cache.count++; Py_INCREF(code_object); } /* AddTraceback */ #include "compile.h" #include "frameobject.h" #include "traceback.h" static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( const char *funcname, int c_line, int py_line, const char *filename) { PyCodeObject *py_code = 0; PyObject *py_srcfile = 0; PyObject *py_funcname = 0; #if PY_MAJOR_VERSION < 3 py_srcfile = PyString_FromString(filename); #else py_srcfile = PyUnicode_FromString(filename); #endif if (!py_srcfile) goto bad; if (c_line) { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); #else py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); #endif } else { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromString(funcname); #else py_funcname = PyUnicode_FromString(funcname); #endif } if (!py_funcname) goto bad; py_code = __Pyx_PyCode_New( 0, 0, 0, 0, 0, __pyx_empty_bytes, /*PyObject *code,*/ __pyx_empty_tuple, /*PyObject *consts,*/ __pyx_empty_tuple, /*PyObject *names,*/ __pyx_empty_tuple, /*PyObject *varnames,*/ __pyx_empty_tuple, /*PyObject *freevars,*/ __pyx_empty_tuple, /*PyObject *cellvars,*/ py_srcfile, /*PyObject *filename,*/ py_funcname, /*PyObject *name,*/ py_line, __pyx_empty_bytes /*PyObject *lnotab*/ ); Py_DECREF(py_srcfile); Py_DECREF(py_funcname); return py_code; bad: Py_XDECREF(py_srcfile); Py_XDECREF(py_funcname); return NULL; } static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename) { PyCodeObject *py_code = 0; PyFrameObject *py_frame = 0; PyThreadState *tstate = __Pyx_PyThreadState_Current; if (c_line) { c_line = __Pyx_CLineForTraceback(tstate, c_line); } py_code = __pyx_find_code_object(c_line ? -c_line : py_line); if (!py_code) { py_code = __Pyx_CreateCodeObjectForTraceback( funcname, c_line, py_line, filename); if (!py_code) goto bad; __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); } py_frame = PyFrame_New( tstate, /*PyThreadState *tstate,*/ py_code, /*PyCodeObject *code,*/ __pyx_d, /*PyObject *globals,*/ 0 /*PyObject *locals*/ ); if (!py_frame) goto bad; __Pyx_PyFrame_SetLineNumber(py_frame, py_line); PyTraceBack_Here(py_frame); bad: Py_XDECREF(py_code); Py_XDECREF(py_frame); } #if PY_MAJOR_VERSION < 3 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags); if (__Pyx_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pw_5numpy_7ndarray_1__getbuffer__(obj, view, flags); PyErr_Format(PyExc_TypeError, "'%.200s' does not have the buffer interface", Py_TYPE(obj)->tp_name); return -1; } static void __Pyx_ReleaseBuffer(Py_buffer *view) { PyObject *obj = view->obj; if (!obj) return; if (PyObject_CheckBuffer(obj)) { PyBuffer_Release(view); return; } if ((0)) {} else if (__Pyx_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) __pyx_pw_5numpy_7ndarray_3__releasebuffer__(obj, view); view->obj = NULL; Py_DECREF(obj); } #endif /* CIntFromPyVerify */ #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) #define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) #define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ {\ func_type value = func_value;\ if (sizeof(target_type) < sizeof(func_type)) {\ if (unlikely(value != (func_type) (target_type) value)) {\ func_type zero = 0;\ if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ return (target_type) -1;\ if (is_unsigned && unlikely(value < zero))\ goto raise_neg_overflow;\ else\ goto raise_overflow;\ }\ }\ return (target_type) value;\ } /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(int) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(int) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof(int) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; return _PyLong_FromByteArray(bytes, sizeof(int), little, !is_unsigned); } } /* Declarations */ #if CYTHON_CCOMPLEX #ifdef __cplusplus static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { return ::std::complex< float >(x, y); } #else static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { return x + y*(__pyx_t_float_complex)_Complex_I; } #endif #else static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { __pyx_t_float_complex z; z.real = x; z.imag = y; return z; } #endif /* Arithmetic */ #if CYTHON_CCOMPLEX #else static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { return (a.real == b.real) && (a.imag == b.imag); } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; z.real = a.real + b.real; z.imag = a.imag + b.imag; return z; } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; z.real = a.real - b.real; z.imag = a.imag - b.imag; return z; } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; z.real = a.real * b.real - a.imag * b.imag; z.imag = a.real * b.imag + a.imag * b.real; return z; } #if 1 static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { if (b.imag == 0) { return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); } else if (fabsf(b.real) >= fabsf(b.imag)) { if (b.real == 0 && b.imag == 0) { return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.imag); } else { float r = b.imag / b.real; float s = (float)(1.0) / (b.real + b.imag * r); return __pyx_t_float_complex_from_parts( (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); } } else { float r = b.real / b.imag; float s = (float)(1.0) / (b.imag + b.real * r); return __pyx_t_float_complex_from_parts( (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); } } #else static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { if (b.imag == 0) { return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); } else { float denom = b.real * b.real + b.imag * b.imag; return __pyx_t_float_complex_from_parts( (a.real * b.real + a.imag * b.imag) / denom, (a.imag * b.real - a.real * b.imag) / denom); } } #endif static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex a) { __pyx_t_float_complex z; z.real = -a.real; z.imag = -a.imag; return z; } static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex a) { return (a.real == 0) && (a.imag == 0); } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex a) { __pyx_t_float_complex z; z.real = a.real; z.imag = -a.imag; return z; } #if 1 static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex z) { #if !defined(HAVE_HYPOT) || defined(_MSC_VER) return sqrtf(z.real*z.real + z.imag*z.imag); #else return hypotf(z.real, z.imag); #endif } static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { __pyx_t_float_complex z; float r, lnr, theta, z_r, z_theta; if (b.imag == 0 && b.real == (int)b.real) { if (b.real < 0) { float denom = a.real * a.real + a.imag * a.imag; a.real = a.real / denom; a.imag = -a.imag / denom; b.real = -b.real; } switch ((int)b.real) { case 0: z.real = 1; z.imag = 0; return z; case 1: return a; case 2: return __Pyx_c_prod_float(a, a); case 3: z = __Pyx_c_prod_float(a, a); return __Pyx_c_prod_float(z, a); case 4: z = __Pyx_c_prod_float(a, a); return __Pyx_c_prod_float(z, z); } } if (a.imag == 0) { if (a.real == 0) { return a; } else if (b.imag == 0) { z.real = powf(a.real, b.real); z.imag = 0; return z; } else if (a.real > 0) { r = a.real; theta = 0; } else { r = -a.real; theta = atan2f(0.0, -1.0); } } else { r = __Pyx_c_abs_float(a); theta = atan2f(a.imag, a.real); } lnr = logf(r); z_r = expf(lnr * b.real - theta * b.imag); z_theta = theta * b.real + lnr * b.imag; z.real = z_r * cosf(z_theta); z.imag = z_r * sinf(z_theta); return z; } #endif #endif /* Declarations */ #if CYTHON_CCOMPLEX #ifdef __cplusplus static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { return ::std::complex< double >(x, y); } #else static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { return x + y*(__pyx_t_double_complex)_Complex_I; } #endif #else static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { __pyx_t_double_complex z; z.real = x; z.imag = y; return z; } #endif /* Arithmetic */ #if CYTHON_CCOMPLEX #else static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { return (a.real == b.real) && (a.imag == b.imag); } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; z.real = a.real + b.real; z.imag = a.imag + b.imag; return z; } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; z.real = a.real - b.real; z.imag = a.imag - b.imag; return z; } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; z.real = a.real * b.real - a.imag * b.imag; z.imag = a.real * b.imag + a.imag * b.real; return z; } #if 1 static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { if (b.imag == 0) { return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); } else if (fabs(b.real) >= fabs(b.imag)) { if (b.real == 0 && b.imag == 0) { return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.imag); } else { double r = b.imag / b.real; double s = (double)(1.0) / (b.real + b.imag * r); return __pyx_t_double_complex_from_parts( (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); } } else { double r = b.real / b.imag; double s = (double)(1.0) / (b.imag + b.real * r); return __pyx_t_double_complex_from_parts( (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); } } #else static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { if (b.imag == 0) { return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); } else { double denom = b.real * b.real + b.imag * b.imag; return __pyx_t_double_complex_from_parts( (a.real * b.real + a.imag * b.imag) / denom, (a.imag * b.real - a.real * b.imag) / denom); } } #endif static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex a) { __pyx_t_double_complex z; z.real = -a.real; z.imag = -a.imag; return z; } static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex a) { return (a.real == 0) && (a.imag == 0); } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex a) { __pyx_t_double_complex z; z.real = a.real; z.imag = -a.imag; return z; } #if 1 static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex z) { #if !defined(HAVE_HYPOT) || defined(_MSC_VER) return sqrt(z.real*z.real + z.imag*z.imag); #else return hypot(z.real, z.imag); #endif } static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { __pyx_t_double_complex z; double r, lnr, theta, z_r, z_theta; if (b.imag == 0 && b.real == (int)b.real) { if (b.real < 0) { double denom = a.real * a.real + a.imag * a.imag; a.real = a.real / denom; a.imag = -a.imag / denom; b.real = -b.real; } switch ((int)b.real) { case 0: z.real = 1; z.imag = 0; return z; case 1: return a; case 2: return __Pyx_c_prod_double(a, a); case 3: z = __Pyx_c_prod_double(a, a); return __Pyx_c_prod_double(z, a); case 4: z = __Pyx_c_prod_double(a, a); return __Pyx_c_prod_double(z, z); } } if (a.imag == 0) { if (a.real == 0) { return a; } else if (b.imag == 0) { z.real = pow(a.real, b.real); z.imag = 0; return z; } else if (a.real > 0) { r = a.real; theta = 0; } else { r = -a.real; theta = atan2(0.0, -1.0); } } else { r = __Pyx_c_abs_double(a); theta = atan2(a.imag, a.real); } lnr = log(r); z_r = exp(lnr * b.real - theta * b.imag); z_theta = theta * b.real + lnr * b.imag; z.real = z_r * cos(z_theta); z.imag = z_r * sin(z_theta); return z; } #endif #endif /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__NPY_TYPES(enum NPY_TYPES value) { const enum NPY_TYPES neg_one = (enum NPY_TYPES) ((enum NPY_TYPES) 0 - (enum NPY_TYPES) 1), const_zero = (enum NPY_TYPES) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(enum NPY_TYPES) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(enum NPY_TYPES) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(enum NPY_TYPES) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof(enum NPY_TYPES) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(enum NPY_TYPES) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; return _PyLong_FromByteArray(bytes, sizeof(enum NPY_TYPES), little, !is_unsigned); } } /* CIntFromPy */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { if (sizeof(int) < sizeof(long)) { __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } return (int) val; } } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (int) 0; case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) case 2: if (8 * sizeof(int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); } } break; case 3: if (8 * sizeof(int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); } } break; case 4: if (8 * sizeof(int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); } } break; } #endif #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { goto raise_neg_overflow; } #else { int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) return (int) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif if (sizeof(int) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (int) 0; case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) case -2: if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case 2: if (8 * sizeof(int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case -3: if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case 3: if (8 * sizeof(int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case -4: if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; case 4: if (8 * sizeof(int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); } } break; } #endif if (sizeof(int) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } { #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); #else int val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { PyObject *tmp = v; v = PyNumber_Long(tmp); Py_DECREF(tmp); } #endif if (likely(v)) { int one = 1; int is_little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&val; int ret = _PyLong_AsByteArray((PyLongObject *)v, bytes, sizeof(val), is_little, !is_unsigned); Py_DECREF(v); if (likely(!ret)) return val; } #endif return (int) -1; } } else { int val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); if (!tmp) return (int) -1; val = __Pyx_PyInt_As_int(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, "value too large to convert to int"); return (int) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, "can't convert negative value to int"); return (int) -1; } /* CIntFromPy */ static CYTHON_INLINE unsigned int __Pyx_PyInt_As_unsigned_int(PyObject *x) { const unsigned int neg_one = (unsigned int) ((unsigned int) 0 - (unsigned int) 1), const_zero = (unsigned int) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { if (sizeof(unsigned int) < sizeof(long)) { __PYX_VERIFY_RETURN_INT(unsigned int, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } return (unsigned int) val; } } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (unsigned int) 0; case 1: __PYX_VERIFY_RETURN_INT(unsigned int, digit, digits[0]) case 2: if (8 * sizeof(unsigned int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) >= 2 * PyLong_SHIFT) { return (unsigned int) (((((unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])); } } break; case 3: if (8 * sizeof(unsigned int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) >= 3 * PyLong_SHIFT) { return (unsigned int) (((((((unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])); } } break; case 4: if (8 * sizeof(unsigned int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) >= 4 * PyLong_SHIFT) { return (unsigned int) (((((((((unsigned int)digits[3]) << PyLong_SHIFT) | (unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])); } } break; } #endif #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { goto raise_neg_overflow; } #else { int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) return (unsigned int) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif if (sizeof(unsigned int) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(unsigned int, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(unsigned int) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(unsigned int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (unsigned int) 0; case -1: __PYX_VERIFY_RETURN_INT(unsigned int, sdigit, (sdigit) (-(sdigit)digits[0])) case 1: __PYX_VERIFY_RETURN_INT(unsigned int, digit, +digits[0]) case -2: if (8 * sizeof(unsigned int) - 1 > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 2 * PyLong_SHIFT) { return (unsigned int) (((unsigned int)-1)*(((((unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case 2: if (8 * sizeof(unsigned int) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 2 * PyLong_SHIFT) { return (unsigned int) ((((((unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case -3: if (8 * sizeof(unsigned int) - 1 > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 3 * PyLong_SHIFT) { return (unsigned int) (((unsigned int)-1)*(((((((unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case 3: if (8 * sizeof(unsigned int) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 3 * PyLong_SHIFT) { return (unsigned int) ((((((((unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case -4: if (8 * sizeof(unsigned int) - 1 > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 4 * PyLong_SHIFT) { return (unsigned int) (((unsigned int)-1)*(((((((((unsigned int)digits[3]) << PyLong_SHIFT) | (unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; case 4: if (8 * sizeof(unsigned int) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(unsigned int) - 1 > 4 * PyLong_SHIFT) { return (unsigned int) ((((((((((unsigned int)digits[3]) << PyLong_SHIFT) | (unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]))); } } break; } #endif if (sizeof(unsigned int) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(unsigned int, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(unsigned int) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(unsigned int, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } { #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); #else unsigned int val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { PyObject *tmp = v; v = PyNumber_Long(tmp); Py_DECREF(tmp); } #endif if (likely(v)) { int one = 1; int is_little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&val; int ret = _PyLong_AsByteArray((PyLongObject *)v, bytes, sizeof(val), is_little, !is_unsigned); Py_DECREF(v); if (likely(!ret)) return val; } #endif return (unsigned int) -1; } } else { unsigned int val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); if (!tmp) return (unsigned int) -1; val = __Pyx_PyInt_As_unsigned_int(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, "value too large to convert to unsigned int"); return (unsigned int) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, "can't convert negative value to unsigned int"); return (unsigned int) -1; } /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(long) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(long) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof(long) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; return _PyLong_FromByteArray(bytes, sizeof(long), little, !is_unsigned); } } /* CIntFromPy */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { if (sizeof(long) < sizeof(long)) { __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } return (long) val; } } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (long) 0; case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) case 2: if (8 * sizeof(long) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); } } break; case 3: if (8 * sizeof(long) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); } } break; case 4: if (8 * sizeof(long) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); } } break; } #endif #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { goto raise_neg_overflow; } #else { int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) return (long) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif if (sizeof(long) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { case 0: return (long) 0; case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) case -2: if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case 2: if (8 * sizeof(long) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case -3: if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case 3: if (8 * sizeof(long) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case -4: if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; case 4: if (8 * sizeof(long) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); } } break; } #endif if (sizeof(long) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } { #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); #else long val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { PyObject *tmp = v; v = PyNumber_Long(tmp); Py_DECREF(tmp); } #endif if (likely(v)) { int one = 1; int is_little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&val; int ret = _PyLong_AsByteArray((PyLongObject *)v, bytes, sizeof(val), is_little, !is_unsigned); Py_DECREF(v); if (likely(!ret)) return val; } #endif return (long) -1; } } else { long val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); if (!tmp) return (long) -1; val = __Pyx_PyInt_As_long(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, "value too large to convert to long"); return (long) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, "can't convert negative value to long"); return (long) -1; } /* FastTypeChecks */ #if CYTHON_COMPILING_IN_CPYTHON static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { while (a) { a = a->tp_base; if (a == b) return 1; } return b == &PyBaseObject_Type; } static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { PyObject *mro; if (a == b) return 1; mro = a->tp_mro; if (likely(mro)) { Py_ssize_t i, n; n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) return 1; } return 0; } return __Pyx_InBases(a, b); } #if PY_MAJOR_VERSION == 2 static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { PyObject *exception, *value, *tb; int res; __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ErrFetch(&exception, &value, &tb); res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; if (unlikely(res == -1)) { PyErr_WriteUnraisable(err); res = 0; } if (!res) { res = PyObject_IsSubclass(err, exc_type2); if (unlikely(res == -1)) { PyErr_WriteUnraisable(err); res = 0; } } __Pyx_ErrRestore(exception, value, tb); return res; } #else static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; if (!res) { res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); } return res; } #endif static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { Py_ssize_t i, n; assert(PyExceptionClass_Check(exc_type)); n = PyTuple_GET_SIZE(tuple); #if PY_MAJOR_VERSION >= 3 for (i=0; ip) { #if PY_MAJOR_VERSION < 3 if (t->is_unicode) { *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); } else if (t->intern) { *t->p = PyString_InternFromString(t->s); } else { *t->p = PyString_FromStringAndSize(t->s, t->n - 1); } #else if (t->is_unicode | t->is_str) { if (t->intern) { *t->p = PyUnicode_InternFromString(t->s); } else if (t->encoding) { *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); } else { *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); } } else { *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); } #endif if (!*t->p) return -1; if (PyObject_Hash(*t->p) == -1) return -1; ++t; } return 0; } static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); } static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { Py_ssize_t ignore; return __Pyx_PyObject_AsStringAndSize(o, &ignore); } #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT #if !CYTHON_PEP393_ENABLED static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { char* defenc_c; PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); if (!defenc) return NULL; defenc_c = PyBytes_AS_STRING(defenc); #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII { char* end = defenc_c + PyBytes_GET_SIZE(defenc); char* c; for (c = defenc_c; c < end; c++) { if ((unsigned char) (*c) >= 128) { PyUnicode_AsASCIIString(o); return NULL; } } } #endif *length = PyBytes_GET_SIZE(defenc); return defenc_c; } #else static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII if (likely(PyUnicode_IS_ASCII(o))) { *length = PyUnicode_GET_LENGTH(o); return PyUnicode_AsUTF8(o); } else { PyUnicode_AsASCIIString(o); return NULL; } #else return PyUnicode_AsUTF8AndSize(o, length); #endif } #endif #endif static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT if ( #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII __Pyx_sys_getdefaultencoding_not_ascii && #endif PyUnicode_Check(o)) { return __Pyx_PyUnicode_AsStringAndSize(o, length); } else #endif #if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) if (PyByteArray_Check(o)) { *length = PyByteArray_GET_SIZE(o); return PyByteArray_AS_STRING(o); } else #endif { char* result; int r = PyBytes_AsStringAndSize(o, &result, length); if (unlikely(r < 0)) { return NULL; } else { return result; } } } static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { int is_true = x == Py_True; if (is_true | (x == Py_False) | (x == Py_None)) return is_true; else return PyObject_IsTrue(x); } static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { int retval; if (unlikely(!x)) return -1; retval = __Pyx_PyObject_IsTrue(x); Py_DECREF(x); return retval; } static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { #if PY_MAJOR_VERSION >= 3 if (PyLong_Check(result)) { if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, "__int__ returned non-int (type %.200s). " "The ability to return an instance of a strict subclass of int " "is deprecated, and may be removed in a future version of Python.", Py_TYPE(result)->tp_name)) { Py_DECREF(result); return NULL; } return result; } #endif PyErr_Format(PyExc_TypeError, "__%.4s__ returned non-%.4s (type %.200s)", type_name, type_name, Py_TYPE(result)->tp_name); Py_DECREF(result); return NULL; } static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { #if CYTHON_USE_TYPE_SLOTS PyNumberMethods *m; #endif const char *name = NULL; PyObject *res = NULL; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x) || PyLong_Check(x))) #else if (likely(PyLong_Check(x))) #endif return __Pyx_NewRef(x); #if CYTHON_USE_TYPE_SLOTS m = Py_TYPE(x)->tp_as_number; #if PY_MAJOR_VERSION < 3 if (m && m->nb_int) { name = "int"; res = m->nb_int(x); } else if (m && m->nb_long) { name = "long"; res = m->nb_long(x); } #else if (likely(m && m->nb_int)) { name = "int"; res = m->nb_int(x); } #endif #else if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { res = PyNumber_Int(x); } #endif if (likely(res)) { #if PY_MAJOR_VERSION < 3 if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { #else if (unlikely(!PyLong_CheckExact(res))) { #endif return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); } } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "an integer is required"); } return res; } static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { Py_ssize_t ival; PyObject *x; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_CheckExact(b))) { if (sizeof(Py_ssize_t) >= sizeof(long)) return PyInt_AS_LONG(b); else return PyInt_AsSsize_t(b); } #endif if (likely(PyLong_CheckExact(b))) { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)b)->ob_digit; const Py_ssize_t size = Py_SIZE(b); if (likely(__Pyx_sst_abs(size) <= 1)) { ival = likely(size) ? digits[0] : 0; if (size == -1) ival = -ival; return ival; } else { switch (size) { case 2: if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case -2: if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case 3: if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case -3: if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case 4: if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; case -4: if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); } break; } } #endif return PyLong_AsSsize_t(b); } x = PyNumber_Index(b); if (!x) return -1; ival = PyInt_AsSsize_t(x); Py_DECREF(x); return ival; } static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); } static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { return PyInt_FromSize_t(ival); } #endif /* Py_PYTHON_H */ photutils-0.7.2/photutils/geometry/rectangular_overlap.pyx0000644000214200020070000000775513563423715026454 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst #cython: language_level=3 """ This module provides tools to calculate the area of overlap between a rectangle and a pixel grid. """ import numpy as np cimport numpy as np __all__ = ['rectangular_overlap_grid'] cdef extern from "math.h": double asin(double x) double sin(double x) double cos(double x) double sqrt(double x) double fabs(double x) from cpython cimport bool DTYPE = np.float64 ctypedef np.float64_t DTYPE_t cimport cython def rectangular_overlap_grid(double xmin, double xmax, double ymin, double ymax, int nx, int ny, double width, double height, double theta, int use_exact, int subpixels): """ rectangular_overlap_grid(xmin, xmax, ymin, ymax, nx, ny, width, height, use_exact, subpixels) Area of overlap between a rectangle and a pixel grid. The rectangle is centered on the origin. Parameters ---------- xmin, xmax, ymin, ymax : float Extent of the grid in the x and y direction. nx, ny : int Grid dimensions. width : float The width of the rectangle height : float The height of the rectangle theta : float The position angle of the rectangle in radians (counterclockwise). use_exact : 0 or 1 If set to 1, calculates the exact overlap, while if set to 0, uses a subpixel sampling method with ``subpixel`` subpixels in each direction. subpixels : int If ``use_exact`` is 0, each pixel is resampled by this factor in each dimension. Thus, each pixel is divided into ``subpixels ** 2`` subpixels. Returns ------- frac : `~numpy.ndarray` 2-d array giving the fraction of the overlap. """ cdef unsigned int i, j cdef double x, y, dx, dy cdef double pxmin, pxmax, pymin, pymax # Define output array cdef np.ndarray[DTYPE_t, ndim=2] frac = np.zeros([ny, nx], dtype=DTYPE) if use_exact == 1: raise NotImplementedError("Exact mode has not been implemented for " "rectangular apertures") # Find the width of each element in x and y dx = (xmax - xmin) / nx dy = (ymax - ymin) / ny # TODO: can implement a bounding box here for efficiency (as for the # circular and elliptical aperture photometry) for i in range(nx): pxmin = xmin + i * dx # lower end of pixel pxmax = pxmin + dx # upper end of pixel for j in range(ny): pymin = ymin + j * dy pymax = pymin + dy frac[j, i] = rectangular_overlap_single_subpixel( pxmin, pymin, pxmax, pymax, width, height, theta, subpixels) return frac cdef double rectangular_overlap_single_subpixel(double x0, double y0, double x1, double y1, double width, double height, double theta, int subpixels): """ Return the fraction of overlap between a rectangle and a single pixel with given extent, using a sub-pixel sampling method. """ cdef unsigned int i, j cdef double x, y cdef double frac = 0. # Accumulator. cdef double cos_theta = cos(theta) cdef double sin_theta = sin(theta) cdef double half_width, half_height half_width = width / 2. half_height = height / 2. dx = (x1 - x0) / subpixels dy = (y1 - y0) / subpixels x = x0 - 0.5 * dx for i in range(subpixels): x += dx y = y0 - 0.5 * dy for j in range(subpixels): y += dy # Transform into frame of rotated rectangle x_tr = y * sin_theta + x * cos_theta y_tr = y * cos_theta - x * sin_theta if fabs(x_tr) < half_width and fabs(y_tr) < half_height: frac += 1. return frac / (subpixels * subpixels) photutils-0.7.2/photutils/geometry/tests/0000755000214200020070000000000013573510273022774 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/geometry/tests/__init__.py0000644000214200020070000000000013563423715025076 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/geometry/tests/test_circular_overlap_grid.py0000644000214200020070000000174213563423715030755 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the circular_overlap_grid module. """ import itertools from numpy.testing import assert_allclose import pytest from .. import circular_overlap_grid grid_sizes = [50, 500, 1000] circ_sizes = [0.2, 0.4, 0.8] use_exact = [0, 1] subsamples = [1, 5, 10] arg_list = ['grid_size', 'circ_size', 'use_exact', 'subsample'] @pytest.mark.parametrize(('grid_size', 'circ_size', 'use_exact', 'subsample'), list(itertools.product(grid_sizes, circ_sizes, use_exact, subsamples))) def test_circular_overlap_grid(grid_size, circ_size, use_exact, subsample): """ Test normalization of the overlap grid to make sure that a fully enclosed pixel has a value of 1.0. """ g = circular_overlap_grid(-1.0, 1.0, -1.0, 1.0, grid_size, grid_size, circ_size, use_exact, subsample) assert_allclose(g.max(), 1.0) photutils-0.7.2/photutils/geometry/tests/test_elliptical_overlap_grid.py0000644000214200020070000000242113563423715031266 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the elliptical_overlap_grid module. """ import itertools from numpy.testing import assert_allclose import pytest from .. import elliptical_overlap_grid grid_sizes = [50, 500, 1000] maj_sizes = [0.2, 0.4, 0.8] min_sizes = [0.2, 0.4, 0.8] angles = [0.0, 0.5, 1.0] use_exact = [0, 1] subsamples = [1, 5, 10] arg_list = ['grid_size', 'maj_size', 'min_size', 'angle', 'use_exact', 'subsample'] @pytest.mark.parametrize(('grid_size', 'maj_size', 'min_size', 'angle', 'use_exact', 'subsample'), list(itertools.product(grid_sizes, maj_sizes, min_sizes, angles, use_exact, subsamples))) def test_elliptical_overlap_grid(grid_size, maj_size, min_size, angle, use_exact, subsample): """ Test normalization of the overlap grid to make sure that a fully enclosed pixel has a value of 1.0. """ g = elliptical_overlap_grid(-1.0, 1.0, -1.0, 1.0, grid_size, grid_size, maj_size, min_size, angle, use_exact, subsample) assert_allclose(g.max(), 1.0) photutils-0.7.2/photutils/geometry/tests/test_rectangular_overlap_grid.py0000644000214200020070000000176213563423715031462 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the rectangular_overlap_grid module. """ import itertools from numpy.testing import assert_allclose import pytest from .. import rectangular_overlap_grid grid_sizes = [50, 500, 1000] rect_sizes = [0.2, 0.4, 0.8] angles = [0.0, 0.5, 1.0] subsamples = [1, 5, 10] arg_list = ['grid_size', 'rect_size', 'angle', 'subsample'] @pytest.mark.parametrize(('grid_size', 'rect_size', 'angle', 'subsample'), list(itertools.product(grid_sizes, rect_sizes, angles, subsamples))) def test_rectangular_overlap_grid(grid_size, rect_size, angle, subsample): """ Test normalization of the overlap grid to make sure that a fully enclosed pixel has a value of 1.0. """ g = rectangular_overlap_grid(-1.0, 1.0, -1.0, 1.0, grid_size, grid_size, rect_size, rect_size, angle, 0, subsample) assert_allclose(g.max(), 1.0) photutils-0.7.2/photutils/isophote/0000755000214200020070000000000013573510273021631 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/isophote/__init__.py0000644000214200020070000000062613563423715023751 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage contains tools for fitting elliptical isophotes to galaxy images. """ from .ellipse import * # noqa from .fitter import * # noqa from .geometry import * # noqa from .harmonics import * # noqa from .integrator import * # noqa from .isophote import * # noqa from .model import * # noqa from .sample import * # noqa photutils-0.7.2/photutils/isophote/ellipse.py0000644000214200020070000010130113563423715023637 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides a class to fit elliptical isophotes. """ import warnings from astropy.utils.exceptions import AstropyUserWarning import numpy as np from .fitter import (DEFAULT_CONVERGENCE, DEFAULT_FFLAG, DEFAULT_MAXGERR, DEFAULT_MAXIT, DEFAULT_MINIT, CentralEllipseFitter, EllipseFitter) from .geometry import EllipseGeometry from .integrator import BILINEAR from .isophote import Isophote, IsophoteList from .sample import CentralEllipseSample, EllipseSample __all__ = ['Ellipse'] class Ellipse: """ Class to fit elliptical isophotes to a galaxy image. The isophotes in the image are measured using an iterative method described by `Jedrzejewski (1987; MNRAS 226, 747) `_. See the **Notes** section below for details about the algorithm. Parameters ---------- image : 2D `~numpy.ndarray` The image array. geometry : `~photutils.isophote.EllipseGeometry` instance or `None`, optional The optional geometry that describes the first ellipse to be fitted. If `None`, a default `~photutils.isophote.EllipseGeometry` instance is created centered on the image frame with ellipticity of 0.2 and a position angle of 90 degrees. threshold : float, optional The threshold for the object centerer algorithm. By lowering this value the object centerer becomes less strict, in the sense that it will accept lower signal-to-noise data. If set to a very large value, the centerer is effectively shut off. In this case, either the geometry information supplied by the ``geometry`` parameter is used as is, or the fit algorithm will terminate prematurely. Note that once the object centerer runs successfully, the (x, y) coordinates in the ``geometry`` attribute (an `~photutils.isophote.EllipseGeometry` instance) are modified in place. The default is 0.1 Notes ----- The image is measured using an iterative method described by `Jedrzejewski (1987; MNRAS 226, 747) `_. Each isophote is fitted at a pre-defined, fixed semimajor axis length. The algorithm starts from a first-guess elliptical isophote defined by approximate values for the (x, y) center coordinates, ellipticity, and position angle. Using these values, the image is sampled along an elliptical path, producing a 1-dimensional function that describes the dependence of intensity (pixel value) with angle (E). The function is stored as a set of 1D numpy arrays. The harmonic content of this function is analyzed by least-squares fitting to the function: .. math:: y = y0 + (A1 * \\sin(E)) + (B1 * \\cos(E)) + (A2 * \\sin(2 * E)) + (B2 * \\cos(2 * E)) Each one of the harmonic amplitudes (A1, B1, A2, and B2) is related to a specific ellipse geometric parameter in the sense that it conveys information regarding how much the parameter's current value deviates from the "true" one. To compute this deviation, the image's local radial gradient has to be taken into account too. The algorithm picks up the largest amplitude among the four, estimates the local gradient, and computes the corresponding increment in the associated ellipse parameter. That parameter is updated, and the image is resampled. This process is repeated until any one of the following criteria are met: 1. the largest harmonic amplitude is less than a given fraction of the rms residual of the intensity data around the harmonic fit. 2. a user-specified maximum number of iterations is reached. 3. more than a given fraction of the elliptical sample points have no valid data in then, either because they lie outside the image boundaries or because they were flagged out from the fit by sigma-clipping. In any case, a minimum number of iterations is always performed. If iterations stop because of reasons 2 or 3 above, then those ellipse parameters that generated the lowest absolute values for harmonic amplitudes will be used. At this point, the image data sample coming from the best fit ellipse is fitted by the following function: .. math:: y = y0 + (An * sin(n * E)) + (Bn * cos(n * E)) with :math:`n = 3` and :math:`n = 4`. The corresponding amplitudes (A3, B3, A4, and B4), divided by the semimajor axis length and local intensity gradient, measure the isophote's deviations from perfect ellipticity (these amplitudes, divided by semimajor axis and gradient, are the actual quantities stored in the output `~photutils.isophote.Isophote` instance). The algorithm then measures the integrated intensity and the number of non-flagged pixels inside the elliptical isophote, and also inside the corresponding circle with same center and radius equal to the semimajor axis length. These parameters, their errors, other associated parameters, and auxiliary information, are stored in the `~photutils.isophote.Isophote` instance. Errors in intensity and local gradient are obtained directly from the rms scatter of intensity data along the fitted ellipse. Ellipse geometry errors are obtained from the errors in the coefficients of the first and second simultaneous harmonic fit. Third and fourth harmonic amplitude errors are obtained in the same way, but only after the first and second harmonics are subtracted from the raw data. For more details, see the error analysis in `Busko (1996; ASPC 101, 139) `_. After fitting the ellipse that corresponds to a given value of the semimajor axis (by the process described above), the axis length is incremented/decremented following a pre-defined rule. At each step, the starting, first-guess, ellipse parameters are taken from the previously fitted ellipse that has the closest semimajor axis length to the current one. On low surface brightness regions (those having large radii), the small values of the image radial gradient can induce large corrections and meaningless values for the ellipse parameters. The algorithm has the ability to stop increasing semimajor axis based on several criteria, including signal-to-noise ratio. See the `~photutils.isophote.Isophote` documentation for the meaning of the stop code reported after each fit. The fit algorithm provides a k-sigma clipping algorithm for cleaning deviant sample points at each isophote, thus improving convergence stability against any non-elliptical structure such as stars, spiral arms, HII regions, defects, etc. The fit algorithm has no way of finding where, in the input image frame, the galaxy to be measured is located. The center (x, y) coordinates need to be close to the actual center for the fit to work. An "object centerer" function helps to verify that the selected position can be used as starting point. This function scans a 10x10 window centered either on the (x, y) coordinates in the `~photutils.isophote.EllipseGeometry` instance passed to the constructor of the `~photutils.isophote.Ellipse` class, or, if any one of them, or both, are set to `None`, on the input image frame center. In case a successful acquisition takes place, the `~photutils.isophote.EllipseGeometry` instance is modified in place to reflect the solution of the object centerer algorithm. In some cases the object centerer algorithm may fail, even though there is enough signal-to-noise to start a fit (e.g. in objects with very high ellipticity). In those cases the sensitivity of the algorithm can be decreased by decreasing the value of the object centerer threshold parameter. The centerer works by looking to where a quantity akin to a signal-to-noise ratio is maximized within the 10x10 window. The centerer can thus be shut off entirely by setting the threshold to a large value >> 1 (meaning, no location inside the search window will achieve that signal-to-noise ratio). A note of caution: the ellipse fitting algorithm was designed explicitly with an elliptical galaxy brightness distribution in mind. In particular, a well defined negative radial intensity gradient across the region being fitted is paramount for the achievement of stable solutions. Use of the algorithm in other types of images (e.g., planetary nebulae) may lead to inability to converge to any acceptable solution. """ def __init__(self, image, geometry=None, threshold=0.1): self.image = image if geometry is not None: self._geometry = geometry else: _x0 = image.shape[1] / 2 _y0 = image.shape[0] / 2 self._geometry = EllipseGeometry(_x0, _y0, 10., eps=0.2, pa=np.pi/2) self.set_threshold(threshold) def set_threshold(self, threshold): """ Modify the threshold value used by the centerer. Parameters ---------- threshold : float The new threshold value to use. """ self._geometry.centerer_threshold = threshold def fit_image(self, sma0=None, minsma=0., maxsma=None, step=0.1, conver=DEFAULT_CONVERGENCE, minit=DEFAULT_MINIT, maxit=DEFAULT_MAXIT, fflag=DEFAULT_FFLAG, maxgerr=DEFAULT_MAXGERR, sclip=3., nclip=0, integrmode=BILINEAR, linear=None, maxrit=None, fix_center=False, fix_pa=False, fix_eps=False): # This parameter list is quite large and should in principle be # simplified by re-distributing these controls to somewhere else. # We keep this design though because it better mimics the flat # architecture used in the original STSDAS task `ellipse`. """ Fit multiple isophotes to the image array. This method loops over each value of the semimajor axis (sma) length (constructed from the input parameters), fitting a single isophote at each sma. The entire set of isophotes is returned in an `~photutils.isophote.IsophoteList` instance. Note that the fix_XXX parameters act in unison. Meaning, if one of them is set via this call, the others will assume their default (False) values. This effectively overrides any settings that are present in the internal `~photutils.isophote.EllipseGeometry` instance that is carried along as a property of this class. If an instance of `~photutils.isophote.EllipseGeometry` was passed to this class' constructor, that instance will be effectively overriden by the fix_XXX parameters in this call. Parameters ---------- sma0 : float, optional The starting value for the semimajor axis length (pixels). This value must not be the minimum or maximum semimajor axis length, but something in between. The algorithm can't start from the very center of the galaxy image because the modelling of elliptical isophotes on that region is poor and it will diverge very easily if not tied to other previously fit isophotes. It can't start from the maximum value either because the maximum is not known beforehand, depending on signal-to-noise. The ``sma0`` value should be selected such that the corresponding isophote has a good signal-to-noise ratio and a clearly defined geometry. If set to `None` (the default), one of two actions will be taken: if a `~photutils.isophote.EllipseGeometry` instance was input to the `~photutils.isophote.Ellipse` constructor, its ``sma`` value will be used. Otherwise, a default value of 10. will be used. minsma : float, optional The minimum value for the semimajor axis length (pixels). The default is 0. maxsma : float or `None`, optional The maximum value for the semimajor axis length (pixels). When set to `None` (default), the algorithm will increase the semimajor axis until one of several conditions will cause it to stop and revert to fit ellipses with sma < ``sma0``. step : float, optional The step value used to grow/shrink the semimajor axis length (pixels if ``linear=True``, or a relative value if ``linear=False``). See the ``linear`` parameter. The default is 0.1. conver : float, optional The main convergence criterion. Iterations stop when the largest harmonic amplitude becomes smaller (in absolute value) than ``conver`` times the harmonic fit rms. The default is 0.05. minit : int, optional The minimum number of iterations to perform. A minimum of 10 (the default) iterations guarantees that, on average, 2 iterations will be available for fitting each independent parameter (the four harmonic amplitudes and the intensity level). For the first isophote, the minimum number of iterations is 2 * ``minit`` to ensure that, even departing from not-so-good initial values, the algorithm has a better chance to converge to a sensible solution. maxit : int, optional The maximum number of iterations to perform. The default is 50. fflag : float, optional The acceptable fraction of flagged data points in the sample. If the actual fraction of valid data points is smaller than this, the iterations will stop and the current `~photutils.isophote.Isophote` will be returned. Flagged data points are points that either lie outside the image frame, are masked, or were rejected by sigma-clipping. The default is 0.7. maxgerr : float, optional The maximum acceptable relative error in the local radial intensity gradient. This is the main control for preventing ellipses to grow to regions of too low signal-to-noise ratio. It specifies the maximum acceptable relative error in the local radial intensity gradient. `Busko (1996; ASPC 101, 139) `_ showed that the fitting precision relates to that relative error. The usual behavior of the gradient relative error is to increase with semimajor axis, being larger in outer, fainter regions of a galaxy image. In the current implementation, the ``maxgerr`` criterion is triggered only when two consecutive isophotes exceed the value specified by the parameter. This prevents premature stopping caused by contamination such as stars and HII regions. A number of actions may happen when the gradient error exceeds ``maxgerr`` (or becomes non-significant and is set to `None`). If the maximum semimajor axis specified by ``maxsma`` is set to `None`, semimajor axis growth is stopped and the algorithm proceeds inwards to the galaxy center. If ``maxsma`` is set to some finite value, and this value is larger than the current semimajor axis length, the algorithm enters non-iterative mode and proceeds outwards until reaching ``maxsma``. The default is 0.5. sclip : float, optional The sigma-clip sigma value. The default is 3.0. nclip : int, optional The number of sigma-clip interations. The default is 0, which means sigma-clipping is skipped. integrmode : {'bilinear', 'nearest_neighbor', 'mean', 'median'}, optional The area integration mode. The default is 'bilinear'. linear : bool, optional The semimajor axis growing/shrinking mode. If `False` (default), the geometric growing mode is chosen, thus the semimajor axis length is increased by a factor of (1. + ``step``), and the process is repeated until either the semimajor axis value reaches the value of parameter ``maxsma``, or the last fitted ellipse has more than a given fraction of its sampled points flagged out (see ``fflag``). The process then resumes from the first fitted ellipse (at ``sma0``) inwards, in steps of (1./(1. + ``step``)), until the semimajor axis length reaches the value ``minsma``. In case of linear growing, the increment or decrement value is given directly by ``step`` in pixels. If ``maxsma`` is set to `None`, the semimajor axis will grow until a low signal-to-noise criterion is met. See ``maxgerr``. maxrit : float or `None`, optional The maximum value of semimajor axis to perform an actual fit. Whenever the current semimajor axis length is larger than ``maxrit``, the isophotes will be extracted using the current geometry, without being fitted. This non-iterative mode may be useful for sampling regions of very low surface brightness, where the algorithm may become unstable and unable to recover reliable geometry information. Non-iterative mode can also be entered automatically whenever the ellipticity exceeds 1.0 or the ellipse center crosses the image boundaries. If `None` (default), then no maximum value is used. fix_center : bool, optional Keep center of ellipse fixed during fit? The default is False. fix_pa : bool, optional Keep position angle of semi-major axis of ellipse fixed during fit? The default is False. fix_eps : bool, optional Keep ellipticity of ellipse fixed during fit? The default is False. Returns ------- result : `~photutils.isophote.IsophoteList` instance A list-like object of `~photutils.isophote.Isophote` instances, sorted by increasing semimajor axis length. """ # multiple fitted isophotes will be stored here isophote_list = [] # get starting sma from appropriate source: keyword parameter, # internal EllipseGeometry instance, or fixed default value. if not sma0: if self._geometry: sma = self._geometry.sma else: sma = 10. else: sma = sma0 # Override geometry instance with parameters set at the call. if isinstance(linear, bool): self._geometry.linear_growth = linear else: linear = self._geometry.linear_growth if fix_center and fix_pa and fix_eps: warnings.warn(': Everything is fixed. Fit not possible.', AstropyUserWarning) return IsophoteList([]) if fix_center or fix_pa or fix_eps: # Note that this overrides the geometry instance for good. self._geometry.fix = np.array([fix_center, fix_center, fix_pa, fix_eps]) # first, go from initial sma outwards until # hitting one of several stopping criteria. noiter = False first_isophote = True while True: # first isophote runs longer minit_a = 2 * minit if first_isophote else minit first_isophote = False isophote = self.fit_isophote(sma, step, conver, minit_a, maxit, fflag, maxgerr, sclip, nclip, integrmode, linear, maxrit, noniterate=noiter, isophote_list=isophote_list) # check for failed fit. if (isophote.stop_code < 0 or isophote.stop_code == 1): # in case the fit failed right at the outset, return an # empty list. This is the usual case when the user # provides initial guesses that are too way off to enable # the fitting algorithm to find any meaningful solution. if len(isophote_list) == 1: warnings.warn('No meaningful fit was possible.', AstropyUserWarning) return IsophoteList([]) self._fix_last_isophote(isophote_list, -1) # get last isophote from the actual list, since the last # `isophote` instance in this context may no longer be OK. isophote = isophote_list[-1] # if two consecutive isophotes failed to fit, # shut off iterative mode. Or, bail out and # change to go inwards. if len(isophote_list) > 2: if ((isophote.stop_code == 5 and isophote_list[-2].stop_code == 5) or isophote.stop_code == 1): if maxsma and maxsma > isophote.sma: # if a maximum sma value was provided by # user, and the current sma is smaller than # maxsma, keep growing sma in non-iterative # mode until reaching it. noiter = True else: # if no maximum sma, stop growing and change # to go inwards. break # reset variable from the actual list, since the last # `isophote` instance may no longer be OK. isophote = isophote_list[-1] # update sma. If exceeded user-defined # maximum, bail out from this loop. sma = isophote.sample.geometry.update_sma(step) if maxsma and sma >= maxsma: break # reset sma so as to go inwards. first_isophote = isophote_list[0] sma, step = first_isophote.sample.geometry.reset_sma(step) # now, go from initial sma inwards towards center. while True: isophote = self.fit_isophote(sma, step, conver, minit, maxit, fflag, maxgerr, sclip, nclip, integrmode, linear, maxrit, going_inwards=True, isophote_list=isophote_list) # if abnormal condition, fix isophote but keep going. if isophote.stop_code < 0: self._fix_last_isophote(isophote_list, 0) # reset variable from the actual list, since the last # `isophote` instance may no longer be OK. isophote = isophote_list[-1] # figure out next sma; if exceeded user-defined # minimum, or too small, bail out from this loop sma = isophote.sample.geometry.update_sma(step) if sma <= max(minsma, 0.5): break # if user asked for minsma=0, extract special isophote there if minsma == 0.0: # isophote is appended to isophote_list _ = self.fit_isophote(0.0, isophote_list=isophote_list) # sort list of isophotes according to sma isophote_list.sort() return IsophoteList(isophote_list) def fit_isophote(self, sma, step=0.1, conver=DEFAULT_CONVERGENCE, minit=DEFAULT_MINIT, maxit=DEFAULT_MAXIT, fflag=DEFAULT_FFLAG, maxgerr=DEFAULT_MAXGERR, sclip=3., nclip=0, integrmode=BILINEAR, linear=False, maxrit=None, noniterate=False, going_inwards=False, isophote_list=None): """ Fit a single isophote with a given semimajor axis length. The ``step`` and ``linear`` parameters are not used to actually grow or shrink the current fitting semimajor axis length. They are necessary so the sampling algorithm can know where to start the gradient computation and also how to compute the elliptical sector areas (when area integration mode is selected). Parameters ---------- sma : float The semimajor axis length (pixels). step : float, optional The step value used to grow/shrink the semimajor axis length (pixels if ``linear=True``, or a relative value if ``linear=False``). See the ``linear`` parameter. The default is 0.1. conver : float, optional The main convergence criterion. Iterations stop when the largest harmonic amplitude becomes smaller (in absolute value) than ``conver`` times the harmonic fit rms. The default is 0.05. minit : int, optional The minimum number of iterations to perform. A minimum of 10 (the default) iterations guarantees that, on average, 2 iterations will be available for fitting each independent parameter (the four harmonic amplitudes and the intensity level). For the first isophote, the minimum number of iterations is 2 * ``minit`` to ensure that, even departing from not-so-good initial values, the algorithm has a better chance to converge to a sensible solution. maxit : int, optional The maximum number of iterations to perform. The default is 50. fflag : float, optional The acceptable fraction of flagged data points in the sample. If the actual fraction of valid data points is smaller than this, the iterations will stop and the current `~photutils.isophote.Isophote` will be returned. Flagged data points are points that either lie outside the image frame, are masked, or were rejected by sigma-clipping. The default is 0.7. maxgerr : float, optional The maximum acceptable relative error in the local radial intensity gradient. When fitting a single isophote by itself this paramter doesn't have any effect on the outcome. sclip : float, optional The sigma-clip sigma value. The default is 3.0. nclip : int, optional The number of sigma-clip interations. The default is 0, which means sigma-clipping is skipped. integrmode : {'bilinear', 'nearest_neighbor', 'mean', 'median'}, optional The area integration mode. The default is 'bilinear'. linear : bool, optional The semimajor axis growing/shrinking mode. When fitting just one isophote, this parameter is used only by the code that define the details of how elliptical arc segments ("sectors") are extracted from the image when using area extraction modes (see the ``integrmode`` parameter). maxrit : float or `None`, optional The maximum value of semimajor axis to perform an actual fit. Whenever the current semimajor axis length is larger than ``maxrit``, the isophotes will be extracted using the current geometry, without being fitted. This non-iterative mode may be useful for sampling regions of very low surface brightness, where the algorithm may become unstable and unable to recover reliable geometry information. Non-iterative mode can also be entered automatically whenever the ellipticity exceeds 1.0 or the ellipse center crosses the image boundaries. If `None` (default), then no maximum value is used. noniterate : bool, optional Whether the fitting algorithm should be bypassed and an isophote should be extracted with the geometry taken directly from the most recent `~photutils.isophote.Isophote` instance stored in the ``isophote_list`` parameter. This parameter is mainly used when running the method in a loop over different values of semimajor axis length, and we want to change from iterative to non-iterative mode somewhere along the sequence of isophotes. When set to `True`, this parameter overrides the behavior associated with parameter ``maxrit``. The default is `False`. going_inwards : bool, optional Parameter to define the sense of SMA growth. When fitting just one isophote, this parameter is used only by the code that defines the details of how elliptical arc segments ("sectors") are extracted from the image, when using area extraction modes (see the ``integrmode`` parameter). The default is `False`. isophote_list : list or `None`, optional If not `None` (the default), the fitted `~photutils.isophote.Isophote` instance is appended to this list. It must be created and managed by the caller. Returns ------- result : `~photutils.isophote.Isophote` instance The fitted isophote. The fitted isophote is also appended to the input list input to the ``isophote_list`` parameter. """ geometry = self._geometry # if available, geometry from last fitted isophote will be # used as initial guess for next isophote. if isophote_list: geometry = isophote_list[-1].sample.geometry # do the fit if noniterate or (maxrit and sma > maxrit): isophote = self._non_iterative(sma, step, linear, geometry, sclip, nclip, integrmode) else: isophote = self._iterative(sma, step, linear, geometry, sclip, nclip, integrmode, conver, minit, maxit, fflag, maxgerr, going_inwards) # store result in list if isophote_list is not None and isophote.valid: isophote_list.append(isophote) return isophote def _iterative(self, sma, step, linear, geometry, sclip, nclip, integrmode, conver, minit, maxit, fflag, maxgerr, going_inwards=False): if sma > 0.: # iterative fitter sample = EllipseSample(self.image, sma, astep=step, sclip=sclip, nclip=nclip, linear_growth=linear, geometry=geometry, integrmode=integrmode) fitter = EllipseFitter(sample) else: # sma == 0 requires special handling sample = CentralEllipseSample(self.image, 0.0, geometry=geometry) fitter = CentralEllipseFitter(sample) isophote = fitter.fit(conver, minit, maxit, fflag, maxgerr, going_inwards) return isophote def _non_iterative(self, sma, step, linear, geometry, sclip, nclip, integrmode): sample = EllipseSample(self.image, sma, astep=step, sclip=sclip, nclip=nclip, linear_growth=linear, geometry=geometry, integrmode=integrmode) sample.update(geometry.fix) # build isophote without iterating with an EllipseFitter isophote = Isophote(sample, 0, True, stop_code=4) return isophote @staticmethod def _fix_last_isophote(isophote_list, index): if isophote_list: isophote = isophote_list.pop() # check if isophote is bad; if so, fix its geometry # to be like the geometry of the index-th isophote # in list. isophote.fix_geometry(isophote_list[index]) # force new extraction of raw data, since # geometry changed. isophote.sample.values = None isophote.sample.update(isophote.sample.geometry.fix) # we take the opportunity to change an eventual # negative stop code to its' positive equivalent. code = (5 if isophote.stop_code < 0 else isophote.stop_code) # build new instance so it can have its attributes # populated from the updated sample attributes. new_isophote = Isophote(isophote.sample, isophote.niter, isophote.valid, code) # add new isophote to list isophote_list.append(new_isophote) photutils-0.7.2/photutils/isophote/fitter.py0000644000214200020070000003766413563423715023523 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides a class to fit ellipses. """ import math from astropy import log import numpy as np import numpy.ma as ma from .harmonics import (first_and_second_harmonic_function, fit_first_and_second_harmonics) from .isophote import CentralPixel, Isophote from .sample import EllipseSample __all__ = ['EllipseFitter'] __doctest_skip__ = ['EllipseFitter.fit'] PI2 = np.pi / 2 MAX_EPS = 0.95 MIN_EPS = 0.05 DEFAULT_CONVERGENCE = 0.05 DEFAULT_MINIT = 10 DEFAULT_MAXIT = 50 DEFAULT_FFLAG = 0.7 DEFAULT_MAXGERR = 0.5 class EllipseFitter: """ Class to fit ellipses. Parameters ---------- sample : `~photutils.isophote.EllipseSample` instance The sample data to be fitted. """ def __init__(self, sample): self._sample = sample def fit(self, conver=DEFAULT_CONVERGENCE, minit=DEFAULT_MINIT, maxit=DEFAULT_MAXIT, fflag=DEFAULT_FFLAG, maxgerr=DEFAULT_MAXGERR, going_inwards=False): """ Fit an elliptical isophote. Parameters ---------- conver : float, optional The main convergence criterion. Iterations stop when the largest harmonic amplitude becomes smaller (in absolute value) than ``conver`` times the harmonic fit rms. The default is 0.05. minit : int, optional The minimum number of iterations to perform. A minimum of 10 (the default) iterations guarantees that, on average, 2 iterations will be available for fitting each independent parameter (the four harmonic amplitudes and the intensity level). For the first isophote, the minimum number of iterations is 2 * ``minit`` to ensure that, even departing from not-so-good initial values, the algorithm has a better chance to converge to a sensible solution. maxit : int, optional The maximum number of iterations to perform. The default is 50. fflag : float, optional The acceptable fraction of flagged data points in the sample. If the actual fraction of valid data points is smaller than this, the iterations will stop and the current `~photutils.isophote.Isophote` will be returned. Flagged data points are points that either lie outside the image frame, are masked, or were rejected by sigma-clipping. The default is 0.7. maxgerr : float, optional The maximum acceptable relative error in the local radial intensity gradient. This is the main control for preventing ellipses to grow to regions of too low signal-to-noise ratio. It specifies the maximum acceptable relative error in the local radial intensity gradient. `Busko (1996; ASPC 101, 139) `_ showed that the fitting precision relates to that relative error. The usual behavior of the gradient relative error is to increase with semimajor axis, being larger in outer, fainter regions of a galaxy image. In the current implementation, the ``maxgerr`` criterion is triggered only when two consecutive isophotes exceed the value specified by the parameter. This prevents premature stopping caused by contamination such as stars and HII regions. A number of actions may happen when the gradient error exceeds ``maxgerr`` (or becomes non-significant and is set to `None`). If the maximum semimajor axis specified by ``maxsma`` is set to `None`, semimajor axis growth is stopped and the algorithm proceeds inwards to the galaxy center. If ``maxsma`` is set to some finite value, and this value is larger than the current semimajor axis length, the algorithm enters non-iterative mode and proceeds outwards until reaching ``maxsma``. The default is 0.5. going_inwards : bool, optional Parameter to define the sense of SMA growth. When fitting just one isophote, this parameter is used only by the code that defines the details of how elliptical arc segments ("sectors") are extracted from the image, when using area extraction modes (see the ``integrmode`` parameter in the `~photutils.isophote.EllipseSample` class). The default is `False`. Returns ------- result : `~photutils.isophote.Isophote` instance The fitted isophote, which also contains fit status information. Examples -------- >>> from photutils.isophote import EllipseSample, EllipseFitter >>> sample = EllipseSample(data, sma=10.) >>> fitter = EllipseFitter(sample) >>> isophote = fitter.fit() """ sample = self._sample # this flag signals that limiting gradient error (`maxgerr`) # wasn't exceeded yet. lexceed = False # here we keep track of the sample that caused the minimum harmonic # amplitude(in absolute value). This will eventually be used to # build the resulting Isophote in cases where iterations run to # the maximum allowed (maxit), or the maximum number of flagged # data points (fflag) is reached. minimum_amplitude_value = np.Inf minimum_amplitude_sample = None # these must be passed throughout the execution chain. fixed_parameters = self._sample.geometry.fix for i in range(maxit): # Force the sample to compute its gradient and associated values. sample.update(fixed_parameters) # The extract() method returns sampled values as a 2-d numpy array # with the following structure: # values[0] = 1-d array with angles # values[1] = 1-d array with radii # values[2] = 1-d array with intensity values = sample.extract() # Fit harmonic coefficients. Failure in fitting is # a fatal error; terminate immediately with sample # marked as invalid. try: coeffs = fit_first_and_second_harmonics(values[0], values[2]) coeffs = coeffs[0] except Exception as e: log.info(e) sample.geometry.fix = fixed_parameters return Isophote(sample, i + 1, False, 3) # Mask out coefficients that control fixed ellipse parameters. free_coeffs = ma.masked_array(coeffs[1:], mask=fixed_parameters) # Largest non-masked harmonic in absolute value drives the correction. largest_harmonic_index = np.argmax(np.abs(free_coeffs)) largest_harmonic = free_coeffs[largest_harmonic_index] # see if the amplitude decreased; if yes, keep the # corresponding sample for eventual later use. if abs(largest_harmonic) < minimum_amplitude_value: minimum_amplitude_value = abs(largest_harmonic) minimum_amplitude_sample = sample # check if converged model = first_and_second_harmonic_function(values[0], coeffs) residual = values[2] - model if ((conver * sample.sector_area * np.std(residual)) > np.abs(largest_harmonic)): # Got a valid solution. But before returning, ensure # that a minimum of iterations has run. if i >= minit - 1: sample.update(fixed_parameters) return Isophote(sample, i + 1, True, 0) # it may not have converged yet, but the sample contains too # many invalid data points: return. if sample.actual_points < (sample.total_points * fflag): # when too many data points were flagged, return the # best fit sample instead of the current one. minimum_amplitude_sample.update(fixed_parameters) return Isophote(minimum_amplitude_sample, i + 1, True, 1) # pick appropriate corrector code. corrector = _CORRECTORS[largest_harmonic_index] # generate *NEW* EllipseSample instance with corrected # parameter. Note that this instance is still devoid of other # information besides its geometry. It needs to be explicitly # updated for computations to proceed. We have to build a new # EllipseSample instance every time because of the lazy # extraction process used by EllipseSample code. To minimize # the number of calls to the area integrators, we pay a # (hopefully smaller) price here, by having multiple calls to # the EllipseSample constructor. sample = corrector.correct(sample, largest_harmonic) sample.update(fixed_parameters) # see if any abnormal (or unusual) conditions warrant # the change to non-iterative mode, or go-inwards mode. proceed, lexceed = self._check_conditions( sample, maxgerr, going_inwards, lexceed) if not proceed: sample.update(fixed_parameters) return Isophote(sample, i + 1, True, -1) # Got to the maximum number of iterations. Return with # code 2, and handle it as a valid isophote. Use the # best fit sample instead of the current one. minimum_amplitude_sample.update(fixed_parameters) return Isophote(minimum_amplitude_sample, maxit, True, 2) @staticmethod def _check_conditions(sample, maxgerr, going_inwards, lexceed): proceed = True # If center wandered more than allowed, put it back # in place and signal the end of iterative mode. # if wander: # if abs(dx) > WANDER(al)) or abs(dy) > WANDER(al): # sample.geometry.x0 -= dx # sample.geometry.y0 -= dy # STOP(al) = ST_NONITERATE # proceed = False # check if an acceptable gradient value could be computed. if sample.gradient_error: if not going_inwards and ( sample.gradient_relative_error > maxgerr or sample.gradient >= 0.0): if lexceed: proceed = False else: lexceed = True else: proceed = False # check if ellipse geometry diverged. if abs(sample.geometry.eps > MAX_EPS): proceed = False if (sample.geometry.x0 < 1. or sample.geometry.x0 > sample.image.shape[1] or sample.geometry.y0 < 1. or sample.geometry.y0 > sample.image.shape[0]): proceed = False # See if eps == 0 (round isophote) was crossed. # If so, fix it but still proceed if sample.geometry.eps < 0.: sample.geometry.eps = min(-sample.geometry.eps, MAX_EPS) if sample.geometry.pa < PI2: sample.geometry.pa += PI2 else: sample.geometry.pa -= PI2 # If ellipse is an exact circle, computations will diverge. # Make it slightly flat, but still proceed if sample.geometry.eps == 0.0: sample.geometry.eps = MIN_EPS return proceed, lexceed class _ParameterCorrector: def correct(self, sample, harmonic): raise NotImplementedError class _PositionCorrector(_ParameterCorrector): @staticmethod def finalize_correction(dx, dy, sample): new_x0 = sample.geometry.x0 + dx new_y0 = sample.geometry.y0 + dy return EllipseSample(sample.image, sample.geometry.sma, x0=new_x0, y0=new_y0, astep=sample.geometry.astep, sclip=sample.sclip, nclip=sample.nclip, eps=sample.geometry.eps, position_angle=sample.geometry.pa, linear_growth=sample.geometry.linear_growth, integrmode=sample.integrmode) class _PositionCorrector0(_PositionCorrector): def correct(self, sample, harmonic): aux = -harmonic * (1. - sample.geometry.eps) / sample.gradient dx = -aux * math.sin(sample.geometry.pa) dy = aux * math.cos(sample.geometry.pa) return self.finalize_correction(dx, dy, sample) class _PositionCorrector1(_PositionCorrector): def correct(self, sample, harmonic): aux = -harmonic / sample.gradient dx = aux * math.cos(sample.geometry.pa) dy = aux * math.sin(sample.geometry.pa) return self.finalize_correction(dx, dy, sample) class _AngleCorrector(_ParameterCorrector): def correct(self, sample, harmonic): eps = sample.geometry.eps sma = sample.geometry.sma gradient = sample.gradient correction = (harmonic * 2. * (1. - eps) / sma / gradient / ((1. - eps)**2 - 1.)) # '% np.pi' to make angle lie between 0 and np.pi radians new_pa = (sample.geometry.pa + correction) % np.pi return EllipseSample(sample.image, sample.geometry.sma, x0=sample.geometry.x0, y0=sample.geometry.y0, astep=sample.geometry.astep, sclip=sample.sclip, nclip=sample.nclip, eps=sample.geometry.eps, position_angle=new_pa, linear_growth=sample.geometry.linear_growth, integrmode=sample.integrmode) class _EllipticityCorrector(_ParameterCorrector): def correct(self, sample, harmonic): eps = sample.geometry.eps sma = sample.geometry.sma gradient = sample.gradient correction = harmonic * 2. * (1. - eps) / sma / gradient new_eps = min((sample.geometry.eps - correction), MAX_EPS) return EllipseSample(sample.image, sample.geometry.sma, x0=sample.geometry.x0, y0=sample.geometry.y0, astep=sample.geometry.astep, sclip=sample.sclip, nclip=sample.nclip, eps=new_eps, position_angle=sample.geometry.pa, linear_growth=sample.geometry.linear_growth, integrmode=sample.integrmode) # instances of corrector code live here: _CORRECTORS = [_PositionCorrector0(), _PositionCorrector1(), _AngleCorrector(), _EllipticityCorrector()] class CentralEllipseFitter(EllipseFitter): """ A special Fitter class to handle the case of the central pixel in the galaxy image. """ def fit(self, conver=DEFAULT_CONVERGENCE, minit=DEFAULT_MINIT, maxit=DEFAULT_MAXIT, fflag=DEFAULT_FFLAG, maxgerr=DEFAULT_MAXGERR, going_inwards=False): """ Perform just a simple 1-pixel extraction at the current (x0, y0) position using bilinear interpolation. The input parameters are ignored, but included simple to match the calling signature of the parent class. Returns ------- result : `~photutils.isophote.CentralEllipsePixel` instance The central pixel value. For convenience, the `~photutils.isophote.CentralEllipsePixel` class inherits from the `~photutils.isophote.Isophote` class, although it's not really a true isophote but just a single intensity value at the central position. Thus, most of its attributes are hardcoded to `None` or other default value when appropriate. """ # default values fixed_parameters = np.array([False, False, False, False]) self._sample.update(fixed_parameters) return CentralPixel(self._sample) photutils-0.7.2/photutils/isophote/geometry.py0000644000214200020070000004701513563423715024050 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides a container class to store parameters for the geometry of an ellipse. """ import math from astropy import log import numpy as np __all__ = ['EllipseGeometry'] IN_MASK = [ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], ] OUT_MASK = [ [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], [1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1], [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], ] def _area(sma, eps, phi, r): """ Compute elliptical sector area. """ aux = r * math.cos(phi) / sma signal = aux / abs(aux) if abs(aux) >= 1.: aux = signal return abs(sma**2 * (1.-eps) / 2. * math.acos(aux)) class EllipseGeometry: """ Container class to store parameters for the geometry of an ellipse. Parameters that describe the relationship of a given ellipse with other associated ellipses are also encapsulated in this container. These associated ellipses may include, e.g., the two (inner and outer) bounding ellipses that are used to build sectors along the elliptical path. These sectors are used as areas for integrating pixel values, when the area integration mode (mean or median) is used. This class also keeps track of where in the ellipse we are when performing an 'extract' operation. This is mostly relevant when using an area integration mode (as opposed to a pixel integration mode) Parameters ---------- x0, y0 : float The center pixel coordinate of the ellipse. sma : float The semimajor axis of the ellipse in pixels. eps : ellipticity The ellipticity of the ellipse. pa : float The position angle (in radians) of the semimajor axis in relation to the postive x axis of the image array (rotating towards the positive y axis). Position angles are defined in the range :math:`0 < PA <= \\pi`. Avoid using as starting position angle of 0., since the fit algorithm may not work properly. When the ellipses are such that position angles are near either extreme of the range, noise can make the solution jump back and forth between successive isophotes, by amounts close to 180 degrees. astep : float, optional The step value for growing/shrinking the semimajor axis. It can be expressed either in pixels (when ``linear_growth=True``) or as a relative value (when ``linear_growth=False``). The default is 0.1. linear_growth : bool, optional The semimajor axis growing/shrinking mode. The default is `False`. fix_center : bool, optional Keep center of ellipse fixed during fit? The default is False. fix_pa : bool, optional Keep position angle of semi-major axis of ellipse fixed during fit? The default is False. fix_eps : bool, optional Keep ellipticity of ellipse fixed during fit? The default is False. """ def __init__(self, x0, y0, sma, eps, pa, astep=0.1, linear_growth=False, fix_center=False, fix_pa=False, fix_eps=False): self.x0 = x0 self.y0 = y0 self.sma = sma self.eps = eps self.pa = pa self.astep = astep self.linear_growth = linear_growth # Fixed parameters are flagged in here. Note that the # ordering must follow the same ordering used in the # fitter._CORRECTORS list. self.fix = np.array([fix_center, fix_center, fix_pa, fix_eps]) # limits for sector angular width self._phi_min = 0.05 self._phi_max = 0.2 # variables used in the calculation of the sector angular width sma1, sma2 = self.bounding_ellipses() inner_sma = min((sma2 - sma1), 3.) self._area_factor = (sma2 - sma1) * inner_sma # sma can eventually be zero! if self.sma > 0.: self.sector_angular_width = max(min((inner_sma / self.sma), self._phi_max), self._phi_min) self.initial_polar_angle = self.sector_angular_width / 2. self.initial_polar_radius = self.radius(self.initial_polar_angle) def find_center(self, image, threshold=0.1, verbose=True): """ Find the center of a galaxy. If the algorithm is successful the (x, y) coordinates in this `~photutils.isophote.EllipseGeometry` (i.e. the ``x0`` and ``y0`` attributes) instance will be modified. The isophote fit algorithm requires an initial guess for the galaxy center (x, y) coordinates and these coordinates must be close to the actual galaxy center for the isophote fit to work. This method provides can provide an initial guess for the galaxy center coordinates. See the **Notes** section below for more details. Parameters ---------- image : 2D `~numpy.ndarray` The image array. Masked arrays are not recognized here. This assumes that centering should always be done on valid pixels. threshold : float, optional The centerer threshold. To turn off the centerer, set this to a large value (i.e. >> 1). The default is 0.1. verbose : bool, optional Whether to print object centering information. The default is `True`. Notes ----- The centerer function scans a 10x10 window centered on the (x, y) coordinates in the `~photutils.isophote.EllipseGeometry` instance passed to the constructor of the `~photutils.isophote.Ellipse` class. If any of the `~photutils.isophote.EllipseGeometry` (x, y) coordinates are `None`, the center of the input image frame is used. If the center acquisition is successful, the `~photutils.isophote.EllipseGeometry` instance is modified in place to reflect the solution of the object centerer algorithm. In some cases the object centerer algorithm may fail even though there is enough signal-to-noise to start a fit (e.g. objects with very high ellipticity). In those cases the sensitivity of the algorithm can be decreased by decreasing the value of the object centerer threshold parameter. The centerer works by looking where a quantity akin to a signal-to-noise ratio is maximized within the 10x10 window. The centerer can thus be shut off entirely by setting the threshold to a large value (i.e. >> 1; meaning no location inside the search window will achieve that signal-to-noise ratio). """ self._centerer_mask_half_size = len(IN_MASK) / 2 self.centerer_threshold = threshold # number of pixels in each mask sz = len(IN_MASK) self._centerer_ones_in = np.ma.masked_array(np.ones(shape=(sz, sz)), mask=IN_MASK) self._centerer_ones_out = np.ma.masked_array(np.ones(shape=(sz, sz)), mask=OUT_MASK) self._centerer_in_mask_npix = np.sum(self._centerer_ones_in) self._centerer_out_mask_npix = np.sum(self._centerer_ones_out) # Check if center coordinates point to somewhere inside the frame. # If not, set then to frame center. shape = image.shape _x0 = self.x0 _y0 = self.y0 if (_x0 is None or _x0 < 0 or _x0 >= shape[1] or _y0 is None or _y0 < 0 or _y0 >= shape[0]): _x0 = shape[1] / 2 _y0 = shape[0] / 2 max_fom = 0. max_i = 0 max_j = 0 # scan all positions inside window window_half_size = 5 for i in range(int(_x0 - window_half_size), int(_x0 + window_half_size) + 1): for j in range(int(_y0 - window_half_size), int(_y0 + window_half_size) + 1): # ensure that it stays inside image frame i1 = int(max(0, i - self._centerer_mask_half_size)) j1 = int(max(0, j - self._centerer_mask_half_size)) i2 = int(min(shape[1] - 1, i + self._centerer_mask_half_size)) j2 = int(min(shape[0] - 1, j + self._centerer_mask_half_size)) window = image[j1:j2, i1:i2] # averages in inner and outer regions. inner = np.ma.masked_array(window, mask=IN_MASK) outer = np.ma.masked_array(window, mask=OUT_MASK) inner_avg = np.sum(inner) / self._centerer_in_mask_npix outer_avg = np.sum(outer) / self._centerer_out_mask_npix # standard deviation and figure of merit inner_std = np.std(inner) outer_std = np.std(outer) stddev = np.sqrt(inner_std**2 + outer_std**2) fom = (inner_avg - outer_avg) / stddev if fom > max_fom: max_fom = fom max_i = i max_j = j # figure of merit > threshold: update geometry with new coordinates. if max_fom > threshold: self.x0 = float(max_i) self.y0 = float(max_j) if verbose: log.info("Found center at x0 = {0:5.1f}, y0 = {1:5.1f}" .format(self.x0, self.y0)) else: if verbose: log.info('Result is below the threshold -- keeping the ' 'original coordinates.') def radius(self, angle): """ Calculate the polar radius for a given polar angle. Parameters ---------- angle : float The polar angle (radians). Returns ------- radius : float The polar radius (pixels). """ return (self.sma * (1. - self.eps) / np.sqrt(((1. - self.eps) * np.cos(angle))**2 + (np.sin(angle))**2)) def initialize_sector_geometry(self, phi): """ Initialize geometry attributes associated with an elliptical sector at the given polar angle ``phi``. This function computes: * the four vertices that define the elliptical sector on the pixel array. * the sector area (saved in the ``sector_area`` attribute) * the sector angular width (saved in ``sector_angular_width`` attribute) Parameters ---------- phi : float The polar angle (radians) where the sector is located. Returns ------- x, y : 1D `~numpy.ndarray` The x and y coordinates of each vertex as 1D arrays. """ # These polar radii bound the region between the inner # and outer ellipses that define the sector. sma1, sma2 = self.bounding_ellipses() eps_ = 1. - self.eps # polar vector at one side of the elliptical sector self._phi1 = phi - self.sector_angular_width / 2. r1 = (sma1 * eps_ / math.sqrt((eps_ * math.cos(self._phi1))**2 + (math.sin(self._phi1))**2)) r2 = (sma2 * eps_ / math.sqrt((eps_ * math.cos(self._phi1))**2 + (math.sin(self._phi1))**2)) # polar vector at the other side of the elliptical sector self._phi2 = phi + self.sector_angular_width / 2. r3 = (sma2 * eps_ / math.sqrt((eps_ * math.cos(self._phi2))**2 + (math.sin(self._phi2))**2)) r4 = (sma1 * eps_ / math.sqrt((eps_ * math.cos(self._phi2))**2 + (math.sin(self._phi2))**2)) # sector area sa1 = _area(sma1, self.eps, self._phi1, r1) sa2 = _area(sma2, self.eps, self._phi1, r2) sa3 = _area(sma2, self.eps, self._phi2, r3) sa4 = _area(sma1, self.eps, self._phi2, r4) self.sector_area = abs((sa3 - sa2) - (sa4 - sa1)) # angular width of sector. It is calculated such that the sectors # come out with roughly constant area along the ellipse. self.sector_angular_width = max(min((self._area_factor / (r3 - r4) / r4), self._phi_max), self._phi_min) # compute the 4 vertices that define the elliptical sector. vertex_x = np.zeros(shape=4, dtype=float) vertex_y = np.zeros(shape=4, dtype=float) # vertices are labelled in counterclockwise sequence vertex_x[0:2] = np.array([r1, r2]) * math.cos(self._phi1 + self.pa) vertex_x[2:4] = np.array([r4, r3]) * math.cos(self._phi2 + self.pa) vertex_y[0:2] = np.array([r1, r2]) * math.sin(self._phi1 + self.pa) vertex_y[2:4] = np.array([r4, r3]) * math.sin(self._phi2 + self.pa) vertex_x += self.x0 vertex_y += self.y0 return vertex_x, vertex_y def bounding_ellipses(self): """ Compute the semimajor axis of the two ellipses that bound the annulus where integrations take place. Returns ------- sma1, sma2 : float The smaller and larger values of semimajor axis length that define the annulus bounding ellipses. """ if self.linear_growth: a1 = self.sma - self.astep / 2. a2 = self.sma + self.astep / 2. else: a1 = self.sma * (1. - self.astep / 2.) a2 = self.sma * (1. + self.astep / 2.) return a1, a2 def polar_angle_sector_limits(self): """ Return the two polar angles that bound the sector. The two bounding polar angles become available only after calling the :meth:`~photutils.isophote.EllipseGeometry.initialize_sector_geometry` method. Returns ------- phi1, phi2 : float The smaller and larger values of polar angle that bound the current sector. """ return self._phi1, self._phi2 def to_polar(self, x, y): """ Return the radius and polar angle in the ellipse coordinate system given (x, y) pixel image coordinates. This function takes care of the different definitions for position angle (PA) and polar angle (phi): .. math:: -\\pi < PA < \\pi 0 < phi < 2 \\pi Note that radius can be anything. The solution is not tied to the semimajor axis length, but to the center position and tilt angle. Parameters ---------- x, y : float The (x, y) image coordinates. Returns ------- radius, angle : float The ellipse radius and polar angle. """ # We split in between a scalar version and a # vectorized version. This is necessary for # now so we don't pay a heavy speed penalty # that is incurred when using vectorized code. # The split in two separate functions helps in # the profiling analysis: most of the time is # spent in the scalar function. if isinstance(x, (int, float)): return self._to_polar_scalar(x, y) else: return self._to_polar_vectorized(x, y) def _to_polar_scalar(self, x, y): x1 = x - self.x0 y1 = y - self.y0 radius = x1**2 + y1**2 if radius > 0.0: radius = math.sqrt(radius) angle = math.asin(abs(y1) / radius) else: radius = 0. angle = 1. if x1 >= 0. and y1 < 0.: angle = 2*np.pi - angle elif x1 < 0. and y1 >= 0.: angle = np.pi - angle elif x1 < 0. and y1 < 0.: angle = np.pi + angle pa1 = self.pa if self.pa < 0.: pa1 = self.pa + 2*np.pi angle = angle - pa1 if angle < 0.: angle = angle + 2*np.pi return radius, angle def _to_polar_vectorized(self, x, y): x1 = np.atleast_2d(x) - self.x0 y1 = np.atleast_2d(y) - self.y0 radius = x1**2 + y1**2 angle = np.ones(radius.shape) imask = (radius > 0.0) radius[imask] = np.sqrt(radius[imask]) angle[imask] = np.arcsin(np.abs(y1[imask]) / radius[imask]) radius[~imask] = 0. angle[~imask] = 1. idx = (x1 >= 0.) & (y1 < 0) angle[idx] = 2*np.pi - angle[idx] idx = (x1 < 0.) & (y1 >= 0.) angle[idx] = np.pi - angle[idx] idx = (x1 < 0.) & (y1 < 0.) angle[idx] = np.pi + angle[idx] pa1 = self.pa if self.pa < 0.: pa1 = self.pa + 2*np.pi angle = angle - pa1 angle[angle < 0] += 2*np.pi return radius, angle def update_sma(self, step): """ Calculate an updated value for the semimajor axis, given the current value and the step value. The step value must be managed by the caller to support both modes: grow outwards and shrink inwards. Parameters ---------- step : float The step value. Returns ------- sma : float The new semimajor axis length. """ if self.linear_growth: sma = self.sma + step else: sma = self.sma * (1. + step) return sma def reset_sma(self, step): """ Change the direction of semimajor axis growth, from outwards to inwards. Parameters ---------- step : float The current step value. Returns ------- sma, new_step : float The new semimajor axis length and the new step value to initiate the shrinking of the semimajor axis length. This is the step value that should be used when calling the :meth:`~photutils.isophote.EllipseGeometry.update_sma` method. """ if self.linear_growth: sma = self.sma - step step = -step else: aux = 1. / (1. + step) sma = self.sma * aux step = aux - 1. return sma, step photutils-0.7.2/photutils/isophote/harmonics.py0000644000214200020070000001022713563423715024173 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for computing and fitting harmonic functions. """ import numpy as np __all__ = ['first_and_second_harmonic_function', 'fit_first_and_second_harmonics', 'fit_upper_harmonic'] def _least_squares_fit(optimize_func, parameters): # call the least squares fitting # function and handle the result. from scipy.optimize import leastsq solution = leastsq(optimize_func, parameters, full_output=True) if solution[4] > 4: raise RuntimeError("Error in least squares fit: " + solution[3]) # return coefficients and covariance matrix return (solution[0], solution[1]) def first_and_second_harmonic_function(phi, c): """ Compute the harmonic function value used to calculate the corrections for ellipse fitting. This function includes simultaneously both the first and second order harmonics: .. math:: f(phi) = c[0] + c[1]*\\sin(phi) + c[2]*\\cos(phi) + c[3]*\\sin(2*phi) + c[4]*\\cos(2*phi) Parameters ---------- phi : float or `~numpy.ndarray` The angle(s) along the elliptical path, going towards the positive y axis, starting coincident with the position angle. That is, the angles are defined from the semimajor axis that lies in the positive x quadrant. c : `~numpy.ndarray` of shape (5,) Array containing the five harmonic coefficients. Returns ------- result : float or `~numpy.ndarray` The function value(s) at the given input angle(s). """ return (c[0] + c[1]*np.sin(phi) + c[2]*np.cos(phi) + c[3]*np.sin(2*phi) + c[4]*np.cos(2*phi)) def fit_first_and_second_harmonics(phi, intensities): """ Fit the first and second harmonic function values to a set of (angle, intensity) pairs. This function is used to compute corrections for ellipse fitting: .. math:: f(phi) = y0 + a1*\\sin(phi) + b1*\\cos(phi) + a2*\\sin(2*phi) + b2*\\cos(2*phi) Parameters ---------- phi : float or `~numpy.ndarray` The angle(s) along the elliptical path, going towards the positive y axis, starting coincident with the position angle. That is, the angles are defined from the semimajor axis that lies in the positive x quadrant. intensities : `~numpy.ndarray` The intensities measured along the elliptical path, at the angles defined by the ``phi`` parameter. Returns ------- y0, a1, b1, a2, b2 : float The fitted harmonic coefficent values. """ a1 = b1 = a2 = b2 = 1. def optimize_func(x): return first_and_second_harmonic_function( phi, np.array([x[0], x[1], x[2], x[3], x[4]])) - intensities return _least_squares_fit(optimize_func, [np.mean(intensities), a1, b1, a2, b2]) def fit_upper_harmonic(phi, intensities, order): """ Fit upper harmonic function to a set of (angle, intensity) pairs. With ``order`` set to 3 or 4, the resulting amplitudes, divided by the semimajor axis length and local gradient, measure the deviations from perfect ellipticity. The harmonic function that is fit is: .. math:: y(phi, order) = y0 + An*\\sin(order*phi) + Bn*\\cos(order*phi) Parameters ---------- phi : float or `~numpy.ndarray` The angle(s) along the elliptical path, going towards the positive y axis, starting coincident with the position angle. That is, the angles are defined from the semimajor axis that lies in the positive x quadrant. intensities : `~numpy.ndarray` The intensities measured along the elliptical path, at the angles defined by the ``phi`` parameter. order : int The order of the harmonic to be fitted. Returns ------- y0, An, Bn : float The fitted harmonic values. """ an = bn = 1. def optimize_func(x): return (x[0] + x[1]*np.sin(order*phi) + x[2]*np.cos(order*phi) - intensities) return _least_squares_fit(optimize_func, [np.mean(intensities), an, bn]) photutils-0.7.2/photutils/isophote/integrator.py0000644000214200020070000002652013563423715024371 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for pixel integration. """ import math import numpy.ma as ma __all__ = ['INTEGRATORS', 'NEAREST_NEIGHBOR', 'BILINEAR', 'MEAN', 'MEDIAN'] # integration modes NEAREST_NEIGHBOR = 'nearest_neighbor' BILINEAR = 'bilinear' MEAN = 'mean' MEDIAN = 'median' class _Integrator: """ Base class that supports different kinds of pixel integration methods. Parameters ---------- image : 2D `~numpy.ndarray` The image array. geometry : `~photutils.isophote.EllipseGeometry` instance object that encapsulates geometry information about current ellipse angles : list output list; contains the angle values along the elliptical path radii : list output list; contains the radius values along the elliptical path intensities : list output list; contains the extracted intensity values along the elliptical path """ def __init__(self, image, geometry, angles, radii, intensities): self._image = image self._geometry = geometry self._angles = angles self._radii = radii self._intensities = intensities # for bounds checking self._i_range = range(0, self._image.shape[1] - 1) self._j_range = range(0, self._image.shape[0] - 1) def integrate(self, radius, phi): """ The three input lists (angles, radii, intensities) are appended with one sample point taken from the image by a chosen integration method. Sub classes should implement the actual integration method. Parameters ---------- radius : float length of radius vector in pixels phi : float polar angle of radius vector """ raise NotImplementedError def _reset(self): """ Starts the results lists anew. This method is for internal use and shouldn't be used by external callers. """ self._angles = [] self._radii = [] self._intensities = [] def _store_results(self, phi, radius, sample): self._angles.append(phi) self._radii.append(radius) self._intensities.append(sample) def get_polar_angle_step(self): """ Returns the polar angle step used to walk over the elliptical path. The polar angle step is defined by the actual integrator subclass. Returns ------- float the polar angle step """ raise NotImplementedError def get_sector_area(self): """ Returns the area of elliptical sectors where the integration takes place. This area is defined and managed by the actual integrator subclass. Depending on the integrator, the area may be a fixed constant, or may change along the elliptical path, so it's up to the caller to use this information in a correct way. Returns ------- float the sector area """ raise NotImplementedError def is_area(self): """ Returns the type of the integrator. An area integrator gets it's value from operating over a (generally variable) number of pixels that define a finite area that lays around the elliptical path, at a certain point on the image defined by a polar angle and radius values. A pixel integrator, by contrast, integrates over a fixed and normally small area related to a single pixel on the image. An example is the bilinear integrator, which integrates over a small, fixed, 5-pixel area. This method checks if the integrator is of the first type or not. Returns ------- boolean True if this is an area integrator, False otherwise """ raise NotImplementedError class _NearestNeighborIntegrator(_Integrator): def integrate(self, radius, phi): self._r = radius # Get image coordinates of (radius, phi) pixel i = int(radius * math.cos(phi + self._geometry.pa) + self._geometry.x0) j = int(radius * math.sin(phi + self._geometry.pa) + self._geometry.y0) # ignore data point if outside image boundaries if (i in self._i_range) and (j in self._j_range): sample = self._image[j][i] if sample is not ma.masked: self._store_results(phi, radius, sample) def get_polar_angle_step(self): return 1. / self._r def get_sector_area(self): return 1. def is_area(self): return False class _BiLinearIntegrator(_Integrator): def integrate(self, radius, phi): self._r = radius # Get image coordinates of (radius, phi) pixel x_ = radius * math.cos(phi + self._geometry.pa) + self._geometry.x0 y_ = radius * math.sin(phi + self._geometry.pa) + self._geometry.y0 i = int(x_) j = int(y_) fx = x_ - i fy = y_ - j # ignore data point if outside image boundaries if (i in self._i_range) and (j in self._j_range): # in the future, will need to handle masked pixels here qx = 1. - fx qy = 1. - fy if (self._image[j][i] is not ma.masked and self._image[j+1][i] is not ma.masked and self._image[j][i+1] is not ma.masked and self._image[j+1][i+1] is not ma.masked): sample = (self._image[j][i] * qx * qy + self._image[j + 1][i] * qx * fy + self._image[j][i + 1] * fx * qy + self._image[j + 1][i + 1] * fy * fx) self._store_results(phi, radius, sample) def get_polar_angle_step(self): return 1. / self._r def get_sector_area(self): return 2. def is_area(self): return False class _AreaIntegrator(_Integrator): def __init__(self, image, geometry, angles, radii, intensities): super().__init__(image, geometry, angles, radii, intensities) # build auxiliary bilinear integrator to be used when # sector areas contain a too small number of valid pixels. self._bilinear_integrator = INTEGRATORS[BILINEAR](image, geometry, angles, radii, intensities) def integrate(self, radius, phi): self._phi = phi # Get image coordinates of the four vertices of the elliptical sector. vertex_x, vertex_y = self._geometry.initialize_sector_geometry(phi) self._sector_area = self._geometry.sector_area # step in polar angle to be used by caller next time # when updating the current polar angle `phi` to point # to the next sector. self._phistep = self._geometry.sector_angular_width # define rectangular image area that encompasses the elliptical # sector. We have to account for rounding of pixel indices. i1 = int(min(vertex_x)) - 1 j1 = int(min(vertex_y)) - 1 i2 = int(max(vertex_x)) + 1 j2 = int(max(vertex_y)) + 1 # polar angle limits for this sector phi1, phi2 = self._geometry.polar_angle_sector_limits() # ignore data point if the elliptical sector lies # partially, ou totally, outside image boundaries if (i1 in self._i_range) and (j1 in self._j_range) and \ (i2 in self._i_range) and (j2 in self._j_range): # Scan rectangular image area, compute sample value. npix = 0 accumulator = self.initialize_accumulator() for j in range(j1, j2): for i in range(i1, i2): # Check if polar coordinates of each pixel # put it inside elliptical sector. rp, phip = self._geometry.to_polar(i, j) # check if inside angular limits if phip < phi2 and phip >= phi1: # check if radius is inside bounding ellipses sma1, sma2 = self._geometry.bounding_ellipses() aux = ((1. - self._geometry.eps) / math.sqrt(((1. - self._geometry.eps) * math.cos(phip))**2 + (math.sin(phip))**2)) r1 = sma1 * aux r2 = sma2 * aux if rp < r2 and rp >= r1: # update accumulator with pixel value pix_value = self._image[j][i] if pix_value is not ma.masked: accumulator, npix = self.accumulate( pix_value, accumulator) # If 6 or less pixels were sampled, get the bilinear # interpolated value instead. if npix in range(0, 7): # must reset integrator to remove older samples. self._bilinear_integrator._reset() self._bilinear_integrator.integrate(radius, phi) # because it was reset, current value is the only one stored # internally in the bilinear integrator instance. Move it # from the internal integrator to this instance. if len(self._bilinear_integrator._intensities) > 0: sample_value = self._bilinear_integrator._intensities[0] self._store_results(phi, radius, sample_value) elif npix > 6: sample_value = self.compute_sample_value(accumulator) self._store_results(phi, radius, sample_value) def get_polar_angle_step(self): _, phi2 = self._geometry.polar_angle_sector_limits() phistep = self._geometry.sector_angular_width / 2. + phi2 - self._phi return phistep def get_sector_area(self): return self._sector_area def is_area(self): return True def initialize_accumulator(self): raise NotImplementedError def accumulate(self, pixel_value, accumulator): raise NotImplementedError def compute_sample_value(self, accumulator): raise NotImplementedError class _MeanIntegrator(_AreaIntegrator): def initialize_accumulator(self): accumulator = 0. self._npix = 0 return accumulator def accumulate(self, pixel_value, accumulator): accumulator += pixel_value self._npix += 1 return accumulator, self._npix def compute_sample_value(self, accumulator): return accumulator / self._npix class _MedianIntegrator(_AreaIntegrator): def initialize_accumulator(self): accumulator = [] self._npix = 0 return accumulator def accumulate(self, pixel_value, accumulator): accumulator.append(pixel_value) self._npix += 1 return accumulator, self._npix def compute_sample_value(self, accumulator): accumulator.sort() return accumulator[int(self._npix/2)] # Specific integrator subclasses can be instantiated from here. INTEGRATORS = { NEAREST_NEIGHBOR: _NearestNeighborIntegrator, BILINEAR: _BiLinearIntegrator, MEAN: _MeanIntegrator, MEDIAN: _MedianIntegrator } photutils-0.7.2/photutils/isophote/isophote.py0000644000214200020070000006035413572576702024055 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides classes to store the results of isophote fits. """ from collections import OrderedDict from astropy.table import QTable import astropy.units as u import numpy as np from .harmonics import (first_and_second_harmonic_function, fit_first_and_second_harmonics, fit_upper_harmonic) __all__ = ['Isophote', 'IsophoteList'] class Isophote: """ Container class to store the results of single isophote fit. The extracted data sample at the given isophote (sampled intensities along the elliptical path on the image) is also kept as an attribute of this class. The container concept helps in segregating information directly related to the sample, from information that more closely relates to the fitting process, such as status codes, errors for isophote parameters, and the like. Parameters ---------- sample : `~photutils.isophote.EllipseSample` instance The sample information. niter : int The number of iterations used to fit the isophote. valid : bool The status of the fitting operation. stop_code : int The fitting stop code: * 0: Normal. * 1: Fewer than the pre-specified fraction of the extracted data points are valid. * 2: Exceeded maximum number of iterations. * 3: Singular matrix in harmonic fit, results may not be valid. This also signals an insufficient number of data points to fit. * 4: Small or wrong gradient, or ellipse diverged. Subsequent ellipses at larger or smaller semimajor axis may have the same constant geometric parameters. It's also used when the user turns off the fitting algorithm via the ``maxrit`` fitting parameter (see the `~photutils.isophote.Ellipse` class). * 5: Ellipse diverged; not even the minimum number of iterations could be executed. Subsequent ellipses at larger or smaller semimajor axis may have the same constant geometric parameters. * -1: Internal use. Attributes ---------- rms : float The root-mean-square of intensity values along the elliptical path. int_err : float The error of the mean (rms / sqrt(# data points)). ellip_err : float The ellipticity error. pa_err : float The position angle error (radians). x0_err : float The error associated with the center x coordinate. y0_err : float The error associated with the center y coordinate. pix_stddev : float The estimate of pixel standard deviation (rms * sqrt(average sector integration area)). grad : float The local radial intensity gradient. grad_error : float The measurement error of the local radial intensity gradient. grad_r_error : float The relative error of local radial intensity gradient. tflux_e : float The sum of all pixels inside the ellipse. npix_e : int The total number of valid pixels inside the ellipse. tflux_c : float The sum of all pixels inside a circle with the same ``sma`` as the ellipse. npix_c : int The total number of valid pixels inside a circle with the same ``sma`` as the ellipse. sarea : float The average sector area on the isophote (pixel**2). ndata : int The number of extracted data points. nflag : int The number of discarded data points. Data points can be discarded either because they are physically outside the image frame boundaries, because they were rejected by sigma-clipping, or they are masked. a3, b3, a4, b4 : float The higher order harmonics that measure the deviations from a perfect ellipse. These values are actually the raw harmonic amplitudes divided by the local radial gradient and the semimajor axis length, so they can directly be compared with each other. a3_err, b3_err, a4_err, b4_err : float The errors associated with the ``a3``, ``b3``, ``a4``, and ``b4`` attributes. """ def __init__(self, sample, niter, valid, stop_code): self.sample = sample self.niter = niter self.valid = valid self.stop_code = stop_code self.intens = sample.mean self.rms = np.std(sample.values[2]) self.int_err = self.rms / np.sqrt(sample.actual_points) self.pix_stddev = self.rms * np.sqrt(sample.sector_area) self.grad = sample.gradient self.grad_error = sample.gradient_error self.grad_r_error = sample.gradient_relative_error self.sarea = sample.sector_area self.ndata = sample.actual_points self.nflag = sample.total_points - sample.actual_points # flux contained inside ellipse and circle (self.tflux_e, self.tflux_c, self.npix_e, self.npix_c) = self._compute_fluxes() self._compute_errors() # deviations from a perfect ellipse (self.a3, self.b3, self.a3_err, self.b3_err) = self._compute_deviations(sample, 3) (self.a4, self.b4, self.a4_err, self.b4_err) = self._compute_deviations(sample, 4) # This method is useful for sorting lists of instances. Note # that __lt__ is the python3 way of supporting sorting. def __lt__(self, other): if hasattr(other, 'sma'): return self.sma < other.sma raise ValueError('Comparison object does not have a "sma" attribute.') def __str__(self): return str(self.to_table()) @property def sma(self): """The semimajor axis length (pixels).""" return self.sample.geometry.sma @property def eps(self): """The ellipticity of the ellipse.""" return self.sample.geometry.eps @property def pa(self): """The position angle (radians) of the ellipse.""" return self.sample.geometry.pa @property def x0(self): """The center x coordinate (pixel).""" return self.sample.geometry.x0 @property def y0(self): """The center y coordinate (pixel).""" return self.sample.geometry.y0 def _compute_fluxes(self): """ Compute integrated flux inside ellipse, as well as inside a circle defined with the same semimajor axis. Pixels in a square section enclosing circle are scanned; the distance of each pixel to the isophote center is compared both with the semimajor axis length and with the length of the ellipse radius vector, and integrals are updated if the pixel distance is smaller. """ # Compute limits of square array that encloses circle. sma = self.sample.geometry.sma x0 = self.sample.geometry.x0 y0 = self.sample.geometry.y0 xsize = self.sample.image.shape[1] ysize = self.sample.image.shape[0] imin = max(0, int(x0 - sma - 0.5) - 1) jmin = max(0, int(y0 - sma - 0.5) - 1) imax = min(xsize, int(x0 + sma + 0.5) + 1) jmax = min(ysize, int(y0 + sma + 0.5) + 1) # Integrate if (jmax-jmin > 1) and (imax-imin) > 1: y, x = np.mgrid[jmin:jmax, imin:imax] radius, angle = self.sample.geometry.to_polar(x, y) radius_e = self.sample.geometry.radius(angle) midx = (radius <= sma) values = self.sample.image[y[midx], x[midx]] tflux_c = np.ma.sum(values) npix_c = np.ma.count(values) midx2 = (radius <= radius_e) values = self.sample.image[y[midx2], x[midx2]] tflux_e = np.ma.sum(values) npix_e = np.ma.count(values) else: tflux_e = 0. tflux_c = 0. npix_e = 0 npix_c = 0 return tflux_e, tflux_c, npix_e, npix_c def _compute_deviations(self, sample, n): """ Compute deviations from a perfect ellipse, based on the amplitudes and errors for harmonic "n". Note that we first subtract the first and second harmonics from the raw data. """ try: coeffs = fit_first_and_second_harmonics(self.sample.values[0], self.sample.values[2]) coeffs = coeffs[0] model = first_and_second_harmonic_function(self.sample.values[0], coeffs) residual = self.sample.values[2] - model c = fit_upper_harmonic(sample.values[0], residual, n) covariance = c[1] ce = np.diagonal(covariance) c = c[0] a = c[1] / self.sma / sample.gradient b = c[2] / self.sma / sample.gradient # this comes from the old code. Likely it was based on # empirical experience with the STSDAS task, so we leave # it here without too much thought. gre = self.grad_r_error if self.grad_r_error is not None else 0.64 a_err = abs(a) * np.sqrt((ce[1] / c[1])**2 + gre**2) b_err = abs(b) * np.sqrt((ce[2] / c[2])**2 + gre**2) except Exception: # we want to catch everything a = b = a_err = b_err = None return a, b, a_err, b_err def _compute_errors(self): """ Compute parameter errors based on the diagonal of the covariance matrix of the four harmonic coefficients for harmonics n=1 and n=2. """ try: coeffs = fit_first_and_second_harmonics(self.sample.values[0], self.sample.values[2]) covariance = coeffs[1] coeffs = coeffs[0] model = first_and_second_harmonic_function(self.sample.values[0], coeffs) residual_rms = np.std(self.sample.values[2] - model) errors = np.diagonal(covariance) * residual_rms eps = self.sample.geometry.eps pa = self.sample.geometry.pa # parameter errors result from direct projection of # coefficient errors. These showed to be the error estimators # that best convey the errors measured in Monte Carlo # experiments (see Busko 1996; ASPC 101, 139). ea = abs(errors[2] / self.grad) eb = abs(errors[1] * (1. - eps) / self.grad) self.x0_err = np.sqrt((ea * np.cos(pa))**2 + (eb * np.sin(pa))**2) self.y0_err = np.sqrt((ea * np.sin(pa))**2 + (eb * np.cos(pa))**2) self.ellip_err = (abs(2. * errors[4] * (1. - eps) / self.sma / self.grad)) if abs(eps) > np.finfo(float).resolution: self.pa_err = (abs(2. * errors[3] * (1. - eps) / self.sma / self.grad / (1. - (1. - eps)**2))) else: self.pa_err = 0. except Exception: # we want to catch everything self.x0_err = self.y0_err = self.pa_err = self.ellip_err = 0. def fix_geometry(self, isophote): """ Fix the geometry of a problematic isophote to be identical to the input isophote. This method should be called when the fitting goes berserk and delivers an isophote with bad geometry, such as ellipticity > 1 or another meaningless situation. This is not a problem in itself when fitting any given isophote, but will create an error when the affected isophote is used as starting guess for the next fit. Parameters ---------- isophote : `~photutils.isophote.Isophote` instance The isophote from which to take the geometry information. """ self.sample.geometry.eps = isophote.sample.geometry.eps self.sample.geometry.pa = isophote.sample.geometry.pa self.sample.geometry.x0 = isophote.sample.geometry.x0 self.sample.geometry.y0 = isophote.sample.geometry.y0 def sampled_coordinates(self): """ Return the (x, y) coordinates where the image was sampled in order to get the intensities associated with this isophote. Returns ------- x, y : 1D `~numpy.ndarray` The x and y coordinates as 1D arrays. """ return self.sample.coordinates() def to_table(self): """ Return the main isophote parameters as an astropy `~astropy.table.QTable`. Returns ------- result : `~astropy.table.QTable` An astropy `~astropy.table.QTable` containing the main isophote paramters. """ return _isophote_list_to_table([self]) class CentralPixel(Isophote): """ Specialized Isophote class for the galaxy central pixel. This class holds only a single intensity value at the central position. Thus, most of its attributes are hardcoded to `None` or a default value when appropriate. Parameters ---------- sample : `~photutils.utils.EllipseSample` instance The sample information. """ def __init__(self, sample): self.sample = sample self.niter = 0 self.valid = True self.stop_code = 0 self.intens = sample.mean # some values are set to zero to ease certain tasks # such as model building and plotting magnitude errors self.rms = None self.int_err = 0.0 self.pix_stddev = None self.grad = 0.0 self.grad_error = None self.grad_r_error = None self.sarea = None self.ndata = sample.actual_points self.nflag = sample.total_points - sample.actual_points self.tflux_e = self.tflux_c = self.npix_e = self.npix_c = None self.a3 = self.b3 = 0.0 self.a4 = self.b4 = 0.0 self.a3_err = self.b3_err = 0.0 self.a4_err = self.b4_err = 0.0 self.ellip_err = 0. self.pa_err = 0. self.x0_err = 0. self.y0_err = 0. @property def eps(self): return 0. @property def pa(self): return 0. @property def x0(self): return self.sample.geometry.x0 class IsophoteList: """ Container class that provides the same attributes as the `~photutils.isophote.Isophote` class, but for a list of isophotes. The attributes of this class are arrays representing the values of the attributes for the entire list of `~photutils.isophote.Isophote` instances. See the `~photutils.isophote.Isophote` class for a description of the attributes. The class extends the `list` functionality, thus provides basic list behavior such as slicing, appending, and support for '+' and '+=' operators. Parameters ---------- iso_list : list of `~photutils.isophote.Isophote` A list of `~photutils.isophote.Isophote` instances. """ def __init__(self, iso_list): self._list = iso_list def __len__(self): return len(self._list) def __delitem__(self, index): self._list.__delitem__(index) def __setitem__(self, index, value): self._list.__setitem__(index, value) def __getitem__(self, index): if isinstance(index, slice): return IsophoteList(self._list[index]) return self._list.__getitem__(index) def __iter__(self): return self._list.__iter__() def sort(self): self._list.sort() def insert(self, index, value): self._list.insert(index, value) def append(self, value): self.insert(len(self) + 1, value) def extend(self, value): self._list.extend(value._list) def __iadd__(self, value): self.extend(value) return self def __add__(self, value): temp = self._list[:] # shallow copy temp.extend(value._list) return IsophoteList(temp) def get_closest(self, sma): """ Return the `~photutils.isophote.Isophote` instance that has the closest semimajor axis length to the input semimajor axis. Parameters ---------- sma : float The semimajor axis length. Returns ------- isophote : `~photutils.isophote.Isophote` instance The isophote with the closest semimajor axis value. """ index = (np.abs(self.sma - sma)).argmin() return self._list[index] def _collect_as_array(self, attr_name): return np.array(self._collect_as_list(attr_name), dtype=float) def _collect_as_list(self, attr_name): return [getattr(iso, attr_name) for iso in self._list] @property def sample(self): """ The isophote `~photutils.isophote.EllipseSample` information. """ return self._collect_as_list('sample') @property def sma(self): """The semimajor axis length (pixels).""" return self._collect_as_array('sma') @property def intens(self): """The mean intensity value along the elliptical path.""" return self._collect_as_array('intens') @property def int_err(self): """The error of the mean intensity (rms / sqrt(# data points)).""" return self._collect_as_array('int_err') @property def eps(self): """The ellipticity of the ellipse.""" return self._collect_as_array('eps') @property def ellip_err(self): """The ellipticity error.""" return self._collect_as_array('ellip_err') @property def pa(self): """The position angle (radians) of the ellipse.""" return self._collect_as_array('pa') @property def pa_err(self): """The position angle error (radians).""" return self._collect_as_array('pa_err') @property def x0(self): """The center x coordinate (pixel).""" return self._collect_as_array('x0') @property def x0_err(self): """The error associated with the center x coordinate.""" return self._collect_as_array('x0_err') @property def y0(self): """The center y coordinate (pixel).""" return self._collect_as_array('y0') @property def y0_err(self): """The error associated with the center y coordinate.""" return self._collect_as_array('y0_err') @property def rms(self): """ The root-mean-square of intensity values along the elliptical path. """ return self._collect_as_array('rms') @property def pix_stddev(self): """ The estimate of pixel standard deviation (rms * sqrt(average sector integration area)). """ return self._collect_as_array('pix_stddev') @property def grad(self): """The local radial intensity gradient.""" return self._collect_as_array('grad') @property def grad_error(self): """ The measurement error of the local radial intensity gradient. """ return self._collect_as_array('grad_error') @property def grad_r_error(self): """ The relative error of local radial intensity gradient. """ return self._collect_as_array('grad_r_error') @property def sarea(self): """The average sector area on the isophote (pixel**2).""" return self._collect_as_array('sarea') @property def ndata(self): """The number of extracted data points.""" return self._collect_as_array('ndata') @property def nflag(self): """ The number of discarded data points. Data points can be discarded either because they are physically outside the image frame boundaries, because they were rejected by sigma-clipping, or they are masked. """ return self._collect_as_array('nflag') @property def niter(self): """The number of iterations used to fit the isophote.""" return self._collect_as_array('niter') @property def valid(self): """The status of the fitting operation.""" return self._collect_as_array('valid') @property def stop_code(self): """The fitting stop code.""" return self._collect_as_array('stop_code') @property def tflux_e(self): """The sum of all pixels inside the ellipse.""" return self._collect_as_array('tflux_e') @property def tflux_c(self): """ The sum of all pixels inside a circle with the same ``sma`` as the ellipse. """ return self._collect_as_array('tflux_c') @property def npix_e(self): """The total number of valid pixels inside the ellipse.""" return self._collect_as_array('npix_e') @property def npix_c(self): """ The total number of valid pixels inside a circle with the same ``sma`` as the ellipse. """ return self._collect_as_array('npix_c') @property def a3(self): """ A third-order harmonic coefficent. See the :func:`~photutils.isophote.fit_upper_harmonic` function for details. """ return self._collect_as_array('a3') @property def b3(self): """ A third-order harmonic coefficent. See the :func:`~photutils.isophote.fit_upper_harmonic` function for details. """ return self._collect_as_array('b3') @property def a4(self): """ A fourth-order harmonic coefficent. See the :func:`~photutils.isophote.fit_upper_harmonic` function for details. """ return self._collect_as_array('a4') @property def b4(self): """ A fourth-order harmonic coefficent. See the :func:`~photutils.isophote.fit_upper_harmonic` function for details. """ return self._collect_as_array('b4') @property def a3_err(self): """ The error associated with `~photutils.isophote.IsophoteList.a3`. """ return self._collect_as_array('a3_err') @property def b3_err(self): """ The error associated with `~photutils.isophote.IsophoteList.b3`. """ return self._collect_as_array('b3_err') @property def a4_err(self): """ The error associated with `~photutils.isophote.IsophoteList.a4`. """ return self._collect_as_array('a4_err') @property def b4_err(self): """ The error associated with `~photutils.isophote.IsophoteList.b3`. """ return self._collect_as_array('b4_err') def to_table(self): """ Convert an `~photutils.isophote.IsophoteList` instance to a `~astropy.table.QTable` with the main isophote parameters. Returns ------- result : `~astropy.table.QTable` An astropy QTable with the main isophote parameters. """ return _isophote_list_to_table(self) def _isophote_list_to_table(isophote_list): """ Convert an `~photutils.isophote.IsophoteList` instance to a `~astropy.table.QTable`. Parameters ---------- isophote_list : list of `~photutils.isophote.Isophote` or a `~photutils.isophote.IsophoteList` instance A list of isophotes. Returns ------- result : `~astropy.table.QTable` An astropy QTable with the main isophote parameters. """ properties = OrderedDict() properties['sma'] = 'sma' properties['intens'] = 'intens' properties['int_err'] = 'intens_err' properties['eps'] = 'ellipticity' properties['ellip_err'] = 'ellipticity_err' properties['pa'] = 'pa' properties['pa_err'] = 'pa_err' properties['grad'] = 'grad' properties['grad_error'] = 'grad_err' properties['grad_r_error'] = 'grad_rerr' properties['x0'] = 'x0' properties['x0_err'] = 'x0_err' properties['y0'] = 'y0' properties['y0_err'] = 'y0_err' properties['ndata'] = 'ndata' properties['nflag'] = 'flag' properties['niter'] = 'niter' properties['stop_code'] = 'stop_code' isotable = QTable() for k, v in properties.items(): isotable[v] = np.array([getattr(iso, k) for iso in isophote_list]) if k in ('pa', 'pa_err'): isotable[v] = isotable[v] * 180. / np.pi * u.deg return isotable photutils-0.7.2/photutils/isophote/model.py0000644000214200020070000001377513563423715023323 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module profiles tools for building a model elliptical galaxy image from a list of isophotes. """ import numpy as np from .geometry import EllipseGeometry __all__ = ['build_ellipse_model'] def build_ellipse_model(shape, isolist, fill=0., high_harmonics=False): """ Build a model elliptical galaxy image from a list of isophotes. For each ellipse in the input isophote list the algorithm fills the output image array with the corresponding isophotal intensity. Pixels in the output array are in general only partially covered by the isophote "pixel". The algorithm takes care of this partial pixel coverage by keeping track of how much intensity was added to each pixel by storing the partial area information in an auxiliary array. The information in this array is then used to normalize the pixel intensities. Parameters ---------- shape : 2-tuple The (ny, nx) shape of the array used to generate the input ``isolist``. isolist : `~photutils.isophote.IsophoteList` instance The isophote list created by the `~photutils.isophote.Ellipse` class. fill : float, optional The constant value to fill empty pixels. If an output pixel has no contribution from any isophote, it will be assigned this value. The default is 0. high_harmonics : bool, optional Whether to add the higher-order harmonics (i.e. ``a3``, ``b3``, ``a4``, and ``b4``; see `~photutils.isophote.Isophote` for details) to the result. Returns ------- result : 2D `~numpy.ndarray` The image with the model galaxy. """ from scipy.interpolate import LSQUnivariateSpline # the target grid is spaced in 0.1 pixel intervals so as # to ensure no gaps will result on the output array. finely_spaced_sma = np.arange(isolist[0].sma, isolist[-1].sma, 0.1) # interpolate ellipse parameters # End points must be discarded, but how many? # This seems to work so far nodes = isolist.sma[2:-2] intens_array = LSQUnivariateSpline( isolist.sma, isolist.intens, nodes)(finely_spaced_sma) eps_array = LSQUnivariateSpline( isolist.sma, isolist.eps, nodes)(finely_spaced_sma) pa_array = LSQUnivariateSpline( isolist.sma, isolist.pa, nodes)(finely_spaced_sma) x0_array = LSQUnivariateSpline( isolist.sma, isolist.x0, nodes)(finely_spaced_sma) y0_array = LSQUnivariateSpline( isolist.sma, isolist.y0, nodes)(finely_spaced_sma) grad_array = LSQUnivariateSpline( isolist.sma, isolist.grad, nodes)(finely_spaced_sma) a3_array = LSQUnivariateSpline( isolist.sma, isolist.a3, nodes)(finely_spaced_sma) b3_array = LSQUnivariateSpline( isolist.sma, isolist.b3, nodes)(finely_spaced_sma) a4_array = LSQUnivariateSpline( isolist.sma, isolist.a4, nodes)(finely_spaced_sma) b4_array = LSQUnivariateSpline( isolist.sma, isolist.b4, nodes)(finely_spaced_sma) # Return deviations from ellipticity to their original amplitude meaning a3_array = -a3_array * grad_array * finely_spaced_sma b3_array = -b3_array * grad_array * finely_spaced_sma a4_array = -a4_array * grad_array * finely_spaced_sma b4_array = -b4_array * grad_array * finely_spaced_sma # correct deviations cased by fluctuations in spline solution eps_array[np.where(eps_array < 0.)] = 0. result = np.zeros(shape=shape) weight = np.zeros(shape=shape) eps_array[np.where(eps_array < 0.)] = 0.05 # for each interpolated isophote, generate intensity values on the # output image array # for index in range(len(finely_spaced_sma)): for index in range(1, len(finely_spaced_sma)): sma0 = finely_spaced_sma[index] eps = eps_array[index] pa = pa_array[index] x0 = x0_array[index] y0 = y0_array[index] geometry = EllipseGeometry(x0, y0, sma0, eps, pa) intens = intens_array[index] # scan angles. Need to go a bit beyond full circle to ensure # full coverage. r = sma0 phi = 0. while phi <= 2*np.pi + geometry._phi_min: # we might want to add the third and fourth harmonics # to the basic isophotal intensity. harm = 0. if high_harmonics: harm = (a3_array[index] * np.sin(3.*phi) + b3_array[index] * np.cos(3.*phi) + a4_array[index] * np.sin(4.*phi) + b4_array[index] * np.cos(4.*phi) / 4.) # get image coordinates of (r, phi) pixel x = r * np.cos(phi + pa) + x0 y = r * np.sin(phi + pa) + y0 i = int(x) j = int(y) # if outside image boundaries, ignore. if (i > 0 and i < shape[1] - 1 and j > 0 and j < shape[0] - 1): # get fractional deviations relative to target array fx = x - float(i) fy = y - float(j) # add up the isophote contribution to the overlapping pixels result[j, i] += (intens + harm) * (1. - fy) * (1. - fx) result[j, i + 1] += (intens + harm) * (1. - fy) * fx result[j + 1, i] += (intens + harm) * fy * (1. - fx) result[j + 1, i + 1] += (intens + harm) * fy * fx # add up the fractional area contribution to the # overlapping pixels weight[j, i] += (1. - fy) * (1. - fx) weight[j, i + 1] += (1. - fy) * fx weight[j + 1, i] += fy * (1. - fx) weight[j + 1, i + 1] += fy * fx # step towards next pixel on ellipse phi = max((phi + 0.75 / r), geometry._phi_min) r = geometry.radius(phi) # zero weight values must be set to 1. weight[np.where(weight <= 0.)] = 1. # normalize result /= weight # fill value result[np.where(result == 0.)] = fill return result photutils-0.7.2/photutils/isophote/sample.py0000644000214200020070000003706413563423715023501 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides a class to sample data along an elliptical path. """ import copy import numpy as np from .geometry import EllipseGeometry from .integrator import INTEGRATORS __all__ = ['EllipseSample'] class EllipseSample: """ Class to sample image data along an elliptical path. The image intensities along the elliptical path can be extracted using a selection of integration algorithms. The ``geometry`` attribute describes the geometry of the elliptical path. Parameters ---------- image : 2D `~numpy.ndarray` The input image. sma : float The semimajor axis length in pixels. x0, y0 : float, optional The (x, y) coordinate of the ellipse center. astep : float, optional The step value for growing/shrinking the semimajor axis. It can be expressed either in pixels (when ``linear_growth=True``) or as a relative value (when ``linear_growth=False``). The default is 0.1. eps : float, optional The ellipticity of the ellipse. The default is 0.2. pa : float, optional The position angle of ellipse in relation to the positive x axis of the image array (rotating towards the positive y axis). The default is 0. sclip : float, optional The sigma-clip sigma value. The default is 3.0. nclip : int, optional The number of sigma-clip interations. Set to zero to skip sigma-clipping. The default is 0. linear_growth : bool, optional The semimajor axis growing/shrinking mode. The default is `False`. integrmode : {'bilinear', 'nearest_neighbor', 'mean', 'median'}, optional The area integration mode. The default is 'bilinear'. geometry : `~photutils.isophote.EllipseGeometry` instance or `None` The geometry that describes the ellipse. This can be used in lieu of the explicit specification of parameters ``sma``, ``x0``, ``y0``, ``eps``, etc. In any case, the `~photutils.isophote.EllipseGeometry` instance becomes an attribute of the `~photutils.isophote.EllipseSample` object. The default is `None`. Attributes ---------- values : 2D `~numpy.ndarray` The sampled values as a 2D array, where the rows contain the angles, radii, and extracted intensity values, respectively. mean : float The mean intensity along the elliptical path. geometry : `~photutils.isophote.EllipseGeometry` instance The geometry of the elliptical path. gradient : float The local radial intensity gradient. gradient_error : float The error associated with the local radial intensity gradient. gradient_relative_error : float The relative error associated with the local radial intensity gradient. sector_area : float The average area of the sectors along the elliptical path from which the sample values were integrated. total_points : int The total number of sample values that would cover the entire elliptical path. actual_points : int The actual number of sample values that were taken from the image. It can be smaller than ``total_points`` when the ellipse encompasses regions outside the image, or when sigma-clipping removed some of the points. """ def __init__(self, image, sma, x0=None, y0=None, astep=0.1, eps=0.2, position_angle=0., sclip=3., nclip=0, linear_growth=False, integrmode='bilinear', geometry=None): self.image = image self.integrmode = integrmode if geometry: # when the geometry is inherited from somewhere else, # its sma attribute must be replaced by the value # explicitly passed to the constructor. self.geometry = copy.deepcopy(geometry) self.geometry.sma = sma else: # if no center was specified, assume it's roughly # coincident with the image center _x0 = x0 _y0 = y0 if not _x0 or not _y0: _x0 = image.shape[1] / 2 _y0 = image.shape[0] / 2 self.geometry = EllipseGeometry(_x0, _y0, sma, eps, position_angle, astep, linear_growth) # sigma-clip parameters self.sclip = sclip self.nclip = nclip # extracted values associated with this sample. self.values = None self.mean = None self.gradient = None self.gradient_error = None self.gradient_relative_error = None self.sector_area = None # total_points reports the total number of pairs angle-radius that # were attempted. actual_points reports the actual number of sampled # pairs angle-radius that resulted in valid values. self.total_points = 0 self.actual_points = 0 def extract(self): """ Extract sample data by scanning an elliptical path over the image array. Returns ------- result : 2D `~numpy.ndarray` The rows of the array contain the angles, radii, and extracted intensity values, respectively. """ # the sample values themselves are kept cached to prevent # multiple calls to the integrator code. if self.values is not None: return self.values else: s = self._extract() self.values = s return s def _extract(self, phi_min=0.05): # Here the actual sampling takes place. This is called only once # during the life of an EllipseSample instance, because it's an # expensive calculation. This method should not be called from # external code. # If one wants to force it to re-run, then do: # # sample.values = None # # before calling sample.extract() # individual extracted sample points will be stored in here angles = [] radii = [] intensities = [] sector_areas = [] # reset counters self.total_points = 0 self.actual_points = 0 # build integrator integrator = INTEGRATORS[self.integrmode](self.image, self.geometry, angles, radii, intensities) # initialize walk along elliptical path radius = self.geometry.initial_polar_radius phi = self.geometry.initial_polar_angle # In case of an area integrator, ask the integrator to deliver a # hint of how much area the sectors will have. In case of too # small areas, tests showed that the area integrators (mean, # median) won't perform properly. In that case, we override the # caller's selection and use the bilinear integrator regardless. if integrator.is_area(): integrator.integrate(radius, phi) area = integrator.get_sector_area() # this integration that just took place messes up with the # storage arrays and the constructors. We have to build a new # integrator instance from scratch, even if it is the same # kind as originally selected by the caller. angles = [] radii = [] intensities = [] if area < 1.0: integrator = INTEGRATORS['bilinear']( self.image, self.geometry, angles, radii, intensities) else: integrator = INTEGRATORS[self.integrmode](self.image, self.geometry, angles, radii, intensities) # walk along elliptical path, integrating at specified # places defined by polar vector. Need to go a bit beyond # full circle to ensure full coverage. while phi <= np.pi*2. + phi_min: # do the integration at phi-radius position, and append # results to the angles, radii, and intensities lists. integrator.integrate(radius, phi) # store sector area locally sector_areas.append(integrator.get_sector_area()) # update total number of points self.total_points += 1 # update angle and radius to be used to define # next polar vector along the elliptical path phistep_ = integrator.get_polar_angle_step() phi += min(phistep_, 0.5) radius = self.geometry.radius(phi) # average sector area is calculated after the integrator had # the opportunity to step over the entire elliptical path. self.sector_area = np.mean(np.array(sector_areas)) # apply sigma-clipping. angles, radii, intensities = self._sigma_clip(angles, radii, intensities) # actual number of sampled points, after sigma-clip removed outliers. self.actual_points = len(angles) # pack results in 2-d array result = np.array([np.array(angles), np.array(radii), np.array(intensities)]) return result def _sigma_clip(self, angles, radii, intensities): if self.nclip > 0: for i in range(self.nclip): # do not use list.copy()! must be python2-compliant. angles, radii, intensities = self._iter_sigma_clip( angles[:], radii[:], intensities[:]) return np.array(angles), np.array(radii), np.array(intensities) def _iter_sigma_clip(self, angles, radii, intensities): # Can't use scipy or astropy tools because they use masked arrays. # Also, they operate on a single array, and we need to operate on # three arrays simultaneously. We need something that physically # removes the clipped points from the arrays, since that is what # the remaining of the `ellipse` code expects. r_angles = [] r_radii = [] r_intensities = [] values = np.array(intensities) mean = np.mean(values) sig = np.std(values) lower = mean - self.sclip * sig upper = mean + self.sclip * sig count = 0 for k in range(len(intensities)): if intensities[k] >= lower and intensities[k] < upper: r_angles.append(angles[k]) r_radii.append(radii[k]) r_intensities.append(intensities[k]) count += 1 return r_angles, r_radii, r_intensities def update(self, fixed_parameters): """ Update this `~photutils.isophote.EllipseSample` instance. This method calls the :meth:`~photutils.isophote.EllipseSample.extract` method to get the values that match the current ``geometry`` attribute, and then computes the the mean intensity, local gradient, and other associated quantities. """ self.geometry.fix = fixed_parameters step = self.geometry.astep # Update the mean value first, using extraction from main sample. s = self.extract() self.mean = np.mean(s[2]) # Get sample with same geometry but at a different distance from # center. Estimate gradient from there. gradient, gradient_error = self._get_gradient(step) # Check for meaningful gradient. If no meaningful gradient, try # another sample, this time using larger radius. Meaningful # gradient means something shallower, but still close to within # a factor 3 from previous gradient estimate. If no previous # estimate is available, guess it by adding the error to the # current gradient. previous_gradient = self.gradient if not previous_gradient: previous_gradient = gradient + gradient_error # solution adopted before 08/12/2019 # previous_gradient = -0.05 # good enough, based on usage if gradient >= (previous_gradient / 3.): # gradient is negative! gradient, gradient_error = self._get_gradient(2 * step) # If still no meaningful gradient can be measured, try with # previous one, slightly shallower. A factor 0.8 is not too far # from what is expected from geometrical sampling steps of 10-20% # and a deVaucouleurs law or an exponential disk (at least at its # inner parts, r <~ 5 req). Gradient error is meaningless in this # case. if gradient >= (previous_gradient / 3.): gradient = previous_gradient * 0.8 gradient_error = None self.gradient = gradient self.gradient_error = gradient_error if gradient_error: self.gradient_relative_error = gradient_error / np.abs(gradient) else: self.gradient_relative_error = None def _get_gradient(self, step): gradient_sma = (1. + step) * self.geometry.sma gradient_sample = EllipseSample( self.image, gradient_sma, x0=self.geometry.x0, y0=self.geometry.y0, astep=self.geometry.astep, sclip=self.sclip, nclip=self.nclip, eps=self.geometry.eps, position_angle=self.geometry.pa, linear_growth=self.geometry.linear_growth, integrmode=self.integrmode) sg = gradient_sample.extract() mean_g = np.mean(sg[2]) gradient = (mean_g - self.mean) / self.geometry.sma / step s = self.extract() sigma = np.std(s[2]) sigma_g = np.std(sg[2]) gradient_error = (np.sqrt(sigma**2 / len(s[2]) + sigma_g**2 / len(sg[2])) / self.geometry.sma / step) return gradient, gradient_error def coordinates(self): """ Return the (x, y) coordinates associated with each sampled point. Returns ------- x, y : 1D `~numpy.ndarray` The x and y coordinate arrays. """ angles = self.values[0] radii = self.values[1] x = np.zeros(len(angles)) y = np.zeros(len(angles)) for i in range(len(x)): x[i] = (radii[i] * np.cos(angles[i] + self.geometry.pa) + self.geometry.x0) y[i] = (radii[i] * np.sin(angles[i] + self.geometry.pa) + self.geometry.y0) return x, y class CentralEllipseSample(EllipseSample): """ An `~photutils.isophote.EllipseSample` subclass designed to handle the special case of the central pixel in the galaxy image. """ def update(self, fixed_parameters): """ Update this `~photutils.isophote.EllipseSample` instance with the intensity integrated at the (x0, y0) center position using bilinear integration. The local gradient is set to `None`. 'fixed_parameters' is ignored in this subclass. """ s = self.extract() self.mean = s[2][0] self.gradient = None self.gradient_error = None self.gradient_relative_error = None def _extract(self): angles = [] radii = [] intensities = [] integrator = INTEGRATORS['bilinear'](self.image, self.geometry, angles, radii, intensities) integrator.integrate(0.0, 0.0) self.total_points = 1 self.actual_points = 1 return np.array([np.array(angles), np.array(radii), np.array(intensities)]) photutils-0.7.2/photutils/isophote/tests/0000755000214200020070000000000013573510273022773 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/isophote/tests/__init__.py0000644000214200020070000000000013563423715025075 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/isophote/tests/data/0000755000214200020070000000000013573510273023704 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/isophote/tests/data/M51_table.fits0000644000214200020070000006250013547426552026316 0ustar lbradleySTSCI\science00000000000000SIMPLE = T / file does conform to FITS standard BITPIX = 16 / number of bits per data pixel NAXIS = 0 / number of data axes EXTEND = T / FITS dataset may contain extensions COMMENT FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H ORIGIN = 'STScI-STSDAS/TABLES' / Tables version 2002-02-22 FILENAME= 'M51_table.fits' / name of file NEXTEND = 1 / number of extensions in file END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 160 / width of table in bytes NAXIS2 = 52 PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 40 TTYPE1 = 'SMA ' / label for field 1 TFORM1 = '1E ' / data format of field: 4-byte REAL TUNIT1 = 'pixel ' / physical unit of field TTYPE2 = 'INTENS ' / label for field 2 TFORM2 = '1E ' / data format of field: 4-byte REAL TTYPE3 = 'INT_ERR ' / label for field 3 TFORM3 = '1E ' / data format of field: 4-byte REAL TTYPE4 = 'PIX_VAR ' / label for field 4 TFORM4 = '1E ' / data format of field: 4-byte REAL TTYPE5 = 'RMS ' / label for field 5 TFORM5 = '1E ' / data format of field: 4-byte REAL TTYPE6 = 'ELLIP ' / label for field 6 TFORM6 = '1E ' / data format of field: 4-byte REAL TTYPE7 = 'ELLIP_ERR' / label for field 7 TFORM7 = '1E ' / data format of field: 4-byte REAL TTYPE8 = 'PA ' / label for field 8 TFORM8 = '1E ' / data format of field: 4-byte REAL TUNIT8 = 'degrees ' / physical unit of field TTYPE9 = 'PA_ERR ' / label for field 9 TFORM9 = '1E ' / data format of field: 4-byte REAL TUNIT9 = 'degrees ' / physical unit of field TTYPE10 = 'X0 ' / label for field 10 TFORM10 = '1E ' / data format of field: 4-byte REAL TUNIT10 = 'pixel ' / physical unit of field TTYPE11 = 'X0_ERR ' / label for field 11 TFORM11 = '1E ' / data format of field: 4-byte REAL TUNIT11 = 'pixel ' / physical unit of field TTYPE12 = 'Y0 ' / label for field 12 TFORM12 = '1E ' / data format of field: 4-byte REAL TUNIT12 = 'pixel ' / physical unit of field TTYPE13 = 'Y0_ERR ' / label for field 13 TFORM13 = '1E ' / data format of field: 4-byte REAL TUNIT13 = 'pixel ' / physical unit of field TTYPE14 = 'GRAD ' / label for field 14 TFORM14 = '1E ' / data format of field: 4-byte REAL TTYPE15 = 'GRAD_ERR' / label for field 15 TFORM15 = '1E ' / data format of field: 4-byte REAL TTYPE16 = 'GRAD_R_ERR' / label for field 16 TFORM16 = '1E ' / data format of field: 4-byte REAL TTYPE17 = 'RSMA ' / label for field 17 TFORM17 = '1E ' / data format of field: 4-byte REAL TUNIT17 = 'pixel**1/4' / physical unit of field TTYPE18 = 'MAG ' / label for field 18 TFORM18 = '1E ' / data format of field: 4-byte REAL TTYPE19 = 'MAG_LERR' / label for field 19 TFORM19 = '1E ' / data format of field: 4-byte REAL TTYPE20 = 'MAG_UERR' / label for field 20 TFORM20 = '1E ' / data format of field: 4-byte REAL TTYPE21 = 'TFLUX_E ' / label for field 21 TFORM21 = '1E ' / data format of field: 4-byte REAL TTYPE22 = 'TFLUX_C ' / label for field 22 TFORM22 = '1E ' / data format of field: 4-byte REAL TTYPE23 = 'TMAG_E ' / label for field 23 TFORM23 = '1E ' / data format of field: 4-byte REAL TTYPE24 = 'TMAG_C ' / label for field 24 TFORM24 = '1E ' / data format of field: 4-byte REAL TTYPE25 = 'NPIX_E ' / label for field 25 TFORM25 = '1J ' / data format of field: 4-byte INTEGER TTYPE26 = 'NPIX_C ' / label for field 26 TFORM26 = '1J ' / data format of field: 4-byte INTEGER TTYPE27 = 'A3 ' / label for field 27 TFORM27 = '1E ' / data format of field: 4-byte REAL TTYPE28 = 'A3_ERR ' / label for field 28 TFORM28 = '1E ' / data format of field: 4-byte REAL TTYPE29 = 'B3 ' / label for field 29 TFORM29 = '1E ' / data format of field: 4-byte REAL TTYPE30 = 'B3_ERR ' / label for field 30 TFORM30 = '1E ' / data format of field: 4-byte REAL TTYPE31 = 'A4 ' / label for field 31 TFORM31 = '1E ' / data format of field: 4-byte REAL TTYPE32 = 'A4_ERR ' / label for field 32 TFORM32 = '1E ' / data format of field: 4-byte REAL TTYPE33 = 'B4 ' / label for field 33 TFORM33 = '1E ' / data format of field: 4-byte REAL TTYPE34 = 'B4_ERR ' / label for field 34 TFORM34 = '1E ' / data format of field: 4-byte REAL TTYPE35 = 'NDATA ' / label for field 35 TFORM35 = '1J ' / data format of field: 4-byte INTEGER TTYPE36 = 'NFLAG ' / label for field 36 TFORM36 = '1J ' / data format of field: 4-byte INTEGER TTYPE37 = 'NITER ' / label for field 37 TFORM37 = '1J ' / data format of field: 4-byte INTEGER TTYPE38 = 'STOP ' / label for field 38 TFORM38 = '1J ' / data format of field: 4-byte INTEGER TTYPE39 = 'A_BIG ' / label for field 39 TFORM39 = '1E ' / data format of field: 4-byte REAL TTYPE40 = 'SAREA ' / label for field 40 TFORM40 = '1E ' / data format of field: 4-byte REAL TUNIT40 = 'pixel ' / physical unit of field TDISP1 = 'F7.2 ' / display format TDISP2 = 'G10.3 ' / display format TDISP3 = 'G10.3 ' / display format TDISP4 = 'G9.3 ' / display format TDISP5 = 'G9.3 ' / display format TDISP6 = 'F6.4 ' / display format TDISP7 = 'F6.4 ' / display format TDISP8 = 'F6.2 ' / display format TDISP9 = 'F6.2 ' / display format TDISP10 = 'F7.2 ' / display format TDISP11 = 'F6.2 ' / display format TDISP12 = 'F7.2 ' / display format TDISP13 = 'F6.2 ' / display format TDISP14 = 'G8.3 ' / display format TDISP15 = 'G6.3 ' / display format TDISP16 = 'G6.3 ' / display format TDISP17 = 'F7.5 ' / display format TDISP18 = 'G7.3 ' / display format TDISP19 = 'G7.3 ' / display format TDISP20 = 'G7.3 ' / display format TDISP21 = 'G12.5 ' / display format TDISP22 = 'G12.5 ' / display format TDISP23 = 'G7.3 ' / display format TDISP24 = 'G7.3 ' / display format TDISP25 = 'I6 ' / display format TNULL25 = -2147483647 / undefined value for column TDISP26 = 'I6 ' / display format TNULL26 = -2147483647 / undefined value for column TDISP27 = 'G9.3 ' / display format TDISP28 = 'G7.3 ' / display format TDISP29 = 'G9.3 ' / display format TDISP30 = 'G7.3 ' / display format TDISP31 = 'G9.3 ' / display format TDISP32 = 'G7.3 ' / display format TDISP33 = 'G9.3 ' / display format TDISP34 = 'G7.3 ' / display format TDISP35 = 'I5 ' / display format TNULL35 = -2147483647 / undefined value for column TDISP36 = 'I5 ' / display format TNULL36 = -2147483647 / undefined value for column TDISP37 = 'I3 ' / display format TNULL37 = -2147483647 / undefined value for column TDISP38 = 'I2 ' / display format TNULL38 = -2147483647 / undefined value for column TDISP39 = 'G9.3 ' / display format TDISP40 = 'F5.1 ' / display format IMAGE = 'dev$pix ' END Eñ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿC€ñ)ÿÿÿÿC~§ÿÿÿÿÄ϶ÿÿÿÿÿÿÿÿÁ‰Bÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿ?__EÖ¥nA·÷ŒBêƒGB¥ÓZ=J‹=³ ´BSäB“°ñC€ñ)<ÁQ&C~§<Á[ÄÏ‚ÇD ÑŒ>Æe§?Y~`Áy•;n¡h;mÑ¡Eñ°Eñ°Á‰BÁ‰B=¨i=8 –¼ÔÛº=›‰=H?ç<Ìh¬½‡À„<õ¸! @)kM@?µµEÔ A»oBø<\B¯‡z=#¡b=­ kB@^-BÅLC€ð=<Íð¤C}À<ͽ)Ä͆YDÆ7>ÀÉ?^¼üÁDE;¬¾;~ºjEñ°Eñ°Á‰BÁ‰B=—”™=.v;¼Î'9=¡&;úsx<‰Ñ½ª;F= H @}“Ä@?!azEÑ‘ÀAäRžC‡BÍέ=J[=¹kÆB[w¹B_ |C€íT<ôš~C~U<ó ’ÄÊLTD#¼6>Ï3>?dùÁ";—¾;—Eñ°Eñ°Á‰BÁ‰B=´í%=G+Û¼Ïok=d=†›==Ô ½f*<<ã×€ A:ª@?1„ÓEÎ} AâãÞCYBÌ„=eàa=¨iB=¥B2©5C€í<ôÄC}<ô;uÄÈ‚DŽ¢>¾!?iœÁÍE;™ {;˜]LEñ°Eñ°Á‰BÁ‰B=••]=+¶Ž¼Éyù=MŒ:Ö<‡†ñ½©Â—= ©ü @£2@?CEOEËSÌAñxiCècBÙ¨=„Á•=£Ì)BHÉBC€êu=ÕËC}=ÿˆÄŽD>¹¾Ë?o>6Áˆ©;¥m;¤©úEñ°Eñ°Á‰BÁ‰B= pD=(&C¼Ï(ä<õ×<ÈÊ7<—Û½2<ôÔ6 @¹*þ@?VÌ>EÇçB\DC# ÈBçg¯=•Û*=–¤SB86éA÷PíC€é=­¶C}=vÄÍm,DÈZ>¦·ã?uÁ=*;²ì ;²Eñ°Eñ°Á‰BÁ‰B=‚l¤=±7¼ÎYc<ñÏ«¼ …‰µ?zë’ÁÜÜ;­¤;¬.¢Eñ°Eñ°Á‰BÁ‰B<ÇM;<ìˆ÷¼»ßÄ<ã&½aM<|“ô½“ã<¶ ? 2@ëì@?óãE¿uAëÖCQBÔ”d=©HÆ=<þ¡AáZuAŠðC€ç<ȺC~<ÎìÄõÓ^CÁä’>Iêô?€|CÁua;«éƒ;«˜Eñ°GÈÁ‰BÁ4¹E¼Ag<¡Ôž½çÞ<¥Œ…½Cr-Bz?ƒ•kÁï±;•zŒ;”ÔPGÈGÈÁ4¹EÁ4¹E¼F”³%E²6oA¯Œ4BßǾBž<=¾&M<Õ<–Aç)÷A _/C€é<‰ƒ‰C}´<Ži´Å¹%Cs")=ê{&?†Á²Á>Y;‰,Œ;ˆž@GÈGÈÁ4¹EÁ4¹E¼I‘Ÿ£yÖ@?¬÷E©û9A™ò­BÄ>ôBŠÄN=·'‘<©ÃóAð@åûBC€êÐÙ"@?ÑJEE—žA£m¶BÐTÔB“P=¼]<‘_Aó*@À‰C€í#GRÿGRÿÁ=LòÁ=Lò ¼\=;îs“<(Á;äN‰<o~;Ô »º¿ø;ÉÇë ? 2è@?æ8E‹ƒA”¼|B½š/B†®=®u\}A >LB[lB'«=Âc°<dA®s @+J[C€îÇ<(*Ct›<,]Ä¥þøB–Ìæ=h¶?Ÿ7[Á <ü;R$£;QŽG°‡G½.ÁF>GÁGrºRv|;-WGå(H¦ÁJƬÁMQñ%¼ Û;_Ã<Í"8;sYÀ;‰ú ;QC@:$;Q ‹ ?ׯ@@`PæE ~f@ï „BA¦ØBîµ=ʶw<2XAñî@UuÉC€ðÉ<¢a?Ch<¨c¥Ä ÜAóøG=`žœ?¯#KÁ2;l×|;l÷«@@v¿dE¾ @èOyBDóeB Cå=Ч݄@@‡¶DíJ@Ù¢¾B@]WB·=ÚøE<[4øB«6@q$›C€é×<òQgCjå<ùT6æF·AÁÜj=•<?·¯§ÁÅ;’•;~¶‡H9@H*”@ÁP)pÁQ°d19¼¸c¹;Ÿú»aõC~Z=?û5Ã`î;A°¢=ÈiK?À¦ÓÁ…¡;ŸMt;ž’àHEH^@ÁT<+ÁVEÊIY¼æ_<ë¼F»¡;îL¼ÆÚ;½’¼7Ý;­dÕ =éý@@´¡²D½*µ@þ¤ÙBƒ=B9š!=¿‹€<¦€BðK@ÒÓ)C€Ø’=v—pCZ=yæÃ<ØjA§‡7=ã/?ÅLÀþe;»Ñ;º˜6Hd €HiÔ@ÁV»­ÁW*þ]a½<€¼e±6<Kr¼þêî;þzç9þ`;â-)" >¸èŸ@@ƱÞD¯•=A=(Bì¯BH¶,=¤S<³íOB ÕÈA×5C€Ý±=‘ÃXC¥>=”’Ã#%ƒA›C=ó ­?ÊÀûÎH;ÎÃÈ;Í“@Hz·H…l`ÁXaÁYvdmy½ <4¸*»1µ´<%^¼úŸ<gGÙ@@ÚuD£ÙAµIB™œwBY=1=–88<Øb{Aõ³×A*2jC€æ(=¼€ŽC¼=ÂeùÃUIAíz> Yä?ÎíSÀù=÷;èß;æ‰çHŽ” H”º ÁZ™Á[YZ‡‘¼ê‰ƒ<\Cä<3”ïedÂÉIkA‚¯S>&5?ÓêµÀ÷í;þ‡5;ü·aHŸß@H¨ÀÁ\š¦Á]z]£±¼©<†Q<¦iT<†ãø;{€<}¼<Êô<„oã- >Tè¡@A;=DÛÆA|B©[ BoG={Ð÷=-ÝAVÕJA¢Y·CÈ>4ŽaCø¸>=aý† Au<ÿ>jh?ÙåÀôáÍ<]µ<hVH· HÀÅ@Á^õ†Á_ÚÖËݼ‰îq<µÛw9mY}<´(Q="Éè<»š,¼2Î<®mM2 >çV@At]D‹ØßA6ïBÀÿýBˆx¹=ƒz=KÎÁÙBA¶¯ñCl÷>kNßC‚1«>rÞÇÂ`@ A]Ų>}+Ø?ÞB ÀóæE<æÂ<²sHʺ€HÖš Á`ºÔÁa·ýï¼Ýx<ÒÌ5=A ©<᪇½|Ïo<äGûÀ(M<À9À7 >xóÙ@A Dˆ0TA"BºRšBƒÀ=ÏêÌ=÷4Á¾’úA3=ÃC£œ>Eð•C‚\ÿ>OÛzÂn±€A9ÀÜ>G8·?ãž©Àòú< e5< Q&HáYÀHô Áb‘KÁcóÁ=¼©_e<—ë‹={—<¹%î½(xÞ<›½¯»Ãžµ<ŒsK<>%Ì>@A0D‚¨@ûüâB².«B{üâ>r˜<é/Á‰\@ÑW?CÄß>$|‘C‚kw>4OЮAïn> |¯?éÈÀñ‰¥<†'<‚áHùw@I ðÁdUiÁeöÕGy½;G P¥<Ï6fÁ­[8@¡ÒÕCÐ/>$&C‚jH>3‚.ÂkxADý> ]ÿ?îºÉÀï—á<®ä<³æI 80Ik Áf>Áh`yѽ/žL<\Õg={C P¥=$ h ëA CÐ/>“ZõC‚jH>˜5¾”A©G>u«U?ô|}ÀíRz< Ž<ÿIlàI0épÁh|ÅÁjg™Ó)<\’¨<¯êl=°½U<ò\æ½ARþ<‘ŽK¾Øæ= !M2ACÂÎ@AjAŠDcßûAcäB˲B‹k>râÍ=&ÃÛÂ"R)@³ÌÂC«{>®™qC‚?m>´SÁë«B@ÿ„ð>ŠÈ ?úaºÀìÇÐ<K]<ë I)`IJ*àÁiŸ Ál¹ ¡<+\;<ËÊ=¨ã =T$½G6<Ý»‘¾ "Ù=$²ÕP2AÜ@A€×?D_îAÔ/BØÓØB™Qù>“òf=†Â"R)@‹MÆCÏÕ>·19C‚ K>¾œ1Áã0°@ôçG>‰úÏ@5®Àì,Ž<&ä¶<%VÈI8ZÀIeG0ÁkÜÁnè®I%½Ìt<úÖ}=<.1<à}R¼Ø}™<ª´O¾B)=" ‹T2@ßy‚@A¹’D]¶ÆA³>Bß_þBó0>· <šÔ&¨Ê?ïåÇCö8>W@7C‚D¥>e"†Â9ŽG@Ö²¦>O@M"ÀëÔ<)¬<(äICÁIƒ«ÐÁl)°ÁqP²}Õ½a9 ‘d@A›åºD<û'@ó(ðBájOBŸd†>6L <”7{Â[·@KáÎCzã>M—C‚?m>BâEÂLyÈ@µié=ã u@w«ÀæG<<3¸T<1ìúI„\(I–8ÁqgçÁsšÇ×±½!ð·<+©à=É<*ŸÁ¼b¹°<ìð¼ªð<zÔn @O @A«|³D*ñ @÷ÛBí¤uB¨ ß>Z³¤<¼;•ÂY7Ê@\þCB>“‚C‚%>Šû»Âd¯@­ž…>Ï@ µÀÀâÊéô<{X2¼|É Óè<š·ÂKà@YºC€ÀŸ>‹ñýCŽH>„î×Â1rØ@×ó*>Å·@ ÙÀáõó<üô<|\2I›Ç˜I¼Á Áti>a^ÊC;ø>X¡ŒÂ?@ŽûÄ=ì7@nrÀÙ¿ü<]–‚Ÿ>š)ZC‚eV>¡•ÙÁê¿@Œ1ñ>àú@ê ÀÚ^?hûê@{ ÀÌÒ<ˆ½v<†«ŠIúv`Ju<Á||=Á}Ü K ¼v;M<ûB=H7<¨mļKÄ.^w³@";ÀÈ…Ö<®´J<«V\J 7¤JKÈÁ~ºÁ~´[ ™¡=`vÚ<ÏvÞ=²øÈ<ñ.¼„=<·ä½w< ÆÐ2A J @BæbCÍÑ@¦‡ÓBÞ¾ŽB =ŠY=2Ú”ÂsèíA˜}ºCV¤?^ÀœCðß?Wþ¿Àö{?a=é¼n@ßãÀÄ7¬<¤¸ï<¡º~Jé J›PÁ¹ÏÁ€!‡¼£-ä<ºÎê=Œ×ì<Å´¢½ŠÜ<Àáк‡û<·:Èå2Bã@B'C‚0@¥n–BèB¤"k=ŠY= 5QÂsèíAo.VC€?@÷C„<›?:PBÁ 3o@‰>ovÉ@"´£ÀÁ?{<²_}<®Þ*J'<øJ,u(Á€ÁOÁ¥ûa½u7}<µ¢–½“ó5<ÆE½?ý×<™½þ=ðQX=¸Xü2B%@B7̇CwÝu@z.ëB² #B|Z>-åX<ɽfB¡r8@éFC|Éa?*;+C‚û?\fÁ¶P?‰7Ô>^õ@&¡ À¿‰ˆ-åX<·o±Øg@ƒã#C|Éa?*tóC‚û?äzÀ‡wž?nÎ> 2@*¥¨À¸òh<1’©JM¹ÜÁÝkÁ‚ßû]<ô¦ÿ`HµÏuC‚’¥>¯%0À•¯>Ü%u=¼AT@.ÃÀ¶§™<„Z;ÿ3ÅJIž¬J`‹Á‚a ÁƒP}%ù;d]#;óöb<¤4 ;ûb[¼‰`ä;둦=! %<S3 ?poñ@Bt¢ìC?Ù?fò¥AÆöVAŒ°C~'f?[ÌC‚’¥?XÓÊ¿±‹ÿÿÿÿÿÿÿÿ@2ùçÀ®Ôø;Ò;ÐÑJr¶Jtm¼Áƒý}Á„ +-=-ñ;ßO'Â>“û3>)ÕbÂ> Ažý6C€ÿ=]UžC€~|=WŸcÄ¢QD Xd?‰©Ò?Y~`Á‡;'; á¢F’*F’*ÁÅ+ÁÅ+¼ÖÙ=ä%.»Ž½=ÔnF½•w·=§ÔD¾ ½Œ>­Aò =Fâ:@?µµF%ªA±[HBâBŸÝ÷>“û3>)ÂÂ=ûpAžëC€€=sZ¦C€~S=mËÄ ˆžD?‰ŽI?^¼üÁz;,a×;+ÿ/F’*F’*ÁÅ+ÁÅ+¼×P÷=ä§»ŽQD=ÔSÀ½•=³=§uð¾ ¬¶>­ . =´dö@?!azF£dAÖ§¸CÐüBÁ|Ï>“û3>)¾¶Â>ÀAžçþC€€=…ÖÝC€~(=‚a¾Ä²D'V]?‰’/?dùÁj©;QvA;PÒçF’*F’*ÁÅ+ÁÅ+¼× «=䈻)ü=ÔO'½•ˆ|=§Ã; ¨ƒ>­ _ =Ó9'@?1„ÓFµBØ!C%…Bê>“û3>)À,Â=þ­ S =@?CEOF GB'CHT¾C §Ê>“û3>)ÊjÂ>ûAžòòC€þ=¡üÝC€}È=ÎQÄ6Á@;šì;šB£F’*F’*ÁÅ+ÁÅ+¼ÕÕd=ä» =Ô_•½•}È=§Ç¤¾ ³œ>­$Ž =Þm.@?VÌ>F `B>&Crd‰C+eÅ>“û3>)ÆÖÂ=ùvAžïšC€€=²*NC€}Œ=­”?ÄO6YD^½‰?‰—’?uÁ#‹;¼Ã†;»½¥F’*F’*ÁÅ+ÁÅ+¼×ƒ=ä!»­¹ =ü™š@?lGF HÎBfÞC’¤ÏCOb¹>“û3>)ÅÐÂ=ýpAžî¥C€€=Ãû#C€}N=¾í³ÄcîXDuO?‰—.?zë’ÁØ;æM;äÓÂF’*F’*ÁÅ+ÁÅ+¼Öö=ä·»Ž@=ÔXÞ½•Z =§i¾ ¯ú>­Ð >&•·@?óãF ÷B‹6îC±vçCzøÿ>“û3>)ȆÂ>Ažñ.C€ý=ךC€} =ÒdÄzÀ˜D†Çi?‰™}?€|CÁÖƒ< É< ¯ôF’*G5ö´ÁÅ+Á:ºŸ¼Õ=ä »Œ“=Ô\ν•¼M=¨Q¾ ¯ë>­® >‰“è@?Žò­FX÷B¨È÷C×(×C˜$ >“K±=ë7éÂ=eA] C€õ=£ðC€|¼=ŸûÚÄÇÛ„DŽZO?6Wk?ƒ•kÁ¢<,ßf<+6-F’*G5ö´ÁÅ+Á:ºŸ¼—D7=ší©»\Ñî=’½Í½F¿=Y¾^dD>7¿ ?Ô=ç@?>%F´B¦Í‘CÔ¢C–Z¬>wdª=…"Â7'úA¾C€€Ô=Bn§C€~µ=A&«Å(èÉD`}">ªI?†Á²Á¶<0uÕ<.¹1G5ö´G5ö´Á:ºŸÁ:ºŸ¼,Ž="š‹»´ƒò=à‹¼·rãSC=(ÉÓÂ;Ôl@Ó'OC€=VC€Z=’uÅH¤ïDç>J½÷?ŠÁ,Z<ûÿ<Ê‹G5ö´G5ö´Á:ºŸÁ:ºŸ»‡ ï<Ģ˻‹Zì<½ -¼€2y<+µ ½…*j<ƒP+ >LDù@?¾C„Eëü;BNxdCƒ™xC:>Gêv<í»âÂ:cö@œ-;C€:<ËýC€R<Èö]ÅMU CãB·> «u?U}Á;ô";òYÓGrâ‡G’®Á?¾áÁC‘ »!ºí<ˆ§­»ñÚ<ƒ\q¼Rè< Ɔ½-xÂ<#~ç ={Ò@?ÑJEEÜ6DB*ÀNCYªyCé½>C%6<·ÙîÂ9ï@vÓ~C€€è<¬ ªC€(<ªv*ÅHÅC¥Ëâ=ÓgÛ?½öÁëm;Ø*Â;Öá3Grâ‡G’®Á?¾áÁC‘ »o£a<ý“<„WÂ8òÈ@6‚ÒC€&<‡A]C€S<†C:Å=šùCPªÃ=ŒÞG?”;xÁ‚Ì;­Ì;¬¿‰G’®G’®ÁC‘ÁC‘ »€æ€<¡gºËj<Ò¼ ‘B;°u¼¬{®;­ðB =Âý@?ý=µE¹@A’ÍB»"·B„S*>5KÇ<·BÂ7Δ?Ö¿^C€<<'ÐC€Ñ<&ªÅ2ÈC\Ë=O|¡?—Î…ÁæÚ;\Ìh;\^G’®G’®ÁC‘ÁC‘ »¾Í±;˜b:;—5T»½Yµ;‡>U»²1; =L\@@ HWE¦:ÙAªVBØÈâB™J9>*üû5z;×ZÜÂënú@@(ˆ-EŒãÕA-2ýBm)¨B'³ >?<‚ÏÂ1Ü?®©KC€€.<@¤pC€€üI`@@9b˜EËè@ô9¤B2Aû½Õ>D›ä;ŸäüÂ6Xî?WQ·C€é<ÂC€€f<6xÄ®¢AAþe<ºv>?¦üÆÁ¼;äb;˜dH ª3H?QÁN5ÁNåv9ζ¾;=rUº³a;5º¨ù¡;øÿ»ÍÁ&;-7 > m³@@KìtEiÑ@™xAÔf4A–0^>AN‚;Y?Â3î?Õ C€ý;Á¸3C€ù;Áù²Ä‰¹A´#<¨'×?«›Áëz:¨w:¨0÷H ª3H9´ÁN5ÁSI%¸£nž:ùë7¸¨çs:ùŽf:½Í:ç1‹;M":çô =¸ó´@@`PæESÌÇ@¡:äAþíUA´B»>AÌr;‹›ýÂ8¶Å?90 C€€š< 8HC€ù< bkÄWÿ§A’ž<­/R4-@@v¿dEABû@'šõAŠø’ADˆÞ>FŸ…;BÂ4¼Z>¿µ:C€»; ¹ C€ý; ’YÄ=ÑAÔ F÷D:Ö¬WÂ18>ŠjsC€€;€ ïC€€;€ZÄ&‘-@Ù<&Õq?·¯§Á â¯:<ª‡:>G²b; 9Â3î¦>°XjC€ü;¶ ÁC€€ ;¶rÄ…ô@£5 <"Šï?¼‘Á Î:gÚg:gÃNHtDKH…”ÁWí4ÁYjŽ;E9ï»:£ôx¹À¨o:¥0Ø7Y¿:”§;'±:•Ì´2?Q÷ @@¤5çE–—?Šæ A:@@ºÿ|>I­:”{‹Â35ô>=E*C€ò;W2C€>;WnÃä ï@HI:ŒXàÂ2ë£>4bÊC€€T;_²ÖC€€H;`2ö×@ \Ë;Ć?ÅLÁn'9ýX 9ýEH“¸5H e˜Á[;Á\©9Sa9µxm:)2¹kK:'c[¹5:Í:²Ã:Œö =<‘@@ƱÞDæ7?%‰M@­>@tÔß>Jdù:R’*Â49j>ˆC€€¢;8­†C€º;8ž¶Ã›V‘?¡x9;… i?ÊÁ›ã9Ǫ]9È hH¡çH´^Á\ºÁ^³ ayº2y¾9÷ýz8:âº9ö´¶¸3Ã9溂+¿9äç # <$YH@@ÚuDÍýÚ>É0@^ø@ ]>I¸": àùÂ3¾Ù=¶” C€€+; ~aC€½; ‰üÃ}æ–?<>§;=Í?ÎíSÁ­v9‡Ê9‡­BH³ÌHÆgãÁ^žÁ`Zúw‘ºi›9¦©M¹=)ö9£ÄÆ·œ¯¿9¡N†9ör¹9žŒ“' ;ÒÃ}@@ðk´D¸{g>_$á?ÿ¤Å?´Äq>Jë¤9©)#Â4’°=TOC€å:²ü¤C€ù:²Ö:ÃRn±?ïÃ;Ê?ÓêµÀý†9(.è9'üƒHÂÖùHÛ´=Á` QÁb q‹±9ª¾9Kà 7ƒš–9L{À¸ÞÚI9@|,¹Ê€ƒ9A$ * ‰¤„@%?ébl>Kee9æ/sÂ3“¢=óC€€;¨ÃC€×;¾Ã./>ËÖ;y?ÙåÀù™,9h7Û9hÿHÝÎÞHõzÀÁbJÔÁd Ƴݹ¤˜9‰Fž7à"9Š<ú9ŒŠÔ9ðç¹ÿ–Y9‚ç. ;~Ç@At]D’ÀŠ>9î?깚?¥ùÄ>K9¯UÎÂ3à’=\ºùC€é:à¿sC€µ:àÉ–Ã °Ø>„Na:ï X?ÞB Àõ’î9/÷$90óHðËKI(äÁc¸Áex%Ó¹o{9P 39=A9Oä½µ,N]9Iȵ9®¹v9I¹ 3 ;˜K@A D‚¬X>°Ÿ? s?‰7C>KF¶9—$Â4ó==¡ÀC€ð:Ô× C€€:ÔÕÒÂè€>:•Ñ:ÍÇ+?ãž©ÀñŠÉ94e9ðŸI¥IFáÁeECÁg÷ý=8q*98зãÈô98þú67Q947š9”°Z94w·8:ˆQq@A0Dhh~=Ñêã?’®?Nœ>K°:9tÀøÂ4C*=iàC€€:¾^C€€:¾L9½¨û=ö$¾:¦Æ?éÈÀíw8ú›ž8ûdYI¬YIÍåÁfÊÁh‡e/y86ì9q÷¸çœ‘9“ù¸ƒ»u9Õj8šmR9ß> ;:̪@AA™šDNXy=¦´ ?sz?+Õs>KÅû9OýÂ42=ÌïC€€ :±¶ÎC€ÿ:±°qÂ™ÈÆ=© :Œ´+?îºÉÀéU8àmÍ8àÌI÷¯I/9ÁhS¨Áj8°mѸC9ZV·“Ø8ÿö²¸ŸªÀ8ø19{̈8÷}D :öLÀ@ATõÃD7z=kŽI?3>ýJ|>KÖ9.&@Â4)s<ØžžC€€5:¢é>C€ë:¢ßÂyBb=P¿Û:Ve?ô|}Àå-Õ8²“¯8²ì“I,) I=PÁiî”Ák™h½)¹‘­8ÒÀÒ·ÞÀà8Ôk®¸"û8Ê]9{`Ì8˯„J :oÇ©@AjAŠD"b¬= x>áä÷>Ÿ»A>Lõ8×E’Â47<†ÌxC€÷:^E_C€ü:^C ÂIÓ<íÅV:_f?úaºÀá18p¤‚8r ’IÔË>7›ì>LMÍ8¬:Â4ƒ§›>lS€>LD¼8ºÙfÂ4á1%¡=ú†>L¥8~û Â4ÿ<.C€Ù:/0 C€ü:/.•ÁÏÄt<ó¸9¦Gß@w«ÀÔƒÅ7ëï[7êì·IqÁtI…j¨ÁoÔXÁq‹Cµ±8—mx8€·„g8Q¶¸†Z82¸¸¬8uqm :R³@A«|³CÉ`E<%×o> “L=ã>L‰8Q‹ºÂ4:<èC€ü:oÃC€€:lBÁ§?#jD<úa¬@ µÀÀÐg-7æbù7ãÚãI„5{Iœ^ÁqbÓÁrñ’©5XO8è·Z9ÿ8ü¶©{u7ûNf¸±³7üvhx 9×lm@A¼¢ÅC³2x< ˜B>ÊH=ËY™>L…s8?SÂ4Š;»»ÄC€õ9ùèÒC€ô9ùèCÁ„Û,>Ô;C<ÌyZ@ ÙÀÌYQ7Ý 7ÙêJIIœµ%ÁrÂ~ÁtVÖ{Õ5àÁ7º]¶A*#7º©·R67ºHU6£M7ºnð„ :bX@AÏÙCŸâK:žu¤<¨§€LŸþ8òÂ3þÂ;³‹C€Ü:íC€ß:ž+ÁKe>”r”<º×@nrÀÈc6¥6†lI›ßI©*tÁt'Áu« -¶¢ p7²V¸7wé‘7²®ã6¾¥7®Db¸`67®ñú‘ 9–Å@Aä?ÕCä:„$Å<“GVL©7ÛiäÂ4±;ˆbeC€€9ÜaëC€ô9Üa]Á#Êæ>Jó§<žš@ê Àćs6uÝ6…œøI¨I¸[ÎÁuŒrÁw)‚ý ·Qâ/7‡”ü¶#ðœ7ˆ=6lm7ƒ’ƒ¸Ké‡7„êŸ 9Q:¸@AûC€‡;ÇW=:Òö=Å>L«7´ÖßÂ3ý³;`ðæC€ó9ÇÚ/C€ò9ÇÚßÁ Ú> Di<‰@{ ÀÀÍY70P˜7)±ÀI¶XÆIÇãdÁvø¶Áx‘- ¯ µÔš7`(k¶ͧ7a"ï6ˆ¯ê7[›]¸dO7\Üf¯ 9T¾@B BCgô¡;#Å=GÂñ= @±>Lª7‹ò^Â4;-?C€€9©í–C€û9©ì‰ÀÆcñ=¬­<^@";À½;~7F7@žÝIÅëÝIÙ"ôÁxe3ÁzB »¡·ªÄæ7*å-·3y7, ë¶™0ð7*n7¬7+±üÀ 7ù¤Û@BæbCRi°>L°Ã7_ï‡Â3þË; m½C€€9•ÎÝC€€ 9•Ï!ÀšYŒ=€ËpL¼7;ųÂ3ý—:é•5C€ü9Š!C€ý9Š!”Àpã°=ï°<(çö@"´£À¶©Í6œïø6¡|IéÎJqÁ{L¼­7(yÂ3ý]:¶ÖûC€þ9n«C€ÿ9n›À7ö<ÒØ7<´3@&¡ À³³6ïüÌ6ïEˆIý™âJ .Á|³ŸÁ~n$«Õ6ŒªÍ6¶P:¶J¨6·B=6žbm6³” ·m°6´  8\A@BJ-ÈC#o:€+Ù<¾>c<†…Ê>L¾è6ÞÕŸÂ4»:Š ñC€ö9F_C€ó9F^ÎÀBD<¬<Cµ@*¥¨À°ú6ÛE´6Ù<J aŠJz˜Á~8IÁ€f ]5Ÿ—ˆ6Š|`5­‹36‹»µêË6‰*û·~Ñ6‰Áý 7ÿ¡Ö@B^eCÊ$:~ç¤<ÆX£<Œ@>L¿Ý6¶ÑãÂ3ÿ:cQOC€€92øïC€ù92ù ¿Ù&¿>LÂã6˜ñÂ4°:>¹C€ü9$êC€û9$é忤×<[¢;ÈGM@2ùçÀ¬Eå3“nˆ³“nˆJ&.J9€GÁ€³2Á§Ä$Ë-ñ¶¿-ƒ6=šÐ´V¡ö6=ÝæµŠ Ë6=Sj¶÷Ù6=­KV 7¾f:@B†ŒÏC~>LÃá6pŸÂ3ÿÒ:¡›C€þ9]¬C€€9]¶¿w’”;¤®z;ªI@7J¾ÀªK¾2áϲáÏJ6Š„JM8{ÁƒÿÁ‚ˆg,_7©6²çs6ö%¶|àj6?ùµT¿g6ã¤4ܰ6={x 7pé@@B”JBÿâh:„n<í8Ù<§½È>LÄð6RÂ3ÿò:¾MC€€9òñC€€9òó¿;é;YêJ;•Ì@;¶9À¨¥7»}7 JI¬}Jc†ÜÁ‚a£ÁƒmÖ5·C)3“-(6Ð^4§+Û6CÀ4di66É4a3°6IF 7à–d@B¢Î8Bõ ô9Õ}LÆY6ôôÂ4e9Æ GC€ÿ8äqC€€8äP¿ |;˸;ƒR@@<ýÀ§•6<·6a³*J_ÏçJ~µÁƒI<Á„cA Qi³ ^5Æ/EµŠ¬5Æ{4†e$5ÂÆ¶Á¿â5Ã=éÇ 7@N°@B³ Bì˜>LÇ76 Î Â3ÿÒ9«–+C€ÿ8Ùj¼C€ü8Ùj˾уÃ:·õ‹;`Æ@@Dß²À¥Ä€3Ôxw³ÔxwJy‰-JŽetÁ„;'Á…aN¿biµµ¦5«°µÈµ—5¬µ®>5«Á5¯§b5«­jô 7cR@BÄþ¦BäÍÚ>LÈ5ÜzhÂ4"9‰BýC€€8¿QÊC€ÿ8¿QÁ¾š…œ:hÙ;@áå@IŸÀ¤¬º4yLÍ´yLÍJ‹ÏÃJ ¬_Á…8IÁ†m‰_Uw=²†ÿã5‰ecµm¥5‰Ë#´ z5ˆº6/6Y5‰:& 6׆º@Bر·BÞÙ>LÈ¿5½,UÂ49kŠäC€€8´’C€ÿ8´’ ¾c=h:†k;%Ø@N{¦À£Â4HR´HRJc¡J¶ !Á†?Á‡ƒ'sG)5Y…5kiíµ’‘L5l-´†iå5jÜN5»)ã5k¡‡] 6 l¶@Bî]BÚ¿>LÉË5š[Â49@ £C€ÿ8¢C€€8¢¾&Ř9½åë;¿ñ@SvJÀ¢ÿi³¯u3¯uJ²)&JÏdEÁ‡SCÁˆ¥‹k®M4ž‰»5@.²µ@(Ä5@Ⳙ5@‚4Âh35@á‘™ 6H”Ë@C™BÖ">LÊc5„B¢Â49$ªC€þ8˜ÀõC€ý8˜Àð½ó‡Ý9u¾[;)À@XªÀ¢_d4*F´*FJÊáwJíÅzÁˆt-Á‰Õ ¨¹Òý2û)û5$£OµŠHõ5% 1Œ[¯5$/ƒµŸ`!5$¼Ü 6Ø@C5ÂBÓt>LÊ£5^f7Â3ÿÿ9 hC€ÿ8AÐC€þ8Aн¯øy9Få:݇Þ@]È…À¡Ý4ÐÓ´ÐÓJèQKö€Á‰¡tÁ‹ÉÌ1ÿ5³…ǧ5 –µ_Z5 ½4„³»5 uµ¨ò5 †c% 68½‰@C¡‰BЊÆ9ÄgÒ<3<6–ß>LË5BPçÂ3ÿÿ8ñ¸àC€€8‡ºQC€ÿ8‡ºQ½}Tæ8ž~®: *@c!À¡sþ6Þ$6…L]K·=K¨NÁŠÚoÁŒV¼÷4Ñ´sÓø4ñÚ©µ9Ø]4òÄ´¤4ñ@µqå.4ò@ u 5Ç8à@C.~}BΔz9FIû<¾Ú;Ác*>LË5#³äÂ3ÿÿ8Ë¿C€þ8{ÍC€ý8{ν5ƒ8•G’:Ó@h›¸À¡ê6¶ç5úÂöK±ºK8´ˆÁŒ|Á¨À*Óuµ³%-4Ëøµ`:4Ì¡ã2š.á4˶05~94ÌsÆÎ 5·@í@C?ñŠBÍ m9ñÇ<;ðr<ä£>LË~5ÞyÂ3ÿÿ8²þC€ý8s4=C€þ8s4>½§8dB‰:ã @n7¢À Ý96256)“K3öKWø¶ÁnåÁ}i³Ä4V™4³\ˆ´ ðÝ4´³¶Ox4²âKµMˆð4³š&/ 4Ǭe@CS#KBËÔ®>LË”4ÿöÇÂ3ÿÿ8Ÿ6}C€þ8mù?C€ÿ8mù?¼µÂ[@sö-À ¨À³„33„3KROLK}¬XÁŽÉkÁjCµ¹#4Bje4Ÿ~,´š_ 4 ©³NO¤4Ÿuü2%„E4 þš 5.†„@Ch@lBÊäõ>LËÆ4ãŸÂ3ÿÿ8C˜C€ÿ8h=ŸC€þ8h=Ÿ¼~Ór7¸@i:¹º@yØ-À Ì4û´ûKvÊÙK•”hÁ-Á‘Ù—–)´”'£4y®´4úa³‰É4hú´c‚›4÷o 3·òJ@CzBÊ,:{<ÝR<œHT>LÌ4ÏœoÂ3ÿÿ8ãC€ÿ8i†“C€þ8i†”¼1bN7¥ð­:ï{ø@Þ~À `6¼+œ6®Ç¡K‘dmK°óPÁ‘™ÝÁ“N§€Ñ! ´ˆùP4O|´“ÉÚ4Ó'³€…u4:Ž´èÒ4ÊË‘ 4yNÖ@CŒƒ#BÉžm>LÌ4¼ÎÂ3ÿõ8pmC€þ8kÛ»C€ÿ8kÛ¿»õŒH7€N;ħ@ƒÀ G´²ÖZ’2ÖZ’K«éLÌ5¡cÂ3ÿõ9c C€þ8ðÉFC€ÿ8ðÉQ»¨=@†-ÌÀ 5³† 3† KÁºKÓ›(Á”ßÁ”Ü[rŸÑc²¡«s4óˆ ´»×Ú4´úÀ´}v]4΢aµ›?4ÉÔî,‘5eß\@photutils-0.7.2/photutils/isophote/tests/data/synth_lowsnr_table.fits0000644000214200020070000007020013547426552030521 0ustar lbradleySTSCI\science00000000000000SIMPLE = T / file does conform to FITS standard BITPIX = 16 / number of bits per data pixel NAXIS = 0 / number of data axes EXTEND = T / FITS dataset may contain extensions COMMENT FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H ORIGIN = 'STScI-STSDAS/TABLES' / Tables version 2002-02-22 FILENAME= 'synth_lowsnr_table.fits' / name of file NEXTEND = 1 / number of extensions in file END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 160 / width of table in bytes NAXIS2 = 55 PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 40 TTYPE1 = 'SMA ' / label for field 1 TFORM1 = '1E ' / data format of field: 4-byte REAL TUNIT1 = 'pixel ' / physical unit of field TTYPE2 = 'INTENS ' / label for field 2 TFORM2 = '1E ' / data format of field: 4-byte REAL TTYPE3 = 'INT_ERR ' / label for field 3 TFORM3 = '1E ' / data format of field: 4-byte REAL TTYPE4 = 'PIX_VAR ' / label for field 4 TFORM4 = '1E ' / data format of field: 4-byte REAL TTYPE5 = 'RMS ' / label for field 5 TFORM5 = '1E ' / data format of field: 4-byte REAL TTYPE6 = 'ELLIP ' / label for field 6 TFORM6 = '1E ' / data format of field: 4-byte REAL TTYPE7 = 'ELLIP_ERR' / label for field 7 TFORM7 = '1E ' / data format of field: 4-byte REAL TTYPE8 = 'PA ' / label for field 8 TFORM8 = '1E ' / data format of field: 4-byte REAL TUNIT8 = 'degrees ' / physical unit of field TTYPE9 = 'PA_ERR ' / label for field 9 TFORM9 = '1E ' / data format of field: 4-byte REAL TUNIT9 = 'degrees ' / physical unit of field TTYPE10 = 'X0 ' / label for field 10 TFORM10 = '1E ' / data format of field: 4-byte REAL TUNIT10 = 'pixel ' / physical unit of field TTYPE11 = 'X0_ERR ' / label for field 11 TFORM11 = '1E ' / data format of field: 4-byte REAL TUNIT11 = 'pixel ' / physical unit of field TTYPE12 = 'Y0 ' / label for field 12 TFORM12 = '1E ' / data format of field: 4-byte REAL TUNIT12 = 'pixel ' / physical unit of field TTYPE13 = 'Y0_ERR ' / label for field 13 TFORM13 = '1E ' / data format of field: 4-byte REAL TUNIT13 = 'pixel ' / physical unit of field TTYPE14 = 'GRAD ' / label for field 14 TFORM14 = '1E ' / data format of field: 4-byte REAL TTYPE15 = 'GRAD_ERR' / label for field 15 TFORM15 = '1E ' / data format of field: 4-byte REAL TTYPE16 = 'GRAD_R_ERR' / label for field 16 TFORM16 = '1E ' / data format of field: 4-byte REAL TTYPE17 = 'RSMA ' / label for field 17 TFORM17 = '1E ' / data format of field: 4-byte REAL TUNIT17 = 'pixel**1/4' / physical unit of field TTYPE18 = 'MAG ' / label for field 18 TFORM18 = '1E ' / data format of field: 4-byte REAL TTYPE19 = 'MAG_LERR' / label for field 19 TFORM19 = '1E ' / data format of field: 4-byte REAL TTYPE20 = 'MAG_UERR' / label for field 20 TFORM20 = '1E ' / data format of field: 4-byte REAL TTYPE21 = 'TFLUX_E ' / label for field 21 TFORM21 = '1E ' / data format of field: 4-byte REAL TTYPE22 = 'TFLUX_C ' / label for field 22 TFORM22 = '1E ' / data format of field: 4-byte REAL TTYPE23 = 'TMAG_E ' / label for field 23 TFORM23 = '1E ' / data format of field: 4-byte REAL TTYPE24 = 'TMAG_C ' / label for field 24 TFORM24 = '1E ' / data format of field: 4-byte REAL TTYPE25 = 'NPIX_E ' / label for field 25 TFORM25 = '1J ' / data format of field: 4-byte INTEGER TTYPE26 = 'NPIX_C ' / label for field 26 TFORM26 = '1J ' / data format of field: 4-byte INTEGER TTYPE27 = 'A3 ' / label for field 27 TFORM27 = '1E ' / data format of field: 4-byte REAL TTYPE28 = 'A3_ERR ' / label for field 28 TFORM28 = '1E ' / data format of field: 4-byte REAL TTYPE29 = 'B3 ' / label for field 29 TFORM29 = '1E ' / data format of field: 4-byte REAL TTYPE30 = 'B3_ERR ' / label for field 30 TFORM30 = '1E ' / data format of field: 4-byte REAL TTYPE31 = 'A4 ' / label for field 31 TFORM31 = '1E ' / data format of field: 4-byte REAL TTYPE32 = 'A4_ERR ' / label for field 32 TFORM32 = '1E ' / data format of field: 4-byte REAL TTYPE33 = 'B4 ' / label for field 33 TFORM33 = '1E ' / data format of field: 4-byte REAL TTYPE34 = 'B4_ERR ' / label for field 34 TFORM34 = '1E ' / data format of field: 4-byte REAL TTYPE35 = 'NDATA ' / label for field 35 TFORM35 = '1J ' / data format of field: 4-byte INTEGER TTYPE36 = 'NFLAG ' / label for field 36 TFORM36 = '1J ' / data format of field: 4-byte INTEGER TTYPE37 = 'NITER ' / label for field 37 TFORM37 = '1J ' / data format of field: 4-byte INTEGER TTYPE38 = 'STOP ' / label for field 38 TFORM38 = '1J ' / data format of field: 4-byte INTEGER TTYPE39 = 'A_BIG ' / label for field 39 TFORM39 = '1E ' / data format of field: 4-byte REAL TTYPE40 = 'SAREA ' / label for field 40 TFORM40 = '1E ' / data format of field: 4-byte REAL TUNIT40 = 'pixel ' / physical unit of field TDISP1 = 'F7.2 ' / display format TDISP2 = 'G10.3 ' / display format TDISP3 = 'G10.3 ' / display format TDISP4 = 'G9.3 ' / display format TDISP5 = 'G9.3 ' / display format TDISP6 = 'F6.4 ' / display format TDISP7 = 'F6.4 ' / display format TDISP8 = 'F6.2 ' / display format TDISP9 = 'F6.2 ' / display format TDISP10 = 'F7.2 ' / display format TDISP11 = 'F6.2 ' / display format TDISP12 = 'F7.2 ' / display format TDISP13 = 'F6.2 ' / display format TDISP14 = 'G8.3 ' / display format TDISP15 = 'G6.3 ' / display format TDISP16 = 'G6.3 ' / display format TDISP17 = 'F7.5 ' / display format TDISP18 = 'G7.3 ' / display format TDISP19 = 'G7.3 ' / display format TDISP20 = 'G7.3 ' / display format TDISP21 = 'G12.5 ' / display format TDISP22 = 'G12.5 ' / display format TDISP23 = 'G7.3 ' / display format TDISP24 = 'G7.3 ' / display format TDISP25 = 'I6 ' / display format TNULL25 = -2147483647 / undefined value for column TDISP26 = 'I6 ' / display format TNULL26 = -2147483647 / undefined value for column TDISP27 = 'G9.3 ' / display format TDISP28 = 'G7.3 ' / display format TDISP29 = 'G9.3 ' / display format TDISP30 = 'G7.3 ' / display format TDISP31 = 'G9.3 ' / display format TDISP32 = 'G7.3 ' / display format TDISP33 = 'G9.3 ' / display format TDISP34 = 'G7.3 ' / display format TDISP35 = 'I5 ' / display format TNULL35 = -2147483647 / undefined value for column TDISP36 = 'I5 ' / display format TNULL36 = -2147483647 / undefined value for column TDISP37 = 'I3 ' / display format TNULL37 = -2147483647 / undefined value for column TDISP38 = 'I2 ' / display format TNULL38 = -2147483647 / undefined value for column TDISP39 = 'G9.3 ' / display format TDISP40 = 'F5.1 ' / display format IMAGE = 'synth_lowsnr.fits' END FGŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿC€}àÿÿÿÿC€}rÿÿÿÿÃX‘ðÿÿÿÿÿÿÿÿÁ¼Cÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿ?__F„MA’§àBºó™—>2EžÂH¦ A¡ÔŽC€}à=nMC€}r=adÃñwlD Ε?“)[?Y~`Á…ø;/; ØQFGŸFGŸÁ¼CÁ¼C;†mh=èdž=c&>¾)>¤b¾£ +>»Êƒ >_¨@?µµFÌA³"ABäZB¡x>˜ð7>1G@ÂF A¡~HC€~=¡|C€}G=vÝ€Äÿ¨DŽ)?‘˜:?^¼üÁy‹;.,C;-¹kFGŸFGŸÁ¼CÁ¼C»žAÒ=ç`j=jÕ>d½î¡> l¿¾¤ $>» >òw@?!azFŸ¾AÙ`0C ŒæBÃð™>˜ x>0ëxÂEñëA¡òC€~!=Ž—C€}E=‡R©ÄwD)rç?÷å?dùÁj7;Tî;S€RFGŸFGŸÁ¼CÁ¼C»Ò‚‹=çC‡=LK9=ú2Y½î!>Î ¾£íU>¹þ =“Hi@?1„ÓF„B²VC'á„Bíkb>—†Ä>0?uÂE]UA¡ÉÓC€~3=›^C€}0=”IGÄ%¥ÝD:¥?9~?iœÁWƒ;Æ;€£ëFGŸFGŸÁ¼CÁ¼C¼ \—=æåå=4P=ó]¬½çù>¾Ü¾£Î¦>¸çn >ƒò@?CEOF KëB×:CKÁüC>–Ù>0¾ÂDù1A¢*rC€~M=ª[C€}2=¢ÍoÄ7]/DM÷¦?ÇT?o>6Á@¡;Œð;œà„FGŸFGŸÁ¼CÁ¼C¼"¶P=æîµ=ù(=í8ҽ䫽>‡*¾£ÐK>¸W¶ >¥éó@?VÌ>F jáBAs~CvšPC._ß>–Ù>/UÆÂD…9A¡‹ÿC€~m=º‘¦C€}=²‚ëÄJˆ’Db¢7?;.?uÁ$à;¿÷Ã;¾õ'FGŸFGŸÁ¼CÁ¼C¼@ž=æÏo=ج=è½ßó=þâA¾£°¿>·' ?Ÿu@?lGF VYBjöùC•ÂàCSË[>–8>/^ÂD?A¢HÌC€~„=ÌÒ`C€}=ÄEUÄ`[Dz8 ?Žð?zë’Áˆ;ëj;é˜ÜFGŸFGŸÁ¼CÁ¼C¼S¸E=æñ.<ßû =äàç½ÛÄ=ùÖí¾£Åú>·9û ?7/@?óãF ŒBŽ[LCµxEC€Q‹>–8>/rÂD$A¢’C€~ž=à÷ÍC€|þ=ׇÄw8DD‰ÏÈ?Ž´Å?€|CÁØù<æØ<¾eFGŸG6 Á¼CÁ:¼x¼`Tõ=æïy<Ǹ˜=âᱽܼ~=úz“¾£Œ>¶­- >aMY@?Žò­FtmB¬ÒÿCÜNúC›È>•‚Ê=÷ÒiÂD‹AfšC€~³=®ð~C€|í=§¤¶ÄÁ/D“Æ?C 8?ƒ•kÁ¥‘<0â 0á¡ ?€Î@?>%F1‡B²–šCã¨C ú1>y¹þ=ŒûCÂ;óAd¬C€€®=OZ´C€=KädÅ*<DqÀ >µÅæ?†Á²Áy<<¾r<:ÄQG6 G6 Á:¼xÁ:¼x¼k07=- )»j—=%4.¼ÿW&SòJ=3'-Â? @ßz C€€þ= ì(C€û= D<ÅIHD*Â>XVw?ŠÁ-¶<£¨<BîG6 G6 Á:¼xÁ:¼x»þ _<Ðßjº?`Z<È_ ¼™à<6i齌ÿ%<=? =ö´R@?¾C„EëóBXH÷C‰ÚîCBôé>Hø\<ø«²Â;ª @¢˜äC€=<ÔÀ\C€€ <Ò$-ÅM]ÐCî)Ý>q?U}Ág;ÿ²ë;ýà«GrÙ¢G’"Á?¾>ÁC »Æóœ<Ž¶Ò¸¶Gj<‰̼Y[[<³ ½7*6<*ÈŒ >Z@ÿ@?ÑJEEÜ0îB.[C^BÆC)‚>Eÿ<»˜RÂ9d(@y©C€€â<¯·vC€á<®<"ÅHt©Cª7½=Ùb%?½öÁë;ÜÉÇ;Ûe«GrÙ¢G’"Á?¾>ÁC »íæ?€“<†ÄÂ6ã€@7ͧC€<‰àC€€ <‰EúÅ=—C\?ž=•"ô?”;xÁƒ;°è ;°­G’"G’"ÁCÁC ¼óí<E¹€ò<=£»ø¼];±¬%¼¬·û;¯ññ =”¯@?ý=µE¹×A©„B×’B˜nr>7&<<-Ï×Â49?÷RC€,¹ö<§œÂ/ýv@<9ÜC€€<šUC€n<›-LÅ¥C¨=€½?›w¤Á ÿ;ª#;©TjG’"GºëËÁCÁG<´ ¼yUÖ;çyºò2–;âÇ/»$éÓ;•˜<…Ëe;—­œ @èh¨@@5úE˜—A:Y»Bv„ÀB.P >4-<2Â5Þ‰?¼†¿C€~Õ<0—(C€€º<0:’ÄÑäžB¦åT=KŽÁ?Ÿ7[ÁŒ ;)ñ;)7GâëÕHgpÁJ›ÁM ºÅrX;“%ºFà'; c» ¤½; ª„ìø›@@(ˆ-EŒ©‹ACgðB…É B=3x>=ÂV<R€Â-‚Õ?ÈéC€À<[îC€€û<][ŠÄ¬yKByñ=8Ü?£7Á";AP@;@ÏYGâëÕHgpÁJ›ÁM »aûÎ;¥-:Á¢;£Ú®»-q¥;¢½Éº—=;¡©N ?P1m@@9b˜EÊìA±XBa€aBt!>D—;ËéÂ4?ˆ´ÔC€€{<(iC€b<(4Ä®3ÿBô&<àÅá?¦üÆÁ¼k;%×È;%oJH ‘‡H»ÁNÁNáºÊ• ;oàÄ:¹ß[;eEª»iûH;D˻ݲý;:ÿ™ =ðÏÄ@@KìtEiöy@¬™4BrçA·|>B,>;„ÅÂ3‘ã?-.C€€ˆ;ëùŸC€;ì9ĉ3–B kz=£?«›Áî@:Í%l:ÌôØH ‘‡H9gÁNÁS¡%:=ÅK;9·;}ª;2ï9át—;á};q;¼~ >[Ìñ@@`PæET;^A•ŸBf0rB"Ä´>D½ß;ü_¬Â:¤«?¥xnC€äît;>fºH,ÊîH9gÁQé»ÁS¡!%;VîB;ÌÝ;›;‹Ô›9"y;‹2<;ZY¾;‰6 >t2@@v¿dEA†-@ºžûB¼ìAÚÕ!>FÄü;¢.zÂ7Ÿ¥?SC€€w<1^ÒC€‚‚<0‰±Ä?Ò AªQ<ãM»?³\pÁ ¢[;!,;æ.HEÑVHP=^ÁTC:ÁU')-;²ž;&*;w\-;#[ë;»Ör; ëYºÐÀÌ; LH ={iÄ@@‡¶E.¹ò@ª­íBÐ AÑ é>D"è;˜×ëÂ3( ?G@lC€€²<6-íC€‚‰<6cÄ(Ý…A…Ãb<ÊÉ?·¯§Á Ûð;Ýâ;¥HEÑVHnéÁTC:ÁW{Í)9;Í€z;m&;%yj;];ú¨:×{Á9ººÁ:Õ  <1”ü@@•HFE¼„@‘ÁBC A¼uô>C%X;•øfÂ6ì?Ht±C€€(JHc;©îŽÂ5ö?XTC€}ßO’i;–@Â4å?;ü}C€{<PZ¢;PpýÂ5¥?QEC€|´<8uC€~V<7ªÜÓz@õúÀ<ÈÄ%?ÊÁ©ª:Èi…:ÈÐHŸÇH´B×Á\…”Á^°u_yºÞ?:î˜;|f;:ìŸ[ºû:âλ-G:à!# <§*`@@ÚuDÍ-µ@WV´AíºF’;œÜÂ3ÈÔ?K¦C€€É<–µC€‚)<–À;Ãw@@Õåc<Ýw'?ÎíSÁ›ß;û;ºkH³e`HÆpÁ^›Á`[±w‘»=&ý;&Û²<!6;$Ú»{ú`;ý]»w‰;¥ ' =µ@@ðk´D¶‹n@6n\AÓy{A•ˆû>:‡a;“Ÿ£Â4/ì?J=:C€-<›B–C€ƒŠ<›9lÃKpŸ@È•j<ügá?ÓêµÀý(; ’; „HŃvHÛ®ÓÁ`FîÁb ±9 F;Ø<$ä;åÊ»˜; j³;ið1; !Þ+ =Ä0@A;=D¤ #@j‚[BkAÈöÚ>>Ú!;ʰËÂ9}V?‡Ž¥C€}<ë  C€~ˆ<éõiÃ+ÆZ@Ðw˜=W|?ÙåÀùqo;FöÙ;FbòHݼ¬Hõ-ÁbIgÁd8³Ý;‹,;n^;Ðê;lx¿:z6»;lå®:ë·K;km„/ >’<´@At]D‰ånA<&B¸ÄÅB‚¦²=ÚŸ;Ò};Âeù'?êBC€€= C€€<ùL&à È'AOâ0=Áô?ÞB ÀóiQ<î8<įHû´ÊIQÙÁd},Áe}|ç»Æ ò;b®ã;Ò";_»/dË;^&:öêÓ;] 62B~O@A Dtzv@øß½B¨÷jBnôe=ÚŸ;éãfÂeù'@,ÀC€€=‡¥C€€=¥HÂݺàA%åˆ=¿‰ƒ?ãž©Àï9Z< /< ê7I ËIk×Áf7ãÁgZ=»*°y;{BÉ;§ˆr;~'í;Æ‹¢;qD;Õ‘ë;s²;2B{—@A0De†@No‰B¬TAË/=>>¶E<B[Â.‘Ú?°ÃC€‰Û=KØÄC€vÙ=M\¥Â«ˆæ@“ÐÁ=\™á?éÈÀí;z)û;yN©I_IôÁfö»Áh‹5y;ž Õ;œ&<;œÔżû;‡€Ã<~4;‰´ > ?*$ú@AA™šDRÙm@Ih·B·¦AÎT>Z ;óÈÂ7¼x?ˆC€‚h=RbC€pÎ=Q& ‰@aô =4(Ü?îºÉÀê$;…;„€&I{I/NÃÁh)cÁj?eÑ»ÕM!;”K©;Àp¢;”œü8³';’•Ò;¡‰Ó;“3FC >’ÓÐ@ATõÃD8á’@7{jB ‚~AÅKì>O9;òQ]Â5]Ú?”àGC€=c«@C€zý=c2ˆÂ‡H@L>=A?ô|}Àå„&;Š/é;‰¨.I+ĸI=ÕwÁiäcÁk¡¹);ž×¿;”(º{';”Ñ’O9<+ÏzÂAÔF?Ô¯rC€À=³¾æC€‰=°*âÂFïQ@=Ô=tGò?úaºÀá û;µ™~;´«¡II?;<YÂ3±2?´Ÿ~C€‰=¡ØXC€‚ =¡êøÂÍ”@åx=i”ä@5®Àܱ;”çø;”GSINxGI`x]Ám³ÁnŠn•%;çU8;®Ú»@ëZ;®`×¼:¯_;©X7»šŒc;© iZ >OÓœ@A¹’D?ò@87ÆB!0ÍAãõ>>UPÌXG<8ÉÂCš ?Ú—'C€Ž²>õtC€y,=û·ÁÐá¤?éW_=Žý@w«ÀÔÓ;Ä.Š;Ã8IqCNI…«»ÁoËEÁq“º­±<4÷;ãÜ<&ã˜;ä÷V<`3;â(»a;âžl ?2þ@A«|³CÅ—‚@Û§BM·AÎç>.ò~<†.àÂCš @@= C€u%>HxTC€yµ>D ‹Á~ ø@,·x>. l@ µÀÀϾq;Ól;Ò/‡I…ÕÿIæöÁq™8Árú…­©<¶Þ<(q;WôE<_ˆ;˜Xw< K¼?4M<U¸z ?ÜfE@A¼¢ÅC±“@ 2ñBl’AÉk>2Ó)e±C€oO>)8ºÁŠ ã@á=òýM@ ÙÀËï;;Û*®;ÙÖPI‘,IœÿäÁsÍÁt_¥Õ<ÕÆ;ú‹:;ø:ª:c$;ö.þ¼|Ê;ù~™† ? ¹ø@AÏÙC¢ •@ 7,BfAÍ|>Zf<]*ÇÂ%pÝ@¥ÆC€_à>IlC€z>N2ÁZ’·?øZ—>p«@nrÀÈÚ;ì%Æ;ê™ I™ø6I©ŒÕÁtrÁuµ y-;ú´,< %=<‘þ< yš»»”p< ZÕ;”s< È2@Œz@Aä?ÕC¹n@AWB%ÓAêƒ~>Zf‚}C€z>…6Á0š*?Ê;ì>“ê@ê ÀįQ<ê<¼áI§5YI¸†8ÁuwGÁw-€ß ¼ 9¬<$¸»ïtÔ<$!g¼#PN<#ö;‚<"Êcž2AG@AûCà[?÷ÚúBAËÀu>ZçC€k·>ƒ»ÃC€Íx>†ÛÝÁØ?¹Õ_>¦í@{ ÀÁ*1<H<¸IµIÈ-Áv×ñÁx•j ¼Pâs<ïî:e¥ <”Z»¼¹A<(<_n<JÔ­2@Rp@B BCin“@ ‡8B+©“AòÄn>Zç<¿kHÂ%pÝ@a·C€Vº>èGC€µ¡>íèÑÀ¼Í?¨S>cˆ@";À½sì<(}<&‹ÕIĈ£IÙw„ÁxEéÁz ƒ¡:qÊB`)Á©%C€i<>½7¸À»ìÇ?Ý>Bîû@ßãÀ¹×/<@–<>IØ Iëç}Áyì-Á{qíU¼¶³L<;¨u69Ì=DÂTÆõ@ÐåC€Õ1?_NqC€„¼?Uó½À*t3?jâÆ>°b_@"´£À¶±u<"ßÊ@ŒS=CY'ÂD~A±C€ßZ?žiûChÄ?šÐ¿å*H?Eè…>Ý?@&¡ À²¼<0°Ë<.òºIÿ­/J ?2Á|×ÞÁ~sÙ Õ=!ûÈ= Ú3<Õ\(<ÿü¼˜G<öM3»«Ð¹<ïaÇ? kw@BJ-ÈC6r?¹²B þ¹AÅû›>r¸=×Â.b@Ôf’C€¬å?aâ¡C€R1?cG“À #ä>Ór>Cì¬@*¥¨À°(<"ÖE!€Ú<ÑèÂ'@Ú@¡œC€ÿù?F"C€Ÿ[?I ¸À ‘?â>}uò@.ÃÀ®ZŸ<*z<(Ý3Jh¼J(«kÁ€1Á€ÔBí%ù»·LìG­Ö=R1ÝÂ'@ÚAò0CfÖ?ß»”C¬-?ãÔ0¿’•‘>²J>›|&@2ùçÀ¬9’G­Ö=EÓÂRæ@û”dC€Ý?îB0C~µô?äU”¿v³>ŽÐ>”šÄ@7J¾Àªè<7’<5) J7`¢JM‘ÁŽ)Á‚Œ+,µ7©=b‚ß= Tö¼9›7<õ‹n=ab=q =±¦=HVy2?ß±@B”JBþñ,? ²B AÎW>(‘=<9‚ÂWTA ËSC~?ô29C€~?êHA¿`W9>kÿÿ>†¦ÿ@;¶9À¨nÔ<0º<.VåJNämJcõ$Á‚šqÁƒr 8-C)<Ò<æÀñ¼rŸ<âçµ=–0¾=üµ½7@,<ò ȧ ?^Ư@B¢Î8Bô’ò?ž}PBh8AÓK&>IÀT=Ø€ÕÂWTAˆoVC©¼@ž½RC‚Fí@–áȾ§×u>\¨­?(Gš@@<ýÀ¦ýŒ<5<36ÖJ`dËJ~8ÁƒOÁ„fíAOQi=»Ôj=¶0J¼2wÿ=‡IU>C¢{>«ê½z4 =œv@Ç?®[T@photutils-0.7.2/photutils/isophote/tests/data/synth_table.fits0000644000214200020070000007020013547426552027115 0ustar lbradleySTSCI\science00000000000000SIMPLE = T / file does conform to FITS standard BITPIX = 16 / number of bits per data pixel NAXIS = 0 / number of data axes EXTEND = T / FITS dataset may contain extensions COMMENT FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H ORIGIN = 'STScI-STSDAS/TABLES' / Tables version 2002-02-22 FILENAME= 'synth_table.fits' / name of file NEXTEND = 1 / number of extensions in file END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 160 / width of table in bytes NAXIS2 = 69 PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 40 TTYPE1 = 'SMA ' / label for field 1 TFORM1 = '1E ' / data format of field: 4-byte REAL TUNIT1 = 'pixel ' / physical unit of field TTYPE2 = 'INTENS ' / label for field 2 TFORM2 = '1E ' / data format of field: 4-byte REAL TTYPE3 = 'INT_ERR ' / label for field 3 TFORM3 = '1E ' / data format of field: 4-byte REAL TTYPE4 = 'PIX_VAR ' / label for field 4 TFORM4 = '1E ' / data format of field: 4-byte REAL TTYPE5 = 'RMS ' / label for field 5 TFORM5 = '1E ' / data format of field: 4-byte REAL TTYPE6 = 'ELLIP ' / label for field 6 TFORM6 = '1E ' / data format of field: 4-byte REAL TTYPE7 = 'ELLIP_ERR' / label for field 7 TFORM7 = '1E ' / data format of field: 4-byte REAL TTYPE8 = 'PA ' / label for field 8 TFORM8 = '1E ' / data format of field: 4-byte REAL TUNIT8 = 'degrees ' / physical unit of field TTYPE9 = 'PA_ERR ' / label for field 9 TFORM9 = '1E ' / data format of field: 4-byte REAL TUNIT9 = 'degrees ' / physical unit of field TTYPE10 = 'X0 ' / label for field 10 TFORM10 = '1E ' / data format of field: 4-byte REAL TUNIT10 = 'pixel ' / physical unit of field TTYPE11 = 'X0_ERR ' / label for field 11 TFORM11 = '1E ' / data format of field: 4-byte REAL TUNIT11 = 'pixel ' / physical unit of field TTYPE12 = 'Y0 ' / label for field 12 TFORM12 = '1E ' / data format of field: 4-byte REAL TUNIT12 = 'pixel ' / physical unit of field TTYPE13 = 'Y0_ERR ' / label for field 13 TFORM13 = '1E ' / data format of field: 4-byte REAL TUNIT13 = 'pixel ' / physical unit of field TTYPE14 = 'GRAD ' / label for field 14 TFORM14 = '1E ' / data format of field: 4-byte REAL TTYPE15 = 'GRAD_ERR' / label for field 15 TFORM15 = '1E ' / data format of field: 4-byte REAL TTYPE16 = 'GRAD_R_ERR' / label for field 16 TFORM16 = '1E ' / data format of field: 4-byte REAL TTYPE17 = 'RSMA ' / label for field 17 TFORM17 = '1E ' / data format of field: 4-byte REAL TUNIT17 = 'pixel**1/4' / physical unit of field TTYPE18 = 'MAG ' / label for field 18 TFORM18 = '1E ' / data format of field: 4-byte REAL TTYPE19 = 'MAG_LERR' / label for field 19 TFORM19 = '1E ' / data format of field: 4-byte REAL TTYPE20 = 'MAG_UERR' / label for field 20 TFORM20 = '1E ' / data format of field: 4-byte REAL TTYPE21 = 'TFLUX_E ' / label for field 21 TFORM21 = '1E ' / data format of field: 4-byte REAL TTYPE22 = 'TFLUX_C ' / label for field 22 TFORM22 = '1E ' / data format of field: 4-byte REAL TTYPE23 = 'TMAG_E ' / label for field 23 TFORM23 = '1E ' / data format of field: 4-byte REAL TTYPE24 = 'TMAG_C ' / label for field 24 TFORM24 = '1E ' / data format of field: 4-byte REAL TTYPE25 = 'NPIX_E ' / label for field 25 TFORM25 = '1J ' / data format of field: 4-byte INTEGER TTYPE26 = 'NPIX_C ' / label for field 26 TFORM26 = '1J ' / data format of field: 4-byte INTEGER TTYPE27 = 'A3 ' / label for field 27 TFORM27 = '1E ' / data format of field: 4-byte REAL TTYPE28 = 'A3_ERR ' / label for field 28 TFORM28 = '1E ' / data format of field: 4-byte REAL TTYPE29 = 'B3 ' / label for field 29 TFORM29 = '1E ' / data format of field: 4-byte REAL TTYPE30 = 'B3_ERR ' / label for field 30 TFORM30 = '1E ' / data format of field: 4-byte REAL TTYPE31 = 'A4 ' / label for field 31 TFORM31 = '1E ' / data format of field: 4-byte REAL TTYPE32 = 'A4_ERR ' / label for field 32 TFORM32 = '1E ' / data format of field: 4-byte REAL TTYPE33 = 'B4 ' / label for field 33 TFORM33 = '1E ' / data format of field: 4-byte REAL TTYPE34 = 'B4_ERR ' / label for field 34 TFORM34 = '1E ' / data format of field: 4-byte REAL TTYPE35 = 'NDATA ' / label for field 35 TFORM35 = '1J ' / data format of field: 4-byte INTEGER TTYPE36 = 'NFLAG ' / label for field 36 TFORM36 = '1J ' / data format of field: 4-byte INTEGER TTYPE37 = 'NITER ' / label for field 37 TFORM37 = '1J ' / data format of field: 4-byte INTEGER TTYPE38 = 'STOP ' / label for field 38 TFORM38 = '1J ' / data format of field: 4-byte INTEGER TTYPE39 = 'A_BIG ' / label for field 39 TFORM39 = '1E ' / data format of field: 4-byte REAL TTYPE40 = 'SAREA ' / label for field 40 TFORM40 = '1E ' / data format of field: 4-byte REAL TUNIT40 = 'pixel ' / physical unit of field TDISP1 = 'F7.2 ' / display format TDISP2 = 'G10.3 ' / display format TDISP3 = 'G10.3 ' / display format TDISP4 = 'G9.3 ' / display format TDISP5 = 'G9.3 ' / display format TDISP6 = 'F6.4 ' / display format TDISP7 = 'F6.4 ' / display format TDISP8 = 'F6.2 ' / display format TDISP9 = 'F6.2 ' / display format TDISP10 = 'F7.2 ' / display format TDISP11 = 'F6.2 ' / display format TDISP12 = 'F7.2 ' / display format TDISP13 = 'F6.2 ' / display format TDISP14 = 'G8.3 ' / display format TDISP15 = 'G6.3 ' / display format TDISP16 = 'G6.3 ' / display format TDISP17 = 'F7.5 ' / display format TDISP18 = 'G7.3 ' / display format TDISP19 = 'G7.3 ' / display format TDISP20 = 'G7.3 ' / display format TDISP21 = 'G12.5 ' / display format TDISP22 = 'G12.5 ' / display format TDISP23 = 'G7.3 ' / display format TDISP24 = 'G7.3 ' / display format TDISP25 = 'I6 ' / display format TNULL25 = -2147483647 / undefined value for column TDISP26 = 'I6 ' / display format TNULL26 = -2147483647 / undefined value for column TDISP27 = 'G9.3 ' / display format TDISP28 = 'G7.3 ' / display format TDISP29 = 'G9.3 ' / display format TDISP30 = 'G7.3 ' / display format TDISP31 = 'G9.3 ' / display format TDISP32 = 'G7.3 ' / display format TDISP33 = 'G9.3 ' / display format TDISP34 = 'G7.3 ' / display format TDISP35 = 'I5 ' / display format TNULL35 = -2147483647 / undefined value for column TDISP36 = 'I5 ' / display format TNULL36 = -2147483647 / undefined value for column TDISP37 = 'I3 ' / display format TNULL37 = -2147483647 / undefined value for column TDISP38 = 'I2 ' / display format TNULL38 = -2147483647 / undefined value for column TDISP39 = 'G9.3 ' / display format TDISP40 = 'F5.1 ' / display format IMAGE = 'synth.fits' END F’*ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿC€€ÿÿÿÿC€~zÿÿÿÿÃvôÿÿÿÿÿÿÿÿÁÅ+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿ?__F‘^A’˜ÃBºßùB„#ø>“ü7>)Ä›Â=ýœAžì›C€€=]?€C€~z=W‹(ĨPD R$?‰0?Y~`Á‡Œ;‹; ÉF’*F’*ÁÅ+ÁÅ+¼× h=䨻‹z«=ÔV½•O.=§—Ô¾ °>­#^ =s z@?µµF%²A±q™Bâ2BŸò>“ü7>)À Â=þ AžèUC€€=sYC€~T=mÄ ŠÍD$P?‰•å?^¼üÁz€;,w®;,üF’*F’*ÁÅ+ÁÅ+¼× a=ä+»Ë =ÔSP½•Uª=§•«¾ «5>­ =Šƒf@?!azF£gAÖ´qCÙBÁˆG>“ü7>)ÊBÂ>¥AžñæC€€=…àC€~*=‚jÄ­D'Zù?‰š[?dùÁj©;Q|;PäcF’*F’*ÁÅ+ÁÅ+¼ÖSû=ä5»ŽQ¾=Ô`,½•­ÿ=§÷¾ ²!>­" =ÊŽ@?1„ÓF¿BÙC%†&Bê>“ü7>)¿Â>üAžçkC€€=“9ùC€}ú=kÒÄ+D\D87?‰G?iœÁWk;~‘s;}­PF’*F’*ÁÅ+ÁÅ+¼Öžj=䑻޲:=ÔQ뽕›ï=§ÖÀ¾ ¨Z>­ Þ =ï+¿@?CEOF G B)#CHWcC ©©>“ü7>)ÉåÂ>ïAžñC€þ=¡ýµC€}É=ÍÄ6Á@;šî2;šDoF’*F’*ÁÅ+ÁÅ+¼ÕuS=ä »_=Ô`T½•Àã=¨ æ¾ ±/>­"4 > U@?VÌ>F `B>?CrY\C+]Þ>“ü7>)·œÂ=ùÞAžàpC€€=²ÁC€}‹=­„àÄO@ÇD^·z?‰Œç?uÁ#‹;¼³š;»»¬F’*F’*ÁÅ+ÁÅ+¼×^Î=äÖ»Œë¨=ÔF(½•)=§^ü¾ £ž>­© >6™‘@?lGF HÐBfbC’¢—CO_•>“ü7>)úÂ=ÿEAžëÈC€€=ÃùC€}N=¾ë5ÄcïDuQ?‰–6?zë’ÁØ;æG‰;äÑÆF’*F’*ÁÅ+ÁÅ+¼× )=äË»•|=ÔV`½•l =§­Ð¾ ­Í>­< >;t@?óãF öýB‹6ˆC±vdCzøF>“ü7>)Ç{Â>ÔAžïLC€þ=טÏC€} =ÒÐÄz¿ûD†Æá?‰™H?€|CÁÖƒ< Ë < ¬ôF’*G5ö´ÁÅ+Á:ºŸ¼Õø=äó»´=Ô\T½•¢½=§ê»¾ ¯ô>­u >jöq@?Žò­FXãB¨ÈªC×(tC˜#Ã>“IÕ=ë7ÁÂ=dÇA]3C€ö=£ïÄC€|¼=ŸûLÄÇÝzDŽY’?6T¯?ƒ•kÁ¢<,á-<+3”F’*G5ö´ÁÅ+Á:ºŸ¼—rb=ší×»]¢k=’¼Î½Eú)=N$¾^c >4€ ?Öý@?>%F±B¦Î{CÔ£2C–[>wcA=… Â7'eAþC€€Ô=BoC€~¶=A'KÅ(éÞD`|r>ª­?†Á²Áµ<0t}<.¼¬G5ö´G5ö´Á:ºŸÁ:ºŸ¼,‹Ô="šÀ»´µI=àß¼·o5SD©=(Î*Â;Ô @Ó+IC€€ÿ=ZC€Z=–ÅH£}Dèß>JÁÆ?ŠÁ,]<þ~<ÌÖG5ö´G5ö´Á:ºŸÁ:ºŸ»‡ T<ĨW»‹N<½|¼€:6<+¸<½….Œ<ƒTÏ > Ê1@?¾C„Eëü;BNxdCƒ™xC:>Géù<íº¿Â:d@œ,ÒC€:<ËôC€R<ÈõRÅMV$CãB> ªM?U}Á;ô";òYÓGrâ‡G’®Á?¾áÁC‘ »!º<ˆ¦ñ»ñ<ƒ[¼¼Rç\< ŵ½-wÓ<#} ={Ò@?ÑJEEÜ6MB*Á,CY«”Cê…>C$ô<·Ù~Â9ï+@vÓ3C€€è<¬ >C€(<ªu¹ÅHŲC¥Ëí=ÓgB?½öÁën;Ø-®;ÖßyGrâ‡G’®Á?¾áÁC‘ »o‘™<ýi<„^Â8òÇ@6‚ÿC€&<‡A`C€S<†C=Å=šùCPªÃ=ŒÞG?”;xÁ‚Ì;­Ì;¬¿‰G’®G’®ÁC‘ÁC‘ »€æ€<¡gºËj<Ò¼ ‘B;°u¼¬{®;­ðB =Âý@?ý=µE¹@A’ÍB»"·B„S*>5K<·IÂ7Î’?Ö¿•C€<<'ÓC€Ñ<&ªÅ2ÈC\Ë=O|¡?—Î…ÁæÚ;\Ìh;\^G’®G’®ÁC‘ÁC‘ »¾Í±;˜b:;—5T»½Yµ;‡>U»²1; =L\@@ HWE¦:àAªBØÈB™Iþ>*ý;áËG’®G»+¿ÁC‘ÁGB¥ ¼W<;Ûã3ºêÀe;Ù_qºmåj;†ð<‡¡^;ˆD @u`˜@@5úE˜úŸAþôBK·«B Ì>5 ;×[ñÂçXº@@(ˆ-EŒãÕA-5ÿBm-ÇB'µô>?ñ<Â1Ûê?®§˜C€€.<@¢wC€€üC®#@@9b˜EËì@ôR1B2úAû×#>Dœ;Ÿê(Â6X§?WXŽC€é<’ C€€f<:ÈÄ®¢·Aþm¼<º|?¦üÆÁ¼;êÒ;¯çH ª3H?QÁN5ÁNåv9ο™;=xº³;5 º©:K;ÿ»ÍÃ;3 >ÝH@@KìtEiÐà@}AÔ;¬A–K>AM|;Y øÂ3 Ÿ?ÌâC€ý;Á¬?C€ù;Áí‹Ä‰ A´8<¨K?«›Áëv:¨[ :¨ ½H ª3H9´ÁN5ÁSI%¸£âš:ùÛu¸¨¢:ù~Í:½Ñ::ç˜;T§:æì& =¿Ùç@@`PæEȘ@¡'mAþÎŽA´,ø>A˱;‹¡(Â8¶ˆ?97rC€€š< =GC€ù< gmÄWÿA’ <­M?¯#KÁ 3¨:Ó—):ÓcH,ëÃH9´ÁQíÁSI!%ºy]Í;#EÕ¹ƒ‰;!C`ºK(t;àÐ;Žãf;, >Lìß@@v¿dEAC@'¢jAŠþÁAD‘>F ;M Â4¼K>¿Ã)C€º; Å±C€ý; žiÄ=ÐøA»JF÷o:Ö­àÂ18>ŠkZC€€;€!ßC€€;€žLÄ&¼@Ùf²<'Í?·¯§Á â®:<°v:<ËHEãŽHn$ÁTDÔÁW|J)9:P(:}}¸ 6ù:{µ<:cÒ(:j*óº½F´:h–H =U@@•HFE`@ qAld_A''‰>G²Æ; ;ŽÂ3îl>°[@C€ü;¶ýC€€;¶¾Ä…ô@¢ßÝ<"6?¼‘Á Ð:gÅì:gf™HtDKH…”ÁWí4ÁYjŽ;E9ìŽ:£÷E¹À·Á:¥3Ÿ7"B°:”ªö;'‹:•І2?S€@@¤5çE–œ?Š™Aðé@º—Ä>I­7:”v™Â36 >=>ÀC€ò;W*ýC€>;WfÚÃä-@HIp:ŒTFÂ2ë¥>4\ôC€€S;_«zC€€I;_þÒö×Ü@ ¾;Å Ý?ÅLÁn'9þ]ª9þmêH“¸5H e˜Á[;Á\©9Sa9´ô:)f¹×*:'^ž¹Fß:3:²ÄŸ:‡u =8ä‡@@ƱÞDæ6ú?$}ñ@¬¡@sIq>JdÂ:R”fÂ49¡>ƒ C€€¢;8¯wC€º;8 šÃ›Vk? º;„q5?ÊÁ›ã9Æßu9ÆWêH¡çH´^Á\ºÁ^³ ayº2Ë;9÷ø˜8=>¥9ö¯è¸4ç`9澺‚# 9ää3# <=º@@ÚuDÍýÕ>ÈsÛ@]K+@zm>I¸: ÜfÂ3¾É=¶Ž?C€€+; yðC€½; …ŽÃ}æP?;R0;<Þá?ÎíSÁ­u9†þ‚9‡uÌH³ÌHÆgãÁ^žÁ`Zúw‘ºLô9¦¦’¹=à9£Â·š‹9¡Mc9öN9ž‹u' ;Ú71@@ðk´D¸{i>^£_?ÿf?´[‡>Jë©9©&JÂ4’µ=TK‚C€å:²ù¢C€ù:²Ó7ÃRnÛ?ÖÌ;¼Ü?ÓêµÀý†9'ž?9'ÌNHÂÖùHÛ´=Á` QÁb q‹±9‘à9KÝ`7M°9Lxý¸Þ¨¥9@x;¹Ê9A * ‰€A@$ÛŸ?é$ï>KeW9æ26Â3“¦=‘²C€€;ª[C€×;ÀÃ.B>Ì; W?ÙåÀù™,9hÞ9gàHÝÎÞHõzÀÁbJÔÁd Ƴݹ¤5B9‰G©7mZ9Š> 9Œwÿ9òa¹ÿ˜d9‚èŸ. ;r{ö@At]D’ÀŠ>;|+?ì°1?§]&>K 9¯PMÂ3à‘=\´C€é:à¸gC€µ:à‰à °Ï>ƒ»4:î~?ÞB Àõ’î91'91žØHðËKI(äÁc¸Áex%Ó¹gÿ9PÜ9='9OÞhµp¼9IÁÖ9®¾9I²/3 ;*I±@A D‚¬X>d–?Á¨Ý?ˆð#>KF·9—ÿÂ4ó==¡C€ð:ÔÖÖC€€:ÔÕžÂè€>:Z:Í…E?ãž©ÀñŠÉ9ÎH9ЉI¥IFáÁeECÁg÷ý=8q-98Ïô·ã¹Q98þÏ67£G947b9”±94w8:‰JØ@A0Dhh„=Ù&?—!?Uº–>K°M9tÄ/Â4C&=kßC€€:¾`œC€€:¾N¾Â½© =ûCã:©“š?éÈÀíw9°ó9ú°I¬YIÍåÁfÊÁh‡e/y86-Î9s§¸çÍ'9•¥¸„©9ÕÛ8š¿Š9L> ;;k@AA™šDNXy=¤ÂÍ?p-¤?)Ôê>KÅú9PˆÂ44=ÐdC€€ :±»C€ÿ:±µ#™ÈÓ=§õ„:‹ÌH?îºÉÀéU8ݼ8ÞwI÷¯I/9ÁhS¨Áj8°mѸ™@9]í·“§:8ÿýݸŸ‰Á8ø#¿9{ß›8÷ƒŽD :ðß^@ATõÃD7{=l·E?3ü_>þ‰Ô>KÖ|9.#WÂ4)r<Ø›C€€5:¢æ…C€ë:¢ÜUÂyBz=Ph}:V 7?ô|}Àå-Õ8³V8´I,) I=PÁiî”Ák™h½)¹i8Ò½a·Þf8Ôh7¸"9-8Éþ9{Tñ8ˬŸJ :psÔ@AjAŠD"b¬=”/>×ng>˜U9>Lô8×FcÂ47<†ÌýC€÷:^F8C€ü:^CåÂIÓ<éÂ:°?úaºÀá18e„)8fë„I²Ã²>|Ϥ>LMX8¬(ÇÂ4ˆ”é´>R˜;>LD¢8ºÜÞÂ4ßYëã>þ>L¤8~óXÂ4<(êC€Ù:/*ðC€ü:/(ãÁÏÄt<uE9¶ì@w«ÀÔƒÅ8ñÑ8pIqÁtI…j¨ÁoÔXÁq‹Cµ±8—KÓ8m·:58M ¸V:8/o¸¸”£8rÂm :LI}@A«|³CÉ`F;é§þ=â<–=Ÿù6>L‰8Q”QÂ49<ípC€ü:vBC€€:rÁÁ§ ?#i°<ú`¿@ µÀÀÐg-7¢7 êI„5{Iœ^ÁqbÓÁrñ’©4謰8î·Y˜8‘¶©£¿7ûYG¸±·Ì7üMx 9Úc@A¼¢ÅC³2w;æI?=éÛN=¥\”>L…m8@Â4†;»¼ÅC€õ9ùê"C€ô9ùé”Á„Û%>Ô:™<ÌxÁ@ ÙÀÌYP7°µè7´ |IIœµ%ÁrÂ~ÁtVÖ{Õ5Ç´7º‘=¶Cc7º©í·RãF7ºHÄ6£“ž7ºo[„ : -@AÏÙCŸâJ;ì*4=û[â=±¼Ó>L 8÷Â3þÀ;³‘kC€Ü:¢’C€ß:¢ÏÁKes>”tF<ºÙ2@nrÀÈc7Ë&O7Ï8I›ßI©*tÁt'Áu« -¶ l¯7²\~7ya7²´»6¾„Ì7®K©¸_éÒ7®ù'‘ 9“ÝÙ@Aä?ÕCä>L©~7ÛqžÂ4´;ˆg5C€€9Üi¯C€ô9ÜiÁ#Êæ>JóÉ<žš6@ê Àćs´,âu4,âuI¨I¸[ÎÁuŒrÁw)‚ý ·QZA7‡š¶$l'7ˆB>6i³¨7ƒ–¦¸Lî7„†&Ÿ 9M–@AûC€‡;f¤¹=†×=>²>L«7´ÛwÂ3ý³;`ö˜C€ó9ÇßCC€ò9ÇßòÁ Ú> E<‰Ò@{ ÀÀÍY7|U7ub I¶XÆIÇãdÁvø¶Áx‘- ¯ µÏBd7`.L¶ˆˆ7a(Ö6‰Ê7[¡ý¸Xé7\㯠9HÓÖ@B BCgô¡;LË´=zÒ=1[¹>Lª7‹ó¯Â4;-žÞC€€9©ï1C€û9©î$ÀÆcñ=¬è<^@";À½;~7xY'7rò¦IÅëÝIÙ"ôÁxe3ÁzB »¡·ªÄ¨7*è·2•7,ζ™!Ô7*qO7ÀT7+µ5À 8…±@BæbCRi°>L°Ç7_îÂ3þË; lÈC€€9•Í×C€€ 9•ÎÀšYŒ=€ËoL¼7;ÆÂÂ3ý—:é–ŠC€ü9Š!ÞC€ý9Š"\Àpã°=ïò<(è<@"´£À¶©Í6¼É[6ÁfËIéÎJqÁ{L¼­7)¬Â3ý]:¶Ø{C€þ9n C€ÿ9n À7ö<Ò׿<³ß@&¡ À³³6Ê&©6ÉoƒIý™âJ .Á|³ŸÁ~n$«Õ6Œ¤S6¶Q¿¶J¡m6·CÅ6žP6³•O·m»6´¡J 8Zé@BJ-ÈC#o:Lã~<˜¯L¾è6ÞÃEÂ4¸:Š•‡C€ö9FN®C€ó9FNxÀBD<¬9<Cg@*¥¨À°ú6®ðu6¬æþJ aŠJz˜Á~8IÁ€f ]5Ÿì‡6Špõ5­SÊ6ŠöEµçó*6‰ ·ir6‰· 8kT@B^eCÊ$:{ŸÚ<ÃË.<Šrq>L¿Ý6¶Ñ†Â3ÿ:cPÚC€€92ø“C€ù92ø±¿Ù&¿>LÂã6˜òüÂ4°:>»zC€ü9$ìC€û9$ëó¿¤×<\è;ÈII@2ùçÀ¬Eå3“nˆ³“nˆJ&.J9€GÁ€³2Á§Ä$Ë-ñ¶¿R6=m´[Ç56=à„µŠÂ³6=Uö^6=¯§V 7»š@B†ŒÏC~>LÃá6pEæÂ3ÿÑ:»UC€þ9v%C€€9v/¿w’”;¤®ß;ªIø@7J¾ÀªK¾2áϲáÏJ6Š„JM8{ÁƒÿÁ‚ˆg,_7©6²ã6 ¶}Ñ6YµW¼6ül4Ý¢;6VQx 7r×@B”JBÿâh:„oÍ<íä*<¨6ë>LÄð6RÂ3ÿò:»ÏC€€9ðTC€€9ðW¿;é;Yì4;•@;¶9À¨¥7»}7 JI¬}Jc†ÜÁ‚a£ÁƒmÖ5·C)3•dX6Íß4§)C6A?4d¦P6Ɖ4YY˜6FÌ 7Þ}@B¢Î8Bõ ô9Ï‘LÆY6õAÂ4e9Æ ¦C€ÿ8äÞC€€8伿 |;Ä‚;‚ýÀ@@<ýÀ§•6z³46])©J_ÏçJ~µÁƒI<Á„cA Qi³w15Æ/¿µ‰Ä…5Æö4„65ÂÇ ¶Á´D5Ã>ÝÇ 7@y4@B³ Bì˜>LÇ76 ÏÔÂ3ÿÑ9«˜gC€ÿ8ÙmC€ü8ÙmŸ¾ÑƒÃ:·øí;`Êb@Dß²À¥Ä€3Ôxw³ÔxwJy‰-JŽetÁ„;'Á…aN¿biµRr5«ƒŠµÉj 5¬òµ®éè5« 85­Ôë5«¯ßô 7eM¿@BÄþ¦BäÍÚ>LÈ5Üw+Â4"9‰@ûC€€8¿NûC€ÿ8¿Nñ¾š…œ:hÃe;@Ïç@IŸÀ¤¬º4yLÍ´yLÍJ‹ÏÃJ ¬_Á…8IÁ†m‰_Uw=².Ž5‰bëµæ5‰È«´þ'5ˆ‡h60Ô÷5ˆúè& 6Ø| @Bر·BÞÙ>LÈ¿5½9ßÂ49k›¿C€€8´žûC€ÿ8´žø¾c=h:XL;$Ýã@N{¦À£Â4HR´HRJc¡J¶ !Á†?Á‡ƒ'sG)5Zl5kz>µ’ïº5l(‰´…ƒ5jîÆ5¹žÀ5k´] 6¦$À@Bî]BÚ¿>LÉÊ5šQ6Â49?þbC€ÿ8¡ù¿C€€8¡ù½¾&Ř9½ý¸;Ò5@SvJÀ¢ÿi³¯u3¯uJ²)&JÏdEÁ‡SCÁˆ¥‹k®M4¯d;5@!ݵ=âÛ5@Õ ³ùëè5@ ¦4Æ€œ5@Ó¨™ 6N.@C™BÖ":.ºú<Ðì <“»W>LÊa5„Â49$_ØC€þ8˜|C€ý8˜|½ó‡9zä;Þy@XªÀ¢_d6éÅQ6ÙïmJÊáwJíÅzÁˆt-Á‰Õ ¨¹Òý3Ah5$YÒµ‰dÚ5$ÖR09 5#ç_µž?^5$s§Ü 60Ø@C5ÂBÓt>LÊ£5^.­Â49 EüC€þ8‹C€ÿ8‰½¯øy9"³:ÝS6@]È…À¡Ý4ÐÓ´ÐÓJèQKö€Á‰¡tÁ‹ÉÌ1ÿ5³¼uU5 tdµK5 åé4ŒQ5 å{µ¨©ð5 dI% 6>ÙP@C¡‰BЊÆ9Ñ}O<‰¶ LË5B™æÂ48ò¯C€€8‡íNC€ÿ8‡íM½}Tæ8Ÿ¼þ:¡k¹@c!À¡sþ6‡îI6KK·=K¨NÁŠÚoÁŒV¼÷4Ñ´q}°4ò>4µ0BÜ4ó'ù´â™4ñ©¤µmð4òªžu 5Íš[@C.~}BΔz9qçÒ<&Ó;ëìý>LË5#ûÂ3ÿû8̲C€ÿ8| 7C€þ8| :½5ƒ8–n:Ô@±@h›¸À¡ê6*ŸÂ6JNK±ºK8´ˆÁŒ|Á¨À*Óuµ1‰nÊ4ÌNݵx 4Ìù2”ô^4Ìí5à¦4ÌÔ×Î 5«©§@C?ñŠBÍ m9-CI;ú—@;±1É>LË}5ÖÂ48²ózC€ý8s%ñC€þ8s%ñ½§8^#:Ý`!@n7¢À Ý95÷5åœuK3öKWø¶ÁnåÁ}i³Ä43rÑ4³Où´5z4³ön³—ˆ24²ã}µ@ï4³›L/ 4ÕP~@CS#KBËÔ®>LË’5ÈWÂ48 5tC€ÿ8ovUC€€8ovT¼µÂ[@sö-À ¨À³„33„3KROLK}¬XÁŽÉkÁjCµ¹#4c¾ó4 u‚´´ÊÐ4¡ é³Zå”4 lø³ª4¡ÿš 5eˆ@Ch@lBÊäõ>LËÆ4ä*¹Â3ÿý8ñ×C€ÿ8i\C€þ8i\¼~Ór7¯ÿ×:°Ïl@yØ-À Ì4û´ûKvÊÙK•”hÁ-Á‘Ù—–)´“E94Žà´ÁÓM4Ž¡/´³,4Ž ­´h0A4Ž›Ä 4&ll@CzBÊ,:]à<ãë< Ý×>LÌ4ОoÂ3ÿý8ºNC€ÿ8j¨ÉC€þ8j¨Ê¼1bN7ªÎµ:ö‚=@Þ~À `6Á«l6´GnK‘dmK°óPÁ‘™ÝÁ“N§€Ñ! ´š14ëj´›n04‚o±²dú~4×X´ 14‚hG‘ 4i(ÿ@CŒƒ#BÉžm>LÌ4¼ÊâÂ3ÿú8qkC€ÿ8lÙ@C€þ8lÙB»õŒH7vý;ÀD@ƒÀ G´²ÖZ’2ÖZ’K«éLÌ5üÂ3ÿú9ÄVC€ÿ8ñk„C€þ8ñk‹»¨=@†-ÌÀ 5³† 3† KÁºKÓ›(Á”ßÁ”Ü[rŸÑc³Ì#4ôµ´á:ª4µgO´lc&4Ï,³µ˜c4Ê\,‘5„›@photutils-0.7.2/photutils/isophote/tests/data/synth_table_mean.fits0000644000214200020070000023540013547426552030122 0ustar lbradleySTSCI\science00000000000000SIMPLE = T / file does conform to FITS standard BITPIX = 16 / number of bits per data pixel NAXIS = 0 / number of data axes EXTEND = T / There may be standard extensions COMMENT FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H ORIGIN = 'STScI-STSDAS/TABLES' / Tables version 2002-02-22 FILENAME= 'synth_table.fits' / name of file NEXTEND = 3 / number of extensions in file END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 160 / width of table in bytes NAXIS2 = 69 PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 40 TTYPE1 = 'SMA ' / label for field 1 TFORM1 = '1E ' / data format of field: 4-byte REAL TUNIT1 = 'pixel ' / physical unit of field TTYPE2 = 'INTENS ' / label for field 2 TFORM2 = '1E ' / data format of field: 4-byte REAL TTYPE3 = 'INT_ERR ' / label for field 3 TFORM3 = '1E ' / data format of field: 4-byte REAL TTYPE4 = 'PIX_VAR ' / label for field 4 TFORM4 = '1E ' / data format of field: 4-byte REAL TTYPE5 = 'RMS ' / label for field 5 TFORM5 = '1E ' / data format of field: 4-byte REAL TTYPE6 = 'ELLIP ' / label for field 6 TFORM6 = '1E ' / data format of field: 4-byte REAL TTYPE7 = 'ELLIP_ERR' / label for field 7 TFORM7 = '1E ' / data format of field: 4-byte REAL TTYPE8 = 'PA ' / label for field 8 TFORM8 = '1E ' / data format of field: 4-byte REAL TUNIT8 = 'degrees ' / physical unit of field TTYPE9 = 'PA_ERR ' / label for field 9 TFORM9 = '1E ' / data format of field: 4-byte REAL TUNIT9 = 'degrees ' / physical unit of field TTYPE10 = 'X0 ' / label for field 10 TFORM10 = '1E ' / data format of field: 4-byte REAL TUNIT10 = 'pixel ' / physical unit of field TTYPE11 = 'X0_ERR ' / label for field 11 TFORM11 = '1E ' / data format of field: 4-byte REAL TUNIT11 = 'pixel ' / physical unit of field TTYPE12 = 'Y0 ' / label for field 12 TFORM12 = '1E ' / data format of field: 4-byte REAL TUNIT12 = 'pixel ' / physical unit of field TTYPE13 = 'Y0_ERR ' / label for field 13 TFORM13 = '1E ' / data format of field: 4-byte REAL TUNIT13 = 'pixel ' / physical unit of field TTYPE14 = 'GRAD ' / label for field 14 TFORM14 = '1E ' / data format of field: 4-byte REAL TTYPE15 = 'GRAD_ERR' / label for field 15 TFORM15 = '1E ' / data format of field: 4-byte REAL TTYPE16 = 'GRAD_R_ERR' / label for field 16 TFORM16 = '1E ' / data format of field: 4-byte REAL TTYPE17 = 'RSMA ' / label for field 17 TFORM17 = '1E ' / data format of field: 4-byte REAL TUNIT17 = 'pixel**1/4' / physical unit of field TTYPE18 = 'MAG ' / label for field 18 TFORM18 = '1E ' / data format of field: 4-byte REAL TTYPE19 = 'MAG_LERR' / label for field 19 TFORM19 = '1E ' / data format of field: 4-byte REAL TTYPE20 = 'MAG_UERR' / label for field 20 TFORM20 = '1E ' / data format of field: 4-byte REAL TTYPE21 = 'TFLUX_E ' / label for field 21 TFORM21 = '1E ' / data format of field: 4-byte REAL TTYPE22 = 'TFLUX_C ' / label for field 22 TFORM22 = '1E ' / data format of field: 4-byte REAL TTYPE23 = 'TMAG_E ' / label for field 23 TFORM23 = '1E ' / data format of field: 4-byte REAL TTYPE24 = 'TMAG_C ' / label for field 24 TFORM24 = '1E ' / data format of field: 4-byte REAL TTYPE25 = 'NPIX_E ' / label for field 25 TFORM25 = '1J ' / data format of field: 4-byte INTEGER TTYPE26 = 'NPIX_C ' / label for field 26 TFORM26 = '1J ' / data format of field: 4-byte INTEGER TTYPE27 = 'A3 ' / label for field 27 TFORM27 = '1E ' / data format of field: 4-byte REAL TTYPE28 = 'A3_ERR ' / label for field 28 TFORM28 = '1E ' / data format of field: 4-byte REAL TTYPE29 = 'B3 ' / label for field 29 TFORM29 = '1E ' / data format of field: 4-byte REAL TTYPE30 = 'B3_ERR ' / label for field 30 TFORM30 = '1E ' / data format of field: 4-byte REAL TTYPE31 = 'A4 ' / label for field 31 TFORM31 = '1E ' / data format of field: 4-byte REAL TTYPE32 = 'A4_ERR ' / label for field 32 TFORM32 = '1E ' / data format of field: 4-byte REAL TTYPE33 = 'B4 ' / label for field 33 TFORM33 = '1E ' / data format of field: 4-byte REAL TTYPE34 = 'B4_ERR ' / label for field 34 TFORM34 = '1E ' / data format of field: 4-byte REAL TTYPE35 = 'NDATA ' / label for field 35 TFORM35 = '1J ' / data format of field: 4-byte INTEGER TTYPE36 = 'NFLAG ' / label for field 36 TFORM36 = '1J ' / data format of field: 4-byte INTEGER TTYPE37 = 'NITER ' / label for field 37 TFORM37 = '1J ' / data format of field: 4-byte INTEGER TTYPE38 = 'STOP ' / label for field 38 TFORM38 = '1J ' / data format of field: 4-byte INTEGER TTYPE39 = 'A_BIG ' / label for field 39 TFORM39 = '1E ' / data format of field: 4-byte REAL TTYPE40 = 'SAREA ' / label for field 40 TFORM40 = '1E ' / data format of field: 4-byte REAL TUNIT40 = 'pixel ' / physical unit of field TDISP1 = 'F7.2 ' / display format TDISP2 = 'G10.3 ' / display format TDISP3 = 'G10.3 ' / display format TDISP4 = 'G9.3 ' / display format TDISP5 = 'G9.3 ' / display format TDISP6 = 'F6.4 ' / display format TDISP7 = 'F6.4 ' / display format TDISP8 = 'F6.2 ' / display format TDISP9 = 'F6.2 ' / display format TDISP10 = 'F7.2 ' / display format TDISP11 = 'F6.2 ' / display format TDISP12 = 'F7.2 ' / display format TDISP13 = 'F6.2 ' / display format TDISP14 = 'G8.3 ' / display format TDISP15 = 'G6.3 ' / display format TDISP16 = 'G6.3 ' / display format TDISP17 = 'F7.5 ' / display format TDISP18 = 'G7.3 ' / display format TDISP19 = 'G7.3 ' / display format TDISP20 = 'G7.3 ' / display format TDISP21 = 'G12.5 ' / display format TDISP22 = 'G12.5 ' / display format TDISP23 = 'G7.3 ' / display format TDISP24 = 'G7.3 ' / display format TDISP25 = 'I6 ' / display format TNULL25 = -2147483647 / undefined value for column TDISP26 = 'I6 ' / display format TNULL26 = -2147483647 / undefined value for column TDISP27 = 'G9.3 ' / display format TDISP28 = 'G7.3 ' / display format TDISP29 = 'G9.3 ' / display format TDISP30 = 'G7.3 ' / display format TDISP31 = 'G9.3 ' / display format TDISP32 = 'G7.3 ' / display format TDISP33 = 'G9.3 ' / display format TDISP34 = 'G7.3 ' / display format TDISP35 = 'I5 ' / display format TNULL35 = -2147483647 / undefined value for column TDISP36 = 'I5 ' / display format TNULL36 = -2147483647 / undefined value for column TDISP37 = 'I3 ' / display format TNULL37 = -2147483647 / undefined value for column TDISP38 = 'I2 ' / display format TNULL38 = -2147483647 / undefined value for column TDISP39 = 'G9.3 ' / display format TDISP40 = 'F5.1 ' / display format IMAGE = 'synth.fits' END F’*ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿC€€ÿÿÿÿC€~zÿÿÿÿÃvôÿÿÿÿÿÿÿÿÁÅ+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿ?__F‘^A’˜ÃBºßùB„#ø>“ü7>)Ä›Â=ýœAžì›C€€=]?€C€~z=W‹(ĨPD R$?‰0?Y~`Á‡Œ;‹; ÉF’*F’*ÁÅ+ÁÅ+¼× h=䨻‹z«=ÔV½•O.=§—Ô¾ °>­#^ =s z@?µµF%²A±q™Bâ2BŸò>“ü7>)À Â=þ AžèUC€€=sYC€~T=mÄ ŠÍD$P?‰•å?^¼üÁz€;,w®;,üF’*F’*ÁÅ+ÁÅ+¼× a=ä+»Ë =ÔSP½•Uª=§•«¾ «5>­ =Šƒf@?!azF£gAÖ´qCÙBÁˆG>“ü7>)ÊBÂ>¥AžñæC€€=…àC€~*=‚jÄ­D'Zù?‰š[?dùÁj©;Q|;PäcF’*F’*ÁÅ+ÁÅ+¼ÖSû=ä5»ŽQ¾=Ô`,½•­ÿ=§÷¾ ²!>­" =ÊŽ@?1„ÓF¿BÙC%†&Bê>“ü7>)¿Â>üAžçkC€€=“9ùC€}ú=kÒÄ+D\D87?‰G?iœÁWk;~‘s;}­PF’*F’*ÁÅ+ÁÅ+¼Öžj=䑻޲:=ÔQ뽕›ï=§ÖÀ¾ ¨Z>­ Þ =ï+¿@?CEOF G B)#CHWcC ©©>“ü7>)ÉåÂ>ïAžñC€þ=¡ýµC€}É=ÍÄ6Á@;šî2;šDoF’*F’*ÁÅ+ÁÅ+¼ÕuS=ä »_=Ô`T½•Àã=¨ æ¾ ±/>­"4 > U@?VÌ>F `B>?CrY\C+]Þ>“ü7>)·œÂ=ùÞAžàpC€€=²ÁC€}‹=­„àÄO@ÇD^·z?‰Œç?uÁ#‹;¼³š;»»¬F’*F’*ÁÅ+ÁÅ+¼×^Î=äÖ»Œë¨=ÔF(½•)=§^ü¾ £ž>­© >6™‘@?lGF HÐBfbC’¢—CO_•>“ü7>)úÂ=ÿEAžëÈC€€=ÃùC€}N=¾ë5ÄcïDuQ?‰–6?zë’ÁØ;æG‰;äÑÆF’*F’*ÁÅ+ÁÅ+¼× )=äË»•|=ÔV`½•l =§­Ð¾ ­Í>­< >;t@?óãF öýB‹6ˆC±vdCzøF>“ü7>)Ç{Â>ÔAžïLC€þ=טÏC€} =ÒÐÄz¿ûD†Æá?‰™H?€|CÁÖƒ< Ë < ¬ôF’*G5ö´ÁÅ+Á:ºŸ¼Õø=äó»´=Ô\T½•¢½=§ê»¾ ¯ô>­u >jöq@?Žò­FXãB¨ÈªC×(tC˜#Ã>“IÕ=ë7ÁÂ=dÇA]3C€ö=£ïÄC€|¼=ŸûLÄÇÝzDŽY’?6T¯?ƒ•kÁ¢<,á-<+3”F’*G5ö´ÁÅ+Á:ºŸ¼—rb=ší×»]¢k=’¼Î½Eú)=N$¾^c >4€ ?Öý@?>%F±B¦Î{CÔ£2C–[>wcA=… Â7'eAþC€€Ô=BoC€~¶=A'KÅ(éÞD`|r>ª­?†Á²Áµ<0t}<.¼¬G5ö´G5ö´Á:ºŸÁ:ºŸ¼,‹Ô="šÀ»´µI=àß¼·o5SD©=(Î*Â;Ô @Ó+IC€€ÿ=ZC€Z=–ÅH£}Dèß>JÁÆ?ŠÁ,]<þ~<ÌÖG5ö´G5ö´Á:ºŸÁ:ºŸ»‡ T<ĨW»‹N<½|¼€:6<+¸<½….Œ<ƒTÏ > Ê1@?¾C„Eëü;BNxdCƒ™xC:>Géù<íº¿Â:d@œ,ÒC€:<ËôC€R<ÈõRÅMV$CãB> ªM?U}Á;ô";òYÓGrâ‡G’®Á?¾áÁC‘ »!º<ˆ¦ñ»ñ<ƒ[¼¼Rç\< ŵ½-wÓ<#} ={Ò@?ÑJEEÜ6MB*Á,CY«”Cê…>C$ô<·Ù~Â9ï+@vÓ3C€€è<¬ >C€(<ªu¹ÅHŲC¥Ëí=ÓgB?½öÁën;Ø-®;ÖßyGrâ‡G’®Á?¾áÁC‘ »o‘™<ýi<„^Â8òÇ@6‚ÿC€&<‡A`C€S<†C=Å=šùCPªÃ=ŒÞG?”;xÁ‚Ì;­Ì;¬¿‰G’®G’®ÁC‘ÁC‘ »€æ€<¡gºËj<Ò¼ ‘B;°u¼¬{®;­ðB =Âý@?ý=µE¹@A’ÍB»"·B„S*>5K<·IÂ7Î’?Ö¿•C€<<'ÓC€Ñ<&ªÅ2ÈC\Ë=O|¡?—Î…ÁæÚ;\Ìh;\^G’®G’®ÁC‘ÁC‘ »¾Í±;˜b:;—5T»½Yµ;‡>U»²1; =L\@@ HWE¦:àAªBØÈB™Iþ>*ý;áËG’®G»+¿ÁC‘ÁGB¥ ¼W<;Ûã3ºêÀe;Ù_qºmåj;†ð<‡¡^;ˆD @u`˜@@5úE˜úŸAþôBK·«B Ì>5 ;×[ñÂçXº@@(ˆ-EŒãÕA-5ÿBm-ÇB'µô>?ñ<Â1Ûê?®§˜C€€.<@¢wC€€üC®#@@9b˜EËì@ôR1B2úAû×#>Dœ;Ÿê(Â6X§?WXŽC€é<’ C€€f<:ÈÄ®¢·Aþm¼<º|?¦üÆÁ¼;êÒ;¯çH ª3H?QÁN5ÁNåv9ο™;=xº³;5 º©:K;ÿ»ÍÃ;3 >ÝH@@KìtEiÐà@}AÔ;¬A–K>AM|;Y øÂ3 Ÿ?ÌâC€ý;Á¬?C€ù;Áí‹Ä‰ A´8<¨K?«›Áëv:¨[ :¨ ½H ª3H9´ÁN5ÁSI%¸£âš:ùÛu¸¨¢:ù~Í:½Ñ::ç˜;T§:æì& =¿Ùç@@`PæEȘ@¡'mAþÎŽA´,ø>A˱;‹¡(Â8¶ˆ?97rC€€š< =GC€ù< gmÄWÿA’ <­M?¯#KÁ 3¨:Ó—):ÓcH,ëÃH9´ÁQíÁSI!%ºy]Í;#EÕ¹ƒ‰;!C`ºK(t;àÐ;Žãf;, >Lìß@@v¿dEAC@'¢jAŠþÁAD‘>F ;M Â4¼K>¿Ã)C€º; Å±C€ý; žiÄ=ÐøA»JF÷o:Ö­àÂ18>ŠkZC€€;€!ßC€€;€žLÄ&¼@Ùf²<'Í?·¯§Á â®:<°v:<ËHEãŽHn$ÁTDÔÁW|J)9:P(:}}¸ 6ù:{µ<:cÒ(:j*óº½F´:h–H =U@@•HFE`@ qAld_A''‰>G²Æ; ;ŽÂ3îl>°[@C€ü;¶ýC€€;¶¾Ä…ô@¢ßÝ<"6?¼‘Á Ð:gÅì:gf™HtDKH…”ÁWí4ÁYjŽ;E9ìŽ:£÷E¹À·Á:¥3Ÿ7"B°:”ªö;'‹:•І2?S€@@¤5çE–œ?Š™Aðé@º—Ä>I­7:”v™Â36 >=>ÀC€ò;W*ýC€>;WfÚÃä-@HIp:ŒTFÂ2ë¥>4\ôC€€S;_«zC€€I;_þÒö×Ü@ ¾;Å Ý?ÅLÁn'9þ]ª9þmêH“¸5H e˜Á[;Á\©9Sa9´ô:)f¹×*:'^ž¹Fß:3:²ÄŸ:‡u =8ä‡@@ƱÞDæ6ú?$}ñ@¬¡@sIq>JdÂ:R”fÂ49¡>ƒ C€€¢;8¯wC€º;8 šÃ›Vk? º;„q5?ÊÁ›ã9Æßu9ÆWêH¡çH´^Á\ºÁ^³ ayº2Ë;9÷ø˜8=>¥9ö¯è¸4ç`9澺‚# 9ää3# <=º@@ÚuDÍýÕ>ÈsÛ@]K+@zm>I¸: ÜfÂ3¾É=¶Ž?C€€+; yðC€½; …ŽÃ}æP?;R0;<Þá?ÎíSÁ­u9†þ‚9‡uÌH³ÌHÆgãÁ^žÁ`Zúw‘ºLô9¦¦’¹=à9£Â·š‹9¡Mc9öN9ž‹u' ;Ú71@@ðk´D¸{i>^£_?ÿf?´[‡>Jë©9©&JÂ4’µ=TK‚C€å:²ù¢C€ù:²Ó7ÃRnÛ?ÖÌ;¼Ü?ÓêµÀý†9'ž?9'ÌNHÂÖùHÛ´=Á` QÁb q‹±9‘à9KÝ`7M°9Lxý¸Þ¨¥9@x;¹Ê9A * ‰€A@$ÛŸ?é$ï>KeW9æ26Â3“¦=‘²C€€;ª[C€×;ÀÃ.B>Ì; W?ÙåÀù™,9hÞ9gàHÝÎÞHõzÀÁbJÔÁd Ƴݹ¤5B9‰G©7mZ9Š> 9Œwÿ9òa¹ÿ˜d9‚èŸ. ;r{ö@At]D’ÀŠ>;|+?ì°1?§]&>K 9¯PMÂ3à‘=\´C€é:à¸gC€µ:à‰à °Ï>ƒ»4:î~?ÞB Àõ’î91'91žØHðËKI(äÁc¸Áex%Ó¹gÿ9PÜ9='9OÞhµp¼9IÁÖ9®¾9I²/3 ;*I±@A D‚¬X>d–?Á¨Ý?ˆð#>KF·9—ÿÂ4ó==¡C€ð:ÔÖÖC€€:ÔÕžÂè€>:Z:Í…E?ãž©ÀñŠÉ9ÎH9ЉI¥IFáÁeECÁg÷ý=8q-98Ïô·ã¹Q98þÏ67£G947b9”±94w8:‰JØ@A0Dhh„=Ù&?—!?Uº–>K°M9tÄ/Â4C&=kßC€€:¾`œC€€:¾N¾Â½© =ûCã:©“š?éÈÀíw9°ó9ú°I¬YIÍåÁfÊÁh‡e/y86-Î9s§¸çÍ'9•¥¸„©9ÕÛ8š¿Š9L> ;;k@AA™šDNXy=¤ÂÍ?p-¤?)Ôê>KÅú9PˆÂ44=ÐdC€€ :±»C€ÿ:±µ#™ÈÓ=§õ„:‹ÌH?îºÉÀéU8ݼ8ÞwI÷¯I/9ÁhS¨Áj8°mѸ™@9]í·“§:8ÿýݸŸ‰Á8ø#¿9{ß›8÷ƒŽD :ðß^@ATõÃD7{=l·E?3ü_>þ‰Ô>KÖ|9.#WÂ4)r<Ø›C€€5:¢æ…C€ë:¢ÜUÂyBz=Ph}:V 7?ô|}Àå-Õ8³V8´I,) I=PÁiî”Ák™h½)¹i8Ò½a·Þf8Ôh7¸"9-8Éþ9{Tñ8ˬŸJ :psÔ@AjAŠD"b¬=”/>×ng>˜U9>Lô8×FcÂ47<†ÌýC€÷:^F8C€ü:^CåÂIÓ<éÂ:°?úaºÀá18e„)8fë„I²Ã²>|Ϥ>LMX8¬(ÇÂ4ˆ”é´>R˜;>LD¢8ºÜÞÂ4ßYëã>þ>L¤8~óXÂ4<(êC€Ù:/*ðC€ü:/(ãÁÏÄt<uE9¶ì@w«ÀÔƒÅ8ñÑ8pIqÁtI…j¨ÁoÔXÁq‹Cµ±8—KÓ8m·:58M ¸V:8/o¸¸”£8rÂm :LI}@A«|³CÉ`F;é§þ=â<–=Ÿù6>L‰8Q”QÂ49<ípC€ü:vBC€€:rÁÁ§ ?#i°<ú`¿@ µÀÀÐg-7¢7 êI„5{Iœ^ÁqbÓÁrñ’©4謰8î·Y˜8‘¶©£¿7ûYG¸±·Ì7üMx 9Úc@A¼¢ÅC³2w;æI?=éÛN=¥\”>L…m8@Â4†;»¼ÅC€õ9ùê"C€ô9ùé”Á„Û%>Ô:™<ÌxÁ@ ÙÀÌYP7°µè7´ |IIœµ%ÁrÂ~ÁtVÖ{Õ5Ç´7º‘=¶Cc7º©í·RãF7ºHÄ6£“ž7ºo[„ : -@AÏÙCŸâJ;ì*4=û[â=±¼Ó>L 8÷Â3þÀ;³‘kC€Ü:¢’C€ß:¢ÏÁKes>”tF<ºÙ2@nrÀÈc7Ë&O7Ï8I›ßI©*tÁt'Áu« -¶ l¯7²\~7ya7²´»6¾„Ì7®K©¸_éÒ7®ù'‘ 9“ÝÙ@Aä?ÕCä>L©~7ÛqžÂ4´;ˆg5C€€9Üi¯C€ô9ÜiÁ#Êæ>JóÉ<žš6@ê Àćs´,âu4,âuI¨I¸[ÎÁuŒrÁw)‚ý ·QZA7‡š¶$l'7ˆB>6i³¨7ƒ–¦¸Lî7„†&Ÿ 9M–@AûC€‡;f¤¹=†×=>²>L«7´ÛwÂ3ý³;`ö˜C€ó9ÇßCC€ò9ÇßòÁ Ú> E<‰Ò@{ ÀÀÍY7|U7ub I¶XÆIÇãdÁvø¶Áx‘- ¯ µÏBd7`.L¶ˆˆ7a(Ö6‰Ê7[¡ý¸Xé7\㯠9HÓÖ@B BCgô¡;LË´=zÒ=1[¹>Lª7‹ó¯Â4;-žÞC€€9©ï1C€û9©î$ÀÆcñ=¬è<^@";À½;~7xY'7rò¦IÅëÝIÙ"ôÁxe3ÁzB »¡·ªÄ¨7*è·2•7,ζ™!Ô7*qO7ÀT7+µ5À 8…±@BæbCRi°>L°Ç7_îÂ3þË; lÈC€€9•Í×C€€ 9•ÎÀšYŒ=€ËoL¼7;ÆÂÂ3ý—:é–ŠC€ü9Š!ÞC€ý9Š"\Àpã°=ïò<(è<@"´£À¶©Í6¼É[6ÁfËIéÎJqÁ{L¼­7)¬Â3ý]:¶Ø{C€þ9n C€ÿ9n À7ö<Ò׿<³ß@&¡ À³³6Ê&©6ÉoƒIý™âJ .Á|³ŸÁ~n$«Õ6Œ¤S6¶Q¿¶J¡m6·CÅ6žP6³•O·m»6´¡J 8Zé@BJ-ÈC#o:Lã~<˜¯L¾è6ÞÃEÂ4¸:Š•‡C€ö9FN®C€ó9FNxÀBD<¬9<Cg@*¥¨À°ú6®ðu6¬æþJ aŠJz˜Á~8IÁ€f ]5Ÿì‡6Špõ5­SÊ6ŠöEµçó*6‰ ·ir6‰· 8kT@B^eCÊ$:{ŸÚ<ÃË.<Šrq>L¿Ý6¶Ñ†Â3ÿ:cPÚC€€92ø“C€ù92ø±¿Ù&¿>LÂã6˜òüÂ4°:>»zC€ü9$ìC€û9$ëó¿¤×<\è;ÈII@2ùçÀ¬Eå3“nˆ³“nˆJ&.J9€GÁ€³2Á§Ä$Ë-ñ¶¿R6=m´[Ç56=à„µŠÂ³6=Uö^6=¯§V 7»š@B†ŒÏC~>LÃá6pEæÂ3ÿÑ:»UC€þ9v%C€€9v/¿w’”;¤®ß;ªIø@7J¾ÀªK¾2áϲáÏJ6Š„JM8{ÁƒÿÁ‚ˆg,_7©6²ã6 ¶}Ñ6YµW¼6ül4Ý¢;6VQx 7r×@B”JBÿâh:„oÍ<íä*<¨6ë>LÄð6RÂ3ÿò:»ÏC€€9ðTC€€9ðW¿;é;Yì4;•@;¶9À¨¥7»}7 JI¬}Jc†ÜÁ‚a£ÁƒmÖ5·C)3•dX6Íß4§)C6A?4d¦P6Ɖ4YY˜6FÌ 7Þ}@B¢Î8Bõ ô9Ï‘LÆY6õAÂ4e9Æ ¦C€ÿ8äÞC€€8伿 |;Ä‚;‚ýÀ@@<ýÀ§•6z³46])©J_ÏçJ~µÁƒI<Á„cA Qi³w15Æ/¿µ‰Ä…5Æö4„65ÂÇ ¶Á´D5Ã>ÝÇ 7@y4@B³ Bì˜>LÇ76 ÏÔÂ3ÿÑ9«˜gC€ÿ8ÙmC€ü8ÙmŸ¾ÑƒÃ:·øí;`Êb@Dß²À¥Ä€3Ôxw³ÔxwJy‰-JŽetÁ„;'Á…aN¿biµRr5«ƒŠµÉj 5¬òµ®éè5« 85­Ôë5«¯ßô 7eM¿@BÄþ¦BäÍÚ>LÈ5Üw+Â4"9‰@ûC€€8¿NûC€ÿ8¿Nñ¾š…œ:hÃe;@Ïç@IŸÀ¤¬º4yLÍ´yLÍJ‹ÏÃJ ¬_Á…8IÁ†m‰_Uw=².Ž5‰bëµæ5‰È«´þ'5ˆ‡h60Ô÷5ˆúè& 6Ø| @Bر·BÞÙ>LÈ¿5½9ßÂ49k›¿C€€8´žûC€ÿ8´žø¾c=h:XL;$Ýã@N{¦À£Â4HR´HRJc¡J¶ !Á†?Á‡ƒ'sG)5Zl5kz>µ’ïº5l(‰´…ƒ5jîÆ5¹žÀ5k´] 6¦$À@Bî]BÚ¿>LÉÊ5šQ6Â49?þbC€ÿ8¡ù¿C€€8¡ù½¾&Ř9½ý¸;Ò5@SvJÀ¢ÿi³¯u3¯uJ²)&JÏdEÁ‡SCÁˆ¥‹k®M4¯d;5@!ݵ=âÛ5@Õ ³ùëè5@ ¦4Æ€œ5@Ó¨™ 6N.@C™BÖ":.ºú<Ðì <“»W>LÊa5„Â49$_ØC€þ8˜|C€ý8˜|½ó‡9zä;Þy@XªÀ¢_d6éÅQ6ÙïmJÊáwJíÅzÁˆt-Á‰Õ ¨¹Òý3Ah5$YÒµ‰dÚ5$ÖR09 5#ç_µž?^5$s§Ü 60Ø@C5ÂBÓt>LÊ£5^.­Â49 EüC€þ8‹C€ÿ8‰½¯øy9"³:ÝS6@]È…À¡Ý4ÐÓ´ÐÓJèQKö€Á‰¡tÁ‹ÉÌ1ÿ5³¼uU5 tdµK5 åé4ŒQ5 å{µ¨©ð5 dI% 6>ÙP@C¡‰BЊÆ9Ñ}O<‰¶ LË5B™æÂ48ò¯C€€8‡íNC€ÿ8‡íM½}Tæ8Ÿ¼þ:¡k¹@c!À¡sþ6‡îI6KK·=K¨NÁŠÚoÁŒV¼÷4Ñ´q}°4ò>4µ0BÜ4ó'ù´â™4ñ©¤µmð4òªžu 5Íš[@C.~}BΔz9qçÒ<&Ó;ëìý>LË5#ûÂ3ÿû8̲C€ÿ8| 7C€þ8| :½5ƒ8–n:Ô@±@h›¸À¡ê6*ŸÂ6JNK±ºK8´ˆÁŒ|Á¨À*Óuµ1‰nÊ4ÌNݵx 4Ìù2”ô^4Ìí5à¦4ÌÔ×Î 5«©§@C?ñŠBÍ m9-CI;ú—@;±1É>LË}5ÖÂ48²ózC€ý8s%ñC€þ8s%ñ½§8^#:Ý`!@n7¢À Ý95÷5åœuK3öKWø¶ÁnåÁ}i³Ä43rÑ4³Où´5z4³ön³—ˆ24²ã}µ@ï4³›L/ 4ÕP~@CS#KBËÔ®>LË’5ÈWÂ48 5tC€ÿ8ovUC€€8ovT¼µÂ[@sö-À ¨À³„33„3KROLK}¬XÁŽÉkÁjCµ¹#4c¾ó4 u‚´´ÊÐ4¡ é³Zå”4 lø³ª4¡ÿš 5eˆ@Ch@lBÊäõ>LËÆ4ä*¹Â3ÿý8ñ×C€ÿ8i\C€þ8i\¼~Ór7¯ÿ×:°Ïl@yØ-À Ì4û´ûKvÊÙK•”hÁ-Á‘Ù—–)´“E94Žà´ÁÓM4Ž¡/´³,4Ž ­´h0A4Ž›Ä 4&ll@CzBÊ,:]à<ãë< Ý×>LÌ4ОoÂ3ÿý8ºNC€ÿ8j¨ÉC€þ8j¨Ê¼1bN7ªÎµ:ö‚=@Þ~À `6Á«l6´GnK‘dmK°óPÁ‘™ÝÁ“N§€Ñ! ´š14ëj´›n04‚o±²dú~4×X´ 14‚hG‘ 4i(ÿ@CŒƒ#BÉžm>LÌ4¼ÊâÂ3ÿú8qkC€ÿ8lÙ@C€þ8lÙB»õŒH7vý;ÀD@ƒÀ G´²ÖZ’2ÖZ’K«éLÌ5üÂ3ÿú9ÄVC€ÿ8ñk„C€þ8ñk‹»¨=@†-ÌÀ 5³† 3† KÁºKÓ›(Á”ßÁ”Ü[rŸÑc³Ì#4ôµ´á:ª4µgO´lc&4Ï,³µ˜c4Ê\,‘5„›@XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 160 / width of table in bytes NAXIS2 = 69 PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 40 TTYPE1 = 'SMA ' / label for field 1 TFORM1 = '1E ' / data format of field: 4-byte REAL TUNIT1 = 'pixel ' / physical unit of field TTYPE2 = 'INTENS ' / label for field 2 TFORM2 = '1E ' / data format of field: 4-byte REAL TTYPE3 = 'INT_ERR ' / label for field 3 TFORM3 = '1E ' / data format of field: 4-byte REAL TTYPE4 = 'PIX_VAR ' / label for field 4 TFORM4 = '1E ' / data format of field: 4-byte REAL TTYPE5 = 'RMS ' / label for field 5 TFORM5 = '1E ' / data format of field: 4-byte REAL TTYPE6 = 'ELLIP ' / label for field 6 TFORM6 = '1E ' / data format of field: 4-byte REAL TTYPE7 = 'ELLIP_ERR' / label for field 7 TFORM7 = '1E ' / data format of field: 4-byte REAL TTYPE8 = 'PA ' / label for field 8 TFORM8 = '1E ' / data format of field: 4-byte REAL TUNIT8 = 'degrees ' / physical unit of field TTYPE9 = 'PA_ERR ' / label for field 9 TFORM9 = '1E ' / data format of field: 4-byte REAL TUNIT9 = 'degrees ' / physical unit of field TTYPE10 = 'X0 ' / label for field 10 TFORM10 = '1E ' / data format of field: 4-byte REAL TUNIT10 = 'pixel ' / physical unit of field TTYPE11 = 'X0_ERR ' / label for field 11 TFORM11 = '1E ' / data format of field: 4-byte REAL TUNIT11 = 'pixel ' / physical unit of field TTYPE12 = 'Y0 ' / label for field 12 TFORM12 = '1E ' / data format of field: 4-byte REAL TUNIT12 = 'pixel ' / physical unit of field TTYPE13 = 'Y0_ERR ' / label for field 13 TFORM13 = '1E ' / data format of field: 4-byte REAL TUNIT13 = 'pixel ' / physical unit of field TTYPE14 = 'GRAD ' / label for field 14 TFORM14 = '1E ' / data format of field: 4-byte REAL TTYPE15 = 'GRAD_ERR' / label for field 15 TFORM15 = '1E ' / data format of field: 4-byte REAL TTYPE16 = 'GRAD_R_ERR' / label for field 16 TFORM16 = '1E ' / data format of field: 4-byte REAL TTYPE17 = 'RSMA ' / label for field 17 TFORM17 = '1E ' / data format of field: 4-byte REAL TUNIT17 = 'pixel**1/4' / physical unit of field TTYPE18 = 'MAG ' / label for field 18 TFORM18 = '1E ' / data format of field: 4-byte REAL TTYPE19 = 'MAG_LERR' / label for field 19 TFORM19 = '1E ' / data format of field: 4-byte REAL TTYPE20 = 'MAG_UERR' / label for field 20 TFORM20 = '1E ' / data format of field: 4-byte REAL TTYPE21 = 'TFLUX_E ' / label for field 21 TFORM21 = '1E ' / data format of field: 4-byte REAL TTYPE22 = 'TFLUX_C ' / label for field 22 TFORM22 = '1E ' / data format of field: 4-byte REAL TTYPE23 = 'TMAG_E ' / label for field 23 TFORM23 = '1E ' / data format of field: 4-byte REAL TTYPE24 = 'TMAG_C ' / label for field 24 TFORM24 = '1E ' / data format of field: 4-byte REAL TTYPE25 = 'NPIX_E ' / label for field 25 TFORM25 = '1J ' / data format of field: 4-byte INTEGER TTYPE26 = 'NPIX_C ' / label for field 26 TFORM26 = '1J ' / data format of field: 4-byte INTEGER TTYPE27 = 'A3 ' / label for field 27 TFORM27 = '1E ' / data format of field: 4-byte REAL TTYPE28 = 'A3_ERR ' / label for field 28 TFORM28 = '1E ' / data format of field: 4-byte REAL TTYPE29 = 'B3 ' / label for field 29 TFORM29 = '1E ' / data format of field: 4-byte REAL TTYPE30 = 'B3_ERR ' / label for field 30 TFORM30 = '1E ' / data format of field: 4-byte REAL TTYPE31 = 'A4 ' / label for field 31 TFORM31 = '1E ' / data format of field: 4-byte REAL TTYPE32 = 'A4_ERR ' / label for field 32 TFORM32 = '1E ' / data format of field: 4-byte REAL TTYPE33 = 'B4 ' / label for field 33 TFORM33 = '1E ' / data format of field: 4-byte REAL TTYPE34 = 'B4_ERR ' / label for field 34 TFORM34 = '1E ' / data format of field: 4-byte REAL TTYPE35 = 'NDATA ' / label for field 35 TFORM35 = '1J ' / data format of field: 4-byte INTEGER TTYPE36 = 'NFLAG ' / label for field 36 TFORM36 = '1J ' / data format of field: 4-byte INTEGER TTYPE37 = 'NITER ' / label for field 37 TFORM37 = '1J ' / data format of field: 4-byte INTEGER TTYPE38 = 'STOP ' / label for field 38 TFORM38 = '1J ' / data format of field: 4-byte INTEGER TTYPE39 = 'A_BIG ' / label for field 39 TFORM39 = '1E ' / data format of field: 4-byte REAL TTYPE40 = 'SAREA ' / label for field 40 TFORM40 = '1E ' / data format of field: 4-byte REAL TUNIT40 = 'pixel ' / physical unit of field TDISP1 = 'F7.2 ' / display format TDISP2 = 'G10.3 ' / display format TDISP3 = 'G10.3 ' / display format TDISP4 = 'G9.3 ' / display format TDISP5 = 'G9.3 ' / display format TDISP6 = 'F6.4 ' / display format TDISP7 = 'F6.4 ' / display format TDISP8 = 'F6.2 ' / display format TDISP9 = 'F6.2 ' / display format TDISP10 = 'F7.2 ' / display format TDISP11 = 'F6.2 ' / display format TDISP12 = 'F7.2 ' / display format TDISP13 = 'F6.2 ' / display format TDISP14 = 'G8.3 ' / display format TDISP15 = 'G6.3 ' / display format TDISP16 = 'G6.3 ' / display format TDISP17 = 'F7.5 ' / display format TDISP18 = 'G7.3 ' / display format TDISP19 = 'G7.3 ' / display format TDISP20 = 'G7.3 ' / display format TDISP21 = 'G12.5 ' / display format TDISP22 = 'G12.5 ' / display format TDISP23 = 'G7.3 ' / display format TDISP24 = 'G7.3 ' / display format TDISP25 = 'I6 ' / display format TNULL25 = -2147483647 / undefined value for column TDISP26 = 'I6 ' / display format TNULL26 = -2147483647 / undefined value for column TDISP27 = 'G9.3 ' / display format TDISP28 = 'G7.3 ' / display format TDISP29 = 'G9.3 ' / display format TDISP30 = 'G7.3 ' / display format TDISP31 = 'G9.3 ' / display format TDISP32 = 'G7.3 ' / display format TDISP33 = 'G9.3 ' / display format TDISP34 = 'G7.3 ' / display format TDISP35 = 'I5 ' / display format TNULL35 = -2147483647 / undefined value for column TDISP36 = 'I5 ' / display format TNULL36 = -2147483647 / undefined value for column TDISP37 = 'I3 ' / display format TNULL37 = -2147483647 / undefined value for column TDISP38 = 'I2 ' / display format TNULL38 = -2147483647 / undefined value for column TDISP39 = 'G9.3 ' / display format TDISP40 = 'F5.1 ' / display format IMAGE = 'synth.fits' END F’*ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿC€€ÿÿÿÿC€~zÿÿÿÿÃvôÿÿÿÿÿÿÿÿÁÅ+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿ?__F‘^A’˜ÃBºßùB„#ø>“ü7>)Ä›Â=ýœAžì›C€€=]?€C€~z=W‹(ĨPD R$?‰0?Y~`Á‡Œ;‹; ÉF’*F’*ÁÅ+ÁÅ+¼× h=䨻‹z«=ÔV½•O.=§—Ô¾ °>­#^ =s z@?µµF%²A±q™Bâ2BŸò>“ü7>)À Â=þ AžèUC€€=sYC€~T=mÄ ŠÍD$P?‰•å?^¼üÁz€;,w®;,üF’*F’*ÁÅ+ÁÅ+¼× a=ä+»Ë =ÔSP½•Uª=§•«¾ «5>­ =Šƒf@?!azF£gAÖ´qCÙBÁˆG>“ü7>)ÊBÂ>¥AžñæC€€=…àC€~*=‚jÄ­D'Zù?‰š[?dùÁj©;Q|;PäcF’*F’*ÁÅ+ÁÅ+¼ÖSû=ä5»ŽQ¾=Ô`,½•­ÿ=§÷¾ ²!>­" =ÊŽ@?1„ÓF¿BÙC%†&Bê>“ü7>)¿Â>üAžçkC€€=“9ùC€}ú=kÒÄ+D\D87?‰G?iœÁWk;~‘s;}­PF’*F’*ÁÅ+ÁÅ+¼Öžj=䑻޲:=ÔQ뽕›ï=§ÖÀ¾ ¨Z>­ Þ =ï+¿@?CEOF G B)#CHWcC ©©>“ü7>)ÉåÂ>ïAžñC€þ=¡ýµC€}É=ÍÄ6Á@;šî2;šDoF’*F’*ÁÅ+ÁÅ+¼ÕuS=ä »_=Ô`T½•Àã=¨ æ¾ ±/>­"4 > U@?VÌ>F `B>?CrY\C+]Þ>“ü7>)·œÂ=ùÞAžàpC€€=²ÁC€}‹=­„àÄO@ÇD^·z?‰Œç?uÁ#‹;¼³š;»»¬F’*F’*ÁÅ+ÁÅ+¼×^Î=äÖ»Œë¨=ÔF(½•)=§^ü¾ £ž>­© >6™‘@?lGF HÐBfbC’¢—CO_•>“ü7>)úÂ=ÿEAžëÈC€€=ÃùC€}N=¾ë5ÄcïDuQ?‰–6?zë’ÁØ;æG‰;äÑÆF’*F’*ÁÅ+ÁÅ+¼× )=äË»•|=ÔV`½•l =§­Ð¾ ­Í>­< >;t@?óãF öýB‹6ˆC±vdCzøF>“ü7>)Ç{Â>ÔAžïLC€þ=טÏC€} =ÒÐÄz¿ûD†Æá?‰™H?€|CÁÖƒ< Ë < ¬ôF’*G5ö´ÁÅ+Á:ºŸ¼Õø=äó»´=Ô\T½•¢½=§ê»¾ ¯ô>­u >jöq@?Žò­FXãB¨ÈªC×(tC˜#Ã>“IÕ=ë7ÁÂ=dÇA]3C€ö=£ïÄC€|¼=ŸûLÄÇÝzDŽY’?6T¯?ƒ•kÁ¢<,á-<+3”F’*G5ö´ÁÅ+Á:ºŸ¼—rb=ší×»]¢k=’¼Î½Eú)=N$¾^c >4€ ?Öý@?>%F±B¦Î{CÔ£2C–[>wcA=… Â7'eAþC€€Ô=BoC€~¶=A'KÅ(éÞD`|r>ª­?†Á²Áµ<0t}<.¼¬G5ö´G5ö´Á:ºŸÁ:ºŸ¼,‹Ô="šÀ»´µI=àß¼·o5SD©=(Î*Â;Ô @Ó+IC€€ÿ=ZC€Z=–ÅH£}Dèß>JÁÆ?ŠÁ,]<þ~<ÌÖG5ö´G5ö´Á:ºŸÁ:ºŸ»‡ T<ĨW»‹N<½|¼€:6<+¸<½….Œ<ƒTÏ > Ê1@?¾C„Eëü;BNxdCƒ™xC:>Géù<íº¿Â:d@œ,ÒC€:<ËôC€R<ÈõRÅMV$CãB> ªM?U}Á;ô";òYÓGrâ‡G’®Á?¾áÁC‘ »!º<ˆ¦ñ»ñ<ƒ[¼¼Rç\< ŵ½-wÓ<#} ={Ò@?ÑJEEÜ6MB*Á,CY«”Cê…>C$ô<·Ù~Â9ï+@vÓ3C€€è<¬ >C€(<ªu¹ÅHŲC¥Ëí=ÓgB?½öÁën;Ø-®;ÖßyGrâ‡G’®Á?¾áÁC‘ »o‘™<ýi<„^Â8òÇ@6‚ÿC€&<‡A`C€S<†C=Å=šùCPªÃ=ŒÞG?”;xÁ‚Ì;­Ì;¬¿‰G’®G’®ÁC‘ÁC‘ »€æ€<¡gºËj<Ò¼ ‘B;°u¼¬{®;­ðB =Âý@?ý=µE¹@A’ÍB»"·B„S*>5K<·IÂ7Î’?Ö¿•C€<<'ÓC€Ñ<&ªÅ2ÈC\Ë=O|¡?—Î…ÁæÚ;\Ìh;\^G’®G’®ÁC‘ÁC‘ »¾Í±;˜b:;—5T»½Yµ;‡>U»²1; =L\@@ HWE¦:àAªBØÈB™Iþ>*ý;áËG’®G»+¿ÁC‘ÁGB¥ ¼W<;Ûã3ºêÀe;Ù_qºmåj;†ð<‡¡^;ˆD @u`˜@@5úE˜úŸAþôBK·«B Ì>5 ;×[ñÂçXº@@(ˆ-EŒãÕA-5ÿBm-ÇB'µô>?ñ<Â1Ûê?®§˜C€€.<@¢wC€€üC®#@@9b˜EËì@ôR1B2úAû×#>Dœ;Ÿê(Â6X§?WXŽC€é<’ C€€f<:ÈÄ®¢·Aþm¼<º|?¦üÆÁ¼;êÒ;¯çH ª3H?QÁN5ÁNåv9ο™;=xº³;5 º©:K;ÿ»ÍÃ;3 >ÝH@@KìtEiÐà@}AÔ;¬A–K>AM|;Y øÂ3 Ÿ?ÌâC€ý;Á¬?C€ù;Áí‹Ä‰ A´8<¨K?«›Áëv:¨[ :¨ ½H ª3H9´ÁN5ÁSI%¸£âš:ùÛu¸¨¢:ù~Í:½Ñ::ç˜;T§:æì& =¿Ùç@@`PæEȘ@¡'mAþÎŽA´,ø>A˱;‹¡(Â8¶ˆ?97rC€€š< =GC€ù< gmÄWÿA’ <­M?¯#KÁ 3¨:Ó—):ÓcH,ëÃH9´ÁQíÁSI!%ºy]Í;#EÕ¹ƒ‰;!C`ºK(t;àÐ;Žãf;, >Lìß@@v¿dEAC@'¢jAŠþÁAD‘>F ;M Â4¼K>¿Ã)C€º; Å±C€ý; žiÄ=ÐøA»JF÷o:Ö­àÂ18>ŠkZC€€;€!ßC€€;€žLÄ&¼@Ùf²<'Í?·¯§Á â®:<°v:<ËHEãŽHn$ÁTDÔÁW|J)9:P(:}}¸ 6ù:{µ<:cÒ(:j*óº½F´:h–H =U@@•HFE`@ qAld_A''‰>G²Æ; ;ŽÂ3îl>°[@C€ü;¶ýC€€;¶¾Ä…ô@¢ßÝ<"6?¼‘Á Ð:gÅì:gf™HtDKH…”ÁWí4ÁYjŽ;E9ìŽ:£÷E¹À·Á:¥3Ÿ7"B°:”ªö;'‹:•І2?S€@@¤5çE–œ?Š™Aðé@º—Ä>I­7:”v™Â36 >=>ÀC€ò;W*ýC€>;WfÚÃä-@HIp:ŒTFÂ2ë¥>4\ôC€€S;_«zC€€I;_þÒö×Ü@ ¾;Å Ý?ÅLÁn'9þ]ª9þmêH“¸5H e˜Á[;Á\©9Sa9´ô:)f¹×*:'^ž¹Fß:3:²ÄŸ:‡u =8ä‡@@ƱÞDæ6ú?$}ñ@¬¡@sIq>JdÂ:R”fÂ49¡>ƒ C€€¢;8¯wC€º;8 šÃ›Vk? º;„q5?ÊÁ›ã9Æßu9ÆWêH¡çH´^Á\ºÁ^³ ayº2Ë;9÷ø˜8=>¥9ö¯è¸4ç`9澺‚# 9ää3# <=º@@ÚuDÍýÕ>ÈsÛ@]K+@zm>I¸: ÜfÂ3¾É=¶Ž?C€€+; yðC€½; …ŽÃ}æP?;R0;<Þá?ÎíSÁ­u9†þ‚9‡uÌH³ÌHÆgãÁ^žÁ`Zúw‘ºLô9¦¦’¹=à9£Â·š‹9¡Mc9öN9ž‹u' ;Ú71@@ðk´D¸{i>^£_?ÿf?´[‡>Jë©9©&JÂ4’µ=TK‚C€å:²ù¢C€ù:²Ó7ÃRnÛ?ÖÌ;¼Ü?ÓêµÀý†9'ž?9'ÌNHÂÖùHÛ´=Á` QÁb q‹±9‘à9KÝ`7M°9Lxý¸Þ¨¥9@x;¹Ê9A * ‰€A@$ÛŸ?é$ï>KeW9æ26Â3“¦=‘²C€€;ª[C€×;ÀÃ.B>Ì; W?ÙåÀù™,9hÞ9gàHÝÎÞHõzÀÁbJÔÁd Ƴݹ¤5B9‰G©7mZ9Š> 9Œwÿ9òa¹ÿ˜d9‚èŸ. ;r{ö@At]D’ÀŠ>;|+?ì°1?§]&>K 9¯PMÂ3à‘=\´C€é:à¸gC€µ:à‰à °Ï>ƒ»4:î~?ÞB Àõ’î91'91žØHðËKI(äÁc¸Áex%Ó¹gÿ9PÜ9='9OÞhµp¼9IÁÖ9®¾9I²/3 ;*I±@A D‚¬X>d–?Á¨Ý?ˆð#>KF·9—ÿÂ4ó==¡C€ð:ÔÖÖC€€:ÔÕžÂè€>:Z:Í…E?ãž©ÀñŠÉ9ÎH9ЉI¥IFáÁeECÁg÷ý=8q-98Ïô·ã¹Q98þÏ67£G947b9”±94w8:‰JØ@A0Dhh„=Ù&?—!?Uº–>K°M9tÄ/Â4C&=kßC€€:¾`œC€€:¾N¾Â½© =ûCã:©“š?éÈÀíw9°ó9ú°I¬YIÍåÁfÊÁh‡e/y86-Î9s§¸çÍ'9•¥¸„©9ÕÛ8š¿Š9L> ;;k@AA™šDNXy=¤ÂÍ?p-¤?)Ôê>KÅú9PˆÂ44=ÐdC€€ :±»C€ÿ:±µ#™ÈÓ=§õ„:‹ÌH?îºÉÀéU8ݼ8ÞwI÷¯I/9ÁhS¨Áj8°mѸ™@9]í·“§:8ÿýݸŸ‰Á8ø#¿9{ß›8÷ƒŽD :ðß^@ATõÃD7{=l·E?3ü_>þ‰Ô>KÖ|9.#WÂ4)r<Ø›C€€5:¢æ…C€ë:¢ÜUÂyBz=Ph}:V 7?ô|}Àå-Õ8³V8´I,) I=PÁiî”Ák™h½)¹i8Ò½a·Þf8Ôh7¸"9-8Éþ9{Tñ8ˬŸJ :psÔ@AjAŠD"b¬=”/>×ng>˜U9>Lô8×FcÂ47<†ÌýC€÷:^F8C€ü:^CåÂIÓ<éÂ:°?úaºÀá18e„)8fë„I²Ã²>|Ϥ>LMX8¬(ÇÂ4ˆ”é´>R˜;>LD¢8ºÜÞÂ4ßYëã>þ>L¤8~óXÂ4<(êC€Ù:/*ðC€ü:/(ãÁÏÄt<uE9¶ì@w«ÀÔƒÅ8ñÑ8pIqÁtI…j¨ÁoÔXÁq‹Cµ±8—KÓ8m·:58M ¸V:8/o¸¸”£8rÂm :LI}@A«|³CÉ`F;é§þ=â<–=Ÿù6>L‰8Q”QÂ49<ípC€ü:vBC€€:rÁÁ§ ?#i°<ú`¿@ µÀÀÐg-7¢7 êI„5{Iœ^ÁqbÓÁrñ’©4謰8î·Y˜8‘¶©£¿7ûYG¸±·Ì7üMx 9Úc@A¼¢ÅC³2w;æI?=éÛN=¥\”>L…m8@Â4†;»¼ÅC€õ9ùê"C€ô9ùé”Á„Û%>Ô:™<ÌxÁ@ ÙÀÌYP7°µè7´ |IIœµ%ÁrÂ~ÁtVÖ{Õ5Ç´7º‘=¶Cc7º©í·RãF7ºHÄ6£“ž7ºo[„ : -@AÏÙCŸâJ;ì*4=û[â=±¼Ó>L 8÷Â3þÀ;³‘kC€Ü:¢’C€ß:¢ÏÁKes>”tF<ºÙ2@nrÀÈc7Ë&O7Ï8I›ßI©*tÁt'Áu« -¶ l¯7²\~7ya7²´»6¾„Ì7®K©¸_éÒ7®ù'‘ 9“ÝÙ@Aä?ÕCä>L©~7ÛqžÂ4´;ˆg5C€€9Üi¯C€ô9ÜiÁ#Êæ>JóÉ<žš6@ê Àćs´,âu4,âuI¨I¸[ÎÁuŒrÁw)‚ý ·QZA7‡š¶$l'7ˆB>6i³¨7ƒ–¦¸Lî7„†&Ÿ 9M–@AûC€‡;f¤¹=†×=>²>L«7´ÛwÂ3ý³;`ö˜C€ó9ÇßCC€ò9ÇßòÁ Ú> E<‰Ò@{ ÀÀÍY7|U7ub I¶XÆIÇãdÁvø¶Áx‘- ¯ µÏBd7`.L¶ˆˆ7a(Ö6‰Ê7[¡ý¸Xé7\㯠9HÓÖ@B BCgô¡;LË´=zÒ=1[¹>Lª7‹ó¯Â4;-žÞC€€9©ï1C€û9©î$ÀÆcñ=¬è<^@";À½;~7xY'7rò¦IÅëÝIÙ"ôÁxe3ÁzB »¡·ªÄ¨7*è·2•7,ζ™!Ô7*qO7ÀT7+µ5À 8…±@BæbCRi°>L°Ç7_îÂ3þË; lÈC€€9•Í×C€€ 9•ÎÀšYŒ=€ËoL¼7;ÆÂÂ3ý—:é–ŠC€ü9Š!ÞC€ý9Š"\Àpã°=ïò<(è<@"´£À¶©Í6¼É[6ÁfËIéÎJqÁ{L¼­7)¬Â3ý]:¶Ø{C€þ9n C€ÿ9n À7ö<Ò׿<³ß@&¡ À³³6Ê&©6ÉoƒIý™âJ .Á|³ŸÁ~n$«Õ6Œ¤S6¶Q¿¶J¡m6·CÅ6žP6³•O·m»6´¡J 8Zé@BJ-ÈC#o:Lã~<˜¯L¾è6ÞÃEÂ4¸:Š•‡C€ö9FN®C€ó9FNxÀBD<¬9<Cg@*¥¨À°ú6®ðu6¬æþJ aŠJz˜Á~8IÁ€f ]5Ÿì‡6Špõ5­SÊ6ŠöEµçó*6‰ ·ir6‰· 8kT@B^eCÊ$:{ŸÚ<ÃË.<Šrq>L¿Ý6¶Ñ†Â3ÿ:cPÚC€€92ø“C€ù92ø±¿Ù&¿>LÂã6˜òüÂ4°:>»zC€ü9$ìC€û9$ëó¿¤×<\è;ÈII@2ùçÀ¬Eå3“nˆ³“nˆJ&.J9€GÁ€³2Á§Ä$Ë-ñ¶¿R6=m´[Ç56=à„µŠÂ³6=Uö^6=¯§V 7»š@B†ŒÏC~>LÃá6pEæÂ3ÿÑ:»UC€þ9v%C€€9v/¿w’”;¤®ß;ªIø@7J¾ÀªK¾2áϲáÏJ6Š„JM8{ÁƒÿÁ‚ˆg,_7©6²ã6 ¶}Ñ6YµW¼6ül4Ý¢;6VQx 7r×@B”JBÿâh:„oÍ<íä*<¨6ë>LÄð6RÂ3ÿò:»ÏC€€9ðTC€€9ðW¿;é;Yì4;•@;¶9À¨¥7»}7 JI¬}Jc†ÜÁ‚a£ÁƒmÖ5·C)3•dX6Íß4§)C6A?4d¦P6Ɖ4YY˜6FÌ 7Þ}@B¢Î8Bõ ô9Ï‘LÆY6õAÂ4e9Æ ¦C€ÿ8äÞC€€8伿 |;Ä‚;‚ýÀ@@<ýÀ§•6z³46])©J_ÏçJ~µÁƒI<Á„cA Qi³w15Æ/¿µ‰Ä…5Æö4„65ÂÇ ¶Á´D5Ã>ÝÇ 7@y4@B³ Bì˜>LÇ76 ÏÔÂ3ÿÑ9«˜gC€ÿ8ÙmC€ü8ÙmŸ¾ÑƒÃ:·øí;`Êb@Dß²À¥Ä€3Ôxw³ÔxwJy‰-JŽetÁ„;'Á…aN¿biµRr5«ƒŠµÉj 5¬òµ®éè5« 85­Ôë5«¯ßô 7eM¿@BÄþ¦BäÍÚ>LÈ5Üw+Â4"9‰@ûC€€8¿NûC€ÿ8¿Nñ¾š…œ:hÃe;@Ïç@IŸÀ¤¬º4yLÍ´yLÍJ‹ÏÃJ ¬_Á…8IÁ†m‰_Uw=².Ž5‰bëµæ5‰È«´þ'5ˆ‡h60Ô÷5ˆúè& 6Ø| @Bر·BÞÙ>LÈ¿5½9ßÂ49k›¿C€€8´žûC€ÿ8´žø¾c=h:XL;$Ýã@N{¦À£Â4HR´HRJc¡J¶ !Á†?Á‡ƒ'sG)5Zl5kz>µ’ïº5l(‰´…ƒ5jîÆ5¹žÀ5k´] 6¦$À@Bî]BÚ¿>LÉÊ5šQ6Â49?þbC€ÿ8¡ù¿C€€8¡ù½¾&Ř9½ý¸;Ò5@SvJÀ¢ÿi³¯u3¯uJ²)&JÏdEÁ‡SCÁˆ¥‹k®M4¯d;5@!ݵ=âÛ5@Õ ³ùëè5@ ¦4Æ€œ5@Ó¨™ 6N.@C™BÖ":.ºú<Ðì <“»W>LÊa5„Â49$_ØC€þ8˜|C€ý8˜|½ó‡9zä;Þy@XªÀ¢_d6éÅQ6ÙïmJÊáwJíÅzÁˆt-Á‰Õ ¨¹Òý3Ah5$YÒµ‰dÚ5$ÖR09 5#ç_µž?^5$s§Ü 60Ø@C5ÂBÓt>LÊ£5^.­Â49 EüC€þ8‹C€ÿ8‰½¯øy9"³:ÝS6@]È…À¡Ý4ÐÓ´ÐÓJèQKö€Á‰¡tÁ‹ÉÌ1ÿ5³¼uU5 tdµK5 åé4ŒQ5 å{µ¨©ð5 dI% 6>ÙP@C¡‰BЊÆ9Ñ}O<‰¶ LË5B™æÂ48ò¯C€€8‡íNC€ÿ8‡íM½}Tæ8Ÿ¼þ:¡k¹@c!À¡sþ6‡îI6KK·=K¨NÁŠÚoÁŒV¼÷4Ñ´q}°4ò>4µ0BÜ4ó'ù´â™4ñ©¤µmð4òªžu 5Íš[@C.~}BΔz9qçÒ<&Ó;ëìý>LË5#ûÂ3ÿû8̲C€ÿ8| 7C€þ8| :½5ƒ8–n:Ô@±@h›¸À¡ê6*ŸÂ6JNK±ºK8´ˆÁŒ|Á¨À*Óuµ1‰nÊ4ÌNݵx 4Ìù2”ô^4Ìí5à¦4ÌÔ×Î 5«©§@C?ñŠBÍ m9-CI;ú—@;±1É>LË}5ÖÂ48²ózC€ý8s%ñC€þ8s%ñ½§8^#:Ý`!@n7¢À Ý95÷5åœuK3öKWø¶ÁnåÁ}i³Ä43rÑ4³Où´5z4³ön³—ˆ24²ã}µ@ï4³›L/ 4ÕP~@CS#KBËÔ®>LË’5ÈWÂ48 5tC€ÿ8ovUC€€8ovT¼µÂ[@sö-À ¨À³„33„3KROLK}¬XÁŽÉkÁjCµ¹#4c¾ó4 u‚´´ÊÐ4¡ é³Zå”4 lø³ª4¡ÿš 5eˆ@Ch@lBÊäõ>LËÆ4ä*¹Â3ÿý8ñ×C€ÿ8i\C€þ8i\¼~Ór7¯ÿ×:°Ïl@yØ-À Ì4û´ûKvÊÙK•”hÁ-Á‘Ù—–)´“E94Žà´ÁÓM4Ž¡/´³,4Ž ­´h0A4Ž›Ä 4&ll@CzBÊ,:]à<ãë< Ý×>LÌ4ОoÂ3ÿý8ºNC€ÿ8j¨ÉC€þ8j¨Ê¼1bN7ªÎµ:ö‚=@Þ~À `6Á«l6´GnK‘dmK°óPÁ‘™ÝÁ“N§€Ñ! ´š14ëj´›n04‚o±²dú~4×X´ 14‚hG‘ 4i(ÿ@CŒƒ#BÉžm>LÌ4¼ÊâÂ3ÿú8qkC€ÿ8lÙ@C€þ8lÙB»õŒH7vý;ÀD@ƒÀ G´²ÖZ’2ÖZ’K«éLÌ5üÂ3ÿú9ÄVC€ÿ8ñk„C€þ8ñk‹»¨=@†-ÌÀ 5³† 3† KÁºKÓ›(Á”ßÁ”Ü[rŸÑc³Ì#4ôµ´á:ª4µgO´lc&4Ï,³µ˜c4Ê\,‘5„›@XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 160 / width of table in bytes NAXIS2 = 69 PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 40 TTYPE1 = 'SMA ' / label for field 1 TFORM1 = '1E ' / data format of field: 4-byte REAL TUNIT1 = 'pixel ' / physical unit of field TTYPE2 = 'INTENS ' / label for field 2 TFORM2 = '1E ' / data format of field: 4-byte REAL TTYPE3 = 'INT_ERR ' / label for field 3 TFORM3 = '1E ' / data format of field: 4-byte REAL TTYPE4 = 'PIX_VAR ' / label for field 4 TFORM4 = '1E ' / data format of field: 4-byte REAL TTYPE5 = 'RMS ' / label for field 5 TFORM5 = '1E ' / data format of field: 4-byte REAL TTYPE6 = 'ELLIP ' / label for field 6 TFORM6 = '1E ' / data format of field: 4-byte REAL TTYPE7 = 'ELLIP_ERR' / label for field 7 TFORM7 = '1E ' / data format of field: 4-byte REAL TTYPE8 = 'PA ' / label for field 8 TFORM8 = '1E ' / data format of field: 4-byte REAL TUNIT8 = 'degrees ' / physical unit of field TTYPE9 = 'PA_ERR ' / label for field 9 TFORM9 = '1E ' / data format of field: 4-byte REAL TUNIT9 = 'degrees ' / physical unit of field TTYPE10 = 'X0 ' / label for field 10 TFORM10 = '1E ' / data format of field: 4-byte REAL TUNIT10 = 'pixel ' / physical unit of field TTYPE11 = 'X0_ERR ' / label for field 11 TFORM11 = '1E ' / data format of field: 4-byte REAL TUNIT11 = 'pixel ' / physical unit of field TTYPE12 = 'Y0 ' / label for field 12 TFORM12 = '1E ' / data format of field: 4-byte REAL TUNIT12 = 'pixel ' / physical unit of field TTYPE13 = 'Y0_ERR ' / label for field 13 TFORM13 = '1E ' / data format of field: 4-byte REAL TUNIT13 = 'pixel ' / physical unit of field TTYPE14 = 'GRAD ' / label for field 14 TFORM14 = '1E ' / data format of field: 4-byte REAL TTYPE15 = 'GRAD_ERR' / label for field 15 TFORM15 = '1E ' / data format of field: 4-byte REAL TTYPE16 = 'GRAD_R_ERR' / label for field 16 TFORM16 = '1E ' / data format of field: 4-byte REAL TTYPE17 = 'RSMA ' / label for field 17 TFORM17 = '1E ' / data format of field: 4-byte REAL TUNIT17 = 'pixel**1/4' / physical unit of field TTYPE18 = 'MAG ' / label for field 18 TFORM18 = '1E ' / data format of field: 4-byte REAL TTYPE19 = 'MAG_LERR' / label for field 19 TFORM19 = '1E ' / data format of field: 4-byte REAL TTYPE20 = 'MAG_UERR' / label for field 20 TFORM20 = '1E ' / data format of field: 4-byte REAL TTYPE21 = 'TFLUX_E ' / label for field 21 TFORM21 = '1E ' / data format of field: 4-byte REAL TTYPE22 = 'TFLUX_C ' / label for field 22 TFORM22 = '1E ' / data format of field: 4-byte REAL TTYPE23 = 'TMAG_E ' / label for field 23 TFORM23 = '1E ' / data format of field: 4-byte REAL TTYPE24 = 'TMAG_C ' / label for field 24 TFORM24 = '1E ' / data format of field: 4-byte REAL TTYPE25 = 'NPIX_E ' / label for field 25 TFORM25 = '1J ' / data format of field: 4-byte INTEGER TTYPE26 = 'NPIX_C ' / label for field 26 TFORM26 = '1J ' / data format of field: 4-byte INTEGER TTYPE27 = 'A3 ' / label for field 27 TFORM27 = '1E ' / data format of field: 4-byte REAL TTYPE28 = 'A3_ERR ' / label for field 28 TFORM28 = '1E ' / data format of field: 4-byte REAL TTYPE29 = 'B3 ' / label for field 29 TFORM29 = '1E ' / data format of field: 4-byte REAL TTYPE30 = 'B3_ERR ' / label for field 30 TFORM30 = '1E ' / data format of field: 4-byte REAL TTYPE31 = 'A4 ' / label for field 31 TFORM31 = '1E ' / data format of field: 4-byte REAL TTYPE32 = 'A4_ERR ' / label for field 32 TFORM32 = '1E ' / data format of field: 4-byte REAL TTYPE33 = 'B4 ' / label for field 33 TFORM33 = '1E ' / data format of field: 4-byte REAL TTYPE34 = 'B4_ERR ' / label for field 34 TFORM34 = '1E ' / data format of field: 4-byte REAL TTYPE35 = 'NDATA ' / label for field 35 TFORM35 = '1J ' / data format of field: 4-byte INTEGER TTYPE36 = 'NFLAG ' / label for field 36 TFORM36 = '1J ' / data format of field: 4-byte INTEGER TTYPE37 = 'NITER ' / label for field 37 TFORM37 = '1J ' / data format of field: 4-byte INTEGER TTYPE38 = 'STOP ' / label for field 38 TFORM38 = '1J ' / data format of field: 4-byte INTEGER TTYPE39 = 'A_BIG ' / label for field 39 TFORM39 = '1E ' / data format of field: 4-byte REAL TTYPE40 = 'SAREA ' / label for field 40 TFORM40 = '1E ' / data format of field: 4-byte REAL TUNIT40 = 'pixel ' / physical unit of field TDISP1 = 'F7.2 ' / display format TDISP2 = 'G10.3 ' / display format TDISP3 = 'G10.3 ' / display format TDISP4 = 'G9.3 ' / display format TDISP5 = 'G9.3 ' / display format TDISP6 = 'F6.4 ' / display format TDISP7 = 'F6.4 ' / display format TDISP8 = 'F6.2 ' / display format TDISP9 = 'F6.2 ' / display format TDISP10 = 'F7.2 ' / display format TDISP11 = 'F6.2 ' / display format TDISP12 = 'F7.2 ' / display format TDISP13 = 'F6.2 ' / display format TDISP14 = 'G8.3 ' / display format TDISP15 = 'G6.3 ' / display format TDISP16 = 'G6.3 ' / display format TDISP17 = 'F7.5 ' / display format TDISP18 = 'G7.3 ' / display format TDISP19 = 'G7.3 ' / display format TDISP20 = 'G7.3 ' / display format TDISP21 = 'G12.5 ' / display format TDISP22 = 'G12.5 ' / display format TDISP23 = 'G7.3 ' / display format TDISP24 = 'G7.3 ' / display format TDISP25 = 'I6 ' / display format TNULL25 = -2147483647 / undefined value for column TDISP26 = 'I6 ' / display format TNULL26 = -2147483647 / undefined value for column TDISP27 = 'G9.3 ' / display format TDISP28 = 'G7.3 ' / display format TDISP29 = 'G9.3 ' / display format TDISP30 = 'G7.3 ' / display format TDISP31 = 'G9.3 ' / display format TDISP32 = 'G7.3 ' / display format TDISP33 = 'G9.3 ' / display format TDISP34 = 'G7.3 ' / display format TDISP35 = 'I5 ' / display format TNULL35 = -2147483647 / undefined value for column TDISP36 = 'I5 ' / display format TNULL36 = -2147483647 / undefined value for column TDISP37 = 'I3 ' / display format TNULL37 = -2147483647 / undefined value for column TDISP38 = 'I2 ' / display format TNULL38 = -2147483647 / undefined value for column TDISP39 = 'G9.3 ' / display format TDISP40 = 'F5.1 ' / display format IMAGE = 'synth.fits' END F’*ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿC€€ÿÿÿÿC€~zÿÿÿÿÃvôÿÿÿÿÿÿÿÿÁÅ+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿ?__F‘^A’˜ÃBºßùB„#ø>“ü7>)Ä›Â=ýœAžì›C€€=]?€C€~z=W‹(ĨPD R$?‰0?Y~`Á‡Œ;‹; ÉF’*F’*ÁÅ+ÁÅ+¼× h=䨻‹z«=ÔV½•O.=§—Ô¾ °>­#^ =s z@?µµF%²A±q™Bâ2BŸò>“ü7>)À Â=þ AžèUC€€=sYC€~T=mÄ ŠÍD$P?‰•å?^¼üÁz€;,w®;,üF’*F’*ÁÅ+ÁÅ+¼× a=ä+»Ë =ÔSP½•Uª=§•«¾ «5>­ =Šƒf@?!azF£gAÖ´qCÙBÁˆG>“ü7>)ÊBÂ>¥AžñæC€€=…àC€~*=‚jÄ­D'Zù?‰š[?dùÁj©;Q|;PäcF’*F’*ÁÅ+ÁÅ+¼ÖSû=ä5»ŽQ¾=Ô`,½•­ÿ=§÷¾ ²!>­" =ÊŽ@?1„ÓF¿BÙC%†&Bê>“ü7>)¿Â>üAžçkC€€=“9ùC€}ú=kÒÄ+D\D87?‰G?iœÁWk;~‘s;}­PF’*F’*ÁÅ+ÁÅ+¼Öžj=䑻޲:=ÔQ뽕›ï=§ÖÀ¾ ¨Z>­ Þ =ï+¿@?CEOF G B)#CHWcC ©©>“ü7>)ÉåÂ>ïAžñC€þ=¡ýµC€}É=ÍÄ6Á@;šî2;šDoF’*F’*ÁÅ+ÁÅ+¼ÕuS=ä »_=Ô`T½•Àã=¨ æ¾ ±/>­"4 > U@?VÌ>F `B>?CrY\C+]Þ>“ü7>)·œÂ=ùÞAžàpC€€=²ÁC€}‹=­„àÄO@ÇD^·z?‰Œç?uÁ#‹;¼³š;»»¬F’*F’*ÁÅ+ÁÅ+¼×^Î=äÖ»Œë¨=ÔF(½•)=§^ü¾ £ž>­© >6™‘@?lGF HÐBfbC’¢—CO_•>“ü7>)úÂ=ÿEAžëÈC€€=ÃùC€}N=¾ë5ÄcïDuQ?‰–6?zë’ÁØ;æG‰;äÑÆF’*F’*ÁÅ+ÁÅ+¼× )=äË»•|=ÔV`½•l =§­Ð¾ ­Í>­< >;t@?óãF öýB‹6ˆC±vdCzøF>“ü7>)Ç{Â>ÔAžïLC€þ=טÏC€} =ÒÐÄz¿ûD†Æá?‰™H?€|CÁÖƒ< Ë < ¬ôF’*G5ö´ÁÅ+Á:ºŸ¼Õø=äó»´=Ô\T½•¢½=§ê»¾ ¯ô>­u >jöq@?Žò­FXãB¨ÈªC×(tC˜#Ã>“IÕ=ë7ÁÂ=dÇA]3C€ö=£ïÄC€|¼=ŸûLÄÇÝzDŽY’?6T¯?ƒ•kÁ¢<,á-<+3”F’*G5ö´ÁÅ+Á:ºŸ¼—rb=ší×»]¢k=’¼Î½Eú)=N$¾^c >4€ ?Öý@?>%F±B¦Î{CÔ£2C–[>wcA=… Â7'eAþC€€Ô=BoC€~¶=A'KÅ(éÞD`|r>ª­?†Á²Áµ<0t}<.¼¬G5ö´G5ö´Á:ºŸÁ:ºŸ¼,‹Ô="šÀ»´µI=àß¼·o5SD©=(Î*Â;Ô @Ó+IC€€ÿ=ZC€Z=–ÅH£}Dèß>JÁÆ?ŠÁ,]<þ~<ÌÖG5ö´G5ö´Á:ºŸÁ:ºŸ»‡ T<ĨW»‹N<½|¼€:6<+¸<½….Œ<ƒTÏ > Ê1@?¾C„Eëü;BNxdCƒ™xC:>Géù<íº¿Â:d@œ,ÒC€:<ËôC€R<ÈõRÅMV$CãB> ªM?U}Á;ô";òYÓGrâ‡G’®Á?¾áÁC‘ »!º<ˆ¦ñ»ñ<ƒ[¼¼Rç\< ŵ½-wÓ<#} ={Ò@?ÑJEEÜ6MB*Á,CY«”Cê…>C$ô<·Ù~Â9ï+@vÓ3C€€è<¬ >C€(<ªu¹ÅHŲC¥Ëí=ÓgB?½öÁën;Ø-®;ÖßyGrâ‡G’®Á?¾áÁC‘ »o‘™<ýi<„^Â8òÇ@6‚ÿC€&<‡A`C€S<†C=Å=šùCPªÃ=ŒÞG?”;xÁ‚Ì;­Ì;¬¿‰G’®G’®ÁC‘ÁC‘ »€æ€<¡gºËj<Ò¼ ‘B;°u¼¬{®;­ðB =Âý@?ý=µE¹@A’ÍB»"·B„S*>5K<·IÂ7Î’?Ö¿•C€<<'ÓC€Ñ<&ªÅ2ÈC\Ë=O|¡?—Î…ÁæÚ;\Ìh;\^G’®G’®ÁC‘ÁC‘ »¾Í±;˜b:;—5T»½Yµ;‡>U»²1; =L\@@ HWE¦:àAªBØÈB™Iþ>*ý;áËG’®G»+¿ÁC‘ÁGB¥ ¼W<;Ûã3ºêÀe;Ù_qºmåj;†ð<‡¡^;ˆD @u`˜@@5úE˜úŸAþôBK·«B Ì>5 ;×[ñÂçXº@@(ˆ-EŒãÕA-5ÿBm-ÇB'µô>?ñ<Â1Ûê?®§˜C€€.<@¢wC€€üC®#@@9b˜EËì@ôR1B2úAû×#>Dœ;Ÿê(Â6X§?WXŽC€é<’ C€€f<:ÈÄ®¢·Aþm¼<º|?¦üÆÁ¼;êÒ;¯çH ª3H?QÁN5ÁNåv9ο™;=xº³;5 º©:K;ÿ»ÍÃ;3 >ÝH@@KìtEiÐà@}AÔ;¬A–K>AM|;Y øÂ3 Ÿ?ÌâC€ý;Á¬?C€ù;Áí‹Ä‰ A´8<¨K?«›Áëv:¨[ :¨ ½H ª3H9´ÁN5ÁSI%¸£âš:ùÛu¸¨¢:ù~Í:½Ñ::ç˜;T§:æì& =¿Ùç@@`PæEȘ@¡'mAþÎŽA´,ø>A˱;‹¡(Â8¶ˆ?97rC€€š< =GC€ù< gmÄWÿA’ <­M?¯#KÁ 3¨:Ó—):ÓcH,ëÃH9´ÁQíÁSI!%ºy]Í;#EÕ¹ƒ‰;!C`ºK(t;àÐ;Žãf;, >Lìß@@v¿dEAC@'¢jAŠþÁAD‘>F ;M Â4¼K>¿Ã)C€º; Å±C€ý; žiÄ=ÐøA»JF÷o:Ö­àÂ18>ŠkZC€€;€!ßC€€;€žLÄ&¼@Ùf²<'Í?·¯§Á â®:<°v:<ËHEãŽHn$ÁTDÔÁW|J)9:P(:}}¸ 6ù:{µ<:cÒ(:j*óº½F´:h–H =U@@•HFE`@ qAld_A''‰>G²Æ; ;ŽÂ3îl>°[@C€ü;¶ýC€€;¶¾Ä…ô@¢ßÝ<"6?¼‘Á Ð:gÅì:gf™HtDKH…”ÁWí4ÁYjŽ;E9ìŽ:£÷E¹À·Á:¥3Ÿ7"B°:”ªö;'‹:•І2?S€@@¤5çE–œ?Š™Aðé@º—Ä>I­7:”v™Â36 >=>ÀC€ò;W*ýC€>;WfÚÃä-@HIp:ŒTFÂ2ë¥>4\ôC€€S;_«zC€€I;_þÒö×Ü@ ¾;Å Ý?ÅLÁn'9þ]ª9þmêH“¸5H e˜Á[;Á\©9Sa9´ô:)f¹×*:'^ž¹Fß:3:²ÄŸ:‡u =8ä‡@@ƱÞDæ6ú?$}ñ@¬¡@sIq>JdÂ:R”fÂ49¡>ƒ C€€¢;8¯wC€º;8 šÃ›Vk? º;„q5?ÊÁ›ã9Æßu9ÆWêH¡çH´^Á\ºÁ^³ ayº2Ë;9÷ø˜8=>¥9ö¯è¸4ç`9澺‚# 9ää3# <=º@@ÚuDÍýÕ>ÈsÛ@]K+@zm>I¸: ÜfÂ3¾É=¶Ž?C€€+; yðC€½; …ŽÃ}æP?;R0;<Þá?ÎíSÁ­u9†þ‚9‡uÌH³ÌHÆgãÁ^žÁ`Zúw‘ºLô9¦¦’¹=à9£Â·š‹9¡Mc9öN9ž‹u' ;Ú71@@ðk´D¸{i>^£_?ÿf?´[‡>Jë©9©&JÂ4’µ=TK‚C€å:²ù¢C€ù:²Ó7ÃRnÛ?ÖÌ;¼Ü?ÓêµÀý†9'ž?9'ÌNHÂÖùHÛ´=Á` QÁb q‹±9‘à9KÝ`7M°9Lxý¸Þ¨¥9@x;¹Ê9A * ‰€A@$ÛŸ?é$ï>KeW9æ26Â3“¦=‘²C€€;ª[C€×;ÀÃ.B>Ì; W?ÙåÀù™,9hÞ9gàHÝÎÞHõzÀÁbJÔÁd Ƴݹ¤5B9‰G©7mZ9Š> 9Œwÿ9òa¹ÿ˜d9‚èŸ. ;r{ö@At]D’ÀŠ>;|+?ì°1?§]&>K 9¯PMÂ3à‘=\´C€é:à¸gC€µ:à‰à °Ï>ƒ»4:î~?ÞB Àõ’î91'91žØHðËKI(äÁc¸Áex%Ó¹gÿ9PÜ9='9OÞhµp¼9IÁÖ9®¾9I²/3 ;*I±@A D‚¬X>d–?Á¨Ý?ˆð#>KF·9—ÿÂ4ó==¡C€ð:ÔÖÖC€€:ÔÕžÂè€>:Z:Í…E?ãž©ÀñŠÉ9ÎH9ЉI¥IFáÁeECÁg÷ý=8q-98Ïô·ã¹Q98þÏ67£G947b9”±94w8:‰JØ@A0Dhh„=Ù&?—!?Uº–>K°M9tÄ/Â4C&=kßC€€:¾`œC€€:¾N¾Â½© =ûCã:©“š?éÈÀíw9°ó9ú°I¬YIÍåÁfÊÁh‡e/y86-Î9s§¸çÍ'9•¥¸„©9ÕÛ8š¿Š9L> ;;k@AA™šDNXy=¤ÂÍ?p-¤?)Ôê>KÅú9PˆÂ44=ÐdC€€ :±»C€ÿ:±µ#™ÈÓ=§õ„:‹ÌH?îºÉÀéU8ݼ8ÞwI÷¯I/9ÁhS¨Áj8°mѸ™@9]í·“§:8ÿýݸŸ‰Á8ø#¿9{ß›8÷ƒŽD :ðß^@ATõÃD7{=l·E?3ü_>þ‰Ô>KÖ|9.#WÂ4)r<Ø›C€€5:¢æ…C€ë:¢ÜUÂyBz=Ph}:V 7?ô|}Àå-Õ8³V8´I,) I=PÁiî”Ák™h½)¹i8Ò½a·Þf8Ôh7¸"9-8Éþ9{Tñ8ˬŸJ :psÔ@AjAŠD"b¬=”/>×ng>˜U9>Lô8×FcÂ47<†ÌýC€÷:^F8C€ü:^CåÂIÓ<éÂ:°?úaºÀá18e„)8fë„I²Ã²>|Ϥ>LMX8¬(ÇÂ4ˆ”é´>R˜;>LD¢8ºÜÞÂ4ßYëã>þ>L¤8~óXÂ4<(êC€Ù:/*ðC€ü:/(ãÁÏÄt<uE9¶ì@w«ÀÔƒÅ8ñÑ8pIqÁtI…j¨ÁoÔXÁq‹Cµ±8—KÓ8m·:58M ¸V:8/o¸¸”£8rÂm :LI}@A«|³CÈýë<,ß|=Ø[=˜Ì±>Mÿj8’’Â4 ï<6KMC€ø:]XÆC€€:]VOÁ¤ª·?$Ê/=v@ µÀÀÐV17ñ97ív I„5{Iœ^ÁqbÓÁrñ’©¸ÅG81˜a7‰y81ûû7]4Ì8$ÔZ¸à* 8&š2 :7Nå@A¼¢ÅC²áu<.=»Ÿz=„«b>N·8~yòÂ4Ì<¿C€ð:TZC€ÿ:TQÁuÙ>Òtó<Ð4@ ÙÀÌI˜7è½·7ég±IIœµ%ÁrÂ~ÁtVÖ{Õ5Þ!—8`ÿ5’ë8½W8^ËÛ8¢Ê¸x¶;84“2 9ª¸@AÏÙCŸŸ >$ÔT@Ov?‘°£>M«–:—@HÂ4Ì><ïC€ð<Š˜wC€ÿ<Š—ÉÁG‚Ì>‘‘@<ºÈs@nrÀÈTi:‹Ë:~ëI›ßI©*tÁt'Áu« -5Äad:6uø:m‰Ö:7i¹À?9:'+ã:ö:(:ž22>|be@LÍÚAä?ÕCŽ‹x>jÝ@Žñƒ?Ï—”>J¥‡:ôþÂ4Ì>šfèC€<õï¾C€€î<õî‡Á!ú >Ujª<¨¥º@ê ÀÄf:e•:dÞ/I¨HþI¸[ÎÁu“ÒÁw)‚ º^Râ:”M繆Úr:•D!9ޏY:}j:ý_“:¶'2 >9\ä@òÂzAûC€Õ> Þ @; Î?yI>J¥‡:ªÖdÂ4Ì>WU§C€€Â<¼¥BC€-<¼¤RÀú÷…>º–<’œ€@{ ÀÀ®h:Ý·:Ø…I¶XÆIÇãdÁvø¶Áx‘- ¯ :qÞú:Må9áö:Nk§9Oa:LT¹ÀRf:Mñ22>K‘ AnÞB BCg€Š>b—@_%?‹i&>Lgc:Öw8Â3}>†¤^C€Ì=C€€#=®`ÀÂnÄ=Ã×+<€íC@";À½*:4¤E:4|IIÅúYIÙ"ôÁxfxÁzB ½¡¹sÖ]:ƒ ã8§ã7:„b¹Oùa:rÉ»:Uƒ:sTy7 =°¡UA#íÓBæbCQÜ]=Æ,T@!±Æ?Ay>Lœ›:¥xÂ3×#>QTñC€Ì<Þ±gC€€#<ÞºÀ•Î=Šv,¥:>BIÖ›Ië‘ÁyÍÁ{k'¹oñÖ:M;­¹Eo:L9\@:L(.º $:KH= =[¶A2Ï9B'C?®Œ=]A”?Ƨî>âaê>MIm:TgŠÂ4Ô>âjC€G¶­_>MIm:A9ÝÂ4Ô=ñISC€€µ<œ¢×C€ <œ #À4êÙ<ÜÐé<:@&¡ À³ª 9‡¹9†æ©Iý™âJ .Á|³ŸÁ~n$«Õ·±ì„9î1&¹"ã09ïO|9 eP9ëv"º “79ìà«I =ªrs>LÛg:I%pÂ3ö4=ý®™C€ž<´ûC€õ<´­À …™<²<ˆ@*¥¨À°íÚ9T”9YˆJ aŠJz˜Á~8IÁ€f ]·Õl–9úk½·X199ùb¸‹‡9úAl7fÕ9ù±zQ :âÜæAo†ƒB^eCý=´5?¡TC>žÙl>Lôœ:UÆìÂ3ö4>¦C€ž<Ò[vC€õ<Ò]t¿ÔÜY<_ }<y[@.ÃÀ®uº9w=9v¹JpuJ(w•ÁÉNÁ€Ñ–]%ù8SM:B7¬{:ÉW8x¼:4úºɵ: hY <³“ÒA„Bt¢ìC<2<ˆî?5(:>)q9>Lôœ:õÂ3ö4=¢¾,C€ž<‹Ì¤C€õ<‹Íô¿ Æ$< Qž;Ú§@2ùçÀ¬=•9×g9¡ïJ& ÀJ9€GÁ€²Á§Ä$Å-ñ8ŸÁŸ9 þ󏻨F9 o”8Ÿ T9 Éo¸©09 lUb2=Vç˜A’O¥B†ŒÏCnÄ>/>Mcë: ÐËÂ3ö4=­‡C€ž<¥zâC€õ<¥|¢¿sÎÙ;¶mï;¿V@7J¾ÀªGÈ8ý·8üJ6qKJM8{Á‚ÌÁ‚ˆg,S7©8´x9¬ŽM´êò9­ï˜7P-z9«™H9ÅD9¬·Ýj <¯Þ9A£€UB”JBÿª·÷¥>KðÁ: »óÂ3ö4=®L’C€€0<·C€c<·S¿8 ;n-Ï;¥—S@;¶9À¨ˆ8ÜßB8ÜÈrJIÌyJc†ÜÁ‚cÁƒmÖ5ÇC)¸8Ûÿ9­)¤·=÷E9®óÜ6%í»9­Ä9%9­úòq ;Î4A¸Ê˜B¢Î8BôËÚ<…? ó=Μ`>L˜:«=Â3ö4=žäaC€€j<¸*SC€¡<¸-¿ DT;#€;˜´N@@<ýÀ§¡8¬ @8«ý™J_æßJ~µÁƒJ Á„cAQi¶ ÷9Ÿ'z8—Ù9žùI8(šÂ9˜0:€×d9—4*w ;¶AÔI%B³ Bëò®;¾û¶>¸a=„aµ>LÆ£9ÄÔ9Â3ö4=qL¶C€€j<š|C€¡<š~ɾÌÁ:ÊFÂ;|æÿ@Dß²À¥¾/8a«08`T„Jy‰-JŽetÁ„;'Á…aN¿bi8™~y9r£Ù¶ª6…9qœa¸¬IŠ9ož*9«Nq9pTÀ{ ;dçÀAøLÏBÄþ¦Bä«{;}¬:>†ì™=1÷„>L®]9“øÂ3ö4=8‘ÅC€[<¼C€€®< ¾—",:wÃ;X]?@IŸÀ¤§8(8J‹ÓVJ ¬_Á…8‚Á†m‰_Yw=8‡-k97à 8>› 97EH8øÛ97Co¹€96Åè~ ;¨aDB$ÄBر·BÞ¾Ú;#}ë>?NÙ<åf">L®]9‘fÂ3ö4=5\úC€€Y<‹p)C€±<‹r¿¾^Y:;60@N{¦À£¾ 7Íèe7Ê!ìJc¡J¶ !Á†?Á‡ƒ'sG)¸ êc94§1¸"غ94+‘·þÚ«94–h¸.žC94¡~ ;š B2 ÙBî]BÙó/:úEr>! :<¯”œ>M%9‚©ãÂ4:D="¿4C€€Y<‰è9C€±<‰Øþ¾#ŒÎ9Ñ:Ž;#¿ñ@SvJÀ¢üt7 ºm7žßJ²…JÏdEÁ‡R™Áˆ¥‹[®M¶s{9"u¢·¨=9"v7;»9"K…¸ +Ã9!ÜN~ <÷€BWX)C™BÖò:ø÷5>079<®ª>M%9uuÂ3ä™=ÝC€€Y<Žp¿C€±<Žx&½îo69„à&;ª#@XªÀ¢\Û7¢7¡;£JÊÚÆJíÅzÁˆsäÁ‰Õ ¨±Òý·àÖ39wŽ8ƒÄW9:8ðB9‹à9 -p9$~ ;F¢õB‚H›C5ÂBÒ÷ò:–¿¥=ê LÝ¥9®ÏÂ4È<ÇsC€€YLÚ,9fÂ3û­<ÄQ®C€S<].éC€€·<]0¸½wñ8Õ -:ÛùÊ@c!À¡rA2–½²–½K¶lK¨NÁŠÚaÁŒV¼÷ 4Ñ8¿8ðÈ5cçI8Ã*Ûµ½mÛ8ÀÛb¹7ƒ8ÀWq~ :†©B¾ÈvC.~}BÎ<:îb0>`–Ž<§=”>Lç§9 é[Â3û­<È„ÈC€€ -_LÁÀ8ëäÂ3û­<’Ü„C€€ ¸»<(EV>LËp8ã²"Â3û­<ðEC€€ U÷)Láæ8ÒØÂ3þÉ<‚èC€ä@yØ-À 87hpe7lYKvÂìK•”hÁ,ÖÁ‘Ùƒ–)7 8‚”j5+oü8‚; ¶Ét`8‚>8N Ž8äñ~ 8ZÚÞCLyqCzBÊ):®½>pÝÏLÝ¥8š¨Â3þÉL¿â8¥1DÂ4<–ÌC€õ<}XTC€Û<}UÑ»ðÙÓ@ƒÀ GY³ñýL3ñýLK«êÏKÆ …Á“|Á”I ]ŒK¶ì7l8‹ì5û*8OšÓ·nDl8m]Ö8)k8lzqK3 7óRQC•¶Cš@BÉ1';/ ‡>¨°ƒ<Ì­>L¿â8€ ‹Â4<¯[C€õ<‹òC€Û<‹ïý»¥`…8µ2ª<Œ>Ä@†-ÌÀ 4Ú7ð?¯7óG{KÁçKÓ›(Á”íÁ”Ü[r¥Ñc¶f 8Hòê7¼V8H= 1.: aux = saux return abs(a ** 2 * (1. - eps) / 2. * math.acos(aux)) def test_angles(phi_min=0.05, phi_max=0.2): a = 40. astep = 1.1 eps = 0.1 # r = a a1 = a * (1. - ((1. - 1. / astep) / 2.)) a2 = a * (1. + (astep - 1.) / 2.) r3 = a2 r4 = a1 aux = min((a2 - a1), 3.) sarea = (a2 - a1) * aux dphi = max(min((aux / a), phi_max), phi_min) phi = dphi / 2. phi2 = phi - dphi / 2. aux = 1. - eps r3 = a2 * aux / np.sqrt((aux * np.cos(phi2))**2 + (np.sin(phi2))**2) r4 = a1 * aux / np.sqrt((aux * np.cos(phi2))**2 + (np.sin(phi2))**2) ncount = 0 while phi < np.pi*2: phi1 = phi2 r1 = r4 r2 = r3 phi2 = phi + dphi / 2. aux = 1. - eps r3 = a2 * aux / np.sqrt((aux * np.cos(phi2))**2 + (np.sin(phi2))**2) r4 = a1 * aux / np.sqrt((aux * np.cos(phi2))**2 + (np.sin(phi2))**2) sa1 = sector_area(a1, eps, phi1, r1) sa2 = sector_area(a2, eps, phi1, r2) sa3 = sector_area(a2, eps, phi2, r3) sa4 = sector_area(a1, eps, phi2, r4) area = abs((sa3 - sa2) - (sa4 - sa1)) # Compute step to next sector and its angular span dphi = max(min((sarea / (r3 - r4) / r4), phi_max), phi_min) phistep = dphi / 2. + phi2 - phi ncount += 1 assert 11.0 < area < 12.4 phi = phi + min(phistep, 0.5) # r = (a * (1. - eps) / np.sqrt(((1. - eps) * np.cos(phi))**2 + # (np.sin(phi))**2)) assert ncount == 72 photutils-0.7.2/photutils/isophote/tests/test_ellipse.py0000644000214200020070000001330313563423715026044 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the ellipse module. """ import math from astropy.io import fits from astropy.modeling.models import Gaussian2D import numpy as np import pytest from .make_test_data import make_test_image from ..ellipse import Ellipse from ..geometry import EllipseGeometry from ..isophote import Isophote, IsophoteList from ...datasets import get_path, make_noise_image try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False # define an off-center position and a tilted sma POS = 384 PA = 10. / 180. * np.pi # build off-center test data. It's fine to have a single np array to use # in all tests that need it, but do not use a single instance of # EllipseGeometry. The code may eventually modify it's contents. The safe # bet is to build it wherever it's needed. The cost is negligible. OFFSET_GALAXY = make_test_image(x0=POS, y0=POS, pa=PA, noise=1.e-12, random_state=123) @pytest.mark.skipif('not HAS_SCIPY') class TestEllipse: def setup_class(self): # centered, tilted galaxy self.data = make_test_image(pa=PA, random_state=123) @pytest.mark.remote_data def test_find_center(self): path = get_path('isophote/M51.fits', location='photutils-datasets', cache=True) hdu = fits.open(path) data = hdu[0].data hdu.close() geometry = EllipseGeometry(252, 253, 10., 0.2, np.pi/2) geometry.find_center(data) assert geometry.x0 == 257. assert geometry.y0 == 258. def test_basic(self): ellipse = Ellipse(self.data) isophote_list = ellipse.fit_image() assert isinstance(isophote_list, IsophoteList) assert len(isophote_list) > 1 assert isinstance(isophote_list[0], Isophote) # verify that the list is properly sorted in sem-major axis length assert isophote_list[-1] > isophote_list[0] # the fit should stop where gradient loses reliability. assert len(isophote_list) == 69 assert isophote_list[-1].stop_code == 1 def test_linear(self): ellipse = Ellipse(self.data) isophote_list = ellipse.fit_image(linear=True, step=2.) # verify that the list is properly sorted in sem-major axis length assert isophote_list[-1] > isophote_list[0] # difference in sma between successive isohpotes must be constant. step = isophote_list[-1].sma - isophote_list[-2].sma assert math.isclose((isophote_list[-2].sma - isophote_list[-3].sma), step, rel_tol=0.01) assert math.isclose((isophote_list[-3].sma - isophote_list[-4].sma), step, rel_tol=0.01) assert math.isclose((isophote_list[2].sma - isophote_list[1].sma), step, rel_tol=0.01) def test_fit_one_ellipse(self): ellipse = Ellipse(self.data) isophote = ellipse.fit_isophote(40.) assert isinstance(isophote, Isophote) assert isophote.valid def test_offcenter_fail(self): # A first guess ellipse that is centered in the image frame. # This should result in failure since the real galaxy # image is off-center by a large offset. ellipse = Ellipse(OFFSET_GALAXY) isophote_list = ellipse.fit_image() assert len(isophote_list) == 0 def test_offcenter_fit(self): # A first guess ellipse that is roughly centered on the # offset galaxy image. g = EllipseGeometry(POS+5, POS+5, 10., eps=0.2, pa=PA, astep=0.1) ellipse = Ellipse(OFFSET_GALAXY, geometry=g) isophote_list = ellipse.fit_image() # the fit should stop when too many potential sample # points fall outside the image frame. assert len(isophote_list) == 63 assert isophote_list[-1].stop_code == 1 def test_offcenter_go_beyond_frame(self): # Same as before, but now force the fit to goo # beyond the image frame limits. g = EllipseGeometry(POS+5, POS+5, 10., eps=0.2, pa=PA, astep=0.1) ellipse = Ellipse(OFFSET_GALAXY, geometry=g) isophote_list = ellipse.fit_image(maxsma=400.) # the fit should go to maxsma, but with fixed geometry assert len(isophote_list) == 71 assert isophote_list[-1].stop_code == 4 # check that no zero-valued intensities were left behind # in the sample arrays when sampling outside the image. for iso in isophote_list: assert not np.any(iso.sample.values[2] == 0) def test_ellipse_shape(self): """Regression test for #670/673.""" ny = 500 nx = 150 g = Gaussian2D(100., nx / 2., ny / 2., 20, 12, theta=40.*np.pi/180.) y, x = np.mgrid[0:ny, 0:nx] noise = make_noise_image((ny, nx), distribution='gaussian', mean=0., stddev=2., random_state=12345) data = g(x, y) + noise ellipse = Ellipse(data) # estimates initial center isolist = ellipse.fit_image() assert len(isolist) == 54 @pytest.mark.remote_data @pytest.mark.skipif('not HAS_SCIPY') class TestEllipseOnRealData: def test_basic(self): path = get_path('isophote/M105-S001-RGB.fits', location='photutils-datasets', cache=True) hdu = fits.open(path) data = hdu[0].data[0] hdu.close() g = EllipseGeometry(530., 511, 30., 0.2, 20./180.*3.14) ellipse = Ellipse(data, geometry=g) isophote_list = ellipse.fit_image() assert len(isophote_list) >= 60 # check that isophote at about sma=70 got an uneventful fit assert isophote_list.get_closest(70.).stop_code == 0 photutils-0.7.2/photutils/isophote/tests/test_fitter.py0000644000214200020070000001656413563423715025720 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the fitter module. """ from astropy.io import fits import numpy as np from numpy.testing import assert_allclose import pytest from .make_test_data import make_test_image from ..fitter import CentralEllipseFitter, EllipseFitter from ..geometry import EllipseGeometry from ..harmonics import fit_first_and_second_harmonics from ..integrator import MEAN from ..isophote import Isophote from ..sample import CentralEllipseSample, EllipseSample from ...datasets import get_path try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False DATA = make_test_image(random_state=123) DEFAULT_POS = 256 DEFAULT_FIX = np.array([False, False, False, False]) def test_gradient(): sample = EllipseSample(DATA, 40.) sample.update(DEFAULT_FIX) assert_allclose(sample.mean, 200.02, atol=0.01) assert_allclose(sample.gradient, -4.222, atol=0.001) assert_allclose(sample.gradient_error, 0.0003, atol=0.0001) assert_allclose(sample.gradient_relative_error, 7.45e-05, atol=1.e-5) assert_allclose(sample.sector_area, 2.00, atol=0.01) @pytest.mark.skipif('not HAS_SCIPY') def test_fitting_raw(): """ This test performs a raw (no EllipseFitter), 1-step correction in one single ellipse coefficient. """ # pick first guess ellipse that is off in just # one of the parameters (eps). sample = EllipseSample(DATA, 40., eps=2*0.2) sample.update(DEFAULT_FIX) s = sample.extract() harmonics = fit_first_and_second_harmonics(s[0], s[2]) y0, a1, b1, a2, b2 = harmonics[0] # when eps is off, b2 is the largest (in absolute value). assert abs(b2) > abs(a1) assert abs(b2) > abs(b1) assert abs(b2) > abs(a2) correction = (b2 * 2. * (1. - sample.geometry.eps) / sample.geometry.sma / sample.gradient) new_eps = sample.geometry.eps - correction # got closer to test data (eps=0.2) assert_allclose(new_eps, 0.21, atol=0.01) @pytest.mark.skipif('not HAS_SCIPY') def test_fitting_small_radii(): sample = EllipseSample(DATA, 2.) fitter = EllipseFitter(sample) isophote = fitter.fit() assert isinstance(isophote, Isophote) assert isophote.ndata == 13 @pytest.mark.skipif('not HAS_SCIPY') def test_fitting_eps(): # initial guess is off in the eps parameter sample = EllipseSample(DATA, 40., eps=2*0.2) fitter = EllipseFitter(sample) isophote = fitter.fit() assert isinstance(isophote, Isophote) g = isophote.sample.geometry assert g.eps >= 0.19 assert g.eps <= 0.21 @pytest.mark.skipif('not HAS_SCIPY') def test_fitting_pa(): data = make_test_image(pa=np.pi/4, noise=0.01, random_state=123) # initial guess is off in the pa parameter sample = EllipseSample(data, 40) fitter = EllipseFitter(sample) isophote = fitter.fit() g = isophote.sample.geometry assert g.pa >= (np.pi/4 - 0.05) assert g.pa <= (np.pi/4 + 0.05) @pytest.mark.skipif('not HAS_SCIPY') def test_fitting_xy(): pos = DEFAULT_POS - 5 data = make_test_image(x0=pos, y0=pos, random_state=123) # initial guess is off in the x0 and y0 parameters sample = EllipseSample(data, 40) fitter = EllipseFitter(sample) isophote = fitter.fit() g = isophote.sample.geometry assert g.x0 >= (pos - 1) assert g.x0 <= (pos + 1) assert g.y0 >= (pos - 1) assert g.y0 <= (pos + 1) @pytest.mark.skipif('not HAS_SCIPY') def test_fitting_all(): # build test image that is off from the defaults # assumed by the EllipseSample constructor. pos = DEFAULT_POS - 5 angle = np.pi / 4 eps = 2 * 0.2 data = make_test_image(x0=pos, y0=pos, eps=eps, pa=angle, random_state=123) sma = 60. # initial guess is off in all parameters. We find that the initial # guesses, especially for position angle, must be kinda close to the # actual value. 20% off max seems to work in this case of high SNR. sample = EllipseSample(data, sma, position_angle=(1.2 * angle)) fitter = EllipseFitter(sample) isophote = fitter.fit() assert isophote.stop_code == 0 g = isophote.sample.geometry assert g.x0 >= (pos - 1.5) # position within 1.5 pixel assert g.x0 <= (pos + 1.5) assert g.y0 >= (pos - 1.5) assert g.y0 <= (pos + 1.5) assert g.eps >= (eps - 0.01) # eps within 0.01 assert g.eps <= (eps + 0.01) assert g.pa >= (angle - 0.05) # pa within 5 deg assert g.pa <= (angle + 0.05) sample_m = EllipseSample(data, sma, position_angle=(1.2 * angle), integrmode=MEAN) fitter_m = EllipseFitter(sample_m) isophote_m = fitter_m.fit() assert isophote_m.stop_code == 0 @pytest.mark.remote_data @pytest.mark.skipif('not HAS_SCIPY') class TestM51: def setup_class(self): path = get_path('isophote/M51.fits', location='photutils-datasets', cache=True) hdu = fits.open(path) self.data = hdu[0].data hdu.close() def test_m51(self): # here we evaluate the detailed convergence behavior # for a particular ellipse where we can see the eps # parameter jumping back and forth. # sample = EllipseSample(self.data, 13.31000001, eps=0.16, # position_angle=((-37.5+90)/180.*np.pi)) # sample.update() # fitter = EllipseFitter(sample) # isophote = fitter.fit() # we start the fit with initial values taken from # previous isophote, as determined by the old code. # sample taken in high SNR region sample = EllipseSample(self.data, 21.44, eps=0.18, position_angle=(36./180.*np.pi)) fitter = EllipseFitter(sample) isophote = fitter.fit() assert isophote.ndata == 119 assert_allclose(isophote.intens, 685.4, atol=0.1) # last sample taken by the original code, before turning inwards. sample = EllipseSample(self.data, 61.16, eps=0.219, position_angle=((77.5+90)/180*np.pi)) fitter = EllipseFitter(sample) isophote = fitter.fit() assert isophote.ndata == 382 assert_allclose(isophote.intens, 156.3, atol=0.1) def test_m51_outer(self): # sample taken at the outskirts of the image, so many # data points lay outside the image frame. This checks # for the presence of gaps in the sample arrays. sample = EllipseSample(self.data, 330., eps=0.2, position_angle=((90)/180*np.pi), integrmode='median') fitter = EllipseFitter(sample) isophote = fitter.fit() assert not np.any(isophote.sample.values[2] == 0) def test_m51_central(self): # this code finds central x and y offset by about 0.1 pixel wrt the # spp code. In here we use as input the position computed by this # code, thus this test is checking just the extraction algorithm. g = EllipseGeometry(257.02, 258.1, 0.0, 0.0, 0.0, 0.1, False) sample = CentralEllipseSample(self.data, 0.0, geometry=g) fitter = CentralEllipseFitter(sample) isophote = fitter.fit() # the central pixel intensity is about 3% larger than # found by the spp code. assert isophote.ndata == 1 assert isophote.intens <= 7560. assert isophote.intens >= 7550. photutils-0.7.2/photutils/isophote/tests/test_geometry.py0000644000214200020070000001140513563423715026243 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the geometry module. """ import numpy as np from numpy.testing import assert_allclose import pytest from ..geometry import EllipseGeometry @pytest.mark.parametrize('astep, linear_growth', [(0.2, False), (20., True)]) def test_geometry(astep, linear_growth): geometry = EllipseGeometry(255., 255., 100., 0.4, np.pi/2, astep, linear_growth) sma1, sma2 = geometry.bounding_ellipses() assert_allclose((sma1, sma2), (90.0, 110.0), atol=0.01) # using an arbitrary angle of 0.5 rad. This is to avoid a polar # vector that sits on top of one of the ellipse's axis. vertex_x, vertex_y = geometry.initialize_sector_geometry(0.6) assert_allclose(geometry.sector_angular_width, 0.0571, atol=0.01) assert_allclose(geometry.sector_area, 63.83, atol=0.01) assert_allclose(vertex_x, [215.4, 206.6, 213.5, 204.3], atol=0.1) assert_allclose(vertex_y, [316.1, 329.7, 312.5, 325.3], atol=0.1) def test_to_polar(): # trivial case of a circle centered in (0.,0.) geometry = EllipseGeometry(0., 0., 100., 0.0, 0., 0.2, False) r, p = geometry.to_polar(100., 0.) assert_allclose(r, 100., atol=0.1) assert_allclose(p, 0., atol=0.0001) r, p = geometry.to_polar(0., 100.) assert_allclose(r, 100., atol=0.1) assert_allclose(p, np.pi/2., atol=0.0001) # vector with length 100. at 45 deg angle r, p = geometry.to_polar(70.71, 70.71) assert_allclose(r, 100., atol=0.1) assert_allclose(p, np.pi/4., atol=0.0001) # position angle tilted 45 deg from X axis geometry = EllipseGeometry(0., 0., 100., 0.0, np.pi/4., 0.2, False) r, p = geometry.to_polar(100., 0.) assert_allclose(r, 100., atol=0.1) assert_allclose(p, np.pi*7./4., atol=0.0001) r, p = geometry.to_polar(0., 100.) assert_allclose(r, 100., atol=0.1) assert_allclose(p, np.pi/4., atol=0.0001) # vector with length 100. at 45 deg angle r, p = geometry.to_polar(70.71, 70.71) assert_allclose(r, 100., atol=0.1) assert_allclose(p, np.pi*2., atol=0.0001) def test_area(): # circle with center at origin geometry = EllipseGeometry(0., 0., 100., 0.0, 0., 0.2, False) # sector at 45 deg on circle vertex_x, vertex_y = geometry.initialize_sector_geometry(45./180.*np.pi) assert_allclose(vertex_x, [65.21, 79.70, 62.03, 75.81], atol=0.01) assert_allclose(vertex_y, [62.03, 75.81, 65.21, 79.70], atol=0.01) # sector at 0 deg on circle vertex_x, vertex_y = geometry.initialize_sector_geometry(0) assert_allclose(vertex_x, [89.97, 109.97, 89.97, 109.96], atol=0.01) assert_allclose(vertex_y, [-2.25, -2.75, 2.25, 2.75], atol=0.01) def test_area2(): # circle with center at 100.,100. geometry = EllipseGeometry(100., 100., 100., 0.0, 0., 0.2, False) # sector at 45 deg on circle vertex_x, vertex_y = geometry.initialize_sector_geometry(45./180.*np.pi) assert_allclose(vertex_x, [165.21, 179.70, 162.03, 175.81], atol=0.01) assert_allclose(vertex_y, [162.03, 175.81, 165.21, 179.70], atol=0.01) # sector at 225 deg on circle vertex_x, vertex_y = geometry.initialize_sector_geometry(225./180.*np.pi) assert_allclose(vertex_x, [34.79, 20.30, 37.97, 24.19], atol=0.01) assert_allclose(vertex_y, [37.97, 24.19, 34.79, 20.30], atol=0.01) def test_reset_sma(): geometry = EllipseGeometry(0., 0., 100., 0.0, 0., 0.2, False) sma, step = geometry.reset_sma(0.2) assert_allclose(sma, 83.33, atol=0.01) assert_allclose(step, -0.1666, atol=0.001) geometry = EllipseGeometry(0., 0., 100., 0.0, 0., 20., True) sma, step = geometry.reset_sma(20.) assert_allclose(sma, 80., atol=0.01) assert_allclose(step, -20., atol=0.01) def test_update_sma(): geometry = EllipseGeometry(0., 0., 100., 0.0, 0., 0.2, False) sma = geometry.update_sma(0.2) assert_allclose(sma, 120., atol=0.01) geometry = EllipseGeometry(0., 0., 100., 0.0, 0., 20., True) sma = geometry.update_sma(20.) assert_allclose(sma, 120., atol=0.01) def test_polar_angle_sector_limits(): geometry = EllipseGeometry(0., 0., 100., 0.3, np.pi/4, 0.2, False) geometry.initialize_sector_geometry(np.pi/3) phi1, phi2 = geometry.polar_angle_sector_limits() assert_allclose(phi1, 1.022198, atol=0.0001) assert_allclose(phi2, 1.072198, atol=0.0001) def test_bounding_ellipses(): geometry = EllipseGeometry(0., 0., 100., 0.3, np.pi/4, 0.2, False) sma1, sma2 = geometry.bounding_ellipses() assert_allclose((sma1, sma2), (90.0, 110.0), atol=0.01) def test_radius(): geometry = EllipseGeometry(0., 0., 100., 0.3, np.pi/4, 0.2, False) r = geometry.radius(0.0) assert_allclose(r, 100.0, atol=0.01) r = geometry.radius(np.pi/2) assert_allclose(r, 70.0, atol=0.01) photutils-0.7.2/photutils/isophote/tests/test_harmonics.py0000644000214200020070000001461313572576702026404 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the harmonics module. """ import numpy as np from numpy.testing import assert_allclose import pytest from .make_test_data import make_test_image from ..harmonics import (first_and_second_harmonic_function, fit_first_and_second_harmonics, fit_upper_harmonic) from ..sample import EllipseSample from ..fitter import EllipseFitter try: from scipy.optimize import leastsq # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False @pytest.mark.skipif('not HAS_SCIPY') def test_harmonics_1(): # this is an almost as-is example taken from stackoverflow N = 100 # number of data points t = np.linspace(0, 4*np.pi, N) # create artificial data with noise: # mean = 0.5, amplitude = 3., phase = 0.1, noise-std = 0.01 data = 3.0 * np.sin(t + 0.1) + 0.5 + 0.01 * np.random.randn(N) # first guesses for harmonic parameters guess_mean = np.mean(data) guess_std = 3 * np.std(data) / 2**0.5 guess_phase = 0 # Minimize the difference between the actual data and our "guessed" # parameters # optimize_func = lambda x: x[0] * np.sin(t + x[1]) + x[2] - data def optimize_func(x): return x[0] * np.sin(t + x[1]) + x[2] - data est_std, est_phase, est_mean = leastsq( optimize_func, [guess_std, guess_phase, guess_mean])[0] # recreate the fitted curve using the optimized parameters data_fit = est_std * np.sin(t + est_phase) + est_mean residual = data - data_fit assert_allclose(np.mean(residual), 0., atol=0.001) assert_allclose(np.std(residual), 0.01, atol=0.01) @pytest.mark.skipif('not HAS_SCIPY') def test_harmonics_2(): # this uses the actual functional form used for fitting ellipses N = 100 E = np.linspace(0, 4*np.pi, N) y0_0 = 100. a1_0 = 10. b1_0 = 5. a2_0 = 8. b2_0 = 2. data = (y0_0 + a1_0*np.sin(E) + b1_0*np.cos(E) + a2_0*np.sin(2*E) + b2_0*np.cos(2*E) + 0.01*np.random.randn(N)) harmonics = fit_first_and_second_harmonics(E, data) y0, a1, b1, a2, b2 = harmonics[0] data_fit = (y0 + a1*np.sin(E) + b1*np.cos(E) + a2*np.sin(2*E) + b2*np.cos(2*E) + 0.01*np.random.randn(N)) residual = data - data_fit assert_allclose(np.mean(residual), 0., atol=0.01) assert_allclose(np.std(residual), 0.015, atol=0.01) @pytest.mark.skipif('not HAS_SCIPY') def test_harmonics_3(): """Tests an upper harmonic fit.""" N = 100 E = np.linspace(0, 4*np.pi, N) y0_0 = 100. a1_0 = 10. b1_0 = 5. order = 3 data = (y0_0 + a1_0*np.sin(order*E) + b1_0*np.cos(order*E) + 0.01*np.random.randn(N)) harmonic = fit_upper_harmonic(E, data, order) y0, a1, b1 = harmonic[0] data_fit = (y0 + a1*np.sin(order*E) + b1*np.cos(order*E) + 0.01*np.random.randn(N)) residual = data - data_fit assert_allclose(np.mean(residual), 0., atol=0.01) assert_allclose(np.std(residual), 0.015, atol=0.01) @pytest.mark.skipif('not HAS_SCIPY') class TestFitEllipseSamples: def setup_class(self): # major axis parallel to X image axis self.data1 = make_test_image(random_state=123) # major axis tilted 45 deg wrt X image axis self.data2 = make_test_image(pa=np.pi/4, random_state=123) def test_fit_ellipsesample_1(self): sample = EllipseSample(self.data1, 40.) s = sample.extract() harmonics = fit_first_and_second_harmonics(s[0], s[2]) y0, a1, b1, a2, b2 = harmonics[0] assert_allclose(np.mean(y0), 200.019, atol=0.001) assert_allclose(np.mean(a1), -0.000138, atol=0.001) assert_allclose(np.mean(b1), 0.000254, atol=0.001) assert_allclose(np.mean(a2), -5.658e-05, atol=0.001) assert_allclose(np.mean(b2), -0.00911, atol=0.001) # check that harmonics subtract nicely model = first_and_second_harmonic_function( s[0], np.array([y0, a1, b1, a2, b2])) residual = s[2] - model assert_allclose(np.mean(residual), 0., atol=0.001) assert_allclose(np.std(residual), 0.015, atol=0.01) def test_fit_ellipsesample_2(self): # initial guess is rounder than actual image sample = EllipseSample(self.data1, 40., eps=0.1) s = sample.extract() harmonics = fit_first_and_second_harmonics(s[0], s[2]) y0, a1, b1, a2, b2 = harmonics[0] assert_allclose(np.mean(y0), 188.686, atol=0.001) assert_allclose(np.mean(a1), 0.000283, atol=0.001) assert_allclose(np.mean(b1), 0.00692, atol=0.001) assert_allclose(np.mean(a2), -0.000215, atol=0.001) assert_allclose(np.mean(b2), 10.153, atol=0.001) def test_fit_ellipsesample_3(self): # initial guess for center is offset sample = EllipseSample(self.data1, x0=220., y0=210., sma=40.) s = sample.extract() harmonics = fit_first_and_second_harmonics(s[0], s[2]) y0, a1, b1, a2, b2 = harmonics[0] assert_allclose(np.mean(y0), 152.660, atol=0.001) assert_allclose(np.mean(a1), 55.338, atol=0.001) assert_allclose(np.mean(b1), 33.091, atol=0.001) assert_allclose(np.mean(a2), 33.036, atol=0.001) assert_allclose(np.mean(b2), -14.306, atol=0.001) def test_fit_ellipsesample_4(self): sample = EllipseSample(self.data2, 40., eps=0.4) s = sample.extract() harmonics = fit_first_and_second_harmonics(s[0], s[2]) y0, a1, b1, a2, b2 = harmonics[0] assert_allclose(np.mean(y0), 245.102, atol=0.001) assert_allclose(np.mean(a1), -0.003108, atol=0.001) assert_allclose(np.mean(b1), -0.0578, atol=0.001) assert_allclose(np.mean(a2), 28.781, atol=0.001) assert_allclose(np.mean(b2), -63.184, atol=0.001) def test_fit_upper_harmonics(self): data = make_test_image(noise=1.e-10, random_state=123) sample = EllipseSample(data, 40) fitter = EllipseFitter(sample) iso = fitter.fit(maxit=400) assert_allclose(iso.a3, -6.87e-7, atol=1.e-9) assert_allclose(iso.b3, 1.68e-6, atol=1.e-8) assert_allclose(iso.a4, -4.36e-6, atol=1.e-8) assert_allclose(iso.b4, 4.73e-5, atol=1.e-7) assert_allclose(iso.a3_err, 5.28e-5, atol=1.e-7) assert_allclose(iso.b3_err, 5.24e-5, atol=1.e-7) assert_allclose(iso.a4_err, 5.28e-5, atol=1.e-7) assert_allclose(iso.b4_err, 5.24e-5, atol=1.e-7) photutils-0.7.2/photutils/isophote/tests/test_integrator.py0000644000214200020070000001204313563423715026565 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the integrator module. """ from astropy.io import fits import numpy as np import numpy.ma as ma from numpy.testing import assert_allclose import pytest from ..integrator import BILINEAR, MEAN, MEDIAN, NEAREST_NEIGHBOR from ..sample import EllipseSample from ...datasets import get_path @pytest.mark.remote_data class TestData: def setup_class(self): path = get_path('isophote/synth_highsnr.fits', location='photutils-datasets', cache=True) hdu = fits.open(path) self.data = hdu[0].data hdu.close() def make_sample(self, masked=False, sma=40., integrmode=BILINEAR): if masked: data = ma.masked_values(self.data, 200., atol=10.0, rtol=0.) else: data = self.data sample = EllipseSample(data, sma, integrmode=integrmode) s = sample.extract() assert len(s) == 3 assert len(s[0]) == len(s[1]) assert len(s[0]) == len(s[2]) return s, sample @pytest.mark.remote_data class TestUnmasked(TestData): def test_bilinear(self): s, sample = self.make_sample() assert len(s[0]) == 225 # intensities assert_allclose(np.mean(s[2]), 200.76, atol=0.01) assert_allclose(np.std(s[2]), 21.55, atol=0.01) # radii assert_allclose(np.max(s[1]), 40.0, atol=0.01) assert_allclose(np.min(s[1]), 32.0, atol=0.01) assert sample.total_points == 225 assert sample.actual_points == 225 def test_bilinear_small(self): # small radius forces sub-pixel sampling s, sample = self.make_sample(sma=10.) # intensities assert_allclose(np.mean(s[2]), 1045.4, atol=0.1) assert_allclose(np.std(s[2]), 143.0, atol=0.1) # radii assert_allclose(np.max(s[1]), 10.0, atol=0.1) assert_allclose(np.min(s[1]), 8.0, atol=0.1) assert sample.total_points == 57 assert sample.actual_points == 57 def test_nearest_neighbor(self): s, sample = self.make_sample(integrmode=NEAREST_NEIGHBOR) assert len(s[0]) == 225 # intensities assert_allclose(np.mean(s[2]), 201.1, atol=0.1) assert_allclose(np.std(s[2]), 21.8, atol=0.1) # radii assert_allclose(np.max(s[1]), 40.0, atol=0.01) assert_allclose(np.min(s[1]), 32.0, atol=0.01) assert sample.total_points == 225 assert sample.actual_points == 225 def test_mean(self): s, sample = self.make_sample(integrmode=MEAN) assert len(s[0]) == 64 # intensities assert_allclose(np.mean(s[2]), 199.9, atol=0.1) assert_allclose(np.std(s[2]), 21.3, atol=0.1) # radii assert_allclose(np.max(s[1]), 40.0, atol=0.01) assert_allclose(np.min(s[1]), 32.0, atol=0.01) assert_allclose(sample.sector_area, 12.4, atol=0.1) assert sample.total_points == 64 assert sample.actual_points == 64 def test_mean_small(self): s, sample = self.make_sample(sma=5., integrmode=MEAN) assert len(s[0]) == 29 # intensities assert_allclose(np.mean(s[2]), 2339.0, atol=0.1) assert_allclose(np.std(s[2]), 284.7, atol=0.1) # radii assert_allclose(np.max(s[1]), 5.0, atol=0.01) assert_allclose(np.min(s[1]), 4.0, atol=0.01) assert_allclose(sample.sector_area, 2.0, atol=0.1) assert sample.total_points == 29 assert sample.actual_points == 29 def test_median(self): s, sample = self.make_sample(integrmode=MEDIAN) assert len(s[0]) == 64 # intensities assert_allclose(np.mean(s[2]), 199.9, atol=0.1) assert_allclose(np.std(s[2]), 21.3, atol=0.1) # radii assert_allclose(np.max(s[1]), 40.0, atol=0.01) assert_allclose(np.min(s[1]), 32.01, atol=0.01) assert_allclose(sample.sector_area, 12.4, atol=0.1) assert sample.total_points == 64 assert sample.actual_points == 64 @pytest.mark.remote_data class TestMasked(TestData): def test_bilinear(self): s, sample = self.make_sample(masked=True, integrmode=BILINEAR) assert len(s[0]) == 157 # intensities assert_allclose(np.mean(s[2]), 201.52, atol=0.01) assert_allclose(np.std(s[2]), 25.21, atol=0.01) # radii assert_allclose(np.max(s[1]), 40.0, atol=0.01) assert_allclose(np.min(s[1]), 32.0, atol=0.01) assert sample.total_points == 225 assert sample.actual_points == 157 def test_mean(self): s, sample = self.make_sample(masked=True, integrmode=MEAN) assert len(s[0]) == 51 # intensities assert_allclose(np.mean(s[2]), 199.9, atol=0.1) assert_allclose(np.std(s[2]), 24.12, atol=0.1) # radii assert_allclose(np.max(s[1]), 40.0, atol=0.01) assert_allclose(np.min(s[1]), 32.0, atol=0.01) assert_allclose(sample.sector_area, 12.4, atol=0.1) assert sample.total_points == 64 assert sample.actual_points == 51 photutils-0.7.2/photutils/isophote/tests/test_isophote.py0000644000214200020070000002121213572576702026244 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the isophote module. """ from astropy.io import fits import numpy as np from numpy.testing import assert_allclose import pytest from .make_test_data import make_test_image from ..fitter import EllipseFitter from ..isophote import Isophote, IsophoteList from ..sample import EllipseSample from ...datasets import get_path DEFAULT_FIX = np.array([False, False, False, False]) try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False @pytest.mark.remote_data @pytest.mark.skipif('not HAS_SCIPY') class TestIsophote: def setup_class(self): path = get_path('isophote/M51.fits', location='photutils-datasets', cache=True) hdu = fits.open(path) self.data = hdu[0].data hdu.close() def test_fit(self): # low noise image, fitted perfectly by sample data = make_test_image(noise=1.e-10, random_state=123) sample = EllipseSample(data, 40) fitter = EllipseFitter(sample) iso = fitter.fit(maxit=400) assert iso.valid assert iso.stop_code == 0 or iso.stop_code == 2 # fitted values assert iso.intens <= 201. assert iso.intens >= 199. assert iso.int_err <= 0.0010 assert iso.int_err >= 0.0009 assert iso.pix_stddev <= 0.03 assert iso.pix_stddev >= 0.02 assert abs(iso.grad) <= 4.25 assert abs(iso.grad) >= 4.20 # integrals assert iso.tflux_e <= 1.85E6 assert iso.tflux_e >= 1.82E6 assert iso.tflux_c <= 2.025E6 assert iso.tflux_c >= 2.022E6 # deviations from perfect ellipticity. Note # that sometimes a None covariance can be # generated by scipy.optimize.leastsq assert iso.a3 is None or abs(iso.a3) <= 0.01 assert iso.b3 is None or abs(iso.b3) <= 0.01 assert iso.a4 is None or abs(iso.a4) <= 0.01 assert iso.b4 is None or abs(iso.b4) <= 0.01 def test_m51(self): sample = EllipseSample(self.data, 21.44) fitter = EllipseFitter(sample) iso = fitter.fit() assert iso.valid assert iso.stop_code == 0 or iso.stop_code == 2 # geometry g = iso.sample.geometry assert g.x0 >= (257 - 1.5) # position within 1.5 pixel assert g.x0 <= (257 + 1.5) assert g.y0 >= (259 - 1.5) assert g.y0 <= (259 + 2.0) assert g.eps >= (0.19 - 0.05) # eps within 0.05 assert g.eps <= (0.19 + 0.05) assert g.pa >= (0.62 - 0.05) # pa within 5 deg assert g.pa <= (0.62 + 0.05) # fitted values assert_allclose(iso.intens, 682.9, atol=0.1) assert_allclose(iso.rms, 83.27, atol=0.01) assert_allclose(iso.int_err, 7.63, atol=0.01) assert_allclose(iso.pix_stddev, 117.8, atol=0.1) assert_allclose(iso.grad, -36.08, atol=0.1) # integrals assert iso.tflux_e <= 1.20e6 assert iso.tflux_e >= 1.19e6 assert iso.tflux_c <= 1.38e6 assert iso.tflux_c >= 1.36e6 # deviations from perfect ellipticity. Note # that sometimes a None covariance can be # generated by scipy.optimize.leastsq assert iso.a3 is None or abs(iso.a3) <= 0.05 assert iso.b3 is None or abs(iso.b3) <= 0.05 assert iso.a4 is None or abs(iso.a4) <= 0.05 assert iso.b4 is None or abs(iso.b4) <= 0.05 def test_m51_niter(self): # compares with old STSDAS task. In this task, the # default for the starting value of SMA is 10; it # fits with 20 iterations. sample = EllipseSample(self.data, 10) fitter = EllipseFitter(sample) iso = fitter.fit() assert iso.valid assert iso.niter == 50 class TestIsophoteList: def setup_class(self): data = make_test_image(random_state=123) self.slen = 5 self.isolist_sma10 = self.build_list(data, sma0=10., slen=self.slen) self.isolist_sma100 = self.build_list(data, sma0=100., slen=self.slen) self.isolist_sma200 = self.build_list(data, sma0=200., slen=self.slen) @staticmethod def build_list(data, sma0, slen=5): iso_list = [] for k in range(slen): sample = EllipseSample(data, float(k + sma0)) sample.update(DEFAULT_FIX) iso_list.append(Isophote(sample, k, True, 0)) result = IsophoteList(iso_list) return result def test_basic_list(self): # make sure it can be indexed as a list. result = self.isolist_sma10[:] assert isinstance(result[0], Isophote) # make sure the important arrays contain floats. # especially the sma array, which is derived # from a property in the Isophote class. assert isinstance(result.sma, np.ndarray) assert isinstance(result.sma[0], float) assert isinstance(result.intens, np.ndarray) assert isinstance(result.intens[0], float) assert isinstance(result.rms, np.ndarray) assert isinstance(result.int_err, np.ndarray) assert isinstance(result.pix_stddev, np.ndarray) assert isinstance(result.grad, np.ndarray) assert isinstance(result.grad_error, np.ndarray) assert isinstance(result.grad_r_error, np.ndarray) assert isinstance(result.sarea, np.ndarray) assert isinstance(result.niter, np.ndarray) assert isinstance(result.ndata, np.ndarray) assert isinstance(result.nflag, np.ndarray) assert isinstance(result.valid, np.ndarray) assert isinstance(result.stop_code, np.ndarray) assert isinstance(result.tflux_c, np.ndarray) assert isinstance(result.tflux_e, np.ndarray) assert isinstance(result.npix_c, np.ndarray) assert isinstance(result.npix_e, np.ndarray) assert isinstance(result.a3, np.ndarray) assert isinstance(result.a4, np.ndarray) assert isinstance(result.b3, np.ndarray) assert isinstance(result.b4, np.ndarray) samples = result.sample assert isinstance(samples, list) assert isinstance(samples[0], EllipseSample) iso = result.get_closest(13.6) assert isinstance(iso, Isophote) assert_allclose(iso.sma, 14., atol=1e-6) def test_extend(self): # the extend method shouldn't return anything, # and should modify the first list in place. inner_list = self.isolist_sma10[:] outer_list = self.isolist_sma100[:] assert len(inner_list) == self.slen assert len(outer_list) == self.slen inner_list.extend(outer_list) assert len(inner_list) == 2 * self.slen # the __iadd__ operator should behave like the # extend method. inner_list = self.isolist_sma10[:] outer_list = self.isolist_sma100[:] inner_list += outer_list assert len(inner_list) == 2 * self.slen # the __add__ operator should create a new IsophoteList # instance with the result, and should not modify # the operands. inner_list = self.isolist_sma10[:] outer_list = self.isolist_sma100[:] result = inner_list + outer_list assert isinstance(result, IsophoteList) assert len(inner_list) == self.slen assert len(outer_list) == self.slen assert len(result) == 2 * self.slen def test_slicing(self): iso_list = self.isolist_sma10[:] assert len(iso_list) == self.slen assert len(iso_list[1:-1]) == self.slen - 2 assert len(iso_list[2:-2]) == self.slen - 4 def test_combined(self): # combine extend with slicing. inner_list = self.isolist_sma10[:] outer_list = self.isolist_sma100[:] sublist = inner_list[2:-2] dummy = sublist.extend(outer_list) assert not dummy assert len(sublist) == 2*self.slen - 4 # try one more slice. even_outer_list = self.isolist_sma200 sublist.extend(even_outer_list[1:-1]) assert len(sublist) == 2*self.slen - 4 + 3 # combine __add__ with slicing. sublist = inner_list[2:-2] result = sublist + outer_list assert isinstance(result, IsophoteList) assert len(sublist) == self.slen - 4 assert len(result) == 2*self.slen - 4 result = inner_list[2:-2] + outer_list assert isinstance(result, IsophoteList) assert len(result) == 2*self.slen - 4 def test_sort(self): inner_list = self.isolist_sma10[:] outer_list = self.isolist_sma100[:] result = outer_list[2:-2] + inner_list assert result[-1].sma < result[0].sma result.sort() assert result[-1].sma > result[0].sma photutils-0.7.2/photutils/isophote/tests/test_model.py0000644000214200020070000000337013563423715025512 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the model module. """ from astropy.io import fits import numpy as np import pytest from .make_test_data import make_test_image from ..ellipse import Ellipse from ..geometry import EllipseGeometry from ..model import build_ellipse_model from ...datasets import get_path try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False @pytest.mark.remote_data @pytest.mark.skipif('not HAS_SCIPY') def test_model(): path = get_path('isophote/M105-S001-RGB.fits', location='photutils-datasets', cache=True) hdu = fits.open(path) data = hdu[0].data[0] hdu.close() g = EllipseGeometry(530., 511, 10., 0.1, 10./180.*np.pi) ellipse = Ellipse(data, geometry=g, threshold=1.e5) isophote_list = ellipse.fit_image() model = build_ellipse_model(data.shape, isophote_list, fill=np.mean(data[10:100, 10:100])) assert data.shape == model.shape residual = data - model assert np.mean(residual) <= 5.0 assert np.mean(residual) >= -5.0 @pytest.mark.skipif('not HAS_SCIPY') def test_model_simulated_data(): data = make_test_image(nx=200, ny=200, i0=10., sma=5., eps=0.5, pa=np.pi/3., noise=0.05, random_state=123) g = EllipseGeometry(100., 100., 5., 0.5, np.pi/3.) ellipse = Ellipse(data, geometry=g, threshold=1.e5) isophote_list = ellipse.fit_image() model = build_ellipse_model(data.shape, isophote_list, fill=np.mean(data[0:50, 0:50])) assert data.shape == model.shape residual = data - model assert np.mean(residual) <= 5.0 assert np.mean(residual) >= -5.0 photutils-0.7.2/photutils/isophote/tests/test_regression.py0000644000214200020070000001733413563423715026577 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Despite being cast as a unit test, this code implements regression testing of the Ellipse algorithm, against results obtained by the stsdas$analysis/isophote task 'ellipse'. The stsdas task was run on test images and results were stored in tables. The code here runs the Ellipse algorithm on the same images, producing a list of Isophote instances. The contents of this list then get compared with the contents of the corresponding table. Some quantities are compared in assert statements. These were designed to be executed only when the synth_highsnr.fits image is used as input. That way, we are mainly checking numerical differences that originate in the algorithms themselves, and not caused by noise. The quantities compared this way are: - mean intensity: less than 1% diff. for sma > 3 pixels, 5% otherwise - ellipticity: less than 1% diff. for sma > 3 pixels, 20% otherwise - position angle: less than 1 deg. diff. for sma > 3 pixels, 20 deg. otherwise - X and Y position: less than 0.2 pixel diff. For the M51 image we have mostly good agreement with the SPP code in most of the parameters (mean isophotal intensity agrees within a fraction of 1% mostly), but every now and then the ellipticity and position angle of the semi-major axis may differ by a large amount from what the SPP code measures. The code also stops prematurely wrt the larger sma values measured by the SPP code. This is caused by a difference in the way the gradient relative error is measured in each case, and suggests that the SPP code may have a bug. The not-so-good behavior observed in the case of the M51 image is to be expected though. This image is exactly the type of galaxy image for which the algorithm *wasn't* designed for. It has an almost negligible smooth ellipsoidal component, and a lot of lumpy spiral structure that causes the radial gradient computation to go berserk. On top of that, the ellipticity is small (roundish isophotes) throughout the image, causing large relative errors and instability in the fitting algorithm. For now, we can only check the bilinear integration mode. The mean and median modes cannot be checked since the original 'ellipse' task has a bug that causes the creation of erroneous output tables. A partial comparison could be made if we write new code that reads the standard output of 'ellipse' instead, captured from screen, and use it as reference for the regression. """ import math import os.path as op from astropy.io import fits from astropy.table import Table import numpy as np import pytest from ..ellipse import Ellipse from ..integrator import BILINEAR from ...datasets import get_path try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False @pytest.mark.remote_data @pytest.mark.skipif('not HAS_SCIPY') # @pytest.mark.parametrize('name', ['M51', 'synth', 'synth_lowsnr', # 'synth_highsnr']) @pytest.mark.parametrize('name', ['synth_highsnr']) def test_regression(name, integrmode=BILINEAR, verbose=False): """ NOTE: The original code in SPP won't create the right table for the MEAN integration moder, so use the screen output at synth_table_mean.txt to compare results visually with synth_table_mean.fits. """ filename = '{0}_table.fits'.format(name) path = op.join(op.dirname(op.abspath(__file__)), 'data', filename) table = Table.read(path) nrows = len(table['SMA']) path = get_path('isophote/{0}.fits'.format(name), location='photutils-datasets', cache=True) hdu = fits.open(path) data = hdu[0].data hdu.close() ellipse = Ellipse(data) isophote_list = ellipse.fit_image() # isophote_list = ellipse.fit_image(sclip=2., nclip=3) fmt = ("%5.2f %6.1f %8.3f %8.3f %8.3f %9.5f %6.2f " "%6.2f %6.2f %5.2f %4d %3d %3d %2d") for row in range(nrows): try: iso = isophote_list[row] except IndexError: # skip non-existent rows in isophote list, if that's the case. break # data from Isophote sma_i = iso.sample.geometry.sma intens_i = iso.intens int_err_i = iso.int_err if iso.int_err else 0. pix_stddev_i = iso.pix_stddev if iso.pix_stddev else 0. rms_i = iso.rms if iso.rms else 0. ellip_i = iso.sample.geometry.eps if iso.sample.geometry.eps else 0. pa_i = iso.sample.geometry.pa if iso.sample.geometry.pa else 0. x0_i = iso.sample.geometry.x0 y0_i = iso.sample.geometry.y0 rerr_i = (iso.sample.gradient_relative_error if iso.sample.gradient_relative_error else 0.) ndata_i = iso.ndata nflag_i = iso.nflag niter_i = iso.niter stop_i = iso.stop_code # convert to old code reference system pa_i = (pa_i - np.pi/2) / np.pi * 180. x0_i += 1 y0_i += 1 # ref data from table sma_t = table['SMA'][row] intens_t = table['INTENS'][row] int_err_t = table['INT_ERR'][row] pix_stddev_t = table['PIX_VAR'][row] rms_t = table['RMS'][row] ellip_t = table['ELLIP'][row] pa_t = table['PA'][row] x0_t = table['X0'][row] y0_t = table['Y0'][row] rerr_t = table['GRAD_R_ERR'][row] ndata_t = table['NDATA'][row] nflag_t = table['NFLAG'][row] niter_t = table['NITER'][row] if table['NITER'][row] else 0 stop_t = table['STOP'][row] if table['STOP'][row] else -1 # relative differences sma_d = (sma_i - sma_t) / sma_t * 100. if sma_t > 0. else 0. intens_d = (intens_i - intens_t) / intens_t * 100. int_err_d = ((int_err_i - int_err_t) / int_err_t * 100. if int_err_t > 0. else 0.) pix_stddev_d = ((pix_stddev_i - pix_stddev_t) / pix_stddev_t * 100. if pix_stddev_t > 0. else 0.) rms_d = (rms_i - rms_t) / rms_t * 100. if rms_t > 0. else 0. ellip_d = (ellip_i - ellip_t) / ellip_t * 100. pa_d = pa_i - pa_t # diff in angle is absolute x0_d = x0_i - x0_t # diff in position is absolute y0_d = y0_i - y0_t rerr_d = rerr_i - rerr_t # diff in relative error is absolute ndata_d = (ndata_i - ndata_t) / ndata_t * 100. nflag_d = 0 niter_d = 0 stop_d = 0 if stop_i == stop_t else -1 if verbose: print("* data " + fmt % (sma_i, intens_i, int_err_i, pix_stddev_i, rms_i, ellip_i, pa_i, x0_i, y0_i, rerr_i, ndata_i, nflag_i, niter_i, stop_i)) print(" ref " + fmt % (sma_t, intens_t, int_err_t, pix_stddev_t, rms_t, ellip_t, pa_t, x0_t, y0_t, rerr_t, ndata_t, nflag_t, niter_t, stop_t)) print(" diff " + fmt % (sma_d, intens_d, int_err_d, pix_stddev_d, rms_d, ellip_d, pa_d, x0_d, y0_d, rerr_d, ndata_d, nflag_d, niter_d, stop_d)) print() if name == "synth_highsnr" and integrmode == BILINEAR: assert abs(x0_d) <= 0.21 assert abs(y0_d) <= 0.21 if sma_i > 3.: assert abs(intens_d) <= 1. else: assert abs(intens_d) <= 5. if not math.isnan(ellip_d): if sma_i > 3.: assert abs(ellip_d) <= 1. # 1% else: assert abs(ellip_d) <= 20. # 20% if not math.isnan(pa_d): if sma_i > 3.: assert abs(pa_d) <= 1. # 1 deg. else: assert abs(pa_d) <= 20. # 20 deg. photutils-0.7.2/photutils/isophote/tests/test_sample.py0000644000214200020070000000326313563423715025674 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the sample module. """ import numpy as np import pytest from .make_test_data import make_test_image from ..integrator import BILINEAR, MEAN, MEDIAN, NEAREST_NEIGHBOR from ..isophote import Isophote from ..sample import EllipseSample DEFAULT_FIX = np.array([False, False, False, False]) DATA = make_test_image(background=100., i0=0., noise=10., random_state=123) # the median is not so good at estimating rms @pytest.mark.parametrize('integrmode, amin, amax', [(NEAREST_NEIGHBOR, 7., 15.), (BILINEAR, 7., 15.), (MEAN, 7., 15.), (MEDIAN, 6., 15.)]) def test_scatter(integrmode, amin, amax): """ Check that the pixel standard deviation can be reliably estimated from the rms scatter and the sector area. The test data is just a flat image with noise, no galaxy. We define the noise rms and then compare how close the pixel std dev estimated at extraction matches this input noise. """ sample = EllipseSample(DATA, 50., astep=0.2, integrmode=integrmode) sample.update(DEFAULT_FIX) iso = Isophote(sample, 0, True, 0) assert iso.pix_stddev < amax assert iso.pix_stddev > amin def test_coordinates(): sample = EllipseSample(DATA, 50.) sample.update(DEFAULT_FIX) x, y = sample.coordinates() assert isinstance(x, np.ndarray) assert isinstance(y, np.ndarray) def test_sclip(): sample = EllipseSample(DATA, 50., nclip=3) sample.update(DEFAULT_FIX) x, y = sample.coordinates() assert isinstance(x, np.ndarray) assert isinstance(y, np.ndarray) photutils-0.7.2/photutils/morphology/0000755000214200020070000000000013573510273022176 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/morphology/__init__.py0000644000214200020070000000036613563423715024317 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage contains tools for measuring morphological properties of objects in an astronomical image. """ from .core import * # noqa from .non_parametric import * # noqa photutils-0.7.2/photutils/morphology/core.py0000644000214200020070000000324613572573665023522 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for measuring morphological properties of sources. """ import numpy as np __all__ = ['data_properties'] def data_properties(data, mask=None, background=None): """ Calculate the morphological properties (and centroid) of a 2D array (e.g. an image cutout of an object) using image moments. Parameters ---------- data : array_like or `~astropy.units.Quantity` The 2D array of the image. mask : array_like (bool), optional A boolean mask, with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Masked data are excluded from all calculations. background : float, array_like, or `~astropy.units.Quantity`, optional The background level that was previously present in the input ``data``. ``background`` may either be a scalar value or a 2D image with the same shape as the input ``data``. Inputting the ``background`` merely allows for its properties to be measured within each source segment. The input ``background`` does *not* get subtracted from the input ``data``, which should already be background-subtracted. Returns ------- result : `~photutils.segmentation.SourceProperties` instance A `~photutils.segmentation.SourceProperties` object. """ from ..segmentation import SourceProperties # prevent circular imports segment_image = np.ones(data.shape, dtype=int) return SourceProperties(data, segment_image, label=1, mask=mask, background=background) photutils-0.7.2/photutils/morphology/non_parametric.py0000644000214200020070000000351313563423715025556 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides functions for measuring non-parametric morphologies of sources. """ import numpy as np __all__ = ['gini'] def gini(data): """ Calculate the `Gini coefficient `_ of a 2D array. The Gini coefficient is calculated using the prescription from `Lotz et al. 2004 `_ as: .. math:: G = \\frac{1}{\\left | \\bar{x} \\right | n (n - 1)} \\sum^{n}_{i} (2i - n - 1) \\left | x_i \\right | where :math:`\\bar{x}` is the mean over all pixel values :math:`x_i`. The Gini coefficient is a way of measuring the inequality in a given set of values. In the context of galaxy morphology, it measures how the light of a galaxy image is distributed among its pixels. A Gini coefficient value of 0 corresponds to a galaxy image with the light evenly distributed over all pixels while a Gini coefficient value of 1 represents a galaxy image with all its light concentrated in just one pixel. Usually Gini's measurement needs some sort of preprocessing for defining the galaxy region in the image based on the quality of the input data. As there is not a general standard for doing this, this is left for the user. Parameters ---------- data : array-like The 2D data array or object that can be converted to an array. Returns ------- gini : `float` The Gini coefficient of the input 2D array. """ flattened = np.sort(np.ravel(data)) npix = np.size(flattened) normalization = np.abs(np.mean(flattened)) * npix * (npix - 1) kernel = (2. * np.arange(1, npix + 1) - npix - 1) * np.abs(flattened) return np.sum(kernel) / normalization photutils-0.7.2/photutils/morphology/tests/0000755000214200020070000000000013573510273023340 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/morphology/tests/__init__.py0000644000214200020070000000000013563423715025442 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/morphology/tests/test_core.py0000644000214200020070000000204413572573665025716 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the core module. """ import numpy as np from numpy.testing import assert_allclose import pytest from ..core import data_properties try: import skimage # noqa HAS_SKIMAGE = True except ImportError: HAS_SKIMAGE = False XCS = [25.7] YCS = [26.2] XSTDDEVS = [3.2, 4.0] YSTDDEVS = [5.7, 4.1] THETAS = np.array([30., 45.]) * np.pi / 180. DATA = np.zeros((3, 3)) DATA[0:2, 1] = 1. DATA[1, 0:2] = 1. DATA[1, 1] = 2. @pytest.mark.skipif('not HAS_SKIMAGE') def test_data_properties(): data = np.ones((2, 2)).astype(float) mask = np.array([[False, False], [True, True]]) props = data_properties(data, mask=None) props2 = data_properties(data, mask=mask) properties = ['xcentroid', 'ycentroid', 'area'] result = [getattr(props, i).value for i in properties] result2 = [getattr(props2, i).value for i in properties] assert_allclose([0.5, 0.5, 4.0], result, rtol=0, atol=1.e-6) assert_allclose([0.5, 0.0, 2.0], result2, rtol=0, atol=1.e-6) photutils-0.7.2/photutils/morphology/tests/test_non_parametric.py0000644000214200020070000000070313563423715027755 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the non_parametric module. """ import numpy as np from ..non_parametric import gini def test_gini(): """ Test Gini coefficient calculation. """ data_evenly_distributed = np.ones((100, 100)) data_point_like = np.zeros((100, 100)) data_point_like[50, 50] = 1 assert gini(data_evenly_distributed) == 0. assert gini(data_point_like) == 1. photutils-0.7.2/photutils/psf/0000755000214200020070000000000013573510273020567 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/psf/__init__.py0000644000214200020070000000057013572236170022702 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage contains tools to perform point-spread-function (PSF) photometry. """ from .epsf import * # noqa from .epsf_stars import * # noqa from .groupstars import * # noqa from .matching import * # noqa from .models import * # noqa from .photometry import * # noqa from .utils import * # noqa photutils-0.7.2/photutils/psf/epsf.py0000644000214200020070000010506613572576136022117 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools to build and fit an effective PSF (ePSF) based on Anderson and King (2000; PASP 112, 1360) and Anderson (2016), ISR WFC3 2016-12. """ import copy import time import warnings from astropy.modeling.fitting import LevMarLSQFitter from astropy.nddata.utils import (overlap_slices, PartialOverlapError, NoOverlapError) from astropy.utils.exceptions import AstropyUserWarning import numpy as np from .epsf_stars import EPSFStar, EPSFStars, LinkedEPSFStar from .models import EPSFModel from ..centroids import centroid_epsf from ..extern.sigma_clipping import SigmaClip try: import bottleneck # pylint: disable=W0611 HAS_BOTTLENECK = True except ImportError: HAS_BOTTLENECK = False __all__ = ['EPSFFitter', 'EPSFBuilder'] class EPSFFitter: """ Class to fit an ePSF model to one or more stars. Parameters ---------- fitter : `astropy.modeling.fitting.Fitter`, optional A `~astropy.modeling.fitting.Fitter` object. fit_boxsize : int, tuple of int, or `None`, optional The size (in pixels) of the box centered on the star to be used for ePSF fitting. This allows using only a small number of central pixels of the star (i.e. where the star is brightest) for fitting. If ``fit_boxsize`` is a scalar then a square box of size ``fit_boxsize`` will be used. If ``fit_boxsize`` has two elements, they should be in ``(ny, nx)`` order. The size must be greater than or equal to 3 pixels for both axes. If `None`, the fitter will use the entire star image. fitter_kwargs : dict-like, optional Any additional keyword arguments (except ``x``, ``y``, ``z``, or ``weights``) to be passed directly to the ``__call__()`` method of the input ``fitter``. """ def __init__(self, fitter=LevMarLSQFitter(), fit_boxsize=5, **fitter_kwargs): self.fitter = fitter self.fitter_has_fit_info = hasattr(self.fitter, 'fit_info') if fit_boxsize is not None: fit_boxsize = np.atleast_1d(fit_boxsize).astype(int) if len(fit_boxsize) == 1: fit_boxsize = np.repeat(fit_boxsize, 2) min_size = 3 if any([size < min_size for size in fit_boxsize]): raise ValueError('size must be >= {} for x and y' .format(min_size)) self.fit_boxsize = fit_boxsize # remove any fitter keyword arguments that we need to set remove_kwargs = ['x', 'y', 'z', 'weights'] fitter_kwargs = copy.deepcopy(fitter_kwargs) for kwarg in remove_kwargs: if kwarg in fitter_kwargs: del fitter_kwargs[kwarg] self.fitter_kwargs = fitter_kwargs def __call__(self, epsf, stars): """ Fit an ePSF model to stars. Parameters ---------- epsf : `EPSFModel` An ePSF model to be fitted to the stars. stars : `EPSFStars` object The stars to be fit. The center coordinates for each star should be as close as possible to actual centers. For stars than contain weights, a weighted fit of the ePSF to the star will be performed. Returns ------- fitted_stars : `EPSFStars` object The fitted stars. The ePSF-fitted center position and flux are stored in the ``center`` (and ``cutout_center``) and ``flux`` attributes. """ if len(stars) == 0: return stars if not isinstance(epsf, EPSFModel): raise TypeError('The input epsf must be an EPSFModel.') # make a copy of the input ePSF epsf = epsf.copy() # perform the fit fitted_stars = [] for star in stars: if isinstance(star, EPSFStar): fitted_star = self._fit_star(epsf, star, self.fitter, self.fitter_kwargs, self.fitter_has_fit_info, self.fit_boxsize) elif isinstance(star, LinkedEPSFStar): fitted_star = [] for linked_star in star: fitted_star.append( self._fit_star(epsf, linked_star, self.fitter, self.fitter_kwargs, self.fitter_has_fit_info, self.fit_boxsize)) fitted_star = LinkedEPSFStar(fitted_star) fitted_star.constrain_centers() else: raise TypeError('stars must contain only EPSFStar and/or ' 'LinkedEPSFStar objects.') fitted_stars.append(fitted_star) return EPSFStars(fitted_stars) def _fit_star(self, epsf, star, fitter, fitter_kwargs, fitter_has_fit_info, fit_boxsize): """ Fit an ePSF model to a single star. The input ``epsf`` will usually be modified by the fitting routine in this function. Make a copy before calling this function if the original is needed. """ if fit_boxsize is not None: try: xcenter, ycenter = star.cutout_center large_slc, _ = overlap_slices(star.shape, fit_boxsize, (ycenter, xcenter), mode='strict') except (PartialOverlapError, NoOverlapError): warnings.warn('The star at ({0}, {1}) cannot be fit because ' 'its fitting region extends beyond the star ' 'cutout image.'.format(star.center[0], star.center[1]), AstropyUserWarning) star = copy.deepcopy(star) star._fit_error_status = 1 return star data = star.data[large_slc] weights = star.weights[large_slc] # define the origin of the fitting region x0 = large_slc[1].start y0 = large_slc[0].start else: # use the entire cutout image data = star.data weights = star.weights # define the origin of the fitting region x0 = 0 y0 = 0 # Define positions in the undersampled grid. The fitter will # evaluate on the defined interpolation grid, currently in the # range [0, len(undersampled grid)]. yy, xx = np.indices(data.shape, dtype=np.float) xx = xx + x0 - star.cutout_center[0] yy = yy + y0 - star.cutout_center[1] # define the initial guesses for fitted flux and shifts epsf.flux = star.flux epsf.x_0 = 0.0 epsf.y_0 = 0.0 try: fitted_epsf = fitter(model=epsf, x=xx, y=yy, z=data, weights=weights, **fitter_kwargs) except TypeError: # fitter doesn't support weights fitted_epsf = fitter(model=epsf, x=xx, y=yy, z=data, **fitter_kwargs) fit_error_status = 0 if fitter_has_fit_info: fit_info = copy.copy(fitter.fit_info) if 'ierr' in fit_info and fit_info['ierr'] not in [1, 2, 3, 4]: fit_error_status = 2 # fit solution was not found else: fit_info = None # compute the star's fitted position x_center = star.cutout_center[0] + fitted_epsf.x_0.value y_center = star.cutout_center[1] + fitted_epsf.y_0.value star = copy.deepcopy(star) star.cutout_center = (x_center, y_center) # set the star's flux to the ePSF-fitted flux star.flux = fitted_epsf.flux.value star._fit_info = fit_info star._fit_error_status = fit_error_status return star class EPSFBuilder: """ Class to build an effective PSF (ePSF). See `Anderson and King (2000; PASP 112, 1360) `_ and `Anderson (2016), ISR WFC3 2016-12 `_ for details. Parameters ---------- oversampling : int or tuple of two int, optional The oversampling factor(s) of the ePSF relative to the input ``stars`` along the x and y axes. The ``oversampling`` can either be a single float or a tuple of two floats of the form ``(x_oversamp, y_oversamp)``. If ``oversampling`` is a scalar then the oversampling will be the same for both the x and y axes. shape : float, tuple of two floats, or `None`, optional The shape of the output ePSF. If the ``shape`` is not `None`, it will be derived from the sizes of the input ``stars`` and the ePSF oversampling factor. If the size is even along any axis, it will be made odd by adding one. The output ePSF will always have odd sizes along both axes to ensure a well-defined central pixel. smoothing_kernel : {'quartic', 'quadratic'}, 2D `~numpy.ndarray`, or `None` The smoothing kernel to apply to the ePSF. The predefined ``'quartic'`` and ``'quadratic'`` kernels are derived from fourth and second degree polynomials, respectively. Alternatively, a custom 2D array can be input. If `None` then no smoothing will be performed. recentering_func : callable, optional A callable object (e.g. function or class) that is used to calculate the centroid of a 2D array. The callable must accept a 2D `~numpy.ndarray`, have a ``mask`` keyword and optionally ``error`` and ``oversampling`` keywords. The callable object must return a tuple of two 1D `~numpy.ndarray` variables, representing the x and y centroids. recentering_maxiters : int, optional The maximum number of recentering iterations to perform during each ePSF build iteration. fitter : `EPSFFitter` object, optional A `EPSFFitter` object use to fit the ePSF to stars. To set fitter options, a new object with specific options should be passed in - the default uses simply the default options. To see more of these options, see the `EPSFFitter` documentation. maxiters : int, optional The maximum number of iterations to perform. progress_bar : bool, option Whether to print the progress bar during the build iterations. norm_radius : float, optional The pixel radius over which the ePSF is normalized. shift_val : float, optional The undersampled value at which to compute the shifts. It must be a strictly positive number. recentering_boxsize : float or tuple of two floats, optional The size (in pixels) of the box used to calculate the centroid of the ePSF during each build iteration. If a single integer number is provided, then a square box will be used. If two values are provided, then they should be in ``(ny, nx)`` order. center_accuracy : float, optional The desired accuracy for the centers of stars. The building iterations will stop if the centers of all the stars change by less than ``center_accuracy`` pixels between iterations. All stars must meet this condition for the loop to exit. """ def __init__(self, oversampling=4., shape=None, smoothing_kernel='quartic', recentering_func=centroid_epsf, recentering_maxiters=20, fitter=EPSFFitter(), maxiters=10, progress_bar=True, norm_radius=5.5, shift_val=0.5, recentering_boxsize=(5, 5), center_accuracy=1.0e-3): flux_residual_sigclip = SigmaClip(sigma=3, cenfunc='median', maxiters=10) # TODO: replace with kwarg in 8.0 if oversampling is None: raise ValueError("'oversampling' must be specified.") oversampling = np.atleast_1d(oversampling).astype(int) if len(oversampling) == 1: oversampling = np.repeat(oversampling, 2) if np.any(oversampling % 2 != 0): raise ValueError('Oversampling factor must be a multiple of two.') if np.any(oversampling <= 0.0): raise ValueError('oversampling must be a positive number.') self._norm_radius = norm_radius self._shift_val = shift_val self.oversampling = oversampling self.shape = self._init_img_params(shape) if self.shape is not None: self.shape = self.shape.astype(int) self.recentering_func = recentering_func self.recentering_maxiters = recentering_maxiters self.recentering_boxsize = self._init_img_params(recentering_boxsize) self.recentering_boxsize = self.recentering_boxsize.astype(int) self.smoothing_kernel = smoothing_kernel if not isinstance(fitter, EPSFFitter): raise TypeError('fitter must be an EPSFFitter instance.') self.fitter = fitter if center_accuracy <= 0.0: raise ValueError('center_accuracy must be a positive number.') self.center_accuracy_sq = center_accuracy**2 maxiters = int(maxiters) if maxiters <= 0: raise ValueError("'maxiters' must be a positive number.") self.maxiters = maxiters self.progress_bar = progress_bar if not isinstance(flux_residual_sigclip, SigmaClip): raise ValueError("'flux_residual_sigclip' must be an" " astropy.stats.SigmaClip function.") self.flux_residual_sigclip = flux_residual_sigclip # store each ePSF build iteration self._epsf = [] def __call__(self, stars): return self.build_epsf(stars) @staticmethod def _init_img_params(param): """ Initialize 2D image-type parameters that can accept either a single or two values. """ if param is not None: param = np.atleast_1d(param) if len(param) == 1: param = np.repeat(param, 2) return param def _create_initial_epsf(self, stars): """ Create an initial `EPSFModel` object. The initial ePSF data are all zeros. If ``shape`` is not specified, the shape of the ePSF data array is determined from the shape of the input ``stars`` and the oversampling factor. If the size is even along any axis, it will be made odd by adding one. The output ePSF will always have odd sizes along both axes to ensure a central pixel. Parameters ---------- stars : `EPSFStars` object The stars used to build the ePSF. Returns ------- epsf : `EPSFModel` The initial ePSF model. """ norm_radius = self._norm_radius shift_val = self._shift_val oversampling = self.oversampling shape = self.shape # define the ePSF shape if shape is not None: shape = np.atleast_1d(shape).astype(int) if len(shape) == 1: shape = np.repeat(shape, 2) else: # Stars class should have odd-sized dimensions, and thus we # get the oversampled shape as oversampling * len + 1; if # len=25, then newlen=101, for example. x_shape = np.int(np.ceil(stars._max_shape[0]) * oversampling[0] + 1) y_shape = np.int(np.ceil(stars._max_shape[1]) * oversampling[1] + 1) shape = np.array((y_shape, x_shape)) # verify odd sizes of shape shape = [(i + 1) if i % 2 == 0 else i for i in shape] data = np.zeros(shape, dtype=np.float) # ePSF origin should be in the undersampled pixel units, not the # oversampled grid units. The middle, fractional (as we wish for # the center of the pixel, so the center should be at (v.5, w.5) # detector pixels) value is simply the average of the two values # at the extremes. xcenter = stars._max_shape[0] / 2. ycenter = stars._max_shape[1] / 2. epsf = EPSFModel(data=data, origin=(xcenter, ycenter), oversampling=oversampling, norm_radius=norm_radius, shift_val=shift_val) return epsf def _resample_residual(self, star, epsf): """ Compute a normalized residual image in the oversampled ePSF grid. A normalized residual image is calculated by subtracting the normalized ePSF model from the normalized star at the location of the star in the undersampled grid. The normalized residual image is then resampled from the undersampled star grid to the oversampled ePSF grid. Parameters ---------- star : `EPSFStar` object A single star object. epsf : `EPSFModel` object The ePSF model. Returns ------- image : 2D `~numpy.ndarray` A 2D image containing the resampled residual image. The image contains NaNs where there is no data. """ # Compute the normalized residual by subtracting the ePSF model # from the normalized star at the location of the star in the # undersampled grid. x = star._xidx_centered y = star._yidx_centered stardata = (star._data_values_normalized - epsf.evaluate(x=x, y=y, flux=1.0, x_0=0.0, y_0=0.0)) x = epsf.oversampling[0] * star._xidx_centered y = epsf.oversampling[1] * star._yidx_centered epsf_xcenter, epsf_ycenter = (int((epsf.data.shape[1] - 1) / 2), int((epsf.data.shape[0] - 1) / 2)) xidx = _py2intround(x + epsf_xcenter) yidx = _py2intround(y + epsf_ycenter) resampled_img = np.full(epsf.shape, np.nan) mask = np.logical_and(np.logical_and(xidx >= 0, xidx < epsf.shape[1]), np.logical_and(yidx >= 0, yidx < epsf.shape[0])) xidx_ = xidx[mask] yidx_ = yidx[mask] resampled_img[yidx_, xidx_] = stardata[mask] return resampled_img def _resample_residuals(self, stars, epsf): """ Compute normalized residual images for all the input stars. Parameters ---------- stars : `EPSFStars` object The stars used to build the ePSF. epsf : `EPSFModel` object The ePSF model. Returns ------- epsf_resid : 3D `~numpy.ndarray` A 3D cube containing the resampled residual images. """ shape = (stars.n_good_stars, epsf.shape[0], epsf.shape[1]) epsf_resid = np.zeros(shape) for i, star in enumerate(stars.all_good_stars): epsf_resid[i, :, :] = self._resample_residual(star, epsf) return epsf_resid def _smooth_epsf(self, epsf_data): """ Smooth the ePSF array by convolving it with a kernel. Parameters ---------- epsf_data : 2D `~numpy.ndarray` A 2D array containing the ePSF image. Returns ------- result : 2D `~numpy.ndarray` The smoothed (convolved) ePSF data. """ from scipy.ndimage import convolve if self.smoothing_kernel is None: return epsf_data elif self.smoothing_kernel == 'quartic': # from Polynomial2D fit with degree=4 to 5x5 array of # zeros with 1. at the center # Polynomial2D(4, c0_0=0.04163265, c1_0=-0.76326531, # c2_0=0.99081633, c3_0=-0.4, c4_0=0.05, # c0_1=-0.76326531, c0_2=0.99081633, c0_3=-0.4, # c0_4=0.05, c1_1=0.32653061, c1_2=-0.08163265, # c1_3=0., c2_1=-0.08163265, c2_2=0.02040816, # c3_1=-0.)> kernel = np.array( [[+0.041632, -0.080816, 0.078368, -0.080816, +0.041632], [-0.080816, -0.019592, 0.200816, -0.019592, -0.080816], [+0.078368, +0.200816, 0.441632, +0.200816, +0.078368], [-0.080816, -0.019592, 0.200816, -0.019592, -0.080816], [+0.041632, -0.080816, 0.078368, -0.080816, +0.041632]]) elif self.smoothing_kernel == 'quadratic': # from Polynomial2D fit with degree=2 to 5x5 array of # zeros with 1. at the center # Polynomial2D(2, c0_0=-0.07428571, c1_0=0.11428571, # c2_0=-0.02857143, c0_1=0.11428571, # c0_2=-0.02857143, c1_1=-0.) kernel = np.array( [[-0.07428311, 0.01142786, 0.03999952, 0.01142786, -0.07428311], [+0.01142786, 0.09714283, 0.12571449, 0.09714283, +0.01142786], [+0.03999952, 0.12571449, 0.15428215, 0.12571449, +0.03999952], [+0.01142786, 0.09714283, 0.12571449, 0.09714283, +0.01142786], [-0.07428311, 0.01142786, 0.03999952, 0.01142786, -0.07428311]]) elif isinstance(self.smoothing_kernel, np.ndarray): kernel = self.smoothing_kernel else: raise TypeError('Unsupported kernel.') return convolve(epsf_data, kernel) def _recenter_epsf(self, epsf, centroid_func=centroid_epsf, box_size=(5, 5), maxiters=20, center_accuracy=1.0e-4): """ Calculate the center of the ePSF data and shift the data so the ePSF center is at the center of the ePSF data array. Parameters ---------- epsf : `EPSFModel` object The ePSF model. centroid_func : callable, optional A callable object (e.g. function or class) that is used to calculate the centroid of a 2D array. The callable must accept a 2D `~numpy.ndarray`, have a ``mask`` keyword and optionally an ``error`` keyword. The callable object must return a tuple of two 1D `~numpy.ndarray` variables, representing the x and y centroids. box_size : float or tuple of two floats, optional The size (in pixels) of the box used to calculate the centroid of the ePSF during each build iteration. If a single integer number is provided, then a square box will be used. If two values are provided, then they should be in ``(ny, nx)`` order. maxiters : int, optional The maximum number of recentering iterations to perform. center_accuracy : float, optional The desired accuracy for the centers of stars. The building iterations will stop if the center of the ePSF changes by less than ``center_accuracy`` pixels between iterations. Returns ------- result : 2D `~numpy.ndarray` The recentered ePSF data. """ epsf_data = epsf._data epsf = EPSFModel(data=epsf._data, origin=epsf.origin, oversampling=epsf.oversampling, norm_radius=epsf._norm_radius, shift_val=epsf._shift_val, normalize=False) xcenter, ycenter = epsf.origin y, x = np.indices(epsf._data.shape, dtype=np.float) x /= epsf.oversampling[0] y /= epsf.oversampling[1] dx_total, dy_total = 0, 0 iter_num = 0 center_accuracy_sq = center_accuracy ** 2 center_dist_sq = center_accuracy_sq + 1.e6 center_dist_sq_prev = center_dist_sq + 1 while (iter_num < maxiters and center_dist_sq >= center_accuracy_sq): iter_num += 1 # Anderson & King (2000) recentering function depends # on specific pixels, and thus does not need a cutout if self.recentering_func == centroid_epsf: epsf_cutout = epsf_data else: slices_large, _ = overlap_slices(epsf_data.shape, box_size, (ycenter * self.oversampling[1], xcenter * self.oversampling[0])) epsf_cutout = epsf_data[slices_large] mask = ~np.isfinite(epsf_cutout) try: # find a new center position xcenter_new, ycenter_new = centroid_func( epsf_cutout, mask=mask, oversampling=epsf.oversampling, shift_val=epsf._shift_val) except TypeError: # centroid_func doesn't accept oversampling and/or shift_val # keywords - try oversampling alone try: xcenter_new, ycenter_new = centroid_func( epsf_cutout, mask=mask, oversampling=epsf.oversampling) except TypeError: # centroid_func doesn't accept oversampling and # shift_val xcenter_new, ycenter_new = centroid_func(epsf_cutout, mask=mask) if self.recentering_func != centroid_epsf: xcenter_new += slices_large[1].start/self.oversampling[0] ycenter_new += slices_large[0].start/self.oversampling[1] # Calculate the shift; dx = i - x_star so if dx was positively # incremented then x_star was negatively incremented for a given i. # We will therefore actually subsequently subtract dx from xcenter # (or x_star). dx = xcenter_new - xcenter dy = ycenter_new - ycenter center_dist_sq = dx**2 + dy**2 if center_dist_sq >= center_dist_sq_prev: # don't shift break center_dist_sq_prev = center_dist_sq dx_total += dx dy_total += dy epsf_data = epsf.evaluate(x=x, y=y, flux=1.0, x_0=xcenter - dx_total, y_0=ycenter - dy_total) return epsf_data def _build_epsf_step(self, stars, epsf=None): """ A single iteration of improving an ePSF. Parameters ---------- stars : `EPSFStars` object The stars used to build the ePSF. epsf : `EPSFModel` object, optional The initial ePSF model. If not input, then the ePSF will be built from scratch. Returns ------- epsf : `EPSFModel` object The updated ePSF. """ if len(stars) < 1: raise ValueError('stars must contain at least one EPSFStar or ' 'LinkedEPSFStar object.') if epsf is None: # create an initial ePSF (array of zeros) epsf = self._create_initial_epsf(stars) else: # improve the input ePSF epsf = copy.deepcopy(epsf) # compute a 3D stack of 2D residual images residuals = self._resample_residuals(stars, epsf) # compute the sigma-clipped average along the 3D stack with warnings.catch_warnings(): warnings.simplefilter('ignore', category=RuntimeWarning) warnings.simplefilter('ignore', category=AstropyUserWarning) residuals = self.flux_residual_sigclip(residuals, axis=0, masked=False, return_bounds=False) if HAS_BOTTLENECK: residuals = bottleneck.nanmedian(residuals, axis=0) else: residuals = np.nanmedian(residuals, axis=0) # interpolate any missing data (np.nan) mask = ~np.isfinite(residuals) if np.any(mask): residuals = _interpolate_missing_data(residuals, mask, method='cubic') # fill any remaining nans (outer points) with zeros residuals[~np.isfinite(residuals)] = 0. # add the residuals to the previous ePSF image new_epsf = epsf._data + residuals # smooth and recenter the ePSF new_epsf = self._smooth_epsf(new_epsf) epsf = EPSFModel(data=new_epsf, origin=epsf.origin, oversampling=epsf.oversampling, norm_radius=epsf._norm_radius, shift_val=epsf._shift_val, normalize=False) epsf._data = self._recenter_epsf( epsf, centroid_func=self.recentering_func, box_size=self.recentering_boxsize, maxiters=self.recentering_maxiters) # Return the new ePSF object, but with undersampled grid pixel # coordinates. xcenter = (epsf._data.shape[1] - 1) / 2. / epsf.oversampling[0] ycenter = (epsf._data.shape[0] - 1) / 2. / epsf.oversampling[1] return EPSFModel(data=epsf._data, origin=(xcenter, ycenter), oversampling=epsf.oversampling, norm_radius=epsf._norm_radius, shift_val=epsf._shift_val) def build_epsf(self, stars, init_epsf=None): """ Iteratively build an ePSF from star cutouts. Parameters ---------- stars : `EPSFStars` object The stars used to build the ePSF. init_epsf : `EPSFModel` object, optional The initial ePSF model. If not input, then the ePSF will be built from scratch. Returns ------- epsf : `EPSFModel` object The constructed ePSF. fitted_stars : `EPSFStars` object The input stars with updated centers and fluxes derived from fitting the output ``epsf``. """ iter_num = 0 n_stars = stars.n_stars fit_failed = np.zeros(n_stars, dtype=bool) epsf = init_epsf dt = 0. center_dist_sq = self.center_accuracy_sq + 1. centers = stars.cutout_center_flat while (iter_num < self.maxiters and not np.all(fit_failed) and np.max(center_dist_sq) >= self.center_accuracy_sq): t_start = time.time() iter_num += 1 if self.progress_bar: if iter_num == 1: dt_str = ' [? s/iter]' else: dt_str = ' [{:.1f} s/iter]'.format(dt) print('PROGRESS: iteration {0:d} (of max {1}){2}' .format(iter_num, self.maxiters, dt_str), end='\r') # build/improve the ePSF epsf = self._build_epsf_step(stars, epsf=epsf) # fit the new ePSF to the stars to find improved centers # we catch fit warnings here -- stars with unsuccessful fits # are excluded from the ePSF build process with warnings.catch_warnings(): message = '.*The fit may be unsuccessful;.*' warnings.filterwarnings('ignore', message=message, category=AstropyUserWarning) stars = self.fitter(epsf, stars) # find all stars where the fit failed fit_failed = np.array([star._fit_error_status > 0 for star in stars.all_stars]) if np.all(fit_failed): raise ValueError('The ePSF fitting failed for all stars.') # permanently exclude fitting any star where the fit fails # after 3 iterations if iter_num > 3 and np.any(fit_failed): idx = fit_failed.nonzero()[0] for i in idx: stars.all_stars[i]._excluded_from_fit = True # if no star centers have moved by more than pixel accuracy, # stop the iteration loop early dx_dy = stars.cutout_center_flat - centers dx_dy = dx_dy[np.logical_not(fit_failed)] center_dist_sq = np.sum(dx_dy * dx_dy, axis=1, dtype=np.float64) centers = stars.cutout_center_flat self._epsf.append(epsf) dt = time.time() - t_start return epsf, stars def _py2intround(a): """ Round the input to the nearest integer. If two integers are equally close, rounding is done away from 0. """ data = np.asanyarray(a) value = np.where(data >= 0, np.floor(data + 0.5), np.ceil(data - 0.5)).astype(int) if not hasattr(a, '__iter__'): value = np.asscalar(value) return value def _interpolate_missing_data(data, mask, method='cubic'): """ Interpolate missing data as identified by the ``mask`` keyword. Parameters ---------- data : 2D `~numpy.ndarray` An array containing the 2D image. mask : 2D bool `~numpy.ndarray` A 2D booleen mask array with the same shape as the input ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. The masked data points are those that will be interpolated. method : {'cubic', 'nearest'}, optional The method of used to interpolate the missing data: * ``'cubic'``: Masked data are interpolated using 2D cubic splines. This is the default. * ``'nearest'``: Masked data are interpolated using nearest-neighbor interpolation. Returns ------- data_interp : 2D `~numpy.ndarray` The interpolated 2D image. """ from scipy import interpolate data_interp = np.array(data, copy=True) if len(data_interp.shape) != 2: raise ValueError("'data' must be a 2D array.") if mask.shape != data.shape: raise ValueError("'mask' and 'data' must have the same shape.") y, x = np.indices(data_interp.shape) xy = np.dstack((x[~mask].ravel(), y[~mask].ravel()))[0] z = data_interp[~mask].ravel() if method == 'nearest': interpol = interpolate.NearestNDInterpolator(xy, z) elif method == 'cubic': interpol = interpolate.CloughTocher2DInterpolator(xy, z) else: raise ValueError('Unsupported interpolation method.') xy_missing = np.dstack((x[mask].ravel(), y[mask].ravel()))[0] data_interp[mask] = interpol(xy_missing) return data_interp photutils-0.7.2/photutils/psf/epsf_stars.py0000644000214200020070000006753413572236170023331 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools to extract cutouts of stars and data structures to hold the cutouts for fitting and building ePSFs. """ import warnings from astropy.nddata import NDData from astropy.nddata.utils import (overlap_slices, NoOverlapError, PartialOverlapError) from astropy.table import Table from astropy.utils import lazyproperty from astropy.utils.exceptions import AstropyUserWarning from astropy.wcs import WCS from astropy.wcs.utils import skycoord_to_pixel import numpy as np from ..aperture import BoundingBox __all__ = ['EPSFStar', 'EPSFStars', 'LinkedEPSFStar', 'extract_stars'] class EPSFStar: """ A class to hold a 2D cutout image and associated metadata of a star used to build an ePSF. Parameters ---------- data : `~numpy.ndarray` A 2D cutout image of a single star. weights : `~numpy.ndarray` or `None`, optional A 2D array of the weights associated with the input ``data``. cutout_center : tuple of two floats or `None`, optional The ``(x, y)`` position of the star's center with respect to the input cutout ``data`` array. If `None`, then the center of of the input cutout ``data`` array will be used. origin : tuple of two int, optional The ``(x, y)`` index of the origin (bottom-left corner) pixel of the input cutout array with respect to the original array from which the cutout was extracted. This can be used to convert positions within the cutout image to positions in the original image. ``origin`` and ``wcs_large`` must both be input for a linked star (a single star extracted from different images). wcs_large : `None` or WCS object, optional A WCS object associated with the large image from which the cutout array was extracted. It should not be the WCS object of the input cutout ``data`` array. The WCS object must support the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). ``origin`` and ``wcs_large`` must both be input for a linked star (a single star extracted from different images). id_label : int, str, or `None`, optional An optional identification number or label for the star. """ def __init__(self, data, weights=None, cutout_center=None, origin=(0, 0), wcs_large=None, id_label=None): self._data = np.asanyarray(data) self.shape = self._data.shape if weights is not None: if weights.shape != data.shape: raise ValueError('weights must have the same shape as the ' 'input data array.') self.weights = np.asanyarray(weights, dtype=np.float).copy() else: self.weights = np.ones_like(self._data, dtype=np.float) self.mask = (self.weights <= 0.) # mask out invalid image data invalid_data = np.logical_not(np.isfinite(self._data)) if np.any(invalid_data): self.weights[invalid_data] = 0. self.mask[invalid_data] = True self._cutout_center = cutout_center self.origin = np.asarray(origin) self.wcs_large = wcs_large self.id_label = id_label self.flux = self.estimate_flux() self._excluded_from_fit = False self._fitinfo = None def __array__(self): """ Array representation of the mask data array (e.g., for matplotlib). """ return self._data @property def data(self): """The 2D cutout image.""" return self._data @property def cutout_center(self): """ A `~numpy.ndarray` of the ``(x, y)`` position of the star's center with respect to the input cutout ``data`` array. """ return self._cutout_center @cutout_center.setter def cutout_center(self, value): if value is None: value = ((self.shape[1] - 1) / 2., (self.shape[0] - 1) / 2.) else: if len(value) != 2: raise ValueError('The "cutout_center" attribute must have ' 'two elements in (x, y) form.') self._cutout_center = np.asarray(value) @property def center(self): """ A `~numpy.ndarray` of the ``(x, y)`` position of the star's center in the original (large) image (not the cutout image). """ return self.cutout_center + self.origin @lazyproperty def slices(self): """ A tuple of two slices representing the cutout region with respect to the original (large) image. """ return (slice(self.origin[1], self.origin[1] + self.shape[1]), slice(self.origin[0], self.origin[0] + self.shape[0])) @lazyproperty def bbox(self): """ The minimal `~photutils.aperture.BoundingBox` for the cutout region with respect to the original (large) image. """ return BoundingBox(self.slices[1].start, self.slices[1].stop, self.slices[0].start, self.slices[0].stop) def estimate_flux(self): """ Estimate the star's flux by summing values in the input cutout array. Missing data is filled in by interpolation to better estimate the total flux. """ from .epsf import _interpolate_missing_data if np.any(self.mask): data_interp = _interpolate_missing_data(self.data, method='cubic', mask=self.mask) data_interp = _interpolate_missing_data(data_interp, method='nearest', mask=self.mask) flux = np.sum(data_interp, dtype=np.float64) else: flux = np.sum(self.data, dtype=np.float64) return flux def register_epsf(self, epsf): """ Register and scale (in flux) the input ``epsf`` to the star. Parameters ---------- epsf : `EPSFModel` The ePSF to register. Returns ------- data : `~numpy.ndarray` A 2D array of the registered/scaled ePSF. """ yy, xx = np.indices(self.shape, dtype=np.float) xx = xx - self.cutout_center[0] yy = yy - self.cutout_center[1] return self.flux * epsf.evaluate(xx, yy, flux=1.0, x_0=0.0, y_0=0.0) def compute_residual_image(self, epsf): """ Compute the residual image of the star data minus the registered/scaled ePSF. Parameters ---------- epsf : `EPSFModel` The ePSF to subtract. Returns ------- data : `~numpy.ndarray` A 2D array of the residual image. """ return self.data - self.register_epsf(epsf) @lazyproperty def _xy_idx(self): """ 1D arrays of x and y indices of unmasked pixels in the cutout reference frame. """ yidx, xidx = np.indices(self._data.shape) return xidx[~self.mask].ravel(), yidx[~self.mask].ravel() @lazyproperty def _xidx(self): """ 1D arrays of x indices of unmasked pixels in the cutout reference frame. """ return self._xy_idx[0] @lazyproperty def _yidx(self): """ 1D arrays of y indices of unmasked pixels in the cutout reference frame. """ return self._xy_idx[1] @property def _xidx_centered(self): """ 1D array of x indices of unmasked pixels, with respect to the star center, in the cutout reference frame. """ return self._xy_idx[0] - self.cutout_center[0] @property def _yidx_centered(self): """ 1D array of y indices of unmasked pixels, with respect to the star center, in the cutout reference frame. """ return self._xy_idx[1] - self.cutout_center[1] @lazyproperty def _data_values(self): """1D array of unmasked cutout data values.""" return self.data[~self.mask].ravel() @lazyproperty def _data_values_normalized(self): """ 1D array of unmasked cutout data values, normalized by the star's total flux. """ return self._data_values / self.flux @lazyproperty def _weight_values(self): """ 1D array of unmasked weight values. """ return self.weights[~self.mask].ravel() class EPSFStars: """ Class to hold a list of `EPSFStar` and/or `LinkedEPSFStar` objects. Parameters ---------- star_list : list of `EPSFStar` or `LinkedEPSFStar` objects A list of `EPSFStar` and/or `LinkedEPSFStar` objects. """ def __init__(self, stars_list): if isinstance(stars_list, (EPSFStar, LinkedEPSFStar)): self._data = [stars_list] elif isinstance(stars_list, list): self._data = stars_list else: raise ValueError('stars_list must be a list of EPSFStar and/or ' 'LinkedEPSFStar objects.') def __len__(self): return len(self._data) def __getitem__(self, index): return self._data[index] def __delitem__(self, index): del self._data[index] def __iter__(self): for i in self._data: yield i def __getattr__(self, attr): if attr in ['cutout_center', 'center', 'flux', '_excluded_from_fit']: return np.array([getattr(star, attr) for star in self._data]) else: return [getattr(star, attr) for star in self._data] def _getattr_flat(self, attr): values = [] for item in self._data: if isinstance(item, LinkedEPSFStar): values.extend(getattr(item, attr)) else: values.append(getattr(item, attr)) return np.array(values) @property def cutout_center_flat(self): """ A `~numpy.ndarray` of the ``(x, y)`` position of all the stars' centers (including linked stars) with respect to the input cutout ``data`` array, as a 2D array (``n_all_stars`` x 2). Note that when `EPSFStars` contains any `LinkedEPSFStar`, the ``cutout_center`` attribute will be a nested 3D array. """ return self._getattr_flat('cutout_center') @property def center_flat(self): """ A `~numpy.ndarray` of the ``(x, y)`` position of all the stars' centers (including linked stars) with respect to the original (large) image (not the cutout image) as a 2D array (``n_all_stars`` x 2). Note that when `EPSFStars` contains any `LinkedEPSFStar`, the ``center`` attribute will be a nested 3D array. """ return self._getattr_flat('center') @lazyproperty def all_stars(self): """ A list of all `EPSFStar` objects stored in this object, including those that comprise linked stars (i.e. `LinkedEPSFStar`), as a flat list. """ stars = [] for item in self._data: if isinstance(item, LinkedEPSFStar): stars.extend(item.all_stars) else: stars.append(item) return stars @property def all_good_stars(self): """ A list of all `EPSFStar` objects stored in this object that have not been excluded from fitting, including those that comprise linked stars (i.e. `LinkedEPSFStar`), as a flat list. """ stars = [] for star in self.all_stars: if star._excluded_from_fit: continue else: stars.append(star) return stars @lazyproperty def n_stars(self): """ The total number of stars. A linked star is counted only once. """ return len(self._data) @lazyproperty def n_all_stars(self): """ The total number of `EPSFStar` objects, including all the linked stars within `LinkedEPSFStar`. Each linked star is included in the count. """ return len(self.all_stars) @property def n_good_stars(self): """ The total number of `EPSFStar` objects, including all the linked stars within `LinkedEPSFStar`, that have not been excluded from fitting. Each non-excluded linked star is included in the count. """ return len(self.all_good_stars) @lazyproperty def _max_shape(self): """ The maximum x and y shapes of all the `EPSFStar`\\s (including linked stars). """ return np.max([star.shape for star in self.all_stars], axis=0) class LinkedEPSFStar(EPSFStars): """ A class to hold a list of `EPSFStar` objects for linked stars. Linked stars are `EPSFStar` cutouts from different images that represent the same physical star. When building the ePSF, linked stars are constrained to have the same sky coordinates. Parameters ---------- star_list : list of `EPSFStar` objects A list of `EPSFStar` objects for the same physical star. Each `EPSFStar` object must have a valid ``wcs_large`` attribute to convert between pixel and sky coordinates. """ def __init__(self, stars_list): for star in stars_list: if not isinstance(star, EPSFStar): raise ValueError('stars_list must contain only EPSFStar ' 'objects.') if star.wcs_large is None: raise ValueError('Each EPSFStar object must have a valid ' 'wcs_large attribute.') super().__init__(stars_list) def constrain_centers(self): """ Constrain the centers of linked `EPSFStar` objects (i.e. the same physical star) to have the same sky coordinate. Only `EPSFStar` objects that have not been excluded during the ePSF build process will be used to constrain the centers. The single sky coordinate is calculated as the mean of sky coordinates of the linked stars. """ if len(self._data) < 2: # no linked stars return idx = np.logical_not(self._excluded_from_fit).nonzero()[0] if idx.size == 0: warnings.warn('Cannot constrain centers of linked stars because ' 'all the stars have been excluded during the ePSF ' 'build process.', AstropyUserWarning) return good_stars = [self._data[i] for i in idx] coords = [] for star in good_stars: wcs = star.wcs_large xposition = star.center[0] yposition = star.center[1] try: coords.append(wcs.pixel_to_world_values(xposition, yposition)) except AttributeError: if isinstance(wcs, WCS): # for Astropy < 3.1 WCS support coords.append(wcs.all_pix2world(xposition, yposition, 0)) else: raise ValueError('Input wcs does not support the shared ' 'WCS interface.') # compute mean cartesian coordinates lon, lat = np.transpose(coords) lon *= np.pi / 180. lat *= np.pi / 180. x_mean = np.mean(np.cos(lat) * np.cos(lon)) y_mean = np.mean(np.cos(lat) * np.sin(lon)) z_mean = np.mean(np.sin(lat)) # convert mean cartesian coordinates back to spherical hypot = np.hypot(x_mean, y_mean) mean_lon = np.arctan2(y_mean, x_mean) mean_lat = np.arctan2(z_mean, hypot) mean_lon *= 180. / np.pi mean_lat *= 180. / np.pi # convert mean sky coordinates back to center pixel coordinates # for each star for star in good_stars: try: center = star.wcs_large.world_to_pixel_values(mean_lon, mean_lat) except AttributeError: # for Astropy < 3.1 WCS support center = star.wcs_large.all_world2pix(mean_lon, mean_lat, 0) star.cutout_center = np.array(center) - star.origin def extract_stars(data, catalogs, size=(11, 11)): """ Extract cutout images centered on stars defined in the input catalog(s). Stars where the cutout array bounds partially or completely lie outside of the input ``data`` image will not be extracted. Parameters ---------- data : `~astropy.nddata.NDData` or list of `~astropy.nddata.NDData` A `~astropy.nddata.NDData` object or a list of `~astropy.nddata.NDData` objects containing the 2D image(s) from which to extract the stars. If the input ``catalogs`` contain only the sky coordinates (i.e. not the pixel coordinates) of the stars then each of the `~astropy.nddata.NDData` objects must have a valid ``wcs`` attribute. catalogs : `~astropy.table.Table`, list of `~astropy.table.Table` A catalog or list of catalogs of sources to be extracted from the input ``data``. To link stars in multiple images as a single source, you must use a single source catalog where the positions defined in sky coordinates. If a list of catalogs is input (or a single catalog with a single `~astropy.nddata.NDData` object), they are assumed to correspond to the list of `~astropy.nddata.NDData` objects input in ``data`` (i.e. a separate source catalog for each 2D image). For this case, the center of each source can be defined either in pixel coordinates (in ``x`` and ``y`` columns) or sky coordinates (in a ``skycoord`` column containing a `~astropy.coordinates.SkyCoord` object). If both are specified, then the pixel coordinates will be used. If a single source catalog is input with multiple `~astropy.nddata.NDData` objects, then these sources will be extracted from every 2D image in the input ``data``. In this case, the sky coordinates for each source must be specified as a `~astropy.coordinates.SkyCoord` object contained in a column called ``skycoord``. Each `~astropy.nddata.NDData` object in the input ``data`` must also have a valid ``wcs`` attribute. Pixel coordinates (in ``x`` and ``y`` columns) will be ignored. Optionally, each catalog may also contain an ``id`` column representing the ID/name of stars. If this column is not present then the extracted stars will be given an ``id`` number corresponding the the table row number (starting at 1). Any other columns present in the input ``catalogs`` will be ignored. size : int or array_like (int), optional The extraction box size along each axis. If ``size`` is a scalar then a square box of size ``size`` will be used. If ``size`` has two elements, they should be in ``(ny, nx)`` order. The size must be greater than or equal to 3 pixel for both axes. Size must be odd in both axes; if either is even, it is padded by one to force oddness. Returns ------- stars : `EPSFStars` instance A `EPSFStars` instance containing the extracted stars. """ if isinstance(data, NDData): data = [data] if isinstance(catalogs, Table): catalogs = [catalogs] for img in data: if not isinstance(img, NDData): raise ValueError('data must be a single or list of NDData ' 'objects.') for cat in catalogs: if not isinstance(cat, Table): raise ValueError('catalogs must be a single or list of Table ' 'objects.') if len(catalogs) == 1 and len(data) > 1: if 'skycoord' not in catalogs[0].colnames: raise ValueError('When inputting a single catalog with multiple ' 'NDData objects, the catalog must have a ' '"skycoord" column.') if any([img.wcs is None for img in data]): raise ValueError('When inputting a single catalog with multiple ' 'NDData objects, each NDData object must have ' 'a wcs attribute.') else: for cat in catalogs: if 'x' not in cat.colnames or 'y' not in cat.colnames: if 'skycoord' not in cat.colnames: raise ValueError('When inputting multiple catalogs, ' 'each one must have a "x" and "y" ' 'column or a "skycoord" column.') else: if any([img.wcs is None for img in data]): raise ValueError('When inputting catalog(s) with ' 'only skycoord positions, each ' 'NDData object must have a wcs ' 'attribute.') if len(data) != len(catalogs): raise ValueError('When inputting multiple catalogs, the number ' 'of catalogs must match the number of input ' 'images.') size = np.atleast_1d(size) if len(size) == 1: size = np.repeat(size, 2) # Force size to odd numbers such that there is always a central pixel with # even spacing either side of the pixel. size = tuple(_size+1 if _size % 2 == 0 else _size for _size in size) min_size = 3 if size[0] < min_size or size[1] < min_size: raise ValueError('size must be >= {} for x and y'.format(min_size)) if len(catalogs) == 1: # may included linked stars use_xy = True if len(data) > 1: use_xy = False # linked stars require skycoord positions stars = [] # stars is a list of lists, one list of stars in each image for img in data: stars.append(_extract_stars(img, catalogs[0], size=size, use_xy=use_xy)) # transpose the list of lists, to associate linked stars stars = list(map(list, zip(*stars))) # remove 'None' stars (i.e. no or partial overlap in one or more # images) and handle the case of only one "linked" star stars_out = [] n_input = len(catalogs[0]) * len(data) n_extracted = 0 for star in stars: good_stars = [i for i in star if i is not None] n_extracted += len(good_stars) if not good_stars: continue # no overlap in any image elif len(good_stars) == 1: good_stars = good_stars[0] # only one star, cannot be linked else: good_stars = LinkedEPSFStar(good_stars) stars_out.append(good_stars) else: # no linked stars stars_out = [] for img, cat in zip(data, catalogs): stars_out.extend(_extract_stars(img, cat, size=size, use_xy=True)) n_input = len(stars_out) stars_out = [star for star in stars_out if star is not None] n_extracted = len(stars_out) n_excluded = n_input - n_extracted if n_excluded > 0: warnings.warn('{} star(s) were not extracted because their cutout ' 'region extended beyond the input image.' .format(n_excluded), AstropyUserWarning) return EPSFStars(stars_out) def _extract_stars(data, catalog, size=(11, 11), use_xy=True): """ Extract cutout images from a single image centered on stars defined in the single input catalog. Parameters ---------- data : `~astropy.nddata.NDData` A `~astropy.nddata.NDData` object containing the 2D image from which to extract the stars. If the input ``catalog`` contains only the sky coordinates (i.e. not the pixel coordinates) of the stars then the `~astropy.nddata.NDData` object must have a valid ``wcs`` attribute. catalogs : `~astropy.table.Table` A single catalog of sources to be extracted from the input ``data``. The center of each source can be defined either in pixel coordinates (in ``x`` and ``y`` columns) or sky coordinates (in a ``skycoord`` column containing a `~astropy.coordinates.SkyCoord` object). If both are specified, then the value of the ``use_xy`` keyword determines which coordinates will be used. size : int or array_like (int), optional The extraction box size along each axis. If ``size`` is a scalar then a square box of size ``size`` will be used. If ``size`` has two elements, they should be in ``(ny, nx)`` order. The size must be greater than or equal to 3 pixel for both axes. Size must be odd in both axes; if either is even, it is padded by one to force oddness. use_xy : bool, optional Whether to use the ``x`` and ``y`` pixel positions when both pixel and sky coordinates are present in the input catalog table. If `False` then sky coordinates are used instead of pixel coordinates (e.g. for linked stars). The default is `True`. Returns ------- stars : list of `EPSFStar` objects A list of `EPSFStar` instances containing the extracted stars. """ # Force size to odd numbers such that there is always a central pixel with # even spacing either side of the pixel. if np.isscalar(size): size = size+1 if size % 2 == 0 else size else: size = tuple(_size+1 if _size % 2 == 0 else _size for _size in size) colnames = catalog.colnames if ('x' not in colnames or 'y' not in colnames) or not use_xy: try: xcenters, ycenters = data.wcs.world_to_pixel(catalog['skycoord']) except AttributeError: # for Astropy < 3.1 WCS support xcenters, ycenters = skycoord_to_pixel(catalog['skycoord'], data.wcs, origin=0, mode='all') else: xcenters = catalog['x'].data.astype(np.float) ycenters = catalog['y'].data.astype(np.float) if 'id' in colnames: ids = catalog['id'] else: ids = np.arange(len(catalog), dtype=np.int) + 1 if data.uncertainty is None: weights = np.ones_like(data.data) else: if data.uncertainty.uncertainty_type == 'weights': weights = np.asanyarray(data.uncertainty.array, dtype=np.float) else: warnings.warn('The data uncertainty attribute has an unsupported ' 'type. Only uncertainty_type="weights" can be ' 'used to set weights. Weights will be set to 1.', AstropyUserWarning) weights = np.ones_like(data.data) if data.mask is not None: weights[data.mask] = 0. stars = [] for xcenter, ycenter, obj_id in zip(xcenters, ycenters, ids): try: large_slc, _ = overlap_slices(data.data.shape, size, (ycenter, xcenter), mode='strict') data_cutout = data.data[large_slc] weights_cutout = weights[large_slc] except (PartialOverlapError, NoOverlapError): stars.append(None) continue origin = (large_slc[1].start, large_slc[0].start) cutout_center = (xcenter - origin[0], ycenter - origin[1]) star = EPSFStar(data_cutout, weights_cutout, cutout_center=cutout_center, origin=origin, wcs_large=data.wcs, id_label=obj_id) stars.append(star) return stars photutils-0.7.2/photutils/psf/groupstars.py0000644000214200020070000002153313572573665023373 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides classes to perform grouping of stars. """ import abc from astropy.table import Column import numpy as np __all__ = ['DAOGroup', 'DBSCANGroup', 'GroupStarsBase'] class GroupStarsBase(metaclass=abc.ABCMeta): """ This base class provides the basic interface for subclasses that are capable of classifying stars in groups. """ def __call__(self, starlist): """ Classify stars into groups. Parameters ---------- starlist : `~astropy.table.Table` List of star positions. Columns named as ``x_0`` and ``y_0``, which corresponds to the centroid coordinates of the sources, must be provided. Returns ------- group_starlist : `~astropy.table.Table` ``starlist`` with an additional column named ``group_id`` whose unique values represent groups of mutually overlapping stars. """ return self.group_stars(starlist) @abc.abstractmethod def group_stars(self, starlist): """ Classify stars into groups. Parameters ---------- starlist : `~astropy.table.Table` List of star positions. Columns named as ``x_0`` and ``y_0``, which corresponds to the centroid coordinates of the sources, must be provided. Returns ------- group_starlist : `~astropy.table.Table` ``starlist`` with an additional column named ``group_id`` whose unique values represent groups of mutually overlapping stars. """ raise NotImplementedError('Needs to be implemented in a subclass.') class DAOGroup(GroupStarsBase): """ This class implements the DAOGROUP algorithm presented by Stetson (1987). The method ``group_stars`` divides an entire starlist into sets of distinct, self-contained groups of mutually overlapping stars. It accepts as input a list of stars and determines which stars are close enough to be capable of adversely influencing each others' profile fits. Parameters ---------- crit_separation : float or int Distance, in units of pixels, such that any two stars separated by less than this distance will be placed in the same group. Notes ----- Assuming the psf fwhm to be known, ``crit_separation`` may be set to k*fwhm, for some positive real k. See Also -------- photutils.detection.DAOStarFinder References ---------- [1] Stetson, Astronomical Society of the Pacific, Publications, (ISSN 0004-6280), vol. 99, March 1987, p. 191-222. Available at: http://adsabs.harvard.edu/abs/1987PASP...99..191S """ def __init__(self, crit_separation): self.crit_separation = crit_separation @property def crit_separation(self): return self._crit_separation @crit_separation.setter def crit_separation(self, crit_separation): if not isinstance(crit_separation, (float, int)): raise ValueError('crit_separation is expected to be either ' 'float or int. Received {}.' .format(type(crit_separation))) elif crit_separation < 0.0: raise ValueError('crit_separation is expected to be a positive ' 'real number. Got {}'.format(crit_separation)) else: self._crit_separation = crit_separation def group_stars(self, starlist): cstarlist = starlist.copy() if 'id' not in cstarlist.colnames: cstarlist.add_column(Column(name='id', data=np.arange(len(cstarlist)) + 1)) cstarlist.add_column(Column(name='group_id', data=np.zeros(len(cstarlist), dtype=int))) if not np.array_equal(cstarlist['id'], np.arange(len(cstarlist)) + 1): raise ValueError('id colum must be an integer-valued ' + 'sequence starting from 1. ' + 'Got {}'.format(cstarlist['id'])) n = 1 while (cstarlist['group_id'] == 0).sum() > 0: init_star = cstarlist[np.where(cstarlist['group_id'] == 0)[0][0]] index = self.find_group(init_star, cstarlist[cstarlist['group_id'] == 0]) cstarlist['group_id'][index-1] = n k = 1 K = len(index) while k < K: init_star = cstarlist[cstarlist['id'] == index[k]] tmp_index = self.find_group( init_star, cstarlist[cstarlist['group_id'] == 0]) if len(tmp_index) > 0: cstarlist['group_id'][tmp_index-1] = n index = np.append(index, tmp_index) K = len(index) k += 1 n += 1 return cstarlist def find_group(self, star, starlist): """ Find the ids of those stars in ``starlist`` which are at a distance less than ``crit_separation`` from ``star``. Parameters ---------- star : `~astropy.table.Row` Star which will be either the head of a cluster or an isolated one. starlist : `~astropy.table.Table` List of star positions. Columns named as ``x_0`` and ``y_0``, which corresponds to the centroid coordinates of the sources, must be provided. Returns ------- Array containing the ids of those stars which are at a distance less than ``crit_separation`` from ``star``. """ star_distance = np.hypot(star['x_0'] - starlist['x_0'], star['y_0'] - starlist['y_0']) distance_criteria = star_distance < self.crit_separation return np.asarray(starlist[distance_criteria]['id']) class DBSCANGroup(GroupStarsBase): """ Class to create star groups according to a distance criteria using the Density-based Spatial Clustering of Applications with Noise (DBSCAN) from scikit-learn. Parameters ---------- crit_separation : float or int Distance, in units of pixels, such that any two stars separated by less than this distance will be placed in the same group. min_samples : int, optional (default=1) Minimum number of stars necessary to form a group. metric : string or callable (default='euclidean') The metric to use when calculating distance between each pair of stars. algorithm : {'auto', 'ball_tree', 'kd_tree', 'brute'}, optional The algorithm to be used to actually find nearest neighbors. leaf_size : int, optional (default = 30) Leaf size passed to BallTree or cKDTree. References ---------- [1] Scikit Learn DBSCAN. https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html#sklearn.cluster.DBSCAN Notes ----- * The attribute ``crit_separation`` corresponds to ``eps`` in `sklearn.cluster.DBSCAN `_. * This class provides more general algorithms than `photutils.psf.DAOGroup`. More precisely, `photutils.psf.DAOGroup` is a special case of `photutils.psf.DBSCANGroup` when ``min_samples=1`` and ``metric=euclidean``. Additionally, `photutils.psf.DBSCANGroup` may be faster than `photutils.psf.DAOGroup`. """ def __init__(self, crit_separation, min_samples=1, metric='euclidean', algorithm='auto', leaf_size=30): self.crit_separation = crit_separation self.min_samples = min_samples self.metric = metric self.algorithm = algorithm self.leaf_size = leaf_size def group_stars(self, starlist): from sklearn.cluster import DBSCAN cstarlist = starlist.copy() if 'id' not in cstarlist.colnames: cstarlist.add_column(Column(name='id', data=np.arange(len(cstarlist)) + 1)) if not np.array_equal(cstarlist['id'], np.arange(len(cstarlist)) + 1): raise ValueError('id colum must be an integer-valued ' + 'sequence starting from 1. ' + 'Got {}'.format(cstarlist['id'])) pos_stars = np.transpose((cstarlist['x_0'], cstarlist['y_0'])) dbscan = DBSCAN(eps=self.crit_separation, min_samples=self.min_samples, metric=self.metric, algorithm=self.algorithm, leaf_size=self.leaf_size) cstarlist['group_id'] = (dbscan.fit(pos_stars).labels_ + np.ones(len(cstarlist), dtype=int)) return cstarlist photutils-0.7.2/photutils/psf/matching/0000755000214200020070000000000013573510273022361 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/psf/matching/__init__.py0000644000214200020070000000033713563423715024500 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage contains tools to generate kernels for matching point spread functions. """ from .fourier import * # noqa from .windows import * # noqa photutils-0.7.2/photutils/psf/matching/fourier.py0000644000214200020070000000652413563423715024420 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for matching PSFs using Fourier methods. """ import numpy as np from numpy.fft import fft2, ifft2, fftshift, ifftshift __all__ = ['resize_psf', 'create_matching_kernel'] def resize_psf(psf, input_pixel_scale, output_pixel_scale, order=3): """ Resize a PSF using spline interpolation of the requested order. Parameters ---------- psf : 2D `~numpy.ndarray` The 2D data array of the PSF. input_pixel_scale : float The pixel scale of the input ``psf``. The units must match ``output_pixel_scale``. output_pixel_scale : float The pixel scale of the output ``psf``. The units must match ``input_pixel_scale``. order : float, optional The order of the spline interpolation (0-5). The default is 3. Returns ------- result : 2D `~numpy.ndarray` The resampled/interpolated 2D data array. """ from scipy.ndimage import zoom ratio = input_pixel_scale / output_pixel_scale return zoom(psf, ratio, order=order) / ratio**2 def create_matching_kernel(source_psf, target_psf, window=None): """ Create a kernel to match 2D point spread functions (PSF) using the ratio of Fourier transforms. Parameters ---------- source_psf : 2D `~numpy.ndarray` The source PSF. The source PSF should have higher resolution (i.e. narrower) than the target PSF. ``source_psf`` and ``target_psf`` must have the same shape and pixel scale. target_psf : 2D `~numpy.ndarray` The target PSF. The target PSF should have lower resolution (i.e. broader) than the source PSF. ``source_psf`` and ``target_psf`` must have the same shape and pixel scale. window : callable, optional The window (or taper) function or callable class instance used to remove high frequency noise from the PSF matching kernel. Some examples include: * `~photutils.psf.matching.HanningWindow` * `~photutils.psf.matching.TukeyWindow` * `~photutils.psf.matching.CosineBellWindow` * `~photutils.psf.matching.SplitCosineBellWindow` * `~photutils.psf.matching.TopHatWindow` For more information on window functions and example usage, see :ref:`psf_matching`. Returns ------- kernel : 2D `~numpy.ndarray` The matching kernel to go from ``source_psf`` to ``target_psf``. The output matching kernel is normalized such that it sums to 1. """ # inputs are copied so that they are not changed when normalizing source_psf = np.copy(np.asanyarray(source_psf)) target_psf = np.copy(np.asanyarray(target_psf)) if source_psf.shape != target_psf.shape: raise ValueError('source_psf and target_psf must have the same shape ' '(i.e. registered with the same pixel scale).') # ensure input PSFs are normalized source_psf /= source_psf.sum() target_psf /= target_psf.sum() source_otf = fftshift(fft2(source_psf)) target_otf = fftshift(fft2(target_psf)) ratio = target_otf / source_otf # apply a window function in frequency space if window is not None: ratio *= window(target_psf.shape) kernel = np.real(fftshift((ifft2(ifftshift(ratio))))) return kernel / kernel.sum() photutils-0.7.2/photutils/psf/matching/tests/0000755000214200020070000000000013573510273023523 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/psf/matching/tests/__init__.py0000644000214200020070000000000013563423715025625 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/psf/matching/tests/test_fourier.py0000644000214200020070000000277713563423715026627 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the fourier module. """ from astropy.modeling.fitting import LevMarLSQFitter from astropy.modeling.models import Gaussian2D import numpy as np from numpy.testing import assert_allclose import pytest from ..fourier import create_matching_kernel, resize_psf from ..windows import SplitCosineBellWindow try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False @pytest.mark.skipif('not HAS_SCIPY') def test_resize_psf(): psf1 = np.ones((5, 5)) psf2 = resize_psf(psf1, 0.1, 0.05) assert psf2.shape == (10, 10) @pytest.mark.skipif('not HAS_SCIPY') def test_create_matching_kernel(): """Test with noiseless 2D Gaussians.""" size = 25 cen = (size - 1) / 2. y, x = np.mgrid[0:size, 0:size] std1 = 3. std2 = 5. gm1 = Gaussian2D(1., cen, cen, std1, std1) gm2 = Gaussian2D(1., cen, cen, std2, std2) g1 = gm1(x, y) g2 = gm2(x, y) g1 /= g1.sum() g2 /= g2.sum() window = SplitCosineBellWindow(0.0, 0.2) k = create_matching_kernel(g1, g2, window=window) fitter = LevMarLSQFitter() gfit = fitter(gm1, x, y, k) assert_allclose(gfit.x_stddev, gfit.y_stddev) assert_allclose(gfit.x_stddev, np.sqrt(std2**2 - std1**2), 0.06) def test_create_matching_kernel_shapes(): """Test with wrong PSF shapes.""" with pytest.raises(ValueError): psf1 = np.ones((5, 5)) psf2 = np.ones((3, 3)) create_matching_kernel(psf1, psf2) photutils-0.7.2/photutils/psf/matching/tests/test_windows.py0000644000214200020070000000377313563423715026643 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the windows module. """ import numpy as np from numpy.testing import assert_allclose import pytest from ..windows import (CosineBellWindow, HanningWindow, SplitCosineBellWindow, TopHatWindow, TukeyWindow) try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False def test_hanning(): win = HanningWindow() data = win((5, 5)) ref = [0., 0.19715007, 0.5, 0.19715007, 0.] assert_allclose(data[1, :], ref) def test_hanning_numpy(): """Test Hanning window against 1D numpy version.""" size = 101 cen = (size - 1) // 2 shape = (size, size) win = HanningWindow() data = win(shape) ref1d = np.hanning(shape[0]) assert_allclose(data[cen, :], ref1d) def test_tukey(): win = TukeyWindow(0.5) data = win((5, 5)) ref = [0., 0.63312767, 1., 0.63312767, 0.] assert_allclose(data[1, :], ref) @pytest.mark.skipif('not HAS_SCIPY') def test_tukey_scipy(): """Test Tukey window against 1D scipy version.""" # scipy.signal.tukey was introduced in Scipy v0.16.0 from scipy.signal import tukey size = 101 cen = (size - 1) // 2 shape = (size, size) alpha = 0.4 win = TukeyWindow(alpha=alpha) data = win(shape) ref1d = tukey(shape[0], alpha=alpha) assert_allclose(data[cen, :], ref1d) def test_cosine_bell(): win = CosineBellWindow(alpha=0.8) data = win((7, 7)) ref = [0., 0., 0.19715007, 0.5, 0.19715007, 0., 0.] assert_allclose(data[2, :], ref) def test_split_cosine_bell(): win = SplitCosineBellWindow(alpha=0.8, beta=0.2) data = win((5, 5)) ref = [0., 0.3454915, 1., 0.3454915, 0.] assert_allclose(data[2, :], ref) def test_tophat(): win = TopHatWindow(beta=0.5) data = win((5, 5)) ref = [0., 1., 1., 1., 0.] assert_allclose(data[2, :], ref) def test_invalid_shape(): with pytest.raises(ValueError): win = HanningWindow() win((5,)) photutils-0.7.2/photutils/psf/matching/windows.py0000644000214200020070000001512513563423715024434 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides window (or tapering) functions for matching PSFs using Fourier methods. """ import numpy as np __all__ = ['SplitCosineBellWindow', 'HanningWindow', 'TukeyWindow', 'CosineBellWindow', 'TopHatWindow'] def _radial_distance(shape): """ Return an array where each value is the Euclidean distance from the array center. Parameters ---------- shape : tuple of int The size of the output array along each axis. Returns ------- result : `~numpy.ndarray` An array containing the Euclidian radial distances from the array center. """ if len(shape) != 2: raise ValueError('shape must have only 2 elements') position = (np.asarray(shape) - 1) / 2. x = np.arange(shape[1]) - position[1] y = np.arange(shape[0]) - position[0] xx, yy = np.meshgrid(x, y) return np.sqrt(xx**2 + yy**2) class SplitCosineBellWindow: """ Class to define a 2D split cosine bell taper function. Parameters ---------- alpha : float, optional The percentage of array values that are tapered. beta : float, optional The inner diameter as a fraction of the array size beyond which the taper begins. ``beta`` must be less or equal to 1.0. Examples -------- .. plot:: :include-source: import matplotlib.pyplot as plt from photutils import SplitCosineBellWindow taper = SplitCosineBellWindow(alpha=0.4, beta=0.3) data = taper((101, 101)) plt.imshow(data, cmap='viridis', origin='lower') plt.colorbar() A 1D cut across the image center: .. plot:: :include-source: import matplotlib.pyplot as plt from photutils import SplitCosineBellWindow taper = SplitCosineBellWindow(alpha=0.4, beta=0.3) data = taper((101, 101)) plt.plot(data[50, :]) """ def __init__(self, alpha, beta): self.alpha = alpha self.beta = beta def __call__(self, shape): """ Return a 2D split cosine bell. Parameters ---------- shape : tuple of int The size of the output array along each axis. Returns ------- result : `~numpy.ndarray` A 2D array containing the cosine bell values. """ radial_dist = _radial_distance(shape) npts = (np.array(shape).min() - 1.) / 2. r_inner = self.beta * npts r = radial_dist - r_inner r_taper = int(np.floor(self.alpha * npts)) if r_taper != 0: f = 0.5 * (1.0 + np.cos(np.pi * r / r_taper)) else: f = np.ones(shape) f[radial_dist < r_inner] = 1. r_cut = r_inner + r_taper f[radial_dist > r_cut] = 0. return f class HanningWindow(SplitCosineBellWindow): """ Class to define a 2D `Hanning (or Hann) window `_ function. The Hann window is a taper formed by using a raised cosine with ends that touch zero. Examples -------- .. plot:: :include-source: import matplotlib.pyplot as plt from photutils import HanningWindow taper = HanningWindow() data = taper((101, 101)) plt.imshow(data, cmap='viridis', origin='lower') plt.colorbar() A 1D cut across the image center: .. plot:: :include-source: import matplotlib.pyplot as plt from photutils import HanningWindow taper = HanningWindow() data = taper((101, 101)) plt.plot(data[50, :]) """ def __init__(self): super().__init__(alpha=1.0, beta=0.0) class TukeyWindow(SplitCosineBellWindow): """ Class to define a 2D `Tukey window `_ function. The Tukey window is a taper formed by using a split cosine bell function with ends that touch zero. Parameters ---------- alpha : float, optional The percentage of array values that are tapered. Examples -------- .. plot:: :include-source: import matplotlib.pyplot as plt from photutils import TukeyWindow taper = TukeyWindow(alpha=0.4) data = taper((101, 101)) plt.imshow(data, cmap='viridis', origin='lower') plt.colorbar() A 1D cut across the image center: .. plot:: :include-source: import matplotlib.pyplot as plt from photutils import TukeyWindow taper = TukeyWindow(alpha=0.4) data = taper((101, 101)) plt.plot(data[50, :]) """ def __init__(self, alpha): super().__init__(alpha=alpha, beta=1.0 - alpha) class CosineBellWindow(SplitCosineBellWindow): """ Class to define a 2D cosine bell window function. Parameters ---------- alpha : float, optional The percentage of array values that are tapered. Examples -------- .. plot:: :include-source: import matplotlib.pyplot as plt from photutils import CosineBellWindow taper = CosineBellWindow(alpha=0.3) data = taper((101, 101)) plt.imshow(data, cmap='viridis', origin='lower') plt.colorbar() A 1D cut across the image center: .. plot:: :include-source: import matplotlib.pyplot as plt from photutils import CosineBellWindow taper = CosineBellWindow(alpha=0.3) data = taper((101, 101)) plt.plot(data[50, :]) """ def __init__(self, alpha): super().__init__(alpha=alpha, beta=0.0) class TopHatWindow(SplitCosineBellWindow): """ Class to define a 2D top hat window function. Parameters ---------- beta : float, optional The inner diameter as a fraction of the array size beyond which the taper begins. ``beta`` must be less or equal to 1.0. Examples -------- .. plot:: :include-source: import matplotlib.pyplot as plt from photutils import TopHatWindow taper = TopHatWindow(beta=0.4) data = taper((101, 101)) plt.imshow(data, cmap='viridis', origin='lower', interpolation='nearest') plt.colorbar() A 1D cut across the image center: .. plot:: :include-source: import matplotlib.pyplot as plt from photutils import TopHatWindow taper = TopHatWindow(beta=0.4) data = taper((101, 101)) plt.plot(data[50, :]) """ def __init__(self, beta): super().__init__(alpha=0.0, beta=beta) photutils-0.7.2/photutils/psf/models.py0000644000214200020070000012645413572236170022440 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides models for doing PSF/PRF-fitting photometry. """ import copy import itertools import warnings from astropy.modeling import Fittable2DModel, Parameter from astropy.nddata import NDData from astropy.utils.exceptions import AstropyWarning import numpy as np __all__ = ['NonNormalizable', 'FittableImageModel', 'EPSFModel', 'GriddedPSFModel', 'IntegratedGaussianPRF', 'PRFAdapter'] class NonNormalizable(AstropyWarning): """ Used to indicate that a :py:class:`FittableImageModel` model is non-normalizable. """ class FittableImageModel(Fittable2DModel): """ A fittable 2D model of an image allowing for image intensity scaling and image translations. This class takes 2D image data and computes the values of the model at arbitrary locations (including at intra-pixel, fractional positions) within this image using spline interpolation provided by :py:class:`~scipy.interpolate.RectBivariateSpline`. The fittable model provided by this class has three model parameters: an image intensity scaling factor (``flux``) which is applied to (normalized) image, and two positional parameters (``x_0`` and ``y_0``) indicating the location of a feature in the coordinate grid on which the model is to be evaluated. If this class is initialized with ``flux`` (intensity scaling factor) set to `None`, then ``flux`` is going to be estimated as ``sum(data)``. Parameters ---------- data : numpy.ndarray Array containing 2D image. origin : tuple, None, optional A reference point in the input image ``data`` array. When origin is `None`, origin will be set at the middle of the image array. If ``origin`` represents the location of a feature (e.g., the position of an intensity peak) in the input ``data``, then model parameters ``x_0`` and ``y_0`` show the location of this peak in an another target image to which this model was fitted. Fundamentally, it is the coordinate in the model's image data that should map to coordinate (``x_0``, ``y_0``) of the output coordinate system on which the model is evaluated. Alternatively, when ``origin`` is set to ``(0,0)``, then model parameters ``x_0`` and ``y_0`` are shifts by which model's image should be translated in order to match a target image. normalize : bool, optional Indicates whether or not the model should be build on normalized input image data. If true, then the normalization constant (*N*) is computed so that .. math:: N \\cdot C \\cdot \\sum\\limits_{i,j} D_{i,j} = 1, where *N* is the normalization constant, *C* is correction factor given by the parameter ``normalization_correction``, and :math:`D_{i,j}` are the elements of the input image ``data`` array. normalization_correction : float, optional A strictly positive number that represents correction that needs to be applied to model's data normalization (see *C* in the equation in the comments to ``normalize`` for more details). A possible application for this parameter is to account for aperture correction. Assuming model's data represent a PSF to be fitted to some target star, we set ``normalization_correction`` to the aperture correction that needs to be applied to the model. That is, ``normalization_correction`` in this case should be set to the ratio between the total flux of the PSF (including flux outside model's data) to the flux of model's data. Then, best fitted value of the ``flux`` model parameter will represent an aperture-corrected flux of the target star. In the case of aperture correction, ``normalization_correction`` should be a value larger than one, as the total flux, including regions outside of the aperture, should be larger than the flux inside the aperture, and thus the correction is applied as an inversely multiplied factor. fill_value : float, optional The value to be returned by the `evaluate` or ``astropy.modeling.Model.__call__`` methods when evaluation is performed outside the definition domain of the model. kwargs : dict, optional Additional optional keyword arguments to be passed directly to the `compute_interpolator` method. See `compute_interpolator` for more details. oversampling : float or tuple of two floats, optional The oversampling factor(s) of the model in the ``x`` and ``y`` directions. If ``oversampling`` is a scalar it will be treated as being the same in both x and y; otherwise a tuple of two floats will be treated as ``(x_oversamp, y_oversamp)``. """ flux = Parameter(description='Intensity scaling factor for image data.', default=1.0) x_0 = Parameter(description='X-position of a feature in the image in ' 'the output coordinate grid on which the model is ' 'evaluated.', default=0.0) y_0 = Parameter(description='Y-position of a feature in the image in ' 'the output coordinate grid on which the model is ' 'evaluated.', default=0.0) def __init__(self, data, flux=flux.default, x_0=x_0.default, y_0=y_0.default, normalize=False, normalization_correction=1.0, origin=None, oversampling=1, fill_value=0.0, **kwargs): self._fill_value = fill_value self._img_norm = None self._normalization_status = 0 if normalize else 2 self._store_interpolator_kwargs(**kwargs) self._set_oversampling(oversampling) if normalization_correction <= 0: raise ValueError("'normalization_correction' must be strictly " "positive.") self._normalization_correction = normalization_correction self._data = np.array(data, copy=True, dtype=np.float64) if not np.all(np.isfinite(self._data)): raise ValueError("All elements of input 'data' must be finite.") # set input image related parameters: self._ny, self._nx = self._data.shape self._shape = self._data.shape if self._data.size < 1: raise ValueError("Image data array cannot be zero-sized.") # set the origin of the coordinate system in image's pixel grid: self.origin = origin flux = self._initial_norm(flux, normalize) super().__init__(flux, x_0, y_0) # initialize interpolator: self.compute_interpolator(**kwargs) def _initial_norm(self, flux, normalize): if flux is None: if self._img_norm is None: self._img_norm = self._compute_raw_image_norm() flux = self._img_norm self._compute_normalization(normalize) return flux def _compute_raw_image_norm(self): """ Helper function that computes the uncorrected inverse normalization factor of input image data. This quantity is computed as the *sum of all pixel values*. .. note:: This function is intended to be overriden in a subclass if one desires to change the way the normalization factor is computed. """ return np.sum(self._data, dtype=np.float64) def _compute_normalization(self, normalize): """ Helper function that computes (corrected) normalization factor of the original image data. This quantity is computed as the inverse "raw image norm" (or total "flux" of model's image) corrected by the ``normalization_correction``: .. math:: N = 1/(\\Phi * C), where :math:`\\Phi` is the "total flux" of model's image as computed by `_compute_raw_image_norm` and *C* is the normalization correction factor. :math:`\\Phi` is computed only once if it has not been previously computed. Otherwise, the existing (stored) value of :math:`\\Phi` is not modified as :py:class:`FittableImageModel` does not allow image data to be modified after the object is created. .. note:: Normally, this function should not be called by the end-user. It is intended to be overriden in a subclass if one desires to change the way the normalization factor is computed. """ self._normalization_constant = 1.0 / self._normalization_correction if normalize: # compute normalization constant so that # N*C*sum(data) = 1: if self._img_norm is None: self._img_norm = self._compute_raw_image_norm() if self._img_norm != 0.0 and np.isfinite(self._img_norm): self._normalization_constant /= self._img_norm self._normalization_status = 0 else: self._normalization_constant = 1.0 self._normalization_status = 1 warnings.warn("Overflow encountered while computing " "normalization constant. Normalization " "constant will be set to 1.", NonNormalizable) else: self._normalization_status = 2 @property def oversampling(self): """ The factor by which the stored image is oversampled. I.e., an input to this model is multipled by this factor to yield the index into the stored image. """ return self._oversampling def _set_oversampling(self, value): """ This is a private method because it's used in the initializer by the ``oversampling`` """ try: value = np.atleast_1d(value).astype(float) if len(value) == 1: value = np.repeat(value, 2) except ValueError: raise ValueError('Oversampling factors must be float') if np.any(value <= 0): raise ValueError('Oversampling factors must be greater than 0') self._oversampling = value @property def data(self): """ Get original image data. """ return self._data @property def normalized_data(self): """Get normalized and/or intensity-corrected image data.""" return self._normalization_constant * self._data @property def normalization_constant(self): """ Get normalization constant. """ return self._normalization_constant @property def normalization_status(self): """ Get normalization status. Possible status values are: - 0: **Performed**. Model has been successfuly normalized at user's request. - 1: **Failed**. Attempt to normalize has failed. - 2: **NotRequested**. User did not request model to be normalized. """ return self._normalization_status @property def normalization_correction(self): """ Set/Get flux correction factor. .. note:: When setting correction factor, model's flux will be adjusted accordingly such that if this model was a good fit to some target image before, then it will remain a good fit after correction factor change. """ return self._normalization_correction @normalization_correction.setter def normalization_correction(self, normalization_correction): old_cf = self._normalization_correction self._normalization_correction = normalization_correction self._compute_normalization(normalize=self._normalization_status != 2) # adjust model's flux so that if this model was a good fit to # some target image, then it will remain a good fit after # correction factor change: self.flux *= normalization_correction / old_cf @property def shape(self): """ A tuple of dimensions of the data array in numpy style (ny, nx). """ return self._shape @property def nx(self): """Number of columns in the data array.""" return self._nx @property def ny(self): """Number of rows in the data array.""" return self._ny @property def origin(self): """ A tuple of ``x`` and ``y`` coordinates of the origin of the coordinate system in terms of pixels of model's image. When setting the coordinate system origin, a tuple of two `int` or `float` may be used. If origin is set to `None`, the origin of the coordinate system will be set to the middle of the data array (``(npix-1)/2.0``). .. warning:: Modifying ``origin`` will not adjust (modify) model's parameters ``x_0`` and ``y_0``. """ return (self._x_origin, self._y_origin) @origin.setter def origin(self, origin): if origin is None: self._x_origin = (self._nx - 1) / 2.0 self._y_origin = (self._ny - 1) / 2.0 elif hasattr(origin, '__iter__') and len(origin) == 2: self._x_origin, self._y_origin = origin else: raise TypeError("Parameter 'origin' must be either None or an " "iterable with two elements.") @property def x_origin(self): """X-coordinate of the origin of the coordinate system.""" return self._x_origin @property def y_origin(self): """Y-coordinate of the origin of the coordinate system.""" return self._y_origin @property def fill_value(self): """ Fill value to be returned for coordinates outside of the domain of definition of the interpolator. If ``fill_value`` is `None`, then values outside of the domain of definition are the ones returned by the interpolator. """ return self._fill_value @fill_value.setter def fill_value(self, fill_value): self._fill_value = fill_value def _store_interpolator_kwargs(self, **kwargs): """ This function should be called in a subclass whenever model's interpolator is (re-)computed. """ self._interpolator_kwargs = copy.deepcopy(kwargs) @property def interpolator_kwargs(self): """ Get current interpolator's arguments used when interpolator was created. """ return self._interpolator_kwargs def compute_interpolator(self, **kwargs): """ Compute/define the interpolating spline. This function can be overriden in a subclass to define custom interpolators. Parameters ---------- kwargs : dict, optional Additional optional keyword arguments: - **degree** : int, tuple, optional Degree of the interpolating spline. A tuple can be used to provide different degrees for the X- and Y-axes. Default value is degree=3. - **s** : float, optional Non-negative smoothing factor. Default value s=0 corresponds to interpolation. See :py:class:`~scipy.interpolate.RectBivariateSpline` for more details. Notes ----- * When subclassing :py:class:`FittableImageModel` for the purpose of overriding :py:func:`compute_interpolator`, the :py:func:`evaluate` may need to overriden as well depending on the behavior of the new interpolator. In addition, for improved future compatibility, make sure that the overriding method stores keyword arguments ``kwargs`` by calling ``_store_interpolator_kwargs`` method. * Use caution when modifying interpolator's degree or smoothness in a computationally intensive part of the code as it may decrease code performance due to the need to recompute interpolator. """ from scipy.interpolate import RectBivariateSpline if 'degree' in kwargs: degree = kwargs['degree'] if hasattr(degree, '__iter__') and len(degree) == 2: degx = int(degree[0]) degy = int(degree[1]) else: degx = int(degree) degy = int(degree) if degx < 0 or degy < 0: raise ValueError("Interpolator degree must be a non-negative " "integer") else: degx = 3 degy = 3 smoothness = kwargs.get('s', 0) x = np.arange(self._nx, dtype=np.float) y = np.arange(self._ny, dtype=np.float) self.interpolator = RectBivariateSpline( x, y, self._data.T, kx=degx, ky=degy, s=smoothness ) self._store_interpolator_kwargs(**kwargs) def evaluate(self, x, y, flux, x_0, y_0, use_oversampling=True): """ Evaluate the model on some input variables and provided model parameters. Parameters ---------- use_oversampling : bool, optional Whether to use the oversampling factor to calculate the model pixel indices. The default is `True`, which means the input indices will be multipled by this factor. """ if use_oversampling: xi = self._oversampling[0] * (np.asarray(x) - x_0) yi = self._oversampling[1] * (np.asarray(y) - y_0) else: xi = np.asarray(x) - x_0 yi = np.asarray(y) - y_0 xi += self._x_origin yi += self._y_origin f = flux * self._normalization_constant evaluated_model = f * self.interpolator.ev(xi, yi) if self._fill_value is not None: # find indices of pixels that are outside the input pixel grid and # set these pixels to the 'fill_value': invalid = (((xi < 0) | (xi > self._nx - 1)) | ((yi < 0) | (yi > self._ny - 1))) evaluated_model[invalid] = self._fill_value return evaluated_model class EPSFModel(FittableImageModel): """ A class that models an effective PSF (ePSF). While this class is a subclass of `FittableImageModel`, it is very similar. The primary differences/motivation are a few additional parameters necessary specifically for ePSFs. Parameters ---------- oversampling : int or tuple of two int, optional The oversampling factor(s) of the model in the ``x`` and ``y`` directions. If ``oversampling`` is a scalar it will be treated as being the same in both x and y; otherwise a tuple of two floats will be treated as ``(x_oversamp, y_oversamp)``. norm_radius : float, optional The radius inside which the ePSF is normalized by the sum over undersampled integer pixel values inside a circular aperture. shift_val : float, optional The fractional undersampled pixel amount (equivalent to an integer oversampled pixel value) at which to evaluate the asymmetric ePSF centroid corrections. """ def __init__(self, data, flux=1.0, x_0=0.0, y_0=0.0, normalize=True, normalization_correction=1.0, origin=None, oversampling=1, fill_value=0.0, norm_radius=5.5, shift_val=0.5, **kwargs): self._norm_radius = norm_radius self._shift_val = shift_val super().__init__(data=data, flux=flux, x_0=x_0, y_0=y_0, normalize=normalize, normalization_correction=normalization_correction, origin=origin, oversampling=oversampling, fill_value=fill_value, **kwargs) def _initial_norm(self, flux, normalize): if flux is None: if self._img_norm is None: self._img_norm = self._compute_raw_image_norm() flux = self._img_norm if normalize: self._compute_normalization() else: self._img_norm = self._compute_raw_image_norm() return flux def _compute_raw_image_norm(self): """ Helper function that computes the normalization of input image data. This quantity is computed as the sum of all undersampled integer pixel values within radius pixels of the center of the ePSF. """ # First need the indices of each axis at the oversampled # resolution; if oversampling = 4 then x = [0, 0.25, 0.5, 0.75, ...] x = np.arange(self._nx, dtype=np.float64) / self.oversampling[0] y = np.arange(self._ny, dtype=np.float64) / self.oversampling[1] # Take indices where the undersampled grid is an integer -- # i.e., the actual undersampled grid -- and find the cut where # sqrt(dx**2 + dy**2) <= radius x_0, y_0 = int((self._nx - 1) / 2), int((self._ny - 1) / 2) # However, as we are in units of the undersampled grid, we must # convert to undersampled units by the same factor of oversampling x_0 /= self.oversampling[0] y_0 /= self.oversampling[1] # When checking if the index is at the center of a pixel, we # check such that the index number is half that of the # oversampling -- if we oversample by a factor 4 then the middle # pixel of the 0th large pixel is 2 ([0, 1, 2, 3, 4]). For this to # work we require oversampling to be an even number; otherwise, # the ``middle'' pixel will be halfway between two oversampled # pixels. over_index_middle = 1 / 2 cut = (((x.reshape(1, -1) - x_0)**2 + (y.reshape(-1, 1) - y_0)**2 <= self._norm_radius**2) & (x.reshape(1, -1) % 1.0 == over_index_middle) & (y.reshape(-1, 1) % 1.0 == over_index_middle)) return np.sum(self._data[cut], dtype=np.float64) def _compute_normalization(self): """ Helper function that computes (corrected) normalization factor of the original image data. For the ePSF this is defined as the sum over the inner N (default=5.5) pixels of the non-oversampled image. Will re-normalize the data to the value calculated. """ if self._img_norm is None: if np.sum(self._data) == 0: self._img_norm = 1 else: self._img_norm = self._compute_raw_image_norm() if self._img_norm != 0.0 and np.isfinite(self._img_norm): self._data /= (self._img_norm * self._normalization_correction) self._normalization_status = 0 else: self._normalization_status = 1 self._img_norm = 1 warnings.warn("Overflow encountered while computing " "normalization constant. Normalization " "constant will be set to 1.", NonNormalizable) def _set_oversampling(self, value): try: value = np.atleast_1d(value).astype(int) if len(value) == 1: value = np.repeat(value, 2) # We need oversampling to be a factor of 2 for ``middle of # pixel'' in the undersampled regime to have a pixel placed at # it in the oversampled regime. if np.any(value % 2 != 0) and np.logical_not(np.all(value == 1)): raise ValueError('Oversampling factor must be a multiple of ' 'two') except ValueError: raise ValueError('Oversampling factor must be a scalar') if np.any(value <= 0): raise ValueError('Oversampling factor must be greater than 0') self._oversampling = value def normalized_data(self): """ Overloaded dummy function that also returns self._data, as the normalization occurs within _compute_normalization in EPSFModel, and as such self._data will sum, accounting for under/oversampled pixels, to 1/self._normalization_correction. """ return self._data @FittableImageModel.origin.setter def origin(self, origin): if origin is None: self._x_origin = (self._nx - 1) / 2.0 / self.oversampling[0] self._y_origin = (self._ny - 1) / 2.0 / self.oversampling[1] elif (hasattr(origin, '__iter__') and len(origin) == 2): self._x_origin, self._y_origin = origin else: raise TypeError("Parameter 'origin' must be either None or an " "iterable with two elements.") def compute_interpolator(self, **kwargs): """ Compute/define the interpolating spline. This function can be overriden in a subclass to define custom interpolators. Parameters ---------- kwargs : dict, optional Additional optional keyword arguments: - **degree** : int, tuple, optional Degree of the interpolating spline. A tuple can be used to provide different degrees for the X- and Y-axes. Default value is degree=3. - **s** : float, optional Non-negative smoothing factor. Default value s=0 corresponds to interpolation. See :py:class:`~scipy.interpolate.RectBivariateSpline` for more details. Notes ----- * When subclassing :py:class:`FittableImageModel` for the purpose of overriding :py:func:`compute_interpolator`, the :py:func:`evaluate` may need to overriden as well depending on the behavior of the new interpolator. In addition, for improved future compatibility, make sure that the overriding method stores keyword arguments ``kwargs`` by calling ``_store_interpolator_kwargs`` method. * Use caution when modifying interpolator's degree or smoothness in a computationally intensive part of the code as it may decrease code performance due to the need to recompute interpolator. """ from scipy.interpolate import RectBivariateSpline if 'degree' in kwargs: degree = kwargs['degree'] if hasattr(degree, '__iter__') and len(degree) == 2: degx = int(degree[0]) degy = int(degree[1]) else: degx = int(degree) degy = int(degree) if degx < 0 or degy < 0: raise ValueError("Interpolator degree must be a non-negative " "integer") else: degx = 3 degy = 3 if 's' in kwargs: smoothness = kwargs['s'] else: smoothness = 0 # Interpolator must be set to interpolate on the undersampled # pixel grid, going from 0 to len(undersampled_grid) x = np.arange(self._nx, dtype=np.float) / self.oversampling[0] y = np.arange(self._ny, dtype=np.float) / self.oversampling[1] self.interpolator = RectBivariateSpline( x, y, self._data.T, kx=degx, ky=degy, s=smoothness) self._store_interpolator_kwargs(**kwargs) def evaluate(self, x, y, flux, x_0, y_0): """ Evaluate the model on some input variables and provided model parameters. """ xi = np.asarray(x) - x_0 + self._x_origin yi = np.asarray(y) - y_0 + self._y_origin evaluated_model = flux * self.interpolator.ev(xi, yi) if self._fill_value is not None: # find indices of pixels that are outside the input pixel # grid and set these pixels to the 'fill_value': invalid = (((xi < 0) | (xi > (self._nx - 1) / self.oversampling[0])) | ((yi < 0) | (yi > (self._ny - 1) / self.oversampling[1]))) evaluated_model[invalid] = self._fill_value return evaluated_model class GriddedPSFModel(Fittable2DModel): """ A fittable 2D model containing a grid PSF models defined at specific locations that are interpolated to evaluate a PSF at an arbitrary (x, y) position. Parameters ---------- data : `~astropy.nddata.NDData` An `~astropy.nddata.NDData` object containing the grid of reference PSF arrays. The data attribute must contain a 3D `~numpy.ndarray` containing a stack of the 2D PSFs (the data shape should be (N_psf, PSF_ny, PSF_nx)). The meta attribute must be `dict` containing the following: * ``'grid_xypos'``: A list of the (x, y) grid positions of each reference PSF. The order of positions should match the first axis of the 3D `~numpy.ndarray` of PSFs. In other words, ``grid_xypos[i]`` should be the (x, y) position of the reference PSF defined in ``data[i]``. * ``'oversampling'``: The integer oversampling factor of the PSF. The meta attribute may contain other properties such as the telescope, instrument, detector, and filter of the PSF. """ flux = Parameter(description='Intensity scaling factor for the PSF ' 'model.', default=1.0) x_0 = Parameter(description='x position in the output coordinate grid ' 'where the model is evaluated.', default=0.0) y_0 = Parameter(description='y position in the output coordinate grid ' 'where the model is evaluated.', default=0.0) def __init__(self, data, flux=flux.default, x_0=x_0.default, y_0=y_0.default, fill_value=0.0): if not isinstance(data, NDData): raise TypeError('data must be an NDData instance.') if data.data.ndim != 3: raise ValueError('The NDData data attribute must be a 3D numpy ' 'ndarray') if 'grid_xypos' not in data.meta: raise ValueError('"grid_xypos" must be in the nddata meta ' 'dictionary.') if len(data.meta['grid_xypos']) != data.data.shape[0]: raise ValueError('The length of grid_xypos must match the number ' 'of input PSFs.') if 'oversampling' not in data.meta: raise ValueError('"oversampling" must be in the nddata meta ' 'dictionary.') if not np.isscalar(data.meta['oversampling']): raise ValueError('oversampling must be a scalar value') self.data = np.array(data.data, copy=True, dtype=np.float) self.meta = data.meta self.grid_xypos = data.meta['grid_xypos'] self.oversampling = data.meta['oversampling'] self._grid_xpos, self._grid_ypos = np.transpose(self.grid_xypos) self._xgrid = np.unique(self._grid_xpos) # also sorts values self._ygrid = np.unique(self._grid_ypos) # also sorts values if (len(list(itertools.product(self._xgrid, self._ygrid))) != len(self.grid_xypos)): raise ValueError('"grid_xypos" must form a regular grid.') self._xgrid_min = self._xgrid[0] self._xgrid_max = self._xgrid[-1] self._ygrid_min = self._ygrid[0] self._ygrid_max = self._ygrid[-1] super().__init__(flux, x_0, y_0) @staticmethod def _find_bounds_1d(data, x): """ Find the index of the lower bound where ``x`` should be inserted into ``a`` to maintain order. The index of the upper bound is the index of the lower bound plus 2. Both bound indices must be within the array. Parameters ---------- data : 1D `~numpy.ndarray` The 1D array to search. x : float The value to insert. Returns ------- index : int The index of the lower bound. """ idx = np.searchsorted(data, x) if idx == 0: idx0 = 0 elif idx == len(data): # pragma: no cover idx0 = idx - 2 else: idx0 = idx - 1 return idx0 def _find_bounding_points(self, x, y): """ Find the indices of the grid points that bound the input ``(x, y)`` position. Parameters ---------- x, y : float The ``(x, y)`` position where the PSF is to be evaluated. Returns ------- indices : list of int A list of indices of the bounding grid points. """ if not np.isscalar(x) or not np.isscalar(y): # pragma: no cover raise TypeError('x and y must be scalars') if (x < self._xgrid_min or x > self._xgrid_max or y < self._ygrid_min or y > self._ygrid_max): # pragma: no cover raise ValueError('(x, y) position is outside of the region ' 'defined by grid of PSF positions') x0 = self._find_bounds_1d(self._xgrid, x) y0 = self._find_bounds_1d(self._ygrid, y) points = list(itertools.product(self._xgrid[x0:x0 + 2], self._ygrid[y0:y0 + 2])) indices = [] for xx, yy in points: indices.append(np.argsort(np.hypot(self._grid_xpos - xx, self._grid_ypos - yy))[0]) return indices @staticmethod def _bilinear_interp(xyref, zref, xi, yi): """ Perform bilinear interpolation of four 2D arrays located at points on a regular grid. Parameters ---------- xyref : list of 4 (x, y) pairs A list of 4 ``(x, y)`` pairs that form a rectangle. refdata : 3D `~numpy.ndarray` A 3D `~numpy.ndarray` of shape ``(4, nx, ny)``. The first axis corresponds to ``xyref``, i.e. ``refdata[0, :, :]`` is the 2D array located at ``xyref[0]``. xi, yi : float The ``(xi, yi)`` point at which to perform the interpolation. The ``(xi, yi)`` point must lie within the rectangle defined by ``xyref``. Returns ------- result : 2D `~numpy.ndarray` The 2D interpolated array. """ if len(xyref) != 4: raise ValueError('xyref must contain only 4 (x, y) pairs') if zref.shape[0] != 4: raise ValueError('zref must have a length of 4 on the first ' 'axis.') xyref = [tuple(i) for i in xyref] idx = sorted(range(len(xyref)), key=xyref.__getitem__) xyref = sorted(xyref) # sort by x, then y (x0, y0), (_x0, y1), (x1, _y0), (_x1, _y1) = xyref if x0 != _x0 or x1 != _x1 or y0 != _y0 or y1 != _y1: raise ValueError('The refxy points do not form a rectangle.') if not np.isscalar(xi): xi = xi[0] if not np.isscalar(yi): yi = yi[0] if not x0 <= xi <= x1 or not y0 <= yi <= y1: raise ValueError('The (x, y) input is not within the rectangle ' 'defined by xyref.') data = np.asarray(zref)[idx] weights = np.array([(x1 - xi) * (y1 - yi), (x1 - xi) * (yi - y0), (xi - x0) * (y1 - yi), (xi - x0) * (yi - y0)]) norm = (x1 - x0) * (y1 - y0) return np.sum(data * weights[:, None, None], axis=0) / norm def evaluate(self, x, y, flux, x_0, y_0): """ Evaluate the `GriddedPSFModel` for the input parameters. """ # NOTE: this is needed because the PSF photometry routines input # length-1 values instead of scalars. TODO: fix the photometry # routines. if not np.isscalar(x_0): x_0 = x_0[0] if not np.isscalar(y_0): y_0 = y_0[0] if (x_0 < self._xgrid_min or x_0 > self._xgrid_max or y_0 < self._ygrid_min or y_0 > self._ygrid_max): # position is outside of the grid, so simply use the # closest reference PSF self._ref_indices = np.argsort(np.hypot(self._grid_xpos - x_0, self._grid_ypos - y_0))[0] self._psf_interp = self.data[self._ref_indices, :, :] else: # find the four bounding reference PSFs and interpolate self._ref_indices = self._find_bounding_points(x_0, y_0) xyref = np.array(self.grid_xypos)[self._ref_indices] psfs = self.data[self._ref_indices, :, :] self._psf_interp = self._bilinear_interp(xyref, psfs, x_0, y_0) # now evaluate the PSF at the (x_0, y_0) subpixel position on # the input (x, y) values psfmodel = FittableImageModel(self._psf_interp, oversampling=self.oversampling) return psfmodel.evaluate(x, y, flux, x_0, y_0) class IntegratedGaussianPRF(Fittable2DModel): r""" Circular Gaussian model integrated over pixels. Because it is integrated, this model is considered a PRF, *not* a PSF (see :ref:`psf-terminology` for more about the terminology used here.) This model is a Gaussian *integrated* over an area of ``1`` (in units of the model input coordinates, e.g. 1 pixel). This is in contrast to the apparently similar `astropy.modeling.functional_models.Gaussian2D`, which is the value of a 2D Gaussian *at* the input coordinates, with no integration. So this model is equivalent to assuming the PSF is Gaussian at a *sub-pixel* level. Parameters ---------- sigma : float Width of the Gaussian PSF. flux : float, optional Total integrated flux over the entire PSF x_0 : float, optional Position of the peak in x direction. y_0 : float, optional Position of the peak in y direction. Notes ----- This model is evaluated according to the following formula: .. math:: f(x, y) = \frac{F}{4} \left[ {\rm erf} \left(\frac{x - x_0 + 0.5} {\sqrt{2} \sigma} \right) - {\rm erf} \left(\frac{x - x_0 - 0.5} {\sqrt{2} \sigma} \right) \right] \left[ {\rm erf} \left(\frac{y - y_0 + 0.5} {\sqrt{2} \sigma} \right) - {\rm erf} \left(\frac{y - y_0 - 0.5} {\sqrt{2} \sigma} \right) \right] where ``erf`` denotes the error function and ``F`` the total integrated flux. """ flux = Parameter(default=1) x_0 = Parameter(default=0) y_0 = Parameter(default=0) sigma = Parameter(default=1, fixed=True) _erf = None fit_deriv = None @property def bounding_box(self): halfwidth = 4 * self.sigma return ((int(self.y_0 - halfwidth), int(self.y_0 + halfwidth)), (int(self.x_0 - halfwidth), int(self.x_0 + halfwidth))) def __init__(self, sigma=sigma.default, x_0=x_0.default, y_0=y_0.default, flux=flux.default, **kwargs): if self._erf is None: from scipy.special import erf self.__class__._erf = erf super().__init__(n_models=1, sigma=sigma, x_0=x_0, y_0=y_0, flux=flux, **kwargs) def evaluate(self, x, y, flux, x_0, y_0, sigma): """Model function Gaussian PSF model.""" return (flux / 4 * ((self._erf((x - x_0 + 0.5) / (np.sqrt(2) * sigma)) - self._erf((x - x_0 - 0.5) / (np.sqrt(2) * sigma))) * (self._erf((y - y_0 + 0.5) / (np.sqrt(2) * sigma)) - self._erf((y - y_0 - 0.5) / (np.sqrt(2) * sigma))))) class PRFAdapter(Fittable2DModel): """ A model that adapts a supplied PSF model to act as a PRF. It integrates the PSF model over pixel "boxes". A critical built-in assumption is that the PSF model scale and location parameters are in *pixel* units. Parameters ---------- psfmodel : a 2D model The model to assume as representative of the PSF renormalize_psf : bool If True, the model will be integrated from -inf to inf and re-scaled so that the total integrates to 1. Note that this renormalization only occurs *once*, so if the total flux of ``psfmodel`` depends on position, this will *not* be correct. xname : str or None The name of the ``psfmodel`` parameter that corresponds to the x-axis center of the PSF. If None, the model will be assumed to be centered at x=0. yname : str or None The name of the ``psfmodel`` parameter that corresponds to the y-axis center of the PSF. If None, the model will be assumed to be centered at y=0. fluxname : str or None The name of the ``psfmodel`` parameter that corresponds to the total flux of the star. If None, a scaling factor will be applied by the ``PRFAdapter`` instead of modifying the ``psfmodel``. Notes ----- This current implementation of this class (using numerical integration for each pixel) is extremely slow, and only suited for experimentation over relatively few small regions. """ flux = Parameter(default=1) x_0 = Parameter(default=0) y_0 = Parameter(default=0) def __init__(self, psfmodel, renormalize_psf=True, flux=flux.default, x_0=x_0.default, y_0=y_0.default, xname=None, yname=None, fluxname=None, **kwargs): self.psfmodel = psfmodel.copy() if renormalize_psf: from scipy.integrate import dblquad self._psf_scale_factor = 1. / dblquad(self.psfmodel, -np.inf, np.inf, lambda x: -np.inf, lambda x: np.inf)[0] else: self._psf_scale_factor = 1 self.xname = xname self.yname = yname self.fluxname = fluxname # these can be used to adjust the integration behavior. Might be # used in the future to expose how the integration happens self._dblquadkwargs = {} super().__init__(n_models=1, x_0=x_0, y_0=y_0, flux=flux, **kwargs) def evaluate(self, x, y, flux, x_0, y_0): """The evaluation function for PRFAdapter.""" if self.xname is None: dx = x - x_0 else: dx = x setattr(self.psfmodel, self.xname, x_0) if self.xname is None: dy = y - y_0 else: dy = y setattr(self.psfmodel, self.yname, y_0) if self.fluxname is None: return (flux * self._psf_scale_factor * self._integrated_psfmodel(dx, dy)) else: setattr(self.psfmodel, self.yname, flux * self._psf_scale_factor) return self._integrated_psfmodel(dx, dy) def _integrated_psfmodel(self, dx, dy): from scipy.integrate import dblquad # infer type/shape from the PSF model. Seems wasteful, but the # integration step is a *lot* more expensive so its just peanuts out = np.empty_like(self.psfmodel(dx, dy)) outravel = out.ravel() for i, (xi, yi) in enumerate(zip(dx.ravel(), dy.ravel())): outravel[i] = dblquad(self.psfmodel, xi-0.5, xi+0.5, lambda x: yi-0.5, lambda x: yi+0.5, **self._dblquadkwargs)[0] return out photutils-0.7.2/photutils/psf/photometry.py0000644000214200020070000012154313572576136023372 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides classes to perform PSF-fitting photometry. """ import warnings from astropy.modeling.fitting import LevMarLSQFitter from astropy.nddata.utils import overlap_slices from astropy.stats import SigmaClip, gaussian_sigma_to_fwhm from astropy.table import Column, Table, hstack, vstack from astropy.utils.exceptions import AstropyUserWarning import numpy as np from .groupstars import DAOGroup from .utils import (_extract_psf_fitting_names, get_grouped_psf_model, subtract_psf) from ..aperture import CircularAperture, aperture_photometry from ..background import MMMBackground from ..detection import DAOStarFinder from ..utils.exceptions import NoDetectionsWarning __all__ = ['BasicPSFPhotometry', 'IterativelySubtractedPSFPhotometry', 'DAOPhotPSFPhotometry'] class BasicPSFPhotometry: """ This class implements a PSF photometry algorithm that can find sources in an image, group overlapping sources into a single model, fit the model to the sources, and subtracting the models from the image. This is roughly equivalent to the DAOPHOT routines FIND, GROUP, NSTAR, and SUBTRACT. This implementation allows a flexible and customizable interface to perform photometry. For instance, one is able to use different implementations for grouping and finding sources by using ``group_maker`` and ``finder`` respectivelly. In addition, sky background estimation is performed by ``bkg_estimator``. Parameters ---------- group_maker : callable or `~photutils.psf.GroupStarsBase` ``group_maker`` should be able to decide whether a given star overlaps with any other and label them as beloging to the same group. ``group_maker`` receives as input an `~astropy.table.Table` object with columns named as ``id``, ``x_0``, ``y_0``, in which ``x_0`` and ``y_0`` have the same meaning of ``xcentroid`` and ``ycentroid``. This callable must return an `~astropy.table.Table` with columns ``id``, ``x_0``, ``y_0``, and ``group_id``. The column ``group_id`` should cotain integers starting from ``1`` that indicate which group a given source belongs to. See, e.g., `~photutils.psf.DAOGroup`. bkg_estimator : callable, instance of any `~photutils.background.BackgroundBase` subclass, or None ``bkg_estimator`` should be able to compute either a scalar background or a 2D background of a given 2D image. See, e.g., `~photutils.background.MedianBackground`. If None, no background subtraction is performed. psf_model : `astropy.modeling.Fittable2DModel` instance PSF or PRF model to fit the data. Could be one of the models in this package like `~photutils.psf.sandbox.DiscretePRF`, `~photutils.psf.IntegratedGaussianPRF`, or any other suitable 2D model. This object needs to identify three parameters (position of center in x and y coordinates and the flux) in order to set them to suitable starting values for each fit. The names of these parameters should be given as ``x_0``, ``y_0`` and ``flux``. `~photutils.psf.prepare_psf_model` can be used to prepare any 2D model to match this assumption. fitshape : int or length-2 array-like Rectangular shape around the center of a star which will be used to collect the data to do the fitting. Can be an integer to be the same along both axes. E.g., 5 is the same as (5, 5), which means to fit only at the following relative pixel positions: [-2, -1, 0, 1, 2]. Each element of ``fitshape`` must be an odd number. finder : callable or instance of any `~photutils.detection.StarFinderBase` subclasses or None ``finder`` should be able to identify stars, i.e. compute a rough estimate of the centroids, in a given 2D image. ``finder`` receives as input a 2D image and returns an `~astropy.table.Table` object which contains columns with names: ``id``, ``xcentroid``, ``ycentroid``, and ``flux``. In which ``id`` is an integer-valued column starting from ``1``, ``xcentroid`` and ``ycentroid`` are center position estimates of the sources and ``flux`` contains flux estimates of the sources. See, e.g., `~photutils.detection.DAOStarFinder`. If ``finder`` is ``None``, initial guesses for positions of objects must be provided. fitter : `~astropy.modeling.fitting.Fitter` instance Fitter object used to compute the optimized centroid positions and/or flux of the identified sources. See `~astropy.modeling.fitting` for more details on fitters. aperture_radius : `None` or float The radius (in units of pixels) used to compute initial estimates for the fluxes of sources. ``aperture_radius`` must be set if initial flux guesses are not input to the photometry class via the ``init_guesses`` keyword. For tabular PSF models (e.g. an `EPSFModel`), you must input the ``aperture_radius`` keyword. For analytical PSF models, alternatively you may define a FWHM attribute on your input psf_model. Notes ----- Note that an ambiguity arises whenever ``finder`` and ``init_guesses`` (keyword argument for ``do_photometry``) are both not ``None``. In this case, ``finder`` is ignored and initial guesses are taken from ``init_guesses``. In addition, an warning is raised to remaind the user about this behavior. If there are problems with fitting large groups, change the parameters of the grouping algorithm to reduce the number of sources in each group or input a ``star_groups`` table that only includes the groups that are relevant (e.g. manually remove all entries that coincide with artifacts). References ---------- [1] Stetson, Astronomical Society of the Pacific, Publications, (ISSN 0004-6280), vol. 99, March 1987, p. 191-222. Available at: http://adsabs.harvard.edu/abs/1987PASP...99..191S """ def __init__(self, group_maker, bkg_estimator, psf_model, fitshape, finder=None, fitter=LevMarLSQFitter(), aperture_radius=None): self.group_maker = group_maker self.bkg_estimator = bkg_estimator self.psf_model = psf_model self.fitter = fitter self.fitshape = fitshape self.finder = finder self.aperture_radius = aperture_radius self._pars_to_set = None self._pars_to_output = None self._residual_image = None @property def fitshape(self): return self._fitshape @fitshape.setter def fitshape(self, value): value = np.asarray(value) # assume a lone value should mean both axes if value.shape == (): value = np.array((value, value)) if value.size == 2: if np.all(value) > 0: if np.all(value % 2) == 1: self._fitshape = tuple(value) else: raise ValueError('fitshape must be odd integer-valued, ' 'received fitshape = {}'.format(value)) else: raise ValueError('fitshape must have positive elements, ' 'received fitshape = {}'.format(value)) else: raise ValueError('fitshape must have two dimensions, ' 'received fitshape = {}'.format(value)) @property def aperture_radius(self): return self._aperture_radius @aperture_radius.setter def aperture_radius(self, value): if isinstance(value, (int, float)) and value > 0: self._aperture_radius = value elif value is None: self._aperture_radius = value else: raise ValueError('aperture_radius must be a positive number') def get_residual_image(self): """ Returns an image that is the result of the subtraction between the original image and the fitted sources. Returns ------- residual_image : 2D array-like, `~astropy.io.fits.ImageHDU`, `~astropy.io.fits.HDUList` """ return self._residual_image def __call__(self, image, init_guesses=None): """ Performs PSF photometry. See `do_photometry` for more details including the `__call__` signature. """ return self.do_photometry(image, init_guesses) def do_photometry(self, image, init_guesses=None): """ Perform PSF photometry in ``image``. This method assumes that ``psf_model`` has centroids and flux parameters which will be fitted to the data provided in ``image``. A compound model, in fact a sum of ``psf_model``, will be fitted to groups of stars automatically identified by ``group_maker``. Also, ``image`` is not assumed to be background subtracted. If ``init_guesses`` are not ``None`` then this method uses ``init_guesses`` as initial guesses for the centroids. If the centroid positions are set as ``fixed`` in the PSF model ``psf_model``, then the optimizer will only consider the flux as a variable. Parameters ---------- image : 2D array-like, `~astropy.io.fits.ImageHDU`, `~astropy.io.fits.HDUList` Image to perform photometry. init_guesses: `~astropy.table.Table` Table which contains the initial guesses (estimates) for the set of parameters. Columns 'x_0' and 'y_0' which represent the positions (in pixel coordinates) for each object must be present. 'flux_0' can also be provided to set initial fluxes. If 'flux_0' is not provided, aperture photometry is used to estimate initial values for the fluxes. Additional columns of the form '_0' will be used to set the initial guess for any parameters of the ``psf_model`` model that are not fixed. Returns ------- output_tab : `~astropy.table.Table` or None Table with the photometry results, i.e., centroids and fluxes estimations and the initial estimates used to start the fitting process. Uncertainties on the fitted parameters are reported as columns called ``_unc`` provided that the fitter object contains a dictionary called ``fit_info`` with the key ``param_cov``, which contains the covariance matrix. If ``param_cov`` is not present, uncertanties are not reported. """ if self.bkg_estimator is not None: image = image - self.bkg_estimator(image) if self.aperture_radius is None: if hasattr(self.psf_model, 'fwhm'): self.aperture_radius = self.psf_model.fwhm.value elif hasattr(self.psf_model, 'sigma'): self.aperture_radius = (self.psf_model.sigma.value * gaussian_sigma_to_fwhm) if self.aperture_radius is None: if init_guesses is None: raise ValueError('aperture_radius was not input and could ' 'not be determined by the input psf_model ' '(e.g. an EPSFModel). For tabular PSF ' 'models, you must input the aperture_radius ' 'keyword. For analytical PSF models, you ' 'must either input the aperture_radius ' 'keyword or define a fwhm or sigma ' 'attribute on your input psf_model.') if (init_guesses is not None and 'flux_0' not in init_guesses.colnames): raise ValueError('init_guesses were input, but the "flux_0" ' 'column was not present. Initial fluxes ' 'cannot be calculated because ' 'aperture_radius must was not input and ' 'could not be determined by the input ' 'psf_model (e.g. an EPSFModel). For ' 'analytical PSF models, you must either ' 'input the aperture_radius keyword or ' 'define a fwhm or sigma attribute on your ' 'input psf_model.') if init_guesses is not None: # make sure the code does not modify user's input init_guesses = init_guesses.copy() if self.finder is not None: warnings.warn('Both init_guesses and finder are different ' 'than None, which is ambiguous. finder is ' 'going to be ignored.', AstropyUserWarning) if 'flux_0' not in init_guesses.colnames: positions = np.transpose((init_guesses['x_0'], init_guesses['y_0'])) apertures = CircularAperture(positions, r=self.aperture_radius) init_guesses['flux_0'] = aperture_photometry( image, apertures)['aperture_sum'] else: if self.finder is None: raise ValueError('Finder cannot be None if init_guesses are ' 'not given.') sources = self.finder(image) if len(sources) > 0: positions = np.transpose((sources['xcentroid'], sources['ycentroid'])) apertures = CircularAperture(positions, r=self.aperture_radius) sources['aperture_flux'] = aperture_photometry( image, apertures)['aperture_sum'] init_guesses = Table(names=['x_0', 'y_0', 'flux_0'], data=[sources['xcentroid'], sources['ycentroid'], sources['aperture_flux']]) self._define_fit_param_names() for p0, param in self._pars_to_set.items(): if p0 not in init_guesses.colnames: init_guesses[p0] = (len(init_guesses) * [getattr(self.psf_model, param).value]) star_groups = self.group_maker(init_guesses) output_tab, self._residual_image = self.nstar(image, star_groups) star_groups = star_groups.group_by('group_id') output_tab = hstack([star_groups, output_tab]) return output_tab def nstar(self, image, star_groups): """ Fit, as appropriate, a compound or single model to the given ``star_groups``. Groups are fitted sequentially from the smallest to the biggest. In each iteration, ``image`` is subtracted by the previous fitted group. Parameters ---------- image : numpy.ndarray Background-subtracted image. star_groups : `~astropy.table.Table` This table must contain the following columns: ``id``, ``group_id``, ``x_0``, ``y_0``, ``flux_0``. ``x_0`` and ``y_0`` are initial estimates of the centroids and ``flux_0`` is an initial estimate of the flux. Additionally, columns named as ``_0`` are required if any other parameter in the psf model is free (i.e., the ``fixed`` attribute of that parameter is ``False``). Returns ------- result_tab : `~astropy.table.Table` Astropy table that contains photometry results. image : numpy.ndarray Residual image. """ result_tab = Table() for param_tab_name in self._pars_to_output.keys(): result_tab.add_column(Column(name=param_tab_name)) unc_tab = Table() for param, isfixed in self.psf_model.fixed.items(): if not isfixed: unc_tab.add_column(Column(name=param + "_unc")) y, x = np.indices(image.shape) star_groups = star_groups.group_by('group_id') for n in range(len(star_groups.groups)): group_psf = get_grouped_psf_model(self.psf_model, star_groups.groups[n], self._pars_to_set) usepixel = np.zeros_like(image, dtype=bool) for row in star_groups.groups[n]: usepixel[overlap_slices(large_array_shape=image.shape, small_array_shape=self.fitshape, position=(row['y_0'], row['x_0']), mode='trim')[0]] = True fit_model = self.fitter(group_psf, x[usepixel], y[usepixel], image[usepixel]) param_table = self._model_params2table(fit_model, len(star_groups.groups[n])) result_tab = vstack([result_tab, param_table]) if 'param_cov' in self.fitter.fit_info.keys(): unc_tab = vstack([unc_tab, self._get_uncertainties( len(star_groups.groups[n]))]) try: from astropy.nddata.utils import NoOverlapError except ImportError: raise ImportError("astropy 1.1 or greater is required in " "order to use this class.") # do not subtract if the fitting did not go well try: image = subtract_psf(image, self.psf_model, param_table, subshape=self.fitshape) except NoOverlapError: pass if 'param_cov' in self.fitter.fit_info.keys(): result_tab = hstack([result_tab, unc_tab]) return result_tab, image def _define_fit_param_names(self): """ Convenience function to define mappings between the names of the columns in the initial guess table (and the name of the fitted parameters) and the actual name of the parameters in the model. This method sets the following parameters on the ``self`` object: * ``pars_to_set`` : Dict which maps the names of the parameters initial guesses to the actual name of the parameter in the model. * ``pars_to_output`` : Dict which maps the names of the fitted parameters to the actual name of the parameter in the model. """ xname, yname, fluxname = _extract_psf_fitting_names(self.psf_model) self._pars_to_set = {'x_0': xname, 'y_0': yname, 'flux_0': fluxname} self._pars_to_output = {'x_fit': xname, 'y_fit': yname, 'flux_fit': fluxname} for p, isfixed in self.psf_model.fixed.items(): p0 = p + '_0' pfit = p + '_fit' if p not in (xname, yname, fluxname) and not isfixed: self._pars_to_set[p0] = p self._pars_to_output[pfit] = p def _get_uncertainties(self, star_group_size): """ Retrieve uncertainties on fitted parameters from the fitter object. Parameters ---------- star_group_size : int Number of stars in the given group. Returns ------- unc_tab : `~astropy.table.Table` Table which contains uncertainties on the fitted parameters. The uncertainties are reported as one standard deviation. """ unc_tab = Table() for param_name in self.psf_model.param_names: if not self.psf_model.fixed[param_name]: unc_tab.add_column(Column(name=param_name + "_unc", data=np.empty(star_group_size))) if 'param_cov' in self.fitter.fit_info.keys(): if self.fitter.fit_info['param_cov'] is not None: k = 0 n_fit_params = len(unc_tab.colnames) for i in range(star_group_size): unc_tab[i] = np.sqrt(np.diag( self.fitter.fit_info['param_cov']) )[k: k + n_fit_params] k = k + n_fit_params return unc_tab def _model_params2table(self, fit_model, star_group_size): """ Place fitted parameters into an astropy table. Parameters ---------- fit_model : `astropy.modeling.Fittable2DModel` instance PSF or PRF model to fit the data. Could be one of the models in this package like `~photutils.psf.sandbox.DiscretePRF`, `~photutils.psf.IntegratedGaussianPRF`, or any other suitable 2D model. star_group_size : int Number of stars in the given group. Returns ------- param_tab : `~astropy.table.Table` Table that contains the fitted parameters. """ param_tab = Table() for param_tab_name in self._pars_to_output.keys(): param_tab.add_column(Column(name=param_tab_name, data=np.empty(star_group_size))) if star_group_size > 1: for i in range(star_group_size): for param_tab_name, param_name in self._pars_to_output.items(): param_tab[param_tab_name][i] = getattr(fit_model, param_name + '_' + str(i)).value else: for param_tab_name, param_name in self._pars_to_output.items(): param_tab[param_tab_name] = getattr(fit_model, param_name).value return param_tab class IterativelySubtractedPSFPhotometry(BasicPSFPhotometry): """ This class implements an iterative algorithm to perform point spread function photometry in crowded fields. This consists of applying a loop of find sources, make groups, fit groups, subtract groups, and then repeat until no more stars are detected or a given number of iterations is reached. Parameters ---------- group_maker : callable or `~photutils.psf.GroupStarsBase` ``group_maker`` should be able to decide whether a given star overlaps with any other and label them as beloging to the same group. ``group_maker`` receives as input an `~astropy.table.Table` object with columns named as ``id``, ``x_0``, ``y_0``, in which ``x_0`` and ``y_0`` have the same meaning of ``xcentroid`` and ``ycentroid``. This callable must return an `~astropy.table.Table` with columns ``id``, ``x_0``, ``y_0``, and ``group_id``. The column ``group_id`` should cotain integers starting from ``1`` that indicate which group a given source belongs to. See, e.g., `~photutils.psf.DAOGroup`. bkg_estimator : callable, instance of any `~photutils.background.BackgroundBase` subclass, or None ``bkg_estimator`` should be able to compute either a scalar background or a 2D background of a given 2D image. See, e.g., `~photutils.background.MedianBackground`. If None, no background subtraction is performed. psf_model : `astropy.modeling.Fittable2DModel` instance PSF or PRF model to fit the data. Could be one of the models in this package like `~photutils.psf.sandbox.DiscretePRF`, `~photutils.psf.IntegratedGaussianPRF`, or any other suitable 2D model. This object needs to identify three parameters (position of center in x and y coordinates and the flux) in order to set them to suitable starting values for each fit. The names of these parameters should be given as ``x_0``, ``y_0`` and ``flux``. `~photutils.psf.prepare_psf_model` can be used to prepare any 2D model to match this assumption. fitshape : int or length-2 array-like Rectangular shape around the center of a star which will be used to collect the data to do the fitting. Can be an integer to be the same along both axes. E.g., 5 is the same as (5, 5), which means to fit only at the following relative pixel positions: [-2, -1, 0, 1, 2]. Each element of ``fitshape`` must be an odd number. finder : callable or instance of any `~photutils.detection.StarFinderBase` subclasses ``finder`` should be able to identify stars, i.e. compute a rough estimate of the centroids, in a given 2D image. ``finder`` receives as input a 2D image and returns an `~astropy.table.Table` object which contains columns with names: ``id``, ``xcentroid``, ``ycentroid``, and ``flux``. In which ``id`` is an integer-valued column starting from ``1``, ``xcentroid`` and ``ycentroid`` are center position estimates of the sources and ``flux`` contains flux estimates of the sources. See, e.g., `~photutils.detection.DAOStarFinder` or `~photutils.detection.IRAFStarFinder`. fitter : `~astropy.modeling.fitting.Fitter` instance Fitter object used to compute the optimized centroid positions and/or flux of the identified sources. See `~astropy.modeling.fitting` for more details on fitters. aperture_radius : float The radius (in units of pixels) used to compute initial estimates for the fluxes of sources. If ``None``, one FWHM will be used if it can be determined from the ```psf_model``. niters : int or None Number of iterations to perform of the loop FIND, GROUP, SUBTRACT, NSTAR. If None, iterations will proceed until no more stars remain. Note that in this case it is *possible* that the loop will never end if the PSF has structure that causes subtraction to create new sources infinitely. Notes ----- If there are problems with fitting large groups, change the parameters of the grouping algorithm to reduce the number of sources in each group or input a ``star_groups`` table that only includes the groups that are relevant (e.g. manually remove all entries that coincide with artifacts). References ---------- [1] Stetson, Astronomical Society of the Pacific, Publications, (ISSN 0004-6280), vol. 99, March 1987, p. 191-222. Available at: http://adsabs.harvard.edu/abs/1987PASP...99..191S """ def __init__(self, group_maker, bkg_estimator, psf_model, fitshape, finder, fitter=LevMarLSQFitter(), niters=3, aperture_radius=None): super().__init__(group_maker, bkg_estimator, psf_model, fitshape, finder, fitter, aperture_radius) self.niters = niters @property def niters(self): return self._niters @niters.setter def niters(self, value): if value is None: self._niters = None else: try: if value <= 0: raise ValueError('niters must be positive.') else: self._niters = int(value) except ValueError: raise ValueError('niters must be None or an integer or ' 'convertable into an integer.') @property def finder(self): return self._finder @finder.setter def finder(self, value): if value is None: raise ValueError("finder cannot be None for " "IterativelySubtractedPSFPhotometry - you may " "want to use BasicPSFPhotometry. Please see the " "Detection section on photutils documentation.") else: self._finder = value def do_photometry(self, image, init_guesses=None): """ Perform PSF photometry in ``image``. This method assumes that ``psf_model`` has centroids and flux parameters which will be fitted to the data provided in ``image``. A compound model, in fact a sum of ``psf_model``, will be fitted to groups of stars automatically identified by ``group_maker``. Also, ``image`` is not assumed to be background subtracted. If ``init_guesses`` are not ``None`` then this method uses ``init_guesses`` as initial guesses for the centroids. If the centroid positions are set as ``fixed`` in the PSF model ``psf_model``, then the optimizer will only consider the flux as a variable. Parameters ---------- image : 2D array-like, `~astropy.io.fits.ImageHDU`, `~astropy.io.fits.HDUList` Image to perform photometry. init_guesses: `~astropy.table.Table` Table which contains the initial guesses (estimates) for the set of parameters. Columns 'x_0' and 'y_0' which represent the positions (in pixel coordinates) for each object must be present. 'flux_0' can also be provided to set initial fluxes. If 'flux_0' is not provided, aperture photometry is used to estimate initial values for the fluxes. Additional columns of the form '_0' will be used to set the initial guess for any parameters of the ``psf_model`` model that are not fixed. Returns ------- output_table : `~astropy.table.Table` or None Table with the photometry results, i.e., centroids and fluxes estimations and the initial estimates used to start the fitting process. Uncertainties on the fitted parameters are reported as columns called ``_unc`` provided that the fitter object contains a dictionary called ``fit_info`` with the key ``param_cov``, which contains the covariance matrix. """ if init_guesses is not None: table = super().do_photometry(image, init_guesses) table['iter_detected'] = np.ones(table['x_fit'].shape, dtype=np.int32) # n_start = 2 because it starts in the second iteration # since the first iteration is above output_table = self._do_photometry(init_guesses.colnames, n_start=2) output_table = vstack([table, output_table]) else: if self.bkg_estimator is not None: self._residual_image = image - self.bkg_estimator(image) else: self._residual_image = image if self.aperture_radius is None: if hasattr(self.psf_model, 'fwhm'): self.aperture_radius = self.psf_model.fwhm.value elif hasattr(self.psf_model, 'sigma'): self.aperture_radius = (self.psf_model.sigma.value * gaussian_sigma_to_fwhm) output_table = self._do_photometry(['x_0', 'y_0', 'flux_0']) return output_table def _do_photometry(self, param_tab, n_start=1): """ Helper function which performs the iterations of the photometry process. Parameters ---------- param_names : list Names of the columns which represent the initial guesses. For example, ['x_0', 'y_0', 'flux_0'], for intial guesses on the center positions and the flux. n_start : int Integer representing the start index of the iteration. It is 1 if init_guesses are None, and 2 otherwise. Returns ------- output_table : `~astropy.table.Table` or None Table with the photometry results, i.e., centroids and fluxes estimations and the initial estimates used to start the fitting process. """ output_table = Table() self._define_fit_param_names() for (init_parname, fit_parname) in zip(self._pars_to_set.keys(), self._pars_to_output.keys()): output_table.add_column(Column(name=init_parname)) output_table.add_column(Column(name=fit_parname)) sources = self.finder(self._residual_image) n = n_start while((sources is not None and len(sources) > 0) and (self.niters is None or n <= self.niters)): positions = np.transpose((sources['xcentroid'], sources['ycentroid'])) apertures = CircularAperture(positions, r=self.aperture_radius) sources['aperture_flux'] = aperture_photometry( self._residual_image, apertures)['aperture_sum'] init_guess_tab = Table(names=['id', 'x_0', 'y_0', 'flux_0'], data=[sources['id'], sources['xcentroid'], sources['ycentroid'], sources['aperture_flux']]) for param_tab_name, param_name in self._pars_to_set.items(): if param_tab_name not in (['x_0', 'y_0', 'flux_0']): init_guess_tab.add_column( Column(name=param_tab_name, data=(getattr(self.psf_model, param_name) * np.ones(len(sources))))) star_groups = self.group_maker(init_guess_tab) table, self._residual_image = super().nstar( self._residual_image, star_groups) star_groups = star_groups.group_by('group_id') table = hstack([star_groups, table]) table['iter_detected'] = n*np.ones(table['x_fit'].shape, dtype=np.int32) output_table = vstack([output_table, table]) # do not warn if no sources are found beyond the first iteration with warnings.catch_warnings(): warnings.simplefilter('ignore', NoDetectionsWarning) sources = self.finder(self._residual_image) n += 1 return output_table class DAOPhotPSFPhotometry(IterativelySubtractedPSFPhotometry): """ This class implements an iterative algorithm based on the DAOPHOT algorithm presented by Stetson (1987) to perform point spread function photometry in crowded fields. This consists of applying a loop of find sources, make groups, fit groups, subtract groups, and then repeat until no more stars are detected or a given number of iterations is reached. Basically, this classes uses `~photutils.psf.IterativelySubtractedPSFPhotometry`, but with grouping, finding, and background estimation routines defined a priori. More precisely, this class uses `~photutils.psf.DAOGroup` for grouping, `~photutils.detection.DAOStarFinder` for finding sources, and `~photutils.background.MMMBackground` for background estimation. Those classes are based on GROUP, FIND, and SKY routines used in DAOPHOT, respectively. The parameter ``crit_separation`` is associated with `~photutils.psf.DAOGroup`. ``sigma_clip`` is associated with `~photutils.background.MMMBackground`. ``threshold`` and ``fwhm`` are associated with `~photutils.detection.DAOStarFinder`. Parameters from ``ratio`` to ``roundhi`` are also associated with `~photutils.detection.DAOStarFinder`. Parameters ---------- crit_separation : float or int Distance, in units of pixels, such that any two stars separated by less than this distance will be placed in the same group. threshold : float The absolute image value above which to select sources. fwhm : float The full-width half-maximum (FWHM) of the major axis of the Gaussian kernel in units of pixels. psf_model : `astropy.modeling.Fittable2DModel` instance PSF or PRF model to fit the data. Could be one of the models in this package like `~photutils.psf.sandbox.DiscretePRF`, `~photutils.psf.IntegratedGaussianPRF`, or any other suitable 2D model. This object needs to identify three parameters (position of center in x and y coordinates and the flux) in order to set them to suitable starting values for each fit. The names of these parameters should be given as ``x_0``, ``y_0`` and ``flux``. `~photutils.psf.prepare_psf_model` can be used to prepare any 2D model to match this assumption. fitshape : int or length-2 array-like Rectangular shape around the center of a star which will be used to collect the data to do the fitting. Can be an integer to be the same along both axes. E.g., 5 is the same as (5, 5), which means to fit only at the following relative pixel positions: [-2, -1, 0, 1, 2]. Each element of ``fitshape`` must be an odd number. sigma : float, optional Number of standard deviations used to perform sigma clip with a `astropy.stats.SigmaClip` object. ratio : float, optional The ratio of the minor to major axis standard deviations of the Gaussian kernel. ``ratio`` must be strictly positive and less than or equal to 1.0. The default is 1.0 (i.e., a circular Gaussian kernel). theta : float, optional The position angle (in degrees) of the major axis of the Gaussian kernel measured counter-clockwise from the positive x axis. sigma_radius : float, optional The truncation radius of the Gaussian kernel in units of sigma (standard deviation) [``1 sigma = FWHM / (2.0*sqrt(2.0*log(2.0)))``]. sharplo : float, optional The lower bound on sharpness for object detection. sharphi : float, optional The upper bound on sharpness for object detection. roundlo : float, optional The lower bound on roundess for object detection. roundhi : float, optional The upper bound on roundess for object detection. fitter : `~astropy.modeling.fitting.Fitter` instance Fitter object used to compute the optimized centroid positions and/or flux of the identified sources. See `~astropy.modeling.fitting` for more details on fitters. niters : int or None Number of iterations to perform of the loop FIND, GROUP, SUBTRACT, NSTAR. If None, iterations will proceed until no more stars remain. Note that in this case it is *possible* that the loop will never end if the PSF has structure that causes subtraction to create new sources infinitely. aperture_radius : float The radius (in units of pixels) used to compute initial estimates for the fluxes of sources. If ``None``, one FWHM will be used if it can be determined from the ```psf_model``. Notes ----- If there are problems with fitting large groups, change the parameters of the grouping algorithm to reduce the number of sources in each group or input a ``star_groups`` table that only includes the groups that are relevant (e.g. manually remove all entries that coincide with artifacts). References ---------- [1] Stetson, Astronomical Society of the Pacific, Publications, (ISSN 0004-6280), vol. 99, March 1987, p. 191-222. Available at: http://adsabs.harvard.edu/abs/1987PASP...99..191S """ def __init__(self, crit_separation, threshold, fwhm, psf_model, fitshape, sigma=3., ratio=1.0, theta=0.0, sigma_radius=1.5, sharplo=0.2, sharphi=1.0, roundlo=-1.0, roundhi=1.0, fitter=LevMarLSQFitter(), niters=3, aperture_radius=None): self.crit_separation = crit_separation self.threshold = threshold self.fwhm = fwhm self.sigma = sigma self.ratio = ratio self.theta = theta self.sigma_radius = sigma_radius self.sharplo = sharplo self.sharphi = sharphi self.roundlo = roundlo self.roundhi = roundhi group_maker = DAOGroup(crit_separation=self.crit_separation) bkg_estimator = MMMBackground(sigma_clip=SigmaClip(sigma=self.sigma)) finder = DAOStarFinder(threshold=self.threshold, fwhm=self.fwhm, ratio=self.ratio, theta=self.theta, sigma_radius=self.sigma_radius, sharplo=self.sharplo, sharphi=self.sharphi, roundlo=self.roundlo, roundhi=self.roundhi) super().__init__(group_maker=group_maker, bkg_estimator=bkg_estimator, psf_model=psf_model, fitshape=fitshape, finder=finder, fitter=fitter, niters=niters, aperture_radius=aperture_radius) photutils-0.7.2/photutils/psf/sandbox.py0000644000214200020070000003361613572576136022621 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module stores work related to photutils.psf that is not quite ready for prime-time (i.e., is not considered a stable public API), but is included either for experimentation or as legacy code. """ from astropy.modeling import Fittable2DModel, Parameter from astropy.modeling.fitting import LevMarLSQFitter from astropy.nddata.utils import extract_array, subpixel_indices from astropy.table import Table import numpy as np from ..utils import mask_to_mirrored_num __all__ = ['DiscretePRF', 'Reproject'] __doctest_requires__ = {('Reproject'): ['gwcs']} class DiscretePRF(Fittable2DModel): """ A discrete Pixel Response Function (PRF) model. The discrete PRF model stores images of the PRF at different subpixel positions or offsets as a lookup table. The resolution is given by the subsampling parameter, which states in how many subpixels a pixel is divided. In the typical case of wanting to create a PRF from an image with many point sources, use the `~DiscretePRF.create_from_image` method, rather than directly initializing this class. The discrete PRF model class in initialized with a 4 dimensional array, that contains the PRF images at different subpixel positions. The definition of the axes is as following: 1. Axis: y subpixel position 2. Axis: x subpixel position 3. Axis: y direction of the PRF image 4. Axis: x direction of the PRF image The total array therefore has the following shape (subsampling, subsampling, prf_size, prf_size) Parameters ---------- prf_array : ndarray Array containing PRF images. normalize : bool Normalize PRF images to unity. Equivalent to saying there is *no* flux outside the bounds of the PRF images. subsampling : int, optional Factor of subsampling. Default = 1. Notes ----- See :ref:`psf-terminology` for more details on the distinction between PSF and PRF as used in this module. """ flux = Parameter('flux') x_0 = Parameter('x_0') y_0 = Parameter('y_0') def __init__(self, prf_array, normalize=True, subsampling=1): # Array shape and dimension check if subsampling == 1: if prf_array.ndim == 2: prf_array = np.array([[prf_array]]) if prf_array.ndim != 4: raise TypeError('Array must have 4 dimensions.') if prf_array.shape[:2] != (subsampling, subsampling): raise TypeError('Incompatible subsampling and array size') if np.isnan(prf_array).any(): raise Exception("Array contains NaN values. Can't create PRF.") # Normalize if requested if normalize: for i in range(prf_array.shape[0]): for j in range(prf_array.shape[1]): prf_array[i, j] /= prf_array[i, j].sum() # Set PRF asttributes self._prf_array = prf_array self.subsampling = subsampling constraints = {'fixed': {'x_0': True, 'y_0': True}} x_0 = 0 y_0 = 0 flux = 1 super().__init__(n_models=1, x_0=x_0, y_0=y_0, flux=flux, **constraints) self.fitter = LevMarLSQFitter() @property def prf_shape(self): """Shape of the PRF image.""" return self._prf_array.shape[-2:] def evaluate(self, x, y, flux, x_0, y_0): """ Discrete PRF model evaluation. Given a certain position and flux the corresponding image of the PSF is chosen and scaled to the flux. If x and y are outside the boundaries of the image, zero will be returned. Parameters ---------- x : float x coordinate array in pixel coordinates. y : float y coordinate array in pixel coordinates. flux : float Model flux. x_0 : float x position of the center of the PRF. y_0 : float y position of the center of the PRF. """ # Convert x and y to index arrays x = (x - x_0 + 0.5 + self.prf_shape[1] // 2).astype('int') y = (y - y_0 + 0.5 + self.prf_shape[0] // 2).astype('int') # Get subpixel indices y_sub, x_sub = subpixel_indices((y_0, x_0), self.subsampling) # Out of boundary masks x_bound = np.logical_or(x < 0, x >= self.prf_shape[1]) y_bound = np.logical_or(y < 0, y >= self.prf_shape[0]) out_of_bounds = np.logical_or(x_bound, y_bound) # Set out of boundary indices to zero x[x_bound] = 0 y[y_bound] = 0 result = flux * self._prf_array[int(y_sub), int(x_sub)][y, x] # Set out of boundary values to zero result[out_of_bounds] = 0 return result @classmethod def create_from_image(cls, imdata, positions, size, fluxes=None, mask=None, mode='mean', subsampling=1, fix_nan=False): """ Create a discrete point response function (PRF) from image data. Given a list of positions and size this function estimates an image of the PRF by extracting and combining the individual PRFs from the given positions. NaN values are either ignored by passing a mask or can be replaced by the mirrored value with respect to the center of the PRF. Note that if fluxes are *not* specified explicitly, it will be flux estimated from an aperture of the same size as the PRF image. This does *not* account for aperture corrections so often will *not* be what you want for anything other than quick-look needs. Parameters ---------- imdata : array Data array with the image to extract the PRF from positions : List or array or `~astropy.table.Table` List of pixel coordinate source positions to use in creating the PRF. If this is a `~astropy.table.Table` it must have columns called ``x_0`` and ``y_0``. size : odd int Size of the quadratic PRF image in pixels. mask : bool array, optional Boolean array to mask out bad values. fluxes : array, optional Object fluxes to normalize extracted PRFs. If not given (or None), the flux is estimated from an aperture of the same size as the PRF image. mode : {'mean', 'median'} One of the following modes to combine the extracted PRFs: * 'mean': Take the pixelwise mean of the extracted PRFs. * 'median': Take the pixelwise median of the extracted PRFs. subsampling : int Factor of subsampling of the PRF (default = 1). fix_nan : bool Fix NaN values in the data by replacing it with the mirrored value. Assuming that the PRF is symmetrical. Returns ------- prf : `photutils.psf.sandbox.DiscretePRF` Discrete PRF model estimated from data. """ # Check input array type and dimension. if np.iscomplexobj(imdata): raise TypeError('Complex type not supported') if imdata.ndim != 2: raise ValueError('{0}-d array not supported. ' 'Only 2-d arrays supported.'.format(imdata.ndim)) if size % 2 == 0: raise TypeError("Size must be odd.") if fluxes is not None and len(fluxes) != len(positions): raise TypeError('Position and flux arrays must be of equal ' 'length.') if mask is None: mask = np.isnan(imdata) if isinstance(positions, (list, tuple)): positions = np.array(positions) if isinstance(positions, Table) or \ (isinstance(positions, np.ndarray) and positions.dtype.names is not None): # One can do clever things like # positions['x_0', 'y_0'].as_array().view((positions['x_0'].dtype, # 2)) # but that requires positions['x_0'].dtype is # positions['y_0'].dtype. # Better do something simple to allow type promotion if required. pos = np.empty((len(positions), 2)) pos[:, 0] = positions['x_0'] pos[:, 1] = positions['y_0'] positions = pos if isinstance(fluxes, (list, tuple)): fluxes = np.array(fluxes) if mode == 'mean': combine = np.ma.mean elif mode == 'median': combine = np.ma.median else: raise Exception('Invalid mode to combine prfs.') data_internal = np.ma.array(data=imdata, mask=mask) prf_model = np.ndarray(shape=(subsampling, subsampling, size, size)) positions_subpixel_indices = \ np.array([subpixel_indices(_, subsampling) for _ in positions], dtype=int) for i in range(subsampling): for j in range(subsampling): extracted_sub_prfs = [] sub_prf_indices = np.all(positions_subpixel_indices == [j, i], axis=1) if not sub_prf_indices.any(): raise ValueError('The source coordinates do not sample ' 'all sub-pixel positions. Reduce the ' 'value of the subsampling parameter.') positions_sub_prfs = positions[sub_prf_indices] for k, position in enumerate(positions_sub_prfs): x, y = position extracted_prf = extract_array(data_internal, (size, size), (y, x)) # Check shape to exclude incomplete PRFs at the boundaries # of the image if (extracted_prf.shape == (size, size) and np.ma.sum(extracted_prf) != 0): # Replace NaN values by mirrored value, with respect # to the prf's center if fix_nan: prf_nan = extracted_prf.mask if prf_nan.any(): if (prf_nan.sum() > 3 or prf_nan[size // 2, size // 2]): continue else: extracted_prf = mask_to_mirrored_num( extracted_prf, prf_nan, (size // 2, size // 2)) # Normalize and add extracted PRF to data cube if fluxes is None: extracted_prf_norm = (np.ma.copy(extracted_prf) / np.ma.sum(extracted_prf)) else: fluxes_sub_prfs = fluxes[sub_prf_indices] extracted_prf_norm = (np.ma.copy(extracted_prf) / fluxes_sub_prfs[k]) extracted_sub_prfs.append(extracted_prf_norm) else: continue prf_model[i, j] = np.ma.getdata( combine(np.ma.dstack(extracted_sub_prfs), axis=2)) return cls(prf_model, subsampling=subsampling) class Reproject: """ Class to reproject pixel coordinates between unrectified and rectified images. Parameters ---------- wcs_original, wcs_rectified : `~astropy.wcs.WCS` or `~gwcs.wcs.WCS` The WCS objects for the original (unrectified) and rectified images. origin : {0, 1} Whether to use 0- or 1-based pixel coordinates. """ def __init__(self, wcs_original, wcs_rectified): self.wcs_original = wcs_original self.wcs_rectified = wcs_rectified @staticmethod def _reproject(wcs1, wcs2, x, y): """ Perform the forward transformation of ``wcs1`` followed by the inverse transformation of ``wcs2``. Parameters ---------- wcs1, wcs2 : WCS objects World coordinate system (WCS) transformations that support the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- x, y: float or array-like of float The pixel coordinates. """ try: skycoord = wcs1.pixel_to_world(x, y) return wcs2.world_to_pixel(skycoord) except AttributeError: raise ValueError('Input wcs objects do not support the shared ' 'WCS interface.') def to_rectified(self, x, y): """ Convert the input (x, y) positions from the original (unrectified) image to the rectified image. Parameters ---------- x, y: float or array-like of float The zero-index pixel coordinates in the original (unrectified) image. Returns ------- x, y: float or array-like The zero-index pixel coordinates in the rectified image. """ return self._reproject(self.wcs_original, self.wcs_rectified, x, y) def to_original(self, x, y): """ Convert the input (x, y) positions from the rectified image to the original (unrectified) image. Parameters ---------- x, y: float or array-like of float The zero-index pixel coordinates in the rectified image. Returns ------- x, y: float or array-like The zero-index pixel coordinates in the original (unrectified) image. """ return self._reproject(self.wcs_rectified, self.wcs_original, x, y) photutils-0.7.2/photutils/psf/tests/0000755000214200020070000000000013573510273021731 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/psf/tests/__init__.py0000644000214200020070000000000013563423715024033 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/psf/tests/test_epsf.py0000644000214200020070000001735613572574524024323 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the epsf module. """ from astropy.modeling.fitting import LevMarLSQFitter from astropy.nddata import NDData from astropy.table import Table import numpy as np from numpy.testing import assert_allclose, assert_almost_equal import pytest from ..epsf import EPSFBuilder, EPSFFitter from ..epsf_stars import extract_stars, EPSFStar, EPSFStars from ..models import IntegratedGaussianPRF, EPSFModel from ...datasets import make_gaussian_prf_sources_image, apply_poisson_noise from ...centroids import centroid_com try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False @pytest.mark.skipif('not HAS_SCIPY') class TestEPSFBuild: def setup_class(self): """ Create a simulated image for testing. """ from scipy.spatial import cKDTree shape = (750, 750) # define random star positions nstars = 100 from astropy.utils.misc import NumpyRNGContext with NumpyRNGContext(12345): # seed for repeatability xx = np.random.uniform(low=0, high=shape[1], size=nstars) yy = np.random.uniform(low=0, high=shape[0], size=nstars) # enforce a minimum separation min_dist = 25 coords = [(yy[0], xx[0])] for xxi, yyi in zip(xx, yy): newcoord = [yyi, xxi] dist, _ = cKDTree([newcoord]).query(coords, 1) if np.min(dist) > min_dist: coords.append(newcoord) yy, xx = np.transpose(coords) with NumpyRNGContext(12345): # seed for repeatability zz = np.random.uniform(low=0, high=200000., size=len(xx)) # define a table of model parameters self.stddev = 2. sources = Table() sources['amplitude'] = zz sources['x_0'] = xx sources['y_0'] = yy sources['sigma'] = np.zeros(len(xx)) + self.stddev sources['theta'] = 0. self.data = make_gaussian_prf_sources_image(shape, sources) self.nddata = NDData(self.data) init_stars = Table() init_stars['x'] = xx.astype(int) init_stars['y'] = yy.astype(int) self.init_stars = init_stars def test_extract_stars(self): size = 25 stars = extract_stars(self.nddata, self.init_stars, size=size) assert len(stars) == 79 assert isinstance(stars, EPSFStars) assert isinstance(stars[0], EPSFStar) assert stars[0].data.shape == (size, size) def test_epsf_build(self): """ This is an end-to-end test of EPSFBuilder on a simulated image. """ size = 25 oversampling = 4. stars = extract_stars(self.nddata, self.init_stars, size=size) epsf_builder = EPSFBuilder(oversampling=oversampling, maxiters=8, progress_bar=False, norm_radius=25, recentering_maxiters=5) epsf, fitted_stars = epsf_builder(stars) ref_size = (size * oversampling) + 1 assert epsf.data.shape == (ref_size, ref_size) y0 = (ref_size - 1) / 2 / oversampling y = np.arange(ref_size, dtype=float) / oversampling psf_model = IntegratedGaussianPRF(sigma=self.stddev) z = epsf.data x = psf_model.evaluate(y.reshape(-1, 1), y.reshape(1, -1), 1, y0, y0, self.stddev) assert_allclose(z, x, rtol=1e-2, atol=1e-5) resid_star = fitted_stars[0].compute_residual_image(epsf) assert_almost_equal(np.sum(resid_star)/fitted_stars[0].flux, 0, decimal=3) def test_epsf_fitting_bounds(self): size = 25 oversampling = 4. stars = extract_stars(self.nddata, self.init_stars, size=size) epsf_builder = EPSFBuilder(oversampling=oversampling, maxiters=8, progress_bar=True, norm_radius=25, recentering_maxiters=5, fitter=EPSFFitter(fit_boxsize=30), smoothing_kernel='quadratic') # With a boxsize larger than the cutout we expect the fitting to # fail for all stars, due to star._fit_error_status with pytest.raises(ValueError): epsf_builder(stars) def test_epsf_build_invalid_fitter(self): """ Test that the input fitter is an EPSFFitter instance. """ with pytest.raises(TypeError): EPSFBuilder(fitter=EPSFFitter, maxiters=3) with pytest.raises(TypeError): EPSFBuilder(fitter=LevMarLSQFitter(), maxiters=3) with pytest.raises(TypeError): EPSFBuilder(fitter=LevMarLSQFitter, maxiters=3) def test_epsfbuilder_inputs(): with pytest.raises(ValueError): EPSFBuilder(oversampling=None) with pytest.raises(ValueError): EPSFBuilder(oversampling=-1) with pytest.raises(ValueError): EPSFBuilder(maxiters=-1) with pytest.raises(ValueError): EPSFBuilder(oversampling=3) with pytest.raises(ValueError): EPSFBuilder(oversampling=[3, 6]) with pytest.raises(ValueError): EPSFBuilder(oversampling=[-1, 4]) def test_epsfmodel_inputs(): data = np.array([[], []]) with pytest.raises(ValueError): EPSFModel(data) data = np.ones((5, 5), dtype=float) data[2, 2] = np.inf with pytest.raises(ValueError): EPSFModel(data) data[2, 2] = np.finfo(np.float64).max * 2 with pytest.raises(ValueError): EPSFModel(data, flux=None) data[2, 2] = 1 for oversampling in [3, np.NaN, 'a', -1, [3, 4], [-2, 4]]: with pytest.raises(ValueError): EPSFModel(data, oversampling=oversampling) for origin in ['a', (1, 2, 3)]: with pytest.raises(TypeError): EPSFModel(data, origin=origin) @pytest.mark.skipif('not HAS_SCIPY') def test_epsf_build_with_noise(): oversampling = 4 size = 25 sigma = 0.5 # should be "truth" ePSF m = IntegratedGaussianPRF(sigma=sigma, x_0=12.5, y_0=12.5, flux=1) yy, xx = np.mgrid[0:size*oversampling+1, 0:size*oversampling+1] xx = xx / oversampling yy = yy / oversampling truth_epsf = m(xx, yy) Nstars = 16 # one star per oversampling=4 point, roughly xdim = np.ceil(np.sqrt(Nstars)).astype(int) ydim = np.ceil(Nstars / xdim).astype(int) xarray = np.arange((size-1)/2+2, (size-1)/2+2 + xdim*size, size) yarray = np.arange((size-1)/2+2, (size-1)/2+2 + ydim*size, size) xarray, yarray = np.meshgrid(xarray, yarray) xarray, yarray = xarray.ravel(), yarray.ravel() np.random.seed(seed=76312) xpos = np.random.uniform(-0.5, 0.5, Nstars) ypos = np.random.uniform(-0.5, 0.5, Nstars) amps = np.random.uniform(50, 1000, Nstars) sources = Table() sources['amplitude'] = amps sources['x_0'] = xarray[:Nstars] + xpos sources['y_0'] = yarray[:Nstars] + ypos sources['sigma'] = [sigma]*Nstars stars_tbl = Table() stars_tbl['x'] = sources['x_0'] stars_tbl['y'] = sources['y_0'] data = make_gaussian_prf_sources_image((size*ydim+4, size*xdim+4), sources) data += 20 # counts/s data *= 100 # seconds data = apply_poisson_noise(data).astype(float) data /= 100 data -= 20 nddata = NDData(data=data) stars = extract_stars(nddata, stars_tbl, size=size) for star in stars: star.cutout_center = centroid_com(star.data) epsf_builder = EPSFBuilder(oversampling=oversampling, maxiters=5, progress_bar=False, norm_radius=7.5, recentering_func=centroid_com, shift_val=0.5) epsf, fitted_stars = epsf_builder(stars) assert_allclose(epsf.data, truth_epsf, rtol=1e-1, atol=5e-2) photutils-0.7.2/photutils/psf/tests/test_epsf_stars.py0000644000214200020070000000557013563423715025525 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the epsf_stars module. """ from astropy.modeling.models import Moffat2D from astropy.nddata import NDData from astropy.table import Table import numpy as np from numpy.testing import assert_allclose import pytest from ..epsf_stars import extract_stars, EPSFStar, EPSFStars from ..models import EPSFModel, IntegratedGaussianPRF try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False @pytest.mark.skipif('not HAS_SCIPY') class TestExtractStars: def setup_class(self): stars_tbl = Table() stars_tbl['x'] = [15, 15, 35, 35] stars_tbl['y'] = [15, 35, 40, 10] self.stars_tbl = stars_tbl yy, xx = np.mgrid[0:51, 0:55] self.data = np.zeros(xx.shape) for (xi, yi) in zip(stars_tbl['x'], stars_tbl['y']): m = Moffat2D(100, xi, yi, 3, 3) self.data += m(xx, yy) self.nddata = NDData(data=self.data) def test_extract_stars(self): size = 11 stars = extract_stars(self.nddata, self.stars_tbl, size=size) assert len(stars) == 4 assert isinstance(stars, EPSFStars) assert isinstance(stars[0], EPSFStar) assert stars[0].data.shape == (size, size) assert stars.n_stars == stars.n_all_stars assert stars.n_stars == stars.n_good_stars assert stars.center.shape == (len(stars), 2) def test_extract_stars_inputs(self): with pytest.raises(ValueError): extract_stars(np.ones(3), self.stars_tbl) with pytest.raises(ValueError): extract_stars(self.nddata, [(1, 1), (2, 2), (3, 3)]) with pytest.raises(ValueError): extract_stars(self.nddata, [self.stars_tbl, self.stars_tbl]) with pytest.raises(ValueError): extract_stars([self.nddata, self.nddata], self.stars_tbl) @pytest.mark.skipif('not HAS_SCIPY') def test_epsf_star_residual_image(): """ Test to ensure ``compute_residual_image`` gives correct residuals. """ size = 100 yy, xx, = np.mgrid[0:size+1, 0:size+1] / 4 gmodel = IntegratedGaussianPRF().evaluate(xx, yy, 1, 12.5, 12.5, 2.5) epsf = EPSFModel(gmodel, oversampling=4, norm_radius=100) _size = 25 data = np.zeros((_size, _size)) _yy, _xx, = np.mgrid[0:_size, 0:_size] data += epsf.evaluate(x=_xx, y=_yy, flux=16, x_0=12, y_0=12) tbl = Table() tbl['x'] = [12] tbl['y'] = [12] stars = extract_stars(NDData(data), tbl, size=23) residual = stars[0].compute_residual_image(epsf) # As current EPSFStar instances cannot accept IntegratedGaussianPRF as input, # we have to accept some loss of precision from the conversion to ePSF, and # spline fitting (twice), so assert_allclose cannot be more more precise than # 0.001 currently. assert_allclose(np.sum(residual), 0., atol=1.e-3, rtol=1e-3) photutils-0.7.2/photutils/psf/tests/test_groupstars.py0000644000214200020070000004432313572573665025576 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the groupstars module. """ from astropy.table import Table, vstack import numpy as np from numpy.testing import assert_almost_equal import pytest from ..groupstars import DAOGroup, DBSCANGroup try: import sklearn.cluster # noqa HAS_SKLEARN = True except ImportError: HAS_SKLEARN = False def assert_table_almost_equal(table1, table2): assert table1.colnames == table2.colnames assert table1.meta == table2.meta for colname in table1.colnames: assert_almost_equal(table1[colname], table2[colname]) class TestDAOGROUP: def test_daogroup_one(self): """ +---------+--------+---------+---------+--------+---------+ | * * * * | | | 0.2 + + | | | | | | 0 + * * + | | | | | | -0.2 + + | | | * * * * | +---------+--------+---------+---------+--------+---------+ 0 0.5 1 1.5 2 x and y axis are in pixel coordinates. Each asterisk represents the centroid of a star. """ x_0 = np.array([0, np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4, -np.sqrt(2)/4]) y_0 = np.array([0, np.sqrt(2)/4, -np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4]) x_1 = x_0 + 2.0 first_group = Table([x_0, y_0, np.arange(len(x_0)) + 1, np.ones(len(x_0), dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) second_group = Table([x_1, y_0, len(x_0) + np.arange(len(x_0)) + 1, 2*np.ones(len(x_0), dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) starlist = vstack([first_group, second_group]) daogroup = DAOGroup(crit_separation=0.6) test_starlist = daogroup(starlist['x_0', 'y_0', 'id']) assert_table_almost_equal(starlist, test_starlist) def test_daogroup_two(self): """ +--------------+--------------+-------------+--------------+ 3 + * + | * | 2.5 + * + | * | 2 + * + | | 1.5 + + | | 1 + * + | * | 0.5 + * + | * | 0 + * + +--------------+--------------+-------------+--------------+ -1 -0.5 0 0.5 1 """ first_group = Table([np.zeros(5), np.linspace(0, 1, 5), np.arange(5) + 1, np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) second_group = Table([np.zeros(5), np.linspace(2, 3, 5), 6 + np.arange(5), 2*np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) starlist = vstack([first_group, second_group]) daogroup = DAOGroup(crit_separation=0.3) test_starlist = daogroup(starlist['x_0', 'y_0', 'id']) assert_table_almost_equal(starlist, test_starlist) def test_daogroup_three(self): """ 1 +--+-------+--------+--------+--------+-------+--------+--+ | | | | | | 0.5 + + | | | | 0 + * * * * * * * * * * + | | | | -0.5 + + | | | | | | -1 +--+-------+--------+--------+--------+-------+--------+--+ 0 0.5 1 1.5 2 2.5 3 """ first_group = Table([np.linspace(0, 1, 5), np.zeros(5), np.arange(5) + 1, np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) second_group = Table([np.linspace(2, 3, 5), np.zeros(5), 6 + np.arange(5), 2*np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) starlist = vstack([first_group, second_group]) daogroup = DAOGroup(crit_separation=0.3) test_starlist = daogroup(starlist['x_0', 'y_0', 'id']) assert_table_almost_equal(starlist, test_starlist) def test_daogroup_four(self): """ +-+---------+---------+---------+---------+-+ 1 + * + | * * | | | | | 0.5 + + | | | | | | 0 + * * + | | | | -0.5 + + | | | | | * * | -1 + * + +-+---------+---------+---------+---------+-+ -1 -0.5 0 0.5 1 """ x = np.linspace(-1., 1., 5) y = np.sqrt(1. - x**2) xx = np.hstack((x, x)) yy = np.hstack((y, -y)) starlist = Table([xx, yy, np.arange(10) + 1, np.ones(10, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) daogroup = DAOGroup(crit_separation=2.5) test_starlist = daogroup(starlist['x_0', 'y_0', 'id']) assert_table_almost_equal(starlist, test_starlist) def test_daogroup_five(self): """ +--+--------+--------+-------+--------+--------+--------+--+ 3 + * + | * | 2.5 + * + | * | 2 + * + | | 1.5 + * * * * * * * * * * + | | 1 + * + | * | 0.5 + * + | * | 0 + * + +--+--------+--------+-------+--------+--------+--------+--+ 0 0.5 1 1.5 2 2.5 3 """ first_group = Table([1.5*np.ones(5), np.linspace(0, 1, 5), np.arange(5) + 1, np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) second_group = Table([1.5*np.ones(5), np.linspace(2, 3, 5), 6 + np.arange(5), 2*np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) third_group = Table([np.linspace(0, 1, 5), 1.5*np.ones(5), 11 + np.arange(5), 3*np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) fourth_group = Table([np.linspace(2, 3, 5), 1.5*np.ones(5), 16 + np.arange(5), 4*np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) starlist = vstack([first_group, second_group, third_group, fourth_group]) daogroup = DAOGroup(crit_separation=0.3) test_starlist = daogroup(starlist['x_0', 'y_0', 'id']) assert_table_almost_equal(starlist, test_starlist) def test_daogroup_six(self): """ +------+----------+----------+----------+----------+------+ | * * * * * * | | | 0.2 + + | | | | | | 0 + * * * + | | | | | | -0.2 + + | | | * * * * * * | +------+----------+----------+----------+----------+------+ 0 1 2 3 4 """ x_0 = np.array([0, np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4, -np.sqrt(2)/4]) y_0 = np.array([0, np.sqrt(2)/4, -np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4]) x_1 = x_0 + 2.0 x_2 = x_0 + 4.0 first_group = Table([x_0, y_0, np.arange(5) + 1, np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) second_group = Table([x_1, y_0, 6 + np.arange(5), 2*np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) third_group = Table([x_2, y_0, 11 + np.arange(5), 3*np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) starlist = vstack([first_group, second_group, third_group]) daogroup = DAOGroup(crit_separation=0.6) test_starlist = daogroup(starlist['x_0', 'y_0', 'id']) assert_table_almost_equal(starlist, test_starlist) def test_isolated_sources(self): """ Test case when all sources are isolated. """ x_0 = np.array([0, np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4, -np.sqrt(2)/4]) y_0 = np.array([0, np.sqrt(2)/4, -np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4]) starlist = Table([x_0, y_0, np.arange(len(x_0)) + 1, np.arange(len(x_0)) + 1], names=('x_0', 'y_0', 'id', 'group_id')) daogroup = DAOGroup(crit_separation=0.01) test_starlist = daogroup(starlist['x_0', 'y_0', 'id']) assert_table_almost_equal(starlist, test_starlist) def test_id_column(self): x_0 = np.array([0, np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4, -np.sqrt(2)/4]) y_0 = np.array([0, np.sqrt(2)/4, -np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4]) starlist = Table([x_0, y_0, np.arange(len(x_0)) + 1, np.arange(len(x_0)) + 1], names=('x_0', 'y_0', 'id', 'group_id')) daogroup = DAOGroup(crit_separation=0.01) test_starlist = daogroup(starlist['x_0', 'y_0']) assert_table_almost_equal(starlist, test_starlist) def test_id_column_raise_error(self): x_0 = np.array([0, np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4, -np.sqrt(2)/4]) y_0 = np.array([0, np.sqrt(2)/4, -np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4]) starlist = Table([x_0, y_0, np.arange(len(x_0)), np.arange(len(x_0)) + 1], names=('x_0', 'y_0', 'id', 'group_id')) daogroup = DAOGroup(crit_separation=0.01) with pytest.raises(ValueError): daogroup(starlist['x_0', 'y_0', 'id']) @pytest.mark.skipif('not HAS_SKLEARN') class TestDBSCANGroup: def test_group_stars_one(object): x_0 = np.array([0, np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4, -np.sqrt(2)/4]) y_0 = np.array([0, np.sqrt(2)/4, -np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4]) x_1 = x_0 + 2.0 first_group = Table([x_0, y_0, np.arange(len(x_0)) + 1, np.ones(len(x_0), dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) second_group = Table([x_1, y_0, len(x_0) + np.arange(len(x_0)) + 1, 2*np.ones(len(x_0), dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) starlist = vstack([first_group, second_group]) dbscan = DBSCANGroup(crit_separation=0.6) test_starlist = dbscan(starlist['x_0', 'y_0', 'id']) assert_table_almost_equal(starlist, test_starlist) def test_group_stars_two(object): first_group = Table([1.5*np.ones(5), np.linspace(0, 1, 5), np.arange(5) + 1, np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) second_group = Table([1.5*np.ones(5), np.linspace(2, 3, 5), 6 + np.arange(5), 2*np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) third_group = Table([np.linspace(0, 1, 5), 1.5*np.ones(5), 11 + np.arange(5), 3*np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) fourth_group = Table([np.linspace(2, 3, 5), 1.5*np.ones(5), 16 + np.arange(5), 4*np.ones(5, dtype=int)], names=('x_0', 'y_0', 'id', 'group_id')) starlist = vstack([first_group, second_group, third_group, fourth_group]) dbscan = DBSCANGroup(crit_separation=0.3) test_starlist = dbscan(starlist['x_0', 'y_0', 'id']) assert_table_almost_equal(starlist, test_starlist) def test_isolated_sources(self): """ Test case when all sources are isolated. """ x_0 = np.array([0, np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4, -np.sqrt(2)/4]) y_0 = np.array([0, np.sqrt(2)/4, -np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4]) starlist = Table([x_0, y_0, np.arange(len(x_0)) + 1, np.arange(len(x_0)) + 1], names=('x_0', 'y_0', 'id', 'group_id')) dbscan = DBSCANGroup(crit_separation=0.01) test_starlist = dbscan(starlist['x_0', 'y_0', 'id']) assert_table_almost_equal(starlist, test_starlist) def test_id_column(self): x_0 = np.array([0, np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4, -np.sqrt(2)/4]) y_0 = np.array([0, np.sqrt(2)/4, -np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4]) starlist = Table([x_0, y_0, np.arange(len(x_0)) + 1, np.arange(len(x_0)) + 1], names=('x_0', 'y_0', 'id', 'group_id')) dbscan = DBSCANGroup(crit_separation=0.01) test_starlist = dbscan(starlist['x_0', 'y_0']) assert_table_almost_equal(starlist, test_starlist) def test_id_column_raise_error(self): x_0 = np.array([0, np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4, -np.sqrt(2)/4]) y_0 = np.array([0, np.sqrt(2)/4, -np.sqrt(2)/4, np.sqrt(2)/4, -np.sqrt(2)/4]) starlist = Table([x_0, y_0, np.arange(len(x_0)), np.arange(len(x_0)) + 1], names=('x_0', 'y_0', 'id', 'group_id')) dbscan = DBSCANGroup(crit_separation=0.01) with pytest.raises(ValueError): dbscan(starlist['x_0', 'y_0', 'id']) photutils-0.7.2/photutils/psf/tests/test_models.py0000644000214200020070000003500413563423715024632 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the models module. """ from itertools import product from astropy.modeling.models import Gaussian2D, Moffat2D from astropy.nddata import NDData import astropy.units as u import numpy as np from numpy.testing import assert_allclose import pytest from ..models import (FittableImageModel, GriddedPSFModel, IntegratedGaussianPRF, PRFAdapter) from ...segmentation import detect_sources, source_properties try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False @pytest.mark.skipif('not HAS_SCIPY') class TestFittableImageModel: def setup_class(self): self.gm = Gaussian2D(x_stddev=3, y_stddev=3) def test_fittable_image_model(self): xx, yy = np.mgrid[-2:3, -2:3] model_nonorm = FittableImageModel(self.gm(xx, yy)) assert_allclose(model_nonorm(0, 0), self.gm(0, 0)) assert_allclose(model_nonorm(1, 1), self.gm(1, 1)) assert_allclose(model_nonorm(-2, 1), self.gm(-2, 1)) # subpixel should *not* match, but be reasonably close # in this case good to ~0.1% seems to be fine assert_allclose(model_nonorm(0.5, 0.5), self.gm(0.5, 0.5), rtol=.001) assert_allclose(model_nonorm(-0.5, 1.75), self.gm(-0.5, 1.75), rtol=.001) model_norm = FittableImageModel(self.gm(xx, yy), normalize=True) assert not np.allclose(model_norm(0, 0), self.gm(0, 0)) assert_allclose(np.sum(model_norm(xx, yy)), 1) model_norm2 = FittableImageModel(self.gm(xx, yy), normalize=True, normalization_correction=2) assert not np.allclose(model_norm2(0, 0), self.gm(0, 0)) assert_allclose(model_norm(0, 0), model_norm2(0, 0)*2) assert_allclose(np.sum(model_norm2(xx, yy)), 0.5) def test_fittable_image_model_oversampling(self): oversamp = 3 # oversampling factor xx, yy = np.mgrid[-3:3.00001:(1/oversamp), -3:3.00001:(1/oversamp)] im = self.gm(xx, yy) assert im.shape[0] > 7 model_oversampled = FittableImageModel(im, oversampling=oversamp) assert_allclose(model_oversampled(0, 0), self.gm(0, 0)) assert_allclose(model_oversampled(1, 1), self.gm(1, 1)) assert_allclose(model_oversampled(-2, 1), self.gm(-2, 1)) assert_allclose(model_oversampled(0.5, 0.5), self.gm(0.5, 0.5), rtol=.001) assert_allclose(model_oversampled(-0.5, 1.75), self.gm(-0.5, 1.75), rtol=.001) # without oversampling the same tests should fail except for at # the origin model_wrongsampled = FittableImageModel(im) assert_allclose(model_wrongsampled(0, 0), self.gm(0, 0)) assert not np.allclose(model_wrongsampled(1, 1), self.gm(1, 1)) assert not np.allclose(model_wrongsampled(-2, 1), self.gm(-2, 1)) assert not np.allclose(model_wrongsampled(0.5, 0.5), self.gm(0.5, 0.5), rtol=.001) assert not np.allclose(model_wrongsampled(-0.5, 1.75), self.gm(-0.5, 1.75), rtol=.001) def test_centering_oversampled(self): gm = Gaussian2D(x_stddev=2, y_stddev=3) oversamp = 3 xx, yy = np.mgrid[-3:3.00001:(1/oversamp), -3:3.00001:(1/oversamp)] model_oversampled = FittableImageModel(gm(xx, yy), oversampling=oversamp) valcen = gm(0, 0) val36 = gm(0.66, 0.66) assert_allclose(valcen, model_oversampled(0, 0)) assert_allclose(val36, model_oversampled(0.66, 0.66), rtol=1.e-6) model_oversampled.x_0 = 2.5 model_oversampled.y_0 = -3.5 assert_allclose(valcen, model_oversampled(2.5, -3.5)) assert_allclose(val36, model_oversampled(2.5 + 0.66, -3.5 + 0.66), rtol=1.e-6) def test_oversampling_inputs(self): data = np.arange(30).reshape(5, 6) for oversampling in [4, (3, 3), (3, 4), '1', ('1', '2')]: fim = FittableImageModel(data, oversampling=oversampling) if not hasattr(oversampling, '__len__'): _oversamp = float(oversampling) else: _oversamp = tuple(float(o) for o in oversampling) assert np.all(fim._oversampling == _oversamp) for oversampling in ['a', ('b', 2), (-1, 3), -1]: with pytest.raises(ValueError): fim = FittableImageModel(data, oversampling=oversampling) class TestGriddedPSFModel: def setup_class(self): psfs = [] y, x = np.mgrid[0:101, 0:101] for i in range(16): theta = i * 10. * np.pi / 180. g = Gaussian2D(1, 50, 50, 10, 5, theta=theta) m = g(x, y) psfs.append(m) xgrid = [0, 40, 160, 200] ygrid = [0, 60, 140, 200] grid_xypos = list(product(xgrid, ygrid)) meta = {} meta['grid_xypos'] = grid_xypos meta['oversampling'] = 4 self.nddata = NDData(psfs, meta=meta) self.psfmodel = GriddedPSFModel(self.nddata) def test_gridded_psf_model(self): keys = ['grid_xypos', 'oversampling'] for key in keys: assert key in self.psfmodel.meta assert len(self.psfmodel.meta) == 2 assert len(self.psfmodel.meta['grid_xypos']) == 16 assert self.psfmodel.oversampling == 4 assert (self.psfmodel.meta['oversampling'] == self.psfmodel.oversampling) assert self.psfmodel.data.shape == (16, 101, 101) @pytest.mark.skipif('not HAS_SCIPY') def test_gridded_psf_model_basic_eval(self): y, x = np.mgrid[0:100, 0:100] psf = self.psfmodel.evaluate(x=x, y=y, flux=100, x_0=40, y_0=60) assert psf.shape == (100, 100) @pytest.mark.skipif('not HAS_SCIPY') def test_gridded_psf_model_eval_outside_grid(self): y, x = np.mgrid[-50:50, -50:50] psf1 = self.psfmodel.evaluate(x=x, y=y, flux=100, x_0=0, y_0=0) y, x = np.mgrid[-60:40, -60:40] psf2 = self.psfmodel.evaluate(x=x, y=y, flux=100, x_0=-10, y_0=-10) assert_allclose(psf1, psf2) y, x = np.mgrid[150:250, 150:250] psf3 = self.psfmodel.evaluate(x=x, y=y, flux=100, x_0=200, y_0=200) y, x = np.mgrid[170:270, 170:270] psf4 = self.psfmodel.evaluate(x=x, y=y, flux=100, x_0=220, y_0=220) assert_allclose(psf3, psf4) @pytest.mark.skipif('not HAS_SCIPY') def test_gridded_psf_model_interp(self): # test xyref length with pytest.raises(ValueError): self.psfmodel._bilinear_interp([1, 1], 1, 1, 1) # test zref shape with pytest.raises(ValueError): xyref = [[0, 0], [0, 1], [1, 0], [1, 1]] zref = np.ones((3, 4, 4)) self.psfmodel._bilinear_interp(xyref, zref, 1, 1) # test if refxy points form a rectangle with pytest.raises(ValueError): xyref = [[0, 0], [0, 1], [1, 0], [2, 2]] zref = np.ones((4, 4, 4)) self.psfmodel._bilinear_interp(xyref, zref, 1, 1) # test if xi and yi are outside of xyref xyref = [[0, 0], [0, 1], [1, 0], [1, 1]] zref = np.ones((4, 4, 4)) with pytest.raises(ValueError): self.psfmodel._bilinear_interp(xyref, zref, 100, 1) with pytest.raises(ValueError): self.psfmodel._bilinear_interp(xyref, zref, 1, 100) # test non-scalar xi and yi idx = [0, 1, 4, 5] xyref = np.array(self.psfmodel.grid_xypos)[idx] psfs = self.psfmodel.data[idx, :, :] val1 = self.psfmodel._bilinear_interp(xyref, psfs, 10, 20) val2 = self.psfmodel._bilinear_interp(xyref, psfs, [10], [20]) assert_allclose(val1, val2) def test_gridded_psf_model_invalid_inputs(self): data = np.ones((4, 3, 3)) # check if NDData with pytest.raises(TypeError): GriddedPSFModel(data) # check PSF data dimension with pytest.raises(ValueError): GriddedPSFModel(NDData(np.ones((3, 3)))) # check that grid_xypos is in meta meta = {'oversampling': 4} nddata = NDData(data, meta=meta) with pytest.raises(ValueError): GriddedPSFModel(nddata) # check grid_xypos length meta = {'grid_xypos': [[0, 0], [1, 0], [1, 0]], 'oversampling': 4} nddata = NDData(data, meta=meta) with pytest.raises(ValueError): GriddedPSFModel(nddata) # check if grid_xypos is a regular grid meta = {'grid_xypos': [[0, 0], [1, 0], [1, 0], [3, 4]], 'oversampling': 4} nddata = NDData(data, meta=meta) with pytest.raises(ValueError): GriddedPSFModel(nddata) # check that oversampling is in meta meta = {'grid_xypos': [[0, 0], [0, 1], [1, 0], [1, 1]]} nddata = NDData(data, meta=meta) with pytest.raises(ValueError): GriddedPSFModel(nddata) # check oversampling is a scalar meta = {'grid_xypos': [[0, 0], [0, 1], [1, 0], [1, 1]], 'oversampling': [4, 4]} nddata = NDData(data, meta=meta) with pytest.raises(ValueError): GriddedPSFModel(nddata) @pytest.mark.skipif('not HAS_SCIPY') def test_gridded_psf_model_eval(self): """ Create a simulated image using GriddedPSFModel and test the properties of the generated sources. """ shape = (200, 200) data = np.zeros(shape) eval_xshape = np.int(np.ceil(self.psfmodel.data.shape[2] / self.psfmodel.oversampling)) eval_yshape = np.int(np.ceil(self.psfmodel.data.shape[1] / self.psfmodel.oversampling)) xx = [40, 50, 160, 160] yy = [60, 150, 50, 140] zz = [100, 100, 100, 100] for xxi, yyi, zzi in zip(xx, yy, zz): x0 = np.int(np.floor(xxi - (eval_xshape - 1) / 2.)) y0 = np.int(np.floor(yyi - (eval_yshape - 1) / 2.)) x1 = x0 + eval_xshape y1 = y0 + eval_yshape if x0 < 0: x0 = 0 if y0 < 0: y0 = 0 if x1 > shape[1]: x1 = shape[1] if y1 > shape[0]: y1 = shape[0] y, x = np.mgrid[y0:y1, x0:x1] data[y, x] += self.psfmodel.evaluate(x=x, y=y, flux=zzi, x_0=xxi, y_0=yyi) segm = detect_sources(data, 0., 5) props = source_properties(data, segm) orients = props.orientation.to(u.deg) assert_allclose(orients[1].value, 50., rtol=1.e-5) assert_allclose(orients[2].value, -80., rtol=1.e-5) assert 88.3 < orients[0].value < 88.4 assert 64. < orients[3].value < 64.2 @pytest.mark.skipif('not HAS_SCIPY') class TestIntegratedGaussianPRF: widths = [0.001, 0.01, 0.1, 1] sigmas = [0.5, 1., 2., 10., 12.34] @pytest.mark.parametrize('width', widths) def test_subpixel_gauss_psf(self, width): """ Test subpixel accuracy of IntegratedGaussianPRF by checking the sum of pixels. """ gauss_psf = IntegratedGaussianPRF(width) y, x = np.mgrid[-10:11, -10:11] assert_allclose(gauss_psf(x, y).sum(), 1) @pytest.mark.parametrize('sigma', sigmas) def test_gaussian_psf_integral(self, sigma): """ Test if IntegratedGaussianPRF integrates to unity on larger scales. """ psf = IntegratedGaussianPRF(sigma=sigma) y, x = np.mgrid[-100:101, -100:101] assert_allclose(psf(y, x).sum(), 1) @pytest.mark.skipif('not HAS_SCIPY') class TestPRFAdapter: def normalize_moffat(self, mof): # this is the analytic value needed to get a total flux of 1 mof = mof.copy() mof.amplitude = (mof.alpha-1)/(np.pi*mof.gamma**2) return mof @pytest.mark.parametrize("adapterkwargs", [ dict(xname='x_0', yname='y_0', fluxname=None, renormalize_psf=False), dict(xname=None, yname=None, fluxname=None, renormalize_psf=False), dict(xname='x_0', yname='y_0', fluxname='amplitude', renormalize_psf=False)]) def test_create_eval_prfadapter(self, adapterkwargs): mof = Moffat2D(gamma=1, alpha=4.8) prf = PRFAdapter(mof, **adapterkwargs) # test that these work without errors prf.x_0 = 0.5 prf.y_0 = -0.5 prf.flux = 1.2 prf(0, 0) @pytest.mark.parametrize("adapterkwargs", [ dict(xname='x_0', yname='y_0', fluxname=None, renormalize_psf=True), dict(xname='x_0', yname='y_0', fluxname=None, renormalize_psf=False), dict(xname=None, yname=None, fluxname=None, renormalize_psf=False) ]) def test_prfadapter_integrates(self, adapterkwargs): from scipy.integrate import dblquad mof = Moffat2D(gamma=1.5, alpha=4.8) if not adapterkwargs['renormalize_psf']: mof = self.normalize_moffat(mof) prf1 = PRFAdapter(mof, **adapterkwargs) # first check that the PRF over a central grid ends up summing to the # integrand over the whole PSF xg, yg = np.meshgrid(*([(-1, 0, 1)]*2)) evalmod = prf1(xg, yg) if adapterkwargs['renormalize_psf']: mof = self.normalize_moffat(mof) integrand, itol = dblquad(mof, -1.5, 1.5, lambda x: -1.5, lambda x: 1.5) assert_allclose(np.sum(evalmod), integrand, atol=itol * 10) @pytest.mark.parametrize("adapterkwargs", [ dict(xname='x_0', yname='y_0', fluxname=None, renormalize_psf=False), dict(xname=None, yname=None, fluxname=None, renormalize_psf=False)]) def test_prfadapter_sizematch(self, adapterkwargs): from scipy.integrate import dblquad mof1 = self.normalize_moffat(Moffat2D(gamma=1, alpha=4.8)) prf1 = PRFAdapter(mof1, **adapterkwargs) # now try integrating over differently-sampled PRFs # and check that they match mof2 = self.normalize_moffat(Moffat2D(gamma=2, alpha=4.8)) prf2 = PRFAdapter(mof2, **adapterkwargs) xg1, yg1 = np.meshgrid(*([(-0.5, 0.5)]*2)) xg2, yg2 = np.meshgrid(*([(-1.5, -0.5, 0.5, 1.5)]*2)) eval11 = prf1(xg1, yg1) eval22 = prf2(xg2, yg2) integrand, itol = dblquad(mof1, -2, 2, lambda x: -2, lambda x: 2) # it's a bit of a guess that the above itol is appropriate, but # it should be close assert_allclose(np.sum(eval11), np.sum(eval22), atol=itol*100) photutils-0.7.2/photutils/psf/tests/test_photometry.py0000644000214200020070000005745013572576136025600 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the photometry module. """ from astropy.convolution.utils import discretize_model from astropy.modeling import Fittable2DModel, Parameter from astropy.modeling.fitting import LevMarLSQFitter from astropy.modeling.models import Gaussian2D, Moffat2D from astropy.stats import SigmaClip, gaussian_sigma_to_fwhm from astropy.table import Table from astropy.tests.helper import catch_warnings from astropy.utils.exceptions import AstropyUserWarning import numpy as np from numpy.testing import assert_allclose, assert_array_equal, assert_equal import pytest from ..groupstars import DAOGroup from ..models import IntegratedGaussianPRF, FittableImageModel from ..photometry import (BasicPSFPhotometry, DAOPhotPSFPhotometry, IterativelySubtractedPSFPhotometry) from ..sandbox import DiscretePRF from ..utils import prepare_psf_model from ...background import MMMBackground, StdBackgroundRMS from ...datasets import make_gaussian_prf_sources_image, make_noise_image from ...detection import DAOStarFinder try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False def make_psf_photometry_objs(std=1, sigma_psf=1): """ Produces baseline photometry objects which are then modified as-needed in specific tests below """ daofind = DAOStarFinder(threshold=5.0*std, fwhm=sigma_psf*gaussian_sigma_to_fwhm) daogroup = DAOGroup(1.5*sigma_psf*gaussian_sigma_to_fwhm) threshold = 5. * std fwhm = sigma_psf * gaussian_sigma_to_fwhm crit_separation = 1.5 * sigma_psf * gaussian_sigma_to_fwhm daofind = DAOStarFinder(threshold=threshold, fwhm=fwhm) daogroup = DAOGroup(crit_separation) mode_bkg = MMMBackground() psf_model = IntegratedGaussianPRF(sigma=sigma_psf) fitter = LevMarLSQFitter() basic_phot_obj = BasicPSFPhotometry(finder=daofind, group_maker=daogroup, bkg_estimator=mode_bkg, psf_model=psf_model, fitter=fitter, fitshape=(11, 11)) iter_phot_obj = IterativelySubtractedPSFPhotometry(finder=daofind, group_maker=daogroup, bkg_estimator=mode_bkg, psf_model=psf_model, fitter=fitter, niters=1, fitshape=(11, 11)) dao_phot_obj = DAOPhotPSFPhotometry(crit_separation=crit_separation, threshold=threshold, fwhm=fwhm, psf_model=psf_model, fitshape=(11, 11), niters=1) return (basic_phot_obj, iter_phot_obj, dao_phot_obj) sigma_psfs = [] # A group of two overlapped stars and an isolated one sigma_psfs.append(2) sources1 = Table() sources1['flux'] = [800, 1000, 1200] sources1['x_0'] = [13, 18, 25] sources1['y_0'] = [16, 16, 25] sources1['sigma'] = [sigma_psfs[-1]] * 3 sources1['theta'] = [0] * 3 sources1['id'] = [1, 2, 3] sources1['group_id'] = [1, 1, 2] # one single group with four stars. sigma_psfs.append(2) sources2 = Table() sources2['flux'] = [700, 800, 700, 800] sources2['x_0'] = [12, 17, 12, 17] sources2['y_0'] = [15, 15, 20, 20] sources2['sigma'] = [sigma_psfs[-1]] * 4 sources2['theta'] = [0] * 4 sources2['id'] = [1, 2, 3, 4] sources2['group_id'] = [1, 1, 1, 1] # one faint star and one brither companion # although they are in the same group, the detection algorithm # is not able to detect the fainter star, hence photometry should # be performed with niters > 1 or niters=None sigma_psfs.append(2) sources3 = Table() sources3['flux'] = [10000, 1000] sources3['x_0'] = [18, 13] sources3['y_0'] = [17, 19] sources3['sigma'] = [sigma_psfs[-1]] * 2 sources3['theta'] = [0] * 2 sources3['id'] = [1] * 2 sources3['group_id'] = [1] * 2 sources3['iter_detected'] = [1, 2] @pytest.mark.skipif('not HAS_SCIPY') @pytest.mark.parametrize("sigma_psf, sources", [(sigma_psfs[2], sources3)]) def test_psf_photometry_niters(sigma_psf, sources): img_shape = (32, 32) # generate image with read-out noise (Gaussian) and # background noise (Poisson) image = (make_gaussian_prf_sources_image(img_shape, sources) + make_noise_image(img_shape, distribution='poisson', mean=6., random_state=1) + make_noise_image(img_shape, distribution='gaussian', mean=0., stddev=2., random_state=1)) cp_image = image.copy() sigma_clip = SigmaClip(sigma=3.) bkgrms = StdBackgroundRMS(sigma_clip) std = bkgrms(image) phot_obj = make_psf_photometry_objs(std, sigma_psf)[1:3] for iter_phot_obj in phot_obj: iter_phot_obj.niters = None result_tab = iter_phot_obj(image) residual_image = iter_phot_obj.get_residual_image() assert (result_tab['x_0_unc'] < 1.96 * sigma_psf / np.sqrt(sources['flux'])).all() assert (result_tab['y_0_unc'] < 1.96 * sigma_psf / np.sqrt(sources['flux'])).all() assert (result_tab['flux_unc'] < 1.96 * np.sqrt(sources['flux'])).all() assert_allclose(result_tab['x_fit'], sources['x_0'], rtol=1e-1) assert_allclose(result_tab['y_fit'], sources['y_0'], rtol=1e-1) assert_allclose(result_tab['flux_fit'], sources['flux'], rtol=1e-1) assert_array_equal(result_tab['id'], sources['id']) assert_array_equal(result_tab['group_id'], sources['group_id']) assert_array_equal(result_tab['iter_detected'], sources['iter_detected']) assert_allclose(np.mean(residual_image), 0.0, atol=1e1) # make sure image is note overwritten assert_array_equal(cp_image, image) @pytest.mark.skipif('not HAS_SCIPY') @pytest.mark.parametrize("sigma_psf, sources", [(sigma_psfs[0], sources1), (sigma_psfs[1], sources2), # these ensure that the test *fails* if the model # PSFs are the wrong shape pytest.param(sigma_psfs[0]/1.2, sources1, marks=pytest.mark.xfail()), pytest.param(sigma_psfs[1]*1.2, sources2, marks=pytest.mark.xfail())]) def test_psf_photometry_oneiter(sigma_psf, sources): """ Tests in an image with a group of two overlapped stars and an isolated one. """ img_shape = (32, 32) # generate image with read-out noise (Gaussian) and # background noise (Poisson) image = (make_gaussian_prf_sources_image(img_shape, sources) + make_noise_image(img_shape, distribution='poisson', mean=6., random_state=1) + make_noise_image(img_shape, distribution='gaussian', mean=0., stddev=2., random_state=1)) cp_image = image.copy() sigma_clip = SigmaClip(sigma=3.) bkgrms = StdBackgroundRMS(sigma_clip) std = bkgrms(image) phot_objs = make_psf_photometry_objs(std, sigma_psf) for phot_proc in phot_objs: result_tab = phot_proc(image) residual_image = phot_proc.get_residual_image() assert (result_tab['x_0_unc'] < 1.96 * sigma_psf / np.sqrt(sources['flux'])).all() assert (result_tab['y_0_unc'] < 1.96 * sigma_psf / np.sqrt(sources['flux'])).all() assert (result_tab['flux_unc'] < 1.96 * np.sqrt(sources['flux'])).all() assert_allclose(result_tab['x_fit'], sources['x_0'], rtol=1e-1) assert_allclose(result_tab['y_fit'], sources['y_0'], rtol=1e-1) assert_allclose(result_tab['flux_fit'], sources['flux'], rtol=1e-1) assert_array_equal(result_tab['id'], sources['id']) assert_array_equal(result_tab['group_id'], sources['group_id']) assert_allclose(np.mean(residual_image), 0.0, atol=1e1) # test fixed photometry phot_proc.psf_model.x_0.fixed = True phot_proc.psf_model.y_0.fixed = True pos = Table(names=['x_0', 'y_0'], data=[sources['x_0'], sources['y_0']]) cp_pos = pos.copy() result_tab = phot_proc(image, pos) residual_image = phot_proc.get_residual_image() assert 'x_0_unc' not in result_tab.colnames assert 'y_0_unc' not in result_tab.colnames assert (result_tab['flux_unc'] < 1.96 * np.sqrt(sources['flux'])).all() assert_array_equal(result_tab['x_fit'], sources['x_0']) assert_array_equal(result_tab['y_fit'], sources['y_0']) assert_allclose(result_tab['flux_fit'], sources['flux'], rtol=1e-1) assert_array_equal(result_tab['id'], sources['id']) assert_array_equal(result_tab['group_id'], sources['group_id']) assert_allclose(np.mean(residual_image), 0.0, atol=1e1) # make sure image is not overwritten assert_array_equal(cp_image, image) # make sure initial guess table is not modified assert_array_equal(cp_pos, pos) # resets fixed positions phot_proc.psf_model.x_0.fixed = False phot_proc.psf_model.y_0.fixed = False @pytest.mark.skipif('not HAS_SCIPY') def test_niters_errors(): iter_phot_obj = make_psf_photometry_objs()[1] # tests that niters is set to an integer even if the user inputs # a float iter_phot_obj.niters = 1.1 assert_equal(iter_phot_obj.niters, 1) # test that a ValueError is raised if niters <= 0 with pytest.raises(ValueError): iter_phot_obj.niters = 0 # test that it's OK to set niters to None iter_phot_obj.niters = None @pytest.mark.skipif('not HAS_SCIPY') def test_fitshape_errors(): basic_phot_obj = make_psf_photometry_objs()[0] # first make sure setting to a scalar does the right thing (and makes # no errors) basic_phot_obj.fitshape = 11 assert np.all(basic_phot_obj.fitshape == (11, 11)) # test that a ValuError is raised if fitshape has even components with pytest.raises(ValueError): basic_phot_obj.fitshape = (2, 2) with pytest.raises(ValueError): basic_phot_obj.fitshape = 2 # test that a ValueError is raised if fitshape has non positive # components with pytest.raises(ValueError): basic_phot_obj.fitshape = (-1, 0) # test that a ValueError is raised if fitshape has more than two # dimensions with pytest.raises(ValueError): basic_phot_obj.fitshape = (3, 3, 3) @pytest.mark.skipif('not HAS_SCIPY') def test_aperture_radius_errors(): basic_phot_obj = make_psf_photometry_objs()[0] # test that aperture_radius was set to None by default assert_equal(basic_phot_obj.aperture_radius, None) # test that a ValueError is raised if aperture_radius is non positive with pytest.raises(ValueError): basic_phot_obj.aperture_radius = -3 @pytest.mark.skipif('not HAS_SCIPY') def test_finder_errors(): iter_phot_obj = make_psf_photometry_objs()[1] with pytest.raises(ValueError): iter_phot_obj.finder = None with pytest.raises(ValueError): iter_phot_obj = IterativelySubtractedPSFPhotometry( finder=None, group_maker=DAOGroup(1), bkg_estimator=MMMBackground(), psf_model=IntegratedGaussianPRF(1), fitshape=(11, 11)) @pytest.mark.skipif('not HAS_SCIPY') def test_finder_positions_warning(): basic_phot_obj = make_psf_photometry_objs(sigma_psf=2)[0] positions = Table() positions['x_0'] = [12.8, 18.2, 25.3] positions['y_0'] = [15.7, 16.5, 25.1] image = (make_gaussian_prf_sources_image((32, 32), sources1) + make_noise_image((32, 32), distribution='poisson', mean=6., random_state=1)) with catch_warnings(AstropyUserWarning): result_tab = basic_phot_obj(image=image, init_guesses=positions) assert_array_equal(result_tab['x_0'], positions['x_0']) assert_array_equal(result_tab['y_0'], positions['y_0']) assert_allclose(result_tab['x_fit'], positions['x_0'], rtol=1e-1) assert_allclose(result_tab['y_fit'], positions['y_0'], rtol=1e-1) with pytest.raises(ValueError): basic_phot_obj.finder = None result_tab = basic_phot_obj(image=image) @pytest.mark.skipif('not HAS_SCIPY') def test_aperture_radius(): img_shape = (32, 32) # generate image with read-out noise (Gaussian) and # background noise (Poisson) image = (make_gaussian_prf_sources_image(img_shape, sources1) + make_noise_image(img_shape, distribution='poisson', mean=6., random_state=1) + make_noise_image(img_shape, distribution='gaussian', mean=0., stddev=2., random_state=1)) basic_phot_obj = make_psf_photometry_objs()[0] # test that aperture radius is properly set whenever the PSF model has # a `fwhm` attribute class PSFModelWithFWHM(Fittable2DModel): x_0 = Parameter(default=1) y_0 = Parameter(default=1) flux = Parameter(default=1) fwhm = Parameter(default=5) def __init__(self, fwhm=fwhm.default): super().__init__(fwhm=fwhm) def evaluate(self, x, y, x_0, y_0, flux, fwhm): return flux / (fwhm * (x - x_0)**2 * (y - y_0)**2) psf_model = PSFModelWithFWHM() basic_phot_obj.psf_model = psf_model basic_phot_obj(image) assert_equal(basic_phot_obj.aperture_radius, psf_model.fwhm.value) PARS_TO_SET_0 = {'x_0': 'x_0', 'y_0': 'y_0', 'flux_0': 'flux'} PARS_TO_OUTPUT_0 = {'x_fit': 'x_0', 'y_fit': 'y_0', 'flux_fit': 'flux'} PARS_TO_SET_1 = PARS_TO_SET_0.copy() PARS_TO_SET_1['sigma_0'] = 'sigma' PARS_TO_OUTPUT_1 = PARS_TO_OUTPUT_0.copy() PARS_TO_OUTPUT_1['sigma_fit'] = 'sigma' @pytest.mark.parametrize("actual_pars_to_set, actual_pars_to_output," "is_sigma_fixed", [(PARS_TO_SET_0, PARS_TO_OUTPUT_0, True), (PARS_TO_SET_1, PARS_TO_OUTPUT_1, False)]) @pytest.mark.skipif('not HAS_SCIPY') def test_define_fit_param_names(actual_pars_to_set, actual_pars_to_output, is_sigma_fixed): psf_model = IntegratedGaussianPRF() psf_model.sigma.fixed = is_sigma_fixed basic_phot_obj = make_psf_photometry_objs()[0] basic_phot_obj.psf_model = psf_model basic_phot_obj._define_fit_param_names() assert_equal(basic_phot_obj._pars_to_set, actual_pars_to_set) assert_equal(basic_phot_obj._pars_to_output, actual_pars_to_output) # tests previously written to psf_photometry PSF_SIZE = 11 GAUSSIAN_WIDTH = 1. IMAGE_SIZE = 101 # Position and FLUXES of test sources INTAB = Table([[50., 23, 12, 86], [50., 83, 80, 84], [np.pi * 10, 3.654, 20., 80 / np.sqrt(3)]], names=['x_0', 'y_0', 'flux_0']) # Create test psf psf_model = Gaussian2D(1. / (2 * np.pi * GAUSSIAN_WIDTH ** 2), PSF_SIZE // 2, PSF_SIZE // 2, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) test_psf = discretize_model(psf_model, (0, PSF_SIZE), (0, PSF_SIZE), mode='oversample') # Set up grid for test image image = np.zeros((IMAGE_SIZE, IMAGE_SIZE)) # Add sources to test image for x, y, flux in INTAB: model = Gaussian2D(flux / (2 * np.pi * GAUSSIAN_WIDTH ** 2), x, y, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) image += discretize_model(model, (0, IMAGE_SIZE), (0, IMAGE_SIZE), mode='oversample') # Some tests require an image with wider sources. WIDE_GAUSSIAN_WIDTH = 3. WIDE_INTAB = Table([[50, 23.2], [50.5, 1], [10, 20]], names=['x_0', 'y_0', 'flux_0']) wide_image = np.zeros((IMAGE_SIZE, IMAGE_SIZE)) # Add sources to test image for x, y, flux in WIDE_INTAB: model = Gaussian2D(flux / (2 * np.pi * WIDE_GAUSSIAN_WIDTH ** 2), x, y, WIDE_GAUSSIAN_WIDTH, WIDE_GAUSSIAN_WIDTH) wide_image += discretize_model(model, (0, IMAGE_SIZE), (0, IMAGE_SIZE), mode='oversample') @pytest.mark.skipif('not HAS_SCIPY') def test_psf_photometry_discrete(): """ Test psf_photometry with discrete PRF model. """ prf = DiscretePRF(test_psf, subsampling=1) basic_phot = BasicPSFPhotometry(group_maker=DAOGroup(2), bkg_estimator=None, psf_model=prf, fitshape=7) f = basic_phot(image=image, init_guesses=INTAB) for n in ['x', 'y', 'flux']: assert_allclose(f[n + '_0'], f[n + '_fit'], rtol=1e-6) @pytest.mark.skipif('not HAS_SCIPY') def test_tune_coordinates(): """ Test psf_photometry with discrete PRF model and coordinates that need to be adjusted in the fit. """ prf = DiscretePRF(test_psf, subsampling=1) prf.x_0.fixed = False prf.y_0.fixed = False # Shift all sources by 0.3 pixels intab = INTAB.copy() intab['x_0'] += 0.3 basic_phot = BasicPSFPhotometry(group_maker=DAOGroup(2), bkg_estimator=None, psf_model=prf, fitshape=7) f = basic_phot(image=image, init_guesses=intab) for n in ['x', 'y', 'flux']: assert_allclose(f[n + '_0'], f[n + '_fit'], rtol=1e-3) @pytest.mark.skipif('not HAS_SCIPY') def test_psf_boundary(): """ Test psf_photometry with discrete PRF model at the boundary of the data. """ prf = DiscretePRF(test_psf, subsampling=1) basic_phot = BasicPSFPhotometry(group_maker=DAOGroup(2), bkg_estimator=None, psf_model=prf, fitshape=7, aperture_radius=5.5) intab = Table(data=[[1], [1]], names=['x_0', 'y_0']) f = basic_phot(image=image, init_guesses=intab) assert_allclose(f['flux_fit'], 0, atol=1e-8) @pytest.mark.skipif('not HAS_SCIPY') def test_aperture_radius_value_error(): """ Test that a ValueError is raised for tabular PSF models when aperture_radius is not defined. """ prf = DiscretePRF(test_psf, subsampling=1) basic_phot = BasicPSFPhotometry(group_maker=DAOGroup(2), bkg_estimator=None, psf_model=prf, fitshape=7) with pytest.raises(ValueError): basic_phot(image=image) # with initial guesses, but without a "flux_0" column intab = Table(data=[[1], [1]], names=['x_0', 'y_0']) with pytest.raises(ValueError): basic_phot(image=image, init_guesses=intab) @pytest.mark.skipif('not HAS_SCIPY') def test_psf_boundary_gaussian(): """ Test psf_photometry with discrete PRF model at the boundary of the data. """ psf = IntegratedGaussianPRF(GAUSSIAN_WIDTH) basic_phot = BasicPSFPhotometry(group_maker=DAOGroup(2), bkg_estimator=None, psf_model=psf, fitshape=7) intab = Table(data=[[1], [1]], names=['x_0', 'y_0']) f = basic_phot(image=image, init_guesses=intab) assert_allclose(f['flux_fit'], 0, atol=1e-8) @pytest.mark.skipif('not HAS_SCIPY') def test_psf_photometry_gaussian(): """ Test psf_photometry with Gaussian PSF model. """ psf = IntegratedGaussianPRF(sigma=GAUSSIAN_WIDTH) basic_phot = BasicPSFPhotometry(group_maker=DAOGroup(2), bkg_estimator=None, psf_model=psf, fitshape=7) f = basic_phot(image=image, init_guesses=INTAB) for n in ['x', 'y', 'flux']: assert_allclose(f[n + '_0'], f[n + '_fit'], rtol=1e-3) @pytest.mark.skipif('not HAS_SCIPY') @pytest.mark.parametrize("renormalize_psf", (True, False)) def test_psf_photometry_gaussian2(renormalize_psf): """ Test psf_photometry with Gaussian PSF model from Astropy. """ psf = Gaussian2D(1. / (2 * np.pi * GAUSSIAN_WIDTH ** 2), PSF_SIZE // 2, PSF_SIZE // 2, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) psf = prepare_psf_model(psf, xname='x_mean', yname='y_mean', renormalize_psf=renormalize_psf) basic_phot = BasicPSFPhotometry(group_maker=DAOGroup(2), bkg_estimator=None, psf_model=psf, fitshape=7) f = basic_phot(image=image, init_guesses=INTAB) for n in ['x', 'y']: assert_allclose(f[n + '_0'], f[n + '_fit'], rtol=1e-1) assert_allclose(f['flux_0'], f['flux_fit'], rtol=1e-1) @pytest.mark.skipif('not HAS_SCIPY') def test_psf_photometry_moffat(): """ Test psf_photometry with Moffat PSF model from Astropy. """ psf = Moffat2D(1. / (2 * np.pi * GAUSSIAN_WIDTH ** 2), PSF_SIZE // 2, PSF_SIZE // 2, 1, 1) psf = prepare_psf_model(psf, xname='x_0', yname='y_0', renormalize_psf=False) basic_phot = BasicPSFPhotometry(group_maker=DAOGroup(2), bkg_estimator=None, psf_model=psf, fitshape=7) f = basic_phot(image=image, init_guesses=INTAB) f.pprint(max_width=-1) for n in ['x', 'y']: assert_allclose(f[n + '_0'], f[n + '_fit'], rtol=1e-3) # image was created with a gaussian, so flux won't match exactly assert_allclose(f['flux_0'], f['flux_fit'], rtol=1e-1) @pytest.mark.skipif('not HAS_SCIPY') def test_psf_fitting_data_on_edge(): """ No mask is input explicitly here, but source 2 is so close to the edge that the subarray that's extracted gets a mask internally. """ psf_guess = IntegratedGaussianPRF(flux=1, sigma=WIDE_GAUSSIAN_WIDTH) psf_guess.flux.fixed = psf_guess.x_0.fixed = psf_guess.y_0.fixed = False basic_phot = BasicPSFPhotometry(group_maker=DAOGroup(2), bkg_estimator=None, psf_model=psf_guess, fitshape=7) outtab = basic_phot(image=wide_image, init_guesses=WIDE_INTAB) for n in ['x', 'y', 'flux']: assert_allclose(outtab[n + '_0'], outtab[n + '_fit'], rtol=0.05, atol=0.1) @pytest.mark.skipif('not HAS_SCIPY') def test_finder_return_none(): """ Test psf_photometry with finder that does not return None if no sources are detected, to test Iterative PSF fitting. """ def tophatfinder(image): """ Simple top hat finder function for use with a top hat PRF""" fluxes = np.unique(image[image > 1]) table = Table(names=['id', 'xcentroid', 'ycentroid', 'flux'], dtype=[int, float, float, float]) for n, f in enumerate(fluxes): ys, xs = np.where(image == f) x = np.mean(xs) y = np.mean(ys) table.add_row([int(n+1), x, y, f*9]) table.sort(['flux']) return table prf = np.zeros((7, 7), float) prf[2:5, 2:5] = 1/9 prf = FittableImageModel(prf) img = np.zeros((50, 50), float) x0 = [38, 20, 35] y0 = [20, 5, 40] f0 = [50, 100, 200] for x, y, f in zip(x0, y0, f0): img[y-1:y+2, x-1:x+2] = f/9 intab = Table(data=[[37, 19.6, 34.9], [19.6, 4.5, 40.1], [45, 103, 210]], names=['x_0', 'y_0', 'flux_0']) iter_phot = IterativelySubtractedPSFPhotometry(finder=tophatfinder, group_maker=DAOGroup(2), bkg_estimator=None, psf_model=prf, fitshape=7, niters=2, aperture_radius=3) results = iter_phot(image=img, init_guesses=intab) assert_allclose(results['flux_fit'], f0, rtol=0.05) photutils-0.7.2/photutils/psf/tests/test_sandbox.py0000644000214200020070000000750613563423715025013 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the sandbox module. """ from astropy.convolution.utils import discretize_model from astropy.modeling.models import Gaussian2D from astropy.table import Table import numpy as np from numpy.testing import assert_allclose import pytest from ..sandbox import DiscretePRF PSF_SIZE = 11 GAUSSIAN_WIDTH = 1. IMAGE_SIZE = 101 # Position and FLUXES of test sources INTAB = Table([[50., 23, 12, 86], [50., 83, 80, 84], [np.pi * 10, 3.654, 20., 80 / np.sqrt(3)]], names=['x_0', 'y_0', 'flux_0']) # Create test psf psf_model = Gaussian2D(1. / (2 * np.pi * GAUSSIAN_WIDTH ** 2), PSF_SIZE // 2, PSF_SIZE // 2, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) test_psf = discretize_model(psf_model, (0, PSF_SIZE), (0, PSF_SIZE), mode='oversample') # Set up grid for test image image = np.zeros((IMAGE_SIZE, IMAGE_SIZE)) # Add sources to test image for x, y, flux in INTAB: model = Gaussian2D(flux / (2 * np.pi * GAUSSIAN_WIDTH ** 2), x, y, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) image += discretize_model(model, (0, IMAGE_SIZE), (0, IMAGE_SIZE), mode='oversample') # Some tests require an image with wider sources. WIDE_GAUSSIAN_WIDTH = 3. WIDE_INTAB = Table([[50, 23.2], [50.5, 1], [10, 20]], names=['x_0', 'y_0', 'flux_0']) wide_image = np.zeros((IMAGE_SIZE, IMAGE_SIZE)) # Add sources to test image for x, y, flux in WIDE_INTAB: model = Gaussian2D(flux / (2 * np.pi * WIDE_GAUSSIAN_WIDTH ** 2), x, y, WIDE_GAUSSIAN_WIDTH, WIDE_GAUSSIAN_WIDTH) wide_image += discretize_model(model, (0, IMAGE_SIZE), (0, IMAGE_SIZE), mode='oversample') def test_create_prf_mean(): """ Check if create_prf works correctly on simulated data. Position input format: list """ prf = DiscretePRF.create_from_image(image, list(INTAB['x_0', 'y_0'].as_array()), PSF_SIZE, subsampling=1, mode='mean') assert_allclose(prf._prf_array[0, 0], test_psf, atol=1E-8) def test_create_prf_median(): """ Check if create_prf works correctly on simulated data. Position input format: astropy.table.Table """ prf = DiscretePRF.create_from_image(image, np.array(INTAB['x_0', 'y_0']), PSF_SIZE, subsampling=1, mode='median') assert_allclose(prf._prf_array[0, 0], test_psf, atol=1E-8) def test_create_prf_nan(): """ Check if create_prf deals correctly with nan values. """ image_nan = image.copy() image_nan[52, 52] = np.nan image_nan[52, 48] = np.nan prf = DiscretePRF.create_from_image(image, np.array(INTAB['x_0', 'y_0']), PSF_SIZE, subsampling=1, fix_nan=True) assert not np.isnan(prf._prf_array[0, 0]).any() def test_create_prf_flux(): """ Check if create_prf works correctly when FLUXES are specified. """ prf = DiscretePRF.create_from_image(image, np.array(INTAB['x_0', 'y_0']), PSF_SIZE, subsampling=1, mode='median', fluxes=INTAB['flux_0']) assert_allclose(prf._prf_array[0, 0].sum(), 1) assert_allclose(prf._prf_array[0, 0], test_psf, atol=1E-8) def test_create_prf_excessive_subsampling(): """ Check if a helpful error is raised if the subsampling parameter is too high. """ with pytest.raises(ValueError) as exc: DiscretePRF.create_from_image(image, list(INTAB['x_0', 'y_0'].as_array()), PSF_SIZE, subsampling=999) assert('subsampling' in exc.value.args[0]) photutils-0.7.2/photutils/psf/tests/test_utils.py0000644000214200020070000001347313563423715024515 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the utils module. """ from astropy.convolution.utils import discretize_model from astropy.modeling.models import Gaussian2D from astropy.table import Table import numpy as np from numpy.testing import assert_allclose import pytest from ..models import IntegratedGaussianPRF from ..sandbox import DiscretePRF from ..utils import get_grouped_psf_model, prepare_psf_model, subtract_psf try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False PSF_SIZE = 11 GAUSSIAN_WIDTH = 1. IMAGE_SIZE = 101 # Position and FLUXES of test sources INTAB = Table([[50., 23, 12, 86], [50., 83, 80, 84], [np.pi * 10, 3.654, 20., 80 / np.sqrt(3)]], names=['x_0', 'y_0', 'flux_0']) # Create test psf psf_model = Gaussian2D(1. / (2 * np.pi * GAUSSIAN_WIDTH ** 2), PSF_SIZE // 2, PSF_SIZE // 2, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) test_psf = discretize_model(psf_model, (0, PSF_SIZE), (0, PSF_SIZE), mode='oversample') # Set up grid for test image image = np.zeros((IMAGE_SIZE, IMAGE_SIZE)) # Add sources to test image for x, y, flux in INTAB: model = Gaussian2D(flux / (2 * np.pi * GAUSSIAN_WIDTH ** 2), x, y, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) image += discretize_model(model, (0, IMAGE_SIZE), (0, IMAGE_SIZE), mode='oversample') @pytest.fixture(scope="module") def moffimg(): """ This fixture requires scipy so don't call it from non-scipy tests """ from scipy import integrate from astropy.modeling.models import Moffat2D mof = Moffat2D(alpha=4.8) # this is the analytic value needed to get a total flux of 1 mof.amplitude = (mof.alpha-1)/(np.pi*mof.gamma**2) # first make sure it really is normalized assert (1 - integrate.dblquad(mof, -10, 10, lambda x: -10, lambda x: 10)[0]) < 1e-6 # now create an "image" of the PSF xg, yg = np.meshgrid(*([np.linspace(-2, 2, 100)]*2)) return mof, (xg, yg, mof(xg, yg)) @pytest.mark.skipif('not HAS_SCIPY') def test_moffat_fitting(moffimg): """ Test that the Moffat to be fit in test_psf_adapter is behaving correctly """ from astropy.modeling.fitting import LevMarLSQFitter from astropy.modeling.models import Moffat2D mof, (xg, yg, img) = moffimg # a closeish-but-wrong "guessed Moffat" guess_moffat = Moffat2D(x_0=.1, y_0=-.05, gamma=1.05, amplitude=mof.amplitude*1.06, alpha=4.75) f = LevMarLSQFitter() fit_mof = f(guess_moffat, xg, yg, img) assert_allclose(fit_mof.parameters, mof.parameters, rtol=.01, atol=.0005) # we set the tolerances in flux to be 2-3% because the shape paraameters of # the guessed version are known to be wrong. @pytest.mark.parametrize("prepkwargs,tols", [ (dict(xname='x_0', yname='y_0', fluxname=None, renormalize_psf=True), (1e-3, .02)), (dict(xname=None, yname=None, fluxname=None, renormalize_psf=True), (1e-3, .02)), (dict(xname=None, yname=None, fluxname=None, renormalize_psf=False), (1e-3, .03)), (dict(xname='x_0', yname='y_0', fluxname='amplitude', renormalize_psf=False), (1e-3, None)), ]) @pytest.mark.skipif('not HAS_SCIPY') def test_prepare_psf_model(moffimg, prepkwargs, tols): """ Test that prepare_psf_model behaves as expected for fitting (don't worry about full-on psf photometry for now) """ from astropy.modeling.fitting import LevMarLSQFitter from astropy.modeling.models import Moffat2D mof, (xg, yg, img) = moffimg f = LevMarLSQFitter() # a close-but-wrong "guessed Moffat" guess_moffat = Moffat2D(x_0=.1, y_0=-.05, gamma=1.01, amplitude=mof.amplitude*1.01, alpha=4.79) if prepkwargs['renormalize_psf']: # definitely very wrong, so this ensures the re-normalization # stuff works guess_moffat.amplitude = 5. if prepkwargs['xname'] is None: guess_moffat.x_0 = 0 if prepkwargs['yname'] is None: guess_moffat.y_0 = 0 psfmod = prepare_psf_model(guess_moffat, **prepkwargs) xytol, fluxtol = tols fit_psfmod = f(psfmod, xg, yg, img) if xytol is not None: assert np.abs(getattr(fit_psfmod, fit_psfmod.xname)) < xytol assert np.abs(getattr(fit_psfmod, fit_psfmod.yname)) < xytol if fluxtol is not None: assert np.abs(1 - getattr(fit_psfmod, fit_psfmod.fluxname)) < fluxtol # ensure the amplitude and shape parameters did *not* change assert fit_psfmod.psfmodel.gamma == guess_moffat.gamma assert fit_psfmod.psfmodel.alpha == guess_moffat.alpha if prepkwargs['fluxname'] is None: assert fit_psfmod.psfmodel.amplitude == guess_moffat.amplitude @pytest.mark.skipif('not HAS_SCIPY') def test_get_grouped_psf_model(): igp = IntegratedGaussianPRF(sigma=1.2) tab = Table(names=['x_0', 'y_0', 'flux_0'], data=[[1, 2], [3, 4], [0.5, 1]]) pars_to_set = {'x_0': 'x_0', 'y_0': 'y_0', 'flux_0': 'flux'} gpsf = get_grouped_psf_model(igp, tab, pars_to_set) assert gpsf.x_0_0 == 1 assert gpsf.y_0_1 == 4 assert gpsf.flux_0 == 0.5 assert gpsf.flux_1 == 1 assert gpsf.sigma_0 == gpsf.sigma_1 == 1.2 @pytest.mark.skipif('not HAS_SCIPY') def test_subtract_psf(): """Test subtract_psf.""" prf = DiscretePRF(test_psf, subsampling=1) posflux = INTAB.copy() for n in posflux.colnames: posflux.rename_column(n, n.split('_')[0] + '_fit') residuals = subtract_psf(image, prf, posflux) assert_allclose(residuals, np.zeros_like(image), atol=1E-4) photutils-0.7.2/photutils/psf/utils.py0000644000214200020070000002062613572236170022307 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides utilities for PSF-fitting photometry. """ from astropy.table import Table from astropy.modeling import models from astropy.nddata.utils import add_array, extract_array import numpy as np __all__ = ['prepare_psf_model', 'get_grouped_psf_model', 'subtract_psf'] def prepare_psf_model(psfmodel, xname=None, yname=None, fluxname=None, renormalize_psf=True): """ Convert a 2D PSF model to one suitable for use with `BasicPSFPhotometry` or its subclasses. The resulting model may be a composite model, but should have only the x, y, and flux related parameters un-fixed. Parameters ---------- psfmodel : a 2D model The model to assume as representative of the PSF. xname : str or None The name of the ``psfmodel`` parameter that corresponds to the x-axis center of the PSF. If None, the model will be assumed to be centered at x=0, and a new parameter will be added for the offset. yname : str or None The name of the ``psfmodel`` parameter that corresponds to the y-axis center of the PSF. If None, the model will be assumed to be centered at y=0, and a new parameter will be added for the offset. fluxname : str or None The name of the ``psfmodel`` parameter that corresponds to the total flux of the star. If None, a scaling factor will be added to the model. renormalize_psf : bool If True, the model will be integrated from -inf to inf and re-scaled so that the total integrates to 1. Note that this renormalization only occurs *once*, so if the total flux of ``psfmodel`` depends on position, this will *not* be correct. Returns ------- outmod : a model A new model ready to be passed into `BasicPSFPhotometry` or its subclasses. """ if xname is None: xinmod = models.Shift(0, name='x_offset') xname = 'offset_0' else: xinmod = models.Identity(1) xname = xname + '_2' xinmod.fittable = True if yname is None: yinmod = models.Shift(0, name='y_offset') yname = 'offset_1' else: yinmod = models.Identity(1) yname = yname + '_2' yinmod.fittable = True outmod = (xinmod & yinmod) | psfmodel if fluxname is None: outmod = outmod * models.Const2D(1, name='flux_scaling') fluxname = 'amplitude_3' else: fluxname = fluxname + '_2' if renormalize_psf: # we do the import here because other machinery works w/o scipy from scipy import integrate integrand = integrate.dblquad(psfmodel, -np.inf, np.inf, lambda x: -np.inf, lambda x: np.inf)[0] normmod = models.Const2D(1./integrand, name='renormalize_scaling') outmod = outmod * normmod # final setup of the output model - fix all the non-offset/scale # parameters for pnm in outmod.param_names: outmod.fixed[pnm] = pnm not in (xname, yname, fluxname) # and set the names so that BasicPSFPhotometry knows what to do outmod.xname = xname outmod.yname = yname outmod.fluxname = fluxname # now some convenience aliases if reasonable outmod.psfmodel = outmod[2] if 'x_0' not in outmod.param_names and 'y_0' not in outmod.param_names: outmod.x_0 = getattr(outmod, xname) outmod.y_0 = getattr(outmod, yname) if 'flux' not in outmod.param_names: outmod.flux = getattr(outmod, fluxname) return outmod def get_grouped_psf_model(template_psf_model, star_group, pars_to_set): """ Construct a joint PSF model which consists of a sum of PSF's templated on a specific model, but whose parameters are given by a table of objects. Parameters ---------- template_psf_model : `astropy.modeling.Fittable2DModel` instance The model to use for *individual* objects. Must have parameters named ``x_0``, ``y_0``, and ``flux``. star_group : `~astropy.table.Table` Table of stars for which the compound PSF will be constructed. It must have columns named ``x_0``, ``y_0``, and ``flux_0``. Returns ------- group_psf An `astropy.modeling` ``CompoundModel`` instance which is a sum of the given PSF models. """ group_psf = None for star in star_group: psf_to_add = template_psf_model.copy() for param_tab_name, param_name in pars_to_set.items(): setattr(psf_to_add, param_name, star[param_tab_name]) if group_psf is None: # this is the first one only group_psf = psf_to_add else: group_psf += psf_to_add return group_psf def _extract_psf_fitting_names(psf): """ Determine the names of the x coordinate, y coordinate, and flux from a model. Returns (xname, yname, fluxname) """ if hasattr(psf, 'xname'): xname = psf.xname elif 'x_0' in psf.param_names: xname = 'x_0' else: raise ValueError('Could not determine x coordinate name for ' 'psf_photometry.') if hasattr(psf, 'yname'): yname = psf.yname elif 'y_0' in psf.param_names: yname = 'y_0' else: raise ValueError('Could not determine y coordinate name for ' 'psf_photometry.') if hasattr(psf, 'fluxname'): fluxname = psf.fluxname elif 'flux' in psf.param_names: fluxname = 'flux' else: raise ValueError('Could not determine flux name for psf_photometry.') return xname, yname, fluxname def _call_fitter(fitter, psf, x, y, data, weights): """ Not all fitters have to support a weight array. This function includes the weight in the fitter call only if really needed. """ if np.all(weights == 1.): return fitter(psf, x, y, data) else: return fitter(psf, x, y, data, weights=weights) def subtract_psf(data, psf, posflux, subshape=None): """ Subtract PSF/PRFs from an image. Parameters ---------- data : `~astropy.nddata.NDData` or array (must be 2D) Image data. psf : `astropy.modeling.Fittable2DModel` instance PSF/PRF model to be substracted from the data. posflux : Array-like of shape (3, N) or `~astropy.table.Table` Positions and fluxes for the objects to subtract. If an array, it is interpreted as ``(x, y, flux)`` If a table, the columns 'x_fit', 'y_fit', and 'flux_fit' must be present. subshape : length-2 or None The shape of the region around the center of the location to subtract the PSF from. If None, subtract from the whole image. Returns ------- subdata : same shape and type as ``data`` The image with the PSF subtracted """ if data.ndim != 2: raise ValueError('{0}-d array not supported. Only 2-d arrays can be ' 'passed to subtract_psf.'.format(data.ndim)) # translate array input into table if hasattr(posflux, 'colnames'): if 'x_fit' not in posflux.colnames: raise ValueError('Input table does not have x_fit') if 'y_fit' not in posflux.colnames: raise ValueError('Input table does not have y_fit') if 'flux_fit' not in posflux.colnames: raise ValueError('Input table does not have flux_fit') else: posflux = Table(names=['x_fit', 'y_fit', 'flux_fit'], data=posflux) # Set up contstants across the loop psf = psf.copy() xname, yname, fluxname = _extract_psf_fitting_names(psf) indices = np.indices(data.shape) subbeddata = data.copy() if subshape is None: indicies_reversed = indices[::-1] for row in posflux: getattr(psf, xname).value = row['x_fit'] getattr(psf, yname).value = row['y_fit'] getattr(psf, fluxname).value = row['flux_fit'] subbeddata -= psf(*indicies_reversed) else: for row in posflux: x_0, y_0 = row['x_fit'], row['y_fit'] y = extract_array(indices[0], subshape, (y_0, x_0)) x = extract_array(indices[1], subshape, (y_0, x_0)) getattr(psf, xname).value = x_0 getattr(psf, yname).value = y_0 getattr(psf, fluxname).value = row['flux_fit'] subbeddata = add_array(subbeddata, -psf(x, y), (y_0, x_0)) return subbeddata photutils-0.7.2/photutils/segmentation/0000755000214200020070000000000013573510273022474 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/segmentation/__init__.py0000644000214200020070000000053313563423715024611 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage contains tools for detecting sources using image segmentation and measuring their centroids, photometry, and morphological properties. """ from .core import * # noqa from .deblend import * # noqa from .detect import * # noqa from .properties import * # noqa photutils-0.7.2/photutils/segmentation/core.py0000644000214200020070000012140413572576136024011 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides classes for a segmentation image and a single segment within a segmentation image. """ from copy import deepcopy from astropy.utils import lazyproperty, deprecated import numpy as np from ..aperture import BoundingBox from ..utils.colormaps import make_random_cmap __all__ = ['Segment', 'SegmentationImage'] __doctest_requires__ = {('SegmentationImage', 'SegmentationImage.*'): ['scipy']} class Segment: """ Class for a single labeled region (segment) within a segmentation image. Parameters ---------- segment_data : int `~numpy.ndarray` A segmentation array where source regions are labeled by different positive integer values. A value of zero is reserved for the background. label : int The segment label number. slices : tuple of two slices A tuple of two slices representing the minimal box that contains the labeled region. area : float The area of the segment in pixels**2. """ def __init__(self, segment_data, label, slices, area): self._segment_data = segment_data self.label = label self.slices = slices self.area = area def __str__(self): cls_name = '<{0}.{1}>'.format(self.__class__.__module__, self.__class__.__name__) cls_info = [] params = ['label', 'slices', 'area'] for param in params: cls_info.append((param, getattr(self, param))) fmt = ['{0}: {1}'.format(key, val) for key, val in cls_info] return '{}\n'.format(cls_name) + '\n'.join(fmt) def __repr__(self): return self.__str__() def __array__(self): """ Array representation of the labeled region (e.g., for matplotlib). """ return self.data @lazyproperty def data(self): """ A cutout array of the segment using the minimal bounding box, where pixels outside of the labeled region are set to zero (i.e. neighboring segments within the rectangular cutout array are not shown). """ cutout = np.copy(self._segment_data[self.slices]) cutout[cutout != self.label] = 0 return cutout @lazyproperty def data_ma(self): """ A `~numpy.ma.MaskedArray` cutout array of the segment using the minimal bounding box. The mask is `True` for pixels outside of the source segment (i.e. neighboring segments within the rectangular cutout array are masked). """ mask = (self._segment_data[self.slices] != self.label) return np.ma.masked_array(self._segment_data[self.slices], mask=mask) @lazyproperty def bbox(self): """ The `~photutils.aperture.BoundingBox` of the minimal rectangular region containing the source segment. """ if self._segment_data.ndim != 2: raise ValueError('The "bbox" attribute requires a 2D ' 'segmentation image.') return BoundingBox(self.slices[1].start, self.slices[1].stop, self.slices[0].start, self.slices[0].stop) def make_cutout(self, data, masked_array=False): """ Create a (masked) cutout array from the input ``data`` using the minimal bounding box of the segment (labeled region). If ``masked_array`` is `False` (default), then the returned cutout array is simply a `~numpy.ndarray`. The returned cutout is a view (not a copy) of the input ``data``. No pixels are altered (e.g. set to zero) within the bounding box. If ``masked_array` is `True`, then the returned cutout array is a `~numpy.ma.MaskedArray`, where the mask is `True` for pixels outside of the segment (labeled region). The data part of the masked array is a view (not a copy) of the input ``data``. Parameters ---------- data : array-like The data array from which to create the masked cutout array. ``data`` must have the same shape as the segmentation array. masked_array : bool, optional If `True` then a `~numpy.ma.MaskedArray` will be created where the mask is `True` for pixels outside of the segment (labeled region). If `False`, then a `~numpy.ndarray` will be generated. Returns ------- result : `~numpy.ndarray` or `~numpy.ma.MaskedArray` The cutout array. """ data = np.asanyarray(data) if data.shape != self._segment_data.shape: raise ValueError('data must have the same shape as the ' 'segmentation array.') if masked_array: mask = (self._segment_data[self.slices] != self.label) return np.ma.masked_array(data[self.slices], mask=mask) else: return data[self.slices] class SegmentationImage: """ Class for a segmentation image. Parameters ---------- data : array_like (int) A segmentation array where source regions are labeled by different positive integer values. A value of zero is reserved for the background. The segmentation image must contain at least one non-zero pixel and must not contain any non-finite values (e.g. NaN, inf). """ def __init__(self, data): self.data = data def __getitem__(self, index): return self.segments[index] def __iter__(self): for i in self.segments: yield i def __str__(self): cls_name = '<{0}.{1}>'.format(self.__class__.__module__, self.__class__.__name__) cls_info = [] params = ['shape', 'nlabels', 'max_label'] for param in params: cls_info.append((param, getattr(self, param))) fmt = ['{0}: {1}'.format(key, val) for key, val in cls_info] return '{}\n'.format(cls_name) + '\n'.join(fmt) def __repr__(self): return self.__str__() def __array__(self): """ Array representation of the segmentation array (e.g., for matplotlib). """ return self._data @lazyproperty def _cmap(self): """ A matplotlib colormap consisting of (random) muted colors. This is very useful for plotting the segmentation array. """ return self.make_cmap(background_color='#000000', random_state=1234) @staticmethod def _get_labels(data): """ Return a sorted array of the non-zero labels in the segmentation image. Parameters ---------- data : array_like (int) A segmentation array where source regions are labeled by different positive integer values. A value of zero is reserved for the background. Returns ------- result : `~numpy.ndarray` An array of non-zero label numbers. Notes ----- This is a static method so it can be used in :meth:`remove_masked_labels` on a masked version of the segmentation array. Examples -------- >>> from photutils import SegmentationImage >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm._get_labels(segm.data) array([1, 3, 4, 5, 7]) """ # np.unique also sorts elements return np.unique(data[data != 0]) @lazyproperty def segments(self): """ A list of `Segment` objects. The list starts with the *non-zero* label. The returned list has a length equal to the number of labels and matches the order of the ``labels`` attribute. """ segments = [] for label, slc in zip(self.labels, self.slices): segments.append(Segment(self.data, label, slc, self.get_area(label))) return segments @property def data(self): """The segmentation array.""" return self._data @data.setter def data(self, value): if np.any(~np.isfinite(value)): raise ValueError('data must not contain any non-finite values ' '(e.g. NaN, inf)') value = np.asarray(value, dtype=int) if not np.any(value): raise ValueError('The segmentation image must contain at least ' 'one non-zero pixel.') if np.min(value) < 0: raise ValueError('The segmentation image cannot contain ' 'negative integers.') if '_data' in self.__dict__: # needed only when data is reassigned, not on init self.__dict__ = {} self._data = value # pylint: disable=attribute-defined-outside-init @lazyproperty def data_ma(self): """ A `~numpy.ma.MaskedArray` version of the segmentation array where the background (label = 0) has been masked. """ return np.ma.masked_where(self.data == 0, self.data) @lazyproperty def shape(self): """The shape of the segmentation array.""" return self._data.shape @lazyproperty def _ndim(self): """The number of array dimensions of the segmentation array.""" return self._data.ndim @lazyproperty def labels(self): """The sorted non-zero labels in the segmentation array.""" return self._get_labels(self.data) @lazyproperty def nlabels(self): """The number of non-zero labels in the segmentation array.""" return len(self.labels) @lazyproperty def max_label(self): """The maximum non-zero label in the segmentation array.""" return np.max(self.labels) def get_index(self, label): """ Find the index of the input ``label``. Parameters ---------- labels : int The label numbers to find. Returns ------- index : int The array index. Raises ------ ValueError If ``label`` is invalid. """ self.check_labels(label) return np.searchsorted(self.labels, label) def get_indices(self, labels): """ Find the indices of the input ``labels``. Parameters ---------- labels : int, array-like (1D, int) The label numbers(s) to find. Returns ------- indices : int `~numpy.ndarray` An integer array of indices with the same shape as ``labels``. If ``labels`` is a scalar, then the returned index will also be a scalar. Raises ------ ValueError If any input ``labels`` are invalid. """ self.check_labels(labels) return np.searchsorted(self.labels, labels) @lazyproperty def slices(self): """ A list of tuples, where each tuple contains two slices representing the minimal box that contains the labeled region. The list starts with the *non-zero* label. The returned list has a length equal to the number of labels and matches the order of the ``labels`` attribute. """ from scipy.ndimage import find_objects return [slc for slc in find_objects(self._data) if slc is not None] @lazyproperty def background_area(self): """The area (in pixel**2) of the background (label=0) region.""" return len(self.data[self.data == 0]) @lazyproperty def areas(self): """ A 1D array of areas (in pixel**2) of the non-zero labeled regions. The `~numpy.ndarray` starts with the *non-zero* label. The returned array has a length equal to the number of labels and matches the order of the ``labels`` attribute. """ return np.array([area for area in np.bincount(self.data.ravel())[1:] if area != 0]) def get_area(self, label): """ The area (in pixel**2) of the region for the input label. Parameters ---------- label : int The label whose area to return. Label must be non-zero. Returns ------- area : `~numpy.ndarray` The area of the labeled region. """ return self.get_areas(label) def get_areas(self, labels): """ The areas (in pixel**2) of the regions for the input labels. Parameters ---------- labels : int, 1D array-like (int) The label(s) for which to return areas. Label must be non-zero. Returns ------- areas : `~numpy.ndarray` The areas of the labeled regions. """ idx = self.get_indices(labels) return self.areas[idx] @lazyproperty def is_consecutive(self): """ Determine whether or not the non-zero labels in the segmentation array are consecutive and start from 1. """ return ((self.labels[-1] - self.labels[0] + 1) == self.nlabels and self.labels[0] == 1) @lazyproperty def missing_labels(self): """ A 1D `~numpy.ndarray` of the sorted non-zero labels that are missing in the consecutive sequence from one to the maximum label number. """ return np.array(sorted(set(range(0, self.max_label + 1)) .difference(np.insert(self.labels, 0, 0)))) def copy(self): """Return a deep copy of this class instance.""" return deepcopy(self) def check_label(self, label): """ Check that the input label is a valid label number within the segmentation array. Parameters ---------- label : int The label number to check. Raises ------ ValueError If the input ``label`` is invalid. """ self.check_labels(label) def check_labels(self, labels): """ Check that the input label(s) are valid label numbers within the segmentation array. Parameters ---------- labels : int, 1D array-like (int) The label(s) to check. Raises ------ ValueError If any input ``labels`` are invalid. """ labels = np.atleast_1d(labels) bad_labels = set() # check for positive label numbers idx = np.where(labels <= 0)[0] if idx.size > 0: bad_labels.update(labels[idx]) # check if label is in the segmentation array bad_labels.update(np.setdiff1d(labels, self.labels)) if bad_labels: if len(bad_labels) == 1: raise ValueError('label {} is invalid'.format(bad_labels)) else: raise ValueError('labels {} are invalid'.format(bad_labels)) @deprecated('0.7', alternative='make_cmap') def cmap(self, background_color='#000000', random_state=None): """ Define a matplotlib colormap consisting of (random) muted colors. This is very useful for plotting the segmentation array. Parameters ---------- background_color : str or `None`, optional A hex string in the "#rrggbb" format defining the first color in the colormap. This color will be used as the background color (label = 0) when plotting the segmentation array. The default is black ('#000000'). random_state : int or `~numpy.random.mtrand.RandomState`, optional The pseudo-random number generator state used for random sampling. Separate function calls with the same ``random_state`` will generate the same colormap. """ return self.make_cmap(background_color=background_color, random_state=random_state) # pragma: no cover def make_cmap(self, background_color='#000000', random_state=None): """ Define a matplotlib colormap consisting of (random) muted colors. This is very useful for plotting the segmentation array. Parameters ---------- background_color : str or `None`, optional A hex string in the "#rrggbb" format defining the first color in the colormap. This color will be used as the background color (label = 0) when plotting the segmentation array. The default is black ('#000000'). random_state : int or `~numpy.random.mtrand.RandomState`, optional The pseudo-random number generator state used for random sampling. Separate function calls with the same ``random_state`` will generate the same colormap. Returns ------- cmap : `matplotlib.colors.ListedColormap` The matplotlib colormap. """ from matplotlib import colors cmap = make_random_cmap(self.max_label + 1, random_state=random_state) if background_color is not None: cmap.colors[0] = colors.hex2color(background_color) return cmap @deprecated('0.7', alternative='reassign_labels') def relabel(self, labels, new_label): """ Reassign one or more label numbers. Multiple input ``labels`` will all be reassigned to the same ``new_label`` number. Parameters ---------- labels : int, array-like (1D, int) The label numbers(s) to reassign. new_label : int The reassigned label number. """ self.reassign_label(labels, new_label) # pragma: no cover def reassign_label(self, label, new_label, relabel=False): """ Reassign a label number to a new number. If ``new_label`` is already present in the segmentation array, then it will be combined with the input ``label`` number. Parameters ---------- labels : int The label number to reassign. new_label : int The newly assigned label number. relabel : bool, optional If `True`, then the segmentation array will be relabeled such that the labels are in consecutive order starting from 1. Examples -------- >>> from photutils import SegmentationImage >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.reassign_label(label=1, new_label=2) >>> segm.data array([[2, 2, 0, 0, 4, 4], [0, 0, 0, 0, 0, 4], [0, 0, 3, 3, 0, 0], [7, 0, 0, 0, 0, 5], [7, 7, 0, 5, 5, 5], [7, 7, 0, 0, 5, 5]]) >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.reassign_label(label=1, new_label=4) >>> segm.data array([[4, 4, 0, 0, 4, 4], [0, 0, 0, 0, 0, 4], [0, 0, 3, 3, 0, 0], [7, 0, 0, 0, 0, 5], [7, 7, 0, 5, 5, 5], [7, 7, 0, 0, 5, 5]]) >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.reassign_label(label=1, new_label=4, relabel=True) >>> segm.data array([[2, 2, 0, 0, 2, 2], [0, 0, 0, 0, 0, 2], [0, 0, 1, 1, 0, 0], [4, 0, 0, 0, 0, 3], [4, 4, 0, 3, 3, 3], [4, 4, 0, 0, 3, 3]]) """ self.reassign_labels(label, new_label, relabel=relabel) def reassign_labels(self, labels, new_label, relabel=False): """ Reassign one or more label numbers. Multiple input ``labels`` will all be reassigned to the same ``new_label`` number. If ``new_label`` is already present in the segmentation array, then it will be combined with the input ``labels``. Parameters ---------- labels : int, array-like (1D, int) The label numbers(s) to reassign. new_label : int The reassigned label number. relabel : bool, optional If `True`, then the segmentation array will be relabeled such that the labels are in consecutive order starting from 1. Examples -------- >>> from photutils import SegmentationImage >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.reassign_labels(labels=[1, 7], new_label=2) >>> segm.data array([[2, 2, 0, 0, 4, 4], [0, 0, 0, 0, 0, 4], [0, 0, 3, 3, 0, 0], [2, 0, 0, 0, 0, 5], [2, 2, 0, 5, 5, 5], [2, 2, 0, 0, 5, 5]]) >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.reassign_labels(labels=[1, 7], new_label=4) >>> segm.data array([[4, 4, 0, 0, 4, 4], [0, 0, 0, 0, 0, 4], [0, 0, 3, 3, 0, 0], [4, 0, 0, 0, 0, 5], [4, 4, 0, 5, 5, 5], [4, 4, 0, 0, 5, 5]]) >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.reassign_labels(labels=[1, 7], new_label=2, relabel=True) >>> segm.data array([[1, 1, 0, 0, 3, 3], [0, 0, 0, 0, 0, 3], [0, 0, 2, 2, 0, 0], [1, 0, 0, 0, 0, 4], [1, 1, 0, 4, 4, 4], [1, 1, 0, 0, 4, 4]]) """ self.check_labels(labels) labels = np.atleast_1d(labels) if labels.size == 0: return idx = np.zeros(self.max_label + 1, dtype=int) idx[self.labels] = self.labels idx[labels] = new_label # reassign labels if relabel: labels = np.unique(idx[idx != 0]) idx2 = np.zeros(max(labels) + 1, dtype=int) idx2[labels] = np.arange(len(labels)) + 1 idx = idx2[idx] data_new = idx[self.data] self.__dict__ = {} # reset all cached properties self._data = data_new # use _data to avoid validation def relabel_consecutive(self, start_label=1): """ Reassign the label numbers consecutively starting from a given label number. Parameters ---------- start_label : int, optional The starting label number, which should be a strictly positive integer. The default is 1. Examples -------- >>> from photutils import SegmentationImage >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.relabel_consecutive() >>> segm.data array([[1, 1, 0, 0, 3, 3], [0, 0, 0, 0, 0, 3], [0, 0, 2, 2, 0, 0], [5, 0, 0, 0, 0, 4], [5, 5, 0, 4, 4, 4], [5, 5, 0, 0, 4, 4]]) """ if start_label <= 0: raise ValueError('start_label must be > 0.') if ((self.labels[0] == start_label) and (self.labels[-1] - self.labels[0] + 1) == self.nlabels): return new_labels = np.zeros(self.max_label + 1, dtype=int) new_labels[self.labels] = np.arange(self.nlabels) + start_label data_new = new_labels[self.data] self.__dict__ = {} # reset all cached properties self._data = data_new # use _data to avoid validation def keep_label(self, label, relabel=False): """ Keep only the specified label. Parameters ---------- label : int The label number to keep. relabel : bool, optional If `True`, then the single segment will be assigned a label value of 1. Examples -------- >>> from photutils import SegmentationImage >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.keep_label(label=3) >>> segm.data array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 3, 3, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]) >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.keep_label(label=3, relabel=True) >>> segm.data array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]) """ self.keep_labels(label, relabel=relabel) def keep_labels(self, labels, relabel=False): """ Keep only the specified labels. Parameters ---------- labels : int, array-like (1D, int) The label number(s) to keep. relabel : bool, optional If `True`, then the segmentation array will be relabeled such that the labels are in consecutive order starting from 1. Examples -------- >>> from photutils import SegmentationImage >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.keep_labels(labels=[5, 3]) >>> segm.data array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 3, 3, 0, 0], [0, 0, 0, 0, 0, 5], [0, 0, 0, 5, 5, 5], [0, 0, 0, 0, 5, 5]]) >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.keep_labels(labels=[5, 3], relabel=True) >>> segm.data array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 0, 0], [0, 0, 0, 0, 0, 2], [0, 0, 0, 2, 2, 2], [0, 0, 0, 0, 2, 2]]) """ self.check_labels(labels) labels = np.atleast_1d(labels) labels_tmp = list(set(self.labels) - set(labels)) self.remove_labels(labels_tmp, relabel=relabel) def remove_label(self, label, relabel=False): """ Remove the label number. The removed label is assigned a value of zero (i.e., background). Parameters ---------- label : int The label number to remove. relabel : bool, optional If `True`, then the segmentation array will be relabeled such that the labels are in consecutive order starting from 1. Examples -------- >>> from photutils import SegmentationImage >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.remove_label(label=5) >>> segm.data array([[1, 1, 0, 0, 4, 4], [0, 0, 0, 0, 0, 4], [0, 0, 3, 3, 0, 0], [7, 0, 0, 0, 0, 0], [7, 7, 0, 0, 0, 0], [7, 7, 0, 0, 0, 0]]) >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.remove_label(label=5, relabel=True) >>> segm.data array([[1, 1, 0, 0, 3, 3], [0, 0, 0, 0, 0, 3], [0, 0, 2, 2, 0, 0], [4, 0, 0, 0, 0, 0], [4, 4, 0, 0, 0, 0], [4, 4, 0, 0, 0, 0]]) """ self.remove_labels(label, relabel=relabel) def remove_labels(self, labels, relabel=False): """ Remove one or more labels. Removed labels are assigned a value of zero (i.e., background). Parameters ---------- labels : int, array-like (1D, int) The label number(s) to remove. relabel : bool, optional If `True`, then the segmentation array will be relabeled such that the labels are in consecutive order starting from 1. Examples -------- >>> from photutils import SegmentationImage >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.remove_labels(labels=[5, 3]) >>> segm.data array([[1, 1, 0, 0, 4, 4], [0, 0, 0, 0, 0, 4], [0, 0, 0, 0, 0, 0], [7, 0, 0, 0, 0, 0], [7, 7, 0, 0, 0, 0], [7, 7, 0, 0, 0, 0]]) >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.remove_labels(labels=[5, 3], relabel=True) >>> segm.data array([[1, 1, 0, 0, 2, 2], [0, 0, 0, 0, 0, 2], [0, 0, 0, 0, 0, 0], [3, 0, 0, 0, 0, 0], [3, 3, 0, 0, 0, 0], [3, 3, 0, 0, 0, 0]]) """ self.check_labels(labels) self.reassign_labels(labels, new_label=0, relabel=relabel) def remove_border_labels(self, border_width, partial_overlap=True, relabel=False): """ Remove labeled segments near the array border. Labels within the defined border region will be removed. Parameters ---------- border_width : int The width of the border region in pixels. partial_overlap : bool, optional If this is set to `True` (the default), a segment that partially extends into the border region will be removed. Segments that are completely within the border region are always removed. relabel : bool, optional If `True`, then the segmentation array will be relabeled such that the labels are in consecutive order starting from 1. Examples -------- >>> from photutils import SegmentationImage >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.remove_border_labels(border_width=1) >>> segm.data array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 3, 3, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]) >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.remove_border_labels(border_width=1, ... partial_overlap=False) >>> segm.data array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 3, 3, 0, 0], [7, 0, 0, 0, 0, 5], [7, 7, 0, 5, 5, 5], [7, 7, 0, 0, 5, 5]]) """ if border_width >= min(self.shape) / 2: raise ValueError('border_width must be smaller than half the ' 'array size in any dimension') border_mask = np.zeros(self.shape, dtype=bool) for i in range(border_mask.ndim): border_mask = border_mask.swapaxes(0, i) border_mask[:border_width] = True border_mask[-border_width:] = True border_mask = border_mask.swapaxes(0, i) self.remove_masked_labels(border_mask, partial_overlap=partial_overlap, relabel=relabel) def remove_masked_labels(self, mask, partial_overlap=True, relabel=False): """ Remove labeled segments located within a masked region. Parameters ---------- mask : array_like (bool) A boolean mask, with the same shape as the segmentation array, where `True` values indicate masked pixels. partial_overlap : bool, optional If this is set to `True` (default), a segment that partially extends into a masked region will also be removed. Segments that are completely within a masked region are always removed. relabel : bool, optional If `True`, then the segmentation array will be relabeled such that the labels are in consecutive order starting from 1. Examples -------- >>> from photutils import SegmentationImage >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> mask = np.zeros(segm.data.shape, dtype=bool) >>> mask[0, :] = True # mask the first row >>> segm.remove_masked_labels(mask) >>> segm.data array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 3, 3, 0, 0], [7, 0, 0, 0, 0, 5], [7, 7, 0, 5, 5, 5], [7, 7, 0, 0, 5, 5]]) >>> segm = SegmentationImage([[1, 1, 0, 0, 4, 4], ... [0, 0, 0, 0, 0, 4], ... [0, 0, 3, 3, 0, 0], ... [7, 0, 0, 0, 0, 5], ... [7, 7, 0, 5, 5, 5], ... [7, 7, 0, 0, 5, 5]]) >>> segm.remove_masked_labels(mask, partial_overlap=False) >>> segm.data array([[0, 0, 0, 0, 4, 4], [0, 0, 0, 0, 0, 4], [0, 0, 3, 3, 0, 0], [7, 0, 0, 0, 0, 5], [7, 7, 0, 5, 5, 5], [7, 7, 0, 0, 5, 5]]) """ if mask.shape != self.shape: raise ValueError('mask must have the same shape as the ' 'segmentation array') remove_labels = self._get_labels(self.data[mask]) if not partial_overlap: interior_labels = self._get_labels(self.data[~mask]) remove_labels = list(set(remove_labels) - set(interior_labels)) self.remove_labels(remove_labels, relabel=relabel) def outline_segments(self, mask_background=False): """ Outline the labeled segments. The "outlines" represent the pixels *just inside* the segments, leaving the background pixels unmodified. Parameters ---------- mask_background : bool, optional Set to `True` to mask the background pixels (labels = 0) in the returned array. This is useful for overplotting the segment outlines. The default is `False`. Returns ------- boundaries : `~numpy.ndarray` or `~numpy.ma.MaskedArray` An array with the same shape of the segmentation array containing only the outlines of the labeled segments. The pixel values in the outlines correspond to the labels in the segmentation array. If ``mask_background`` is `True`, then a `~numpy.ma.MaskedArray` is returned. Examples -------- >>> from photutils import SegmentationImage >>> segm = SegmentationImage([[0, 0, 0, 0, 0, 0], ... [0, 2, 2, 2, 2, 0], ... [0, 2, 2, 2, 2, 0], ... [0, 2, 2, 2, 2, 0], ... [0, 2, 2, 2, 2, 0], ... [0, 0, 0, 0, 0, 0]]) >>> segm.outline_segments() array([[0, 0, 0, 0, 0, 0], [0, 2, 2, 2, 2, 0], [0, 2, 0, 0, 2, 0], [0, 2, 0, 0, 2, 0], [0, 2, 2, 2, 2, 0], [0, 0, 0, 0, 0, 0]]) """ from scipy.ndimage import (generate_binary_structure, grey_dilation, grey_erosion) # mode='constant' ensures outline is included on the array borders selem = generate_binary_structure(self._ndim, 1) # edge connectivity eroded = grey_erosion(self.data, footprint=selem, mode='constant', cval=0.) dilated = grey_dilation(self.data, footprint=selem, mode='constant', cval=0.) outlines = ((dilated != eroded) & (self.data != 0)).astype(int) outlines *= self.data if mask_background: outlines = np.ma.masked_where(outlines == 0, outlines) return outlines photutils-0.7.2/photutils/segmentation/deblend.py0000644000214200020070000003156413572576136024465 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for deblending overlapping sources labeled in a segmentation image. """ import warnings from astropy.utils.exceptions import AstropyUserWarning import numpy as np from .core import SegmentationImage from .detect import _make_binary_structure, _detect_sources from ..utils.convolution import _filter_data from ..utils.exceptions import NoDetectionsWarning __all__ = ['deblend_sources'] def deblend_sources(data, segment_img, npixels, filter_kernel=None, labels=None, nlevels=32, contrast=0.001, mode='exponential', connectivity=8, relabel=True): """ Deblend overlapping sources labeled in a segmentation image. Sources are deblended using a combination of multi-thresholding and `watershed segmentation `_. In order to deblend sources, there must be a saddle between them. Parameters ---------- data : array_like The data array. segment_img : `~photutils.segmentation.SegmentationImage` or array_like (int) A segmentation image, either as a `~photutils.segmentation.SegmentationImage` object or an `~numpy.ndarray`, with the same shape as ``data`` where sources are labeled by different positive integer values. A value of zero is reserved for the background. npixels : int The number of connected pixels, each greater than ``threshold``, that an object must have to be detected. ``npixels`` must be a positive integer. filter_kernel : array-like or `~astropy.convolution.Kernel2D`, optional The array of the kernel used to filter the image before thresholding. Filtering the image will smooth the noise and maximize detectability of objects with a shape similar to the kernel. labels : int or array-like of int, optional The label numbers to deblend. If `None` (default), then all labels in the segmentation image will be deblended. nlevels : int, optional The number of multi-thresholding levels to use. Each source will be re-thresholded at ``nlevels`` levels spaced exponentially or linearly (see the ``mode`` keyword) between its minimum and maximum values within the source segment. contrast : float, optional The fraction of the total (blended) source flux that a local peak must have (at any one of the multi-thresholds) to be considered as a separate object. ``contrast`` must be between 0 and 1, inclusive. If ``contrast = 0`` then every local peak will be made a separate object (maximum deblending). If ``contrast = 1`` then no deblending will occur. The default is 0.001, which will deblend sources with a 7.5 magnitude difference. mode : {'exponential', 'linear'}, optional The mode used in defining the spacing between the multi-thresholding levels (see the ``nlevels`` keyword). The default is 'exponential'. connectivity : {8, 4}, optional The type of pixel connectivity used in determining how pixels are grouped into a detected source. The options are 8 (default) or 4. 8-connected pixels touch along their edges or corners. 4-connected pixels touch along their edges. For reference, SExtractor uses 8-connected pixels. relabel : bool If `True` (default), then the segmentation image will be relabeled such that the labels are in consecutive order starting from 1. Returns ------- segment_image : `~photutils.segmentation.SegmentationImage` A segmentation image, with the same shape as ``data``, where sources are marked by different positive integer values. A value of zero is reserved for the background. See Also -------- :func:`photutils.segmentation.detect_sources` """ if not isinstance(segment_img, SegmentationImage): segment_img = SegmentationImage(segment_img) if segment_img.shape != data.shape: raise ValueError('The data and segmentation image must have ' 'the same shape') if labels is None: labels = segment_img.labels labels = np.atleast_1d(labels) segment_img.check_labels(labels) if filter_kernel is not None: data = _filter_data(data, filter_kernel, mode='constant', fill_value=0.0) last_label = segment_img.max_label segm_deblended = object.__new__(SegmentationImage) segm_deblended._data = np.copy(segment_img.data) for label in labels: source_slice = segment_img.slices[segment_img.get_index(label)] source_data = data[source_slice] source_segm = object.__new__(SegmentationImage) source_segm._data = np.copy(segment_img.data[source_slice]) source_segm.keep_labels(label) # include only one label source_deblended = _deblend_source( source_data, source_segm, npixels, nlevels=nlevels, contrast=contrast, mode=mode, connectivity=connectivity) if not np.array_equal(source_deblended.data.astype(bool), source_segm.data.astype(bool)): raise ValueError('Deblending failed for source "{0}". Please ' 'ensure you used the same pixel connectivity ' 'in detect_sources and deblend_sources. If ' 'this issue persists, then please inform the ' 'developers.'.format(label)) if source_deblended.nlabels > 1: source_deblended.relabel_consecutive(start_label=1) # replace the original source with the deblended source source_mask = (source_deblended.data > 0) segm_tmp = segm_deblended.data segm_tmp[source_slice][source_mask] = ( source_deblended.data[source_mask] + last_label) segm_deblended.__dict__ = {} # reset cached properties segm_deblended._data = segm_tmp last_label += source_deblended.nlabels if relabel: segm_deblended.relabel_consecutive() return segm_deblended def _deblend_source(data, segment_img, npixels, nlevels=32, contrast=0.001, mode='exponential', connectivity=8): """ Deblend a single labeled source. Parameters ---------- data : array_like The cutout data array for a single source. ``data`` should also already be smoothed by the same filter used in :func:`~photutils.segmentation.detect_sources`, if applicable. segment_img : `~photutils.segmentation.SegmentationImage` A cutout `~photutils.segmentation.SegmentationImage` object with the same shape as ``data``. ``segment_img`` should contain only *one* source label. npixels : int The number of connected pixels, each greater than ``threshold``, that an object must have to be detected. ``npixels`` must be a positive integer. nlevels : int, optional The number of multi-thresholding levels to use. Each source will be re-thresholded at ``nlevels`` levels spaced exponentially or linearly (see the ``mode`` keyword) between its minimum and maximum values within the source segment. contrast : float, optional The fraction of the total (blended) source flux that a local peak must have (at any one of the multi-thresholds) to be considered as a separate object. ``contrast`` must be between 0 and 1, inclusive. If ``contrast = 0`` then every local peak will be made a separate object (maximum deblending). If ``contrast = 1`` then no deblending will occur. The default is 0.001, which will deblend sources with a 7.5 magnitude difference. mode : {'exponential', 'linear'}, optional The mode used in defining the spacing between the multi-thresholding levels (see the ``nlevels`` keyword). The default is 'exponential'. connectivity : {8, 4}, optional The type of pixel connectivity used in determining how pixels are grouped into a detected source. The options are 8 (default) or 4. 8-connected pixels touch along their edges or corners. 4-connected pixels touch along their edges. For reference, SExtractor uses 8-connected pixels. Returns ------- segment_image : `~photutils.segmentation.SegmentationImage` A segmentation image, with the same shape as ``data``, where sources are marked by different positive integer values. A value of zero is reserved for the background. Note that the returned `SegmentationImage` may *not* have consecutive labels. """ from scipy.ndimage import label as ndilabel from skimage.morphology import watershed if nlevels < 1: raise ValueError('nlevels must be >= 1, got "{0}"'.format(nlevels)) if contrast < 0 or contrast > 1: raise ValueError('contrast must be >= 0 and <= 1, got ' '"{0}"'.format(contrast)) segm_mask = (segment_img.data > 0) source_values = data[segm_mask] source_sum = float(np.nansum(source_values)) source_min = np.nanmin(source_values) source_max = np.nanmax(source_values) if source_min == source_max: return segment_img # no deblending if mode == 'exponential' and source_min < 0: warnings.warn('Source "{0}" contains negative values, setting ' 'deblending mode to "linear"'.format( segment_img.labels[0]), AstropyUserWarning) mode = 'linear' steps = np.arange(1., nlevels + 1) if mode == 'exponential': if source_min == 0: source_min = source_max * 0.01 thresholds = source_min * ((source_max / source_min) ** (steps / (nlevels + 1))) elif mode == 'linear': thresholds = source_min + ((source_max - source_min) / (nlevels + 1)) * steps else: raise ValueError('"{0}" is an invalid mode; mode must be ' '"exponential" or "linear"'.format(mode)) # suppress NoDetectionsWarning during deblending warnings.filterwarnings('ignore', category=NoDetectionsWarning) mask = ~segm_mask segments = _detect_sources(data, thresholds, npixels=npixels, connectivity=connectivity, mask=mask, deblend_skip=True) selem = _make_binary_structure(data.ndim, connectivity) # define the sources (markers) for the watershed algorithm nsegments = len(segments) if nsegments == 0: # no deblending return segment_img else: for i in range(nsegments - 1): segm_lower = segments[i].data segm_upper = segments[i + 1].data relabel = False # if the are more sources at the upper level, then # remove the parent source(s) from the lower level, # but keep any sources in the lower level that do not have # multiple children in the upper level for label in segments[i].labels: mask = (segm_lower == label) # checks for 1-to-1 label mapping n -> m (where m >= 0) upper_labels = segm_upper[mask] upper_labels = np.unique(upper_labels[upper_labels != 0]) if upper_labels.size >= 2: relabel = True segm_lower[mask] = segm_upper[mask] if relabel: segm_new = object.__new__(SegmentationImage) segm_new._data = ndilabel(segm_lower, structure=selem)[0] segments[i + 1] = segm_new else: segments[i + 1] = segments[i] # Deblend using watershed. If any sources do not meet the # contrast criterion, then remove the faintest such source and # repeat until all sources meet the contrast criterion. markers = segments[-1].data mask = segment_img.data.astype(bool) remove_marker = True while remove_marker: markers = watershed(-data, markers, mask=mask, connectivity=selem) labels = np.unique(markers[markers != 0]) flux_frac = np.array([np.sum(data[markers == label]) for label in labels]) / source_sum remove_marker = any(flux_frac < contrast) if remove_marker: # remove only the faintest source (one at a time) # because several faint sources could combine to meet the # constrast criterion markers[markers == labels[np.argmin(flux_frac)]] = 0. segm_new = object.__new__(SegmentationImage) segm_new._data = markers return segm_new photutils-0.7.2/photutils/segmentation/detect.py0000644000214200020070000003636213572576136024341 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for detecting sources in an image. """ import warnings from astropy.convolution import Gaussian2DKernel from astropy.stats import gaussian_fwhm_to_sigma from astropy.utils.decorators import deprecated_renamed_argument import numpy as np from .core import SegmentationImage from ..detection import detect_threshold from ..utils.convolution import _filter_data from ..utils.exceptions import NoDetectionsWarning __all__ = ['detect_sources', 'make_source_mask'] def _make_binary_structure(ndim, connectivity): """ Make a binary structure element. Parameters ---------- ndim : int The number of array dimensions. connectivity : {4, 8} For the case of ``ndim=2``, the type of pixel connectivity used in determining how pixels are grouped into a detected source. The options are 4 or 8 (default). 4-connected pixels touch along their edges. 8-connected pixels touch along their edges or corners. For reference, SExtractor uses 8-connected pixels. Returns ------- array : ndarray of int or bool The binary structure element. If ``ndim <= 2`` an array of int is returned, otherwise an array of bool is returned. """ from scipy.ndimage import generate_binary_structure if ndim == 1: selem = np.array((1, 1, 1)) elif ndim == 2: if connectivity == 4: selem = np.array(((0, 1, 0), (1, 1, 1), (0, 1, 0))) elif connectivity == 8: selem = np.ones((3, 3), dtype=int) else: raise ValueError('Invalid connectivity={0}. ' 'Options are 4 or 8'.format(connectivity)) else: selem = generate_binary_structure(ndim, 1) return selem def _detect_sources(data, thresholds, npixels, filter_kernel=None, connectivity=8, mask=None, deblend_skip=False): """ Detect sources above a specified threshold value in an image and return a `~photutils.segmentation.SegmentationImage` object. Detected sources must have ``npixels`` connected pixels that are each greater than the ``threshold`` value. If the filtering option is used, then the ``threshold`` is applied to the filtered image. The input ``mask`` can be used to mask pixels in the input data. Masked pixels will not be included in any source. This function does not deblend overlapping sources. First use this function to detect sources followed by :func:`~photutils.segmentation.deblend_sources` to deblend sources. Parameters ---------- data : array_like The 2D array of the image. thresholds : array-like of floats or arrays The data value or pixel-wise data values to be used for the detection thresholds. A 2D ``threshold`` must have the same shape as ``data``. See `~photutils.detection.detect_threshold` for one way to create a ``threshold`` image. npixels : int The number of connected pixels, each greater than ``threshold``, that an object must have to be detected. ``npixels`` must be a positive integer. filter_kernel : array-like (2D) or `~astropy.convolution.Kernel2D`, optional The 2D array of the kernel used to filter the image before thresholding. Filtering the image will smooth the noise and maximize detectability of objects with a shape similar to the kernel. connectivity : {4, 8}, optional The type of pixel connectivity used in determining how pixels are grouped into a detected source. The options are 4 or 8 (default). 4-connected pixels touch along their edges. 8-connected pixels touch along their edges or corners. For reference, SExtractor uses 8-connected pixels. mask : array_like of bool, optional A boolean mask, with the same shape as the input ``data``, where `True` values indicate masked pixels. Masked pixels will not be included in any source. deblend_skip : bool, optional If `True` do not include the segmentation image in the output list for any threshold level where the number of detected sources is less than 2. This is useful for source deblending and improves its performance. Returns ------- segment_image : list of `~photutils.segmentation.SegmentationImage` A list of 2D segmentation images, with the same shape as ``data``, where sources are marked by different positive integer values. A value of zero is reserved for the background. If no sources are found for a given threshold, then the output list will contain `None` for that threshold. Also see the ``deblend_skip`` keyword. """ from scipy import ndimage if (npixels <= 0) or (int(npixels) != npixels): raise ValueError('npixels must be a positive integer, got ' '"{0}"'.format(npixels)) if mask is not None: if mask.shape != data.shape: raise ValueError('mask must have the same shape as the input ' 'image.') if filter_kernel is not None: data = _filter_data(data, filter_kernel, mode='constant', fill_value=0.0, check_normalization=True) # ignore RuntimeWarning caused by > comparison when data contains NaNs warnings.simplefilter('ignore', category=RuntimeWarning) selem = _make_binary_structure(data.ndim, connectivity) segms = [] for threshold in thresholds: data2 = data > threshold if mask is not None: data2 &= ~mask # return if threshold was too high to detect any sources if np.count_nonzero(data2) == 0: warnings.warn('No sources were found.', NoDetectionsWarning) if deblend_skip: continue else: segms.append(None) continue segm_img, _ = ndimage.label(data2, structure=selem) # remove objects with less than npixels # NOTE: for typical data, making the cutout images is ~10x faster # than using segm_img directly segm_slices = ndimage.find_objects(segm_img) for i, slices in enumerate(segm_slices): cutout = segm_img[slices] segment_mask = (cutout == (i+1)) if np.count_nonzero(segment_mask) < npixels: cutout[segment_mask] = 0 if np.count_nonzero(segm_img) == 0: warnings.warn('No sources were found.', NoDetectionsWarning) if deblend_skip: continue else: segms.append(None) continue segm = object.__new__(SegmentationImage) segm._data = segm_img if deblend_skip and segm.nlabels == 1: continue else: segm.relabel_consecutive() segms.append(segm) return segms def detect_sources(data, threshold, npixels, filter_kernel=None, connectivity=8, mask=None): """ Detect sources above a specified threshold value in an image and return a `~photutils.segmentation.SegmentationImage` object. Detected sources must have ``npixels`` connected pixels that are each greater than the ``threshold`` value. If the filtering option is used, then the ``threshold`` is applied to the filtered image. The input ``mask`` can be used to mask pixels in the input data. Masked pixels will not be included in any source. This function does not deblend overlapping sources. First use this function to detect sources followed by :func:`~photutils.segmentation.deblend_sources` to deblend sources. Parameters ---------- data : array_like The 2D array of the image. threshold : float or array-like The data value or pixel-wise data values to be used for the detection threshold. A 2D ``threshold`` must have the same shape as ``data``. See `~photutils.detection.detect_threshold` for one way to create a ``threshold`` image. npixels : int The number of connected pixels, each greater than ``threshold``, that an object must have to be detected. ``npixels`` must be a positive integer. filter_kernel : array-like (2D) or `~astropy.convolution.Kernel2D`, optional The 2D array of the kernel used to filter the image before thresholding. Filtering the image will smooth the noise and maximize detectability of objects with a shape similar to the kernel. connectivity : {4, 8}, optional The type of pixel connectivity used in determining how pixels are grouped into a detected source. The options are 4 or 8 (default). 4-connected pixels touch along their edges. 8-connected pixels touch along their edges or corners. For reference, SExtractor uses 8-connected pixels. mask : array_like of bool, optional A boolean mask, with the same shape as the input ``data``, where `True` values indicate masked pixels. Masked pixels will not be included in any source. Returns ------- segment_image : `~photutils.segmentation.SegmentationImage` or `None` A 2D segmentation image, with the same shape as ``data``, where sources are marked by different positive integer values. A value of zero is reserved for the background. If no sources are found then `None` is returned. See Also -------- :func:`photutils.detection.detect_threshold`, :class:`photutils.segmentation.SegmentationImage`, :func:`photutils.segmentation.source_properties` :func:`photutils.segmentation.deblend_sources` Examples -------- .. plot:: :include-source: # make a table of Gaussian sources from astropy.table import Table table = Table() table['amplitude'] = [50, 70, 150, 210] table['x_mean'] = [160, 25, 150, 90] table['y_mean'] = [70, 40, 25, 60] table['x_stddev'] = [15.2, 5.1, 3., 8.1] table['y_stddev'] = [2.6, 2.5, 3., 4.7] table['theta'] = np.array([145., 20., 0., 60.]) * np.pi / 180. # make an image of the sources with Gaussian noise from photutils.datasets import make_gaussian_sources_image from photutils.datasets import make_noise_image shape = (100, 200) sources = make_gaussian_sources_image(shape, table) noise = make_noise_image(shape, distribution='gaussian', mean=0., stddev=5., random_state=12345) image = sources + noise # detect the sources from photutils import detect_threshold, detect_sources threshold = detect_threshold(image, nsigma=3) from astropy.convolution import Gaussian2DKernel kernel_sigma = 3.0 / (2.0 * np.sqrt(2.0 * np.log(2.0))) # FWHM = 3 kernel = Gaussian2DKernel(kernel_sigma, x_size=3, y_size=3) kernel.normalize() segm = detect_sources(image, threshold, npixels=5, filter_kernel=kernel) # plot the image and the segmentation image import matplotlib.pyplot as plt fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 8)) ax1.imshow(image, origin='lower', interpolation='nearest') ax2.imshow(segm.data, origin='lower', interpolation='nearest') """ return _detect_sources(data, (threshold,), npixels, filter_kernel=filter_kernel, connectivity=connectivity, mask=mask)[0] @deprecated_renamed_argument('snr', 'nsigma', 0.7) @deprecated_renamed_argument('mask_value', None, 0.7) def make_source_mask(data, nsigma, npixels, mask=None, mask_value=None, filter_fwhm=None, filter_size=3, filter_kernel=None, sigclip_sigma=3.0, sigclip_iters=5, dilate_size=11): """ Make a source mask using source segmentation and binary dilation. Parameters ---------- data : array_like The 2D array of the image. nsigma : float The number of standard deviations per pixel above the ``background`` for which to consider a pixel as possibly being part of a source. npixels : int The number of connected pixels, each greater than ``threshold``, that an object must have to be detected. ``npixels`` must be a positive integer. mask : array_like, bool, optional A boolean mask with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Masked pixels are ignored when computing the image background statistics. mask_value : float, optional Deprecated. An image data value (e.g., ``0.0``) that is ignored when computing the image background statistics. ``mask_value`` will be ignored if ``mask`` is input. filter_fwhm : float, optional The full-width at half-maximum (FWHM) of the Gaussian kernel to filter the image before thresholding. ``filter_fwhm`` and ``filter_size`` are ignored if ``filter_kernel`` is defined. filter_size : float, optional The size of the square Gaussian kernel image. Used only if ``filter_fwhm`` is defined. ``filter_fwhm`` and ``filter_size`` are ignored if ``filter_kernel`` is defined. filter_kernel : array-like (2D) or `~astropy.convolution.Kernel2D`, optional The 2D array of the kernel used to filter the image before thresholding. Filtering the image will smooth the noise and maximize detectability of objects with a shape similar to the kernel. ``filter_kernel`` overrides ``filter_fwhm`` and ``filter_size``. sigclip_sigma : float, optional The number of standard deviations to use as the clipping limit when calculating the image background statistics. sigclip_iters : int, optional The number of iterations to perform sigma clipping, or `None` to clip until convergence is achieved (i.e., continue until the last iteration clips nothing) when calculating the image background statistics. dilate_size : int, optional The size of the square array used to dilate the segmentation image. Returns ------- mask : 2D bool `~numpy.ndarray` A 2D boolean image containing the source mask. """ from scipy import ndimage threshold = detect_threshold(data, nsigma, background=None, error=None, mask=mask, mask_value=None, sigclip_sigma=sigclip_sigma, sigclip_iters=sigclip_iters) kernel = None if filter_kernel is not None: kernel = filter_kernel if filter_fwhm is not None: kernel_sigma = filter_fwhm * gaussian_fwhm_to_sigma kernel = Gaussian2DKernel(kernel_sigma, x_size=filter_size, y_size=filter_size) if kernel is not None: kernel.normalize() segm = detect_sources(data, threshold, npixels, filter_kernel=kernel) if segm is None: return np.zeros(data.shape, dtype=bool) selem = np.ones((dilate_size, dilate_size)) return ndimage.binary_dilation(segm.data.astype(bool), selem) photutils-0.7.2/photutils/segmentation/properties.py0000644000214200020070000021130413572576136025254 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for calculating the properties of sources defined by a segmentation image. """ import warnings from astropy.coordinates import SkyCoord from astropy.table import QTable import astropy.units as u from astropy.utils import deprecated, lazyproperty from astropy.utils.exceptions import AstropyUserWarning import numpy as np from .core import SegmentationImage from ..aperture import BoundingBox from ..utils._moments import _moments, _moments_central from ..utils.convolution import _filter_data from ..utils._wcs_helpers import _pixel_to_world __all__ = ['SourceProperties', 'source_properties', 'SourceCatalog'] __doctest_requires__ = {('SourceProperties', 'SourceProperties.*', 'SourceCatalog', 'SourceCatalog.*', 'source_properties', 'properties_table'): ['scipy']} # default table columns for `to_table()` output DEFAULT_COLUMNS = ['id', 'xcentroid', 'ycentroid', 'sky_centroid', 'sky_centroid_icrs', 'source_sum', 'source_sum_err', 'background_sum', 'background_mean', 'background_at_centroid', 'bbox_xmin', 'bbox_xmax', 'bbox_ymin', 'bbox_ymax', 'min_value', 'max_value', 'minval_xpos', 'minval_ypos', 'maxval_xpos', 'maxval_ypos', 'area', 'equivalent_radius', 'perimeter', 'semimajor_axis_sigma', 'semiminor_axis_sigma', 'orientation', 'eccentricity', 'ellipticity', 'elongation', 'covar_sigx2', 'covar_sigxy', 'covar_sigy2', 'cxx', 'cxy', 'cyy', 'gini'] class SourceProperties: """ Class to calculate photometry and morphological properties of a single labeled source. Parameters ---------- data : array_like or `~astropy.units.Quantity` The 2D array from which to calculate the source photometry and properties. If ``filtered_data`` is input, then it will be used instead of ``data`` to calculate the source centroid and morphological properties. Source photometry is always measured from ``data``. For accurate source properties and photometry, ``data`` should be background-subtracted. Non-finite ``data`` values (NaN and +/- inf) are automatically masked. segment_img : `SegmentationImage` or array_like (int) A 2D segmentation image, either as a `SegmentationImage` object or an `~numpy.ndarray`, with the same shape as ``data`` where sources are labeled by different positive integer values. A value of zero is reserved for the background. label : int The label number of the source whose properties are calculated. filtered_data : array-like or `~astropy.units.Quantity`, optional The filtered version of the background-subtracted ``data`` from which to calculate the source centroid and morphological properties. The kernel used to perform the filtering should be the same one used in defining the source segments (e.g., see :func:`~photutils.segmentation.detect_sources`). If ``data`` is a `~astropy.units.Quantity` array then ``filtered_data`` must be a `~astropy.units.Quantity` array (and vise versa) with identical units. Non-finite ``filtered_data`` values (NaN and +/- inf) are not automatically masked, unless they are at the same position of non-finite values in the input ``data`` array. Such pixels can be masked using the ``mask`` keyword. If `None`, then the unfiltered ``data`` will be used instead. error : array_like or `~astropy.units.Quantity`, optional The total error array corresponding to the input ``data`` array. ``error`` is assumed to include *all* sources of error, including the Poisson error of the sources (see `~photutils.utils.calc_total_error`) . ``error`` must have the same shape as the input ``data``. If ``data`` is a `~astropy.units.Quantity` array then ``error`` must be a `~astropy.units.Quantity` array (and vise versa) with identical units. Non-finite ``error`` values (NaN and +/- inf) are not automatically masked, unless they are at the same position of non-finite values in the input ``data`` array. Such pixels can be masked using the ``mask`` keyword. See the Notes section below for details on the error propagation. mask : array_like (bool), optional A boolean mask with the same shape as ``data`` where a `True` value indicates the corresponding element of ``data`` is masked. Masked data are excluded from all calculations. Non-finite values (NaN and +/- inf) in the input ``data`` are automatically masked. background : float, array_like, or `~astropy.units.Quantity`, optional The background level that was *previously* present in the input ``data``. ``background`` may either be a scalar value or a 2D image with the same shape as the input ``data``. If ``data`` is a `~astropy.units.Quantity` array then ``background`` must be a `~astropy.units.Quantity` array (and vise versa) with identical units. Inputting the ``background`` merely allows for its properties to be measured within each source segment. The input ``background`` does *not* get subtracted from the input ``data``, which should already be background-subtracted. Non-finite ``background`` values (NaN and +/- inf) are not automatically masked, unless they are at the same position of non-finite values in the input ``data`` array. Such pixels can be masked using the ``mask`` keyword. wcs : WCS object or `None`, optional A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). If `None`, then all sky-based properties will be set to `None`. Notes ----- ``data`` (and optional ``filtered_data``) should be background-subtracted for accurate source photometry and properties. `SExtractor`_'s centroid and morphological parameters are always calculated from a filtered "detection" image, i.e. the image used to define the segmentation image. The usual downside of the filtering is the sources will be made more circular than they actually are. If you wish to reproduce `SExtractor`_ centroid and morphology results, then input a filtered and background-subtracted "detection" image into the ``filtered_data`` keyword. If ``filtered_data`` is `None`, then the unfiltered ``data`` will be used for the source centroid and morphological parameters. Negative data values (``filtered_data`` or ``data``) within the source segment are set to zero when calculating morphological properties based on image moments. Negative values could occur, for example, if the segmentation image was defined from a different image (e.g., different bandpass) or if the background was oversubtracted. Note that `~photutils.segmentation.SourceProperties.source_sum` always includes the contribution of negative ``data`` values. The input ``error`` array is assumed to include *all* sources of error, including the Poisson error of the sources. `~photutils.segmentation.SourceProperties.source_sum_err` is simply the quadrature sum of the pixel-wise total errors over the non-masked pixels within the source segment: .. math:: \\Delta F = \\sqrt{\\sum_{i \\in S} \\sigma_{\\mathrm{tot}, i}^2} where :math:`\\Delta F` is `~photutils.segmentation.SourceProperties.source_sum_err`, :math:`S` are the non-masked pixels in the source segment, and :math:`\\sigma_{\\mathrm{tot}, i}` is the input ``error`` array. Custom errors for source segments can be calculated using the `~photutils.segmentation.SourceProperties.error_cutout_ma` and `~photutils.segmentation.SourceProperties.background_cutout_ma` properties, which are 2D `~numpy.ma.MaskedArray` cutout versions of the input ``error`` and ``background``. The mask is `True` for pixels outside of the source segment, masked pixels from the ``mask`` input, or any non-finite ``data`` values (NaN and +/- inf). .. _SExtractor: https://www.astromatic.net/software/sextractor """ def __init__(self, data, segment_img, label, filtered_data=None, error=None, mask=None, background=None, wcs=None): if not isinstance(segment_img, SegmentationImage): segment_img = SegmentationImage(segment_img) if segment_img.shape != data.shape: raise ValueError('segment_img and data must have the same shape.') inputs = (data, filtered_data, error, background) has_unit = [hasattr(x, 'unit') for x in inputs if x is not None] use_units = all(has_unit) if any(has_unit) and not use_units: raise ValueError('If any of data, filtered_data, error, or ' 'background has units, then they all must have ' 'the same units.') if use_units: self._data_unit = data.unit else: self._data_unit = 1 if error is not None: error = np.asanyarray(error) if error.shape != data.shape: raise ValueError('error and data must have the same shape.') if use_units and error.unit != self._data_unit: raise ValueError('error and data must have the same units.') if mask is np.ma.nomask: mask = None if mask is not None: mask = np.asanyarray(mask) if mask.shape != data.shape: raise ValueError('mask and data must have the same shape.') if background is not None: background = np.atleast_1d(background) if len(background) == 1: background = np.zeros(data.shape) + background else: background = np.asanyarray(background) if background.shape != data.shape: raise ValueError('background and data must have the same ' 'shape.') if use_units and background.unit != self._data_unit: raise ValueError('background and data must have the same ' 'units.') if filtered_data is not None: filtered_data = np.asanyarray(filtered_data) if filtered_data.shape != data.shape: raise ValueError('filtered_data and data must have the same ' 'shape.') if use_units and filtered_data.unit != self._data_unit: raise ValueError('filtered_data and data must have the same ' 'units.') self._filtered_data = filtered_data else: self._filtered_data = data self._data = data self._segment_img = segment_img self._error = error self._mask = mask self._background = background # 2D array self._wcs = wcs segment_img.check_labels(label) self.label = label self.segment = segment_img[segment_img.get_index(label)] self.slices = self.segment.slices def __str__(self): cls_name = '<{0}.{1}>'.format(self.__class__.__module__, self.__class__.__name__) cls_info = [] params = ['label', 'sky_centroid'] for param in params: cls_info.append((param, getattr(self, param))) fmt = (['{0}: {1}'.format(key, val) for key, val in cls_info]) fmt.insert(1, 'centroid (x, y): ({0:0.4f}, {1:0.4f})' .format(self.xcentroid.value, self.ycentroid.value)) return '{}\n'.format(cls_name) + '\n'.join(fmt) def __repr__(self): return self.__str__() @lazyproperty def _segment_mask(self): """ Boolean mask for source segment. ``_segment_mask`` is `True` for all pixels outside of the source segment for this label. Pixels from other source segments within the rectangular cutout are `True`. """ return self._segment_img.data[self.slices] != self.label @lazyproperty def _input_mask(self): """ Boolean mask for the user-input mask. """ if self._mask is not None: return self._mask[self.slices] else: return None @lazyproperty def _data_mask(self): """ Boolean mask for non-finite (NaN and +/- inf) ``data`` values. """ return ~np.isfinite(self.data_cutout) @lazyproperty def _total_mask(self): """ Boolean mask representing the combination of the ``_segment_mask``, ``_input_mask``, and ``_data_mask``. This mask is applied to ``data``, ``error``, and ``background`` inputs when calculating properties. """ mask = self._segment_mask | self._data_mask if self._input_mask is not None: mask |= self._input_mask return mask @lazyproperty def _is_completely_masked(self): """ `True` if all pixels within the source segment are masked, otherwise `False`. """ return np.all(self._total_mask) @lazyproperty def _data_zeroed(self): """ A 2D `~numpy.ndarray` cutout from the input ``data`` where any masked pixels (``_segment_mask``, ``_input_mask``, or ``_data_mask``) are set to zero. Invalid values (NaN and +/- inf) are set to zero via the ``_data_mask``. Any units are dropped on the input ``data``. This is a 2D array representation (with zeros as placeholders for the masked/removed values) of the 1D ``_data_values`` property, which is used for ``source_sum``, ``area``, ``min_value``, ``max_value``, ``minval_pos``, ``maxval_pos``, etc. """ if isinstance(self.data_cutout, u.Quantity): cutout = self.data_cutout.value else: cutout = self.data_cutout # NOTE: using np.where is faster than # _data = np.copy(self.data_cutout) # self._data[self._total_mask] = 0. return np.where(self._total_mask, 0, cutout).astype(float) # copy @lazyproperty def _filtered_data_zeroed(self): """ A 2D `~numpy.ndarray` cutout from the input ``filtered_data`` (or ``data`` if ``filtered_data`` is `None`) where any masked pixels (``_segment_mask``, ``_input_mask``, or ``_data_mask``) are set to zero. Invalid values (NaN and +/- inf) are set to zero. Any units are dropped on the input ``filtered_data`` (or ``data``). Negative data values are also set to zero because negative pixels (especially at large radii) can result in image moments that result in negative variances. This array is used for moment-based properties. """ filt_data = self._filtered_data[self.slices] if isinstance(filt_data, u.Quantity): filt_data = filt_data.value filt_data = np.where(self._total_mask, 0., filt_data) # copy filt_data[filt_data < 0] = 0. return filt_data.astype(float) def make_cutout(self, data, masked_array=False): """ Create a (masked) cutout array from the input ``data`` using the minimal bounding box of the source segment. If ``masked_array`` is `False` (default), then the returned cutout array is simply a `~numpy.ndarray`. The returned cutout is a view (not a copy) of the input ``data``. No pixels are altered (e.g. set to zero) within the bounding box. If ``masked_array` is `True`, then the returned cutout array is a `~numpy.ma.MaskedArray`. The mask is `True` for pixels outside of the source segment (labeled region of interest), masked pixels from the ``mask`` input, or any non-finite ``data`` values (NaN and +/- inf). The data part of the masked array is a view (not a copy) of the input ``data``. Parameters ---------- data : array-like (2D) The data array from which to create the masked cutout array. ``data`` must have the same shape as the segmentation image input into `SourceProperties`. masked_array : bool, optional If `True` then a `~numpy.ma.MaskedArray` will be returned, where the mask is `True` for pixels outside of the source segment (labeled region of interest), masked pixels from the ``mask`` input, or any non-finite ``data`` values (NaN and +/- inf). If `False`, then a `~numpy.ndarray` will be returned. Returns ------- result : 2D `~numpy.ndarray` or `~numpy.ma.MaskedArray` The 2D cutout array. """ data = np.asanyarray(data) if data.shape != self._segment_img.shape: raise ValueError('data must have the same shape as the ' 'segmentation image input to SourceProperties') if masked_array: return np.ma.masked_array(data[self.slices], mask=self._total_mask) else: return data[self.slices] def to_table(self, columns=None, exclude_columns=None): """ Create a `~astropy.table.QTable` of properties. If ``columns`` or ``exclude_columns`` are not input, then the `~astropy.table.QTable` will include a default list of scalar-valued properties. Parameters ---------- columns : str or list of str, optional Names of columns, in order, to include in the output `~astropy.table.QTable`. The allowed column names are any of the attributes of `SourceProperties`. exclude_columns : str or list of str, optional Names of columns to exclude from the default columns in the output `~astropy.table.QTable`. The default columns are defined in the ``photutils.segmentation.properties.DEFAULT_COLUMNS`` variable. Returns ------- table : `~astropy.table.QTable` A single-row table of properties of the source. """ return _properties_table(self, columns=columns, exclude_columns=exclude_columns) @lazyproperty def data_cutout(self): """ A 2D `~numpy.ndarray` cutout from the data using the minimal bounding box of the source segment. """ return self._data[self.slices] @lazyproperty def data_cutout_ma(self): """ A 2D `~numpy.ma.MaskedArray` cutout from the ``data``. The mask is `True` for pixels outside of the source segment (labeled region of interest), masked pixels from the ``mask`` input, or any non-finite ``data`` values (NaN and +/- inf). """ return np.ma.masked_array(self._data[self.slices], mask=self._total_mask) @lazyproperty def filtered_data_cutout_ma(self): """ A 2D `~numpy.ma.MaskedArray` cutout from the ``filtered_data``. If ``filtered_data`` was not input, then the cutout will be from the input ``data``. The mask is `True` for pixels outside of the source segment (labeled region of interest), masked pixels from the ``mask`` input, or any non-finite ``data`` values (NaN and +/- inf). """ return np.ma.masked_array(self._filtered_data[self.slices], mask=self._total_mask) @lazyproperty def error_cutout_ma(self): """ A 2D `~numpy.ma.MaskedArray` cutout from the input ``error`` image. The mask is `True` for pixels outside of the source segment (labeled region of interest), masked pixels from the ``mask`` input, or any non-finite ``data`` values (NaN and +/- inf). If ``error`` is `None`, then ``error_cutout_ma`` is also `None`. """ if self._error is None: return None else: return np.ma.masked_array(self._error[self.slices], mask=self._total_mask) @lazyproperty def background_cutout_ma(self): """ A 2D `~numpy.ma.MaskedArray` cutout from the input ``background``. The mask is `True` for pixels outside of the source segment (labeled region of interest), masked pixels from the ``mask`` input, or any non-finite ``data`` values (NaN and +/- inf). If ``background`` is `None`, then ``background_cutout_ma`` is also `None`. """ if self._background is None: return None else: return np.ma.masked_array(self._background[self.slices], mask=self._total_mask) @lazyproperty @deprecated('0.7') def values(self): """ A 1D `~numpy.ndarray` of the unmasked ``data`` values within the source segment. Non-finite pixel values (NaN and +/- inf) are excluded (automatically masked). If all pixels are masked, ``values`` will be an empty array. """ return self._data_values # pragma: no cover @lazyproperty def _data_values(self): """ A 1D `~numpy.ndarray` of the unmasked ``data`` values within the source segment. Non-finite pixel values (NaN and +/- inf) are excluded (automatically masked) via the ``_data_mask``. If all pixels are masked, an empty array will be returned. This array is used for ``source_sum``, ``area``, ``min_value``, ``max_value``, ``minval_pos``, ``maxval_pos``, etc. """ return self.data_cutout_ma.compressed() @lazyproperty def _filtered_data_values(self): return self.filtered_data_cutout_ma.compressed() @lazyproperty def _error_values(self): return self.error_cutout_ma.compressed() @lazyproperty def _background_values(self): return self.background_cutout_ma.compressed() @lazyproperty def indices(self): """ A tuple of two `~numpy.ndarray` containing the ``y`` and ``x`` pixel indices, respectively, of unmasked pixels within the source segment. Non-finite ``data`` values (NaN and +/- inf) are excluded. If all ``data`` pixels are masked, a tuple of two empty arrays will be returned. """ yindices, xindices = np.nonzero(self.data_cutout_ma) return (yindices + self.slices[0].start, xindices + self.slices[1].start) @lazyproperty @deprecated('0.7', 'indices') def coords(self): """ A tuple of two `~numpy.ndarray` containing the ``y`` and ``x`` pixel indices, respectively, of unmasked pixels within the source segment. Non-finite ``data`` values (NaN and +/- inf) are excluded. If all ``data`` pixels are masked, a tuple of two empty arrays will be returned. """ return self.indices # pragma: no cover @lazyproperty def moments(self): """Spatial moments up to 3rd order of the source.""" return _moments(self._filtered_data_zeroed, order=3) @lazyproperty def moments_central(self): """ Central moments (translation invariant) of the source up to 3rd order. """ ycentroid, xcentroid = self.cutout_centroid.value return _moments_central(self._filtered_data_zeroed, center=(xcentroid, ycentroid), order=3) @lazyproperty def id(self): """ The source identification number corresponding to the object label in the segmentation image. """ return self.label @lazyproperty def cutout_centroid(self): """ The ``(y, x)`` coordinate, relative to the `data_cutout`, of the centroid within the source segment. """ moments = self.moments if moments[0, 0] != 0: ycentroid = moments[1, 0] / moments[0, 0] xcentroid = moments[0, 1] / moments[0, 0] return (ycentroid, xcentroid) * u.pix else: return (np.nan, np.nan) * u.pix @lazyproperty def centroid(self): """ The ``(y, x)`` coordinate of the centroid within the source segment. """ ycen, xcen = self.cutout_centroid.value return (ycen + self.slices[0].start, xcen + self.slices[1].start) * u.pix @lazyproperty def xcentroid(self): """ The ``x`` coordinate of the centroid within the source segment. """ return self.centroid[1] @lazyproperty def ycentroid(self): """ The ``y`` coordinate of the centroid within the source segment. """ return self.centroid[0] @lazyproperty def sky_centroid(self): """ The sky coordinates of the centroid within the source segment, returned as a `~astropy.coordinates.SkyCoord` object. The output coordinate frame is the same as the input WCS. """ return _pixel_to_world(self.xcentroid.value, self.ycentroid.value, self._wcs) @lazyproperty def sky_centroid_icrs(self): """ The sky coordinates, in the International Celestial Reference System (ICRS) frame, of the centroid within the source segment, returned as a `~astropy.coordinates.SkyCoord` object. """ if self._wcs is None: return None else: return self.sky_centroid.icrs @lazyproperty def bbox(self): """ The `~photutils.aperture.BoundingBox` of the minimal rectangular region containing the source segment. """ return BoundingBox(self.slices[1].start, self.slices[1].stop, self.slices[0].start, self.slices[0].stop) @lazyproperty def bbox_xmin(self): """ The minimum ``x`` pixel location within the minimal bounding box containing the source segment. """ return self.bbox.ixmin * u.pix @lazyproperty def bbox_xmax(self): """ The maximum ``x`` pixel location within the minimal bounding box containing the source segment. Note that this value is inclusive, unlike numpy slice indices. """ return (self.bbox.ixmax - 1) * u.pix @lazyproperty def bbox_ymin(self): """ The minimum ``y`` pixel location within the minimal bounding box containing the source segment. """ return self.bbox.iymin * u.pix @lazyproperty def bbox_ymax(self): """ The maximum ``y`` pixel location within the minimal bounding box containing the source segment. Note that this value is inclusive, unlike numpy slice indices. """ return (self.bbox.iymax - 1) * u.pix @lazyproperty @deprecated('0.7', 'bbox_xmin') def xmin(self): """ The minimum ``x`` pixel location within the minimal bounding box containing the source segment. """ return self.bbox_xmin # pragma: no cover @lazyproperty @deprecated('0.7', 'bbox_xmax') def xmax(self): """ The maximum ``x`` pixel location within the minimal bounding box containing the source segment. Note that this value is inclusive, unlike numpy slice indices. """ return self.bbox_xmax # pragma: no cover @lazyproperty @deprecated('0.7', 'bbox_ymin') def ymin(self): """ The minimum ``y`` pixel location within the minimal bounding box containing the source segment. """ return self.bbox_ymin # pragma: no cover @lazyproperty @deprecated('0.7', 'bbox_ymax') def ymax(self): """ The maximum``y`` pixel location within the minimal bounding box containing the source segment. Note that this value is inclusive, unlike numpy slice indices. """ return self.bbox_ymax # pragma: no cover @lazyproperty def sky_bbox_ll(self): """ The sky coordinates of the lower-left vertex of the minimal bounding box of the source segment, returned as a `~astropy.coordinates.SkyCoord` object. The bounding box encloses all of the source segment pixels in their entirety, thus the vertices are at the pixel *corners*. """ return _calc_sky_bbox_corner(self.bbox, 'll', self._wcs) @lazyproperty def sky_bbox_ul(self): """ The sky coordinates of the upper-left vertex of the minimal bounding box of the source segment, returned as a `~astropy.coordinates.SkyCoord` object. The bounding box encloses all of the source segment pixels in their entirety, thus the vertices are at the pixel *corners*. """ return _calc_sky_bbox_corner(self.bbox, 'ul', self._wcs) @lazyproperty def sky_bbox_lr(self): """ The sky coordinates of the lower-right vertex of the minimal bounding box of the source segment, returned as a `~astropy.coordinates.SkyCoord` object. The bounding box encloses all of the source segment pixels in their entirety, thus the vertices are at the pixel *corners*. """ return _calc_sky_bbox_corner(self.bbox, 'lr', self._wcs) @lazyproperty def sky_bbox_ur(self): """ The sky coordinates of the upper-right vertex of the minimal bounding box of the source segment, returned as a `~astropy.coordinates.SkyCoord` object. The bounding box encloses all of the source segment pixels in their entirety, thus the vertices are at the pixel *corners*. """ return _calc_sky_bbox_corner(self.bbox, 'ur', self._wcs) @lazyproperty def min_value(self): """ The minimum pixel value of the ``data`` within the source segment. """ if self._is_completely_masked: return np.nan * self._data_unit else: return np.min(self._data_values) @lazyproperty def max_value(self): """ The maximum pixel value of the ``data`` within the source segment. """ if self._is_completely_masked: return np.nan * self._data_unit else: return np.max(self._data_values) @lazyproperty def minval_cutout_pos(self): """ The ``(y, x)`` coordinate, relative to the `data_cutout`, of the minimum pixel value of the ``data`` within the source segment. If there are multiple occurrences of the minimum value, only the first occurence is returned. """ if self._is_completely_masked: return (np.nan, np.nan) * u.pix else: arr = self.data_cutout_ma # multiplying by unit converts int to float, but keep as # float in case the array contains a NaN return np.asarray(np.unravel_index(np.argmin(arr), arr.shape)) * u.pix @lazyproperty def maxval_cutout_pos(self): """ The ``(y, x)`` coordinate, relative to the `data_cutout`, of the maximum pixel value of the ``data`` within the source segment. If there are multiple occurrences of the maximum value, only the first occurence is returned. """ if self._is_completely_masked: return (np.nan, np.nan) * u.pix else: arr = self.data_cutout_ma # multiplying by unit converts int to float, but keep as # float in case the array contains a NaN return np.asarray(np.unravel_index(np.argmax(arr), arr.shape)) * u.pix @lazyproperty def minval_pos(self): """ The ``(y, x)`` coordinate of the minimum pixel value of the ``data`` within the source segment. If there are multiple occurrences of the minimum value, only the first occurence is returned. """ if self._is_completely_masked: return (np.nan, np.nan) * u.pix else: yposition, xposition = self.minval_cutout_pos.value return (yposition + self.slices[0].start, xposition + self.slices[1].start) * u.pix @lazyproperty def maxval_pos(self): """ The ``(y, x)`` coordinate of the maximum pixel value of the ``data`` within the source segment. If there are multiple occurrences of the maximum value, only the first occurence is returned. """ if self._is_completely_masked: return (np.nan, np.nan) * u.pix else: yposition, xposition = self.maxval_cutout_pos.value return (yposition + self.slices[0].start, xposition + self.slices[1].start) * u.pix @lazyproperty def minval_xpos(self): """ The ``x`` coordinate of the minimum pixel value of the ``data`` within the source segment. If there are multiple occurrences of the minimum value, only the first occurence is returned. """ return self.minval_pos[1] @lazyproperty def minval_ypos(self): """ The ``y`` coordinate of the minimum pixel value of the ``data`` within the source segment. If there are multiple occurrences of the minimum value, only the first occurence is returned. """ return self.minval_pos[0] @lazyproperty def maxval_xpos(self): """ The ``x`` coordinate of the maximum pixel value of the ``data`` within the source segment. If there are multiple occurrences of the maximum value, only the first occurence is returned. """ return self.maxval_pos[1] @lazyproperty def maxval_ypos(self): """ The ``y`` coordinate of the maximum pixel value of the ``data`` within the source segment. If there are multiple occurrences of the maximum value, only the first occurence is returned. """ return self.maxval_pos[0] @lazyproperty def source_sum(self): """ The sum of the unmasked ``data`` values within the source segment. .. math:: F = \\sum_{i \\in S} (I_i - B_i) where :math:`F` is ``source_sum``, :math:`(I_i - B_i)` is the ``data``, and :math:`S` are the unmasked pixels in the source segment. Non-finite pixel values (NaN and +/- inf) are excluded (automatically masked). """ if self._is_completely_masked: return np.nan * self._data_unit # table output needs unit else: return np.sum(self._data_values) @lazyproperty def source_sum_err(self): """ The uncertainty of `~photutils.segmentation.SourceProperties.source_sum`, propagated from the input ``error`` array. ``source_sum_err`` is the quadrature sum of the total errors over the non-masked pixels within the source segment: .. math:: \\Delta F = \\sqrt{\\sum_{i \\in S} \\sigma_{\\mathrm{tot}, i}^2} where :math:`\\Delta F` is ``source_sum_err``, :math:`\\sigma_{\\mathrm{tot, i}}` are the pixel-wise total errors, and :math:`S` are the non-masked pixels in the source segment. Pixel values that are masked in the input ``data``, including any non-finite pixel values (NaN and +/- inf) that are automatically masked, are also masked in the error array. """ if self._error is not None: if self._is_completely_masked: return np.nan * self._data_unit # table output needs unit else: return np.sqrt(np.sum(self._error_values ** 2)) else: return None @lazyproperty def background_sum(self): """ The sum of ``background`` values within the source segment. Pixel values that are masked in the input ``data``, including any non-finite pixel values (NaN and +/- inf) that are automatically masked, are also masked in the background array. """ if self._background is not None: if self._is_completely_masked: return np.nan * self._data_unit # unit for table else: return np.sum(self._background_values) else: return None @lazyproperty def background_mean(self): """ The mean of ``background`` values within the source segment. Pixel values that are masked in the input ``data``, including any non-finite pixel values (NaN and +/- inf) that are automatically masked, are also masked in the background array. """ if self._background is not None: if self._is_completely_masked: return np.nan * self._data_unit # unit for table else: return np.mean(self._background_values) else: return None @lazyproperty def background_at_centroid(self): """ The value of the ``background`` at the position of the source centroid. The background value at fractional position values are determined using bilinear interpolation. """ if self._background is not None: from scipy.ndimage import map_coordinates # centroid can be NaN if segment is completely masked or if # all data values are <= 0 if np.any(~np.isfinite(self.centroid)): return np.nan * self._data_unit # unit for table else: value = map_coordinates(self._background, [[self.ycentroid.value], [self.xcentroid.value]], order=1, mode='nearest')[0] return value * self._data_unit else: return None @lazyproperty def area(self): """ The total unmasked area of the source segment in units of pixels**2. Note that the source area may be smaller than its segment area if a mask is input to `SourceProperties` or `source_properties`, or if the ``data`` within the segment contains invalid values (NaN and +/- inf). """ if self._is_completely_masked: return np.nan * u.pix**2 else: return len(self._data_values) * u.pix**2 @lazyproperty def equivalent_radius(self): """ The radius of a circle with the same `area` as the source segment. """ return np.sqrt(self.area / np.pi) @lazyproperty def perimeter(self): """ The perimeter of the source segment, approximated as the total length of lines connecting the centers of the border pixels defined by a 4-pixel connectivity. If any masked pixels make holes within the source segment, then the perimeter around the inner hole (e.g. an annulus) will also contribute to the total perimeter. References ---------- .. [1] K. Benkrid, D. Crookes, and A. Benkrid. "Design and FPGA Implementation of a Perimeter Estimator". Proceedings of the Irish Machine Vision and Image Processing Conference, pp. 51-57 (2000). http://www.cs.qub.ac.uk/~d.crookes/webpubs/papers/perimeter.doc """ if self._is_completely_masked: return np.nan * u.pix # unit for table else: from scipy.ndimage import binary_erosion, convolve data = ~self._total_mask selem = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]]) data_eroded = binary_erosion(data, selem, border_value=0) border = np.logical_xor(data, data_eroded).astype(int) kernel = np.array([[10, 2, 10], [2, 1, 2], [10, 2, 10]]) perimeter_data = convolve(border, kernel, mode='constant', cval=0) size = 34 perimeter_hist = np.bincount(perimeter_data.ravel(), minlength=size) weights = np.zeros(size, dtype=float) weights[[5, 7, 15, 17, 25, 27]] = 1. weights[[21, 33]] = np.sqrt(2.) weights[[13, 23]] = (1 + np.sqrt(2.)) / 2. return (perimeter_hist[0:size] @ weights) * u.pix @lazyproperty def inertia_tensor(self): """ The inertia tensor of the source for the rotation around its center of mass. """ moments = self.moments_central mu_02 = moments[0, 2] mu_11 = -moments[1, 1] mu_20 = moments[2, 0] return np.array([[mu_02, mu_11], [mu_11, mu_20]]) * u.pix**2 @lazyproperty def covariance(self): """ The covariance matrix of the 2D Gaussian function that has the same second-order moments as the source. """ moments = self.moments_central if moments[0, 0] != 0: mu_norm = moments / moments[0, 0] covariance = self._check_covariance( np.array([[mu_norm[0, 2], mu_norm[1, 1]], [mu_norm[1, 1], mu_norm[2, 0]]])) return covariance * u.pix**2 else: return np.empty((2, 2)) * np.nan * u.pix**2 @staticmethod def _check_covariance(covariance): """ Check and modify the covariance matrix in the case of "infinitely" thin detections. This follows SExtractor's prescription of incrementally increasing the diagonal elements by 1/12. """ increment = 1. / 12 # arbitrary SExtractor value value = (covariance[0, 0] * covariance[1, 1]) - covariance[0, 1]**2 if value >= increment**2: return covariance else: covar = np.copy(covariance) while value < increment**2: covar[0, 0] += increment covar[1, 1] += increment value = (covar[0, 0] * covar[1, 1]) - covar[0, 1]**2 return covar @lazyproperty def covariance_eigvals(self): """ The two eigenvalues of the `covariance` matrix in decreasing order. """ unit = u.pix**2 # eigvals unit if np.any(~np.isfinite(self.covariance.value)): return (np.nan, np.nan) * unit else: eigvals = np.linalg.eigvals(self.covariance.value) if np.any(eigvals < 0): # negative variance return (np.nan, np.nan) * unit # pragma: no cover return (np.max(eigvals), np.min(eigvals)) * unit @lazyproperty def semimajor_axis_sigma(self): """ The 1-sigma standard deviation along the semimajor axis of the 2D Gaussian function that has the same second-order central moments as the source. """ # this matches SExtractor's A parameter return np.sqrt(self.covariance_eigvals[0]) @lazyproperty def semiminor_axis_sigma(self): """ The 1-sigma standard deviation along the semiminor axis of the 2D Gaussian function that has the same second-order central moments as the source. """ # this matches SExtractor's B parameter return np.sqrt(self.covariance_eigvals[1]) @lazyproperty def eccentricity(self): """ The eccentricity of the 2D Gaussian function that has the same second-order moments as the source. The eccentricity is the fraction of the distance along the semimajor axis at which the focus lies. .. math:: e = \\sqrt{1 - \\frac{b^2}{a^2}} where :math:`a` and :math:`b` are the lengths of the semimajor and semiminor axes, respectively. """ semimajor_var, semiminor_var = self.covariance_eigvals if semimajor_var == 0: return 0. # pragma: no cover return np.sqrt(1. - (semiminor_var / semimajor_var)) @lazyproperty def orientation(self): """ The angle in radians between the ``x`` axis and the major axis of the 2D Gaussian function that has the same second-order moments as the source. The angle increases in the counter-clockwise direction. """ covar_00, covar_01, _, covar_11 = self.covariance.flat if covar_00 < 0 or covar_11 < 0: # negative variance return np.nan * u.deg # pragma: no cover # Quantity output in radians because inputs are Quantities orient_radians = 0.5 * np.arctan2(2. * covar_01, (covar_00 - covar_11)) return orient_radians.to(u.deg) @lazyproperty def elongation(self): """ The ratio of the lengths of the semimajor and semiminor axes: .. math:: \\mathrm{elongation} = \\frac{a}{b} where :math:`a` and :math:`b` are the lengths of the semimajor and semiminor axes, respectively. Note that this is the same as `SExtractor`_'s elongation parameter. """ return self.semimajor_axis_sigma / self.semiminor_axis_sigma @lazyproperty def ellipticity(self): """ ``1`` minus the ratio of the lengths of the semimajor and semiminor axes (or ``1`` minus the `elongation`): .. math:: \\mathrm{ellipticity} = 1 - \\frac{b}{a} where :math:`a` and :math:`b` are the lengths of the semimajor and semiminor axes, respectively. Note that this is the same as `SExtractor`_'s ellipticity parameter. """ return 1.0 - (self.semiminor_axis_sigma / self.semimajor_axis_sigma) @lazyproperty def covar_sigx2(self): """ The ``(0, 0)`` element of the `covariance` matrix, representing :math:`\\sigma_x^2`, in units of pixel**2. Note that this is the same as `SExtractor`_'s X2 parameter. """ return self.covariance[0, 0] @lazyproperty def covar_sigy2(self): """ The ``(1, 1)`` element of the `covariance` matrix, representing :math:`\\sigma_y^2`, in units of pixel**2. Note that this is the same as `SExtractor`_'s Y2 parameter. """ return self.covariance[1, 1] @lazyproperty def covar_sigxy(self): """ The ``(0, 1)`` and ``(1, 0)`` elements of the `covariance` matrix, representing :math:`\\sigma_x \\sigma_y`, in units of pixel**2. Note that this is the same as `SExtractor`_'s XY parameter. """ return self.covariance[0, 1] @lazyproperty def cxx(self): """ `SExtractor`_'s CXX ellipse parameter in units of pixel**(-2). The ellipse is defined as .. math:: cxx (x - \\bar{x})^2 + cxy (x - \\bar{x}) (y - \\bar{y}) + cyy (y - \\bar{y})^2 = R^2 where :math:`R` is a parameter which scales the ellipse (in units of the axes lengths). `SExtractor`_ reports that the isophotal limit of a source is well represented by :math:`R \\approx 3`. """ return ((np.cos(self.orientation) / self.semimajor_axis_sigma)**2 + (np.sin(self.orientation) / self.semiminor_axis_sigma)**2) @lazyproperty def cyy(self): """ `SExtractor`_'s CYY ellipse parameter in units of pixel**(-2). The ellipse is defined as .. math:: cxx (x - \\bar{x})^2 + cxy (x - \\bar{x}) (y - \\bar{y}) + cyy (y - \\bar{y})^2 = R^2 where :math:`R` is a parameter which scales the ellipse (in units of the axes lengths). `SExtractor`_ reports that the isophotal limit of a source is well represented by :math:`R \\approx 3`. """ return ((np.sin(self.orientation) / self.semimajor_axis_sigma)**2 + (np.cos(self.orientation) / self.semiminor_axis_sigma)**2) @lazyproperty def cxy(self): """ `SExtractor`_'s CXY ellipse parameter in units of pixel**(-2). The ellipse is defined as .. math:: cxx (x - \\bar{x})^2 + cxy (x - \\bar{x}) (y - \\bar{y}) + cyy (y - \\bar{y})^2 = R^2 where :math:`R` is a parameter which scales the ellipse (in units of the axes lengths). `SExtractor`_ reports that the isophotal limit of a source is well represented by :math:`R \\approx 3`. """ return (2. * np.cos(self.orientation) * np.sin(self.orientation) * ((1. / self.semimajor_axis_sigma**2) - (1. / self.semiminor_axis_sigma**2))) @lazyproperty def gini(self): """ The `Gini coefficient `_ of the source. The Gini coefficient is calculated using the prescription from `Lotz et al. 2004 `_ as: .. math:: G = \\frac{1}{\\left | \\bar{x} \\right | n (n - 1)} \\sum^{n}_{i} (2i - n - 1) \\left | x_i \\right | where :math:`\\bar{x}` is the mean over all pixel values :math:`x_i`. The Gini coefficient is a way of measuring the inequality in a given set of values. In the context of galaxy morphology, it measures how the light of a galaxy image is distributed among its pixels. A Gini coefficient value of 0 corresponds to a galaxy image with the light evenly distributed over all pixels while a Gini coefficient value of 1 represents a galaxy image with all its light concentrated in just one pixel. """ npix = np.size(self._data_values) normalization = (np.abs(np.mean(self._data_values)) * npix * (npix - 1)) kernel = ((2. * np.arange(1, npix + 1) - npix - 1) * np.abs(np.sort(self._data_values))) return np.sum(kernel) / normalization def source_properties(data, segment_img, error=None, mask=None, background=None, filter_kernel=None, wcs=None, labels=None): """ Calculate photometry and morphological properties of sources defined by a labeled segmentation image. Parameters ---------- data : array_like or `~astropy.units.Quantity` The 2D array from which to calculate the source photometry and properties. ``data`` should be background-subtracted. Non-finite ``data`` values (NaN and +/- inf) are automatically masked. segment_img : `SegmentationImage` or array_like (int) A 2D segmentation image, either as a `SegmentationImage` object or an `~numpy.ndarray`, with the same shape as ``data`` where sources are labeled by different positive integer values. A value of zero is reserved for the background. error : array_like or `~astropy.units.Quantity`, optional The total error array corresponding to the input ``data`` array. ``error`` is assumed to include *all* sources of error, including the Poisson error of the sources (see `~photutils.utils.calc_total_error`) . ``error`` must have the same shape as the input ``data``. Non-finite ``error`` values (NaN and +/- inf) are not automatically masked, unless they are at the same position of non-finite values in the input ``data`` array. Such pixels can be masked using the ``mask`` keyword. See the Notes section below for details on the error propagation. mask : array_like (bool), optional A boolean mask with the same shape as ``data`` where a `True` value indicates the corresponding element of ``data`` is masked. Masked data are excluded from all calculations. Non-finite values (NaN and +/- inf) in the input ``data`` are automatically masked. background : float, array_like, or `~astropy.units.Quantity`, optional The background level that was *previously* present in the input ``data``. ``background`` may either be a scalar value or a 2D image with the same shape as the input ``data``. Inputting the ``background`` merely allows for its properties to be measured within each source segment. The input ``background`` does *not* get subtracted from the input ``data``, which should already be background-subtracted. Non-finite ``background`` values (NaN and +/- inf) are not automatically masked, unless they are at the same position of non-finite values in the input ``data`` array. Such pixels can be masked using the ``mask`` keyword. filter_kernel : array-like (2D) or `~astropy.convolution.Kernel2D`, optional The 2D array of the kernel used to filter the data prior to calculating the source centroid and morphological parameters. The kernel should be the same one used in defining the source segments, i.e. the detection image (e.g., see :func:`~photutils.segmentation.detect_sources`). If `None`, then the unfiltered ``data`` will be used instead. wcs : `None` or WCS object, optional A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). If `None`, then all sky-based properties will be set to `None`. labels : int, array-like (1D, int) The segmentation labels for which to calculate source properties. If `None` (default), then the properties will be calculated for all labeled sources. Returns ------- output : `SourceCatalog` instance A `SourceCatalog` instance containing the properties of each source. Notes ----- `SExtractor`_'s centroid and morphological parameters are always calculated from a filtered "detection" image, i.e. the image used to define the segmentation image. The usual downside of the filtering is the sources will be made more circular than they actually are. If you wish to reproduce `SExtractor`_ centroid and morphology results, then input a filtered and background-subtracted "detection" image into the ``filtered_data`` keyword. If ``filtered_data`` is `None`, then the unfiltered ``data`` will be used for the source centroid and morphological parameters. Negative data values (``filtered_data`` or ``data``) within the source segment are set to zero when calculating morphological properties based on image moments. Negative values could occur, for example, if the segmentation image was defined from a different image (e.g., different bandpass) or if the background was oversubtracted. Note that `~photutils.segmentation.SourceProperties.source_sum` always includes the contribution of negative ``data`` values. The input ``error`` is assumed to include *all* sources of error, including the Poisson error of the sources. `~photutils.segmentation.SourceProperties.source_sum_err` is simply the quadrature sum of the pixel-wise total errors over the non-masked pixels within the source segment: .. math:: \\Delta F = \\sqrt{\\sum_{i \\in S} \\sigma_{\\mathrm{tot}, i}^2} where :math:`\\Delta F` is `~photutils.segmentation.SourceProperties.source_sum_err`, :math:`S` are the non-masked pixels in the source segment, and :math:`\\sigma_{\\mathrm{tot}, i}` is the input ``error`` array. .. _SExtractor: https://www.astromatic.net/software/sextractor See Also -------- SegmentationImage, SourceProperties, detect_sources Examples -------- >>> import numpy as np >>> from photutils import SegmentationImage, source_properties >>> image = np.arange(16.).reshape(4, 4) >>> print(image) # doctest: +SKIP [[ 0. 1. 2. 3.] [ 4. 5. 6. 7.] [ 8. 9. 10. 11.] [12. 13. 14. 15.]] >>> segm = SegmentationImage([[1, 1, 0, 0], ... [1, 0, 0, 2], ... [0, 0, 2, 2], ... [0, 2, 2, 0]]) >>> props = source_properties(image, segm) Print some properties of the first object (labeled with ``1`` in the segmentation image): >>> props[0].id # id corresponds to segment label number 1 >>> props[0].centroid # doctest: +FLOAT_CMP >>> props[0].source_sum # doctest: +FLOAT_CMP 5.0 >>> props[0].area # doctest: +FLOAT_CMP >>> props[0].max_value # doctest: +FLOAT_CMP 4.0 Print some properties of the second object (labeled with ``2`` in the segmentation image): >>> props[1].id # id corresponds to segment label number 2 >>> props[1].centroid # doctest: +FLOAT_CMP >>> props[1].perimeter # doctest: +FLOAT_CMP >>> props[1].orientation # doctest: +FLOAT_CMP """ if not isinstance(segment_img, SegmentationImage): segment_img = SegmentationImage(segment_img) if segment_img.shape != data.shape: raise ValueError('segment_img and data must have the same shape.') # filter the data once, instead of repeating for each source if filter_kernel is not None: filtered_data = _filter_data(data, filter_kernel, mode='constant', fill_value=0.0, check_normalization=True) else: filtered_data = None if labels is None: labels = segment_img.labels labels = np.atleast_1d(labels) sources_props = [] for label in labels: if label not in segment_img.labels: warnings.warn('label {} is not in the segmentation image.' .format(label), AstropyUserWarning) continue # skip invalid labels sources_props.append(SourceProperties( data, segment_img, label, filtered_data=filtered_data, error=error, mask=mask, background=background, wcs=wcs)) if not sources_props: raise ValueError('No sources are defined.') return SourceCatalog(sources_props, wcs=wcs) class SourceCatalog: """ Class to hold source catalogs. """ def __init__(self, properties_list, wcs=None): if isinstance(properties_list, SourceProperties): self._data = [properties_list] elif isinstance(properties_list, list): if not properties_list: raise ValueError('properties_list must not be an empty list.') self._data = properties_list else: raise ValueError('invalid input.') self.wcs = wcs self._cache = {} def __len__(self): return len(self._data) def __getitem__(self, index): return self._data[index] def __delitem__(self, index): del self._data[index] def __iter__(self): for i in self._data: yield i def __str__(self): cls_name = '<{0}.{1}>'.format(self.__class__.__module__, self.__class__.__name__) fmt = ['Catalog length: {0}'.format(len(self))] return '{}\n'.format(cls_name) + '\n'.join(fmt) def __repr__(self): return self.__str__() def __getattr__(self, attr): if attr not in self._cache: values = [getattr(p, attr) for p in self._data] if isinstance(values[0], u.Quantity): # turn list of Quantities into a Quantity array values = u.Quantity(values) if isinstance(values[0], SkyCoord): # pragma: no cover # failsafe: turn list of SkyCoord into a SkyCoord array values = SkyCoord(values) self._cache[attr] = values return self._cache[attr] @lazyproperty def _none_list(self): """ Return a list of `None` values, used by SkyCoord properties if ``wcs`` is `None`. """ return [None] * len(self._data) @lazyproperty def background_at_centroid(self): background = self._data[0]._background if background is None: return self._none_list else: from scipy.ndimage import map_coordinates values = map_coordinates(background, [[self.ycentroid.value], [self.xcentroid.value]], order=1, mode='nearest')[0] mask = np.isfinite(self.xcentroid) & np.isfinite(self.ycentroid) values[~mask] = np.nan return values * self._data[0]._data_unit @lazyproperty def sky_centroid(self): if self.wcs is None: return self._none_list else: # For a large catalog, it's much faster to calculate world # coordinates using the complete list of (x, y) instead of # looping through the individual (x, y). It's also much # faster to recalculate the world coordinates than to create a # SkyCoord array from a loop-generated SkyCoord list. The # assumption here is that the wcs is the same for each # SourceProperties instance. return _pixel_to_world(self.xcentroid, self.ycentroid, self.wcs) @lazyproperty def sky_centroid_icrs(self): if self.wcs is None: return self._none_list else: return self.sky_centroid.icrs @lazyproperty def sky_bbox_ll(self): if self.wcs is None: return self._none_list else: return _calc_sky_bbox_corner(self.bbox, 'll', self.wcs) @lazyproperty def sky_bbox_ul(self): if self.wcs is None: return self._none_list else: return _calc_sky_bbox_corner(self.bbox, 'ul', self.wcs) @lazyproperty def sky_bbox_lr(self): if self.wcs is None: return self._none_list else: return _calc_sky_bbox_corner(self.bbox, 'lr', self.wcs) @lazyproperty def sky_bbox_ur(self): if self.wcs is None: return self._none_list else: return _calc_sky_bbox_corner(self.bbox, 'ur', self.wcs) def to_table(self, columns=None, exclude_columns=None): """ Construct a `~astropy.table.QTable` of source properties from a `SourceCatalog` object. If ``columns`` or ``exclude_columns`` are not input, then the `~astropy.table.QTable` will include a default list of scalar-valued properties. Multi-dimensional properties, e.g. `~photutils.segmentation.SourceProperties.data_cutout`, can be included in the ``columns`` input, but they will not be preserved when writing the table to a file. This is a limitation of multi-dimensional columns in astropy tables. Parameters ---------- columns : str or list of str, optional Names of columns, in order, to include in the output `~astropy.table.QTable`. The allowed column names are any of the attributes of `SourceProperties`. exclude_columns : str or list of str, optional Names of columns to exclude from the default columns in the output `~astropy.table.QTable`. The default columns are defined in the ``photutils.segmentation.properties.DEFAULT_COLUMNS`` variable. Returns ------- table : `~astropy.table.QTable` A table of source properties with one row per source. See Also -------- SegmentationImage, SourceProperties, source_properties, detect_sources Examples -------- >>> import numpy as np >>> from photutils import source_properties >>> image = np.arange(16.).reshape(4, 4) >>> print(image) # doctest: +SKIP [[ 0. 1. 2. 3.] [ 4. 5. 6. 7.] [ 8. 9. 10. 11.] [12. 13. 14. 15.]] >>> segm = SegmentationImage([[1, 1, 0, 0], ... [1, 0, 0, 2], ... [0, 0, 2, 2], ... [0, 2, 2, 0]]) >>> cat = source_properties(image, segm) >>> columns = ['id', 'xcentroid', 'ycentroid', 'source_sum'] >>> tbl = cat.to_table(columns=columns) >>> tbl['xcentroid'].info.format = '.10f' # optional format >>> tbl['ycentroid'].info.format = '.10f' # optional format >>> print(tbl) id xcentroid ycentroid source_sum pix pix --- ------------ ------------ ---------- 1 0.2000000000 0.8000000000 5.0 2 2.0909090909 2.3636363636 55.0 """ return _properties_table(self, columns=columns, exclude_columns=exclude_columns) def _properties_table(obj, columns=None, exclude_columns=None): """ Construct a `~astropy.table.QTable` of source properties from a `SourceProperties` or `SourceCatalog` object. Parameters ---------- obj : `SourceProperties` or `SourceCatalog` instance The object containing the source properties. columns : str or list of str, optional Names of columns, in order, to include in the output `~astropy.table.QTable`. The allowed column names are any of the attributes of `SourceProperties`. exclude_columns : str or list of str, optional Names of columns to exclude from the default columns in the output `~astropy.table.QTable`. The default columns are defined in the ``photutils.segmentation.properties.DEFAULT_COLUMNS`` variable. Returns ------- table : `~astropy.table.QTable` A table of source properties with one row per source. """ # start with the default columns columns_all = DEFAULT_COLUMNS table_columns = None if exclude_columns is not None: table_columns = [s for s in columns_all if s not in exclude_columns] if columns is not None: table_columns = np.atleast_1d(columns) if table_columns is None: table_columns = columns_all tbl = QTable() for column in table_columns: values = getattr(obj, column) if isinstance(obj, SourceProperties): # turn scalar values into length-1 arrays because QTable # column assignment requires an object with a length values = np.atleast_1d(values) # Unfortunately np.atleast_1d creates an array of SkyCoord # instead of a SkyCoord array (Quantity does work correctly # with np.atleast_1d). Here we make a SkyCoord array for # the output table column. if isinstance(values[0], SkyCoord): values = SkyCoord(values) # length-1 SkyCoord array tbl[column] = values return tbl def _calc_sky_bbox_corner(bbox, corner, wcs): """ Calculate the sky coordinates at the corner of a minimal bounding box. The bounding box encloses all of the source segment pixels in their entirety, thus the vertices are at the pixel *corners*. Parameters ---------- bbox : `~photutils.aperture.BoundingBox` The source bounding box. corner : {'ll', 'ul', 'lr', 'ur'} The desired bounding box corner: * 'll': lower left * 'ul': upper left * 'lr': lower right * 'ur': upper right wcs : `None` or WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- skycoord : `~astropy.coordinates.SkyCoord` or `None` The sky coordinate at the bounding box corner. If ``wcs`` is `None`, then `None` will be returned. """ if corner == 'll': xpos = bbox.ixmin - 0.5 ypos = bbox.iymin - 0.5 elif corner == 'ul': xpos = bbox.ixmin - 0.5 ypos = bbox.iymax + 0.5 elif corner == 'lr': xpos = bbox.ixmax + 0.5 ypos = bbox.iymin - 0.5 elif corner == 'ur': xpos = bbox.ixmax + 0.5 ypos = bbox.iymax + 0.5 else: raise ValueError('Invalid corner name.') return _pixel_to_world(xpos, ypos, wcs) photutils-0.7.2/photutils/segmentation/tests/0000755000214200020070000000000013573510273023636 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/segmentation/tests/__init__.py0000644000214200020070000000000013563423715025740 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/segmentation/tests/test_core.py0000644000214200020070000003012713572573665026217 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the core module. """ import numpy as np from numpy.testing import assert_allclose import pytest from ..core import Segment, SegmentationImage try: import matplotlib # noqa HAS_MATPLOTLIB = True except ImportError: HAS_MATPLOTLIB = False try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False @pytest.mark.skipif('not HAS_SCIPY') class TestSegmentationImage: def setup_class(self): self.data = [[1, 1, 0, 0, 4, 4], [0, 0, 0, 0, 0, 4], [0, 0, 3, 3, 0, 0], [7, 0, 0, 0, 0, 5], [7, 7, 0, 5, 5, 5], [7, 7, 0, 0, 5, 5]] self.segm = SegmentationImage(self.data) def test_array(self): assert_allclose(self.segm.data, self.segm.__array__()) def test_copy(self): segm = SegmentationImage(self.data) segm2 = segm.copy() assert segm.data is not segm2.data assert segm.labels is not segm2.labels segm.data[0, 0] = 100. assert segm.data[0, 0] != segm2.data[0, 0] def test_invalid_data(self): # contains all zeros data = np.zeros((3, 3)) with pytest.raises(ValueError): SegmentationImage(data) # contains a NaN data = np.zeros((5, 5)) data[2, 2] = np.nan with pytest.raises(ValueError): SegmentationImage(data) # contains an inf data = np.zeros((5, 5)) data[2, 2] = np.inf data[0, 0] = -np.inf with pytest.raises(ValueError): SegmentationImage(data) # contains a negative value data = np.arange(-1, 8).reshape(3, 3) with pytest.raises(ValueError): SegmentationImage(data) @pytest.mark.parametrize('label', [0, -1, 2]) def test_invalid_label(self, label): # test with scalar labels with pytest.raises(ValueError): self.segm.check_label(label) self.segm.check_labels(label) def test_invalid_label_array(self): # test with array of labels with pytest.raises(ValueError): self.segm.check_labels([0, -1, 2]) def test_data_ma(self): assert isinstance(self.segm.data_ma, np.ma.MaskedArray) assert np.ma.count(self.segm.data_ma) == 18 assert np.ma.count_masked(self.segm.data_ma) == 18 def test_segments(self): assert isinstance(self.segm[0], Segment) assert_allclose(self.segm[0].data, self.segm[0].__array__()) assert self.segm[0].data_ma.shape == self.segm[0].data.shape assert (self.segm[0].data_ma.filled(0.).sum() == self.segm[0].data.sum()) label = 4 idx = self.segm.get_index(label) assert self.segm[idx].label == label assert self.segm[idx].area == self.segm.get_area(label) assert self.segm[idx].slices == self.segm.slices[idx] assert self.segm[idx].bbox.slices == self.segm[idx].slices for i, segment in enumerate(self.segm): assert segment.label == self.segm.labels[i] def test_repr_str(self): assert repr(self.segm) == str(self.segm) props = ['shape', 'nlabels', 'max_label'] for prop in props: assert '{}:'.format(prop) in repr(self.segm) def test_segment_repr_str(self): assert repr(self.segm[0]) == str(self.segm[0]) props = ['label', 'slices', 'area'] for prop in props: assert '{}:'.format(prop) in repr(self.segm[0]) def test_segment_data(self): assert_allclose(self.segm[3].data.shape, (3, 3)) assert_allclose(np.unique(self.segm[3].data), [0, 5]) def test_segment_make_cutout(self): cutout = self.segm[3].make_cutout(self.data, masked_array=False) assert not np.ma.is_masked(cutout) assert_allclose(cutout.shape, (3, 3)) cutout = self.segm[3].make_cutout(self.data, masked_array=True) assert np.ma.is_masked(cutout) assert_allclose(cutout.shape, (3, 3)) def test_segment_make_cutout_input(self): with pytest.raises(ValueError): self.segm[0].make_cutout(np.arange(10)) def test_labels(self): assert_allclose(self.segm.labels, [1, 3, 4, 5, 7]) def test_nlabels(self): assert self.segm.nlabels == 5 def test_max_label(self): assert self.segm.max_label == 7 def test_areas(self): expected = np.array([2, 2, 3, 6, 5]) assert_allclose(self.segm.areas, expected) assert (self.segm.get_area(1) == self.segm.areas[self.segm.get_index(1)]) assert_allclose(self.segm.get_areas(self.segm.labels), self.segm.areas) def test_background_area(self): assert self.segm.background_area == 18 def test_is_consecutive(self): assert not self.segm.is_consecutive data = [[2, 2, 0], [0, 3, 3], [0, 0, 4]] segm = SegmentationImage(data) assert not segm.is_consecutive # does not start with label=1 segm.relabel_consecutive(start_label=1) assert segm.is_consecutive def test_missing_labels(self): assert_allclose(self.segm.missing_labels, [2, 6]) def test_check_labels(self): with pytest.raises(ValueError): self.segm.check_label(2) self.segm.check_labels([2]) with pytest.raises(ValueError): self.segm.check_labels([2, 6]) @pytest.mark.skipif('not HAS_MATPLOTLIB') def test_make_cmap(self): cmap = self.segm.make_cmap() assert len(cmap.colors) == (self.segm.max_label + 1) assert_allclose(cmap.colors[0], [0, 0, 0]) assert_allclose(self.segm._cmap.colors, self.segm.make_cmap(background_color='#000000', random_state=1234).colors) def test_reassign_labels(self): segm = SegmentationImage(self.data) segm.reassign_labels(labels=[1, 7], new_label=2) ref_data = np.array([[2, 2, 0, 0, 4, 4], [0, 0, 0, 0, 0, 4], [0, 0, 3, 3, 0, 0], [2, 0, 0, 0, 0, 5], [2, 2, 0, 5, 5, 5], [2, 2, 0, 0, 5, 5]]) assert_allclose(segm.data, ref_data) assert segm.nlabels == len(segm.slices) - segm.slices.count(None) @pytest.mark.parametrize('start_label', [1, 5]) def test_relabel_consecutive(self, start_label): segm = SegmentationImage(self.data) ref_data = np.array([[1, 1, 0, 0, 3, 3], [0, 0, 0, 0, 0, 3], [0, 0, 2, 2, 0, 0], [5, 0, 0, 0, 0, 4], [5, 5, 0, 4, 4, 4], [5, 5, 0, 0, 4, 4]]) ref_data[ref_data != 0] += (start_label - 1) segm.relabel_consecutive(start_label=start_label) assert_allclose(segm.data, ref_data) # relabel_consecutive should do nothing if already consecutive segm.relabel_consecutive(start_label=start_label) assert_allclose(segm.data, ref_data) assert segm.nlabels == len(segm.slices) - segm.slices.count(None) @pytest.mark.parametrize('start_label', [0, -1]) def test_relabel_consecutive_start_invalid(self, start_label): with pytest.raises(ValueError): segm = SegmentationImage(self.data) segm.relabel_consecutive(start_label=start_label) def test_keep_labels(self): ref_data = np.array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 3, 3, 0, 0], [0, 0, 0, 0, 0, 5], [0, 0, 0, 5, 5, 5], [0, 0, 0, 0, 5, 5]]) segm = SegmentationImage(self.data) segm.keep_labels([5, 3]) assert_allclose(segm.data, ref_data) def test_keep_labels_relabel(self): ref_data = np.array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 0, 0], [0, 0, 0, 0, 0, 2], [0, 0, 0, 2, 2, 2], [0, 0, 0, 0, 2, 2]]) segm = SegmentationImage(self.data) segm.keep_labels([5, 3], relabel=True) assert_allclose(segm.data, ref_data) def test_remove_labels(self): ref_data = np.array([[1, 1, 0, 0, 4, 4], [0, 0, 0, 0, 0, 4], [0, 0, 0, 0, 0, 0], [7, 0, 0, 0, 0, 0], [7, 7, 0, 0, 0, 0], [7, 7, 0, 0, 0, 0]]) segm = SegmentationImage(self.data) segm.remove_labels(labels=[5, 3]) assert_allclose(segm.data, ref_data) def test_remove_labels_relabel(self): ref_data = np.array([[1, 1, 0, 0, 2, 2], [0, 0, 0, 0, 0, 2], [0, 0, 0, 0, 0, 0], [3, 0, 0, 0, 0, 0], [3, 3, 0, 0, 0, 0], [3, 3, 0, 0, 0, 0]]) segm = SegmentationImage(self.data) segm.remove_labels(labels=[5, 3], relabel=True) assert_allclose(segm.data, ref_data) def test_remove_border_labels(self): ref_data = np.array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 3, 3, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]) segm = SegmentationImage(self.data) segm.remove_border_labels(border_width=1) assert_allclose(segm.data, ref_data) def test_remove_border_labels_border_width(self): with pytest.raises(ValueError): segm = SegmentationImage(self.data) segm.remove_border_labels(border_width=3) def test_remove_masked_labels(self): ref_data = np.array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 3, 3, 0, 0], [7, 0, 0, 0, 0, 5], [7, 7, 0, 5, 5, 5], [7, 7, 0, 0, 5, 5]]) segm = SegmentationImage(self.data) mask = np.zeros(segm.data.shape, dtype=bool) mask[0, :] = True segm.remove_masked_labels(mask) assert_allclose(segm.data, ref_data) def test_remove_masked_labels_without_partial_overlap(self): ref_data = np.array([[0, 0, 0, 0, 4, 4], [0, 0, 0, 0, 0, 4], [0, 0, 3, 3, 0, 0], [7, 0, 0, 0, 0, 5], [7, 7, 0, 5, 5, 5], [7, 7, 0, 0, 5, 5]]) segm = SegmentationImage(self.data) mask = np.zeros(segm.data.shape, dtype=bool) mask[0, :] = True segm.remove_masked_labels(mask, partial_overlap=False) assert_allclose(segm.data, ref_data) def test_remove_masked_segments_mask_shape(self): segm = SegmentationImage(np.ones((5, 5))) mask = np.zeros((3, 3), dtype=bool) with pytest.raises(ValueError): segm.remove_masked_labels(mask) def test_outline_segments(self): segm_array = np.zeros((5, 5)).astype(int) segm_array[1:4, 1:4] = 2 segm = SegmentationImage(segm_array) segm_array_ref = np.copy(segm_array) segm_array_ref[2, 2] = 0 assert_allclose(segm.outline_segments(), segm_array_ref) def test_outline_segments_masked_background(self): segm_array = np.zeros((5, 5)).astype(int) segm_array[1:4, 1:4] = 2 segm = SegmentationImage(segm_array) segm_array_ref = np.copy(segm_array) segm_array_ref[2, 2] = 0 segm_outlines = segm.outline_segments(mask_background=True) assert isinstance(segm_outlines, np.ma.MaskedArray) assert np.ma.count(segm_outlines) == 8 assert np.ma.count_masked(segm_outlines) == 17 photutils-0.7.2/photutils/segmentation/tests/test_deblend.py0000644000214200020070000002446413572236170026656 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the deblend module. """ from astropy.modeling.models import Gaussian2D from astropy.tests.helper import catch_warnings from astropy.utils.exceptions import AstropyUserWarning import numpy as np from numpy.testing import assert_allclose import pytest from ..core import SegmentationImage from ..deblend import deblend_sources from ..detect import detect_sources from ...utils.exceptions import NoDetectionsWarning try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False try: import skimage # noqa HAS_SKIMAGE = True except ImportError: HAS_SKIMAGE = False @pytest.mark.skipif('not HAS_SCIPY') @pytest.mark.skipif('not HAS_SKIMAGE') class TestDeblendSources: def setup_class(self): g1 = Gaussian2D(100, 50, 50, 5, 5) g2 = Gaussian2D(100, 35, 50, 5, 5) g3 = Gaussian2D(30, 70, 50, 5, 5) y, x = np.mgrid[0:100, 0:100] self.x = x self.y = y self.data = g1(x, y) + g2(x, y) self.data3 = self.data + g3(x, y) self.threshold = 10 self.npixels = 5 self.segm = detect_sources(self.data, self.threshold, self.npixels) self.segm3 = detect_sources(self.data3, self.threshold, self.npixels) @pytest.mark.parametrize('mode', ['exponential', 'linear']) def test_deblend_sources(self, mode): result = deblend_sources(self.data, self.segm, self.npixels, mode=mode) assert result.nlabels == 2 assert result.nlabels == len(result.slices) mask1 = (result.data == 1) mask2 = (result.data == 2) assert_allclose(len(result.data[mask1]), len(result.data[mask2])) assert_allclose(np.sum(self.data[mask1]), np.sum(self.data[mask2])) assert_allclose(np.nonzero(self.segm), np.nonzero(result)) def test_deblend_multiple_sources(self): g4 = Gaussian2D(100, 50, 15, 5, 5) g5 = Gaussian2D(100, 35, 15, 5, 5) g6 = Gaussian2D(100, 50, 85, 5, 5) g7 = Gaussian2D(100, 35, 85, 5, 5) x = self.x y = self.y data = self.data + g4(x, y) + g5(x, y) + g6(x, y) + g7(x, y) segm = detect_sources(data, self.threshold, self.npixels) result = deblend_sources(data, segm, self.npixels) assert result.nlabels == 6 assert result.nlabels == len(result.slices) assert result.areas[0] == result.areas[1] assert result.areas[0] == result.areas[2] assert result.areas[0] == result.areas[3] assert result.areas[0] == result.areas[4] assert result.areas[0] == result.areas[5] def test_deblend_multiple_sources_with_neighbor(self): g1 = Gaussian2D(100, 50, 50, 20, 5, theta=45) g2 = Gaussian2D(100, 35, 50, 5, 5) g3 = Gaussian2D(100, 60, 20, 5, 5) x = self.x y = self.y data = (g1 + g2 + g3)(x, y) segm = detect_sources(data, self.threshold, self.npixels) result = deblend_sources(data, segm, self.npixels) assert result.nlabels == 3 @pytest.mark.parametrize('contrast, nlabels', ((0.001, 6), (0.017, 5), (0.06, 4), (0.1, 3), (0.15, 2), (0.45, 1))) def test_deblend_contrast(self, contrast, nlabels): y, x = np.mgrid[0:51, 0:151] y0 = 25 data = (Gaussian2D(9.5, 16, y0, 5, 5)(x, y) + Gaussian2D(51, 30, y0, 3, 3)(x, y) + Gaussian2D(30, 42, y0, 5, 5)(x, y) + Gaussian2D(80, 66, y0, 8, 8)(x, y) + Gaussian2D(71, 88, y0, 8, 8)(x, y) + Gaussian2D(18, 119, y0, 7, 7)(x, y)) npixels = 5 segm = detect_sources(data, 1.0, npixels) segm2 = deblend_sources(data, segm, npixels, mode='linear', nlevels=32, contrast=contrast) assert segm2.nlabels == nlabels def test_deblend_connectivity(self): data = np.zeros((51, 51)) data[15:36, 15:36] = 10. data[14, 36] = 1. data[13, 37] = 10 data[14, 14] = 5. data[13, 13] = 10. data[36, 14] = 10. data[37, 13] = 10. data[36, 36] = 10. data[37, 37] = 10. segm = detect_sources(data, 0.1, 1, connectivity=4) assert segm.nlabels == 9 segm2 = deblend_sources(data, segm, 1, mode='linear', connectivity=4) assert segm2.nlabels == 9 segm = detect_sources(data, 0.1, 1, connectivity=8) assert segm.nlabels == 1 segm2 = deblend_sources(data, segm, 1, mode='linear', connectivity=8) assert segm2.nlabels == 3 with pytest.raises(ValueError): deblend_sources(data, segm, 1, mode='linear', connectivity=4) def test_deblend_label_assignment(self): """ Regression test to ensure newly-deblended labels are unique. """ y, x = np.mgrid[0:201, 0:101] y0a = 35 y1a = 60 yshift = 100 y0b = y0a + yshift y1b = y1a + yshift data = (Gaussian2D(80, 36, y0a, 8, 8)(x, y) + Gaussian2D(71, 58, y1a, 8, 8)(x, y) + Gaussian2D(30, 36, y1a, 7, 7)(x, y) + Gaussian2D(30, 58, y0a, 7, 7)(x, y) + Gaussian2D(80, 36, y0b, 8, 8)(x, y) + Gaussian2D(71, 58, y1b, 8, 8)(x, y) + Gaussian2D(30, 36, y1b, 7, 7)(x, y) + Gaussian2D(30, 58, y0b, 7, 7)(x, y)) npixels = 5 segm1 = detect_sources(data, 5.0, npixels) segm2 = deblend_sources(data, segm1, npixels, mode='linear', nlevels=32, contrast=0.3) assert segm2.nlabels == 4 @pytest.mark.parametrize('mode', ['exponential', 'linear']) def test_deblend_sources_norelabel(self, mode): result = deblend_sources(self.data, self.segm, self.npixels, mode=mode, relabel=False) assert result.nlabels == 2 assert len(result.slices) <= result.max_label assert len(result.slices) == result.nlabels assert_allclose(np.nonzero(self.segm), np.nonzero(result)) @pytest.mark.parametrize('mode', ['exponential', 'linear']) def test_deblend_three_sources(self, mode): result = deblend_sources(self.data3, self.segm3, self.npixels, mode=mode) assert result.nlabels == 3 assert_allclose(np.nonzero(self.segm3), np.nonzero(result)) def test_deblend_sources_segm_array(self): result = deblend_sources(self.data, self.segm.data, self.npixels) assert result.nlabels == 2 def test_segment_img_badshape(self): segm_wrong = np.ones((2, 2)) with pytest.raises(ValueError): deblend_sources(self.data, segm_wrong, self.npixels) def test_invalid_nlevels(self): with pytest.raises(ValueError): deblend_sources(self.data, self.segm, self.npixels, nlevels=0) def test_invalid_contrast(self): with pytest.raises(ValueError): deblend_sources(self.data, self.segm, self.npixels, contrast=-1) def test_invalid_mode(self): with pytest.raises(ValueError): deblend_sources(self.data, self.segm, self.npixels, mode='invalid') def test_invalid_connectivity(self): with pytest.raises(ValueError): deblend_sources(self.data, self.segm, self.npixels, connectivity='invalid') def test_constant_source(self): data = self.data.copy() data[data.nonzero()] = 1. result = deblend_sources(data, self.segm, self.npixels) assert_allclose(result, self.segm) def test_source_with_negval(self): data = self.data.copy() data -= 20 with catch_warnings(AstropyUserWarning) as warning_lines: deblend_sources(data, self.segm, self.npixels) assert ('contains negative values' in str(warning_lines[0].message)) def test_source_zero_min(self): data = self.data.copy() data -= data[self.segm.data > 0].min() result1 = deblend_sources(self.data, self.segm, self.npixels) result2 = deblend_sources(data, self.segm, self.npixels) assert_allclose(result1, result2) def test_connectivity(self): """Regression test for #341.""" data = np.zeros((3, 3)) data[0, 0] = 2 data[1, 1] = 2 data[2, 2] = 1 segm = np.zeros(data.shape, dtype=int) segm[data.nonzero()] = 1 segm = SegmentationImage(segm) data = data * 100. segm_deblend = deblend_sources(data, segm, npixels=1, connectivity=8) assert segm_deblend.nlabels == 1 with pytest.raises(ValueError): deblend_sources(data, segm, npixels=1, connectivity=4) def test_data_nan(self): """ Test that deblending occurs even if the data within a segment contains one or more NaNs. Regression test for #658. """ data = self.data.copy() data[50, 50] = np.nan segm2 = deblend_sources(data, self.segm, 5) assert segm2.nlabels == 2 def test_watershed(self): """ Regression test to ensure watershed input mask is bool array. With scikit-image >= 0.13, the mask must be a bool array. In particular, if the mask array contains label 512, the watershed algorithm fails. """ segm = self.segm.copy() segm.reassign_label(1, 512) result = deblend_sources(self.data, segm, self.npixels) assert result.nlabels == 2 def test_nondetection(self): """ Test for case where no sources are detected at one of the threshold levels. For this case, a `NoDetectionsWarning` should not be raised when deblending sources. """ data = np.copy(self.data3) data[50, 50] = 1000. data[50, 70] = 500. self.segm = detect_sources(data, self.threshold, self.npixels) with catch_warnings(NoDetectionsWarning) as warning_lines: deblend_sources(data, self.segm, self.npixels) assert len(warning_lines) == 0 def test_nonconsecutive_labels(self): segm = self.segm.copy() segm.reassign_label(1, 1000) result = deblend_sources(self.data, segm, self.npixels) assert result.nlabels == 2 photutils-0.7.2/photutils/segmentation/tests/test_detect.py0000644000214200020070000001554013572573665026541 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the detect module. """ from astropy.convolution import Gaussian2DKernel from astropy.stats import gaussian_fwhm_to_sigma from astropy.tests.helper import catch_warnings from astropy.utils.exceptions import AstropyUserWarning import numpy as np from numpy.testing import assert_allclose, assert_array_equal import pytest from ...utils.exceptions import NoDetectionsWarning from ..detect import detect_sources, make_source_mask from ...datasets import make_4gaussians_image try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False @pytest.mark.skipif('not HAS_SCIPY') class TestDetectSources: def setup_class(self): self.data = np.array([[0, 1, 0], [0, 2, 0], [0, 0, 0]]).astype(float) self.refdata = np.array([[0, 1, 0], [0, 1, 0], [0, 0, 0]]) fwhm2sigma = 1.0 / (2.0 * np.sqrt(2.0 * np.log(2.0))) filter_kernel = Gaussian2DKernel(2. * fwhm2sigma, x_size=3, y_size=3) filter_kernel.normalize() self.filter_kernel = filter_kernel def test_detection(self): """Test basic detection.""" segm = detect_sources(self.data, threshold=0.9, npixels=2) assert_array_equal(segm.data, self.refdata) def test_small_sources(self): """Test detection where sources are smaller than npixels size.""" with catch_warnings(NoDetectionsWarning) as warning_lines: detect_sources(self.data, threshold=0.9, npixels=5) assert warning_lines[0].category == NoDetectionsWarning assert 'No sources were found.' in str(warning_lines[0].message) def test_npixels(self): """ Test removal of sources whose size is less than npixels. Regression tests for #663. """ data = np.zeros((8, 8)) data[0:4, 0] = 1 data[0, 0:4] = 1 data[3, 3:] = 2 data[3:, 3] = 2 segm = detect_sources(data, 0, npixels=8) assert segm.nlabels == 1 segm = detect_sources(data, 0, npixels=9) assert segm.nlabels == 1 data = np.zeros((8, 8)) data[0:4, 0] = 1 data[0, 0:4] = 1 data[3, 2:] = 2 data[3:, 2] = 2 data[5:, 3] = 2 npixels = np.arange(9, 14) for npixels in np.arange(9, 14): segm = detect_sources(data, 0, npixels=npixels) assert segm.nlabels == 1 assert segm.areas[0] == 13 with catch_warnings(NoDetectionsWarning) as warning_lines: detect_sources(data, 0, npixels=14) assert warning_lines[0].category == NoDetectionsWarning assert 'No sources were found.' in str(warning_lines[0].message) def test_zerothresh(self): """Test detection with zero threshold.""" segm = detect_sources(self.data, threshold=0., npixels=2) assert_array_equal(segm.data, self.refdata) def test_zerodet(self): """Test detection with large threshold giving no detections.""" with catch_warnings(NoDetectionsWarning) as warning_lines: detect_sources(self.data, threshold=7, npixels=2) assert warning_lines[0].category == NoDetectionsWarning assert 'No sources were found.' in str(warning_lines[0].message) def test_8connectivity(self): """Test detection with connectivity=8.""" data = np.eye(3) segm = detect_sources(data, threshold=0.9, npixels=1, connectivity=8) assert_array_equal(segm.data, data) def test_4connectivity(self): """Test detection with connectivity=4.""" data = np.eye(3) ref = np.diag([1, 2, 3]) segm = detect_sources(data, threshold=0.9, npixels=1, connectivity=4) assert_array_equal(segm.data, ref) def test_basic_filter_kernel(self): """Test detection with filter_kernel.""" kernel = np.ones((3, 3)) / 9. threshold = 0.3 expected = np.ones((3, 3)) expected[2] = 0 segm = detect_sources(self.data, threshold, npixels=1, filter_kernel=kernel) assert_array_equal(segm.data, expected) def test_npixels_nonint(self): """Test if error raises if npixel is non-integer.""" with pytest.raises(ValueError): detect_sources(self.data, threshold=1, npixels=0.1) def test_npixels_negative(self): """Test if error raises if npixel is negative.""" with pytest.raises(ValueError): detect_sources(self.data, threshold=1, npixels=-1) def test_connectivity_invalid(self): """Test if error raises if connectivity is invalid.""" with pytest.raises(ValueError): detect_sources(self.data, threshold=1, npixels=1, connectivity=10) def test_filter_kernel_array(self): segm = detect_sources(self.data, 0.1, npixels=1, filter_kernel=self.filter_kernel.array) assert_array_equal(segm.data, np.ones((3, 3))) def test_filter_kernel(self): segm = detect_sources(self.data, 0.1, npixels=1, filter_kernel=self.filter_kernel) assert_array_equal(segm.data, np.ones((3, 3))) def test_unnormalized_filter_kernel(self): with catch_warnings(AstropyUserWarning) as warning_lines: detect_sources(self.data, 0.1, npixels=1, filter_kernel=self.filter_kernel*10.) assert warning_lines[0].category == AstropyUserWarning assert ('The kernel is not normalized.' in str(warning_lines[0].message)) def test_mask(self): data = np.zeros((11, 11)) data[3:8, 3:8] = 5. mask = np.zeros(data.shape, dtype=bool) mask[4:6, 4:6] = True segm1 = detect_sources(data, 1., 1.) segm2 = detect_sources(data, 1., 1., mask=mask) assert segm2.areas[0] == segm1.areas[0] - mask.sum() def test_mask_shape(self): with pytest.raises(ValueError): detect_sources(self.data, 1., 1., mask=np.ones((5, 5))) @pytest.mark.skipif('not HAS_SCIPY') class TestMakeSourceMask: def setup_class(self): self.data = make_4gaussians_image() def test_dilate_size(self): mask1 = make_source_mask(self.data, 5, 10) mask2 = make_source_mask(self.data, 5, 10, dilate_size=20) assert np.count_nonzero(mask2) > np.count_nonzero(mask1) def test_kernel(self): mask1 = make_source_mask(self.data, 5, 10, filter_fwhm=2, filter_size=3) sigma = 2 * gaussian_fwhm_to_sigma kernel = Gaussian2DKernel(sigma, x_size=3, y_size=3) mask2 = make_source_mask(self.data, 5, 10, filter_kernel=kernel) assert_allclose(mask1, mask2) def test_no_detections(self): mask = make_source_mask(self.data, 100, 100) assert np.count_nonzero(mask) == 0 photutils-0.7.2/photutils/segmentation/tests/test_properties.py0000644000214200020070000005405413572573665027470 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the properties module. """ import itertools import astropy.units as u import astropy.wcs as WCS from astropy.modeling import models from astropy.table import QTable from astropy.tests.helper import assert_quantity_allclose, catch_warnings from astropy.utils.exceptions import AstropyUserWarning from astropy.utils.misc import isiterable from numpy.testing import assert_allclose import numpy as np import pytest from ..core import SegmentationImage from ..detect import detect_sources from ..properties import SourceCatalog, SourceProperties, source_properties try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False XCEN = 51. YCEN = 52.7 MAJOR_SIG = 8. MINOR_SIG = 3. THETA = np.pi / 6. G1 = models.Gaussian2D(111., XCEN, YCEN, MAJOR_SIG, MINOR_SIG, theta=THETA) G2 = models.Gaussian2D(50, 20, 80, 5.1, 4.5) G3 = models.Gaussian2D(70, 75, 18, 9.2, 4.5) Y, X = np.mgrid[0:100, 0:100] IMAGE = G1(X, Y) + G2(X, Y) + G3(X, Y) THRESHOLD = 0.1 ERR_VALS = [0., 2.5] BACKGRD_VALS = [None, 0., 1., 3.5] FWHM2SIGMA = 1.0 / (2.0 * np.sqrt(2.0 * np.log(2.0))) @pytest.mark.skipif('not HAS_SCIPY') class TestSourceProperties: def setup_class(self): self.segm = detect_sources(IMAGE, THRESHOLD, npixels=5) def test_invalid_shapes(self): wrong_shape = np.ones((3, 3)) with pytest.raises(ValueError): SourceProperties(IMAGE, np.eye(3, dtype=int), label=1) with pytest.raises(ValueError): SourceProperties(IMAGE, self.segm, label=1, filtered_data=wrong_shape) with pytest.raises(ValueError): SourceProperties(IMAGE, self.segm, label=1, error=wrong_shape) with pytest.raises(ValueError): SourceProperties(IMAGE, self.segm, label=1, background=wrong_shape) def test_invalid_units(self): unit = u.uJy wrong_unit = u.km with pytest.raises(ValueError): SourceProperties(IMAGE*unit, self.segm, label=1, filtered_data=IMAGE*wrong_unit) with pytest.raises(ValueError): SourceProperties(IMAGE*unit, self.segm, label=1, error=IMAGE*wrong_unit) with pytest.raises(ValueError): SourceProperties(IMAGE*unit, self.segm, label=1, background=IMAGE*wrong_unit) # all array inputs must have the same unit with pytest.raises(ValueError): SourceProperties(IMAGE*unit, self.segm, label=1, filtered_data=IMAGE) @pytest.mark.parametrize('label', (0, -1)) def test_label_invalid(self, label): with pytest.raises(ValueError): SourceProperties(IMAGE, self.segm, label=label) @pytest.mark.parametrize('label', (0, -1)) def test_label_missing(self, label): segm = self.segm.copy() segm.remove_label(2) with pytest.raises(ValueError): SourceProperties(IMAGE, segm, label=2) SourceProperties(IMAGE, segm, label=label) def test_wcs(self): mywcs = WCS.WCS(naxis=2) rho = np.pi / 3. scale = 0.1 / 3600. mywcs.wcs.cd = [[scale*np.cos(rho), -scale*np.sin(rho)], [scale*np.sin(rho), scale*np.cos(rho)]] mywcs.wcs.ctype = ['RA---TAN', 'DEC--TAN'] props = SourceProperties(IMAGE, self.segm, wcs=mywcs, label=1) assert props.sky_centroid_icrs is not None assert props.sky_bbox_ll is not None assert props.sky_bbox_ul is not None assert props.sky_bbox_lr is not None assert props.sky_bbox_ur is not None tbl = props.to_table() assert len(tbl) == 1 def test_nowcs(self): props = SourceProperties(IMAGE, self.segm, wcs=None, label=1) assert props.sky_centroid_icrs is None assert props.sky_bbox_ll is None assert props.sky_bbox_ul is None assert props.sky_bbox_lr is None assert props.sky_bbox_ur is None def test_to_table(self): props = SourceProperties(IMAGE, self.segm, label=2) t1 = props.to_table() assert isinstance(t1, QTable) assert len(t1) == 1 assert_quantity_allclose(t1['area'], 1058 * u.pix**2) def test_masks(self): """ Test masks, including automatic masking of all non-finite (e.g. NaN, inf) values in the data array. """ error = np.ones(IMAGE.shape) * 5.1 error[41, 35] = np.nan error[42, 36] = np.inf background = np.ones(IMAGE.shape) * 1.2 background[62, 55] = np.nan background[63, 56] = np.inf mask = np.zeros(IMAGE.shape).astype(bool) mask[45:55, :] = True data = np.copy(IMAGE) data[40, 40:45] = np.nan data[60, 60:65] = np.inf data[65, 65:70] = -np.inf props = SourceProperties(data, self.segm, label=2, error=error, background=background, mask=mask) # ensure mask is identical for data, error, and background assert props.data_cutout_ma.compressed().size == 677 assert (props.data_cutout_ma.compressed().size == props.filtered_data_cutout_ma.compressed().size) assert (props.data_cutout_ma.compressed().size == props.error_cutout_ma.compressed().size) assert (props.data_cutout_ma.compressed().size == props.background_cutout_ma.compressed().size) assert (len(props._filtered_data_values) == props.filtered_data_cutout_ma.compressed().size) # test for non-finite values in error and/or background outside # of the data mask tbl = props.to_table() assert np.isnan(tbl['source_sum_err']) assert np.isnan(tbl['background_sum']) assert np.isnan(tbl['background_mean']) # test that the masks are independent objects assert (np.count_nonzero(props._segment_mask) != np.count_nonzero(props._total_mask)) assert (np.count_nonzero(props._data_mask) != np.count_nonzero(props._total_mask)) assert_allclose(props._data_zeroed.sum(), props.source_sum) assert_allclose(props.data_cutout, props.make_cutout(props._data, masked_array=False)) assert_allclose(props.data_cutout_ma, props.make_cutout(props._data, masked_array=True)) assert_allclose(props.error_cutout_ma, props.make_cutout(props._error, masked_array=True)) assert_allclose(props.background_cutout_ma, props.make_cutout(props._background, masked_array=True)) def test_completely_masked(self): """Test case where a source is completely masked.""" error = np.ones(IMAGE.shape) * 5.1 background = np.ones(IMAGE.shape) * 1.2 mask = np.ones(IMAGE.shape).astype(bool) obj = source_properties(IMAGE, self.segm, error=error, background=background, mask=mask)[0] assert np.isnan(obj.xcentroid.value) assert np.isnan(obj.ycentroid.value) assert np.isnan(obj.source_sum) assert np.isnan(obj.source_sum_err) assert np.isnan(obj.background_sum) assert np.isnan(obj.background_mean) assert np.isnan(obj.background_at_centroid) assert np.isnan(obj.area) assert np.isnan(obj.perimeter) assert np.isnan(obj.min_value) assert np.isnan(obj.max_value) assert np.isnan(obj.minval_xpos.value) assert np.isnan(obj.minval_ypos.value) assert np.isnan(obj.maxval_xpos.value) assert np.isnan(obj.maxval_ypos.value) assert np.all(np.isnan(obj.minval_cutout_pos.value)) assert np.all(np.isnan(obj.maxval_cutout_pos.value)) assert np.isnan(obj.gini) def test_repr_str(self): props = SourceProperties(IMAGE, self.segm, label=1) assert repr(props) == str(props) attrs = ['label', 'centroid', 'sky_centroid'] for attr in attrs: assert '{}:'.format(attr) in repr(props) @pytest.mark.skipif('not HAS_SCIPY') class TestSourcePropertiesFunctionInputs: def setup_class(self): self.segm = detect_sources(IMAGE, THRESHOLD, npixels=5) def test_segment_shape(self): wrong_shape = np.eye(3, dtype=int) with pytest.raises(ValueError): source_properties(IMAGE, wrong_shape) def test_error_shape(self): wrong_shape = np.ones((2, 2)) with pytest.raises(ValueError): source_properties(IMAGE, self.segm, error=wrong_shape) def test_background_shape(self): wrong_shape = np.ones((2, 2)) with pytest.raises(ValueError): source_properties(IMAGE, self.segm, background=wrong_shape) def test_mask_shape(self): wrong_shape = np.zeros((2, 2)).astype(bool) with pytest.raises(ValueError): source_properties(IMAGE, self.segm, mask=wrong_shape) def test_labels(self): props = source_properties(IMAGE, self.segm, labels=1) assert props[0].id == 1 def test_invalidlabels(self): with catch_warnings(AstropyUserWarning) as warning_lines: source_properties(IMAGE, self.segm, labels=[-1, 1]) assert warning_lines[0].category == AstropyUserWarning assert ('label -1 is not in the segmentation image.' in str(warning_lines[0].message)) def test_nosources(self): with pytest.raises(ValueError): source_properties(IMAGE, self.segm, labels=-1) @pytest.mark.skipif('not HAS_SCIPY') class TestSourcePropertiesFunction: def setup_class(self): self.segm = detect_sources(IMAGE, THRESHOLD, npixels=5) def test_properties(self): obj = source_properties(IMAGE, self.segm)[1] assert obj.id == 2 assert_quantity_allclose(obj.xcentroid, XCEN*u.pix, rtol=1.e-2) assert_quantity_allclose(obj.ycentroid, YCEN*u.pix, rtol=1.e-2) assert_allclose(obj.source_sum, 16723.388) assert_quantity_allclose(obj.semimajor_axis_sigma, MAJOR_SIG*u.pix, rtol=1.e-2) assert_quantity_allclose(obj.semiminor_axis_sigma, MINOR_SIG*u.pix, rtol=1.e-2) assert_quantity_allclose(obj.orientation, THETA*u.rad, rtol=1.e-3) assert obj.bbox_xmin.value == 25 assert obj.bbox_xmax.value == 77 assert obj.bbox_ymin.value == 35 assert obj.bbox_ymax.value == 70 assert_quantity_allclose(obj.area, 1058.0*u.pix**2) assert_allclose(len(obj.indices), 2) assert_allclose(len(obj.indices[0]), obj.area.value) properties = ['background_at_centroid', 'background_mean', 'eccentricity', 'ellipticity', 'elongation', 'equivalent_radius', 'max_value', 'maxval_xpos', 'maxval_ypos', 'min_value', 'minval_xpos', 'minval_ypos', 'perimeter', 'cxx', 'cxy', 'cyy', 'covar_sigx2', 'covar_sigxy', 'covar_sigy2', 'bbox_xmin', 'bbox_xmax', 'bbox_ymin', 'bbox_ymax'] for propname in properties: assert not isiterable(getattr(obj, propname)) properties = ['centroid', 'covariance_eigvals', 'cutout_centroid', 'maxval_cutout_pos', 'minval_cutout_pos'] shapes = [getattr(obj, p).shape for p in properties] for shape in shapes: assert shape == (2,) properties = ['covariance', 'inertia_tensor'] shapes = [getattr(obj, p).shape for p in properties] for shape in shapes: assert shape == (2, 2) properties = ['moments', 'moments_central'] shapes = [getattr(obj, p).shape for p in properties] for shape in shapes: assert shape == (4, 4) def test_properties_background_notnone(self): value = 1. props = source_properties(IMAGE, self.segm, background=value) assert props[0].background_mean == value assert_allclose(props[0].background_at_centroid, value) def test_properties_background_units(self): unit = u.uJy value = 1. * unit props = source_properties(IMAGE * unit, self.segm, background=value) assert props[0].background_mean == value assert_allclose(props[0].background_at_centroid, value) def test_properties_error_background_none(self): props = source_properties(IMAGE, self.segm) assert props[0].background_cutout_ma is None assert props[0].error_cutout_ma is None def test_cutout_shapes(self): error = np.ones(IMAGE.shape, dtype=float) props = source_properties(IMAGE, self.segm, error=error, background=1.) bbox = props[0].bbox properties = ['background_cutout_ma', 'data_cutout', 'data_cutout_ma', 'error_cutout_ma'] shapes = [getattr(props[0], p).shape for p in properties] for shape in shapes: assert shape == bbox.shape def test_make_cutout(self): props = source_properties(IMAGE, self.segm) data = np.ones((2, 2)) with pytest.raises(ValueError): props[0].make_cutout(data) @pytest.mark.parametrize(('error_value', 'background'), list(itertools.product(ERR_VALS, BACKGRD_VALS))) def test_segmentation_inputs(self, error_value, background): error = np.ones(IMAGE.shape) * error_value props = source_properties(IMAGE, self.segm, error=error, background=background) obj = props[1] assert_quantity_allclose(obj.xcentroid, XCEN*u.pix, rtol=1.e-2) assert_quantity_allclose(obj.ycentroid, YCEN*u.pix, rtol=1.e-2) assert_quantity_allclose(obj.semimajor_axis_sigma, MAJOR_SIG*u.pix, rtol=1.e-2) assert_quantity_allclose(obj.semiminor_axis_sigma, MINOR_SIG*u.pix, rtol=1.e-2) assert_quantity_allclose(obj.orientation, THETA*u.rad, rtol=1.e-3) assert obj.bbox_xmin.value == 25 assert obj.bbox_xmax.value == 77 assert obj.bbox_ymin.value == 35 assert obj.bbox_ymax.value == 70 area = obj.area.value assert_allclose(area, 1058.0) if background is not None: assert_allclose(obj.background_sum, area * background) assert_allclose(obj.source_sum, 16723.388) true_error = np.sqrt(obj.area.value) * error_value assert_allclose(obj.source_sum_err, true_error) def test_data_allzero(self): props = source_properties(IMAGE*0., self.segm) proplist = ['xcentroid', 'ycentroid', 'semimajor_axis_sigma', 'semiminor_axis_sigma', 'eccentricity', 'orientation', 'ellipticity', 'elongation', 'cxx', 'cxy', 'cyy'] for prop in proplist: assert np.isnan(getattr(props[0], prop)) def test_mask(self): data = np.zeros((3, 3)) data[0, 1] = 1. data[1, 1] = 1. mask = np.zeros(data.shape, dtype=bool) mask[0, 1] = True segm = data.astype(int) props = source_properties(data, segm, mask=mask) assert_allclose(props[0].xcentroid.value, 1) assert_allclose(props[0].ycentroid.value, 1) assert_allclose(props[0].source_sum, 1) assert_allclose(props[0].area.value, 1) def test_mask_nomask(self): props = source_properties(IMAGE, self.segm, mask=np.ma.nomask) mask = np.zeros(IMAGE.shape).astype(bool) props2 = source_properties(IMAGE, self.segm, mask=mask) assert_allclose(props.xcentroid.value, props2.xcentroid.value) assert_allclose(props.ycentroid.value, props2.ycentroid.value) assert_quantity_allclose(props.source_sum, props2.source_sum) def test_single_pixel_segment(self): segm = np.zeros(self.segm.shape, dtype=int) segm[50, 50] = 1 props = source_properties(IMAGE, segm) assert props[0].eccentricity == 0 def test_filtering(self): from astropy.convolution import Gaussian2DKernel filter_kernel = Gaussian2DKernel(2.*FWHM2SIGMA, x_size=3, y_size=3) error = np.sqrt(IMAGE) props1 = source_properties(IMAGE, self.segm, error=error) props2 = source_properties(IMAGE, self.segm, error=error, filter_kernel=filter_kernel.array) p1, p2 = props1[0], props2[0] keys = ['source_sum', 'source_sum_err'] for key in keys: assert getattr(p1, key) == getattr(p2, key) keys = ['semimajor_axis_sigma', 'semiminor_axis_sigma'] for key in keys: assert getattr(p1, key) != getattr(p2, key) def test_filtering_kernel(self): data = np.zeros((3, 3)) data[1, 1] = 1. from astropy.convolution import Gaussian2DKernel filter_kernel = Gaussian2DKernel(2.*FWHM2SIGMA, x_size=3, y_size=3) error = np.sqrt(IMAGE) props1 = source_properties(IMAGE, self.segm, error=error) props2 = source_properties(IMAGE, self.segm, error=error, filter_kernel=filter_kernel) p1, p2 = props1[0], props2[0] keys = ['source_sum', 'source_sum_err'] for key in keys: assert getattr(p1, key) == getattr(p2, key) keys = ['semimajor_axis_sigma', 'semiminor_axis_sigma'] for key in keys: assert getattr(p1, key) != getattr(p2, key) def test_data_nan(self): """Test case when data contains NaNs within a segment.""" data = np.ones((20, 20)) data[2, 2] = np.nan segm = np.zeros((20, 20)).astype(int) segm[1:5, 1:5] = 1 segm[7:15, 7:15] = 2 segm = SegmentationImage(segm) props = source_properties(data, segm) assert_quantity_allclose(props.minval_xpos, [1, 7]*u.pix) def test_nonconsecutive_labels(self): segm = self.segm.copy() segm.reassign_label(1, 1000) cat = source_properties(IMAGE, segm) assert len(cat) == 3 assert cat.id == [2, 3, 1000] assert cat[0].id == 2 assert cat[1].id == 3 assert cat[segm.get_index(label=1000)].id == 1000 @pytest.mark.skipif('not HAS_SCIPY') class TestSourceCatalog: def setup_class(self): self.segm = detect_sources(IMAGE, THRESHOLD, npixels=5) def test_basic(self): segm = np.zeros(IMAGE.shape) x = y = np.arange(0, 100, 10) segm[y, x] = np.arange(10) cat = source_properties(IMAGE, segm) assert len(cat) == 9 cat2 = cat[0:5] assert len(cat2) == 5 cat3 = SourceCatalog(cat2) del cat3[4] assert len(cat3) == 4 # test iteration for obj in cat: assert obj.area.value == 1 def test_inputs(self): cat = source_properties(IMAGE, self.segm) cat2 = SourceCatalog(cat[0]) assert len(cat) == 3 assert len(cat2) == 1 with pytest.raises(ValueError): SourceCatalog([]) with pytest.raises(ValueError): SourceCatalog('a') def test_table(self): cat = source_properties(IMAGE, self.segm) t = cat.to_table() assert isinstance(t, QTable) assert len(t) == 3 def test_table_include(self): cat = source_properties(IMAGE, self.segm) columns = ['id', 'xcentroid'] t = cat.to_table(columns=columns) assert isinstance(t, QTable) assert len(t) == 3 assert t.colnames == columns def test_table_include_invalidname(self): cat = source_properties(IMAGE, self.segm) columns = ['idzz', 'xcentroidzz'] with pytest.raises(AttributeError): cat.to_table(columns=columns) def test_table_exclude(self): cat = source_properties(IMAGE, self.segm) exclude = ['id', 'xcentroid'] t = cat.to_table(exclude_columns=exclude) assert isinstance(t, QTable) assert len(t) == 3 with pytest.raises(KeyError): t['id'] def test_table_wcs(self): mywcs = WCS.WCS(naxis=2) rho = np.pi / 3. scale = 0.1 / 3600. mywcs.wcs.cd = [[scale*np.cos(rho), -scale*np.sin(rho)], [scale*np.sin(rho), scale*np.cos(rho)]] mywcs.wcs.ctype = ['RA---TAN', 'DEC--TAN'] cat = source_properties(IMAGE, self.segm, wcs=mywcs) columns = ['sky_centroid', 'sky_centroid_icrs', 'sky_bbox_ll', 'sky_bbox_ul', 'sky_bbox_lr', 'sky_bbox_ur'] t = cat.to_table(columns=columns) for column in columns: assert t[0][column] is not None assert t.colnames == columns obj = cat[0] row = t[0] assert_quantity_allclose(obj.sky_bbox_ll.ra, row['sky_bbox_ll'].ra) assert_quantity_allclose(obj.sky_bbox_ll.dec, row['sky_bbox_ll'].dec) assert_quantity_allclose(obj.sky_bbox_ul.ra, row['sky_bbox_ul'].ra) assert_quantity_allclose(obj.sky_bbox_ul.dec, row['sky_bbox_ul'].dec) assert_quantity_allclose(obj.sky_bbox_lr.ra, row['sky_bbox_lr'].ra) assert_quantity_allclose(obj.sky_bbox_lr.dec, row['sky_bbox_lr'].dec) assert_quantity_allclose(obj.sky_bbox_ur.ra, row['sky_bbox_ur'].ra) assert_quantity_allclose(obj.sky_bbox_ur.dec, row['sky_bbox_ur'].dec) def test_table_no_wcs(self): cat = source_properties(IMAGE, self.segm) columns = ['sky_centroid', 'sky_centroid_icrs', 'sky_bbox_ll', 'sky_bbox_ul', 'sky_bbox_lr', 'sky_bbox_ur'] t = cat.to_table(columns=columns) for column in columns: assert t[0][column] is None assert t.colnames == columns def test_repr_str(self): segm = np.zeros(IMAGE.shape) x = y = np.arange(0, 100, 10) segm[y, x] = np.arange(10) cat = source_properties(IMAGE, segm) assert repr(cat) == str(cat) assert 'Catalog length:' in repr(cat) photutils-0.7.2/photutils/tests/0000755000214200020070000000000013573510273021141 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/tests/__init__.py0000644000214200020070000000000013563423715023243 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/tests/coveragerc0000644000214200020070000000124512444404542023203 0ustar lbradleySTSCI\science00000000000000[run] source = photutils omit = photutils/*__init__* photutils/_astropy_init.py photutils/conftest* photutils/cython_version* photutils/*setup* photutils/*tests/* photutils/version* photutils/extern/* [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} photutils-0.7.2/photutils/utils/0000755000214200020070000000000013573510273021137 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/utils/__init__.py0000644000214200020070000000062113572576136023260 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This subpackage provides general-purpose utility functions. """ from .check_random_state import * # noqa from .colormaps import * # noqa from .convolution import * # noqa from .errors import * # noqa from .exceptions import * # noqa from .interpolation import * # noqa from .misc import * # noqa from .stats import * # noqa photutils-0.7.2/photutils/utils/_moments.py0000644000214200020070000000322313563423715023335 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provide tools for calculating image moments. """ import numpy as np __all__ = ['_moments_central', '_moments'] def _moments_central(data, center=None, order=1): """ Calculate the central image moments up to the specified order. Parameters ---------- data : 2D array-like The input 2D array. center : tuple of two floats or `None`, optional The ``(x, y)`` center position. If `None` it will calculated as the "center of mass" of the input ``data``. order : int, optional The maximum order of the moments to calculate. Returns ------- moments : 2D `~numpy.ndarray` The central image moments. """ data = np.asarray(data).astype(float) if data.ndim != 2: raise ValueError('data must be a 2D array.') if center is None: from ..centroids import centroid_com center = centroid_com(data) indices = np.ogrid[[slice(0, i) for i in data.shape]] ypowers = (indices[0] - center[1]) ** np.arange(order + 1) xpowers = np.transpose(indices[1] - center[0]) ** np.arange(order + 1) return np.dot(np.dot(np.transpose(ypowers), data), xpowers) def _moments(data, order=1): """ Calculate the raw image moments up to the specified order. Parameters ---------- data : 2D array-like The input 2D array. order : int, optional The maximum order of the moments to calculate. Returns ------- moments : 2D `~numpy.ndarray` The raw image moments. """ return _moments_central(data, center=(0, 0), order=order) photutils-0.7.2/photutils/utils/_wcs_helpers.py0000644000214200020070000001065413563423715024177 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides WCS helper tools. """ from astropy import units as u from astropy.coordinates import UnitSphericalRepresentation from astropy.wcs import WCS from astropy.wcs.utils import pixel_to_skycoord, skycoord_to_pixel import numpy as np def _pixel_to_world(xpos, ypos, wcs): """ Calculate the sky coordinates at the input pixel positions. Parameters ---------- xpos, ypos : float or array-like The x and y pixel position(s). wcs : WCS object or `None` A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- skycoord : `~astropy.coordinates.SkyCoord` The sky coordinate(s) at the input position(s). """ if wcs is None: return None try: return wcs.pixel_to_world(xpos, ypos) except AttributeError: if isinstance(wcs, WCS): # for Astropy < 3.1 WCS support return pixel_to_skycoord(xpos, ypos, wcs, origin=0) else: raise ValueError('Input wcs does not support the shared WCS ' 'interface.') def _world_to_pixel(skycoord, wcs): """ Calculate the sky coordinates at the input pixel positions. Parameters ---------- skycoord : `~astropy.coordinates.SkyCoord` The sky coordinate(s). wcs : WCS object or `None` A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- xpos, ypos : float or array-like The x and y pixel position(s) at the input sky coordinate(s). """ if wcs is None: return None try: return wcs.world_to_pixel(skycoord) except AttributeError: if isinstance(wcs, WCS): # for Astropy < 3.1 WCS support return skycoord_to_pixel(skycoord, wcs, origin=0) else: raise ValueError('Input wcs does not support the shared WCS ' 'interface.') def _pixel_scale_angle_at_skycoord(skycoord, wcs, offset=1.0*u.arcsec): """ Calculate the pixel scale and WCS rotation angle at the position of a SkyCoord coordinate. Parameters ---------- skycoord : `~astropy.coordinates.SkyCoord` The SkyCoord coordinate. wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). offset : `~astropy.units.Quantity` A small angular offset to use to compute the pixel scale and position angle. Returns ------- scale : `~astropy.units.Quantity` The pixel scale in arcsec/pixel. angle : `~astropy.units.Quantity` The angle (in degrees) measured counterclockwise from the positive x axis to the "North" axis of the celestial coordinate system. Notes ----- If distortions are present in the image, the x and y pixel scales likely differ. This function computes a single pixel scale along the North/South axis. """ try: x, y = wcs.world_to_pixel(skycoord) # We take a point directly North (i.e. latitude offset) the input # sky coordinate and convert it to pixel coordinates, then we use the # pixel deltas between the input and offset sky coordinate to # calculate the pixel scale and angle. skycoord_offset = skycoord.directional_offset_by(0.0, offset) x_offset, y_offset = wcs.world_to_pixel(skycoord_offset) except AttributeError: # for Astropy < 3.1 WCS support x, y = skycoord_to_pixel(skycoord, wcs) coord = skycoord.represent_as('unitspherical') coord_new = UnitSphericalRepresentation(coord.lon, coord.lat + offset) coord_offset = skycoord.realize_frame(coord_new) x_offset, y_offset = skycoord_to_pixel(coord_offset, wcs) dx = x_offset - x dy = y_offset - y scale = offset.to(u.arcsec) / (np.hypot(dx, dy) * u.pixel) angle = (np.arctan2(dy, dx) * u.radian).to(u.deg) return scale, angle photutils-0.7.2/photutils/utils/check_random_state.py0000644000214200020070000000260313563423715025332 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools to seed a numpy RandomState instance. """ import numbers import numpy as np __all__ = ['check_random_state'] def check_random_state(seed): """ Turn seed into a `numpy.random.mtrand.RandomState` instance. Parameters ---------- seed : `None`, int, or `numpy.random.mtrand.RandomState` If ``seed`` is `None`, return the `~numpy.random.mtrand.RandomState` singleton used by ``numpy.random``. If ``seed`` is an `int`, return a new `~numpy.random.mtrand.RandomState` instance seeded with ``seed``. If ``seed`` is already a `~numpy.random.mtrand.RandomState`, return it. Otherwise raise ``ValueError``. Returns ------- random_state : `numpy.random.mtrand.RandomState` RandomState object. Notes ----- This routine is from scikit-learn. See https://scikit-learn.org/stable/developers/utilities.html#validation-tools. """ if seed is None or seed is np.random: return np.random.mtrand._rand if isinstance(seed, (numbers.Integral, np.integer)): return np.random.RandomState(seed) if isinstance(seed, np.random.RandomState): return seed raise ValueError('{0!r} cannot be used to seed a numpy.random.RandomState' ' instance'.format(seed)) photutils-0.7.2/photutils/utils/colormaps.py0000644000214200020070000000420313572576136023520 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for generating matplotlib colormaps. """ from astropy.utils import deprecated import numpy as np from .check_random_state import check_random_state __all__ = ['make_random_cmap'] @deprecated('0.7', alternative='make_random_cmap') def random_cmap(ncolors=256, random_state=None): """ Make a matplotlib colormap consisting of (random) muted colors. A random colormap is very useful for plotting segmentation images. Parameters ---------- ncolors : int, optional The number of colors in the colormap. The default is 256. random_state : int or `~numpy.random.mtrand.RandomState`, optional The pseudo-random number generator state used for random sampling. Separate function calls with the same ``random_state`` will generate the same colormap. Returns ------- cmap : `matplotlib.colors.ListedColormap` The matplotlib colormap with random colors. """ return make_random_cmap(ncolors=ncolors, random_state=random_state) def make_random_cmap(ncolors=256, random_state=None): """ Make a matplotlib colormap consisting of (random) muted colors. A random colormap is very useful for plotting segmentation images. Parameters ---------- ncolors : int, optional The number of colors in the colormap. The default is 256. random_state : int or `~numpy.random.mtrand.RandomState`, optional The pseudo-random number generator state used for random sampling. Separate function calls with the same ``random_state`` will generate the same colormap. Returns ------- cmap : `matplotlib.colors.ListedColormap` The matplotlib colormap with random colors. """ from matplotlib import colors prng = check_random_state(random_state) h = prng.uniform(low=0.0, high=1.0, size=ncolors) s = prng.uniform(low=0.2, high=0.7, size=ncolors) v = prng.uniform(low=0.5, high=1.0, size=ncolors) hsv = np.dstack((h, s, v)) rgb = np.squeeze(colors.hsv_to_rgb(hsv)) return colors.ListedColormap(rgb) photutils-0.7.2/photutils/utils/convolution.py0000644000214200020070000001003013572576136024073 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for convolving images with a kernel. """ import warnings from astropy.convolution import Kernel2D from astropy.units import Quantity from astropy.utils import deprecated from astropy.utils.exceptions import AstropyUserWarning import numpy as np __all__ = ['filter_data'] @deprecated('0.7') def filter_data(data, kernel, mode='constant', fill_value=0.0, check_normalization=False): """ Convolve a 2D image with a 2D kernel. The kernel may either be a 2D `~numpy.ndarray` or a `~astropy.convolution.Kernel2D` object. Parameters ---------- data : array_like The 2D array of the image. kernel : array-like (2D) or `~astropy.convolution.Kernel2D` The 2D kernel used to filter the input ``data``. Filtering the ``data`` will smooth the noise and maximize detectability of objects with a shape similar to the kernel. mode : {'constant', 'reflect', 'nearest', 'mirror', 'wrap'}, optional The ``mode`` determines how the array borders are handled. For the ``'constant'`` mode, values outside the array borders are set to ``fill_value``. The default is ``'constant'``. fill_value : scalar, optional Value to fill data values beyond the array borders if ``mode`` is ``'constant'``. The default is ``0.0``. check_normalization : bool, optional If `True` then a warning will be issued if the kernel is not normalized to 1. """ return _filter_data(data, kernel, mode=mode, fill_value=fill_value, check_normalization=check_normalization) def _filter_data(data, kernel, mode='constant', fill_value=0.0, check_normalization=False): """ Convolve a 2D image with a 2D kernel. The kernel may either be a 2D `~numpy.ndarray` or a `~astropy.convolution.Kernel2D` object. Parameters ---------- data : array_like The 2D array of the image. kernel : array-like (2D) or `~astropy.convolution.Kernel2D` The 2D kernel used to filter the input ``data``. Filtering the ``data`` will smooth the noise and maximize detectability of objects with a shape similar to the kernel. mode : {'constant', 'reflect', 'nearest', 'mirror', 'wrap'}, optional The ``mode`` determines how the array borders are handled. For the ``'constant'`` mode, values outside the array borders are set to ``fill_value``. The default is ``'constant'``. fill_value : scalar, optional Value to fill data values beyond the array borders if ``mode`` is ``'constant'``. The default is ``0.0``. check_normalization : bool, optional If `True` then a warning will be issued if the kernel is not normalized to 1. """ from scipy import ndimage if kernel is not None: if isinstance(kernel, Kernel2D): kernel_array = kernel.array else: kernel_array = kernel if check_normalization: if not np.allclose(np.sum(kernel_array), 1.0): warnings.warn('The kernel is not normalized.', AstropyUserWarning) # scipy.ndimage.convolve currently strips units, but be explicit # in case that behavior changes unit = None if isinstance(data, Quantity): unit = data.unit data = data.value # NOTE: astropy.convolution.convolve fails with zero-sum # kernels (used in findstars) (cf. astropy #1647) # NOTE: if data is int and kernel is float, ndimage.convolve # will return an int image - here we make the data float so # that a float image is always returned result = ndimage.convolve(data.astype(float), kernel_array, mode=mode, cval=fill_value) if unit is not None: result = result * unit # can't use *= with older astropy return result else: return data photutils-0.7.2/photutils/utils/errors.py0000644000214200020070000001503713563423715023036 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for calculating total error arrays. """ import astropy.units as u from astropy.utils.misc import isiterable import numpy as np __all__ = ['calc_total_error'] def calc_total_error(data, bkg_error, effective_gain): """ Calculate a total error array, combining a background-only error array with the Poisson noise of sources. Parameters ---------- data : array_like or `~astropy.units.Quantity` The data array. bkg_error : array_like or `~astropy.units.Quantity` The pixel-wise Gaussian 1-sigma background-only errors of the input ``data``. ``bkg_error`` should include all sources of "background" error but *exclude* the Poisson error of the sources. ``bkg_error`` must have the same shape as ``data``. If ``data`` and ``bkg_error`` are `~astropy.units.Quantity` objects, then they must have the same units. effective_gain : float, array-like, or `~astropy.units.Quantity` Ratio of counts (e.g., electrons or photons) to the units of ``data`` used to calculate the Poisson error of the sources. Returns ------- total_error : `~numpy.ndarray` or `~astropy.units.Quantity` The total error array. If ``data``, ``bkg_error``, and ``effective_gain`` are all `~astropy.units.Quantity` objects, then ``total_error`` will also be returned as a `~astropy.units.Quantity` object with the same units as the input ``data``. Otherwise, a `~numpy.ndarray` will be returned. Notes ----- To use units, ``data``, ``bkg_error``, and ``effective_gain`` must *all* be `~astropy.units.Quantity` objects. ``data`` and ``bkg_error`` must have the same units. A `ValueError` will be raised if only some of the inputs are `~astropy.units.Quantity` objects or if the ``data`` and ``bkg_error`` units differ. The total error array, :math:`\\sigma_{\\mathrm{tot}}` is: .. math:: \\sigma_{\\mathrm{tot}} = \\sqrt{\\sigma_{\\mathrm{bkg}}^2 + \\frac{I}{g_{\\mathrm{eff}}}} where :math:`\\sigma_{\\mathrm{bkg}}`, :math:`I`, and :math:`g_{\\mathrm{eff}}` are the background ``bkg_error`` image, ``data`` image, and ``effective_gain`` (image or scalar), respectively. ``effective_gain`` can either be a scalar value or a 2D image with the same shape as the ``data``. For example, if your input ``data`` are in units of electrons/s then ``effective_gain`` should be the exposure time or an exposure-time map. A 2D ``effective_gain`` image is useful with a ``data`` image that has variable depths across the field (e.g. a mosaic image with non-uniform exposure times). As an example, if your input ``data`` is a variable-depth mosaic image in units of electrons/s, then ``effective_gain`` should be an exposure time map. Pixels where ``data`` (:math:`I_i)` is negative are excluded from the total error calculation, i.e. :math:`\\sigma_{\\mathrm{tot}, i} = \\sigma_{\\mathrm{bkg}, i}`. Note that this is different from `SExtractor`_, which includes pixels where :math:`I_i` is negative and therefore can underestimate the total errors in such cases. To replicate `SExtractor`_ errors when it is configured to consider weight maps as gain maps (i.e. 'WEIGHT_GAIN=Y'; which is the default), one should input an ``effective_gain`` calculated as: .. math:: g_{\\mathrm{eff}}^{\\prime} = g_{\\mathrm{eff}} \\left( \\frac{\\mathrm{RMS_{\\mathrm{median}}^2}}{\\sigma_{\\mathrm{bkg}}^2} \\right) where :math:`\\sigma_{\\mathrm{bkg}}` are the background-only errors, :math:`g_{\\mathrm{eff}}` is the effective gain, and :math:`\\mathrm{RMS_{\\mathrm{median}}}` is the median value of the low-resolution background RMS map. In `SExtractor`_ this value is printed to stdout as "(M+D) RMS: ". If you are using `~photutils.background.Background2D`, the median value of the low-resolution background RMS map is returned via the `~photutils.background.Background2D.background_rms_median` attribute. In that case the total error is: .. math:: \\sigma_{\\mathrm{tot}} = \\sqrt{\\sigma_{\\mathrm{bkg}}^2 + \\left(\\frac{I}{g_{\\mathrm{eff}}}\\right) \\left(\\frac{\\sigma_{\\mathrm{bkg}}^2} {\\mathrm{RMS_{\\mathrm{median}}^2}}\\right)} .. _SExtractor: https://www.astromatic.net/software/sextractor """ data = np.asanyarray(data) bkg_error = np.asanyarray(bkg_error) inputs = [data, bkg_error, effective_gain] has_unit = [hasattr(x, 'unit') for x in inputs] use_units = all(has_unit) if any(has_unit) and not use_units: raise ValueError('If any of data, bkg_error, or effective_gain has ' 'units, then they all must all have units.') if use_units: if data.unit != bkg_error.unit: raise ValueError('data and bkg_error must have the same units.') count_units = [u.electron, u.photon] datagain_unit = data.unit * effective_gain.unit if datagain_unit not in count_units: raise u.UnitsError('(data * effective_gain) has units of "{0}", ' 'but it must have count units (e.g. ' 'u.electron or u.photon).' .format(datagain_unit)) if not isiterable(effective_gain): effective_gain = np.zeros(data.shape) + effective_gain else: effective_gain = np.asanyarray(effective_gain) if effective_gain.shape != data.shape: raise ValueError('If input effective_gain is 2D, then it must ' 'have the same shape as the input data.') if np.any(effective_gain <= 0): raise ValueError('effective_gain must be strictly positive ' 'everywhere.') # This calculation assumes that data and bkg_error have the same # units. source_variance is calculated to have units of # (data.unit)**2 so that it can be added with bkg_error**2 below. The # final returned error will have units of data.unit. np.maximum is # used to ensure that negative data values do not contribute to the # Poisson noise. if use_units: unit = data.unit data = data.value effective_gain = effective_gain.value source_variance = np.maximum(data / effective_gain, 0) * unit**2 else: source_variance = np.maximum(data / effective_gain, 0) return np.sqrt(bkg_error**2 + source_variance) photutils-0.7.2/photutils/utils/exceptions.py0000644000214200020070000000047713563423715023705 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides custom exceptions. """ from astropy.utils.exceptions import AstropyWarning __all__ = ['NoDetectionsWarning'] class NoDetectionsWarning(AstropyWarning): """ A warning class to indicate no sources were detected. """ photutils-0.7.2/photutils/utils/interpolation.py0000644000214200020070000003547313572576136024425 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools for interpolating data. """ from astropy.utils import deprecated import numpy as np __all__ = ['ShepardIDWInterpolator', 'mask_to_mirrored_num'] __doctest_requires__ = {('ShepardIDWInterpolator'): ['scipy']} __doctest_skip__ = ['mask_to_mirrored_num'] class ShepardIDWInterpolator: """ Class to perform Inverse Distance Weighted (IDW) interpolation. This interpolator uses a modified version of `Shepard's method `_ (see the Notes section for details). Parameters ---------- coordinates : float, 1D array-like, or NxM-array-like Coordinates of the known data points. In general, it is expected that these coordinates are in a form of a NxM-like array where N is the number of points and M is dimension of the coordinate space. When M=1 (1D space), then the ``coordinates`` parameter may be entered as a 1D array or, if only one data point is available, ``coordinates`` can be a scalar number representing the 1D coordinate of the data point. .. note:: If the dimensionality of ``coordinates`` is larger than 2, e.g., if it is of the form N1 x N2 x N3 x ... x Nn x M, then it will be flattened to form an array of size NxM where N = N1 * N2 * ... * Nn. values : float or 1D array-like Values of the data points corresponding to each coordinate provided in ``coordinates``. In general a 1D array is expected. When a single data point is available, then ``values`` can be a scalar number. .. note:: If the dimensionality of ``values`` is larger than 1 then it will be flattened. weights : float or 1D array-like, optional Weights to be associated with each data value. These weights, if provided, will be combined with inverse distance weights (see the Notes section for details). When ``weights`` is `None` (default), then only inverse distance weights will be used. When provided, this input parameter must have the same form as ``values``. leafsize : float, optional The number of points at which the k-d tree algorithm switches over to brute-force. ``leafsize`` must be positive. See `scipy.spatial.cKDTree` for further information. Notes ----- This interpolator uses a slightly modified version of `Shepard's method `_. The essential difference is the introduction of a "regularization" parameter (``reg``) that is used when computing the inverse distance weights: .. math:: w_i = 1 / (d(x, x_i)^{power} + r) By supplying a positive regularization parameter one can avoid singularities at the locations of the data points as well as control the "smoothness" of the interpolation (e.g., make the weights of the neighbors less varied). The "smoothness" of interpolation can also be controlled by the power parameter (``power``). Examples -------- This class can can be instantiated using the following syntax:: >>> from photutils.utils import ShepardIDWInterpolator as idw Example of interpolating 1D data:: >>> import numpy as np >>> np.random.seed(123) >>> x = np.random.random(100) >>> y = np.sin(x) >>> f = idw(x, y) >>> f(0.4) # doctest: +FLOAT_CMP 0.38862424043228855 >>> np.sin(0.4) # doctest: +FLOAT_CMP 0.3894183423086505 >>> xi = np.random.random(4) >>> xi # doctest: +FLOAT_CMP array([0.51312815, 0.66662455, 0.10590849, 0.13089495]) >>> f(xi) # doctest: +FLOAT_CMP array([0.49086423, 0.62647862, 0.1056854 , 0.13048335]) >>> np.sin(xi) # doctest: +FLOAT_CMP array([0.49090493, 0.6183367 , 0.10571061, 0.13052149]) NOTE: In the last example, ``xi`` may be a ``Nx1`` array instead of a 1D vector. Example of interpolating 2D data:: >>> pos = np.random.rand(1000, 2) >>> val = np.sin(pos[:, 0] + pos[:, 1]) >>> f = idw(pos, val) >>> f([0.5, 0.6]) # doctest: +FLOAT_CMP 0.8931264958740567 >>> np.sin(0.5 + 0.6) # doctest: +FLOAT_CMP 0.8912073600614354 """ def __init__(self, coordinates, values, weights=None, leafsize=10): from scipy.spatial import cKDTree coordinates = np.atleast_2d(coordinates) if coordinates.shape[0] == 1: coordinates = np.transpose(coordinates) if coordinates.ndim != 2: coordinates = np.reshape(coordinates, (-1, coordinates.shape[-1])) values = np.asanyarray(values).ravel() ncoords = coordinates.shape[0] if ncoords < 1: raise ValueError('You must enter at least one data point.') if values.shape[0] != ncoords: raise ValueError('The number of values must match the number ' 'of coordinates.') if weights is not None: weights = np.asanyarray(weights).ravel() if weights.shape[0] != ncoords: raise ValueError('The number of weights must match the ' 'number of coordinates.') if np.any(weights < 0.0): raise ValueError('All weight values must be non-negative ' 'numbers.') self.coordinates = coordinates self.ncoords = ncoords self.coords_ndim = coordinates.shape[1] self.values = values self.weights = weights self.kdtree = cKDTree(coordinates, leafsize=leafsize) def __call__(self, positions, n_neighbors=8, eps=0.0, power=1.0, reg=0.0, conf_dist=1e-12, dtype=float): """ Evaluate the interpolator at the given positions. Parameters ---------- positions : float, 1D array-like, or NxM-array-like Coordinates of the position(s) at which the interpolator should be evaluated. In general, it is expected that these coordinates are in a form of a NxM-like array where N is the number of points and M is dimension of the coordinate space. When M=1 (1D space), then the ``positions`` parameter may be input as a 1D-like array or, if only one data point is available, ``positions`` can be a scalar number representing the 1D coordinate of the data point. .. note:: If the dimensionality of the ``positions`` argument is larger than 2, e.g., if it is of the form N1 x N2 x N3 x ... x Nn x M, then it will be flattened to form an array of size NxM where N = N1 * N2 * ... * Nn. .. warning:: The dimensionality of ``positions`` must match the dimensionality of the ``coordinates`` used during the initialization of the interpolator. n_neighbors : int, optional The maximum number of nearest neighbors to use during the interpolation. eps : float, optional Set to use approximate nearest neighbors; the kth neighbor is guaranteed to be no further than (1 + ``eps``) times the distance to the real *k*-th nearest neighbor. See `scipy.spatial.cKDTree.query` for further information. power : float, optional The power of the inverse distance used for the interpolation weights. See the Notes section for more details. reg : float, optional The regularization parameter. It may be used to control the smoothness of the interpolator. See the Notes section for more details. conf_dist : float, optional The confusion distance below which the interpolator should use the value of the closest data point instead of attempting to interpolate. This is used to avoid singularities at the known data points, especially if ``reg`` is 0.0. dtype : data-type The data type of the output interpolated values. If `None` then the type will be inferred from the type of the ``values`` parameter used during the initialization of the interpolator. """ n_neighbors = int(n_neighbors) if n_neighbors < 1: raise ValueError('n_neighbors must be a positive integer') if conf_dist is not None and conf_dist <= 0.0: conf_dist = None positions = np.asanyarray(positions) if positions.ndim == 0: # assume we have a single 1D coordinate if self.coords_ndim != 1: raise ValueError('The dimensionality of the input position ' 'does not match the dimensionality of the ' 'coordinates used to initialize the ' 'interpolator.') elif positions.ndim == 1: # assume we have a single point if (self.coords_ndim != 1 and (positions.shape[-1] != self.coords_ndim)): raise ValueError('The input position was provided as a 1D ' 'array, but its length does not match the ' 'dimensionality of the coordinates used ' 'to initialize the interpolator.') elif positions.ndim != 2: raise ValueError('The input positions must be an array-like ' 'object of dimensionality no larger than 2.') positions = np.reshape(positions, (-1, self.coords_ndim)) npositions = positions.shape[0] distances, idx = self.kdtree.query(positions, k=n_neighbors, eps=eps) if n_neighbors == 1: return self.values[idx] if dtype is None: dtype = self.values.dtype interp_values = np.zeros(npositions, dtype=dtype) for k in range(npositions): valid_idx = np.isfinite(distances[k]) idk = idx[k][valid_idx] dk = distances[k][valid_idx] if dk.shape[0] == 0: interp_values[k] = np.nan continue if conf_dist is not None: # check if we are close to a known data point confused = (dk <= conf_dist) if np.any(confused): interp_values[k] = self.values[idk[confused][0]] continue w = 1.0 / ((dk ** power) + reg) if self.weights is not None: w *= self.weights[idk] wtot = np.sum(w) if wtot > 0.0: interp_values[k] = np.dot(w, self.values[idk]) / wtot else: interp_values[k] = np.nan if len(interp_values) == 1: return interp_values[0] else: return interp_values def _mask_to_mirrored_num(image, mask_image, center_position, bbox=None): """ Replace masked pixels with the value of the pixel mirrored across a given ``center_position``. If the mirror pixel is unavailable (i.e. itself masked or outside of the image), then the masked pixel value is set to zero. Parameters ---------- image : `numpy.ndarray`, 2D The 2D array of the image. mask_image : array-like, bool A boolean mask with the same shape as ``image``, where a `True` value indicates the corresponding element of ``image`` is considered bad. center_position : 2-tuple (x, y) center coordinates around which masked pixels will be mirrored. bbox : list, tuple, `numpy.ndarray`, optional The bounding box (x_min, x_max, y_min, y_max) over which to replace masked pixels. Returns ------- result : `numpy.ndarray`, 2D A 2D array with replaced masked pixels. """ if bbox is None: ny, nx = image.shape bbox = [0, nx, 0, ny] subdata = np.copy(image[bbox[2]:bbox[3]+1, bbox[0]:bbox[1]+1]) submask = mask_image[bbox[2]:bbox[3]+1, bbox[0]:bbox[1]+1] y_masked, x_masked = np.nonzero(submask) x_mirror = (2 * (center_position[0] - bbox[0]) - x_masked + 0.5).astype('int32') y_mirror = (2 * (center_position[1] - bbox[2]) - y_masked + 0.5).astype('int32') # Reset mirrored pixels that go out of the image. outofimage = ((x_mirror < 0) | (y_mirror < 0) | (x_mirror >= subdata.shape[1]) | (y_mirror >= subdata.shape[0])) if outofimage.any(): x_mirror[outofimage] = x_masked[outofimage].astype('int32') y_mirror[outofimage] = y_masked[outofimage].astype('int32') subdata[y_masked, x_masked] = subdata[y_mirror, x_mirror] # Set pixels that mirrored to another masked pixel to zero. # This will also set to zero any pixels that mirrored out of # the image. mirror_is_masked = submask[y_mirror, x_mirror] x_bad = x_masked[mirror_is_masked] y_bad = y_masked[mirror_is_masked] subdata[y_bad, x_bad] = 0.0 outimage = np.copy(image) outimage[bbox[2]:bbox[3]+1, bbox[0]:bbox[1]+1] = subdata return outimage @deprecated(0.7) def mask_to_mirrored_num(image, mask_image, center_position, bbox=None): """ Replace masked pixels with the value of the pixel mirrored across a given ``center_position``. If the mirror pixel is unavailable (i.e. itself masked or outside of the image), then the masked pixel value is set to zero. Parameters ---------- image : `numpy.ndarray`, 2D The 2D array of the image. mask_image : array-like, bool A boolean mask with the same shape as ``image``, where a `True` value indicates the corresponding element of ``image`` is considered bad. center_position : 2-tuple (x, y) center coordinates around which masked pixels will be mirrored. bbox : list, tuple, `numpy.ndarray`, optional The bounding box (x_min, x_max, y_min, y_max) over which to replace masked pixels. Returns ------- result : `numpy.ndarray`, 2D A 2D array with replaced masked pixels. Examples -------- >>> import numpy as np >>> from photutils.utils import mask_to_mirrored_num >>> image = np.arange(16).reshape(4, 4) >>> mask = np.zeros(image.shape, dtype=bool) >>> mask[0, 0] = True >>> mask[1, 1] = True >>> mask_to_mirrored_num(image, mask, (1.5, 1.5)) array([[15, 1, 2, 3], [ 4, 10, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15]]) """ return _mask_to_mirrored_num(image, mask_image, center_position, bbox=bbox) photutils-0.7.2/photutils/utils/misc.py0000644000214200020070000000160413572576136022456 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools to return the installed astropy and photutils versions. """ from astropy.utils import deprecated __all__ = ['get_version_info'] @deprecated('0.7') def get_version_info(): """ Return astropy and photutils versions. Returns ------- result : str The astropy and photutils versions. """ return _get_version_info() def _get_version_info(): """ Return astropy and photutils versions. Returns ------- result : str The astropy and photutils versions. """ from astropy import __version__ astropy_version = __version__ from photutils import __version__ photutils_version = __version__ return 'astropy: {0}, photutils: {1}'.format(astropy_version, photutils_version) photutils-0.7.2/photutils/utils/stats.py0000644000214200020070000000717413572576136022671 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides tools to calculate statistics. """ from astropy.utils import deprecated import numpy as np __all__ = ['std_blocksum'] def _mesh_values(data, box_size): """ Extract all the data values in boxes of size ``box_size``. Values from incomplete boxes, either because of the image edges or masked pixels, are not returned. Parameters ---------- data : 2D `~numpy.ma.MaskedArray` The input masked array. box_size : int The box size. Returns ------- result : 2D `~numpy.ndarray` A 2D array containing the data values in the boxes (along the x axis). """ data = np.ma.asanyarray(data) ny, nx = data.shape nyboxes = ny // box_size nxboxes = nx // box_size # include only complete boxes ny_crop = nyboxes * box_size nx_crop = nxboxes * box_size data = data[0:ny_crop, 0:nx_crop] # a reshaped 2D masked array with mesh data along the x axis data = np.ma.swapaxes(data.reshape( nyboxes, box_size, nxboxes, box_size), 1, 2).reshape( nyboxes * nxboxes, box_size * box_size) # include only boxes without any masked pixels idx = np.where(np.ma.count_masked(data, axis=1) == 0) return data[idx] @deprecated('0.7') def std_blocksum(data, block_sizes, mask=None): """ Calculate the standard deviation of block-summed data values at sizes of ``block_sizes``. Values from incomplete blocks, either because of the image edges or masked pixels, are not included. Parameters ---------- data : array-like The 2D array to block sum. block_sizes : int, array-like of int An array of integer (square) block sizes. mask : array-like (bool), optional A boolean mask, with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Blocks that contain *any* masked data are excluded from calculations. Returns ------- result : `~numpy.ndarray` An array of the standard deviations of the block-summed array for the input ``block_sizes``. """ return _std_blocksum(data, block_sizes, mask=mask) def _std_blocksum(data, block_sizes, mask=None): """ Calculate the standard deviation of block-summed data values at sizes of ``block_sizes``. Values from incomplete blocks, either because of the image edges or masked pixels, are not included. Parameters ---------- data : array-like The 2D array to block sum. block_sizes : int, array-like of int An array of integer (square) block sizes. mask : array-like (bool), optional A boolean mask, with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Blocks that contain *any* masked data are excluded from calculations. Returns ------- result : `~numpy.ndarray` An array of the standard deviations of the block-summed array for the input ``block_sizes``. """ data = np.ma.asanyarray(data) if mask is not None and mask is not np.ma.nomask: mask = np.asanyarray(mask) if data.shape != mask.shape: raise ValueError('data and mask must have the same shape.') data.mask |= mask stds = [] block_sizes = np.atleast_1d(block_sizes) for block_size in block_sizes: mesh_values = _mesh_values(data, block_size) block_sums = np.sum(mesh_values, axis=1) stds.append(np.std(block_sums)) return np.array(stds) photutils-0.7.2/photutils/utils/tests/0000755000214200020070000000000013573510273022301 5ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/utils/tests/__init__.py0000644000214200020070000000000013563423715024403 0ustar lbradleySTSCI\science00000000000000photutils-0.7.2/photutils/utils/tests/test_colormaps.py0000644000214200020070000000106413563423715025715 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the colormaps module. """ from numpy.testing import assert_allclose import pytest from ..colormaps import make_random_cmap try: import matplotlib # noqa HAS_MATPLOTLIB = True except ImportError: HAS_MATPLOTLIB = False @pytest.mark.skipif('not HAS_MATPLOTLIB') def test_colormap(): ncolors = 100 cmap = make_random_cmap(ncolors, random_state=12345) assert len(cmap.colors) == ncolors assert_allclose(cmap.colors[0], [0.9234715, 0.64837165, 0.76454726]) photutils-0.7.2/photutils/utils/tests/test_convolution.py0000644000214200020070000000457113572576136026311 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the convolution module. """ from astropy.convolution import Gaussian2DKernel from astropy.tests.helper import catch_warnings import astropy.units as u from astropy.utils.exceptions import AstropyUserWarning from numpy.testing import assert_allclose import pytest from ..convolution import _filter_data from ...datasets import make_100gaussians_image try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False @pytest.mark.skipif('not HAS_SCIPY') class TestFilterData: def setup_class(self): self.data = make_100gaussians_image() self.kernel = Gaussian2DKernel(3., x_size=3, y_size=3) def test_filter_data(self): filt_data1 = _filter_data(self.data, self.kernel) filt_data2 = _filter_data(self.data, self.kernel.array) assert_allclose(filt_data1, filt_data2) def test_filter_data_units(self): unit = u.electron filt_data = _filter_data(self.data * unit, self.kernel) assert isinstance(filt_data, u.Quantity) assert filt_data.unit == unit def test_filter_data_types(self): """ Test to ensure output is a float array for integer input data. """ filt_data = _filter_data(self.data.astype(int), self.kernel.array.astype(int)) assert filt_data.dtype == float filt_data = _filter_data(self.data.astype(int), self.kernel.array.astype(float)) assert filt_data.dtype == float filt_data = _filter_data(self.data.astype(float), self.kernel.array.astype(int)) assert filt_data.dtype == float filt_data = _filter_data(self.data.astype(float), self.kernel.array.astype(float)) assert filt_data.dtype == float def test_filter_data_kernel_none(self): """ Test for kernel=None. """ kernel = None filt_data = _filter_data(self.data, kernel) assert_allclose(filt_data, self.data) def test_filter_data_check_normalization(self): """ Test kernel normalization check. """ with catch_warnings(AstropyUserWarning) as w: _filter_data(self.data, self.kernel, check_normalization=True) assert len(w) == 1 photutils-0.7.2/photutils/utils/tests/test_errors.py0000644000214200020070000000460613563423715025237 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the errors module. """ import astropy.units as u import numpy as np from numpy.testing import assert_allclose import pytest from ..errors import calc_total_error SHAPE = (5, 5) DATAVAL = 2. DATA = np.ones(SHAPE) * DATAVAL MASK = np.zeros(DATA.shape, dtype=bool) MASK[2, 2] = True BKG_ERROR = np.ones(SHAPE) EFFGAIN = np.ones(SHAPE) * DATAVAL BACKGROUND = np.ones(SHAPE) WRONG_SHAPE = np.ones((2, 2)) class TestCalculateTotalError: def test_error_shape(self): with pytest.raises(ValueError): calc_total_error(DATA, WRONG_SHAPE, EFFGAIN) def test_gain_shape(self): with pytest.raises(ValueError): calc_total_error(DATA, BKG_ERROR, WRONG_SHAPE) @pytest.mark.parametrize('effective_gain', (0, -1)) def test_gain_le_zero(self, effective_gain): with pytest.raises(ValueError): calc_total_error(DATA, BKG_ERROR, effective_gain) def test_gain_scalar(self): error_tot = calc_total_error(DATA, BKG_ERROR, 2.) assert_allclose(error_tot, np.sqrt(2.) * BKG_ERROR) def test_gain_array(self): error_tot = calc_total_error(DATA, BKG_ERROR, EFFGAIN) assert_allclose(error_tot, np.sqrt(2.) * BKG_ERROR) def test_units(self): units = u.electron / u.s error_tot1 = calc_total_error(DATA * units, BKG_ERROR * units, EFFGAIN * u.s) assert error_tot1.unit == units error_tot2 = calc_total_error(DATA, BKG_ERROR, EFFGAIN) assert_allclose(error_tot1.value, error_tot2) def test_error_units(self): units = u.electron / u.s with pytest.raises(ValueError): calc_total_error(DATA * units, BKG_ERROR * u.electron, EFFGAIN * u.s) def test_effgain_units(self): units = u.electron / u.s with pytest.raises(u.UnitsError): calc_total_error(DATA * units, BKG_ERROR * units, EFFGAIN * u.km) def test_missing_bkgerror_units(self): units = u.electron / u.s with pytest.raises(ValueError): calc_total_error(DATA * units, BKG_ERROR, EFFGAIN * u.s) def test_missing_effgain_units(self): units = u.electron / u.s with pytest.raises(ValueError): calc_total_error(DATA * units, BKG_ERROR * units, EFFGAIN) photutils-0.7.2/photutils/utils/tests/test_interpolation.py0000644000214200020070000001277313572576136026624 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the interpolation module. """ import warnings from astropy.utils.exceptions import AstropyDeprecationWarning import numpy as np from numpy.testing import assert_allclose import pytest from .. import ShepardIDWInterpolator as idw from ..interpolation import _mask_to_mirrored_num try: import scipy # noqa HAS_SCIPY = True except ImportError: HAS_SCIPY = False SHAPE = (5, 5) DATA = np.ones(SHAPE) * 2.0 MASK = np.zeros(DATA.shape, dtype=bool) MASK[2, 2] = True ERROR = np.ones(SHAPE) BACKGROUND = np.ones(SHAPE) WRONG_SHAPE = np.ones((2, 2)) @pytest.mark.skipif('not HAS_SCIPY') class TestShepardIDWInterpolator: def setup_class(self): np.random.seed(123) self.x = np.random.random(100) self.y = np.sin(self.x) self.f = idw(self.x, self.y) @pytest.mark.parametrize('positions', [0.4, np.arange(2, 5)*0.1]) def test_idw_1d(self, positions): f = idw(self.x, self.y) assert_allclose(f(positions), np.sin(positions), atol=1e-2) def test_idw_weights(self): weights = self.y * 0.1 f = idw(self.x, self.y, weights=weights) pos = 0.4 assert_allclose(f(pos), np.sin(pos), atol=1e-2) def test_idw_2d(self): pos = np.random.rand(1000, 2) val = np.sin(pos[:, 0] + pos[:, 1]) f = idw(pos, val) x = 0.5 y = 0.6 assert_allclose(f([x, y]), np.sin(x + y), atol=1e-2) def test_idw_3d(self): val = np.ones((3, 3, 3)) pos = np.indices(val.shape) f = idw(pos, val) assert_allclose(f([0.5, 0.5, 0.5]), 1.0) def test_no_coordinates(self): with pytest.raises(ValueError): idw([], 0) def test_values_invalid_shape(self): with pytest.raises(ValueError): idw(self.x, 0) def test_weights_invalid_shape(self): with pytest.raises(ValueError): idw(self.x, self.y, weights=10) def test_weights_negative(self): with pytest.raises(ValueError): idw(self.x, self.y, weights=-self.y) def test_n_neighbors_one(self): assert_allclose(self.f(0.5, n_neighbors=1), 0.48103656) def test_n_neighbors_negative(self): with pytest.raises(ValueError): self.f(0.5, n_neighbors=-1) def test_conf_dist_negative(self): assert_allclose(self.f(0.5, conf_dist=-1), self.f(0.5, conf_dist=None)) def test_dtype_none(self): result = self.f(0.5, dtype=None) assert result.dtype == float def test_positions_0d_nomatch(self): """test when position ndim doesn't match coordinates ndim""" pos = np.random.rand(10, 2) val = np.sin(pos[:, 0] + pos[:, 1]) f = idw(pos, val) with pytest.raises(ValueError): f(0.5) def test_positions_1d_nomatch(self): """test when position ndim doesn't match coordinates ndim""" pos = np.random.rand(10, 2) val = np.sin(pos[:, 0] + pos[:, 1]) f = idw(pos, val) with pytest.raises(ValueError): f([0.5]) def test_positions_3d(self): with pytest.raises(ValueError): self.f(np.ones((3, 3, 3))) class TestMaskToMirroredNum: def setup_class(cls): """Ignore all deprecation warnings here.""" warnings.simplefilter('ignore', AstropyDeprecationWarning) def test_mask_to_mirrored_num(self): """ Test mask_to_mirrored_num. """ center = (1.5, 1.5) data = np.arange(16).reshape(4, 4) mask = np.zeros(data.shape, dtype=bool) mask[0, 0] = True mask[1, 1] = True data_ref = data.copy() data_ref[0, 0] = data[3, 3] data_ref[1, 1] = data[2, 2] mirror_data = _mask_to_mirrored_num(data, mask, center) assert_allclose(mirror_data, data_ref, rtol=0, atol=1.e-6) def test_mask_to_mirrored_num_range(self): """ Test mask_to_mirrored_num when mirrored pixels are outside of the image. """ center = (2.5, 2.5) data = np.arange(16).reshape(4, 4) mask = np.zeros(data.shape, dtype=bool) mask[0, 0] = True mask[1, 1] = True data_ref = data.copy() data_ref[0, 0] = 0. data_ref[1, 1] = 0. mirror_data = _mask_to_mirrored_num(data, mask, center) assert_allclose(mirror_data, data_ref, rtol=0, atol=1.e-6) def test_mask_to_mirrored_num_masked(self): """ Test mask_to_mirrored_num when mirrored pixels are also masked. """ center = (0.5, 0.5) data = np.arange(16).reshape(4, 4) data[0, 0] = 100 mask = np.zeros(data.shape, dtype=bool) mask[0, 0] = True mask[1, 1] = True data_ref = data.copy() data_ref[0, 0] = 0. data_ref[1, 1] = 0. mirror_data = _mask_to_mirrored_num(data, mask, center) assert_allclose(mirror_data, data_ref, rtol=0, atol=1.e-6) def test_mask_to_mirrored_num_bbox(self): """ Test mask_to_mirrored_num with a bounding box. """ center = (1.5, 1.5) data = np.arange(16).reshape(4, 4) data[0, 0] = 100 mask = np.zeros(data.shape, dtype=bool) mask[0, 0] = True mask[1, 1] = True data_ref = data.copy() data_ref[1, 1] = data[2, 2] bbox = (1, 2, 1, 2) mirror_data = _mask_to_mirrored_num(data, mask, center, bbox=bbox) assert_allclose(mirror_data, data_ref, rtol=0, atol=1.e-6) photutils-0.7.2/photutils/utils/tests/test_moments.py0000644000214200020070000000220613563423715025377 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the moments module. """ import numpy as np from numpy.testing import assert_equal, assert_allclose import pytest from .._moments import _moments, _moments_central def test_moments(): data = np.array([[0, 1], [0, 1]]) moments = _moments(data, order=2) result = np.array([[2, 2, 2], [1, 1, 1], [1, 1, 1]]) assert_equal(moments, result) assert_allclose(moments[0, 1] / moments[0, 0], 1.0) assert_allclose(moments[1, 0] / moments[0, 0], 0.5) def test_moments_central(): data = np.array([[0, 1], [0, 1]]) moments = _moments_central(data, order=2) result = np.array([[2., 0., 0.], [0., 0., 0.], [0.5, 0., 0.]]) assert_allclose(moments, result) def test_moments_central_nonsquare(): data = np.array([[0, 1], [0, 1], [0, 1]]) moments = _moments_central(data, order=2) result = np.array([[3., 0., 0.], [0., 0., 0.], [2., 0., 0.]]) assert_allclose(moments, result) def test_moments_central_invalid_dim(): data = np.arange(27).reshape(3, 3, 3) with pytest.raises(ValueError): _moments_central(data, order=3) photutils-0.7.2/photutils/utils/tests/test_random_state.py0000644000214200020070000000102413563423715026372 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the random_state module. """ import numpy as np import pytest from .. import check_random_state @pytest.mark.parametrize('seed', [None, np.random, 1, np.random.RandomState(1)]) def test_seed(seed): assert isinstance(check_random_state(seed), np.random.RandomState) @pytest.mark.parametrize('seed', [1., [1, 2]]) def test_invalid_seed(seed): with pytest.raises(ValueError): check_random_state(seed) photutils-0.7.2/photutils/utils/tests/test_stats.py0000644000214200020070000000171313572576136025063 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Tests for the stats module. """ import numpy as np from numpy.testing import assert_allclose import pytest from ..stats import _std_blocksum from ...datasets import make_noise_image def test_std_blocksum(): stddev = 5 data = make_noise_image((100, 100), mean=0, stddev=stddev, random_state=12345) block_sizes = np.array([5, 7, 10]) stds = _std_blocksum(data, block_sizes) expected = np.array([stddev, stddev, stddev]) assert_allclose(stds / block_sizes, expected, atol=0.2) mask = np.zeros(data.shape, dtype=bool) mask[25:50, 25:50] = True stds2 = _std_blocksum(data, block_sizes, mask=mask) assert_allclose(stds2 / block_sizes, expected, atol=0.3) def test_std_blocksum_mask_shape(): with pytest.raises(ValueError): data = np.ones((10, 10)) mask = np.ones((2, 2)) _std_blocksum(data, 10, mask=mask) photutils-0.7.2/photutils/utils/wcs_helpers.py0000644000214200020070000000745213572576136024050 0ustar lbradleySTSCI\science00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module provides WCS helper tools. """ from astropy import units as u from astropy.utils import deprecated from ._wcs_helpers import _pixel_to_world, _pixel_scale_angle_at_skycoord @deprecated('0.7', 'The pixel_scale_angle_at_skycoord function is deprecated ' 'and will be removed in v0.8') def pixel_scale_angle_at_skycoord(skycoord, wcs, offset=1. * u.arcsec): """ Calculate the pixel scale and WCS rotation angle at the position of a SkyCoord coordinate. Parameters ---------- skycoord : `~astropy.coordinates.SkyCoord` The SkyCoord coordinate. wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). offset : `~astropy.units.Quantity` A small angular offset to use to compute the pixel scale and position angle. Returns ------- scale : `~astropy.units.Quantity` The pixel scale in arcsec/pixel. angle : `~astropy.units.Quantity` The angle (in degrees) measured counterclockwise from the positive x axis to the "North" axis of the celestial coordinate system. Notes ----- If distortions are present in the image, the x and y pixel scales likely differ. This function computes a single pixel scale along the North/South axis. """ return _pixel_scale_angle_at_skycoord(skycoord, wcs, offset=offset) @deprecated('0.7', 'The assert_angle_or_pixel function is deprecated and ' 'will be removed in v0.8') def assert_angle_or_pixel(name, q): """ Check that ``q`` is either an angular or a pixel :class:`~astropy.units.Quantity`. """ if isinstance(q, u.Quantity): if q.unit.physical_type == 'angle' or q.unit == u.pixel: pass else: raise ValueError("{0} should have angular or pixel " "units".format(name)) else: raise TypeError("{0} should be a Quantity instance".format(name)) @deprecated('0.7', 'The assert_angle function is deprecated and will be ' 'removed in v0.8') def assert_angle(name, q): """ Check that ``q`` is an angular :class:`~astropy.units.Quantity`. """ if isinstance(q, u.Quantity): if q.unit.physical_type == 'angle': pass else: raise ValueError("{0} should have angular units".format(name)) else: raise TypeError("{0} should be a Quantity instance".format(name)) @deprecated('0.7', 'The pixel_to_icrs_coords function is deprecated and will ' 'be removed in v0.8') def pixel_to_icrs_coords(x, y, wcs): """ Convert pixel coordinates to ICRS Right Ascension and Declination. This is merely a convenience function to extract RA and Dec. from a `~astropy.coordinates.SkyCoord` instance so they can be put in separate columns in a `~astropy.table.Table`. Parameters ---------- x : float or array-like The x pixel coordinate. y : float or array-like The y pixel coordinate. wcs : WCS object A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS `_ (e.g. `astropy.wcs.WCS`, `gwcs.wcs.WCS`). Returns ------- ra : `~astropy.units.Quantity` The ICRS Right Ascension in degrees. dec : `~astropy.units.Quantity` The ICRS Declination in degrees. """ icrs_coords = (_pixel_to_world(x, y, wcs)).icrs icrs_ra = icrs_coords.ra.degree * u.deg icrs_dec = icrs_coords.dec.degree * u.deg return icrs_ra, icrs_dec photutils-0.7.2/photutils/version.py0000644000214200020070000000056613573510264022045 0ustar lbradleySTSCI\science00000000000000# Autogenerated by Astropy-affiliated package photutils's setup.py on 2019-12-09 18:21:40 UTC import datetime version = "0.7.2" githash = "885aee002153269aee15c5923c662c48ad132532" major = 0 minor = 7 bugfix = 2 version_info = (major, minor, bugfix) release = True timestamp = datetime.datetime(2019, 12, 9, 18, 21, 40) debug = False astropy_helpers_version = "3.2.1" photutils-0.7.2/setup.cfg0000644000214200020070000000435013573510173017566 0ustar lbradleySTSCI\science00000000000000[metadata] name = photutils provides = photutils version = 0.7.2 author = Photutils Developers author_email = photutils.team@gmail.com license = BSD 3-Clause License license_file = LICENSE.rst url = https://github.com/astropy/photutils github_project = astropy/photutils edit_on_github = False description = An Astropy package for source detection and photometry long_description = file: README.rst long_description_content_type = text/x-rst keywords = astronomy, astrophysics, photometry, aperture, psf, source detection, background, segmentation, centroids, isophote, morphology classifiers = Intended Audience :: Science/Research License :: OSI Approved :: BSD License Natural Language :: English Operating System :: OS Independent Programming Language :: Cython Programming Language :: Python Programming Language :: Python :: 3 Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: Implementation :: CPython Topic :: Scientific/Engineering :: Astronomy [options] python_requires = >=3.5 packages = find: setup_requires = numpy>=1.13 install_requires = numpy>=1.13 astropy>=2.0.12,!=3.0.*,!=3.1,!=3.1.1 tests_require = pytest pytest-remotedata pytest-doctestplus coverage zip_safe = False [options.extras_require] all = scipy matplotlib>=2.2 scikit-image>=0.14.2 scikit-learn gwcs>=0.11 docs = sphinx sphinx-astropy scipy matplotlib>=2.2 scikit-image>=0.14.2 scikit-learn test = pytest-remotedata pytest-doctestplus pytest-xdist coverage scipy matplotlib>=2.2 scikit-image>=0.14.2 scikit-learn gwcs>=0.11 [options.package_data] * = *.c photutils.datasets = data/* photutils.detection.tests = data/* photutils.isophote.tests = data/* photutils.tests = coveragerc photutils = CITATION [build_sphinx] source-dir = docs build-dir = docs/_build all_files = 1 [build_docs] source-dir = docs build-dir = docs/_build all_files = 1 [tool:pytest] minversion = 3.1 testpaths = "photutils" "docs" norecursedirs = "docs[\/]_build" "photutils[\/]extern" doctest_plus = enabled addopts = -p no:warnings [ah_bootstrap] auto_use = True photutils-0.7.2/setup.py0000744000214200020070000000346413563423715017471 0ustar lbradleySTSCI\science00000000000000#!/usr/bin/env python # Licensed under a 3-clause BSD style license - see LICENSE.rst import builtins import os # Ensure that astropy-helpers is available import ah_bootstrap # noqa from setuptools import setup from setuptools.config import read_configuration from astropy_helpers.distutils_helpers import is_distutils_display_option from astropy_helpers.setup_helpers import register_commands, get_package_info from astropy_helpers.version_helpers import generate_version_py # 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_ = read_configuration('setup.cfg')['metadata']['name'] # Create a dictionary with setup command overrides. Note that this gets # information about the package (name and version) from the setup.cfg file. cmdclassd = register_commands() # Freeze build information in version.py. Note that this gets information # about the package (name and version) from the setup.cfg file. version = generate_version_py() # 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() if is_distutils_display_option(): # Avoid installing setup_requires dependencies if the user just # queries for information setup_requires = [] else: setup_requires = read_configuration('setup.cfg')['options']['setup_requires'] # Make sure we have the packages needed for building photuils, but do not # require them when installing from an sdist as the c files are included. if not os.path.exists(os.path.join(os.path.dirname(__file__), 'PKG-INFO')): setup_requires.extend(['cython>=0.28']) setup(setup_requires=setup_requires, version=version, cmdclass=cmdclassd, **package_info)