-
Notifications
You must be signed in to change notification settings - Fork 5
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
Mhs/das 2108/handle no data #6
Changes from 8 commits
8e70e4f
6f3f62c
b2eef3b
b384e1f
a309eff
a2296ce
cbbb64c
f99ba33
e46aafd
37ff062
3dbba3c
da4a015
ea5a2a1
8e5f376
9a7902f
92a303e
1beaa4d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
1.0.1 | ||
1.0.2 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,8 @@ | |
|
||
import requests | ||
from harmony.message import Source as HarmonySource | ||
import numpy as np | ||
from numpy import ndarray | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: It feels a bit weird importing all of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup. Ok, I tried again. I can update it by putting my type in single quotes. Is that better? from typing import TYPE_CHECKING
if TYPE_CHECKING:
from numpy import ndarray And then def remove_alpha(raster: 'ndarray') -> tuple['ndarray', 'ndarray', None]:
"""remove alpha layer when it exists."""
if raster.shape[0] == 4:
return raster[0:3, :, :], raster[3, :, :]
return raster, None There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is that even right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, I'm worried this next comment is me missing something, but couldn't you just stick with the single import (
I tried a toy model locally, and that seemed okay. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could. This was why I hadn't elsewhere: "but I remember the format got black wonky" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. but I don't have strong opinions I suppose 9a7902f |
||
from osgeo_utils.auxiliary.color_palette import ColorPalette | ||
from pystac import Item | ||
from rasterio.io import DatasetReader | ||
|
@@ -18,6 +20,8 @@ | |
|
||
# Constants for output PNG images | ||
# Applied to transparent pixels where alpha < 255 | ||
TRANSPARENT = np.uint8(0) | ||
OPAQUE = np.uint8(255) | ||
TRANSPARENT_RGBA = (0, 0, 0, 0) | ||
TRANSPARENT_IDX = 254 | ||
|
||
|
@@ -26,6 +30,13 @@ | |
NODATA_IDX = 255 | ||
|
||
|
||
def remove_alpha(raster: ndarray) -> tuple[ndarray, ndarray, None]: | ||
"""remove alpha layer when it exists.""" | ||
if raster.shape[0] == 4: | ||
return raster[0:3, :, :], raster[3, :, :] | ||
return raster, None | ||
flamingbear marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
def palette_from_remote_colortable(url: str) -> ColorPalette: | ||
"""Return a gdal ColorPalette from a remote colortable.""" | ||
response = requests.get(url, timeout=10) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ | |
from rasterio.warp import Resampling | ||
from xarray import DataArray | ||
|
||
|
||
from harmony_browse_image_generator.browse import ( | ||
convert_mulitband_to_raster, | ||
convert_singleband_to_raster, | ||
|
@@ -36,6 +37,8 @@ | |
convert_colormap_to_palette, | ||
get_color_palette, | ||
palette_from_remote_colortable, | ||
OPAQUE, | ||
TRANSPARENT, | ||
) | ||
from harmony_browse_image_generator.exceptions import HyBIGError | ||
from tests.unit.utility import rasterio_test_file | ||
|
@@ -298,39 +301,46 @@ def test_create_browse_imagery_with_mocks( | |
) | ||
|
||
def test_convert_singleband_to_raster_without_colortable(self): | ||
ds = MagicMock(DataArray) | ||
ds.__getitem__.return_value = self.data | ||
"""Tests convert_gray_1band_to_raster.""" | ||
|
||
return_data = np.copy(self.data).astype('float64') | ||
return_data[0][1] = np.nan | ||
ds = DataArray(return_data).expand_dims('band') | ||
|
||
expected_raster = np.array( | ||
[ | ||
[ | ||
[0, 104, 198, 255], | ||
[0, 0, 198, 255], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you change this from 104 to 0 to demonstrate transparent pixel behavior? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, yes, this is the expected array, I added a missing value at the [0,1] location, and these changes are the ones reflected in the output from the missing data. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh right. You changed the code so the expected array changed. |
||
[0, 104, 198, 255], | ||
[0, 104, 198, 255], | ||
[0, 104, 198, 255], | ||
], | ||
[ | ||
[0, 104, 198, 255], | ||
[0, 0, 198, 255], | ||
[0, 104, 198, 255], | ||
[0, 104, 198, 255], | ||
[0, 104, 198, 255], | ||
], | ||
[ | ||
[0, 104, 198, 255], | ||
[0, 0, 198, 255], | ||
[0, 104, 198, 255], | ||
[0, 104, 198, 255], | ||
[0, 104, 198, 255], | ||
], | ||
[ | ||
[255, 0, 255, 255], | ||
[255, 255, 255, 255], | ||
[255, 255, 255, 255], | ||
[255, 255, 255, 255], | ||
], | ||
], | ||
dtype='uint8', | ||
) | ||
|
||
actual_raster = convert_singleband_to_raster(ds, None) | ||
assert_array_equal(expected_raster, actual_raster) | ||
|
||
def test_convert_singleband_to_raster_with_colormap(self): | ||
ds = MagicMock(DataArray) | ||
flamingbear marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ds.__getitem__.return_value = self.data | ||
ds = DataArray(self.data).expand_dims('band') | ||
|
||
expected_raster = np.array( | ||
[ | ||
|
@@ -367,13 +377,11 @@ def test_convert_singleband_to_raster_with_colormap(self): | |
assert_array_equal(expected_raster, actual_raster) | ||
|
||
def test_convert_singleband_to_raster_with_colormap_and_bad_data(self): | ||
ds = MagicMock(DataArray) | ||
data_array = np.array(self.data, dtype='float') | ||
data_array[0, 0] = np.nan | ||
ds = DataArray(data_array).expand_dims('band') | ||
nv_color = (10, 20, 30, 40) | ||
|
||
ds.__getitem__.return_value = data_array | ||
|
||
# Read the image down: red, yellow, green, blue | ||
expected_raster = np.array( | ||
[ | ||
|
@@ -412,9 +420,14 @@ def test_convert_singleband_to_raster_with_colormap_and_bad_data(self): | |
assert_array_equal(expected_raster, actual_raster) | ||
|
||
def test_convert_3_multiband_to_raster(self): | ||
ds = Mock(DataArray) | ||
ds.rio.count = 3 | ||
ds.to_numpy.return_value = np.stack([self.data, self.data, self.data]) | ||
|
||
bad_data = np.copy(self.data).astype('float64') | ||
bad_data[1][1] = np.nan | ||
bad_data[1][2] = np.nan | ||
ds = DataArray( | ||
np.stack([self.data, bad_data, self.data]), | ||
dims=('band', 'y', 'x'), | ||
) | ||
|
||
expected_raster = np.array( | ||
[ | ||
|
@@ -426,7 +439,7 @@ def test_convert_3_multiband_to_raster(self): | |
], | ||
[ | ||
[0, 85, 170, 255], | ||
[0, 85, 170, 255], | ||
[0, 0, 0, 255], | ||
[0, 85, 170, 255], | ||
[0, 85, 170, 255], | ||
], | ||
|
@@ -436,6 +449,12 @@ def test_convert_3_multiband_to_raster(self): | |
[0, 85, 170, 255], | ||
[0, 85, 170, 255], | ||
], | ||
[ | ||
[OPAQUE, OPAQUE, OPAQUE, OPAQUE], | ||
[OPAQUE, TRANSPARENT, TRANSPARENT, OPAQUE], | ||
[OPAQUE, OPAQUE, OPAQUE, OPAQUE], | ||
[OPAQUE, OPAQUE, OPAQUE, OPAQUE], | ||
], | ||
], | ||
dtype='uint8', | ||
) | ||
|
@@ -444,16 +463,27 @@ def test_convert_3_multiband_to_raster(self): | |
assert_array_equal(expected_raster, actual_raster.data) | ||
|
||
def test_convert_4_multiband_to_raster(self): | ||
"""Input data has NaN _fillValue match in the red layer at [1,1] | ||
and alpha chanel also exists with a single transparent value at [0,0] | ||
flamingbear marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
See that the expected output has transformed the missing data [nan] | ||
into fully transparent at [1,1] and retained the transparent value of 1 | ||
at [0,0] | ||
|
||
""" | ||
ds = Mock(DataArray) | ||
bad_data = np.copy(self.data).astype('float64') | ||
bad_data[1, 1] = np.nan | ||
|
||
alpha = np.ones_like(self.data) * 255 | ||
alpha[0, 0] = 1 | ||
ds.rio.count = 4 | ||
ds.to_numpy.return_value = np.stack([self.data, self.data, self.data, alpha]) | ||
ds.to_numpy.return_value = np.stack([bad_data, self.data, self.data, alpha]) | ||
expected_raster = np.array( | ||
[ | ||
[ | ||
[0, 85, 170, 255], | ||
[0, 85, 170, 255], | ||
[0, 0, 170, 255], | ||
[0, 85, 170, 255], | ||
[0, 85, 170, 255], | ||
], | ||
|
@@ -471,7 +501,7 @@ def test_convert_4_multiband_to_raster(self): | |
], | ||
[ | ||
[1, 255, 255, 255], | ||
[255, 255, 255, 255], | ||
[255, 0, 255, 255], | ||
[255, 255, 255, 255], | ||
[255, 255, 255, 255], | ||
], | ||
|
@@ -493,7 +523,8 @@ def test_convert_5_multiband_to_raster(self): | |
convert_mulitband_to_raster(ds) | ||
|
||
self.assertEqual( | ||
excepted.exception.message, 'Cannot create image from 5 band image' | ||
excepted.exception.message, | ||
'Cannot create image from 5 band image. Expecting 3 or 4 bands.', | ||
) | ||
|
||
def test_prepare_raster_for_writing_jpeg_3band(self): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh - weird that this ordering happened. Feels a bit off, but I guess I trust it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed this too*, I think we don't have that set in the pre-commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3dbba3c
I had a bad pyproject.toml, not sure why our precommit didn't catch it though. I will look
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should propagate this to the other repos as we touch them.
da4a015
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch - I might just put up a couple of PRs now. (Some of those repos don't get much love and we might forget)