Esempio n. 1
0
def make_timeseries_plot_2sided(time,
                                data1,
                                data2,
                                title,
                                units1,
                                units2,
                                monthly=True,
                                fig_name=None,
                                dpi=None):

    fig, ax1 = plt.subplots(figsize=(9, 6))
    ax1.plot_date(time, data1, '-', linewidth=1.5, color='blue')
    ax1.grid(True)
    if not monthly:
        monthly_ticks(ax1)
    ax1.set_ylabel(units1, color='blue', fontsize=16)
    ax1.tick_params(axis='y', labelcolor='blue')
    ax2 = ax1.twinx()
    ax2.plot_date(time, data2, '-', linewidth=1.5, color='red')
    ax2.get_yaxis().get_major_formatter().set_useOffset(False)
    ax2.set_ylabel(units2, color='red', fontsize=16)
    ax2.tick_params(axis='y', labelcolor='red')
    if np.amin(data1) < 0 and np.amax(data1) > 0 and np.amin(
            data2) < 0 and np.amax(data2) > 0:
        # Both timeseries cross 0. Line them up there.
        val1 = max(-np.amin(data1), np.amax(data1))
        val2 = max(-np.amin(data2), np.amax(data2))
        ax1.set_ylim([-val1, val1])
        ax2.set_ylim([-val2, val2])
        ax1.axhline(color='black')
    plt.title(title, fontsize=18)
    finished_plot(fig, fig_name=fig_name, dpi=dpi)
Esempio n. 2
0
def plot_timeseries_max(file_path,
                        var_name,
                        grid,
                        xmin=None,
                        xmax=None,
                        ymin=None,
                        ymax=None,
                        title='',
                        units='',
                        fig_name=None,
                        monthly=True):

    if not isinstance(grid, Grid):
        # This is the path to the NetCDF grid file, not a Grid object
        # Make a grid object from it
        grid = Grid(grid)

    if isinstance(file_path, str):
        # Just one file
        first_file = file_path
    elif isinstance(file_path, list):
        # More than one
        first_file = file_path[0]
    else:
        print 'Error (plot_timeseries_max): file_path must be a string or a list'
        sys.exit()
    # Calculate timeseries on the first file
    values = timeseries_max(first_file,
                            var_name,
                            grid,
                            xmin=xmin,
                            xmax=xmax,
                            ymin=ymin,
                            ymax=ymax)
    # Read time axis
    time = netcdf_time(first_file, monthly=monthly)
    if isinstance(file_path, list):
        # More files to read
        for file in file_path[1:]:
            values_tmp = timeseries_max(file,
                                        var_name,
                                        grid,
                                        xmin=xmin,
                                        xmax=xmax,
                                        ymin=ymin,
                                        ymax=ymax)
            time_tmp = netcdf_time(file, monthly=monthly)
            # Concatenate the arrays
            values = np.concatenate((values, values_tmp))
            time = np.concatenate((time, time_tmp))

    # Plot
    fig, ax = plt.subplots()
    ax.plot_date(time, values, '-', linewidth=1.5)
    ax.grid(True)
    yearly_ticks(ax)
    plt.title(title, fontsize=18)
    plt.ylabel(units, fontsize=16)
    finished_plot(fig, fig_name=fig_name)
Esempio n. 3
0
def plot_vel(u,
             v,
             grid,
             vel_option='avg',
             vmin=None,
             vmax=None,
             zoom_fris=False,
             xmin=None,
             xmax=None,
             ymin=None,
             ymax=None,
             date_string=None,
             fig_name=None):

    # Do the correct vertical transformation, and interpolate to the tracer grid
    speed, u_plot, v_plot = prepare_vel(u, v, grid, vel_option=vel_option)

    include_shelf = True
    if vel_option == 'avg':
        title_beg = 'Vertically averaged '
    elif vel_option == 'sfc':
        title_beg = 'Surface '
    elif vel_option == 'bottom':
        title_beg = 'Bottom '
    elif vel_option == 'ice':
        title_beg = 'Sea ice '
        include_shelf = False

    # Make the plot but don't finish it yet
    fig, ax = latlon_plot(speed,
                          grid,
                          ctype='vel',
                          include_shelf=include_shelf,
                          vmin=vmin,
                          vmax=vmax,
                          zoom_fris=zoom_fris,
                          xmin=xmin,
                          xmax=xmax,
                          date_string=date_string,
                          title=title_beg + 'velocity (m/s)',
                          return_fig=True)

    # Overlay circulation
    if zoom_fris:
        chunk = 6
    else:
        chunk = 10
    if vel_option == 'avg':
        scale = 0.8
    elif vel_option == 'sfc':
        scale = 1.5
    elif vel_option == 'bottom':
        scale = 1
    elif vel_option == 'ice':
        scale = 4
    overlay_vectors(ax, u_plot, v_plot, grid, chunk=chunk, scale=scale)

    finished_plot(fig, fig_name=fig_name)
Esempio n. 4
0
def ts_slice_plot (temp, salt, grid, lon0=None, lat0=None, hmin=None, hmax=None, zmin=None, zmax=None, tmin=None, tmax=None, smin=None, smax=None, date_string=None, fig_name=None):

    # Choose what the endpoints of the colourbars should do
    extend = [get_extend(vmin=tmin, vmax=tmax), get_extend(vmin=smin, vmax=smax)]
    # Build the temperature patches and get the bounds
    patches, temp_values, loc0, hmin, hmax, zmin, zmax, tmin_tmp, tmax_tmp, left, right, below, above = slice_patches(temp, grid, lon0=lon0, lat0=lat0, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, return_bdry=True)
    # Get the salinity values on the same patches, and their colour bounds
    salt_values, smin_tmp, smax_tmp = slice_values(salt, grid, left, right, below, above, hmin, hmax, zmin, zmax, lon0=lon0, lat0=lat0)

    # Update any colour bounds which aren't already set
    if tmin is None:
        tmin = tmin_tmp
    if tmax is None:
        tmax = tmax_tmp
    if smin is None:
        smin = smin_tmp
    if smax is None:
        smax = smax_tmp

    # Figure out orientation and format slice location
    if lon0 is not None:
        h_axis = 'lat'
        loc_string = lon_label(loc0, 3)
    elif lat0 is not None:
        h_axis = 'lon'
        loc_string = lat_label(loc0, 3)

    # Set panels
    fig, gs, cax_t, cax_s = set_panels('1x2C2')
    # Wrap some things up in lists for easier iteration
    values = [temp_values, salt_values]
    vmin = [tmin, smin]
    vmax = [tmax, smax]
    cax = [cax_t, cax_s]
    title = [r'Temperature ($^{\circ}$C)', 'Salinity (psu)']
    for i in range(2):
        ax = plt.subplot(gs[0,i])
        # Plot patches
        img = plot_slice_patches(ax, patches, values[i], hmin, hmax, zmin, zmax, vmin[i], vmax[i])
        # Nice axes
        slice_axes(ax, h_axis=h_axis)
        if i == 1:
            # Don't need depth labels a second time
            ax.set_yticklabels([])
            ax.set_ylabel('')
        # Add a colourbar and hide every second label so they're not squished
        cbar = plt.colorbar(img, cax=cax[i], extend=extend[i], orientation='horizontal')
        for label in cbar.ax.xaxis.get_ticklabels()[1::2]:
            label.set_visible(False)
        # Variable title
        plt.title(title[i], fontsize=18)
    if date_string is not None:
        # Add date to main title
        loc_string += ', ' + date_string
    # Main title
    plt.suptitle(loc_string, fontsize=20)
    finished_plot(fig, fig_name=fig_name)
Esempio n. 5
0
def plot_fris_massbalance(file_path, grid, fig_name=None, monthly=True):

    if not isinstance(grid, Grid):
        # This is the path to the NetCDF grid file, not a Grid object
        # Make a grid object from it
        grid = Grid(grid)

    if isinstance(file_path, str):
        # Just one file
        first_file = file_path
    elif isinstance(file_path, list):
        # More than one
        first_file = file_path[0]
    else:
        print 'Error (plot_fris_massbalance): file_path must be a string or a list'
        sys.exit()
    # Calculate timeseries on the first file
    melt, freeze = fris_melt(first_file, grid, mass_balance=True)
    # Read time axis
    time = netcdf_time(first_file, monthly=monthly)
    if isinstance(file_path, list):
        # More files to read
        for file in file_path[1:]:
            melt_tmp, freeze_tmp = fris_melt(file, grid, mass_balance=True)
            time_tmp = netcdf_time(file, monthly=monthly)
            # Concatenate the arrays
            melt = np.concatenate((melt, melt_tmp))
            freeze = np.concatenate((freeze, freeze_tmp))
            time = np.concatenate((time, time_tmp))

    # Plot
    fig, ax = plt.subplots()
    ax.plot_date(time, melt, '-', color='red', linewidth=1.5, label='Melting')
    ax.plot_date(time,
                 freeze,
                 '-',
                 color='blue',
                 linewidth=1.5,
                 label='Freezing')
    ax.plot_date(time,
                 melt + freeze,
                 '-',
                 color='black',
                 linewidth=1.5,
                 label='Total')
    ax.axhline(color='black')
    ax.grid(True)
    yearly_ticks(ax)
    plt.title('Basal mass balance of FRIS', fontsize=18)
    plt.ylabel('Gt/y', fontsize=16)
    ax.legend()
    finished_plot(fig, fig_name=fig_name)
Esempio n. 6
0
def timeseries_multi_plot(times,
                          datas,
                          labels,
                          colours,
                          title='',
                          units='',
                          monthly=True,
                          fig_name=None):

    # Figure out if time is a list or a single array that applies to all timeseries
    multi_time = isinstance(times, list)
    # Boolean which will tell us whether we need a line at 0
    crosses_zero = False

    fig, ax = plt.subplots(figsize=(11, 6))
    # Plot each line
    for i in range(len(datas)):
        if multi_time:
            time = times[i]
        else:
            time = times
        ax.plot_date(time,
                     datas[i],
                     '-',
                     color=colours[i],
                     label=labels[i],
                     linewidth=1.5)
        if (not crosses_zero) and (np.amin(datas[i]) < 0) and (np.amax(
                datas[i]) > 0):
            crosses_zero = True

    ax.grid(True)
    if crosses_zero:
        # Add a line at 0
        ax.axhline(color='black')
    if not monthly:
        monthly_ticks(ax)
    plt.title(title, fontsize=18)
    plt.ylabel(units, fontsize=16)
    # Move plot over to make room for legend
    box = ax.get_position()
    ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
    # Make legend
    ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

    finished_plot(fig, fig_name=fig_name)
Esempio n. 7
0
def make_timeseries_plot(time,
                         data,
                         title='',
                         units='',
                         monthly=True,
                         fig_name=None):

    fig, ax = plt.subplots()
    ax.plot_date(time, data, '-', linewidth=1.5)
    if np.amin(data) < 0 and np.amax(data) > 0:
        # Add a line at 0
        ax.axhline(color='black')
    ax.grid(True)
    if not monthly:
        monthly_ticks(ax)
    plt.title(title, fontsize=18)
    plt.ylabel(units, fontsize=16)
    finished_plot(fig, fig_name=fig_name)
Esempio n. 8
0
def slice_plot (data, grid, gtype='t', lon0=None, lat0=None, hmin=None, hmax=None, zmin=None, zmax=None, vmin=None, vmax=None, ctype='basic', title=None, date_string=None, fig_name=None):

    # Choose what the endpoints of the colourbar should do
    extend = get_extend(vmin=vmin, vmax=vmax)

    # Build the patches and get the bounds
    patches, values, loc0, hmin, hmax, zmin, zmax, vmin_tmp, vmax_tmp = slice_patches(data, grid, gtype=gtype, lon0=lon0, lat0=lat0, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax)  
    # Update any colour bounds which aren't already set
    if vmin is None:
        vmin = vmin_tmp
    if vmax is None:
        vmax = vmax_tmp
    # Set colour map
    cmap, vmin, vmax = set_colours(values, ctype=ctype, vmin=vmin, vmax=vmax)

    # Figure out orientation and format slice location
    if lon0 is not None:
        h_axis = 'lat'
        loc_string = lon_label(loc0, 3)
    elif lat0 is not None:
        h_axis = 'lon'
        loc_string = lat_label(loc0, 3)
    # Set up the title
    if title is None:
        title = ''
    title += ' at ' + loc_string    

    # Plot
    fig, ax = plt.subplots()
    # Add patches
    img = plot_slice_patches(ax, patches, values, hmin, hmax, zmin, zmax, vmin, vmax, cmap=cmap)
    # Make nice axis labels
    slice_axes(ax, h_axis=h_axis)
    # Add a colourbar
    plt.colorbar(img, extend=extend)
    # Add a title
    plt.title(title, fontsize=18)
    if date_string is not None:
        # Add the date in the bottom right corner
        plt.text(.99, .01, date_string, fontsize=14, ha='right', va='bottom', transform=fig.transFigure)
    finished_plot(fig, fig_name=fig_name)
Esempio n. 9
0
def plot_aice_minmax(file_path, grid, year, fig_name=None, monthly=True):

    if not isinstance(grid, Grid):
        # This is the path to the NetCDF grid file, not a Grid object
        # Make a grid object from it
        grid = Grid(grid)

    # Read sea ice area and the corresponding dates
    aice = mask_land_zice(read_netcdf(file_path, 'SIarea'),
                          grid,
                          time_dependent=True)
    time = netcdf_time(file_path, monthly=monthly)
    # Find the range of dates we care about
    t_start, t_end = select_year(time, year)
    # Trim the arrays to these dates
    aice = aice[t_start:t_end, :]
    time = time[t_start:t_end]
    # Find the indices of min and max sea ice area
    t_min, t_max = find_aice_min_max(aice, grid)
    # Wrap up in lists for easy iteration
    aice_minmax = [aice[t_min, :], aice[t_max, :]]
    time_minmax = [time[t_min], time[t_max]]

    # Plot
    fig, gs, cax = set_panels('1x2C1')
    for t in range(2):
        lon, lat, aice_plot = cell_boundaries(aice_minmax[t], grid)
        ax = plt.subplot(gs[0, t])
        shade_land_zice(ax, grid)
        img = ax.pcolormesh(lon, lat, aice_plot, vmin=0, vmax=1)
        latlon_axes(ax, lon, lat)
        if t == 1:
            # Don't need latitude labels a second time
            ax.set_yticklabels([])
        plt.title(parse_date(date=time_minmax[t]), fontsize=18)
    # Colourbar
    plt.colorbar(img, cax=cax, orientation='horizontal')
    # Main title above
    plt.suptitle('Min and max sea ice area', fontsize=22)
    finished_plot(fig, fig_name=fig_name)
Esempio n. 10
0
def make_timeseries_plot_2sided(time,
                                data1,
                                data2,
                                title,
                                units1,
                                units2,
                                monthly=True,
                                fig_name=None,
                                dpi=None):

    fig, ax1 = plt.subplots(figsize=(9, 6))
    ax1.plot_date(time, data1, '-', linewidth=1.5, color='blue')
    ax1.grid(True)
    if not monthly:
        monthly_ticks(ax1)
    ax1.set_ylabel(units1, color='blue', fontsize=16)
    ax1.tick_params(axis='y', labelcolor='blue')
    ax2 = ax1.twinx()
    ax2.plot_date(time, data2, '-', linewidth=1.5, color='red')
    ax2.get_yaxis().get_major_formatter().set_useOffset(False)
    ax2.set_ylabel(units2, color='red', fontsize=16)
    ax2.tick_params(axis='y', labelcolor='red')
    plt.title(title, fontsize=18)
    finished_plot(fig, fig_name=fig_name, dpi=dpi)
Esempio n. 11
0
def amundsen_rignot_comparison(file_path,
                               precomputed=False,
                               option='melting',
                               file_path_2=None,
                               sim_names=None,
                               fig_name=None):

    shelf_names = [
        'getz', 'dotson_crosson', 'thwaites', 'pig', 'cosgrove', 'abbot',
        'venable'
    ]
    shelf_titles = [
        'Getz', 'Dotson &\nCrosson', 'Thwaites', 'Pine Island', 'Cosgrove',
        'Abbot', 'Venable'
    ]
    num_shelves = len(shelf_names)

    if not precomputed:
        grid = Grid(file_path)

    second = file_path_2 is not None
    ensemble = second and isinstance(file_path_2, list)
    if ensemble:
        num_ens = len(file_path_2)
    if second and (sim_names is None or not isinstance(sim_names, list)
                   or len(sim_names) != 2):
        print 'Error (amundsen_rignot_comparison): must set sim_names as list of 2 simulation names if file_path_2 is set.'
        sys.exit()

    model_melt = []
    if second:
        model2_melt = []
    obs_melt = []
    obs_std = []
    for shelf in shelf_names:
        var_name = shelf + '_' + option
        if precomputed:
            model_melt.append(
                read_netcdf(file_path, var_name, time_average=True))
            if second:
                if ensemble:
                    for n in range(num_ens):
                        melt_tmp = read_netcdf(file_path_2[n],
                                               var_name,
                                               time_average=True)
                        if n == 0:
                            min_melt = melt_tmp
                            max_melt = melt_tmp
                        else:
                            min_melt = min(min_melt, melt_tmp)
                            max_melt = max(max_melt, melt_tmp)
                    model2_melt.append([min_melt, max_melt])
                else:
                    model2_melt.append(
                        read_netcdf(file_path_2, var_name, time_average=True))
        else:
            model_melt.append(
                timeseries_ismr(file_path,
                                grid,
                                shelf=shelf,
                                result=option,
                                time_average=True))
            if second:
                if ensemble:
                    for n in range(num_ens):
                        melt_tmp = timeseries_ismr(file_path_2[n],
                                                   grid,
                                                   shelf=shelf,
                                                   result=option,
                                                   time_average=True)
                        if n == 0:
                            min_melt = melt_tmp
                            max_melt = melt_tmp
                        else:
                            min_melt = min(min_melt, melt_tmp)
                            max_melt = max(max_melt, melt_tmp)
                    model2_melt.append([min_melt, max_melt])
                else:
                    model2_melt.append(
                        timeseries_ismr(file_path_2,
                                        grid,
                                        shelf=shelf,
                                        result=option,
                                        time_average=True))
        obs = rignot_melt[shelf]
        if option == 'massloss':
            obs_melt.append(obs[0])
            obs_std.append(obs[1])
        elif option == 'melting':
            obs_melt.append(obs[2])
            obs_std.append(obs[3])
        else:
            print 'Error (amundsen_rignot_comparison): invalid option ' + option
            sys.exit()

    if second and ensemble:
        # Convert from min/max to central value and difference, for plotting
        model2_melt0 = []
        model2_melt_diff = []
        for n in range(num_shelves):
            model2_melt0.append(0.5 * (model2_melt[n][0] + model2_melt[n][1]))
            model2_melt_diff.append(model2_melt0[n] - model2_melt[n][0])

    fig, ax = plt.subplots()
    if second:
        ax.plot(range(num_shelves),
                model_melt,
                'o',
                color='blue',
                label=sim_names[0])
        if ensemble:
            ax.errorbar(range(num_shelves),
                        model2_melt0,
                        yerr=model2_melt_diff,
                        fmt='none',
                        color='green',
                        capsize=4,
                        label=sim_names[1])
        else:
            ax.plot(range(num_shelves),
                    model2_melt,
                    'o',
                    color='green',
                    label=sim_names[1])
    else:
        if isinstance(sim_names, list):
            label = sim_names[0]
        elif isinstance(sim_names, str):
            label = sim_names
        else:
            label = 'MITgcm'
        ax.plot(range(num_shelves), model_melt, 'o', color='blue', label=label)
    ax.errorbar(range(num_shelves),
                obs_melt,
                yerr=obs_std,
                fmt='none',
                color='black',
                capsize=4,
                label='Observations')
    ax.legend()
    ax.grid(True)
    plt.xticks(range(num_shelves), shelf_titles, rotation='vertical')
    plt.subplots_adjust(bottom=0.2)
    if option == 'massloss':
        title = 'Basal mass loss'
        units = 'Gt/y'
    elif option == 'melting':
        title = 'Average melt rate'
        units = 'm/y'
    plt.title(title, fontsize=16)
    plt.ylabel(units, fontsize=12)
    finished_plot(fig, fig_name=fig_name)
Esempio n. 12
0
def ctd_cast_compare(loc,
                     hovmoller_file,
                     obs_file,
                     grid,
                     std=False,
                     ens_hovmoller_files=None,
                     month=2,
                     fig_name=None):

    from scipy.io import loadmat

    ensemble = ens_hovmoller_files is not None

    grid = choose_grid(grid, None)

    # Get bounds on region
    [xmin, xmax, ymin, ymax] = region_bounds[loc]
    # Read obs
    f = loadmat(obs_file)
    obs_lat = np.squeeze(f['Lat'])
    obs_lon = np.squeeze(f['Lon'])
    obs_depth = -1 * np.squeeze(f['P'])
    obs_temp = np.transpose(f['PT'])
    obs_salt = np.transpose(f['S'])
    # Convert NaNs into mask
    obs_temp = np.ma.masked_where(np.isnan(obs_temp), obs_temp)
    obs_salt = np.ma.masked_where(np.isnan(obs_salt), obs_salt)
    # Find casts within given region
    index = (obs_lon >= xmin) * (obs_lon <= xmax) * (obs_lat >=
                                                     ymin) * (obs_lat <= ymax)
    obs_temp = obs_temp[index, :]
    obs_salt = obs_salt[index, :]
    num_obs = obs_temp.shape[0]

    # Read model output
    model_temp = read_netcdf(hovmoller_file, loc + '_temp')
    model_salt = read_netcdf(hovmoller_file, loc + '_salt')
    if month != 0:
        # Select the month we want
        time = netcdf_time(hovmoller_file, monthly=False)
        index = [t.month == month for t in time]
        model_temp = model_temp[index, :]
        model_salt = model_salt[index, :]
    num_model = model_temp.shape[0]

    if ensemble:
        # Read model ensemble output, all in one
        ens_temp = None
        ens_salt = None
        ens_time = None
        for file_path in ens_hovmoller_files:
            temp_tmp = read_netcdf(file_path, loc + '_temp')
            salt_tmp = read_netcdf(file_path, loc + '_salt')
            time_tmp = netcdf_time(file_path, monthly=False)
            if ens_temp is None:
                ens_temp = temp_tmp
                ens_salt = salt_tmp
                ens_time = time_tmp
            else:
                ens_temp = np.concatenate((ens_temp, temp_tmp))
                ens_salt = np.concatenate((ens_salt, salt_tmp))
                ens_time = np.concatenate((ens_time, time_tmp))
        if month != 0:
            index = [t.month == month for t in ens_time]
            ens_temp = ens_temp[index, :]
            ens_salt = ens_salt[index, :]

    # Set panels
    fig, gs = set_panels('1x2C0')
    # Wrap things up in lists for easier iteration
    obs_data = [obs_temp, obs_salt]
    model_data = [model_temp, model_salt]
    if ensemble:
        ens_data = [ens_temp, ens_salt]
        all_data = [obs_data, model_data, ens_data]
        depths = [obs_depth, grid.z, grid.z]
        colours = ['black', 'red', 'blue']
        num_ranges = len(colours)
    titles = ['Temperature', 'Salinity']
    if std:
        titles = [t + ' std' for t in titles]
    units = [deg_string + 'C', 'psu']
    if std:
        vmin = [None, None]
        vmax = [None, None]
    else:
        vmin = [-2, 33]
        vmax = [2, 34.75]
    for i in range(2):
        ax = plt.subplot(gs[0, i])
        if ensemble:
            # Plot transparent ranges, with means on top
            # OR just plot standard deviation
            for n in range(num_ranges):
                if std:
                    ax.plot(np.std(all_data[n][i], axis=0),
                            depths[n],
                            color=colours[n],
                            linewidth=2)
                else:
                    ax.fill_betweenx(depths[n],
                                     np.amin(all_data[n][i], axis=0),
                                     x2=np.amax(all_data[n][i], axis=0),
                                     color=colours[n],
                                     alpha=0.3)
                    ax.plot(np.mean(all_data[n][i], axis=0),
                            depths[n],
                            color=colours[n],
                            linewidth=2)
        else:
            # Plot obs
            if std:
                ax.plot(np.std(obs_data[i], axis=0),
                        obs_depth,
                        color='black',
                        linewidth=2)
            else:
                # Plot individual lines
                for n in range(num_obs):
                    ax.plot(obs_data[i][n, :],
                            obs_depth,
                            color=(0.6, 0.6, 0.6),
                            linewidth=1)
                # Plot obs mean in thicker dashedblack
                ax.plot(np.mean(obs_data[i], axis=0),
                        obs_depth,
                        color='black',
                        linewidth=2,
                        linestyle='dashed')
            # Plot model years
            if std:
                ax.plot(np.std(model_data[i], axis=0),
                        grid.z,
                        color='blue',
                        linewidth=2)
            else:
                # Different colours for each year
                for n in range(num_model):
                    ax.plot(model_data[i][n, :], grid.z, linewidth=1)
                # Plot model mean in thicker black
                ax.plot(np.mean(model_data[i], axis=0),
                        grid.z,
                        color='black',
                        linewidth=2)
        ax.set_xlim([vmin[i], vmax[i]])
        ax.grid(True)
        plt.title(titles[i], fontsize=16)
        plt.xlabel(units[i], fontsize=14)
        if i == 0:
            plt.ylabel('Depth (m)', fontsize=14)
        else:
            ax.set_yticklabels([])
    if ensemble:
        plt.suptitle(loc + ': CTDs (black), ERA5 (red), PACE ensemble (blue)',
                     fontsize=20)
    else:
        if std:
            plt.suptitle(loc + ': model (blue) vs CTDs (black)', fontsize=20)
        else:
            plt.suptitle(loc + ': model (colours) vs CTDs (grey)', fontsize=20)
    finished_plot(fig, fig_name=fig_name)
Esempio n. 13
0
def hovmoller_ts_plot(temp,
                      salt,
                      time,
                      grid,
                      smooth=0,
                      split_year=None,
                      tmin=None,
                      tmax=None,
                      smin=None,
                      smax=None,
                      zmin=None,
                      zmax=None,
                      monthly=True,
                      t_contours=None,
                      s_contours=None,
                      title=None,
                      date_since_start=False,
                      start=0,
                      t0=None,
                      s0=None,
                      ctype='basic',
                      loc_string='',
                      fig_name=None,
                      figsize=(12, 7),
                      dpi=None,
                      return_fig=False,
                      ab_inside=False,
                      rasterized=False):

    # Set panels
    fig, gs, cax_t, cax_s = set_panels('2x1C2', figsize=figsize)
    if split_year is not None:
        if date_since_start:
            first_year = time[0].year - time[start].year
            last_year = time[-1].year - time[start].year
        else:
            first_year = time[0].year
            last_year = time[-1].year
        width1 = (split_year - first_year)
        width2 = (last_year + 1 - split_year)
        gs = plt.GridSpec(2, 2, width_ratios=[width1, width2])
        gs.update(left=0.08,
                  right=0.9,
                  bottom=0.1,
                  top=0.88,
                  hspace=0.2,
                  wspace=0.01)
        # Need to choose the correct colour bounds
        if any([zmin, zmax]):
            tmin_tmp, tmax_tmp = var_min_max_zt(temp,
                                                grid,
                                                zmin=zmin,
                                                zmax=zmax)
            smin_tmp, smax_tmp = var_min_max_zt(salt,
                                                grid,
                                                zmin=zmin,
                                                zmax=zmax)
            if tmin is None:
                tmin = tmin_tmp
            if tmax is None:
                tmax = tmax_tmp
            if smin is None:
                smin = smin_tmp
            if smax is None:
                smax = smax_tmp

    # Wrap things up in lists for easier iteration
    data = [temp, salt]
    vmin = [tmin, smin]
    vmax = [tmax, smax]
    val0 = [t0, s0]
    contours = [t_contours, s_contours]
    if ab_inside:
        titles = ['Temperature (' + deg_string + 'C)', 'Salinity (psu)']
        ab = ['a', 'b']
    else:
        titles = ['a) Temperature (' + deg_string + 'C)', 'b) Salinity (psu)']
    cax = [cax_t, cax_s]
    axs = []
    for i in range(2):
        ax = plt.subplot(gs[i, 0])
        # Make the plot
        img = hovmoller_plot(data[i],
                             time,
                             grid,
                             smooth=smooth,
                             ax=ax,
                             make_cbar=False,
                             vmin=vmin[i],
                             vmax=vmax[i],
                             zmin=zmin,
                             zmax=zmax,
                             monthly=monthly,
                             contours=contours[i],
                             ctype=ctype,
                             title=titles[i],
                             date_since_start=date_since_start,
                             start=start,
                             val0=val0[i],
                             end_t=split_year,
                             rasterized=rasterized)
        if ab_inside:
            plt.text(0.01,
                     0.98,
                     ab[i],
                     weight='bold',
                     ha='left',
                     va='top',
                     fontsize=16,
                     transform=ax.transAxes)
        # Add a colourbar
        extend = get_extend(vmin=vmin[i], vmax=vmax[i])
        cbar = plt.colorbar(img, cax=cax[i], extend=extend)
        reduce_cbar_labels(cbar)
        if i == 0:
            # Remove x-tick labels from top plot
            ax.set_xticklabels([])
        else:
            ax.set_xlabel('Year', fontsize=14)
            ax.set_ylabel('')
        axs.append(ax)
        if split_year is not None:
            # Now make another plot beside
            ax2 = plt.subplot(gs[i, 1])
            img = hovmoller_plot(data[i],
                                 time,
                                 grid,
                                 smooth=smooth,
                                 ax=ax2,
                                 make_cbar=False,
                                 vmin=vmin[i],
                                 vmax=vmax[i],
                                 zmin=zmin,
                                 zmax=zmax,
                                 monthly=monthly,
                                 contours=contours[i],
                                 ctype=ctype,
                                 title='',
                                 date_since_start=date_since_start,
                                 start=start,
                                 val0=val0[i],
                                 start_t=split_year,
                                 rasterized=rasterized)
            ax2.set_yticklabels([])
            ax2.set_ylabel('')
            if i == 0:
                ax2.set_xticklabels([])
            axs.append(ax2)
    if title is None:
        title = loc_string
    plt.suptitle(title, fontsize=22)
    if return_fig:
        return fig, axs
    else:
        finished_plot(fig, fig_name=fig_name, dpi=dpi)
Esempio n. 14
0
def ts_distribution_plot(file_path,
                         region='all',
                         grid=None,
                         time_index=None,
                         t_start=None,
                         t_end=None,
                         time_average=False,
                         second_file_path=None,
                         tmin=None,
                         tmax=None,
                         smin=None,
                         smax=None,
                         num_bins=1000,
                         date_string=None,
                         figsize=(8, 6),
                         fig_name=None):

    # Build the grid if needed
    grid = choose_grid(grid, file_path)
    # Make sure we'll end up with a single record in time
    check_single_time(time_index, time_average)
    # Determine what to write about the date
    date_string = check_date_string(date_string, file_path, time_index)

    # Quick inner function to read data (THETA or SALT)
    def read_data(var_name):
        # First choose the right file
        if second_file_path is not None:
            file_path_use = find_variable(file_path, second_file_path)
        else:
            file_path_use = file_path
        data = read_netcdf(file_path_use,
                           var_name,
                           time_index=time_index,
                           t_start=t_start,
                           t_end=t_end,
                           time_average=time_average)
        return data

    # Call this function for each variable
    temp = read_data('THETA')
    salt = read_data('SALT')

    if region == 'all':
        mask = grid.hfac > 0
    elif region == 'cavities':
        mask = grid.ice_mask
    else:
        mask = grid.get_region_mask(region)

    # Make the bins
    volume, temp_centres, salt_centres, temp_edges, salt_edges = ts_binning(
        temp, salt, grid, mask, num_bins=num_bins)

    # Find the volume bounds for plotting
    min_vol = np.log(np.amin(volume))
    max_vol = np.log(np.amax(volume))
    # Calculate the surface freezing point for plotting
    tfreeze_sfc = tfreeze(salt_centres, 0)
    # Choose the plotting bounds if not set
    if tmin is None:
        tmin = temp_bins[0]
    if tmax is None:
        tmax = temp_bins[-1]
    if smin is None:
        smin = salt_bins[0]
    if smax is None:
        smax = salt_bins[-1]
    # Construct the title
    title = 'Water masses'
    if region == 'all':
        pass
    elif region == 'cavities':
        title += ' in ice shelf cavities'
    elif region.endswith('cavity'):
        title += ' in ' + region_names[region[:region.index('_cavity')]]
    else:
        title += ' in ' + region_names[region]
    if date_string != '':
        title += ', ' + date_string

    # Plot
    fig, ax = plt.subplots(figsize=figsize)
    # Use a log scale for visibility
    img = plt.pcolor(salt_centres,
                     temp_centres,
                     np.log(volume),
                     vmin=min_vol,
                     vmax=max_vol)
    # Add the surface freezing point
    plt.plot(salt_centres,
             tfreeze_sfc,
             color='black',
             linestyle='dashed',
             linewidth=2)
    ax.grid(True)
    ax.set_xlim([smin, smax])
    ax.set_ylim([tmin, tmax])
    plt.xlabel('Salinity (psu)')
    plt.ylabel('Temperature (' + deg_string + 'C)')
    plt.colorbar(img)
    plt.text(.9,
             .6,
             'log of volume',
             ha='center',
             rotation=-90,
             transform=fig.transFigure)
    plt.title(title)
    finished_plot(fig, fig_name=fig_name)
Esempio n. 15
0
def timeseries_multi_plot(times,
                          datas,
                          labels,
                          colours,
                          linestyles=None,
                          alphas=None,
                          title='',
                          units='',
                          monthly=True,
                          fig_name=None,
                          dpi=None,
                          legend_in_centre=False,
                          legend_outside=True,
                          dates=True,
                          thick_last=False,
                          thick_first=False,
                          first_on_top=False,
                          vline=None,
                          return_fig=False,
                          year_ticks=None):

    # Figure out if time is a list or a single array that applies to all timeseries
    multi_time = isinstance(times, list)
    # Booleans which will tell us whether we need a line at 0 or 100
    negative = False
    positive = False
    lt_100 = False
    gt_100 = False
    for data in datas:
        if np.amin(data) < 0:
            negative = True
        if np.amax(data) > 0:
            positive = True
        if np.amin(data) < 100:
            lt_100 = True
        if np.amax(data) > 100:
            gt_100 = True
    crosses_zero = negative and positive
    crosses_100 = lt_100 and gt_100 and units[0] == '%'
    if multi_time:
        start_time = times[0][0]
        end_time = start_time
        for time in times:
            if time[-1] > end_time:
                end_time = time[-1]
    else:
        start_time = times[0]
        end_time = times[-1]

    plot_legend = labels is not None
    if labels is None:
        labels = [None for i in range(len(datas))]

    if linestyles is None:
        linestyles = ['solid' for n in range(len(labels))]
    if alphas is None:
        alphas = [1 for n in range(len(labels))]

    if legend_outside:
        figsize = (11, 6)
    else:
        figsize = (8, 6)
    fig, ax = plt.subplots(figsize=figsize)
    # Plot each line
    for i in range(len(datas)):
        if multi_time:
            time = times[i]
        else:
            time = times
        if (thick_first and i == 0) or (thick_last and i == len(datas) - 1):
            linewidth = 2
        else:
            linewidth = 1
        if first_on_top and i == 0:
            if dates:
                ax.plot_date(time,
                             datas[i],
                             '-',
                             color=colours[i],
                             label=labels[i],
                             linewidth=linewidth,
                             linestyle=linestyles[i],
                             alpha=alphas[i],
                             zorder=len(datas))
            else:
                ax.plot(time,
                        datas[i],
                        '-',
                        color=colours[i],
                        label=labels[i],
                        linewidth=linewidth,
                        linestyle=linestyles[i],
                        alpha=alphas[i],
                        zorder=len(datas))
        else:
            if dates:
                ax.plot_date(time,
                             datas[i],
                             '-',
                             color=colours[i],
                             label=labels[i],
                             linewidth=linewidth,
                             linestyle=linestyles[i],
                             alpha=alphas[i])
            else:
                ax.plot(time,
                        datas[i],
                        '-',
                        color=colours[i],
                        label=labels[i],
                        linewidth=linewidth,
                        linestyle=linestyles[i],
                        alpha=alphas[i])
        ax.set_xlim(start_time, end_time)

    ax.grid(linestyle='dotted')
    if crosses_zero:
        # Add a line at 0
        ax.axhline(color='black', linestyle='dashed')
    if crosses_100:
        # Add a line at 100%
        ax.axhline(100, color='black', linestyle='dashed')
    if vline is not None:
        if dates:
            vline = datetime.date(vline, 1, 1)
        ax.axvline(vline, color='black', linestyle='dashed')
    if not monthly:
        monthly_ticks(ax)
    if year_ticks is not None:
        if dates:
            year_ticks = [datetime.date(y, 1, 1) for y in year_ticks]
        ax.set_xticks(year_ticks)
    plt.title(title, fontsize=18)
    plt.ylabel(units, fontsize=16)
    if not dates:
        plt.xlabel('Years', fontsize=16)
    if plot_legend:
        if legend_outside:
            # Move plot over to make room for legend
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
            # Make legend
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
        elif legend_in_centre:
            ax.legend(loc='center')
        else:
            ax.legend(loc='best')
    if return_fig:
        return fig, ax
    else:
        finished_plot(fig, fig_name=fig_name, dpi=dpi)
Esempio n. 16
0
def latlon_plot(data,
                grid,
                gtype='t',
                include_shelf=True,
                ctype='basic',
                vmin=None,
                vmax=None,
                zoom_fris=False,
                xmin=None,
                xmax=None,
                ymin=None,
                ymax=None,
                date_string=None,
                title=None,
                return_fig=False,
                fig_name=None,
                change_points=None):

    # Choose what the endpoints of the colourbar should do
    extend = get_extend(vmin=vmin, vmax=vmax)

    # If we're zooming, we need to choose the correct colour bounds
    if zoom_fris or any([xmin, xmax, ymin, ymax]):
        vmin_tmp, vmax_tmp = var_min_max(data,
                                         grid,
                                         zoom_fris=zoom_fris,
                                         xmin=xmin,
                                         xmax=xmax,
                                         ymin=ymin,
                                         ymax=ymax,
                                         gtype=gtype)
        # Don't override manually set bounds
        if vmin is None:
            vmin = vmin_tmp
        if vmax is None:
            vmax = vmax_tmp
    # Get colourmap
    cmap, vmin, vmax = set_colours(data,
                                   ctype=ctype,
                                   vmin=vmin,
                                   vmax=vmax,
                                   change_points=change_points)

    # Prepare quadrilateral patches
    lon, lat, data_plot = cell_boundaries(data, grid, gtype=gtype)

    fig, ax = plt.subplots()
    if include_shelf:
        # Shade land in grey
        shade_land(ax, grid, gtype=gtype)
    else:
        # Shade land and ice shelves in grey
        shade_land_zice(ax, grid, gtype=gtype)
    # Plot the data
    img = ax.pcolormesh(lon, lat, data_plot, cmap=cmap, vmin=vmin, vmax=vmax)
    if include_shelf:
        # Contour ice shelf front
        contour_iceshelf_front(ax, grid)
    # Add a colourbar
    plt.colorbar(img, extend=extend)
    # Make nice axes
    latlon_axes(ax,
                lon,
                lat,
                zoom_fris=zoom_fris,
                xmin=xmin,
                xmax=xmax,
                ymin=ymin,
                ymax=ymax)
    if date_string is not None:
        # Add the date in the bottom right corner
        plt.text(.99,
                 .01,
                 date_string,
                 fontsize=14,
                 ha='right',
                 va='bottom',
                 transform=fig.transFigure)
    if title is not None:
        # Add a title
        plt.title(title, fontsize=18)

    if return_fig:
        return fig, ax
    else:
        finished_plot(fig, fig_name=fig_name)
Esempio n. 17
0
def timeseries_multi_plot(times,
                          datas,
                          labels,
                          colours,
                          title='',
                          units='',
                          monthly=True,
                          fig_name=None,
                          dpi=None,
                          legend_in_centre=False,
                          dates=True):

    # Figure out if time is a list or a single array that applies to all timeseries
    multi_time = isinstance(times, list)
    # Boolean which will tell us whether we need a line at 0
    negative = False
    positive = False
    for data in datas:
        if np.amin(data) < 0:
            negative = True
        if np.amax(data) > 0:
            positive = True
    crosses_zero = negative and positive
    if not dates:
        if multi_time:
            start_time = times[0][0]
            end_time = start_time
            for time in times:
                end_time = max(end_time, time[-1])
        else:
            start_time = times[0]
            end_time = times[-1]

    if legend_in_centre:
        figsize = (8, 6)
    else:
        figsize = (11, 6)
    fig, ax = plt.subplots(figsize=figsize)
    # Plot each line
    for i in range(len(datas)):
        if multi_time:
            time = times[i]
        else:
            time = times
        if dates:
            ax.plot_date(time,
                         datas[i],
                         '-',
                         color=colours[i],
                         label=labels[i],
                         linewidth=1.5)
        else:
            ax.plot(time,
                    datas[i],
                    '-',
                    color=colours[i],
                    label=labels[i],
                    linewidth=1.5)
            ax.set_xlim(start_time, end_time)

    ax.grid(True)
    if crosses_zero:
        # Add a line at 0
        ax.axhline(color='black')
    if not monthly:
        monthly_ticks(ax)
    plt.title(title, fontsize=18)
    plt.ylabel(units, fontsize=16)
    if legend_in_centre:
        # Make legend
        ax.legend(loc='center')
    else:
        # Move plot over to make room for legend
        box = ax.get_position()
        ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
        # Make legend
        ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

    finished_plot(fig, fig_name=fig_name, dpi=dpi)