Example #1
0
def get_matrix_A(fn, gauge_name):
    # points to read information from
    point_reader = reader(file(gauge_name))
    points = []
    point_name = []
    for i, row in enumerate(point_reader):
        if i == 0:
            for j, value in enumerate(row):
                if value.strip() == 'easting': easting = j
                if value.strip() == 'northing': northing = j
                if value.strip() == 'name': name = j
                if value.strip() == 'elevation': elevation = j
        else:
            #points.append([float(row[easting]),float(row[northing])])
            points.append([float(row[easting]), float(row[northing])])
            point_name.append(row[name])
    points_array = np.array(points, np.float)
    dim_gauge = int(np.sqrt(points_array.shape[0]))
    interpolation_points = ensure_absolute(points_array)

    # read the sww file to extract something
    fid = NetCDFFile(fn, netcdf_mode_r)
    xllcorner = fid.xllcorner
    yllcorner = fid.yllcorner
    zone = fid.zone
    x = fid.variables['x'][:]
    y = fid.variables['y'][:]

    triangles = fid.variables['volumes'][:]

    x = np.reshape(x, (len(x), 1))
    y = np.reshape(y, (len(y), 1))
    vertex_coordinates = np.concatenate((x, y), axis=1)
    ele = fid.variables['elevation'][:]
    fid.close()

    vertex_coordinates = ensure_absolute(vertex_coordinates)
    triangles = ensure_numeric(triangles)

    interpolation_points = ensure_numeric(interpolation_points)
    interpolation_points[:, 0] -= xllcorner
    interpolation_points[:, 1] -= yllcorner

    mesh = Mesh(vertex_coordinates, triangles)
    mesh_boundary_polygon = mesh.get_boundary_polygon()
    indices = outside_polygon(interpolation_points, mesh_boundary_polygon)
    interp = Interpolate(vertex_coordinates, triangles)
    matrix_A, inside_poly_indices, outside_poly_indices, centroids = interp._build_interpolation_matrix_A(
        interpolation_points, output_centroids=False, verbose=False)

    ele = matrix_A * ele
    ele = np.asarray(ele)
    ele = ele.reshape((100, 100))

    return ele, matrix_A
def inundation_damage(sww_base_name, exposure_files_in,
                      exposure_file_out_marker=None,
                      ground_floor_height=0.3,
                      overwrite=False, verbose=True,
                                 use_cache = True):
    """
    This is the main function for calculating tsunami damage due to
    inundation.  It gets the location of structures from the exposure
    file and gets the inundation of these structures from the
    sww file.

    It then calculates the damage loss.

    Note, structures outside of the sww file get the minimum inundation
    (-ground_floor_height).
    
    These calculations are done over all the sww files with the sww_base_name
    in the specified directory.

    exposure_files_in - a file or a list of files to input from
    exposure_file_out_marker -  this string will be added to the input file
                                name to get the output file name
    """
    if isinstance(exposure_files_in, basestring):
        exposure_files_in = [exposure_files_in]


    for exposure_file_in in exposure_files_in:
        csv = Exposure(exposure_file_in,
                           title_check_list=[SHORE_DIST_LABEL,WALL_TYPE_LABEL,
                                             STR_VALUE_LABEL,CONT_VALUE_LABEL])
        geospatial = csv.get_location()
        geospatial = ensure_absolute(geospatial)
        max_depths, max_momentums = calc_max_depth_and_momentum(sww_base_name,
                        geospatial,
                        ground_floor_height=ground_floor_height,
                        verbose=verbose,
                        use_cache=use_cache)
        edm = EventDamageModel(max_depths,
                               csv.get_column(SHORE_DIST_LABEL),
                               csv.get_column(WALL_TYPE_LABEL),
                               csv.get_column(STR_VALUE_LABEL),
                               csv.get_column(CONT_VALUE_LABEL)
                               )
        results_dic = edm.calc_damage_and_costs(verbose_csv=True,
                                                verbose=verbose)
        for title, value in results_dic.iteritems():
            csv.set_column(title, value, overwrite=overwrite)
    
        # Save info back to csv file
        if exposure_file_out_marker == None:
            exposure_file_out = exposure_file_in
        else:
            # split off extension, in such a way to deal with more than one '.' in the name of file
            split_name = exposure_file_in.split('.')
            exposure_file_out =  '.'.join(split_name[:-1]) + exposure_file_out_marker + \
                                '.' + split_name[-1]
        csv.save(exposure_file_out)
        if verbose: log.critical('Augmented building file written to %s'
                                 % exposure_file_out)
Example #3
0
def inside_polygon(points, polygon, closed=True, verbose=False):
    """Determine points inside a polygon

       Functions inside_polygon and outside_polygon have been defined in
       terms of separate_by_polygon which will put all inside indices in
       the first part of the indices array and outside indices in the last

       See separate_points_by_polygon for documentation

       points and polygon can be a geospatial instance,
       a list or a numeric array
    """

    try:
        points = ensure_absolute(points)
    except NameError as err:
        raise_(NameError, err)
    except:
        # If this fails it is going to be because the points can't be
        # converted to a numeric array.
        msg = 'Points could not be converted to numeric array'
        raise_(Exception, msg)

    try:
        polygon = ensure_absolute(polygon)
    except NameError as e:
        raise_(NameError, e)
    except:
        # If this fails it is going to be because the points can't be
        # converted to a numeric array.
        msg = ('Polygon %s could not be converted to numeric array' %
               (str(polygon)))
        raise_(Exception, msg)

    if len(points.shape) == 1:
        # Only one point was passed in. Convert to array of points
        points = num.reshape(points, (1, 2))

    indices, count = separate_points_by_polygon(points,
                                                polygon,
                                                closed=closed,
                                                verbose=verbose)

    # Return indices of points inside polygon
    return indices[:count]
Example #4
0
def inside_polygon(points, polygon, closed=True, verbose=False):
    """Determine points inside a polygon

       Functions inside_polygon and outside_polygon have been defined in
       terms of separate_by_polygon which will put all inside indices in
       the first part of the indices array and outside indices in the last

       See separate_points_by_polygon for documentation

       points and polygon can be a geospatial instance,
       a list or a numeric array
    """

    try:
        points = ensure_absolute(points)
    except NameError, err:
        raise NameError, err
Example #5
0
def inside_polygon(points, polygon, closed=True, verbose=False):
    """Determine points inside a polygon

       Functions inside_polygon and outside_polygon have been defined in
       terms of separate_by_polygon which will put all inside indices in
       the first part of the indices array and outside indices in the last

       See separate_points_by_polygon for documentation

       points and polygon can be a geospatial instance,
       a list or a numeric array
    """

    try:
        points = ensure_absolute(points)
    except NameError, err:
        raise NameError, err
Example #6
0
       points and polygon can be a geospatial instance,
       a list or a numeric array
    """

    try:
        points = ensure_absolute(points)
    except NameError, err:
        raise NameError, err
    except:
        # If this fails it is going to be because the points can't be
        # converted to a numeric array.
        msg = 'Points could not be converted to numeric array'
        raise Exception, msg

    try:
        polygon = ensure_absolute(polygon)
    except NameError, e:
        raise NameError, e
    except:
        # If this fails it is going to be because the points can't be
        # converted to a numeric array.
        msg = ('Polygon %s could not be converted to numeric array' %
               (str(polygon)))
        raise Exception, msg

    if len(points.shape) == 1:
        # Only one point was passed in. Convert to array of points
        points = num.reshape(points, (1, 2))

    indices, count = separate_points_by_polygon(points,
                                                polygon,
Example #7
0
def inundation_damage(sww_base_name,
                      exposure_files_in,
                      exposure_file_out_marker=None,
                      ground_floor_height=0.3,
                      overwrite=False,
                      verbose=True,
                      use_cache=True):
    """
    This is the main function for calculating tsunami damage due to
    inundation.  It gets the location of structures from the exposure
    file and gets the inundation of these structures from the
    sww file.

    It then calculates the damage loss.

    Note, structures outside of the sww file get the minimum inundation
    (-ground_floor_height).
    
    These calculations are done over all the sww files with the sww_base_name
    in the specified directory.

    exposure_files_in - a file or a list of files to input from
    exposure_file_out_marker -  this string will be added to the input file
                                name to get the output file name
    """
    if isinstance(exposure_files_in, basestring):
        exposure_files_in = [exposure_files_in]

    for exposure_file_in in exposure_files_in:
        csv = Exposure(exposure_file_in,
                       title_check_list=[
                           SHORE_DIST_LABEL, WALL_TYPE_LABEL, STR_VALUE_LABEL,
                           CONT_VALUE_LABEL
                       ])
        geospatial = csv.get_location()
        geospatial = ensure_absolute(geospatial)
        max_depths, max_momentums = calc_max_depth_and_momentum(
            sww_base_name,
            geospatial,
            ground_floor_height=ground_floor_height,
            verbose=verbose,
            use_cache=use_cache)
        edm = EventDamageModel(max_depths, csv.get_column(SHORE_DIST_LABEL),
                               csv.get_column(WALL_TYPE_LABEL),
                               csv.get_column(STR_VALUE_LABEL),
                               csv.get_column(CONT_VALUE_LABEL))
        results_dic = edm.calc_damage_and_costs(verbose_csv=True,
                                                verbose=verbose)
        for title, value in results_dic.iteritems():
            csv.set_column(title, value, overwrite=overwrite)

        # Save info back to csv file
        if exposure_file_out_marker is None:
            exposure_file_out = exposure_file_in
        else:
            # split off extension, in such a way to deal with more than one '.' in the name of file
            split_name = exposure_file_in.split('.')
            exposure_file_out =  '.'.join(split_name[:-1]) + exposure_file_out_marker + \
                                '.' + split_name[-1]
        csv.save(exposure_file_out)
        if verbose:
            log.critical('Augmented building file written to %s' %
                         exposure_file_out)
Example #8
0
def _fit_to_mesh(point_coordinates,
                 vertex_coordinates=None,
                 triangles=None,
                 mesh=None,
                 point_attributes=None,
                 alpha=DEFAULT_ALPHA,
                 verbose=False,
                 mesh_origin=None,
                 data_origin=None,
                 max_read_lines=None,
                 attribute_name=None,
                 cg_precon='Jacobi',
                 use_c_cg=True):
    """
    Fit a smooth surface to a triangulation,
    given data points with attributes.


        Inputs:
        vertex_coordinates: List of coordinate pairs [xi, eta] of
        points constituting a mesh (or an m x 2 numeric array or
              a geospatial object)
              Points may appear multiple times
              (e.g. if vertices have discontinuities)

          triangles: List of 3-tuples (or a numeric array) of
          integers representing indices of all vertices in the mesh.

          point_coordinates: List of coordinate pairs [x, y] of data points
          (or an nx2 numeric array). This can also be a .csv/.txt/.pts
          file name.

          alpha: Smoothing parameter.

          mesh_origin: A geo_reference object or 3-tuples consisting of
              UTM zone, easting and northing.
              If specified vertex coordinates are assumed to be
              relative to their respective origins.

          point_attributes: Vector or array of data at the
                            point_coordinates.

    """

    if mesh is None:
        # FIXME(DSG): Throw errors if triangles or vertex_coordinates
        # are None

        #Convert input to numeric arrays
        triangles = ensure_numeric(triangles, num.int)
        vertex_coordinates = ensure_absolute(vertex_coordinates,
                                             geo_reference=mesh_origin)

        if verbose:
            log.critical('_fit_to_mesh: Building mesh')
        mesh = Mesh(vertex_coordinates, triangles)

        # Don't need this as we have just created the mesh
        #mesh.check_integrity()

    interp = Fit(mesh=mesh,
                 verbose=verbose,
                 alpha=alpha,
                 cg_precon=cg_precon,
                 use_c_cg=use_c_cg)

    vertex_attributes = interp.fit(point_coordinates,
                                   point_attributes,
                                   point_origin=data_origin,
                                   max_read_lines=max_read_lines,
                                   attribute_name=attribute_name,
                                   verbose=verbose)

    # Add the value checking stuff that's in least squares.
    # Maybe this stuff should get pushed down into Fit.
    # at least be a method of Fit.
    # Or intigrate it into the fit method, saving teh max and min's
    # as att's.

    return vertex_attributes
Example #9
0
def get_netcdf_file_function(filename,
                             quantity_names=None,
                             interpolation_points=None,
                             domain_starttime=None,
                             time_thinning=1,
                             time_limit=None,
                             verbose=False,
                             boundary_polygon=None,
                             output_centroids=False):
    """Read time history of spatial data from NetCDF sww file and
    return a callable object f(t,x,y)
    which will return interpolated values based on the input file.

    Model time (domain_starttime)
    will be checked, possibly modified and returned
    
    All times are assumed to be in UTC

    See Interpolation function for further documentation
    """

    # FIXME: Check that model origin is the same as file's origin
    # (both in UTM coordinates)
    # If not - modify those from file to match domain
    # (origin should be passed in)
    # Take this code from e.g. dem2pts in data_manager.py
    # FIXME: Use geo_reference to read and write xllcorner...

    import time, calendar
    from anuga.config import time_format

    # Open NetCDF file
    if verbose: log.critical('Reading %s' % filename)

    fid = NetCDFFile(filename, netcdf_mode_r)

    if isinstance(quantity_names, basestring):
        quantity_names = [quantity_names]

    if quantity_names is None or len(quantity_names) < 1:
        msg = 'No quantities are specified in file_function'
        raise Exception(msg)

    if interpolation_points is not None:

        #interpolation_points = num.array(interpolation_points, num.float)
        interpolation_points = ensure_absolute(interpolation_points)
        msg = 'Points must by N x 2. I got %d' % interpolation_points.shape[1]
        assert interpolation_points.shape[1] == 2, msg

    # Now assert that requested quantitites (and the independent ones)
    # are present in file
    missing = []
    for quantity in ['time'] + quantity_names:
        if not fid.variables.has_key(quantity):
            missing.append(quantity)

    if len(missing) > 0:
        msg = 'Quantities %s could not be found in file %s'\
              % (str(missing), filename)
        fid.close()
        raise Exception(msg)

    # Decide whether this data has a spatial dimension
    spatial = True
    for quantity in ['x', 'y']:
        if not fid.variables.has_key(quantity):
            spatial = False

    if filename[-3:] == 'tms' and spatial is True:
        msg = 'Files of type TMS must not contain spatial information'
        raise Exception(msg)

    if filename[-3:] == 'sww' and spatial is False:
        msg = 'Files of type SWW must contain spatial information'
        raise Exception(msg)

    if filename[-3:] == 'sts' and spatial is False:
        #What if mux file only contains one point
        msg = 'Files of type STS must contain spatial information'
        raise Exception(msg)

    # JJ REMOVED
    #if filename[-3:] == 'sts' and boundary_polygon is None:
    #    #What if mux file only contains one point
    #    msg = 'Files of type sts require boundary polygon'
    #    raise Exception(msg)

    # Get first timestep
    try:
        starttime = float(fid.starttime)
    except ValueError:
        msg = 'Could not read starttime from file %s' % filename
        raise Exception(msg)

    # Get variables
    # if verbose: log.critical('Get variables'    )
    time = fid.variables['time'][:]

    # FIXME(Ole): Is time monotoneous?

    # Apply time limit if requested
    upper_time_index = len(time)
    msg = 'Time vector obtained from file %s has length 0' % filename
    assert upper_time_index > 0, msg

    if time_limit is not None:
        # Adjust given time limit to given start time
        time_limit = time_limit - starttime

        # Find limit point
        for i, t in enumerate(time):
            if t > time_limit:
                upper_time_index = i
                break

        msg = 'Time vector is zero. Requested time limit is %f' % time_limit
        assert upper_time_index > 0, msg

        if time_limit < time[-1] and verbose is True:
            log.critical('Limited time vector from %.2fs to %.2fs' %
                         (time[-1], time_limit))

    time = time[:upper_time_index]

    # Get time independent stuff
    if spatial:
        # Get origin
        #xllcorner = fid.xllcorner[0]
        #yllcorner = fid.yllcorner[0]
        #zone = fid.zone[0]

        xllcorner = fid.xllcorner
        yllcorner = fid.yllcorner
        zone = fid.zone

        x = fid.variables['x'][:]
        y = fid.variables['y'][:]
        if filename.endswith('sww'):
            triangles = fid.variables['volumes'][:]

        x = num.reshape(x, (len(x), 1))
        y = num.reshape(y, (len(y), 1))
        vertex_coordinates = num.concatenate((x, y), axis=1)  #m x 2 array

        if boundary_polygon is not None:
            # Remove sts points that do not lie on boundary
            # FIXME(Ole): Why don't we just remove such points from the list of
            # points and associated data?
            # I am actually convinced we can get rid of neighbour_gauge_id
            # altogether as the sts file is produced using the ordering file.
            # All sts points are therefore always present in the boundary.
            # In fact, they *define* parts of the boundary.
            boundary_polygon = ensure_numeric(boundary_polygon)
            boundary_polygon[:, 0] -= xllcorner
            boundary_polygon[:, 1] -= yllcorner
            temp = []
            boundary_id = []
            gauge_id = []
            for i in range(len(boundary_polygon)):
                for j in range(len(x)):
                    if num.allclose(vertex_coordinates[j],
                                    boundary_polygon[i],
                                    rtol=1e-4,
                                    atol=1e-4):
                        #FIXME:
                        #currently gauges lat and long is stored as float and
                        #then cast to double. This cuases slight repositioning
                        #of vertex_coordinates.
                        temp.append(boundary_polygon[i])
                        gauge_id.append(j)
                        boundary_id.append(i)
                        break
            gauge_neighbour_id = []
            for i in range(len(boundary_id) - 1):
                if boundary_id[i] + 1 == boundary_id[i + 1]:
                    gauge_neighbour_id.append(i + 1)
                else:
                    gauge_neighbour_id.append(-1)
            if boundary_id[len(boundary_id)-1]==len(boundary_polygon)-1 \
               and boundary_id[0]==0:
                gauge_neighbour_id.append(0)
            else:
                gauge_neighbour_id.append(-1)
            gauge_neighbour_id = ensure_numeric(gauge_neighbour_id)


            if len(num.compress(gauge_neighbour_id>=0, gauge_neighbour_id)) \
               != len(temp)-1:
                msg = 'incorrect number of segments'
                raise Exception(msg)
            vertex_coordinates = ensure_numeric(temp)
            if len(vertex_coordinates) == 0:
                msg = 'None of the sts gauges fall on the boundary'
                raise Exception(msg)
        else:
            gauge_neighbour_id = None

        if interpolation_points is not None:
            # Adjust for georef
            interpolation_points[:, 0] -= xllcorner
            interpolation_points[:, 1] -= yllcorner
    else:
        gauge_neighbour_id = None

    if domain_starttime is not None:
        # If domain_startime is *later* than starttime,
        # move time back - relative to domain's time
        if domain_starttime > starttime:
            time = time - domain_starttime + starttime

        # FIXME Use method in geo to reconcile
        # if spatial:
        # assert domain.geo_reference.xllcorner == xllcorner
        # assert domain.geo_reference.yllcorner == yllcorner
        # assert domain.geo_reference.zone == zone

    if verbose:
        log.critical('File_function data obtained from: %s' % filename)
        log.critical('  References:')
        if spatial:
            log.critical('    Lower left corner: [%f, %f]' %
                         (xllcorner, yllcorner))
        log.critical('    Start time:   %f' % starttime)

    # Produce values for desired data points at
    # each timestep for each quantity
    quantities = {}
    for i, name in enumerate(quantity_names):
        quantities[name] = fid.variables[name][:]
        if boundary_polygon is not None:
            #removes sts points that do not lie on boundary
            quantities[name] = num.take(quantities[name], gauge_id, axis=1)

    # Close sww, tms or sts netcdf file
    fid.close()

    from anuga.fit_interpolate.interpolate import Interpolation_function

    if not spatial:
        vertex_coordinates = triangles = interpolation_points = None
    if filename[-3:] == 'sts':  #added
        triangles = None
        #vertex coordinates is position of urs gauges

    if verbose:
        log.critical('Calling interpolation function')

    # Return Interpolation_function instance as well as
    # starttime for use to possible modify that of domain
    return (Interpolation_function(time,
                                   quantities,
                                   quantity_names,
                                   vertex_coordinates,
                                   triangles,
                                   interpolation_points,
                                   time_thinning=time_thinning,
                                   verbose=verbose,
                                   gauge_neighbour_id=gauge_neighbour_id,
                                   output_centroids=output_centroids),
            starttime)
Example #10
0
def interpolate_sww2csv(sww_file,
                        points,
                        depth_file,
                        velocity_x_file,
                        velocity_y_file,
                        stage_file=None,
                        froude_file=None,
                        time_thinning=1,
                        g=9.80665,
                        verbose=True,
                        use_cache=True):
    """
    Interpolate the quantities at a given set of locations, given
    an sww file.
    The results are written to csv files.

    sww_file is the input sww file.
    points is a list of the 'gauges' x,y location.
    depth_file is the name of the output depth file
    velocity_x_file is the name of the output x velocity file.
    velocity_y_file is the name of the output y velocity file.
    stage_file is the name of the output stage file.

    In the csv files columns represents the gauges and each row is a
    time slice.

    Time_thinning_number controls how many timesteps to use. Only
    timesteps with index%time_thinning_number == 0 will used, or
    in other words a value of 3, say, will cause the algorithm to
    use every third time step.

    In the future let points be a points file.
    And let the user choose the quantities.

    This is currently quite specific.
    If it is need to be more general, change things.
    """

    quantities = ['stage', 'elevation', 'xmomentum', 'ymomentum']
    points = ensure_absolute(points)
    point_count = len(points)
    callable_sww = file_function(sww_file,
                                 quantities=quantities,
                                 interpolation_points=points,
                                 verbose=verbose,
                                 time_thinning=time_thinning,
                                 use_cache=use_cache)

    csv_files = CSV_files(depth_file,
                          velocity_x_file,
                          velocity_y_file,
                          stage_file=stage_file,
                          froude_file=froude_file)

    # Write heading
    heading = [str(x[0]) + ':' + str(x[1]) for x in points]
    heading.insert(0, 'time')

    csv_files.write_headings(heading)
    for time in callable_sww.get_time():
        depths = [time]
        velocity_xs = [time]
        velocity_ys = [time]

        stages = [
            time
        ]  # May not be used if stage file is None, but makes code below simpler
        froudes = [
            time
        ]  # May not be used if stage file is None, but makes code below simpler

        for point_i, point in enumerate(points):
            quantities = callable_sww(time, point_i)

            w = quantities[0]
            z = quantities[1]
            momentum_x = quantities[2]
            momentum_y = quantities[3]
            depth = w - z

            if w == NAN or z == NAN or momentum_x == NAN:
                velocity_x = NAN
            else:
                if depth > epsilon:
                    velocity_x = momentum_x / depth  # Absolute velocity
                else:
                    velocity_x = 0

            if w == NAN or z == NAN or momentum_y == NAN:
                velocity_y = NAN
            else:
                if depth > epsilon:
                    velocity_y = momentum_y / depth  # Absolute velocity
                else:
                    velocity_y = 0

            if depth < epsilon:
                froude = NAN
            else:
                froude = sqrt(velocity_x * velocity_x + velocity_y *
                              velocity_y) / sqrt(depth * g)  # gravity m/s/s

            # Append values to lists
            depths.append(depth)
            velocity_xs.append(velocity_x)
            velocity_ys.append(velocity_y)
            stages.append(w)
            froudes.append(froude)

        csv_files.write_row(depths, velocity_xs, velocity_ys, stages, froudes)

    # Clean up (force the file handles inside the writers to close
    csv_files.close_all()
Example #11
0
def urs_ungridded2sww(basename_in='o', basename_out=None, verbose=False,
                      mint=None, maxt=None,
                      mean_stage=0,
                      origin=None,
                      hole_points_UTM=None,
                      zscale=1):
    """
    Convert URS C binary format for wave propagation to
    sww format native to abstract_2d_finite_volumes.

    Specify only basename_in and read files of the form
    basefilename-z-mux, basefilename-e-mux and
    basefilename-n-mux containing relative height,
    x-velocity and y-velocity, respectively.

    Also convert latitude and longitude to UTM. All coordinates are
    assumed to be given in the GDA94 datum. The latitude and longitude
    information is assumed ungridded grid.

    min's and max's: If omitted - full extend is used.
    To include a value min ans max may equal it.
    Lat and lon are assumed to be in decimal degrees.

    origin is a 3-tuple with geo referenced
    UTM coordinates (zone, easting, northing)
    It will be the origin of the sww file. This shouldn't be used,
    since all of anuga should be able to handle an arbitary origin.
    The mux point info is NOT relative to this origin.

    URS C binary format has data organised as TIME, LONGITUDE, LATITUDE
    which means that latitude is the fastest
    varying dimension (row major order, so to speak)

    In URS C binary the latitudes and longitudes are in assending order.

    Note, interpolations of the resulting sww file will be different
    from results of urs2sww.  This is due to the interpolation
    function used, and the different grid structure between urs2sww
    and this function.

    Interpolating data that has an underlying gridded source can
    easily end up with different values, depending on the underlying
    mesh.

    consider these 4 points
    50  -50

    0     0

    The grid can be
     -
    |\|   A
     -
     or;
      -
     |/|  B
      -

    If a point is just below the center of the midpoint, it will have a
    +ve value in grid A and a -ve value in grid B.
    """

    from anuga.mesh_engine.mesh_engine import NoTrianglesError
    from anuga.pmesh.mesh import Mesh

    files_in = [basename_in + WAVEHEIGHT_MUX_LABEL,
                basename_in + EAST_VELOCITY_LABEL,
                basename_in + NORTH_VELOCITY_LABEL]
    quantities = ['HA','UA','VA']

    # instantiate urs_points of the three mux files.
    mux = {}
    for quantity, file in map(None, quantities, files_in):
        mux[quantity] = Read_urs(file)

    # Could check that the depth is the same. (hashing)

    # handle to a mux file to do depth stuff
    a_mux = mux[quantities[0]]

    # Convert to utm
    lat = a_mux.lonlatdep[:,1]
    long = a_mux.lonlatdep[:,0]
    points_utm, zone = convert_from_latlon_to_utm(latitudes=lat,
                                                  longitudes=long)

    elevation = a_mux.lonlatdep[:,2] * -1

    # grid (create a mesh from the selected points)
    # This mesh has a problem.  Triangles are streched over ungridded areas.
    # If these areas could be described as holes in pmesh, that would be great.

    # I can't just get the user to selection a point in the middle.
    # A boundary is needed around these points.
    # But if the zone of points is obvious enough auto-segment should do
    # a good boundary.
    mesh = Mesh()
    mesh.add_vertices(points_utm)
    mesh.auto_segment(smooth_indents=True, expand_pinch=True)

    # To try and avoid alpha shape 'hugging' too much
    mesh.auto_segment(mesh.shape.get_alpha() * 1.1)
    if hole_points_UTM is not None:
        point = ensure_absolute(hole_points_UTM)
        mesh.add_hole(point[0], point[1])

    try:
        mesh.generate_mesh(minimum_triangle_angle=0.0, verbose=False)
    except NoTrianglesError:
        # This is a bit of a hack, going in and changing the data structure.
        mesh.holes = []
        mesh.generate_mesh(minimum_triangle_angle=0.0, verbose=False)

    mesh_dic = mesh.Mesh2MeshList()

    #mesh.export_mesh_file(basename_in + '_168.tsh')
    #import sys; sys.exit()
    # These are the times of the mux file
    mux_times = []
    for i in range(a_mux.time_step_count):
        mux_times.append(a_mux.time_step * i)
    (mux_times_start_i, mux_times_fin_i) = read_time_from_mux(mux_times, mint, maxt)
    times = mux_times[mux_times_start_i:mux_times_fin_i]

    if mux_times_start_i == mux_times_fin_i:
        # Close the mux files
        for quantity, file in map(None, quantities, files_in):
            mux[quantity].close()
        msg = "Due to mint and maxt there's no time info in the boundary SWW."
        raise Exception(msg)

    # If this raise is removed there is currently no downstream errors

    points_utm=ensure_numeric(points_utm)
    assert num.alltrue(ensure_numeric(mesh_dic['generatedpointlist'])
                       == ensure_numeric(points_utm))

    volumes = mesh_dic['generatedtrianglelist']

    # Write sww intro and grid stuff.
    if basename_out is None:
        swwname = basename_in + '.sww'
    else:
        swwname = basename_out + '.sww'

    if verbose: log.critical('Output to %s' % swwname)

    outfile = NetCDFFile(swwname, netcdf_mode_w)

    # For a different way of doing this, check out tsh2sww
    # work out sww_times and the index range this covers
    sww = Write_sww(['elevation'], ['stage', 'xmomentum', 'ymomentum'])
    sww.store_header(outfile, times, len(volumes), len(points_utm),
                     verbose=verbose, sww_precision=netcdf_float)
    outfile.mean_stage = mean_stage
    outfile.zscale = zscale

    sww.store_triangulation(outfile, points_utm, volumes,
                            zone,  
                            new_origin=origin,
                            verbose=verbose)
    sww.store_static_quantities(outfile, elevation=elevation)

    if verbose: log.critical('Converting quantities')

    # Read in a time slice from each mux file and write it to the SWW file
    j = 0
    for ha, ua, va in map(None, mux['HA'], mux['UA'], mux['VA']):
        if j >= mux_times_start_i and j < mux_times_fin_i:
            stage = zscale*ha + mean_stage
            h = stage - elevation
            xmomentum = ua*h
            ymomentum = -1 * va * h # -1 since in mux files south is positive.
            sww.store_quantities(outfile,
                                 slice_index=j-mux_times_start_i,
                                 verbose=verbose,
                                 stage=stage,
                                 xmomentum=xmomentum,
                                 ymomentum=ymomentum,
                                 sww_precision=num.float)
        j += 1

    if verbose: sww.verbose_quantities(outfile)

    outfile.close()
Example #12
0
def _fit_to_mesh(point_coordinates,
                 vertex_coordinates=None,
                 triangles=None,
                 mesh=None,
                 point_attributes=None,
                 alpha=DEFAULT_ALPHA,
                 verbose=False,
                 mesh_origin=None,
                 data_origin=None,
                 max_read_lines=None,
                 attribute_name=None,
                 cg_precon='Jacobi',
                 use_c_cg=True):
    """
    Fit a smooth surface to a triangulation,
    given data points with attributes.


        Inputs:
        vertex_coordinates: List of coordinate pairs [xi, eta] of
        points constituting a mesh (or an m x 2 numeric array or
              a geospatial object)
              Points may appear multiple times
              (e.g. if vertices have discontinuities)

          triangles: List of 3-tuples (or a numeric array) of
          integers representing indices of all vertices in the mesh.

          point_coordinates: List of coordinate pairs [x, y] of data points
          (or an nx2 numeric array). This can also be a .csv/.txt/.pts
          file name.

          alpha: Smoothing parameter.

          mesh_origin: A geo_reference object or 3-tuples consisting of
              UTM zone, easting and northing.
              If specified vertex coordinates are assumed to be
              relative to their respective origins.

          point_attributes: Vector or array of data at the
                            point_coordinates.

    """

    if mesh is None:
        # FIXME(DSG): Throw errors if triangles or vertex_coordinates
        # are None

        #Convert input to numeric arrays
        triangles = ensure_numeric(triangles, num.int)
        vertex_coordinates = ensure_absolute(vertex_coordinates,
                                             geo_reference = mesh_origin)

        if verbose:
            log.critical('_fit_to_mesh: Building mesh')
        mesh = Mesh(vertex_coordinates, triangles)

        # Don't need this as we have just created the mesh
        #mesh.check_integrity()

    interp = Fit(mesh=mesh,
                 verbose=verbose,
                 alpha=alpha,
                 cg_precon=cg_precon,
                 use_c_cg=use_c_cg)

    vertex_attributes = interp.fit(point_coordinates,
                                   point_attributes,
                                   point_origin=data_origin,
                                   max_read_lines=max_read_lines,
                                   attribute_name=attribute_name,
                                   verbose=verbose)

    # Add the value checking stuff that's in least squares.
    # Maybe this stuff should get pushed down into Fit.
    # at least be a method of Fit.
    # Or intigrate it into the fit method, saving teh max and min's
    # as att's.

    return vertex_attributes
Example #13
0
    def fit(self, point_coordinates_or_filename=None, z=None,
            verbose=False,
            point_origin=None,
            attribute_name=None,
            max_read_lines=1e7):
        """Fit a smooth surface to given 1d array of data points z.

        The smooth surface is computed at each vertex in the underlying
        mesh using the formula given in the module doc string.

        Inputs:
        point_coordinates_or_filename: The co-ordinates of the data points.
              A filename of a .pts file or a
              List of coordinate pairs [x, y] of
              data points or an nx2 numeric array or a Geospatial_data object
              or points file filename
          z: Single 1d vector or array of data at the point_coordinates.

        """
        if isinstance(point_coordinates_or_filename, basestring):
            if point_coordinates_or_filename[-4:] != ".pts":
                use_blocking_option2 = False

        # NOTE PADARN 29/03/13: File reading from C has been removed. Now 
        # the input is either a set of points, or a filename which is then
        # handled by the Geospatial_data object

        if verbose:
            print 'Fit.fit: Initializing'

        # Use blocking to load in the point info
        if isinstance(point_coordinates_or_filename, basestring):
            msg = "Don't set a point origin when reading from a file"
            assert point_origin is None, msg
            filename = point_coordinates_or_filename

            G_data = Geospatial_data(filename,
                                     max_read_lines=max_read_lines,
                                     load_file_now=False,
                                     verbose=verbose)

            for i, geo_block in enumerate(G_data):

               # Build the array
                points = geo_block.get_data_points(absolute=True)
                z = geo_block.get_attributes(attribute_name=attribute_name)

                self._build_matrix_AtA_Atz(points, z, attribute_name, verbose)

            point_coordinates = None

            if verbose:
                print ''
        else:
            point_coordinates = point_coordinates_or_filename


        # This condition either means a filename was read or the function
        # recieved a None as input
        if point_coordinates is None:
            if verbose:
                log.critical('Fit.fit: Warning: no data points in fit')
            msg = 'No interpolation matrix.'
            assert self.AtA is not None, msg
            assert self.Atz is not None


        else:
            point_coordinates = ensure_absolute(point_coordinates,
                                                geo_reference=point_origin)
            # if isinstance(point_coordinates,Geospatial_data) and z is None:
            # z will come from the geo-ref

            self._build_matrix_AtA_Atz(point_coordinates, z, verbose=verbose, output='counter')

        # Check sanity
        m = self.mesh.number_of_nodes  # Nbr of basis functions (1/vertex)
        n = self.point_count
        if n < m and self.alpha == 0.0:
            msg = 'ERROR (least_squares): Too few data points\n'
            msg += 'There are only %d data points and alpha == 0. ' % n
            msg += 'Need at least %d\n' % m
            msg += 'Alternatively, set smoothing parameter alpha to a small '
            msg += 'positive value,\ne.g. 1.0e-3.'
            raise TooFewPointsError(msg)

        self._build_coefficient_matrix_B(verbose)
        loners = self.mesh.get_lone_vertices()
        # FIXME  - make this as error message.
        # test with
        # Not_yet_test_smooth_att_to_mesh_with_excess_verts.
        if len(loners) > 0:
            msg = 'WARNING: (least_squares): \nVertices with no triangles\n'
            msg += 'All vertices should be part of a triangle.\n'
            msg += 'In the future this will be inforced.\n'
            msg += 'The following vertices are not part of a triangle;\n'
            msg += str(loners)
            log.critical(msg)

            #raise VertsWithNoTrianglesError(msg)
        return conjugate_gradient(self.B, self.Atz, self.Atz,
                                  imax=2 * len(self.Atz)+1000, use_c_cg=self.use_c_cg,
                                  precon=self.cg_precon)
Example #14
0
        # read header and determine the column numbers to read correctly.
        if i == 0:
            for j, value in enumerate(row):
                if value.strip() == 'easting': easting = j
                if value.strip() == 'northing': northing = j
                if value.strip() == 'name': name = j
                if value.strip() == 'elevation': elevation = j
        else:
            #points.append([float(row[easting]),float(row[northing])])
            points.append([float(row[easting]), float(row[northing])])
            point_name.append(row[name])

    #convert to array for file_function
    points_array = num.array(points, num.float)

    points_array = ensure_absolute(points_array)

    #print 'points_array', points_array

    dir_name, base = os.path.split(sww_file)

    #need to get current directory so when path and file
    #are "joined" below the directory is correct
    if dir_name == '':
        dir_name = getcwd()

    if access(sww_file, R_OK):
        if verbose: log.critical('File %s exists' % sww_file)
    else:
        msg = 'File "%s" could not be opened: no read permission' % sww_file
        raise Exception(msg)
def get_netcdf_file_function(filename,
                             quantity_names=None,
                             interpolation_points=None,
                             domain_starttime=None,                            
                             time_thinning=1,                 
                             time_limit=None,            
                             verbose=False,
                             boundary_polygon=None,
                             output_centroids=False):
    """Read time history of spatial data from NetCDF sww file and
    return a callable object f(t,x,y)
    which will return interpolated values based on the input file.

    Model time (domain_starttime)
    will be checked, possibly modified and returned
    
    All times are assumed to be in UTC

    See Interpolation function for further documentation
    """

    # FIXME: Check that model origin is the same as file's origin
    # (both in UTM coordinates)
    # If not - modify those from file to match domain
    # (origin should be passed in)
    # Take this code from e.g. dem2pts in data_manager.py
    # FIXME: Use geo_reference to read and write xllcorner...

    import time, calendar
    from anuga.config import time_format

    # Open NetCDF file
    if verbose: log.critical('Reading %s' % filename)

    fid = NetCDFFile(filename, netcdf_mode_r)

    if isinstance(quantity_names, basestring):
        quantity_names = [quantity_names]        

    if quantity_names is None or len(quantity_names) < 1:
        msg = 'No quantities are specified in file_function'
        raise Exception(msg)
 
    if interpolation_points is not None:

        #interpolation_points = num.array(interpolation_points, num.float)
        interpolation_points = ensure_absolute(interpolation_points)
        msg = 'Points must by N x 2. I got %d' % interpolation_points.shape[1]
        assert interpolation_points.shape[1] == 2, msg

    # Now assert that requested quantitites (and the independent ones)
    # are present in file 
    missing = []
    for quantity in ['time'] + quantity_names:
        if not fid.variables.has_key(quantity):
            missing.append(quantity)

    if len(missing) > 0:
        msg = 'Quantities %s could not be found in file %s'\
              % (str(missing), filename)
        fid.close()
        raise Exception(msg)

    # Decide whether this data has a spatial dimension
    spatial = True
    for quantity in ['x', 'y']:
        if not fid.variables.has_key(quantity):
            spatial = False

    if filename[-3:] == 'tms' and spatial is True:
        msg = 'Files of type TMS must not contain spatial information'
        raise Exception(msg)

    if filename[-3:] == 'sww' and spatial is False:
        msg = 'Files of type SWW must contain spatial information'        
        raise Exception(msg)

    if filename[-3:] == 'sts' and spatial is False:
        #What if mux file only contains one point
        msg = 'Files of type STS must contain spatial information'        
        raise Exception(msg)

    # JJ REMOVED
    #if filename[-3:] == 'sts' and boundary_polygon is None:
    #    #What if mux file only contains one point
    #    msg = 'Files of type sts require boundary polygon'        
    #    raise Exception(msg)

    # Get first timestep
    try:
        starttime = float(fid.starttime)
    except ValueError:
        msg = 'Could not read starttime from file %s' % filename
        raise Exception(msg)


    # Get variables
    # if verbose: log.critical('Get variables'    )
    time = fid.variables['time'][:]

    # FIXME(Ole): Is time monotoneous?

    # Apply time limit if requested
    upper_time_index = len(time)    
    msg = 'Time vector obtained from file %s has length 0' % filename
    assert upper_time_index > 0, msg
    
    if time_limit is not None:
        # Adjust given time limit to given start time
        time_limit = time_limit - starttime


        # Find limit point
        for i, t in enumerate(time):
            if t > time_limit:
                upper_time_index = i
                break
                
        msg = 'Time vector is zero. Requested time limit is %f' % time_limit
        assert upper_time_index > 0, msg

        if time_limit < time[-1] and verbose is True:
            log.critical('Limited time vector from %.2fs to %.2fs'
                         % (time[-1], time_limit))

    time = time[:upper_time_index]


    
    
    # Get time independent stuff
    if spatial:
        # Get origin
        #xllcorner = fid.xllcorner[0]
        #yllcorner = fid.yllcorner[0]
        #zone = fid.zone[0]

        xllcorner = fid.xllcorner
        yllcorner = fid.yllcorner
        zone = fid.zone

        x = fid.variables['x'][:]
        y = fid.variables['y'][:]
        if filename.endswith('sww'):
            triangles = fid.variables['volumes'][:]

        x = num.reshape(x, (len(x), 1))
        y = num.reshape(y, (len(y), 1))
        vertex_coordinates = num.concatenate((x, y), axis=1) #m x 2 array

        if boundary_polygon is not None:
            # Remove sts points that do not lie on boundary
            # FIXME(Ole): Why don't we just remove such points from the list of
            # points and associated data?
            # I am actually convinced we can get rid of neighbour_gauge_id
            # altogether as the sts file is produced using the ordering file.
            # All sts points are therefore always present in the boundary.
            # In fact, they *define* parts of the boundary.
            boundary_polygon=ensure_numeric(boundary_polygon)
            boundary_polygon[:, 0] -= xllcorner
            boundary_polygon[:, 1] -= yllcorner
            temp=[]
            boundary_id=[]
            gauge_id=[]
            for i in range(len(boundary_polygon)):
                for j in range(len(x)):
                    if num.allclose(vertex_coordinates[j],
                                    boundary_polygon[i], rtol=1e-4, atol=1e-4):
                        #FIXME:
                        #currently gauges lat and long is stored as float and
                        #then cast to double. This cuases slight repositioning
                        #of vertex_coordinates.
                        temp.append(boundary_polygon[i])
                        gauge_id.append(j)
                        boundary_id.append(i)
                        break
            gauge_neighbour_id=[]
            for i in range(len(boundary_id)-1):
                if boundary_id[i]+1==boundary_id[i+1]:
                    gauge_neighbour_id.append(i+1)
                else:
                    gauge_neighbour_id.append(-1)
            if boundary_id[len(boundary_id)-1]==len(boundary_polygon)-1 \
               and boundary_id[0]==0:
                gauge_neighbour_id.append(0)
            else:
                gauge_neighbour_id.append(-1)
            gauge_neighbour_id=ensure_numeric(gauge_neighbour_id)

            
            if len(num.compress(gauge_neighbour_id>=0, gauge_neighbour_id)) \
               != len(temp)-1:
                msg='incorrect number of segments'
                raise Exception(msg)
            vertex_coordinates=ensure_numeric(temp)
            if len(vertex_coordinates)==0:
                msg = 'None of the sts gauges fall on the boundary'
                raise Exception(msg)
        else:
            gauge_neighbour_id=None

        if interpolation_points is not None:
            # Adjust for georef
            interpolation_points[:, 0] -= xllcorner
            interpolation_points[:, 1] -= yllcorner        
    else:
        gauge_neighbour_id=None
        
    if domain_starttime is not None:
        # If domain_startime is *later* than starttime,
        # move time back - relative to domain's time
        if domain_starttime > starttime:
            time = time - domain_starttime + starttime

        # FIXME Use method in geo to reconcile
        # if spatial:
        # assert domain.geo_reference.xllcorner == xllcorner
        # assert domain.geo_reference.yllcorner == yllcorner
        # assert domain.geo_reference.zone == zone        
        
    if verbose:
        log.critical('File_function data obtained from: %s' % filename)
        log.critical('  References:')
        if spatial:
            log.critical('    Lower left corner: [%f, %f]'
                         % (xllcorner, yllcorner))
        log.critical('    Start time:   %f' % starttime)
        
    
    # Produce values for desired data points at
    # each timestep for each quantity
    quantities = {}
    for i, name in enumerate(quantity_names):
        quantities[name] = fid.variables[name][:]
        if boundary_polygon is not None:
            #removes sts points that do not lie on boundary
            quantities[name] = num.take(quantities[name], gauge_id, axis=1)
            
    # Close sww, tms or sts netcdf file         
    fid.close()

    from anuga.fit_interpolate.interpolate import Interpolation_function

    if not spatial:
        vertex_coordinates = triangles = interpolation_points = None
    if filename[-3:] == 'sts':#added
        triangles = None
        #vertex coordinates is position of urs gauges

    if verbose:
        log.critical('Calling interpolation function')
        
    # Return Interpolation_function instance as well as
    # starttime for use to possible modify that of domain
    return (Interpolation_function(time,
                                   quantities,
                                   quantity_names,
                                   vertex_coordinates,
                                   triangles,
                                   interpolation_points,
                                   time_thinning=time_thinning,
                                   verbose=verbose,
                                   gauge_neighbour_id=gauge_neighbour_id,
                                   output_centroids=output_centroids),
            starttime)
Example #16
0
def sww2csv_gauges(sww_file,
                   gauge_file,
                   out_name='gauge_',
                   quantities=['stage', 'depth', 'elevation',
                               'xmomentum', 'ymomentum'],
                   verbose=False,
                   use_cache=True,
                   output_centroids=False):
    """
    
    Inputs: 
        NOTE: if using csv2timeseries_graphs after creating csv file,
        it is essential to export quantities 'depth' and 'elevation'.
        'depth' is good to analyse gauges on land and elevation is used
        automatically by csv2timeseries_graphs in the legend.
        
        sww_file: path to any sww file
        
        gauge_file: Assumes that it follows this format
            name, easting, northing, elevation
            point1, 100.3, 50.2, 10.0
            point2, 10.3, 70.3, 78.0
        
        NOTE: order of column can change but names eg 'easting', 'elevation' 
        must be the same! ALL lowercaps!

        out_name: prefix for output file name (default is 'gauge_')
        
    Outputs: 
        one file for each gauge/point location in the points file. They
        will be named with this format in the same directory as the 'sww_file'
            <out_name><name>.csv
        eg gauge_point1.csv if <out_name> not supplied
           myfile_2_point1.csv if <out_name> ='myfile_2_'
            
        They will all have a header
    
    Usage: sww2csv_gauges(sww_file='test1.sww',
                          quantities = ['stage', 'elevation','depth','bearing'],
                          gauge_file='gauge.txt')    
    
    Interpolate the quantities at a given set of locations, given
    an sww file.
    The results are written to a csv file.

    In the future let points be a points file.
    And the user choose the quantities.

    This is currently quite specific.
    If it needs to be more general, change things.

    This is really returning speed, not velocity.
    """
    
    from csv import reader,writer
    from anuga.utilities.numerical_tools import ensure_numeric, mean, NAN
    import string
    from anuga.utilities.file_utils import get_all_swwfiles
    from anuga.abstract_2d_finite_volumes.util import file_function    

    assert isinstance(gauge_file,string_types) or isinstance(gauge_file, str), 'Gauge filename must be a string or unicode'
    assert isinstance(out_name,string_types) or isinstance(out_name, str), 'Output filename prefix must be a string'
    
    try:
        gid = open(gauge_file)
        point_reader = reader(gid)
        gid.close()
    except Exception as e:
        msg = 'File "%s" could not be opened: Error="%s"' % (gauge_file, e)
        raise Exception(msg)

    if verbose: log.critical('Gauges obtained from: %s' % gauge_file)
    
    gid = open(gauge_file)
    point_reader = reader(gid)

    points = []
    point_name = []
    
    # read point info from file
    for i,row in enumerate(point_reader):
        # read header and determine the column numbers to read correctly.
        if i==0:
            for j,value in enumerate(row):
                if value.strip()=='easting':easting=j
                if value.strip()=='northing':northing=j
                if value.strip()=='name':name=j
                if value.strip()=='elevation':elevation=j
        else:
            #points.append([float(row[easting]),float(row[northing])])
            points.append([float(row[easting]),float(row[northing])])
            point_name.append(row[name])
        
    gid.close()

    #convert to array for file_function
    points_array = num.array(points,num.float)
        
    points_array = ensure_absolute(points_array)

    #print 'points_array', points_array

    dir_name, base = os.path.split(sww_file)    

    #need to get current directory so when path and file
    #are "joined" below the directory is correct
    if dir_name == '':
        dir_name =getcwd()
        
    if access(sww_file,R_OK):
        if verbose: log.critical('File %s exists' % sww_file)
    else:
        msg = 'File "%s" could not be opened: no read permission' % sww_file
        raise Exception(msg)

    sww_files = get_all_swwfiles(look_in_dir=dir_name,
                                 base_name=base,
                                 verbose=verbose)

    # fudge to get SWW files in 'correct' order, oldest on the left
    sww_files.sort()

    if verbose:
        log.critical('sww files=%s' % sww_files)
    
    #to make all the quantities lower case for file_function
    quantities = [quantity.lower() for quantity in quantities]

    # what is quantities are needed from sww file to calculate output quantities
    # also 

    core_quantities = ['stage', 'elevation', 'xmomentum', 'ymomentum']

    gauge_file = out_name

    heading = [quantity for quantity in quantities]
    heading.insert(0,'time')
    heading.insert(1,'hours')
    
    if verbose: log.critical('Writing csv files')

    quake_offset_time = None

    is_opened = [False]*len(points_array)
    for sww_file in sww_files:
        sww_file = join(dir_name, sww_file+'.sww')
        callable_sww = file_function(sww_file,
                                     quantities=core_quantities,
                                     interpolation_points=points_array,
                                     verbose=verbose,
                                     use_cache=use_cache,
                                     output_centroids = output_centroids)

        if quake_offset_time is None:
            quake_offset_time = callable_sww.starttime

        for point_i, point in enumerate(points_array):
            for time in callable_sww.get_time():
                # add domain starttime to relative time.
                quake_time = time + quake_offset_time
                point_quantities = callable_sww(time, point_i) # __call__ is overridden


                if point_quantities[0] != NAN:
                    if is_opened[point_i] == False:
                        points_handle = open(dir_name + sep + gauge_file
                                             + point_name[point_i] + '.csv', 'w')
                        points_writer = writer(points_handle)
                        points_writer.writerow(heading)
                        is_opened[point_i] = True
                    else:
                        points_handle = open(dir_name + sep + gauge_file
                                             + point_name[point_i] + '.csv', 'a')
                        points_writer = writer(points_handle)


                    points_list = [quake_time, quake_time/3600.] +  _quantities2csv(quantities, point_quantities, callable_sww.centroids, point_i)
                    points_writer.writerow(points_list)
                    points_handle.close()
                else:
                    if verbose:
                        msg = 'gauge' + point_name[point_i] + 'falls off the mesh in file ' + sww_file + '.'
                        log.warning(msg)
Example #17
0
       a list or a numeric array
    """

    try:
        points = ensure_absolute(points)
    except NameError, err:
        raise NameError, err
    except:
        # If this fails it is going to be because the points can't be
        # converted to a numeric array.
        msg = 'Points could not be converted to numeric array' 
        raise Exception, msg


    try:
        polygon = ensure_absolute(polygon)
    except NameError, e:
        raise NameError, e
    except:
        # If this fails it is going to be because the points can't be
        # converted to a numeric array.
        msg = ('Polygon %s could not be converted to numeric array'
               % (str(polygon)))
        raise Exception, msg

    if len(points.shape) == 1:
        # Only one point was passed in. Convert to array of points
        points = num.reshape(points, (1,2))

    indices, count = separate_points_by_polygon(points, polygon,
                                                closed=closed,
Example #18
0
    def __init__(self,
                 time,
                 quantities,
                 quantity_names=None,
                 vertex_coordinates=None,
                 triangles=None,
                 interpolation_points=None,
                 time_thinning=1,
                 verbose=False,
                 gauge_neighbour_id=None,
                 output_centroids=False):
        """Initialise object and build spatial interpolation if required

        Time_thinning_number controls how many timesteps to use. Only timesteps
        with index%time_thinning_number == 0 will used, or in other words a
        value of 3, say, will cause the algorithm to use every third time step.
        """

        from anuga.config import time_format

        if verbose is True:
            log.critical('Interpolation_function: input checks')

        # Check temporal info
        time = ensure_numeric(time)

        if not num.alltrue(time[1:] - time[:-1] >= 0):
            # This message is time consuming to form due to the conversion of
            msg = 'Time must be a monotonuosly increasing sequence %s' % time
            raise Exception(msg)

        # Check if quantities is a single array only
        if not isinstance(quantities, dict):
            quantities = ensure_numeric(quantities)
            quantity_names = ['Attribute']

            # Make it a dictionary
            quantities = {quantity_names[0]: quantities}

        # Use keys if no names are specified
        if quantity_names is None:
            quantity_names = list(quantities.keys())

        # Check spatial info
        if vertex_coordinates is None:
            self.spatial = False
        else:
            # FIXME (Ole): Try ensure_numeric here -
            #              this function knows nothing about georefering.
            vertex_coordinates = ensure_absolute(vertex_coordinates)

            if triangles is not None:
                triangles = ensure_numeric(triangles)
            self.spatial = True

        if verbose is True:
            log.critical('Interpolation_function: thinning by %d' %
                         time_thinning)

        # Thin timesteps if needed
        # Note array() is used to make the thinned arrays contiguous in memory
        self.time = num.array(time[::time_thinning])
        for name in quantity_names:
            if len(quantities[name].shape) == 2:
                quantities[name] = num.array(
                    quantities[name][::time_thinning, :])

        if verbose is True:
            log.critical('Interpolation_function: precomputing')

        # Save for use with statistics
        self.quantities_range = {}
        for name in quantity_names:
            q = quantities[name][:].flatten()
            self.quantities_range[name] = [min(q), max(q)]

        self.quantity_names = quantity_names
        self.vertex_coordinates = vertex_coordinates
        self.interpolation_points = interpolation_points

        self.index = 0  # Initial time index
        self.precomputed_values = {}
        self.centroids = []

        # Precomputed spatial interpolation if requested
        if interpolation_points is not None:
            #no longer true. sts files have spatial = True but
            #if self.spatial is False:
            #    raise Exception('Triangles and vertex_coordinates must be specified')
            #
            try:
                self.interpolation_points = \
                    interpolation_points = ensure_numeric(interpolation_points)
            except:
                msg = 'Interpolation points must be an N x 2 numeric array ' \
                      'or a list of points\n'
                msg += 'Got: %s.' % (str(self.interpolation_points)[:60] +
                                     '...')
                raise Exception(msg)

            # Ensure 'mesh_boundary_polygon' is defined
            mesh_boundary_polygon = None

            if triangles is not None and vertex_coordinates is not None:
                # Check that all interpolation points fall within
                # mesh boundary as defined by triangles and vertex_coordinates.
                from anuga.abstract_2d_finite_volumes.neighbour_mesh import Mesh
                from anuga.geometry.polygon import outside_polygon

                # Create temporary mesh object from mesh info passed
                # into this function.
                mesh = Mesh(vertex_coordinates, triangles)
                mesh_boundary_polygon = mesh.get_boundary_polygon()

                indices = outside_polygon(interpolation_points,
                                          mesh_boundary_polygon)

                # Record result
                #self.mesh_boundary_polygon = mesh_boundary_polygon
                self.indices_outside_mesh = indices

                # Report
                if len(indices) > 0:
                    msg = 'Interpolation points in Interpolation function fall '
                    msg += 'outside specified mesh. Offending points:\n'
                    out_interp_pts = []
                    for i in indices:
                        msg += '%d: %s\n' % (i, interpolation_points[i])
                        out_interp_pts.append(
                            ensure_numeric(interpolation_points[i]))

                    if verbose is True:
                        import sys
                        from anuga.geometry.polygon import plot_polygons
                        title = ('Interpolation points fall '
                                 'outside specified mesh')
                        plot_polygons([
                            mesh_boundary_polygon, interpolation_points,
                            out_interp_pts
                        ], ['line', 'point', 'outside'],
                                      figname='points_boundary_out',
                                      label=title)

                    # Joaquim Luis suggested this as an Exception, so
                    # that the user can now what the problem is rather than
                    # looking for NaN's. However, NANs are handy as they can
                    # be ignored leaving good points for continued processing.
                    if verbose:
                        log.critical(msg)
                    #raise Exception(msg)

            elif triangles is None and vertex_coordinates is not None:  #jj
                #Dealing with sts file
                pass
            else:
                raise Exception(
                    'Sww file function requires both triangles and '
                    'vertex_coordinates. sts file file function '
                    'requires the latter.')

            # Plot boundary and interpolation points,
            # but only if if 'mesh_boundary_polygon' has data.
            if verbose is True and mesh_boundary_polygon is not None:
                import sys
                if sys.platform == 'win32':
                    from anuga.geometry.polygon import plot_polygons
                    title = ('Interpolation function: '
                             'Polygon and interpolation points')
                    plot_polygons(
                        [mesh_boundary_polygon, interpolation_points],
                        ['line', 'point'],
                        figname='points_boundary',
                        label=title)

            m = len(self.interpolation_points)
            p = len(self.time)

            for name in quantity_names:
                self.precomputed_values[name] = num.zeros((p, m), num.float)

            if verbose is True:
                log.critical('Build interpolator')

            # Build interpolator
            if triangles is not None and vertex_coordinates is not None:
                if verbose:
                    msg = 'Building interpolation matrix from source mesh '
                    msg += '(%d vertices, %d triangles)' \
                           % (vertex_coordinates.shape[0],
                              triangles.shape[0])
                    log.critical(msg)

                # This one is no longer needed for STS files
                interpol = Interpolate(vertex_coordinates,
                                       triangles,
                                       verbose=verbose)

            elif triangles is None and vertex_coordinates is not None:
                if verbose:
                    log.critical('Interpolation from STS file')

            if verbose:
                log.critical(
                    'Interpolating (%d interpolation points, %d timesteps).' %
                    (self.interpolation_points.shape[0], self.time.shape[0]))

                if time_thinning > 1:
                    log.critical('Timesteps were thinned by a factor of %d' %
                                 time_thinning)
                else:
                    log.critical()

            for i, t in enumerate(self.time):
                # Interpolate quantities at this timestep
                #if verbose and i%((p+10)/10) == 0:
                if verbose:
                    log.critical('  time step %d of %d' % (i, p))

                for name in quantity_names:
                    if len(quantities[name].shape) == 2:
                        Q = quantities[name][i, :]  # Quantities at timestep i
                    else:
                        Q = quantities[name][:]  # No time dependency

                    #if verbose and i%((p+10)/10) == 0:
                    if verbose:
                        log.critical('    quantity %s, size=%d' %
                                     (name, len(Q)))

                    # Interpolate
                    if triangles is not None and vertex_coordinates is not None:
                        result = interpol.interpolate(Q,
                                                      point_coordinates=\
                                                      self.interpolation_points,
                                                      verbose=False,
                                                      output_centroids=output_centroids)
                        self.centroids = interpol.centroids
                    elif triangles is None and vertex_coordinates is not None:
                        result = interpolate_polyline(Q,
                                                      vertex_coordinates,
                                                      gauge_neighbour_id,
                                                      interpolation_points=\
                                                          self.interpolation_points)

                    #assert len(result), len(interpolation_points)
                    self.precomputed_values[name][i, :] = result

            # Report
            if verbose:
                log.critical(self.statistics())
        else:
            # Store quantitites as is
            for name in quantity_names:
                self.precomputed_values[name] = quantities[name]
Example #19
0
        # read header and determine the column numbers to read correctly.
        if i==0:
            for j,value in enumerate(row):
                if value.strip()=='easting':easting=j
                if value.strip()=='northing':northing=j
                if value.strip()=='name':name=j
                if value.strip()=='elevation':elevation=j
        else:
            #points.append([float(row[easting]),float(row[northing])])
            points.append([float(row[easting]),float(row[northing])])
            point_name.append(row[name])
        
    #convert to array for file_function
    points_array = num.array(points,num.float)
        
    points_array = ensure_absolute(points_array)

    #print 'points_array', points_array

    dir_name, base = os.path.split(sww_file)    

    #need to get current directory so when path and file
    #are "joined" below the directory is correct
    if dir_name == '':
        dir_name =getcwd()
        
    if access(sww_file,R_OK):
        if verbose: log.critical('File %s exists' % sww_file)
    else:
        msg = 'File "%s" could not be opened: no read permission' % sww_file
        raise Exception(msg)
Example #20
0
    def fit(self,
            point_coordinates_or_filename=None,
            z=None,
            verbose=False,
            point_origin=None,
            attribute_name=None,
            max_read_lines=1e7):
        """Fit a smooth surface to given 1d array of data points z.

        The smooth surface is computed at each vertex in the underlying
        mesh using the formula given in the module doc string.

        Inputs:
        point_coordinates_or_filename: The co-ordinates of the data points.
              A filename of a .pts file or a
              List of coordinate pairs [x, y] of
              data points or an nx2 numeric array or a Geospatial_data object
              or points file filename
          z: Single 1d vector or array of data at the point_coordinates.

        """
        if isinstance(point_coordinates_or_filename, basestring):
            if point_coordinates_or_filename[-4:] != ".pts":
                use_blocking_option2 = False

        # NOTE PADARN 29/03/13: File reading from C has been removed. Now
        # the input is either a set of points, or a filename which is then
        # handled by the Geospatial_data object

        if verbose:
            print 'Fit.fit: Initializing'

        # Use blocking to load in the point info
        if isinstance(point_coordinates_or_filename, basestring):
            msg = "Don't set a point origin when reading from a file"
            assert point_origin is None, msg
            filename = point_coordinates_or_filename

            G_data = Geospatial_data(filename,
                                     max_read_lines=max_read_lines,
                                     load_file_now=False,
                                     verbose=verbose)

            for i, geo_block in enumerate(G_data):

                # Build the array
                points = geo_block.get_data_points(absolute=True)
                z = geo_block.get_attributes(attribute_name=attribute_name)

                self._build_matrix_AtA_Atz(points, z, attribute_name, verbose)

            point_coordinates = None

            if verbose:
                print ''
        else:
            point_coordinates = point_coordinates_or_filename

        # This condition either means a filename was read or the function
        # recieved a None as input
        if point_coordinates is None:
            if verbose:
                log.critical('Fit.fit: Warning: no data points in fit')
            msg = 'No interpolation matrix.'
            assert self.AtA is not None, msg
            assert self.Atz is not None

        else:
            point_coordinates = ensure_absolute(point_coordinates,
                                                geo_reference=point_origin)
            # if isinstance(point_coordinates,Geospatial_data) and z is None:
            # z will come from the geo-ref

            self._build_matrix_AtA_Atz(point_coordinates,
                                       z,
                                       verbose=verbose,
                                       output='counter')

        # Check sanity
        m = self.mesh.number_of_nodes  # Nbr of basis functions (1/vertex)
        n = self.point_count
        if n < m and self.alpha == 0.0:
            msg = 'ERROR (least_squares): Too few data points\n'
            msg += 'There are only %d data points and alpha == 0. ' % n
            msg += 'Need at least %d\n' % m
            msg += 'Alternatively, set smoothing parameter alpha to a small '
            msg += 'positive value,\ne.g. 1.0e-3.'
            raise TooFewPointsError(msg)

        self._build_coefficient_matrix_B(verbose)
        loners = self.mesh.get_lone_vertices()
        # FIXME  - make this as error message.
        # test with
        # Not_yet_test_smooth_att_to_mesh_with_excess_verts.
        if len(loners) > 0:
            msg = 'WARNING: (least_squares): \nVertices with no triangles\n'
            msg += 'All vertices should be part of a triangle.\n'
            msg += 'In the future this will be inforced.\n'
            msg += 'The following vertices are not part of a triangle;\n'
            msg += str(loners)
            log.critical(msg)

            #raise VertsWithNoTrianglesError(msg)
        return conjugate_gradient(self.B,
                                  self.Atz,
                                  self.Atz,
                                  imax=2 * len(self.Atz) + 1000,
                                  use_c_cg=self.use_c_cg,
                                  precon=self.cg_precon)
    def __init__(self,
                 vertex_coordinates=None,
                 triangles=None,
                 mesh=None,
                 mesh_origin=None,
                 verbose=False):
        """ Build interpolation matrix mapping from
        function values at vertices to function values at data points

        Pass in a mesh instance or vertex_coordinates and triangles
        and optionally mesh_origin
        
        Inputs:

          vertex_coordinates: List of coordinate pairs [xi, eta] of
          points constituting a mesh (or an m x 2 numeric array or
              a geospatial object)
              Points may appear multiple times
              (e.g. if vertices have discontinuities)

          triangles: List of 3-tuples (or a numeric array) of
              integers representing indices of all vertices in the mesh.

        mesh: A mesh instance describing the mesh.

          mesh_origin: A geo_reference object or 3-tuples consisting of
              UTM zone, easting and northing.
              If specified vertex coordinates are assumed to be
              relative to their respective origins.

          Note: Don't supply a vertex coords as a geospatial object and
              a mesh origin, since geospatial has its own mesh origin.
        """

        # NOTE PADARN: The Fit_Interpolate class now uses a the c based
        # quad tree to store triangles, rather than the python based tree.
        # The tree is still stored at self.root. However, the subtrees of
        # the new quad tree can not be directly accessed by python as
        # was previously possible.
        # Most of the previous functionality has been preserved.

        global build_quadtree_time
        if mesh is None:
            if vertex_coordinates is not None and triangles is not None:
                # Fixme (DSG) Throw errors if triangles or vertex_coordinates
                # are None

                # Convert input to numeric arrays
                triangles = ensure_numeric(triangles, num.int)
                vertex_coordinates = ensure_absolute(vertex_coordinates,
                                                     geo_reference=mesh_origin)

                if verbose:
                    log.critical('FitInterpolate: Building mesh')

                self.mesh = Mesh(vertex_coordinates, triangles)

                #self.mesh.check_integrity() # Time consuming
            else:
                self.mesh = None
        else:
            self.mesh = mesh

        if self.mesh is not None:
            if verbose:
                log.critical('FitInterpolate: Building quad tree')
            #This stores indices of vertices
            t0 = time.time()

            self.root = MeshQuadtree(self.mesh, verbose=verbose)
            build_quadtree_time = time.time() - t0
def calc_max_depth_and_momentum(sww_base_name, points,
                                ground_floor_height=0.0,
                                verbose=True,
                                 use_cache = True):
    """
    Calculate the maximum inundation height above ground floor for a list
    of locations.

    The inundation value is in the range -ground_floor_height to
    overflow errors.

    These calculations are done over all the sww files with the sww_base_name
    in the specified directory.
    """

    quantities =  ['stage', 'elevation', 'xmomentum', 'ymomentum']
    points = ensure_absolute(points)
    point_count = len(points)

    # initialise the max lists
    max_depths = [-ground_floor_height]*point_count
    max_momentums = [-ground_floor_height]*point_count
    
    # How many sww files are there?
    dir, base = os.path.split(sww_base_name)
    if base[-4:] == '.sww':
        base = base[:-4]
    if dir == "": dir = "." # Unix compatibility
    dir_ls = os.listdir(dir)
    interate_over = [x for x in dir_ls if base in x and x[-4:] == '.sww']
    if len(interate_over) == 0:
        msg = 'No files of the base name %s.'\
              %(sww_base_name)
        raise IOError, msg
    from os import sep

    for this_sww_file in interate_over:
        callable_sww = file_function(dir+sep+this_sww_file,
                                     quantities=quantities,
                                     interpolation_points=points,
                                     verbose=verbose,
                                     use_cache=use_cache)

        for point_i, point in enumerate(points):
            for time in callable_sww.get_time():
                quantity_values = callable_sww(time,point_i)
                w = quantity_values[0]
                z = quantity_values[1]
                uh = quantity_values[2] 
                vh = quantity_values[3]

                #print w,z,uh,vh
                if w == NAN or z == NAN or uh == NAN or vh == NAN:
                    continue
                    
                #  -ground_floor_height is the minimum value.
                depth = w - z - ground_floor_height
              
                if depth > max_depths[point_i]:
                    max_depths[point_i] = depth
                
                momentum = sqrt(uh*uh + vh*vh)
                if momentum > max_momentums[point_i]:
                    max_momentums[point_i] = momentum


    return max_depths, max_momentums
def interpolate_sww2csv(sww_file,
                        points,
                        depth_file,
                        velocity_x_file,
                        velocity_y_file,
                        stage_file=None,
                        froude_file=None,
                        time_thinning=1,
                        g = 9.80665,
                        verbose=True,
                        use_cache = True):
    """
    Interpolate the quantities at a given set of locations, given
    an sww file.
    The results are written to csv files.

    sww_file is the input sww file.
    points is a list of the 'gauges' x,y location.
    depth_file is the name of the output depth file
    velocity_x_file is the name of the output x velocity file.
    velocity_y_file is the name of the output y velocity file.
    stage_file is the name of the output stage file.

    In the csv files columns represents the gauges and each row is a
    time slice.

    Time_thinning_number controls how many timesteps to use. Only
    timesteps with index%time_thinning_number == 0 will used, or
    in other words a value of 3, say, will cause the algorithm to
    use every third time step.

    In the future let points be a points file.
    And let the user choose the quantities.

    This is currently quite specific.
    If it is need to be more general, change things.
    """

    quantities =  ['stage', 'elevation', 'xmomentum', 'ymomentum']
    points = ensure_absolute(points)
    point_count = len(points)
    callable_sww = file_function(sww_file,
                                 quantities=quantities,
                                 interpolation_points=points,
                                 verbose=verbose,
                                 time_thinning=time_thinning,
                                 use_cache=use_cache)

    depth_writer = writer(file(depth_file, "wb"))
    velocity_x_writer = writer(file(velocity_x_file, "wb"))
    velocity_y_writer = writer(file(velocity_y_file, "wb"))
    if stage_file is not None:
        stage_writer = writer(file(stage_file, "wb"))
    if froude_file is not None:
        froude_writer = writer(file(froude_file, "wb"))

    # Write heading
    heading = [str(x[0])+ ':' + str(x[1]) for x in points]
    heading.insert(0, "time")
    depth_writer.writerow(heading)
    velocity_x_writer.writerow(heading)
    velocity_y_writer.writerow(heading)
    if stage_file is not None:
        stage_writer.writerow(heading)
    if froude_file is not None:
        froude_writer.writerow(heading)

    for time in callable_sww.get_time():
        depths = [time]
        velocity_xs = [time]
        velocity_ys = [time]
        if stage_file is not None:
            stages = [time]
        if froude_file is not None:
            froudes = [time]
        for point_i, point in enumerate(points):
            quantities = callable_sww(time,point_i)

            w = quantities[0]
            z = quantities[1]
            momentum_x = quantities[2]
            momentum_y = quantities[3]
            depth = w - z

            if w == NAN or z == NAN or momentum_x == NAN:
                velocity_x = NAN
            else:
                if depth > 1.e-30: # use epsilon
                    velocity_x = momentum_x / depth  #Absolute velocity
                else:
                    velocity_x = 0

            if w == NAN or z == NAN or momentum_y == NAN:
                velocity_y = NAN
            else:
                if depth > 1.e-30: # use epsilon
                    velocity_y = momentum_y / depth  #Absolute velocity
                else:
                    velocity_y = 0

            if depth < 1.e-30: # use epsilon
                froude = NAN
            else:

                froude = sqrt(velocity_x*velocity_x + velocity_y*velocity_y)/ \
                         sqrt(depth * g) # gravity m/s/s

            depths.append(depth)
            velocity_xs.append(velocity_x)
            velocity_ys.append(velocity_y)

            if stage_file is not None:
                stages.append(w)
            if froude_file is not None:
                froudes.append(froude)

        depth_writer.writerow(depths)
        velocity_x_writer.writerow(velocity_xs)
        velocity_y_writer.writerow(velocity_ys)

        if stage_file is not None:
            stage_writer.writerow(stages)
        if froude_file is not None:
            froude_writer.writerow(froudes)
Example #24
0
def calc_max_depth_and_momentum(sww_base_name,
                                points,
                                ground_floor_height=0.0,
                                verbose=True,
                                use_cache=True):
    """
    Calculate the maximum inundation height above ground floor for a list
    of locations.

    The inundation value is in the range -ground_floor_height to
    overflow errors.

    These calculations are done over all the sww files with the sww_base_name
    in the specified directory.
    """

    quantities = ['stage', 'elevation', 'xmomentum', 'ymomentum']
    points = ensure_absolute(points)
    point_count = len(points)

    # initialise the max lists
    max_depths = [-ground_floor_height] * point_count
    max_momentums = [-ground_floor_height] * point_count

    # How many sww files are there?
    dir, base = os.path.split(sww_base_name)
    if base[-4:] == '.sww':
        base = base[:-4]
    if dir == "": dir = "."  # Unix compatibility
    dir_ls = os.listdir(dir)
    interate_over = [x for x in dir_ls if base in x and x[-4:] == '.sww']
    if len(interate_over) == 0:
        msg = 'No files of the base name %s.'\
              %(sww_base_name)
        raise IOError, msg
    from os import sep

    for this_sww_file in interate_over:
        callable_sww = file_function(dir + sep + this_sww_file,
                                     quantities=quantities,
                                     interpolation_points=points,
                                     verbose=verbose,
                                     use_cache=use_cache)

        for point_i, point in enumerate(points):
            for time in callable_sww.get_time():
                quantity_values = callable_sww(time, point_i)
                w = quantity_values[0]
                z = quantity_values[1]
                uh = quantity_values[2]
                vh = quantity_values[3]

                #print w,z,uh,vh
                if w == NAN or z == NAN or uh == NAN or vh == NAN:
                    continue

                #  -ground_floor_height is the minimum value.
                depth = w - z - ground_floor_height

                if depth > max_depths[point_i]:
                    max_depths[point_i] = depth

                momentum = sqrt(uh * uh + vh * vh)
                if momentum > max_momentums[point_i]:
                    max_momentums[point_i] = momentum

    return max_depths, max_momentums
    def __init__(self,
                 time,
                 quantities,
                 quantity_names=None,
                 vertex_coordinates=None,
                 triangles=None,
                 interpolation_points=None,
                 time_thinning=1,
                 verbose=False,
                 gauge_neighbour_id=None,
                 output_centroids=False):
        """Initialise object and build spatial interpolation if required

        Time_thinning_number controls how many timesteps to use. Only timesteps
        with index%time_thinning_number == 0 will used, or in other words a
        value of 3, say, will cause the algorithm to use every third time step.
        """

        from anuga.config import time_format

        if verbose is True:
            log.critical('Interpolation_function: input checks')

        # Check temporal info
        time = ensure_numeric(time)

        if not num.alltrue(time[1:] - time[:-1] >= 0):
            # This message is time consuming to form due to the conversion of
            msg = 'Time must be a monotonuosly increasing sequence %s' % time
            raise Exception(msg)

        # Check if quantities is a single array only
        if not isinstance(quantities, dict):
            quantities = ensure_numeric(quantities)
            quantity_names = ['Attribute']

            # Make it a dictionary
            quantities = {quantity_names[0]: quantities}

        # Use keys if no names are specified
        if quantity_names is None:
            quantity_names = quantities.keys()

        # Check spatial info
        if vertex_coordinates is None:
            self.spatial = False
        else:
            # FIXME (Ole): Try ensure_numeric here -
            #              this function knows nothing about georefering.
            vertex_coordinates = ensure_absolute(vertex_coordinates)

            if triangles is not None:
                triangles = ensure_numeric(triangles)
            self.spatial = True

        if verbose is True:
            log.critical('Interpolation_function: thinning by %d'
                         % time_thinning)


        # Thin timesteps if needed
        # Note array() is used to make the thinned arrays contiguous in memory
        self.time = num.array(time[::time_thinning])
        for name in quantity_names:
            if len(quantities[name].shape) == 2:
                quantities[name] = num.array(quantities[name][::time_thinning,:])

        if verbose is True:
            log.critical('Interpolation_function: precomputing')

        # Save for use with statistics
        self.quantities_range = {}
        for name in quantity_names:
            q = quantities[name][:].flatten()
            self.quantities_range[name] = [min(q), max(q)]

        self.quantity_names = quantity_names
        self.vertex_coordinates = vertex_coordinates
        self.interpolation_points = interpolation_points

        self.index = 0    # Initial time index
        self.precomputed_values = {}
        self.centroids = []

        # Precomputed spatial interpolation if requested
        if interpolation_points is not None:
            #no longer true. sts files have spatial = True but
            #if self.spatial is False:
            #    raise Exception('Triangles and vertex_coordinates must be specified')
            #
            try:
                self.interpolation_points = \
                    interpolation_points = ensure_numeric(interpolation_points)
            except:
                msg = 'Interpolation points must be an N x 2 numeric array ' \
                      'or a list of points\n'
                msg += 'Got: %s.' %(str(self.interpolation_points)[:60] + '...')
                raise Exception(msg)

            # Ensure 'mesh_boundary_polygon' is defined
            mesh_boundary_polygon = None
            
            if triangles is not None and vertex_coordinates is not None:
                # Check that all interpolation points fall within
                # mesh boundary as defined by triangles and vertex_coordinates.
                from anuga.abstract_2d_finite_volumes.neighbour_mesh import Mesh
                from anuga.geometry.polygon import outside_polygon

                # Create temporary mesh object from mesh info passed
                # into this function.
                mesh = Mesh(vertex_coordinates, triangles)
                mesh_boundary_polygon = mesh.get_boundary_polygon()

                indices = outside_polygon(interpolation_points,
                                          mesh_boundary_polygon)

                # Record result
                #self.mesh_boundary_polygon = mesh_boundary_polygon
                self.indices_outside_mesh = indices

                # Report
                if len(indices) > 0:
                    msg = 'Interpolation points in Interpolation function fall '
                    msg += 'outside specified mesh. Offending points:\n'
                    out_interp_pts = []
                    for i in indices:
                        msg += '%d: %s\n' % (i, interpolation_points[i])
                        out_interp_pts.append(
                                    ensure_numeric(interpolation_points[i]))

                    if verbose is True:
                        import sys
                        from anuga.geometry.polygon import plot_polygons
                        title = ('Interpolation points fall '
                                 'outside specified mesh')
                        plot_polygons([mesh_boundary_polygon,
                                       interpolation_points,
                                       out_interp_pts],
                                      ['line', 'point', 'outside'],
                                      figname='points_boundary_out',
                                      label=title)

                    # Joaquim Luis suggested this as an Exception, so
                    # that the user can now what the problem is rather than
                    # looking for NaN's. However, NANs are handy as they can
                    # be ignored leaving good points for continued processing.
                    if verbose:
                        log.critical(msg)
                    #raise Exception(msg)

            elif triangles is None and vertex_coordinates is not None:    #jj
                #Dealing with sts file
                pass
            else:
                raise Exception('Sww file function requires both triangles and '
                                'vertex_coordinates. sts file file function '
                                'requires the latter.')

            # Plot boundary and interpolation points,
            # but only if if 'mesh_boundary_polygon' has data.
            if verbose is True and mesh_boundary_polygon is not None:
                import sys
                if sys.platform == 'win32':
                    from anuga.geometry.polygon import plot_polygons
                    title = ('Interpolation function: '
                             'Polygon and interpolation points')
                    plot_polygons([mesh_boundary_polygon,
                                   interpolation_points],
                                  ['line', 'point'],
                                  figname='points_boundary',
                                  label=title)

            m = len(self.interpolation_points)
            p = len(self.time)

            for name in quantity_names:
                self.precomputed_values[name] = num.zeros((p, m), num.float)

            if verbose is True:
                log.critical('Build interpolator')


            # Build interpolator
            if triangles is not None and vertex_coordinates is not None:
                if verbose:
                    msg = 'Building interpolation matrix from source mesh '
                    msg += '(%d vertices, %d triangles)' \
                           % (vertex_coordinates.shape[0],
                              triangles.shape[0])
                    log.critical(msg)

                # This one is no longer needed for STS files
                interpol = Interpolate(vertex_coordinates,
                                       triangles,
                                       verbose=verbose)

            elif triangles is None and vertex_coordinates is not None:
                if verbose:
                    log.critical('Interpolation from STS file')



            if verbose:
                log.critical('Interpolating (%d interpolation points, %d timesteps).'
                             % (self.interpolation_points.shape[0], self.time.shape[0]))

                if time_thinning > 1:
                    log.critical('Timesteps were thinned by a factor of %d'
                                 % time_thinning)
                else:
                    log.critical()

            for i, t in enumerate(self.time):
                # Interpolate quantities at this timestep
                #if verbose and i%((p+10)/10) == 0:
                if verbose:
                    log.critical('  time step %d of %d' % (i, p))

                for name in quantity_names:
                    if len(quantities[name].shape) == 2:
                        Q = quantities[name][i,:] # Quantities at timestep i
                    else:
                        Q = quantities[name][:]   # No time dependency

                    #if verbose and i%((p+10)/10) == 0:
                    if verbose:
                        log.critical('    quantity %s, size=%d' % (name, len(Q)))

                    # Interpolate
                    if triangles is not None and vertex_coordinates is not None:
                        result = interpol.interpolate(Q,
                                                      point_coordinates=\
                                                      self.interpolation_points,
                                                      verbose=False,
                                                      output_centroids=output_centroids)
                        self.centroids = interpol.centroids                                                          
                    elif triangles is None and vertex_coordinates is not None:
                        result = interpolate_polyline(Q,
                                                      vertex_coordinates,
                                                      gauge_neighbour_id,
                                                      interpolation_points=\
                                                          self.interpolation_points)

                    #assert len(result), len(interpolation_points)
                    self.precomputed_values[name][i, :] = result                                    
                    
            # Report
            if verbose:
                log.critical(self.statistics())            
        else:
            # Store quantitites as is
            for name in quantity_names:
                self.precomputed_values[name] = quantities[name]
Example #26
0
def urs_ungridded2sww(basename_in='o',
                      basename_out=None,
                      verbose=False,
                      mint=None,
                      maxt=None,
                      mean_stage=0,
                      origin=None,
                      hole_points_UTM=None,
                      zscale=1):
    """
    Convert URS C binary format for wave propagation to
    sww format native to abstract_2d_finite_volumes.

    Specify only basename_in and read files of the form
    basefilename-z-mux, basefilename-e-mux and
    basefilename-n-mux containing relative height,
    x-velocity and y-velocity, respectively.

    Also convert latitude and longitude to UTM. All coordinates are
    assumed to be given in the GDA94 datum. The latitude and longitude
    information is assumed ungridded grid.

    min's and max's: If omitted - full extend is used.
    To include a value min ans max may equal it.
    Lat and lon are assumed to be in decimal degrees.

    origin is a 3-tuple with geo referenced
    UTM coordinates (zone, easting, northing)
    It will be the origin of the sww file. This shouldn't be used,
    since all of anuga should be able to handle an arbitary origin.
    The mux point info is NOT relative to this origin.

    URS C binary format has data organised as TIME, LONGITUDE, LATITUDE
    which means that latitude is the fastest
    varying dimension (row major order, so to speak)

    In URS C binary the latitudes and longitudes are in assending order.

    Note, interpolations of the resulting sww file will be different
    from results of urs2sww.  This is due to the interpolation
    function used, and the different grid structure between urs2sww
    and this function.

    Interpolating data that has an underlying gridded source can
    easily end up with different values, depending on the underlying
    mesh.

    consider these 4 points
    50  -50

    0     0

    The grid can be
     -
    |\|   A
     -
     or;
      -
     |/|  B
      -

    If a point is just below the center of the midpoint, it will have a
    +ve value in grid A and a -ve value in grid B.
    """

    from anuga.mesh_engine.mesh_engine import NoTrianglesError
    from anuga.pmesh.mesh import Mesh

    files_in = [
        basename_in + WAVEHEIGHT_MUX_LABEL, basename_in + EAST_VELOCITY_LABEL,
        basename_in + NORTH_VELOCITY_LABEL
    ]
    quantities = ['HA', 'UA', 'VA']

    # instantiate urs_points of the three mux files.
    mux = {}
    for quantity, file in zip(quantities, files_in):
        mux[quantity] = Read_urs(file)

    # Could check that the depth is the same. (hashing)

    # handle to a mux file to do depth stuff
    a_mux = mux[quantities[0]]

    # Convert to utm
    lat = a_mux.lonlatdep[:, 1]
    long = a_mux.lonlatdep[:, 0]
    points_utm, zone = convert_from_latlon_to_utm(latitudes=lat,
                                                  longitudes=long)

    elevation = a_mux.lonlatdep[:, 2] * -1

    # grid (create a mesh from the selected points)
    # This mesh has a problem.  Triangles are streched over ungridded areas.
    # If these areas could be described as holes in pmesh, that would be great.

    # I can't just get the user to selection a point in the middle.
    # A boundary is needed around these points.
    # But if the zone of points is obvious enough auto-segment should do
    # a good boundary.
    mesh = Mesh()
    mesh.add_vertices(points_utm)
    mesh.auto_segment(smooth_indents=True, expand_pinch=True)

    # To try and avoid alpha shape 'hugging' too much
    mesh.auto_segment(mesh.shape.get_alpha() * 1.1)
    if hole_points_UTM is not None:
        point = ensure_absolute(hole_points_UTM)
        mesh.add_hole(point[0], point[1])

    try:
        mesh.generate_mesh(minimum_triangle_angle=0.0, verbose=False)
    except NoTrianglesError:
        # This is a bit of a hack, going in and changing the data structure.
        mesh.holes = []
        mesh.generate_mesh(minimum_triangle_angle=0.0, verbose=False)

    mesh_dic = mesh.Mesh2MeshList()

    #mesh.export_mesh_file(basename_in + '_168.tsh')
    #import sys; sys.exit()
    # These are the times of the mux file
    mux_times = []
    for i in range(a_mux.time_step_count):
        mux_times.append(a_mux.time_step * i)
    (mux_times_start_i,
     mux_times_fin_i) = read_time_from_mux(mux_times, mint, maxt)
    times = mux_times[mux_times_start_i:mux_times_fin_i]

    if mux_times_start_i == mux_times_fin_i:
        # Close the mux files
        for quantity, file in zip(quantities, files_in):
            mux[quantity].close()
        msg = "Due to mint and maxt there's no time info in the boundary SWW."
        raise Exception(msg)

    # If this raise is removed there is currently no downstream errors

    points_utm = ensure_numeric(points_utm)
    assert num.alltrue(
        ensure_numeric(mesh_dic['generatedpointlist']) == ensure_numeric(
            points_utm))

    volumes = mesh_dic['generatedtrianglelist']

    # Write sww intro and grid stuff.
    if basename_out is None:
        swwname = basename_in + '.sww'
    else:
        swwname = basename_out + '.sww'

    if verbose: log.critical('Output to %s' % swwname)

    outfile = NetCDFFile(swwname, netcdf_mode_w)

    # For a different way of doing this, check out tsh2sww
    # work out sww_times and the index range this covers
    sww = Write_sww(['elevation'], ['stage', 'xmomentum', 'ymomentum'])
    sww.store_header(outfile,
                     times,
                     len(volumes),
                     len(points_utm),
                     verbose=verbose,
                     sww_precision=netcdf_float)
    outfile.mean_stage = mean_stage
    outfile.zscale = zscale

    sww.store_triangulation(outfile,
                            points_utm,
                            volumes,
                            zone,
                            new_origin=origin,
                            verbose=verbose)
    sww.store_static_quantities(outfile, elevation=elevation)

    if verbose: log.critical('Converting quantities')

    # Read in a time slice from each mux file and write it to the SWW file
    j = 0
    for ha, ua, va in zip(mux['HA'], mux['UA'], mux['VA']):
        if j >= mux_times_start_i and j < mux_times_fin_i:
            stage = zscale * ha + mean_stage
            h = stage - elevation
            xmomentum = ua * h
            ymomentum = -1 * va * h  # -1 since in mux files south is positive.
            sww.store_quantities(outfile,
                                 slice_index=j - mux_times_start_i,
                                 verbose=verbose,
                                 stage=stage,
                                 xmomentum=xmomentum,
                                 ymomentum=ymomentum,
                                 sww_precision=num.float)
        j += 1

    if verbose: sww.verbose_quantities(outfile)

    outfile.close()
    def __init__(self,
                 vertex_coordinates=None,
                 triangles=None,
                 mesh=None,
                 mesh_origin=None,
                 verbose=False):


        """ Build interpolation matrix mapping from
        function values at vertices to function values at data points

        Pass in a mesh instance or vertex_coordinates and triangles
        and optionally mesh_origin
        
        Inputs:

          vertex_coordinates: List of coordinate pairs [xi, eta] of
          points constituting a mesh (or an m x 2 numeric array or
              a geospatial object)
              Points may appear multiple times
              (e.g. if vertices have discontinuities)

          triangles: List of 3-tuples (or a numeric array) of
              integers representing indices of all vertices in the mesh.

        mesh: A mesh instance describing the mesh.

          mesh_origin: A geo_reference object or 3-tuples consisting of
              UTM zone, easting and northing.
              If specified vertex coordinates are assumed to be
              relative to their respective origins.

          Note: Don't supply a vertex coords as a geospatial object and
              a mesh origin, since geospatial has its own mesh origin.
        """

        # NOTE PADARN: The Fit_Interpolate class now uses a the c based
        # quad tree to store triangles, rather than the python based tree.
        # The tree is still stored at self.root. However, the subtrees of
        # the new quad tree can not be directly accessed by python as 
        # was previously possible.
        # Most of the previous functionality has been preserved.

        global build_quadtree_time
        if mesh is None:
            if vertex_coordinates is not None and triangles is not None:
                # Fixme (DSG) Throw errors if triangles or vertex_coordinates
                # are None

                # Convert input to numeric arrays
                triangles = ensure_numeric(triangles, num.int)
                vertex_coordinates = ensure_absolute(vertex_coordinates,
                                                 geo_reference=mesh_origin)

                if verbose:
                    log.critical('FitInterpolate: Building mesh')
					

                self.mesh = Mesh(vertex_coordinates, triangles)

                #self.mesh.check_integrity() # Time consuming
            else:
                self.mesh = None
        else:
            self.mesh = mesh

        if self.mesh is not None:
            if verbose:
                log.critical('FitInterpolate: Building quad tree')
            #This stores indices of vertices
            t0 = time.time()

            self.root = MeshQuadtree(self.mesh, verbose=verbose)
            build_quadtree_time = time.time() - t0