Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the ninjotiff writer to provide correct scale and offset #889

Merged
merged 14 commits into from
Sep 30, 2019
Merged
26 changes: 26 additions & 0 deletions satpy/composites/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,32 @@ def __call__(self, projectables, nonprojectables=None, **info):
return proj


class SingleBandCompositor(CompositeBase):
"""Basic single-band composite builder.

This preserves all the attributes of the dataset it is derived from.
"""

def __call__(self, projectables, nonprojectables=None, **attrs):
"""Build the composite."""
if len(projectables) != 1:
raise ValueError("Can't have more than one band in a single-band composite")

data = projectables[0]
new_attrs = data.attrs.copy()

new_attrs.update({key: val
for (key, val) in attrs.items()
if val is not None})
resolution = new_attrs.get('resolution', None)
new_attrs.update(self.attrs)
if resolution is not None:
new_attrs['resolution'] = resolution

return xr.DataArray(data=data.data, attrs=new_attrs,
dims=data.dims, coords=data.coords)


class GenericCompositor(CompositeBase):
"""Basic colored composite builder."""

Expand Down
38 changes: 35 additions & 3 deletions satpy/tests/compositor_tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,37 @@ def test_call(self):
np.testing.assert_allclose(res, exp)


class TestSingleBandCompositor(unittest.TestCase):
"""Test the single-band compositor."""

def setUp(self):
"""Create test data."""
from satpy.composites import SingleBandCompositor
self.comp = SingleBandCompositor(name='test')

all_valid = np.ones((2, 2))
self.all_valid = xr.DataArray(all_valid, dims=['y', 'x'])

def test_call(self):
"""Test calling the compositor."""
# Dataset with extra attributes
all_valid = self.all_valid
all_valid.attrs['sensor'] = 'foo'
attrs = {'foo': 'bar', 'resolution': 333, 'units': 'K',
'calibration': 'BT', 'wavelength': 10.8}
self.comp.attrs['resolution'] = None
res = self.comp([self.all_valid], **attrs)
# Verify attributes
self.assertEqual(res.attrs.get('sensor'), 'foo')
self.assertTrue('foo' in res.attrs)
self.assertEqual(res.attrs.get('foo'), 'bar')
self.assertTrue('units' in res.attrs)
self.assertTrue('calibration' in res.attrs)
self.assertFalse('modifiers' in res.attrs)
self.assertEqual(res.attrs['wavelength'], 10.8)
self.assertEquals(res.attrs['resolution'], 333)


class TestGenericCompositor(unittest.TestCase):
"""Test generic compositor."""

Expand Down Expand Up @@ -884,17 +915,17 @@ def test_init(self, get_area_def):
get_area_def.assert_called_once_with("euro4")

@mock.patch('satpy.Scene')
def test_call(self, Scene):
def test_call(self, Scene): # noqa
"""Test the static compositing."""
from satpy.composites import StaticImageCompositor

class mock_scene(dict):
class MockScene(dict):
def load(self, arg):
pass

img = mock.MagicMock()
img.attrs = {}
scn = mock_scene()
scn = MockScene()
scn['image'] = img
Scene.return_value = scn
comp = StaticImageCompositor("name", filename="foo.tif")
Expand Down Expand Up @@ -1043,6 +1074,7 @@ def suite():
mysuite.addTest(loader.loadTestsFromTestCase(TestColormapCompositor))
mysuite.addTest(loader.loadTestsFromTestCase(TestPaletteCompositor))
mysuite.addTest(loader.loadTestsFromTestCase(TestCloudTopHeightCompositor))
mysuite.addTest(loader.loadTestsFromTestCase(TestSingleBandCompositor))
mysuite.addTest(loader.loadTestsFromTestCase(TestGenericCompositor))
mysuite.addTest(loader.loadTestsFromTestCase(TestNIRReflectance))
mysuite.addTest(loader.loadTestsFromTestCase(TestPrecipCloudsCompositor))
Expand Down
19 changes: 10 additions & 9 deletions satpy/tests/writer_tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@
#
# You should have received a copy of the GNU General Public License along with
# satpy. If not, see <http://www.gnu.org/licenses/>.
"""The writer tests package.
"""
"""The writer tests package."""

import sys

from satpy.tests.writer_tests import (test_cf, test_geotiff,
from satpy.tests.writer_tests import (test_cf,
test_geotiff,
test_simple_image,
test_scmi, test_mitiff,
test_utils)
# FIXME: pyninjotiff is not xarray/dask friendly
from satpy.tests.writer_tests import test_ninjotiff # noqa
test_scmi,
test_mitiff,
test_utils,
test_ninjotiff,
)

if sys.version_info < (2, 7):
import unittest2 as unittest
Expand All @@ -34,11 +35,11 @@


def suite():
"""Test suite for all writer tests"""
"""Test suite for all writer tests."""
mysuite = unittest.TestSuite()
mysuite.addTests(test_cf.suite())
mysuite.addTests(test_geotiff.suite())
# mysuite.addTests(test_ninjotiff.suite())
mysuite.addTests(test_ninjotiff.suite())
mysuite.addTests(test_simple_image.suite())
mysuite.addTests(test_scmi.suite())
mysuite.addTests(test_mitiff.suite())
Expand Down
60 changes: 52 additions & 8 deletions satpy/tests/writer_tests/test_ninjotiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,68 @@
#
# You should have received a copy of the GNU General Public License along with
# satpy. If not, see <http://www.gnu.org/licenses/>.
"""Tests for the NinJoTIFF writer.
"""
import sys
"""Tests for the NinJoTIFF writer."""

if sys.version_info < (2, 7):
import unittest2 as unittest
import sys
import unittest
import xarray as xr
from dask.delayed import Delayed
import six
if six.PY3:
from unittest import mock
else:
import unittest
import mock


class FakeImage:
"""Fake image."""

def __init__(self, data, mode):
"""Init fake image."""
self.data = data
self.mode = mode


modules = {'pyninjotiff': mock.Mock(),
'pyninjotiff.ninjotiff': mock.Mock()}


@mock.patch.dict(sys.modules, modules)
class TestNinjoTIFFWriter(unittest.TestCase):
"""The ninjo tiff writer tests."""

def test_init(self):
"""Test the init."""
from satpy.writers.ninjotiff import NinjoTIFFWriter
ninjo_tags = {40000: 'NINJO'}
ntw = NinjoTIFFWriter(tags=ninjo_tags)
self.assertDictEqual(ntw.tags, ninjo_tags)

@mock.patch('satpy.writers.ninjotiff.ImageWriter.save_dataset')
@mock.patch('satpy.writers.ninjotiff.convert_units')
def test_dataset(self, uconv, iwsd):
"""Test saving a dataset."""
from satpy.writers.ninjotiff import NinjoTIFFWriter
ntw = NinjoTIFFWriter()
dataset = xr.DataArray([1, 2, 3], attrs={'units': 'K'})
ntw.save_dataset(dataset, physic_unit='CELSIUS')
uconv.assert_called_once_with(dataset, 'K', 'CELSIUS')
self.assertEqual(iwsd.call_count, 1)

@mock.patch('satpy.writers.ninjotiff.NinjoTIFFWriter.save_dataset')
@mock.patch('satpy.writers.ninjotiff.ImageWriter.save_image')
def test_image(self, iwsi, save_dataset):
"""Test saving an image."""
from satpy.writers.ninjotiff import NinjoTIFFWriter
NinjoTIFFWriter()
ntw = NinjoTIFFWriter()
dataset = xr.DataArray([1, 2, 3], attrs={'units': 'K'})
img = FakeImage(dataset, 'L')
ret = ntw.save_image(img, filename='bla.tif', compute=False)
self.assertIsInstance(ret, Delayed)


def suite():
"""The test suite for this writer's tests."""
"""Test suite for this writer's tests."""
loader = unittest.TestLoader()
mysuite = unittest.TestSuite()
mysuite.addTest(loader.loadTestsFromTestCase(TestNinjoTIFFWriter))
Expand Down
Loading