Ejemplo n.º 1
0
def read_plot_ts_slice_diff (file_path_1, file_path_2, grid=None, lon0=None, lat0=None, point0=None, point1=None, time_index=None, t_start=None, t_end=None, time_average=False, time_index_2=None, t_start_2=None, t_end_2=None, hmin=None, hmax=None, zmin=None, zmax=None, tmin=None, tmax=None, smin=None, smax=None, tcontours=None, scontours=None, date_string=None, fig_name=None, second_file_path_1=None, second_file_path_2=None):

    diff_time = (time_index_2 is not None) or (time_average and (t_start_2 is not None or t_end_2 is not None))

    grid = choose_grid(grid, file_path_1)
    check_single_time(time_index, time_average)
    date_string = check_date_string(date_string, file_path_1, time_index)

    # Inner function to read a variable from the correct NetCDF file and mask appropriately
    def read_and_mask (var_name, file_path, second_file_path=None, check_diff_time=False):
        # Do we need to choose the right file?
        if second_file_path is not None:
            file_path_use = find_variable(file_path, second_file_path, var_name)
        else:
            file_path_use = file_path
        # Read and mask the data
        if check_diff_time and diff_time:
            return mask_3d(read_netcdf(file_path_use, var_name, time_index=time_index_2, t_start=t_start_2, t_end=t_end_2, time_average=time_average), grid)
        else:
            return mask_3d(read_netcdf(file_path_use, var_name, time_index=time_index, t_start=t_start, t_end=t_end, time_average=time_average), grid)


    # Interface to call read_and_mask for each variable
    def read_and_mask_both (var_name):
        data1 = read_and_mask(var_name, file_path_1, second_file_path=second_file_path_1)
        data2 = read_and_mask(var_name, file_path_2, second_file_path=second_file_path_2, check_diff_time=True)
        return data1, data2

    # Read temperature and salinity for each simulation
    temp_1, temp_2 = read_and_mask_both('THETA')
    salt_1, salt_2 = read_and_mask_both('SALT')

    # Plot
    ts_slice_plot_diff(temp_1, temp_2, salt_1, salt_2, grid, lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, tmin=tmin, tmax=tmax, smin=smin, smax=smax, tcontours=tcontours, scontours=scontours, date_string=date_string, fig_name=fig_name)    
Ejemplo n.º 2
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)
Ejemplo n.º 3
0
def read_plot_hovmoller_diff(var_name,
                             hovmoller_file_1,
                             hovmoller_file_2,
                             grid,
                             zmin=None,
                             zmax=None,
                             vmin=None,
                             vmax=None,
                             contours=None,
                             monthly=True,
                             fig_name=None,
                             figsize=(14, 5)):

    time, data_diff = read_and_trim_diff(hovmoller_file_1, hovmoller_file_2,
                                         var_name)
    title, units = read_title_units(hovmoller_file_1, var_name)
    grid = choose_grid(grid, None)
    hovmoller_plot(data_diff,
                   time,
                   grid,
                   vmin=vmin,
                   vmax=vmax,
                   zmin=zmin,
                   zmax=zmax,
                   monthly=monthly,
                   contours=contours,
                   ctype='plusminus',
                   title='Change in ' + title,
                   fig_name=fig_name,
                   figsize=figsize)
Ejemplo n.º 4
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)
Ejemplo n.º 5
0
def read_plot_hovmoller_ts_diff(hovmoller_file_1,
                                hovmoller_file_2,
                                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):

    time, temp_diff = read_and_trim_diff(hovmoller_file_1, hovmoller_file_2,
                                         loc + '_temp')
    salt_diff = read_and_trim_diff(hovmoller_file_1, hovmoller_file_2,
                                   loc + '_salt')[1]
    grid = choose_grid(grid, None)
    if loc == 'PIB':
        loc_string = 'Pine Island Bay '
    elif loc == 'Dot':
        loc_string = 'Dotson front '
    hovmoller_ts_plot(temp_diff,
                      salt_diff,
                      time,
                      grid,
                      tmin=tmin,
                      tmax=tmax,
                      smin=smin,
                      smax=smax,
                      zmin=zmin,
                      zmax=zmax,
                      monthly=monthly,
                      t_contours=t_contours,
                      s_contours=s_contours,
                      ctype='plusminus',
                      loc_string=loc_string,
                      fig_name=fig_name,
                      figsize=figsize,
                      dpi=dpi)
Ejemplo n.º 6
0
def read_plot_hovmoller_ts_diff(hovmoller_file_1,
                                hovmoller_file_2,
                                loc,
                                grid,
                                smooth=0,
                                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):

    time, temp_diff = read_and_trim_diff(hovmoller_file_1, hovmoller_file_2,
                                         loc + '_temp')
    salt_diff = read_and_trim_diff(hovmoller_file_1, hovmoller_file_2,
                                   loc + '_salt')[1]
    grid = choose_grid(grid, None)
    loc_string = region_names[loc]
    hovmoller_ts_plot(temp_diff,
                      salt_diff,
                      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,
                      ctype='plusminus',
                      loc_string=loc_string,
                      fig_name=fig_name,
                      figsize=figsize,
                      dpi=dpi)
Ejemplo n.º 7
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)
Ejemplo n.º 8
0
def read_plot_ts_slice (file_path, grid=None, lon0=None, lat0=None, point0=None, point1=None, time_index=None, t_start=None, t_end=None, time_average=False, hmin=None, hmax=None, zmin=None, zmax=None, tmin=None, tmax=None, smin=None, smax=None, tcontours=None, scontours=None, date_string=None, fig_name=None, second_file_path=None):

    grid = choose_grid(grid, file_path)
    check_single_time(time_index, time_average)
    date_string = check_date_string(date_string, file_path, time_index)

    # Inner function to read a variable from the correct NetCDF file and mask appropriately
    def read_and_mask (var_name):
        # Do we need to choose the right file?
        if second_file_path is not None:
            file_path_use = find_variable(file_path, second_file_path, var_name)
        else:
            file_path_use = file_path
        # Read and mask the data
        data = mask_3d(read_netcdf(file_path_use, var_name, time_index=time_index, t_start=t_start, t_end=t_end, time_average=time_average), grid)
        return data

    # Read temperature and salinity
    temp = read_and_mask('THETA')
    salt = read_and_mask('SALT')

    # Plot
    ts_slice_plot(temp, salt, grid, lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, tmin=tmin, tmax=tmax, smin=smin, smax=smax, tcontours=tcontours, scontours=scontours, date_string=date_string, fig_name=fig_name)
Ejemplo n.º 9
0
def calc_load_anomaly (grid, out_file, option='constant', ini_temp_file=None, ini_salt_file=None, ini_temp=None, ini_salt=None, constant_t=-1.9, constant_s=34.4, eosType='MDJWF', rhoConst=1035, tAlpha=None, sBeta=None, Tref=None, Sref=None, hfac=None, prec=64, check_grid=True):

    errorTol = 1e-13  # convergence criteria

    # Build the grid if needed
    if check_grid:
        grid = choose_grid(grid, None)
    # Decide which hfac to use
    if hfac is None:
        hfac = grid.hfac

    # Set temperature and salinity
    if ini_temp is not None and ini_salt is not None:
        # Deep copy of the arrays
        temp = np.copy(ini_temp)
        salt = np.copy(ini_salt)
    elif ini_temp_file is not None and ini_salt_file is not None:
        # Read from file
        temp = read_binary(ini_temp_file, [grid.nx, grid.ny, grid.nz], 'xyz', prec=prec)
        salt = read_binary(ini_salt_file, [grid.nx, grid.ny, grid.nz], 'xyz', prec=prec)
    else:
        print 'Error (calc_load_anomaly): Must either specify ini_temp and ini_salt OR ini_temp_file and ini_salt_file'
        sys.exit()

    # Fill in the ice shelves
    # The bathymetry will get filled too, but that doesn't matter because pressure is integrated from the top down
    closed = hfac==0
    if option == 'constant':
        # Fill with constant values
        temp[closed] = constant_t
        salt[closed] = constant_s
    elif option == 'nearest':
        # Select the layer immediately below the ice shelves and tile to make it 3D
        temp_top = xy_to_xyz(select_top(np.ma.masked_where(closed, temp), return_masked=False), grid)
        salt_top = xy_to_xyz(select_top(np.ma.masked_where(closed, salt), return_masked=False), grid)
        # Fill the mask with these values
        temp[closed] = temp_top[closed]
        salt[closed] = salt_top[closed]    
    elif option == 'precomputed':
        for data in [temp, salt]:
            # Make sure there are no missing values
            if (data[~closed]==0).any():
                print 'Error (calc_load_anomaly): you selected the precomputed option, but there are appear to be missing values in the land mask.'
                sys.exit()
            # Make sure it's not a masked array as this will break the rms
            if isinstance(data, np.ma.MaskedArray):
                # Fill the mask with zeros
                data[data.mask] = 0
                data = data.data
    else:
        print 'Error (calc_load_anomaly): invalid option ' + option
        sys.exit()

    # Get vertical integrands considering z at both centres and edges of layers
    dz_merged = np.zeros(2*grid.nz)
    dz_merged[::2] = abs(grid.z - grid.z_edges[:-1])  # dz of top half of each cell
    dz_merged[1::2] = abs(grid.z_edges[1:] - grid.z)  # dz of bottom half of each cell
    # Tile to make 3D
    z = z_to_xyz(grid.z, grid)
    dz_merged = z_to_xyz(dz_merged, grid)

    # Initial guess for pressure (dbar) at centres of cells
    press = abs(z)*gravity*rhoConst*1e-4

    # Iteratively calculate pressure load anomaly until it converges
    press_old = np.zeros(press.shape)  # Dummy initial value for pressure from last iteration
    rms_error = 0
    while True:
        rms_old = rms_error
        rms_error = rms(press, press_old)
        print 'RMS error = ' + str(rms_error)
        if rms_error < errorTol or np.abs(rms_error-rms_old) < 0.1*errorTol:
            print 'Converged'
            break
        # Save old pressure
        press_old = np.copy(press)
        # Calculate density anomaly at centres of cells
        drho_c = density(eosType, salt, temp, press, rhoConst=rhoConst, Tref=Tref, Sref=Sref, tAlpha=tAlpha, sBeta=sBeta) - rhoConst
        # Use this for both centres and edges of cells
        drho = np.zeros(dz_merged.shape)
        drho[::2,...] = drho_c
        drho[1::2,...] = drho_c
        # Integrate pressure load anomaly (Pa)
        pload_full = np.cumsum(drho*gravity*dz_merged, axis=0)
        # Update estimate of pressure
        press = (abs(z)*gravity*rhoConst + pload_full[1::2,...])*1e-4

    # Extract pload at each level edge (don't care about centres anymore)
    pload_edges = pload_full[::2,...]

    # Now find pload at the ice shelf base
    # For each xy point, calculate three variables:
    # (1) pload at the base of the last fully dry ice shelf cell
    # (2) pload at the base of the cell beneath that
    # (3) hFacC for that cell
    # To calculate (1) we have to shift pload_3d_edges upward by 1 cell
    pload_edges_above = neighbours_z(pload_edges)[0]
    pload_above = select_top(np.ma.masked_where(closed, pload_edges_above), return_masked=False)
    pload_below = select_top(np.ma.masked_where(closed, pload_edges), return_masked=False)
    hfac_below = select_top(np.ma.masked_where(closed, hfac), return_masked=False)
    # Now we can interpolate to the ice base
    pload = pload_above + (1-hfac_below)*(pload_below - pload_above)

    # Write to file
    write_binary(pload, out_file, prec=prec)
Ejemplo n.º 10
0
def read_plot_slice_diff (var, file_path_1, file_path_2, grid=None, lon0=None, lat0=None, point0=None, point1=None, time_index=None, t_start=None, t_end=None, time_average=False, time_index_2=None, t_start_2=None, t_end_2=None, hmin=None, hmax=None, zmin=None, zmax=None, vmin=None, vmax=None, contours=None, date_string=None, fig_name=None, eosType='MDJWF', rhoConst=None, Tref=None, Sref=None, tAlpha=None, sBeta=None, ref_depth=0):

    # Figure out if the two files use different time indices
    diff_time = (time_index_2 is not None) or (time_average and (t_start_2 is not None or t_end_2 is not None))

    # Get set up just like read_plot_slice
    grid = choose_grid(grid, file_path_1)
    check_single_time(time_index, time_average)
    date_string = check_date_string(date_string, file_path_1, time_index)

    # Inner function to read a variable from a NetCDF file and mask appropriately
    def read_and_mask (var_name, file_path, check_diff_time=False, gtype='t'):
        if var_name in ['tminustf', 'rho']:
            # Need to read 2 variables
            temp = read_and_mask('THETA', file_path, check_diff_time=check_diff_time)
            salt = read_and_mask('SALT', file_path, check_diff_time=check_diff_time)
            if var_name == 'rho':
                return mask_3d(density(eosType, salt, temp, ref_depth, rhoConst=rhoConst, Tref=Tref, Sref=Sref, tAlpha=tAlpha, sBeta=sBeta), grid)
            elif var_name == 'tminustf':
                return t_minus_tf(temp, salt, grid)
        elif var_name in ['vnorm', 'valong']:
            u = read_and_mask('UVEL', file_path, check_diff_time=check_diff_time, gtype='u')
            v = read_and_mask('VVEL', file_path, check_diff_time=check_diff_time, gtype='v')
            if var_name == 'vnorm':
                return normal_vector(u, v, grid, point0, point1)
            elif var_name == 'valong':
                return parallel_vector(u, v, grid, point0, point1)
        elif var_name == 'tadv_along':
            tadv_x = read_and_mask('ADVx_TH', file_path, check_diff_time=check_diff_time)
            tadv_y = read_and_mask('ADVy_TH', file_path, check_diff_time=check_diff_time)
            return parallel_vector(tadv_x, tadv_y, grid, point0, point1)
        elif var_name == 'tdif_along':
            tdif_x = read_and_mask('DFxE_TH', file_path, check_diff_time=check_diff_time)
            tdif_y = read_and_mask('DFyE_TH', file_path, check_diff_time=check_diff_time)
            return parallel_vector(tdif_x, tdif_y, grid, point0, point1)
        else:
            if check_diff_time and diff_time:
                return mask_3d(read_netcdf(file_path, var_name, time_index=time_index_2, t_start=t_start_2, t_end=t_end_2, time_average=time_average), grid, gtype=gtype)
            else:
                return mask_3d(read_netcdf(file_path, var_name, time_index=time_index, t_start=t_start, t_end=t_end, time_average=time_average), grid, gtype=gtype)

    # Interface to call read_and_mask for each variable
    def read_and_mask_both (var_name, gtype='t'):
        data1 = read_and_mask(var_name, file_path_1, gtype=gtype)
        data2 = read_and_mask(var_name, file_path_2, check_diff_time=True, gtype=gtype)
        return data1, data2

    if var in ['vnorm', 'valong', 'tadv_along', 'tdif_along'] and None in [point0, point1]:
        print 'Error (read_plot_slice_diff): normal or along-transect variables require point0 and point1 to be specified.'
        sys.exit()

    # Read variables and make plots
    if var == 'temp':
        temp_1, temp_2 = read_and_mask_both('THETA')
        slice_plot_diff(temp_1, temp_2, grid, lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title='Change in temperature ('+deg_string+'C)', date_string=date_string, fig_name=fig_name)
    elif var == 'salt':
        salt_1, salt_2 = read_and_mask_both('SALT')     
        slice_plot_diff(salt_1, salt_2, grid, lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title='Change in salinity (psu)', date_string=date_string, fig_name=fig_name)
    elif var == 'tminustf':
        tmtf_1, tmtf_2 = read_and_mask_both('tminustf')
        slice_plot_diff(tmtf_1, tmtf_2, grid, lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title='Change in difference from in-situ freezing point ('+deg_string+')', date_string=date_string, fig_name=fig_name)
    elif var == 'rho':
        rho_1, rho_2 = read_and_mask_both('rho')
        slice_plot_diff(rho_1, rho_2, grid, lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title=r'Change in density (kg/m$^3$)', date_string=date_string, fig_name=fig_name)
    elif var == 'u':
        u_1, u_2 = read_and_mask_both('UVEL', gtype='u')
        slice_plot_diff(u_1, u_2, grid, gtype='u', lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title='Change in zonal velocity (m/s)', date_string=date_string, fig_name=fig_name)
    elif var == 'v':
        v_1, v_2 = read_and_mask_both('VVEL', gtype='v')
        slice_plot_diff(v_1, v_2, grid, gtype='v', lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title='Change in meridional velocity (m/s)', date_string=date_string, fig_name=fig_name)
    elif var == 'vnorm':
        vnorm_1, vnorm_2 = read_and_mask_both(var)
        slice_plot_diff(vnorm_1, vnorm_2, grid, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title='Change in normal velocity (m/s)', date_string=date_string, fig_name=fig_name)
    elif var == 'valong':
        valong_1, valong_2 = read_and_mask_both(var)
        slice_plot_diff(valong_1, valong_2, grid, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title='Change in along-transect velocity (m/s)', date_string=date_string, fig_name=fig_name)
    elif var == 'tadv_along':
        tadv_along_1, tadv_along_2 = read_and_mask_both(var)
        slice_plot_diff(tadv_along_1, tadv_along_2, grid, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title=r'Change in along-transect advective heat transport (Km$^3$/s)', date_string=date_string, fig_name=fig_name)
    elif var == 'tdif_along':
        tdif_along_1, tdif_along_2 = read_and_mask_both(var)
        slice_plot_diff(tdif_along_1, tdif_along_2, grid, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title=r'Change in along-transect diffusive heat transport (Km$^3$/s)', date_string=date_string, fig_name=fig_name)
    else:
        print 'Error (read_plot_slice_diff): variable key ' + str(var) + ' does not exist'
        sys.exit()
Ejemplo n.º 11
0
def read_plot_slice (var, file_path, grid=None, lon0=None, lat0=None, point0=None, point1=None, time_index=None, t_start=None, t_end=None, time_average=False, hmin=None, hmax=None, zmin=None, zmax=None, vmin=None, vmax=None, contours=None, date_string=None, fig_name=None, second_file_path=None, eosType='MDJWF', rhoConst=None, Tref=None, Sref=None, tAlpha=None, sBeta=None, ref_depth=0):

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

    # Inner function to read a variable from the correct NetCDF file and mask appropriately
    def read_and_mask (var_name, check_second=False, gtype='t'):
        # Do we need to choose the right file?
        if check_second and second_file_path is not None:
            file_path_use = find_variable(file_path, second_file_path, var_name)
        else:
            file_path_use = file_path
        # Read and mask the data
        return mask_3d(read_netcdf(file_path_use, var_name, time_index=time_index, t_start=t_start, t_end=t_end, time_average=time_average), grid, gtype=gtype)

    # Read necessary variables from NetCDF file and mask appropriately
    if var in ['temp', 'tminustf', 'rho']:
        temp = read_and_mask('THETA', check_second=True)
    if var in ['salt', 'tminustf', 'rho']:
        salt = read_and_mask('SALT', check_second=True)
    if var in ['u', 'vnorm', 'valong']:
        u = read_and_mask('UVEL', gtype='u')
    if var in ['v', 'vnorm', 'valong']:
        v = read_and_mask('VVEL', gtype='v')
    if var == 'tadv_along':
        tadv_x = read_and_mask('ADVx_TH')
        tadv_y = read_and_mask('ADVy_TH')
    if var == 'tdif_along':
        tdif_x = read_and_mask('DFxE_TH')
        tdif_y = read_and_mask('DFyE_TH')

    if var in ['vnorm', 'valong', 'tadv_along', 'tdif_along'] and None in [point0, point1]:
        print 'Error (read_plot_slice): normal or along-transect variables require point0 and point1 to be specified.'
        sys.exit()
            
    # Plot
    if var == 'temp':
        slice_plot(temp, grid, lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title='Temperature ('+deg_string+'C)', date_string=date_string, fig_name=fig_name)
    elif var == 'salt':
        slice_plot(salt, grid, lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title='Salinity (psu)', date_string=date_string, fig_name=fig_name)
    elif var == 'tminustf':
        slice_plot(t_minus_tf(temp, salt, grid), grid, lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, ctype='plusminus', title='Difference from in-situ freezing point ('+deg_string+'C)', date_string=date_string, fig_name=fig_name)
    elif var == 'rho':
        # Calculate density
        rho = mask_3d(density(eosType, salt, temp, ref_depth, rhoConst=rhoConst, Tref=Tref, Sref=Sref, tAlpha=tAlpha, sBeta=sBeta), grid)
        slice_plot(rho, grid, lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, contours=contours, title=r'Density (kg/m$^3$)', date_string=date_string, fig_name=fig_name)
    elif var == 'u':
        slice_plot(u, grid, gtype='u', lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, ctype='plusminus', contours=contours, title='Zonal velocity (m/s)', date_string=date_string, fig_name=fig_name)
    elif var == 'v':
        slice_plot(v, grid, gtype='v', lon0=lon0, lat0=lat0, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, ctype='plusminus', contours=contours, title='Meridional velocity (m/s)', date_string=date_string, fig_name=fig_name)
    elif var == 'vnorm':
        vnorm = normal_vector(u, v, grid, point0, point1)
        slice_plot(vnorm, grid, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, ctype='plusminus', contours=contours, title='Normal velocity (m/s)', date_string=date_string, fig_name=fig_name)
    elif var == 'valong':
        valong = parallel_vector(u, v, grid, point0, point1)
        slice_plot(valong, grid, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, ctype='plusminus', contours=contours, title='Along-transect velocity (m/s)', date_string=date_string, fig_name=fig_name)
    elif var == 'tadv_along':
        tadv_along = parallel_vector(tadv_x, tadv_y, grid, point0, point1)
        slice_plot(tadv_along, grid, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, ctype='plusminus', contours=contours, title=r'Along-transect advective heat transport (Km$^3$/s)', date_string=date_string, fig_name=fig_name)
    elif var == 'tdif_along':
        tdif_along = parallel_vector(tdif_x, tdif_y, grid, point0, point1)
        slice_plot(tdif_along, grid, point0=point0, point1=point1, hmin=hmin, hmax=hmax, zmin=zmin, zmax=zmax, vmin=vmin, vmax=vmax, ctype='plusminus', contours=contours, title=r'Along-transect diffusive heat transport (Km$^3$/s)', date_string=date_string, fig_name=fig_name)
    else:
        print 'Error (read_plot_slice): variable key ' + str(var) + ' does not exist'
        sys.exit()
Ejemplo n.º 12
0
def ts_distribution_plot(file_path,
                         option='fris',
                         grid=None,
                         time_index=None,
                         t_start=None,
                         t_end=None,
                         time_average=False,
                         second_file_path=None,
                         tmin=None,
                         tmax=None,
                         smin=None,
                         smax=None,
                         num_bins=1000,
                         date_string=None,
                         figsize=(8, 6),
                         fig_name=None):

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

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

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

    # Select the points we care about
    if option == 'fris':
        # Select all points in the FRIS cavity
        loc_index = (grid.hfac > 0) * xy_to_xyz(grid.fris_mask, grid)
    elif option == 'cavities':
        # Select all points in ice shelf cavities
        loc_index = (grid.hfac > 0) * xy_to_xyz(grid.ice_mask, grid)
    elif option == 'all':
        # Select all unmasked points
        loc_index = grid.hfac > 0
    else:
        print 'Error (plot_misc): invalid option ' + option
        sys.exit()

    # Inner function to set up bins for a given variable (temp or salt)
    def set_bins(data):
        # Find the bounds on the data at the points we care about
        vmin = np.amin(data[loc_index])
        vmax = np.amax(data[loc_index])
        # Choose a small epsilon to add/subtract from the boundaries
        # This way nothing will be at the edge of a beginning/end bin
        eps = (vmax - vmin) * 1e-3
        # Calculate boundaries of bins
        bins = np.linspace(vmin - eps, vmax + eps, num=num_bins)
        # Now calculate the centres of bins for plotting
        centres = 0.5 * (bins[:-1] + bins[1:])
        return bins, centres

    # Call this function for each variable
    temp_bins, temp_centres = set_bins(temp)
    salt_bins, salt_centres = set_bins(salt)
    # Now set up a 2D array to increment with volume of water masses
    volume = np.zeros([temp_centres.size, salt_centres.size])

    # Loop over all cells to increment volume
    # This can't really be vectorised unfortunately
    for i in range(grid.nx):
        for j in range(grid.ny):
            if option == 'fris' and not grid.fris_mask[j, i]:
                # Disregard all points not in FRIS cavity
                continue
            if option == 'cavities' and not grid.ice_mask[j, i]:
                # Disregard all points not in ice shelf cavities
                continue
            for k in range(grid.nz):
                if grid.hfac[k, j, i] == 0:
                    # Disregard all masked points
                    continue
                # If we're still here, it's a point we care about
                # Figure out which bins it falls into
                temp_index = np.nonzero(temp_bins > temp[k, j, i])[0][0] - 1
                salt_index = np.nonzero(salt_bins > salt[k, j, i])[0][0] - 1
                # Increment volume array
                volume[temp_index, salt_index] += grid.dV[k, j, i]
    # Mask bins with zero volume
    volume = np.ma.masked_where(volume == 0, volume)

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

    # Plot
    fig, ax = plt.subplots(figsize=figsize)
    # Use a log scale for visibility
    img = plt.pcolor(salt_centres,
                     temp_centres,
                     np.log(volume),
                     vmin=min_vol,
                     vmax=max_vol)
    # Add the surface freezing point
    plt.plot(salt_centres,
             tfreeze_sfc,
             color='black',
             linestyle='dashed',
             linewidth=2)
    ax.grid(True)
    ax.set_xlim([smin, smax])
    ax.set_ylim([tmin, tmax])
    plt.xlabel('Salinity (psu)')
    plt.ylabel('Temperature (' + deg_string + 'C)')
    plt.colorbar(img)
    plt.text(.9,
             .6,
             'log of volume',
             ha='center',
             rotation=-90,
             transform=fig.transFigure)
    plt.title(title)
    finished_plot(fig, fig_name=fig_name)
Ejemplo n.º 13
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
Ejemplo n.º 14
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)
Ejemplo n.º 15
0
def ts_distribution_plot(file_path,
                         region='all',
                         grid=None,
                         time_index=None,
                         t_start=None,
                         t_end=None,
                         time_average=False,
                         second_file_path=None,
                         tmin=None,
                         tmax=None,
                         smin=None,
                         smax=None,
                         num_bins=1000,
                         date_string=None,
                         figsize=(8, 6),
                         fig_name=None):

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

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

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

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

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

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

    # Plot
    fig, ax = plt.subplots(figsize=figsize)
    # Use a log scale for visibility
    img = plt.pcolor(salt_centres,
                     temp_centres,
                     np.log(volume),
                     vmin=min_vol,
                     vmax=max_vol)
    # Add the surface freezing point
    plt.plot(salt_centres,
             tfreeze_sfc,
             color='black',
             linestyle='dashed',
             linewidth=2)
    ax.grid(True)
    ax.set_xlim([smin, smax])
    ax.set_ylim([tmin, tmax])
    plt.xlabel('Salinity (psu)')
    plt.ylabel('Temperature (' + deg_string + 'C)')
    plt.colorbar(img)
    plt.text(.9,
             .6,
             'log of volume',
             ha='center',
             rotation=-90,
             transform=fig.transFigure)
    plt.title(title)
    finished_plot(fig, fig_name=fig_name)