Пример #1
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)
Пример #2
0
def precompute_timeseries (mit_file, timeseries_file, timeseries_types=None, monthly=True, lon0=None, lat0=None, key='PAS'):

    # Timeseries to compute
    if timeseries_types is None:
        if key == 'WSS':
            timeseries_types = ['fris_mass_balance', 'eta_avg', 'seaice_area', 'fris_temp', 'fris_salt', 'fris_age']
        elif key == 'WSK':
            timeseries_types = ['fris_mass_balance', 'hice_corner', 'mld_ewed', 'eta_avg', 'seaice_area', 'fris_temp', 'fris_salt']
        elif key == 'PAS':
            timeseries_types = ['all_massloss', 'eta_avg', 'seaice_area']

    # Build the grid
    grid = Grid(mit_file)

    # Set up or update the file and time axis
    id = set_update_file(timeseries_file, grid, 't')
    num_time = set_update_time(id, mit_file, monthly=monthly)

    # 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
            set_update_var(id, num_time, melt, 't', 'fris_total_melt', title_melt, units)
            set_update_var(id, num_time, freeze, 't', 'fris_total_freeze', title_freeze, units)
        else:
            data = calc_special_timeseries(ts_name, mit_file, grid=grid, lon0=lon0, lat0=lat0, monthly=monthly)[1]
            set_update_var(id, num_time, data, 't', ts_name, title, units)

    # Finished
    if isinstance(id, nc.Dataset):
        id.close()
    elif isinstance(id, NCfile):
        id.close()
Пример #3
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()
Пример #4
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)
Пример #5
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)
Пример #6
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)
Пример #7
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)