Exemple #1
0
def read_mode_info(dir_NM, option, i_clip=None):

    # Define directories and files.
    dir_processed = os.path.join(dir_NM, 'processed')

    # Load the mode identification information.
    path_ids = os.path.join(dir_processed, 'mode_ids_{:}.txt'.format(option))
    i_mode, l, type_, shell = np.loadtxt(path_ids, dtype=np.int).T
    if i_clip is not None:

        i_mode = i_mode[:i_clip]
        l = l[:i_clip]
        type_ = type_[:i_clip]
        shell = shell[:i_clip]

    # Read the mode frequency.
    file_eigval_list = os.path.join(dir_processed, 'eigenvalue_list.txt')
    _, f = read_eigenvalues(file_eigval_list)

    ## Read coefficients.
    #coeffs = load_all_vsh_coefficients(dir_NM, i_mode)

    if i_clip is not None:

        f = f[:i_clip]

    return i_mode, f, l, type_, shell
Exemple #2
0
def plot_sh_disp_animation(dir_NM, i_mode, i_radius_str, n_lat_grid, mode_real_or_complex, rotation_period_hrs, save = True):

    # Determine if the plot is 'quick' mode or 'full' mode.
    if i_radius_str is None:

        option = 'quick'

    else:

        option = 'full'

    if mode_real_or_complex == 'real':

        raise NotImplementedError

    elif mode_real_or_complex in ['complex_real_only', 'complex_imag_only']:

        print('Animation for complex mode requires both real and imaginary parts. Change flag from \'{:}\' to \'complex\' in input_plotting.txt'.format(mode_real_or_complex))
        raise ValueError

    elif mode_real_or_complex == 'complex':

        # Plot the first frame, which is the real part.
        fig, ax_arr, handles, fields, contour_info = plot_sh_disp_wrapper(dir_NM, i_mode, n_lat_grid, 'complex_real_only', show = False, fmt = None, close = False, c_bar_label = 'Displacement', figsize = (3.5, 7.0))

        # Identify the eigenvalue list file.
        # Load the frequency of the mode.
        dir_processed = os.path.join(dir_NM, 'processed')
        path_eigenvalues = os.path.join(dir_processed, 'eigenvalue_list.txt')
        freq_mHz = read_eigenvalues(path_eigenvalues, i_mode = i_mode)
        freq_Hz = 1.0E-3*freq_mHz
    
        time_str_fmt = 'Time = {:>6.2f} h,\n{:>.2f} mode cycles,\n{:>.2f} rotations'
        time_str = time_str_fmt.format(0.0, 0.0, 0.0)
        time_title = ax_arr[0].set_title(time_str)

        rotation_period_seconds = 60.0*60.0*rotation_period_hrs
        t_min = 0.0
        t_max = 0.25*rotation_period_seconds
        n_t = 200
        t = np.linspace(t_min, t_max, n_t)
        
        period_mode = 1.0/freq_Hz
        t_hours = t/3600.0
        t_mode_cycles = t/period_mode
        t_rotations = t_hours/rotation_period_hrs

        omega = 2.0*np.pi*freq_Hz # Angular freq, radians per second.
        phase = omega*t
        cos_phase = np.cos(phase)
        sin_phase = np.sin(phase)

        Ur_real = (fields['U']['real']['r']*cos_phase[:, np.newaxis, np.newaxis]) - (fields['U']['imag']['r']*sin_phase[:, np.newaxis, np.newaxis])
        Ur_imag = (fields['U']['real']['r']*sin_phase[:, np.newaxis, np.newaxis]) + (fields['U']['imag']['r']*cos_phase[:, np.newaxis, np.newaxis])

        Ve_real = (fields['V']['real']['e']*cos_phase[:, np.newaxis, np.newaxis]) - (fields['V']['imag']['e']*sin_phase[:, np.newaxis, np.newaxis])
        Ve_imag = (fields['V']['real']['e']*sin_phase[:, np.newaxis, np.newaxis]) + (fields['V']['imag']['e']*cos_phase[:, np.newaxis, np.newaxis])
        Vn_real = (fields['V']['real']['n']*cos_phase[:, np.newaxis, np.newaxis]) - (fields['V']['imag']['n']*sin_phase[:, np.newaxis, np.newaxis])
        Vn_imag = (fields['V']['real']['n']*sin_phase[:, np.newaxis, np.newaxis]) + (fields['V']['imag']['n']*cos_phase[:, np.newaxis, np.newaxis])

        We_real = (fields['W']['real']['e']*cos_phase[:, np.newaxis, np.newaxis]) - (fields['W']['imag']['e']*sin_phase[:, np.newaxis, np.newaxis])
        We_imag = (fields['W']['real']['e']*sin_phase[:, np.newaxis, np.newaxis]) + (fields['W']['imag']['e']*cos_phase[:, np.newaxis, np.newaxis])
        Wn_real = (fields['W']['real']['n']*cos_phase[:, np.newaxis, np.newaxis]) - (fields['W']['imag']['n']*sin_phase[:, np.newaxis, np.newaxis])
        Wn_imag = (fields['W']['real']['n']*sin_phase[:, np.newaxis, np.newaxis]) + (fields['W']['imag']['n']*cos_phase[:, np.newaxis, np.newaxis])

        def animate(i):
            
            time_title.set_text(time_str_fmt.format(t_hours[i], t_mode_cycles[i], t_rotations[i]))

            ax = ax_arr[0]
            
            v_scalar = Ur_real[i, :, :]
            v_scalar, lon_grid = add_cyclic_point(v_scalar, contour_info['lon_grid'])
            ax.collections = [] 
            ax.contourf(
                np.rad2deg(lon_grid),
                np.rad2deg(contour_info['lat_grid']),
                v_scalar,
                contour_info['c_levels'],
                transform   = ccrs.PlateCarree(),
                norm        = contour_info['norm'],
                cmap        = contour_info['cmap'])
            
            ax = ax_arr[1]
            # slice_ controls the down-sampling of the data.
            slice_ = int(np.ceil(lon_grid.shape[0]/20))
            
            v_e = Ve_real[i, :, :] 
            v_n = Vn_real[i, :, :]
            v_scalar = np.sqrt((v_e**2.0) + (v_n**2.0))
            v_scalar, lon_grid = add_cyclic_point(v_scalar, contour_info['lon_grid'])

            ax.collections = [] 
            ax.contourf(
                np.rad2deg(lon_grid),
                np.rad2deg(contour_info['lat_grid']),
                v_scalar,
                contour_info['c_levels'],
                transform   = ccrs.PlateCarree(),
                norm        = contour_info['norm'],
                cmap        = contour_info['cmap'], zorder = -1)

            #print(handles[2].__dict__)
            #handles[2]['U'] = v_e[::slice_, ::slice_]
            #handles[2]['V'] = v_n[::slice_, ::slice_]
            #handles[2].set_UVC(
            #    v_e[::slice_, ::slice_],
            #    v_n[::slice_, ::slice_],)

            slice_ = int(np.ceil(lon_grid.shape[0]/20))
            arrows = ax.quiver(
                np.rad2deg(lon_grid[::slice_]),
                np.rad2deg(contour_info['lat_grid'][::slice_]),
                v_e[::slice_, ::slice_],
                v_n[::slice_, ::slice_],
                transform   = ccrs.PlateCarree(),
                scale       = 1.0E1,
                pivot       = 'middle',
                color       = 'mediumblue')

            ax = ax_arr[2]
            # slice_ controls the down-sampling of the data.
            slice_ = int(np.ceil(lon_grid.shape[0]/20))
            
            v_e = We_real[i, :, :] 
            v_n = Wn_real[i, :, :]
            v_scalar = np.sqrt((v_e**2.0) + (v_n**2.0))
            v_scalar, lon_grid = add_cyclic_point(v_scalar, contour_info['lon_grid'])

            ax.collections = [] 
            ax.contourf(
                np.rad2deg(lon_grid),
                np.rad2deg(contour_info['lat_grid']),
                v_scalar,
                contour_info['c_levels'],
                transform   = ccrs.PlateCarree(),
                norm        = contour_info['norm'],
                cmap        = contour_info['cmap'], zorder = -1)

            #print(handles[2].__dict__)
            #handles[2]['U'] = v_e[::slice_, ::slice_]
            #handles[2]['V'] = v_n[::slice_, ::slice_]
            #handles[2].set_UVC(
            #    v_e[::slice_, ::slice_],
            #    v_n[::slice_, ::slice_],)

            slice_ = int(np.ceil(lon_grid.shape[0]/20))
            arrows = ax.quiver(
                np.rad2deg(lon_grid[::slice_]),
                np.rad2deg(contour_info['lat_grid'][::slice_]),
                v_e[::slice_, ::slice_],
                v_n[::slice_, ::slice_],
                transform   = ccrs.PlateCarree(),
                scale       = 1.0E1,
                pivot       = 'middle',
                color       = 'mediumblue')


        anim = FuncAnimation(
            fig, animate, interval= 10, frames=len(t)-1)

        fmt = 'gif'
        if option == 'quick':

            name_anim = 'disp_anim_{:}_{:>05d}.{:}'.format(option, i_mode, fmt)

        else:

            name_anim = 'disp_anim_{:}_{:>05d}_{:>03d}.{:}'.format(option, i_mode, j_radius, fmt)

        if save:

            dir_plot = os.path.join(dir_processed, 'plots')
            path_anim = os.path.join(dir_plot, name_anim)
            print('Saving animation to {:}'.format(path_anim))
            anim.save(path_anim, writer='imagemagick')

        plt.show()

    else:

        raise ValueError

    return
Exemple #3
0
def plot_sh_disp_wrapper(dir_NM, i_mode, n_lat_grid, mode_real_or_complex, show = True, fmt = 'pdf', transparent = False, i_radius_str = None, close = True, c_bar_label = 'Default', figsize = None, path_outline = None):
    '''
    Plots a vector field on the surface of a sphere in terms of the radial, consoidal and toroidal components.
    This is a wrapper for plot_sh_disp() which first loads the necessary arrays. 

    Input:

    dir_NM, i_mode, n_lat_grid, fmt
        See 'Definitions of variables' in NMPostProcess/process.py.

    Output:

    None
    '''

    # Set transparency.
    transparent = True

    # Define directories.
    dir_processed = os.path.join(dir_NM, 'processed')
    dir_spectral = os.path.join(dir_processed, 'spectral')
    dir_plot = os.path.join(dir_processed, 'plots')
    mkdir_if_not_exist(dir_plot)

    # Load outline data if specified.
    if path_outline is not None:

        outline_data = np.loadtxt(path_outline)

    else:

        outline_data = None

    # Determine if the plot is 'quick' mode or 'full' mode.
    if i_radius_str is None:

        option = 'quick'

    else:

        option = 'full'

    if mode_real_or_complex in ['real', 'complex_imag_only', 'complex_real_only']:
        
        if figsize is None:

            figsize = (3.5, 6.0)

        two_panel = False

    elif mode_real_or_complex == 'complex':

        if figsize is None:

            figsize = (7.0, 6.0)

        two_panel = True

    else:

        raise ValueError

    # Reconstruct the coordinate grid.
    n_lon_grid = (2*n_lat_grid) - 1
    lon_grid = np.linspace(0.0, 2.0*np.pi, n_lon_grid + 1, endpoint = True)[:-1]
    lat_grid = np.linspace(-np.pi/2.0, np.pi/2.0, n_lat_grid, endpoint=True)

    if i_radius_str == 'all':

        _, header_info, _, _ = load_vsh_coefficients(dir_NM, i_mode, 0)
        n_samples = len(header_info['r_sample'])

        i_radius_list = list(range(n_samples))

    elif i_radius_str is None:

        i_radius_list = [None]

    else:

        i_radius_list = [int(i_radius_str)]

    # Identify the eigenvalue list file.
    # Load the frequency of the mode.
    path_eigenvalues = os.path.join(dir_processed, 'eigenvalue_list.txt')
    freq_mHz = read_eigenvalues(path_eigenvalues, i_mode = i_mode)

    first_iteration = True
    for j_radius in i_radius_list:
        
        fig = plt.figure(figsize = figsize)

        # Load the VSH coefficients for the specified mode.
        coeffs, header_info, r_sample, i_sample = load_vsh_coefficients(dir_NM, i_mode, j_radius)

        if mode_real_or_complex == 'real':

            Ulm, Vlm, Wlm = coeffs

        else:

            Ulm_real, Vlm_real, Wlm_real, Ulm_imag, Vlm_imag, Wlm_imag = coeffs

        title_str_mode = 'Mode {:>4d}'.format(i_mode)
        title_str_freq = 'freq. {:>7.4f} mHz'.format(freq_mHz)
        title_str_sample = region_int_to_title(i_sample, r_sample, shell_name_path = os.path.join(dir_processed, 'shell_names.txt'))
        title_str_sample = title_str_sample[0].lower() + title_str_sample[1:]
        if two_panel:

            title = '{:} ({:}), sampled at {:}'.format(title_str_mode, title_str_freq, title_str_sample)

        else:

            title = '{:} ({:}),\nsampled at {:}'.format(title_str_mode, title_str_freq, title_str_sample)

        if first_iteration:

            # Infer the maximum l-value used.
            #n_coeffs = len(Ulm)
            n_coeffs = coeffs.shape[-1]
            l_max = (int((np.round(np.sqrt(8*n_coeffs + 1)) - 1))//2) - 1

            # Re-construct the shtns calculator.
            m_max = l_max
            sh_calculator   = shtns.sht(l_max, m_max)
            grid_type       =       shtns.sht_reg_fast          \
                                |   shtns.SHT_SOUTH_POLE_FIRST  \
                                |   shtns.SHT_PHI_CONTIGUOUS
            sh_calculator.set_grid(n_lat_grid, n_lon_grid, flags = grid_type)

            first_iteration = False

        n_c_levels_default = 20 

        # Expand the VSH into spatial components and plot.
        if mode_real_or_complex == 'real':

            U_r, V_e, V_n, W_e, W_n = project_from_spherical_harmonics(sh_calculator, Ulm, Vlm, Wlm)
            fig, ax_arr, handles, contour_info = plot_sh_disp_3_comp(lon_grid, lat_grid, U_r, V_e, V_n, W_e, W_n, fig = fig, ax_arr = None, show = False, title = title, n_c_levels = n_c_levels_default)

            fields = {  'U' : {'r' : U_r},
                        'V' : {'e' : V_e, 'n' : V_n},
                        'W' : {'e' : W_e, 'n' : W_n}}

        else:

            U_real_r, V_real_e, V_real_n, W_real_e, W_real_n = project_from_spherical_harmonics(sh_calculator, Ulm_real, Vlm_real, Wlm_real)
            U_imag_r, V_imag_e, V_imag_n, W_imag_e, W_imag_n = project_from_spherical_harmonics(sh_calculator, Ulm_imag, Vlm_imag, Wlm_imag)

            fields = {
                'U' :   {   'real' : {  'r' : U_real_r},
                            'imag' : {  'r' : U_imag_r}},
                'V' :   {   'real' : {  'n' : V_real_n,
                                        'e' : V_real_e},
                            'imag' : {  'n' : V_imag_n,
                                        'e' : V_imag_e}},
                'W' :   {   'real' : {  'n' : W_real_n,
                                        'e' : W_real_e},
                            'imag' : {  'n' : W_imag_n,
                                        'e' : W_imag_e}}}

            #U_abs_r = np.sqrt((U_real_r**2.0) + (U_imag_r**2.0))
            #V_abs_e = np.sqrt((V_real_e**2.0) + (V_imag_e**2.0))
            #V_abs_n = np.sqrt((V_real_n**2.0) + (V_imag_n**2.0))
            #W_abs_e = np.sqrt((W_real_e**2.0) + (W_imag_e**2.0))
            #W_abs_n = np.sqrt((W_real_n**2.0) + (W_imag_n**2.0))

            if c_bar_label == 'Default':

                c_bar_label_real = 'Real part'
                c_bar_label_imag = 'Imaginary part'

            else:

                c_bar_label_real = c_bar_label
                c_bar_label_imag = c_bar_label

            if mode_real_or_complex == 'complex':

                #plt.imshow(W_real_e)
                #plt.show()

                fig, ax_arr_real, handles_real, contour_info_real = plot_sh_disp_3_comp(lon_grid, lat_grid, U_real_r, V_real_e, V_real_n, W_real_e, W_real_n, fig = fig, axes_grid_int = 121, ax_arr = None, show = False, title = title, n_c_levels = n_c_levels_default, c_bar_label = c_bar_label_real, outline_data = outline_data)
                fig, ax_arr_imag, handles_imag, contour_info_imag = plot_sh_disp_3_comp(lon_grid, lat_grid, U_imag_r, V_imag_e, V_imag_n, W_imag_e, W_imag_n, fig = fig, axes_grid_int = 122, ax_arr = None, show = False, title = None, n_c_levels = n_c_levels_default, c_bar_label = c_bar_label_imag, outline_data = outline_data)

                contour_info = [contour_info_real, contour_info_imag]

                ax_arr = [ax_arr_real, ax_arr_imag]
                handles = [handles_real, handles_imag]

            elif mode_real_or_complex == 'complex_real_only':

                fig, ax_arr, handles, contour_info = plot_sh_disp_3_comp(lon_grid, lat_grid, U_real_r, V_real_e, V_real_n, W_real_e, W_real_n, fig = fig, ax_arr = None, show = False, title = title, n_c_levels = n_c_levels_default, c_bar_label = c_bar_label_real, outline_data = outline_data) 

            elif mode_real_or_complex == 'complex_imag_only':

                fig, ax_arr, handles, contour_info = plot_sh_disp_3_comp(lon_grid, lat_grid, U_real_r, V_real_e, V_real_n, W_real_e, W_real_n, fig = fig, ax_arr = None, show = False, title = title, n_c_levels = n_c_levels_default, c_bar_label = c_bar_label_imag, outline_data = outline_data)

            else:
                
                raise ValueError

        # Save the plot.
        if fmt is not None:

            real_or_complex_str_dict = {
                'real'              : 'real',
                'complex'              : 'cplx',
                'complex_real_only'     : 'real_only',
                'complex_imag_only'    : 'imag_only'}

            real_or_complex_str = real_or_complex_str_dict[mode_real_or_complex]

            if option == 'quick':

                name_fig = 'displacement_{:}_{:}_{:>05d}.{:}'.format(option, real_or_complex_str, i_mode, fmt)

            else:

                name_fig = 'displacement_{:}_{:}_{:>05d}_{:>03d}.{:}'.format(option, real_or_complex_str, i_mode, j_radius, fmt)
            
            #plt.draw()
            path_fig = os.path.join(dir_plot, name_fig)
            print('Saving figure to {:}'.format(path_fig))
            save_figure(path_fig, fmt, transparent = transparent)

        # Show the plot.
        if show:

            plt.show()

        # Close the plot.
        if close:
            
            plt.close()

    return fig, ax_arr, handles, fields, contour_info
Exemple #4
0
def main():

    # Read the NMPostProcess input file.
    dir_PM, dir_NM, option, l_max, i_mode_str, n_radii = read_input_NMPostProcess()

    # Load the mode identification information.
    dir_processed = os.path.join(dir_NM, 'processed')
    path_ids = os.path.join(dir_processed, 'mode_ids_{:}.txt'.format(option))
    i_mode, l, type_, shell = np.loadtxt(path_ids, dtype = np.int).T

    # Read the mode frequency. 
    file_eigval_list        = os.path.join(dir_processed, 'eigenvalue_list.txt')
    _, f = read_eigenvalues(file_eigval_list)
    num_modes = len(f)

    # Read 3-D mode information.
    mode_info = mode_id_information_to_dict(type_, l, f, shell)

    # Find 1-D mode information.
    Ouroboros_input_file = '../Ouroboros/input_Magrathea.txt'
    Ouroboros_info = read_Ouroboros_input_file(Ouroboros_input_file)

    mode_types = list(mode_info.keys())
    NormalModes_to_Ouroboros_T_layer_num_dict = {0 : 1, 2 : 0}
    paths_ref = dict()
    for mode_type in mode_types:
        
        if mode_type[0] == 'T':

            _, _, _, dir_type = get_Ouroboros_out_dirs(Ouroboros_info, 'T')
            layer_number_NormalModes = int(mode_type[1])
            layer_number_Ouroboros = \
                NormalModes_to_Ouroboros_T_layer_num_dict[layer_number_NormalModes]

            path_ref = os.path.join(dir_type, 'eigenvalues_{:>03d}.txt'.format(layer_number_Ouroboros))

        else:

            _, _, _, dir_type = get_Ouroboros_out_dirs(Ouroboros_info, mode_type)

            path_ref = os.path.join(dir_type, 'eigenvalues.txt')
        
        paths_ref[mode_type] = path_ref

    # Read 1-D reference information.
    nlf_ref = reference_mode_info_to_dict(paths_ref)

    # For each mode, find best fitting reference mode.
    n       = np.zeros(num_modes, dtype = np.int)
    f_ref   = np.zeros(num_modes)
    ref_key_list = []
    for i in range(num_modes):


        if type_[i] == 0:

            ref_key = 'R'

        elif type_[i] == 1:

            ref_key = 'S'

        elif type_[i] == 2:

            ref_key = 'T{:>1d}'.format(shell[i])

        else:

            raise ValueError

        ref_key_list.append(ref_key)

        j_match = np.where(nlf_ref[ref_key]['l'] == l[i])[0]
        k_match = np.argmin(np.abs(nlf_ref[ref_key]['f'][j_match] - f[i]))
        i_match = j_match[k_match]

        n[i] = nlf_ref[ref_key]['n'][i_match]
        f_ref[i] = nlf_ref[ref_key]['f'][i_match]

    f_diff = f - f_ref

    format_string = '{:>5d} {:>1d} {:>4} {:>1d} {:>9.6f} {:>9.6f} {:>+10.6f}'
    print('{:>5} {:>1} {:>4} {:>1} {:>9} {:>9}'.format('Mode', 'n', 'type', 'l', 'f', 'f_ref', 'f_diff'))
    for i in range(num_modes):

        print(format_string.format(i_mode[i], n[i], ref_key_list[i], l[i], f[i], f_ref[i], f_diff[i]))

    return
def main():

    # Read the NMPostProcess input file.
    _, dir_NM_1, _, _, _, _ = read_input_NMPostProcess()

    # Read the comparison input file.
    file_compare = 'input_compare.txt'
    with open(file_compare, 'r') as in_id:

        dir_NM_2 = in_id.readline().strip()

    # Read the mode frequencies.
    dir_processed_1 = os.path.join(dir_NM_1, 'processed')
    file_eigval_list_1 = os.path.join(dir_processed_1, 'eigenvalue_list.txt')
    _, f_1 = read_eigenvalues(file_eigval_list_1)
    #
    dir_processed_2 = os.path.join(dir_NM_2, 'processed')
    file_eigval_list_2 = os.path.join(dir_processed_2, 'eigenvalue_list.txt')
    _, f_2 = read_eigenvalues(file_eigval_list_2)

    # Read the comparison information.
    path_compare = os.path.join(dir_processed_1, 'comparison.txt')
    i_mode_1, i_mode_2 = np.loadtxt(path_compare, dtype=np.int).T

    # Load the mode identification information.
    path_ids_1 = os.path.join(dir_processed_1, 'mode_ids_quick.txt')
    _, l_1, _, _ = np.loadtxt(path_ids_1, dtype=np.int).T
    #i_mode, l, type_, shell = np.loadtxt(path_ids, dtype = np.int).T

    # Sort the frequencies of the comparison run to their best match in the
    # original run.
    f_2_reordered = f_2[i_mode_2]

    # Find minimum and maximum frequencies.
    f_min = np.min(np.concatenate([f_1, f_2]))
    f_max = np.max(np.concatenate([f_1, f_2]))

    # Find maximum frequency difference.
    f_diff = f_1 - f_2_reordered
    f_diff_frac = f_diff / (0.5 * (f_1 + f_2_reordered))
    f_diff_max = np.max(np.abs(f_diff))
    print('Maximum frequency difference: {:>12.6} muHz'.format(f_diff_max *
                                                               1.0E3))

    #fig = plt.figure(figsize = (7.0, 7.0))
    #ax  = plt.gca()

    #ax.scatter(f_1, f_2_reordered)

    ## Plot guide line.
    #f_line_buff = 0.2
    #f_min_line = f_min*(1.0 - f_line_buff)
    #f_max_line = f_max*(1.0 + f_line_buff)
    #ax.plot([f_min_line, f_max_line], [f_min_line, f_max_line])

    ## Set axis limits.
    #f_lim_buff = 0.1
    #f_min_lim = f_min*(1.0 - f_lim_buff)
    #f_max_lim = f_max*(1.0 + f_lim_buff)
    #ax.set_xlim([f_min_lim, f_max_lim])
    #ax.set_ylim([f_min_lim, f_max_lim])

    #font_size_label = 12
    #ax.set_xlabel('Frequency (mHz) of mode in run 1', fontsize = font_size_label)
    #ax.set_ylabel('Frequency (mHz) of mode in run 2', fontsize = font_size_label)

    #ax.set_aspect(1.0)

    #plt.show()

    #fig = plt.figure()
    #ax = plt.gca()

    ##ax.plot(i_mode_1, f_diff*1.0E3, 'k.-')
    #ax.plot(i_mode_1, f_diff_frac*1.0E2, 'k.-')

    #font_size_label = 12
    #ax.set_xlabel('Mode number', fontsize = font_size_label)
    ##ax.set_ylabel('Frequency difference ($\mu$Hz)', fontsize = font_size_label)
    #ax.set_ylabel('Frequency difference (%)', fontsize = font_size_label)

    #fig = plt.figure()
    #ax = plt.gca()

    #ax.scatter(f_1, f_diff*1.0E3, c = 'k', alpha = 0.5)
    ##ax.plot(i_mode_1, f_diff_frac*1.0E2, 'k.-')

    #font_size_label = 12
    #ax.set_xlabel('Frequency', fontsize = font_size_label)
    #ax.set_ylabel('Frequency difference ($\mu$Hz)', fontsize = font_size_label)
    ##ax.set_ylabel('Frequency difference (%)', fontsize = font_size_label)

    fig = plt.figure()
    ax = plt.gca()

    ax.scatter(l_1, f_1, s=10 * 1.0E3 * np.abs(f_diff), c='k', alpha=0.5)
    #ax.plot(i_mode_1, f_diff_frac*1.0E2, 'k.-')

    ax.scatter([], [], c='k', s=10.0, label='1 $\mu Hz$')
    ax.scatter([], [], c='k', s=100.0, label='10 $\mu Hz$')
    ax.legend()

    font_size_label = 12
    ax.set_xlabel('Angular order, $\ell$', fontsize=font_size_label)
    ax.set_ylabel('Frequency (mHz)', fontsize=font_size_label)
    #ax.set_ylabel('Frequency difference ($\mu$Hz)', fontsize = font_size_label)
    ##ax.set_ylabel('Frequency difference (%)', fontsize = font_size_label)

    plt.show()