Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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))
Ejemplo n.º 4
0
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))
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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))
Ejemplo n.º 7
0
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))
Ejemplo n.º 8
0
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))
Ejemplo n.º 9
0
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))
Ejemplo n.º 11
0
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))