def side_patches(elements, lat_max, lon0, data):

    # Get SideElements interpolated to lon0
    selements = fesom_sidegrid(elements, data, lon0, lat_max)
    # Build an array of quadrilateral patches for the plot, and of data
    # values corresponding to each SideElement
    patches = []
    values = []
    lat_min = lat_max
    for selm in selements:
        # Make patch
        coord = transpose(vstack((selm.y, selm.z)))
        patches.append(Polygon(coord, True, linewidth=0.))
        # Save data value
        values.append(selm.var)
        lat_min = min(lat_min, amin(selm.y))
    # Show a little bit of the land mask
    lat_min = lat_min - 0.5

    return patches, values, lat_min
def zonal_ts_before_after_ross_2094():

    # File paths
    mesh_path = '/short/y99/kaa561/FESOM/mesh/meshB/'
    file_beg = '/short/y99/kaa561/FESOM/highres_spinup/annual_avg.oce.mean.1996.2005.nc'
    file_end = '/short/y99/kaa561/FESOM/rcp85_A/output/MK44005.2094.oce.mean.nc'
    lon0 = -159
    lat_min = -85
    lat_max = -73

    print 'Building FESOM mesh'
    elm2D = fesom_grid(mesh_path)
    print 'Reading temperature and salinity data'
    id = Dataset(file_beg, 'r')
    temp_nodes_beg = id.variables['temp'][0, :]
    salt_nodes_beg = id.variables['salt'][0, :]
    id.close()
    # Annually average 2094
    id = Dataset(file_end, 'r')
    temp_nodes_end = mean(id.variables['temp'][:, :], axis=0)
    salt_nodes_end = mean(id.variables['salt'][:, :], axis=0)
    id.close()

    print 'Interpolating to ' + str(lon0)
    # Build arrays of SideElements making up zonal slices
    # Start with beginning
    selements_temp_beg = fesom_sidegrid(elm2D, temp_nodes_beg, lon0, lat_max)
    selements_salt_beg = fesom_sidegrid(elm2D, salt_nodes_beg, lon0, lat_max)
    # Build array of quadrilateral patches for the plots, and data values
    # corresponding to each SideElement
    patches = []
    temp_beg = []
    for selm in selements_temp_beg:
        # Make patch
        coord = transpose(vstack((selm.y, selm.z)))
        patches.append(Polygon(coord, True, linewidth=0.))
        # Save data value
        temp_beg.append(selm.var)
    temp_beg = array(temp_beg)
    # Salinity has same patches but different values
    salt_beg = []
    for selm in selements_salt_beg:
        salt_beg.append(selm.var)
    salt_beg = array(salt_beg)
    # Repeat for end
    selements_temp_end = fesom_sidegrid(elm2D, temp_nodes_end, lon0, lat_max)
    selements_salt_end = fesom_sidegrid(elm2D, salt_nodes_end, lon0, lat_max)
    temp_end = []
    for selm in selements_temp_end:
        temp_end.append(selm.var)
    temp_end = array(temp_end)
    salt_end = []
    for selm in selements_salt_end:
        salt_end.append(selm.var)
    salt_end = array(salt_end)
    # Find bounds on each variable
    temp_min = min(amin(temp_beg), amin(temp_end))
    temp_max = max(amax(temp_beg), amax(temp_end))
    salt_min = min(amin(salt_beg), amin(salt_end))
    salt_max = max(amax(salt_beg), amax(salt_end))
    # Find deepest depth
    # Start with 0
    depth_min = 0
    # Modify with patches
    for selm in selements_temp_beg:
        depth_min = min(depth_min, amin(selm.z))
    # Round down to nearest 50 metres
    depth_min = floor(depth_min / 50) * 50

    print 'Plotting'
    fig = figure(figsize=(16, 10))
    # Temperature
    gs_temp = GridSpec(1, 2)
    gs_temp.update(left=0.11,
                   right=0.9,
                   bottom=0.5,
                   top=0.9,
                   wspace=0.05,
                   hspace=0.5)
    # Beginning
    ax = subplot(gs_temp[0, 0])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(temp_beg)
    img.set_edgecolor('face')
    img.set_clim(vmin=temp_min, vmax=temp_max)
    ax.add_collection(img)
    xlim([lat_min, lat_max])
    ylim([depth_min, 0])
    title(r'Temperature ($^{\circ}$C), 1996-2005', fontsize=24)
    ax.set_xticklabels([])
    ylabel('Depth (m)', fontsize=18)
    # End
    ax = subplot(gs_temp[0, 1])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(temp_end)
    img.set_edgecolor('face')
    img.set_clim(vmin=temp_min, vmax=temp_max)
    ax.add_collection(img)
    xlim([lat_min, lat_max])
    ylim([depth_min, 0])
    title(r'Temperature ($^{\circ}$C), 2094', fontsize=24)
    ax.set_xticklabels([])
    ax.set_yticklabels([])
    # Add a colorbar on the right
    cbaxes = fig.add_axes([0.92, 0.55, 0.02, 0.3])
    cbar = colorbar(img, cax=cbaxes, extend='both')
    cbar.ax.tick_params(labelsize=16)
    # Salinity
    gs_salt = GridSpec(1, 2)
    gs_salt.update(left=0.11,
                   right=0.9,
                   bottom=0.05,
                   top=0.45,
                   wspace=0.05,
                   hspace=0.5)
    # Beginning
    ax = subplot(gs_salt[0, 0])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(salt_beg)
    img.set_edgecolor('face')
    img.set_clim(vmin=salt_min, vmax=salt_max)
    ax.add_collection(img)
    xlim([lat_min, lat_max])
    ylim([depth_min, 0])
    title('Salinity (psu), 1996-2005', fontsize=24)
    xlabel('Latitude', fontsize=18)
    ylabel('Depth (m)', fontsize=18)
    # End
    ax = subplot(gs_salt[0, 1])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(salt_end)
    img.set_edgecolor('face')
    img.set_clim(vmin=salt_min, vmax=salt_max)
    ax.add_collection(img)
    xlim([lat_min, lat_max])
    ylim([depth_min, 0])
    title('Salinity (psu), 2094', fontsize=24)
    xlabel('Latitude', fontsize=18)
    ax.set_yticklabels([])
    # Add a colorbar on the right
    cbaxes = fig.add_axes([0.92, 0.1, 0.02, 0.3])
    cbar = colorbar(img, cax=cbaxes, extend='both')
    cbar.ax.tick_params(labelsize=16)
    # Main title
    suptitle(r'RCP 8.5 A, 159$^{\circ}$W', fontsize=28)

    fig.show()
    fig.savefig('159W_rcp85_A_2094.png')
Exemple #3
0
def temp_salt_slice (elm2D, file_path, tstep, lon0, depth_min, save=False, fig_name=None):

    # Set northern boundary and upper (surface) boundary
    lat_max = -30
    depth_max = 0

    # Bounds on colour scales for temperature and salinity
    var_min = [-2, 33.8]
    var_max = [3, 34.8]
    var_tick = [1, 0.2]

    # Read temperature and salinity at each node
    id = Dataset(file_path, 'r')
    temp = id.variables['temp'][tstep-1,:]
    salt = id.variables['salt'][tstep-1,:]
    id.close()

    # Choose what to write on the title about longitude
    if lon0 < 0:
        lon_string = str(-lon0) + 'W'
    else:
        lon_string = str(lon0) + 'E'

    # Set up plots
    fig = figure(figsize=(24,6))
    # Make SideElements with temperature data
    selements_temp = fesom_sidegrid(elm2D, temp, lon0, lat_max)
    # Build an array of quadrilateral patches for the plot, and of data values
    # corresponding to each SideElement
    # Also find the minimum latitude of any SideElement
    patches = []
    values = []
    lat_min = lat_max
    for selm in selements_temp:
        # Make patch
        coord = transpose(vstack((selm.y,selm.z)))
        patches.append(Polygon(coord, True, linewidth=0.))
        # Save data value
        values.append(selm.var)
        # Update minimum latitude if needed
        lat_min = min(lat_min, amin(selm.y))
    # Set southern boundary to be just south of the minimum latitude
    lat_min = lat_min-1
    # Add to plot
    ax1 = fig.add_subplot(1,2,1)
    img1 = PatchCollection(patches)
    img1.set_array(array(values))
    img1.set_edgecolor('face')
    img1.set_clim(vmin=var_min[0], vmax=var_max[0])
    ax1.add_collection(img1)
    xlim(lat_min, lat_max)
    ylim(depth_min, depth_max)
    xlabel('Latitude')
    ylabel('Depth (m)')
    title(r'Temperature ($^{\circ}$C)', fontsize=20)
    cbar1 = colorbar(img1, ticks=arange(var_min[0], var_max[0]+var_tick[0], var_tick[0]), extend='both')
    cbar1.ax.tick_params(labelsize=16)
    # Repeat for salinity
    selements_salt = fesom_sidegrid(elm2D, salt, lon0, lat_max)
    patches = []
    values = []
    for selm in selements_salt:
        coord = transpose(vstack((selm.y,selm.z)))
        patches.append(Polygon(coord, True, linewidth=0.))
        values.append(selm.var)
    ax2 = fig.add_subplot(1,2,2)
    img2 = PatchCollection(patches)
    img2.set_array(array(values))
    img2.set_edgecolor('face')
    img2.set_clim(vmin=var_min[1], vmax=var_max[1])
    ax2.add_collection(img2)
    xlim(lat_min, lat_max)
    ylim(depth_min, depth_max)
    xlabel('Latitude')
    ylabel('Depth (m)')
    title('Salinity (psu)', fontsize=20)
    cbar2 = colorbar(img2, ticks=arange(var_min[1], var_max[1]+var_tick[1], var_tick[1]), extend='both')
    cbar2.ax.tick_params(labelsize=16)
    suptitle('Time index ' + str(tstep) + ', ' + lon_string, fontsize=24)
    subplots_adjust(wspace=0.025)

    if save:
        fig.savefig(fig_name)
    else:
        fig.show()
def zonal_cavity_ts_res():

    # Paths to mesh directories
    mesh_path_low = '../FESOM/mesh/low_res/'
    mesh_path_high = '../FESOM/mesh/high_res/'
    # Paths to output files
    output_path_low = '../FESOM/lowres_spinup/rep3/'
    output_path_high = '../FESOM/highres_spinup/rep3/'
    file_name = 'annual_avg.oce.mean.nc'

    # Name of each ice shelf
    shelf_names = [
        'Larsen D Ice Shelf', 'Larsen C Ice Shelf',
        'Wilkins & George VI & Stange Ice Shelves', 'Ronne-Filchner Ice Shelf',
        'Abbot Ice Shelf', 'Pine Island Glacier Ice Shelf',
        'Thwaites Ice Shelf', 'Dotson Ice Shelf', 'Getz Ice Shelf',
        'Nickerson Ice Shelf', 'Sulzberger Ice Shelf', 'Mertz Ice Shelf',
        'Totten & Moscow University Ice Shelves', 'Shackleton Ice Shelf',
        'West Ice Shelf', 'Amery Ice Shelf', 'Prince Harald Ice Shelf',
        'Baudouin & Borchgrevink Ice Shelves', 'Lazarev Ice Shelf',
        'Nivl Ice Shelf', 'Fimbul & Jelbart & Ekstrom Ice Shelves',
        'Brunt & Riiser-Larsen Ice Shelves', 'Ross Ice Shelf'
    ]
    # Beginnings of filenames for figures
    fig_heads = [
        'larsen_d', 'larsen_c', 'wilkins_georgevi_stange', 'ronne_filchner',
        'abbot', 'pig', 'thwaites', 'dotson', 'getz', 'nickerson',
        'sulzberger', 'mertz', 'totten_moscowuni', 'shackleton', 'west',
        'amery', 'prince_harald', 'baudouin_borchgrevink', 'lazarev', 'nivl',
        'fimbul_jelbart_ekstrom', 'brunt_riiser_larsen', 'ross'
    ]
    # Longitudes intersecting each ice shelf
    lon0 = [
        -60, -62, -68, -55, -93, -101, -106, -113, -120, -145, -150, 145, 116,
        96, 85, 71, 36, 25, 15, 11, -1, -20, 180
    ]
    # Latitude bounds for each ice shelf
    lat_min = [
        -73.1, -69.35, -73.1, -82.6, -73.28, -75.4, -75.5, -75, -74.9, -75.9,
        -77.8, -67.7, -67.17, -66.67, -67.25, -72, -69.7, -71, -70.4, -70.75,
        -71.83, -75.6, -84.6
    ]
    lat_max = [
        -72, -66.13, -70, -75.5, -72.3, -74.4, -74.67, -74, -73.5, -75.3,
        -76.41, -67, -66.5, -64.83, -66.25, -68.5, -68.7, -69.9, -69.33,
        -69.83, -69.33, -72.9, -77
    ]
    num_shelves = len(shelf_names)

    print 'Building FESOM mesh'
    elm2D_low = fesom_grid(mesh_path_low)
    elm2D_high = fesom_grid(mesh_path_high)
    print 'Reading temperature and salinity data'
    id = Dataset(output_path_low + file_name, 'r')
    temp_nodes_low = id.variables['temp'][0, :]
    salt_nodes_low = id.variables['salt'][0, :]
    id.close()
    id = Dataset(output_path_high + file_name, 'r')
    temp_nodes_high = id.variables['temp'][0, :]
    salt_nodes_high = id.variables['salt'][0, :]
    id.close()

    # Loop over ice shelves
    for index in range(num_shelves):
        print 'Processing ' + shelf_names[index]
        # Figure out what to write on the title about longitude
        if lon0[index] < 0:
            lon_string = ' (' + str(-lon0[index]) + r'$^{\circ}$W)'
        else:
            lon_string = ' (' + str(lon0[index]) + r'$^{\circ}$E)'
        # Build arrays of SideElements making up zonal slices
        selements_temp_low = fesom_sidegrid(elm2D_low, temp_nodes_low,
                                            lon0[index], lat_max[index])
        selements_salt_low = fesom_sidegrid(elm2D_low, salt_nodes_low,
                                            lon0[index], lat_max[index])
        selements_temp_high = fesom_sidegrid(elm2D_high, temp_nodes_high,
                                             lon0[index], lat_max[index])
        selements_salt_high = fesom_sidegrid(elm2D_high, salt_nodes_high,
                                             lon0[index], lat_max[index])
        # Build array of quadrilateral patches for the plots, and data values
        # corresponding to each SideElement
        patches_low = []
        temp_low = []
        for selm in selements_temp_low:
            # Make patch
            coord = transpose(vstack((selm.y, selm.z)))
            patches_low.append(Polygon(coord, True, linewidth=0.))
            # Save data value
            temp_low.append(selm.var)
        temp_low = array(temp_low)
        # Salinity has same patches but different values
        salt_low = []
        for selm in selements_salt_low:
            salt_low.append(selm.var)
        salt_low = array(salt_low)
        # Repeat for high-res
        patches_high = []
        temp_high = []
        for selm in selements_temp_high:
            coord = transpose(vstack((selm.y, selm.z)))
            patches_high.append(Polygon(coord, True, linewidth=0.))
            temp_high.append(selm.var)
        temp_high = array(temp_high)
        salt_high = []
        for selm in selements_salt_high:
            salt_high.append(selm.var)
        salt_high = array(salt_high)
        # Find bounds on each variable
        temp_min = min(amin(temp_low), amin(temp_high))
        temp_max = max(amax(temp_low), amax(temp_high))
        salt_min = min(amin(salt_low), amin(salt_high))
        salt_max = max(amax(salt_low), amax(salt_high))
        # Find deepest depth
        # Start with 0
        depth_min = 0
        # Modify with low-res patches
        for selm in selements_temp_low:
            depth_min = min(depth_min, amin(selm.z))
        # Modify with high-res patches
        for selm in selements_temp_high:
            depth_min = min(depth_min, amin(selm.z))
        # Round down to nearest 50 metres
        depth_min = floor(depth_min / 50) * 50
        # Plot
        fig = figure(figsize=(18, 12))
        # Low-res temperature
        ax = fig.add_subplot(2, 2, 1)
        img1 = PatchCollection(patches_low, cmap='jet')
        img1.set_array(temp_low)
        img1.set_edgecolor('face')
        img1.set_clim(vmin=temp_min, vmax=temp_max)
        ax.add_collection(img1)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        title(r'Low-res temperature ($^{\circ}$C)', fontsize=20)
        ylabel('Depth (m)', fontsize=16)
        # High-res temperature
        ax = fig.add_subplot(2, 2, 2)
        img2 = PatchCollection(patches_high, cmap='jet')
        img2.set_array(temp_high)
        img2.set_edgecolor('face')
        img2.set_clim(vmin=temp_min, vmax=temp_max)
        ax.add_collection(img2)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        title(r'High-res temperature ($^{\circ}$C)', fontsize=20)
        # Add colorbar for temperature
        cbaxes_temp = fig.add_axes([0.92, 0.575, 0.01, 0.3])
        cbar_temp = colorbar(img2, cax=cbaxes_temp)
        cbar_temp.ax.tick_params(labelsize=16)
        # Low-res salinity
        ax = fig.add_subplot(2, 2, 3)
        img3 = PatchCollection(patches_low, cmap='jet')
        img3.set_array(salt_low)
        img3.set_edgecolor('face')
        img3.set_clim(vmin=salt_min, vmax=salt_max)
        ax.add_collection(img3)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        title('Low-res salinity (psu)', fontsize=20)
        xlabel('Latitude', fontsize=16)
        ylabel('Depth (m)', fontsize=16)
        # High-res salinity
        ax = fig.add_subplot(2, 2, 4)
        img4 = PatchCollection(patches_high, cmap='jet')
        img4.set_array(salt_high)
        img4.set_edgecolor('face')
        img4.set_clim(vmin=salt_min, vmax=salt_max)
        ax.add_collection(img4)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        title('High-res salinity (psu)', fontsize=20)
        xlabel('Latitude', fontsize=16)
        # Add colorbar for salinity
        cbaxes_salt = fig.add_axes([0.92, 0.125, 0.01, 0.3])
        cbar_salt = colorbar(img4, cax=cbaxes_salt)
        cbar_salt.ax.tick_params(labelsize=16)
        # Main title
        suptitle(shelf_names[index] + lon_string, fontsize=28)
        #fig.show()
        fig.savefig(fig_heads[index] + '_zonal_ts.png')
def mip_zonal_cavity_ts (roms_grid, roms_file, fesom_mesh_path_lr, fesom_file_lr, fesom_mesh_path_hr, fesom_file_hr):

    # Name of each ice shelf
    shelf_names = ['Larsen D Ice Shelf', 'Larsen C Ice Shelf', 'Wilkins & George VI & Stange Ice Shelves', 'Ronne-Filchner Ice Shelf', 'Abbot Ice Shelf', 'Pine Island Glacier Ice Shelf', 'Thwaites Ice Shelf', 'Dotson Ice Shelf', 'Getz Ice Shelf', 'Nickerson Ice Shelf', 'Sulzberger Ice Shelf', 'Mertz Ice Shelf', 'Totten & Moscow University Ice Shelves', 'Shackleton Ice Shelf', 'West Ice Shelf', 'Amery Ice Shelf', 'Prince Harald Ice Shelf', 'Baudouin & Borchgrevink Ice Shelves', 'Lazarev Ice Shelf', 'Nivl Ice Shelf', 'Fimbul & Jelbart & Ekstrom Ice Shelves', 'Brunt & Riiser-Larsen Ice Shelves', 'Ross Ice Shelf']
    # Beginnings of filenames for figures
    fig_heads = ['larsen_d', 'larsen_c', 'wilkins_georgevi_stange', 'ronne_filchner', 'abbot', 'pig', 'thwaites', 'dotson', 'getz', 'nickerson', 'sulzberger', 'mertz', 'totten_moscowuni', 'shackleton', 'west', 'amery', 'prince_harald', 'baudouin_borchgrevink', 'lazarev', 'nivl', 'fimbul_jelbart_ekstrom', 'brunt_riiser_larsen', 'ross']
    # Longitudes intersecting each ice shelf
    lon0 = [-60, -62, -68, -55, -93, -101, -106, -113, -120, -145, -150, 145, 116, 96, 85, 71, 36, 25, 15, 11, -1, -20, 180]
    # Latitude bounds for each ice shelf
    lat_min = [-73.1, -69.35, -73.1, -82.6, -73.28, -75.4, -75.5, -75, -74.9, -75.9, -77.8, -67.7, -67.17, -66.67, -67.25, -72, -69.7, -71, -70.4, -70.75, -71.83, -75.6, -84.6]
    lat_max = [-72, -66.13, -70, -75.5, -72.3, -74.4, -74.67, -74, -73.5, -75.3, -76.41, -67, -66.5, -64.83, -66.25, -68.5, -68.7, -69.9, -69.33, -69.83, -69.33, -72.9, -77]
    num_shelves = len(shelf_names)
    # ROMS grid parameters
    theta_s = 7.0
    theta_b = 2.0
    hc = 250
    N = 31

    print 'Setting up ROMS'
    # Start with grid
    id = Dataset(roms_grid, 'r')
    h = id.variables['h'][:,:]
    zice = id.variables['zice'][:,:]
    lon_2d = id.variables['lon_rho'][:,:]
    lat_2d = id.variables['lat_rho'][:,:]
    id.close()
    # Get a 3D array of z-coordinates; sc_r and Cs_r are unused in this script
    z_3d, sc_r, Cs_r = calc_z(h, zice, theta_s, theta_b, hc, N)
    # Read temperature and salinity
    id = Dataset(roms_file, 'r')
    roms_temp_3d = id.variables['temp'][0,:,:,:]
    roms_salt_3d = id.variables['salt'][0,:,:,:]
    id.close()

    print 'Setting up low-res FESOM'
    # Build the regular FESOM grid
    elm2D_lr = fesom_grid(fesom_mesh_path_lr)
    # Read temperature and salinity at every node
    id = Dataset(fesom_file_lr, 'r')
    fesom_temp_nodes_lr = id.variables['temp'][0,:]
    fesom_salt_nodes_lr = id.variables['salt'][0,:]
    id.close()

    print 'Setting up high-res FESOM'
    elm2D_hr = fesom_grid(fesom_mesh_path_hr)
    id = Dataset(fesom_file_hr, 'r')
    fesom_temp_nodes_hr = id.variables['temp'][0,:]
    fesom_salt_nodes_hr = id.variables['salt'][0,:]
    id.close()

    # Loop over ice shelves
    for index in range(num_shelves):
        print 'Processing ' + shelf_names[index]
        # Figure out what to write on the title about longitude
        if lon0[index] < 0:
            lon_string = ' ('+str(-lon0[index])+r'$^{\circ}$W)'
        else:
            lon_string = ' ('+str(lon0[index])+r'$^{\circ}$E)'

        # MetROMS
        # Make sure longitude is between 0 and 360
        roms_lon0 = lon0[index]
        if roms_lon0 < 0:
            roms_lon0 += 360
        # Interpolate to given longitude
        roms_temp, roms_z, roms_lat = interp_lon_roms(roms_temp_3d, z_3d, lat_2d, lon_2d, roms_lon0)
        roms_salt, roms_z, roms_lat = interp_lon_roms(roms_salt_3d, z_3d, lat_2d, lon_2d, roms_lon0)
        # Figure out deepest depth
        flag = (roms_lat >= lat_min[index])*(roms_lat <= lat_max[index])
        depth_min_tmp = amin(roms_z[flag])
        # Round down to nearest 50 metres
        depth_min = floor(depth_min_tmp/50)*50

        # FESOM low-res
        # Build arrays of SideElements making up zonal slices
        selements_temp_lr = fesom_sidegrid(elm2D_lr, fesom_temp_nodes_lr, lon0[index], lat_max[index])
        selements_salt_lr = fesom_sidegrid(elm2D_lr, fesom_salt_nodes_lr, lon0[index], lat_max[index])
        # Build array of quadrilateral patches for the plots, and data values
        # corresponding to each SideElement
        patches_lr = []
        fesom_temp_lr = []
        for selm in selements_temp_lr:
            # Make patch
            coord = transpose(vstack((selm.y, selm.z)))
            patches_lr.append(Polygon(coord, True, linewidth=0.))
            # Save data value
            fesom_temp_lr.append(selm.var)
        fesom_temp_lr = array(fesom_temp_lr)
        # Salinity has same patches but different values
        fesom_salt_lr = []
        for selm in selements_salt_lr:
            fesom_salt_lr.append(selm.var)
        fesom_salt_lr = array(fesom_salt_lr)

        # FESOM high-res
        selements_temp_hr = fesom_sidegrid(elm2D_hr, fesom_temp_nodes_hr, lon0[index], lat_max[index])
        selements_salt_hr = fesom_sidegrid(elm2D_hr, fesom_salt_nodes_hr, lon0[index], lat_max[index])
        patches_hr = []
        fesom_temp_hr = []
        for selm in selements_temp_hr:
            coord = transpose(vstack((selm.y, selm.z)))
            patches_hr.append(Polygon(coord, True, linewidth=0.))
            fesom_temp_hr.append(selm.var)
        fesom_temp_hr = array(fesom_temp_hr)
        fesom_salt_hr = []
        for selm in selements_salt_hr:
            fesom_salt_hr.append(selm.var)
        fesom_salt_hr = array(fesom_salt_hr)

        # Find bounds on each variable
        temp_min = amin(array([amin(roms_temp[flag]), amin(fesom_temp_lr), amin(fesom_temp_hr)]))
        temp_max = amax(array([amax(roms_temp[flag]), amax(fesom_temp_lr), amax(fesom_temp_hr)]))
        salt_min = amin(array([amin(roms_salt[flag]), amin(fesom_salt_lr), amin(fesom_salt_hr)]))
        salt_max = amax(array([amax(roms_salt[flag]), amax(fesom_salt_lr), amax(fesom_salt_hr)]))
        # Plot
        fig = figure(figsize=(24,12))
        # MetROMS temperature
        ax = fig.add_subplot(2, 3, 1)
        pcolor(roms_lat, roms_z, roms_temp, vmin=temp_min, vmax=temp_max, cmap='jet')
        title(r'MetROMS temperature ($^{\circ}$C)', fontsize=20)
        ylabel('Depth (m)', fontsize=16)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        # FESOM low-res temperature
        ax = fig.add_subplot(2, 3, 2)
        img = PatchCollection(patches_lr, cmap='jet')
        img.set_array(fesom_temp_lr)
        img.set_edgecolor('face')
        img.set_clim(vmin=temp_min, vmax=temp_max)
        ax.add_collection(img)
        title(r'FESOM (low-res) temperature ($^{\circ}$C)', fontsize=20)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        # FESOM high-res temperature
        ax = fig.add_subplot(2, 3, 3)
        img = PatchCollection(patches_hr, cmap='jet')
        img.set_array(fesom_temp_hr)
        img.set_edgecolor('face')
        img.set_clim(vmin=temp_min, vmax=temp_max)
        ax.add_collection(img)
        title(r'FESOM (high-res) temperature ($^{\circ}$C)', fontsize=20)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        # Add colorbar for temperature
        cbaxes = fig.add_axes([0.92, 0.575, 0.01, 0.3])
        cbar = colorbar(img, cax=cbaxes)
        cbar.ax.tick_params(labelsize=16)
        # MetROMS salinity
        ax = fig.add_subplot(2, 3, 4)
        pcolor(roms_lat, roms_z, roms_salt, vmin=salt_min, vmax=salt_max, cmap='jet')
        title('MetROMS salinity (psu)', fontsize=20)    
        xlabel('Latitude', fontsize=16)
        ylabel('Depth (m)', fontsize=16)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        # FESOM low-res salinity
        ax = fig.add_subplot(2, 3, 5)
        img = PatchCollection(patches_lr, cmap='jet')
        img.set_array(fesom_salt_lr)
        img.set_edgecolor('face') 
        img.set_clim(vmin=salt_min, vmax=salt_max)
        ax.add_collection(img)
        title(r'FESOM (low-res) salinity (psu)', fontsize=20)
        xlabel('Latitude', fontsize=16)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        # FESOM high-res salinity
        ax = fig.add_subplot(2, 3, 6)
        img = PatchCollection(patches_hr, cmap='jet')
        img.set_array(fesom_salt_hr)
        img.set_edgecolor('face') 
        img.set_clim(vmin=salt_min, vmax=salt_max)
        ax.add_collection(img)
        title(r'FESOM (high-res) salinity (psu)', fontsize=20)
        xlabel('Latitude', fontsize=16)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        # Add colorbar for salinity
        cbaxes = fig.add_axes([0.92, 0.125, 0.01, 0.3])
        cbar = colorbar(img, cax=cbaxes)
        cbar.ax.tick_params(labelsize=16)
        # Main title
        suptitle(shelf_names[index] + lon_string, fontsize=28)
        #fig.show()
        fig.savefig(fig_heads[index] + '_zonal_ts.png')
def zonal_cavity_ts_rcp(mesh_path, spinup_path, rcp_path, fig_dir=''):

    file_name_beg = spinup_path + 'annual_avg.oce.mean.1996.2005.nc'
    file_name_end = rcp_path + 'annual_avg.oce.mean.2091.2100.nc'

    # Name of each ice shelf
    shelf_names = [
        'Larsen D Ice Shelf', 'Larsen C Ice Shelf',
        'Wilkins & George VI & Stange Ice Shelves', 'Ronne-Filchner Ice Shelf',
        'Abbot Ice Shelf', 'Pine Island Glacier Ice Shelf',
        'Thwaites Ice Shelf', 'Dotson Ice Shelf', 'Getz Ice Shelf',
        'Nickerson Ice Shelf', 'Sulzberger Ice Shelf', 'Mertz Ice Shelf',
        'Totten & Moscow University Ice Shelves', 'Shackleton Ice Shelf',
        'West Ice Shelf', 'Amery Ice Shelf', 'Prince Harald Ice Shelf',
        'Baudouin & Borchgrevink Ice Shelves', 'Lazarev Ice Shelf',
        'Nivl Ice Shelf', 'Fimbul & Jelbart & Ekstrom Ice Shelves',
        'Brunt & Riiser-Larsen Ice Shelves', 'Ross Ice Shelf'
    ]
    # Beginnings of filenames for figures
    fig_heads = [
        'larsen_d', 'larsen_c', 'wilkins_georgevi_stange', 'ronne_filchner',
        'abbot', 'pig', 'thwaites', 'dotson', 'getz', 'nickerson',
        'sulzberger', 'mertz', 'totten_moscowuni', 'shackleton', 'west',
        'amery', 'prince_harald', 'baudouin_borchgrevink', 'lazarev', 'nivl',
        'fimbul_jelbart_ekstrom', 'brunt_riiser_larsen', 'ross'
    ]
    # Longitudes intersecting each ice shelf
    lon0 = [
        -60, -62, -68, -55, -93, -101, -106, -113, -120, -145, -150, 145, 116,
        96, 85, 71, 36, 25, 15, 11, -1, -20, 180
    ]
    # Latitude bounds for each ice shelf
    lat_min = [
        -73.1, -69.35, -73.1, -82.6, -73.28, -75.4, -75.5, -75, -74.9, -75.9,
        -77.8, -67.7, -67.17, -66.67, -67.25, -72, -69.7, -71, -70.4, -70.75,
        -71.83, -75.6, -84.6
    ]
    lat_max = [
        -72, -66.13, -70, -75.5, -72.3, -74.4, -74.67, -74, -73.5, -75.3,
        -76.41, -67, -66.5, -64.83, -66.25, -68.5, -68.7, -69.9, -69.33,
        -69.83, -69.33, -72.9, -77
    ]
    num_shelves = len(shelf_names)

    print 'Building FESOM mesh'
    elm2D = fesom_grid(mesh_path)
    print 'Reading temperature and salinity data'
    id = Dataset(file_name_beg, 'r')
    temp_nodes_beg = id.variables['temp'][0, :]
    salt_nodes_beg = id.variables['salt'][0, :]
    id.close()
    id = Dataset(file_name_end, 'r')
    temp_nodes_end = id.variables['temp'][0, :]
    salt_nodes_end = id.variables['salt'][0, :]
    id.close()
    temp_nodes_diff = temp_nodes_end - temp_nodes_beg
    salt_nodes_diff = salt_nodes_end - salt_nodes_beg

    # Loop over ice shelves
    for index in range(num_shelves):
        print 'Processing ' + shelf_names[index]
        # Figure out what to write on the title about longitude
        if lon0[index] < 0:
            lon_string = ' (' + str(-lon0[index]) + r'$^{\circ}$W)'
        else:
            lon_string = ' (' + str(lon0[index]) + r'$^{\circ}$E)'
        # Build arrays of SideElements making up zonal slices
        selements_temp_beg = fesom_sidegrid(elm2D, temp_nodes_beg, lon0[index],
                                            lat_max[index])
        selements_salt_beg = fesom_sidegrid(elm2D, salt_nodes_beg, lon0[index],
                                            lat_max[index])
        selements_temp_end = fesom_sidegrid(elm2D, temp_nodes_end, lon0[index],
                                            lat_max[index])
        selements_salt_end = fesom_sidegrid(elm2D, salt_nodes_end, lon0[index],
                                            lat_max[index])
        selements_temp_diff = fesom_sidegrid(elm2D, temp_nodes_diff,
                                             lon0[index], lat_max[index])
        selements_salt_diff = fesom_sidegrid(elm2D, salt_nodes_diff,
                                             lon0[index], lat_max[index])
        # Build array of quadrilateral patches for the plots, and data values
        # corresponding to each SideElement
        patches = []
        temp_beg = []
        for selm in selements_temp_beg:
            # Make patch
            coord = transpose(vstack((selm.y, selm.z)))
            patches.append(Polygon(coord, True, linewidth=0.))
            # Save data value
            temp_beg.append(selm.var)
        temp_beg = array(temp_beg)
        # Other variables have same patches but different values
        salt_beg = []
        for selm in selements_salt_beg:
            salt_beg.append(selm.var)
        salt_beg = array(salt_beg)
        temp_end = []
        for selm in selements_temp_end:
            temp_end.append(selm.var)
        temp_end = array(temp_end)
        salt_end = []
        for selm in selements_salt_end:
            salt_end.append(selm.var)
        salt_end = array(salt_end)
        temp_diff = []
        for selm in selements_temp_diff:
            temp_diff.append(selm.var)
        temp_diff = array(temp_diff)
        salt_diff = []
        for selm in selements_salt_diff:
            salt_diff.append(selm.var)
        salt_diff = array(salt_diff)
        # Find bounds on each variable
        temp_min = min(amin(temp_beg), amin(temp_end))
        temp_max = max(amax(temp_beg), amax(temp_end))
        temp_max_diff = amax(abs(temp_diff))
        salt_min = min(amin(salt_beg), amin(salt_end))
        salt_max = max(amax(salt_beg), amax(salt_end))
        salt_max_diff = amax(abs(salt_diff))
        # Find deepest depth
        depth_min = 0
        for selm in selements_temp_beg:
            depth_min = min(depth_min, amin(selm.z))
        # Round down to nearest 50 metres
        depth_min = floor(depth_min / 50) * 50
        # Plot
        fig = figure(figsize=(24, 12))
        # Temperature (beginning)
        ax = fig.add_subplot(2, 3, 1)
        img = PatchCollection(patches, cmap='jet')
        img.set_array(temp_beg)
        img.set_edgecolor('face')
        img.set_clim(vmin=temp_min, vmax=temp_max)
        ax.add_collection(img)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        title(r'Temperature ($^{\circ}$C), 1996-2005', fontsize=20)
        ylabel('Depth (m)', fontsize=16)
        # Add colorbar for absolute temperature
        cbaxes_temp = fig.add_axes([0.05, 0.575, 0.01, 0.3])
        cbar_temp = colorbar(img, cax=cbaxes_temp)
        cbar_temp.ax.tick_params(labelsize=16)
        # Temperature (end)
        ax = fig.add_subplot(2, 3, 2)
        img = PatchCollection(patches, cmap='jet')
        img.set_array(temp_end)
        img.set_edgecolor('face')
        img.set_clim(vmin=temp_min, vmax=temp_max)
        ax.add_collection(img)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        title(r'Temperature ($^{\circ}$C), 2091-2100', fontsize=20)
        ylabel('Depth (m)', fontsize=16)
        # Temperature (difference)
        ax = fig.add_subplot(2, 3, 3)
        img = PatchCollection(patches, cmap='RdBu_r')
        img.set_array(temp_diff)
        img.set_edgecolor('face')
        img.set_clim(vmin=-temp_max_diff, vmax=temp_max_diff)
        ax.add_collection(img)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        title(r'Temperature ($^{\circ}$C), change', fontsize=20)
        ylabel('Depth (m)', fontsize=16)
        # Add colorbar for temperature difference
        cbaxes_dtemp = fig.add_axes([0.92, 0.575, 0.01, 0.3])
        cbar_dtemp = colorbar(img, cax=cbaxes_dtemp)
        cbar_dtemp.ax.tick_params(labelsize=16)
        # Salinity (beginning)
        ax = fig.add_subplot(2, 3, 4)
        img = PatchCollection(patches, cmap='jet')
        img.set_array(salt_beg)
        img.set_edgecolor('face')
        img.set_clim(vmin=salt_min, vmax=salt_max)
        ax.add_collection(img)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        title('Salinity (psu), 1995-2005', fontsize=20)
        ylabel('Depth (m)', fontsize=16)
        # Add colorbar for absolute salinity
        cbaxes_salt = fig.add_axes([0.05, 0.125, 0.01, 0.3])
        cbar_salt = colorbar(img, cax=cbaxes_salt)
        cbar_salt.ax.tick_params(labelsize=16)
        # Salinity (end)
        ax = fig.add_subplot(2, 3, 5)
        img = PatchCollection(patches, cmap='jet')
        img.set_array(salt_end)
        img.set_edgecolor('face')
        img.set_clim(vmin=salt_min, vmax=salt_max)
        ax.add_collection(img)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        title('Salinity (psu), 2091-2100', fontsize=20)
        ylabel('Depth (m)', fontsize=16)
        # Salinity (difference)
        ax = fig.add_subplot(2, 3, 6)
        img = PatchCollection(patches, cmap='RdBu_r')
        img.set_array(salt_diff)
        img.set_edgecolor('face')
        img.set_clim(vmin=-salt_max_diff, vmax=salt_max_diff)
        ax.add_collection(img)
        xlim([lat_min[index], lat_max[index]])
        ylim([depth_min, 0])
        title('Salinity (psu), change', fontsize=20)
        ylabel('Depth (m)', fontsize=16)
        # Add colorbar for salinity difference
        cbaxes_dsalt = fig.add_axes([0.92, 0.125, 0.01, 0.3])
        cbar_dsalt = colorbar(img, cax=cbaxes_dsalt)
        cbar_dsalt.ax.tick_params(labelsize=16)
        # Main title
        suptitle(shelf_names[index] + lon_string, fontsize=28)
        #fig.show()
        fig.savefig(fig_dir + fig_heads[index] + '_zonal_ts.png')
def timeseries_dpt (mesh_path, ocn_file, log_file):

    circumpolar = False  # Don't transform x and y coordinates, we need them!
    cross_180 = False    # Don't make second copies of elements that cross 180E
    days_per_output = 5  # Number of days for each output step

    # Longitude of Drake Passage zonal slice
    lon0 = -67
    # Latitude bounds on Drake Passage zonal slice
    lat_min = -68
    lat_max = -54.5

    dpt = []
    # Check if the log file exists
    if exists(log_file):
        print 'Reading previously calculated values'
        f = open(log_file, 'r')
        # Skip the first line (header)
        f.readline()
        for line in f:
            dpt.append(float(line))
        f.close()

    print 'Building grid'
    # First get regular 2D elements
    elm2D = fesom_grid(mesh_path, circumpolar, cross_180)
    # Read longitude and latitude of each node in order (needed for rotation)
    fid = open(mesh_path + 'nod3d.out', 'r')
    fid.readline()
    lon = []
    lat = []
    for line in fid:
        tmp = line.split()
        lon_tmp = float(tmp[1])
        lat_tmp = float(tmp[2])
        if lon_tmp < -180:
            lon_tmp += 360
        elif lon_tmp > 180:
            lon_tmp -= 360
        lon.append(lon_tmp)
        lat.append(lat_tmp)
    fid.close()
    lon = array(lon)
    lat = array(lat)

    print 'Reading data'
    id = Dataset(ocn_file, 'r')
    num_time = id.variables['time'].shape[0]
    # Read both u and v so we can rotate to get the real u
    u_r = id.variables['u'][:,:]
    v_r = id.variables['v'][:,:]
    id.close()

    print 'Unrotating velocity vector'
    u = zeros(shape(u_r))
    # Rotate one time index at a time
    for t in range(num_time):
        u_tmp, v_tmp = unrotate_vector(lon, lat, u_r[t,:], v_r[t,:])
        u[t,:] = u_tmp

    print 'Extracting zonal slice through Drake Passage'
    # Get quadrilateral elements in the latitude vs depth slice
    selements = fesom_sidegrid(elm2D, u, lon0, lat_max, lat_min)

    print 'Setting up arrays'
    # Eastward velocity at each element
    u_selm = zeros([num_time, len(selements)])
    # Area of each element
    area_selm = zeros(len(selements))
    # Loop over elements to fill these in
    for i in range(len(selements)):
        selm = selements[i]
        u_selm[:,i] = selm.var
        area_selm[i] = selm.area()
    # Build timeseries
    for t in range(num_time):
        # Integrate u*area and convert to Sv
        dpt.append(sum(u_selm[t,:]*area_selm)*1e-6)

    # Calculate time values
    time = arange(len(dpt))*days_per_output/365.

    print 'Plotting'
    clf()
    plot(time, dpt)
    xlabel('Years')
    ylabel('Drake Passage Transport (Sv)')
    grid(True)
    savefig('drakepsgtrans.png')

    print 'Saving results to log file'
    f = open(log_file, 'w')
    f.write('Drake Passage Transport (Sv):\n')
    for elm in dpt:
        f.write(str(elm) + '\n')
    f.close()
def zonal_slice_plot (mesh_path, file_path, var_name, tstep, lon0, depth_min, save=False, fig_name=None, set_limits=False, limits=None):

    # Set northern boundary and upper (surface) boundary
    lat_max = -50
    depth_max = 0
    # Font sizes for figure
    font_sizes = [30, 24, 20]

    # Read variable name and units for title
    id = Dataset(file_path, 'r')
    varid = id.variables[var_name]
    name = varid.getncattr('description')
    units = varid.getncattr('units')
    if lon0 < 0:
        lon_string = 'at ' + str(-lon0) + 'W'
    else:
        lon_string = 'at ' + str(lon0) + 'E'

    # Read data
    data = id.variables[var_name][tstep-1,:]
    # Check for vector variables that need to be unrotated
    if var_name in ['u', 'v']:
        # Read the rotated lat and lon
        fid = open(mesh_path + 'nod3d.out', 'r')
        fid.readline()
        lon = []
        lat = []
        for line in fid:
            tmp = line.split()
            lon_tmp = float(tmp[1])
            lat_tmp = float(tmp[2])
            if lon_tmp < -180:
                lon_tmp += 360
            elif lon_tmp > 180:
                lon_tmp -= 360
            lon.append(lon_tmp)
            lat.append(lat_tmp)
        fid.close()
        lon = array(lon)
        lat = array(lat)
        if var_name == 'u':
            u_data = data[:]
            v_data = id.variables['v'][tstep-1,:]
            u_data_lonlat, v_data_lonlat = unrotate_vector(lon, lat, u_data, v_data)
            data = u_data_lonlat[:]
        elif var_name == 'v':
            v_data = data[:]
            u_data = id.variables['u'][tstep-1,:]
            u_data_lonlat, v_data_lonlat = unrotate_vector(lon, lat, u_data, v_data)
            data = v_data_lonlat[:]
    id.close()    

    # Build the regular FESOM grid
    elm2D = fesom_grid(mesh_path)

    # Build the array of SideElements making up the zonal slice
    selements = fesom_sidegrid(elm2D, data, lon0, lat_max)

    # Build an array of quadrilateral patches for the plot, and of data values
    # corresponding to each SideElement
    # Also find the minimum latitude of any SideElement
    patches = []
    values = []
    lat_min = lat_max
    for selm in selements:
        # Make patch
        coord = transpose(vstack((selm.y,selm.z)))
        patches.append(Polygon(coord, True, linewidth=0.))
        # Save data value
        values.append(selm.var)
        # Update minimum latitude if needed
        lat_min = min(lat_min, amin(selm.y))
    # Set southern boundary to be just south of the minimum latitude
    lat_min = lat_min-1

    # Choose colour bounds
    if set_limits:
        # User-specified bounds
        var_min = limits[0]
        var_max = limits[1]
        if var_min == -var_max:
            # Bounds are centered on zero, so choose a blue-to-red colourmap
            # centered on yellow
            colour_map = 'RdYlBu_r'
        else:
            colour_map = 'jet'
    else:
        # Determine bounds automatically
        if var_name in ['u', 'v', 'w']:
            # Center levels on 0 for certain variables, with a blue-to-red
            # colourmap
            max_val = amax(abs(array(values)))
            var_min = -max_val
            var_max = max_val
            colour_map = 'RdYlBu_r'
        else:
            var_min = amin(array(values))
            var_max = amax(array(values))
            colour_map = 'jet'

    # Set up plot
    fig = figure(figsize=(16,8))
    ax = fig.add_subplot(1,1,1)
    # Set colourmap for patches, and refer it to the values array
    img = PatchCollection(patches, cmap=colour_map)
    img.set_array(array(values))
    img.set_edgecolor('face')
    # Add patches to plot
    ax.add_collection(img)

    # Configure plot
    xlim(lat_min, lat_max)
    ylim(depth_min, depth_max)
    title(name + ' (' + units + ') ' + lon_string, fontsize=font_sizes[0])
    xlabel('Latitude', fontsize=font_sizes[1])
    ylabel('Depth (m)', fontsize=font_sizes[1])
    setp(ax.get_xticklabels(), fontsize=font_sizes[2])
    setp(ax.get_yticklabels(), fontsize=font_sizes[2])
    cbar = colorbar(img)
    cbar.ax.tick_params(labelsize=font_sizes[2])
    img.set_clim(vmin=var_min, vmax=var_max)

    if save:
        fig.savefig(fig_name)
    else:
        fig.show()
def timeseries_dpt (mesh_path, ocn_file, log_file, fig_dir=''):

    circumpolar = False  # Needs to be global for SideElements
    cross_180 = False    # Don't make second copies of elements that cross 180E
    days_per_output = 5  # Number of days for each output step

    # Longitude of Drake Passage zonal slice
    lon0 = -67
    # Latitude bounds on Drake Passage zonal slice
    lat_min = -68
    lat_max = -54.5

    dpt = []
    # Check if the log file exists
    if exists(log_file):
        print 'Reading previously calculated values'
        f = open(log_file, 'r')
        # Skip the first line (header)
        f.readline()
        for line in f:
            dpt.append(float(line))
        f.close()

    print 'Building grid'
    # First get regular 2D elements
    elm2D = fesom_grid(mesh_path, circumpolar, cross_180)
    # Read longitude and latitude of each node in order (needed for rotation)
    fid = open(mesh_path + 'nod3d.out', 'r')
    fid.readline()
    lon = []
    lat = []
    for line in fid:
        tmp = line.split()
        lon_tmp = float(tmp[1])
        lat_tmp = float(tmp[2])
        if lon_tmp < -180:
            lon_tmp += 360
        elif lon_tmp > 180:
            lon_tmp -= 360
        lon.append(lon_tmp)
        lat.append(lat_tmp)
    fid.close()
    lon = array(lon)
    lat = array(lat)

    print 'Reading data'
    id = Dataset(ocn_file, 'r')
    num_time = id.variables['time'].shape[0]
    # Read both u and v so we can rotate to get the real u
    u_r = id.variables['u'][:,:]
    v_r = id.variables['v'][:,:]
    id.close()

    print 'Unrotating velocity vector'
    u = zeros(shape(u_r))
    # Rotate one time index at a time
    for t in range(num_time):
        u_tmp, v_tmp = unrotate_vector(lon, lat, u_r[t,:], v_r[t,:])
        u[t,:] = u_tmp

    print 'Extracting zonal slice through Drake Passage'
    # Get quadrilateral elements in the latitude vs depth slice
    selements = fesom_sidegrid(elm2D, u, lon0, lat_max, lat_min)

    print 'Setting up arrays'
    # Eastward velocity at each element
    u_selm = zeros([num_time, len(selements)])
    # Area of each element
    area_selm = zeros(len(selements))
    # Loop over elements to fill these in
    for i in range(len(selements)):
        selm = selements[i]
        u_selm[:,i] = selm.var
        area_selm[i] = selm.area()
    # Build timeseries
    for t in range(num_time):
        # Integrate u*area and convert to Sv
        dpt.append(sum(u_selm[t,:]*area_selm)*1e-6)

    # Calculate time values
    time = arange(len(dpt))*days_per_output/365.

    print 'Plotting'
    clf()
    plot(time, dpt)
    xlabel('Years')
    ylabel('Drake Passage Transport (Sv)')
    grid(True)
    savefig(fig_dir + 'drakepsgtrans.png')

    print 'Saving results to log file'
    f = open(log_file, 'w')
    f.write('Drake Passage Transport (Sv):\n')
    for elm in dpt:
        f.write(str(elm) + '\n')
    f.close()
def zonal_ts_rcp_lon(lon0, lat_min, lat_max, save=False, fig_name=None):

    # File paths
    mesh_path = '/short/y99/kaa561/FESOM/mesh/meshB/'
    directory_beg = '/short/y99/kaa561/FESOM/highres_spinup/'
    directories = [
        '/short/y99/kaa561/FESOM/rcp45_M/', '/short/y99/kaa561/FESOM/rcp45_A/',
        '/short/y99/kaa561/FESOM/rcp85_M/', '/short/y99/kaa561/FESOM/rcp85_A/',
        '/short/y99/kaa561/FESOM/highres_spinup/'
    ]
    file_beg = 'annual_avg.oce.mean.1996.2005.nc'
    file_end = 'annual_avg.oce.mean.2091.2100.nc'
    # Titles for plotting
    expt_names = [
        'RCP 4.5 M', 'RCP 4.5 A', 'RCP 8.5 M', 'RCP 8.5 A', 'CONTROL'
    ]
    num_expts = len(directories)
    # Start and end years for each period
    beg_years = [1996, 2005]
    end_years = [2091, 2100]
    # Figure out what to write on the title about longitude
    if lon0 < 0:
        lon_string = str(-lon0) + r'$^{\circ}$W'
    else:
        lon_string = str(lon0) + r'$^{\circ}$E'

    print 'Building FESOM mesh'
    elm2D = fesom_grid(mesh_path)
    print 'Reading temperature and salinity data'
    id = Dataset(directory_beg + file_beg, 'r')
    temp_nodes_beg = id.variables['temp'][0, :]
    salt_nodes_beg = id.variables['salt'][0, :]
    id.close()
    n3d = size(temp_nodes_beg)
    # Get anomalies for each experiment
    temp_nodes_diff = zeros([num_expts, n3d])
    salt_nodes_diff = zeros([num_expts, n3d])
    for expt in range(num_expts):
        id = Dataset(directories[expt] + file_end, 'r')
        temp_nodes_diff[expt, :] = id.variables['temp'][0, :] - temp_nodes_beg
        salt_nodes_diff[expt, :] = id.variables['salt'][0, :] - salt_nodes_beg

    print 'Interpolating to ' + lon_string
    # Build arrays of SideElements making up zonal slices
    # Start with beginning
    print '...' + str(beg_years[0]) + '-' + str(beg_years[1])
    selements_temp_beg = fesom_sidegrid(elm2D, temp_nodes_beg, lon0, lat_max)
    selements_salt_beg = fesom_sidegrid(elm2D, salt_nodes_beg, lon0, lat_max)
    # Build array of quadrilateral patches for the plots, and data values
    # corresponding to each SideElement
    patches = []
    temp_beg = []
    for selm in selements_temp_beg:
        # Make patch
        coord = transpose(vstack((selm.y, selm.z)))
        patches.append(Polygon(coord, True, linewidth=0.))
        # Save data value
        temp_beg.append(selm.var)
    temp_beg = array(temp_beg)
    # Salinity has same patches but different values
    salt_beg = []
    for selm in selements_salt_beg:
        salt_beg.append(selm.var)
    salt_beg = array(salt_beg)
    # Repeat for anomalies for each experiment
    temp_diff = zeros([num_expts, len(patches)])
    salt_diff = zeros([num_expts, len(patches)])
    for expt in range(num_expts):
        print '...' + expt_names[expt]
        selements_temp_diff = fesom_sidegrid(elm2D, temp_nodes_diff[expt, :],
                                             lon0, lat_max)
        selements_salt_diff = fesom_sidegrid(elm2D, salt_nodes_diff[expt, :],
                                             lon0, lat_max)
        i = 0
        for selm in selements_temp_diff:
            temp_diff[expt, i] = selm.var
            i += 1
        i = 0
        for selm in selements_salt_diff:
            salt_diff[expt, i] = selm.var
            i += 1
    # Find bounds on each variable
    temp_min = amin(temp_beg)
    temp_max = amax(temp_beg)
    salt_min = amin(salt_beg)
    salt_max = amax(salt_beg)
    temp_max_diff = 2.0
    salt_max_diff = 0.5
    # Find deepest depth
    # Start with 0
    depth_min = 0
    # Modify with patches
    for selm in selements_temp_beg:
        depth_min = min(depth_min, amin(selm.z))
    # Round down to nearest 50 metres
    depth_min = floor(depth_min / 50) * 50

    print 'Plotting'
    fig = figure(figsize=(20, 16))
    # Temperature
    gs_temp = GridSpec(2, 3)
    gs_temp.update(left=0.11,
                   right=0.9,
                   bottom=0.51,
                   top=0.9,
                   wspace=0.05,
                   hspace=0.5)
    # Beginning
    ax = subplot(gs_temp[0, 0])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(temp_beg)
    img.set_edgecolor('face')
    img.set_clim(vmin=temp_min, vmax=temp_max)
    ax.add_collection(img)
    xlim([lat_min, lat_max])
    ylim([depth_min, 0])
    title(str(beg_years[0]) + '-' + str(beg_years[1]), fontsize=20)
    xlabel('Latitude', fontsize=16)
    ylabel('Depth (m)', fontsize=16)
    # Add a colorbar on the left
    cbaxes = fig.add_axes([0.02, 0.75, 0.015, 0.15])
    cbar = colorbar(img, cax=cbaxes, extend='both')
    # Anomalies for each experiment
    for expt in range(num_expts):
        if expt < 2:
            ax = subplot(gs_temp[0, expt + 1])
        else:
            ax = subplot(gs_temp[1, expt - 2])
        img = PatchCollection(patches, cmap='RdBu_r')
        img.set_array(temp_diff[expt, :])
        img.set_edgecolor('face')
        img.set_clim(vmin=-temp_max_diff, vmax=temp_max_diff)
        ax.add_collection(img)
        xlim([lat_min, lat_max])
        ylim([depth_min, 0])
        title(expt_names[expt], fontsize=20)
        ax.set_xticklabels([])
        ax.set_yticklabels([])
        if expt == 0:
            xlabel(str(end_years[0]) + '-' + str(end_years[1]) + ' anomalies',
                   fontsize=20)
            text(-69.5,
                 1200,
                 r'Temperature ($^{\circ}$C) at ' + lon_string,
                 fontsize=28)
        if expt == num_expts - 1:
            # Add a colorbar on the right
            cbaxes = fig.add_axes([0.92, 0.75, 0.015, 0.15])
            cbar = colorbar(img, cax=cbaxes, extend='both')
    # Salinity
    gs_salt = GridSpec(2, 3)
    gs_salt.update(left=0.11,
                   right=0.9,
                   bottom=0.02,
                   top=0.41,
                   wspace=0.05,
                   hspace=0.5)
    # Beginning
    ax = subplot(gs_salt[0, 0])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(salt_beg)
    img.set_edgecolor('face')
    img.set_clim(vmin=salt_min, vmax=salt_max)
    ax.add_collection(img)
    xlim([lat_min, lat_max])
    ylim([depth_min, 0])
    title(str(beg_years[0]) + '-' + str(beg_years[1]), fontsize=20)
    xlabel('Latitude', fontsize=16)
    ylabel('Depth (m)', fontsize=16)
    # Add a colorbar on the left
    cbaxes = fig.add_axes([0.02, 0.26, 0.015, 0.15])
    cbar = colorbar(img, cax=cbaxes, extend='both')
    # Anomalies for each experiment
    for expt in range(num_expts):
        if expt < 2:
            ax = subplot(gs_salt[0, expt + 1])
        else:
            ax = subplot(gs_salt[1, expt - 2])
        img = PatchCollection(patches, cmap='RdBu_r')
        img.set_array(salt_diff[expt, :])
        img.set_edgecolor('face')
        img.set_clim(vmin=-salt_max_diff, vmax=salt_max_diff)
        ax.add_collection(img)
        xlim([lat_min, lat_max])
        ylim([depth_min, 0])
        title(expt_names[expt], fontsize=20)
        ax.set_xticklabels([])
        ax.set_yticklabels([])
        if expt == 0:
            xlabel(str(end_years[0]) + '-' + str(end_years[1]) + ' anomalies',
                   fontsize=20)
            text(-68, 1200, 'Salinity (psu) at ' + lon_string, fontsize=28)
        if expt == num_expts - 1:
            # Add a colorbar on the right
            cbaxes = fig.add_axes([0.92, 0.26, 0.015, 0.15])
            cbar = colorbar(img, cax=cbaxes, extend='both')
    if save:
        fig.savefig(fig_name)
    else:
        fig.show()
Exemple #11
0
def amundsen_slices_before_after(rcp, model, save=False, fig_name=None):

    # File paths
    mesh_path = '/short/y99/kaa561/FESOM/mesh/meshB/'
    file_beg = '/short/y99/kaa561/FESOM/highres_spinup/sept.oce.1996.2005.nc'
    file_end = '/short/y99/kaa561/FESOM/rcp' + rcp + '_' + model + '/sept.oce.2091.2100.nc'
    # Spatial bounds and labels
    lon0 = -104
    lon_string = str(int(round(-lon0))) + r'$^{\circ}$W'
    lat_min = -75.1
    lat_max = -70.8
    lat_ticks = arange(-75, -71 + 1, 1)
    lat_labels = []
    for lat in lat_ticks:
        lat_labels.append(str(int(round(-lat))) + r'$^{\circ}$S')
    depth_min = -1200
    depth_max = 0
    depth_ticks = arange(-1000, 0 + 250, 250)
    depth_labels = []
    for depth in depth_ticks:
        depth_labels.append(str(int(round(-depth))))
    if model == 'M':
        model_title = 'MMM'
    elif model == 'A':
        model_title = 'ACCESS'
    # Bounds on colourbars
    temp_min = -1.8
    temp_max = 1.1
    temp_ticks = arange(-1.5, 1 + 0.5, 0.5)
    salt_min = 33.6
    salt_max = 34.6
    salt_ticks = arange(33.6, 34.6 + 0.2, 0.2)
    # Density contours to plot
    density_contours = [27.45, 27.55]
    # Parameters for regular grid interpolation (needed for density contours)
    num_lat = 500
    num_depth = 250

    print 'Building FESOM mesh'
    elm2D = fesom_grid(mesh_path)
    print 'Reading temperature and salinity data'
    id = Dataset(file_beg, 'r')
    temp_nodes_beg = id.variables['temp'][0, :]
    salt_nodes_beg = id.variables['salt'][0, :]
    id.close()
    id = Dataset(file_end, 'r')
    temp_nodes_end = id.variables['temp'][0, :]
    salt_nodes_end = id.variables['salt'][0, :]

    print 'Calculating density'
    density_nodes_beg = unesco(temp_nodes_beg, salt_nodes_beg,
                               zeros(shape(temp_nodes_beg))) - 1000
    density_nodes_end = unesco(temp_nodes_end, salt_nodes_end,
                               zeros(shape(temp_nodes_end))) - 1000

    print 'Interpolating to ' + str(lon0)
    # Build arrays of SideElements making up zonal slices
    # Start with beginning
    selements_temp_beg = fesom_sidegrid(elm2D, temp_nodes_beg, lon0, lat_max)
    selements_salt_beg = fesom_sidegrid(elm2D, salt_nodes_beg, lon0, lat_max)
    # Build array of quadrilateral patches for the plots, and data values
    # corresponding to each SideElement
    patches = []
    temp_beg = []
    for selm in selements_temp_beg:
        # Make patch
        coord = transpose(vstack((selm.y, selm.z)))
        patches.append(Polygon(coord, True, linewidth=0.))
        # Save data value
        temp_beg.append(selm.var)
    temp_beg = array(temp_beg)
    print 'Temp bounds, beginning: ' + str(amin(temp_beg)) + ' ' + str(
        amax(temp_beg))
    # Salinity has same patches but different values
    salt_beg = []
    for selm in selements_salt_beg:
        salt_beg.append(selm.var)
    salt_beg = array(salt_beg)
    print 'Salt bounds, beginning: ' + str(amin(salt_beg)) + ' ' + str(
        amax(salt_beg))
    # Repeat for end
    selements_temp_end = fesom_sidegrid(elm2D, temp_nodes_end, lon0, lat_max)
    selements_salt_end = fesom_sidegrid(elm2D, salt_nodes_end, lon0, lat_max)
    temp_end = []
    for selm in selements_temp_end:
        temp_end.append(selm.var)
    temp_end = array(temp_end)
    print 'Temp bounds, end: ' + str(amin(temp_end)) + ' ' + str(
        amax(temp_end))
    salt_end = []
    for selm in selements_salt_end:
        salt_end.append(selm.var)
    salt_end = array(salt_end)
    print 'Salt bounds, end: ' + str(amin(salt_end)) + ' ' + str(
        amax(salt_end))

    print 'Interpolating density to regular grid'
    lat_reg = linspace(lat_min, lat_max, num_lat)
    depth_reg = linspace(-depth_max, -depth_min, num_depth)
    density_reg_beg = zeros([num_depth, num_lat])
    density_reg_end = zeros([num_depth, num_lat])
    density_reg_beg[:, :] = NaN
    density_reg_end[:, :] = NaN
    # For each element, check if a point on the regular grid lies
    # within. If so, do barycentric interpolation to that point, at each
    # depth on the regular grid.
    for elm in elm2D:
        # Check if this element crosses lon0
        if amin(elm.lon) < lon0 and amax(elm.lon) > lon0:
            # Check if we are within the latitude bounds
            if amax(elm.lat) > lat_min and amin(elm.lat) < lat_max:
                # Find largest regular latitude value south of Element
                tmp = nonzero(lat_reg > amin(elm.lat))[0]
                if len(tmp) == 0:
                    # Element crosses the southern boundary
                    jS = 0
                else:
                    jS = tmp[0] - 1
                # Find smallest regular latitude north of Element
                tmp = nonzero(lat_reg > amax(elm.lat))[0]
                if len(tmp) == 0:
                    # Element crosses the northern boundary
                    jN = num_lat
                else:
                    jN = tmp[0]
                for j in range(jS + 1, jN):
                    # There is a chance that the regular gridpoint at j
                    # lies within this element
                    lat0 = lat_reg[j]
                    if in_triangle(elm, lon0, lat0):
                        # Yes it does
                        # Get area of entire triangle
                        area = triangle_area(elm.lon, elm.lat)
                        # Get area of each sub-triangle formed by (lon0, lat0)
                        area0 = triangle_area([lon0, elm.lon[1], elm.lon[2]],
                                              [lat0, elm.lat[1], elm.lat[2]])
                        area1 = triangle_area([lon0, elm.lon[0], elm.lon[2]],
                                              [lat0, elm.lat[0], elm.lat[2]])
                        area2 = triangle_area([lon0, elm.lon[0], elm.lon[1]],
                                              [lat0, elm.lat[0], elm.lat[1]])
                        # Find fractional area of each
                        cff = [area0 / area, area1 / area, area2 / area]
                        # Interpolate each depth value
                        for k in range(num_depth):
                            # Linear interpolation in the vertical for the
                            # value at each corner of the triangle
                            node_vals_beg = []
                            node_vals_end = []
                            for n in range(3):
                                id1, id2, coeff1, coeff2 = elm.nodes[
                                    n].find_depth(depth_reg[k])
                                if any(isnan(array([id1, id2, coeff1,
                                                    coeff2]))):
                                    # No ocean data here (seafloor or ice shelf)
                                    node_vals_beg.append(NaN)
                                    node_vals_end.append(NaN)
                                else:
                                    node_vals_beg.append(
                                        coeff1 * density_nodes_beg[id1] +
                                        coeff2 * density_nodes_beg[id2])
                                    node_vals_end.append(
                                        coeff1 * density_nodes_end[id1] +
                                        coeff2 * density_nodes_end[id2])
                            if any(isnan(node_vals_beg)):
                                pass
                            else:
                                # Barycentric interpolation for the value at
                                # lon0, lat0
                                density_reg_beg[k, j] = sum(
                                    array(cff) * array(node_vals_beg))
                                density_reg_end[k, j] = sum(
                                    array(cff) * array(node_vals_end))
    density_reg_beg = ma.masked_where(isnan(density_reg_beg), density_reg_beg)
    density_reg_end = ma.masked_where(isnan(density_reg_end), density_reg_end)
    depth_reg = -1 * depth_reg

    print 'Plotting'
    fig = figure(figsize=(16, 10))
    # Temperature
    gs_temp = GridSpec(1, 2)
    gs_temp.update(left=0.08,
                   right=0.9,
                   bottom=0.5,
                   top=0.88,
                   wspace=0.05,
                   hspace=0.5)
    # Beginning
    ax = subplot(gs_temp[0, 0])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(temp_beg)
    img.set_edgecolor('face')
    img.set_clim(vmin=temp_min, vmax=temp_max)
    ax.add_collection(img)
    # Overlay density contours on regular grid
    contour(lat_reg,
            depth_reg,
            density_reg_beg,
            levels=density_contours,
            colors='black')
    xlim([lat_min, lat_max])
    ylim([depth_min, depth_max])
    title(r'Temperature ($^{\circ}$C), 1996-2005', fontsize=24)
    ax.set_xticks(lat_ticks)
    ax.set_xticklabels([])
    ax.set_yticks(depth_ticks)
    ax.set_yticklabels(depth_labels, fontsize=16)
    ylabel('Depth (m)', fontsize=18)
    # End
    ax = subplot(gs_temp[0, 1])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(temp_end)
    img.set_edgecolor('face')
    img.set_clim(vmin=temp_min, vmax=temp_max)
    ax.add_collection(img)
    contour(lat_reg,
            depth_reg,
            density_reg_end,
            levels=density_contours,
            colors='black')
    xlim([lat_min, lat_max])
    ylim([depth_min, depth_max])
    title(r'Temperature ($^{\circ}$C), 2091-2100', fontsize=24)
    ax.set_xticks(lat_ticks)
    ax.set_xticklabels([])
    ax.set_yticks(depth_ticks)
    ax.set_yticklabels([])
    # Add a colorbar on the right
    cbaxes = fig.add_axes([0.92, 0.55, 0.02, 0.28])
    cbar = colorbar(img, cax=cbaxes, extend='both', ticks=temp_ticks)
    cbar.ax.tick_params(labelsize=16)
    # Salinity
    gs_salt = GridSpec(1, 2)
    gs_salt.update(left=0.08,
                   right=0.9,
                   bottom=0.07,
                   top=0.45,
                   wspace=0.05,
                   hspace=0.5)
    # Beginning
    ax = subplot(gs_salt[0, 0])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(salt_beg)
    img.set_edgecolor('face')
    img.set_clim(vmin=salt_min, vmax=salt_max)
    ax.add_collection(img)
    contour(lat_reg,
            depth_reg,
            density_reg_beg,
            levels=density_contours,
            colors='black')
    xlim([lat_min, lat_max])
    ylim([depth_min, depth_max])
    title('Salinity (psu), 1996-2005', fontsize=24)
    ax.set_xticks(lat_ticks)
    ax.set_xticklabels(lat_labels, fontsize=16)
    xlabel('Latitude', fontsize=18)
    ax.set_yticks(depth_ticks)
    ax.set_yticklabels(depth_labels, fontsize=16)
    ylabel('Depth (m)', fontsize=18)
    # End
    ax = subplot(gs_salt[0, 1])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(salt_end)
    img.set_edgecolor('face')
    img.set_clim(vmin=salt_min, vmax=salt_max)
    ax.add_collection(img)
    contour(lat_reg,
            depth_reg,
            density_reg_end,
            levels=density_contours,
            colors='black')
    xlim([lat_min, lat_max])
    ylim([depth_min, depth_max])
    title('Salinity (psu), 2091-2100', fontsize=24)
    ax.set_xticks(lat_ticks)
    ax.set_xticklabels(lat_labels, fontsize=16)
    xlabel('Latitude', fontsize=18)
    ax.set_yticks(lat_ticks)
    ax.set_yticklabels([])
    # Add a colorbar on the right
    cbaxes = fig.add_axes([0.92, 0.12, 0.02, 0.28])
    cbar = colorbar(img, cax=cbaxes, extend='both', ticks=salt_ticks)
    cbar.ax.tick_params(labelsize=16)
    # Main title
    suptitle('RCP ' + rcp[0] + '.' + rcp[1] + ' ' + model_title + ', ' +
             lon_string + ' (Amundsen Sea), September',
             fontsize=28)

    if save:
        fig.savefig(fig_name)
    else:
        fig.show()
def mip_drift_slices(roms_grid, roms_file, fesom_mesh_path_lr, fesom_file_lr,
                     fesom_mesh_path_hr, fesom_file_hr):

    # Paths to ECCO2 files with initial conditions for temp and salt
    ecco_temp_file = '/short/m68/kaa561/metroms_iceshelf/data/originals/ECCO2/THETA.1440x720x50.199201.nc'
    ecco_salt_file = '/short/m68/kaa561/metroms_iceshelf/data/originals/ECCO2/SALT.1440x720x50.199201.nc'
    # Longitude to interpolate to (OE)
    lon0 = 0
    # Bounds on plot
    lat_min = -73
    lat_max = -30
    depth_min = -6000
    depth_max = 0
    # ROMS grid parameters
    theta_s = 7.0
    theta_b = 2.0
    hc = 250
    N = 31
    # Bounds on colour scales for temperature and salinity
    temp_min = -2
    temp_max = 6
    salt_min = 33.9
    salt_max = 34.9
    # Contours to overlay
    temp_contour = 0.75
    salt_contour = 34.5
    # Parameters for FESOM regular grid interpolation (needed for contours)
    num_lat = 500
    num_depth = 250

    # Get longitude for the title
    if lon0 < 0:
        lon_string = str(int(round(-lon0))) + r'$^{\circ}$W'
    else:
        lon_string = str(int(round(lon0))) + r'$^{\circ}$E'

    print 'Processing ECCO2'
    id = Dataset(ecco_temp_file, 'r')
    # Read grid variables
    ecco_lat = id.variables['LATITUDE_T'][:]
    ecco_depth = -1 * id.variables['DEPTH_T'][:]
    if lon0 == 0:
        # Hard-coded lon0 = 0E: average between the first (0.125 E) and last
        # (359.875 E = -0.125 W) indices in the regular ECCO2 grid
        ecco_temp = 0.5 * (id.variables['THETA'][0, :, :, 0] +
                           id.variables['THETA'][0, :, :, -1])
        id.close()
        id = Dataset(ecco_salt_file, 'r')
        ecco_salt = 0.5 * (id.variables['SALT'][0, :, :, 0] +
                           id.variables['SALT'][0, :, :, -1])
        id.close()
    else:
        print 'lon0 is only coded for 0E at this time'
        #return

    print 'Processing ROMS'
    # Read grid variables we need
    id = Dataset(roms_grid, 'r')
    roms_lon_2d = id.variables['lon_rho'][:, :]
    roms_lat_2d = id.variables['lat_rho'][:, :]
    roms_h = id.variables['h'][:, :]
    roms_zice = id.variables['zice'][:, :]
    id.close()
    # Read temperature and salinity
    id = Dataset(roms_file, 'r')
    roms_temp_3d = id.variables['temp'][0, :, :, :]
    roms_salt_3d = id.variables['salt'][0, :, :, :]
    id.close()
    # Get a 3D array of z-coordinates; sc_r and Cs_r are unused in this script
    roms_z_3d, sc_r, Cs_r = calc_z(roms_h, roms_zice, theta_s, theta_b, hc, N)
    # Make sure we are in the range 0-360
    if lon0 < 0:
        lon0 += 360
    # Interpolate to lon0
    roms_temp, roms_z, roms_lat = interp_lon_roms(roms_temp_3d, roms_z_3d,
                                                  roms_lat_2d, roms_lon_2d,
                                                  lon0)
    roms_salt, roms_z, roms_lat = interp_lon_roms(roms_salt_3d, roms_z_3d,
                                                  roms_lat_2d, roms_lon_2d,
                                                  lon0)
    # Switch back to range -180-180
    if lon0 > 180:
        lon0 -= 360

    print 'Processing low-res FESOM'
    # Build regular elements
    elements_lr = fesom_grid(fesom_mesh_path_lr)
    # Read temperature and salinity
    id = Dataset(fesom_file_lr, 'r')
    fesom_temp_nodes_lr = id.variables['temp'][0, :]
    fesom_salt_nodes_lr = id.variables['salt'][0, :]
    id.close()
    # Make SideElements
    selements_temp_lr = fesom_sidegrid(elements_lr, fesom_temp_nodes_lr, lon0,
                                       lat_max)
    selements_salt_lr = fesom_sidegrid(elements_lr, fesom_salt_nodes_lr, lon0,
                                       lat_max)
    # Build an array of quadrilateral patches for the plot, and of data values
    # corresponding to each SideElement
    patches_lr = []
    fesom_temp_lr = []
    for selm in selements_temp_lr:
        # Make patch
        coord = transpose(vstack((selm.y, selm.z)))
        patches_lr.append(Polygon(coord, True, linewidth=0.))
        # Save data value
        fesom_temp_lr.append(selm.var)
    # Repeat for salinity
    fesom_salt_lr = []
    for selm in selements_salt_lr:
        fesom_salt_lr.append(selm.var)
    # Interpolate to regular grid so we can overlay contours
    lat_reg = linspace(lat_min, lat_max, num_lat)
    depth_reg = linspace(-depth_max, -depth_min, num_depth)
    temp_reg_lr = zeros([num_depth, num_lat])
    salt_reg_lr = zeros([num_depth, num_lat])
    temp_reg_lr[:, :] = NaN
    salt_reg_lr[:, :] = NaN
    # For each element, check if a point on the regular grid lies
    # within. If so, do barycentric interpolation to that point, at each
    # depth on the regular grid.
    for elm in elements_lr:
        # Check if this element crosses lon0
        if amin(elm.lon) < lon0 and amax(elm.lon) > lon0:
            # Check if we are within the latitude bounds
            if amax(elm.lat) > lat_min and amin(elm.lat) < lat_max:
                # Find largest regular latitude value south of Element
                tmp = nonzero(lat_reg > amin(elm.lat))[0]
                if len(tmp) == 0:
                    # Element crosses the southern boundary
                    jS = 0
                else:
                    jS = tmp[0] - 1
                # Find smallest regular latitude north of Element
                tmp = nonzero(lat_reg > amax(elm.lat))[0]
                if len(tmp) == 0:
                    # Element crosses the northern boundary
                    jN = num_lat
                else:
                    jN = tmp[0]
                for j in range(jS + 1, jN):
                    # There is a chance that the regular gridpoint at j
                    # lies within this element
                    lat0 = lat_reg[j]
                    if in_triangle(elm, lon0, lat0):
                        # Yes it does
                        # Get area of entire triangle
                        area = triangle_area(elm.lon, elm.lat)
                        # Get area of each sub-triangle formed by (lon0, lat0)
                        area0 = triangle_area([lon0, elm.lon[1], elm.lon[2]],
                                              [lat0, elm.lat[1], elm.lat[2]])
                        area1 = triangle_area([lon0, elm.lon[0], elm.lon[2]],
                                              [lat0, elm.lat[0], elm.lat[2]])
                        area2 = triangle_area([lon0, elm.lon[0], elm.lon[1]],
                                              [lat0, elm.lat[0], elm.lat[1]])
                        # Find fractional area of each
                        cff = [area0 / area, area1 / area, area2 / area]
                        # Interpolate each depth value
                        for k in range(num_depth):
                            # Linear interpolation in the vertical for the
                            # value at each corner of the triangle
                            node_vals_temp = []
                            node_vals_salt = []
                            for n in range(3):
                                id1, id2, coeff1, coeff2 = elm.nodes[
                                    n].find_depth(depth_reg[k])
                                if any(isnan(array([id1, id2, coeff1,
                                                    coeff2]))):
                                    # No ocean data here (seafloor or ice shelf)
                                    node_vals_temp.append(NaN)
                                    node_vals_salt.append(NaN)
                                else:
                                    node_vals_temp.append(
                                        coeff1 * fesom_temp_nodes_lr[id1] +
                                        coeff2 * fesom_temp_nodes_lr[id2])
                                    node_vals_salt.append(
                                        coeff1 * fesom_salt_nodes_lr[id1] +
                                        coeff2 * fesom_salt_nodes_lr[id2])
                            if any(isnan(node_vals_temp)):
                                pass
                            else:
                                # Barycentric interpolation for the value at
                                # lon0, lat0
                                temp_reg_lr[k, j] = sum(
                                    array(cff) * array(node_vals_temp))
                                salt_reg_lr[k, j] = sum(
                                    array(cff) * array(node_vals_salt))
    temp_reg_lr = ma.masked_where(isnan(temp_reg_lr), temp_reg_lr)
    salt_reg_lr = ma.masked_where(isnan(salt_reg_lr), salt_reg_lr)

    print 'Processing high-res FESOM'
    elements_hr = fesom_grid(fesom_mesh_path_hr)
    id = Dataset(fesom_file_hr, 'r')
    fesom_temp_nodes_hr = id.variables['temp'][0, :]
    fesom_salt_nodes_hr = id.variables['salt'][0, :]
    id.close()
    selements_temp_hr = fesom_sidegrid(elements_hr, fesom_temp_nodes_hr, lon0,
                                       lat_max)
    selements_salt_hr = fesom_sidegrid(elements_hr, fesom_salt_nodes_hr, lon0,
                                       lat_max)
    patches_hr = []
    fesom_temp_hr = []
    for selm in selements_temp_hr:
        coord = transpose(vstack((selm.y, selm.z)))
        patches_hr.append(Polygon(coord, True, linewidth=0.))
        fesom_temp_hr.append(selm.var)
    fesom_salt_hr = []
    for selm in selements_salt_hr:
        fesom_salt_hr.append(selm.var)
    lat_reg = linspace(lat_min, lat_max, num_lat)
    temp_reg_hr = zeros([num_depth, num_lat])
    salt_reg_hr = zeros([num_depth, num_lat])
    temp_reg_hr[:, :] = NaN
    salt_reg_hr[:, :] = NaN
    for elm in elements_hr:
        if amin(elm.lon) < lon0 and amax(elm.lon) > lon0:
            if amax(elm.lat) > lat_min and amin(elm.lat) < lat_max:
                tmp = nonzero(lat_reg > amin(elm.lat))[0]
                if len(tmp) == 0:
                    jS = 0
                else:
                    jS = tmp[0] - 1
                tmp = nonzero(lat_reg > amax(elm.lat))[0]
                if len(tmp) == 0:
                    jN = num_lat
                else:
                    jN = tmp[0]
                for j in range(jS + 1, jN):
                    lat0 = lat_reg[j]
                    if in_triangle(elm, lon0, lat0):
                        area = triangle_area(elm.lon, elm.lat)
                        area0 = triangle_area([lon0, elm.lon[1], elm.lon[2]],
                                              [lat0, elm.lat[1], elm.lat[2]])
                        area1 = triangle_area([lon0, elm.lon[0], elm.lon[2]],
                                              [lat0, elm.lat[0], elm.lat[2]])
                        area2 = triangle_area([lon0, elm.lon[0], elm.lon[1]],
                                              [lat0, elm.lat[0], elm.lat[1]])
                        cff = [area0 / area, area1 / area, area2 / area]
                        for k in range(num_depth):
                            node_vals_temp = []
                            node_vals_salt = []
                            for n in range(3):
                                id1, id2, coeff1, coeff2 = elm.nodes[
                                    n].find_depth(depth_reg[k])
                                if any(isnan(array([id1, id2, coeff1,
                                                    coeff2]))):
                                    node_vals_temp.append(NaN)
                                    node_vals_salt.append(NaN)
                                else:
                                    node_vals_temp.append(
                                        coeff1 * fesom_temp_nodes_hr[id1] +
                                        coeff2 * fesom_temp_nodes_hr[id2])
                                    node_vals_salt.append(
                                        coeff1 * fesom_salt_nodes_hr[id1] +
                                        coeff2 * fesom_salt_nodes_hr[id2])
                            if any(isnan(node_vals_temp)):
                                pass
                            else:
                                temp_reg_hr[k, j] = sum(
                                    array(cff) * array(node_vals_temp))
                                salt_reg_hr[k, j] = sum(
                                    array(cff) * array(node_vals_salt))
    temp_reg_hr = ma.masked_where(isnan(temp_reg_hr), temp_reg_hr)
    salt_reg_hr = ma.masked_where(isnan(salt_reg_hr), salt_reg_hr)

    depth_reg = -1 * depth_reg

    # Set up axis labels the way we want them
    lat_ticks = arange(lat_min + 3, lat_max + 10, 10)
    lat_labels = []
    for val in lat_ticks:
        lat_labels.append(str(int(round(-val))) + r'$^{\circ}$S')
    depth_ticks = range(depth_min + 1000, 0 + 1000, 1000)
    depth_labels = []
    for val in depth_ticks:
        depth_labels.append(str(int(round(-val))))

    print 'Plotting'
    fig = figure(figsize=(14, 24))
    # ECCO2
    gs1 = GridSpec(1, 2)
    gs1.update(left=0.1, right=0.95, bottom=0.7575, top=0.94, wspace=0.08)
    # Temperature
    ax = subplot(gs1[0, 0])
    pcolor(ecco_lat,
           ecco_depth,
           ecco_temp,
           vmin=temp_min,
           vmax=temp_max,
           cmap='jet')
    # Overlay contour
    contour(ecco_lat,
            ecco_depth,
            ecco_temp,
            levels=[temp_contour],
            color='black')
    title(r'Temperature ($^{\circ}$C)', fontsize=24)
    ylabel('Depth (m)', fontsize=18)
    xlim([lat_min, lat_max])
    ylim([depth_min, depth_max])
    ax.set_xticks(lat_ticks)
    ax.set_xticklabels(lat_labels, fontsize=16)
    ax.set_yticks(depth_ticks)
    ax.set_yticklabels(depth_labels, fontsize=16)
    text(-64,
         1000,
         'a) ECCO2 initial conditions at ' + lon_string + ', January 1992',
         fontsize=28)
    # Salinity
    ax = subplot(gs1[0, 1])
    pcolor(ecco_lat,
           ecco_depth,
           ecco_salt,
           vmin=salt_min,
           vmax=salt_max,
           cmap='jet')
    contour(ecco_lat,
            ecco_depth,
            ecco_salt,
            levels=[salt_contour],
            color='black')
    title('Salinity (psu)', fontsize=24)
    xlim([lat_min, lat_max])
    ylim([depth_min, depth_max])
    ax.set_xticks(lat_ticks)
    ax.set_xticklabels(lat_labels, fontsize=16)
    ax.set_yticks(depth_ticks)
    ax.set_yticklabels([])
    # MetROMS
    gs2 = GridSpec(1, 2)
    gs2.update(left=0.1, right=0.95, bottom=0.525, top=0.7075, wspace=0.08)
    # Temperature
    ax = subplot(gs2[0, 0])
    pcolor(roms_lat,
           roms_z,
           roms_temp,
           vmin=temp_min,
           vmax=temp_max,
           cmap='jet')
    contour(roms_lat, roms_z, roms_temp, levels=[temp_contour], color='black')
    ylabel('Depth (m)', fontsize=18)
    xlim([lat_min, lat_max])
    ylim([depth_min, depth_max])
    ax.set_xticks(lat_ticks)
    ax.set_xticklabels(lat_labels, fontsize=16)
    ax.set_yticks(depth_ticks)
    ax.set_yticklabels(depth_labels, fontsize=16)
    text(-49, 300, 'b) MetROMS, January 2016', fontsize=28)
    # Salinity
    ax = subplot(gs2[0, 1])
    pcolor(roms_lat,
           roms_z,
           roms_salt,
           vmin=salt_min,
           vmax=salt_max,
           cmap='jet')
    contour(roms_lat, roms_z, roms_salt, levels=[salt_contour], color='black')
    xlim([lat_min, lat_max])
    ylim([depth_min, depth_max])
    ax.set_xticks(lat_ticks)
    ax.set_xticklabels(lat_labels, fontsize=16)
    ax.set_yticks(depth_ticks)
    ax.set_yticklabels([])
    # FESOM low-res
    gs3 = GridSpec(1, 2)
    gs3.update(left=0.1, right=0.95, bottom=0.2925, top=0.475, wspace=0.08)
    # Temperature
    ax = subplot(gs3[0, 0])
    img = PatchCollection(patches_lr, cmap='jet')
    img.set_array(array(fesom_temp_lr))
    img.set_edgecolor('face')
    img.set_clim(vmin=temp_min, vmax=temp_max)
    ax.add_collection(img)
    # Overlay contour on regular grid
    contour(lat_reg,
            depth_reg,
            temp_reg_lr,
            levels=[temp_contour],
            color='black')
    ylabel('Depth (m)', fontsize=18)
    xlim([lat_min, lat_max])
    ylim([depth_min, depth_max])
    ax.set_xticks(lat_ticks)
    ax.set_xticklabels(lat_labels, fontsize=16)
    ax.set_yticks(depth_ticks)
    ax.set_yticklabels(depth_labels, fontsize=16)
    text(-53, 300, 'c) FESOM (low-res), January 2016', fontsize=28)
    # Salinity
    ax = subplot(gs3[0, 1])
    img = PatchCollection(patches_lr, cmap='jet')
    img.set_array(array(fesom_salt_lr))
    img.set_edgecolor('face')
    img.set_clim(vmin=salt_min, vmax=salt_max)
    ax.add_collection(img)
    contour(lat_reg,
            depth_reg,
            salt_reg_lr,
            levels=[salt_contour],
            color='black')
    xlim([lat_min, lat_max])
    ylim([depth_min, depth_max])
    ax.set_xticks(lat_ticks)
    ax.set_xticklabels(lat_labels, fontsize=16)
    ax.set_yticks(depth_ticks)
    ax.set_yticklabels([])
    # FESOM high-res
    gs4 = GridSpec(1, 2)
    gs4.update(left=0.1, right=0.95, bottom=0.06, top=0.2425, wspace=0.08)
    # Temperature
    ax = subplot(gs4[0, 0])
    img = PatchCollection(patches_hr, cmap='jet')
    img.set_array(array(fesom_temp_hr))
    img.set_edgecolor('face')
    img.set_clim(vmin=temp_min, vmax=temp_max)
    ax.add_collection(img)
    contour(lat_reg,
            depth_reg,
            temp_reg_hr,
            levels=[temp_contour],
            color='black')
    ylabel('Depth (m)', fontsize=18)
    xlim([lat_min, lat_max])
    ylim([depth_min, depth_max])
    ax.set_xticks(lat_ticks)
    ax.set_xticklabels(lat_labels, fontsize=16)
    ax.set_yticks(depth_ticks)
    ax.set_yticklabels(depth_labels, fontsize=16)
    text(-53, 300, 'd) FESOM (high-res), January 2016', fontsize=28)
    # Add a colorbar for temperature
    cbaxes = fig.add_axes([0.17, 0.015, 0.3, 0.015])
    cbar = colorbar(img,
                    orientation='horizontal',
                    cax=cbaxes,
                    extend='both',
                    ticks=arange(temp_min, temp_max + 2, 2))
    cbar.ax.tick_params(labelsize=16)
    # Salinity
    ax = subplot(gs4[0, 1])
    img = PatchCollection(patches_hr, cmap='jet')
    img.set_array(array(fesom_salt_hr))
    img.set_edgecolor('face')
    img.set_clim(vmin=salt_min, vmax=salt_max)
    ax.add_collection(img)
    contour(lat_reg,
            depth_reg,
            salt_reg_hr,
            levels=[salt_contour],
            color='black')
    xlim([lat_min, lat_max])
    ylim([depth_min, depth_max])
    ax.set_xticks(lat_ticks)
    ax.set_xticklabels(lat_labels, fontsize=16)
    ax.set_yticks(depth_ticks)
    ax.set_yticklabels([])
    # Add a colorbar for salinity
    cbaxes = fig.add_axes([0.6, 0.015, 0.3, 0.02])
    cbar = colorbar(img,
                    orientation='horizontal',
                    cax=cbaxes,
                    extend='both',
                    ticks=arange(salt_min + 0.1, salt_max + 0.1, 0.2))
    cbar.ax.tick_params(labelsize=16)
    fig.show()
    fig.savefig('ts_drift.png')
Exemple #13
0
def zonal_ts_before_after(lon0,
                          lat_min,
                          lat_max,
                          rcp,
                          model,
                          save=False,
                          fig_name=None,
                          season=None):

    # File paths
    mesh_path = '/short/y99/kaa561/FESOM/mesh/meshB/'
    if season is not None:
        file_beg = '/short/y99/kaa561/FESOM/highres_spinup/seasonal_climatology_oce_1996_2005.nc'
        file_end = '/short/y99/kaa561/FESOM/highres_spinup/seasonal_climatology_oce_2091_2100.nc'
    else:
        file_beg = '/short/y99/kaa561/FESOM/highres_spinup/annual_avg.oce.mean.1996.2005.nc'
        file_end = '/short/y99/kaa561/FESOM/rcp' + rcp + '_' + model + '/annual_avg.oce.mean.2091.2100.nc'
    # Figure out what to write on the title about longitude
    if lon0 < 0:
        lon_string = str(int(round(-lon0))) + r'$^{\circ}$W'
    else:
        lon_string = str(int(round(lon0))) + r'$^{\circ}$E'
    season_names = ['DJF', 'MAM', 'JJA', 'SON']
    if season is not None:
        season_string = ', ' + season_names[season]
    else:
        season_string = ''

    print 'Building FESOM mesh'
    elm2D = fesom_grid(mesh_path)
    print 'Reading temperature and salinity data'
    if season is not None:
        t = season
    else:
        t = 0
    id = Dataset(file_beg, 'r')
    temp_nodes_beg = id.variables['temp'][t, :]
    salt_nodes_beg = id.variables['salt'][t, :]
    id.close()
    id = Dataset(file_end, 'r')
    temp_nodes_end = id.variables['temp'][t, :]
    salt_nodes_end = id.variables['salt'][t, :]

    print 'Interpolating to ' + str(lon0)
    # Build arrays of SideElements making up zonal slices
    # Start with beginning
    selements_temp_beg = fesom_sidegrid(elm2D, temp_nodes_beg, lon0, lat_max)
    selements_salt_beg = fesom_sidegrid(elm2D, salt_nodes_beg, lon0, lat_max)
    # Build array of quadrilateral patches for the plots, and data values
    # corresponding to each SideElement
    patches = []
    temp_beg = []
    for selm in selements_temp_beg:
        # Make patch
        coord = transpose(vstack((selm.y, selm.z)))
        patches.append(Polygon(coord, True, linewidth=0.))
        # Save data value
        temp_beg.append(selm.var)
    temp_beg = array(temp_beg)
    # Salinity has same patches but different values
    salt_beg = []
    for selm in selements_salt_beg:
        salt_beg.append(selm.var)
    salt_beg = array(salt_beg)
    # Repeat for end
    selements_temp_end = fesom_sidegrid(elm2D, temp_nodes_end, lon0, lat_max)
    selements_salt_end = fesom_sidegrid(elm2D, salt_nodes_end, lon0, lat_max)
    temp_end = []
    for selm in selements_temp_end:
        temp_end.append(selm.var)
    temp_end = array(temp_end)
    salt_end = []
    for selm in selements_salt_end:
        salt_end.append(selm.var)
    salt_end = array(salt_end)
    # Find bounds on each variable
    temp_min = min(amin(temp_beg), amin(temp_end))
    temp_max = max(amax(temp_beg), amax(temp_end))
    salt_min = min(amin(salt_beg), amin(salt_end))
    salt_max = max(amax(salt_beg), amax(salt_end))
    # Find deepest depth
    # Start with 0
    depth_min = 0
    # Modify with patches
    for selm in selements_temp_beg:
        depth_min = min(depth_min, amin(selm.z))
    # Round down to nearest 50 metres
    depth_min = floor(depth_min / 50) * 50

    print 'Plotting'
    fig = figure(figsize=(16, 10))
    # Temperature
    gs_temp = GridSpec(1, 2)
    gs_temp.update(left=0.11,
                   right=0.9,
                   bottom=0.5,
                   top=0.9,
                   wspace=0.05,
                   hspace=0.5)
    # Beginning
    ax = subplot(gs_temp[0, 0])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(temp_beg)
    img.set_edgecolor('face')
    img.set_clim(vmin=temp_min, vmax=temp_max)
    ax.add_collection(img)
    xlim([lat_min, lat_max])
    ylim([depth_min, 0])
    title(r'Temperature ($^{\circ}$C), 1996-2005', fontsize=24)
    ax.set_xticklabels([])
    ylabel('Depth (m)', fontsize=18)
    # End
    ax = subplot(gs_temp[0, 1])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(temp_end)
    img.set_edgecolor('face')
    img.set_clim(vmin=temp_min, vmax=temp_max)
    ax.add_collection(img)
    xlim([lat_min, lat_max])
    ylim([depth_min, 0])
    title(r'Temperature ($^{\circ}$C), 2091-2100', fontsize=24)
    ax.set_xticklabels([])
    ax.set_yticklabels([])
    # Add a colorbar on the right
    cbaxes = fig.add_axes([0.92, 0.55, 0.02, 0.3])
    cbar = colorbar(img, cax=cbaxes, extend='both')
    cbar.ax.tick_params(labelsize=16)
    # Salinity
    gs_salt = GridSpec(1, 2)
    gs_salt.update(left=0.11,
                   right=0.9,
                   bottom=0.05,
                   top=0.45,
                   wspace=0.05,
                   hspace=0.5)
    # Beginning
    ax = subplot(gs_salt[0, 0])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(salt_beg)
    img.set_edgecolor('face')
    img.set_clim(vmin=salt_min, vmax=salt_max)
    ax.add_collection(img)
    xlim([lat_min, lat_max])
    ylim([depth_min, 0])
    title('Salinity (psu), 1996-2005', fontsize=24)
    xlabel('Latitude', fontsize=18)
    ylabel('Depth (m)', fontsize=18)
    # End
    ax = subplot(gs_salt[0, 1])
    img = PatchCollection(patches, cmap='jet')
    img.set_array(salt_end)
    img.set_edgecolor('face')
    img.set_clim(vmin=salt_min, vmax=salt_max)
    ax.add_collection(img)
    xlim([lat_min, lat_max])
    ylim([depth_min, 0])
    title('Salinity (psu), 2091-2100', fontsize=24)
    xlabel('Latitude', fontsize=18)
    ax.set_yticklabels([])
    # Add a colorbar on the right
    cbaxes = fig.add_axes([0.92, 0.1, 0.02, 0.3])
    cbar = colorbar(img, cax=cbaxes, extend='both')
    cbar.ax.tick_params(labelsize=16)
    # Main title
    suptitle('RCP ' + rcp[0] + '.' + rcp[1] + ' ' + model + ', ' + lon_string +
             season_string,
             fontsize=28)

    if save:
        fig.savefig(fig_name)
    else:
        fig.show()