Commit a18134d5 authored by Daniel Scheffler's avatar Daniel Scheffler
Browse files

Input BadDataMask with unexpected values is now rejected; fixed some bugs

components.CoReg:
- GeoArray_CoReg
    - added type hint
    - mask_baddata is now set to an instance of BadDataMask -> input BadDataMask with unexpected values is now rejected
- COREG:
    - revised _get_image_windows_to_match()

components.CoReg_local.COREG_LOCAL:
- __init__(): updated docstring

components.DeShifter.DESHIFTER:
- __init__(): bugfix for not available 'original map info'
- correct_shifts(): added type hint; bugfix for wrong no-warping-condition
- added float tolerance to output validation

- updated __version__
parent 13c71a5c
......@@ -9,7 +9,7 @@ from .components import utilities
from .components import geometry
__author__ = 'Daniel Scheffler'
__version__= '2017-01-19_01'
__version__= '2017-01-19_02'
__all__=['COREG',
'COREG_LOCAL',
......
......@@ -28,7 +28,7 @@ from . import geometry as GEO
from . import io as IO
from . import plotting as PLT
from py_tools_ds.ptds import GeoArray
from py_tools_ds.ptds.io.raster.GeoArray import GeoArray, BadDataMask
from py_tools_ds.ptds.geo.coord_calc import corner_coord_to_minmax, get_corner_coordinates
from py_tools_ds.ptds.geo.vector.topology import get_overlap_polygon, get_smallest_boxImYX_that_contains_boxMapYX
from py_tools_ds.ptds.geo.projection import prj_equal, get_proj4info
......@@ -45,6 +45,8 @@ from py_tools_ds.ptds.similarity.raster import calc_ssim
class GeoArray_CoReg(GeoArray):
def __init__(self, CoReg_params, imID):
# type: (dict, str) -> None
assert imID in ['ref', 'shift']
# run GeoArray init
......@@ -103,7 +105,7 @@ class GeoArray_CoReg(GeoArray):
# add bad data mask
given_mask = CoReg_params['mask_baddata_%s' % ('ref' if imID == 'ref' else 'tgt')]
if given_mask:
self.mask_baddata = given_mask
self.mask_baddata = BadDataMask(given_mask)
......@@ -653,26 +655,26 @@ class COREG(object):
match_fullGeoArr = self.ref if self.grid2use=='ref' else self.shift
other_fullGeoArr = self.shift if self.grid2use=='ref' else self.ref
self.matchWin = GeoArray(np.array([]), copy(match_fullGeoArr.gt), copy(match_fullGeoArr.prj),
nodata=copy(match_fullGeoArr.nodata)) # array data is overwritten later
self.otherWin = GeoArray(np.array([]), copy(other_fullGeoArr.gt), copy(other_fullGeoArr.prj),
nodata=copy(other_fullGeoArr.nodata)) # array data is overwritten later
self.matchWin.imID = match_fullGeoArr.imID
self.otherWin.imID = other_fullGeoArr.imID
# matchWin per subset-read einlesen -> self.matchWin.data
rS, rE, cS, cE = GEO.get_GeoArrayPosition_from_boxImYX(self.matchBox.boxImYX)
assert np.array_equal(np.abs(np.array([rS,rE,cS,cE])), np.array([rS,rE,cS,cE])), \
'Got negative values in gdalReadInputs for %s.' %match_fullGeoArr.imName
self.matchWin.arr = match_fullGeoArr[rS:rE,cS:cE, match_fullGeoArr.band4match]
self.matchWin.gt = GEO.get_subset_GeoTransform(match_fullGeoArr.gt, self.matchBox.boxImYX)
self.matchWin = GeoArray(match_fullGeoArr[rS:rE,cS:cE, match_fullGeoArr.band4match],
geotransform = GEO.get_subset_GeoTransform(match_fullGeoArr.gt, self.matchBox.boxImYX),
projection = copy(match_fullGeoArr.prj),
nodata = copy(match_fullGeoArr.nodata))
self.matchWin.imID = match_fullGeoArr.imID
# otherWin per subset-read einlesen
rS, rE, cS, cE = GEO.get_GeoArrayPosition_from_boxImYX(self.otherBox.boxImYX)
assert np.array_equal(np.abs(np.array([rS,rE,cS,cE])), np.array([rS,rE,cS,cE])), \
'Got negative values in gdalReadInputs for %s.' %other_fullGeoArr.imName
self.otherWin.arr = other_fullGeoArr[rS:rE, cS:cE, other_fullGeoArr.band4match]
self.otherWin.gt = GEO.get_subset_GeoTransform(other_fullGeoArr.gt, self.otherBox.boxImYX)
self.otherWin = GeoArray(other_fullGeoArr[rS:rE, cS:cE, other_fullGeoArr.band4match],
geotransform = GEO.get_subset_GeoTransform(other_fullGeoArr.gt, self.otherBox.boxImYX),
projection = copy(other_fullGeoArr.prj),
nodata = copy(other_fullGeoArr.nodata))
self.otherWin.imID = other_fullGeoArr.imID
#self.matchWin.deepcopy_array()
#self.otherWin.deepcopy_array()
......
......@@ -107,18 +107,20 @@ class COREG_LOCAL(object):
matching window position within the actual image overlap
(default: True; deactivated if 'data_corners_im0' and 'data_corners_im1' are given
:param binary_ws(bool): use binary X/Y dimensions for the matching window (default: True)
:param mask_baddata_ref(str, GeoArray): path to a 2D boolean mask file (or an instance of GeoArray) for the
reference image where all bad data pixels (e.g. clouds) are marked with
True and the remaining pixels with False. Must have the same geographic
extent and projection like 'im_ref'. The mask is used to check if the
chosen matching window position is valid in the sense of useful data.
Otherwise this window position is rejected.
:param mask_baddata_tgt(str, GeoArray): path to a 2D boolean mask file (or an instance of GeoArray) for the
image to be shifted where all bad data pixels (e.g. clouds) are marked
with True and the remaining pixels with False. Must have the same
geographic extent and projection like 'im_ref'. The mask is used to
check if the chosen matching window position is valid in the sense of
useful data. Otherwise this window position is rejected.
:param mask_baddata_ref(str, BadDataMask):
path to a 2D boolean mask file (or an instance of BadDataMask) for the
reference image where all bad data pixels (e.g. clouds) are marked with
True and the remaining pixels with False. Must have the same geographic
extent and projection like 'im_ref'. The mask is used to check if the
chosen matching window position is valid in the sense of useful data.
Otherwise this window position is rejected.
:param mask_baddata_tgt(str, BadDataMask):
path to a 2D boolean mask file (or an instance of BadDataMask) for the
image to be shifted where all bad data pixels (e.g. clouds) are marked
with True and the remaining pixels with False. Must have the same
geographic extent and projection like 'im_ref'. The mask is used to
check if the chosen matching window position is valid in the sense of
useful data. Otherwise this window position is rejected.
:param CPUs(int): number of CPUs to use during calculation of geometric quality grid
(default: None, which means 'all CPUs available')
:param progress(bool): show progress bars (default: True)
......
......@@ -101,7 +101,7 @@ class DESHIFTER(object):
mapI = coreg_results['updated map info']
self.updated_map_info = mapI if mapI else geotransform2mapinfo(self.shift_gt, self.shift_prj)
self.updated_gt = mapinfo2geotransform(self.updated_map_info) if mapI else self.shift_gt
self.original_map_info = coreg_results['original map info']
self.original_map_info = coreg_results['original map info'] # only exists in global de-shifting # FIXME WHY?
self.updated_projection = self.ref_prj
self.out_grid = self._get_out_grid() # needs self.ref_grid, self.im2shift
......@@ -207,7 +207,7 @@ class DESHIFTER(object):
def correct_shifts(self):
# type: () -> collections.OrderedDict
#type: () -> collections.OrderedDict
if not self.q:
print('Correcting geometric shifts...')
......@@ -215,7 +215,7 @@ class DESHIFTER(object):
t_start = time.time()
equal_prj = prj_equal(self.ref_prj,self.shift_prj)
if equal_prj and not self.GCPList and is_coord_grid_equal(self.shift_gt, *self.out_grid):
if equal_prj and not self.GCPList and is_coord_grid_equal(self.updated_gt, *self.out_grid):
"""NO RESAMPLING NEEDED"""
self.is_shifted = True
......@@ -229,8 +229,11 @@ class DESHIFTER(object):
# clip with target extent
# NOTE: get_mapPos() does not perform any resampling as long as source and target projection are equal
self.arr_shifted, self.updated_gt, self.updated_projection = \
shifted_geoArr.get_mapPos((xmin,ymin,xmax,ymax), self.shift_prj, fillVal=self.nodata,
band2get=self.band2process)
shifted_geoArr.get_mapPos((xmin,ymin,xmax,ymax),
self.shift_prj,
fillVal = self.nodata,
band2get = self.band2process)
self.updated_map_info = geotransform2mapinfo(self.updated_gt, self.updated_projection)
else:
......@@ -287,7 +290,7 @@ class DESHIFTER(object):
# # TO DO implement output writer
# FIXME avoid reading the whole band if clip_extent is passed
#print('warping')
in_arr = self.im2shift[:,:,self.band2process] if self.band2process is not None and self.im2shift.ndim==3\
else self.im2shift[:]
......@@ -302,7 +305,7 @@ class DESHIFTER(object):
in_nodata = self.nodata,
out_nodata = self.nodata,
out_gsd = self.out_gsd,
out_bounds = self._get_out_extent(),
out_bounds = self._get_out_extent(), # always returns an extent snapped to the target grid
gcpList = self.GCPList,
#polynomialOrder = str(3),
#options = '-refine_gcps 500 1.9',
......@@ -329,7 +332,7 @@ class DESHIFTER(object):
out_geoArr.save(self.path_out,fmt=self.fmt_out, creationOptions=self.out_creaOpt)
# validation
if not is_coord_grid_equal(self.updated_gt, *self.out_grid):
if not is_coord_grid_equal(self.updated_gt, *self.out_grid, tolerance=1.e8):
raise RuntimeError('DESHIFTER output dataset has not the desired target pixel grid. Target grid '
'was %s. Output geotransform is %s.' % (str(self.out_grid), str(self.updated_gt)))
# TODO to be continued (extent, map info, ...)
......
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