Exemplo n.º 1
0
    def _unrotate_equation(rotated_lons, rotated_lats,
                           rotated_us, rotated_vs, pole_lon, pole_lat):
        # Perform a rotated-pole 'unrotate winds' transformation on arrays of
        # rotated-lat, rotated-lon, u and v.
        # This can be defined as an analytic function : cf. UMDP015

        # Work out the rotation angles.
        lambda_angle = np.radians(pole_lon - 180.0)
        phi_angle = np.radians(90.0 - pole_lat)

        # Get the locations in true lats+lons.
        trueLongitude, trueLatitude = unrotate_pole(rotated_lons,
                                                    rotated_lats,
                                                    pole_lon,
                                                    pole_lat)

        # Calculate inter-coordinate rotation coefficients.
        cos_rot = (np.cos(np.radians(rotated_lons)) *
                   np.cos(np.radians(trueLongitude) - lambda_angle) +
                   np.sin(np.radians(rotated_lons)) *
                   np.sin(np.radians(trueLongitude) - lambda_angle) *
                   np.cos(phi_angle))
        sin_rot = -((np.sin(np.radians(trueLongitude) - lambda_angle) *
                     np.sin(phi_angle))
                    / np.cos(np.radians(rotated_lats)))

        # Matrix-multiply to rotate the vectors.
        u_true = rotated_us * cos_rot - rotated_vs * sin_rot
        v_true = rotated_vs * cos_rot + rotated_us * sin_rot

        return u_true, v_true
Exemplo n.º 2
0
    def _unrotate_equation(rotated_lons, rotated_lats, rotated_us, rotated_vs,
                           pole_lon, pole_lat):
        # Perform a rotated-pole 'unrotate winds' transformation on arrays of
        # rotated-lat, rotated-lon, u and v.
        # This can be defined as an analytic function : cf. UMDP015

        # Work out the rotation angles.
        lambda_angle = np.radians(pole_lon - 180.0)
        phi_angle = np.radians(90.0 - pole_lat)

        # Get the locations in true lats+lons.
        trueLongitude, trueLatitude = unrotate_pole(rotated_lons, rotated_lats,
                                                    pole_lon, pole_lat)

        # Calculate inter-coordinate rotation coefficients.
        cos_rot = np.cos(np.radians(rotated_lons)) * np.cos(
            np.radians(trueLongitude) -
            lambda_angle) + np.sin(np.radians(rotated_lons)) * np.sin(
                np.radians(trueLongitude) - lambda_angle) * np.cos(phi_angle)
        sin_rot = -((np.sin(np.radians(trueLongitude) - lambda_angle) *
                     np.sin(phi_angle)) / np.cos(np.radians(rotated_lats)))

        # Matrix-multiply to rotate the vectors.
        u_true = rotated_us * cos_rot - rotated_vs * sin_rot
        v_true = rotated_vs * cos_rot + rotated_us * sin_rot

        return u_true, v_true
def unrotate_pole_update_cube(cube):
    lat = cube.coord('grid_latitude').points
    lon = cube.coord('grid_longitude').points
    
    cs = cube.coord_system('CoordSystem')

    if isinstance(cs, RotatedGeogCS):
        #print ' %s  - %s - Unrotate pole %s' % (diag, experiment_id, cs)
        lons, lats = meshgrid(lon, lat) 

        lons,lats = unrotate_pole(lons,lats, cs.grid_north_pole_longitude, cs.grid_north_pole_latitude)
       
        lon=lons[0]
        lat=lats[:,0]
                
        for i, coord in enumerate (cube.coords()):
            if coord.standard_name=='grid_latitude':
                lat_dim_coord_cube = i
            if coord.standard_name=='grid_longitude':
                lon_dim_coord_cube = i

    
        # IRIS unrotate_pole uses the default cartopy.crs.Geodetic, which is 
        # WGS84 by default 
        wgs84_cs = GeogCS(semi_major_axis= 6378137.,
                                         inverse_flattening=298.257223563)

    
     
        cube.remove_coord('grid_latitude')
        cube.remove_coord('grid_longitude')
        cube.add_dim_coord(DimCoord(points=lat, standard_name='grid_latitude', units='degrees', coord_system=wgs84_cs), lat_dim_coord_cube)
        cube.add_dim_coord(DimCoord(points=lon, standard_name='grid_longitude', units='degrees', coord_system=wgs84_cs), lon_dim_coord_cube)

        return cube
Exemplo n.º 4
0
def main(infile):

    thiscube = iris.load_cube(infile)

    xmin_rp = min(thiscube.coord('grid_longitude').points) - (0.036/2)
    xmax_rp = max(thiscube.coord('grid_longitude').points) + (0.036/2)
    ymin_rp = min(thiscube.coord('grid_latitude').points) - (0.036/2)
    ymax_rp = max(thiscube.coord('grid_latitude').points) + (0.036/2)

    pole_lat = thiscube.coord("grid_latitude").coord_system.grid_north_pole_latitude
    pole_lon = thiscube.coord("grid_latitude").coord_system.grid_north_pole_longitude

    bbox_ll = carto.unrotate_pole(np.array([xmin_rp,xmax_rp]), np.array([ymin_rp, ymax_rp]), pole_lon, pole_lat)

    latpts = np.arange(bbox_ll[1][0], bbox_ll[1][1], float(0.036))
    lonpts = np.arange(bbox_ll[0][0], bbox_ll[0][1], float(0.036))

    latitude = iris.coords.DimCoord(latpts, standard_name='latitude', units='degrees')
    longitude = iris.coords.DimCoord(lonpts, standard_name='longitude', units='degrees')

    ll = cs.GeogCS(semi_major_axis=6378137, semi_minor_axis=6356752.314245)
    llcube = iris.cube.Cube(np.zeros((latpts.size, lonpts.size), np.float32), dim_coords_and_dims=[(latitude, 0), (longitude, 1)])
    llcube.coord_system = ll

    llcube.coord(axis='x').coord_system = ll
    llcube.coord(axis='y').coord_system = ll

    thiscube_ll = iris.experimental.regrid.regrid_bilinear_rectilinear_src_and_grid(thiscube, llcube)

    outfile = infile.replace('.pp','_ll.nc')

    iris.save(thiscube_ll, outfile)

    return(thiscube_ll)
Exemplo n.º 5
0
def tilable(settings, data_var, query=None):
    file_names = get_file_names(settings["pattern"])
    cubes = get_cubes(file_names[0], data_var)
    cube = cubes[0]

    # Search for lon/lat arrays
    lons, lats = None, None
    for name in dim_names(cube):
        if "latitude" in name:
            lats = cube.coord(name)[:].points
        if "longitude" in name:
            lons = cube.coord(name)[:].points

    # Constrain cube
    dims = {
        key: value
        for key, value in query.items()
        if key not in ["grid_latitude", "grid_longitude"]
    }
    kwargs = {}
    for key, value in query.items():
        if key in ["grid_latitude", "grid_longitude"]:
            continue
        if "time" in key:
            kwargs[key] = fromisoformat(value)
        else:
            kwargs[key] = float(value)

    cube_slice = cube.extract(iris.Constraint(**kwargs))

    coord_system = cube.coord_system()
    if isinstance(coord_system, RotatedGeogCS):
        # UKV Rotated pole support
        rotated_lons, rotated_lats = np.meshgrid(lons, lats)
        pole_lon = coord_system.grid_north_pole_longitude
        pole_lat = coord_system.grid_north_pole_latitude
        lons, lats = unrotate_pole(rotated_lons, rotated_lats, pole_lon,
                                   pole_lat)

    # # Roll input data into [-180, 180] range
    # if np.any(lons > 180.0):
    #     shift_by = np.sum(lons > 180.0)
    #     lons[lons > 180.0] -= 360.
    #     lons = np.roll(lons, shift_by)
    #     values = np.roll(values, shift_by, axis=1)

    if cube_slice.ndim != 2:
        raise Exception(f"unsupported ndim: {cube_slice.ndim}")

    values = cube_slice.data.copy()
    return {
        "latitude": lats,
        "longitude": lons,
        "values": values,
        "units": str(cube.units)
    }
Exemplo n.º 6
0
def unroate_pole(resource, write_to_file=True): 
  from numpy import reshape, repeat
  from iris.analysis import cartography  as ct
  
  ds = Dataset(resource, mode='a')
  
  try:
    if 'rotated_latitude_longitude' in ds.variables:
      rp = ds.variables['rotated_latitude_longitude']
    elif 'rotated_pole' in ds.variables:   
      rp = ds.variables['rotated_pole']
    else: 
      logger.debug('rotated pole variable not found')
    pole_lat = rp.grid_north_pole_latitude
    pole_lon = rp.grid_north_pole_longitude
  except Exception as e: 
    logger.debug('failed to find rotated_pole coorinates: %s' % e)
  try:   
    if 'rlat' in ds.variables: 
      rlats = ds.variables['rlat']
      rlons = ds.variables['rlon']
      
    if 'x' in ds.variables:
      rlats = ds.variables['y']
      rlons = ds.variables['x'] 
  except Exception as e: 
    logger.debug('failed to read in rotated coordiates %s '% e)
    
  try:   
    rlons_i = reshape(rlons,(1,len(rlons)))
    rlats_i = reshape(rlats,(len(rlats),1))
    grid_rlats = repeat(rlats_i, (len(rlons)), axis=1)
    grid_rlons = repeat(rlons_i, (len(rlats)), axis=0)
  except Exception as e: 
    logger.debug('failed to repeat coordinates %s'% e)
  
  lons, lats = ct.unrotate_pole(grid_rlons, grid_rlats, pole_lon, pole_lat)
  
  if write_to_file == True: 
    lat = ds.createVariable('lat','f8',('rlat','rlon'))
    lon = ds.createVariable('lon','f8',('rlat','rlon'))    
    
    lon.standard_name = "longitude" ;
    lon.long_name = "longitude coordinate" ;
    lon.units = 'degrees_east'
    lat.standard_name = "latitude" ;
    lat.long_name = "latitude coordinate" ;
    lat.units = 'degrees_north'
    
    lat[:] = lats
    lon[:] = lons
  
  ds.close()
  return lats, lons
Exemplo n.º 7
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
Exemplo n.º 8
0
 def test_2d_coords_contour(self):
     ny, nx = 4, 6
     x1 = np.linspace(-20, 70, nx)
     y1 = np.linspace(10, 60, ny)
     data = np.zeros((ny, nx))
     data.flat[:] = np.arange(nx * ny) % 7
     cube = Cube(data, long_name='Odd data')
     x2, y2 = np.meshgrid(x1, y1)
     true_lons, true_lats = unrotate_pole(x2, y2, -130., 77.)
     co_x = AuxCoord(true_lons, standard_name='longitude', units='degrees')
     co_y = AuxCoord(true_lats, standard_name='latitude', units='degrees')
     cube.add_aux_coord(co_y, (0, 1))
     cube.add_aux_coord(co_x, (0, 1))
     ax = plt.axes(projection=ccrs.PlateCarree())
     qplt.contourf(cube)
     ax.coastlines(color='red')
     ax.gridlines(draw_labels=True)
     ax.set_extent((0, 180, 0, 90))
     self.check_graphic()
Exemplo n.º 9
0
def setCubeRegularLatLon(cube, field, filename):

    # https://github.com/SciTools/iris/issues/448
    glon = cube.coord('grid_longitude')
    rotated_lons = glon.points
    glat = cube.coord('grid_latitude')
    rotated_lats = glat.points
    pole_lat = glat.coord_system.grid_north_pole_latitude
    pole_lon = glat.coord_system.grid_north_pole_longitude

    rotated_lats, rotated_lons = meshgrid(rotated_lons, rotated_lats)

    lons, lats = icart.unrotate_pole(rotated_lons, rotated_lats, pole_lon, pole_lat)

    ## the below lat is 2D array
    regular2DLatitude = AuxCoord(lons, standard_name='longitude', units='degree_north')
    ## the below lon is 2D array
    regular2DLongitude = AuxCoord(lats, standard_name='latitude', units='degree_east')

    cube.remove_coord('grid_latitude')
    cube.remove_coord('grid_longitude')

    cube.add_aux_coord(regular2DLatitude, [0, 1])
    cube.add_aux_coord(regular2DLongitude, [0, 1])
Exemplo n.º 10
0
def setCubeRegularLatLon(cube, field, filename):
        
    # https://github.com/SciTools/iris/issues/448
    glon = cube.coord('grid_longitude')
    rotated_lons = glon.points
    glat = cube.coord('grid_latitude')
    rotated_lats = glat.points
    pole_lat = glat.coord_system.grid_north_pole_latitude
    pole_lon = glat.coord_system.grid_north_pole_longitude

    rotated_lats, rotated_lons = meshgrid(rotated_lons, rotated_lats)

    lons, lats = icart.unrotate_pole(rotated_lons, rotated_lats, pole_lon, pole_lat)

    ## the below lat is 2D array
    regular2DLatitude = AuxCoord(lons, standard_name='longitude', units='degree_north')
    ## the below lon is 2D array
    regular2DLongitude = AuxCoord(lats, standard_name='latitude', units='degree_east')
    
    cube.remove_coord('grid_latitude')
    cube.remove_coord('grid_longitude')
    
    cube.add_aux_coord(regular2DLatitude, [0, 1])
    cube.add_aux_coord(regular2DLongitude, [0, 1])
Exemplo n.º 11
0
def unrotateGrid(data):
    ##
    ##      ROTATE GRID BACK TO STANDARD
    ##

    import iris.analysis.cartography as ircrt

    ### LAM Configuration from suite u-bg610
    dlat = 0.015714
    dlon = 0.016334
    frst_lat = -5.6112
    frst_lon = 353.0345
    pole_lat = 37.5000
    pole_lon = 177.5000

    rot_lat = data.coord('grid_latitude').points
    rot_lon = data.coord('grid_longitude').points

    rot_pole = data.coord('grid_latitude').coord_system.as_cartopy_crs()

    lon, lat = ircrt.unrotate_pole(rot_lon, rot_lat, frst_lon, frst_lat)

    # Print to check conversion
    print ('******')
    print ('Test of unrotated coordinate grid: ')
    print ('Rotated lon coord = ', rot_lon[0])
    print ('Rotated lat coord = ', rot_lat[0])
    print ('Lon = ', lon[0])
    print ('Lat = ', lat[0])
    print (' ')

    # ******
    # lat/lon vertices of nest (output):  85.960219407715 80.41973098346767 49.567255645848604 -27.55740381723681
    # ******

    return lon, lat
Exemplo n.º 12
0
def sample_2d_latlons(regional=False, rotated=False, transformed=False):
    """
    Construct small 2d cubes with 2d X and Y coordinates.

    This makes cubes with 'expanded' coordinates (4 bounds per cell), analagous
    to ORCA data.
    The coordinates are always geographical, so either it has a coord system
    or they are "true" lats + lons.
    ( At present, they are always latitudes and longitudes, but maybe in a
    rotated system. )
    The results always have fully contiguous bounds.

    Kwargs:
    * regional (bool):
        If False (default), results cover the whole globe, and there is
        implicit connectivity between rhs + lhs of the array.
        If True, coverage is regional and edges do not connect.
    * rotated (bool):
        If False, X and Y coordinates are true-latitudes and longitudes, with
        an implicit coordinate system (i.e. None).
        If True, the X and Y coordinates are lats+lons in a selected
        rotated-latlon coordinate system.
    * transformed (bool):
        Build coords from rotated coords as for 'rotated', but then replace
        their values with the equivalent "true" lats + lons, and no
        coord-system (defaults to true-latlon).
        In this case, the X and Y coords are no longer 'meshgrid' style,
        i.e. the points + bounds values vary in *both* dimensions.

    .. note::

        'transformed' is an alternative to 'rotated' :  when 'transformed' is
        set, then 'rotated' has no effect.

    .. Some sample results printouts ::

        >>> print(sample_2d_latlons())
        test_data / (unknown)               (-- : 5; -- : 6)
             Auxiliary coordinates:
                  latitude                      x       x
                  longitude                     x       x
        >>>
        >>> print(sample_2d_latlons().coord(axis='x')[0, :2])
        AuxCoord(array([ 37.5 ,  93.75]),
                 bounds=array([[   0.   ,   65.625,   65.625,    0.   ],
                               [  65.625,  121.875,  121.875,   65.625]]),
                 standard_name='longitude', units=Unit('degrees'))
        >>> print(np.round(sample_2d_latlons().coord(axis='x').points, 3))
        [[  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]]
        >>> print(np.round(sample_2d_latlons().coord(axis='y').points, 3))
        [[-85.  -85.  -85.  -85.  -85.  -85. ]
         [-47.5 -47.5 -47.5 -47.5 -47.5 -47.5]
         [-10.  -10.  -10.  -10.  -10.  -10. ]
         [ 27.5  27.5  27.5  27.5  27.5  27.5]
         [ 65.   65.   65.   65.   65.   65. ]]


        >>> print(np.round(
            sample_2d_latlons(rotated=True).coord(axis='x').points, 3))
        [[  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]]
        >>> print(sample_2d_latlons(rotated=True).coord(axis='y').coord_system)
        RotatedGeogCS(75.0, 120.0)


        >>> print(
            sample_2d_latlons(transformed=True).coord(axis='y').coord_system)
        None
        >>> print(np.round(
            sample_2d_latlons(transformed=True).coord(axis='x').points, 3))
        [[ -50.718  -40.983  -46.74   -71.938  -79.293  -70.146]
         [ -29.867   17.606   77.936  157.145 -141.037  -93.172]
         [ -23.139   31.007   87.699  148.322 -154.639 -100.505]
         [ -16.054   41.218   92.761  143.837 -164.738 -108.105]
         [  10.86    61.78   100.236  137.285  175.511 -135.446]]
        >>> print(np.round(
            sample_2d_latlons(transformed=True).coord(axis='y').points, 3))
        [[-70.796 -74.52  -79.048 -79.26  -74.839 -70.96 ]
         [-34.99  -46.352 -59.721 -60.34  -47.305 -35.499]
         [  1.976 -10.626 -22.859 -23.349 -11.595   1.37 ]
         [ 38.914  25.531  14.312  13.893  24.585  38.215]
         [ 74.197  60.258  51.325  51.016  59.446  73.268]]
        >>>

    """
    def sample_cube(xargs, yargs):
        # Make a test cube with given latitude + longitude coordinates.
        # xargs/yargs are args for np.linspace (start, stop, N), to make the X
        # and Y coordinate points.
        x0, x1, nx = xargs
        y0, y1, ny = yargs
        # Data has cycling values, staggered a bit in successive rows.
        data = np.zeros((ny, nx))
        data.flat[:] = np.arange(ny * nx) % (nx + 2)
        # Build a 2d cube with longitude + latitude coordinates.
        cube = Cube(data, long_name='test_data')
        x_pts = np.linspace(x0, x1, nx, endpoint=True)
        y_pts = np.linspace(y0, y1, ny, endpoint=True)
        co_x = DimCoord(x_pts, standard_name='longitude', units='degrees')
        co_y = DimCoord(y_pts, standard_name='latitude', units='degrees')
        cube.add_dim_coord(co_y, 0)
        cube.add_dim_coord(co_x, 1)
        return cube

    # Start by making a "normal" cube with separate 1-D X and Y coords.
    if regional:
        # Make a small regional cube.
        cube = sample_cube(xargs=(150., 243.75, 6), yargs=(-10., 40., 5))

        # Add contiguous bounds.
        for ax in ('x', 'y'):
            cube.coord(axis=ax).guess_bounds()
    else:
        # Global data, but at a drastically reduced resolution.
        cube = sample_cube(xargs=(37.5, 318.75, 6), yargs=(-85., 65., 5))

        # Make contiguous bounds and adjust outer edges to ensure it is global.
        for name in ('longitude', 'latitude'):
            coord = cube.coord(name)
            coord.guess_bounds()
            bds = coord.bounds.copy()
            # Make bounds global, by fixing lowest and uppermost values.
            if name == 'longitude':
                bds[0, 0] = 0.0
                bds[-1, 1] = 360.0
            else:
                bds[0, 0] = -90.0
                bds[-1, 1] = 90.0
            coord.bounds = bds

    # Now convert the 1-d coords to 2-d equivalents.
    # Get original 1-d coords.
    co_1d_x, co_1d_y = [cube.coord(axis=ax).copy() for ax in ('x', 'y')]

    # Calculate 2-d equivalents.
    co_2d_x, co_2d_y = grid_coords_2d_from_1d(co_1d_x, co_1d_y)

    # Remove the old grid coords.
    for coord in (co_1d_x, co_1d_y):
        cube.remove_coord(coord)

    # Add the new grid coords.
    for coord in (co_2d_x, co_2d_y):
        cube.add_aux_coord(coord, (0, 1))

    if transformed or rotated:
        # Put the cube locations into a rotated coord system.
        pole_lat, pole_lon = 75.0, 120.0
        if transformed:
            # Reproject coordinate values from rotated to true lat-lons.
            co_x, co_y = [cube.coord(axis=ax) for ax in ('x', 'y')]
            # Unrotate points.
            lons, lats = co_x.points, co_y.points
            lons, lats = unrotate_pole(lons, lats, pole_lon, pole_lat)
            co_x.points, co_y.points = lons, lats
            # Unrotate bounds.
            lons, lats = co_x.bounds, co_y.bounds
            # Note: save the shape, flatten + then re-apply the shape, because
            # "unrotate_pole" uses "cartopy.crs.CRS.transform_points", which
            # only works on arrays of 1 or 2 dimensions.
            shape = lons.shape
            lons, lats = unrotate_pole(lons.flatten(), lats.flatten(),
                                       pole_lon, pole_lat)
            co_x.bounds, co_y.bounds = lons.reshape(shape), lats.reshape(shape)
        else:
            # "Just" rotate operation : add a coord-system to each coord.
            cs = RotatedGeogCS(pole_lat, pole_lon)
            for coord in cube.coords():
                coord.coord_system = cs

    return cube
Exemplo n.º 13
0
    fu = '%s%s/%s/%s%s.pp' % (pp_file_path, expmin1, experiment_id,
                              experiment_id, diag)

    print experiment_id
    sys.stdout.flush()

    cube = iris.load_cube(fu, glob_tc)
    #cube = iris.load_cube(fu)
    cs = cube.coord_system('CoordSystem')

    lons, lats = np.meshgrid(
        cube.coord('grid_longitude').points,
        cube.coord('grid_latitude').points)

    unrot_lons, unrot_lats = unrotate_pole(lons, lats,
                                           cs.grid_north_pole_longitude,
                                           cs.grid_north_pole_latitude)

    latmin = unrot_lats.min()
    latmax = unrot_lats.max()
    lonmin = unrot_lons.min()
    lonmax = unrot_lons.max()

    lat_constraint = iris.Constraint(
        grid_latitude=lambda la: latmin <= la.point <= latmax)
    lon_constraint = iris.Constraint(
        grid_longitude=lambda lo: lonmin <= lo.point <= lonmax)
    #time_constraint=
    regrid_cube = regrid_cube_init.extract(lat_constraint & lon_constraint)

    #pdb.set_trace()
 expmin1 = experiment_id[:-1]

 fu = '%s%s/%s/%s%s.pp' % (pp_file_path, expmin1, experiment_id, experiment_id, diag)

 print experiment_id
 sys.stdout.flush()

      
 cube = iris.load_cube(fu,   glob_tc)
 #cube = iris.load_cube(fu)       
 cs = cube.coord_system('CoordSystem')

 lons, lats = np.meshgrid(cube.coord('grid_longitude').points, cube.coord('grid_latitude').points)

 unrot_lons, unrot_lats = unrotate_pole(lons, 
                                        lats,
                                        cs.grid_north_pole_longitude,
                                        cs.grid_north_pole_latitude)
                                         
 latmin = unrot_lats.min()
 latmax = unrot_lats.max()
 lonmin = unrot_lons.min()
 lonmax = unrot_lons.max()

 lat_constraint=iris.Constraint(grid_latitude= lambda la: latmin <= la.point <= latmax)
 lon_constraint=iris.Constraint(grid_longitude= lambda lo: lonmin <= lo.point <= lonmax)  
#time_constraint=
 regrid_cube = regrid_cube_init.extract(lat_constraint & lon_constraint)   

 #pdb.set_trace()

 mean_list=[]
Exemplo n.º 15
0
def unrotate_pole(resource, write_to_file=True):
    from numpy import reshape, repeat
    from iris.analysis import cartography as ct

    ds = Dataset(resource, mode="a")

    if "lat" in ds.variables.keys():
        logger.info("coordinates already unrotated")
        lats = ds.variables["lat"][:]
        lons = ds.variables["lon"][:]

    else:
        try:
            if "rotated_latitude_longitude" in ds.variables:
                rp = ds.variables["rotated_latitude_longitude"]
            elif "rotated_pole" in ds.variables:
                rp = ds.variables["rotated_pole"]
            else:
                logger.debug("rotated pole variable not found")
            pole_lat = rp.grid_north_pole_latitude
            pole_lon = rp.grid_north_pole_longitude
        except Exception as e:
            logger.debug("failed to find rotated_pole coordinates: %s" % e)
        try:
            if "rlat" in ds.variables:
                rlats = ds.variables["rlat"]
                rlons = ds.variables["rlon"]

            if "x" in ds.variables:
                rlats = ds.variables["y"]
                rlons = ds.variables["x"]
        except Exception as e:
            logger.debug("failed to read in rotated coordiates %s " % e)

        try:
            rlons_i = reshape(rlons, (1, len(rlons)))
            rlats_i = reshape(rlats, (len(rlats), 1))
            grid_rlats = repeat(rlats_i, (len(rlons)), axis=1)
            grid_rlons = repeat(rlons_i, (len(rlats)), axis=0)
        except Exception as e:
            logger.debug("failed to repeat coordinates %s" % e)

        lons, lats = ct.unrotate_pole(grid_rlons, grid_rlats, pole_lon, pole_lat)

        if write_to_file == True:
            lat = ds.createVariable("lat", "f8", ("rlat", "rlon"))
            lon = ds.createVariable("lon", "f8", ("rlat", "rlon"))

            lon.standard_name = "longitude"
            lon.long_name = "longitude coordinate"
            lon.units = "degrees_east"
            lat.standard_name = "latitude"
            lat.long_name = "latitude coordinate"
            lat.units = "degrees_north"

            lat[:] = lats
            lon[:] = lons

    ds.close()

    return lats, lons
Exemplo n.º 16
0
def sample_2d_latlons(regional=False, rotated=False, transformed=False):
    """
    Construct small 2d cubes with 2d X and Y coordinates.

    This makes cubes with 'expanded' coordinates (4 bounds per cell), analagous
    to ORCA data.
    The coordinates are always geographical, so either it has a coord system
    or they are "true" lats + lons.
    ( At present, they are always latitudes and longitudes, but maybe in a
    rotated system. )
    The results always have fully contiguous bounds.

    Kwargs:
    * regional (bool):
        If False (default), results cover the whole globe, and there is
        implicit connectivity between rhs + lhs of the array.
        If True, coverage is regional and edges do not connect.
    * rotated (bool):
        If False, X and Y coordinates are true-latitudes and longitudes, with
        an implicit coordinate system (i.e. None).
        If True, the X and Y coordinates are lats+lons in a selected
        rotated-latlon coordinate system.
    * transformed (bool):
        Build coords from rotated coords as for 'rotated', but then replace
        their values with the equivalent "true" lats + lons, and no
        coord-system (defaults to true-latlon).
        In this case, the X and Y coords are no longer 'meshgrid' style,
        i.e. the points + bounds values vary in *both* dimensions.

    .. note::

        'transformed' is an alternative to 'rotated' :  when 'transformed' is
        set, then 'rotated' has no effect.

    .. Some sample results printouts ::

        >>> print(sample_2d_latlons())
        test_data / (unknown)               (-- : 5; -- : 6)
             Auxiliary coordinates:
                  latitude                      x       x
                  longitude                     x       x
        >>>
        >>> print(sample_2d_latlons().coord(axis='x')[0, :2])
        AuxCoord(array([ 37.5 ,  93.75]),
                 bounds=array([[   0.   ,   65.625,   65.625,    0.   ],
                               [  65.625,  121.875,  121.875,   65.625]]),
                 standard_name='longitude', units=Unit('degrees'))
        >>> print(np.round(sample_2d_latlons().coord(axis='x').points, 3))
        [[  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]]
        >>> print(np.round(sample_2d_latlons().coord(axis='y').points, 3))
        [[-85.  -85.  -85.  -85.  -85.  -85. ]
         [-47.5 -47.5 -47.5 -47.5 -47.5 -47.5]
         [-10.  -10.  -10.  -10.  -10.  -10. ]
         [ 27.5  27.5  27.5  27.5  27.5  27.5]
         [ 65.   65.   65.   65.   65.   65. ]]


        >>> print(np.round(
            sample_2d_latlons(rotated=True).coord(axis='x').points, 3))
        [[  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]
         [  37.5    93.75  150.    206.25  262.5   318.75]]
        >>> print(sample_2d_latlons(rotated=True).coord(axis='y').coord_system)
        RotatedGeogCS(75.0, 120.0)


        >>> print(
            sample_2d_latlons(transformed=True).coord(axis='y').coord_system)
        None
        >>> print(np.round(
            sample_2d_latlons(transformed=True).coord(axis='x').points, 3))
        [[ -50.718  -40.983  -46.74   -71.938  -79.293  -70.146]
         [ -29.867   17.606   77.936  157.145 -141.037  -93.172]
         [ -23.139   31.007   87.699  148.322 -154.639 -100.505]
         [ -16.054   41.218   92.761  143.837 -164.738 -108.105]
         [  10.86    61.78   100.236  137.285  175.511 -135.446]]
        >>> print(np.round(
            sample_2d_latlons(transformed=True).coord(axis='y').points, 3))
        [[-70.796 -74.52  -79.048 -79.26  -74.839 -70.96 ]
         [-34.99  -46.352 -59.721 -60.34  -47.305 -35.499]
         [  1.976 -10.626 -22.859 -23.349 -11.595   1.37 ]
         [ 38.914  25.531  14.312  13.893  24.585  38.215]
         [ 74.197  60.258  51.325  51.016  59.446  73.268]]
        >>>

    """
    def sample_cube(xargs, yargs):
        # Make a test cube with given latitude + longitude coordinates.
        # xargs/yargs are args for np.linspace (start, stop, N), to make the X
        # and Y coordinate points.
        x0, x1, nx = xargs
        y0, y1, ny = yargs
        # Data has cycling values, staggered a bit in successive rows.
        data = np.zeros((ny, nx))
        data.flat[:] = np.arange(ny * nx) % (nx + 2)
        # Build a 2d cube with longitude + latitude coordinates.
        cube = Cube(data, long_name="test_data")
        x_pts = np.linspace(x0, x1, nx, endpoint=True)
        y_pts = np.linspace(y0, y1, ny, endpoint=True)
        co_x = DimCoord(x_pts, standard_name="longitude", units="degrees")
        co_y = DimCoord(y_pts, standard_name="latitude", units="degrees")
        cube.add_dim_coord(co_y, 0)
        cube.add_dim_coord(co_x, 1)
        return cube

    # Start by making a "normal" cube with separate 1-D X and Y coords.
    if regional:
        # Make a small regional cube.
        cube = sample_cube(xargs=(150.0, 243.75, 6), yargs=(-10.0, 40.0, 5))

        # Add contiguous bounds.
        for ax in ("x", "y"):
            cube.coord(axis=ax).guess_bounds()
    else:
        # Global data, but at a drastically reduced resolution.
        cube = sample_cube(xargs=(37.5, 318.75, 6), yargs=(-85.0, 65.0, 5))

        # Make contiguous bounds and adjust outer edges to ensure it is global.
        for name in ("longitude", "latitude"):
            coord = cube.coord(name)
            coord.guess_bounds()
            bds = coord.bounds.copy()
            # Make bounds global, by fixing lowest and uppermost values.
            if name == "longitude":
                bds[0, 0] = 0.0
                bds[-1, 1] = 360.0
            else:
                bds[0, 0] = -90.0
                bds[-1, 1] = 90.0
            coord.bounds = bds

    # Now convert the 1-d coords to 2-d equivalents.
    # Get original 1-d coords.
    co_1d_x, co_1d_y = [cube.coord(axis=ax).copy() for ax in ("x", "y")]

    # Calculate 2-d equivalents.
    co_2d_x, co_2d_y = grid_coords_2d_from_1d(co_1d_x, co_1d_y)

    # Remove the old grid coords.
    for coord in (co_1d_x, co_1d_y):
        cube.remove_coord(coord)

    # Add the new grid coords.
    for coord in (co_2d_x, co_2d_y):
        cube.add_aux_coord(coord, (0, 1))

    if transformed or rotated:
        # Put the cube locations into a rotated coord system.
        pole_lat, pole_lon = 75.0, 120.0
        if transformed:
            # Reproject coordinate values from rotated to true lat-lons.
            co_x, co_y = [cube.coord(axis=ax) for ax in ("x", "y")]
            # Unrotate points.
            lons, lats = co_x.points, co_y.points
            lons, lats = unrotate_pole(lons, lats, pole_lon, pole_lat)
            co_x.points, co_y.points = lons, lats
            # Unrotate bounds.
            lons, lats = co_x.bounds, co_y.bounds
            # Note: save the shape, flatten + then re-apply the shape, because
            # "unrotate_pole" uses "cartopy.crs.CRS.transform_points", which
            # only works on arrays of 1 or 2 dimensions.
            shape = lons.shape
            lons, lats = unrotate_pole(lons.flatten(), lats.flatten(),
                                       pole_lon, pole_lat)
            co_x.bounds, co_y.bounds = lons.reshape(shape), lats.reshape(shape)
        else:
            # "Just" rotate operation : add a coord-system to each coord.
            cs = RotatedGeogCS(pole_lat, pole_lon)
            for coord in cube.coords():
                coord.coord_system = cs

    return cube
Exemplo n.º 17
0
def unrotate_pole(resource, write_to_file=False):
    """
    Calculates the unrotatated coordinates for a rotated pole grid

    :param resource: netCDF file or list of files of one datatset
    :param write_to_file: calculated values will be written to file if True (default=False)

    :return list: lats, lons
    """
    from numpy import reshape, repeat
    from iris.analysis import cartography as ct

    if len(resource) == 1:
        ds = Dataset(resource[0])
    else:
        ds = MFDataset(resource)

    # ds = MFDataset(resource)

    if 'lat' in ds.variables.keys():
        LOGGER.info('file include unrotated coordinate values')
        lats = ds.variables['lat'][:]
        lons = ds.variables['lon'][:]
    else:
        try:
            if 'rotated_latitude_longitude' in ds.variables:
                rp = ds.variables['rotated_latitude_longitude']
            elif 'rotated_pole' in ds.variables:
                rp = ds.variables['rotated_pole']
            else:
                LOGGER.debug('rotated pole variable not found')
            pole_lat = rp.grid_north_pole_latitude
            pole_lon = rp.grid_north_pole_longitude
        except:
            LOGGER.exception('failed to find rotated_pole coordinates')
        try:
            if 'rlat' in ds.variables:
                rlats = ds.variables['rlat']
                rlons = ds.variables['rlon']

            if 'x' in ds.variables:
                rlats = ds.variables['y']
                rlons = ds.variables['x']
        except:
            LOGGER.exception('failed to read in rotated coordiates')

        try:
            rlons_i = reshape(rlons, (1, len(rlons)))
            rlats_i = reshape(rlats, (len(rlats), 1))
            grid_rlats = repeat(rlats_i, (len(rlons)), axis=1)
            grid_rlons = repeat(rlons_i, (len(rlats)), axis=0)
        except:
            LOGGER.execption('failed to repeat coordinates')

        lons, lats = ct.unrotate_pole(grid_rlons, grid_rlats, pole_lon,
                                      pole_lat)

    if write_to_file is True:
        lat = ds.createVariable('lat', 'f8', ('rlat', 'rlon'))
        lon = ds.createVariable('lon', 'f8', ('rlat', 'rlon'))

        lon.standard_name = "longitude"
        lon.long_name = "longitude coordinate"
        lon.units = 'degrees_east'
        lat.standard_name = "latitude"
        lat.long_name = "latitude coordinate"
        lat.units = 'degrees_north'

        lat[:] = lats
        lon[:] = lons

    ds.close()

    return lats, lons
Exemplo n.º 18
0
def extract_section(cube, waypoints, n_sample_points=30):
    """
    Extract a section from the cube given lat-lon waypoints. This works
    on any cube with x and y dimension coordinates. If the cube also contains
    Z or T etc dimension coordinates then these are retained in the extracted
    section.

    :param cube: Iris cube
    :param waypoints: List of dictionaries, whose keys are 'latitude' and
                      'longitude' and whose values are the lat/lon points
                      that should be included in the section.
    :param n_sample_points: Number of sample points to include in section

    :returns: An iris cube which no longer has X and Y as dimension coordinates
              but instead has an 'i_sample_point' coordinate.
              If latitude and longitude were not in the original cube, they
              are added to to the new section cube.

    Load sample data - a gridded surface-only, time-varying cube:

    >>> import config
    >>> sample_datadir = config.SAMPLE_DATADIR+'gridded_cube_list/'
    >>> cube = iris.load_cube(sample_datadir+'aqum_oper_1days.nc',
    ... 'mass_concentration_of_ozone_in_air')
    >>> print(cube) # doctest: +NORMALIZE_WHITESPACE
    mass_concentration_of_ozone_in_air / (ug/m3) (time: 25; grid_latitude: 182; \
grid_longitude: 146)
         Dimension coordinates:
              time                 x                  -                    -
              grid_latitude        -                  x                    -
              grid_longitude       -                  -                    x
         Auxiliary coordinates:
              forecast_period      x                  -                    -
              surface_altitude     -                  x                    x
         Derived coordinates:
              altitude             -                  x                    x
         Scalar coordinates:
              atmosphere_hybrid_height_coordinate: 20.000338 m, \
bound=(0.0, 49.998882) m
              forecast_day: 1.0 Days
              model_level_number: 1
              sigma: 0.9977165, bound=(1.0, 0.99429625)
         Attributes:
              Conventions: CF-1.5
              STASH: m01s34i001
              label: aqum_oper
              short_name: O3
              source: Data from Met Office Unified Model
         Cell methods:
              mean: time (1 hour)

    Set up waypoints list:

    >>> waypoints = [
    ... {'latitude': 50.8, 'longitude': -1.8},
    ... {'latitude': 51.2, 'longitude':	-1.2},
    ... {'latitude': 51.4, 'longitude':	-0.9}]

    Extract section along these waypoints:

    >>> section = extract_section(cube, waypoints)
    >>> print(section)
    mass_concentration_of_ozone_in_air / (ug/m3) (time: 25; i_sample_point: 30)
         Dimension coordinates:
              time                                    x                   -
              i_sample_point                          -                   x
         Auxiliary coordinates:
              forecast_period                         x                   -
              grid_latitude                           -                   x
              grid_longitude                          -                   x
              latitude                                -                   x
              longitude                               -                   x
              surface_altitude                        -                   x
         Derived coordinates:
              altitude                                -                   x
         Scalar coordinates:
              atmosphere_hybrid_height_coordinate: 20.000338 m, \
bound=(0.0, 49.998882) m
              forecast_day: 1.0 Days
              model_level_number: 1
              sigma: 0.9977165, bound=(1.0, 0.99429625)
         Attributes:
              Conventions: CF-1.5
              STASH: m01s34i001
              label: aqum_oper
              short_name: O3
              source: Data from Met Office Unified Model
         Cell methods:
              mean: time (1 hour)

    """

    xcoord, ycoord = guess_coord_names(cube, ['X', 'Y'])

    if None in [xcoord, ycoord]:
        raise ValueError('Can not calculate section for this cube')

    lat_lon_coord_system = iris.coord_systems.GeogCS(
        semi_major_axis=iris.fileformats.pp.EARTH_RADIUS)
    lons = np.array([waypoint['longitude'] for waypoint in waypoints])
    lats = np.array([waypoint['latitude'] for waypoint in waypoints])

    #Calculate waypoints in cube coordinates
    if xcoord == 'grid_longitude' and ycoord == 'grid_latitude':
        #Rotated pole
        pole_lon = cube.coord(xcoord).coord_system.grid_north_pole_longitude
        pole_lat = cube.coord(ycoord).coord_system.grid_north_pole_latitude

        #Perform rotation
        rot_lons, rot_lats = rotate_pole(lons, lats, pole_lon, pole_lat)

        #Put back into waypoints format
        cube_waypoints = [{
            xcoord: lon,
            ycoord: lat
        } for lat, lon in zip(rot_lats, rot_lons)]
    elif xcoord == 'projection_x_coordinate' and \
         ycoord == 'projection_y_coordinate':
        #Other coordinate system (note this may work for x/ycoords other than
        #those considered here
        ll_crs = lat_lon_coord_system.as_cartopy_crs()
        cube_crs = cube.coord(xcoord).coord_system.as_cartopy_crs()
        #Convert to lat/lon points
        cube_lonlats = ll_crs.transform_points(cube_crs, lons, lats)
        cube_lons = cube_lonlats[:, 0]
        cube_lats = cube_lonlats[:, 1]
        #Put back into waypoints format
        cube_waypoints = [{
            xcoord: lon,
            ycoord: lat
        } for lat, lon in zip(cube_lats, cube_lons)]

    elif xcoord == 'longitude' and ycoord == 'latitude':
        cube_waypoints = waypoints
    else:
        raise ValueError('Unable to convert cube x/y points to lat/lon')

    #Specify the trajectory (straight-line) by giving the
    # start and end of the line and specifying how many points there
    # should be on the line (in this case 30)
    sample_points = trajectory.Trajectory(cube_waypoints,
                                          sample_count=n_sample_points)

    #Extract the data from the cube at the sample points
    #(Note this only works with iris vn2.2+)
    section = sample_points.interpolate(cube)

    #Rename new index coordinate
    section.coord('index').rename('i_sample_point')

    #Also add latitude and longitude coords to section
    #if not in original cube
    if xcoord != 'longitude' and ycoord != 'latitude':

        cube_lons_samplepts = np.array(
            [d[xcoord] for d in sample_points.sampled_points])
        cube_lats_samplepts = np.array(
            [d[ycoord] for d in sample_points.sampled_points])

        if xcoord == 'grid_longitude' and ycoord == 'grid_latitude':
            section_lons, section_lats = unrotate_pole(cube_lons_samplepts,
                                                       cube_lats_samplepts,
                                                       pole_lon, pole_lat)
        elif xcoord == 'projection_x_coordinate' and \
             ycoord == 'projection_y_coordinate':
            #Other coordinate system (note this may work for x/ycoords other than
            #those considered here
            lonlats = cube_crs.transform_points(ll_crs, cube_lons_samplepts,
                                                cube_lats_samplepts)
            section_lons = lonlats[:, 0]
            section_lats = lonlats[:, 1]

        #Set up lat/lon coords and add as aux coords
        lon_coord = iris.coords.AuxCoord(section_lons,
                                         standard_name='longitude',
                                         units='degrees',
                                         coord_system=lat_lon_coord_system)

        lat_coord = iris.coords.AuxCoord(section_lats,
                                         standard_name='latitude',
                                         units='degrees',
                                         coord_system=lat_lon_coord_system)
        section.add_aux_coord(lon_coord, section.coord_dims(xcoord))
        section.add_aux_coord(lat_coord, section.coord_dims(ycoord))

    return section
Exemplo n.º 19
0
def unrotate_pole(resource, write_to_file=True):
    """
    Calculates the unrotatated coordinates for a rotated pole grid

    :param resource: netCDF file

    :return list: lats, lons
    """
    from numpy import reshape, repeat
    from iris.analysis import cartography as ct
    ds = Dataset(resource, mode='a')

    if 'lat' in ds.variables.keys():
        LOGGER.info('coordinates already unrotated')
        lats = ds.variables['lat'][:]
        lons = ds.variables['lon'][:]

    else:
        try:
            if 'rotated_latitude_longitude' in ds.variables:
                rp = ds.variables['rotated_latitude_longitude']
            elif 'rotated_pole' in ds.variables:
                rp = ds.variables['rotated_pole']
            else:
                LOGGER.debug('rotated pole variable not found')
            pole_lat = rp.grid_north_pole_latitude
            pole_lon = rp.grid_north_pole_longitude
        except Exception as e:
            LOGGER.debug('failed to find rotated_pole coordinates: %s' % e)
        try:
            if 'rlat' in ds.variables:
                rlats = ds.variables['rlat']
                rlons = ds.variables['rlon']

            if 'x' in ds.variables:
                rlats = ds.variables['y']
                rlons = ds.variables['x']
        except Exception as e:
            LOGGER.debug('failed to read in rotated coordiates %s' % e)

        try:
            rlons_i = reshape(rlons, (1, len(rlons)))
            rlats_i = reshape(rlats, (len(rlats), 1))
            grid_rlats = repeat(rlats_i, (len(rlons)), axis=1)
            grid_rlons = repeat(rlons_i, (len(rlats)), axis=0)
        except Exception as e:
            LOGGER.debug('failed to repeat coordinates %s' % e)

        lons, lats = ct.unrotate_pole(grid_rlons, grid_rlats, pole_lon,
                                      pole_lat)

    if write_to_file is True:
        lat = ds.createVariable('lat', 'f8', ('rlat', 'rlon'))
        lon = ds.createVariable('lon', 'f8', ('rlat', 'rlon'))

        lon.standard_name = "longitude"
        lon.long_name = "longitude coordinate"
        lon.units = 'degrees_east'
        lat.standard_name = "latitude"
        lat.long_name = "latitude coordinate"
        lat.units = 'degrees_north'

        lat[:] = lats
        lon[:] = lons
    ds.close()

    return lats, lons