コード例 #1
0
def determine_grid_type(dataset_url):
    try:
        UGrid.from_ncfile(dataset_url)
        grid_type = 'ugrid'
    except ValueError:
        try:
            from_ncfile(dataset_url)
            grid_type = 'sgrid'
        except SGridNonCompliantError:
            grid_type = None
    return grid_type
コード例 #2
0
def determine_grid_type(dataset_url):
    try:
        UGrid.from_ncfile(dataset_url)
        grid_type = 'ugrid'
    except ValueError:
        try:
            from_ncfile(dataset_url)
            grid_type = 'sgrid'
        except SGridNonCompliantError:
            grid_type = None
    return grid_type
コード例 #3
0
 def plot(self, variable, show=False, index=None):
     if index is None:
         self.animation(
             variable,
             # show=True,
             save='/home/jreniel/pyschism/examples/example_1/test.gif',
             vmin=0,
             vmax=3,
             # start_frame=200,
             # end_frame=300,
         )
     else:
         var = self.nc[variable]
         ugrid = UGrid.from_nc_dataset(self.nc)
         x = ugrid.nodes[:, 0]
         y = ugrid.nodes[:, 1]
         triangulation = Triangulation(x, y, ugrid.faces[:, :3])
         triangulation.set_mask(self.nc['wetdry_elem'][index])
         plt.tricontourf(triangulation,
                         var[index, :],
                         levels=256,
                         cmap='jet')
         plt.gca().axis('scaled')
         if show:
             plt.show()
コード例 #4
0
ファイル: ugrid_tides.py プロジェクト: zhaojiayi/sci-wms
    def wgs84_bounds(self, layer):
        with netCDF4.Dataset(self.topology_file) as nc:
            try:
                data_location = nc.variables['u'].location
                mesh_name = nc.variables['u'].mesh
                # Use local topology for pulling bounds data
                ug = UGrid.from_ncfile(self.topology_file, mesh_name=mesh_name)
                coords = np.empty(0)
                if data_location == 'node':
                    coords = ug.nodes
                elif data_location == 'face':
                    coords = ug.face_coordinates
                elif data_location == 'edge':
                    coords = ug.edge_coordinates

                minx = np.nanmin(coords[:, 0])
                miny = np.nanmin(coords[:, 1])
                maxx = np.nanmax(coords[:, 0])
                maxy = np.nanmax(coords[:, 1])

                return DotDict(minx=minx,
                               miny=miny,
                               maxx=maxx,
                               maxy=maxy,
                               bbox=(minx, miny, maxx, maxy))
            except AttributeError:
                pass
コード例 #5
0
ファイル: test_ugrid.py プロジェクト: veenstrajelmer/pyugrid
def test_full_set():
    grid = UGrid(nodes=nodes,
                 faces=faces,
                 edges=edges,
                 boundaries=boundaries,
                 )

    # Check the dtype of key objects.
    # Implicitly makes sure they are numpy arrays (or array-like).
    assert grid.num_vertices == 3

    assert grid.nodes.dtype == NODE_DT
    assert grid.faces.dtype == IND_DT
    assert grid.edges.dtype == IND_DT
    assert grid.boundaries.dtype == IND_DT

    # Check shape of grid arrays.
    assert len(grid.nodes.shape) == 2
    assert len(grid.faces.shape) == 2
    assert len(grid.edges.shape) == 2
    assert len(grid.boundaries.shape) == 2

    assert grid.nodes.shape[1] == 2
    assert grid.faces.shape[1] == 3
    assert grid.edges.shape[1] == 2
    assert grid.boundaries.shape[1] == 2
コード例 #6
0
ファイル: tardis.py プロジェクト: ocefpaf/utilities
def add_mesh(cube, url):
    """
    Adds the unstructured mesh info the to cube.  Soon in an iris near you!

    """
    from pyugrid import UGrid
    ug = UGrid.from_ncfile(url)
    cube.mesh = ug
    cube.mesh_dimension = 1
    return cube
コード例 #7
0
ファイル: ugrid.py プロジェクト: moghimis/sci-wms
    def make_rtree(self):

        with self.dataset() as nc:
            ug = UGrid.from_nc_dataset(nc=nc)

            def rtree_faces_generator_function():
                for face_idx, node_list in enumerate(ug.faces):
                    nodes = ug.nodes[node_list]
                    xmin, ymin = np.min(nodes, 0)
                    xmax, ymax = np.max(nodes, 0)
                    yield (face_idx, (xmin, ymin, xmax, ymax), face_idx)

            logger.info("Building Faces Rtree Topology Cache for {0}".format(self.name))
            start = time.time()
            _, face_temp_file = tempfile.mkstemp(suffix='.face')
            pf = index.Property()
            pf.filename = str(face_temp_file)
            pf.overwrite = True
            pf.storage   = index.RT_Disk
            pf.dimension = 2
            idx = index.Index(pf.filename,
                              rtree_faces_generator_function(),
                              properties=pf,
                              interleaved=True,
                              overwrite=True)
            idx.close()
            logger.info("Built Faces Rtree Topology Cache in {0} seconds.".format(time.time() - start))
            shutil.move('{}.dat'.format(face_temp_file), self.face_tree_data_file)
            shutil.move('{}.idx'.format(face_temp_file), self.face_tree_index_file)

            def rtree_nodes_generator_function():
                for node_index, (x, y) in enumerate(ug.nodes):
                    yield (node_index, (x, y, x, y), node_index)
            logger.info("Building Nodes Rtree Topology Cache for {0}".format(self.name))
            start = time.time()
            _, node_temp_file = tempfile.mkstemp(suffix='.node')
            pn = index.Property()
            pn.filename = str(node_temp_file)
            pn.overwrite = True
            pn.storage   = index.RT_Disk
            pn.dimension = 2
            idx = index.Index(pn.filename,
                              rtree_nodes_generator_function(),
                              properties=pn,
                              interleaved=True,
                              overwrite=True)
            idx.close()
            logger.info("Built Nodes Rtree Topology Cache in {0} seconds.".format(time.time() - start))
            shutil.move('{}.dat'.format(node_temp_file), self.node_tree_data_file)
            shutil.move('{}.idx'.format(node_temp_file), self.node_tree_index_file)
コード例 #8
0
ファイル: ugrid.py プロジェクト: ayan-usgs/sci-wms
    def make_rtree(self):
        p = rtree.index.Property()
        p.overwrite = True
        p.storage   = rtree.index.RT_Disk
        p.Dimension = 2

        with self.dataset() as nc:
            ug = UGrid.from_nc_dataset(nc=nc)

            class FastRtree(rtree.Rtree):
                def dumps(self, obj):
                    try:
                        import cPickle
                        return cPickle.dumps(obj, -1)
                    except ImportError:
                        super(FastRtree, self).dumps(obj)

            def rtree_faces_generator_function():
                for face_idx, node_list in enumerate(ug.faces):
                    nodes = ug.nodes[node_list]
                    xmin, ymin = np.min(nodes, 0)
                    xmax, ymax = np.max(nodes, 0)
                    yield (face_idx, (xmin, ymin, xmax, ymax), face_idx)
            logger.info("Building Faces Rtree Topology Cache for {0}".format(self.name))
            _, face_temp_file = tempfile.mkstemp(suffix='.face')
            start = time.time()
            FastRtree(face_temp_file,
                      rtree_faces_generator_function(),
                      properties=p,
                      overwrite=True,
                      interleaved=True)
            logger.info("Built Faces Rtree Topology Cache in {0} seconds.".format(time.time() - start))
            shutil.move('{}.dat'.format(face_temp_file), self.face_tree_data_file)
            shutil.move('{}.idx'.format(face_temp_file), self.face_tree_index_file)

            def rtree_nodes_generator_function():
                for node_index, (x, y) in enumerate(ug.nodes):
                    yield (node_index, (x, y, x, y), node_index)
            logger.info("Building Nodes Rtree Topology Cache for {0}".format(self.name))
            _, node_temp_file = tempfile.mkstemp(suffix='.node')
            start = time.time()
            FastRtree(node_temp_file,
                      rtree_nodes_generator_function(),
                      properties=p,
                      overwrite=True,
                      interleaved=True)
            logger.info("Built Nodes Rtree Topology Cache in {0} seconds.".format(time.time() - start))
            shutil.move('{}.dat'.format(node_temp_file), self.node_tree_data_file)
            shutil.move('{}.idx'.format(node_temp_file), self.node_tree_index_file)
コード例 #9
0
ファイル: ugrid.py プロジェクト: jdickin/sci-wms
    def make_rtree(self):

        with self.dataset() as nc:
            ug = UGrid.from_nc_dataset(nc=nc)

            def rtree_faces_generator_function():
                for face_idx, node_list in enumerate(ug.faces):
                    nodes = ug.nodes[node_list]
                    xmin, ymin = np.min(nodes, 0)
                    xmax, ymax = np.max(nodes, 0)
                    yield (face_idx, (xmin, ymin, xmax, ymax), face_idx)
            logger.info("Building Faces Rtree Topology Cache for {0}".format(self.name))
            start = time.time()
            _, face_temp_file = tempfile.mkstemp(suffix='.face')
            pf = index.Property()
            pf.filename = str(face_temp_file)
            pf.overwrite = True
            pf.storage   = index.RT_Disk
            pf.dimension = 2
            idx = index.Index(pf.filename.decode('utf-8'),
                              rtree_faces_generator_function(),
                              properties=pf,
                              interleaved=True,
                              overwrite=True)
            idx.close()
            logger.info("Built Faces Rtree Topology Cache in {0} seconds.".format(time.time() - start))
            shutil.move('{}.dat'.format(face_temp_file), self.face_tree_data_file)
            shutil.move('{}.idx'.format(face_temp_file), self.face_tree_index_file)

            def rtree_nodes_generator_function():
                for node_index, (x, y) in enumerate(ug.nodes):
                    yield (node_index, (x, y, x, y), node_index)
            logger.info("Building Nodes Rtree Topology Cache for {0}".format(self.name))
            start = time.time()
            _, node_temp_file = tempfile.mkstemp(suffix='.node')
            pn = index.Property()
            pn.filename = str(node_temp_file)
            pn.overwrite = True
            pn.storage   = index.RT_Disk
            pn.dimension = 2
            idx = index.Index(pn.filename.decode('utf-8'),
                              rtree_nodes_generator_function(),
                              properties=pn,
                              interleaved=True,
                              overwrite=True)
            idx.close()
            logger.info("Built Nodes Rtree Topology Cache in {0} seconds.".format(time.time() - start))
            shutil.move('{}.dat'.format(node_temp_file), self.node_tree_data_file)
            shutil.move('{}.idx'.format(node_temp_file), self.node_tree_index_file)
コード例 #10
0
    def update_cache(self, force=False):
        with self.dataset() as nc:
            ug = UGrid.from_nc_dataset(nc=nc)
            ug.save_as_netcdf(self.topology_file)

            if not os.path.exists(self.topology_file):
                logger.error(
                    "Failed to create topology_file cache for Dataset '{}'".
                    format(self.dataset))
                return

            time_vars = nc.get_variables_by_attributes(standard_name='time')
            time_dims = list(
                itertools.chain.from_iterable(
                    [time_var.dimensions for time_var in time_vars]))
            unique_time_dims = list(set(time_dims))
            with EnhancedDataset(self.topology_file, mode='a') as cached_nc:
                # create pertinent time dimensions if they aren't already present
                for unique_time_dim in unique_time_dims:
                    dim_size = len(nc.dimensions[unique_time_dim])
                    try:
                        cached_nc.createDimension(unique_time_dim,
                                                  size=dim_size)
                    except RuntimeError:
                        continue

                # support cases where there may be more than one variable with standard_name='time' in a dataset
                for time_var in time_vars:
                    try:
                        time_var_obj = cached_nc.createVariable(
                            time_var._name, time_var.dtype,
                            time_var.dimensions)
                    except RuntimeError:
                        time_var_obj = cached_nc.variables[time_var.name]

                    time_var_obj[:] = time_var[:]
                    time_var_obj.units = time_var.units
                    time_var_obj.standard_name = 'time'

            # Now do the RTree index
            self.make_rtree()

        self.cache_last_updated = datetime.utcnow().replace(tzinfo=pytz.utc)
        self.save()
コード例 #11
0
ファイル: ugrid.py プロジェクト: ayan-usgs/sci-wms
    def update_cache(self, force=False):
        with self.dataset() as nc:
            ug = UGrid.from_nc_dataset(nc=nc)
            ug.save_as_netcdf(self.topology_file)

            if not os.path.exists(self.topology_file):
                logger.error("Failed to create topology_file cache for Dataset '{}'".format(self.dataset))
                return

            time_vars = nc.get_variables_by_attributes(standard_name='time')
            time_dims = list(itertools.chain.from_iterable([time_var.dimensions for time_var in time_vars]))
            unique_time_dims = list(set(time_dims))
            with EnhancedDataset(self.topology_file, mode='a') as cached_nc:
                # create pertinent time dimensions if they aren't already present
                for unique_time_dim in unique_time_dims:
                    dim_size = len(nc.dimensions[unique_time_dim])
                    try:
                        cached_nc.createDimension(unique_time_dim, size=dim_size)
                    except RuntimeError:
                        continue

                # support cases where there may be more than one variable with standard_name='time' in a dataset
                for time_var in time_vars:
                    try:
                        time_var_obj = cached_nc.createVariable(time_var._name,
                                                                time_var.dtype,
                                                                time_var.dimensions)
                    except RuntimeError:
                        time_var_obj = cached_nc.variables[time_var.name]

                    time_var_obj[:] = time_var[:]
                    time_var_obj.units = time_var.units
                    time_var_obj.standard_name = 'time'

            # Now do the RTree index
            self.make_rtree()

        self.cache_last_updated = datetime.utcnow().replace(tzinfo=pytz.utc)
        self.save()
コード例 #12
0
ファイル: ugrid.py プロジェクト: ayan-usgs/sci-wms
    def wgs84_bounds(self, layer):
        with self.dataset() as nc:
            try:
                data_location = nc.variables[layer.access_name].location
                mesh_name = nc.variables[layer.access_name].mesh
                # Use local topology for pulling bounds data
                ug = UGrid.from_ncfile(self.topology_file, mesh_name=mesh_name)
                coords = np.empty(0)
                if data_location == 'node':
                    coords = ug.nodes
                elif data_location == 'face':
                    coords = ug.face_coordinates
                elif data_location == 'edge':
                    coords = ug.edge_coordinates

                minx = np.nanmin(coords[:, 1])
                miny = np.nanmin(coords[:, 0])
                maxx = np.nanmax(coords[:, 1])
                maxy = np.nanmax(coords[:, 0])

                return DotDict(minx=minx, miny=miny, maxx=maxx, maxy=maxy)
            except AttributeError:
                pass
コード例 #13
0
ファイル: ugrid.py プロジェクト: moghimis/sci-wms
    def update_grid_cache(self, force=False):
        with self.dataset() as nc:
            if nc is None:
                logger.error("Failed update_grid_cache, could not load dataset "
                             "as a netCDF4 object")
                return

            ug = UGrid.from_nc_dataset(nc=nc)

            # Atomic write
            tmphandle, tmpsave = tempfile.mkstemp()
            try:
                ug.save_as_netcdf(tmpsave)
            finally:
                os.close(tmphandle)
                if os.path.isfile(tmpsave):
                    shutil.move(tmpsave, self.topology_file)
                else:
                    logger.error("Failed to create topology_file cache for Dataset '{}'".format(self.dataset.name))
                    return

        # Now do the RTree index
        self.make_rtree()
コード例 #14
0
ファイル: ugrid.py プロジェクト: moghimis/sci-wms
    def getmap(self, layer, request):
        time_index, time_value = self.nearest_time(layer, request.GET['time'])
        wgs84_bbox = request.GET['wgs84_bbox']

        with self.dataset() as nc:
            data_obj = nc.variables[layer.access_name]
            data_location = data_obj.location
            mesh_name = data_obj.mesh

            ug = UGrid.from_ncfile(self.topology_file, mesh_name=mesh_name)
            coords = np.empty(0)
            if data_location == 'node':
                coords = ug.nodes
            elif data_location == 'face':
                coords = ug.face_coordinates
            elif data_location == 'edge':
                coords = ug.edge_coordinates

            lon = coords[:, 0]
            lat = coords[:, 1]

            # Calculate any vector padding if we need to
            padding = None
            vector_step = request.GET['vectorstep']
            if request.GET['image_type'] == 'vectors':
                padding_factor = calc_safety_factor(request.GET['vectorscale'])
                padding = calc_lon_lat_padding(lon, lat, padding_factor) * vector_step

            # Calculate the boolean spatial mask to slice with
            bool_spatial_idx = data_handler.ugrid_lat_lon_subset_idx(lon, lat,
                                                                     bbox=wgs84_bbox.bbox,
                                                                     padding=padding)

            # Randomize vectors to subset if we need to
            if request.GET['image_type'] == 'vectors' and vector_step > 1:
                num_vec = int(bool_spatial_idx.size / vector_step)
                step = int(bool_spatial_idx.size / num_vec)
                bool_spatial_idx[np.where(bool_spatial_idx==True)][0::step] = False  # noqa: E225

            # If no triangles intersect the field of view, return a transparent tile
            if not np.any(bool_spatial_idx):
                logger.info("No triangles in field of view, returning empty tile.")
                return self.empty_response(layer, request)

            if isinstance(layer, Layer):
                if (len(data_obj.shape) == 3):
                    z_index, z_value = self.nearest_z(layer, request.GET['elevation'])
                    data = data_obj[time_index, z_index, :]
                elif (len(data_obj.shape) == 2):
                    data = data_obj[time_index, :]
                elif len(data_obj.shape) == 1:
                    data = data_obj[:]
                else:
                    logger.debug("Dimension Mismatch: data_obj.shape == {0} and time = {1}".format(data_obj.shape, time_value))
                    return self.empty_response(layer, request)

                if request.GET['image_type'] in ['pcolor', 'contours', 'filledcontours']:
                    # Avoid triangles with nan values
                    bool_spatial_idx[np.isnan(data)] = False

                    # Get the faces to plot
                    faces = ug.faces[:]
                    face_idx = data_handler.face_idx_from_node_idx(faces, bool_spatial_idx)
                    faces_subset = faces[face_idx]
                    tri_subset = Tri.Triangulation(lon, lat, triangles=faces_subset)

                    if request.GET['image_type'] == 'pcolor':
                        return mpl_handler.tripcolor_response(tri_subset, data, request, data_location=data_location)
                    else:
                        return mpl_handler.tricontouring_response(tri_subset, data, request)
                elif request.GET['image_type'] in ['filledhatches', 'hatches']:
                    raise NotImplementedError('matplotlib does not support hatching on triangular grids... sorry!')
                else:
                    raise NotImplementedError('Image type "{}" is not supported.'.format(request.GET['image_type']))

            elif isinstance(layer, VirtualLayer):
                # Data needs to be [var1,var2] where var are 1D (nodes only, elevation and time already handled)
                data = []
                for l in layer.layers:
                    data_obj = nc.variables[l.var_name]
                    if (len(data_obj.shape) == 3):
                        z_index, z_value = self.nearest_z(layer, request.GET['elevation'])
                        data.append(data_obj[time_index, z_index, bool_spatial_idx])
                    elif (len(data_obj.shape) == 2):
                        data.append(data_obj[time_index, bool_spatial_idx])
                    elif len(data_obj.shape) == 1:
                        data.append(data_obj[bool_spatial_idx])
                    else:
                        logger.debug("Dimension Mismatch: data_obj.shape == {0} and time = {1}".format(data_obj.shape, time_value))
                        return self.empty_response(layer, request)

                if request.GET['image_type'] == 'vectors':
                    return mpl_handler.quiver_response(lon[bool_spatial_idx],
                                                       lat[bool_spatial_idx],
                                                       data[0],
                                                       data[1],
                                                       request)
                else:
                    raise NotImplementedError('Image type "{}" is not supported.'.format(request.GET['image_type']))
コード例 #15
0
    def getmap(self, layer, request):
        time_index, time_value = self.nearest_time(layer, request.GET['time'])
        wgs84_bbox = request.GET['wgs84_bbox']

        with self.dataset() as nc:
            data_obj = nc.variables[layer.access_name]
            data_location = data_obj.location
            mesh_name = data_obj.mesh

            ug = UGrid.from_ncfile(self.topology_file, mesh_name=mesh_name)
            coords = np.empty(0)
            if data_location == 'node':
                coords = ug.nodes
            elif data_location == 'face':
                coords = ug.face_coordinates
            elif data_location == 'edge':
                coords = ug.edge_coordinates

            lon = coords[:, 0]
            lat = coords[:, 1]

            if request.GET[
                    'vectorscale'] is not None:  # is not None if vectors are being plotted
                vectorscale = request.GET['vectorscale']
                padding_factor = calc_safety_factor(vectorscale)
                vectorstep = request.GET[
                    'vectorstep']  # returns 1 by default if vectors are being plotted
                spatial_idx_padding = calc_lon_lat_padding(
                    lon, lat, padding_factor) * vectorstep
                spatial_idx = data_handler.lat_lon_subset_idx(
                    lon,
                    lat,
                    wgs84_bbox.minx,
                    wgs84_bbox.miny,
                    wgs84_bbox.maxx,
                    wgs84_bbox.maxy,
                    padding=spatial_idx_padding)
                if vectorstep > 1:
                    np.random.shuffle(spatial_idx)
                    nvec = int(len(spatial_idx) / vectorstep)
                    spatial_idx = spatial_idx[:nvec]
            else:
                spatial_idx = data_handler.lat_lon_subset_idx(
                    lon, lat, wgs84_bbox.minx, wgs84_bbox.miny,
                    wgs84_bbox.maxx, wgs84_bbox.maxy)
            face_indicies = ug.faces[:]
            face_indicies_spatial_idx = data_handler.faces_subset_idx(
                face_indicies, spatial_idx)

            # If no triangles intersect the field of view, return a transparent tile
            if (len(spatial_idx) == 0) or (len(face_indicies_spatial_idx)
                                           == 0):
                logger.debug(
                    "No triangles in field of view, returning empty tile.")
                return self.empty_response(layer, request)

            if isinstance(layer, Layer):
                if (len(data_obj.shape) == 3):
                    z_index, z_value = self.nearest_z(layer,
                                                      request.GET['elevation'])
                    data = data_obj[time_index, z_index, :]
                elif (len(data_obj.shape) == 2):
                    data = data_obj[time_index, :]
                elif len(data_obj.shape) == 1:
                    data = data_obj[:]
                else:
                    logger.debug(
                        "Dimension Mismatch: data_obj.shape == {0} and time = {1}"
                        .format(data_obj.shape, time_value))
                    return self.empty_response(layer, request)

                if request.GET['image_type'] == 'filledcontours':
                    mask = np.isnan(data)  # array with NaNs appearing as True
                    if mask.any():
                        data_mask = ~mask  # negate the NaN boolean array; mask for non-NaN data elements
                        # slice the data, lon, and lat to get elements that correspond to non-NaN values
                        data = data_mask[data_mask]
                        lon = lon[data_mask]
                        lat = lat[data_mask]
                        # recalculate the spatial index using the subsetted lat/lon
                        spatial_idx = data_handler.lat_lon_subset_idx(
                            lon, lat, wgs84_bbox.minx, wgs84_bbox.miny,
                            wgs84_bbox.maxx, wgs84_bbox.maxy)
                    face_indicies_spatial_idx = data_handler.faces_subset_idx(
                        face_indicies, spatial_idx)
                    tri_subset = Tri.Triangulation(
                        lon,
                        lat,
                        triangles=face_indicies[face_indicies_spatial_idx])
                    return mpl_handler.tricontourf_response(
                        tri_subset, data, request)
                else:
                    raise NotImplementedError(
                        'Image type "{}" is not supported.'.format(
                            request.GET['image_type']))

            elif isinstance(layer, VirtualLayer):

                # Data needs to be [var1,var2] where var are 1D (nodes only, elevation and time already handled)
                data = []
                for l in layer.layers:
                    data_obj = nc.variables[l.var_name]
                    if (len(data_obj.shape) == 3):
                        z_index, z_value = self.nearest_z(
                            layer, request.GET['elevation'])
                        data.append(data_obj[time_index, z_index, :])
                    elif (len(data_obj.shape) == 2):
                        data.append(data_obj[time_index, :])
                    elif len(data_obj.shape) == 1:
                        data.append(data_obj[:])
                    else:
                        logger.debug(
                            "Dimension Mismatch: data_obj.shape == {0} and time = {1}"
                            .format(data_obj.shape, time_value))
                        return self.empty_response(layer, request)

                if request.GET['image_type'] == 'vectors':
                    return mpl_handler.quiver_response(lon[spatial_idx],
                                                       lat[spatial_idx],
                                                       data[0][spatial_idx],
                                                       data[1][spatial_idx],
                                                       request, vectorscale)
                else:
                    raise NotImplementedError(
                        'Image type "{}" is not supported.'.format(
                            request.GET['image_type']))
コード例 #16
0
    def make_rtree(self):
        p = rtree.index.Property()
        p.overwrite = True
        p.storage = rtree.index.RT_Disk
        p.Dimension = 2

        with self.dataset() as nc:
            ug = UGrid.from_nc_dataset(nc=nc)

            class FastRtree(rtree.Rtree):
                def dumps(self, obj):
                    try:
                        import cPickle
                        return cPickle.dumps(obj, -1)
                    except ImportError:
                        super(FastRtree, self).dumps(obj)

            def rtree_faces_generator_function():
                for face_idx, node_list in enumerate(ug.faces):
                    nodes = ug.nodes[node_list]
                    xmin, ymin = np.min(nodes, 0)
                    xmax, ymax = np.max(nodes, 0)
                    yield (face_idx, (xmin, ymin, xmax, ymax), face_idx)

            logger.info("Building Faces Rtree Topology Cache for {0}".format(
                self.name))
            _, face_temp_file = tempfile.mkstemp(suffix='.face')
            start = time.time()
            FastRtree(face_temp_file,
                      rtree_faces_generator_function(),
                      properties=p,
                      overwrite=True,
                      interleaved=True)
            logger.info(
                "Built Faces Rtree Topology Cache in {0} seconds.".format(
                    time.time() - start))
            shutil.move('{}.dat'.format(face_temp_file),
                        self.face_tree_data_file)
            shutil.move('{}.idx'.format(face_temp_file),
                        self.face_tree_index_file)

            def rtree_nodes_generator_function():
                for node_index, (x, y) in enumerate(ug.nodes):
                    yield (node_index, (x, y, x, y), node_index)

            logger.info("Building Nodes Rtree Topology Cache for {0}".format(
                self.name))
            _, node_temp_file = tempfile.mkstemp(suffix='.node')
            start = time.time()
            FastRtree(node_temp_file,
                      rtree_nodes_generator_function(),
                      properties=p,
                      overwrite=True,
                      interleaved=True)
            logger.info(
                "Built Nodes Rtree Topology Cache in {0} seconds.".format(
                    time.time() - start))
            shutil.move('{}.dat'.format(node_temp_file),
                        self.node_tree_data_file)
            shutil.move('{}.idx'.format(node_temp_file),
                        self.node_tree_index_file)
コード例 #17
0
ファイル: ugrid.py プロジェクト: jdickin/sci-wms
    def getmap(self, layer, request):
        time_index, time_value = self.nearest_time(layer, request.GET['time'])
        wgs84_bbox = request.GET['wgs84_bbox']

        with self.dataset() as nc:
            data_obj = nc.variables[layer.access_name]
            data_location = data_obj.location
            mesh_name = data_obj.mesh

            ug = UGrid.from_ncfile(self.topology_file, mesh_name=mesh_name)
            coords = np.empty(0)
            if data_location == 'node':
                coords = ug.nodes
            elif data_location == 'face':
                coords = ug.face_coordinates
            elif data_location == 'edge':
                coords = ug.edge_coordinates

            lon = coords[:, 0]
            lat = coords[:, 1]

            # Calculate any vector padding if we need to
            padding = None
            vector_step = request.GET['vectorstep']
            if request.GET['image_type'] == 'vectors':
                padding_factor = calc_safety_factor(request.GET['vectorscale'])
                padding = calc_lon_lat_padding(lon, lat, padding_factor) * vector_step

            # Calculate the boolean spatial mask to slice with
            bool_spatial_idx = data_handler.ugrid_lat_lon_subset_idx(lon, lat,
                                                                     bbox=wgs84_bbox.bbox,
                                                                     padding=padding)

            # Randomize vectors to subset if we need to
            if request.GET['image_type'] == 'vectors' and vector_step > 1:
                num_vec = int(bool_spatial_idx.size / vector_step)
                step = int(bool_spatial_idx.size / num_vec)
                bool_spatial_idx[np.where(bool_spatial_idx==True)][0::step] = False

            # If no triangles intersect the field of view, return a transparent tile
            if not np.any(bool_spatial_idx):
                logger.warning("No triangles in field of view, returning empty tile.")
                return self.empty_response(layer, request)

            if isinstance(layer, Layer):
                if (len(data_obj.shape) == 3):
                    z_index, z_value = self.nearest_z(layer, request.GET['elevation'])
                    data = data_obj[time_index, z_index, :]
                elif (len(data_obj.shape) == 2):
                    data = data_obj[time_index, :]
                elif len(data_obj.shape) == 1:
                    data = data_obj[:]
                else:
                    logger.debug("Dimension Mismatch: data_obj.shape == {0} and time = {1}".format(data_obj.shape, time_value))
                    return self.empty_response(layer, request)

                if request.GET['image_type'] in ['pcolor', 'contours', 'filledcontours']:
                    # Avoid triangles with nan values
                    bool_spatial_idx[np.isnan(data)] = False

                    # Get the faces to plot
                    faces = ug.faces[:]
                    face_idx = data_handler.face_idx_from_node_idx(faces, bool_spatial_idx)
                    faces_subset = faces[face_idx]
                    tri_subset = Tri.Triangulation(lon, lat, triangles=faces_subset)

                    if request.GET['image_type'] == 'pcolor':
                        return mpl_handler.tripcolor_response(tri_subset, data, request, data_location=data_location)
                    else:
                        return mpl_handler.tricontouring_response(tri_subset, data, request)
                elif request.GET['image_type'] in ['filledhatches', 'hatches']:
                    raise NotImplementedError('matplotlib does not support hatching on triangular grids... sorry!')
                else:
                    raise NotImplementedError('Image type "{}" is not supported.'.format(request.GET['image_type']))

            elif isinstance(layer, VirtualLayer):
                # Data needs to be [var1,var2] where var are 1D (nodes only, elevation and time already handled)
                data = []
                for l in layer.layers:
                    data_obj = nc.variables[l.var_name]
                    if (len(data_obj.shape) == 3):
                        z_index, z_value = self.nearest_z(layer, request.GET['elevation'])
                        data.append(data_obj[time_index, z_index, bool_spatial_idx])
                    elif (len(data_obj.shape) == 2):
                        data.append(data_obj[time_index, bool_spatial_idx])
                    elif len(data_obj.shape) == 1:
                        data.append(data_obj[bool_spatial_idx])
                    else:
                        logger.debug("Dimension Mismatch: data_obj.shape == {0} and time = {1}".format(data_obj.shape, time_value))
                        return self.empty_response(layer, request)

                if request.GET['image_type'] == 'vectors':
                    return mpl_handler.quiver_response(lon[bool_spatial_idx],
                                                       lat[bool_spatial_idx],
                                                       data[0],
                                                       data[1],
                                                       request)
                else:
                    raise NotImplementedError('Image type "{}" is not supported.'.format(request.GET['image_type']))
コード例 #18
0
    def minmax(self, layer, request):
        time_index, time_value = self.nearest_time(layer, request.GET['time'])
        wgs84_bbox = request.GET['wgs84_bbox']

        with self.dataset() as nc:
            data_obj = nc.variables[layer.access_name]
            data_location = data_obj.location
            mesh_name = data_obj.mesh

            ug = UGrid.from_ncfile(self.topology_file, mesh_name=mesh_name)
            coords = np.empty(0)
            if data_location == 'node':
                coords = ug.nodes
            elif data_location == 'face':
                coords = ug.face_coordinates
            elif data_location == 'edge':
                coords = ug.edge_coordinates

            lon = coords[:, 0]
            lat = coords[:, 1]
            spatial_idx = data_handler.lat_lon_subset_idx(
                lon, lat, wgs84_bbox.minx, wgs84_bbox.miny, wgs84_bbox.maxx,
                wgs84_bbox.maxy)

            vmin = None
            vmax = None
            data = None
            if isinstance(layer, Layer):
                if (len(data_obj.shape) == 3):
                    z_index, z_value = self.nearest_z(layer,
                                                      request.GET['elevation'])
                    data = data_obj[time_index, z_index, spatial_idx]
                elif (len(data_obj.shape) == 2):
                    data = data_obj[time_index, spatial_idx]
                elif len(data_obj.shape) == 1:
                    data = data_obj[spatial_idx]
                else:
                    logger.debug(
                        "Dimension Mismatch: data_obj.shape == {0} and time = {1}"
                        .format(data_obj.shape, time_value))

                if data is not None:
                    vmin = np.nanmin(data).item()
                    vmax = np.nanmax(data).item()
            elif isinstance(layer, VirtualLayer):

                # Data needs to be [var1,var2] where var are 1D (nodes only, elevation and time already handled)
                data = []
                for l in layer.layers:
                    data_obj = nc.variables[l.var_name]
                    if (len(data_obj.shape) == 3):
                        z_index, z_value = self.nearest_z(
                            layer, request.GET['elevation'])
                        data.append(data_obj[time_index, z_index, spatial_idx])
                    elif (len(data_obj.shape) == 2):
                        data.append(data_obj[time_index, spatial_idx])
                    elif len(data_obj.shape) == 1:
                        data.append(data_obj[spatial_idx])
                    else:
                        logger.debug(
                            "Dimension Mismatch: data_obj.shape == {0} and time = {1}"
                            .format(data_obj.shape, time_value))

                if ',' in layer.var_name and data:
                    # Vectors, so return magnitude
                    data = [
                        sqrt((u * u) + (v * v)) for (
                            u,
                            v,
                        ) in data.T if u != np.nan and v != np.nan
                    ]
                    vmin = min(data)
                    vmax = max(data)

            return gmd_handler.from_dict(dict(min=vmin, max=vmax))
コード例 #19
0
ファイル: ugrid.py プロジェクト: ayan-usgs/sci-wms
    def minmax(self, layer, request):
        time_index, time_value = self.nearest_time(layer, request.GET['time'])
        wgs84_bbox = request.GET['wgs84_bbox']

        with self.dataset() as nc:
            data_obj = nc.variables[layer.access_name]
            data_location = data_obj.location
            mesh_name = data_obj.mesh

            ug = UGrid.from_ncfile(self.topology_file, mesh_name=mesh_name)
            coords = np.empty(0)
            if data_location == 'node':
                coords = ug.nodes
            elif data_location == 'face':
                coords = ug.face_coordinates
            elif data_location == 'edge':
                coords = ug.edge_coordinates

            lon = coords[:, 0]
            lat = coords[:, 1]
            spatial_idx = data_handler.lat_lon_subset_idx(lon, lat, wgs84_bbox.minx, wgs84_bbox.miny, wgs84_bbox.maxx, wgs84_bbox.maxy)

            vmin = None
            vmax = None
            data = None
            if isinstance(layer, Layer):
                if (len(data_obj.shape) == 3):
                    z_index, z_value = self.nearest_z(layer, request.GET['elevation'])
                    data = data_obj[time_index, z_index, spatial_idx]
                elif (len(data_obj.shape) == 2):
                    data = data_obj[time_index, spatial_idx]
                elif len(data_obj.shape) == 1:
                    data = data_obj[spatial_idx]
                else:
                    logger.debug("Dimension Mismatch: data_obj.shape == {0} and time = {1}".format(data_obj.shape, time_value))

                if data is not None:
                    vmin = np.nanmin(data).item()
                    vmax = np.nanmax(data).item()
            elif isinstance(layer, VirtualLayer):

                # Data needs to be [var1,var2] where var are 1D (nodes only, elevation and time already handled)
                data = []
                for l in layer.layers:
                    data_obj = nc.variables[l.var_name]
                    if (len(data_obj.shape) == 3):
                        z_index, z_value = self.nearest_z(layer, request.GET['elevation'])
                        data.append(data_obj[time_index, z_index, spatial_idx])
                    elif (len(data_obj.shape) == 2):
                        data.append(data_obj[time_index, spatial_idx])
                    elif len(data_obj.shape) == 1:
                        data.append(data_obj[spatial_idx])
                    else:
                        logger.debug("Dimension Mismatch: data_obj.shape == {0} and time = {1}".format(data_obj.shape, time_value))

                if ',' in layer.var_name and data:
                    # Vectors, so return magnitude
                    data = [ sqrt((u*u) + (v*v)) for (u, v,) in data.T if u != np.nan and v != np.nan]
                    vmin = min(data)
                    vmax = max(data)

            return gmd_handler.from_dict(dict(min=vmin, max=vmax))
コード例 #20
0
ファイル: ugrid_tides.py プロジェクト: zhaojiayi/sci-wms
    def update_cache(self, force=False):
        with self.dataset() as nc:
            ug = UGrid.from_nc_dataset(nc)
            ug.save_as_netcdf(self.topology_file)

            if not os.path.exists(self.topology_file):
                logger.error(
                    "Failed to create topology_file cache for Dataset '{}'".
                    format(self.dataset))
                return

            uamp = nc.get_variables_by_attributes(
                standard_name='eastward_sea_water_velocity_amplitude')[0]
            vamp = nc.get_variables_by_attributes(
                standard_name='northward_sea_water_velocity_amplitude')[0]
            uphase = nc.get_variables_by_attributes(
                standard_name='eastward_sea_water_velocity_phase')[0]
            vphase = nc.get_variables_by_attributes(
                standard_name='northward_sea_water_velocity_phase')[0]
            tnames = nc.get_variables_by_attributes(
                standard_name='tide_constituent')[0]
            tfreqs = nc.get_variables_by_attributes(
                standard_name='tide_frequency')[0]

            with netCDF4.Dataset(self.topology_file, mode='a') as cnc:

                ntides = uamp.shape[uamp.dimensions.index('ntides')]
                nlocs = uamp.shape[uamp.dimensions.index(uamp.location)]
                cnc.createDimension('ntides', ntides)
                cnc.createDimension('maxStrlen64', 64)

                vdims = ('ntides', '{}_num_{}'.format(uamp.mesh,
                                                      uamp.location))

                # Swap ntides to always be the first dimension.. it can be the second in the source files!
                transpose = False
                if uamp.shape[0] > uamp.shape[1]:
                    logger.info(
                        "Found flipped dimensions in source file... fixing in local cache."
                    )
                    transpose = True

                # We are changing the variable names to 'u' and 'v' from 'u_amp' and 'v_amp' so
                # the layer.access_method can find the variable from the virtual layer 'u,v'
                ua = cnc.createVariable('u',
                                        uamp.dtype,
                                        vdims,
                                        zlib=True,
                                        fill_value=uamp._FillValue,
                                        chunksizes=[1, nlocs / 4])
                for x in uamp.ncattrs():
                    if x != '_FillValue':
                        ua.setncattr(x, uamp.getncattr(x))
                va = cnc.createVariable('v',
                                        vamp.dtype,
                                        vdims,
                                        zlib=True,
                                        fill_value=vamp._FillValue,
                                        chunksizes=[1, nlocs / 4])
                for x in vamp.ncattrs():
                    if x != '_FillValue':
                        va.setncattr(x, vamp.getncattr(x))
                up = cnc.createVariable('u_phase',
                                        uphase.dtype,
                                        vdims,
                                        zlib=True,
                                        fill_value=uphase._FillValue,
                                        chunksizes=[1, nlocs / 4])
                for x in uphase.ncattrs():
                    if x != '_FillValue':
                        up.setncattr(x, uphase.getncattr(x))
                vp = cnc.createVariable('v_phase',
                                        vphase.dtype,
                                        vdims,
                                        zlib=True,
                                        fill_value=vphase._FillValue,
                                        chunksizes=[1, nlocs / 4])
                for x in vphase.ncattrs():
                    if x != '_FillValue':
                        vp.setncattr(x, vphase.getncattr(x))

                tc = cnc.createVariable('tidenames', tnames.dtype,
                                        tnames.dimensions)
                tc[:] = tnames[:]
                for x in tnames.ncattrs():
                    if x != '_FillValue':
                        tc.setncattr(x, tnames.getncattr(x))

                tf = cnc.createVariable('tidefreqs', tfreqs.dtype,
                                        ('ntides', ))
                tf[:] = tfreqs[:]
                for x in tfreqs.ncattrs():
                    if x != '_FillValue':
                        tf.setncattr(x, tfreqs.getncattr(x))

                for r in range(ntides):
                    logger.info("Saving ntide {} into cache".format(r))
                    if transpose is True:
                        ua[r, :] = uamp[:, r].T
                        va[r, :] = vamp[:, r].T
                        up[r, :] = uphase[:, r].T
                        vp[r, :] = vphase[:, r].T
                    else:
                        ua[r, :] = uamp[r, :]
                        va[r, :] = vamp[r, :]
                        up[r, :] = uphase[r, :]
                        vp[r, :] = vphase[r, :]

        # Now do the RTree index
        self.make_rtree()

        self.cache_last_updated = datetime.utcnow().replace(tzinfo=pytz.utc)
        self.save()
コード例 #21
0
ファイル: ugrid.py プロジェクト: ayan-usgs/sci-wms
    def getmap(self, layer, request):
        time_index, time_value = self.nearest_time(layer, request.GET['time'])
        wgs84_bbox = request.GET['wgs84_bbox']

        with self.dataset() as nc:
            data_obj = nc.variables[layer.access_name]
            data_location = data_obj.location
            mesh_name = data_obj.mesh

            ug = UGrid.from_ncfile(self.topology_file, mesh_name=mesh_name)
            coords = np.empty(0)
            if data_location == 'node':
                coords = ug.nodes
            elif data_location == 'face':
                coords = ug.face_coordinates
            elif data_location == 'edge':
                coords = ug.edge_coordinates

            lon = coords[:, 0]
            lat = coords[:, 1]

            if request.GET['vectorscale'] is not None:  # is not None if vectors are being plotted
                vectorscale = request.GET['vectorscale']
                padding_factor = calc_safety_factor(vectorscale)
                vectorstep = request.GET['vectorstep']  # returns 1 by default if vectors are being plotted
                spatial_idx_padding = calc_lon_lat_padding(lon, lat, padding_factor) * vectorstep
                spatial_idx = data_handler.lat_lon_subset_idx(lon, lat,
                                                              wgs84_bbox.minx,
                                                              wgs84_bbox.miny,
                                                              wgs84_bbox.maxx,
                                                              wgs84_bbox.maxy,
                                                              padding=spatial_idx_padding
                                                              )
                if vectorstep > 1:
                    np.random.shuffle(spatial_idx)
                    nvec = int(len(spatial_idx) / vectorstep)
                    spatial_idx = spatial_idx[:nvec]
            else:
                spatial_idx = data_handler.lat_lon_subset_idx(lon, lat,
                                                              wgs84_bbox.minx,
                                                              wgs84_bbox.miny,
                                                              wgs84_bbox.maxx,
                                                              wgs84_bbox.maxy
                                                              )
            face_indicies = ug.faces[:]
            face_indicies_spatial_idx = data_handler.faces_subset_idx(face_indicies, spatial_idx)

            # If no triangles intersect the field of view, return a transparent tile
            if (len(spatial_idx) == 0) or (len(face_indicies_spatial_idx) == 0):
                logger.debug("No triangles in field of view, returning empty tile.")
                return self.empty_response(layer, request)

            if isinstance(layer, Layer):
                if (len(data_obj.shape) == 3):
                    z_index, z_value = self.nearest_z(layer, request.GET['elevation'])
                    data = data_obj[time_index, z_index, :]
                elif (len(data_obj.shape) == 2):
                    data = data_obj[time_index, :]
                elif len(data_obj.shape) == 1:
                    data = data_obj[:]
                else:
                    logger.debug("Dimension Mismatch: data_obj.shape == {0} and time = {1}".format(data_obj.shape, time_value))
                    return self.empty_response(layer, request)

                if request.GET['image_type'] == 'filledcontours':
                    mask = np.isnan(data)  # array with NaNs appearing as True
                    if mask.any():
                        data_mask = ~mask  # negate the NaN boolean array; mask for non-NaN data elements
                        # slice the data, lon, and lat to get elements that correspond to non-NaN values
                        data = data_mask[data_mask]
                        lon = lon[data_mask]
                        lat = lat[data_mask]
                        # recalculate the spatial index using the subsetted lat/lon
                        spatial_idx = data_handler.lat_lon_subset_idx(lon,
                                                                      lat,
                                                                      wgs84_bbox.minx,
                                                                      wgs84_bbox.miny,
                                                                      wgs84_bbox.maxx,
                                                                      wgs84_bbox.maxy
                                                                      )
                    face_indicies_spatial_idx = data_handler.faces_subset_idx(face_indicies, spatial_idx)
                    tri_subset = Tri.Triangulation(lon,
                                                   lat,
                                                   triangles=face_indicies[face_indicies_spatial_idx]
                                                   )
                    return mpl_handler.tricontourf_response(tri_subset,
                                                            data,
                                                            request
                                                            )
                else:
                    raise NotImplementedError('Image type "{}" is not supported.'.format(request.GET['image_type']))

            elif isinstance(layer, VirtualLayer):

                # Data needs to be [var1,var2] where var are 1D (nodes only, elevation and time already handled)
                data = []
                for l in layer.layers:
                    data_obj = nc.variables[l.var_name]
                    if (len(data_obj.shape) == 3):
                        z_index, z_value = self.nearest_z(layer, request.GET['elevation'])
                        data.append(data_obj[time_index, z_index, :])
                    elif (len(data_obj.shape) == 2):
                        data.append(data_obj[time_index, :])
                    elif len(data_obj.shape) == 1:
                        data.append(data_obj[:])
                    else:
                        logger.debug("Dimension Mismatch: data_obj.shape == {0} and time = {1}".format(data_obj.shape, time_value))
                        return self.empty_response(layer, request)

                if request.GET['image_type'] == 'vectors':
                    return mpl_handler.quiver_response(lon[spatial_idx],
                                                       lat[spatial_idx],
                                                       data[0][spatial_idx],
                                                       data[1][spatial_idx],
                                                       request,
                                                       vectorscale
                                                       )
                else:
                    raise NotImplementedError('Image type "{}" is not supported.'.format(request.GET['image_type']))
コード例 #22
0
ファイル: ugrid_tides.py プロジェクト: zhaojiayi/sci-wms
    def get_tidal_vectors(self,
                          layer,
                          time,
                          bbox,
                          vector_scale=None,
                          vector_step=None):

        vector_scale = vector_scale or 1
        vector_step = vector_step or 1

        with netCDF4.Dataset(self.topology_file) as nc:
            data_obj = nc.variables[layer.access_name]
            data_location = getattr(data_obj, 'location', 'node')
            mesh_name = data_obj.mesh

            ug = UGrid.from_nc_dataset(nc, mesh_name=mesh_name)
            coords = np.empty(0)
            if data_location == 'node':
                coords = ug.nodes
            elif data_location == 'face':
                coords = ug.face_coordinates
            elif data_location == 'edge':
                coords = ug.edge_coordinates

            lon = coords[:, 0]
            lat = coords[:, 1]

            padding_factor = calc_safety_factor(vector_scale)
            padding = calc_lon_lat_padding(lon, lat,
                                           padding_factor) * vector_step
            spatial_idx = data_handler.ugrid_lat_lon_subset_idx(
                lon, lat, bbox=bbox, padding=padding)

            tnames = nc.get_variables_by_attributes(
                standard_name='tide_constituent')[0]
            tfreqs = nc.get_variables_by_attributes(
                standard_name='tide_frequency')[0]

            from utide import _ut_constants_fname
            from utide.utilities import loadmatbunch
            con_info = loadmatbunch(_ut_constants_fname)['const']

            # Get names from the utide constant file
            utide_const_names = [e.strip() for e in con_info['name'].tolist()]

            # netCDF4-python is returning ugly arrays of bytes...
            names = []
            for n in tnames[:]:
                z = ''.join([x.decode('utf-8') for x in n.tolist()
                             if x]).strip()
                names.append(z)

            if 'STEADY' in names:
                names[names.index('STEADY')] = 'Z0'
            extract_names = list(
                set(utide_const_names).intersection(set(names)))

            ntides = data_obj.shape[data_obj.dimensions.index('ntides')]
            extract_mask = np.zeros(shape=(ntides, ), dtype=bool)
            for n in extract_names:
                extract_mask[names.index(n)] = True

            if not spatial_idx.any() or not extract_mask.any():
                e = np.ma.empty(0)
                return e, e, e, e

            ua = nc.variables['u'][extract_mask, spatial_idx]
            va = nc.variables['v'][extract_mask, spatial_idx]
            up = nc.variables['u_phase'][extract_mask, spatial_idx]
            vp = nc.variables['v_phase'][extract_mask, spatial_idx]
            freqs = tfreqs[extract_mask]

            omega = freqs * 3600  # Convert from radians/s to radians/hour.

            from utide.harmonics import FUV
            from matplotlib.dates import date2num
            v, u, f = FUV(
                t=np.array([date2num(time) + 366.1667]),
                tref=np.array([0]),
                lind=np.array(
                    [utide_const_names.index(x) for x in extract_names]),
                lat=
                55,  # Reference latitude for 3rd order satellites (degrees) (55 is fine always)
                ngflgs=[0, 0, 0,
                        0])  # [NodsatLint NodsatNone GwchLint GwchNone]

            s = calendar.timegm(time.timetuple()) / 60 / 60.
            v, u, f = map(np.squeeze, (v, u, f))
            v = v * 2 * np.pi  # Convert phase in radians.
            u = u * 2 * np.pi  # Convert phase in radians.

            U = (f * ua.T *
                 np.cos(v + s * omega + u - up.T * np.pi / 180)).sum(axis=1)
            V = (f * va.T *
                 np.cos(v + s * omega + u - vp.T * np.pi / 180)).sum(axis=1)

            return U, V, lon[spatial_idx], lat[spatial_idx]
コード例 #23
0
ファイル: ugrid_tides.py プロジェクト: jdickin/sci-wms
    def update_cache(self, force=False):
        with self.dataset() as nc:
            ug = UGrid.from_nc_dataset(nc)
            ug.save_as_netcdf(self.topology_file)

            if not os.path.exists(self.topology_file):
                logger.error("Failed to create topology_file cache for Dataset '{}'".format(self.dataset))
                return

            uamp = nc.get_variables_by_attributes(standard_name='eastward_sea_water_velocity_amplitude')[0]
            vamp = nc.get_variables_by_attributes(standard_name='northward_sea_water_velocity_amplitude')[0]
            uphase = nc.get_variables_by_attributes(standard_name='eastward_sea_water_velocity_phase')[0]
            vphase = nc.get_variables_by_attributes(standard_name='northward_sea_water_velocity_phase')[0]
            tnames = nc.get_variables_by_attributes(standard_name='tide_constituent')[0]
            tfreqs = nc.get_variables_by_attributes(standard_name='tide_frequency')[0]

            with netCDF4.Dataset(self.topology_file, mode='a') as cnc:

                ntides = uamp.shape[uamp.dimensions.index('ntides')]
                nlocs = uamp.shape[uamp.dimensions.index(uamp.location)]
                cnc.createDimension('ntides', ntides)
                cnc.createDimension('maxStrlen64', 64)

                vdims = ('ntides', '{}_num_{}'.format(uamp.mesh, uamp.location))

                # Swap ntides to always be the first dimension.. it can be the second in the source files!
                transpose = False
                if uamp.shape[0] > uamp.shape[1]:
                    logger.info("Found flipped dimensions in source file... fixing in local cache.")
                    transpose = True

                # We are changing the variable names to 'u' and 'v' from 'u_amp' and 'v_amp' so
                # the layer.access_method can find the variable from the virtual layer 'u,v'
                ua = cnc.createVariable('u', uamp.dtype, vdims, zlib=True, fill_value=uamp._FillValue, chunksizes=[1, nlocs/4])
                for x in uamp.ncattrs():
                    if x != '_FillValue':
                        ua.setncattr(x, uamp.getncattr(x))
                va = cnc.createVariable('v', vamp.dtype, vdims, zlib=True, fill_value=vamp._FillValue, chunksizes=[1, nlocs/4])
                for x in vamp.ncattrs():
                    if x != '_FillValue':
                        va.setncattr(x, vamp.getncattr(x))
                up = cnc.createVariable('u_phase', uphase.dtype, vdims, zlib=True, fill_value=uphase._FillValue, chunksizes=[1, nlocs/4])
                for x in uphase.ncattrs():
                    if x != '_FillValue':
                        up.setncattr(x, uphase.getncattr(x))
                vp = cnc.createVariable('v_phase', vphase.dtype, vdims, zlib=True, fill_value=vphase._FillValue, chunksizes=[1, nlocs/4])
                for x in vphase.ncattrs():
                    if x != '_FillValue':
                        vp.setncattr(x, vphase.getncattr(x))

                tc = cnc.createVariable('tidenames', tnames.dtype, tnames.dimensions)
                tc[:] = tnames[:]
                for x in tnames.ncattrs():
                    if x != '_FillValue':
                        tc.setncattr(x, tnames.getncattr(x))

                tf = cnc.createVariable('tidefreqs', tfreqs.dtype, ('ntides',))
                tf[:] = tfreqs[:]
                for x in tfreqs.ncattrs():
                    if x != '_FillValue':
                        tf.setncattr(x, tfreqs.getncattr(x))

                for r in range(ntides):
                    logger.info("Saving ntide {} into cache".format(r))
                    if transpose is True:
                        ua[r, :] = uamp[:, r].T
                        va[r, :] = vamp[:, r].T
                        up[r, :] = uphase[:, r].T
                        vp[r, :] = vphase[:, r].T
                    else:
                        ua[r, :] = uamp[r, :]
                        va[r, :] = vamp[r, :]
                        up[r, :] = uphase[r, :]
                        vp[r, :] = vphase[r, :]

        # Now do the RTree index
        self.make_rtree()

        self.cache_last_updated = datetime.utcnow().replace(tzinfo=pytz.utc)
        self.save()
コード例 #24
0
    def animation(
        self,
        variable,
        save=False,
        fps=3,
        start_frame=0,
        end_frame=-1,
        figsize=None,
        wireframe=False,
        cmap='jet',
        levels=256,
        show=False,
        xmin=None,
        xmax=None,
        ymin=None,
        ymax=None,
        vmin=None,
        vmax=None,
    ):

        fig = plt.figure(figsize)
        ax = fig.add_subplot(111)

        plt.tight_layout(pad=2)

        ugrid = UGrid.from_nc_dataset(self.nc)
        x = ugrid.nodes[:, 0]
        y = ugrid.nodes[:, 1]
        triangulation = Triangulation(x, y, ugrid.faces[:, :3])
        xmin = np.min(x) if xmin is None else xmin
        xmax = np.max(x) if xmax is None else xmax
        ymin = np.min(y) if ymin is None else ymin
        ymax = np.max(y) if ymax is None else ymax
        vmin = np.min(self.nc[variable]) if vmin is None else vmin
        vmax = np.max(self.nc[variable]) if vmax is None else vmax
        unit = OutputVariableUnit[OutputVariableShortName(variable).name].value

        def animate(index):
            _ax = fig.get_axes()
            ax.clear()
            if len(_ax) > 1:
                cax = _ax[1]
                cax.cla()
            else:
                cax = None

            triangulation.set_mask(self.nc['wetdry_elem'][index])

            if wireframe:
                ax.triplot(triangulation, color='k', linewidth=0.7)

            ax.tricontourf(triangulation,
                           self.nc[variable][index, :],
                           cmap=cmap,
                           levels=levels,
                           vmin=vmin,
                           vmax=vmax)

            ax.set_ylim(ymin, ymax, auto=True)
            ax.set_xlim(xmin, xmax, auto=True)

            ax.set_xlabel('Longitude (°E)')
            ax.set_ylabel('Latitude (°N)')

            # ax.set_title(dates[i].strftime('%b %d, %Y %H:%M'))
            m = plt.cm.ScalarMappable(cmap=cmap)
            m.set_array(self.nc[variable][index, :])
            m.set_clim(vmin, vmax)
            cbar = fig.colorbar(m,
                                cax=cax,
                                format='%.1f',
                                boundaries=np.linspace(vmin, vmax, levels))

            # cbar = fig.colorbar(_ax)
            cbar.ax.set_ylabel(f'{variable} [{unit}]', rotation=90)

        end_frame = end_frame % self.nc[variable].shape[0] \
            if end_frame < 0 else end_frame
        start_frame = start_frame % self.nc[variable].shape[0] \
            if start_frame < 0 else start_frame
        frames = range(start_frame, end_frame)
        anim = FuncAnimation(fig, animate, frames, blit=False)

        if save:
            anim.save(pathlib.Path(save), writer='imagemagick', fps=fps)

        if show:
            plt.show()

        return anim
コード例 #25
0
ファイル: ugrid_tides.py プロジェクト: jdickin/sci-wms
    def get_tidal_vectors(self, layer, time, bbox, vector_scale=None, vector_step=None):

        vector_scale = vector_scale or 1
        vector_step = vector_step or 1

        with netCDF4.Dataset(self.topology_file) as nc:
            data_obj = nc.variables[layer.access_name]
            data_location = getattr(data_obj, 'location', 'node')
            mesh_name = data_obj.mesh

            ug = UGrid.from_nc_dataset(nc, mesh_name=mesh_name)
            coords = np.empty(0)
            if data_location == 'node':
                coords = ug.nodes
            elif data_location == 'face':
                coords = ug.face_coordinates
            elif data_location == 'edge':
                coords = ug.edge_coordinates

            lon = coords[:, 0]
            lat = coords[:, 1]

            padding_factor = calc_safety_factor(vector_scale)
            padding = calc_lon_lat_padding(lon, lat, padding_factor) * vector_step
            spatial_idx = data_handler.ugrid_lat_lon_subset_idx(lon, lat,
                                                                bbox=bbox,
                                                                padding=padding)

            tnames = nc.get_variables_by_attributes(standard_name='tide_constituent')[0]
            tfreqs = nc.get_variables_by_attributes(standard_name='tide_frequency')[0]

            from utide import _ut_constants_fname
            from utide.utilities import loadmatbunch
            con_info = loadmatbunch(_ut_constants_fname)['const']

            # Get names from the utide constant file
            utide_const_names = [ e.strip() for e in con_info['name'].tolist() ]

            # netCDF4-python is returning ugly arrays of bytes...
            names = []
            for n in tnames[:]:
                z = ''.join([ x.decode('utf-8') for x in n.tolist() if x ]).strip()
                names.append(z)

            if 'STEADY' in names:
                names[names.index('STEADY')] = 'Z0'
            extract_names = list(set(utide_const_names).intersection(set(names)))

            ntides = data_obj.shape[data_obj.dimensions.index('ntides')]
            extract_mask = np.zeros(shape=(ntides,), dtype=bool)
            for n in extract_names:
                extract_mask[names.index(n)] = True

            if not spatial_idx.any() or not extract_mask.any():
                e = np.ma.empty(0)
                return e, e, e, e

            ua = nc.variables['u'][extract_mask, spatial_idx]
            va = nc.variables['v'][extract_mask, spatial_idx]
            up = nc.variables['u_phase'][extract_mask, spatial_idx]
            vp = nc.variables['v_phase'][extract_mask, spatial_idx]
            freqs = tfreqs[extract_mask]

            omega = freqs * 3600  # Convert from radians/s to radians/hour.

            from utide.harmonics import FUV
            from matplotlib.dates import date2num
            v, u, f = FUV(t=np.array([date2num(time) + 366.1667]),
                          tref=np.array([0]),
                          lind=np.array([ utide_const_names.index(x) for x in extract_names ]),
                          lat=55,  # Reference latitude for 3rd order satellites (degrees) (55 is fine always)
                          ngflgs=[0, 0, 0, 0])  # [NodsatLint NodsatNone GwchLint GwchNone]

            s = calendar.timegm(time.timetuple()) / 60 / 60.
            v, u, f = map(np.squeeze, (v, u, f))
            v = v * 2 * np.pi  # Convert phase in radians.
            u = u * 2 * np.pi  # Convert phase in radians.

            U = (f * ua.T * np.cos(v + s * omega + u - up.T * np.pi / 180)).sum(axis=1)
            V = (f * va.T * np.cos(v + s * omega + u - vp.T * np.pi / 180)).sum(axis=1)

            return U, V, lon[spatial_idx], lat[spatial_idx]