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