Example #1
0
lat = iris.coords.DimCoord(lat.data[:, 0],
                           standard_name='latitude',
                           units='degrees_N',
                           var_name='lat')
theta = iris.coords.DimCoord(theta.data,
                             standard_name='air_potential_temperature',
                             units='K',
                             var_name='T')

cube = iris.cube.Cube(cube,
                      long_name='Ertel Potential Voriticity',
                      var_name='EPV',
                      dim_coords_and_dims=[(L_S, 0), (theta, 1), (lat, 2),
                                           (lon, 3)])

level = iris.Constraint(air_potential_temperature=300)
cube = cube.extract(level)

# #PATH = '/home/local/WIN/wseviou1/data/swvac/'
# PATH = '../output/'
# ext = 'res_test57.-70.-nu4-urlx-kt4.0.c-0020sat200.0.T85'
# var = 'q'
# var_name = 'potential_vorticity_of_atmosphere_layer'
# res = 85
anim = False
plot = True
#
days = [5, 10]
# #days=[0,10,20,30,40,49]
# #days=[0,13,15,17,19,21,23,25,100]
# #days=[20,22,24,26,28,30,35,200]
Example #2
0
 def test_cube_extract_coord_which_does_not_exist(self):
     self.assertEqual(self.t.extract(iris.Constraint(doesnt_exist=8.1)), None)
Example #3
0
 def test_simple(self):
     constraint = iris.Constraint(latitude=10)
     cube = self.single_cube.extract(constraint)
     self.assertCML(cube, ('cdm', 'extract', 'lat_eq_10.cml'))
     constraint = iris.Constraint(latitude=lambda c: c > 10)
     self.assertCML(self.single_cube.extract(constraint), ('cdm', 'extract', 'lat_gt_10.cml'))
Example #4
0
def age_of_air(run):
    """Calculate the age of air metrics."""
    # Create metrics dictionary with MDI incase age of air
    # diagnostics not available
    metrics = {
        'RMS error: tropical Age of Air': -10000.,
        'RMS error: NH midlatitude Age of Air': -10000.
    }

    try:
        # Set up to only run for 5 year period
        analysis_start_dt, analysis_end_dt = calculate_analysis_years(run)
        constraint = dict(from_dt=analysis_start_dt,
                          to_dt=analysis_end_dt,
                          lbproc=128)
        # Calculate age of air metrics if appropriate diagnostic available
        with warnings.catch_warnings():
            warnings.filterwarnings('ignore', '.*orography.*', UserWarning)
            agecube = load_run_ss(run, 'monthly', 'age_of_stratospheric_air',
                                  **constraint)  # m01s34i150
    except iris.exceptions.ConstraintMismatchError:
        logger.warning('Age of air fields absent.  Skipping this diagnostic.')
    except ValueError:
        logger.warning("Run length < 12 years: Can't assess age of air")
    else:
        # Create time/zonal means of age data
        agecube = agecube.collapsed(['longitude', 'time'], iris.analysis.MEAN)
        # Convert units of data from seconds to years
        agecube.data /= RSECS_PER_360DAY_YEAR
        # Create latitude bounds for area-weighted averaging
        agecube.coord('latitude').guess_bounds()
        # Convert units of height from metres to km
        agecube.coord('level_height').convert_units('km')

        # Calculate area-weighted means for tropics
        trop_cons = iris.Constraint(latitude=lambda lat: -10 <= lat <= 10)
        diag1 = weight_lat_ave(agecube.extract(trop_cons))
        diag1.var_name = 'tropical_age_of_air'

        # Calculate area-weighted means for mid-latitudes
        mlat_cons = iris.Constraint(latitude=lambda lat: 35 <= lat <= 45)
        diag2 = weight_lat_ave(agecube.extract(mlat_cons))
        diag2.var_name = 'midlat_age_of_air'

        # Write age of air data to CWD
        outfile = '{0}_age_of_air_{1}.nc'
        cubelist = iris.cube.CubeList([diag1, diag2])
        with iris.FUTURE.context(netcdf_no_unlimited=True):
            iris.save(cubelist, outfile.format(run['runid'], run.period))

        # Calculate metrics
        diag1sf6 = iai.Linear(diag1, [('level_height', ZSF6_KM)])
        diag1co2 = iai.Linear(diag1, [('level_height', ZCO2_KM)])
        diag2sf6 = iai.Linear(diag2, [('level_height', Z2_KM)])
        diag2co2 = iai.Linear(diag2, [('level_height', Z2_KM2)])
        metric1sf6 = np.sqrt(np.mean((diag1sf6.data - AGE_YRS)**2))
        metric1co2 = np.sqrt(np.mean((diag1co2.data - AGE_YRS2)**2))
        metric2sf6 = np.sqrt(np.mean((diag2sf6.data - AGE2_YRS)**2))
        metric2co2 = np.sqrt(np.mean((diag2co2.data - AGE2_YRS2)**2))
        trop_age = (metric1sf6 + metric1co2) / 2.
        midl_age = (metric2sf6 + metric2co2) / 2.

        # Add metrics to dictionary
        metrics['RMS error: tropical Age of Air'] = float(trop_age)
        metrics['RMS error: NH midlatitude Age of Air'] = float(midl_age)

    return metrics
Example #5
0
 def test_cube_extract_1d(self):
     # Extract the first value from the second coord in the cube
     # this result is shared with the self.t[0, 0:] test
     self.assertCML([self.t.extract(iris.Constraint(dim1=3.0))], ('cube_slice', '2d_to_1d_cube_slice.cml'))
Example #6
0
import numpy
import datetime

import matplotlib
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.patches import Rectangle

start = datetime.datetime(1851, 1, 1, 0, 0)
end = datetime.datetime(2018, 12, 31, 23, 59)

from get_sample import get_sample_cube

egrid = iris.load_cube("/scratch/hadcc/hadcrut5/build/HadCRUT5/analysis/"+
                     "HadCRUT.5.0.0.0.analysis.anomalies.%d.nc" % 1,
                       iris.Constraint(time=lambda cell: cell.point.year==1850 and\
                                                         cell.point.month==1))

(ndata, dts) = get_sample_cube(start, end, new_grid=egrid)

# Plot the resulting array as a 2d colourmap
fig = Figure(
    figsize=(19.2, 6),  # Width, Height (inches)
    dpi=600,
    facecolor=(0.5, 0.5, 0.5, 1),
    edgecolor=None,
    linewidth=0.0,
    frameon=False,
    subplotpars=None,
    tight_layout=None)
canvas = FigureCanvas(fig)
matplotlib.rc('image', aspect='auto')
Example #7
0
def extract_time(cube, start_year, start_month, start_day, end_year, end_month,
                 end_day):
    """
    Extract a time range from a cube.

    Given a time range passed in as a series of years, months and days, it
    returns a time-extracted cube with data only within the specified
    time range.

    Parameters
    ----------
    cube: iris.cube.Cube
        input cube.
    start_year: int
        start year
    start_month: int
        start month
    start_day: int
        start day
    end_year: int
        end year
    end_month: int
        end month
    end_day: int
        end day

    Returns
    -------
    iris.cube.Cube
        Sliced cube.

    Raises
    ------
    ValueError
        if time ranges are outside the cube time limits

    """
    time_coord = cube.coord('time')
    time_units = time_coord.units
    if time_units.calendar == '360_day':
        if start_day > 30:
            start_day = 30
        if end_day > 30:
            end_day = 30
    t_1 = PartialDateTime(year=int(start_year),
                          month=int(start_month),
                          day=int(start_day))
    t_2 = PartialDateTime(year=int(end_year),
                          month=int(end_month),
                          day=int(end_day))

    constraint = iris.Constraint(time=lambda t: t_1 <= t.point < t_2)

    cube_slice = cube.extract(constraint)
    if cube_slice is None:
        raise ValueError(
            f"Time slice {start_year:0>4d}-{start_month:0>2d}-{start_day:0>2d}"
            f" to {end_year:0>4d}-{end_month:0>2d}-{end_day:0>2d} is outside "
            f"cube time bounds {time_coord.cell(0)} to {time_coord.cell(-1)}.")

    # Issue when time dimension was removed when only one point as selected.
    if cube_slice.ndim != cube.ndim:
        if cube_slice.coord('time') == time_coord:
            logger.debug('No change needed to time.')
            return cube

    return cube_slice
Example #8
0
 def test_cell(self):
     cell = iris.coords.Cell(10)
     constraint = iris.Constraint(model_level_number=cell)
     sub_list = self.slices.extract(constraint)
     self.assertEqual(len(sub_list), 6)
Example #9
0
 def test_cell_equal_bounds(self):
     cell = self.slices[0].coord('level_height').cell(0)
     constraint = iris.Constraint(level_height=cell)
     sub_list = self.slices.extract(constraint)
     self.assertEqual(len(sub_list), 6)
Example #10
0
    def test_non_existant_coordinate(self):
        # Check the behaviour when a constraint is given for a coordinate which does not exist/span a dimension
        self.assertEqual(self.cube[0, :, :].extract(self.level_10), None)

        self.assertEqual(self.cube.extract(iris.Constraint(wibble=10)), None)
Example #11
0
 def test_mismatched_type(self):
     constraint = iris.Constraint(model_level_number='aardvark')
     sub_list = self.slices.extract(constraint)
     self.assertEqual(len(sub_list), 0)
Example #12
0
    def setUp(self):
        self.dec_path = tests.get_data_path(
            ['PP', 'globClim1', 'dec_subset.pp'])
        self.theta_path = tests.get_data_path(['PP', 'globClim1', 'theta.pp'])

        self.humidity = iris.Constraint(SN_SPECIFIC_HUMIDITY)
        self.theta = iris.Constraint(SN_AIR_POTENTIAL_TEMPERATURE)

        # Coord based constraints
        self.level_10 = iris.Constraint(model_level_number=10)
        self.level_22 = iris.Constraint(model_level_number=22)

        # Value based coord constraint
        self.level_30 = iris.Constraint(model_level_number=30)
        self.level_gt_30_le_3 = iris.Constraint(
            model_level_number=lambda c: (c > 30) | (c <= 3))
        self.invalid_inequality = iris.Constraint(
            coord_values={'model_level_number': lambda c: c > 1000})

        # bound based coord constraint
        self.level_height_of_model_level_number_10 = iris.Constraint(
            level_height=1900)
        self.model_level_number_10_22 = iris.Constraint(
            model_level_number=[10, 22])

        # Invalid constraints
        self.pressure_950 = iris.Constraint(model_level_number=950)

        self.lat_30 = iris.Constraint(latitude=30)
        self.lat_gt_45 = iris.Constraint(latitude=lambda c: c > 45)
Example #13
0
landmask = ~(ma.make_mask(lsmask.data.copy()) + np.zeros(rh_plv.shape)).astype(
    bool)  # mask sea, show land
seamask = (ma.make_mask(lsmask.data.copy()) + np.zeros(rh_plv.shape)).astype(
    bool)  # mask land, show sea

RHocean = rh_plv_anom.copy()
Tocean = temp_plv_anom.copy()
RHland = rh_plv_anom.copy()
Tland = temp_plv_anom.copy()
RHocean.data = ma.array(RHocean.data, mask=seamask)
Tocean.data = ma.array(Tocean.data, mask=seamask)
RHland.data = ma.array(RHland.data, mask=landmask)
Tland.data = ma.array(Tland.data, mask=landmask)
# --------------

tropics = iris.Constraint(latitude=lambda v: -30 <= v <= 30)
Tocean_trop = Tocean.extract(tropics)
grid_areas_trop = iris.analysis.cartography.area_weights(Tocean_trop)

Tocean_trop_mean = Tocean_trop.collapsed(['latitude', 'longitude'],
                                         iris.analysis.MEAN,
                                         weights=grid_areas_trop)

SthAm = iris.Constraint(longitude=lambda l: (290 <= l <= 315),
                        latitude=lambda l: (-23 <= l <= 0))
RHplv_SthAm = rh_plv_anom.extract(SthAm)
grid_areas_SthAm = iris.analysis.cartography.area_weights(RHplv_SthAm)

RHplv_SthAm_armean = RHplv_SthAm.collapsed(['latitude', 'longitude'],
                                           iris.analysis.MEAN,
                                           weights=grid_areas_SthAm)
                    default="%s/EUSTACE/derived/ERA5_20CRv3_comparison" % \
                                           os.getenv('SCRATCH'),
                    type=str,required=False)
args = parser.parse_args()
if not os.path.isdir(args.opdir):
    os.makedirs(args.opdir)

# Fix dask SPICE bug
import dask
dask.config.set(scheduler='single-threaded')

# Get EUSTACE field for grid dimensions
egrid = iris.load_cube(("%s/EUSTACE/1.0/1969/"+
                        "tas_global_eustace_0_19690312.nc") % 
                        os.getenv('SCRATCH'),
            iris.Constraint(cube_func=(lambda c: c.var_name == 'tas')))

# Make the 20CR climatology
n=[]
for m in range(1,13):
    mc=iris.Constraint(time=lambda cell: cell.point.month == m and \
                                         cell.point.year > 1980 and \
                                         cell.point.year < 2011)
    h=iris.load_cube('%s/20CR/version_3/monthly_means/air.2m.mon.mean.nc' % 
                                                   os.getenv('SCRATCH'),
                 iris.Constraint(name='air_temperature') & mc)
    n.append(h.extract(mc).collapsed('time', iris.analysis.MEAN))

# Make the ERA5 climatology
n5=[]
for m in range(1,13):
def main():

    for p_level in plot_levels:

        # Set pressure height contour min/max
        if p_level == 925:
            clev_min = 660.
            clev_max = 810.
        elif p_level == 850:
            clev_min = 1435.
            clev_max = 1530.
        elif p_level == 700:
            clev_min = 3090.
            clev_max = 3155.
        elif p_level == 500:
            clev_min = 5800.
            clev_max = 5890.
        else:
            print 'Contour min/max not set for this pressure level'

# Set potential temperature min/max
        if p_level == 925:
            clevpt_min = 300.
            clevpt_max = 312.
        elif p_level == 850:
            clevpt_min = 302.
            clevpt_max = 310.
        elif p_level == 700:
            clevpt_min = 312.
            clevpt_max = 320.
        elif p_level == 500:
            clevpt_min = 325.
            clevpt_max = 332.
        else:
            print 'Potential temperature min/max not set for this pressure level'

# Set specific humidity min/max
        if p_level == 925:
            clevsh_min = 0.012
            clevsh_max = 0.020
        elif p_level == 850:
            clevsh_min = 0.007
            clevsh_max = 0.017
        elif p_level == 700:
            clevsh_min = 0.002
            clevsh_max = 0.010
        elif p_level == 500:
            clevsh_min = 0.001
            clevsh_max = 0.005
        else:
            print 'Specific humidity min/max not set for this pressure level'

        #clevs_col = np.arange(clev_min, clev_max)
        clevs_lin = np.arange(clev_min, clev_max, 5)

        p_level_constraint = iris.Constraint(pressure=p_level)

        for plot_diag in plot_diags:

            for experiment_id in experiment_ids:

                expmin1 = experiment_id[:-1]

                pp_file = '%s_%s_on_p_levs_mean_by_day.pp' % (experiment_id,
                                                              plot_diag)
                pfile = '%s%s/%s/%s' % (pp_file_path, expmin1, experiment_id,
                                        pp_file)
                pcube = iris.load_cube(pfile, p_level_constraint)

                # For each hour in cube

                height_pp_file = '%s_408_on_p_levs_mean_by_day.pp' % (
                    experiment_id)
                height_pfile = '%s%s/%s/%s' % (pp_file_path, expmin1,
                                               experiment_id, height_pp_file)
                height_cube = iris.load_cube(height_pfile, p_level_constraint)

                print pcube
                print height_cube

                #time_coords = cube_f.coord('time')
                #add_hour_of_day(pcube, pcube.coord('time'))

                #add_hour_of_day(height_cube, height_cube.coord('time'))

                iris.coord_categorisation.add_day_of_year(pcube,
                                                          time_coords,
                                                          name='day_of_year')
                iris.coord_categorisation.add_day_of_year(height_cube,
                                                          time_coords,
                                                          name='day_of_year')

                #pcube.remove_coord('time')
                #cube_diff.remove_coord('time')
                #height_cube.remove_coord('time')
                #height_cube_diff.remove_coord('time')

                #p_cube_difference = iris.analysis.maths.subtract(pcube, cube_diff, dim='hour')
                #height_cube_difference = iris.analysis.maths.subtract(height_cube, height_cube_diff, dim='hour')

                #pdb.set_trace()

                #del height_cube, pcube, height_cube_diff, cube_diff

                for t, time_cube in enumerate(
                        pcube.slices(['grid_latitude', 'grid_longitude'])):

                    #pdb.set_trace()

                    print time_cube
                    height_cube_slice = height_cube.extract(
                        iris.Constraint(hour=time_cube.coord('hour').points))

                    # Get  time of averagesfor plot title

                    #h = u.num2date(np.array(time_cube.coord('hour').points, dtype=float)[0]).strftime('%H%M')
                    h = u.num2date(
                        np.array(time_cube.coord('time').points,
                                 dtype=float)[0]).strftime('%d%b')

                    #Convert to India time

                    # from_zone = tz.gettz('UTC')
                    # to_zone = tz.gettz('Asia/Kolkata')

                    # h_utc = u.num2date(np.array(time_cube.coord('hour').points, dtype=float)[0]).replace(tzinfo=from_zone)

                    # h_local = h_utc.astimezone(to_zone).strftime('%H%M')

                    fig = plt.figure(**figprops)

                    cmap = plt.cm.RdBu_r

                    ax = plt.axes(projection=ccrs.PlateCarree(),
                                  extent=(lon_low, lon_high,
                                          lat_low + degs_crop_bottom,
                                          lat_high - degs_crop_top))

                    m =\
                        Basemap(llcrnrlon=lon_low,llcrnrlat=lat_low,urcrnrlon=lon_high,urcrnrlat=lat_high, rsphere = 6371229)
                    #pdb.set_trace()
                    lat = time_cube.coord('grid_latitude').points
                    lon = time_cube.coord('grid_longitude').points

                    cs = time_cube.coord_system('CoordSystem')

                    lons, lats = np.meshgrid(lon, lat)
                    lons, lats = iris.analysis.cartography.unrotate_pole\
                                (lons,lats, cs.grid_north_pole_longitude, cs.grid_north_pole_latitude)

                    x, y = m(lons, lats)

                    if plot_diag == 'temp':
                        min_contour = clevpt_min
                        max_contour = clevpt_max
                        cb_label = 'K'
                        main_title = '8km  Explicit model (dklyu) minus 8km parametrised model geopotential height (grey contours), potential temperature (colours),\
                                          and wind (vectors) %s UTC    %s IST' % (
                            h, h_local)
                        tick_interval = 2
                        clev_number = max_contour - min_contour + 1
                    elif plot_diag == 'sp_hum':
                        min_contour = clevsh_min
                        max_contour = clevsh_max
                        cb_label = 'kg/kg'
                        main_title = '8km  Explicit model (dklyu) minus 8km parametrised model geopotential height (grey contours), specific humidity (colours),\
                                         and wind (vectors) %s UTC    %s IST' % (
                            h, h_local)
                        tick_interval = 0.002
                        clev_number = (max_contour - min_contour +
                                       0.001) * (10**3)

                    clevs = np.linspace(min_contour, max_contour, clev_number)
                    #clevs = np.linspace(-3, 3, 32)
                    cont = plt.contourf(x,
                                        y,
                                        time_cube.data,
                                        clevs,
                                        cmap=cmap,
                                        extend='both')

                    #cont = iplt.contourf(time_cube, clevs, cmap=cmap, extend='both')

                    cs_lin = iplt.contour(height_cube_slice,
                                          clevs_lin,
                                          colors='#262626',
                                          linewidths=1.)
                    plt.clabel(cs_lin, fontsize=14, fmt='%d', color='black')

                    #del time_cube

                    #plt.clabel(cont, fmt='%d')
                    #ax.stock_img()
                    ax.coastlines(resolution='110m', color='#262626')

                    gl = ax.gridlines(draw_labels=True,
                                      linewidth=0.5,
                                      color='#262626',
                                      alpha=0.5,
                                      linestyle='--')
                    gl.xlabels_top = False
                    gl.ylabels_right = False
                    #gl.xlines = False
                    dx, dy = 10, 10

                    gl.xlocator = mticker.FixedLocator(
                        range(int(lon_low_tick),
                              int(lon_high_tick) + dx, dx))
                    gl.ylocator = mticker.FixedLocator(
                        range(int(lat_low_tick),
                              int(lat_high_tick) + dy, dy))
                    gl.xformatter = LONGITUDE_FORMATTER
                    gl.yformatter = LATITUDE_FORMATTER

                    gl.xlabel_style = {'size': 12, 'color': '#262626'}
                    #gl.xlabel_style = {'color': '#262626', 'weight': 'bold'}
                    gl.ylabel_style = {'size': 12, 'color': '#262626'}

                    cbar = fig.colorbar(cont,
                                        orientation='horizontal',
                                        pad=0.05,
                                        extend='both')
                    cbar.set_label('%s' % cb_label,
                                   fontsize=10,
                                   color='#262626')
                    #cbar.set_label(time_cube.units, fontsize=10, color='#262626')
                    cbar.set_ticks(
                        np.arange(min_contour, max_contour + tick_interval,
                                  tick_interval))
                    ticks = (np.arange(min_contour,
                                       max_contour + tick_interval,
                                       tick_interval))
                    cbar.set_ticklabels(['${%.1f}$' % i for i in ticks])

                    cbar.ax.tick_params(labelsize=10, color='#262626')

                    #main_title='Mean Rainfall for EMBRACE Period -%s UTC (%s IST)' % (h, h_local)
                    #main_title=time_cube.standard_name.title().replace('_',' ')
                    #model_info = re.sub(r'[(\']', ' ', model_info)
                    #model_info = re.sub(r'[\',)]', ' ', model_info)
                    #print model_info

                    file_save_name = '%s_%s_%s_hPa_and_geop_height_%s' % (
                        experiment_id, plot_diag, p_level, h)
                    save_dir = '%s%s/%s' % (save_path, experiment_id,
                                            plot_diag)
                    if not os.path.exists('%s' % save_dir):
                        os.makedirs('%s' % (save_dir))

                    #plt.show()

                    #fig.savefig('%s/%s_notitle.png' % (save_dir, file_save_name), format='png', bbox_inches='tight')

                    plt.title('%s UTC' % (h))
                    fig.savefig('%s/%s_short_title.png' %
                                (save_dir, file_save_name),
                                format='png',
                                bbox_inches='tight')

                    #model_info=re.sub('(.{68} )', '\\1\n', str(model_name_convert_title.main(experiment_id)), 0, re.DOTALL)
                    #plt.title('\n'.join(wrap('%s\n%s' % (main_title, model_info), 1000,replace_whitespace=False)), fontsize=16)
                    #fig.savefig('%s/%s.png' % (save_dir, file_save_name), format='png', bbox_inches='tight')

                    fig.clf()
                    plt.close()
                    #del time_cube
                    gc.collect()
Example #16
0
 def test_cell_different_bounds(self):
     cell = iris.coords.Cell(10, bound=(9, 11))
     constraint = iris.Constraint(model_level_number=cell)
     sub_list = self.slices.extract(constraint)
     self.assertEqual(len(sub_list), 0)
Example #17
0
def getSeasConstr(name):

    sncon = {'ann': iris.Constraint(month_number=lambda cell: 1 <= cell <= 12),
            'mj' : iris.Constraint(month_number=lambda cell: 5 <= cell <= 6),
            'jj' : iris.Constraint(month_number=lambda cell: 6 <= cell <= 7),
            'ja' : iris.Constraint(month_number=lambda cell: 7 <= cell <= 8),
            'as' : iris.Constraint(month_number=lambda cell: 8 <= cell <= 9),
            'so' : iris.Constraint(month_number=lambda cell: 9 <= cell <= 10),
            'jan' :  iris.Constraint(month_number=lambda cell: cell == 1),
            'feb' :  iris.Constraint(month_number=lambda cell: cell == 2),
            'mar' :  iris.Constraint(month_number=lambda cell: cell == 3),
            'apr' :  iris.Constraint(month_number=lambda cell: cell == 4),
            'may' :  iris.Constraint(month_number=lambda cell: cell == 5),
            'jun' :  iris.Constraint(month_number=lambda cell: cell == 6),
            'jul' :  iris.Constraint(month_number=lambda cell: cell == 7),
            'aug' :  iris.Constraint(month_number=lambda cell: cell == 8),
            'sep' :  iris.Constraint(month_number=lambda cell: cell == 9),
            'oct' :  iris.Constraint(month_number=lambda cell: cell == 10),
            'nov' :  iris.Constraint(month_number=lambda cell: cell == 11),
            'dec' :  iris.Constraint(month_number=lambda cell: cell == 12),
            'djf': iris.Constraint(month_number=lambda cell: (cell == 12) | (1 <= cell <= 2)),
            'mam': iris.Constraint(month_number=lambda cell: 3 <= cell <= 5),
            'jja': iris.Constraint(month_number=lambda cell: 6 <= cell <= 8),
            'jas': iris.Constraint(month_number=lambda cell: 7 <= cell <= 9),
            'jjas': iris.Constraint(month_number=lambda cell: 6 <= cell <= 9),
            'mjjas': iris.Constraint(month_number=lambda cell: 5<= cell<=9),
            'son': iris.Constraint(month_number=lambda cell: 9 <= cell <= 11)
            }

    return(sncon[name])
Example #18
0
    def setUp(self):
        """
        Set up cubes and sitelists for use in testing SpotExtraction.
        The envisaged scenario is an island (1) surrounded by water (0).

          Land-sea       Orography      Diagnostic

          0 0 0 0 0      0 0 0 0 0       0  1  2  3  4
          0 1 1 1 0      0 1 2 1 0       5  6  7  8  9
          0 1 1 1 0      0 2 3 2 0      10 11 12 13 14
          0 1 1 1 0      0 1 2 1 0      15 16 17 18 19
          0 0 0 0 0      0 0 0 0 0      20 21 22 23 24

        """
        # Set up diagnostic data cube and neighbour cubes.
        diagnostic_data = np.arange(25).reshape(5, 5)

        xcoord = iris.coords.DimCoord(
            np.linspace(0, 40, 5), standard_name='longitude', units='degrees')
        ycoord = iris.coords.DimCoord(
            np.linspace(0, 40, 5), standard_name='latitude', units='degrees')

        attributes = {
            'mosg__grid_domain': 'global',
            'mosg__grid_type': 'standard'}

        diagnostic_cube_xy = iris.cube.Cube(
            diagnostic_data, standard_name="air_temperature", units='K',
            dim_coords_and_dims=[(ycoord, 1), (xcoord, 0)],
            attributes=attributes)
        diagnostic_cube_yx = iris.cube.Cube(
            diagnostic_data.T, standard_name="air_temperature", units='K',
            dim_coords_and_dims=[(ycoord, 0), (xcoord, 1)],
            attributes=attributes)

        diagnostic_cube_hash = create_coordinate_hash(diagnostic_cube_yx)

        # neighbours, each group is for a point under two methods, e.g.
        # [ 0.  0.  0.] is the nearest point to the first spot site, whilst
        # [ 1.  1. -1.] is the nearest land point to the same site.
        neighbours = np.array([[[0., 0., 0.],
                                [1., 1., -1.]],
                               [[0., 0., -1.],
                                [1., 1., 0.]],
                               [[2., 2., 0.],
                                [2., 2., 0.]],
                               [[2., 2., 1.],
                                [2., 2., 1.]]])
        altitudes = np.array([0, 1, 3, 2])
        latitudes = np.array([10, 10, 20, 20])
        longitudes = np.array([10, 10, 20, 20])
        wmo_ids = np.arange(4)
        grid_attributes = ['x_index', 'y_index', 'vertical_displacement']
        neighbour_methods = ['nearest', 'nearest_land']
        neighbour_cube = build_spotdata_cube(
            neighbours, 'grid_neighbours', 1, altitudes, latitudes,
            longitudes, wmo_ids, grid_attributes=grid_attributes,
            neighbour_methods=neighbour_methods)
        neighbour_cube.attributes['model_grid_hash'] = diagnostic_cube_hash

        coordinate_cube = neighbour_cube.extract(
            iris.Constraint(neighbour_selection_method_name='nearest') &
            iris.Constraint(grid_attributes_key=['x_index', 'y_index']))
        coordinate_cube.data = np.rint(coordinate_cube.data).astype(int)

        self.latitudes = latitudes
        self.longitudes = longitudes
        self.diagnostic_cube_xy = diagnostic_cube_xy
        self.diagnostic_cube_yx = diagnostic_cube_yx
        self.neighbours = neighbours
        self.neighbour_cube = neighbour_cube
        self.coordinate_cube = coordinate_cube
def plot_cross_section_for_seasons(data_path="",
                                   i_start=0,
                                   j_start=0,
                                   i_end=-1,
                                   j_end=-1,
                                   var_name=None):

    name_constraint = iris.Constraint(
        cube_func=lambda c: c.var_name == var_name)
    data_cube = iris.load_cube(data_path, constraint=name_constraint)

    fig = plt.figure()
    impath = os.path.join(
        NEMO_IMAGES_DIR,
        "vert_sect_{0}_{1}_{2}_{3}_{4}.jpeg".format(var_name, i_start, j_start,
                                                    i_end, j_end))

    #Add month_number coordinate
    #coord_categorisation.add_month_number(cube, "time")
    coord_categorisation.add_season(data_cube, "time")

    cube_seasonal = data_cube.aggregated_by("season", analysis.MEAN)

    nplots = cube_seasonal.shape[0]
    ncols = 2
    nrows = nplots // ncols if nplots % ncols == 0 else nplots // ncols + 1

    b, lons, lats = nemo_commons.get_basemap_and_coordinates_from_file(
        T_FILE_PATH, resolution="i")

    print("lons shape: ", lons.shape)

    gs = gridspec.GridSpec(ncols=ncols + 1,
                           nrows=nrows + 1,
                           width_ratios=[1, 1, 0.05],
                           hspace=0.3)  # +1 for the colorbar and for map

    bath_path = os.path.join(EXP_DIR, "bathy_meter.nc")
    the_mask = nemo_commons.get_mask(path=bath_path)

    depths = Dataset(T_FILE_PATH).variables["deptht"][:]
    bathymetry = Dataset(bath_path).variables["Bathymetry"][:]

    vert_mask = np.ma.masked_all(depths.shape + bathymetry.shape)
    for lev, di in enumerate(depths):
        not_mask_j, not_mask_i = np.where(di < bathymetry * 0.95)
        vert_mask[lev, not_mask_j, not_mask_i] = 1

    lons_sel, lats_sel = None, None
    depths_2d = None
    vmin = None
    vmax = None
    nx, ny = None, None
    dists_2d = None
    season_to_section = {}
    for i, season in zip(list(range(nplots)),
                         cube_seasonal.coord("season").points):

        data = cube_seasonal.extract(
            iris.Constraint(season=season)).data.squeeze()

        assert data.ndim == 3
        _, ny, nx = data.shape

        if i_end == -1:
            i_end = nx - 1
        if j_end == -1:
            j_end = ny - 1

        j_mask, i_mask = np.where(~the_mask)
        print("mask shape: ", the_mask.shape)
        print("data shape: ", data.shape)
        data[:, j_mask, i_mask] = np.ma.masked

        i_list, j_list = get_section_hor_indices(i_start=i_start,
                                                 i_end=i_end,
                                                 j_start=j_start,
                                                 j_end=j_end)

        data_sel = data[:, j_list, i_list]
        data_sel = np.ma.masked_where(vert_mask[:, j_list, i_list].mask,
                                      data_sel)
        print("data_sel shape: ", data_sel.shape)
        if lons_sel is None:
            lons_sel = lons[j_list, i_list]
            lats_sel = lats[j_list, i_list]

            p_start = (lats[j_start, i_start], lons[j_start, i_start])
            dists = [
                GreatCircleDistance(p_start, (the_lat, the_lon)).km
                for the_lat, the_lon in zip(lats_sel, lons_sel)
            ]

            dists_2d, depths_2d = np.meshgrid(dists, depths)

        season_to_section[season] = data_sel

        if vmin is None:
            vmin = data_sel.min()
        else:
            vmin = min(vmin, data_sel.min())

        if vmax is None:
            vmax = data_sel.max()
        else:
            vmax = max(vmax, data_sel.max())

    delta = 1.0
    clevs = np.arange(np.floor(vmin), vmax + delta, delta)
    cmap = cm.get_cmap("jet", len(clevs) - 1)
    if clevs is not None:
        bn = BoundaryNorm(clevs, len(clevs) - 1)
    else:
        bn = None

    print("{0}: ".format(var_name), vmin, vmax)
    cs = None
    ax = None
    for i, season in zip(list(range(nplots)),
                         cube_seasonal.coord("season").points):
        print(season)
        row = i // ncols
        col = i % ncols
        ax = fig.add_subplot(gs[row, col])

        ax.set_title(season.upper())
        data = season_to_section[season]
        print(data.min(), data.max())

        #to_plot = np.ma.masked_where(~the_mask, data)
        #print to_plot.min(), to_plot.max()

        #cs = ax.pcolormesh(dists_2d, depths_2d, data, norm = bn, cmap = cmap)
        cs = ax.contourf(dists_2d, depths_2d, data, levels=clevs, cmap=cmap)
        #cs = ax.pcolormesh(dists_2d, depths_2d, data, norm = bn, cmap = cmap)
        #b.drawcoastlines(linewidth=cpp.COASTLINE_WIDTH)
        #b.drawparallels(np.arange(-90, 90, 2))
        #b.drawmeridians(np.arange(-180, 180, 2))

        if col != 0:
            ax.yaxis.set_ticks([])

        ax.xaxis.set_ticks([])

        assert isinstance(ax, Axes)
        ax.invert_yaxis()
        ax.set_ylim(80, 0)  # Disregard areas deeper than 150 m
        if row == 0 and col == 0:
            ax.set_ylabel("Depth (m)", fontdict={"fontsize": 20})
    cb = plt.colorbar(cs,
                      ticks=clevs[::2],
                      cax=fig.add_subplot(gs[:nrows, ncols]))

    ax = fig.add_subplot(gs[nrows, :])
    x, y = b(lons, lats)

    b.drawcoastlines(linewidth=cpp.COASTLINE_WIDTH)
    b.fillcontinents()

    assert isinstance(ax, Axes)
    ax.add_line(
        Line2D([x[j_start, i_start], x[j_end, i_end]],
               [y[j_start, i_start], y[j_end, i_end]],
               linewidth=3))

    fig.savefig(impath, bbox_inches="tight")

    pass
Example #20
0
def load_min_max_LST(season_filepath, REGION):

    if REGION != 'EUROPE':
        left_lon = float(REGIONS[REGION][0])
        right_lon = float(REGIONS[REGION][2])
        lower_lat = float(REGIONS[REGION][1])
        upper_lat = float(REGIONS[REGION][3])

        lat_constraint = iris.Constraint(
            latitude=lambda c: lower_lat <= c.point <= upper_lat)
        lon_constraint = iris.Constraint(
            longitude=lambda c: left_lon <= c.point <= right_lon)

        lst_warm_max = iris.load(
            season_filepath,
            'Coverage of Maximum Land Surface Temperature in Warm Window (PMW)'
        )
        lst_warm_max = lst_warm_max.extract(lat_constraint)
        lst_warm_max = lst_warm_max.extract(lon_constraint)

        lst_cold_max = iris.load(
            season_filepath,
            'Coverage of Maximum Land Surface Temperature in Cold Window (PMW)'
        )
        lst_cold_max = lst_cold_max.extract(lat_constraint)
        lst_cold_max = lst_cold_max.extract(lon_constraint)

        lst_cold_min = iris.load(
            season_filepath,
            'Coverage of Minimum Land Surface Temperature in Cold Window (PMW)'
        )
        lst_cold_min = lst_cold_min.extract(lat_constraint)
        lst_cold_min = lst_cold_min.extract(lon_constraint)

    else:
        lst_warm_max = iris.load(
            season_filepath,
            'Coverage of Maximum Land Surface Temperature in Warm Window (PMW)'
        )
        lst_cold_max = iris.load(
            season_filepath,
            'Coverage of Maximum Land Surface Temperature in Cold Window (PMW)'
        )
        lst_cold_min = iris.load(
            season_filepath,
            'Coverage of Minimum Land Surface Temperature in Cold Window (PMW)'
        )

    lons = lst_warm_max[0].coord('longitude').points
    lats = lst_warm_max[0].coord('latitude').points

    num_of_years = len(lst_warm_max)
    shape1 = lst_cold_max[0].shape[0]
    shape2 = lst_cold_max[0].shape[1]
    lst_warm_max_data = np.zeros((num_of_years, shape1, shape2))
    lst_cold_max_data = np.zeros((num_of_years, shape1, shape2))
    lst_cold_min_data = np.zeros((num_of_years, shape1, shape2))

    for i in range(num_of_years):
        lst_warm_max_data[i, :] = lst_warm_max[i].data
        lst_cold_max_data[i, :] = lst_cold_max[i].data
        lst_cold_min_data[i, :] = lst_cold_min[i].data

    average_lst_warm_max = np.mean(lst_warm_max_data, axis=0)
    average_lst_cold_max = np.mean(lst_cold_max_data, axis=0)
    average_lst_cold_min = np.mean(lst_cold_min_data, axis=0)

    return lst_warm_max_data, lst_cold_max_data, lst_cold_min_data, average_lst_warm_max, average_lst_cold_max, average_lst_cold_min, lons, lats
Example #21
0
def multi_age_plot(run):
    """
    Plot results.

    This function is plotting the results of the function age_of_air for each
    run against observations.
    """
    # Run age_of_air for each run.
    # Age_of_air returns metrics and writes results into an *.nc in the current
    # working directory.
    # To make this function independent of the previous call to age_of_air,
    # age_of_air is run again for each run in this function
    #
    # This behaviour is due to the convention that only metric_functions can
    # return metric values, multi_functions are supposed to
    # only produce plots (see __init__.py).

    ######################################

    # Set up constraints to deal with loading data
    trop_cons = iris.Constraint(
        cube_func=lambda c: c.var_name == 'tropical_age_of_air')
    midl_cons = iris.Constraint(
        cube_func=lambda c: c.var_name == 'midlat_age_of_air')

    # Set up generic input file name
    infile = '{0}_age_of_air_{1}.nc'

    # Create control filename
    cntlfile = infile.format(run['suite_id1'], run['period'])

    # Create experiment filename
    exptfile = infile.format(run['suite_id2'], run['period'])

    # If no control data then stop ...
    if not os.path.exists(cntlfile):
        logger.warning('Age of air for control absent. skipping ...')
        return

    # Create tropics plot
    fig = plt.figure()
    ax1 = plt.gca()
    # Plot OBS
    plt.plot(AGE_YRS,
             ZSF6_KM,
             linestyle='-',
             marker='s',
             color='black',
             label='SF6 obs')
    plt.plot(AGE_YRS2,
             ZCO2_KM,
             linestyle='-',
             marker='D',
             color='black',
             label='CO2 obs')
    # Plot control
    diag = iris.load_cube(cntlfile, trop_cons)
    levs = diag.coord('level_height').points
    plt.plot(diag.data, levs, label=run['suite_id1'])
    # Plot experiment
    if os.path.exists(exptfile):
        diag = iris.load_cube(exptfile, trop_cons)
        levs = diag.coord('level_height').points
        plt.plot(diag.data, levs, label=run['suite_id2'])
    ax1.set_title('Tropical mean age profile (10S-10N)')
    ax1.set_xlabel('Mean age (years)')
    ax1.set_ylabel('Height (km)')
    ax1.set_ylim(16, 34)
    ax1.legend(loc='upper left')
    fig.savefig('age_tropics.png')
    plt.close()

    # Create midlats plot
    fig = plt.figure()
    ax1 = plt.gca()
    # Plot OBS
    plt.plot(AGE2_YRS,
             Z2_KM,
             linestyle='-',
             marker='s',
             color='black',
             label='SF6 obs')
    plt.plot(AGE2_YRS2,
             Z2_KM2,
             linestyle='-',
             marker='D',
             color='black',
             label='CO2 obs')
    # Plot control
    diag = iris.load_cube(cntlfile, midl_cons)
    levs = diag.coord('level_height').points
    plt.plot(diag.data, levs, label=run['suite_id1'])
    # Plot experiment
    if os.path.exists(exptfile):
        diag = iris.load_cube(exptfile, midl_cons)
        levs = diag.coord('level_height').points
        plt.plot(diag.data, levs, label=run['suite_id2'])
    ax1.set_title('Midlatitude mean age profile (35N-45N)')
    ax1.set_xlabel('Mean age (years)')
    ax1.set_ylabel('Height (km)')
    ax1.set_ylim(16, 34)
    ax1.legend(loc='upper left')
    fig.savefig('age_midlatitudes.png')
    plt.close()
import os
import math
import pickle

import Meteorographica as mg

import matplotlib
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
import cartopy
import cartopy.crs as ccrs

# Get the 20CR data
ic=twcr.load('prmsl',datetime.datetime(2009,3,12,18),
                           version='2c')
ic=ic.extract(iris.Constraint(member=1))

# Need to resize data so it's dimensions are a multiple of 8 (3*2-fold pool)
class ResizeLayer(tf.keras.layers.Layer):
   def __init__(self, newsize=None, **kwargs):
      super(ResizeLayer, self).__init__(**kwargs)
      self.resize_newsize = newsize
   def build(self, input_shape):
      self.resize_newsize *= 1
   def call(self, input):
      return tf.image.resize_images(input, self.resize_newsize,
                                    align_corners=True)
   def get_config(self):
      return {'newsize': self.resize_newsize}

# Padding and pruning functions for periodic boundary conditions
Example #23
0
 def test_cube_extract_0d(self):
     # Extract the first value from each of the coords in the cube
     # this result is shared with the self.t[0, 0] test
     self.assertCML([self.t.extract(iris.Constraint(dim1=3.0, dim2=iris.coords.Cell(0, (0, 1))))], ('cube_slice', '2d_to_0d_cube_slice.cml'))
Example #24
0
import matplotlib.patches as patch
import numpy as np
import cartopy.crs as ccrs
from cis.data_io.gridded_data import make_from_cube

def load_callback(cube, field, fname):
    variable_attributes = ['date_metadata_modified', 'date_issued', 'date_modified', 'date_created',
                           'isccp_input_files', 'time_coverage_start', 'time_coverage_end', 'isccp_month', 'id',
                           'history']
    for a in variable_attributes:
        cube.attributes.pop(a)
months=['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']       
for i in  range(12):
    directory = '/Users/clim_proc/Documents/POC MPhys Project/Modis/ISCCP data/data/international-satellite-cloud-climate-project-isccp-h-series-data/access/isccp-basic/hgm/'
    filelist = glob(directory+'ISCCP-Basic*GLOBAL*0'+str(i+1)+'*99.9999*')
    c = iris.load(filelist[0], iris.Constraint(cube_func=lambda x:
        x.var_name=='cldamt_types'), callback=load_callback).concatenate_cube()[:,1,...]
    no = 0
    for filename in filelist[1:]:
    
        year = int(filename.split('.')[4])
        c += (iris.load(filename, iris.Constraint(cube_func=lambda x:
            x.var_name=='cldamt_types'), callback=load_callback).concatenate_cube())[:,1,...]
        no += 1
        print(no+1, ' of ', len(filelist), ' done')
        
    mean = c/no
    fig=plt.figure(figsize=(15,15))#, dpi=300)
    ax = plt.axes(projection=ccrs.PlateCarree())
    ax.coastlines()
    ax.set_title=(months[i])
    make_from_cube(c).plot(ax=ax)
Example #25
0
 def test_cube_extract_2d(self):
     # Do nothing - return the original
     self.assertCML([self.t.extract(iris.Constraint())], ('cube_slice', '2d_orig.cml'))
Example #26
0
TX = TX.concatenate_cube()
TN = iris.load(tmin)
TN = TN.concatenate_cube()

#Initialize Indices
TXx_MON = iris.cube.CubeList()
TNx_MON = iris.cube.CubeList()
TXn_MON = iris.cube.CubeList()
TNn_MON = iris.cube.CubeList()
DTR_MON = iris.cube.CubeList()
FD_MON = iris.cube.CubeList()
TR_MON = iris.cube.CubeList()

for i in range(len(YEARS)):
    print(YEARS[i])
    year_constraint = iris.Constraint(
        time=lambda c: c.point.year == int(YEARS[i]))

    #initialize different indice
    TXx_MONTHS = iris.cube.CubeList()
    TXn_MONTHS = iris.cube.CubeList()
    TNx_MONTHS = iris.cube.CubeList()
    TNn_MONTHS = iris.cube.CubeList()
    DTR_MONTHS = iris.cube.CubeList()
    FD_MONTHS = iris.cube.CubeList()
    TR_MONTHS = iris.cube.CubeList()

    TN_YEAR = TN.extract(year_constraint)
    TX_YEAR = TX.extract(year_constraint)

    for MONTH in MONTHS:
        print(MONTH)
Example #27
0
 def test_cube_extract_coord_with_non_existant_values(self):
     self.assertEqual(self.t.extract(iris.Constraint(dim1=8)), None)
def read_cp4(explicit, temporal, variable, start_year, start_month, end_year,
             end_month):

    if explicit:
        explicit_str = 'explicit-4km'
    else:
        explicit_str = 'param-25km'
    if start_year <= 2007:
        present_future = 'present'
    else:
        present_future = 'future'

    # match variable names with longer names used in directory structure
    var_directory = dict()
    var_directory['psl'] = 'mean_sea_level_pressure'
    var_directory['prsn'] = 'snowfall'
    var_directory['huss'] = 'near_surface_air_specific_humidity'
    var_directory['hfls'] = 'surface_latent_heat_flux'
    var_directory['tas'] = 'near_surface_air_temperature'
    var_directory['ps'] = 'surface_pressure'
    var_directory['rlut'] = 'outgoing_longwave_radiation'
    var_directory['hfss'] = 'surface_sensible_heat_flux'
    var_directory['pr'] = 'precipitation'

    nmonths_per_year = 12
    ndays_per_month = 30
    basedir = '/badc/impala/data/' + explicit_str + '/' + present_future + '/' + temporal + '/' + var_directory[
        variable] + '/'
    all_cubes = iris.cube.CubeList()
    varConstraint = iris.Constraint(
        cube_func=(lambda c: c.var_name == variable))
    print('reading {res} {y:04d}/{m:02d} to {y2:04d}/{m2:02d}'.format(
        res=explicit_str,
        y=start_year,
        m=start_month,
        y2=end_year,
        m2=end_month))
    for y in range(start_year, end_year + 1):
        if temporal == 'mon':
            ncdir = basedir
            if y == start_year:
                first_month = start_month
            else:
                first_month = 1
            if y == end_year:
                last_month = end_month
            else:
                last_month = nmonths_per_year
            first_date_str = '{y:04d}{m:02d}-'.format(y=y, m=first_month)
            last_date_str = '{y:04d}{m:02d}'.format(y=y, m=last_month)
            filename = variable + '_' + explicit_str + '_' + present_future + '_' + first_date_str + last_date_str + '.nc'
            #print('opening', filename)
            try:
                this_cube = iris.load_cube(ncdir + filename, varConstraint)
            except OSError as err:
                print(filename)
                raise err
            all_cubes.append(this_cube)
        else:
            for m in range(1, nmonths_per_year + 1):
                if y == start_year and m < start_month:
                    continue
                if y == end_year and m > end_month:
                    break
                ncdir = basedir + '{y:04d}/{m:02d}/'.format(y=y, m=m)
                for d in range(ndays_per_month):
                    filename = variable + '_' + explicit_str + '_' + present_future + '_{y:04d}{m:02d}{d:02d}.nc'.format(
                        y=y, m=m, d=d + 1)
                    #print('opening', filename)
                    try:
                        this_cube = iris.load_cube(ncdir + filename,
                                                   varConstraint)
                    except OSError as err:
                        print(filename)
                        raise err
                    all_cubes.append(this_cube)

    iris.util.unify_time_units(all_cubes)
    equalise_attributes(all_cubes)
    cubes = all_cubes.concatenate()

    return cubes[0]
Example #29
0
    def test_combined(self):
        constraint = iris.Constraint(latitude=lambda c: c > 10, longitude=lambda c: c >= 10)

        self.assertCML(self.single_cube.extract(constraint), ('cdm', 'extract', 'lat_gt_10_and_lon_ge_10.cml'))
def get_sample(min_lon=-180,max_lon=360,min_lat=-90,max_lat=90,
                    start=datetime.datetime(1851,1,1,0,0),
                    end=datetime.datetime(1900,12,31,23,59),
                    climatology=None,
                    climstart=1961,climend=1991,
                    new_grid=None):

    # Load the model data
    e=[]
    dts=None
    for member in range(1,81):
        m = []
        for year in range(start.year,end.year+1):
            
            h=iris.load_cube('%s/20CR/version_3/monthly_means/%04d/PRMSL.%04d.mnmean_mem%03d.nc' % 
                                                               (os.getenv('SCRATCH'),year,year,member),
                             iris.Constraint(name='Pressure reduced to MSL') &
                                                          iris.Constraint(time=lambda cell: \
                                             start <= cell.point <=end))
            dty=h.coords('time')[0].units.num2date(h.coords('time')[0].points)

            # Anomalise
            if climatology is not None:
                for tidx in range(len(dty)):
                    midx=dty[tidx].month-1
                    h.data[tidx,:,:] -= climatology[midx].data

            if new_grid is not None:
                h = h.regrid(new_grid,iris.analysis.Nearest())
    
            # Reduce to area of interest
            h.coord('latitude').guess_bounds()
            h.coord('longitude').guess_bounds()
            h=h.extract(iris.Constraint(longitude=lambda v: min_lon <= v <= max_lon,
                                        latitude =lambda v: min_lat <= v <= max_lat))
                
            h.attributes=None
            h2=h
            if len(m)>0:
                # Workaround for metadata bug from varying versions of HDF library
                h2=m[0].copy()
                h2.data=h.data
                h2.remove_coord('time')
                h2.add_dim_coord(h.coord('time'),data_dim=0)
            m.append(h2)

        e.append(iris.cube.CubeList(m).concatenate_cube())

        if member==1:
            if dts is None:
                dts=dty
            else:
                dts=numpy.concatenate(dts,dty)
            
    # Get area averages
    ntp=e[0].data.shape[0]
    w = iris.analysis.cartography.area_weights(e[0])
    ndata=numpy.ma.array(numpy.zeros((ntp,80)),mask=True)
    for t in range(ntp):
        for m in range(80):
           ndata[:,m]=e[m].collapsed(['latitude', 'longitude'],
                                     iris.analysis.MEAN,
                                     weights=w).data
            
    return (ndata,dts)