Commit 488437ea authored by Daniel Scheffler's avatar Daniel Scheffler
Browse files

Merge branch 'enhancement/improve_metahandling' into 'master'

Enhancement/improve metahandling

See merge request !22
parents 2d17bdff 0531f649
Pipeline #21615 canceled with stages
......@@ -2,10 +2,17 @@
History
=======
0.10.11 (coming soon)
---------------------
0.10.11 (2021-04-08)
--------------------
* Fixed another numpy data type DeprecationWarning.
* Added 'make docs' artifacts to .gitignore.
* Fixed undeleted output of Test_GeoArray.test_save().
* Added .gitkeep to tests/output/ folder.
* 'make lint' now directly prints the log outputs.
* Band names and nodata values are now correctly read in case of data formats other than ENVI.
* Improved saved metadata for all formats (mainly applies to band names and nodata values).
* Fixed nodata value not passed through when reading a data format other than ENVI and saving in ENVI format.
0.10.10 (2021-02-19)
......
......@@ -51,9 +51,12 @@ clean-test: ## remove test and coverage artifacts
rm -fr nosetests.xml
lint: ## check style with flake8
flake8 --max-line-length=120 geoarray tests > ./tests/linting/flake8.log
pycodestyle geoarray --exclude="*.ipynb,*.ipynb*" --max-line-length=120 > ./tests/linting/pycodestyle.log
-pydocstyle geoarray > ./tests/linting/pydocstyle.log
flake8 --max-line-length=120 geoarray tests > ./tests/linting/flake8.log || \
(cat ./tests/linting/flake8.log && exit 1)
pycodestyle geoarray --exclude="*.ipynb,*.ipynb*" --max-line-length=120 > ./tests/linting/pycodestyle.log || \
(cat ./tests/linting/pycodestyle.log && exit 1)
-pydocstyle geoarray > ./tests/linting/pydocstyle.log || \
(cat ./tests/linting/pydocstyle.log && exit 1)
urlcheck: ## check for dead URLs
urlchecker check . --file-types .py,.rst,.md,.json
......
......@@ -818,7 +818,6 @@ class GeoArray(object):
:param getitem_params: <list> a list of slices in the form [row_slice, col_slice, band_slice]
:return out_arr: <np.ndarray> the output array
"""
ds = gdal.Open(path)
if not ds:
raise Exception('Error reading file: ' + gdal.GetLastErrorMsg())
......@@ -1022,16 +1021,34 @@ class GeoArray(object):
# ENVI #
########
if fmt == 'ENVI':
ds_out.SetMetadata(envi_metadict, 'ENVI')
for bidx in range(self.bands):
band = ds_out.GetRasterBand(bidx + 1)
if 'band_names' in envi_metadict:
for bidx in range(self.bands):
band = ds_out.GetRasterBand(bidx + 1)
if 'band_names' in envi_metadict:
bandname = self.metadata.band_meta['band_names'][bidx].strip()
band.SetDescription(bandname)
assert band.GetDescription() == bandname
del band
# NOTE: band-specific nodata values are not supported by the ENVI header format
if 'nodata' in envi_metadict:
nodataVal = self.metadata.band_meta['nodata'][bidx]
band.SetNoDataValue(nodataVal)
assert band.GetNoDataValue() == nodataVal
del band
# avoid that band names are written to global meta
if 'band_names' in envi_metadict:
del envi_metadict['band_names']
if 'nodata' in envi_metadict:
del envi_metadict['nodata']
# set data ignore value in case self.metadata.band_meta contains a unique nodata value
if 'nodata' in self.metadata.band_meta and len(set(self.metadata.band_meta['nodata'])) == 1:
envi_metadict['data ignore value'] = str(self.metadata.band_meta['nodata'][0])
ds_out.SetMetadata(envi_metadict, 'ENVI')
if 'description' in envi_metadict:
ds_out.SetDescription(envi_metadict['description'])
......@@ -1052,12 +1069,22 @@ class GeoArray(object):
for bidx in range(self.bands):
band = ds_out.GetRasterBand(bidx + 1)
bandmeta = bandmeta_dict[bidx]
bandmeta = bandmeta_dict[bidx].copy()
# filter global metadata out
bandmeta = {k: v for k, v in bandmeta.items() if k not in self.metadata.global_meta}
# meta2write = dict((k, repr(v)) for k, v in self.metadata.band_meta.items() if v is not np.nan)
band.SetMetadata(bandmeta)
if 'band_names' in envi_metadict:
if 'band_names' in bandmeta:
band.SetDescription(self.metadata.band_meta['band_names'][bidx].strip())
del bandmeta['band_names']
if 'nodata' in bandmeta:
band.SetNoDataValue(self.metadata.band_meta['nodata'][bidx])
del bandmeta['nodata']
if bandmeta:
band.SetMetadata(bandmeta)
band.FlushCache()
del band
......
......@@ -196,6 +196,17 @@ class GDAL_Metadata(object):
# meta_gs = GeoSeries(band.GetMetadata())
bandmeta_dict = band.GetMetadata()
# read bandname
bandname = band.GetDescription()
if bandname:
bandmeta_dict['band_names'] = bandname
# read nodata value
nodataVal = band.GetNoDataValue()
if nodataVal is not None:
bandmeta_dict['nodata'] = nodataVal
# read remaining meta
for k, v in bandmeta_dict.items():
if k not in self.band_meta:
self.band_meta[k] = []
......
......@@ -424,14 +424,16 @@ class Test_GeoArray(TestCase):
with tempfile.NamedTemporaryFile(dir=os.path.join(tests_path, "tests", "data", "output"),
prefix="L8_BadDataMask10x11_copy_",
suffix=".tif") as tf:
# Save as temporary GTiff
L8_2bands_extract10x11_copy = tf.name
gA.save(L8_2bands_extract10x11_copy, fmt="GTiff")
gA_copy = GeoArray(L8_2bands_extract10x11_copy)
self.assertTrue(os.path.exists(L8_2bands_extract10x11_copy))
self.assertIsInstance(gA_copy, GeoArray)
self.assertTrue(np.array_equal(gA[:], gA_copy[:]))
# save GeoArray and validate output
for fmt in ['ENVI', 'GTiff']:
gA.save(tf.name, fmt=fmt)
gA_copy = GeoArray(tf.name)
self.assertTrue(os.path.exists(tf.name))
self.assertIsInstance(gA_copy, GeoArray)
self.assertTrue(np.array_equal(gA[:], gA_copy[:]))
self.assertEqual(gA._nodata, gA_copy._nodata)
def test_show(self):
# test 3D case
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment