Commit e04db20b authored by Daniel Scheffler's avatar Daniel Scheffler

First implementation of metadata class in GeoArray.

parent 7bc08f6d
......@@ -40,6 +40,7 @@ from py_tools_ds.numeric.array import get_array_tilebounds
# internal imports
from .subsetting import get_array_at_mapPos
from .metadata import GDAL_Metadata
if PY3:
# noinspection PyCompatibility
......@@ -171,7 +172,7 @@ class GeoArray(object):
# update bandnames in metadata
if self._metadata is not None:
self.metadata.loc['band_name', :] = list_bandnames
self.metadata.band_meta['band_names'] = list_bandnames
else:
del self.bandnames
......@@ -499,9 +500,8 @@ class GeoArray(object):
if self._metadata is not None:
return self._metadata
else:
default = GeoDataFrame(columns=range(self.bands))
# for bn,idx in self.bandnames.items():
# default.loc['band_index',bn] = idx
default = GDAL_Metadata(nbands=self.bands)
self._metadata = default
if not self.is_inmem:
self.set_gdalDataset_meta()
......@@ -717,28 +717,13 @@ class GeoArray(object):
# FIXME this does not support different nodata values within the same file
self._nodata = band.GetNoDataValue()
# read global domain metadata
# TODO check to specifically use the 'ENVI' metadata domain ds.GetMetadata('ENVI')
global_meta = ds.GetMetadata()
# read band domain metadata
for b in range(self.bands):
band = ds.GetRasterBand(b + 1)
meta_gs = GeoSeries(band.GetMetadata())
# add band names if available
if 'Band_%s' % str(b + 1) in global_meta.keys():
meta_gs['band_name'] = global_meta['Band_%s' % str(b + 1)]
# TODO add the remaining global metadata
# set metadata attribute
if self.is_inmem or not self.filePath:
# metadata cannot be read from disk -> set it to the default
self._metadata = GDAL_Metadata(nbands=self.bands)
# avoid double-call of set_gdalDataset_meta by setting self._metadata to default value
self._metadata = \
self._metadata if self._metadata is not None else GeoDataFrame(columns=range(self.bands))
# fill metadata
self.metadata[b] = meta_gs
del band
else:
self._metadata = GDAL_Metadata(filePath=self.filePath)
del ds
......@@ -909,32 +894,30 @@ class GeoArray(object):
# set metadata
# NOTE: The dataset has to be written BEFORE metadata are added. Otherwise, metadata are not written.
if not self.metadata.empty:
global_meta = {}
if fmt == 'ENVI':
envi_metadict = self.metadata.to_ENVI_metadict()
ds_out.SetMetadata(envi_metadict, 'ENVI')
# set band domain metadata
for bidx in range(self.bands):
band = ds_out.GetRasterBand(bidx + 1)
meta2write = self.metadata[bidx].to_dict()
meta2write = dict((k, repr(v)) for k, v in meta2write.items() if v is not np.nan)
if 'band_names' in envi_metadict:
ds_out.SetMetadata({'Band_%s' % str(bidx + 1): self.metadata.band_meta['band_names'][bidx]
for bidx in range(self.bands)})
if 'band_name' in meta2write:
global_meta['Band_%s' % str(bidx + 1)] = str(meta2write['band_name'])
del meta2write['band_name']
ds_out.FlushCache()
gdal.Unlink(out_path + '.aux.xml')
band.SetMetadata(meta2write)
band.FlushCache()
del band
elif self.metadata.all_meta:
# set global domain metadata
if self.metadata.global_meta:
ds_out.SetMetadata(self.metadata.global_meta)
# set global domain metadata
if global_meta:
ds_out.SetMetadata(global_meta)
# set band domain metadata
for bidx in range(self.bands):
band = ds_out.GetRasterBand(bidx + 1)
meta2write = dict((k, repr(v)) for k, v in self.metadata.band_meta.items() if v is not np.nan)
# get ENVI metadata domain
# ds_orig = gdal.Open(self.filePath)
# envi_meta_domain = ds_orig.GetMetadata('ENVI')
# ds.SetMetadata(envi_meta_domain, 'ENVI')
# ds_orig = None
band.SetMetadata(meta2write)
band.FlushCache()
del band
ds_out.FlushCache()
......
......@@ -97,13 +97,30 @@ class GDAL_Metadata(object):
return all_meta
@staticmethod
def _convert_str_parameter(param_value):
def _convert_param_from_str(param_value):
try:
try:
return int(param_value) # NOTE: float('0.34') causes ValueError: invalid literal for int() with base 10
except ValueError:
return float(param_value)
except ValueError:
if param_value.startswith('{'):
param_value = param_value.split('{')[1]
if param_value.endswith('}'):
param_value = param_value.split('}')[0]
return param_value.strip()
def _convert_param_to_ENVI_str(self, param_value):
if isinstance(param_value, int):
return str(param_value)
elif isinstance(param_value, float):
return '%f' % param_value
elif isinstance(param_value, list):
return '{ ' + ', '.join([self._convert_param_to_ENVI_str(i) for i in param_value]) + ' }'
else:
return param_value
def read_from_file(self, filePath):
......@@ -139,11 +156,11 @@ class GDAL_Metadata(object):
item_str.split('}')[0].strip() if item_str.strip().endswith('}') else
item_str.strip() for item_str in v.split(',')]
self.band_meta[k] = [self._convert_str_parameter(item_str) for item_str in item_list]
self.band_meta[k] = [self._convert_param_from_str(item_str) for item_str in item_list]
else:
# global meta parameter
self.global_meta[k] = self._convert_str_parameter(v)
self.global_meta[k] = self._convert_param_from_str(v)
#####################
# remaining formats #
......@@ -163,7 +180,7 @@ class GDAL_Metadata(object):
if k not in self.band_meta:
self.band_meta[k] = []
self.band_meta[k].append(self._convert_str_parameter(v))
self.band_meta[k].append(self._convert_param_from_str(v))
# # fill metadata
# self.df[b] = meta_gs
......@@ -175,4 +192,8 @@ class GDAL_Metadata(object):
return self.all_meta
def __repr__(self):
return pformat(self.all_meta)
return 'Metadata: \n\n' + pformat(self.all_meta)
def to_ENVI_metadict(self):
return dict(zip(self.all_meta.keys(),
[self._convert_param_to_ENVI_str(i) for i in self.all_meta.values()]))
......@@ -4,12 +4,21 @@
from unittest import TestCase
from geoarray.metadata import GDAL_Metadata
from geoarray import GeoArray
class Test_GDAL_Metadata(TestCase):
def setUp(self):
self.test_filePath = '/home/gfz-fe/scheffler/temp/SPECHOM/ORIG_DATA/' \
'f130502t01p00r09_refl_master_calibration_Aviris.bsq' # FIXME
self.test_outfilePath = '/home/gfz-fe/scheffler/temp/SPECHOM_py/debugging/' \
'f130502t01p00r09_refl_master_calibration_Aviris_out.bsq' # FIXME
def test_init(self):
GDAL_Metadata(self.test_filePath)
meta = GDAL_Metadata(self.test_filePath)
self.assertIsInstance(meta, GDAL_Metadata)
def test_save(self):
gA = GeoArray(self.test_filePath)
gA.to_mem()
gA.save(self.test_outfilePath)
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