def testUsingSmallGrid(self): """ Test using a small 5 by 5 grid Same data was used in FRUIT unit testing """ input_fine_river_directions_test_field = field.makeField(self.input_fine_river_directions_test_data, field_type='RiverDirections', grid_type='LatLong',nlat=15,nlong=15) input_fine_total_cumulative_flow_test_field = field.makeField(self.input_fine_total_cumulative_flow_test_data, field_type='CumulativeFlow', grid_type='LatLong',nlat=15,nlong=15) cotat_params_text =\ """ &cotat_parameters MUFP = 1.5 area_threshold = 9 run_check_for_sinks = .True. / """ with open(self.cotat_params_file_path,'w') as f: f.write(textwrap.dedent(cotat_params_text)) output_coarse_river_directions = \ cotat_plus_driver.run_cotat_plus(fine_rdirs_field=input_fine_river_directions_test_field, fine_total_cumulative_flow_field=\ input_fine_total_cumulative_flow_test_field, cotat_plus_parameters_filepath=self.cotat_params_file_path, coarse_grid_type='LatLong',nlat=5,nlong=5) np.testing.assert_array_equal(output_coarse_river_directions.get_data(), self.small_grid_expected_result, "Running scaling code over small 5 by 5 grid doesn't" " produce expected results")
def load_field(filename,file_type,field_type,unmask=True,timeslice=None, fieldname=None,check_for_grid_info=False,grid_type='HD',**grid_kwargs): """Inteface that loads a field as a raw array of data and returns it as a field object. Arguments: filename: string; the full path to the file to opened file_type: string; the code for this file type field_type: string; the code for this field type unmask (optional): boolean; flag to specifying whether the field is returned with any mask removed (True) or not (False) timeslice: integer; which timeslice to select from a (netCDF4) file with multiple time slices fieldname: string; which field to select from a (netCDF4) file with multiple fields check_for_grid_info: boolean; Search to see if file has grid info and use this to replace grid type specified if found grid_type: string; the code for this grid type **grid_kwargs: dictionary; key word arguments specifying parameters of the grid Returns: A field of object or an object of a field subclass Uses the getFileHelper pseudo-factory function to get the appropriate IOHelper subclass to load this file type and then uses this to loads the file; passing in any grid_kwargs supplied. Uses makeField factory function to create a field of the requested type with the loaded data and returns this object. Use a list to retrieve any grid information found by the loading function and add it to the field. """ grid_info=[] raw_field = iohelper.getFileHelper(file_type).load_field(filename,unmask,timeslice,fieldname, check_for_grid_info,grid_info, grid_type,**grid_kwargs) if len(grid_info) == 0: return fld.makeField(raw_field,field_type,grid_type,**grid_kwargs) else: return fld.makeField(raw_field,field_type,grid_info[0])
def run_cotat_plus(fine_rdirs_field,fine_total_cumulative_flow_field,cotat_plus_parameters_filepath, coarse_grid_type,**coarse_grid_kwargs): """Run the cotat plus fortran code using f2py for a lat-lon field Arguments: fine_rdirs_field: 2d ndarray; the fine river directions to be upscaled in 1-9 keypad format fine_total_cumulative_flow_field: 2d ndarray; the fine total cumulative flow (created from the fine_rdirs_field) to be used in upscaling cotat_plus_parameter_filepath: string; the file path containing the namelist with the parameters for the cotat plus upscaling algorithm coarse_grid_type: string; code for the coarse grid type to be upscaled to **coarse_grid_kwargs(optional): keyword dictionary; the parameter of the coarse grid to upscale to (if required) Return: 2d ndarray; the upscaled river direction on the coarse grid Compiles and runs the COTAT plus algorithm in Fortran using f2py for a lat-lon field """ additional_fortran_filenames = ["base/area_mod.o", "base/coords_mod.o", "algorithms/cotat_parameters_mod.o", "algorithms/cotat_plus.o", "base/doubly_linked_list_mod.o", "base/doubly_linked_list_link_mod.o", "base/field_section_mod.o", "base/precision_mod.o", "base/subfield_mod.o", "algorithms/map_non_coincident_grids_mod.o", "base/unstructured_grid_mod.o"] additional_fortran_filepaths = [path.join(fortran_project_object_path,filename) for filename in\ additional_fortran_filenames] f2py_mngr = f2py_manager.f2py_manager(path.join(fortran_project_source_path, "drivers", "cotat_plus_driver_mod.f90"), func_name="cotat_plus_latlon_f2py_wrapper", additional_fortran_files=additional_fortran_filepaths, include_path=fortran_project_include_path) coarse_grid = grid.makeGrid(coarse_grid_type,**coarse_grid_kwargs) if using_mpi(): comm = MPI.COMM_WORLD comm.bcast(MPICommands.RUNCOTATPLUS, root=0) coarse_rdirs_field_raw = f2py_mngr.\ run_current_function_or_subroutine(fine_rdirs_field.get_data().astype(np.int64,order='F'), fine_total_cumulative_flow_field.get_data().astype(np.int64,order='F'), cotat_plus_parameters_filepath, coarse_grid.get_grid_dimensions()[0], coarse_grid.get_grid_dimensions()[1]) coarse_rdirs_field = field.makeField(coarse_rdirs_field_raw.astype(np.float64),'RiverDirections',coarse_grid_type, **coarse_grid_kwargs) if fine_rdirs_field.grid_has_coordinates(): nlat_fine,nlon_fine = fine_rdirs_field.get_grid_dimensions() lat_pts_fine,lon_pts_fine = fine_rdirs_field.get_grid_coordinates() nlat_coarse,nlon_coarse = coarse_grid.get_grid_dimensions() lat_pts_coarse,lon_pts_coarse = \ coordinate_scaling_utilities.generate_coarse_pts(nlat_fine,nlon_fine, lat_pts_fine,lon_pts_fine, nlat_coarse,nlon_coarse) coarse_rdirs_field.set_grid_coordinates([lat_pts_coarse,lon_pts_coarse]) return coarse_rdirs_field
def follow_streams(rdirs_in, cumulative_flow): downstream_cells_out = np.zeros(rdirs_in.get_data().shape, dtype=np.int32) follow_streams_wrapper.follow_streams(rdirs_in.get_data(), cumulative_flow.\ get_cells_with_loops().astype(np.int32), downstream_cells_out) return field.makeField(downstream_cells_out, field_type="Generic", grid_type=rdirs_in.get_grid())
def testUsingSmallGrid(self): """ Test using a small 5 by 5 grid as the coarse grid, 15 by 15 fine grid Same data was used in FRUIT unit testing """ coarse_rdirs_field = field.makeField(self.coarse_rdirs, field_type='RiverDirections', grid_type='LatLong', nlat=5, nlong=5) coarse_cumulative_flow_field = field.makeField( self.coarse_cumulative_flow, field_type='CumulativeFlow', grid_type='LatLong', nlat=5, nlong=5) coarse_catchments_field = field.makeField(self.coarse_catchments, field_type='Generic', grid_type='LatLong', nlat=15, nlong=15) fine_rdirs_field = field.makeField(self.fine_rdirs, field_type='RiverDirections', grid_type='LatLong', nlat=15, nlong=15) fine_cumulative_flow_field = field.makeField( self.fine_cumulative_flow, field_type='CumulativeFlow', grid_type='LatLong', nlat=15, nlong=15) updated_output_coarse_river_directions =\ loop_breaker_driver.run_loop_breaker(coarse_rdirs_field, coarse_cumulative_flow_field, coarse_catchments_field, fine_rdirs_field, fine_cumulative_flow_field, self.loop_nums_list, coarse_grid_type='LatLong',nlat=5,nlong=5) np.testing.assert_array_equal( updated_output_coarse_river_directions.get_data(), self.expected_results, "Testing the loop breaking code with a small test grid doesn't give" " expected results")
def advanced_flow_to_rivermouth_calculation_driver(input_river_directions_filename, input_flow_to_cell_filename, output_flow_to_river_mouths_filename, input_river_directions_fieldname, input_flow_to_cell_fieldname, output_flow_to_river_mouths_fieldname): rdirs_field = iodriver.advanced_field_loader(input_river_directions_filename, field_type="RiverDirections", fieldname=input_river_directions_fieldname) flowtocell_field = iodriver.advanced_field_loader(input_flow_to_cell_filename, field_type="CumulativeFlow", fieldname=input_flow_to_cell_fieldname) rivermouth_field = field.makeField(rdirs_field.get_river_mouths(),'Generic', grid_type=rdirs_field.get_grid()) flowtorivermouths_field = field.makeField(flowtocell_field.\ find_cumulative_flow_at_outlets(rivermouth_field.\ get_data()), field_type="Generic", grid_type=rdirs_field.get_grid()) iodriver.advanced_field_writer(output_flow_to_river_mouths_filename, field=flowtorivermouths_field, fieldname=output_flow_to_river_mouths_fieldname)
def main(rdirs_filepath,updatedrdirs_filepath,lsmask_filepath=None, flowtocell_filepath=None,rivermouths_filepath=None, flowtorivermouths_filepath=None,skip_marking_mouths=False, flip_mask_ud=False,grid_type='HD',**grid_kwargs): """Top level function to drive the river mouth marking process Arguments: rdirs_filepath: string; full path to input river directions file updatedrdirs_filepath: string; full path to target output river directions file lsmask_filepath(optional): string; full path to land sea mask filepath flowtocell_filepath(optional): string; full path to cumulative flow input file path. Requires flowtorivermouths_filepath to be defined for this option to be meaningful; if it is not will raise a warning rivermouths_filepath(optional): string; full path to optional target river mouths output file - if used this will create a file where the position of river mouths is marked True and all other points are marked false flowtorivermouths_filepath(optional): string; full path to optional target flow to river mouth output file that will contain 0 everywhere expect at river mouths where it will contain the cumulative flow to that river mouth skip_marking_mouths(optional): boolean; if this flag is set to True then don't mark river mouths and perform only the additional task otherwise (if it is False) proceed as normal flip_mask_ud: boolean; flip the landsea mask (if any) upside down before processing? grid_type: string; keyword specifying the grid type **grid_kwargs: dictionary of keyword arguments; parameters for the specified grid type if required Return: Nothing Additional tasks are producing a river mouths output file and producing a flow to river mouth output file. """ #Load files rdirs_field = iodriver.load_field(filename=rdirs_filepath, file_type=iodriver.get_file_extension(rdirs_filepath), field_type="RiverDirections", grid_type=grid_type,**grid_kwargs) if lsmask_filepath: lsmask = iodriver.load_field(filename=lsmask_filepath, file_type=iodriver.get_file_extension(lsmask_filepath), field_type="Generic", grid_type=grid_type,**grid_kwargs) if flip_mask_ud: lsmask.flip_data_ud() else: lsmask = None if flowtocell_filepath: flowtocell_field = iodriver.load_field(filename=flowtocell_filepath, file_type=iodriver.get_file_extension(flowtocell_filepath), field_type="CumulativeFlow", grid_type=grid_type,**grid_kwargs) else: flowtocell_field = None if not skip_marking_mouths: #Perform the actual marking of river mouths rdirs_field.mark_river_mouths(lsmask.get_data() if lsmask is not None else None) #Write out the updated river directions field iodriver.write_field(filename=updatedrdirs_filepath, field=rdirs_field, file_type=iodriver.get_file_extension(updatedrdirs_filepath)) #Perform any additional tasks if any: either making a seperate river mouths mask file or #generating a file with the cumulative flow to each river mouth or both (or potentially neither) if rivermouths_filepath or (flowtocell_field is not None): rivermouth_field = field.makeField(rdirs_field.get_river_mouths(),'Generic',grid_type, **grid_kwargs) if flowtocell_field is not None: if flowtorivermouths_filepath: flowtorivermouths_field = field.makeField(flowtocell_field.\ find_cumulative_flow_at_outlets(rivermouth_field.\ get_data()), 'Generic',grid_type, **grid_kwargs) iodriver.write_field(flowtorivermouths_filepath,flowtorivermouths_field, file_type=iodriver.get_file_extension(flowtorivermouths_filepath)) else: raise UserWarning("Flow to cell file specified but no target flow to river" " mouth target file defined; not processing the flow to" " cell field") if rivermouths_filepath: iodriver.write_field(rivermouths_filepath,rivermouth_field, file_type=iodriver.get_file_extension(rivermouths_filepath))