Source code for geographer.cutters.single_raster_cutter_grid
"""SingleRasterCutter that cuts a raster to a grid of rasters."""from__future__importannotationsimportloggingfrompathlibimportPathfromtypingimportAnyimportrasterioasriofromaffineimportAffinefrompydanticimportfield_validatorfromrasterio.windowsimportWindowfromgeographer.connectorimportConnectorfromgeographer.cutters.single_raster_cutter_baseimportSingleRasterCutterfromgeographer.cutters.type_aliasesimportRasterSizelogger=logging.getLogger(__name__)
[docs]classSingleRasterCutterToGrid(SingleRasterCutter):"""SingleRasterCutter that cuts a raster into a grid of rasters."""new_raster_size:RasterSize@field_validator("new_raster_size")defnew_raster_size_type_correctness(cls,value:RasterSize)->RasterSize:"""Validate new_raster_size has correct type."""is_int:bool=isinstance(value,int)is_pair_of_ints:bool=(isinstance(value,tuple)andlen(value)==2andall(isinstance(entry,int)forentryinvalue))ifnot(is_intoris_pair_of_ints):raiseTypeError("new_raster_size needs to be an integer or a pair of integers!")returnvalue@field_validator("new_raster_size")defnew_raster_size_side_lengths_must_be_positive(cls,value:RasterSize)->RasterSize:"""Validate new_raster_size side lengths are positive."""ifisinstance(value,tuple)andnotall(val>0forvalinvalue):logger.error("new_raster_size: need positive side length(s)")raiseValueError("new_raster_size: need positive side length(s)")elifisinstance(value,int)andvalue<=0:logger.error("new_raster_size: need positive side length(s)")raiseValueError("new_raster_size: need positive side length(s)")returnvalue@propertydefnew_raster_size_rows(self)->int:"""Return number of rows of new raster size."""ifisinstance(self.new_raster_size,tuple):returnself.new_raster_size[0]else:returnself.new_raster_size@propertydefnew_raster_size_cols(self)->int:"""Return number of columns of new raster size."""ifisinstance(self.new_raster_size,tuple):returnself.new_raster_size[1]else:returnself.new_raster_sizedef_get_windows_transforms_raster_names(self,source_raster_name:str,source_connector:Connector,target_connector:Connector|None=None,new_rasters_dict:dict|None=None,**kwargs:Any,)->list[tuple[Window,Affine,str]]:source_raster_path=source_connector.rasters_dir/source_raster_namewithrio.open(source_raster_path)assrc:ifnotsrc.height%self.new_raster_size_rows==0:logger.warning("number of rows in source raster not divisible by ""number of rows in new rasters")ifnotsrc.width%self.new_raster_size_cols==0:logger.warning("number of columns in source raster not divisible \ by number of columns in new rasters")windows_transforms_raster_names=[]# Iterate through grid ...foriinrange(src.width//self.new_raster_size_cols):forjinrange(src.height//self.new_raster_size_rows):# ... remember windows, ...window=Window(i*self.new_raster_size_cols,j*self.new_raster_size_rows,width=self.new_raster_size_cols,height=self.new_raster_size_rows,)# ... transforms ...window_transform=src.window_transform(window)# ... and raster names.new_raster_name=f"{Path(source_raster_name).stem}_{j}_{i}.tif"windows_transforms_raster_names.append((window,window_transform,new_raster_name))returnwindows_transforms_raster_names