[pyresample] 01/07: New upstream version 1.5.0
Antonio Valentino
a_valentino-guest at moszumanska.debian.org
Sun Jun 4 16:02:44 UTC 2017
This is an automated email from the git hooks/post-receive script.
a_valentino-guest pushed a commit to branch master
in repository pyresample.
commit ace2314e86ba5b8ffb481d0f2ee902a91e7d5367
Author: Antonio Valentino <antonio.valentino at tiscali.it>
Date: Sun Jun 4 09:04:09 2017 +0000
New upstream version 1.5.0
---
.bumpversion.cfg | 2 +-
.travis.yml | 8 +-
appveyor.yml | 1 +
changelog.rst | 414 ++++++----------------------------
docs/areas.yaml | 30 +++
docs/requirements.txt | 1 +
docs/source/geo_def.rst | 216 ++++++++++++------
pyresample/bilinear/__init__.py | 30 ++-
pyresample/data_reduce.py | 81 ++++---
pyresample/ewa/__init__.py | 36 ++-
pyresample/geometry.py | 193 +++++++++++++++-
pyresample/test/test_ewa_fornav.py | 34 +++
pyresample/test/test_ewa_ll2cr.py | 33 +++
pyresample/test/test_files/areas.yaml | 30 +++
pyresample/test/test_geometry.py | 186 ++++++++++++++-
pyresample/test/test_utils.py | 53 +++--
pyresample/utils.py | 78 +++++--
pyresample/version.py | 2 +-
setup.py | 3 +-
19 files changed, 912 insertions(+), 519 deletions(-)
diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 3553896..4eee916 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
[bumpversion]
-current_version = 1.3.0
+current_version = 1.5.0
commit = True
tag = True
diff --git a/.travis.yml b/.travis.yml
index 78fb339..6693de1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,5 @@
language: python
python:
-- '2.6'
- '2.7'
- '3.3'
- '3.4'
@@ -11,11 +10,6 @@ before_install:
- sudo apt-get install libfreetype6-dev
- sudo apt-get install libgeos-3.3.8 libgeos-c1 libgeos-dev
install:
-- if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install "matplotlib<1.5.0"; fi
-- if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install unittest2; fi
-- if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install importlib; fi
-- if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install "sphinx<1.5.0"; fi
-- if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install "pillow<4.0.0"; fi
- if [[ $TRAVIS_PYTHON_VERSION == "2.7" ]]; then pip install "matplotlib>=1.5.0"; fi
- if [[ $TRAVIS_PYTHON_VERSION == "2.7" ]]; then pip install "sphinx>=1.5.0"; fi
- if [[ $TRAVIS_PYTHON_VERSION == "3.3" ]]; then pip install "matplotlib<1.5.0"; fi
@@ -29,7 +23,7 @@ install:
- pip install coveralls
script:
# Once doctests pass this should be uncommented to replace the other coverage run line
-- coverage run --source=pyresample setup.py test && cd docs && mkdir doctest && sphinx-build -E -n -b doctest ./source ./doctest
+- coverage run --source=pyresample setup.py test && cd docs && mkdir doctest && sphinx-build -E -n -b doctest ./source ./doctest && cd ..
after_success: coveralls
notifications:
slack: pytroll:96mNSYSI1dBjGyzVXkBT6qFt
diff --git a/appveyor.yml b/appveyor.yml
index b85c25e..ef6de64 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -67,6 +67,7 @@ install:
- "conda create -q --yes -n test python=%PYTHON_VERSION% basemap-data-hires sphinx pyproj scipy pykdtree"
- "activate test"
- "pip install coveralls"
+ - "pip install mock"
- "where python"
build: false # Not a C# project, build stuff at the test step instead.
diff --git a/changelog.rst b/changelog.rst
index 5a68a7a..d45d4ca 100644
--- a/changelog.rst
+++ b/changelog.rst
@@ -1,35 +1,85 @@
Changelog
=========
-v1.3.0 (2017-02-07)
+
+v1.5.0 (2017-05-02)
-------------------
+- update changelog. [Martin Raspaud]
+- Bump version: 1.4.1 → 1.5.0. [Martin Raspaud]
+- Merge pull request #58 from pytroll/feature-yaml-areas. [David Hoese]
+
+ Add support for areas in yaml format
+- Remove support for python 2.6. [Martin Raspaud]
+- Explain that x/y can be lon/lat. [Martin Raspaud]
+- Fix __str__ and dump of area defs to be more explicit. [Martin
+ Raspaud]
+- Add missing doctest file. [Martin Raspaud]
+- Add yaml as a requirement. [Martin Raspaud]
+- Add support for areas in yaml format. [Martin Raspaud]
+- Fix travis script not going back to base directory for coveralls to
+ work. [davidh-ssec]
+
+ Sphinx was used for testing and included a `cd` command but that made coveralls unable to find the .coverage output.
+ (cherry picked from commit 33e692a)
+
+- Replace dict comprehension for 2.6 compatibility. [davidh-ssec]
+- Add basic ll2cr and fornav wrapper tests. [davidh-ssec]
+
+
+v1.4.1 (2017-04-07)
+-------------------
- update changelog. [Martin Raspaud]
+- Bump version: 1.4.0 → 1.4.1. [Martin Raspaud]
+- Fix non-contiguous arrays passed to EWA resampling. [davidh-ssec]
+
+ Includes fixes for tuple `out` and proper passing of keyword arguments
+
+- Ensure pyproj gets ndarrays with np.nans instead of masked arrays.
+ [Panu Lahtinen]
+- Handle older numpy versions without "copy" kwrd in .astype() [Panu
+ Lahtinen]
+
+
+v1.4.0 (2017-04-02)
+-------------------
+- update changelog. [Martin Raspaud]
+- Bump version: 1.3.1 → 1.4.0. [Martin Raspaud]
+- Add mock to appveyor. [Martin Raspaud]
+- Fix 2.6 compatibility. [Martin Raspaud]
+- Add StackedAreaDefinition class and helper functions. [Martin Raspaud]
+
+
+v1.3.1 (2017-03-22)
+-------------------
+- update changelog. [Martin Raspaud]
+- Bump version: 1.3.0 → 1.3.1. [Martin Raspaud]
+- Handle TypeError raised by case where all values are masked. [Panu
+ Lahtinen]
+- Remove trailing spaces in data_reduce.py. [Martin Raspaud]
+- Fix data reduction when poles are within area. [Martin Raspaud]
+- Make rtd happy with a new requirements file. [Martin Raspaud]
+- add pytroll's pykdtree to requirements.txt. [Martin Raspaud]
-- Bump version: 1.2.9 → 1.3.0. [Martin Raspaud]
+v1.3.0 (2017-02-07)
+-------------------
+- update changelog. [Martin Raspaud]
+- Bump version: 1.2.9 → 1.3.0. [Martin Raspaud]
- Merge pull request #55 from pytroll/feature-bilinear. [Martin Raspaud]
Feature bilinear
-
- Add Python2 miniconda version number. [Panu Lahtinen]
-
- Rename *area_in* to *source_geo_def* and *area_out* to
*target_area_def* [Panu Lahtinen]
-
- Fix search radius from 50e5 meters to 50e3 meters. [Panu Lahtinen]
-
- Add access to kd_tree parameters reduce_data, segments and epsilon.
[Panu Lahtinen]
-
- Add missing return value to docstring. [Panu Lahtinen]
-
- Remove possibility to use tuple of coordinates as "in_area" [Panu
Lahtinen]
-
- Try if older version of Pillow is installable with Python 2.6. [Panu
Lahtinen]
-
- Remove obsolete tests + minor adjustments + comments. [Panu Lahtinen]
Remove tests for functions that were removed. Add test for getting
@@ -37,9 +87,7 @@ v1.3.0 (2017-02-07)
that small variations doesn't cause failures when solving the quadratic
equation. Check all pixels of the output in test_get_bil_info().
-
- Adjust order so that most common case is first. [Panu Lahtinen]
-
- Remove parallelity checks. [Panu Lahtinen]
Don't bother checking if lines area parallel, just run the most common
@@ -47,14 +95,10 @@ v1.3.0 (2017-02-07)
consecutively for those where no valid data is yet present (ie. have
np.nan).
-
- Test failure of _get_ts_irregular when verticals are parallel. [Panu
Lahtinen]
-
- Refactor numpyfying. [Panu Lahtinen]
-
- Clarify function name. [Panu Lahtinen]
-
- Refactor. [Panu Lahtinen]
Move common parts of _get_ts_irregular() and _get_ts_uprights_parallel()
@@ -62,68 +106,42 @@ v1.3.0 (2017-02-07)
one to solve the other fractional distance not solved from the quadratic
equation.
-
- Fix example code. [Panu Lahtinen]
-
- Enable doctest for resampling from bilinear coefficients. [Panu
Lahtinen]
-
- Fix unittest which had wrong "correct" value. [Panu Lahtinen]
-
- Replace np.ma.masked_where() with np.ma.masked_invalid() [Panu
Lahtinen]
-
- Move input checks to a function. [Panu Lahtinen]
-
- Add more unit tests. [Panu Lahtinen]
-
- Move check of source area to get_bil_info() [Panu Lahtinen]
-
- Ensure data is not a masked array. [Panu Lahtinen]
-
- Remove indexing which isn't used. [Panu Lahtinen]
-
- Unpack result one step further to get a float instead of ndarray.
[Panu Lahtinen]
-
- Mask out warnings about invalid values in less and greater. [Panu
Lahtinen]
-
- Documentation for pyresample.bilinear. [Panu Lahtinen]
-
- Add few tests for bilinear interpolation. [Panu Lahtinen]
-
- Fix typos, fix _get_ts_parallellogram() [Panu Lahtinen]
-
- Adjust comment. [Panu Lahtinen]
-
- Ignore messages about invalid values due to np.nan. [Panu Lahtinen]
-
- Handle cases with parallel sides in the rectangle formed by
neighbours. [Panu Lahtinen]
-
- Make it possible to give input coordinates instead of area definition.
[Panu Lahtinen]
-
- Fixes: check for # datasets, output shape for multiple datasets,
masking, make output reshaping optional. [Panu Lahtinen]
-
- Add convenience function resample_bilinear(), remove unused logging.
[Panu Lahtinen]
-
- Rename get_corner() as _get_corner() [Panu Lahtinen]
-
- Add better docstrings, rename helper functions private. [Panu
Lahtinen]
-
- Cleanup code. [Panu Lahtinen]
-
- Extend docstrings, add a keyword to return masked arrays or arrays
with np.nan:s. [Panu Lahtinen]
-
- Add default value for search radius, adjust default number of
neighbours. [Panu Lahtinen]
-
- Initial version of bilinear resampling. [Panu Lahtinen]
NOTE: Only works if both source and destination are area definitions.
@@ -131,68 +149,51 @@ v1.3.0 (2017-02-07)
linear solution of bx + c = 0), testing, logging and all the error
handling.
-
- Allow areas to be flipped. [Martin Raspaud]
-
- Factorize get_xy_from_lonlat and get_xy_from_proj_coords. [Martin
Raspaud]
-
- Remove `fill_value` documentation for get_neighbour_info. [davidh-
ssec]
Fix #50
+
v1.2.9 (2016-12-13)
-------------------
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.2.8 → 1.2.9. [Martin Raspaud]
-
- Merge pull request #52 from mitkin/mitkin-pr-setuptools32. [Martin
Raspaud]
Specify minimum version of setuptools
-
- Specify minimum version of setuptools. [Mikhail Itkin]
Prior to version 3.2 setuptools would not recognize correctly the language of `*.cpp` extensions and would assume it's `*.c` no matter what. Version 3.2 of setuptools fixes that.
-
- Fix sphinx dependency to support python 2.6 and 3.3. [Martin Raspaud]
+
v1.2.8 (2016-12-06)
-------------------
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.2.7 → 1.2.8. [Martin Raspaud]
-
- Correct style in setup.py. [Martin Raspaud]
-
- Make pykdtree a requirement. [Martin Raspaud]
-
- Correct style in geometry.py. [Martin Raspaud]
-
- Allow precision errors when comparing area_extents. [Martin Raspaud]
-
- Allow numbers in proj dict when building proj4 string. [Martin
Raspaud]
+
v1.2.7 (2016-11-15)
-------------------
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.2.6 → 1.2.7. [Martin Raspaud]
-
- Add bump and changelog config files. [Martin Raspaud]
-
- Merge pull request #49 from Funkensieper/fix-polygon-area. [Martin
Raspaud]
Fix polygon area
-
- Disable snapping of angles in get_polygon_area() [Stephan
Finkensieper]
@@ -201,7 +202,6 @@ v1.2.7 (2016-11-15)
prevent negative area values
- Adjust reference values in tests on overlap-rate
-
- Fix polygon area computation for R != 1. [Stephan Finkensieper]
Parentheses were missing, see
@@ -211,25 +211,20 @@ v1.2.7 (2016-11-15)
for reference. Only affects earth radius R != 1 which is not
implemented yet.
-
- Install pykdtree from conda forge in pre-master. [davidh-ssec]
-
- Merge pull request #47 from mitkin/feature_plot-cmap. [David Hoese]
Add option to choose colormap
-
- Add option to choose colormap. [Mikhail Itkin]
Make possible to indicate which colormap to use when plotting image
+
v1.2.6 (2016-10-19)
-------------------
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.2.5 → 1.2.6. [Martin Raspaud]
-
- Pre master (#44) [Radar, Satellite and Nowcasting Division]
* add a subset function to the geometry file
@@ -253,272 +248,197 @@ v1.2.6 (2016-10-19)
* removed pyc file, that should not be in the git repository
-
- Add appveyor status badge to README. [davidh-ssec]
-
- Merge remote-tracking branch 'deni90/master' into pre-master-davidh.
[davidh-ssec]
-
- Fix test_custom_uncert and test_gauss_uncert for mips* [Daniel
Knezevic]
-
- Fix pykdtree install on appveyor by turning off OpenMP. [davidh-ssec]
-
- Update appveyor config to install missing headers required by
pykdtree. [davidh-ssec]
-
- Change appveyor to use conda-forge instead of IOOS. [davidh-ssec]
-
- Add slack notifications from appveyor. [davidh-ssec]
+
v1.2.5 (2016-07-21)
-------------------
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.2.4 → 1.2.5. [Martin Raspaud]
-
- Fix EWA fornav for integer data and add test. [davidh-ssec]
There was a bug when doing the averaging in EWA where the current pixel was being rounded based on the previous pixel's value instead of the current pixel. This only affects integer data because values above 0 are rounded up by 0.5 and values below 0 are rounded by 0.5, for floats this round value is 0.0.
-
- Fix certain compilers not liking integers being passed to isnan.
[davidh-ssec]
-
- Replace catch_warnings in all tests with astropy version. [davidh-
ssec]
-
- Use catch_warnings from astropy (or at least try to) [davidh-ssec]
-
- Test removing version specific warning checks in `test_swath_wrap`
[davidh-ssec]
-
- Move USE_CYTHON handling to if main block in setup.py. [davidh-ssec]
-
- Fix isnan definition only if a macro doesn't already exist. [davidh-
ssec]
Numpy does some special macro stuff to define a good npy_isnan function. Some systems define a macro for it, others don't. Hopefully this works for all systems. A better solution might be to define a templated isnan that calls npy_isnan if it isn't an integer.
-
- fix EWA compile failure on windows python 3.5. [David Hoese]
-
- Make pykdtree install on appveyor optional. [davidh-ssec]
-
- Add pykdtree to appveyor dependencies. [davidh-ssec]
-
- Fix setup.py test on windows for multiprocessing tests. [davidh-ssec]
On Windows when new processes are started the initially command is imported or re-executed. For setup.py this is a big problem since the usual boilerplate does not include `if __name__ == "__main__"` so the setup.py test command gets rerun and rerun. This results in the child processes never actually being run for newer versions of python (2.7+). There still seems to be an issue with `test_nearest_resize` on Windows.
-
- Merge pull request #41 from cpaulik/fix-windows-ewa. [David Hoese]
Fix Windows CI import Error
-
- Install scipy in Windows CI to fix import problems. [Christoph Paulik]
-
- Fix copy/paste error in EWA fornav. [davidh-ssec]
I had started rewriting EWA in cython then realized it was faster in straight C++ so copied/pasted the cython code and modified it. Seems like I missed this 'or' hanging around.
-
- Fix NAN constant/macro for EWA on Windows. [davidh-ssec]
-
- Merge branch 'add-windows-CI' into fix-windows-ewa. [davidh-ssec]
-
- CI: Add IOOS conda channel to get basemap for Windows and python > 2.
[Christoph Paulik]
-
- Merge branch 'add-windows-CI' into fix-windows-ewa. [davidh-ssec]
-
- Add pyproj to conda install in Appveyor CI. [Christoph Paulik]
-
- Make extra_compile_args platform dependent. [Christoph Paulik]
-
- Add Appveyor CI configuration. [Christoph Paulik]
-
- Fix EWA resampling's isnan to work better with windows. [davidh-ssec]
+
v1.2.4 (2016-06-27)
-------------------
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.2.3 → 1.2.4. [Martin Raspaud]
-
- Fix setup.py extension import and use error. [davidh-ssec]
-
- Fix case when __builtins__ is a dict. [Martin Raspaud]
+
v1.2.3 (2016-06-21)
-------------------
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.2.2 → 1.2.3. [Martin Raspaud]
-
- Fix list of package names in setup.py. [davidh-ssec]
'pyresample.ewa' wasn't listed before and was not importable from an installed package.
+
v1.2.2 (2016-06-21)
-------------------
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.2.1 → 1.2.2. [Martin Raspaud]
-
- Add the header files to the MANIFEST.in. [Martin Raspaud]
Without this, the compilation of the ewa extension crashes.
+
v1.2.1 (2016-06-21)
-------------------
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.2.0 → 1.2.1. [Martin Raspaud]
-
- Include EWA header files as dependency for extensions. [davidh-ssec]
The .c and .cpp files are automatically included because they are listed as sources, but the header files are not. When building a source tarball (uploading to PyPI) the _fornav_templates.h file was not included and building would fail.
-
- Merge branch 'pre-master' of github.com:mraspaud/pyresample into pre-
master. [Adam.Dybbroe]
-
- Merge branch 'pre-master' of github.com:mraspaud/pyresample into pre-
master. [Adam.Dybbroe]
Conflicts:
docs/source/conf.py
-
- Run the base class init function first. [Adam.Dybbroe]
+
v1.2.0 (2016-06-17)
-------------------
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.1.6 → 1.2.0. [Martin Raspaud]
-
- Merge branch 'northaholic-feature-lonlat2colrow' into pre-master.
[Adam.Dybbroe]
-
- Add two convenience methods lonlat2colrow and colrow2lonlat to
AreaDefinition-class. [Sauli Joro]
-
- Fix bug in EWA grid origin calculation. [davidh-ssec]
Forgot that cell height was negative so ended up subtracting a negative, going in the wrong direction for the Y origin of the grid.
-
- Merge pull request #37 from davidh-ssec/feature-ewa-resampling. [David
Hoese]
Feature ewa resampling
-
- Fix bug in EWA conversion from AreaDefinition to upper-left origin
X/Y. [davidh-ssec]
I was using the area extent for the origin x/y locations, but the extent is actually the outer edge of the pixels so half a pixel needs to be added to each coordinate.
-
- Add EWA C extensions to mocked modules for read the docs. [davidh-
ssec]
Readthedocs.org fails to import the _ll2cr and _fornav extensions because it seems to not compile them properly. Their documentation isn't necessarily needed so I'm hoping that mocking them will let the import work.
-
- Add pyresample.ewa to API documentation list. [davidh-ssec]
-
- Update EWA wrapper functions to use explicit kwargs. [davidh-ssec]
-
- Correct comments and documentation in EWA documentation. [davidh-ssec]
-
- Add ll2cr and fornav wrappers to make calling easier. [davidh-ssec]
Updated documentation with correct usage and added information why EWA is different than kdtree
-
- Fix print statements in documentation so doctests are python 3
compatible. [davidh-ssec]
-
- Add pillow dependency for plot tests and quicklook extra. [davidh-
ssec]
-
- Add 'areas.cfg' file to repository and modify doctests to use that
instead. [davidh-ssec]
-
- Run doctests after unittests on travis. [davidh-ssec]
-
- Fix documentation for AreaDefinition object. [davidh-ssec]
-
- Update documentation to be numpy style and get rid of all warnings
when building docs. [davidh-ssec]
-
- Create special requirements.txt for docs. [davidh-ssec]
Readthedocs really doesn't like an empty string for the requirements file
-
- Try empty string for requirements file in readthedocs yaml. [davidh-
ssec]
-
- Fix readthedocs yaml config file. [davidh-ssec]
Readthedocs was using the requirements file during package installation, but was failing to install basemap (not needed for documentation build) so I attempted to make it an empty string in the yaml file. This makes Rtd hang on the build process. This should at least stop the hanging.
-
- Add napoleon docs extension and intial testing with numpy style
docstrings. [davidh-ssec]
-
- Add working example for EWA resampling to docs. [davidh-ssec]
I originally had this example but removed it when I had import problems. After I figured those out I forgot to put the original example back.
-
- Add basemap back in to the requirements.txt so that it can be
installed on travis. [davidh-ssec]
Similarly removed the requirements file when readthedocs is running and mocked third-party packages to documentation can still be built
-
- Fix setup.py requiring numpy for extension includes. [davidh-ssec]
The EWA extensions require the numpy headers to be built. These are normally found by importing numpy and doing `numpy.get_includes()`. Obviously if this is run on a new environment numpy is probably not installed so a simple `python setup.py install` will fail.
-
- Add "quicklook" extra in to travis test install. [davidh-ssec]
These packages are needed to properly test the "plot" package. These were included in requirements.txt but have been moved for now.
-
- Move plot test imports in to test functions for cleaner test failures.
[davidh-ssec]
-
- Add readthedocs yaml file for configuration. [davidh-ssec]
-
- Remove mocked modules from sphinx docs conf.py. [davidh-ssec]
This is the first step in making pyresamples docs buildable in the current readthedocs version
-
- Replace relative imports with absolute imports. [davidh-ssec]
I noticed a lot of warnings and import problems with building pyresample's documentation because of these relative imports
-
- Add EWA documentation to swath.rst. [davidh-ssec]
-
- Add tests for EWA fornav module. [davidh-ssec]
-
- Update documentation for ll2cr and fornav cython. [davidh-ssec]
-
- Merge remote-tracking branch 'davidh_fork/feature-ewa-resampling' into
feature-ewa-resampling. [davidh-ssec]
@@ -526,181 +446,126 @@ v1.2.0 (2016-06-17)
# pyresample/ewa/_fornav.pyx
# pyresample/ewa/_ll2cr.pyx
-
- Remove old and unused polar2grid ll2cr and fornav python modules.
[davidh-ssec]
-
- Fix travis tests on python 2.6. [davidh-ssec]
-
- Add ewa ll2cr tests to main test suite. [davidh-ssec]
-
- Add simple tests for ewa ll2cr. [davidh-ssec]
These tests were adapted from Polar2Grid so some of the terminology or organization might reflect P2G's design rather than satpy or pyresample.
-
- Revert import multiprocessing setup.py for python 2.6 compatibility.
[davidh-ssec]
-
- Fix old polar2grid import in ll2cr module. [davidh-ssec]
-
- Add method for converting area def to areas.def string format.
[davidh-ssec]
-
- Remove unused code from fornav wrapper. [davidh-ssec]
-
- Add initial EWA files copied from Polar2Grid. [davidh-ssec]
-
- Add basic documentation to fornav cython function. [davidh-ssec]
-
- Remove old and unused polar2grid ll2cr and fornav python modules.
[davidh-ssec]
-
- Fix travis tests on python 2.6. [davidh-ssec]
-
- Add ewa ll2cr tests to main test suite. [davidh-ssec]
-
- Add simple tests for ewa ll2cr. [davidh-ssec]
These tests were adapted from Polar2Grid so some of the terminology or organization might reflect P2G's design rather than satpy or pyresample.
-
- Revert import multiprocessing setup.py for python 2.6 compatibility.
[davidh-ssec]
-
- Fix old polar2grid import in ll2cr module. [davidh-ssec]
-
- Add method for converting area def to areas.def string format.
[davidh-ssec]
-
- Remove unused code from fornav wrapper. [davidh-ssec]
-
- Add initial EWA files copied from Polar2Grid. [davidh-ssec]
-
- Add .gitignore with python and C patterns. [davidh-ssec]
-
- Update tests so they don't fail on OSX. [davidh-ssec]
OSX seems to calculate slightly different results from `_spatial_mp.Cartesian` regardless of numexpr being installed. Although the changes are small they seem to affect the results enough to fail this test compared to normal linux execution.
-
- Add 'load_tests' for easier test selection. [davidh-ssec]
PyCharm and possibly other IDEs don't really play well with unittest TestSuites, but work as expected when `load_tests` is used.
-
- Make kd_tree test work on older numpy version. [Martin Raspaud]
VisibleDeprecationWarning is not available in numpy <1.9.
-
- Adapt to newest pykdtree version. [Martin Raspaud]
The kdtree object's attribute `data_pts` has been renamed to `data`.
-
- Run tests on python 3.5 in travis also. [Martin Raspaud]
+
v1.1.6 (2016-02-25)
-------------------
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.1.5 → 1.1.6. [Martin Raspaud]
-
- Fix #35 supporting scipy kdtree again. [Martin Raspaud]
A previous commit was looking for a 'data_pts' attribute in the kdtree
object, which is available in pykdtree, but not scipy.
-
- Merge pull request #32 from mitkin/master. [Martin Raspaud]
[tests] Skip deprecation warnings in test_gauss_multi_uncert
-
- Merge remote-tracking branch 'gh-pytroll/pre-master' [Mikhail Itkin]
-
- Put quotes around pip version specifiers to make things work. [Martin
Raspaud]
-
- Install the right matplotlib in travis. [Martin Raspaud]
The latest matplotlib (1.5) doesn't support python 2.6 and 3.3. This patch
chooses the right matplotlib version to install depending on the python
version at hand.
-
- Skip deprecation warnings. [Mikhail Itkin]
Catch the rest of the warnings. Check if there is only one, and
whether it contains the relevant message ('possible more than 8
neighbours found'). This patch is necessary for python 2.7.9 and newer
-
- Merge pull request #31 from bhawkins/fix-kdtree-dtype. [Martin
Raspaud]
Fix possible type mismatch with pykdtree.
-
- Add test to expose pykdtree TypeError exception. [Brian Hawkins]
-
- Fix possible type mismatch with pykdtree. [Brian Hawkins]
+
v1.1.5 (2015-10-12)
-------------------
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.1.4 → 1.1.5. [Martin Raspaud]
-
- Don't build on 3.2 anymore (because of coverage's lack of support for
3.2). [Martin Raspaud]
-
- Fix build badge adress. [Martin Raspaud]
-
- Fix the unicode problem in python3. [Martin Raspaud]
+
v1.1.4 (2015-10-08)
-------------------
Fix
~~~
-
- Bugfix: Accept unicode proj4 strings. Fixes #24. [Martin Raspaud]
Other
~~~~~
-
- update changelog. [Martin Raspaud]
-
- Bump version: 1.1.3 → 1.1.4. [Martin Raspaud]
-
- Add python-configobj as a rpm requirement in setup.cfg. [Martin
Raspaud]
-
- Add setup.cfg to allow rpm generation with bdist_rpm. [Martin Raspaud]
-
- Bugfix to address a numpy DeprecationWarning. [Martin Raspaud]
Numpy won't take non-integer indices soon, so make index an int.
-
- Merge branch 'release-1.1.3' [Martin Raspaud]
-
- Merge branch 'licence-lgpl' into pre-master. [Martin Raspaud]
-
- Switch to lgplv3, and bump up version number. [Martin Raspaud]
-
- Swith badge to main repository. [Martin Raspaud]
-
- Merge branch 'hotfix-v1.1.2' into pre-master. [Martin Raspaud]
-
- Merge branch 'hotfix-v1.1.2' [Martin Raspaud]
-
- Bump up version number. [Martin Raspaud]
-
- Merge branch 'mitkin-master' into hotfix-v1.1.2. [Martin Raspaud]
-
- Merge branch 'master' of https://github.com/mitkin/pyresample into
mitkin-master. [Martin Raspaud]
-
- [test_plot] allow travis to test plot.py. [Mikhail Itkin]
-
- [pip+travis] use `requirements.txt` [Mikhail Itkin]
Use `requirements.txt` instead of setuptools' `extras_require`
@@ -713,58 +578,44 @@ Other
`setup` call is meant for cruicial dependencies, not custom ones, so we
don't use them neither.
-
- [README] markdown + build status. [Mikhail Itkin]
* Using markdown extension, added `README` symlink
* Added travis build status badge
-
- remove pip `-e` switch. [Mikhail Itkin]
-
- Merge branch 'master' of github.com:mitkin/pyresample. [Mikhail Itkin]
-
- don't use setup.py for basemap installation. [Mikhail Itkin]
Instead of putting basemap and matplotlib into `extras_require`
install them directly
-
- don't use setup.py for basemap installation. [Mikhail Itkin]
Instead of putting basemap and matplotlib into `extras_require`
install them directly
-
- Using ubuntu GIS custom ppa. [Mikhail Itkin]
Added custom ppa with more up-to-date libgeos dependencies
-
- Install extra requirements using pip functionality. [Mikhail Itkin]
-
- Added more meaningful "quicklooks" name. [Mikhail Itkin]
Using quicklooks name as it's what matplotlib and basemap are needed for
-
- [setup] added plotting dependencies. [Mikhail Itkin]
pyresample/plot requires two extra dependencies:
* matplotlib
* basemap
-
- [travis] added system dependencies. [Mikhail Itkin]
* matplotlib requires libfreetype6-dev
* basemap requires libgeos libgeos-c1 and libgeos-dev
-
- Merge branch 'release-v1.1.1' [Martin Raspaud]
-
- Merge branch 'release-v1.1.1' [Martin Raspaud]
-
- Restore API functionality by importing necessary modules in __init__
[Martin Raspaud]
-
- Merge branch 'release-v1.1.1' into pre-master. [Martin Raspaud]
Conflicts:
@@ -772,12 +623,9 @@ Other
pyresample/kd_tree.py
test/test_geometry.py
-
- Removing old test directory. [Martin Raspaud]
-
- Merge the hotfix and the unittest restructuring into the release
branch. [Martin Raspaud]
-
- Merge branch 'release-v1.1.1' into hotfix-1.1.1. [Thomas Lavergne]
Conflicts:
@@ -785,279 +633,165 @@ Other
test/test_geometry.py
test/test_grid.py
-
- Be specific about the valid range of longitudes. [Thomas Lavergne]
-
- Be more specific about the valid longitude range [-180:+180[. Add a
test for utils.wrap_longitudes() [Thomas Lavergne]
-
- Add check on valid latitude in [-90:+90] (and associated test) [Thomas
Lavergne]
-
- Automatic longitude wrapping (bugfix towards 1.1.1) [Thomas Lavergne]
-
- Merge branch 'release-v1.1.1' into pre-master. [Martin Raspaud]
-
- Add news about new release. [Martin Raspaud]
-
- remove some relative imports. [Martin Raspaud]
-
- Cleanup and bump up version number to v1.1.1. [Martin Raspaud]
-
- Add pykdtree to the list of requirements for travis. [Martin Raspaud]
-
- Add .travis.yml file for automatic testing. [Martin Raspaud]
-
- Correct handling of long type in kd_tree.py for Python 2. [Martin
Valgur]
-
- Made testing of a Proj4 string independent of the order of elements
inside the string since the order was different on Python 2 and 3.
Replaced deprecated failIf with assertFalse. [Martin Valgur]
-
- Multiple small fixes to make the code work on both Python 2 and 3.
shmem_as_ndarray() now uses numpy.frombuffer() to provide equivalent
functionality. [Martin Valgur]
-
- Got rid of dependencies on the six package. [Martin Valgur]
-
- Applied python-modernize to pyresample. [Martin Valgur]
-
- Update README. [Martin Raspaud]
-
- Merge branch 'pre-master' of https://code.google.com/p/pyresample into
pre-master. [Martin Raspaud]
-
- A stray line of code is removed and I take back the recent enhancement
concerning swath to swath mapping. [Adam Dybbroe]
-
- Removed debug printouts. [Adam Dybbroe]
-
- More active support of swath to swath reprojection. [Adam Dybbroe]
-
- Add a plot on multiprocessing performance increases. [Martin Raspaud]
-
- Added outer_boundary_corners property to the area def class. [Adam
Dybbroe]
-
- corrected docs. [Esben S. Nielsen]
-
- modified uncert count to show above 0. Updated docs to relect uncert
option. [Esben S. Nielsen]
-
- cleaned up code a bit in kd_tree.py. [Esben S. Nielsen]
-
- made API doc work with readthedocs and bumped version number. [Esben
S. Nielsen]
-
- cleaned up code and tests. [Esben S. Nielsen]
-
- added masking of uncert counts. [Esben S. Nielsen]
-
- test passes again for uncertainty calculations. [Esben S. Nielsen]
-
- changed uncertainty API. First working uncertainty version. [Esben S.
Nielsen]
-
- not quite there. [Esben S. Nielsen]
-
- basic uncertainty implemented. [Esben S. Nielsen]
-
- updated docs. [Esben S. Nielsen]
-
- Fixing bug, and adding unittest-main run. [Adam Dybbroe]
-
- Making get_xy_from_lonlat work on arrays of points as well as single
points. [Adam Dybbroe]
-
- renamed functions in geometry.py and added proj_x_coords and
proj_y_coords properties. [Esben S. Nielsen]
-
- corrected __eq__ in geometry. [Esben S. Nielsen]
-
- Merge branch 'pre-master' of https://code.google.com/p/pyresample into
pre-master. [Adam Dybbroe]
-
- now kd_tree resampling selects dtype. [Esben S. Nielsen]
-
- removed random print statement. [Esben S. Nielsen]
-
- made get_capabilites function. [Esben S. Nielsen]
-
- test passes again. [Esben S. Nielsen]
-
- removed caching from geometry. [Esben S. Nielsen]
-
- Merge branch 'pre-master' of https://code.google.com/p/pyresample into
pre-master. [Martin Raspaud]
-
- Optimize transform_lonlats with numexpr. [Martin Raspaud]
-
- Unittests should work for both py2.6 and 2.7. [Adam Dybbroe]
-
- updated docs. [Esben S. Nielsen]
-
- fixed unit tests. [Esben S. Nielsen]
-
- Using assertRaises in py2.6 and py2.7 compatible version. [Adam
Dybbroe]
-
- bugfix to unittest suite. [Adam Dybbroe]
-
- Trying to make test-functions compatible with both python 2.6 and 2.7.
[Adam Dybbroe]
-
- Fixing bug in get_xy_from_lonlat and adding unittests on this
function. [Adam Dybbroe]
-
- Adding function get_xy_from_lonlat. [Adam Dybbroe]
-
- integrated pykdtree and handled latlong projection bug. [Esben S.
Nielsen]
-
- updated unit tests according to deprecation warnings. [Esben S.
Nielsen]
-
- Better parsing of a area definition (allow ':' in value fields) [Lars
Orum Rasmussen]
-
- updated docs. [Esben S. Nielsen]
-
- Merge branch 'pre-master' of https://code.google.com/p/pyresample into
pre-master. [Martin Raspaud]
-
- doc version. [esn]
-
- improved Basemap integration with globe projections. Updated docs on
epsilon. [esn]
-
- Accomodate for allclose behaviour change in numpy 1.6.2. [Martin
Raspaud]
From 1.6.2 numpy.allclose does not accept arrays that cannot be
broadcasted to the same shape. Hence a ValueError catch to return False.
-
- updadet doc for plotting. [Esben S. Nielsen]
-
- updated plot test to use AGG. [Esben S. Nielsen]
-
- Now handles plotting in Plate Carre projection. Added utils.fwhm2sigma
function. [Esben S. Nielsen]
-
- Merge branch 'master' of https://code.google.com/p/pyresample. [Esben
S. Nielsen]
-
- added pypi info. [Esben S. Nielsen]
-
- built docs. [Esben S. Nielsen]
-
- corrected test_swath.py to account for implementation specific
precision. [Esben S. Nielsen]
-
- more datatype specifications. [Esben S. Nielsen]
-
- removed warning check for python 2.5. [Esben S. Nielsen]
-
- corrected multi channnel bug. Added warnings for potential problematic
neighbour query condition. [Esben S. Nielsen]
-
- Now str() generates a unique string for area and coordinate definition
object. [Lars Orum Rasmussen]
-
- corrected manifest so doc images are included. [Esben S. Nielsen]
-
- Moved tests dir to test. Updated MANIFEST.in. [Esben S. Nielsen]
-
- Added MANIFEST.in. [Esben S. Nielsen]
-
- Applied setup.py patches. Made plotting more robust. [Esben S.
Nielsen]
-
- applied patch for getting version number. [Esben S. Nielsen]
-
- Bugfixing quicklooks. [StorPipfugl]
-
- Updated docs. [StorPipfugl]
-
- Updated docs. [StorPipfugl]
-
- Updated docs. [StorPipfugl]
-
- Added Basemap integration. [StorPipfugl]
-
- Added Basemap integration. [StorPipfugl]
-
- Updated docs. [StorPipfugl]
-
- Rebuild docs. [StorPipfugl]
-
- Made setup.py more robust. [StorPipfugl]
-
- New doc version. [StorPipfugl]
-
- Updated tests. [StorPipfugl]
-
- Reduced size of linesample arrays. Restructures kd_tree query to
remove redundant lon lat calculations. [StorPipfugl]
-
- Added geographic filtering. Swaths can now be concatenated and
appended. User no langer have to ravel data before resampling.
[StorPipfugl]
-
- Updated docs. [StorPipfugl]
-
- Updated install_requires. [StorPipfugl]
-
- version 0.7.3. [StorPipfugl]
-
- Bugfixes: Correct number of channels in empty result set. Resampling
of masked data to 1d swath now works. [StorPipfugl]
-
- Added Martin's spherical geometry operations. Updated documentation.
[StorPipfugl]
-
- Added equal and not equal operators for geometry defs. Restructured
the geometry module to be pickable. Added correct handling of empty
result data sets. [StorPipfugl]
-
- Incomplete - taskpyresample. [StorPipfugl]
-
- Set svn:mime-type. [StorPipfugl]
-
- Corrected doc errors. [StorPipfugl]
-
- Removed dist dir. [StorPipfugl]
-
- No commit message. [StorPipfugl]
-
- Updated documentation. New release. [StorPipfugl]
-
- Started updating docstrings. [StorPipfugl]
-
- Restructured API. [StorPipfugl]
-
- Now uses geometry types. Introduced API symmetry between swath->grid
and grid->swath resampling. [StorPipfugl]
-
- Consolidated version tag. [StorPipfugl]
-
- Mime types set. [StorPipfugl]
-
- Mime types set. [StorPipfugl]
-
- Removed test. [StorPipfugl]
-
- Removed unneeded function. [StorPipfugl]
-
- Mime types set. [StorPipfugl]
-
- Mime types set. [StorPipfugl]
-
- No commit message. [StorPipfugl]
-
- Moved to Google Code under GPLv3 license. [StorPipfugl]
-
- moved to Google Code. [StorPipfugl]
+
diff --git a/docs/areas.yaml b/docs/areas.yaml
new file mode 100644
index 0000000..121638f
--- /dev/null
+++ b/docs/areas.yaml
@@ -0,0 +1,30 @@
+ease_sh:
+ description: Antarctic EASE grid
+ projection:
+ a: 6371228.0
+ units: m
+ lon_0: 0
+ proj: laea
+ lat_0: -90
+ shape:
+ height: 425
+ width: 425
+ area_extent:
+ lower_left_xy: [-5326849.0625, -5326849.0625]
+ upper_right_xy: [5326849.0625, 5326849.0625]
+ units: m
+ease_nh:
+ description: Arctic EASE grid
+ projection:
+ a: 6371228.0
+ units: m
+ lon_0: 0
+ proj: laea
+ lat_0: 90
+ shape:
+ height: 425
+ width: 425
+ area_extent:
+ lower_left_xy: [-5326849.0625, -5326849.0625]
+ upper_right_xy: [5326849.0625, 5326849.0625]
+ units: m
diff --git a/docs/requirements.txt b/docs/requirements.txt
index e69de29..c219864 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -0,0 +1 @@
+git+https://github.com/pytroll/pykdtree.git@pre-master
diff --git a/docs/source/geo_def.rst b/docs/source/geo_def.rst
index 3938db0..2889824 100644
--- a/docs/source/geo_def.rst
+++ b/docs/source/geo_def.rst
@@ -9,21 +9,22 @@ Remarks
All longitudes and latitudes provided to **pyresample.geometry** must be in degrees.
Longitudes must additionally be in the [-180;+180[ validity range.
-As of version 1.1.1, the **pyresample.geometry** contructors will check the range of
-longitude values, send a warning if some of them fall outside validity range,
-and automatically correct the invalid values into [-180;+180[.
+As of version 1.1.1, the **pyresample.geometry** contructors will check the range of
+longitude values, send a warning if some of them fall outside validity range,
+and automatically correct the invalid values into [-180;+180[.
Use function **utils.wrap_longitudes** for wrapping longitudes yourself.
AreaDefinition
--------------
-The cartographic definition of grid areas used by Pyresample is contained in an object of type AreaDefintion.
-The following arguments are needed to initialize an area:
+The cartographic definition of grid areas used by Pyresample is contained in an
+object of type AreaDefintion. The following arguments are needed to initialize
+an area:
-* **area_id** ID of area
+* **area_id** ID of area
* **name**: Description
-* **proj_id**: ID of projection
+* **proj_id**: ID of projection (being deprecated)
* **proj_dict**: Proj4 parameters as dict
* **x_size**: Number of grid columns
* **y_size**: Number of grid rows
@@ -39,22 +40,21 @@ where
Creating an area definition:
.. doctest::
-
+
>>> from pyresample import geometry
>>> area_id = 'ease_sh'
- >>> name = 'Antarctic EASE grid'
+ >>> description = 'Antarctic EASE grid'
>>> proj_id = 'ease_sh'
- >>> proj4_args = 'proj=laea, lat_0=-90, lon_0=0, a=6371228.0, units=m'
- >>> x_size = 425
+ >>> x_size = 425
>>> y_size = 425
>>> area_extent = (-5326849.0625,-5326849.0625,5326849.0625,5326849.0625)
>>> proj_dict = {'a': '6371228.0', 'units': 'm', 'lon_0': '0',
... 'proj': 'laea', 'lat_0': '-90'}
- >>> area_def = geometry.AreaDefinition(area_id, name, proj_id, proj_dict, x_size,
- ... y_size, area_extent)
+ >>> area_def = geometry.AreaDefinition(area_id, description, proj_id,
+ ... proj_dict, x_size, y_size, area_extent)
>>> print(area_def)
Area ID: ease_sh
- Name: Antarctic EASE grid
+ Description: Antarctic EASE grid
Projection ID: ease_sh
Projection: {'a': '6371228.0', 'lat_0': '-90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
Number of columns: 425
@@ -68,20 +68,20 @@ area defintions. The function **get_area_def** can construct an area definition
based on area extent and a proj4-string or a list of proj4 arguments.
.. doctest::
-
+
>>> from pyresample import utils
>>> area_id = 'ease_sh'
- >>> area_name = 'Antarctic EASE grid'
+ >>> description = 'Antarctic EASE grid'
>>> proj_id = 'ease_sh'
- >>> proj4_args = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
+ >>> projection = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
>>> x_size = 425
>>> y_size = 425
>>> area_extent = (-5326849.0625,-5326849.0625,5326849.0625,5326849.0625)
- >>> area_def = utils.get_area_def(area_id, area_name, proj_id, proj4_args,
+ >>> area_def = utils.get_area_def(area_id, description, proj_id, projection,
... x_size, y_size, area_extent)
>>> print(area_def)
Area ID: ease_sh
- Name: Antarctic EASE grid
+ Description: Antarctic EASE grid
Projection ID: ease_sh
Projection: {'a': '6371228.0', 'lat_0': '-90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
Number of columns: 425
@@ -89,7 +89,87 @@ based on area extent and a proj4-string or a list of proj4 arguments.
Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
-The **load_area** function can be used to parse area definitions from a configuration file.
+The **load_area** function can be used to parse area definitions from a
+configuration file. Assuming the file **areas.yaml** exists with the following
+content
+
+.. code-block:: yaml
+
+ ease_sh:
+ description: Antarctic EASE grid
+ projection:
+ a: 6371228.0
+ units: m
+ lon_0: 0
+ proj: laea
+ lat_0: -90
+ shape:
+ height: 425
+ width: 425
+ area_extent:
+ lower_left_xy: [-5326849.0625, -5326849.0625]
+ upper_right_xy: [5326849.0625, 5326849.0625]
+ units: m
+ ease_nh:
+ description: Arctic EASE grid
+ projection:
+ a: 6371228.0
+ units: m
+ lon_0: 0
+ proj: laea
+ lat_0: 90
+ shape:
+ height: 425
+ width: 425
+ area_extent:
+ lower_left_xy: [-5326849.0625, -5326849.0625]
+ upper_right_xy: [5326849.0625, 5326849.0625]
+ units: m
+
+
+An area definition dict can be read using
+
+.. doctest::
+
+ >>> from pyresample import utils
+ >>> area = utils.load_area('areas.yaml', 'ease_nh')
+ >>> print(area)
+ Area ID: ease_nh
+ Description: Arctic EASE grid
+ Projection: {'a': '6371228.0', 'lat_0': '90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
+ Number of columns: 425
+ Number of rows: 425
+ Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
+
+Note: In the configuration file, the section name maps to **area_id**.
+
+.. note::
+
+ The `lower_left_xy` and `upper_right_xy` items give the coordinates of the
+ outer edges of the corner pixels on the x and y axis respectively. When the
+ projection coordinates are longitudes and latitudes, it is expected to
+ provide the extent in `longitude, latitude` order.
+
+Several area definitions can be read at once using the region names in an argument list
+
+.. doctest::
+
+ >>> from pyresample import utils
+ >>> nh_def, sh_def = utils.load_area('areas.yaml', 'ease_nh', 'ease_sh')
+ >>> print(sh_def)
+ Area ID: ease_sh
+ Description: Antarctic EASE grid
+ Projection: {'a': '6371228.0', 'lat_0': '-90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
+ Number of columns: 425
+ Number of rows: 425
+ Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
+
+
+
+.. note::
+
+ For backwards compatibility, we still support the legacy area file format:
+
Assuming the file **areas.cfg** exists with the following content
.. code-block:: bash
@@ -120,7 +200,7 @@ An area definition dict can be read using
>>> area = utils.load_area('areas.cfg', 'ease_nh')
>>> print(area)
Area ID: ease_nh
- Name: Arctic EASE grid
+ Description: Arctic EASE grid
Projection ID: ease_nh
Projection: {'a': '6371228.0', 'lat_0': '90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
Number of columns: 425
@@ -137,7 +217,7 @@ Several area definitions can be read at once using the region names in an argume
>>> nh_def, sh_def = utils.load_area('areas.cfg', 'ease_nh', 'ease_sh')
>>> print(sh_def)
Area ID: ease_sh
- Name: Antarctic EASE grid
+ Description: Antarctic EASE grid
Projection ID: ease_sh
Projection: {'a': '6371228.0', 'lat_0': '-90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
Number of columns: 425
@@ -156,7 +236,7 @@ of resampling by using a GridDefinition object instead an AreaDefinition object.
>>> lons = np.ones((100, 100))
>>> lats = np.ones((100, 100))
>>> grid_def = geometry.GridDefinition(lons=lons, lats=lats)
-
+
SwathDefinition
---------------
A swath is defined by the lon and lat values of the data points
@@ -168,7 +248,7 @@ A swath is defined by the lon and lat values of the data points
>>> lons = np.ones((500, 20))
>>> lats = np.ones((500, 20))
>>> swath_def = geometry.SwathDefinition(lons=lons, lats=lats)
-
+
Two swaths can be concatenated if their coloumn count matches
.. doctest::
@@ -181,144 +261,150 @@ Two swaths can be concatenated if their coloumn count matches
>>> lons2 = np.ones((300, 20))
>>> lats2 = np.ones((300, 20))
>>> swath_def2 = geometry.SwathDefinition(lons=lons2, lats=lats2)
- >>> swath_def3 = swath_def1.concatenate(swath_def2)
-
+ >>> swath_def3 = swath_def1.concatenate(swath_def2)
+
Geographic coordinates and boundaries
-------------------------------------
A ***definition** object allows for retrieval of geographic coordinates using array slicing (slice stepping is currently not supported).
-All ***definition** objects exposes the coordinates **lons**, **lats** and **cartesian_coords**.
-AreaDefinition exposes the full set of projection coordinates as **projection_x_coords** and **projection_y_coords**
+All ***definition** objects exposes the coordinates **lons**, **lats** and **cartesian_coords**.
+AreaDefinition exposes the full set of projection coordinates as
+**projection_x_coords** and **projection_y_coords**. Note that in the case of
+projection coordinates expressed in longitude and latitude,
+**projection_x_coords** will be longitude and **projection_y_coords** will be
+latitude.
Get full coordinate set:
.. doctest::
-
+
>>> from pyresample import utils
>>> area_id = 'ease_sh'
- >>> area_name = 'Antarctic EASE grid'
+ >>> description = 'Antarctic EASE grid'
>>> proj_id = 'ease_sh'
- >>> proj4_args = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
+ >>> projection = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
>>> x_size = 425
>>> y_size = 425
>>> area_extent = (-5326849.0625,-5326849.0625,5326849.0625,5326849.0625)
- >>> area_def = utils.get_area_def(area_id, area_name, proj_id, proj4_args,
+ >>> area_def = utils.get_area_def(area_id, description, proj_id, projection,
... x_size, y_size, area_extent)
>>> lons, lats = area_def.get_lonlats()
Get slice of coordinate set:
.. doctest::
-
+
>>> from pyresample import utils
>>> area_id = 'ease_sh'
- >>> area_name = 'Antarctic EASE grid'
+ >>> description = 'Antarctic EASE grid'
>>> proj_id = 'ease_sh'
- >>> proj4_args = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
+ >>> projection = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
>>> x_size = 425
>>> y_size = 425
>>> area_extent = (-5326849.0625,-5326849.0625,5326849.0625,5326849.0625)
- >>> area_def = utils.get_area_def(area_id, area_name, proj_id, proj4_args,
+ >>> area_def = utils.get_area_def(area_id, description, proj_id, projection,
... x_size, y_size, area_extent)
>>> cart_subset = area_def.get_cartesian_coords()[100:200, 350:]
-
-If only the 1D range of a projection coordinate is required it can be extraxted using the **proj_x_coord** or **proj_y_coords** property of a geographic coordinate
+
+If only the 1D range of a projection coordinate is required it can be extraxted
+using the **proj_x_coord** or **proj_y_coords** property of a geographic coordinate
.. doctest::
-
+
>>> from pyresample import utils
>>> area_id = 'ease_sh'
- >>> area_name = 'Antarctic EASE grid'
+ >>> description = 'Antarctic EASE grid'
>>> proj_id = 'ease_sh'
- >>> proj4_args = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
+ >>> projection = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
>>> x_size = 425
>>> y_size = 425
>>> area_extent = (-5326849.0625,-5326849.0625,5326849.0625,5326849.0625)
- >>> area_def = utils.get_area_def(area_id, area_name, proj_id, proj4_args,
+ >>> area_def = utils.get_area_def(area_id, description, proj_id, projection,
... x_size, y_size, area_extent)
>>> proj_x_range = area_def.proj_x_coords
-
+
Spherical geometry operations
-----------------------------
-Some basic spherical operations are available for ***definition** objects. The spherical geometry operations
-are calculated based on the corners of a GeometryDefinition (2D SwathDefinition or Grid/AreaDefinition) and assuming the edges are great circle arcs.
+Some basic spherical operations are available for ***definition** objects. The
+spherical geometry operations are calculated based on the corners of a
+GeometryDefinition (2D SwathDefinition or Grid/AreaDefinition) and assuming the
+edges are great circle arcs.
It can be tested if geometries overlaps
.. doctest::
- >>> import numpy as np
+ >>> import numpy as np
>>> from pyresample import utils
>>> area_id = 'ease_sh'
- >>> area_name = 'Antarctic EASE grid'
+ >>> description = 'Antarctic EASE grid'
>>> proj_id = 'ease_sh'
- >>> proj4_args = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
+ >>> projection = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
>>> x_size = 425
>>> y_size = 425
>>> area_extent = (-5326849.0625,-5326849.0625,5326849.0625,5326849.0625)
- >>> area_def = utils.get_area_def(area_id, area_name, proj_id, proj4_args,
+ >>> area_def = utils.get_area_def(area_id, description, proj_id, projection,
... x_size, y_size, area_extent)
>>> lons = np.array([[-40, -11.1], [9.5, 19.4], [65.5, 47.5], [90.3, 72.3]])
>>> lats = np.array([[-70.1, -58.3], [-78.8, -63.4], [-73, -57.6], [-59.5, -50]])
>>> swath_def = geometry.SwathDefinition(lons, lats)
>>> print(swath_def.overlaps(area_def))
True
-
+
The fraction of overlap can be calculated
.. doctest::
- >>> import numpy as np
+ >>> import numpy as np
>>> from pyresample import utils
>>> area_id = 'ease_sh'
- >>> area_name = 'Antarctic EASE grid'
+ >>> description = 'Antarctic EASE grid'
>>> proj_id = 'ease_sh'
- >>> proj4_args = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
+ >>> projection = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
>>> x_size = 425
>>> y_size = 425
>>> area_extent = (-5326849.0625,-5326849.0625,5326849.0625,5326849.0625)
- >>> area_def = utils.get_area_def(area_id, area_name, proj_id, proj4_args,
+ >>> area_def = utils.get_area_def(area_id, description, proj_id, projection,
... x_size, y_size, area_extent)
>>> lons = np.array([[-40, -11.1], [9.5, 19.4], [65.5, 47.5], [90.3, 72.3]])
>>> lats = np.array([[-70.1, -58.3], [-78.8, -63.4], [-73, -57.6], [-59.5, -50]])
>>> swath_def = geometry.SwathDefinition(lons, lats)
>>> overlap_fraction = swath_def.overlap_rate(area_def)
-
+
And the polygon defining the (great circle) boundaries over the overlapping area can be calculated
.. doctest::
- >>> import numpy as np
+ >>> import numpy as np
>>> from pyresample import utils
>>> area_id = 'ease_sh'
- >>> area_name = 'Antarctic EASE grid'
+ >>> description = 'Antarctic EASE grid'
>>> proj_id = 'ease_sh'
- >>> proj4_args = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
+ >>> projection = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
>>> x_size = 425
>>> y_size = 425
>>> area_extent = (-5326849.0625,-5326849.0625,5326849.0625,5326849.0625)
- >>> area_def = utils.get_area_def(area_id, area_name, proj_id, proj4_args,
+ >>> area_def = utils.get_area_def(area_id, description, proj_id, projection,
... x_size, y_size, area_extent)
>>> lons = np.array([[-40, -11.1], [9.5, 19.4], [65.5, 47.5], [90.3, 72.3]])
>>> lats = np.array([[-70.1, -58.3], [-78.8, -63.4], [-73, -57.6], [-59.5, -50]])
>>> swath_def = geometry.SwathDefinition(lons, lats)
>>> overlap_polygon = swath_def.intersection(area_def)
-
+
It can be tested if a (lon, lat) point is inside a GeometryDefinition
.. doctest::
- >>> import numpy as np
+ >>> import numpy as np
>>> from pyresample import utils
>>> area_id = 'ease_sh'
- >>> area_name = 'Antarctic EASE grid'
+ >>> description = 'Antarctic EASE grid'
>>> proj_id = 'ease_sh'
- >>> proj4_args = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
+ >>> projection = '+proj=laea +lat_0=-90 +lon_0=0 +a=6371228.0 +units=m'
>>> x_size = 425
>>> y_size = 425
>>> area_extent = (-5326849.0625,-5326849.0625,5326849.0625,5326849.0625)
- >>> area_def = utils.get_area_def(area_id, area_name, proj_id, proj4_args,
+ >>> area_def = utils.get_area_def(area_id, description, proj_id, projection,
... x_size, y_size, area_extent)
>>> print((0, -90) in area_def)
True
-
diff --git a/pyresample/bilinear/__init__.py b/pyresample/bilinear/__init__.py
index 7e7f855..4f721f1 100644
--- a/pyresample/bilinear/__init__.py
+++ b/pyresample/bilinear/__init__.py
@@ -149,10 +149,12 @@ def get_sample_from_bil_info(data, t__, s__, input_idxs, idx_arr,
result = result.data
result[mask] = np.nan
- with np.errstate(invalid='ignore'):
- idxs = (result > data_max) | (result < data_min)
-
- result[idxs] = np.nan
+ try:
+ with np.errstate(invalid='ignore'):
+ idxs = (result > data_max) | (result < data_min)
+ result[idxs] = np.nan
+ except TypeError:
+ pass
if output_shape is not None:
result = result.reshape(output_shape)
@@ -489,8 +491,15 @@ def _get_output_xy(target_area_def, proj):
"""Get x/y coordinates of the target grid."""
# Read output coordinates
out_lons, out_lats = target_area_def.get_lonlats()
+
+ # Replace masked arrays with np.nan'd ndarrays
+ out_lons = _convert_masks_to_nans(out_lons)
+ out_lats = _convert_masks_to_nans(out_lats)
+
+ # Mask invalid coordinates
out_lons, out_lats = _mask_coordinates(out_lons, out_lats)
+ # Convert coordinates to output projection x/y space
out_x, out_y = proj(out_lons, out_lats)
return out_x, out_y
@@ -511,12 +520,25 @@ def _get_input_xy(source_geo_def, proj, input_idxs, idx_ref):
in_lons = in_lons[idx_ref]
in_lats = in_lats[idx_ref]
+ # Replace masked arrays with np.nan'd ndarrays
+ in_lons = _convert_masks_to_nans(in_lons)
+ in_lats = _convert_masks_to_nans(in_lats)
+
# Convert coordinates to output projection x/y space
in_x, in_y = proj(in_lons, in_lats)
return in_x, in_y
+def _convert_masks_to_nans(arr):
+ """Remove masked array masks and replace corresponding values with nans"""
+ if hasattr(arr, 'mask'):
+ mask = arr.mask
+ arr = arr.data
+ arr[mask] = np.nan
+ return arr
+
+
def _check_data_shape(data, input_idxs):
"""Check data shape and adjust if necessary."""
# Handle multiple datasets
diff --git a/pyresample/data_reduce.py b/pyresample/data_reduce.py
index 7fda9fa..76e488a 100644
--- a/pyresample/data_reduce.py
+++ b/pyresample/data_reduce.py
@@ -21,27 +21,26 @@ from __future__ import absolute_import
import numpy as np
-
# Earth radius
R = 6370997.0
def swath_from_cartesian_grid(cart_grid, lons, lats, data,
radius_of_influence):
- """Makes coarse data reduction of swath data by comparison with
+ """Makes coarse data reduction of swath data by comparison with
cartesian grid
Parameters
----------
- chart_grid : numpy array
+ chart_grid : numpy array
Grid of area cartesian coordinates
- lons : numpy array
+ lons : numpy array
Swath lons
- lats : numpy array
+ lats : numpy array
Swath lats
- data : numpy array
+ data : numpy array
Swath data
- radius_of_influence : float
+ radius_of_influence : float
Cut off distance in meters
Returns
@@ -62,20 +61,20 @@ def swath_from_cartesian_grid(cart_grid, lons, lats, data,
def get_valid_index_from_cartesian_grid(cart_grid, lons, lats,
radius_of_influence):
- """Calculates relevant data indices using coarse data reduction of swath
+ """Calculates relevant data indices using coarse data reduction of swath
data by comparison with cartesian grid
Parameters
----------
- chart_grid : numpy array
+ chart_grid : numpy array
Grid of area cartesian coordinates
- lons : numpy array
+ lons : numpy array
Swath lons
- lats : numpy array
+ lats : numpy array
Swath lats
- data : numpy array
+ data : numpy array
Swath data
- radius_of_influence : float
+ radius_of_influence : float
Cut off distance in meters
Returns
@@ -110,28 +109,28 @@ def get_valid_index_from_cartesian_grid(cart_grid, lons, lats,
def swath_from_lonlat_grid(grid_lons, grid_lats, lons, lats, data,
radius_of_influence):
- """Makes coarse data reduction of swath data by comparison with
+ """Makes coarse data reduction of swath data by comparison with
lon lat grid
Parameters
----------
- grid_lons : numpy array
+ grid_lons : numpy array
Grid of area lons
- grid_lats : numpy array
+ grid_lats : numpy array
Grid of area lats
- lons : numpy array
+ lons : numpy array
Swath lons
- lats : numpy array
+ lats : numpy array
Swath lats
- data : numpy array
+ data : numpy array
Swath data
- radius_of_influence : float
+ radius_of_influence : float
Cut off distance in meters
Returns
-------
(lons, lats, data) : list of numpy arrays
- Reduced swath data and coordinate set
+ Reduced swath data and coordinate set
"""
valid_index = get_valid_index_from_lonlat_grid(
@@ -146,28 +145,28 @@ def swath_from_lonlat_grid(grid_lons, grid_lats, lons, lats, data,
def swath_from_lonlat_boundaries(boundary_lons, boundary_lats, lons, lats, data,
radius_of_influence):
- """Makes coarse data reduction of swath data by comparison with
+ """Makes coarse data reduction of swath data by comparison with
lon lat boundary
Parameters
----------
- boundary_lons : numpy array
+ boundary_lons : numpy array
Grid of area lons
- boundary_lats : numpy array
+ boundary_lats : numpy array
Grid of area lats
- lons : numpy array
+ lons : numpy array
Swath lons
- lats : numpy array
+ lats : numpy array
Swath lats
- data : numpy array
+ data : numpy array
Swath data
- radius_of_influence : float
+ radius_of_influence : float
Cut off distance in meters
Returns
-------
(lons, lats, data) : list of numpy arrays
- Reduced swath data and coordinate set
+ Reduced swath data and coordinate set
"""
valid_index = get_valid_index_from_lonlat_boundaries(boundary_lons,
@@ -181,20 +180,20 @@ def swath_from_lonlat_boundaries(boundary_lons, boundary_lats, lons, lats, data,
def get_valid_index_from_lonlat_grid(grid_lons, grid_lats, lons, lats, radius_of_influence):
- """Calculates relevant data indices using coarse data reduction of swath
+ """Calculates relevant data indices using coarse data reduction of swath
data by comparison with lon lat grid
Parameters
----------
- chart_grid : numpy array
+ chart_grid : numpy array
Grid of area cartesian coordinates
- lons : numpy array
+ lons : numpy array
Swath lons
- lats : numpy array
+ lats : numpy array
Swath lats
- data : numpy array
+ data : numpy array
Swath data
- radius_of_influence : float
+ radius_of_influence : float
Cut off distance in meters
Returns
@@ -222,7 +221,7 @@ def get_valid_index_from_lonlat_grid(grid_lons, grid_lats, lons, lats, radius_of
def get_valid_index_from_lonlat_boundaries(boundary_lons, boundary_lats, lons, lats, radius_of_influence):
- """Find relevant indices from grid boundaries using the
+ """Find relevant indices from grid boundaries using the
winding number theorem"""
valid_index = _get_valid_index(boundary_lons.side1, boundary_lons.side2,
@@ -237,7 +236,7 @@ def get_valid_index_from_lonlat_boundaries(boundary_lons, boundary_lats, lons, l
def _get_valid_index(lons_side1, lons_side2, lons_side3, lons_side4,
lats_side1, lats_side2, lats_side3, lats_side4,
lons, lats, radius_of_influence):
- """Find relevant indices from grid boundaries using the
+ """Find relevant indices from grid boundaries using the
winding number theorem"""
# Coarse reduction of data based on extrema analysis of the boundary
@@ -290,14 +289,14 @@ def _get_valid_index(lons_side1, lons_side2, lons_side3, lons_side4,
# From the winding number theorem follows:
# angle_sum possiblilities:
- #-360: area covers north pole
- # 360: area covers south pole
+ # 360: area covers north pole
+ #-360: area covers south pole
# 0: area covers no poles
# else: area covers both poles
- if round(angle_sum) == -360:
+ if round(angle_sum) == 360:
# Covers NP
valid_index = (lats >= lat_min_buffered)
- elif round(angle_sum) == 360:
+ elif round(angle_sum) == -360:
# Covers SP
valid_index = (lats <= lat_max_buffered)
elif round(angle_sum) == 0:
diff --git a/pyresample/ewa/__init__.py b/pyresample/ewa/__init__.py
index cf20ffa..6c48748 100644
--- a/pyresample/ewa/__init__.py
+++ b/pyresample/ewa/__init__.py
@@ -107,8 +107,12 @@ def ll2cr(swath_def, area_def, fill=np.nan, copy=True):
lons, lats = swath_def.get_lonlats()
# ll2cr requires 64-bit floats due to pyproj limitations
# also need a copy of lons, lats since they are written to in-place
- lons = lons.astype(np.float64, copy=copy)
- lats = lats.astype(np.float64, copy=copy)
+ try:
+ lons = lons.astype(np.float64, copy=copy)
+ lats = lats.astype(np.float64, copy=copy)
+ except TypeError:
+ lons = lons.astype(np.float64)
+ lats = lats.astype(np.float64)
# Break the input area up in to the expected parameters for ll2cr
p = area_def.proj4_string
@@ -204,7 +208,7 @@ def fornav(cols, rows, area_def, data_in,
data_in = [data_in]
# need a list for replacing these arrays later
- data_in = list(data_in)
+ data_in = [np.ascontiguousarray(d) for d in data_in]
# determine a fill value if they didn't tell us what they have as a
# fill value in the numpy arrays
if "fill" is None:
@@ -213,7 +217,8 @@ def fornav(cols, rows, area_def, data_in,
elif np.issubdtype(data_in[0].dtype, np.integer):
fill = -999
else:
- raise ValueError("Unsupported input data type for EWA Resampling: {}".format(data_in[0].dtype))
+ raise ValueError(
+ "Unsupported input data type for EWA Resampling: {}".format(data_in[0].dtype))
convert_to_masked = False
for idx, in_arr in enumerate(data_in):
@@ -224,18 +229,29 @@ def fornav(cols, rows, area_def, data_in,
data_in = tuple(data_in)
if out is not None:
- # the user may have provided memmapped arrays or other array-like objects
- out = tuple("out")
+ # the user may have provided memmapped arrays or other array-like
+ # objects
+ if isinstance(out, (tuple, list)):
+ out = tuple(out)
+ else:
+ out = (out,)
else:
# create a place for output data to be written
- out = tuple(np.empty(area_def.shape, dtype=in_arr.dtype) for in_arr in data_in)
+ out = tuple(np.empty(area_def.shape, dtype=in_arr.dtype)
+ for in_arr in data_in)
# see if the user specified rows per scan
# otherwise, use the entire swath as one "scanline"
rows_per_scan = rows_per_scan or data_in[0].shape[0]
results = _fornav.fornav_wrapper(cols, rows, data_in, out,
- np.nan, np.nan, rows_per_scan)
+ np.nan, np.nan, rows_per_scan,
+ weight_count=weight_count,
+ weight_min=weight_min,
+ weight_distance_max=weight_distance_max,
+ weight_delta_max=weight_delta_max,
+ weight_sum_min=weight_sum_min,
+ maximum_weight_mode=maximum_weight_mode)
def _mask_helper(data, fill):
if np.isnan(fill):
@@ -245,11 +261,11 @@ def fornav(cols, rows, area_def, data_in,
if convert_to_masked:
# they gave us masked arrays so give them masked arrays back
- out = [np.ma.masked_where(_mask_helper(out_arr, fill), out_arr) for out_arr in out]
+ out = [np.ma.masked_where(_mask_helper(out_arr, fill), out_arr)
+ for out_arr in out]
if len(out) == 1:
# they only gave us one data array as input, so give them one back
out = out[0]
results = results[0]
return results, out
-
diff --git a/pyresample/geometry.py b/pyresample/geometry.py
index 3000598..7f6809a 100644
--- a/pyresample/geometry.py
+++ b/pyresample/geometry.py
@@ -23,8 +23,10 @@
"""Classes for geometry operations"""
import warnings
+from collections import OrderedDict
import numpy as np
+import yaml
from pyresample import _spatial_mp, utils
@@ -33,6 +35,10 @@ class DimensionError(Exception):
pass
+class IncompatibleAreas(Exception):
+ """Error when the areas to combine are not compatible."""
+
+
class Boundary(object):
"""Container for geometry boundary.
@@ -581,13 +587,36 @@ class AreaDefinition(BaseDefinition):
', '.join(["'%s': '%s'" % (str(k), str(proj_dict[k]))
for k in sorted(proj_dict.keys())]) +
'}')
- return ('Area ID: %s\nName: %s\nProjection ID: %s\n'
- 'Projection: %s\nNumber of columns: %s\nNumber of rows: %s\n'
- 'Area extent: %s') % (self.area_id, self.name, self.proj_id,
- proj_str, self.x_size, self.y_size,
- self.area_extent)
+
+ if self.proj_id is None:
+ third_line = ""
+ else:
+ third_line = "Projection ID: {0}\n".format(self.proj_id)
+
+ return ('Area ID: {0}\nDescription: {1}\n{2}'
+ 'Projection: {3}\nNumber of columns: {4}\nNumber of rows: {5}\n'
+ 'Area extent: {6}').format(self.area_id, self.name, third_line,
+ proj_str, self.x_size, self.y_size,
+ self.area_extent)
def create_areas_def(self):
+ to_dump = OrderedDict()
+ res = OrderedDict()
+ to_dump[self.area_id] = res
+
+ res['description'] = self.name
+ res['shape'] = OrderedDict([('height', self.y_size),
+ ('width', self.x_size)])
+ res['area_extent'] = OrderedDict([('lower_left_xy',
+ list(self.area_extent[:2])),
+ ('upper_right_xy',
+ list(self.area_extent[2:])),
+ ('units', 'm')
+ ])
+
+ return ordered_dump(to_dump)
+
+ def create_areas_def_legacy(self):
proj_dict = self.proj_dict
proj_str = ','.join(["%s=%s" % (str(k), str(proj_dict[k]))
for k in sorted(proj_dict.keys())])
@@ -599,8 +628,10 @@ class AreaDefinition(BaseDefinition):
fmt += "\tXSIZE:\t{x_size}\n"
fmt += "\tYSIZE:\t{y_size}\n"
fmt += "\tAREA_EXTENT: {area_extent}\n}};\n"
- area_def_str = fmt.format(name=self.name, area_id=self.area_id, proj_str=proj_str,
- x_size=self.x_size, y_size=self.y_size, area_extent=self.area_extent)
+ area_def_str = fmt.format(name=self.name, area_id=self.area_id,
+ proj_str=proj_str, x_size=self.x_size,
+ y_size=self.y_size,
+ area_extent=self.area_extent)
return area_def_str
__repr__ = __str__
@@ -915,7 +946,7 @@ class AreaDefinition(BaseDefinition):
dtype = self.dtype
if self.lons is None or self.lats is None:
- #Data is not cached
+ # Data is not cached
if nprocs is None:
nprocs = self.nprocs
@@ -944,7 +975,7 @@ class AreaDefinition(BaseDefinition):
del(target_x)
del(target_y)
else:
- #Data is cached
+ # Data is cached
if data_slice is None:
# Full slice
lons = self.lons
@@ -963,6 +994,137 @@ class AreaDefinition(BaseDefinition):
return '+' + ' +'.join([t[0] + '=' + str(t[1]) for t in items])
+def combine_area_extents_vertical(area1, area2):
+ """Combine the area extents of areas 1 and 2."""
+ if (area1.area_extent[0] == area2.area_extent[0] and
+ area1.area_extent[2] == area2.area_extent[2]):
+ current_extent = list(area1.area_extent)
+ if np.isclose(area1.area_extent[1], area2.area_extent[3]):
+ current_extent[1] = area2.area_extent[1]
+ elif np.isclose(area1.area_extent[3], area2.area_extent[1]):
+ current_extent[3] = area2.area_extent[3]
+ else:
+ raise IncompatibleAreas(
+ "Can't concatenate area definitions with "
+ "incompatible area extents: "
+ "{0} and {1}".format(area1, area2))
+ return current_extent
+
+
+def concatenate_area_defs(area1, area2, axis=0):
+ """Append *area2* to *area1* and return the results"""
+ different_items = (set(area1.proj_dict.items()) ^
+ set(area2.proj_dict.items()))
+ if axis == 0:
+ same_size = area1.x_size == area2.x_size
+ else:
+ raise NotImplementedError('Only vertical contatenation is supported.')
+ if different_items or not same_size:
+ raise IncompatibleAreas("Can't concatenate area definitions with "
+ "different projections: "
+ "{0} and {1}".format(area1, area2))
+
+ if axis == 0:
+ area_extent = combine_area_extents_vertical(area1, area2)
+ x_size = area1.x_size
+ y_size = area1.y_size + area2.y_size
+ else:
+ raise NotImplementedError('Only vertical contatenation is supported.')
+ return AreaDefinition(area1.area_id, area1.name, area1.proj_id,
+ area1.proj_dict, x_size, y_size,
+ area_extent)
+
+
+class StackedAreaDefinition(BaseDefinition):
+ """Definition based on muliple vertically stacked AreaDefinitions."""
+
+ def __init__(self, *definitions, **kwargs):
+ """Base this instance on *definitions*.
+
+ *kwargs* used here are `nprocs` and `dtype` (see AreaDefinition).
+ """
+ nprocs = kwargs.get('nprocs', 1)
+ super(StackedAreaDefinition, self).__init__(nprocs=nprocs)
+ self.dtype = kwargs.get('dtype', np.float64)
+ self.defs = []
+ self.proj_dict = {}
+ for definition in definitions:
+ self.append(definition)
+
+ @property
+ def x_size(self):
+ return self.defs[0].x_size
+
+ @property
+ def y_size(self):
+ return sum(definition.y_size for definition in self.defs)
+
+ @property
+ def size(self):
+ return self.y_size * self.x_size
+
+ def append(self, definition):
+ """Append another definition to the area."""
+ if isinstance(definition, StackedAreaDefinition):
+ for area in definition.defs:
+ self.append(area)
+ return
+ if definition.y_size == 0:
+ return
+ if not self.defs:
+ self.proj_dict = definition.proj_dict
+ elif self.proj_dict != definition.proj_dict:
+ raise NotImplementedError('Cannot append areas:'
+ ' Proj.4 dict mismatch')
+ try:
+ self.defs[-1] = concatenate_area_defs(self.defs[-1], definition)
+ except (IncompatibleAreas, IndexError):
+ self.defs.append(definition)
+
+ def get_lonlats(self, nprocs=None, data_slice=None, cache=False, dtype=None):
+ """Return lon and lat arrays of the area."""
+
+ llons = []
+ llats = []
+ try:
+ row_slice, col_slice = data_slice
+ except TypeError:
+ row_slice = slice(0, self.y_size)
+ col_slice = slice(0, self.x_size)
+ offset = 0
+ for definition in self.defs:
+ local_row_slice = slice(max(row_slice.start - offset, 0),
+ min(max(row_slice.stop - offset, 0),
+ definition.y_size),
+ row_slice.step)
+ lons, lats = definition.get_lonlats(nprocs=nprocs,
+ data_slice=(local_row_slice,
+ col_slice),
+ cache=cache,
+ dtype=dtype)
+
+ llons.append(lons)
+ llats.append(lats)
+ offset += lons.shape[0]
+
+ self.lons = np.vstack(llons)
+ self.lats = np.vstack(llats)
+
+ return self.lons, self.lats
+
+ def squeeze(self):
+ """Generate a single AreaDefinition if possible."""
+ if len(self.defs) == 1:
+ return self.defs[0]
+ else:
+ return self
+
+ @property
+ def proj4_string(self):
+ """Returns projection definition as Proj.4 string"""
+ return self.defs[0].proj4_string
+
+
def _get_slice(segments, shape):
"""Generator for segmenting a 1D or 2D array"""
@@ -1005,3 +1167,16 @@ def _get_highest_level_class(obj1, obj2):
else:
klass = obj1.__class__
return klass
+
+
+def ordered_dump(data, stream=None, Dumper=yaml.Dumper, **kwds):
+ class OrderedDumper(Dumper):
+ pass
+
+ def _dict_representer(dumper, data):
+ return dumper.represent_mapping(
+ yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
+ data.items(), flow_style=False)
+
+ OrderedDumper.add_representer(OrderedDict, _dict_representer)
+ return yaml.dump(data, stream, OrderedDumper, **kwds)
diff --git a/pyresample/test/test_ewa_fornav.py b/pyresample/test/test_ewa_fornav.py
index 8fd2127..975bc2e 100644
--- a/pyresample/test/test_ewa_fornav.py
+++ b/pyresample/test/test_ewa_fornav.py
@@ -118,12 +118,46 @@ class TestFornav(unittest.TestCase):
self.assertTrue(((out == 1) | (out == -128)).all(),
msg="Unexpected interpolation values were returned")
+
+class TestFornavWrapper(unittest.TestCase):
+ """Test the function wrapping the lower-level fornav code."""
+ def test_fornav_swath_larger_float32(self):
+ """Test that a swath larger than the output grid fills the entire grid.
+ """
+ from pyresample.ewa import fornav
+ swath_shape = (1600, 3200)
+ data_type = np.float32
+ # Create a fake row and cols array
+ rows = np.empty(swath_shape, dtype=np.float32)
+ rows[:] = np.linspace(-500, 2500, 1600)[:, None]
+ cols = np.empty(swath_shape, dtype=np.float32)
+ cols[:] = np.linspace(-2500, 1500, 3200)
+ # Create a fake data swath
+ data = np.ones(swath_shape, dtype=data_type)
+ out = np.empty((1000, 1000), dtype=data_type)
+ # area can be None because `out` is specified
+ area = None
+
+ grid_points_covered, out_res = fornav(cols, rows, area, data,
+ rows_per_scan=16, out=out)
+ self.assertIs(out, out_res)
+ # The swath was larger than the grid, all of the grid should have
+ # been covered by swath pixels
+ self.assertEqual(grid_points_covered, out.size,
+ msg="Not all grid pixels were filled")
+ # The swath was all 1s so there shouldn't be any non-1 values in the
+ # output except outside the swath
+ self.assertTrue(((out == 1) | np.isnan(out)).all(),
+ msg="Unexpected interpolation values were returned")
+
+
def suite():
"""The test suite.
"""
loader = unittest.TestLoader()
mysuite = unittest.TestSuite()
mysuite.addTest(loader.loadTestsFromTestCase(TestFornav))
+ mysuite.addTest(loader.loadTestsFromTestCase(TestFornavWrapper))
return mysuite
diff --git a/pyresample/test/test_ewa_ll2cr.py b/pyresample/test/test_ewa_ll2cr.py
index 311a071..99caaaa 100644
--- a/pyresample/test/test_ewa_ll2cr.py
+++ b/pyresample/test/test_ewa_ll2cr.py
@@ -179,6 +179,38 @@ class TestLL2CRDynamic(unittest.TestCase):
self.assertTrue(np.all(np.diff(lon_arr[0]) >= 0), "ll2cr didn't return monotonic columns over the dateline")
+class TestLL2CRWrapper(unittest.TestCase):
+ def test_basic1(self):
+ from pyresample.ewa import ll2cr
+ from pyresample.geometry import SwathDefinition, AreaDefinition
+ from pyresample.utils import proj4_str_to_dict
+ lon_arr = create_test_longitude(-95.0, -75.0, (50, 100), dtype=np.float64)
+ lat_arr = create_test_latitude(18.0, 40.0, (50, 100), dtype=np.float64)
+ swath_def = SwathDefinition(lon_arr, lat_arr)
+ grid_info = static_lcc.copy()
+ cw = grid_info["cell_width"]
+ ch = grid_info["cell_height"]
+ ox = grid_info["origin_x"]
+ oy = grid_info["origin_y"]
+ w = grid_info["width"]
+ h = grid_info["height"]
+ half_w = abs(cw / 2.)
+ half_h = abs(ch / 2.)
+ extents = [
+ ox - half_w, oy - h * abs(ch) - half_h,
+ ox + w * abs(cw) + half_w, oy + half_h
+ ]
+ area = AreaDefinition('test_area', 'test_area', 'test_area',
+ proj4_str_to_dict(grid_info['proj4_definition']),
+ w, h, extents)
+ points_in_grid, lon_res, lat_res, = ll2cr(swath_def, area,
+ fill=np.nan, copy=False)
+ self.assertEqual(points_in_grid, lon_arr.size, "all points should be contained in a dynamic grid")
+ self.assertIs(lon_arr, lon_res)
+ self.assertIs(lat_arr, lat_res)
+ self.assertEqual(points_in_grid, lon_arr.size, "all these test points should fall in this grid")
+
+
def suite():
"""The test suite.
"""
@@ -186,6 +218,7 @@ def suite():
mysuite = unittest.TestSuite()
mysuite.addTest(loader.loadTestsFromTestCase(TestLL2CRStatic))
mysuite.addTest(loader.loadTestsFromTestCase(TestLL2CRDynamic))
+ mysuite.addTest(loader.loadTestsFromTestCase(TestLL2CRWrapper))
return mysuite
diff --git a/pyresample/test/test_files/areas.yaml b/pyresample/test/test_files/areas.yaml
new file mode 100644
index 0000000..121638f
--- /dev/null
+++ b/pyresample/test/test_files/areas.yaml
@@ -0,0 +1,30 @@
+ease_sh:
+ description: Antarctic EASE grid
+ projection:
+ a: 6371228.0
+ units: m
+ lon_0: 0
+ proj: laea
+ lat_0: -90
+ shape:
+ height: 425
+ width: 425
+ area_extent:
+ lower_left_xy: [-5326849.0625, -5326849.0625]
+ upper_right_xy: [5326849.0625, 5326849.0625]
+ units: m
+ease_nh:
+ description: Arctic EASE grid
+ projection:
+ a: 6371228.0
+ units: m
+ lon_0: 0
+ proj: laea
+ lat_0: 90
+ shape:
+ height: 425
+ width: 425
+ area_extent:
+ lower_left_xy: [-5326849.0625, -5326849.0625]
+ upper_right_xy: [5326849.0625, 5326849.0625]
+ units: m
diff --git a/pyresample/test/test_geometry.py b/pyresample/test/test_geometry.py
index 0e7c07f..470ad52 100644
--- a/pyresample/test/test_geometry.py
+++ b/pyresample/test/test_geometry.py
@@ -1,9 +1,16 @@
from __future__ import with_statement
+import random
import sys
+
import numpy as np
+from mock import MagicMock, patch
+
+from pyresample import geo_filter, geometry
+from pyresample.geometry import (IncompatibleAreas,
+ combine_area_extents_vertical,
+ concatenate_area_defs)
from pyresample.test.utils import catch_warnings
-from pyresample import geometry, geo_filter
if sys.version_info < (2, 7):
import unittest2 as unittest
@@ -544,7 +551,8 @@ class Test(unittest.TestCase):
proj_id = 'geos0'
x_size = 3712
y_size = 3712
- area_extent = [-5570248.477339261, -5567248.074173444, 5567248.074173444, 5570248.477339261]
+ area_extent = [-5570248.477339261, -5567248.074173444,
+ 5567248.074173444, 5570248.477339261]
proj_dict = {'a': '6378169.00',
'b': '6356583.80',
'h': '35785831.0',
@@ -570,8 +578,7 @@ class Test(unittest.TestCase):
# test scalars
lon, lat = (-8.125547604568746, -14.345524111874646)
- self.assertTrue(area.lonlat2colrow(lon,lat) == (1567, 2375))
-
+ self.assertTrue(area.lonlat2colrow(lon, lat) == (1567, 2375))
def test_colrow2lonlat(self):
@@ -581,7 +588,8 @@ class Test(unittest.TestCase):
proj_id = 'geos0'
x_size = 3712
y_size = 3712
- area_extent = [-5570248.477339261, -5567248.074173444, 5567248.074173444, 5570248.477339261]
+ area_extent = [-5570248.477339261, -5567248.074173444,
+ 5567248.074173444, 5570248.477339261]
proj_dict = {'a': '6378169.00',
'b': '6356583.80',
'h': '35785831.0',
@@ -602,16 +610,15 @@ class Test(unittest.TestCase):
# test arrays
lon_expects = np.array([28.77763033, 8.23765962])
lat_expects = np.array([61.20120556, 50.05836402])
- self.assertTrue(np.allclose(lons__, lon_expects, rtol = 0, atol = 1e-7))
- self.assertTrue(np.allclose(lats__, lat_expects, rtol = 0, atol = 1e-7))
+ self.assertTrue(np.allclose(lons__, lon_expects, rtol=0, atol=1e-7))
+ self.assertTrue(np.allclose(lats__, lat_expects, rtol=0, atol=1e-7))
# test scalars
lon__, lat__ = area.colrow2lonlat(1567, 2375)
lon_expect = -8.125547604568746
lat_expect = -14.345524111874646
- self.assertTrue(np.allclose(lon__, lon_expect, rtol = 0, atol = 1e-7))
- self.assertTrue(np.allclose(lat__, lat_expect, rtol = 0, atol = 1e-7))
-
+ self.assertTrue(np.allclose(lon__, lon_expect, rtol=0, atol=1e-7))
+ self.assertTrue(np.allclose(lat__, lat_expect, rtol=0, atol=1e-7))
def test_get_xy_from_lonlat(self):
"""Test the function get_xy_from_lonlat"""
@@ -694,12 +701,171 @@ class Test(unittest.TestCase):
self.assertTrue((y__.data == y_expects).all())
+class TestStackedAreaDefinition(unittest.TestCase):
+ """Test the StackedAreaDefition."""
+
+ def test_append(self):
+ """Appending new definitions."""
+ area1 = geometry.AreaDefinition("area1", 'area1', "geosmsg",
+ {'a': '6378169.0', 'b': '6356583.8',
+ 'h': '35785831.0', 'lon_0': '0.0',
+ 'proj': 'geos', 'units': 'm'},
+ 5568, 464,
+ (3738502.0095458371, 3715498.9194295374,
+ -1830246.0673044831, 3251436.5796920112)
+ )
+
+ area2 = geometry.AreaDefinition("area2", 'area2', "geosmsg",
+ {'a': '6378169.0', 'b': '6356583.8',
+ 'h': '35785831.0', 'lon_0': '0.0',
+ 'proj': 'geos', 'units': 'm'},
+ 5568, 464,
+ (3738502.0095458371, 4179561.259167064,
+ -1830246.0673044831, 3715498.9194295374)
+ )
+
+ adef = geometry.StackedAreaDefinition(area1, area2)
+ self.assertEqual(len(adef.defs), 1)
+ self.assertTupleEqual(adef.defs[0].area_extent,
+ (3738502.0095458371, 4179561.259167064,
+ -1830246.0673044831, 3251436.5796920112))
+
+ # same
+
+ area3 = geometry.AreaDefinition("area3", 'area3', "geosmsg",
+ {'a': '6378169.0', 'b': '6356583.8',
+ 'h': '35785831.0', 'lon_0': '0.0',
+ 'proj': 'geos', 'units': 'm'},
+ 5568, 464,
+ (3738502.0095458371, 3251436.5796920112,
+ -1830246.0673044831, 2787374.2399544837))
+ adef.append(area3)
+ self.assertEqual(len(adef.defs), 1)
+ self.assertTupleEqual(adef.defs[0].area_extent,
+ (3738502.0095458371, 4179561.259167064,
+ -1830246.0673044831, 2787374.2399544837))
+
+ self.assertIsInstance(adef.squeeze(), geometry.AreaDefinition)
+
+ # transition
+ area4 = geometry.AreaDefinition("area4", 'area4', "geosmsg",
+ {'a': '6378169.0', 'b': '6356583.8',
+ 'h': '35785831.0', 'lon_0': '0.0',
+ 'proj': 'geos', 'units': 'm'},
+ 5568, 464,
+ (5567747.7409681147, 2787374.2399544837,
+ -1000.3358822065015, 2323311.9002169576))
+
+ adef.append(area4)
+ self.assertEqual(len(adef.defs), 2)
+ self.assertTupleEqual(adef.defs[-1].area_extent,
+ (5567747.7409681147, 2787374.2399544837,
+ -1000.3358822065015, 2323311.9002169576))
+
+ self.assertEqual(adef.y_size, 4 * 464)
+ self.assertIsInstance(adef.squeeze(), geometry.StackedAreaDefinition)
+
+ adef2 = geometry.StackedAreaDefinition()
+ self.assertEqual(len(adef2.defs), 0)
+
+ adef2.append(adef)
+ self.assertEqual(len(adef2.defs), 2)
+ self.assertTupleEqual(adef2.defs[-1].area_extent,
+ (5567747.7409681147, 2787374.2399544837,
+ -1000.3358822065015, 2323311.9002169576))
+
+ self.assertEqual(adef2.y_size, 4 * 464)
+
+ def test_get_lonlats(self):
+ """Test get_lonlats on StackedAreaDefinition."""
+ area3 = geometry.AreaDefinition("area3", 'area3', "geosmsg",
+ {'a': '6378169.0', 'b': '6356583.8',
+ 'h': '35785831.0', 'lon_0': '0.0',
+ 'proj': 'geos', 'units': 'm'},
+ 5568, 464,
+ (3738502.0095458371, 3251436.5796920112,
+ -1830246.0673044831, 2787374.2399544837))
+
+ # transition
+ area4 = geometry.AreaDefinition("area4", 'area4', "geosmsg",
+ {'a': '6378169.0', 'b': '6356583.8',
+ 'h': '35785831.0', 'lon_0': '0.0',
+ 'proj': 'geos', 'units': 'm'},
+ 5568, 464,
+ (5567747.7409681147, 2787374.2399544837,
+ -1000.3358822065015, 2323311.9002169576))
+
+ final_area = geometry.StackedAreaDefinition(area3, area4)
+ self.assertEqual(len(final_area.defs), 2)
+ lons, lats = final_area.get_lonlats()
+ lons0, lats0 = final_area.defs[0].get_lonlats()
+ lons1, lats1 = final_area.defs[1].get_lonlats()
+ np.testing.assert_allclose(lons[:464, :], lons0)
+ np.testing.assert_allclose(lons[464:, :], lons1)
+ np.testing.assert_allclose(lats[:464, :], lats0)
+ np.testing.assert_allclose(lats[464:, :], lats1)
+
+ def test_combine_area_extents(self):
+ """Test combination of area extents."""
+ area1 = MagicMock()
+ area1.area_extent = (1, 2, 3, 4)
+ area2 = MagicMock()
+ area2.area_extent = (1, 6, 3, 2)
+ res = combine_area_extents_vertical(area1, area2)
+ self.assertListEqual(res, [1, 6, 3, 4])
+
+ area1 = MagicMock()
+ area1.area_extent = (1, 2, 3, 4)
+ area2 = MagicMock()
+ area2.area_extent = (1, 4, 3, 6)
+ res = combine_area_extents_vertical(area1, area2)
+ self.assertListEqual(res, [1, 2, 3, 6])
+
+ def test_append_area_defs_fail(self):
+ """Fail appending areas."""
+ area1 = MagicMock()
+ area1.proj_dict = {"proj": 'A'}
+ area1.x_size = 4
+ area1.y_size = 5
+ area2 = MagicMock()
+ area2.proj_dict = {'proj': 'B'}
+ area2.x_size = 4
+ area2.y_size = 6
+ # res = combine_area_extents_vertical(area1, area2)
+ self.assertRaises(IncompatibleAreas,
+ concatenate_area_defs, area1, area2)
+
+ @patch('pyresample.geometry.AreaDefinition')
+ def test_append_area_defs(self, adef):
+ """Test appending area definitions."""
+ x_size = random.randrange(6425)
+ area1 = MagicMock()
+ area1.area_extent = (1, 2, 3, 4)
+ area1.proj_dict = {"proj": 'A'}
+ area1.y_size = random.randrange(6425)
+ area1.x_size = x_size
+
+ area2 = MagicMock()
+ area2.area_extent = (1, 4, 3, 6)
+ area2.proj_dict = {"proj": 'A'}
+ area2.y_size = random.randrange(6425)
+ area2.x_size = x_size
+
+ res = concatenate_area_defs(area1, area2)
+ area_extent = [1, 2, 3, 6]
+ y_size = area1.y_size + area2.y_size
+ adef.assert_called_once_with(area1.area_id, area1.name, area1.proj_id,
+ area1.proj_dict, area1.x_size, y_size,
+ area_extent)
+
+
def suite():
"""The test suite.
"""
loader = unittest.TestLoader()
mysuite = unittest.TestSuite()
mysuite.addTest(loader.loadTestsFromTestCase(Test))
+ mysuite.addTest(loader.loadTestsFromTestCase(TestStackedAreaDefinition))
return mysuite
diff --git a/pyresample/test/test_utils.py b/pyresample/test/test_utils.py
index a70050b..4162fe0 100644
--- a/pyresample/test/test_utils.py
+++ b/pyresample/test/test_utils.py
@@ -1,10 +1,10 @@
import os
import unittest
-from pyresample import utils
-
import numpy as np
+from pyresample import utils
+
def tmp(f):
f.tmp = True
@@ -13,42 +13,65 @@ def tmp(f):
class Test(unittest.TestCase):
- def test_area_parser(self):
+ def test_area_parser_legacy(self):
+ """Test legacy area parser."""
ease_nh, ease_sh = utils.parse_area_file(os.path.join(os.path.dirname(__file__),
'test_files',
'areas.cfg'), 'ease_nh', 'ease_sh')
- nh_found = (ease_nh.__str__() == """Area ID: ease_nh
-Name: Arctic EASE grid
+ nh_str = """Area ID: ease_nh
+Description: Arctic EASE grid
Projection ID: ease_nh
Projection: {'a': '6371228.0', 'lat_0': '90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
Number of columns: 425
Number of rows: 425
-Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)""")
+Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)"""
+ self.assertEquals(ease_nh.__str__(), nh_str)
- sh_found = (ease_sh.__str__() == """Area ID: ease_sh
-Name: Antarctic EASE grid
+ sh_str = """Area ID: ease_sh
+Description: Antarctic EASE grid
Projection ID: ease_sh
Projection: {'a': '6371228.0', 'lat_0': '-90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
Number of columns: 425
Number of rows: 425
-Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)""")
+Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)"""
+ self.assertEquals(ease_sh.__str__(), sh_str)
- self.assertTrue(
- nh_found and sh_found, msg='Failed to parse areas correctly')
+ def test_area_parser_yaml(self):
+ """Test YAML area parser."""
+ ease_nh, ease_sh = utils.parse_area_file(os.path.join(os.path.dirname(__file__),
+ 'test_files',
+ 'areas.yaml'),
+ 'ease_nh', 'ease_sh')
+
+ nh_str = """Area ID: ease_nh
+Description: Arctic EASE grid
+Projection: {'a': '6371228.0', 'lat_0': '90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
+Number of columns: 425
+Number of rows: 425
+Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)"""
+ self.assertEquals(ease_nh.__str__(), nh_str)
+
+ sh_str = """Area ID: ease_sh
+Description: Antarctic EASE grid
+Projection: {'a': '6371228.0', 'lat_0': '-90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
+Number of columns: 425
+Number of rows: 425
+Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)"""
+ self.assertEquals(ease_sh.__str__(), sh_str)
def test_load_area(self):
ease_nh = utils.load_area(os.path.join(os.path.dirname(__file__),
'test_files',
'areas.cfg'), 'ease_nh')
- nh_found = (ease_nh.__str__() == """Area ID: ease_nh
-Name: Arctic EASE grid
+ nh_str = """Area ID: ease_nh
+Description: Arctic EASE grid
Projection ID: ease_nh
Projection: {'a': '6371228.0', 'lat_0': '90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
Number of columns: 425
Number of rows: 425
-Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)""")
- self.assertTrue(nh_found, msg='Failed to load area correctly')
+Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)"""
+ self.assertEquals(nh_str, ease_nh.__str__())
def test_not_found_exception(self):
self.assertRaises(utils.AreaNotFound, utils.parse_area_file,
diff --git a/pyresample/utils.py b/pyresample/utils.py
index 1f9a221..9284752 100644
--- a/pyresample/utils.py
+++ b/pyresample/utils.py
@@ -24,10 +24,11 @@
from __future__ import absolute_import
import numpy as np
+import six
+import yaml
from configobj import ConfigObj
import pyresample as pr
-import six
class AreaNotFound(Exception):
@@ -43,8 +44,8 @@ def load_area(area_file_name, *regions):
-----------
area_file_name : str
Path to area definition file
- regions : str argument list
- Regions to parse. If no regions are specified all
+ regions : str argument list
+ Regions to parse. If no regions are specified all
regions in the file are returned
Returns
@@ -73,8 +74,8 @@ def parse_area_file(area_file_name, *regions):
-----------
area_file_name : str
Path to area definition file
- regions : str argument list
- Regions to parse. If no regions are specified all
+ regions : str argument list
+ Regions to parse. If no regions are specified all
regions in the file are returned
Returns
@@ -88,6 +89,44 @@ def parse_area_file(area_file_name, *regions):
If a specified area is not found
"""
+ try:
+ return _parse_yaml_area_file(area_file_name, *regions)
+ except yaml.scanner.ScannerError:
+ return _parse_legacy_area_file(area_file_name, *regions)
+
+
+def _parse_yaml_area_file(area_file_name, *regions):
+ """Parse area information from a yaml area file."""
+
+ with open(area_file_name) as fd_:
+ area_dict = yaml.load(fd_)
+
+ area_list = regions or area_dict.keys()
+
+ res = []
+
+ for area_name in area_list:
+ try:
+ params = area_dict[area_name]
+ except KeyError:
+ raise AreaNotFound('Area "{0}" not found in file "{1}"'.format(
+ area_name, area_file_name))
+ description = params['description']
+ projection = params['projection']
+ xsize = params['shape']['width']
+ ysize = params['shape']['height']
+ area_extent = (params['area_extent']['lower_left_xy'] +
+ params['area_extent']['upper_right_xy'])
+ res.append(pr.geometry.AreaDefinition(area_name, description,
+ None, projection,
+ xsize, ysize,
+ area_extent))
+ return res
+
+
+def _parse_legacy_area_file(area_file_name, *regions):
+ """Parse area information from a legacy area file."""
+
area_file = open(area_file_name, 'r')
area_list = list(regions)
if len(area_list) == 0:
@@ -176,9 +215,9 @@ def get_area_def(area_id, area_name, proj_id, proj4_args, x_size, y_size,
Proj4 arguments as list of arguments or string
x_size : int
Number of pixel in x dimension
- y_size : int
+ y_size : int
Number of pixel in y dimension
- area_extent : list
+ area_extent : list
Area extent as a list of ints (LL_x, LL_y, UR_x, UR_y)
Returns
@@ -197,11 +236,11 @@ def generate_quick_linesample_arrays(source_area_def, target_area_def, nprocs=1)
Parameters
-----------
- source_area_def : object
+ source_area_def : object
Source area definition as AreaDefinition object
- target_area_def : object
+ target_area_def : object
Target area definition as AreaDefinition object
- nprocs : int, optional
+ nprocs : int, optional
Number of processor cores to be used
Returns
@@ -233,13 +272,13 @@ def generate_nearest_neighbour_linesample_arrays(source_area_def, target_area_de
Parameters
-----------
- source_area_def : object
+ source_area_def : object
Source area definition as AreaDefinition object
- target_area_def : object
+ target_area_def : object
Target area definition as AreaDefinition object
- radius_of_influence : float
+ radius_of_influence : float
Cut off distance in meters
- nprocs : int, optional
+ nprocs : int, optional
Number of processor cores to be used
Returns
@@ -294,7 +333,7 @@ def fwhm2sigma(fwhm):
Parameters
----------
- fwhm : float
+ fwhm : float
FWHM of gauss function (3 dB level of beam footprint)
Returns
@@ -318,6 +357,15 @@ def _get_proj4_args(proj4_args):
return proj_config.dict()
+def proj4_str_to_dict(proj4_str):
+ """Convert PROJ.4 compatible string definition to dict
+
+ Note: Key only parameters will be assigned a value of `True`.
+ """
+ pairs = (x.split('=', 1) for x in proj4_str.split(" "))
+ return dict((x[0], (x[1] if len(x) == 2 else True)) for x in pairs)
+
+
def _downcast_index_array(index_array, size):
"""Try to downcast array to uint16
"""
diff --git a/pyresample/version.py b/pyresample/version.py
index 31f6462..d73a813 100644
--- a/pyresample/version.py
+++ b/pyresample/version.py
@@ -15,4 +15,4 @@
# You should have received a copy of the GNU Lesser General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
-__version__ = '1.3.0'
+__version__ = '1.5.0'
diff --git a/setup.py b/setup.py
index 284b535..a1a38c1 100644
--- a/setup.py
+++ b/setup.py
@@ -26,7 +26,8 @@ from setuptools.command.build_ext import build_ext as _build_ext
version = imp.load_source('pyresample.version', 'pyresample/version.py')
-requirements = ['setuptools>=3.2', 'pyproj', 'numpy', 'configobj', 'pykdtree>=1.1.1']
+requirements = ['setuptools>=3.2', 'pyproj', 'numpy', 'configobj',
+ 'pykdtree>=1.1.1', 'pyyaml']
extras_require = {'pykdtree': ['pykdtree>=1.1.1'],
'numexpr': ['numexpr'],
'quicklook': ['matplotlib', 'basemap', 'pillow']}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/pyresample.git
More information about the Pkg-grass-devel
mailing list