def load_additional_manual_truesink_matches(additional_matches_filename,reference_rmouth_outflows_filename, data_rmouth_outflows_filename,reference_flowmap_field_filename, data_flowmap_field_filename,flip_data_rmouth_outflow_field=False, rotate_data_rmouth_outflow_field=False, flip_data_flowmap_field=False,rotate_data_flowmap_field=False, grid_type="HD",**grid_kwargs): """Any any additional matches involving true sinks by hand using details in list in a text file Includes both matches between a river and truesink, a truesink and a river and a true sink and a true sink. True sinks are ready from the cumulative flow to cell field and are not verified. """ reference_rmouth_field = iodriver.load_field(reference_rmouth_outflows_filename, file_type = iodriver.\ get_file_extension(reference_rmouth_outflows_filename), field_type='Generic', grid_type=grid_type,**grid_kwargs) data_rmouth_field = iodriver.load_field(data_rmouth_outflows_filename, file_type = iodriver.\ get_file_extension(data_rmouth_outflows_filename), field_type='Generic', grid_type=grid_type,**grid_kwargs) reference_flowmap_field = iodriver.load_field(reference_flowmap_field_filename, file_type = iodriver.\ get_file_extension(reference_flowmap_field_filename), field_type='Generic', grid_type=grid_type,**grid_kwargs) data_flowmap_field = iodriver.load_field(data_flowmap_field_filename, file_type = iodriver.\ get_file_extension(data_flowmap_field_filename), field_type='Generic', grid_type=grid_type,**grid_kwargs) if flip_data_rmouth_outflow_field: data_rmouth_field.flip_data_ud() if rotate_data_rmouth_outflow_field: data_rmouth_field.rotate_field_by_a_hundred_and_eighty_degrees() if flip_data_flowmap_field: data_flowmap_field.flip_data_ud() if rotate_data_flowmap_field: data_flowmap_field.rotate_field_by_a_hundred_and_eighty_degrees() first_line_pattern = re.compile(r"^ref_lat *, *ref_lon *, *ref_type *, *data_lat *, *data_lon *, *data_type *$") comment_line_pattern = re.compile(r"^ *#.*$") additional_matches = [] with open(additional_matches_filename) as f: if not first_line_pattern.match(f.readline().strip()): raise RuntimeError("List of corrections being loaded has incorrect format the first line") for line in f: if comment_line_pattern.match(line): continue ref_lat,ref_lon,ref_type,data_lat,data_lon,data_type = line.strip().split(",") ref_lat,ref_lon,data_lat,data_lon=[int(coords) for coords in [ref_lat,ref_lon,data_lat,data_lon]] params = Params('default') outflow_types={"RM":{"ref":reference_rmouth_field,"data":data_rmouth_field}, "TS":{"ref":reference_flowmap_field,"data":data_flowmap_field}} ref_mouth = RiverMouth(ref_lat,ref_lon, outflow_types[ref_type]["ref"].get_data()[ref_lat,ref_lon],0,params) data_mouth = RiverMouth(data_lat,data_lon, outflow_types[data_type]["data"].get_data()[data_lat,data_lon],0,params) additional_matches.append((ref_mouth,data_mouth)) return additional_matches
def load_additional_manual_matches(additional_matches_filename,reference_rmouth_outflows_filename, data_rmouth_outflows_filename,flip_data_field=False, rotate_data_field=False,grid_type='HD',**grid_kwargs): """Add any additional matches made by hand using details list in a text file""" reference_field = iodriver.load_field(reference_rmouth_outflows_filename, file_type = iodriver.\ get_file_extension(reference_rmouth_outflows_filename), field_type='Generic', grid_type=grid_type,**grid_kwargs) data_field = iodriver.load_field(data_rmouth_outflows_filename, file_type = iodriver.\ get_file_extension(data_rmouth_outflows_filename), field_type='Generic', grid_type=grid_type,**grid_kwargs) if flip_data_field: data_field.flip_data_ud() if rotate_data_field: data_field.rotate_field_by_a_hundred_and_eighty_degrees() first_line_pattern = re.compile(r"^ref_lat *, *ref_lon *, *data_lat *, *data_lon$") comment_line_pattern = re.compile(r"^ *#.*$") additional_matches = [] with open(additional_matches_filename) as f: if not first_line_pattern.match(f.readline().strip()): raise RuntimeError("List of corrections being loaded has incorrect format the first line") for line in f: if comment_line_pattern.match(line): continue ref_lat,ref_lon,data_lat,data_lon = [int(coord) for coord in line.strip().split(",")] params = Params('default') ref_mouth = RiverMouth(ref_lat,ref_lon,reference_field.get_data()[ref_lat,ref_lon],0,params) data_mouth = RiverMouth(data_lat,data_lon,data_field.get_data()[data_lat,data_lon],0,params) additional_matches.append((ref_mouth,data_mouth)) return additional_matches
def main(rdirs_filename, output_filename, grid_type, **grid_kwargs): """Top level function for cumulative flow to cell flow map generation Inputs: rdir_filename: string; full path to the file contain the input river direction field output_filename: string; full path of the target file to write the generated cumulative flow to cell field to grid_type: string; a keyword specifying the grid type of the input and output fields **grid_kwargs (optional): keyword dictionary; any parameters of the input and output grid that are required Returns: Nothing """ rdirs = iodriver.load_field(rdirs_filename, iodriver.get_file_extension(rdirs_filename), "Generic", grid_type=grid_type, **grid_kwargs) nlat, nlong = rdirs.get_grid().get_grid_dimensions() paths_map = field.Field(create_hypothetical_river_paths_map( riv_dirs=rdirs.get_data(), lsmask=None, use_f2py_func=True, use_f2py_sparse_iterator=True, nlat=nlat, nlong=nlong), grid=grid_type, **grid_kwargs) iodriver.write_field(output_filename, paths_map, iodriver.get_file_extension(output_filename))
def cotat_plus_driver(input_fine_rdirs_filepath,input_fine_total_cumulative_flow_path, output_coarse_rdirs_filepath,cotat_plus_parameters_filepath, fine_grid_type,fine_grid_kwargs={},coarse_grid_type='HD',**coarse_grid_kwargs): """Top level driver for the cotat plus algorithm Arguments: input_fine_rdirs_filepath: string; path to the file with fine river directions to upscale input_fine_total_cumulative_flow_path: string; path to the file with the fine scale cumulative flow from the fine river directions output_coarse_rdirs_filepath: string; path to the file to write the upscaled coarse river directions to cotat_plus_parameters_filepath: string; the file path containing the namelist with the parameters for the cotat plus upscaling algorithm fine_grid_type: string; code for the fine grid type to upscale from **fine_grid_kwargs(optional): keyword dictionary; the parameter of the fine grid to upscale from 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) Returns: Nothing Compiles and runs the COTAT plus algorithm in Fortran using f2py for a lat-lon field. Writes output specified filename. """ fine_rdirs_field = iodriver.load_field(input_fine_rdirs_filepath, file_type=iodriver.\ get_file_extension(input_fine_rdirs_filepath), field_type='RiverDirections', grid_type=fine_grid_type,**fine_grid_kwargs) fine_total_cumulative_flow_field =\ iodriver.load_field(input_fine_total_cumulative_flow_path, file_type=iodriver.\ get_file_extension(input_fine_total_cumulative_flow_path), field_type='CumulativeFlow', grid_type=fine_grid_type,**fine_grid_kwargs) coarse_rdirs_field = run_cotat_plus(fine_rdirs_field, fine_total_cumulative_flow_field, cotat_plus_parameters_filepath,coarse_grid_type, **coarse_grid_kwargs) iodriver.write_field(output_coarse_rdirs_filepath, coarse_rdirs_field, file_type=iodriver.\ get_file_extension(output_coarse_rdirs_filepath))
def main(reference_rmouth_outflows_filename, data_rmouth_outflows_filename, grid_type='HD',param_set='default',flip_data_field=False, rotate_data_field=False,flip_ref_field=False,rotate_ref_field=False,**grid_kwargs): """Top level river mouth matching routine. Deals with file handling""" reference_field = iodriver.load_field(reference_rmouth_outflows_filename, file_type = iodriver.\ get_file_extension(reference_rmouth_outflows_filename), field_type='Generic', grid_type=grid_type,**grid_kwargs) data_field = iodriver.load_field(data_rmouth_outflows_filename, file_type = iodriver.\ get_file_extension(data_rmouth_outflows_filename), field_type='Generic', grid_type=grid_type,**grid_kwargs) if flip_data_field: data_field.flip_data_ud() if rotate_data_field: data_field.rotate_field_by_a_hundred_and_eighty_degrees() if flip_ref_field: reference_field.flip_data_ud() if rotate_ref_field: reference_field.rotate_field_by_a_hundred_and_eighty_degrees() params = Params(param_set) return generate_matches(reference_field.get_data(), data_field.get_data(),params)
def main(filename, output_filename, loop_logfile, use_cpp_code=True, grid_type='HD', **grid_kwargs): """Generates a file with numbered catchments from a given river flow direction file Inputs: filename: string; the input file of river directions output_filename: string; the target file for the output numbered catchments loop_logfile: string; an input file of catchments with loop to be updated use_cpp_alg: bool; use the Cpp code if True otherwise use the Fortran code grid_type: string; a keyword giving the type of grid being used **grid_kwargs(optional): keyword dictionary; the parameter of the grid to be used (if required) Returns: Nothing Produces the numbered catchments where the numbering is in descending order of size; also update the loop log file to reflect the relabelling of catchements and runs a check on the type of catchments generated (which are placed in a log file with the same basename as the output catchments but with the extension '.log'). """ rdirs = iodriver.load_field( filename, file_type=iodriver.get_file_extension(filename), field_type='Generic', grid_type=grid_type, **grid_kwargs) if use_cpp_code: catchments = compute_catchments_cpp(rdirs.get_data(), loop_logfile) else: catchment_types, catchments = compute_catchments( rdirs.get_data(), loop_logfile) check_catchment_types(catchment_types, logfile=path.splitext(output_filename)[0] + ".log") numbered_catchments = field.Field(renumber_catchments_by_size( catchments, loop_logfile), grid=grid_type, **grid_kwargs) iodriver.write_field( filename=output_filename, field=numbered_catchments, file_type=iodriver.get_file_extension(output_filename))
def generate_orography_with_sinks_filled(input_orography_filename,output_orography_filename, ls_mask_filename=None,truesinks_filename=None, flip_ud=True,flip_lsmask_ud=True, flip_truesinks_ud=True,grid_type='HD', add_slight_slope_when_filling_sinks=True, slope_param=0.1,**grid_kwargs): """Generate an orography with the sinks filled using a priority flood type technique Input: input_orography_filename: string; the full path to the file containing the input orography output_orography_filename: string; the full path to the target file to write the output orography to ls_mask_filename: string; the full path to the file containing the input landsea mask.None means ignore. truesinks_filename: string; the full path to the file containing the true sinks to use. None means ignore. flip_ud: boolean; Flip the orography upside down before processing flip_lsmask_ud: boolean; Flip the landsea mask upside down before processing flip_truesinks_ud: boolean; Flip the true sinks upside down before processing grid_type: string; keyword for the grid type being used add_slight_slope_when_filling_sinks: boolean; a small increment to the height of each successive cell when filling a sink to give sink a slight slope slope_param: double; the small increment to add if adding a slight slope when fillings sinks **grid_kwargs: keyword dictionary; paramaters of the grid being used (if necessary) returns: nothing Load and manipulates necessary fields (making dummy field where necessary) then calls C++ sink filling algorithm through cython to perform actual sink filling and finally write out the result. """ orography = iodriver.load_field(input_orography_filename, file_type=iodriver.get_file_extension(input_orography_filename), field_type='Orography', grid_type=grid_type,**grid_kwargs) if flip_ud: orography.flip_data_ud() grid_dims=orography.get_grid().get_grid_dimensions() if not truesinks_filename: truesinks = Field(np.empty((1,1),dtype=np.int32),grid='HD') use_true_sinks = False; else: use_true_sinks = True; truesinks = iodriver.load_field(truesinks_filename, file_type=iodriver.\ get_file_extension(truesinks_filename), field_type='Generic', grid_type=grid_type, **grid_kwargs) if flip_truesinks_ud: truesinks.flip_data_ud() if ls_mask_filename is None: use_ls_mask = False ls_mask = Field(ls_mask = np.zeros(grid_dims,dtype=np.int32,order='C'),grid='LatLong', nlat=grid_dims[0],nlon=grid_dims[1]) else: use_ls_mask = True ls_mask = iodriver.load_field(ls_mask_filename, file_type=iodriver.get_file_extension(ls_mask_filename), field_type='Generic',grid_type=grid_type,**grid_kwargs) if flip_lsmask_ud: ls_mask.flip_data_ud() #Dtype change and ascontinguousarray must be applied here so orography keeps the correct #reference when running the C++ code orography.change_dtype(np.float64) orography.make_contiguous() fill_sinks_wrapper.fill_sinks_cpp_func(orography_array=orography.get_data(), method = 1, use_ls_mask = use_ls_mask, landsea_in = np.ascontiguousarray(ls_mask.get_data(), dtype=np.int32), set_ls_as_no_data_flag = False, use_true_sinks = use_true_sinks, true_sinks_in = np.ascontiguousarray(truesinks.get_data(), dtype=np.int32), add_slope =add_slight_slope_when_filling_sinks, epsilon = slope_param) iodriver.write_field(output_orography_filename,orography, file_type=iodriver.get_file_extension(output_orography_filename))
def generate_sinkless_flow_directions(filename,output_filename,ls_mask_filename=None, truesinks_filename=None,catchment_nums_filename=None, flip_ud=True,grid_type='HD',**grid_kwargs): """Generate sinkless flow directions from a given orography Input: filename: string; the full path to the file containing the input orography output_filename: string; the full target path for the output file the generated flow direction will be written to ls_mask_filename: string, the full path to the file containing the input landsea mask. None means ignore. truesinks_filename: string, the full path to the file containing the true sinks to use. None means ignore. flip_ud: boolean; If true flip the input fields upside down before processing... this affects the directions you get as it affects whether 7 8 9 is up and 1 2 3 is down or visa versa grid_type: string; keyword for the grid type being used **grid_kwargs: keyword dictionary; paramaters of the grid being used (if necessary) returns: nothing Loads the orography, creates an empty array for the river flow direction of the same size; either loads the landsea mask or makes a dummy field for this of the appropriate size (required for the interface to work correctly) and then passes this input to fill_sinks_cpp_func of Cython fill_sinks_wrapper to interface with the C++ code that actual generates the flow directions according to Algorithm 4 of Barnes et al (2014). Finally save the output river direction field. """ orography = iodriver.load_field(filename, file_type=iodriver.get_file_extension(filename), field_type='Orography', grid_type=grid_type,**grid_kwargs) if flip_ud: orography.flip_data_ud() grid_dims=orography.get_grid().get_grid_dimensions() rdirs = np.zeros(grid_dims,dtype=np.float64,order='C') if not truesinks_filename: truesinks = Field(np.empty((1,1),dtype=np.int32),grid='HD') use_true_sinks = False; else: use_true_sinks = True; truesinks = iodriver.load_field(truesinks_filename, file_type=iodriver.\ get_file_extension(truesinks_filename), field_type='Generic', grid_type=grid_type, **grid_kwargs) if flip_ud: truesinks.flip_data_ud() if ls_mask_filename is None: use_ls_mask = False ls_mask = np.zeros(grid_dims,dtype=np.int32,order='C') else: use_ls_mask = True ls_mask = iodriver.load_field(ls_mask_filename, file_type=iodriver.get_file_extension(ls_mask_filename), field_type='Generic',grid_type=grid_type,**grid_kwargs) if flip_ud: ls_mask.flip_data_ud() catchment_nums = np.zeros(grid_dims,dtype=np.int32,order='C') next_cell_lat_index_in = np.zeros(grid_dims,dtype=np.int32,order='C') next_cell_lon_index_in = np.zeros(grid_dims,dtype=np.int32,order='C') fill_sinks_wrapper.fill_sinks_cpp_func(orography_array=np.ascontiguousarray(orography.get_data(), #@UndefinedVariable dtype=np.float64), method = 4, use_ls_mask = use_ls_mask, landsea_in = np.ascontiguousarray(ls_mask.get_data(), dtype=np.int32), set_ls_as_no_data_flag = False, use_true_sinks = use_true_sinks, true_sinks_in = np.ascontiguousarray(truesinks.get_data(), dtype=np.int32), next_cell_lat_index_in = next_cell_lat_index_in, next_cell_lon_index_in = next_cell_lon_index_in, rdirs_in = rdirs, catchment_nums_in = catchment_nums, prefer_non_diagonal_initial_dirs = False) iodriver.write_field(output_filename,Field(rdirs,grid_type,**grid_kwargs), file_type=iodriver.get_file_extension(output_filename)) if catchment_nums_filename: iodriver.write_field(catchment_nums_filename, field=Field(catchment_nums,grid_type,**grid_kwargs), file_type=iodriver.get_file_extension(catchment_nums_filename))
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))
def drive_connected_lsmask_creation(input_lsmask_filename, output_lsmask_filename, input_ls_seed_points_filename=None, input_ls_seed_points_list_filename=None, use_diagonals_in=True, rotate_seeds_about_polar_axis=False, flip_seeds_ud=False, flip_input_mask_ud=False, grid_type='HD', **grid_kwargs): """Drives the creation of a fully connected land-sea mask Argument: input_lsmask_filename: string; the full path of the input land-sea mask which may contain disconnected sea points output_lsmask_filename: string; the full path of the output land-sea mask without any disconnected sea point input_ls_seed_points_filename(optional): string; the full path of the file with an array with at least one point in the center of each ocean/sea to be included input_ls_seed_points_list_filename(optional): string; the full path of the file with a list of at least one point in the center of each ocean/sea to be included - these will be added to the contents of input_ls_seed_points_filename, normally only one of the two arguments would be used to initialise the seed points use_diagonals_in: boolean; if true count a diagonal connection as being connected flip_input_mask_ud: boolean; if true flip the input mask up down before processing rotate_seeds_about_polar_axis: if true then rotate the seeds about the polar axis by 180 degrees, i.e. shift the position of the zero longitude by 180 degrees when reading the seed points flip_seeds_upside_down: boolean; if true then flip the seeds upside down (i.e. about the equator) grid_type: string; the code for this grid type **grid_kwargs: dictionary; key word arguments specifying parameters of the grid Returns: Nothing Creates a land-sea masked based on the supplied land-sea mask with any sea points not connected to the supplied ocean seeds points (by other sea points) change to land points """ lsmask = iodriver.load_field(input_lsmask_filename, file_type=iodriver.\ get_file_extension(input_lsmask_filename), field_type='Generic', grid_type=grid_type,**grid_kwargs) if flip_input_mask_ud: lsmask.flip_data_ud() if input_ls_seed_points_filename: input_ls_seedpts = iodriver.load_field(input_ls_seed_points_filename, file_type=iodriver.\ get_file_extension(input_ls_seed_points_filename), field_type='Generic', grid_type=grid_type,**grid_kwargs) else: input_ls_seedpts = field.makeEmptyField('Generic', np.int32, grid_type, **grid_kwargs) if input_ls_seed_points_list_filename: points_list = [] print("Reading input from {0}".format( input_ls_seed_points_list_filename)) comment_line_pattern = re.compile(r"^ *#.*$") with open(input_ls_seed_points_list_filename) as f: if f.readline().strip() != grid_type: raise RuntimeError( "List of landsea points being loaded is not for correct grid-type" ) for line in f: if comment_line_pattern.match(line): continue points_list.append( tuple(int(coord) for coord in line.strip().split(","))) input_ls_seedpts.flag_listed_points(points_list) if rotate_seeds_about_polar_axis: input_ls_seedpts.rotate_field_by_a_hundred_and_eighty_degrees() if flip_seeds_ud: input_ls_seedpts.flip_data_ud() lsmask.change_dtype(np.int32) cc_lsmask_wrapper.create_connected_ls_mask( lsmask.get_data(), input_ls_seedpts.get_data().astype(dtype=np.int32, order='C', copy=False), use_diagonals_in) iodriver.write_field(output_lsmask_filename,lsmask, file_type=iodriver.\ get_file_extension(output_lsmask_filename))
def loop_breaker_driver(input_coarse_rdirs_filepath,input_coarse_cumulative_flow_filepath, input_coarse_catchments_filepath,input_fine_rdirs_filepath, input_fine_cumulative_flow_filepath,output_updated_coarse_rdirs_filepath, loop_nums_list_filepath,coarse_grid_type,fine_grid_type, fine_grid_kwargs={},**coarse_grid_kwargs): """Drive the FORTRAN code to remove more complex loops from a field of river directions Arguments: input_coarse_rdirs_filepath: string, full path to input coarse river directions to remove loops from input_coarse_cumulative_flow_filepath: string, full path to the input coarse cumulative flow file input_coarse_catchments_filepath: string, full path to the coarse input catchments file input_fine_rdirs_filepath: string, full path to the fine input river directions the coarse input river directions were upscaled from input_fine_cumulative_flow_filepath: string, full path to the catchments generated from the fine input river directions output_updated_coarse_rdirs_filepath: string, full path to write the coarse river direction with the specified loops removed too loop_nums_list_filepath: string, full path to the file contain the catchment numbers of the loops to remove, one per line, see code below for correct format for the first line coarse_grid_type: string; code for the grid type of the coarse grid fine_grid_type: string; code for the grid type of the fine grid fine_grid_kwargs: keyword dictionary; key word arguments specifying parameters of the fine grid (if required) **coarse_grid_kwarg: keyword dictionary; key word arguments specifying parameters of the coarse grid (if required) Returns: nothing """ input_coarse_rdirs_field = iodriver.load_field(input_coarse_rdirs_filepath, file_type=iodriver.\ get_file_extension(input_coarse_rdirs_filepath), field_type='RiverDirections', grid_type=coarse_grid_type,**coarse_grid_kwargs) coarse_cumulative_flow_field =\ iodriver.load_field(input_coarse_cumulative_flow_filepath, file_type=iodriver.\ get_file_extension(input_coarse_cumulative_flow_filepath), field_type='CumulativeFlow', grid_type=coarse_grid_type,**coarse_grid_kwargs) coarse_catchments_field =\ iodriver.load_field(input_coarse_catchments_filepath, file_type=iodriver.\ get_file_extension(input_coarse_catchments_filepath), field_type='Generic', grid_type=coarse_grid_type,**coarse_grid_kwargs) fine_rdirs_field = iodriver.load_field(input_fine_rdirs_filepath, file_type=iodriver.\ get_file_extension(input_fine_rdirs_filepath), field_type='RiverDirections', grid_type=fine_grid_type,**fine_grid_kwargs) fine_cumulative_flow_field =\ iodriver.load_field(input_fine_cumulative_flow_filepath, file_type=iodriver.\ get_file_extension(input_fine_cumulative_flow_filepath), field_type='CumulativeFlow', grid_type=fine_grid_type,**fine_grid_kwargs) loop_nums_list = [] first_line_pattern = re.compile(r"^Loops found in catchments:$") with open(loop_nums_list_filepath,'r') as f: if not first_line_pattern.match(f.readline().strip()): raise RuntimeError("Format of the file with list of catchments to remove loops from" " is invalid") for line in f: loop_nums_list.append(int(line.strip())) print('Removing loops from catchments: ' + ", ".join(str(value) for value in loop_nums_list)) output_coarse_rdirs_field = run_loop_breaker(input_coarse_rdirs_field,coarse_cumulative_flow_field, coarse_catchments_field,fine_rdirs_field, fine_cumulative_flow_field,loop_nums_list, coarse_grid_type,**coarse_grid_kwargs) iodriver.write_field(output_updated_coarse_rdirs_filepath, output_coarse_rdirs_field, file_type=iodriver.\ get_file_extension(output_updated_coarse_rdirs_filepath))
def drive_orography_upscaling(input_fine_orography_file, output_coarse_orography_file, landsea_file=None, true_sinks_file=None, upscaling_parameters_filename=None, fine_grid_type='LatLong10min', coarse_grid_type='HD', input_orography_field_name=None, flip_landsea=False, rotate_landsea=False, flip_true_sinks=False, rotate_true_sinks=False, fine_grid_kwargs={}, **coarse_grid_kwargs): """Drive the C++ sink filling code base to make a tarasov-like orography upscaling Arguments: input_fine_orography_file: string; full path to input fine orography file output_coarse_orography_file: string; full path of target output coarse orography file landsea_file: string; full path to input fine landsea mask file (optional) true_sinks_file: string; full path to input fine true sinks file (optional) upscaling_parameters_filename: string; full path to the orography upscaling parameter file (optional) fine_grid_type: string; code for the fine grid type to be upscaled from (optional) coarse_grid_type: string; code for the coarse grid type to be upscaled to (optional) input_orography_field_name: string; name of field in the input orography file (optional) flip_landsea: bool; flip the input landsea mask upside down rotate_landsea: bool; rotate the input landsea mask by 180 degrees along the horizontal axis flip_true_sinks: bool; flip the input true sinks field upside down rotate_true_sinks: bool; rotate the input true sinks field by 180 degrees along the horizontal axis fine_grid_kwargs: keyword dictionary; the parameter of the fine grid to upscale from (if required) **coarse_grid_kwargs: keyword dictionary; the parameters of the coarse grid to upscale to (if required) Returns: Nothing. """ if upscaling_parameters_filename: config = read_and_validate_config(upscaling_parameters_filename) method = config.getint("orography_upscaling_parameters", "method") add_slope_in = config.getboolean("orography_upscaling_parameters", "add_slope_in") epsilon_in = config.getfloat("orography_upscaling_parameters", "epsilon_in") tarasov_separation_threshold_for_returning_to_same_edge_in =\ config.getint("orography_upscaling_parameters", "tarasov_separation_threshold_for_returning_to_same_edge_in") tarasov_min_path_length_in = config.getfloat( "orography_upscaling_parameters", "tarasov_min_path_length_in") tarasov_include_corners_in_same_edge_criteria_in = \ config.getboolean("orography_upscaling_parameters", "tarasov_include_corners_in_same_edge_criteria_in") else: #use defaults method = 1 add_slope_in = False epsilon_in = 0.1 tarasov_separation_threshold_for_returning_to_same_edge_in = 5 tarasov_min_path_length_in = 2.0 tarasov_include_corners_in_same_edge_criteria_in = False output_orography = field.makeEmptyField(field_type='Orography', dtype=np.float64, grid_type=coarse_grid_type, **coarse_grid_kwargs) input_orography = iodriver.load_field( input_fine_orography_file, file_type=get_file_extension(input_fine_orography_file), field_type='Orography', unmask=True, fieldname=input_orography_field_name, grid_type=fine_grid_type, **fine_grid_kwargs) if landsea_file: landsea_mask = iodriver.load_field( landsea_file, file_type=get_file_extension(landsea_file), field_type='Generic', unmask=True, grid_type=fine_grid_type, **fine_grid_kwargs) if flip_landsea: landsea_mask.flip_data_ud() if rotate_landsea: landsea_mask.rotate_field_by_a_hundred_and_eighty_degrees() else: landsea_mask = field.makeEmptyField(field_type='Generic', dtype=np.int32, grid_type=fine_grid_type, **fine_grid_kwargs) if true_sinks_file: true_sinks = iodriver.load_field( true_sinks_file, file_type=get_file_extension(true_sinks_file), field_type='Generic', unmask=True, grid_type=fine_grid_type, **fine_grid_kwargs) if flip_true_sinks: true_sinks.flip_data_ud() if rotate_true_sinks: true_sinks.rotate_field_by_a_hundred_and_eighty_degrees() else: true_sinks = field.makeEmptyField(field_type='Generic', dtype=np.int32, grid_type=fine_grid_type, **fine_grid_kwargs) if not np.issubdtype(input_orography.get_data().dtype, np.float64()): input_orography.change_dtype(np.float64) #Make sure old data type array is flushed out of memory immediately gc.collect() upscale_orography_wrapper.upscale_orography(orography_in=input_orography.get_data(), orography_out=output_orography.get_data(), method=method,landsea_in=landsea_mask.get_data(), true_sinks_in=true_sinks.get_data(), add_slope_in=add_slope_in, epsilon_in=epsilon_in, tarasov_separation_threshold_for_returning_to_same_edge_in=\ tarasov_separation_threshold_for_returning_to_same_edge_in, tarasov_min_path_length_in=tarasov_min_path_length_in, tarasov_include_corners_in_same_edge_criteria_in=\ tarasov_include_corners_in_same_edge_criteria_in) iodriver.write_field( output_coarse_orography_file, output_orography, file_type=get_file_extension(output_coarse_orography_file))