Пример #1
0
    def __init__(self, file_path = "", var_name = "",
                 bathymetry_path = "/skynet3_rech1/huziy/NEMO_OFFICIAL/dev_v3_4_STABLE_2012/NEMOGCM/CONFIG/GLK_LIM3_Michigan/EXP00/bathy_meter.nc"):
        """
        :param file_path:
        :param var_name:
        :param bathymetry_path: used to mask land points
        """
        self.current_time_frame = -1
        self.var_name = var_name

        self.cube = iris.load_cube(file_path, constraint=iris.Constraint(cube_func=lambda c: c.var_name == var_name))
        self.lons, self.lats = cartography.get_xy_grids(self.cube)

        lons2d_gl, lats2d_gl = nemo_commons.get_2d_lons_lats_from_nemo(path=bathymetry_path)
        mask_gl = nemo_commons.get_mask(path=bathymetry_path)

        xs, ys, zs = lat_lon.lon_lat_to_cartesian(lons2d_gl.flatten(), lats2d_gl.flatten())
        xt, yt, zt = lat_lon.lon_lat_to_cartesian(self.lons.flatten(), self.lats.flatten())

        tree = cKDTree(list(zip(xs, ys, zs)))
        dists, indices = tree.query(list(zip(xt, yt, zt)))

        self.mask = mask_gl.flatten()[indices].reshape(self.lons.shape)


        self.nt = self.cube.shape[0]
        assert isinstance(self.cube, Cube)
        print(self.nt)
Пример #2
0
def _map_common(draw_method_name, arg_func, mode, cube, data, *args, **kwargs):
    """
    Draw the given cube on a map using its points or bounds.

    "Mode" parameter will switch functionality between POINT or BOUND plotting.

    """
    # get the 2d x and 2d y from the CS
    if mode == iris.coords.POINT_MODE:
        x, y = cartography.get_xy_grids(cube)
    else:
        try:
            x, y = cartography.get_xy_contiguous_bounded_grids(cube)
        # Exception translation.
        except iris.exceptions.CoordinateMultiDimError:
            raise ValueError("Could not get XY grid from bounds. "
                             "X or Y coordinate not 1D.")
        except ValueError:
            raise ValueError("Could not get XY grid from bounds. "
                             "X or Y coordinate doesn't have 2 bounds "
                             "per point.")

    # take a copy of the data so that we can make modifications to it
    data = data.copy()

    # If we are global, then append the first column of data the array to the
    # last (and add 360 degrees) NOTE: if it is found that this block of code
    # is useful in anywhere other than this plotting routine, it may be better
    # placed in the CS.
    x_coord = cube.coord(axis="X")
    if getattr(x_coord, 'circular', False):
        _, direction = iris.util.monotonic(x_coord.points,
                                           return_direction=True)
        y = np.append(y, y[:, 0:1], axis=1)
        x = np.append(x, x[:, 0:1] + 360 * direction, axis=1)
        data = ma.concatenate([data, data[:, 0:1]], axis=1)

    # Replace non-cartopy subplot/axes with a cartopy alternative.
    cs = cube.coord_system('CoordSystem')
    if cs:
        cartopy_proj = cs.as_cartopy_projection()
    else:
        cartopy_proj = cartopy.crs.PlateCarree()
    ax = _get_cartopy_axes(cartopy_proj)

    draw_method = getattr(ax, draw_method_name)

    # Set the "from transform" keyword.
    # NB. While cartopy doesn't support spherical contours, just use the
    # projection as the source CRS.
    assert 'transform' not in kwargs, 'Transform keyword is not allowed.'
    kwargs['transform'] = cartopy_proj

    if arg_func is not None:
        new_args, kwargs = arg_func(x, y, data, *args, **kwargs)
    else:
        new_args = (x, y, data) + args

    # Draw the contour lines/filled contours.
    return draw_method(*new_args, **kwargs)
Пример #3
0
def mslp(theta, Pi, w, lapse_rate=0.0065, npmsl_height=500.0):
    """Calculate mean sea-level pressure

    Args:
        theta (iris.cube.Cube): Potential temperature at theta-points

        Pi (iris.cube.Cube): Exner pressure at rho-points

        w (iris.cube.Cube): Vertical velocity at theta-points, including
            surface level

        lapse_rate (float): (default is 0.0065)

        npmsl_height (float): (default is 500.0)

    Returns:
        iris.cube.Cube:
    """
    # Extract height coordinate of each grid position
    z_theta = constants.earth_avg_radius.data + w.coord('altitude').points
    z_rho = constants.earth_avg_radius.data + Pi.coord('altitude').points[:-1]
    level_height = theta.coord('level_height').points

    # Calculate grid variables
    grid_lons, grid_lats = cartography.get_xy_grids(theta)
    cos_theta_lat = np.cos(grid_lats)
    delta_lambda = grid_lons[0, 1] - grid_lons[0, 0]
    delta_phi = grid_lats[1, 0] - grid_lats[0, 0]

    # Calculate pressure and exner on theta levels
    Pi = interpolate.interpolate(Pi,
                                 level_height=w.coord('level_height').points)
    P = pressure(Pi)

    # Extract surface pressure and remove from other variables
    P_star = P[0]
    Pi = Pi[1:]
    P = P[1:]

    # Calculate mean sea-level pressure using hacked MetUM routine
    P_msl = fvariable.calc_pmsl(theta.data, Pi.data, P.data, P_star.data,
                                z_theta, z_rho, cos_theta_lat, level_height,
                                constants.Cp_d.data, constants.g.data,
                                constants.Rd.data, lapse_rate,
                                constants.earth_avg_radius.data, delta_lambda,
                                delta_phi, npmsl_height)

    # Copy data into a new cube
    P_msl = P[0].copy(data=P_msl)
    P_msl.rename('air_pressure_at_mean_sea_level')

    return P_msl
Пример #4
0
def true_coords(cube):
    """Extract latitude and longitude from a cube with rotated coordinates

    Args:
        cube (iris.cube.Cube):

    Returns:
        tuple (numpy.ndarray, numpy.ndarray):
            N-dimensional arrays of longitude and latitude
    """
    lon, lat = cartography.get_xy_grids(cube)
    cs = cube.coord_system()
    if cs.grid_mapping_name == 'rotated_latitude_longitude':
        lon, lat = cartography.unrotate_pole(lon, lat,
                                             cs.grid_north_pole_longitude,
                                             cs.grid_north_pole_latitude)

    return lon, lat
Пример #5
0
def polar_coords(cube):
    """Get spherical polar coordinates from a cube

    Args:
        cube (iris.cube.Cube): An iris cube with the relevant coordinate
            information. XY grids and the altitude coordinate are required.

    Returns:
        tuple (numpy.ndarray, numpy.ndarray, numpy.ndarray):
            The zonal and meridional co-ordinates in radians and the vertical
            co-ordinate in metres
    """
    rho = constants.earth_avg_radius.data + cube.coord('altitude').points
    x, y = cartography.get_xy_grids(cube)

    theta = x * (np.pi / 180)
    phi = (90 - y) * (np.pi / 180)

    return theta, phi, rho
Пример #6
0
    def __init__(
        self,
        file_path="",
        var_name="",
        bathymetry_path="/skynet3_rech1/huziy/NEMO_OFFICIAL/dev_v3_4_STABLE_2012/NEMOGCM/CONFIG/GLK_LIM3_Michigan/EXP00/bathy_meter.nc"
    ):
        """
        :param file_path:
        :param var_name:
        :param bathymetry_path: used to mask land points
        """
        self.current_time_frame = -1
        self.var_name = var_name

        self.cube = iris.load_cube(
            file_path,
            constraint=iris.Constraint(
                cube_func=lambda c: c.var_name == var_name))
        self.lons, self.lats = cartography.get_xy_grids(self.cube)

        lons2d_gl, lats2d_gl = nemo_commons.get_2d_lons_lats_from_nemo(
            path=bathymetry_path)
        mask_gl = nemo_commons.get_mask(path=bathymetry_path)

        xs, ys, zs = lat_lon.lon_lat_to_cartesian(lons2d_gl.flatten(),
                                                  lats2d_gl.flatten())
        xt, yt, zt = lat_lon.lon_lat_to_cartesian(self.lons.flatten(),
                                                  self.lats.flatten())

        tree = cKDTree(list(zip(xs, ys, zs)))
        dists, indices = tree.query(list(zip(xt, yt, zt)))

        self.mask = mask_gl.flatten()[indices].reshape(self.lons.shape)

        self.nt = self.cube.shape[0]
        assert isinstance(self.cube, Cube)
        print(self.nt)
Пример #7
0
def rdf_pv(data_in, data_out, name, pole_lon, pole_lat, domain):
    # Load the trajectories
    trajectories = trload.raw(data_in)

    # Check which trajectories are in the domain
    for trajectory in trajectories:
        in_domain(trajectory, pole_lon, pole_lat, domain)

    # Calculate variable at the start of all trajectories
    rlons, rlats, values, cube = rdf(name, trajectories, pole_lon, pole_lat)

    # Save the preliminary data
    with open(data_out + '.pkl', 'w') as output:
        pickle.dump((rlons, rlats, values), output)

    # Put the values on the normal grid
    lons, lats = get_xy_grids(cube)
    field = regular_grid(values, rlons, rlats, lons, lats)
    cube = cube[0].copy(data=field)

    # Save the field
    files.save([cube], data_out + '.nc')

    return
Пример #8
0
def mass_integrals(cubes, lon, lat, theta_level, dtheta, dlambda, dphi):
    """

    Args:
        cubes (iris.cube.CubeList):
        lon (np.Array): Circuit longitudes (degrees)
        lat (np.Array): Circuit latitudes (degrees)
        theta_level: Isentropic level of the circuit
        dtheta (int): Isentrope spacing used to calculate volume integrals
        dlambda (float): Longitudinal grid spacing in radians
        dphi (float): Latitudinal grid spacing in radians

    Returns:
        iris.cube.Cube: A tuple containing four `iris.cube.Cube`s. Area, volume, mass
            and circulation calculated from the integrals.

    """
    # Get height at [theta - dtheta/2, theta, theta + dtheta/2]
    levels = ('air_potential_temperature', [
        theta_level - dtheta / 2.0, theta_level, theta_level + dtheta / 2.0
    ])
    zth = convert.calc('altitude', cubes, levels=levels)

    # Extract model output grid
    glon, glat = cartography.get_xy_grids(zth)
    gridpoints = np.array([glon.flatten(), glat.flatten()]).transpose()

    # Mask all points that are not contained in the circuit
    points = np.array([lon, lat]).transpose()
    pth = Path(points)
    mask = np.logical_not(pth.contains_points(gridpoints).reshape(glat.shape))

    # Area = r**2 cos(phi) dlambda dphi
    area = (a + zth[1])**2 * np.cos(np.deg2rad(glat)) * dlambda * dphi
    area.units = 'm^2'
    area.rename('area')
    total_area = integrate(area, mask)

    # Volume = area * dz
    volume = area * (zth[2] - zth[0])
    # theta coordinate disappears here
    volume.add_aux_coord(area.coord("air_potential_temperature"))
    volume.rename('volume')
    total_volume = integrate(volume, mask)

    # Mass = density * volume
    levels = ('air_potential_temperature', [theta_level])
    density = convert.calc('air_density', cubes, levels=levels)[0]
    mass = density * volume
    mass.rename('mass')
    total_mass = integrate(mass, mask)

    # Circulation = \int rho.pv.dv / dtheta
    pv = convert.calc('ertel_potential_vorticity', cubes, levels=levels)[0]
    pv.convert_units('m^2 K s-1 kg-1')
    pv_substance = pv * mass
    circulation = integrate(pv_substance, mask) / dtheta

    circulation.rename('mass_integrated_circulation')

    return total_area, total_volume, total_mass, circulation