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)
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
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)
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)
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
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)
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)
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)
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')
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()
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)
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)
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()
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')
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)
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)
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
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)
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
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()
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()
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)
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)
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)
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)