diff --git a/geoarray/baseclasses.py b/geoarray/baseclasses.py index ece369c9a5c4bf7a8af3251c9a36535cedb2e6f4..5000849f5443d5de999813e763a0172781825e6e 100644 --- a/geoarray/baseclasses.py +++ b/geoarray/baseclasses.py @@ -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() diff --git a/geoarray/metadata.py b/geoarray/metadata.py index a39a946708f9c1af9e1f9dabbad2b35d3c23237a..54dceb0f36061d56a3e05a34870d3a87dee72310 100644 --- a/geoarray/metadata.py +++ b/geoarray/metadata.py @@ -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()])) diff --git a/tests/test_metadata.py b/tests/test_metadata.py index edf985be50a6dd24d80dbf9bc996c8a0cbe4d2dc..e6bb385b731295586b1afc8615370ffa8f021a84 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -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)