Пример #1
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)
Пример #2
0
def read_and_trim_diff(file_1, file_2, var_name):

    time_1 = netcdf_time(file_1, monthly=False)
    time_2 = netcdf_time(file_2, monthly=False)
    data_1 = read_netcdf(file_1, var_name)
    data_2 = read_netcdf(file_2, var_name)
    time, data_diff = trim_and_diff(time_1, time_2, data_1, data_2)
    return time, data_diff
Пример #3
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)
Пример #4
0
def read_plot_hovmoller(var_name,
                        hovmoller_file,
                        grid,
                        zmin=None,
                        zmax=None,
                        vmin=None,
                        vmax=None,
                        contours=None,
                        monthly=True,
                        fig_name=None,
                        figsize=(14, 5)):

    data = read_netcdf(hovmoller_file, var_name)
    # Set monthly=False so we don't back up an extra month (because precomputed)
    time = netcdf_time(hovmoller_file, monthly=False)
    title, units = read_title_units(hovmoller_file, var_name)

    grid = choose_grid(grid, None)

    # Make the plot
    hovmoller_plot(data,
                   time,
                   grid,
                   vmin=vmin,
                   vmax=vmax,
                   zmin=zmin,
                   zmax=zmax,
                   monthly=monthly,
                   contours=contours,
                   title=title,
                   fig_name=fig_name,
                   figsize=figsize)
Пример #5
0
def select_common_time (output_files_1, output_files_2, option='last_year', monthly=True, check_match=True):

    if not monthly and option == 'last_year':
        print 'Error (select_common_time): need monthly output to correctly select the last year.'
        sys.exit()

    # Concatenate the time arrays from all files
    time_1 = calc_timeseries(output_files_1, option='time')
    time_2 = calc_timeseries(output_files_2, option='time')
    # Find the last time index in the shortest simulation
    time_index = min(time_1.size, time_2.size) - 1
    file_path_1, time_index_1 = find_time_index(output_files_1, time_index)
    file_path_2, time_index_2 = find_time_index(output_files_2, time_index)
    if check_match:
        # Make sure we got this right
        if netcdf_time(file_path_1, monthly=monthly)[time_index_1] != netcdf_time(file_path_2, monthly=monthly)[time_index_2]:
            print 'Error (select_common_time): something went wrong when matching time indices between the two files.'
            sys.exit()
    if option == 'last_year':
        # Add 1 to get the upper bound on the time range we care about
        t_end_1 = time_index_1 + 1
        t_end_2 = time_index_2 + 1
        # Find the index 12 before that
        t_start_1 = t_end_1 - 12
        t_start_2 = t_end_2 - 12
        # Make sure it's still contained within one file
        if t_start_1 < 0 or t_start_2 < 0:
            print "Error (select_common_time): option last_year doesn't work if that year isn't contained within one file, for both simulations."
            sys.exit()
        # Set the other options
        time_index_1 = None
        time_index_2 = None
        time_average = True
    elif option == 'last_month':
        # Set the other options
        t_start_1 = None
        t_start_2 = None
        t_end_1 = None
        t_end_2 = None
        time_average = False
    else:
        print 'Error (select_common_time): invalid option ' + option
        sys.exit()
    return file_path_1, file_path_2, time_index_1, time_index_2, t_start_1, t_start_2, t_end_1, t_end_2, time_average
Пример #6
0
def read_plot_timeseries(var,
                         file_path,
                         precomputed=False,
                         grid=None,
                         lon0=None,
                         lat0=None,
                         fig_name=None,
                         monthly=True,
                         legend_in_centre=False,
                         dpi=None):

    # Set parameters (only care about title and units)
    title, units = set_parameters(var)[2:4]

    if precomputed:
        # Read the time array; don't need to back up one month
        time = netcdf_time(file_path, monthly=False)

    if var.endswith('mass_balance'):
        if precomputed:
            # Read the fields from the timeseries file
            shelf = var[:var.index('_mass_balance')]
            melt = read_netcdf(file_path, shelf + '_total_melt')
            freeze = read_netcdf(file_path, shelf + '_total_freeze')
        else:
            # Calculate the timeseries from the MITgcm file(s)
            time, melt, freeze = calc_special_timeseries(var,
                                                         file_path,
                                                         grid=grid,
                                                         monthly=monthly)
        timeseries_multi_plot(time, [melt, freeze, melt + freeze],
                              ['Melting', 'Freezing', 'Net'],
                              ['red', 'blue', 'black'],
                              title=title,
                              units=units,
                              monthly=monthly,
                              fig_name=fig_name,
                              dpi=dpi,
                              legend_in_centre=legend_in_centre)
    else:
        if precomputed:
            data = read_netcdf(file_path, var)
        else:
            time, data = calc_special_timeseries(var,
                                                 file_path,
                                                 grid=grid,
                                                 lon0=lon0,
                                                 lat0=lat0,
                                                 monthly=monthly)
        make_timeseries_plot(time,
                             data,
                             title=title,
                             units=units,
                             monthly=monthly,
                             fig_name=fig_name,
                             dpi=dpi)
Пример #7
0
def plot_geometry_timeseries(output_dir='./',
                             fig_name_1=None,
                             fig_name_2=None):

    from postprocess import segment_file_paths

    file_paths = segment_file_paths(output_dir)

    # Get the grid from the first one
    old_grid = Grid(file_paths[0])

    # Set up timeseries arrays
    time = []
    ground = []
    unground = []
    thin = []
    thick = []

    # Loop over the rest of the timeseries
    for file_path in file_paths[1:]:
        print 'Processing ' + file_path
        # Save time index from the beginning of the run
        time.append(netcdf_time(file_path)[0])
        # Calculate geometry changes
        new_grid = Grid(file_path)
        ground.append(
            np.count_nonzero((old_grid.bathy != 0) * (new_grid.bathy == 0)))
        unground.append(
            np.count_nonzero((old_grid.bathy == 0) * (new_grid.bathy != 0)))
        ddraft = np.ma.masked_where(
            old_grid.draft == 0,
            np.ma.masked_where(new_grid.draft == 0,
                               new_grid.draft - old_grid.draft))
        thin.append(np.amin(ddraft))
        thick.append(np.amax(ddraft))
        old_grid = new_grid
    time = np.array(time)
    ground = np.array(ground)
    unground = np.array(unground)
    thin = -1 * np.array(thin)
    thick = np.array(thick)

    # Plot
    timeseries_multi_plot(time, [ground, unground],
                          ['# Grounded', '# Ungrounded'], ['blue', 'red'],
                          title='Changes in ocean cells',
                          fig_name=fig_name_1)
    timeseries_multi_plot(time, [thin, thick],
                          ['Maximum thinning', 'Maximum thickening'],
                          ['red', 'blue'],
                          title='Changes in ice shelf draft',
                          fig_name=fig_name_2)
Пример #8
0
def read_plot_hovmoller_ts(hovmoller_file,
                           loc,
                           grid,
                           smooth=0,
                           zmin=None,
                           zmax=None,
                           tmin=None,
                           tmax=None,
                           smin=None,
                           smax=None,
                           t_contours=None,
                           s_contours=None,
                           date_since_start=False,
                           ctype='basic',
                           t0=None,
                           s0=None,
                           title=None,
                           fig_name=None,
                           monthly=True,
                           figsize=(12, 7),
                           dpi=None,
                           return_fig=False):

    grid = choose_grid(grid, None)
    temp = read_netcdf(hovmoller_file, loc + '_temp')
    salt = read_netcdf(hovmoller_file, loc + '_salt')
    time = netcdf_time(hovmoller_file, monthly=False)
    loc_string = region_names[loc]
    return hovmoller_ts_plot(temp,
                             salt,
                             time,
                             grid,
                             smooth=smooth,
                             tmin=tmin,
                             tmax=tmax,
                             smin=smin,
                             smax=smax,
                             zmin=zmin,
                             zmax=zmax,
                             monthly=monthly,
                             t_contours=t_contours,
                             s_contours=s_contours,
                             loc_string=loc_string,
                             title=title,
                             date_since_start=date_since_start,
                             ctype=ctype,
                             t0=t0,
                             s0=s0,
                             figsize=figsize,
                             dpi=dpi,
                             return_fig=return_fig,
                             fig_name=fig_name)
Пример #9
0
def plot_seaice_annual (file_path, grid_path='../grid/', fig_dir='.', monthly=True):

    fig_dir = real_dir(fig_dir)

    grid = Grid(grid_path)

    time = netcdf_time(file_path, monthly=monthly)
    first_year = time[0].year
    if time[0].month > 2:
        first_year += 1
    last_year = time[-1].year
    if time[-1].month < 8:
        last_year -= 1
    for year in range(first_year, last_year+1):
        plot_aice_minmax(file_path, year, grid=grid, fig_name=fig_dir+'aice_minmax_'+str(year)+'.png')
Пример #10
0
def calc_ice_prod (file_path, out_file, monthly=True):

    # Build the grid from the file
    grid = Grid(file_path)

    # Add up all the terms to get sea ice production at each time index
    ice_prod = read_netcdf(file_path, 'SIdHbOCN') + read_netcdf(file_path, 'SIdHbATC') + read_netcdf(file_path, 'SIdHbATO') + read_netcdf(file_path, 'SIdHbFLO')
    # Also need time
    time = netcdf_time(file_path, monthly=monthly)

    # Set negative values to 0
    ice_prod = np.maximum(ice_prod, 0)

    # Write a new file
    ncfile = NCfile(out_file, grid, 'xyt')
    ncfile.add_time(time)
    ncfile.add_variable('ice_prod', ice_prod, 'xyt', long_name='Net sea ice production', units='m/s')
    ncfile.close()
Пример #11
0
def read_plot_hovmoller_ts(hovmoller_file,
                           loc,
                           grid,
                           zmin=None,
                           zmax=None,
                           tmin=None,
                           tmax=None,
                           smin=None,
                           smax=None,
                           t_contours=None,
                           s_contours=None,
                           fig_name=None,
                           monthly=True,
                           figsize=(12, 7),
                           dpi=None):

    grid = choose_grid(grid, None)
    temp = read_netcdf(hovmoller_file, loc + '_temp')
    salt = read_netcdf(hovmoller_file, loc + '_salt')
    time = netcdf_time(hovmoller_file, monthly=False)
    if loc == 'PIB':
        loc_string = 'Pine Island Bay '
    elif loc == 'Dot':
        loc_string = 'Dotson front '
    hovmoller_ts_plot(temp,
                      salt,
                      time,
                      grid,
                      tmin=tmin,
                      tmax=tmax,
                      smin=smin,
                      smax=smax,
                      zmin=zmin,
                      zmax=zmax,
                      monthly=monthly,
                      t_contours=t_contours,
                      s_contours=s_contours,
                      loc_string=loc_string,
                      fig_name=fig_name,
                      figsize=figsize,
                      dpi=dpi)
Пример #12
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)
Пример #13
0
def set_update_time (id, mit_file, monthly=True):
    # Read the time array from the MITgcm file, and its units
    time, time_units = netcdf_time(mit_file, return_units=True, monthly=monthly)
    if isinstance(id, nc.Dataset):
        # File is being updated
        # Update the units to match the old time array
        time_units = id.variables['time'].units
        # Also figure out how many time indices are in the file so far
        num_time = id.variables['time'].size
        # Convert to numeric values
        time = nc.date2num(time, time_units)
        # Append to file
        id.variables['time'][num_time:] = time
        return num_time
    elif isinstance(id, NCfile):
        # File is new
        # Add the time variable to the file
        id.add_time(time, units=time_units)
        return 0
    else:
        print 'Error (set_update_time): unknown id type'
        sys.exit()
Пример #14
0
def plot_seaice_annual(file_path,
                       grid_path='../input/grid.glob.nc',
                       fig_dir='.',
                       monthly=True):

    if not fig_dir.endswith('/'):
        fig_dir += '/'

    grid = Grid(grid_path)

    time = netcdf_time(file_path, monthly=monthly)
    first_year = time[0].year
    if time[0].month > 2:
        first_year += 1
    last_year = time[-1].year
    if time[-1].month < 8:
        last_year -= 1
    for year in range(first_year, last_year + 1):
        plot_aice_minmax(file_path,
                         grid,
                         year,
                         fig_name=fig_dir + 'aice_minmax_' + str(year) +
                         '.png')
Пример #15
0
def read_plot_timeseries_multi(var_names,
                               file_path,
                               diff=False,
                               precomputed=False,
                               grid=None,
                               lon0=None,
                               lat0=None,
                               fig_name=None,
                               monthly=True,
                               legend_in_centre=False,
                               dpi=None,
                               colours=None,
                               smooth=0,
                               annual_average=False):

    if diff and (not isinstance(file_path, list) or len(file_path) != 2):
        print 'Error (read_plot_timeseries_multi): must pass a list of 2 file paths when diff=True.'
        sys.exit()

    if precomputed:
        # Read time arrays
        if diff:
            time_1 = netcdf_time(file_path[0], monthly=False)
            time_2 = netcdf_time(file_path[1], monthly=False)
            time = trim_and_diff(time_1, time_2, time_1, time_2)[0]
        else:
            time = netcdf_time(file_path, monthly=False)

    # Set up the colours
    if colours is None:
        colours = default_colours(len(var_names))

    data = []
    labels = []
    units = None
    if annual_average:
        time_orig = np.copy(time)
    # Loop over variables
    for var in var_names:
        if var.endswith('mass_balance'):
            print 'Error (read_plot_timeseries_multi): ' + var + ' is already a multi-plot by itself.'
            sys.exit()
        title, units_tmp = set_parameters(var)[2:4]
        labels.append(title)
        if units is None:
            units = units_tmp
        elif units != units_tmp:
            print 'Error (read_plot_timeseries_multi): units do not match for all timeseries variables'
            sys.exit()
        if precomputed:
            if diff:
                data_1 = read_netcdf(file_path[0], var)
                data_2 = read_netcdf(file_path[1], var)
                data_tmp = trim_and_diff(time_1, time_2, data_1, data_2)[1]
            else:
                data_tmp = read_netcdf(file_path, var)
        else:
            if diff:
                time, data_tmp = calc_special_timeseries_diff(var,
                                                              file_path[0],
                                                              file_path[1],
                                                              grid=grid,
                                                              lon0=lon0,
                                                              lat0=lat0,
                                                              monthly=monthly)
            else:
                time, data_tmp = calc_special_timeseries(var,
                                                         file_path,
                                                         grid=grid,
                                                         lon0=lon0,
                                                         lat0=lat0,
                                                         monthly=monthly)
        if annual_average:
            time, data_tmp = calc_annual_averages(time_orig, data_tmp)
        data.append(data_tmp)
    for n in range(len(data)):
        data_tmp, time_tmp = moving_average(data[n], smooth, time=time)
        data[n] = data_tmp
    time = time_tmp
    title, labels = trim_titles(labels)
    if diff:
        title = 'Change in ' + title[0].lower() + title[1:]
    timeseries_multi_plot(time,
                          data,
                          labels,
                          colours,
                          title=title,
                          units=units,
                          monthly=monthly,
                          fig_name=fig_name,
                          dpi=dpi,
                          legend_in_centre=legend_in_centre)
Пример #16
0
def read_plot_timeseries_diff(var,
                              file_path_1,
                              file_path_2,
                              precomputed=False,
                              grid=None,
                              lon0=None,
                              lat0=None,
                              fig_name=None,
                              monthly=True):

    # Set parameters (only care about title and units)
    title, units = set_parameters(var)[2:4]
    # Edit the title to show it's a difference plot
    title = 'Change in ' + title[0].lower() + title[1:]

    if precomputed:
        # Read the time arrays
        time_1 = netcdf_time(file_path_1, monthly=False)
        time_2 = netcdf_time(file_path_2, monthly=False)

    # Inner function to read a timeseries from both files and calculate the differences, trimming if needed. Only useful if precomputed=True.
    def read_and_trim(var_name):
        data_1 = read_netcdf(file_path_1, var_name)
        data_2 = read_netcdf(file_path_2, var_name)
        time, data_diff = trim_and_diff(time_1, time_2, data_1, data_2)
        return time, data_diff

    if var.endswith('mass_balance'):
        if precomputed:
            shelf = var[:var.index('_mass_balance')]
            time, melt_diff = read_and_trim(shelf + '_total_melt')
            freeze_diff = read_and_trim(shelf + '_total_freeze')[1]
        else:
            # Calculate the difference timeseries
            time, melt_diff, freeze_diff = calc_special_timeseries_diff(
                var, file_path_1, file_path_2, grid=grid, monthly=monthly)
        timeseries_multi_plot(
            time, [melt_diff, freeze_diff, melt_diff + freeze_diff], [
                'Change in melting\n(>0)', 'Change in freezing\n(<0)',
                'Change in net'
            ], ['red', 'blue', 'black'],
            title=title,
            units=units,
            monthly=monthly,
            fig_name=fig_name)
    else:
        if precomputed:
            time, data_diff = read_and_trim(var)
        else:
            time, data_diff = calc_special_timeseries_diff(var,
                                                           file_path_1,
                                                           file_path_2,
                                                           grid=grid,
                                                           lon0=lon0,
                                                           lat0=lat0,
                                                           monthly=monthly)
        make_timeseries_plot(time,
                             data_diff,
                             title=title,
                             units=units,
                             monthly=monthly,
                             fig_name=fig_name)
Пример #17
0
def calc_timeseries (file_path, option=None, grid=None, gtype='t', var_name=None, shelves='fris', mass_balance=False, result='massloss', xmin=None, xmax=None, ymin=None, ymax=None, threshold=None, lon0=None, lat0=None, tmin=None, tmax=None, smin=None, smax=None, shelf_option='full', point0=None, point1=None, direction='N', monthly=True):

    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 (calc_timeseries): file_path must be a string or a list'
        sys.exit()

    if option not in ['time', 'ismr', 'wed_gyre_trans', 'watermass', 'volume', 'transport_transect'] and var_name is None:
        print 'Error (calc_timeseries): must specify var_name'
        sys.exit()
    if option == 'point_vavg' and (lon0 is None or lat0 is None):
        print 'Error (calc_timeseries): must specify lon0 and lat0'
        sys.exit()
    if option == 'area_threshold' and threshold is None:
        print 'Error (calc_timeseries): must specify threshold'
        sys.exit()
    if option == 'transport_transect' and (point0 is None or point1 is None):
        print 'Error (calc_timeseries): must specify point0 and point1'
        sys.exit()

    # Build the grid if needed
    if option != 'time':
        grid = choose_grid(grid, first_file)

    if option == 'avg_sws_shelf':
        # Choose the right mask
        if shelf_option == 'full':
            shelf_mask = grid.sws_shelf_mask
        elif shelf_option == 'inner':
            shelf_mask = grid.sws_shelf_mask_inner
        elif shelf_option == 'outer':
            shelf_mask = grid.sws_shelf_mask_outer
        else:
            print 'Error (calc_timeseries): invalid shelf_option ' + shelf_option
            sys.exit()
            

    # Calculate timeseries on the first file
    if option == 'ismr':
        if mass_balance:
            melt, freeze = timeseries_ismr(first_file, grid, shelves=shelves, mass_balance=mass_balance, result=result)
        else:
            values = timeseries_ismr(first_file, grid, shelves=shelves, mass_balance=mass_balance, result=result)
    elif option == 'max':
        values = timeseries_max(first_file, var_name, grid, gtype=gtype, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
    elif option == 'avg_sfc':
        values = timeseries_avg_sfc(first_file, var_name, grid, gtype=gtype)
    elif option == 'int_sfc':
        values = timeseries_int_sfc(first_file, var_name, grid, gtype=gtype)
    elif option == 'area_threshold':
        values = timeseries_area_threshold(first_file, var_name, threshold, grid, gtype=gtype)
    elif option == 'avg_fris':
        values = timeseries_avg_3d(first_file, var_name, grid, gtype=gtype, mask=grid.fris_mask)
    elif option == 'avg_sws_shelf':
        values = timeseries_avg_3d(first_file, var_name, grid, gtype=gtype, mask=shelf_mask)
    elif option == 'avg_domain':
        values = timeseries_avg_3d(first_file, var_name, grid, gtype=gtype)
    elif option == 'point_vavg':
        values = timeseries_point_vavg(first_file, var_name, lon0, lat0, grid, gtype=gtype)
    elif option == 'wed_gyre_trans':
        values = timeseries_wed_gyre(first_file, grid)
    elif option == 'watermass':
        values = timeseries_watermass_volume(first_file, grid, tmin=tmin, tmax=tmax, smin=smin, smax=smax)
    elif option == 'volume':
        values = timeseries_domain_volume(first_file, grid)
    elif option == 'transport_transect':
        values = timeseries_transport_transect(first_file, grid, point0, point1, direction=direction)
    elif option != 'time':
        print 'Error (calc_timeseries): invalid option ' + option
        sys.exit()
    # 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:]:
            if option == 'ismr':
                if mass_balance:
                    melt_tmp, freeze_tmp = timeseries_ismr(file, grid, shelves=shelves, mass_balance=mass_balance, result=result)
                else:
                    values_tmp = timeseries_ismr(file, grid, shelves=shelves, mass_balance=mass_balance, result=result)
            elif option == 'max':
                values_tmp = timeseries_max(file, var_name, grid, gtype=gtype, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
            elif option == 'avg_sfc':
                values_tmp = timeseries_avg_sfc(file, var_name, grid, gtype=gtype)
            elif option == 'int_sfc':
                values_tmp = timeseries_int_sfc(file, var_name, grid, gtype=gtype)
            elif option == 'area_threshold':
                values_tmp = timeseries_area_threshold(file, var_name, threshold, grid, gtype=gtype)
            elif option == 'avg_fris':
                values_tmp = timeseries_avg_3d(file, var_name, grid, gtype=gtype, mask=grid.fris_mask)
            elif option == 'avg_sws_shelf':
                values_tmp = timeseries_avg_3d(file, var_name, grid, gtype=gtype, mask=shelf_mask)
            elif option == 'avg_domain':
                values_tmp = timeseries_avg_3d(file, var_name, grid, gtype=gtype)
            elif option == 'point_vavg':
                values_tmp = timeseries_point_vavg(file, var_name, lon0, lat0, grid, gtype=gtype)
            elif option == 'wed_gyre_trans':
                values_tmp = timeseries_wed_gyre(file, grid)
            elif option == 'watermass':
                values_tmp = timeseries_watermass_volume(file, grid, tmin=tmin, tmax=tmax, smin=smin, smax=smax)
            elif option == 'volume':
                values_tmp = timeseries_domain_volume(file, grid)
            elif option == 'transport_transect':
                values_tmp = timeseries_transport_transect(file, grid, point0, point1, direction=direction)
            time_tmp = netcdf_time(file, monthly=monthly)
            # Concatenate the arrays
            if option == 'ismr' and mass_balance:
                melt = np.concatenate((melt, melt_tmp))
                freeze = np.concatenate((freeze, freeze_tmp))
            elif option != 'time':
                values = np.concatenate((values, values_tmp))
            time = np.concatenate((time, time_tmp))

    if option == 'ismr' and mass_balance:
        return time, melt, freeze
    elif option == 'time':
        return time
    else:
        return time, values
Пример #18
0
def process_era5 (in_dir, out_dir, year, six_hourly=True, first_year=False, last_year=False, prec=32):

    in_dir = real_dir(in_dir)
    out_dir = real_dir(out_dir)

    if year == 1979 and not first_year:
        print 'Warning (process_era): last we checked, 1979 was the first year of ERA5. Unless this has changed, you need to set first_year=True.'
    if year == 2018 and not last_year:
        print 'Warning (process_era): last we checked, 2018 was the last year of ERA5. Unless this has changed, you need to set last_year=True.'

    # Construct file paths for input and output files
    in_head = in_dir + 'era5_'
    var_in = ['msl', 't2m', 'd2m', 'u10', 'v10', 'tp', 'ssrd', 'strd', 'e']
    if six_hourly:
        accum_flag = '_2'
    in_tail = '_' + str(year) + '.nc'
    out_head = out_dir + 'ERA5_'
    var_out = ['apressure', 'atemp', 'aqh', 'uwind', 'vwind', 'precip', 'swdown', 'lwdown', 'evap']
    out_tail = '_' + str(year)

    # Northermost latitude to keep
    lat0 = -30
    # Length of ERA5 time interval in seconds
    dt = 3600.

    # Read the grid from the first file
    first_file = in_head + var_in[0] + in_tail
    lon = read_netcdf(first_file, 'longitude')
    lat = read_netcdf(first_file, 'latitude')
    # Find the index of the last latitude we don't care about (remember that latitude goes from north to south in ERA files!)
    j_bound = np.nonzero(lat < lat0)[0][0] - 2
    # Trim and flip latitude
    lat = lat[:j_bound:-1]
    # Also read the first time index for the starting date
    start_date = netcdf_time(first_file, monthly=False)[0]

    if first_year:
        # Print grid information to the reader
        print '\n'
        print 'For var in ' + str(var_out) + ', make these changes in input/data.exf:\n'
        print 'varstartdate1 = ' + start_date.strftime('%Y%m%d')
        if six_hourly:
            print 'varperiod = ' + str(6*dt)
        else:
            print 'varperiod = ' + str(dt)
        print 'varfile = ' + 'ERA5_var'
        print 'var_lon0 = ' + str(lon[0])
        print 'var_lon_inc = ' + str(lon[1]-lon[0])
        print 'var_lat0 = ' + str(lat[0])
        print 'var_lat_inc = ' + str(lat.size-1) + '*' + str(lat[1]-lat[0])
        print 'var_nlon = ' + str(lon.size)
        print 'var_nlat = ' + str(lat.size)
        print '\n'

    # Loop over variables
    for i in range(len(var_in)):
        
        in_file = in_head + var_in[i] + in_tail
        print 'Reading ' + in_file
        data = read_netcdf(in_file, var_in[i])
        
        print 'Processing'
        # Trim and flip over latitude
        data = data[:,:j_bound:-1,:]
        
        if var_in[i] == 'msl':
            # Save pressure for later conversions
            press = np.copy(data)

        elif var_in[i] == 't2m':
            # Convert from Kelvin to Celsius
            data -= temp_C2K

        elif var_in[i] == 'd2m':
            # Calculate specific humidity from dew point temperature and pressure
            # Start with vapour pressure
            e = es0*np.exp(Lv/Rv*(1/temp_C2K - 1/data))
            data = sh_coeff*e/(press - (1-sh_coeff)*e)
            
        elif var_in[i] in ['tp', 'ssrd', 'strd', 'e']:
            # Accumulated variables
            # This is more complicated
            
            if six_hourly:
                # Need to read data from the following hour to interpolate to this hour. This was downloaded into separate files.
                in_file_2 = in_head + var_in[i] + accum_flag + in_tail
                print 'Reading ' + in_file_2
                data_2 = read_netcdf(in_file_2, var_in[i])
                data_2 = data_2[:,:j_bound:-1,:]
            # not six_hourly will be dealt with after the first_year check
            
            if first_year:
                # The first 7 hours of the accumulated variables are missing during the first year of ERA5. Fill this missing period with data from the next available time indices.
                if six_hourly:
                    # The first file is missing two indices (hours 0 and 6)
                    data = np.concatenate((data[:2,:], data), axis=0)
                    # The second file is missing one index (hour 1)
                    data_2 = np.concatenate((data_2[:1,:], data_2), axis=0)
                else:
                    # The first file is missing 7 indices (hours 0 to 6)
                    data = np.concatenate((data[:7,:], data), axis=0)
                    
            if not six_hourly:
                # Now get data from the following hour. Just shift one timestep ahead.
                # First need data from the first hour of next year
                if last_year:
                    # There is no such data; just copy the last hour of this year
                    data_next = data[-1,:]
                else:
                    in_file_2 = in_head + var_in[i] + '_' + str(year+1) + '.nc'
                    data_next = read_netcdf(in_file_2, var_in[i], time_index=0)
                    data_next = data_next[:j_bound:-1,:]  
                data_2 = np.concatenate((data[1:,:], np.expand_dims(data_next,0)), axis=0)
                
            # Now we can interpolate to the given hour: just the mean of either side
            data = 0.5*(data + data_2)
            # Convert from integrals to time-averages
            data /= dt
            if var_in[i] in ['ssrd', 'strd', 'e']:
                # Swap sign on fluxes
                data *= -1

        out_file = out_head + var_out[i] + out_tail
        write_binary(data, out_file, prec=prec)
Пример #19
0
def make_annual_averages (in_dir='./', out_dir='./'):

    in_dir = real_dir(in_dir)
    out_dir = real_dir(out_dir)

    # Find all the files of the form output_*.nc
    file_names = build_file_list(in_dir)
    num_files = len(file_names)
    # Make sure their names go from 1 to n where  n is the number of files
    if '001' not in file_names[0] or '{0:03d}'.format(num_files) not in file_names[-1]:
        print 'Error (make_annual_average): based on filenames, you seem to be missing some files.'
        sys.exit()

    # Get the starting date
    time0 = netcdf_time(file_names[0])[0]
    if time0.month != 1:
        print "Error (make_annual_average): this simulation doesn't start in January."
        sys.exit()
    year0 = time0.year

    # Save the number of months in each file
    num_months = []
    for file in file_names:
        id = nc.Dataset(file)
        num_months.append(id.variables['time'].size)
        id.close()

    # Now the work starts
    year = year0
    i = 0  # file number
    t = 0  # the next time index that needs to be dealt with
    files_to_average = [] # list of files containing timesteps from the current year
    t_start = None  # time index of files_to_average[0] to start the averaging from

    # New iteration of loop each time we process a chunk of time from a file.
    while True:

        if len(files_to_average)==0 and t+12 <= num_months[i]:
            # Option 1: Average a full year
            files_to_average.append(file_names[i])
            t_start = t
            t_end = t+12
            print 'Processing all of ' + str(year) + ' from ' + file_names[i] + ', indices ' + str(t_start) + ' to ' + str(t_end-1)
            average_monthly_files(files_to_average, out_dir+str(year)+'_avg.nc', t_start=t_start, t_end=t_end)
            files_to_average = []
            t_start = None
            t += 12
            year += 1

        elif len(files_to_average)==0 and t+12 > num_months[i]:
            # Option 2: Start a new year
            files_to_average.append(file_names[i])
            t_start = t
            print 'Processing beginning of ' + str(year) + ' from ' + file_names[i] + ', indices ' + str(t_start) + ' to ' + str(num_months[i]-1)
            tmp_months = num_months[i] - t_start
            print '(have processed ' + str(tmp_months) + ' months of ' + str(year) + ')'
            t = num_months[i]

        elif len(files_to_average)>0 and t+12-tmp_months > num_months[i]:
            # Option 3: Add onto an existing year, but can't complete it
            files_to_average.append(file_names[i])
            if t != 0:
                print 'Error (make_annual_averages): something weird happened with Option 3'
                sys.exit()
            print 'Processing middle of ' + str(year) + ' from ' + file_names[i] + ', indices ' + str(t) + ' to ' + str(num_months[i]-1)
            tmp_months += num_months[i] - t
            print '(have processed ' + str(tmp_months) + ' months of ' + str(year) + ')'
            t = num_months[i]

        elif len(files_to_average)>0 and t+12-tmp_months <= num_months[i]:
            # Option 4: Add onto an existing year and complete it
            files_to_average.append(file_names[i])
            if t != 0:
                print 'Error (make_annual_averages): something weird happened with Option 4'
                sys.exit()
            t_end = t+12-tmp_months
            print 'Processing end of ' + str(year) + ' from ' + file_names[i] + ', indices ' + str(t) + ' to ' + str(t_end-1)
            average_monthly_files(files_to_average, out_dir+str(year)+'_avg.nc', t_start=t_start, t_end=t_end)
            files_to_average = []
            t_start = None
            t += 12-tmp_months
            year += 1

        if t == num_months[i]:
            print 'Reached the end of ' + file_names[i]
            # Prepare for the next file
            i += 1
            t = 0
            if i == num_files:
                # No more files
                if len(files_to_average)>0:
                    print 'Warning: ' + str(year) + ' is incomplete. Ignoring it.'
                break
Пример #20
0
def average_monthly_files (input_files, output_file, t_start=0, t_end=None):

    from nco import Nco
    from nco.custom import Limit

    if isinstance(input_files, str):
        # Only one file
        input_files = [input_files]

    # Extract the first time record from the first file
    # This will make a skeleton file with 1 time record and all the right metadata; later we will overwrite the values of all the time-dependent variables with the weighted time-averages.
    print 'Initialising ' + output_file
    nco = Nco()
    nco.ncks(input=input_files[0], output=output_file, options=[Limit('time', t_start, t_start)])

    # Get the starting date
    time0 = netcdf_time(output_file)
    year0 = time0[0].year
    month0 = time0[0].month    

    # Find all the time-dependent variables
    var_names = time_dependent_variables(output_file)

    # Time-average each variable
    id_out = nc.Dataset(output_file, 'a')
    for var in var_names:
        print 'Processing ' + var

        # Reset time
        year = year0
        month = month0
        # Set up accumulation array of the right dimension for this variable
        shape = id_out.variables[var].shape[1:]
        data = np.zeros(shape)
        # Also accumulate total number of days
        total_days = 0

        # Loop over input files
        for i in range(len(input_files)):

            file_name = input_files[i]
            print '...' + file_name
            
            # Figure out how many time indices there are
            id_in = nc.Dataset(file_name, 'r')
            num_time = id_in.variables[var].shape[0]

            # Choose which indices we will loop over: special cases for first and last files, if t_start or t_end are set
            if i == 0:
                t_start_curr = t_start
            else:
                t_start_curr = 0
            if i == len(input_files)-1 and t_end is not None:
                t_end_curr = t_end
            else:
                t_end_curr = num_time

            # Now loop over time indices
            for t in range(t_start_curr, t_end_curr):
                # Integrate
                ndays = days_per_month(month, year)
                data += id_in.variables[var][t,:]*ndays
                total_days += ndays
                # Increment month (and year if needed)
                month += 1
                if month == 13:
                    month = 1
                    year += 1

            id_in.close()

        # Now convert from integral to average
        data /= total_days
        # Overwrite this variable in the output file
        id_out.variables[var][0,:] = data

    id_out.close()
Пример #21
0
def precompute_timeseries (mit_file, timeseries_file, timeseries_types=None, monthly=True, lon0=None, lat0=None):

    # Timeseries to compute
    if timeseries_types is None:
        timeseries_types = ['fris_mass_balance', 'eta_avg', 'seaice_area', 'fris_temp', 'fris_salt', 'fris_age'] #['fris_mass_balance', 'hice_corner', 'mld_ewed', 'eta_avg', 'seaice_area', 'fris_temp', 'fris_salt']

    # Build the grid
    grid = Grid(mit_file)

    # Check if the timeseries file already exists
    file_exists = os.path.isfile(timeseries_file)
    if file_exists:
        # Open it
        id = nc.Dataset(timeseries_file, 'a')
    else:
        # Create it
        ncfile = NCfile(timeseries_file, grid, 't')

    # Define/update time
    # Read the time array from the MITgcm file, and its units
    time, time_units = netcdf_time(mit_file, return_units=True)
    if file_exists:
        # Update the units to match the old time array
        time_units = id.variables['time'].units
        # Also figure out how many time indices are in the file so far
        num_time = id.variables['time'].size
        # Convert to numeric values
        time = nc.date2num(time, time_units)
        # Append to file
        id.variables['time'][num_time:] = time
    else:
        # Add the time variable to the file
        ncfile.add_time(time, units=time_units)

    # Inner function to define/update non-time variables
    def write_var (data, var_name, title, units):
        if file_exists:
            # Append to file
            id.variables[var_name][num_time:] = data
        else:
            # Add the variable to the file
            ncfile.add_variable(var_name, data, 't', long_name=title, units=units)

    # Now process all the timeseries
    for ts_name in timeseries_types:
        print 'Processing ' + ts_name
        # Get information about the variable; only care about title and units
        title, units = set_parameters(ts_name)[2:4]
        if ts_name == 'fris_mass_balance':
            melt, freeze = calc_special_timeseries(ts_name, mit_file, grid=grid, monthly=monthly)[1:]
            # We need two titles now
            title_melt = 'Total melting beneath FRIS'
            title_freeze = 'Total refreezing beneath FRIS'
            # Update two variables
            write_var(melt, 'fris_total_melt', title_melt, units)
            write_var(freeze, 'fris_total_freeze', title_freeze, units)
        else:
            data = calc_special_timeseries(ts_name, mit_file, grid=grid, lon0=lon0, lat0=lat0, monthly=monthly)[1]
            write_var(data, ts_name, title, units)

    # Finished
    if file_exists:
        id.close()
    else:
        ncfile.close()
Пример #22
0
def read_plot_timeseries_ensemble(var_name,
                                  file_paths,
                                  sim_names=None,
                                  precomputed=False,
                                  grid=None,
                                  lon0=None,
                                  lat0=None,
                                  plot_mean=False,
                                  first_in_mean=True,
                                  annual_average=False,
                                  time_use=0,
                                  colours=None,
                                  linestyles=None,
                                  fig_name=None,
                                  monthly=True,
                                  legend_in_centre=False,
                                  dpi=None,
                                  smooth=0,
                                  title=None,
                                  units=None,
                                  print_mean=False,
                                  operator='add',
                                  vline=None,
                                  alpha=False,
                                  plot_anomaly=False,
                                  base_year_start=None,
                                  base_year_end=None,
                                  trim_before=False,
                                  base_year_start_first=None,
                                  percent=False,
                                  year_ticks=None):

    if isinstance(var_name, str):
        var_name = [var_name]
    if (plot_anomaly or percent) and (base_year_start is None
                                      or base_year_end is None):
        print 'Error (read_plot_timeseries_ensemble): must set base_year_start and base_year_end'
        sys.exit()

    # Read data
    all_times = []
    all_datas = []
    for f in file_paths:
        data = None
        for var in var_name:
            if var.endswith('mass_balance'):
                print 'Error (read_plot_timeseries_ensemble): This function does not work for mass balance terms.'
                sys.exit()
            if precomputed:
                time = netcdf_time(f, monthly=False)
                data_tmp = read_netcdf(f, var)
            else:
                time, data_tmp = calc_special_timeseries(var,
                                                         f,
                                                         grid=grid,
                                                         lon0=lon0,
                                                         lat0=lat0,
                                                         monthly=monthly)
            if data is None:
                data = data_tmp
            else:
                if operator == 'add':
                    data += data_tmp
                elif operator == 'subtract':
                    data -= data_tmp
                else:
                    print 'Error (read_plot_timeseries_ensemble): invalid operator ' + operator
                    sys.exit()
        if plot_anomaly or percent or trim_before:
            # Find the time indices that define the baseline period
            if time[0].year > base_year_start:
                if (not plot_anomaly) and (not percent):
                    # This is ok
                    t_start = 0
                    if base_year_start_first is not None and f == file_paths[0]:
                        # A tighter constraint on start year
                        t_start = index_year_start(time, base_year_start_first)
                else:
                    print 'Error (read_plot_timeseries_ensemble): this simulation does not cover the baseline period'
                    sys.exit()
            else:
                t_start, t_end = index_period(time, base_year_start,
                                              base_year_end)
                # Calculate the mean over that period
                data_mean = np.mean(data[t_start:t_end])
            if plot_anomaly:
                # Subtract the mean
                data -= data_mean
            if percent:
                # Express as percentage of mean
                data = data / data_mean * 100
            if trim_before:
                # Trim everything before the baseline period
                data = data[t_start:]
                time = time[t_start:]
        all_times.append(time)
        all_datas.append(data)
    if time_use is None:
        time = all_times
    else:
        # Make sure all simulations are the same length, and then choose one time axis to use
        if any([t.size != all_times[0].size for t in all_times]):
            print 'Error (read_plot_timeseries_ensemble): not all the simulations are the same length.'
            sys.exit()
        time = all_times[time_use]

    if annual_average:
        # Make sure it's an integer number of 30-day months
        calendar = netcdf_time(file_paths[0], return_units=True)[2]
        if calendar != '360_day' or not monthly or time.size % 12 != 0:
            print 'Error (read_plot_timeseries_ensemble): can only do true annual averages if there are an integer number of 30-day months.'
            sys.exit()
        time, all_datas = calc_annual_averages(time, all_datas)

    if smooth != 0:
        for n in range(len(all_datas)):
            if time_use is None:
                data_tmp, time_tmp = moving_average(all_datas[n],
                                                    smooth,
                                                    time=time[n])
                time[n] = time_tmp
            else:
                data_tmp, time_tmp = moving_average(all_datas[n],
                                                    smooth,
                                                    time=time)
            all_datas[n] = data_tmp
        if time_use is not None:
            time = time_tmp

    # Set other things for plot
    if len(var_name) == 1:
        title, units = set_parameters(var_name[0])[2:4]
    elif title is None or units is None:
        print 'Error (read_plot_timeseries_ensemble): must set title and units'
        sys.exit()
    if percent:
        units = '% of ' + str(base_year_start) + '-' + str(
            base_year_end) + ' mean'
    if plot_anomaly:
        title += ' \n(anomaly from ' + str(base_year_start) + '-' + str(
            base_year_end) + ' mean)'
    if colours is None:
        colours = default_colours(len(file_paths))
    if alpha:
        alphas = [1] + [0.5 for n in range(len(file_paths) - 1)]
    else:
        alphas = None

    if plot_mean:
        if first_in_mean:
            n0 = 0
        else:
            n0 = 1
        if time_use is None and any(
            [t.size != all_times[n0].size for t in all_times[n0:]]):
            print 'Error (read_plot_timeseries_ensemble): can only calculate mean if simulations are same length.'
            sys.exit()
        # Calculate the mean
        all_datas.append(np.mean(all_datas[n0:], axis=0))
        all_times.append(all_times[n0])
        if len(colours) != len(all_datas):
            # Choose a colour
            # First replace any black in the colours array
            if 'black' in colours:
                colours[colours.index('black')] = (0.4, 0.4, 0.4)
            colours.append('black')
        if alphas is not None:
            alphas.append(1)
        if sim_names is not None:
            sim_names.append('Mean')

    if print_mean:
        print 'Mean values for ' + title + ':'
        for data, sim in zip(all_datas, sim_names):
            print sim + ': ' + str(np.mean(data)) + ' ' + units

    timeseries_multi_plot(time,
                          all_datas,
                          sim_names,
                          colours,
                          title=title,
                          units=units,
                          monthly=monthly,
                          fig_name=fig_name,
                          dpi=dpi,
                          legend_in_centre=legend_in_centre,
                          thick_last=plot_mean,
                          thick_first=(plot_mean and not first_in_mean),
                          linestyles=linestyles,
                          alphas=alphas,
                          first_on_top=(plot_mean and not first_in_mean),
                          vline=vline,
                          year_ticks=year_ticks)
Пример #23
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)
Пример #24
0
def read_plot_timeseries(var,
                         file_path,
                         diff=False,
                         precomputed=False,
                         grid=None,
                         lon0=None,
                         lat0=None,
                         fig_name=None,
                         monthly=True,
                         legend_in_centre=False,
                         dpi=None,
                         annual_average=False,
                         smooth=0):

    if diff and (not isinstance(file_path, list) or len(file_path) != 2):
        print 'Error (read_plot_timeseries): must pass a list of 2 file paths when diff=True.'
        sys.exit()

    if precomputed:
        # Read time arrays
        if diff:
            time_1 = netcdf_time(file_path[0],
                                 monthly=(monthly and not precomputed))
            time_2 = netcdf_time(file_path[1],
                                 monthly=(monthly and not precomputed))
            calendar = netcdf_time(file_path[0], return_units=True)[2]
            time = trim_and_diff(time_1, time_2, time_1, time_2)[0]
        else:
            time = netcdf_time(file_path,
                               monthly=(monthly and not precomputed))
            calendar = netcdf_time(file_path, return_units=True)[2]

    # Set parameters (only care about title and units)
    title, units = set_parameters(var)[2:4]
    if diff:
        title = 'Change in ' + title[0].lower() + title[1:]

    # Inner function to read a timeseries from both files and calculate the differences, trimming if needed. Only useful if precomputed=True.
    def read_and_trim(var_name):
        data_1 = read_netcdf(file_path[0], var_name)
        data_2 = read_netcdf(file_path[1], var_name)
        data_diff = trim_and_diff(time_1, time_2, data_1, data_2)[1]
        return data_diff

    if var.endswith('mass_balance'):
        if precomputed:
            # Read the fields from the timeseries file
            shelf = var[:var.index('_mass_balance')]
            if diff:
                melt = read_and_trim(shelf + '_total_melt')
                freeze = read_and_trim(shelf + '_total_freeze')
            else:
                melt = read_netcdf(file_path, shelf + '_total_melt')
                freeze = read_netcdf(file_path, shelf + '_total_freeze')
        else:
            # Calculate the timeseries from the MITgcm file(s)
            if diff:
                time, melt, freeze = calc_special_timeseries_diff(
                    var,
                    file_path[0],
                    file_path[1],
                    grid=grid,
                    monthly=monthly)
            else:
                time, melt, freeze = calc_special_timeseries(var,
                                                             file_path,
                                                             grid=grid,
                                                             monthly=monthly)
        if annual_average:
            time, [melt, freeze] = calc_annual_averages(time, [melt, freeze])
        melt = moving_average(melt, smooth, time=time)[0]
        freeze, time = moving_average(freeze, smooth, time=time)
        timeseries_multi_plot(time, [melt, freeze, melt + freeze],
                              ['Melting', 'Freezing', 'Net'],
                              ['red', 'blue', 'black'],
                              title=title,
                              units=units,
                              monthly=monthly,
                              fig_name=fig_name,
                              dpi=dpi,
                              legend_in_centre=legend_in_centre)
    else:
        if precomputed:
            if diff:
                data = read_and_trim(var)
            else:
                data = read_netcdf(file_path, var)
        else:
            if diff:
                time, data = calc_special_timeseries_diff(var,
                                                          file_path[0],
                                                          file_path[1],
                                                          grid=grid,
                                                          monthly=monthly)
            else:
                time, data = calc_special_timeseries(var,
                                                     file_path,
                                                     grid=grid,
                                                     lon0=lon0,
                                                     lat0=lat0,
                                                     monthly=monthly)
        if annual_average:
            time, data = calc_annual_averages(time, data)
        data, time = moving_average(data, smooth, time=time)
        make_timeseries_plot(time,
                             data,
                             title=title,
                             units=units,
                             monthly=monthly,
                             fig_name=fig_name,
                             dpi=dpi)
Пример #25
0
def read_plot_timeseries_multi(var_names,
                               file_path,
                               diff=False,
                               precomputed=False,
                               grid=None,
                               lon0=None,
                               lat0=None,
                               fig_name=None,
                               monthly=True,
                               legend_in_centre=False,
                               dpi=None,
                               colours=None):

    if diff:
        if not isinstance(file_path, list) or len(file_path) != 2:
            print 'Error (read_plot_timeseries_multi): must pass a list of 2 file paths when diff=True.'
            sys.exit()
        file_path_1 = file_path[0]
        file_path_2 = file_path[1]
        time_1 = netcdf_time(file_path_1,
                             monthly=(monthly and not precomputed))
        time_2 = netcdf_time(file_path_2,
                             monthly=(monthly and not precomputed))
        time = trim_and_diff(time_1, time_2, time_1, time_2)[0]
    else:
        time = netcdf_time(file_path, monthly=(monthly and not precomputed))

    data = []
    labels = []
    units = None
    if colours is None:
        colours = [
            'blue', 'red', 'black', 'green', 'cyan', 'magenta', 'yellow'
        ]
        if len(var_names) > len(colours):
            print 'Error (read_plot_timeseries_multi): need to specify colours if there are more than 7 variables.'
            sys.exit()
        colours = colours[:len(var_names)]
    for var in var_names:
        if var.endswith('mass_balance'):
            print 'Error (read_plot_timeseries_multi): ' + var + ' is already a multi-plot by itself.'
            sys.exit()
        title, units_tmp = set_parameters(var)[2:4]
        labels.append(title)
        if units is None:
            units = units_tmp
        elif units != units_tmp:
            print 'Error (read_plot_timeseries_multi): units do not match for all timeseries variables'
            sys.exit()
        if precomputed:
            if diff:
                data_1 = read_netcdf(file_path_1, var)
                data_2 = read_netcdf(file_path_2, var)
                data.append(trim_and_diff(time_1, time_2, data_1, data_2)[1])
            else:
                data.append(read_netcdf(file_path, var))
        else:
            if diff:
                data.append(
                    calc_special_timeseries_diff(var,
                                                 file_path_1,
                                                 file_path_2,
                                                 grid=grid,
                                                 lon0=lon0,
                                                 lat0=lat0,
                                                 monthly=monthly)[1])
            else:
                data.append(
                    calc_special_timeseries(var,
                                            file_path,
                                            grid=grid,
                                            lon0=lon0,
                                            lat0=lat0,
                                            monthly=monthly)[1])
    title, labels = trim_titles(labels)
    if diff:
        title = 'Change in ' + title
    timeseries_multi_plot(time,
                          data,
                          labels,
                          colours,
                          title=title,
                          units=units,
                          monthly=monthly,
                          fig_name=fig_name,
                          dpi=dpi,
                          legend_in_centre=legend_in_centre)