[Git][debian-gis-team/pyresample][upstream] New upstream version 1.10.3
Antonio Valentino
gitlab at salsa.debian.org
Sat Dec 1 20:11:39 GMT 2018
Antonio Valentino pushed to branch upstream at Debian GIS Project / pyresample
Commits:
ebebf228 by Antonio Valentino at 2018-12-01T19:38:02Z
New upstream version 1.10.3
- - - - -
13 changed files:
- .travis.yml
- CHANGELOG.md
- appveyor.yml
- docs/source/API.rst
- pyresample/geometry.py
- pyresample/kd_tree.py
- pyresample/test/test_files/areas.cfg
- pyresample/test/test_geometry.py
- pyresample/test/test_kd_tree.py
- pyresample/test/test_utils.py
- pyresample/utils.py
- pyresample/version.py
- setup.py
Changes:
=====================================
.travis.yml
=====================================
@@ -4,12 +4,13 @@ env:
- PYTHON_VERSION=$PYTHON_VERSION
- NUMPY_VERSION=stable
- MAIN_CMD='python setup.py'
- - CONDA_DEPENDENCIES='xarray dask toolz Cython pykdtree sphinx cartopy pillow matplotlib
+ - CONDA_DEPENDENCIES='xarray dask toolz Cython pykdtree sphinx cartopy rasterio pillow matplotlib
pyyaml pyproj coveralls configobj coverage codecov'
- SETUP_XVFB=False
- EVENT_TYPE='push pull_request'
- SETUP_CMD='test'
- CONDA_CHANNELS='conda-forge'
+ - CONDA_CHANNEL_PRIORITY='True'
matrix:
include:
- env: PYTHON_VERSION=2.7
=====================================
CHANGELOG.md
=====================================
@@ -1,3 +1,26 @@
+## Version 1.10.3 (2018/11/23)
+
+### Issues Closed
+
+* [Issue 92](https://github.com/pytroll/pyresample/issues/92) - Add utility function for converting geotiffs to area definitions ([PR 143](https://github.com/pytroll/pyresample/pull/143))
+
+In this release 1 issue was closed.
+
+### Pull Requests Merged
+
+#### Bugs fixed
+
+* [PR 147](https://github.com/pytroll/pyresample/pull/147) - Fix dtype preservation for kdtree resampling
+* [PR 144](https://github.com/pytroll/pyresample/pull/144) - Non-contiguous area definitions are now not concatenable ([491](https://github.com/pytroll/satpy/issues/491))
+
+#### Features added
+
+* [PR 143](https://github.com/pytroll/pyresample/pull/143) - get_area_def_from_raster ([92](https://github.com/pytroll/pyresample/issues/92))
+* [PR 142](https://github.com/pytroll/pyresample/pull/142) - Add converter from def to yaml
+
+In this release 4 pull requests were closed.
+
+
## Version 1.10.2 (2018/10/01)
### Issues Closed
=====================================
appveyor.yml
=====================================
@@ -3,8 +3,9 @@ environment:
PYTHON: "C:\\conda"
MINICONDA_VERSION: "latest"
CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\ci-helpers\\appveyor\\windows_sdk.cmd"
- CONDA_DEPENDENCIES: "xarray dask toolz Cython pykdtree sphinx cartopy pillow matplotlib pyyaml pyproj coveralls configobj coverage"
+ CONDA_DEPENDENCIES: "xarray dask toolz Cython pykdtree sphinx cartopy rasterio pillow matplotlib pyyaml pyproj coveralls configobj coverage"
CONDA_CHANNELS: "conda-forge"
+ CONDA_CHANNEL_PRIORITY: "True"
matrix:
- PYTHON: "C:\\Python27_32"
=====================================
docs/source/API.rst
=====================================
@@ -1,49 +1,47 @@
pyresample API
-======================
+==============
pyresample.geometry
----------------------------------
+-------------------
.. automodule:: geometry
- :members:
+ :members:
pyresample.image
----------------------------------
+----------------
.. automodule:: image
- :members:
+ :members:
pyresample.grid
----------------------------------
+---------------
.. automodule:: grid
- :members:
+ :members:
pyresample.kd_tree
----------------------------------
+------------------
.. automodule:: kd_tree
- :members:
-
+ :members:
+
pyresample.bilinear
----------------------------------
+-------------------
.. automodule:: bilinear
- :members:
-
+ :members:
+
pyresample.utils
----------------------------------
+----------------
.. automodule:: utils
- :members:
+ :members:
pyresample.data_reduce
----------------------------------
+----------------------
.. automodule:: data_reduce
- :members:
+ :members:
pyresample.plot
----------------------------------
+---------------
.. automodule:: plot
- :members:
+ :members:
pyresample.ewa
--------------
.. automodule:: ewa
:members:
-
-
=====================================
pyresample/geometry.py
=====================================
@@ -920,21 +920,18 @@ class AreaDefinition(BaseDefinition):
return crs
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)
+
+ res = OrderedDict(description=self.name,
+ projection=OrderedDict(self.proj_dict),
+ shape=OrderedDict([('height', self.y_size), ('width', self.x_size)]))
+ units = res['projection'].pop('units', None)
+ extent = OrderedDict([('lower_left_xy', list(self.area_extent[:2])),
+ ('upper_right_xy', list(self.area_extent[2:]))])
+ if units is not None:
+ extent['units'] = units
+ res['area_extent'] = extent
+
+ return ordered_dump(OrderedDict([(self.area_id, res)]))
def create_areas_def_legacy(self):
proj_dict = self.proj_dict
@@ -1452,13 +1449,17 @@ def get_geostationary_bounding_box(geos_area, nb_points=50):
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]):
+ 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 non-contiguous area definitions: "
+ "{0} and {1}".format(area1, area2))
else:
raise IncompatibleAreas(
"Can't concatenate area definitions with "
=====================================
pyresample/kd_tree.py
=====================================
@@ -1077,12 +1077,16 @@ class XArrayResamplerNN(object):
Args:
data (dask.array.Array): Source data pixels to sample
fill_value (float): Output fill value when no source data is
- near the target pixel. If the input data
- is a integer array then the minimum value
- for that integer type is used. Otherwise,
- NaN is used and can be detected in the result
- with ``res.isnull()``.
-
+ near the target pixel. When omitted, if the input data is an
+ integer array then the maximum value for that integer type is
+ used, but otherwise, NaN is used and can be detected in the
+ result with ``res.isnull()``.
+
+ Returns:
+ dask.array.Array: The resampled array. The dtype of the array will
+ be the same as the input data. Pixels with no matching data from
+ the input array will be filled (see the `fill_value` parameter
+ description above).
"""
if fill_value is not None and np.isnan(fill_value) and \
np.issubdtype(data.dtype, np.integer):
@@ -1200,10 +1204,7 @@ class XArrayResamplerNN(object):
dtype=new_data.dtype, concatenate=True)
res = DataArray(res, dims=dst_dims, coords=coords,
attrs=data.attrs.copy())
- res.attrs['_FillValue'] = fill_value
- # if fill_value isn't NaN then we have to tell xarray what null is
- if not np.isnan(fill_value):
- res = res.where(res != fill_value)
+
return res
=====================================
pyresample/test/test_files/areas.cfg
=====================================
@@ -16,6 +16,15 @@ REGION: ease_nh {
AREA_EXTENT: (-5326849.0625,-5326849.0625,5326849.0625,5326849.0625)
};
+#REGION: commented {
+# NAME: Arctic EASE grid
+# PCS_ID: ease_nh
+# PCS_DEF: proj=laea, lat_0=90, lon_0=0, a=6371228.0, units=m
+# XSIZE: 425
+# YSIZE: 425
+# AREA_EXTENT: (-5326849.0625,-5326849.0625,5326849.0625,5326849.0625)
+# };
+
REGION: pc_world {
NAME: Plate Carree world map
PCS_ID: pc_world
=====================================
pyresample/test/test_geometry.py
=====================================
@@ -89,6 +89,33 @@ class Test(unittest.TestCase):
area_def.area_extent[1],
area_def.area_extent[3]))
+ def test_create_areas_def(self):
+ area_def = geometry.AreaDefinition('areaD', 'Europe (3km, HRV, VTC)',
+ 'areaD',
+ {'a': '6378144.0',
+ 'b': '6356759.0',
+ 'lat_0': '50.00',
+ 'lat_ts': '50.00',
+ 'lon_0': '8.00',
+ 'proj': 'stere'},
+ 800,
+ 800,
+ [-1370912.72,
+ -909968.64000000001,
+ 1029087.28,
+ 1490031.3600000001])
+ import yaml
+ res = yaml.load(area_def.create_areas_def())
+ expected = yaml.load(('areaD:\n description: Europe (3km, HRV, VTC)\n'
+ ' projection:\n a: 6378144.0\n b: 6356759.0\n'
+ ' lat_0: 50.0\n lat_ts: 50.0\n lon_0: 8.0\n'
+ ' proj: stere\n shape:\n height: 800\n'
+ ' width: 800\n area_extent:\n'
+ ' lower_left_xy: [-1370912.72, -909968.64]\n'
+ ' upper_right_xy: [1029087.28, 1490031.36]\n'))
+
+ self.assertDictEqual(res, expected)
+
def test_base_type(self):
lons1 = np.arange(-135., +135, 50.)
lats = np.ones_like(lons1) * 70.
@@ -866,15 +893,15 @@ class Test(unittest.TestCase):
proj_dict, 10, 10,
[-1370912.72, -909968.64, 1029087.28,
1490031.36])
- self.assertEquals(area.proj_str,
- '+a=6378144.0 +b=6356759.0 +lat_0=50.0 +lat_ts=50.0 +lon_0=8.0 +proj=stere')
+ self.assertEqual(area.proj_str,
+ '+a=6378144.0 +b=6356759.0 +lat_0=50.0 +lat_ts=50.0 +lon_0=8.0 +proj=stere')
proj_dict['no_rot'] = ''
area = geometry.AreaDefinition('areaD', 'Europe (3km, HRV, VTC)', 'areaD',
proj_dict, 10, 10,
[-1370912.72, -909968.64, 1029087.28,
1490031.36])
- self.assertEquals(area.proj_str,
- '+a=6378144.0 +b=6356759.0 +lat_0=50.0 +lat_ts=50.0 +lon_0=8.0 +no_rot +proj=stere')
+ self.assertEqual(area.proj_str,
+ '+a=6378144.0 +b=6356759.0 +lat_0=50.0 +lat_ts=50.0 +lon_0=8.0 +no_rot +proj=stere')
def assert_np_dict_allclose(dict1, dict2):
@@ -1239,6 +1266,14 @@ class TestStackedAreaDefinition(unittest.TestCase):
res = combine_area_extents_vertical(area1, area2)
self.assertListEqual(res, [1, 2, 3, 6])
+ # Non contiguous area extends shouldn't be combinable
+ area1 = MagicMock()
+ area1.area_extent = (1, 2, 3, 4)
+ area2 = MagicMock()
+ area2.area_extent = (1, 5, 3, 7)
+ self.assertRaises(IncompatibleAreas,
+ combine_area_extents_vertical, area1, area2)
+
def test_append_area_defs_fail(self):
"""Fail appending areas."""
area1 = MagicMock()
=====================================
pyresample/test/test_kd_tree.py
=====================================
@@ -797,6 +797,34 @@ class TestXArrayResamplerNN(unittest.TestCase):
])
np.testing.assert_allclose(actual, expected)
+ def test_nearest_type_preserve(self):
+ """Test 1D swath definition to 2D grid definition; 1 neighbor."""
+ from pyresample.kd_tree import XArrayResamplerNN
+ import xarray as xr
+ import dask.array as da
+ resampler = XArrayResamplerNN(self.tswath_1d, self.tgrid,
+ radius_of_influence=100000,
+ neighbours=1)
+ data = self.tdata_1d
+ data = xr.DataArray(da.from_array(np.array([1, 2, 3]),
+ chunks=5),
+ dims=('my_dim1',))
+ ninfo = resampler.get_neighbour_info()
+ for val in ninfo[:3]:
+ # vii, ia, voi
+ self.assertIsInstance(val, da.Array)
+ res = resampler.get_sample_from_neighbour_info(data, fill_value=255)
+ self.assertIsInstance(res, xr.DataArray)
+ self.assertIsInstance(res.data, da.Array)
+ actual = res.values
+ expected = np.array([
+ [1, 2, 2],
+ [1, 2, 2],
+ [1, 255, 2],
+ [1, 2, 2],
+ ])
+ np.testing.assert_equal(actual, expected)
+
def test_nearest_swath_2d_mask_to_area_1n(self):
"""Test 2D swath definition to 2D area definition; 1 neighbor."""
from pyresample.kd_tree import XArrayResamplerNN
=====================================
pyresample/test/test_utils.py
=====================================
@@ -2,6 +2,7 @@ import os
import unittest
import numpy as np
+import uuid
from pyresample.test.utils import create_test_longitude, create_test_latitude
@@ -11,6 +12,16 @@ def tmp(f):
return f
+def tmptiff(width=100, height=100, transform=None, crs=None, dtype=np.uint8):
+ import rasterio
+ array = np.ones((width, height)).astype(dtype)
+ fname = '/vsimem/%s' % uuid.uuid4()
+ with rasterio.open(fname, 'w', driver='GTiff', count=1, transform=transform,
+ width=width, height=height, crs=crs, dtype=dtype) as dst:
+ dst.write(array, 1)
+ return fname
+
+
class TestLegacyAreaParser(unittest.TestCase):
def test_area_parser_legacy(self):
"""Test legacy area parser."""
@@ -26,7 +37,7 @@ Projection: {'a': '6371228.0', 'lat_0': '90.0', 'lon_0': '0.0', 'proj': 'laea',
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)
+ self.assertEqual(ease_nh.__str__(), nh_str)
self.assertIsInstance(ease_nh.proj_dict['lat_0'], float)
sh_str = """Area ID: ease_sh
@@ -36,7 +47,7 @@ Projection: {'a': '6371228.0', 'lat_0': '-90.0', 'lon_0': '0.0', 'proj': 'laea',
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)
+ self.assertEqual(ease_sh.__str__(), sh_str)
self.assertIsInstance(ease_sh.proj_dict['lat_0'], float)
def test_load_area(self):
@@ -51,7 +62,7 @@ Projection: {'a': '6371228.0', 'lat_0': '90.0', 'lon_0': '0.0', 'proj': 'laea',
Number of columns: 425
Number of rows: 425
Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)"""
- self.assertEquals(nh_str, ease_nh.__str__())
+ self.assertEqual(nh_str, ease_nh.__str__())
def test_not_found_exception(self):
from pyresample import utils
@@ -60,6 +71,12 @@ Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)"""
os.path.dirname(__file__), 'test_files', 'areas.cfg'),
'no_area')
+ def test_commented(self):
+ from pyresample import utils
+ areas = utils.parse_area_file(os.path.join(os.path.dirname(__file__),
+ 'test_files', 'areas.cfg'))
+ self.assertNotIn('commented', [area.name for area in areas])
+
class TestYAMLAreaParser(unittest.TestCase):
def test_area_parser_yaml(self):
@@ -76,7 +93,7 @@ Projection: {'a': '6371228.0', 'lat_0': '90.0', 'lon_0': '0.0', 'proj': 'laea',
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)
+ self.assertEqual(ease_nh.__str__(), nh_str)
sh_str = """Area ID: ease_sh
Description: Antarctic EASE grid
@@ -84,7 +101,7 @@ Projection: {'a': '6371228.0', 'lat_0': '-90.0', 'lon_0': '0.0', 'proj': 'laea',
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)
+ self.assertEqual(ease_sh.__str__(), sh_str)
def test_multiple_file_content(self):
from pyresample import utils
@@ -121,7 +138,7 @@ Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)"""
units: m
"""]
results = utils.parse_area_file(area_list)
- self.assertEquals(len(results), 2)
+ self.assertEqual(len(results), 2)
self.assertIn(results[0].area_id, ('ease_sh', 'ease_sh2'))
self.assertIn(results[1].area_id, ('ease_sh', 'ease_sh2'))
@@ -137,7 +154,7 @@ class TestPreprocessing(unittest.TestCase):
extents2 = [-1000, -1000, 1000. * 4000, 1000. * 4000]
area_def2 = geometry.AreaDefinition('CONUS', 'CONUS', 'CONUS',
- proj_dict, 600, 700, extents2)
+ proj_dict, 600, 700, extents2)
rows, cols = utils.generate_nearest_neighbour_linesample_arrays(area_def, area_def2, 12000.)
def test_nearest_neighbor_area_grid(self):
@@ -251,6 +268,79 @@ class TestMisc(unittest.TestCase):
self.assertIsInstance(proj_dict['lon_0'], float)
self.assertIsInstance(proj_dict2['lon_0'], float)
+ def test_def2yaml_converter(self):
+ from pyresample import utils
+ import tempfile
+ def_file = os.path.join(os.path.dirname(__file__), 'test_files',
+ 'areas.cfg')
+ filehandle, yaml_file = tempfile.mkstemp()
+ os.close(filehandle)
+ try:
+ utils.convert_def_to_yaml(def_file, yaml_file)
+ areas_new = set(utils.parse_area_file(yaml_file))
+ areas_old = set(utils.parse_area_file(def_file))
+
+ self.assertEqual(areas_new, areas_old)
+ finally:
+ os.remove(yaml_file)
+
+ def test_get_area_def_from_raster(self):
+ from rasterio.crs import CRS
+ from affine import Affine
+ from pyresample import utils
+ x_size = 791
+ y_size = 718
+ transform = Affine(300.0379266750948, 0.0, 101985.0,
+ 0.0, -300.041782729805, 2826915.0)
+ crs = CRS(init='epsg:3857')
+ source = tmptiff(x_size, y_size, transform, crs=crs)
+ area_id = 'area_id'
+ proj_id = 'proj_id'
+ name = 'name'
+ area_def = utils.get_area_def_from_raster(source, area_id=area_id, name=name, proj_id=proj_id)
+ self.assertEqual(area_def.area_id, area_id)
+ self.assertEqual(area_def.proj_id, proj_id)
+ self.assertEqual(area_def.name, name)
+ self.assertEqual(area_def.x_size, x_size)
+ self.assertEqual(area_def.y_size, y_size)
+ self.assertDictEqual(crs.to_dict(), area_def.proj_dict)
+ self.assertTupleEqual(area_def.area_extent, (transform.c, transform.f + transform.e * y_size,
+ transform.c + transform.a * x_size, transform.f))
+
+ def test_get_area_def_from_raster_extracts_proj_id(self):
+ from rasterio.crs import CRS
+ from pyresample import utils
+ crs = CRS(init='epsg:3857')
+ source = tmptiff(crs=crs)
+ area_def = utils.get_area_def_from_raster(source)
+ self.assertEqual(area_def.proj_id, 'WGS 84 / Pseudo-Mercator')
+
+ def test_get_area_def_from_raster_rotated_value_err(self):
+ from pyresample import utils
+ from affine import Affine
+ transform = Affine(300.0379266750948, 0.1, 101985.0,
+ 0.0, -300.041782729805, 2826915.0)
+ source = tmptiff(transform=transform)
+ self.assertRaises(ValueError, utils.get_area_def_from_raster, source)
+
+ def test_get_area_def_from_raster_non_georef_value_err(self):
+ from pyresample import utils
+ from affine import Affine
+ transform = Affine(300.0379266750948, 0.0, 101985.0,
+ 0.0, -300.041782729805, 2826915.0)
+ source = tmptiff(transform=transform)
+ self.assertRaises(ValueError, utils.get_area_def_from_raster, source)
+
+ def test_get_area_def_from_raster_non_georef_respects_proj_dict(self):
+ from pyresample import utils
+ from affine import Affine
+ transform = Affine(300.0379266750948, 0.0, 101985.0,
+ 0.0, -300.041782729805, 2826915.0)
+ source = tmptiff(transform=transform)
+ proj_dict = {'init': 'epsg:3857'}
+ area_def = utils.get_area_def_from_raster(source, proj_dict=proj_dict)
+ self.assertDictEqual(area_def.proj_dict, proj_dict)
+
def suite():
"""The test suite.
@@ -263,3 +353,7 @@ def suite():
mysuite.addTest(loader.loadTestsFromTestCase(TestMisc))
return mysuite
+
+
+if __name__ == '__main__':
+ unittest.main()
=====================================
pyresample/utils.py
=====================================
@@ -28,7 +28,7 @@ import numpy as np
import six
import yaml
from configobj import ConfigObj
-from collections import Mapping
+from collections import Mapping, OrderedDict
class AreaNotFound(KeyError):
@@ -149,6 +149,10 @@ def _parse_yaml_area_file(area_file_name, *regions):
params['area_extent']['upper_right_xy'])
except KeyError:
area_extent = None
+ try:
+ projection['units'] = params['area_extent']['units']
+ except KeyError:
+ pass
try:
rotation = params['rotation']
except KeyError:
@@ -202,7 +206,7 @@ def _parse_legacy_area_file(area_file_name, *regions):
in_area = False
for line in area_file:
if not in_area:
- if 'REGION' in line:
+ if 'REGION' in line and not line.strip().startswith('#'):
area_id = line.replace('REGION:', ''). \
replace('{', '').strip()
if area_id in area_list or select_all_areas:
@@ -210,11 +214,14 @@ def _parse_legacy_area_file(area_file_name, *regions):
area_content = ''
elif '};' in line:
in_area = False
- if select_all_areas:
- area_defs.append(_create_area(area_id, area_content))
- else:
- area_defs[area_list.index(area_id)] = _create_area(area_id,
- area_content)
+ try:
+ if select_all_areas:
+ area_defs.append(_create_area(area_id, area_content))
+ else:
+ area_defs[area_list.index(area_id)] = _create_area(area_id,
+ area_content)
+ except KeyError:
+ raise ValueError('Invalid area definition: %s, %s' % (area_id, area_content))
else:
area_content += line
@@ -298,6 +305,110 @@ def get_area_def(area_id, area_name, proj_id, proj4_args, x_size, y_size,
x_size, y_size, area_extent)
+def _get_area_def_from_gdal(dataset, area_id=None, name=None, proj_id=None, proj_dict=None):
+ from pyresample.geometry import AreaDefinition
+
+ # a: width of a pixel
+ # b: row rotation (typically zero)
+ # c: x-coordinate of the upper-left corner of the upper-left pixel
+ # d: column rotation (typically zero)
+ # e: height of a pixel (typically negative)
+ # f: y-coordinate of the of the upper-left corner of the upper-left pixel
+ c, a, b, f, d, e = dataset.GetGeoTransform()
+ if not (b == d == 0):
+ raise ValueError('Rotated rasters are not supported at this time.')
+ area_extent = (c, f + e * dataset.RasterYSize, c + a * dataset.RasterXSize, f)
+
+ if proj_dict is None:
+ from osgeo import osr
+ proj = dataset.GetProjection()
+ if proj != '':
+ sref = osr.SpatialReference(wkt=proj)
+ proj_dict = proj4_str_to_dict(sref.ExportToProj4())
+ else:
+ raise ValueError('The source raster is not gereferenced, please provide the value of proj_dict')
+
+ if proj_id is None:
+ proj_id = proj.split('"')[1]
+
+ area_def = AreaDefinition(area_id, name, proj_id, proj_dict,
+ dataset.RasterXSize, dataset.RasterYSize, area_extent)
+ return area_def
+
+
+def _get_area_def_from_rasterio(dataset, area_id, name, proj_id=None, proj_dict=None):
+ from pyresample.geometry import AreaDefinition
+
+ a, b, c, d, e, f, _, _, _ = dataset.transform
+ if not (b == d == 0):
+ raise ValueError('Rotated rasters are not supported at this time.')
+
+ if proj_dict is None:
+ crs = dataset.crs
+ if crs is not None:
+ proj_dict = dataset.crs.to_dict()
+ else:
+ raise ValueError('The source raster is not gereferenced, please provide the value of proj_dict')
+
+ if proj_id is None:
+ proj_id = crs.wkt.split('"')[1]
+
+ area_def = AreaDefinition(area_id, name, proj_id, proj_dict,
+ dataset.width, dataset.height, dataset.bounds)
+ return area_def
+
+
+def get_area_def_from_raster(source, area_id=None, name=None, proj_id=None, proj_dict=None):
+ """Construct AreaDefinition object from raster
+
+ Parameters
+ ----------
+ source : str, Dataset, DatasetReader or DatasetWriter
+ A file name. Also it can be ``osgeo.gdal.Dataset``,
+ ``rasterio.io.DatasetReader`` or ``rasterio.io.DatasetWriter``
+ area_id : str, optional
+ ID of area
+ name : str, optional
+ Name of area
+ proj_id : str, optional
+ ID of projection
+ proj_dict : dict, optional
+ PROJ.4 parameters
+
+ Returns
+ -------
+ area_def : object
+ AreaDefinition object
+ """
+ try:
+ import rasterio
+ except ImportError:
+ rasterio = None
+ try:
+ from osgeo import gdal
+ except ImportError:
+ raise ImportError('Either rasterio or gdal must be available')
+
+ cleanup_gdal = cleanup_rasterio = None
+ if isinstance(source, (str, six.text_type)):
+ if rasterio is not None:
+ source = rasterio.open(source)
+ cleanup_rasterio = True
+ else:
+ source = gdal.Open(source)
+ cleanup_gdal = True
+
+ try:
+ if rasterio is not None and isinstance(source, (rasterio.io.DatasetReader, rasterio.io.DatasetWriter)):
+ return _get_area_def_from_rasterio(source, area_id, name, proj_id, proj_dict)
+ return _get_area_def_from_gdal(source, area_id, name, proj_id, proj_dict)
+ finally:
+ if cleanup_rasterio:
+ source.close()
+ elif cleanup_gdal:
+ source = None
+
+
def generate_quick_linesample_arrays(source_area_def, target_area_def,
nprocs=1):
"""Generate linesample arrays for quick grid resampling
@@ -410,7 +521,7 @@ def fwhm2sigma(fwhm):
def convert_proj_floats(proj_pairs):
"""Convert PROJ.4 parameters to floats if possible."""
- proj_dict = {}
+ proj_dict = OrderedDict()
for x in proj_pairs:
if len(x) == 1 or x[1] is True:
proj_dict[x[0]] = True
@@ -429,10 +540,10 @@ def _get_proj4_args(proj4_args):
"""
if isinstance(proj4_args, (str, six.text_type)):
- proj_config = ConfigObj(str(proj4_args).replace('+', '').split())
+ proj_config = proj4_str_to_dict(str(proj4_args))
else:
proj_config = ConfigObj(proj4_args)
- return convert_proj_floats(proj_config.dict().items())
+ return convert_proj_floats(proj_config.items())
def proj4_str_to_dict(proj4_str):
@@ -570,3 +681,14 @@ def recursive_dict_update(d, u):
else:
d[k] = u[k]
return d
+
+
+def convert_def_to_yaml(def_area_file, yaml_area_file):
+ """Convert a legacy area def file to the yaml counter partself.
+
+ *yaml_area_file* will be overwritten by the operation.
+ """
+ areas = _parse_legacy_area_file(def_area_file)
+ with open(yaml_area_file, 'w') as yaml_file:
+ for area in areas:
+ yaml_file.write(area.create_areas_def())
=====================================
pyresample/version.py
=====================================
@@ -16,4 +16,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.10.2'
+__version__ = '1.10.3'
=====================================
setup.py
=====================================
@@ -31,9 +31,10 @@ requirements = ['setuptools>=3.2', 'pyproj>=1.9.5.1', 'numpy>=1.10.0', 'configob
extras_require = {'pykdtree': ['pykdtree>=1.1.1'],
'numexpr': ['numexpr'],
'quicklook': ['matplotlib', 'cartopy', 'pillow'],
+ 'rasterio': ['rasterio'],
'dask': ['dask>=0.16.1']}
-test_requires = []
+test_requires = ['rasterio']
if sys.version_info < (3, 3):
test_requires.append('mock')
if sys.version_info < (2, 6):
View it on GitLab: https://salsa.debian.org/debian-gis-team/pyresample/commit/ebebf22839cbd5a534d1d43b4f19d84b975a0a32
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/pyresample/commit/ebebf22839cbd5a534d1d43b4f19d84b975a0a32
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20181201/90f07e46/attachment-0001.html>
More information about the Pkg-grass-devel
mailing list