[python-mpop] 01/06: New upstream version 1.4.0

Antonio Valentino a_valentino-guest at moszumanska.debian.org
Sun Mar 12 09:29:25 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 python-mpop.

commit f15522bf67c76a0d975831f91ed7194dcba8bdd0
Author: Antonio Valentino <antonio.valentino at tiscali.it>
Date:   Sun Mar 12 08:20:29 2017 +0000

    New upstream version 1.4.0
---
 .bumpversion.cfg                 |  2 +-
 .travis.yml                      |  1 -
 changelog.rst                    | 52 +++++++++++++++++++++++
 etc/Himawari-8.cfg.template      |  5 +--
 mpop/imageo/formats/ninjotiff.py | 36 +++++++++-------
 mpop/instruments/viirs.py        |  9 ++--
 mpop/projector.py                | 76 +++++++++++++++++++++++++++++----
 mpop/satin/helper_functions.py   |  1 +
 mpop/satin/nc_osisaf_l2.py       |  2 +-
 mpop/satin/viirs_sdr.py          | 91 +++++++++++++++++++++++++++++++++++++++-
 mpop/tests/test_projector.py     | 70 ++++++++++++++++++-------------
 mpop/version.py                  |  2 +-
 12 files changed, 284 insertions(+), 63 deletions(-)

diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 8167558..3ed55f4 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 1.3.1
+current_version = 1.4.0
 commit = True
 tag = True
 
diff --git a/.travis.yml b/.travis.yml
index e98e6be..8b12589 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,5 @@
 language: python
 python:
-- '2.6'
 - '2.7'
 install:
 - pip install .
diff --git a/changelog.rst b/changelog.rst
index 9e2670a..4ed0c52 100644
--- a/changelog.rst
+++ b/changelog.rst
@@ -1,6 +1,58 @@
 Changelog
 =========
 
+v1.4.0 (2017-02-20)
+-------------------
+
+- Update changelog. [Martin Raspaud]
+
+- Bump version: 1.3.1 → 1.4.0. [Martin Raspaud]
+
+- Merge pull request #44 from pytroll/feature_bilinear. [Martin Raspaud]
+
+  Feature bilinear
+
+- Clarify docstring - radius is also used with bilinear mode. [Panu
+  Lahtinen]
+
+- Test that bilinear interpolation is called. [Panu Lahtinen]
+
+- Mock pyresample.bilinear, autopep8 the file. [Panu Lahtinen]
+
+- Update docstring. [Panu Lahtinen]
+
+- Move imports to top of the file. [Panu Lahtinen]
+
+- Remove Python 2.6 from the tested versions. [Panu Lahtinen]
+
+- Require Pillow version < 4.0.0 for Python 2.6. [Panu Lahtinen]
+
+- Add mask to bilinear resampled data. [Panu Lahtinen]
+
+- Fix naming. [Panu Lahtinen]
+
+- Add implicit flag to receive un-masked parameters for bilinear
+  interpolation. [Panu Lahtinen]
+
+- Add bilinear interpolation. [Panu Lahtinen]
+
+- Merge branch 'pre-master' of github.com:pytroll/mpop into pre-master.
+  [Adam.Dybbroe]
+
+- Clear cache before inserting EWA parameters. [Panu Lahtinen]
+
+- Add EWA resampling. [Panu Lahtinen]
+
+- Convert maximum extent to list before modification. [Martin Raspaud]
+
+- Do the scaling before finalization in ninjotiff's finalize. [Martin
+  Raspaud]
+
+- Fix H8 template file's band names. [Martin Raspaud]
+
+- Extract elevation from viirs-sdr + Fix viirs true color.
+  [Adam.Dybbroe]
+
 v1.3.1 (2016-12-12)
 -------------------
 
diff --git a/etc/Himawari-8.cfg.template b/etc/Himawari-8.cfg.template
index 594b05a..f8b1dd3 100644
--- a/etc/Himawari-8.cfg.template
+++ b/etc/Himawari-8.cfg.template
@@ -69,13 +69,13 @@ resolution = 2000.0
 size = (5500, 5500)
 
 [ahi-8]
-name = 'B08'
+name = 'IR3'
 frequency = (6.06, 6.25, 6.43)
 resolution = 2000.0
 size = (5500, 5500)
 
 [ahi-9]
-name = 'IR3'
+name = 'B09'
 frequency = (6.89, 6.95, 7.01)
 resolution = 2000.0
 size = (5500, 5500)
@@ -121,4 +121,3 @@ name = 'B16'
 frequency = (13.2, 13.3, 13.4)
 resolution = 2000.0
 size = (5500, 5500)
-
diff --git a/mpop/imageo/formats/ninjotiff.py b/mpop/imageo/formats/ninjotiff.py
index be72489..ae0bf4f 100644
--- a/mpop/imageo/formats/ninjotiff.py
+++ b/mpop/imageo/formats/ninjotiff.py
@@ -311,34 +311,40 @@ def _finalize(geo_image, dtype=np.uint8, value_range_measurement_unit=None, data
             offset = 0
         else:
             if value_range_measurement_unit and data_is_scaled_01:
-                # No additional scaling of the input data - assume that data is within [0.0, 1.0]
-                # and interpretate 0.0 as value_range_measurement_unit[0]
-                # and 1.0 as value_range_measurement_unit[1]
+                # No additional scaling of the input data - assume that data is
+                # within [0.0, 1.0] and interpret 0.0 as
+                # value_range_measurement_unit[0] and 1.0 as
+                # value_range_measurement_unit[1]
+
+                # Make room for transparent pixel.
+                scale_fill_value = (
+                    (np.iinfo(dtype).max) / (np.iinfo(dtype).max + 1.0))
+                geo_image = deepcopy(geo_image)
+                geo_image.channels[0] *= scale_fill_value
+
+                geo_image.channels[0] += 1 / (np.iinfo(dtype).max + 1.0)
+
                 channels, fill_value = geo_image._finalize(dtype)
-                fill_value = fill_value or (0,)
                 data = channels[0]
 
-                scale = ((value_range_measurement_unit[1] - value_range_measurement_unit[0]) /
-                         (np.iinfo(dtype).max - 1.0))
-
+                scale = ((value_range_measurement_unit[1] -
+                          value_range_measurement_unit[0]) /
+                         (np.iinfo(dtype).max))
                 # Handle the case where all data has the same value.
                 scale = scale or 1
                 offset = value_range_measurement_unit[0]
 
                 mask = data.mask
 
-                # Make room for transparent pixel.
-                scale_fill_value = (
-                    (np.iinfo(dtype).max - 1.0) / np.iinfo(dtype).max)
-                data = 1 + (data.data * scale_fill_value).astype(dtype)
-
                 offset -= scale
-                scale /= scale_fill_value
+
+                if fill_value is None:
+                    fill_value = 0
 
             else:
                 if value_range_measurement_unit:
-                    data.clip(value_range_measurement_unit[
-                              0], value_range_measurement_unit[1], data)
+                    data.clip(value_range_measurement_unit[0],
+                              value_range_measurement_unit[1], data)
                     chn_min = value_range_measurement_unit[0]
                     chn_max = value_range_measurement_unit[1]
                     log.debug("Scaling, using value range %.2f - %.2f" %
diff --git a/mpop/instruments/viirs.py b/mpop/instruments/viirs.py
index d738c55..90de50b 100644
--- a/mpop/instruments/viirs.py
+++ b/mpop/instruments/viirs.py
@@ -137,11 +137,13 @@ class ViirsCompositer(VisirCompositer):
         """Make a True Color RGB image composite from
         M-bands only.
         """
-        self.check_channels('M02', 'M04', 'M05')
+        #elf.check_channels('M02', 'M04', 'M05')
+        self.check_channels('M03', 'M04', 'M05')
 
         ch1 = self['M05'].check_range()
         ch2 = self['M04'].check_range()
-        ch3 = self['M02'].check_range()
+        #h3 = self['M02'].check_range()
+        ch3 = self['M03'].check_range()
 
         img = geo_image.GeoImage((ch1, ch2, ch3),
                                  self.area,
@@ -156,7 +158,8 @@ class ViirsCompositer(VisirCompositer):
 
         return img
 
-    truecolor.prerequisites = set(['M02', 'M04', 'M05'])
+    truecolor.prerequisites = set(['M03', 'M04', 'M05'])
+#   truecolor.prerequisites = set(['M02', 'M04', 'M05'])
 
     def natural(self):
         """Make a Natural Colors RGB image composite from
diff --git a/mpop/projector.py b/mpop/projector.py
index 4a11958..e31dbfd 100644
--- a/mpop/projector.py
+++ b/mpop/projector.py
@@ -39,6 +39,8 @@ import logging
 
 import numpy as np
 from pyresample import image, utils, geometry, kd_tree
+from pyresample.bilinear import get_sample_from_bil_info, get_bil_info
+
 from mpop import CONFIG_PATH
 
 logger = logging.getLogger(__name__)
@@ -93,11 +95,15 @@ class Projector(object):
     generated projectors can be saved to disk for later reuse. Use the
     :meth:`save` method for this.
 
-    To define a projector object, on has to specify *in_area* and *out_area*,
-    and can also input the *in_lonlats* or the *mode* ('quick' which works only
-    if both in- and out-areas are AreaDefinitions, or 'nearest'). *radius*
-    defines the radius of influence for nearest neighbour search in 'nearest'
-    mode.
+    To define a projector object, on has to specify *in_area* and
+    *out_area*, and can also input the *in_lonlats* or the *mode*.
+    Available modes area:
+    - 'quick' (works only if both in- and out-areas are AreaDefinitions)
+    - 'bilinear' (out-area needs to be AreaDefinition with proj4_string)
+    - 'ewa'
+    - 'nearest'.
+    *radius* defines the radius of influence for nearest neighbour
+    search in 'nearest' and 'bilinear' modes.
     """
 
     def __init__(self, in_area, out_area,
@@ -105,8 +111,9 @@ class Projector(object):
                  radius=10000, nprocs=1):
 
         if (mode is not None and
-                mode not in ["quick", "nearest"]):
-            raise ValueError("Projector mode must be 'nearest' or 'quick'")
+                mode not in ["quick", "nearest", "ewa", "bilinear"]):
+            raise ValueError("Projector mode must be one of 'nearest', "
+                             "'quick', 'ewa', 'bilinear'")
 
         self.area_file = get_area_file()
 
@@ -133,6 +140,7 @@ class Projector(object):
                 self.in_area = in_area
             except AttributeError:
                 try:
+                    # TODO: Note that latlons are in order (lons, lats)
                     self.in_area = geometry.SwathDefinition(lons=in_latlons[0],
                                                             lats=in_latlons[1])
                     in_id = in_area
@@ -160,7 +168,7 @@ class Projector(object):
                                          self.area_file + " or "
                                          "be an area object.")
 
-        #if self.in_area == self.out_area:
+        # if self.in_area == self.out_area:
         #    return
 
         # choosing the right mode if necessary
@@ -216,6 +224,29 @@ class Projector(object):
                 self._cache['row_idx'] = ridx
                 self._cache['col_idx'] = cidx
 
+            elif self.mode == "ewa":
+                from pyresample.ewa import ll2cr
+                swath_points_in_grid, cols, rows = ll2cr(self.in_area,
+                                                         self.out_area)
+                self._cache = {}
+                # self._cache['ewa_swath_points_in_grid'] = \
+                #     swath_points_in_grid
+                self._cache['ewa_cols'] = cols
+                self._cache['ewa_rows'] = rows
+
+            elif self.mode == "bilinear":
+
+                bilinear_t, bilinear_s, input_idxs, idx_arr = \
+                    get_bil_info(self.in_area, self.out_area,
+                                 self.radius, neighbours=32,
+                                 nprocs=nprocs, masked=False)
+
+                self._cache = {}
+                self._cache['bilinear_s'] = bilinear_s
+                self._cache['bilinear_t'] = bilinear_t
+                self._cache['input_idxs'] = input_idxs
+                self._cache['idx_arr'] = idx_arr
+
     def save(self, resave=False):
         """Save the precomputation to disk, and overwrite existing file in case
         *resave* is true.
@@ -258,4 +289,33 @@ class Projector(object):
             res = np.ma.array(img.get_array_from_linesample(row_idx, col_idx),
                               dtype=data.dtype)
 
+        elif self.mode == "ewa":
+            from pyresample.ewa import fornav
+            # TODO: should be user configurable?
+            rows_per_scan = None
+
+            if 'ewa_cols' not in self._cache:
+                self._cache['ewa_cols'] = self._file_cache['ewa_cols']
+                self._cache['ewa_rows'] = self._file_cache['ewa_rows']
+            num_valid_points, res = fornav(self._cache['ewa_cols'],
+                                           self._cache['ewa_rows'],
+                                           self.out_area, data,
+                                           rows_per_scan=rows_per_scan)
+
+        elif self.mode == "bilinear":
+
+            if 'bilinear_t' not in self._cache:
+                self._cache['bilinear_t'] = self._file_cache['bilinear_t']
+                self._cache['bilinear_s'] = self._file_cache['bilinear_s']
+                self._cache['input_idxs'] = self._file_cache['input_idxs']
+                self._cache['idx_arr'] = self._file_cache['idx_arr']
+
+            res = get_sample_from_bil_info(data.ravel(),
+                                           self._cache['bilinear_t'],
+                                           self._cache['bilinear_s'],
+                                           self._cache['input_idxs'],
+                                           self._cache['idx_arr'],
+                                           output_shape=self.out_area.shape)
+            res = np.ma.masked_invalid(res)
+
         return res
diff --git a/mpop/satin/helper_functions.py b/mpop/satin/helper_functions.py
index 8f6c71d..d45a4bc 100644
--- a/mpop/satin/helper_functions.py
+++ b/mpop/satin/helper_functions.py
@@ -87,6 +87,7 @@ def area_def_names_to_extent(area_def_names, proj4_str,
         if not maximum_extent:
             return None
 
+    maximum_extent = list(maximum_extent)
     maximum_extent[0] -= 10000
     maximum_extent[1] -= 10000
     maximum_extent[2] += 10000
diff --git a/mpop/satin/nc_osisaf_l2.py b/mpop/satin/nc_osisaf_l2.py
index ac1a811..14bc34f 100644
--- a/mpop/satin/nc_osisaf_l2.py
+++ b/mpop/satin/nc_osisaf_l2.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-# Copyright (c) 2015 Adam.Dybbroe
+# Copyright (c) 2015, 2016 Adam.Dybbroe
 
 # Author(s):
 
diff --git a/mpop/satin/viirs_sdr.py b/mpop/satin/viirs_sdr.py
index e10bf65..6ee11ff 100644
--- a/mpop/satin/viirs_sdr.py
+++ b/mpop/satin/viirs_sdr.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016.
+# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017.
 
 # Author(s):
 
@@ -258,6 +258,7 @@ class ViirsGeolocationData(object):
         self.longitudes = None
         self.shape = shape
         self.latitudes = None
+        self.elevation = None
         self.mask = None
 
     def read(self):
@@ -272,6 +273,8 @@ class ViirsGeolocationData(object):
                                    dtype=np.float32)
         self.latitudes = np.empty(self.shape,
                                   dtype=np.float32)
+        self.elevation = np.empty(self.shape,
+                                  dtype=np.float32)
         self.mask = np.zeros(self.shape,
                              dtype=np.bool)
 
@@ -286,6 +289,7 @@ class ViirsGeolocationData(object):
             get_lonlat_into(filename,
                             self.longitudes[y0_:y1_, :],
                             self.latitudes[y0_:y1_, :],
+                            self.elevation[y0_:y1_, :],
                             self.mask[y0_:y1_, :])
         self.longitudes = np.ma.array(self.longitudes,
                                       mask=self.mask,
@@ -293,6 +297,9 @@ class ViirsGeolocationData(object):
         self.latitudes = np.ma.array(self.latitudes,
                                      mask=self.mask,
                                      copy=False)
+        self.elevation = np.ma.array(self.elevation,
+                                     mask=self.mask,
+                                     copy=False)
         logger.debug("Geolocation read in for... " + str(self))
         return self
 
@@ -596,6 +603,66 @@ class ViirsSDRReader(Reader):
         return (data['sunz'], data['sun_azi'],
                 data['satz'], data['sat_azi'])
 
+    def get_elevation(self, **kwargs):
+        """Get elevation/topography for a given band type (M, I, or
+        DNB)
+        Optional arguments:
+            bandtype = 'M', 'I', or 'DNB'
+        Return
+            elevation
+
+        """
+
+        if 'bandtype' in kwargs:
+            bandtype = kwargs['bandtype']
+        else:
+            bandtype = 'M'
+
+        if bandtype.startswith('M'):
+            geofilenames = [geofile for geofile in self.geofiles
+                            if os.path.basename(geofile).startswith('GMTCO')]
+            if len(geofilenames) == 0:
+                # Try the geoid instead:
+                geofilenames = [geofile for geofile in self.geofiles
+                                if os.path.basename(geofile).startswith('GMODO')]
+        elif bandtype.startswith('I'):
+            geofilenames = [geofile for geofile in self.geofiles
+                            if os.path.basename(geofile).startswith('GITCO')]
+            if len(geofilenames) == 0:
+                # Try the geoid instead:
+                geofilenames = [geofile for geofile in self.geofiles
+                                if os.path.basename(geofile).startswith('GIMGO')]
+        elif bandtype.startswith('DNB'):
+            geofilenames = [geofile for geofile in self.geofiles
+                            if os.path.basename(geofile).startswith('GDNBO')]
+
+        else:
+            logger.error("Band type %s not supported", bandtype)
+            return None
+
+        geofilenames = sorted(geofilenames)
+
+        hdata = np.empty(self.shape,
+                         dtype=np.float32)
+        hmask = np.zeros(self.shape,
+                         dtype=np.bool)
+
+        granule_length = self.shape[0] / len(geofilenames)
+
+        for index, filename in enumerate(geofilenames):
+
+            swath_index = index * granule_length
+            y0_ = swath_index
+            y1_ = swath_index + granule_length
+
+            get_elevation_into(filename,
+                               hdata[y0_:y1_, :],
+                               hmask[y0_:y1_, :])
+
+        hdata = np.ma.array(hdata, mask=hmask, copy=False)
+
+        return hdata
+
     def load(self, satscene, calibrate=1, time_interval=None,
              area=None, filename=None, **kwargs):
         """Read viirs SDR reflectances and Tbs from file and load it into
@@ -830,6 +897,10 @@ class ViirsSDRReader(Reader):
                 lats=np.ma.masked_where(band.data.mask,
                                         band.geolocation.latitudes,
                                         copy=False))
+            height = np.ma.masked_where(band.data.mask,
+                                        band.geolocation.elevation,
+                                        copy=False)
+
             area_name = ("swath_" + satscene.fullname + "_" +
                          str(satscene.time_slot) + "_"
                          + str(satscene[chn].data.shape) + "_" +
@@ -878,7 +949,7 @@ class ViirsSDRReader(Reader):
                                          if chn.is_loaded()])
 
 
-def get_lonlat_into(filename, out_lons, out_lats, out_mask):
+def get_lonlat_into(filename, out_lons, out_lats, out_height, out_mask):
     """Read lon,lat from hdf5 file"""
     logger.debug("Geo File = " + filename)
 
@@ -891,6 +962,22 @@ def get_lonlat_into(filename, out_lons, out_lats, out_mask):
             out_mask[:] = out_lats < -999
         if key.endswith("Longitude"):
             h5f[key].read_direct(out_lons)
+        if key.endswith("Height"):
+            h5f[key].read_direct(out_height)
+    h5f.close()
+
+
+def get_elevation_into(filename, out_height, out_mask):
+    """Read elevation/height from hdf5 file"""
+    logger.debug("Geo File = " + filename)
+
+    md = HDF5MetaData(filename).read()
+
+    h5f = h5py.File(filename, 'r')
+    for key in md.get_data_keys():
+        if key.endswith("Height"):
+            h5f[key].read_direct(out_height)
+            out_mask[:] = out_height < -999
     h5f.close()
 
 
diff --git a/mpop/tests/test_projector.py b/mpop/tests/test_projector.py
index bd27611..dc8ed80 100644
--- a/mpop/tests/test_projector.py
+++ b/mpop/tests/test_projector.py
@@ -4,11 +4,11 @@
 
 # SMHI,
 # Folkborgsvägen 1,
-# Norrköping, 
+# Norrköping,
 # Sweden
 
 # Author(s):
- 
+
 #   Martin Raspaud <martin.raspaud at smhi.se>
 #   Adam Dybbroe <adam.dybbroe at smhi.se>
 
@@ -37,6 +37,7 @@ import numpy as np
 from mock import MagicMock, patch
 import sys
 sys.modules['pyresample'] = MagicMock()
+sys.modules['pyresample.bilinear'] = MagicMock()
 
 from pyresample import geometry, utils
 
@@ -44,16 +45,18 @@ from mpop.projector import Projector
 import mpop.projector
 
 
-
 class TestProjector(unittest.TestCase):
+
     """Class for testing the Projector class.
     """
 
     proj = None
+
+    @patch('mpop.projector.get_bil_info')
     @patch.object(utils, 'generate_quick_linesample_arrays')
     @patch.object(mpop.projector.kd_tree, 'get_neighbour_info')
     @patch.object(mpop.projector, '_get_area_hash')
-    def test_init(self, gah, gni, gqla):
+    def test_init(self, gah, gni, gqla, bil_info):
         """Creation of coverage.
         """
 
@@ -62,7 +65,6 @@ class TestProjector(unittest.TestCase):
         self.assertRaises(TypeError, Projector)
         self.assertRaises(TypeError, Projector, random_string(20))
 
-
         # in case of string arguments
 
         in_area_id = random_string(20)
@@ -78,12 +80,9 @@ class TestProjector(unittest.TestCase):
         utils.parse_area_file.assert_any_call(area_file, in_area_id)
         utils.parse_area_file.assert_any_call(area_file, out_area_id)
 
-
-
         self.assertEquals(self.proj.in_area, area_type)
         self.assertEquals(self.proj.out_area, area_type)
 
-
         # in case of undefined areas
 
         mock = MagicMock(side_effect=Exception("raise"))
@@ -109,18 +108,21 @@ class TestProjector(unittest.TestCase):
                 self.assertEquals(self.proj.in_area, in_area)
 
         in_area = geometry.SwathDefinition()
-        utils.parse_area_file.return_value.__getitem__.side_effect = [AttributeError, out_area_id]
+        utils.parse_area_file.return_value.__getitem__.side_effect = [
+            AttributeError, out_area_id]
         self.proj = Projector(in_area, out_area_id)
         self.assertEquals(self.proj.in_area, in_area)
 
         out_area = geometry.AreaDefinition()
-        utils.parse_area_file.return_value.__getitem__.side_effect = [in_area_id, AttributeError]
+        utils.parse_area_file.return_value.__getitem__.side_effect = [
+            in_area_id, AttributeError]
         self.proj = Projector(in_area_id, out_area)
         self.assertEquals(self.proj.out_area, out_area)
 
         # in case of lon/lat is input
 
-        utils.parse_area_file.return_value.__getitem__.side_effect = [AttributeError, out_area_id]
+        utils.parse_area_file.return_value.__getitem__.side_effect = [
+            AttributeError, out_area_id]
         lonlats = ("great_lons", "even_greater_lats")
 
         self.proj = Projector("raise", out_area_id, lonlats)
@@ -146,13 +148,25 @@ class TestProjector(unittest.TestCase):
         self.assertTrue(cache['col_idx'] is not None)
 
         # nearest mode cache
-
         self.proj = Projector(in_area_id, out_area_id, mode="nearest")
         cache = getattr(self.proj, "_cache")
         self.assertTrue(cache['valid_index'] is not None)
         self.assertTrue(cache['valid_output_index'] is not None)
         self.assertTrue(cache['index_array'] is not None)
 
+        # bilinear mode cache
+        bil_info.return_value = (1, 2, 3, 4)
+
+        def spam(val):
+            return 'adef'
+
+        with patch.object(mpop.projector, 'get_area_def', spam):
+            self.proj = Projector(in_area_id, out_area_id, mode="bilinear")
+        cache = getattr(self.proj, "_cache")
+        self.assertTrue(cache['bilinear_t'] is not None)
+        self.assertTrue(cache['bilinear_s'] is not None)
+        self.assertTrue(cache['input_idxs'] is not None)
+        self.assertTrue(cache['idx_arr'] is not None)
 
     @patch.object(np.ma, "array")
     @patch.object(mpop.projector.kd_tree, 'get_sample_from_neighbour_info')
@@ -164,35 +178,36 @@ class TestProjector(unittest.TestCase):
         out_area_id = random_string(20)
         data = np.random.standard_normal((3, 1))
 
-        utils.parse_area_file.return_value.__getitem__.side_effect = ["a", "b", "c", "d"]
+        utils.parse_area_file.return_value.__getitem__.side_effect = [
+            "a", "b", "c", "d"]
         # test quick
         self.proj = Projector(in_area_id, out_area_id, mode="quick")
         self.proj.project_array(data)
-        mpop.projector.image.ImageContainer.assert_called_with(\
+        mpop.projector.image.ImageContainer.assert_called_with(
             data, "a", fill_value=None)
         mpop.projector.image.ImageContainer.return_value.\
-            get_array_from_linesample.assert_called_with(\
-            self.proj._cache["row_idx"], self.proj._cache["col_idx"])
-        marray.assert_called_once_with(\
-            mpop.projector.image.ImageContainer.return_value.\
+            get_array_from_linesample.assert_called_with(
+                self.proj._cache["row_idx"], self.proj._cache["col_idx"])
+        marray.assert_called_once_with(
+            mpop.projector.image.ImageContainer.return_value.
             get_array_from_linesample.return_value,
             dtype=np.dtype('float64'))
 
         # test nearest
         in_area = MagicMock()
         out_area = MagicMock()
-        utils.parse_area_file.return_value.__getitem__.side_effect = \
-                        [in_area, out_area]
+        utils.parse_area_file.return_value.__getitem__.side_effect = [
+            in_area, out_area]
         self.proj = Projector(in_area_id, out_area_id, mode="nearest")
         self.proj.project_array(data)
         mpop.projector.kd_tree.get_sample_from_neighbour_info.\
-             assert_called_with('nn',
-                                out_area.shape,
-                                data,
-                                npload.return_value.__getitem__.return_value,
-                                npload.return_value.__getitem__.return_value,
-                                npload.return_value.__getitem__.return_value,
-                                fill_value=None)
+            assert_called_with('nn',
+                               out_area.shape,
+                               data,
+                               npload.return_value.__getitem__.return_value,
+                               npload.return_value.__getitem__.return_value,
+                               npload.return_value.__getitem__.return_value,
+                               fill_value=None)
 
 
 def random_string(length,
@@ -214,4 +229,3 @@ def suite():
     mysuite.addTest(loader.loadTestsFromTestCase(TestProjector))
 
     return mysuite
-
diff --git a/mpop/version.py b/mpop/version.py
index 801da57..89fa315 100644
--- a/mpop/version.py
+++ b/mpop/version.py
@@ -23,4 +23,4 @@
 """Version file.
 """
 
-__version__ = "v1.3.1"
+__version__ = "v1.4.0"

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/python-mpop.git



More information about the Pkg-grass-devel mailing list