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

some bugfixes; added multiple docstrings; updated __version__

- coreg_info: bugfix for recalculating spatial shifts although they are already there

- CoRegPoints_table(): added docstring
- show_image_footprints(): added docstring

- bugfix for not properly setting nodata value
- correct_shifts(): bugfix for not passing nodata value when saving GeoArray

- CoRegPoints_table: added docstring
- GCPList: added docstring
- _get_imXY__mapXY_points(): added print output
- get_CoRegPoints_table(): updated progress bar calls
- to_PointShapefile(): reordered keywords; added docstring

- updated __version__
parent 40099a19
......@@ -9,7 +9,7 @@ from .components import utilities
from .components import geometry
__author__ = 'Daniel Scheffler'
__version__= '2016-11-08_01'
__version__= '2016-11-08_02'
......@@ -941,7 +941,8 @@ class COREG(object):
if self._coreg_info:
return self._coreg_info
if self.success is None:
self._coreg_info = {
'corrected_shifts_px' : {'x':self.x_shift_px, 'y':self.y_shift_px },
'corrected_shifts_map' : {'x':self.x_shift_map, 'y':self.y_shift_map},
......@@ -147,7 +147,7 @@ class COREG_LOCAL(object):
# return a project name that not already has a corresponding folder on disk
projectDir = os.path.join(os.path.dirname(self.im2shift.filePath), 'UntitledProject_1')
while os.path.isdir(projectDir):
projectDir = '%s_%s' % (projectDir.split('_')[0], int(projectDir.split('_')[1]) + 1)
projectDir = '%s_%s' % (projectDir.split('_')[0], int(projectDir.split('_')[-1]) + 1)
self._projectDir = projectDir
return self._projectDir
......@@ -167,6 +167,10 @@ class COREG_LOCAL(object):
def CoRegPoints_table(self):
"""Returns a GeoDataFrame with the columns 'geometry','POINT_ID','X_IM','Y_IM','X_UTM','Y_UTM','X_WIN_SIZE',
'Y_WIN_SIZE','X_SHIFT_PX','Y_SHIFT_PX', 'X_SHIFT_M', 'Y_SHIFT_M', 'ABS_SHIFT' and 'ANGLE' containing all
information containing all the results frm coregistration for all points in the geometric quality grid.
return self.quality_grid.CoRegPoints_table
......@@ -178,6 +182,12 @@ class COREG_LOCAL(object):
return self._success
def show_image_footprints(self):
"""This method is intended to be called from Jupyter Notebook and shows a web map containing the calculated
footprints of the input images as well as the corresponding overlap area."""
return self.COREG_obj.show_image_footprints()
def view_CoRegPoints(self, attribute2plot='ABS_SHIFT', cmap=None, exclude_fillVals=True, backgroundIm='tgt',
figsize=None, savefigPath='', savefigDPI=96):
"""Shows a map of the calculated quality grid with the target image as background.
......@@ -71,7 +71,7 @@ class DESHIFTER(object):
self.path_out = kwargs.get('path_out' , None)
self.fmt_out = kwargs.get('fmt_out' , 'ENVI')
self.band2process = kwargs.get('band2process', None) # starts with 1 # FIXME warum?
self.nodata = kwargs.get('nodata' , None) # FIXME can be replaced by self.im2shift.nodata
self.nodata = kwargs.get('nodata' , self.im2shift.nodata)
self.align_grids = kwargs.get('align_grids' , False)
self.rspAlg = kwargs.get('resamp_alg' , 'cubic')
self.cliptoextent = kwargs.get('cliptoextent', True)
......@@ -81,7 +81,7 @@ class DESHIFTER(object):
self.q = kwargs.get('q' , False) if not self.v else False # overridden by v
self.progress = kwargs.get('progress' , True) if not self.q else False # overridden by q
self.im2shift.nodata = self.nodata
self.im2shift.nodata = kwargs.get('nodata', self.im2shift.nodata)
self.im2shift.q = self.q
self.shift_prj = self.im2shift.projection
self.shift_gt = list(self.im2shift.geotransform)
......@@ -172,7 +172,7 @@ class DESHIFTER(object):
def _get_out_extent(self):
if self.cliptoextent and self.clipextent is None:
self.clipextent = self.im2shift.footprint_poly.envelope.bounds # FIXME
self.clipextent = self.im2shift.footprint_poly.envelope.bounds
xmin, xmax, ymin, ymax =
self.clipextent = xmin, ymin, xmax, ymax
......@@ -301,7 +301,9 @@ class DESHIFTER(object):
self.is_resampled = True
if self.path_out:
GeoArray(out_arr, out_gt, out_prj).save(self.path_out,fmt=self.fmt_out)
out_geoArr = GeoArray(out_arr, out_gt, out_prj, q=self.q)
out_geoArr.nodata = self.nodata # equals self.im2shift.nodata after __init__(),fmt=self.fmt_out)
if self.v: print('Time for shift correction: %.2fs' %(time.time()-t_start))
return self.deshift_results
......@@ -22,7 +22,7 @@ from .CoReg import COREG
from . import io as IO
from py_tools_ds.ptds.geo.projection import isProjectedOrGeographic, get_UTMzone
from import get_generic_outpath
from py_tools_ds.ptds.processing.progress_mon import printProgress
from py_tools_ds.ptds.processing.progress_mon import ProgressBar
......@@ -75,6 +75,10 @@ class Geom_Quality_Grid(object):
def CoRegPoints_table(self):
"""Returns a GeoDataFrame with the columns 'geometry','POINT_ID','X_IM','Y_IM','X_UTM','Y_UTM','X_WIN_SIZE',
'Y_WIN_SIZE','X_SHIFT_PX','Y_SHIFT_PX', 'X_SHIFT_M', 'Y_SHIFT_M', 'ABS_SHIFT' and 'ANGLE' containing all
information containing all the results frm coregistration for all points in the geometric quality grid.
if self._CoRegPoints_table is not None:
return self._CoRegPoints_table
......@@ -89,6 +93,8 @@ class Geom_Quality_Grid(object):
def GCPList(self):
"""Returns a list of GDAL compatible GCP objects.
if self._GCPList:
return self._GCPList
......@@ -102,6 +108,9 @@ class Geom_Quality_Grid(object):
def _get_imXY__mapXY_points(self, grid_res):
if not self.q:
print('Initializing geometric quality grid...')
Xarr,Yarr = np.meshgrid(np.arange(0,self.shift.shape[1],grid_res),
......@@ -182,12 +191,12 @@ class Geom_Quality_Grid(object):
assert not GDF.empty, 'No coregistration point could be placed within the overlap area. Check yout input data!' # FIXME track that
#not_within_nodata = \
# lambda r: np.array(self.ref[r.Y_IM,r.X_IM,self.COREG_obj.ref.band4match]!=self.COREG_obj.ref.nodata and \
# self.shift[r.Y_IM,r.X_IM, self.COREG_obj.shift.band4match] != self.COREG_obj.shift.nodata)[0,0]
#not_within_nodata = \
# lambda r: np.array(self.ref[r.Y_IM,r.X_IM,self.COREG_obj.ref.band4match]!=self.COREG_obj.ref.nodata and \
# self.shift[r.Y_IM,r.X_IM, self.COREG_obj.shift.band4match] != self.COREG_obj.shift.nodata)[0,0]
#GDF['not_within_nodata'] = GDF.apply(lambda GDF_row: not_within_nodata(GDF_row),axis=1)
#GDF = GDF[GDF.not_within_nodata]
#GDF['not_within_nodata'] = GDF.apply(lambda GDF_row: not_within_nodata(GDF_row),axis=1)
#GDF = GDF[GDF.not_within_nodata]
# declare global variables needed for self._get_spatial_shifts()
global global_shared_imref,global_shared_im2shift
......@@ -228,12 +237,12 @@ class Geom_Quality_Grid(object):
results =, list_coreg_kwargs)
results = pool.map_async(self._get_spatial_shifts, list_coreg_kwargs, chunksize=1)
bar = ProgressBar(prefix='\tprogress:')
while True:
numberDone = len(GDF)-results._number_left # this does not really represent the remaining tasks but the remaining chunks -> thus chunksize=1
printProgress(percent=numberDone/len(GDF)*100, barLength=50, prefix='\tprogress:',
suffix='[%s/%s] Complete %.2f sek'%(numberDone,len(GDF), time.time()-t0))
if self.progress:
if results.ready():
results = results.get() # FIXME in some cases the code hangs here ==> x
......@@ -241,10 +250,10 @@ class Geom_Quality_Grid(object):
if not self.q:
print("Calculating geometric quality grid (%s points) in mode 'singleprocessing'..." %len(GDF))
results = np.empty((len(geomPoints),9))
bar = ProgressBar(prefix='\tprogress:')
for i,coreg_kwargs in enumerate(list_coreg_kwargs):
if not self.q:
printProgress(percent=(i+1)/len(GDF)*100, prefix='\tprogress:',
suffix='[%s/%s] Complete'%((i+1),len(GDF)), decimals=1, barLength=50)
if self.progress:
results[i,:] = self._get_spatial_shifts(coreg_kwargs)
# FIXME in some cases the code hangs here ==> x
......@@ -313,7 +322,16 @@ class Geom_Quality_Grid(object):
return lines
def to_PointShapefile(self, skip_nodata=1, skip_nodata_col ='ABS_SHIFT', path_out=None):
def to_PointShapefile(self, path_out=None, skip_nodata=True, skip_nodata_col ='ABS_SHIFT'):
# type: (str, bool, str)
"""Writes the calculated geometric quality grid to a point shapefile containing
Geom_Quality_Grid.CoRegPoints_table as attribute table. This shapefile can easily be displayed using GIS software.
:param path_out: <str> the output path. If not given, it is automatically defined.
:param skip_nodata: <bool> whether to skip all points where no valid match could be found
:param skip_nodata_col: <str> determines which column of Geom_Quality_Grid.CoRegPoints_table is used to
identify points where no valid match could be found
GDF = self.CoRegPoints_table
GDF2pass = GDF if not skip_nodata else GDF[GDF[skip_nodata_col]!=self.outFillVal]
......@@ -325,7 +343,7 @@ class Geom_Quality_Grid(object):
def _to_PointShapefile(self, skip_nodata=1, skip_nodata_col ='ABS_SHIFT'):
def _to_PointShapefile(self, skip_nodata=True, skip_nodata_col ='ABS_SHIFT'):
warnings.warn(DeprecationWarning("'_quality_grid_to_PointShapefile' is deprecated." # TODO delete if other method validated
" 'quality_grid_to_PointShapefile' is much faster."))
GDF = self.CoRegPoints_table
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