Ejemplo n.º 1
0
    def get_data_for_linestring(self, wkb, crs, size):
        """ Profile code. """
        # Consider an envelope slightly larger than the lines envelope.
        length = wkb.Length()
        geometry = vectors.Geometry(wkb.Buffer(length / 100))
        envelope = geometry.envelope
        extent = geometry.extent
        span = geometry.size

        # Now, based on size and span, determine optimal dataset layout.
        cellsize = length / size
        gridsize = tuple(int(math.ceil(s / cellsize)) for s in span)
        x1, y1, x2, y2 = extent

        # Determine indices for one point per pixel on the line
        wkbpoints = wkb.ExportToWkb()[9:]
        vertices = np.fromstring(wkbpoints).byteswap().reshape(-1, 2)
        magicline = vectors.MagicLine(vertices).pixelize(cellsize)
        origin = np.array([x1, y2])
        points = magicline.centers
        indices = tuple(np.uint64(
            (points - origin) / cellsize * np.array([1, -1]),
        ).transpose())[::-1]

        # Get the values from the array
        values = self.get_data_for_polygon(crs=crs,
                                           wkb=envelope,
                                           size=gridsize)[0][indices]

        # make array with distance from origin (x values for graph)
        magnitudes = vectors.magnitude(magicline.vectors)
        distances = magnitudes.cumsum() - magnitudes[0] / 2

        return distances, values
Ejemplo n.º 2
0
def get_response_for_getprofile(get_parameters):
    """ Return json with profile. """
    # This request features a point, but an bbox is needed for reprojection.
    # Note that GetEnvelope() returns x1, x2, y1, y2 but bbox is x1, y1, x2, y2
    geometry = ogr.CreateGeometryFromWkt(str(get_parameters['line']))
    bbox_array = np.array(
        geometry.GetEnvelope(),
    ).reshape(2, 2).transpose().ravel()
    bbox = ','.join(map(str, bbox_array))

    # set longest side to fixed size
    rastersize = 512
    x_extent = bbox_array[2] - bbox_array[0]
    y_extent = bbox_array[3] - bbox_array[1]
    aspect = (lambda x1, y1, x2, y2: (y2 - y1) / (x2 - x1))(*bbox_array)
    if aspect < 1:
        width = rastersize
        cellsize = x_extent / rastersize
        height = int(max(math.ceil(aspect * width), 1))
    else:
        height = rastersize
        cellsize = y_extent / rastersize
        width = int(max(math.ceil(height / aspect), 1))

    # Determine layer and time
    layer_parameter = get_parameters['layers']
    if ':' in layer_parameter:
        layer, mode = layer_parameter.split(':')
    else:
        layer, mode = layer_parameter, 'depth'
    time = int(get_parameters['time'])

    # Get height and quad
    get_parameters_extra = dict(width=width, height=height, bbox=bbox)
    get_parameters_extra.update(get_parameters)
    static_data = StaticData.get(layer=layer)
    quads, ms = get_data(container=static_data.monolith,
                         ma=True, **get_parameters_extra)
    logging.debug('Got quads in {} ms.'.format(ms))

    bathymetry, ms = get_data(container=static_data.pyramid,
                              ma=True, **get_parameters_extra)
    logging.debug('Got bathymetry in {} ms.'.format(ms))

    # Determine the waterlevel
    dynamic_data = DynamicData.get(
        layer=layer, time=time, use_cache=False)
    waterlevel = dynamic_data.waterlevel[quads]
    depth = waterlevel - bathymetry

    # Sample the depth using the cellsize
    magicline = vector.MagicLine(np.array(geometry.GetPoints())[:, :2])
    magicline2 = magicline.pixelize(cellsize)
    centers = magicline2.centers
    lengths_cumsum = vector.magnitude(magicline2.vectors).cumsum()
    distances = lengths_cumsum - lengths_cumsum[0]

    origin = np.array(bbox_array[[0, 3]])
    indices = tuple(np.uint64(
        np.abs(centers - origin) / cellsize,
    ).transpose())[::-1]
    depths = np.ma.maximum(depth[indices], 0)
    waterlevel_sampled = np.ma.maximum(waterlevel[indices], -100)
    bathymetry_sampled = np.ma.maximum(bathymetry[indices], -100)

    #bathymetry from 0 up
    bathymetry_minimum = min(np.ma.amin(bathymetry_sampled, 0), 0)
    bathymetry_sampled = bathymetry_sampled - bathymetry_minimum

    compressed_depths = depths.filled(0)
    compressed_distances = distances
    compressed_waterlevels = waterlevel_sampled.filled(0)
    compressed_bathymetry = bathymetry_sampled.filled(0)

    roundfunc = lambda x: round(x, 5)
    mapped_compressed_distances = map(roundfunc, compressed_distances)

    # The bias is needed for displaying stacked graphs below zero in nv.d3.
    content = json.dumps(dict(
        depth=zip(
            mapped_compressed_distances,
            map(roundfunc, compressed_depths)),
        # waterlevel=zip(
        #     mapped_compressed_distances,
        #     map(roundfunc, compressed_waterlevels)),
        bathymetry=zip(
            mapped_compressed_distances,
            map(roundfunc, compressed_bathymetry)),
        bias=zip(mapped_compressed_distances,
            [roundfunc(bathymetry_minimum)]*len(mapped_compressed_distances)),
    ))

    return content, 200, {
        'content-type': 'application/json',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET'}