Commit 7ec71165 authored by Daniel Scheffler's avatar Daniel Scheffler
Browse files

Removed GMS_object.meta_odict. All metadata is now held in MetaObj.

parent b11a4c6d
......@@ -523,7 +523,6 @@ class L1A_object(GMS_object):
if rasObj.get_projection_type() == 'UTM':
self.MetaObj.CornerTieP_UTM = rasObj.get_corner_coordinates('UTM')
self.meta_odict = self.MetaObj.to_odict() # important in order to keep geotransform/projection
if CFG.inmem_serialization:
self.delete_tempFiles() # these files are needed later in Python execution mode
self.MetaObj.Dataname = previous_dataname # /vsi.. pointing directly to raw data archive (which exists)
......
......@@ -277,7 +277,7 @@ class L1B_object(L1A_object):
def get_spatial_reference_scene(self):
boundsLonLat = corner_coord_to_minmax(self.trueDataCornerLonLat)
footprint_poly = HLP_F.CornerLonLat_to_shapelyPoly(self.trueDataCornerLonLat)
RSF = Scene_finder(boundsLonLat, self.acq_datetime, self.meta_odict['coordinate system string'],
RSF = Scene_finder(boundsLonLat, self.acq_datetime, self.MetaObj.projection,
footprint_poly, self.scene_ID,
min_overlap=CFG.spatial_ref_min_overlap,
min_cloudcov=CFG.spatial_ref_min_cloudcov,
......@@ -486,8 +486,8 @@ class L1B_object(L1A_object):
ref_obj = GMS_object.from_disk((path_gmsFile, ['cube', None]))
# get spectral characteristics
ref_cwl, shift_cwl = [[float(i) for i in GMS_obj.meta_odict['wavelength']] for GMS_obj in [ref_obj, self]]
ref_fwhm, shift_fwhm = [[float(i) for i in GMS_obj.meta_odict['bandwidths']] for GMS_obj in [ref_obj, self]]
ref_cwl, shift_cwl = [[float(i) for i in GMS_obj.MetaObj.CWL] for GMS_obj in [ref_obj, self]]
ref_fwhm, shift_fwhm = [[float(i) for i in GMS_obj.MetaObj.FWHM] for GMS_obj in [ref_obj, self]]
# exclude cirrus/oxygen band of Landsat-8/Sentinel-2
shift_bbl, ref_bbl = [False] * len(shift_cwl), [False] * len(ref_cwl) # bad band lists
......@@ -561,7 +561,7 @@ class L1B_object(L1A_object):
max_shift=CFG.coreg_max_shift_allowed,
ws=CFG.coreg_window_size,
data_corners_ref=[[x, y] for x, y in self.spatRef_scene.polyUTM.convex_hull.exterior.coords],
data_corners_tgt=[transform_any_prj(EPSG2WKT(4326), self.meta_odict['coordinate system string'], x, y)
data_corners_tgt=[transform_any_prj(EPSG2WKT(4326), self.MetaObj.projection, x, y)
for x, y in HLP_F.reorder_CornerLonLat(self.trueDataCornerLonLat)],
nodata=(get_outFillZeroSaturated(geoArr_ref.dtype)[0],
get_outFillZeroSaturated(geoArr_shift.dtype)[0]),
......@@ -690,10 +690,10 @@ class L1B_object(L1A_object):
# update geoinformations and array shape related attributes
self.logger.info("Updating geoinformations of '%s' attribute..." % attrname)
if attrname == 'arr':
self.meta_odict['map info'] = DS.updated_map_info
self.meta_odict['coordinate system string'] = EPSG2WKT(WKT2EPSG(DS.updated_projection))
self.MetaObj.map_info = DS.updated_map_info
self.MetaObj.projection = EPSG2WKT(WKT2EPSG(DS.updated_projection))
self.shape_fullArr = DS.arr_shifted.shape
self.meta_odict['lines'], self.meta_odict['samples'] = DS.arr_shifted.shape[:2]
self.MetaObj.rows, self.MetaObj.cols = DS.arr_shifted.shape[:2]
else:
self.masks_meta['map info'] = DS.updated_map_info
self.masks_meta['coordinate system string'] = EPSG2WKT(WKT2EPSG(DS.updated_projection))
......@@ -705,7 +705,7 @@ class L1B_object(L1A_object):
geoArr.arr, geoArr.gt, geoArr.prj = \
DS.GeoArray_shifted.arr, DS.GeoArray_shifted.gt, DS.GeoArray_shifted.prj
# setattr(self,attrname, DS.GeoArray_shifted) # NOTE: don't set array earlier because setter will also
# # update arr.gt/.prj/.nodata from meta_odict
# # update arr.gt/.prj/.nodata from MetaObj
self.resamp_needed = False
self.coreg_needed = False
......
......@@ -64,8 +64,8 @@ class L1C_object(L1B_object):
self.logger.info('Calculating LonLat array...')
self._lonlat_arr = \
GEOP.get_lonlat_coord_array(self.shape_fullArr, self.arr_pos,
mapinfo2geotransform(self.meta_odict['map info']),
self.meta_odict['coordinate system string'],
mapinfo2geotransform(self.MetaObj.map_info),
self.MetaObj.projection,
meshwidth=10, # for faster processing
nodata_mask=None, # dont overwrite areas outside the image with nodata
outFill=get_outFillZeroSaturated(np.float32)[0])[0]
......@@ -87,17 +87,17 @@ class L1C_object(L1B_object):
"""
if self._VZA_arr is None:
self.logger.info('Calculating viewing zenith array...')
if 'ViewingAngle_arrProv' in self.meta_odict and self.meta_odict['ViewingAngle_arrProv']:
if self.MetaObj.ViewingAngle_arrProv:
# Sentinel-2
self._VZA_arr = GEOP.adjust_acquisArrProv_to_shapeFullArr(self.meta_odict['ViewingAngle_arrProv'],
self._VZA_arr = GEOP.adjust_acquisArrProv_to_shapeFullArr(self.MetaObj.ViewingAngle_arrProv,
self.shape_fullArr,
meshwidth=10, # for faster processing
subset=None,
bandwise=0)
else:
self._VZA_arr = GEOP.calc_VZA_array(self.shape_fullArr, self.arr_pos, self.fullSceneCornerPos,
float(self.meta_odict['ViewingAngle']),
float(self.meta_odict['FieldOfView']),
float(self.MetaObj.ViewingAngle),
float(self.MetaObj.FOV),
self.logger,
nodata_mask=None, # dont overwrite areas outside image with nodata
outFill=get_outFillZeroSaturated(np.float32)[0],
......@@ -120,9 +120,9 @@ class L1C_object(L1B_object):
"""
if self._VAA_arr is None:
self.logger.info('Calculating viewing azimuth array...')
if 'IncidenceAngle_arrProv' in self.meta_odict and self.meta_odict['IncidenceAngle_arrProv']:
if self.MetaObj.IncidenceAngle_arrProv:
# Sentinel-2
self._VAA_arr = GEOP.adjust_acquisArrProv_to_shapeFullArr(self.meta_odict['IncidenceAngle_arrProv'],
self._VAA_arr = GEOP.adjust_acquisArrProv_to_shapeFullArr(self.MetaObj.IncidenceAngle_arrProv,
self.shape_fullArr,
meshwidth=10, # for faster processing
subset=None,
......@@ -156,11 +156,11 @@ class L1C_object(L1B_object):
self._SZA_arr, self._SAA_arr = \
GEOP.calc_SZA_SAA_array(
self.shape_fullArr, self.arr_pos,
self.meta_odict['AcqDate'],
self.meta_odict['AcqTime'],
self.MetaObj.AcqDate,
self.MetaObj.AcqTime,
self.fullSceneCornerPos,
self.fullSceneCornerLonLat,
self.meta_odict['overpass duraction sec'],
self.MetaObj.overpassDurationSec,
self.logger,
meshwidth=10,
nodata_mask=None, # dont overwrite areas outside the image with nodata
......@@ -360,7 +360,7 @@ class AtmCorr(object):
# float32! -> conversion to np.float16 will convert -9999 to -10000
arr2pass = inObj.arr[:, :, bandIdx].astype(np.float32)
arr2pass[arr2pass == inObj.arr.nodata] = np.nan # set nodata values to np.nan
data_dict[bandN] = (arr2pass / inObj.meta_odict['ScaleFactor']).astype(np.float16)
data_dict[bandN] = (arr2pass / inObj.MetaObj.ScaleFactor).astype(np.float16)
else:
inObj.logger.warning("Band '%s' cannot be included into atmospheric correction because it "
"exists multiple times." % bandN)
......@@ -472,14 +472,14 @@ class AtmCorr(object):
del self.logger # otherwise each input object would have multiple fileHandlers
metadata = dict(
U=self.inObjs[0].meta_odict['EarthSunDist'],
U=self.inObjs[0].MetaObj.EarthSunDist,
SENSING_TIME=self.inObjs[0].acq_datetime,
# SENSING_TIME=datetime.strptime('2015-08-12 10:40:21 +0000', '%Y-%m-%d %H:%M:%S %z'),
viewing_zenith=self._meta_get_viewing_zenith(),
viewing_azimuth=self._meta_get_viewing_azimuth(),
relative_viewing_azimuth=self._meta_get_relative_viewing_azimuth(),
sun_mean_azimuth=self.inObjs[0].meta_odict['SunAzimuth'],
sun_mean_zenith=90 - self.inObjs[0].meta_odict['SunElevation'],
sun_mean_azimuth=self.inObjs[0].MetaObj.SunAzimuth,
sun_mean_zenith=90 - self.inObjs[0].MetaObj.SunElevation,
solar_irradiance=self._meta_get_solar_irradiance(),
aux_data=self._meta_get_aux_data(),
spatial_samplings=self._meta_get_spatial_samplings()
......@@ -950,7 +950,6 @@ class AtmCorr(object):
inObj.MetaObj.LayerBandsAssignment = out_LBA
inObj.LayerBandsAssignment = out_LBA
inObj.MetaObj.filter_layerdependent_metadata()
inObj.meta_odict = inObj.MetaObj.to_odict() # actually auto-updated by getter
##################################################################################
# join SURFACE REFLECTANCE as 3D int16 array, scaled to scale factor from config #
......
......@@ -61,7 +61,7 @@ class L2B_object(L2A_object):
method = CFG.spechomo_method
src_dsID = sat_sen_to_datasetid(self.satellite, self.sensor)
src_cwls = self.meta_odict['wavelength']
src_cwls = self.MetaObj.CWL
# FIXME exclude or include thermal bands; respect sorted CWLs in context of LayerBandsAssignment
tgt_sat, tgt_sen = datasetid_to_sat_sen(CFG.datasetid_spectral_ref)
# NOTE: get target LBA at L2A, because spectral characteristics of target sensor do not change after AC
......@@ -124,11 +124,9 @@ class L2B_object(L2A_object):
###################
self.LayerBandsAssignment = tgt_LBA
self.meta_odict['wavelength'] = list(CFG.target_CWL)
self.meta_odict['bandwidths'] = list(CFG.target_FWHM)
self.meta_odict['bands'] = len(CFG.target_CWL)
if 'band names' in self.meta_odict: # FIXME bug workaround
del self.meta_odict['band names'] # TODO
self.MetaObj.CWL = list(CFG.target_CWL)
self.MetaObj.FWHM = list(CFG.target_FWHM)
self.MetaObj.bands = len(CFG.target_CWL)
self.arr = im # type: GeoArray
self.spec_homo_errors = errs # type: Union[np.ndarray, None] # int16, None if ~CFG.spechomo_estimate_accuracy
......
......@@ -297,8 +297,7 @@ def mask_to_ENVI_Classification(InObj, maskname):
rows, cols = classif_array.shape[:2]
bands = 1 if classif_array.ndim == 2 else classif_array.shape[2]
mapI, CSS = (InObj.meta_odict['map info'], InObj.meta_odict['coordinate system string']) \
if hasattr(InObj, 'meta_odict') and InObj.meta_odict else (InObj.MetaObj.map_info, InObj.MetaObj.projection)
mapI, CSS = InObj.MetaObj.map_info, InObj.MetaObj.projection
mask_md = {'file type': 'ENVI Classification', 'map info': mapI, 'coordinate system string': CSS, 'lines': rows,
'samples': cols, 'bands': bands, 'header offset': 0, 'byte order': 0, 'interleave': 'bsq',
'data type': 1, 'data ignore value': get_outFillZeroSaturated(classif_array.dtype)[0]}
......
......@@ -85,7 +85,6 @@ class GMS_object(object):
self._accuracy_layers = None
self._dict_LayerOptTherm = None
self._cloud_masking_algorithm = None
self._meta_odict = None
self._coreg_info = None
# defaults
......@@ -271,13 +270,8 @@ class GMS_object(object):
@property
def MetaObj(self):
if self._meta_odict:
# if there is already a meta_odict -> create a new MetaObj from it (ensures synchronization!)
self._MetaObj = METADATA(self.GMS_identifier).from_odict(self._meta_odict)
del self.meta_odict
elif not self._MetaObj:
# if there is no meta_odict and no MetaObj -> create MetaObj by reading metadata from disk
pass # reading from disk should use L1A_P.L1A_object.import_metadata -> so just return None
# TODO if there is no MetaObj -> create MetaObj by reading metadata from disk
# reading from disk should use L1A_P.L1A_object.import_metadata -> so just return None
return self._MetaObj
......@@ -287,9 +281,6 @@ class GMS_object(object):
"Got %s." % type(MetaObj)
self._MetaObj = MetaObj
# update meta_odict
del self.meta_odict # it is recreated if getter is used the next time
@MetaObj.deleter
def MetaObj(self):
if hasattr(self, '_MetaObj') and self._MetaObj and hasattr(self._MetaObj, 'logger') and \
......@@ -299,32 +290,6 @@ class GMS_object(object):
self._MetaObj = None
@property
def meta_odict(self):
if self._MetaObj:
# if there is already a MetaObj -> create new meta_odict from it (ensures synchronization!)
self._meta_odict = self._MetaObj.to_odict()
del self.MetaObj
elif not self._meta_odict:
# if there is no MetaObj and no meta_odict -> use MetaObj getter to read metadata from disk
pass # reading from disk should use L1A_P.L1A_object.import_metadata -> so just return None
self._meta_odict = None
return self._meta_odict
@meta_odict.setter
def meta_odict(self, odict):
assert isinstance(odict, (collections.OrderedDict, dict)), "'meta_odict' can only be set to an instance of " \
"collections.OrderedDict. Got %s." % type(odict)
self._meta_odict = odict
# update MetaObj
del self.MetaObj # it is recreated if getter is used the next time
@meta_odict.deleter
def meta_odict(self):
self._meta_odict = None
@property
def pathGen(self):
# type: () -> PG.path_generator
......@@ -403,14 +368,14 @@ class GMS_object(object):
self._coreg_info = {
'corrected_shifts_px': {'x': 0, 'y': 0},
'corrected_shifts_map': {'x': 0, 'y': 0},
'original map info': self.meta_odict['map info'],
'original map info': self.MetaObj.map_info,
'updated map info': None,
'shift_reliability': None,
'reference scene ID': None,
'reference entity ID': None,
'reference geotransform': None,
# reference projection must be the own projection in order to avoid overwriting with a wrong EPSG
'reference projection': self.meta_odict['coordinate system string'],
'reference projection': self.MetaObj.projection,
'reference extent': {'rows': None, 'cols': None},
'reference grid': [list(CFG.spatial_ref_gridx),
list(CFG.spatial_ref_gridy)],
......@@ -426,7 +391,7 @@ class GMS_object(object):
@property
def resamp_needed(self):
if self._resamp_needed is None:
gt = mapinfo2geotransform(self.meta_odict['map info'])
gt = mapinfo2geotransform(self.MetaObj.map_info)
self._resamp_needed = not is_coord_grid_equal(gt, CFG.spatial_ref_gridx,
CFG.spatial_ref_gridy)
return self._resamp_needed
......@@ -454,9 +419,6 @@ class GMS_object(object):
self._arr.prj = self.MetaObj.projection if self.MetaObj.projection else self._arr.projection
else:
self._arr.nodata = DEF_D.get_outFillZeroSaturated(self._arr.dtype)[0]
if hasattr(self, 'meta_odict') and self.meta_odict:
self._arr.gt = mapinfo2geotransform(self.meta_odict['map info'])
self._arr.prj = self.meta_odict['coordinate system string']
# set bandnames like this: [B01, .., B8A,]
if self.LayerBandsAssignment:
......@@ -471,6 +433,10 @@ class GMS_object(object):
def arr(self):
self._arr = None
@property
def arr_meta(self):
return self.MetaObj.to_odict()
@property
def mask_nodata(self):
if self._mask_nodata is not None:
......@@ -880,8 +846,11 @@ class GMS_object(object):
# add some selected property values
for i in ['GMS_identifier', 'LayerBandsAssignment', 'coreg_needed', 'coreg_info', 'resamp_needed',
'dict_LayerOptTherm', 'georef', 'meta_odict']:
out_dict[i] = getattr(self, i)
'dict_LayerOptTherm', 'georef', 'MetaObj']:
if i == 'MetaObj':
out_dict['meta_odict'] = self.MetaObj.to_odict()
else:
out_dict[i] = getattr(self, i)
# remove private attributes
if remove_privates:
......@@ -912,7 +881,13 @@ class GMS_object(object):
GMSfileDict = INP_R.GMSfile2dict(path_GMS_file)
# copy all attributes from GMS file (private attributes are not touched since they are not included in GMS file)
GMS_obj.meta_odict = GMSfileDict['meta_odict'] # set that first in order to make some getters and setters work
# set MetaObj first in order to make some getters and setters work
GMS_id = GMS_identifier(image_type=GMSfileDict['image_type'], satellite=GMSfileDict['satellite'],
sensor=GMSfileDict['sensor'], subsystem=GMSfileDict['subsystem'],
proc_level=GMSfileDict['proc_level'], dataset_ID=GMSfileDict['dataset_ID'], logger=None)
GMS_obj.MetaObj = METADATA(GMS_id).from_odict(GMSfileDict['meta_odict'])
for key, value in GMSfileDict.items():
if key in ['GMS_identifier', 'georef', 'dict_LayerOptTherm']:
continue # properties that should better be created on the fly
......@@ -1007,12 +982,9 @@ class GMS_object(object):
bandnames = ['B%s' % i if len(i) == 2 else 'B0%s' % i for i in GMS_obj_merged.LayerBandsAssignment]
# update layer-dependent metadata with respect to remaining input GMS objects
GMS_obj_merged.meta_odict.update({
'band names': [('Band %s' % i) for i in GMS_obj_merged.LayerBandsAssignment],
'LayerBandsAssignment': GMS_obj_merged.LayerBandsAssignment,
'Subsystem': '',
'PhysUnit': GMS_obj_merged.meta_odict['PhysUnit'], # TODO can contain val_optical / val_thermal
})
GMS_obj_merged.MetaObj.LayerBandsAssignment = GMS_obj_merged.LayerBandsAssignment
GMS_obj_merged.MetaObj.Subsystem = ''
GMS_obj_merged.subsystem = ''
del GMS_obj_merged.pathGen # must be refreshed because subsystem is now ''
GMS_obj_merged.close_loggers() # must also be refreshed because it depends on pathGen
......@@ -1188,11 +1160,11 @@ class GMS_object(object):
GMS_obj_merged.build_combined_masks_array()
# update array-dependent metadata
GMS_obj_merged.meta_odict.update({
'samples': GMS_obj_merged.arr.cols, 'lines': GMS_obj_merged.arr.rows,
'bands': GMS_obj_merged.arr.bands,
'map info': geotransform2mapinfo(GMS_obj_merged.arr.gt, GMS_obj_merged.arr.prj),
'coordinate system string': GMS_obj_merged.arr.prj, })
GMS_obj_merged.MetaObj.cols = GMS_obj_merged.arr.cols
GMS_obj_merged.MetaObj.rows = GMS_obj_merged.arr.rows
GMS_obj_merged.MetaObj.bands = GMS_obj_merged.arr.bands
GMS_obj_merged.MetaObj.map_info = geotransform2mapinfo(GMS_obj_merged.arr.gt, GMS_obj_merged.arr.prj)
GMS_obj_merged.MetaObj.projection = GMS_obj_merged.arr.prj
# update corner coordinates # (calc_corner_positions is a method of L1A_object)
GMS_obj_merged.calc_corner_positions()
......@@ -1245,13 +1217,11 @@ class GMS_object(object):
GMS_obj.arr_pos = None
# update MetaObj attributes
GMS_obj.meta_odict.update({
'samples': GMS_obj.arr.cols,
'lines': GMS_obj.arr.rows,
'bands': GMS_obj.arr.bands,
'map info': geotransform2mapinfo(GMS_obj.arr.gt, GMS_obj.arr.prj),
'coordinate system string': GMS_obj.arr.prj
})
GMS_obj.MetaObj.cols = GMS_obj.arr.cols
GMS_obj.MetaObj.rows = GMS_obj.arr.rows
GMS_obj.MetaObj.bands = GMS_obj.arr.bands
GMS_obj.MetaObj.map_info = geotransform2mapinfo(GMS_obj.arr.gt, GMS_obj.arr.prj)
GMS_obj.MetaObj.projection = GMS_obj.arr.prj
# calculate data_corners_imXY (mask_nodata is always an array here because get_mapPos always returns an array)
corners_imYX = calc_FullDataset_corner_positions(
......@@ -1302,7 +1272,8 @@ class GMS_object(object):
# clip all array attributes using the given bounds
# list_arraynames = [i for i in self.__dict__ if not callable(getattr(self, i)) and \
# isinstance(getattr(self, i), np.ndarray)]
list_arraynames = [i for i in ['arr', 'masks', 'ac_errors', 'mask_clouds_confidence', 'spec_homo_errors']
list_arraynames = [i for i in ['arr', 'masks', 'ac_errors', 'mask_clouds_confidence', 'spec_homo_errors',
'accuracy_layers']
if hasattr(self, i) and getattr(self, i) is not None] # FIXME hardcoded
assert list_arraynames
assert imBounds or mapBounds, "Either 'imBounds' or 'mapBounds' must be given. Got nothing."
......@@ -1324,14 +1295,13 @@ class GMS_object(object):
for arrname in list_arraynames:
# get input data for array subsetting
meta2update = sub_GMS_obj.meta_odict if arrname == 'arr' else sub_GMS_obj.masks_meta
geoArr = getattr(self, arrname)
# get subsetted and (possibly) reprojected array
out_prj = out_prj if out_prj else geoArr.prj
rspAlg = 'near' if arrname == 'masks' else 'cubic'
subArr = GeoArray(*geoArr.get_mapPos((xmin, ymin, xmax, ymax), mapBounds_prj,
out_prj=out_prj, rspAlg=rspAlg, progress=progress),
out_prj=out_prj or geoArr.prj,
rspAlg='near' if arrname == 'masks' else 'cubic',
progress=progress),
bandnames=list(geoArr.bandnames), nodata=geoArr.nodata)
# show result
......@@ -1339,11 +1309,23 @@ class GMS_object(object):
subArr.show(figsize=(10, 10))
# update array-related attributes of sub_GMS_obj
meta2update['map info'] = geotransform2mapinfo(subArr.gt, subArr.prj)
meta2update['coordinate system string'] = subArr.prj
meta2update['lines'], meta2update['samples'] = subArr.arr.shape[:2]
meta2update['CS_UTM_ZONE'] = get_UTMzone(prj=subArr.prj) # FIXME only works for UTM
meta2update['CS_EPSG'] = WKT2EPSG(subArr.prj)
if arrname == 'arr':
sub_GMS_obj.MetaObj.map_info = geotransform2mapinfo(subArr.gt, subArr.prj)
sub_GMS_obj.MetaObj.projection = subArr.prj
sub_GMS_obj.MetaObj.rows, sub_GMS_obj.MetaObj.cols = subArr.arr.shape[:2]
sub_GMS_obj.MetaObj.CS_UTM_ZONE = get_UTMzone(prj=subArr.prj) # FIXME only works for UTM
sub_GMS_obj.MetaObj.CS_EPSG = WKT2EPSG(subArr.prj)
elif arrname == 'masks':
sub_GMS_obj.masks_meta['map info'] = geotransform2mapinfo(subArr.gt, subArr.prj)
sub_GMS_obj.masks_meta['coordinate system string'] = subArr.prj
sub_GMS_obj.masks_meta['lines'], sub_GMS_obj.masks_meta['samples'] = subArr.arr.shape[:2]
sub_GMS_obj.masks_meta['CS_UTM_ZONE'] = get_UTMzone(prj=subArr.prj) # FIXME only works for UTM
sub_GMS_obj.masks_meta['CS_EPSG'] = WKT2EPSG(subArr.prj)
else:
# other layers are either not written (i.e. have no separate meta)
# or their meta is directly derived from the corresponding array
pass
delattr(sub_GMS_obj,
arrname) # connected filePath must be disconnected because projection change will be rejected
setattr(sub_GMS_obj, arrname, subArr)
......@@ -1613,7 +1595,6 @@ class GMS_object(object):
outpath = os.path.join(self.ExtractedFolder, '%s__%s.%s' % (self.baseN, tiles[0]['desc'], self.outInterleave))
if CFG.target_radunit_optical in tiles[0]['desc'] or \
CFG.target_radunit_thermal in tiles[0]['desc']:
self.meta_odict = self.MetaObj.to_odict() # important in order to keep geotransform/projection
self.arr_desc = tiles[0]['desc']
self.arr = outpath
# self.arr = os.path.abspath('./testing/out/%s_TOA_Ref.bsq' % self.baseN)
......@@ -1629,8 +1610,8 @@ class GMS_object(object):
self.lonlat_arr = outpath
outpath = os.path.splitext(outpath)[0] + '.hdr' if not outpath.endswith('.hdr') else outpath
out_shape = self.shape_fullArr[:2] + ([tiles[0]['data'].shape[2]] if len(tiles[0]['data'].shape) == 3 else [1])
OUT_W.Tiles_Writer(tiles, outpath, out_shape, tiles[0]['data'].dtype, self.outInterleave, self.meta_odict,
overwrite=overwrite)
OUT_W.Tiles_Writer(tiles, outpath, out_shape, tiles[0]['data'].dtype, self.outInterleave,
self.MetaObj.to_odict(), overwrite=overwrite)
def to_tiles(self, blocksize=(2048, 2048)):
# type: (tuple) -> self
......@@ -1670,7 +1651,7 @@ class GMS_object(object):
tgt_corners_lonlat=self.trueDataCornerLonLat)
# calculate image coordinate bounds of the full GMS object for each MGRS tile within the GeoDataFrame
gt = mapinfo2geotransform(self.meta_odict['map info'])
gt = mapinfo2geotransform(self.MetaObj.map_info)
def get_arrBounds(MGRStileObj):
return list(np.array(MGRStileObj.poly_utm.buffer(pixbuffer * gt[1]).bounds)[[0, 2, 1, 3]])
......@@ -1734,10 +1715,7 @@ class GMS_object(object):
def to_GMS_file(self, path_gms_file=None):
self.close_loggers()
# make sure meta_odict is present
self.meta_odict = self.meta_odict
dict2write = self.attributes2dict(remove_privates=True)
dict2write = self.attributes2dict(remove_privates=True) # includes MetaObj as OrderedDict
dict2write['arr_shape'], dict2write['arr_pos'] = ['cube', None]
path_gms_file = path_gms_file if path_gms_file else self.pathGen.get_path_gmsfile()
......@@ -1746,16 +1724,17 @@ class GMS_object(object):
# so, wenn meta-dicts nicht ins gms-file sollen. ist aber vllt ni schlecht
# -> erlaubt lesen der metadaten direkt aus gms
if k == 'MetaObj':
continue # make sure MetaObj getter is not called -> would delete meta_odict
elif isinstance(v, datetime.datetime):
if isinstance(v, datetime.datetime):
dict2write[k] = v.strftime('%Y-%m-%d %H:%M:%S.%f%z')
elif isinstance(v, DatasetLogger):
if hasattr(v, 'handlers') and v.handlers[:]:
warnings.warn('Not properly closed logger at GMS_obj.logger pointing to %s.' % v.path_logfile)
dict2write[k] = 'not set'
elif isinstance(v, GMS_identifier):
dict2write[k] = v.to_odict(include_logger=False)
elif isinstance(v, collections.OrderedDict) or isinstance(v, dict):
dict2write[k] = dict2write[k].copy()
if 'logger' in v:
......@@ -1763,12 +1742,14 @@ class GMS_object(object):
warnings.warn("Not properly closed logger at %s['logger'] pointing to %s."
% (k, dict2write[k]['logger'].path_logfile))
dict2write[k]['logger'] = 'not set'
elif isinstance(v, np.ndarray):
# delete every 3D Array larger than 100x100
if len(v.shape) == 2 and sum(v.shape) <= 200:
dict2write[k] = v.tolist() # numpy arrays are not jsonable
else:
del dict2write[k]
elif hasattr(v, '__dict__'):
# löscht Instanzen von Objekten und Arrays, aber keine OrderedDicts
if hasattr(v, 'logger'):
......@@ -1828,7 +1809,7 @@ class GMS_object(object):
# set dicts
image_type_dict = dict(arr=self.image_type, masks='MAS', mask_clouds='MAC', accuracy_layers='AL')
metaAttr_dict = dict(arr='meta_odict', masks='masks_meta', mask_clouds='masks_meta',
metaAttr_dict = dict(arr='arr_meta', masks='masks_meta', mask_clouds='masks_meta',
accuracy_layers='accuracy_layers_meta')
out_dtype_dict = dict(arr='int16', masks='uint8', mask_clouds='uint8', accuracy_layers='int16')
print_dict = dict(
......
......@@ -189,6 +189,10 @@ class METADATA(object):
"""
return get_LayerBandsAssignment(self.GMS_identifier, no_thermal=False, no_pan=False, return_fullLBA=True)
@property
def bandnames(self):
return [('Band %s' % i) for i in self.LayerBandsAssignment]
def Read_SPOT_dimap2(self):
"""----METHOD_2------------------------------------------------------------
# read metadata from spot dimap file
......@@ -1622,7 +1626,7 @@ class METADATA(object):
elif odictKey == 'wavelength units':
Meta['wavelength units'] = "Nanometers"
elif odictKey == 'band names':
Meta['band names'] = [('Band %s' % i) for i in self.LayerBandsAssignment]
Meta['band names'] = self.bandnames
# add keys that will not be included into ENVI header
if self.ViewingAngle_arrProv is not None:
......
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