Instruction:
How would you explain what the following Python 3 function does
def atrm_magic(meas_file, dir_path=".", input_dir_path="",
               input_spec_file='specimens.txt', output_spec_file='specimens.txt',
               data_model_num=3):
    """
    Converts ATRM  data to best-fit tensor (6 elements plus sigma)

    Parameters
    ----------
    meas_file : str
        input measurement file
    dir_path : str
        output directory, default "."
    input_dir_path : str
        input file directory IF different from dir_path, default ""
    input_spec_file : str
        input specimen file name, default "specimens.txt"
    output_spec_file : str
        output specimen file name, default "specimens.txt"
    data_model_num : number
        MagIC data model [2, 3], default 3

    Returns
    ---------
    Tuple : (True or False indicating if conversion was sucessful, output file name written)

    """
    # fix up file names
    input_dir_path, dir_path = pmag.fix_directories(input_dir_path, dir_path)
    meas_file = pmag.resolve_file_name(meas_file, input_dir_path)
    rmag_anis = os.path.join(dir_path, 'rmag_anisotropy.txt')
    rmag_res = os.path.join(dir_path, 'rmag_results.txt')
    input_spec_file = pmag.resolve_file_name(input_spec_file, input_dir_path)
    output_spec_file = pmag.resolve_file_name(output_spec_file, dir_path)

    # read in data
    if data_model_num == 3:
        meas_data = []
        meas_data3, file_type = pmag.magic_read(meas_file)
        if file_type != 'measurements':
            print(
                "-E- {} is not a valid measurements file, {}".format(meas_file, file_type))
            return False
        # convert meas_data to 2.5
        for rec in meas_data3:
            meas_map = map_magic.meas_magic3_2_magic2_map
            meas_data.append(map_magic.mapping(rec, meas_map))
        old_spec_recs, file_type = pmag.magic_read(input_spec_file)
        if file_type != 'specimens':
            print("-W- {} is not a valid specimens file ".format(input_spec_file))
            old_spec_recs = []
        spec_recs = []
        for rec in old_spec_recs:
            spec_map = map_magic.spec_magic3_2_magic2_map
            spec_recs.append(map_magic.mapping(rec, spec_map))

    else:
        meas_data, file_type = pmag.magic_read(meas_file)
        if file_type != 'magic_measurements':
            print("-E- {} is is not a valid magic_measurements file ".format(file_type))
            return False, "{} is not a valid magic_measurements file, {}".format(meas_file, file_type)

    meas_data = pmag.get_dictitem(
        meas_data, 'magic_method_codes', 'LP-AN-TRM', 'has')
    if not len(meas_data):
        print("-E- No measurement records found with code LP-AN-TRM")
        return False, "No measurement records found with code LP-AN-TRM"
    #
    #
    # get sorted list of unique specimen names
    ssort = []
    for rec in meas_data:
        spec = rec["er_specimen_name"]
        if spec not in ssort:
            ssort.append(spec)
    sids = sorted(ssort)
    #
    #
    # work on each specimen
    #
    specimen, npos = 0, 6
    RmagSpecRecs, RmagResRecs = [], []
    SpecRecs, SpecRecs3 = [], []
    while specimen < len(sids):
        nmeas = 0
        s = sids[specimen]
        RmagSpecRec = {}
        RmagResRec = {}
        # get old specrec here if applicable
        if data_model_num == 3:
            if spec_recs:
                try:
                    RmagResRec = pmag.get_dictitem(
                        spec_recs, 'er_specimen_name', s, 'T')[0]
                    RmagSpecRec = pmag.get_dictitem(
                        spec_recs, 'er_specimen_name', s, 'T')[0]
                except IndexError:
                    pass

        BX, X = [], []
        method_codes = []
        Spec0 = ""
    #
    # find the data from the meas_data file for this sample
        # and get dec, inc, int and convert to x,y,z
        #
        # fish out data for this specimen name
        data = pmag.get_dictitem(meas_data, 'er_specimen_name', s, 'T')
        if len(data) > 5:
            RmagSpecRec["rmag_anisotropy_name"] = data[0]["er_specimen_name"]
            RmagSpecRec["er_location_name"] = data[0].get(
                "er_location_name", "")
            RmagSpecRec["er_specimen_name"] = data[0]["er_specimen_name"]
            if not "er_sample_name" in RmagSpecRec:
                RmagSpecRec["er_sample_name"] = data[0].get(
                    "er_sample_name", "")
            RmagSpecRec["er_site_name"] = data[0].get("er_site_name", "")
            RmagSpecRec["magic_experiment_names"] = RmagSpecRec["rmag_anisotropy_name"] + ":ATRM"
            RmagSpecRec["er_citation_names"] = "This study"
            RmagResRec["rmag_result_name"] = data[0]["er_specimen_name"] + ":ATRM"
            RmagResRec["er_location_names"] = data[0].get(
                "er_location_names", "")
            RmagResRec["er_specimen_names"] = data[0]["er_specimen_name"]
            if data_model_num == 2:
                RmagResRec["er_sample_names"] = data[0].get(
                    "er_sample_name", "")
            RmagResRec["er_site_names"] = data[0].get("er_site_name", "")
            RmagResRec["magic_experiment_names"] = RmagSpecRec["rmag_anisotropy_name"] + ":ATRM"
            RmagResRec["er_citation_names"] = "This study"
            RmagSpecRec["anisotropy_type"] = "ATRM"
            if "magic_instrument_codes" in list(data[0].keys()):
                RmagSpecRec["magic_instrument_codes"] = data[0]["magic_instrument_codes"]
            else:
                RmagSpecRec["magic_instrument_codes"] = ""
                RmagSpecRec["anisotropy_description"] = "Hext statistics adapted to ATRM"
            for rec in data:
                meths = rec['magic_method_codes'].strip().split(':')
                Dir = []
                Dir.append(float(rec["measurement_dec"]))
                Dir.append(float(rec["measurement_inc"]))
                Dir.append(float(rec["measurement_magn_moment"]))
                if "LT-T-Z" in meths:
                    BX.append(pmag.dir2cart(Dir))  # append baseline steps
                elif "LT-T-I" in meths:
                    X.append(pmag.dir2cart(Dir))
                    nmeas += 1
    #
        if len(BX) == 1:
            for i in range(len(X) - 1):
                BX.append(BX[0])  # assume first 0 field step as baseline
        elif len(BX) == 0:  # assume baseline is zero
            for i in range(len(X)):
                BX.append([0., 0., 0.])  # assume baseline of 0
        elif len(BX) != len(X):  # if BX isn't just one measurement or one in between every infield step, just assume it is zero
            print('something odd about the baselines - just assuming zero')
            for i in range(len(X)):
                BX.append([0., 0., 0.])  # assume baseline of 0
        if nmeas < 6:  # must have at least 6 measurements right now -
            print('skipping specimen ', s, ' too few measurements')
            specimen += 1
        else:
            # B matrix made from design matrix for positions
            B, H, tmpH = pmag.designATRM(npos)
        #
        # subtract optional baseline and put in a work array
        #
            work = np.zeros((nmeas, 3), 'f')
            for i in range(nmeas):
                for j in range(3):
                    # subtract baseline, if available
                    work[i][j] = X[i][j] - BX[i][j]
        #
        # calculate tensor elements
        # first put ARM components in w vector
        #
            w = np.zeros((npos * 3), 'f')
            index = 0
            for i in range(npos):
                for j in range(3):
                    w[index] = work[i][j]
                    index += 1
            s = np.zeros((6), 'f')  # initialize the s matrix
            for i in range(6):
                for j in range(len(w)):
                    s[i] += B[i][j] * w[j]
            trace = s[0] + s[1] + s[2]   # normalize by the trace
            for i in range(6):
                s[i] = s[i] / trace
            a = pmag.s2a(s)

        # ------------------------------------------------------------
        #  Calculating dels is different than in the Kappabridge
        #  routine. Use trace normalized tensor (a) and the applied
        #  unit field directions (tmpH) to generate model X,Y,Z
        #  components. Then compare these with the measured values.
        # ------------------------------------------------------------
            S = 0.
            comp = np.zeros((npos * 3), 'f')
            for i in range(npos):
                for j in range(3):
                    index = i * 3 + j
                    compare = a[j][0] * tmpH[i][0] + a[j][1] * \
                        tmpH[i][1] + a[j][2] * tmpH[i][2]
                    comp[index] = compare
            for i in range(npos * 3):
                d = (w[i] / trace) - comp[i]  # del values
                S += d * d
            nf = float(npos * 3. - 6.)  # number of degrees of freedom
            if S > 0:
                sigma = np.sqrt(S / nf)
            else:
                sigma = 0
            hpars = pmag.dohext(nf, sigma, s)
        #
        # prepare for output
        #
            RmagSpecRec["anisotropy_s1"] = '%8.6f' % (s[0])
            RmagSpecRec["anisotropy_s2"] = '%8.6f' % (s[1])
            RmagSpecRec["anisotropy_s3"] = '%8.6f' % (s[2])
            RmagSpecRec["anisotropy_s4"] = '%8.6f' % (s[3])
            RmagSpecRec["anisotropy_s5"] = '%8.6f' % (s[4])
            RmagSpecRec["anisotropy_s6"] = '%8.6f' % (s[5])
            RmagSpecRec["anisotropy_mean"] = '%8.3e' % (trace / 3)
            RmagSpecRec["anisotropy_sigma"] = '%8.6f' % (sigma)
            RmagSpecRec["anisotropy_unit"] = "Am^2"
            RmagSpecRec["anisotropy_n"] = '%i' % (npos)
            RmagSpecRec["anisotropy_tilt_correction"] = '-1'
            # used by thellier_gui - must be taken out for uploading
            RmagSpecRec["anisotropy_F"] = '%7.1f ' % (hpars["F"])
            # used by thellier_gui - must be taken out for uploading
            RmagSpecRec["anisotropy_F_crit"] = hpars["F_crit"]
            RmagResRec["anisotropy_t1"] = '%8.6f ' % (hpars["t1"])
            RmagResRec["anisotropy_t2"] = '%8.6f ' % (hpars["t2"])
            RmagResRec["anisotropy_t3"] = '%8.6f ' % (hpars["t3"])
            RmagResRec["anisotropy_v1_dec"] = '%7.1f ' % (hpars["v1_dec"])
            RmagResRec["anisotropy_v2_dec"] = '%7.1f ' % (hpars["v2_dec"])
            RmagResRec["anisotropy_v3_dec"] = '%7.1f ' % (hpars["v3_dec"])
            RmagResRec["anisotropy_v1_inc"] = '%7.1f ' % (hpars["v1_inc"])
            RmagResRec["anisotropy_v2_inc"] = '%7.1f ' % (hpars["v2_inc"])
            RmagResRec["anisotropy_v3_inc"] = '%7.1f ' % (hpars["v3_inc"])
            RmagResRec["anisotropy_ftest"] = '%7.1f ' % (hpars["F"])
            RmagResRec["anisotropy_ftest12"] = '%7.1f ' % (hpars["F12"])
            RmagResRec["anisotropy_ftest23"] = '%7.1f ' % (hpars["F23"])
            RmagResRec["result_description"] = 'Critical F: ' + \
                hpars["F_crit"] + ';Critical F12/F13: ' + hpars["F12_crit"]
            if hpars["e12"] > hpars["e13"]:
                RmagResRec["anisotropy_v1_zeta_semi_angle"] = '%7.1f ' % (
                    hpars['e12'])
                RmagResRec["anisotropy_v1_zeta_dec"] = '%7.1f ' % (
                    hpars['v2_dec'])
                RmagResRec["anisotropy_v1_zeta_inc"] = '%7.1f ' % (
                    hpars['v2_inc'])
                RmagResRec["anisotropy_v2_zeta_semi_angle"] = '%7.1f ' % (
                    hpars['e12'])
                RmagResRec["anisotropy_v2_zeta_dec"] = '%7.1f ' % (
                    hpars['v1_dec'])
                RmagResRec["anisotropy_v2_zeta_inc"] = '%7.1f ' % (
                    hpars['v1_inc'])
                RmagResRec["anisotropy_v1_eta_semi_angle"] = '%7.1f ' % (
                    hpars['e13'])
                RmagResRec["anisotropy_v1_eta_dec"] = '%7.1f ' % (
                    hpars['v3_dec'])
                RmagResRec["anisotropy_v1_eta_inc"] = '%7.1f ' % (
                    hpars['v3_inc'])
                RmagResRec["anisotropy_v3_eta_semi_angle"] = '%7.1f ' % (
                    hpars['e13'])
                RmagResRec["anisotropy_v3_eta_dec"] = '%7.1f ' % (
                    hpars['v1_dec'])
                RmagResRec["anisotropy_v3_eta_inc"] = '%7.1f ' % (
                    hpars['v1_inc'])
            else:
                RmagResRec["anisotropy_v1_zeta_semi_angle"] = '%7.1f ' % (
                    hpars['e13'])
                RmagResRec["anisotropy_v1_zeta_dec"] = '%7.1f ' % (
                    hpars['v3_dec'])
                RmagResRec["anisotropy_v1_zeta_inc"] = '%7.1f ' % (
                    hpars['v3_inc'])
                RmagResRec["anisotropy_v3_zeta_semi_angle"] = '%7.1f ' % (
                    hpars['e13'])
                RmagResRec["anisotropy_v3_zeta_dec"] = '%7.1f ' % (
                    hpars['v1_dec'])
                RmagResRec["anisotropy_v3_zeta_inc"] = '%7.1f ' % (
                    hpars['v1_inc'])
                RmagResRec["anisotropy_v1_eta_semi_angle"] = '%7.1f ' % (
                    hpars['e12'])
                RmagResRec["anisotropy_v1_eta_dec"] = '%7.1f ' % (
                    hpars['v2_dec'])
                RmagResRec["anisotropy_v1_eta_inc"] = '%7.1f ' % (
                    hpars['v2_inc'])
                RmagResRec["anisotropy_v2_eta_semi_angle"] = '%7.1f ' % (
                    hpars['e12'])
                RmagResRec["anisotropy_v2_eta_dec"] = '%7.1f ' % (
                    hpars['v1_dec'])
                RmagResRec["anisotropy_v2_eta_inc"] = '%7.1f ' % (
                    hpars['v1_inc'])
            if hpars["e23"] > hpars['e12']:
                RmagResRec["anisotropy_v2_zeta_semi_angle"] = '%7.1f ' % (
                    hpars['e23'])
                RmagResRec["anisotropy_v2_zeta_dec"] = '%7.1f ' % (
                    hpars['v3_dec'])
                RmagResRec["anisotropy_v2_zeta_inc"] = '%7.1f ' % (
                    hpars['v3_inc'])
                RmagResRec["anisotropy_v3_zeta_semi_angle"] = '%7.1f ' % (
                    hpars['e23'])
                RmagResRec["anisotropy_v3_zeta_dec"] = '%7.1f ' % (
                    hpars['v2_dec'])
                RmagResRec["anisotropy_v3_zeta_inc"] = '%7.1f ' % (
                    hpars['v2_inc'])
                RmagResRec["anisotropy_v3_eta_semi_angle"] = '%7.1f ' % (
                    hpars['e13'])
                RmagResRec["anisotropy_v3_eta_dec"] = '%7.1f ' % (
                    hpars['v1_dec'])
                RmagResRec["anisotropy_v3_eta_inc"] = '%7.1f ' % (
                    hpars['v1_inc'])
                RmagResRec["anisotropy_v2_eta_semi_angle"] = '%7.1f ' % (
                    hpars['e12'])
                RmagResRec["anisotropy_v2_eta_dec"] = '%7.1f ' % (
                    hpars['v1_dec'])
                RmagResRec["anisotropy_v2_eta_inc"] = '%7.1f ' % (
                    hpars['v1_inc'])
            else:
                RmagResRec["anisotropy_v2_zeta_semi_angle"] = '%7.1f ' % (
                    hpars['e12'])
                RmagResRec["anisotropy_v2_zeta_dec"] = '%7.1f ' % (
                    hpars['v1_dec'])
                RmagResRec["anisotropy_v2_zeta_inc"] = '%7.1f ' % (
                    hpars['v1_inc'])
                RmagResRec["anisotropy_v3_eta_semi_angle"] = '%7.1f ' % (
                    hpars['e23'])
                RmagResRec["anisotropy_v3_eta_dec"] = '%7.1f ' % (
                    hpars['v2_dec'])
                RmagResRec["anisotropy_v3_eta_inc"] = '%7.1f ' % (
                    hpars['v2_inc'])
                RmagResRec["anisotropy_v3_zeta_semi_angle"] = '%7.1f ' % (
                    hpars['e13'])
                RmagResRec["anisotropy_v3_zeta_dec"] = '%7.1f ' % (
                    hpars['v1_dec'])
                RmagResRec["anisotropy_v3_zeta_inc"] = '%7.1f ' % (
                    hpars['v1_inc'])
                RmagResRec["anisotropy_v2_eta_semi_angle"] = '%7.1f ' % (
                    hpars['e23'])
                RmagResRec["anisotropy_v2_eta_dec"] = '%7.1f ' % (
                    hpars['v3_dec'])
                RmagResRec["anisotropy_v2_eta_inc"] = '%7.1f ' % (
                    hpars['v3_inc'])
            RmagResRec["tilt_correction"] = '-1'
            RmagResRec["anisotropy_type"] = 'ATRM'
            RmagResRec["magic_method_codes"] = 'LP-AN-TRM:AE-H'
            RmagSpecRec["magic_method_codes"] = 'LP-AN-TRM:AE-H'
            RmagResRec["magic_software_packages"] = pmag.get_version()
            RmagSpecRec["magic_software_packages"] = pmag.get_version()
            RmagSpecRecs.append(RmagSpecRec)
            RmagResRecs.append(RmagResRec)
            specimen += 1
        if data_model_num == 3:
            SpecRec = RmagResRec.copy()
            SpecRec.update(RmagSpecRec)
            SpecRecs.append(SpecRec)

    # finished iterating through specimens,
    # now we need to write out the data to files
    if data_model_num == 3:
        # translate records
        for rec in SpecRecs:
            rec3 = map_magic.convert_aniso('magic3', rec)
            SpecRecs3.append(rec3)

        # write output to 3.0 specimens file
        pmag.magic_write(output_spec_file, SpecRecs3, 'specimens')
        print("specimen data stored in {}".format(output_spec_file))
        return True, output_spec_file

    else:
        # write output to 2.5 rmag_ files
        pmag.magic_write(rmag_anis, RmagSpecRecs, 'rmag_anisotropy')
        print("specimen tensor elements stored in ", rmag_anis)
        pmag.magic_write(rmag_res, RmagResRecs, 'rmag_results')
        print("specimen statistics and eigenparameters stored in ", rmag_res)
        return True, rmag_anis

Response: Convert ATRM data to best fit tensor


Instruction:
Implement a function in Python 3 to
transform decs and incs to geographic coordinates.

Response:
def transform_to_geographic(this_spec_meas_df, samp_df, samp, coord="0"):
    """
    Transform decs/incs to geographic coordinates.
    Calls pmag.dogeo_V for the heavy lifting

    Parameters
    ----------
    this_spec_meas_df : pandas dataframe of measurements for a single specimen
    samp_df : pandas dataframe of samples
    samp : samp name

    Returns
    ---------
    this_spec_meas_df : measurements dataframe with transformed coordinates
    """
    # we could return the type of coordinates ACTUALLY used
    # transform geographic
    decs = this_spec_meas_df['dir_dec'].values.tolist()
    incs = this_spec_meas_df['dir_inc'].values.tolist()
    or_info, az_type = pmag.get_orient(samp_df,samp,data_model=3)
    if 'azimuth' in or_info.keys() and cb.not_null(or_info['azimuth'], False):
        azimuths=len(decs)*[or_info['azimuth']]
        dips=len(decs)*[or_info['dip']]
    # if azimuth/dip is missing, or orientation is bad,
    # stick with specimen coordinates
    else:
        return this_spec_meas_df
    dirs = [decs, incs, azimuths, dips]
    dirs_geo = np.array(list(map(list, list(zip(*dirs)))))
    decs, incs = pmag.dogeo_V(dirs_geo)
    if coord == '100' and 'bed_dip_direction' in or_info.keys() and or_info['bed_dip_direction']!="":  # need to do tilt correction too
        bed_dip_dirs = len(decs)*[or_info['bed_dip_direction']]
        bed_dips = len(decs) * [or_info['bed_dip']]
        dirs = [decs, incs, bed_dip_dirs, bed_dips]
        ## this transposes the columns and rows of the list of lists
        dirs_tilt = np.array(list(map(list, list(zip(*dirs)))))
        decs, incs = pmag.dotilt_V(dirs_tilt)
    this_spec_meas_df['dir_dec'] = decs
    this_spec_meas_df['dir_inc'] = incs
    return this_spec_meas_df


Instruction:
Given the following Python 3 function, write the documentation
def hysteresis_magic(output_dir_path=".", input_dir_path="", spec_file="specimens.txt",
                     meas_file="measurements.txt", fmt="svg",
                     save_plots=True, make_plots=True, pltspec="", n_specs=5, interactive=False):
    """
    Calculate hysteresis parameters and plot hysteresis data.
    Plotting may be called interactively with save_plots==False,
    or be suppressed entirely with make_plots==False.

    Parameters
    ----------
    output_dir_path : str, default "."
        Note: if using Windows, all figures will be saved to working directly
              *not* dir_path
    input_dir_path : str
        path for intput file if different from output_dir_path (default is same)
    spec_file : str, default "specimens.txt"
        output file to save hysteresis data
    meas_file : str, default "measurements.txt"
        input measurement file
    fmt : str, default "svg"
        format for figures, [svg, jpg, pdf, png]
    save_plots : bool, default True
        if True, generate and save all requested plots
    make_plots : bool, default True
        if False, skip making plots and just save hysteresis data
        (if False, save_plots will be set to False also)
    pltspec : str, default ""
        specimen name to plot, otherwise will plot all specimens
    n_specs : int
        number of specimens to plot, default 5
        if you want to make all possible plots, specify "all"
    interactive : bool, default False
        interactively plot and display for each specimen
        (this is best used on the command line or in the Python interpreter)

    Returns
    ---------
    Tuple : (True or False indicating if conversion was sucessful, output file names written)
    """
    # put plots in output_dir_path, unless isServer
    incl_directory = True
    if pmagplotlib.isServer or set_env.IS_WIN:
        incl_directory = False
    # figure out directory/file paths
    input_dir_path, output_dir_path = pmag.fix_directories(input_dir_path, output_dir_path)
    spec_file = pmag.resolve_file_name(spec_file, input_dir_path)
    meas_file = pmag.resolve_file_name(meas_file, input_dir_path)
    # format and initialize variables
    verbose = pmagplotlib.verbose
    version_num = pmag.get_version()
    if not make_plots:
        irm_init, imag_init = -1, -1
        save_plots = False
    if save_plots:
        verbose = False
    if pltspec:
        pass
    if interactive:
        save_plots = False

    SpecRecs = []
    #
    #
    meas_data, file_type = pmag.magic_read(meas_file)
    if file_type != 'measurements':
        print('bad file', meas_file)
        return False, []
    #
    # initialize some variables
    # define figure numbers for hyst,deltaM,DdeltaM curves
    HystRecs, RemRecs = [], []
    HDD = {}
    if verbose and make_plots:
        print("Plots may be on top of each other - use mouse to place ")
    if make_plots:
        HDD['hyst'], HDD['deltaM'], HDD['DdeltaM'] = 1, 2, 3
        if make_plots and (not save_plots):
            pmagplotlib.plot_init(HDD['DdeltaM'], 5, 5)
            pmagplotlib.plot_init(HDD['deltaM'], 5, 5)
            pmagplotlib.plot_init(HDD['hyst'], 5, 5)
        imag_init = 0
        irm_init = 0
    else:
        HDD['hyst'], HDD['deltaM'], HDD['DdeltaM'], HDD['irm'], HDD['imag'] = 0, 0, 0, 0, 0
    #
    if spec_file:
        prior_data, file_type = pmag.magic_read(spec_file)
    #
    # get list of unique experiment names and specimen names
    #
    experiment_names, sids = [], []
    hys_data = pmag.get_dictitem(meas_data, 'method_codes', 'LP-HYS', 'has')
    dcd_data = pmag.get_dictitem(
        meas_data, 'method_codes', 'LP-IRM-DCD', 'has')
    imag_data = pmag.get_dictitem(meas_data, 'method_codes', 'LP-IMAG', 'has')
    for rec in hys_data:
        if rec['experiment'] not in experiment_names:
            experiment_names.append(rec['experiment'])
        if rec['specimen'] not in sids:
            sids.append(rec['specimen'])
    #
    k = 0
    # if plotting only one specimen, find it
    if pltspec:
        k = sids.index(pltspec)
    # if plotting only n specimens, remove others from the list
    elif n_specs != "all":
        try:
            sids = sids[:n_specs]
        except:
            pass
    cnt = 0
    while k < len(sids):
        specimen = sids[k]
        if pltspec:
            if specimen != pltspec:
                k += 1
                continue
        else:
            for key, value in HDD.items():
                cnt += 1
                HDD[key] = cnt

            #HDD = {key: value + len(HDD) + k for (key, value) in HDD.items()}
        # initialize a new specimen hysteresis record
        HystRec = {'specimen': specimen, 'experiment': ""}
        if verbose and make_plots:
            print(specimen, k+1, 'out of ', len(sids))
    #
    #
        # B,M for hysteresis, Bdcd,Mdcd for irm-dcd data
        B, M, Bdcd, Mdcd = [], [], [], []
        Bimag, Mimag = [], []  # Bimag,Mimag for initial magnetization curves
        # fish out all the LP-HYS data for this specimen
        spec_data = pmag.get_dictitem(hys_data, 'specimen', specimen, 'T')
        if len(spec_data) > 0:
            meths = spec_data[0]['method_codes'].split(':')
            e = spec_data[0]['experiment']
            HystRec['experiment'] = spec_data[0]['experiment']
            for rec in spec_data:
                B.append(float(rec['meas_field_dc']))
                M.append(float(rec['magn_moment']))
        # fish out all the data for this specimen
        spec_data = pmag.get_dictitem(dcd_data, 'specimen', specimen, 'T')
        if len(spec_data) > 0:
            HystRec['experiment'] = HystRec['experiment'] + \
                ':'+spec_data[0]['experiment']
            irm_exp = spec_data[0]['experiment']
            for rec in spec_data:
                Bdcd.append(float(rec['treat_dc_field']))
                Mdcd.append(float(rec['magn_moment']))
        # fish out all the data for this specimen
        spec_data = pmag.get_dictitem(imag_data, 'specimen', specimen, 'T')
        if len(spec_data) > 0:
            imag_exp = spec_data[0]['experiment']
            for rec in spec_data:
                Bimag.append(float(rec['meas_field_dc']))
                Mimag.append(float(rec['magn_moment']))
    #
    # now plot the hysteresis curve
    #
        if len(B) > 0:
            hmeths = []
            for meth in meths:
                hmeths.append(meth)

            hpars = pmagplotlib.plot_hdd(HDD, B, M, e)
            if interactive:
                if not set_env.IS_WIN:
                    pmagplotlib.draw_figs(HDD)
    #
            if make_plots:
                pmagplotlib.plot_hpars(HDD, hpars, 'bs')
            HystRec['hyst_mr_moment'] = hpars['hysteresis_mr_moment']
            HystRec['hyst_ms_moment'] = hpars['hysteresis_ms_moment']
            HystRec['hyst_bc'] = hpars['hysteresis_bc']
            HystRec['hyst_bcr'] = hpars['hysteresis_bcr']
            HystRec['hyst_xhf'] = hpars['hysteresis_xhf']
            HystRec['experiments'] = e
            HystRec['software_packages'] = version_num
            if hpars["magic_method_codes"] not in hmeths:
                hmeths.append(hpars["magic_method_codes"])
            methods = ""
            for meth in hmeths:
                methods = methods+meth.strip()+":"
            HystRec["method_codes"] = methods[:-1]
            HystRec["citations"] = "This study"
    #
        if len(Bdcd) > 0:
            rmeths = []
            for meth in meths:
                rmeths.append(meth)
            if verbose and make_plots:
                print('plotting IRM')
            if irm_init == 0:
                cnt += 1
                HDD['irm'] = cnt #5 if 'imag' in HDD else 4
                if make_plots and (not save_plots):
                    pmagplotlib.plot_init(HDD['irm'], 5, 5)
                irm_init = 1
            rpars = pmagplotlib.plot_irm(HDD['irm'], Bdcd, Mdcd, irm_exp)
            HystRec['rem_mr_moment'] = rpars['remanence_mr_moment']
            HystRec['rem_bcr'] = rpars['remanence_bcr']
            HystRec['experiments'] = specimen+':'+irm_exp
            if rpars["magic_method_codes"] not in meths:
                meths.append(rpars["magic_method_codes"])
            methods = ""
            for meth in rmeths:
                methods = methods+meth.strip()+":"
            HystRec["method_codes"] = HystRec['method_codes']+':'+methods[:-1]
            HystRec["citations"] = "This study"
        else:
            if irm_init:
                pmagplotlib.clearFIG(HDD['irm'])
        if len(Bimag) > 0:
            if verbose and make_plots:
                print('plotting initial magnetization curve')
# first normalize by Ms
            Mnorm = []
            for m in Mimag:
                Mnorm.append(m / float(hpars['hysteresis_ms_moment']))
            if imag_init == 0:
                HDD['imag'] = 4
                if make_plots and (not save_plots):
                    pmagplotlib.plot_init(HDD['imag'], 5, 5)
                imag_init = 1
            pmagplotlib.plot_imag(HDD['imag'], Bimag, Mnorm, imag_exp)
        else:
            if imag_init:
                pmagplotlib.clearFIG(HDD['imag'])
        if len(list(HystRec.keys())) > 0:
            HystRecs.append(HystRec)
    #
        files = {}
        if save_plots and make_plots:
            if pltspec:
                s = pltspec
            else:
                s = specimen
            files = {}
            for key in list(HDD.keys()):
                if incl_directory:
                    files[key] = os.path.join(output_dir_path, s+'_'+key+'.'+fmt)
                else:
                    files[key] = s+'_'+key+'.'+fmt
            if make_plots and save_plots:
                pmagplotlib.save_plots(HDD, files, incl_directory=incl_directory)
            #if pltspec:
            #    return True, []
        if interactive:
            pmagplotlib.draw_figs(HDD)
            ans = input(
                "S[a]ve plots, [s]pecimen name, [q]uit, <return> to continue\n ")
            if ans == "a":
                files = {}
                for key in list(HDD.keys()):
                    if incl_directory:
                        files[key] = os.path.join(output_dir_path, specimen+'_'+key+'.'+fmt)
                    else:
                        files[key] = specimen+'_'+key+'.'+fmt
                pmagplotlib.save_plots(HDD, files, incl_directory=incl_directory)
            if ans == '':
                k += 1
            if ans == "p":
                del HystRecs[-1]
                k -= 1
            if ans == 'q':
                print("Good bye")
                return True, []
            if ans == 's':
                keepon = 1
                specimen = input(
                    'Enter desired specimen name (or first part there of): ')
                while keepon == 1:
                    try:
                        k = sids.index(specimen)
                        keepon = 0
                    except:
                        tmplist = []
                        for qq in range(len(sids)):
                            if specimen in sids[qq]:
                                tmplist.append(sids[qq])
                        print(specimen, " not found, but this was: ")
                        print(tmplist)
                        specimen = input('Select one or try again\n ')
                        k = sids.index(specimen)

        else:
            k += 1
        if len(B) == 0 and len(Bdcd) == 0:
            if verbose:
                print('skipping this one - no hysteresis data')
            k += 1
        if k < len(sids):
            # must re-init figs for Windows to keep size
            if make_plots and set_env.IS_WIN:
                if not save_plots:
                    pmagplotlib.plot_init(HDD['DdeltaM'], 5, 5)
                    pmagplotlib.plot_init(HDD['deltaM'], 5, 5)
                    pmagplotlib.plot_init(HDD['hyst'], 5, 5)
                if len(Bimag) > 0:
                    HDD['imag'] = 4
                    if not save_plots:
                        pmagplotlib.plot_init(HDD['imag'], 5, 5)
                if len(Bdcd) > 0:
                    HDD['irm'] = 5 if 'imag' in HDD else 4
                    if not save_plots:
                        pmagplotlib.plot_init(HDD['irm'], 5, 5)
            elif not make_plots and set_env.IS_WIN:
                HDD['hyst'], HDD['deltaM'], HDD['DdeltaM'], HDD['irm'], HDD['imag'] = 0, 0, 0, 0, 0
    if len(HystRecs) > 0:
        #  go through prior_data, clean out prior results and save combined file as spec_file
        SpecRecs, keys = [], list(HystRecs[0].keys())
        if len(prior_data) > 0:
            prior_keys = list(prior_data[0].keys())
        else:
            prior_keys = []
        for rec in prior_data:
            for key in keys:
                if key not in list(rec.keys()):
                    rec[key] = ""
            if 'LP-HYS' not in rec['method_codes']:
                SpecRecs.append(rec)
        for rec in HystRecs:
            for key in prior_keys:
                if key not in list(rec.keys()):
                    rec[key] = ""
            prior = pmag.get_dictitem(
                prior_data, 'specimen', rec['specimen'], 'T')
            if len(prior) > 0 and 'sample' in list(prior[0].keys()):
                # pull sample name from prior specimens table
                rec['sample'] = prior[0]['sample']
            SpecRecs.append(rec)
        # drop unnecessary/duplicate rows
        #dir_path = os.path.split(spec_file)[0]
        con = cb.Contribution(input_dir_path, read_tables=[])
        con.add_magic_table_from_data('specimens', SpecRecs)
        con.tables['specimens'].drop_duplicate_rows(
            ignore_cols=['specimen', 'sample', 'citations', 'software_packages'])
        con.tables['specimens'].df = con.tables['specimens'].df.drop_duplicates()
        spec_file = os.path.join(output_dir_path, os.path.split(spec_file)[1])
        con.write_table_to_file('specimens', custom_name=spec_file)
        if verbose:
            print("hysteresis parameters saved in ", spec_file)
        return True, [spec_file]

Response: This function calculates parameters and plots hysteresis data for a single specimen and returns a tuple of True if conversion was sucessful False otherwise.


Instruction:
Write a Python 3 function for
extracting directional and/or intensity data from a MagIC 3.0 format sites.txt file. Default output format is an Excel file. Optional latex format longtable file which can be uploaded to Overleaf or typeset with latex on your own computer. Parameters ___________ site_file : str input file name directions_file : str output file name for directional data intensity_file : str output file name for intensity data site_info : str output file name for site information (lat, lon, location, age....) output_dir_path : str path for output files input_dir_path : str path for intput file if different from output_dir_path (default is same) latex : boolean if True, output file should be latex formatted table with a .tex ending Return : [True,False], error type : True if successful Effects : writes Excel or LaTeX formatted tables for use in publications

Response:
def sites_extract(site_file='sites.txt', directions_file='directions.xls',
                  intensity_file='intensity.xls', info_file='site_info.xls',
                  output_dir_path='.', input_dir_path='', latex=False):
    """
    Extracts directional and/or intensity data from a MagIC 3.0 format sites.txt file.
    Default output format is an Excel file.
    Optional latex format longtable file which can be uploaded to Overleaf or
    typeset with latex on your own computer.

    Parameters
    ___________
    site_file : str
         input file name
    directions_file : str
          output file name for directional data
    intensity_file : str
          output file name for intensity data
    site_info : str
          output file name for site information (lat, lon, location, age....)
    output_dir_path : str
          path for output files
    input_dir_path : str
          path for intput file if different from output_dir_path (default is same)
    latex : boolean
           if True, output file should be latex formatted table with a .tex ending

    Return :
        [True,False], error type : True if successful

    Effects :
        writes Excel or LaTeX formatted tables for use in publications
    """
    # initialize outfile names
    input_dir_path, output_dir_path = pmag.fix_directories(input_dir_path, output_dir_path)
    try:
        fname = pmag.resolve_file_name(site_file, input_dir_path)
    except IOError:
        print("bad site file name")
        return False, "bad site file name"
    sites_df = pd.read_csv(fname, sep='\t', header=1)
    dir_df = map_magic.convert_site_dm3_table_directions(sites_df)
    dir_file = pmag.resolve_file_name(directions_file, output_dir_path)
    if len(dir_df):
        if latex:
            if dir_file.endswith('.xls'):
                dir_file = dir_file[:-4] + ".tex"
            directions_out = open(dir_file, 'w+', errors="backslashreplace")
            directions_out.write('\documentclass{article}\n')
            directions_out.write('\\usepackage{booktabs}\n')
            directions_out.write('\\usepackage{longtable}\n')
            directions_out.write('\\begin{document}')
            directions_out.write(dir_df.to_latex(
                index=False, longtable=True, multicolumn=False))
            directions_out.write('\end{document}\n')
            directions_out.close()
        else:
            dir_df.to_excel(dir_file, index=False)
    else:
        print("No directional data for ouput.")
        dir_file = None
    intensity_file = pmag.resolve_file_name(intensity_file, output_dir_path)
    int_df = map_magic.convert_site_dm3_table_intensity(sites_df)
    if len(int_df):
        if latex:
            if intensity_file.endswith('.xls'):
                intensity_file = intensity_file[:-4] + ".tex"
            intensities_out = open(intensity_file, 'w+',
                                   errors="backslashreplace")
            intensities_out.write('\documentclass{article}\n')
            intensities_out.write('\\usepackage{booktabs}\n')
            intensities_out.write('\\usepackage{longtable}\n')
            intensities_out.write('\\begin{document}')
            intensities_out.write(int_df.to_latex(
                index=False, longtable=True, multicolumn=False))
            intensities_out.write('\end{document}\n')
            intensities_out.close()
        else:
            int_df.to_excel(intensity_file, index=False)
    else:
        print("No intensity data for ouput.")
        intensity_file = None
# site info
    nfo_df = sites_df.dropna(subset=['lat', 'lon'])  # delete blank locations
    if len(nfo_df) > 0:
        SiteCols = ["Site", "Location", "Lat. (N)", "Long. (E)"]
        info_file = pmag.resolve_file_name(info_file, output_dir_path)
        age_cols = ['age', 'age_sigma', 'age_unit']
        for col in age_cols:
            if col not in nfo_df:
                nfo_df[col] = None
        test_age = nfo_df.dropna(subset=['age', 'age_sigma', 'age_unit'])
        if len(test_age) > 0:
            SiteCols.append("Age ")
            SiteCols.append("Age sigma")
            SiteCols.append("Units")
            nfo_df = nfo_df[['site', 'location', 'lat',
                             'lon', 'age', 'age_sigma', 'age_unit']]
        else:
            nfo_df = nfo_df[['site', 'location', 'lat', 'lon']]
        nfo_df.drop_duplicates(inplace=True)
        nfo_df.columns = SiteCols
        nfo_df.fillna(value='', inplace=True)
        if latex:
            if info_file.endswith('.xls'):
                info_file = info_file[:-4] + ".tex"
            info_out = open(info_file, 'w+', errors="backslashreplace")
            info_out.write('\documentclass{article}\n')
            info_out.write('\\usepackage{booktabs}\n')
            info_out.write('\\usepackage{longtable}\n')
            info_out.write('\\begin{document}')
            info_out.write(nfo_df.to_latex(
                index=False, longtable=True, multicolumn=False))
            info_out.write('\end{document}\n')
            info_out.close()
        else:
            nfo_df.to_excel(info_file, index=False)
    else:
        print("No location information  for ouput.")
        info_file = None
    return True, [fname for fname in [info_file, intensity_file, dir_file] if fname]


Instruction:
Given the following Python 3 function, write the documentation
def specimens_extract(spec_file='specimens.txt', output_file='specimens.xls', landscape=False,
                      longtable=False, output_dir_path='.', input_dir_path='', latex=False):
    """
    Extracts specimen results  from a MagIC 3.0 format specimens.txt file.
    Default output format is an Excel file.
    typeset with latex on your own computer.

    Parameters
    ___________
    spec_file : str, default "specimens.txt"
         input file name
    output_file : str, default "specimens.xls"
         output file name
    landscape : boolean, default False
           if True output latex landscape table
    longtable : boolean
           if True output latex longtable
    output_dir_path : str, default "."
        output file directory
    input_dir_path : str, default ""
          path for intput file if different from output_dir_path (default is same)
    latex : boolean, default False
           if True, output file should be latex formatted table with a .tex ending

    Return :
        [True,False],  data table error type : True if successful

    Effects :
        writes xls or latex formatted tables for use in publications
    """
    input_dir_path, output_dir_path = pmag.fix_directories(input_dir_path, output_dir_path)
    try:
        fname = pmag.resolve_file_name(spec_file, input_dir_path)
    except IOError:
        print("bad specimen file name")
        return False, "bad specimen file name"
    spec_df = pd.read_csv(fname, sep='\t', header=1)
    spec_df.dropna('columns', how='all', inplace=True)
    if 'int_abs' in spec_df.columns:
        spec_df.dropna(subset=['int_abs'], inplace=True)
    if len(spec_df) > 0:
        table_df = map_magic.convert_specimen_dm3_table(spec_df)
        out_file = pmag.resolve_file_name(output_file, output_dir_path)
        if latex:
            if out_file.endswith('.xls'):
                out_file = out_file.rsplit('.')[0] + ".tex"
            info_out = open(out_file, 'w+', errors="backslashreplace")
            info_out.write('\documentclass{article}\n')
            info_out.write('\\usepackage{booktabs}\n')
            if landscape:
                info_out.write('\\usepackage{lscape}')
            if longtable:
                info_out.write('\\usepackage{longtable}\n')
            info_out.write('\\begin{document}\n')
            if landscape:
                info_out.write('\\begin{landscape}\n')
            info_out.write(table_df.to_latex(index=False, longtable=longtable,
                                             escape=True, multicolumn=False))
            if landscape:
                info_out.write('\end{landscape}\n')
            info_out.write('\end{document}\n')
            info_out.close()
        else:
            table_df.to_excel(out_file, index=False)

    else:
        print("No specimen data   for ouput.")
    return True, [out_file]

Response: This function extracts specimen results from a MagIC 3. 0 format specimens. txt file and returns a list of lists of boolean values.


Instruction:
How would you code a function in Python 3 to
extract criteria from a MagIC 3.0 format criteria.txt file. Default output format is an Excel file. typeset with latex on your own computer. Parameters ___________ crit_file : str, default "criteria.txt" input file name output_file : str, default "criteria.xls" output file name output_dir_path : str, default "." output file directory input_dir_path : str, default "" path for intput file if different from output_dir_path (default is same) latex : boolean, default False if True, output file should be latex formatted table with a .tex ending Return : [True,False], data table error type : True if successful Effects : writes xls or latex formatted tables for use in publications

Response:
def criteria_extract(crit_file='criteria.txt', output_file='criteria.xls',
                     output_dir_path='.', input_dir_path='', latex=False):
    """
    Extracts criteria  from a MagIC 3.0 format criteria.txt file.
    Default output format is an Excel file.
    typeset with latex on your own computer.

    Parameters
    ___________
    crit_file : str, default "criteria.txt"
         input file name
    output_file : str, default "criteria.xls"
         output file name
    output_dir_path : str, default "."
        output file directory
    input_dir_path : str, default ""
          path for intput file if different from output_dir_path (default is same)
    latex : boolean, default False
           if True, output file should be latex formatted table with a .tex ending

    Return :
        [True,False],  data table error type : True if successful

    Effects :
        writes xls or latex formatted tables for use in publications
    """
    input_dir_path, output_dir_path = pmag.fix_directories(input_dir_path, output_dir_path)
    try:
        fname = pmag.resolve_file_name(crit_file, input_dir_path)
    except IOError:
        print("bad criteria file name")
        return False, "bad criteria file name"
    crit_df = pd.read_csv(fname, sep='\t', header=1)
    if len(crit_df) > 0:
        out_file = pmag.resolve_file_name(output_file, output_dir_path)

        s = crit_df['table_column'].str.split(pat='.', expand=True)
        crit_df['table'] = s[0]
        crit_df['column'] = s[1]
        crit_df = crit_df[['table', 'column',
                           'criterion_value', 'criterion_operation']]

        crit_df.columns = ['Table', 'Statistic', 'Threshold', 'Operation']

        if latex:
            if out_file.endswith('.xls'):
                out_file = out_file.rsplit('.')[0] + ".tex"
            crit_df.loc[crit_df['Operation'].str.contains(
                '<'), 'operation'] = 'maximum'
            crit_df.loc[crit_df['Operation'].str.contains(
                '>'), 'operation'] = 'minimum'
            crit_df.loc[crit_df['Operation'] == '=', 'operation'] = 'equal to'
            info_out = open(out_file, 'w+', errors="backslashreplace")
            info_out.write('\documentclass{article}\n')
            info_out.write('\\usepackage{booktabs}\n')
            # info_out.write('\\usepackage{longtable}\n')
            # T1 will ensure that symbols like '<' are formatted correctly
            info_out.write("\\usepackage[T1]{fontenc}\n")
            info_out.write('\\begin{document}')
            info_out.write(crit_df.to_latex(index=False, longtable=False,
                                            escape=True, multicolumn=False))
            info_out.write('\end{document}\n')
            info_out.close()
        else:
            crit_df.to_excel(out_file, index=False)

    else:
        print("No criteria   for ouput.")
    return True, [out_file]


Instruction:
Here you have a function in Python 3, explain what it does
def eqarea_magic(in_file='sites.txt', dir_path=".", input_dir_path="",
            spec_file="specimens.txt", samp_file="samples.txt",
            site_file="sites.txt", loc_file="locations.txt",
            plot_by="all", crd="g", ignore_tilt=False,
            save_plots=True, fmt="svg", contour=False, color_map="coolwarm",
            plot_ell="", n_plots=5, interactive=False):

    """
    makes equal area projections from declination/inclination data

    Parameters
    ----------
    in_file : str, default "sites.txt"
    dir_path : str
        output directory, default "."
    input_dir_path : str
        input file directory (if different from dir_path), default ""
    spec_file : str
        input specimen file name, default "specimens.txt"
    samp_file: str
        input sample file name, default "samples.txt"
    site_file : str
        input site file name, default "sites.txt"
    loc_file : str
        input location file name, default "locations.txt"
    plot_by : str
        [spc, sam, sit, loc, all] (specimen, sample, site, location, all), default "all"
    crd : ['s','g','t'], coordinate system for plotting whereby:
        s : specimen coordinates, aniso_tile_correction = -1
        g : geographic coordinates, aniso_tile_correction = 0 (default)
        t : tilt corrected coordinates, aniso_tile_correction = 100
    ignore_tilt : bool
        default False.  If True, data are unoriented (allows plotting of measurement dec/inc)
    save_plots : bool
        plot and save non-interactively, default True
    fmt : str
        ["png", "svg", "pdf", "jpg"], default "svg"
    contour : bool
        plot as color contour
    colormap : str
        color map for contour plotting, default "coolwarm"
        see cartopy documentation for more options
    plot_ell : str
        [F,K,B,Be,Bv] plot Fisher, Kent, Bingham, Bootstrap ellipses or Boostrap eigenvectors
        default "" plots none
    n_plots : int
        maximum number of plots to make, default 5
        if you want to make all possible plots, specify "all"
    interactive : bool, default False
        interactively plot and display for each specimen
        (this is best used on the command line or in the Python interpreter)

    Returns
    ---------
    type - Tuple : (True or False indicating if conversion was sucessful, file name(s) written)
    """
    saved = []
    # parse out input/out directories
    input_dir_path, dir_path = pmag.fix_directories(input_dir_path, dir_path)
    # initialize some variables
    verbose = pmagplotlib.verbose
    FIG = {}  # plot dictionary
    FIG['eqarea'] = 1  # eqarea is figure 1
    pmagplotlib.plot_init(FIG['eqarea'], 5, 5)
    # get coordinate system
    if crd == "s":
        coord = "-1"
    elif crd == "t":
        coord = "100"
    else:
        coord = "0"
    # get item to plot by
    if plot_by == 'all':
        plot_key = 'all'
    elif plot_by == 'sit':
        plot_key = 'site'
    elif plot_by == 'sam':
        plot_key = 'sample'
    elif plot_by == 'spc':
        plot_key = 'specimen'
    else:
        plot_by = 'all'
        plot_key = 'all'
    # get distribution to plot ellipses/eigenvectors if desired

    if save_plots:
        verbose = False

    # set keys
    dec_key = 'dir_dec'
    inc_key = 'dir_inc'
    tilt_key = 'dir_tilt_correction'

    # create contribution
    fnames = {"specimens": spec_file, "samples": samp_file,
              'sites': site_file, 'locations': loc_file}

    if not os.path.exists(pmag.resolve_file_name(in_file, input_dir_path)):
        print('-E- Could not find {}'.format(in_file))
        return False, []

    contribution = cb.Contribution(input_dir_path, custom_filenames=fnames,
                                   single_file=in_file)
    table_name = list(contribution.tables.keys())[0]
    contribution.add_magic_table("contribution")

    # get contribution id if available for server plots
    if pmagplotlib.isServer:
        con_id = contribution.get_con_id()
    # try to propagate all names to measurement level
    try:
        contribution.propagate_location_to_samples()
        contribution.propagate_location_to_specimens()
        contribution.propagate_location_to_measurements()
    except KeyError as ex:
        pass

    # the object that contains the DataFrame + useful helper methods:
    data_container = contribution.tables[table_name]
    # the actual DataFrame:
    data = data_container.df
    plot_type = data_container.dtype

    if plot_key != "all" and plot_key not in data.columns:
        print("-E- You can't plot by {} with the data provided".format(plot_key))
        return False, []

    # add tilt key into DataFrame columns if it isn't there already
    if tilt_key not in data.columns:
        data.loc[:, tilt_key] = None

    if verbose:
        print(len(data), ' records read from ', in_file)

    # find desired dec,inc data:
    dir_type_key = ''
    #
    # get plotlist if not plotting all records
    #
    plotlist = []
    if plot_key != "all":

        # return all where plot_key is not blank
        if plot_key not in data.columns:
            print('-E- Can\'t plot by "{}".  That header is not in infile: {}'.format(
                plot_key, in_file))
            return False, []
        plots = data[data[plot_key].notnull()]
        plotlist = plots[plot_key].unique()  # grab unique values
    else:
        plotlist.append('All')

    if n_plots != "all":
        if len(plotlist) > n_plots:
            plotlist = plotlist[:n_plots]
    fignum = 0
    for plot in plotlist:
        fignum += 1
        FIG['eqarea'] = fignum
        pmagplotlib.plot_init(FIG['eqarea'], 5, 5)
        if plot_ell:
            dist = plot_ell.upper()
            # if dist type is unrecognized, use Fisher
            if dist not in ['F', 'K', 'B', 'BE', 'BV']:
                dist = 'F'
            if dist == "BV":
                fignum += 1
                FIG['bdirs'] = fignum
                pmagplotlib.plot_init(FIG['bdirs'], 5, 5)

        if verbose:
            print(plot)
        if plot == 'All':
            # plot everything at once
            plot_data = data
        else:
            # pull out only partial data
            plot_data = data[data[plot_key] == plot]

        # get location names for the data
        locs = []
        if 'location' in plot_data.columns:
            locs = plot_data['location'].dropna().unique()

        DIblock = []
        GCblock = []
        # SLblock, SPblock = [], []
        title = plot
        mode = 1

        if dec_key not in plot_data.columns:
            print("-W- No dec/inc data")
            continue
        # get all records where dec & inc values exist
        plot_data = plot_data[plot_data[dec_key].notnull()
                              & plot_data[inc_key].notnull()]
        if plot_data.empty:
            print("-W- No dec/inc data")
            continue

        # get metadata for naming the plot file
        locations = str(data_container.get_name('location', df_slice=plot_data))
        site = str(data_container.get_name('site', df_slice=plot_data))
        sample = str(data_container.get_name('sample', df_slice=plot_data))
        specimen = str(data_container.get_name('specimen', df_slice=plot_data))

        # make sure method_codes is in plot_data
        if 'method_codes' not in plot_data.columns:
            plot_data['method_codes'] = ''

        # get data blocks
        # would have to ignore tilt to use measurement level data
        DIblock = data_container.get_di_block(df_slice=plot_data,
                                              tilt_corr=coord, excl=['DE-BFP'], ignore_tilt=ignore_tilt)

        if title == 'All':
            if len(locs):
                title = " ,".join(locs) + " - {} {} plotted".format(str(len(DIblock)), plot_type)
            else:
                title = "{} {} plotted".format(str(len(DIblock)), plot_type)
        #SLblock = [[ind, row['method_codes']] for ind, row in plot_data.iterrows()]
        # get great circles
        great_circle_data = data_container.get_records_for_code('DE-BFP', incl=True,
                                                                use_slice=True, sli=plot_data)

        if len(great_circle_data) > 0:
            gc_cond = great_circle_data[tilt_key] == coord
            GCblock = [[float(row[dec_key]), float(row[inc_key])]
                       for ind, row in great_circle_data[gc_cond].iterrows()]
            #SPblock = [[ind, row['method_codes']] for ind, row in great_circle_data[gc_cond].iterrows()]

        if len(DIblock) > 0:
            if not contour:
                pmagplotlib.plot_eq(FIG['eqarea'], DIblock, title)
            else:
                pmagplotlib.plot_eq_cont(
                    FIG['eqarea'], DIblock, color_map=color_map)
        else:
            pmagplotlib.plot_net(FIG['eqarea'])
        if len(GCblock) > 0:
            for rec in GCblock:
                pmagplotlib.plot_circ(FIG['eqarea'], rec, 90., 'g')
        if len(DIblock) == 0 and len(GCblock) == 0:
            if verbose:
                print("no records for plotting")
                fignum -= 1
                if 'bdirs' in FIG:
                    fignum -= 1
            continue
            # sys.exit()
        if plot_ell:
            ppars = pmag.doprinc(DIblock)  # get principal directions
            nDIs, rDIs, npars, rpars = [], [], [], []
            for rec in DIblock:
                angle = pmag.angle([rec[0], rec[1]], [
                                   ppars['dec'], ppars['inc']])
                if angle > 90.:
                    rDIs.append(rec)
                else:
                    nDIs.append(rec)
            if dist == 'B':  # do on whole dataset
                etitle = "Bingham confidence ellipse"
                bpars = pmag.dobingham(DIblock)
                for key in list(bpars.keys()):
                    if key != 'n' and verbose:
                        print("    ", key, '%7.1f' % (bpars[key]))
                    if key == 'n' and verbose:
                        print("    ", key, '       %i' % (bpars[key]))
                npars.append(bpars['dec'])
                npars.append(bpars['inc'])
                npars.append(bpars['Zeta'])
                npars.append(bpars['Zdec'])
                npars.append(bpars['Zinc'])
                npars.append(bpars['Eta'])
                npars.append(bpars['Edec'])
                npars.append(bpars['Einc'])
            if dist == 'F':
                etitle = "Fisher confidence cone"
                if len(nDIs) > 2:
                    fpars = pmag.fisher_mean(nDIs)
                    for key in list(fpars.keys()):
                        if key != 'n' and verbose:
                            print("    ", key, '%7.1f' % (fpars[key]))
                        if key == 'n' and verbose:
                            print("    ", key, '       %i' % (fpars[key]))
                    mode += 1
                    npars.append(fpars['dec'])
                    npars.append(fpars['inc'])
                    npars.append(fpars['alpha95'])  # Beta
                    npars.append(fpars['dec'])
                    isign = abs(fpars['inc']) / fpars['inc']
                    npars.append(fpars['inc']-isign*90.)  # Beta inc
                    npars.append(fpars['alpha95'])  # gamma
                    npars.append(fpars['dec']+90.)  # Beta dec
                    npars.append(0.)  # Beta inc
                if len(rDIs) > 2:
                    fpars = pmag.fisher_mean(rDIs)
                    if verbose:
                        print("mode ", mode)
                    for key in list(fpars.keys()):
                        if key != 'n' and verbose:
                            print("    ", key, '%7.1f' % (fpars[key]))
                        if key == 'n' and verbose:
                            print("    ", key, '       %i' % (fpars[key]))
                    mode += 1
                    rpars.append(fpars['dec'])
                    rpars.append(fpars['inc'])
                    rpars.append(fpars['alpha95'])  # Beta
                    rpars.append(fpars['dec'])
                    isign = abs(fpars['inc']) / fpars['inc']
                    rpars.append(fpars['inc']-isign*90.)  # Beta inc
                    rpars.append(fpars['alpha95'])  # gamma
                    rpars.append(fpars['dec']+90.)  # Beta dec
                    rpars.append(0.)  # Beta inc
            if dist == 'K':
                etitle = "Kent confidence ellipse"
                if len(nDIs) > 3:
                    kpars = pmag.dokent(nDIs, len(nDIs))
                    if verbose:
                        print("mode ", mode)
                    for key in list(kpars.keys()):
                        if key != 'n' and verbose:
                            print("    ", key, '%7.1f' % (kpars[key]))
                        if key == 'n' and verbose:
                            print("    ", key, '       %i' % (kpars[key]))
                    mode += 1
                    npars.append(kpars['dec'])
                    npars.append(kpars['inc'])
                    npars.append(kpars['Zeta'])
                    npars.append(kpars['Zdec'])
                    npars.append(kpars['Zinc'])
                    npars.append(kpars['Eta'])
                    npars.append(kpars['Edec'])
                    npars.append(kpars['Einc'])
                if len(rDIs) > 3:
                    kpars = pmag.dokent(rDIs, len(rDIs))
                    if verbose:
                        print("mode ", mode)
                    for key in list(kpars.keys()):
                        if key != 'n' and verbose:
                            print("    ", key, '%7.1f' % (kpars[key]))
                        if key == 'n' and verbose:
                            print("    ", key, '       %i' % (kpars[key]))
                    mode += 1
                    rpars.append(kpars['dec'])
                    rpars.append(kpars['inc'])
                    rpars.append(kpars['Zeta'])
                    rpars.append(kpars['Zdec'])
                    rpars.append(kpars['Zinc'])
                    rpars.append(kpars['Eta'])
                    rpars.append(kpars['Edec'])
                    rpars.append(kpars['Einc'])
            else:  # assume bootstrap
                if dist == 'BE':
                    if len(nDIs) > 5:
                        BnDIs = pmag.di_boot(nDIs)
                        Bkpars = pmag.dokent(BnDIs, 1.)
                        if verbose:
                            print("mode ", mode)
                        for key in list(Bkpars.keys()):
                            if key != 'n' and verbose:
                                print("    ", key, '%7.1f' % (Bkpars[key]))
                            if key == 'n' and verbose:
                                print("    ", key, '       %i' % (Bkpars[key]))
                        mode += 1
                        npars.append(Bkpars['dec'])
                        npars.append(Bkpars['inc'])
                        npars.append(Bkpars['Zeta'])
                        npars.append(Bkpars['Zdec'])
                        npars.append(Bkpars['Zinc'])
                        npars.append(Bkpars['Eta'])
                        npars.append(Bkpars['Edec'])
                        npars.append(Bkpars['Einc'])
                    if len(rDIs) > 5:
                        BrDIs = pmag.di_boot(rDIs)
                        Bkpars = pmag.dokent(BrDIs, 1.)
                        if verbose:
                            print("mode ", mode)
                        for key in list(Bkpars.keys()):
                            if key != 'n' and verbose:
                                print("    ", key, '%7.1f' % (Bkpars[key]))
                            if key == 'n' and verbose:
                                print("    ", key, '       %i' % (Bkpars[key]))
                        mode += 1
                        rpars.append(Bkpars['dec'])
                        rpars.append(Bkpars['inc'])
                        rpars.append(Bkpars['Zeta'])
                        rpars.append(Bkpars['Zdec'])
                        rpars.append(Bkpars['Zinc'])
                        rpars.append(Bkpars['Eta'])
                        rpars.append(Bkpars['Edec'])
                        rpars.append(Bkpars['Einc'])
                    etitle = "Bootstrapped confidence ellipse"
                elif dist == 'BV':
                    sym = {'lower': ['o', 'c'], 'upper': [
                        'o', 'g'], 'size': 3, 'edgecolor': 'face'}
                    if len(nDIs) > 5:
                        BnDIs = pmag.di_boot(nDIs)
                        pmagplotlib.plot_eq_sym(
                            FIG['bdirs'], BnDIs, 'Bootstrapped Eigenvectors', sym)
                    if len(rDIs) > 5:
                        BrDIs = pmag.di_boot(rDIs)
                        if len(nDIs) > 5:  # plot on existing plots
                            pmagplotlib.plot_di_sym(FIG['bdirs'], BrDIs, sym)
                        else:
                            pmagplotlib.plot_eq(
                                FIG['bdirs'], BrDIs, 'Bootstrapped Eigenvectors')
            if dist == 'B':
                if len(nDIs) > 3 or len(rDIs) > 3:
                    pmagplotlib.plot_conf(FIG['eqarea'], etitle, [], npars, 0)
            elif len(nDIs) > 3 and dist != 'BV':
                pmagplotlib.plot_conf(FIG['eqarea'], etitle, [], npars, 0)
                if len(rDIs) > 3:
                    pmagplotlib.plot_conf(FIG['eqarea'], etitle, [], rpars, 0)
            elif len(rDIs) > 3 and dist != 'BV':
                pmagplotlib.plot_conf(FIG['eqarea'], etitle, [], rpars, 0)

        for key in list(FIG.keys()):
            files = {}
            #if filename:  # use provided filename
            #    filename += '.' + fmt
            if pmagplotlib.isServer:  # use server plot naming convention
                if plot_key == 'all':
                    filename = 'LO:_'+locations+'_SI:__SA:__SP:__CO:_'+crd+'_TY:_'+key+'_.'+fmt
                else:
                    filename = 'LO:_'+locations+'_SI:_'+site+'_SA:_'+sample + \
                        '_SP:_'+str(specimen)+'_CO:_'+crd+'_TY:_'+key+'_.'+fmt
            elif plot_key == 'all':
                filename = 'all'
                if locs:
                    loc_string = "_".join(
                        [str(loc).replace(' ', '_') for loc in locs])
                    filename += "_" + loc_string
                filename += "_" + crd + "_" + key
                filename += ".{}".format(fmt)
            else:  # use more readable naming convention
                filename = ''
                # fix this if plot_by is location , for example
                use_names = {'location': [locations], 'site': [locations, site],
                             'sample': [locations, site, sample],
                             'specimen': [locations, site, sample, specimen]}
                use = use_names[plot_key]
                use.extend([crd, key])
                # [locations, site, sample, specimen, crd, key]:
                for item in use:
                    if item:
                        item = item.replace(' ', '_')
                        filename += item + '_'
                if filename.endswith('_'):
                    filename = filename[:-1]
                filename += ".{}".format(fmt)

            if not pmagplotlib.isServer:
                filename = os.path.join(dir_path, filename)
            files[key] = filename

        if pmagplotlib.isServer:
            titles = {'eqarea': 'Equal Area Plot'}
            FIG = pmagplotlib.add_borders(FIG, titles, con_id=con_id)
            saved_figs = pmagplotlib.save_plots(FIG, files)
            saved.extend(saved_figs)

        elif save_plots:
            saved_figs = pmagplotlib.save_plots(FIG, files, incl_directory=True)
            saved.extend(saved_figs)
            continue
        elif interactive:
            pmagplotlib.draw_figs(FIG)
            ans = input(" S[a]ve to save plot, [q]uit, Return to continue:  ")
            if ans == "q":
                return True, []
            if ans == "a":
                saved_figs = pmagplotlib.save_plots(FIG, files, incl_directory=True)
                saved.extend(saved)
        continue
    return True, saved

Response: This function makes an equal area projection from the declination and inclination data.


Instruction:
Create a Python 3 function for
using a MagIC format locations table to plot poles. Parameters ---------- loc_file : str, default "locations.txt" dir_path : str, default "." directory name to find loc_file in (if not included in loc_file) interactive : bool, default False if True, interactively plot and display (this is best used on the command line only) crd : str, default "" coordinate system [g, t] (geographic, tilt_corrected) sym : str, default "ro" symbol color and shape, default red circles (see matplotlib documentation for more options) symsize : int, default 40 symbol size rsym : str, default "g^" symbol for plotting reverse poles rsymsize : int, default 40 symbol size for reverse poles fmt : str, default "pdf" format for figures, ["svg", "jpg", "pdf", "png"] res : str, default "c" resolution [c, l, i, h] (crude, low, intermediate, high) proj : str, default "ortho" ortho = orthographic lcc = lambert conformal moll = molweide merc = mercator flip : bool, default False if True, flip reverse poles to normal antipode anti : bool, default False if True, plot antipodes for each pole fancy : bool, default False if True, plot topography (not yet implementedj) ell : bool, default False if True, plot ellipses ages : bool, default False if True, plot ages lat_0 : float, default 90. eyeball latitude lon_0 : float, default 0. eyeball longitude save_plots : bool, default True if True, create and save all requested plots

Response:
def polemap_magic(loc_file="locations.txt", dir_path=".", interactive=False, crd="",
                  sym='ro', symsize=40, rsym='g^', rsymsize=40,
                  fmt="pdf", res="c", proj="ortho",
                  flip=False, anti=False, fancy=False,
                  ell=False, ages=False, lat_0=90., lon_0=0., save_plots=True):
    """
    Use a MagIC format locations table to plot poles.

    Parameters
    ----------
    loc_file : str, default "locations.txt"
    dir_path : str, default "."
        directory name to find loc_file in (if not included in loc_file)
    interactive : bool, default False
       if True, interactively plot and display
        (this is best used on the command line only)
    crd : str, default ""
       coordinate system [g, t] (geographic, tilt_corrected)
    sym : str, default "ro"
        symbol color and shape, default red circles
        (see matplotlib documentation for more options)
    symsize : int, default 40
        symbol size
    rsym : str, default "g^"
        symbol for plotting reverse poles
    rsymsize : int, default 40
        symbol size for reverse poles
    fmt : str, default "pdf"
        format for figures, ["svg", "jpg", "pdf", "png"]
    res : str, default "c"
        resolution [c, l, i, h] (crude, low, intermediate, high)
    proj : str, default "ortho"
        ortho = orthographic
        lcc = lambert conformal
        moll = molweide
        merc = mercator
    flip : bool, default False
        if True, flip reverse poles to normal antipode
    anti : bool, default False
        if True, plot antipodes for each pole
    fancy : bool, default False
        if True, plot topography (not yet implementedj)
    ell : bool, default False
        if True, plot ellipses
    ages : bool, default False
        if True, plot ages
    lat_0 : float, default 90.
        eyeball latitude
    lon_0 : float, default 0.
        eyeball longitude
    save_plots : bool, default True
        if True, create and save all requested plots
    """
    # initialize and format variables
    saved = []
    lats, lons = [], []
    Pars = []
    dates, rlats, rlons = [], [], []
    polarities = []
    if interactive:
        save_plots = False
    full_path = pmag.resolve_file_name(loc_file, dir_path)
    dir_path, loc_file = os.path.split(full_path)
    # create MagIC contribution
    con = cb.Contribution(dir_path, single_file=loc_file)
    if not list(con.tables.keys()):
        print("-W - Couldn't read in data")
        return False, "Couldn't read in data"
    FIG = {'map': 1}
    pmagplotlib.plot_init(FIG['map'], 6, 6)

    pole_container = con.tables['locations']
    pole_df = pole_container.df
    if 'pole_lat' not in pole_df.columns or 'pole_lon' not in pole_df.columns:
        print("-W- pole_lat and pole_lon are required columns to run polemap_magic.py")
        return False, "pole_lat and pole_lon are required columns to run polemap_magic.py"
    # use records with pole_lat and pole_lon
    cond1, cond2 = pole_df['pole_lat'].notnull(), pole_df['pole_lon'].notnull()
    Results = pole_df[cond1 & cond2]
    # don't plot identical poles twice
    Results.drop_duplicates(subset=['pole_lat', 'pole_lon', 'location'], inplace=True)
    # use tilt correction if available
    # prioritize tilt-corrected poles
    if 'dir_tilt_correction' in Results.columns:
        if not crd:
            coords = Results['dir_tilt_correction'].unique()
            if 100. in coords:
                crd = 't'
            elif 0. in coords:
                crd = 'g'
            else:
                crd = ''
    coord_dict = {'g': 0, 't': 100}
    coord = coord_dict[crd] if crd else ""
    # filter results by dir_tilt_correction if available
    if (coord or coord == 0) and 'dir_tilt_correction' in Results.columns:
        Results = Results[Results['dir_tilt_correction'] == coord]
    # get location name and average ages
    loc_list = Results['location'].values
    locations = ":".join(Results['location'].unique())
    if 'age' not in Results.columns and 'age_low' in Results.columns and 'age_high' in Results.columns:
        Results['age'] = Results['age_low']+0.5 * \
            (Results['age_high']-Results['age_low'])
    if 'age' in Results.columns and ages:
        dates = Results['age'].unique()

    if not any(Results.index):
        print("-W- No poles could be plotted")
        return False, "No poles could be plotted"

    # go through rows and extract data
    for ind, row in Results.iterrows():
        lat, lon = float(row['pole_lat']), float(row['pole_lon'])
        if 'dir_polarity' in row:
            polarities.append(row['dir_polarity'])
        if anti:
            lats.append(-lat)
            lon = lon + 180.
            if lon > 360:
                lon = lon - 360.
            lons.append(lon)
        elif not flip:
            lats.append(lat)
            lons.append(lon)
        elif flip:
            if lat < 0:
                rlats.append(-lat)
                lon = lon + 180.
                if lon > 360:
                    lon = lon - 360
                rlons.append(lon)
            else:
                lats.append(lat)
                lons.append(lon)
        ppars = []
        ppars.append(lon)
        ppars.append(lat)
        ell1, ell2 = "", ""
        if 'pole_dm' in list(row.keys()) and row['pole_dm']:
            ell1 = float(row['pole_dm'])
        if 'pole_dp' in list(row.keys()) and row['pole_dp']:
            ell2 = float(row['pole_dp'])
        if 'pole_alpha95' in list(row.keys()) and row['pole_alpha95']:
            ell1, ell2 = float(row['pole_alpha95']), float(row['pole_alpha95'])
        if ell1 and ell2 and lons:
            ppars = []
            ppars.append(lons[-1])
            ppars.append(lats[-1])
            ppars.append(ell1)
            ppars.append(lons[-1])
            try:
                isign = abs(lats[-1]) / lats[-1]
            except ZeroDivisionError:
                isign = 1
            ppars.append(lats[-1] - isign * 90.)
            ppars.append(ell2)
            ppars.append(lons[-1] + 90.)
            ppars.append(0.)
            Pars.append(ppars)

    locations = locations.strip(':')
    Opts = {'latmin': -90, 'latmax': 90, 'lonmin': 0., 'lonmax': 360.,
            'lat_0': lat_0, 'lon_0': lon_0, 'proj': proj, 'sym': 'b+',
            'symsize': 40, 'pltgrid': 0, 'res': res, 'boundinglat': 0.,
            'edgecolor': 'face'}
    Opts['details'] = {'coasts': 1, 'rivers': 0, 'states': 0,
                       'countries': 0, 'ocean': 1, 'fancy': fancy}
    base_Opts = Opts.copy()

    # make the base map with a blue triangle at the pole
    pmagplotlib.plot_map(FIG['map'], [90.], [0.], Opts)

    #Opts['pltgrid'] = -1
    if proj=='merc':Opts['pltgrid']=1
    Opts['sym'] = sym
    Opts['symsize'] = symsize
    if len(dates) > 0:
        Opts['names'] = dates
    if len(lats) > 0:
        pole_lats = []
        pole_lons = []
        for num, lat in enumerate(lats):
            lon = lons[num]
            if lat > 0:
                pole_lats.append(lat)
                pole_lons.append(lon)
        # plot the lats and lons of the poles
        pmagplotlib.plot_map(FIG['map'], pole_lats, pole_lons, Opts)

    # do reverse poles
    if len(rlats) > 0:
        reverse_Opts = Opts.copy()
        reverse_Opts['sym'] = rsym
        reverse_Opts['symsize'] = rsymsize
        reverse_Opts['edgecolor'] = 'black'
        # plot the lats and lons of the reverse poles
        pmagplotlib.plot_map(FIG['map'], rlats, rlons, reverse_Opts)

    Opts['names'] = []
    titles = {}
    files = {}

    if pmagplotlib.isServer:
        # plot each indvidual pole for the server
        for ind in range(len(lats)):
            lat = lats[ind]
            lon = lons[ind]
            polarity = ""
            if 'polarites' in locals():
                polarity = polarities[ind]
            polarity = "_" + polarity if polarity else ""
            location = loc_list[ind]
            FIG["map_{}".format(ind)] = ind+2
            pmagplotlib.plot_init(FIG['map_{}'.format(ind)], 6, 6)
            pmagplotlib.plot_map(FIG['map_{}'.format(ind)], [90.], [0.], base_Opts)
            pmagplotlib.plot_map(ind+2, [lat], [lon], Opts)
            titles["map_{}".format(ind)] = location
            if crd:
                fname = "LO:_{}{}_TY:_POLE_map_{}.{}".format(location, polarity, crd, fmt)
                fname_short = "LO:_{}{}_TY:_POLE_map_{}".format(location, polarity, crd)
            else:
                fname = "LO:_{}{}_TY:_POLE_map.{}".format(location, polarity, fmt)
                fname_short = "LO:_{}{}_TY:_POLE_map".format(location, polarity)

            # don't allow identically named files
            if files:
                file_values = files.values()
                file_values_short = [fname.rsplit('.')[0] for fname in file_values]
                if fname_short in file_values_short:
                    for val in [str(n) for n in range(1, 10)]:
                        fname = fname_short + "_{}.".format(val) + fmt
                        if fname not in file_values:
                            break
            files["map_{}".format(ind)] = fname

    # truncate location names so that ultra long filenames are not created
    if len(locations) > 50:
        locations = locations[:50]
    if pmagplotlib.isServer:
        # use server plot naming convention
        con_id = ''
        if 'contribution' in con.tables:
            # try to get contribution id
            if 'id' in con.tables['contribution'].df.columns:
                con_id = con.tables['contribution'].df.iloc[0]['id']
            files['map'] = 'MC:_{}_TY:_POLE_map_{}.{}'.format(con_id, crd, fmt)
        else:
            # no contribution id available
            files['map'] = 'LO:_' + locations + '_TY:_POLE_map_{}.{}'.format(crd, fmt)
    else:
        # use readable naming convention for non-database use
        files['map'] = '{}_POLE_map_{}.{}'.format(locations, crd, fmt)

    #
    if interactive and (not set_env.IS_WIN):
        pmagplotlib.draw_figs(FIG)
    if ell:  # add ellipses if desired.
        Opts['details'] = {'coasts': 0, 'rivers': 0, 'states': 0,
                           'countries': 0, 'ocean': 0, 'fancy': fancy}
        Opts['pltgrid'] = -1  # turn off meridian replotting
        Opts['symsize'] = 2
        Opts['sym'] = 'g-'
        for ppars in Pars:
            if ppars[2] != 0:
                PTS = pmagplotlib.plot_ell(FIG['map'], ppars, 'g.', 0, 0)
                elats, elons = [], []
                for pt in PTS:
                    elons.append(pt[0])
                    elats.append(pt[1])
                # make the base map with a blue triangle at the pole
                pmagplotlib.plot_map(FIG['map'], elats, elons, Opts)
                if interactive and (not set_env.IS_WIN):
                    pmagplotlib.draw_figs(FIG)

    if pmagplotlib.isServer:
        black = '#000000'
        purple = '#800080'
        titles['map'] = 'LO:_' + locations + '_POLE_map'
        con_id = ''
        if 'contribution' in con.tables:
            if 'id' in con.tables['contribution'].df.columns:
                con_id = con.tables['contribution'].df.iloc[0]['id']

            loc_string = ""
            if 'locations' in con.tables:
                num_locs = len(con.tables['locations'].df.index.unique())
                loc_string = "{} location{}".format(num_locs, 's' if num_locs > 1 else '')
                num_lats = len([lat for lat in lats if lat > 0])
                num_rlats = len(rlats)
                npole_string = ""
                rpole_string = ""
                if num_lats:
                    npole_string = "{} normal ".format(num_lats) #, 's' if num_lats > 1 else '')
                if num_rlats:
                    rpole_string = "{} reverse".format(num_rlats)
                if num_lats + num_rlats > 1:
                    pole_string = "poles"
                elif num_lats + num_rlats == 0:
                    pole_string = ""
                else:
                    pole_string = "pole"
            title = "MagIC contribution {}\n {} {}{} {}".format(con_id, loc_string, npole_string, rpole_string, pole_string)
            titles['map'] = title.replace('  ', ' ')
        FIG = pmagplotlib.add_borders(FIG, titles, black, purple, con_id)
        saved = pmagplotlib.save_plots(FIG, files)
    elif interactive:
        pmagplotlib.draw_figs(FIG)
        ans = input(" S[a]ve to save plot, Return to quit:  ")
        if ans == "a":
            saved = pmagplotlib.save_plots(FIG, files)
        else:
            print("Good bye")
    elif save_plots:
        saved = pmagplotlib.save_plots(FIG, files)

    return True, saved


Instruction:
Given the following Python 3 function, write the documentation
def chi_magic(infile="measurements.txt", dir_path=".", experiments="",
              fmt="svg", save_plots=True, interactive=False, contribution=None):
    """
    Parameters
    ----------
    infile : str, default "measurements.txt"
        measurement infile
    dir_path : str, default "."
        input directory
    experiments : str, default ""
        experiment name to plot
    fmt : str, default "svg"
        format for figures, ["svg", "jpg", "pdf", "png"]
    save_plots : bool, default True
        save figures
    interactive : bool, default False
        if True, interactively plot and display
        (this is best used on the command line only)
    contribution : cb.Contribution, default None
        if provided, use Contribution object instead of reading in
        data from files

    Returns
    ---------
    (status, output_files) - Tuple : (True or False indicating if conversion was sucessful, file name(s) written)
    """
    saved = []
    if contribution:
        chi_data_all = contribution.tables['measurements'].df
    else:
        infile = pmag.resolve_file_name(infile, dir_path)
        chi_data_all = pd.read_csv(infile, sep='\t', header=1)
    if not experiments:
        try:
            experiments = chi_data_all.experiment.unique()
        except Exception as ex:
            print(ex)
            experiments = ["all"]
    else:
         experiments = [experiments]

    plotnum = 0
    figs = {}
    fnames = {}
    for exp in experiments:
        if exp == "all":
            chi_data = chi_data_all
        chi_data = chi_data_all[chi_data_all.experiment == exp]
        if len(chi_data) <= 1:
            print('Not enough data to plot {}'.format(exp))
            continue

        plotnum += 1
        if not save_plots:
            pmagplotlib.plot_init(plotnum, 5, 5)  # set up plot
        else:
            plt.figure(plotnum)
        figs[str(plotnum)] = plotnum
        fnames[str(plotnum)] = exp + '_temperature.{}'.format(fmt)

        # get arrays of available temps, frequencies and fields
        Ts = np.sort(chi_data.meas_temp.unique())
        Fs = np.sort(chi_data.meas_freq.unique())
        Bs = np.sort(chi_data.meas_field_ac.unique())

        # plot chi versus temperature at constant field
        b = Bs.max()
        for num, f in enumerate(Fs):
            this_f = chi_data[chi_data.meas_freq == f]
            this_f = this_f[this_f.meas_field_ac == b]
            plt.plot(this_f.meas_temp, 1e6*this_f.susc_chi_volume,
                     label='%i' % (f)+' Hz')
        plt.legend()
        plt.xlabel('Temperature (K)')
        plt.ylabel('$\chi$ ($\mu$SI)')
        plt.title('B = '+'%7.2e' % (b) + ' T')

        plotnum += 1
        figs[str(plotnum)] = plotnum
        fnames[str(plotnum)] = exp + '_frequency.{}'.format(fmt)

        if not save_plots:
            pmagplotlib.plot_init(plotnum, 5, 5)  # set up plot
        else:
            plt.figure(plotnum)
        ## plot chi versus frequency at constant B
        b = Bs.max()
        t = Ts.min()
        this_t = chi_data[chi_data.meas_temp == t]
        this_t = this_t[this_t.meas_field_ac == b]
        plt.semilogx(this_t.meas_freq, 1e6 *
                     this_t.susc_chi_volume, label='%i' % (t)+' K')
        plt.legend()
        plt.xlabel('Frequency (Hz)')
        plt.ylabel('$\chi$ ($\mu$SI)')
        plt.title('B = '+'%7.2e' % (b) + ' T')

    if interactive:
        pmagplotlib.draw_figs(figs)
        ans = input(
            "enter s[a]ve to save files,  [return] to quit ")
        if ans == 'a':
            saved.extend(pmagplotlib.save_plots(figs, fnames))
        else:
            return True, []
    elif save_plots:
        saved.extend(pmagplotlib.save_plots(figs, fnames))

    return True, saved

Response: This function will convert a single measurement file into a single unique one and plot the data.


Instruction:
Can you tell what is the following Python 3 function doing
def quick_hyst(dir_path=".", meas_file="measurements.txt", save_plots=True,
               interactive=False, fmt="png", specimen="", verbose=True, n_plots=10,
               contribution=None):
    """
    makes specimen plots of hysteresis data

    Parameters
    ----------
    dir_path : str, default "."
        input directory
    meas_file : str, default "measurements.txt"
        name of MagIC measurement file
    save_plots : bool, default True
        save figures
    interactive : bool, default False
        if True, interactively plot and display
        (this is best used on the command line only)
    fmt : str, default "svg"
        format for figures, ["svg", "jpg", "pdf", "png"]
    specimen : str, default ""
        specific specimen to plot
    verbose : bool, default True
        if True, print more verbose output

    Returns
    ---------
    Tuple : (True or False indicating if conversion was sucessful, output file name(s) written)
    """

    if contribution is None:
        con = cb.Contribution(dir_path, read_tables=['measurements'],
                              custom_filenames={'measurements': meas_file})
    else:
        con = contribution
    # get as much name data as possible (used for naming plots)
    if 'measurements' not in con.tables:
        print("-W- No measurement file found")
        return False, []
    con.propagate_location_to_measurements()

    if 'measurements' not in con.tables:
        print(main.__doc__)
        print('bad file')
        return False, []
    meas_container = con.tables['measurements']
    #meas_df = meas_container.df

    #
    # initialize some variables
    # define figure numbers for hyst,deltaM,DdeltaM curves
    saved = []
    HystRecs = []
    HDD = {}
    HDD['hyst'] = 1
    pmagplotlib.plot_init(HDD['hyst'], 5, 5)
    #
    # get list of unique experiment names and specimen names
    #
    sids = []
    hyst_data = meas_container.get_records_for_code('LP-HYS')
    #experiment_names = hyst_data['experiment_name'].unique()
    if not len(hyst_data):
        print("-W- No hysteresis data found")
        return False, []
    if 'specimen' not in hyst_data.columns:
        print('-W- No specimen names in measurements data, cannot complete quick_hyst.py')
        return False, []
    sids = hyst_data['specimen'].unique()

    # if 'treat_temp' is provided, use that value, otherwise assume 300
    hyst_data['treat_temp'].where(
        hyst_data['treat_temp'].notnull(), '300', inplace=True)
    # start at first specimen, or at provided specimen ('-spc')
    k = 0
    if specimen:
        try:
            print(sids)
            k = list(sids).index(specimen)
        except ValueError:
            print('-W- No specimen named: {}.'.format(specimen))
            print('-W- Please provide a valid specimen name')
            return False, []
    intlist = ['magn_moment', 'magn_volume', 'magn_mass']

    if len(sids) > n_plots:
        sids = sids[:n_plots]

    while k < len(sids):
        locname, site, sample, synth = '', '', '', ''
        s = sids[k]
        if verbose:
            print(s, k + 1, 'out of ', len(sids))
        # B, M for hysteresis, Bdcd,Mdcd for irm-dcd data
        B, M = [], []
        # get all measurements for this specimen
        spec = hyst_data[hyst_data['specimen'] == s]
        # get names
        if 'location' in spec:
            locname = spec['location'].iloc[0]
        if 'site' in spec:
            site = spec['sample'].iloc[0]
        if 'sample' in spec:
            sample = spec['sample'].iloc[0]
        # get all records with non-blank values in any intlist column
        # find intensity data
        for int_column in intlist:
            if int_column in spec.columns:
                int_col = int_column
                break
        meas_data = spec[spec[int_column].notnull()]
        if len(meas_data) == 0:
            break
        #
        c = ['k-', 'b-', 'c-', 'g-', 'm-', 'r-', 'y-']
        cnum = 0
        Temps = []
        xlab, ylab, title = '', '', ''
        Temps = meas_data['treat_temp'].unique()
        for t in Temps:
            print('working on t: ', t)
            t_data = meas_data[meas_data['treat_temp'] == t]
            m = int_col
            B = t_data['meas_field_dc'].astype(float).values
            M = t_data[m].astype(float).values
            # now plot the hysteresis curve(s)
            #
            if len(B) > 0:
                B = np.array(B)
                M = np.array(M)
                if t == Temps[-1]:
                    xlab = 'Field (T)'
                    ylab = m
                    title = 'Hysteresis: ' + s
                if t == Temps[0]:
                    pmagplotlib.clearFIG(HDD['hyst'])
                pmagplotlib.plot_xy(
                    HDD['hyst'], B, M, sym=c[cnum], xlab=xlab, ylab=ylab, title=title)
                pmagplotlib.plot_xy(HDD['hyst'], [
                                    1.1*B.min(), 1.1*B.max()], [0, 0], sym='k-', xlab=xlab, ylab=ylab, title=title)
                pmagplotlib.plot_xy(HDD['hyst'], [0, 0], [
                                    1.1*M.min(), 1.1*M.max()], sym='k-', xlab=xlab, ylab=ylab, title=title)
                if not save_plots and not set_env.IS_WIN:
                    pmagplotlib.draw_figs(HDD)
                cnum += 1
                if cnum == len(c):
                    cnum = 0
  #
        files = {}
        if save_plots:
            if specimen != "":
                s = specimen
            for key in list(HDD.keys()):
                if pmagplotlib.isServer:
                    if synth == '':
                        files[key] = "LO:_"+locname+'_SI:_'+site + \
                            '_SA:_'+sample+'_SP:_'+s+'_TY:_'+key+'_.'+fmt
                    else:
                        files[key] = 'SY:_'+synth+'_TY:_'+key+'_.'+fmt
                else:
                    if synth == '':
                        filename = ''
                        for item in [locname, site, sample, s, key]:
                            if item:
                                item = item.replace(' ', '_')
                                filename += item + '_'
                        if filename.endswith('_'):
                            filename = filename[:-1]
                        filename += ".{}".format(fmt)
                        files[key] = filename
                    else:
                        files[key] = "{}_{}.{}".format(synth, key, fmt)

            pmagplotlib.save_plots(HDD, files)
            saved.extend([value for value in files.values()])
            if specimen:
                return True, saved
        if interactive:
            pmagplotlib.draw_figs(HDD)
            ans = input(
                "S[a]ve plots, [s]pecimen name, [q]uit, <return> to continue\n ")
            if ans == "a":
                files = {}
                for key in list(HDD.keys()):
                    if pmagplotlib.isServer:  # use server plot naming convention
                        locname = locname if locname else ""
                        site = site if site else ""
                        sample = sample if sample else ""
                        files[key] = "LO:_"+locname+'_SI:_'+site + \
                            '_SA:_'+sample+'_SP:_'+s+'_TY:_'+key+'_.'+fmt
                    else:  # use more readable plot naming convention
                        filename = ''
                        for item in [locname, site, sample, s, key]:
                            if item:
                                item = item.replace(' ', '_')
                                filename += item + '_'
                        if filename.endswith('_'):
                            filename = filename[:-1]
                        filename += ".{}".format(fmt)
                        files[key] = filename

                pmagplotlib.save_plots(HDD, files)
                saved.extend([value for value in files.values()])
            if ans == '':
                k += 1
            if ans == "p":
                del HystRecs[-1]
                k -= 1
            if ans == 'q':
                print("Good bye")
                return True, []
            if ans == 's':
                keepon = 1
                specimen = input(
                    'Enter desired specimen name (or first part there of): ')
                while keepon == 1:
                    try:
                        k = list(sids).index(specimen)
                        keepon = 0
                    except ValueError:
                        tmplist = []
                        for qq in range(len(sids)):
                            if specimen in sids[qq]:
                                tmplist.append(sids[qq])
                        print(specimen, " not found, but this was: ")
                        print(tmplist)
                        specimen = input('Select one or try again\n ')
                        k = list(sids).index(specimen)
        else:
            k += 1
        if not len(B):
            if verbose:
                print('skipping this one - no hysteresis data')
            k += 1
    return True, saved

Response: This function will take a directory path and a measurement file and plot the hysteresis data.