"""Mixin that implements adding/dropping rasters."""from__future__importannotationsimportloggingfromtypingimportTYPE_CHECKING,SequenceimportpandasaspdfromgeopandasimportGeoDataFramefromgeographer.utils.connector_utilsimport_check_df_cols_agreefromgeographer.utils.utilsimportconcat_gdfs,deepcopy_gdfifTYPE_CHECKING:fromgeographer.label_makers.label_maker_baseimportLabelMakerlog=logging.getLogger(__name__)
[docs]classAddDropRastersMixIn:"""Mix-in that implements methods to add and drop rasters."""
[docs]defadd_to_rasters(self,new_rasters:GeoDataFrame,label_maker:LabelMaker|None=None):"""Add rasters to connector's ``rasters`` attribute. Adds the new_rasters to the connector's :ref:`rasters` keeping track of which (vector) geometries are contained in which rasters. Args: new_rasters: GeoDataFrame of raster information conforming to the connector's rasters format label_maker: If given generate labels for new rasters. """new_rasters=deepcopy_gdf(new_rasters)# don't want to modify argumentduplicates=new_rasters[new_rasters.index.duplicated()]iflen(duplicates)>0:raiseValueError("new_rasters contains rows with duplicate raster_names: "f"{duplicates.index.tolist()}")rasters_names_in_both=list(set(new_rasters.index)&set(self.rasters.index))ifrasters_names_in_both:raster_names_in_both_str=", ".join(rasters_names_in_both)raiseValueError("conflict: already have entries for rasters "f"{raster_names_in_both_str}")ifnew_rasters.geometry.isna().any():rasters_with_null_geoms:str=", ".join(new_rasters[new_rasters.geometry.isna()].index)raiseValueError("new_rasters contains rows with None geometries: "f"{rasters_with_null_geoms}")self._check_required_df_cols_exist(df=new_rasters,df_name="new_rasters",mode="rasters")new_rasters=self._get_df_in_crs(df=new_rasters,df_name="new_rasters",crs_epsg_code=self.crs_epsg_code,)_check_df_cols_agree(df=new_rasters,df_name="new_rasters",self_df=self.rasters,self_df_name="self.rasters",)# go through all new rasters...forraster_nameinnew_rasters.index:# add new raster vertex to the graph, add all connections# to existing rasters, and modify self.vectors 'raster_count' valueraster_bounding_rectangle=new_rasters.loc[raster_name,"geometry"]self._add_raster_to_graph_modify_vectors(raster_name,raster_bounding_rectangle=raster_bounding_rectangle)# append new_rastersself.rasters=concat_gdfs([self.rasters,new_rasters])# self.rasters = self.rasters.convert_dtypes()iflabel_makerisnotNone:label_maker.make_labels(connector=self,raster_names=new_rasters.index.tolist())
[docs]defdrop_rasters(self,raster_names:Sequence[str],remove_rasters_from_disk:bool=True,label_maker:LabelMaker|None=None,):"""Drop rasters from ``rasters`` and from dataset. Remove rows from the connector's rasters, delete the corresponding vertices in the graph, and delete the raster from disk (unless remove_rasters_from_disk is set to False). Args: raster_names: raster_names/ids of rasters to be dropped. remove_rasters_from_disk: If true, delete rasters and labels from disk (if they exist). Defaults to True. label_maker: If given, will use label_makers delete_labels method. Defaults to None. """# make sure we don't interpret a string as a list of characters# in the iteration below:ifisinstance(raster_names,str):raster_names=[raster_names]assertpd.api.types.is_list_like(raster_names)# drop row from self.rastersself.rasters.drop(raster_names,inplace=True)# remove all vertices from graph and modify vectors if necessaryforraster_nameinraster_names:self._remove_raster_from_graph_modify_vectors(raster_name)# remove rasters and labels from diskifremove_rasters_from_disk:iflabel_makerisnotNone:label_maker.delete_labels(self,raster_names)fordir_inself.raster_data_dirs:forraster_nameinraster_names:(dir_/raster_name).unlink(missing_ok=True)