Instruction:
Can you tell what is the following Python 3 function doing
def find_sample_min_std(self, Intensities):
        '''
        find the best interpretation with the minimum stratard deviation (in units of percent % !)
        '''

        Best_array = []
        best_array_std_perc = inf
        Best_array_tmp = []
        Best_interpretations = {}
        Best_interpretations_tmp = {}
        for this_specimen in list(Intensities.keys()):
            for value in Intensities[this_specimen]:
                Best_interpretations_tmp[this_specimen] = value
                Best_array_tmp = [value]
                all_other_specimens = list(Intensities.keys())
                all_other_specimens.remove(this_specimen)

                for other_specimen in all_other_specimens:
                    closest_value = self.find_close_value(
                        Intensities[other_specimen], value)
                    Best_array_tmp.append(closest_value)
                    Best_interpretations_tmp[other_specimen] = closest_value

                if std(Best_array_tmp, ddof=1) / mean(Best_array_tmp) < best_array_std_perc:
                    Best_array = Best_array_tmp
                    best_array_std_perc = std(
                        Best_array, ddof=1) / mean(Best_array_tmp)
                    Best_interpretations = copy.deepcopy(
                        Best_interpretations_tmp)
                    Best_interpretations_tmp = {}
        return Best_interpretations, mean(Best_array), std(Best_array, ddof=1)

Response: find the best interpretation with the minimum stratard deviation


Instruction:
Write a Python 3 script to
calculate the Thellier Interpreter Parameters for the given site or sample.

Response:
def thellier_interpreter_pars_calc(self, Grade_As):
        '''
        calcualte sample or site STDEV-OPT paleointensities
        and statistics
        Grade_As={}

        '''
        thellier_interpreter_pars = {}
        thellier_interpreter_pars['stdev-opt'] = {}
        # thellier_interpreter_pars['stdev-opt']['B']=
        # thellier_interpreter_pars['stdev-opt']['std']=
        thellier_interpreter_pars['min-value'] = {}
        # thellier_interpreter_pars['min-value']['B']=
        # thellier_interpreter_pars['min-value']['std']=
        thellier_interpreter_pars['max-value'] = {}
        # thellier_interpreter_pars['max-value']['B']=
        # thellier_interpreter_pars['max-value']['std']=
        thellier_interpreter_pars['fail_criteria'] = []
        thellier_interpreter_pars['pass_or_fail'] = 'pass'

        # acceptance criteria
        if self.acceptance_criteria['average_by_sample_or_site']['value'] == 'sample':
            int_n_cutoff = self.acceptance_criteria['sample_int_n']['value']
            int_sigma_cutoff = self.acceptance_criteria['sample_int_sigma']['value']
            int_sigma_perc_cutoff = self.acceptance_criteria['sample_int_sigma_perc']['value']
            int_interval_cutoff = self.acceptance_criteria['sample_int_interval_uT']['value']
            int_interval_perc_cutoff = self.acceptance_criteria['sample_int_interval_perc']['value']
        else:
            int_n_cutoff = self.acceptance_criteria['site_int_n']['value']
            int_sigma_cutoff = self.acceptance_criteria['site_int_sigma']['value']
            int_sigma_perc_cutoff = self.acceptance_criteria['site_int_sigma_perc']['value']
            int_interval_cutoff = self.acceptance_criteria['site_int_interval_uT']['value']
            int_interval_perc_cutoff = self.acceptance_criteria['site_int_interval_perc']['value']

        N = len(list(Grade_As.keys()))
        if N <= 1:
            thellier_interpreter_pars['pass_or_fail'] = 'fail'
            thellier_interpreter_pars['fail_criteria'].append("int_n")
            return(thellier_interpreter_pars)

        Best_interpretations, best_mean, best_std = self.find_sample_min_std(
            Grade_As)
        sample_acceptable_min, sample_acceptable_min_std, sample_acceptable_max, sample_acceptable_max_std = self.find_sample_min_max_interpretation(
            Grade_As)
        sample_int_interval_uT = sample_acceptable_max - sample_acceptable_min
        sample_int_interval_perc = 100 * \
            ((sample_acceptable_max - sample_acceptable_min) / best_mean)
        thellier_interpreter_pars['stdev_opt_interpretations'] = Best_interpretations
        thellier_interpreter_pars['stdev-opt']['B'] = best_mean
        thellier_interpreter_pars['stdev-opt']['std'] = best_std
        thellier_interpreter_pars['stdev-opt']['std_perc'] = 100. * \
            (best_std / best_mean)
        thellier_interpreter_pars['min-value']['B'] = sample_acceptable_min
        thellier_interpreter_pars['min-value']['std'] = sample_acceptable_min_std
        thellier_interpreter_pars['max-value']['B'] = sample_acceptable_max
        thellier_interpreter_pars['max-value']['std'] = sample_acceptable_max_std
        thellier_interpreter_pars['sample_int_interval_uT'] = sample_int_interval_uT
        thellier_interpreter_pars['sample_int_interval_perc'] = sample_int_interval_perc

        if N < int_n_cutoff:
            thellier_interpreter_pars['pass_or_fail'] = 'fail'
            thellier_interpreter_pars['fail_criteria'].append("int_n")

        pass_int_sigma, pass_int_sigma_perc = True, True
        pass_int_interval, pass_int_interval_perc = True, True

        if not (int_sigma_cutoff == -999 and int_sigma_perc_cutoff == -999):
            if best_std <= int_sigma_cutoff * 1e6 and int_sigma_cutoff != -999:
                pass_sigma = True
            else:
                pass_sigma = False
            if 100. * (best_std / best_mean) <= int_sigma_perc_cutoff and int_sigma_perc_cutoff != -999:
                pass_sigma_perc = True
            else:
                pass_sigma_perc = False
            if not (pass_sigma or pass_sigma_perc):
                thellier_interpreter_pars['pass_or_fail'] = 'fail'
                thellier_interpreter_pars['fail_criteria'].append("int_sigma")

        if not (int_interval_cutoff == -999 and int_interval_perc_cutoff == -999):
            if sample_int_interval_uT <= int_interval_perc_cutoff and int_interval_perc_cutoff != -999:
                pass_interval = True
            else:
                pass_interval = False
            if sample_int_interval_perc <= int_interval_perc_cutoff and int_interval_perc_cutoff != -999:
                pass_interval_perc = True
            else:
                pass_interval_perc = False
            if not (pass_interval or pass_interval_perc):
                thellier_interpreter_pars['pass_or_fail'] = 'fail'
                thellier_interpreter_pars['fail_criteria'].append(
                    "int_interval")

        return(thellier_interpreter_pars)


Instruction:
Write a Python 3 function for
taking in a dictionary and a mapping which contains new key names and returns a new dictionary with the updated key names.

Response:
def mapping(dictionary, mapping):
    """
    takes in a dictionary and a mapping which contains new key names,
    and returns a new dictionary with the updated key names, i.e.:
    dictionary = {'a': 1, 'b': 2, 'c': 3}
    mapping = {'a': 'aa', 'c': 'cc'}
    mapped_dictionary = mapping(dictionary, mapping)
    mapped_dictionary = {'aa': 1, b, 2, 'cc': 3}
    """
    mapped_dictionary = {}
    for key, value in dictionary.items():
        if key in list(mapping.keys()):
            new_key = mapping[key]
            # if there is already a mapped value, try to figure out which value to use
            # (i.e., if both er_synthetic_name and er_specimen_name are in one measurement file)
            if new_key in mapped_dictionary:
                if hasattr(value, 'any'):
                    if not value.any():
                        # if new value is null, leave the old value there
                        continue
                    if hasattr(mapped_dictionary, 'any'):
                        if value.any() and not mapped_dictionary[new_key].any():
                            # choose the one that has a non-null value
                            mapped_dictionary[new_key] = value
                        elif value.any() and mapped_dictionary[new_key].any():
                            # if both have values, choose which one to replace and warn
                            #print('-W- Two possible values found for {}'.format(new_key))
                            #print('    Replacing {} with {}'.format(mapped_dictionary[new_key], value))
                            mapped_dictionary[new_key] = value
                    else:
                        if value.any() and not mapped_dictionary[new_key].any():
                            # choose the one that has a non-null value
                            mapped_dictionary[new_key] = value
                        elif value.any() and mapped_dictionary[new_key].any():
                            # if both have values, choose which one to replace and warn
                            #print('-W- Two possible values found for {}'.format(new_key))
                            #print('    Replacing {} with {}'.format(mapped_dictionary[new_key], value))
                            mapped_dictionary[new_key] = value
                else:
                    if not value:
                        # if new value is null, leave the old value there
                        continue
                    elif value and not mapped_dictionary[new_key]:
                        # choose the one that has a non-null value
                        mapped_dictionary[new_key] = value
                    elif value and mapped_dictionary[new_key]:
                        # if both have values, choose which one to replace and warn
                        #print('-W- Two possible values found for {}'.format(new_key))
                        #print('    Replacing {} with {}'.format(mapped_dictionary[new_key], value))
                        mapped_dictionary[new_key] = value
            # if there is no mapped_value already:
            else:
                mapped_dictionary[new_key] = value
        else:
            # if this line is left in, it gives everything from the original dictionary
            mapped_dictionary[key] = value
    return mapped_dictionary


Instruction:
Write a Python 3 script for
making a full mapping for 2 --> 3 columns. Output the mapping to json in the specified file_path. Note: This file is currently called maps.py, full path is PmagPy/pmagpy/mapping/maps.py. Parameters ---------- file_path : string with full file path to dump mapping json. Returns --------- maps : nested dictionary with format {table_name: {magic2_col_name: magic3_col_name, ...}, ...}

Response:
def cache_mappings(file_path):
    """
    Make a full mapping for 2 --> 3 columns.
    Output the mapping to json in the specified file_path.
    Note: This file is currently called maps.py,
    full path is PmagPy/pmagpy/mapping/maps.py.

    Parameters
    ----------
    file_path : string with full file path to dump mapping json.

    Returns
    ---------
    maps : nested dictionary with format {table_name: {magic2_col_name: magic3_col_name, ...}, ...}
    """
    def get_2_to_3(dm_type, dm):
        table_names3_2_table_names2 = {'measurements': ['magic_measurements'],
                                       'locations': ['er_locations'],
                                       'sites': ['er_sites', 'pmag_sites'],
                                       'samples': ['er_samples', 'pmag_samples'],
                                       'specimens': ['er_specimens', 'pmag_specimens'],
                                       'ages': ['er_ages'],
                                       'criteria': ['pmag_criteria'],
                                       'images': ['er_images'],
                                       'contribution': []}
        table_names3 = table_names3_2_table_names2[dm_type]
        dictionary = {}
        for label, row in dm.iterrows():
            # if there are one or more corresponding 2.5 columns:
            if isinstance(row['previous_columns'], list):
                for previous_values in row['previous_columns']:
                    previous_table = previous_values['table']
                    previous_value = previous_values['column']
                    if previous_table in table_names3:
                        add_to_dict(previous_value, label, dictionary)
                    elif previous_table in ["pmag_results", "rmag_results"]:
                        if label not in dictionary.values():
                            if previous_value not in dictionary.keys():
                                add_to_dict(previous_value, label, dictionary)
        return dictionary

    def add_to_dict(key, value, dictionary):
        if key in dictionary:
            if value != dictionary[key]:
                print('W- OVERWRITING')
                print('was:', key, dictionary[key])
                print('now:', key, value)
        dictionary[key] = value

    # begin
    data_model = DataModel()
    maps = {}
    for table_name in data_model.dm:
        dm = data_model.dm[table_name]
        new_mapping = get_2_to_3(table_name, dm)
        maps[table_name] = new_mapping
    # write maps out to file
    f = open(file_path, 'w')
    f.write("all_maps = ")
    json.dump(maps, f)
    f.close()
    return maps


Instruction:
Given the following Python 3 function, write the documentation
def get_thellier_gui_meas_mapping(input_df, output=2):
    if int(output) == 2:
        thellier_gui_meas3_2_meas2_map = meas_magic3_2_magic2_map.copy()
        if 'treat_step_num' in input_df.columns:
            thellier_gui_meas3_2_meas2_map.update(
                {'treat_step_num': 'measurement_number'})
            thellier_gui_meas3_2_meas2_map.pop('measurement')
        return thellier_gui_meas3_2_meas2_map
    # 2 --> 3
    else:
        thellier_gui_meas2_2_meas3_map = meas_magic2_2_magic3_map.copy()
        if 'measurement' in input_df.columns:
            thellier_gui_meas2_2_meas3_map.pop('measurement_number')
            try:
                res = int(input_df.iloc[0]['measurement_number'])
                if res < 100:
                    thellier_gui_meas2_2_meas3_map['measurement_number'] = 'treat_step_num'
            except ValueError as ex:
                pass
        return thellier_gui_meas2_2_meas3_map

Response: Returns the appropriate mapping for translating measurements in Thellier GUI to MagIC records.


Instruction:
Write a Python 3 function for
converting a dataframe with measurement names to MagIC 2 or 3 or vice versa.

Response:
def convert_meas_df_thellier_gui(meas_df_in, output):
    """
    Take a measurement dataframe and convert column names
    from MagIC 2 --> 3 or vice versa.
    Use treat_step_num --> measurement_number if available,
    otherwise measurement --> measurement_number.

    Parameters
    ----------
    meas_df_in : pandas DataFrame
        input dataframe with measurement data
    output : int
        output to MagIC 2 or MagIC 3
    """
    output = int(output)
    meas_mapping = get_thellier_gui_meas_mapping(meas_df_in, output)
    meas_df_out = meas_df_in.rename(columns=meas_mapping)
    if 'measurement' not in meas_df_out.columns:
        meas_df_out['measurement'] = meas_df_in['measurement']
    return meas_df_out


Instruction:
Write a Python 3 script for
converting measurments tables from magic 2 to 3

Response:
def convert_meas(direction, Rec):
    """
    converts measurments tables from magic 2 to 3 (direction=magic3)
    or from model 3 to 2.5 (direction=magic2) [not available]
    """
    if direction == 'magic3':
        columns = meas_magic2_2_magic3_map
        MeasRec = {}
        for key in columns:
            if key in list(Rec.keys()):
                # transfer info and change column name to data model 3.0
                MeasRec[columns[key]] = Rec[key]
        return MeasRec
    else:  # haven't added this way yet
        pass


Instruction:
Write a Python 3 function that can
convert MagIC site headers to short or readable tables for a figure.

Response:
def convert_site_dm3_table_intensity(sites_df):
    """
    Convert MagIC site headers to short/readable
    headers for a figure (used by ipmag.sites_extract)
    Intensity data only.

    Parameters
    ----------
    sites_df : pandas DataFrame
        sites information

    Returns
    ---------
    int_df : pandas DataFrame
        intensity site data with easily readable headers
    """
    # now for the intensities
    has_vadms, has_vdms = False, False
    if 'int_abs' not in sites_df:
        sites_df['int_abs'] = None
    if 'int_n_samples' not in sites_df:
        sites_df['int_n_samples'] = None
    int_df = sites_df.copy().dropna(subset=['int_abs'])
    int_df['int_n_samples'] = int_df['int_n_samples'].values.astype('int')
    if len(int_df) > 0:
        int_df['int_abs_uT'] = 1e6*int_df.int_abs.values  # convert to uT
        int_df['int_abs_sigma_uT'] = 1e6 * \
            int_df.int_abs_sigma.values  # convert to uT
        int_df['int_abs_uT'] = int_df['int_abs_uT'].values.astype('int')
        int_df['int_abs_sigma_uT'] = int_df['int_abs_sigma_uT'].values.astype(
            'int')
        int_df['int_abs_sigma_perc'] = int_df['int_abs_sigma_perc'].values.astype(
            'int')

        IntCols = ["Site", "N", "B", "B sigma", "sigma (%)"]
        if 'vadm' in int_df.columns:
            test_vadm = int_df.dropna(subset=['vadm'])
            if len(test_vadm) > 0:
                has_vadms = True

        if 'vdm' in int_df.columns:
            test_vdm = int_df.dropna(subset=['vdm'])
            if len(test_vdm) > 0:
                has_vdms = True

        if has_vadms:
            IntCols.append("VADM")
            IntCols.append("VADM sigma")
        if has_vdms:
            IntCols.append("VDM")
            IntCols.append("VDM sigma")
        if not has_vadms and not has_vdms:
            int_df = int_df[['site', 'int_n_samples', 'int_abs_uT', 'int_abs_sigma_uT',
                             'int_abs_sigma_perc']]
        if has_vadms and not has_vdms:
            int_df.sort_values(by=['site', 'vadm'],
                               ascending=False, inplace=True)
            int_df.drop_duplicates(subset=['int_abs_uT', 'site'], inplace=True)

            int_df['vadm_ZAm2'] = 1e-21*int_df.vadm.values
            int_df['vadm_sigma_ZAm2'] = 1e-21*int_df.vadm_sigma.values
            int_df = int_df[['site', 'int_n_samples', 'int_abs_uT', 'int_abs_sigma_uT',
                             'int_abs_sigma_perc', 'vadm_ZAm2', 'vadm_ZAm2_sigma']]
        if not has_vadms and has_vdms:
            int_df.sort_values(by=['site', 'vdm'],
                               ascending=False, inplace=True)
            int_df.drop_duplicates(subset=['int_abs_uT', 'site'], inplace=True)
            int_df['vdm_ZAm2'] = 1e-21*int_df.vdm.values()
            int_df['vdm_sigma_ZAm2'] = 1e-21*int_df.vdm_sigma.values()

            int_df = int_df[['site', 'int_n_samples', 'int_abs_uT', 'int_abs_sigma_uT',
                             'int_abs_sigma_perc', 'vdm_ZAm2', 'vdm_ZAm2_sigma']]
        if has_vadms and has_vdms:
            int_df.sort_values(by=['site', 'vadm'],
                               ascending=False, inplace=True)
            int_df.drop_duplicates(subset=['int_abs_uT', 'site'], inplace=True)
            int_df['vadm_ZAm2'] = 1e-21*int_df.vadm.values
            int_df['vadm_sigma_ZAm2'] = 1e-21*int_df.vadm_sigma.values
            int_df['vdm_ZAm2'] = 1e-21*int_df.vdm.values
            int_df['vdm_sigma_ZAm2'] = 1e-21*int_df.vdm_sigma.values
            int_df = int_df[['site', 'int_n_samples', 'int_abs_uT', 'int_abs_sigma_uT',
                             'int_abs_sigma_perc', 'vadm_ZAm2', 'vadm_sigma_ZAm2', 'vdm_ZAm2', 'vdm_sigma_ZAm2']]
        int_df.columns = IntCols
        int_df.sort_values(by=['Site'], inplace=True, ascending=True)
        int_df.fillna(value='', inplace=True)
    return int_df


Instruction:
Write a Python 3 function for
converting MagIC site headers to short or readable headers for a figure.

Response:
def convert_site_dm3_table_directions(sites_df):
    """
    Convert MagIC site headers to short/readable
    headers for a figure (used by ipmag.sites_extract)
    Directional table only.

    Parameters
    ----------
    sites_df : pandas DataFrame
        sites information

    Returns
    ---------
    dir_df : pandas DataFrame
        directional site data with easily readable headers
    """
    # directional
    # do directional stuff first
    # a few things need cleaning up
    dir_df = sites_df.copy().dropna(
        subset=['dir_dec', 'dir_inc'])  # delete blank directions
    # sort by absolute value of vgp_lat in order to eliminate duplicate rows for
    # directions put in by accident on intensity rows
    DirCols = ["Site", "TC (%)", "Dec.", "Inc.", "N",
               "k    ", "R", "a95", "VGP Lat", "VGP Long"]
    columns = ['site', 'dir_tilt_correction', 'dir_dec', 'dir_inc',
               'dir_n_samples', 'dir_k', 'dir_r', 'dir_alpha95', 'vgp_lat', 'vgp_lon']
    dm3_to_readable = dict(zip(columns, DirCols))
    if len(dir_df) > 0:

        for col in ['dir_n_samples', 'dir_tilt_correction']:
            if col in dir_df.columns:
                dir_df[col] = dir_df[col].values.astype('int')

        columns = dir_df.columns.intersection(columns)
        has_vgps = False
        if 'vgp_lat' in dir_df.columns:
            test_vgp = dir_df.dropna(subset=['vgp_lat', 'vgp_lon'])
            if len(test_vgp) > 0:
                has_vgps = True
        if has_vgps:
            dir_df['vgp_lat_abs'] = dir_df.vgp_lat.abs()
            dir_df.sort_values(by=['site', 'vgp_lat_abs'],
                               ascending=False, inplace=True)
            dir_df = dir_df[columns]
    # this will take the first record for each site's directions (including VGP lat if present)
            dir_df.drop_duplicates(
                subset=['dir_dec', 'dir_inc', 'site'], inplace=True)
        else:
            dir_df.drop_duplicates(
                subset=['dir_dec', 'dir_inc', 'site'], inplace=True)
            dir_df = dir_df[['site', 'dir_tilt_correction', 'dir_dec', 'dir_inc',
                             'dir_n_samples', 'dir_k', 'dir_r', 'dir_alpha95']]
        dir_df.rename(dm3_to_readable, axis='columns', inplace=True)
        dir_df.sort_values(by=['Site'], inplace=True, ascending=True)
        new_cols = list(dir_df.columns.drop('Site'))
        dir_df = dir_df[['Site'] + new_cols]
    return dir_df


Instruction:
Create a Python 3 function to
convert MagIC specimen dataframe to short or readable format for a figure

Response:
def convert_specimen_dm3_table(spec_df):
    """
    Convert MagIC specimen headers to short/readable
    headers for a figure (used by ipmag.specimens_extract)
    """
    from pmagpy import data_model3 as dm3
    # get the data model
    dm = dm3.DataModel()
    # get the specimen absolute intensity column headers
    meas_group = ['meas_step_min', 'meas_step_max', 'meas_step_unit']
    pint_group = dm.get_group_headers('specimens', 'Paleointensity')
    arai_group = dm.get_group_headers(
        'specimens', 'Paleointensity Arai Statistics')
    # filter out the relative intensity stuff
    dm3_columns = list(meas_group)+list(pint_group)+list(arai_group)
    dm3_columns = filter(lambda x: '_rel' not in x, dm3_columns)
    # apply to specimen dataframe
    meas_group_columns = ['meas_step_min', 'meas_step_max', 'meas_step_unit']
    pint_group_columns = list(spec_df.columns.intersection(pint_group))
    arai_group_columns = list(spec_df.columns.intersection(arai_group))
    columns = ['specimen', 'sample']+meas_group_columns + \
        pint_group_columns+arai_group_columns
    spec_df = spec_df.copy()[columns]
    muT_list = ['int_abs', 'int_abs_sigma', 'int_treat_dc_field']
    meas_list = ['meas_step_min', 'meas_step_max']
    for el in muT_list:
        if el in columns:
            spec_df[el] = 1e6*spec_df[el]
    if 'meas_step_unit' in columns:
        for el in meas_list:
            spec_df.loc[spec_df['meas_step_unit'] == 'K', el] = spec_df[el]-273
            spec_df.loc[spec_df['meas_step_unit'] == 'T', el] = 1e3*spec_df[el]
        spec_df.loc[spec_df['meas_step_unit'] == 'K', 'meas_step_unit'] = 'C'
        spec_df.loc[spec_df['meas_step_unit'] == 'T', 'meas_step_unit'] = 'mT'
        spec_df['meas_step_min'] = spec_df['meas_step_min'].astype('int')
        spec_df['meas_step_max'] = spec_df['meas_step_max'].astype('int')
    dm3_columns = ['meas_step_min', 'meas_step_max', 'meas_step_unit', 'int_abs', 'int_abs_sigma',
                   'int_abs_sigma_perc', 'int_n_measurements', 'int_corr', 'int_corr_cooling_rate',
                   'int_corr_aniso', 'int_corr_nlt', 'int_corr_arm', 'int_viscosity_index', 'int_treat_dc_field',
                   'int_b', 'int_b_sigma', 'int_b_beta', 'int_rsc', 'int_f', 'int_fvds', 'int_frac',
                   'int_g', 'int_gmax', 'int_q', 'int_w', 'int_k', 'int_k_sse', 'int_k_prime', 'int_k_prime_sse',
                   'int_scat', 'int_r2_corr', 'int_r2_det', 'int_z', 'int_z_md']
    table_columns = ['Min', 'Max', 'Units', 'B (uT)', 'sigma', 'percent', 'N', 'c/u', 'CR', 'Aniso.', 'NLT', 'AARM', 'VI', 'Lab Field',
                     'b', 'b sigma', 'beta', 'R2', 'f', 'fvds', 'frac', 'g', 'gap max', 'q', 'w', 'k', 'k sse', 'k prime', 'k prime sse',
                     'scat', 'r2 corr', 'r2 det', 'Z', 'Z md']
    spec_mapping = dict(list(zip(dm3_columns, table_columns)))
    spec_df_out = spec_df.rename(columns=spec_mapping)
    if 'N' in spec_df_out.columns:
        spec_df_out['N'] = spec_df_out['N'].astype('int')
    if 'Lab Field' in spec_df_out.columns:
        spec_df_out['Lab Field'] = spec_df_out['Lab Field'].round().astype('int')
    return spec_df_out


Instruction:
Can you write a function in Python 3 where it
names sufar4-asc_magic.py DESCRIPTION converts ascii files generated by SUFAR ver.4.0 to MagIC formated files for use with PmagPy plotting software SYNTAX sufar4-asc_magic.py -h [command line options] OPTIONS -h: prints the help message and quits -f FILE: specify .asc input file name -fsp SINFILE: specify er_specimens input file with location, sample, site, etc. information -F MFILE: specify measurements output file -Fa AFILE: specify rmag_anisotropy output file # MagIC 2 only -Fsi SFILE: specify specimens output file -usr USER: specify who made the measurements -loc LOC: specify location name for study -ins INST: specify instrument used -spc SPEC: specify number of characters to specify specimen from sample -ncn NCON: specify naming convention: default is #2 below -k15 : specify static 15 position mode - default is spinning -new : replace all existing magic files DEFAULTS AFILE: rmag_anisotropy.txt # MagIC 2 only SFILE: default is to create new specimen file USER: "" LOC: "unknown" INST: "" SPEC: 0 sample name is same as site (if SPEC is 1, sample is all but last character) appends to specimen/sample/site files Sample naming convention: [1] XXXXY: where XXXX is an arbitrary length site designation and Y is the single character sample designation. e.g., TG001a is the first sample from site TG001. [default] [2] XXXX-YY: YY sample from site XXXX (XXX, YY of arbitary length) [3] XXXX.YY: YY sample from site XXXX (XXX, YY of arbitary length) [4-Z] XXXX[YYY]: YYY is sample designation with Z characters from site XXX [5] site name same as sample [6] site name entered in site_name column in the orient.txt format input file -- NOT CURRENTLY SUPPORTED [7-Z] [XXXX]YYY: XXXX is site designation with Z characters with sample name XXXXYYYY NB: all others you will have to customize your self or e-mail ltauxe@ucsd.edu for help. [8] This is a synthetic [9] ODP naming convention

Response:
def main():
    """
    NAME
        sufar4-asc_magic.py

    DESCRIPTION
        converts ascii files generated by SUFAR ver.4.0 to MagIC formated
        files for use with PmagPy plotting software

    SYNTAX
        sufar4-asc_magic.py -h [command line options]

    OPTIONS
        -h: prints the help message and quits
        -f FILE: specify .asc input file name
        -fsp SINFILE: specify er_specimens input file with location, sample, site, etc. information
        -F MFILE: specify measurements output file
        -Fa AFILE: specify rmag_anisotropy output file # MagIC 2 only
        -Fsi SFILE: specify specimens output file
        -usr USER: specify who made the measurements
        -loc LOC: specify location name for study
        -ins INST: specify instrument used
        -spc SPEC: specify number of characters to specify specimen from sample
        -ncn NCON:  specify naming convention: default is #2 below
        -k15 : specify static 15 position mode - default is spinning
        -new : replace all existing magic files

    DEFAULTS
        AFILE: rmag_anisotropy.txt  # MagIC 2 only
        SFILE: default is to create new specimen file
        USER: ""
        LOC: "unknown"
        INST: ""
        SPEC: 0  sample name is same as site (if SPEC is 1, sample is all but last character)
        appends to  specimen/sample/site files
       Sample naming convention:
            [1] XXXXY: where XXXX is an arbitrary length site designation and Y
                is the single character sample designation.  e.g., TG001a is the
                first sample from site TG001.    [default]
            [2] XXXX-YY: YY sample from site XXXX (XXX, YY of arbitary length)
            [3] XXXX.YY: YY sample from site XXXX (XXX, YY of arbitary length)
            [4-Z] XXXX[YYY]:  YYY is sample designation with Z characters from site XXX
            [5] site name same as sample
            [6] site name entered in site_name column in the orient.txt format input file  -- NOT CURRENTLY SUPPORTED
            [7-Z] [XXXX]YYY:  XXXX is site designation with Z characters with sample name XXXXYYYY
            NB: all others you will have to customize your self
                 or e-mail ltauxe@ucsd.edu for help.
            [8] This is a synthetic
            [9] ODP naming convention

    """

    args = sys.argv
    if '-h' in args:
        print(main.__doc__)
        sys.exit()

    dataframe = extractor.command_line_dataframe([ ['WD', False, '.'], ['ID', False, ''],
                                                   ['usr', False, ''], ['ncn', False, '1'],
                                                   ['k15', False, False], ['ins', False, ''],
                                                   ['f', True, ''], ['F', False, 'measurements.txt'],
                                                   ['Fa', False, 'rmag_anisotropy.txt'],
                                                   ['Fsi', False, 'specimens.txt'],
                                                   ['loc', False, 'unknown'], ['spc', False, 0],
                                                   ['fsi', False, None], ['DM', False, 3] ])
    #'WD', 'ID', 'usr', 'ncn', 'k15', 'ins', 'f', 'F', 'Fa', 'Fsi', 'loc', 'spc',
    checked_args = extractor.extract_and_check_args(args, dataframe)
    output_dir_path, input_dir_path, user, sample_naming_con, static_15_position_mode, instrument, ascfile, meas_output, aniso_output, spec_outfile, locname, specnum, spec_infile, data_model_num = extractor.get_vars(['WD', 'ID', 'usr', 'ncn', 'k15', 'ins', 'f', 'F', 'Fa', 'Fsi', 'loc', 'spc', 'fsi', 'DM'], checked_args)

    convert.sufar4(ascfile, meas_output, aniso_output, spec_infile,
                   spec_outfile, specnum=specnum, sample_naming_con=sample_naming_con,
                   user=user, locname=locname, instrument=instrument,
                   static_15_position_mode=static_15_position_mode, dir_path=output_dir_path,
                   input_dir_path=input_dir_path, data_model_num=data_model_num)


Instruction:
Write a Python 3 function for
naming make_magic_plots.py DESCRIPTION inspects magic directory for available plots. SYNTAX make_magic_plots.py [command line options] INPUT magic files OPTIONS -h prints help message and quits -f FILE specifies input file name -fmt [png,eps,svg,jpg,pdf] specify format, default is png

Response:
def main():
    """
    NAME
        make_magic_plots.py

    DESCRIPTION
    inspects magic directory for available plots.

    SYNTAX
        make_magic_plots.py [command line options]

    INPUT
        magic files

    OPTIONS
        -h prints help message and quits
        -f FILE specifies input file name
        -fmt [png,eps,svg,jpg,pdf] specify format, default is png
    """
    dirlist = ['./']
    dir_path = os.getcwd()
    names = os.listdir(dir_path)
    for n in names:
        if 'Location' in n:
            dirlist.append(n)
    if '-fmt' in sys.argv:
        ind = sys.argv.index("-fmt")
        fmt = sys.argv[ind+1]
    else:
        fmt = 'png'
    if '-f' in sys.argv:
        ind = sys.argv.index("-f")
        filelist = [sys.argv[ind+1]]
    else:
        filelist = os.listdir(dir_path)
    if '-h' in sys.argv:
        print(main.__doc__)
        sys.exit()
    for loc in dirlist:
        print('working on: ', loc)
        os.chdir(loc)  # change working directories to each location
        crd = 's'
        if 'er_samples.txt' in filelist:  # find coordinate systems
            samps, file_type = pmag.magic_read(
                'er_samples.txt')  # read in data
            # get all none blank sample orientations
            Srecs = pmag.get_dictitem(samps, 'sample_azimuth', '', 'F')
            if len(Srecs) > 0:
                crd = 'g'
        if 'magic_measurements.txt' in filelist:  # start with measurement data
            print('working on measurements data')
            data, file_type = pmag.magic_read(
                'magic_measurements.txt')  # read in data
            if loc == './':
                # get all the blank location names from data file
                data = pmag.get_dictitem(data, 'er_location_name', '', 'T')
            # looking for  zeq_magic possibilities
            # get all none blank method codes
            AFZrecs = pmag.get_dictitem(
                data, 'magic_method_codes', 'LT-AF-Z', 'has')
            # get all none blank method codes
            TZrecs = pmag.get_dictitem(
                data, 'magic_method_codes', 'LT-T-Z', 'has')
            # get all none blank method codes
            MZrecs = pmag.get_dictitem(
                data, 'magic_method_codes', 'LT-M-Z', 'has')
            # get all dec measurements
            Drecs = pmag.get_dictitem(data, 'measurement_dec', '', 'F')
            # get all dec measurements
            Irecs = pmag.get_dictitem(data, 'measurement_inc', '', 'F')
            Mkeys = ['measurement_magnitude', 'measurement_magn_moment',
                     'measurement_magn_volume', 'measurement_magn_mass']
            for key in Mkeys:
                Mrecs = pmag.get_dictitem(
                    data, key, '', 'F')  # get intensity data
                if len(Mrecs) > 0:
                    break
            # potential for stepwise demag curves
            if len(AFZrecs) > 0 or len(TZrecs) > 0 or len(MZrecs) > 0 and len(Drecs) > 0 and len(Irecs) > 0 and len(Mrecs) > 0:
                print('zeq_magic.py -fsp pmag_specimens.txt -sav -fmt ' +
                      fmt+' -crd '+crd)
                os.system('zeq_magic.py -sav -fmt '+fmt+' -crd '+crd)
            # looking for  thellier_magic possibilities
            if len(pmag.get_dictitem(data, 'magic_method_codes', 'LP-PI-TRM', 'has')) > 0:
                print('thellier_magic.py -fsp pmag_specimens.txt -sav -fmt '+fmt)
                os.system('thellier_magic.py -sav -fmt '+fmt)
            # looking for hysteresis possibilities
            if len(pmag.get_dictitem(data, 'magic_method_codes', 'LP-HYS', 'has')) > 0:  # find hyst experiments
                print('quick_hyst.py -sav -fmt '+fmt)
                os.system('quick_hyst.py -sav -fmt '+fmt)
        if 'pmag_results.txt' in filelist:  # start with measurement data
            data, file_type = pmag.magic_read(
                'pmag_results.txt')  # read in data
            print('number of datapoints: ', len(data))
            if loc == './':
                # get all the concatenated location names from data file
                data = pmag.get_dictitem(data, 'er_location_names', ':', 'has')
            print('number of datapoints: ', len(data), loc)
            print('working on pmag_results directions')
            SiteDIs = pmag.get_dictitem(
                data, 'average_dec', "", 'F')  # find decs
            print('number of directions: ', len(SiteDIs))
            SiteDIs = pmag.get_dictitem(
                SiteDIs, 'average_inc', "", 'F')  # find decs and incs
            print('number of directions: ', len(SiteDIs))
            # only individual results - not poles
            SiteDIs = pmag.get_dictitem(SiteDIs, 'data_type', 'i', 'has')
            print('number of directions: ', len(SiteDIs))
            # tilt corrected coordinates
            SiteDIs_t = pmag.get_dictitem(
                SiteDIs, 'tilt_correction', '100', 'T')
            print('number of directions: ', len(SiteDIs))
            if len(SiteDIs_t) > 0:
                print('eqarea_magic.py -sav -crd t -fmt '+fmt)
                os.system('eqarea_magic.py -sav -crd t -fmt '+fmt)
            elif len(SiteDIs) > 0 and 'tilt_correction' not in SiteDIs[0].keys():
                print('eqarea_magic.py -sav -fmt '+fmt)
                os.system('eqarea_magic.py -sav -fmt '+fmt)
            else:
                SiteDIs_g = pmag.get_dictitem(
                    SiteDIs, 'tilt_correction', '0', 'T')  # geographic coordinates
                if len(SiteDIs_g) > 0:
                    print('eqarea_magic.py -sav -crd g -fmt '+fmt)
                    os.system('eqarea_magic.py -sav -crd g -fmt '+fmt)
                else:
                    SiteDIs_s = pmag.get_dictitem(
                        SiteDIs, 'tilt_correction', '-1', 'T')  # sample coordinates
                    if len(SiteDIs_s) > 0:
                        print('eqarea_magic.py -sav -crd s -fmt '+fmt)
                        os.system('eqarea_magic.py -sav -crd s -fmt '+fmt)
                    else:
                        SiteDIs_x = pmag.get_dictitem(
                            SiteDIs, 'tilt_correction', '', 'T')  # no coordinates
                        if len(SiteDIs_x) > 0:
                            print('eqarea_magic.py -sav -fmt '+fmt)
                            os.system('eqarea_magic.py -sav -fmt '+fmt)
            print('working on pmag_results VGP map')
            VGPs = pmag.get_dictitem(
                SiteDIs, 'vgp_lat', "", 'F')  # are there any VGPs?
            if len(VGPs) > 0:  # YES!
                os.system(
                    'vgpmap_magic.py -prj moll -res c -sym ro 5 -sav -fmt png')
            print('working on pmag_results intensities')
            os.system(
                'magic_select.py -f pmag_results.txt -key data_type i T -F tmp.txt')
            os.system(
                'magic_select.py -f tmp.txt -key average_int 0. has -F tmp1.txt')
            os.system(
                "grab_magic_key.py -f tmp1.txt -key average_int | awk '{print $1*1e6}' >tmp2.txt")
            data, file_type = pmag.magic_read('tmp1.txt')  # read in data
            locations = pmag.get_dictkey(data, 'er_location_names', "")
            histfile = 'LO:_'+locations[0]+'_intensities_histogram:_.'+fmt
            os.system(
                "histplot.py -b 1 -xlab 'Intensity (uT)' -sav -f tmp2.txt -F " + histfile)
            print(
                "histplot.py -b 1 -xlab 'Intensity (uT)' -sav -f tmp2.txt -F " + histfile)
            os.system('rm tmp*.txt')
        if 'rmag_hysteresis.txt' in filelist:  # start with measurement data
            print('working on rmag_hysteresis')
            data, file_type = pmag.magic_read(
                'rmag_hysteresis.txt')  # read in data
            if loc == './':
                # get all the blank location names from data file
                data = pmag.get_dictitem(data, 'er_location_name', '', 'T')
            hdata = pmag.get_dictitem(data, 'hysteresis_bcr', '', 'F')
            hdata = pmag.get_dictitem(hdata, 'hysteresis_mr_moment', '', 'F')
            hdata = pmag.get_dictitem(hdata, 'hysteresis_ms_moment', '', 'F')
            # there are data for a dayplot
            hdata = pmag.get_dictitem(hdata, 'hysteresis_bc', '', 'F')
            if len(hdata) > 0:
                print('dayplot_magic.py -sav -fmt '+fmt)
                os.system('dayplot_magic.py -sav -fmt '+fmt)
    # if 'er_sites.txt' in filelist: # start with measurement data
        #    print 'working on er_sites'
            #os.system('basemap_magic.py -sav -fmt '+fmt)
        if 'rmag_anisotropy.txt' in filelist:  # do anisotropy plots if possible
            print('working on rmag_anisotropy')
            data, file_type = pmag.magic_read(
                'rmag_anisotropy.txt')  # read in data
            if loc == './':
                # get all the blank location names from data file
                data = pmag.get_dictitem(data, 'er_location_name', '', 'T')
            # get specimen coordinates
            sdata = pmag.get_dictitem(
                data, 'anisotropy_tilt_correction', '-1', 'T')
            # get specimen coordinates
            gdata = pmag.get_dictitem(
                data, 'anisotropy_tilt_correction', '0', 'T')
            # get specimen coordinates
            tdata = pmag.get_dictitem(
                data, 'anisotropy_tilt_correction', '100', 'T')
            if len(sdata) > 3:
                print('aniso_magic.py -x -B -crd s -sav -fmt '+fmt)
                os.system('aniso_magic.py -x -B -crd s -sav -fmt '+fmt)
            if len(gdata) > 3:
                os.system('aniso_magic.py -x -B -crd g -sav -fmt '+fmt)
            if len(tdata) > 3:
                os.system('aniso_magic.py -x -B -crd t -sav -fmt '+fmt)
        if loc != './':
            os.chdir('..')


Instruction:
Here you have a function in Python 3, explain what it does
def init_UI(self):
# --------------------------------------------------------------------------
    # Setup ScrolledPanel Ctrls---------------------------------------------
# --------------------------------------------------------------------------

    # ----------------------------------------------------------------------
        #  set ctrl size and style variables
    # ----------------------------------------------------------------------
        dw, dh = wx.DisplaySize()
        r1 = dw/1210.
        r2 = dw/640.

        self.GUI_RESOLUTION = min(r1, r2, 1)
        top_bar_2v_space = 5
        top_bar_h_space = 10
        spec_button_space = 10
        side_bar_v_space = 10

    # ----------------------------------------------------------------------
        #  set font size and style
    # ----------------------------------------------------------------------

        FONT_WEIGHT = 1
        if sys.platform.startswith('win'):
            FONT_WEIGHT = -1
        font1 = wx.Font(9+FONT_WEIGHT, wx.SWISS, wx.NORMAL,
                        wx.NORMAL, False, self.font_type)
        font2 = wx.Font(12+FONT_WEIGHT, wx.SWISS, wx.NORMAL,
                        wx.NORMAL, False, self.font_type)
        font = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT)
        font.SetPointSize(10+FONT_WEIGHT)

# --------------------------------------------------------------------------
    # Setup ScrolledPanel Ctrls---------------------------------------------
# --------------------------------------------------------------------------

    # ----------------------------------------------------------------------
        # Create Figures and FigCanvas objects.
    # ----------------------------------------------------------------------

        self.fig1 = Figure((5.*self.GUI_RESOLUTION, 5. *
                            self.GUI_RESOLUTION), dpi=self.dpi)
        self.canvas1 = FigCanvas(self.scrolled_panel, -1, self.fig1)
        self.toolbar1 = NavigationToolbar(self.canvas1)
        self.toolbar1.Hide()
        self.zijderveld_setting = "Zoom"
        self.toolbar1.zoom()
        self.canvas1.Bind(wx.EVT_RIGHT_DOWN, self.right_click_zijderveld)
        self.canvas1.Bind(wx.EVT_MIDDLE_DOWN, self.home_zijderveld)
        self.canvas1.Bind(wx.EVT_LEFT_DCLICK, self.on_zijd_select)
        self.canvas1.Bind(wx.EVT_RIGHT_DCLICK, self.on_zijd_mark)
        self.canvas1.Bind(wx.EVT_MOTION, self.on_change_zijd_mouse_cursor)
        self.canvas1.SetHelpText(dgh.zij_help)

        self.fig2 = Figure((2.5*self.GUI_RESOLUTION, 2.5 *
                            self.GUI_RESOLUTION), dpi=self.dpi)
        self.specimen_eqarea = self.fig2.add_subplot(111)
        draw_net(self.specimen_eqarea)
        self.canvas2 = FigCanvas(self.scrolled_panel, -1, self.fig2)
        self.toolbar2 = NavigationToolbar(self.canvas2)
        self.toolbar2.Hide()
        self.toolbar2.zoom()
        self.specimen_EA_setting = "Zoom"
        self.canvas2.Bind(wx.EVT_LEFT_DCLICK,
                          self.on_equalarea_specimen_select)
        self.canvas2.Bind(wx.EVT_RIGHT_DOWN,
                          self.right_click_specimen_equalarea)
        self.canvas2.Bind(wx.EVT_MOTION, self.on_change_specimen_mouse_cursor)
        self.canvas2.Bind(wx.EVT_MIDDLE_DOWN, self.home_specimen_equalarea)
        self.canvas2.SetHelpText(dgh.spec_eqarea_help)
        self.specimen_EA_xdata = []
        self.specimen_EA_ydata = []

        self.fig3 = Figure((2.5*self.GUI_RESOLUTION, 2.5 *
                            self.GUI_RESOLUTION), dpi=self.dpi)
        self.mplot = self.fig3.add_axes(
            [0.2, 0.15, 0.7, 0.7], frameon=True, facecolor='None')
        self.canvas3 = FigCanvas(self.scrolled_panel, -1, self.fig3)
        self.toolbar3 = NavigationToolbar(self.canvas3)
        self.toolbar3.Hide()
        self.toolbar3.zoom()
        self.MM0_setting = "Zoom"
        self.canvas3.Bind(wx.EVT_RIGHT_DOWN, self.right_click_MM0)
        self.canvas3.Bind(wx.EVT_MIDDLE_DOWN, self.home_MM0)
        self.canvas3.SetHelpText(dgh.MM0_help)

        self.fig4 = Figure((2.5*self.GUI_RESOLUTION, 2.5 *
                            self.GUI_RESOLUTION), dpi=self.dpi)
        self.canvas4 = FigCanvas(self.scrolled_panel, -1, self.fig4)
        self.toolbar4 = NavigationToolbar(self.canvas4)
        self.toolbar4.Hide()
        self.toolbar4.zoom()
        self.high_EA_setting = "Zoom"
        self.canvas4.Bind(wx.EVT_LEFT_DCLICK, self.on_equalarea_high_select)
        self.canvas4.Bind(wx.EVT_RIGHT_DOWN, self.right_click_high_equalarea)
        self.canvas4.Bind(wx.EVT_MOTION, self.on_change_high_mouse_cursor)
        self.canvas4.Bind(wx.EVT_MIDDLE_DOWN, self.home_high_equalarea)
        self.canvas4.SetHelpText(dgh.high_level_eqarea_help)
        self.old_pos = None
        self.high_EA_xdata = []
        self.high_EA_ydata = []
        self.high_level_eqarea = self.fig4.add_subplot(111)
        draw_net(self.high_level_eqarea)

    # ----------------------------------------------------------------------
        # High level Stats Sizer and Switch Stats Button
    # ----------------------------------------------------------------------

        self.stats_sizer = wx.StaticBoxSizer(wx.StaticBox(
            self.panel, wx.ID_ANY, "mean statistics"), wx.VERTICAL)

        for parameter in ['mean_type', 'dec', 'inc', 'alpha95', 'K', 'R', 'n_lines', 'n_planes']:
            COMMAND = "self.%s_window=wx.TextCtrl(self.scrolled_panel,style=wx.TE_CENTER|wx.TE_READONLY,size=(50*self.GUI_RESOLUTION,25))" % parameter
            exec(COMMAND)
            COMMAND = "self.%s_window.SetBackgroundColour(wx.WHITE)" % parameter
            exec(COMMAND)
            COMMAND = "self.%s_window.SetFont(font2)" % parameter
            exec(COMMAND)
            COMMAND = "self.%s_outer_window = wx.GridSizer(1,2,5*self.GUI_RESOLUTION,15*self.GUI_RESOLUTION)" % parameter
            exec(COMMAND)
            COMMAND = """self.%s_outer_window.AddMany([
                    (wx.StaticText(self.scrolled_panel,label='%s',style=wx.TE_CENTER),1,wx.EXPAND),
                    (self.%s_window, 1, wx.EXPAND)])""" % (parameter, parameter, parameter)
            exec(COMMAND)
            COMMAND = "self.stats_sizer.Add(self.%s_outer_window, 1, wx.ALIGN_LEFT|wx.EXPAND)" % parameter
            exec(COMMAND)

        self.switch_stats_button = wx.SpinButton(
            self.scrolled_panel, id=wx.ID_ANY, style=wx.SP_HORIZONTAL | wx.SP_ARROW_KEYS | wx.SP_WRAP, name="change stats")
        self.Bind(wx.EVT_SPIN, self.on_select_stats_button,
                  self.switch_stats_button)
        self.switch_stats_button.SetHelpText(dgh.switch_stats_btn_help)

# --------------------------------------------------------------------------
    #  Side Bar Options and Logger-----------------------------------------
# --------------------------------------------------------------------------

    # ----------------------------------------------------------------------
        # Create text_box for presenting the measurements
    # ----------------------------------------------------------------------

        self.logger = wx.ListCtrl(self.side_panel, id=wx.ID_ANY, size=(
            100*self.GUI_RESOLUTION, 100*self.GUI_RESOLUTION), style=wx.LC_REPORT)
        self.logger.SetFont(font1)
        self.logger.InsertColumn(0, 'i', width=25*self.GUI_RESOLUTION)
        self.logger.InsertColumn(1, 'Step', width=25*self.GUI_RESOLUTION)
        self.logger.InsertColumn(2, 'Tr', width=35*self.GUI_RESOLUTION)
        self.logger.InsertColumn(3, 'Dec', width=35*self.GUI_RESOLUTION)
        self.logger.InsertColumn(4, 'Inc', width=35*self.GUI_RESOLUTION)
        self.logger.InsertColumn(5, 'M', width=45*self.GUI_RESOLUTION)
        self.logger.InsertColumn(6, 'csd', width=45*self.GUI_RESOLUTION)
        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED,
                  self.on_click_listctrl, self.logger)
        self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK,
                  self.on_right_click_listctrl, self.logger)
        self.Bind(wx.EVT_LIST_ITEM_SELECTED,
                  self.on_select_measurement, self.logger)
        self.logger.SetHelpText(dgh.logger_help)

    # ----------------------------------------------------------------------
        #  select specimen box
    # ----------------------------------------------------------------------

        # Combo-box with a list of specimen
        self.specimens_box = wx.ComboBox(self.side_panel, id=wx.ID_ANY, value=self.s, size=(
            200*self.GUI_RESOLUTION, 25), choices=self.specimens, style=wx.CB_DROPDOWN | wx.TE_PROCESS_ENTER, name="specimen")
        self.Bind(wx.EVT_COMBOBOX, self.onSelect_specimen, self.specimens_box)
        self.Bind(wx.EVT_TEXT_ENTER, self.on_enter_specimen,
                  self.specimens_box)
        self.specimens_box.SetHelpText(dgh.specimens_box_help)

        # buttons to move forward and backwards from specimens
        self.nextbutton = wx.Button(
            self.side_panel, id=wx.ID_ANY, label='next', size=(100*self.GUI_RESOLUTION, 25))
        self.Bind(wx.EVT_BUTTON, self.on_next_button, self.nextbutton)
        self.nextbutton.SetFont(font2)
        self.nextbutton.SetHelpText(dgh.nextbutton_help)

        self.prevbutton = wx.Button(
            self.side_panel, id=wx.ID_ANY, label='previous', size=(100*self.GUI_RESOLUTION, 25))
        self.prevbutton.SetFont(font2)
        self.Bind(wx.EVT_BUTTON, self.on_prev_button, self.prevbutton)
        self.prevbutton.SetHelpText(dgh.prevbutton_help)

    # ----------------------------------------------------------------------
        #  select coordinate box
    # ----------------------------------------------------------------------

        self.COORDINATE_SYSTEM, self.coordinate_list = self.get_coordinate_system()
        self.coordinates_box = wx.ComboBox(self.side_panel, id=wx.ID_ANY, size=(
            200*self.GUI_RESOLUTION, 25), choices=self.coordinate_list, value=self.COORDINATE_SYSTEM, style=wx.CB_DROPDOWN | wx.TE_READONLY, name="coordinates")
        self.Bind(wx.EVT_COMBOBOX, self.onSelect_coordinates,
                  self.coordinates_box)
        self.coordinates_box.SetHelpText(dgh.coordinates_box_help)

    # ----------------------------------------------------------------------
        #  Orthogonal Zijderveld Options box
    # ----------------------------------------------------------------------

        self.orthogonal_box = wx.ComboBox(self.side_panel, id=wx.ID_ANY, value='X=East', size=(
            200*self.GUI_RESOLUTION, 25), choices=['X=NRM dec', 'X=East', 'X=North'], style=wx.CB_DROPDOWN | wx.TE_READONLY, name="orthogonal_plot")
        # remove 'X=best fit line dec' as option given that is isn't implemented for multiple components
        self.Bind(wx.EVT_COMBOBOX, self.onSelect_orthogonal_box,
                  self.orthogonal_box)
        self.orthogonal_box.SetHelpText(dgh.orthogonal_box_help)

# --------------------------------------------------------------------------
    #  Top Bar Options ----------------------------------------------------
# --------------------------------------------------------------------------

    # ----------------------------------------------------------------------
        #  select bounds box
    # ----------------------------------------------------------------------

        self.T_list = []

        self.tmin_box = wx.ComboBox(self.panel, id=wx.ID_ANY, size=(
            50*self.GUI_RESOLUTION, 25), choices=self.T_list, style=wx.CB_DROPDOWN | wx.TE_READONLY)
        self.Bind(wx.EVT_COMBOBOX, self.get_new_PCA_parameters, self.tmin_box)
        self.tmin_box.SetHelpText(dgh.tmin_box_help)

        self.tmax_box = wx.ComboBox(self.panel, id=wx.ID_ANY, size=(
            50*self.GUI_RESOLUTION, 25), choices=self.T_list, style=wx.CB_DROPDOWN | wx.TE_READONLY)
        self.Bind(wx.EVT_COMBOBOX, self.get_new_PCA_parameters, self.tmax_box)
        self.tmax_box.SetHelpText(dgh.tmax_box_help)

    # ----------------------------------------------------------------------
        #  Specimens interpretations Management box
    # ----------------------------------------------------------------------

        list_fits = []

        self.fit_box = wx.ComboBox(self.panel, id=wx.ID_ANY, size=(
            50*self.GUI_RESOLUTION, 25), choices=list_fits, style=wx.TE_PROCESS_ENTER)
        self.Bind(wx.EVT_COMBOBOX, self.on_select_fit, self.fit_box)
        self.Bind(wx.EVT_TEXT_ENTER, self.on_enter_fit_name, self.fit_box)
        self.fit_box.SetHelpText(dgh.fit_box_help)

        self.add_fit_button = wx.Button(
            self.panel, id=wx.ID_ANY, label='add fit', size=(50*self.GUI_RESOLUTION, 25))
        self.add_fit_button.SetFont(font2)
        self.Bind(wx.EVT_BUTTON, self.on_btn_add_fit, self.add_fit_button)
        self.add_fit_button.SetHelpText(dgh.add_fit_button_help)

        # save/delete interpretation buttons
        self.save_fit_button = wx.Button(self.panel, id=wx.ID_ANY, label='save', size=(
            50*self.GUI_RESOLUTION, 25))  # ,style=wx.BU_EXACTFIT)#, size=(175, 28))
        self.save_fit_button.SetFont(font2)
        self.save_fit_button.SetHelpText(dgh.save_fit_btn_help)

        self.delete_fit_button = wx.Button(self.panel, id=wx.ID_ANY, label='delete fit', size=(
            50*self.GUI_RESOLUTION, 25))  # ,style=wx.BU_EXACTFIT)#, size=(175, 28))
        self.delete_fit_button.SetFont(font2)
        self.delete_fit_button.SetHelpText(dgh.delete_fit_btn_help)

        self.Bind(wx.EVT_BUTTON, self.on_save_interpretation_button,
                  self.save_fit_button)
        self.Bind(wx.EVT_BUTTON, self.on_btn_delete_fit,
                  self.delete_fit_button)

        # auto-save interpretation buttons
        self.auto_save = wx.CheckBox(self.panel, wx.ID_ANY, 'auto-save')
        if self.preferences['auto_save']:
            self.auto_save.SetValue(True)

        self.auto_save_info = wx.Button(self.panel, wx.ID_ANY, "?")
        self.Bind(wx.EVT_BUTTON, self.on_btn_info_click, self.auto_save_info)

    # ----------------------------------------------------------------------
        # Interpretation Type and Display window
    # ----------------------------------------------------------------------

        self.PCA_type_box = wx.ComboBox(self.panel, id=wx.ID_ANY, size=(50*self.GUI_RESOLUTION, 25), value='line', choices=[
                                        'line', 'line-anchored', 'line-with-origin', 'plane', 'Fisher'], style=wx.CB_DROPDOWN | wx.TE_READONLY, name="coordinates")
        self.Bind(wx.EVT_COMBOBOX,
                  self.on_select_specimen_mean_type_box, self.PCA_type_box)
        self.PCA_type_box.SetHelpText(dgh.PCA_type_help)

        self.plane_display_box = wx.ComboBox(self.panel, id=wx.ID_ANY, size=(50*self.GUI_RESOLUTION, 25), value='whole plane', choices=[
                                             'whole plane', 'u. hemisphere', 'l. hemisphere', 'poles', 'bfv', 'wp + bfv'], style=wx.CB_DROPDOWN | wx.TE_READONLY, name="PlaneType")
        self.Bind(wx.EVT_COMBOBOX, self.on_select_plane_display_box,
                  self.plane_display_box)
        self.plane_display_box.SetHelpText(dgh.plane_display_help)

    # ----------------------------------------------------------------------
        # Interpretation Statistics StaticSizer
    # ----------------------------------------------------------------------

        box_sizer_specimen_stat = wx.StaticBoxSizer(wx.StaticBox(
            self.panel, wx.ID_ANY, "Interpretation Direction and Statistics"), wx.HORIZONTAL)

        for parameter in ['dec', 'inc', 'n', 'mad', 'dang', 'alpha95']:
            COMMAND = "self.s%s_window=wx.TextCtrl(self.panel,style=wx.TE_CENTER|wx.TE_READONLY,size=(25*self.GUI_RESOLUTION,25))" % parameter
            exec(COMMAND)
            COMMAND = "self.s%s_window.SetBackgroundColour(wx.WHITE)" % parameter
            exec(COMMAND)
            COMMAND = "self.s%s_window.SetFont(font2)" % parameter
            exec(COMMAND)

        specimen_stat_window = wx.GridSizer(2, 6, 0, 5)
        specimen_stat_window.AddMany([(wx.StaticText(self.panel, label="dec", style=wx.TE_CENTER), 1, wx.EXPAND | wx.TOP, 2*top_bar_2v_space),
                                      (wx.StaticText(self.panel, label="inc", style=wx.TE_CENTER),
                                       1, wx.EXPAND | wx.TOP, 2*top_bar_2v_space),
                                      (wx.StaticText(self.panel, label="n", style=wx.TE_CENTER),
                                       1, wx.EXPAND | wx.TOP, 2*top_bar_2v_space),
                                      (wx.StaticText(self.panel, label="mad", style=wx.TE_CENTER),
                                       1, wx.EXPAND | wx.TOP, 2*top_bar_2v_space),
                                      (wx.StaticText(self.panel, label="dang", style=wx.TE_CENTER),
                                       1, wx.TE_CENTER | wx.EXPAND | wx.TOP, 2*top_bar_2v_space),
                                      (wx.StaticText(self.panel, label="a95", style=wx.TE_CENTER),
                                       1, wx.TE_CENTER | wx.EXPAND | wx.TOP, 2*top_bar_2v_space),
                                      (self.sdec_window, 1, wx.EXPAND),
                                      (self.sinc_window, 1, wx.EXPAND),
                                      (self.sn_window, 1, wx.EXPAND),
                                      (self.smad_window, 1, wx.EXPAND),
                                      (self.sdang_window, 1, wx.EXPAND),
                                      (self.salpha95_window, 1, wx.EXPAND)])
        box_sizer_specimen_stat.Add(
            specimen_stat_window, 1, wx.ALIGN_LEFT | wx.EXPAND)

    # ----------------------------------------------------------------------
        # High level mean window
    # ----------------------------------------------------------------------

        self.level_box = wx.ComboBox(self.panel, id=wx.ID_ANY, size=(50*self.GUI_RESOLUTION, 25), value='site',  choices=[
                                     'sample', 'site', 'location', 'study'], style=wx.CB_DROPDOWN | wx.TE_READONLY, name="high_level")
        self.Bind(wx.EVT_COMBOBOX, self.onSelect_high_level, self.level_box)
        self.level_box.SetHelpText(dgh.level_box_help)

        self.level_names = wx.ComboBox(self.panel, id=wx.ID_ANY, size=(
            50*self.GUI_RESOLUTION, 25), value=self.site, choices=self.sites, style=wx.CB_DROPDOWN | wx.TE_READONLY, name="high_level_names")
        self.Bind(wx.EVT_COMBOBOX, self.onSelect_level_name, self.level_names)
        self.level_names.SetHelpText(dgh.level_names_help)

    # ----------------------------------------------------------------------
        # mean types box
    # ----------------------------------------------------------------------

        self.mean_type_box = wx.ComboBox(self.panel, id=wx.ID_ANY, size=(50*self.GUI_RESOLUTION, 25), value='None', choices=[
                                         'Fisher', 'Fisher by polarity', 'None'], style=wx.CB_DROPDOWN | wx.TE_READONLY, name="high_type")
        self.Bind(wx.EVT_COMBOBOX, self.onSelect_mean_type_box,
                  self.mean_type_box)
        self.mean_type_box.SetHelpText(dgh.mean_type_help)

        self.mean_fit_box = wx.ComboBox(self.panel, id=wx.ID_ANY, size=(50*self.GUI_RESOLUTION, 25), value='None', choices=[
                                        'None', 'All'] + list_fits, style=wx.CB_DROPDOWN | wx.TE_READONLY, name="high_type")
        self.Bind(wx.EVT_COMBOBOX, self.onSelect_mean_fit_box,
                  self.mean_fit_box)
        self.mean_fit_box.SetHelpText(dgh.mean_fit_help)
        self.mean_fit = 'None'

    # ----------------------------------------------------------------------
        # Warnings TextCtrl
    # ----------------------------------------------------------------------
        warning_sizer = wx.StaticBoxSizer(wx.StaticBox(
            self.panel, wx.ID_ANY, "Current Data Warnings"), wx.VERTICAL)

        self.warning_box = wx.TextCtrl(self.panel, id=wx.ID_ANY, size=(50*self.GUI_RESOLUTION, 50 + 2*top_bar_2v_space),
                                       value="No Problems", style=wx.TE_MULTILINE | wx.TE_READONLY | wx.HSCROLL, name="warning_box")
        self.warning_box.SetHelpText(dgh.warning_help)

        warning_sizer.Add(self.warning_box, 1, wx.TOP | wx.EXPAND)

    # ----------------------------------------------------------------------
        # Design the panel
    # ----------------------------------------------------------------------

        # Top Bar-----------------------------------------------------------
        top_bar_sizer = wx.BoxSizer(wx.HORIZONTAL)

        bounds_sizer = wx.StaticBoxSizer(wx.StaticBox(
            self.panel, wx.ID_ANY, "Bounds"), wx.VERTICAL)
        bounds_sizer.AddMany([(self.tmin_box, 1, wx.ALIGN_TOP | wx.EXPAND | wx.BOTTOM, top_bar_2v_space),
                              (self.tmax_box, 1, wx.ALIGN_BOTTOM | wx.EXPAND | wx.TOP, top_bar_2v_space)])
        top_bar_sizer.Add(bounds_sizer, 1, wx.ALIGN_LEFT)

        fit_sizer = wx.StaticBoxSizer(wx.StaticBox(
            self.panel, wx.ID_ANY, "Interpretation Options"), wx.VERTICAL)
        fit_grid = wx.GridSizer(2, 3, top_bar_h_space, 2*top_bar_2v_space)
        fit_grid.AddMany([(self.add_fit_button, 1, wx.ALIGN_TOP | wx.ALIGN_LEFT | wx.EXPAND),
                          (self.save_fit_button, 1, wx.ALIGN_TOP |
                           wx.ALIGN_LEFT | wx.EXPAND),
                          (self.auto_save, 1, wx.ALIGN_CENTER),
                          (self.fit_box, 1, wx.ALIGN_BOTTOM |
                           wx.ALIGN_LEFT | wx.EXPAND),
                          (self.delete_fit_button, 1, wx.ALIGN_BOTTOM | wx.ALIGN_LEFT | wx.EXPAND),
                          (self.auto_save_info, 1, wx.ALIGN_CENTER)])
        fit_sizer.Add(fit_grid, 1, wx.EXPAND)
        top_bar_sizer.Add(fit_sizer, 2, wx.ALIGN_LEFT |
                          wx.LEFT, top_bar_h_space)

        fit_type_sizer = wx.StaticBoxSizer(wx.StaticBox(
            self.panel, wx.ID_ANY, "Interpretation Type"), wx.VERTICAL)
        fit_type_sizer.AddMany([(self.PCA_type_box, 1, wx.ALIGN_TOP | wx.EXPAND | wx.BOTTOM, top_bar_2v_space),
                                (self.plane_display_box, 1, wx.ALIGN_BOTTOM | wx.EXPAND | wx.TOP, top_bar_2v_space)])
        top_bar_sizer.Add(fit_type_sizer, 1, wx.ALIGN_LEFT |
                          wx.LEFT, top_bar_h_space)

        top_bar_sizer.Add(box_sizer_specimen_stat, 3,
                          wx.ALIGN_LEFT | wx.LEFT, top_bar_h_space)

        level_sizer = wx.StaticBoxSizer(wx.StaticBox(
            self.panel, wx.ID_ANY, "Display Level"), wx.VERTICAL)
        level_sizer.AddMany([(self.level_box, 1, wx.ALIGN_TOP | wx.EXPAND | wx.BOTTOM, top_bar_2v_space),
                             (self.level_names, 1, wx.ALIGN_BOTTOM | wx.EXPAND | wx.TOP, top_bar_2v_space)])
        top_bar_sizer.Add(level_sizer, 1, wx.ALIGN_LEFT |
                          wx.LEFT, top_bar_h_space)

        mean_options_sizer = wx.StaticBoxSizer(wx.StaticBox(
            self.panel, wx.ID_ANY, "Mean Options"), wx.VERTICAL)
        mean_options_sizer.AddMany([(self.mean_type_box, 1, wx.ALIGN_TOP | wx.EXPAND | wx.BOTTOM, top_bar_2v_space),
                                    (self.mean_fit_box, 1, wx.ALIGN_BOTTOM | wx.EXPAND | wx.TOP, top_bar_2v_space)])
        top_bar_sizer.Add(mean_options_sizer, 1,
                          wx.ALIGN_LEFT | wx.LEFT, top_bar_h_space)

        top_bar_sizer.Add(warning_sizer, 2, wx.ALIGN_LEFT |
                          wx.LEFT, top_bar_h_space)

        # Side Bar------------------------------------------------------------
        side_bar_sizer = wx.BoxSizer(wx.VERTICAL)

        spec_sizer = wx.StaticBoxSizer(wx.StaticBox(
            self.side_panel, wx.ID_ANY, "Specimen"), wx.VERTICAL)
        spec_buttons_sizer = wx.GridSizer(1, 2, 0, spec_button_space)
        spec_buttons_sizer.AddMany([(self.prevbutton, 1, wx.ALIGN_LEFT | wx.EXPAND),
                                    (self.nextbutton, 1, wx.ALIGN_RIGHT | wx.EXPAND)])
        spec_sizer.AddMany([(self.specimens_box, 1, wx.ALIGN_TOP | wx.EXPAND | wx.BOTTOM, side_bar_v_space/2),
                            (spec_buttons_sizer, 1, wx.ALIGN_BOTTOM | wx.EXPAND | wx.TOP, side_bar_v_space/2)])
        side_bar_sizer.Add(spec_sizer, .5, wx.ALIGN_TOP | wx.EXPAND)
        side_bar_sizer.Add(wx.StaticLine(self.side_panel), .5,
                           wx.ALL | wx.EXPAND, side_bar_v_space)

        coordinate_sizer = wx.StaticBoxSizer(wx.StaticBox(
            self.side_panel, wx.ID_ANY, "Coordinate System"), wx.VERTICAL)
        coordinate_sizer.Add(self.coordinates_box, .5, wx.EXPAND)
        side_bar_sizer.Add(coordinate_sizer, .5, wx.ALIGN_TOP | wx.EXPAND)
        side_bar_sizer.Add(wx.StaticLine(self.side_panel), .5,
                           wx.ALL | wx.EXPAND, side_bar_v_space)

        zijderveld_option_sizer = wx.StaticBoxSizer(wx.StaticBox(
            self.side_panel, wx.ID_ANY, "Zijderveld Plot Options"), wx.VERTICAL)
        zijderveld_option_sizer.Add(self.orthogonal_box, 1, wx.EXPAND)
        side_bar_sizer.Add(zijderveld_option_sizer, .5,
                           wx.ALIGN_TOP | wx.EXPAND)

        side_bar_sizer.Add(self.logger, proportion=1,
                           flag=wx.ALIGN_TOP | wx.TOP | wx.EXPAND, border=8)

        # Mean Stats and button Sizer-----------------------------------------
        stats_and_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
        stats_and_button_sizer.AddMany([(self.stats_sizer, 1, wx.ALIGN_LEFT | wx.EXPAND),
                                        (self.switch_stats_button, .3, wx.ALIGN_RIGHT | wx.EXPAND)])

        # EQ area MM0 and stats sizer-----------------------------------------
        eqarea_MM0_stats_sizer = wx.GridSizer(2, 2, 0, 0)
        eqarea_MM0_stats_sizer.AddMany([(self.canvas2, 1, wx.ALIGN_LEFT | wx.EXPAND),
                                        (self.canvas4, 1, wx.ALIGN_RIGHT | wx.EXPAND),
                                        (self.canvas3, 1, wx.ALIGN_LEFT | wx.EXPAND),
                                        (stats_and_button_sizer, 1, wx.ALIGN_RIGHT | wx.EXPAND)])

        # Plots and Stats Sizer-----------------------------------------------
        full_plots_sizer = wx.BoxSizer(wx.HORIZONTAL)
        full_plots_sizer.Add(self.canvas1, 1, wx.ALIGN_LEFT | wx.EXPAND)
        full_plots_sizer.Add(eqarea_MM0_stats_sizer, 1.5,
                             wx.ALIGN_RIGHT | wx.EXPAND)

        self.panel.SetSizerAndFit(top_bar_sizer)
        self.side_panel.SetSizerAndFit(side_bar_sizer)
        self.scrolled_panel.SetSizer(full_plots_sizer)

        # Outer Sizer---------------------------------------------------------
        add_side_bar_sizer = wx.BoxSizer(wx.HORIZONTAL)
        add_side_bar_sizer.Add(self.side_panel, 1, wx.ALIGN_LEFT | wx.EXPAND)
        add_side_bar_sizer.Add(self.scrolled_panel, 5,
                               wx.ALIGN_RIGHT | wx.EXPAND)

        outersizer = wx.BoxSizer(wx.VERTICAL)
        outersizer.Add(self.panel, .2, wx.ALIGN_TOP | wx.EXPAND)
        outersizer.Add(add_side_bar_sizer, 1, wx.ALIGN_BOTTOM | wx.EXPAND)

        self.SetSizer(outersizer)
        outersizer.Fit(self)

        self.GUI_SIZE = self.GetSize()

Response: Initializes the main GUI for the current locale.


Instruction:
Can you write a function in Python 3 where it
gets the available coordinate system.

Response:
def get_coordinate_system(self):
        """
        Check self.Data for available coordinate systems.

        Returns
        ---------
        initial_coordinate, coordinate_list : str, list
        i.e., 'geographic', ['specimen', 'geographic']
        """
        coordinate_list = ['specimen']
        initial_coordinate = 'specimen'
        for specimen in self.specimens:
            if 'geographic' not in coordinate_list and self.Data[specimen]['zijdblock_geo']:
                coordinate_list.append('geographic')
                initial_coordinate = 'geographic'
            if 'tilt-corrected' not in coordinate_list and self.Data[specimen]['zijdblock_tilt']:
                coordinate_list.append('tilt-corrected')
        return initial_coordinate, coordinate_list


Instruction:
Can you generate a brief explanation for the following Python 3 code
def create_menu(self):
        self.menubar = wx.MenuBar()

        # -----------------
        # File Menu
        # -----------------

        menu_file = wx.Menu()

        m_change_WD = menu_file.Append(-1,
                                       "Change Working Directory\tCtrl-W", "")
        self.Bind(wx.EVT_MENU, self.on_menu_change_working_directory, m_change_WD)

        m_import_meas_file = menu_file.Append(-1,
                                        "Change measurements file", "")

        self.Bind(wx.EVT_MENU, self.on_menu_import_meas_file, m_import_meas_file)

        m_import_LSQ = menu_file.Append(-1,
                                        "&Import Interpretations from LSQ file\tCtrl-L", "")
        self.Bind(wx.EVT_MENU, self.on_menu_read_from_LSQ, m_import_LSQ)

        m_previous_interpretation = menu_file.Append(
            -1, "&Import interpretations from a redo file\tCtrl-R", "")
        self.Bind(wx.EVT_MENU, self.on_menu_previous_interpretation,
                  m_previous_interpretation)

        m_save_interpretation = menu_file.Append(
            -1, "&Save interpretations to a redo file\tCtrl-S", "")
        self.Bind(wx.EVT_MENU, self.on_menu_save_interpretation,
                  m_save_interpretation)

        m_make_MagIC_results_tables = menu_file.Append(
            -1, "&Save MagIC tables\tCtrl-Shift-S", "")
        self.Bind(wx.EVT_MENU, self.on_menu_make_MagIC_results_tables,
                  m_make_MagIC_results_tables)

        submenu_save_plots = wx.Menu()

        m_save_zij_plot = submenu_save_plots.Append(
            -1, "&Save Zijderveld plot", "")
        self.Bind(wx.EVT_MENU, self.on_save_Zij_plot, m_save_zij_plot, "Zij")

        m_save_eq_plot = submenu_save_plots.Append(
            -1, "&Save specimen equal area plot", "")
        self.Bind(wx.EVT_MENU, self.on_save_Eq_plot,
                  m_save_eq_plot, "specimen-Eq")

        m_save_M_t_plot = submenu_save_plots.Append(-1, "&Save M-t plot", "")
        self.Bind(wx.EVT_MENU, self.on_save_M_t_plot, m_save_M_t_plot, "M_t")

        m_save_high_level = submenu_save_plots.Append(
            -1, "&Save high level plot", "")
        self.Bind(wx.EVT_MENU, self.on_save_high_level,
                  m_save_high_level, "Eq")

        m_save_all_plots = submenu_save_plots.Append(-1, "&Save all plots", "")
        self.Bind(wx.EVT_MENU, self.on_save_all_figures, m_save_all_plots)

        m_new_sub_plots = menu_file.AppendSubMenu(submenu_save_plots, "&Save plot")

        menu_file.AppendSeparator()
        m_exit = menu_file.Append(-1, "E&xit\tCtrl-Q", "Exit")
        self.Bind(wx.EVT_MENU, self.on_menu_exit, m_exit)

        # -----------------
        # Edit Menu
        # -----------------

        menu_edit = wx.Menu()

        m_new = menu_edit.Append(-1, "&New interpretation\tCtrl-N", "")
        self.Bind(wx.EVT_MENU, self.on_btn_add_fit, m_new)

        m_delete = menu_edit.Append(-1, "&Delete interpretation\tCtrl-D", "")
        self.Bind(wx.EVT_MENU, self.on_btn_delete_fit, m_delete)

        m_next_interp = menu_edit.Append(-1,
                                         "&Next interpretation\tCtrl-Up", "")
        self.Bind(wx.EVT_MENU, self.on_menu_next_interp, m_next_interp)

        m_previous_interp = menu_edit.Append(-1,
                                             "&Previous interpretation\tCtrl-Down", "")
        self.Bind(wx.EVT_MENU, self.on_menu_prev_interp, m_previous_interp)

        m_next_specimen = menu_edit.Append(-1,
                                           "&Next Specimen\tCtrl-Right", "")
        self.Bind(wx.EVT_MENU, self.on_next_button, m_next_specimen)

        m_previous_specimen = menu_edit.Append(-1,
                                               "&Previous Specimen\tCtrl-Left", "")
        self.Bind(wx.EVT_MENU, self.on_prev_button, m_previous_specimen)

        menu_flag_meas = wx.Menu()

        m_good = menu_flag_meas.Append(-1, "&Good Measurement\tCtrl-Alt-G", "")
        self.Bind(wx.EVT_MENU, self.on_menu_flag_meas_good, m_good)
        m_bad = menu_flag_meas.Append(-1, "&Bad Measurement\tCtrl-Alt-B", "")
        self.Bind(wx.EVT_MENU, self.on_menu_flag_meas_bad, m_bad)

        m_flag_meas = menu_edit.AppendSubMenu(menu_flag_meas, "&Flag Measurement Data")

        menu_coordinates = wx.Menu()

        m_speci = menu_coordinates.Append(-1,
                                          "&Specimen Coordinates\tCtrl-P", "")
        self.Bind(wx.EVT_MENU, self.on_menu_change_speci_coord, m_speci)
        if "geographic" in self.coordinate_list:
            m_geo = menu_coordinates.Append(-1,
                                            "&Geographic Coordinates\tCtrl-G", "")
            self.Bind(wx.EVT_MENU, self.on_menu_change_geo_coord, m_geo)
        if "tilt-corrected" in self.coordinate_list:
            m_tilt = menu_coordinates.Append(-1,
                                             "&Tilt-Corrected Coordinates\tCtrl-T", "")
            self.Bind(wx.EVT_MENU, self.on_menu_change_tilt_coord, m_tilt)

        m_coords = menu_edit.AppendSubMenu(menu_coordinates, "&Coordinate Systems")

        # -----------------
        # Analysis Menu
        # -----------------

        menu_Analysis = wx.Menu()

        submenu_criteria = wx.Menu()

        m_change_criteria_file = submenu_criteria.Append(
            -1, "&Change acceptance criteria", "")
        self.Bind(wx.EVT_MENU, self.on_menu_change_criteria,
                  m_change_criteria_file)

        m_import_criteria_file = submenu_criteria.Append(
            -1, "&Import criteria file", "")
        self.Bind(wx.EVT_MENU, self.on_menu_criteria_file,
                  m_import_criteria_file)

        m_new_sub = menu_Analysis.AppendSubMenu(submenu_criteria, "Acceptance criteria")

        menu_flag_fit = wx.Menu()

        m_good_fit = menu_flag_fit.Append(-1,
                                          "&Good Interpretation\tCtrl-Shift-G", "")
        self.Bind(wx.EVT_MENU, self.on_menu_flag_fit_good, m_good_fit)
        m_bad_fit = menu_flag_fit.Append(-1,
                                         "&Bad Interpretation\tCtrl-Shift-B", "")
        self.Bind(wx.EVT_MENU, self.on_menu_flag_fit_bad, m_bad_fit)

        m_flag_fit = menu_Analysis.AppendSubMenu(menu_flag_fit, "&Flag Interpretations")

        submenu_sample_check = wx.Menu()

        m_check_orient = submenu_sample_check.Append(
            -1, "&Check Sample Orientations\tCtrl-O", "")
        self.Bind(wx.EVT_MENU, self.on_menu_check_orient, m_check_orient)

        m_mark_samp_bad = submenu_sample_check.Append(
            -1, "&Mark Sample Bad\tCtrl-.", "")
        self.Bind(wx.EVT_MENU, self.on_menu_mark_samp_bad, m_mark_samp_bad)

        m_mark_samp_good = submenu_sample_check.Append(
            -1, "&Mark Sample Good\tCtrl-,", "")
        self.Bind(wx.EVT_MENU, self.on_menu_mark_samp_good, m_mark_samp_good)

        m_submenu = menu_Analysis.AppendSubMenu(submenu_sample_check, "Sample Orientation")

        submenu_toggle_mean_display = wx.Menu()

        lines = ["m_%s_toggle_mean = submenu_toggle_mean_display.AppendCheckItem(-1, '&%s', ''); self.Bind(wx.EVT_MENU, self.on_menu_toggle_mean, m_%s_toggle_mean)" % (
            f, f) for f in self.all_fits_list]

        for line in lines:
            exec(line)

        menu_Analysis.AppendSubMenu(submenu_toggle_mean_display, "Toggle Mean Display")

        # -----------------
        # Tools Menu
        # -----------------

        menu_Tools = wx.Menu()

#        m_auto_interpret = menu_Tools.Append(-1, "&Auto interpret (alpha version)\tCtrl-A", "")
#        self.Bind(wx.EVT_MENU, self.autointerpret, m_auto_interpret)

        m_edit_interpretations = menu_Tools.Append(
            -1, "&Interpretation editor\tCtrl-E", "")
        self.Bind(wx.EVT_MENU, self.on_menu_edit_interpretations,
                  m_edit_interpretations)

        m_view_VGP = menu_Tools.Append(-1, "&View VGPs\tCtrl-Shift-V", "")
        self.Bind(wx.EVT_MENU, self.on_menu_view_vgps, m_view_VGP)

        # -----------------
        # Help Menu
        # -----------------

        menu_Help = wx.Menu()

        m_help = menu_Help.Append(-1, "&Usage and Tips\tCtrl-H", "")
        self.Bind(wx.EVT_MENU, self.on_menu_help, m_help)

        m_cookbook = menu_Help.Append(-1, "&PmagPy Cookbook\tCtrl-Shift-W", "")
        self.Bind(wx.EVT_MENU, self.on_menu_cookbook, m_cookbook)

        m_docs = menu_Help.Append(-1, "&Open Docs\tCtrl-Shift-H", "")
        self.Bind(wx.EVT_MENU, self.on_menu_docs, m_docs)

        m_git = menu_Help.Append(-1, "&Github Page\tCtrl-Shift-G", "")
        self.Bind(wx.EVT_MENU, self.on_menu_git, m_git)

        m_debug = menu_Help.Append(-1, "&Open Debugger\tCtrl-Shift-D", "")
        self.Bind(wx.EVT_MENU, self.on_menu_debug, m_debug)

        # -----------------

        #self.menubar.Append(menu_preferences, "& Preferences")
        self.menubar.Append(menu_file, "&File")
        self.menubar.Append(menu_edit, "&Edit")
        self.menubar.Append(menu_Analysis, "&Analysis")
        self.menubar.Append(menu_Tools, "&Tools")
        self.menubar.Append(menu_Help, "&Help")
        #self.menubar.Append(menu_Plot, "&Plot")
        #self.menubar.Append(menu_results_table, "&Table")
        #self.menubar.Append(menu_MagIC, "&MagIC")
        self.SetMenuBar(self.menubar)

Response: Create the menu for the GUI current structure


Instruction:
Here you have a function in Python 3, explain what it does
def draw_figure(self, s, update_high_plots=True):
        self.initialize_CART_rot(s)

        # Draw Zij plot
        self.draw_zijderveld()

        # Draw specimen equal area
        self.draw_spec_eqarea()

        # Draw M/M0 plot ( or NLT data on the same area in the GUI)
        self.draw_MM0()

        # If measurements are selected redisplay selected data
        if len(self.selected_meas) > 0:
            self.plot_selected_meas()

        # Draw high level equal area
        if update_high_plots:
            self.plot_high_levels_data()
        self.canvas4.draw()

Response: This method draws the current figure for the current specimen and updates all plots.


Instruction:
Make a summary of the following Python 3 code
def draw_zijderveld(self):
        self.fig1.clf()
        axis_bounds = [0, .1, 1, .85]
        self.zijplot = self.fig1.add_axes(
            axis_bounds, frameon=False, facecolor='None', label='zig_orig', zorder=0)
        self.zijplot.clear()
        self.zijplot.axis('equal')
        self.zijplot.xaxis.set_visible(False)
        self.zijplot.yaxis.set_visible(False)

        self.MS = 6*self.GUI_RESOLUTION
        self.dec_MEC = 'k'
        self.dec_MFC = 'r'
        self.inc_MEC = 'k'
        self.inc_MFC = 'b'
        self.MS = 6*self.GUI_RESOLUTION
        self.zijdblock_steps = self.Data[self.s]['zijdblock_steps']
        self.vds = self.Data[self.s]['vds']

        self.zijplot.plot(self.CART_rot_good[:, 0], -1*self.CART_rot_good[:, 1], 'ro-',
                          markersize=self.MS, clip_on=False, picker=True, zorder=1)  # x,y or N,E
        self.zijplot.plot(self.CART_rot_good[:, 0], -1*self.CART_rot_good[:, 2], 'bs-',
                          markersize=self.MS, clip_on=False, picker=True, zorder=1)  # x-z or N,D

        for i in range(len(self.CART_rot_bad)):
            self.zijplot.plot(self.CART_rot_bad[:, 0][i], -1 * self.CART_rot_bad[:, 1][i], 'o', mfc='None',
                              mec=self.dec_MEC, markersize=self.MS, clip_on=False, picker=False)  # x,y or N,E
            self.zijplot.plot(self.CART_rot_bad[:, 0][i], -1 * self.CART_rot_bad[:, 2][i], 's', mfc='None',
                              mec=self.inc_MEC, markersize=self.MS, clip_on=False, picker=False)  # x-z or N,D

        if self.preferences['show_Zij_treatments']:
            for i in range(len(self.zijdblock_steps)):
                if int(self.preferences['show_Zij_treatments_steps']) != 1:
                    if i != 0 and (i+1) % int(self.preferences['show_Zij_treatments_steps']) == 0:
                        self.zijplot.text(self.CART_rot[i][0], -1*self.CART_rot[i][2], "  %s" % (
                            self.zijdblock_steps[i]), fontsize=8*self.GUI_RESOLUTION, color='gray', ha='left', va='center')  # inc
                else:
                    self.zijplot.text(self.CART_rot[i][0], -1*self.CART_rot[i][2], "  %s" % (
                        self.zijdblock_steps[i]), fontsize=10*self.GUI_RESOLUTION, color='gray', ha='left', va='center')  # inc

        # -----

        xmin, xmax = self.zijplot.get_xlim()
        if xmax < 0:
            xmax = 0
        if xmin > 0:
            xmin = 0
        # else:
        #    xmin=xmin+xmin%0.2

        props = dict(color='black', linewidth=1.0, markeredgewidth=0.5)

        xlocs = array(list(arange(0.2, xmax, 0.2)) +
                      list(arange(-0.2, xmin, -0.2)))
        if len(xlocs) > 0:
            xtickline, = self.zijplot.plot(
                xlocs, [0]*len(xlocs), linestyle='', marker='+', **props)
            xtickline.set_clip_on(False)

        axxline, = self.zijplot.plot([xmin, xmax], [0, 0], **props)
        axxline.set_clip_on(False)

        TEXT = ""
        if self.COORDINATE_SYSTEM == 'specimen':
            self.zijplot.text(xmax, 0, ' x', fontsize=10,
                              verticalalignment='bottom')
        else:
            if self.ORTHO_PLOT_TYPE == 'N-S':
                TEXT = " N"
            elif self.ORTHO_PLOT_TYPE == 'E-W':
                TEXT = " E"
            else:
                TEXT = " x"
            self.zijplot.text(xmax, 0, TEXT, fontsize=10,
                              verticalalignment='bottom')

        # -----

        ymin, ymax = self.zijplot.get_ylim()
        if ymax < 0:
            ymax = 0
        if ymin > 0:
            ymin = 0

        ylocs = array(list(arange(0.2, ymax, 0.2)) +
                      list(arange(-0.2, ymin, -0.2)))
        if len(ylocs) > 0:
            ytickline, = self.zijplot.plot(
                [0]*len(ylocs), ylocs, linestyle='', marker='+', **props)
            ytickline.set_clip_on(False)

        axyline, = self.zijplot.plot([0, 0], [ymin, ymax], **props)
        axyline.set_clip_on(False)

        TEXT1, TEXT2 = "", ""
        if self.COORDINATE_SYSTEM == 'specimen':
            TEXT1, TEXT2 = " y", "      z"
        else:
            if self.ORTHO_PLOT_TYPE == 'N-S':
                TEXT1, TEXT2 = " E", "     D"
            elif self.ORTHO_PLOT_TYPE == 'E-W':
                TEXT1, TEXT2 = " S", "     D"
            else:
                TEXT1, TEXT2 = " y", "      z"
        self.zijplot.text(0, ymin, TEXT1, fontsize=10,
                          color='r', verticalalignment='top')
        self.zijplot.text(0, ymin, '    ,', fontsize=10,
                          color='k', verticalalignment='top')
        self.zijplot.text(0, ymin, TEXT2, fontsize=10,
                          color='b', verticalalignment='top')

        # ----

        if self.ORTHO_PLOT_TYPE == 'N-S':
            STRING = ""
            #STRING1="N-S orthogonal plot"
            self.fig1.text(0.01, 0.98, "Zijderveld plot: x = North", {
                           'family': self.font_type, 'fontsize': 10*self.GUI_RESOLUTION, 'style': 'normal', 'va': 'center', 'ha': 'left'})
        elif self.ORTHO_PLOT_TYPE == 'E-W':
            STRING = ""
            #STRING1="E-W orthogonal plot"
            self.fig1.text(0.01, 0.98, "Zijderveld plot:: x = East", {
                           'family': self.font_type, 'fontsize': 10*self.GUI_RESOLUTION, 'style': 'normal', 'va': 'center', 'ha': 'left'})

        elif self.ORTHO_PLOT_TYPE == 'PCA_dec':
            self.fig1.text(0.01, 0.98, "Zijderveld plot", {
                           'family': self.font_type, 'fontsize': 10*self.GUI_RESOLUTION, 'style': 'normal', 'va': 'center', 'ha': 'left'})
            if 'specimen_dec' in list(self.current_fit.pars.keys()) and type(self.current_fit.pars['specimen_dec']) != str:
                STRING = "X-axis rotated to best fit line declination (%.0f); " % (
                    self.current_fit.pars['specimen_dec'])
            else:
                STRING = "X-axis rotated to NRM (%.0f); " % (
                    self.zijblock[0][1])
        else:
            self.fig1.text(0.01, 0.98, "Zijderveld plot", {
                           'family': self.font_type, 'fontsize': 10*self.GUI_RESOLUTION, 'style': 'normal', 'va': 'center', 'ha': 'left'})
            STRING = "X-axis rotated to NRM (%.0f); " % (self.zijblock[0][1])
            #STRING1="Zijderveld plot"

        STRING = STRING+"NRM=%.2e " % (self.zijblock[0][3]) + 'Am^2'
        self.fig1.text(0.01, 0.95, STRING, {'family': self.font_type, 'fontsize': 8 *
                                            self.GUI_RESOLUTION, 'style': 'normal', 'va': 'center', 'ha': 'left'})

        xmin, xmax = self.zijplot.get_xlim()
        ymin, ymax = self.zijplot.get_ylim()

        self.zij_xlim_initial = (xmin, xmax)
        self.zij_ylim_initial = (ymin, ymax)

        self.canvas1.draw()

Response: Draws the zijderveld plot on canvas1


Instruction:
Create a Python 3 function for
calculating point positions and draws the Specimen eqarea plot on canvas2

Response:
def draw_spec_eqarea(self):
        """
        Calculates point positions and draws the Specimen eqarea plot on
        canvas2
        """
        draw_net(self.specimen_eqarea)
        self.specimen_eqarea.text(-1.2, 1.15, "specimen: %s" % self.s, {
                                  'family': self.font_type, 'fontsize': 10*self.GUI_RESOLUTION, 'style': 'normal', 'va': 'center', 'ha': 'left'})

        x_eq = array([row[0] for row in self.zij_norm])
        y_eq = array([row[1] for row in self.zij_norm])
        z_eq = abs(array([row[2] for row in self.zij_norm]))

        # remove bad data from plotting:
        x_eq_good, y_eq_good, z_eq_good = [], [], []
        x_eq_bad, y_eq_bad, z_eq_bad = [], [], []
        for i in range(len(list(self.zij_norm))):
            if self.Data[self.s]['measurement_flag'][i] == 'g':
                x_eq_good.append(self.zij_norm[i][0])
                y_eq_good.append(self.zij_norm[i][1])
                z_eq_good.append(abs(self.zij_norm[i][2]))
            else:
                x_eq_bad.append(self.zij_norm[i][0])
                y_eq_bad.append(self.zij_norm[i][1])
                z_eq_bad.append(abs(self.zij_norm[i][2]))

        x_eq_good, y_eq_good, z_eq_good = array(
            x_eq_good), array(y_eq_good), array(z_eq_good)
        x_eq_bad, y_eq_bad, z_eq_bad = array(
            x_eq_bad), array(y_eq_bad), array(z_eq_bad)

        R_good = array(sqrt(1-z_eq_good)/sqrt(x_eq_good**2 +
                                              y_eq_good**2))  # from Collinson 1983
        # from Collinson 1983
        R_bad = array(sqrt(1-z_eq_bad)/sqrt(x_eq_bad**2+y_eq_bad**2))

        eqarea_data_x_good = y_eq_good*R_good
        eqarea_data_y_good = x_eq_good*R_good

        eqarea_data_x_bad = y_eq_bad*R_bad
        eqarea_data_y_bad = x_eq_bad*R_bad

        self.specimen_eqarea.plot(
            eqarea_data_x_good, eqarea_data_y_good, lw=0.5, color='gray')  # ,zorder=0)

        # --------------------
        # scatter plot
        # --------------------

        x_eq_dn, y_eq_dn, z_eq_dn, eq_dn_temperatures = [], [], [], []
        x_eq_dn = array([row[0] for row in self.zij_norm if row[2] > 0])
        y_eq_dn = array([row[1] for row in self.zij_norm if row[2] > 0])
        z_eq_dn = abs(array([row[2] for row in self.zij_norm if row[2] > 0]))

        if len(x_eq_dn) > 0:
            # from Collinson 1983
            R = array(sqrt(1-z_eq_dn)/sqrt(x_eq_dn**2+y_eq_dn**2))
            eqarea_data_x_dn = y_eq_dn*R
            eqarea_data_y_dn = x_eq_dn*R
            self.specimen_eqarea.scatter([eqarea_data_x_dn], [eqarea_data_y_dn], marker='o',
                                         edgecolor='black', facecolor="#808080", s=15*self.GUI_RESOLUTION, lw=1, clip_on=False)

        x_eq_up, y_eq_up, z_eq_up = [], [], []
        x_eq_up = array([row[0] for row in self.zij_norm if row[2] <= 0])
        y_eq_up = array([row[1] for row in self.zij_norm if row[2] <= 0])
        z_eq_up = abs(array([row[2] for row in self.zij_norm if row[2] <= 0]))
        if len(x_eq_up) > 0:
            # from Collinson 1983
            R = array(sqrt(1-z_eq_up)/sqrt(x_eq_up**2+y_eq_up**2))
            eqarea_data_x_up = y_eq_up*R
            eqarea_data_y_up = x_eq_up*R
            self.specimen_eqarea.scatter([eqarea_data_x_up], [eqarea_data_y_up], marker='o',
                                         edgecolor='black', facecolor="#FFFFFF", s=15*self.GUI_RESOLUTION, lw=1, clip_on=False)

        # self.preferences['show_eqarea_treatments']=True
        if self.preferences['show_eqarea_treatments']:
            for i in range(len(self.zijdblock_steps)):
                self.specimen_eqarea.text(eqarea_data_x[i], eqarea_data_y[i], "%.1f" % float(
                    self.zijdblock_steps[i]), fontsize=8*self.GUI_RESOLUTION, color="0.5")

        # add line to show the direction of the x axis in the Zijderveld plot

        if str(self.orthogonal_box.GetValue()) in ["X=best fit line dec", "X=NRM dec"]:
            XY = []
            if str(self.orthogonal_box.GetValue()) == "X=NRM dec":
                dec_zij = self.zijblock[0][1]
                XY = pmag.dimap(dec_zij, 0)
            if str(self.orthogonal_box.GetValue()) == "X=best fit line dec":
                if 'specimen_dec' in list(self.current_fit.pars.keys()) and type(self.current_fit.pars['specimen_dec']) != str:
                    dec_zij = self.current_fit.pars['specimen_dec']
                    XY = pmag.dimap(dec_zij, 0)
            if XY != []:
                self.specimen_eqarea.plot(
                    [0, XY[0]], [0, XY[1]], ls='-', c='gray', lw=0.5)  # ,zorder=0)

        self.canvas2.draw()


Instruction:
Can you implement a function in Python 3 that
draws the M and M0 plot on canvas3.

Response:
def draw_MM0(self):
        """
        Draws the M/M0 plot in the GUI on canvas3
        """
        self.fig3.clf()
        self.fig3.text(0.02, 0.96, 'M/M0', {'family': self.font_type, 'fontsize': 10 *
                                            self.GUI_RESOLUTION, 'style': 'normal', 'va': 'center', 'ha': 'left'})
        self.mplot = self.fig3.add_axes(
            [0.2, 0.15, 0.7, 0.7], frameon=True, facecolor='None')

        thermal_x, thermal_y = [], []
        thermal_x_bad, thermal_y_bad = [], []
        af_x, af_y = [], []
        af_x_bad, af_y_bad = [], []
        for i in range(len(self.Data[self.s]['zijdblock'])):
            step = self.Data[self.s]['zijdblock_steps'][i]
            # bad point
            if self.Data[self.s]['measurement_flag'][i] == 'b':
                if step == "0":
                    thermal_x_bad.append(self.Data[self.s]['zijdblock'][i][0])
                    af_x_bad.append(self.Data[self.s]['zijdblock'][i][0])
                    thermal_y_bad.append(
                        self.Data[self.s]['zijdblock'][i][3]/self.Data[self.s]['zijdblock'][0][3])
                    af_y_bad.append(
                        self.Data[self.s]['zijdblock'][i][3]/self.Data[self.s]['zijdblock'][0][3])
                elif "C" in step:
                    thermal_x_bad.append(self.Data[self.s]['zijdblock'][i][0])
                    thermal_y_bad.append(
                        self.Data[self.s]['zijdblock'][i][3]/self.Data[self.s]['zijdblock'][0][3])
                elif "T" in step:
                    af_x_bad.append(self.Data[self.s]['zijdblock'][i][0])
                    af_y_bad.append(
                        self.Data[self.s]['zijdblock'][i][3]/self.Data[self.s]['zijdblock'][0][3])
                else:
                    continue

            else:
                if step == "0":
                    thermal_x.append(self.Data[self.s]['zijdblock'][i][0])
                    af_x.append(self.Data[self.s]['zijdblock'][i][0])
                    thermal_y.append(
                        self.Data[self.s]['zijdblock'][i][3]/self.Data[self.s]['zijdblock'][0][3])
                    af_y.append(self.Data[self.s]['zijdblock'][i]
                                [3]/self.Data[self.s]['zijdblock'][0][3])
                elif "C" in step:
                    thermal_x.append(self.Data[self.s]['zijdblock'][i][0])
                    thermal_y.append(
                        self.Data[self.s]['zijdblock'][i][3]/self.Data[self.s]['zijdblock'][0][3])
                elif "T" in step:
                    af_x.append(self.Data[self.s]['zijdblock'][i][0])
                    af_y.append(self.Data[self.s]['zijdblock'][i]
                                [3]/self.Data[self.s]['zijdblock'][0][3])
                else:
                    continue

        if len(thermal_x)+len(thermal_x_bad) > self.Data[self.s]['zijdblock_steps'].count('0'):
            self.mplot.plot(thermal_x, thermal_y, 'ro-',
                            markersize=self.MS, lw=1, clip_on=False, zorder=1)
            for i in range(len(thermal_x_bad)):
                self.mplot.plot([thermal_x_bad[i]], [thermal_y_bad[i]], 'o',
                                mfc='None', mec='k', markersize=self.MS, clip_on=False, zorder=1)

        self.mplot.set_xlabel('Thermal (C)', color='r')
        for tl in self.mplot.get_xticklabels():
            tl.set_color('r')

        self.mplot_af = self.mplot.twiny()
        if len(af_x)+len(af_x_bad) > self.Data[self.s]['zijdblock_steps'].count('0'):
            self.mplot_af.plot(
                af_x, af_y, 'bo-', markersize=self.MS, lw=1, clip_on=False, zorder=1)
            for i in range(len(af_x_bad)):
                self.mplot_af.plot([af_x_bad[i]], [
                                   af_y_bad[i]], 'o', mfc='None', mec='k', markersize=self.MS, clip_on=False, zorder=1)

        self.mplot_af.set_xlabel('AF (mT)', color='b')
        for tl in self.mplot_af.get_xticklabels():
            tl.set_color('b')

        self.mplot.tick_params(axis='both', which='major', labelsize=7)
        self.mplot_af.tick_params(axis='both', which='major', labelsize=7)
        self.mplot.spines["right"].set_visible(False)
        self.mplot_af.spines["right"].set_visible(False)
        self.mplot.get_xaxis().tick_bottom()
        self.mplot.get_yaxis().tick_left()
        self.mplot.set_ylabel("M / NRM0", fontsize=8*self.GUI_RESOLUTION)

        self.canvas3.draw()