def test_astype(self): arr = from_shapely(self.geoms, crs=27700) df = GeoDataFrame({"col1": [0, 1]}, geometry=arr) df2 = df.astype({"col1": str}) assert df2.crs == self.osgb
def get_CoRegPoints_table(self): assert self.XY_points is not None and self.XY_mapPoints is not None # create a dataframe containing 'geometry','POINT_ID','X_IM','Y_IM','X_UTM','Y_UTM' # (convert imCoords to mapCoords XYarr2PointGeom = np.vectorize(lambda X, Y: Point(X, Y), otypes=[Point]) geomPoints = np.array(XYarr2PointGeom(self.XY_mapPoints[:, 0], self.XY_mapPoints[:, 1])) if isLocal(self.COREG_obj.shift.prj): crs = None elif isProjectedOrGeographic(self.COREG_obj.shift.prj) == 'geographic': crs = dict(ellps='WGS84', datum='WGS84', proj='longlat') elif isProjectedOrGeographic(self.COREG_obj.shift.prj) == 'projected': UTMzone = abs(get_UTMzone(prj=self.COREG_obj.shift.prj)) south = get_UTMzone(prj=self.COREG_obj.shift.prj) < 0 crs = dict(ellps='WGS84', datum='WGS84', proj='utm', zone=UTMzone, south=south, units='m', no_defs=True) if not south: del crs['south'] else: crs = None GDF = GeoDataFrame(index=range(len(geomPoints)), crs=crs, columns=['geometry', 'POINT_ID', 'X_IM', 'Y_IM', 'X_UTM', 'Y_UTM']) GDF['geometry'] = geomPoints GDF['POINT_ID'] = range(len(geomPoints)) GDF.loc[:, ['X_IM', 'Y_IM']] = self.XY_points GDF.loc[:, ['X_UTM', 'Y_UTM']] = self.XY_mapPoints # exclude offsite points and points on bad data mask GDF = self._exclude_bad_XYpos(GDF) if GDF.empty: self.CoRegPoints_table = GDF return self.CoRegPoints_table # choose a random subset of points if a maximum number has been given if self.max_points and len(GDF) > self.max_points: GDF = GDF.sample(self.max_points).copy() # equalize pixel grids in order to save warping time if len(GDF) > 100: # NOTE: actually grid res should be also changed here because self.shift.xgsd changes and grid res is # connected to that self.COREG_obj.equalize_pixGrids() # validate reference and target image inputs assert self.ref.footprint_poly # this also checks for mask_nodata and nodata value assert self.shift.footprint_poly # ensure the input arrays for CoReg are in memory -> otherwise the code will get stuck in multiprocessing if # neighboured matching windows overlap during reading from disk!! self.ref.cache_array_subset( [self.COREG_obj.ref.band4match]) # only sets geoArr._arr_cache; does not change number of bands self.shift.cache_array_subset([self.COREG_obj.shift.band4match]) # get all variations of kwargs for coregistration list_coreg_kwargs = (self._get_coreg_kwargs(i, self.XY_mapPoints[i]) for i in GDF.index) # generator # run co-registration for whole grid if self.CPUs is None or self.CPUs > 1: if not self.q: cpus = self.CPUs if self.CPUs is not None else multiprocessing.cpu_count() print("Calculating tie point grid (%s points) using %s CPU cores..." % (len(GDF), cpus)) with multiprocessing.Pool(self.CPUs, initializer=mp_initializer, initargs=(self.ref, self.shift)) as pool: if self.q or not self.progress: results = pool.map(self._get_spatial_shifts, list_coreg_kwargs) else: results = pool.map_async(self._get_spatial_shifts, list_coreg_kwargs, chunksize=1) bar = ProgressBar(prefix='\tprogress:') while True: time.sleep(.1) # this does not really represent the remaining tasks but the remaining chunks # -> thus chunksize=1 # noinspection PyProtectedMember numberDone = len(GDF) - results._number_left if self.progress: bar.print_progress(percent=numberDone / len(GDF) * 100) if results.ready(): # <= this is the line where multiprocessing can freeze if an exception appears within # COREG ans is not raised results = results.get() break else: # declare global variables needed for self._get_spatial_shifts() global global_shared_imref, global_shared_im2shift global_shared_imref = self.ref global_shared_im2shift = self.shift if not self.q: print("Calculating tie point grid (%s points) on 1 CPU core..." % len(GDF)) results = np.empty((len(geomPoints), 14), np.object) bar = ProgressBar(prefix='\tprogress:') for i, coreg_kwargs in enumerate(list_coreg_kwargs): if self.progress: bar.print_progress((i + 1) / len(GDF) * 100) results[i, :] = self._get_spatial_shifts(coreg_kwargs) # merge results with GDF # NOTE: We use a pandas.DataFrame here because the geometry column is missing. # GDF.astype(...) fails with geopandas>0.6.0 if the geometry columns is missing. records = DataFrame(results, columns=['POINT_ID', 'X_WIN_SIZE', 'Y_WIN_SIZE', 'X_SHIFT_PX', 'Y_SHIFT_PX', 'X_SHIFT_M', 'Y_SHIFT_M', 'ABS_SHIFT', 'ANGLE', 'SSIM_BEFORE', 'SSIM_AFTER', 'SSIM_IMPROVED', 'RELIABILITY', 'LAST_ERR']) # merge DataFrames (dtype must be equal to records.dtypes; We need np.object due to None values) GDF = GDF.astype(np.object).merge(records.astype(np.object), on='POINT_ID', how="inner") GDF = GDF.replace([np.nan, None], int(self.outFillVal)) # fillna fails with geopandas==0.6.0 GDF.crs = crs # gets lost when using GDF.astype(np.object), so we have to reassign that if not self.q: print("Found %s matches." % len(GDF[GDF.LAST_ERR == int(self.outFillVal)])) # filter tie points according to given filter level if self.tieP_filter_level > 0: if not self.q: print('Performing validity checks...') TPR = Tie_Point_Refiner(GDF[GDF.ABS_SHIFT != self.outFillVal], **self.outlDetect_settings) GDF_filt, new_columns = TPR.run_filtering(level=self.tieP_filter_level) GDF = GDF.merge(GDF_filt[['POINT_ID'] + new_columns], on='POINT_ID', how="outer") GDF = GDF.replace([np.nan, None], int(self.outFillVal)) # fillna fails with geopandas==0.6.0 self.CoRegPoints_table = GDF if not self.q: if GDF.empty: warnings.warn('No valid GCPs could by identified.') else: if self.tieP_filter_level > 0: print("%d valid tie points remain after filtering." % len(GDF[GDF.OUTLIER.__eq__(False)])) return self.CoRegPoints_table