Пример #1
0
    def setUp(self):
        """Create test data and mock pycoast/pydecorate."""
        from trollimage.xrimage import XRImage
        from pyresample.geometry import AreaDefinition
        import xarray as xr
        import dask.array as da

        proj_dict = {'proj': 'lcc', 'datum': 'WGS84', 'ellps': 'WGS84',
                     'lon_0': -95., 'lat_0': 25, 'lat_1': 25,
                     'units': 'm', 'no_defs': True}
        self.area_def = AreaDefinition(
            'test', 'test', 'test', proj_dict,
            200, 400, (-1000., -1500., 1000., 1500.),
        )
        self.orig_rgb_img = XRImage(
            xr.DataArray(da.arange(75., chunks=10).reshape(3, 5, 5) / 75.,
                         dims=('bands', 'y', 'x'),
                         coords={'bands': ['R', 'G', 'B']},
                         attrs={'name': 'test_ds', 'area': self.area_def})
        )
        self.orig_l_img = XRImage(
            xr.DataArray(da.arange(25., chunks=10).reshape(5, 5) / 75.,
                         dims=('y', 'x'),
                         attrs={'name': 'test_ds', 'area': self.area_def})
        )

        self.decorate = {
            'decorate': [
                {'logo': {'logo_path': '', 'height': 143, 'bg': 'white', 'bg_opacity': 255}},
                {'text': {
                    'txt': 'TEST',
                    'align': {'top_bottom': 'bottom', 'left_right': 'right'},
                    'font': '',
                    'font_size': 22,
                    'height': 30,
                    'bg': 'black',
                    'bg_opacity': 255,
                    'line': 'white'}},
                {'scale': {
                    'colormap': greys,
                    'extend': False,
                    'width': 1670, 'height': 110,
                    'tick_marks': 5, 'minor_tick_marks': 1,
                    'cursor': [0, 0], 'bg':'white',
                    'title':'TEST TITLE OF SCALE',
                    'fontsize': 110, 'align': 'cc'
                }}
            ]
        }

        import_mock = mock.MagicMock()
        modules = {'pycoast': import_mock.pycoast,
                   'pydecorate': import_mock.pydecorate}
        self.module_patcher = mock.patch.dict('sys.modules', modules)
        self.module_patcher.start()
Пример #2
0
    def setUp(self):
        """Create test data and mock pycoast/pydecorate."""
        from trollimage.xrimage import XRImage
        from pyresample.geometry import AreaDefinition
        import xarray as xr
        import dask.array as da

        proj_dict = {'proj': 'lcc', 'datum': 'WGS84', 'ellps': 'WGS84',
                     'lon_0': -95., 'lat_0': 25, 'lat_1': 25,
                     'units': 'm', 'no_defs': True}
        self.area_def = AreaDefinition(
            'test', 'test', 'test', proj_dict,
            200, 400, (-1000., -1500., 1000., 1500.),
        )
        self.orig_rgb_img = XRImage(
            xr.DataArray(da.arange(75., chunks=10).reshape(3, 5, 5) / 75.,
                         dims=('bands', 'y', 'x'),
                         coords={'bands': ['R', 'G', 'B']},
                         attrs={'name': 'test_ds', 'area': self.area_def})
        )
        self.orig_l_img = XRImage(
            xr.DataArray(da.arange(25., chunks=10).reshape(5, 5) / 75.,
                         dims=('y', 'x'),
                         attrs={'name': 'test_ds', 'area': self.area_def})
        )

        self.decorate = {
            'decorate': [
                {'logo': {'logo_path': '', 'height': 143, 'bg': 'white', 'bg_opacity': 255}},
                {'text': {
                    'txt': 'TEST',
                    'align': {'top_bottom': 'bottom', 'left_right': 'right'},
                    'font': '',
                    'font_size': 22,
                    'height': 30,
                    'bg': 'black',
                    'bg_opacity': 255,
                    'line': 'white'}}
            ]
        }

        self.contour_writer = mock.patch('pycoast.ContourWriterAGG')
        self.dec_writer = mock.patch('pydecorate.DecoratorAGG')
        self.cw = self.contour_writer.start()
        self.dw = self.dec_writer.start()
Пример #3
0
def to_image(dataset, copy=False, **kwargs):
    # Only add keywords if they are present
    for key in ["mode", "fill_value", "palette"]:
        if key in dataset.attrs:
            kwargs.setdefault(key, dataset.attrs[key])
    dataset = dataset.squeeze()

    if dataset.ndim < 2:
        raise ValueError("Need at least a 2D array to make an image.")
    else:
        return XRImage(dataset)
Пример #4
0
 def test_colormap_write(self):
     """Test writing an image with a colormap."""
     from satpy.writers.geotiff import GeoTIFFWriter
     from trollimage.xrimage import XRImage
     from trollimage.colormap import spectral
     datasets = self._get_test_datasets()
     w = GeoTIFFWriter(base_dir=self.base_dir)
     # we'd have to customize enhancements to test this through
     # save_datasets. We'll use `save_image` as a workaround.
     img = XRImage(datasets[0])
     img.palettize(spectral)
     w.save_image(img, keep_palette=True)
Пример #5
0
def test_write_rgba():
    """Test saving an RGBA image."""
    area = STEREOGRAPHIC_AREA

    fill_value = np.nan
    arr = create_hsv_color_disk(fill_value)

    attrs = dict([('platform_name', 'NOAA-18'),
                  ('resolution', 1050),
                  ('polarization', None),
                  ('start_time', TIME - datetime.timedelta(minutes=55)),
                  ('end_time', TIME - datetime.timedelta(minutes=50)),
                  ('level', None),
                  ('sensor', 'avhrr-3'),
                  ('ancillary_variables', []),
                  ('area', area),
                  ('wavelength', None),
                  ('optional_datasets', []),
                  ('standard_name', 'overview'),
                  ('name', 'overview'),
                  ('prerequisites', [0.6, 0.8, 10.8]),
                  ('optional_prerequisites', []),
                  ('calibration', None),
                  ('modifiers', None),
                  ('mode', 'RGBA'),
                  ('enhancement_history', [{'scale': np.array([1,  1, -1]), 'offset': np.array([0, 0, 1])},
                                           {'scale': np.array([0.0266347, 0.03559078, 0.01329783]),
                                            'offset': np.array([-0.02524969, -0.01996642,  3.8918446])},
                                           {'gamma': 1.6}])])

    kwargs = {'compute': True, 'fill_value': None, 'sat_id': 6300014,
              'chan_id': 6500015, 'data_cat': 'PPRN', 'data_source': 'SMHI', 'nbits': 8}
    alpha = np.where(np.isnan(arr[0, :, :]), 0, 1)
    arr = np.nan_to_num(arr)
    arr = np.vstack((arr, alpha[np.newaxis, :, :]))
    data = da.from_array(arr.clip(0, 1), chunks=1024)

    data = xr.DataArray(data, coords={'bands': ['R', 'G', 'B', 'A']}, dims=[
                        'bands', 'y', 'x'], attrs=attrs)

    img = XRImage(data)
    with tempfile.NamedTemporaryFile(delete=DELETE_FILES) as tmpfile:
        filename = tmpfile.name
        if not DELETE_FILES:
            print(filename)
        save(img, filename, data_is_scaled_01=True, **kwargs)
        tif = TiffFile(filename)
        res = tif[0].asarray()
        for idx in range(4):
            np.testing.assert_allclose(res[:, :, idx], np.round(
                np.nan_to_num(arr[idx, :, :]) * 255).astype(np.uint8))
        np.testing.assert_allclose(res[:, :, 3] == 0, alpha == 0)
Пример #6
0
    def _test_enhancement(self, func, data, expected, **kwargs):
        from trollimage.xrimage import XRImage

        pre_attrs = data.attrs
        img = XRImage(data)
        func(img, **kwargs)

        self.assertIsInstance(img.data.data, da.Array)
        self.assertListEqual(sorted(pre_attrs.keys()),
                             sorted(img.data.attrs.keys()),
                             "DataArray attributes were not preserved")

        np.testing.assert_allclose(img.data.values, expected, atol=1.e-6, rtol=0)
Пример #7
0
    def test_cimss_true_color_contrast(self):
        """Test the cimss_true_color_contrast enhancement."""
        from satpy.enhancements.abi import cimss_true_color_contrast
        from trollimage.xrimage import XRImage

        expected = np.array([[
            [0., 0., 0.05261956, 0.13396146],
            [0.21530335, 0.29664525, 0.37798715, 0.45932905],
            [0.54067095, 0.62201285, 0.70335475, 0.78469665],
            [0.86603854, 0.94738044, 1., 1.],
            ]])
        img = XRImage(self.da)
        cimss_true_color_contrast(img)
        np.testing.assert_almost_equal(img.data.compute(), expected)
Пример #8
0
def run_and_check_enhancement(func, data, expected, **kwargs):
    """Perform basic checks that apply to multiple tests."""
    from trollimage.xrimage import XRImage

    pre_attrs = data.attrs
    img = XRImage(data)
    func(img, **kwargs)

    assert isinstance(img.data.data, da.Array)
    old_keys = set(pre_attrs.keys())
    # It is OK to have "enhancement_history" added
    new_keys = set(img.data.attrs.keys()) - {"enhancement_history"}
    assert old_keys == new_keys

    np.testing.assert_allclose(img.data.values, expected, atol=1.e-6, rtol=0)
Пример #9
0
def palettize(img, min_out, max_out, min_in=0, max_in=1.0, colormap=None, alpha=True, **kwargs):
    """Apply a colormap to data and return the indices in to that colormap."""
    import xarray as xr
    import dask.array as da
    from trollimage.xrimage import XRImage
    import trollimage.colormap as ticolormap
    from satpy import CHUNK_SIZE
    good_data_mask = kwargs['good_data_mask']

    if img.ndim > 2:
        raise ValueError("Not sure how to palettize more than 2 dimensions")

    if colormap is None:
        raise ValueError("'colormap' is required for 'palettize' rescaling")
    elif not isinstance(colormap, ticolormap.Colormap):
        raise ValueError("Unknown 'colormap' type: %s", str(type(colormap)))

    dims = ('y', 'x') if img.ndim == 2 else ('y',)
    attrs = kwargs.get('attrs', {})
    xrimg = XRImage(
        xr.DataArray(da.from_array(img, chunks=CHUNK_SIZE), dims=dims, attrs=attrs))
    if alpha:
        # use colormap as is
        tmp_cmap = colormap
        # produce LA image
        xrimg = xrimg.convert(xrimg.mode + 'A')
    else:
        # the colormap has a value at 0 (first position) that represents
        # invalid data. We should palettize based on the colormap without
        # the 0 and then increment
        tmp_cmap = ticolormap.Colormap(*zip(colormap.values[1:], colormap.colors[1:]))

    tmp_cmap.set_range(min_in, max_in)
    xrimg.palettize(tmp_cmap)
    img_data = xrimg.data.values

    if alpha:
        # multiply alpha by the output size
        img_data[1, :, :] *= max_out
    else:
        # get the single band (L)
        img_data = img_data[0]
        # increment the indexes by 1 because the colormap has a 0 fill value
        img_data += 1
        img_data[~good_data_mask] = 0
    # our data values are now integers that can't be scaled to the output type
    # because they need to match the colormap
    return img_data
Пример #10
0
    def _test_enhancement(self, func, data, expected, **kwargs):
        """Perform basic checks that apply to multiple tests."""
        from trollimage.xrimage import XRImage

        pre_attrs = data.attrs
        img = XRImage(data)
        func(img, **kwargs)

        assert isinstance(img.data.data, da.Array)
        assert sorted(pre_attrs.keys()) == sorted(
            img.data.attrs.keys()), "DataArray attributes were not preserved"

        np.testing.assert_allclose(img.data.values,
                                   expected,
                                   atol=1.e-6,
                                   rtol=0)
Пример #11
0
    def test_jma_true_color_reproduction(self):
        """Test the jma_true_color_reproduction enhancement."""
        from trollimage.xrimage import XRImage

        from satpy.enhancements.ahi import jma_true_color_reproduction

        expected = [[[-109.98, 10.998, 131.976, 252.954, 373.932],
                     [494.91, 615.888, 736.866, 857.844, 978.822]],
                    [[-97.6, 9.76, 117.12, 224.48, 331.84],
                     [439.2, 546.56, 653.92, 761.28, 868.64]],
                    [[-94.27, 9.427, 113.124, 216.821, 320.518],
                     [424.215, 527.912, 631.609, 735.306, 839.003]]]

        img = XRImage(self.rgb)
        jma_true_color_reproduction(img)
        np.testing.assert_almost_equal(img.data.compute(), expected)
Пример #12
0
def test_write_rgb_classified():
    """Test saving a transparent RGB."""
    area = STEREOGRAPHIC_AREA

    x_size, y_size = 1024, 1024
    arr = np.zeros((3, y_size, x_size))

    attrs = dict([('platform_name', 'NOAA-18'),
                  ('resolution', 1050),
                  ('polarization', None),
                  ('start_time', TIME - datetime.timedelta(minutes=65)),
                  ('end_time', TIME - datetime.timedelta(minutes=60)),
                  ('level', None),
                  ('sensor', 'avhrr-3'),
                  ('ancillary_variables', []),
                  ('area', area),
                  ('wavelength', None),
                  ('optional_datasets', []),
                  ('standard_name', 'overview'),
                  ('name', 'overview'),
                  ('prerequisites', [0.6, 0.8, 10.8]),
                  ('optional_prerequisites', []),
                  ('calibration', None),
                  ('modifiers', None),
                  ('mode', 'P')])

    kwargs = {'compute': True, 'fill_value': None, 'sat_id': 6300014,
              'chan_id': 1700015, 'data_cat': 'PPRN', 'data_source': 'SMHI', 'nbits': 8}

    data1 = da.tile(da.repeat(da.arange(4, chunks=1024), 256), 256).reshape((1, 256, 1024))
    datanan = da.ones((1, 256, 1024), chunks=1024) * 4
    data2 = da.tile(da.repeat(da.arange(4, chunks=1024), 256), 512).reshape((1, 512, 1024))
    data = da.concatenate((data1, datanan, data2), axis=1)
    data = xr.DataArray(data, coords={'bands': ['P']}, dims=['bands', 'y', 'x'], attrs=attrs)

    img = XRImage(data)
    with tempfile.NamedTemporaryFile(delete=DELETE_FILES) as tmpfile:
        filename = tmpfile.name
        if not DELETE_FILES:
            print(filename)
        save(img, filename, data_is_scaled_01=True, **kwargs)
        tif = TiffFile(filename)
        res = tif[0].asarray()
        for idx in range(3):
            np.testing.assert_allclose(res[:, :, idx], np.round(
                np.nan_to_num(arr[idx, :, :]) * 255).astype(np.uint8))
        np.testing.assert_allclose(res[:, :, 3] == 0, np.isnan(arr[0, :, :]))
Пример #13
0
def to_image(dataset):
    """Convert ``dataset`` into a :class:`~trollimage.xrimage.XRImage` instance.

    Convert the ``dataset`` into an instance of the
    :class:`~trollimage.xrimage.XRImage` class.  This function makes no other
    changes.  To get an enhanced image, possibly with overlays and decoration,
    see :func:`~get_enhanced_image`.

    Args:
        dataset (xarray.DataArray): Data to be converted to an image.

    Returns:
        Instance of :class:`~trollimage.xrimage.XRImage`.

    """
    dataset = dataset.squeeze()
    if dataset.ndim < 2:
        raise ValueError("Need at least a 2D array to make an image.")
    return XRImage(dataset)
Пример #14
0
def _pil_to_xrimage(img, adef, fill_value=None):
    """Convert PIL image to trollimage.xrimage.XRImage"""
    # Get image mode, width and height
    mode = img.mode
    width = img.width
    height = img.height

    # Convert to Numpy array
    img = np.array(img)

    # Get the minimum and maximum values of the input datatype
    min_val = np.iinfo(img.dtype).min
    max_val = np.iinfo(img.dtype).max

    img = img.reshape((height, width, len(mode)))

    # Reorder for XRImage
    img = np.rollaxis(img, 2, -3)
    # Remove alpha channel if fill_value is set
    if fill_value is not None:
        if 'A' in mode:
            mask = img[-1, :, :] == min_val
            # Remove alpha channel
            img = img[:-1, :, :]
            if np.any(mask):
                # Set fill_value for each channel
                for i in range(img.shape[0]):
                    chan = img[i, :, :]
                    chan[mask] = fill_value
    bands = BANDS[img.shape[0]]

    # Add image data to scene as xarray.DataArray
    img = xr.DataArray(img, dims=['bands', 'y', 'x'])
    img['bands'] = bands
    # Add area definition
    img.attrs['area'] = adef

    # Convert to XRImage
    img = XRImage(img)
    # Static stretch
    img.crude_stretch(min_val, max_val)

    return img
Пример #15
0
def add_scale(orig, dc, img, scale):
    """Add scale to an image using the pydecorate package.

    All the features of pydecorate's ``add_scale`` are available.
    See documentation of :doc:`pydecorate:index` for more info.

    """
    LOG.info("Add scale to image.")

    dc.add_scale(**scale)

    arr = da.from_array(np.array(img) / 255.0, chunks=CHUNK_SIZE)

    new_data = xr.DataArray(arr, dims=['y', 'x', 'bands'],
                            coords={'y': orig.data.coords['y'],
                                    'x': orig.data.coords['x'],
                                    'bands': list(img.mode)},
                            attrs=orig.data.attrs)
    return XRImage(new_data)
Пример #16
0
def test_write_rgb_with_a():
    """Test saving a transparent RGB."""
    from pyninjotiff.ninjotiff import save
    from pyninjotiff.tifffile import TiffFile

    area = FakeArea(
        {
            'ellps': 'WGS84',
            'lat_0': '90.0',
            'lat_ts': '60.0',
            'lon_0': '0.0',
            'proj': 'stere'
        }, (-1000000.0, -4500000.0, 2072000.0, -1428000.0), 1024, 1024)

    x_size, y_size = 1024, 1024
    arr = np.zeros((3, y_size, x_size))
    radius = min(x_size, y_size) / 2.0
    centre = x_size / 2, y_size / 2

    for x in range(x_size):
        for y in range(y_size):
            rx = x - centre[0]
            ry = y - centre[1]
            s = ((x - centre[0])**2.0 + (y - centre[1])**2.0)**0.5 / radius
            if s <= 1.0:
                h = ((np.arctan2(ry, rx) / np.pi) + 1.0) / 2.0
                rgb = colorsys.hsv_to_rgb(h, s, 1.0)
                arr[:, y, x] = np.array(rgb)
            else:
                arr[:, y, x] = np.nan

    attrs = dict([('platform_name', 'NOAA-18'), ('resolution', 1050),
                  ('polarization', None),
                  ('start_time', TIME - datetime.timedelta(minutes=55)),
                  ('end_time', TIME - datetime.timedelta(minutes=50)),
                  ('level', None), ('sensor', 'avhrr-3'),
                  ('ancillary_variables', []), ('area', area),
                  ('wavelength', None), ('optional_datasets', []),
                  ('standard_name', 'overview'), ('name', 'overview'),
                  ('prerequisites', [0.6, 0.8, 10.8]),
                  ('optional_prerequisites', []), ('calibration', None),
                  ('modifiers', None), ('mode', 'RGB'),
                  ('enhancement_history', [{
                      'scale': np.array([1, 1, -1]),
                      'offset': np.array([0, 0, 1])
                  }, {
                      'scale':
                      np.array([0.0266347, 0.03559078, 0.01329783]),
                      'offset':
                      np.array([-0.02524969, -0.01996642, 3.8918446])
                  }, {
                      'gamma': 1.6
                  }])])

    kwargs = {
        'compute': True,
        'fill_value': None,
        'sat_id': 6300014,
        'chan_id': 6500015,
        'data_cat': 'PPRN',
        'data_source': 'SMHI',
        'nbits': 8
    }
    data = da.from_array(arr.clip(0, 1), chunks=1024)

    data = xr.DataArray(data,
                        coords={'bands': ['R', 'G', 'B']},
                        dims=['bands', 'y', 'x'],
                        attrs=attrs)
    from trollimage.xrimage import XRImage
    img = XRImage(data)
    with tempfile.NamedTemporaryFile(delete=DELETE_FILES) as tmpfile:
        filename = tmpfile.name
        if not DELETE_FILES:
            print(filename)
        save(img, filename, data_is_scaled_01=True, **kwargs)
        tif = TiffFile(filename)
        res = tif[0].asarray()
        for idx in range(3):
            np.testing.assert_allclose(
                res[:, :, idx],
                np.round(np.nan_to_num(arr[idx, :, :]) * 255).astype(np.uint8))
        np.testing.assert_allclose(res[:, :, 3] == 0, np.isnan(arr[0, :, :]))
Пример #17
0
def add_overlay(orig, area, coast_dir, color=(0, 0, 0), width=0.5, resolution=None,
                level_coast=1, level_borders=1, fill_value=None):
    """Add coastline and political borders to image.

    Uses ``color`` for feature colors where ``color`` is a 3-element tuple
    of integers between 0 and 255 representing (R, G, B).

    .. warning::

        This function currently loses the data mask (alpha band).

    ``resolution`` is chosen automatically if None (default), otherwise it should be one of:

    +-----+-------------------------+---------+
    | 'f' | Full resolution         | 0.04 km |
    | 'h' | High resolution         | 0.2 km  |
    | 'i' | Intermediate resolution | 1.0 km  |
    | 'l' | Low resolution          | 5.0 km  |
    | 'c' | Crude resolution        | 25  km  |
    +-----+-------------------------+---------+

    """

    if area is None:
        raise ValueError("Area of image is None, can't add overlay.")

    from pycoast import ContourWriterAGG
    if isinstance(area, str):
        area = get_area_def(area)
    LOG.info("Add coastlines and political borders to image.")

    if resolution is None:

        x_resolution = ((area.area_extent[2] -
                         area.area_extent[0]) /
                        area.x_size)
        y_resolution = ((area.area_extent[3] -
                         area.area_extent[1]) /
                        area.y_size)
        res = min(x_resolution, y_resolution)

        if res > 25000:
            resolution = "c"
        elif res > 5000:
            resolution = "l"
        elif res > 1000:
            resolution = "i"
        elif res > 200:
            resolution = "h"
        else:
            resolution = "f"

        LOG.debug("Automagically choose resolution %s", resolution)

    if hasattr(orig, 'convert'):
        # image must be in RGB space to work with pycoast/pydecorate
        orig = orig.convert('RGBA' if orig.mode.endswith('A') else 'RGB')
    elif not orig.mode.startswith('RGB'):
        raise RuntimeError("'trollimage' 1.6+ required to support adding "
                           "overlays/decorations to non-RGB data.")
    img = orig.pil_image(fill_value=fill_value)
    cw_ = ContourWriterAGG(coast_dir)
    cw_.add_coastlines(img, area, outline=color,
                       resolution=resolution, width=width, level=level_coast)
    cw_.add_borders(img, area, outline=color,
                    resolution=resolution, width=width, level=level_borders)

    arr = da.from_array(np.array(img) / 255.0, chunks=CHUNK_SIZE)

    new_data = xr.DataArray(arr, dims=['y', 'x', 'bands'],
                            coords={'y': orig.data.coords['y'],
                                    'x': orig.data.coords['x'],
                                    'bands': list(img.mode)},
                            attrs=orig.data.attrs)
    return XRImage(new_data)
Пример #18
0
def _fake_get_enhanced_image(img, enhance=None, overlay=None, decorate=None):
    from trollimage.xrimage import XRImage
    return XRImage(img)
Пример #19
0
def add_overlay(orig,
                area,
                coast_dir,
                color=(0, 0, 0),
                width=0.5,
                resolution=None,
                level_coast=1,
                level_borders=1,
                fill_value=None,
                grid=None):
    """Add coastline, political borders and grid(graticules) to image.

    Uses ``color`` for feature colors where ``color`` is a 3-element tuple
    of integers between 0 and 255 representing (R, G, B).

    .. warning::

        This function currently loses the data mask (alpha band).

    ``resolution`` is chosen automatically if None (default),
    otherwise it should be one of:

    +-----+-------------------------+---------+
    | 'f' | Full resolution         | 0.04 km |
    +-----+-------------------------+---------+
    | 'h' | High resolution         | 0.2 km  |
    +-----+-------------------------+---------+
    | 'i' | Intermediate resolution | 1.0 km  |
    +-----+-------------------------+---------+
    | 'l' | Low resolution          | 5.0 km  |
    +-----+-------------------------+---------+
    | 'c' | Crude resolution        | 25  km  |
    +-----+-------------------------+---------+

    ``grid`` is a dictionary with key values as documented in detail in pycoast

    eg. overlay={'grid': {'major_lonlat': (10, 10),
                          'write_text': False,
                          'outline': (224, 224, 224),
                          'width': 0.5}}

    Here major_lonlat is plotted every 10 deg for both longitude and latitude,
    no labels for the grid lines are plotted, the color used for the grid lines
    is light gray, and the width of the gratucules is 0.5 pixels.

    For grid if aggdraw is used, font option is mandatory, if not
    ``write_text`` is set to False::

        font = aggdraw.Font('black', '/usr/share/fonts/truetype/msttcorefonts/Arial.ttf',
                            opacity=127, size=16)

    """

    if area is None:
        raise ValueError("Area of image is None, can't add overlay.")

    from pycoast import ContourWriterAGG
    if isinstance(area, str):
        area = get_area_def(area)
    LOG.info("Add coastlines and political borders to image.")

    if resolution is None:

        x_resolution = ((area.area_extent[2] - area.area_extent[0]) /
                        area.x_size)
        y_resolution = ((area.area_extent[3] - area.area_extent[1]) /
                        area.y_size)
        res = min(x_resolution, y_resolution)

        if res > 25000:
            resolution = "c"
        elif res > 5000:
            resolution = "l"
        elif res > 1000:
            resolution = "i"
        elif res > 200:
            resolution = "h"
        else:
            resolution = "f"

        LOG.debug("Automagically choose resolution %s", resolution)

    if hasattr(orig, 'convert'):
        # image must be in RGB space to work with pycoast/pydecorate
        orig = orig.convert('RGBA' if orig.mode.endswith('A') else 'RGB')
    elif not orig.mode.startswith('RGB'):
        raise RuntimeError("'trollimage' 1.6+ required to support adding "
                           "overlays/decorations to non-RGB data.")
    img = orig.pil_image(fill_value=fill_value)
    cw_ = ContourWriterAGG(coast_dir)
    cw_.add_coastlines(img,
                       area,
                       outline=color,
                       resolution=resolution,
                       width=width,
                       level=level_coast)
    cw_.add_borders(img,
                    area,
                    outline=color,
                    resolution=resolution,
                    width=width,
                    level=level_borders)
    # Only add grid if major_lonlat is given.
    if grid and 'major_lonlat' in grid and grid['major_lonlat']:
        major_lonlat = grid.pop('major_lonlat')
        minor_lonlat = grid.pop('minor_lonlat', major_lonlat)

        cw_.add_grid(img, area, major_lonlat, minor_lonlat, **grid)

    arr = da.from_array(np.array(img) / 255.0, chunks=CHUNK_SIZE)

    new_data = xr.DataArray(arr,
                            dims=['y', 'x', 'bands'],
                            coords={
                                'y': orig.data.coords['y'],
                                'x': orig.data.coords['x'],
                                'bands': list(img.mode)
                            },
                            attrs=orig.data.attrs)
    return XRImage(new_data)
Пример #20
0
def test_write_rgb_tb():
    """Test saving a non-trasparent RGB with thumbnails."""
    from pyninjotiff.ninjotiff import save
    from pyninjotiff.tifffile import TiffFile

    area = FakeArea(
        {
            'ellps': 'WGS84',
            'lat_0': 90.0,
            'lat_ts': 60.0,
            'lon_0': 0.0,
            'proj': 'stere'
        }, (-1000000.0, -4500000.0, 2072000.0, -1428000.0), 1024, 1024)

    x_size, y_size = 1024, 1024
    arr = np.zeros((3, y_size, x_size))
    radius = min(x_size, y_size) / 2.0
    centre = x_size / 2, y_size / 2

    for x in range(x_size):
        for y in range(y_size):
            rx = x - centre[0]
            ry = y - centre[1]
            s = ((x - centre[0])**2.0 + (y - centre[1])**2.0)**0.5 / radius
            if s <= 1.0:
                h = ((np.arctan2(ry, rx) / np.pi) + 1.0) / 2.0
                rgb = colorsys.hsv_to_rgb(h, s, 1.0)
                arr[:, y, x] = np.array(rgb)

    attrs = dict([('platform_name', 'NOAA-18'), ('resolution', 1050),
                  ('polarization', None), ('level', None),
                  ('sensor', 'avhrr-3'), ('ancillary_variables', []),
                  ('area', area),
                  ('start_time', TIME - datetime.timedelta(minutes=45)),
                  ('end_time', TIME - datetime.timedelta(minutes=40)),
                  ('wavelength', None), ('optional_datasets', []),
                  ('standard_name', 'overview'), ('name', 'overview'),
                  ('prerequisites', [0.6, 0.8, 10.8]),
                  ('optional_prerequisites', []), ('calibration', None),
                  ('modifiers', None), ('mode', 'RGB'),
                  ('enhancement_history', [{
                      'scale': np.array([1, 1, -1]),
                      'offset': np.array([0, 0, 1])
                  }, {
                      'scale':
                      np.array([0.0266347, 0.03559078, 0.01329783]),
                      'offset':
                      np.array([-0.02524969, -0.01996642, 3.8918446])
                  }, {
                      'gamma': 1.6
                  }])])

    kwargs = {
        'compute': True,
        'fill_value': None,
        'sat_id': 6300014,
        'chan_id': 6500015,
        'data_cat': 'PPRN',
        'data_source': 'SMHI',
        'nbits': 8,
        'tile_length': 256,
        'tile_width': 256
    }
    data = da.from_array(arr.clip(0, 1), chunks=1024)
    data = xr.DataArray(data,
                        coords={'bands': ['R', 'G', 'B']},
                        dims=['bands', 'y', 'x'],
                        attrs=attrs)

    from trollimage.xrimage import XRImage
    img = XRImage(data)

    with tempfile.NamedTemporaryFile(delete=DELETE_FILES) as tmpfile:
        filename = tmpfile.name
        if not DELETE_FILES:
            print(filename)
        save(img, filename, data_is_scaled_01=False, **kwargs)
        tif = TiffFile(filename)
        res = tif[0].asarray()
        assert (tif.pages[0].tags['tile_length'].value == 256)
        assert (tif.pages[1].tags['tile_length'].value == 128)
        assert (tif.pages[0].tags['tile_width'].value == 256)
        assert (tif.pages[1].tags['tile_width'].value == 128)
        assert (len(tif.pages) == 2)
        assert (tif.pages[0].shape == (1024, 1024, 4))
        assert (tif.pages[1].shape == (512, 512, 4))
        for idx in range(3):
            np.testing.assert_allclose(
                res[:, :, idx],
                np.round(arr[idx, :, :] * 255).astype(np.uint8))

        tags = {
            'new_subfile_type':
            0,
            'image_width':
            1024,
            'image_length':
            1024,
            'bits_per_sample': (8, 8, 8, 8),
            'compression':
            32946,
            'photometric':
            2,
            'orientation':
            1,
            'samples_per_pixel':
            4,
            'planar_configuration':
            1,
            'software':
            b'tifffile/pytroll',
            'datetime':
            b'2020:01:17 14:17:23',
            'tile_width':
            256,
            'tile_length':
            256,
            'tile_offsets':
            (951, 24414, 77352, 126135, 141546, 206260, 272951, 318709, 349650,
             413166, 475735, 519168, 547960, 570326, 615924, 666705),
            'tile_byte_counts':
            (23463, 52938, 48783, 15411, 64714, 66691, 45758, 30941, 63516,
             62569, 43433, 28792, 22366, 45598, 50781, 13371),
            'extra_samples':
            2,
            'sample_format': (1, 1, 1, 1),
            'model_pixel_scale':
            (0.026949458523585643, 0.027040118922685666, 0.0),
            'model_tie_point':
            (0.0, 0.0, 0.0, -35.00279008179894, 73.3850622630575, 0.0),
            '40000':
            b'NINJO',
            '40001':
            6300014,
            '40002':
            1579264321,
            '40003':
            1579267043,
            '40004':
            6500015,
            '40005':
            2,
            '40006':
            b'/tmp/tmpb4kn93qt',
            '40007':
            b'PPRN',
            '40008':
            b'',
            '40009':
            24,
            '40010':
            b'SMHI',
            '40011':
            1,
            '40012':
            1024,
            '40013':
            1,
            '40014':
            1024,
            '40015':
            b'NPOL',
            '40016':
            -35.00278854370117,
            '40017':
            24.72344398498535,
            '40018':
            6378137.0,
            '40019':
            6356752.5,
            '40021':
            60.0,
            '40022':
            0.0,
            '40023':
            0.0,
            '40024':
            b'None',
            '40025':
            b'None',
            '40026':
            0,
            '40027':
            255,
            '40028':
            1.0,
            '40029':
            0.0,
            '40040':
            0,
            '40041':
            0,
            '40042':
            1,
            '40043':
            0,
            '50000':
            0,
            'fill_order':
            1,
            'rows_per_strip':
            4294967295,
            'resolution_unit':
            2,
            'predictor':
            1,
            'ycbcr_subsampling':
            1,
            'ycbcr_positioning':
            1
        }
        read_tags = tif.pages[0].tags
        assert (read_tags.keys() == tags.keys())
        for key, val in tags.items():
            if key in ['datetime', '40002', '40003', '40006']:
                continue
            assert (val == read_tags[key].value)
Пример #21
0
def _fake_get_enhanced_image(img):
    from trollimage.xrimage import XRImage
    return XRImage(img)
Пример #22
0
def to_image(dataset):
    dataset = dataset.squeeze()
    if dataset.ndim < 2:
        raise ValueError("Need at least a 2D array to make an image.")
    else:
        return XRImage(dataset)