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
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'}